Created
January 1, 2014 16:41
-
-
Save johnfredcee/8209392 to your computer and use it in GitHub Desktop.
Sketch of a C based object system that decouples objects and functions
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| typedef struct | |
| { | |
| unsigned code; | |
| } class; | |
| static int class_count = 0; | |
| class classes[256]; | |
| typedef struct | |
| { | |
| void *class; | |
| } object; | |
| typedef object (*methodptr)(object); | |
| typedef struct | |
| { | |
| void *class; | |
| char *data; | |
| } string; | |
| typedef struct | |
| { | |
| unsigned size; | |
| methodptr* functions; | |
| unsigned* codes; | |
| } hashtable; | |
| typedef struct | |
| { | |
| hashtable *hashes; | |
| methodptr *default; | |
| } generic; | |
| unsigned hash(unsigned code, unsigned size) | |
| { | |
| unsigned mask = (1 << size) - 1; | |
| unsigned a = code; | |
| a -= (a<<6); | |
| a ^= (a>>17); | |
| a -= (a<<9); | |
| a ^= (a<<4); | |
| a -= (a<<3); | |
| a ^= (a<<10); | |
| a ^= (a>>15); | |
| return a & mask; | |
| } | |
| hashtable* new_hashtable(unsigned size) | |
| { | |
| hashtable* result; | |
| unsigned slots = 1 << size; | |
| result = malloc(hashtable); | |
| result->functions = malloc(slots * sizeof(methodptr)); | |
| memset(result->functions, 0, slots * sizeof(methodptr)); | |
| result->codes = malloc(slots * sizeof(unsigned)); | |
| memset(result->codes, 0, slots * sizeof(unsigned)); | |
| result->size = size; | |
| return result; | |
| } | |
| void delete_hashtable(hashtable* table) | |
| { | |
| free(table->codes); | |
| free(table->functions); | |
| free(table); | |
| } | |
| hashtable* extend_hashtable(hashtable* table) | |
| { | |
| hashtable* result; | |
| unsigned slots = 1 << (table->size + 1); | |
| result = malloc(hashtable); | |
| result->functions = malloc(slots * sizeof(methodptr)); | |
| memset(result->functions, 0, slots * sizeof(methodptr)); | |
| result->codes = malloc(slots * sizeof(unsigned)); | |
| memset(result->codes, 0, slots * sizeof(unsigned)); | |
| result->size = table->size + 1; | |
| // rehash | |
| delete(table); | |
| return result; | |
| } | |
| void add_hash(hashtable* table, unsigned code, methodptr* function) | |
| { | |
| unsigned hashcode = hash(code, table->size); | |
| table->codes[hashcode] = code; | |
| table->functions[hashcode] = function; | |
| } | |
| void remove_hash(hashtable* table, unsigned code, methodptr* function) | |
| { | |
| unsigned hashcode = hash(code, table->size); | |
| table->codes[hashcode] = 0; | |
| table->functions[hashcode] = NULL; | |
| } | |
| methodptr* get_fun(hashtable* table, unsigned code) | |
| { | |
| unsigned hashcode = hash(code, table->size); | |
| return table->functions[hashcode]; | |
| } | |
| unsigned new_class() | |
| { | |
| unsigned result = class_count; | |
| class *new_class = malloc(sizeof(class)); | |
| new_class->code = class_count; | |
| classes[class_count] = new_class; | |
| class_count++; | |
| return result; | |
| } | |
| generic* new_generic(methodptr *defaultfn) | |
| { | |
| generic *result = malloc(sizeof(generic)); | |
| result->hashes = new_hashtable(8); | |
| result->defaultfn = defaultfn; | |
| } | |
| void add_method(generic* genericfun, unsigned code, methodptr* function) | |
| { | |
| add_hash(genericfun->hashes, code, function); | |
| } | |
| void remove_method(generic* genericfun, unsigned code) | |
| { | |
| remove_hash(genericfun->hashes, code); | |
| } | |
| object* dispatch(generic* genericfun, object* object) | |
| { | |
| methodptr* method = get_fun(genericfun->hashes, object->class->code); | |
| if (method) | |
| return method(object); | |
| else | |
| return genericfun->defualt(object); | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment