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 | 1040 |
1 files changed, 470 insertions, 570 deletions
diff --git a/Master/texmf-dist/tex/latex/l3experimental/l3str/l3str.sty b/Master/texmf-dist/tex/latex/l3experimental/l3str/l3str.sty index cc4d6716ed5..d9ef6271899 100644 --- a/Master/texmf-dist/tex/latex/l3experimental/l3str/l3str.sty +++ b/Master/texmf-dist/tex/latex/l3experimental/l3str/l3str.sty @@ -46,31 +46,32 @@ %% %% ----------------------------------------------------------------------- \RequirePackage{expl3} -\GetIdInfo$Id: l3str.dtx 3159 2012-01-09 00:51:58Z bruno $ +\GetIdInfo$Id: l3str.dtx 3257 2012-01-29 13:37:03Z bruno $ {L3 Experimental Strings} \ProvidesExplPackage {\ExplFileName}{\ExplFileDate}{\ExplFileVersion}{\ExplFileDescription} -\RequirePackage{l3tl-analysis} -\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 { const } - \str_tmp:w { put_left } - \str_tmp:w { gput_left } - \str_tmp:w { put_right } - \str_tmp:w { gput_right } -\group_end: +\RequirePackage{l3tl-analysis,l3flag} +\cs_if_exist:NF \use_ii_i:nn + { \cs_new:Npn \use_ii_i:nn #1#2 { #2 #1 } } +\tl_map_inline:nn + { + { set } + { gset } + { const } + { put_left } + { gput_left } + { put_right } + { gput_right } + } + { + \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 } + } \cs_new_protected_nopar:Npn \str_tmp:w { } -\tl_new:N \l_str_tmpa_tl -\int_new:N \l_str_tmpa_int +\tl_new:N \l_str_internal_tl +\int_new:N \l_str_internal_int \tl_new:N \g_str_result_tl -\int_new:N \l_str_char_int \int_const:Nn \c_forty_eight { 48 } \int_const:Nn \c_fifty_eight { 58 } \int_const:Nn \c_sixty_five { 65 } @@ -79,7 +80,7 @@ \int_const:Nn \c_one_hundred_twenty_three { 123 } \int_const:Nn \c_one_hundred_twenty_seven { 127 } \int_const:Nn \c_max_char_int - { \pdftex_if_engine:TF { 255 } { 1114111 } } + { \pdftex_if_engine:TF { "FF } { "10FFFF } } \int_const:Nn \c_str_replacement_char_int { "FFFD } \tl_const:Nx \c_backslash_str { \cs_to_str:N \\ } \tl_const:Nx \c_lbrace_str { \cs_to_str:N \{ } @@ -87,18 +88,25 @@ \tl_const:Nx \c_hash_str { \cs_to_str:N \# } \tl_const:Nx \c_tilde_str { \cs_to_str:N \~ } \tl_const:Nx \c_percent_str { \cs_to_str:N \% } -\prop_new:N \g_str_aliases_prop -\prop_gput:Nnn \g_str_aliases_prop { latin1 } { iso88591 } -\prop_gput:Nnn \g_str_aliases_prop { latin2 } { iso88592 } -\prop_gput:Nnn \g_str_aliases_prop { latin3 } { iso88593 } -\prop_gput:Nnn \g_str_aliases_prop { latin4 } { iso88594 } -\prop_gput:Nnn \g_str_aliases_prop { latin5 } { iso88599 } -\prop_gput:Nnn \g_str_aliases_prop { latin6 } { iso885910 } -\prop_gput:Nnn \g_str_aliases_prop { latin7 } { iso885913 } -\prop_gput:Nnn \g_str_aliases_prop { latin8 } { iso885914 } -\prop_gput:Nnn \g_str_aliases_prop { latin9 } { iso885915 } -\prop_gput:Nnn \g_str_aliases_prop { latin10 } { iso885916 } -\prop_gput:Nnn \g_str_aliases_prop { hexadecimal } { hex } +\prop_new:N \g_str_file_prop +\prop_gput:Nnn \g_str_file_prop { latin1 } { iso88591 } +\prop_gput:Nnn \g_str_file_prop { latin2 } { iso88592 } +\prop_gput:Nnn \g_str_file_prop { latin3 } { iso88593 } +\prop_gput:Nnn \g_str_file_prop { latin4 } { iso88594 } +\prop_gput:Nnn \g_str_file_prop { latin5 } { iso88599 } +\prop_gput:Nnn \g_str_file_prop { latin6 } { iso885910 } +\prop_gput:Nnn \g_str_file_prop { latin7 } { iso885913 } +\prop_gput:Nnn \g_str_file_prop { latin8 } { iso885914 } +\prop_gput:Nnn \g_str_file_prop { latin9 } { iso885915 } +\prop_gput:Nnn \g_str_file_prop { latin10 } { iso885916 } +\prop_gput:Nnn \g_str_file_prop { utf16le } { utf16 } +\prop_gput:Nnn \g_str_file_prop { utf16be } { utf16 } +\prop_gput:Nnn \g_str_file_prop { utf32le } { utf32 } +\prop_gput:Nnn \g_str_file_prop { utf32be } { utf32 } +\prop_gput:Nnn \g_str_file_prop { hexadecimal } { hex } +\bool_new:N \g_str_error_bool +\flag_new:n { str_byte } +\flag_new:n { str_error } \group_begin: \char_set_lccode:nn { `\* } { `\ } \char_set_lccode:nn { `\A } { `\A } @@ -110,7 +118,7 @@ \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 + \cs_new:Npn \tl_to_other_str_loop:w #1 ~ #2 ~ #3 ~ #4 ~ #5 ~ #6 ~ #7 ~ #8 ~ #9 \q_stop { \if_meaning:w A #8 @@ -119,7 +127,7 @@ \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 + \cs_new:Npn \tl_to_other_str_end:w \fi: #1 \q_mark #2 * A #3 \q_stop { \fi: #2 } } \group_begin: @@ -133,10 +141,10 @@ \tl_gset:Nx #1 { \exp_after:wN \str_gset_other_loop:w \tl_to_str:n {#2} ~ % - A ~ A ~ A ~ A ~ A ~ A ~ A ~ A ~ A ~ \q_mark \q_stop + A ~ A ~ A ~ A ~ A ~ A ~ A ~ A ~ A ~ \q_stop } } - \cs_new_nopar:Npn \str_gset_other_loop:w + \cs_new:Npn \str_gset_other_loop:w #1 ~ #2 ~ #3 ~ #4 ~ #5 ~ #6 ~ #7 ~ #8 ~ #9 ~ { \if_meaning:w A #9 @@ -145,32 +153,42 @@ #1 * #2 * #3 * #4 * #5 * #6 * #7 * #8 * #9 \str_gset_other_loop:w * } - \cs_new_nopar:Npn \str_gset_other_end:w \fi: #1 * A #2 \q_stop + \cs_new:Npn \str_gset_other_end:w \fi: #1 * A #2 \q_stop { \fi: #1 } } -\cs_if_exist:NF \use_i:nnnnnnnn - { \cs_new:Npn \use_i:nnnnnnnn #1#2#3#4#5#6#7#8 {#1} } -\cs_new:Npn \str_aux_toks_range:nn #1#2 +\cs_new:Npn \str_count_spaces:N + { \exp_args:No \str_count_spaces:n } +\cs_new:Npn \str_count_spaces:n #1 { - \exp_after:wN \str_aux_toks_range:ww - \int_use:N \int_eval:w #1 \exp_after:wN ; - \int_use:N \int_eval:w #2 ; - \prg_break_point:n { } + \int_eval:n + { + \exp_after:wN \str_count_spaces_loop:wwwwwwwww + \tl_to_str:n {#1} ~ + X 7 ~ X 6 ~ X 5 ~ X 4 ~ X 3 ~ X 2 ~ X 1 ~ X 0 ~ X -1 ~ + \q_stop + } } -\cs_new:Npn \str_aux_toks_range:ww #1 ; #2 ; +\cs_new:Npn \str_count_spaces_loop:wwwwwwwww #1~#2~#3~#4~#5~#6~#7~#8~#9~ { - \if_num:w #1 = #2 \exp_stop_f: - \exp_after:wN \prg_map_break: + \if_meaning:w X #9 + \exp_after:wN \use_none_delimit_by_q_stop:w \fi: - \tex_the:D \tex_toks:D #1 \exp_stop_f: - \exp_after:wN \str_aux_toks_range:ww - \int_use:N \int_eval:w #1 + \c_one ; #2 ; + \c_nine + \str_count_spaces_loop:wwwwwwwww } \cs_new_nopar:Npn \str_length:N { \exp_args:No \str_length:n } \cs_new:Npn \str_length:n #1 - { \exp_args:Nf \str_length_unsafe:n { \tl_to_other_str:n {#1} } } -\cs_new_nopar:Npn \str_length_unsafe:n #1 - { \str_length_aux:n { \str_length_loop:NNNNNNNNN #1 } } + { + \str_length_aux:n + { + \str_count_spaces:n {#1} + + \exp_after:wN \str_length_loop:NNNNNNNNN \tl_to_str:n {#1} + } + } +\cs_new: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 @@ -189,7 +207,7 @@ } \cs_set:Npn \str_length_loop:NNNNNNNNN #1#2#3#4#5#6#7#8#9 { - \if_catcode:w X #9 + \if_meaning:w X #9 \exp_after:wN \use_none_delimit_by_q_stop:w \fi: \c_nine + \str_length_loop:NNNNNNNNN @@ -201,12 +219,13 @@ \tl_to_str:n {#1} { { } } ~ \q_stop } -\cs_set_nopar:Npn \str_head_aux:w #1 ~ % +\cs_set: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 - { \use_i_delimit_by_q_stop:nw #1 { } \q_stop } + { + \exp_after:wN \use_i_delimit_by_q_stop:nw + \tl_to_str:n {#1} { } \q_stop + } \cs_new_nopar:Npn \str_tail:N { \exp_args:No \str_tail:n } \cs_set:Npn \str_tail:n #1 { @@ -214,107 +233,93 @@ \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_set: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 + \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_new_nopar:Npn \str_tail_aux_ii:w #1 #2 X #3 \q_stop { #2 } -\cs_new:Npn \str_skip_do:nn #1 +\cs_new:Npn \str_tail_aux_ii:w #1 #2 X #3 \q_stop { #2 } +\cs_new:Npn \str_skip_c_zero:w #1; { - \if_num:w \int_eval:w #1 > \c_seven - \exp_after:wN \str_skip_aux:nnnnnnnnn + \if_num:w \int_eval:w #1 > \c_eight + \exp_after:wN \str_skip_aux:wNNNNNNNN \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 - { \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 } + \exp_after:wN \str_skip_end:w + \int_use:N \int_eval:w \fi: + #1 ; + } +\cs_new:Npn \str_skip_aux:wNNNNNNNN #1; #2#3#4#5#6#7#8#9 + { \exp_after:wN \str_skip_c_zero:w \int_use:N \int_eval:w #1 - \c_eight ; } +\cs_new:Npn \str_skip_end:w #1 ; + { + \exp_after:wN \str_skip_end_ii:NNNNNNNN + \if_case:w \if_num:w #1 > \c_zero #1 \else: 0 \fi: \exp_stop_f: + \or: \or: \or: \or: \or: \or: \or: \or: + } +\cs_new:Npn \str_skip_end_ii:NNNNNNNN #1#2#3#4#5#6#7#8 { \fi: \c_zero } +\cs_new:Npn \str_collect_delimit_by_q_stop:w #1; + { + \exp_after:wN \str_collect_aux:wn + \int_use:N \int_eval:w #1 ; + { } } -\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 { { } { } { } { } { } { } { } } +\cs_new:Npn \str_collect_aux:wn #1 ; + { + \if_num:w #1 > \c_seven + \exp_after:wN \str_collect_aux:wnNNNNNNN + \else: + \exp_after:wN \str_collect_end:wn \fi: + #1 ; + } +\cs_new:Npn \str_collect_aux:wnNNNNNNN #1; #2 #3#4#5#6#7#8#9 + { + \exp_after:wN \str_collect_aux:wn + \int_use:N \int_eval:w #1 - \c_seven ; + { #2 #3#4#5#6#7#8#9 } + } +\cs_new:Npn \str_collect_end:wn #1 ; + { + \exp_after:wN \str_collect_end_ii:nnnnnnnnw + \if_case:w \if_num:w #1 > \c_zero #1 \else: 0 \fi: \exp_stop_f: + \or: \or: \or: \or: \or: \or: \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:Npn \str_collect_end_ii:nnnnnnnnw #1#2#3#4#5#6#7#8 #9 \q_stop + { #1#2#3#4#5#6#7#8 } \cs_new_nopar:Npn \str_item:Nn { \exp_args:No \str_item:nn } -\cs_new:Npn \str_item:nn #1#2 +\cs_new:Npn \str_item:nn #1 { - \exp_args:Nf \tl_to_str:n - { \exp_args:Nf \str_item_unsafe:nn { \tl_to_other_str:n {#1} } {#2} } + \exp_last_unbraced:Nf \token_to_str:N + \exp_args:Nf \str_item_unsafe:nn { \tl_to_other_str:n {#1} } } \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 +\cs_new:Npn \str_item_unsafe:nn #1#2 { - \exp_args:Nff \str_item_aux:nn - { \int_eval:n {#2} } - { \str_length_unsafe:n {#1} } + \exp_after:wN \str_item_aux:ww + \int_use:N \int_eval:w #2 \exp_after:wN ; + \int_value:w \str_length_unsafe:n {#1} ; #1 \q_stop } -\cs_new_nopar:Npn \str_item_aux:nn #1#2 +\cs_new:Npn \str_item_aux:ww #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 } + \exp_after:wN \use_i_delimit_by_q_stop:nw + \tex_romannumeral:D \str_skip_c_zero:w #1 + #2 ; } } { \int_compare:nNnTF {#1} < {#2} { - \str_skip_do:nn {#1} - { \use_i_delimit_by_q_stop:nw } + \exp_after:wN \use_i_delimit_by_q_stop:nw + \tex_romannumeral:D \str_skip_c_zero:w #1 ; } { \use_none_delimit_by_q_stop:w } } @@ -335,28 +340,26 @@ \exp_after:wN \str_substr_aux:www \int_value:w \str_length_unsafe:n {#1} \exp_after:wN ; \int_use:N \int_eval:w #2 + \c_zero \exp_after:wN ; - \int_use:N \int_eval:w \exp_args:Nf \str_substr_unsafe:nN {#3} \c_max_int ; + \int_use:N \int_eval:w + \exp_args:Nf \str_substr_aux:nN {#3} \c_max_int ; #1 \q_stop } -\cs_new:Npn \str_substr_unsafe:nN #1 #2 +\cs_new:Npn \str_substr_aux:nN #1 #2 { \tl_if_empty:nTF {#1} {#2} {#1} } \cs_new:Npn \str_substr_aux:www #1; #2; #3; { \exp_args:Nf \str_substr_aux:nnw - { \str_aux_normalize_range:nn {#2} {#1} } - { \str_aux_normalize_range:nn {#3} {#1} } + { \str_substr_normalize_range:nn {#2} {#1} } + { \str_substr_normalize_range:nn {#3} {#1} } } \cs_new:Npn \str_substr_aux: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 } - } + \exp_after:wN \str_collect_delimit_by_q_stop:w + \int_use:N \int_eval:w #2 - #1 \exp_after:wN ; + \tex_romannumeral:D \str_skip_c_zero:w #1 ; } -\cs_new:Npn \str_aux_normalize_range:nn #1#2 +\cs_new:Npn \str_substr_normalize_range:nn #1#2 { \int_eval:n { @@ -383,7 +386,7 @@ \prg_new_conditional:Npnn \str_if_contains_char:NN #1#2 { T , TF } { \exp_after:wN \str_if_contains_char_aux:NN \exp_after:wN #2 - #1 { \prg_map_break:n { ? \fi: } } + \tl_to_str:n \exp_after:wN {#1} { \prg_map_break:n { ? \fi: } } \prg_break_point:n { } \prg_return_false: } @@ -394,14 +397,14 @@ \prg_break_point:n { } \prg_return_false: } -\cs_new_nopar:Npn \str_if_contains_char_aux:NN #1#2 +\cs_new:Npn \str_if_contains_char_aux:NN #1#2 { \if_charcode:w #1 #2 - \exp_after:wN \str_if_contains_char_end: + \exp_after:wN \str_if_contains_char_true: \fi: \str_if_contains_char_aux:NN #1 } -\cs_new_nopar:Npn \str_if_contains_char_end: +\cs_new_nopar:Npn \str_if_contains_char_true: { \prg_map_break:n { \prg_return_true: \use_none:n } } \prg_new_conditional:Npnn \str_aux_octal_use:N #1 { TF } { @@ -433,11 +436,11 @@ \fi: } \group_begin: - \tl_clear:N \l_str_tmpa_tl + \tl_clear:N \l_str_internal_tl \char_set_catcode_other:n { \c_zero } \tl_gset:Nx \g_str_result_tl { \tl_to_str:n { 0123456789ABCDEF } } - \tl_map_inline:Nn \g_str_result_tl - { \char_set_lccode:nn {`#1} {`#1} } + \exp_args:No \tl_map_inline:nn { \g_str_result_tl " } + { \char_set_lccode:nn {`#1} { \c_zero } } \tl_map_inline:Nn \g_str_result_tl { \tl_map_inline:Nn \g_str_result_tl @@ -448,12 +451,12 @@ \tl_const:cx { c_str_byte_ \int_eval:n {"#1##1} _tl } { ^^@ #1 ##1 } - \tl_put_right:Nn \l_str_tmpa_tl { ^^@ } + \tl_put_right:Nn \l_str_internal_tl { ^^@ } } } } \tl_const:Nx \c_str_positive_bytes_tl - { \exp_after:wN \use_none:n \l_str_tmpa_tl } + { \exp_after:wN \use_none:n \l_str_internal_tl } \group_end: \tl_const:cn { c_str_byte_-1_tl } { { } \use_none:n { } } \cs_new:Npn \str_output_byte:n #1 @@ -474,244 +477,166 @@ } \cs_new_nopar:Npn \str_output_end: { \int_eval_end: _tl \cs_end: } -\cs_new_protected_nopar:Npn \str_aux_gmap_result:N #1 +\cs_new:Npn \str_output_byte_pair_be:n #1 + { + \exp_args:Nf \str_output_byte_pair_aux:nnN + { \int_div_truncate:nn { #1 } { "100 } } {#1} \use:nn + } +\cs_new:Npn \str_output_byte_pair_le:n #1 + { + \exp_args:Nf \str_output_byte_pair_aux:nnN + { \int_div_truncate:nn { #1 } { "100 } } {#1} \use_ii_i:nn + } +\cs_new:Npn \str_output_byte_pair_aux:nnN #1#2#3 + { + #3 + { \str_output_byte:n { #1 } } + { \str_output_byte:n { #2 - #1 * "100 } } + } +\cs_new_protected:Npn \str_convert_gmap:N #1 { \tl_gset:Nx \g_str_result_tl { - \exp_after:wN \str_aux_gmap_result_loop:NN + \exp_after:wN \str_convert_gmap_loop:NN \exp_after:wN #1 \g_str_result_tl { ? \prg_map_break: } \prg_break_point:n { } } } -\cs_new_nopar:Npn \str_aux_gmap_result_loop:NN #1#2 +\cs_new:Npn \str_convert_gmap_loop:NN #1#2 { \use_none:n #2 #1#2 - \str_aux_gmap_result_loop:NN #1 + \str_convert_gmap_loop:NN #1 } -\cs_new_protected_nopar:Npn \str_aux_gmap_internal_result:N #1 +\cs_new_protected:Npn \str_convert_gmap_internal:N #1 { \tl_gset:Nx \g_str_result_tl { - \exp_after:wN \str_aux_gmap_internal_result_loop:Nww + \exp_after:wN \str_convert_gmap_internal_loop:Nww \exp_after:wN #1 \g_str_result_tl \s_tl \q_stop \prg_map_break: \s_tl \prg_break_point:n { } } } -\cs_new_nopar:Npn \str_aux_gmap_internal_result_loop:Nww #1 #2 \s_tl #3 \s_tl +\cs_new:Npn \str_convert_gmap_internal_loop:Nww #1 #2 \s_tl #3 \s_tl { \use_none_delimit_by_q_stop:w #3 \q_stop #1 {#3} - \str_aux_gmap_internal_result_loop:Nww #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_protected:Npn \str_escape_use:NNNn #1#2#3#4 - { - \str_aux_escape:NNNn #1#2#3 {#4} - \g_str_result_tl - } -\cs_new_protected:Npn \str_aux_escape:NNNn #1#2#3#4 + \str_convert_gmap_internal_loop:Nww #1 + } +\cs_new_protected:Npn \str_if_flag_error:nnx #1 + { + \flag_if_raised:nTF {#1} + { \msg_kernel_error:nnx { str } } + { \use_none:nn } + } +\cs_new_protected:Npn \str_if_flag_no_error:nnx #1#2#3 + { \flag_if_raised:nT {#1} { \bool_gset_true:N \g_str_error_bool } } +\cs_new_protected:Npn \str_if_flag_times:nT #1#2 + { \flag_if_raised:nT {#1} { #2~(x \flag_height:n {#1} ) } } +\cs_new_protected_nopar:Npn \str_set_convert:Nnnn + { \str_convert_aux_i:nNNnnn { } \tl_set_eq:NN } +\cs_new_protected_nopar:Npn \str_gset_convert:Nnnn + { \str_convert_aux_i:nNNnnn { } \tl_gset_eq:NN } +\prg_new_protected_conditional:Npnn + \str_set_convert:Nnnn #1#2#3#4 { T , F , TF } + { + \bool_gset_false:N \g_str_error_bool + \str_convert_aux_i:nNNnnn + { \cs_set_eq:NN \str_if_flag_error:nnx \str_if_flag_no_error:nnx } + \tl_set_eq:NN #1 {#2} {#3} {#4} + \bool_if:NTF \g_str_error_bool \prg_return_false: \prg_return_true: + } +\prg_new_protected_conditional:Npnn + \str_gset_convert:Nnnn #1#2#3#4 { T , F , TF } + { + \bool_gset_false:N \g_str_error_bool + \str_convert_aux_i:nNNnnn + { \cs_set_eq:NN \str_if_flag_error:nnx \str_if_flag_no_error:nnx } + \tl_gset_eq:NN #1 {#2} {#3} {#4} + \bool_if:NTF \g_str_error_bool \prg_return_false: \prg_return_true: + } +\cs_new_protected:Npn \str_convert_aux_i:nNNnnn #1#2#3#4#5#6 { \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 } + #1 \str_gset_other:Nn \g_str_result_tl {#4} - \int_zero:N \l_str_tmpa_int - \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 - } - \tl_gput_left:Nx \g_str_result_tl - { \str_aux_toks_range:nn \c_zero \l_str_tmpa_int } - \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:NN \str_aux_escape_unescaped:N \prg_do_nothing: -\cs_new_eq:NN \str_aux_escape_escaped:N \prg_do_nothing: -\cs_new_eq:NN \str_aux_escape_raw:N \prg_do_nothing: -\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: } - \tex_toks:D \l_str_tmpa_int \exp_after:wN { \g_str_result_tl } - \int_incr:N \l_str_tmpa_int - \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 } - { - \l_str_char_int = "0 - \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_nopar:Npn \str_aux_escape_x_unbraced_i:N #1 - { - \str_aux_hexadecimal_use:NTF #1 - { \str_aux_escape_x_unbraced_ii:N } - { \exp_stop_f: \str_aux_escape_x_end: #1 } - } -\cs_new_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_use:NTF #1 - { \exp_stop_f: \str_aux_escape_x_end: } - { \exp_stop_f: \str_aux_escape_x_end: #1 } - } - } -\cs_new_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_use:NTF #1 - { \str_aux_escape_x_braced_loop:N } - { \exp_stop_f: \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_kernel_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: - { - \tex_lccode:D \c_zero \l_str_char_int - \tl_to_lowercase:n - { - \tl_gset:Nx \g_str_result_tl - { \if_false: } \fi: - \str_aux_escape_raw:N ^^@ - \str_aux_escape_loop:N - } - } -\group_end: -\cs_new_protected:Npn \str_set_convert:Nnnn - { \str_convert_aux_i:NNnnn \tl_set_eq:NN } -\cs_new_protected:Npn \str_gset_convert:Nnnn - { \str_convert_aux_i:NNnnn \tl_gset_eq:NN } -\cs_new_protected:Npn \str_convert_aux_i:NNnnn #1#2#3#4#5 - { - \group_begin: - \str_gset_other:Nn \g_str_result_tl {#5} - \exp_after:wN \str_convert_aux_ii:wwwnn - \tl_to_str:n {#3} /// \q_stop - { from } { input } \str_convert_from_native: \use_i:nn - + \tl_to_str:n {#5} /// \q_stop + { decode } { unescape } + \prg_do_nothing: + \str_convert_decode_: \exp_after:wN \str_convert_aux_ii:wwwnn - \tl_to_str:n {#4} /// \q_stop - { to } { output } \str_convert_to_native: \use_ii:nn - + \tl_to_str:n {#6} /// \q_stop + { encode } { escape } + \use_ii_i:nn + \str_convert_encode_: \group_end: - #1 #2 \g_str_result_tl + #2 #3 \g_str_result_tl } -\cs_new_protected:Npn \str_convert_aux_ii:wwwnn #1 / #2 // #3 \q_stop #4#5 +\cs_new_protected:Npn \str_convert_aux_ii:wwwnn + #1 / #2 // #3 \q_stop #4#5 { - \str_convert_aux_iii:nnF {#4} {#1} {native} - \str_convert_aux_iii:nnF {#5} {#2} { } - \exp_args:Ncc \str_convert_aux_v:NNnNN + \str_convert_aux_iv:nnn {enc} {#4} {#1} + \str_convert_aux_iv:nnn {esc} {#5} {#2} + \exp_args:Ncc \str_convert_aux_iii:NNnNN { str_convert_#4_#1: } { str_convert_#5_#2: } {#2} } -\cs_new_protected:Npn \str_convert_aux_iii:nnF #1#2#3 +\cs_new_protected:Npn \str_convert_aux_iii:NNnNN #1#2#3#4#5 { - \cs_if_exist:cF { str_convert_#1_#2: } - { - \exp_args:Nx \str_convert_aux_iv:nnnF - { \str_aux_lowercase_alphanum:n {#2} } - {#1} {#2} {#3} - } + \if_meaning:w #1 #5 + \tl_if_empty:nF {#3} + { \msg_kernel_error:nnx { str } { native-escaping } {#3} } + #1 + \else: + #4 #2 #1 + \fi: } -\cs_new_protected:Npn \str_convert_aux_iv:nnnF #1#2#3#4 +\cs_new_protected:Npn \str_convert_aux_iv:nnn #1#2#3 { - \cs_if_exist:cF { str_convert_#2_#1: } + \cs_if_exist:cF { str_convert_#2_#3: } { - \group_begin: - \str_load_catcodes: - \str_load_one:n {#1} - \group_end: - } - \cs_if_exist:cTF { str_convert_#2_#1: } - { \cs_gset_eq:cc { str_convert_#2_#3: } { str_convert_#2_#1: } } - { - \msg_kernel_error:nnx { str } { unknown-#2 } {#3} - \cs_gset_eq:cc { str_convert_#2_#3: } { str_convert_#2_#4: } + \exp_args:Nx \str_convert_aux_v:nnnn + { \str_convert_lowercase_alphanum:n {#3} } + {#1} {#2} {#3} } } -\cs_new_protected:Npn \str_convert_aux_v:NNnNN #1#2#3#4#5 +\cs_new_protected:Npn \str_convert_aux_v:nnnn #1#2#3#4 { - #5 { } {#1} - \cs_if_eq:NNTF #1 #4 + \cs_if_exist:cF { str_convert_#3_#1: } { - \tl_if_empty:nF {#3} - { \msg_kernel_error:nnx { str } { native-ignore-escaping } {#3} } + \prop_get:NnNF \g_str_file_prop {#1} \l_str_internal_tl + { \tl_set:Nn \l_str_internal_tl {#1} } + \cs_if_exist:cF { str_convert_#3_ \l_str_internal_tl : } + { + \file_if_exist:nTF { l3str-#2- \l_str_internal_tl .def } + { + \group_begin: + \str_load_catcodes: + \file_input:n { l3str-#2- \l_str_internal_tl .def } + \group_end: + } + { + \tl_clear:N \l_str_internal_tl + \msg_kernel_error:nnxx { str } { unknown-#2 } {#4} {#1} + } + } + \cs_if_exist:cF { str_convert_#3_#1: } + { + \cs_gset_eq:cc { str_convert_#3_#1: } + { str_convert_#3_ \l_str_internal_tl : } + } } - { #2 } - #5 {#1} { } + \cs_gset_eq:cc { str_convert_#3_#4: } { str_convert_#3_#1: } } -\cs_new:Npn \str_aux_lowercase_alphanum:n #1 +\cs_new:Npn \str_convert_lowercase_alphanum:n #1 { - \exp_after:wN \str_aux_lowercase_alphanum_loop:N + \exp_after:wN \str_convert_lowercase_alphanum_loop:N \tl_to_str:n {#1} { ? \prg_map_break: } \prg_break_point:n { } } -\cs_new:Npn \str_aux_lowercase_alphanum_loop:N #1 +\cs_new:Npn \str_convert_lowercase_alphanum_loop:N #1 { \use_none:n #1 \if_num:w `#1 < \c_ninety_one @@ -730,312 +655,287 @@ \fi: \fi: \fi: - \str_aux_lowercase_alphanum_loop:N - } -\cs_new_protected_nopar:Npn \str_convert_from_internal: { } -\cs_new_protected_nopar:Npn \str_convert_to_internal: { } -\cs_new_protected:Npn \str_load:n #1 - { - \group_begin: - \str_load_catcodes: - \clist_map_inline:nn {#1} - { - \exp_args:Nx \str_load_one:n - { \str_aux_lowercase_alphanum:n {#1} } - } - \group_end: - } -\cs_new_protected:Npn \str_load_one:n #1 - { - \cs_if_exist:cF { str_convert_from_ #1 : } - { - \cs_if_exist:cF { str_convert_input_#1: } - { - \file_if_exist:nTF { l3str- #1 .def } - { \file_input:n { l3str- #1 .def } } - { \str_load_alias:n {#1} } - } - } + \str_convert_lowercase_alphanum_loop:N } -\cs_new_protected:Npn \str_load_alias:n #1 - { - \exp_args:NNx \prop_get:NnNTF \g_str_aliases_prop {#1} \l_str_tmpa_tl - { - \str_load_one:n { \l_str_tmpa_tl } - \cs_if_exist:cTF - { str_convert_from_ \l_str_tmpa_tl : } - { - \str_load_alias_aux:nnn {#1} { \l_str_tmpa_tl } { from } - \str_load_alias_aux:nnn {#1} { \l_str_tmpa_tl } { to } - } - { - \str_load_alias_aux:nnn {#1} { \l_str_tmpa_tl } { input } - \str_load_alias_aux:nnn {#1} { \l_str_tmpa_tl } { output } - } - } - { \msg_kernel_error:nnx { str } { file-not-found } {#1} } - } -\cs_new_protected:Npn \str_load_alias_aux:nnn #1#2#3 - { \cs_new_eq:cc { str_convert_#3_#1: } { str_convert_#3_#2: } } \cs_new_protected:Npn \str_load_catcodes: { \char_set_catcode_escape:N \\ \char_set_catcode_group_begin:N \{ \char_set_catcode_group_end:N \} + \char_set_catcode_math_toggle:N \$ + \char_set_catcode_alignment:N \& + \char_set_catcode_parameter:N \# \char_set_catcode_math_superscript:N \^ \char_set_catcode_ignore:N \ % - \tl_map_function:nN { abcdefghijklmnopqrstuvwxyz_:ABCDEFN } + \char_set_catcode_space:N \~ + \tl_map_function:nN { abcdefghijklmnopqrstuvwxyz_:ABCDEFILNPSTUX } \char_set_catcode_letter:N - \tl_map_function:nN { 0123456789"'?*+ } + \tl_map_function:nN { 0123456789"'?*+-.(),`!/<>[];= } \char_set_catcode_other:N \char_set_catcode_comment:N \% \int_set:Nn \tex_endlinechar:D {32} } -\cs_new_protected:Npn \str_convert_from_eight_bit:n #1 +\pdftex_if_engine:TF + { \cs_new_eq:NN \str_filter_bytes:n \use:n } + { + \cs_new:Npn \str_filter_bytes:n #1 + { + \str_filter_bytes_aux:N #1 + { ? \prg_map_break: } + \prg_break_point:n { } + } + \cs_new:Npn \str_filter_bytes_aux:N #1 + { + \use_none:n #1 + \if_num:w `#1 < 256 \exp_stop_f: + #1 + \else: + \flag_raise:n { str_byte } + \fi: + \str_filter_bytes_aux:N + } + } +\pdftex_if_engine:TF + { \cs_new_protected_nopar:Npn \str_convert_unescape_: { } } + { + \cs_new_protected_nopar:Npn \str_convert_unescape_: + { + \flag_clear:n { str_byte } + \tl_gset:Nx \g_str_result_tl + { \exp_args:No \str_filter_bytes:n \g_str_result_tl } + \str_if_flag_error:nnx { str_byte } { non-byte } { bytes } + } + } +\cs_new_eq:NN \str_convert_unescape_bytes: \str_convert_unescape_: +\cs_new_protected_nopar:Npn \str_convert_escape_: { } +\cs_new_eq:NN \str_convert_escape_bytes: \str_convert_escape_: +\cs_new_protected_nopar:Npn \str_convert_decode_: + { \str_convert_gmap:N \str_decode_native_char:N } +\cs_new:Npn \str_decode_native_char:N #1 + { #1 \s_tl \int_value:w `#1 \s_tl } +\group_begin: + \char_set_catcode_other:n { 0 } + \pdftex_if_engine:TF + { + \cs_new_protected_nopar:Npn \str_convert_encode_: + { + \flag_clear:n { str_error } + \str_convert_gmap_internal:N \str_encode_native_char:n + \str_if_flag_error:nnx { str_error } + { pdfTeX-native-overflow } { } + } + \cs_new:Npn \str_encode_native_char:n #1 + { + \if_num:w #1 < \c_two_hundred_fifty_six + \str_output_byte:n {#1} + \else: + \flag_raise:n { str_error } + ? + \fi: + } + \msg_kernel_new:nnnn { str } { pdfTeX-native-overflow } + { Character~code~too~large~for~pdfTeX. } + { + The~pdfTeX~engine~only~supports~8-bit~characters:~ + valid~character~codes~are~in~the~range~[0,255].~ + To~manipulate~arbitrary~Unicode,~use~LuaTeX~or~XeTeX. + } + } + { + \cs_new_protected_nopar:Npn \str_convert_encode_: + { + \tex_lccode:D \c_zero \c_zero + \int_zero:N \l_str_internal_int + \tl_set_eq:NN \l_str_internal_tl \g_str_result_tl + \tl_gclear:N \g_str_result_tl + \exp_after:wN \str_encode_native_loop:w + \l_str_internal_tl \s_tl { \q_stop \prg_map_break: } \s_tl + \prg_break_point:n { \str_encode_native_flush: } + } + \cs_new_protected:Npn \str_encode_native_loop:w #1 \s_tl #2 \s_tl + { + \use_none_delimit_by_q_stop:w #2 \q_stop + \if_num:w \l_str_internal_int = \c_two_hundred_fifty_five + \str_encode_native_flush: + \l_str_internal_int \c_zero + \fi: + \tex_advance:D \l_str_internal_int \c_one + \tex_lccode:D \l_str_internal_int \int_eval:w #2 \int_eval_end: + \str_encode_native_loop:w + } + \cs_new_protected_nopar:Npn \str_encode_native_flush: + { + \use:x + { + \tl_to_lowercase:n + { + \tl_gput_right:Nx \exp_not:N \g_str_result_tl + { + \exp_after:wN \str_encode_native_filter:N + \c_str_positive_bytes_tl + { ? = \c_zero \fi: \prg_map_break: } + \prg_break_point:n { } + } + } + } + } + \cs_new:Npn \str_encode_native_filter:N #1 + { + \if_num:w `#1 > \l_str_internal_int + \exp_after:wN \prg_map_break: + \fi: + \if_num:w \tex_lccode:D `#1 = \c_zero + ^^@ + \else: + #1 + \fi: + \str_encode_native_filter:N + } + } +\group_end: +\cs_new_protected:Npn \str_declare_eight_bit_encoding:nnn #1#2#3 + { + \tl_set:Nn \l_str_internal_tl {#1} + \cs_new_protected_nopar:cpn { str_convert_decode_#1: } + { \str_convert_decode_eight_bit:n {#1} } + \cs_new_protected_nopar:cpn { str_convert_encode_#1: } + { \str_convert_encode_eight_bit:n {#1} } + \tl_const:cn { c_str_encoding_#1_tl } {#2} + \tl_const:cn { c_str_encoding_#1_missing_tl } {#3} + } +\cs_new_protected:Npn \str_convert_decode_eight_bit:n #1 { \group_begin: - \int_zero:N \l_str_tmpa_int - \exp_last_unbraced:Nx \str_convert_from_eight_bit_load:nn + \int_zero:N \l_str_internal_int + \exp_last_unbraced:Nx \str_decode_eight_bit_load:nn { \tl_use:c { c_str_encoding_#1_tl } } { \q_stop \prg_map_break: } { } \prg_break_point:n { } - \exp_last_unbraced:Nx \str_convert_from_eight_bit_load_missing:n + \exp_last_unbraced:Nx \str_decode_eight_bit_load_missing:n { \tl_use:c { c_str_encoding_#1_missing_tl } } { \q_stop \prg_map_break: } \prg_break_point:n { } - \str_aux_gmap_result:N \str_convert_from_eight_bit_aux:N + \flag_clear:n { str_error } + \str_convert_gmap:N \str_decode_eight_bit_char:N + \str_if_flag_error:nnx { str_error } { decode-8-bit } {#1} \group_end: } -\cs_new_protected_nopar:Npn \str_convert_from_eight_bit_load:nn #1#2 +\cs_new_protected:Npn \str_decode_eight_bit_load:nn #1#2 { \use_none_delimit_by_q_stop:w #1 \q_stop - \tex_dimen:D "#1 = \l_str_tmpa_int sp \scan_stop: - \tex_skip:D \l_str_tmpa_int = "#1 sp \scan_stop: - \tex_toks:D \l_str_tmpa_int \exp_after:wN { \int_value:w "#2 } - \tex_advance:D \l_str_tmpa_int \c_one - \str_convert_from_eight_bit_load:nn + \tex_dimen:D "#1 = \l_str_internal_int sp \scan_stop: + \tex_skip:D \l_str_internal_int = "#1 sp \scan_stop: + \tex_toks:D \l_str_internal_int \exp_after:wN { \int_value:w "#2 } + \tex_advance:D \l_str_internal_int \c_one + \str_decode_eight_bit_load:nn } -\cs_new_protected_nopar:Npn \str_convert_from_eight_bit_load_missing:n #1 +\cs_new_protected:Npn \str_decode_eight_bit_load_missing:n #1 { \use_none_delimit_by_q_stop:w #1 \q_stop - \tex_dimen:D "#1 = \l_str_tmpa_int sp \scan_stop: - \tex_skip:D \l_str_tmpa_int = "#1 sp \scan_stop: - \tex_toks:D \l_str_tmpa_int \exp_after:wN + \tex_dimen:D "#1 = \l_str_internal_int sp \scan_stop: + \tex_skip:D \l_str_internal_int = "#1 sp \scan_stop: + \tex_toks:D \l_str_internal_int \exp_after:wN { \int_use:N \c_str_replacement_char_int } - \tex_advance:D \l_str_tmpa_int \c_one - \str_convert_from_eight_bit_load_missing:n + \tex_advance:D \l_str_internal_int \c_one + \str_decode_eight_bit_load_missing:n } -\cs_new:Npn \str_convert_from_eight_bit_aux:N #1 +\cs_new:Npn \str_decode_eight_bit_char:N #1 { #1 \s_tl - \if_num:w \tex_dimen:D `#1 < \l_str_tmpa_int + \if_num:w \tex_dimen:D `#1 < \l_str_internal_int \if_num:w \tex_skip:D \tex_dimen:D `#1 = `#1 \exp_stop_f: \tex_the:D \tex_toks:D \tex_dimen:D \fi: \fi: \int_value:w `#1 \s_tl } -\cs_new_protected:Npn \str_convert_to_eight_bit:n #1 +\cs_new_protected:Npn \str_convert_encode_eight_bit:n #1 { \group_begin: - \int_zero:N \l_str_tmpa_int - \exp_last_unbraced:Nx \str_convert_to_eight_bit_load:nn + \int_zero:N \l_str_internal_int + \exp_last_unbraced:Nx \str_encode_eight_bit_load:nn { \tl_use:c { c_str_encoding_#1_tl } } { \q_stop \prg_map_break: } { } \prg_break_point:n { } - \str_aux_gmap_internal_result:N \str_convert_to_eight_bit_aux:n + \flag_clear:n { str_error } + \str_convert_gmap_internal:N \str_encode_eight_bit_char:n + \str_if_flag_error:nnx { str_error } { encode-8-bit } {#1} \group_end: } -\cs_new_protected_nopar:Npn \str_convert_to_eight_bit_load:nn #1#2 +\cs_new_protected:Npn \str_encode_eight_bit_load:nn #1#2 { \use_none_delimit_by_q_stop:w #1 \q_stop - \tex_dimen:D "#2 = \l_str_tmpa_int sp \scan_stop: - \tex_skip:D \l_str_tmpa_int = "#2 sp \scan_stop: - \exp_args:NNf \tex_toks:D \l_str_tmpa_int + \tex_dimen:D "#2 = \l_str_internal_int sp \scan_stop: + \tex_skip:D \l_str_internal_int = "#2 sp \scan_stop: + \exp_args:NNf \tex_toks:D \l_str_internal_int { \str_output_byte:n { "#1 } } - \tex_advance:D \l_str_tmpa_int \c_one - \str_convert_to_eight_bit_load:nn + \tex_advance:D \l_str_internal_int \c_one + \str_encode_eight_bit_load:nn } -\cs_new:Npn \str_convert_to_eight_bit_aux:n #1 +\cs_new:Npn \str_encode_eight_bit_char:n #1 { \if_num:w #1 > \c_max_register_int - \msg_expandable_kernel_error:nnn - { str } { eight-bit-to-byte-overflow } {#1} + \flag_raise:n { str_error } \else: - \if_num:w \tex_dimen:D #1 < \l_str_tmpa_int + \if_num:w \tex_dimen:D #1 < \l_str_internal_int \if_num:w \tex_skip:D \tex_dimen:D #1 = #1 \exp_stop_f: \tex_the:D \tex_toks:D \tex_dimen:D #1 \exp_stop_f: \exp_after:wN \exp_after:wN \exp_after:wN \use_none:nn \fi: \fi: - \str_convert_to_eight_bit_aux_ii:n {#1} + \str_encode_eight_bit_char_aux:n {#1} \fi: } -\cs_new:Npn \str_convert_to_eight_bit_aux_ii:n #1 +\cs_new:Npn \str_encode_eight_bit_char_aux:n #1 { \if_num:w #1 < \c_two_hundred_fifty_six \str_output_byte:n {#1} \else: - \msg_expandable_kernel_error:nn { str } { eight-bit-to-byte } + \flag_raise:n { str_error } \fi: } -\cs_new_protected:Npn \str_encoding_eight_bit:n #1 +\msg_kernel_new:nnn { str } { unknown-esc } + { Escaping~scheme~'#1'~(filtered:~'#2')~unknown. } +\msg_kernel_new:nnn { str } { unknown-enc } + { Encoding~scheme~'#1'~(filtered:~'#2')~unknown. } +\msg_kernel_new:nnnn { str } { native-escaping } + { The~'native'~encoding~scheme~does~not~support~any~escaping. } { - \cs_new_protected:cpn { str_convert_from_#1: } - { \str_convert_from_eight_bit:n {#1} } - \cs_new_protected:cpn { str_convert_to_#1: } - { \str_convert_to_eight_bit:n {#1} } - } -\pdftex_if_engine:TF - { \cs_new_eq:NN \str_filter_bytes:n \use:n } - { - \cs_new_nopar:Npn \str_filter_bytes:n #1 - { - \str_filter_bytes_aux:N #1 - { ? \prg_map_break: } - \prg_break_point:n { } - } - \cs_new_nopar:Npn \str_filter_bytes_aux:N #1 - { - \use_none:n #1 - \if_num:w `#1 < 256 \exp_stop_f: #1 \fi: - \str_filter_bytes_aux:N - } + Since~native~strings~do~not~consist~in~bytes,~ + none~of~the~escaping~methods~make~sense.~ + The~specified~escaping,~'#1',~will be ignored. } -\pdftex_if_engine:TF - { \cs_new_protected_nopar:Npn \str_convert_input_: { } } +\msg_kernel_new:nnn { str } { file-not-found } + { File~'l3str-#1.def'~not~found. } +\pdftex_if_engine:F { - \cs_new_protected_nopar:Npn \str_convert_input_: + \msg_kernel_new:nnnn { str } { non-byte } + { String~invalid~in~escaping~'#1':~it~may~only~contain~bytes. } { - \tl_gset:Nx \g_str_result_tl - { \exp_args:No \str_filter_bytes:n \g_str_result_tl } - } - } -\cs_new_eq:NN \str_convert_input_bytes: \str_convert_input_: -\cs_new_protected_nopar:Npn \str_convert_output_: { } -\cs_new_eq:NN \str_convert_output_bytes: \str_convert_output_: -\cs_new_protected_nopar:Npn \str_convert_from_native: - { \str_aux_gmap_result:N \str_convert_from_native_aux:N } -\cs_new:Npn \str_convert_from_native_aux:N #1 - { #1 \s_tl \int_value:w `#1 \s_tl } -\cs_new_protected_nopar:Npn \str_convert_to_native: - { - \tl_set_eq:NN \l_str_tmpa_tl \g_str_result_tl - \str_aux_convert_to_native:n - { - \exp_after:wN \str_convert_to_native_aux:w - \l_str_tmpa_tl \s_tl { \q_stop \prg_map_break: } \s_tl - } - } -\cs_new_protected_nopar:Npn \str_convert_to_native_aux:w #1 \s_tl #2 \s_tl - { - \use_none_delimit_by_q_stop:w #2 \q_stop - \str_aux_convert_to_native_step:n {#2} - \str_convert_to_native_aux:w - } -\cs_new_protected_nopar:Npn \str_aux_convert_to_native:n #1 - { - \tex_lccode:D \c_zero \c_zero - \int_zero:N \l_str_tmpa_int - \tl_gclear:N \g_str_result_tl - #1 - \prg_break_point:n { \str_aux_convert_to_native_flush: } - } -\cs_new_protected_nopar:Npn \str_aux_convert_to_native_step:n #1 - { - \if_num:w \l_str_tmpa_int = \c_two_hundred_fifty_five - \str_aux_convert_to_native_flush: - \l_str_tmpa_int \c_zero - \fi: - \tex_advance:D \l_str_tmpa_int \c_one - \if_int_compare:w #1 > \c_max_char_int - \msg_kernel_error:nnx { str } { overflow } {#1} - \tex_lccode:D \l_str_tmpa_int \c_str_replacement_char_int - \else: - \tex_lccode:D \l_str_tmpa_int \int_eval:w #1 \int_eval_end: - \fi: - } -\cs_new_protected_nopar:Npn \str_aux_convert_to_native_flush: - { - \use:x - { - \tl_to_lowercase:n + Some~characters~in~the~string~you~asked~to~convert~are~not~ + 8-bit~characters.~Perhaps~the~string~is~a~'native'~Unicode~string?~ + If~it~is,~try~using\\ + \\ + \iow_indent:n { - \tl_gput_right:Nx \exp_not:N \g_str_result_tl - { - \exp_after:wN \str_aux_convert_to_native_filter:N - \c_str_positive_bytes_tl - { ? = \c_zero \fi: \prg_map_break: } - \prg_break_point:n { } - } + \iow_char:N\\str_set_convert:Nnnn \\ + \ \ <str~var>~\{~<string>~\}~\{~native~\}~\{~<target~encoding>~\} } } } -\group_begin: - \char_set_catcode_other:n { 0 } - \cs_new:Npn \str_aux_convert_to_native_filter:N #1 - { - \if_num:w `#1 > \l_str_tmpa_int - \exp_after:wN \prg_map_break: - \fi: - \if_num:w \tex_lccode:D `#1 = \c_zero - ^^@ - \else: - #1 - \fi: - \str_aux_convert_to_native_filter:N - } -\group_end: -\msg_kernel_new:nnnn { str } { x-missing-brace } - { Missing~closing~brace~in~ \token_to_str:N \x ~byte~sequence. } +\msg_kernel_new:nnnn { str } { decode-8-bit } + { Invalid~string~in~encoding~'#1'. } { - You~wrote~something~like~ - `\iow_char:N\\x\{ \int_to_hexadecimal:n { \l_str_char_int }'.~ - The~closing~brace~is~missing. + LaTeX~came~across~a~byte~which~is~not~defined~to~represent~ + any~character~in~the~encoding~'#1'. } -\msg_kernel_new:nnnn { str } { overflow } - { Character~code~#1~too~big. } +\msg_kernel_new:nnnn { str } { encode-8-bit } + { Unicode~string~cannot~be~converted~to~encoding~'#1'. } { - \int_compare:nNnTF {#1} > { 1114111 } - { The~Unicode~standard~limits~code~points~to~1114111. } - { - The~pdfTeX~engine~only~supports~8-bit~characters:~ - valid~character~codes~are~in~the~range~[0,255].~ - To~manipulate~arbitrary~Unicode,~use~LuaTeX~or~XeTeX. - } + The~encoding~'#1'~only~contains~a~subset~of~all~Unicode~characters.~ + LaTeX~was~asked~to~convert~a~string~to~that~encoding,~but~that~ + string~contains~a~character~that~'#1'~does~not~support. } -\msg_kernel_new:nnn { str } { convert-input } - { Input~scheme~`#1'~unknown. } -\msg_kernel_new:nnn { str } { convert-from } - { Encoding~`#1'~unknown. } -\msg_kernel_new:nnn { str } { convert-to } - { Encoding~`#1'~unknown.~Using~UTF-8. } -\msg_kernel_new:nnn { str } { convert-output } - { Output~scheme~`#1~unknown. } -\msg_kernel_new:nnn { str } { to-native } - { Use~\str_set_convert:Nnn to~convert~to~native~strings. } -\msg_kernel_new:nnn { str } { unicode-surrogate } - { Code~point~#1~is~an~unpaired~surrogate. } -\msg_kernel_new:nnn { str } { utf16-surrogate } - { UTF-16~unpaired~surrogate~#1. } -\msg_kernel_new:nnn { str } { utf16-odd } - { UTF-16~dangling~byte~#1. } -\msg_kernel_new:nnn { str } { utf8-extra-conti } - { UTF-8~extra~continuation~byte~#1. } -\msg_kernel_new:nnn { str } { utf8-missing-conti } - { UTF-8~missing~continuation~byte~#1. } -\msg_kernel_new:nnn { str } { utf8-invalid-byte } - { Byte~#1~cannot~appear~in~UTF-8. } -\msg_kernel_new:nnn { str } { utf8-overlong } - { Overlong~UTF-8~byte~sequence~for~code~point~#1. } -\msg_kernel_new:nnn { str } { utf8-premature-end } - { Incomplete~last~UTF-8~character. } -\msg_kernel_new:nnn { str } { utf8-overflow } - { Code~point~#1~too~large~(UTF-8). } -\msg_kernel_new:nnn { str } { utf32-overflow } - { Code~point~too~large~(UTF-32~`#1'). } -\msg_kernel_new:nnn { str } { utf32-truncated } - { Truncated~UTF-32~string~`...#1'. } \cs_set:Npn \str_length_skip_spaces:N { \exp_args:No \str_length_skip_spaces:n } \cs_set_eq:NN \str_length_skip_spaces:n \str_length_ignore_spaces:n |