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"));
}