texlive[73581] Master/texmf-dist: jsonparse (24jan25)

commits+karl at tug.org commits+karl at tug.org
Fri Jan 24 22:05:57 CET 2025


Revision: 73581
          https://tug.org/svn/texlive?view=revision&revision=73581
Author:   karl
Date:     2025-01-24 22:05:57 +0100 (Fri, 24 Jan 2025)
Log Message:
-----------
jsonparse (24jan25)

Modified Paths:
--------------
    trunk/Master/texmf-dist/doc/latex/jsonparse/README.md
    trunk/Master/texmf-dist/doc/latex/jsonparse/jason/jason.tex
    trunk/Master/texmf-dist/doc/latex/jsonparse/jsonparse-doc.pdf
    trunk/Master/texmf-dist/doc/latex/jsonparse/jsonparse-doc.tex
    trunk/Master/texmf-dist/tex/latex/jsonparse/jsonparse.sty

Modified: trunk/Master/texmf-dist/doc/latex/jsonparse/README.md
===================================================================
--- trunk/Master/texmf-dist/doc/latex/jsonparse/README.md	2025-01-24 21:05:48 UTC (rev 73580)
+++ trunk/Master/texmf-dist/doc/latex/jsonparse/README.md	2025-01-24 21:05:57 UTC (rev 73581)
@@ -1,4 +1,4 @@
-![Version 1.0.1](https://img.shields.io/badge/version-1.0.1-blue)
+![Version 1.0.2](https://img.shields.io/badge/version-1.0.2-blue)
 
 ![Jason, the JSON parsing horse](https://github.com/jasperhabicht/jsonparse/assets/6378801/ddfddc70-bf5f-4121-ba45-4b9128875d85)
 

Modified: trunk/Master/texmf-dist/doc/latex/jsonparse/jason/jason.tex
===================================================================
--- trunk/Master/texmf-dist/doc/latex/jsonparse/jason/jason.tex	2025-01-24 21:05:48 UTC (rev 73580)
+++ trunk/Master/texmf-dist/doc/latex/jsonparse/jason/jason.tex	2025-01-24 21:05:57 UTC (rev 73581)
@@ -27,7 +27,7 @@
 \draw_begin:
 
 % sky
-\cs_new:Npn \__jsonparse_jason_path_i: {
+\cs_new_protected:Npn \__jsonparse_jason_path_i: {
   \draw_path_moveto:n { 433.418 , 221.836 }
   \draw_path_curveto:nnn { 433.418 , 335.695 } { 341.117 , 428 } { 227.254 , 428 }
   \draw_path_curveto:nnn { 113.391 , 428 } { 21.086 , 335.695 } { 21.086 , 221.836 }
@@ -37,7 +37,7 @@
 }
 
 % head
-\cs_new:Npn \__jsonparse_jason_path_ii: {
+\cs_new_protected:Npn \__jsonparse_jason_path_ii: {
   \draw_path_moveto:n { 406.586 , 385.5 }
   \draw_path_curveto:nnn { 406.586 , 385.5 } { 396.254 , 373.168 } { 370.586 , 298.836 }
   \draw_path_curveto:nnn { 344.922 , 224.5 } { 332.254 , 185.168 } { 321.918 , 158.836 }
@@ -61,7 +61,7 @@
 }
 
 % mane
-\cs_new:Npn \__jsonparse_jason_path_iii: {
+\cs_new_protected:Npn \__jsonparse_jason_path_iii: {
   \draw_path_moveto:n { 453.754 , 303.168 }
   \draw_path_curveto:nnn { 453.754 , 303.168 } { 444.086 , 288.336 } { 432.086 , 282.168 }
   \draw_path_curveto:nnn { 420.676 , 276.305 } { 407.586 , 275 } { 407.586 , 275 }
@@ -85,7 +85,7 @@
 }
 
 % bangs
-\cs_new:Npn \__jsonparse_jason_path_iv: {
+\cs_new_protected:Npn \__jsonparse_jason_path_iv: {
   \draw_path_moveto:n { 255.586 , 71 }
   \draw_path_curveto:nnn { 244.922 , 61.336 } { 233.754 , 60.168 } { 224.918 , 59.836 }
   \draw_path_curveto:nnn { 209.812 , 59.266 } { 199.918 , 33.168 } { 199.918 , 33.168 }
@@ -110,7 +110,7 @@
 }
 
 % muzzle
-\cs_new:Npn \__jsonparse_jason_path_v: {
+\cs_new_protected:Npn \__jsonparse_jason_path_v: {
   \draw_path_moveto:n { 108.738 , 351.707 }
   \draw_path_curveto:nnn { 117.086 , 341.312 } { 128.648 , 326.078 } { 131.504 , 318.086 }
   \draw_path_curveto:nnn { 139.004 , 297.086 } { 130.254 , 287.336 } { 125.504 , 280.086 }
@@ -128,7 +128,7 @@
 }
 
 % head outline
-\cs_new:Npn \__jsonparse_jason_path_vi: {
+\cs_new_protected:Npn \__jsonparse_jason_path_vi: {
   \draw_path_moveto:n { 108.738 , 351.707 }
   \draw_path_curveto:nnn { 122.176 , 342.695 } { 136.945 , 331.641 } { 155.254 , 324.586 }
   \draw_path_curveto:nnn { 179.297 , 315.316 } { 219.527 , 312.707 } { 241.223 , 302.762 }
@@ -153,7 +153,7 @@
 }
 
 % ear
-\cs_new:Npn \__jsonparse_jason_path_vii: {
+\cs_new_protected:Npn \__jsonparse_jason_path_vii: {
   \draw_path_moveto:n { 177.586 , 74.5 }
   \draw_path_curveto:nnn { 177.586 , 74.5 } { 177.086 , 69.336 } { 167.418 , 59.336 }
   \draw_path_curveto:nnn { 165.707 , 57.562 } { 163.84 , 56.199 } { 161.93 , 55.145 }
@@ -174,7 +174,7 @@
 }
 
 % eye
-\cs_new:Npn \__jsonparse_jason_path_viii: {
+\cs_new_protected:Npn \__jsonparse_jason_path_viii: {
   \draw_path_moveto:n { 230.922 , 186.793 }
   \draw_path_curveto:nnn { 230.922 , 196.391 } { 222.188 , 204.168 } { 211.422 , 204.168 }
   \draw_path_curveto:nnn { 200.648 , 204.168 } { 191.922 , 196.391 } { 191.922 , 186.793 }
@@ -184,7 +184,7 @@
 }
 
 % pupil
-\cs_new:Npn \__jsonparse_jason_path_ix: {
+\cs_new_protected:Npn \__jsonparse_jason_path_ix: {
   \draw_path_moveto:n { 217.922 , 188.836 }
   \draw_path_curveto:nnn { 217.922 , 192.699 } { 214.375 , 195.836 } { 210.004 , 195.836 }
   \draw_path_curveto:nnn { 205.633 , 195.836 } { 202.086 , 192.699 } { 202.086 , 188.836 }
@@ -194,7 +194,7 @@
 }
 
 % nostril
-\cs_new:Npn \__jsonparse_jason_path_x: {
+\cs_new_protected:Npn \__jsonparse_jason_path_x: {
   \draw_path_moveto:n { 68.77 , 289.297 }
   \draw_path_curveto:nnn { 68.77 , 289.297 } { 71.215 , 285.078 } { 74.879 , 280.211 }
   \draw_path_curveto:nnn { 79.305 , 274.324 } { 87.262 , 269.184 } { 91.254 , 268.836 }
@@ -205,7 +205,7 @@
 }
 
 % mouth
-\cs_new:Npn \__jsonparse_jason_path_xi: {
+\cs_new_protected:Npn \__jsonparse_jason_path_xi: {
   \draw_path_moveto:n { 27.488 , 319.328 }
   \draw_path_curveto:nnn { 26.766 , 323.887 } { 26.395 , 330.605 } { 29.504 , 334.336 }
   \draw_path_curveto:nnn { 34.504 , 340.336 } { 44.004 , 349.336 } { 65.504 , 336.336 }
@@ -216,7 +216,7 @@
 }
 
 % mouth outline
-\cs_new:Npn \__jsonparse_jason_path_xii: {
+\cs_new_protected:Npn \__jsonparse_jason_path_xii: {
   \draw_path_moveto:n { 17.652 , 318.48 }
   \draw_path_curveto:nnn { 19.613 , 318.891 } { 21.801 , 319.188 } { 24.254 , 319.336 }
   \draw_path_curveto:nnn { 25.383 , 319.402 } { 26.453 , 319.395 } { 27.488 , 319.328 }
@@ -223,7 +223,7 @@
 }
 
 % teeth
-\cs_new:Npn \__jsonparse_jason_path_xiii: {
+\cs_new_protected:Npn \__jsonparse_jason_path_xiii: {
   \draw_path_moveto:n { 96.598 , 304.234 }
   \draw_path_curveto:nnn { 80.379 , 312.863 } { 52.5 , 327.137 } { 44.855 , 327.496 }
   \draw_path_curveto:nnn { 37.57 , 327.84 } { 31.289 , 322.75 } { 27.891 , 319.293 }

Modified: trunk/Master/texmf-dist/doc/latex/jsonparse/jsonparse-doc.pdf
===================================================================
(Binary files differ)

Modified: trunk/Master/texmf-dist/doc/latex/jsonparse/jsonparse-doc.tex
===================================================================
--- trunk/Master/texmf-dist/doc/latex/jsonparse/jsonparse-doc.tex	2025-01-24 21:05:48 UTC (rev 73580)
+++ trunk/Master/texmf-dist/doc/latex/jsonparse/jsonparse-doc.tex	2025-01-24 21:05:57 UTC (rev 73581)
@@ -11,8 +11,8 @@
 % This work has the LPPL maintenance status `maintained'.
 %
 \documentclass[a4paper]{article}
-\def\jsonparsefileversion{1.0.1}
-\def\jsonparsefiledate{21 January 2025}
+\def\jsonparsefileversion{1.0.2}
+\def\jsonparsefiledate{23 January 2025}
 
 \usepackage[T1]{fontenc}
 \usepackage{Alegreya}
@@ -216,6 +216,7 @@
 \changes{v0.9.12}{2025/01/17}{Bug fixes; adding commands to access items in arrays.}
 \changes{v1.0.0}{2025/01/20}{Streamlining of code, unification of command structure.}
 \changes{v1.0.1}{2025/01/21}{Fixes in documentation. Added user command for filtering.}
+\changes{v1.0.2}{2025/01/23}{Support for Unicode surrogate pairs.}
 
 \begin{document}
 \vspace*{-1cm}
@@ -254,8 +255,12 @@
 
 JSON strings cannot contain the two characters \macro{"} and \macro{\}. These two characters need to be escaped with a preceding backslash (\macro{\}).  This package therefore redefines locally the TeX control symbols \macro{\"}, \macro{\/}, \macro{\\}, \macro{\b}, \macro{\f}, \macro{\n}, \macro{\r}, \macro{\t} and \macro{\u}. These control symbols are prevented from expanding during parsing. For example, \macro{\"} is first defined as \macro{\exp_not:N \"} and only when typeset, \macro{\"} is expanded to \macro{"}, which ensures that strings are parsed properly.
 
-Similarly, the control symbol \macro{\/} expands eventually to \macro{/} and \macro{\\} to \macro{\c_backslash_str} (i.\,e. a backslash with category code 12). The escape sequence \macro{\u} followed by a hex value consisting of four digits eventually expands to \macro{\char"} followed by the relevant four hex digits. The JSON escape sequences \macro{\b}, \macro{\f}, \macro{\n}, \macro{\r} and \macro{\t} eventually expand to token variables of which the contents can be set using the relevant \macro{replacement} key. See more on setting options below in section \ref{sec:options}.
+Similarly, the control symbol \macro{\/} expands eventually to \macro{/} and \macro{\\} to \macro{\c_backslash_str} (i.\,e. a backslash with category code 12).
 
+The escape sequence \macro{\u} followed by a hex value consisting of four digits eventually expands to \macro{\codepoint_generate:nn} that creates the character represented by the relevant four hex digits with category code 12 (``other''). If two escape sequences \macro{\u} wit four hex digits each follow each other and together represent a Unicode surrogate pair, this surrogate pair is converted into the relevant Unicode codepoint.
+
+The JSON escape sequences \macro{\b}, \macro{\f}, \macro{\n}, \macro{\r} and \macro{\t} eventually expand to token variables of which the contents can be set using the relevant \macro{replacement} key. See more on setting options below in section \ref{sec:options}.
+
 It is possible to insert TeX macros to the JSON source that will eventually be parsed when typesetting. Backslashes of TeX macros need to be escaped by another backslash. The TeX macros \macro{\"} and \macro{\\} must be escaped twice in the JSON source so that they become \macro{\\\"} and \macro{\\\\} respectively.
 
 \begin{macrodef}
@@ -275,7 +280,7 @@
     \JSONParseValue{\myJSONdataB}{d.b}
 \end{codeexamplecolumns}
 
-Note that the control sequence \macro{\x} is replaced by the value exactly. Therefore, if the value happens to be a string, the control sequence \macro{\x} should be placed between quotation marks (\macro{"}) in order for the resulting string to be valid JSON. The control sequence \macro{\x} is only available inside the \macro{\JSONParse} command, but not inside the \macro{\JSONParseFromFile} command. 
+Note that the control sequence \macro{\x} is replaced by the value exactly. Therefore, if the value happens to be a string, the control sequence \macro{\x} should be placed between quotation marks (\macro{"}) in order for the resulting string to be valid JSON. The control sequence \macro{\x} is only available inside the \macro{\JSONParse} command, but not inside the \macro{\JSONParseFromFile} command.
 
 \begin{macrodef}
 |escape|={all}
@@ -347,7 +352,7 @@
 
 The first argument denotes the token variable where the value should be stored into. If this token variable has not yet been defined, it will be created by this command. The second argument represents the token variable (property list) that has been created using the commands \macro{\JSONParse} or \macro{\JSONParseFromFile} and that stores the parsed JSON data. The third argument takes the key to select the relevant value.
 
-The token list returned by this command is a string variable where all characters have category code 12 (``other''), except for spaces and (horizontal) tabs that have category code 10 (``space''). 
+The token list returned by this command is a string variable where all characters have category code 12 (``other''), except for spaces and (horizontal) tabs that have category code 10 (``space'').
 
 \begin{macrodef}
 |\JSONParseSetRescanValue|{<token variable>}{<token variable>}{<key>}
@@ -366,10 +371,8 @@
 \begin{macrodef}
 |\JSONParseKeys|{<token variable>}{<key>}
 \end{macrodef}
-The command \macro{\JSONParseSetKeys} is used to get all top-level keys of a JSON object as JSON array and return this array as string where all characters (except for spaces and tabs) have category code 12 (``other''). The first argument of the command takes the token variable that holds the parsed JSON data. The second argument takes the key to select the relevant entry from the parsed JSON data using JavaScript syntax. 
+The command \macro{\JSONParseSetKeys} is used to get all top-level keys of a JSON object as JSON array and return this array as string where all characters (except for spaces and tabs) have category code 12 (``other''). The first argument of the command takes the token variable that holds the parsed JSON data. The second argument takes the key to select the relevant entry from the parsed JSON data using JavaScript syntax.
 
-\textbf{Caution!} This command has been redefined in version 0.9.12 which affects the accepted arguments and return value.
-
 \begin{macrodef}
 |\JSONParseSetKeys|{<token variable>}{<token variable>}{<key>}
 \end{macrodef}
@@ -378,7 +381,7 @@
 \begin{macrodef}
 |\JSONParseFilter|{<token variable>}{<token variable>}{<key>}
 \end{macrodef}
-The command \macro{\JSONParseFilter} is used to select a part (such as an object or an array) of a JSON object or JSON array and parse this into a token variable (a property list). The first argument denotes the token variable where the value should be stored into. The second argument of the command takes the token variable that holds the parsed JSON data. The third argument takes the key to select the relevant entry from the parsed JSON data using JavaScript syntax. 
+The command \macro{\JSONParseFilter} is used to select a part (such as an object or an array) of a JSON object or JSON array and parse this into a token variable (a property list). The first argument denotes the token variable where the value should be stored into. The second argument of the command takes the token variable that holds the parsed JSON data. The third argument takes the key to select the relevant entry from the parsed JSON data using JavaScript syntax.
 
 \begin{macrodef}
 |\JSONParseArrayValues|[<options>]{<token variable>}{<key>}[<subkey>]{<string>}
@@ -409,7 +412,7 @@
 
 \begin{macrodef}
 |\JSONParseArrayValuesMap|[<options>]{<token variable>}{<key>}[<subkey>]
-    {<command name>}[<before code>][<after code>]
+  {<command name>}[<before code>][<after code>]
 \end{macrodef}
 The command \macro{\JSONParseArrayValuesMap} takes the same first three arguments as the command \macro{\JSONParseArrayValues} and works in a similar way. However, instead of a string that is added between the array items, it takes a command name as fourth argument. This command can be defined beforehand and will be called for every array item. Inside its definition, the commands \macro{\JSONParseArrayIndex}, \macro{\JSONParseArrayKey} and \macro{\JSONParseArrayValue} can be used which are updated for each item and output the index, the key and the value of the current item respectively. Note that these commands are defined globally to make accessing them as easy as possible.
 
@@ -539,7 +542,7 @@
 
 \begin{codeexample}
 \l_jsonparse_externalize_prefix_str \c_sys_jobname_str
-    \c_underscore_str \l_jsonparse_current_prop_str
+  \c_underscore_str \l_jsonparse_current_prop_str
 \end{codeexample}
 
 The token variable \macro{\l_jsonparse_externalize_prefix_str} contains the prefix that is set using the key \macro{externalize prefix}. \macro{\c_sys_jobname_str} holds the name of the current file (the current job name), \macro{\c_underscore_str} is an underscore and the token variable \macro{\l_jsonparse_current_prop_str} contains the name of the property list where the relevant JSON data is stored into.
@@ -623,7 +626,7 @@
 |\jsonparse_parse_keys:NN| <token variable> <string variable>
 \end{macrodef}
 The command \macro{\jsonparse_parse_keys:NN} processes the token variable given as the first arguments as property list and selects all top-level keys which are then stored in the string variable as JSON array. The pseudo key \macro{.} (or the string defined using the key \macro{child sep}) to select the complete JSON data is ignored. If the JSON data is an array, the indices (wrapped into the separators defined by \macro{separator/array left} and \macro{separator/array right}) of the items are used as keys.
-  
+
 \begin{macrodef}
 |\jsonparse_filter:Nn| <token variable> {<key>}
 \end{macrodef}
@@ -638,10 +641,38 @@
 |\jsonparse_if_num:nTF| {<string>} {<true code>} {<false code>}
 |\jsonparse_if_num:nT| {<string>} {<true code>}
 |\jsonparse_if_num:nF| {<string>} {<false code>}
-|\jsonparse_if_num_p:n| {<string>}
 \end{macrodef}
-The command \macro{\jsonparse_if_num:nTF} checks whether a string is a valid JSON number according the relevant specification. It executes the true code if the string is a valid JSON number and the false code if not. The variants \macro{\jsonparse_if_num:nT} and \macro{\jsonparse_if_num:nF} work accordingly. The command \macro{\jsonparse_if_num_p:n} returns a boolean true or false (i.\,e. \macro{\c_true_bool} or \macro{\c_false_bool}).
+The command \macro{\jsonparse_if_num:nTF} checks whether a string is a valid JSON number according the relevant specification. It executes the true code if the string is a valid JSON number and the false code if not. The variants \macro{\jsonparse_if_num:nT} and \macro{\jsonparse_if_num:nF} work accordingly.
 
+\begin{macrodef}
+|\jsonparse_unicode_if_high_surrogate:nTF| {<codepoint>}
+  {<true code>} {<false code>}
+|\jsonparse_unicode_if_high_surrogate:nT| {<codepoint>} {<true code>}
+|\jsonparse_unicode_if_high_surrogate:nF| {<codepoint>} {<false code>}
+|\jsonparse_unicode_if_high_surrogate_p:n| {<codepoint>}
+\end{macrodef}
+The command \macro{\jsonparse_unicode_if_high_surrogate:nTF} can be used to check whether a codepoint entered as argument (an integer that can be hexadecimal if preceded by \macro{"}) is in the range of \macro{"D800} and \macro{"DBFF} which means that it is the first part of a surrogate pair (a high surrogate). The variants that only provide an argument for the true or false case work accordingly. The command \macro{\jsonparse_unicode_if_high_surrogate_p:n} returns a boolean true or false (i.\,e. \macro{\c_true_bool} or \macro{\c_false_bool}).
+
+This conditional function is fully expandable.
+
+\begin{macrodef}
+|\jsonparse_unicode_if_low_surrogate:nTF| {<codepoint>}
+  {<true code>} {<false code>}
+|\jsonparse_unicode_if_low_surrogate:nT| {<codepoint>} {<true code>}
+|\jsonparse_unicode_if_low_surrogate:nF| {<codepoint>} {<false code>}
+|\jsonparse_unicode_if_low_surrogate_p:n| {<codepoint>}
+\end{macrodef}
+The command \macro{\jsonparse_unicode_if_low_surrogate:nTF} can be used to check whether a codepoint entered as argument (an integer that can be hexadecimal if preceded by \macro{"}) is in the range of \macro{"DC00} and \macro{"DFFF} which means that it is the last part of a surrogate pair (a low surrogate). The variants that only provide an argument for the true or false case work accordingly. The command \macro{\jsonparse_unicode_if_low_surrogate_p:n} returns a boolean true or false (i.\,e. \macro{\c_true_bool} or \macro{\c_false_bool}).
+
+This conditional function is fully expandable.
+
+\begin{macrodef}
+|\jsonparse_unicode_join_surrogate_pair:nn| {<codepoint>} {<codepoint>}
+\end{macrodef}
+The command \macro{\jsonparse_unicode_join_surrogate_pair:nn} coverts a surrogate pair to the relevant codepoint. It takes as first argument the codepoint of the low surrogate and as second argument the codepoint of the high surrogate. It does not check whether the codepoints actually belong to the relevant ranges of codepoints for high and low surrogates.
+
+This function is fully expandable.
+
 % =====
 
 \printchanges

Modified: trunk/Master/texmf-dist/tex/latex/jsonparse/jsonparse.sty
===================================================================
--- trunk/Master/texmf-dist/tex/latex/jsonparse/jsonparse.sty	2025-01-24 21:05:48 UTC (rev 73580)
+++ trunk/Master/texmf-dist/tex/latex/jsonparse/jsonparse.sty	2025-01-24 21:05:57 UTC (rev 73581)
@@ -10,7 +10,7 @@
 %
 % This work has the LPPL maintenance status `maintained'.
 %
-\ProvidesExplPackage {jsonparse} {2025-01-21} {1.0.1}
+\ProvidesExplPackage {jsonparse} {2025-01-23} {1.0.2}
   {A handy way to parse, store and access JSON data from files or strings in LaTeX documents}
 
 \msg_new:nnn { jsonparse } { old-kernel } {
@@ -236,7 +236,7 @@
   rescan                      .groups:n   = { output }
 }
 
-\cs_new:Npn \__jsonparse_warning_unused_keys: {
+\cs_new_protected:Npn \__jsonparse_warning_unused_keys: {
   \clist_map_inline:Nn \l__jsonparse_unused_keys_clist {
     \msg_warning:nne { jsonparse } { unknown-key } {
       ##1
@@ -254,7 +254,8 @@
 % ===
 
 \cs_if_exist:NF \str_casefold:n {
-  \cs_new:Npn \str_casefold:n { \str_foldcase:n }
+  \cs_new_eq:NN \str_casefold:n \str_foldcase:n
+  \cs_new:Npn \str_foldcase:n { \str_casefold:n }
 }
 
 \cs_generate_variant:Nn \file_input:n { e }
@@ -391,7 +392,7 @@
   \c__jsonparse_num_plus_minus_fraction_clist
   \c__jsonparse_num_exponent_clist
 
-\prg_new_conditional:Npnn \jsonparse_if_num:n #1 { p , T , F , TF } {
+\prg_new_protected_conditional:Npnn \jsonparse_if_num:n #1 { T , F , TF } {
   \bool_set_true:N \l__jsonparse_num_bool
   \bool_set_false:N \l__jsonparse_num_zero_seen_bool
   \bool_set_false:N \l__jsonparse_num_plus_minus_seen_bool
@@ -413,7 +414,7 @@
   }
 }
 
-\cs_new:Npn \__jsonparse_parse_num:n #1 {
+\cs_new_protected:Npn \__jsonparse_parse_num:n #1 {
   \tl_set:Ne \l__jsonparse_num_input_tl { \tl_trim_spaces:e {#1} }
   \tl_if_empty:NF \l__jsonparse_num_input_tl {
     \cs_if_exist_use:cTF { __jsonparse_parse_num_ \str_head_ignore_spaces:o { \l__jsonparse_num_input_tl } :w } {
@@ -425,39 +426,39 @@
   }
 }
 
-\cs_new:cpn { __jsonparse_parse_num_ + :w } #1 \q_stop {
+\cs_new_protected:cpn { __jsonparse_parse_num_ + :w } #1 \q_stop {
   \exp_last_unbraced:No
     \__jsonparse_parse_num_plus_minus:w #1 \q_stop
 }
 
-\cs_new:cpn { __jsonparse_parse_num_ - :w } #1 \q_stop {
+\cs_new_protected:cpn { __jsonparse_parse_num_ - :w } #1 \q_stop {
   \exp_last_unbraced:No
     \__jsonparse_parse_num_plus_minus:w #1 \q_stop
 }
 
-\cs_new:cpn { __jsonparse_parse_num_ . :w } #1 \q_stop {
+\cs_new_protected:cpn { __jsonparse_parse_num_ . :w } #1 \q_stop {
   \exp_last_unbraced:No
     \__jsonparse_parse_num_fraction:w #1 \q_stop
 }
 
-\cs_new:cpn { __jsonparse_parse_num_ e :w } #1 \q_stop {
+\cs_new_protected:cpn { __jsonparse_parse_num_ e :w } #1 \q_stop {
   \exp_last_unbraced:No
     \__jsonparse_parse_num_exponent:w #1 \q_stop
 }
 
-\cs_new:cpn { __jsonparse_parse_num_ E :w } #1 \q_stop {
+\cs_new_protected:cpn { __jsonparse_parse_num_ E :w } #1 \q_stop {
   \exp_last_unbraced:No
     \__jsonparse_parse_num_exponent:w #1 \q_stop
 }
 
 \clist_map_inline:Nn \c__jsonparse_num_digits_clist {
-  \cs_new:cpn { __jsonparse_parse_num_ #1 :w } ##1 \q_stop {
+  \cs_new_protected:cpn { __jsonparse_parse_num_ #1 :w } ##1 \q_stop {
     \exp_last_unbraced:No
       \__jsonparse_parse_num_digit:w ##1 \q_stop
   }
 }
 
-\cs_new:Npn \__jsonparse_parse_num_plus_minus:w #1 \q_stop {
+\cs_new_protected:Npn \__jsonparse_parse_num_plus_minus:w #1 \q_stop {
   \bool_if:NTF \l__jsonparse_num_plus_minus_seen_bool {
     \tl_set:Nn \l__jsonparse_num_remainder_tl { }
     \bool_set_false:N \l__jsonparse_num_bool
@@ -480,7 +481,7 @@
   \__jsonparse_parse_num:n { \l__jsonparse_num_remainder_tl }
 }
 
-\cs_new:Npn \__jsonparse_parse_num_fraction:w #1 \q_stop {
+\cs_new_protected:Npn \__jsonparse_parse_num_fraction:w #1 \q_stop {
   \bool_if:NTF \l__jsonparse_num_fraction_seen_bool {
     \tl_set:Nn \l__jsonparse_num_remainder_tl { }
     \bool_set_false:N \l__jsonparse_num_bool
@@ -503,7 +504,7 @@
   \__jsonparse_parse_num:n { \l__jsonparse_num_remainder_tl }
 }
 
-\cs_new:Npn \__jsonparse_parse_num_exponent:w #1 \q_stop {
+\cs_new_protected:Npn \__jsonparse_parse_num_exponent:w #1 \q_stop {
   \bool_if:NTF \l__jsonparse_num_exponent_seen_bool {
     \tl_set:Nn \l__jsonparse_num_remainder_tl { }
     \bool_set_false:N \l__jsonparse_num_bool
@@ -527,7 +528,7 @@
   \__jsonparse_parse_num:n { \l__jsonparse_num_remainder_tl }
 }
 
-\cs_new:Npn \__jsonparse_parse_num_digit:w #1 \q_stop {
+\cs_new_protected:Npn \__jsonparse_parse_num_digit:w #1 \q_stop {
   \bool_lazy_any:nTF {
     { \tl_if_empty_p:N \l__jsonparse_num_input_last_tl }
     { \bool_lazy_and_p:nn
@@ -549,7 +550,7 @@
   \__jsonparse_parse_num:n { \l__jsonparse_num_remainder_tl }
 }
 
-\cs_new:Npn \__jsonparse_parse_num_other:w #1 \q_stop {
+\cs_new_protected:Npn \__jsonparse_parse_num_other:w #1 \q_stop {
   \tl_set:Nn \l__jsonparse_num_remainder_tl { }
   \bool_set_false:N \l__jsonparse_num_bool
 }
@@ -586,32 +587,32 @@
 
 % ===
 
-\cs_new:cpn { __jsonparse_parse_ \c_left_brace_str :w } #1 \q_stop {
+\cs_new_protected:cpn { __jsonparse_parse_ \c_left_brace_str :w } #1 \q_stop {
   \exp_last_unbraced:No
     \__jsonparse_parse_object_begin:w #1 \q_stop
 }
 
-\cs_new:cpn { __jsonparse_parse_ \c_right_brace_str :w } #1 \q_stop {
+\cs_new_protected:cpn { __jsonparse_parse_ \c_right_brace_str :w } #1 \q_stop {
   \exp_last_unbraced:No
     \__jsonparse_parse_object_end:w #1 \q_stop
 }
 
-\cs_new:cpn { __jsonparse_parse_ [ :w } #1 \q_stop {
+\cs_new_protected:cpn { __jsonparse_parse_ [ :w } #1 \q_stop {
   \exp_last_unbraced:No
     \__jsonparse_parse_array_begin:w #1 \q_stop
 }
 
-\cs_new:cpn { __jsonparse_parse_ ] :w } #1 \q_stop {
+\cs_new_protected:cpn { __jsonparse_parse_ ] :w } #1 \q_stop {
   \exp_last_unbraced:No
     \__jsonparse_parse_array_end:w #1 \q_stop
 }
 
-\cs_new:cpn { __jsonparse_parse_ " :w } #1 \q_stop {
+\cs_new_protected:cpn { __jsonparse_parse_ " :w } #1 \q_stop {
   \exp_last_unbraced:No
     \__jsonparse_parse_string_key:w #1 \q_stop
 }
 
-\cs_new:Npn \__jsonparse_array_key_set: {
+\cs_new_protected:Npn \__jsonparse_array_key_set: {
   \str_if_eq:eVT {
     \tl_range:Nen \l__jsonparse_prefix_tl {
       \int_eval:n {
@@ -626,7 +627,7 @@
   }
 }
 
-\exp_last_unbraced:NNo \cs_new:Npn \__jsonparse_parse_object_begin:w \c_left_brace_str #1 \q_stop {
+\exp_last_unbraced:NNo \cs_new_protected:Npn \__jsonparse_parse_object_begin:w \c_left_brace_str #1 \q_stop {
   \__jsonparse_array_key_set:
   \group_begin:
     \tl_set:Nn \l__jsonparse_remainder_tl {#1}
@@ -646,7 +647,7 @@
     \__jsonparse_parse_remainder:
 }
 
-\exp_last_unbraced:NNo \cs_new:Npn \__jsonparse_parse_object_end:w \c_right_brace_str #1 \q_stop {
+\exp_last_unbraced:NNo \cs_new_protected:Npn \__jsonparse_parse_object_end:w \c_right_brace_str #1 \q_stop {
     \tl_set:Ne \l__jsonparse_object_array_val_tl {
       \tl_range:Nne \l__jsonparse_object_array_val_tl { 1 } {
         \int_eval:n {
@@ -673,7 +674,7 @@
   \__jsonparse_parse_remainder:
 }
 
-\cs_new:Npn \__jsonparse_parse_array_begin:w [ #1 \q_stop {
+\cs_new_protected:Npn \__jsonparse_parse_array_begin:w [ #1 \q_stop {
   \__jsonparse_array_key_set:
   \group_begin:
     \tl_set:Nn \l__jsonparse_remainder_tl {#1}
@@ -697,7 +698,7 @@
     \__jsonparse_parse_remainder:
 }
 
-\cs_new:Npn \__jsonparse_parse_array_end:w ] #1 \q_stop {
+\cs_new_protected:Npn \__jsonparse_parse_array_end:w ] #1 \q_stop {
     \tl_set:Ne \l__jsonparse_object_array_val_tl {
       \tl_range:Nne \l__jsonparse_object_array_val_tl { 1 } {
         \int_eval:n {
@@ -724,7 +725,7 @@
   \__jsonparse_parse_remainder:
 }
 
-\cs_new:Npn \__jsonparse_parse_string_key:w " #1 " #2 \q_stop {
+\cs_new_protected:Npn \__jsonparse_parse_string_key:w " #1 " #2 \q_stop {
   \__jsonparse_array_key_set:
   \tl_set:Ne \l__jsonparse_remainder_tl { \tl_trim_spaces:n {#2} }
   % key or string?
@@ -746,7 +747,7 @@
   \__jsonparse_parse_remainder:
 }
 
-\cs_new:Npn \__jsonparse_parse_other:w #1 \q_stop {
+\cs_new_protected:Npn \__jsonparse_parse_other:w #1 \q_stop {
   \__jsonparse_array_key_set:
   \tl_set:Nn \l__jsonparse_remainder_tl {#1}
   \tl_set:Nn \l__jsonparse_temp_tl { #1 , }
@@ -756,7 +757,7 @@
     \__jsonparse_parse_other_aux:w \l__jsonparse_temp_tl \q_stop
 }
 
-\cs_new:Npn \__jsonparse_parse_other_aux:w #1 , #2 \q_stop {
+\cs_new_protected:Npn \__jsonparse_parse_other_aux:w #1 , #2 \q_stop {
   \tl_set:Ne \l__jsonparse_temp_tl { \tl_trim_spaces:n {#1} }
   \cs_if_exist_use:cF { __jsonparse_parse_ \str_casefold:o { \l__jsonparse_temp_tl } : } {
     \bool_if:NTF \l__jsonparse_check_num_bool {
@@ -772,7 +773,7 @@
           }
         }
       } {
-        % not a valid JSON fp
+        % not a valid JSON number
         \msg_error:nnoo { jsonparse } { parsing-error }
           { \l__jsonparse_key_tl } {#1}
       }
@@ -800,7 +801,7 @@
   \__jsonparse_parse_remainder:
 }
 
-\cs_new:Npn \__jsonparse_parse_true: {
+\cs_new_protected:Npn \__jsonparse_parse_true: {
   \tl_set_eq:NN \l__jsonparse_val_tl \l__jsonparse_true_str
   \prop_gput:Nee \g_jsonparse_entries_prop
     { \l__jsonparse_key_tl } { \l__jsonparse_val_tl }
@@ -813,7 +814,7 @@
   }
 }
 
-\cs_new:Npn \__jsonparse_parse_false: {
+\cs_new_protected:Npn \__jsonparse_parse_false: {
   \tl_set_eq:NN \l__jsonparse_val_tl \l__jsonparse_false_str
   \prop_gput:Nee \g_jsonparse_entries_prop
     { \l__jsonparse_key_tl } { \l__jsonparse_val_tl }
@@ -826,7 +827,7 @@
   }
 }
 
-\cs_new:Npn \__jsonparse_parse_null: {
+\cs_new_protected:Npn \__jsonparse_parse_null: {
   \tl_set_eq:NN \l__jsonparse_val_tl \l__jsonparse_null_str
   \prop_gput:Nee \g_jsonparse_entries_prop
     { \l__jsonparse_key_tl } { \l__jsonparse_val_tl }
@@ -839,7 +840,7 @@
   }
 }
 
-\cs_new:Npn \__jsonparse_parse_remainder: {
+\cs_new_protected:Npn \__jsonparse_parse_remainder: {
   \tl_set:Ne \l__jsonparse_remainder_tl { \tl_trim_spaces:e { \l__jsonparse_remainder_tl } }
   \tl_if_head_eq_charcode:oNT { \l__jsonparse_remainder_tl } , {
     \tl_remove_once:Nn \l__jsonparse_remainder_tl { , }
@@ -849,7 +850,7 @@
   }
 }
 
-\cs_new:Npn \__jsonparse_filter:nn #1#2 {
+\cs_new_protected:Npn \__jsonparse_filter:nn #1#2 {
   \str_case_e:en {
     \tl_range:nne {#1} { 1 } { \int_eval:n {
       \tl_count:o { \l__jsonparse_filter_key_str } + 1
@@ -870,7 +871,7 @@
   }
 }
 
-\cs_new:Npn \__jsonparse_warning_undefined_prop:N #1 {
+\cs_new_protected:Npn \__jsonparse_warning_undefined_prop:N #1 {
   \prop_if_exist:NF #1 {
     \msg_error:nnn { jsonparse } { prop-undefined }
       {#1}
@@ -879,7 +880,7 @@
 
 \cs_new_protected:Npn \jsonparse_filter:Nn #1#2 {
   \prop_clear:N \l__jsonparse_temp_prop
-  \str_set:Nn \l__jsonparse_filter_key_str {#2}
+  \str_set:Ne \l__jsonparse_filter_key_str {#2}
   \str_if_eq:NNTF \l__jsonparse_filter_key_str \l__jsonparse_child_sep_str {
     \prop_set_eq:NN \l__jsonparse_temp_prop #1
     \prop_remove:Ne \l__jsonparse_temp_prop { \l__jsonparse_child_sep_str }
@@ -912,7 +913,7 @@
   \prop_gput:Nnn #1 {#2} {#3}
 }
 
-\cs_new:Npn \__jsonparse_externalize:Nn #1#2 {
+\cs_new_protected:Npn \__jsonparse_externalize:Nn #1#2 {
   \file_if_exist:eTF {#2} {
     \msg_error:nne { jsonparse } { file-exists }
       {#2}
@@ -931,7 +932,7 @@
 
 % ===
 
-\cs_new:Npn \__jsonparse_nested_construct_cs:Nnn #1#2#3 {
+\cs_new_protected:Npn \__jsonparse_nested_construct_cs:Nnn #1#2#3 {
   \cs_set:Npn #1 #2 ##1 #3 #2 ##2 #3 {
     \prop_item:ce {##1} {##2}
   }
@@ -1031,14 +1032,63 @@
   \group_end:
 }
 
-\cs_set_eq:NN \__jsonparse_tex_quote: \"
-\cs_set_eq:NN \__jsonparse_tex_backslash: \\
+\cs_new_eq:NN \__jsonparse_tex_quote: \"
+\cs_new_eq:NN \__jsonparse_tex_backslash: \\
 
-\cs_new:Npn \__jsonparse_unicode_char:NNNN #1#2#3#4 {
-  \symbol{ " \str_uppercase:n { #1 #2 #3 #4 } } { }
+\prg_new_conditional:Npnn \jsonparse_unicode_if_high_surrogate:n #1 { p , T , F , TF } {
+  \int_compare:nNnTF {#1} > { "D7FF } {
+    \int_compare:nNnTF {#1} < { "DC00 } {
+      \prg_return_true:
+    } {
+      \prg_return_false:
+    }
+  } {
+    \prg_return_false:
+  }
 }
 
-\cs_new:Npn \__jsonparse_rescan_setup:Nn #1#2 {
+\prg_new_conditional:Npnn \jsonparse_unicode_if_low_surrogate:n #1 { p , T , F , TF } {
+  \int_compare:nNnTF {#1} > { "DBFF } {
+    \int_compare:nNnTF {#1} < { "E000 } {
+      \prg_return_true:
+    } {
+      \prg_return_false:
+    }
+  } {
+    \prg_return_false:
+  }
+}
+
+\cs_new:Npn \jsonparse_unicode_convert_surrogate_pair:nn #1#2 {
+  \int_eval:n { ( #1 - "D800 ) * "0400 + ( #2 - "DC00 ) + "10000 }
+}
+
+\cs_new:Npn \__jsonparse_unicode_char:NNNNN #1#2#3#4#5 {
+  \__jsonparse_unicode_char_aux:nNNNN { } #1#2#3#4
+  \cs_if_eq:NNTF #5 \u {
+    \__jsonparse_unicode_char_aux:nNNNN { " #1#2#3#4 }
+  } {
+    #5
+  }
+}
+
+\cs_new:Npn \__jsonparse_unicode_char_aux:nNNNN #1#2#3#4#5 {
+  \tl_if_empty:nTF {#1} {
+    \exp_args:Ne \jsonparse_unicode_if_high_surrogate:nF { " \str_uppercase:n {#2#3#4#5} } {
+      \exp_args:Ne \codepoint_generate:nn { " \str_uppercase:n {#2#3#4#5} } { 12 }
+    }
+  } {
+    \exp_args:Ne \jsonparse_unicode_if_low_surrogate:nTF { " \str_uppercase:n {#2#3#4#5} } {
+      \codepoint_generate:nn {
+        \exp_args:Nne \jsonparse_unicode_convert_surrogate_pair:nn {#1} { " \str_uppercase:n {#2#3#4#5} }
+      } { 12 }
+    } {
+      \exp_args:Ne \codepoint_generate:nn { " \str_uppercase:n {#2#3#4#5} } { 12 }
+    }
+  }
+}
+
+\cs_new_protected:Npn \__jsonparse_rescan_setup:Nn #1#2 {
   \cs_set:Npn \" { " }
   \cs_set:Npn \/ { / }
   \cs_set:Npn \\ { \c_backslash_str }
@@ -1047,7 +1097,7 @@
   \cs_set:Npn \n { \l__jsonparse_linefeed_str }
   \cs_set:Npn \r { \l__jsonparse_carriage_return_str }
   \cs_set:Npn \t { \l__jsonparse_horizontal_tab_str }
-  \cs_set_eq:NN \u \__jsonparse_unicode_char:NNNN
+  \cs_set_eq:NN \u \__jsonparse_unicode_char:NNNNN
   \tl_set:Ne #1 {#2}
   \cs_set_eq:NN \" \__jsonparse_tex_quote:
   \cs_set_eq:NN \\ \__jsonparse_tex_backslash:
@@ -1064,17 +1114,17 @@
     \tl_replace_all:Noe #1 { \c_ampersand_str } { \c_backslash_str \c_ampersand_str }
   }
   \bool_if:NT \l__jsonparse_escape_circumflex_accent_bool {
-    \tl_replace_all:Non #1 { \c_circumflex_str } { \textasciicircum }
+    \tl_replace_all:Non #1 { \c_circumflex_str } { \codepoint_generate:nn { "5E } { 12 } }
   }
   \bool_if:NT \l__jsonparse_escape_low_line_bool {
     \tl_replace_all:Noe #1 { \c_underscore_str } { \c_backslash_str \c_underscore_str }
   }
   \bool_if:NT \l__jsonparse_escape_tilde_bool {
-    \tl_replace_all:Non #1 { \c_tilde_str } { \textasciitilde }
+    \tl_replace_all:Non #1 { \c_tilde_str } { \codepoint_generate:nn { "7E } { 12 } }
   }
 }
 
-\cs_new:Npn \__jsonparse_rescan:n #1 {
+\cs_new_protected:Npn \__jsonparse_rescan:n #1 {
   \group_begin:
     \__jsonparse_rescan_setup:Nn \l__jsonparse_temp_tl {#1}
     \tl_rescan:no { } { \l__jsonparse_temp_tl }
@@ -1081,7 +1131,7 @@
   \group_end:
 }
 
-\cs_new:Npn \__jsonparse_gset_rescan:Nn #1#2 {
+\cs_new_protected:Npn \__jsonparse_gset_rescan:Nn #1#2 {
   \group_begin:
     \__jsonparse_rescan_setup:Nn \l__jsonparse_temp_tl {#2}
     \tl_gset_rescan:Nno #1 { } { \l__jsonparse_temp_tl }
@@ -1122,7 +1172,7 @@
   \__jsonparse_gset_rescan:Ne #1 { \prop_item:Ne #2 {#3} }
 }
 
-\cs_new:Npn \__jsonparse_parse_keys:nn #1#2 {
+\cs_new_protected:Npn \__jsonparse_parse_keys:nn #1#2 {
   \tl_if_in:nVF {#1} \l__jsonparse_child_sep_str {
     \bool_if:NTF \l__jsonparse_prop_map_first_bool {
       \bool_set_false:N \l__jsonparse_prop_map_first_bool
@@ -1170,7 +1220,7 @@
   #1
 }
 
-\cs_new:Npn \__jsonparse_array_count:nn #1#2 {
+\cs_new_protected:Npn \__jsonparse_array_count:nn #1#2 {
   \str_if_eq:eVF { \tl_head:n {#1} } \l__jsonparse_array_sep_left_str {
     \msg_error:nnn { jsonparse } { not-array-item }
       {#1}
@@ -1216,7 +1266,7 @@
   \tl_set:NV #1 \l__jsonparse_array_count_int
 }
 
-\cs_new:Npn \__jsonparse_array_values:n #1 {
+\cs_new_protected:Npn \__jsonparse_array_values:n #1 {
   \bool_if:NTF \l__jsonparse_prop_map_first_bool {
     \bool_set_false:N \l__jsonparse_prop_map_first_bool
   } {
@@ -1263,7 +1313,7 @@
     \tl_set_eq:NN \l__jsonparse_temp_tl #2
     \jsonparse_filter:Nn \l__jsonparse_temp_tl {#3}
     \jsonparse_array_count:NN \l__jsonparse_temp_tl \l__jsonparse_array_count_int
-    \str_set:Nn \l__jsonparse_array_values_key_str {#4}
+    \str_set:Ne \l__jsonparse_array_values_key_str {#4}
     \tl_set:Nn \l__jsonparse_array_values_insert_tl {#5}
     \bool_set_true:N \l__jsonparse_prop_map_first_bool
     \int_step_function:nN { \l__jsonparse_array_count_int }
@@ -1275,7 +1325,7 @@
 \tl_new:N \JSONParseArrayKey
 \tl_new:N \JSONParseArrayValue
 
-\cs_new:Npn \__jsonparse_array_values_map_keys:n #1 {
+\cs_new_protected:Npn \__jsonparse_array_values_map_keys:n #1 {
   \int_incr:N \l__jsonparse_array_keys_index_int
   \tl_set:Ne \l__jsonparse_array_keys_index_roman_tl {
     \int_to_Roman:n { \l__jsonparse_array_keys_index_int }
@@ -1312,7 +1362,7 @@
   }
 }
 
-\cs_new:Npn \__jsonparse_array_values_map:n #1 {
+\cs_new_protected:Npn \__jsonparse_array_values_map:n #1 {
   \bool_if:NTF \l__jsonparse_zero_based_bool {
     \tl_gset:Nn \JSONParseArrayIndex { \int_eval:n { #1 - 1 } }
   } {
@@ -1353,7 +1403,7 @@
   \use:c { \l__jsonparse_array_map_function_str }
 }
 
-\cs_set:Npn \__jsonparse_array_map_generate_cs:n #1 {
+\cs_set_protected:Npn \__jsonparse_array_map_generate_cs:n #1 {
   \int_incr:N \l__jsonparse_array_keys_index_int
   \tl_set:Ne \l__jsonparse_array_keys_index_roman_tl {
     \int_to_Roman:n { \l__jsonparse_array_keys_index_int }



More information about the tex-live-commits mailing list.