1 /* JSON parsing and serialization.
3 Copyright (C) 2017-2018 Free Software Foundation, Inc.
5 This file is part of GNU Emacs.
7 GNU Emacs is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 3 of the License, or (at
10 your option) any later version.
12 GNU Emacs is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
33 #define JSON_HAS_ERROR_CODE (JANSSON_VERSION_HEX >= 0x020B00)
39 DEF_DLL_FN (void, json_set_alloc_funcs
,
40 (json_malloc_t malloc_fn
, json_free_t free_fn
));
41 DEF_DLL_FN (void, json_delete
, (json_t
*json
));
42 DEF_DLL_FN (json_t
*, json_array
, (void));
43 DEF_DLL_FN (int, json_array_append_new
, (json_t
*array
, json_t
*value
));
44 DEF_DLL_FN (size_t, json_array_size
, (const json_t
*array
));
45 DEF_DLL_FN (json_t
*, json_object
, (void));
46 DEF_DLL_FN (int, json_object_set_new
,
47 (json_t
*object
, const char *key
, json_t
*value
));
48 DEF_DLL_FN (json_t
*, json_null
, (void));
49 DEF_DLL_FN (json_t
*, json_true
, (void));
50 DEF_DLL_FN (json_t
*, json_false
, (void));
51 DEF_DLL_FN (json_t
*, json_integer
, (json_int_t value
));
52 DEF_DLL_FN (json_t
*, json_real
, (double value
));
53 DEF_DLL_FN (json_t
*, json_stringn
, (const char *value
, size_t len
));
54 DEF_DLL_FN (char *, json_dumps
, (const json_t
*json
, size_t flags
));
55 DEF_DLL_FN (int, json_dump_callback
,
56 (const json_t
*json
, json_dump_callback_t callback
, void *data
,
58 DEF_DLL_FN (json_int_t
, json_integer_value
, (const json_t
*integer
));
59 DEF_DLL_FN (double, json_real_value
, (const json_t
*real
));
60 DEF_DLL_FN (const char *, json_string_value
, (const json_t
*string
));
61 DEF_DLL_FN (size_t, json_string_length
, (const json_t
*string
));
62 DEF_DLL_FN (json_t
*, json_array_get
, (const json_t
*array
, size_t index
));
63 DEF_DLL_FN (json_t
*, json_object_get
, (const json_t
*object
, const char *key
));
64 DEF_DLL_FN (size_t, json_object_size
, (const json_t
*object
));
65 DEF_DLL_FN (const char *, json_object_iter_key
, (void *iter
));
66 DEF_DLL_FN (void *, json_object_iter
, (json_t
*object
));
67 DEF_DLL_FN (json_t
*, json_object_iter_value
, (void *iter
));
68 DEF_DLL_FN (void *, json_object_key_to_iter
, (const char *key
));
69 DEF_DLL_FN (void *, json_object_iter_next
, (json_t
*object
, void *iter
));
70 DEF_DLL_FN (json_t
*, json_loads
,
71 (const char *input
, size_t flags
, json_error_t
*error
));
72 DEF_DLL_FN (json_t
*, json_load_callback
,
73 (json_load_callback_t callback
, void *data
, size_t flags
,
74 json_error_t
*error
));
76 /* This is called by json_decref, which is an inline function. */
77 void json_delete(json_t
*json
)
79 fn_json_delete (json
);
82 static bool json_initialized
;
85 init_json_functions (void)
87 HMODULE library
= w32_delayed_load (Qjson
);
92 LOAD_DLL_FN (library
, json_set_alloc_funcs
);
93 LOAD_DLL_FN (library
, json_delete
);
94 LOAD_DLL_FN (library
, json_array
);
95 LOAD_DLL_FN (library
, json_array_append_new
);
96 LOAD_DLL_FN (library
, json_array_size
);
97 LOAD_DLL_FN (library
, json_object
);
98 LOAD_DLL_FN (library
, json_object_set_new
);
99 LOAD_DLL_FN (library
, json_null
);
100 LOAD_DLL_FN (library
, json_true
);
101 LOAD_DLL_FN (library
, json_false
);
102 LOAD_DLL_FN (library
, json_integer
);
103 LOAD_DLL_FN (library
, json_real
);
104 LOAD_DLL_FN (library
, json_stringn
);
105 LOAD_DLL_FN (library
, json_dumps
);
106 LOAD_DLL_FN (library
, json_dump_callback
);
107 LOAD_DLL_FN (library
, json_integer_value
);
108 LOAD_DLL_FN (library
, json_real_value
);
109 LOAD_DLL_FN (library
, json_string_value
);
110 LOAD_DLL_FN (library
, json_string_length
);
111 LOAD_DLL_FN (library
, json_array_get
);
112 LOAD_DLL_FN (library
, json_object_get
);
113 LOAD_DLL_FN (library
, json_object_size
);
114 LOAD_DLL_FN (library
, json_object_iter_key
);
115 LOAD_DLL_FN (library
, json_object_iter
);
116 LOAD_DLL_FN (library
, json_object_iter_value
);
117 LOAD_DLL_FN (library
, json_object_key_to_iter
);
118 LOAD_DLL_FN (library
, json_object_iter_next
);
119 LOAD_DLL_FN (library
, json_loads
);
120 LOAD_DLL_FN (library
, json_load_callback
);
127 #define json_set_alloc_funcs fn_json_set_alloc_funcs
128 #define json_array fn_json_array
129 #define json_array_append_new fn_json_array_append_new
130 #define json_array_size fn_json_array_size
131 #define json_object fn_json_object
132 #define json_object_set_new fn_json_object_set_new
133 #define json_null fn_json_null
134 #define json_true fn_json_true
135 #define json_false fn_json_false
136 #define json_integer fn_json_integer
137 #define json_real fn_json_real
138 #define json_stringn fn_json_stringn
139 #define json_dumps fn_json_dumps
140 #define json_dump_callback fn_json_dump_callback
141 #define json_integer_value fn_json_integer_value
142 #define json_real_value fn_json_real_value
143 #define json_string_value fn_json_string_value
144 #define json_string_length fn_json_string_length
145 #define json_array_get fn_json_array_get
146 #define json_object_get fn_json_object_get
147 #define json_object_size fn_json_object_size
148 #define json_object_iter_key fn_json_object_iter_key
149 #define json_object_iter fn_json_object_iter
150 #define json_object_iter_value fn_json_object_iter_value
151 #define json_object_key_to_iter fn_json_object_key_to_iter
152 #define json_object_iter_next fn_json_object_iter_next
153 #define json_loads fn_json_loads
154 #define json_load_callback fn_json_load_callback
156 #endif /* WINDOWSNT */
158 /* We install a custom allocator so that we can avoid objects larger
159 than PTRDIFF_MAX. Such objects wouldn't play well with the rest of
160 Emacs's codebase, which generally uses ptrdiff_t for sizes and
161 indices. The other functions in this file also generally assume
162 that size_t values never exceed PTRDIFF_MAX. */
165 json_malloc (size_t size
)
167 if (size
> PTRDIFF_MAX
)
172 return malloc (size
);
176 json_free (void *ptr
)
184 json_set_alloc_funcs (json_malloc
, json_free
);
187 #if !JSON_HAS_ERROR_CODE
189 /* Return whether STRING starts with PREFIX. */
192 json_has_prefix (const char *string
, const char *prefix
)
194 size_t string_len
= strlen (string
);
195 size_t prefix_len
= strlen (prefix
);
196 return string_len
>= prefix_len
&& memcmp (string
, prefix
, prefix_len
) == 0;
199 /* Return whether STRING ends with SUFFIX. */
202 json_has_suffix (const char *string
, const char *suffix
)
204 size_t string_len
= strlen (string
);
205 size_t suffix_len
= strlen (suffix
);
206 return string_len
>= suffix_len
207 && memcmp (string
+ string_len
- suffix_len
, suffix
, suffix_len
) == 0;
212 /* Create a multibyte Lisp string from the UTF-8 string in
213 [DATA, DATA + SIZE). If the range [DATA, DATA + SIZE) does not
214 contain a valid UTF-8 string, an unspecified string is returned.
215 Note that all callers below either pass only value UTF-8 strings or
216 use this function for formatting error messages; in the latter case
217 correctness isn't critical. */
220 json_make_string (const char *data
, ptrdiff_t size
)
222 return code_convert_string (make_specified_string (data
, -1, size
, false),
223 Qutf_8_unix
, Qt
, false, true, true);
226 /* Create a multibyte Lisp string from the null-terminated UTF-8
227 string beginning at DATA. If the string is not a valid UTF-8
228 string, an unspecified string is returned. Note that all callers
229 below either pass only value UTF-8 strings or use this function for
230 formatting error messages; in the latter case correctness isn't
234 json_build_string (const char *data
)
236 return json_make_string (data
, strlen (data
));
239 /* Return a unibyte string containing the sequence of UTF-8 encoding
240 units of the UTF-8 representation of STRING. If STRING does not
241 represent a sequence of Unicode scalar values, return a string with
242 unspecified contents. */
245 json_encode (Lisp_Object string
)
247 /* FIXME: Raise an error if STRING is not a scalar value
249 return code_convert_string (string
, Qutf_8_unix
, Qt
, true, true, true);
252 static _Noreturn
void
253 json_out_of_memory (void)
255 xsignal0 (Qjson_out_of_memory
);
258 /* Signal a Lisp error corresponding to the JSON ERROR. */
260 static _Noreturn
void
261 json_parse_error (const json_error_t
*error
)
264 #if JSON_HAS_ERROR_CODE
265 switch (json_error_code (error
))
267 case json_error_premature_end_of_input
:
268 symbol
= Qjson_end_of_file
;
270 case json_error_end_of_input_expected
:
271 symbol
= Qjson_trailing_content
;
274 symbol
= Qjson_parse_error
;
278 if (json_has_suffix (error
->text
, "expected near end of file"))
279 symbol
= Qjson_end_of_file
;
280 else if (json_has_prefix (error
->text
, "end of file expected"))
281 symbol
= Qjson_trailing_content
;
283 symbol
= Qjson_parse_error
;
286 list5 (json_build_string (error
->text
),
287 json_build_string (error
->source
), make_natnum (error
->line
),
288 make_natnum (error
->column
), make_natnum (error
->position
)));
292 json_release_object (void *object
)
294 json_decref (object
);
297 /* Signal an error if OBJECT is not a string, or if OBJECT contains
298 embedded null characters. */
301 check_string_without_embedded_nulls (Lisp_Object object
)
303 CHECK_STRING (object
);
304 CHECK_TYPE (memchr (SDATA (object
), '\0', SBYTES (object
)) == NULL
,
305 Qstring_without_embedded_nulls_p
, object
);
308 /* Signal an error of type `json-out-of-memory' if OBJECT is
312 json_check (json_t
*object
)
315 json_out_of_memory ();
319 /* If STRING is not a valid UTF-8 string, signal an error of type
320 `wrong-type-argument'. STRING must be a unibyte string. */
323 json_check_utf8 (Lisp_Object string
)
325 CHECK_TYPE (utf8_string_p (string
), Qutf_8_string_p
, string
);
328 static json_t
*lisp_to_json (Lisp_Object
);
330 /* Convert a Lisp object to a toplevel JSON object (array or object).
331 This returns Lisp_Object so we can use unbind_to. The return value
334 static _GL_ARG_NONNULL ((2)) Lisp_Object
335 lisp_to_json_toplevel_1 (Lisp_Object lisp
, json_t
**json
)
339 ptrdiff_t size
= ASIZE (lisp
);
340 *json
= json_check (json_array ());
341 ptrdiff_t count
= SPECPDL_INDEX ();
342 record_unwind_protect_ptr (json_release_object
, json
);
343 for (ptrdiff_t i
= 0; i
< size
; ++i
)
346 = json_array_append_new (*json
, lisp_to_json (AREF (lisp
, i
)));
348 json_out_of_memory ();
350 eassert (json_array_size (*json
) == size
);
351 clear_unwind_protect (count
);
352 return unbind_to (count
, Qnil
);
354 else if (HASH_TABLE_P (lisp
))
356 struct Lisp_Hash_Table
*h
= XHASH_TABLE (lisp
);
357 *json
= json_check (json_object ());
358 ptrdiff_t count
= SPECPDL_INDEX ();
359 record_unwind_protect_ptr (json_release_object
, *json
);
360 for (ptrdiff_t i
= 0; i
< HASH_TABLE_SIZE (h
); ++i
)
361 if (!NILP (HASH_HASH (h
, i
)))
363 Lisp_Object key
= json_encode (HASH_KEY (h
, i
));
364 /* We can't specify the length, so the string must be
366 check_string_without_embedded_nulls (key
);
367 const char *key_str
= SSDATA (key
);
368 /* Reject duplicate keys. These are possible if the hash
369 table test is not `equal'. */
370 if (json_object_get (*json
, key_str
) != NULL
)
371 wrong_type_argument (Qjson_value_p
, lisp
);
372 int status
= json_object_set_new (*json
, key_str
,
373 lisp_to_json (HASH_VALUE (h
, i
)));
376 /* A failure can be caused either by an invalid key or
378 json_check_utf8 (key
);
379 json_out_of_memory ();
382 clear_unwind_protect (count
);
383 return unbind_to (count
, Qnil
);
385 else if (NILP (lisp
))
387 *json
= json_check (json_object ());
390 else if (CONSP (lisp
))
392 Lisp_Object tail
= lisp
;
393 *json
= json_check (json_object ());
394 ptrdiff_t count
= SPECPDL_INDEX ();
395 record_unwind_protect_ptr (json_release_object
, *json
);
398 Lisp_Object pair
= XCAR (tail
);
400 Lisp_Object key_symbol
= XCAR (pair
);
401 Lisp_Object value
= XCDR (pair
);
402 CHECK_SYMBOL (key_symbol
);
403 Lisp_Object key
= SYMBOL_NAME (key_symbol
);
404 /* We can't specify the length, so the string must be
406 check_string_without_embedded_nulls (key
);
407 const char *key_str
= SSDATA (key
);
408 /* Only add element if key is not already present. */
409 if (json_object_get (*json
, key_str
) == NULL
)
412 = json_object_set_new (*json
, key_str
, lisp_to_json (value
));
414 json_out_of_memory ();
417 CHECK_LIST_END (tail
, lisp
);
418 clear_unwind_protect (count
);
419 return unbind_to (count
, Qnil
);
421 wrong_type_argument (Qjson_value_p
, lisp
);
424 /* Convert LISP to a toplevel JSON object (array or object). Signal
425 an error of type `wrong-type-argument' if LISP is not a vector,
426 hashtable, or alist. */
429 lisp_to_json_toplevel (Lisp_Object lisp
)
431 if (++lisp_eval_depth
> max_lisp_eval_depth
)
432 xsignal0 (Qjson_object_too_deep
);
434 lisp_to_json_toplevel_1 (lisp
, &json
);
439 /* Convert LISP to any JSON object. Signal an error of type
440 `wrong-type-argument' if the type of LISP can't be converted to a
444 lisp_to_json (Lisp_Object lisp
)
446 if (EQ (lisp
, QCnull
))
447 return json_check (json_null ());
448 else if (EQ (lisp
, QCfalse
))
449 return json_check (json_false ());
450 else if (EQ (lisp
, Qt
))
451 return json_check (json_true ());
452 else if (INTEGERP (lisp
))
454 CHECK_TYPE_RANGED_INTEGER (json_int_t
, lisp
);
455 return json_check (json_integer (XINT (lisp
)));
457 else if (FLOATP (lisp
))
458 return json_check (json_real (XFLOAT_DATA (lisp
)));
459 else if (STRINGP (lisp
))
461 Lisp_Object encoded
= json_encode (lisp
);
462 json_t
*json
= json_stringn (SSDATA (encoded
), SBYTES (encoded
));
465 /* A failure can be caused either by an invalid string or by
467 json_check_utf8 (encoded
);
468 json_out_of_memory ();
473 /* LISP now must be a vector, hashtable, or alist. */
474 return lisp_to_json_toplevel (lisp
);
477 DEFUN ("json-serialize", Fjson_serialize
, Sjson_serialize
, 1, 1, NULL
,
478 doc
: /* Return the JSON representation of OBJECT as a string.
479 OBJECT must be a vector, hashtable, or alist, and its elements can
480 recursively contain `:null', `:false', t, numbers, strings, or other
481 vectors hashtables, and alist. `:null', `:false', and t will be
482 converted to JSON null, false, and true values, respectively. Vectors
483 will be converted to JSON arrays, and hashtables and alists to JSON
484 objects. Hashtable keys must be strings without embedded null
485 characters and must be unique within each object. Alist keys must be
486 symbols; if a key is duplicate, the first instance is used. */)
489 ptrdiff_t count
= SPECPDL_INDEX ();
492 if (!json_initialized
)
495 json_initialized
= init_json_functions ();
496 status
= json_initialized
? Qt
: Qnil
;
497 Vlibrary_cache
= Fcons (Fcons (Qjson
, status
), Vlibrary_cache
);
499 if (!json_initialized
)
501 message1 ("jansson library not found");
506 json_t
*json
= lisp_to_json_toplevel (object
);
507 record_unwind_protect_ptr (json_release_object
, json
);
509 /* If desired, we might want to add the following flags:
510 JSON_DECODE_ANY, JSON_ALLOW_NUL. */
511 char *string
= json_dumps (json
, JSON_COMPACT
);
513 json_out_of_memory ();
514 record_unwind_protect_ptr (free
, string
);
516 return unbind_to (count
, json_build_string (string
));
519 struct json_buffer_and_size
526 json_insert (void *data
)
528 struct json_buffer_and_size
*buffer_and_size
= data
;
529 /* FIXME: This should be possible without creating an intermediate
532 = json_make_string (buffer_and_size
->buffer
, buffer_and_size
->size
);
537 struct json_insert_data
539 /* nil if json_insert succeeded, otherwise the symbol
540 Qcatch_all_memory_full or a cons (ERROR-SYMBOL . ERROR-DATA). */
544 /* Callback for json_dump_callback that inserts the UTF-8 string in
545 [BUFFER, BUFFER + SIZE) into the current buffer.
546 If [BUFFER, BUFFER + SIZE) does not contain a valid UTF-8 string,
547 an unspecified string is inserted into the buffer. DATA must point
548 to a structure of type json_insert_data. This function may not
549 exit nonlocally. It catches all nonlocal exits and stores them in
550 data->error for reraising. */
553 json_insert_callback (const char *buffer
, size_t size
, void *data
)
555 struct json_insert_data
*d
= data
;
556 struct json_buffer_and_size buffer_and_size
557 = {.buffer
= buffer
, .size
= size
};
558 d
->error
= internal_catch_all (json_insert
, &buffer_and_size
, Fidentity
);
559 return NILP (d
->error
) ? 0 : -1;
562 DEFUN ("json-insert", Fjson_insert
, Sjson_insert
, 1, 1, NULL
,
563 doc
: /* Insert the JSON representation of OBJECT before point.
564 This is the same as (insert (json-serialize OBJECT)), but potentially
565 faster. See the function `json-serialize' for allowed values of
569 ptrdiff_t count
= SPECPDL_INDEX ();
572 if (!json_initialized
)
575 json_initialized
= init_json_functions ();
576 status
= json_initialized
? Qt
: Qnil
;
577 Vlibrary_cache
= Fcons (Fcons (Qjson
, status
), Vlibrary_cache
);
579 if (!json_initialized
)
581 message1 ("jansson library not found");
586 json_t
*json
= lisp_to_json (object
);
587 record_unwind_protect_ptr (json_release_object
, json
);
589 struct json_insert_data data
;
590 /* If desired, we might want to add the following flags:
591 JSON_DECODE_ANY, JSON_ALLOW_NUL. */
593 = json_dump_callback (json
, json_insert_callback
, &data
, JSON_COMPACT
);
596 if (CONSP (data
.error
))
597 xsignal (XCAR (data
.error
), XCDR (data
.error
));
599 json_out_of_memory ();
602 return unbind_to (count
, Qnil
);
605 enum json_object_type
{
606 json_object_hashtable
,
610 /* Convert a JSON object to a Lisp object. */
612 static _GL_ARG_NONNULL ((1)) Lisp_Object
613 json_to_lisp (json_t
*json
, enum json_object_type object_type
)
615 switch (json_typeof (json
))
624 /* Return an integer if possible, a floating-point number
625 otherwise. This loses precision for integers with large
626 magnitude; however, such integers tend to be nonportable
627 anyway because many JSON implementations use only 64-bit
628 floating-point numbers with 53 mantissa bits. See
629 https://tools.ietf.org/html/rfc7159#section-6 for some
631 return make_fixnum_or_float (json_integer_value (json
));
633 return make_float (json_real_value (json
));
635 return json_make_string (json_string_value (json
),
636 json_string_length (json
));
639 if (++lisp_eval_depth
> max_lisp_eval_depth
)
640 xsignal0 (Qjson_object_too_deep
);
641 size_t size
= json_array_size (json
);
642 if (FIXNUM_OVERFLOW_P (size
))
643 xsignal0 (Qoverflow_error
);
644 Lisp_Object result
= Fmake_vector (make_natnum (size
), Qunbound
);
645 for (ptrdiff_t i
= 0; i
< size
; ++i
)
647 json_to_lisp (json_array_get (json
, i
), object_type
));
653 if (++lisp_eval_depth
> max_lisp_eval_depth
)
654 xsignal0 (Qjson_object_too_deep
);
658 case json_object_hashtable
:
660 size_t size
= json_object_size (json
);
661 if (FIXNUM_OVERFLOW_P (size
))
662 xsignal0 (Qoverflow_error
);
663 result
= CALLN (Fmake_hash_table
, QCtest
, Qequal
, QCsize
,
665 struct Lisp_Hash_Table
*h
= XHASH_TABLE (result
);
668 json_object_foreach (json
, key_str
, value
)
670 Lisp_Object key
= json_build_string (key_str
);
672 ptrdiff_t i
= hash_lookup (h
, key
, &hash
);
673 /* Keys in JSON objects are unique, so the key can't
676 hash_put (h
, key
, json_to_lisp (value
, object_type
), hash
);
680 case json_object_alist
:
685 json_object_foreach (json
, key_str
, value
)
687 Lisp_Object key
= Fintern (json_build_string (key_str
), Qnil
);
689 = Fcons (Fcons (key
, json_to_lisp (value
, object_type
)),
692 result
= Fnreverse (result
);
696 /* Can't get here. */
703 /* Can't get here. */
707 static enum json_object_type
708 json_parse_object_type (ptrdiff_t nargs
, Lisp_Object
*args
)
713 return json_object_hashtable
;
716 Lisp_Object key
= args
[0];
717 Lisp_Object value
= args
[1];
718 if (!EQ (key
, QCobject_type
))
719 wrong_choice (list1 (QCobject_type
), key
);
720 if (EQ (value
, Qhash_table
))
721 return json_object_hashtable
;
722 else if (EQ (value
, Qalist
))
723 return json_object_alist
;
725 wrong_choice (list2 (Qhash_table
, Qalist
), value
);
728 wrong_type_argument (Qplistp
, Flist (nargs
, args
));
732 DEFUN ("json-parse-string", Fjson_parse_string
, Sjson_parse_string
, 1, MANY
,
734 doc
: /* Parse the JSON STRING into a Lisp object.
735 This is essentially the reverse operation of `json-serialize', which
736 see. The returned object will be a vector, hashtable, or alist. Its
737 elements will be `:null', `:false', t, numbers, strings, or further
738 vectors, hashtables, and alists. If there are duplicate keys in an
739 object, all but the last one are ignored. If STRING doesn't contain a
740 valid JSON object, an error of type `json-parse-error' is signaled.
741 The keyword argument `:object-type' specifies which Lisp type is used
742 to represent objects; it can be `hash-table' or `alist'.
743 usage: (json-parse-string STRING &key (OBJECT-TYPE \\='hash-table)) */)
744 (ptrdiff_t nargs
, Lisp_Object
*args
)
746 ptrdiff_t count
= SPECPDL_INDEX ();
749 if (!json_initialized
)
752 json_initialized
= init_json_functions ();
753 status
= json_initialized
? Qt
: Qnil
;
754 Vlibrary_cache
= Fcons (Fcons (Qjson
, status
), Vlibrary_cache
);
756 if (!json_initialized
)
758 message1 ("jansson library not found");
763 Lisp_Object string
= args
[0];
764 Lisp_Object encoded
= json_encode (string
);
765 check_string_without_embedded_nulls (encoded
);
766 enum json_object_type object_type
767 = json_parse_object_type (nargs
- 1, args
+ 1);
770 json_t
*object
= json_loads (SSDATA (encoded
), 0, &error
);
772 json_parse_error (&error
);
774 /* Avoid leaking the object in case of further errors. */
776 record_unwind_protect_ptr (json_release_object
, object
);
778 return unbind_to (count
, json_to_lisp (object
, object_type
));
781 struct json_read_buffer_data
783 /* Byte position of position to read the next chunk from. */
787 /* Callback for json_load_callback that reads from the current buffer.
788 DATA must point to a structure of type json_read_buffer_data.
789 data->point must point to the byte position to read from; after
790 reading, data->point is advanced accordingly. The buffer point
791 itself is ignored. This function may not exit nonlocally. */
794 json_read_buffer_callback (void *buffer
, size_t buflen
, void *data
)
796 struct json_read_buffer_data
*d
= data
;
798 /* First, parse from point to the gap or the end of the accessible
799 portion, whatever is closer. */
800 ptrdiff_t point
= d
->point
;
801 ptrdiff_t end
= BUFFER_CEILING_OF (point
) + 1;
802 ptrdiff_t count
= end
- point
;
805 memcpy (buffer
, BYTE_POS_ADDR (point
), count
);
810 DEFUN ("json-parse-buffer", Fjson_parse_buffer
, Sjson_parse_buffer
,
812 doc
: /* Read JSON object from current buffer starting at point.
813 This is similar to `json-parse-string', which see. Move point after
814 the end of the object if parsing was successful. On error, point is
816 usage: (json-parse-buffer &key (OBJECT-TYPE \\='hash-table)) */)
817 (ptrdiff_t nargs
, Lisp_Object
*args
)
819 ptrdiff_t count
= SPECPDL_INDEX ();
822 if (!json_initialized
)
825 json_initialized
= init_json_functions ();
826 status
= json_initialized
? Qt
: Qnil
;
827 Vlibrary_cache
= Fcons (Fcons (Qjson
, status
), Vlibrary_cache
);
829 if (!json_initialized
)
831 message1 ("jansson library not found");
836 enum json_object_type object_type
= json_parse_object_type (nargs
, args
);
838 ptrdiff_t point
= PT_BYTE
;
839 struct json_read_buffer_data data
= {.point
= point
};
841 json_t
*object
= json_load_callback (json_read_buffer_callback
, &data
,
842 JSON_DISABLE_EOF_CHECK
, &error
);
845 json_parse_error (&error
);
847 /* Avoid leaking the object in case of further errors. */
848 record_unwind_protect_ptr (json_release_object
, object
);
850 /* Convert and then move point only if everything succeeded. */
851 Lisp_Object lisp
= json_to_lisp (object
, object_type
);
853 /* Adjust point by how much we just read. */
854 point
+= error
.position
;
855 SET_PT_BOTH (BYTE_TO_CHAR (point
), point
);
857 return unbind_to (count
, lisp
);
860 /* Simplified version of 'define-error' that works with pure
864 define_error (Lisp_Object name
, const char *message
, Lisp_Object parent
)
866 eassert (SYMBOLP (name
));
867 eassert (SYMBOLP (parent
));
868 Lisp_Object parent_conditions
= Fget (parent
, Qerror_conditions
);
869 eassert (CONSP (parent_conditions
));
870 eassert (!NILP (Fmemq (parent
, parent_conditions
)));
871 eassert (NILP (Fmemq (name
, parent_conditions
)));
872 Fput (name
, Qerror_conditions
, pure_cons (name
, parent_conditions
));
873 Fput (name
, Qerror_message
, build_pure_c_string (message
));
879 DEFSYM (QCnull
, ":null");
880 DEFSYM (QCfalse
, ":false");
882 DEFSYM (Qstring_without_embedded_nulls_p
, "string-without-embedded-nulls-p");
883 DEFSYM (Qjson_value_p
, "json-value-p");
884 DEFSYM (Qutf_8_string_p
, "utf-8-string-p");
886 DEFSYM (Qjson_error
, "json-error");
887 DEFSYM (Qjson_out_of_memory
, "json-out-of-memory");
888 DEFSYM (Qjson_parse_error
, "json-parse-error");
889 DEFSYM (Qjson_end_of_file
, "json-end-of-file");
890 DEFSYM (Qjson_trailing_content
, "json-trailing-content");
891 DEFSYM (Qjson_object_too_deep
, "json-object-too-deep");
892 define_error (Qjson_error
, "generic JSON error", Qerror
);
893 define_error (Qjson_out_of_memory
,
894 "not enough memory for creating JSON object", Qjson_error
);
895 define_error (Qjson_parse_error
, "could not parse JSON stream",
897 define_error (Qjson_end_of_file
, "end of JSON stream", Qjson_parse_error
);
898 define_error (Qjson_trailing_content
, "trailing content after JSON stream",
900 define_error (Qjson_object_too_deep
,
901 "object cyclic or Lisp evaluation too deep", Qjson_error
);
903 DEFSYM (Qpure
, "pure");
904 DEFSYM (Qside_effect_free
, "side-effect-free");
906 DEFSYM (Qjson_serialize
, "json-serialize");
907 DEFSYM (Qjson_parse_string
, "json-parse-string");
908 Fput (Qjson_serialize
, Qpure
, Qt
);
909 Fput (Qjson_serialize
, Qside_effect_free
, Qt
);
910 Fput (Qjson_parse_string
, Qpure
, Qt
);
911 Fput (Qjson_parse_string
, Qside_effect_free
, Qt
);
913 DEFSYM (QCobject_type
, ":object-type");
914 DEFSYM (Qalist
, "alist");
916 defsubr (&Sjson_serialize
);
917 defsubr (&Sjson_insert
);
918 defsubr (&Sjson_parse_string
);
919 defsubr (&Sjson_parse_buffer
);