diff options
author | bpc2003 <wpesfriendnva@gmail.com> | 2025-05-18 18:11:14 -0400 |
---|---|---|
committer | bpc2003 <wpesfriendnva@gmail.com> | 2025-05-18 18:11:14 -0400 |
commit | 0575736fd33a60796ce29c0241da2492363fe24d (patch) | |
tree | e4cf4131f1784ac865daeec516bd544875416aea | |
parent | e99a79f1499b6cfb60007587ebeda645c32d38dc (diff) |
Added attribute parsing to decoder
-rw-r--r-- | src/include/xml/decode.c | 162 | ||||
-rw-r--r-- | src/include/xml/xml.h | 2 | ||||
-rw-r--r-- | src/test.c | 453 |
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 @@ -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); } |