_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 __WJENull(WJElement container, const char *path, WJEAction action, WJElement *last, const char *file, const int line) { WJElement e; WJEAction a; /* Find an element that is appropriate for the given action, creating new elements as needed. When action is WJE_GET skip any elements of the wrong type. */ e = (last ? *last : NULL); do { a = action; e = WJESearch(container, path, &a, e, file, line); } while (e && (action & WJE_ACTION_MASK) == WJE_GET && e->type != WJR_TYPE_NULL); if (e) { switch (e->type) { case WJR_TYPE_UNKNOWN: /* A new object was created, and the changes count has already been updated. */ e->type = WJR_TYPE_NULL; break; case WJR_TYPE_NULL: break; default: if (WJE_GET != (action & WJE_ACTION_MASK)) { _WJEChanged(e); } break; } } if (last) *last = e; switch ((a & WJE_ACTION_MASK)) { case WJE_SET: case WJE_PUT: return(WJEReset(e, WJR_TYPE_NULL)); default: case WJE_GET: case WJE_NEW: return(e); } }
EXPORT double __WJEDouble(WJElement container, const char *path, WJEAction action, WJElement *last, double value, const char *file, const int line) { _WJElement *e; /* Find an element that is appropriate for the given action, creating new elements as needed. */ if ((e = _WJESearch(container, path, &action, last ? *last : NULL, file, line))) { 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_BOOL; break; case WJR_TYPE_NUMBER: #ifdef WJE_DISTINGUISH_INTEGER_TYPE case WJR_TYPE_INTEGER: #endif if (e->pub.type == WJR_TYPE_NUMBER) { if (e->value.number.negative) { if (e->value.number.d * -1.0 == value) { break; } } else { if (e->value.number.d == value) { break; } } } else { if (e->value.number.negative) { if ((double) e->value.number.i * -1.0 == value) { break; } } else { if ((double) e->value.number.i == value) { 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(value); switch (e->pub.type) { case WJR_TYPE_NUMBER: if (e->value.number.negative) { return(e->value.number.d * -1.0); } else { return(e->value.number.d); } break; #ifdef WJE_DISTINGUISH_INTEGER_TYPE case WJR_TYPE_INTEGER: if (e->value.number.negative) { return((double) e->value.number.i * -1.0); } else { return((double) e->value.number.i); } break; #endif case WJR_TYPE_BOOL: case WJR_TYPE_TRUE: case WJR_TYPE_FALSE: if (e->value.boolean) { return(1); } else { return(0); } break; default: return(0); } case WJE_SET: case WJE_NEW: case WJE_PUT: if ((e = _WJEReset(e, WJR_TYPE_NUMBER))) { if (value < 0) { e->value.number.negative = TRUE; e->value.number.d = -value; e->value.number.i = (uint64) -value; } else { e->value.number.negative = FALSE; e->value.number.d = value; e->value.number.i = (uint64) value; } if (e->value.number.d != (double) e->value.number.i) { e->value.number.hasDecimalPoint = TRUE; e->pub.type = WJR_TYPE_NUMBER; } else { #ifdef WJE_DISTINGUISH_INTEGER_TYPE e->pub.type = WJR_TYPE_INTEGER; #else e->pub.type = WJR_TYPE_NUMBER; #endif e->value.number.hasDecimalPoint = FALSE; } return(value); } else { /* Negate the value - It must NOT match the original */ return(-value); } } }
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); } } }
EXPORT XplBool __WJEBool(WJElement container, const char *path, WJEAction action, WJElement *last, XplBool value, const char *file, const int line) { _WJElement *e; char *s; /* 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_BOOL; break; case WJR_TYPE_BOOL: case WJR_TYPE_TRUE: case WJR_TYPE_FALSE: if (e->value.boolean == value) { 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(value); switch (e->pub.type) { case WJR_TYPE_BOOL: case WJR_TYPE_TRUE: case WJR_TYPE_FALSE: return(e->value.boolean); case WJR_TYPE_NUMBER: return(e->value.number.d != 0); #ifdef WJE_DISTINGUISH_INTEGER_TYPE case WJR_TYPE_INTEGER: return(e->value.number.i != 0); #endif /* case WJR_TYPE_NUMBER: case WJR_TYPE_INTEGER: if (e->value.number.hasDecimalPoint) { return(e->value.number.d != 0); } else { return(e->value.number.i != 0); } break; */ default: case WJR_TYPE_UNKNOWN: case WJR_TYPE_NULL: /* Treat NULL as FALSE */ return(FALSE); case WJR_TYPE_OBJECT: case WJR_TYPE_ARRAY: /* TRUE based on the existance of the object */ return(TRUE); case WJR_TYPE_STRING: if ((s = e->value.string) && ( !stricmp(s, "true") || !stricmp(s, "yes") || !stricmp(s, "enabled") || !stricmp(s, "1") || !stricmp(s, "t") || !stricmp(s, "on") )) { return(TRUE); } else { return(FALSE); } } case WJE_SET: case WJE_NEW: case WJE_PUT: if ((e = _WJEReset(e, value ? WJR_TYPE_TRUE : WJR_TYPE_FALSE))) { return((e->value.boolean = value)); } else { return(!value); } } }
static void _WJENum(WJElement container, const char *path, WJEAction action, WJElement *last, void *value, size_t size, XplBool issigned, const char *file, const int line) { _WJElement *e; char *s, *end; uint64 r; uint64 v; XplBool negative; /* 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_NUMBER; break; case WJR_TYPE_NUMBER: #ifdef WJE_DISTINGUISH_INTEGER_TYPE case WJR_TYPE_INTEGER: #endif negative = FALSE; if ((e->value.number.i == _WJEGetNum(value, size, issigned, &negative)) && negative == e->value.number.negative ) { 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) { /* Leave value alone */ return; } switch (e->pub.type) { case WJR_TYPE_NUMBER: #ifdef WJE_DISTINGUISH_INTEGER_TYPE case WJR_TYPE_INTEGER: #endif _WJESetNum(value, size, issigned, e->value.number.i, e->value.number.negative); return; case WJR_TYPE_BOOL: case WJR_TYPE_TRUE: case WJR_TYPE_FALSE: if (e->value.boolean) { _WJESetNum(value, size, issigned, 1, FALSE); } else { _WJESetNum(value, size, issigned, 0, FALSE); } return; case WJR_TYPE_STRING: /* Does the string contain a number? */ s = skipspace(e->value.string); if(s[0] == '-') { negative = TRUE; ++s; } else { negative = FALSE; } r = strtoull(s, &end, 0); if (end != s && (!(s = skipspace(end)) || !*s)) { _WJESetNum(value, size, issigned, r, negative); return; } /* fallthrough */ default: case WJR_TYPE_UNKNOWN: case WJR_TYPE_NULL: case WJR_TYPE_OBJECT: case WJR_TYPE_ARRAY: return; } case WJE_SET: case WJE_NEW: case WJE_PUT: if ((e = _WJEReset(e, WJR_TYPE_NUMBER))) { e->value.number.negative = FALSE; e->value.number.hasDecimalPoint = FALSE; e->value.number.i = _WJEGetNum(value, size, issigned, &e->value.number.negative); e->value.number.d = (double) e->value.number.i; #ifdef WJE_DISTINGUISH_INTEGER_TYPE e->pub.type = WJR_TYPE_INTEGER; #else e->pub.type = WJR_TYPE_NUMBER; #endif return; } else { /* Negate the value - It must NOT match the original */ v = _WJEGetNum(value, size, issigned, &negative); _WJESetNum(value, size, issigned, !v, negative); return; } } }