summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbpc2003 <wpesfriendnva@gmail.com>2025-05-18 18:11:14 -0400
committerbpc2003 <wpesfriendnva@gmail.com>2025-05-18 18:11:14 -0400
commit0575736fd33a60796ce29c0241da2492363fe24d (patch)
treee4cf4131f1784ac865daeec516bd544875416aea
parente99a79f1499b6cfb60007587ebeda645c32d38dc (diff)
Added attribute parsing to decoder
-rw-r--r--src/include/xml/decode.c162
-rw-r--r--src/include/xml/xml.h2
-rw-r--r--src/test.c453
3 files changed, 340 insertions, 277 deletions
diff --git a/src/include/xml/decode.c b/src/include/xml/decode.c
index a405e97..e486a18 100644
--- a/src/include/xml/decode.c
+++ b/src/include/xml/decode.c
@@ -5,70 +5,126 @@
static char *gettag(char *xml, int *pos);
static char *getvalue(char *xml, int *pos);
+static attr_t *getattrs(char *parsed, char **tag, int *n_attrs);
// TODO: make this smaller
+// TODO: add attribute parsing
map_t *decode(char *xml, int *pos, int *len)
{
- if (*len)
- ++(*len);
- else
- *len = 1;
- map_t *decoded = calloc(1, sizeof(map_t));
+ if (*len)
+ ++(*len);
+ else
+ *len = 1;
+ map_t *decoded = calloc(1, sizeof(map_t));
- int err = 0, closed = 1;
- for (int i = *pos; i < strlen(xml); ++i) {
- if (!strncmp(xml + i, "</", 2)) {
- i += 2;
- char *tmp = gettag(xml, &i);
- if (!strcmp(decoded->tag, tmp))
- *pos = i;
- else
- err = 1;
- free(tmp);
- goto end;
- } else if (xml[i] == '<' && closed) {
- ++i;
- decoded->tag = gettag(xml, &i);
- closed = 0;
- } else if (xml[i] == '<' && !closed) {
- map_t *ndec = decode(xml, &i, &(decoded->n));
- decoded->size = sizeof(map_t);
- if (decoded->n > 1)
- decoded->payload = realloc(decoded->payload, decoded->n * sizeof(map_t));
- else
- decoded->payload = calloc(1, sizeof(map_t));
- ((map_t *) decoded->payload)[decoded->n - 1] = *ndec;
- free(ndec);
- } else {
- decoded->payload = getvalue(xml, &i);
- decoded->size = sizeof(char);
- decoded->n = strlen(decoded->payload);
- }
- }
- end:
- if (err) {
- free(decoded);
- decoded = NULL;
- }
- return decoded;
+ int err = 0, closed = 1;
+ for (int i = *pos; i < strlen(xml); ++i) {
+ if (!strncmp(xml + i, "</", 2)) {
+ i += 2;
+ char *tmp = gettag(xml, &i);
+ if (!strcmp(decoded->tag, tmp))
+ *pos = i;
+ else
+ err = 1;
+ free(tmp);
+ goto end;
+ } else if (xml[i] == '<' && closed) {
+ ++i;
+ decoded->attrs =
+ getattrs(gettag(xml, &i),
+ &(decoded->tag), &(decoded->n_attrs));
+ closed = 0;
+ } else if (xml[i] == '<' && !closed) {
+ map_t *ndec = decode(xml, &i, &(decoded->n));
+ decoded->size = sizeof(map_t);
+ if (decoded->n > 1)
+ decoded->payload = realloc(decoded->payload, decoded->n * sizeof(map_t));
+ else
+ decoded->payload = calloc(1, sizeof(map_t));
+ ((map_t *) decoded->payload)[decoded->n - 1] = *ndec;
+ free(ndec);
+ } else {
+ decoded->payload = getvalue(xml, &i);
+ decoded->size = sizeof(char);
+ decoded->n = strlen(decoded->payload);
+ }
+ }
+ end:
+ if (err) {
+ free(decoded);
+ decoded = NULL;
+ }
+ return decoded;
}
static char *gettag(char *xml, int *pos)
{
- int len, i;
- for (i = *pos, len = 0; xml[i] != '>'; ++i, ++len) ;
- char *title = calloc(len + 1, sizeof(char));
- strncpy(title, xml + *pos, len);
- *pos += len;
- return title;
+ int len, i;
+ for (i = *pos, len = 0; xml[i] != '>' && i < strlen(xml); ++i, ++len)
+ ;
+ if (i >= strlen(xml))
+ return NULL;
+ char *title = calloc(len + 1, sizeof(char));
+ strncpy(title, xml + *pos, len);
+ *pos += len;
+ return title;
}
static char *getvalue(char *xml, int *pos)
{
- int len, i;
- for (i = *pos, len = 0; xml[i] != '<'; ++i, ++len) ;
- char *value = calloc(len + 1, sizeof(char));
- strncpy(value, xml + *pos, len);
- *pos += len - 1;
- return value;
+ int len, i;
+ for (i = *pos, len = 0; xml[i] != '<' && i < strlen(xml); ++i, ++len)
+ ;
+ if (i >= strlen(xml))
+ return NULL;
+ char *value = calloc(len + 1, sizeof(char));
+ strncpy(value, xml + *pos, len);
+ *pos += len - 1;
+ return value;
+}
+
+static attr_t *getattrs(char *parsed, char **tag, int *n_attrs)
+{
+ attr_t *attrs;
+ char *iter = strtok(parsed, " ");
+ *tag = calloc(strlen(iter) + 1, sizeof(char));
+ strcpy(*tag, iter);
+
+ if ((iter = strtok(NULL, " ")))
+ attrs = calloc((*n_attrs = 1), sizeof(attr_t));
+ else {
+ free(parsed);
+ return NULL;
+ }
+
+ int pos = 0;
+ do {
+ if (!iter)
+ break;
+ int i, len = strlen(iter);
+ for (i = 0; i < len && iter[i] != '='; ++i)
+ ;
+ if (i >= len ||
+ (iter[i] == '=' && i >= len - 1) ||
+ (iter[i + 1] != '\'' && iter[i + 1] != '"')) {
+ free(parsed);
+ free(attrs);
+ return NULL;
+ }
+
+ char *name = calloc(i + 1, sizeof(char));
+ char *value = calloc(len - i, sizeof(char));
+ strncpy(name, iter, i);
+ strcpy(value, iter + i + 1);
+ memmove(value, value + 1, strlen(value) - 1);
+ value[strlen(value) - 2] = '\0';
+ if (pos >= *n_attrs)
+ attrs = realloc(attrs, (*n_attrs *= 2) * sizeof(attr_t));
+ attrs[pos].id = name;
+ attrs[pos++].value = value;
+ } while((iter = strtok(NULL, " ")));
+
+ *n_attrs = pos;
+ free(parsed);
+ return attrs;
}
diff --git a/src/include/xml/xml.h b/src/include/xml/xml.h
index d64c61b..ff64796 100644
--- a/src/include/xml/xml.h
+++ b/src/include/xml/xml.h
@@ -25,5 +25,7 @@ map_t *decode(char *xml, int *pos, int *len);
/* encode: encodes the provided map_t into a xml statement */
char *encode(map_t *map, int len);
+/* freemap: frees a map and its children */
+void freemap(map_t *map);
#endif
diff --git a/src/test.c b/src/test.c
index 9c9492c..6a99e2a 100644
--- a/src/test.c
+++ b/src/test.c
@@ -7,299 +7,304 @@
void test_writedb(void)
{
- tablist_t *list = readdb("dbs/test.db");
- writedb("dbs/test.db", list);
- delkeys(list, -1, NULL, 0);
- free(list);
+ tablist_t *list = readdb("dbs/test.db");
+ writedb("dbs/test.db", list);
+ delkeys(list, -1, NULL, 0);
+ free(list);
}
void test_readdb(void)
{
- tablist_t *list = readdb("dbs/test.db");
- tablist_t *indices = getkeys(list, -1, NULL, 0);
- for (int i = 0; i < indices[0].len; ++i) {
- printf("id: %d\n", i);
- for (int j = 0; indices[i].tab[j].flag; ++j)
- printf("%s\n", indices[i].tab[j].key);
- }
- free(indices);
- delkeys(list, -1, NULL, 0);
- free(list);
+ tablist_t *list = readdb("dbs/test.db");
+ tablist_t *indices = getkeys(list, -1, NULL, 0);
+ for (int i = 0; i < indices[0].len; ++i) {
+ printf("id: %d\n", i);
+ for (int j = 0; indices[i].tab[j].flag; ++j)
+ printf("%s\n", indices[i].tab[j].key);
+ }
+ free(indices);
+ delkeys(list, -1, NULL, 0);
+ free(list);
}
void test_setkeys(void)
{
- tablist_t *list = readdb("dbs/test.db");
- char *pairs[] = { "name:John" };
- if (setkeys(&list, -1, pairs, 1)) {
- fprintf(stderr, "test_setkeys: failed\n");
- return;
- }
- for (int i = 0; i < list[0].len; ++i) {
- printf("id: %d\n", i);
- tablist_t *indexes = getkeys(list, i, NULL, 0);
- for (int j = 0; indexes[0].tab[j].flag; ++j)
- printf("%s\n", indexes[0].tab[j].key);
- free(indexes);
- }
- delkeys(list, -1, NULL, 0);
- free(list);
+ tablist_t *list = readdb("dbs/test.db");
+ char *pairs[] = { "name:John" };
+ if (setkeys(&list, -1, pairs, 1)) {
+ fprintf(stderr, "test_setkeys: failed\n");
+ return;
+ }
+ for (int i = 0; i < list[0].len; ++i) {
+ printf("id: %d\n", i);
+ tablist_t *indexes = getkeys(list, i, NULL, 0);
+ for (int j = 0; indexes[0].tab[j].flag; ++j)
+ printf("%s\n", indexes[0].tab[j].key);
+ free(indexes);
+ }
+ delkeys(list, -1, NULL, 0);
+ free(list);
}
void test_setkeys_fail(void)
{
- tablist_t *list = readdb("dbs/test.db");
- char *pairs[] = { "namejohn" };
- if (!setkeys(&list, -1, pairs, 1)) {
- fprintf(stderr, "test_setkeys_fail: failed\n");
- return;
- }
- delkeys(list, -1, NULL, 0);
- free(list);
+ tablist_t *list = readdb("dbs/test.db");
+ char *pairs[] = { "namejohn" };
+ if (!setkeys(&list, -1, pairs, 1)) {
+ fprintf(stderr, "test_setkeys_fail: failed\n");
+ return;
+ }
+ delkeys(list, -1, NULL, 0);
+ free(list);
}
void test_setkeys_multi_fail(void)
{
- tablist_t *list = readdb("dbs/test.db");
- char *pairs[] = { "name:John", NULL };
- if (!setkeys(&list, -1, pairs, 2)) {
- fprintf(stderr, "test_setkeys_multi_fail: failed\n");
- return;
- }
- delkeys(list, -1, NULL, 0);
- free(list);
+ tablist_t *list = readdb("dbs/test.db");
+ char *pairs[] = { "name:John", NULL };
+ if (!setkeys(&list, -1, pairs, 2)) {
+ fprintf(stderr, "test_setkeys_multi_fail: failed\n");
+ return;
+ }
+ delkeys(list, -1, NULL, 0);
+ free(list);
}
void test_setkeys_single(void)
{
- tablist_t *list = readdb("dbs/test.db");
- char *pairs[] = { "name:Alice" };
- if (setkeys(&list, 101, pairs, 1)) {
- fprintf(stderr, "test_setkeys_single: failed\n");
- return;
- }
- delkeys(list, -1, NULL, 0);
- free(list);
+ tablist_t *list = readdb("dbs/test.db");
+ char *pairs[] = { "name:Alice" };
+ if (setkeys(&list, 101, pairs, 1)) {
+ fprintf(stderr, "test_setkeys_single: failed\n");
+ return;
+ }
+ delkeys(list, -1, NULL, 0);
+ free(list);
}
void test_setkeys_multipairs(void)
{
- tablist_t *list = readdb("dbs/test.db");
- char *pairs[] = { "name:Bob", "active:true" };
- if (setkeys(&list, 0, pairs, 2)) {
- fprintf(stderr, "test_setkeys_multipairs: failed\n");
- return;
- }
- delkeys(list, -1, NULL, 0);
- free(list);
+ tablist_t *list = readdb("dbs/test.db");
+ char *pairs[] = { "name:Bob", "active:true" };
+ if (setkeys(&list, 0, pairs, 2)) {
+ fprintf(stderr, "test_setkeys_multipairs: failed\n");
+ return;
+ }
+ delkeys(list, -1, NULL, 0);
+ free(list);
}
void test_delkeys(void)
{
- tablist_t *list = readdb("dbs/test.db");
- char *keys[] = { "Row_1" };
- if (delkeys(list, -1, keys, 1)) {
- fprintf(stderr, "test_delkeys: failed\n");
- return;
- }
- for (int i = 0; i < list[0].len; ++i) {
- printf("id: %d\n", i);
- tablist_t *indexes = getkeys(list, i, NULL, 0);
- for (int j = 0; indexes[0].tab[j].flag; ++j)
- printf("%s\n", indexes[0].tab[j].key);
- free(indexes);
- }
- delkeys(list, -1, NULL, 0);
- free(list);
+ tablist_t *list = readdb("dbs/test.db");
+ char *keys[] = { "Row_1" };
+ if (delkeys(list, -1, keys, 1)) {
+ fprintf(stderr, "test_delkeys: failed\n");
+ return;
+ }
+ for (int i = 0; i < list[0].len; ++i) {
+ printf("id: %d\n", i);
+ tablist_t *indexes = getkeys(list, i, NULL, 0);
+ for (int j = 0; indexes[0].tab[j].flag; ++j)
+ printf("%s\n", indexes[0].tab[j].key);
+ free(indexes);
+ }
+ delkeys(list, -1, NULL, 0);
+ free(list);
}
void test_delkeys_all(void)
{
- tablist_t *list = readdb("dbs/test.db");
- if (delkeys(list, -1, NULL, 0)) {
- fprintf(stderr, "test_delkeys_all: failed\n");
- return;
- }
- free(list);
+ tablist_t *list = readdb("dbs/test.db");
+ if (delkeys(list, -1, NULL, 0)) {
+ fprintf(stderr, "test_delkeys_all: failed\n");
+ return;
+ }
+ free(list);
}
void test_delkeys_fail(void)
{
- tablist_t *list = readdb("dbs/test.db");
- char *keys[] = { "Row_4" };
- if (!delkeys(list, -1, keys, 1)) {
- fprintf(stderr, "test_delkeys_fail: failed\n");
- return;
- }
- delkeys(list, -1, NULL, 0);
- free(list);
+ tablist_t *list = readdb("dbs/test.db");
+ char *keys[] = { "Row_4" };
+ if (!delkeys(list, -1, keys, 1)) {
+ fprintf(stderr, "test_delkeys_fail: failed\n");
+ return;
+ }
+ delkeys(list, -1, NULL, 0);
+ free(list);
}
void test_delkeys_single(void)
{
- tablist_t *list = readdb("dbs/test.db");
- if (delkeys(list, 0, NULL, 0)) {
- fprintf(stderr, "test_delkeys_single: failed\n");
- return;
- }
- delkeys(list, -1, NULL, 0);
- free(list);
+ tablist_t *list = readdb("dbs/test.db");
+ if (delkeys(list, 0, NULL, 0)) {
+ fprintf(stderr, "test_delkeys_single: failed\n");
+ return;
+ }
+ delkeys(list, -1, NULL, 0);
+ free(list);
}
void test_delkeys_multi(void)
{
- tablist_t *list = readdb("dbs/test.db");
- char *keys[] = { "Row_1", "Row_2" };
- if (delkeys(list, -1, keys, 2)) {
- fprintf(stderr, "test_delkeys_multi: failed\n");
- return;
- }
- delkeys(list, -1, NULL, 0);
- free(list);
+ tablist_t *list = readdb("dbs/test.db");
+ char *keys[] = { "Row_1", "Row_2" };
+ if (delkeys(list, -1, keys, 2)) {
+ fprintf(stderr, "test_delkeys_multi: failed\n");
+ return;
+ }
+ delkeys(list, -1, NULL, 0);
+ free(list);
}
void test_getkeys_multi(void)
{
- tablist_t *list = readdb("dbs/test.db");
- char *keys[] = { "Row_1", "Row_2" };
- tablist_t *ret = getkeys(list, 0, keys, 2);
- if (ret == NULL) {
- fprintf(stderr, "test_getkeys_multi: failed\n");
- return;
- }
- for (int i = 0; ret[0].tab[i].flag; ++i)
- printf("%s\n", ret[0].tab[i].key);
- free(ret);
- delkeys(list, -1, NULL, 0);
- free(list);
+ tablist_t *list = readdb("dbs/test.db");
+ char *keys[] = { "Row_1", "Row_2" };
+ tablist_t *ret = getkeys(list, 0, keys, 2);
+ if (ret == NULL) {
+ fprintf(stderr, "test_getkeys_multi: failed\n");
+ return;
+ }
+ for (int i = 0; ret[0].tab[i].flag; ++i)
+ printf("%s\n", ret[0].tab[i].key);
+ free(ret);
+ delkeys(list, -1, NULL, 0);
+ free(list);
}
void test_getkeys_multi_fail(void)
{
- tablist_t *list = readdb("dbs/test.db");
- char *keys[] = { "Row_1", "Row_4" };
- tablist_t *ret = getkeys(list, 0, keys, 2);
- if (ret) {
- fprintf(stderr, "test_getkeys_multi_fail: failed\n");
- return;
- }
- delkeys(list, -1, NULL, 0);
- free(list);
+ tablist_t *list = readdb("dbs/test.db");
+ char *keys[] = { "Row_1", "Row_4" };
+ tablist_t *ret = getkeys(list, 0, keys, 2);
+ if (ret) {
+ fprintf(stderr, "test_getkeys_multi_fail: failed\n");
+ return;
+ }
+ delkeys(list, -1, NULL, 0);
+ free(list);
}
void test_getkeys(void)
{
- tablist_t *list = readdb("dbs/test.db");
- tablist_t *ret = getkeys(list, -1, NULL, 0);
- if (!ret) {
- fprintf(stderr, "test_getkeys: failed\n");
- return;
- }
- free(ret);
- delkeys(list, -1, NULL, 0);
- free(list);
+ tablist_t *list = readdb("dbs/test.db");
+ tablist_t *ret = getkeys(list, -1, NULL, 0);
+ if (!ret) {
+ fprintf(stderr, "test_getkeys: failed\n");
+ return;
+ }
+ free(ret);
+ delkeys(list, -1, NULL, 0);
+ free(list);
}
void test_encode(void)
{
- map_t *map = calloc(1, sizeof(map_t));
- map->attrs = NULL;
- map->n_attrs = 0;
- map->tag = "documents";
- map->size = sizeof(map_t);
- map->n = 2;
- map->payload = (map_t []) {
- {
- .attrs = (attr_t []) {
- { .id = "id", .value = "0" }
- },
- .n_attrs = 1,
- .tag = "document",
- .payload = (map_t []) {
- {
- .attrs = NULL,
- .n_attrs = 0,
- .tag = "test",
- .payload = "test",
- .size = sizeof(char),
- .n = 4
- }
- },
- .size = sizeof(map_t),
- .n = 1
- },
- {
- .attrs = (attr_t []) {
- { .id = "id", .value = "1" }
- },
- .n_attrs = 1,
- .tag = "document",
- .payload = (map_t []) {
- {
- .attrs = NULL,
- .n_attrs = 0,
- .tag = "test",
- .payload = "test",
- .size = sizeof(char),
- .n = 4
- }
- },
- .size = sizeof(map_t),
- .n = 1
- }
- };
+ map_t *map = calloc(1, sizeof(map_t));
+ map->attrs = NULL;
+ map->n_attrs = 0;
+ map->tag = "documents";
+ map->size = sizeof(map_t);
+ map->n = 2;
+ map->payload = (map_t []) {
+ {
+ .attrs = (attr_t []) {
+ { .id = "id", .value = "0" }
+ },
+ .n_attrs = 1,
+ .tag = "document",
+ .payload = (map_t []) {
+ {
+ .attrs = NULL,
+ .n_attrs = 0,
+ .tag = "test",
+ .payload = "test",
+ .size = sizeof(char),
+ .n = 4
+ }
+ },
+ .size = sizeof(map_t),
+ .n = 1
+ },
+ {
+ .attrs = (attr_t []) {
+ { .id = "id", .value = "1" }
+ },
+ .n_attrs = 1,
+ .tag = "document",
+ .payload = (map_t []) {
+ {
+ .attrs = NULL,
+ .n_attrs = 0,
+ .tag = "test",
+ .payload = "test",
+ .size = sizeof(char),
+ .n = 4
+ }
+ },
+ .size = sizeof(map_t),
+ .n = 1
+ }
+ };
- char *xml = encode(map, 1);
- if (xml == NULL) {
- fprintf(stderr, "test_encode: failed\n");
- return;
- }
- printf("%s\n", xml);
- free(map);
- free(xml);
+ char *xml = encode(map, 1);
+ if (xml == NULL) {
+ fprintf(stderr, "test_encode: failed\n");
+ return;
+ }
+ printf("%s\n", xml);
+ free(map);
+ free(xml);
}
void test_decode(void)
{
- char *xml =
- "<set><key1>value1</key1><key2>value2</key2></set>";
- int len = 0, start = 0;
- map_t *map = decode(xml, &start, &len);
- printf("%s\n", (xml = encode(map, 1)));
- free(xml);
- // TODO: create a freemap function
- free(map->tag);
- map_t *pl = (map_t *) map->payload;
- free(pl[0].tag);
- free(pl[1].tag);
- free(pl[0].payload);
- free(pl[1].payload);
- free(map->payload);
- free(map);
+ char *xml =
+ "<set id='0' test='true'><key1>value1</key1><key2>value2</key2></set>";
+ int len = 0, start = 0;
+ map_t *map = decode(xml, &start, &len);
+ printf("%s\n", (xml = encode(map, 1)));
+ free(xml);
+ // TODO: create a freemap function
+ free(map->tag);
+ free(map->attrs[0].id);
+ free(map->attrs[0].value);
+ free(map->attrs[1].id);
+ free(map->attrs[1].value);
+ free(map->attrs);
+ map_t *pl = (map_t *) map->payload;
+ free(pl[0].tag);
+ free(pl[1].tag);
+ free(pl[0].payload);
+ free(pl[1].payload);
+ free(map->payload);
+ free(map);
}
int main(void)
{
- // test_writedb();
- // test_readdb();
- // test_getkeys();
- // test_getkeys_multi();
- // test_getkeys_multi_fail();
- //
- // test_setkeys();
- // test_setkeys_fail();
- // test_setkeys_single();
- // test_setkeys_multipairs();
- // test_setkeys_multi_fail();
- //
- // test_delkeys();
- // test_delkeys_all();
- // test_delkeys_fail();
- // test_delkeys_single();
- // test_delkeys_multi();
- test_encode();
- test_decode();
+ // test_writedb();
+ // test_readdb();
+ // test_getkeys();
+ // test_getkeys_multi();
+ // test_getkeys_multi_fail();
+ //
+ // test_setkeys();
+ // test_setkeys_fail();
+ // test_setkeys_single();
+ // test_setkeys_multipairs();
+ // test_setkeys_multi_fail();
+ //
+ // test_delkeys();
+ // test_delkeys_all();
+ // test_delkeys_fail();
+ // test_delkeys_single();
+ // test_delkeys_multi();
+ test_encode();
+ test_decode();
- exit(0);
+ exit(0);
}