summaryrefslogtreecommitdiff
path: root/lisp/json.el
diff options
context:
space:
mode:
Diffstat (limited to 'lisp/json.el')
-rw-r--r--lisp/json.el47
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 "]"