#include "ir.h"\r
#undef do_error\r
#define do_error(...) exit(-1)\r
+#define XXH_PRIVATE_API\r
+#include "../xxHash/xxhash.h"\r
/* Public */\r
int ir_init(void);\r
void ir_quit(void);\r
+void ir_test(void);\r
int ir_linker(void);\r
int ir_condenser(void);\r
/* Memory allocation structures */\r
struct pagenode_t* root, * head;\r
size_t pagesize;\r
};\r
-#define DATA_PAGESIZE (sys_pagesize)\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
struct ir_set_t\r
{ struct ir_set_t* nextchild, * nextsib;\r
struct ir_class_t* class;\r
- long long ref;\r
+ uint32_t ref;\r
uint8_t* name;\r
struct ir_framebox_t* frameboxes;\r
struct ir_simplex_t* audio;\r
static inline\r
union ir_setdata_t* ir_framedata (enum dtype,const uint8_t*,apc_facing,int,int);\r
static inline\r
-int init_pagelist(struct pagelist_t*,size_t);\r
-static\r
-void ir_free_pagenodes(struct pagenode_t*);\r
-static inline\r
int bytes_identical(const uint8_t*,const uint8_t*);\r
static inline\r
int classnames_identical(const uint8_t*,const uint8_t*);\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 pagelist_alloc(pagelist) do { \\r
+ pagelist.head->header.next = (struct pagenode_t*) calloc(pagelist.pagesize,1); \\r
+ if (pagelist.head->header.next == NULL) \\r
+ eprintf("Memory allocation error\n"); \\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*) calloc(size,1); \\r
+ if (pagelist.root == NULL) \\r
+ eprintf("Memory allocation error\n"); \\r
+ pagelist.root->header.head = pagelist.root->root; \\r
+ pagelist.head = pagelist.root; \\r
+ } while (0)\r
+static\r
+void pagenode_free(struct pagenode_t*);\r
+#define REFHASH(ref) (XXH32(&ref, sizeof(uint32_t), 0xCEED) & 0xCFF)\r
+\r
extern //apc.c\r
long sys_pagesize;\r
static\r
-struct pagelist_t datapages, namepages;\r
+struct pagelist_t datapages, namepages, refhashpages;\r
static\r
struct ir_class_t root_class = { .name = (uint8_t*)"." };\r
\r
/* Init */\r
int ir_init\r
( void )\r
-{ if (init_pagelist(&datapages, (size_t)DATA_PAGESIZE))\r
- eprintf("Memory allocation error\n");\r
- if (init_pagelist(&namepages, (size_t)NAME_PAGESIZE))\r
- eprintf("Memory allocation error\n");\r
+{ pagelist_init(datapages, (size_t)SYS_PAGESIZE);\r
+ pagelist_init(namepages, (size_t)NAME_PAGESIZE);\r
+ pagelist_init(refhashpages, (size_t)SYS_PAGESIZE);\r
return 0;\r
}\r
\r
-static inline\r
-int init_pagelist\r
-( struct pagelist_t* pl,\r
- size_t size\r
-)\r
-{ pl->pagesize = size;\r
- pl->root = (struct pagenode_t*) calloc(size,1);\r
- if (pl->root == NULL)\r
- return -1;\r
- pl->root->header.head = pl->root->root;\r
- pl->head = pl->root;\r
- return 0;\r
-}\r
-\r
-/* Quit/Cleanup\r
- Recursively clean pagenode linked list\r
-*/\r
+/* Quit/Cleanup */\r
void ir_quit\r
( void )\r
-{ ir_free_pagenodes(datapages.root);\r
- ir_free_pagenodes(namepages.root);\r
+{ 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 ir_free_pagenodes\r
+void pagenode_free\r
( struct pagenode_t* pagenode )\r
{ if (pagenode->header.next != NULL)\r
- ir_free_pagenodes(pagenode->header.next);\r
+ pagenode_free(pagenode->header.next);\r
free(pagenode);\r
}\r
\r
-/* Link\r
-*/\r
+/* Link */\r
int ir_linker\r
( void )\r
-{ return 0; }\r
+{ \r
+ return 0;\r
+}\r
\r
-/* Condense\r
-*/\r
+/* Condense */\r
int ir_condenser\r
( void )\r
{ return 0; }\r
return class->root_set = iter;\r
}\r
\r
+struct ir_set_t* ir_set_from_ref\r
+( uint32_t ref )\r
+{ uint16_t hash;\r
+ struct ir_set_t** iters;\r
+ struct pagenode_t* iterp;\r
+ iterp = refhashpages.root;\r
+ hash = REFHASH(ref);\r
+ do\r
+ iters = ((struct ir_set_t**) iterp->root) + hash;\r
+ while (*iters != NULL && (*iters)->ref != ref && (iterp = iterp->header.next) != NULL);\r
+ return *iters;\r
+}\r
+\r
+\r
/* Add a set to a set\r
Attempts to create a new subset of the specified set, returning the\r
child if it already exists\r
return (ca == cb);\r
}\r
\r
-/* Assign Setdata to Set\r
-\r
- */\r
+/* Assign Setdata to Set */\r
void ir_set_assign_data\r
( struct ir_set_t* set,\r
union ir_setdata_t* setdata\r
\r
void ir_set_assign_ref\r
( struct ir_set_t* set,\r
- long long ref\r
+ uint32_t ref\r
)\r
-{ if (set->ref != 0)\r
- wprintf("Ref override: 0x%lx -> 0x%lx for set %s\n",\r
- (long unsigned) set->ref, (long unsigned) ref, set->name);\r
+{ uint16_t hash, oldhash;\r
+ struct ir_set_t** iters;\r
+ struct pagenode_t* iterp;\r
+ uint32_t oldref;\r
+ oldref = set->ref;\r
+ oldhash = 0;\r
+ hash = REFHASH(ref);\r
+ iterp = refhashpages.root;\r
+ check_depth:\r
+ iters = ((struct ir_set_t**) iterp->root) + hash;\r
+ if (*iters == NULL || *iters == set)\r
+ *iters = set;\r
+ else\r
+ { if (iterp->header.next == NULL)\r
+ pagelist_alloc(refhashpages);\r
+ iterp = iterp->header.next;\r
+ goto check_depth;\r
+ }\r
+ if (oldref != 0)\r
+ { wprintf("Ref override: 0x%x -> 0x%x for set %s\n", oldref, ref, set->name);\r
+ if (oldhash != 0)\r
+ *iters = NULL;\r
+ else\r
+ { oldhash = hash;\r
+ hash = REFHASH(oldref);\r
+ goto check_depth;\r
+ }\r
+ }\r
set->ref = ref;\r
- //TODO: reflist_add(set);\r
}\r
\r
void ir_data_assign_path\r
}\r
\r
struct ir_setld_t* ir_setld_from_ref\r
-( long long ref )\r
+( uint32_t ref )\r
{ struct ir_setld_t* setld;\r
setld = struct_alloc(ir_setld_t);\r
setld->ref = ref;\r
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
-{ if (!bytes) //valid behavior to attain current head\r
- return datapages.head->header.head;\r
- if (PL_HEADMEM(datapages) < bytes) \r
- { datapages.head->header.next = (struct pagenode_t*) calloc(datapages.pagesize,1);\r
- if (datapages.head->header.next == NULL)\r
- eprintf("Memory allocation error \n");\r
- datapages.head = datapages.head->header.next; \r
- datapages.head->header.head = datapages.head->root;\r
- }\r
+{ if (PL_HEADMEM(datapages) < bytes) \r
+ pagelist_alloc(datapages);\r
datapages.head->header.head += bytes;\r
return (void*) datapages.head->header.head - bytes;\r
}\r
for (head_mem = PL_HEADMEM(namepages); *iter && *iter != '_' && head_mem; head_mem--)\r
*(namepages.head->header.head)++ = *iter++;\r
if (head_mem == 0) //not enough room\r
- { namepages.head->header.next = (struct pagenode_t*) calloc(namepages.pagesize,1);\r
- if (namepages.head->header.next == NULL)\r
- eprintf("Memory allocation error\n");\r
- namepages.head = namepages.head->header.next;\r
- namepages.head->header.head = namepages.head->root;\r
+ { pagelist_alloc(namepages);\r
goto copy;\r
}\r
*(namepages.head->header.head)++ = '\0';\r
for (head_mem = PL_HEADMEM(namepages); *iter && head_mem; head_mem--)\r
*(namepages.head->header.head)++ = *iter++;\r
if (head_mem == 0) //not enough room\r
- { namepages.head->header.next = (struct pagenode_t*) calloc(namepages.pagesize,1);\r
- if (namepages.head->header.next == NULL)\r
- eprintf("Memory allocation error\n");\r
- namepages.head = namepages.head->header.next;\r
- namepages.head->header.head = namepages.head->root;\r
+ { pagelist_alloc(namepages);\r
goto copy;\r
}\r
*(namepages.head->header.head)++ = '\0';\r
return name;\r
}\r
+\r
+#define pdepth() do { for (i = 0; i < depth * 2; i++) putchar(' '); } while (0)\r
+void ir_test(void)\r
+{ struct ir_class_t* class, * classbuf;\r
+ struct ir_set_t* set, * set_child;\r
+ int depth, i, olddepth;\r
+ depth = olddepth = 0;\r
+ classbuf = NULL;\r
+ for(class = ir_class_root(); class != NULL; class = class->nextchild)\r
+ {handle_class:\r
+ pdepth();\r
+ uprintf("%U\n",class->name);\r
+ old_depth = depth;\r
+ set = class->root_set;\r
+ handle_set:\r
+ while(set != NULL)\r
+ { pdepth();uprintf("|");\r
+ pdepth();\r
+ uprintf("-[%U]",set->name);\r
+ set_child = set->nextchild;\r
+ while (set_child != NULL)\r
+ { depth++;\r
+ uprintf("--[%U]",set_child->name);\r
+ set_child = set_child->nextchild;\r
+ }\r
+ uprintf("\n");\r
+ set = set->nextsib;\r
+ }\r
+ if (class->nextsib != NULL)\r
+ { if (classbuf == NULL)\r
+ classbuf = class;\r
+ class = class->nextsib;\r
+ goto handle_class;\r
+ }\r
+ if (classbuf != NULL)\r
+ class = classbuf;\r
+ classbuf = NULL;\r
+ uprintf("\n");\r
+ depth = olddepth + 1;\r
+ }\r
+}\r