beginnings of binaryout
authorJordan <jordanlavatai@gmail.com>
Wed, 15 Feb 2017 04:32:36 +0000 (20:32 -0800)
committerJordan <jordanlavatai@gmail.com>
Wed, 15 Feb 2017 04:32:36 +0000 (20:32 -0800)
src/apc.h
src/binaryout.c [new file with mode: 0644]
src/ir.c
src/ir.h
src/pagenode.h [new file with mode: 0644]

index 348712c..9649c24 100644 (file)
--- a/src/apc.h
+++ b/src/apc.h
@@ -5,6 +5,8 @@
 enum frame_facing { SFACE, SWFACE, WFACE, NWFACE, NFACE, NEFACE, EFACE, SEFACE, FACING_MAX };
 typedef enum frame_facing apc_facing;
 
+
 #define APC_NAME_MAX 64
 
 #endif //_APC_H_
diff --git a/src/binaryout.c b/src/binaryout.c
new file mode 100644 (file)
index 0000000..ee82c6f
--- /dev/null
@@ -0,0 +1,833 @@
+/* Standard */
+#include <stdlib.h> //exit, malloc
+#include <stdio.h>  //print
+#include <stdarg.h> //va_args
+#include <string.h> //memset, str*
+#include <errno.h>
+/* Unicode */
+#include <unistd.h>   //u8_* functions
+#include <unitypes.h> //uint8_t as a char
+#include <unistr.h>   //u32_cpy
+#include <unistdio.h> //ulc_fprintf
+/* Local */
+#include "print.h"
+#include "apc.h"
+#include "ir.h"
+#include "pagenode.h"
+#undef  do_error
+#define do_error(...) exit(-1)
+#define XXH_PRIVATE_API
+#include "../xxHash/xxhash.h"
+#define STB_IMAGE_IMPLEMENTATION
+#include "stb_image.h"
+
+/* Public */
+void ir_binout_init(struct ir_class_t*);
+
+/* Memory Allocation */
+#define  struct_alloc(_T) ((struct _T*) stack_alloc(&datapages, sizeof(struct _T)))
+static
+struct pagelist_t linkpages, datapages;
+
+enum model_type { SS };
+/* Binaryout out structure definitions */
+struct bin_img_info_t {
+  int height;
+  int width;
+  int fwidth; //map and frame width
+  int fheight; //map and frame height
+  int unaligned_width;
+  int unaligned_height;
+};
+struct bin_ht_header_t {
+  long start;
+  int entries;
+};
+struct bin_ht_entry_t {
+  uint32_t key; 
+  long value;
+};
+struct bin_class_header_t {
+  struct bin_ht_header_t child_ht;
+  struct bin_ht_header_t rootset_ht;
+  int namelen;
+};
+struct bin_set_header_t {
+  struct bin_ht_header_t child_ht;
+  long sdat_start; //points to setdata_header
+  int namelen;
+};
+struct bin_setdata_header_t {
+  struct bin_ht_header_t variant_ht;
+  long attach_pos; 
+};
+struct bin_model_header_t { //one for each framebox, currently
+  long facing_array_start;
+  enum model_type type;
+};
+struct bin_frame_header_t {
+  int width;
+  int height;
+  int frames;
+  long op_start;
+};
+struct bin_plink_t {
+  enum ltype type;
+  ir_set trg_set;
+  uint8_t* name;
+  long src_pos; 
+};
+struct bin_pixel_t {
+  int x, y, z; 
+  uint32_t ref;
+};
+struct bin_pixel_node_t {
+  struct bin_pixel_node_t* next;
+  struct bin_pixel_t data;
+};
+struct bin_op_t {
+  int x;
+  int y;
+  int attach_idx;
+};
+struct bin_attachment_header_t {
+  int num_attachment_lists;
+  int num_attachments;
+};
+struct bin_attachment_t {
+  int idx;
+  ir_set set;
+};
+/* Read out of the als, after first ir pass, resolves the
+   attach_pos of the src-set that created the attachment_list
+   to the header that describes the attachment_list */
+struct bin_attachment_list_t {
+  int num_attachments;
+  struct bin_attachment_t** attachments;
+  long filepos;
+}; 
+
+struct bin_attachment_list_t **attachment_stack, **asp; //attachment_stack, attachment_stack_pointer
+FILE* binaryout;
+
+
+
+#define  NAMEHASH(name, domain) (XXH32(name, u8_strlen(name), 0XCEED ) & domain) 
+
+/* Given a position and a size, checks if the bytes are null and returns
+   the file position to where it started. 1 if not null, 0 if null*/
+/* TODO: Determine why fseeking file past end sets bytes to -1, and not 0 */
+static inline
+int bytes_null( int len, int pos )
+{ while(len--)
+    { if(fgetc(binaryout) > 0)
+       { fseek(binaryout, pos, SEEK_SET);        
+          return 1;
+       }
+    }
+  fseek(binaryout, pos, SEEK_SET);
+  return 0;
+}
+/* Checks if the key at entrypos is the same as the parameter key. Returns
+   1 if so, 0 if not. */
+static inline
+int bin_keys_identical
+( long entry_pos,
+  uint32_t key
+)
+{ uint32_t curr_key;
+  fseek(binaryout, entry_pos, SEEK_SET);
+  fscanf(binaryout, "%u", &curr_key);
+  if( curr_key == key)
+    return 1;
+  return 0;    
+}
+
+long bin_traverse_class(ir_class);
+/* Takes root class and begins processing */
+void
+ir_binout_init(ir_class root_class)
+{ binaryout = fopen("binaryout", "w+");
+  asp = attachment_stack;
+  pagelist_init(datapages, (size_t) SYS_PAGESIZE);
+  pagelist_init(linkpages, (size_t) SYS_PAGESIZE);
+  bin_traverse_class(root_class);
+}
+
+#define ENTRY_OCCUPIED() (bytes_null(sizeof(ht_entry->key), entry_pos))
+#define WRITE_ENTRY() do {                             \
+      if(fseek(binaryout, entry_pos, SEEK_SET) == -1) wprintf("fseek failed with %s", strerror(errno)); \
+      fwrite(&ht_entry, sizeof ht_entry, 1, binaryout);        \
+  } while (0)
+#define LOOP_ENTRY(_HTSTART) (entry_pos = _HTSTART)
+#define INC_ENTRY() do { \
+      entry_pos += sizeof(ht_entry);           \
+      if(fseek(binaryout, entry_pos, SEEK_SET) == -1) eprintf("fseek failed with %s", strerror(errno)); \
+  } while (0)
+#define HT_END(_HTEND) (entry_pos >= _HTEND) //just in case at last entry
+void
+/* TODO: Should overwrite be a default? */
+bin_insert_ht_entry
+( long ht_start,
+  long ht_size,
+  struct bin_ht_entry_t* ht_entry,
+  int overwrite
+)
+{ long entry_pos, ht_end;
+
+  ht_end = ht_start + ht_size; 
+  entry_pos = ht_start + sizeof(ht_entry) * ht_entry->key;
+  fseek(binaryout, entry_pos, SEEK_SET);
+  
+  if (!ENTRY_OCCUPIED())
+    { uprintf("key not occupied\n");
+      WRITE_ENTRY();
+    }
+  while( ENTRY_OCCUPIED() )
+    { if(overwrite)
+       { if(bin_keys_identical(entry_pos, ht_entry->key))
+           break;      
+         else 
+          { eprintf("error in hashtable insertion, keys are identical");
+          }
+       }
+      if (HT_END(ht_end))
+       LOOP_ENTRY(ht_start);
+      else 
+       INC_ENTRY();
+    }
+  WRITE_ENTRY();
+    
+}
+
+/* |     class header   |
+   |--------------------|
+   |     rootset ht     |
+   |--------------------|
+   |    rootsets data   |
+   |--------------------|
+   |    classchild ht   |
+   |--------------------|
+   |  classchild header |
+   |        ...         |
+*/
+
+long bin_traverse_set(ir_set);
+long
+#define HT_INIT(_START,  _SIZE, _INIT_ENTRIES) do {       \
+  _SIZE = _INIT_ENTRIES ? (_INIT_ENTRIES * (sizeof(struct bin_ht_entry_t) << 1)): 0; \
+  _START = ftell(binaryout); \
+  fseek(binaryout, _SIZE, SEEK_CUR); \
+} while (0)
+bin_traverse_class
+( ir_class class)
+{ ir_class citer;
+  ir_set siter;
+  struct bin_class_header_t class_header;
+  struct bin_ht_entry_t ht_entry;
+  long class_start, classht_start, classht_size, rootsetht_start, rootsetht_size;
+  int num_csibs, num_ssibs;
+  uint8_t* class_name;
+
+  class_start = ftell(binaryout);
+  class_name = get_class_name(class);
+
+  num_csibs = get_class_sibcount(class);
+  num_ssibs = get_set_sibcount(get_class_root_set(class));
+
+  /* alloc space (before hash tables) for class header */
+  class_header.namelen = u8_strlen(class_name);
+  fseek(binaryout, class_start + sizeof(class_header) + class_header.namelen ,SEEK_SET);
+  
+  HT_INIT(classht_start, classht_size, num_csibs);
+  HT_INIT(rootsetht_start, rootsetht_size, num_ssibs);
+  
+  /* TODO: Figure out generic way to output headers */
+  /* populate class header */
+  class_header.child_ht.entries = num_csibs;
+  class_header.child_ht.start = classht_start;
+  class_header.rootset_ht.entries = num_ssibs;
+  class_header.rootset_ht.start = rootsetht_start;
+  fseek(binaryout, class_start, SEEK_SET); //seek back to where we allocated header
+  fwrite(&class_header, sizeof(class_header), 1, binaryout);
+  fwrite(class_name, class_header.namelen, 1, binaryout);
+  /* Start populating root_set hash table */
+  for ( siter = get_class_root_set(class); siter != NULL; siter = get_set_nextsib(siter))
+    { fseek(binaryout, 0, SEEK_END);
+      ht_entry.key = NAMEHASH(get_set_name(siter), num_ssibs << 1);
+      ht_entry.value = bin_traverse_set(siter);
+      bin_insert_ht_entry(rootsetht_start, rootsetht_size, &ht_entry, 0);      
+    }
+
+  /* Start populating class child hash table */
+  for ( citer = get_class_nextchild(class); citer != NULL; citer = get_class_nextsib(citer))
+    { fseek(binaryout, 0, SEEK_END);
+      ht_entry.key = NAMEHASH(get_class_name(citer), num_csibs << 1);     
+      ht_entry.value = bin_traverse_class(citer);
+      bin_insert_ht_entry(classht_start, classht_size, &ht_entry, 0);
+    }
+
+  return class_start;
+}
+
+long bin_process_sdat( ir_set);
+
+/* |    set header   |--|
+   |-----------------|  |
+   |     set data    |<-|
+   |-----------------|  |
+---|   setchild ht   |<--
+|  |-----------------|
+|->| setchild header |
+|->|      ...        |
+*/
+
+long
+bin_traverse_set
+( ir_set set )
+{ ir_set iter;
+  struct bin_set_header_t header;
+  struct bin_ht_entry_t ht_entry;
+  int num_child, setname_len;
+  long childht_start, childht_size, set_start;
+  uint8_t* set_name;
+
+  set_start = ftell(binaryout);
+  set_name = get_set_name(set);
+  
+  /* alloc space for set header */
+  setname_len = u8_strlen(set_name);
+  fseek(binaryout, sizeof(struct bin_set_header_t) + setname_len , SEEK_CUR);
+
+  /* process the set data */
+  header.sdat_start = bin_process_sdat(set);
+
+  /* Setup child hash table for current sets children */
+  num_child = get_set_sibcount(get_set_nextchild(set));
+  HT_INIT(childht_start, childht_size, num_child);
+
+  /* populate header, write to file */
+  header.child_ht.entries = num_child;
+  header.child_ht.start = childht_start;
+  fseek(binaryout, set_start, SEEK_SET);
+  fwrite(&header, sizeof(struct bin_set_header_t), 1, binaryout);
+  fwrite(set_name, setname_len, 1, binaryout);
+
+  for(iter = get_set_nextchild(set); iter != NULL; iter = get_set_nextsib(iter))
+    { fseek(binaryout, 0, SEEK_END);
+      ht_entry.key = NAMEHASH(get_set_name(iter), num_child << 1);
+      ht_entry.value = bin_traverse_set(iter);
+      bin_insert_ht_entry(childht_start, childht_size, &ht_entry, 0);      
+    }
+  
+
+  set_set_filepos(set, set_start);
+  return set_start;
+  
+}
+/* |   sdat header    |
+   |------------------|
+   |    variant ht    |
+   |------------------|
+   | 1st variant data | -- variant == framebox
+   |------------------|
+   | 2nd variant data |
+   |------------------|
+   |       etc.       |
+*/
+
+void bin_insert_links(int, struct bin_ht_header_t*, long);
+struct bin_pixel_node_t* bin_find_default_pixel_list(ir_set);
+void bin_process_frameboxes(ir_set, struct bin_ht_header_t*, struct bin_pixel_node_t*);
+int bin_process_links(ir_set, ir_setdata);
+
+/* Init the variant hash table for the set, process the sets links and add them to link_stack
+   and variant hash table, and then output the actual framedata */
+long
+bin_process_sdat
+( ir_set set )
+{ struct bin_setdata_header_t header;
+  struct bin_attachment_list_t attachment_list;
+  struct bin_pixel_node_t *default_pixel_list;
+  struct bin_ht_header_t ht_header;
+  long varht_start, varht_size, sdat_start;
+  int num_entries, num_links;
+  ir_setdata olink_head;
+
+  sdat_start = ftell(binaryout);
+  /* Alloc position for sdat_header */
+  fseek(binaryout, sizeof(struct bin_setdata_header_t), SEEK_CUR);
+
+  num_links = bin_process_links(set, olink_head);
+  num_entries = get_set_variants(set) + num_links;
+  
+  HT_INIT(varht_start, varht_size, num_entries);
+
+  /* Populate the sdat_header */
+  fseek(binaryout, 0, sdat_start);
+  header.variant_ht.start = ht_header.start = varht_start;
+  header.variant_ht.entries = ht_header.entries = num_entries;
+  attachment_list.filepos = header.attach_pos = ftell(binaryout) + sizeof(varht_start) + sizeof(num_entries);
+  fwrite(&header, sizeof(header), 1, binaryout);
+  fseek(binaryout, 0, SEEK_END);
+
+  /* insert the links that were processed into the variant hash table */
+  bin_insert_links(num_links, &ht_header, attachment_list.filepos);
+  /* Determine the default pixel list for all of the frameboxes */
+  default_pixel_list = bin_find_default_pixel_list(set);
+  /* Output each framebox, and insert it into the variant hash table */
+  bin_process_frameboxes(set, &ht_header, default_pixel_list);
+
+  /* TODO: Convert the default pixel list to an attachment_list and then push the  */
+  /*       sdats attachment_list onto the attachment_stack so it can be procesed   */
+
+
+  return sdat_start;
+}
+
+
+/* Adds a vlink onto the stack_alloc to be popped during the processing of the
+   sets variant hash table. If the vlink has a name, its a vlink to a single
+   variant. if the vlink doesnt have a name, its the vlink to an entire variant
+   hash table, and each variant (framebox) needs to be added */
+int
+bin_process_vlink
+( ir_setdata vlink,
+  ir_set trg_set
+)
+{ struct bin_plink_t* plp;
+  ir_setdata fiter;
+  uint8_t* link_name;
+  int num_links;
+
+  num_links = 0;
+
+  /* TODO: Macroize? or not worth? */
+  link_name = get_link_name(vlink);
+  
+  if (link_name)
+    { plp = struct_alloc(bin_plink_t);
+      plp->src_pos = 0; // TBD @ process_setdata
+      plp->name = link_name;
+      plp->trg_set = trg_set;
+      plp->type = VLINK;
+      num_links++;
+    }
+  else // linking a variant hash table
+    for (fiter = get_set_frameboxes(trg_set); fiter != NULL; fiter = get_framebox_nextsib(fiter))
+      { plp = struct_alloc(bin_plink_t);
+       plp->src_pos = 0; // TBD @ process_setdata
+       plp->name = get_framebox_name(fiter);
+       plp->trg_set = trg_set;
+       plp->type = VLINK;
+       num_links++;
+      }
+
+  return num_links;
+
+}
+
+/* Adds an mlink to the stack_alloc, to be processed later */
+int
+bin_process_mlink
+( ir_setdata mlink,
+  ir_set trg_set
+)
+{ struct bin_plink_t* plp;
+  uint8_t* mlink_name;
+  mlink_name = get_link_name(mlink);
+  plp = struct_alloc(bin_plink_t);
+  plp->src_pos = 0; //TBD after resolving the childlist | TODO: attach_pos?
+  if(mlink_name) plp->name = mlink_name;
+  plp->trg_set = trg_set;
+  plp->type = MLINK;
+
+  return 1;
+}
+
+/* TODO: implement this */
+/* Determine if olink is already part of the olink_list. 
+   if it is, theres a cycle, return 1. Else return 0. */
+static inline
+int olink_cycle
+( ir_setdata olink,
+  ir_setdata olink_head )
+{ ir_setdata iter;
+
+  
+
+  return 0;
+
+}
+
+/* Given a set, determine the number of links it has and process each link and 
+   then add them to stack_alloc, where they will be popped off and further processed. */
+int
+bin_process_links
+( ir_set src_set,
+  ir_setdata olink_head
+)
+{ int num_links;
+  ir_setdata liter; //link iter
+  ir_set trg_set;
+
+  num_links = 0;
+  
+  for(liter = get_set_links(src_set); liter != NULL; liter = get_link_nextsib(liter))
+    { trg_set = get_set_from_ref(get_link_ref(liter));
+      switch (get_link_type(liter)) {
+      case OLINK:
+       if (olink_cycle(liter, olink_head)) //TODO: stack of olinks to iterate and check for cycles? 
+         return num_links;
+        num_links += bin_process_vlink(liter, trg_set);
+       num_links += bin_process_mlink(liter, trg_set);
+       num_links += bin_process_links(trg_set, liter);
+       break;
+      case VLINK:
+       num_links += bin_process_vlink(liter, trg_set);
+       break;
+      case MLINK:
+        num_links += bin_process_mlink(liter, trg_set);
+       break;
+      case ALINK: //TODO: ?
+       break;
+      }      
+    }
+  return num_links;
+}
+
+/* Insert both mlinks and vlinks into the link stack, after determining their src_pos. Vlinks 
+   have an additional requirement of being added into the variant hash table */ 
+#define pop_linkp()      (*(struct bin_plink_t**) pagelist_pop(&datapages, sizeof(struct bin_plink_t*)))
+#define PUSH_PLINK(_LINK) (*(struct bin_plink_t**) stack_alloc(&linkpages, sizeof (_LINK)) = _LINK )
+void
+bin_insert_links
+( int num_links,
+  struct bin_ht_header_t* ht,
+  long attach_pos
+)
+{ struct bin_plink_t* plp;
+  struct bin_ht_entry_t ht_entry;
+  int i;
+  
+  /* Insert vlinks into hash table, put v/mlinks on link stack to be processed later */
+  for ( i = 0; i < num_links; i++)
+    { plp = pop_linkp();
+      switch (plp->type) {
+      case MLINK:
+       plp->trg_set = plp->trg_set;
+       plp->src_pos = attach_pos;
+       PUSH_PLINK(plp);
+       break;
+      case VLINK:
+       ht_entry.key = NAMEHASH(plp->name, ht->entries << 1);
+        ht_entry.value = 0;
+        bin_insert_ht_entry(ht->start, ht->entries * sizeof(ht_entry), &ht_entry, 0);     
+        plp->src_pos = ht_entry.key + sizeof(ht_entry.key);
+       PUSH_PLINK(plp);
+       break;
+      case OLINK:
+       break;
+       //shouldnt exist
+      case ALINK:
+       break;
+        //TBD
+      }
+    }
+}
+
+long bin_process_facing(ir_setdata, apc_facing, struct bin_pixel_node_t*);
+/* |-------------------|
+   |  framebox header  |
+   |-------------------|
+   | SFACE framesheet  | 
+   |-------------------|
+   | SWFACE framesheet |
+   |-------------------|
+   |       etc.        |
+*/   
+long
+bin_process_framebox
+( ir_set set,
+  ir_setdata framebox,
+  struct bin_pixel_node_t* default_pixel_list
+)
+{ struct bin_model_header_t header;
+  long framebox_start, index_pos;
+  int i;
+
+  framebox_start = ftell(binaryout);
+
+  /* insert model header */
+  header.type = SS;
+  header.facing_array_start = framebox_start + sizeof(header);
+  fwrite(&header, sizeof(header), 1, binaryout);
+
+  /* Create the index array for framesheet of each direction */
+  for ( i = SFACE; i < FACING_MAX; i++)
+    { fseek(binaryout, 0, SEEK_END);
+      index_pos = bin_process_facing(framebox, i, default_pixel_list); //TODO: finish process_direction
+      fseek(binaryout, header.facing_array_start + i * sizeof(long), SEEK_SET);
+      fwrite(&index_pos, sizeof(long), 1, binaryout);    
+    }
+  
+  return framebox_start;
+}
+void
+bin_process_frameboxes
+( ir_set set,
+  struct bin_ht_header_t* ht,
+  struct bin_pixel_node_t* default_pixel_list
+)
+{ struct bin_ht_entry_t ht_entry;
+  ir_setdata fiter;
+  
+  /* Insert variants into hash table to overwrite olink insertions*/
+  for ( fiter = get_set_frameboxes(set); fiter != NULL; fiter = get_framebox_nextsib(fiter))
+    { fseek(binaryout, 0, SEEK_END);
+      ht_entry.key = NAMEHASH(get_framebox_name(fiter), ht->entries << 1);  
+      ht_entry.value = bin_process_framebox(set, fiter, default_pixel_list);
+      bin_insert_ht_entry(ht->start, ht->entries * sizeof(ht_entry), &ht_entry, 1);     
+    }
+
+}
+/* Determine clipping based on image height/width and frame height/width */
+static inline
+void bin_set_img_info
+( struct bin_img_info_t* img_info,
+  ir_setdata framedata
+)
+{ img_info->fwidth = get_framedata_width(framedata);
+  img_info->fheight = get_framedata_height(framedata);
+  img_info->unaligned_height = img_info->height % img_info->fheight;
+  img_info->unaligned_width = img_info->width % img_info->fwidth;
+
+}
+
+/* TODO: Implement this */
+long
+bin_process_frame
+ ()
+{}
+
+
+
+/* Combine the framesheet and mapsheet to create
+   the output sheet */
+/* |-------------------------|
+   |  outputsheet header     |
+   |-------------------------|
+   |  pixel data for frame1  |
+   |-------------------------|
+   |  op data for frame1     |
+   |-------------------------| 
+   |         etc.            | */
+//TODO: processing direction sounds dumb, but cant call it process_framesheet because
+//      its actually the mapsheet and the framesheet. rename to output sheet?
+/* THIS FUNCTION IS NOT DONE */
+long
+bin_process_facing
+( ir_setdata framebox,
+  apc_facing facing,
+  struct bin_pixel_node_t* default_pixel_list
+)
+{ struct bin_img_info_t mapsheet_info, framesheet_info;
+  int num_mapchannels, num_framechannels;
+  long facing_start;
+  unsigned char* mapdata, * framedata;
+
+  facing_start = ftell(binaryout);
+
+  
+  /* Set up data pointers to mapsheet and framesheet, as well as their image infos */
+  mapdata = stbi_load(get_framedata_name(get_framebox_facing_mapdata(framebox,SFACE)), &mapsheet_info.width, &mapsheet_info.width, &num_framechannels , 0);
+  framedata = stbi_load(get_framedata_name(get_framebox_facing_framedata(framebox,SFACE)), &framesheet_info.width, &framesheet_info.height, &num_mapchannels, 0);
+  bin_set_img_info(&framesheet_info, get_framebox_facing_framedata(framebox, SFACE));
+  bin_set_img_info(&mapsheet_info, get_framebox_facing_mapdata(framebox, SFACE));
+
+  /* TODO: output framesheet/direction header */
+
+  
+  /* For each frame and map i in framesheet + mapsheet */
+    /* output frame data */
+    /* output op space for frames */
+    /* determine ops in map */
+    /* check if ops are acceptable */
+    /* output ops */
+  
+  return facing_start;
+  
+}
+
+
+
+
+
+/* Insert pixel(s) into the list, z sorted */
+void
+bin_insert_node_into_list
+( struct bin_pixel_node_t* pixel_list_root,
+  struct bin_pixel_node_t* pixel_node
+)
+{ struct bin_pixel_node_t* head_node, *prev_node;
+  int node_z;
+
+  head_node = pixel_list_root->next;
+  node_z = pixel_node->data.z;
+
+  if(head_node == NULL)
+    { head_node = pixel_node;
+    }
+  prev_node = pixel_list_root;
+  while(head_node != NULL)
+    { if(node_z > head_node->data.z)
+       { prev_node = head_node;
+         head_node = head_node->next;
+       }
+      else if (node_z < head_node->data.z || node_z == head_node->data.z)
+       { prev_node->next = pixel_node;
+         pixel_node->next = head_node;
+         break;
+       }
+    }
+
+
+}
+
+/* TODO: Finish this */
+struct bin_pixel_node_t*
+bin_process_pixel
+( unsigned char* data,
+  int x,
+  int y,
+  int init_height,
+  int init_width
+)
+{ struct bin_pixel_node_t* pixel_node;
+
+
+  pixel_node = struct_alloc(bin_pixel_node_t);
+
+  if(data)
+    { /* get ref from 4 bytes of data */
+      pixel_node->data.ref = (int) data;
+      /* bitshift by ? to get Z ordering */
+
+      /* set x and y */
+      pixel_node->data.x = x + init_width ;
+      pixel_node->data.y = y + init_width;
+      data += 4;
+    }
+  else
+    { data += 4; //TODO: does this correctly increment past 0x00000000?
+      return NULL;
+    }
+  
+  
+
+  return pixel_node;
+      
+}
+
+/* Returns the non null pixels of a single frame */
+/* TODO: Finish this */
+struct bin_pixel_node_t* 
+bin_map_to_pixel_list
+( struct bin_img_info_t* img_info,
+  int init_height,
+  int init_width,
+  unsigned char* data
+)
+{ int x, y;
+  struct bin_pixel_node_t* pixel_list, * pixel_node;
+
+  pixel_list = NULL;
+
+  /* Check if frame clips */
+  if( img_info->unaligned_width )
+    ;
+  if (img_info->unaligned_height )
+    ;
+  
+  /* Process the map*/
+  for (y = 0; y < img_info->fheight; y++)
+    { for ( x = 0; x < img_info->fwidth; x++ )
+        { pixel_node = bin_process_pixel(data, x, y, init_height, init_width);
+          bin_insert_node_into_list(pixel_list, pixel_node);
+        }
+    }
+
+  return pixel_node;   
+}
+
+static inline
+int bin_pixel_list_len
+( struct bin_pixel_node_t* pl )
+{ struct bin_pixel_node_t* plp;
+  int count;
+  count = 0;
+  plp = pl;
+  while(plp)
+    { count++;
+      plp = plp->next;
+    }    
+  return count;
+}
+
+struct bin_pixel_node_t* 
+bin_cmp_default_pixel_lists
+( struct bin_pixel_node_t* pl1,
+  struct bin_pixel_node_t* pl2
+)
+{ struct bin_pixel_node_t* pl1p, * pl2p;
+  int i, pl1_len, pl2_len;
+
+  pl1p = pl1;
+  pl2p = pl2;
+  pl1_len = bin_pixel_list_len(pl1);
+  pl2_len = bin_pixel_list_len(pl2);
+  
+  if (pl1_len > pl2_len)
+    return pl1;
+  else if (pl1_len < pl2_len)
+    return pl2;
+  /* pl1 == pl2, make sure that all refs are the same */
+  /* TODO: what type of warning/error handling should occur here? */
+  for (i = 0; i < pl1_len; i++)
+    { if (pl1p->data.ref != pl2p->data.ref)
+       eprintf("Error in determining default pixel list\n");
+      pl1p = pl1p->next;
+      pl2p = pl2p->next;
+    }
+  return pl1; //doesnt matter which one you return
+}
+
+/* Find default framebox, based on the framebox with the most attachments*/
+/* Search through first frame of S of each framebox */
+struct bin_pixel_node_t*
+bin_find_default_pixel_list
+( ir_set set)
+{ ir_setdata fiter;
+  struct bin_pixel_node_t* default_pixel_list, * curr_pixel_list;
+  unsigned char* data;
+  int num_channels;
+  struct bin_img_info_t img_info;
+  
+  for (fiter = get_set_frameboxes(set); fiter != NULL; fiter = get_framebox_nextsib(fiter))
+    { /* TODO: Stringify the frame name with .png? */
+      /* TODO: Add directory changing */
+      data = stbi_load(get_framedata_name(get_framebox_facing_mapdata(fiter, SFACE)), &img_info.width, &img_info.width, &num_channels, 0);
+      bin_set_img_info(&img_info, get_framebox_facing_mapdata(fiter, SFACE));
+      curr_pixel_list = bin_map_to_pixel_list(&img_info, 0, 0, data);
+      default_pixel_list = bin_cmp_default_pixel_lists(curr_pixel_list, default_pixel_list);
+
+      free(data);       
+    }
+
+  return default_pixel_list;
+}
index 6355654..3f90e18 100644 (file)
--- a/src/ir.c
+++ b/src/ir.c
@@ -10,6 +10,7 @@
 #include <stdarg.h> //va_args\r
 #include <stdint.h> //uint64_t\r
 #include <string.h> //memset, str*\r
