00001 /* ezxml.h 00002 * 00003 * Copyright 2004-2006 Aaron Voisine <aaron@voisine.org> 00004 * 00005 * Permission is hereby granted, free of charge, to any person obtaining 00006 * a copy of this software and associated documentation files (the 00007 * "Software"), to deal in the Software without restriction, including 00008 * without limitation the rights to use, copy, modify, merge, publish, 00009 * distribute, sublicense, and/or sell copies of the Software, and to 00010 * permit persons to whom the Software is furnished to do so, subject to 00011 * the following conditions: 00012 * 00013 * The above copyright notice and this permission notice shall be included 00014 * in all copies or substantial portions of the Software. 00015 * 00016 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 00017 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 00018 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 00019 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 00020 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 00021 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 00022 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 00023 */ 00024 00025 #ifndef _EZXML_H 00026 #define _EZXML_H 00027 00028 #include <stdlib.h> 00029 #include <stdio.h> 00030 #include <stdarg.h> 00031 #include <fcntl.h> 00032 00033 #ifdef __cplusplus 00034 extern "C" 00035 { 00036 #endif 00037 00038 #define EZXML_BUFSIZE 1024 /* size of internal memory buffers */ 00039 #define EZXML_NAMEM 0x80 /* name is malloced */ 00040 #define EZXML_TXTM 0x40 /* txt is malloced */ 00041 #define EZXML_DUP 0x20 /* attribute name and value are strduped */ 00042 00043 typedef struct ezxml *ezxml_t; 00044 struct ezxml 00045 { 00046 char *name; /* tag name */ 00047 char **attr; /* tag attributes { name, value, name, value, ... NULL } */ 00048 char *txt; /* tag character content, empty string if none */ 00049 size_t off; /* tag offset from start of parent tag character content */ 00050 ezxml_t next; /* next tag with same name in this section at this depth */ 00051 ezxml_t sibling; /* next tag with different name in same section and depth */ 00052 ezxml_t ordered; /* next tag, same section and depth, in original order */ 00053 ezxml_t child; /* head of sub tag list, NULL if none */ 00054 ezxml_t parent; /* parent tag, NULL if current tag is root tag */ 00055 short flags; /* additional information */ 00056 }; 00057 00058 /* Given a string of xml data and its length, parses it and creates an ezxml */ 00059 /* structure. For efficiency, modifies the data by adding null terminators */ 00060 /* and decoding ampersand sequences. If you don't want this, copy the data and */ 00061 /* pass in the copy. Returns NULL on failure. */ 00062 ezxml_t ezxml_parse_str(char *s, 00063 size_t len); 00064 00065 /* A wrapper for ezxml_parse_str() that accepts a file descriptor. First */ 00066 /* attempts to mem map the file. Failing that, reads the file into memory. */ 00067 /* Returns NULL on failure. */ 00068 ezxml_t ezxml_parse_fd(int fd); 00069 00070 /* a wrapper for ezxml_parse_fd() that accepts a file name */ 00071 ezxml_t ezxml_parse_file(const char *file); 00072 00073 /* Wrapper for ezxml_parse_str() that accepts a file stream. Reads the entire */ 00074 /* stream into memory and then parses it. For xml files, use ezxml_parse_file() */ 00075 /* or ezxml_parse_fd() */ 00076 ezxml_t ezxml_parse_fp(FILE * fp); 00077 00078 /* returns the first child tag (one level deeper) with the given name or NULL */ 00079 /* if not found */ 00080 ezxml_t ezxml_child(ezxml_t xml, 00081 const char *name); 00082 00083 /* returns the next tag of the same name in the same section and depth or NULL */ 00084 /* if not found */ 00085 #define ezxml_next(xml) ((xml) ? xml->next : NULL) 00086 00087 /* Returns the Nth tag with the same name in the same section at the same depth */ 00088 /* or NULL if not found. An index of 0 returns the tag given. */ 00089 ezxml_t ezxml_idx(ezxml_t xml, 00090 int idx); 00091 00092 /* returns the name of the given tag */ 00093 #define ezxml_name(xml) ((xml) ? xml->name : NULL) 00094 00095 /* returns the given tag's character content or empty string if none */ 00096 #define ezxml_txt(xml) ((xml) ? xml->txt : "") 00097 00098 /* returns the value of the requested tag attribute, or NULL if not found */ 00099 const char *ezxml_attr(ezxml_t xml, 00100 const char *attr); 00101 00102 /* Traverses the ezxml sturcture to retrieve a specific subtag. Takes a */ 00103 /* variable length list of tag names and indexes. The argument list must be */ 00104 /* terminated by either an index of -1 or an empty string tag name. Example: */ 00105 /* title = ezxml_get(library, "shelf", 0, "book", 2, "title", -1); */ 00106 /* This retrieves the title of the 3rd book on the 1st shelf of library. */ 00107 /* Returns NULL if not found. */ 00108 ezxml_t ezxml_get(ezxml_t xml, 00109 ...); 00110 00111 /* Converts an ezxml structure back to xml. Returns a string of xml data that */ 00112 /* must be freed. */ 00113 char *ezxml_toxml(ezxml_t xml); 00114 00115 /* returns a NULL terminated array of processing instructions for the given */ 00116 /* target */ 00117 const char **ezxml_pi(ezxml_t xml, 00118 const char *target); 00119 00120 /* frees the memory allocated for an ezxml structure */ 00121 void ezxml_free(ezxml_t xml); 00122 00123 /* returns parser error message or empty string if none */ 00124 const char *ezxml_error(ezxml_t xml); 00125 00126 /* returns a new empty ezxml structure with the given root tag name */ 00127 ezxml_t ezxml_new(const char *name); 00128 00129 /* wrapper for ezxml_new() that strdup()s name */ 00130 #define ezxml_new_d(name) ezxml_set_flag(ezxml_new(strdup(name)), EZXML_NAMEM) 00131 00132 /* Adds a child tag. off is the offset of the child tag relative to the start */ 00133 /* of the parent tag's character content. Returns the child tag. */ 00134 ezxml_t ezxml_add_child(ezxml_t xml, 00135 const char *name, 00136 size_t off); 00137 00138 /* wrapper for ezxml_add_child() that strdup()s name */ 00139 #define ezxml_add_child_d(xml, name, off) \ 00140 ezxml_set_flag(ezxml_add_child(xml, strdup(name), off), EZXML_NAMEM) 00141 00142 /* sets the character content for the given tag and returns the tag */ 00143 ezxml_t ezxml_set_txt(ezxml_t xml, 00144 const char *txt); 00145 00146 /* wrapper for ezxml_set_txt() that strdup()s txt */ 00147 #define ezxml_set_txt_d(xml, txt) \ 00148 ezxml_set_flag(ezxml_set_txt(xml, strdup(txt)), EZXML_TXTM) 00149 00150 /* Sets the given tag attribute or adds a new attribute if not found. A value */ 00151 /* of NULL will remove the specified attribute. Returns the tag given. */ 00152 ezxml_t ezxml_set_attr(ezxml_t xml, 00153 const char *name, 00154 const char *value); 00155 00156 /* Wrapper for ezxml_set_attr() that strdup()s name/value. Value cannot be NULL */ 00157 #define ezxml_set_attr_d(xml, name, value) \ 00158 ezxml_set_attr(ezxml_set_flag(xml, EZXML_DUP), strdup(name), strdup(value)) 00159 00160 /* sets a flag for the given tag and returns the tag */ 00161 ezxml_t ezxml_set_flag(ezxml_t xml, 00162 short flag); 00163 00164 /* removes a tag along with its subtags without freeing its memory */ 00165 ezxml_t ezxml_cut(ezxml_t xml); 00166 00167 /* inserts an existing tag into an ezxml structure */ 00168 ezxml_t ezxml_insert(ezxml_t xml, 00169 ezxml_t dest, 00170 size_t off); 00171 00172 /* Moves an existing tag to become a subtag of dest at the given offset from */ 00173 /* the start of dest's character content. Returns the moved tag. */ 00174 #define ezxml_move(xml, dest, off) ezxml_insert(ezxml_cut(xml), dest, off) 00175 00176 /* removes a tag along with all its subtags */ 00177 #define ezxml_remove(xml) ezxml_free(ezxml_cut(xml)) 00178 00179 #ifdef __cplusplus 00180 } 00181 #endif 00182 #endif /* _EZXML_H */