/*
 *  ex_file_slice - Use slices to pack many objects into a single file.
 *
 *  This example packs two strings into a single file, and then uses a
 *  file slice to open them one at a time. While this usage is contrived,
 *  the same principle can be used to pack multiple images (for example)
 *  into a single file, and later read them back via Allegro's image loader. 
 *
 */
#include "allegro5/allegro.h"

#include "common.c"

#define BUFFER_SIZE 1024

static void pack_object(ALLEGRO_FILE *file, const void *object, size_t len)
{
   /* First write the length of the object, so we know how big to make
      the slice when it is opened later. */      
   al_fwrite32le(file, len);
   al_fwrite(file, object, len);
}

static ALLEGRO_FILE *get_next_chunk(ALLEGRO_FILE *file)
{
   /* Reads the length of the next chunk, and if not at end of file, returns a 
      slice that represents that portion of the file. */ 
   const uint32_t length = al_fread32le(file);
   return !al_feof(file) ? al_fopen_slice(file, length, "rw") : NULL;
}

int main(int argc, const char *argv[])
{
   ALLEGRO_FILE *master, *slice;
   ALLEGRO_PATH *tmp_path;

   const char *first_string = "Hello, World!";
   const char *second_string = "The quick brown fox jumps over the lazy dog.";
   char buffer[BUFFER_SIZE];

   (void) argc, (void) argv;

   if (!al_init()) {
      abort_example("Could not init Allegro.\n");
   }

   open_log();

   master = al_make_temp_file("ex_file_slice_XXXX", &tmp_path);
   if (!master) {
      abort_example("Unable to create temporary file\n");
   }

   /* Pack both strings into the master file. */
   pack_object(master, first_string, strlen(first_string));
   pack_object(master, second_string, strlen(second_string));

   /* Seek back to the beginning of the file, as if we had just opened it */
   al_fseek(master, 0, ALLEGRO_SEEK_SET);

   /* Loop through the main file, opening a slice for each object */
   while ((slice = get_next_chunk(master))) {
      /* Note: While the slice is open, we must avoid using the master file!
         If you were dealing with packed images, this is where you would pass 'slice'
         to al_load_bitmap_f(). */

      if (al_fsize(slice) < BUFFER_SIZE) {
         /* We could have used al_fgets(), but just to show that the file slice
            is constrained to the string object, we'll read the entire slice. */
         al_fread(slice, buffer, al_fsize(slice));
         buffer[al_fsize(slice)] = 0;
         log_printf("Chunk of size %d: '%s'\n", (int) al_fsize(slice), buffer);
      }

      /* The slice must be closed before the next slice is opened. Closing
         the slice will advanced the master file to the end of the slice. */
      al_fclose(slice);
   }

   al_fclose(master);

   al_remove_filename(al_path_cstr(tmp_path, '/'));

   close_log(true);

   return 0;
}
