summaryrefslogtreecommitdiff
path: root/src/include
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 /src/include
parente99a79f1499b6cfb60007587ebeda645c32d38dc (diff)
Added attribute parsing to decoder
Diffstat (limited to 'src/include')
-rw-r--r--src/include/xml/decode.c162
-rw-r--r--src/include/xml/xml.h2
2 files changed, 111 insertions, 53 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