diff options
Diffstat (limited to 'pjlib/src/pj/xml.c')
-rw-r--r-- | pjlib/src/pj/xml.c | 784 |
1 files changed, 392 insertions, 392 deletions
diff --git a/pjlib/src/pj/xml.c b/pjlib/src/pj/xml.c index ff3684a8..8dccedec 100644 --- a/pjlib/src/pj/xml.c +++ b/pjlib/src/pj/xml.c @@ -1,392 +1,392 @@ -/* $Header: /pjproject-0.3/pjlib/src/pj/xml.c 9 10/14/05 12:26a Bennylp $ */
-/* $Log: /pjproject-0.3/pjlib/src/pj/xml.c $
- *
- * 9 10/14/05 12:26a Bennylp
- * Finished error code framework, some fixes in ioqueue, etc. Pretty
- * major.
- *
- * 8 9/21/05 1:39p Bennylp
- * Periodic checkin for backup.
- *
- * 7 9/17/05 10:37a Bennylp
- * Major reorganization towards version 0.3.
- *
- */
-#include <pj/xml.h>
-#include <pj/scanner.h>
-#include <pj/except.h>
-#include <pj/pool.h>
-#include <pj/string.h>
-#include <pj/log.h>
-#include <pj/os.h>
-
-#define EX_SYNTAX_ERROR 12
-#define THIS_FILE "xml.c"
-
-static void on_syntax_error(struct pj_scanner *scanner)
-{
- PJ_UNUSED_ARG(scanner);
- PJ_THROW(EX_SYNTAX_ERROR);
-}
-
-static pj_xml_node *alloc_node( pj_pool_t *pool )
-{
- pj_xml_node *node;
-
- node = pj_pool_calloc(pool, 1, sizeof(pj_xml_node));
- pj_list_init( &node->attr_head );
- pj_list_init( &node->node_head );
-
- return node;
-}
-
-static pj_xml_attr *alloc_attr( pj_pool_t *pool )
-{
- return pj_pool_calloc(pool, 1, sizeof(pj_xml_attr));
-}
-
-/* This is a recursive function! */
-static pj_xml_node *xml_parse_node( pj_pool_t *pool, pj_scanner *scanner)
-{
- pj_xml_node *node;
- pj_str_t end_name;
-
- PJ_CHECK_STACK();
-
- if (*scanner->curptr != '<')
- on_syntax_error(scanner);
-
- /* Handle Processing Instructino (PI) construct (i.e. "<?") */
- if (*scanner->curptr == '<' && *(scanner->curptr+1) == '?') {
- pj_scan_advance_n(scanner, 2, PJ_FALSE);
- for (;;) {
- pj_str_t dummy;
- pj_scan_get_until_ch(scanner, '?', &dummy);
- if (*scanner->curptr=='?' && *(scanner->curptr+1)=='>') {
- pj_scan_advance_n(scanner, 2, PJ_TRUE);
- break;
- } else {
- pj_scan_advance_n(scanner, 1, PJ_FALSE);
- }
- }
- return xml_parse_node(pool, scanner);
- }
-
- /* Handle comments construct (i.e. "<!--") */
- if (pj_scan_strcmp(scanner, "<!--", 4) == 0) {
- pj_scan_advance_n(scanner, 4, PJ_FALSE);
- for (;;) {
- pj_str_t dummy;
- pj_scan_get_until_ch(scanner, '-', &dummy);
- if (pj_scan_strcmp(scanner, "-->", 3) == 0) {
- pj_scan_advance_n(scanner, 3, PJ_TRUE);
- break;
- } else {
- pj_scan_advance_n(scanner, 1, PJ_FALSE);
- }
- }
- return xml_parse_node(pool, scanner);
- }
-
- /* Alloc node. */
- node = alloc_node(pool);
-
- /* Get '<' */
- pj_scan_get_char(scanner);
-
- /* Get node name. */
- pj_scan_get_until_chr( scanner, " />\t", &node->name);
-
- /* Get attributes. */
- while (*scanner->curptr != '>' && *scanner->curptr != '/') {
- pj_xml_attr *attr = alloc_attr(pool);
-
- pj_scan_get_until_chr( scanner, "=> \t", &attr->name);
- if (*scanner->curptr == '=') {
- pj_scan_get_char( scanner );
- pj_scan_get_quote(scanner, '"', '"', &attr->value);
- /* remove quote characters */
- ++attr->value.ptr;
- attr->value.slen -= 2;
- }
-
- pj_list_insert_before( &node->attr_head, attr );
- }
-
- if (*scanner->curptr == '/') {
- pj_scan_get_char(scanner);
- if (pj_scan_get_char(scanner) != '>')
- on_syntax_error(scanner);
- return node;
- }
-
- /* Enclosing bracket. */
- if (pj_scan_get_char(scanner) != '>')
- on_syntax_error(scanner);
-
- /* Sub nodes. */
- while (*scanner->curptr == '<' && *(scanner->curptr+1) != '/') {
- pj_xml_node *sub_node = xml_parse_node(pool, scanner);
- pj_list_insert_before( &node->node_head, sub_node );
- }
-
- /* Content. */
- if (!pj_scan_is_eof(scanner) && *scanner->curptr != '<') {
- pj_scan_get_until_ch(scanner, '<', &node->content);
- }
-
- /* Enclosing node. */
- if (pj_scan_get_char(scanner) != '<' || pj_scan_get_char(scanner) != '/')
- on_syntax_error(scanner);
-
- pj_scan_get_until_chr(scanner, " \t>", &end_name);
-
- /* Compare name. */
- if (pj_stricmp(&node->name, &end_name) != 0)
- on_syntax_error(scanner);
-
- /* Enclosing '>' */
- if (pj_scan_get_char(scanner) != '>')
- on_syntax_error(scanner);
-
- return node;
-}
-
-PJ_DEF(pj_xml_node*) pj_xml_parse( pj_pool_t *pool, char *msg, pj_size_t len)
-{
- pj_xml_node *node = NULL;
- pj_scanner scanner;
- PJ_USE_EXCEPTION;
-
- if (!msg || !len || !pool)
- return NULL;
-
- pj_scan_init( &scanner, msg, len,
- PJ_SCAN_AUTOSKIP_WS|PJ_SCAN_AUTOSKIP_NEWLINE,
- &on_syntax_error);
- PJ_TRY {
- node = xml_parse_node(pool, &scanner);
- }
- PJ_DEFAULT {
- PJ_LOG(4,(THIS_FILE, "Syntax error parsing XML in line %d column %d",
- scanner.line, scanner.col));
- }
- PJ_END;
- pj_scan_fini( &scanner );
- return node;
-}
-
-/* This is a recursive function. */
-static int xml_print_node( const pj_xml_node *node, int indent,
- char *buf, pj_size_t len )
-{
- int i;
- char *p = buf;
- pj_xml_attr *attr;
- pj_xml_node *sub_node;
-
-#define SIZE_LEFT() ((int)(len - (p-buf)))
-
- PJ_CHECK_STACK();
-
- /* Print name. */
- if (SIZE_LEFT() < node->name.slen + indent + 5)
- return -1;
- for (i=0; i<indent; ++i)
- *p++ = ' ';
- *p++ = '<';
- pj_memcpy(p, node->name.ptr, node->name.slen);
- p += node->name.slen;
-
- /* Print attributes. */
- attr = node->attr_head.next;
- while (attr != &node->attr_head) {
-
- if (SIZE_LEFT() < attr->name.slen + attr->value.slen + 4)
- return -1;
-
- *p++ = ' ';
-
- /* Attribute name. */
- pj_memcpy(p, attr->name.ptr, attr->name.slen);
- p += attr->name.slen;
-
- /* Attribute value. */
- if (attr->value.slen) {
- *p++ = '=';
- *p++ = '"';
- pj_memcpy(p, attr->value.ptr, attr->value.slen);
- p += attr->value.slen;
- *p++ = '"';
- }
-
- attr = attr->next;
- }
-
- /* Check for empty node. */
- if (node->content.slen==0 &&
- node->node_head.next==(pj_xml_node*)&node->node_head)
- {
- *p++ = ' ';
- *p++ = '/';
- *p++ = '>';
- return p-buf;
- }
-
- /* Enclosing '>' */
- if (SIZE_LEFT() < 1) return -1;
- *p++ = '>';
-
- /* Print sub nodes. */
- sub_node = node->node_head.next;
- while (sub_node != (pj_xml_node*)&node->node_head) {
- int printed;
-
- if (SIZE_LEFT() < indent + 3)
- return -1;
- //*p++ = '\r';
- *p++ = '\n';
-
- printed = xml_print_node(sub_node, indent + 1, p, SIZE_LEFT());
- if (printed < 0)
- return -1;
-
- p += printed;
- sub_node = sub_node->next;
- }
-
- /* Content. */
- if (node->content.slen) {
- if (SIZE_LEFT() < node->content.slen) return -1;
- pj_memcpy(p, node->content.ptr, node->content.slen);
- p += node->content.slen;
- }
-
- /* Enclosing node. */
- if (node->node_head.next != (pj_xml_node*)&node->node_head) {
- if (SIZE_LEFT() < node->name.slen + 5 + indent)
- return -1;
- //*p++ = '\r';
- *p++ = '\n';
- for (i=0; i<indent; ++i)
- *p++ = ' ';
- } else {
- if (SIZE_LEFT() < node->name.slen + 3)
- return -1;
- }
- *p++ = '<';
- *p++ = '/';
- pj_memcpy(p, node->name.ptr, node->name.slen);
- p += node->name.slen;
- *p++ = '>';
-
-#undef SIZE_LEFT
-
- return p - buf;
-}
-
-PJ_DEF(int) pj_xml_print(const pj_xml_node *node, char *buf, pj_size_t len,
- pj_bool_t include_prolog)
-{
- int prolog_len = 0;
- int printed;
-
- if (!node || !buf || !len)
- return 0;
-
- if (include_prolog) {
- pj_str_t prolog = {"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n", 39};
- if ((int)len < prolog.slen)
- return -1;
- pj_memcpy(buf, prolog.ptr, prolog.slen);
- prolog_len = prolog.slen;
- }
-
- printed = xml_print_node(node, 0, buf+prolog_len, len-prolog_len) + prolog_len;
- if (printed > 0 && len-printed >= 1) {
- buf[printed++] = '\n';
- }
- return printed;
-}
-
-
-PJ_DEF(void) pj_xml_add_node( pj_xml_node *parent, pj_xml_node *node )
-{
- pj_list_insert_before(&parent->node_head, node);
-}
-
-PJ_DEF(void) pj_xml_add_attr( pj_xml_node *node, pj_xml_attr *attr )
-{
- pj_list_insert_before(&node->attr_head, attr);
-}
-
-PJ_DEF(pj_xml_node*) pj_xml_find_node(pj_xml_node *parent, const pj_str_t *name)
-{
- pj_xml_node *node = parent->node_head.next;
-
- PJ_CHECK_STACK();
-
- while (node != (void*)&parent->node_head) {
- if (pj_stricmp(&node->name, name) == 0)
- return node;
- node = node->next;
- }
- return NULL;
-}
-
-
-PJ_DEF(pj_xml_node*) pj_xml_find_next_node( pj_xml_node *parent, pj_xml_node *node,
- const pj_str_t *name)
-{
- PJ_CHECK_STACK();
-
- node = node->next;
- while (node != (void*)&parent->node_head) {
- if (pj_stricmp(&node->name, name) == 0)
- return node;
- node = node->next;
- }
- return NULL;
-}
-
-
-PJ_DEF(pj_xml_attr*) pj_xml_find_attr( pj_xml_node *node, const pj_str_t *name,
- const pj_str_t *value)
-{
- pj_xml_attr *attr = node->attr_head.next;
- while (attr != (void*)&node->attr_head) {
- if (pj_stricmp(&attr->name, name)==0) {
- if (value) {
- if (pj_stricmp(&attr->value, value)==0)
- return attr;
- } else {
- return attr;
- }
- }
- attr = attr->next;
- }
- return NULL;
-}
-
-
-
-PJ_DEF(pj_xml_node*) pj_xml_find( pj_xml_node *parent, const pj_str_t *name,
- const void *data,
- pj_bool_t (*match)(pj_xml_node *, const void*))
-{
- pj_xml_node *head = (void*)&parent->node_head, *node = head->next;
-
- while (node != (void*)head) {
- if (name && pj_stricmp(&node->name, name)==0) {
- if (match) {
- if (match(node, data))
- return node;
- } else {
- return node;
- }
- }
- node = node->next;
- }
- return NULL;
-}
-
+/* $Header: /pjproject-0.3/pjlib/src/pj/xml.c 9 10/14/05 12:26a Bennylp $ */ +/* $Log: /pjproject-0.3/pjlib/src/pj/xml.c $ + * + * 9 10/14/05 12:26a Bennylp + * Finished error code framework, some fixes in ioqueue, etc. Pretty + * major. + * + * 8 9/21/05 1:39p Bennylp + * Periodic checkin for backup. + * + * 7 9/17/05 10:37a Bennylp + * Major reorganization towards version 0.3. + * + */ +#include <pj/xml.h> +#include <pj/scanner.h> +#include <pj/except.h> +#include <pj/pool.h> +#include <pj/string.h> +#include <pj/log.h> +#include <pj/os.h> + +#define EX_SYNTAX_ERROR 12 +#define THIS_FILE "xml.c" + +static void on_syntax_error(struct pj_scanner *scanner) +{ + PJ_UNUSED_ARG(scanner); + PJ_THROW(EX_SYNTAX_ERROR); +} + +static pj_xml_node *alloc_node( pj_pool_t *pool ) +{ + pj_xml_node *node; + + node = pj_pool_calloc(pool, 1, sizeof(pj_xml_node)); + pj_list_init( &node->attr_head ); + pj_list_init( &node->node_head ); + + return node; +} + +static pj_xml_attr *alloc_attr( pj_pool_t *pool ) +{ + return pj_pool_calloc(pool, 1, sizeof(pj_xml_attr)); +} + +/* This is a recursive function! */ +static pj_xml_node *xml_parse_node( pj_pool_t *pool, pj_scanner *scanner) +{ + pj_xml_node *node; + pj_str_t end_name; + + PJ_CHECK_STACK(); + + if (*scanner->curptr != '<') + on_syntax_error(scanner); + + /* Handle Processing Instructino (PI) construct (i.e. "<?") */ + if (*scanner->curptr == '<' && *(scanner->curptr+1) == '?') { + pj_scan_advance_n(scanner, 2, PJ_FALSE); + for (;;) { + pj_str_t dummy; + pj_scan_get_until_ch(scanner, '?', &dummy); + if (*scanner->curptr=='?' && *(scanner->curptr+1)=='>') { + pj_scan_advance_n(scanner, 2, PJ_TRUE); + break; + } else { + pj_scan_advance_n(scanner, 1, PJ_FALSE); + } + } + return xml_parse_node(pool, scanner); + } + + /* Handle comments construct (i.e. "<!--") */ + if (pj_scan_strcmp(scanner, "<!--", 4) == 0) { + pj_scan_advance_n(scanner, 4, PJ_FALSE); + for (;;) { + pj_str_t dummy; + pj_scan_get_until_ch(scanner, '-', &dummy); + if (pj_scan_strcmp(scanner, "-->", 3) == 0) { + pj_scan_advance_n(scanner, 3, PJ_TRUE); + break; + } else { + pj_scan_advance_n(scanner, 1, PJ_FALSE); + } + } + return xml_parse_node(pool, scanner); + } + + /* Alloc node. */ + node = alloc_node(pool); + + /* Get '<' */ + pj_scan_get_char(scanner); + + /* Get node name. */ + pj_scan_get_until_chr( scanner, " />\t", &node->name); + + /* Get attributes. */ + while (*scanner->curptr != '>' && *scanner->curptr != '/') { + pj_xml_attr *attr = alloc_attr(pool); + + pj_scan_get_until_chr( scanner, "=> \t", &attr->name); + if (*scanner->curptr == '=') { + pj_scan_get_char( scanner ); + pj_scan_get_quote(scanner, '"', '"', &attr->value); + /* remove quote characters */ + ++attr->value.ptr; + attr->value.slen -= 2; + } + + pj_list_insert_before( &node->attr_head, attr ); + } + + if (*scanner->curptr == '/') { + pj_scan_get_char(scanner); + if (pj_scan_get_char(scanner) != '>') + on_syntax_error(scanner); + return node; + } + + /* Enclosing bracket. */ + if (pj_scan_get_char(scanner) != '>') + on_syntax_error(scanner); + + /* Sub nodes. */ + while (*scanner->curptr == '<' && *(scanner->curptr+1) != '/') { + pj_xml_node *sub_node = xml_parse_node(pool, scanner); + pj_list_insert_before( &node->node_head, sub_node ); + } + + /* Content. */ + if (!pj_scan_is_eof(scanner) && *scanner->curptr != '<') { + pj_scan_get_until_ch(scanner, '<', &node->content); + } + + /* Enclosing node. */ + if (pj_scan_get_char(scanner) != '<' || pj_scan_get_char(scanner) != '/') + on_syntax_error(scanner); + + pj_scan_get_until_chr(scanner, " \t>", &end_name); + + /* Compare name. */ + if (pj_stricmp(&node->name, &end_name) != 0) + on_syntax_error(scanner); + + /* Enclosing '>' */ + if (pj_scan_get_char(scanner) != '>') + on_syntax_error(scanner); + + return node; +} + +PJ_DEF(pj_xml_node*) pj_xml_parse( pj_pool_t *pool, char *msg, pj_size_t len) +{ + pj_xml_node *node = NULL; + pj_scanner scanner; + PJ_USE_EXCEPTION; + + if (!msg || !len || !pool) + return NULL; + + pj_scan_init( &scanner, msg, len, + PJ_SCAN_AUTOSKIP_WS|PJ_SCAN_AUTOSKIP_NEWLINE, + &on_syntax_error); + PJ_TRY { + node = xml_parse_node(pool, &scanner); + } + PJ_DEFAULT { + PJ_LOG(4,(THIS_FILE, "Syntax error parsing XML in line %d column %d", + scanner.line, scanner.col)); + } + PJ_END; + pj_scan_fini( &scanner ); + return node; +} + +/* This is a recursive function. */ +static int xml_print_node( const pj_xml_node *node, int indent, + char *buf, pj_size_t len ) +{ + int i; + char *p = buf; + pj_xml_attr *attr; + pj_xml_node *sub_node; + +#define SIZE_LEFT() ((int)(len - (p-buf))) + + PJ_CHECK_STACK(); + + /* Print name. */ + if (SIZE_LEFT() < node->name.slen + indent + 5) + return -1; + for (i=0; i<indent; ++i) + *p++ = ' '; + *p++ = '<'; + pj_memcpy(p, node->name.ptr, node->name.slen); + p += node->name.slen; + + /* Print attributes. */ + attr = node->attr_head.next; + while (attr != &node->attr_head) { + + if (SIZE_LEFT() < attr->name.slen + attr->value.slen + 4) + return -1; + + *p++ = ' '; + + /* Attribute name. */ + pj_memcpy(p, attr->name.ptr, attr->name.slen); + p += attr->name.slen; + + /* Attribute value. */ + if (attr->value.slen) { + *p++ = '='; + *p++ = '"'; + pj_memcpy(p, attr->value.ptr, attr->value.slen); + p += attr->value.slen; + *p++ = '"'; + } + + attr = attr->next; + } + + /* Check for empty node. */ + if (node->content.slen==0 && + node->node_head.next==(pj_xml_node*)&node->node_head) + { + *p++ = ' '; + *p++ = '/'; + *p++ = '>'; + return p-buf; + } + + /* Enclosing '>' */ + if (SIZE_LEFT() < 1) return -1; + *p++ = '>'; + + /* Print sub nodes. */ + sub_node = node->node_head.next; + while (sub_node != (pj_xml_node*)&node->node_head) { + int printed; + + if (SIZE_LEFT() < indent + 3) + return -1; + //*p++ = '\r'; + *p++ = '\n'; + + printed = xml_print_node(sub_node, indent + 1, p, SIZE_LEFT()); + if (printed < 0) + return -1; + + p += printed; + sub_node = sub_node->next; + } + + /* Content. */ + if (node->content.slen) { + if (SIZE_LEFT() < node->content.slen) return -1; + pj_memcpy(p, node->content.ptr, node->content.slen); + p += node->content.slen; + } + + /* Enclosing node. */ + if (node->node_head.next != (pj_xml_node*)&node->node_head) { + if (SIZE_LEFT() < node->name.slen + 5 + indent) + return -1; + //*p++ = '\r'; + *p++ = '\n'; + for (i=0; i<indent; ++i) + *p++ = ' '; + } else { + if (SIZE_LEFT() < node->name.slen + 3) + return -1; + } + *p++ = '<'; + *p++ = '/'; + pj_memcpy(p, node->name.ptr, node->name.slen); + p += node->name.slen; + *p++ = '>'; + +#undef SIZE_LEFT + + return p - buf; +} + +PJ_DEF(int) pj_xml_print(const pj_xml_node *node, char *buf, pj_size_t len, + pj_bool_t include_prolog) +{ + int prolog_len = 0; + int printed; + + if (!node || !buf || !len) + return 0; + + if (include_prolog) { + pj_str_t prolog = {"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n", 39}; + if ((int)len < prolog.slen) + return -1; + pj_memcpy(buf, prolog.ptr, prolog.slen); + prolog_len = prolog.slen; + } + + printed = xml_print_node(node, 0, buf+prolog_len, len-prolog_len) + prolog_len; + if (printed > 0 && len-printed >= 1) { + buf[printed++] = '\n'; + } + return printed; +} + + +PJ_DEF(void) pj_xml_add_node( pj_xml_node *parent, pj_xml_node *node ) +{ + pj_list_insert_before(&parent->node_head, node); +} + +PJ_DEF(void) pj_xml_add_attr( pj_xml_node *node, pj_xml_attr *attr ) +{ + pj_list_insert_before(&node->attr_head, attr); +} + +PJ_DEF(pj_xml_node*) pj_xml_find_node(pj_xml_node *parent, const pj_str_t *name) +{ + pj_xml_node *node = parent->node_head.next; + + PJ_CHECK_STACK(); + + while (node != (void*)&parent->node_head) { + if (pj_stricmp(&node->name, name) == 0) + return node; + node = node->next; + } + return NULL; +} + + +PJ_DEF(pj_xml_node*) pj_xml_find_next_node( pj_xml_node *parent, pj_xml_node *node, + const pj_str_t *name) +{ + PJ_CHECK_STACK(); + + node = node->next; + while (node != (void*)&parent->node_head) { + if (pj_stricmp(&node->name, name) == 0) + return node; + node = node->next; + } + return NULL; +} + + +PJ_DEF(pj_xml_attr*) pj_xml_find_attr( pj_xml_node *node, const pj_str_t *name, + const pj_str_t *value) +{ + pj_xml_attr *attr = node->attr_head.next; + while (attr != (void*)&node->attr_head) { + if (pj_stricmp(&attr->name, name)==0) { + if (value) { + if (pj_stricmp(&attr->value, value)==0) + return attr; + } else { + return attr; + } + } + attr = attr->next; + } + return NULL; +} + + + +PJ_DEF(pj_xml_node*) pj_xml_find( pj_xml_node *parent, const pj_str_t *name, + const void *data, + pj_bool_t (*match)(pj_xml_node *, const void*)) +{ + pj_xml_node *head = (void*)&parent->node_head, *node = head->next; + + while (node != (void*)head) { + if (name && pj_stricmp(&node->name, name)==0) { + if (match) { + if (match(node, data)) + return node; + } else { + return node; + } + } + node = node->next; + } + return NULL; +} + |