X-Git-Url: https://git.kengrimes.com/?p=henge%2Fapc.git;a=blobdiff_plain;f=src%2Fbinaryout.c;h=ad9c5cd3b2806a9026bd2c1bd5de026dd6cb7592;hp=39ece407ca6a40f1983bfcd2dcb59ef2969116b5;hb=3e4496a9ecca4b2e107f4473af2bdd062690ffc4;hpb=d6c67861eaed9dc64d8bf2c1ddd91bf7a1f458fe diff --git a/src/binaryout.c b/src/binaryout.c index 39ece40..ad9c5cd 100644 --- a/src/binaryout.c +++ b/src/binaryout.c @@ -22,10 +22,13 @@ #include "../stb/stb_image.h" #define STB_IMAGE_WRITE_IMPLEMENTATION #include "../stb/stb_image_write.h" +#include "../ston/ston.h" /* Public */ void ir_binout_init(struct ir_class_t*); - +/* Private */ +static +long file_ht_insert(long,int,int,int,uint32_t*,uint32_t,uint32_t); /* Memory Allocation */ #define struct_alloc(_T) ((struct _T*) stack_alloc(&datapages, sizeof(struct _T))) static @@ -46,11 +49,11 @@ struct bin_ht_header_t { int entries; int size; }; -struct bin_default_ht_entry_t { +struct bin_ht_entry_t { uint32_t key; long value; }; -struct bin_var_ht_entry_t { +struct bin_variant_ht_entry_t { uint32_t key; long vvalue; long mvalue; @@ -81,7 +84,7 @@ struct bin_frame_header_t { }; struct bin_pixel_t { - int x, y, z, num; //the x matching pixel + int x, y, z; uint32_t ref; int attach_idx; }; @@ -121,13 +124,23 @@ struct bin_processed_links_t struct bin_linklist_t* dlink_list; int dlink_len; }; +struct bin_pixel_ht_entry_t +{ uint16_t key; + uint16_t value; +}; +struct bin_pixel_ht_t +{ struct bin_pixel_ht_t* next; + struct bin_pixel_ht_entry_t* hash_entries; +}; + +static struct bin_attachment_list_t **attachment_stack, **asp; //attachment_stack, attachment_stack_pointer +static FILE* binaryout; - #define NAMEHASH(name, domain) (XXH32(name, u8_strlen(name), 0XCEED ) & domain) - +#define REFHASH(ref, domain) (XXH32(&ref, sizeof(uint32_t), 0xCEED) & domain) static inline int bin_set_varcount ( ir_set set ) @@ -161,20 +174,6 @@ int bin_set_sibcount return count; } -/* 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 @@ -205,95 +204,128 @@ ir_binout_init(ir_class root_class) bin_traverse_class(root_class); } - +/* INSERT INTO HASH TABLE */ /* Returns the key position where the hash table entry was inserted. */ -#define ENTRY_OCCUPIED() (bytes_null(uint32_t), entry_pos)) -#define LOOP_ENTRY(_HTSTART) (entry_pos = _HTSTART) -#define WRITE_DEF_ENTRY() do { \ - if(fseek(binaryout, entry_pos, SEEK_SET) == -1) wprintf("fseek failed with %s", strerror(errno)); \ - fwrite(&def_ht_entry, sizeof def_ht_entry, 1, binaryout); \ +#define SEEK_TO(_FPOS) do { \ + errno = 0; \ + if (fseek(binaryout, _FPOS, SEEK_SET)) \ + eprintf("Failed to seek to position %l: %s\n", _FPOS, strerror(errno)); \ } while (0) -#define INC_DEF_ENTRY() do { \ - entry_pos += sizeof(def_ht_entry); \ - if(fseek(binaryout, entry_pos, SEEK_SET) == -1) eprintf("fseek failed with %s", strerror(errno)); \ +#define SEEK_REL(_FPOS) do { \ + errno = 0; \ + if (fseek(binaryout, _FPOS, SEEK_CUR)) \ + eprintf("Failed to seek to position %l: %s\n", _FPOS, strerror(errno)); \ + } while (0) +#define READ_DATA_AND_INCREMENT(_DATA,_SIZE) do { \ + errno = 0; \ + if (fread(_DATA, _SIZE, 1, binaryout) != 1) \ + eprintf("Failed to read data at file position %l: %s\n", \ + ftell(binaryout), \ + strerror(errno)); \ + } while (0) +#define READ_DATA(_DATA,_SIZE) do { \ + READ_DATA_AND_INCREMENT(_DATA,_SIZE); \ + SEEK_REL(-_SIZE); \ + } while (0) +#define WRITE_DATA_AND_INCREMENT(_DATA,_SIZE) do { \ + errno = 0; \ + if (fwrite(_DATA, _SIZE, 1, binaryout) != 1) \ + eprintf("Failed to write data to file at position %l: %s\n", \ + ftell(binaryout), \ + strerror(errno)); \ + } while (0) +#define WRITE_DATA(_DATA,_SIZE) do { \ + WRITE_DATA_AND_INCREMENT(_DATA,_SIZE); \ + SEEK_REL(-_SIZE); \ } while (0) -#define HT_END(_HTEND) (entry_pos >= _HTEND) //just in case at last entry -long -bin_insert_default_ht_entry -( long ht_start, - int ht_size, - struct bin_def_ht_entry_t* def_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_DEF_ENTRY(); +/* Insert a value into an arbitrary hash table in-file */ +static +long file_ht_insert +( long ht_start, + int ht_row_values, + int ht_which_value, + int ht_rows, + uint32_t* overwrite, + uint32_t key, + uint32_t value +) +{ uint32_t entry[ht_row_values]; +# define ENTRY_VAL(N) entry[N] +# define ENTRY_KEY ENTRY_VAL(0) + uint8_t looped = 0; + size_t entry_row = key & (ht_rows - 1); + int i; + long writepos, startpos; + startpos = ftell(binaryout); + next_entry: + SEEK_TO(ht_start + (entry_row * sizeof(entry))); + READ_DATA(entry, sizeof(uint32_t) * ht_row_values); + for (i = 0; i < ht_row_values; i++) + if (entry[i] != 0) + goto populated; + write_position: + SEEK_REL(sizeof(uint32_t) * ht_which_value); + WRITE_DATA(entry + ht_which_value, sizeof(*entry)); + writepos = ftell(binaryout); + SEEK_TO(startpos); + return writepos; + populated: + if (ENTRY_KEY == key) + { if (overwrite != NULL) + *overwrite = ENTRY_VAL(ht_which_value); + ENTRY_VAL(ht_which_value) = value; + goto write_position; } - 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_DEF_ENTRY(); + if (entry_row < ht_rows) + entry_row++; + else if (looped) + eprintf("cannot insert into filled hashtable\n"); + else + { looped++; + entry_row = 0; } - WRITE_DEF_ENTRY(); - - return entry_pos; - + goto next_entry; } -long -#define WRITE_VAR_ENTRY() do { \ - if(fseek(binaryout, entry_pos, SEEK_SET) == -1) wprintf("fseek failed with %s", strerror(errno)); \ - fwrite(&var_ht_entry, sizeof var_ht_entry, 1, binaryout); \ -} while (0) -#define INC_VAR_ENTRY() do { \ - entry_pos += sizeof(var_ht_entry); \ - if(fseek(binaryout, entry_pos, SEEK_SET) == -1) eprintf("fseek failed with %s", strerror(errno)); \ - } while (0) -bin_insert_var_ht_entry -( long ht_start, - int ht_size, - struct bin_var_ht_entry_t* var_ht_entry, - int overwrite -) -{ long entry_pos, ht_end; - ht_end = ht_start + ht_size; - entry_pos = ht_start + sizeof(var_ht_entry) * ht_entry->key; - fseek(binaryout, entry_pos, SEEK_SET); - - if (!ENTRY_OCCUPIED()) - { uprintf("key not occupied\n"); - WRITE_VAR_ENTRY(); +static +uint32_t* mem_ht_insert +( void* ht_start, + int ht_row_values, + int ht_which_value, + int ht_rows, + uint32_t* overwrite, + uint32_t key, + uint32_t value +) +{ uint32_t* entry; + uint8_t looped = 0; + size_t entry_row = key & (ht_rows - 1); + int i; + next_entry: + entry = (uint32_t*)ht_start + (ht_row_values * entry_row); + for (i = 0; i < ht_row_values; i++) + if (entry[i] != 0) + goto populated; + write_position: + entry[ht_which_value] = value; + return &entry[ht_which_value]; + populated: + if (ENTRY_KEY == key) + { if (overwrite != NULL) + *overwrite = ENTRY_VAL(ht_which_value); + goto write_position; } - 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_VAR_ENTRY(); + if (entry_row < ht_rows) + entry_row++; + else if (looped) + eprintf("cannot insert into filled hashtable\n"); + else + { looped++; + entry_row = 0; } - WRITE_VAR_ENTRY(); - - return entry_pos; + goto next_entry; +} /** @see http://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2 */ static inline @@ -337,19 +369,20 @@ bin_traverse_class { ir_class citer; ir_set siter; struct bin_class_header_t class_header; - struct bin_def_ht_entry_t ht_entry; long class_start, classht_start, classht_size, rootsetht_start, rootsetht_size; int num_class_entries, num_rootset_entries; uint8_t* class_name; + class_header.namelen = u8_strlen(class_name); + + class_start = ftell(binaryout); class_name = ir_class_name(class); num_class_entries = bin_calculate_ht_entries(bin_class_sibcount(class)); - num_rootset_entries = bin_calculate_ht_entries(ir_class_rootset(class)); + num_rootset_entries = bin_calculate_ht_entries(bin_set_sibcount(ir_class_rootset(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); DEF_HT_INIT(classht_start, classht_size, num_class_entries); @@ -370,9 +403,11 @@ bin_traverse_class /* Start populating root_set hash table */ for ( siter = ir_class_rootset(class); siter != NULL; siter = ir_set_nextsib(siter)) { fseek(binaryout, 0, SEEK_END); - ht_entry.key = NAMEHASH(ir_set_name(siter), num_rootset_entries); - ht_entry.value = bin_traverse_set(siter); - bin_insert_def_ht_entry(rootsetht_start, rootsetht_size, &ht_entry, 0); + file_ht_insert(rootsetht_start, 2, 1, + rootsetht_size, + &old_value, + NAMEHASH(ir_set_name(siter), num_rootset_entries), + bin_traverse_set(siter)); } /* Start populating class child hash table */ @@ -380,9 +415,11 @@ bin_traverse_class { if(chdir((char*) class_name)) eprintf("CHDIR %U from %s\n",(char*) class_name,getcwd(NULL,255)); fseek(binaryout, 0, SEEK_END); - ht_entry.key = NAMEHASH(ir_class_name(citer), num_class_entries); - ht_entry.value = bin_traverse_class(citer); - bin_insert_def_ht_entry(classht_start, classht_size, &ht_entry, 0); + file_ht_insert(classht_start, 2, 1, + classht_size, + &old_value, + NAMEHASH(ir_class_name(citer), num_class_entries), + bin_traverse_class(citer)); if (chdir("..")) eprintf("CHDIR ..\n"); } @@ -439,7 +476,7 @@ bin_traverse_set { fseek(binaryout, 0, SEEK_END); ht_entry.key = NAMEHASH(ir_set_name(iter), num_entries); ht_entry.value = bin_traverse_set(iter); - bin_insert_def_ht_entry(childht_start, childht_size, &ht_entry, 0); + bin_insert_ht_entry(childht_start, childht_size, &ht_entry, 0); } @@ -785,6 +822,23 @@ bin_process_framebox return framebox_start; } +static inline +struct bin_pixel_ht_t* bin_pixel_ht_alloc +() +{ struct bin_pixel_ht_t* htp; + if(!(htp = (struct bin_pixel_ht_t*) malloc(sizeof(bin_pixel_ht_t) + ))) + eprintf("error mallocing pixel_ht\n"); + + return htp; +} +int bin_insert_pixel_ht_entry +( struct bin_pixel_ht_t* ht, + struct bin_pixel_ht_entry_t* ht_entry +) +{ + +} + void bin_process_frameboxes ( ir_set set, @@ -792,12 +846,26 @@ bin_process_frameboxes struct bin_pixel_node_t* default_pixel_list ) { struct bin_ht_entry_t ht_entry; + struct bin_pixel_ht_t* ht; + struct bin_pixel_node_t* pixeliter; ir_setdata fiter; + + /* create the default ht */ + ht = bin_ht_alloc(); + for(pixeliter = default_pixel_list; pixeliter != NULL; pixeliter = pixeliter->next) + { ht_entry.val = 1; + ht_entry.key = pixel_iter->data.ref; + bin_insert_pixel_ht_entry(&ht, ; + } + + + /* Insert variants into hash table to overwrite olink insertions*/ for ( fiter = ir_set_framebox(set); fiter != NULL; fiter = ir_setdata_nextsib(fiter)) { fseek(binaryout, 0, SEEK_END); - ht_entry.key = NAMEHASH(ir_setdata_name(fiter), ht->entries); + ht_entry.key = NAMEHASH(ir_setdata_name(fiter), ht->entries); + /* create the copy, pass the copy */ ht_entry.value = bin_process_framebox(set, fiter, default_pixel_list); bin_insert_var_ht_entry(ht->start, ht->entries * sizeof(ht_entry), &ht_entry, 1); } @@ -889,7 +957,7 @@ bin_process_facing /* pixel_list == ops, output up to fwidth amount of them */ void -bin_output_pixel_list(struct bin_pixel_node_t* map_pixel_list) +bin_output_pixel_list(struct bin_pixel_node_t* map_pixel_list); /* TODO: Please rename all the functions jhc*/ static inline @@ -923,29 +991,65 @@ int bin_set_map_pixel_list_attach_idxs defaultiter = defaultiter->next; } } +int bin_ref_in_pixel_list +( struct bin_pixel_node_t* pixel_list, + uint32_t ref +) +{ struct bin_pixel_node_t* iter; + for(iter = pixel_list; iter != NULL; iter = iter->next) + { if(ref == iter.data.ref) + return 1; + } + return 0; +} + +struct bin_pixel_ht_t* +#define PIXEL_HT_SIZE() (sizeof(bin_pixel_ht_entry_t) * SYS_PAGESIZE + sizeof(bin_pixel_ht_t*)) +bin_pixel_ht_alloc +( void ) +{ struct bin_pixel_ht_t* ht; -/* map_pixel_list cannot have more pixels. for all of its pixels, - the refs must be represented in default pixel list. 0 if invalid, 1 if valid */ + if(!(ht = (struct bin_pixel_ht_t*) malloc( PIXEL_HT_SIZE()))) + eprintf("Memory allocation error in bin_pixel_ht_alloc\n"); + memset(ht, 0, PIXEL_HT_SIZE()); + + return ht; +} + +void +bin_insert_pixel_ht_entry +( struct bin_pixel_ht_t** ht, + struct bin_pixel_ht_entry_t* ht_entry +) +{ if(*ht == NULL) + *ht = bin_pixel_ht_alloc(); + +} + +/* Determines if the multiset map_pixel is a subset of the multiset default pixel list. + 0 if invalid, 1 if valid */ static inline int bin_valid_map_pixel_list -( struct bin_pixel_node_t* default_pixel_list, +( struct bin_pixel_ht_t* default_ht, struct bin_pixel_node_t* map_pixel_list ) -{ struct bin_pixel_node_t* mapiter, *defaultiter; +{ struct bin_pixel_node_t* mapiter, *defaultiter, *tmpdefault, tmpmap; + int i; defaultiter = default_pixel_list; - /* check length of each to make sure default < max */ - /* for each pixel node in default and map */ - /* TODO: Implement:: basically just checkking if map_pixel_list is subset of default_pixel_list - which means is the intersection of default_pl and map_pl == default_pl */ - + mapiter = map_pixel_list; + while(mapiter != NULL) + { /* hash the ref*/ + /* compare against the default ht */ + /* decrement the value of the found ht_entry */ + /* if(value == 0) */ + /* return 0 */ - if(!mapiter && defaultiter) //defaultiter is longer so error! - return 0; + } - - + + return 1; } static inline @@ -963,7 +1067,7 @@ int bin_process_map_pixel_list } void -bin_assign_pixel_idxs + bin_assign_pixel_idxs ( struct bin_pixel_node_t* pixel_list ) { } @@ -972,111 +1076,65 @@ bin_assign_pixel_idxs /* number the pixels as you insert them */ struct bin_pixel_node_t* bin_insert_node_into_list -( struct bin_pixel_node_t* pixel_list_root, +( struct bin_pixel_node_t** pixel_list_root, struct bin_pixel_node_t* pixel_node ) -{ struct bin_pixel_node_t* head_node, * prev_node; +{ struct bin_pixel_node_t** head_node; + head_node = pixel_list_root; - if(pixel_list_root == NULL) - { pixel_list_root = pixel_node; - } - - prev_node = head_node = pixel_list_root; - while(head_node != NULL) - { if(pixel_node->data.z > head_node->data.z) - { if(head_node->next) - { prev_node = head_node; - head_node = head_node->next; - } - else - { head_node->next = pixel_node; - break; - } - } - else if (pixel_node->data.z < head_node->data.z) - { pixel_node->num++; - prev_node->next = pixel_node; - pixel_node->next = head_node; - break; - } - else // pixel_node->data.z == head_node->data.z - { pixel_node->num = head_node->num + 1; - prev_node->next = pixel_node; - pixel_node->next = head_node; - } - } + while(*head_node != NULL && head_node->data.ref < pixel_node->data.ref) + head_node = &((*head_node)->next); + + pixel_node->next = *head_node; + *head_node = pixel_node; return pixel_list_root; } -/* Returns the non null pixels of a single map */ -/* TODO: Finish this */ -struct bin_pixel_node_t* +/* Returns the non null pixels of a single mapframe (unaligned or not) + given any height and width */ +struct bin_pixel_node_t* bin_mapframe_to_pixel_list ( struct bin_img_info_t* img_info, int init_height, int init_width, RBGA_t* data ) -{ int x, y, fheight, fwidth; +{ int j, i, fheight, fwidth, fhsize, fwsize; + RGBA_t* p; struct bin_pixel_node_t* pixel_list,* pixel_node; pixel_list = NULL; /* if frame clips, process unclippign frames */ - if( img_info->unaligned_width ) - { if(img_info->height < img_info->fheight) - fheight = img_info->height; - else - fheight = img_info->fheight; - } - else - fheight = img_info->fheight; - if (img_info->unaligned_height ) - { if(img_info->width < img_info->fwidth) - fwidth = img_info->width; - else - fwidth = img_info->fwidth; - } - else - fwidth = img_info->fwidth; + + fwsize = img_info->unaligned_width ? img_info->unaligned_width : img_info->fwidth; + fhsize = img_info->unaligned_height ? img_info->unaligned_height : img_info->fwidth; + + + fwidth = img_info->fwidth; + fheight = img_info->fheight; /* Process the map*/ - for (y = 0; y < fheight ; y++) - { for ( x = 0; x < fwidth; x++ ) - { if (*data) + for (i = init_height; i < fhsize; i++) + { for ( j = init_width; j < fwsize; j++ ) + { if (p = data[i*img_info->width+j]) { pixel_node = struct_alloc(bin_pixel_node_t); /* get ref from 4 bytes of data */ - pixel_node->data.ref = (*data) >> 8; + pixel_node->data.ref = (*p) >> 8; /* bitshift by ? to get Z */ - pixel_node->data.z = (*data & 0xFF); + pixel_node->data.z = (*p & 0xFF); /* set x and y */ - pixel_node->data.x = x + init_width; - pixel_node->data.y = y + init_width; - pixel_list = bin_insert_node_into_list(pixel_list, pixel_node); + pixel_node->data.x = j; + pixel_node->data.y = i; + pixel_node->data.num = 0; + pixel_list = bin_insert_node_into_list(&pixel_list, pixel_node); } - data++; } - data += img_info->width - img_info->fwidth; //stride TODO: isnt this null at the last iteration? - } - //TODO: fix these two for loops why dontcha - for ( x = 0; x < fwidth; x++ ) - { if (*data) - { pixel_node = struct_alloc(bin_pixel_node_t); - /* get ref from 4 bytes of data */ - pixel_node->data.ref = (*data) >> 8; - /* bitshift by ? to get Z */ - pixel_node->data.z = (*data & 0xFF); - /* set x and y */ - pixel_node->data.x = x + init_width; - pixel_node->data.y = y + init_width; - pixel_list = bin_insert_node_into_list(pixel_list, pixel_node); - } - data++; } return pixel_list; @@ -1095,7 +1153,7 @@ int bin_pixel_list_len } return count; } - +/* TODO: what are the qualifications for the default pixel list? len and __? */ struct bin_pixel_node_t* bin_cmp_default_pixel_lists ( struct bin_pixel_node_t* pl1,