12
12
13
13
use container:: Container ;
14
14
use option:: { None , Option , Some } ;
15
- use str;
16
- use str:: { StrSlice , OwnedStr } ;
17
- use u32;
18
- use uint;
15
+ use str:: StrSlice ;
19
16
use unicode:: { derived_property, general_category} ;
20
17
18
+ #[ cfg( test) ] use str:: OwnedStr ;
19
+
21
20
#[ cfg( not( test) ) ] use cmp:: { Eq , Ord } ;
22
21
#[ cfg( not( test) ) ] use num:: Zero ;
23
22
@@ -202,21 +201,21 @@ pub fn from_digit(num: uint, radix: uint) -> Option<char> {
202
201
/// - chars in [0x100,0xffff] get 4-digit escapes: `\\uNNNN`
203
202
/// - chars above 0x10000 get 8-digit escapes: `\\UNNNNNNNN`
204
203
///
205
- pub fn escape_unicode ( c : char ) -> ~str {
206
- let s = u32:: to_str_radix ( c as u32 , 16 u) ;
207
- let ( c, pad) = cond ! (
208
- ( c <= '\xff' ) { ( 'x' , 2 u) }
209
- ( c <= '\uffff' ) { ( 'u' , 4 u) }
210
- _ { ( 'U' , 8 u) }
204
+ pub fn escape_unicode ( c : char , f : & fn ( char ) ) {
205
+ // avoid calling str::to_str_radix because we don't really need to allocate
206
+ // here.
207
+ f ( '\\' ) ;
208
+ let pad = cond ! (
209
+ ( c <= '\xff' ) { f( 'x' ) ; 2 }
210
+ ( c <= '\uffff' ) { f( 'u' ) ; 4 }
211
+ _ { f( 'U' ) ; 8 }
211
212
) ;
212
- assert ! ( s . len ( ) <= pad ) ;
213
- let mut out = ~" \\ " ;
214
- out . push_str ( str :: from_char ( c ) ) ;
215
- for uint :: range ( s . len ( ) , pad ) |_| {
216
- out . push_str ( "0" ) ;
213
+ for int :: range_step ( 4 * ( pad - 1 ) , - 1 , - 4 ) |offset| {
214
+ match ( ( c as u32 ) >> offset ) & 0xf {
215
+ i @ 0 .. 9 => { f ( '0' + i as char ) ; }
216
+ i => { f ( 'a' + ( i - 10 ) as char ) ; }
217
+ }
217
218
}
218
- out. push_str ( s) ;
219
- out
220
219
}
221
220
222
221
///
@@ -231,16 +230,16 @@ pub fn escape_unicode(c: char) -> ~str {
231
230
/// - Any other chars in the range [0x20,0x7e] are not escaped.
232
231
/// - Any other chars are given hex unicode escapes; see `escape_unicode`.
233
232
///
234
- pub fn escape_default ( c : char ) -> ~ str {
233
+ pub fn escape_default ( c : char , f : & fn ( char ) ) {
235
234
match c {
236
- '\t' => ~" \\ t" ,
237
- '\r' => ~" \\ r",
238
- '\n' => ~" \\ n" ,
239
- '\\' => ~" \\ \\ " ,
240
- '\'' => ~" \\ ' " ,
241
- '"' => ~" \\ \" " ,
242
- '\x20' .. '\x7e' => str :: from_char ( c) ,
243
- _ => c. escape_unicode ( ) ,
235
+ '\t' => { f ( '\\' ) ; f ( 't' ) ; }
236
+ '\r' => { f ( '\\' ) ; f ( 'r' ) ; }
237
+ '\n' => { f ( '\\' ) ; f ( 'n' ) ; }
238
+ '\\' => { f ( '\\' ) ; f ( '\\' ) ; }
239
+ '\'' => { f ( ' \\') ; f ( '\'' ) ; }
240
+ '"' => { f ( '\\' ) ; f ( '"' ) ; }
241
+ '\x20' .. '\x7e' => { f ( c) ; }
242
+ _ => c. escape_unicode ( f ) ,
244
243
}
245
244
}
246
245
@@ -274,8 +273,8 @@ pub trait Char {
274
273
fn is_digit_radix ( & self , radix : uint ) -> bool ;
275
274
fn to_digit ( & self , radix : uint ) -> Option < uint > ;
276
275
fn from_digit ( num : uint , radix : uint ) -> Option < char > ;
277
- fn escape_unicode ( & self ) -> ~ str ;
278
- fn escape_default ( & self ) -> ~ str ;
276
+ fn escape_unicode ( & self , f : & fn ( char ) ) ;
277
+ fn escape_default ( & self , f : & fn ( char ) ) ;
279
278
fn len_utf8_bytes ( & self ) -> uint ;
280
279
}
281
280
@@ -302,9 +301,9 @@ impl Char for char {
302
301
303
302
fn from_digit ( num : uint , radix : uint ) -> Option < char > { from_digit ( num, radix) }
304
303
305
- fn escape_unicode ( & self ) -> ~ str { escape_unicode ( * self ) }
304
+ fn escape_unicode ( & self , f : & fn ( char ) ) { escape_unicode ( * self , f ) }
306
305
307
- fn escape_default ( & self ) -> ~ str { escape_default ( * self ) }
306
+ fn escape_default ( & self , f : & fn ( char ) ) { escape_default ( * self , f ) }
308
307
309
308
fn len_utf8_bytes ( & self ) -> uint { len_utf8_bytes ( * self ) }
310
309
}
@@ -392,27 +391,37 @@ fn test_is_digit() {
392
391
393
392
#[ test]
394
393
fn test_escape_default( ) {
395
- assert_eq ! ( '\n' . escape_default( ) , ~"\\ n");
396
- assert_eq!('\r '.escape_default(), ~" \\ r");
397
- assert_eq!('\''.escape_default(), ~" \\ ' ");
398
- assert_eq!('" ' . escape_default( ) , ~"\\ \" ") ;
399
- assert_eq ! ( ' ' . escape_default( ) , ~" ");
400
- assert_eq!('a'.escape_default(), ~" a");
401
- assert_eq!('~'.escape_default(), ~" ~") ;
402
- assert_eq ! ( '\x00' . escape_default( ) , ~"\\ x00");
403
- assert_eq!('\x1f '.escape_default(), ~" \\ x1f");
404
- assert_eq!('\x7f '.escape_default(), ~" \\ x7f");
405
- assert_eq!('\xff '.escape_default(), ~" \\ xff");
406
- assert_eq!('\u011b '.escape_default(), ~" \\ u011b");
407
- assert_eq!('\U 0001d4b6'.escape_default(), ~" \\ U0001d4b6 ");
394
+ fn string( c : char ) -> ~str {
395
+ let mut result = ~"";
396
+ do escape_default ( c) |c| { result. push_char ( c) ; }
397
+ return result;
398
+ }
399
+ assert_eq ! ( string( '\n' ) , ~"\\ n");
400
+ assert_eq!(string('\r '), ~" \\ r");
401
+ assert_eq!(string('\''), ~" \\ ' ");
402
+ assert_eq!(string('" ' ) , ~"\\ \" ") ;
403
+ assert_eq ! ( string( ' ' ) , ~" ");
404
+ assert_eq!(string('a'), ~" a");
405
+ assert_eq!(string('~'), ~" ~") ;
406
+ assert_eq ! ( string( '\x00' ) , ~"\\ x00");
407
+ assert_eq!(string('\x1f '), ~" \\ x1f");
408
+ assert_eq!(string('\x7f '), ~" \\ x7f");
409
+ assert_eq!(string('\xff '), ~" \\ xff");
410
+ assert_eq!(string('\u011b '), ~" \\ u011b");
411
+ assert_eq!(string('\U 0001d4b6'), ~" \\ U0001d4b6 ");
408
412
}
409
413
410
414
#[test]
411
415
fn test_escape_unicode() {
412
- assert_eq!('\x00 '.escape_unicode(), ~" \\ x00");
413
- assert_eq!('\n '.escape_unicode(), ~" \\ x0a");
414
- assert_eq!(' '.escape_unicode(), ~" \\ x20");
415
- assert_eq!('a'.escape_unicode(), ~" \\ x61");
416
- assert_eq!('\u011b '.escape_unicode(), ~" \\ u011b");
417
- assert_eq!('\U 0001d4b6'.escape_unicode(), ~"\\ U0001d4b6" ) ;
416
+ fn string(c: char) -> ~str {
417
+ let mut result = ~" ";
418
+ do escape_unicode(c) |c| { result.push_char(c); }
419
+ return result;
420
+ }
421
+ assert_eq!(string('\x00 '), ~" \\ x00");
422
+ assert_eq!(string('\n '), ~" \\ x0a");
423
+ assert_eq!(string(' '), ~" \\ x20");
424
+ assert_eq!(string('a'), ~" \\ x61");
425
+ assert_eq!(string('\u011b '), ~" \\ u011b");
426
+ assert_eq!(string('\U 0001d4b6'), ~"\\ U0001d4b6" ) ;
418
427
}
0 commit comments