static bool _check(Validator *v, ValidationEvent const *e, ValidationState *s, void *ctxt) { if (e->type != EV_NUM) { validation_state_notify_error(s, VEC_NOT_NUMBER, ctxt); validation_state_pop_validator(s); return false; } Number n; number_init(&n); if (number_set_n(&n, e->value.string.ptr, e->value.string.len)) { number_clear(&n); // TODO: Number format error validation_state_notify_error(s, VEC_NOT_NUMBER, ctxt); validation_state_pop_validator(s); return false; } bool res = _check_conditions((NumberValidator *) v, &n, s, ctxt); number_clear(&n); validation_state_pop_validator(s); return res; }
static bool check_generic(Validator *v, ValidationEvent const *e, ValidationState *s, void *ctxt) { // depth is used to track when current and all nested arrays are closed // layout checks done by YAJL int depth = GPOINTER_TO_INT(validation_state_get_context(s)); switch (e->type) { case EV_ARR_START: validation_state_set_context(s, GINT_TO_POINTER(++depth)); return true; case EV_ARR_END: validation_state_set_context(s, GINT_TO_POINTER(--depth)); if (!depth) // all arrays are closed. Last one was array validated by this object // so all validations are passed validation_state_pop_validator(s); return true; default: if (!depth) { // if there is non ARR_START event when depth is zero (a.k.a. basic array is not started yet) // than it's not array at all. // return error validation_state_notify_error(s, VEC_NOT_ARRAY, ctxt); validation_state_pop_validator(s); return false; } // if basic array is started (depth is non-zero) we don't care. All is fine return true; } }
static bool check(Validator *v, ValidationEvent const *e, ValidationState *s, void *c) { ArrayValidator *varr = (ArrayValidator *) v; MyContext *my_ctxt = (MyContext *) validation_state_get_context(s); if (!my_ctxt->has_started) { if (e->type != EV_ARR_START) { validation_state_notify_error(s, VEC_NOT_ARRAY, c); validation_state_pop_validator(s); return false; } my_ctxt->has_started = true; my_ctxt->cur_validator = varr->items ? varr->items->validators : NULL; return true; } if (e->type == EV_ARR_END) { bool res = true; if (varr->min_items != -1 && my_ctxt->items_count < varr->min_items) { validation_state_notify_error(s, VEC_ARRAY_TOO_SHORT, c); res = false; } else if (varr->unique_items && s->notify && s->notify->has_array_duplicates && s->notify->has_array_duplicates(s, c)) { validation_state_notify_error(s, VEC_ARRAY_HAS_DUPLICATES, c); res = false; } validation_state_pop_validator(s); return res; } ++my_ctxt->items_count; if (varr->max_items != -1 && my_ctxt->items_count > varr->max_items) { validation_state_notify_error(s, VEC_ARRAY_TOO_LONG, c); validation_state_pop_validator(s); return false; } Validator* vcur = _get_current_validator(varr, my_ctxt); if (vcur) { validation_state_push_validator(s, vcur); bool valid = validation_check(e, s, c); if (!valid) validation_state_pop_validator(s); return valid; } validation_state_notify_error(s, VEC_ARRAY_TOO_LONG, c); validation_state_pop_validator(s); return false; }
static bool check_integer_generic(Validator *v, ValidationEvent const *e, ValidationState *s, void *ctxt) { if (e->type != EV_NUM) { validation_state_notify_error(s, VEC_NOT_NUMBER, ctxt); validation_state_pop_validator(s); return false; } Number n; number_init(&n); bool res = check_integer_conditions(&n, e, s, ctxt); number_clear(&n); validation_state_pop_validator(s); return res; }
static bool check_generic(Validator *v, ValidationEvent const *e, ValidationState *s, void *ctxt) { validation_state_pop_validator(s); if (e->type != EV_NUM) { validation_state_notify_error(s, VEC_NOT_NUMBER, ctxt); return false; } return true; }