159 lines
3.3 KiB
C
159 lines
3.3 KiB
C
#include "sortedmap.h"
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
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;
|
|
}
|
|
}
|