+#include <errno.h>\r
 /* Unicode */\r
 #include <unistd.h>   //u8_* functions\r
 #include <unitypes.h> //uint8_t as a char\r
@@ -19,6 +20,7 @@
 #include "print.h"\r
 #include "apc.h"\r
 #include "ir.h"\r
+#include "pagenode.h"\r
 #undef  do_error\r
 #define do_error(...) exit(-1)\r
 #define XXH_PRIVATE_API\r
@@ -29,25 +31,6 @@ void     ir_quit(void);
 void     ir_test(void);\r
 int      ir_linker(void);\r
 int      ir_condenser(void);\r
-/* Memory allocation structures */\r
-struct pagenode_t;\r
-struct pagenode_header_t {\r
-  struct pagenode_t* next;\r
-  char*              head;\r
-};\r
-struct pagenode_t {\r
-  struct pagenode_header_t header;\r
-  char                     root[];\r
-};\r
-struct pagelist_t {\r
-  struct pagenode_t* root, * head;\r
-  size_t             pagesize;\r
-};\r
-#define SYS_PAGESIZE     (sys_pagesize)\r
-#define NAME_PAGESIZE    (APC_NAME_MAX * 1024)\r
-#define PL_HEADERSIZE    (sizeof(struct pagenode_header_t))\r
-#define PL_HEADSIZE(_PL) (_PL.head->header.head - _PL.head->root)\r
-#define PL_HEADMEM(_PL)  (_PL.pagesize - PL_HEADERSIZE - PL_HEADSIZE(_PL))\r
 /* Set data mem */\r
 enum dtype { FSDAT, MSDAT, ADAT, LDAT, FBDAT };\r
 struct ir_namelist_t;\r
