diff options
Diffstat (limited to 'Master/texmf-dist/tex/latex/l3experimental/l3str/l3str.sty')
-rw-r--r-- | Master/texmf-dist/tex/latex/l3experimental/l3str/l3str.sty | 970 |
1 files changed, 970 insertions, 0 deletions
diff --git a/Master/texmf-dist/tex/latex/l3experimental/l3str/l3str.sty b/Master/texmf-dist/tex/latex/l3experimental/l3str/l3str.sty new file mode 100644 index 00000000000..9a69d0da0a6 --- /dev/null +++ b/Master/texmf-dist/tex/latex/l3experimental/l3str/l3str.sty @@ -0,0 +1,970 @@ +%% +%% This is file `l3str.sty', +%% generated with the docstrip utility. +%% +%% The original source files were: +%% +%% l3str.dtx (with options: `package') +%% +%% EXPERIMENTAL CODE +%% +%% Do not distribute this file without also distributing the +%% source files specified above. +%% +%% Do not distribute a modified version of this file. +%% +%% File: l3str.dtx Copyright (C) 2011 The LaTeX3 Project +%% +%% It may be distributed and/or modified under the conditions of the +%% LaTeX Project Public License (LPPL), either version 1.3c of this +%% license or (at your option) any later version. The latest version +%% of this license is in the file +%% +%% http://www.latex-project.org/lppl.txt +%% +%% This file is part of the "l3experimental bundle" (The Work in LPPL) +%% and all files in that bundle must be distributed together. +%% +%% The released version of this bundle is available from CTAN. +%% +%% ----------------------------------------------------------------------- +%% +%% The development version of the bundle can be found at +%% +%% http://www.latex-project.org/svnroot/experimental/trunk/ +%% +%% for those people who are interested. +%% +%%%%%%%%%%% +%% NOTE: %% +%%%%%%%%%%% +%% +%% Snapshots taken from the repository represent work in progress and may +%% not work or may contain conflicting material! We therefore ask +%% people _not_ to put them into distributions, archives, etc. without +%% prior consultation with the LaTeX3 Project. +%% +%% ----------------------------------------------------------------------- +\RequirePackage{expl3} +\GetIdInfo$Id: l3str.dtx 2895 2011-10-09 15:58:19Z joseph $ + {L3 Experimental Strings} +\ProvidesExplPackage + {\ExplFileName}{\ExplFileDate}{\ExplFileVersion}{\ExplFileDescription} +\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} } } + } +\cs_if_exist:NF \use_i:nnnnnnnn + { \cs_new:Npn \use_i:nnnnnnnn #1#2#3#4#5#6#7#8 {#1} } +\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} +\cs_set_protected_nopar:Npn \str_tmp:w { } +\tl_new:N \g_str_tmpa_tl +\tl_new:N \g_str_result_tl +\int_new:N \l_str_char_int +\int_new:N \l_str_bytes_int +\tl_const:Nx \c_backslash_str { \cs_to_str:N \\ } +\tl_const:Nx \c_lbrace_str { \cs_to_str:N \{ } +\tl_const:Nx \c_rbrace_str { \cs_to_str:N \} } +\tl_const:Nx \c_hash_str { \cs_to_str:N \# } +\tl_const:Nx \c_percent_str { \cs_to_str:N \% } +\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 + #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 } +\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 + { \tl_to_other_str:n {#2} } + { \tl_to_other_str:n {#3} } + } +\cs_new_nopar:Npn \str_length:N { \exp_args:No \str_length:n } +\cs_new:Npn \str_length:n { \str_sanitize_args:Nn \str_length_unsafe:n } +\cs_new_nopar:Npn \str_length_unsafe:n #1 + { \str_length_aux:n { \str_length_loop:NNNNNNNNN #1 } } +\cs_new:Npn \str_length_ignore_spaces:n #1 + { + \str_length_aux:n + { \exp_after:wN \str_length_loop:NNNNNNNNN \tl_to_str:n {#1} } + } +\cs_new:Npn \str_length_aux:n #1 + { + \int_eval:n + { + #1 + { X \c_eight } { X \c_seven } { X \c_six } + { X \c_five } { X \c_four } { X \c_three } + { X \c_two } { X \c_one } { X \c_zero } + \q_stop + } + } +\cs_set:Npn \str_length_loop:NNNNNNNNN #1#2#3#4#5#6#7#8#9 + { + \if_catcode:w X #9 + \exp_after:wN \use_none_delimit_by_q_stop:w + \fi: + \c_nine + \str_length_loop:NNNNNNNNN + } +\cs_set_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_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 + { \use_i_delimit_by_q_stop:nw #1 { } \q_stop } +\cs_new_nopar:Npn \str_tail:N { \exp_args:No \str_tail:n } +\cs_set:Npn \str_tail:n #1 + { + \exp_after:wN \str_tail_aux:w + \reverse_if:N \if_charcode:w + \scan_stop: \tl_to_str:n {#1} X X \q_stop + } +\cs_set_nopar:Npn \str_tail_aux:w #1 X #2 \q_stop { \fi: #1 } +\cs_new:Npn \str_tail_ignore_spaces:n #1 + { + \exp_after:wN \str_tail_aux_ii:w + \tl_to_str:n {#1} X { } X \q_stop + } +\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:Npn \str_skip_do:nn #1 + { + \int_compare:nNnTF {#1} > \c_seven + { \str_skip_aux:nnnnnnnnn } + { \str_skip_end:n } + {#1} + } +\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 + { + \if_case:w \int_eval:w #1 \int_eval_end: + \str_skip_end_ii:nwn { XXXXXXX } + \or: \str_skip_end_ii:nwn { XXXXXX } + \or: \str_skip_end_ii:nwn { XXXXX } + \or: \str_skip_end_ii:nwn { XXXX } + \or: \str_skip_end_ii:nwn { XXX } + \or: \str_skip_end_ii:nwn { XX } + \or: \str_skip_end_ii:nwn { X } + \or: \str_skip_end_ii:nwn { } + \else: \str_skip_end_ii:nwn { XXXXXXX } + \fi: + } +\cs_new:Npn \str_skip_end_ii:nwn #1 #2 \fi: #3 + { \fi: \use_i:nnnnnnnn {#3} #1 } +\cs_new:Npn \str_collect_do:nn #1#2 + { \str_collect_aux:n {#1} { \str_collect_end_iii:nwNNNNNNN {#2} } } +\cs_new:Npn \str_collect_aux:n #1 + { + \int_compare:nNnTF {#1} > \c_seven + { \str_collect_aux:nnNNNNNNN } + { \str_collect_end:n } + {#1} + } +\cs_new:Npn \str_collect_aux:nnNNNNNNN #1#2 #3#4#5#6#7#8#9 + { + \exp_args:Nf \str_collect_aux:n + { \int_eval:n { #1 - \c_seven } } + { #2 #3#4#5#6#7#8#9 } + } +\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 { {} } + \or: \str_collect_end_ii:nwn { } + \else: \str_collect_end_ii:nwn { {}{}{}{}{}{}{} } + \fi: + } +\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} } +\cs_new_nopar:Npn \str_item:Nn { \exp_args:No \str_item:nn } +\cs_new:Npn \str_item:nn #1#2 + { + \exp_args:Nf \tl_to_str:n + { \str_sanitize_args:Nn \str_item_unsafe:nn {#1} {#2} } + } +\cs_new:Npn \str_item_ignore_spaces:nn #1 + { \exp_args:No \str_item_unsafe:nn { \tl_to_str:n {#1} } } +\cs_new_nopar:Npn \str_item_unsafe:nn #1#2 + { + \exp_args:Nff \str_item_aux:nn + { \int_eval:n {#2} } + { \str_length_unsafe:n {#1} } + #1 + \q_stop + } +\cs_new_nopar:Npn \str_item_aux:nn #1#2 + { + \int_compare:nNnTF {#1} < \c_zero + { + \int_compare:nNnTF {#1} < {-#2} + { \use_none_delimit_by_q_stop:w } + { + \str_skip_do:nn { #1 + #2 } + { \use_i_delimit_by_q_stop:nw } + } + } + { + \int_compare:nNnTF {#1} < {#2} + { + \str_skip_do:nn {#1} + { \use_i_delimit_by_q_stop:nw } + } + { \use_none_delimit_by_q_stop:w } + } + } +\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 + { + \exp_args:Nf \tl_to_str:n + { \str_sanitize_args:Nn \str_from_to_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> + { + \str_aux_eval_args:Nnnn \str_from_to_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> + { + \exp_args:Nf \str_from_to_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 + { + \str_skip_do:nn {#1} + { + \exp_args:Nf \str_collect_do:nn + { \int_eval:n { #2 - #1 } } + { \use_i_delimit_by_q_stop:nw } + } + } +\cs_new:Npn \str_aux_eval_args:Nnnn #1#2#3#4 + { + \exp_after:wN #1 + \exp_after:wN { \int_value:w \int_eval:w #2 \exp_after:wN } + \exp_after:wN { \int_value:w \int_eval:w #3 \exp_after:wN } + \exp_after:wN { \int_value:w \int_eval:w #4 } + } +\cs_new:Npn \str_aux_normalize_range:nn #1#2 + { + \int_eval:n + { + \if_num:w #1 < \c_zero + \if_num:w #1 < - #2 \exp_stop_f: + \c_zero + \else: + #1 + #2 + \fi: + \else: + \if_num:w #1 < #2 \exp_stop_f: + #1 + \else: + #2 + \fi: + \fi: + } + } +\cs_new_nopar:Npn \str_map_tokens:Nn + { \exp_args:No \str_map_tokens:nn } +\cs_new_nopar:Npn \str_map_tokens:nn + { \str_sanitize_args:Nn \str_map_tokens_aux:nn } +\cs_new:Npn \str_map_tokens_aux:nn #1#2 + { + \str_map_tokens_loop:nN {#2} #1 + { ? \use_none_delimit_by_q_recursion_stop:w } \q_recursion_stop + } +\cs_new_nopar:Npn \str_map_tokens_loop:nN #1#2 + { + \use_none:n #2 + #1 #2 + \str_map_tokens_loop:nN {#1} + } +\cs_new_eq:NN \str_map_break_do:n \use_i_delimit_by_q_recursion_stop:nw +\prg_new_conditional:Npnn \str_if_eq:NN #1#2 { p , TF , T , F } + { + \if_int_compare:w \pdftex_strcmp:D { \tl_to_str:N #1 } { \tl_to_str:N #2 } + = \c_zero \prg_return_true: \else: \prg_return_false: \fi: + } +\prg_new_conditional:Npnn \str_if_contains_char:NN #1#2 { p , T , F , TF } + { + \str_map_tokens:Nn #1 { \str_if_contains_char_aux:NN #2 } + \prg_return_false: + } +\prg_new_conditional:Npnn \str_if_contains_char:nN #1#2 { p , T , F , TF } + { + \str_map_tokens:nn {#1} { \str_if_contains_char_aux:NN #2 } + \prg_return_false: + } +\cs_new_nopar:Npn \str_if_contains_char_aux:NN #1#2 + { + \if_num:w `#1 = `#2 \exp_stop_f: + \str_if_contains_char_end:w + \fi: + } +\cs_new_nopar:Npn \str_if_contains_char_end:w \fi: #1 \prg_return_false: + { \fi: \prg_return_true: } +\prg_new_conditional:Npnn \str_if_bytes:N #1 { p , T , F , TF } + { + \str_map_tokens:Nn #1 { \str_if_bytes_aux:N } + \prg_return_true: + } +\cs_new_nopar:Npn \str_if_bytes_aux:N #1 + { + \int_compare:nNnF {`#1} < \c_two_hundred_fifty_six + { + \use_i_delimit_by_q_recursion_stop:nw + { \prg_return_false: \use_none:n } + } + } +\prg_new_protected_conditional:Npnn \str_aux_hexadecimal_test:N #1 { TF } + { + \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 } + \prg_return_true: + } + { + \if_num:w \c_fifteen < "1 \exp_not:N #1 \exp_stop_f: + \int_set:Nn \l_str_char_int + { \c_sixteen * \l_str_char_int + "#1 } + \prg_return_true: + \else: + \prg_return_false: + \fi: + } + } +\prg_new_protected_conditional:Npnn \str_aux_octal_test:N #1 { TF } + { + \if_num:w \c_seven < '1 \exp_not:N #1 \exp_stop_f: + \int_set:Nn \l_str_char_int + { \c_eight * \l_str_char_int + '#1 } + \prg_return_true: + \else: + \prg_return_false: + \fi: + } +\cs_new_protected_nopar:Npn \str_aux_char_if_octal_digit:NTF #1 + { \tl_if_in:nnTF { 01234567 } {#1} } +\cs_new_protected:Npn \str_input:Nn #1#2 + { + \str_aux_escape:NNNn \token_to_str:N \token_to_str:N \token_to_str:N {#2} + \tl_set_eq:NN #1 \g_str_result_tl + } +\cs_new_protected:Npn \str_ginput:Nn #1#2 + { + \str_aux_escape:NNNn \token_to_str:N \token_to_str:N \token_to_str:N {#2} + \tl_gset_eq:NN #1 \g_str_result_tl + } +\cs_new_eq:NN \str_aux_escape_unescaped:N \use:n +\cs_new_eq:NN \str_aux_escape_escaped:N \use:n +\cs_new_eq:NN \str_aux_escape_raw:N \use:n +\cs_new_protected:Npn \str_aux_escape:NNNn #1#2#3#4 + { + \group_begin: + \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} + \tl_gset:Nx \g_str_result_tl { \tl_to_other_str:n {#4} } + \tl_gset:Nx \g_str_result_tl + { + \exp_after:wN \str_aux_escape_loop:N \g_str_result_tl + \q_recursion_tail \q_recursion_stop + } + \group_end: + } +\cs_new_nopar:Npn \str_aux_escape_loop:N #1 + { + \cs_if_exist_use:cF { str_aux_escape_\token_to_str:N #1:w } + { \str_aux_escape_unescaped:N #1 } + \str_aux_escape_loop:N + } +\cs_new_nopar:cpn { str_aux_escape_ \c_backslash_str :w } + \str_aux_escape_loop:N #1 + { + \cs_if_exist_use:cF { str_aux_escape_/\token_to_str:N #1:w } + { \str_aux_escape_escaped:N #1 } + \str_aux_escape_loop:N + } +\cs_new_eq:cN + { str_aux_escape_ \c_backslash_str q_recursion_tail :w } + \use_none_delimit_by_q_recursion_stop:w +\cs_new_eq:cN + { str_aux_escape_ / \c_backslash_str q_recursion_tail :w } + \use_none_delimit_by_q_recursion_stop:w +\cs_new_nopar:cpn { str_aux_escape_~:w } { } +\cs_new_nopar:cpx { str_aux_escape_/a:w } + { \exp_not:N \str_aux_escape_raw:N \iow_char:N \^^G } +\cs_new_nopar:cpx { str_aux_escape_/t:w } + { \exp_not:N \str_aux_escape_raw:N \iow_char:N \^^I } +\cs_new_nopar:cpx { str_aux_escape_/n:w } + { \exp_not:N \str_aux_escape_raw:N \iow_char:N \^^J } +\cs_new_nopar:cpx { str_aux_escape_/f:w } + { \exp_not:N \str_aux_escape_raw:N \iow_char:N \^^L } +\cs_new_nopar:cpx { str_aux_escape_/r:w } + { \exp_not:N \str_aux_escape_raw:N \iow_char:N \^^M } +\cs_new_nopar:cpx { str_aux_escape_/e:w } + { \exp_not:N \str_aux_escape_raw:N \iow_char:N \^^[ } +\cs_new_nopar:cpn { str_aux_escape_/x:w } \str_aux_escape_loop:N + { + \if_false: { \fi: } + \int_zero:N \l_str_char_int + \str_aux_escape_x_test:N + } +\cs_new_protected_nopar:Npx \str_aux_escape_x_test:N #1 + { + \exp_not:N \token_if_eq_charcode:NNTF \c_space_token #1 + { \exp_not:N \str_aux_escape_x_test:N } + { + \exp_not:N \token_if_eq_charcode:NNTF \c_lbrace_str #1 + { \exp_not:N \str_aux_escape_x_braced_loop:N } + { \exp_not:N \str_aux_escape_x_unbraced_i:N #1 } + } + } +\cs_new_protected_nopar:Npn \str_aux_escape_x_unbraced_i:N #1 + { + \str_aux_hexadecimal_test:NTF #1 + { \str_aux_escape_x_unbraced_ii:N } + { \str_aux_escape_x_end: #1 } + } +\cs_new_protected_nopar:Npn \str_aux_escape_x_unbraced_ii:N #1 + { + \token_if_eq_charcode:NNTF \c_space_token #1 + { \str_aux_escape_x_unbraced_ii:N } + { + \str_aux_hexadecimal_test:NTF #1 + { \str_aux_escape_x_end: } + { \str_aux_escape_x_end: #1 } + } + } +\cs_new_protected_nopar:Npn \str_aux_escape_x_braced_loop:N #1 + { + \token_if_eq_charcode:NNTF \c_space_token #1 + { \str_aux_escape_x_braced_loop:N } + { + \str_aux_hexadecimal_test:NTF #1 + { \str_aux_escape_x_braced_loop:N } + { \str_aux_escape_x_braced_end:N #1 } + } + } +\cs_new_protected_nopar:Npx \str_aux_escape_x_braced_end:N #1 + { + \exp_not:N \token_if_eq_charcode:NNTF \c_rbrace_str #1 + { \exp_not:N \str_aux_escape_x_end: } + { + \msg_error:nn { str } { x-missing-brace } + \exp_not:N \str_aux_escape_x_end: #1 + } + } +\group_begin: + \char_set_catcode_other:N \^^@ + \cs_new_protected_nopar:Npn \str_aux_escape_x_end: + { + \group_begin: + \char_set_lccode:nn { \c_zero } { \l_str_char_int } + \tl_to_lowercase:n + { + \group_end: + \tl_gput_right:Nx \g_str_result_tl + { \if_false: } \fi: + \str_aux_escape_raw:N ^^@ + \str_aux_escape_loop:N + } + } +\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. + } +\group_begin: + \char_set_catcode_other:n {`\^^@} + \cs_new_protected_nopar:Npn \str_aux_convert_store: + { + \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} + \tl_to_lowercase:n { #1 #2 {^^@} } + } +\group_end: +\cs_new_nopar:Npn \str_aux_byte_to_hexadecimal:N #1 + { + \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 } + } + { \msg_expandable_error:n { Invalid~byte~`#1'. } } + } +\cs_new_nopar:Npn \str_aux_byte_to_octal:N #1 + { + \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_to_octal:n {`#1} } + { \msg_expandable_error:n { Invalid~byte~`#1'. } } + } + } +\cs_new_protected_nopar:Npn \str_bytes_escape_hexadecimal:NN #1#2 + { + \str_set:Nx #1 + { \str_map_tokens:Nn #2 \str_aux_byte_to_hexadecimal:N } + } +\tl_const:Nx \c_str_bytes_escape_name_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 + { \str_map_tokens:Nn #2 \str_bytes_escape_name_aux:N } + } +\cs_new_nopar:Npn \str_bytes_escape_name_aux:N #1 + { + \int_compare:nNnTF {`#1} < {"21} + { \c_hash_str \str_aux_byte_to_hexadecimal:N #1 } + { + \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 + { \c_hash_str \str_aux_byte_to_hexadecimal:N #1 } + {#1} + } + } + } +\tl_const:Nx \c_str_bytes_escape_string_str { \c_backslash_str ( ) } +\cs_new_protected_nopar:Npn \str_bytes_escape_string:NN #1#2 + { + \str_set:Nx #1 + { \str_map_tokens:Nn #2 \str_bytes_escape_string_aux:N } + } +\cs_new_nopar:Npn \str_bytes_escape_string_aux:N #1 + { + \int_compare:nNnTF {`#1} < {"21} + { \c_backslash_str \str_aux_byte_to_octal:N #1 } + { + \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 + { \c_backslash_str } + #1 + } + } + } +\cs_new_protected_nopar:Npn \str_bytes_unescape_hexadecimal:NN #1#2 + { + \group_begin: + \tl_gclear:N \g_str_result_tl + \int_zero:N \l_str_char_int + \exp_last_unbraced:Nf \str_bytes_unescape_hexadecimal_aux:N + { \tl_to_other_str:N #2 } 0 + \q_recursion_tail \q_recursion_stop + \group_end: + \tl_set_eq:NN #1 \g_str_result_tl + } +\cs_new_protected_nopar:Npn \str_bytes_unescape_hexadecimal_aux:N #1 + { + \quark_if_recursion_tail_stop:N #1 + \str_aux_hexadecimal_test:NTF #1 + { \str_bytes_unescape_hexadecimal_aux_ii:N } + { \str_bytes_unescape_hexadecimal_aux:N } + } +\cs_new_protected_nopar:Npn \str_bytes_unescape_hexadecimal_aux_ii:N #1 + { + \quark_if_recursion_tail_stop:N #1 + \str_aux_hexadecimal_test:NTF #1 + { + \str_aux_convert_store: + \int_zero:N \l_str_char_int + \str_bytes_unescape_hexadecimal_aux:N + } + { \str_bytes_unescape_hexadecimal_aux_ii:N } + } +\group_begin: + \char_set_lccode:nn {`\*} {`\#} + \tl_to_lowercase:n + { + \group_end: + \cs_new_protected_nopar:Npn \str_bytes_unescape_name:NN #1#2 + { + \group_begin: + \tl_gclear:N \g_str_result_tl + \int_zero:N \l_str_char_int + \exp_last_unbraced:Nf \str_bytes_unescape_name_aux:wN + { \tl_to_other_str:N #2 } + * \q_recursion_tail \q_recursion_stop + \group_end: + \tl_set_eq:NN #1 \g_str_result_tl + } + \cs_new_protected_nopar:Npn \str_bytes_unescape_name_aux:wN #1 * #2 + { + \tl_gput_right:Nx \g_str_result_tl {#1} + \quark_if_recursion_tail_stop:N #2 + \str_aux_hexadecimal_test:NTF #2 + { \str_bytes_unescape_name_aux_ii:NN #2 } + { + \tl_gput_right:Nx \g_str_result_tl { \c_hash_str } + \str_bytes_unescape_name_aux:wN #2 + } + } + } +\cs_new_protected_nopar:Npn \str_bytes_unescape_name_aux_ii:NN #1#2 + { + \str_aux_hexadecimal_test:NTF #2 + { + \str_aux_convert_store: + \int_zero:N \l_str_char_int + \str_bytes_unescape_name_aux:wN + } + { + \tl_gput_right:Nx \g_str_result_tl { \c_hash_str #1 } + \int_zero:N \l_str_char_int + \str_bytes_unescape_name_aux:wN #2 + } + } +\group_begin: + \char_set_lccode:nn {`\*} {`\\} + \char_set_catcode_other:N \^^J + \char_set_catcode_other:N \^^M + \tl_to_lowercase:n + { + \group_end: + \cs_new_protected_nopar:Npn \str_bytes_unescape_string:NN #1#2 + { + \group_begin: + \tl_gclear:N \g_str_result_tl + \exp_last_unbraced:Nf \str_bytes_unescape_string_aux:wN + { \tl_to_other_str:N #2 } + * \q_recursion_tail \q_recursion_stop + \group_end: + \tl_set_eq:NN #1 \g_str_result_tl + } + \cs_new_protected_nopar:Npn \str_bytes_unescape_string_aux:wN #1 * #2 + { + \tl_gput_right:Nx \g_str_result_tl {#1} + \quark_if_recursion_tail_stop:N #2 + \int_zero:N \l_str_char_int + \str_aux_octal_test:NTF #2 + { \str_bytes_unescape_string_aux_d:N } + { + \int_set:Nn \l_str_char_int + { + \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} + } + {`#2} + } + \int_compare:nNnF \l_str_char_int = \c_minus_one + { \str_aux_convert_store: } + \str_bytes_unescape_string_aux:wN + } + } + } +\cs_new_protected_nopar:Npn \str_bytes_unescape_string_aux_d:N #1 + { + \str_aux_octal_test:NTF #1 + { \str_bytes_unescape_string_aux_dd:N } + { + \str_aux_convert_store: + \str_bytes_unescape_string_aux:wN #1 + } + } +\cs_new_protected_nopar:Npn \str_bytes_unescape_string_aux_dd:N #1 + { + \str_aux_octal_test:NTF #1 + { + \str_aux_convert_store: + \str_bytes_unescape_string_aux:wN + } + { + \str_aux_convert_store: + \str_bytes_unescape_string_aux:wN #1 + } + } +\tl_const:Nx \c_str_bytes_percent_encode_str { \tl_to_str:n { [] } } +\tl_const:Nx \c_str_bytes_percent_encode_not_str { \tl_to_str:n { "-.<> } } +\cs_new_protected_nopar:Npn \str_bytes_percent_encode:NN #1#2 + { + \str_set:Nx #1 + { \str_map_tokens:Nn #2 \str_bytes_percent_encode_aux:N } + } +\cs_new_nopar:Npn \str_bytes_percent_encode_aux:N #1 + { + \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} + { \c_percent_str \str_aux_byte_to_hexadecimal:N #1 } + { + \str_if_contains_char:NNTF \c_str_bytes_percent_encode_str #1 + { \c_percent_str \str_aux_byte_to_hexadecimal:N #1 } + { #1 } + } + } + } +\group_begin: + \char_set_lccode:nn {`\*} {`\%} + \tl_to_lowercase:n + { + \group_end: + \cs_new_protected_nopar:Npn \str_bytes_percent_decode:NN #1#2 + { + \group_begin: + \tl_gclear:N \g_str_result_tl + \exp_last_unbraced:Nf \str_bytes_percent_decode_aux:wN + { \tl_to_other_str:N #2 } + * \q_recursion_tail \q_recursion_stop + \group_end: + \tl_set_eq:NN #1 \g_str_result_tl + } + \cs_new_protected_nopar:Npn \str_bytes_percent_decode_aux:wN #1 * #2 + { + \tl_gput_right:Nx \g_str_result_tl {#1} + \quark_if_recursion_tail_stop:N #2 + \int_zero:N \l_str_char_int + \str_aux_hexadecimal_test:NTF #2 + { \str_bytes_percent_decode_aux_ii:NN #2 } + { + \tl_gput_right:Nx \g_str_result_tl { \c_percent_str } + \str_bytes_percent_decode_aux:wN #2 + } + } + } +\cs_new_protected_nopar:Npn \str_bytes_percent_decode_aux_ii:NN #1#2 + { + \str_aux_hexadecimal_test:NTF #2 + { + \str_aux_convert_store: + \str_bytes_percent_decode_aux:wN + } + { + \tl_gput_right:Nx \g_str_result_tl {#1} + \str_bytes_percent_decode_aux:wN #2 + } + } +\cs_new_protected_nopar:Npn \str_native_from_UTF_viii:NN #1#2 + { + \group_begin: + \tl_gclear:N \g_str_result_tl + \exp_last_unbraced:Nf \str_native_from_UTF_viii_aux_i:N + { \tl_to_other_str:N #2 } + \q_recursion_tail \q_recursion_stop + \group_end: + \tl_set_eq:NN #1 \g_str_result_tl + } +\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 + \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 + { + \int_compare:nNnTF \l_str_char_int < {#1} + { + \int_set_eq:NN \l_str_bytes_int #2 + \use_none_delimit_by_q_stop:w + } + { \int_sub:Nn \l_str_char_int {#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 } + { + \if_meaning:w \q_recursion_tail #1 + \msg_error:nn { str } { utf8-premature-end } + \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?? + \int_decr:N \l_str_bytes_int + \int_compare:nNnTF {`#1} < {128} + { \use_ii:nn } + { \int_compare:nNnTF {`#1} < {192} } + { + \int_add:Nn \l_str_char_int { `#1 - 128 } + \str_native_from_UTF_viii_aux_iii:N + } + { + \msg_error:nnx { str } { utf8-missing-byte } {#1} + \str_native_from_UTF_viii_aux_i:N #1 + } + } + } +\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 } } + } + { + \pdftex_if_engine:TF + { + \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 } + } + } + { \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? + } +\msg_new:nnn { str } { utf8-pdftex-overflow } + { The~character~number~#1~is~too~big~for~pdfTeX. } +\cs_new_protected_nopar:Npn \str_UTF_viii_from_native:NN #1#2 + { + \group_begin: + \tl_gclear:N \g_str_result_tl + \str_map_tokens:Nn #2 \str_UTF_viii_from_native_aux_i:N + \group_end: + \tl_set_eq:NN #1 \g_str_result_tl + } +\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} + { \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} + \ERROR % somehow the unicode char was > "1FFFFF > "10FFFF + \tl_gclear:N \g_str_tmpa_tl + \use_none:n \q_stop + \int_add:Nn \l_str_char_int { 2 * \l_str_bytes_int } + \str_aux_convert_store: + \tl_gput_right:Nx \g_str_result_tl { \g_str_tmpa_tl } + } + } +\cs_new_protected_nopar:Npn \str_UTF_viii_from_native_aux_ii:n #1 + { + \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?? + \int_add:Nn \l_str_bytes_int {#1} + \int_compare:nNnT \l_str_char_int < {#1} + { \use_none_delimit_by_q_stop:w } + } +\cs_gset: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 +%% +%% +%% End of file `l3str.sty'. |