Created
September 11, 2012 00:06
-
-
Save JAChapmanII/3694953 to your computer and use it in GitHub Desktop.
vmap from current c_map
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
#ifndef MAP_ITERATOR_H | |
#define MAP_ITERATOR_H | |
// Various locations an iterator can be at currently | |
typedef enum { IT_BEGIN, IT_END, IT_NODE, IT_INVALID } IteratorType; | |
#endif /* MAP_ITERATOR_H */ |
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
#include "map_util.h" | |
size_t util_writeSizeT(FILE *outFile, size_t toWrite) { // {{{ | |
if(!outFile) | |
return 0; | |
uint8_t buf[sizeof(size_t)] = { 0 }; | |
for(size_t i = 0; i < sizeof(size_t); ++i) | |
buf[i] = (toWrite >> (8*i)) & 0xff; | |
return fwrite(buf, 1, sizeof(size_t), outFile); | |
} // }}} | |
size_t util_readSizeT(FILE *inFile) { // {{{ | |
uint8_t buf[sizeof(size_t)] = { 0 }; | |
size_t read = fread(buf, 1, sizeof(size_t), inFile); | |
if(read != sizeof(size_t)) | |
return 0; | |
size_t result = 0; | |
for(size_t i = sizeof(size_t); i > 0; --i) | |
result = (result << 8) + buf[i - 1]; | |
return result; | |
} // }}} |
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
#ifndef UTIL_H | |
#define UTIL_H | |
#include <stdio.h> | |
#include <stdint.h> | |
// Write a size_t to a file in a endian independant way | |
size_t util_writeSizeT(FILE *outFile, size_t toWrite); | |
// Read a size_t from a file in a endian independant way | |
size_t util_readSizeT(FILE *inFile); | |
#endif // UTIL_H |
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
#include "vmap.h" | |
#include <stdlib.h> | |
#include <string.h> | |
#include "map_util.h" | |
#define SUCCESS 0 | |
#define FAILURE 1 | |
#define INVALID_SOURCE 8 | |
#define ALLOC_FAIL 9 | |
//---------------------------------------- | |
void vmap_stringInit(char **str); | |
void vmap_stringFree(char *str); | |
int vmap_stringCopy(char **dst, char **src); | |
int vmap_stringCompare(char *s1, char *s2); | |
char *vmap_stringFormat(char *str); | |
size_t vmap_stringSize(char *str); | |
int vmap_stringWrite(char *str, FILE *file); | |
int vmap_stringRead(char **str, FILE *file); | |
// vim: ft=c: | |
void vmapn_fixHeight(VMap_Node *vmapn); | |
VMap_Node *vmapn_set(VMap_Node *vmapn, | |
char * key, char * val); | |
VMap_Node *vmapn_find(VMap_Node *vmapn, char * key); | |
VMap_Node *vmapn_min(VMap_Node *vmapn); | |
VMap_Node *vmapn_max(VMap_Node *vmapn); | |
int vmapn_kequals(VMap_Node *left, VMap_Node *right); | |
VMap_Node *vmapn_erase(VMap_Node *vmapn, char * key); | |
VMap_Node *vmapn_balance(VMap_Node *vmapn); | |
VMap_Node *vmapn_rightRotation(VMap_Node *n); | |
VMap_Node *vmapn_leftRotation(VMap_Node *n); | |
size_t vmapn_size(VMap_Node *vmapn); | |
VMap *vmap_create(void) { // {{{ | |
VMap *vmap = malloc(sizeof(VMap)); | |
if(!vmap) | |
return NULL; | |
vmap->root = NULL; | |
return vmap; | |
} // }}} | |
void vmap_free(VMap *vmap) { // {{{ | |
if(!vmap) | |
return; | |
if(vmap->root) | |
vmapn_free(vmap->root); | |
free(vmap); | |
} // }}} | |
VMap_Node *vmapn_create(char * key, char * val) { // {{{ | |
if(!(key != NULL) || !(val != NULL)) | |
return NULL; | |
VMap_Node *vmapn = malloc(sizeof(VMap_Node)); | |
if(!vmapn) | |
return NULL; | |
vmapn->left = vmapn->right = NULL; | |
vmapn->height = 1; | |
vmap_stringInit(&vmapn->key); | |
vmap_stringInit(&vmapn->val); | |
vmap_stringCopy(&vmapn->key, &key); | |
vmap_stringCopy(&vmapn->val, &val); | |
if(!(key != NULL) || !(val != NULL)) { | |
vmapn_free(vmapn); | |
return NULL; | |
} | |
return vmapn; | |
} // }}} | |
void vmapn_free(VMap_Node *vmapn) { // {{{ | |
if(!vmapn) | |
return; | |
if(vmapn->left) | |
vmapn_free(vmapn->left); | |
if(vmapn->right) | |
vmapn_free(vmapn->right); | |
char * key = vmapn->key; | |
if((key != NULL)) | |
vmap_stringFree(vmapn->key); | |
char * val = vmapn->val; | |
if((val != NULL)) | |
vmap_stringFree(vmapn->val); | |
free(vmapn); | |
} // }}} | |
VMap_Iterator *vmapi_create(void) { // {{{ | |
VMap_Iterator *vmapi = malloc(sizeof(VMap_Iterator)); | |
if(!vmapi) | |
return NULL; | |
vmapi->type = IT_INVALID; | |
vmapi->map = NULL; | |
vmapi->current = NULL; | |
return vmapi; | |
}// }}} | |
void vmapi_free(VMap_Iterator *vmapi) { // {{{ | |
if(!vmapi) | |
return; | |
free(vmapi); | |
} // }}} | |
/* TODO: error handling */ | |
int vmap_set(VMap *vmap, char * key, char * val) { | |
if(!(key != NULL) || !(val != NULL)) | |
return 1; | |
if(!vmap->root) { | |
vmap->root = vmapn_create(key, val); | |
if(!vmap->root) | |
return 1; | |
return 0; | |
} | |
vmap->root = vmapn_set(vmap->root, key, val); | |
return 0; | |
} | |
VMap_Node *vmapn_set(VMap_Node *vmapn, // {{{ | |
char * key, char * val) { | |
// TODO: this was just return; .... | |
if(!vmapn || !(key != NULL) || !(val != NULL)) return vmapn; | |
int cmp = vmap_stringCompare(vmapn->key, key); | |
// TODO: error on this condition? This makes _set obsolete | |
if(!cmp) { | |
if(vmap_stringCopy(&vmapn->val, &val) != SUCCESS) { | |
// TODO: handle errors | |
} | |
return vmapn; | |
} | |
VMap_Node **child; | |
if(cmp > 0) | |
child = &vmapn->left; | |
else | |
child = &vmapn->right; | |
if(!*child) | |
*child = vmapn_create(key, val); | |
else | |
*child = vmapn_set(*child, key, val); | |
vmapn_fixHeight(vmapn); | |
return vmapn_balance(vmapn); | |
} // }}} | |
uint8_t vmapn_height(VMap_Node *vmapn) { // {{{ | |
if(!vmapn) | |
return 0; | |
return vmapn->height; | |
} // }}} | |
// TODO: implement -- is this still needed thanks to add semantics? | |
int vmap_set(VMap *vmap, char * key, char * val); | |
VMap_Node *vmap_min(VMap *vmap) { // {{{ | |
if(!vmap || !vmap->root) | |
return NULL; | |
return vmapn_min(vmap->root); | |
} // }}} | |
VMap_Node *vmapn_min(VMap_Node *vmapn) { // {{{ | |
if(!vmapn) | |
return NULL; | |
if(vmapn->left) | |
return vmapn_min(vmapn->left); | |
return vmapn; | |
} // }}} | |
VMap_Node *vmap_max(VMap *vmap) { // {{{ | |
if(!vmap || !vmap->root) | |
return NULL; | |
return vmapn_max(vmap->root); | |
} // }}} | |
VMap_Node *vmapn_max(VMap_Node *vmapn) { // {{{ | |
if(!vmapn) | |
return NULL; | |
if(vmapn->right) | |
return vmapn_max(vmapn->right); | |
return vmapn; | |
} // }}} | |
int vmapn_kequals(VMap_Node *left, VMap_Node *right) { // {{{ | |
if((left == NULL) || (right == NULL)) | |
return 0; | |
return (vmap_stringCompare(left->key, right->key) == 0); | |
} // }}} | |
// TODO: the find method can probably use this, then simply look at the left | |
// TODO: or right child for the final result. | |
VMap_Node *vmap_parent(VMap *vmap, VMap_Node *vmapn) { // {{{ | |
if(!vmap || !vmap->root || !vmapn) | |
return NULL; | |
VMap_Node *cur = vmap->root; | |
// TODO: currently if the the target is the root, we skip over it and | |
// TODO: return a NULL. We may want to keep these semantics, but bail early? | |
do { | |
if(vmapn_kequals(cur->left, vmapn) || | |
vmapn_kequals(cur->right, vmapn)) | |
return cur; | |
int cmp = vmap_stringCompare(cur->key, vmapn->key); | |
if(cmp > 0) | |
cur = cur->left; | |
else | |
cur = cur->right; | |
} while(cur != NULL); | |
return NULL; | |
} // }}} | |
// TODO: these probably have special cases when there are no/few nodes | |
VMap_Node *vmap_next(VMap *vmap, VMap_Node *vmapn) { // {{{ | |
if(vmapn->right != NULL) | |
return vmapn_min(vmapn->right); | |
VMap_Node *cur = vmapn; | |
while(1) { | |
VMap_Node *parent = vmap_parent(vmap, cur); | |
// hit end, or we don't have a parent (not in map) | |
if(parent == NULL) | |
return NULL; | |
if(parent->left == cur) | |
return parent; | |
cur = parent; | |
} | |
} // }}} | |
VMap_Node *vmap_prev(VMap *vmap, VMap_Node *vmapn) { // {{{ | |
if(vmapn->left != NULL) | |
return vmapn_max(vmapn->left); | |
VMap_Node *cur = vmapn; | |
while(1) { | |
VMap_Node *parent = vmap_parent(vmap, cur); | |
// hit end, or we don't have a parent (not in map) | |
if(parent == NULL) | |
return NULL; | |
if(parent->right == cur) | |
return parent; | |
cur = parent; | |
} | |
} // }}} | |
int vmap_erase(VMap *vmap, char * key) { // {{{ | |
if(!vmap || !(key != NULL)) | |
return 1; | |
vmap->root = vmapn_erase(vmap->root, key); | |
return 0; | |
} // }}} | |
VMap_Node *vmapn_erase(VMap_Node *vmapn, char * key) { // {{{ | |
if(!vmapn || !(key != NULL)) | |
return NULL; | |
int cmp = vmap_stringCompare(vmapn->key, key); | |
if(!cmp) { | |
if(!vmapn->left && !vmapn->right) { | |
vmapn_free(vmapn); | |
return NULL; | |
} | |
if(vmapn->left && !vmapn->right) { | |
VMap_Node *l = vmapn->left; | |
vmapn->left = NULL; | |
vmapn_free(vmapn); | |
return l; | |
} | |
if(!vmapn->left && vmapn->right) { | |
VMap_Node *r = vmapn->right; | |
vmapn->right = NULL; | |
vmapn_free(vmapn); | |
return r; | |
} | |
// replace with min from right tree | |
VMap_Node *min = vmapn_min(vmapn->right); | |
if(!min) { | |
; // TODO: panic | |
} | |
VMap_Node *m = vmapn_create(min->key, min->val); | |
if(!m) { | |
; // TODO: panic | |
} | |
// this should be one of the simple cases above | |
vmapn->right = vmapn_erase(vmapn->right, min->key); | |
m->left = vmapn->left; | |
m->right = vmapn->right; | |
m->height = vmapn->height; | |
vmapn->left = vmapn->right = NULL; | |
vmapn_free(vmapn); | |
vmapn_fixHeight(m); | |
return vmapn_balance(m); | |
} | |
if(cmp > 0) { | |
if(!vmapn->left) | |
return vmapn; | |
vmapn->left = vmapn_erase(vmapn->left, key); | |
} else { | |
if(!vmapn->right) | |
return vmapn; | |
vmapn->right = vmapn_erase(vmapn->right, key); | |
} | |
vmapn_fixHeight(vmapn); | |
return vmapn_balance(vmapn); | |
} // }}} | |
void vmapn_fixHeight(VMap_Node *vmapn) { // {{{ | |
if(!vmapn) | |
return; | |
int lh = vmapn_height(vmapn->left), | |
rh = vmapn_height(vmapn->right); | |
vmapn->height = ((lh > rh) ? lh : rh) + 1; | |
} // }}} | |
VMap_Node *vmapn_balance(VMap_Node *vmapn) { // {{{ | |
int lh = vmapn_height(vmapn->left), rh = vmapn_height(vmapn->right); | |
if(rh - lh > 1) { | |
lh = vmapn_height(vmapn->right->left); | |
rh = vmapn_height(vmapn->right->right); | |
if(lh > rh) | |
vmapn->right = vmapn_rightRotation(vmapn->right); | |
vmapn = vmapn_leftRotation(vmapn); | |
} else if(lh - rh > 1) { | |
lh = vmapn_height(vmapn->left->left); | |
rh = vmapn_height(vmapn->left->right); | |
if(rh > lh) | |
vmapn->left = vmapn_leftRotation(vmapn->left); | |
vmapn = vmapn_rightRotation(vmapn); | |
} | |
return vmapn; | |
} // }}} | |
VMap_Node *vmapn_rightRotation(VMap_Node *n) { // {{{ | |
VMap_Node *nr = n->left, *c = n->left->right; | |
nr->right = n; | |
n->left = c; | |
vmapn_fixHeight(n); | |
vmapn_fixHeight(nr); | |
return nr; | |
} // }}} | |
VMap_Node *vmapn_leftRotation(VMap_Node *n) { // {{{ | |
VMap_Node *nr = n->right, *b = n->right->left; | |
nr->left = n; | |
n->right = b; | |
vmapn_fixHeight(n); | |
vmapn_fixHeight(nr); | |
return nr; | |
} // }}} | |
VMap_Node *vmap_find(VMap *vmap, char * key) { // {{{ | |
if(!vmap->root || !(key != NULL)) | |
return NULL; | |
return vmapn_find(vmap->root, key); | |
} // }}} | |
VMap_Node *vmapn_find(VMap_Node *vmapn, char * key) { // {{{ | |
if(!vmapn || !(key != NULL)) | |
return NULL; | |
int cmp = vmap_stringCompare(vmapn->key, key); | |
if(!cmp) | |
return vmapn; | |
if(cmp > 0) | |
return vmapn_find(vmapn->left, key); | |
return vmapn_find(vmapn->right, key); | |
} // }}} | |
int vmap_contains(VMap *vmap, char * key) { | |
return vmap_find(vmap, key) != NULL; | |
} | |
char * vmap_get(VMap *vmap, char * key) { | |
VMap_Node *node = vmap_find(vmap, key); | |
if(node) | |
return node->val; | |
return NULL; | |
} | |
void vmapi_front(VMap_Iterator *vmapi, VMap *vmap) { // {{{ | |
if(!vmapi || !vmap) | |
return; | |
vmapi->map = vmap; | |
vmapi->type = IT_NODE; | |
vmapi->current = vmap_min(vmap); | |
} // }}} | |
void vmapi_back(VMap_Iterator *vmapi, VMap *vmap) { // {{{ | |
if(!vmapi || !vmap) | |
return; | |
vmapi->map = vmap; | |
vmapi->type = IT_NODE; | |
vmapi->current = vmap_max(vmap); | |
} // }}} | |
void vmapi_next(VMap_Iterator *vmapi) { // {{{ | |
if(!vmapi || !vmapi->map) | |
return; | |
switch(vmapi->type) { | |
case IT_BEGIN: | |
vmapi->current = vmap_min(vmapi->map); | |
vmapi->type = IT_NODE; | |
return; | |
case IT_END: | |
return; | |
case IT_NODE: | |
vmapi->current = vmap_next(vmapi->map, vmapi->current); | |
if(vmapi->current == NULL) | |
vmapi->type = IT_END; | |
case IT_INVALID: | |
return; | |
} | |
} // }}} | |
void vmapi_prev(VMap_Iterator *vmapi) { // {{{ | |
if(!vmapi || !vmapi->map) | |
return; | |
switch(vmapi->type) { | |
case IT_BEGIN: | |
return; | |
case IT_END: | |
vmapi->current = vmap_max(vmapi->map); | |
vmapi->type = IT_NODE; | |
return; | |
case IT_NODE: | |
vmapi->current = vmap_prev(vmapi->map, vmapi->current); | |
if(vmapi->current == NULL) | |
vmapi->type = IT_BEGIN; | |
case IT_INVALID: | |
return; | |
} | |
} // }}} | |
size_t vmap_size(VMap *vmap) { // {{{ | |
if(!vmap->root) | |
return 0; | |
return vmapn_size(vmap->root); | |
} // }}} | |
size_t vmapn_size(VMap_Node *vmapn) { // {{{ | |
if(!vmapn) | |
return 0; | |
/* NULL children are handled above */ | |
return vmapn_size(vmapn->left) + vmapn_size(vmapn->right) + 1; | |
} // }}} | |
int vmap_load(VMap *vmap, FILE *inFile) { // {{{ | |
if(!vmap || !inFile) | |
return -1; | |
size_t size = util_readSizeT(inFile); | |
if(size == 0) | |
return -2; | |
size_t rnodes = 0; | |
for(; rnodes < size; ++rnodes) { | |
char * key; | |
char * val; | |
if(vmap_stringRead(&key, inFile) != SUCCESS) { | |
// TODO: handle errors? | |
fprintf(stderr, "vmap_load: error on READ_KEY\n"); | |
} | |
if(vmap_stringRead(&val, inFile) != SUCCESS) { | |
// TODO: handle errors? | |
fprintf(stderr, "vmap_load: error on READ_VAL\n"); | |
} | |
// add the node to the VMap | |
vmap_set(vmap, key, val); | |
} | |
if(rnodes != size) { | |
fprintf(stderr, "rn: %lu, s: %lu\n", rnodes, size); | |
return -3; | |
} | |
return rnodes; | |
} // }}} | |
int vmap_read(VMap *vmap, char *fileName) { // {{{ | |
if(!vmap || !fileName) | |
return 0; | |
FILE *dumpFile = fopen(fileName, "r"); | |
if(!dumpFile) | |
return 0; | |
int res = vmap_load(vmap, dumpFile); | |
fclose(dumpFile); | |
return res; | |
} // }}} | |
int vmapn_dump(VMap_Node *vmapn, FILE *dumpFile) { // {{{ | |
if(!vmapn || !dumpFile) | |
return 0; | |
int count = 1; | |
if(vmap_stringWrite(vmapn->key, dumpFile) != SUCCESS) { | |
// TODO: handle errors? | |
fprintf(stderr, "vmapn_dump: error during WRITE_KEY\n"); | |
count = 0; | |
} else { | |
if(vmap_stringWrite(vmapn->val, dumpFile) != SUCCESS) { | |
// TODO: handle errors? | |
fprintf(stderr, "vmapn_dump: error during WRITE_VAL\n"); | |
count = 0; | |
} | |
} | |
count += vmapn_dump(vmapn->left, dumpFile); | |
count += vmapn_dump(vmapn->right, dumpFile); | |
return count; | |
} // }}} | |
int vmap_write(VMap *vmap, FILE *outFile) { // {{{ | |
if(!vmap || !outFile) | |
return -1; | |
size_t size = vmap_size(vmap); | |
if(size < 1) | |
return 0; | |
if(util_writeSizeT(outFile, size) != sizeof(size_t)) | |
return -128; | |
int count = vmapn_dump(vmap->root, outFile); | |
return count; | |
} // }}} | |
int vmap_dump(VMap *vmap, char *fileName) { // {{{ | |
if(!vmap || !fileName) | |
return 0; | |
FILE *dumpFile = fopen(fileName, "wb"); | |
if(!dumpFile) | |
return 0; | |
int count = vmap_write(vmap, dumpFile); | |
fclose(dumpFile); | |
return count; | |
} // }}} | |
int vmapn_writeDot(VMap_Node *vmapn, FILE *of, int nullCount) { // {{{ | |
if(!of || !vmapn) | |
return 0; | |
char *keyString = vmap_stringFormat(vmapn->key); | |
char *valString = vmap_stringFormat(vmapn->val); | |
fprintf(of, "\t\"%s = %s\";\n", keyString, valString); | |
if(vmapn->left) { | |
char *lKeyString = vmap_stringFormat(vmapn->left->key); | |
char *lValString = vmap_stringFormat(vmapn->left->val); | |
fprintf(of, "\t\"%s = %s\" -> \"%s = %s\";\n", keyString, valString, | |
lKeyString, lValString); | |
free(lKeyString); | |
free(lValString); | |
nullCount += vmapn_writeDot(vmapn->left, of, nullCount); | |
} else { | |
fprintf(of, "null%d [shape=point]\n", nullCount); | |
fprintf(of, "\t\"%s = %s\" -> null%d\n", keyString, valString, nullCount); | |
nullCount++; | |
} | |
if(vmapn->right) { | |
char *rKeyString = vmap_stringFormat(vmapn->right->key); | |
char *rValString = vmap_stringFormat(vmapn->right->val); | |
fprintf(of, "\t\"%s = %s\" -> \"%s = %s\";\n", keyString, valString, | |
rKeyString, rValString); | |
free(rKeyString); | |
free(rValString); | |
nullCount += vmapn_writeDot(vmapn->right, of, nullCount); | |
} else { | |
fprintf(of, "null%d [shape=point]\n", nullCount); | |
fprintf(of, "\t\"%s = %s\" -> null%d\n", keyString, valString, nullCount); | |
nullCount++; | |
} | |
free(keyString); | |
free(valString); | |
return nullCount; | |
} // }}} | |
int vmap_writeDot(VMap *vmap, char *outputName) { // {{{ | |
if(!vmap || !outputName) | |
return 1; | |
FILE *of = fopen(outputName, "w"); | |
if(!of) | |
return 2; | |
fprintf(of, "digraph BST {\n"); | |
fprintf(of, "\tnode [fontname=\"Arial\"];\n"); | |
vmapn_writeDot(vmap->root, of, 0); | |
fprintf(of, "}\n"); | |
fclose(of); | |
return 0; | |
} // }}} | |
//---------------------------------------- | |
void vmap_stringInit(char **str) { // {{{ | |
*str = NULL; | |
} // }}} | |
void vmap_stringFree(char *str) { // {{{ | |
free(str); | |
} // }}} | |
int vmap_stringCopy(char **dst, char **src) { // {{{ | |
if(*src == NULL) | |
return INVALID_SOURCE; | |
if(*dst != NULL) { | |
free(*dst); | |
*dst = NULL; | |
} | |
*dst = strdup(*src); | |
if(*dst == NULL) | |
return ALLOC_FAIL; | |
return SUCCESS; | |
} // }}} | |
int vmap_stringCompare(char *s1, char *s2) { // {{{ | |
return strcmp(s1, s2); | |
} // }}} | |
char *vmap_stringFormat(char *str) { // {{{ | |
return strdup(str); // TODO: better error handling | |
} // }}} | |
size_t vmap_stringSize(char *str) { // {{{ | |
if(str == NULL) | |
return 0; | |
return strlen(str); | |
} // }}} | |
int vmap_stringWrite(char *str, FILE *file) { // {{{ | |
size_t len = strlen(str), byteSize = (2 << 8) - 1; | |
if(len > byteSize) | |
return FAILURE; | |
uint8_t l = len; | |
if(fwrite(&l, 1, 1, file) != 1) | |
return FAILURE;// TODO: error handling? Seek backward? | |
if(fwrite(str, 1, len, file) != len) | |
return FAILURE;// TODO: error handling? Seek backward? | |
return SUCCESS; | |
} // }}} | |
int vmap_stringRead(char **str, FILE *file) { // {{{ | |
uint8_t len = 0; | |
if(fread(&len, 1, 1, file) != 1) { | |
return FAILURE;// TODO: error handling? Seek? | |
} | |
*str = calloc(len + 1, 1); | |
if(*str == NULL) { | |
return ALLOC_FAIL; // TODO: error handling? Seek? | |
} | |
if(fread(*str, 1, len, file) != len) { | |
return FAILURE;// TODO: error handling? Seek? | |
} | |
(*str)[len] = '\0'; | |
return SUCCESS; | |
} // }}} | |
// vim: ft=c: |
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
#ifndef VMAP_H | |
#define VMAP_H | |
#include <stdint.h> | |
#include <stdio.h> | |
#include "map_iterator.h" | |
/* VMap_Node, a node in an AVL tree */ | |
typedef struct VMap_Node { | |
char * key; | |
char * val; | |
struct VMap_Node *left; | |
struct VMap_Node *right; | |
uint8_t height; | |
} VMap_Node; | |
/* A char * -> char * map backed by an AVL tree */ | |
typedef struct { | |
VMap_Node *root; | |
} VMap; | |
// A VMap bidirectional iterator | |
typedef struct { | |
IteratorType type; | |
VMap_Node *current; | |
VMap *map; | |
} VMap_Iterator; | |
/* Create an empty VMap */ | |
VMap *vmap_create(void); | |
/* Free all memory associated with a VMap */ | |
void vmap_free(VMap *vmap); | |
/* Create a VMap_Node object */ | |
VMap_Node *vmapn_create(char * key, char * val); | |
/* Free space associated with a VMap_Node */ | |
void vmapn_free(VMap_Node *vmapn); | |
// Create a VMap_Iterator object | |
VMap_Iterator *vmapi_create(void); | |
// Free space assoicated with a VMap_Iterator | |
void vmapi_free(VMap_Iterator *vmapi); | |
/* Set a key/value pair in the tree (create if necessary) | |
* returns 1 on failure, 0 otherwise | |
*/ | |
int vmap_set(VMap *vmap, char * key, char * val); | |
/* Remove a node from the tree */ | |
int vmap_erase(VMap *vmap, char * key); | |
/* Search VMap for a specific node */ | |
VMap_Node *vmap_find(VMap *vmap, char * key); | |
/* Determine if a VMap contains the given key, returns a boolean */ | |
int vmap_contains(VMap *vmap, char * key); | |
/* Return a node from a VMap | |
* if the VMap doesn't contain the key, a default value is returned | |
*/ | |
char * vmap_get(VMap *vmap, char * key); | |
// Search a VMap for the minimum element | |
VMap_Node *vmap_min(VMap *vmap); | |
// Search a VMap for the maximum element | |
VMap_Node *vmap_max(VMap *vmap); | |
// Search a VMap for the parent of the given element | |
VMap_Node *vmap_parent(VMap *vmap, VMap_Node *vmapn); | |
// Search a VMap for the element occurring after a given element | |
VMap_Node *vmap_next(VMap *vmap, VMap_Node *vmapn); | |
// Search a VMap for the element occurring before a given element | |
VMap_Node *vmap_prev(VMap *vmap, VMap_Node *vmapn); | |
// Start a VMap_Iterator at the front of a VMap | |
void vmapi_front(VMap_Iterator *vmapi, VMap *vmap); | |
// Start a VMap_Iterator at the back of a VMap | |
void vmapi_back(VMap_Iterator *vmapi, VMap *vmap); | |
// Move a VMap_Iterator to the next element | |
void vmapi_next(VMap_Iterator *vmapi); | |
// Move a VMap_Iterator to the previous element | |
void vmapi_prev(VMap_Iterator *vmapi); | |
/* Recursively compute the total nodes in a VMap */ | |
size_t vmap_size(VMap *vmap); | |
/* Write a VMap to a file */ | |
int vmap_write(VMap *vmap, FILE *outFile); | |
/* Try to open a file and write the VMap to it */ | |
int vmap_dump(VMap *vmap, char *fileName); | |
/* Read a VMap from a file */ | |
int vmap_load(VMap *vmap, FILE *inFile); | |
/* Try to open a file and load the VMap from it */ | |
int vmap_read(VMap *vmap, char *fileName); | |
/* Write this VMap out as a graphviz .dot file */ | |
int vmap_writeDot(VMap *vmap, char *outputName); | |
#endif /* VMAP_H */ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment