Received: (at 70007) by debbugs.gnu.org; 2 Apr 2024 17:19:20 +0000 From debbugs-submit-bounces <at> debbugs.gnu.org Tue Apr 02 13:19:20 2024 Received: from localhost ([127.0.0.1]:56132 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1rrhn5-0004Ob-7e for submit <at> 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 <mattias.engdegard@HIDDEN>) id 1rrhn2-0004Nv-L2 for 70007 <at> 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 <at> 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\)) Subject: Re: bug#70007: [PATCH] native JSON encoder From: =?utf-8?Q?Mattias_Engdeg=C3=A5rd?= <mattias.engdegard@HIDDEN> In-Reply-To: <86cyr7agjo.fsf@HIDDEN> Date: Tue, 2 Apr 2024 19:19:03 +0200 Content-Transfer-Encoding: quoted-printable Message-Id: <850DEC32-F318-4F3E-BA87-55FC6DC74CD3@HIDDEN> References: <1BF559D1-DB9F-4FEB-90ED-72E0EFD76424@HIDDEN> <86wmpphrg7.fsf@HIDDEN> <C6944977-0CF9-4D19-9D92-EA1F086700D7@HIDDEN> <4589243D-C11A-45C1-AF3E-6F4A5BADEB54@HIDDEN> <864jcrindg.fsf@HIDDEN> <291DD5F1-85B8-4647-A40A-EBBD4C51E253@HIDDEN> <8634sbijfx.fsf@HIDDEN> <2CF47DA5-A65B-47C4-A28A-6FEE1469BD13@HIDDEN> <86cyrdfuai.fsf@HIDDEN> <3139C8FE-5C67-4FE3-B940-F449DA73E76C@HIDDEN> <86le5zdfbi.fsf@HIDDEN> <E07F73AC-A127-4E6D-A86F-0FB303F2BB48@HIDDEN> <4C93E902-282D-4408-B449-C8E771B2B3E4@HIDDEN> <86cyr7agjo.fsf@HIDDEN> To: Eli Zaretskii <eliz@HIDDEN> X-Mailer: Apple Mail (2.3654.120.0.1.15) X-Spam-Score: 0.0 (/) X-Debbugs-Envelope-To: 70007 Cc: casouri@HIDDEN, 70007 <at> debbugs.gnu.org X-BeenThere: debbugs-submit <at> debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: <debbugs-submit.debbugs.gnu.org> List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe> List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/> List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org> List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help> List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe> Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org> X-Spam-Score: -1.0 (-) 2 apr. 2024 kl. 18.13 skrev Eli Zaretskii <eliz@HIDDEN>: >> 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.
bug-gnu-emacs@HIDDEN
:bug#70007
; Package emacs
.
Full text available.Received: (at 70007) by debbugs.gnu.org; 2 Apr 2024 16:14:32 +0000 From debbugs-submit-bounces <at> debbugs.gnu.org Tue Apr 02 12:14:32 2024 Received: from localhost ([127.0.0.1]:55814 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1rrgmM-0007j4-F5 for submit <at> 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 <eliz@HIDDEN>) id 1rrgmI-0007id-Rg for 70007 <at> 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 <eliz@HIDDEN>) 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@HIDDEN> From: Eli Zaretskii <eliz@HIDDEN> To: Mattias =?utf-8?Q?Engdeg=C3=A5rd?= <mattias.engdegard@HIDDEN> In-Reply-To: <4C93E902-282D-4408-B449-C8E771B2B3E4@HIDDEN> (message from Mattias =?utf-8?Q?Engdeg=C3=A5rd?= on Tue, 2 Apr 2024 16:13:58 +0200) Subject: Re: bug#70007: [PATCH] native JSON encoder References: <1BF559D1-DB9F-4FEB-90ED-72E0EFD76424@HIDDEN> <86wmpphrg7.fsf@HIDDEN> <C6944977-0CF9-4D19-9D92-EA1F086700D7@HIDDEN> <4589243D-C11A-45C1-AF3E-6F4A5BADEB54@HIDDEN> <864jcrindg.fsf@HIDDEN> <291DD5F1-85B8-4647-A40A-EBBD4C51E253@HIDDEN> <8634sbijfx.fsf@HIDDEN> <2CF47DA5-A65B-47C4-A28A-6FEE1469BD13@HIDDEN> <86cyrdfuai.fsf@HIDDEN> <3139C8FE-5C67-4FE3-B940-F449DA73E76C@HIDDEN> <86le5zdfbi.fsf@HIDDEN> <E07F73AC-A127-4E6D-A86F-0FB303F2BB48@HIDDEN> <4C93E902-282D-4408-B449-C8E771B2B3E4@HIDDEN> MIME-version: 1.0 Content-type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Spam-Score: -2.3 (--) X-Debbugs-Envelope-To: 70007 Cc: casouri@HIDDEN, 70007 <at> debbugs.gnu.org X-BeenThere: debbugs-submit <at> debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: <debbugs-submit.debbugs.gnu.org> List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe> List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/> List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org> List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help> List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe> Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org> X-Spam-Score: -3.3 (---) > From: Mattias Engdegård <mattias.engdegard@HIDDEN> > Date: Tue, 2 Apr 2024 16:13:58 +0200 > Cc: casouri@HIDDEN, > 70007 <at> 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.
bug-gnu-emacs@HIDDEN
:bug#70007
; Package emacs
.
Full text available.Received: (at 70007) by debbugs.gnu.org; 2 Apr 2024 14:14:14 +0000 From debbugs-submit-bounces <at> debbugs.gnu.org Tue Apr 02 10:14:14 2024 Received: from localhost ([127.0.0.1]:54855 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1rretx-0007Iu-JL for submit <at> 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 <mattias.engdegard@HIDDEN>) id 1rretv-0007I1-C9 for 70007 <at> 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 <at> 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: =?utf-8?Q?Mattias_Engdeg=C3=A5rd?= <mattias.engdegard@HIDDEN> Message-Id: <4C93E902-282D-4408-B449-C8E771B2B3E4@HIDDEN> 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\)) Subject: Re: bug#70007: [PATCH] native JSON encoder Date: Tue, 2 Apr 2024 16:13:58 +0200 In-Reply-To: <E07F73AC-A127-4E6D-A86F-0FB303F2BB48@HIDDEN> To: Eli Zaretskii <eliz@HIDDEN> References: <1BF559D1-DB9F-4FEB-90ED-72E0EFD76424@HIDDEN> <86wmpphrg7.fsf@HIDDEN> <C6944977-0CF9-4D19-9D92-EA1F086700D7@HIDDEN> <4589243D-C11A-45C1-AF3E-6F4A5BADEB54@HIDDEN> <864jcrindg.fsf@HIDDEN> <291DD5F1-85B8-4647-A40A-EBBD4C51E253@HIDDEN> <8634sbijfx.fsf@HIDDEN> <2CF47DA5-A65B-47C4-A28A-6FEE1469BD13@HIDDEN> <86cyrdfuai.fsf@HIDDEN> <3139C8FE-5C67-4FE3-B940-F449DA73E76C@HIDDEN> <86le5zdfbi.fsf@HIDDEN> <E07F73AC-A127-4E6D-A86F-0FB303F2BB48@HIDDEN> X-Mailer: Apple Mail (2.3654.120.0.1.15) X-Spam-Score: 0.0 (/) X-Debbugs-Envelope-To: 70007 Cc: casouri@HIDDEN, 70007 <at> debbugs.gnu.org X-BeenThere: debbugs-submit <at> debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: <debbugs-submit.debbugs.gnu.org> List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe> List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/> List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org> List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help> List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe> Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org> 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--
bug-gnu-emacs@HIDDEN
:bug#70007
; Package emacs
.
Full text available.Received: (at 70007) by debbugs.gnu.org; 30 Mar 2024 23:30:29 +0000 From debbugs-submit-bounces <at> debbugs.gnu.org Sat Mar 30 19:30:29 2024 Received: from localhost ([127.0.0.1]:46335 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1rqi9b-0005Xv-Vp for submit <at> 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 <rcopley@HIDDEN>) id 1rqi9W-0005XR-Mc for 70007 <at> 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 <at> 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@HIDDEN> <86wmpphrg7.fsf@HIDDEN> <C6944977-0CF9-4D19-9D92-EA1F086700D7@HIDDEN> <4589243D-C11A-45C1-AF3E-6F4A5BADEB54@HIDDEN> <864jcrindg.fsf@HIDDEN> <291DD5F1-85B8-4647-A40A-EBBD4C51E253@HIDDEN> <8634sbijfx.fsf@HIDDEN> <2CF47DA5-A65B-47C4-A28A-6FEE1469BD13@HIDDEN> <86cyrdfuai.fsf@HIDDEN> <3139C8FE-5C67-4FE3-B940-F449DA73E76C@HIDDEN> <86le5zdfbi.fsf@HIDDEN> <E07F73AC-A127-4E6D-A86F-0FB303F2BB48@HIDDEN> <f55f685b-03c2-5132-c32d-3e0127816fd0@HIDDEN> <868r1zd65p.fsf@HIDDEN> In-Reply-To: <868r1zd65p.fsf@HIDDEN> From: Richard Copley <rcopley@HIDDEN> Date: Sat, 30 Mar 2024 23:29:48 +0000 Message-ID: <CAPM58oiUY43iO6yVYsHvGdFmdH-Z26oT760OdoKEdo1CpwXbYA@HIDDEN> Subject: Re: bug#70007: [PATCH] native JSON encoder To: Eli Zaretskii <eliz@HIDDEN> Content-Type: text/plain; charset="UTF-8" X-Spam-Score: 0.0 (/) X-Debbugs-Envelope-To: 70007 Cc: mattias.engdegard@HIDDEN, 70007 <at> debbugs.gnu.org X-BeenThere: debbugs-submit <at> debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: <debbugs-submit.debbugs.gnu.org> List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe> List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/> List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org> List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help> List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe> Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org> X-Spam-Score: -1.0 (-) On Sat, 30 Mar 2024 at 16:40, Eli Zaretskii <eliz@HIDDEN> wrote: > Please try again, I hope I fixed this. Thanks, looks good.
bug-gnu-emacs@HIDDEN
:bug#70007
; Package emacs
.
Full text available.Received: (at 70007) by debbugs.gnu.org; 30 Mar 2024 20:37:22 +0000 From debbugs-submit-bounces <at> debbugs.gnu.org Sat Mar 30 16:37:22 2024 Received: from localhost ([127.0.0.1]:46241 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1rqfS6-0005Fp-8n for submit <at> 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 <mplscorwin@HIDDEN>) id 1rqfS4-0005FY-1D for 70007 <at> 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 <at> 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@HIDDEN> <C6944977-0CF9-4D19-9D92-EA1F086700D7@HIDDEN> <4589243D-C11A-45C1-AF3E-6F4A5BADEB54@HIDDEN> <864jcrindg.fsf@HIDDEN> <291DD5F1-85B8-4647-A40A-EBBD4C51E253@HIDDEN> <8634sbijfx.fsf@HIDDEN> <2CF47DA5-A65B-47C4-A28A-6FEE1469BD13@HIDDEN> <86cyrdfuai.fsf@HIDDEN> <3139C8FE-5C67-4FE3-B940-F449DA73E76C@HIDDEN> <86le5zdfbi.fsf@HIDDEN> <E07F73AC-A127-4E6D-A86F-0FB303F2BB48@HIDDEN> <f55f685b-03c2-5132-c32d-3e0127816fd0@HIDDEN> <1BF559D1-DB9F-4FEB-90ED-72E0EFD76424@HIDDEN> <86r0fr3by5.fsf@HIDDEN> In-Reply-To: <86r0fr3by5.fsf@HIDDEN> From: Corwin Brust <corwin@HIDDEN> Date: Sat, 30 Mar 2024 15:36:59 -0500 Message-ID: <CAJf-WoT9zSNTe4FWHPAbwKXA7Qaiour94KfH6WLk39fTN9-Tdg@HIDDEN> Subject: Re: bug#70007: [PATCH] native JSON encoder To: Andy Moreton <andrewjmoreton@HIDDEN> Content-Type: text/plain; charset="UTF-8" X-Spam-Score: 0.2 (/) X-Debbugs-Envelope-To: 70007 Cc: 70007 <at> debbugs.gnu.org X-BeenThere: debbugs-submit <at> debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: <debbugs-submit.debbugs.gnu.org> List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe> List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/> List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org> List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help> List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe> Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org> 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!
bug-gnu-emacs@HIDDEN
:bug#70007
; Package emacs
.
Full text available.Received: (at 70007) by debbugs.gnu.org; 30 Mar 2024 20:21:52 +0000 From debbugs-submit-bounces <at> debbugs.gnu.org Sat Mar 30 16:21:51 2024 Received: from localhost ([127.0.0.1]:46212 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1rqfD5-0004N3-Jl for submit <at> 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 <mattias.engdegard@HIDDEN>) id 1rqfD2-0004MV-Qw for 70007 <at> 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 <at> 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\)) Subject: Re: bug#70007: [PATCH] native JSON encoder From: =?utf-8?Q?Mattias_Engdeg=C3=A5rd?= <mattias.engdegard@HIDDEN> In-Reply-To: <86edbrd6bv.fsf@HIDDEN> Date: Sat, 30 Mar 2024 21:21:39 +0100 Content-Transfer-Encoding: quoted-printable Message-Id: <FD8BB0FC-A423-477F-A4C1-3C11455B1751@HIDDEN> References: <1BF559D1-DB9F-4FEB-90ED-72E0EFD76424@HIDDEN> <86wmpphrg7.fsf@HIDDEN> <C6944977-0CF9-4D19-9D92-EA1F086700D7@HIDDEN> <4589243D-C11A-45C1-AF3E-6F4A5BADEB54@HIDDEN> <864jcrindg.fsf@HIDDEN> <291DD5F1-85B8-4647-A40A-EBBD4C51E253@HIDDEN> <8634sbijfx.fsf@HIDDEN> <2CF47DA5-A65B-47C4-A28A-6FEE1469BD13@HIDDEN> <86cyrdfuai.fsf@HIDDEN> <3139C8FE-5C67-4FE3-B940-F449DA73E76C@HIDDEN> <86le5zdfbi.fsf@HIDDEN> <E07F73AC-A127-4E6D-A86F-0FB303F2BB48@HIDDEN> <86edbrd6bv.fsf@HIDDEN> To: Eli Zaretskii <eliz@HIDDEN> X-Mailer: Apple Mail (2.3654.120.0.1.15) X-Spam-Score: 0.0 (/) X-Debbugs-Envelope-To: 70007 Cc: casouri@HIDDEN, 70007 <at> debbugs.gnu.org X-BeenThere: debbugs-submit <at> debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: <debbugs-submit.debbugs.gnu.org> List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe> List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/> List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org> List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help> List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe> Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org> X-Spam-Score: -1.0 (-) 30 mars 2024 kl. 17.37 skrev Eli Zaretskii <eliz@HIDDEN>: > 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.
bug-gnu-emacs@HIDDEN
:bug#70007
; Package emacs
.
Full text available.Received: (at submit) by debbugs.gnu.org; 30 Mar 2024 16:46:19 +0000 From debbugs-submit-bounces <at> debbugs.gnu.org Sat Mar 30 12:46:19 2024 Received: from localhost ([127.0.0.1]:46104 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1rqbqV-0001dO-Bl for submit <at> 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 <geb-bug-gnu-emacs@HIDDEN>) id 1rqbqT-0001cP-5Q for submit <at> 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 <geb-bug-gnu-emacs@HIDDEN>) id 1rqbqL-0004iY-QS for bug-gnu-emacs@HIDDEN; 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 <geb-bug-gnu-emacs@HIDDEN>) id 1rqbqK-00024z-Iz for bug-gnu-emacs@HIDDEN; Sat, 30 Mar 2024 12:46:09 -0400 Received: from list by ciao.gmane.io with local (Exim 4.92) (envelope-from <geb-bug-gnu-emacs@HIDDEN>) id 1rqbqF-0005Fo-TM for bug-gnu-emacs@HIDDEN; Sat, 30 Mar 2024 17:46:03 +0100 X-Injected-Via-Gmane: http://gmane.org/ To: bug-gnu-emacs@HIDDEN From: Andy Moreton <andrewjmoreton@HIDDEN> Subject: Re: bug#70007: [PATCH] native JSON encoder Date: Sat, 30 Mar 2024 16:45:54 +0000 Message-ID: <86r0fr3by5.fsf@HIDDEN> References: <1BF559D1-DB9F-4FEB-90ED-72E0EFD76424@HIDDEN> <86wmpphrg7.fsf@HIDDEN> <C6944977-0CF9-4D19-9D92-EA1F086700D7@HIDDEN> <4589243D-C11A-45C1-AF3E-6F4A5BADEB54@HIDDEN> <864jcrindg.fsf@HIDDEN> <291DD5F1-85B8-4647-A40A-EBBD4C51E253@HIDDEN> <8634sbijfx.fsf@HIDDEN> <2CF47DA5-A65B-47C4-A28A-6FEE1469BD13@HIDDEN> <86cyrdfuai.fsf@HIDDEN> <3139C8FE-5C67-4FE3-B940-F449DA73E76C@HIDDEN> <86le5zdfbi.fsf@HIDDEN> <E07F73AC-A127-4E6D-A86F-0FB303F2BB48@HIDDEN> <f55f685b-03c2-5132-c32d-3e0127816fd0@HIDDEN> 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@HIDDEN; 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 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 [...] 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-Debbugs-Envelope-To: submit X-BeenThere: debbugs-submit <at> debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: <debbugs-submit.debbugs.gnu.org> List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe> List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/> List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org> List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help> List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe> Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org> 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': > <artificial>:(.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
bug-gnu-emacs@HIDDEN
:bug#70007
; Package emacs
.
Full text available.Received: (at 70007) by debbugs.gnu.org; 30 Mar 2024 16:41:02 +0000 From debbugs-submit-bounces <at> debbugs.gnu.org Sat Mar 30 12:41:02 2024 Received: from localhost ([127.0.0.1]:46095 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1rqblO-0001LA-56 for submit <at> 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 <eliz@HIDDEN>) id 1rqblM-0001KT-AU for 70007 <at> 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 <eliz@HIDDEN>) 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@HIDDEN> From: Eli Zaretskii <eliz@HIDDEN> To: Richard Copley <rcopley@HIDDEN> In-Reply-To: <f55f685b-03c2-5132-c32d-3e0127816fd0@HIDDEN> (message from Richard Copley on Sat, 30 Mar 2024 16:14:45 +0000) Subject: Re: bug#70007: [PATCH] native JSON encoder References: <1BF559D1-DB9F-4FEB-90ED-72E0EFD76424@HIDDEN> <86wmpphrg7.fsf@HIDDEN> <C6944977-0CF9-4D19-9D92-EA1F086700D7@HIDDEN> <4589243D-C11A-45C1-AF3E-6F4A5BADEB54@HIDDEN> <864jcrindg.fsf@HIDDEN> <291DD5F1-85B8-4647-A40A-EBBD4C51E253@HIDDEN> <8634sbijfx.fsf@HIDDEN> <2CF47DA5-A65B-47C4-A28A-6FEE1469BD13@HIDDEN> <86cyrdfuai.fsf@HIDDEN> <3139C8FE-5C67-4FE3-B940-F449DA73E76C@HIDDEN> <86le5zdfbi.fsf@HIDDEN> <E07F73AC-A127-4E6D-A86F-0FB303F2BB48@HIDDEN> <f55f685b-03c2-5132-c32d-3e0127816fd0@HIDDEN> MIME-version: 1.0 Content-type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Spam-Score: -2.3 (--) X-Debbugs-Envelope-To: 70007 Cc: mattias.engdegard@HIDDEN, 70007 <at> debbugs.gnu.org X-BeenThere: debbugs-submit <at> debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: <debbugs-submit.debbugs.gnu.org> List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe> List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/> List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org> List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help> List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe> Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org> X-Spam-Score: -3.3 (---) > Cc: 70007 <at> debbugs.gnu.org > Date: Sat, 30 Mar 2024 16:14:45 +0000 > From: Richard Copley <rcopley@HIDDEN> > > 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': > <artificial>:(.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.
bug-gnu-emacs@HIDDEN
:bug#70007
; Package emacs
.
Full text available.Received: (at 70007) by debbugs.gnu.org; 30 Mar 2024 16:37:23 +0000 From debbugs-submit-bounces <at> debbugs.gnu.org Sat Mar 30 12:37:23 2024 Received: from localhost ([127.0.0.1]:46080 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1rqbhq-00017W-Tq for submit <at> 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 <eliz@HIDDEN>) id 1rqbhp-00017K-II for 70007 <at> 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 <eliz@HIDDEN>) 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@HIDDEN> From: Eli Zaretskii <eliz@HIDDEN> To: Mattias =?utf-8?Q?Engdeg=C3=A5rd?= <mattias.engdegard@HIDDEN> In-Reply-To: <E07F73AC-A127-4E6D-A86F-0FB303F2BB48@HIDDEN> (message from Mattias =?utf-8?Q?Engdeg=C3=A5rd?= on Sat, 30 Mar 2024 15:22:34 +0100) Subject: Re: bug#70007: [PATCH] native JSON encoder References: <1BF559D1-DB9F-4FEB-90ED-72E0EFD76424@HIDDEN> <86wmpphrg7.fsf@HIDDEN> <C6944977-0CF9-4D19-9D92-EA1F086700D7@HIDDEN> <4589243D-C11A-45C1-AF3E-6F4A5BADEB54@HIDDEN> <864jcrindg.fsf@HIDDEN> <291DD5F1-85B8-4647-A40A-EBBD4C51E253@HIDDEN> <8634sbijfx.fsf@HIDDEN> <2CF47DA5-A65B-47C4-A28A-6FEE1469BD13@HIDDEN> <86cyrdfuai.fsf@HIDDEN> <3139C8FE-5C67-4FE3-B940-F449DA73E76C@HIDDEN> <86le5zdfbi.fsf@HIDDEN> <E07F73AC-A127-4E6D-A86F-0FB303F2BB48@HIDDEN> MIME-version: 1.0 Content-type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Spam-Score: -2.3 (--) X-Debbugs-Envelope-To: 70007 Cc: casouri@HIDDEN, 70007 <at> debbugs.gnu.org X-BeenThere: debbugs-submit <at> debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: <debbugs-submit.debbugs.gnu.org> List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe> List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/> List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org> List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help> List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe> Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org> X-Spam-Score: -3.3 (---) > From: Mattias Engdegård <mattias.engdegard@HIDDEN> > Date: Sat, 30 Mar 2024 15:22:34 +0100 > Cc: casouri@HIDDEN, > 70007 <at> 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.
bug-gnu-emacs@HIDDEN
:bug#70007
; Package emacs
.
Full text available.Received: (at 70007) by debbugs.gnu.org; 30 Mar 2024 16:15:00 +0000 From debbugs-submit-bounces <at> debbugs.gnu.org Sat Mar 30 12:14:59 2024 Received: from localhost ([127.0.0.1]:46070 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1rqbMB-0008V7-KH for submit <at> 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 <rcopley@HIDDEN>) id 1rqbM8-0008Ui-C9 for 70007 <at> 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 <at> 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: <f55f685b-03c2-5132-c32d-3e0127816fd0@HIDDEN> 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 Subject: Re: bug#70007: [PATCH] native JSON encoder To: =?UTF-8?Q?Mattias_Engdeg=c3=a5rd?= <mattias.engdegard@HIDDEN> References: <1BF559D1-DB9F-4FEB-90ED-72E0EFD76424@HIDDEN> <86wmpphrg7.fsf@HIDDEN> <C6944977-0CF9-4D19-9D92-EA1F086700D7@HIDDEN> <4589243D-C11A-45C1-AF3E-6F4A5BADEB54@HIDDEN> <864jcrindg.fsf@HIDDEN> <291DD5F1-85B8-4647-A40A-EBBD4C51E253@HIDDEN> <8634sbijfx.fsf@HIDDEN> <2CF47DA5-A65B-47C4-A28A-6FEE1469BD13@HIDDEN> <86cyrdfuai.fsf@HIDDEN> <3139C8FE-5C67-4FE3-B940-F449DA73E76C@HIDDEN> <86le5zdfbi.fsf@HIDDEN> <E07F73AC-A127-4E6D-A86F-0FB303F2BB48@HIDDEN> From: Richard Copley <rcopley@HIDDEN> In-Reply-To: <E07F73AC-A127-4E6D-A86F-0FB303F2BB48@HIDDEN> Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 8bit X-Spam-Score: -3.0 (---) X-Debbugs-Envelope-To: 70007 Cc: 70007 <at> debbugs.gnu.org X-BeenThere: debbugs-submit <at> debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: <debbugs-submit.debbugs.gnu.org> List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe> List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/> List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org> List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help> List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe> Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org> 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': <artificial>:(.text.startup+0x39a9): undefined reference to `syms_of_json' collect2: error: ld returned 1 exit status make[2]: *** [Makefile:739: temacs] Error 1
bug-gnu-emacs@HIDDEN
:bug#70007
; Package emacs
.
Full text available.Received: (at 70007) by debbugs.gnu.org; 30 Mar 2024 14:22:49 +0000 From debbugs-submit-bounces <at> debbugs.gnu.org Sat Mar 30 10:22:49 2024 Received: from localhost ([127.0.0.1]:45936 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1rqZbc-00036p-7e for submit <at> 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 <mattias.engdegard@HIDDEN>) id 1rqZbZ-00036D-4a for 70007 <at> 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 <at> 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\)) Subject: Re: bug#70007: [PATCH] native JSON encoder From: =?utf-8?Q?Mattias_Engdeg=C3=A5rd?= <mattias.engdegard@HIDDEN> In-Reply-To: <86le5zdfbi.fsf@HIDDEN> Date: Sat, 30 Mar 2024 15:22:34 +0100 Content-Transfer-Encoding: quoted-printable Message-Id: <E07F73AC-A127-4E6D-A86F-0FB303F2BB48@HIDDEN> References: <1BF559D1-DB9F-4FEB-90ED-72E0EFD76424@HIDDEN> <86wmpphrg7.fsf@HIDDEN> <C6944977-0CF9-4D19-9D92-EA1F086700D7@HIDDEN> <4589243D-C11A-45C1-AF3E-6F4A5BADEB54@HIDDEN> <864jcrindg.fsf@HIDDEN> <291DD5F1-85B8-4647-A40A-EBBD4C51E253@HIDDEN> <8634sbijfx.fsf@HIDDEN> <2CF47DA5-A65B-47C4-A28A-6FEE1469BD13@HIDDEN> <86cyrdfuai.fsf@HIDDEN> <3139C8FE-5C67-4FE3-B940-F449DA73E76C@HIDDEN> <86le5zdfbi.fsf@HIDDEN> To: Eli Zaretskii <eliz@HIDDEN> X-Mailer: Apple Mail (2.3654.120.0.1.15) X-Spam-Score: 0.0 (/) X-Debbugs-Envelope-To: 70007 Cc: casouri@HIDDEN, 70007 <at> debbugs.gnu.org X-BeenThere: debbugs-submit <at> debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: <debbugs-submit.debbugs.gnu.org> List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe> List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/> List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org> List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help> List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe> Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org> X-Spam-Score: -1.0 (-) 30 mars 2024 kl. 14.22 skrev Eli Zaretskii <eliz@HIDDEN>: > 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.
bug-gnu-emacs@HIDDEN
:bug#70007
; Package emacs
.
Full text available.Received: (at 70007) by debbugs.gnu.org; 30 Mar 2024 13:23:12 +0000 From debbugs-submit-bounces <at> debbugs.gnu.org Sat Mar 30 09:23:12 2024 Received: from localhost ([127.0.0.1]:44203 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1rqYfv-0007pi-MA for submit <at> 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 <eliz@HIDDEN>) id 1rqYfs-0007pF-QE for 70007 <at> 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 <eliz@HIDDEN>) 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@HIDDEN> From: Eli Zaretskii <eliz@HIDDEN> To: Mattias =?utf-8?Q?Engdeg=C3=A5rd?= <mattias.engdegard@HIDDEN> In-Reply-To: <3139C8FE-5C67-4FE3-B940-F449DA73E76C@HIDDEN> (message from Mattias =?utf-8?Q?Engdeg=C3=A5rd?= on Sat, 30 Mar 2024 12:41:31 +0100) Subject: Re: bug#70007: [PATCH] native JSON encoder References: <1BF559D1-DB9F-4FEB-90ED-72E0EFD76424@HIDDEN> <86wmpphrg7.fsf@HIDDEN> <C6944977-0CF9-4D19-9D92-EA1F086700D7@HIDDEN> <4589243D-C11A-45C1-AF3E-6F4A5BADEB54@HIDDEN> <864jcrindg.fsf@HIDDEN> <291DD5F1-85B8-4647-A40A-EBBD4C51E253@HIDDEN> <8634sbijfx.fsf@HIDDEN> <2CF47DA5-A65B-47C4-A28A-6FEE1469BD13@HIDDEN> <86cyrdfuai.fsf@HIDDEN> <3139C8FE-5C67-4FE3-B940-F449DA73E76C@HIDDEN> MIME-version: 1.0 Content-type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Spam-Score: -2.3 (--) X-Debbugs-Envelope-To: 70007 Cc: casouri@HIDDEN, 70007 <at> debbugs.gnu.org X-BeenThere: debbugs-submit <at> debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: <debbugs-submit.debbugs.gnu.org> List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe> List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/> List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org> List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help> List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe> Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org> X-Spam-Score: -3.3 (---) > From: Mattias Engdegård <mattias.engdegard@HIDDEN> > Date: Sat, 30 Mar 2024 12:41:31 +0100 > Cc: casouri@HIDDEN, > 70007 <at> debbugs.gnu.org > > 29 mars 2024 kl. 07.04 skrev Eli Zaretskii <eliz@HIDDEN>: > > > 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.
bug-gnu-emacs@HIDDEN
:bug#70007
; Package emacs
.
Full text available.Received: (at 70007) by debbugs.gnu.org; 30 Mar 2024 11:41:45 +0000 From debbugs-submit-bounces <at> debbugs.gnu.org Sat Mar 30 07:41:45 2024 Received: from localhost ([127.0.0.1]:44093 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1rqX5l-0002Zj-27 for submit <at> 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 <mattias.engdegard@HIDDEN>) id 1rqX5h-0002ZO-N2 for 70007 <at> 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 <at> 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: =?utf-8?Q?Mattias_Engdeg=C3=A5rd?= <mattias.engdegard@HIDDEN> Message-Id: <3139C8FE-5C67-4FE3-B940-F449DA73E76C@HIDDEN> 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\)) Subject: Re: bug#70007: [PATCH] native JSON encoder Date: Sat, 30 Mar 2024 12:41:31 +0100 In-Reply-To: <86cyrdfuai.fsf@HIDDEN> To: Eli Zaretskii <eliz@HIDDEN> References: <1BF559D1-DB9F-4FEB-90ED-72E0EFD76424@HIDDEN> <86wmpphrg7.fsf@HIDDEN> <C6944977-0CF9-4D19-9D92-EA1F086700D7@HIDDEN> <4589243D-C11A-45C1-AF3E-6F4A5BADEB54@HIDDEN> <864jcrindg.fsf@HIDDEN> <291DD5F1-85B8-4647-A40A-EBBD4C51E253@HIDDEN> <8634sbijfx.fsf@HIDDEN> <2CF47DA5-A65B-47C4-A28A-6FEE1469BD13@HIDDEN> <86cyrdfuai.fsf@HIDDEN> X-Mailer: Apple Mail (2.3654.120.0.1.15) X-Spam-Score: 0.0 (/) X-Debbugs-Envelope-To: 70007 Cc: casouri@HIDDEN, 70007 <at> debbugs.gnu.org X-BeenThere: debbugs-submit <at> debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: <debbugs-submit.debbugs.gnu.org> List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe> List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/> List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org> List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help> List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe> Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org> 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 <eliz@HIDDEN>: > 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= <mattiase@HIDDEN>=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<stdlib.h>=0A=20= #include=20<math.h>=0A=20=0A-#include=20<jansson.h>=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<windows.h>=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--
bug-gnu-emacs@HIDDEN
:bug#70007
; Package emacs
.
Full text available.Received: (at 70007) by debbugs.gnu.org; 29 Mar 2024 06:04:35 +0000 From debbugs-submit-bounces <at> debbugs.gnu.org Fri Mar 29 02:04:35 2024 Received: from localhost ([127.0.0.1]:41557 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1rq5Lu-00072o-Q6 for submit <at> 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 <eliz@HIDDEN>) id 1rq5Lr-00072R-3F for 70007 <at> 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 <eliz@HIDDEN>) 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@HIDDEN> From: Eli Zaretskii <eliz@HIDDEN> To: Mattias =?utf-8?Q?Engdeg=C3=A5rd?= <mattias.engdegard@HIDDEN> In-Reply-To: <2CF47DA5-A65B-47C4-A28A-6FEE1469BD13@HIDDEN> (message from Mattias =?utf-8?Q?Engdeg=C3=A5rd?= on Thu, 28 Mar 2024 21:59:38 +0100) Subject: Re: bug#70007: [PATCH] native JSON encoder References: <1BF559D1-DB9F-4FEB-90ED-72E0EFD76424@HIDDEN> <86wmpphrg7.fsf@HIDDEN> <C6944977-0CF9-4D19-9D92-EA1F086700D7@HIDDEN> <4589243D-C11A-45C1-AF3E-6F4A5BADEB54@HIDDEN> <864jcrindg.fsf@HIDDEN> <291DD5F1-85B8-4647-A40A-EBBD4C51E253@HIDDEN> <8634sbijfx.fsf@HIDDEN> <2CF47DA5-A65B-47C4-A28A-6FEE1469BD13@HIDDEN> MIME-version: 1.0 Content-type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Spam-Score: -2.3 (--) X-Debbugs-Envelope-To: 70007 Cc: casouri@HIDDEN, 70007 <at> debbugs.gnu.org X-BeenThere: debbugs-submit <at> debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: <debbugs-submit.debbugs.gnu.org> List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe> List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/> List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org> List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help> List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe> Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org> X-Spam-Score: -3.3 (---) > From: Mattias Engdegård <mattias.engdegard@HIDDEN> > Date: Thu, 28 Mar 2024 21:59:38 +0100 > Cc: casouri@HIDDEN, > 70007 <at> debbugs.gnu.org > > 27 mars 2024 kl. 20.05 skrev Eli Zaretskii <eliz@HIDDEN>: > > >>> 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.
bug-gnu-emacs@HIDDEN
:bug#70007
; Package emacs
.
Full text available.Received: (at 70007) by debbugs.gnu.org; 28 Mar 2024 20:59:52 +0000 From debbugs-submit-bounces <at> debbugs.gnu.org Thu Mar 28 16:59:52 2024 Received: from localhost ([127.0.0.1]:41240 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1rpwql-0005XA-Qm for submit <at> 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 <mattias.engdegard@HIDDEN>) id 1rpwqh-0005Wv-C9 for 70007 <at> 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 <at> 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\)) Subject: Re: bug#70007: [PATCH] native JSON encoder From: =?utf-8?Q?Mattias_Engdeg=C3=A5rd?= <mattias.engdegard@HIDDEN> In-Reply-To: <8634sbijfx.fsf@HIDDEN> Date: Thu, 28 Mar 2024 21:59:38 +0100 Content-Transfer-Encoding: quoted-printable Message-Id: <2CF47DA5-A65B-47C4-A28A-6FEE1469BD13@HIDDEN> References: <1BF559D1-DB9F-4FEB-90ED-72E0EFD76424@HIDDEN> <86wmpphrg7.fsf@HIDDEN> <C6944977-0CF9-4D19-9D92-EA1F086700D7@HIDDEN> <4589243D-C11A-45C1-AF3E-6F4A5BADEB54@HIDDEN> <864jcrindg.fsf@HIDDEN> <291DD5F1-85B8-4647-A40A-EBBD4C51E253@HIDDEN> <8634sbijfx.fsf@HIDDEN> To: Eli Zaretskii <eliz@HIDDEN> X-Mailer: Apple Mail (2.3654.120.0.1.15) X-Spam-Score: 0.0 (/) X-Debbugs-Envelope-To: 70007 Cc: casouri@HIDDEN, 70007 <at> debbugs.gnu.org X-BeenThere: debbugs-submit <at> debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: <debbugs-submit.debbugs.gnu.org> List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe> List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/> List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org> List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help> List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe> Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org> X-Spam-Score: -1.0 (-) 27 mars 2024 kl. 20.05 skrev Eli Zaretskii <eliz@HIDDEN>: >>> 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.
bug-gnu-emacs@HIDDEN
:bug#70007
; Package emacs
.
Full text available.Received: (at 70007) by debbugs.gnu.org; 28 Mar 2024 19:16:49 +0000 From debbugs-submit-bounces <at> debbugs.gnu.org Thu Mar 28 15:16:49 2024 Received: from localhost ([127.0.0.1]:41163 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1rpvF3-0007nu-HP for submit <at> 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 <theo@HIDDEN>) id 1rpvF1-0007nV-8f for 70007 <at> debbugs.gnu.org; Thu, 28 Mar 2024 15:16:48 -0400 X-Report-Abuse: Please report any abuse attempt to abuse@HIDDEN 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 <theo@HIDDEN> To: Eli Zaretskii <eliz@HIDDEN> Subject: Re: bug#70007: [PATCH] native JSON encoder In-Reply-To: <86wmpphrg7.fsf@HIDDEN> (Eli Zaretskii's message of "Tue, 26 Mar 2024 18:46:00 +0200") References: <1BF559D1-DB9F-4FEB-90ED-72E0EFD76424@HIDDEN> <86wmpphrg7.fsf@HIDDEN> Date: Thu, 28 Mar 2024 20:16:35 +0100 Message-ID: <87y1a29nfw.fsf@HIDDEN> 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-Debbugs-Envelope-To: 70007 Cc: Mattias =?utf-8?Q?Engdeg=C3=A5rd?= <mattias.engdegard@HIDDEN>, 70007 <at> debbugs.gnu.org X-BeenThere: debbugs-submit <at> debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: <debbugs-submit.debbugs.gnu.org> List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe> List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/> List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org> List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help> List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe> Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org> X-Spam-Score: -1.0 (-) Eli Zaretskii <eliz@HIDDEN> writes: >> From: Mattias Engdeg=C3=A5rd <mattias.engdegard@HIDDEN> >> 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
bug-gnu-emacs@HIDDEN
:bug#70007
; Package emacs
.
Full text available.Received: (at 70007) by debbugs.gnu.org; 27 Mar 2024 19:06:09 +0000 From debbugs-submit-bounces <at> debbugs.gnu.org Wed Mar 27 15:06:09 2024 Received: from localhost ([127.0.0.1]:38365 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1rpYbB-0003XH-8N for submit <at> 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 <eliz@HIDDEN>) id 1rpYb6-0003WD-Dh for 70007 <at> 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 <eliz@HIDDEN>) 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@HIDDEN> From: Eli Zaretskii <eliz@HIDDEN> To: Mattias =?utf-8?Q?Engdeg=C3=A5rd?= <mattias.engdegard@HIDDEN> In-Reply-To: <291DD5F1-85B8-4647-A40A-EBBD4C51E253@HIDDEN> (message from Mattias =?utf-8?Q?Engdeg=C3=A5rd?= on Wed, 27 Mar 2024 19:57:24 +0100) Subject: Re: bug#70007: [PATCH] native JSON encoder References: <1BF559D1-DB9F-4FEB-90ED-72E0EFD76424@HIDDEN> <86wmpphrg7.fsf@HIDDEN> <C6944977-0CF9-4D19-9D92-EA1F086700D7@HIDDEN> <4589243D-C11A-45C1-AF3E-6F4A5BADEB54@HIDDEN> <864jcrindg.fsf@HIDDEN> <291DD5F1-85B8-4647-A40A-EBBD4C51E253@HIDDEN> MIME-version: 1.0 Content-type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Spam-Score: -2.3 (--) X-Debbugs-Envelope-To: 70007 Cc: casouri@HIDDEN, 70007 <at> debbugs.gnu.org X-BeenThere: debbugs-submit <at> debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: <debbugs-submit.debbugs.gnu.org> List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe> List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/> List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org> List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help> List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe> Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org> X-Spam-Score: -3.3 (---) > From: Mattias Engdegård <mattias.engdegard@HIDDEN> > Date: Wed, 27 Mar 2024 19:57:24 +0100 > Cc: Yuan Fu <casouri@HIDDEN>, > 70007 <at> 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.
bug-gnu-emacs@HIDDEN
:bug#70007
; Package emacs
.
Full text available.Received: (at 70007) by debbugs.gnu.org; 27 Mar 2024 18:57:39 +0000 From debbugs-submit-bounces <at> debbugs.gnu.org Wed Mar 27 14:57:39 2024 Received: from localhost ([127.0.0.1]:38360 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1rpYSx-0002uI-3k for submit <at> 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 <mattias.engdegard@HIDDEN>) id 1rpYSt-0002tc-Fq for 70007 <at> 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 <at> 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\)) Subject: Re: bug#70007: [PATCH] native JSON encoder From: =?utf-8?Q?Mattias_Engdeg=C3=A5rd?= <mattias.engdegard@HIDDEN> In-Reply-To: <864jcrindg.fsf@HIDDEN> Date: Wed, 27 Mar 2024 19:57:24 +0100 Content-Transfer-Encoding: quoted-printable Message-Id: <291DD5F1-85B8-4647-A40A-EBBD4C51E253@HIDDEN> References: <1BF559D1-DB9F-4FEB-90ED-72E0EFD76424@HIDDEN> <86wmpphrg7.fsf@HIDDEN> <C6944977-0CF9-4D19-9D92-EA1F086700D7@HIDDEN> <4589243D-C11A-45C1-AF3E-6F4A5BADEB54@HIDDEN> <864jcrindg.fsf@HIDDEN> To: Eli Zaretskii <eliz@HIDDEN> X-Mailer: Apple Mail (2.3654.120.0.1.15) X-Spam-Score: 0.0 (/) X-Debbugs-Envelope-To: 70007 Cc: Yuan Fu <casouri@HIDDEN>, 70007 <at> debbugs.gnu.org X-BeenThere: debbugs-submit <at> debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: <debbugs-submit.debbugs.gnu.org> List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe> List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/> List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org> List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help> List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe> Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org> X-Spam-Score: -1.0 (-) Eli, thank you for your comments! 27 mars 2024 kl. 18.40 skrev Eli Zaretskii <eliz@HIDDEN>: >> +/* 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.
bug-gnu-emacs@HIDDEN
:bug#70007
; Package emacs
.
Full text available.Received: (at 70007) by debbugs.gnu.org; 27 Mar 2024 17:41:12 +0000 From debbugs-submit-bounces <at> debbugs.gnu.org Wed Mar 27 13:41:12 2024 Received: from localhost ([127.0.0.1]:38330 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1rpXGy-0004zc-1a for submit <at> 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 <eliz@HIDDEN>) id 1rpXGv-0004z2-8D for 70007 <at> 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 <eliz@HIDDEN>) 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@HIDDEN> From: Eli Zaretskii <eliz@HIDDEN> To: Mattias =?utf-8?Q?Engdeg=C3=A5rd?= <mattias.engdegard@HIDDEN>, Yuan Fu <casouri@HIDDEN> In-Reply-To: <4589243D-C11A-45C1-AF3E-6F4A5BADEB54@HIDDEN> (message from Mattias =?utf-8?Q?Engdeg=C3=A5rd?= on Wed, 27 Mar 2024 16:49:53 +0100) Subject: Re: bug#70007: [PATCH] native JSON encoder References: <1BF559D1-DB9F-4FEB-90ED-72E0EFD76424@HIDDEN> <86wmpphrg7.fsf@HIDDEN> <C6944977-0CF9-4D19-9D92-EA1F086700D7@HIDDEN> <4589243D-C11A-45C1-AF3E-6F4A5BADEB54@HIDDEN> MIME-version: 1.0 Content-type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Spam-Score: -2.3 (--) X-Debbugs-Envelope-To: 70007 Cc: 70007 <at> debbugs.gnu.org X-BeenThere: debbugs-submit <at> debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: <debbugs-submit.debbugs.gnu.org> List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe> List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/> List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org> List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help> List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe> Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org> X-Spam-Score: -3.3 (---) > From: Mattias Engdegård <mattias.engdegard@HIDDEN> > Date: Wed, 27 Mar 2024 16:49:53 +0100 > Cc: 70007 <at> 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?
bug-gnu-emacs@HIDDEN
:bug#70007
; Package emacs
.
Full text available.Received: (at 70007) by debbugs.gnu.org; 27 Mar 2024 15:50:05 +0000 From debbugs-submit-bounces <at> debbugs.gnu.org Wed Mar 27 11:50:05 2024 Received: from localhost ([127.0.0.1]:38214 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1rpVXQ-0004ZN-Hv for submit <at> 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 <mattias.engdegard@HIDDEN>) id 1rpVXN-0004YB-5Y for 70007 <at> 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 <at> 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: =?utf-8?Q?Mattias_Engdeg=C3=A5rd?= <mattias.engdegard@HIDDEN> Message-Id: <4589243D-C11A-45C1-AF3E-6F4A5BADEB54@HIDDEN> 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\)) Subject: Re: bug#70007: [PATCH] native JSON encoder Date: Wed, 27 Mar 2024 16:49:53 +0100 In-Reply-To: <C6944977-0CF9-4D19-9D92-EA1F086700D7@HIDDEN> To: Eli Zaretskii <eliz@HIDDEN> References: <1BF559D1-DB9F-4FEB-90ED-72E0EFD76424@HIDDEN> <86wmpphrg7.fsf@HIDDEN> <C6944977-0CF9-4D19-9D92-EA1F086700D7@HIDDEN> X-Mailer: Apple Mail (2.3654.120.0.1.15) X-Spam-Score: 0.0 (/) X-Debbugs-Envelope-To: 70007 Cc: 70007 <at> debbugs.gnu.org X-BeenThere: debbugs-submit <at> debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: <debbugs-submit.debbugs.gnu.org> List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe> List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/> List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org> List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help> List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe> Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org> 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<stddef.h>=0A=20= #include=20<stdint.h>=0A=20#include=20<stdlib.h>=0A+#include=20<math.h>=0A= =20=0A=20#include=20<jansson.h>=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--
bug-gnu-emacs@HIDDEN
:bug#70007
; Package emacs
.
Full text available.Received: (at 70007) by debbugs.gnu.org; 27 Mar 2024 12:46:27 +0000 From debbugs-submit-bounces <at> debbugs.gnu.org Wed Mar 27 08:46:27 2024 Received: from localhost ([127.0.0.1]:36023 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1rpSfj-0002ij-Af for submit <at> 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 <mattias.engdegard@HIDDEN>) id 1rpSfh-0002ht-5k for 70007 <at> 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 <at> 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\)) Subject: Re: bug#70007: [PATCH] native JSON encoder From: =?utf-8?Q?Mattias_Engdeg=C3=A5rd?= <mattias.engdegard@HIDDEN> In-Reply-To: <86wmpphrg7.fsf@HIDDEN> Date: Wed, 27 Mar 2024 13:46:17 +0100 Content-Transfer-Encoding: quoted-printable Message-Id: <C6944977-0CF9-4D19-9D92-EA1F086700D7@HIDDEN> References: <1BF559D1-DB9F-4FEB-90ED-72E0EFD76424@HIDDEN> <86wmpphrg7.fsf@HIDDEN> To: Eli Zaretskii <eliz@HIDDEN> X-Mailer: Apple Mail (2.3654.120.0.1.15) X-Spam-Score: 0.0 (/) X-Debbugs-Envelope-To: 70007 Cc: 70007 <at> debbugs.gnu.org X-BeenThere: debbugs-submit <at> debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: <debbugs-submit.debbugs.gnu.org> List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe> List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/> List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org> List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help> List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe> Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org> X-Spam-Score: -1.0 (-) 26 mars 2024 kl. 17.46 skrev Eli Zaretskii <eliz@HIDDEN>: >> - 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.
bug-gnu-emacs@HIDDEN
:bug#70007
; Package emacs
.
Full text available.Received: (at 70007) by debbugs.gnu.org; 26 Mar 2024 16:46:26 +0000 From debbugs-submit-bounces <at> debbugs.gnu.org Tue Mar 26 12:46:26 2024 Received: from localhost ([127.0.0.1]:34791 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1rp9wQ-0005LO-Gt for submit <at> 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 <eliz@HIDDEN>) id 1rp9wO-0005Kr-0r for 70007 <at> 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 <eliz@HIDDEN>) 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@HIDDEN> From: Eli Zaretskii <eliz@HIDDEN> To: Mattias =?utf-8?Q?Engdeg=C3=A5rd?= <mattias.engdegard@HIDDEN> In-Reply-To: <1BF559D1-DB9F-4FEB-90ED-72E0EFD76424@HIDDEN> (message from Mattias =?utf-8?Q?Engdeg=C3=A5rd?= on Tue, 26 Mar 2024 16:33:52 +0100) Subject: Re: bug#70007: [PATCH] native JSON encoder References: <1BF559D1-DB9F-4FEB-90ED-72E0EFD76424@HIDDEN> MIME-version: 1.0 Content-type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Spam-Score: -2.3 (--) X-Debbugs-Envelope-To: 70007 Cc: 70007 <at> debbugs.gnu.org X-BeenThere: debbugs-submit <at> debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: <debbugs-submit.debbugs.gnu.org> List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe> List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/> List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org> List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help> List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe> Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org> X-Spam-Score: -3.3 (---) > From: Mattias Engdegård <mattias.engdegard@HIDDEN> > 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.
bug-gnu-emacs@HIDDEN
:bug#70007
; Package emacs
.
Full text available.Received: (at submit) by debbugs.gnu.org; 26 Mar 2024 15:34:32 +0000 From debbugs-submit-bounces <at> debbugs.gnu.org Tue Mar 26 11:34:32 2024 Received: from localhost ([127.0.0.1]:34488 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1rp8op-00028V-Kg for submit <at> 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 <mattias.engdegard@HIDDEN>) id 1rp8on-00027b-9P for submit <at> 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 <mattias.engdegard@HIDDEN>) id 1rp8oQ-0000yM-Ok for bug-gnu-emacs@HIDDEN; 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 <mattias.engdegard@HIDDEN>) id 1rp8oI-0006Il-4c for bug-gnu-emacs@HIDDEN; Tue, 26 Mar 2024 11:34:01 -0400 Received: by mail-lj1-x22f.google.com with SMTP id 38308e7fff4ca-2d6ee81bc87so6440421fa.1 for <bug-gnu-emacs@HIDDEN>; 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 <bug-gnu-emacs@HIDDEN> (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Tue, 26 Mar 2024 08:33:53 -0700 (PDT) From: =?utf-8?Q?Mattias_Engdeg=C3=A5rd?= <mattias.engdegard@HIDDEN> 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\)) Subject: [PATCH] native JSON encoder Message-Id: <1BF559D1-DB9F-4FEB-90ED-72E0EFD76424@HIDDEN> Date: Tue, 26 Mar 2024 16:33:52 +0100 To: Emacs Bug Report <bug-gnu-emacs@HIDDEN> X-Mailer: Apple Mail (2.3654.120.0.1.15) Received-SPF: pass client-ip=2a00:1450:4864:20::22f; envelope-from=mattias.engdegard@HIDDEN; 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-Debbugs-Envelope-To: submit X-BeenThere: debbugs-submit <at> debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: <debbugs-submit.debbugs.gnu.org> List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe> List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/> List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org> List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help> List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe> Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org> 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<stddef.h>=0A=20= #include=20<stdint.h>=0A=20#include=20<stdlib.h>=0A+#include=20<math.h>=0A= =20=0A=20#include=20<jansson.h>=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--
Mattias Engdegård <mattias.engdegard@HIDDEN>
:bug-gnu-emacs@HIDDEN
.
Full text available.bug-gnu-emacs@HIDDEN
:bug#70007
; Package emacs
.
Full text available.
GNU bug tracking system
Copyright (C) 1999 Darren O. Benham,
1997 nCipher Corporation Ltd,
1994-97 Ian Jackson.