summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/tex/latex/l3experimental/l3str/l3str.sty
diff options
context:
space:
mode:
Diffstat (limited to 'Master/texmf-dist/tex/latex/l3experimental/l3str/l3str.sty')
-rw-r--r--Master/texmf-dist/tex/latex/l3experimental/l3str/l3str.sty1040
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