From db01318a8e246249ceea23255a6512ea8a5c00c2 Mon Sep 17 00:00:00 2001 From: Jordan Date: Tue, 14 Feb 2017 20:32:36 -0800 Subject: [PATCH] beginnings of binaryout --- src/apc.h | 2 + src/binaryout.c | 833 ++++++++++++++++++++++++++++++++++++++++++++++++ src/ir.c | 101 +----- src/ir.h | 27 ++ src/pagenode.h | 88 +++++ 5 files changed, 966 insertions(+), 85 deletions(-) create mode 100644 src/binaryout.c create mode 100644 src/pagenode.h diff --git a/src/apc.h b/src/apc.h index 348712c..9649c24 100644 --- 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 index 0000000..ee82c6f --- /dev/null +++ b/src/binaryout.c @@ -0,0 +1,833 @@ +/* Standard */ +#include //exit, malloc +#include //print +#include //va_args +#include //memset, str* +#include +/* Unicode */ +#include //u8_* functions +#include //uint8_t as a char +#include //u32_cpy +#include //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; +} diff --git a/src/ir.c b/src/ir.c index 6355654..3f90e18 100644 --- a/src/ir.c +++ b/src/ir.c @@ -10,6 +10,7 @@ #include //va_args #include //uint64_t #include //memset, str* +#include /* Unicode */ #include //u8_* functions #include //uint8_t as a char @@ -19,6 +20,7 @@ #include "print.h" #include "apc.h" #include "ir.h" +#include "pagenode.h" #undef do_error #define do_error(...) exit(-1) #define XXH_PRIVATE_API @@ -29,25 +31,6 @@ void ir_quit(void); void ir_test(void); int ir_linker(void); int ir_condenser(void); -/* 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; -}; -#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)) /* Set data mem */ enum dtype { FSDAT, MSDAT, ADAT, LDAT, FBDAT }; struct ir_namelist_t; @@ -107,6 +90,7 @@ struct ir_set_t struct ir_framebox_t* frameboxes; struct ir_simplex_t* audio; struct ir_link_t* links; + long filepos; }; /* Functions */ static inline @@ -118,37 +102,12 @@ int bytes_identical(const uint8_t*,const uint8_t*); static inline int classnames_identical(const uint8_t*,const uint8_t*); static -void* stack_alloc(size_t); -#define struct_alloc(_T) ((struct _T*) stack_alloc(sizeof(struct _T))) -#define struct_clear(_S) (memset((_S), 0, sizeof(*(_S)))) -static uint8_t* name_alloc(const uint8_t*); static uint8_t* classname_alloc(const uint8_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*); +#define struct_clear(_S) (memset((_S), 0, sizeof(*(_S)))) #define REFHASH(ref) (XXH32(&ref, sizeof(uint32_t), 0xCEED) & 0xCFF) - +#define struct_alloc(_T) ((struct _T*) stack_alloc(&datapages, sizeof(struct _T))) extern //apc.c long sys_pagesize; static @@ -162,6 +121,7 @@ int ir_init { pagelist_init(datapages, (size_t)SYS_PAGESIZE); pagelist_init(namepages, (size_t)NAME_PAGESIZE); pagelist_init(refhashpages, (size_t)SYS_PAGESIZE); + return 0; } @@ -171,15 +131,7 @@ void ir_quit { pagenode_free(datapages.root); pagenode_free(namepages.root); pagenode_free(refhashpages.root); -} -/* 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); } /* Link */ @@ -594,34 +546,6 @@ union ir_setdata_t* ir_link return (union ir_setdata_t*) link; } -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; -} - -static -void* stack_alloc -( size_t bytes ) -{ void* p; - if (PL_HEADMEM(datapages) < bytes) - pagelist_alloc(datapages); - p = datapages.head->header.head; - datapages.head->header.head += bytes; - return p; -} static uint8_t* name_alloc @@ -663,19 +587,23 @@ uint8_t* classname_alloc static void crawl_class(struct ir_class_t*); static void crawl_set(struct ir_set_t*,int); + void ir_test(void) { uprintf("IR From Directory: %s\n",getcwd(NULL,255)); crawl_class(&root_class); if (root_class.root_set != NULL) crawl_set(root_class.root_set, 0); + uprintf("starting binaryout \n"); + ir_binout_init(&root_class); } + static void crawl_class ( struct ir_class_t* class ) { struct ir_class_t* iter; for (iter = class->nextchild; iter != NULL; iter = iter->nextsib) - { wprintf("%U/\n", iter->name); + { wprintf("Crawling class %U/\n", iter->name); if(chdir((char*)iter->name)) eprintf("CHDIR %U from %s\n",iter->name,getcwd(NULL,255)); crawl_class(iter); @@ -683,11 +611,12 @@ void crawl_class crawl_set(iter->root_set, 0); uprintf("%U\\\n",iter->name); if (chdir("..")) - eprintf("CHDIR ..\n"); + eprintf("CHDIR ..\n"); + wprintf("Finished crawling class %U/\n", iter->name); } } -#define push_setp(setp) (*(struct ir_set_t**)stack_alloc(sizeof(struct ir_set_t*)) = setp) +#define push_setp(setp) (*(struct ir_set_t**)stack_alloc(&datapages, sizeof(struct ir_set_t*)) = setp) #define pop_setp() (*(struct ir_set_t**)pagelist_pop(&datapages, sizeof(struct ir_set_t*))) static void crawl_set @@ -700,11 +629,13 @@ void crawl_set while (i--) putchar('.'); i = depth; + for(iter = set; iter != NULL; iter = iter->nextchild) { uprintf("[%10U]", iter->name); push_setp(iter); i++; } + putchar('\n'); while (--i >= depth) if (((iter = pop_setp())->nextsib) != NULL) diff --git a/src/ir.h b/src/ir.h index 68fcde2..096c760 100644 --- 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*); ir_setld ir_setld_addchild(ir_setld,const uint8_t*); #endif //_IR_H_ + +int get_class_sibcount(ir_class); +int get_set_sibcount(ir_set); +int get_set_variants(ir_set); +ir_set get_class_root_set(ir_class); +ir_set get_set_nextsib(ir_set); +ir_set get_set_nextchild(ir_set); +ir_setdata get_set_frameboxes(ir_set); +ir_setdata get_set_links(ir_set); +uint8_t* get_set_name(ir_set); +long get_set_filepos(ir_set); +void set_set_filepos(ir_set, long); +ir_set get_set_from_ref(uint32_t); +ir_class get_class_nextchild(ir_class); +ir_class get_class_nextsib(ir_class); +uint8_t* get_class_name(ir_class); +uint8_t* get_link_name(ir_setdata); +ir_setdata get_link_nextsib(ir_setdata); +uint32_t get_link_ref(ir_setdata); +enum ltype get_link_type(ir_setdata); +ir_setdata get_framebox_nextsib(ir_setdata); +uint8_t* get_framebox_name(ir_setdata); +ir_setdata get_framebox_facing_framedata(ir_setdata, apc_facing); +ir_setdata get_framebox_facing_mapdata(ir_setdata, apc_facing); +int get_framedata_height(ir_setdata); +int get_framedata_width(ir_setdata); +uint8_t* get_framedata_name(ir_setdata); diff --git a/src/pagenode.h b/src/pagenode.h new file mode 100644 index 0000000..8497f81 --- /dev/null +++ b/src/pagenode.h @@ -0,0 +1,88 @@ +#include //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; +} -- 2.18.0