示例#1
0
static int js_generator_double(lua_State *L) {
    js_generator_assert(L,
                        yajl_gen_double(*js_check_generator(L, 1),
                                        luaL_checknumber(L, 2)),
                        __FILE__, __LINE__);
    return 0;
}
示例#2
0
文件: json.c 项目: chrisnorman7/stunt
static yajl_gen_status
generate(yajl_gen g, Var v, void *ctx)
{
    struct generate_context *gctx = (struct generate_context *)ctx;

    switch (v.type) {
    case TYPE_INT:
	return yajl_gen_integer(g, v.v.num);
    case TYPE_FLOAT:
	return yajl_gen_double(g, *v.v.fnum);
    case TYPE_OBJ:
    case TYPE_ERR:
	{
	    const char *tmp = value_to_literal(v);
	    if (MODE_EMBEDDED_TYPES == gctx->mode)
		tmp = append_type(tmp, v.type);
	    return yajl_gen_string(g, (const unsigned char *)tmp, strlen(tmp));
	}
    case TYPE_STR:
	{
	    const char *tmp = v.v.str;
	    size_t len = strlen(tmp);
	    if (MODE_EMBEDDED_TYPES == gctx->mode)
		if (TYPE_NONE != valid_type(&tmp, &len))
		    tmp = append_type(tmp, v.type);
	    return yajl_gen_string(g, (const unsigned char *)tmp, strlen(tmp));
	}
    case TYPE_MAP:
	{
	    struct do_map_closure dmc;
	    dmc.g = g;
	    dmc.gctx = gctx;
	    dmc.status = yajl_gen_status_ok;
	    yajl_gen_map_open(g);
	    if (mapforeach(v, do_map, &dmc))
		return dmc.status;
	    yajl_gen_map_close(g);
	    return yajl_gen_status_ok;
	}
    case TYPE_LIST:
	{
	    int i;
	    yajl_gen_status status;
	    yajl_gen_array_open(g);
	    for (i = 1; i <= v.v.list[0].v.num; i++) {
		status = generate(g, v.v.list[i], ctx);
		if (yajl_gen_status_ok != status)
		    return status;
	    }
	    yajl_gen_array_close(g);
	    return yajl_gen_status_ok;
	}
    default:
	panic("Unsupported type in generate()");
    }

    return -1;
}
示例#3
0
int orderly_write_json2(yajl_gen g, const orderly_json * j)
{
    yajl_gen_status s;
    int rv = 1;

    if (j) {
        if (j->k) yajl_gen_string(g, (const unsigned char *) j->k, strlen(j->k));

        switch (j->t) {
            case orderly_json_none:
                return 0;
            case orderly_json_null:
                s = yajl_gen_null(g);
                break;
            case orderly_json_string:
                s = yajl_gen_string(g, (const unsigned char *) j->v.s, strlen(j->v.s));
                break;
            case orderly_json_boolean:
                s = yajl_gen_bool(g, j->v.b);
                break;
            case orderly_json_integer:
                s = yajl_gen_integer(g, j->v.i);
                break;
            case orderly_json_number:
                s = yajl_gen_double(g, j->v.n);
                break;
            case orderly_json_object:
                s = yajl_gen_map_open(g);
                rv = orderly_write_json2(g, j->v.children.first);
                s = yajl_gen_map_close(g);
                break;
            case orderly_json_array:
                s = yajl_gen_array_open(g);
                rv = orderly_write_json2(g, j->v.children.first);
                s = yajl_gen_array_close(g);
                break;
        }

        if (rv && j->next) rv = orderly_write_json2(g, j->next);
    }

    return rv;
}
示例#4
0
static int json_format(struct formatter *fmt, struct recordset *rset)
{
	struct record *r;
	struct json_formatter_data *priv = fmt->priv;
	yajl_gen_map_open(priv->yajl);
        int repeat = 0;
	for_each_record(r, rset) {
		if(r->type != RECORD_TYPE_RSET || !repeat)
			yajl_gen_string(priv->yajl, (unsigned char*)r->name, r->len_n-1);
                if(r->type != RECORD_TYPE_RSET) {
                  if(repeat) yajl_gen_array_close(priv->yajl);
                repeat = 0;
                }

		switch(r->type) {
		case RECORD_TYPE_STRING:
			yajl_gen_string(priv->yajl, (unsigned char*)r->value_str, r->len_v-1);
			break;
		case RECORD_TYPE_INT:
			yajl_gen_integer(priv->yajl, r->value_int);
			break;
		case RECORD_TYPE_UINT:
		case RECORD_TYPE_HEX:
			yajl_gen_integer(priv->yajl, r->value_uint);
			break;
		case RECORD_TYPE_DOUBLE:
			yajl_gen_double(priv->yajl, r->value_double);
			break;
		case RECORD_TYPE_RSET:
                  if(!repeat) yajl_gen_array_open(priv->yajl);
			json_format(fmt, r->value_rset);

			repeat = 1;
			break;
		default:
			break;
		}
	}
        if(repeat) yajl_gen_array_close(priv->yajl);
	yajl_gen_map_close(priv->yajl);
	json_print(fmt->f, priv->yajl);
	return 0;
}
示例#5
0
文件: message.c 项目: bvanderveen/fcs
void message_bus_write_json(yajl_gen g, void *context) {
    state *state = context;

    yajl_val output_values = state_get_json(state, STATE_OUTPUT_VALUES);

    assert(YAJL_IS_ARRAY(output_values));

    yajl_gen_map_open(g);

    int len = YAJL_GET_ARRAY(output_values)->len;
    for (int i = 0; i < len; i++) {
        char *k = YAJL_GET_STRING(YAJL_GET_ARRAY(output_values)->values[i]);

        state_value_type type = state_get_value_type(state, k);

        yajl_gen_string(g, (unsigned char *)k, strlen(k));

        float float_value;
        int int_value;
        yajl_val json_value;
        switch (type) {
            case state_value_type_float:
                float_value = state_get_float(state, k);
                yajl_gen_double(g, (double)float_value);
                break;
            case state_value_type_int:
                int_value = state_get_int(state, k);
                yajl_gen_integer(g, int_value);
                break;
            case state_value_type_json:
                json_value = state_get_json(state, k);
                json_write_value(g, json_value);
                break;
            default:
                assert(0);
                break;
        }
    }

    yajl_gen_map_close(g);
}
示例#6
0
文件: IoYajlGen.c 项目: Akiyah/io
IoObject *IoYajlGen_pushDouble(IoYajlGen *self, IoObject *locals, IoMessage *m)
{
	double d = IoMessage_locals_doubleArgAt_(m, locals, 0);
	yajl_gen_double(DATA(self), d);
	return self;
}
示例#7
0
static int gen_jansson_value(yajl_gen gen, json_t *value) {
	json_error_t jerr;
	const char *str;
	size_t len;
	int rc;

	int type = json_typeof(value);
	switch(type) {
	case JSON_OBJECT:
		yajl_gen_map_open(gen);
		gen_jansson_object(gen,value);
		yajl_gen_map_close(gen);
		break;

	case JSON_ARRAY:
		yajl_gen_array_open(gen);
		gen_jansson_array(gen,value);
		yajl_gen_array_close(gen);
		break;

	case JSON_STRING:
		rc = json_unpack_ex(value, &jerr, 0, "s%", &str,&len);
		if(rc != 0) {
			rdlog(LOG_ERR,"Couldn't extract string: %s",jerr.text);
			return 0;
		}
		yajl_gen_string(gen, (const unsigned char *)str, len);
		break;

	case JSON_INTEGER:
		{
			json_int_t i = json_integer_value(value);
			yajl_gen_integer(gen,i);
		}
		break;

	case JSON_REAL:
		{
			double d = json_number_value(value);
			yajl_gen_double(gen,d);
		}
		break;

	case JSON_TRUE:
		yajl_gen_bool(gen,1);
		break;

	case JSON_FALSE:
		yajl_gen_bool(gen,0);
		break;

	case JSON_NULL:
		yajl_gen_null(gen);
		break;

	default:
		rdlog(LOG_ERR,"Unkown jansson type %d",type);
		break;
	};

	return 1;
}
示例#8
0
int
enc_json(Encoder* enc, ERL_NIF_TERM term)
{
    int ival;
    unsigned int uival;
    long lval;
    unsigned long ulval;
    double dval;
    ERL_NIF_TERM head;
    ERL_NIF_TERM tail;
    int arity;
    const ERL_NIF_TERM* tuple;
    
    if(enif_is_atom(enc->env, term))
    {
        return enc_atom(enc, term);
    }
    
    if(enif_is_binary(enc->env, term))
    {
        return enc_binary(enc, term);
    }
    
    if(enif_get_int(enc->env, term, &ival))
    {
        if(yajl_gen_integer(enc->handle, ival) != yajl_gen_status_ok)
        {
            enc->error = enif_make_atom(enc->env, "bad_integer");
            return ERROR;
        }
        return OK;
    }
    
    if(enif_get_uint(enc->env, term, &uival))
    {
        if(yajl_gen_integer(enc->handle, uival) != yajl_gen_status_ok)
        {
            enc->error = enif_make_atom(enc->env, "bad_unsigned_integer");
            return ERROR;
        }
        return OK;
    }
    
    if(enif_get_long(enc->env, term, &lval))
    {
        if(yajl_gen_integer(enc->handle, lval) != yajl_gen_status_ok)
        {
            enc->error = enif_make_atom(enc->env, "bad_long");
            return ERROR;
        }
        return OK;
    }
    
    if(enif_get_ulong(enc->env, term, &ulval))
    {
        if(yajl_gen_integer(enc->handle, ulval) != yajl_gen_status_ok)
        {
            enc->error = enif_make_atom(enc->env, "bad_unsigned_long");
            return ERROR;
        }
        return OK;
    }

    if(enif_get_double(enc->env, term, &dval))
    {
        if(yajl_gen_double(enc->handle, dval) != yajl_gen_status_ok)
        {
            enc->error = enif_make_atom(enc->env, "bad_double");
            return ERROR;
        }
        return OK;
    }

    if(enif_is_empty_list(enc->env, term))
    {
        if(yajl_gen_array_open(enc->handle) != yajl_gen_status_ok)
        {
            enc->error = enif_make_atom(enc->env, "failed_to_open_empty_list");
            return ERROR;
        }
        if(yajl_gen_array_close(enc->handle) != yajl_gen_status_ok)
        {
            enc->error = enif_make_atom(enc->env, "failed_to_close_empty_list");
            return ERROR;
        }
        return OK;
    }

    if(enif_get_list_cell(enc->env, term, &head, &tail))
    {
        return enc_array(enc, head, tail);
    }
    
    if(enif_get_tuple(enc->env, term, &arity, &tuple))
    {
        if(arity == 1)
        {
            if(enif_is_empty_list(enc->env, tuple[0]))
            {
                if(yajl_gen_map_open(enc->handle) != yajl_gen_status_ok)
                {
                    enc->error = enif_make_atom(enc->env,
                                                "failed_to_open_empty_map");
                    return ERROR;
                }
                if(yajl_gen_map_close(enc->handle) != yajl_gen_status_ok)
                {
                    enc->error = enif_make_atom(enc->env,
                                                "failed_to_close_empty_map");
                    return ERROR;
                }
                return OK;
            }
            else if(enif_get_list_cell(enc->env, tuple[0], &head, &tail))
            {
                return enc_map(enc, head, tail);
            }
        }
    }

    enc->error = enif_make_tuple(enc->env, 2,
        enif_make_atom(enc->env, "badarg"),
        term
    );
    return ERROR;
}
示例#9
0
static bool element(mpack_reader_t* reader, yajl_gen gen, options_t* options, int depth) {
    const mpack_tag_t tag = mpack_read_tag(reader);
    if (mpack_reader_error(reader) != mpack_ok)
        return false;

    if (!options->debug && depth == 0 && (tag.type != mpack_type_map && tag.type != mpack_type_array)) {
        fprintf(stderr, "%s: Top-level object must be a map or array. Try debug viewing mode (-d)\n", options->command);
        return false;
    }

    // TODO check not depth zero
    switch (tag.type) {
        case mpack_type_bool:   return yajl_gen_bool(gen, tag.v.b) == yajl_gen_status_ok;
        case mpack_type_nil:    return yajl_gen_null(gen) == yajl_gen_status_ok;
        case mpack_type_int:    return yajl_gen_integer(gen, tag.v.i) == yajl_gen_status_ok;
        case mpack_type_float:  return yajl_gen_double(gen, tag.v.f) == yajl_gen_status_ok;
        case mpack_type_double: return yajl_gen_double(gen, tag.v.d) == yajl_gen_status_ok;

        case mpack_type_uint:
            if (tag.v.u > (uint64_t)INT64_MAX) {
                char buf[32];
                snprintf(buf, sizeof(buf), "%" PRIu64, tag.v.u);
                return yajl_gen_string(gen, (const unsigned char*)buf, strlen(buf)) == yajl_gen_status_ok;
            }
            return yajl_gen_integer(gen, (int64_t)tag.v.u) == yajl_gen_status_ok;

        case mpack_type_str:
            return string(reader, gen, options, tag.v.l);

        case mpack_type_bin:
            if (options->base64) {
                return base64_bin(reader, gen, options, tag.v.l, options->base64_prefix);
            } else if (options->debug) {
                mpack_skip_bytes(reader, tag.v.l);
                mpack_done_bin(reader);

                // output nothing to allow us to print our debug string
                skip_quotes = true;
                if (yajl_gen_string(gen, (const unsigned char*)"", 0) != yajl_gen_status_ok)
                    return false;
                skip_quotes = false;

                char buf[64];
                snprintf(buf, sizeof(buf), "<bin of size %u>", tag.v.l);
                print(out_file, buf, strlen(buf));
                return true;
            } else {
                fprintf(stderr, "%s: bin unencodable in JSON. Try debug viewing mode (-d)\n", options->command);
                return false;
            }

        case mpack_type_ext:
            if (options->base64) {
                return base64_ext(reader, gen, options, tag.exttype, tag.v.l);
            } else if (options->debug) {
                mpack_skip_bytes(reader, tag.v.l);
                mpack_done_ext(reader);

                // output nothing to allow us to print our debug string
                skip_quotes = true;
                if (yajl_gen_string(gen, (const unsigned char*)"", 0) != yajl_gen_status_ok)
                    return false;
                skip_quotes = false;

                char buf[64];
                snprintf(buf, sizeof(buf), "<ext of type %i size %u>", tag.exttype, tag.v.l);
                print(out_file, buf, strlen(buf));
                return true;
            } else {
                fprintf(stderr, "%s: ext type %i unencodable in JSON. Try debug viewing mode (-d)\n", options->command, tag.exttype);
                return false;
            }

        case mpack_type_array:
            if (yajl_gen_array_open(gen) != yajl_gen_status_ok)
                return false;
            for (size_t i = 0; i < tag.v.l; ++i)
                if (!element(reader, gen, options, depth + 1))
                    return false;
            mpack_done_array(reader);
            return yajl_gen_array_close(gen) == yajl_gen_status_ok;

        case mpack_type_map:
            if (yajl_gen_map_open(gen) != yajl_gen_status_ok)
                return false;
            for (size_t i = 0; i < tag.v.l; ++i) {

                if (options->debug) {
                    element(reader, gen, options, depth + 1);
                } else {
                    uint32_t len = mpack_expect_str(reader);
                    if (mpack_reader_error(reader) != mpack_ok) {
                        fprintf(stderr, "%s: map key is not a string. Try debug viewing mode (-d)\n", options->command);
                        return false;
                    }
                    if (!string(reader, gen, options, len))
                        return false;
                }

                if (!element(reader, gen, options, depth + 1))
                    return false;
            }
            mpack_done_map(reader);
            return yajl_gen_map_close(gen) == yajl_gen_status_ok;
    }

    return true;
}
示例#10
0
static yajl_gen_status ProcessObject(_YajlEncoder *self, PyObject *object)
{
    yajl_gen handle = (yajl_gen)(self->_generator);
    yajl_gen_status status = yajl_gen_in_error_state;
    PyObject *iterator, *item;
    unsigned short int decref = 0;

    if (object == Py_None) {
        return yajl_gen_null(handle);
    }
    if (object == Py_True) {
        return yajl_gen_bool(handle, 1);
    }
    if (object == Py_False) {
        return yajl_gen_bool(handle, 0);
    }
    if (PyUnicode_Check(object)) {
        object = PyUnicode_AsUTF8String(object);
        decref = 1;
    }
    if (PyString_Check(object)) {
        const unsigned char *buffer = NULL;
        Py_ssize_t length;
        PyString_AsStringAndSize(object, (char **)&buffer, &length);
        status = yajl_gen_string(handle, buffer, (unsigned int)(length));
        if (decref) {
            Py_XDECREF(object);
        }
        return status;
    }
    if (PyInt_Check(object)) {
        return yajl_gen_integer(handle, PyInt_AsLong(object));
    }
    if (PyLong_Check(object)) {
        return yajl_gen_integer(handle, PyLong_AsLong(object));
    }
    if (PyFloat_Check(object)) {
        return yajl_gen_double(handle, PyFloat_AsDouble(object));
    }
    if (PyList_Check(object)) {
        /*
         * Recurse and handle the list 
         */
        iterator = PyObject_GetIter(object);
        if (iterator == NULL)
            goto exit;
        status = yajl_gen_array_open(handle);
        while ((item = PyIter_Next(iterator))) {
            status = ProcessObject(self, item);
            Py_XDECREF(item);
        }
        Py_XDECREF(iterator);
        status = yajl_gen_array_close(handle);
        return status;
    }
    if (PyDict_Check(object)) {
        PyObject *key, *value;
        Py_ssize_t position = 0;

        status = yajl_gen_map_open(handle);
        while (PyDict_Next(object, &position, &key, &value)) {
            status = ProcessObject(self, key);
            status = ProcessObject(self, value);
        }
        return yajl_gen_map_close(handle);
    }

        
    exit:
        return yajl_gen_in_error_state;
}
示例#11
0
void
obj_dump(VALUE obj, yajl_gen gen)
{
  int type;
  yajl_gen_map_open(gen);

  yajl_gen_cstr(gen, "_id");
  yajl_gen_value(gen, obj);

  struct obj_track *tracker = NULL;
  if (st_lookup(objs, (st_data_t)obj, (st_data_t *)&tracker) && BUILTIN_TYPE(obj) != T_NODE) {
    yajl_gen_cstr(gen, "file");
    yajl_gen_cstr(gen, tracker->source);
    yajl_gen_cstr(gen, "line");
    yajl_gen_integer(gen, tracker->line);
  }

  yajl_gen_cstr(gen, "type");
  switch (type=BUILTIN_TYPE(obj)) {
    case T_DATA:
      yajl_gen_cstr(gen, "data");

      if (RBASIC(obj)->klass) {
        yajl_gen_cstr(gen, "class");
        yajl_gen_value(gen, RBASIC(obj)->klass);

        yajl_gen_cstr(gen, "class_name");
        VALUE name = rb_classname(RBASIC(obj)->klass);
        if (RTEST(name))
          yajl_gen_cstr(gen, RSTRING(name)->ptr);
        else
          yajl_gen_cstr(gen, 0);
      }
      break;

    case T_FILE:
      yajl_gen_cstr(gen, "file");
      break;

    case T_FLOAT:
      yajl_gen_cstr(gen, "float");

      yajl_gen_cstr(gen, "data");
      yajl_gen_double(gen, RFLOAT(obj)->value);
      break;

    case T_BIGNUM:
      yajl_gen_cstr(gen, "bignum");

      yajl_gen_cstr(gen, "negative");
      yajl_gen_bool(gen, RBIGNUM(obj)->sign == 0);

      yajl_gen_cstr(gen, "length");
      yajl_gen_integer(gen, RBIGNUM(obj)->len);

      yajl_gen_cstr(gen, "data");
      yajl_gen_string(gen, RBIGNUM(obj)->digits, RBIGNUM(obj)->len);
      break;

    case T_MATCH:
      yajl_gen_cstr(gen, "match");

      yajl_gen_cstr(gen, "data");
      yajl_gen_value(gen, RMATCH(obj)->str);
      break;

    case T_REGEXP:
      yajl_gen_cstr(gen, "regexp");

      yajl_gen_cstr(gen, "length");
      yajl_gen_integer(gen, RREGEXP(obj)->len);

      yajl_gen_cstr(gen, "data");
      yajl_gen_cstr(gen, RREGEXP(obj)->str);
      break;

    case T_SCOPE:
      yajl_gen_cstr(gen, "scope");

      struct SCOPE *scope = (struct SCOPE *)obj;
      if (scope->local_tbl) {
        int i = 1;
        int n = scope->local_tbl[0];
        VALUE *list = &scope->local_vars[-1];
        VALUE cur = *list++;

        yajl_gen_cstr(gen, "node");
        yajl_gen_value(gen, cur);

        if (n) {
          yajl_gen_cstr(gen, "variables");
          yajl_gen_map_open(gen);
          while (n--) {
            cur = *list++;
            yajl_gen_cstr(gen, scope->local_tbl[i] == 95 ? "_" : rb_id2name(scope->local_tbl[i]));
            yajl_gen_value(gen, cur);
            i++;
          }
          yajl_gen_map_close(gen);
        }
      }
      break;

    case T_NODE:
      yajl_gen_cstr(gen, "node");

      yajl_gen_cstr(gen, "node_type");
      yajl_gen_cstr(gen, nd_type_str(obj));

      yajl_gen_cstr(gen, "file");
      yajl_gen_cstr(gen, RNODE(obj)->nd_file);

      yajl_gen_cstr(gen, "line");
      yajl_gen_integer(gen, nd_line(obj));

      yajl_gen_cstr(gen, "node_code");
      yajl_gen_integer(gen, nd_type(obj));

      switch (nd_type(obj)) {
        case NODE_SCOPE:
          break;
      }
      break;

    case T_STRING:
      yajl_gen_cstr(gen, "string");

      yajl_gen_cstr(gen, "length");
      yajl_gen_integer(gen, RSTRING(obj)->len);

      if (FL_TEST(obj, ELTS_SHARED|FL_USER3)) {
        yajl_gen_cstr(gen, "shared");
        yajl_gen_value(gen, RSTRING(obj)->aux.shared);

        yajl_gen_cstr(gen, "flags");
        yajl_gen_array_open(gen);
        if (FL_TEST(obj, ELTS_SHARED))
          yajl_gen_cstr(gen, "elts_shared");
        if (FL_TEST(obj, FL_USER3))
          yajl_gen_cstr(gen, "str_assoc");
        yajl_gen_array_close(gen);
      } else {
        yajl_gen_cstr(gen, "data");
        yajl_gen_string(gen, (unsigned char *)RSTRING(obj)->ptr, RSTRING(obj)->len);
      }
      break;

    case T_VARMAP:
      yajl_gen_cstr(gen, "varmap");

      struct RVarmap *vars = (struct RVarmap *)obj;

      if (vars->next) {
        yajl_gen_cstr(gen, "next");
        yajl_gen_value(gen, (VALUE)vars->next);
      }

      if (vars->id) {
        yajl_gen_cstr(gen, "data");
        yajl_gen_map_open(gen);
        yajl_gen_cstr(gen, rb_id2name(vars->id));
        yajl_gen_value(gen, vars->val);
        yajl_gen_map_close(gen);
      }
      break;

    case T_CLASS:
    case T_MODULE:
    case T_ICLASS:
      yajl_gen_cstr(gen, type==T_CLASS ? "class" : type==T_MODULE ? "module" : "iclass");

      yajl_gen_cstr(gen, "name");
      VALUE name = rb_classname(obj);
      if (RTEST(name))
        yajl_gen_cstr(gen, RSTRING(name)->ptr);
      else
        yajl_gen_cstr(gen, 0);

      yajl_gen_cstr(gen, "super");
      yajl_gen_value(gen, RCLASS(obj)->super);

      yajl_gen_cstr(gen, "super_name");
      VALUE super_name = rb_classname(RCLASS(obj)->super);
      if (RTEST(super_name))
        yajl_gen_cstr(gen, RSTRING(super_name)->ptr);
      else
        yajl_gen_cstr(gen, 0);

      if (FL_TEST(obj, FL_SINGLETON)) {
        yajl_gen_cstr(gen, "singleton");
        yajl_gen_bool(gen, 1);
      }

      if (RCLASS(obj)->iv_tbl && RCLASS(obj)->iv_tbl->num_entries) {
        yajl_gen_cstr(gen, "ivars");
        yajl_gen_map_open(gen);
        st_foreach(RCLASS(obj)->iv_tbl, each_ivar, (st_data_t)gen);
        yajl_gen_map_close(gen);
      }

      if (type != T_ICLASS && RCLASS(obj)->m_tbl && RCLASS(obj)->m_tbl->num_entries) {
        yajl_gen_cstr(gen, "methods");
        yajl_gen_map_open(gen);
        st_foreach(RCLASS(obj)->m_tbl, each_ivar, (st_data_t)gen);
        yajl_gen_map_close(gen);
      }
      break;

    case T_OBJECT:
      yajl_gen_cstr(gen, "object");

      yajl_gen_cstr(gen, "class");
      yajl_gen_value(gen, RBASIC(obj)->klass);

      yajl_gen_cstr(gen, "class_name");
      yajl_gen_cstr(gen, rb_obj_classname(obj));

      struct RClass *klass = RCLASS(obj);

      if (klass->iv_tbl && klass->iv_tbl->num_entries) {
        yajl_gen_cstr(gen, "ivars");
        yajl_gen_map_open(gen);
        st_foreach(klass->iv_tbl, each_ivar, (st_data_t)gen);
        yajl_gen_map_close(gen);
      }
      break;

    case T_ARRAY:
      yajl_gen_cstr(gen, "array");

      struct RArray *ary = RARRAY(obj);

      yajl_gen_cstr(gen, "length");
      yajl_gen_integer(gen, ary->len);

      if (FL_TEST(obj, ELTS_SHARED)) {
        yajl_gen_cstr(gen, "shared");
        yajl_gen_value(gen, ary->aux.shared);
      } else if (ary->len) {
        yajl_gen_cstr(gen, "data");
        yajl_gen_array_open(gen);
        int i;
        for(i=0; i < ary->len; i++)
          yajl_gen_value(gen, ary->ptr[i]);
        yajl_gen_array_close(gen);
      }
      break;

    case T_HASH:
      yajl_gen_cstr(gen, "hash");

      struct RHash *hash = RHASH(obj);

      yajl_gen_cstr(gen, "length");
      if (hash->tbl)
        yajl_gen_integer(gen, hash->tbl->num_entries);
      else
        yajl_gen_integer(gen, 0);

      yajl_gen_cstr(gen, "default");
      yajl_gen_value(gen, hash->ifnone);

      if (hash->tbl && hash->tbl->num_entries) {
        yajl_gen_cstr(gen, "data");
        //yajl_gen_map_open(gen);
        yajl_gen_array_open(gen);
        st_foreach(hash->tbl, each_hash_entry, (st_data_t)gen);
        yajl_gen_array_close(gen);
        //yajl_gen_map_close(gen);
      }
      break;

    default:
      yajl_gen_cstr(gen, "unknown");
  }

  yajl_gen_cstr(gen, "code");
  yajl_gen_integer(gen, BUILTIN_TYPE(obj));

  yajl_gen_map_close(gen);
}