static bool jarray_to_string_append (jvalue_ref jref, JStreamRef generating) { ssize_t i; assert(jis_array(jref)); if (UNLIKELY(!generating)) { PJ_LOG_ERR("Cannot append string value to NULL output stream"); return false; } SANITY_CHECK_POINTER(jref); if (UNLIKELY(jis_null(jref))) { PJ_LOG_ERR("INTERNAL ERROR!!!!!!!!!! - used internal API for array --> string for JSON null"); generating->null_value (generating); return false; } if (UNLIKELY(!generating->a_begin (generating))) { PJ_LOG_ERR("Schema validation error, arrays are not allowed"); return false; } for (i = 0; i < jarray_size (jref); i++) { jvalue_ref toAppend = jarray_get (jref, i); SANITY_CHECK_POINTER(toAppend); if (UNLIKELY(!jvalue_to_string_append (toAppend, generating))) { return false; } } if (UNLIKELY(!generating->a_end (generating))) { PJ_LOG_ERR("Schema validation error, array did not validate against schema"); return false; } return true; }
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; }
static bool jobject_to_string_append (jvalue_ref jref, JStreamRef generating) { SANITY_CHECK_POINTER(jref); if (UNLIKELY(!generating->o_begin (generating))) { PJ_LOG_ERR("Schema validation error, objects are not allowed."); return false; } if (!jis_object (jref)) { const char *asStr = jvalue_tostring_internal_layer2 (jref, NULL, false); generating->string (generating, J_CSTR_TO_BUF("Internal error - not an object")); generating->string (generating, j_cstr_to_buffer(asStr)); // create invalid JSON on purpose return false; } jobject_iter it; jobject_iter_init(&it, jref); jobject_key_value key_value; while (jobject_iter_next(&it, &key_value)) { assert(jis_string(key_value.key)); if(UNLIKELY(!key_value_to_string_append(key_value, generating))) { return false; } } if (UNLIKELY(!generating->o_end (generating))) { PJ_LOG_ERR("Schema validation error, object did not validate against schema"); return false; } return true; }
static const char *jvalue_tostring_internal_layer2 (jvalue_ref val, JSchemaInfoRef schemainfo, bool schemaNecessary) { SANITY_CHECK_POINTER(val); CHECK_POINTER_RETURN_VALUE(val, "null"); if (!val->m_toString) { if (schemaNecessary && !jvalue_check_schema(val, schemainfo)) { return NULL; } bool parseok = false; StreamStatus error; JStreamRef generating = jstreamInternal(TOP_None); if (generating == NULL) { return NULL; } parseok = jvalue_to_string_append (val, generating); val->m_toString = generating->finish (generating, &error); val->m_toStringDealloc = free; assert (val->m_toString != NULL); if(!parseok) { return NULL; } } return val->m_toString; }
static bool jnumber_to_string_append (jvalue_ref jref, JStreamRef generating) { SANITY_CHECK_POINTER(jref); if (jnum_deref(jref)->m_error) { PJ_LOG_WARN("converting a number that has an error (%d) set to a string", jnum_deref(jref)->m_error); } bool ok = false; switch (jnum_deref(jref)->m_type) { case NUM_RAW: assert(jnum_deref(jref)->value.raw.m_len != 0); ok = (generating->number (generating, jnum_deref(jref)->value.raw) != NULL); break; case NUM_FLOAT: ok = (generating->floating (generating, jnum_deref(jref)->value.floating) != NULL); break; case NUM_INT: ok = (generating->integer (generating, jnum_deref(jref)->value.integer) != NULL); break; default: // mismatched on purpose so that generation yields an error assert(false); generating->o_begin (generating); raw_buffer asStrBuf = J_CSTR_TO_BUF("Error - Unrecognized number type"); generating->string (generating, asStrBuf); generating->integer (generating, jnum_deref(jref)->m_type); break; } return ok; }
static bool jvalue_to_string_append (jvalue_ref jref, JStreamRef generating) { SANITY_CHECK_POINTER(jref); if (jref == NULL) { PJ_LOG_ERR("Internal error. Using NULL pointer instead of reference to NULL JSON object"); jref = &JNULL; } CHECK_POINTER_MSG_RETURN_VALUE(generating, false, "Internal problem due to buffer to append to being null"); bool success = false; switch (jref->m_type) { case JV_NULL: success = (generating->null_value (generating) != NULL); if (UNLIKELY(!success)) { PJ_LOG_ERR("Schema validation error, null value not accepted"); } break; case JV_OBJECT: success = jobject_to_string_append (jref, generating); break; case JV_ARRAY: success = jarray_to_string_append (jref, generating); break; case JV_NUM: success = jnumber_to_string_append (jref, generating); break; case JV_STR: success = jstring_to_string_append (jref, generating); break; case JV_BOOL: success = jboolean_to_string_append (jref, generating); break; default: PJ_LOG_ERR("Internal error. Unknown jvalue type"); break; } return success; }
bool jsaxparser_init(jsaxparser_ref parser, JSchemaInfoRef schemaInfo, PJSAXCallbacks *callback, void *callback_ctxt) { memset(parser, 0, sizeof(struct jsaxparser) - sizeof(mem_pool_t)); parser->validator = NOTHING_VALIDATOR; parser->uri_resolver = NULL; parser->schemaInfo = schemaInfo; if (schemaInfo && schemaInfo->m_schema) { parser->validator = schemaInfo->m_schema->validator; parser->uri_resolver = schemaInfo->m_schema->uri_resolver; } if (callback == NULL) { parser->yajl_cb = no_callbacks; } else { parser->yajl_cb.yajl_null = callback->m_null ? (pj_yajl_null)callback->m_null : no_callbacks.yajl_null; parser->yajl_cb.yajl_boolean = callback->m_boolean ? (pj_yajl_boolean)callback->m_boolean : no_callbacks.yajl_boolean; parser->yajl_cb.yajl_integer = NULL; parser->yajl_cb.yajl_double = NULL; parser->yajl_cb.yajl_number = callback->m_number ? (pj_yajl_number)callback->m_number : no_callbacks.yajl_number; parser->yajl_cb.yajl_string = callback->m_string ? (pj_yajl_string)callback->m_string : no_callbacks.yajl_string; parser->yajl_cb.yajl_start_map = callback->m_objStart ? (pj_yajl_start_map)callback->m_objStart : no_callbacks.yajl_start_map; parser->yajl_cb.yajl_map_key = callback->m_objKey ? (pj_yajl_map_key)callback->m_objKey : no_callbacks.yajl_map_key; parser->yajl_cb.yajl_end_map = callback->m_objEnd ? (pj_yajl_end_map)callback->m_objEnd : no_callbacks.yajl_end_map; parser->yajl_cb.yajl_start_array = callback->m_arrStart ? (pj_yajl_start_array)callback->m_arrStart : no_callbacks.yajl_start_array; parser->yajl_cb.yajl_end_array = callback->m_arrEnd ? (pj_yajl_end_array)callback->m_arrEnd : no_callbacks.yajl_end_array; } parser->errorHandler.m_parser = err_parser; parser->errorHandler.m_schema = err_schema; parser->errorHandler.m_unknown = err_unknown; parser->errorHandler.m_ctxt = parser; validation_state_init(&(parser->validation_state), parser->validator, parser->uri_resolver, &jparse_notification); PJSAXContext __internalCtxt = { .ctxt = (callback_ctxt != NULL ? callback_ctxt : NULL), .m_handlers = &parser->yajl_cb, .m_errors = &parser->errorHandler, .m_error_code = 0, .errorDescription = NULL, .validation_state = &parser->validation_state, }; parser->internalCtxt = __internalCtxt; mempool_init(&parser->memory_pool); yajl_alloc_funcs allocFuncs = { mempool_malloc, mempool_realloc, mempool_free, &parser->memory_pool }; const bool allow_comments = true; #if YAJL_VERSION < 20000 yajl_parser_config yajl_opts = { allow_comments, 0, // currently only UTF-8 will be supported for input. }; parser->handle = yajl_alloc(&my_bounce, &yajl_opts, &allocFuncs, &parser->internalCtxt); #else parser->handle = yajl_alloc(&my_bounce, &allocFuncs, &parser->internalCtxt); yajl_config(parser->handle, yajl_allow_comments, allow_comments ? 1 : 0); // currently only UTF-8 will be supported for input. yajl_config(parser->handle, yajl_dont_validate_strings, 1); #endif // YAJL_VERSION return true; } static bool jsaxparser_process_error(jsaxparser_ref parser, const char *buf, int buf_len, bool final_stage) { if ( #if YAJL_VERSION < 20000 (final_stage || yajl_status_insufficient_data != parser->status) && #endif !handle_yajl_error(parser->status, parser->handle, buf, buf_len, parser->schemaInfo, &parser->internalCtxt) ) { if (parser->yajlError) { yajl_free_error(parser->handle, (unsigned char*)parser->yajlError); parser->yajlError = NULL; } parser->yajlError = (char*)yajl_get_error(parser->handle, 1, (unsigned char*)buf, buf_len); return false; } return true; } const char *jsaxparser_get_error(jsaxparser_ref parser) { SANITY_CHECK_POINTER(parser); if (parser->schemaError) return parser->schemaError; if (parser->yajlError) return parser->yajlError; return NULL; }
static void *jsaxparser_get_sax_context(jsaxparser_ref parser) { SANITY_CHECK_POINTER(parser); return jsax_getContext(&parser->internalCtxt); }