123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679 |
- #include <stdlib.h>
- #include <string.h>
- #include <ctype.h>
- #include "bxml.h"
- #include "ses.h"
- #define BXML_WS " \t\n\r"
- /* Strdup isn't ANSI C, just posix... :p so we need our own local version.*/
- static char * bxml_strdup(const char *str) {
- char * res = malloc(strlen(str) + 1);
- if(res) { strcpy(res, str); }
- return res;
- }
- /* Strdup isn't ANSI C, just posix... :p so we need our own local version.*/
- static char * bxml_strdup_size(const char *str, int size) {
- char * res = malloc(size + 1);
- if(res) {
- if (size < 0) {
- size = strlen(str);
- }
- strncpy(res, str, (size_t) size);
- res[size] = '\0';
- }
- return res;
- }
- /* Initializes a bxml attributes, sets no relationships! */
- BxmlAttribute *
- bxmlattribute_init_size(BxmlAttribute * me, char * name, int namesize, char * value, int valuesize) {
- if (!me) return NULL;
- me->name = bxml_strdup_size(name, namesize);
- if (!me->name) return NULL;
- me->value = bxml_strdup_size(value, valuesize);
- if (!me->value) {
- free(me->name);
- me->name = NULL;
- return NULL;
- }
- me->next = NULL;
- return me;
- }
- /* Initializes a bxml attributes, sets no relationships! */
- BxmlAttribute *
- bxmlattribute_init(BxmlAttribute * me, char * name, char * value) {
- return bxmlattribute_init_size(me, name, -1, value, -1);
- }
- /* Sets the value of an attribute. */
- BxmlAttribute * bxmlattribute_set_value_size(BxmlAttribute * me, char * value, int size) {
- if (!me) return NULL;
- free(me->value);
- me->value = bxml_strdup_size(value, size);
- if (!me->value) return NULL;
- return me;
- }
- BxmlAttribute * bxmlattribute_set_value(BxmlAttribute * me, char * value) {
- return bxmlattribute_set_value_size(me, value, -1);
- }
- /* Cleans up an attribute. Does nothing with linked attributes! */
- void bxmlattribute_done(BxmlAttribute * me) {
- if (!me) return;
- free(me->value);
- free(me->name);
- me->value = NULL;
- me->name = NULL;
- me->next = NULL;
- }
- /* Frees a bxmlattribute without doing anything to apotential next one. */
- void bxmlattribute_free_one(BxmlAttribute * me) {
- bxmlattribute_done(me);
- free(me);
- }
- /* Frees a linked list of bxml attributes */
- void bxmlattribute_free_list(BxmlAttribute * me) {
- BxmlAttribute * now, * aid;
- now = me;
- while (now) {
- aid = now->next;
- bxmlattribute_free_one(now);
- now = aid;
- }
- }
- /* Allocates a new bxmlattibute */
- BxmlAttribute * bxmlattribute_alloc(void) {
- return calloc(sizeof(BxmlAttribute), 1);
- }
- BxmlAttribute * bxmlattribute_new_size(char * name, int namesize, char * value, int valuesize) {
- return bxmlattribute_init_size(bxmlattribute_alloc(), name, namesize, value, valuesize);
- }
- BxmlAttribute * bxmlattribute_new(char * name, char * value) {
- return bxmlattribute_init(bxmlattribute_alloc(), name, value);
- }
- /* Appends or insterts an existing attribute to the list at me.
- * returns you on sucess or NULL on failure. */
- BxmlAttribute * bxmlattribute_insert(BxmlAttribute * me, BxmlAttribute * you) {
- BxmlAttribute * aid;
- if (!me) return NULL;
- if (!you) return NULL;
- aid = me->next;
- me->next = you;
- you->next = aid;
- return you;
- }
- /* Inserts a new attribute to the list after me. */
- BxmlAttribute *
- bxmlattribute_insert_new(BxmlAttribute * me, char * name, char * value) {
- return bxmlattribute_insert(me, bxmlattribute_new(name, value));
- }
- /* Inserts a new attribute to the list after me. */
- BxmlAttribute *
- bxmlattribute_insert_new_size(BxmlAttribute * me, char * name, int namesize, char * value, int valuesize) {
- return bxmlattribute_insert(me, bxmlattribute_new_size(name, namesize, value, valuesize));
- }
- /* Initializes a Bxml me. Does not set up any relationships nor
- * call strdup! */
- Bxml * bxml_init_all(Bxml * me, int kind, char * name, char * text) {
- if(!me) return NULL;
- me->parent = NULL;
- me->sibling = NULL;
- me->child = NULL;
- me->attributes = NULL;
- me->kind = kind;
- me->name = name;
- me->text = text;
- return me;
- }
- /* Initializes a bxml me based on it's kind. */
- Bxml * bxml_init_size_va(Bxml * me, int kind, int size, va_list args) {
- char * name = NULL;
- char * text = NULL;
- switch(kind) {
- case BXML_ROOT:
- return bxml_init_all(me, kind, NULL, NULL);
- case BXML_TAG:
- name = bxml_strdup_size(va_arg(args, char *), size);
- if (!name) return NULL;
- return bxml_init_all(me, kind, name, NULL);
- case BXML_TEXT:
- text = bxml_strdup_size(va_arg(args, char *), size);
- if (!text) return NULL;
- return bxml_init_all(me, kind, NULL, text);
- case BXML_COMMENT:
- text = bxml_strdup_size(va_arg(args, char *), size);
- if (!text) return NULL;
- return bxml_init_all(me, kind, NULL, text);
- default:
- return NULL;
- }
- }
- /* Initializes a bxml me based on it's kind. */
- Bxml * bxml_init_va(Bxml * me, int kind, va_list args) {
- return bxml_init_size_va(me, kind, -1, args);
- }
-
-
- /* Allocates a new Bxml node */
- Bxml * bxml_alloc() {
- return calloc(sizeof(Bxml), 1);
- }
- /* Allocates and initialzes a new Bxml node. */
- Bxml * bxml_new_size_va(int kind, int size, va_list args) {
- return bxml_init_size_va(bxml_alloc(), kind, size, args);
- }
- /* Allocates and initialzes a new Bxml node. */
- Bxml * bxml_new_va(int kind, va_list args) {
- return bxml_init_size_va(bxml_alloc(), kind, -1, args);
- }
- /** Appends text to the text of this tag */
- Bxml * bxml_append_buf(Bxml * me, char * buf, int bufsize) {
- if (!me->text) {
- me->text = bxml_strdup_size(buf, bufsize);
- if (!me->text) return NULL;
- } else {
- int oldsize = strlen(me->text);
- me->text = realloc(me->text, oldsize + bufsize + 1);
- strncpy(me->text + oldsize, buf, bufsize);
- me->text[oldsize+bufsize] = '\0';
- }
- return me;
- }
- /* Removes a child from parent. Does NOT free it, but returns it on success,
- * or NULL if no such child. Comparison is by address. */
- Bxml * bxml_remove_child(Bxml * parent, Bxml * child) {
- Bxml * index, * previous;
- /* First child as special case. */
- if (parent->child == child) {
- parent->child = parent->child->sibling;
- return child;
- }
-
- for (index = parent->child; index; index = index->sibling) {
- /* next up is the child... */
- if (index->sibling == child) {
- /* cut it from the linked list */
- index->sibling = index->sibling->sibling;
- return child;
- }
- }
- return NULL;
- }
-
- /* Merges two text tags and returns a newly allocated
- * test tag on success, or NULL on failure.
- */
- Bxml * bxml_merge_text(Bxml * text1, Bxml * text2) {
- Swis buffer;
- Bxml * result;
- if (!text1) return NULL;
- if (!text2) return NULL;
- if (text1->kind != BXML_TEXT) return NULL;
- if (text2->kind != BXML_TEXT) return NULL;
-
- if (!swis_init_cstr(&buffer, text1->text)) return NULL;
-
- if (!swis_append_cstr(&buffer, text2->text)) {
- swis_free(&buffer);
- return NULL;
- }
-
- result = bxml_new_size(BXML_TEXT, buffer.size, buffer.text);
- swis_free(&buffer);
- return result;
- }
- /* Merges two adjacent text tag, frees them and replaces them by the
- * merged tag.
- */
- Bxml * bxml_merge_adjacent_text(Bxml * text1, Bxml * text2) {
- Bxml * parent;
- Bxml * merged = bxml_merge_text(text1, text2);
- if (!merged) return NULL;
- parent = text1->parent;
- bxml_remove_child(parent, text1);
- bxml_free(text1);
- bxml_remove_child(parent, text2);
- bxml_free(text2);
- bxml_add_child(parent, merged);
- return merged;
- }
-
- /* Allocates and initialzes a new Bxml node. */
- Bxml * bxml_new(int kind, ...) {
- Bxml * result;
- va_list args;
- va_start(args, kind);
- result = bxml_new_va(kind, args);
- va_end(args);
- return result;
- }
- /* Allocates and initialzes a new Bxml node. */
- Bxml * bxml_new_size(int kind, int size, ...) {
- Bxml * result;
- va_list args;
- va_start(args, size);
- result = bxml_new_size_va(kind, size, args);
- va_end(args);
- return result;
- }
- /* Cleans up a Bxml node, freeing the children recursively. */
- Bxml * bxml_done(Bxml * me) {
- Bxml * aid = me->child;
- Bxml * next = NULL;
- while(aid) {
- next = aid->sibling; // get next, since aid will be destroyed.
- bxml_free(aid); // free first child
- aid = next; // move to next child.
- }
- bxmlattribute_free_list(me->attributes);
- free(me->name);
- free(me->text);
- return me;
- }
- /* Frees this node and cleans up its children recursively. returns NULL. */
- Bxml * bxml_free(Bxml * me) {
- if(!me) return NULL;
- bxml_done(me);
- free(me);
- return NULL;
- }
- /* Sets node siling to be the sibling node of this node, possibly inserting
- * between an existing sibling.
- * returns you if OK, NULL on error.
- **/
- Bxml * bxml_add_sibling(Bxml * me, Bxml * you) {
- Bxml * old_sibling;
- if(!me) return NULL;
- if(!you) return NULL;
- old_sibling = me->sibling;
- /* Ensure proper insertion. */
- you->sibling = old_sibling;
- me->sibling = you;
- return you;
- }
- /* Gets the last sibing of me, or NULL if no sibling. */
- Bxml * bxml_get_last_sibling(Bxml * me) {
- Bxml * aid;
- if (!me) return NULL;
- for (aid = me; aid->sibling ; aid = aid->sibling);
- return aid;
- }
- /* Adds a sibling to me, at the end of the sibling list. */
- Bxml * bxml_append_sibling(Bxml * me, Bxml * you) {
- Bxml * index;
- if (!me) return NULL;
- if (!you) return NULL;
- return bxml_add_sibling(bxml_get_last_sibling(me), you);
- }
- /* Returns the pos-th sibling of me */
- Bxml * bxml_get_sibling_at(Bxml * me, int pos) {
- int index = 0;
- Bxml * aid;
- if (!me) return NULL;
- for (aid = me; aid; aid = aid->sibling) {
- if (index == pos) return aid;
- index++;
- }
- return NULL;
- }
- /* Returns the pos-th child of me */
- Bxml * bxml_get_child_at(Bxml * me, int pos) {
- if (!me) return NULL;
- return bxml_get_sibling_at(me->child, pos);
- }
- /* Gets the last sibing of me, or NULL if no sibling. */
- Bxml * bxml_get_last_child(Bxml * me) {
- Bxml * aid;
- if (!me) return NULL;
- if (!me->child) return NULL;
- return bxml_get_last_sibling(me->child);
- }
- /* Adds attr as an attribute to the Bxml tag me.
- * Returns you if ok, NULL on error.
- */
- BxmlAttribute * bxml_add_attribute(Bxml * me, BxmlAttribute * you) {
- Bxml * oldnext;
- if (!me) return NULL;
- if (!you) return NULL;
-
- if (!me->last_attr) {
- me->attributes = you;
- me->last_attr = you;
- } else {
- bxmlattribute_insert(me->last_attr, you);
- }
- return you;
- }
- /** Makes a new attribute and adds it to me. */
- BxmlAttribute * bxml_new_attribute_size(Bxml * me, char * name, int namesize, char * value, int valuesize) {
- return bxml_add_attribute(me, bxmlattribute_new_size(name, namesize, value, valuesize));
- }
- /** Makes a new attribute and adds it to me. */
- BxmlAttribute * bxml_new_attribute(Bxml * me, char * name, char * value) {
- return bxml_add_attribute(me, bxmlattribute_new(name, value));
- }
- /** Gets the attribute of me with the given name, or NULL if no such attribute. */
- BxmlAttribute * bxml_get_attribute_pointer(Bxml * me, char * name) {
- BxmlAttribute * index;
- for(index = me->attributes; index ; index = index->next) {
- if (strcmp(name, index->name) == 0) {
- return index;
- }
- }
- return NULL;
- }
- /** Gets the value of the attribute of me with the given name, or NULL if no
- * such attribute. */
- char * bxml_get_attribute(Bxml * me, char * name) {
- BxmlAttribute * result;
- result = bxml_get_attribute_pointer(me, name);
- return result ? result->value : NULL;
- }
- /** Sets the attribute value of the given name. If the attribte already existed,
- * it will be overwritten, otherwise it will be made new. */
- BxmlAttribute * bxml_set_attribute(Bxml * me, char * name, char * value) {
- BxmlAttribute * attribute;
- attribute = bxml_get_attribute_pointer(me, name);
- if (attribute) {
- return bxmlattribute_set_value(attribute, value);
- }
- return bxml_new_attribute(me, name, value);
- }
- /* Adds child as a child node of the Bxml tag me.
- * Ensures that any siblings are connected correctly as well.
- * Returns child if OK, NULL on error.
- */
- Bxml * bxml_add_child(Bxml * me, Bxml * child) {
- if (!me) return NULL;
- if (!child) return NULL;
- child->parent = me;
-
- if (!me->child) {
- me->child = child;
- return child;
- } else {
- return bxml_append_sibling(me->child, child);
- }
- }
- Bxml * bxml_new_child_size_va(Bxml * me, int kind, int size, va_list args) {
- Bxml * child;
- child = bxml_new_size_va(kind, size, args);
- if (!bxml_add_child(me, child)) {
- bxml_free(child);
- return NULL;
- }
- return child;
- }
- Bxml * bxml_new_child_va(Bxml * me, int kind, va_list args) {
- return bxml_new_child_size_va(me, kind, -1, args);
- }
- /* Adds a new child initialized depending on kind.
- * Text nodes should pass the text of the node,
- * tags should pass the name of the tag.
- */
- Bxml * bxml_new_child_size(Bxml * me, int kind, int size, ...) {
- Bxml * result;
- va_list args;
- va_start(args, size);
- result = bxml_new_child_size_va(me, kind, size, args);
- va_end(args);
- return result;
- }
- /* Adds a new child initialized depending on kind.
- * Text nodes should pass the text of the node,
- * tags should pass the name of the tag.
- */
- Bxml * bxml_new_child(Bxml * me, int kind, ...) {
- Bxml * result;
- va_list args;
- va_start(args, kind);
- result = bxml_new_child_va(me, kind, args);
- va_end(args);
- return result;
- }
- /**
- * xml_print_element_names:
- * @a_node: the initial xml node to consider.
- *
- * Prints the names of the all the xml elements
- * that are siblings or children of a given xml node.
- */
- void bxml_print_element_names(Bxml * node) {
- Bxml * now = NULL;
- static int level = 0;
- for (now = node; now; now = now->sibling) {
- if (now->kind == BXML_TAG) {
- printf("node type: Element, %d, name: %s\n", level, now->name);
- } else {
- printf("node type: %d, %d, name: %s\n", node->kind, level, now->name);
- }
- level++;
- bxml_print_element_names(now->child);
- level--;
- }
- }
- /**
- * bxml_print_all_attributes: a debugging function to print all xml attributes
- */
- void bxml_print_all_attributes(Bxml * node) {
- BxmlAttribute * attr;
- printf("Node a%s attributes:", node->name);
- for(attr = node->attributes ; attr ; attr = attr->next) {
- printf(" %s=%s", attr->name, attr->value);
- }
- puts("");
- }
- int bxml_kind_is(Bxml * me, int kind) {
- if (!me) return 0;
- if (kind < 1) return !0;
- return (me->kind == kind);
- }
- int bxml_name_is(Bxml * me, char * name) {
- if (!name) return !0;
- if (!me) return 0;
- if (!me->name) return 0;
- return (strcmp(me->name, name) == 0);
- }
- int bxml_match_name_and_kind(Bxml * me, char * name, int kind) {
- return (bxml_kind_is(me, kind) && bxml_name_is(me, name));
- }
- /** Finds a sibling node. If name is not null
- or type is strictly positive, return matching nodes.
- Also searches node itself, so pass node->next if you don't want that.*/
- Bxml * bxml_find_next_kind(Bxml * node, const char * name, int kind) {
- Bxml * now;
- for (now = node; now; now = now->sibling) {
- if (bxml_match_name_and_kind(now, (char *)name, kind)) {
- return now;
- }
- }
- return NULL;
- }
- /** Shorthand for bxml_find_next_type(node, name, BXML_TAG */
- Bxml * bxml_find_next(Bxml * node, const char * name) {
- return bxml_find_next_kind(node, name, BXML_TAG);
- }
- /** Nonrecursively finds a BXML child node with the given name,
- * and kind including self. */
- Bxml * bxml_find_child_kind(Bxml * node, const char * name, int kind) {
- if (!node) return NULL;
- return bxml_find_next_kind(node->child, name, kind);
- }
- /** Nonrecursively finds a BXML child node with the given name, including self. */
- Bxml * bxml_find_child(Bxml * node, const char * name) {
- return bxml_find_child_kind(node, name, BXML_TAG);
- }
- /** Finds a child node with the given paths, pass null as last one */
- Bxml * bxml_find_child_deep_va(Bxml * node, va_list args) {
- const char * name = NULL;
- Bxml * res = NULL;
- Bxml * aid = node;
- for(name = va_arg(args, const char *); name && aid;
- name = va_arg(args, const char *)) {
- aid = bxml_find_child(aid, name);
- }
- res = aid;
- return res;
- }
- /** Finds a child node with the given paths, pass null as last one */
- Bxml * bxml_find_child_deep(Bxml * node, ...) {
- Bxml * result;
- va_list args;
- va_start(args, node);
- result = bxml_find_child_deep_va(node, args);
- va_end(args);
- return result;
- }
- /** Gets an integer property from the node and stores it into result,
- * returns result if ok, NULL if not a correct integer */
- long * bxml_get_attribute_long(Bxml * node, char * name, long * result) {
- long aid;
- char * prop = bxml_get_attribute(node, name);
- if (!prop) return false;
- errno = 0;
- aid = strtol(prop, NULL, 10);
- if (errno) { return NULL; }
- (*result) = aid;
- return result;
- }
- /** Gets an double property from the node and stores it into result,
- * returns result if ok, NULL if not a correct integer */
- double * bxml_get_attribute_double(Bxml * node, char * name, double * result) {
- double aid;
- char * prop = bxml_get_attribute(node, name);
- if (!prop) return false;
- errno = 0;
- aid = strtod(prop, NULL);
- if (errno) { return NULL; }
- (*result) = aid;
- return result;
- }
- /* Returns a reference to the first text node child of node */
- Bxml * bxml_get_text_tag_under(Bxml * node) {
- return bxml_find_child_kind(node, NULL, BXML_TEXT);
- }
- /** Returns a reference to the (first) text contents of an xml node.
- * this looks in the child node for the text.
- */
- char * bxml_get_text_under(Bxml * node) {
- Bxml * text_tag = bxml_get_text_tag_under(node);
- return text_tag->text;
- }
- /** Recursively outputs a debug rep of xml to file. */
- int bxml_show_to(Bxml * xml, FILE * out, int depth) {
- int index;
- for (index = 0; index < depth; index++) {
- fprintf(out, " ");
- }
- if (xml->kind == BXML_TAG) {
- fprintf(out, ">%s", xml->name);
- } else if (xml->kind == BXML_TEXT) {
- fprintf(out, ">#text: %s", xml->text);
- } else {
- fprintf(out, ">%s: %s", xml->name, xml->text);
- }
-
- if (xml->attributes) {
- BxmlAttribute * nattr = xml->attributes;
- fprintf(out, "(");
- while (nattr) {
- fprintf(out, " %s->%s", nattr->name, nattr->value);
- nattr = nattr->next;
- }
- fprintf(out, " )");
- }
- fprintf(out, "\n");
-
- if (xml->child) {
- bxml_show_to(xml->child, out, depth + 1);
- }
- if (xml->sibling) {
- bxml_show_to(xml->sibling, out, depth);
- }
- return depth;
- }
|