#include "sortedmap.h" #include #include #include SortedMap * map() { SortedMap *this = malloc(sizeof(SortedMap)); this->type = EMPTY; this->key = NULL; return this; } void * get_map(SortedMap *this, char *key) { switch (this->type) { case EMPTY: return NULL; case LEAF: if (strcmp(key, this->key) == 0) return this->content.value; return NULL; case INTERN: if (strcmp(key, this->key) <= 0) { return get_map(this->content.children.l, key); } else { return get_map(this->content.children.r, key); } default: return NULL; } } SortedMap * put_map(SortedMap *this, char *key, void *value) { SortedMap *leaf, *intern; int cmp = this->key != NULL ? strcmp(key, this->key) : 0; switch (this->type) { case EMPTY: this->type = LEAF; this->key = key; this->content.value = value; return this; case LEAF: if (cmp == 0) { this->content.value = value; return this; } leaf = malloc(sizeof(SortedMap)); leaf->type = LEAF; leaf->key = key; leaf->content.value = value; intern = malloc(sizeof(SortedMap)); intern->type = INTERN; intern->key = cmp <= 0 ? key : this->key; intern->content.children.l = cmp <= 0 ? leaf : this; intern->content.children.r = cmp <= 0 ? this : leaf; return intern; case INTERN: if (cmp <= 0) { this->content.children.l = put_map(this->content.children.l, key, value); return this; } else { this->content.children.r = put_map(this->content.children.r, key, value); return this; } default: return NULL; } } void print_indent_(int indent) { int i; for(i = 0; i < indent; i++) printf(" "); } void print_map_(SortedMap *this, int indent) { switch (this->type) { case EMPTY: printf("empty\n"); break; case LEAF: print_indent_(indent); printf("%s: %s\n", this->key, (char *) this->content.value); break; case INTERN: print_map_(this->content.children.r, indent + 1); print_indent_(indent); printf("%s\n", this->key); print_map_(this->content.children.l, indent + 1); break; } } void print_map(SortedMap *this) { print_map_(this, 0); } void * fold_map(SortedMap *this, void * init, void * (*f)(void * acc, char *key, void *value)) { switch (this->type) { case EMPTY: return init; case LEAF: return f(init, this->key, this->content.value); case INTERN: return fold_map(this->content.children.r, fold_map(this->content.children.l, init, f), f); default: return NULL; } } void free_mapvalues(SortedMap *this) { switch (this->type) { case EMPTY: break; case LEAF: free(this->content.value); break; case INTERN: free_mapvalues(this->content.children.l); free_mapvalues(this->content.children.r); break; } } void free_mapkeys(SortedMap *this) { switch (this->type) { case EMPTY: break; case LEAF: free(this->key); break; case INTERN: free_mapkeys(this->content.children.l); free_mapkeys(this->content.children.r); break; } } void * free_mappair(void *acc, char *key, void *value) { free(key); free(value); return NULL; } void * free_mapitem(void *acc, char *key, void *value) { free(value); return NULL; } void free_map(SortedMap *this) { switch (this->type) { case EMPTY: case LEAF: free(this); break; case INTERN: free_map(this->content.children.l); free_map(this->content.children.r); free(this); break; } }