]> granicus.if.org Git - php/commitdiff
MFH (json.c r-1.32) Add support for encoding options
authorSara Golemon <pollita@php.net>
Mon, 17 Dec 2007 07:48:27 +0000 (07:48 +0000)
committerSara Golemon <pollita@php.net>
Mon, 17 Dec 2007 07:48:27 +0000 (07:48 +0000)
ext/json/json.c
ext/json/tests/006.phpt [new file with mode: 0644]

index 79c6fd5b9e15d89d53195884dfc0a5ed2b1eb3ad..d9455b011f3b64a993e583bf081535fd22cf663c 100644 (file)
@@ -37,6 +37,11 @@ static PHP_FUNCTION(json_decode);
 
 static const char digits[] = "0123456789abcdef";
 
+#define PHP_JSON_HEX_TAG       (1<<0)
+#define PHP_JSON_HEX_AMP       (1<<1)
+#define PHP_JSON_HEX_APOS      (1<<2)
+#define PHP_JSON_HEX_QUOT      (1<<3)
+
 /* {{{ json_functions[]
  *
  * Every user visible function must have an entry in json_functions[].
@@ -48,6 +53,19 @@ static const function_entry json_functions[] = {
 };
 /* }}} */
 
+/* {{{ MINIT */
+static PHP_MINIT_FUNCTION(json)
+{
+       REGISTER_LONG_CONSTANT("JSON_HEX_TAG",  PHP_JSON_HEX_TAG,  CONST_CS | CONST_PERSISTENT);
+       REGISTER_LONG_CONSTANT("JSON_HEX_AMP",  PHP_JSON_HEX_AMP,  CONST_CS | CONST_PERSISTENT);
+       REGISTER_LONG_CONSTANT("JSON_HEX_APOS", PHP_JSON_HEX_APOS, CONST_CS | CONST_PERSISTENT);
+       REGISTER_LONG_CONSTANT("JSON_HEX_QUOT", PHP_JSON_HEX_QUOT, CONST_CS | CONST_PERSISTENT);
+
+       return SUCCESS;
+}
+/* }}} */
+
+
 /* {{{ json_module_entry
  */
 zend_module_entry json_module_entry = {
@@ -56,7 +74,7 @@ zend_module_entry json_module_entry = {
 #endif
     "json",
     json_functions,
-    NULL,
+    PHP_MINIT(json),
     NULL,
     NULL,
     NULL,
@@ -83,8 +101,8 @@ static PHP_MINFO_FUNCTION(json)
 }
 /* }}} */
 
-static void json_encode_r(smart_str *buf, zval *val TSRMLS_DC);
-static void json_escape_string(smart_str *buf, char *s, int len);
+static void json_encode_r(smart_str *buf, zval *val, int options TSRMLS_DC);
+static void json_escape_string(smart_str *buf, char *s, int len, int options);
 
 static int json_determine_array_type(zval **val TSRMLS_DC)  /* {{{ */
 {
@@ -120,7 +138,7 @@ static int json_determine_array_type(zval **val TSRMLS_DC)  /* {{{ */
 }
 /* }}} */
 
-static void json_encode_array(smart_str *buf, zval **val TSRMLS_DC) { /* {{{ */
+static void json_encode_array(smart_str *buf, zval **val, int options TSRMLS_DC) { /* {{{ */
     int i, r;
     HashTable *myht;
 
@@ -176,7 +194,7 @@ static void json_encode_array(smart_str *buf, zval **val TSRMLS_DC) { /* {{{ */
                         need_comma = 1;
                     }
  
-                    json_encode_r(buf, *data TSRMLS_CC);
+                    json_encode_r(buf, *data, options TSRMLS_CC);
                 } else if (r == 1) {
                     if (i == HASH_KEY_IS_STRING) {
                         if (key[0] == '\0' && Z_TYPE_PP(val) == IS_OBJECT) {
@@ -190,10 +208,10 @@ static void json_encode_array(smart_str *buf, zval **val TSRMLS_DC) { /* {{{ */
                             need_comma = 1;
                         }
 
-                        json_escape_string(buf, key, key_len - 1);
+                        json_escape_string(buf, key, key_len - 1, options);
                         smart_str_appendc(buf, ':');
 
-                        json_encode_r(buf, *data TSRMLS_CC);
+                        json_encode_r(buf, *data, options TSRMLS_CC);
                     } else {
                         if (need_comma) {
                             smart_str_appendc(buf, ',');
@@ -206,7 +224,7 @@ static void json_encode_array(smart_str *buf, zval **val TSRMLS_DC) { /* {{{ */
                         smart_str_appendc(buf, '"');
                         smart_str_appendc(buf, ':');
 
-                        json_encode_r(buf, *data TSRMLS_CC);
+                        json_encode_r(buf, *data, options TSRMLS_CC);
                     }
                 }
 
@@ -230,7 +248,7 @@ static void json_encode_array(smart_str *buf, zval **val TSRMLS_DC) { /* {{{ */
 
 #define REVERSE16(us) (((us & 0xf) << 12) | (((us >> 4) & 0xf) << 8) | (((us >> 8) & 0xf) << 4) | ((us >> 12) & 0xf))
 
-static void json_escape_string(smart_str *buf, char *s, int len) /* {{{ */
+static void json_escape_string(smart_str *buf, char *s, int len, int options) /* {{{ */
 {
     int pos = 0;
     unsigned short us;
@@ -266,7 +284,11 @@ static void json_escape_string(smart_str *buf, char *s, int len) /* {{{ */
         {
             case '"':
                 {
-                    smart_str_appendl(buf, "\\\"", 2);
+                    if (options & PHP_JSON_HEX_QUOT) {
+                        smart_str_appendl(buf, "\\u0022", 6);
+                    } else {
+                        smart_str_appendl(buf, "\\\"", 2);
+                    }
                 }
                 break;
             case '\\':
@@ -304,6 +326,42 @@ static void json_escape_string(smart_str *buf, char *s, int len) /* {{{ */
                     smart_str_appendl(buf, "\\t", 2);
                 }
                 break;
+            case '<':
+                {
+                    if (options & PHP_JSON_HEX_TAG) {
+                        smart_str_appendl(buf, "\\u003C", 6);
+                    } else {
+                        smart_str_appendc(buf, '<');
+                    }
+                }
+                break;
+            case '>':
+                {
+                    if (options & PHP_JSON_HEX_TAG) {
+                        smart_str_appendl(buf, "\\u003E", 6);
+                    } else {
+                        smart_str_appendc(buf, '>');
+                    }
+                }
+                break;
+            case '&':
+                {
+                    if (options & PHP_JSON_HEX_AMP) {
+                        smart_str_appendl(buf, "\\u0026", 6);
+                    } else {
+                        smart_str_appendc(buf, '&');
+                    }
+                }
+                break;
+            case '\'':
+                {
+                    if (options & PHP_JSON_HEX_APOS) {
+                        smart_str_appendl(buf, "\\u0027", 6);
+                    } else {
+                        smart_str_appendc(buf, '\'');
+                    }
+                }
+                break;
             default:
                 {
                     if (us >= ' ' && (us & 127) == us)
@@ -333,7 +391,7 @@ static void json_escape_string(smart_str *buf, char *s, int len) /* {{{ */
 }
 /* }}} */
 
-static void json_encode_r(smart_str *buf, zval *val TSRMLS_DC) /* {{{ */
+static void json_encode_r(smart_str *buf, zval *val, int options TSRMLS_DC) /* {{{ */
 {
     switch (Z_TYPE_P(val)) {
         case IS_NULL:
@@ -369,11 +427,11 @@ static void json_encode_r(smart_str *buf, zval *val TSRMLS_DC) /* {{{ */
             }
             break;
         case IS_STRING:
-            json_escape_string(buf, Z_STRVAL_P(val), Z_STRLEN_P(val));
+            json_escape_string(buf, Z_STRVAL_P(val), Z_STRLEN_P(val), options);
             break;
         case IS_ARRAY:
         case IS_OBJECT:
-            json_encode_array(buf, &val TSRMLS_CC);
+            json_encode_array(buf, &val, options TSRMLS_CC);
             break;
         default:
             zend_error(E_WARNING, "[json] (json_encode_r) type is unsupported, encoded as null.");
@@ -391,12 +449,13 @@ static PHP_FUNCTION(json_encode)
 {
     zval *parameter;
     smart_str buf = {0};
+    long options = 0;
 
-    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &parameter) == FAILURE) {
+    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|l", &parameter, &options) == FAILURE) {
         return;
     }
 
-    json_encode_r(&buf, parameter TSRMLS_CC);
+    json_encode_r(&buf, parameter, options TSRMLS_CC);
 
     ZVAL_STRINGL(return_value, buf.c, buf.len, 1);
 
diff --git a/ext/json/tests/006.phpt b/ext/json/tests/006.phpt
new file mode 100644 (file)
index 0000000..e1d4b46
--- /dev/null
@@ -0,0 +1,23 @@
+--TEST--
+json_encode() & extended encoding
+--SKIPIF--
+<?php if (!extension_loaded("json")) print "skip"; ?>
+--FILE--
+<?php
+
+$a = array('<foo>',"'bar'",'"baz"','&blong&');
+
+echo "Normal: ", json_encode($a), "\n";
+echo "Tags: ",   json_encode($a,JSON_HEX_TAG), "\n";
+echo "Apos: ",   json_encode($a,JSON_HEX_APOS), "\n";
+echo "Quot: ",   json_encode($a,JSON_HEX_QUOT), "\n";
+echo "Amp: ",    json_encode($a,JSON_HEX_AMP), "\n";
+echo "All: ",    json_encode($a,JSON_HEX_TAG|JSON_HEX_APOS|JSON_HEX_QUOT|JSON_HEX_AMP), "\n";
+?>
+--EXPECT--
+Normal: ["<foo>","'bar'","\"baz\"","&blong&"]
+Tags: ["\u003Cfoo\u003E","'bar'","\"baz\"","&blong&"]
+Apos: ["<foo>","\u0027bar\u0027","\"baz\"","&blong&"]
+Quot: ["<foo>","'bar'","\u0022baz\u0022","&blong&"]
+Amp: ["<foo>","'bar'","\"baz\"","\u0026blong\u0026"]
+All: ["\u003Cfoo\u003E","\u0027bar\u0027","\u0022baz\u0022","\u0026blong\u0026"]