#include "jsoncdaccord.h" #include "internal.h" #include "optional.h" enum subschematype { JDAC_ALLOF = 0, JDAC_ANYOF, JDAC_ONEOF }; // shall return valid or invalid based on subschema type int _jdac_test_subschema_array(json_object *jobj, json_object *jsubschema_array, enum subschematype type) { if (jsubschema_array == NULL) { return JDAC_ERR_VALID; } // MUST be a non-empty array if (!json_object_is_type(jsubschema_array, json_type_array)) { return JDAC_ERR_SCHEMA_ERROR; } int arraylen = (int)json_object_array_length(jsubschema_array); if (arraylen == 0) { return JDAC_ERR_SCHEMA_ERROR; } int number_of_valid_schemas = 0; for (int i = 0; i < arraylen; i++) { json_object *jsubschema = json_object_array_get_idx(jsubschema_array, i); if (!json_object_is_type(jsubschema, json_type_object) && !json_object_is_type(jsubschema, json_type_boolean)) { return JDAC_ERR_SCHEMA_ERROR; } int err = _jdac_validate_instance(jobj, jsubschema); if (err == JDAC_ERR_VALID) { number_of_valid_schemas++; } else if (err == JDAC_ERR_SCHEMA_ERROR) { return JDAC_ERR_SCHEMA_ERROR; } else { // continue } } if (type == JDAC_ALLOF) { if (number_of_valid_schemas == arraylen) { return JDAC_ERR_VALID; } } else if (type == JDAC_ANYOF) { if (number_of_valid_schemas > 0) { return JDAC_ERR_VALID; } } else if (type == JDAC_ONEOF) { if (number_of_valid_schemas == 1) { return JDAC_ERR_VALID; } } return JDAC_ERR_INVALID_SUBSCHEMALOGIC; } int _jdac_check_subschemalogic(json_object *jobj, json_object *jschema) { int err; json_object *jarray; jarray = json_object_object_get(jschema, "allOf"); err = _jdac_test_subschema_array(jobj, jarray, JDAC_ALLOF); if (err) { return JDAC_ERR_INVALID_SUBSCHEMALOGIC; } jarray = json_object_object_get(jschema, "anyOf"); err = _jdac_test_subschema_array(jobj, jarray, JDAC_ANYOF); if (err) { return JDAC_ERR_INVALID_SUBSCHEMALOGIC; } jarray = json_object_object_get(jschema, "oneOf"); err = _jdac_test_subschema_array(jobj, jarray, JDAC_ONEOF); if (err) { return JDAC_ERR_INVALID_SUBSCHEMALOGIC; } json_object *jnot = json_object_object_get(jschema, "not"); if (jnot) { // "not" is special, and MUST be a json object if (json_object_is_type(jnot, json_type_object) || json_object_is_type(jnot, json_type_boolean)) { err = _jdac_validate_instance(jobj, jnot); if (err == JDAC_ERR_VALID) { return JDAC_ERR_INVALID_SUBSCHEMALOGIC; } else if (err == JDAC_ERR_SCHEMA_ERROR) { return JDAC_ERR_SCHEMA_ERROR; } else { return JDAC_ERR_VALID; } } else { return JDAC_ERR_SCHEMA_ERROR; } } json_object *if_schema = json_object_object_get(jschema, "if"); json_object *then_schema = json_object_object_get(jschema, "then"); json_object *else_schema = json_object_object_get(jschema, "else"); if (if_schema) { err = _jdac_validate_instance(jobj, if_schema); if (err == JDAC_ERR_VALID && then_schema) { err = _jdac_validate_instance(jobj, then_schema); return err; } else if (err != JDAC_ERR_VALID && else_schema) { err = _jdac_validate_instance(jobj, else_schema); return err; } } return JDAC_ERR_VALID; }