Package: python-cjson
Version: 1.0.5-4build1
Severity: normal
I've written a patch that fixes this and is resonably fast. I'm sure
there are faster ways to do this, but this is about how much time I'm
willing to spend on it :)
-- no debconf information
Index: python-cjson-1.0.5/cjson.c
=================================================================== ---
python-cjson-1.0.5.orig/cjson.c +++ python-cjson-1.0.5/cjson.c @@ -19,6
+19,9 @@ int all_unicode; // make all output strings unicode if true }
JSONData;
+unsigned int *strutil_remove_index(unsigned int *arr, size_t *num_elements, int index);
+char *strutil_do_removal(const char *s_in, size_t s_in_len, unsigned int *mask, size_t num_elements);
+
static PyObject* encode_object(PyObject *object);
static PyObject* encode_string(PyObject *object);
static PyObject* encode_unicode(PyObject *object);
@@ -120,9 +123,12 @@
int c, escaping, has_unicode, string_escape;
Py_ssize_t len;
char *ptr;
+ unsigned int *escaped_solidus_mask = NULL;
+ size_t escaped_solidus_mask_size = 0;
// look for the closing quote
escaping = has_unicode = string_escape = False;
+
ptr = jsondata->ptr + 1;
while (True) {
c = *ptr;
@@ -145,6 +151,11 @@
case 'u':
has_unicode = True;
break;
+ case '/':
+ escaped_solidus_mask = strutil_remove_index(escaped_solidus_mask,
+ &escaped_solidus_mask_size,
+ ptr - jsondata->ptr - 2);
+ /* Intentionally not break'ing */
case '"':
case 'r':
case 'n':
@@ -164,9 +175,22 @@
if (has_unicode || jsondata->all_unicode)
object = PyUnicode_DecodeUnicodeEscape(jsondata->ptr+1, len, NULL);
- else if (string_escape)
- object = PyString_DecodeEscape(jsondata->ptr+1, len, NULL, 0, NULL);
- else
+ else if (string_escape) {
+ char *s;
+ s = jsondata->ptr+1;
+
+ if (escaped_solidus_mask_size) {
+ s = strutil_do_removal(s, len, escaped_solidus_mask, escaped_solidus_mask_size);
+ len = len - escaped_solidus_mask_size;
+ }
+
+ object = PyString_DecodeEscape(s, len, NULL, 0, NULL);
+
+ if (escaped_solidus_mask_size) {
+ free(s);
+ free(escaped_solidus_mask);
+ }
+ } else
object = PyString_FromStringAndSize(jsondata->ptr+1, len);
if (object == NULL) {
Index: python-cjson-1.0.5/jsontest.py
===================================================================
--- python-cjson-1.0.5.orig/jsontest.py
+++ python-cjson-1.0.5/jsontest.py
@@ -91,6 +91,12 @@
s = cjson.encode(r'/')
self.assertEqual(r'"\/"', _removeWhitespace(s))
+# Disabled by Soren Hansen. It's supposed to be escaped,
+# so verifying that it isn't is nonsense.
+# def testWriteNonEscapedSolidus(self):
+# s = cjson.encode(r'/')
+# self.assertEqual(r'"/"', _removeWhitespace(s))
+
def testWriteEscapedReverseSolidus(self):
s = cjson.encode("\\")
self.assertEqual(r'"\\"', _removeWhitespace(s))
Index: python-cjson-1.0.5/strutil.c
===================================================================
--- /dev/null
+++ python-cjson-1.0.5/strutil.c
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2011 Dan Pascu. See LICENSE for details.
+ * Author: Soren Hansen <[email protected]>
+ *
+ * Utility functions for cjson (kept separate to make unit testing easier).
+ *
+ * To run the tests:
+ * ./test_strutil.sh
+ *
+ * Disclaimer:
+ * I don't think it is very pretty. At all. I do think it's pretty fast,
+ * though.
+ */
+
+#include <math.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <assert.h>
+#include <string.h>
+
+#define ARRAY_SIZE_INCREMENTS 256
+
+static size_t size_to_allocate(int bit);
+unsigned int *strutil_remove_index(unsigned int *arr, size_t *num_elements, int index);
+char *strutil_do_removal(const char *s_in, size_t s_in_len, unsigned int *mask, size_t num_elements);
+
+static size_t
+size_to_allocate(int num_elements) {
+ return (((num_elements+255)/ARRAY_SIZE_INCREMENTS))*ARRAY_SIZE_INCREMENTS;
+}
+
+unsigned int *strutil_remove_index(unsigned int *arr, size_t *num_elements, int index) {
+ size_t required_size;
+
+ required_size = size_to_allocate(*num_elements+1);
+ if (required_size > size_to_allocate(*num_elements)) {
+ if ((arr = realloc(arr, sizeof(int)*required_size)) == NULL)
+ return NULL;
+ }
+ arr[(*num_elements)++] = index;
+ return arr;
+}
+
+char *strutil_do_removal(const char *s_in, size_t s_in_len,
+ unsigned int *arr, size_t num_elements) {
+ const char *in_ptr;
+ char *s_out = malloc(s_in_len - num_elements);
+ char *out_ptr;
+ int i = 0;
+ int last_index = s_in_len;
+ int width;
+
+ /* Point to last element of each of the arrays */
+ in_ptr = s_in + s_in_len;
+ out_ptr = s_out + s_in_len - num_elements;
+
+ for (i=num_elements-1;i>=0;i--,in_ptr--) {
+ width = last_index-arr[i]-1;
+ out_ptr -= width;
+ in_ptr -= width;
+ memcpy(out_ptr, in_ptr, width);
+ last_index = arr[i];
+ }
+ memcpy(s_out, s_in, last_index);
+ return s_out;
+}
+
+#ifdef TEST
+void test_strutil_do_removal(void) {
+ unsigned int *arr = NULL;
+ size_t num_elements = 0;
+ char *s_in = "X123456X789X123X";
+ char *s_out;
+
+ /* Mark all the X's for removal */
+ arr = strutil_remove_index(arr, &num_elements, 0);
+ arr = strutil_remove_index(arr, &num_elements, 7);
+ arr = strutil_remove_index(arr, &num_elements, 11);
+ arr = strutil_remove_index(arr, &num_elements, 15);
+
+ s_out = strutil_do_removal(s_in, strlen(s_in), arr, num_elements);
+ assert(strcmp(s_out, "123456789123") == 0);
+ free(s_out);
+ free(arr);
+}
+
+void test_required_size_for_bit(void) {
+ assert(size_to_allocate(0) == 0);
+ assert(size_to_allocate(1) == 256);
+ assert(size_to_allocate(255) == 256);
+ assert(size_to_allocate(256) == 256);
+ assert(size_to_allocate(257) == 512);
+}
+
+int main(int argc, char *argv[]) {
+ test_required_size_for_bit();
+ test_strutil_do_removal();
+ return 0;
+}
+#endif
Index: python-cjson-1.0.5/test_strutil.sh
===================================================================
--- /dev/null
+++ python-cjson-1.0.5/test_strutil.sh
@@ -0,0 +1,5 @@
+#!/bin/sh
+set -e
+gcc -Wall -pg -fprofile-arcs -o strutil_unittest -O0 -DTEST strutil.c -lm
+#gcc -o strutil_unittest -DTEST strutil.c -lm
+./strutil_unittest
Index: python-cjson-1.0.5/setup.py
===================================================================
--- python-cjson-1.0.5.orig/setup.py
+++ python-cjson-1.0.5/setup.py
@@ -25,6 +25,6 @@
"Topic :: Software Development :: Libraries :: Python Modules"
],
ext_modules = [
- Extension(name='cjson', sources=['cjson.c'], define_macros=macros)
+ Extension(name='cjson', sources=['cjson.c','strutil.c'], define_macros=macros)
]
)
_______________________________________________
Python-modules-team mailing list
[email protected]
http://lists.alioth.debian.org/cgi-bin/mailman/listinfo/python-modules-team