Function: json-insert
json-insert is a function defined in json.c.
Signature
(json-insert OBJECT &rest ARGS)
Documentation
Insert the JSON representation of OBJECT before point.
This is the same as (insert (json-serialize OBJECT)), but potentially
faster. See the function json-serialize for allowed values of
OBJECT.
Probably introduced at or before Emacs version 27.1.
Source Code
// Defined in /usr/src/emacs/src/json.c
{
ptrdiff_t count = SPECPDL_INDEX ();
#ifdef WINDOWSNT
if (!json_initialized)
{
Lisp_Object status;
json_initialized = init_json_functions ();
status = json_initialized ? Qt : Qnil;
Vlibrary_cache = Fcons (Fcons (Qjson, status), Vlibrary_cache);
}
if (!json_initialized)
Fsignal (Qjson_unavailable,
list1 (build_unibyte_string ("jansson library not found")));
#endif
struct json_configuration conf =
{json_object_hashtable, json_array_array, QCnull, QCfalse};
json_parse_args (nargs - 1, args + 1, &conf, false);
json_t *json = lisp_to_json (args[0], &conf);
record_unwind_protect_ptr (json_release_object, json);
prepare_to_modify_buffer (PT, PT, NULL);
move_gap_both (PT, PT_BYTE);
struct json_insert_data data;
data.inserted_bytes = 0;
/* Could have used json_dumpb, but that became available only in
Jansson 2.10, whereas we want to support 2.7 and upward. */
int status = json_dump_callback (json, json_insert_callback, &data,
JSON_COMPACT | JSON_ENCODE_ANY);
if (status == -1)
{
if (CONSP (data.error))
xsignal (XCAR (data.error), XCDR (data.error));
else
json_out_of_memory ();
}
ptrdiff_t inserted = 0;
ptrdiff_t inserted_bytes = data.inserted_bytes;
if (inserted_bytes > 0)
{
/* If required, decode the stuff we've read into the gap. */
struct coding_system coding;
/* JSON strings are UTF-8 encoded strings. If for some reason
the text returned by the Jansson library includes invalid
byte sequences, they will be represented by raw bytes in the
buffer text. */
setup_coding_system (Qutf_8_unix, &coding);
coding.dst_multibyte =
!NILP (BVAR (current_buffer, enable_multibyte_characters));
if (CODING_MAY_REQUIRE_DECODING (&coding))
{
/* Now we have all the new bytes at the beginning of the gap,
but `decode_coding_gap` needs them at the end of the gap, so
we need to move them. */
memmove (GAP_END_ADDR - inserted_bytes, GPT_ADDR, inserted_bytes);
decode_coding_gap (&coding, inserted_bytes);
inserted = coding.produced_char;
}
else
{
/* Make the inserted text part of the buffer, as unibyte text. */
eassert (NILP (BVAR (current_buffer, enable_multibyte_characters)));
insert_from_gap_1 (inserted_bytes, inserted_bytes, false);
/* The target buffer is unibyte, so we don't need to decode. */
invalidate_buffer_caches (current_buffer,
PT, PT + inserted_bytes);
adjust_after_insert (PT, PT_BYTE,
PT + inserted_bytes,
PT_BYTE + inserted_bytes,
inserted_bytes);
inserted = inserted_bytes;
}
}
/* Call after-change hooks. */
signal_after_change (PT, 0, inserted);
if (inserted > 0)
{
update_compositions (PT, PT, CHECK_BORDER);
/* Move point to after the inserted text. */
SET_PT_BOTH (PT + inserted, PT_BYTE + inserted_bytes);
}
return unbind_to (count, Qnil);
}