diff options
Diffstat (limited to 'Master/texmf-dist/source/latex/l3experimental/l3str/l3str.dtx')
-rw-r--r-- | Master/texmf-dist/source/latex/l3experimental/l3str/l3str.dtx | 753 |
1 files changed, 433 insertions, 320 deletions
diff --git a/Master/texmf-dist/source/latex/l3experimental/l3str/l3str.dtx b/Master/texmf-dist/source/latex/l3experimental/l3str/l3str.dtx index a718f986ce7..b3648c57ede 100644 --- a/Master/texmf-dist/source/latex/l3experimental/l3str/l3str.dtx +++ b/Master/texmf-dist/source/latex/l3experimental/l3str/l3str.dtx @@ -35,7 +35,7 @@ % %<*driver|package> \RequirePackage{expl3} -\GetIdInfo$Id: l3str.dtx 2895 2011-10-09 15:58:19Z joseph $ +\GetIdInfo$Id: l3str.dtx 2921 2011-10-17 13:23:36Z bruno $ {L3 Experimental Strings} %</driver|package> %<*driver> @@ -72,25 +72,23 @@ % \LaTeX3 provides a set of functions to manipulate token lists % as strings of characters, ignoring the category codes of those % characters. -% -% There is no separate string data type: string variables are simply -% specialized token lists, conventionally made out only of characters -% with category code $12$ (other), except spaces, which have category -% code $10$ (blank space). All the \enquote{safe} functions in this -% module first convert their argument to a string for internal processing, +% +% String variables are simply specialised token lists, but by convention +% should be named with the suffix \texttt{\ldots str}. Such variables should +% contain characters with category code $12$ (other), except spaces, which +% have category code $10$ (blank space). All the \enquote{safe} functions in +% this module first convert their argument to a string for internal processing, % and will not treat a token list or the corresponding string representation -% differently. However, it is often better to name token list variables -% meant to contain string data with a name such as \cs{l_\ldots{}_str}. -% Those are then manipulated mostly with tools from \pkg{l3tl}. +% differently. % % Most functions in this module come in three flavours: % \begin{itemize} -% \item \cs{str_...:N...}, which expect a token list -% variable as their argument; -% \item \cs{str_...:n...}, taking any token list (or string) as an argument; -% \item \cs{str_..._ignore_spaces:n...}, which ignores any space encountered -% during the operation: these functions are slightly faster than those -% which take care of escaping spaces appropriately; +% \item \cs{str_...:N...}, which expect a token list +% variable as their argument; +% \item \cs{str_...:n...}, taking any token list (or string) as an argument; +% \item \cs{str_..._ignore_spaces:n...}, which ignores any space encountered +% during the operation: these functions are slightly faster than those +% which take care of escaping spaces appropriately; % \end{itemize} % When performance is important, the internal \cs{str_..._unsafe:n...} % functions, which expect a \enquote{safe} string in which spaces @@ -98,66 +96,119 @@ % % \subsection{Conversion and input of strings} % -% \begin{variable}{\c_backslash_str, -% \c_lbrace_str,\c_rbrace_str,\c_hash_str,\c_percent_str} +% \begin{variable} +% { +% \c_backslash_str, +% \c_lbrace_str, +% \c_rbrace_str, +% \c_hash_str, +% \c_percent_str +% } % Constant strings, containing a single character, with category code $12$. % \end{variable} % -% \begin{function}[EXP]{\tl_to_str:N,\tl_to_str:n} +% \begin{function}[EXP]{\tl_to_str:N, \tl_to_str:n} % \begin{syntax} % \cs{tl_to_str:N} \meta{tl var} % \cs{tl_to_str:n} \Arg{token list} % \end{syntax} -% Converts the \meta{token list} to a \meta{string}. +% Converts the \meta{token list} to a \meta{string}, leaving the resulting +% tokens in the input stream. +% \end{function} +% +% \begin{function}{\str_set:Nn, \str_set:Nx, \str_set:cn, \str_set:cx} +% \begin{syntax} +% \cs{str_set:Nn} \meta{str var} \Arg{token list} +% \end{syntax} +% Converts the \meta{token list} to a \meta{string}, +% and saves the result in \meta{str var}. +% \end{function} +% +% \begin{function}{\str_gset:Nn, \str_gset:Nx, \str_gset:cn, \str_gset:cx} +% \begin{syntax} +% \cs{str_gset:Nn} \meta{str var} \Arg{token list} +% \end{syntax} +% Converts the \meta{token list} to a \meta{string}, +% and saves the result in \meta{str var} globally. % \end{function} % % \begin{function} % { -% \str_set:Nn, \str_set:Nx, -% \str_set:cn, \str_set:cx, -% \str_gset:Nn, \str_gset:Nx, -% \str_gset:cn, \str_gset:cx, +% \str_put_left:Nn, \str_put_left:Nx, +% \str_put_left:cn, \str_put_left:cx % } +% \begin{syntax} +% \cs{str_put_left:Nn} \meta{str var} \Arg{token list} +% \end{syntax} +% Converts the \meta{token list} to a \meta{string}, +% and prepends the result to \meta{str var}. +% The current contents of the \meta{str var} are not +% automatically converted to a string. +% \end{function} +% % \begin{function} % { -% \str_put_left:Nn, \str_put_left:Nx, -% \str_put_left:cn, \str_put_left:cx, % \str_gput_left:Nn, \str_gput_left:Nx, -% \str_gput_left:cn, \str_gput_left:cx, +% \str_gput_left:cn, \str_gput_left:cx % } +% \begin{syntax} +% \cs{str_gput_left:Nn} \meta{str var} \Arg{token list} +% \end{syntax} +% Converts the \meta{token list} to a \meta{string}, +% and prepends the result to \meta{str var}, globally. +% The current contents of the \meta{str var} are not +% automatically converted to a string. +% \end{function} +% % \begin{function} % { % \str_put_right:Nn, \str_put_right:Nx, -% \str_put_right:cn, \str_put_right:cx, -% \str_gput_right:Nn, \str_gput_right:Nx, -% \str_gput_right:cn, \str_gput_right:cx, +% \str_put_right:cn, \str_put_right:cx % } % \begin{syntax} -% \cs{str_set:Nn} \meta{str var} \Arg{token list} +% \cs{str_put_right:Nn} \meta{str var} \Arg{token list} % \end{syntax} % Converts the \meta{token list} to a \meta{string}, -% and saves the result in \meta{str var}. -% \end{function} +% and appends the result to \meta{str var}. +% The current contents of the \meta{str var} are not +% automatically converted to a string. % \end{function} +% +% \begin{function} +% { +% \str_gput_right:Nn, \str_gput_right:Nx, +% \str_gput_right:cn, \str_gput_right:cx +% } +% \begin{syntax} +% \cs{str_gput_right:Nn} \meta{str var} \Arg{token list} +% \end{syntax} +% Converts the \meta{token list} to a \meta{string}, +% and appends the result to \meta{str var}, globally. +% The current contents of the \meta{str var} are not +% automatically converted to a string. % \end{function} % -% \begin{function}{\str_input:Nn,\str_ginput:Nn} +% \begin{function}{\str_input:Nn, \str_ginput:Nn} % \begin{syntax} % \cs{str_input:Nn} \meta{str var} \Arg{token list} % \end{syntax} % Converts the \meta{token list} into a \meta{string}, and stores -% it in the \meta{str var}. Special characters can be input by +% it in the \meta{str var}, within the current \TeX{} group level +% for the \texttt{input} variant and globally for the \texttt{ginput} +% version. +% Special characters can be input by % escaping them with a backslash. % \begin{itemize} -% \item Spaces are ignored unless escaped with a backslash. -% \item |\xhh| produces the character with code \texttt{hh} -% in hexadecimal: when |\x| is encountered, up to two hexadecimal digits -% (\texttt{0}--\texttt{9}, \texttt{a}--\texttt{f}, \texttt{A}--\texttt{F}) -% are read to give a number between $0$ and $255$. -% \item |\x{hh...}| produces the character with code \texttt{hh...} -% (an aribtrary number of hexadecimal digits are read): -% this is mostly useful for Lua\TeX{} and Xe\TeX{}. -% \item |\a|, |\e|, |\f|, |\n|, |\r|, |\t| stand for specific characters: +% \item Spaces are ignored unless escaped with a backslash. +% \item |\xhh| produces the character with code \texttt{hh} +% in hexadecimal: when |\x| is encountered, up to two hexadecimal digits +% (\texttt{0}--\texttt{9}, \texttt{a}--\texttt{f}, +% \texttt{A}--\texttt{F}) +% are read to give a number between $0$ and $255$. +% \item |\x{hh...}| produces the character with code \texttt{hh...} +% (an arbitrary number of hexadecimal digits are read): +% this is mostly useful for \LuaTeX{} and \XeTeX{}. +% \item |\a|, |\e|, |\f|, |\n|, |\r|, |\t| stand for specific characters: % \begin{center} % \begin{tabular}{cccc} % |\a| & |\^^G| & alarm & hex \texttt{07} \\ @@ -172,26 +223,27 @@ % For instance, % \begin{quote} % \cs{tl_new:N} \cs{l_my_str} \\ -% \cs{str_input:Nn} \cs{l_my_str} |{\x3C \\ \# abc\ def\^}| +% \cs{str_input:Nn} \cs{l_my_str} |{\x3C \\ \# abc\ def\^\n}| % \end{quote} -% results in \cs{l_my_str} containing the characters |\<#abc def^|, -% since |<| has ascii code \texttt{3C} (in hexadecimal). +% results in \cs{l_my_str} containing the characters |<\#abc def^|, +% followed by a newline character (hex \texttt{0A}) +% since |<| has \textsc{ascii} code \texttt{3C} (in hexadecimal). % \end{function} % % \subsection{Characters given by their position} % -% \begin{function}[EXP]{\str_length:N} -% \begin{function}[EXP]{\str_length:n} -% \begin{function}[EXP]{\str_length_ignore_spaces:n} +% \begin{function}[EXP] +% {\str_length:N, \str_length:n, \str_length_ignore_spaces:n} % \begin{syntax} % \cs{str_length:n} \Arg{token list} % \end{syntax} % Leaves the length of the string representation of \meta{token list} -% in the input stream. The functions differ in their treatment of spaces. +% in the input stream as an integer denotation. The functions differ in +% their treatment of spaces. % In the case of \cs{str_length:N} and \cs{str_length:n}, % all characters including spaces are counted. -% The \cs{str_length_ignore_spaces:n} returns the number of non-space -% characters. +% The \cs{str_length_ignore_spaces:n} leaves the number of non-space +% characters in the input stream. % \begin{texnote} % The \cs{str_length:n} of a given token list may depend % on the category codes in effect when it is measured, @@ -200,12 +252,8 @@ % on the escape character, and the category code of \texttt{a}. % \end{texnote} % \end{function} -% \end{function} -% \end{function} % -% \begin{function}[EXP]{\str_head:N} -% \begin{function}[EXP]{\str_head:n} -% \begin{function}[EXP]{\str_head_ignore_spaces:n} +% \begin{function}[EXP]{\str_head:N, \str_head:n, \str_head_ignore_spaces:n} % \begin{syntax} % \cs{str_head:n} \Arg{token list} % \end{syntax} @@ -215,18 +263,14 @@ % The functions differ in their treatment of spaces. % In the case of \cs{str_head:N} and \cs{str_head:n}, % a leading space is returned with category code $10$ (blank space). -% The \cs{str_head_ignore_spaces:n} function returns the first -% non-space character. +% The \cs{str_head_ignore_spaces:n} function leaves the first +% non-space character in the input stream. % If the \meta{token list} is empty (or blank in the case of the % \texttt{_ignore_spaces} variant), then nothing is left on the % input stream. % \end{function} -% \end{function} -% \end{function} % -% \begin{function}[EXP]{\str_tail:N} -% \begin{function}[EXP]{\str_tail:n} -% \begin{function}[EXP]{\str_tail_ignore_spaces:n} +% \begin{function}[EXP]{\str_tail:N, \str_tail:n, \str_tail_ignore_spaces:n} % \begin{syntax} % \cs{str_tail:n} \Arg{token list} % \end{syntax} @@ -239,12 +283,8 @@ % only that space, while \cs{str_tail_ignore_spaces:n} trims % the first non-space character. % \end{function} -% \end{function} -% \end{function} % -% \begin{function}[EXP]{\str_item:Nn} -% \begin{function}[EXP]{\str_item:nn} -% \begin{function}[EXP]{\str_item_ignore_spaces:nn} +% \begin{function}[EXP]{\str_item:Nn, \str_item:nn, \str_item_ignore_spaces:nn} % \begin{syntax} % \cs{str_item:nn} \Arg{token list} \Arg{integer expression} % \end{syntax} @@ -260,29 +300,25 @@ % the right-most character, \emph{etc.}, while $0$ is the first % (left-most) character. % \end{function} -% \end{function} -% \end{function} % -% \begin{function}[EXP]{\str_from_to:Nnn} -% \begin{function}[EXP]{\str_from_to:nnn} -% \begin{function}[EXP]{\str_from_to_ignore_spaces:nnn} +% \begin{function}[EXP] +% {\str_substr:Nnn, \str_substr:nnn, \str_substr_ignore_spaces:nnn} % \begin{syntax} -% \cs{str_from_to:nnn} \Arg{token list} \Arg{start index} \Arg{end index} +% \cs{str_substr:nnn} \Arg{token list} \Arg{start index} \Arg{end index} % \end{syntax} % Converts the \meta{token list} to a \meta{string}, % and leaves in the input stream the characters % between \meta{start index} (inclusive) and \meta{end index} (exclusive). % If either of \meta{start index} or \meta{end index} is negative, -% the it is incremented by the length of the list. -% \end{function} -% \end{function} +% the it is incremented by the length of the list. Both \meta{start index} +% and \meta{end index} count from $0$ for the first (left most) character. % \end{function} % % \subsection{String conditionals} % -% \begin{function}[EXP,pTF]{\str_if_eq:NN} -% \begin{function}[EXP,pTF] +% \begin{function}[EXP, pTF] % { +% \str_if_eq:NN, % \str_if_eq:nn, \str_if_eq:Vn, \str_if_eq:on, \str_if_eq:no, % \str_if_eq:nV, \str_if_eq:VV, \str_if_eq:xx % } @@ -300,10 +336,9 @@ % expandable (including those involving an \texttt{x}-type % expansion). % \end{function} -% \end{function} % -% \begin{function}[EXP,pTF]{\str_if_contains_char:NN} -% \begin{function}[EXP,pTF]{\str_if_contains_char:nN} +% \begin{function}[EXP, pTF] +% {\str_if_contains_char:NN, \str_if_contains_char:nN} % \begin{syntax} % \cs{str_if_contains_char:nN} \Arg{token list} \meta{char} % \end{syntax} @@ -312,43 +347,43 @@ % The \meta{char} can be given either directly, or as a one % letter control sequence. % \end{function} -% \end{function} % -% \subsection{Bytes and encoding} +% \subsection{Byte conditionals} % -% \subsubsection{Conditionals} -% -% \begin{function}[EXP,pTF]{\str_if_bytes:N} +% \begin{function}[EXP, pTF]{\str_if_bytes:N} % \begin{syntax} % \cs{str_if_bytes:NTF} \meta{str var} \Arg{true code} \Arg{false code} % \end{syntax} % Tests whether the \meta{str var} only contains characters -% in the range $0$--$255$. -% \end{function} -% -% \begin{function}[EXP,pTF]{\str_if_UTF_viii:N} -% \begin{syntax} -% \cs{str_if_UTF_viii:N} \meta{str var} \Arg{true code} \Arg{false code} -% \end{syntax} -% Tests whether the \meta{str var} only contains characters -% in the range $0$--$255$, and forms a valid \texttt{UTF8} string. -% \textbf{Missing!} ^^A Missing. +% in the range $0$ to $255$. % \end{function} % -% \subsubsection{Conversion} +% ^^A\begin{function}[EXP, pTF]{\str_if_UTF_viii:N} +% ^^A \begin{syntax} +% ^^A \cs{str_if_UTF_viii:N} \meta{str var} \Arg{true code} \Arg{false code} +% ^^A \end{syntax} +% ^^A Tests whether the \meta{str var} only contains characters +% ^^A in the range $0$--$255$, and forms a valid \texttt{UTF8} string. +% ^^A \textbf{Missing!} ^^A Missing. +% ^^A\end{function} +% +% \subsection{Byte conversion} +% +% Byte conversions are necessary where strings are to be used in PDF +% string objects or within URLs. In both cases, only a restricted subset +% of characters are permitted. % % \begin{function}{\str_native_from_UTF_viii:NN} % \begin{syntax} % \cs{str_native_from_UTF_viii:NN} \meta{str~var1} \meta{str~var2} % \end{syntax} -% Reads the contents of the \meta{str~var2} as an \texttt{UTF8}-encoded +% Reads the contents of the \meta{str~var2} as an \textsc{utf8}-encoded % sequence of bytes, and stores the resulting characters (which can % now have any character code) into \meta{str~var1}. % This function raises an error if the \meta{str~var2} is not -% a valid sequence of bytes in the \texttt{UTF8} encoding. +% a valid sequence of bytes in the \textsc{utf8} encoding. % In the \pdfTeX{} engine, this function raises an error if any of the -% resulting characters is outside the range $0$--$255$ (in other words, -% don't use this function with \pdfTeX{}). +% resulting characters is outside the range $0$ to $255$. % \end{function} % % \begin{function}{\str_UTF_viii_from_native:NN} @@ -356,58 +391,123 @@ % \cs{str_UTF_viii_from_native:NN} \meta{str~var1} \meta{str~var2} % \end{syntax} % Converts each character of the \meta{str~var2} into -% a sequence of bytes, as defined by the \texttt{UTF8} +% a sequence of bytes, as defined by the \textsc{utf8} % encoding, and stores the result in \meta{str~var1}. % In the \pdfTeX{} engine, this function is of course % of very little use, but can be used without harm: -% characters in the range $0$--$127$ are left unchanged, -% and characters in the range $128$--$255$ become two-byte +% characters in the range $0$ to $127$ are left unchanged, +% and characters in the range $128$ to $255$ become two-byte % sequences, as per the definition of \texttt{UTF8}. % \end{function} % -% \begin{function}{\str_bytes_escape_hexadecimal:NN} -% \begin{function}{\str_bytes_unescape_hexadecimal:NN} +% \begin{function} +% {\str_bytes_escape_hexadecimal:NN, \str_bytes_unescape_hexadecimal:NN} % \begin{syntax} % \cs{str_bytes_escape_hexadecimal:NN} \meta{str var1} \meta{str var2} % \cs{str_bytes_unescape_hexadecimal:NN} \meta{str var1} \meta{str var2} % \end{syntax} -% See \tn{pdfescapehex}. ^^A missing doc -% \end{function} +% The \texttt{escape} variant takes each character in \meta{str var1} +% and converts it into the hexadecimal representation. The resulting +% string is stored in \meta{str var2} within the current \TeX{} group +% level. The \texttt{unescape} variant reverses this process. +% Thus for example +% \begin{verbatim} +% \str_set:Nn \l_mya_str { Hello ( ) } +% \str_bytes_escape_hexadecimal:NN \l_mya_str \l_myb_str +% \end{verbatim} +% will result in \cs{l_myb_str} containing the string |48656C6C6F2829|, +% while +% \begin{verbatim} +% \str_set:Nn \l_mya_str { 48656C6C6F2829 } +% \str_bytes_unescape_hexadecimal:NN \l_mya_str \l_myb_str +% \end{verbatim} +% will result in \cs{l_myb_str} containing the string |Hello()|. +% See also \tn{pdfescapehex}. % \end{function} % -% \begin{function}{\str_bytes_escape_name:NN} -% \begin{function}{\str_bytes_unescape_name:NN} +% \begin{function} +% {\str_bytes_escape_name:NN, \str_bytes_unescape_name:NN} % \begin{syntax} % \cs{str_bytes_escape_name:NN} \meta{str var1} \meta{str var2} % \cs{str_bytes_unescape_name:NN} \meta{str var1} \meta{str var2} % \end{syntax} -% See \tn{pdfescapename}. ^^A missing doc -% \end{function} +% The \texttt{escape} variant takes each character in \meta{str var1} +% and replaces any which cannot be used directly in a PDF string object +% with the appropriate hexadecimal representation preceded by the |#| +% character. The resulting +% string is stored in \meta{str var2} within the current \TeX{} group +% level. The \texttt{unescape} variant reverses this process. Thus for +% example +% \begin{verbatim} +% \str_set:Nn \l_mya_str { Hello ( ) } +% \str_bytes_escape_name:NN \l_mya_str \l_myb_str +% \end{verbatim} +% will result in \cs{l_myb_str} containing the string |Hello#28#29|, +% while +% \begin{verbatim} +% \char_set_catcode_other:N \# +% \str_set:Nn \l_mya_str { Hello#28#29 } +% \str_bytes_unescape_name:NN \l_mya_str \l_myb_str +% \end{verbatim} +% will result in \cs{l_myb_str} containing the string |Hello()|. +% See also \tn{pdfescapename}. % \end{function} % -% \begin{function}{\str_bytes_escape_string:NN} -% \begin{function}{\str_bytes_unescape_string:NN} +% \begin{function}{\str_bytes_escape_string:NN, \str_bytes_unescape_string:NN} % \begin{syntax} % \cs{str_bytes_escape_string:NN} \meta{str var1} \meta{str var2} % \cs{str_bytes_unescape_string:NN} \meta{str var1} \meta{str var2} % \end{syntax} -% See \tn{pdfescapestring}. ^^A missing doc -% \end{function} +% The \texttt{escape} variant takes each character in \meta{str var1} +% and prepends a |\| to any which cannot be used directly in a PDF string +% object. The resulting string is stored in \meta{str var2} within the +% current \TeX{} group level. The \texttt{unescape} variant reverses this +% process. Thus for example +% \begin{verbatim} +% \str_set:Nn \l_mya_str { Hello [ ] } +% \str_bytes_escape_string:NN \l_mya_str \l_myb_str +% \end{verbatim} +% will result in \cs{l_myb_str} containing the string |Hello\(\)|, +% while +% \begin{verbatim} +% \str_set:Nn \l_mya_str { Hello\(\) } +% \str_bytes_unescape_string:NN \l_mya_str \l_myb_str +% \end{verbatim} +% will result in \cs{l_myb_str} containing the string |Hello()|. +% Some characters (for example a space) are converted to a three-digit +% octal representation, so for example a space gives |\040|. +% See also \tn{pdfescapename}. % \end{function} % -% \begin{function}{\str_bytes_percent_encode:NN} -% \begin{function}{\str_bytes_percent_decode:NN} +% \begin{function}{\str_bytes_percent_encode:NN, \str_bytes_percent_decode:NN} % \begin{syntax} % \cs{str_bytes_percent_encode:NN} meta{str var1} \meta{str var2} % \cs{str_bytes_percent_decode:NN} meta{str var1} \meta{str var2} % \end{syntax} -% Used for urls. ^^A missing doc -% \end{function} +% The \texttt{escape} variant takes each character in \meta{str var1} +% and replaces any which cannot be used directly in a URL +% with the appropriate hexadecimal representation preceded by the |%| +% character. The resulting +% string is stored in \meta{str var2} within the current \TeX{} group +% level. The \texttt{unescape} variant reverses this process. Thus for +% example +% \begin{verbatim} +% \str_set:Nn \l_mya_str { Hello ( ) } +% \str_bytes_precent_encode:NN \l_mya_str \l_myb_str +% \end{verbatim} +% will result in \cs{l_myb_str} containing the string |Hello%28%29|, +% while +% \begin{verbatim} +% \char_set_catcode_other:N \% +% \str_set:Nn \l_mya_str { Hello%28%29 } +% \str_bytes_unescape_name:NN \l_mya_str \l_myb_str +% \end{verbatim} +% will result in \cs{l_myb_str} containing the string |Hello()|. % \end{function} % % \subsection{Internal string functions} % -% \begin{function}[EXP]{\tl_to_other_str:N,\tl_to_other_str:n} +% \begin{function}[EXP]{\tl_to_other_str:N, \tl_to_other_str:n} % \begin{syntax} % \cs{tl_to_other_str:n} \Arg{token list} % \end{syntax} @@ -421,7 +521,7 @@ % \end{texnote} % \end{function} % -% \begin{function}[EXP]{\str_sanitize_args:Nn,\str_sanitize_args:Nnn} +% \begin{function}[EXP]{\str_sanitize_args:Nn, \str_sanitize_args:Nnn} % \begin{syntax} % \cs{str_sanitize_args:Nnn} \meta{function} % ~~\Arg{token list1} \Arg{token list2} @@ -473,7 +573,6 @@ % Some functionalities of \pkg{stringstrings} and \pkg{xstring} as well. % %^^A Should "str_item" be "str_char"? -%^^A Should "str_from_to" be "str_substr"? % % \end{documentation} % @@ -482,7 +581,7 @@ % \section{\pkg{l3str} implementation} % % \begin{macrocode} -%<*package> +%<*initex|package> % \end{macrocode} % % \begin{macrocode} @@ -492,31 +591,18 @@ % % Those string-related functions are defined in \pkg{l3kernel}. % \begin{itemize} -% \item \cs{str_if_eq:nn}[pTF] and variants, -% \item \cs{str_if_eq_return:on}, -% \item \cs{tl_to_str:n}, \cs{tl_to_str:N}, \cs{tl_to_str:c}, -% \item \cs{token_to_str:N}, \cs{cs_to_str:N} -% \item \cs{str_head:n}, \cs{str_head_aux:w}, (changed behaviour slightly) -% \item \cs{str_tail:n}, \cs{str_tail_aux:w}, (changed behaviour slightly) -% \item \cs{str_length_skip_spaces} (deprecated) -% \item \cs{str_length_loop:NNNNNNNNN} (unchanged) +% \item \cs{str_if_eq:nn}[pTF] and variants, +% \item \cs{str_if_eq_return:on}, +% \item \cs{tl_to_str:n}, \cs{tl_to_str:N}, \cs{tl_to_str:c}, +% \item \cs{token_to_str:N}, \cs{cs_to_str:N} +% \item \cs{str_head:n}, \cs{str_head_aux:w}, (copied here) +% \item \cs{str_tail:n}, \cs{str_tail_aux:w}, (copied here) +% \item \cs{str_length_skip_spaces} (deprecated) +% \item \cs{str_length_loop:NNNNNNNNN} (unchanged) % \end{itemize} % % \subsection{General functions} % -% \begin{macro}[EXP,aux]{\cs_if_exist_use:cF} -% This function could be moved to a different module in \pkg{l3kernel}. -% If the control sequence exists, use it, -% otherwise fall back to a default behaviour. -% \begin{macrocode} -\cs_if_exist:NF \cs_if_exist_use:cF - { - \cs_new:Npn \cs_if_exist_use:cF #1 - { \cs_if_exist:cTF {#1} { \use:c {#1} } } - } -% \end{macrocode} -% \end{macro} -% % \begin{macro}[EXP,aux]{\use_i:nnnnnnnn} % A function which may already be defined elsewhere. % \begin{macrocode} @@ -542,18 +628,20 @@ % } % Simply convert the token list inputs to \meta{strings}. % \begin{macrocode} -\cs_set:Npn \str_tmp:w #1 - { - \cs_new_protected:cpx { str_#1:Nn } ##1##2 - { \exp_not:c { tl_#1:Nx } ##1 { \exp_not:N \tl_to_str:n {##2} } } - \exp_args:Nc \cs_generate_variant:Nn { str_#1:Nn } { Nx , cn , cx } - } -\str_tmp:w {set} -\str_tmp:w {gset} -\str_tmp:w {put_left} -\str_tmp:w {gput_left} -\str_tmp:w {put_right} -\str_tmp:w {gput_right} +\group_begin: + \cs_set_protected_nopar:Npn \str_tmp:w #1 + { + \cs_new_protected:cpx { str_ #1 :Nn } ##1##2 + { \exp_not:c { tl_ #1 :Nx } ##1 { \exp_not:N \tl_to_str:n {##2} } } + \exp_args:Nc \cs_generate_variant:Nn { str_ #1 :Nn } { Nx , cn , cx } + } + \str_tmp:w { set } + \str_tmp:w { gset } + \str_tmp:w { put_left } + \str_tmp:w { gput_left } + \str_tmp:w { put_right } + \str_tmp:w { gput_right } +\group_end: % \end{macrocode} % \end{macro} % @@ -563,7 +651,7 @@ % \begin{variable}{\g_str_tmpa_tl} % Internal scratch space for some functions. % \begin{macrocode} -\cs_set_protected_nopar:Npn \str_tmp:w { } +\cs_new_protected_nopar:Npn \str_tmp:w { } \tl_new:N \g_str_tmpa_tl % \end{macrocode} % \end{variable} @@ -579,11 +667,11 @@ % \end{macrocode} % \end{variable} % -% \begin{variable}{\l_str_char_int,\l_str_bytes_int} +% \begin{variable}{\l_str_char_int, \l_str_bytes_int} % When converting from various escaped forms to raw characters, % we often need to read several digits (hexadecimal or octal depending % on the case) and keep track of the corresponding character code -% in \cs{l_str_char_int}. For UTF-8 support, the number of bytes +% in \cs{l_str_char_int}. For \textsc{utf8} support, the number of bytes % of for the current character is stored in \cs{l_str_bytes_int}. % \begin{macrocode} \int_new:N \l_str_char_int @@ -591,8 +679,14 @@ % \end{macrocode} % \end{variable} % -% \begin{variable}{\c_backslash_str, -% \c_lbrace_str,\c_rbrace_str,\c_hash_str,\c_percent_str} +% \begin{variable} +% { +% \c_backslash_str, +% \c_lbrace_str, +% \c_rbrace_str, +% \c_hash_str, +% \c_percent_str +% } % For all of those strings, \cs{cs_to_str:N} produce characters % with the correct category code. % \begin{macrocode} @@ -606,48 +700,45 @@ % % \subsection{Escaping spaces} % -% \begin{macro}[EXP]{\tl_to_other_str:N,\tl_to_other_str:n} -% \begin{macro}[EXP,aux]{\tl_to_other_str_loop:w,\tl_to_other_str_end:w} +% \begin{macro}[EXP]{\tl_to_other_str:N, \tl_to_other_str:n} +% \begin{macro}[EXP,aux]{\tl_to_other_str_loop:w, \tl_to_other_str_end:w} % Replaces all spaces by \enquote{other} spaces, after converting % the token list to a string via \cs{tl_to_str:n}. % \begin{macrocode} \group_begin: -\char_set_lccode:nn {`\*}{`\ } -\char_set_lccode:nn {`\A}{`\A} -\tl_to_lowercase:n { - \group_end: - \cs_new:Npn \tl_to_other_str:n #1 - { - \exp_after:wN \tl_to_other_str_loop:w \tl_to_str:n {#1} ~ % - A ~ A ~ A ~ A ~ A ~ A ~ A ~ A ~ \q_mark \q_stop - } - \cs_new_nopar:Npn \tl_to_other_str_loop:w +\char_set_lccode:nn { `\* } { `\ } +\char_set_lccode:nn { `\A } { `\A } +\tl_to_lowercase:n + { + \group_end: + \cs_new:Npn \tl_to_other_str:n #1 + { + \exp_after:wN \tl_to_other_str_loop:w \tl_to_str:n {#1} ~ % + A ~ A ~ A ~ A ~ A ~ A ~ A ~ A ~ \q_mark \q_stop + } + \cs_new_nopar:Npn \tl_to_other_str_loop:w #1 ~ #2 ~ #3 ~ #4 ~ #5 ~ #6 ~ #7 ~ #8 ~ #9 \q_stop - { - \if_meaning:w A #8 - \tl_to_other_str_end:w - \fi: - \tl_to_other_str_loop:w - #9 #1 * #2 * #3 * #4 * #5 * #6 * #7 * #8 * \q_stop - } - \cs_new_nopar:Npn \tl_to_other_str_end:w \fi: #1 \q_mark #2 * A #3 \q_stop - { \fi: #2 } -} -\cs_new_nopar:Npn \tl_to_other_str:N - { \exp_args:No \tl_to_other_str:n } + { + \if_meaning:w A #8 + \tl_to_other_str_end:w + \fi: + \tl_to_other_str_loop:w + #9 #1 * #2 * #3 * #4 * #5 * #6 * #7 * #8 * \q_stop + } + \cs_new_nopar:Npn \tl_to_other_str_end:w \fi: #1 \q_mark #2 * A #3 \q_stop + { \fi: #2 } + } +\cs_new_nopar:Npn \tl_to_other_str:N { \exp_args:No \tl_to_other_str:n } % \end{macrocode} % \end{macro} % \end{macro} % -% \begin{macro}[EXP]{\str_sanitize_args:Nn,\str_sanitize_args:Nnn} +% \begin{macro}[EXP]{\str_sanitize_args:Nn, \str_sanitize_args:Nnn} % Here, \texttt{f}-expansion does not lose leading spaces, % since they have catcode \enquote{other} after \cs{str_sanitize:n}. % \begin{macrocode} -\cs_new:Npn \str_sanitize_args:Nn #1 #2 - { - \exp_args:Nf #1 - { \tl_to_other_str:n {#2} } - } +\cs_new:Npn \str_sanitize_args:Nn #1#2 + { \exp_args:Nf #1 { \tl_to_other_str:n {#2} } } \cs_new:Npn \str_sanitize_args:Nnn #1#2#3 { \exp_args:Nff #1 @@ -726,15 +817,15 @@ % gives an empty result after passing through % \cs{use_i_delimit_by_q_stop:nw}. % \begin{macrocode} -\cs_set_nopar:Npn \str_head:N { \exp_args:No \str_head:n } +\cs_new_nopar:Npn \str_head:N { \exp_args:No \str_head:n } \cs_set:Npn \str_head:n #1 { \exp_after:wN \str_head_aux:w \tl_to_str:n {#1} { { } } ~ \q_stop } -\cs_set_nopar:Npx \str_head_aux:w #1 ~ % - { \exp_not:N \use_i_delimit_by_q_stop:nw #1 { ~ } } +\cs_set_nopar:Npn \str_head_aux:w #1 ~ % + { \use_i_delimit_by_q_stop:nw #1 { ~ } } \cs_new:Npn \str_head_ignore_spaces:n #1 { \exp_after:wN \use_i_delimit_by_q_stop:nw \tl_to_str:n {#1} { } \q_stop } \cs_new_nopar:Npn \str_head_unsafe:n #1 @@ -779,7 +870,7 @@ } \cs_new_nopar:Npn \str_tail_unsafe:n #1 { \str_tail_aux_ii:w #1 X { } X \q_stop } -\cs_set_nopar:Npn \str_tail_aux_ii:w #1 #2 X #3 \q_stop { #2 } +\cs_new_nopar:Npn \str_tail_aux_ii:w #1 #2 X #3 \q_stop { #2 } % \end{macrocode} % \end{macro} % \end{macro} @@ -800,12 +891,14 @@ % \begin{macrocode} \cs_new:Npn \str_skip_do:nn #1 { - \int_compare:nNnTF {#1} > \c_seven - { \str_skip_aux:nnnnnnnnn } - { \str_skip_end:n } + \if_num:w \int_eval:w #1 > \c_seven + \exp_after:wN \str_skip_aux:nnnnnnnnn + \else: + \exp_after:wN \str_skip_end:n + \fi: {#1} } -\cs_new:Npn \str_skip_aux:nnnnnnnnn #1#2 #3#4#5#6#7#8#9 +\cs_new:Npn \str_skip_aux:nnnnnnnnn #1#2#3#4#5#6#7#8#9 { \exp_args:Nf \str_skip_do:nn { \int_eval:n { #1 - \c_seven } } {#2} } \cs_new:Npn \str_skip_end:n #1 { @@ -821,7 +914,7 @@ \else: \str_skip_end_ii:nwn { XXXXXXX } \fi: } -\cs_new:Npn \str_skip_end_ii:nwn #1 #2 \fi: #3 +\cs_new:Npn \str_skip_end_ii:nwn #1#2 \fi: #3 { \fi: \use_i:nnnnnnnn {#3} #1 } % \end{macrocode} % \end{macro} @@ -861,18 +954,18 @@ \cs_new:Npn \str_collect_end:n #1 { \if_case:w \int_eval:w #1 \int_eval_end: - \str_collect_end_ii:nwn { {}{}{}{}{}{}{} } - \or: \str_collect_end_ii:nwn { {}{}{}{}{}{} } - \or: \str_collect_end_ii:nwn { {}{}{}{}{} } - \or: \str_collect_end_ii:nwn { {}{}{}{} } - \or: \str_collect_end_ii:nwn { {}{}{} } - \or: \str_collect_end_ii:nwn { {}{} } - \or: \str_collect_end_ii:nwn { {} } + \str_collect_end_ii:nwn { { } { } { } { } { } { } { } } + \or: \str_collect_end_ii:nwn { { } { } { } { } { } { } } + \or: \str_collect_end_ii:nwn { { } { } { } { } { } } + \or: \str_collect_end_ii:nwn { { } { } { } { } } + \or: \str_collect_end_ii:nwn { { } { } { } } + \or: \str_collect_end_ii:nwn { { } { } } + \or: \str_collect_end_ii:nwn { { } } \or: \str_collect_end_ii:nwn { } - \else: \str_collect_end_ii:nwn { {}{}{}{}{}{}{} } + \else: \str_collect_end_ii:nwn { { } { } { } { } { } { } { } } \fi: } -\cs_new:Npn \str_collect_end_ii:nwn #1 #2 \fi: #3 +\cs_new:Npn \str_collect_end_ii:nwn #1#2 \fi: #3 { \fi: #3 \q_stop #1 } \cs_new:Npn \str_collect_end_iii:nwNNNNNNN #1 #2 \q_stop #3#4#5#6#7#8#9 { #1 {#2#3#4#5#6#7#8#9} } @@ -938,12 +1031,12 @@ % \end{macro} % \end{macro} % -% \begin{macro}[EXP]{\str_from_to:Nnn} -% \begin{macro}[EXP]{\str_from_to:nnn} -% \begin{macro}[EXP]{\str_from_to_ignore_spaces:nnn} -% \begin{macro}[EXP]{\str_from_to_unsafe:nnn} -% \begin{macro}[EXP,aux]{\str_from_to_aux:nnnw} -% \begin{macro}[EXP,aux]{\str_from_to_aux_ii:nnw} +% \begin{macro}[EXP]{\str_substr:Nnn} +% \begin{macro}[EXP]{\str_substr:nnn} +% \begin{macro}[EXP]{\str_substr_ignore_spaces:nnn} +% \begin{macro}[EXP]{\str_substr_unsafe:nnn} +% \begin{macro}[EXP,aux]{\str_substr_aux:nnnw} +% \begin{macro}[EXP,aux]{\str_substr_aux_ii:nnw} % \begin{macro}[EXP,aux]{\str_aux_eval_args:Nnnn} % \begin{macro}[EXP,aux]{\str_aux_normalize_range:nn} % Sanitize the string, then limit the second and third arguments @@ -952,30 +1045,30 @@ % Afterwards, skip characters, then keep some more, and finally % drop the end of the string. % \begin{macrocode} -\cs_new_nopar:Npn \str_from_to:Nnn { \exp_args:No \str_from_to:nnn } -\cs_new:Npn \str_from_to:nnn #1#2#3 +\cs_new_nopar:Npn \str_substr:Nnn { \exp_args:No \str_substr:nnn } +\cs_new:Npn \str_substr:nnn #1#2#3 { \exp_args:Nf \tl_to_str:n - { \str_sanitize_args:Nn \str_from_to_unsafe:nnn {#1}{#2}{#3} } + { \str_sanitize_args:Nn \str_substr_unsafe:nnn {#1} {#2} {#3} } } -\cs_new:Npn \str_from_to_ignore_spaces:nnn #1 - { \exp_args:No \str_from_to_unsafe:nnn { \tl_to_str:n {#1} } } -\cs_new:Npn \str_from_to_unsafe:nnn #1#2#3 % <string> <from> <to> +\cs_new:Npn \str_substr_ignore_spaces:nnn #1 + { \exp_args:No \str_substr_unsafe:nnn { \tl_to_str:n {#1} } } +\cs_new:Npn \str_substr_unsafe:nnn #1#2#3 { - \str_aux_eval_args:Nnnn \str_from_to_aux:nnnw + \str_aux_eval_args:Nnnn \str_substr_aux:nnnw { \str_length_unsafe:n {#1} } {#2} {#3} #1 \q_stop } -\cs_new:Npn \str_from_to_aux:nnnw #1#2#3 % <len> <from> <to> +\cs_new:Npn \str_substr_aux:nnnw #1#2#3 { - \exp_args:Nf \str_from_to_aux_ii:nnw + \exp_args:Nf \str_substr_aux_ii:nnw { \str_aux_normalize_range:nn {#2} {#1} } { \str_aux_normalize_range:nn {#3} {#1} } } -\cs_new:Npn \str_from_to_aux_ii:nnw #1#2 +\cs_new:Npn \str_substr_aux_ii:nnw #1#2 { \str_skip_do:nn {#1} { @@ -1127,7 +1220,7 @@ % % \subsection{Internal conditionals} % -% \begin{macro}[aux]{\str_aux_hexadecimal_test:N} +% \begin{macro}[aux]{\str_aux_hexadecimal_test:NTF} % This test is used when reading hexadecimal digits, for the |\x| escape % sequence, and some conversion functions. It returns \meta{true} if the % token is a hexadecimal digit, and \meta{false} otherwise. It has the @@ -1137,7 +1230,7 @@ % \begin{macrocode} \prg_new_protected_conditional:Npnn \str_aux_hexadecimal_test:N #1 { TF } { - \tl_if_in:onTF { \tl_to_str:n {abcdef} } {#1} + \tl_if_in:onTF { \tl_to_str:n { abcdef } } {#1} { \int_set:Nn \l_str_char_int { \c_sixteen * \l_str_char_int + `#1 - 87 } @@ -1156,7 +1249,7 @@ % \end{macrocode} % \end{macro} % -% \begin{macro}[aux]{\str_aux_octal_test:N} +% \begin{macro}[aux]{\str_aux_octal_test:NTF} % This test is used when reading octal digits, for % some conversion functions. It returns \meta{true} if the % token is an octal digit, and \meta{false} otherwise. @@ -1193,7 +1286,8 @@ % and in the regular expression module to go through the regular expression % once before actually parsing it. The goal in that case is to turn any % character with a meaning in regular expressions (\texttt{*}, \texttt{?}, -% \texttt{\{}, etc.) into a marker indicating that this was a special character, +% \texttt{\{}, etc.) into a marker indicating that this was a special +% character, % and replace any escaped character by the corresponding unescaped character, % so that the \pkg{l3regex} code can avoid caring about escaping issues % (those can become quite complex to handle in combination with ranges @@ -1201,7 +1295,7 @@ % % The idea is to feed unescaped characters to one function, % escaped characters to another, and feed |\a|, |\e|, |\f|, -% |\n|, |\r|, |\t| and |\x| converted to the approriate +% |\n|, |\r|, |\t| and |\x| converted to the appropriate % character to a third function. Spaces are ignored unless % escaped. % For the \cs{str_(g)input:Nn} application, all the functions are simply @@ -1245,7 +1339,7 @@ \cs_set_nopar:Npn \str_aux_escape_unescaped:N { #1 } \cs_set_nopar:Npn \str_aux_escape_escaped:N { #2 } \cs_set_nopar:Npn \str_aux_escape_raw:N { #3 } - \int_set:Nn \tex_escapechar:D {92} + \int_set:Nn \tex_escapechar:D { 92 } \tl_gset:Nx \g_str_result_tl { \tl_to_other_str:n {#4} } \tl_gset:Nx \g_str_result_tl { @@ -1278,9 +1372,11 @@ % \begin{macro}[aux]+\str_aux_escape_\q_recursion_tail:w+ % \begin{macro}[aux]+\str_aux_escape_/\q_recursion_tail:w+ % \begin{macro}[aux]+\str_aux_escape_ :w+ -% \begin{macro}[aux]{ +% \begin{macro}[aux] +% { % \str_aux_escape_/a:w, \str_aux_escape_/e:w, \str_aux_escape_/f:w, -% \str_aux_escape_/n:w, \str_aux_escape_/r:w, \str_aux_escape_/t:w} +% \str_aux_escape_/n:w, \str_aux_escape_/r:w, \str_aux_escape_/t:w +% } % The loop is ended upon seeing \cs{q_recursion_tail}. % Spaces are ignored, and |\a|, |\e|, |\f|, |\n|, |\r|, |\t| take % their meaning here. @@ -1396,12 +1492,6 @@ } } \group_end: -\msg_new:nnn { str } { x-missing-brace } - { - You~wrote~something~like~ - `\iow_char:N\\x\{ \int_to_hexadecimal:n { \l_str_char_int }'.~ - The~closing~brace~is~missing. - } % \end{macrocode} % \end{macro} % \end{macro} @@ -1411,21 +1501,21 @@ % \end{macro} % \end{macro} % -% \subsubsection{Escape and unescape strings for pdf use} +% \subsubsection{Escape and unescape strings for PDF use} % % \begin{macro}{\str_aux_convert_store:} % \begin{macro}{\str_aux_convert_store:NNn} % \begin{macrocode} \group_begin: - \char_set_catcode_other:n {`\^^@} + \char_set_catcode_other:n { `\^^@ } \cs_new_protected_nopar:Npn \str_aux_convert_store: { - \char_set_lccode:nn {\c_zero} {\l_str_char_int} + \char_set_lccode:nn { \c_zero } { \l_str_char_int } \tl_to_lowercase:n { \tl_gput_right:Nx \g_str_result_tl {^^@} } } \cs_new_protected_nopar:Npn \str_aux_convert_store:NNn #1#2#3 { - \char_set_lccode:nn {\c_zero} {#3} + \char_set_lccode:nn { \c_zero } {#3} \tl_to_lowercase:n { #1 #2 {^^@} } } \group_end: @@ -1438,7 +1528,7 @@ % \begin{macrocode} \cs_new_nopar:Npn \str_aux_byte_to_hexadecimal:N #1 { - \int_compare:nNnTF {`#1} < {256} + \int_compare:nNnTF {`#1} < { 256 } { \int_to_letter:n { \int_div_truncate:nn {`#1} \c_sixteen } \int_to_letter:n { \int_mod:nn {`#1} \c_sixteen } @@ -1447,14 +1537,14 @@ } \cs_new_nopar:Npn \str_aux_byte_to_octal:N #1 { - \int_compare:nNnTF {`#1} < {64} + \int_compare:nNnTF {`#1} < { 64 } { 0 \int_to_letter:n { \int_div_truncate:nn {`#1} \c_eight } \int_to_letter:n { \int_mod:nn {`#1} \c_eight } } { - \int_compare:nNnTF {`#1} < {256} + \int_compare:nNnTF {`#1} < { 256 } { \int_to_octal:n {`#1} } { \msg_expandable_error:n { Invalid~byte~`#1'. } } } @@ -1476,7 +1566,7 @@ % \begin{macro}{\str_bytes_escape_name:NN} % \begin{macrocode} \tl_const:Nx \c_str_bytes_escape_name_str - { \c_hash_str \c_percent_str \c_lbrace_str \c_rbrace_str () /<>[] } + { \c_hash_str \c_percent_str \c_lbrace_str \c_rbrace_str ()/<>[] } \cs_new_protected_nopar:Npn \str_bytes_escape_name:NN #1#2 { \str_set:Nx #1 @@ -1484,10 +1574,10 @@ } \cs_new_nopar:Npn \str_bytes_escape_name_aux:N #1 { - \int_compare:nNnTF {`#1} < {"21} + \int_compare:nNnTF {`#1} < { "21 } { \c_hash_str \str_aux_byte_to_hexadecimal:N #1 } { - \int_compare:nNnTF {`#1} > {"7E} + \int_compare:nNnTF {`#1} > { "7E } { \c_hash_str \str_aux_byte_to_hexadecimal:N #1 } { \str_if_contains_char:NNTF \c_str_bytes_escape_name_str #1 @@ -1501,7 +1591,7 @@ % % \begin{macro}{\str_bytes_escape_string:NN} % Any character below (and including) space, and any character -% above (anc including) \texttt{del}, are converted to octal. +% above (and including) \texttt{del}, are converted to octal. % One backslash is added before each parenthesis and backslash. % \begin{macrocode} \tl_const:Nx \c_str_bytes_escape_string_str { \c_backslash_str ( ) } @@ -1512,10 +1602,10 @@ } \cs_new_nopar:Npn \str_bytes_escape_string_aux:N #1 { - \int_compare:nNnTF {`#1} < {"21} + \int_compare:nNnTF {`#1} < { "21 } { \c_backslash_str \str_aux_byte_to_octal:N #1 } { - \int_compare:nNnTF {`#1} > {"7E} + \int_compare:nNnTF {`#1} > { "7E } { \c_backslash_str \str_aux_byte_to_octal:N #1 } { \str_if_contains_char:NNT \c_str_bytes_escape_string_str #1 @@ -1639,7 +1729,7 @@ % If followed by an end-of-line character, the backslash and % the end-of-line are ignored. If followed by anything else, % the backslash is ignored. -% The pdf specification indicates that LF, CR, and CRLF should be +% The PDF specification indicates that LF, CR, and CRLF should be % converted to LF: \emph{this is not implemented here}. % \begin{macrocode} \group_begin: @@ -1671,16 +1761,16 @@ { \prg_case_str:xxn {#2} { - {n} {10} - {r} {13} - {t} {9} - {b} {8} - {f} {12} - {(} {40} - {)} {41} - {\c_backslash_str} {92} - {^^J} {-1} - {^^M} {-1} + { n } { 10 } + { r } { 13 } + { t } { 9 } + { b } { 8 } + { f } { 12 } + { ( } { 40 } + { ) } { 41 } + { \c_backslash_str } { 92 } + { ^^J } { -1 } + { ^^M } { -1 } } {`#2} } @@ -1727,14 +1817,14 @@ } \cs_new_nopar:Npn \str_bytes_percent_encode_aux:N #1 { - \int_compare:nNnTF {`#1} < {"41} + \int_compare:nNnTF {`#1} < { "41 } { \str_if_contains_char:NNTF \c_str_bytes_percent_encode_not_str #1 { #1 } { \c_percent_str \str_aux_byte_to_hexadecimal:N #1 } } { - \int_compare:nNnTF {`#1} > {"7E} + \int_compare:nNnTF {`#1} > { "7E } { \c_percent_str \str_aux_byte_to_hexadecimal:N #1 } { \str_if_contains_char:NNTF \c_str_bytes_percent_encode_str #1 @@ -1798,6 +1888,14 @@ % \subsubsection{UTF-8 support} % % \begin{macro}{\str_native_from_UTF_viii:NN} +% \begin{macro}[aux] +% { +% \str_native_from_UTF_viii_aux_i:N, +% \str_native_from_UTF_viii_aux_ii:nN, +% \str_native_from_UTF_viii_aux_iii:N, +% \str_native_from_UTF_viii_aux_iv:, +% \str_native_from_UTF_viii_aux_v: +% } % \begin{macrocode} \cs_new_protected_nopar:Npn \str_native_from_UTF_viii:NN #1#2 { @@ -1812,19 +1910,18 @@ \cs_new_protected_nopar:Npn \str_native_from_UTF_viii_aux_i:N #1 { \quark_if_recursion_tail_stop:N #1 - \int_set:Nn \l_str_char_int { `#1 } - \str_native_from_UTF_viii_aux_ii:nN {128} \c_one - \str_native_from_UTF_viii_aux_ii:nN {64} \c_zero - \str_native_from_UTF_viii_aux_ii:nN {32} \c_two - \str_native_from_UTF_viii_aux_ii:nN {16} \c_three - \str_native_from_UTF_viii_aux_ii:nN {8} \c_four + \int_set:Nn \l_str_char_int {`#1} + \str_native_from_UTF_viii_aux_ii:nN { 128 } \c_one + \str_native_from_UTF_viii_aux_ii:nN { 64 } \c_zero + \str_native_from_UTF_viii_aux_ii:nN { 32 } \c_two + \str_native_from_UTF_viii_aux_ii:nN { 16 } \c_three + \str_native_from_UTF_viii_aux_ii:nN { 8 } \c_four \msg_error:nnx { str } { utf8-invalid-byte } {#1} \use_i:nnn \str_native_from_UTF_viii_aux_i:N \q_stop \str_native_from_UTF_viii_aux_iii:N } -\cs_new_protected_nopar:Npn - \str_native_from_UTF_viii_aux_ii:nN #1#2 +\cs_new_protected_nopar:Npn \str_native_from_UTF_viii_aux_ii:nN #1#2 { \int_compare:nNnTF \l_str_char_int < {#1} { @@ -1833,8 +1930,7 @@ } { \int_sub:Nn \l_str_char_int {#1} } } -\cs_new_protected_nopar:Npn - \str_native_from_UTF_viii_aux_iii:N #1 +\cs_new_protected_nopar:Npn \str_native_from_UTF_viii_aux_iii:N #1 { \int_compare:nNnTF \l_str_bytes_int < \c_two { \str_native_from_UTF_viii_aux_iv: #1 } @@ -1844,11 +1940,11 @@ \exp_after:wN \use_none_delimit_by_q_recursion_stop:w \fi: \quark_if_recursion_tail_stop:N #1 - \tex_multiply:D \l_str_char_int by 64 \scan_stop: % no interface?? + \tex_multiply:D \l_str_char_int by 64 \scan_stop: \int_decr:N \l_str_bytes_int - \int_compare:nNnTF {`#1} < {128} + \int_compare:nNnTF {`#1} < { 128 } { \use_ii:nn } - { \int_compare:nNnTF {`#1} < {192} } + { \int_compare:nNnTF {`#1} < { 192 } } { \int_add:Nn \l_str_char_int { `#1 - 128 } \str_native_from_UTF_viii_aux_iii:N @@ -1859,49 +1955,35 @@ } } } -\cs_new_protected_nopar:Npn - \str_native_from_UTF_viii_aux_iv: +\cs_new_protected_nopar:Npn \str_native_from_UTF_viii_aux_iv: { \int_compare:nNnTF \l_str_bytes_int = \c_zero { \msg_error:nnx { str } { utf8-extra-byte } { \int_eval:n { \l_str_char_int + 128 } } } + { \str_native_from_UTF_viii_aux_v: } + \str_native_from_UTF_viii_aux_i:N + } +\pdftex_if_engine:TF + { + \cs_new_protected_nopar:Npn \str_native_from_UTF_viii_aux_v: { - \pdftex_if_engine:TF + \int_compare:nNnTF { \l_str_char_int } < { 256 } + { \str_aux_convert_store: } { - \int_compare:nNnTF { \l_str_char_int } < { 256 } - { \str_aux_convert_store: } - { - \msg_error:nnx { str } { utf8-pdftex-overflow } - { \int_use:N \l_str_char_int } - } + \msg_error:nnx { str } { utf8-pdftex-overflow } + { \int_use:N \l_str_char_int } } - { \str_aux_convert_store: } } - \str_native_from_UTF_viii_aux_i:N - } -\msg_new:nnn { str } { utf8-invalid-byte } - { - \int_compare:nNnTF {`#1} < {256} - { Byte~number~\int_eval:n {`#1}~invalid~in~utf-8~encoding. } - { The~character~number~\int_eval:n {`#1}~is~not~a~byte. } } -\msg_new:nnn { str } { utf8-missing-byte } - { The~byte~number~\int_eval:n {`#1}~is~not~a~valid~continuation~byte. } -\msg_new:nnn { str } { utf8-extra-byte } - { The~byte~number~\int_eval:n {`#1}~is~only~valid~as~a~continuation~byte. } -\msg_new:nnnn { str } { utf8-premature-end } - { Incomplete~last~utf8~character. } { - The~sequence~of~byte~that~I~need~to~convert~to~utf8 \ - ended~before~the~last~character~was~complete.~Perhaps \ - it~was~mistakenly~truncated? + \cs_new_protected_nopar:Npn \str_native_from_UTF_viii_aux_v: + { \str_aux_convert_store: } } -\msg_new:nnn { str } { utf8-pdftex-overflow } - { The~character~number~#1~is~too~big~for~pdfTeX. } % \end{macrocode} % \end{macro} +% \end{macro} % % \begin{macro}{\str_UTF_viii_from_native:NN} % \begin{macrocode} @@ -1916,14 +1998,14 @@ \cs_new_protected_nopar:Npn \str_UTF_viii_from_native_aux_i:N #1 { \int_set:Nn \l_str_char_int {`#1} - \int_compare:nNnTF \l_str_char_int < {128} + \int_compare:nNnTF \l_str_char_int < { 128 } { \tl_gput_right:Nx \g_str_result_tl {#1} } { \tl_gclear:N \g_str_tmpa_tl \int_set:Nn \l_str_bytes_int { 64 } - \str_UTF_viii_from_native_aux_ii:n {32} - \str_UTF_viii_from_native_aux_ii:n {16} - \str_UTF_viii_from_native_aux_ii:n {8} + \str_UTF_viii_from_native_aux_ii:n { 32 } + \str_UTF_viii_from_native_aux_ii:n { 16 } + \str_UTF_viii_from_native_aux_ii:n { 8 } \ERROR % somehow the unicode char was > "1FFFFF > "10FFFF \tl_gclear:N \g_str_tmpa_tl \use_none:n \q_stop @@ -1936,29 +2018,60 @@ { \str_aux_convert_store:NNn \tl_gput_left:Nx \g_str_tmpa_tl - { 128 + \int_mod:nn { \l_str_char_int } {64} } - \tex_divide:D \l_str_char_int by 64 \scan_stop: % no interface?? + { 128 + \int_mod:nn { \l_str_char_int } { 64 } } + \tex_divide:D \l_str_char_int by 64 \scan_stop: \int_add:Nn \l_str_bytes_int {#1} \int_compare:nNnT \l_str_char_int < {#1} { \use_none_delimit_by_q_stop:w } } % \end{macrocode} % \end{macro} +% +% \subsection{Messages} +% +% \begin{macrocode} +\msg_new:nnnn { str } { x-missing-brace } + { Missing~closing~brace~in~ \token_to_str:N \x ~byte~sequence. } + { + You~wrote~something~like~ + `\iow_char:N\\x\{ \int_to_hexadecimal:n { \l_str_char_int }'.~ + The~closing~brace~is~missing. + } +\msg_new:nnn { str } { utf8-invalid-byte } + { + \int_compare:nNnTF {`#1} < { 256 } + { Byte~number~ \int_eval:n {`#1} ~invalid~in~utf-8~encoding. } + { The~character~number~ \int_eval:n {`#1} ~is~not~a~byte. } + } +\msg_new:nnn { str } { utf8-missing-byte } + { The~byte~number~ \int_eval:n {`#1} ~is~not~a~valid~continuation~byte. } +\msg_new:nnn { str } { utf8-extra-byte } + { The~byte~number~ \int_eval:n {`#1} ~is~only~valid~as~a~continuation~byte. } +\msg_new:nnnn { str } { utf8-premature-end } + { Incomplete~last~UTF8~character. } + { + The~sequence~of~byte~that~to~be~converted~to~UTF8~ + ended~before~the~last~character~was~complete.~Perhaps~ + it~was~mistakenly~truncated? + } +\msg_new:nnn { str } { utf8-pdftex-overflow } + { The~character~number~#1~is~too~big~for~pdfTeX. } +% \end{macrocode} % % \subsection{Deprecated string functions} % -% \begin{macro}{\str_length_skip_spaces:N,\str_length_skip_spaces:n} +% \begin{macro}{\str_length_skip_spaces:N, \str_length_skip_spaces:n} % The naming scheme is a little bit more consistent % with \enquote{ignore_spaces} instead of \enquote{skip_spaces}. % \begin{macrocode} -\cs_gset:Npn \str_length_skip_spaces:N +\cs_set:Npn \str_length_skip_spaces:N { \exp_args:No \str_length_skip_spaces:n } -\cs_gset_eq:NN \str_length_skip_spaces:n \str_length_ignore_spaces:n +\cs_set_eq:NN \str_length_skip_spaces:n \str_length_ignore_spaces:n % \end{macrocode} % \end{macro} % % \begin{macrocode} -%</package> +%</initex|package> % \end{macrocode} % % \end{implementation} |