add json printing and parsing (of strings)
This commit is contained in:
parent
563b1b0c5a
commit
a13c6ecb3a
6 changed files with 277 additions and 81 deletions
166
sortedmap.c
166
sortedmap.c
|
@ -2,77 +2,65 @@
|
|||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
struct intern {
|
||||
enum nodetype type;
|
||||
char * key;
|
||||
struct node * left;
|
||||
struct node * right;
|
||||
};
|
||||
|
||||
struct leaf {
|
||||
enum nodetype type;
|
||||
char * key;
|
||||
void * value;
|
||||
};
|
||||
|
||||
SortedMap * map() {
|
||||
return NULL;
|
||||
SortedMap *this = malloc(sizeof(SortedMap));
|
||||
this->type = EMPTY;
|
||||
this->key = NULL;
|
||||
return this;
|
||||
}
|
||||
|
||||
void * get_map(SortedMap *this, char *key) {
|
||||
if (this == NULL) return NULL;
|
||||
if (this->type == LEAF) {
|
||||
if (strcmp(key, this->key) == 0) return ((struct leaf *) this)->value;
|
||||
switch (this->type) {
|
||||
case EMPTY:
|
||||
return NULL;
|
||||
} else {
|
||||
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(((struct intern *) this)->left, key);
|
||||
return get_map(this->content.children.l, key);
|
||||
} else {
|
||||
return get_map(((struct intern *) this)->right, key);
|
||||
return get_map(this->content.children.r, key);
|
||||
}
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
SortedMap * put_map(SortedMap *this, char *key, void *value) {
|
||||
struct leaf *leaf, *newleaf;
|
||||
struct intern *intern;
|
||||
int cmp;
|
||||
|
||||
if (this == NULL) {
|
||||
struct leaf *leaf = malloc(sizeof(struct leaf));
|
||||
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->value = value;
|
||||
return (SortedMap *) leaf;
|
||||
} else {
|
||||
cmp = strcmp(key, this->key);
|
||||
if (this->type == LEAF) {
|
||||
leaf = (struct leaf*) this;
|
||||
if (cmp == 0) {
|
||||
leaf->value = value;
|
||||
return (SortedMap *) leaf;
|
||||
}
|
||||
newleaf = malloc(sizeof(struct leaf));
|
||||
newleaf->type = LEAF;
|
||||
newleaf->key = key;
|
||||
newleaf->value = value;
|
||||
intern = malloc(sizeof(struct intern));
|
||||
intern->type = INTERN;
|
||||
intern->key = leaf->key;
|
||||
intern->left = (struct node*) (cmp < 0 ? newleaf : leaf);
|
||||
intern->right = (struct node*) (cmp < 0 ? leaf : newleaf);
|
||||
return (SortedMap *) intern;
|
||||
leaf->content.value = value;
|
||||
intern = malloc(sizeof(SortedMap));
|
||||
intern->type = INTERN;
|
||||
intern->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 {
|
||||
intern = (struct intern*) this;
|
||||
if (cmp <= 0) {
|
||||
intern->left = put_map(intern->left, key, value);
|
||||
return (SortedMap *) intern;
|
||||
} else {
|
||||
intern->right = put_map(intern->right, key, value);
|
||||
return (SortedMap *) intern;
|
||||
}
|
||||
this->content.children.r = put_map(this->content.children.r, key, value);
|
||||
return this;
|
||||
}
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -82,42 +70,64 @@ void print_indent_(int indent) {
|
|||
}
|
||||
|
||||
void print_map_(SortedMap *this, int indent) {
|
||||
if (this->type == LEAF) {
|
||||
struct leaf *leaf = (struct leaf*) this;
|
||||
switch (this->type) {
|
||||
case EMPTY:
|
||||
printf("empty\n");
|
||||
break;
|
||||
case LEAF:
|
||||
print_indent_(indent);
|
||||
printf("%s: %s\n", leaf->key, (char *) leaf->value);
|
||||
} else {
|
||||
struct intern *intern = (struct intern*) this;
|
||||
print_map_(intern->left, indent + 1);
|
||||
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", intern->key);
|
||||
print_map_(intern->right, indent + 1);
|
||||
printf("%s\n", this->key);
|
||||
print_map_(this->content.children.l, indent + 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void print_map(SortedMap *this) {
|
||||
if (this == NULL) printf("empty\n");
|
||||
else print_map_(this, 0);
|
||||
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(fold_map(init, this->content.children.l, f), this->content.children.r, f);
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void free_mapvalues(SortedMap *this) {
|
||||
if (this == NULL) return;
|
||||
else if (this->type == LEAF) free(((struct leaf*) this)->value);
|
||||
else {
|
||||
struct intern *intern = (struct intern*) this;
|
||||
free_mapvalues(intern->left);
|
||||
free_mapvalues(intern->right);
|
||||
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_map(SortedMap *this) {
|
||||
struct intern *intern;
|
||||
if (this == NULL) return;
|
||||
else if (this->type == LEAF) free(this);
|
||||
else {
|
||||
intern = (struct intern*) this;
|
||||
free_map(intern->left);
|
||||
free_map(intern->right);
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue