11// good luck to those that follow; here be dragons
22
33use crate :: string:: {
4- is_digit, is_linebreak, is_loc_word , is_space, is_uni_digit, is_uni_linebreak, is_uni_space,
5- is_uni_word , is_word, lower_ascii, lower_locate , lower_unicode, upper_locate , upper_unicode,
4+ is_digit, is_linebreak, is_space, is_uni_digit, is_uni_linebreak, is_uni_space, is_uni_word ,
5+ is_word, lower_ascii, lower_unicode, upper_unicode,
66} ;
77
8- use super :: { MAXREPEAT , SreAtCode , SreCatCode , SreInfo , SreOpcode , StrDrive , StringCursor } ;
8+ use super :: { Locale , MAXREPEAT , SreAtCode , SreCatCode , SreInfo , SreOpcode , StrDrive , StringCursor } ;
99use alloc:: { vec, vec:: Vec } ;
1010use core:: { convert:: TryFrom , ptr:: null} ;
1111use optional:: Optioned ;
@@ -18,6 +18,7 @@ pub struct Request<'a, S> {
1818 pub pattern_codes : & ' a [ u32 ] ,
1919 pub match_all : bool ,
2020 pub must_advance : bool ,
21+ pub locale : Locale ,
2122}
2223
2324impl < ' a , S : StrDrive > Request < ' a , S > {
@@ -38,6 +39,7 @@ impl<'a, S: StrDrive> Request<'a, S> {
3839 pattern_codes,
3940 match_all,
4041 must_advance : false ,
42+ locale : Locale :: default ( ) ,
4143 }
4244 }
4345}
@@ -674,20 +676,24 @@ fn _match<S: StrDrive>(req: &Request<'_, S>, state: &mut State, mut ctx: MatchCo
674676 }
675677 SreOpcode :: CATEGORY => {
676678 let cat_code = SreCatCode :: try_from ( ctx. peek_code ( req, 1 ) ) . unwrap ( ) ;
677- if ctx. at_end ( req) || !category ( cat_code, ctx. peek_char :: < S > ( ) ) {
679+ if ctx. at_end ( req)
680+ || !category ( cat_code, ctx. peek_char :: < S > ( ) , req. locale )
681+ {
678682 break ' result false ;
679683 }
680684 ctx. skip_code ( 2 ) ;
681685 ctx. advance_char :: < S > ( ) ;
682686 }
683- SreOpcode :: IN => general_op_in ! ( charset) ,
687+ SreOpcode :: IN => general_op_in ! ( |set , c| charset( set , c , req . locale ) ) ,
684688 SreOpcode :: IN_IGNORE => {
685- general_op_in ! ( |set, c| charset( set, lower_ascii( c) ) )
689+ general_op_in ! ( |set, c| charset( set, lower_ascii( c) , req . locale ) )
686690 }
687691 SreOpcode :: IN_UNI_IGNORE => {
688- general_op_in ! ( |set, c| charset( set, lower_unicode( c) ) )
692+ general_op_in ! ( |set, c| charset( set, lower_unicode( c) , req. locale) )
693+ }
694+ SreOpcode :: IN_LOC_IGNORE => {
695+ general_op_in ! ( |set, c| charset_loc_ignore( set, c, req. locale) )
689696 }
690- SreOpcode :: IN_LOC_IGNORE => general_op_in ! ( charset_loc_ignore) ,
691697 SreOpcode :: MARK => {
692698 state
693699 . marks
@@ -837,13 +843,17 @@ fn _match<S: StrDrive>(req: &Request<'_, S>, state: &mut State, mut ctx: MatchCo
837843 SreOpcode :: NOT_LITERAL_UNI_IGNORE => {
838844 general_op_literal ! ( |code, c| code != lower_unicode( c) )
839845 }
840- SreOpcode :: LITERAL_LOC_IGNORE => general_op_literal ! ( char_loc_ignore) ,
846+ SreOpcode :: LITERAL_LOC_IGNORE => {
847+ general_op_literal ! ( |code, c| char_loc_ignore( code, c, req. locale) )
848+ }
841849 SreOpcode :: NOT_LITERAL_LOC_IGNORE => {
842- general_op_literal ! ( |code, c| !char_loc_ignore( code, c) )
850+ general_op_literal ! ( |code, c| !char_loc_ignore( code, c, req . locale ) )
843851 }
844852 SreOpcode :: GROUPREF => general_op_groupref ! ( |x| x) ,
845853 SreOpcode :: GROUPREF_IGNORE => general_op_groupref ! ( lower_ascii) ,
846- SreOpcode :: GROUPREF_LOC_IGNORE => general_op_groupref ! ( lower_locate) ,
854+ SreOpcode :: GROUPREF_LOC_IGNORE => {
855+ general_op_groupref ! ( |c| req. locale. lower( c) )
856+ }
847857 SreOpcode :: GROUPREF_UNI_IGNORE => general_op_groupref ! ( lower_unicode) ,
848858 SreOpcode :: GROUPREF_EXISTS => {
849859 let ( group_start, group_end) =
@@ -1042,7 +1052,7 @@ fn search_info_charset<S: StrDrive>(
10421052 req. must_advance = false ;
10431053
10441054 loop {
1045- while !ctx. at_end ( req) && !charset ( set, ctx. peek_char :: < S > ( ) ) {
1055+ while !ctx. at_end ( req) && !charset ( set, ctx. peek_char :: < S > ( ) , req . locale ) {
10461056 ctx. advance_char :: < S > ( ) ;
10471057 }
10481058 if ctx. at_end ( req) {
@@ -1226,27 +1236,27 @@ fn at<S: StrDrive>(req: &Request<'_, S>, ctx: &MatchContext, at_code: SreAtCode)
12261236 }
12271237 SreAtCode :: END_LINE => ctx. at_linebreak ( req) || ctx. at_end ( req) ,
12281238 SreAtCode :: END_STRING => ctx. at_end ( req) ,
1229- SreAtCode :: LOC_BOUNDARY => ctx. at_boundary ( req, is_loc_word ) ,
1230- SreAtCode :: LOC_NON_BOUNDARY => ctx. at_non_boundary ( req, is_loc_word ) ,
1239+ SreAtCode :: LOC_BOUNDARY => ctx. at_boundary ( req, |ch| req . locale . is_word ( ch ) ) ,
1240+ SreAtCode :: LOC_NON_BOUNDARY => ctx. at_non_boundary ( req, |ch| req . locale . is_word ( ch ) ) ,
12311241 SreAtCode :: UNI_BOUNDARY => ctx. at_boundary ( req, is_uni_word) ,
12321242 SreAtCode :: UNI_NON_BOUNDARY => ctx. at_non_boundary ( req, is_uni_word) ,
12331243 }
12341244}
12351245
1236- fn char_loc_ignore ( code : u32 , c : u32 ) -> bool {
1237- code == c || code == lower_locate ( c) || code == upper_locate ( c)
1246+ fn char_loc_ignore ( code : u32 , c : u32 , locale : Locale ) -> bool {
1247+ code == c || code == locale . lower ( c) || code == locale . upper ( c)
12381248}
12391249
1240- fn charset_loc_ignore ( set : & [ u32 ] , c : u32 ) -> bool {
1241- let lo = lower_locate ( c) ;
1242- if charset ( set, c ) {
1250+ fn charset_loc_ignore ( set : & [ u32 ] , c : u32 , locale : Locale ) -> bool {
1251+ let lo = locale . lower ( c) ;
1252+ if charset ( set, lo , locale ) {
12431253 return true ;
12441254 }
1245- let up = upper_locate ( c) ;
1246- up != lo && charset ( set, up)
1255+ let up = locale . upper ( c) ;
1256+ up != lo && charset ( set, up, locale )
12471257}
12481258
1249- fn category ( cat_code : SreCatCode , c : u32 ) -> bool {
1259+ fn category ( cat_code : SreCatCode , c : u32 , locale : Locale ) -> bool {
12501260 match cat_code {
12511261 SreCatCode :: DIGIT => is_digit ( c) ,
12521262 SreCatCode :: NOT_DIGIT => !is_digit ( c) ,
@@ -1256,8 +1266,8 @@ fn category(cat_code: SreCatCode, c: u32) -> bool {
12561266 SreCatCode :: NOT_WORD => !is_word ( c) ,
12571267 SreCatCode :: LINEBREAK => is_linebreak ( c) ,
12581268 SreCatCode :: NOT_LINEBREAK => !is_linebreak ( c) ,
1259- SreCatCode :: LOC_WORD => is_loc_word ( c) ,
1260- SreCatCode :: LOC_NOT_WORD => !is_loc_word ( c) ,
1269+ SreCatCode :: LOC_WORD => locale . is_word ( c) ,
1270+ SreCatCode :: LOC_NOT_WORD => !locale . is_word ( c) ,
12611271 SreCatCode :: UNI_DIGIT => is_uni_digit ( c) ,
12621272 SreCatCode :: UNI_NOT_DIGIT => !is_uni_digit ( c) ,
12631273 SreCatCode :: UNI_SPACE => is_uni_space ( c) ,
@@ -1269,7 +1279,7 @@ fn category(cat_code: SreCatCode, c: u32) -> bool {
12691279 }
12701280}
12711281
1272- fn charset ( set : & [ u32 ] , ch : u32 ) -> bool {
1282+ fn charset ( set : & [ u32 ] , ch : u32 , locale : Locale ) -> bool {
12731283 /* check if character is a member of the given set */
12741284 let mut ok = true ;
12751285 let mut i = 0 ;
@@ -1292,7 +1302,7 @@ fn charset(set: &[u32], ch: u32) -> bool {
12921302 break ;
12931303 }
12941304 } ;
1295- if category ( cat_code, ch) {
1305+ if category ( cat_code, ch, locale ) {
12961306 return ok;
12971307 }
12981308 i += 2 ;
@@ -1382,7 +1392,8 @@ fn _count<S: StrDrive>(
13821392 ctx. skip_char :: < S > ( max_count) ;
13831393 }
13841394 SreOpcode :: IN => {
1385- while ctx. cursor . position < end && charset ( & ctx. pattern ( req) [ 2 ..] , ctx. peek_char :: < S > ( ) )
1395+ while ctx. cursor . position < end
1396+ && charset ( & ctx. pattern ( req) [ 2 ..] , ctx. peek_char :: < S > ( ) , req. locale )
13861397 {
13871398 ctx. advance_char :: < S > ( ) ;
13881399 }
@@ -1400,10 +1411,14 @@ fn _count<S: StrDrive>(
14001411 general_count_literal ( req, ctx, end, |code, c| code != lower_ascii ( c) ) ;
14011412 }
14021413 SreOpcode :: LITERAL_LOC_IGNORE => {
1403- general_count_literal ( req, ctx, end, char_loc_ignore) ;
1414+ general_count_literal ( req, ctx, end, |code, c| {
1415+ char_loc_ignore ( code, c, req. locale )
1416+ } ) ;
14041417 }
14051418 SreOpcode :: NOT_LITERAL_LOC_IGNORE => {
1406- general_count_literal ( req, ctx, end, |code, c| !char_loc_ignore ( code, c) ) ;
1419+ general_count_literal ( req, ctx, end, |code, c| {
1420+ !char_loc_ignore ( code, c, req. locale )
1421+ } ) ;
14071422 }
14081423 SreOpcode :: LITERAL_UNI_IGNORE => {
14091424 general_count_literal ( req, ctx, end, |code, c| code == lower_unicode ( c) ) ;
0 commit comments