ext/yajl_ext.c in yajl-ruby-0.6.3 vs ext/yajl_ext.c in yajl-ruby-0.6.4

- old
+ new

@@ -1,13 +1,13 @@ #include "yajl_ext.h" -// Helpers for building objects +/* Helpers for building objects */ inline void yajl_check_and_fire_callback(void * ctx) { struct yajl_parser_wrapper * wrapper; GetParser((VALUE)ctx, wrapper); - // No need to do any of this if the callback isn't even setup + /* No need to do any of this if the callback isn't even setup */ if (wrapper->parse_complete_callback != Qnil) { int len = RARRAY_LEN(wrapper->builderStack); if (len == 1 && wrapper->nestedArrayLevel == 0 && wrapper->nestedHashLevel == 0) { rb_funcall(wrapper->parse_complete_callback, intern_call, 1, rb_ary_pop(wrapper->builderStack)); } @@ -96,19 +96,19 @@ switch (TYPE(obj)) { case T_HASH: status = yajl_gen_map_open(w->encoder); - // TODO: itterate through keys in the hash + /* TODO: itterate through keys in the hash */ VALUE keys = rb_funcall(obj, intern_keys, 0); VALUE entry, keyStr; for(idx=0; idx<RARRAY_LEN(keys); idx++) { entry = rb_ary_entry(keys, idx); - keyStr = rb_funcall(entry, intern_to_s, 0); // key must be a string - // the key + keyStr = rb_funcall(entry, intern_to_s, 0); /* key must be a string */ + /* the key */ yajl_encode_part(w, keyStr, io); - // the value + /* the value */ yajl_encode_part(w, rb_hash_aref(obj, entry), io); } status = yajl_gen_map_close(w->encoder); break; @@ -131,19 +131,22 @@ break; case T_FIXNUM: case T_FLOAT: case T_BIGNUM: str = rb_funcall(obj, intern_to_s, 0); + if (strcmp(RSTRING_PTR(str), "NaN") == 0 || strcmp(RSTRING_PTR(str), "Infinity") == 0 || strcmp(RSTRING_PTR(str), "-Infinity") == 0) { + rb_raise(cEncodeError, "'%s' is an invalid number", RSTRING_PTR(str)); + } status = yajl_gen_number(w->encoder, RSTRING_PTR(str), (unsigned int)RSTRING_LEN(str)); break; case T_STRING: status = yajl_gen_string(w->encoder, (const unsigned char *)RSTRING_PTR(obj), (unsigned int)RSTRING_LEN(obj), 1); break; default: if (rb_respond_to(obj, intern_to_json)) { str = rb_funcall(obj, intern_to_json, 0); - quote_strings = 0; // this lets us append on to the buffer without Yajl quoting it again + quote_strings = 0; /* this lets us append on to the buffer without Yajl quoting it again */ } else { str = rb_funcall(obj, intern_to_s, 0); } status = yajl_gen_string(w->encoder, (const unsigned char *)RSTRING_PTR(str), (unsigned int)RSTRING_LEN(str), quote_strings); break; @@ -172,11 +175,11 @@ rb_raise(cParseError, "%s", (const char *) str); yajl_free_error(parser, str); } } -// YAJL Callbacks +/* YAJL Callbacks */ static int yajl_found_null(void * ctx) { yajl_set_static_value(ctx, Qnil); yajl_check_and_fire_callback(ctx); return 1; } @@ -186,19 +189,23 @@ yajl_check_and_fire_callback(ctx); return 1; } static int yajl_found_number(void * ctx, const char * numberVal, unsigned int numberLen) { - VALUE subString = rb_str_new(numberVal, numberLen); - char * cSubString = RSTRING_PTR(subString); + char * cSubString = ALLOC_N(char, numberLen+1); + if (cSubString) { + memcpy(cSubString, numberVal, numberLen); + } + cSubString[numberLen] = '\0'; - if (strstr(cSubString, ".") != NULL || strstr(cSubString, "e") != NULL || strstr(cSubString, "E") != NULL) { - yajl_set_static_value(ctx, rb_Float(subString)); + if (strchr(cSubString, '.') != NULL || strchr(cSubString, 'e') != NULL || strchr(cSubString, 'E') != NULL) { + yajl_set_static_value(ctx, rb_float_new(atof(cSubString))); } else { - yajl_set_static_value(ctx, rb_Integer(subString)); + yajl_set_static_value(ctx, INT2FIX(atoi(cSubString))); } yajl_check_and_fire_callback(ctx); + free(cSubString); return 1; } static int yajl_found_string(void * ctx, const unsigned char * stringVal, unsigned int stringLen) { yajl_set_static_value(ctx, rb_str_new((const char *)stringVal, stringLen)); @@ -208,14 +215,13 @@ static int yajl_found_hash_key(void * ctx, const unsigned char * stringVal, unsigned int stringLen) { struct yajl_parser_wrapper * wrapper; GetParser((VALUE)ctx, wrapper); VALUE keyStr = rb_str_new((const char *)stringVal, stringLen); - + if (wrapper->symbolizeKeys) { - ID key = rb_intern(RSTRING_PTR(keyStr)); - yajl_set_static_value(ctx, ID2SYM(key)); + yajl_set_static_value(ctx, rb_funcall(keyStr, intern_to_sym, 0)); } else { yajl_set_static_value(ctx, keyStr); } yajl_check_and_fire_callback(ctx); return 1; @@ -258,11 +264,11 @@ yajl_check_and_fire_callback(ctx); return 1; } -// Ruby Interface +/* Ruby Interface */ /* * Document-class: Yajl::Parser * * This class contains methods for parsing JSON directly from an IO object. @@ -285,21 +291,21 @@ struct yajl_parser_wrapper * wrapper; yajl_parser_config cfg; VALUE opts, obj; int allowComments = 1, checkUTF8 = 1, symbolizeKeys = 0; - // Scan off config vars + /* Scan off config vars */ if (rb_scan_args(argc, argv, "01", &opts) == 1) { Check_Type(opts, T_HASH); - if (rb_hash_aref(opts, ID2SYM(sym_allow_comments)) == Qfalse) { + if (rb_hash_aref(opts, sym_allow_comments) == Qfalse) { allowComments = 0; } - if (rb_hash_aref(opts, ID2SYM(sym_check_utf8)) == Qfalse) { + if (rb_hash_aref(opts, sym_check_utf8) == Qfalse) { checkUTF8 = 0; } - if (rb_hash_aref(opts, ID2SYM(sym_symbolize_keys)) == Qtrue) { + if (rb_hash_aref(opts, sym_symbolize_keys) == Qtrue) { symbolizeKeys = 1; } } cfg = (yajl_parser_config){allowComments, checkUTF8}; @@ -352,16 +358,15 @@ * block is for this method. */ static VALUE rb_yajl_parser_parse(int argc, VALUE * argv, VALUE self) { yajl_status stat; struct yajl_parser_wrapper * wrapper; - VALUE parsed, rbufsize, input, blk; + VALUE rbufsize, input, blk; GetParser(self, wrapper); - parsed = rb_str_new2(""); - // setup our parameters + /* setup our parameters */ rb_scan_args(argc, argv, "11&", &input, &rbufsize, &blk); if (NIL_P(rbufsize)) { rbufsize = INT2FIX(READ_BUFSIZE); } else { Check_Type(rbufsize, T_FIXNUM); @@ -371,19 +376,20 @@ } if (TYPE(input) == T_STRING) { yajl_parse_chunk((const unsigned char *)RSTRING_PTR(input), RSTRING_LEN(input), wrapper->parser); } else if (rb_respond_to(input, intern_eof)) { + VALUE parsed = rb_str_new2(""); while (rb_funcall(input, intern_eof, 0) != Qtrue) { rb_funcall(input, intern_io_read, 2, rbufsize, parsed); yajl_parse_chunk((const unsigned char *)RSTRING_PTR(parsed), RSTRING_LEN(parsed), wrapper->parser); } } else { rb_raise(cParseError, "input must be a string or IO"); } - // parse any remaining buffered data + /* parse any remaining buffered data */ stat = yajl_parse_complete(wrapper->parser); if (wrapper->parse_complete_callback != Qnil) { yajl_check_and_fire_callback((void *)self); return Qnil; @@ -465,17 +471,17 @@ yajl_gen_config cfg; VALUE opts, obj, indent; const char * indentString = " "; int beautify = 0; - // Scan off config vars + /* Scan off config vars */ if (rb_scan_args(argc, argv, "01", &opts) == 1) { Check_Type(opts, T_HASH); - if (rb_hash_aref(opts, ID2SYM(sym_pretty)) == Qtrue) { + if (rb_hash_aref(opts, sym_pretty) == Qtrue) { beautify = 1; - indent = rb_hash_aref(opts, ID2SYM(sym_indent)); + indent = rb_hash_aref(opts, sym_indent); if (indent != Qnil) { Check_Type(indent, T_STRING); indentString = RSTRING_PTR(indent); } } @@ -483,12 +489,12 @@ cfg = (yajl_gen_config){beautify, indentString}; obj = Data_Make_Struct(klass, struct yajl_encoder_wrapper, yajl_encoder_wrapper_mark, yajl_encoder_wrapper_free, wrapper); wrapper->encoder = yajl_gen_alloc(&cfg, NULL); wrapper->on_progress_callback = Qnil; - if (opts != Qnil && rb_funcall(opts, intern_has_key, 1, ID2SYM(sym_terminator)) == Qtrue) { - wrapper->terminator = rb_hash_aref(opts, ID2SYM(sym_terminator)); + if (opts != Qnil && rb_funcall(opts, intern_has_key, 1, sym_terminator) == Qtrue) { + wrapper->terminator = rb_hash_aref(opts, sym_terminator); } else { wrapper->terminator = 0; } rb_obj_call_init(obj, 0, 0); return obj; @@ -541,14 +547,14 @@ if (blk != Qnil) { wrapper->on_progress_callback = blk; } - // begin encode process + /* begin encode process */ yajl_encode_part(wrapper, obj, io); - // just make sure we output the remaining buffer + /* just make sure we output the remaining buffer */ yajl_gen_get_buf(wrapper->encoder, &buffer, &len); outBuff = rb_str_new((const char *)buffer, len); yajl_gen_clear(wrapper->encoder); if (io != Qnil) { @@ -588,11 +594,11 @@ wrapper->on_progress_callback = callback; return Qnil; } -// JSON Gem compatibility +/* JSON Gem compatibility */ /* * Document-class: Hash */ /* @@ -781,11 +787,11 @@ rb_define_method(rb_cNilClass, "to_json", rb_yajl_json_ext_nil_to_json, -1); return Qnil; } -// Ruby Extension initializer +/* Ruby Extension initializer */ void Init_yajl_ext() { mYajl = rb_define_module("Yajl"); cParseError = rb_define_class_under(mYajl, "ParseError", rb_eStandardError); cEncodeError = rb_define_class_under(mYajl, "EncodeError", rb_eStandardError); @@ -810,14 +816,15 @@ intern_eof = rb_intern("eof?"); intern_call = rb_intern("call"); intern_keys = rb_intern("keys"); intern_to_s = rb_intern("to_s"); intern_to_json = rb_intern("to_json"); - - sym_allow_comments = rb_intern("allow_comments"); - sym_check_utf8 = rb_intern("check_utf8"); - sym_pretty = rb_intern("pretty"); - sym_indent = rb_intern("indent"); - sym_terminator = rb_intern("terminator"); - sym_symbolize_keys = rb_intern("symbolize_keys"); + intern_to_sym = rb_intern("to_sym"); intern_has_key = rb_intern("has_key?"); + + sym_allow_comments = ID2SYM(rb_intern("allow_comments")); + sym_check_utf8 = ID2SYM(rb_intern("check_utf8")); + sym_pretty = ID2SYM(rb_intern("pretty")); + sym_indent = ID2SYM(rb_intern("indent")); + sym_terminator = ID2SYM(rb_intern("terminator")); + sym_symbolize_keys = ID2SYM(rb_intern("symbolize_keys")); }