@@ -107,6 +90,7 @@ struct ir_set_t
   struct ir_framebox_t* frameboxes;\r
   struct ir_simplex_t*  audio;\r
   struct ir_link_t*     links;\r
+  long filepos;\r
 };\r
 /* Functions */\r
 static inline\r
@@ -118,37 +102,12 @@ int      bytes_identical(const uint8_t*,const uint8_t*);
 static inline\r
 int      classnames_identical(const uint8_t*,const uint8_t*);\r
 static\r
-void*    stack_alloc(size_t);\r
-#define  struct_alloc(_T) ((struct _T*) stack_alloc(sizeof(struct _T)))\r
-#define  struct_clear(_S) (memset((_S), 0, sizeof(*(_S))))\r
-static\r
 uint8_t* name_alloc(const uint8_t*);\r
 static\r
 uint8_t* classname_alloc(const uint8_t*);\r
-static inline\r
-void*    pagelist_pop(struct pagelist_t*,size_t);\r
-#define $($)#$\r
-#define  pagelist_alloc(pagelist) do {                                 \\r
-    pagelist.head->header.next = (struct pagenode_t*) malloc(pagelist.pagesize); \\r
-    if (pagelist.head->header.next == NULL)                            \\r
-      eprintf("Memory allocation error\n");                            \\r
-    struct_clear(pagelist.head->header.next);                          \\r
-    pagelist.head = pagelist.head->header.next;                                \\r
-    pagelist.head->header.head = pagelist.head->root;                  \\r
-  } while (0)\r
-#define  pagelist_init(pagelist,size) do {                     \\r
-    pagelist.pagesize = size;                                  \\r
-    pagelist.root = (struct pagenode_t*) malloc(size);         \\r
-    if (pagelist.root == NULL)                                 \\r
-      eprintf("Memory allocation error\n");                    \\r
-    struct_clear(pagelist.root);                               \\r
-    pagelist.head = pagelist.root;                             \\r
-    pagelist.head->header.head = pagelist.head->root;          \\r
-  } while (0)\r
-static\r
-void     pagenode_free(struct pagenode_t*);\r
+#define  struct_clear(_S) (memset((_S), 0, sizeof(*(_S))))\r
 #define  REFHASH(ref) (XXH32(&ref, sizeof(uint32_t), 0xCEED) & 0xCFF)\r
