int dom_number(JSAXContextRef ctxt, const char *number, size_t numberLen) { DomInfo *data = getDOMContext(ctxt); jvalue_ref jnum; CHECK_CONDITION_RETURN_VALUE(data == NULL, 0, "number encountered without any context"); CHECK_CONDITION_RETURN_VALUE(data->m_prev == NULL, 0, "unexpected state - how is this possible?"); CHECK_POINTER_RETURN_VALUE(number, 0); CHECK_CONDITION_RETURN_VALUE(numberLen == 0, 0, "unexpected - numeric string doesn't actually contain a number"); jnum = createOptimalNumber(data->m_optInformation, number, numberLen); if (data->m_value == NULL) { if (UNLIKELY(!jis_array(data->m_prev->m_value))) { PJ_LOG_ERR("PBNJSON_ARR_MISPLACED_NUM", 1, PMLOGKS("NUM", number), "Improper place for number"); j_release(&jnum); return 0; } jarray_append(data->m_prev->m_value, jnum); } else if (jis_string(data->m_value)) { if (UNLIKELY(!jis_object(data->m_prev->m_value))) { PJ_LOG_ERR("PBNJSON_OBJ_MISPLACED_NUM", 1, PMLOGKS("NUM", number), "Improper place for number"); j_release(&jnum); return 0; } jobject_put(data->m_prev->m_value, data->m_value, jnum); data->m_value = NULL; } else { PJ_LOG_ERR("PBNJSON_NUM_VALUE_WO_KEY", 1, PMLOGKS("NUM", number), "value portion of key-value pair without a key"); return 0; } return 1; }
int dom_null(JSAXContextRef ctxt) { DomInfo *data = getDOMContext(ctxt); // no handle to the context CHECK_CONDITION_RETURN_VALUE(data == NULL, 0, "null encountered without any context"); // no parent node CHECK_CONDITION_RETURN_VALUE(data->m_prev == NULL, 0, "unexpected state - how is this possible?"); SANITY_CHECK_POINTER(ctxt); SANITY_CHECK_POINTER(data->m_prev); if (data->m_value == NULL) { CHECK_CONDITION_RETURN_VALUE(!jis_array(data->m_prev->m_value), 0, "Improper place for null"); jarray_append(data->m_prev->m_value, jnull()); } else if (jis_string(data->m_value)) { CHECK_CONDITION_RETURN_VALUE(!jis_object(data->m_prev->m_value), 0, "Improper place for null"); jobject_put(data->m_prev->m_value, data->m_value, jnull()); data->m_value = NULL; } else { PJ_LOG_ERR("PBNJSON_NULL_VALUE_WO_KEY", 0, "value portion of key-value pair without a key"); return 0; } return 1; }
int dom_string(JSAXContextRef ctxt, const char *string, size_t stringLen) { DomInfo *data = getDOMContext(ctxt); CHECK_CONDITION_RETURN_VALUE(data == NULL, 0, "string encountered without any context"); CHECK_CONDITION_RETURN_VALUE(data->m_prev == NULL, 0, "unexpected state - how is this possible?"); jvalue_ref jstr = createOptimalString(data->m_optInformation, string, stringLen); if (data->m_value == NULL) { if (UNLIKELY(!jis_array(data->m_prev->m_value))) { PJ_LOG_ERR("PBNJSON_ARR_MISPLACED_STR", 1, PMLOGKS("STRING", string), "Improper place for string"); j_release(&jstr); return 0; } jarray_append(data->m_prev->m_value, jstr); } else if (jis_string(data->m_value)) { if (UNLIKELY(!jis_object(data->m_prev->m_value))) { PJ_LOG_ERR("PBNJSON_OBJ_MISPLACED_STR", 1, PMLOGKS("STRING", string), "Improper place for string"); j_release(&jstr); return 0; } jobject_put(data->m_prev->m_value, data->m_value, jstr); data->m_value = NULL; } else { PJ_LOG_ERR("PBNJSON_STR_VALUE_WO_KEY", 1, PMLOGKS("STRING", string), "value portion of key-value pair without a key"); return 0; } return 1; }
static int dom_object_start(JSAXContextRef ctxt) { DomInfo *data = getDOMContext(ctxt); jvalue_ref newParent; DomInfo *newChild; CHECK_CONDITION_RETURN_VALUE(data == NULL, 0, "object encountered without any context"); newParent = jobject_create(); newChild = calloc(1, sizeof(DomInfo)); if (UNLIKELY(newChild == NULL || jis_null(newParent))) { PJ_LOG_ERR("Failed to allocate space for new object"); j_release(&newParent); free(newChild); return 0; } newChild->m_prev = data; newChild->m_optInformation = data->m_optInformation; changeDOMContext(ctxt, newChild); if (data->m_prev != NULL) { if (jis_array(data->m_prev->m_value)) { assert(data->m_value == NULL); jarray_append(data->m_prev->m_value, newParent); } else { assert(jis_object(data->m_prev->m_value)); CHECK_CONDITION_RETURN_VALUE(!jis_string(data->m_value), 0, "improper place for a child object"); jobject_put(data->m_prev->m_value, data->m_value, newParent); } } // not using reference counting here on purpose data->m_value = newParent; return 1; }
static int dom_array_end(JSAXContextRef ctxt) { DomInfo *data = getDOMContext(ctxt); CHECK_CONDITION_RETURN_VALUE(data == NULL, 0, "array end encountered without any context"); CHECK_CONDITION_RETURN_VALUE(data->m_value != NULL, 0, "key/value for array"); CHECK_CONDITION_RETURN_VALUE(!jis_array(data->m_prev->m_value), 0, "array end encountered, but not in an array"); assert(data->m_prev != NULL); changeDOMContext(ctxt, data->m_prev); if (data->m_prev->m_prev != NULL) data->m_prev->m_value = NULL; free(data); return 1; }
static int dom_object_end(JSAXContextRef ctxt) { DomInfo *data = getDOMContext(ctxt); CHECK_CONDITION_RETURN_VALUE(data == NULL, 0, "object end encountered without any context"); CHECK_CONDITION_RETURN_VALUE(data->m_value != NULL, 0, "mismatch between key/value count"); CHECK_CONDITION_RETURN_VALUE(!jis_object(data->m_prev->m_value), 0, "object end encountered, but not in an object"); assert(data->m_prev != NULL); changeDOMContext(ctxt, data->m_prev); if (data->m_prev->m_prev != NULL) data->m_prev->m_value = NULL; free(data); return 1; }
int dom_object_key(JSAXContextRef ctxt, const char *key, size_t keyLen) { DomInfo *data = getDOMContext(ctxt); CHECK_CONDITION_RETURN_VALUE(data == NULL, 0, "object key encountered without any context"); CHECK_CONDITION_RETURN_VALUE(data->m_value != NULL, 0, "Improper place for an object key"); CHECK_CONDITION_RETURN_VALUE(data->m_prev == NULL, 0, "object key encountered without any parent object"); CHECK_CONDITION_RETURN_VALUE(!jis_object(data->m_prev->m_value), 0, "object key encountered without any parent object"); // Need to be careful here - typically, m_value isn't reference counted // thus if parsing fails and m_value hasn't been inserted into a bigger object that is // tracked, we will leak. // The alternate behaviour is to insert into the parent value with a null value. // Then when inserting the value of the key/value pair into an object, we first remove the key & re-insert // a key/value pair (we don't currently have a replace mechanism). data->m_value = createOptimalString(data->m_optInformation, key, keyLen); return 1; }
int dom_object_end(JSAXContextRef ctxt) { DomInfo *data = getDOMContext(ctxt); CHECK_CONDITION_RETURN_VALUE(data == NULL, 0, "object end encountered without any context"); CHECK_CONDITION_RETURN_VALUE(data->m_value != NULL, 0, "mismatch between key/value count"); CHECK_CONDITION_RETURN_VALUE(!jis_object(data->m_prev->m_value), 0, "object end encountered, but not in an object"); assert(data->m_prev != NULL); changeDOMContext(ctxt, data->m_prev); if (data->m_prev->m_prev != NULL) { j_release(&data->m_prev->m_value); // 0xdeadbeef may be written in debug mode, which fools the code data->m_prev->m_value = NULL; } free(data); return 1; }
int dom_boolean(JSAXContextRef ctxt, bool value) { DomInfo *data = getDOMContext(ctxt); CHECK_CONDITION_RETURN_VALUE(data == NULL, 0, "boolean encountered without any context"); CHECK_CONDITION_RETURN_VALUE(data->m_prev == NULL, 0, "unexpected state - how is this possible?"); if (data->m_value == NULL) { CHECK_CONDITION_RETURN_VALUE(!jis_array(data->m_prev->m_value), 0, "Improper place for boolean"); jarray_append(data->m_prev->m_value, jboolean_create(value)); } else if (jis_string(data->m_value)) { CHECK_CONDITION_RETURN_VALUE(!jis_object(data->m_prev->m_value), 0, "Improper place for boolean"); jobject_put(data->m_prev->m_value, data->m_value, jboolean_create(value)); data->m_value = NULL; } else { PJ_LOG_ERR("PBNJSON_BOOL_VALUE_WO_KEY", 0, "value portion of key-value pair without a key"); return 0; } return 1; }
int dom_object_start(JSAXContextRef ctxt) { DomInfo *data = getDOMContext(ctxt); jvalue_ref newParent; DomInfo *newChild; CHECK_CONDITION_RETURN_VALUE(data == NULL, 0, "object encountered without any context"); newParent = jobject_create(); newChild = calloc(1, sizeof(DomInfo)); if (UNLIKELY(newChild == NULL || !jis_valid(newParent))) { PJ_LOG_ERR("PBNJSON_OBJ_CALLOC_ERR", 0, "Failed to allocate space for new object"); j_release(&newParent); free(newChild); return 0; } newChild->m_prev = data; newChild->m_optInformation = data->m_optInformation; changeDOMContext(ctxt, newChild); if (data->m_prev != NULL) { if (jis_array(data->m_prev->m_value)) { assert(data->m_value == NULL); jarray_append(data->m_prev->m_value, jvalue_copy(newParent)); } else { assert(jis_object(data->m_prev->m_value)); if (UNLIKELY(!jis_string(data->m_value))) { PJ_LOG_ERR("PBNJSON_OBJ_MISPLACED_CHILD", 0, "improper place for a child object"); j_release(&newParent); return 0; } jobject_put(data->m_prev->m_value, data->m_value, jvalue_copy(newParent)); } } data->m_value = newParent; return 1; }
static inline bool jsax_parse_inject_internal(JSAXContextRef ctxt, jvalue_ref key, jvalue_ref value) { assert (ctxt != NULL); assert (value != NULL); yajl_callbacks *cbs = ctxt->m_handlers; raw_buffer str; if (key) { str = jstring_get_fast(key); if (UNLIKELY(!cbs->yajl_map_key(ctxt, (const unsigned char *)str.m_str, str.m_len))) return false; } switch (value->m_type) { case JV_OBJECT: { jobject_key_value keyval; if (UNLIKELY(!cbs->yajl_start_map(ctxt))) return false; for (jobject_iter i = jobj_iter_init(value); jobj_iter_is_valid(i); i = jobj_iter_next(i)) { jobj_iter_deref(i, &keyval); if (UNLIKELY(!jsax_parse_inject(ctxt, keyval.key, keyval.value))) return false; } if (UNLIKELY(!cbs->yajl_end_map(ctxt))) return false; break; } case JV_ARRAY: { jvalue_ref item; if (UNLIKELY(!cbs->yajl_start_array(ctxt))) return false; for (ssize_t i = jarray_size(value) - 1; i >= 0; i--) { item = jarray_get(value, i); if (UNLIKELY(!jsax_parse_inject(ctxt, NULL, item))) return false; } if (UNLIKELY(!cbs->yajl_end_array(ctxt))) return false; break; } case JV_STR: { str = jstring_get_fast(value); if (UNLIKELY(!cbs->yajl_string(ctxt, (const unsigned char *)str.m_str, str.m_len))) return false; break; } case JV_NUM: { assert (value->value.val_num.m_type == NUM_RAW); // this numeric string should have come directly from a schema - we don't do any conversion internally. // how did this state occur? CHECK_CONDITION_RETURN_VALUE(value->value.val_num.m_type != NUM_RAW, false, "Some internal problem parsing schema"); str = jnumber_deref_raw(value); if (UNLIKELY(!cbs->yajl_number(ctxt, str.m_str, str.m_len))) return false; break; } case JV_BOOL: { if (UNLIKELY(!cbs->yajl_boolean(ctxt, jboolean_deref(value)))) return false; break; } case JV_NULL: { if (UNLIKELY(!cbs->yajl_null(ctxt))) return false; break; } default: { // how can this occur? - memory corruption? PJ_SCHEMA_ERR("Internal error - schema is corrupt"); return false; } } return true; }