]> code.delx.au - gnu-emacs/commitdiff
Rewrite json-encode-string
authorDmitry Gutov <dgutov@yandex.ru>
Sun, 22 Mar 2015 22:50:58 +0000 (00:50 +0200)
committerDmitry Gutov <dgutov@yandex.ru>
Sun, 22 Mar 2015 22:50:58 +0000 (00:50 +0200)
Fixes: debbugs:20154
* lisp/json.el (json-decode-char0): Delete this alias.
(json-encode-string): Rewrite to improve performance.
(json-encode-char): Fold into `json-encode-string'.

lisp/ChangeLog
lisp/json.el

index 52c6a726432d6530afae20c851147d9e485079ba..2fc318a3b89b9d73b563fe7d1b17760bd10c383b 100644 (file)
@@ -1,3 +1,9 @@
+2015-03-22  Dmitry Gutov  <dgutov@yandex.ru>
+
+       * json.el (json-decode-char0): Delete this alias.
+       (json-encode-string): Rewrite to improve performance (bug#20154).
+       (json-encode-char): Fold into `json-encode-string'.
+
 2015-03-22  Artur Malabarba  <bruce.connor.am@gmail.com>
 
        * menu-bar.el (menu-bar-update-buffers): Count displayed buffers
index 98974e67b7e304088c4baf21804b1df8b73bbd21..fb0f62c877794747d158bf378f7af3fabe87e9c2 100644 (file)
@@ -55,7 +55,6 @@
 
 ;; Compatibility code
 
-(defalias 'json-encode-char0 'encode-char)
 (defalias 'json-decode-char0 'decode-char)
 
 
@@ -313,24 +312,28 @@ representation will be parsed correctly."
 
 ;; String encoding
 
-(defun json-encode-char (char)
-  "Encode CHAR as a JSON string."
-  (setq char (json-encode-char0 char 'ucs))
-  (let ((control-char (car (rassoc char json-special-chars))))
-    (cond
-     ;; Special JSON character (\n, \r, etc.).
-     (control-char
-      (format "\\%c" control-char))
-     ;; ASCIIish printable character.
-     ((and (> char 31) (< char 127))
-      (format "%c" char))
-     ;; Fallback: UCS code point in \uNNNN form.
-     (t
-      (format "\\u%04x" char)))))
-
 (defun json-encode-string (string)
   "Return a JSON representation of STRING."
-  (format "\"%s\"" (mapconcat 'json-encode-char string "")))
+  ;; Reimplement the meat of `replace-regexp-in-string', for
+  ;; performance (bug#20154).
+  (let ((l (length string))
+        (start 0)
+        res mb)
+    ;; Skip over ASCIIish printable characters.
+    (while (setq mb (string-match "[\"\\/\b\f\n\r\t]\\|[^ -~]" string start))
+      (let* ((c (aref string mb))
+             (special (rassq c json-special-chars)))
+        (push (substring string start mb) res)
+        (push (if special
+                  ;; Special JSON character (\n, \r, etc.).
+                  (string ?\\ (car special))
+                ;; Fallback: UCS code point in \uNNNN form.
+                (format "\\u%04x" c))
+              res)
+        (setq start (1+ mb))))
+    (push (substring string start l) res)
+    (push "\"" res)
+    (apply #'concat "\"" (nreverse res))))
 
 (defun json-encode-key (object)
   "Return a JSON representation of OBJECT.