Пример #1
0
int o_json_parse_string(void * ctx, const unsigned char * v, unsigned int l)
{
    o_json_parse_context * pc = (o_json_parse_context *) ctx;
    orderly_json * n = orderly_alloc_json(pc->alloc, orderly_json_string);
    BUF_STRDUP(n->v.s, pc->alloc, v, l);
    PUSH_NODE(pc, n);
    return 1;
}
Пример #2
0
int o_json_parse_map_key(void * ctx, const unsigned char * v,
                         unsigned int l)
{
    o_json_parse_context * pc = (o_json_parse_context *) ctx;
    char * k = NULL;
    BUF_STRDUP(k, pc->alloc, v, l);
    orderly_ps_push(pc->alloc, pc->keyStack, k);
    return 1;
}
Пример #3
0
orderly_json *
orderly_clone_json(orderly_alloc_funcs * alloc, orderly_json * j)
{
    orderly_json * copy = NULL;
    if (!j) return copy;
    copy = orderly_alloc_json(alloc, j->t);
    if (j->k) BUF_STRDUP(copy->k, alloc, j->k, strlen(j->k));
    
    switch(j->t) {
        case orderly_json_none:
        case orderly_json_null:
            break;
        case orderly_json_string:
            if (j->v.s) BUF_STRDUP(copy->v.s, alloc, j->v.s, strlen(j->v.s));
            break;
        case orderly_json_boolean:
            copy->v.b = j->v.b;
            break;
        case orderly_json_integer:
            copy->v.i = j->v.i;
            break;
        case orderly_json_number:
            copy->v.n = j->v.n;
            break;
        case orderly_json_object:
        case orderly_json_array: {
            /* here's the deep copy part */
            orderly_json * p;

            for (p = j->v.children.first; p != NULL; p = p->next) {
                orderly_json * nk = orderly_clone_json(alloc, p);
                if (copy->v.children.last) {
                    copy->v.children.last->next = nk;
                    copy->v.children.last = nk;
                } else {
                    copy->v.children.first = copy->v.children.last = nk;
                }
            }
            break;
        }
    }
    return copy;
}
Пример #4
0
void ajv_set_error ( ajv_state s, ajv_error e,
                     const ajv_node * node, const char *info, int infolen ) {

  ajv_clear_error(s);
  s->error.node = node;
  s->error.code = e;
  if (info) {
    BUF_STRDUP(s->error.extra_info, 
               s->AF, info, infolen);
  }

}
Пример #5
0
unsigned char * ajv_get_error(ajv_handle hand, int verbose,
                              const unsigned char * jsonText,
                              unsigned int jsonTextLength) {
  char * yajl_err;
  orderly_buf ret = orderly_buf_alloc(hand->AF);
  ajv_state s = hand;
  unsigned char *cret;
  struct ajv_error_t *e = &(s->error);

  int yajl_length;
  const char *fn;
  if (e->node) {
    fn = ajv_node_format(e->node->node);
  }
  if (e->code == ajv_e_no_error) { 
    return yajl_get_error(hand->yajl,verbose,jsonText,jsonTextLength);
  } 

  /* include the yajl error message when verbose */
  if (verbose == 1) {
    yajl_err = 
      (char *)yajl_get_error(hand->yajl,verbose,
                             (unsigned char *)jsonText,jsonTextLength);

    yajl_length = strlen(yajl_err);
  }

  if (e->code == ajv_e_out_of_range) {
    const orderly_node *on = e->node->node;
    const char *type = orderly_node_type_to_string(on->t);
    orderly_buf_append_string(ret,type);
    if (on->t == orderly_node_array
        || on->t == orderly_node_string) {
      orderly_buf_append_string(ret," length");
    }
    orderly_buf_append_string(ret," ");
    orderly_buf_append_string(ret,e->extra_info);
    orderly_buf_append_string(ret," not in range ");
    if (ORDERLY_RANGE_SPECIFIED(on->range)) {
      char buf[128];
      orderly_buf_append_string(ret, "{");
      buf[0] = 0;
      if (ORDERLY_RANGE_LHS_DOUBLE & on->range.info)
        sprintf(buf, "%.15g", on->range.lhs.d);
      else if (ORDERLY_RANGE_LHS_INT & on->range.info)
        sprintf(buf, "%ld", on->range.lhs.i);
      if (buf[0]) orderly_buf_append_string(ret, buf);
      orderly_buf_append_string(ret, ",");
      buf[0] = 0;
      if (ORDERLY_RANGE_RHS_DOUBLE & on->range.info)
        sprintf(buf, "%.15g", on->range.rhs.d);
      else if (ORDERLY_RANGE_RHS_INT & on->range.info)
        sprintf(buf, "%ld", on->range.rhs.i);
      if (buf[0]) orderly_buf_append_string(ret, buf);
      orderly_buf_append_string(ret, "}");
    }
  } else {
    orderly_buf_append_string(ret, (const char *)ajv_error_to_string(e->code));
  }

  if (e->code == ajv_e_invalid_format) {
    orderly_buf_append_string(ret, " '");
    orderly_buf_append_string(ret, fn);
    orderly_buf_append_string(ret, "':");
  }

  if (e->extra_info) {
    if (e->code == ajv_e_incomplete_container) {
      if (e->node) {
        if (e->node->node->t == orderly_node_object) {
          orderly_buf_append_string(ret, ", object missing required property");
        } else {
          orderly_buf_append_string(ret, ", tuple missing ");
          orderly_buf_append_string(ret, e->extra_info);
          orderly_buf_append_string(ret, " elements");
        }
      }
    }
    if (e->code == ajv_e_illegal_value) {
      orderly_buf_append_string(ret, ":");
    }
    if (e->code != ajv_e_out_of_range 
        && !(e->code == ajv_e_incomplete_container 
             && e->node 
             && e->node->node->t == orderly_node_array)) {
      orderly_buf_append_string(ret, " '");
      orderly_buf_append_string(ret, e->extra_info);
      orderly_buf_append_string(ret, "'");
    }
  }

  if (e->node) {
      if (e->code == ajv_e_type_mismatch) {
        if (e->node->node->name) {
          orderly_buf_append_string(ret, " for property '");
          orderly_buf_append_string(ret, e->node->node->name);
          orderly_buf_append_string(ret, "'");
        }
        if (e->node->parent && e->node->parent->node->tuple_typed == 1) {
          ajv_node_state ns = (ajv_node_state)orderly_ps_current(s->node_state);
          char buf[128];
          orderly_buf_append_string(ret, " for array element ");
          snprintf(buf,128,"%d",orderly_ps_length(ns->seen)+1);
          orderly_buf_append_string(ret,buf);
        }
        orderly_buf_append_string(ret, ", expected '");
        orderly_buf_append_string(ret, orderly_node_type_to_string(e->node->node->t));
        orderly_buf_append_string(ret, "'");
      }
  }
  if (e->code == ajv_e_unexpected_key) {
        orderly_buf_append_string(ret, ", while additionalProperties forbidden");
  }
  orderly_buf_append_string(ret,".");
  BUF_STRDUP(cret, hand->AF, orderly_buf_data(ret),
             orderly_buf_len(ret));
  orderly_buf_free(ret);
  return cret;
}
Пример #6
0
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,
                                          &regerror,
                                          &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;
}