📄 nad.c
字号:
for(attr = nad->elems[elem].attr; attr >= 0; attr = nad->attrs[attr].next) { if(nad->attrs[attr].lname <= 0) continue; /* make enough space for the wrapper part */ ns = nad->attrs[attr].my_ns; if(ns >= 0 && nad->nss[ns].iprefix >= 0) { NAD_SAFE(nad->cdata, nad->ccur + nad->attrs[attr].lname + nad->nss[ns].lprefix + 4, nad->clen); } else { NAD_SAFE(nad->cdata, nad->ccur + nad->attrs[attr].lname + 3, nad->clen); } *(nad->cdata + nad->ccur++) = ' '; /* add the prefix if necessary */ if(ns >= 0 && nad->nss[ns].iprefix >= 0) { memcpy(nad->cdata + nad->ccur, nad->cdata + nad->nss[ns].iprefix, nad->nss[ns].lprefix); nad->ccur += nad->nss[ns].lprefix; *(nad->cdata + nad->ccur++) = ':'; } /* copy in the name parts */ memcpy(nad->cdata + nad->ccur, nad->cdata + nad->attrs[attr].iname, nad->attrs[attr].lname); nad->ccur += nad->attrs[attr].lname; *(nad->cdata + nad->ccur++) = '='; *(nad->cdata + nad->ccur++) = '\''; /* copy in the escaped value */ _nad_escape(nad, nad->attrs[attr].ival, nad->attrs[attr].lval, 3); /* make enough space for the closing quote and add it */ NAD_SAFE(nad->cdata, nad->ccur + 1, nad->clen); *(nad->cdata + nad->ccur++) = '\''; } /* figure out what's next */ if(elem+1 == nad->ecur) ndepth = -1; else ndepth = nad->elems[elem+1].depth; /* handle based on if there are children, update nelem after done */ if(ndepth <= nad->elems[elem].depth) { /* make sure there's enough for what we could need */ NAD_SAFE(nad->cdata, nad->ccur + 2, nad->clen); if(nad->elems[elem].lcdata == 0) { memcpy(nad->cdata + nad->ccur, "/>", 2); nad->ccur += 2; }else{ *(nad->cdata + nad->ccur++) = '>'; /* copy in escaped cdata */ _nad_escape(nad, nad->elems[elem].icdata, nad->elems[elem].lcdata,2); /* make room */ ns = nad->elems[elem].my_ns; if(ns >= 0 && nad->nss[ns].iprefix >= 0) { NAD_SAFE(nad->cdata, nad->ccur + 4 + nad->elems[elem].lname + nad->nss[ns].lprefix, nad->clen); } else { NAD_SAFE(nad->cdata, nad->ccur + 3 + nad->elems[elem].lname, nad->clen); } /* close tag */ memcpy(nad->cdata + nad->ccur, "</", 2); nad->ccur += 2; /* add the prefix if necessary */ if(ns >= 0 && nad->nss[ns].iprefix >= 0) { memcpy(nad->cdata + nad->ccur, nad->cdata + nad->nss[ns].iprefix, nad->nss[ns].lprefix); nad->ccur += nad->nss[ns].lprefix; *(nad->cdata + nad->ccur++) = ':'; } memcpy(nad->cdata + nad->ccur, nad->cdata + nad->elems[elem].iname, nad->elems[elem].lname); nad->ccur += nad->elems[elem].lname; *(nad->cdata + nad->ccur++) = '>'; } /* always try to append the tail */ _nad_escape(nad, nad->elems[elem].itail, nad->elems[elem].ltail,2); /* if no siblings either, bail */ if(ndepth < nad->elems[elem].depth) return elem+1; /* next sibling */ elem++; }else{ int nelem; /* process any children */ /* close ourself and append any cdata first */ NAD_SAFE(nad->cdata, nad->ccur + 1, nad->clen); *(nad->cdata + nad->ccur++) = '>'; _nad_escape(nad, nad->elems[elem].icdata, nad->elems[elem].lcdata,2); /* process children */ nelem = _nad_lp0(nad,elem+1); /* close and tail up */ ns = nad->elems[elem].my_ns; if(ns >= 0 && nad->nss[ns].iprefix >= 0) { NAD_SAFE(nad->cdata, nad->ccur + 4 + nad->elems[elem].lname + nad->nss[ns].lprefix, nad->clen); } else { NAD_SAFE(nad->cdata, nad->ccur + 3 + nad->elems[elem].lname, nad->clen); } memcpy(nad->cdata + nad->ccur, "</", 2); nad->ccur += 2; if(ns >= 0 && nad->nss[ns].iprefix >= 0) { memcpy(nad->cdata + nad->ccur, nad->cdata + nad->nss[ns].iprefix, nad->nss[ns].lprefix); nad->ccur += nad->nss[ns].lprefix; *(nad->cdata + nad->ccur++) = ':'; } memcpy(nad->cdata + nad->ccur, nad->cdata + nad->elems[elem].iname, nad->elems[elem].lname); nad->ccur += nad->elems[elem].lname; *(nad->cdata + nad->ccur++) = '>'; _nad_escape(nad, nad->elems[elem].itail, nad->elems[elem].ltail,2); /* if the next element is not our sibling, we're done */ if(nelem < nad->ecur && nad->elems[nelem].depth < nad->elems[elem].depth) return nelem; /* for next sibling in while loop */ elem = nelem; } /* here's the end of that big while loop */ } return elem;}void nad_print(nad_t nad, int elem, char **xml, int *len){ int ixml = nad->ccur; _nad_ptr_check(__func__, nad); _nad_lp0(nad,elem); *len = nad->ccur - ixml; *xml = nad->cdata + ixml;}/** * nads serialize to a buffer of this form: * * [buflen][ecur][acur][ncur][ccur][elems][attrs][nss][cdata] * * nothing is done with endianness or word length, so the nad must be * serialized and deserialized on the same platform * * buflen is not actually used by deserialize(), but is provided as a * convenience to the application so it knows how many bytes to read before * passing them in to deserialize() * * the depths array is not stored, so after deserialization * nad_append_elem() and nad_append_cdata() will not work. this is rarely * a problem */void nad_serialize(nad_t nad, char **buf, int *len) { char *pos; _nad_ptr_check(__func__, nad); *len = sizeof(int) * 5 + /* 4 ints in nad_t, plus one for len */ sizeof(struct nad_elem_st) * nad->ecur + sizeof(struct nad_attr_st) * nad->acur + sizeof(struct nad_ns_st) * nad->ncur + sizeof(char) * nad->ccur; *buf = (char *) malloc(*len); pos = *buf; * (int *) pos = *len; pos += sizeof(int); * (int *) pos = nad->ecur; pos += sizeof(int); * (int *) pos = nad->acur; pos += sizeof(int); * (int *) pos = nad->ncur; pos += sizeof(int); * (int *) pos = nad->ccur; pos += sizeof(int); memcpy(pos, nad->elems, sizeof(struct nad_elem_st) * nad->ecur); pos += sizeof(struct nad_elem_st) * nad->ecur; memcpy(pos, nad->attrs, sizeof(struct nad_attr_st) * nad->acur); pos += sizeof(struct nad_attr_st) * nad->acur; memcpy(pos, nad->nss, sizeof(struct nad_ns_st) * nad->ncur); pos += sizeof(struct nad_ns_st) * nad->ncur; memcpy(pos, nad->cdata, sizeof(char) * nad->ccur);}nad_t nad_deserialize(nad_cache_t cache, const char *buf) { nad_t nad = nad_new(cache); const char *pos = buf + sizeof(int); /* skip len */ _nad_ptr_check(__func__, nad); nad->ecur = * (int *) pos; pos += sizeof(int); nad->acur = * (int *) pos; pos += sizeof(int); nad->ncur = * (int *) pos; pos += sizeof(int); nad->ccur = * (int *) pos; pos += sizeof(int); nad->elen = nad->ecur; nad->alen = nad->acur; nad->nlen = nad->ncur; nad->clen = nad->ccur; if(nad->ecur > 0) { nad->elems = (struct nad_elem_st *) malloc(sizeof(struct nad_elem_st) * nad->ecur); memcpy(nad->elems, pos, sizeof(struct nad_elem_st) * nad->ecur); pos += sizeof(struct nad_elem_st) * nad->ecur; } if(nad->acur > 0) { nad->attrs = (struct nad_attr_st *) malloc(sizeof(struct nad_attr_st) * nad->acur); memcpy(nad->attrs, pos, sizeof(struct nad_attr_st) * nad->acur); pos += sizeof(struct nad_attr_st) * nad->acur; } if(nad->ncur > 0) { nad->nss = (struct nad_ns_st *) malloc(sizeof(struct nad_ns_st) * nad->ncur); memcpy(nad->nss, pos, sizeof(struct nad_ns_st) * nad->ncur); pos += sizeof(struct nad_ns_st) * nad->ncur; } if(nad->ccur > 0) { nad->cdata = (char *) malloc(sizeof(char) * nad->ccur); memcpy(nad->cdata, pos, sizeof(char) * nad->ccur); } return nad;}#ifdef HAVE_EXPAT/** parse a buffer into a nad */struct build_data { nad_t nad; int depth;};static void _nad_parse_element_start(void *arg, const char *name, const char **atts) { struct build_data *bd = (struct build_data *) arg; char buf[1024]; char *uri, *elem, *prefix; const char **attr; int ns; /* make a copy */ strncpy(buf, name, 1024); buf[1023] = '\0'; /* expat gives us: prefixed namespaced elem: uri|elem|prefix default namespaced elem: uri|elem un-namespaced elem: elem */ /* extract all the bits */ uri = buf; elem = strchr(uri, '|'); if(elem != NULL) { *elem = '\0'; elem++; prefix = strchr(elem, '|'); if(prefix != NULL) { *prefix = '\0'; prefix++; } ns = nad_add_namespace(bd->nad, uri, prefix); } else { /* un-namespaced, just take it as-is */ uri = NULL; elem = buf; prefix = NULL; ns = -1; } /* add it */ nad_append_elem(bd->nad, ns, elem, bd->depth); /* now the attributes, one at a time */ attr = atts; while(attr[0] != NULL) { /* make a copy */ strncpy(buf, attr[0], 1024); buf[1023] = '\0'; /* extract all the bits */ uri = buf; elem = strchr(uri, '|'); if(elem != NULL) { *elem = '\0'; elem++; prefix = strchr(elem, '|'); if(prefix != NULL) { *prefix = '\0'; prefix++; } ns = nad_add_namespace(bd->nad, uri, prefix); } else { /* un-namespaced, just take it as-is */ uri = NULL; elem = buf; prefix = NULL; ns = -1; } /* add it */ nad_append_attr(bd->nad, ns, elem, (char *) attr[1]); attr += 2; } bd->depth++;}static void _nad_parse_element_end(void *arg, const char *name) { struct build_data *bd = (struct build_data *) arg; bd->depth--;}static void _nad_parse_cdata(void *arg, const char *str, int len) { struct build_data *bd = (struct build_data *) arg; /* go */ nad_append_cdata(bd->nad, (char *) str, len, bd->depth);}static void _nad_parse_namespace_start(void *arg, const char *prefix, const char *uri) { struct build_data *bd = (struct build_data *) arg; int ns; ns = nad_add_namespace(bd->nad, (char *) uri, (char *) prefix); /* Always set the namespace (to catch cases where nad_add_namespace doesn't add it) */ bd->nad->scope = ns; }nad_t nad_parse(nad_cache_t cache, const char *buf, int len) { struct build_data bd; XML_Parser p; if(len == 0) len = strlen(buf); p = XML_ParserCreateNS(NULL, '|'); if(p == NULL) return NULL; XML_SetReturnNSTriplet(p, 1); bd.nad = nad_new(cache); bd.depth = 0; XML_SetUserData(p, (void *) &bd); XML_SetElementHandler(p, _nad_parse_element_start, _nad_parse_element_end); XML_SetCharacterDataHandler(p, _nad_parse_cdata); XML_SetStartNamespaceDeclHandler(p, _nad_parse_namespace_start); if(!XML_Parse(p, buf, len, 1)) { XML_ParserFree(p); nad_free(bd.nad); return NULL; } XML_ParserFree(p); if(bd.depth != 0) return NULL; return bd.nad;}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -