rtyler / py-yajl

py-yajl provides Python bindings for the Yajl JSON encoder/decoder library
http://rtyler.github.com/py-yajl
74 stars 18 forks source link

Problem with long ints on 32bit platforms #23

Closed mattbillenstein closed 7 years ago

mattbillenstein commented 14 years ago

I've found an inconsistency with how the built-in json module and yajl handle dumping long ints on 32-bit platforms:

$ python -c 'import json;print json.dumps(1282204340000)'
1282204340000

$ python -c 'import yajl as json;print json.dumps(1282204340000)'
-1

Basically PyLong_AsLong catches the overflow and passes -1 to yajl_gen_integer() ...

Here's a patch you might consider:

diff -r -u yajl-0.3.5/encoder.c yajl-0.3.5-mod/encoder.c
--- yajl-0.3.5/encoder.c    2010-04-08 04:35:07.000000000 +0000
+++ yajl-0.3.5-mod/encoder.c    2010-08-19 07:51:33.000000000 +0000
@@ -164,7 +164,7 @@
     }
 #endif
     if (PyLong_Check(object)) {
-        return yajl_gen_integer(handle, PyLong_AsLong(object));
+        return yajl_gen_integer(handle, PyLong_AsLongLong(object));
     }
     if (PyFloat_Check(object)) {
         return yajl_gen_double(handle, PyFloat_AsDouble(object));
diff -r -u yajl-0.3.5/setup.py yajl-0.3.5-mod/setup.py
--- yajl-0.3.5/setup.py 2010-04-08 04:41:59.000000000 +0000
+++ yajl-0.3.5-mod/setup.py 2010-08-19 07:59:06.000000000 +0000
@@ -61,7 +61,7 @@
     print('>>>      `git submodule update --init`')
     subprocess.call(['git', 'submodule', 'update', '--init'])

-subprocess.call(['git', 'submodule', 'update',])
+#subprocess.call(['git', 'submodule', 'update',])

 if not os.path.exists('includes'):
     # Our symlink into the yajl directory isn't there, let's fixulate that
diff -r -u yajl-0.3.5/yajl/src/api/yajl_gen.h yajl-0.3.5-mod/yajl/src/api/yajl_gen.h
--- yajl-0.3.5/yajl/src/api/yajl_gen.h  2010-01-09 09:19:26.000000000 +0000
+++ yajl-0.3.5-mod/yajl/src/api/yajl_gen.h  2010-08-19 07:42:51.000000000 +0000
@@ -122,7 +122,7 @@
     /** free a generator handle */    
     YAJL_API void yajl_gen_free(yajl_gen handle);

-    YAJL_API yajl_gen_status yajl_gen_integer(yajl_gen hand, long int number);
+    YAJL_API yajl_gen_status yajl_gen_integer(yajl_gen hand, long long int number);
     /** generate a floating point number.  number may not be infinity or
      *  NaN, as these have no representation in JSON.  In these cases the
      *  generator will return 'yajl_gen_invalid_number' */
diff -r -u yajl-0.3.5/yajl/src/yajl_gen.c yajl-0.3.5-mod/yajl/src/yajl_gen.c
--- yajl-0.3.5/yajl/src/yajl_gen.c  2010-04-05 05:06:01.000000000 +0000
+++ yajl-0.3.5-mod/yajl/src/yajl_gen.c  2010-08-19 07:41:48.000000000 +0000
@@ -178,11 +178,11 @@
         g->print(g->ctx, "\n", 1);        

 yajl_gen_status
-yajl_gen_integer(yajl_gen g, long int number)
+yajl_gen_integer(yajl_gen g, long long int number)
 {
     char i[32];
     ENSURE_VALID_STATE; ENSURE_NOT_KEY; INSERT_SEP; INSERT_WHITESPACE;
-    sprintf(i, "%ld", number);
+    sprintf(i, "%lld", number);
     g->print(g->ctx, i, strlen(i));
     APPENDED_ATOM;
     FINAL_NEWLINE;

Which replicates the json.dumps behavior:

$ python -c 'import yajl as json;print json.dumps(1282204340000)'
1282204340000
rtyler commented 14 years ago

Didn't your mother ever tell you to always use unified diffs ;)

Anyways, I'm on a plane tonight so I'll take a look and add a test case and hopefully get a release ready for when I touch down :)

lloyd commented 14 years ago

rtyler: can't you just always use the yajl_gen_number call and format yer numbers into strings yourself?