-\r
+#define  struct_alloc(_T) ((struct _T*) stack_alloc(&datapages, sizeof(struct _T)))\r
 extern //apc.c\r
 long     sys_pagesize;\r
 static\r
@@ -162,6 +121,7 @@ int ir_init
 { pagelist_init(datapages, (size_t)SYS_PAGESIZE);\r
   pagelist_init(namepages, (size_t)NAME_PAGESIZE);\r
   pagelist_init(refhashpages, (size_t)SYS_PAGESIZE);\r
+\r
   return 0;\r
 }\r
 \r
@@ -171,15 +131,7 @@ void ir_quit
 { pagenode_free(datapages.root);\r
   pagenode_free(namepages.root);\r
   pagenode_free(refhashpages.root);\r
-}\r
 \r
-/* Recursively clean pagenode linked list, freeing last first */\r
-static\r
-void pagenode_free\r
-( struct pagenode_t* pagenode )\r
-{ if (pagenode->header.next != NULL)\r
-    pagenode_free(pagenode->header.next);\r
-  free(pagenode);\r
 }\r
 \r
 /* Link */\r
@@ -594,34 +546,6 @@ union ir_setdata_t* ir_link
   return (union ir_setdata_t*) link;\r
 }\r
 \r
-static inline\r
-void* pagelist_pop\r
-( struct pagelist_t* pagelist,\r
-  size_t             size\r
-)\r
-{ size_t headsize = PL_HEADSIZE((*pagelist));\r
-  if (!headsize)\r
-    { free(pagelist->head);\r
-      pagelist->head = pagelist->root;\r
-      while (pagelist->head->header.next != NULL)\r
-       pagelist->head = pagelist->head->header.next;\r
-    }\r
-  if (headsize < size)\r
-    eprintf("Attempted to pop unaligned value from pagelist\n");\r
-  pagelist->head->header.head -= size;\r
-  return pagelist->head->header.head;\r
-}\r
-\r
-static\r
-void* stack_alloc\r
-( size_t bytes )\r
-{ void* p;\r
-  if (PL_HEADMEM(datapages) < bytes) \r
-    pagelist_alloc(datapages);\r
-  p = datapages.head->header.head;\r
-  datapages.head->header.head += bytes;\r
-  return p;\r
-}\r
 \r
 static\r
 uint8_t* name_alloc\r
