EXPORT XplBool _WJEDetach(WJElement document, const char *file, const int line) { if (!document) { return(FALSE); } MemUpdateOwner(document, file, line); /* Remove references to the document */ if (document->parent) { WJEChanged(document->parent); if (document->parent->child == document) { document->parent->child = document->next; } document->parent->count--; document->parent = NULL; } if (document->prev) { document->prev->next = document->next; } if (document->next) { document->next->prev = document->prev; } document->prev = NULL; document->next = NULL; return(TRUE); }
EXPORT WJElement _WJEOpenDocument(WJReader reader, char *where, WJELoadCB loadcb, void *data, const char *file, const int line) { WJElement element; if ((element = _WJELoad(NULL, reader, where, loadcb, data, file, line))) { MemUpdateOwner(element, file, line); } return(element); }
_WJElement * _WJENew(_WJElement *parent, char *name, size_t len, const char *file, int line) { _WJElement *result; WJElement prev; if (parent) { _WJEChanged((WJElement) parent); if (WJR_TYPE_ARRAY == parent->pub.type) { /* Children of an array can not have a name */ name = NULL; len = 0; } else if (WJR_TYPE_OBJECT != parent->pub.type || !name || !*name) { /* Only arrays and objects can contain children, and elements in an object MUST be named. */ return(NULL); } } if ((result = MemMalloc(sizeof(_WJElement) + len + 1))) { memset(result, 0, sizeof(_WJElement)); MemUpdateOwner(result, file, line); if (name) { strncpy(result->_name, name, len); result->pub.name = result->_name; } result->_name[len] = '\0'; if (parent) { result->pub.parent = (WJElement) parent; if (!parent->pub.child) { parent->pub.child = (WJElement) result; } else { /* Find the last child so it can be added at the end */ for (prev = parent->pub.child; prev && prev->next; prev = prev->next); prev->next = (WJElement) result; result->pub.prev = prev; } parent->pub.count++; } result->pub.type = WJR_TYPE_OBJECT; } return(result); }
EXPORT WJElement _WJECopyDocument(WJElement to, WJElement from, WJECopyCB copycb, void *data, const char *file, const int line) { if (to) { WJElement c; for (c = from->child; c; c = c->next) { _WJECopy((_WJElement *) to, c, copycb, data, file, line); } } else { if ((to = _WJECopy(NULL, from, copycb, data, file, line))) { MemUpdateOwner(to, file, line); } } return(to); }
EXPORT char * __WJEStringN(WJElement container, const char *path, WJEAction action, WJElement *last, const char *value, size_t len, const char *file, const int line) { _WJElement *e; /* Find an element that is appropriate for the given action, creating new elements as needed. */ e = _WJESearch(container, path, &action, last ? *last : NULL, file, line); if (e) { switch (e->pub.type) { case WJR_TYPE_UNKNOWN: /* A new object was created, and the changes count has already been updated. */ e->pub.type = WJR_TYPE_STRING; break; case WJR_TYPE_STRING: if (!e->value.string && !value) { break; } if (e->value.string && value && !wstrcmp(e->value.string, value, action)) { break; } /* fallthrough */ default: if (WJE_GET != (action & WJE_ACTION_MASK)) { _WJEChanged(e); } break; } } if (last) *last = (WJElement) e; switch ((action & WJE_ACTION_MASK)) { default: case WJE_GET: if (!e) return((char *) value); switch (e->pub.type) { case WJR_TYPE_STRING: if (e->value.string) { return(e->value.string); } else { break; } case WJR_TYPE_BOOL: case WJR_TYPE_TRUE: case WJR_TYPE_FALSE: if (e->value.boolean) { return("true"); } else { return("false"); } default: case WJR_TYPE_NUMBER: #ifdef WJE_DISTINGUISH_INTEGER_TYPE case WJR_TYPE_INTEGER: #endif case WJR_TYPE_UNKNOWN: case WJR_TYPE_NULL: case WJR_TYPE_OBJECT: case WJR_TYPE_ARRAY: break; } return((char *) value); case WJE_SET: case WJE_NEW: case WJE_PUT: if ((e = _WJEReset(e, WJR_TYPE_STRING))) { if (!value) { return((e->value.string = NULL)); } else { e->value.string = MemMallocWait(len + 1); strncpy(e->value.string, value, len); e->value.string[len] = '\0'; MemUpdateOwner(e->value.string, file, line); e->pub.length = len; return(e->value.string); } } else { return(NULL); } } }
static WJElement _WJELoad(_WJElement *parent, WJReader reader, char *where, WJELoadCB loadcb, void *data, const char *file, const int line) { char *current, *name, *value; _WJElement *l = NULL; XplBool complete; size_t actual, used, len; if (!reader) { return((WJElement) _WJENew(NULL, NULL, 0, file, line)); } if (!where) { /* A NULL poisition in a WJReader indicates the root of the document, so we must read to find the first real object. */ where = WJRNext(NULL, 2048, reader); } if (!where) { /* This appears to be an empty document */ return(NULL); } name = where[1] ? where + 1 : NULL; if (name && (WJEChild((WJElement) parent, name, WJE_GET))) { /* Do not load duplicate names */ return(NULL); } if (loadcb && !loadcb((WJElement)parent, name, data, file, line)) { /* The consumer has rejected this item */ return(NULL); } if ((l = _WJENew(parent, name, name ? strlen(name) : 0, file, line))) { switch ((l->pub.type = *where)) { default: case WJR_TYPE_UNKNOWN: case WJR_TYPE_NULL: break; case WJR_TYPE_OBJECT: case WJR_TYPE_ARRAY: while (reader && (current = WJRNext(where, 2048, reader))) { _WJELoad(l, reader, current, loadcb, data, file, line); } break; case WJR_TYPE_STRING: actual = 0; used = 0; len = 0; complete = FALSE; l->value.string = NULL; l->pub.length = 0; do { if ((value = WJRStringEx(&complete, &len, reader))) { if (used + len >= actual) { l->value.string = MemMallocEx(l->value.string, len + 1 + used, &actual, TRUE, TRUE); MemUpdateOwner(l->value.string, file, line); } memcpy(l->value.string + used, value, len); used += len; l->value.string[used] = '\0'; l->pub.length = used; } } while (!complete); break; case WJR_TYPE_NUMBER: l->value.number.hasDecimalPoint = WJRIntOrDouble(reader, &l->value.number.i, &l->value.number.d); if (WJRNegative(reader)) { /* Store the number as a positive, but keep track of the fact that it was negative. */ l->value.number.negative = TRUE; } else { l->value.number.negative = FALSE; } break; case WJR_TYPE_TRUE: l->value.boolean = TRUE; break; case WJR_TYPE_BOOL: case WJR_TYPE_FALSE: l->value.boolean = FALSE; break; } } return((WJElement) l); }