diff options
Diffstat (limited to 'lisp/json.el')
-rw-r--r-- | lisp/json.el | 47 |
1 files changed, 31 insertions, 16 deletions
diff --git a/lisp/json.el b/lisp/json.el index 0cef554c56e..049c9b1951a 100644 --- a/lisp/json.el +++ b/lisp/json.el @@ -1,4 +1,4 @@ -;;; json.el --- JavaScript Object Notation parser / generator +;;; json.el --- JavaScript Object Notation parser / generator -*- lexical-binding: t -*- ;; Copyright (C) 2006-2017 Free Software Foundation, Inc. @@ -188,7 +188,7 @@ Unlike `reverse', this keeps the property-value pairs intact." ;; Reader utilities (defsubst json-advance (&optional n) - "Skip past the following N characters." + "Advance N characters forward." (forward-char n)) (defsubst json-peek () @@ -293,7 +293,7 @@ KEYWORD is the keyword expected." (unless (member keyword json-keywords) (signal 'json-unknown-keyword (list keyword))) (mapc (lambda (char) - (unless (char-equal char (json-peek)) + (when (/= char (json-peek)) (signal 'json-unknown-keyword (list (save-excursion (backward-word-strictly 1) @@ -330,10 +330,10 @@ representation will be parsed correctly." ;; If SIGN is non-nil, the number is explicitly signed. (let ((number-regexp "\\([0-9]+\\)?\\(\\.[0-9]+\\)?\\([Ee][+-]?[0-9]+\\)?")) - (cond ((and (null sign) (char-equal (json-peek) ?-)) + (cond ((and (null sign) (= (json-peek) ?-)) (json-advance) (- (json-read-number t))) - ((and (null sign) (char-equal (json-peek) ?+)) + ((and (null sign) (= (json-peek) ?+)) (json-advance) (json-read-number t)) ((and (looking-at number-regexp) @@ -363,6 +363,10 @@ representation will be parsed correctly." ;; String parsing +(defun json--decode-utf-16-surrogates (high low) + "Return the code point represented by the UTF-16 surrogates HIGH and LOW." + (+ (lsh (- high #xD800) 10) (- low #xDC00) #x10000)) + (defun json-read-escaped-char () "Read the JSON string escaped character at point." ;; Skip over the '\' @@ -372,7 +376,18 @@ representation will be parsed correctly." (cond (special (cdr special)) ((not (eq char ?u)) char) - ((looking-at "[0-9A-Fa-f][0-9A-Fa-f][0-9A-Fa-f][0-9A-Fa-f]") + ;; Special-case UTF-16 surrogate pairs, + ;; cf. https://tools.ietf.org/html/rfc7159#section-7. Note that + ;; this clause overlaps with the next one and therefore has to + ;; come first. + ((looking-at + (rx (group (any "Dd") (any "89ABab") (= 2 (any xdigit))) + "\\u" (group (any "Dd") (any "C-Fc-f") (= 2 (any xdigit))))) + (json-advance 10) + (json--decode-utf-16-surrogates + (string-to-number (match-string 1) 16) + (string-to-number (match-string 2) 16))) + ((looking-at (rx (= 4 xdigit))) (let ((hex (match-string 0))) (json-advance 4) (string-to-number hex 16))) @@ -381,14 +396,14 @@ representation will be parsed correctly." (defun json-read-string () "Read the JSON string at point." - (unless (char-equal (json-peek) ?\") + (unless (= (json-peek) ?\") (signal 'json-string-format (list "doesn't start with `\"'!"))) ;; Skip over the '"' (json-advance) (let ((characters '()) (char (json-peek))) - (while (not (char-equal char ?\")) - (push (if (char-equal char ?\\) + (while (not (= char ?\")) + (push (if (= char ?\\) (json-read-escaped-char) (json-pop)) characters) @@ -480,11 +495,11 @@ Please see the documentation of `json-object-type' and `json-key-type'." ;; read key/value pairs until "}" (let ((elements (json-new-object)) key value) - (while (not (char-equal (json-peek) ?})) + (while (not (= (json-peek) ?})) (json-skip-whitespace) (setq key (json-read-string)) (json-skip-whitespace) - (if (char-equal (json-peek) ?:) + (if (= (json-peek) ?:) (json-advance) (signal 'json-object-format (list ":" (json-peek)))) (json-skip-whitespace) @@ -495,8 +510,8 @@ Please see the documentation of `json-object-type' and `json-key-type'." (funcall json-post-element-read-function)) (setq elements (json-add-to-object elements key value)) (json-skip-whitespace) - (unless (char-equal (json-peek) ?}) - (if (char-equal (json-peek) ?,) + (when (/= (json-peek) ?}) + (if (= (json-peek) ?,) (json-advance) (signal 'json-object-format (list "," (json-peek)))))) ;; Skip over the "}" @@ -606,7 +621,7 @@ become JSON objects." (json-skip-whitespace) ;; read values until "]" (let (elements) - (while (not (char-equal (json-peek) ?\])) + (while (not (= (json-peek) ?\])) (json-skip-whitespace) (when json-pre-element-read-function (funcall json-pre-element-read-function (length elements))) @@ -614,8 +629,8 @@ become JSON objects." (when json-post-element-read-function (funcall json-post-element-read-function)) (json-skip-whitespace) - (unless (char-equal (json-peek) ?\]) - (if (char-equal (json-peek) ?,) + (when (/= (json-peek) ?\]) + (if (= (json-peek) ?,) (json-advance) (signal 'json-error (list 'bleah))))) ;; Skip over the "]" |