@@ -663,19 +587,23 @@ uint8_t* classname_alloc
 \r
 static void crawl_class(struct ir_class_t*);\r
 static void crawl_set(struct ir_set_t*,int);\r
+\r
 void     ir_test(void)\r
 { uprintf("IR From Directory: %s\n",getcwd(NULL,255));\r
   crawl_class(&root_class);\r
   if (root_class.root_set != NULL)\r
     crawl_set(root_class.root_set, 0);\r
+  uprintf("starting binaryout \n");\r
+  ir_binout_init(&root_class);\r
 }\r
 \r
+\r
 static\r
 void crawl_class\r
 ( struct ir_class_t* class )\r
 { struct ir_class_t* iter;\r
   for (iter = class->nextchild; iter != NULL; iter = iter->nextsib)\r
-    { wprintf("%U/\n", iter->name);\r
+    { wprintf("Crawling class %U/\n", iter->name);\r
       if(chdir((char*)iter->name))\r
        eprintf("CHDIR %U from %s\n",iter->name,getcwd(NULL,255));\r
       crawl_class(iter);\r
@@ -683,11 +611,12 @@ void crawl_class
         crawl_set(iter->root_set, 0);\r
       uprintf("%U\\\n",iter->name);\r
       if (chdir(".."))\r
-       eprintf("CHDIR ..\n");\r
+       eprintf("CHDIR ..\n");\r
+      wprintf("Finished crawling class %U/\n", iter->name);\r
     }\r
 }\r
 \r
-#define push_setp(setp) (*(struct ir_set_t**)stack_alloc(sizeof(struct ir_set_t*)) = setp)\r
+#define push_setp(setp) (*(struct ir_set_t**)stack_alloc(&datapages, sizeof(struct ir_set_t*)) = setp)\r
 #define pop_setp()      (*(struct ir_set_t**)pagelist_pop(&datapages, sizeof(struct ir_set_t*)))\r
 static\r
 void crawl_set\r
@@ -700,11 +629,13 @@ void crawl_set
   while (i--)\r
     putchar('.');\r
   i = depth;\r
+\r
   for(iter = set; iter != NULL; iter = iter->nextchild)\r
     { uprintf("[%10U]", iter->name);\r
       push_setp(iter);\r
       i++;\r
     }\r
+\r
   putchar('\n');\r
   while (--i >= depth)\r
     if (((iter = pop_setp())->nextsib) != NULL)\r
index 68fcde2..096c760 100644 (file)
--- a/src/ir.h
+++ b/src/ir.h
@@ -86,3 +86,30 @@ ir_setld   ir_setld_from_ref(uint32_t);
 ir_setld   ir_setld_from_classld(ir_classld,const uint8_t*);\r
 ir_setld   ir_setld_addchild(ir_setld,const uint8_t*);\r
 #endif //_IR_H_\r
+\r
+int get_class_sibcount(ir_class);\r
+int get_set_sibcount(ir_set);\r
+int get_set_variants(ir_set);\r
+ir_set get_class_root_set(ir_class);\r
+ir_set get_set_nextsib(ir_set);\r
+ir_set get_set_nextchild(ir_set);\r
+ir_setdata get_set_frameboxes(ir_set);\r
+ir_setdata get_set_links(ir_set);\r
+uint8_t* get_set_name(ir_set);\r
+long get_set_filepos(ir_set);\r
+void set_set_filepos(ir_set, long);\r
+ir_set get_set_from_ref(uint32_t);\r
+ir_class get_class_nextchild(ir_class);\r
+ir_class get_class_nextsib(ir_class);\r
+uint8_t* get_class_name(ir_class);\r
+uint8_t* get_link_name(ir_setdata);\r
+ir_setdata get_link_nextsib(ir_setdata);\r
+uint32_t get_link_ref(ir_setdata);\r
+enum ltype get_link_type(ir_setdata);\r
+ir_setdata get_framebox_nextsib(ir_setdata);\r
+uint8_t* get_framebox_name(ir_setdata);\r
+ir_setdata get_framebox_facing_framedata(ir_setdata, apc_facing);\r
+ir_setdata get_framebox_facing_mapdata(ir_setdata, apc_facing);\r
+int get_framedata_height(ir_setdata);\r
+int get_framedata_width(ir_setdata);\r
+uint8_t* get_framedata_name(ir_setdata);\r
diff --git a/src/pagenode.h b/src/pagenode.h
new file mode 100644 (file)
index 0000000..8497f81
--- /dev/null
@@ -0,0 +1,88 @@
+#include <stdlib.h> //malloc
+
+extern //apc.c
+long sys_pagesize;
+
+#define SYS_PAGESIZE     (sys_pagesize)
+#define NAME_PAGESIZE    (APC_NAME_MAX * 1024)
+#define PL_HEADERSIZE    (sizeof(struct pagenode_header_t))
+#define PL_HEADSIZE(_PL) (_PL.head->header.head - _PL.head->root)
+#define PL_HEADMEM(_PL)  (_PL.pagesize - PL_HEADERSIZE - PL_HEADSIZE(_PL))
+#define  struct_clear(_S) (memset((_S), 0, sizeof(*(_S))))
+/* Memory allocation structures */
+struct pagenode_t;
+struct pagenode_header_t {
+  struct pagenode_t* next;
+  char*              head;
+};
+struct pagenode_t {
+  struct pagenode_header_t header;
+  char                     root[];
+};
+struct pagelist_t {
+  struct pagenode_t* root, * head;
+  size_t             pagesize;
+};
+
+static
+void*    stack_alloc(struct pagelist_t*, size_t);
+static inline
+void*    pagelist_pop(struct pagelist_t*,size_t);
+#define $($)#$
+#define  pagelist_alloc(pagelist) do {                                 \
+    pagelist.head->header.next = (struct pagenode_t*) malloc(pagelist.pagesize); \
+    if (pagelist.head->header.next == NULL)                            \
+      eprintf("Memory allocation error\n");                            \
+    struct_clear(pagelist.head->header.next);                          \
+    pagelist.head = pagelist.head->header.next;                                \
+    pagelist.head->header.head = pagelist.head->root;                  \
+  } while (0)
+#define  pagelist_init(pagelist,size) do {                     \
+    pagelist.pagesize = size;                                  \
+    pagelist.root = (struct pagenode_t*) malloc(size);         \
+    if (pagelist.root == NULL)                                 \
+      eprintf("Memory allocation error\n");                    \
+    struct_clear(pagelist.root);                               \
+    pagelist.head = pagelist.root;                             \
+    pagelist.head->header.head = pagelist.head->root;          \
+  } while (0)
+static
+void     pagenode_free(struct pagenode_t*);
+
+static inline
+void* pagelist_pop
+( struct pagelist_t* pagelist,
+  size_t             size
+)
+{ size_t headsize = PL_HEADSIZE((*pagelist));
+  if (!headsize)
+    { free(pagelist->head);
+      pagelist->head = pagelist->root;
+      while (pagelist->head->header.next != NULL)
+       pagelist->head = pagelist->head->header.next;
+    }
+  if (headsize < size)
+    eprintf("Attempted to pop unaligned value from pagelist\n");
+  pagelist->head->header.head -= size;
+  return pagelist->head->header.head;
+}
+
+/* Recursively clean pagenode linked list, freeing last first */
+static
+void pagenode_free
+( struct pagenode_t* pagenode )
+{ if (pagenode->header.next != NULL)
+    pagenode_free(pagenode->header.next);
+  free(pagenode);
+}
+static
+void* stack_alloc
+( struct pagelist_t* pagelist,
+  size_t bytes )
+{ void* p;
+  if (PL_HEADMEM((*pagelist)) < bytes) 
+    pagelist_alloc((*pagelist));
+  p = pagelist->head->header.head;
+  pagelist->head->header.head += bytes;
+  return p;
+}