Repository: Nykakin/chompjs (language: python)

Issue:
Translate NaN as float('nan')
See https://stackoverflow.com/a/944733/939364


Discussion / hints:

Fix patch:
diff --git a/CHANGELOG b/CHANGELOG
index 9f119d3..ee91dbb 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,3 +1,9 @@
+1.1.9
+* Handle NaN in input (#37)
+
+1.1.8
+* Fixed previous release (package couldn't be installed)
+
 1.1.7
 * Handle unquoted properties starting with reserved JS keywords (#34)
 
diff --git a/_chompjs/buffer.c b/_chompjs/buffer.c
index 33ad41f..4445be1 100644
--- a/_chompjs/buffer.c
+++ b/_chompjs/buffer.c
@@ -28,7 +28,7 @@ void push(struct CharBuffer* buffer, char value) {
     }
 }
 
-void push_string(struct CharBuffer* buffer, char* value, size_t len) {
+void push_string(struct CharBuffer* buffer, const char* value, size_t len) {
     if(buffer->index + len >= buffer->memory_buffer_length) {
         buffer->data = realloc(buffer->data, 2*buffer->memory_buffer_length);
         buffer->memory_buffer_length *= 2;
diff --git a/_chompjs/buffer.h b/_chompjs/buffer.h
index abcea1c..efef357 100644
--- a/_chompjs/buffer.h
+++ b/_chompjs/buffer.h
@@ -24,7 +24,7 @@ void release_char_buffer(struct CharBuffer* buffer);
 
 void push(struct CharBuffer* buffer, char value);
 
-void push_string(struct CharBuffer* buffer, char* value, size_t len);
+void push_string(struct CharBuffer* buffer, const char* value, size_t len);
 
 void pop(struct CharBuffer* buffer);
 
diff --git a/_chompjs/parser.c b/_chompjs/parser.c
index 1536167..2c795ea 100644
--- a/_chompjs/parser.c
+++ b/_chompjs/parser.c
@@ -57,12 +57,12 @@ void unemit(struct Lexer* lexer) {
     pop(&lexer->output);
 }
 
-void emit_string(char *s, size_t size, struct Lexer* lexer) {
+void emit_string(const char *s, size_t size, struct Lexer* lexer) {
     push_string(&lexer->output, s, size);
     lexer->input_position += size;   
 }
 
-void emit_string_in_place(char *s, size_t size, struct Lexer* lexer) {
+void emit_string_in_place(const char *s, size_t size, struct Lexer* lexer) {
     push_string(&lexer->output, s, size);
 }
 
@@ -181,8 +181,18 @@ struct State* json(struct Lexer* lexer) {
     return &states[ERROR_STATE];
 }
 
+struct State* _handle_string(struct Lexer* lexer, const char* string, size_t length) {
+    char next_char = lexer->input[lexer->input_position+length+1];
+    if(next_char == '_' || isalnum(next_char)) {
+        return handle_unrecognized(lexer);
+    }
+    emit_string(string, length, lexer);
+    return &states[JSON_STATE];
+}
+
 struct State* value(struct Lexer* lexer) {
     char c = next_char(lexer);
+    const char* position = lexer->input + lexer->input_position;
 
     if(c == '"' || c == '\'' || c == '`') {
         return handle_quoted(lexer);
@@ -192,26 +202,16 @@ struct State* value(struct Lexer* lexer) {
         } else {
             return handle_numeric(lexer);
         }
-    } else if(strncmp(lexer->input + lexer->input_position, "true", 4) == 0) {
-        char next_char = lexer->input[lexer->input_position+5];
-        if(next_char == '_' || isalnum(next_char)) {
-            return handle_unrecognized(lexer);
-        }
-        emit_string("true", 4, lexer);
-    } else if(strncmp(lexer->input + lexer->input_position, "false", 5) == 0) {
-        char next_char = lexer->input[lexer->input_position+6];
-        if(next_char == '_' || isalnum(next_char)) {
-            return handle_unrecognized(lexer);
-        }
-        emit_string("false", 5, lexer);
-    } else if(strncmp(lexer->input + lexer->input_position, "null", 4) == 0) {
-        char next_char = lexer->input[lexer->input_position+5];
-        if(next_char == '_' || isalnum(next_char)) {
-            return handle_unrecognized(lexer);
-        }
-        emit_string("null", 4, lexer);
+    } else if(strncmp(position, "true", 4) == 0) {
+        return _handle_string(lexer, "true", 4);
+    } else if(strncmp(position, "false", 5) == 0) {
+        return _handle_string(lexer, "false", 5);
+    } else if(strncmp(position, "null", 4) == 0) {
+        return _handle_string(lexer, "null", 4);
     } else if(c == ']' || c == '}' || c == '[' || c == '{') {
         return &states[JSON_STATE];
+    } else if(strncmp(position, "NaN", 3) == 0) {
+        return _handle_string(lexer, "NaN", 3);
     } else {
         return handle_unrecognized(lexer);
     }
diff --git a/_chompjs/parser.h b/_chompjs/parser.h
index 73cdd48..d1e2be8 100644
--- a/_chompjs/parser.h
+++ b/_chompjs/parser.h
@@ -85,10 +85,10 @@ void emit_in_place(char c, struct Lexer* lexer);
 void unemit(struct Lexer* lexer);
 
 /** Send string to output buffer, advance input position */
-void emit_string(char *s, size_t size, struct Lexer* lexer);
+void emit_string(const char *s, size_t size, struct Lexer* lexer);
 
 /** Send string to output buffer, keep old input position */
-void emit_string_in_place(char *s, size_t size, struct Lexer* lexer);
+void emit_string_in_place(const char *s, size_t size, struct Lexer* lexer);
 
 /** Handle comments in JSON body */
 void handle_comments(struct Lexer* lexer);
diff --git a/setup.py b/setup.py
index babcb34..0d893b7 100644
--- a/setup.py
+++ b/setup.py
@@ -26,7 +26,7 @@
 
 setup(
     name='chompjs',
-    version='1.1.8',
+    version='1.1.9',
     description='Parsing JavaScript objects into Python dictionaries',
     author='Mariusz Obajtek',
     author_email='nykakin@gmail.com',


Test patch:
diff --git a/chompjs/test_parser.py b/chompjs/test_parser.py
index a8a401b..4878901 100644
--- a/chompjs/test_parser.py
+++ b/chompjs/test_parser.py
@@ -2,6 +2,7 @@
 from __future__ import unicode_literals
 
 import functools
+import math
 import unittest
 
 from chompjs import parse_js_object
@@ -85,6 +86,11 @@ def test_parse_standard_values(self, in_data, expected_data):
         result = parse_js_object(in_data)
         self.assertEqual(result, expected_data)
 
+    def test_parse_nan(self):
+        in_data = '{"A": NaN}'
+        result = parse_js_object(in_data)
+        assert math.isnan(result["A"])
+
     @parametrize_test(
         ("{abc: 100, dev: 200}", {'abc': 100, 'dev': 200}),
         ("{abcdefghijklmnopqrstuvwxyz: 12}", {"abcdefghijklmnopqrstuvwxyz": 12}),