Пример #1
0
static void f_keys(jv input[], jv output[]) {
  if (jv_get_kind(input[0]) == JV_KIND_OBJECT) {
    int nkeys = jv_object_length(jv_copy(input[0]));
    jv* keys = malloc(sizeof(jv) * nkeys);
    int kidx = 0;
    jv_object_foreach(i, input[0]) {
      keys[kidx++] = jv_object_iter_key(input[0], i);
    }
Пример #2
0
jv jv_keys(jv x) {
  if (jv_get_kind(x) == JV_KIND_OBJECT) {
    int nkeys = jv_object_length(jv_copy(x));
    jv* keys = malloc(sizeof(jv) * nkeys);
    int kidx = 0;
    jv_object_foreach(i, x) {
      keys[kidx++] = jv_object_iter_key(x, i);
    }
Пример #3
0
static void f_length(jv input[], jv output[]) {
  if (jv_get_kind(input[0]) == JV_KIND_ARRAY) {
    output[0] = jv_number(jv_array_length(input[0]));
  } else if (jv_get_kind(input[0]) == JV_KIND_OBJECT) {
    output[0] = jv_number(jv_object_length(input[0]));
  } else if (jv_get_kind(input[0]) == JV_KIND_STRING) {
    output[0] = jv_number(jv_string_length(input[0]));
  } else {
    output[0] = jv_invalid_with_msg(jv_string_fmt("Cannot get the length of %s",
                                                  jv_kind_name(jv_get_kind(input[0]))));
    jv_free(input[0]);
  }
}
Пример #4
0
static pfunc token(struct jv_parser* p, char ch) {
  switch (ch) {
  case '[':
    if (jv_is_valid(p->next)) return "Expected separator between values";
    push(p, jv_array());
    break;

  case '{':
    if (jv_is_valid(p->next)) return "Expected separator between values";
    push(p, jv_object());
    break;

  case ':':
    if (!jv_is_valid(p->next)) 
      return "Expected string key before ':'";
    if (p->stackpos == 0 || jv_get_kind(p->stack[p->stackpos-1]) != JV_KIND_OBJECT)
      return "':' not as part of an object";
    if (jv_get_kind(p->next) != JV_KIND_STRING)
      return "Object keys must be strings";
    push(p, p->next);
    p->next = jv_invalid();
    break;

  case ',':
    if (!jv_is_valid(p->next))
      return "Expected value before ','";
    if (p->stackpos == 0)
      return "',' not as part of an object or array";
    if (jv_get_kind(p->stack[p->stackpos-1]) == JV_KIND_ARRAY) {
      p->stack[p->stackpos-1] = jv_array_append(p->stack[p->stackpos-1], p->next);
      p->next = jv_invalid();
    } else if (jv_get_kind(p->stack[p->stackpos-1]) == JV_KIND_STRING) {
      assert(p->stackpos > 1 && jv_get_kind(p->stack[p->stackpos-2]) == JV_KIND_OBJECT);
      p->stack[p->stackpos-2] = jv_object_set(p->stack[p->stackpos-2], 
                                              p->stack[p->stackpos-1], p->next);
      p->stackpos--;
      p->next = jv_invalid();
    } else {
      // this case hits on input like {"a", "b"}
      return "Objects must consist of key:value pairs";
    }
    break;

  case ']':
    if (p->stackpos == 0 || jv_get_kind(p->stack[p->stackpos-1]) != JV_KIND_ARRAY)
      return "Unmatched ']'";
    if (jv_is_valid(p->next)) {
      p->stack[p->stackpos-1] = jv_array_append(p->stack[p->stackpos-1], p->next);
      p->next = jv_invalid();
    } else {
      if (jv_array_length(jv_copy(p->stack[p->stackpos-1])) != 0) {
        // this case hits on input like [1,2,3,]
        return "Expected another array element";
      }
    }
    jv_free(p->next);
    p->next = p->stack[--p->stackpos];
    break;

  case '}':
    if (p->stackpos == 0)
      return "Unmatched '}'";
    if (jv_is_valid(p->next)) {
      if (jv_get_kind(p->stack[p->stackpos-1]) != JV_KIND_STRING)
        return "Objects must consist of key:value pairs";
      assert(p->stackpos > 1 && jv_get_kind(p->stack[p->stackpos-2]) == JV_KIND_OBJECT);
      p->stack[p->stackpos-2] = jv_object_set(p->stack[p->stackpos-2], 
                                              p->stack[p->stackpos-1], p->next);
      p->stackpos--;
      p->next = jv_invalid();
    } else {
      if (jv_get_kind(p->stack[p->stackpos-1]) != JV_KIND_OBJECT)
        return "Unmatched '}'";
      if (jv_object_length(jv_copy(p->stack[p->stackpos-1])) != 0)
        return "Expected another key-value pair";
    }
    jv_free(p->next);
    p->next = p->stack[--p->stackpos];
    break;
  }
  return 0;
}
Пример #5
0
static void
php_jv_dump(zval **return_value, jv x TSRMLS_DC)
{
    switch (jv_get_kind(x)) {
        default:
        case JV_KIND_INVALID:
            if (PHP_JQ_G(display_errors)) {
                PHP_JQ_ERR(E_WARNING, "json parse error");
            }
            break;
        case JV_KIND_NULL:
            INIT_PZVAL(*return_value);
            ZVAL_NULL(*return_value);
            break;
        case JV_KIND_FALSE:
            INIT_PZVAL(*return_value);
            ZVAL_BOOL(*return_value, 0);
            break;
        case JV_KIND_TRUE:
            INIT_PZVAL(*return_value);
            ZVAL_BOOL(*return_value, 1);
            break;
        case JV_KIND_NUMBER: {
            double d = jv_number_value(x);
            INIT_PZVAL(*return_value);
            if (d != d || d > LONG_MAX || d < LONG_MIN) {
                ZVAL_DOUBLE(*return_value, jv_number_value(x));
            } else if (d == (long)d) {
                ZVAL_LONG(*return_value, (long)d);
            } else {
                ZVAL_DOUBLE(*return_value, jv_number_value(x));
            }
            break;
        }
        case JV_KIND_STRING: {
            int len = jv_string_length_bytes(jv_copy(x));
            INIT_PZVAL(*return_value);
            if (len <= 0) {
                ZVAL_EMPTY_STRING(*return_value);
            } else {
                ZVAL_STRINGL(*return_value, jv_string_value(x), len, 1);
            }
            break;
        }
        case JV_KIND_ARRAY: {
            int i, len = jv_array_length(jv_copy(x));
            INIT_PZVAL(*return_value);
            array_init(*return_value);
            if (len == 0) {
                break;
            }

            for (i = 0; i < len; i++) {
                jv value = jv_array_get(jv_copy(x), i);
                if (jv_is_valid(value)) {
                    zval *zv;
                    ALLOC_INIT_ZVAL(zv);
                    php_jv_dump(&zv, value TSRMLS_CC);
                    zend_hash_next_index_insert(Z_ARRVAL_PP(return_value),
                                                &zv, sizeof(zv), NULL);
                } else {
                    jv_free(value);
                }
            }
            break;
        }
        case JV_KIND_OBJECT: {
            int i = 0, first = 1;
            INIT_PZVAL(*return_value);
            array_init(*return_value);
            if (jv_object_length(jv_copy(x)) == 0) {
                break;
            }

            while (1) {
                jv key, value;
                zval *zv;

                if (first) {
                    i = jv_object_iter(x);
                } else {
                    i = jv_object_iter_next(x, i);
                }
                if (!jv_object_iter_valid(x, i)) {
                    break;
                }

                key = jv_object_iter_key(x, i);
                value = jv_object_iter_value(x, i);

                ALLOC_INIT_ZVAL(zv);
                php_jv_dump(&zv, value TSRMLS_CC);
                zend_symtable_update(Z_ARRVAL_PP(return_value),
                                     jv_string_value(key),
                                     jv_string_length_bytes(jv_copy(key)) + 1,
                                     &zv, sizeof(zv), NULL);

                first = 0;
                jv_free(key);
            }
        }
    }

    jv_free(x);
}