orderly_reader orderly_reader_new(const orderly_alloc_funcs * alloc) { orderly_reader rdr = NULL; { static orderly_alloc_funcs orderlyAllocFuncBuffer; static orderly_alloc_funcs * orderlyAllocFuncBufferPtr = NULL; if (orderlyAllocFuncBufferPtr == NULL) { orderly_set_default_alloc_funcs(&orderlyAllocFuncBuffer); orderlyAllocFuncBufferPtr = &orderlyAllocFuncBuffer; } if (alloc == NULL) alloc = orderlyAllocFuncBufferPtr; } rdr = OR_MALLOC(alloc, sizeof(struct orderly_reader_t)); memcpy((void *) (&(rdr->alloc)), (void *) alloc, sizeof(orderly_alloc_funcs)); rdr->node = NULL; rdr->status = orderly_parse_s_ok; rdr->errBuf = NULL; rdr->finalOffset = 0; return rdr; }
orderly_json * orderly_alloc_json(orderly_alloc_funcs * alloc, orderly_json_type t) { orderly_json * n = (orderly_json *) OR_MALLOC(alloc, sizeof(orderly_json)); memset((void *) n, 0, sizeof(orderly_json)); n->t = t; return n; }
ajv_node_state ajv_alloc_node_state( const orderly_alloc_funcs * alloc, const ajv_node *node) { ajv_node_state n = (ajv_node_state)OR_MALLOC(alloc, sizeof(struct ajv_node_state_t)); memset((void *) n, 0, sizeof(struct ajv_node_state_t)); orderly_ps_init(n->required); orderly_ps_init(n->seen); n->node = node; return n; }
ajv_handle ajv_alloc(const yajl_callbacks * callbacks, const yajl_parser_config * config, const yajl_alloc_funcs * allocFuncs, void * ctx) { const orderly_alloc_funcs * AF = (const orderly_alloc_funcs *) allocFuncs; { static orderly_alloc_funcs orderlyAllocFuncBuffer; static orderly_alloc_funcs * orderlyAllocFuncBufferPtr = NULL; if (orderlyAllocFuncBufferPtr == NULL) { orderly_set_default_alloc_funcs(&orderlyAllocFuncBuffer); orderlyAllocFuncBufferPtr = &orderlyAllocFuncBuffer; } AF = orderlyAllocFuncBufferPtr; } struct ajv_state_t *ajv_state = (struct ajv_state_t *) OR_MALLOC(AF, sizeof(struct ajv_state_t)); memset((void *) ajv_state, 0, sizeof(struct ajv_state_t)); ajv_state->AF = AF; ajv_state->any.parent = ajv_state->any.child = ajv_state->any.sibling = NULL; ajv_state->any.node = orderly_alloc_node((orderly_alloc_funcs *)AF, orderly_node_any); ajv_state->cb = callbacks; ajv_state->cbctx = ctx; ajv_state->ypc = config; ajv_state->yajl = yajl_alloc(&(ajv_state->ourcb), config, allocFuncs, (void *)ajv_state); orderly_ps_init(ajv_state->node_state); return ajv_state; }
orderly_lexer orderly_lex_alloc(orderly_alloc_funcs * alloc) { static orderly_alloc_funcs orderlyAllocFuncBuffer; static orderly_alloc_funcs * orderlyAllocFuncBufferPtr = NULL; orderly_lexer lxr = NULL; if (orderlyAllocFuncBufferPtr == NULL) { orderly_set_default_alloc_funcs(&orderlyAllocFuncBuffer); orderlyAllocFuncBufferPtr = &orderlyAllocFuncBuffer; } if (alloc == NULL) alloc = orderlyAllocFuncBufferPtr; assert( alloc != NULL ); lxr = (orderly_lexer) OR_MALLOC(alloc, sizeof(struct orderly_lexer_t)); memset((void *) lxr, 0, sizeof(struct orderly_lexer_t)); lxr->alloc = alloc; lxr->previousOffset = 0; return lxr; }
static orderly_json_parse_status parse_json_schema(orderly_alloc_funcs * alloc, orderly_json * j, orderly_node ** n) { orderly_json_parse_status s = orderly_json_parse_s_ok; orderly_json * k; *n = NULL; if (j->t != orderly_json_object) { /* XXX: offset into the buffer!? */ return orderly_json_parse_s_object_expected; } *n = orderly_alloc_node(alloc, orderly_node_empty); (*n)->additional_properties = orderly_node_any; for (k=j->v.children.first; k != NULL; k=k->next) { if (k->k != NULL) { if (!strcmp(k->k, "type")) { if (k->t == orderly_json_string) { (*n)->t = orderly_string_to_node_type(k->v.s, strlen(k->v.s)); if ((*n)->t == orderly_node_empty) { s = orderly_json_parse_s_invalid_type_value; goto toErrIsHuman; } } else if (k->t == orderly_json_array) { /* support items containing an *array* of schema * for tuple typing */ orderly_json * pj = NULL; orderly_node ** last = &((*n)->child); (*n)->t = orderly_node_union; for (pj = k->v.children.first; pj; pj = pj->next) { s = parse_json_schema(alloc, pj, last); if (s != orderly_json_parse_s_ok) { goto toErrIsHuman; } last = &((*last)->sibling); } } else { s = orderly_json_parse_s_type_expects_string_or_array; goto toErrIsHuman; } } else if (!strcmp(k->k, "properties")) { orderly_json * p = NULL; orderly_node ** last = &((*n)->child); if (k->t != orderly_json_object) { s = orderly_json_parse_s_invalid_properties_value; goto toErrIsHuman; } for (p=k->v.children.first; p != NULL; p=p->next) { orderly_node * pn = NULL; s = parse_json_schema(alloc, p, &pn); if (pn) { *last = pn; last = &(pn->sibling); BUF_STRDUP(pn->name, alloc, p->k, strlen(p->k)); } if (s != orderly_json_parse_s_ok) { goto toErrIsHuman; } } } else if (!strcmp(k->k, "items")) { /* support items containing an *array* of schema * for tuple typing */ if (k->t == orderly_json_array) { orderly_json * pj = NULL; orderly_node ** last = &((*n)->child); (*n)->tuple_typed = 1; for (pj = k->v.children.first; pj; pj = pj->next) { s = parse_json_schema(alloc, pj, last); if (s != orderly_json_parse_s_ok) { goto toErrIsHuman; } last = &((*last)->sibling); } } else if (k->t == orderly_json_object) { orderly_node * pn = NULL; s = parse_json_schema(alloc, k, &pn); if (s != orderly_json_parse_s_ok) { goto toErrIsHuman; } (*n)->child = pn; } else { s = orderly_json_parse_s_items_gets_object_or_array; goto toErrIsHuman; } } else if (!strcmp(k->k, "optional")) { if (k->t != orderly_json_boolean) { s = orderly_json_parse_s_invalid_optional_value; goto toErrIsHuman; } (*n)->optional = k->v.b; } else if (!strcmp(k->k, "minimum")) { if (k->t == orderly_json_integer) { (*n)->range.info |= ORDERLY_RANGE_LHS_INT; (*n)->range.lhs.i = k->v.i; } else if (k->t == orderly_json_number) { (*n)->range.info |= ORDERLY_RANGE_LHS_DOUBLE; (*n)->range.lhs.d = k->v.n; } else { s = orderly_json_parse_s_minimum_requires_number; goto toErrIsHuman; } } else if (!strcmp(k->k, "maximum")) { if (k->t == orderly_json_integer) { (*n)->range.info |= ORDERLY_RANGE_RHS_INT; (*n)->range.rhs.i = k->v.i; } else if (k->t == orderly_json_number) { (*n)->range.info |= ORDERLY_RANGE_RHS_DOUBLE; (*n)->range.rhs.d = k->v.n; } else { s = orderly_json_parse_s_maximum_requires_number; goto toErrIsHuman; } } else if (!strcmp(k->k, "minLength")) { if (k->t == orderly_json_integer) { (*n)->range.info |= ORDERLY_RANGE_LHS_INT; (*n)->range.lhs.i = k->v.i; } else { s = orderly_json_parse_s_minlength_requires_integer; goto toErrIsHuman; } } else if (!strcmp(k->k, "maxLength")) { if (k->t == orderly_json_integer) { (*n)->range.info |= ORDERLY_RANGE_RHS_INT; (*n)->range.rhs.i = k->v.i; } else { s = orderly_json_parse_s_maxlength_requires_integer; goto toErrIsHuman; } } else if (!strcmp(k->k, "minItems")) { if (k->t == orderly_json_integer) { (*n)->range.info |= ORDERLY_RANGE_LHS_INT; (*n)->range.lhs.i = k->v.i; } else { s = orderly_json_parse_s_minitems_requires_integer; goto toErrIsHuman; } } else if (!strcmp(k->k, "maxItems")) { if (k->t == orderly_json_integer) { (*n)->range.info |= ORDERLY_RANGE_RHS_INT; (*n)->range.rhs.i = k->v.i; } else { s = orderly_json_parse_s_maxitems_requires_integer; goto toErrIsHuman; } } else if (!strcmp(k->k, "additionalProperties")) { if (k->t == orderly_json_boolean) { (*n)->additional_properties = k->v.b ? orderly_node_any : orderly_node_empty; } else if (k->t == orderly_json_object && !strcmp(k->v.children.first->k, "type")) { if (k->v.children.first->t == orderly_json_string) { (*n)->additional_properties = orderly_string_to_node_type(k->v.children.first->v.s, strlen(k->v.children.first->v.s)); } else { s = orderly_json_parse_s_invalid_type_value; goto toErrIsHuman; } } else { s = orderly_json_parse_s_addprop_requires_boolean; } } else if (!strcmp(k->k, "default")) { /* clone */ (*n)->default_value = orderly_clone_json(alloc, k); /* remove the key */ OR_FREE(alloc, (char *) (*n)->default_value->k); (*n)->default_value->k = NULL; } else if (!strcmp(k->k, "enum")) { /* clone */ (*n)->values = orderly_clone_json(alloc, k); /* remove the key */ OR_FREE(alloc, (char *) (*n)->values->k); (*n)->values->k = NULL; } else if (!strcmp(k->k, "pattern")) { if (k->t == orderly_json_string) { pcre *regex; const char *regerror; int erroffset; int error_code = 0; BUF_STRDUP((*n)->regex, alloc, k->v.s, strlen(k->v.s)); regex = pcre_compile2((*n)->regex, 0, &error_code, ®error, &erroffset, NULL); if (regex) { pcre_free(regex); } if (error_code != 0) { s = orderly_parse_s_regex_error + error_code; goto toErrIsHuman; } } else { s = orderly_json_parse_s_pattern_requires_string; goto toErrIsHuman; } } else if (!strcmp(k->k, "requires")) { if ((*n)->requires) { s = orderly_json_parse_s_duplicate_requires; goto toErrIsHuman; } if (k->t == orderly_json_string) { (*n)->requires = OR_MALLOC(alloc, 2 * sizeof(char *)); BUF_STRDUP((*n)->requires[0], alloc, k->v.s, strlen(k->v.s)); (*n)->requires[1] = NULL; } else if (k->t == orderly_json_array) { unsigned int num = 0; orderly_json * ks; for (ks = k->v.children.first; ks; ks = ks->next) { unsigned int i; char ** p; if (ks->t != orderly_json_string) { s = orderly_json_parse_s_requires_value_error; goto toErrIsHuman; } num++; p = OR_MALLOC(alloc, sizeof(char *) * (num + 1)); for (i = 0; i < num - 1; i++) p[i] = (char *) (*n)->requires[i]; BUF_STRDUP(p[i], alloc, ks->v.s, strlen(ks->v.s)); p[++i] = NULL; if ((*n)->requires) OR_FREE(alloc, (*n)->requires); (*n)->requires = (const char **) p; } } } else if (!strcmp(k->k, "$schema")) { /* XXX: detect schema version, and store it somewhere!?, then go back and adjust things */ } else { orderly_json ** jPtr; /* all unexpected properties are passed through using * the passthrough_properties element of the node. */ /* XXX: should this behavior be configurable? */ if ((*n)->passthrough_properties == NULL) { (*n)->passthrough_properties = orderly_alloc_json(alloc, orderly_json_object); } jPtr = &((*n)->passthrough_properties->v.children.first); while (*jPtr) jPtr = &((*jPtr)->next); /* clone onto the passthrough object */ (*jPtr) = orderly_clone_json(alloc, k); } } } /* json schema has some implied defaults, insert them */ interject_defaults(alloc,*n); return s; toErrIsHuman: if (*n) orderly_free_node(alloc, n); return s; }