From unknown Sun Jun 15 14:44:57 2025 X-Loop: help-debbugs@gnu.org Subject: bug#70007: [PATCH] native JSON encoder Resent-From: Mattias =?UTF-8?Q?Engdeg=C3=A5rd?= Original-Sender: "Debbugs-submit" Resent-CC: bug-gnu-emacs@gnu.org Resent-Date: Tue, 26 Mar 2024 15:35:01 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: report 70007 X-GNU-PR-Package: emacs X-GNU-PR-Keywords: patch To: 70007@debbugs.gnu.org X-Debbugs-Original-To: Emacs Bug Report Received: via spool by submit@debbugs.gnu.org id=B.17114672728219 (code B ref -1); Tue, 26 Mar 2024 15:35:01 +0000 Received: (at submit) by debbugs.gnu.org; 26 Mar 2024 15:34:32 +0000 Received: from localhost ([127.0.0.1]:34488 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1rp8op-00028V-Kg for submit@debbugs.gnu.org; Tue, 26 Mar 2024 11:34:31 -0400 Received: from lists.gnu.org ([2001:470:142::17]:35458) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1rp8on-00027b-9P for submit@debbugs.gnu.org; Tue, 26 Mar 2024 11:34:30 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1rp8oQ-0000yM-Ok for bug-gnu-emacs@gnu.org; Tue, 26 Mar 2024 11:34:08 -0400 Received: from mail-lj1-x22f.google.com ([2a00:1450:4864:20::22f]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1rp8oI-0006Il-4c for bug-gnu-emacs@gnu.org; Tue, 26 Mar 2024 11:34:01 -0400 Received: by mail-lj1-x22f.google.com with SMTP id 38308e7fff4ca-2d6ee81bc87so6440421fa.1 for ; Tue, 26 Mar 2024 08:33:56 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1711467234; x=1712072034; darn=gnu.org; h=to:date:message-id:subject:mime-version:from:sender:from:to:cc :subject:date:message-id:reply-to; bh=QRkLtcr+EgvnDYUk8l8Y21pG2S4sv24IUJFjQ7aUOys=; b=I3DD68b7I1GN8VSiwVp/4f/htxSRUHYUh6R768JkjAk5h9yhUOeJS3rfY6XC8uwVOb 7ozZaq2LC0+rYu7IcC5HhBkvvDohXv2/GFWeIxQ4p38g6cP0XRrWH0yqMbgqYjii6sCU v35oKjLD/jvPCxMp7SB9iV6o/eh2YTQfZxhLDt6ce/D1g87Q7ut1JoDa6z19+rWmRouR zvI4IrVZoKVqg+UpAMQhtQubys28L36mOoWIrw6D9Hx4Puokkvyr4iC6tIvtdjmYME8G /dt0Bqj3aqs+b/04toYscsSNI+7ePP5GE9VMDA87vSdJ9qJVeFJXy48qDPQBpCWRu9rx f9Rw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1711467234; x=1712072034; h=to:date:message-id:subject:mime-version:from:sender :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=QRkLtcr+EgvnDYUk8l8Y21pG2S4sv24IUJFjQ7aUOys=; b=Bn4I3GE5tEYUTcdfzgoChydTfc/aCKRAKsSdLe7Xdnbb36olv8v6GzD+EBvb8bIs5x vjBy5lEMckGeNpcq3rtsmJOvbZNmf91UbZG1bFOFA6xrri7gwizzv3sDe54PAPifBGBV 6L+YMVdTVCEeDHEOiR6/svwsvx+083snGNumruOTQ8m0JBgyQ4EOU10MoSJbYSq0/rc6 XlTrQiZ5Dl+Br1LZP/HsB0LafKpBamjjunSNb+QaRLw9BUSE71lxLlDB0yZVUzEqIPs7 ftJdhByL9XM5YgSl7SNFK95us+2IgvjE5Zz6C7XNXtDFbeBrJyhlkO3pcP2l3K+O4R8W 4QsQ== X-Gm-Message-State: AOJu0Yy060FSRlFbqS6eWmodcq6yaZ3iKizLgnISzAp7UCfupocvyNzy 6npo9rHdedbxlKiFSOtUjcn+ZTSUTc+/uL3DIedtmFXxATRdP7EGO2hXoN6H X-Google-Smtp-Source: AGHT+IEMmzZ3k0v2q3GovR/BVORH7TWPmui9//TuSSYNrk4ZKuC92QC5RmSg54I3jkfo1c7vKVWC2w== X-Received: by 2002:a2e:960b:0:b0:2d4:6786:e8 with SMTP id v11-20020a2e960b000000b002d4678600e8mr6276025ljh.12.1711467233471; Tue, 26 Mar 2024 08:33:53 -0700 (PDT) Received: from smtpclient.apple (c80-217-1-132.bredband.tele2.se. [80.217.1.132]) by smtp.gmail.com with ESMTPSA id q126-20020a2e2a84000000b002d4764f825fsm1737761ljq.63.2024.03.26.08.33.52 for (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Tue, 26 Mar 2024 08:33:53 -0700 (PDT) From: Mattias =?UTF-8?Q?Engdeg=C3=A5rd?= Content-Type: multipart/mixed; boundary="Apple-Mail=_7330F7C9-D7F2-4246-9F8E-A734AAA47A92" Mime-Version: 1.0 (Mac OS X Mail 14.0 \(3654.120.0.1.15\)) Message-Id: <1BF559D1-DB9F-4FEB-90ED-72E0EFD76424@gmail.com> Date: Tue, 26 Mar 2024 16:33:52 +0100 X-Mailer: Apple Mail (2.3654.120.0.1.15) Received-SPF: pass client-ip=2a00:1450:4864:20::22f; envelope-from=mattias.engdegard@gmail.com; helo=mail-lj1-x22f.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-Spam-Score: 1.0 (+) X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -0.0 (/) --Apple-Mail=_7330F7C9-D7F2-4246-9F8E-A734AAA47A92 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset=us-ascii If we replace the lisp-to-JSON encoder with native code, we would not = need the jansson library for it and it would be faster. There is ongoing work on a JSON-to-lisp parser, but the author has made = it clear that he does not have time to write an encoder, so I spent a = morning mashing up the attached patch. It generally produces the same result as the old code, except: - The old code incorrectly accepted strings with non-Unicode characters = (raw bytes). There is no reason to do this; JSON is UTF-8 only. - The old code spent a lot of time ensuring that object keys were = unique. The new code doesn't: it's a garbage-in garbage-out type of = situation. The new code could do with some optimisation but it's already about = twice as fast as the old code, sometimes more. I'd be very happy if someone could test it with packages that use this = interface (json-serialise, json-insert). --Apple-Mail=_7330F7C9-D7F2-4246-9F8E-A734AAA47A92 Content-Disposition: attachment; filename=json-serialise.diff Content-Type: application/octet-stream; x-unix-mode=0644; name="json-serialise.diff" Content-Transfer-Encoding: quoted-printable diff=20--git=20a/src/json.c=20b/src/json.c=0Aindex=20= e849ccaf722..7fbe700e07c=20100644=0A---=20a/src/json.c=0A+++=20= b/src/json.c=0A@@=20-23,6=20+23,7=20@@=20Copyright=20(C)=202017-2024=20= Free=20Software=20Foundation,=20Inc.=0A=20#include=20=0A=20= #include=20=0A=20#include=20=0A+#include=20=0A= =20=0A=20#include=20=0A=20=0A@@=20-231,12=20+232,6=20@@=20= json_encode=20(Lisp_Object=20string)=0A=20=20=20return=20= encode_string_utf_8=20(string,=20Qnil,=20false,=20Qt,=20Qt);=0A=20}=0A=20= =0A-static=20AVOID=0A-json_out_of_memory=20(void)=0A-{=0A-=20=20xsignal0=20= (Qjson_out_of_memory);=0A-}=0A-=0A=20/*=20Signal=20a=20Lisp=20error=20= corresponding=20to=20the=20JSON=20ERROR.=20=20*/=0A=20=0A=20static=20= AVOID=0A@@=20-289,26=20+284,6=20@@=20check_string_without_embedded_nulls=20= (Lisp_Object=20object)=0A=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= Qstring_without_embedded_nulls_p,=20object);=0A=20}=0A=20=0A-/*=20Signal=20= an=20error=20of=20type=20`json-out-of-memory'=20if=20OBJECT=20is=0A-=20=20= =20NULL.=20=20*/=0A-=0A-static=20json_t=20*=0A-json_check=20(json_t=20= *object)=0A-{=0A-=20=20if=20(object=20=3D=3D=20NULL)=0A-=20=20=20=20= json_out_of_memory=20();=0A-=20=20return=20object;=0A-}=0A-=0A-/*=20If=20= STRING=20is=20not=20a=20valid=20UTF-8=20string,=20signal=20an=20error=20= of=20type=0A-=20=20=20`wrong-type-argument'.=20=20STRING=20must=20be=20a=20= unibyte=20string.=20=20*/=0A-=0A-static=20void=0A-json_check_utf8=20= (Lisp_Object=20string)=0A-{=0A-=20=20CHECK_TYPE=20(utf8_string_p=20= (string),=20Qutf_8_string_p,=20string);=0A-}=0A-=0A=20enum=20= json_object_type=20{=0A=20=20=20json_object_hashtable,=0A=20=20=20= json_object_alist,=0A@@=20-327,179=20+302,6=20@@=20json_check_utf8=20= (Lisp_Object=20string)=0A=20=20=20Lisp_Object=20false_object;=0A=20};=0A=20= =0A-static=20json_t=20*lisp_to_json=20(Lisp_Object,=0A-=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= const=20struct=20json_configuration=20*conf);=0A-=0A-/*=20Convert=20a=20= Lisp=20object=20to=20a=20nonscalar=20JSON=20object=20(array=20or=20= object).=20=20*/=0A-=0A-static=20json_t=20*=0A-lisp_to_json_nonscalar_1=20= (Lisp_Object=20lisp,=0A-=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20const=20struct=20json_configuration=20*conf)=0A= -{=0A-=20=20json_t=20*json;=0A-=20=20specpdl_ref=20count;=0A-=0A-=20=20= if=20(VECTORP=20(lisp))=0A-=20=20=20=20{=0A-=20=20=20=20=20=20ptrdiff_t=20= size=20=3D=20ASIZE=20(lisp);=0A-=20=20=20=20=20=20json=20=3D=20= json_check=20(json_array=20());=0A-=20=20=20=20=20=20count=20=3D=20= SPECPDL_INDEX=20();=0A-=20=20=20=20=20=20record_unwind_protect_ptr=20= (json_release_object,=20json);=0A-=20=20=20=20=20=20for=20(ptrdiff_t=20i=20= =3D=200;=20i=20<=20size;=20++i)=0A-=20=20=20=20=20=20=20=20{=0A-=20=20=20= =20=20=20=20=20=20=20int=20status=0A-=20=20=20=20=20=20=20=20=20=20=20=20= =3D=20json_array_append_new=20(json,=20lisp_to_json=20(AREF=20(lisp,=20= i),=0A-=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20conf));=0A-=20=20=20=20=20=20=20=20=20=20= if=20(status=20=3D=3D=20-1)=0A-=20=20=20=20=20=20=20=20=20=20=20=20= json_out_of_memory=20();=0A-=20=20=20=20=20=20=20=20}=0A-=20=20=20=20=20=20= eassert=20(json_array_size=20(json)=20=3D=3D=20size);=0A-=20=20=20=20}=0A= -=20=20else=20if=20(HASH_TABLE_P=20(lisp))=0A-=20=20=20=20{=0A-=20=20=20=20= =20=20struct=20Lisp_Hash_Table=20*h=20=3D=20XHASH_TABLE=20(lisp);=0A-=20=20= =20=20=20=20json=20=3D=20json_check=20(json_object=20());=0A-=20=20=20=20= =20=20count=20=3D=20SPECPDL_INDEX=20();=0A-=20=20=20=20=20=20= record_unwind_protect_ptr=20(json_release_object,=20json);=0A-=20=20=20=20= =20=20DOHASH=20(h,=20key,=20v)=0A-=20=20=20=20=20=20=20=20{=0A-=09=20=20= CHECK_STRING=20(key);=0A-=09=20=20Lisp_Object=20ekey=20=3D=20json_encode=20= (key);=0A-=09=20=20/*=20We=20can't=20specify=20the=20length,=20so=20the=20= string=20must=20be=0A-=09=20=20=20=20=20null-terminated.=20=20*/=0A-=09=20= =20check_string_without_embedded_nulls=20(ekey);=0A-=09=20=20const=20= char=20*key_str=20=3D=20SSDATA=20(ekey);=0A-=09=20=20/*=20Reject=20= duplicate=20keys.=20=20These=20are=20possible=20if=20the=20hash=0A-=09=20= =20=20=20=20table=20test=20is=20not=20`equal'.=20=20*/=0A-=09=20=20if=20= (json_object_get=20(json,=20key_str)=20!=3D=20NULL)=0A-=09=20=20=20=20= wrong_type_argument=20(Qjson_value_p,=20lisp);=0A-=09=20=20int=20status=0A= -=09=20=20=20=20=3D=20json_object_set_new=20(json,=20key_str,=0A-=09=09=09= =09=20=20=20lisp_to_json=20(v,=20conf));=0A-=09=20=20if=20(status=20=3D=3D= =20-1)=0A-=09=20=20=20=20{=0A-=09=20=20=20=20=20=20/*=20A=20failure=20= can=20be=20caused=20either=20by=20an=20invalid=20key=20or=0A-=09=09=20by=20= low=20memory.=20=20*/=0A-=09=20=20=20=20=20=20json_check_utf8=20(ekey);=0A= -=09=20=20=20=20=20=20json_out_of_memory=20();=0A-=09=20=20=20=20}=0A-=09= }=0A-=20=20=20=20}=0A-=20=20else=20if=20(NILP=20(lisp))=0A-=20=20=20=20= return=20json_check=20(json_object=20());=0A-=20=20else=20if=20(CONSP=20= (lisp))=0A-=20=20=20=20{=0A-=20=20=20=20=20=20Lisp_Object=20tail=20=3D=20= lisp;=0A-=20=20=20=20=20=20json=20=3D=20json_check=20(json_object=20());=0A= -=20=20=20=20=20=20count=20=3D=20SPECPDL_INDEX=20();=0A-=20=20=20=20=20=20= record_unwind_protect_ptr=20(json_release_object,=20json);=0A-=20=20=20=20= =20=20bool=20is_plist=20=3D=20!CONSP=20(XCAR=20(tail));=0A-=20=20=20=20=20= =20FOR_EACH_TAIL=20(tail)=0A-=20=20=20=20=20=20=20=20{=0A-=20=20=20=20=20= =20=20=20=20=20const=20char=20*key_str;=0A-=20=20=20=20=20=20=20=20=20=20= Lisp_Object=20value;=0A-=20=20=20=20=20=20=20=20=20=20Lisp_Object=20= key_symbol;=0A-=20=20=20=20=20=20=20=20=20=20if=20(is_plist)=0A-=20=20=20= =20=20=20=20=20=20=20=20=20{=0A-=20=20=20=20=20=20=20=20=20=20=20=20=20=20= key_symbol=20=3D=20XCAR=20(tail);=0A-=20=20=20=20=20=20=20=20=20=20=20=20= =20=20tail=20=3D=20XCDR=20(tail);=0A-=20=20=20=20=20=20=20=20=20=20=20=20= =20=20CHECK_CONS=20(tail);=0A-=20=20=20=20=20=20=20=20=20=20=20=20=20=20= value=20=3D=20XCAR=20(tail);=0A-=20=20=20=20=20=20=20=20=20=20=20=20}=0A= -=20=20=20=20=20=20=20=20=20=20else=0A-=20=20=20=20=20=20=20=20=20=20=20=20= {=0A-=20=20=20=20=20=20=20=20=20=20=20=20=20=20Lisp_Object=20pair=20=3D=20= XCAR=20(tail);=0A-=20=20=20=20=20=20=20=20=20=20=20=20=20=20CHECK_CONS=20= (pair);=0A-=20=20=20=20=20=20=20=20=20=20=20=20=20=20key_symbol=20=3D=20= XCAR=20(pair);=0A-=20=20=20=20=20=20=20=20=20=20=20=20=20=20value=20=3D=20= XCDR=20(pair);=0A-=20=20=20=20=20=20=20=20=20=20=20=20}=0A-=20=20=20=20=20= =20=20=20=20=20CHECK_SYMBOL=20(key_symbol);=0A-=20=20=20=20=20=20=20=20=20= =20Lisp_Object=20key=20=3D=20SYMBOL_NAME=20(key_symbol);=0A-=20=20=20=20=20= =20=20=20=20=20/*=20We=20can't=20specify=20the=20length,=20so=20the=20= string=20must=20be=0A-=20=20=20=20=20=20=20=20=20=20=20=20=20= null-terminated.=20=20*/=0A-=20=20=20=20=20=20=20=20=20=20= check_string_without_embedded_nulls=20(key);=0A-=20=20=20=20=20=20=20=20=20= =20key_str=20=3D=20SSDATA=20(key);=0A-=20=20=20=20=20=20=20=20=20=20/*=20= In=20plists,=20ensure=20leading=20":"=20in=20keys=20is=20stripped.=20=20= It=0A-=20=20=20=20=20=20=20=20=20=20=20=20=20will=20be=20reconstructed=20= later=20in=20`json_to_lisp'.*/=0A-=20=20=20=20=20=20=20=20=20=20if=20= (is_plist=20&&=20':'=20=3D=3D=20key_str[0]=20&&=20key_str[1])=0A-=20=20=20= =20=20=20=20=20=20=20=20=20{=0A-=20=20=20=20=20=20=20=20=20=20=20=20=20=20= key_str=20=3D=20&key_str[1];=0A-=20=20=20=20=20=20=20=20=20=20=20=20}=0A= -=20=20=20=20=20=20=20=20=20=20/*=20Only=20add=20element=20if=20key=20is=20= not=20already=20present.=20=20*/=0A-=20=20=20=20=20=20=20=20=20=20if=20= (json_object_get=20(json,=20key_str)=20=3D=3D=20NULL)=0A-=20=20=20=20=20=20= =20=20=20=20=20=20{=0A-=20=20=20=20=20=20=20=20=20=20=20=20=20=20int=20= status=0A-=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=3D=20= json_object_set_new=20(json,=20key_str,=20lisp_to_json=20(value,=0A-=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20conf));=0A-=20=20=20=20=20= =20=20=20=20=20=20=20=20=20if=20(status=20=3D=3D=20-1)=0A-=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20json_out_of_memory=20();=0A-=20=20=20=20= =20=20=20=20=20=20=20=20}=0A-=20=20=20=20=20=20=20=20}=0A-=20=20=20=20=20= =20CHECK_LIST_END=20(tail,=20lisp);=0A-=20=20=20=20}=0A-=20=20else=0A-=20= =20=20=20wrong_type_argument=20(Qjson_value_p,=20lisp);=0A-=0A-=20=20= clear_unwind_protect=20(count);=0A-=20=20unbind_to=20(count,=20Qnil);=0A= -=20=20return=20json;=0A-}=0A-=0A-/*=20Convert=20LISP=20to=20a=20= nonscalar=20JSON=20object=20(array=20or=20object).=20=20Signal=0A-=20=20=20= an=20error=20of=20type=20`wrong-type-argument'=20if=20LISP=20is=20not=20= a=20vector,=0A-=20=20=20hashtable,=20alist,=20or=20plist.=20=20*/=0A-=0A= -static=20json_t=20*=0A-lisp_to_json_nonscalar=20(Lisp_Object=20lisp,=0A= -=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= const=20struct=20json_configuration=20*conf)=0A-{=0A-=20=20if=20= (++lisp_eval_depth=20>=20max_lisp_eval_depth)=0A-=20=20=20=20xsignal0=20= (Qjson_object_too_deep);=0A-=20=20json_t=20*json=20=3D=20= lisp_to_json_nonscalar_1=20(lisp,=20conf);=0A-=20=20--lisp_eval_depth;=0A= -=20=20return=20json;=0A-}=0A-=0A-/*=20Convert=20LISP=20to=20any=20JSON=20= object.=20=20Signal=20an=20error=20of=20type=0A-=20=20=20= `wrong-type-argument'=20if=20the=20type=20of=20LISP=20can't=20be=20= converted=20to=20a=0A-=20=20=20JSON=20object.=20=20*/=0A-=0A-static=20= json_t=20*=0A-lisp_to_json=20(Lisp_Object=20lisp,=20const=20struct=20= json_configuration=20*conf)=0A-{=0A-=20=20if=20(EQ=20(lisp,=20= conf->null_object))=0A-=20=20=20=20return=20json_check=20(json_null=20= ());=0A-=20=20else=20if=20(EQ=20(lisp,=20conf->false_object))=0A-=20=20=20= =20return=20json_check=20(json_false=20());=0A-=20=20else=20if=20(EQ=20= (lisp,=20Qt))=0A-=20=20=20=20return=20json_check=20(json_true=20());=0A-=20= =20else=20if=20(INTEGERP=20(lisp))=0A-=20=20=20=20{=0A-=20=20=20=20=20=20= intmax_t=20low=20=3D=20TYPE_MINIMUM=20(json_int_t);=0A-=20=20=20=20=20=20= intmax_t=20high=20=3D=20TYPE_MAXIMUM=20(json_int_t);=0A-=20=20=20=20=20=20= intmax_t=20value=20=3D=20check_integer_range=20(lisp,=20low,=20high);=0A= -=20=20=20=20=20=20return=20json_check=20(json_integer=20(value));=0A-=20= =20=20=20}=0A-=20=20else=20if=20(FLOATP=20(lisp))=0A-=20=20=20=20return=20= json_check=20(json_real=20(XFLOAT_DATA=20(lisp)));=0A-=20=20else=20if=20= (STRINGP=20(lisp))=0A-=20=20=20=20{=0A-=20=20=20=20=20=20Lisp_Object=20= encoded=20=3D=20json_encode=20(lisp);=0A-=20=20=20=20=20=20json_t=20= *json=20=3D=20json_stringn=20(SSDATA=20(encoded),=20SBYTES=20(encoded));=0A= -=20=20=20=20=20=20if=20(json=20=3D=3D=20NULL)=0A-=20=20=20=20=20=20=20=20= {=0A-=20=20=20=20=20=20=20=20=20=20/*=20A=20failure=20can=20be=20caused=20= either=20by=20an=20invalid=20string=20or=20by=0A-=20=20=20=20=20=20=20=20= =20=20=20=20=20low=20memory.=20=20*/=0A-=20=20=20=20=20=20=20=20=20=20= json_check_utf8=20(encoded);=0A-=20=20=20=20=20=20=20=20=20=20= json_out_of_memory=20();=0A-=20=20=20=20=20=20=20=20}=0A-=20=20=20=20=20=20= return=20json;=0A-=20=20=20=20}=0A-=0A-=20=20/*=20LISP=20now=20must=20be=20= a=20vector,=20hashtable,=20alist,=20or=20plist.=20=20*/=0A-=20=20return=20= lisp_to_json_nonscalar=20(lisp,=20conf);=0A-}=0A-=0A=20static=20void=0A=20= json_parse_args=20(ptrdiff_t=20nargs,=0A=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20Lisp_Object=20*args,=0A@@=20-585,6=20+387,332=20@@=20= DEFUN=20("json--available-p",=20Fjson__available_p,=20= Sjson__available_p,=200,=200,=20NULL,=0A=20=20=20return=20= json_available_p=20()=20?=20Qt=20:=20Qnil;=0A=20}=0A=20=0A+/*=20JSON=20= encoding=20context=20*/=0A+typedef=20struct=20{=0A+=20=20char=20*buf;=0A= +=20=20ptrdiff_t=20size;=09=09/*=20number=20of=20bytes=20in=20buf=20*/=0A= +=20=20ptrdiff_t=20capacity;=09=09/*=20allocated=20size=20of=20buf=20*/=0A= +=20=20ptrdiff_t=20chars_delta;=20=20=20=20=20=20=20=20/*=20size=20-=20= {number=20of=20Unicode=20chars=20in=20buf}=20*/=0A+=0A+=20=20int=20= maxdepth;=0A+=20=20struct=20json_configuration=20conf;=0A+}=20= json_out_t;=0A+=0A+static=20NO_INLINE=20void=0A+json_out_grow=20= (json_out_t=20*jo,=20ptrdiff_t=20bytes)=0A+{=0A+=20=20ptrdiff_t=20need=20= =3D=20jo->size=20+=20bytes;=0A+=20=20ptrdiff_t=20new_size=20=3D=20max=20= (need,=20512);=0A+=20=20while=20(new_size=20<=20need)=0A+=20=20=20=20= new_size=20<<=3D=201;=0A+=20=20jo->buf=20=3D=20xrealloc=20(jo->buf,=20= new_size);=0A+=20=20jo->capacity=20=3D=20new_size;=0A+}=0A+=0A+static=20= void=0A+cleanup_json_out=20(void=20*arg)=0A+{=0A+=20=20json_out_t=20*jo=20= =3D=20arg;=0A+=20=20xfree=20(jo->buf);=0A+=20=20jo->buf=20=3D=20NULL;=0A= +}=0A+=0A+/*=20Make=20room=20for=20`bytes`=20more=20bytes=20in=20buffer.=20= =20*/=0A+static=20void=0A+json_make_room=20(json_out_t=20*jo,=20= ptrdiff_t=20bytes)=0A+{=0A+=20=20if=20(bytes=20>=20jo->capacity=20-=20= jo->size)=0A+=20=20=20=20json_out_grow=20(jo,=20bytes);=0A+}=0A+=0A= +#define=20JSON_OUT_STR(jo,=20str)=20(json_out_str=20(jo,=20str,=20= sizeof=20(str)=20-=201))=0A+=0A+/*=20Add=20`bytes`=20bytes=20from=20= `str`=20to=20the=20buffer.=20=20*/=0A+static=20void=0A+json_out_str=20= (json_out_t=20*jo,=20const=20char=20*str,=20size_t=20bytes)=0A+{=0A+=20=20= json_make_room=20(jo,=20bytes);=0A+=20=20memcpy=20(jo->buf=20+=20= jo->size,=20str,=20bytes);=0A+=20=20jo->size=20+=3D=20bytes;=0A+}=0A+=0A= +static=20void=0A+json_out_byte=20(json_out_t=20*jo,=20unsigned=20char=20= c)=0A+{=0A+=20=20json_make_room=20(jo,=201);=0A+=20=20= jo->buf[jo->size++]=20=3D=20c;=0A+}=0A+=0A+static=20void=0A= +json_out_fixnum=20(json_out_t=20*jo,=20EMACS_INT=20x)=0A+{=0A+=20=20= char=20buf[INT_BUFSIZE_BOUND=20(EMACS_INT)];=0A+=20=20char=20*end=20=3D=20= buf=20+=20sizeof=20buf;=0A+=20=20char=20*p=20=3D=20fixnum_to_string=20= (x,=20buf,=20end);=0A+=20=20json_out_str=20(jo,=20p,=20end=20-=20p);=0A= +}=0A+=0A+static=20AVOID=0A+string_not_unicode=20(Lisp_Object=20obj)=0A= +{=0A+=20=20/*=20FIXME:=20for=20test=20compatibility,=20not=20a=20very=20= descriptive=20error=20*/=0A+=20=20wrong_type_argument=20(Qjson_value_p,=20= obj);=0A+}=0A+=0A+static=20unsigned=20char=20json_plain_char[256]=20=3D=20= {=0A+=20=20/*=2032=20chars/line:=201=20for=20printable=20ASCII=20+=20DEL=20= except=20"=20and=20\,=200=20elsewhere=20*/=0A+=20=20= 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,=20/*=20= 00-1f=20*/=0A+=20=20= 1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,=20/*=20= 20-3f=20*/=0A+=20=20= 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,=20/*=20= 40-5f=20*/=0A+=20=20= 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,=20/*=20= 60-7f=20*/=0A+=20=20= 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,=20/*=20= 80-9f=20*/=0A+=20=20= 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,=20/*=20= a0-bf=20*/=0A+=20=20= 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,=20/*=20= c0-df=20*/=0A+=20=20= 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,=20/*=20= e0-ff=20*/=0A+};=0A+=0A+static=20void=0A+json_out_string=20(json_out_t=20= *jo,=20Lisp_Object=20str,=20int=20skip)=0A+{=0A+=20=20/*=20FIXME:=20this=20= code=20is=20slow,=20make=20faster!=20*/=0A+=0A+=20=20static=20const=20= char=20hexchar[16]=20=3D=20"0123456789ABCDEF";=0A+=20=20ptrdiff_t=20len=20= =3D=20SBYTES=20(str);=0A+=20=20json_make_room=20(jo,=20len=20+=202);=0A+=20= =20json_out_byte=20(jo,=20'"');=0A+=20=20unsigned=20char=20*p=20=3D=20= SDATA=20(str);=0A+=20=20unsigned=20char=20*end=20=3D=20p=20+=20len;=0A+=20= =20p=20+=3D=20skip;=0A+=20=20while=20(p=20<=20end)=0A+=20=20=20=20{=0A+=20= =20=20=20=20=20unsigned=20char=20c=20=3D=20*p;=0A+=20=20=20=20=20=20if=20= (json_plain_char[c])=0A+=09{=0A+=09=20=20json_out_byte=20(jo,=20c);=0A+=09= =20=20p++;=0A+=09}=0A+=20=20=20=20=20=20else=20if=20(c=20>=200x7f)=0A+=09= {=0A+=09=20=20if=20(STRING_MULTIBYTE=20(str))=0A+=09=20=20=20=20{=0A+=09=20= =20=20=20=20=20int=20n;=0A+=09=20=20=20=20=20=20if=20(c=20<=3D=200xc1)=0A= +=09=09string_not_unicode=20(str);=0A+=09=20=20=20=20=20=20if=20(c=20<=3D=20= 0xdf)=0A+=09=09n=20=3D=202;=0A+=09=20=20=20=20=20=20else=20if=20(c=20<=3D=20= 0xef)=0A+=09=09{=0A+=09=09=20=20int=20v=20=3D=20(((c=20&=200x0f)=20<<=20= 12)=0A+=09=09=09=20=20=20+=20((p[1]=20&=200x3f)=20<<=206)=20+=20(p[2]=20= &=200x3f));=0A+=09=09=20=20if=20(char_surrogate_p=20(v))=0A+=09=09=20=20=20= =20string_not_unicode=20(str);=0A+=09=09=20=20n=20=3D=203;=0A+=09=09}=0A= +=09=20=20=20=20=20=20else=20if=20(c=20<=3D=200xf7)=0A+=09=09{=0A+=09=09=20= =20int=20v=20=3D=20(((c=20&=200x07)=20<<=2018)=0A+=09=09=09=20=20=20+=20= ((p[1]=20&=200x3f)=20<<=2012)=0A+=09=09=09=20=20=20+=20((p[2]=20&=20= 0x3f)=20<<=206)=0A+=09=09=09=20=20=20+=20(p[3]=20&=200x3f));=0A+=09=09=20= =20if=20(v=20>=20MAX_UNICODE_CHAR)=0A+=09=09=20=20=20=20= string_not_unicode=20(str);=0A+=09=09=20=20n=20=3D=204;=0A+=09=09}=0A+=09= =20=20=20=20=20=20else=0A+=09=09string_not_unicode=20(str);=0A+=09=20=20=20= =20=20=20json_out_str=20(jo,=20(const=20char=20*)p,=20n);=0A+=09=20=20=20= =20=20=20jo->chars_delta=20+=3D=20n=20-=201;=0A+=09=20=20=20=20=20=20p=20= +=3D=20n;=0A+=09=20=20=20=20}=0A+=09=20=20else=0A+=09=20=20=20=20= string_not_unicode=20(str);=0A+=09}=0A+=20=20=20=20=20=20else=0A+=09{=0A= +=09=20=20json_out_byte=20(jo,=20'\\');=0A+=09=20=20switch=20(c)=0A+=09=20= =20=20=20{=0A+=09=20=20=20=20case=20'"':=0A+=09=20=20=20=20case=20'\\':=20= json_out_byte=20(jo,=20c);=20break;=0A+=09=20=20=20=20case=20'\b':=20= json_out_byte=20(jo,=20'b');=20break;=0A+=09=20=20=20=20case=20'\t':=20= json_out_byte=20(jo,=20't');=20break;=0A+=09=20=20=20=20case=20'\n':=20= json_out_byte=20(jo,=20'n');=20break;=0A+=09=20=20=20=20case=20'\f':=20= json_out_byte=20(jo,=20'f');=20break;=0A+=09=20=20=20=20case=20'\r':=20= json_out_byte=20(jo,=20'r');=20break;=0A+=09=20=20=20=20default:=0A+=09=20= =20=20=20=20=20{=0A+=09=09char=20hex[5]=20=3D=20{=20'u',=20'0',=20'0',=0A= +=09=09=09=09hexchar[c=20>>=204],=20hexchar[c=20&=200xf]=20};=0A+=09=09= json_out_str=20(jo,=20hex,=205);=0A+=09=09break;=0A+=09=20=20=20=20=20=20= }=0A+=09=20=20=20=20}=0A+=09=20=20p++;=0A+=09}=0A+=20=20=20=20}=0A+=20=20= json_out_byte=20(jo,=20'"');=0A+}=0A+=0A+static=20void=0A+json_out_nest=20= (json_out_t=20*jo)=0A+{=0A+=20=20--jo->maxdepth;=0A+=20=20if=20= (jo->maxdepth=20<=200)=0A+=20=20=20=20error=20("Maximum=20JSON=20= serialisation=20depth=20exceeded");=0A+}=0A+=0A+static=20void=0A= +json_out_unnest=20(json_out_t=20*jo)=0A+{=0A+=20=20++jo->maxdepth;=0A+}=0A= +=0A+static=20void=20json_out_something=20(json_out_t=20*jo,=20= Lisp_Object=20obj);=0A+=0A+static=20void=0A+json_out_object_cons=20= (json_out_t=20*jo,=20Lisp_Object=20obj)=0A+{=0A+=20=20json_out_nest=20= (jo);=0A+=20=20json_out_byte=20(jo,=20'{');=0A+=20=20bool=20is_alist=20=3D= =20CONSP=20(XCAR=20(obj));=0A+=20=20bool=20first=20=3D=20true;=0A+=20=20= Lisp_Object=20tail=20=3D=20obj;=0A+=20=20FOR_EACH_TAIL=20(tail)=0A+=20=20= =20=20{=0A+=20=20=20=20=20=20if=20(!first)=0A+=09json_out_byte=20(jo,=20= ',');=0A+=20=20=20=20=20=20first=20=3D=20false;=0A+=20=20=20=20=20=20= Lisp_Object=20key_sym;=0A+=20=20=20=20=20=20Lisp_Object=20value;=0A+=20=20= =20=20=20=20if=20(is_alist)=0A+=09{=0A+=09=20=20Lisp_Object=20pair=20=3D=20= XCAR=20(tail);=0A+=09=20=20CHECK_CONS=20(pair);=0A+=09=20=20key_sym=20=3D=20= XCAR=20(pair);=0A+=09=20=20value=20=3D=20XCDR=20(pair);=0A+=09}=0A+=20=20= =20=20=20=20else=0A+=09{=0A+=09=20=20key_sym=20=3D=20XCAR=20(tail);=0A+=09= =20=20tail=20=3D=20XCDR=20(tail);=0A+=09=20=20CHECK_CONS=20(tail);=0A+=09= =20=20value=20=3D=20XCAR=20(tail);=0A+=09}=0A+=20=20=20=20=20=20/*=20= FIXME:=20do=20we=20care=20about=20dup=20keys=20here?=20(probably=20not)=20= */=0A+=20=20=20=20=20=20CHECK_SYMBOL=20(key_sym);=0A+=20=20=20=20=20=20= Lisp_Object=20key=20=3D=20SYMBOL_NAME=20(key_sym);=0A+=20=20=20=20=20=20= const=20char=20*keystr=20=3D=20SSDATA=20(key);=0A+=20=20=20=20=20=20/*=20= Skip=20leading=20':'=20in=20plist=20keys.=20=20*/=0A+=20=20=20=20=20=20= int=20skip=20=3D=20!is_alist=20&&=20keystr[0]=20=3D=3D=20':'=20&&=20= keystr[1]=20?=201=20:=200;=0A+=20=20=20=20=20=20json_out_string=20(jo,=20= key,=20skip);=0A+=20=20=20=20=20=20json_out_byte=20(jo,=20':');=0A+=20=20= =20=20=20=20json_out_something=20(jo,=20value);=0A+=20=20=20=20}=0A+=20=20= CHECK_LIST_END=20(tail,=20obj);=0A+=20=20json_out_byte=20(jo,=20'}');=0A= +=20=20json_out_unnest=20(jo);=0A+}=0A+=0A+static=20void=0A= +json_out_object_hash=20(json_out_t=20*jo,=20Lisp_Object=20obj)=0A+{=0A+=20= =20json_out_nest=20(jo);=0A+=20=20json_out_byte=20(jo,=20'{');=0A+=20=20= struct=20Lisp_Hash_Table=20*h=20=3D=20XHASH_TABLE=20(obj);=0A+=20=20bool=20= first=20=3D=20true;=0A+=20=20DOHASH=20(h,=20k,=20v)=0A+=20=20=20=20{=0A+=20= =20=20=20=20=20if=20(!first)=0A+=09json_out_byte=20(jo,=20',');=0A+=20=20= =20=20=20=20first=20=3D=20false;=0A+=20=20=20=20=20=20/*=20FIXME:=20do=20= we=20care=20about=20dup=20keys=20here?=20(probably=20not)=20*/=0A+=20=20=20= =20=20=20CHECK_STRING=20(k);=0A+=20=20=20=20=20=20json_out_string=20(jo,=20= k,=200);=0A+=20=20=20=20=20=20json_out_byte=20(jo,=20':');=0A+=20=20=20=20= =20=20json_out_something=20(jo,=20v);=0A+=20=20=20=20}=0A+=20=20= json_out_byte=20(jo,=20'}');=0A+=20=20json_out_unnest=20(jo);=0A+=0A+}=0A= +=0A+static=20void=0A+json_out_array=20(json_out_t=20*jo,=20Lisp_Object=20= obj)=0A+{=0A+=20=20json_out_nest=20(jo);=0A+=20=20json_out_byte=20(jo,=20= '[');=0A+=20=20ptrdiff_t=20n=20=3D=20ASIZE=20(obj);=0A+=20=20for=20= (ptrdiff_t=20i=20=3D=200;=20i=20<=20n;=20i++)=0A+=20=20=20=20{=0A+=20=20=20= =20=20=20if=20(i=20>=200)=0A+=09json_out_byte=20(jo,=20',');=0A+=20=20=20= =20=20=20json_out_something=20(jo,=20AREF=20(obj,=20i));=0A+=20=20=20=20= }=0A+=20=20json_out_byte=20(jo,=20']');=0A+=20=20json_out_unnest=20(jo);=0A= +}=0A+=0A+static=20void=0A+json_out_float=20(json_out_t=20*jo,=20= Lisp_Object=20f)=0A+{=0A+=20=20double=20x=20=3D=20XFLOAT_DATA=20(f);=0A+=20= =20if=20(isinf=20(x)=20||=20isnan=20(x))=0A+=20=20=20=20signal_error=20= ("not=20a=20finite=20number",=20f);=0A+=20=20json_make_room=20(jo,=20= FLOAT_TO_STRING_BUFSIZE);=0A+=20=20int=20n=20=3D=20float_to_string=20= (jo->buf=20+=20jo->size,=20x);=0A+=20=20jo->size=20+=3D=20n;=0A+}=0A+=0A= +static=20void=0A+json_out_bignum=20(json_out_t=20*jo,=20Lisp_Object=20= x)=0A+{=0A+=20=20int=20base=20=3D=2010;=0A+=20=20ptrdiff_t=20size=20=3D=20= bignum_bufsize=20(x,=20base);=0A+=20=20json_make_room=20(jo,=20size);=0A= +=20=20int=20n=20=3D=20bignum_to_c_string=20(jo->buf=20+=20jo->size,=20= size,=20x,=20base);=0A+=20=20jo->size=20+=3D=20n;=0A+}=0A+=0A+static=20= void=0A+json_out_something=20(json_out_t=20*jo,=20Lisp_Object=20obj)=0A= +{=0A+=20=20if=20(EQ=20(obj,=20jo->conf.null_object))=0A+=20=20=20=20= JSON_OUT_STR=20(jo,=20"null");=0A+=20=20else=20if=20(EQ=20(obj,=20= jo->conf.false_object))=0A+=20=20=20=20JSON_OUT_STR=20(jo,=20"false");=0A= +=20=20else=20if=20(EQ=20(obj,=20Qt))=0A+=20=20=20=20JSON_OUT_STR=20(jo,=20= "true");=0A+=20=20else=20if=20(NILP=20(obj))=0A+=20=20=20=20JSON_OUT_STR=20= (jo,=20"{}");=0A+=20=20else=20if=20(FIXNUMP=20(obj))=0A+=20=20=20=20= json_out_fixnum=20(jo,=20XFIXNUM=20(obj));=0A+=20=20else=20if=20(STRINGP=20= (obj))=0A+=20=20=20=20json_out_string=20(jo,=20obj,=200);=0A+=20=20else=20= if=20(CONSP=20(obj))=0A+=20=20=20=20json_out_object_cons=20(jo,=20obj);=0A= +=20=20else=20if=20(FLOATP=20(obj))=0A+=20=20=20=20json_out_float=20(jo,=20= obj);=0A+=20=20else=20if=20(HASH_TABLE_P=20(obj))=0A+=20=20=20=20= json_out_object_hash=20(jo,=20obj);=0A+=20=20else=20if=20(VECTORP=20= (obj))=0A+=20=20=20=20json_out_array=20(jo,=20obj);=0A+=20=20else=20if=20= (BIGNUMP=20(obj))=0A+=20=20=20=20json_out_bignum=20(jo,=20obj);=0A+=20=20= else=0A+=20=20=20=20wrong_type_argument=20(Qjson_value_p,=20obj);=0A+}=0A= +=0A+static=20Lisp_Object=0A+json_out_string_result=20(json_out_t=20*jo)=0A= +{=0A+=20=20/*=20FIXME:=20should=20this=20be=20a=20unibyte=20or=20= multibyte=20string?=0A+=20=20=20=20=20Right=20now=20we=20make=20a=20= multibyte=20string=20for=20test=20compatibility,=0A+=20=20=20=20=20but=20= we=20are=20really=20encoding=20so=20unibyte=20would=20make=20more=20= sense.=20=20*/=0A+=20=20ptrdiff_t=20nchars=20=3D=20jo->size=20-=20= jo->chars_delta;=0A+=20=20return=20make_multibyte_string=20(jo->buf,=20= nchars,=20jo->size);=0A+}=0A+=0A+/*=20FIXME:=20update=20doc=20string=20= */=0A=20DEFUN=20("json-serialize",=20Fjson_serialize,=20Sjson_serialize,=20= 1,=20MANY,=0A=20=20=20=20=20=20=20=20NULL,=0A=20=20=20=20=20=20=20=20= doc:=20/*=20Return=20the=20JSON=20representation=20of=20OBJECT=20as=20a=20= string.=0A@@=20-614,95=20+742,17=20@@=20DEFUN=20("json-serialize",=20= Fjson_serialize,=20Sjson_serialize,=201,=20MANY,=0A=20usage:=20= (json-serialize=20OBJECT=20&rest=20ARGS)=20=20*/)=0A=20=20=20=20=20=20= (ptrdiff_t=20nargs,=20Lisp_Object=20*args)=0A=20{=0A-=20=20specpdl_ref=20= count=20=3D=20SPECPDL_INDEX=20();=0A+=20=20json_out_t=20jo=20=3D=20{=0A+=20= =20=20=20.maxdepth=20=3D=2025,=0A+=20=20=20=20.conf=20=3D=20= {json_object_hashtable,=20json_array_array,=20QCnull,=20QCfalse}=0A+=20=20= };=0A+=20=20json_parse_args=20(nargs=20-=201,=20args=20+=201,=20= &jo.conf,=20false);=0A+=20=20Lisp_Object=20object=20=3D=20args[0];=0A=20=0A= -#ifdef=20WINDOWSNT=0A-=20=20ensure_json_available=20();=0A-#endif=0A-=0A= -=20=20struct=20json_configuration=20conf=20=3D=0A-=20=20=20=20= {json_object_hashtable,=20json_array_array,=20QCnull,=20QCfalse};=0A-=20=20= json_parse_args=20(nargs=20-=201,=20args=20+=201,=20&conf,=20false);=0A-=0A= -=20=20json_t=20*json=20=3D=20lisp_to_json=20(args[0],=20&conf);=0A-=20=20= record_unwind_protect_ptr=20(json_release_object,=20json);=0A-=0A-=20=20= char=20*string=20=3D=20json_dumps=20(json,=20JSON_COMPACT=20|=20= JSON_ENCODE_ANY);=0A-=20=20if=20(string=20=3D=3D=20NULL)=0A-=20=20=20=20= json_out_of_memory=20();=0A-=20=20record_unwind_protect_ptr=20= (json_free,=20string);=0A-=0A-=20=20return=20unbind_to=20(count,=20= build_string_from_utf8=20(string));=0A-}=0A-=0A-struct=20= json_buffer_and_size=0A-{=0A-=20=20const=20char=20*buffer;=0A-=20=20= ptrdiff_t=20size;=0A-=20=20/*=20This=20tracks=20how=20many=20bytes=20= were=20inserted=20by=20the=20callback=20since=0A-=20=20=20=20=20= json_dump_callback=20was=20called.=20=20*/=0A-=20=20ptrdiff_t=20= inserted_bytes;=0A-};=0A-=0A-static=20Lisp_Object=0A-json_insert=20(void=20= *data)=0A-{=0A-=20=20struct=20json_buffer_and_size=20*buffer_and_size=20= =3D=20data;=0A-=20=20ptrdiff_t=20len=20=3D=20buffer_and_size->size;=0A-=20= =20ptrdiff_t=20inserted_bytes=20=3D=20buffer_and_size->inserted_bytes;=0A= -=20=20ptrdiff_t=20gap_size=20=3D=20GAP_SIZE=20-=20inserted_bytes;=0A-=0A= -=20=20/*=20Enlarge=20the=20gap=20if=20necessary.=20=20*/=0A-=20=20if=20= (gap_size=20<=20len)=0A-=20=20=20=20make_gap=20(len=20-=20gap_size);=0A-=0A= -=20=20/*=20Copy=20this=20chunk=20of=20data=20into=20the=20gap.=20=20*/=0A= -=20=20memcpy=20((char=20*)=20BEG_ADDR=20+=20PT_BYTE=20-=20BEG_BYTE=20+=20= inserted_bytes,=0A-=09=20=20buffer_and_size->buffer,=20len);=0A-=20=20= buffer_and_size->inserted_bytes=20+=3D=20len;=0A-=20=20return=20Qnil;=0A= -}=0A-=0A-static=20Lisp_Object=0A-json_handle_nonlocal_exit=20(enum=20= nonlocal_exit=20type,=20Lisp_Object=20data)=0A-{=0A-=20=20switch=20= (type)=0A-=20=20=20=20{=0A-=20=20=20=20case=20NONLOCAL_EXIT_SIGNAL:=0A-=20= =20=20=20=20=20return=20data;=0A-=20=20=20=20case=20NONLOCAL_EXIT_THROW:=0A= -=20=20=20=20=20=20return=20Fcons=20(Qno_catch,=20data);=0A-=20=20=20=20= default:=0A-=20=20=20=20=20=20eassume=20(false);=0A-=20=20=20=20}=0A-}=0A= -=0A-struct=20json_insert_data=0A-{=0A-=20=20/*=20This=20tracks=20how=20= many=20bytes=20were=20inserted=20by=20the=20callback=20since=0A-=20=20=20= =20=20json_dump_callback=20was=20called.=20=20*/=0A-=20=20ptrdiff_t=20= inserted_bytes;=0A-=20=20/*=20nil=20if=20json_insert=20succeeded,=20= otherwise=20the=20symbol=0A-=20=20=20=20=20Qcatch_all_memory_full=20or=20= a=20cons=20(ERROR-SYMBOL=20.=20ERROR-DATA).=20=20*/=0A-=20=20Lisp_Object=20= error;=0A-};=0A-=0A-/*=20Callback=20for=20json_dump_callback=20that=20= inserts=20a=20JSON=20representation=0A-=20=20=20as=20a=20unibyte=20= string=20into=20the=20gap.=20=20DATA=20must=20point=20to=20a=20structure=0A= -=20=20=20of=20type=20json_insert_data.=20=20This=20function=20may=20not=20= exit=20nonlocally.=0A-=20=20=20It=20catches=20all=20nonlocal=20exits=20= and=20stores=20them=20in=20data->error=20for=0A-=20=20=20reraising.=20=20= */=0A-=0A-static=20int=0A-json_insert_callback=20(const=20char=20= *buffer,=20size_t=20size,=20void=20*data)=0A-{=0A-=20=20struct=20= json_insert_data=20*d=20=3D=20data;=0A-=20=20struct=20= json_buffer_and_size=20buffer_and_size=0A-=20=20=20=20=3D=20{.buffer=20=3D= =20buffer,=20.size=20=3D=20size,=20.inserted_bytes=20=3D=20= d->inserted_bytes};=0A-=20=20d->error=20=3D=20internal_catch_all=20= (json_insert,=20&buffer_and_size,=0A-=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= json_handle_nonlocal_exit);=0A-=20=20d->inserted_bytes=20=3D=20= buffer_and_size.inserted_bytes;=0A-=20=20return=20NILP=20(d->error)=20?=20= 0=20:=20-1;=0A+=20=20specpdl_ref=20count=20=3D=20SPECPDL_INDEX=20();=0A+=20= =20record_unwind_protect_ptr=20(cleanup_json_out,=20&jo);=0A+=20=20= json_out_something=20(&jo,=20object);=0A+=20=20return=20unbind_to=20= (count,=20json_out_string_result=20(&jo));=0A=20}=0A=20=0A=20DEFUN=20= ("json-insert",=20Fjson_insert,=20Sjson_insert,=201,=20MANY,=0A@@=20= -714,72=20+764,61=20@@=20DEFUN=20("json-insert",=20Fjson_insert,=20= Sjson_insert,=201,=20MANY,=0A=20usage:=20(json-insert=20OBJECT=20&rest=20= ARGS)=20=20*/)=0A=20=20=20=20=20=20(ptrdiff_t=20nargs,=20Lisp_Object=20= *args)=0A=20{=0A-=20=20specpdl_ref=20count=20=3D=20SPECPDL_INDEX=20();=0A= +=20=20json_out_t=20jo=20=3D=20{=0A+=20=20=20=20.maxdepth=20=3D=2025,=0A= +=20=20=20=20.conf=20=3D=20{json_object_hashtable,=20json_array_array,=20= QCnull,=20QCfalse}=0A+=20=20};=0A+=20=20json_parse_args=20(nargs=20-=20= 1,=20args=20+=201,=20&jo.conf,=20false);=0A+=20=20Lisp_Object=20object=20= =3D=20args[0];=0A=20=0A-#ifdef=20WINDOWSNT=0A-=20=20= ensure_json_available=20();=0A-#endif=0A-=0A-=20=20struct=20= json_configuration=20conf=20=3D=0A-=20=20=20=20{json_object_hashtable,=20= json_array_array,=20QCnull,=20QCfalse};=0A-=20=20json_parse_args=20= (nargs=20-=201,=20args=20+=201,=20&conf,=20false);=0A+=20=20specpdl_ref=20= count=20=3D=20SPECPDL_INDEX=20();=0A+=20=20record_unwind_protect_ptr=20= (cleanup_json_out,=20&jo);=0A+=20=20json_out_something=20(&jo,=20= object);=0A=20=0A-=20=20json_t=20*json=20=3D=20lisp_to_json=20(args[0],=20= &conf);=0A-=20=20record_unwind_protect_ptr=20(json_release_object,=20= json);=0A+=20=20/*=20FIXME:=20Do=20we=20really=20need=20to=20do=20all=20= this=20work=20below=20to=20insert=20a=20string?=0A+=20=20=20=20=20Is=20= there=20no=20function=20already=20written?=20=20I=20must=20be=20missing=20= something.=20=20*/=0A=20=0A=20=20=20prepare_to_modify_buffer=20(PT,=20= PT,=20NULL);=0A=20=20=20move_gap_both=20(PT,=20PT_BYTE);=0A-=20=20struct=20= json_insert_data=20data;=0A-=20=20data.inserted_bytes=20=3D=200;=0A-=20=20= /*=20Could=20have=20used=20json_dumpb,=20but=20that=20became=20available=20= only=20in=0A-=20=20=20=20=20Jansson=202.10,=20whereas=20we=20want=20to=20= support=202.7=20and=20upward.=20=20*/=0A-=20=20int=20status=20=3D=20= json_dump_callback=20(json,=20json_insert_callback,=20&data,=0A-=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20JSON_COMPACT=20|=20JSON_ENCODE_ANY);=0A-=20=20if=20= (status=20=3D=3D=20-1)=0A-=20=20=20=20{=0A-=20=20=20=20=20=20if=20(CONSP=20= (data.error))=0A-=20=20=20=20=20=20=20=20xsignal=20(XCAR=20(data.error),=20= XCDR=20(data.error));=0A-=20=20=20=20=20=20else=0A-=20=20=20=20=20=20=20=20= json_out_of_memory=20();=0A-=20=20=20=20}=0A+=20=20if=20(GAP_SIZE=20<=20= jo.size)=0A+=20=20=20=20make_gap=20(jo.size=20-=20GAP_SIZE);=0A+=20=20= memcpy=20((char=20*)=20BEG_ADDR=20+=20PT_BYTE=20-=20BEG_BYTE,=20jo.buf,=20= jo.size);=0A+=0A+=20=20/*=20No=20need=20to=20keep=20allocation=20beyond=20= this=20point.=20=20*/=0A+=20=20unbind_to=20(count,=20Qnil);=0A=20=0A=20=20= =20ptrdiff_t=20inserted=20=3D=200;=0A-=20=20ptrdiff_t=20inserted_bytes=20= =3D=20data.inserted_bytes;=0A-=20=20if=20(inserted_bytes=20>=200)=0A+=20=20= ptrdiff_t=20inserted_bytes=20=3D=20jo.size;=0A+=0A+=20=20/*=20If=20= required,=20decode=20the=20stuff=20we've=20read=20into=20the=20gap.=20=20= */=0A+=20=20struct=20coding_system=20coding;=0A+=20=20/*=20JSON=20= strings=20are=20UTF-8=20encoded=20strings.=20=20*/=0A+=20=20= setup_coding_system=20(Qutf_8_unix,=20&coding);=0A+=20=20= coding.dst_multibyte=20=3D=20!NILP=20(BVAR=20(current_buffer,=0A+=09=09=09= =09=20=20=20=20=20=20enable_multibyte_characters));=0A+=20=20if=20= (CODING_MAY_REQUIRE_DECODING=20(&coding))=0A=20=20=20=20=20{=0A-=20=20=20= =20=20=20/*=20If=20required,=20decode=20the=20stuff=20we've=20read=20= into=20the=20gap.=20=20*/=0A-=20=20=20=20=20=20struct=20coding_system=20= coding;=0A-=20=20=20=20=20=20/*=20JSON=20strings=20are=20UTF-8=20encoded=20= strings.=20=20If=20for=20some=20reason=0A-=09=20the=20text=20returned=20= by=20the=20Jansson=20library=20includes=20invalid=0A-=09=20byte=20= sequences,=20they=20will=20be=20represented=20by=20raw=20bytes=20in=20= the=0A-=09=20buffer=20text.=20=20*/=0A-=20=20=20=20=20=20= setup_coding_system=20(Qutf_8_unix,=20&coding);=0A-=20=20=20=20=20=20= coding.dst_multibyte=20=3D=0A-=09!NILP=20(BVAR=20(current_buffer,=20= enable_multibyte_characters));=0A-=20=20=20=20=20=20if=20= (CODING_MAY_REQUIRE_DECODING=20(&coding))=0A-=09{=0A-=20=20=20=20=20=20=20= =20=20=20/*=20Now=20we=20have=20all=20the=20new=20bytes=20at=20the=20= beginning=20of=20the=20gap,=0A-=20=20=20=20=20=20=20=20=20=20=20=20=20= but=20`decode_coding_gap`=20needs=20them=20at=20the=20end=20of=20the=20= gap,=20so=0A-=20=20=20=20=20=20=20=20=20=20=20=20=20we=20need=20to=20= move=20them.=20=20*/=0A-=20=20=20=20=20=20=20=20=20=20memmove=20= (GAP_END_ADDR=20-=20inserted_bytes,=20GPT_ADDR,=20inserted_bytes);=0A-=09= =20=20decode_coding_gap=20(&coding,=20inserted_bytes);=0A-=09=20=20= inserted=20=3D=20coding.produced_char;=0A-=09}=0A-=20=20=20=20=20=20else=0A= -=09{=0A-=20=20=20=20=20=20=20=20=20=20/*=20Make=20the=20inserted=20text=20= part=20of=20the=20buffer,=20as=20unibyte=20text.=20=20*/=0A-=20=20=20=20=20= =20=20=20=20=20eassert=20(NILP=20(BVAR=20(current_buffer,=20= enable_multibyte_characters)));=0A-=20=20=20=20=20=20=20=20=20=20= insert_from_gap_1=20(inserted_bytes,=20inserted_bytes,=20false);=0A-=0A-=09= =20=20/*=20The=20target=20buffer=20is=20unibyte,=20so=20we=20don't=20= need=20to=20decode.=20=20*/=0A-=09=20=20invalidate_buffer_caches=20= (current_buffer,=0A-=09=09=09=09=20=20=20=20PT,=20PT=20+=20= inserted_bytes);=0A-=09=20=20adjust_after_insert=20(PT,=20PT_BYTE,=0A-=09= =09=09=20=20=20=20=20=20=20PT=20+=20inserted_bytes,=0A-=09=09=09=20=20=20= =20=20=20=20PT_BYTE=20+=20inserted_bytes,=0A-=09=09=09=20=20=20=20=20=20=20= inserted_bytes);=0A-=09=20=20inserted=20=3D=20inserted_bytes;=0A-=09}=0A= +=20=20=20=20=20=20/*=20Now=20we=20have=20all=20the=20new=20bytes=20at=20= the=20beginning=20of=20the=20gap,=0A+=09=20but=20`decode_coding_gap`=20= needs=20them=20at=20the=20end=20of=20the=20gap,=20so=0A+=09=20we=20need=20= to=20move=20them.=20=20*/=0A+=20=20=20=20=20=20memmove=20(GAP_END_ADDR=20= -=20inserted_bytes,=20GPT_ADDR,=20inserted_bytes);=0A+=20=20=20=20=20=20= decode_coding_gap=20(&coding,=20inserted_bytes);=0A+=20=20=20=20=20=20= inserted=20=3D=20coding.produced_char;=0A+=20=20=20=20}=0A+=20=20else=0A= +=20=20=20=20{=0A+=20=20=20=20=20=20/*=20Make=20the=20inserted=20text=20= part=20of=20the=20buffer,=20as=20unibyte=20text.=20=20*/=0A+=20=20=20=20=20= =20eassert=20(NILP=20(BVAR=20(current_buffer,=20= enable_multibyte_characters)));=0A+=20=20=20=20=20=20insert_from_gap_1=20= (inserted_bytes,=20inserted_bytes,=20false);=0A+=0A+=20=20=20=20=20=20/*=20= The=20target=20buffer=20is=20unibyte,=20so=20we=20don't=20need=20to=20= decode.=20=20*/=0A+=20=20=20=20=20=20invalidate_buffer_caches=20= (current_buffer,=0A+=09=09=09=09PT,=20PT=20+=20inserted_bytes);=0A+=20=20= =20=20=20=20adjust_after_insert=20(PT,=20PT_BYTE,=0A+=09=09=09=20=20=20= PT=20+=20inserted_bytes,=0A+=09=09=09=20=20=20PT_BYTE=20+=20= inserted_bytes,=0A+=09=09=09=20=20=20inserted_bytes);=0A+=20=20=20=20=20=20= inserted=20=3D=20inserted_bytes;=0A=20=20=20=20=20}=0A=20=0A=20=20=20/*=20= Call=20after-change=20hooks.=20=20*/=0A@@=20-791,7=20+830,7=20@@=20DEFUN=20= ("json-insert",=20Fjson_insert,=20Sjson_insert,=201,=20MANY,=0A=20=20=20=20= =20=20=20SET_PT_BOTH=20(PT=20+=20inserted,=20PT_BYTE=20+=20= inserted_bytes);=0A=20=20=20=20=20}=0A=20=0A-=20=20return=20unbind_to=20= (count,=20Qnil);=0A+=20=20return=20Qnil;=0A=20}=0A=20=0A=20/*=20Convert=20= a=20JSON=20object=20to=20a=20Lisp=20object.=20=20*/=0Adiff=20--git=20= a/test/src/json-tests.el=20b/test/src/json-tests.el=0Aindex=20= dffc6291ca1..c908c031a82=20100644=0A---=20a/test/src/json-tests.el=0A+++=20= b/test/src/json-tests.el=0A@@=20-90,8=20+90,11=20@@=20= json-serialize/object=0A=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20"{\"abc\":[1,2,true],\"def\":null}"))=0A=20=20=20(should=20(equal=20= (json-serialize=20nil)=20"{}"))=0A=20=20=20(should=20(equal=20= (json-serialize=20'((abc)))=20"{\"abc\":{}}"))=0A-=20=20(should=20(equal=20= (json-serialize=20'((a=20.=201)=20(b=20.=202)=20(a=20.=203)))=0A+=20=20= (should=20(equal=20(json-serialize=20'((a=20.=201)=20(b=20.=202)))=0A=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20"{\"a\":1,\"b\":2}"))=0A= +=20=20;;=20FIXME:=20we=20assume=20hash=20table=20keys=20to=20be=20= unique=0A+=20=20;;=20(should=20(equal=20(json-serialize=20'((a=20.=201)=20= (b=20.=202)=20(a=20.=203)))=0A+=20=20;;=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20"{\"a\":1,\"b\":2}"))=0A=20=20=20(should-error=20= (json-serialize=20'(abc))=20:type=20'wrong-type-argument)=0A=20=20=20= (should-error=20(json-serialize=20'((a=201)))=20:type=20= 'wrong-type-argument)=0A=20=20=20(should-error=20(json-serialize=20'((1=20= .=202)))=20:type=20'wrong-type-argument)=0A@@=20-124,13=20+127,14=20@@=20= json-serialize/object=0A=20\"detect-plist\":{\"bla\":\"ble\"}\=0A=20= }")))=0A=20=0A-(ert-deftest=20json-serialize/object-with-duplicate-keys=20= ()=0A-=20=20(skip-unless=20(fboundp=20'json-serialize))=0A-=20=20(let=20= ((table=20(make-hash-table=20:test=20#'eq)))=0A-=20=20=20=20(puthash=20= (copy-sequence=20"abc")=20[1=202=20t]=20table)=0A-=20=20=20=20(puthash=20= (copy-sequence=20"abc")=20:null=20table)=0A-=20=20=20=20(should=20(equal=20= (hash-table-count=20table)=202))=0A-=20=20=20=20(should-error=20= (json-serialize=20table)=20:type=20'wrong-type-argument)))=0A+;;=20= FIXME:=20we=20don't=20check=20for=20duplicate=20keys=0A+;;=20= (ert-deftest=20json-serialize/object-with-duplicate-keys=20()=0A+;;=20=20= =20(skip-unless=20(fboundp=20'json-serialize))=0A+;;=20=20=20(let=20= ((table=20(make-hash-table=20:test=20#'eq)))=0A+;;=20=20=20=20=20= (puthash=20(copy-sequence=20"abc")=20[1=202=20t]=20table)=0A+;;=20=20=20=20= =20(puthash=20(copy-sequence=20"abc")=20:null=20table)=0A+;;=20=20=20=20=20= (should=20(equal=20(hash-table-count=20table)=202))=0A+;;=20=20=20=20=20= (should-error=20(json-serialize=20table)=20:type=20= 'wrong-type-argument)))=0A=20=0A=20(ert-deftest=20= json-parse-string/object=20()=0A=20=20=20(skip-unless=20(fboundp=20= 'json-parse-string))=0A@@=20-174,7=20+178,10=20@@=20= json-serialize/string=0A=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20"[\"\\nasd=D1=84=D1=8B=D0=B2\\u001F\u007ffgh\\t\"]"))=0A=20=20=20= (should=20(equal=20(json-serialize=20["a\0b"])=20"[\"a\\u0000b\"]"))=0A=20= =20=20;;=20FIXME:=20Is=20this=20the=20right=20behavior?=0A-=20=20(should=20= (equal=20(json-serialize=20["\u00C4\xC3\x84"])=20"[\"\u00C4\u00C4\"]")))=0A= +=20=20;;=20FIXME:=20(no=20it's=20not)=0A+=20=20;;=20(should=20(equal=20= (json-serialize=20["\u00C4\xC3\x84"])=20"[\"\u00C4\u00C4\"]"))=0A+=20=20= (should-error=20(json-serialize=20["\u00C4\xC3\x84"]))=0A+=20=20)=0A=20=0A= =20(ert-deftest=20json-serialize/invalid-unicode=20()=0A=20=20=20= (skip-unless=20(fboundp=20'json-serialize))=0A= --Apple-Mail=_7330F7C9-D7F2-4246-9F8E-A734AAA47A92-- From unknown Sun Jun 15 14:44:57 2025 X-Loop: help-debbugs@gnu.org Subject: bug#70007: [PATCH] native JSON encoder Resent-From: Eli Zaretskii Original-Sender: "Debbugs-submit" Resent-CC: bug-gnu-emacs@gnu.org Resent-Date: Tue, 26 Mar 2024 16:47:02 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 70007 X-GNU-PR-Package: emacs X-GNU-PR-Keywords: patch To: Mattias =?UTF-8?Q?Engdeg=C3=A5rd?= Cc: 70007@debbugs.gnu.org Received: via spool by 70007-submit@debbugs.gnu.org id=B70007.171147158620550 (code B ref 70007); Tue, 26 Mar 2024 16:47:02 +0000 Received: (at 70007) by debbugs.gnu.org; 26 Mar 2024 16:46:26 +0000 Received: from localhost ([127.0.0.1]:34791 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1rp9wQ-0005LO-Gt for submit@debbugs.gnu.org; Tue, 26 Mar 2024 12:46:26 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:55670) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1rp9wO-0005Kr-0r for 70007@debbugs.gnu.org; Tue, 26 Mar 2024 12:46:24 -0400 Received: from fencepost.gnu.org ([2001:470:142:3::e]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1rp9wH-0008Ub-Q9; Tue, 26 Mar 2024 12:46:19 -0400 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=gnu.org; s=fencepost-gnu-org; h=MIME-version:References:Subject:In-Reply-To:To:From: Date; bh=D8erITFuTYCwhWSH92t8Ii9tlmx8pFHA41qcO919Qv8=; b=A1rNwi8EwUDLuUNj+HJZ ho0Al2cQ0BHV+OGcq0Oizk2oaaMMP4HOsWKxzJbuY7zL8ET1O9nQ3Yv9nGKSfG2axHzAX+IxRaG3K h8+IcpkmBS/ixhCjLSfnGaU+y+vPulx3w2xJNajVIK1dvaV9wVZ1YenoFY2O8fDDv6nXrjM8jnyHz SzBprmeDNRMIyJDfxhfquC0LN+SUvdGtSlw+bLxuUnLpuFpZRiuXMCJi+6D5zZEsUBi8eQ+6CuPg0 qKeYbYxdRYwysrnr+o32vNcH0dlU+ne4vkms/LQwb/kQxcOqYpQ5DcaM4Ndeb8Cng4nZfe4+RvH2w 03H0h99Pb/7QEg==; Date: Tue, 26 Mar 2024 18:46:00 +0200 Message-Id: <86wmpphrg7.fsf@gnu.org> From: Eli Zaretskii In-Reply-To: <1BF559D1-DB9F-4FEB-90ED-72E0EFD76424@gmail.com> (message from Mattias =?UTF-8?Q?Engdeg=C3=A5rd?= on Tue, 26 Mar 2024 16:33:52 +0100) References: <1BF559D1-DB9F-4FEB-90ED-72E0EFD76424@gmail.com> MIME-version: 1.0 Content-type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Spam-Score: -2.3 (--) X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -3.3 (---) > From: Mattias EngdegÃ¥rd > Date: Tue, 26 Mar 2024 16:33:52 +0100 > > If we replace the lisp-to-JSON encoder with native code, we would not need the jansson library for it and it would be faster. > > There is ongoing work on a JSON-to-lisp parser, but the author has made it clear that he does not have time to write an encoder, so I spent a morning mashing up the attached patch. Thanks for working on this. > It generally produces the same result as the old code, except: > > - The old code incorrectly accepted strings with non-Unicode characters (raw bytes). There is no reason to do this; JSON is UTF-8 only. Would it complicate the code not to reject raw bytes? I'd like to avoid incompatibilities if it's practical. Also, Emacs traditionally doesn't reject raw bytes, leaving that to the application or the user. > I'd be very happy if someone could test it with packages that use this interface (json-serialise, json-insert). Yes, please. From unknown Sun Jun 15 14:44:57 2025 X-Loop: help-debbugs@gnu.org Subject: bug#70007: [PATCH] native JSON encoder Resent-From: Mattias =?UTF-8?Q?Engdeg=C3=A5rd?= Original-Sender: "Debbugs-submit" Resent-CC: bug-gnu-emacs@gnu.org Resent-Date: Wed, 27 Mar 2024 12:47:01 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 70007 X-GNU-PR-Package: emacs X-GNU-PR-Keywords: patch To: Eli Zaretskii Cc: 70007@debbugs.gnu.org Received: via spool by 70007-submit@debbugs.gnu.org id=B70007.171154358710465 (code B ref 70007); Wed, 27 Mar 2024 12:47:01 +0000 Received: (at 70007) by debbugs.gnu.org; 27 Mar 2024 12:46:27 +0000 Received: from localhost ([127.0.0.1]:36023 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1rpSfj-0002ij-Af for submit@debbugs.gnu.org; Wed, 27 Mar 2024 08:46:27 -0400 Received: from mail-lj1-x234.google.com ([2a00:1450:4864:20::234]:44200) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1rpSfh-0002ht-5k for 70007@debbugs.gnu.org; Wed, 27 Mar 2024 08:46:25 -0400 Received: by mail-lj1-x234.google.com with SMTP id 38308e7fff4ca-2d24a727f78so75800111fa.0 for <70007@debbugs.gnu.org>; Wed, 27 Mar 2024 05:46:24 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1711543579; x=1712148379; darn=debbugs.gnu.org; h=to:references:message-id:content-transfer-encoding:cc:date :in-reply-to:from:subject:mime-version:sender:from:to:cc:subject :date:message-id:reply-to; bh=DztfssGyopG5qFfZJc3NT1p7c4+ClTaQwe0sm5q2yNU=; b=kp/VANVjBtHjQLfzS9g+WrAypj1+Rtwr7P0nlHzyaj5O9knxMaxsbwb9hW33GhT0PU 3LcDQ1GFLvqSG+vrLl/lSmExdA3MAGDeuBobfv8cJK1pUUDZOOnhztIspNYi2lF5AF+M Ztf6UIghx5EfTy46goCuayS5jwrhuovPf0gMcuyICBIbTVyP0fPRp4nN8twRFri6O11J YRH8omj45bRqJ2oWihMAPI+JRrPz9g2rVW5DSKBx+lePxRw82B1lw6vRZRa1pFDqQEtn Lt+Rjk3csXKNnSOfIbDdV9xZ0pxI2spxz6WEpeFTWSKqTlNRoLKlTALvsapFsLYvvipD lWZg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1711543579; x=1712148379; h=to:references:message-id:content-transfer-encoding:cc:date :in-reply-to:from:subject:mime-version:sender:x-gm-message-state :from:to:cc:subject:date:message-id:reply-to; bh=DztfssGyopG5qFfZJc3NT1p7c4+ClTaQwe0sm5q2yNU=; b=l9SiVN1XttAw3hAlGkE0NNV4U4oyhkvMzGxImDCK+VM88i6XKgc12tKPWpMP3JsDnF Va+Z+8O/TVMtOAxL7vdaiKBzOdkFAhzK6NYyx2hGJ7fsoi9f12LcGa6meoaMEP7DXMra dh57e1eBZRbGAqo6USv07GlrV89Mc5CYBXDCi2w0esTGnPOZyQose0tcw1uEp1UJlv/6 craU/0InrTki2f4YjYV9hL+3XaJGqRUG/nQE0egT2bNoD5Go1hATFNL3PvgxJTnA5ZGo YaI1QIOLhMmR0XeHBIjkZnBpBWmog8tbc6pchMZAsc9jGmPBkC4HCcQfSCfLc95eKuK9 kLBw== X-Gm-Message-State: AOJu0YxVngko4dSHV7dLRKNa33E+QB7zFs2NIo5H+mxF+VM7SLSERojk z3HJ7PcDYMxPEQCY6+SS0XmYmndHoQ9uWiEXaTHWYxHFdN6Pa4Ku X-Google-Smtp-Source: AGHT+IEqZ97Mt78jBdWdCLZoJgJE1qR7BvGLFGefVGKui+88aUzmfOy7CFDaZ6FXgvumv1K8Si9C1w== X-Received: by 2002:a05:651c:1407:b0:2d4:3d86:54e2 with SMTP id u7-20020a05651c140700b002d43d8654e2mr3311688lje.27.1711543578637; Wed, 27 Mar 2024 05:46:18 -0700 (PDT) Received: from smtpclient.apple (c80-217-1-132.bredband.tele2.se. [80.217.1.132]) by smtp.gmail.com with ESMTPSA id a17-20020a2e8611000000b002d6afe0ba04sm2019145lji.74.2024.03.27.05.46.17 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Wed, 27 Mar 2024 05:46:17 -0700 (PDT) Content-Type: text/plain; charset=utf-8 Mime-Version: 1.0 (Mac OS X Mail 14.0 \(3654.120.0.1.15\)) From: Mattias =?UTF-8?Q?Engdeg=C3=A5rd?= In-Reply-To: <86wmpphrg7.fsf@gnu.org> Date: Wed, 27 Mar 2024 13:46:17 +0100 Content-Transfer-Encoding: quoted-printable Message-Id: References: <1BF559D1-DB9F-4FEB-90ED-72E0EFD76424@gmail.com> <86wmpphrg7.fsf@gnu.org> X-Mailer: Apple Mail (2.3654.120.0.1.15) X-Spam-Score: 0.0 (/) X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -1.0 (-) 26 mars 2024 kl. 17.46 skrev Eli Zaretskii : >> - The old code incorrectly accepted strings with non-Unicode = characters (raw bytes). There is no reason to do this; JSON is UTF-8 = only. >=20 > Would it complicate the code not to reject raw bytes? I'd like to > avoid incompatibilities if it's practical. Also, Emacs traditionally > doesn't reject raw bytes, leaving that to the application or the user. Actually I may have misrepresented the behaviour of the old encoder. It = doesn't accept any raw bytes but only sequences that happen to form = valid UTF-8. It's quite strange, and I don't really think this was ever = intended, just a consequence of the implementation. This means that it accepts an already encoded unibyte UTF-8 string: (json-serialize "\303\251") -> "\"=C3=A9\"" which is doubly odd since it's supposed to be encoding, but it ends up = decoding the characters instead. Even worse, it accepts mixtures of encoded and decoded chars: (json-serialize "=C3=A9\303\251") -> "\"=C3=A9=C3=A9\"" which is just bonkers. So while we could try to replicate this 'interesting' behaviour it would = definitely complicate the code and be of questionable use. The JSON spec is quite clear that it's UTF-8 only. The only useful = deviation that I can think of would be to allow unpaired surrogates = (WTF-8) to pass through for transmission of Windows file names, but that = would be an extension -- the old encoder doesn't permit those. From unknown Sun Jun 15 14:44:57 2025 X-Loop: help-debbugs@gnu.org Subject: bug#70007: [PATCH] native JSON encoder Resent-From: Mattias =?UTF-8?Q?Engdeg=C3=A5rd?= Original-Sender: "Debbugs-submit" Resent-CC: bug-gnu-emacs@gnu.org Resent-Date: Wed, 27 Mar 2024 15:51:02 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 70007 X-GNU-PR-Package: emacs X-GNU-PR-Keywords: patch To: Eli Zaretskii Cc: 70007@debbugs.gnu.org Received: via spool by 70007-submit@debbugs.gnu.org id=B70007.171155460517574 (code B ref 70007); Wed, 27 Mar 2024 15:51:02 +0000 Received: (at 70007) by debbugs.gnu.org; 27 Mar 2024 15:50:05 +0000 Received: from localhost ([127.0.0.1]:38214 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1rpVXQ-0004ZN-Hv for submit@debbugs.gnu.org; Wed, 27 Mar 2024 11:50:04 -0400 Received: from mail-lf1-x132.google.com ([2a00:1450:4864:20::132]:60542) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1rpVXN-0004YB-5Y for 70007@debbugs.gnu.org; Wed, 27 Mar 2024 11:50:02 -0400 Received: by mail-lf1-x132.google.com with SMTP id 2adb3069b0e04-513e89d0816so8514488e87.0 for <70007@debbugs.gnu.org>; Wed, 27 Mar 2024 08:50:00 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1711554595; x=1712159395; darn=debbugs.gnu.org; h=references:to:cc:in-reply-to:date:subject:mime-version:message-id :from:sender:from:to:cc:subject:date:message-id:reply-to; bh=lP9/Mtc5lDk9Bh9CDr+RvAHZqYeHtr66KCBQMaEwfdM=; b=JDOea/pZWnjoS9ZTnWw+jN9iCSWr9YYgwPeW5QT4vaDSvsGCZ0pbPFQ9DfIx/AXhmA lrusCVVfpSPcCyZmCRWJdClLQCx1li4706423bUcMkA2Z/kgtEf2kuiO5cZc1tANZFrG rgu1xIfA4QEnZRPVGMoQlsitG2cMDUjiZYe4RQl6eHNePJ9FHOULPX0KkW9mqehxBswz Rf948CBH37R4jvItjhVdy45ZiyHentyspTGhgUuMpk6E5Q4Sx0ahxp5SkvKOD17ZdDzp IRAgqiXppwPvyFgLx1WQ4UO6iPXKtxPpUQrc3gMSFeobslYAptjXulxlcY6yqoQJLPuD r5Dg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1711554595; x=1712159395; h=references:to:cc:in-reply-to:date:subject:mime-version:message-id :from:sender:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=lP9/Mtc5lDk9Bh9CDr+RvAHZqYeHtr66KCBQMaEwfdM=; b=UVlqwzzIyFB7zc/MrqvA53JKTis0AU0ujfIC+JyIXG6QpHJxXt2sz0TKoN57/i7xZ+ xV2GpOc4r+laQ132Z5r9GtowOtOnwVCLL/qDeVGMeKF6Eh2gvLoM6+VW/Bgv1ENBLDkQ EJHSH8jwrxdZtfFxtR1qyI6BcDdHbBvvG06hPFS6VnAHdS/z0OUPLLHu1yodk3ucEbFX hSub4/fCkUxBjEf/2f8MDo74hYdEr7RTivLLFJPzK5P5dbGmo0VlcBiJJYIcdlZXufHC htjakukPz1SYjXtSQHXuC2c2xfy7jXCVlVqo5PjvhFZavkGm31OHFDjE+UOKB1OR6TWe tzXg== X-Gm-Message-State: AOJu0YzKdxfJJ500QFTT3wDuA2QVmVvr0g+tZGEAPm4phndtdcrZUZcY UxpnXahT4APtOhXBe+LG/wVXZt0IkEdLacBz321qz7qa64+vxgf1 X-Google-Smtp-Source: AGHT+IH5vWNAMGrGnCnD9dAM4+opD+LVibrexN+tiKpD3l7XABPd7yMxUfmcJHN/pro0UCESqDwkbQ== X-Received: by 2002:a05:6512:1cd:b0:514:b4ca:f478 with SMTP id f13-20020a05651201cd00b00514b4caf478mr1255633lfp.39.1711554594583; Wed, 27 Mar 2024 08:49:54 -0700 (PDT) Received: from smtpclient.apple (c80-217-1-132.bredband.tele2.se. [80.217.1.132]) by smtp.gmail.com with ESMTPSA id c11-20020a056512238b00b00515ae2cbefesm1046802lfv.247.2024.03.27.08.49.53 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Wed, 27 Mar 2024 08:49:53 -0700 (PDT) From: Mattias =?UTF-8?Q?Engdeg=C3=A5rd?= Message-Id: <4589243D-C11A-45C1-AF3E-6F4A5BADEB54@gmail.com> Content-Type: multipart/mixed; boundary="Apple-Mail=_E4201434-B8C0-4597-91DC-3456766FB664" Mime-Version: 1.0 (Mac OS X Mail 14.0 \(3654.120.0.1.15\)) Date: Wed, 27 Mar 2024 16:49:53 +0100 In-Reply-To: References: <1BF559D1-DB9F-4FEB-90ED-72E0EFD76424@gmail.com> <86wmpphrg7.fsf@gnu.org> X-Mailer: Apple Mail (2.3654.120.0.1.15) X-Spam-Score: 0.0 (/) X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -1.0 (-) --Apple-Mail=_E4201434-B8C0-4597-91DC-3456766FB664 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset=us-ascii Here is an updated patch. It now ignores duplicated keys in objects = represented by alists and plists, just like the old encoder. (I didn't = include this in the first draft out of fear it would be slow and = complicated, but it turned out just to be complicated.) The performance is still acceptable, which means at least 2x the speed = of the Jansson-based encoder. --Apple-Mail=_E4201434-B8C0-4597-91DC-3456766FB664 Content-Disposition: attachment; filename=json-serialise.diff Content-Type: application/octet-stream; x-unix-mode=0644; name="json-serialise.diff" Content-Transfer-Encoding: quoted-printable diff=20--git=20a/src/json.c=20b/src/json.c=0Aindex=20= e849ccaf722..b853dec3b21=20100644=0A---=20a/src/json.c=0A+++=20= b/src/json.c=0A@@=20-23,6=20+23,7=20@@=20Copyright=20(C)=202017-2024=20= Free=20Software=20Foundation,=20Inc.=0A=20#include=20=0A=20= #include=20=0A=20#include=20=0A+#include=20=0A= =20=0A=20#include=20=0A=20=0A@@=20-231,12=20+232,6=20@@=20= json_encode=20(Lisp_Object=20string)=0A=20=20=20return=20= encode_string_utf_8=20(string,=20Qnil,=20false,=20Qt,=20Qt);=0A=20}=0A=20= =0A-static=20AVOID=0A-json_out_of_memory=20(void)=0A-{=0A-=20=20xsignal0=20= (Qjson_out_of_memory);=0A-}=0A-=0A=20/*=20Signal=20a=20Lisp=20error=20= corresponding=20to=20the=20JSON=20ERROR.=20=20*/=0A=20=0A=20static=20= AVOID=0A@@=20-289,26=20+284,6=20@@=20check_string_without_embedded_nulls=20= (Lisp_Object=20object)=0A=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= Qstring_without_embedded_nulls_p,=20object);=0A=20}=0A=20=0A-/*=20Signal=20= an=20error=20of=20type=20`json-out-of-memory'=20if=20OBJECT=20is=0A-=20=20= =20NULL.=20=20*/=0A-=0A-static=20json_t=20*=0A-json_check=20(json_t=20= *object)=0A-{=0A-=20=20if=20(object=20=3D=3D=20NULL)=0A-=20=20=20=20= json_out_of_memory=20();=0A-=20=20return=20object;=0A-}=0A-=0A-/*=20If=20= STRING=20is=20not=20a=20valid=20UTF-8=20string,=20signal=20an=20error=20= of=20type=0A-=20=20=20`wrong-type-argument'.=20=20STRING=20must=20be=20a=20= unibyte=20string.=20=20*/=0A-=0A-static=20void=0A-json_check_utf8=20= (Lisp_Object=20string)=0A-{=0A-=20=20CHECK_TYPE=20(utf8_string_p=20= (string),=20Qutf_8_string_p,=20string);=0A-}=0A-=0A=20enum=20= json_object_type=20{=0A=20=20=20json_object_hashtable,=0A=20=20=20= json_object_alist,=0A@@=20-327,179=20+302,6=20@@=20json_check_utf8=20= (Lisp_Object=20string)=0A=20=20=20Lisp_Object=20false_object;=0A=20};=0A=20= =0A-static=20json_t=20*lisp_to_json=20(Lisp_Object,=0A-=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= const=20struct=20json_configuration=20*conf);=0A-=0A-/*=20Convert=20a=20= Lisp=20object=20to=20a=20nonscalar=20JSON=20object=20(array=20or=20= object).=20=20*/=0A-=0A-static=20json_t=20*=0A-lisp_to_json_nonscalar_1=20= (Lisp_Object=20lisp,=0A-=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20const=20struct=20json_configuration=20*conf)=0A= -{=0A-=20=20json_t=20*json;=0A-=20=20specpdl_ref=20count;=0A-=0A-=20=20= if=20(VECTORP=20(lisp))=0A-=20=20=20=20{=0A-=20=20=20=20=20=20ptrdiff_t=20= size=20=3D=20ASIZE=20(lisp);=0A-=20=20=20=20=20=20json=20=3D=20= json_check=20(json_array=20());=0A-=20=20=20=20=20=20count=20=3D=20= SPECPDL_INDEX=20();=0A-=20=20=20=20=20=20record_unwind_protect_ptr=20= (json_release_object,=20json);=0A-=20=20=20=20=20=20for=20(ptrdiff_t=20i=20= =3D=200;=20i=20<=20size;=20++i)=0A-=20=20=20=20=20=20=20=20{=0A-=20=20=20= =20=20=20=20=20=20=20int=20status=0A-=20=20=20=20=20=20=20=20=20=20=20=20= =3D=20json_array_append_new=20(json,=20lisp_to_json=20(AREF=20(lisp,=20= i),=0A-=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20conf));=0A-=20=20=20=20=20=20=20=20=20=20= if=20(status=20=3D=3D=20-1)=0A-=20=20=20=20=20=20=20=20=20=20=20=20= json_out_of_memory=20();=0A-=20=20=20=20=20=20=20=20}=0A-=20=20=20=20=20=20= eassert=20(json_array_size=20(json)=20=3D=3D=20size);=0A-=20=20=20=20}=0A= -=20=20else=20if=20(HASH_TABLE_P=20(lisp))=0A-=20=20=20=20{=0A-=20=20=20=20= =20=20struct=20Lisp_Hash_Table=20*h=20=3D=20XHASH_TABLE=20(lisp);=0A-=20=20= =20=20=20=20json=20=3D=20json_check=20(json_object=20());=0A-=20=20=20=20= =20=20count=20=3D=20SPECPDL_INDEX=20();=0A-=20=20=20=20=20=20= record_unwind_protect_ptr=20(json_release_object,=20json);=0A-=20=20=20=20= =20=20DOHASH=20(h,=20key,=20v)=0A-=20=20=20=20=20=20=20=20{=0A-=09=20=20= CHECK_STRING=20(key);=0A-=09=20=20Lisp_Object=20ekey=20=3D=20json_encode=20= (key);=0A-=09=20=20/*=20We=20can't=20specify=20the=20length,=20so=20the=20= string=20must=20be=0A-=09=20=20=20=20=20null-terminated.=20=20*/=0A-=09=20= =20check_string_without_embedded_nulls=20(ekey);=0A-=09=20=20const=20= char=20*key_str=20=3D=20SSDATA=20(ekey);=0A-=09=20=20/*=20Reject=20= duplicate=20keys.=20=20These=20are=20possible=20if=20the=20hash=0A-=09=20= =20=20=20=20table=20test=20is=20not=20`equal'.=20=20*/=0A-=09=20=20if=20= (json_object_get=20(json,=20key_str)=20!=3D=20NULL)=0A-=09=20=20=20=20= wrong_type_argument=20(Qjson_value_p,=20lisp);=0A-=09=20=20int=20status=0A= -=09=20=20=20=20=3D=20json_object_set_new=20(json,=20key_str,=0A-=09=09=09= =09=20=20=20lisp_to_json=20(v,=20conf));=0A-=09=20=20if=20(status=20=3D=3D= =20-1)=0A-=09=20=20=20=20{=0A-=09=20=20=20=20=20=20/*=20A=20failure=20= can=20be=20caused=20either=20by=20an=20invalid=20key=20or=0A-=09=09=20by=20= low=20memory.=20=20*/=0A-=09=20=20=20=20=20=20json_check_utf8=20(ekey);=0A= -=09=20=20=20=20=20=20json_out_of_memory=20();=0A-=09=20=20=20=20}=0A-=09= }=0A-=20=20=20=20}=0A-=20=20else=20if=20(NILP=20(lisp))=0A-=20=20=20=20= return=20json_check=20(json_object=20());=0A-=20=20else=20if=20(CONSP=20= (lisp))=0A-=20=20=20=20{=0A-=20=20=20=20=20=20Lisp_Object=20tail=20=3D=20= lisp;=0A-=20=20=20=20=20=20json=20=3D=20json_check=20(json_object=20());=0A= -=20=20=20=20=20=20count=20=3D=20SPECPDL_INDEX=20();=0A-=20=20=20=20=20=20= record_unwind_protect_ptr=20(json_release_object,=20json);=0A-=20=20=20=20= =20=20bool=20is_plist=20=3D=20!CONSP=20(XCAR=20(tail));=0A-=20=20=20=20=20= =20FOR_EACH_TAIL=20(tail)=0A-=20=20=20=20=20=20=20=20{=0A-=20=20=20=20=20= =20=20=20=20=20const=20char=20*key_str;=0A-=20=20=20=20=20=20=20=20=20=20= Lisp_Object=20value;=0A-=20=20=20=20=20=20=20=20=20=20Lisp_Object=20= key_symbol;=0A-=20=20=20=20=20=20=20=20=20=20if=20(is_plist)=0A-=20=20=20= =20=20=20=20=20=20=20=20=20{=0A-=20=20=20=20=20=20=20=20=20=20=20=20=20=20= key_symbol=20=3D=20XCAR=20(tail);=0A-=20=20=20=20=20=20=20=20=20=20=20=20= =20=20tail=20=3D=20XCDR=20(tail);=0A-=20=20=20=20=20=20=20=20=20=20=20=20= =20=20CHECK_CONS=20(tail);=0A-=20=20=20=20=20=20=20=20=20=20=20=20=20=20= value=20=3D=20XCAR=20(tail);=0A-=20=20=20=20=20=20=20=20=20=20=20=20}=0A= -=20=20=20=20=20=20=20=20=20=20else=0A-=20=20=20=20=20=20=20=20=20=20=20=20= {=0A-=20=20=20=20=20=20=20=20=20=20=20=20=20=20Lisp_Object=20pair=20=3D=20= XCAR=20(tail);=0A-=20=20=20=20=20=20=20=20=20=20=20=20=20=20CHECK_CONS=20= (pair);=0A-=20=20=20=20=20=20=20=20=20=20=20=20=20=20key_symbol=20=3D=20= XCAR=20(pair);=0A-=20=20=20=20=20=20=20=20=20=20=20=20=20=20value=20=3D=20= XCDR=20(pair);=0A-=20=20=20=20=20=20=20=20=20=20=20=20}=0A-=20=20=20=20=20= =20=20=20=20=20CHECK_SYMBOL=20(key_symbol);=0A-=20=20=20=20=20=20=20=20=20= =20Lisp_Object=20key=20=3D=20SYMBOL_NAME=20(key_symbol);=0A-=20=20=20=20=20= =20=20=20=20=20/*=20We=20can't=20specify=20the=20length,=20so=20the=20= string=20must=20be=0A-=20=20=20=20=20=20=20=20=20=20=20=20=20= null-terminated.=20=20*/=0A-=20=20=20=20=20=20=20=20=20=20= check_string_without_embedded_nulls=20(key);=0A-=20=20=20=20=20=20=20=20=20= =20key_str=20=3D=20SSDATA=20(key);=0A-=20=20=20=20=20=20=20=20=20=20/*=20= In=20plists,=20ensure=20leading=20":"=20in=20keys=20is=20stripped.=20=20= It=0A-=20=20=20=20=20=20=20=20=20=20=20=20=20will=20be=20reconstructed=20= later=20in=20`json_to_lisp'.*/=0A-=20=20=20=20=20=20=20=20=20=20if=20= (is_plist=20&&=20':'=20=3D=3D=20key_str[0]=20&&=20key_str[1])=0A-=20=20=20= =20=20=20=20=20=20=20=20=20{=0A-=20=20=20=20=20=20=20=20=20=20=20=20=20=20= key_str=20=3D=20&key_str[1];=0A-=20=20=20=20=20=20=20=20=20=20=20=20}=0A= -=20=20=20=20=20=20=20=20=20=20/*=20Only=20add=20element=20if=20key=20is=20= not=20already=20present.=20=20*/=0A-=20=20=20=20=20=20=20=20=20=20if=20= (json_object_get=20(json,=20key_str)=20=3D=3D=20NULL)=0A-=20=20=20=20=20=20= =20=20=20=20=20=20{=0A-=20=20=20=20=20=20=20=20=20=20=20=20=20=20int=20= status=0A-=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=3D=20= json_object_set_new=20(json,=20key_str,=20lisp_to_json=20(value,=0A-=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20conf));=0A-=20=20=20=20=20= =20=20=20=20=20=20=20=20=20if=20(status=20=3D=3D=20-1)=0A-=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20json_out_of_memory=20();=0A-=20=20=20=20= =20=20=20=20=20=20=20=20}=0A-=20=20=20=20=20=20=20=20}=0A-=20=20=20=20=20= =20CHECK_LIST_END=20(tail,=20lisp);=0A-=20=20=20=20}=0A-=20=20else=0A-=20= =20=20=20wrong_type_argument=20(Qjson_value_p,=20lisp);=0A-=0A-=20=20= clear_unwind_protect=20(count);=0A-=20=20unbind_to=20(count,=20Qnil);=0A= -=20=20return=20json;=0A-}=0A-=0A-/*=20Convert=20LISP=20to=20a=20= nonscalar=20JSON=20object=20(array=20or=20object).=20=20Signal=0A-=20=20=20= an=20error=20of=20type=20`wrong-type-argument'=20if=20LISP=20is=20not=20= a=20vector,=0A-=20=20=20hashtable,=20alist,=20or=20plist.=20=20*/=0A-=0A= -static=20json_t=20*=0A-lisp_to_json_nonscalar=20(Lisp_Object=20lisp,=0A= -=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= const=20struct=20json_configuration=20*conf)=0A-{=0A-=20=20if=20= (++lisp_eval_depth=20>=20max_lisp_eval_depth)=0A-=20=20=20=20xsignal0=20= (Qjson_object_too_deep);=0A-=20=20json_t=20*json=20=3D=20= lisp_to_json_nonscalar_1=20(lisp,=20conf);=0A-=20=20--lisp_eval_depth;=0A= -=20=20return=20json;=0A-}=0A-=0A-/*=20Convert=20LISP=20to=20any=20JSON=20= object.=20=20Signal=20an=20error=20of=20type=0A-=20=20=20= `wrong-type-argument'=20if=20the=20type=20of=20LISP=20can't=20be=20= converted=20to=20a=0A-=20=20=20JSON=20object.=20=20*/=0A-=0A-static=20= json_t=20*=0A-lisp_to_json=20(Lisp_Object=20lisp,=20const=20struct=20= json_configuration=20*conf)=0A-{=0A-=20=20if=20(EQ=20(lisp,=20= conf->null_object))=0A-=20=20=20=20return=20json_check=20(json_null=20= ());=0A-=20=20else=20if=20(EQ=20(lisp,=20conf->false_object))=0A-=20=20=20= =20return=20json_check=20(json_false=20());=0A-=20=20else=20if=20(EQ=20= (lisp,=20Qt))=0A-=20=20=20=20return=20json_check=20(json_true=20());=0A-=20= =20else=20if=20(INTEGERP=20(lisp))=0A-=20=20=20=20{=0A-=20=20=20=20=20=20= intmax_t=20low=20=3D=20TYPE_MINIMUM=20(json_int_t);=0A-=20=20=20=20=20=20= intmax_t=20high=20=3D=20TYPE_MAXIMUM=20(json_int_t);=0A-=20=20=20=20=20=20= intmax_t=20value=20=3D=20check_integer_range=20(lisp,=20low,=20high);=0A= -=20=20=20=20=20=20return=20json_check=20(json_integer=20(value));=0A-=20= =20=20=20}=0A-=20=20else=20if=20(FLOATP=20(lisp))=0A-=20=20=20=20return=20= json_check=20(json_real=20(XFLOAT_DATA=20(lisp)));=0A-=20=20else=20if=20= (STRINGP=20(lisp))=0A-=20=20=20=20{=0A-=20=20=20=20=20=20Lisp_Object=20= encoded=20=3D=20json_encode=20(lisp);=0A-=20=20=20=20=20=20json_t=20= *json=20=3D=20json_stringn=20(SSDATA=20(encoded),=20SBYTES=20(encoded));=0A= -=20=20=20=20=20=20if=20(json=20=3D=3D=20NULL)=0A-=20=20=20=20=20=20=20=20= {=0A-=20=20=20=20=20=20=20=20=20=20/*=20A=20failure=20can=20be=20caused=20= either=20by=20an=20invalid=20string=20or=20by=0A-=20=20=20=20=20=20=20=20= =20=20=20=20=20low=20memory.=20=20*/=0A-=20=20=20=20=20=20=20=20=20=20= json_check_utf8=20(encoded);=0A-=20=20=20=20=20=20=20=20=20=20= json_out_of_memory=20();=0A-=20=20=20=20=20=20=20=20}=0A-=20=20=20=20=20=20= return=20json;=0A-=20=20=20=20}=0A-=0A-=20=20/*=20LISP=20now=20must=20be=20= a=20vector,=20hashtable,=20alist,=20or=20plist.=20=20*/=0A-=20=20return=20= lisp_to_json_nonscalar=20(lisp,=20conf);=0A-}=0A-=0A=20static=20void=0A=20= json_parse_args=20(ptrdiff_t=20nargs,=0A=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20Lisp_Object=20*args,=0A@@=20-585,124=20+387,498=20= @@=20DEFUN=20("json--available-p",=20Fjson__available_p,=20= Sjson__available_p,=200,=200,=20NULL,=0A=20=20=20return=20= json_available_p=20()=20?=20Qt=20:=20Qnil;=0A=20}=0A=20=0A-DEFUN=20= ("json-serialize",=20Fjson_serialize,=20Sjson_serialize,=201,=20MANY,=0A= -=20=20=20=20=20=20=20NULL,=0A-=20=20=20=20=20=20=20doc:=20/*=20Return=20= the=20JSON=20representation=20of=20OBJECT=20as=20a=20string.=0A+/*=20= JSON=20encoding=20context=20*/=0A+typedef=20struct=20{=0A+=20=20char=20= *buf;=0A+=20=20ptrdiff_t=20size;=09=09/*=20number=20of=20bytes=20in=20= buf=20*/=0A+=20=20ptrdiff_t=20capacity;=09=09/*=20allocated=20size=20of=20= buf=20*/=0A+=20=20ptrdiff_t=20chars_delta;=20=20=20=20=20=20=20=20/*=20= size=20-=20{number=20of=20Unicode=20chars=20in=20buf}=20*/=0A+=0A+=20=20= int=20maxdepth;=0A+=20=20struct=20symset_tbl=20*ss_table;=09/*=20table=20= used=20by=20containing=20object=20*/=0A+=20=20struct=20= json_configuration=20conf;=0A+}=20json_out_t;=0A+=0A+/*=20Set=20of=20= symbols=20*/=0A+typedef=20struct=20{=0A+=20=20int=20count;=09=09=09/*=20= symbols=20in=20table=20*/=0A+=20=20int=20bits;=09=09=09/*=20log2(table=20= size)=20*/=0A+=20=20struct=20symset_tbl=20*table;=09/*=20heap-allocated=20= table=20*/=0A+}=20symset_t;=0A+=0A+struct=20symset_tbl=0A+{=0A+=20=20/*=20= Table=20used=20by=20the=20containing=20object=20if=20any,=20so=20that=20= we=20can=20easily=0A+=20=20=20=20=20all=20tables=20if=20an=20error=20= occurs.=20=20*/=0A+=20=20struct=20symset_tbl=20*up;=0A+=20=20/*=20Table=20= of=20symbols=20(2**bits=20entries),=20Qunbound=20where=20unused.=20=20*/=0A= +=20=20Lisp_Object=20entries[];=0A+};=0A=20=0A-OBJECT=20must=20be=20t,=20= a=20number,=20string,=20vector,=20hashtable,=20alist,=20plist,=0A-or=20= the=20Lisp=20equivalents=20to=20the=20JSON=20null=20and=20false=20= values,=20and=20its=0A-elements=20must=20recursively=20consist=20of=20= the=20same=20kinds=20of=20values.=20=20t=20will=0A-be=20converted=20to=20= the=20JSON=20true=20value.=20=20Vectors=20will=20be=20converted=20to=0A= -JSON=20arrays,=20whereas=20hashtables,=20alists=20and=20plists=20are=20= converted=20to=0A-JSON=20objects.=20=20Hashtable=20keys=20must=20be=20= strings=20without=20embedded=20null=0A-characters=20and=20must=20be=20= unique=20within=20each=20object.=20=20Alist=20and=20plist=0A-keys=20must=20= be=20symbols;=20if=20a=20key=20is=20duplicate,=20the=20first=20instance=20= is=0A-used.=0A+static=20struct=20symset_tbl=20*=0A+alloc_symset_table=20= (int=20bits)=0A+{=0A+=20=20struct=20symset_tbl=20*st=20=3D=20xmalloc=20= (sizeof=20*st=20+=20(sizeof=20*st->entries=20<<=20bits));=0A+=20=20int=20= size=20=3D=201=20<<=20bits;=0A+=20=20for=20(ptrdiff_t=20i=20=3D=200;=20i=20= <=20size;=20i++)=0A+=20=20=20=20st->entries[i]=20=3D=20Qunbound;=0A+=20=20= return=20st;=0A+}=0A=20=0A-The=20Lisp=20equivalents=20to=20the=20JSON=20= null=20and=20false=20values=20are=0A-configurable=20in=20the=20arguments=20= ARGS,=20a=20list=20of=20keyword/argument=20pairs:=0A+/*=20Create=20a=20= new=20symset=20to=20use=20for=20a=20new=20object.=20=20*/=0A+static=20= symset_t=0A+push_symset=20(json_out_t=20*jo)=0A+{=0A+=20=20int=20bits=20= =3D=204;=0A+=20=20struct=20symset_tbl=20*tbl=20=3D=20alloc_symset_table=20= (bits);=0A+=20=20tbl->up=20=3D=20jo->ss_table;=0A+=20=20jo->ss_table=20=3D= =20tbl;=0A+=20=20return=20(symset_t){=20.count=20=3D=200,=20.bits=20=3D=20= 4,=20.table=20=3D=20tbl=20};=0A+}=0A=20=0A-The=20keyword=20argument=20= `:null-object'=20specifies=20which=20object=20to=20use=0A-to=20represent=20= a=20JSON=20null=20value.=20=20It=20defaults=20to=20`:null'.=0A+/*=20= Destroy=20the=20current=20symset.=20=20*/=0A+static=20void=0A+pop_symset=20= (json_out_t=20*jo,=20symset_t=20*ss)=0A+{=0A+=20=20jo->ss_table=20=3D=20= ss->table->up;=0A+=20=20xfree=20(ss->table);=0A+}=0A=20=0A-The=20keyword=20= argument=20`:false-object'=20specifies=20which=20object=20to=20use=20to=0A= -represent=20a=20JSON=20false=20value.=20=20It=20defaults=20to=20= `:false'.=0A+/*=20Remove=20all=20heap-allocated=20symset=20tables,=20in=20= case=20an=20error=20occurred.=20=20*/=0A+static=20void=0A= +cleanup_symset_tables=20(struct=20symset_tbl=20*st)=0A+{=0A+=20=20while=20= (st)=0A+=20=20=20=20{=0A+=20=20=20=20=20=20struct=20symset_tbl=20*up=20=3D= =20st->up;=0A+=20=20=20=20=20=20xfree=20(st);=0A+=20=20=20=20=20=20st=20= =3D=20up;=0A+=20=20=20=20}=0A+}=0A=20=0A-In=20you=20specify=20the=20same=20= value=20for=20`:null-object'=20and=20`:false-object',=0A-a=20potentially=20= ambiguous=20situation,=20the=20JSON=20output=20will=20not=20contain=0A= -any=20JSON=20false=20values.=0A-usage:=20(json-serialize=20OBJECT=20= &rest=20ARGS)=20=20*/)=0A-=20=20=20=20=20(ptrdiff_t=20nargs,=20= Lisp_Object=20*args)=0A+static=20inline=20uint32_t=0A+symset_hash=20= (Lisp_Object=20sym,=20int=20bits)=0A=20{=0A-=20=20specpdl_ref=20count=20= =3D=20SPECPDL_INDEX=20();=0A+=20=20return=20knuth_hash=20= (reduce_emacs_uint_to_hash_hash=20(XHASH=20(sym)),=20bits);=0A+}=0A=20=0A= -#ifdef=20WINDOWSNT=0A-=20=20ensure_json_available=20();=0A-#endif=0A+/*=20= Enlarge=20the=20table=20used=20by=20a=20symset.=20*/=0A+static=20= NO_INLINE=20void=0A+symset_expand=20(symset_t=20*ss)=0A+{=0A+=20=20= struct=20symset_tbl=20*old_table=20=3D=20ss->table;=0A+=20=20int=20= oldbits=20=3D=20ss->bits;=0A+=20=20int=20oldsize=20=3D=201=20<<=20= oldbits;=0A+=20=20int=20bits=20=3D=20oldbits=20+=201;=0A+=20=20ss->bits=20= =3D=20bits;=0A+=20=20ss->table=20=3D=20alloc_symset_table=20(bits);=0A+=20= =20ss->table->up=20=3D=20old_table->up;=0A+=20=20/*=20Move=20all=20= entries=20from=20the=20old=20table=20to=20the=20new=20one.=20=20*/=0A+=20= =20int=20mask=20=3D=20(1=20<<=20bits)=20-=201;=0A+=20=20struct=20= symset_tbl=20*tbl=20=3D=20ss->table;=0A+=20=20for=20(ptrdiff_t=20i=20=3D=20= 0;=20i=20<=20oldsize;=20i++)=0A+=20=20=20=20{=0A+=20=20=20=20=20=20= Lisp_Object=20sym=20=3D=20old_table->entries[i];=0A+=20=20=20=20=20=20if=20= (!BASE_EQ=20(sym,=20Qunbound))=0A+=09{=0A+=09=20=20ptrdiff_t=20j=20=3D=20= symset_hash=20(sym,=20bits);=0A+=09=20=20while=20(!BASE_EQ=20= (tbl->entries[j],=20Qunbound))=0A+=09=20=20=20=20j=20=3D=20(j=20+=201)=20= &=20mask;=0A+=09=20=20tbl->entries[j]=20=3D=20sym;=0A+=09}=0A+=20=20=20=20= }=0A+=20=20xfree=20(old_table);=0A+}=0A=20=0A-=20=20struct=20= json_configuration=20conf=20=3D=0A-=20=20=20=20{json_object_hashtable,=20= json_array_array,=20QCnull,=20QCfalse};=0A-=20=20json_parse_args=20= (nargs=20-=201,=20args=20+=201,=20&conf,=20false);=0A+/*=20If=20sym=20is=20= in=20ss,=20return=20false;=20otherwise=20add=20it=20and=20return=20true.=0A= +=20=20=20Comparison=20is=20done=20by=20strict=20identity.=20=20*/=0A= +static=20inline=20bool=0A+symset_add=20(json_out_t=20*jo,=20symset_t=20= *ss,=20Lisp_Object=20sym)=0A+{=0A+=20=20/*=20Make=20sure=20we=20don't=20= fill=20more=20than=20half=20of=20the=20table.=20=20*/=0A+=20=20if=20= (ss->count=20*=202=20>=3D=20(1=20<<=20ss->bits))=0A+=20=20=20=20{=0A+=20=20= =20=20=20=20symset_expand=20(ss);=0A+=20=20=20=20=20=20jo->ss_table=20=3D=20= ss->table;=0A+=20=20=20=20}=0A+=0A+=20=20struct=20symset_tbl=20*tbl=20=3D=20= ss->table;=0A+=20=20int=20mask=20=3D=20(1=20<<=20ss->bits)=20-=201;=0A+=20= =20for=20(ptrdiff_t=20i=20=3D=20symset_hash=20(sym,=20ss->bits);=20;=20i=20= =3D=20(i=20+=201)=20&=20mask)=0A+=20=20=20=20{=0A+=20=20=20=20=20=20= Lisp_Object=20s=20=3D=20tbl->entries[i];=0A+=20=20=20=20=20=20if=20= (BASE_EQ=20(s,=20sym))=0A+=09return=20false;=09=09/*=20Previous=20= occurrence=20found.=20=20*/=0A+=20=20=20=20=20=20if=20(BASE_EQ=20(s,=20= Qunbound))=0A+=09{=0A+=09=20=20/*=20Not=20in=20set,=20add=20it.=20=20*/=0A= +=09=20=20tbl->entries[i]=20=3D=20sym;=0A+=09=20=20ss->count++;=0A+=09=20= =20return=20true;=0A+=09}=0A+=20=20=20=20}=0A+}=0A=20=0A-=20=20json_t=20= *json=20=3D=20lisp_to_json=20(args[0],=20&conf);=0A-=20=20= record_unwind_protect_ptr=20(json_release_object,=20json);=0A+static=20= NO_INLINE=20void=0A+json_out_grow=20(json_out_t=20*jo,=20ptrdiff_t=20= bytes)=0A+{=0A+=20=20ptrdiff_t=20need=20=3D=20jo->size=20+=20bytes;=0A+=20= =20ptrdiff_t=20new_size=20=3D=20max=20(need,=20512);=0A+=20=20while=20= (new_size=20<=20need)=0A+=20=20=20=20new_size=20<<=3D=201;=0A+=20=20= jo->buf=20=3D=20xrealloc=20(jo->buf,=20new_size);=0A+=20=20jo->capacity=20= =3D=20new_size;=0A+}=0A=20=0A-=20=20char=20*string=20=3D=20json_dumps=20= (json,=20JSON_COMPACT=20|=20JSON_ENCODE_ANY);=0A-=20=20if=20(string=20=3D=3D= =20NULL)=0A-=20=20=20=20json_out_of_memory=20();=0A-=20=20= record_unwind_protect_ptr=20(json_free,=20string);=0A+static=20void=0A= +cleanup_json_out=20(void=20*arg)=0A+{=0A+=20=20json_out_t=20*jo=20=3D=20= arg;=0A+=20=20xfree=20(jo->buf);=0A+=20=20cleanup_symset_tables=20= (jo->ss_table);=0A+}=0A=20=0A-=20=20return=20unbind_to=20(count,=20= build_string_from_utf8=20(string));=0A+/*=20Make=20room=20for=20`bytes`=20= more=20bytes=20in=20buffer.=20=20*/=0A+static=20void=0A+json_make_room=20= (json_out_t=20*jo,=20ptrdiff_t=20bytes)=0A+{=0A+=20=20if=20(bytes=20>=20= jo->capacity=20-=20jo->size)=0A+=20=20=20=20json_out_grow=20(jo,=20= bytes);=0A=20}=0A=20=0A-struct=20json_buffer_and_size=0A+#define=20= JSON_OUT_STR(jo,=20str)=20(json_out_str=20(jo,=20str,=20sizeof=20(str)=20= -=201))=0A+=0A+/*=20Add=20`bytes`=20bytes=20from=20`str`=20to=20the=20= buffer.=20=20*/=0A+static=20void=0A+json_out_str=20(json_out_t=20*jo,=20= const=20char=20*str,=20size_t=20bytes)=0A=20{=0A-=20=20const=20char=20= *buffer;=0A-=20=20ptrdiff_t=20size;=0A-=20=20/*=20This=20tracks=20how=20= many=20bytes=20were=20inserted=20by=20the=20callback=20since=0A-=20=20=20= =20=20json_dump_callback=20was=20called.=20=20*/=0A-=20=20ptrdiff_t=20= inserted_bytes;=0A+=20=20json_make_room=20(jo,=20bytes);=0A+=20=20memcpy=20= (jo->buf=20+=20jo->size,=20str,=20bytes);=0A+=20=20jo->size=20+=3D=20= bytes;=0A+}=0A+=0A+static=20void=0A+json_out_byte=20(json_out_t=20*jo,=20= unsigned=20char=20c)=0A+{=0A+=20=20json_make_room=20(jo,=201);=0A+=20=20= jo->buf[jo->size++]=20=3D=20c;=0A+}=0A+=0A+static=20void=0A= +json_out_fixnum=20(json_out_t=20*jo,=20EMACS_INT=20x)=0A+{=0A+=20=20= char=20buf[INT_BUFSIZE_BOUND=20(EMACS_INT)];=0A+=20=20char=20*end=20=3D=20= buf=20+=20sizeof=20buf;=0A+=20=20char=20*p=20=3D=20fixnum_to_string=20= (x,=20buf,=20end);=0A+=20=20json_out_str=20(jo,=20p,=20end=20-=20p);=0A= +}=0A+=0A+static=20AVOID=0A+string_not_unicode=20(Lisp_Object=20obj)=0A= +{=0A+=20=20/*=20FIXME:=20for=20test=20compatibility,=20not=20a=20very=20= descriptive=20error=20*/=0A+=20=20wrong_type_argument=20(Qjson_value_p,=20= obj);=0A+}=0A+=0A+static=20unsigned=20char=20json_plain_char[256]=20=3D=20= {=0A+=20=20/*=2032=20chars/line:=201=20for=20printable=20ASCII=20+=20DEL=20= except=20"=20and=20\,=200=20elsewhere=20*/=0A+=20=20= 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,=20/*=20= 00-1f=20*/=0A+=20=20= 1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,=20/*=20= 20-3f=20*/=0A+=20=20= 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,=20/*=20= 40-5f=20*/=0A+=20=20= 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,=20/*=20= 60-7f=20*/=0A+=20=20= 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,=20/*=20= 80-9f=20*/=0A+=20=20= 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,=20/*=20= a0-bf=20*/=0A+=20=20= 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,=20/*=20= c0-df=20*/=0A+=20=20= 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,=20/*=20= e0-ff=20*/=0A=20};=0A=20=0A-static=20Lisp_Object=0A-json_insert=20(void=20= *data)=0A+static=20void=0A+json_out_string=20(json_out_t=20*jo,=20= Lisp_Object=20str,=20int=20skip)=0A=20{=0A-=20=20struct=20= json_buffer_and_size=20*buffer_and_size=20=3D=20data;=0A-=20=20ptrdiff_t=20= len=20=3D=20buffer_and_size->size;=0A-=20=20ptrdiff_t=20inserted_bytes=20= =3D=20buffer_and_size->inserted_bytes;=0A-=20=20ptrdiff_t=20gap_size=20=3D= =20GAP_SIZE=20-=20inserted_bytes;=0A-=0A-=20=20/*=20Enlarge=20the=20gap=20= if=20necessary.=20=20*/=0A-=20=20if=20(gap_size=20<=20len)=0A-=20=20=20=20= make_gap=20(len=20-=20gap_size);=0A-=0A-=20=20/*=20Copy=20this=20chunk=20= of=20data=20into=20the=20gap.=20=20*/=0A-=20=20memcpy=20((char=20*)=20= BEG_ADDR=20+=20PT_BYTE=20-=20BEG_BYTE=20+=20inserted_bytes,=0A-=09=20=20= buffer_and_size->buffer,=20len);=0A-=20=20= buffer_and_size->inserted_bytes=20+=3D=20len;=0A-=20=20return=20Qnil;=0A= +=20=20/*=20FIXME:=20this=20code=20is=20slow,=20make=20faster!=20*/=0A+=0A= +=20=20static=20const=20char=20hexchar[16]=20=3D=20"0123456789ABCDEF";=0A= +=20=20ptrdiff_t=20len=20=3D=20SBYTES=20(str);=0A+=20=20json_make_room=20= (jo,=20len=20+=202);=0A+=20=20json_out_byte=20(jo,=20'"');=0A+=20=20= unsigned=20char=20*p=20=3D=20SDATA=20(str);=0A+=20=20unsigned=20char=20= *end=20=3D=20p=20+=20len;=0A+=20=20p=20+=3D=20skip;=0A+=20=20while=20(p=20= <=20end)=0A+=20=20=20=20{=0A+=20=20=20=20=20=20unsigned=20char=20c=20=3D=20= *p;=0A+=20=20=20=20=20=20if=20(json_plain_char[c])=0A+=09{=0A+=09=20=20= json_out_byte=20(jo,=20c);=0A+=09=20=20p++;=0A+=09}=0A+=20=20=20=20=20=20= else=20if=20(c=20>=200x7f)=0A+=09{=0A+=09=20=20if=20(STRING_MULTIBYTE=20= (str))=0A+=09=20=20=20=20{=0A+=09=20=20=20=20=20=20int=20n;=0A+=09=20=20=20= =20=20=20if=20(c=20<=3D=200xc1)=0A+=09=09string_not_unicode=20(str);=0A+=09= =20=20=20=20=20=20if=20(c=20<=3D=200xdf)=0A+=09=09n=20=3D=202;=0A+=09=20=20= =20=20=20=20else=20if=20(c=20<=3D=200xef)=0A+=09=09{=0A+=09=09=20=20int=20= v=20=3D=20(((c=20&=200x0f)=20<<=2012)=0A+=09=09=09=20=20=20+=20((p[1]=20= &=200x3f)=20<<=206)=20+=20(p[2]=20&=200x3f));=0A+=09=09=20=20if=20= (char_surrogate_p=20(v))=0A+=09=09=20=20=20=20string_not_unicode=20= (str);=0A+=09=09=20=20n=20=3D=203;=0A+=09=09}=0A+=09=20=20=20=20=20=20= else=20if=20(c=20<=3D=200xf7)=0A+=09=09{=0A+=09=09=20=20int=20v=20=3D=20= (((c=20&=200x07)=20<<=2018)=0A+=09=09=09=20=20=20+=20((p[1]=20&=200x3f)=20= <<=2012)=0A+=09=09=09=20=20=20+=20((p[2]=20&=200x3f)=20<<=206)=0A+=09=09=09= =20=20=20+=20(p[3]=20&=200x3f));=0A+=09=09=20=20if=20(v=20>=20= MAX_UNICODE_CHAR)=0A+=09=09=20=20=20=20string_not_unicode=20(str);=0A+=09= =09=20=20n=20=3D=204;=0A+=09=09}=0A+=09=20=20=20=20=20=20else=0A+=09=09= string_not_unicode=20(str);=0A+=09=20=20=20=20=20=20json_out_str=20(jo,=20= (const=20char=20*)p,=20n);=0A+=09=20=20=20=20=20=20jo->chars_delta=20+=3D=20= n=20-=201;=0A+=09=20=20=20=20=20=20p=20+=3D=20n;=0A+=09=20=20=20=20}=0A+=09= =20=20else=0A+=09=20=20=20=20string_not_unicode=20(str);=0A+=09}=0A+=20=20= =20=20=20=20else=0A+=09{=0A+=09=20=20json_out_byte=20(jo,=20'\\');=0A+=09= =20=20switch=20(c)=0A+=09=20=20=20=20{=0A+=09=20=20=20=20case=20'"':=0A+=09= =20=20=20=20case=20'\\':=20json_out_byte=20(jo,=20c);=20break;=0A+=09=20=20= =20=20case=20'\b':=20json_out_byte=20(jo,=20'b');=20break;=0A+=09=20=20=20= =20case=20'\t':=20json_out_byte=20(jo,=20't');=20break;=0A+=09=20=20=20=20= case=20'\n':=20json_out_byte=20(jo,=20'n');=20break;=0A+=09=20=20=20=20= case=20'\f':=20json_out_byte=20(jo,=20'f');=20break;=0A+=09=20=20=20=20= case=20'\r':=20json_out_byte=20(jo,=20'r');=20break;=0A+=09=20=20=20=20= default:=0A+=09=20=20=20=20=20=20{=0A+=09=09char=20hex[5]=20=3D=20{=20= 'u',=20'0',=20'0',=0A+=09=09=09=09hexchar[c=20>>=204],=20hexchar[c=20&=20= 0xf]=20};=0A+=09=09json_out_str=20(jo,=20hex,=205);=0A+=09=09break;=0A+=09= =20=20=20=20=20=20}=0A+=09=20=20=20=20}=0A+=09=20=20p++;=0A+=09}=0A+=20=20= =20=20}=0A+=20=20json_out_byte=20(jo,=20'"');=0A=20}=0A=20=0A-static=20= Lisp_Object=0A-json_handle_nonlocal_exit=20(enum=20nonlocal_exit=20type,=20= Lisp_Object=20data)=0A+static=20void=0A+json_out_nest=20(json_out_t=20= *jo)=0A+{=0A+=20=20--jo->maxdepth;=0A+=20=20if=20(jo->maxdepth=20<=200)=0A= +=20=20=20=20error=20("Maximum=20JSON=20serialisation=20depth=20= exceeded");=0A+}=0A+=0A+static=20void=0A+json_out_unnest=20(json_out_t=20= *jo)=0A=20{=0A-=20=20switch=20(type)=0A+=20=20++jo->maxdepth;=0A+}=0A+=0A= +static=20void=20json_out_something=20(json_out_t=20*jo,=20Lisp_Object=20= obj);=0A+=0A+static=20void=0A+json_out_object_cons=20(json_out_t=20*jo,=20= Lisp_Object=20obj)=0A+{=0A+=20=20json_out_nest=20(jo);=0A+=20=20symset_t=20= ss=20=3D=20push_symset=20(jo);=0A+=20=20json_out_byte=20(jo,=20'{');=0A+=20= =20bool=20is_alist=20=3D=20CONSP=20(XCAR=20(obj));=0A+=20=20bool=20first=20= =3D=20true;=0A+=20=20Lisp_Object=20tail=20=3D=20obj;=0A+=20=20= FOR_EACH_TAIL=20(tail)=0A=20=20=20=20=20{=0A-=20=20=20=20case=20= NONLOCAL_EXIT_SIGNAL:=0A-=20=20=20=20=20=20return=20data;=0A-=20=20=20=20= case=20NONLOCAL_EXIT_THROW:=0A-=20=20=20=20=20=20return=20Fcons=20= (Qno_catch,=20data);=0A-=20=20=20=20default:=0A-=20=20=20=20=20=20= eassume=20(false);=0A+=20=20=20=20=20=20Lisp_Object=20key;=0A+=20=20=20=20= =20=20Lisp_Object=20value;=0A+=20=20=20=20=20=20if=20(is_alist)=0A+=09{=0A= +=09=20=20Lisp_Object=20pair=20=3D=20XCAR=20(tail);=0A+=09=20=20= CHECK_CONS=20(pair);=0A+=09=20=20key=20=3D=20XCAR=20(pair);=0A+=09=20=20= value=20=3D=20XCDR=20(pair);=0A+=09}=0A+=20=20=20=20=20=20else=0A+=09{=0A= +=09=20=20key=20=3D=20XCAR=20(tail);=0A+=09=20=20tail=20=3D=20XCDR=20= (tail);=0A+=09=20=20CHECK_CONS=20(tail);=0A+=09=20=20value=20=3D=20XCAR=20= (tail);=0A+=09}=0A+=20=20=20=20=20=20key=20=3D=20= maybe_remove_pos_from_symbol=20(key);=0A+=20=20=20=20=20=20CHECK_TYPE=20= (BARE_SYMBOL_P=20(key),=20Qsymbolp,=20key);=0A+=0A+=20=20=20=20=20=20if=20= (symset_add=20(jo,=20&ss,=20key))=0A+=09{=0A+=09=20=20if=20(!first)=0A+=09= =20=20=20=20json_out_byte=20(jo,=20',');=0A+=09=20=20first=20=3D=20= false;=0A+=0A+=09=20=20Lisp_Object=20key_str=20=3D=20SYMBOL_NAME=20= (key);=0A+=09=20=20const=20char=20*str=20=3D=20SSDATA=20(key_str);=0A+=09= =20=20/*=20Skip=20leading=20':'=20in=20plist=20keys.=20=20*/=0A+=09=20=20= int=20skip=20=3D=20!is_alist=20&&=20str[0]=20=3D=3D=20':'=20&&=20str[1]=20= ?=201=20:=200;=0A+=09=20=20json_out_string=20(jo,=20key_str,=20skip);=0A= +=09=20=20json_out_byte=20(jo,=20':');=0A+=09=20=20json_out_something=20= (jo,=20value);=0A+=09}=0A+=20=20=20=20}=0A+=20=20CHECK_LIST_END=20(tail,=20= obj);=0A+=20=20json_out_byte=20(jo,=20'}');=0A+=20=20pop_symset=20(jo,=20= &ss);=0A+=20=20json_out_unnest=20(jo);=0A+}=0A+=0A+static=20void=0A= +json_out_object_hash=20(json_out_t=20*jo,=20Lisp_Object=20obj)=0A+{=0A+=20= =20json_out_nest=20(jo);=0A+=20=20json_out_byte=20(jo,=20'{');=0A+=20=20= struct=20Lisp_Hash_Table=20*h=20=3D=20XHASH_TABLE=20(obj);=0A+=20=20bool=20= first=20=3D=20true;=0A+=20=20DOHASH=20(h,=20k,=20v)=0A+=20=20=20=20{=0A+=20= =20=20=20=20=20if=20(!first)=0A+=09json_out_byte=20(jo,=20',');=0A+=20=20= =20=20=20=20first=20=3D=20false;=0A+=20=20=20=20=20=20/*=20FIXME:=20do=20= we=20care=20about=20dup=20keys=20here?=20(probably=20not)=20*/=0A+=20=20=20= =20=20=20CHECK_STRING=20(k);=0A+=20=20=20=20=20=20json_out_string=20(jo,=20= k,=200);=0A+=20=20=20=20=20=20json_out_byte=20(jo,=20':');=0A+=20=20=20=20= =20=20json_out_something=20(jo,=20v);=0A=20=20=20=20=20}=0A+=20=20= json_out_byte=20(jo,=20'}');=0A+=20=20json_out_unnest=20(jo);=0A+=0A=20}=0A= =20=0A-struct=20json_insert_data=0A+static=20void=0A+json_out_array=20= (json_out_t=20*jo,=20Lisp_Object=20obj)=0A=20{=0A-=20=20/*=20This=20= tracks=20how=20many=20bytes=20were=20inserted=20by=20the=20callback=20= since=0A-=20=20=20=20=20json_dump_callback=20was=20called.=20=20*/=0A-=20= =20ptrdiff_t=20inserted_bytes;=0A-=20=20/*=20nil=20if=20json_insert=20= succeeded,=20otherwise=20the=20symbol=0A-=20=20=20=20=20= Qcatch_all_memory_full=20or=20a=20cons=20(ERROR-SYMBOL=20.=20= ERROR-DATA).=20=20*/=0A-=20=20Lisp_Object=20error;=0A-};=0A+=20=20= json_out_nest=20(jo);=0A+=20=20json_out_byte=20(jo,=20'[');=0A+=20=20= ptrdiff_t=20n=20=3D=20ASIZE=20(obj);=0A+=20=20for=20(ptrdiff_t=20i=20=3D=20= 0;=20i=20<=20n;=20i++)=0A+=20=20=20=20{=0A+=20=20=20=20=20=20if=20(i=20>=20= 0)=0A+=09json_out_byte=20(jo,=20',');=0A+=20=20=20=20=20=20= json_out_something=20(jo,=20AREF=20(obj,=20i));=0A+=20=20=20=20}=0A+=20=20= json_out_byte=20(jo,=20']');=0A+=20=20json_out_unnest=20(jo);=0A+}=0A=20=0A= -/*=20Callback=20for=20json_dump_callback=20that=20inserts=20a=20JSON=20= representation=0A-=20=20=20as=20a=20unibyte=20string=20into=20the=20gap.=20= =20DATA=20must=20point=20to=20a=20structure=0A-=20=20=20of=20type=20= json_insert_data.=20=20This=20function=20may=20not=20exit=20nonlocally.=0A= -=20=20=20It=20catches=20all=20nonlocal=20exits=20and=20stores=20them=20= in=20data->error=20for=0A-=20=20=20reraising.=20=20*/=0A+static=20void=0A= +json_out_float=20(json_out_t=20*jo,=20Lisp_Object=20f)=0A+{=0A+=20=20= double=20x=20=3D=20XFLOAT_DATA=20(f);=0A+=20=20if=20(isinf=20(x)=20||=20= isnan=20(x))=0A+=20=20=20=20signal_error=20("not=20a=20finite=20number",=20= f);=0A+=20=20json_make_room=20(jo,=20FLOAT_TO_STRING_BUFSIZE);=0A+=20=20= int=20n=20=3D=20float_to_string=20(jo->buf=20+=20jo->size,=20x);=0A+=20=20= jo->size=20+=3D=20n;=0A+}=0A=20=0A-static=20int=0A-json_insert_callback=20= (const=20char=20*buffer,=20size_t=20size,=20void=20*data)=0A+static=20= void=0A+json_out_bignum=20(json_out_t=20*jo,=20Lisp_Object=20x)=0A=20{=0A= -=20=20struct=20json_insert_data=20*d=20=3D=20data;=0A-=20=20struct=20= json_buffer_and_size=20buffer_and_size=0A-=20=20=20=20=3D=20{.buffer=20=3D= =20buffer,=20.size=20=3D=20size,=20.inserted_bytes=20=3D=20= d->inserted_bytes};=0A-=20=20d->error=20=3D=20internal_catch_all=20= (json_insert,=20&buffer_and_size,=0A-=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= json_handle_nonlocal_exit);=0A-=20=20d->inserted_bytes=20=3D=20= buffer_and_size.inserted_bytes;=0A-=20=20return=20NILP=20(d->error)=20?=20= 0=20:=20-1;=0A+=20=20int=20base=20=3D=2010;=0A+=20=20ptrdiff_t=20size=20= =3D=20bignum_bufsize=20(x,=20base);=0A+=20=20json_make_room=20(jo,=20= size);=0A+=20=20int=20n=20=3D=20bignum_to_c_string=20(jo->buf=20+=20= jo->size,=20size,=20x,=20base);=0A+=20=20jo->size=20+=3D=20n;=0A+}=0A+=0A= +static=20void=0A+json_out_something=20(json_out_t=20*jo,=20Lisp_Object=20= obj)=0A+{=0A+=20=20if=20(EQ=20(obj,=20jo->conf.null_object))=0A+=20=20=20= =20JSON_OUT_STR=20(jo,=20"null");=0A+=20=20else=20if=20(EQ=20(obj,=20= jo->conf.false_object))=0A+=20=20=20=20JSON_OUT_STR=20(jo,=20"false");=0A= +=20=20else=20if=20(EQ=20(obj,=20Qt))=0A+=20=20=20=20JSON_OUT_STR=20(jo,=20= "true");=0A+=20=20else=20if=20(NILP=20(obj))=0A+=20=20=20=20JSON_OUT_STR=20= (jo,=20"{}");=0A+=20=20else=20if=20(FIXNUMP=20(obj))=0A+=20=20=20=20= json_out_fixnum=20(jo,=20XFIXNUM=20(obj));=0A+=20=20else=20if=20(STRINGP=20= (obj))=0A+=20=20=20=20json_out_string=20(jo,=20obj,=200);=0A+=20=20else=20= if=20(CONSP=20(obj))=0A+=20=20=20=20json_out_object_cons=20(jo,=20obj);=0A= +=20=20else=20if=20(FLOATP=20(obj))=0A+=20=20=20=20json_out_float=20(jo,=20= obj);=0A+=20=20else=20if=20(HASH_TABLE_P=20(obj))=0A+=20=20=20=20= json_out_object_hash=20(jo,=20obj);=0A+=20=20else=20if=20(VECTORP=20= (obj))=0A+=20=20=20=20json_out_array=20(jo,=20obj);=0A+=20=20else=20if=20= (BIGNUMP=20(obj))=0A+=20=20=20=20json_out_bignum=20(jo,=20obj);=0A+=20=20= else=0A+=20=20=20=20wrong_type_argument=20(Qjson_value_p,=20obj);=0A+}=0A= +=0A+static=20Lisp_Object=0A+json_out_string_result=20(json_out_t=20*jo)=0A= +{=0A+=20=20/*=20FIXME:=20should=20this=20be=20a=20unibyte=20or=20= multibyte=20string?=0A+=20=20=20=20=20Right=20now=20we=20make=20a=20= multibyte=20string=20for=20test=20compatibility,=0A+=20=20=20=20=20but=20= we=20are=20really=20encoding=20so=20unibyte=20would=20make=20more=20= sense.=20=20*/=0A+=20=20ptrdiff_t=20nchars=20=3D=20jo->size=20-=20= jo->chars_delta;=0A+=20=20return=20make_multibyte_string=20(jo->buf,=20= nchars,=20jo->size);=0A+}=0A+=0A+DEFUN=20("json-serialize",=20= Fjson_serialize,=20Sjson_serialize,=201,=20MANY,=0A+=20=20=20=20=20=20=20= NULL,=0A+=20=20=20=20=20=20=20doc:=20/*=20Return=20the=20JSON=20= representation=20of=20OBJECT=20as=20a=20string.=0A+=0A+OBJECT=20must=20= be=20t,=20a=20number,=20string,=20vector,=20hashtable,=20alist,=20plist,=0A= +or=20the=20Lisp=20equivalents=20to=20the=20JSON=20null=20and=20false=20= values,=20and=20its=0A+elements=20must=20recursively=20consist=20of=20= the=20same=20kinds=20of=20values.=20=20t=20will=0A+be=20converted=20to=20= the=20JSON=20true=20value.=20=20Vectors=20will=20be=20converted=20to=0A= +JSON=20arrays,=20whereas=20hashtables,=20alists=20and=20plists=20are=20= converted=20to=0A+JSON=20objects.=20=20Hashtable=20keys=20must=20be=20= strings=20and=20must=20be=20unique=20within=0A+each=20object.=20=20Alist=20= and=20plist=20keys=20must=20be=20symbols;=20if=20a=20key=20is=20= duplicate,=0A+the=20first=20instance=20is=20used.=0A+=0A+The=20Lisp=20= equivalents=20to=20the=20JSON=20null=20and=20false=20values=20are=0A= +configurable=20in=20the=20arguments=20ARGS,=20a=20list=20of=20= keyword/argument=20pairs:=0A+=0A+The=20keyword=20argument=20= `:null-object'=20specifies=20which=20object=20to=20use=0A+to=20represent=20= a=20JSON=20null=20value.=20=20It=20defaults=20to=20`:null'.=0A+=0A+The=20= keyword=20argument=20`:false-object'=20specifies=20which=20object=20to=20= use=20to=0A+represent=20a=20JSON=20false=20value.=20=20It=20defaults=20= to=20`:false'.=0A+=0A+In=20you=20specify=20the=20same=20value=20for=20= `:null-object'=20and=20`:false-object',=0A+a=20potentially=20ambiguous=20= situation,=20the=20JSON=20output=20will=20not=20contain=0A+any=20JSON=20= false=20values.=0A+usage:=20(json-serialize=20OBJECT=20&rest=20ARGS)=20=20= */)=0A+=20=20=20=20=20(ptrdiff_t=20nargs,=20Lisp_Object=20*args)=0A+{=0A= +=20=20json_out_t=20jo=20=3D=20{=0A+=20=20=20=20.maxdepth=20=3D=2025,=0A= +=20=20=20=20.conf=20=3D=20{json_object_hashtable,=20json_array_array,=20= QCnull,=20QCfalse}=0A+=20=20};=0A+=20=20json_parse_args=20(nargs=20-=20= 1,=20args=20+=201,=20&jo.conf,=20false);=0A+=20=20Lisp_Object=20object=20= =3D=20args[0];=0A+=0A+=20=20specpdl_ref=20count=20=3D=20SPECPDL_INDEX=20= ();=0A+=20=20record_unwind_protect_ptr=20(cleanup_json_out,=20&jo);=0A+=20= =20json_out_something=20(&jo,=20object);=0A+=20=20return=20unbind_to=20= (count,=20json_out_string_result=20(&jo));=0A=20}=0A=20=0A=20DEFUN=20= ("json-insert",=20Fjson_insert,=20Sjson_insert,=201,=20MANY,=0A@@=20= -714,72=20+890,61=20@@=20DEFUN=20("json-insert",=20Fjson_insert,=20= Sjson_insert,=201,=20MANY,=0A=20usage:=20(json-insert=20OBJECT=20&rest=20= ARGS)=20=20*/)=0A=20=20=20=20=20=20(ptrdiff_t=20nargs,=20Lisp_Object=20= *args)=0A=20{=0A-=20=20specpdl_ref=20count=20=3D=20SPECPDL_INDEX=20();=0A= +=20=20json_out_t=20jo=20=3D=20{=0A+=20=20=20=20.maxdepth=20=3D=2025,=0A= +=20=20=20=20.conf=20=3D=20{json_object_hashtable,=20json_array_array,=20= QCnull,=20QCfalse}=0A+=20=20};=0A+=20=20json_parse_args=20(nargs=20-=20= 1,=20args=20+=201,=20&jo.conf,=20false);=0A+=20=20Lisp_Object=20object=20= =3D=20args[0];=0A=20=0A-#ifdef=20WINDOWSNT=0A-=20=20= ensure_json_available=20();=0A-#endif=0A-=0A-=20=20struct=20= json_configuration=20conf=20=3D=0A-=20=20=20=20{json_object_hashtable,=20= json_array_array,=20QCnull,=20QCfalse};=0A-=20=20json_parse_args=20= (nargs=20-=201,=20args=20+=201,=20&conf,=20false);=0A+=20=20specpdl_ref=20= count=20=3D=20SPECPDL_INDEX=20();=0A+=20=20record_unwind_protect_ptr=20= (cleanup_json_out,=20&jo);=0A+=20=20json_out_something=20(&jo,=20= object);=0A=20=0A-=20=20json_t=20*json=20=3D=20lisp_to_json=20(args[0],=20= &conf);=0A-=20=20record_unwind_protect_ptr=20(json_release_object,=20= json);=0A+=20=20/*=20FIXME:=20Do=20we=20really=20need=20to=20do=20all=20= this=20work=20below=20to=20insert=20a=20string?=0A+=20=20=20=20=20Is=20= there=20no=20function=20already=20written?=20=20I=20must=20be=20missing=20= something.=20=20*/=0A=20=0A=20=20=20prepare_to_modify_buffer=20(PT,=20= PT,=20NULL);=0A=20=20=20move_gap_both=20(PT,=20PT_BYTE);=0A-=20=20struct=20= json_insert_data=20data;=0A-=20=20data.inserted_bytes=20=3D=200;=0A-=20=20= /*=20Could=20have=20used=20json_dumpb,=20but=20that=20became=20available=20= only=20in=0A-=20=20=20=20=20Jansson=202.10,=20whereas=20we=20want=20to=20= support=202.7=20and=20upward.=20=20*/=0A-=20=20int=20status=20=3D=20= json_dump_callback=20(json,=20json_insert_callback,=20&data,=0A-=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20JSON_COMPACT=20|=20JSON_ENCODE_ANY);=0A-=20=20if=20= (status=20=3D=3D=20-1)=0A-=20=20=20=20{=0A-=20=20=20=20=20=20if=20(CONSP=20= (data.error))=0A-=20=20=20=20=20=20=20=20xsignal=20(XCAR=20(data.error),=20= XCDR=20(data.error));=0A-=20=20=20=20=20=20else=0A-=20=20=20=20=20=20=20=20= json_out_of_memory=20();=0A-=20=20=20=20}=0A+=20=20if=20(GAP_SIZE=20<=20= jo.size)=0A+=20=20=20=20make_gap=20(jo.size=20-=20GAP_SIZE);=0A+=20=20= memcpy=20((char=20*)=20BEG_ADDR=20+=20PT_BYTE=20-=20BEG_BYTE,=20jo.buf,=20= jo.size);=0A+=0A+=20=20/*=20No=20need=20to=20keep=20allocation=20beyond=20= this=20point.=20=20*/=0A+=20=20unbind_to=20(count,=20Qnil);=0A=20=0A=20=20= =20ptrdiff_t=20inserted=20=3D=200;=0A-=20=20ptrdiff_t=20inserted_bytes=20= =3D=20data.inserted_bytes;=0A-=20=20if=20(inserted_bytes=20>=200)=0A+=20=20= ptrdiff_t=20inserted_bytes=20=3D=20jo.size;=0A+=0A+=20=20/*=20If=20= required,=20decode=20the=20stuff=20we've=20read=20into=20the=20gap.=20=20= */=0A+=20=20struct=20coding_system=20coding;=0A+=20=20/*=20JSON=20= strings=20are=20UTF-8=20encoded=20strings.=20=20*/=0A+=20=20= setup_coding_system=20(Qutf_8_unix,=20&coding);=0A+=20=20= coding.dst_multibyte=20=3D=20!NILP=20(BVAR=20(current_buffer,=0A+=09=09=09= =09=20=20=20=20=20=20enable_multibyte_characters));=0A+=20=20if=20= (CODING_MAY_REQUIRE_DECODING=20(&coding))=0A=20=20=20=20=20{=0A-=20=20=20= =20=20=20/*=20If=20required,=20decode=20the=20stuff=20we've=20read=20= into=20the=20gap.=20=20*/=0A-=20=20=20=20=20=20struct=20coding_system=20= coding;=0A-=20=20=20=20=20=20/*=20JSON=20strings=20are=20UTF-8=20encoded=20= strings.=20=20If=20for=20some=20reason=0A-=09=20the=20text=20returned=20= by=20the=20Jansson=20library=20includes=20invalid=0A-=09=20byte=20= sequences,=20they=20will=20be=20represented=20by=20raw=20bytes=20in=20= the=0A-=09=20buffer=20text.=20=20*/=0A-=20=20=20=20=20=20= setup_coding_system=20(Qutf_8_unix,=20&coding);=0A-=20=20=20=20=20=20= coding.dst_multibyte=20=3D=0A-=09!NILP=20(BVAR=20(current_buffer,=20= enable_multibyte_characters));=0A-=20=20=20=20=20=20if=20= (CODING_MAY_REQUIRE_DECODING=20(&coding))=0A-=09{=0A-=20=20=20=20=20=20=20= =20=20=20/*=20Now=20we=20have=20all=20the=20new=20bytes=20at=20the=20= beginning=20of=20the=20gap,=0A-=20=20=20=20=20=20=20=20=20=20=20=20=20= but=20`decode_coding_gap`=20needs=20them=20at=20the=20end=20of=20the=20= gap,=20so=0A-=20=20=20=20=20=20=20=20=20=20=20=20=20we=20need=20to=20= move=20them.=20=20*/=0A-=20=20=20=20=20=20=20=20=20=20memmove=20= (GAP_END_ADDR=20-=20inserted_bytes,=20GPT_ADDR,=20inserted_bytes);=0A-=09= =20=20decode_coding_gap=20(&coding,=20inserted_bytes);=0A-=09=20=20= inserted=20=3D=20coding.produced_char;=0A-=09}=0A-=20=20=20=20=20=20else=0A= -=09{=0A-=20=20=20=20=20=20=20=20=20=20/*=20Make=20the=20inserted=20text=20= part=20of=20the=20buffer,=20as=20unibyte=20text.=20=20*/=0A-=20=20=20=20=20= =20=20=20=20=20eassert=20(NILP=20(BVAR=20(current_buffer,=20= enable_multibyte_characters)));=0A-=20=20=20=20=20=20=20=20=20=20= insert_from_gap_1=20(inserted_bytes,=20inserted_bytes,=20false);=0A-=0A-=09= =20=20/*=20The=20target=20buffer=20is=20unibyte,=20so=20we=20don't=20= need=20to=20decode.=20=20*/=0A-=09=20=20invalidate_buffer_caches=20= (current_buffer,=0A-=09=09=09=09=20=20=20=20PT,=20PT=20+=20= inserted_bytes);=0A-=09=20=20adjust_after_insert=20(PT,=20PT_BYTE,=0A-=09= =09=09=20=20=20=20=20=20=20PT=20+=20inserted_bytes,=0A-=09=09=09=20=20=20= =20=20=20=20PT_BYTE=20+=20inserted_bytes,=0A-=09=09=09=20=20=20=20=20=20=20= inserted_bytes);=0A-=09=20=20inserted=20=3D=20inserted_bytes;=0A-=09}=0A= +=20=20=20=20=20=20/*=20Now=20we=20have=20all=20the=20new=20bytes=20at=20= the=20beginning=20of=20the=20gap,=0A+=09=20but=20`decode_coding_gap`=20= needs=20them=20at=20the=20end=20of=20the=20gap,=20so=0A+=09=20we=20need=20= to=20move=20them.=20=20*/=0A+=20=20=20=20=20=20memmove=20(GAP_END_ADDR=20= -=20inserted_bytes,=20GPT_ADDR,=20inserted_bytes);=0A+=20=20=20=20=20=20= decode_coding_gap=20(&coding,=20inserted_bytes);=0A+=20=20=20=20=20=20= inserted=20=3D=20coding.produced_char;=0A+=20=20=20=20}=0A+=20=20else=0A= +=20=20=20=20{=0A+=20=20=20=20=20=20/*=20Make=20the=20inserted=20text=20= part=20of=20the=20buffer,=20as=20unibyte=20text.=20=20*/=0A+=20=20=20=20=20= =20eassert=20(NILP=20(BVAR=20(current_buffer,=20= enable_multibyte_characters)));=0A+=20=20=20=20=20=20insert_from_gap_1=20= (inserted_bytes,=20inserted_bytes,=20false);=0A+=0A+=20=20=20=20=20=20/*=20= The=20target=20buffer=20is=20unibyte,=20so=20we=20don't=20need=20to=20= decode.=20=20*/=0A+=20=20=20=20=20=20invalidate_buffer_caches=20= (current_buffer,=0A+=09=09=09=09PT,=20PT=20+=20inserted_bytes);=0A+=20=20= =20=20=20=20adjust_after_insert=20(PT,=20PT_BYTE,=0A+=09=09=09=20=20=20= PT=20+=20inserted_bytes,=0A+=09=09=09=20=20=20PT_BYTE=20+=20= inserted_bytes,=0A+=09=09=09=20=20=20inserted_bytes);=0A+=20=20=20=20=20=20= inserted=20=3D=20inserted_bytes;=0A=20=20=20=20=20}=0A=20=0A=20=20=20/*=20= Call=20after-change=20hooks.=20=20*/=0A@@=20-791,7=20+956,7=20@@=20DEFUN=20= ("json-insert",=20Fjson_insert,=20Sjson_insert,=201,=20MANY,=0A=20=20=20=20= =20=20=20SET_PT_BOTH=20(PT=20+=20inserted,=20PT_BYTE=20+=20= inserted_bytes);=0A=20=20=20=20=20}=0A=20=0A-=20=20return=20unbind_to=20= (count,=20Qnil);=0A+=20=20return=20Qnil;=0A=20}=0A=20=0A=20/*=20Convert=20= a=20JSON=20object=20to=20a=20Lisp=20object.=20=20*/=0Adiff=20--git=20= a/test/src/json-tests.el=20b/test/src/json-tests.el=0Aindex=20= dffc6291ca1..351d909f05b=20100644=0A---=20a/test/src/json-tests.el=0A+++=20= b/test/src/json-tests.el=0A@@=20-126,11=20+126,38=20@@=20= json-serialize/object=0A=20=0A=20(ert-deftest=20= json-serialize/object-with-duplicate-keys=20()=0A=20=20=20(skip-unless=20= (fboundp=20'json-serialize))=0A-=20=20(let=20((table=20(make-hash-table=20= :test=20#'eq)))=0A-=20=20=20=20(puthash=20(copy-sequence=20"abc")=20[1=20= 2=20t]=20table)=0A-=20=20=20=20(puthash=20(copy-sequence=20"abc")=20= :null=20table)=0A-=20=20=20=20(should=20(equal=20(hash-table-count=20= table)=202))=0A-=20=20=20=20(should-error=20(json-serialize=20table)=20= :type=20'wrong-type-argument)))=0A+=0A+=20=20(dolist=20(n=20'(1=205=2020=20= 100))=0A+=20=20=20=20(let=20((symbols=20(mapcar=20(lambda=20(i)=20= (make-symbol=20(format=20"s%d"=20i)))=0A+=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(number-sequence=201=20= n)))=0A+=20=20=20=20=20=20=20=20=20=20(expected=20(concat=20"{"=0A+=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20(mapconcat=20(lambda=20(i)=20(format=20"\"s%d\":%d"=20i=20i))=0A+=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20(number-sequence=201=20n)=20",")=0A+=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20"}")))=0A+=20=20=20=20=20=20;;=20alist=0A+=20=20=20=20=20=20= (should=20(equal=20(json-serialize=0A+=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20(append=0A+=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20(cl-mapcar=20#'cons=0A+=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20symbols=20(number-sequence=201=20n))=0A+=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(cl-mapcar=20#'cons=0A+=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20symbols=20(number-sequence=201001=20(+=201000=20= n)))))=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= expected))=0A+=20=20=20=20=20=20;;=20plist=0A+=20=20=20=20=20=20(should=20= (equal=20(json-serialize=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20(append=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20(cl-mapcan=20#'list=0A+=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20symbols=20(number-sequence=201=20n))=0A+=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20(cl-mapcan=20#'list=0A+=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20symbols=20(number-sequence=201001=20(+=201000=20n)))))=0A= +=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= expected))))=0A+=0A+=20=20;;=20We=20don't=20check=20for=20duplicated=20= keys=20in=20hash=20tables.=0A+=20=20;;=20(let=20((table=20= (make-hash-table=20:test=20#'eq)))=0A+=20=20;;=20=20=20(puthash=20= (copy-sequence=20"abc")=20[1=202=20t]=20table)=0A+=20=20;;=20=20=20= (puthash=20(copy-sequence=20"abc")=20:null=20table)=0A+=20=20;;=20=20=20= (should=20(equal=20(hash-table-count=20table)=202))=0A+=20=20;;=20=20=20= (should-error=20(json-serialize=20table)=20:type=20= 'wrong-type-argument))=0A+=20=20)=0A=20=0A=20(ert-deftest=20= json-parse-string/object=20()=0A=20=20=20(skip-unless=20(fboundp=20= 'json-parse-string))=0A@@=20-174,7=20+201,10=20@@=20= json-serialize/string=0A=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20"[\"\\nasd=D1=84=D1=8B=D0=B2\\u001F\u007ffgh\\t\"]"))=0A=20=20=20= (should=20(equal=20(json-serialize=20["a\0b"])=20"[\"a\\u0000b\"]"))=0A=20= =20=20;;=20FIXME:=20Is=20this=20the=20right=20behavior?=0A-=20=20(should=20= (equal=20(json-serialize=20["\u00C4\xC3\x84"])=20"[\"\u00C4\u00C4\"]")))=0A= +=20=20;;=20FIXME:=20(no=20it's=20not)=0A+=20=20;;=20(should=20(equal=20= (json-serialize=20["\u00C4\xC3\x84"])=20"[\"\u00C4\u00C4\"]"))=0A+=20=20= (should-error=20(json-serialize=20["\u00C4\xC3\x84"]))=0A+=20=20)=0A=20=0A= =20(ert-deftest=20json-serialize/invalid-unicode=20()=0A=20=20=20= (skip-unless=20(fboundp=20'json-serialize))=0A= --Apple-Mail=_E4201434-B8C0-4597-91DC-3456766FB664-- From unknown Sun Jun 15 14:44:57 2025 X-Loop: help-debbugs@gnu.org Subject: bug#70007: [PATCH] native JSON encoder Resent-From: Eli Zaretskii Original-Sender: "Debbugs-submit" Resent-CC: bug-gnu-emacs@gnu.org Resent-Date: Wed, 27 Mar 2024 17:42:02 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 70007 X-GNU-PR-Package: emacs X-GNU-PR-Keywords: patch To: Mattias =?UTF-8?Q?Engdeg=C3=A5rd?= , Yuan Fu Cc: 70007@debbugs.gnu.org Received: via spool by 70007-submit@debbugs.gnu.org id=B70007.171156127219201 (code B ref 70007); Wed, 27 Mar 2024 17:42:02 +0000 Received: (at 70007) by debbugs.gnu.org; 27 Mar 2024 17:41:12 +0000 Received: from localhost ([127.0.0.1]:38330 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1rpXGy-0004zc-1a for submit@debbugs.gnu.org; Wed, 27 Mar 2024 13:41:12 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:54384) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1rpXGv-0004z2-8D for 70007@debbugs.gnu.org; Wed, 27 Mar 2024 13:41:10 -0400 Received: from fencepost.gnu.org ([2001:470:142:3::e]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1rpXGp-00049j-Lw; Wed, 27 Mar 2024 13:41:03 -0400 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=gnu.org; s=fencepost-gnu-org; h=MIME-version:References:Subject:In-Reply-To:To:From: Date; bh=9lKA/lbeTmHfzoDN2Q3IdM36nHNW+nHMueGQJfW9b8M=; b=K00PW1IB/eSdtCrA1h6y nazFcV/1puV2UYZq+2XqMTUqAepcFJL76DbmU81ihpGJAmJ2kLfPiv/qZoclpKOLJKypZTE7DR6iU Q3X/eICqWqyL/jqfPwISLj6n7qNDxZwhexXoX+n0yZ0/S7ymRAT2L3Q+gPoQpA6UneGC56KA3Ld2C YJiJC3Ztyhe+DxogqxW90ooYPXmIziF1c7cV8gTzPzKPoCIpzrrXvKIvsyHacEqqz4fCnSfhtNZww 4fgtMGyQiHUgbf46sFRNCtLuLE3itL83aRULYi1xl+uBgnkDcbvLG7EZFVIJYwIFtTDzUT6Hb3ca9 0xutc4SXGULxNQ==; Date: Wed, 27 Mar 2024 19:40:59 +0200 Message-Id: <864jcrindg.fsf@gnu.org> From: Eli Zaretskii In-Reply-To: <4589243D-C11A-45C1-AF3E-6F4A5BADEB54@gmail.com> (message from Mattias =?UTF-8?Q?Engdeg=C3=A5rd?= on Wed, 27 Mar 2024 16:49:53 +0100) References: <1BF559D1-DB9F-4FEB-90ED-72E0EFD76424@gmail.com> <86wmpphrg7.fsf@gnu.org> <4589243D-C11A-45C1-AF3E-6F4A5BADEB54@gmail.com> MIME-version: 1.0 Content-type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Spam-Score: -2.3 (--) X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -3.3 (---) > From: Mattias EngdegÃ¥rd > Date: Wed, 27 Mar 2024 16:49:53 +0100 > Cc: 70007@debbugs.gnu.org > > Here is an updated patch. It now ignores duplicated keys in objects represented by alists and plists, just like the old encoder. (I didn't include this in the first draft out of fear it would be slow and complicated, but it turned out just to be complicated.) > > The performance is still acceptable, which means at least 2x the speed of the Jansson-based encoder. Thanks. A few initial comments and questions, based on a very cursory reading. > +/* JSON encoding context */ This is not our comment style. > +typedef struct { > + char *buf; > + ptrdiff_t size; /* number of bytes in buf */ > + ptrdiff_t capacity; /* allocated size of buf */ > + ptrdiff_t chars_delta; /* size - {number of Unicode chars in buf} */ When you say "Unicode chars", what do you mean? characters or bytes? If characters, then why do you need to qualify them with "Unicode"? > +struct symset_tbl > +{ > + /* Table used by the containing object if any, so that we can easily > + all tables if an error occurs. */ > + struct symset_tbl *up; > + /* Table of symbols (2**bits entries), Qunbound where unused. */ > + Lisp_Object entries[]; ^^ Is this portable enough? > +static struct symset_tbl * > +alloc_symset_table (int bits) > +{ > + struct symset_tbl *st = xmalloc (sizeof *st + (sizeof *st->entries << bits)); > + int size = 1 << bits; I'd add an assertion here that BITS is not large enough to produce zero. > +/* Enlarge the table used by a symset. */ ^^ Two spaces there, please. > +static NO_INLINE void > +symset_expand (symset_t *ss) > +{ > + struct symset_tbl *old_table = ss->table; > + int oldbits = ss->bits; > + int oldsize = 1 << oldbits; I'd add an assertion here about the magnitude of BITS. > + while (p < end) > + { > + unsigned char c = *p; > + if (json_plain_char[c]) > + { > + json_out_byte (jo, c); > + p++; > + } > + else if (c > 0x7f) > + { > + if (STRING_MULTIBYTE (str)) > + { > + int n; > + if (c <= 0xc1) > + string_not_unicode (str); > + if (c <= 0xdf) > + n = 2; > + else if (c <= 0xef) > + { > + int v = (((c & 0x0f) << 12) > + + ((p[1] & 0x3f) << 6) + (p[2] & 0x3f)); > + if (char_surrogate_p (v)) > + string_not_unicode (str); > + n = 3; > + } > + else if (c <= 0xf7) > + { > + int v = (((c & 0x07) << 18) > + + ((p[1] & 0x3f) << 12) > + + ((p[2] & 0x3f) << 6) > + + (p[3] & 0x3f)); > + if (v > MAX_UNICODE_CHAR) > + string_not_unicode (str); > + n = 4; > + } > + else > + string_not_unicode (str); > + json_out_str (jo, (const char *)p, n); > + jo->chars_delta += n - 1; > + p += n; > + } > + else > + string_not_unicode (str); This rejects unibyte non-ASCII strings, AFAU, in which case I suggest to think whether we really want that. E.g., why is it wrong to encode a string to UTF-8, and then send it to JSON? > +static void > +json_out_float (json_out_t *jo, Lisp_Object f) > +{ > + double x = XFLOAT_DATA (f); > + if (isinf (x) || isnan (x)) > + signal_error ("not a finite number", f); Is JSON unable to handle Inf and NaN? > +static Lisp_Object > +json_out_string_result (json_out_t *jo) > +{ > + /* FIXME: should this be a unibyte or multibyte string? > + Right now we make a multibyte string for test compatibility, > + but we are really encoding so unibyte would make more sense. */ I indeed think this should be a unibyte string, because otherwise writing it to a file or a process will/might encode it, which would be wrong. > + json_out_t jo = { > + .maxdepth = 25, Is this arbitrary, or is it what JSON expects? If arbitrary, should it be customizable? should it be documented? > + /* FIXME: Do we really need to do all this work below to insert a string? > + Is there no function already written? I must be missing something. */ There is no function. All the insert_from_* functions in insdel.c do something similar. Btw, shouldn't json-insert call treesit_record_change? Yuan? From unknown Sun Jun 15 14:44:57 2025 X-Loop: help-debbugs@gnu.org Subject: bug#70007: [PATCH] native JSON encoder Resent-From: Mattias =?UTF-8?Q?Engdeg=C3=A5rd?= Original-Sender: "Debbugs-submit" Resent-CC: bug-gnu-emacs@gnu.org Resent-Date: Wed, 27 Mar 2024 18:58:01 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 70007 X-GNU-PR-Package: emacs X-GNU-PR-Keywords: patch To: Eli Zaretskii Cc: Yuan Fu , 70007@debbugs.gnu.org Received: via spool by 70007-submit@debbugs.gnu.org id=B70007.171156585911182 (code B ref 70007); Wed, 27 Mar 2024 18:58:01 +0000 Received: (at 70007) by debbugs.gnu.org; 27 Mar 2024 18:57:39 +0000 Received: from localhost ([127.0.0.1]:38360 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1rpYSx-0002uI-3k for submit@debbugs.gnu.org; Wed, 27 Mar 2024 14:57:39 -0400 Received: from mail-lf1-x130.google.com ([2a00:1450:4864:20::130]:46144) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1rpYSt-0002tc-Fq for 70007@debbugs.gnu.org; Wed, 27 Mar 2024 14:57:37 -0400 Received: by mail-lf1-x130.google.com with SMTP id 2adb3069b0e04-512e39226efso76026e87.0 for <70007@debbugs.gnu.org>; Wed, 27 Mar 2024 11:57:35 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1711565847; x=1712170647; darn=debbugs.gnu.org; h=to:references:message-id:content-transfer-encoding:cc:date :in-reply-to:from:subject:mime-version:sender:from:to:cc:subject :date:message-id:reply-to; bh=yn6up81U/LxJJM14IRSJXShzBsuckqKmsBet6jsHqsQ=; b=Au3IAkKex5/qOF3NvsWbeZjrFUL33JQoUCYztCfQepG1ncLwgcMX5AfKUCw4+gq2Dx t/3jbxFi14yh5E1CvFEd7ooh51VZRbd0e6mTjqGkSsNkFE+w+XEvisazUAdWwsPS+Vqm TkC1vKhotyobQv9UcomB3KpuFNP1lH/diRll4pGhchR8FfK+zlciB9la4LkasSy/U5O6 o0eDI8FDvLHboviz0BShJhuSqHXtbGWVJRliHOP0F7ZSTQNmC0T7UmWg7FzSKvscRVyl 0GZTom3o0r6aeDwrrdV8GPOw/gvdqxykZs3yAyeKNaAiGlo6WoZkUSxpPJ7C7dtr13qj aKvA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1711565847; x=1712170647; h=to:references:message-id:content-transfer-encoding:cc:date :in-reply-to:from:subject:mime-version:sender:x-gm-message-state :from:to:cc:subject:date:message-id:reply-to; bh=yn6up81U/LxJJM14IRSJXShzBsuckqKmsBet6jsHqsQ=; b=hunh9J9xPG3BMKg4l90LufP7KJaB8NOz1pK5X15vR6iBA+OpESzKQlS2NuJ2cSUdFv 6csPdvkoYJ9CPJBENBKiob13iZGnFodboLUCJKav2XcyHGafG+l/rE5Li65P3jV0nIFq BtFckGwuAqw2VXuy/Mycgi1czYUinSYV6QGkj6uDkwsYTKHmFz2NCG9B9voK3hxd6RNQ adbrODpsXE9aS1mUqBEF6rfBzX98aLhlp7OpI9WQJaakxxm6uxMCKTfzblSfaSGRChBf xSTH497y5EIs9wgMPux5U/XONUsxqsOTBiiPx8kVrdxLHsKpD8dqJPzX1QMwJ6MSBpfl i5HA== X-Forwarded-Encrypted: i=1; AJvYcCUQszLLiKM2v+KEhFsY6jBtp3VrxwDRh7Qj9LR9O8MW1eBNYhw7rW6UXa8vMk/FJ3uh0R5phNGkBTdJnPgFTgJHQLeY85Y= X-Gm-Message-State: AOJu0Yz+Ys9Zm+F5V8vTKDs20eWEjN3t5IbdJAG5vJzDGtIIOplHIbWE hRNUMf6x+o8VJ/nsy7yt17D0827TI/LzWeuPmUm+I8EVfku1XHYO X-Google-Smtp-Source: AGHT+IFthrONboqDSxnd80YkfjlW2VR+WYFiREKmjTRqmZEuDPDnhOTxjnkk+6+CnsZJmifo8eUfvQ== X-Received: by 2002:a05:6512:289:b0:515:8159:788d with SMTP id j9-20020a056512028900b005158159788dmr214313lfp.64.1711565846982; Wed, 27 Mar 2024 11:57:26 -0700 (PDT) Received: from smtpclient.apple (c80-217-1-132.bredband.tele2.se. [80.217.1.132]) by smtp.gmail.com with ESMTPSA id c42-20020a05651223aa00b00515ac42651dsm1287909lfv.257.2024.03.27.11.57.25 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Wed, 27 Mar 2024 11:57:26 -0700 (PDT) Content-Type: text/plain; charset=us-ascii Mime-Version: 1.0 (Mac OS X Mail 14.0 \(3654.120.0.1.15\)) From: Mattias =?UTF-8?Q?Engdeg=C3=A5rd?= In-Reply-To: <864jcrindg.fsf@gnu.org> Date: Wed, 27 Mar 2024 19:57:24 +0100 Content-Transfer-Encoding: quoted-printable Message-Id: <291DD5F1-85B8-4647-A40A-EBBD4C51E253@gmail.com> References: <1BF559D1-DB9F-4FEB-90ED-72E0EFD76424@gmail.com> <86wmpphrg7.fsf@gnu.org> <4589243D-C11A-45C1-AF3E-6F4A5BADEB54@gmail.com> <864jcrindg.fsf@gnu.org> X-Mailer: Apple Mail (2.3654.120.0.1.15) X-Spam-Score: 0.0 (/) X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -1.0 (-) Eli, thank you for your comments! 27 mars 2024 kl. 18.40 skrev Eli Zaretskii : >> +/* JSON encoding context */ >=20 > This is not our comment style. I'll go through the code and clean up all comments. >> +typedef struct { >> + char *buf; >> + ptrdiff_t size; /* number of bytes in buf */ >> + ptrdiff_t capacity; /* allocated size of buf */ >> + ptrdiff_t chars_delta; /* size - {number of Unicode chars = in buf} */ >=20 > When you say "Unicode chars", what do you mean? characters or bytes? > If characters, then why do you need to qualify them with "Unicode"? Characters. Will clarify. >> + Lisp_Object entries[]; > ^^ > Is this portable enough? Something I'd like to know, too. We rely on C99 in many other aspects. = Are there still compilers that are important to us but don't get this = right? 10 years ago this was apparently an issue for IBM XL C 12.1, but modern = versions are based on Clang. We could take our chances here; obviously = we'll change it if someone complains but it seems unlikely. What do you = think? > I'd add an assertion here that BITS is not large enough to produce = zero. I'll deal with that in some way or another. > This rejects unibyte non-ASCII strings, AFAU, in which case I suggest > to think whether we really want that. E.g., why is it wrong to encode > a string to UTF-8, and then send it to JSON? The way I see it, that would break the JSON abstraction: it transports = strings of Unicode characters, not strings of bytes. A user who for some = reason has a string of bytes that encode Unicode characters can just = decode it in order to prove it to us. It's not the JSON encoder's job to = decode the user's strings. (It would also be a pain to deal with and risks slowing down the string = serialiser even if it's a case that never happens.) > Is JSON unable to handle Inf and NaN? That's right. >> + /* FIXME: should this be a unibyte or multibyte string? >> + Right now we make a multibyte string for test compatibility, >> + but we are really encoding so unibyte would make more sense. = */ >=20 > I indeed think this should be a unibyte string, because otherwise > writing it to a file or a process will/might encode it, which would be > wrong. I would prefer that, too, but used multibyte for compatibility with the = old code and so that its tests pass. It should probably be a separate change if we decide that unibyte is = better here. >> + json_out_t jo =3D { >> + .maxdepth =3D 25, >=20 > Is this arbitrary, or is it what JSON expects? If arbitrary, should > it be customizable? should it be documented? It's semi-arbitrary but reasonable: the JSON_checker at json.org uses a = maximum depth of 20 by default, and many implementations use its test = suite. RFC-8259 states that the maximum depth is = implementation-dependent. It's hardly worth making this into a parameter for the user to adjust = but I'll clarify the code. >> + /* FIXME: Do we really need to do all this work below to insert a = string? >> + Is there no function already written? I must be missing = something. */ >=20 > There is no function. All the insert_from_* functions in insdel.c do > something similar. Thank you for confirming that. Looks like we could use some abstraction = then. From unknown Sun Jun 15 14:44:57 2025 X-Loop: help-debbugs@gnu.org Subject: bug#70007: [PATCH] native JSON encoder Resent-From: Eli Zaretskii Original-Sender: "Debbugs-submit" Resent-CC: bug-gnu-emacs@gnu.org Resent-Date: Wed, 27 Mar 2024 19:07:01 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 70007 X-GNU-PR-Package: emacs X-GNU-PR-Keywords: patch To: Mattias =?UTF-8?Q?Engdeg=C3=A5rd?= Cc: casouri@gmail.com, 70007@debbugs.gnu.org Received: via spool by 70007-submit@debbugs.gnu.org id=B70007.171156636913600 (code B ref 70007); Wed, 27 Mar 2024 19:07:01 +0000 Received: (at 70007) by debbugs.gnu.org; 27 Mar 2024 19:06:09 +0000 Received: from localhost ([127.0.0.1]:38365 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1rpYbB-0003XH-8N for submit@debbugs.gnu.org; Wed, 27 Mar 2024 15:06:09 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:59828) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1rpYb6-0003WD-Dh for 70007@debbugs.gnu.org; Wed, 27 Mar 2024 15:06:08 -0400 Received: from fencepost.gnu.org ([2001:470:142:3::e]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1rpYb0-0006pj-MF; Wed, 27 Mar 2024 15:05:58 -0400 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=gnu.org; s=fencepost-gnu-org; h=MIME-version:References:Subject:In-Reply-To:To:From: Date; bh=JBZvqtiPMK2msP7EgwbC0yr3SlJzHU0GwNOc4LflgCI=; b=k3AqXy8Y2fypq/WdxWhT T21UVDXrKQFxlQoXxjd7vRYbmqYdn6LdAOdt+TNzOFk4QnGihTCoX5kIPSj6vcb7j81xWKCEZjgLL 98Vq7sYUEwS/TRGx4Q4aKUmqABe/uWDBeUERZVVfFbxY2C5GFx6NiSU3YrU0LcqrQj2IGDtcLEbN1 0rrTJJ38AHbpS4eYVUysDqzQJXZuQR4ebQ6On3UhZP4CBxx+WYBJCw/2JOj9zy/iOAD/0C1PZBiyO ibNESWF0NhVMVRb9/ZVbodyqYBP5/sAZF7acTs7n9nMeXf41ekG9nmKR6zUBzea9qF4bwP52GpgzT E8hu93odxJXqug==; Date: Wed, 27 Mar 2024 21:05:54 +0200 Message-Id: <8634sbijfx.fsf@gnu.org> From: Eli Zaretskii In-Reply-To: <291DD5F1-85B8-4647-A40A-EBBD4C51E253@gmail.com> (message from Mattias =?UTF-8?Q?Engdeg=C3=A5rd?= on Wed, 27 Mar 2024 19:57:24 +0100) References: <1BF559D1-DB9F-4FEB-90ED-72E0EFD76424@gmail.com> <86wmpphrg7.fsf@gnu.org> <4589243D-C11A-45C1-AF3E-6F4A5BADEB54@gmail.com> <864jcrindg.fsf@gnu.org> <291DD5F1-85B8-4647-A40A-EBBD4C51E253@gmail.com> MIME-version: 1.0 Content-type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Spam-Score: -2.3 (--) X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -3.3 (---) > From: Mattias EngdegÃ¥rd > Date: Wed, 27 Mar 2024 19:57:24 +0100 > Cc: Yuan Fu , > 70007@debbugs.gnu.org > > Eli, thank you for your comments! Thanks for working on this in the first place. > > This rejects unibyte non-ASCII strings, AFAU, in which case I suggest > > to think whether we really want that. E.g., why is it wrong to encode > > a string to UTF-8, and then send it to JSON? > > The way I see it, that would break the JSON abstraction: it transports strings of Unicode characters, not strings of bytes. What's the difference? AFAIU, JSON expects UTF-8 encoded strings, and whether that is used as a sequence of bytes or a sequence of characters is in the eyes of the beholder: the bytestream is the same, only the interpretation changes. So I'm not sure I understand how this would break the assumption. > A user who for some reason has a string of bytes that encode Unicode characters can just decode it in order to prove it to us. It's not the JSON encoder's job to decode the user's strings. I didn't suggest to decode the input string, not at all. I suggested to allow unibyte strings, and process them just like you process pure-ASCII strings, leaving it to the caller to make sure the string has only valid UTF-8 sequences. Forcing callers to decode such strings is IMO too harsh and largely unjustified. > (It would also be a pain to deal with and risks slowing down the string serialiser even if it's a case that never happens.) I don't understand why. Once again, I'm just talking about passing the bytes through as you do with ASCII characters. From unknown Sun Jun 15 14:44:57 2025 X-Loop: help-debbugs@gnu.org Subject: bug#70007: [PATCH] native JSON encoder Resent-From: Theodor Thornhill Original-Sender: "Debbugs-submit" Resent-CC: bug-gnu-emacs@gnu.org Resent-Date: Thu, 28 Mar 2024 19:17:01 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 70007 X-GNU-PR-Package: emacs X-GNU-PR-Keywords: patch To: Eli Zaretskii Cc: Mattias =?UTF-8?Q?Engdeg=C3=A5rd?= , 70007@debbugs.gnu.org Received: via spool by 70007-submit@debbugs.gnu.org id=B70007.171165340930008 (code B ref 70007); Thu, 28 Mar 2024 19:17:01 +0000 Received: (at 70007) by debbugs.gnu.org; 28 Mar 2024 19:16:49 +0000 Received: from localhost ([127.0.0.1]:41163 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1rpvF3-0007nu-HP for submit@debbugs.gnu.org; Thu, 28 Mar 2024 15:16:49 -0400 Received: from out-175.mta0.migadu.com ([2001:41d0:1004:224b::af]:63157) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1rpvF1-0007nV-8f for 70007@debbugs.gnu.org; Thu, 28 Mar 2024 15:16:48 -0400 X-Report-Abuse: Please report any abuse attempt to abuse@migadu.com and include these headers. DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=thornhill.no; s=key1; t=1711653399; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=PYkWCq5l64nbppyOfCrm10eoeQh5uZxf7Rzy198dAeM=; b=KL9oh+U/fNNGZDQGwKI2etf7vuo81gQxipLiWcI37KKuJnNTJVjbuzMq0IESXWZ/WKSCqg uNfoPCdZ3yaIMlQVZ8hYEPlw9LOIP1b6dk/PXyMsmLD3XBesW5FRYgSeUkLHbwPqcxM2vY 2R67/p1tb3k+h8lwCT1s3wOYrO0Hk7yz6MxG3fa7c6/iT91M6P+76EeXmNVj3CJbzWF9Zo kdMh1EaH5OEL4il3nl/sTcuMBBD8eexdtGZtRCitiF4GSpdYTDaEP1I3IGPB+4wN1x2QdL XjrRSo3Q+A7yzmhu5fVcwZw7FaP1EJOx4mPt2dR9kSGOJoYBTA5X0iEveJa3Rw== From: Theodor Thornhill In-Reply-To: <86wmpphrg7.fsf@gnu.org> (Eli Zaretskii's message of "Tue, 26 Mar 2024 18:46:00 +0200") References: <1BF559D1-DB9F-4FEB-90ED-72E0EFD76424@gmail.com> <86wmpphrg7.fsf@gnu.org> Date: Thu, 28 Mar 2024 20:16:35 +0100 Message-ID: <87y1a29nfw.fsf@thornhill.no> MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable X-Migadu-Flow: FLOW_OUT X-Spam-Score: 0.0 (/) X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -1.0 (-) Eli Zaretskii writes: >> From: Mattias Engdeg=C3=A5rd >> Date: Tue, 26 Mar 2024 16:33:52 +0100 >>=20 >> If we replace the lisp-to-JSON encoder with native code, we would not ne= ed the jansson library for it and it would be faster. >>=20 >> There is ongoing work on a JSON-to-lisp parser, but the author has made = it clear that he does not have time to write an encoder, so I spent a morni= ng mashing up the attached patch. > > Thanks for working on this. > >> It generally produces the same result as the old code, except: >>=20 >> - The old code incorrectly accepted strings with non-Unicode characters = (raw bytes). There is no reason to do this; JSON is UTF-8 only. > > Would it complicate the code not to reject raw bytes? I'd like to > avoid incompatibilities if it's practical. Also, Emacs traditionally > doesn't reject raw bytes, leaving that to the application or the user. > >> I'd be very happy if someone could test it with packages that use this i= nterface (json-serialise, json-insert). > > Yes, please. I've been using this along with the json-to-lisp parser for some time now, and I'm really happy to see these improvements. Thanks a lot! I haven't seen any issues thus far, and emacs is much more responsive. I hope both of these patches will soon arrive on emacs 30. I'll continue using and testing both until then. Thanks, Theo From unknown Sun Jun 15 14:44:57 2025 X-Loop: help-debbugs@gnu.org Subject: bug#70007: [PATCH] native JSON encoder Resent-From: Mattias =?UTF-8?Q?Engdeg=C3=A5rd?= Original-Sender: "Debbugs-submit" Resent-CC: bug-gnu-emacs@gnu.org Resent-Date: Thu, 28 Mar 2024 21:00:05 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 70007 X-GNU-PR-Package: emacs X-GNU-PR-Keywords: patch To: Eli Zaretskii Cc: casouri@gmail.com, 70007@debbugs.gnu.org Received: via spool by 70007-submit@debbugs.gnu.org id=B70007.171165959221280 (code B ref 70007); Thu, 28 Mar 2024 21:00:05 +0000 Received: (at 70007) by debbugs.gnu.org; 28 Mar 2024 20:59:52 +0000 Received: from localhost ([127.0.0.1]:41240 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1rpwql-0005XA-Qm for submit@debbugs.gnu.org; Thu, 28 Mar 2024 16:59:52 -0400 Received: from mail-lf1-x12a.google.com ([2a00:1450:4864:20::12a]:58371) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1rpwqh-0005Wv-C9 for 70007@debbugs.gnu.org; Thu, 28 Mar 2024 16:59:51 -0400 Received: by mail-lf1-x12a.google.com with SMTP id 2adb3069b0e04-512bde3d197so1029786e87.0 for <70007@debbugs.gnu.org>; Thu, 28 Mar 2024 13:59:46 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1711659580; x=1712264380; darn=debbugs.gnu.org; h=to:references:message-id:content-transfer-encoding:cc:date :in-reply-to:from:subject:mime-version:sender:from:to:cc:subject :date:message-id:reply-to; bh=4Tuv6+7kjKZCcxEEJiwBcy1o0tt9jJ0qwO60l/ePvzc=; b=MK/CcA52KiRVr6otf1ykYjmIZ2EYVCO34hiwg2d0Fq3TBPOpr9Ar14wkOO6GqR5PGP 7pmKnKIos3leRlyO+jd9/QCUvYNzuFIaMFI71jyoGuYzHSVrePk32t7efu5FALYzXN+w PoU80/6Hkv9NmoZT2fLtIxbeWE4VV3mmThpxz+UXBwAMubKnLytXVJY/YmfQoQuC/0QR ZpZX+hV+qjROPR9gpS44KyCamutBC9PtLJ+evDwM8mn1ZsX7CuIpfFSQ2kl7UT56pqmU xzZy12o9viq1rJM007Xly2E9UIHkwPYHBnVG8KfAm9exYCBdgQxp0TRK6MZ53XpQej5R Kl/w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1711659580; x=1712264380; h=to:references:message-id:content-transfer-encoding:cc:date :in-reply-to:from:subject:mime-version:sender:x-gm-message-state :from:to:cc:subject:date:message-id:reply-to; bh=4Tuv6+7kjKZCcxEEJiwBcy1o0tt9jJ0qwO60l/ePvzc=; b=r0BrcHB/dK7Z94Vntgq2vX4SgqDPe2HmmYlQB+S1FUmx6YQAq3g257hVhdTcnJrmyk mggAsRGIF1iYaXR2bGH+P1rm5CoW1YMKkV6Y9Vw8QE9jjVmaSu5+UPBVPihC2jnuMI0G hIyORnuOyev5DA0symdSEXqFtLvYIwHMrFw/7YGxnMIhKUQexJirk7NkXHflE4FNOyrt mzF4SMCn+Pcxm0KOT9l65bgjKX0WsOavuSAzvMASDPIY/3vBZu88KQ3mw7rLaz2GOT25 f5zwgG3pOuBzLsfkQapTN7OuSVHXwKElbClhTmP8QgB1oqUEKCp4NbFIGdx3MrNBTPjI +3eg== X-Forwarded-Encrypted: i=1; AJvYcCXL1toMhB7T6v8NLyvdXOTflZtdI4JqJFRlnEYn8YZqnFOWQPoaaoRJzKmHgjj/zWbYP2QlhazX7elkIM9leRZekB9Nsys= X-Gm-Message-State: AOJu0YxUKp34oPNjnlPwLg3ih2+PYmbUazmxaeBeBDsRgiNCXodK5huU j4O5xSx03EPmsA+viwECY9zGUQtLTX0biIJb9wD1JtyNILluHadV X-Google-Smtp-Source: AGHT+IGRvp+WedSJeTQ7Myaxj4wZCsW+VeH9DOpp9xit6y0lr9eHRpV16Xex7yVwiOoRG8oIjo0Nbw== X-Received: by 2002:ac2:5e62:0:b0:515:ab7f:b13e with SMTP id a2-20020ac25e62000000b00515ab7fb13emr408226lfr.33.1711659579551; Thu, 28 Mar 2024 13:59:39 -0700 (PDT) Received: from smtpclient.apple (c80-217-1-132.bredband.tele2.se. [80.217.1.132]) by smtp.gmail.com with ESMTPSA id z14-20020a056512308e00b00515c9605ea5sm297828lfd.261.2024.03.28.13.59.38 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Thu, 28 Mar 2024 13:59:39 -0700 (PDT) Content-Type: text/plain; charset=us-ascii Mime-Version: 1.0 (Mac OS X Mail 14.0 \(3654.120.0.1.15\)) From: Mattias =?UTF-8?Q?Engdeg=C3=A5rd?= In-Reply-To: <8634sbijfx.fsf@gnu.org> Date: Thu, 28 Mar 2024 21:59:38 +0100 Content-Transfer-Encoding: quoted-printable Message-Id: <2CF47DA5-A65B-47C4-A28A-6FEE1469BD13@gmail.com> References: <1BF559D1-DB9F-4FEB-90ED-72E0EFD76424@gmail.com> <86wmpphrg7.fsf@gnu.org> <4589243D-C11A-45C1-AF3E-6F4A5BADEB54@gmail.com> <864jcrindg.fsf@gnu.org> <291DD5F1-85B8-4647-A40A-EBBD4C51E253@gmail.com> <8634sbijfx.fsf@gnu.org> X-Mailer: Apple Mail (2.3654.120.0.1.15) X-Spam-Score: 0.0 (/) X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -1.0 (-) 27 mars 2024 kl. 20.05 skrev Eli Zaretskii : >>> This rejects unibyte non-ASCII strings, AFAU, in which case I = suggest >>> to think whether we really want that. E.g., why is it wrong to = encode >>> a string to UTF-8, and then send it to JSON? >>=20 >> The way I see it, that would break the JSON abstraction: it = transports strings of Unicode characters, not strings of bytes. >=20 > What's the difference? AFAIU, JSON expects UTF-8 encoded strings, and > whether that is used as a sequence of bytes or a sequence of > characters is in the eyes of the beholder: the bytestream is the same, > only the interpretation changes. Well no -- JSON transports Unicode strings: the JSON serialiser takes a = Unicode string as input and outputs a byte sequence; the JSON parser = takes a byte sequence and returns a Unicode string (assuming we are just = interested in strings). That the transport format uses UTF-8 is unrelated; if the user hands an = encoded byte sequence to us then it seems more likely that it's a = mistake. After all, it cannot have come from a received JSON message. I think it was just an another artefact of the old implementation. That = code incorrectly used encode_string_utf_8 even on non-ASCII unibyte = strings and trusted Jansson to validate the result. That resulted in a = lot of wasted work and some strange strings getting accepted. While it's theoretically possible that there are users with code relying = on this behaviour, I can't find any evidence for it in the packages that = I've looked at. > I didn't suggest to decode the input string, not at all. I suggested > to allow unibyte strings, and process them just like you process > pure-ASCII strings, leaving it to the caller to make sure the string > has only valid UTF-8 sequences. Users of this raw-bytes-input feature (if they exist at all) previously = had their input validated by Jansson. While mistakes would probably be = detected at the other end I'm not sure it's a good idea. > Forcing callers to decode such > strings is IMO too harsh and largely unjustified. We usually force them to do so in most other contexts. To take a random = example, `princ` doesn't work with encoded strings. But it's rarely a = problem. Let's see how testing goes. We'll find a solution no matter what, = pass-through or separate slow-path validation, if it turns out that we = really need to after all. From unknown Sun Jun 15 14:44:57 2025 X-Loop: help-debbugs@gnu.org Subject: bug#70007: [PATCH] native JSON encoder Resent-From: Eli Zaretskii Original-Sender: "Debbugs-submit" Resent-CC: bug-gnu-emacs@gnu.org Resent-Date: Fri, 29 Mar 2024 06:05:02 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 70007 X-GNU-PR-Package: emacs X-GNU-PR-Keywords: patch To: Mattias =?UTF-8?Q?Engdeg=C3=A5rd?= Cc: casouri@gmail.com, 70007@debbugs.gnu.org Received: via spool by 70007-submit@debbugs.gnu.org id=B70007.171169227527086 (code B ref 70007); Fri, 29 Mar 2024 06:05:02 +0000 Received: (at 70007) by debbugs.gnu.org; 29 Mar 2024 06:04:35 +0000 Received: from localhost ([127.0.0.1]:41557 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1rq5Lu-00072o-Q6 for submit@debbugs.gnu.org; Fri, 29 Mar 2024 02:04:35 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:53230) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1rq5Lr-00072R-3F for 70007@debbugs.gnu.org; Fri, 29 Mar 2024 02:04:32 -0400 Received: from fencepost.gnu.org ([2001:470:142:3::e]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1rq5Lk-0005jH-Hg; Fri, 29 Mar 2024 02:04:24 -0400 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=gnu.org; s=fencepost-gnu-org; h=MIME-version:References:Subject:In-Reply-To:To:From: Date; bh=LJGz29EtHIsjOMQS50Y2nyTyk+WbIEHXWhRlA8QKnYc=; b=B+JgiLlULygMsQ+dYJNE EPP2QFBmAe6p0Jlff6RkUNk2h6Bi6JwfdmH7DbZrzshFt2SGoVBV6AuomkXPJ22mZ/965pf/XDqU0 G+NVFP4XxfI0xB9OJbGxro9OnvVUscakmZY1oODsw34GqqVi44NByv4MyJoYHl1Ncr6/0C5ksbz59 Xm4bSrdNSlyqXkLj3+7/BUoQlZ/eRUWOyWtm+cAA0Tq4Jf2iabYVE0PR/W4W7CyaizrpmxYPt0Nw2 XADimL04uydoUPejjPS7bGVwogJ+ZQmvtl50O168ggpgtlJpCjkTzgmc6Z3ctmhPy6fRiQ/9wTyJH cekiWei+/pE9/w==; Date: Fri, 29 Mar 2024 09:04:21 +0300 Message-Id: <86cyrdfuai.fsf@gnu.org> From: Eli Zaretskii In-Reply-To: <2CF47DA5-A65B-47C4-A28A-6FEE1469BD13@gmail.com> (message from Mattias =?UTF-8?Q?Engdeg=C3=A5rd?= on Thu, 28 Mar 2024 21:59:38 +0100) References: <1BF559D1-DB9F-4FEB-90ED-72E0EFD76424@gmail.com> <86wmpphrg7.fsf@gnu.org> <4589243D-C11A-45C1-AF3E-6F4A5BADEB54@gmail.com> <864jcrindg.fsf@gnu.org> <291DD5F1-85B8-4647-A40A-EBBD4C51E253@gmail.com> <8634sbijfx.fsf@gnu.org> <2CF47DA5-A65B-47C4-A28A-6FEE1469BD13@gmail.com> MIME-version: 1.0 Content-type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Spam-Score: -2.3 (--) X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -3.3 (---) > From: Mattias EngdegÃ¥rd > Date: Thu, 28 Mar 2024 21:59:38 +0100 > Cc: casouri@gmail.com, > 70007@debbugs.gnu.org > > 27 mars 2024 kl. 20.05 skrev Eli Zaretskii : > > >>> This rejects unibyte non-ASCII strings, AFAU, in which case I suggest > >>> to think whether we really want that. E.g., why is it wrong to encode > >>> a string to UTF-8, and then send it to JSON? > >> > >> The way I see it, that would break the JSON abstraction: it transports strings of Unicode characters, not strings of bytes. > > > > What's the difference? AFAIU, JSON expects UTF-8 encoded strings, and > > whether that is used as a sequence of bytes or a sequence of > > characters is in the eyes of the beholder: the bytestream is the same, > > only the interpretation changes. > > Well no -- JSON transports Unicode strings: the JSON serialiser takes a Unicode string as input and outputs a byte sequence; the JSON parser takes a byte sequence and returns a Unicode string (assuming we are just interested in strings). > > That the transport format uses UTF-8 is unrelated; It is not unrelated. A JSON stream is AFAIK supposed to have strings represented in UTF-8 encoding. When a Lisp program produces a JSON stream, all that should matter to it is that any string there has a valid UTF-8 sequence; where and how that sequence was obtained is of secondary importance. > if the user hands an encoded byte sequence to us then it seems more likely that it's a mistake. We don't know that. Since Emacs lets Lisp programs produce unibyte UTF-8 encoded strings very easily, a program could do just that, for whatever reasons. Unless we have very serious reasons not to allow UTF-8 sequences produced by something other than the JSON serializer itself (and I think we don't), we should not prohibit it. The Emacs spirit is to let bad Lisp program enough rope to hang themselves if that allows legitimate programs do their job more easily and flexibly. > After all, it cannot have come from a received JSON message. It could have, if it was encoded by the calling Lisp program. It could also have been received from another source, in unibyte form that is nonetheless valid UTF-8. If we force non-ASCII strings to be multibyte, Lisp programs will be unable to take a unibyte UTF-8 string received from an external source and plug it directly into an object to be serialized into JSON; instead, they will have to decode the string, then let the serializer encode it back -- a clear waste of CPU cycles. > I think it was just an another artefact of the old implementation. That code incorrectly used encode_string_utf_8 even on non-ASCII unibyte strings and trusted Jansson to validate the result. That resulted in a lot of wasted work and some strange strings getting accepted. I'm not talking about the old implementation. I was not completely happy with it, either, and in particular with its insistence of signaling errors due to encoding issues. I think this is not our business in this case: the responsibility for submitting a valid UTF-8 sequence, when we get a unibyte string, is on the caller. > While it's theoretically possible that there are users with code relying on this behaviour, I can't find any evidence for it in the packages that I've looked at. Once again, my bother is not about some code that expects us to encode UTF-8 byte sequences -- doing that is definitely not TRT. What I would like to see is that unibyte strings are passed through unchanged, so that valid UTF-8 strings will be okay, and invalid ones will produce invalid JSON. This is better than signaling errors, IMNSHO, and in particular is more in-line with how Emacs handles unibyte strings elsewhere. > > I didn't suggest to decode the input string, not at all. I suggested > > to allow unibyte strings, and process them just like you process > > pure-ASCII strings, leaving it to the caller to make sure the string > > has only valid UTF-8 sequences. > > Users of this raw-bytes-input feature (if they exist at all) previously had their input validated by Jansson. While mistakes would probably be detected at the other end I'm not sure it's a good idea. Why not? Once again, if we get a unibyte string, the onus is on the caller to verify it's valid UTF-8, or suffer the consequences. > > Forcing callers to decode such > > strings is IMO too harsh and largely unjustified. > > We usually force them to do so in most other contexts. To take a random example, `princ` doesn't work with encoded strings. But it's rarely a problem. There are many examples to the contrary. For example, primitives that deal with file names can accept both multibyte and unibyte encoded strings. > Let's see how testing goes. We'll find a solution no matter what, pass-through or separate slow-path validation, if it turns out that we really need to after all. OK. FTR, I'm not in favor of validation of unibyte strings, I just suggest that we treat them as plain-ASCII: pass them through without any validation, leaving the validation to the callers. From unknown Sun Jun 15 14:44:57 2025 X-Loop: help-debbugs@gnu.org Subject: bug#70007: [PATCH] native JSON encoder Resent-From: Mattias =?UTF-8?Q?Engdeg=C3=A5rd?= Original-Sender: "Debbugs-submit" Resent-CC: bug-gnu-emacs@gnu.org Resent-Date: Sat, 30 Mar 2024 11:42:02 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 70007 X-GNU-PR-Package: emacs X-GNU-PR-Keywords: patch To: Eli Zaretskii Cc: casouri@gmail.com, 70007@debbugs.gnu.org Received: via spool by 70007-submit@debbugs.gnu.org id=B70007.17117989059907 (code B ref 70007); Sat, 30 Mar 2024 11:42:02 +0000 Received: (at 70007) by debbugs.gnu.org; 30 Mar 2024 11:41:45 +0000 Received: from localhost ([127.0.0.1]:44093 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1rqX5l-0002Zj-27 for submit@debbugs.gnu.org; Sat, 30 Mar 2024 07:41:45 -0400 Received: from mail-lf1-x12c.google.com ([2a00:1450:4864:20::12c]:45304) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1rqX5h-0002ZO-N2 for 70007@debbugs.gnu.org; Sat, 30 Mar 2024 07:41:43 -0400 Received: by mail-lf1-x12c.google.com with SMTP id 2adb3069b0e04-515d55ab035so436967e87.2 for <70007@debbugs.gnu.org>; Sat, 30 Mar 2024 04:41:39 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1711798894; x=1712403694; darn=debbugs.gnu.org; h=references:to:cc:in-reply-to:date:subject:mime-version:message-id :from:sender:from:to:cc:subject:date:message-id:reply-to; bh=lhlkbrTrtEy4QIRhwP4fVRhgXE+g2kJyYlI/Eum8JFo=; b=TlmIoGdaCDpPMC+i390ku4TXGnG48yVpzH5fIEBlIcHe3LtpgMQkuCRnTSZav/hHzg wHqWkWwT/aUYGDaNb2lrfOSPpwCWhp4lo3WjBdWgHsNEhO/lmYQyWqJVyLMiizLpSdxe TIPpS/kF96XezGJXsdVd4ANb4x7fKoKF0InpVua8gw9k+VuEs9F1ebjDOoUoLSmiFCww 6sW1uMlCS6T6dMiRO7XNXWWjSSnT6knjbp1ZwaR88LvHP41RCpYEBWB5YEDrK7h4c/rD FPd+tKTOFPMyoMbyLrWN5umbQdfhO0G/6EzYTJS5VTFpC0XSORpaezPxk/2549NXn/Wm AtdA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1711798894; x=1712403694; h=references:to:cc:in-reply-to:date:subject:mime-version:message-id :from:sender:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=lhlkbrTrtEy4QIRhwP4fVRhgXE+g2kJyYlI/Eum8JFo=; b=PvOp8gwXopoc/bAHf06J6wnzYHinmsuufEDC7nkYyw979HhEYZHtDn2b6K2wc7A3Nf sedRfGmSXyz2WXr8Znl1bVn2afQBM1IYwaFmIh15vVpiUNDAWZzyt6oniWnohxvDCeyg MYj3Opcc15IJfhyVO0cCfYE/syohQ1GWRSzilwNlADtuAFMfeLpmUzRjQoTyuJ76chS0 3PfJaS6pcn0YcfiBe5HS+aVZGnDNVJSuiQhhWP4UpFvmZBhdQWhXWaFM6CJU6mljD6CL AtzyPy5toD3dOFX3mP0FsSALesqdYf7DDVklgmT3S35Dp+NUPrWO092e056BBI8VEFcx ZBXw== X-Forwarded-Encrypted: i=1; AJvYcCVPGBbVMfpx7Rd31f3wxB4TrpxGk4n4lxJkwLtjpEqd1VtqbNaz07SQHvvPrrgJEpeqAHfIO1ttEPyjHSziP1UXqKsGE5M= X-Gm-Message-State: AOJu0Yyg8LvqFKzO4gXzj7XlWKMwVYaYahE5q9nCb1Y3Nwo6epAwuuS+ WKMrSipQ5nlbZhYQniGNVPRuuhhr1oMMtofY14LMMcMTOpdOM+Pd X-Google-Smtp-Source: AGHT+IGbJuAQ29ZS+E+efEMOzv7jspHD8pS23dmSetiCWlrWHREYWSecAuvXGh/c5CsIySYTzY5rfg== X-Received: by 2002:ac2:5fb1:0:b0:516:a010:f1c0 with SMTP id s17-20020ac25fb1000000b00516a010f1c0mr467048lfe.63.1711798893264; Sat, 30 Mar 2024 04:41:33 -0700 (PDT) Received: from smtpclient.apple (c80-217-1-132.bredband.tele2.se. [80.217.1.132]) by smtp.gmail.com with ESMTPSA id t9-20020a195f09000000b00515bad4cd0asm898443lfb.155.2024.03.30.04.41.32 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Sat, 30 Mar 2024 04:41:32 -0700 (PDT) From: Mattias =?UTF-8?Q?Engdeg=C3=A5rd?= Message-Id: <3139C8FE-5C67-4FE3-B940-F449DA73E76C@gmail.com> Content-Type: multipart/mixed; boundary="Apple-Mail=_558A8A9C-18B2-4CE8-A0C1-865EBAE3B503" Mime-Version: 1.0 (Mac OS X Mail 14.0 \(3654.120.0.1.15\)) Date: Sat, 30 Mar 2024 12:41:31 +0100 In-Reply-To: <86cyrdfuai.fsf@gnu.org> References: <1BF559D1-DB9F-4FEB-90ED-72E0EFD76424@gmail.com> <86wmpphrg7.fsf@gnu.org> <4589243D-C11A-45C1-AF3E-6F4A5BADEB54@gmail.com> <864jcrindg.fsf@gnu.org> <291DD5F1-85B8-4647-A40A-EBBD4C51E253@gmail.com> <8634sbijfx.fsf@gnu.org> <2CF47DA5-A65B-47C4-A28A-6FEE1469BD13@gmail.com> <86cyrdfuai.fsf@gnu.org> X-Mailer: Apple Mail (2.3654.120.0.1.15) X-Spam-Score: 0.0 (/) X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -1.0 (-) --Apple-Mail=_558A8A9C-18B2-4CE8-A0C1-865EBAE3B503 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset=us-ascii 29 mars 2024 kl. 07.04 skrev Eli Zaretskii : > OK. FTR, I'm not in favor of validation of unibyte strings, I just > suggest that we treat them as plain-ASCII: pass them through without > any validation, leaving the validation to the callers. Actually we are more or less forced to validate unibyte strings as long = as the serialiser returns multibyte. Which we agree that it probably = shouldn't, but I'd first like to take some time to ensure that returning = unibyte won't break anything. Thank you for pushing the new JSON parser to master. I've rebased my = patch and cleaned it up a bit, and it now removes all uses of Jansson = from json.c. Since the change involves removing some Windows-specific = code, perhaps you would like to check that it still compiles on that = platform, if you have the time? Otherwise I'll push it to master, and will remain ready to make any = further adjustments necessary. We can then remove all remaining Jansson = references (configuration, installation notes, etc), and make the = required NEWS and manual changes. --Apple-Mail=_558A8A9C-18B2-4CE8-A0C1-865EBAE3B503 Content-Disposition: attachment; filename=0001-New-JSON-encoder-bug-70007.patch Content-Type: application/octet-stream; x-unix-mode=0644; name="0001-New-JSON-encoder-bug-70007.patch" Content-Transfer-Encoding: quoted-printable =46rom=204b2f5d8b55946c55838793046944b5680a19ba01=20Mon=20Sep=2017=20= 00:00:00=202001=0AFrom:=20=3D?UTF-8?q?Mattias=3D20Engdeg=3DC3=3DA5rd?=3D=20= =0ADate:=20Tue,=2026=20Mar=202024=2016:44:09=20+0100=0A= Subject:=20[PATCH]=20New=20JSON=20encoder=20(bug#70007)=0A=0AIt=20is=20= in=20general=20at=20least=202x=20faster=20than=20the=20old=20encoder=20= and=20does=20not=0Adepend=20on=20any=20external=20library.=20=20Using=20= our=20own=20code=20also=20gives=20us=0Acontrol=20over=20translation=20= details:=20for=20example,=20we=20now=20have=20full=0Abignum=20support=20= and=20tighter=20float=20formatting.=0A=0A*=20src/json.c=20(json_delete,=20= json_initialized,=20init_json_functions)=0A(json_malloc,=20json_free,=20= init_json,=20json_out_of_memory)=0A(json_releae_object,=20= check_string_without_embedded_nulls,=20json_check)=0A(json_check_utf8,=20= lisp_to_json_nonscalar_1,=20lisp_to_json_nonscalar)=0A(lisp_to_json,=20= json_available_p,=20ensure_json_available,=20json_insert)=0A= (json_handle_nonlocal_exit,=20json_insert_callback):=0ARemove.=20=20= Remaining=20uses=20updated.=0A*=20src/json.c=20(json_out_t,=20symset_t,=20= struct=20symset_tbl)=0A(symset_size,=20make_symset_table,=20push_symset,=20= pop_symset)=0A(cleanup_symset_tables,=20symset_hash,=20symset_expand,=20= symset_add)=0A(json_out_grow_buf,=20cleanup_json_out,=20json_make_room,=20= JSON_OUT_STR)=0A(json_out_str,=20json_out_byte,=20json_out_fixnum,=20= string_not_unicode)=0A(json_plain_char,=20json_out_string,=20= json_out_nest,=20json_out_unnest)=0A(json_out_object_cons,=20= json_out_object_hash),=20json_out_array)=0A(json_out_float,=20= json_out_bignum,=20json_out_something)=0A(json_out_to_string,=20= json_serialize):=20New.=0A(Fjson_serialize,=20Fjson_insert):=0ANew=20= JSON=20encoder=20implementation.=0A*=20test/src/json-tests.el=20= (json-serialize/object-with-duplicate-keys)=0A(json-serialize/string):=20= Update=20tests.=0A---=0A=20src/emacs.c=20=20=20=20=20=20=20=20=20=20=20=20= |=20=20=20=204=20-=0A=20src/json.c=20=20=20=20=20=20=20=20=20=20=20=20=20= |=201071=20++++++++++++++++++++--------------------=0A=20src/lisp.h=20=20= =20=20=20=20=20=20=20=20=20=20=20|=20=20=20=201=20-=0A=20src/print.c=20=20= =20=20=20=20=20=20=20=20=20=20|=20=20=20=201=20+=0A=20= test/src/json-tests.el=20|=20=20=2041=20+-=0A=205=20files=20changed,=20= 581=20insertions(+),=20537=20deletions(-)=0A=0Adiff=20--git=20= a/src/emacs.c=20b/src/emacs.c=0Aindex=2087f12d3fa86..4a34bb06425=20= 100644=0A---=20a/src/emacs.c=0A+++=20b/src/emacs.c=0A@@=20-2013,10=20= +2013,6=20@@=20main=20(int=20argc,=20char=20**argv)=0A=20=20=20= init_random=20();=0A=20=20=20init_xfaces=20();=0A=20=0A-#if=20defined=20= HAVE_JSON=20&&=20!defined=20WINDOWSNT=0A-=20=20init_json=20();=0A-#endif=0A= -=0A=20=20=20if=20(!initialized)=0A=20=20=20=20=20syms_of_comp=20();=0A=20= =0Adiff=20--git=20a/src/json.c=20b/src/json.c=0Aindex=20= afc48c59d5a..711744138b8=20100644=0A---=20a/src/json.c=0A+++=20= b/src/json.c=0A@@=20-25,189=20+25,10=20@@=20Copyright=20(C)=202017-2024=20= Free=20Software=20Foundation,=20Inc.=0A=20#include=20=0A=20= #include=20=0A=20=0A-#include=20=0A-=0A=20#include=20= "lisp.h"=0A=20#include=20"buffer.h"=0A=20#include=20"coding.h"=0A=20=0A= -#ifdef=20WINDOWSNT=0A-#=20include=20=0A-#=20include=20= "w32common.h"=0A-#=20include=20"w32.h"=0A-=0A-DEF_DLL_FN=20(void,=20= json_set_alloc_funcs,=0A-=09=20=20=20=20(json_malloc_t=20malloc_fn,=20= json_free_t=20free_fn));=0A-DEF_DLL_FN=20(void,=20json_delete,=20(json_t=20= *json));=0A-DEF_DLL_FN=20(json_t=20*,=20json_array,=20(void));=0A= -DEF_DLL_FN=20(int,=20json_array_append_new,=20(json_t=20*array,=20= json_t=20*value));=0A-DEF_DLL_FN=20(size_t,=20json_array_size,=20(const=20= json_t=20*array));=0A-DEF_DLL_FN=20(json_t=20*,=20json_object,=20= (void));=0A-DEF_DLL_FN=20(int,=20json_object_set_new,=0A-=09=20=20=20=20= (json_t=20*object,=20const=20char=20*key,=20json_t=20*value));=0A= -DEF_DLL_FN=20(json_t=20*,=20json_null,=20(void));=0A-DEF_DLL_FN=20= (json_t=20*,=20json_true,=20(void));=0A-DEF_DLL_FN=20(json_t=20*,=20= json_false,=20(void));=0A-DEF_DLL_FN=20(json_t=20*,=20json_integer,=20= (json_int_t=20value));=0A-DEF_DLL_FN=20(json_t=20*,=20json_real,=20= (double=20value));=0A-DEF_DLL_FN=20(json_t=20*,=20json_stringn,=20(const=20= char=20*value,=20size_t=20len));=0A-DEF_DLL_FN=20(char=20*,=20= json_dumps,=20(const=20json_t=20*json,=20size_t=20flags));=0A-DEF_DLL_FN=20= (int,=20json_dump_callback,=0A-=09=20=20=20=20(const=20json_t=20*json,=20= json_dump_callback_t=20callback,=20void=20*data,=0A-=09=20=20=20=20=20= size_t=20flags));=0A-DEF_DLL_FN=20(json_t=20*,=20json_object_get,=20= (const=20json_t=20*object,=20const=20char=20*key));=0A-=0A-/*=20This=20= is=20called=20by=20json_decref,=20which=20is=20an=20inline=20function.=20= =20*/=0A-void=20json_delete(json_t=20*json)=0A-{=0A-=20=20fn_json_delete=20= (json);=0A-}=0A-=0A-static=20bool=20json_initialized;=0A-=0A-static=20= bool=0A-init_json_functions=20(void)=0A-{=0A-=20=20HMODULE=20library=20=3D= =20w32_delayed_load=20(Qjson);=0A-=0A-=20=20if=20(!library)=0A-=20=20=20=20= return=20false;=0A-=0A-=20=20LOAD_DLL_FN=20(library,=20= json_set_alloc_funcs);=0A-=20=20LOAD_DLL_FN=20(library,=20json_delete);=0A= -=20=20LOAD_DLL_FN=20(library,=20json_array);=0A-=20=20LOAD_DLL_FN=20= (library,=20json_array_append_new);=0A-=20=20LOAD_DLL_FN=20(library,=20= json_array_size);=0A-=20=20LOAD_DLL_FN=20(library,=20json_object);=0A-=20= =20LOAD_DLL_FN=20(library,=20json_object_set_new);=0A-=20=20LOAD_DLL_FN=20= (library,=20json_null);=0A-=20=20LOAD_DLL_FN=20(library,=20json_true);=0A= -=20=20LOAD_DLL_FN=20(library,=20json_false);=0A-=20=20LOAD_DLL_FN=20= (library,=20json_integer);=0A-=20=20LOAD_DLL_FN=20(library,=20= json_real);=0A-=20=20LOAD_DLL_FN=20(library,=20json_stringn);=0A-=20=20= LOAD_DLL_FN=20(library,=20json_dumps);=0A-=20=20LOAD_DLL_FN=20(library,=20= json_dump_callback);=0A-=20=20LOAD_DLL_FN=20(library,=20= json_object_get);=0A-=0A-=20=20init_json=20();=0A-=0A-=20=20return=20= true;=0A-}=0A-=0A-#define=20json_set_alloc_funcs=20= fn_json_set_alloc_funcs=0A-#define=20json_array=20fn_json_array=0A= -#define=20json_array_append_new=20fn_json_array_append_new=0A-#define=20= json_array_size=20fn_json_array_size=0A-#define=20json_object=20= fn_json_object=0A-#define=20json_object_set_new=20fn_json_object_set_new=0A= -#define=20json_null=20fn_json_null=0A-#define=20json_true=20= fn_json_true=0A-#define=20json_false=20fn_json_false=0A-#define=20= json_integer=20fn_json_integer=0A-#define=20json_real=20fn_json_real=0A= -#define=20json_stringn=20fn_json_stringn=0A-#define=20json_dumps=20= fn_json_dumps=0A-#define=20json_dump_callback=20fn_json_dump_callback=0A= -#define=20json_object_get=20fn_json_object_get=0A-=0A-#endif=09/*=20= WINDOWSNT=20*/=0A-=0A-/*=20We=20install=20a=20custom=20allocator=20so=20= that=20we=20can=20avoid=20objects=20larger=0A-=20=20=20than=20= PTRDIFF_MAX.=20=20Such=20objects=20wouldn't=20play=20well=20with=20the=20= rest=20of=0A-=20=20=20Emacs's=20codebase,=20which=20generally=20uses=20= ptrdiff_t=20for=20sizes=20and=0A-=20=20=20indices.=20=20The=20other=20= functions=20in=20this=20file=20also=20generally=20assume=0A-=20=20=20= that=20size_t=20values=20never=20exceed=20PTRDIFF_MAX.=0A-=0A-=20=20=20= In=20addition,=20we=20need=20to=20use=20a=20custom=20allocator=20because=20= on=0A-=20=20=20MS-Windows=20we=20replace=20malloc/free=20with=20our=20= own=20functions,=20see=0A-=20=20=20w32heap.c,=20so=20we=20must=20force=20= the=20library=20to=20use=20our=20allocator,=20or=0A-=20=20=20else=20we=20= won't=20be=20able=20to=20free=20storage=20allocated=20by=20the=20= library.=20=20*/=0A-=0A-static=20void=20*=0A-json_malloc=20(size_t=20= size)=0A-{=0A-=20=20if=20(size=20>=20PTRDIFF_MAX)=0A-=20=20=20=20{=0A-=20= =20=20=20=20=20errno=20=3D=20ENOMEM;=0A-=20=20=20=20=20=20return=20NULL;=0A= -=20=20=20=20}=0A-=20=20return=20malloc=20(size);=0A-}=0A-=0A-static=20= void=0A-json_free=20(void=20*ptr)=0A-{=0A-=20=20free=20(ptr);=0A-}=0A-=0A= -void=0A-init_json=20(void)=0A-{=0A-=20=20json_set_alloc_funcs=20= (json_malloc,=20json_free);=0A-}=0A-=0A-/*=20Note=20that=20all=20callers=20= of=20make_string_from_utf8=20and=20build_string_from_utf8=0A-=20=20=20= below=20either=20pass=20only=20value=20UTF-8=20strings=20or=20use=20the=20= functionf=20for=0A-=20=20=20formatting=20error=20messages;=20in=20the=20= latter=20case=20correctness=20isn't=0A-=20=20=20critical.=20=20*/=0A-=0A= -/*=20Return=20a=20unibyte=20string=20containing=20the=20sequence=20of=20= UTF-8=20encoding=0A-=20=20=20units=20of=20the=20UTF-8=20representation=20= of=20STRING.=20=20If=20STRING=20does=20not=0A-=20=20=20represent=20a=20= sequence=20of=20Unicode=20scalar=20values,=20return=20a=20string=20with=0A= -=20=20=20unspecified=20contents.=20=20*/=0A-=0A-static=20Lisp_Object=0A= -json_encode=20(Lisp_Object=20string)=0A-{=0A-=20=20/*=20FIXME:=20Raise=20= an=20error=20if=20STRING=20is=20not=20a=20scalar=20value=0A-=20=20=20=20=20= sequence.=20=20*/=0A-=20=20return=20encode_string_utf_8=20(string,=20= Qnil,=20false,=20Qt,=20Qt);=0A-}=0A-=0A-static=20AVOID=0A= -json_out_of_memory=20(void)=0A-{=0A-=20=20xsignal0=20= (Qjson_out_of_memory);=0A-}=0A-=0A-static=20void=0A-json_release_object=20= (void=20*object)=0A-{=0A-=20=20json_decref=20(object);=0A-}=0A-=0A-/*=20= Signal=20an=20error=20if=20OBJECT=20is=20not=20a=20string,=20or=20if=20= OBJECT=20contains=0A-=20=20=20embedded=20null=20characters.=20=20*/=0A-=0A= -static=20void=0A-check_string_without_embedded_nulls=20(Lisp_Object=20= object)=0A-{=0A-=20=20CHECK_STRING=20(object);=0A-=20=20CHECK_TYPE=20= (memchr=20(SDATA=20(object),=20'\0',=20SBYTES=20(object))=20=3D=3D=20= NULL,=0A-=20=20=20=20=20=20=20=20=20=20=20=20=20=20= Qstring_without_embedded_nulls_p,=20object);=0A-}=0A-=0A-/*=20Signal=20= an=20error=20of=20type=20`json-out-of-memory'=20if=20OBJECT=20is=0A-=20=20= =20NULL.=20=20*/=0A-=0A-static=20json_t=20*=0A-json_check=20(json_t=20= *object)=0A-{=0A-=20=20if=20(object=20=3D=3D=20NULL)=0A-=20=20=20=20= json_out_of_memory=20();=0A-=20=20return=20object;=0A-}=0A-=0A-/*=20If=20= STRING=20is=20not=20a=20valid=20UTF-8=20string,=20signal=20an=20error=20= of=20type=0A-=20=20=20`wrong-type-argument'.=20=20STRING=20must=20be=20a=20= unibyte=20string.=20=20*/=0A-=0A-static=20void=0A-json_check_utf8=20= (Lisp_Object=20string)=0A-{=0A-=20=20CHECK_TYPE=20(utf8_string_p=20= (string),=20Qutf_8_string_p,=20string);=0A-}=0A-=0A=20enum=20= json_object_type=20{=0A=20=20=20json_object_hashtable,=0A=20=20=20= json_object_alist,=0A@@=20-226,179=20+47,6=20@@=20json_check_utf8=20= (Lisp_Object=20string)=0A=20=20=20Lisp_Object=20false_object;=0A=20};=0A=20= =0A-static=20json_t=20*lisp_to_json=20(Lisp_Object,=0A-=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= const=20struct=20json_configuration=20*conf);=0A-=0A-/*=20Convert=20a=20= Lisp=20object=20to=20a=20nonscalar=20JSON=20object=20(array=20or=20= object).=20=20*/=0A-=0A-static=20json_t=20*=0A-lisp_to_json_nonscalar_1=20= (Lisp_Object=20lisp,=0A-=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20const=20struct=20json_configuration=20*conf)=0A= -{=0A-=20=20json_t=20*json;=0A-=20=20specpdl_ref=20count;=0A-=0A-=20=20= if=20(VECTORP=20(lisp))=0A-=20=20=20=20{=0A-=20=20=20=20=20=20ptrdiff_t=20= size=20=3D=20ASIZE=20(lisp);=0A-=20=20=20=20=20=20json=20=3D=20= json_check=20(json_array=20());=0A-=20=20=20=20=20=20count=20=3D=20= SPECPDL_INDEX=20();=0A-=20=20=20=20=20=20record_unwind_protect_ptr=20= (json_release_object,=20json);=0A-=20=20=20=20=20=20for=20(ptrdiff_t=20i=20= =3D=200;=20i=20<=20size;=20++i)=0A-=20=20=20=20=20=20=20=20{=0A-=20=20=20= =20=20=20=20=20=20=20int=20status=0A-=20=20=20=20=20=20=20=20=20=20=20=20= =3D=20json_array_append_new=20(json,=20lisp_to_json=20(AREF=20(lisp,=20= i),=0A-=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20conf));=0A-=20=20=20=20=20=20=20=20=20=20= if=20(status=20=3D=3D=20-1)=0A-=20=20=20=20=20=20=20=20=20=20=20=20= json_out_of_memory=20();=0A-=20=20=20=20=20=20=20=20}=0A-=20=20=20=20=20=20= eassert=20(json_array_size=20(json)=20=3D=3D=20size);=0A-=20=20=20=20}=0A= -=20=20else=20if=20(HASH_TABLE_P=20(lisp))=0A-=20=20=20=20{=0A-=20=20=20=20= =20=20struct=20Lisp_Hash_Table=20*h=20=3D=20XHASH_TABLE=20(lisp);=0A-=20=20= =20=20=20=20json=20=3D=20json_check=20(json_object=20());=0A-=20=20=20=20= =20=20count=20=3D=20SPECPDL_INDEX=20();=0A-=20=20=20=20=20=20= record_unwind_protect_ptr=20(json_release_object,=20json);=0A-=20=20=20=20= =20=20DOHASH=20(h,=20key,=20v)=0A-=20=20=20=20=20=20=20=20{=0A-=09=20=20= CHECK_STRING=20(key);=0A-=09=20=20Lisp_Object=20ekey=20=3D=20json_encode=20= (key);=0A-=09=20=20/*=20We=20can't=20specify=20the=20length,=20so=20the=20= string=20must=20be=0A-=09=20=20=20=20=20null-terminated.=20=20*/=0A-=09=20= =20check_string_without_embedded_nulls=20(ekey);=0A-=09=20=20const=20= char=20*key_str=20=3D=20SSDATA=20(ekey);=0A-=09=20=20/*=20Reject=20= duplicate=20keys.=20=20These=20are=20possible=20if=20the=20hash=0A-=09=20= =20=20=20=20table=20test=20is=20not=20`equal'.=20=20*/=0A-=09=20=20if=20= (json_object_get=20(json,=20key_str)=20!=3D=20NULL)=0A-=09=20=20=20=20= wrong_type_argument=20(Qjson_value_p,=20lisp);=0A-=09=20=20int=20status=0A= -=09=20=20=20=20=3D=20json_object_set_new=20(json,=20key_str,=0A-=09=09=09= =09=20=20=20lisp_to_json=20(v,=20conf));=0A-=09=20=20if=20(status=20=3D=3D= =20-1)=0A-=09=20=20=20=20{=0A-=09=20=20=20=20=20=20/*=20A=20failure=20= can=20be=20caused=20either=20by=20an=20invalid=20key=20or=0A-=09=09=20by=20= low=20memory.=20=20*/=0A-=09=20=20=20=20=20=20json_check_utf8=20(ekey);=0A= -=09=20=20=20=20=20=20json_out_of_memory=20();=0A-=09=20=20=20=20}=0A-=09= }=0A-=20=20=20=20}=0A-=20=20else=20if=20(NILP=20(lisp))=0A-=20=20=20=20= return=20json_check=20(json_object=20());=0A-=20=20else=20if=20(CONSP=20= (lisp))=0A-=20=20=20=20{=0A-=20=20=20=20=20=20Lisp_Object=20tail=20=3D=20= lisp;=0A-=20=20=20=20=20=20json=20=3D=20json_check=20(json_object=20());=0A= -=20=20=20=20=20=20count=20=3D=20SPECPDL_INDEX=20();=0A-=20=20=20=20=20=20= record_unwind_protect_ptr=20(json_release_object,=20json);=0A-=20=20=20=20= =20=20bool=20is_plist=20=3D=20!CONSP=20(XCAR=20(tail));=0A-=20=20=20=20=20= =20FOR_EACH_TAIL=20(tail)=0A-=20=20=20=20=20=20=20=20{=0A-=20=20=20=20=20= =20=20=20=20=20const=20char=20*key_str;=0A-=20=20=20=20=20=20=20=20=20=20= Lisp_Object=20value;=0A-=20=20=20=20=20=20=20=20=20=20Lisp_Object=20= key_symbol;=0A-=20=20=20=20=20=20=20=20=20=20if=20(is_plist)=0A-=20=20=20= =20=20=20=20=20=20=20=20=20{=0A-=20=20=20=20=20=20=20=20=20=20=20=20=20=20= key_symbol=20=3D=20XCAR=20(tail);=0A-=20=20=20=20=20=20=20=20=20=20=20=20= =20=20tail=20=3D=20XCDR=20(tail);=0A-=20=20=20=20=20=20=20=20=20=20=20=20= =20=20CHECK_CONS=20(tail);=0A-=20=20=20=20=20=20=20=20=20=20=20=20=20=20= value=20=3D=20XCAR=20(tail);=0A-=20=20=20=20=20=20=20=20=20=20=20=20}=0A= -=20=20=20=20=20=20=20=20=20=20else=0A-=20=20=20=20=20=20=20=20=20=20=20=20= {=0A-=20=20=20=20=20=20=20=20=20=20=20=20=20=20Lisp_Object=20pair=20=3D=20= XCAR=20(tail);=0A-=20=20=20=20=20=20=20=20=20=20=20=20=20=20CHECK_CONS=20= (pair);=0A-=20=20=20=20=20=20=20=20=20=20=20=20=20=20key_symbol=20=3D=20= XCAR=20(pair);=0A-=20=20=20=20=20=20=20=20=20=20=20=20=20=20value=20=3D=20= XCDR=20(pair);=0A-=20=20=20=20=20=20=20=20=20=20=20=20}=0A-=20=20=20=20=20= =20=20=20=20=20CHECK_SYMBOL=20(key_symbol);=0A-=20=20=20=20=20=20=20=20=20= =20Lisp_Object=20key=20=3D=20SYMBOL_NAME=20(key_symbol);=0A-=20=20=20=20=20= =20=20=20=20=20/*=20We=20can't=20specify=20the=20length,=20so=20the=20= string=20must=20be=0A-=20=20=20=20=20=20=20=20=20=20=20=20=20= null-terminated.=20=20*/=0A-=20=20=20=20=20=20=20=20=20=20= check_string_without_embedded_nulls=20(key);=0A-=20=20=20=20=20=20=20=20=20= =20key_str=20=3D=20SSDATA=20(key);=0A-=20=20=20=20=20=20=20=20=20=20/*=20= In=20plists,=20ensure=20leading=20":"=20in=20keys=20is=20stripped.=20=20= It=0A-=20=20=20=20=20=20=20=20=20=20=20=20=20will=20be=20reconstructed=20= later=20in=20`json_to_lisp'.*/=0A-=20=20=20=20=20=20=20=20=20=20if=20= (is_plist=20&&=20':'=20=3D=3D=20key_str[0]=20&&=20key_str[1])=0A-=20=20=20= =20=20=20=20=20=20=20=20=20{=0A-=20=20=20=20=20=20=20=20=20=20=20=20=20=20= key_str=20=3D=20&key_str[1];=0A-=20=20=20=20=20=20=20=20=20=20=20=20}=0A= -=20=20=20=20=20=20=20=20=20=20/*=20Only=20add=20element=20if=20key=20is=20= not=20already=20present.=20=20*/=0A-=20=20=20=20=20=20=20=20=20=20if=20= (json_object_get=20(json,=20key_str)=20=3D=3D=20NULL)=0A-=20=20=20=20=20=20= =20=20=20=20=20=20{=0A-=20=20=20=20=20=20=20=20=20=20=20=20=20=20int=20= status=0A-=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=3D=20= json_object_set_new=20(json,=20key_str,=20lisp_to_json=20(value,=0A-=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20conf));=0A-=20=20=20=20=20= =20=20=20=20=20=20=20=20=20if=20(status=20=3D=3D=20-1)=0A-=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20json_out_of_memory=20();=0A-=20=20=20=20= =20=20=20=20=20=20=20=20}=0A-=20=20=20=20=20=20=20=20}=0A-=20=20=20=20=20= =20CHECK_LIST_END=20(tail,=20lisp);=0A-=20=20=20=20}=0A-=20=20else=0A-=20= =20=20=20wrong_type_argument=20(Qjson_value_p,=20lisp);=0A-=0A-=20=20= clear_unwind_protect=20(count);=0A-=20=20unbind_to=20(count,=20Qnil);=0A= -=20=20return=20json;=0A-}=0A-=0A-/*=20Convert=20LISP=20to=20a=20= nonscalar=20JSON=20object=20(array=20or=20object).=20=20Signal=0A-=20=20=20= an=20error=20of=20type=20`wrong-type-argument'=20if=20LISP=20is=20not=20= a=20vector,=0A-=20=20=20hashtable,=20alist,=20or=20plist.=20=20*/=0A-=0A= -static=20json_t=20*=0A-lisp_to_json_nonscalar=20(Lisp_Object=20lisp,=0A= -=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= const=20struct=20json_configuration=20*conf)=0A-{=0A-=20=20if=20= (++lisp_eval_depth=20>=20max_lisp_eval_depth)=0A-=20=20=20=20xsignal0=20= (Qjson_object_too_deep);=0A-=20=20json_t=20*json=20=3D=20= lisp_to_json_nonscalar_1=20(lisp,=20conf);=0A-=20=20--lisp_eval_depth;=0A= -=20=20return=20json;=0A-}=0A-=0A-/*=20Convert=20LISP=20to=20any=20JSON=20= object.=20=20Signal=20an=20error=20of=20type=0A-=20=20=20= `wrong-type-argument'=20if=20the=20type=20of=20LISP=20can't=20be=20= converted=20to=20a=0A-=20=20=20JSON=20object.=20=20*/=0A-=0A-static=20= json_t=20*=0A-lisp_to_json=20(Lisp_Object=20lisp,=20const=20struct=20= json_configuration=20*conf)=0A-{=0A-=20=20if=20(EQ=20(lisp,=20= conf->null_object))=0A-=20=20=20=20return=20json_check=20(json_null=20= ());=0A-=20=20else=20if=20(EQ=20(lisp,=20conf->false_object))=0A-=20=20=20= =20return=20json_check=20(json_false=20());=0A-=20=20else=20if=20(EQ=20= (lisp,=20Qt))=0A-=20=20=20=20return=20json_check=20(json_true=20());=0A-=20= =20else=20if=20(INTEGERP=20(lisp))=0A-=20=20=20=20{=0A-=20=20=20=20=20=20= intmax_t=20low=20=3D=20TYPE_MINIMUM=20(json_int_t);=0A-=20=20=20=20=20=20= intmax_t=20high=20=3D=20TYPE_MAXIMUM=20(json_int_t);=0A-=20=20=20=20=20=20= intmax_t=20value=20=3D=20check_integer_range=20(lisp,=20low,=20high);=0A= -=20=20=20=20=20=20return=20json_check=20(json_integer=20(value));=0A-=20= =20=20=20}=0A-=20=20else=20if=20(FLOATP=20(lisp))=0A-=20=20=20=20return=20= json_check=20(json_real=20(XFLOAT_DATA=20(lisp)));=0A-=20=20else=20if=20= (STRINGP=20(lisp))=0A-=20=20=20=20{=0A-=20=20=20=20=20=20Lisp_Object=20= encoded=20=3D=20json_encode=20(lisp);=0A-=20=20=20=20=20=20json_t=20= *json=20=3D=20json_stringn=20(SSDATA=20(encoded),=20SBYTES=20(encoded));=0A= -=20=20=20=20=20=20if=20(json=20=3D=3D=20NULL)=0A-=20=20=20=20=20=20=20=20= {=0A-=20=20=20=20=20=20=20=20=20=20/*=20A=20failure=20can=20be=20caused=20= either=20by=20an=20invalid=20string=20or=20by=0A-=20=20=20=20=20=20=20=20= =20=20=20=20=20low=20memory.=20=20*/=0A-=20=20=20=20=20=20=20=20=20=20= json_check_utf8=20(encoded);=0A-=20=20=20=20=20=20=20=20=20=20= json_out_of_memory=20();=0A-=20=20=20=20=20=20=20=20}=0A-=20=20=20=20=20=20= return=20json;=0A-=20=20=20=20}=0A-=0A-=20=20/*=20LISP=20now=20must=20be=20= a=20vector,=20hashtable,=20alist,=20or=20plist.=20=20*/=0A-=20=20return=20= lisp_to_json_nonscalar=20(lisp,=20conf);=0A-}=0A-=0A=20static=20void=0A=20= json_parse_args=20(ptrdiff_t=20nargs,=0A=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20Lisp_Object=20*args,=0A@@=20-450,158=20+98,533=20@@=20= json_parse_args=20(ptrdiff_t=20nargs,=0A=20=20=20}=0A=20}=0A=20=0A= -static=20bool=0A-json_available_p=20(void)=0A+/*=20FIXME:=20Remove=20= completely.=20=20*/=0A+DEFUN=20("json--available-p",=20= Fjson__available_p,=20Sjson__available_p,=200,=200,=20NULL,=0A+=20=20=20=20= =20=20=20doc:=20/*=20Return=20non-nil=20if=20libjansson=20is=20available=20= (internal=20use=20only).=20=20*/)=0A+=20=20(void)=0A=20{=0A-#ifdef=20= WINDOWSNT=0A-=20=20if=20(!json_initialized)=0A-=20=20=20=20{=0A-=20=20=20= =20=20=20Lisp_Object=20status;=0A-=20=20=20=20=20=20json_initialized=20=3D= =20init_json_functions=20();=0A-=20=20=20=20=20=20status=20=3D=20= json_initialized=20?=20Qt=20:=20Qnil;=0A-=20=20=20=20=20=20= Vlibrary_cache=20=3D=20Fcons=20(Fcons=20(Qjson,=20status),=20= Vlibrary_cache);=0A-=20=20=20=20}=0A-=20=20return=20json_initialized;=0A= -#else=20=20/*=20!WINDOWSNT=20*/=0A-=20=20return=20true;=0A-#endif=0A+=20= =20return=20Qt;=0A=20}=0A=20=0A-#ifdef=20WINDOWSNT=0A+/*=20JSON=20= encoding=20context.=20=20*/=0A+typedef=20struct=20{=0A+=20=20char=20= *buf;=0A+=20=20ptrdiff_t=20size;=09=20=20=20=20=20=20/*=20number=20of=20= bytes=20in=20buf=20*/=0A+=20=20ptrdiff_t=20capacity;=09=20=20=20=20=20=20= /*=20allocated=20size=20of=20buf=20*/=0A+=20=20ptrdiff_t=20chars_delta;=20= =20=20=20=20=20/*=20size=20-=20{number=20of=20characters=20in=20buf}=20= */=0A+=0A+=20=20int=20maxdepth;=0A+=20=20struct=20symset_tbl=20= *ss_table;=09/*=20table=20used=20by=20containing=20object=20*/=0A+=20=20= struct=20json_configuration=20conf;=0A+}=20json_out_t;=0A+=0A+/*=20Set=20= of=20symbols.=20=20*/=0A+typedef=20struct=20{=0A+=20=20ptrdiff_t=20= count;=09=09/*=20symbols=20in=20table=20*/=0A+=20=20int=20bits;=09=09=09= /*=20log2(table=20size)=20*/=0A+=20=20struct=20symset_tbl=20*table;=09/*=20= heap-allocated=20table=20*/=0A+}=20symset_t;=0A+=0A+struct=20symset_tbl=0A= +{=0A+=20=20/*=20Table=20used=20by=20the=20containing=20object=20if=20= any,=20so=20that=20we=20can=20free=20all=0A+=20=20=20=20=20tables=20if=20= an=20error=20occurs.=20=20*/=0A+=20=20struct=20symset_tbl=20*up;=0A+=20=20= /*=20Table=20of=20symbols=20(2**bits=20elements),=20Qunbound=20where=20= unused.=20=20*/=0A+=20=20Lisp_Object=20entries[];=0A+};=0A+=0A+static=20= inline=20ptrdiff_t=0A+symset_size=20(int=20bits)=0A+{=0A+=20=20return=20= (ptrdiff_t)1=20<<=20bits;=0A+}=0A+=0A+static=20struct=20symset_tbl=20*=0A= +make_symset_table=20(int=20bits,=20struct=20symset_tbl=20*up)=0A+{=0A+=20= =20int=20maxbits=20=3D=20min=20(SIZE_WIDTH=20-=202=20-=20(word_size=20<=20= 8=20?=202=20:=203),=2032);=0A+=20=20if=20(bits=20>=20maxbits)=0A+=20=20=20= =20error=20("out=20of=20memory");=09/*=20Will=20never=20happen=20in=20= practice.=20=20*/=0A+=20=20struct=20symset_tbl=20*st=20=3D=20xnmalloc=20= (sizeof=20*st->entries=20<<=20bits,=20sizeof=20*st);=0A+=20=20st->up=20=3D= =20up;=0A+=20=20ptrdiff_t=20size=20=3D=20symset_size=20(bits);=0A+=20=20= for=20(ptrdiff_t=20i=20=3D=200;=20i=20<=20size;=20i++)=0A+=20=20=20=20= st->entries[i]=20=3D=20Qunbound;=0A+=20=20return=20st;=0A+}=0A+=0A+/*=20= Create=20a=20new=20symset=20to=20use=20for=20a=20new=20object.=20=20*/=0A= +static=20symset_t=0A+push_symset=20(json_out_t=20*jo)=0A+{=0A+=20=20int=20= bits=20=3D=204;=0A+=20=20struct=20symset_tbl=20*tbl=20=3D=20= make_symset_table=20(bits,=20jo->ss_table);=0A+=20=20jo->ss_table=20=3D=20= tbl;=0A+=20=20return=20(symset_t){=20.count=20=3D=200,=20.bits=20=3D=20= bits,=20.table=20=3D=20tbl=20};=0A+}=0A+=0A+/*=20Destroy=20the=20current=20= symset.=20=20*/=0A=20static=20void=0A-ensure_json_available=20(void)=0A= +pop_symset=20(json_out_t=20*jo,=20symset_t=20*ss)=0A=20{=0A-=20=20if=20= (!json_available_p=20())=0A-=20=20=20=20Fsignal=20(Qjson_unavailable,=0A= -=09=20=20=20=20=20list1=20(build_unibyte_string=20("jansson=20library=20= not=20found")));=0A+=20=20jo->ss_table=20=3D=20ss->table->up;=0A+=20=20= xfree=20(ss->table);=0A=20}=0A-#endif=0A=20=0A-DEFUN=20= ("json--available-p",=20Fjson__available_p,=20Sjson__available_p,=200,=20= 0,=20NULL,=0A-=20=20=20=20=20=20=20doc:=20/*=20Return=20non-nil=20if=20= libjansson=20is=20available=20(internal=20use=20only).=20=20*/)=0A-=20=20= (void)=0A+/*=20Remove=20all=20heap-allocated=20symset=20tables,=20in=20= case=20an=20error=20occurred.=20=20*/=0A+static=20void=0A= +cleanup_symset_tables=20(struct=20symset_tbl=20*st)=0A=20{=0A-=20=20= return=20json_available_p=20()=20?=20Qt=20:=20Qnil;=0A+=20=20while=20= (st)=0A+=20=20=20=20{=0A+=20=20=20=20=20=20struct=20symset_tbl=20*up=20=3D= =20st->up;=0A+=20=20=20=20=20=20xfree=20(st);=0A+=20=20=20=20=20=20st=20= =3D=20up;=0A+=20=20=20=20}=0A=20}=0A=20=0A-DEFUN=20("json-serialize",=20= Fjson_serialize,=20Sjson_serialize,=201,=20MANY,=0A-=20=20=20=20=20=20=20= NULL,=0A-=20=20=20=20=20=20=20doc:=20/*=20Return=20the=20JSON=20= representation=20of=20OBJECT=20as=20a=20string.=0A+static=20inline=20= uint32_t=0A+symset_hash=20(Lisp_Object=20sym,=20int=20bits)=0A+{=0A+=20=20= return=20knuth_hash=20(reduce_emacs_uint_to_hash_hash=20(XHASH=20(sym)),=20= bits);=0A+}=0A=20=0A-OBJECT=20must=20be=20t,=20a=20number,=20string,=20= vector,=20hashtable,=20alist,=20plist,=0A-or=20the=20Lisp=20equivalents=20= to=20the=20JSON=20null=20and=20false=20values,=20and=20its=0A-elements=20= must=20recursively=20consist=20of=20the=20same=20kinds=20of=20values.=20=20= t=20will=0A-be=20converted=20to=20the=20JSON=20true=20value.=20=20= Vectors=20will=20be=20converted=20to=0A-JSON=20arrays,=20whereas=20= hashtables,=20alists=20and=20plists=20are=20converted=20to=0A-JSON=20= objects.=20=20Hashtable=20keys=20must=20be=20strings=20without=20= embedded=20null=0A-characters=20and=20must=20be=20unique=20within=20each=20= object.=20=20Alist=20and=20plist=0A-keys=20must=20be=20symbols;=20if=20a=20= key=20is=20duplicate,=20the=20first=20instance=20is=0A-used.=0A+/*=20= Enlarge=20the=20table=20used=20by=20a=20symset.=20=20*/=0A+static=20= NO_INLINE=20void=0A+symset_expand=20(symset_t=20*ss)=0A+{=0A+=20=20= struct=20symset_tbl=20*old_table=20=3D=20ss->table;=0A+=20=20int=20= oldbits=20=3D=20ss->bits;=0A+=20=20ptrdiff_t=20oldsize=20=3D=20= symset_size=20(oldbits);=0A+=20=20int=20bits=20=3D=20oldbits=20+=201;=0A= +=20=20ss->bits=20=3D=20bits;=0A+=20=20ss->table=20=3D=20= make_symset_table=20(bits,=20old_table->up);=0A+=20=20/*=20Move=20all=20= entries=20from=20the=20old=20table=20to=20the=20new=20one.=20=20*/=0A+=20= =20ptrdiff_t=20mask=20=3D=20symset_size=20(bits)=20-=201;=0A+=20=20= struct=20symset_tbl=20*tbl=20=3D=20ss->table;=0A+=20=20for=20(ptrdiff_t=20= i=20=3D=200;=20i=20<=20oldsize;=20i++)=0A+=20=20=20=20{=0A+=20=20=20=20=20= =20Lisp_Object=20sym=20=3D=20old_table->entries[i];=0A+=20=20=20=20=20=20= if=20(!BASE_EQ=20(sym,=20Qunbound))=0A+=09{=0A+=09=20=20ptrdiff_t=20j=20= =3D=20symset_hash=20(sym,=20bits);=0A+=09=20=20while=20(!BASE_EQ=20= (tbl->entries[j],=20Qunbound))=0A+=09=20=20=20=20j=20=3D=20(j=20+=201)=20= &=20mask;=0A+=09=20=20tbl->entries[j]=20=3D=20sym;=0A+=09}=0A+=20=20=20=20= }=0A+=20=20xfree=20(old_table);=0A+}=0A=20=0A-The=20Lisp=20equivalents=20= to=20the=20JSON=20null=20and=20false=20values=20are=0A-configurable=20in=20= the=20arguments=20ARGS,=20a=20list=20of=20keyword/argument=20pairs:=0A= +/*=20If=20sym=20is=20in=20ss,=20return=20false;=20otherwise=20add=20it=20= and=20return=20true.=0A+=20=20=20Comparison=20is=20done=20by=20strict=20= identity.=20=20*/=0A+static=20inline=20bool=0A+symset_add=20(json_out_t=20= *jo,=20symset_t=20*ss,=20Lisp_Object=20sym)=0A+{=0A+=20=20/*=20Make=20= sure=20we=20don't=20fill=20more=20than=20half=20of=20the=20table.=20=20= */=0A+=20=20if=20(ss->count=20>=3D=20(symset_size=20(ss->bits)=20>>=20= 1))=0A+=20=20=20=20{=0A+=20=20=20=20=20=20symset_expand=20(ss);=0A+=20=20= =20=20=20=20jo->ss_table=20=3D=20ss->table;=0A+=20=20=20=20}=0A=20=0A= -The=20keyword=20argument=20`:null-object'=20specifies=20which=20object=20= to=20use=0A-to=20represent=20a=20JSON=20null=20value.=20=20It=20defaults=20= to=20`:null'.=0A+=20=20struct=20symset_tbl=20*tbl=20=3D=20ss->table;=0A+=20= =20ptrdiff_t=20mask=20=3D=20symset_size=20(ss->bits)=20-=201;=0A+=20=20= for=20(ptrdiff_t=20i=20=3D=20symset_hash=20(sym,=20ss->bits);=20;=20i=20= =3D=20(i=20+=201)=20&=20mask)=0A+=20=20=20=20{=0A+=20=20=20=20=20=20= Lisp_Object=20s=20=3D=20tbl->entries[i];=0A+=20=20=20=20=20=20if=20= (BASE_EQ=20(s,=20sym))=0A+=09return=20false;=09=09/*=20Previous=20= occurrence=20found.=20=20*/=0A+=20=20=20=20=20=20if=20(BASE_EQ=20(s,=20= Qunbound))=0A+=09{=0A+=09=20=20/*=20Not=20in=20set,=20add=20it.=20=20*/=0A= +=09=20=20tbl->entries[i]=20=3D=20sym;=0A+=09=20=20ss->count++;=0A+=09=20= =20return=20true;=0A+=09}=0A+=20=20=20=20}=0A+}=0A=20=0A-The=20keyword=20= argument=20`:false-object'=20specifies=20which=20object=20to=20use=20to=0A= -represent=20a=20JSON=20false=20value.=20=20It=20defaults=20to=20= `:false'.=0A+static=20NO_INLINE=20void=0A+json_out_grow_buf=20= (json_out_t=20*jo,=20ptrdiff_t=20bytes)=0A+{=0A+=20=20ptrdiff_t=20need=20= =3D=20jo->size=20+=20bytes;=0A+=20=20ptrdiff_t=20new_size=20=3D=20max=20= (jo->capacity,=20512);=0A+=20=20while=20(new_size=20<=20need)=0A+=20=20=20= =20new_size=20<<=3D=201;=0A+=20=20jo->buf=20=3D=20xrealloc=20(jo->buf,=20= new_size);=0A+=20=20jo->capacity=20=3D=20new_size;=0A+}=0A=20=0A-In=20= you=20specify=20the=20same=20value=20for=20`:null-object'=20and=20= `:false-object',=0A-a=20potentially=20ambiguous=20situation,=20the=20= JSON=20output=20will=20not=20contain=0A-any=20JSON=20false=20values.=0A= -usage:=20(json-serialize=20OBJECT=20&rest=20ARGS)=20=20*/)=0A-=20=20=20=20= =20(ptrdiff_t=20nargs,=20Lisp_Object=20*args)=0A+static=20void=0A= +cleanup_json_out=20(void=20*arg)=0A=20{=0A-=20=20specpdl_ref=20count=20= =3D=20SPECPDL_INDEX=20();=0A+=20=20json_out_t=20*jo=20=3D=20arg;=0A+=20=20= xfree=20(jo->buf);=0A+=20=20jo->buf=20=3D=20NULL;=0A+=20=20= cleanup_symset_tables=20(jo->ss_table);=0A+}=0A=20=0A-#ifdef=20WINDOWSNT=0A= -=20=20ensure_json_available=20();=0A-#endif=0A+/*=20Make=20room=20for=20= `bytes`=20more=20bytes=20in=20buffer.=20=20*/=0A+static=20void=0A= +json_make_room=20(json_out_t=20*jo,=20ptrdiff_t=20bytes)=0A+{=0A+=20=20= if=20(bytes=20>=20jo->capacity=20-=20jo->size)=0A+=20=20=20=20= json_out_grow_buf=20(jo,=20bytes);=0A+}=0A=20=0A-=20=20struct=20= json_configuration=20conf=20=3D=0A-=20=20=20=20{json_object_hashtable,=20= json_array_array,=20QCnull,=20QCfalse};=0A-=20=20json_parse_args=20= (nargs=20-=201,=20args=20+=201,=20&conf,=20false);=0A+#define=20= JSON_OUT_STR(jo,=20str)=20(json_out_str=20(jo,=20str,=20sizeof=20(str)=20= -=201))=0A=20=0A-=20=20json_t=20*json=20=3D=20lisp_to_json=20(args[0],=20= &conf);=0A-=20=20record_unwind_protect_ptr=20(json_release_object,=20= json);=0A+/*=20Add=20`bytes`=20bytes=20from=20`str`=20to=20the=20buffer.=20= =20*/=0A+static=20void=0A+json_out_str=20(json_out_t=20*jo,=20const=20= char=20*str,=20size_t=20bytes)=0A+{=0A+=20=20json_make_room=20(jo,=20= bytes);=0A+=20=20memcpy=20(jo->buf=20+=20jo->size,=20str,=20bytes);=0A+=20= =20jo->size=20+=3D=20bytes;=0A+}=0A=20=0A-=20=20char=20*string=20=3D=20= json_dumps=20(json,=20JSON_COMPACT=20|=20JSON_ENCODE_ANY);=0A-=20=20if=20= (string=20=3D=3D=20NULL)=0A-=20=20=20=20json_out_of_memory=20();=0A-=20=20= record_unwind_protect_ptr=20(json_free,=20string);=0A+static=20void=0A= +json_out_byte=20(json_out_t=20*jo,=20unsigned=20char=20c)=0A+{=0A+=20=20= json_make_room=20(jo,=201);=0A+=20=20jo->buf[jo->size++]=20=3D=20c;=0A+}=0A= =20=0A-=20=20return=20unbind_to=20(count,=20build_string_from_utf8=20= (string));=0A+static=20void=0A+json_out_fixnum=20(json_out_t=20*jo,=20= EMACS_INT=20x)=0A+{=0A+=20=20char=20buf[INT_BUFSIZE_BOUND=20= (EMACS_INT)];=0A+=20=20char=20*end=20=3D=20buf=20+=20sizeof=20buf;=0A+=20= =20char=20*p=20=3D=20fixnum_to_string=20(x,=20buf,=20end);=0A+=20=20= json_out_str=20(jo,=20p,=20end=20-=20p);=0A=20}=0A=20=0A-struct=20= json_buffer_and_size=0A+static=20AVOID=0A+string_not_unicode=20= (Lisp_Object=20obj)=0A=20{=0A-=20=20const=20char=20*buffer;=0A-=20=20= ptrdiff_t=20size;=0A-=20=20/*=20This=20tracks=20how=20many=20bytes=20= were=20inserted=20by=20the=20callback=20since=0A-=20=20=20=20=20= json_dump_callback=20was=20called.=20=20*/=0A-=20=20ptrdiff_t=20= inserted_bytes;=0A+=20=20/*=20FIXME:=20this=20is=20just=20for=20= compatibility=20with=20existing=20tests,=20it's=20not=0A+=20=20=20=20=20= a=20very=20descriptive=20error.=20=20*/=0A+=20=20wrong_type_argument=20= (Qjson_value_p,=20obj);=0A+}=0A+=0A+static=20const=20unsigned=20char=20= json_plain_char[256]=20=3D=20{=0A+=20=20/*=2032=20chars/line:=201=20for=20= printable=20ASCII=20+=20DEL=20except=20"=20and=20\,=200=20elsewhere=20*/=0A= +=20=200,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,=20= /*=2000-1f=20*/=0A+=20=20= 1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,=20/*=20= 20-3f=20*/=0A+=20=20= 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,=20/*=20= 40-5f=20*/=0A+=20=20= 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,=20/*=20= 60-7f=20*/=0A+=20=20= 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,=20/*=20= 80-9f=20*/=0A+=20=20= 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,=20/*=20= a0-bf=20*/=0A+=20=20= 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,=20/*=20= c0-df=20*/=0A+=20=20= 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,=20/*=20= e0-ff=20*/=0A=20};=0A=20=0A-static=20Lisp_Object=0A-json_insert=20(void=20= *data)=0A+static=20void=0A+json_out_string=20(json_out_t=20*jo,=20= Lisp_Object=20str,=20int=20skip)=0A+{=0A+=20=20/*=20FIXME:=20this=20code=20= is=20slow,=20make=20faster!=20*/=0A+=0A+=20=20static=20const=20char=20= hexchar[16]=20=3D=20"0123456789ABCDEF";=0A+=20=20ptrdiff_t=20len=20=3D=20= SBYTES=20(str);=0A+=20=20json_make_room=20(jo,=20len=20+=202);=0A+=20=20= json_out_byte=20(jo,=20'"');=0A+=20=20unsigned=20char=20*p=20=3D=20SDATA=20= (str);=0A+=20=20unsigned=20char=20*end=20=3D=20p=20+=20len;=0A+=20=20p=20= +=3D=20skip;=0A+=20=20while=20(p=20<=20end)=0A+=20=20=20=20{=0A+=20=20=20= =20=20=20unsigned=20char=20c=20=3D=20*p;=0A+=20=20=20=20=20=20if=20= (json_plain_char[c])=0A+=09{=0A+=09=20=20json_out_byte=20(jo,=20c);=0A+=09= =20=20p++;=0A+=09}=0A+=20=20=20=20=20=20else=20if=20(c=20>=200x7f)=0A+=09= {=0A+=09=20=20if=20(STRING_MULTIBYTE=20(str))=0A+=09=20=20=20=20{=0A+=09=20= =20=20=20=20=20int=20n;=0A+=09=20=20=20=20=20=20if=20(c=20<=3D=200xc1)=0A= +=09=09string_not_unicode=20(str);=0A+=09=20=20=20=20=20=20if=20(c=20<=3D=20= 0xdf)=0A+=09=09n=20=3D=202;=0A+=09=20=20=20=20=20=20else=20if=20(c=20<=3D=20= 0xef)=0A+=09=09{=0A+=09=09=20=20int=20v=20=3D=20(((c=20&=200x0f)=20<<=20= 12)=0A+=09=09=09=20=20=20+=20((p[1]=20&=200x3f)=20<<=206)=20+=20(p[2]=20= &=200x3f));=0A+=09=09=20=20if=20(char_surrogate_p=20(v))=0A+=09=09=20=20=20= =20string_not_unicode=20(str);=0A+=09=09=20=20n=20=3D=203;=0A+=09=09}=0A= +=09=20=20=20=20=20=20else=20if=20(c=20<=3D=200xf7)=0A+=09=09{=0A+=09=09=20= =20int=20v=20=3D=20(((c=20&=200x07)=20<<=2018)=0A+=09=09=09=20=20=20+=20= ((p[1]=20&=200x3f)=20<<=2012)=0A+=09=09=09=20=20=20+=20((p[2]=20&=20= 0x3f)=20<<=206)=0A+=09=09=09=20=20=20+=20(p[3]=20&=200x3f));=0A+=09=09=20= =20if=20(v=20>=20MAX_UNICODE_CHAR)=0A+=09=09=20=20=20=20= string_not_unicode=20(str);=0A+=09=09=20=20n=20=3D=204;=0A+=09=09}=0A+=09= =20=20=20=20=20=20else=0A+=09=09string_not_unicode=20(str);=0A+=09=20=20=20= =20=20=20json_out_str=20(jo,=20(const=20char=20*)p,=20n);=0A+=09=20=20=20= =20=20=20jo->chars_delta=20+=3D=20n=20-=201;=0A+=09=20=20=20=20=20=20p=20= +=3D=20n;=0A+=09=20=20=20=20}=0A+=09=20=20else=0A+=09=20=20=20=20= string_not_unicode=20(str);=0A+=09}=0A+=20=20=20=20=20=20else=0A+=09{=0A= +=09=20=20json_out_byte=20(jo,=20'\\');=0A+=09=20=20switch=20(c)=0A+=09=20= =20=20=20{=0A+=09=20=20=20=20case=20'"':=0A+=09=20=20=20=20case=20'\\':=20= json_out_byte=20(jo,=20c);=20break;=0A+=09=20=20=20=20case=20'\b':=20= json_out_byte=20(jo,=20'b');=20break;=0A+=09=20=20=20=20case=20'\t':=20= json_out_byte=20(jo,=20't');=20break;=0A+=09=20=20=20=20case=20'\n':=20= json_out_byte=20(jo,=20'n');=20break;=0A+=09=20=20=20=20case=20'\f':=20= json_out_byte=20(jo,=20'f');=20break;=0A+=09=20=20=20=20case=20'\r':=20= json_out_byte=20(jo,=20'r');=20break;=0A+=09=20=20=20=20default:=0A+=09=20= =20=20=20=20=20{=0A+=09=09char=20hex[5]=20=3D=20{=20'u',=20'0',=20'0',=0A= +=09=09=09=09hexchar[c=20>>=204],=20hexchar[c=20&=200xf]=20};=0A+=09=09= json_out_str=20(jo,=20hex,=205);=0A+=09=09break;=0A+=09=20=20=20=20=20=20= }=0A+=09=20=20=20=20}=0A+=09=20=20p++;=0A+=09}=0A+=20=20=20=20}=0A+=20=20= json_out_byte=20(jo,=20'"');=0A+}=0A+=0A+static=20void=0A+json_out_nest=20= (json_out_t=20*jo)=0A+{=0A+=20=20--jo->maxdepth;=0A+=20=20if=20= (jo->maxdepth=20<=200)=0A+=20=20=20=20error=20("Maximum=20JSON=20= serialisation=20depth=20exceeded");=0A+}=0A+=0A+static=20void=0A= +json_out_unnest=20(json_out_t=20*jo)=0A=20{=0A-=20=20struct=20= json_buffer_and_size=20*buffer_and_size=20=3D=20data;=0A-=20=20ptrdiff_t=20= len=20=3D=20buffer_and_size->size;=0A-=20=20ptrdiff_t=20inserted_bytes=20= =3D=20buffer_and_size->inserted_bytes;=0A-=20=20ptrdiff_t=20gap_size=20=3D= =20GAP_SIZE=20-=20inserted_bytes;=0A+=20=20++jo->maxdepth;=0A+}=0A=20=0A= -=20=20/*=20Enlarge=20the=20gap=20if=20necessary.=20=20*/=0A-=20=20if=20= (gap_size=20<=20len)=0A-=20=20=20=20make_gap=20(len=20-=20gap_size);=0A= +static=20void=20json_out_something=20(json_out_t=20*jo,=20Lisp_Object=20= obj);=0A=20=0A-=20=20/*=20Copy=20this=20chunk=20of=20data=20into=20the=20= gap.=20=20*/=0A-=20=20memcpy=20((char=20*)=20BEG_ADDR=20+=20PT_BYTE=20-=20= BEG_BYTE=20+=20inserted_bytes,=0A-=09=20=20buffer_and_size->buffer,=20= len);=0A-=20=20buffer_and_size->inserted_bytes=20+=3D=20len;=0A-=20=20= return=20Qnil;=0A+static=20void=0A+json_out_object_cons=20(json_out_t=20= *jo,=20Lisp_Object=20obj)=0A+{=0A+=20=20json_out_nest=20(jo);=0A+=20=20= symset_t=20ss=20=3D=20push_symset=20(jo);=0A+=20=20json_out_byte=20(jo,=20= '{');=0A+=20=20bool=20is_alist=20=3D=20CONSP=20(XCAR=20(obj));=0A+=20=20= bool=20first=20=3D=20true;=0A+=20=20Lisp_Object=20tail=20=3D=20obj;=0A+=20= =20FOR_EACH_TAIL=20(tail)=0A+=20=20=20=20{=0A+=20=20=20=20=20=20= Lisp_Object=20key;=0A+=20=20=20=20=20=20Lisp_Object=20value;=0A+=20=20=20= =20=20=20if=20(is_alist)=0A+=09{=0A+=09=20=20Lisp_Object=20pair=20=3D=20= XCAR=20(tail);=0A+=09=20=20CHECK_CONS=20(pair);=0A+=09=20=20key=20=3D=20= XCAR=20(pair);=0A+=09=20=20value=20=3D=20XCDR=20(pair);=0A+=09}=0A+=20=20= =20=20=20=20else=0A+=09{=0A+=09=20=20key=20=3D=20XCAR=20(tail);=0A+=09=20= =20tail=20=3D=20XCDR=20(tail);=0A+=09=20=20CHECK_CONS=20(tail);=0A+=09=20= =20value=20=3D=20XCAR=20(tail);=0A+=09}=0A+=20=20=20=20=20=20key=20=3D=20= maybe_remove_pos_from_symbol=20(key);=0A+=20=20=20=20=20=20CHECK_TYPE=20= (BARE_SYMBOL_P=20(key),=20Qsymbolp,=20key);=0A+=0A+=20=20=20=20=20=20if=20= (symset_add=20(jo,=20&ss,=20key))=0A+=09{=0A+=09=20=20if=20(!first)=0A+=09= =20=20=20=20json_out_byte=20(jo,=20',');=0A+=09=20=20first=20=3D=20= false;=0A+=0A+=09=20=20Lisp_Object=20key_str=20=3D=20SYMBOL_NAME=20= (key);=0A+=09=20=20const=20char=20*str=20=3D=20SSDATA=20(key_str);=0A+=09= =20=20/*=20Skip=20leading=20':'=20in=20plist=20keys.=20=20*/=0A+=09=20=20= int=20skip=20=3D=20!is_alist=20&&=20str[0]=20=3D=3D=20':'=20&&=20str[1]=20= ?=201=20:=200;=0A+=09=20=20json_out_string=20(jo,=20key_str,=20skip);=0A= +=09=20=20json_out_byte=20(jo,=20':');=0A+=09=20=20json_out_something=20= (jo,=20value);=0A+=09}=0A+=20=20=20=20}=0A+=20=20CHECK_LIST_END=20(tail,=20= obj);=0A+=20=20json_out_byte=20(jo,=20'}');=0A+=20=20pop_symset=20(jo,=20= &ss);=0A+=20=20json_out_unnest=20(jo);=0A=20}=0A=20=0A-static=20= Lisp_Object=0A-json_handle_nonlocal_exit=20(enum=20nonlocal_exit=20type,=20= Lisp_Object=20data)=0A+static=20void=0A+json_out_object_hash=20= (json_out_t=20*jo,=20Lisp_Object=20obj)=0A=20{=0A-=20=20switch=20(type)=0A= +=20=20json_out_nest=20(jo);=0A+=20=20json_out_byte=20(jo,=20'{');=0A+=20= =20struct=20Lisp_Hash_Table=20*h=20=3D=20XHASH_TABLE=20(obj);=0A+=20=20= bool=20first=20=3D=20true;=0A+=20=20DOHASH=20(h,=20k,=20v)=0A=20=20=20=20= =20{=0A-=20=20=20=20case=20NONLOCAL_EXIT_SIGNAL:=0A-=20=20=20=20=20=20= return=20data;=0A-=20=20=20=20case=20NONLOCAL_EXIT_THROW:=0A-=20=20=20=20= =20=20return=20Fcons=20(Qno_catch,=20data);=0A-=20=20=20=20default:=0A-=20= =20=20=20=20=20eassume=20(false);=0A+=20=20=20=20=20=20if=20(!first)=0A+=09= json_out_byte=20(jo,=20',');=0A+=20=20=20=20=20=20first=20=3D=20false;=0A= +=20=20=20=20=20=20CHECK_STRING=20(k);=0A+=20=20=20=20=20=20/*=20It's=20= the=20user's=20responsibility=20to=20ensure=20that=20hash=20keys=20are=0A= +=09=20unique;=20we=20don't=20check=20for=20it.=20=20*/=0A+=20=20=20=20=20= =20json_out_string=20(jo,=20k,=200);=0A+=20=20=20=20=20=20json_out_byte=20= (jo,=20':');=0A+=20=20=20=20=20=20json_out_something=20(jo,=20v);=0A=20=20= =20=20=20}=0A+=20=20json_out_byte=20(jo,=20'}');=0A+=20=20= json_out_unnest=20(jo);=0A+=0A=20}=0A=20=0A-struct=20json_insert_data=0A= +static=20void=0A+json_out_array=20(json_out_t=20*jo,=20Lisp_Object=20= obj)=0A=20{=0A-=20=20/*=20This=20tracks=20how=20many=20bytes=20were=20= inserted=20by=20the=20callback=20since=0A-=20=20=20=20=20= json_dump_callback=20was=20called.=20=20*/=0A-=20=20ptrdiff_t=20= inserted_bytes;=0A-=20=20/*=20nil=20if=20json_insert=20succeeded,=20= otherwise=20the=20symbol=0A-=20=20=20=20=20Qcatch_all_memory_full=20or=20= a=20cons=20(ERROR-SYMBOL=20.=20ERROR-DATA).=20=20*/=0A-=20=20Lisp_Object=20= error;=0A-};=0A+=20=20json_out_nest=20(jo);=0A+=20=20json_out_byte=20= (jo,=20'[');=0A+=20=20ptrdiff_t=20n=20=3D=20ASIZE=20(obj);=0A+=20=20for=20= (ptrdiff_t=20i=20=3D=200;=20i=20<=20n;=20i++)=0A+=20=20=20=20{=0A+=20=20=20= =20=20=20if=20(i=20>=200)=0A+=09json_out_byte=20(jo,=20',');=0A+=20=20=20= =20=20=20json_out_something=20(jo,=20AREF=20(obj,=20i));=0A+=20=20=20=20= }=0A+=20=20json_out_byte=20(jo,=20']');=0A+=20=20json_out_unnest=20(jo);=0A= +}=0A=20=0A-/*=20Callback=20for=20json_dump_callback=20that=20inserts=20= a=20JSON=20representation=0A-=20=20=20as=20a=20unibyte=20string=20into=20= the=20gap.=20=20DATA=20must=20point=20to=20a=20structure=0A-=20=20=20of=20= type=20json_insert_data.=20=20This=20function=20may=20not=20exit=20= nonlocally.=0A-=20=20=20It=20catches=20all=20nonlocal=20exits=20and=20= stores=20them=20in=20data->error=20for=0A-=20=20=20reraising.=20=20*/=0A= +static=20void=0A+json_out_float=20(json_out_t=20*jo,=20Lisp_Object=20f)=0A= +{=0A+=20=20double=20x=20=3D=20XFLOAT_DATA=20(f);=0A+=20=20if=20(isinf=20= (x)=20||=20isnan=20(x))=0A+=20=20=20=20signal_error=20("not=20a=20finite=20= number",=20f);=0A+=20=20/*=20As=20luck=20has=20it,=20float_to_string=20= emits=20correct=20JSON=20float=20syntax=20for=0A+=20=20=20=20=20all=20= numbers=20(because=20Vfloat_output_format=20is=20Qnil).=20=20*/=0A+=20=20= json_make_room=20(jo,=20FLOAT_TO_STRING_BUFSIZE);=0A+=20=20int=20n=20=3D=20= float_to_string=20(jo->buf=20+=20jo->size,=20x);=0A+=20=20jo->size=20+=3D=20= n;=0A+}=0A=20=0A-static=20int=0A-json_insert_callback=20(const=20char=20= *buffer,=20size_t=20size,=20void=20*data)=0A+static=20void=0A= +json_out_bignum=20(json_out_t=20*jo,=20Lisp_Object=20x)=0A=20{=0A-=20=20= struct=20json_insert_data=20*d=20=3D=20data;=0A-=20=20struct=20= json_buffer_and_size=20buffer_and_size=0A-=20=20=20=20=3D=20{.buffer=20=3D= =20buffer,=20.size=20=3D=20size,=20.inserted_bytes=20=3D=20= d->inserted_bytes};=0A-=20=20d->error=20=3D=20internal_catch_all=20= (json_insert,=20&buffer_and_size,=0A-=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= json_handle_nonlocal_exit);=0A-=20=20d->inserted_bytes=20=3D=20= buffer_and_size.inserted_bytes;=0A-=20=20return=20NILP=20(d->error)=20?=20= 0=20:=20-1;=0A+=20=20int=20base=20=3D=2010;=0A+=20=20ptrdiff_t=20size=20= =3D=20bignum_bufsize=20(x,=20base);=0A+=20=20json_make_room=20(jo,=20= size);=0A+=20=20int=20n=20=3D=20bignum_to_c_string=20(jo->buf=20+=20= jo->size,=20size,=20x,=20base);=0A+=20=20jo->size=20+=3D=20n;=0A+}=0A+=0A= +static=20void=0A+json_out_something=20(json_out_t=20*jo,=20Lisp_Object=20= obj)=0A+{=0A+=20=20if=20(EQ=20(obj,=20jo->conf.null_object))=0A+=20=20=20= =20JSON_OUT_STR=20(jo,=20"null");=0A+=20=20else=20if=20(EQ=20(obj,=20= jo->conf.false_object))=0A+=20=20=20=20JSON_OUT_STR=20(jo,=20"false");=0A= +=20=20else=20if=20(EQ=20(obj,=20Qt))=0A+=20=20=20=20JSON_OUT_STR=20(jo,=20= "true");=0A+=20=20else=20if=20(NILP=20(obj))=0A+=20=20=20=20JSON_OUT_STR=20= (jo,=20"{}");=0A+=20=20else=20if=20(FIXNUMP=20(obj))=0A+=20=20=20=20= json_out_fixnum=20(jo,=20XFIXNUM=20(obj));=0A+=20=20else=20if=20(STRINGP=20= (obj))=0A+=20=20=20=20json_out_string=20(jo,=20obj,=200);=0A+=20=20else=20= if=20(CONSP=20(obj))=0A+=20=20=20=20json_out_object_cons=20(jo,=20obj);=0A= +=20=20else=20if=20(FLOATP=20(obj))=0A+=20=20=20=20json_out_float=20(jo,=20= obj);=0A+=20=20else=20if=20(HASH_TABLE_P=20(obj))=0A+=20=20=20=20= json_out_object_hash=20(jo,=20obj);=0A+=20=20else=20if=20(VECTORP=20= (obj))=0A+=20=20=20=20json_out_array=20(jo,=20obj);=0A+=20=20else=20if=20= (BIGNUMP=20(obj))=0A+=20=20=20=20json_out_bignum=20(jo,=20obj);=0A+=20=20= else=0A+=20=20=20=20wrong_type_argument=20(Qjson_value_p,=20obj);=0A+}=0A= +=0A+static=20Lisp_Object=0A+json_out_to_string=20(json_out_t=20*jo)=0A= +{=0A+=20=20/*=20FIXME:=20should=20this=20be=20a=20unibyte=20or=20= multibyte=20string?=0A+=20=20=20=20=20Right=20now=20we=20make=20a=20= multibyte=20string=20for=20test=20compatibility,=0A+=20=20=20=20=20but=20= we=20are=20really=20encoding=20so=20unibyte=20would=20make=20more=20= sense.=20=20*/=0A+=20=20ptrdiff_t=20nchars=20=3D=20jo->size=20-=20= jo->chars_delta;=0A+=20=20return=20make_multibyte_string=20(jo->buf,=20= nchars,=20jo->size);=0A+}=0A+=0A+static=20void=0A+json_serialize=20= (json_out_t=20*jo,=20Lisp_Object=20object,=0A+=09=09ptrdiff_t=20nargs,=20= Lisp_Object=20*args)=0A+{=0A+=20=20*jo=20=3D=20(json_out_t)=20{=0A+=20=20= =20=20/*=20The=20maximum=20nesting=20depth=20allowed=20should=20be=20= sufficient=20for=20most=0A+=20=20=20=20=20=20=20uses=20but=20could=20be=20= raised=20if=20necessary.=20=20(The=20default=20maximum=0A+=20=20=20=20=20= =20=20depth=20for=20JSON_checker=20is=2020.)=20=20*/=0A+=20=20=20=20= .maxdepth=20=3D=2050,=0A+=20=20=20=20.conf=20=3D=20= {json_object_hashtable,=20json_array_array,=20QCnull,=20QCfalse}=0A+=20=20= };=0A+=20=20json_parse_args=20(nargs,=20args,=20&jo->conf,=20false);=0A+=20= =20record_unwind_protect_ptr=20(cleanup_json_out,=20jo);=0A+=0A+=20=20/*=20= Make=20float=20conversion=20independent=20of=20float-output-format.=20=20= */=0A+=20=20if=20(!NILP=20(Vfloat_output_format))=0A+=20=20=20=20= specbind=20(Qfloat_output_format,=20Qnil);=0A+=0A+=20=20= json_out_something=20(jo,=20object);=0A+}=0A+=0A+DEFUN=20= ("json-serialize",=20Fjson_serialize,=20Sjson_serialize,=201,=20MANY,=0A= +=20=20=20=20=20=20=20NULL,=0A+=20=20=20=20=20=20=20doc:=20/*=20Return=20= the=20JSON=20representation=20of=20OBJECT=20as=20a=20string.=0A+=0A= +OBJECT=20must=20be=20t,=20a=20number,=20string,=20vector,=20hashtable,=20= alist,=20plist,=0A+or=20the=20Lisp=20equivalents=20to=20the=20JSON=20= null=20and=20false=20values,=20and=20its=0A+elements=20must=20= recursively=20consist=20of=20the=20same=20kinds=20of=20values.=20=20t=20= will=0A+be=20converted=20to=20the=20JSON=20true=20value.=20=20Vectors=20= will=20be=20converted=20to=0A+JSON=20arrays,=20whereas=20hashtables,=20= alists=20and=20plists=20are=20converted=20to=0A+JSON=20objects.=20=20= Hashtable=20keys=20must=20be=20strings,=20unique=20within=20each=20= object.=0A+Alist=20and=20plist=20keys=20must=20be=20symbols;=20if=20a=20= key=20is=20duplicate,=20the=20first=0A+instance=20is=20used.=20=20A=20= leading=20colon=20in=20plist=20keys=20is=20elided.=0A+=0A+The=20Lisp=20= equivalents=20to=20the=20JSON=20null=20and=20false=20values=20are=0A= +configurable=20in=20the=20arguments=20ARGS,=20a=20list=20of=20= keyword/argument=20pairs:=0A+=0A+The=20keyword=20argument=20= `:null-object'=20specifies=20which=20object=20to=20use=0A+to=20represent=20= a=20JSON=20null=20value.=20=20It=20defaults=20to=20`:null'.=0A+=0A+The=20= keyword=20argument=20`:false-object'=20specifies=20which=20object=20to=20= use=20to=0A+represent=20a=20JSON=20false=20value.=20=20It=20defaults=20= to=20`:false'.=0A+=0A+In=20you=20specify=20the=20same=20value=20for=20= `:null-object'=20and=20`:false-object',=0A+a=20potentially=20ambiguous=20= situation,=20the=20JSON=20output=20will=20not=20contain=0A+any=20JSON=20= false=20values.=0A+usage:=20(json-serialize=20OBJECT=20&rest=20ARGS)=20=20= */)=0A+=20=20=20=20=20(ptrdiff_t=20nargs,=20Lisp_Object=20*args)=0A+{=0A= +=20=20specpdl_ref=20count=20=3D=20SPECPDL_INDEX=20();=0A+=20=20= json_out_t=20jo;=0A+=20=20json_serialize=20(&jo,=20args[0],=20nargs=20-=20= 1,=20args=20+=201);=0A+=20=20return=20unbind_to=20(count,=20= json_out_to_string=20(&jo));=0A=20}=0A=20=0A=20DEFUN=20("json-insert",=20= Fjson_insert,=20Sjson_insert,=201,=20MANY,=0A@@=20-614,71=20+637,52=20@@=20= DEFUN=20("json-insert",=20Fjson_insert,=20Sjson_insert,=201,=20MANY,=0A=20= =20=20=20=20=20(ptrdiff_t=20nargs,=20Lisp_Object=20*args)=0A=20{=0A=20=20= =20specpdl_ref=20count=20=3D=20SPECPDL_INDEX=20();=0A+=20=20json_out_t=20= jo;=0A+=20=20json_serialize=20(&jo,=20args[0],=20nargs=20-=201,=20args=20= +=201);=0A=20=0A-#ifdef=20WINDOWSNT=0A-=20=20ensure_json_available=20();=0A= -#endif=0A-=0A-=20=20struct=20json_configuration=20conf=20=3D=0A-=20=20=20= =20{json_object_hashtable,=20json_array_array,=20QCnull,=20QCfalse};=0A-=20= =20json_parse_args=20(nargs=20-=201,=20args=20+=201,=20&conf,=20false);=0A= -=0A-=20=20json_t=20*json=20=3D=20lisp_to_json=20(args[0],=20&conf);=0A-=20= =20record_unwind_protect_ptr=20(json_release_object,=20json);=0A+=20=20= /*=20FIXME:=20All=20the=20work=20below=20just=20to=20insert=20a=20string=20= into=20a=20buffer?=20=20*/=0A=20=0A=20=20=20prepare_to_modify_buffer=20= (PT,=20PT,=20NULL);=0A=20=20=20move_gap_both=20(PT,=20PT_BYTE);=0A-=20=20= struct=20json_insert_data=20data;=0A-=20=20data.inserted_bytes=20=3D=20= 0;=0A-=20=20/*=20Could=20have=20used=20json_dumpb,=20but=20that=20became=20= available=20only=20in=0A-=20=20=20=20=20Jansson=202.10,=20whereas=20we=20= want=20to=20support=202.7=20and=20upward.=20=20*/=0A-=20=20int=20status=20= =3D=20json_dump_callback=20(json,=20json_insert_callback,=20&data,=0A-=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20JSON_COMPACT=20|=20JSON_ENCODE_ANY);=0A-=20=20= if=20(status=20=3D=3D=20-1)=0A-=20=20=20=20{=0A-=20=20=20=20=20=20if=20= (CONSP=20(data.error))=0A-=20=20=20=20=20=20=20=20xsignal=20(XCAR=20= (data.error),=20XCDR=20(data.error));=0A-=20=20=20=20=20=20else=0A-=20=20= =20=20=20=20=20=20json_out_of_memory=20();=0A-=20=20=20=20}=0A+=20=20if=20= (GAP_SIZE=20<=20jo.size)=0A+=20=20=20=20make_gap=20(jo.size=20-=20= GAP_SIZE);=0A+=20=20memcpy=20((char=20*)=20BEG_ADDR=20+=20PT_BYTE=20-=20= BEG_BYTE,=20jo.buf,=20jo.size);=0A+=0A+=20=20/*=20No=20need=20to=20keep=20= allocation=20beyond=20this=20point.=20=20*/=0A+=20=20unbind_to=20(count,=20= Qnil);=0A=20=0A=20=20=20ptrdiff_t=20inserted=20=3D=200;=0A-=20=20= ptrdiff_t=20inserted_bytes=20=3D=20data.inserted_bytes;=0A-=20=20if=20= (inserted_bytes=20>=200)=0A+=20=20ptrdiff_t=20inserted_bytes=20=3D=20= jo.size;=0A+=0A+=20=20/*=20If=20required,=20decode=20the=20stuff=20we've=20= read=20into=20the=20gap.=20=20*/=0A+=20=20struct=20coding_system=20= coding;=0A+=20=20/*=20JSON=20strings=20are=20UTF-8=20encoded=20strings.=20= =20*/=0A+=20=20setup_coding_system=20(Qutf_8_unix,=20&coding);=0A+=20=20= coding.dst_multibyte=20=3D=20!NILP=20(BVAR=20(current_buffer,=0A+=09=09=09= =09=20=20=20=20=20=20enable_multibyte_characters));=0A+=20=20if=20= (CODING_MAY_REQUIRE_DECODING=20(&coding))=0A=20=20=20=20=20{=0A-=20=20=20= =20=20=20/*=20If=20required,=20decode=20the=20stuff=20we've=20read=20= into=20the=20gap.=20=20*/=0A-=20=20=20=20=20=20struct=20coding_system=20= coding;=0A-=20=20=20=20=20=20/*=20JSON=20strings=20are=20UTF-8=20encoded=20= strings.=20=20If=20for=20some=20reason=0A-=09=20the=20text=20returned=20= by=20the=20Jansson=20library=20includes=20invalid=0A-=09=20byte=20= sequences,=20they=20will=20be=20represented=20by=20raw=20bytes=20in=20= the=0A-=09=20buffer=20text.=20=20*/=0A-=20=20=20=20=20=20= setup_coding_system=20(Qutf_8_unix,=20&coding);=0A-=20=20=20=20=20=20= coding.dst_multibyte=20=3D=0A-=09!NILP=20(BVAR=20(current_buffer,=20= enable_multibyte_characters));=0A-=20=20=20=20=20=20if=20= (CODING_MAY_REQUIRE_DECODING=20(&coding))=0A-=09{=0A-=20=20=20=20=20=20=20= =20=20=20/*=20Now=20we=20have=20all=20the=20new=20bytes=20at=20the=20= beginning=20of=20the=20gap,=0A-=20=20=20=20=20=20=20=20=20=20=20=20=20= but=20`decode_coding_gap`=20needs=20them=20at=20the=20end=20of=20the=20= gap,=20so=0A-=20=20=20=20=20=20=20=20=20=20=20=20=20we=20need=20to=20= move=20them.=20=20*/=0A-=20=20=20=20=20=20=20=20=20=20memmove=20= (GAP_END_ADDR=20-=20inserted_bytes,=20GPT_ADDR,=20inserted_bytes);=0A-=09= =20=20decode_coding_gap=20(&coding,=20inserted_bytes);=0A-=09=20=20= inserted=20=3D=20coding.produced_char;=0A-=09}=0A-=20=20=20=20=20=20else=0A= -=09{=0A-=20=20=20=20=20=20=20=20=20=20/*=20Make=20the=20inserted=20text=20= part=20of=20the=20buffer,=20as=20unibyte=20text.=20=20*/=0A-=20=20=20=20=20= =20=20=20=20=20eassert=20(NILP=20(BVAR=20(current_buffer,=20= enable_multibyte_characters)));=0A-=20=20=20=20=20=20=20=20=20=20= insert_from_gap_1=20(inserted_bytes,=20inserted_bytes,=20false);=0A-=0A-=09= =20=20/*=20The=20target=20buffer=20is=20unibyte,=20so=20we=20don't=20= need=20to=20decode.=20=20*/=0A-=09=20=20invalidate_buffer_caches=20= (current_buffer,=0A-=09=09=09=09=20=20=20=20PT,=20PT=20+=20= inserted_bytes);=0A-=09=20=20adjust_after_insert=20(PT,=20PT_BYTE,=0A-=09= =09=09=20=20=20=20=20=20=20PT=20+=20inserted_bytes,=0A-=09=09=09=20=20=20= =20=20=20=20PT_BYTE=20+=20inserted_bytes,=0A-=09=09=09=20=20=20=20=20=20=20= inserted_bytes);=0A-=09=20=20inserted=20=3D=20inserted_bytes;=0A-=09}=0A= +=20=20=20=20=20=20/*=20Now=20we=20have=20all=20the=20new=20bytes=20at=20= the=20beginning=20of=20the=20gap,=0A+=09=20but=20`decode_coding_gap`=20= needs=20them=20at=20the=20end=20of=20the=20gap,=20so=0A+=09=20we=20need=20= to=20move=20them.=20=20*/=0A+=20=20=20=20=20=20memmove=20(GAP_END_ADDR=20= -=20inserted_bytes,=20GPT_ADDR,=20inserted_bytes);=0A+=20=20=20=20=20=20= decode_coding_gap=20(&coding,=20inserted_bytes);=0A+=20=20=20=20=20=20= inserted=20=3D=20coding.produced_char;=0A+=20=20=20=20}=0A+=20=20else=0A= +=20=20=20=20{=0A+=20=20=20=20=20=20/*=20Make=20the=20inserted=20text=20= part=20of=20the=20buffer,=20as=20unibyte=20text.=20=20*/=0A+=20=20=20=20=20= =20eassert=20(NILP=20(BVAR=20(current_buffer,=20= enable_multibyte_characters)));=0A+=20=20=20=20=20=20insert_from_gap_1=20= (inserted_bytes,=20inserted_bytes,=20false);=0A+=0A+=20=20=20=20=20=20/*=20= The=20target=20buffer=20is=20unibyte,=20so=20we=20don't=20need=20to=20= decode.=20=20*/=0A+=20=20=20=20=20=20invalidate_buffer_caches=20= (current_buffer,=0A+=09=09=09=09PT,=20PT=20+=20inserted_bytes);=0A+=20=20= =20=20=20=20adjust_after_insert=20(PT,=20PT_BYTE,=0A+=09=09=09=20=20=20= PT=20+=20inserted_bytes,=0A+=09=09=09=20=20=20PT_BYTE=20+=20= inserted_bytes,=0A+=09=09=09=20=20=20inserted_bytes);=0A+=20=20=20=20=20=20= inserted=20=3D=20inserted_bytes;=0A=20=20=20=20=20}=0A=20=0A=20=20=20/*=20= Call=20after-change=20hooks.=20=20*/=0A@@=20-690,7=20+694,26=20@@=20= DEFUN=20("json-insert",=20Fjson_insert,=20Sjson_insert,=201,=20MANY,=0A=20= =20=20=20=20=20=20SET_PT_BOTH=20(PT=20+=20inserted,=20PT_BYTE=20+=20= inserted_bytes);=0A=20=20=20=20=20}=0A=20=0A-=20=20return=20unbind_to=20= (count,=20Qnil);=0A+=20=20return=20Qnil;=0A+}=0A+=0A+=0A+/*=20Note=20= that=20all=20callers=20of=20make_string_from_utf8=20and=20= build_string_from_utf8=0A+=20=20=20below=20either=20pass=20only=20value=20= UTF-8=20strings=20or=20use=20the=20function=20for=0A+=20=20=20formatting=20= error=20messages;=20in=20the=20latter=20case=20correctness=20isn't=0A+=20= =20=20critical.=20=20*/=0A+=0A+/*=20Return=20a=20unibyte=20string=20= containing=20the=20sequence=20of=20UTF-8=20encoding=0A+=20=20=20units=20= of=20the=20UTF-8=20representation=20of=20STRING.=20=20If=20STRING=20does=20= not=0A+=20=20=20represent=20a=20sequence=20of=20Unicode=20scalar=20= values,=20return=20a=20string=20with=0A+=20=20=20unspecified=20contents.=20= =20*/=0A+=0A+static=20Lisp_Object=0A+json_encode=20(Lisp_Object=20= string)=0A+{=0A+=20=20/*=20FIXME:=20Raise=20an=20error=20if=20STRING=20= is=20not=20a=20scalar=20value=0A+=20=20=20=20=20sequence.=20=20*/=0A+=20=20= return=20encode_string_utf_8=20(string,=20Qnil,=20false,=20Qt,=20Qt);=0A=20= }=0A=20=0A=20#define=20JSON_PARSER_INTERNAL_OBJECT_WORKSPACE_SIZE=2064=0A= @@=20-1894,7=20+1917,6=20@@=20syms_of_json=20(void)=0A=20=20=20DEFSYM=20= (QCnull,=20":null");=0A=20=20=20DEFSYM=20(QCfalse,=20":false");=0A=20=0A= -=20=20DEFSYM=20(Qstring_without_embedded_nulls_p,=20= "string-without-embedded-nulls-p");=0A=20=20=20DEFSYM=20(Qjson_value_p,=20= "json-value-p");=0A=20=0A=20=20=20DEFSYM=20(Qjson_error,=20= "json-error");=0A@@=20-1907,7=20+1929,6=20@@=20syms_of_json=20(void)=0A=20= =20=20DEFSYM=20(Qjson_invalid_surrogate_error,=20= "json-invalid-surrogate-error")=0A=20=20=20DEFSYM=20= (Qjson_number_out_of_range,=20"json-number-out-of-range-error")=0A=20=20=20= DEFSYM=20(Qjson_escape_sequence_error,=20"json-escape-sequence-error")=0A= -=20=20DEFSYM=20(Qjson_unavailable,=20"json-unavailable");=0A=20=20=20= define_error=20(Qjson_error,=20"generic=20JSON=20error",=20Qerror);=0A=20= =20=20define_error=20(Qjson_out_of_memory,=0A=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20"not=20enough=20memory=20for=20creating=20JSON=20= object",=20Qjson_error);=0Adiff=20--git=20a/src/lisp.h=20b/src/lisp.h=0A= index=20f066c876619..7c4bd435cd8=20100644=0A---=20a/src/lisp.h=0A+++=20= b/src/lisp.h=0A@@=20-4327,7=20+4327,6=20@@=20verify=20(FLT_RADIX=20=3D=3D=20= 2=20||=20FLT_RADIX=20=3D=3D=2016);=0A=20=0A=20#ifdef=20HAVE_JSON=0A=20/*=20= Defined=20in=20json.c.=20=20*/=0A-extern=20void=20init_json=20(void);=0A=20= extern=20void=20syms_of_json=20(void);=0A=20#endif=0A=20=0Adiff=20--git=20= a/src/print.c=20b/src/print.c=0Aindex=2076c577ec800..0d867b89395=20= 100644=0A---=20a/src/print.c=0A+++=20b/src/print.c=0A@@=20-2859,6=20= +2859,7=20@@=20syms_of_print=20(void)=0A=20A=20value=20of=20nil=20means=20= to=20use=20the=20shortest=20notation=0A=20that=20represents=20the=20= number=20without=20losing=20information.=20=20*/);=0A=20=20=20= Vfloat_output_format=20=3D=20Qnil;=0A+=20=20DEFSYM=20= (Qfloat_output_format,=20"float-output-format");=0A=20=0A=20=20=20= DEFVAR_BOOL=20("print-integers-as-characters",=20= print_integers_as_characters,=0A=20=09=20=20=20=20=20=20=20doc:=20/*=20= Non-nil=20means=20integers=20are=20printed=20using=20characters=20= syntax.=0Adiff=20--git=20a/test/src/json-tests.el=20= b/test/src/json-tests.el=0Aindex=20dffc6291ca1..e5cbe8bff5c=20100644=0A= ---=20a/test/src/json-tests.el=0A+++=20b/test/src/json-tests.el=0A@@=20= -126,11=20+126,38=20@@=20json-serialize/object=0A=20=0A=20(ert-deftest=20= json-serialize/object-with-duplicate-keys=20()=0A=20=20=20(skip-unless=20= (fboundp=20'json-serialize))=0A-=20=20(let=20((table=20(make-hash-table=20= :test=20#'eq)))=0A-=20=20=20=20(puthash=20(copy-sequence=20"abc")=20[1=20= 2=20t]=20table)=0A-=20=20=20=20(puthash=20(copy-sequence=20"abc")=20= :null=20table)=0A-=20=20=20=20(should=20(equal=20(hash-table-count=20= table)=202))=0A-=20=20=20=20(should-error=20(json-serialize=20table)=20= :type=20'wrong-type-argument)))=0A+=0A+=20=20(dolist=20(n=20'(1=205=2020=20= 100))=0A+=20=20=20=20(let=20((symbols=20(mapcar=20(lambda=20(i)=20= (make-symbol=20(format=20"s%d"=20i)))=0A+=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(number-sequence=201=20= n)))=0A+=20=20=20=20=20=20=20=20=20=20(expected=20(concat=20"{"=0A+=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20(mapconcat=20(lambda=20(i)=20(format=20"\"s%d\":%d"=20i=20i))=0A+=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20(number-sequence=201=20n)=20",")=0A+=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20"}")))=0A+=20=20=20=20=20=20;;=20alist=0A+=20=20=20=20=20=20= (should=20(equal=20(json-serialize=0A+=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20(append=0A+=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20(cl-mapcar=20#'cons=0A+=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20symbols=20(number-sequence=201=20n))=0A+=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(cl-mapcar=20#'cons=0A+=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20symbols=20(number-sequence=201001=20(+=201000=20= n)))))=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= expected))=0A+=20=20=20=20=20=20;;=20plist=0A+=20=20=20=20=20=20(should=20= (equal=20(json-serialize=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20(append=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20(cl-mapcan=20#'list=0A+=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20symbols=20(number-sequence=201=20n))=0A+=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20(cl-mapcan=20#'list=0A+=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20symbols=20(number-sequence=201001=20(+=201000=20n)))))=0A= +=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= expected))))=0A+=0A+=20=20;;=20We=20don't=20check=20for=20duplicated=20= keys=20in=20hash=20tables.=0A+=20=20;;=20(let=20((table=20= (make-hash-table=20:test=20#'eq)))=0A+=20=20;;=20=20=20(puthash=20= (copy-sequence=20"abc")=20[1=202=20t]=20table)=0A+=20=20;;=20=20=20= (puthash=20(copy-sequence=20"abc")=20:null=20table)=0A+=20=20;;=20=20=20= (should=20(equal=20(hash-table-count=20table)=202))=0A+=20=20;;=20=20=20= (should-error=20(json-serialize=20table)=20:type=20= 'wrong-type-argument))=0A+=20=20)=0A=20=0A=20(ert-deftest=20= json-parse-string/object=20()=0A=20=20=20(skip-unless=20(fboundp=20= 'json-parse-string))=0A@@=20-173,8=20+200,8=20@@=20json-serialize/string=0A= =20=20=20(should=20(equal=20(json-serialize=20= ["\nasd=D1=84=D1=8B=D0=B2\u001f\u007ffgh\t"])=0A=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20"[\"\\nasd=D1=84=D1=8B=D0=B2\\u001F\u007ffgh\\t= \"]"))=0A=20=20=20(should=20(equal=20(json-serialize=20["a\0b"])=20= "[\"a\\u0000b\"]"))=0A-=20=20;;=20FIXME:=20Is=20this=20the=20right=20= behavior?=0A-=20=20(should=20(equal=20(json-serialize=20= ["\u00C4\xC3\x84"])=20"[\"\u00C4\u00C4\"]")))=0A+=20=20(should-error=20= (json-serialize=20["\xC3\x84"]))=0A+=20=20(should-error=20= (json-serialize=20["\u00C4\xC3\x84"])))=0A=20=0A=20(ert-deftest=20= json-serialize/invalid-unicode=20()=0A=20=20=20(skip-unless=20(fboundp=20= 'json-serialize))=0A--=20=0A2.32.0=20(Apple=20Git-132)=0A=0A= --Apple-Mail=_558A8A9C-18B2-4CE8-A0C1-865EBAE3B503-- From unknown Sun Jun 15 14:44:57 2025 X-Loop: help-debbugs@gnu.org Subject: bug#70007: [PATCH] native JSON encoder Resent-From: Eli Zaretskii Original-Sender: "Debbugs-submit" Resent-CC: bug-gnu-emacs@gnu.org Resent-Date: Sat, 30 Mar 2024 13:24:02 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 70007 X-GNU-PR-Package: emacs X-GNU-PR-Keywords: patch To: Mattias =?UTF-8?Q?Engdeg=C3=A5rd?= Cc: casouri@gmail.com, 70007@debbugs.gnu.org Received: via spool by 70007-submit@debbugs.gnu.org id=B70007.171180499230119 (code B ref 70007); Sat, 30 Mar 2024 13:24:02 +0000 Received: (at 70007) by debbugs.gnu.org; 30 Mar 2024 13:23:12 +0000 Received: from localhost ([127.0.0.1]:44203 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1rqYfv-0007pi-MA for submit@debbugs.gnu.org; Sat, 30 Mar 2024 09:23:12 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:38214) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1rqYfs-0007pF-QE for 70007@debbugs.gnu.org; Sat, 30 Mar 2024 09:23:10 -0400 Received: from fencepost.gnu.org ([2001:470:142:3::e]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1rqYfl-0000Lr-7g; Sat, 30 Mar 2024 09:23:01 -0400 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=gnu.org; s=fencepost-gnu-org; h=MIME-version:References:Subject:In-Reply-To:To:From: Date; bh=JJuw+ORI8zlhnvoIR7WneDY5qSTINoXJ1znBHt+RqZ0=; b=nQ51RTkW+ustSJ+YXq/P CBtrqjkBronKAd7CcrDNWmuUPSZILLAWwLv6MvucASQmVvg/Tl67bvHMWGFAEfzh/Ywd/EAC0+VoD oDGjW8DdxTxvfXVP2GsQYXwacKM+mQ4R3ihAh3rCXiy2XRlt9fMz68wcdjeB+WbdQCehwV4JrTEKk 6i1QiMTSx+IiNePtCd0iAYbN8ql+18X/Q7HgRc6wYR8SpimMI1gXfkfMl/cc1sHp/X/r6ZcSBGAVK exQ7Tt0yQZ3hLQ3VQJ1y5Gg4DIchWpyK5973Ya0nSQQyEu/3Iw/htnWLIX82WxB1ur7doxjtHBtZI 9am/nJibPI1ySg==; Date: Sat, 30 Mar 2024 16:22:57 +0300 Message-Id: <86le5zdfbi.fsf@gnu.org> From: Eli Zaretskii In-Reply-To: <3139C8FE-5C67-4FE3-B940-F449DA73E76C@gmail.com> (message from Mattias =?UTF-8?Q?Engdeg=C3=A5rd?= on Sat, 30 Mar 2024 12:41:31 +0100) References: <1BF559D1-DB9F-4FEB-90ED-72E0EFD76424@gmail.com> <86wmpphrg7.fsf@gnu.org> <4589243D-C11A-45C1-AF3E-6F4A5BADEB54@gmail.com> <864jcrindg.fsf@gnu.org> <291DD5F1-85B8-4647-A40A-EBBD4C51E253@gmail.com> <8634sbijfx.fsf@gnu.org> <2CF47DA5-A65B-47C4-A28A-6FEE1469BD13@gmail.com> <86cyrdfuai.fsf@gnu.org> <3139C8FE-5C67-4FE3-B940-F449DA73E76C@gmail.com> MIME-version: 1.0 Content-type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Spam-Score: -2.3 (--) X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -3.3 (---) > From: Mattias EngdegÃ¥rd > Date: Sat, 30 Mar 2024 12:41:31 +0100 > Cc: casouri@gmail.com, > 70007@debbugs.gnu.org > > 29 mars 2024 kl. 07.04 skrev Eli Zaretskii : > > > OK. FTR, I'm not in favor of validation of unibyte strings, I just > > suggest that we treat them as plain-ASCII: pass them through without > > any validation, leaving the validation to the callers. > > Actually we are more or less forced to validate unibyte strings as long as the serialiser returns multibyte. Which we agree that it probably shouldn't, but I'd first like to take some time to ensure that returning unibyte won't break anything. Yes, I was writing about the state of affairs when we change the serializer to emit unibyte strings. > Thank you for pushing the new JSON parser to master. I've rebased my patch and cleaned it up a bit, and it now removes all uses of Jansson from json.c. Since the change involves removing some Windows-specific code, perhaps you would like to check that it still compiles on that platform, if you have the time? It builds and passes the tests, thanks. But I have a couple of minor nits below. > +static struct symset_tbl * > +make_symset_table (int bits, struct symset_tbl *up) > +{ > + int maxbits = min (SIZE_WIDTH - 2 - (word_size < 8 ? 2 : 3), 32); > + if (bits > maxbits) > + error ("out of memory"); /* Will never happen in practice. */ This should be a call to memory_full, no? Or if we must signal this error here, at least make the error message more specific: mention JSON or somesuch. > +{ > + double x = XFLOAT_DATA (f); > + if (isinf (x) || isnan (x)) > + signal_error ("not a finite number", f); I'd prefer a more specific error message here, like JSON does not allow Inf or NaN Last, but not least: should we have a json-available-p function that always returns non-nil, for better backward-compatibility? Otherwise, code out there might decide to use json.elm which is not what we want. From unknown Sun Jun 15 14:44:57 2025 X-Loop: help-debbugs@gnu.org Subject: bug#70007: [PATCH] native JSON encoder Resent-From: Mattias =?UTF-8?Q?Engdeg=C3=A5rd?= Original-Sender: "Debbugs-submit" Resent-CC: bug-gnu-emacs@gnu.org Resent-Date: Sat, 30 Mar 2024 14:23:01 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 70007 X-GNU-PR-Package: emacs X-GNU-PR-Keywords: patch To: Eli Zaretskii Cc: casouri@gmail.com, 70007@debbugs.gnu.org Received: via spool by 70007-submit@debbugs.gnu.org id=B70007.171180856911970 (code B ref 70007); Sat, 30 Mar 2024 14:23:01 +0000 Received: (at 70007) by debbugs.gnu.org; 30 Mar 2024 14:22:49 +0000 Received: from localhost ([127.0.0.1]:45936 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1rqZbc-00036p-7e for submit@debbugs.gnu.org; Sat, 30 Mar 2024 10:22:49 -0400 Received: from mail-lf1-x12b.google.com ([2a00:1450:4864:20::12b]:47416) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1rqZbZ-00036D-4a for 70007@debbugs.gnu.org; Sat, 30 Mar 2024 10:22:46 -0400 Received: by mail-lf1-x12b.google.com with SMTP id 2adb3069b0e04-513da1c1f26so3240599e87.3 for <70007@debbugs.gnu.org>; Sat, 30 Mar 2024 07:22:43 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1711808556; x=1712413356; darn=debbugs.gnu.org; h=to:references:message-id:content-transfer-encoding:cc:date :in-reply-to:from:subject:mime-version:sender:from:to:cc:subject :date:message-id:reply-to; bh=Sg55lROk4ZoqZgqWtEkgdYtr3pbcsZw2+SEUmuuK93k=; b=Utrv2NI0PO5iWMWnPJaMxyTu57sjbxYSBUacW1Wc/PEX7Lxw4BUg/oCmJN7YjMCvHp 658kR401xM+UdA1DcO+/DcbSZnJZrWj2mqZWGXiFtv8Ooo0tGTFvdV+Uj0OKsQkpTs0r fFmvPT1Bey4i94dL+oDZV6450leMCRAdpRKmhYJMHNSVIGv7cFzn+y8dhTnGFN6IZcw+ HBXnOykWM20QHibNx4BxAL1CeUPq3g6t6hkjnRAV5OFzQUJK6g73iqB5Q8aqAAkZ6Yyc R67hPhzASimKsqvui8KNXkU0pmu5R9K3f3dRLDzfbXo8ImtrKf15sJVeSJMv7lw5D8cW FDJw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1711808556; x=1712413356; h=to:references:message-id:content-transfer-encoding:cc:date :in-reply-to:from:subject:mime-version:sender:x-gm-message-state :from:to:cc:subject:date:message-id:reply-to; bh=Sg55lROk4ZoqZgqWtEkgdYtr3pbcsZw2+SEUmuuK93k=; b=GOTxYUC6Kepyke0my9EddZSq2d5BJUrkBh/vRcRm/uCAqIqOSFQumu5AC2XQyfJdQn 46tctaZcOYPl18jrMlsKqibZpbA+Yvi4DbnguiZei+v9iEE4GKV1Am7gwIyFeptWXMTY QfYZ/vl6m7c/4Es1RzvQlpVUyNYAC4/FjHUo1lWrKOU1Nc2gKaATD8NWIpdlBDJPY594 I0eJY2t1J7yMlc4fuJgzRFRsg4Tw4Jsz3M8ENLxMQbLp+hii2GfL+uPWm/FsLs7cxrVz NNjuLgGW15zb+CptUI0ZwsFNbTdnd3TfAxHBTW4T9zZRS7DX/AQ3GuwlNQZDrUWMd3PA CtXw== X-Forwarded-Encrypted: i=1; AJvYcCWw0mtyZVLhYGn2Y+ujQdh/THAmkMjlAUdvupxSuEqLjSAC+qNc4UoGGur5G/ZKwLzACIkks8ObQw0B8FI0HzIi9OJJpzs= X-Gm-Message-State: AOJu0YwIwoDKPI7qKX366kxO1FsTokmWO7lubUTtaXXconPOBvcR7c3v Dh1Kt4UjwXJje462W2wnKDZtUVaPb6XbhQj3V4tMIP+s3Eg9fWJ6 X-Google-Smtp-Source: AGHT+IGqaq61OrP6i6sc/u0798tFmfaLPiw6VLFI0QCXHTLacCGlB2Z1CpXVWqaEvC4PXM83C2Yy+Q== X-Received: by 2002:a05:6512:31c7:b0:513:cc91:9ed7 with SMTP id j7-20020a05651231c700b00513cc919ed7mr140370lfe.11.1711808555934; Sat, 30 Mar 2024 07:22:35 -0700 (PDT) Received: from smtpclient.apple (c80-217-1-132.bredband.tele2.se. [80.217.1.132]) by smtp.gmail.com with ESMTPSA id 16-20020ac25f50000000b0051596fe5619sm920293lfz.40.2024.03.30.07.22.34 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Sat, 30 Mar 2024 07:22:35 -0700 (PDT) Content-Type: text/plain; charset=us-ascii Mime-Version: 1.0 (Mac OS X Mail 14.0 \(3654.120.0.1.15\)) From: Mattias =?UTF-8?Q?Engdeg=C3=A5rd?= In-Reply-To: <86le5zdfbi.fsf@gnu.org> Date: Sat, 30 Mar 2024 15:22:34 +0100 Content-Transfer-Encoding: quoted-printable Message-Id: References: <1BF559D1-DB9F-4FEB-90ED-72E0EFD76424@gmail.com> <86wmpphrg7.fsf@gnu.org> <4589243D-C11A-45C1-AF3E-6F4A5BADEB54@gmail.com> <864jcrindg.fsf@gnu.org> <291DD5F1-85B8-4647-A40A-EBBD4C51E253@gmail.com> <8634sbijfx.fsf@gnu.org> <2CF47DA5-A65B-47C4-A28A-6FEE1469BD13@gmail.com> <86cyrdfuai.fsf@gnu.org> <3139C8FE-5C67-4FE3-B940-F449DA73E76C@gmail.com> <86le5zdfbi.fsf@gnu.org> X-Mailer: Apple Mail (2.3654.120.0.1.15) X-Spam-Score: 0.0 (/) X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -1.0 (-) 30 mars 2024 kl. 14.22 skrev Eli Zaretskii : > This should be a call to memory_full, no? Or if we must signal this > error here, at least make the error message more specific: mention > JSON or somesuch. It's academic, but memory_full is fine. > I'd prefer a more specific error message here, like >=20 > JSON does not allow Inf or NaN Sure. > Last, but not least: should we have a json-available-p function that > always returns non-nil, for better backward-compatibility? Otherwise, > code out there might decide to use json.elm which is not what we want. Yes, keep json-available-p (that always returns t) for compatibility. We = could declare it obsolete but it's not very important. I made the changes above and installed it on master, as well as a = sweeping removal of all things Jansson. From unknown Sun Jun 15 14:44:57 2025 X-Loop: help-debbugs@gnu.org Subject: bug#70007: [PATCH] native JSON encoder Resent-From: Richard Copley Original-Sender: "Debbugs-submit" Resent-CC: bug-gnu-emacs@gnu.org Resent-Date: Sat, 30 Mar 2024 16:15:01 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 70007 X-GNU-PR-Package: emacs X-GNU-PR-Keywords: patch To: Mattias =?UTF-8?Q?Engdeg=C3=A5rd?= Cc: 70007@debbugs.gnu.org Received: via spool by 70007-submit@debbugs.gnu.org id=B70007.171181530032686 (code B ref 70007); Sat, 30 Mar 2024 16:15:01 +0000 Received: (at 70007) by debbugs.gnu.org; 30 Mar 2024 16:15:00 +0000 Received: from localhost ([127.0.0.1]:46070 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1rqbMB-0008V7-KH for submit@debbugs.gnu.org; Sat, 30 Mar 2024 12:14:59 -0400 Received: from mail-wr1-x435.google.com ([2a00:1450:4864:20::435]:58875) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1rqbM8-0008Ui-C9 for 70007@debbugs.gnu.org; Sat, 30 Mar 2024 12:14:58 -0400 Received: by mail-wr1-x435.google.com with SMTP id ffacd0b85a97d-3417a3151c5so1864394f8f.1 for <70007@debbugs.gnu.org>; Sat, 30 Mar 2024 09:14:54 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1711815288; x=1712420088; darn=debbugs.gnu.org; h=content-transfer-encoding:in-reply-to:from:references:cc:to:subject :user-agent:mime-version:date:message-id:from:to:cc:subject:date :message-id:reply-to; bh=oAO4CkWlfPWVrjyMazn+b8+xuijnxvS09ivHs7Jpj7Q=; b=c6uiYKU8/NSdP5NWqHv3auK6VCJEqHRITcUe5CetGc46js/mue8t4jKgNYna7I01/s OnjfeAu5iGW0hefPWHh2wmISTUEv4EB9NBLRTDNPszMY88EB4iAmReuzJswIRvFD6o7Q aPySKWUA84GpWSYW22Pvsx7pwKRQwX32ayQ2AE1bwyODj2FY0OcX4EkubA3ZOsWQdSdh ceEUJcRi+55fim25OvUANN5H8smNwYmv53mVw0ji36U8a/jfu4fX21csgx49ZWHIHIhY tmMIwzwo4TtPjMp1TLRvdUmr4xN7IsSwspWeI7reEjM+787RS+lT36PFrwvOi0BB5Ueu efUQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1711815288; x=1712420088; h=content-transfer-encoding:in-reply-to:from:references:cc:to:subject :user-agent:mime-version:date:message-id:x-gm-message-state:from:to :cc:subject:date:message-id:reply-to; bh=oAO4CkWlfPWVrjyMazn+b8+xuijnxvS09ivHs7Jpj7Q=; b=IwCtMbu2SVgOK8j1LS4mwRDK5gagDLK+SmaIHjGde3sjm5Tl45GcpnKKAwHBofCYlF Zd6koh9NePgW91B6OYK07J6WGGnaQXvbOX+dof1gI/dsEHYMY3Rf5pJbsyPoZYUWuJGm s8TvBf1bQ3VjlxzwKgZNsPv1JimVFGwurrYRcuck7qAgKxQkdsYZAw04w1C/MC7hv+Ej XX77ivTdgO1QK3O5ttfgLeOuFUARtTj4cWZe5UfVnaBCHu27fnlTpRDtzFx84Sps63Cw RZ/bgw3x+321pJTZrou0v3ZmH1rXH0mlr4i3KGWQMwm4r1/velPOoBEmNpnjkuOAbBLF Rekg== X-Gm-Message-State: AOJu0YyRTrCN3GFf8d+8Y5IVYIfpFfZ9buOvwZ+ImnVj1beV/IifcqG8 3KKNRIJm80dXykpYKkn/7SWvflvsXamngGbdAn3mDRul6V13B38G X-Google-Smtp-Source: AGHT+IH0Al3mlijbL5wy74vCHgPpcP5D0HRM0DaOoYWV355DS2O2w6Qgz6mq0syYv1FjFBoeojj0Zg== X-Received: by 2002:adf:fe46:0:b0:33e:69a5:68f9 with SMTP id m6-20020adffe46000000b0033e69a568f9mr3749782wrs.17.1711815288258; Sat, 30 Mar 2024 09:14:48 -0700 (PDT) Received: from [192.168.1.101] (dsl-multi-static-81-140-129-201.in-addr.broadbandscope.com. [81.140.129.201]) by smtp.gmail.com with ESMTPSA id a9-20020a056000050900b00341d7596ec0sm6734320wrf.15.2024.03.30.09.14.47 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Sat, 30 Mar 2024 09:14:47 -0700 (PDT) Message-ID: Date: Sat, 30 Mar 2024 16:14:45 +0000 MIME-Version: 1.0 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:102.0) Gecko/20100101 Thunderbird/102.15.1 References: <1BF559D1-DB9F-4FEB-90ED-72E0EFD76424@gmail.com> <86wmpphrg7.fsf@gnu.org> <4589243D-C11A-45C1-AF3E-6F4A5BADEB54@gmail.com> <864jcrindg.fsf@gnu.org> <291DD5F1-85B8-4647-A40A-EBBD4C51E253@gmail.com> <8634sbijfx.fsf@gnu.org> <2CF47DA5-A65B-47C4-A28A-6FEE1469BD13@gmail.com> <86cyrdfuai.fsf@gnu.org> <3139C8FE-5C67-4FE3-B940-F449DA73E76C@gmail.com> <86le5zdfbi.fsf@gnu.org> From: Richard Copley In-Reply-To: Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 8bit X-Spam-Score: -3.0 (---) X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -4.0 (----) On 30/03/2024 14:22, Mattias EngdegÃ¥rd wrote: > I made the changes above and installed it on master, as well as a sweeping removal of all things Jansson. Hi Mattias, A clean build fails with a linker error: CCLD temacs /usr/bin/ld: /tmp/cc4stUid.ltrans15.ltrans.o: in function `main': :(.text.startup+0x39a9): undefined reference to `syms_of_json' collect2: error: ld returned 1 exit status make[2]: *** [Makefile:739: temacs] Error 1 From unknown Sun Jun 15 14:44:57 2025 X-Loop: help-debbugs@gnu.org Subject: bug#70007: [PATCH] native JSON encoder Resent-From: Eli Zaretskii Original-Sender: "Debbugs-submit" Resent-CC: bug-gnu-emacs@gnu.org Resent-Date: Sat, 30 Mar 2024 16:38:01 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 70007 X-GNU-PR-Package: emacs X-GNU-PR-Keywords: patch To: Mattias =?UTF-8?Q?Engdeg=C3=A5rd?= Cc: casouri@gmail.com, 70007@debbugs.gnu.org Received: via spool by 70007-submit@debbugs.gnu.org id=B70007.17118166434315 (code B ref 70007); Sat, 30 Mar 2024 16:38:01 +0000 Received: (at 70007) by debbugs.gnu.org; 30 Mar 2024 16:37:23 +0000 Received: from localhost ([127.0.0.1]:46080 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1rqbhq-00017W-Tq for submit@debbugs.gnu.org; Sat, 30 Mar 2024 12:37:23 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:59962) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1rqbhp-00017K-II for 70007@debbugs.gnu.org; Sat, 30 Mar 2024 12:37:22 -0400 Received: from fencepost.gnu.org ([2001:470:142:3::e]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1rqbhg-0007w5-0t; Sat, 30 Mar 2024 12:37:13 -0400 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=gnu.org; s=fencepost-gnu-org; h=MIME-version:References:Subject:In-Reply-To:To:From: Date; bh=NlBWV6b+a6Qet4RFvQX459nX8mvidWaSQkp+eKFa5GE=; b=iwfm9a7eOGIyWPYIP9dC j+khJUURgk7I4y9n0hyhIzjlrIWs8tnwfRCHf/EqvGq5GtOCgOzqVVboOnl/hqkDAPd+jaou/Os1K 3rl4bYTOBGsohAlg/x7uRss6G/9NHsBnEbnwbxm3qawXzTu9PnQCd0jBgHOo0vd1eOsDBW47G/4AB 6F4QkIqzvkKPfFYIlyYm5FPwkonAIRVEdYeEIGeWuI44I2IJHNmrALRz+xXcFhp2gjQHUkUsN9EoH xHOhp1A51AR8Czfm5zsrUoDZNirrbc2nOr5MfzLM6qOM8rr9nHECWGVhXSEF5Sc3GiuFABIbBuXww 2nowblRARLf2rg==; Date: Sat, 30 Mar 2024 19:37:08 +0300 Message-Id: <86edbrd6bv.fsf@gnu.org> From: Eli Zaretskii In-Reply-To: (message from Mattias =?UTF-8?Q?Engdeg=C3=A5rd?= on Sat, 30 Mar 2024 15:22:34 +0100) References: <1BF559D1-DB9F-4FEB-90ED-72E0EFD76424@gmail.com> <86wmpphrg7.fsf@gnu.org> <4589243D-C11A-45C1-AF3E-6F4A5BADEB54@gmail.com> <864jcrindg.fsf@gnu.org> <291DD5F1-85B8-4647-A40A-EBBD4C51E253@gmail.com> <8634sbijfx.fsf@gnu.org> <2CF47DA5-A65B-47C4-A28A-6FEE1469BD13@gmail.com> <86cyrdfuai.fsf@gnu.org> <3139C8FE-5C67-4FE3-B940-F449DA73E76C@gmail.com> <86le5zdfbi.fsf@gnu.org> MIME-version: 1.0 Content-type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Spam-Score: -2.3 (--) X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -3.3 (---) > From: Mattias EngdegÃ¥rd > Date: Sat, 30 Mar 2024 15:22:34 +0100 > Cc: casouri@gmail.com, > 70007@debbugs.gnu.org > > I made the changes above and installed it on master, as well as a sweeping removal of all things Jansson. Thanks. The new code failed to link due to an omission in src/Makefile.in, and also the "clever" initialization in json_serialize confused make-docfile (so globals.h were generated incorrectly: they missed the DEFSYMs in syms_of_json). I think I fixed that, but please eyeball the changes to see if I missed something. From unknown Sun Jun 15 14:44:57 2025 X-Loop: help-debbugs@gnu.org Subject: bug#70007: [PATCH] native JSON encoder Resent-From: Eli Zaretskii Original-Sender: "Debbugs-submit" Resent-CC: bug-gnu-emacs@gnu.org Resent-Date: Sat, 30 Mar 2024 16:42:02 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 70007 X-GNU-PR-Package: emacs X-GNU-PR-Keywords: patch To: Richard Copley Cc: mattias.engdegard@gmail.com, 70007@debbugs.gnu.org Received: via spool by 70007-submit@debbugs.gnu.org id=B70007.17118168625160 (code B ref 70007); Sat, 30 Mar 2024 16:42:02 +0000 Received: (at 70007) by debbugs.gnu.org; 30 Mar 2024 16:41:02 +0000 Received: from localhost ([127.0.0.1]:46095 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1rqblO-0001LA-56 for submit@debbugs.gnu.org; Sat, 30 Mar 2024 12:41:02 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:57942) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1rqblM-0001KT-AU for 70007@debbugs.gnu.org; Sat, 30 Mar 2024 12:41:00 -0400 Received: from fencepost.gnu.org ([2001:470:142:3::e]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1rqblF-0000at-0K; Sat, 30 Mar 2024 12:40:53 -0400 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=gnu.org; s=fencepost-gnu-org; h=MIME-version:References:Subject:In-Reply-To:To:From: Date; bh=vKgOY8YUrwC/p8lSHU9GBDq4XpDcOXA0nmKoLIOV43s=; b=f9vIkaQqiVeOmJnr+IN1 uprwb2PMgIda+ID5jj6aJFGNuk1O7c0hC2zY/pzxdnX1kHd7Ub5iue/zDtAzCPqFDAuN4d3KMoMoA byIqyZ8X53n4C3L/BhwV3DGqdP+XVZeFIqoYeD4mvBMsLIt4ZdcqOedZyNGOnnvflzIy/vvlrfXzh xeUHazi/GR64IIH45/LQQfUC9bDoCcgQuoNEc/hibNb+E4rMdUwjWtEMPSh2U+y00w0toskaozWz1 fbPBOND543H1gJuUuZINX4ZZzf9JbYihsvV7Uc4P1JbI0quwVxkoHL9+Np4AK2BpyZjiT+mEpmDSw Bq3erVC1RhklHw==; Date: Sat, 30 Mar 2024 19:40:50 +0300 Message-Id: <868r1zd65p.fsf@gnu.org> From: Eli Zaretskii In-Reply-To: (message from Richard Copley on Sat, 30 Mar 2024 16:14:45 +0000) References: <1BF559D1-DB9F-4FEB-90ED-72E0EFD76424@gmail.com> <86wmpphrg7.fsf@gnu.org> <4589243D-C11A-45C1-AF3E-6F4A5BADEB54@gmail.com> <864jcrindg.fsf@gnu.org> <291DD5F1-85B8-4647-A40A-EBBD4C51E253@gmail.com> <8634sbijfx.fsf@gnu.org> <2CF47DA5-A65B-47C4-A28A-6FEE1469BD13@gmail.com> <86cyrdfuai.fsf@gnu.org> <3139C8FE-5C67-4FE3-B940-F449DA73E76C@gmail.com> <86le5zdfbi.fsf@gnu.org> MIME-version: 1.0 Content-type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Spam-Score: -2.3 (--) X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -3.3 (---) > Cc: 70007@debbugs.gnu.org > Date: Sat, 30 Mar 2024 16:14:45 +0000 > From: Richard Copley > > On 30/03/2024 14:22, Mattias EngdegÃ¥rd wrote: > > I made the changes above and installed it on master, as well as a sweeping removal of all things Jansson. > > Hi Mattias, > A clean build fails with a linker error: > > CCLD temacs > /usr/bin/ld: /tmp/cc4stUid.ltrans15.ltrans.o: in function `main': > :(.text.startup+0x39a9): undefined reference to `syms_of_json' > collect2: error: ld returned 1 exit status > make[2]: *** [Makefile:739: temacs] Error 1 Please try again, I hope I fixed this. From unknown Sun Jun 15 14:44:57 2025 X-Loop: help-debbugs@gnu.org Subject: bug#70007: [PATCH] native JSON encoder In-Reply-To: <1BF559D1-DB9F-4FEB-90ED-72E0EFD76424@gmail.com> Resent-From: Andy Moreton Original-Sender: "Debbugs-submit" Resent-CC: bug-gnu-emacs@gnu.org Resent-Date: Sat, 30 Mar 2024 16:47:02 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 70007 X-GNU-PR-Package: emacs X-GNU-PR-Keywords: patch To: 70007@debbugs.gnu.org X-Debbugs-Original-To: bug-gnu-emacs@gnu.org Received: via spool by submit@debbugs.gnu.org id=B.17118171796291 (code B ref -1); Sat, 30 Mar 2024 16:47:02 +0000 Received: (at submit) by debbugs.gnu.org; 30 Mar 2024 16:46:19 +0000 Received: from localhost ([127.0.0.1]:46104 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1rqbqV-0001dO-Bl for submit@debbugs.gnu.org; Sat, 30 Mar 2024 12:46:19 -0400 Received: from lists.gnu.org ([2001:470:142::17]:38404) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1rqbqT-0001cP-5Q for submit@debbugs.gnu.org; Sat, 30 Mar 2024 12:46:18 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1rqbqL-0004iY-QS for bug-gnu-emacs@gnu.org; Sat, 30 Mar 2024 12:46:09 -0400 Received: from ciao.gmane.io ([116.202.254.214]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1rqbqK-00024z-Iz for bug-gnu-emacs@gnu.org; Sat, 30 Mar 2024 12:46:09 -0400 Received: from list by ciao.gmane.io with local (Exim 4.92) (envelope-from ) id 1rqbqF-0005Fo-TM for bug-gnu-emacs@gnu.org; Sat, 30 Mar 2024 17:46:03 +0100 X-Injected-Via-Gmane: http://gmane.org/ From: Andy Moreton Date: Sat, 30 Mar 2024 16:45:54 +0000 Message-ID: <86r0fr3by5.fsf@gmail.com> References: <1BF559D1-DB9F-4FEB-90ED-72E0EFD76424@gmail.com> <86wmpphrg7.fsf@gnu.org> <4589243D-C11A-45C1-AF3E-6F4A5BADEB54@gmail.com> <864jcrindg.fsf@gnu.org> <291DD5F1-85B8-4647-A40A-EBBD4C51E253@gmail.com> <8634sbijfx.fsf@gnu.org> <2CF47DA5-A65B-47C4-A28A-6FEE1469BD13@gmail.com> <86cyrdfuai.fsf@gnu.org> <3139C8FE-5C67-4FE3-B940-F449DA73E76C@gmail.com> <86le5zdfbi.fsf@gnu.org> Mime-Version: 1.0 Content-Type: text/plain; charset=iso-8859-1 Content-Transfer-Encoding: 8bit User-Agent: Gnus/5.13 (Gnus v5.13) Cancel-Lock: sha1:Z2gUAVUf3EQ3GFdPO6Gp7AbrwZM= Received-SPF: pass client-ip=116.202.254.214; envelope-from=geb-bug-gnu-emacs@m.gmane-mx.org; helo=ciao.gmane.io X-Spam_score_int: 3 X-Spam_score: 0.3 X-Spam_bar: / X-Spam_report: (0.3 / 5.0 requ) BAYES_00=-1.9, DKIM_ADSP_CUSTOM_MED=0.001, FORGED_GMAIL_RCVD=1, FREEMAIL_FORGED_FROMDOMAIN=0.001, FREEMAIL_FROM=0.001, HEADER_FROM_DIFFERENT_DOMAINS=0.249, NML_ADSP_CUSTOM_MED=0.9, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=no autolearn_force=no X-Spam_action: no action X-Spam-Score: 1.3 (+) X-Spam-Report: Spam detection software, running on the system "debbugs.gnu.org", has NOT identified this incoming email as spam. The original message has been attached to this so you can view it or label similar future email. If you have any questions, see the administrator of that system for details. Content preview: On Sat 30 Mar 2024, Richard Copley wrote: > On 30/03/2024 14:22, Mattias =?UTF-8?Q?Engdeg=E5rd?= wrote: >> I made the changes above and installed it on master, as well as a sweeping removal of all things Jansson. > > Hi Mattias, > A clean build fails with [...] Content analysis details: (1.3 points, 10.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- 0.0 FREEMAIL_FROM Sender email is commonly abused enduser mail provider (andrewjmoreton[at]gmail.com) 0.0 T_SPF_PERMERROR SPF: test of record failed (permerror) 1.0 FORGED_GMAIL_RCVD 'From' gmail.com does not match 'Received' headers -0.0 SPF_HELO_PASS SPF: HELO matches SPF record 0.2 HEADER_FROM_DIFFERENT_DOMAINS From and EnvelopeFrom 2nd level mail domains are different 0.0 FREEMAIL_FORGED_FROMDOMAIN 2nd level domains in From and EnvelopeFrom freemail headers are different X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: 0.3 (/) On Sat 30 Mar 2024, Richard Copley wrote: > On 30/03/2024 14:22, Mattias Engdegård wrote: >> I made the changes above and installed it on master, as well as a sweeping removal of all things Jansson. > > Hi Mattias, > A clean build fails with a linker error: > > CCLD temacs > /usr/bin/ld: /tmp/cc4stUid.ltrans15.ltrans.o: in function `main': > :(.text.startup+0x39a9): undefined reference to `syms_of_json' > collect2: error: ld returned 1 exit status > make[2]: *** [Makefile:739: temacs] Error 1 Commit 1135ce461d18 ("Always enable native JSON support and remove Jansson references") removed json.o from configure.ac, but did not add it in Makefile.in to ensure it is always built. Adding json.o to base_obj there appears to fix the build. AndyM From unknown Sun Jun 15 14:44:57 2025 X-Loop: help-debbugs@gnu.org Subject: bug#70007: [PATCH] native JSON encoder Resent-From: Mattias =?UTF-8?Q?Engdeg=C3=A5rd?= Original-Sender: "Debbugs-submit" Resent-CC: bug-gnu-emacs@gnu.org Resent-Date: Sat, 30 Mar 2024 20:22:02 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 70007 X-GNU-PR-Package: emacs X-GNU-PR-Keywords: patch To: Eli Zaretskii Cc: casouri@gmail.com, 70007@debbugs.gnu.org Received: via spool by 70007-submit@debbugs.gnu.org id=B70007.171183011216809 (code B ref 70007); Sat, 30 Mar 2024 20:22:02 +0000 Received: (at 70007) by debbugs.gnu.org; 30 Mar 2024 20:21:52 +0000 Received: from localhost ([127.0.0.1]:46212 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1rqfD5-0004N3-Jl for submit@debbugs.gnu.org; Sat, 30 Mar 2024 16:21:51 -0400 Received: from mail-lj1-x22e.google.com ([2a00:1450:4864:20::22e]:44442) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1rqfD2-0004MV-Qw for 70007@debbugs.gnu.org; Sat, 30 Mar 2024 16:21:49 -0400 Received: by mail-lj1-x22e.google.com with SMTP id 38308e7fff4ca-2d6dda3adb9so29380891fa.1 for <70007@debbugs.gnu.org>; Sat, 30 Mar 2024 13:21:46 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1711830101; x=1712434901; darn=debbugs.gnu.org; h=to:references:message-id:content-transfer-encoding:cc:date :in-reply-to:from:subject:mime-version:sender:from:to:cc:subject :date:message-id:reply-to; bh=qWI4qdW35vQOcSR92ag/e0g97VjK6MWekRpYhN+YG9w=; b=USwJYHSI9YQYP1VuL48TG99xN8WVqapGMeJ5bdC1pafbWCEqsOfbJ0J9qleYtppESD xRnxbrWham6z7pIwckv4f2JNAQwPaoHFJNyAPLg2yNjVICqUv1TojnEgudEgUYzAPFXe FhUeoHJa590ny1VQBTm9Br10chpp5eIagsrXd/11j6LvIHIoBkq1HGyqRzv8+07bb4JS VscTY9Fy9NuuqdG+rVh8mjtqcaY6hcZRWiXyBWKh3RJbihfgBqsxWN38tDNNnwPmUaDj JPZKNhUPQskXwCM/qtHOrBFUznB00V3My93XZ84Mxfdd060lyxnUrgzQdffToUI2QIrY /cxQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1711830101; x=1712434901; h=to:references:message-id:content-transfer-encoding:cc:date :in-reply-to:from:subject:mime-version:sender:x-gm-message-state :from:to:cc:subject:date:message-id:reply-to; bh=qWI4qdW35vQOcSR92ag/e0g97VjK6MWekRpYhN+YG9w=; b=P/YXVwO6L610wv+qjIYpvpPtEXpEf71gyugxSjpFHsjOxz+V6favx2NtNmpqeh3ELK eHePkdGDNO0QwxWgRleabmmaJgg1Agm7KzN5DSaZZ0J6lNwQC2on3R1+QhrIGbn5TghI 8xWV1cPVTZr2p3Vur5kcnBrppR39bd/e+tY4ABn9Hl72ko+Fh2TlZ2kJ3f+rzsm7D2SJ UJm1u3rJfh5ETQYf3m3h/WjI9P0zWDhZFGeiqqBspyRTjwQ68vg7ktHYYWKJLotITKSR 2k8Tw6CagwWReuvyOZLXnbdX0Y6McR5hJVMlZBAk2m6E9DYnNLhVwqnuHZ7M4uHm5yG4 SnVg== X-Forwarded-Encrypted: i=1; AJvYcCWLAKQFwB66ywvDYcAj77U0aaXYpVCUMkgnw/hDbsX+J1FVTPjZhsmraXSffr2aMmo/3Hw46YID+z46N03vplJcdCi9DuM= X-Gm-Message-State: AOJu0YxKn4X/Os27kcy0gRQbZNOKRxkfxaUfXpCXo5Uz2YoUPeZBFcpX 0A3ivSIq2f+EsAQI66b2q9eIYyHnp16dRGviUQ50GKOa6tKa2neM+90h0SC7 X-Google-Smtp-Source: AGHT+IGdfIUmPRsq1IrYKx1E9IUWdp1P0ITGkmh3HCw/pIYIEI4Z2Jg3hMtleQ2BNYn4KotD4KACGw== X-Received: by 2002:a05:6512:3052:b0:515:a8f0:221 with SMTP id b18-20020a056512305200b00515a8f00221mr4834994lfb.37.1711830100500; Sat, 30 Mar 2024 13:21:40 -0700 (PDT) Received: from smtpclient.apple (c80-217-1-132.bredband.tele2.se. [80.217.1.132]) by smtp.gmail.com with ESMTPSA id g13-20020a19e04d000000b00516a2fe4290sm112023lfj.253.2024.03.30.13.21.39 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Sat, 30 Mar 2024 13:21:39 -0700 (PDT) Content-Type: text/plain; charset=us-ascii Mime-Version: 1.0 (Mac OS X Mail 14.0 \(3654.120.0.1.15\)) From: Mattias =?UTF-8?Q?Engdeg=C3=A5rd?= In-Reply-To: <86edbrd6bv.fsf@gnu.org> Date: Sat, 30 Mar 2024 21:21:39 +0100 Content-Transfer-Encoding: quoted-printable Message-Id: References: <1BF559D1-DB9F-4FEB-90ED-72E0EFD76424@gmail.com> <86wmpphrg7.fsf@gnu.org> <4589243D-C11A-45C1-AF3E-6F4A5BADEB54@gmail.com> <864jcrindg.fsf@gnu.org> <291DD5F1-85B8-4647-A40A-EBBD4C51E253@gmail.com> <8634sbijfx.fsf@gnu.org> <2CF47DA5-A65B-47C4-A28A-6FEE1469BD13@gmail.com> <86cyrdfuai.fsf@gnu.org> <3139C8FE-5C67-4FE3-B940-F449DA73E76C@gmail.com> <86le5zdfbi.fsf@gnu.org> <86edbrd6bv.fsf@gnu.org> X-Mailer: Apple Mail (2.3654.120.0.1.15) X-Spam-Score: 0.0 (/) X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -1.0 (-) 30 mars 2024 kl. 17.37 skrev Eli Zaretskii : > Thanks. =20 > The new code failed to link due to an omission in > src/Makefile.in, and also the "clever" initialization in > json_serialize confused make-docfile (so globals.h were generated > incorrectly: they missed the DEFSYMs in syms_of_json). I think I > fixed that, but please eyeball the changes to see if I missed > something. Blast, I thought I had bootstrapped and tested it but naturally used the = wrong tree. Thanks for putting it right. We should do something about make-docfile one of these days. From unknown Sun Jun 15 14:44:57 2025 X-Loop: help-debbugs@gnu.org Subject: bug#70007: [PATCH] native JSON encoder Resent-From: Corwin Brust Original-Sender: "Debbugs-submit" Resent-CC: bug-gnu-emacs@gnu.org Resent-Date: Sat, 30 Mar 2024 20:38:02 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 70007 X-GNU-PR-Package: emacs X-GNU-PR-Keywords: patch To: Andy Moreton Cc: 70007@debbugs.gnu.org Received: via spool by 70007-submit@debbugs.gnu.org id=B70007.171183104220207 (code B ref 70007); Sat, 30 Mar 2024 20:38:02 +0000 Received: (at 70007) by debbugs.gnu.org; 30 Mar 2024 20:37:22 +0000 Received: from localhost ([127.0.0.1]:46241 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1rqfS6-0005Fp-8n for submit@debbugs.gnu.org; Sat, 30 Mar 2024 16:37:22 -0400 Received: from mail-oa1-f43.google.com ([209.85.160.43]:47164) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1rqfS4-0005FY-1D for 70007@debbugs.gnu.org; Sat, 30 Mar 2024 16:37:21 -0400 Received: by mail-oa1-f43.google.com with SMTP id 586e51a60fabf-221816e3ab9so1523915fac.2 for <70007@debbugs.gnu.org>; Sat, 30 Mar 2024 13:37:17 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1711831032; x=1712435832; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=k4xqMacIBpa6m84WFFRzqy5B35zCrTMfMMwpJB+iiTw=; b=kPTbbmm2wqKcOkXRAV6APfXVHgyd2GNnWPlGYCHcLJw8v/l4krAVfXXfiQUrgVj2sF T/zHues+gWZk5eoUCbCc7tEi4gpQileZFG15hTFgfv0+gNDItwp0aerP4NUgbGZp2MEc HlbTXwmaRXx0WLK6sNZstbUCJZPUusqYPQeKYcJLsuytYuVyL8YUxDSP8+ljhVoKu+Yn qHgPV9cNlawr0RBIh58ILUNHO5Palyn1ihoMh2qpkl68kLMnC9n3aUNt9u2CWRVodQKr y9LjCLT7oDx8wrkx4OQ1pd3QavPyXANKqEfScOd7k/UWrQfuu+qJlK0txTEXFwlo+5Sm ZPFQ== X-Gm-Message-State: AOJu0YwpH+cVh3Ke0tRjEuK8NWF+MwKo6k4faFfD37kL7IOKc0YekmwI TMwzF6l2OMDvHPllnqeguOoyAw2KrPfiCEHJqUreQVOVJJYy92HFUhKWbjxbyjzcLTHi7gP0LO8 XqkVCF2cKm5l3OiwX6Kjww7fHNg0= X-Google-Smtp-Source: AGHT+IGxNFCgdmpWjxBH+jtrALzZpB3g9krz5DDUlmySXD5M8oYrHKkgG6bvg8kqJ004sXdhl8galdFhNH56K9svKH8= X-Received: by 2002:a05:6871:7a8:b0:229:fc1d:1ae with SMTP id o40-20020a05687107a800b00229fc1d01aemr6036840oap.31.1711831031958; Sat, 30 Mar 2024 13:37:11 -0700 (PDT) MIME-Version: 1.0 References: <86wmpphrg7.fsf@gnu.org> <4589243D-C11A-45C1-AF3E-6F4A5BADEB54@gmail.com> <864jcrindg.fsf@gnu.org> <291DD5F1-85B8-4647-A40A-EBBD4C51E253@gmail.com> <8634sbijfx.fsf@gnu.org> <2CF47DA5-A65B-47C4-A28A-6FEE1469BD13@gmail.com> <86cyrdfuai.fsf@gnu.org> <3139C8FE-5C67-4FE3-B940-F449DA73E76C@gmail.com> <86le5zdfbi.fsf@gnu.org> <1BF559D1-DB9F-4FEB-90ED-72E0EFD76424@gmail.com> <86r0fr3by5.fsf@gmail.com> In-Reply-To: <86r0fr3by5.fsf@gmail.com> From: Corwin Brust Date: Sat, 30 Mar 2024 15:36:59 -0500 Message-ID: Content-Type: text/plain; charset="UTF-8" X-Spam-Score: 0.2 (/) X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -0.8 (/) > >> I made the changes above and installed it on master, as well as a sweeping removal of all things Jansson. This builds okay for me with MSYS2/Mingw64; here are some Windows binaries if anyone would like to test: https://corwin.bru.st/emacs-30/emacs-30-000f91 Thanks! From unknown Sun Jun 15 14:44:57 2025 X-Loop: help-debbugs@gnu.org Subject: bug#70007: [PATCH] native JSON encoder Resent-From: Richard Copley Original-Sender: "Debbugs-submit" Resent-CC: bug-gnu-emacs@gnu.org Resent-Date: Sat, 30 Mar 2024 23:31:03 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 70007 X-GNU-PR-Package: emacs X-GNU-PR-Keywords: patch To: Eli Zaretskii Cc: mattias.engdegard@gmail.com, 70007@debbugs.gnu.org Received: via spool by 70007-submit@debbugs.gnu.org id=B70007.171184142921338 (code B ref 70007); Sat, 30 Mar 2024 23:31:03 +0000 Received: (at 70007) by debbugs.gnu.org; 30 Mar 2024 23:30:29 +0000 Received: from localhost ([127.0.0.1]:46335 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1rqi9b-0005Xv-Vp for submit@debbugs.gnu.org; Sat, 30 Mar 2024 19:30:29 -0400 Received: from mail-qt1-x82f.google.com ([2607:f8b0:4864:20::82f]:50403) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1rqi9W-0005XR-Mc for 70007@debbugs.gnu.org; Sat, 30 Mar 2024 19:30:26 -0400 Received: by mail-qt1-x82f.google.com with SMTP id d75a77b69052e-430a25ed4e7so20620251cf.0 for <70007@debbugs.gnu.org>; Sat, 30 Mar 2024 16:30:20 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1711841415; x=1712446215; darn=debbugs.gnu.org; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version:from:to:cc:subject:date:message-id:reply-to; bh=mRajx0uQyjI3aBH1/zXgfsO1xKQAeUtPlNKWJt3kja4=; b=jIEq1TN+FAnnRtTlL9rgU9lmApvzivu63+qD5d1/R/KCK0dO2cEh4HsCmqUN/8Rz+n wZeoeSKymxGJoLpvo8fGOriOOxyxzF03k4iXc5SRhkaP6K5w5mmhFxMVMrus81hF2JVw kZ1sg96bTq5Wlgw4ZVUbH5qzweMH9DpejQ/DCo3tNdhRXWMg7SA0TG1EWk8f17YzT1ZY bD5ltzscogD4X2A0a1Bze4zqnoimcGC1Q9NBlZyqMrNbCP4Th67/hNiCTakSHe1v4w1c LM1r+2RPxrvOz8xTx748I59N74t5DqkWIMGLqxi1mdkH/9vhXti7lb6FEEGBnX/e2+8G 7e4w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1711841415; x=1712446215; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=mRajx0uQyjI3aBH1/zXgfsO1xKQAeUtPlNKWJt3kja4=; b=NvYDuJwGax3GSOkRLJJ1DQgvPvU+XpWRYJNlBki7xzcy4L7WMu5mHz8S7So+QrSgQQ +9HZCLI7l/YXLDXFYMMPexx1Xog/btDdPfWkG/kKoFJhU7f0xKBB+3J8rMKjzdStvCUG Aw6uLqvuZESB5OQUsfMc2Vndrh45sq/SLSZkRJScmw/pUh4XkWNlgh+25L+sS8Je+k13 0srqI4DGfyI6gps/A1Fr9Y6vTn8j48Z3MCpo30ONCvx55QzNbtZRcWM6uA1xLeVHhIax Fi+zAZLPpV1GuQ8gGcVjF1bGaz9+aSe0uejJ3mdtJqsroaXC0aqZei7NN/8ufBqXjP1Y iG7g== X-Forwarded-Encrypted: i=1; AJvYcCWY4M+FvCFgVP96CkAHVfRLwwKHxDhsCRKqcco+0B7khEKWckpKgfj10801oEEH96CmWxfoPBl8ECsNmLan6lYQ4HUb+VM= X-Gm-Message-State: AOJu0YxkCVz39bYPLBU8tC80EXZI7OWyy+rAd32sbU1WD3PF2McAQ8ep VLT689TEeu0pvs58SSCNVptGh1LEJ7P8mM8gggGtOytf+FQZ/MPSd1YUqVRkqgV559sS4n9DYBw nfkMzjFput0rNOkLMmNl6BgDKhw4= X-Google-Smtp-Source: AGHT+IGsWMP0ORgpnuW1U6MSjPw399ZieCFqrApVwkQa6udijVTeoJ3Y5yx5Dnsqb67kABg8tnhl6AAHCwR1edoL25Y= X-Received: by 2002:ac8:59c8:0:b0:431:f7fc:dd0f with SMTP id f8-20020ac859c8000000b00431f7fcdd0fmr6763613qtf.54.1711841415003; Sat, 30 Mar 2024 16:30:15 -0700 (PDT) MIME-Version: 1.0 References: <1BF559D1-DB9F-4FEB-90ED-72E0EFD76424@gmail.com> <86wmpphrg7.fsf@gnu.org> <4589243D-C11A-45C1-AF3E-6F4A5BADEB54@gmail.com> <864jcrindg.fsf@gnu.org> <291DD5F1-85B8-4647-A40A-EBBD4C51E253@gmail.com> <8634sbijfx.fsf@gnu.org> <2CF47DA5-A65B-47C4-A28A-6FEE1469BD13@gmail.com> <86cyrdfuai.fsf@gnu.org> <3139C8FE-5C67-4FE3-B940-F449DA73E76C@gmail.com> <86le5zdfbi.fsf@gnu.org> <868r1zd65p.fsf@gnu.org> In-Reply-To: <868r1zd65p.fsf@gnu.org> From: Richard Copley Date: Sat, 30 Mar 2024 23:29:48 +0000 Message-ID: Content-Type: text/plain; charset="UTF-8" X-Spam-Score: 0.0 (/) X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -1.0 (-) On Sat, 30 Mar 2024 at 16:40, Eli Zaretskii wrote: > Please try again, I hope I fixed this. Thanks, looks good. From unknown Sun Jun 15 14:44:57 2025 X-Loop: help-debbugs@gnu.org Subject: bug#70007: [PATCH] native JSON encoder Resent-From: Mattias =?UTF-8?Q?Engdeg=C3=A5rd?= Original-Sender: "Debbugs-submit" Resent-CC: bug-gnu-emacs@gnu.org Resent-Date: Tue, 02 Apr 2024 14:15:02 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 70007 X-GNU-PR-Package: emacs X-GNU-PR-Keywords: patch To: Eli Zaretskii Cc: casouri@gmail.com, 70007@debbugs.gnu.org Received: via spool by 70007-submit@debbugs.gnu.org id=B70007.171206725428086 (code B ref 70007); Tue, 02 Apr 2024 14:15:02 +0000 Received: (at 70007) by debbugs.gnu.org; 2 Apr 2024 14:14:14 +0000 Received: from localhost ([127.0.0.1]:54855 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1rretx-0007Iu-JL for submit@debbugs.gnu.org; Tue, 02 Apr 2024 10:14:14 -0400 Received: from mail-lf1-x130.google.com ([2a00:1450:4864:20::130]:59702) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1rretv-0007I1-C9 for 70007@debbugs.gnu.org; Tue, 02 Apr 2024 10:14:12 -0400 Received: by mail-lf1-x130.google.com with SMTP id 2adb3069b0e04-516b80252c5so854827e87.3 for <70007@debbugs.gnu.org>; Tue, 02 Apr 2024 07:14:07 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1712067241; x=1712672041; darn=debbugs.gnu.org; h=references:to:cc:in-reply-to:date:subject:mime-version:message-id :from:sender:from:to:cc:subject:date:message-id:reply-to; bh=8gyVk4MN1Zd5mZnqH3NH0cDrb7AxYffHP1IZSp9XBFo=; b=hl+o7cxWdIIDxaUD83IwxBPvJmQR+uVjSpPG4RdEIjSMZoP2lS6Nw7KmPM7ZCYAGIX wH7Ri/xXPEfcA67L64eHSKweoBydeo44/Pq46hN+p66nwzpok1IXRuS5TWQ6RW6E0F6y 70mkx3udL1yQWwJQ2POOOF1wf8lNlq12gSfjO7H4EEORQQdKkuDsniYRC+UC0shEv55u F5T2odUYY21qlwv9cpVbzwcUpky6UOkpkio6wlpDcF2ZBlwkL1e+s8ePv9mKQmg1zfct dKi6QoWeOoSQRiE0LNoSdPeTpHnCegHhICoONmx37yib+qnhd2AfUFAAW2xX0g/ab7X7 wPBg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1712067241; x=1712672041; h=references:to:cc:in-reply-to:date:subject:mime-version:message-id :from:sender:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=8gyVk4MN1Zd5mZnqH3NH0cDrb7AxYffHP1IZSp9XBFo=; b=ZSbE0BcGy63wuEXmsy3T7/XVBjmYwNsf+iFmxNLKxMKADvVHNXBtudA/1FxF8QwC00 x0Dg3Ni1mheIAECSHEJhqHSvS2Yww17XqhNYagwCXAFPHy63i2KcSWTqBrQg4JOBiA0/ wGgBcyyMe1lGx3Jp4HijES8NQU5gOC3onOqe2eYD82oQS1UGPd8HYICjzoiGerqDDnNd e6uQ8fCY3eGqkPxPOjuDG7mtQhWIvHiM0W0wzNu1U6iC4STNXsMghIVPSe+CbSsKivQR Yz/ZsFOxCG1Z+fehV+/GikICT+EqmeSMJYF0ePC7ZS8dc80nsygY1kZvkb/DDdpT3zSQ PVvQ== X-Forwarded-Encrypted: i=1; AJvYcCX7zjtXuOMLpni+N6BJM8BUfOHMLX1EYNApSZyxXytcSAY1gh2dVr4ZjUPOZMEwGKtMEWMBw4vj+I5w0vi/yszWLW8JF7M= X-Gm-Message-State: AOJu0YwP2Cu4EtyJBE9K+m7VSpMA5GZTRKIKC0uIEc0qYfvANhoe93NB ocr+1tXoLRPDKBVU3yv4Nl3tQo+1TNUE2rxonKdvHeILiIK6/HaT X-Google-Smtp-Source: AGHT+IGrlhQZ+mPtyJyqcMWuHId2NUpkYnTCwKoS2OAX3xO5R0Eroh22cUe99XwxSfJUVZO1Ue3f9w== X-Received: by 2002:ac2:424b:0:b0:515:9ee7:ce45 with SMTP id m11-20020ac2424b000000b005159ee7ce45mr9207827lfl.49.1712067241078; Tue, 02 Apr 2024 07:14:01 -0700 (PDT) Received: from smtpclient.apple (c80-217-1-132.bredband.tele2.se. [80.217.1.132]) by smtp.gmail.com with ESMTPSA id c15-20020a19760f000000b00515ac3af704sm1739962lff.79.2024.04.02.07.13.59 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Tue, 02 Apr 2024 07:14:00 -0700 (PDT) From: Mattias =?UTF-8?Q?Engdeg=C3=A5rd?= Message-Id: <4C93E902-282D-4408-B449-C8E771B2B3E4@gmail.com> Content-Type: multipart/mixed; boundary="Apple-Mail=_02BFADEC-F9DF-4C2E-8704-AF3AF789CAD1" Mime-Version: 1.0 (Mac OS X Mail 14.0 \(3654.120.0.1.15\)) Date: Tue, 2 Apr 2024 16:13:58 +0200 In-Reply-To: References: <1BF559D1-DB9F-4FEB-90ED-72E0EFD76424@gmail.com> <86wmpphrg7.fsf@gnu.org> <4589243D-C11A-45C1-AF3E-6F4A5BADEB54@gmail.com> <864jcrindg.fsf@gnu.org> <291DD5F1-85B8-4647-A40A-EBBD4C51E253@gmail.com> <8634sbijfx.fsf@gnu.org> <2CF47DA5-A65B-47C4-A28A-6FEE1469BD13@gmail.com> <86cyrdfuai.fsf@gnu.org> <3139C8FE-5C67-4FE3-B940-F449DA73E76C@gmail.com> <86le5zdfbi.fsf@gnu.org> X-Mailer: Apple Mail (2.3654.120.0.1.15) X-Spam-Score: 0.0 (/) X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -1.0 (-) --Apple-Mail=_02BFADEC-F9DF-4C2E-8704-AF3AF789CAD1 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset=utf-8 Looks like the new serialiser inherited a bug from the old code: = `json-insert` in a unibyte buffer does not move point correctly. = Example: (with-temp-buffer (set-buffer-multibyte nil) (json-insert "=C3=A9") (list (buffer-string) (point))) =3D> ("\"\303\251\"" 4) The string is correct but the position should be 5, not 4. This made me look at the Fjson_insert logic a bit. I'm probably = betraying my lack of knowledge about buffer subtleties here, but since = the serialiser always produces (correct) UTF-8, shouldn't it be enough = to copy the bytes, don't bother with any decoding, and perform the = buffer insertion ceremonies? Proposed patch attached. (There will also be a test, of course.) --Apple-Mail=_02BFADEC-F9DF-4C2E-8704-AF3AF789CAD1 Content-Disposition: attachment; filename=json-insert.diff Content-Type: application/octet-stream; x-unix-mode=0644; name="json-insert.diff" Content-Transfer-Encoding: 7bit diff --git a/src/json.c b/src/json.c index c3244ad04d2..7c62d63c6fd 100644 --- a/src/json.c +++ b/src/json.c @@ -656,39 +656,14 @@ DEFUN ("json-insert", Fjson_insert, Sjson_insert, 1, MANY, /* No need to keep allocation beyond this point. */ unbind_to (count, Qnil); - ptrdiff_t inserted = 0; + bool ub_buffer = NILP (BVAR (current_buffer, enable_multibyte_characters)); ptrdiff_t inserted_bytes = jo.size; + ptrdiff_t inserted = ub_buffer ? jo.size : jo.size - jo.chars_delta; - /* If required, decode the stuff we've read into the gap. */ - struct coding_system coding; - /* JSON strings are UTF-8 encoded strings. */ - 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; - } + insert_from_gap_1 (inserted, inserted_bytes, false); + invalidate_buffer_caches (current_buffer, PT, PT + inserted); + adjust_after_insert (PT, PT_BYTE, PT + inserted, PT_BYTE + inserted_bytes, + inserted); /* Call after-change hooks. */ signal_after_change (PT, 0, inserted); --Apple-Mail=_02BFADEC-F9DF-4C2E-8704-AF3AF789CAD1-- From unknown Sun Jun 15 14:44:57 2025 X-Loop: help-debbugs@gnu.org Subject: bug#70007: [PATCH] native JSON encoder Resent-From: Eli Zaretskii Original-Sender: "Debbugs-submit" Resent-CC: bug-gnu-emacs@gnu.org Resent-Date: Tue, 02 Apr 2024 16:15:02 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 70007 X-GNU-PR-Package: emacs X-GNU-PR-Keywords: patch To: Mattias =?UTF-8?Q?Engdeg=C3=A5rd?= Cc: casouri@gmail.com, 70007@debbugs.gnu.org Received: via spool by 70007-submit@debbugs.gnu.org id=B70007.171207447229708 (code B ref 70007); Tue, 02 Apr 2024 16:15:02 +0000 Received: (at 70007) by debbugs.gnu.org; 2 Apr 2024 16:14:32 +0000 Received: from localhost ([127.0.0.1]:55814 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1rrgmM-0007j4-F5 for submit@debbugs.gnu.org; Tue, 02 Apr 2024 12:14:32 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:36984) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1rrgmI-0007id-Rg for 70007@debbugs.gnu.org; Tue, 02 Apr 2024 12:14:29 -0400 Received: from fencepost.gnu.org ([2001:470:142:3::e]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1rrgm9-0000Vs-Lc; Tue, 02 Apr 2024 12:14:17 -0400 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=gnu.org; s=fencepost-gnu-org; h=MIME-version:References:Subject:In-Reply-To:To:From: Date; bh=I4ts5uEPz70vdQzF2ivdvkPm5EBF//BagkhPLti65RI=; b=hzsktpUJSsTf/BBIvBmA BFMlMLqtjA7kTL6U4fki+C7oI0u9J7oR2PbkollOYMjw2EL63JKuzc5zlzWITEfghAhOue430NWg+ WmlFoWUgiPFCOgjg1pPe5xUY7wIOJ720Y6HxV0CfIdFc/8VIyH24wP27EHC74BbdSzR+QwSIvDekw rrpgYGa1YHlvKS+xtOxjq+RLOo9fzVPWKjWjBDxql80DeVOtlptc4u9jjZuE5zi6HClPyVf1HuYnT hgHCQuQKbg/JM88IhM27v0BPIV2nNbkJ4TDbhLYpDwWuGyOWnwOzvxkx40775nYMen75oT1BPW+bp L77ZekltdQI/pg==; Date: Tue, 02 Apr 2024 19:13:47 +0300 Message-Id: <86cyr7agjo.fsf@gnu.org> From: Eli Zaretskii In-Reply-To: <4C93E902-282D-4408-B449-C8E771B2B3E4@gmail.com> (message from Mattias =?UTF-8?Q?Engdeg=C3=A5rd?= on Tue, 2 Apr 2024 16:13:58 +0200) References: <1BF559D1-DB9F-4FEB-90ED-72E0EFD76424@gmail.com> <86wmpphrg7.fsf@gnu.org> <4589243D-C11A-45C1-AF3E-6F4A5BADEB54@gmail.com> <864jcrindg.fsf@gnu.org> <291DD5F1-85B8-4647-A40A-EBBD4C51E253@gmail.com> <8634sbijfx.fsf@gnu.org> <2CF47DA5-A65B-47C4-A28A-6FEE1469BD13@gmail.com> <86cyrdfuai.fsf@gnu.org> <3139C8FE-5C67-4FE3-B940-F449DA73E76C@gmail.com> <86le5zdfbi.fsf@gnu.org> <4C93E902-282D-4408-B449-C8E771B2B3E4@gmail.com> MIME-version: 1.0 Content-type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Spam-Score: -2.3 (--) X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -3.3 (---) > From: Mattias EngdegÃ¥rd > Date: Tue, 2 Apr 2024 16:13:58 +0200 > Cc: casouri@gmail.com, > 70007@debbugs.gnu.org > > Looks like the new serialiser inherited a bug from the old code: `json-insert` in a unibyte buffer does not move point correctly. Example: > > (with-temp-buffer > (set-buffer-multibyte nil) > (json-insert "é") > (list (buffer-string) (point))) > => ("\"\303\251\"" 4) > > The string is correct but the position should be 5, not 4. In a build with --enable-checking, this hits an assertion. So I think we should add this to the test suite. > This made me look at the Fjson_insert logic a bit. I'm probably betraying my lack of knowledge about buffer subtleties here, but since the serialiser always produces (correct) UTF-8, shouldn't it be enough to copy the bytes, don't bother with any decoding, and perform the buffer insertion ceremonies? Yes, I think that's true. One nit, though: if the result could be an empty string, then we should not do anything at all, not even invalidate_buffer_caches. From unknown Sun Jun 15 14:44:57 2025 X-Loop: help-debbugs@gnu.org Subject: bug#70007: [PATCH] native JSON encoder Resent-From: Mattias =?UTF-8?Q?Engdeg=C3=A5rd?= Original-Sender: "Debbugs-submit" Resent-CC: bug-gnu-emacs@gnu.org Resent-Date: Tue, 02 Apr 2024 17:20:03 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 70007 X-GNU-PR-Package: emacs X-GNU-PR-Keywords: patch To: Eli Zaretskii Cc: casouri@gmail.com, 70007@debbugs.gnu.org Received: via spool by 70007-submit@debbugs.gnu.org id=B70007.171207836016918 (code B ref 70007); Tue, 02 Apr 2024 17:20:03 +0000 Received: (at 70007) by debbugs.gnu.org; 2 Apr 2024 17:19:20 +0000 Received: from localhost ([127.0.0.1]:56132 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1rrhn5-0004Ob-7e for submit@debbugs.gnu.org; Tue, 02 Apr 2024 13:19:20 -0400 Received: from mail-lf1-x134.google.com ([2a00:1450:4864:20::134]:60882) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1rrhn2-0004Nv-L2 for 70007@debbugs.gnu.org; Tue, 02 Apr 2024 13:19:17 -0400 Received: by mail-lf1-x134.google.com with SMTP id 2adb3069b0e04-516a0b7f864so2360455e87.1 for <70007@debbugs.gnu.org>; Tue, 02 Apr 2024 10:19:12 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1712078347; x=1712683147; darn=debbugs.gnu.org; h=to:references:message-id:content-transfer-encoding:cc:date :in-reply-to:from:subject:mime-version:sender:from:to:cc:subject :date:message-id:reply-to; bh=eip8XF+fdQbsw8sTVeeFplConaC/dOIoJk19myoPvd0=; b=AeeSHmD3nUs7VvbQN+CaDw6MjH9D3I/SavJEwJbdwKh6HwnoSynA8gaycZRcTmeKrv EeeJyG5zROMFP1H1UFHQTyTDLe+MTA8dccZu/nYNCEspSZkn2yE38F1iwwGdWU39kgZL 9zBCCPYeG1GEvlSsxidWTsu8crLiH3EtNtwTckRN4TO8QLVW3aMyqJIWMUjJXFaId+Lr hfTDxs9hLDF+ffDAp22G52QIse/viQ3JANj5OgOK8WX8KfqjXG/kUyogPzqLLvDXDqSK 4Hbcmi0FPyyVJJfOhA5WxPzhMOu3bhw/jPVKkw30DRdQGFlisWS8Y2kDNuxIn+5fOUoF caFg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1712078347; x=1712683147; h=to:references:message-id:content-transfer-encoding:cc:date :in-reply-to:from:subject:mime-version:sender:x-gm-message-state :from:to:cc:subject:date:message-id:reply-to; bh=eip8XF+fdQbsw8sTVeeFplConaC/dOIoJk19myoPvd0=; b=D0q8NYLfjjsrM8yzlt9s/dOZOkVEsIaf5DrTUSGFr+5AOMDKiq2oaXA6iglt9JkevH w28gPECTxgdpBXPBENJVwOf2dhN63F89XPKEL3nUwD888CjjupCF+2Tfk4iR7bkN7pAx qaApx/5K5ImheIdri9hgD7qfN6LA32fhYlUmcUs9OioDhEmyW59WuVZYr+L9Dtt9oTOl xEnC6WS0uWy5pKAOyVMogbAOd4tO4DqUjjpossr1vm4t9etFSVRjbYBsQ4IAqTto66wN sTqOI1H5B525r/RuUfQTYU7Xeiy+ySTvbh42QYQhBbo/DIYoq/FuZJka/2ih3cx2Q7Vw y1bg== X-Forwarded-Encrypted: i=1; AJvYcCU+/7+8Oo9AkPUsGOdBwofMOfKRPhD/FjnSvqMz9eWz25UhY9lZ5ssFYDO0t05R4Fltqm7NG62x9pWuajEqv56wwjL47y4= X-Gm-Message-State: AOJu0YzRAf++mflbMyIjBLqj1ogG33cREYmH3s0r3b7XY0Ew6UMKSEYI jDYS+fUvw+Z5YZOc1pVjbpysRUTwckRIIhq3xdyAcPd2QbPv29qE X-Google-Smtp-Source: AGHT+IH+rj5u2GoseylIExHx7COsgCQDywopljOGXwbQhhryS9AWM9qpymY5+1up9j9TLhrNg+KqqA== X-Received: by 2002:a05:6512:23a1:b0:512:d877:df6f with SMTP id c33-20020a05651223a100b00512d877df6fmr11488394lfv.2.1712078344413; Tue, 02 Apr 2024 10:19:04 -0700 (PDT) Received: from smtpclient.apple (c80-217-1-132.bredband.tele2.se. [80.217.1.132]) by smtp.gmail.com with ESMTPSA id t7-20020a19ad07000000b00516a25e592fsm913815lfc.306.2024.04.02.10.19.03 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Tue, 02 Apr 2024 10:19:03 -0700 (PDT) Content-Type: text/plain; charset=us-ascii Mime-Version: 1.0 (Mac OS X Mail 14.0 \(3654.120.0.1.15\)) From: Mattias =?UTF-8?Q?Engdeg=C3=A5rd?= In-Reply-To: <86cyr7agjo.fsf@gnu.org> Date: Tue, 2 Apr 2024 19:19:03 +0200 Content-Transfer-Encoding: quoted-printable Message-Id: <850DEC32-F318-4F3E-BA87-55FC6DC74CD3@gmail.com> References: <1BF559D1-DB9F-4FEB-90ED-72E0EFD76424@gmail.com> <86wmpphrg7.fsf@gnu.org> <4589243D-C11A-45C1-AF3E-6F4A5BADEB54@gmail.com> <864jcrindg.fsf@gnu.org> <291DD5F1-85B8-4647-A40A-EBBD4C51E253@gmail.com> <8634sbijfx.fsf@gnu.org> <2CF47DA5-A65B-47C4-A28A-6FEE1469BD13@gmail.com> <86cyrdfuai.fsf@gnu.org> <3139C8FE-5C67-4FE3-B940-F449DA73E76C@gmail.com> <86le5zdfbi.fsf@gnu.org> <4C93E902-282D-4408-B449-C8E771B2B3E4@gmail.com> <86cyr7agjo.fsf@gnu.org> X-Mailer: Apple Mail (2.3654.120.0.1.15) X-Spam-Score: 0.0 (/) X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -1.0 (-) 2 apr. 2024 kl. 18.13 skrev Eli Zaretskii : >> This made me look at the Fjson_insert logic a bit. I'm probably = betraying my lack of knowledge about buffer subtleties here, but since = the serialiser always produces (correct) UTF-8, shouldn't it be enough = to copy the bytes, don't bother with any decoding, and perform the = buffer insertion ceremonies? >=20 > Yes, I think that's true. Thank you, now pushed with added tests. > One nit, though: if the result could be an empty string, then we > should not do anything at all, not even invalidate_buffer_caches. I don't think json-insert can ever end up inserting the empty string = (unless it signals, and then we won't get to the insertion stage). But I = added an assertion for this. From unknown Sun Jun 15 14:44:57 2025 X-Loop: help-debbugs@gnu.org Subject: bug#70007: [PATCH] native JSON encoder Resent-From: Mattias =?UTF-8?Q?Engdeg=C3=A5rd?= Original-Sender: "Debbugs-submit" Resent-CC: bug-gnu-emacs@gnu.org Resent-Date: Sat, 24 Aug 2024 15:36:01 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 70007 X-GNU-PR-Package: emacs X-GNU-PR-Keywords: patch To: Eli Zaretskii Cc: Yuan Fu , 70007@debbugs.gnu.org Received: via spool by 70007-submit@debbugs.gnu.org id=B70007.172451373110376 (code B ref 70007); Sat, 24 Aug 2024 15:36:01 +0000 Received: (at 70007) by debbugs.gnu.org; 24 Aug 2024 15:35:31 +0000 Received: from localhost ([127.0.0.1]:41782 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1shsnb-0002hH-Dt for submit@debbugs.gnu.org; Sat, 24 Aug 2024 11:35:31 -0400 Received: from mail-lf1-f47.google.com ([209.85.167.47]:53511) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1shsnZ-0002h3-Ec for 70007@debbugs.gnu.org; Sat, 24 Aug 2024 11:35:30 -0400 Received: by mail-lf1-f47.google.com with SMTP id 2adb3069b0e04-533462b9428so5068107e87.3 for <70007@debbugs.gnu.org>; Sat, 24 Aug 2024 08:34:40 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1724513615; x=1725118415; darn=debbugs.gnu.org; h=to:references:message-id:content-transfer-encoding:cc:date :in-reply-to:from:subject:mime-version:sender:from:to:cc:subject :date:message-id:reply-to; bh=TVAojt3IqxFHr/xb6906PD+MZKrdOBiERsNLqMiRDNo=; b=URFODMPK10DsBW2hJE9du/pPqEnmcZLvMnqMxW7eVjrZnkDAxJkLGC2YbtwIRQ69Kl qTWmffdwfINO0DNxFjGIWdm6n+Qvs2GcX2Zt4MErBH2GiUHNYV8JpPh6xK8YuTR4UmSp 0ghjiWBZW6K10wFmAKn7702J6BvT8Jza2VfA75gUo/WZv1xA0yqK3xKxh3pXWCkonHd6 plvNFY1isRVsz+PJ8SxiGcB/ocjF9OFt9IPSQ/TBkkVMPj5B6nmeuXeF++Po9rshdynn Q3zH10/UUWrY+lKWr6hhmmozLlmt/emp9Qxiswxj2V74YV2KsmXW4UDJJyhLQXfdKJ6a Mf8g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1724513615; x=1725118415; h=to:references:message-id:content-transfer-encoding:cc:date :in-reply-to:from:subject:mime-version:sender:x-gm-message-state :from:to:cc:subject:date:message-id:reply-to; bh=TVAojt3IqxFHr/xb6906PD+MZKrdOBiERsNLqMiRDNo=; b=RbzYqTrmumdLp5Vjr9z+YweguvSJEB9o/Pcrob+u7B/z8xHOU8wJkoV3GdCdLlRiQF KvRkljjg5lmvKG5mpQcZRLKI3XRKBx1+hrrQSYT8oli3awx47VDG0UjfRJX6fMyeWsHP OyEp93qRRKtLEuIfw3IibT+astevyUhQg87wK+H0gavu9GW5nxZRRw2FpBg892iU7XF+ QqifJ/cZLLy/n1KppBvRg/EtZHb+3sCvjVgrhO+60iI3/L53x1qoSs1ISlZq7rY8dqoh CaUjumQKAnXLr2hPOch1K1oTSWEzZXsqaYc4f1LJFG3PM8rAsPZc9MTBPS3B4et5zhEL gl2A== X-Forwarded-Encrypted: i=1; AJvYcCX6ejvbG8wCaJHwNQR40cLrdReoBAY9up+ZmZQNGfVg9kgP2lvTugdWdf0dgWlXUXaydM+3bA==@debbugs.gnu.org X-Gm-Message-State: AOJu0YyO73ETTshFvpE6efrsMfVEHhDoUUv9iCvNiyXA4q9rK0ZvWr7y Z7jBy/H3Q3WKzAUo32HN9PBDn7WpBFYyKxLqlzrGp8URxF4OfJ0/ X-Google-Smtp-Source: AGHT+IEqYaJDdBI46UJnK4s60PNBxK353qDxw1PnMCIpxlUcAykEp5WTVYGSfmPY0bLDcV1ylq6uBQ== X-Received: by 2002:a05:6512:3a88:b0:529:b718:8d00 with SMTP id 2adb3069b0e04-5343883d653mr4947045e87.8.1724513614276; Sat, 24 Aug 2024 08:33:34 -0700 (PDT) Received: from smtpclient.apple (c188-150-191-82.bredband.tele2.se. [188.150.191.82]) by smtp.gmail.com with ESMTPSA id 2adb3069b0e04-5334ea5d8fcsm881406e87.227.2024.08.24.08.33.33 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Sat, 24 Aug 2024 08:33:33 -0700 (PDT) Content-Type: text/plain; charset=us-ascii Mime-Version: 1.0 (Mac OS X Mail 14.0 \(3654.120.0.1.15\)) From: Mattias =?UTF-8?Q?Engdeg=C3=A5rd?= In-Reply-To: <850DEC32-F318-4F3E-BA87-55FC6DC74CD3@gmail.com> Date: Sat, 24 Aug 2024 17:33:33 +0200 Content-Transfer-Encoding: quoted-printable Message-Id: References: <1BF559D1-DB9F-4FEB-90ED-72E0EFD76424@gmail.com> <86wmpphrg7.fsf@gnu.org> <4589243D-C11A-45C1-AF3E-6F4A5BADEB54@gmail.com> <864jcrindg.fsf@gnu.org> <291DD5F1-85B8-4647-A40A-EBBD4C51E253@gmail.com> <8634sbijfx.fsf@gnu.org> <2CF47DA5-A65B-47C4-A28A-6FEE1469BD13@gmail.com> <86cyrdfuai.fsf@gnu.org> <3139C8FE-5C67-4FE3-B940-F449DA73E76C@gmail.com> <86le5zdfbi.fsf@gnu.org> <4C93E902-282D-4408-B449-C8E771B2B3E4@gmail.com> <86cyr7agjo.fsf@gnu.org> <850DEC32-F318-4F3E-BA87-55FC6DC74CD3@gmail.com> X-Mailer: Apple Mail (2.3654.120.0.1.15) X-Spam-Score: 0.0 (/) X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -1.0 (-) (I'm going through some old unfinished work.) The only major issue remaining here would be whether `json-serialize` = should return a multibyte string, as it does now, or a unibyte string. I = think we agree that unibyte is the correct choice in general, and since = the code is new in Emacs 30 we should make a decision now because = changing it in Emacs 31 will be riskier. On the other hand, the old = libjansson implementation returned a multibyte string. I've looked at packages using the API and they appear entirely agnostic = -- the result is almost always a string that is fed into = `process-send-string`. From unknown Sun Jun 15 14:44:57 2025 X-Loop: help-debbugs@gnu.org Subject: bug#70007: [PATCH] native JSON encoder Resent-From: Eli Zaretskii Original-Sender: "Debbugs-submit" Resent-CC: bug-gnu-emacs@gnu.org Resent-Date: Sat, 24 Aug 2024 16:16:01 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 70007 X-GNU-PR-Package: emacs X-GNU-PR-Keywords: patch To: Mattias =?UTF-8?Q?Engdeg=C3=A5rd?= Cc: casouri@gmail.com, 70007@debbugs.gnu.org Received: via spool by 70007-submit@debbugs.gnu.org id=B70007.172451612314600 (code B ref 70007); Sat, 24 Aug 2024 16:16:01 +0000 Received: (at 70007) by debbugs.gnu.org; 24 Aug 2024 16:15:23 +0000 Received: from localhost ([127.0.0.1]:41812 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1shtQA-0003nQ-Vq for submit@debbugs.gnu.org; Sat, 24 Aug 2024 12:15:23 -0400 Received: from eggs.gnu.org ([209.51.188.92]:43046) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1shtQ8-0003nB-0T for 70007@debbugs.gnu.org; Sat, 24 Aug 2024 12:15:21 -0400 Received: from fencepost.gnu.org ([2001:470:142:3::e]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1shtPF-0006bi-FG; Sat, 24 Aug 2024 12:14:25 -0400 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=gnu.org; s=fencepost-gnu-org; h=MIME-version:References:Subject:In-Reply-To:To:From: Date; bh=kFlubvQjK7eyfmcu++q27xKjsE1cHHTRdnclv++HgTQ=; b=MUjUtZjM3mg95MWDZ/GT mH4Gh2qRE1bYaG/Px6ZIrMdNzWF50bo/4FIxn+ck9EtecEO8OHAN6gXBPl8evI7Rz+ji1pPI23ZVe /tAn2vOTIcxSDXvGK/LKEuqQw1yE50RZtwQb1LTz+pgwE7DYpgWXPMF9x9pYlbtJB8Or8l1C/ZenE GZCSa4PEVRAj4RSc98PLEyOPkHWz+0jBshK0493UsK52QekVZviab/pHGoMvbJVtnb5QIkySAmyII FtJl6N9g+HtLAZktJTNeFltwA8mSJVKSVl5D/1mFKLnM9y75cCGaF4VnNEKghovfl2zDHlmvFrGQ4 arsKzVebZnjX5Q==; Date: Sat, 24 Aug 2024 19:14:22 +0300 Message-Id: <86ikvpnbj5.fsf@gnu.org> From: Eli Zaretskii In-Reply-To: (message from Mattias =?UTF-8?Q?Engdeg=C3=A5rd?= on Sat, 24 Aug 2024 17:33:33 +0200) References: <1BF559D1-DB9F-4FEB-90ED-72E0EFD76424@gmail.com> <86wmpphrg7.fsf@gnu.org> <4589243D-C11A-45C1-AF3E-6F4A5BADEB54@gmail.com> <864jcrindg.fsf@gnu.org> <291DD5F1-85B8-4647-A40A-EBBD4C51E253@gmail.com> <8634sbijfx.fsf@gnu.org> <2CF47DA5-A65B-47C4-A28A-6FEE1469BD13@gmail.com> <86cyrdfuai.fsf@gnu.org> <3139C8FE-5C67-4FE3-B940-F449DA73E76C@gmail.com> <86le5zdfbi.fsf@gnu.org> <4C93E902-282D-4408-B449-C8E771B2B3E4@gmail.com> <86cyr7agjo.fsf@gnu.org> <850DEC32-F318-4F3E-BA87-55FC6DC74CD3@gmail.com> MIME-version: 1.0 Content-type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Spam-Score: -2.3 (--) X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -3.3 (---) > From: Mattias EngdegÃ¥rd > Date: Sat, 24 Aug 2024 17:33:33 +0200 > Cc: Yuan Fu , > 70007@debbugs.gnu.org > > (I'm going through some old unfinished work.) > > The only major issue remaining here would be whether `json-serialize` should return a multibyte string, as it does now, or a unibyte string. I think we agree that unibyte is the correct choice in general, and since the code is new in Emacs 30 we should make a decision now because changing it in Emacs 31 will be riskier. On the other hand, the old libjansson implementation returned a multibyte string. > > I've looked at packages using the API and they appear entirely agnostic -- the result is almost always a string that is fed into `process-send-string`. We are very late in the release process to make such changes without reservations. We should have discussed this much earlier, but that's water under the bridge. Since this could potentially (albeit unlikely) break someone's code, I'm okay with making this change, but with a twist: let's have a variable which could be let-bound around the call to json-serialize, to make the result a multibyte string instead of the default unibyte. This is so if someone comes back crying that we broke his/her code, they could have an easy fire escape. OK? P.S. Of course, the fact that the result is a unibyte string should be mentioned in the doc string. From unknown Sun Jun 15 14:44:57 2025 X-Loop: help-debbugs@gnu.org Subject: bug#70007: [PATCH] native JSON encoder Resent-From: Mattias =?UTF-8?Q?Engdeg=C3=A5rd?= Original-Sender: "Debbugs-submit" Resent-CC: bug-gnu-emacs@gnu.org Resent-Date: Sat, 24 Aug 2024 19:48:02 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 70007 X-GNU-PR-Package: emacs X-GNU-PR-Keywords: patch To: Eli Zaretskii Cc: casouri@gmail.com, 70007@debbugs.gnu.org Received: via spool by 70007-submit@debbugs.gnu.org id=B70007.17245288774222 (code B ref 70007); Sat, 24 Aug 2024 19:48:02 +0000 Received: (at 70007) by debbugs.gnu.org; 24 Aug 2024 19:47:57 +0000 Received: from localhost ([127.0.0.1]:41935 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1shwjs-000162-R4 for submit@debbugs.gnu.org; Sat, 24 Aug 2024 15:47:57 -0400 Received: from mail-lf1-f49.google.com ([209.85.167.49]:48414) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1shwjq-00015i-SH for 70007@debbugs.gnu.org; Sat, 24 Aug 2024 15:47:55 -0400 Received: by mail-lf1-f49.google.com with SMTP id 2adb3069b0e04-533488ffaddso3970188e87.1 for <70007@debbugs.gnu.org>; Sat, 24 Aug 2024 12:47:05 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1724528760; x=1725133560; darn=debbugs.gnu.org; h=to:references:message-id:content-transfer-encoding:cc:date :in-reply-to:from:subject:mime-version:sender:from:to:cc:subject :date:message-id:reply-to; bh=MPSJeUpOlIN0a9DhA19usChVKVZLdIc2esos5+jCKdw=; b=A8lwKNRKp5eHGEYYuSF9KkeQQFN9xmKUWlj44M9+6WLgnJCjib5vrF70wNmUwPFr1R 53J1MRuObf6tvuOzLJytpkvvDbCl++F5P0mxc5ePnAQOrEDCXA00XDszTXyZBHrJo/zA qpYCSi84rjW6DVQfzYF/hMcmWCu1oFXn4IPz5fRGQkERI0xprnCva8Hin0qOddOpxDAj rzbBokxZqc2ndRufGT1gGCwuf2XRtJAie/zCeVr2zgCeHcvkk1XWRYTgqjPnu7WlzVDP qX76wp7Q35I9jQhccfxqLJ7q8vq8b1c8anhSrAtL/GLgT+r1+g1/fokxHS1hEfL1y5lm GCTA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1724528760; x=1725133560; h=to:references:message-id:content-transfer-encoding:cc:date :in-reply-to:from:subject:mime-version:sender:x-gm-message-state :from:to:cc:subject:date:message-id:reply-to; bh=MPSJeUpOlIN0a9DhA19usChVKVZLdIc2esos5+jCKdw=; b=n5jdbq1AmGTep+G8vbHTOhXrvRkNmUxgg0q0h1+HJJw6TFTIzJKtdjNSr8LZrDMXOz GXZuuQZrmu6FDEyGiVPiaf/UDcrYhIsAS557ylElvlYQnupRNIwGi3MjIxCmBk/zJxLy 0AgO+GlFf1GH91+0jmbv3Wa0WrK9187OuEsfju9Gp43oIClYASPBM/gc4sjrWYg81qwc YddqMmGSkCxZwJ16pOoqjEgrozJTkSAw4NJaoraqwmOmYimLkpqSPanuhRAkOmiMFcic 3nnCspZoWpSdDw0ErzQYQB5ED0S6BTk8XmSAvAGH8DFt8uEJfrc2/IvDEntFDaajzKC6 2X7g== X-Forwarded-Encrypted: i=1; AJvYcCViMx43NE9QF0cSWZiv07oiDufhjaPnDG73RcEhvA7JpAunMzZXCSocRkvtXdWpTmhfDfH31g==@debbugs.gnu.org X-Gm-Message-State: AOJu0YxNHjpbH1+XHEsbUPoXXM84aO8vlMKCut+Pw3zwKnCT5ZZzqNfN wISpnhWatt5oCsJpztM3VGR2GywL19wEG5pAzpwq1kN0HSJ5adao X-Google-Smtp-Source: AGHT+IEgn0BeDoJC4oWGGksSv7yFkgf5exwdPOirXSOaVZFS3uMcc3OprmZQGq5Bp9kkvVXmuxOz7A== X-Received: by 2002:a05:6512:2342:b0:52e:9b68:d2da with SMTP id 2adb3069b0e04-5343875fe4cmr4023424e87.9.1724528759335; Sat, 24 Aug 2024 12:45:59 -0700 (PDT) Received: from smtpclient.apple (c188-150-191-82.bredband.tele2.se. [188.150.191.82]) by smtp.gmail.com with ESMTPSA id 2adb3069b0e04-5334ea29321sm934168e87.25.2024.08.24.12.45.58 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Sat, 24 Aug 2024 12:45:59 -0700 (PDT) Content-Type: text/plain; charset=us-ascii Mime-Version: 1.0 (Mac OS X Mail 14.0 \(3654.120.0.1.15\)) From: Mattias =?UTF-8?Q?Engdeg=C3=A5rd?= In-Reply-To: <86ikvpnbj5.fsf@gnu.org> Date: Sat, 24 Aug 2024 21:45:57 +0200 Content-Transfer-Encoding: quoted-printable Message-Id: References: <1BF559D1-DB9F-4FEB-90ED-72E0EFD76424@gmail.com> <86wmpphrg7.fsf@gnu.org> <4589243D-C11A-45C1-AF3E-6F4A5BADEB54@gmail.com> <864jcrindg.fsf@gnu.org> <291DD5F1-85B8-4647-A40A-EBBD4C51E253@gmail.com> <8634sbijfx.fsf@gnu.org> <2CF47DA5-A65B-47C4-A28A-6FEE1469BD13@gmail.com> <86cyrdfuai.fsf@gnu.org> <3139C8FE-5C67-4FE3-B940-F449DA73E76C@gmail.com> <86le5zdfbi.fsf@gnu.org> <4C93E902-282D-4408-B449-C8E771B2B3E4@gmail.com> <86cyr7agjo.fsf@gnu.org> <850DEC32-F318-4F3E-BA87-55FC6DC74CD3@gmail.com> <86ikvpnbj5.fsf@gnu.org> X-Mailer: Apple Mail (2.3654.120.0.1.15) X-Spam-Score: 0.0 (/) X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -1.0 (-) 24 aug. 2024 kl. 18.14 skrev Eli Zaretskii : > We are very late in the release process to make such changes without > reservations. We should have discussed this much earlier, but that's > water under the bridge. Yes, sorry about not following this through in time. But here we are. > Since this could potentially (albeit unlikely) break someone's code, > I'm okay with making this change, but with a twist: let's have a > variable which could be let-bound around the call to json-serialize, > to make the result a multibyte string instead of the default unibyte. > This is so if someone comes back crying that we broke his/her code, > they could have an easy fire escape. Sure, but it's a bit annoying to saddle us with some baggage that we = never expect to be actually used. And for that matter, it's no easier to bind a variable around the call = than putting a call to `decode-coding-string` around it, is it? We could = describe that in NEWS. The null option is to do nothing and stick to what we have now. It's not = a terrible choice either. > P.S. Of course, the fact that the result is a unibyte string should be > mentioned in the doc string. Yes, definitely. From unknown Sun Jun 15 14:44:57 2025 X-Loop: help-debbugs@gnu.org Subject: bug#70007: [PATCH] native JSON encoder Resent-From: Eli Zaretskii Original-Sender: "Debbugs-submit" Resent-CC: bug-gnu-emacs@gnu.org Resent-Date: Sun, 25 Aug 2024 05:09:02 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 70007 X-GNU-PR-Package: emacs X-GNU-PR-Keywords: patch To: Mattias =?UTF-8?Q?Engdeg=C3=A5rd?= , Stefan Monnier , Stefan Kangas , Andrea Corallo Cc: casouri@gmail.com, 70007@debbugs.gnu.org Received: via spool by 70007-submit@debbugs.gnu.org id=B70007.172456252831940 (code B ref 70007); Sun, 25 Aug 2024 05:09:02 +0000 Received: (at 70007) by debbugs.gnu.org; 25 Aug 2024 05:08:48 +0000 Received: from localhost ([127.0.0.1]:42078 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1si5Ue-0008J5-0p for submit@debbugs.gnu.org; Sun, 25 Aug 2024 01:08:48 -0400 Received: from eggs.gnu.org ([209.51.188.92]:44858) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1si5Uc-0008Iq-3m for 70007@debbugs.gnu.org; Sun, 25 Aug 2024 01:08:46 -0400 Received: from fencepost.gnu.org ([2001:470:142:3::e]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1si5Tj-0000BD-3W; Sun, 25 Aug 2024 01:07:51 -0400 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=gnu.org; s=fencepost-gnu-org; h=MIME-version:References:Subject:In-Reply-To:To:From: Date; bh=sB6aVg/H/2j6VsDY1xjHN/Is73uu8qNDT2RUPGvDWeI=; b=jHe7av9MGjn9W6C/Ff5D Y9R28m+YDEe4D7r5oR8GlZkAKzY2y4ZyLkECXPAVXlDZXmB7tXL2WSzEvI0Xq9s/vhO8XCfHnwR5z vToRVj6sPqDWH1c6XY6L9+cLRHPW0Uxk0XFd6XeF0F7mtFDgsM+eSaPTv9jB8LVa7fkDFeZf53vtw 2I5b8EhuTgG39GwDZrAXK43+gqaPmqwYldjNDeRk9aLPicHOmvAS/Qsn/iT0Rwji8CpPlKKU8vyyO xsYWdkzmcPyXg/CE5w/u+egkFqRel1M3M5gpGcou+TLdtOA8WOyhEY532+itpry/7ZwaNakh4n1Xc RtdXhlhuyP8HBg==; Date: Sun, 25 Aug 2024 08:07:48 +0300 Message-Id: <867cc5mbq3.fsf@gnu.org> From: Eli Zaretskii In-Reply-To: (message from Mattias =?UTF-8?Q?Engdeg=C3=A5rd?= on Sat, 24 Aug 2024 21:45:57 +0200) References: <1BF559D1-DB9F-4FEB-90ED-72E0EFD76424@gmail.com> <86wmpphrg7.fsf@gnu.org> <4589243D-C11A-45C1-AF3E-6F4A5BADEB54@gmail.com> <864jcrindg.fsf@gnu.org> <291DD5F1-85B8-4647-A40A-EBBD4C51E253@gmail.com> <8634sbijfx.fsf@gnu.org> <2CF47DA5-A65B-47C4-A28A-6FEE1469BD13@gmail.com> <86cyrdfuai.fsf@gnu.org> <3139C8FE-5C67-4FE3-B940-F449DA73E76C@gmail.com> <86le5zdfbi.fsf@gnu.org> <4C93E902-282D-4408-B449-C8E771B2B3E4@gmail.com> <86cyr7agjo.fsf@gnu.org> <850DEC32-F318-4F3E-BA87-55FC6DC74CD3@gmail.com> <86ikvpnbj5.fsf@gnu.org> MIME-version: 1.0 Content-type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Spam-Score: -2.3 (--) X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -3.3 (---) > From: Mattias EngdegÃ¥rd > Date: Sat, 24 Aug 2024 21:45:57 +0200 > Cc: casouri@gmail.com, > 70007@debbugs.gnu.org > > 24 aug. 2024 kl. 18.14 skrev Eli Zaretskii : > > > We are very late in the release process to make such changes without > > reservations. We should have discussed this much earlier, but that's > > water under the bridge. > > Yes, sorry about not following this through in time. But here we are. > > > Since this could potentially (albeit unlikely) break someone's code, > > I'm okay with making this change, but with a twist: let's have a > > variable which could be let-bound around the call to json-serialize, > > to make the result a multibyte string instead of the default unibyte. > > This is so if someone comes back crying that we broke his/her code, > > they could have an easy fire escape. > > Sure, but it's a bit annoying to saddle us with some baggage that we never expect to be actually used. > And for that matter, it's no easier to bind a variable around the call than putting a call to `decode-coding-string` around it, is it? We could describe that in NEWS. > > The null option is to do nothing and stick to what we have now. It's not a terrible choice either. Let's see what others think about this. Stefan, Stefan, and Andrea: any opinions wrt what, if anything, we should do about this on the emacs-30 branch? From unknown Sun Jun 15 14:44:57 2025 X-Loop: help-debbugs@gnu.org Subject: bug#70007: [PATCH] native JSON encoder Resent-From: Stefan Monnier Original-Sender: "Debbugs-submit" Resent-CC: bug-gnu-emacs@gnu.org Resent-Date: Sun, 25 Aug 2024 17:58:02 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 70007 X-GNU-PR-Package: emacs X-GNU-PR-Keywords: patch To: Eli Zaretskii Cc: Mattias =?UTF-8?Q?Engdeg=C3=A5rd?= , Andrea Corallo , casouri@gmail.com, Stefan Kangas , 70007@debbugs.gnu.org Received: via spool by 70007-submit@debbugs.gnu.org id=B70007.172460862520853 (code B ref 70007); Sun, 25 Aug 2024 17:58:02 +0000 Received: (at 70007) by debbugs.gnu.org; 25 Aug 2024 17:57:05 +0000 Received: from localhost ([127.0.0.1]:43263 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1siHU8-0005QG-Lz for submit@debbugs.gnu.org; Sun, 25 Aug 2024 13:57:04 -0400 Received: from mailscanner.iro.umontreal.ca ([132.204.25.50]:61851) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1siHU7-0005Po-C4 for 70007@debbugs.gnu.org; Sun, 25 Aug 2024 13:57:03 -0400 Received: from pmg2.iro.umontreal.ca (localhost.localdomain [127.0.0.1]) by pmg2.iro.umontreal.ca (Proxmox) with ESMTP id 4CA9B80A1B; Sun, 25 Aug 2024 13:56:06 -0400 (EDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=iro.umontreal.ca; s=mail; t=1724608564; bh=com2T9oSJekBipea9Q1g7FPzS+V1v859hBv4CRUliDE=; h=From:To:Cc:Subject:In-Reply-To:References:Date:From; b=DdQ3oays1+w3KcbFsz+vo7bLWk4ahLU4rLAXQ8IcXVQoYz5wa1FVOzhlzaHO5Yqg5 Zq8OlSoGtjDcN45Vx+LJ3Z9Mq3I2hpybUKWb0ARvKcybj1WrEkIeAMK6wjqi7s+6rM i+9C97y4SIzHT6+jriSoRiBDjdna1J6FkTOF5/HjW7M+qLKAro/LydMHX7ZaqhgJWP Oid2Q2fANclfPe37DWDb0SqagBNFCYqjQmceFRCPpWq6B3pdivpFbZRzqriRKpHsjf nSVbW2aGHE+Bdc2R4pR6xKrS0oKPfbxnqAR/Zk2b9qhnr0CMWIDaRJcZdxT4CXFoTw /oTjdBRUw+q/g== Received: from mail01.iro.umontreal.ca (unknown [172.31.2.1]) by pmg2.iro.umontreal.ca (Proxmox) with ESMTP id B77848060A; Sun, 25 Aug 2024 13:56:04 -0400 (EDT) Received: from pastel (unknown [216.154.9.87]) by mail01.iro.umontreal.ca (Postfix) with ESMTPSA id 7886C1206D6; Sun, 25 Aug 2024 13:56:04 -0400 (EDT) From: Stefan Monnier In-Reply-To: <867cc5mbq3.fsf@gnu.org> (Eli Zaretskii's message of "Sun, 25 Aug 2024 08:07:48 +0300") Message-ID: References: <1BF559D1-DB9F-4FEB-90ED-72E0EFD76424@gmail.com> <86wmpphrg7.fsf@gnu.org> <4589243D-C11A-45C1-AF3E-6F4A5BADEB54@gmail.com> <864jcrindg.fsf@gnu.org> <291DD5F1-85B8-4647-A40A-EBBD4C51E253@gmail.com> <8634sbijfx.fsf@gnu.org> <2CF47DA5-A65B-47C4-A28A-6FEE1469BD13@gmail.com> <86cyrdfuai.fsf@gnu.org> <3139C8FE-5C67-4FE3-B940-F449DA73E76C@gmail.com> <86le5zdfbi.fsf@gnu.org> <4C93E902-282D-4408-B449-C8E771B2B3E4@gmail.com> <86cyr7agjo.fsf@gnu.org> <850DEC32-F318-4F3E-BA87-55FC6DC74CD3@gmail.com> <86ikvpnbj5.fsf@gnu.org> <867cc5mbq3.fsf@gnu.org> Date: Sun, 25 Aug 2024 13:55:53 -0400 User-Agent: Gnus/5.13 (Gnus v5.13) MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable X-SPAM-INFO: Spam detection results: 0 ALL_TRUSTED -1 Passed through trusted hosts only via SMTP AWL 0.009 Adjusted score from AWL reputation of From: address BAYES_00 -1.9 Bayes spam probability is 0 to 1% DKIM_SIGNED 0.1 Message has a DKIM or DK signature, not necessarily valid DKIM_VALID -0.1 Message has at least one valid DKIM or DK signature DKIM_VALID_AU -0.1 Message has a valid DKIM or DK signature from author's domain DKIM_VALID_EF -0.1 Message has a valid DKIM or DK signature from envelope-from domain T_SCC_BODY_TEXT_LINE -0.01 - X-SPAM-LEVEL: X-Spam-Score: -2.3 (--) X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -3.3 (---) >> > Since this could potentially (albeit unlikely) break someone's code, >> > I'm okay with making this change, but with a twist: let's have a >> > variable which could be let-bound around the call to json-serialize, >> > to make the result a multibyte string instead of the default unibyte. >> > This is so if someone comes back crying that we broke his/her code, >> > they could have an easy fire escape. >> Sure, but it's a bit annoying to saddle us with some baggage that we nev= er >> expect to be actually used. >> And for that matter, it's no easier to bind a variable around the call >> than putting a call to `decode-coding-string` around it, is it? We could >> describe that in NEWS. The variable solution has one advantage: users can (setq ... t) in their `.emacs` to keep old code working, tho potentially at the cost of breaking new code. Another option is to introduce a new name (that outputs a unicode string) and obsolete the old one. =F0=9F=99=82 But just making a breaking change is not that bad: ELisp has evolved to be pretty good at making code magically work for both encoded and decoded strings. >> The null option is to do nothing and stick to what we have now. >> It's not a terrible choice either. Returning an encoded strings is something we do want to avoid in the long run, so we might as well bite the bullet now. > Let's see what others think about this. Stefan, Stefan, and Andrea: > any opinions wrt what, if anything, we should do about this on the > emacs-30 branch? I vote for breaking compatibility. Stefan From unknown Sun Jun 15 14:44:57 2025 X-Loop: help-debbugs@gnu.org Subject: bug#70007: [PATCH] native JSON encoder Resent-From: Eli Zaretskii Original-Sender: "Debbugs-submit" Resent-CC: bug-gnu-emacs@gnu.org Resent-Date: Sun, 25 Aug 2024 18:30:02 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 70007 X-GNU-PR-Package: emacs X-GNU-PR-Keywords: patch To: Stefan Monnier Cc: mattias.engdegard@gmail.com, acorallo@gnu.org, casouri@gmail.com, stefankangas@gmail.com, 70007@debbugs.gnu.org Received: via spool by 70007-submit@debbugs.gnu.org id=B70007.172461056224276 (code B ref 70007); Sun, 25 Aug 2024 18:30:02 +0000 Received: (at 70007) by debbugs.gnu.org; 25 Aug 2024 18:29:22 +0000 Received: from localhost ([127.0.0.1]:43273 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1siHzO-0006JU-03 for submit@debbugs.gnu.org; Sun, 25 Aug 2024 14:29:22 -0400 Received: from eggs.gnu.org ([209.51.188.92]:43120) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1siHzL-0006JE-HB for 70007@debbugs.gnu.org; Sun, 25 Aug 2024 14:29:20 -0400 Received: from fencepost.gnu.org ([2001:470:142:3::e]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1siHwL-00052b-V3; Sun, 25 Aug 2024 14:26:13 -0400 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=gnu.org; s=fencepost-gnu-org; h=MIME-version:References:Subject:In-Reply-To:To:From: Date; bh=+c5DTaI/8fIyPIHTc1gVqCOICYtTuS7LAVDBn3BHIcc=; b=Htxkaw4u61xSAxaWzWFn vxRoRF0hWrSZaLL+dPZaZ/Fvh16qYsNJz/b6xdSh3WhH/75ZR3mwrj57tLWpQ3S5Kqdb0RVtutYgG j7I1Lew+GaLWBANjSda7/Zrc3Cf6/2tap5dnCsKZNdPc+FUOoxF39KRGolIK+Ces8QN0UmJD3ju3/ tDcZd6tmI3HJyyNNdzc4XNDVvRDOAQ8gBOLYruWHkG/YFOaULrVM2otYOj4ajSSzNpuQAQ7zT8a3o 2+t/arrGB6Vq/txQjZWZZ6aZswzp1sa/1JcsPHLZSrjA26OD6ZyK2qCgFH/p4kg0um+jYKyzx5Cza XeybPGM1zPH8fw==; Date: Sun, 25 Aug 2024 21:26:11 +0300 Message-Id: <86y14kjw70.fsf@gnu.org> From: Eli Zaretskii In-Reply-To: (message from Stefan Monnier on Sun, 25 Aug 2024 13:55:53 -0400) References: <1BF559D1-DB9F-4FEB-90ED-72E0EFD76424@gmail.com> <86wmpphrg7.fsf@gnu.org> <4589243D-C11A-45C1-AF3E-6F4A5BADEB54@gmail.com> <864jcrindg.fsf@gnu.org> <291DD5F1-85B8-4647-A40A-EBBD4C51E253@gmail.com> <8634sbijfx.fsf@gnu.org> <2CF47DA5-A65B-47C4-A28A-6FEE1469BD13@gmail.com> <86cyrdfuai.fsf@gnu.org> <3139C8FE-5C67-4FE3-B940-F449DA73E76C@gmail.com> <86le5zdfbi.fsf@gnu.org> <4C93E902-282D-4408-B449-C8E771B2B3E4@gmail.com> <86cyr7agjo.fsf@gnu.org> <850DEC32-F318-4F3E-BA87-55FC6DC74CD3@gmail.com> <86ikvpnbj5.fsf@gnu.org> <867cc5mbq3.fsf@gnu.org> MIME-version: 1.0 Content-type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Spam-Score: -2.3 (--) X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -3.3 (---) > From: Stefan Monnier > Cc: Mattias EngdegÃ¥rd , > Stefan Kangas > , Andrea Corallo , > casouri@gmail.com, 70007@debbugs.gnu.org > Date: Sun, 25 Aug 2024 13:55:53 -0400 > > > Let's see what others think about this. Stefan, Stefan, and Andrea: > > any opinions wrt what, if anything, we should do about this on the > > emacs-30 branch? > > I vote for breaking compatibility. And against the additional variable to make this more backward-compatible? From unknown Sun Jun 15 14:44:57 2025 X-Loop: help-debbugs@gnu.org Subject: bug#70007: [PATCH] native JSON encoder Resent-From: Stefan Monnier Original-Sender: "Debbugs-submit" Resent-CC: bug-gnu-emacs@gnu.org Resent-Date: Sun, 25 Aug 2024 19:22:01 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 70007 X-GNU-PR-Package: emacs X-GNU-PR-Keywords: patch To: Eli Zaretskii Cc: mattias.engdegard@gmail.com, acorallo@gnu.org, casouri@gmail.com, stefankangas@gmail.com, 70007@debbugs.gnu.org Received: via spool by 70007-submit@debbugs.gnu.org id=B70007.172461368030202 (code B ref 70007); Sun, 25 Aug 2024 19:22:01 +0000 Received: (at 70007) by debbugs.gnu.org; 25 Aug 2024 19:21:20 +0000 Received: from localhost ([127.0.0.1]:43316 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1siIng-0007r3-9A for submit@debbugs.gnu.org; Sun, 25 Aug 2024 15:21:20 -0400 Received: from mailscanner.iro.umontreal.ca ([132.204.25.50]:6339) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1siInd-0007qo-TO for 70007@debbugs.gnu.org; Sun, 25 Aug 2024 15:21:18 -0400 Received: from pmg2.iro.umontreal.ca (localhost.localdomain [127.0.0.1]) by pmg2.iro.umontreal.ca (Proxmox) with ESMTP id D3B438025B; Sun, 25 Aug 2024 15:20:21 -0400 (EDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=iro.umontreal.ca; s=mail; t=1724613620; bh=o2nMsfD2P2yKbtuNGCUIL2FKdki0Q4OrUyNJ41JreJE=; h=From:To:Cc:Subject:In-Reply-To:References:Date:From; b=QzYwb7zGSF6MkAI8gf37rHefRv4qI4el5vEq/3NwA5gCFc0jI+nHvooOtR4y1xHvF MgnLWS3mogtncLBbi6vyltw+V1qkD04T7FzMYrJUkq8C3xGbkN6UmtC81/YqaqnHuo ma412wqwhk4dZSHkJ2jDCjlCzxEyp72ocYT2jhFpDMITCXE2SoWtY9rtq+k6HTMUTG OQZrXyV8HZ930xBe/n4LHBLiWj0PB+XBJv6R7a88TSb9benBAHndguOnN4luhFDd5L gMJYsJjK5UfoSIi0+8OnXPFsD/lkMz6G54crC2nY0v7zEgFi5DC+fmDVPPN7YwRP8i ikt5enDLV/IyQ== Received: from mail01.iro.umontreal.ca (unknown [172.31.2.1]) by pmg2.iro.umontreal.ca (Proxmox) with ESMTP id 7EACC8076B; Sun, 25 Aug 2024 15:20:20 -0400 (EDT) Received: from pastel (unknown [216.154.9.87]) by mail01.iro.umontreal.ca (Postfix) with ESMTPSA id 2B1541201E7; Sun, 25 Aug 2024 15:20:20 -0400 (EDT) From: Stefan Monnier In-Reply-To: <86y14kjw70.fsf@gnu.org> (Eli Zaretskii's message of "Sun, 25 Aug 2024 21:26:11 +0300") Message-ID: References: <1BF559D1-DB9F-4FEB-90ED-72E0EFD76424@gmail.com> <86wmpphrg7.fsf@gnu.org> <4589243D-C11A-45C1-AF3E-6F4A5BADEB54@gmail.com> <864jcrindg.fsf@gnu.org> <291DD5F1-85B8-4647-A40A-EBBD4C51E253@gmail.com> <8634sbijfx.fsf@gnu.org> <2CF47DA5-A65B-47C4-A28A-6FEE1469BD13@gmail.com> <86cyrdfuai.fsf@gnu.org> <3139C8FE-5C67-4FE3-B940-F449DA73E76C@gmail.com> <86le5zdfbi.fsf@gnu.org> <4C93E902-282D-4408-B449-C8E771B2B3E4@gmail.com> <86cyr7agjo.fsf@gnu.org> <850DEC32-F318-4F3E-BA87-55FC6DC74CD3@gmail.com> <86ikvpnbj5.fsf@gnu.org> <867cc5mbq3.fsf@gnu.org> <86y14kjw70.fsf@gnu.org> Date: Sun, 25 Aug 2024 15:20:18 -0400 User-Agent: Gnus/5.13 (Gnus v5.13) MIME-Version: 1.0 Content-Type: text/plain X-SPAM-INFO: Spam detection results: 0 ALL_TRUSTED -1 Passed through trusted hosts only via SMTP AWL 0.009 Adjusted score from AWL reputation of From: address BAYES_00 -1.9 Bayes spam probability is 0 to 1% DKIM_SIGNED 0.1 Message has a DKIM or DK signature, not necessarily valid DKIM_VALID -0.1 Message has at least one valid DKIM or DK signature DKIM_VALID_AU -0.1 Message has a valid DKIM or DK signature from author's domain DKIM_VALID_EF -0.1 Message has a valid DKIM or DK signature from envelope-from domain T_SCC_BODY_TEXT_LINE -0.01 - X-SPAM-LEVEL: X-Spam-Score: -2.3 (--) X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -3.3 (---) > And against the additional variable to make this more > backward-compatible? Yup. The var would be my second-best choice (and I assume it's immediately declared obsolete). Stefan From unknown Sun Jun 15 14:44:57 2025 X-Loop: help-debbugs@gnu.org Subject: bug#70007: [PATCH] native JSON encoder Resent-From: Mattias =?UTF-8?Q?Engdeg=C3=A5rd?= Original-Sender: "Debbugs-submit" Resent-CC: bug-gnu-emacs@gnu.org Resent-Date: Sun, 25 Aug 2024 20:11:01 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 70007 X-GNU-PR-Package: emacs X-GNU-PR-Keywords: patch To: Stefan Monnier Cc: Eli Zaretskii , Andrea Corallo , casouri@gmail.com, Stefan Kangas , 70007@debbugs.gnu.org Received: via spool by 70007-submit@debbugs.gnu.org id=B70007.17246166333176 (code B ref 70007); Sun, 25 Aug 2024 20:11:01 +0000 Received: (at 70007) by debbugs.gnu.org; 25 Aug 2024 20:10:33 +0000 Received: from localhost ([127.0.0.1]:43332 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1siJZJ-0000p9-75 for submit@debbugs.gnu.org; Sun, 25 Aug 2024 16:10:33 -0400 Received: from mail-lf1-f48.google.com ([209.85.167.48]:46321) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1siJZH-0000ou-4w for 70007@debbugs.gnu.org; Sun, 25 Aug 2024 16:10:32 -0400 Received: by mail-lf1-f48.google.com with SMTP id 2adb3069b0e04-533488ffaebso4126345e87.0 for <70007@debbugs.gnu.org>; Sun, 25 Aug 2024 13:09:40 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1724616515; x=1725221315; darn=debbugs.gnu.org; h=to:references:message-id:content-transfer-encoding:cc:date :in-reply-to:from:subject:mime-version:sender:from:to:cc:subject :date:message-id:reply-to; bh=xob02ckvQpoaMAzskuGIrc5UgOGd3SZSQiT4f3szxD4=; b=Fse6KXgf9LVKgZWcGlCcZ/PwUAxGgT8QfAs/5B46ltHZ1vPA/gGxda//lPGpBcnnuU VIXIXZsqAT1B2g4zjSqPsfB9ICDK2I3w4eX+ObaK+EqokyMtsMlLyQ9K94UrwMGK5rO8 lMQhaSSTxknswtQV2b80Fz2jVWdK7OWO/PM/IiZSfdXXJ/BV9lxWs7modL0ILpovhWiK VI+icL2COzyTjQD4iiV/bzKGAL5ZhY17lyFRZXxVfV666YW19k8W91jw1vHVmMC5p5WI pxeK9emUBej/Kz4J/pIcekXi0NSKNgTf9eR7D2vHnIENuNf+GEikricbTgQfglush5F2 db6w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1724616515; x=1725221315; h=to:references:message-id:content-transfer-encoding:cc:date :in-reply-to:from:subject:mime-version:sender:x-gm-message-state :from:to:cc:subject:date:message-id:reply-to; bh=xob02ckvQpoaMAzskuGIrc5UgOGd3SZSQiT4f3szxD4=; b=BAjYoRtUAKWpczNBLwyadJG1T4eBSRCr7rxSmnAv7Fn0RR/KZ4KY7e9hmq7AYZQVr5 ZRpmIRnQNygEgSMUuq0//p1wNy0NwflMb6e+wyAHEIx9q6M7cpmtFoDJI7lhfq2EZwCb qHcpBKTygJdMiaQKAeUUeCjtZNZIwjaJ7228jh7ontsGNyBD/lEoEHWgEXubDXpkb3ul tZFt6Efs3Pdte1Nz0N4Di25lAIN1WhcjYr4zoBL89+r5JSm3LgWworwnW1RdE94yp/53 VgEtG7T7KThHHguDnh8xBNWkhtwvbAgBSka6z1s3qpK128u03iLPASOMwdJ2MwAs/DGk 08CA== X-Forwarded-Encrypted: i=1; AJvYcCWeQOX5sskOsN93srP8Kqu/QrhixsCzwLjwE9AyfT4cR1ubDZYWQB57/G9vMeRj5oHThjwilg==@debbugs.gnu.org X-Gm-Message-State: AOJu0YyJkn2Ql9Aj08nUqvk9hHIpjMq/6paamjMbgisApqQkn3+n2EHg vqnVwor9rv1lN5aXpgGURPaSKgwQq0p6yECoHAnyrVWJkwFJvAtO X-Google-Smtp-Source: AGHT+IGBLRYpsrdy9Rox1w1ujOEuxLn+XtuBugf9jxd6brfRS4DLtyNFv9Df+yXB5jmGks09UO5xXw== X-Received: by 2002:a05:6512:124f:b0:533:526a:cd08 with SMTP id 2adb3069b0e04-53438773434mr6091324e87.14.1724616514106; Sun, 25 Aug 2024 13:08:34 -0700 (PDT) Received: from smtpclient.apple (c188-150-191-82.bredband.tele2.se. [188.150.191.82]) by smtp.gmail.com with ESMTPSA id 2adb3069b0e04-5334ea996b2sm1233198e87.305.2024.08.25.13.08.33 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Sun, 25 Aug 2024 13:08:33 -0700 (PDT) Content-Type: text/plain; charset=us-ascii Mime-Version: 1.0 (Mac OS X Mail 14.0 \(3654.120.0.1.15\)) From: Mattias =?UTF-8?Q?Engdeg=C3=A5rd?= In-Reply-To: Date: Sun, 25 Aug 2024 22:08:30 +0200 Content-Transfer-Encoding: quoted-printable Message-Id: <4AD8D161-142C-4DED-BD53-7724BC6AE16E@gmail.com> References: <1BF559D1-DB9F-4FEB-90ED-72E0EFD76424@gmail.com> <86wmpphrg7.fsf@gnu.org> <4589243D-C11A-45C1-AF3E-6F4A5BADEB54@gmail.com> <864jcrindg.fsf@gnu.org> <291DD5F1-85B8-4647-A40A-EBBD4C51E253@gmail.com> <8634sbijfx.fsf@gnu.org> <2CF47DA5-A65B-47C4-A28A-6FEE1469BD13@gmail.com> <86cyrdfuai.fsf@gnu.org> <3139C8FE-5C67-4FE3-B940-F449DA73E76C@gmail.com> <86le5zdfbi.fsf@gnu.org> <4C93E902-282D-4408-B449-C8E771B2B3E4@gmail.com> <86cyr7agjo.fsf@gnu.org> <850DEC32-F318-4F3E-BA87-55FC6DC74CD3@gmail.com> <86ikvpnbj5.fsf@gnu.org> <867cc5mbq3.fsf@gnu.org> X-Mailer: Apple Mail (2.3654.120.0.1.15) X-Spam-Score: 0.0 (/) X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -1.0 (-) 25 aug. 2024 kl. 19.55 skrev Stefan Monnier : > The variable solution has one advantage: users can (setq ... t) in = their > `.emacs` to keep old code working, tho potentially at the cost of > breaking new code. Actually that's a terrible solution because it affects all code, not = just a single package. In addition, it will linger in the user's system = indefinitely (.emacs being the prime bioaccumulation tissue) and = potentially cause trouble when he or she installs a perfectly working = package years later. So my preferences are: First place: always unibyte, with no controlling variable. Very close second place: always multibyte, idem. Distant third place: contrived new function name for unibyte, like = json-serialize-encode (no, I don't like it either). Very distant fourth place: variable controlling the string type = returned. From unknown Sun Jun 15 14:44:57 2025 X-Loop: help-debbugs@gnu.org Subject: bug#70007: [PATCH] native JSON encoder Resent-From: Eli Zaretskii Original-Sender: "Debbugs-submit" Resent-CC: bug-gnu-emacs@gnu.org Resent-Date: Sat, 31 Aug 2024 09:47:02 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 70007 X-GNU-PR-Package: emacs X-GNU-PR-Keywords: patch To: Stefan Kangas , Andrea Corallo Cc: Mattias =?UTF-8?Q?Engdeg=C3=A5rd?= , casouri@gmail.com, monnier@iro.umontreal.ca, 70007@debbugs.gnu.org Received: via spool by 70007-submit@debbugs.gnu.org id=B70007.17250975933180 (code B ref 70007); Sat, 31 Aug 2024 09:47:02 +0000 Received: (at 70007) by debbugs.gnu.org; 31 Aug 2024 09:46:33 +0000 Received: from localhost ([127.0.0.1]:53967 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1skKgj-0000pE-42 for submit@debbugs.gnu.org; Sat, 31 Aug 2024 05:46:33 -0400 Received: from eggs.gnu.org ([209.51.188.92]:55678) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1skKgh-0000oz-4b for 70007@debbugs.gnu.org; Sat, 31 Aug 2024 05:46:31 -0400 Received: from fencepost.gnu.org ([2001:470:142:3::e]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1skKff-0007Xc-TC; Sat, 31 Aug 2024 05:45:27 -0400 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=gnu.org; s=fencepost-gnu-org; h=MIME-version:References:Subject:In-Reply-To:To:From: Date; bh=dh01TFV0e5MhxupD2s7FfgFWh5c0fS4eEHPRu7BRWNM=; b=S1SrescHAjokkDgzBuCh Jynf7F3h6j535p6T2sKjZrA6aKuk9mamtGN/L2pCNg7V0Wjzv/FBzbVD+Fd5kuy46W9VUTaoLIuDe FNlnBVMRymsOacKqQWGWhQ4ISYUraTvhEnrVcKew20IH7QwKJY+fExzPnQkaOfv/anKHtviga7jkA G2S5/spg84XEAt0WvsqbeHaqfl8DNjWSOXWU3V5inTY/TFDstP7yOSljmdlODjJ/O1fCUaKjZCogl AluNi9S4bsnELYZDQB4RHMlSKLbBjck91zbn8cdv28MiJT/GZvYFEG7v2chMh1xJQBmhWNO+UMSwA 0QgbhtxXv13c3g==; Date: Sat, 31 Aug 2024 12:45:25 +0300 Message-Id: <861q25c9fu.fsf@gnu.org> From: Eli Zaretskii In-Reply-To: <4AD8D161-142C-4DED-BD53-7724BC6AE16E@gmail.com> (message from Mattias =?UTF-8?Q?Engdeg=C3=A5rd?= on Sun, 25 Aug 2024 22:08:30 +0200) References: <1BF559D1-DB9F-4FEB-90ED-72E0EFD76424@gmail.com> <86wmpphrg7.fsf@gnu.org> <4589243D-C11A-45C1-AF3E-6F4A5BADEB54@gmail.com> <864jcrindg.fsf@gnu.org> <291DD5F1-85B8-4647-A40A-EBBD4C51E253@gmail.com> <8634sbijfx.fsf@gnu.org> <2CF47DA5-A65B-47C4-A28A-6FEE1469BD13@gmail.com> <86cyrdfuai.fsf@gnu.org> <3139C8FE-5C67-4FE3-B940-F449DA73E76C@gmail.com> <86le5zdfbi.fsf@gnu.org> <4C93E902-282D-4408-B449-C8E771B2B3E4@gmail.com> <86cyr7agjo.fsf@gnu.org> <850DEC32-F318-4F3E-BA87-55FC6DC74CD3@gmail.com> <86ikvpnbj5.fsf@gnu.org> <867cc5mbq3.fsf@gnu.org> <4AD8D161-142C-4DED-BD53-7724BC6AE16E@gmail.com> MIME-version: 1.0 Content-type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Spam-Score: -2.3 (--) X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -3.3 (---) > From: Mattias EngdegÃ¥rd > Date: Sun, 25 Aug 2024 22:08:30 +0200 > Cc: Eli Zaretskii , > Stefan Kangas , > Andrea Corallo , > casouri@gmail.com, > 70007@debbugs.gnu.org > > 25 aug. 2024 kl. 19.55 skrev Stefan Monnier : > > > The variable solution has one advantage: users can (setq ... t) in their > > `.emacs` to keep old code working, tho potentially at the cost of > > breaking new code. > > Actually that's a terrible solution because it affects all code, not just a single package. In addition, it will linger in the user's system indefinitely (.emacs being the prime bioaccumulation tissue) and potentially cause trouble when he or she installs a perfectly working package years later. > > So my preferences are: > > First place: always unibyte, with no controlling variable. > Very close second place: always multibyte, idem. > Distant third place: contrived new function name for unibyte, like json-serialize-encode (no, I don't like it either). > Very distant fourth place: variable controlling the string type returned. Stefan Kangas and Andrea, can I have your opinions on this, please? From unknown Sun Jun 15 14:44:57 2025 X-Loop: help-debbugs@gnu.org Subject: bug#70007: [PATCH] native JSON encoder Resent-From: Stefan Kangas Original-Sender: "Debbugs-submit" Resent-CC: bug-gnu-emacs@gnu.org Resent-Date: Sat, 31 Aug 2024 22:18:01 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 70007 X-GNU-PR-Package: emacs X-GNU-PR-Keywords: patch To: Stefan Monnier , Eli Zaretskii Cc: mattias.engdegard@gmail.com, acorallo@gnu.org, casouri@gmail.com, 70007@debbugs.gnu.org Received: via spool by 70007-submit@debbugs.gnu.org id=B70007.172514265326134 (code B ref 70007); Sat, 31 Aug 2024 22:18:01 +0000 Received: (at 70007) by debbugs.gnu.org; 31 Aug 2024 22:17:33 +0000 Received: from localhost ([127.0.0.1]:58381 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1skWPV-0006nS-FQ for submit@debbugs.gnu.org; Sat, 31 Aug 2024 18:17:33 -0400 Received: from mail-ej1-f49.google.com ([209.85.218.49]:52614) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1skWPT-0006nD-MW for 70007@debbugs.gnu.org; Sat, 31 Aug 2024 18:17:32 -0400 Received: by mail-ej1-f49.google.com with SMTP id a640c23a62f3a-a86b64ebd8aso187103566b.1 for <70007@debbugs.gnu.org>; Sat, 31 Aug 2024 15:16:32 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1725142527; x=1725747327; darn=debbugs.gnu.org; h=cc:to:subject:message-id:date:mime-version:references:in-reply-to :from:from:to:cc:subject:date:message-id:reply-to; bh=OASUk4JUUbSX1WEapXMWuXy4JGATz7JBJO8SymCArE0=; b=bihk/NSj1NvoSBJZmDuK2K0HiTZtcLeUjEux01NKjk6rGQbG9RAsfiM1itTTmfk/gn KgalcJ+XuZlLDQVFqcNeZrIMvx6bhkgJzlO4Z07SNBcoKsiJ3PMNZAGNP96JRcguKhoD e22k9ArF5pO1Ol/l0EFvgoWZEot7leiAmz3mPBuXe/RPgl13E8JvYNiNsbVW1Y9d0aWt F5Os13NwgN55hpK1GnkEioGXy1yZG6w6lWjfOUBoPzaZ8VXOtSLjjpNdAZKdf2/3izeU aYlVCTETDPqNGRpSnvurA8FuxqXE7p3i4aeJsBR19JIWHYS95I2aO+7z9OEdLEFU8an7 6I8g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1725142527; x=1725747327; h=cc:to:subject:message-id:date:mime-version:references:in-reply-to :from:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=OASUk4JUUbSX1WEapXMWuXy4JGATz7JBJO8SymCArE0=; b=bTjA4xAuivFqZAtmvmNJVTAqtNRrcSL/0Sg8VcrBLODxb4BIC0TzBRiahYs/R4zXcT J+EVc+Oa9XOVEip5kPrcLWzb7F3doKAZst0IGBqNgiKI7eaCb3kWO70jvN5W6tcj/5DT diBnWWNjksHDsRUnvWLffAvlTinfLIPx7qZ9fozVPYh3pmx2cXbIJK3X8ZrdedzeOgdK mx7IELN1EThWsfAto0H2QcsVhGGZc9o/hrF1iA4xcfIgdD2OPQiS/UkT5OsuhAz+eY0E xT0Jpmiy3CrQeei+luTCR54/x3Xf8C4Yzq2+wb3vnY6qTqQozUjFwzlKHBeZOdf4rW34 I5dA== X-Forwarded-Encrypted: i=1; AJvYcCXZYhcQFxLAvpl/pq+4mN4L+mUzaCnimsf+3u/+zPsoMgxtNRe+qZyXimYctaxXMbxtqP2+TQ==@debbugs.gnu.org X-Gm-Message-State: AOJu0YyYAb+MEbXic1m2P7xtLvrxjMm6piGICXi2qc8D59FylIPDreFl NSlVSbdNm0TspyrlPIOx6zZJ7cAdOx+DASaRvVdwvI9wy63niETCJQSbSbk+bgxAOAEiKMS88gZ P+d60xfobtxdUr3a13ddRFbaorzM= X-Google-Smtp-Source: AGHT+IHaaQ+/HrmnymLzI7ZNaJpONBFzAvHG5k61uuCgnXv7YvUx4vNMPwQ02BvCARBggx4h8mjpddL4G4vfJGO+8Jo= X-Received: by 2002:a05:6402:2686:b0:5be:efb9:b203 with SMTP id 4fb4d7f45d1cf-5c21ed9fc99mr9563889a12.34.1725142526778; Sat, 31 Aug 2024 15:15:26 -0700 (PDT) Received: from 753933720722 named unknown by gmailapi.google.com with HTTPREST; Sat, 31 Aug 2024 15:15:25 -0700 From: Stefan Kangas In-Reply-To: References: <1BF559D1-DB9F-4FEB-90ED-72E0EFD76424@gmail.com> <4589243D-C11A-45C1-AF3E-6F4A5BADEB54@gmail.com> <864jcrindg.fsf@gnu.org> <291DD5F1-85B8-4647-A40A-EBBD4C51E253@gmail.com> <8634sbijfx.fsf@gnu.org> <2CF47DA5-A65B-47C4-A28A-6FEE1469BD13@gmail.com> <86cyrdfuai.fsf@gnu.org> <3139C8FE-5C67-4FE3-B940-F449DA73E76C@gmail.com> <86le5zdfbi.fsf@gnu.org> <4C93E902-282D-4408-B449-C8E771B2B3E4@gmail.com> <86cyr7agjo.fsf@gnu.org> <850DEC32-F318-4F3E-BA87-55FC6DC74CD3@gmail.com> <86ikvpnbj5.fsf@gnu.org> <867cc5mbq3.fsf@gnu.org> <86y14kjw70.fsf@gnu.org> MIME-Version: 1.0 Date: Sat, 31 Aug 2024 15:15:25 -0700 Message-ID: Content-Type: text/plain; charset="UTF-8" X-Spam-Score: 0.0 (/) X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -1.0 (-) Stefan Monnier writes: >> And against the additional variable to make this more >> backward-compatible? > > Yup. The var would be my second-best choice (and I assume it's > immediately declared obsolete). I tend to agree with Stefan M here. From unknown Sun Jun 15 14:44:57 2025 X-Loop: help-debbugs@gnu.org Subject: bug#70007: [PATCH] native JSON encoder Resent-From: Eli Zaretskii Original-Sender: "Debbugs-submit" Resent-CC: bug-gnu-emacs@gnu.org Resent-Date: Sat, 07 Sep 2024 07:27:02 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 70007 X-GNU-PR-Package: emacs X-GNU-PR-Keywords: patch To: acorallo@gnu.org, Stefan Kangas Cc: mattias.engdegard@gmail.com, casouri@gmail.com, monnier@iro.umontreal.ca, 70007@debbugs.gnu.org Received: via spool by 70007-submit@debbugs.gnu.org id=B70007.17256940093297 (code B ref 70007); Sat, 07 Sep 2024 07:27:02 +0000 Received: (at 70007) by debbugs.gnu.org; 7 Sep 2024 07:26:49 +0000 Received: from localhost ([127.0.0.1]:54675 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1smpqK-0000r7-VO for submit@debbugs.gnu.org; Sat, 07 Sep 2024 03:26:49 -0400 Received: from eggs.gnu.org ([209.51.188.92]:49356) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1smpqI-0000qs-Rd for 70007@debbugs.gnu.org; Sat, 07 Sep 2024 03:26:47 -0400 Received: from fencepost.gnu.org ([2001:470:142:3::e]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1smpqD-0006HH-1m; Sat, 07 Sep 2024 03:26:41 -0400 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=gnu.org; s=fencepost-gnu-org; h=References:Subject:In-Reply-To:To:From:Date: mime-version; bh=AkmMzfcWhoSRIKLM66fn1Pzblzm/xr8SMrvph0CIqUQ=; b=c/KGmUjp68xY vW48DIW9v9xk0p8FxqtXVEqowhQ958mv6g9ElR5YbpcoaUSqcGQjWNCBdlUdUDYJrYgsCRb3twyhs ts2zoDLPk1tlSoojq2Q8KhvAd8JLEnle+ingzjBjPeBN7RLtZZPC3xhlQlqVtAc02nEuNnmrGXndW BzSiJi3ooXXZn46WPZ37sK6hWCplWrBxA0pWEVQulZaY1MRz6BC0elMvSHmbQ/UXyEW+/NGIwZYDj EuKyx7FvLp5VtLb3T2Fu9h1i9fl+Q+BPnaaMWFOppNXiNnb6VMolwo8JYg+GdqTU0fmpp8b3btFNx y+xuYi8xDVimxxUC/WrN8w==; Date: Sat, 07 Sep 2024 10:26:39 +0300 Message-Id: <86ikv7zzyo.fsf@gnu.org> From: Eli Zaretskii In-Reply-To: (message from Stefan Kangas on Sat, 31 Aug 2024 15:15:25 -0700) References: <1BF559D1-DB9F-4FEB-90ED-72E0EFD76424@gmail.com> <4589243D-C11A-45C1-AF3E-6F4A5BADEB54@gmail.com> <864jcrindg.fsf@gnu.org> <291DD5F1-85B8-4647-A40A-EBBD4C51E253@gmail.com> <8634sbijfx.fsf@gnu.org> <2CF47DA5-A65B-47C4-A28A-6FEE1469BD13@gmail.com> <86cyrdfuai.fsf@gnu.org> <3139C8FE-5C67-4FE3-B940-F449DA73E76C@gmail.com> <86le5zdfbi.fsf@gnu.org> <4C93E902-282D-4408-B449-C8E771B2B3E4@gmail.com> <86cyr7agjo.fsf@gnu.org> <850DEC32-F318-4F3E-BA87-55FC6DC74CD3@gmail.com> <86ikvpnbj5.fsf@gnu.org> <867cc5mbq3.fsf@gnu.org> <86y14kjw70.fsf@gnu.org> X-Spam-Score: -2.3 (--) X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -3.3 (---) > From: Stefan Kangas > Date: Sat, 31 Aug 2024 15:15:25 -0700 > Cc: mattias.engdegard@gmail.com, acorallo@gnu.org, casouri@gmail.com, > 70007@debbugs.gnu.org > > Stefan Monnier writes: > > >> And against the additional variable to make this more > >> backward-compatible? > > > > Yup. The var would be my second-best choice (and I assume it's > > immediately declared obsolete). > > I tend to agree with Stefan M here. Thanks. Andrea, would you please voice your opinion on this? From unknown Sun Jun 15 14:44:57 2025 X-Loop: help-debbugs@gnu.org Subject: bug#70007: [PATCH] native JSON encoder Resent-From: Andrea Corallo Original-Sender: "Debbugs-submit" Resent-CC: bug-gnu-emacs@gnu.org Resent-Date: Sat, 07 Sep 2024 15:49:02 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 70007 X-GNU-PR-Package: emacs X-GNU-PR-Keywords: patch To: Eli Zaretskii Cc: mattias.engdegard@gmail.com, 70007@debbugs.gnu.org, casouri@gmail.com, Stefan Kangas , monnier@iro.umontreal.ca Received: via spool by 70007-submit@debbugs.gnu.org id=B70007.172572412615473 (code B ref 70007); Sat, 07 Sep 2024 15:49:02 +0000 Received: (at 70007) by debbugs.gnu.org; 7 Sep 2024 15:48:46 +0000 Received: from localhost ([127.0.0.1]:57249 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1smxg6-00041V-AL for submit@debbugs.gnu.org; Sat, 07 Sep 2024 11:48:46 -0400 Received: from eggs.gnu.org ([209.51.188.92]:59404) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1smxg4-00041H-9I for 70007@debbugs.gnu.org; Sat, 07 Sep 2024 11:48:45 -0400 Received: from fencepost.gnu.org ([2001:470:142:3::e]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1smxfx-0001uK-Ru; Sat, 07 Sep 2024 11:48:37 -0400 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=gnu.org; s=fencepost-gnu-org; h=MIME-Version:Date:References:In-Reply-To:Subject:To: From; bh=vt0m8gcVRDg8H4Ty2Vnk0IWsxeC2Kr0Ju+uB/efjJ+4=; b=Mwc4NjH9g23TtavWvW7r pDvcBjzi5jKkS3FK+65x2NGa/5tV63U+lhem0jszvA7ZTVUm4hrB0hWgvSWmQ1KFXdStGNlQ2a2Zv HLSmLpVDS6qefoUXFU/dpHbZZuFuRVY43f8xH7g/lnVGeeaWjh8uUaaS3jMYyz3nE+NYBusl9u2+k r7f8Lqr/beUeKlOC2FEd7C193FYHXTh8OcGp4Au3zhvjyciWGUdpSyddV4H02AxEut9xpXbY/ruvZ 2VTDrEUfmj0AQJVhAtCvl39OJztQbwJZjx/z5vAqr48i9hrBGxdE94Hl5xuSH6aUs57PxHgKLtSn9 UkcaQQ2qIDnHpA==; Received: from acorallo by fencepost.gnu.org with local (Exim 4.90_1) (envelope-from ) id 1smxfx-0005To-0z; Sat, 07 Sep 2024 11:48:37 -0400 From: Andrea Corallo In-Reply-To: <86ikv7zzyo.fsf@gnu.org> (Eli Zaretskii's message of "Sat, 07 Sep 2024 10:26:39 +0300") References: <1BF559D1-DB9F-4FEB-90ED-72E0EFD76424@gmail.com> <864jcrindg.fsf@gnu.org> <291DD5F1-85B8-4647-A40A-EBBD4C51E253@gmail.com> <8634sbijfx.fsf@gnu.org> <2CF47DA5-A65B-47C4-A28A-6FEE1469BD13@gmail.com> <86cyrdfuai.fsf@gnu.org> <3139C8FE-5C67-4FE3-B940-F449DA73E76C@gmail.com> <86le5zdfbi.fsf@gnu.org> <4C93E902-282D-4408-B449-C8E771B2B3E4@gmail.com> <86cyr7agjo.fsf@gnu.org> <850DEC32-F318-4F3E-BA87-55FC6DC74CD3@gmail.com> <86ikvpnbj5.fsf@gnu.org> <867cc5mbq3.fsf@gnu.org> <86y14kjw70.fsf@gnu.org> <86ikv7zzyo.fsf@gnu.org> Date: Sat, 07 Sep 2024 11:48:36 -0400 Message-ID: User-Agent: Gnus/5.13 (Gnus v5.13) MIME-Version: 1.0 Content-Type: text/plain X-Spam-Score: -2.3 (--) X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -3.3 (---) Eli Zaretskii writes: >> From: Stefan Kangas >> Date: Sat, 31 Aug 2024 15:15:25 -0700 >> Cc: mattias.engdegard@gmail.com, acorallo@gnu.org, casouri@gmail.com, >> 70007@debbugs.gnu.org >> >> Stefan Monnier writes: >> >> >> And against the additional variable to make this more >> >> backward-compatible? >> > >> > Yup. The var would be my second-best choice (and I assume it's >> > immediately declared obsolete). >> >> I tend to agree with Stefan M here. > > Thanks. > > Andrea, would you please voice your opinion on this? I'm for returning unibyte indeed. And for the variable or the second function I'm kind of neutral, I'd do it only if it's not too much effort so I'll trust Mattias preference here. Andrea From unknown Sun Jun 15 14:44:57 2025 X-Loop: help-debbugs@gnu.org Subject: bug#70007: [PATCH] native JSON encoder Resent-From: Eli Zaretskii Original-Sender: "Debbugs-submit" Resent-CC: bug-gnu-emacs@gnu.org Resent-Date: Sat, 07 Sep 2024 15:54:02 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 70007 X-GNU-PR-Package: emacs X-GNU-PR-Keywords: patch To: Andrea Corallo Cc: mattias.engdegard@gmail.com, 70007@debbugs.gnu.org, casouri@gmail.com, stefankangas@gmail.com, monnier@iro.umontreal.ca Received: via spool by 70007-submit@debbugs.gnu.org id=B70007.172572438716462 (code B ref 70007); Sat, 07 Sep 2024 15:54:02 +0000 Received: (at 70007) by debbugs.gnu.org; 7 Sep 2024 15:53:07 +0000 Received: from localhost ([127.0.0.1]:57254 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1smxkJ-0004HS-07 for submit@debbugs.gnu.org; Sat, 07 Sep 2024 11:53:07 -0400 Received: from eggs.gnu.org ([209.51.188.92]:41394) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1smxkG-0004Gw-Lp for 70007@debbugs.gnu.org; Sat, 07 Sep 2024 11:53:05 -0400 Received: from fencepost.gnu.org ([2001:470:142:3::e]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1smxk8-0002J3-F1; Sat, 07 Sep 2024 11:52:57 -0400 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=gnu.org; s=fencepost-gnu-org; h=References:Subject:In-Reply-To:To:From:Date: mime-version; bh=0/k26vqxS5GXL1Ej2LjPsWMePeydFZtgNkXLF/Nmrls=; b=KMMLl3cLQ+Pj zZ+D8A56ij9GluyeLP513f9Bs+4jUAvNxMJ+LU48PYLc8ps70EaytOBcnM88ILstjnO6YCTtYkeJk dxbLOTxTqg/rgP+OSBy6jTDkxgqLHqgMBhjp1A63eRDQJrOtRQhIxIr3Ucpwin+5G/6EAUahFDxa1 nPbfK+6QDkTLXUnFxk8tRLG435AatqczCIpze2TAkkjil8HVEvClMw8OT0HOutCiZSji9UkkjlbxL MBv3skpdTr2Xg7mpK2s+v0gGfJKcFbzEasupOcVydwMZ8COMnW9X512gmMl2j9F6BpbIJa+1U6SjP Oh1N4mOk1Gnrw6W9u8M/8A==; Date: Sat, 07 Sep 2024 18:52:49 +0300 Message-Id: <864j6rxxym.fsf@gnu.org> From: Eli Zaretskii In-Reply-To: (message from Andrea Corallo on Sat, 07 Sep 2024 11:48:36 -0400) References: <1BF559D1-DB9F-4FEB-90ED-72E0EFD76424@gmail.com> <864jcrindg.fsf@gnu.org> <291DD5F1-85B8-4647-A40A-EBBD4C51E253@gmail.com> <8634sbijfx.fsf@gnu.org> <2CF47DA5-A65B-47C4-A28A-6FEE1469BD13@gmail.com> <86cyrdfuai.fsf@gnu.org> <3139C8FE-5C67-4FE3-B940-F449DA73E76C@gmail.com> <86le5zdfbi.fsf@gnu.org> <4C93E902-282D-4408-B449-C8E771B2B3E4@gmail.com> <86cyr7agjo.fsf@gnu.org> <850DEC32-F318-4F3E-BA87-55FC6DC74CD3@gmail.com> <86ikvpnbj5.fsf@gnu.org> <867cc5mbq3.fsf@gnu.org> <86y14kjw70.fsf@gnu.org> <86ikv7zzyo.fsf@gnu.org> X-Spam-Score: -2.3 (--) X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -3.3 (---) > From: Andrea Corallo > Cc: Stefan Kangas , monnier@iro.umontreal.ca, > mattias.engdegard@gmail.com, casouri@gmail.com, 70007@debbugs.gnu.org > Date: Sat, 07 Sep 2024 11:48:36 -0400 > > Eli Zaretskii writes: > > >> From: Stefan Kangas > >> Date: Sat, 31 Aug 2024 15:15:25 -0700 > >> Cc: mattias.engdegard@gmail.com, acorallo@gnu.org, casouri@gmail.com, > >> 70007@debbugs.gnu.org > >> > >> Stefan Monnier writes: > >> > >> >> And against the additional variable to make this more > >> >> backward-compatible? > >> > > >> > Yup. The var would be my second-best choice (and I assume it's > >> > immediately declared obsolete). > >> > >> I tend to agree with Stefan M here. > > > > Thanks. > > > > Andrea, would you please voice your opinion on this? > > I'm for returning unibyte indeed. And for the variable or the second > function I'm kind of neutral, I'd do it only if it's not too much effort > so I'll trust Mattias preference here. OK, so let's go with unconditionally unibyte, as it seems to be the consensus here. From unknown Sun Jun 15 14:44:57 2025 X-Loop: help-debbugs@gnu.org Subject: bug#70007: [PATCH] native JSON encoder Resent-From: Mattias =?UTF-8?Q?Engdeg=C3=A5rd?= Original-Sender: "Debbugs-submit" Resent-CC: bug-gnu-emacs@gnu.org Resent-Date: Sun, 08 Sep 2024 18:35:02 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 70007 X-GNU-PR-Package: emacs X-GNU-PR-Keywords: patch To: Eli Zaretskii Cc: casouri@gmail.com, Andrea Corallo , 70007@debbugs.gnu.org, stefankangas@gmail.com, monnier@iro.umontreal.ca Received: via spool by 70007-submit@debbugs.gnu.org id=B70007.172582048716130 (code B ref 70007); Sun, 08 Sep 2024 18:35:02 +0000 Received: (at 70007) by debbugs.gnu.org; 8 Sep 2024 18:34:47 +0000 Received: from localhost ([127.0.0.1]:60054 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1snMkI-0004C6-PN for submit@debbugs.gnu.org; Sun, 08 Sep 2024 14:34:46 -0400 Received: from mail-lf1-f51.google.com ([209.85.167.51]:50265) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1snMkG-0004Bo-Kh for 70007@debbugs.gnu.org; Sun, 08 Sep 2024 14:34:45 -0400 Received: by mail-lf1-f51.google.com with SMTP id 2adb3069b0e04-53653ff0251so4180685e87.0 for <70007@debbugs.gnu.org>; Sun, 08 Sep 2024 11:34:42 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1725820416; x=1726425216; darn=debbugs.gnu.org; h=to:references:message-id:content-transfer-encoding:cc:date :in-reply-to:from:subject:mime-version:sender:from:to:cc:subject :date:message-id:reply-to; bh=UOl4F/hVbN5x9AVEmLD+fBV/1IRwAr1HLGYo7NVc0aw=; b=fhw8VeofE8LI7/rteTBzFo1nJkezH1KmvZI6WStoMDzvMHmQXY1HVlXA3uWs2AAokn Ki/Tw5JzSuU3bFz5p7OThCZY+UMFfBvV1WIkc9gP/EPs0qHRpKBuVltLBS0fZAdX8xFc pbK64CMBI8a4Hi2mrI2B4xC0bmjgcvqearj8yzD+3ZoOqJNf/V7W5Oi1v3ChS45QLyRB Mlq0YvQziclo2kvkKkHMzQbW1aJWwE3Gwea4Gksk1I1bsYkDs36MmKX1YmjpWU0wDcKt bkNirQ7PsLQLUwyoIAa7qyJkdbmDmw2mt4KEU8MH+97aNV9vDas6rDZtynW2kab5vLAc lLFQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1725820416; x=1726425216; h=to:references:message-id:content-transfer-encoding:cc:date :in-reply-to:from:subject:mime-version:sender:x-gm-message-state :from:to:cc:subject:date:message-id:reply-to; bh=UOl4F/hVbN5x9AVEmLD+fBV/1IRwAr1HLGYo7NVc0aw=; b=N9U8URqlT2tw/IJ9E6FYsJDkSVXEkxcZ0p+nZWa5l30eG2S7DQh6F6ZcZhZ6TY6CEk nmEApZ816kfW2akPSvJxgw5wZVYKAW0Vk6AOu6ljem/xHu8lL47rdXd0INC90gL4Tssm xOVI5edWvr+y009s9+/XrATaCrDJaTJLT7HHhzpiC99rNSR/AfwX115F/TXQqltlFeqY 25isBPE8hOddmeUlqtnB9d+5VwDUHLjBxMpN+tiNppS5+6c2YcIngQToh+/baatQ70Uj PBj5kLBkg365jDKwrOYRBM9XJPSWNlwEcAAi4XfirSNvn7MDp+VhMn4s3jdvYxkXid0z vT/Q== X-Forwarded-Encrypted: i=1; AJvYcCW0YHaWnGMJIfMks6TdsSmYlr6RgKBCqoh2II0A6JCV1DscWVrMjvSTLIpNp2ebEApwXZc2pQ==@debbugs.gnu.org X-Gm-Message-State: AOJu0Yy5iaEMeDhhzfPIgRjrCrgnIXX1QGWZATzgrOPVfIsYCpw7RqTa ebmcmaJmUk21vYCQvXlkFigJPKNuO7zpiCQjaPL2ECkNpdbgvl2G X-Google-Smtp-Source: AGHT+IGHihB1Sv9jD27w86tnaUEIU0yEu0yCF4D5EPTnEC/ls7/Wx7EEKJAYMKw+ybbZyEmJbTgcAw== X-Received: by 2002:a05:6512:108f:b0:530:ae99:c7fa with SMTP id 2adb3069b0e04-536587a7721mr5412138e87.10.1725820415379; Sun, 08 Sep 2024 11:33:35 -0700 (PDT) Received: from smtpclient.apple (c188-150-191-82.bredband.tele2.se. [188.150.191.82]) by smtp.gmail.com with ESMTPSA id 2adb3069b0e04-5365f903981sm508109e87.188.2024.09.08.11.33.34 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Sun, 08 Sep 2024 11:33:34 -0700 (PDT) Content-Type: text/plain; charset=us-ascii Mime-Version: 1.0 (Mac OS X Mail 14.0 \(3654.120.0.1.15\)) From: Mattias =?UTF-8?Q?Engdeg=C3=A5rd?= In-Reply-To: <864j6rxxym.fsf@gnu.org> Date: Sun, 8 Sep 2024 20:33:33 +0200 Content-Transfer-Encoding: 7bit Message-Id: References: <1BF559D1-DB9F-4FEB-90ED-72E0EFD76424@gmail.com> <864jcrindg.fsf@gnu.org> <291DD5F1-85B8-4647-A40A-EBBD4C51E253@gmail.com> <8634sbijfx.fsf@gnu.org> <2CF47DA5-A65B-47C4-A28A-6FEE1469BD13@gmail.com> <86cyrdfuai.fsf@gnu.org> <3139C8FE-5C67-4FE3-B940-F449DA73E76C@gmail.com> <86le5zdfbi.fsf@gnu.org> <4C93E902-282D-4408-B449-C8E771B2B3E4@gmail.com> <86cyr7agjo.fsf@gnu.org> <850DEC32-F318-4F3E-BA87-55FC6DC74CD3@gmail.com> <86ikvpnbj5.fsf@gnu.org> <867cc5mbq3.fsf@gnu.org> <86y14kjw70.fsf@gnu.org> <86ikv7zzyo.fsf@gnu.org> <864j6rxxym.fsf@gnu.org> X-Mailer: Apple Mail (2.3654.120.0.1.15) X-Spam-Score: -0.0 (/) X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -1.0 (-) 7 sep. 2024 kl. 17.52 skrev Eli Zaretskii : > OK, so let's go with unconditionally unibyte, as it seems to be the > consensus here. That change has now been pushed to emacs-30. Feel free to adjust as required. From debbugs-submit-bounces@debbugs.gnu.org Tue Sep 10 09:26:06 2024 Received: (at control) by debbugs.gnu.org; 10 Sep 2024 13:26:06 +0000 Received: from localhost ([127.0.0.1]:35067 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1so0sg-0003Xi-5f for submit@debbugs.gnu.org; Tue, 10 Sep 2024 09:26:06 -0400 Received: from mail-lj1-f171.google.com ([209.85.208.171]:53489) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1so0sd-0003XL-Ez for control@debbugs.gnu.org; Tue, 10 Sep 2024 09:26:04 -0400 Received: by mail-lj1-f171.google.com with SMTP id 38308e7fff4ca-2f029e9c9cfso531081fa.2 for ; Tue, 10 Sep 2024 06:25:58 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1725974692; x=1726579492; darn=debbugs.gnu.org; h=to:date:message-id:subject:mime-version:content-transfer-encoding :from:sender:from:to:cc:subject:date:message-id:reply-to; bh=XhSzJKqjWpcGEVyt2qkccC5lbdEmHEzMMjHhaIgXGYQ=; b=ki6x/w+zcQQYJVYC8Wxro+3VPWVZSJEiudi6e7VvJO1aQZIXIvinCX9LZBtrAnbrrb YtJTOGxQrTq3YVo51aRJqKcFULwUXl+IYVu+58ZbgeYtHFOW+INzBV5fV8v88h1B72Ng R21UquABIeMrpiC0WYtD3EWc1tdjohkfo6pVTdSnHgZj9g3/vPUdo/7eBaQD19zxBoew VvWdkAfXeFQHQ6DDej+rhrXjEeZ3A99McBxtksd4rjoT+/QGRRKCOxc/Zup1F9f/VtEj o5JnLkf53IRYqvu9WHTR1Y8133XR2rpWFq9cCm+IR05K3kDwIgL8ZstPRAhwM1rM5+MJ +K+Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1725974692; x=1726579492; h=to:date:message-id:subject:mime-version:content-transfer-encoding :from:sender:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=XhSzJKqjWpcGEVyt2qkccC5lbdEmHEzMMjHhaIgXGYQ=; b=Kxe9acjqqo0NijiLuC2nt3Z7aBz4OQbS8iuKIHnUfGNHuu6m4LccvchklKukhRL6C7 8bl8lvK3uDoGJuPLyywkwhRUqQicADdFjzdkb4S5apLLebj6eb9FdJQ7aGhKIVpzQPkN u511xtRVIpkretDe2wpr5NtmnKweXmSPsKxo+2LAZYg0nVzUrB5ubsNnvx3HgB/6qbGZ 8E+ntA940y+XVtgCg+CHwBmaM4i0kln1GnG+totPXn+izHDoBrnq+WIfMNyaE7lWq+pY pyyjs9T1pWQkKoTEmRQVjkm0dpC27BR2//eEcQt1KRhefwgNRLXYW/T1gDdMUYOTX9pJ 6JjQ== X-Gm-Message-State: AOJu0YxDNaTWdJfRitz+hk5sKSQOQ7OGMQ6X+T1NUbEWgqoFurWXuhxL Rdp9v3d+oCpHzB7IkJH+FLATS1A/OA75vnZzyj2AW/yhGAK7rIsgs+iTIg== X-Google-Smtp-Source: AGHT+IGyNHiX2D9xZ7RW3q4frc2VkDPN523x+S0rnZnk0xRQ7+m+gZi0i7DMNN7rbYwKxCsH0+p/Kg== X-Received: by 2002:a2e:be08:0:b0:2ef:28ed:1ff2 with SMTP id 38308e7fff4ca-2f75a96d9ffmr111751521fa.9.1725974691865; Tue, 10 Sep 2024 06:24:51 -0700 (PDT) Received: from smtpclient.apple (c188-150-191-82.bredband.tele2.se. [188.150.191.82]) by smtp.gmail.com with ESMTPSA id 38308e7fff4ca-2f75c07c5a5sm12190921fa.97.2024.09.10.06.24.51 for (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Tue, 10 Sep 2024 06:24:51 -0700 (PDT) From: =?utf-8?Q?Mattias_Engdeg=C3=A5rd?= Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit Mime-Version: 1.0 (Mac OS X Mail 14.0 \(3654.120.0.1.15\)) Subject: Message-Id: <7D7BF2C5-D55A-4287-B306-E6B51D15ABA5@gmail.com> Date: Tue, 10 Sep 2024 15:24:50 +0200 To: control@debbugs.gnu.org X-Mailer: Apple Mail (2.3654.120.0.1.15) X-Spam-Score: 2.0 (++) X-Spam-Report: Spam detection software, running on the system "debbugs.gnu.org", has NOT identified this incoming email as spam. The original message has been attached to this so you can view it or label similar future email. If you have any questions, see the administrator of that system for details. Content preview: close 70007 stop Content analysis details: (2.0 points, 10.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 SPF_PASS SPF: sender matches SPF record 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record 0.0 FREEMAIL_FROM Sender email is commonly abused enduser mail provider (mattias.engdegard[at]gmail.com) -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at https://www.dnswl.org/, no trust [209.85.208.171 listed in list.dnswl.org] -0.0 RCVD_IN_MSPIKE_H2 RBL: Average reputation (+2) [209.85.208.171 listed in wl.mailspike.net] 2.0 BLANK_SUBJECT Subject is present but empty -0.0 T_SCC_BODY_TEXT_LINE No description available. X-Debbugs-Envelope-To: control X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: 1.0 (+) close 70007 stop