bosko lekovic
/
EthToCom_11
nova proba
XML/dxml.h@27:0772451fb880, 2021-01-17 (annotated)
- Committer:
- Bosko Lekovic
- Date:
- Sun Jan 17 23:03:43 2021 +0100
- Revision:
- 27:0772451fb880
initial commit
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
Bosko Lekovic |
27:0772451fb880 | 1 | /* dxml.h |
Bosko Lekovic |
27:0772451fb880 | 2 | * |
Bosko Lekovic |
27:0772451fb880 | 3 | * softverski modul korigovan 11.04.2020 |
Bosko Lekovic |
27:0772451fb880 | 4 | * |
Bosko Lekovic |
27:0772451fb880 | 5 | */ |
Bosko Lekovic |
27:0772451fb880 | 6 | |
Bosko Lekovic |
27:0772451fb880 | 7 | #ifndef _dxml_H |
Bosko Lekovic |
27:0772451fb880 | 8 | #define _dxml_H |
Bosko Lekovic |
27:0772451fb880 | 9 | |
Bosko Lekovic |
27:0772451fb880 | 10 | #include <stdlib.h> |
Bosko Lekovic |
27:0772451fb880 | 11 | #include <stdio.h> |
Bosko Lekovic |
27:0772451fb880 | 12 | #include <stdarg.h> |
Bosko Lekovic |
27:0772451fb880 | 13 | //#include <fcntl.h> |
Bosko Lekovic |
27:0772451fb880 | 14 | |
Bosko Lekovic |
27:0772451fb880 | 15 | #ifdef __cplusplus |
Bosko Lekovic |
27:0772451fb880 | 16 | extern "C" { |
Bosko Lekovic |
27:0772451fb880 | 17 | #endif |
Bosko Lekovic |
27:0772451fb880 | 18 | |
Bosko Lekovic |
27:0772451fb880 | 19 | #define dxml_BUFSIZE 1024 // size of internal memory buffers |
Bosko Lekovic |
27:0772451fb880 | 20 | #define dxml_NAMEM 0x80 // name is malloced |
Bosko Lekovic |
27:0772451fb880 | 21 | #define dxml_TXTM 0x40 // txt is malloced |
Bosko Lekovic |
27:0772451fb880 | 22 | #define dxml_DUP 0x20 // attribute name and value are strduped |
Bosko Lekovic |
27:0772451fb880 | 23 | |
Bosko Lekovic |
27:0772451fb880 | 24 | typedef struct dxml *dxml_t; |
Bosko Lekovic |
27:0772451fb880 | 25 | struct dxml { |
Bosko Lekovic |
27:0772451fb880 | 26 | char *name; // tag name |
Bosko Lekovic |
27:0772451fb880 | 27 | char **attr; // tag attributes { name, value, name, value, ... NULL } |
Bosko Lekovic |
27:0772451fb880 | 28 | char *txt; // tag character content, empty string if none |
Bosko Lekovic |
27:0772451fb880 | 29 | size_t off; // tag offset from start of parent tag character content |
Bosko Lekovic |
27:0772451fb880 | 30 | dxml_t next; // next tag with same name in this section at this depth |
Bosko Lekovic |
27:0772451fb880 | 31 | dxml_t sibling; // next tag with different name in same section and depth |
Bosko Lekovic |
27:0772451fb880 | 32 | dxml_t ordered; // next tag, same section and depth, in original order |
Bosko Lekovic |
27:0772451fb880 | 33 | dxml_t child; // head of sub tag list, NULL if none |
Bosko Lekovic |
27:0772451fb880 | 34 | dxml_t parent; // parent tag, NULL if current tag is root tag |
Bosko Lekovic |
27:0772451fb880 | 35 | short flags; // additional information |
Bosko Lekovic |
27:0772451fb880 | 36 | }; |
Bosko Lekovic |
27:0772451fb880 | 37 | |
Bosko Lekovic |
27:0772451fb880 | 38 | // Given a string of xml data and its length, parses it and creates an dxml |
Bosko Lekovic |
27:0772451fb880 | 39 | // structure. For efficiency, modifies the data by adding null terminators |
Bosko Lekovic |
27:0772451fb880 | 40 | // and decoding ampersand sequences. If you don't want this, copy the data and |
Bosko Lekovic |
27:0772451fb880 | 41 | // pass in the copy. Returns NULL on failure. |
Bosko Lekovic |
27:0772451fb880 | 42 | dxml_t dxml_parse_str(char *s, size_t len); |
Bosko Lekovic |
27:0772451fb880 | 43 | |
Bosko Lekovic |
27:0772451fb880 | 44 | // A wrapper for dxml_parse_str() that accepts a file descriptor. First |
Bosko Lekovic |
27:0772451fb880 | 45 | // attempts to mem map the file. Failing that, reads the file into memory. |
Bosko Lekovic |
27:0772451fb880 | 46 | // Returns NULL on failure. |
Bosko Lekovic |
27:0772451fb880 | 47 | //dxml_t dxml_parse_fd(int fd); |
Bosko Lekovic |
27:0772451fb880 | 48 | |
Bosko Lekovic |
27:0772451fb880 | 49 | // a wrapper for dxml_parse_fd() that accepts a file name |
Bosko Lekovic |
27:0772451fb880 | 50 | dxml_t dxml_parse_file(const char *file); |
Bosko Lekovic |
27:0772451fb880 | 51 | |
Bosko Lekovic |
27:0772451fb880 | 52 | // Wrapper for dxml_parse_str() that accepts a file stream. Reads the entire |
Bosko Lekovic |
27:0772451fb880 | 53 | // stream into memory and then parses it. For xml files, use dxml_parse_file() |
Bosko Lekovic |
27:0772451fb880 | 54 | // or dxml_parse_fd() |
Bosko Lekovic |
27:0772451fb880 | 55 | dxml_t dxml_parse_fp(FILE *fp); |
Bosko Lekovic |
27:0772451fb880 | 56 | |
Bosko Lekovic |
27:0772451fb880 | 57 | // returns the first child tag (one level deeper) with the given name or NULL |
Bosko Lekovic |
27:0772451fb880 | 58 | // if not found |
Bosko Lekovic |
27:0772451fb880 | 59 | dxml_t dxml_child(dxml_t xml, const char *name); |
Bosko Lekovic |
27:0772451fb880 | 60 | |
Bosko Lekovic |
27:0772451fb880 | 61 | // returns the next tag of the same name in the same section and depth or NULL |
Bosko Lekovic |
27:0772451fb880 | 62 | // if not found |
Bosko Lekovic |
27:0772451fb880 | 63 | #define dxml_next(xml) ((xml) ? xml->next : NULL) |
Bosko Lekovic |
27:0772451fb880 | 64 | |
Bosko Lekovic |
27:0772451fb880 | 65 | // Returns the Nth tag with the same name in the same section at the same depth |
Bosko Lekovic |
27:0772451fb880 | 66 | // or NULL if not found. An index of 0 returns the tag given. |
Bosko Lekovic |
27:0772451fb880 | 67 | dxml_t dxml_idx(dxml_t xml, int idx); |
Bosko Lekovic |
27:0772451fb880 | 68 | |
Bosko Lekovic |
27:0772451fb880 | 69 | // returns the name of the given tag |
Bosko Lekovic |
27:0772451fb880 | 70 | #define dxml_name(xml) ((xml) ? xml->name : NULL) |
Bosko Lekovic |
27:0772451fb880 | 71 | |
Bosko Lekovic |
27:0772451fb880 | 72 | // returns the given tag's character content or empty string if none |
Bosko Lekovic |
27:0772451fb880 | 73 | #define dxml_txt(xml) ((xml) ? xml->txt : "") |
Bosko Lekovic |
27:0772451fb880 | 74 | |
Bosko Lekovic |
27:0772451fb880 | 75 | // returns the value of the requested tag attribute, or NULL if not found |
Bosko Lekovic |
27:0772451fb880 | 76 | const char *dxml_attr(dxml_t xml, const char *attr); |
Bosko Lekovic |
27:0772451fb880 | 77 | |
Bosko Lekovic |
27:0772451fb880 | 78 | // Traverses the dxml sturcture to retrieve a specific subtag. Takes a |
Bosko Lekovic |
27:0772451fb880 | 79 | // variable length list of tag names and indexes. The argument list must be |
Bosko Lekovic |
27:0772451fb880 | 80 | // terminated by either an index of -1 or an empty string tag name. Example: |
Bosko Lekovic |
27:0772451fb880 | 81 | // title = dxml_get(library, "shelf", 0, "book", 2, "title", -1); |
Bosko Lekovic |
27:0772451fb880 | 82 | // This retrieves the title of the 3rd book on the 1st shelf of library. |
Bosko Lekovic |
27:0772451fb880 | 83 | // Returns NULL if not found. |
Bosko Lekovic |
27:0772451fb880 | 84 | dxml_t dxml_get(dxml_t xml, ...); |
Bosko Lekovic |
27:0772451fb880 | 85 | |
Bosko Lekovic |
27:0772451fb880 | 86 | // Converts an dxml structure back to xml. Returns a string of xml data that |
Bosko Lekovic |
27:0772451fb880 | 87 | // must be freed. |
Bosko Lekovic |
27:0772451fb880 | 88 | char *dxml_toxml(dxml_t xml); |
Bosko Lekovic |
27:0772451fb880 | 89 | |
Bosko Lekovic |
27:0772451fb880 | 90 | // returns a NULL terminated array of processing instructions for the given |
Bosko Lekovic |
27:0772451fb880 | 91 | // target |
Bosko Lekovic |
27:0772451fb880 | 92 | const char **dxml_pi(dxml_t xml, const char *target); |
Bosko Lekovic |
27:0772451fb880 | 93 | |
Bosko Lekovic |
27:0772451fb880 | 94 | // frees the memory allocated for an dxml structure |
Bosko Lekovic |
27:0772451fb880 | 95 | void dxml_free(dxml_t xml); |
Bosko Lekovic |
27:0772451fb880 | 96 | |
Bosko Lekovic |
27:0772451fb880 | 97 | // returns parser error message or empty string if none |
Bosko Lekovic |
27:0772451fb880 | 98 | const char *dxml_error(dxml_t xml); |
Bosko Lekovic |
27:0772451fb880 | 99 | |
Bosko Lekovic |
27:0772451fb880 | 100 | // returns a new empty dxml structure with the given root tag name |
Bosko Lekovic |
27:0772451fb880 | 101 | dxml_t dxml_new(const char *name); |
Bosko Lekovic |
27:0772451fb880 | 102 | |
Bosko Lekovic |
27:0772451fb880 | 103 | // wrapper for dxml_new() that strdup()s name |
Bosko Lekovic |
27:0772451fb880 | 104 | #define dxml_new_d(name) dxml_set_flag(dxml_new(strdup(name)), dxml_NAMEM) |
Bosko Lekovic |
27:0772451fb880 | 105 | |
Bosko Lekovic |
27:0772451fb880 | 106 | // Adds a child tag. off is the offset of the child tag relative to the start |
Bosko Lekovic |
27:0772451fb880 | 107 | // of the parent tag's character content. Returns the child tag. |
Bosko Lekovic |
27:0772451fb880 | 108 | dxml_t dxml_add_child(dxml_t xml, const char *name, size_t off); |
Bosko Lekovic |
27:0772451fb880 | 109 | |
Bosko Lekovic |
27:0772451fb880 | 110 | // wrapper for dxml_add_child() that strdup()s name |
Bosko Lekovic |
27:0772451fb880 | 111 | #define dxml_add_child_d(xml, name, off) \ |
Bosko Lekovic |
27:0772451fb880 | 112 | dxml_set_flag(dxml_add_child(xml, strdup(name), off), dxml_NAMEM) |
Bosko Lekovic |
27:0772451fb880 | 113 | |
Bosko Lekovic |
27:0772451fb880 | 114 | // sets the character content for the given tag and returns the tag |
Bosko Lekovic |
27:0772451fb880 | 115 | dxml_t dxml_set_txt(dxml_t xml, const char *txt); |
Bosko Lekovic |
27:0772451fb880 | 116 | |
Bosko Lekovic |
27:0772451fb880 | 117 | // wrapper for dxml_set_txt() that strdup()s txt |
Bosko Lekovic |
27:0772451fb880 | 118 | #define dxml_set_txt_d(xml, txt) \ |
Bosko Lekovic |
27:0772451fb880 | 119 | dxml_set_flag(dxml_set_txt(xml, strdup(txt)), dxml_TXTM) |
Bosko Lekovic |
27:0772451fb880 | 120 | |
Bosko Lekovic |
27:0772451fb880 | 121 | // Sets the given tag attribute or adds a new attribute if not found. A value |
Bosko Lekovic |
27:0772451fb880 | 122 | // of NULL will remove the specified attribute. Returns the tag given. |
Bosko Lekovic |
27:0772451fb880 | 123 | dxml_t dxml_set_attr(dxml_t xml, const char *name, const char *value); |
Bosko Lekovic |
27:0772451fb880 | 124 | |
Bosko Lekovic |
27:0772451fb880 | 125 | // Wrapper for dxml_set_attr() that strdup()s name/value. Value cannot be NULL |
Bosko Lekovic |
27:0772451fb880 | 126 | #define dxml_set_attr_d(xml, name, value) \ |
Bosko Lekovic |
27:0772451fb880 | 127 | dxml_set_attr(dxml_set_flag(xml, dxml_DUP), strdup(name), strdup(value)) |
Bosko Lekovic |
27:0772451fb880 | 128 | |
Bosko Lekovic |
27:0772451fb880 | 129 | // sets a flag for the given tag and returns the tag |
Bosko Lekovic |
27:0772451fb880 | 130 | dxml_t dxml_set_flag(dxml_t xml, short flag); |
Bosko Lekovic |
27:0772451fb880 | 131 | |
Bosko Lekovic |
27:0772451fb880 | 132 | // removes a tag along with its subtags without freeing its memory |
Bosko Lekovic |
27:0772451fb880 | 133 | dxml_t dxml_cut(dxml_t xml); |
Bosko Lekovic |
27:0772451fb880 | 134 | |
Bosko Lekovic |
27:0772451fb880 | 135 | // inserts an existing tag into an dxml structure |
Bosko Lekovic |
27:0772451fb880 | 136 | dxml_t dxml_insert(dxml_t xml, dxml_t dest, size_t off); |
Bosko Lekovic |
27:0772451fb880 | 137 | |
Bosko Lekovic |
27:0772451fb880 | 138 | // Moves an existing tag to become a subtag of dest at the given offset from |
Bosko Lekovic |
27:0772451fb880 | 139 | // the start of dest's character content. Returns the moved tag. |
Bosko Lekovic |
27:0772451fb880 | 140 | #define dxml_move(xml, dest, off) dxml_insert(dxml_cut(xml), dest, off) |
Bosko Lekovic |
27:0772451fb880 | 141 | |
Bosko Lekovic |
27:0772451fb880 | 142 | // removes a tag along with all its subtags |
Bosko Lekovic |
27:0772451fb880 | 143 | #define dxml_remove(xml) dxml_free(dxml_cut(xml)) |
Bosko Lekovic |
27:0772451fb880 | 144 | |
Bosko Lekovic |
27:0772451fb880 | 145 | #ifdef __cplusplus |
Bosko Lekovic |
27:0772451fb880 | 146 | } |
Bosko Lekovic |
27:0772451fb880 | 147 | #endif |
Bosko Lekovic |
27:0772451fb880 | 148 | |
Bosko Lekovic |
27:0772451fb880 | 149 | #endif // _dxml_H |
Bosko Lekovic |
27:0772451fb880 | 150 | |
Bosko Lekovic |
27:0772451fb880 | 151 |