1 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : /* ***** BEGIN LICENSE BLOCK *****
3 : * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 : *
5 : * The contents of this file are subject to the Mozilla Public License Version
6 : * 1.1 (the "License"); you may not use this file except in compliance with
7 : * the License. You may obtain a copy of the License at
8 : * http://www.mozilla.org/MPL/
9 : *
10 : * Software distributed under the License is distributed on an "AS IS" basis,
11 : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 : * for the specific language governing rights and limitations under the
13 : * License.
14 : *
15 : * The Original Code is mozilla.org code.
16 : *
17 : * The Initial Developer of the Original Code is
18 : * Netscape Communications Corporation.
19 : * Portions created by the Initial Developer are Copyright (C) 2000
20 : * the Initial Developer. All Rights Reserved.
21 : *
22 : * Contributor(s):
23 : * Scott Collins <scc@mozilla.org> (original author)
24 : *
25 : * Alternatively, the contents of this file may be used under the terms of
26 : * either of the GNU General Public License Version 2 or later (the "GPL"),
27 : * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
28 : * in which case the provisions of the GPL or the LGPL are applicable instead
29 : * of those above. If you wish to allow use of your version of this file only
30 : * under the terms of either the GPL or the LGPL, and not to allow others to
31 : * use your version of this file under the terms of the MPL, indicate your
32 : * decision by deleting the provisions above and replace them with the notice
33 : * and other provisions required by the GPL or the LGPL. If you do not delete
34 : * the provisions above, a recipient may use your version of this file under
35 : * the terms of any one of the MPL, the GPL or the LGPL.
36 : *
37 : * ***** END LICENSE BLOCK ***** */
38 :
39 : #ifndef nsCharTraits_h___
40 : #define nsCharTraits_h___
41 :
42 : #include <ctype.h>
43 : // for |EOF|, |WEOF|
44 :
45 : #define FORCED_CPP_2BYTE_WCHAR_T
46 : // disable special optimizations for now through this hack
47 :
48 : #if defined(HAVE_CPP_2BYTE_WCHAR_T) && !defined(FORCED_CPP_2BYTE_WCHAR_T)
49 : #define USE_CPP_WCHAR_FUNCS
50 : #endif
51 :
52 : #ifdef USE_CPP_WCHAR_FUNCS
53 : #include <wchar.h>
54 : // for |wmemset|, et al
55 : #endif
56 :
57 : #include <string.h>
58 : // for |memcpy|, et al
59 :
60 : #ifndef nscore_h___
61 : #include "nscore.h"
62 : // for |PRUnichar|
63 : #endif
64 :
65 : // This file may be used (through nsUTF8Utils.h) from non-XPCOM code, in
66 : // particular the standalone software updater. In that case stub out
67 : // the macros provided by nsDebug.h which are only usable when linking XPCOM
68 :
69 : #ifdef NS_NO_XPCOM
70 : #define NS_WARNING(msg)
71 : #define NS_ASSERTION(cond, msg)
72 : #define NS_ERROR(msg)
73 : #else
74 : #ifndef nsDebug_h__
75 : #include "nsDebug.h"
76 : // for NS_ASSERTION
77 : #endif
78 : #endif
79 :
80 : /*
81 : * Some macros for converting PRUnichar (UTF-16) to and from Unicode scalar
82 : * values.
83 : *
84 : * Note that UTF-16 represents all Unicode scalar values up to U+10FFFF by
85 : * using "surrogate pairs". These consist of a high surrogate, i.e. a code
86 : * point in the range U+D800 - U+DBFF, and a low surrogate, i.e. a code point
87 : * in the range U+DC00 - U+DFFF, like this:
88 : *
89 : * U+D800 U+DC00 = U+10000
90 : * U+D800 U+DC01 = U+10001
91 : * ...
92 : * U+DBFF U+DFFE = U+10FFFE
93 : * U+DBFF U+DFFF = U+10FFFF
94 : *
95 : * These surrogate code points U+D800 - U+DFFF are not themselves valid Unicode
96 : * scalar values and are not well-formed UTF-16 except as high-surrogate /
97 : * low-surrogate pairs.
98 : */
99 :
100 : #define PLANE1_BASE PRUint32(0x00010000)
101 : // High surrogates are in the range 0xD800 -- OxDBFF
102 : #define NS_IS_HIGH_SURROGATE(u) ((PRUint32(u) & 0xFFFFFC00) == 0xD800)
103 : // Low surrogates are in the range 0xDC00 -- 0xDFFF
104 : #define NS_IS_LOW_SURROGATE(u) ((PRUint32(u) & 0xFFFFFC00) == 0xDC00)
105 : // Faster than testing NS_IS_HIGH_SURROGATE || NS_IS_LOW_SURROGATE
106 : #define IS_SURROGATE(u) ((PRUint32(u) & 0xFFFFF800) == 0xD800)
107 :
108 : // Everything else is not a surrogate: 0x000 -- 0xD7FF, 0xE000 -- 0xFFFF
109 :
110 : // N = (H - 0xD800) * 0x400 + 0x10000 + (L - 0xDC00)
111 : // I wonder whether we could somehow assert that H is a high surrogate
112 : // and L is a low surrogate
113 : #define SURROGATE_TO_UCS4(h, l) (((PRUint32(h) & 0x03FF) << 10) + \
114 : (PRUint32(l) & 0x03FF) + PLANE1_BASE)
115 :
116 : // Extract surrogates from a UCS4 char
117 : // Reference: the Unicode standard 4.0, section 3.9
118 : // Since (c - 0x10000) >> 10 == (c >> 10) - 0x0080 and
119 : // 0xD7C0 == 0xD800 - 0x0080,
120 : // ((c - 0x10000) >> 10) + 0xD800 can be simplified to
121 : #define H_SURROGATE(c) PRUnichar(PRUnichar(PRUint32(c) >> 10) + \
122 : PRUnichar(0xD7C0))
123 : // where it's to be noted that 0xD7C0 is not bitwise-OR'd
124 : // but added.
125 :
126 : // Since 0x10000 & 0x03FF == 0,
127 : // (c - 0x10000) & 0x03FF == c & 0x03FF so that
128 : // ((c - 0x10000) & 0x03FF) | 0xDC00 is equivalent to
129 : #define L_SURROGATE(c) PRUnichar(PRUnichar(PRUint32(c) & PRUint32(0x03FF)) | \
130 : PRUnichar(0xDC00))
131 :
132 : #define IS_IN_BMP(ucs) (PRUint32(ucs) < PLANE1_BASE)
133 : #define UCS2_REPLACEMENT_CHAR PRUnichar(0xFFFD)
134 :
135 : #define UCS_END PRUint32(0x00110000)
136 : #define IS_VALID_CHAR(c) ((PRUint32(c) < UCS_END) && !IS_SURROGATE(c))
137 : #define ENSURE_VALID_CHAR(c) (IS_VALID_CHAR(c) ? (c) : UCS2_REPLACEMENT_CHAR)
138 :
139 : template <class CharT> struct nsCharTraits {};
140 :
141 : template <>
142 : struct nsCharTraits<PRUnichar>
143 : {
144 : typedef PRUnichar char_type;
145 : typedef PRUint16 unsigned_char_type;
146 : typedef char incompatible_char_type;
147 :
148 : static char_type *sEmptyBuffer;
149 :
150 : static
151 : void
152 : assign( char_type& lhs, char_type rhs )
153 : {
154 : lhs = rhs;
155 : }
156 :
157 :
158 : // integer representation of characters:
159 :
160 : #ifdef USE_CPP_WCHAR_FUNCS
161 : typedef wint_t int_type;
162 : #else
163 : typedef int int_type;
164 : #endif
165 :
166 : static
167 : char_type
168 99502 : to_char_type( int_type c )
169 : {
170 99502 : return char_type(c);
171 : }
172 :
173 : static
174 : int_type
175 1507676 : to_int_type( char_type c )
176 : {
177 1507676 : return int_type( static_cast<unsigned_char_type>(c) );
178 : }
179 :
180 : static
181 : bool
182 680790 : eq_int_type( int_type lhs, int_type rhs )
183 : {
184 680790 : return lhs == rhs;
185 : }
186 :
187 :
188 : // |char_type| comparisons:
189 :
190 : static
191 : bool
192 19402404 : eq( char_type lhs, char_type rhs )
193 : {
194 19402404 : return lhs == rhs;
195 : }
196 :
197 : static
198 : bool
199 : lt( char_type lhs, char_type rhs )
200 : {
201 : return lhs < rhs;
202 : }
203 :
204 :
205 : // operations on s[n] arrays:
206 :
207 : static
208 : char_type*
209 1321079 : move( char_type* s1, const char_type* s2, size_t n )
210 : {
211 1321079 : return static_cast<char_type*>(memmove(s1, s2, n * sizeof(char_type)));
212 : }
213 :
214 : static
215 : char_type*
216 3174857 : copy( char_type* s1, const char_type* s2, size_t n )
217 : {
218 3174857 : return static_cast<char_type*>(memcpy(s1, s2, n * sizeof(char_type)));
219 : }
220 :
221 : static
222 : char_type*
223 210583 : copyASCII( char_type* s1, const char* s2, size_t n )
224 : {
225 3472670 : for (char_type* s = s1; n--; ++s, ++s2) {
226 3262087 : NS_ASSERTION(!(*s2 & ~0x7F), "Unexpected non-ASCII character");
227 3262087 : *s = *s2;
228 : }
229 210583 : return s1;
230 : }
231 :
232 : static
233 : char_type*
234 : assign( char_type* s, size_t n, char_type c )
235 : {
236 : #ifdef USE_CPP_WCHAR_FUNCS
237 : return static_cast<char_type*>(wmemset(s, to_int_type(c), n));
238 : #else
239 : char_type* result = s;
240 : while ( n-- )
241 : assign(*s++, c);
242 : return result;
243 : #endif
244 : }
245 :
246 : static
247 : int
248 606041 : compare( const char_type* s1, const char_type* s2, size_t n )
249 : {
250 : #ifdef USE_CPP_WCHAR_FUNCS
251 : return wmemcmp(s1, s2, n);
252 : #else
253 8828261 : for ( ; n--; ++s1, ++s2 )
254 : {
255 8285264 : if ( !eq(*s1, *s2) )
256 63042 : return to_int_type(*s1) - to_int_type(*s2);
257 : }
258 :
259 542997 : return 0;
260 : #endif
261 : }
262 :
263 : static
264 : int
265 19273 : compareASCII( const char_type* s1, const char* s2, size_t n )
266 : {
267 699097 : for ( ; n--; ++s1, ++s2 )
268 : {
269 680490 : NS_ASSERTION(!(*s2 & ~0x7F), "Unexpected non-ASCII character");
270 680490 : if ( !eq_int_type(to_int_type(*s1), to_int_type(*s2)) )
271 666 : return to_int_type(*s1) - to_int_type(*s2);
272 : }
273 :
274 18607 : return 0;
275 : }
276 :
277 : // this version assumes that s2 is null-terminated and s1 has length n.
278 : // if s1 is shorter than s2 then we return -1; if s1 is longer than s2,
279 : // we return 1.
280 : static
281 : int
282 84 : compareASCIINullTerminated( const char_type* s1, size_t n, const char* s2 )
283 : {
284 300 : for ( ; n--; ++s1, ++s2 )
285 : {
286 300 : if ( !*s2 )
287 0 : return 1;
288 300 : NS_ASSERTION(!(*s2 & ~0x7F), "Unexpected non-ASCII character");
289 300 : if ( !eq_int_type(to_int_type(*s1), to_int_type(*s2)) )
290 84 : return to_int_type(*s1) - to_int_type(*s2);
291 : }
292 :
293 0 : if ( *s2 )
294 0 : return -1;
295 :
296 0 : return 0;
297 : }
298 :
299 : /**
300 : * Convert c to its lower-case form, but only if the lower-case form is
301 : * ASCII. Otherwise leave it alone.
302 : *
303 : * There are only two non-ASCII Unicode characters whose lowercase
304 : * equivalents are ASCII: KELVIN SIGN and LATIN CAPITAL LETTER I WITH
305 : * DOT ABOVE. So it's a simple matter to handle those explicitly.
306 : */
307 : static
308 : char_type
309 99502 : ASCIIToLower( char_type c )
310 : {
311 99502 : if (c < 0x100)
312 : {
313 99502 : if (c >= 'A' && c <= 'Z')
314 27566 : return char_type(c + ('a' - 'A'));
315 :
316 71936 : return c;
317 : }
318 : else
319 : {
320 0 : if (c == 0x212A) // KELVIN SIGN
321 0 : return 'k';
322 0 : if (c == 0x0130) // LATIN CAPITAL LETTER I WITH DOT ABOVE
323 0 : return 'i';
324 0 : return c;
325 : }
326 : }
327 :
328 : static
329 : int
330 21401 : compareLowerCaseToASCII( const char_type* s1, const char* s2, size_t n )
331 : {
332 111647 : for ( ; n--; ++s1, ++s2 )
333 : {
334 99502 : NS_ASSERTION(!(*s2 & ~0x7F), "Unexpected non-ASCII character");
335 99502 : NS_ASSERTION(!(*s2 >= 'A' && *s2 <= 'Z'),
336 : "Unexpected uppercase character");
337 99502 : char_type lower_s1 = ASCIIToLower(*s1);
338 99502 : if ( lower_s1 != to_char_type(*s2) )
339 9256 : return to_int_type(lower_s1) - to_int_type(*s2);
340 : }
341 :
342 12145 : return 0;
343 : }
344 :
345 : // this version assumes that s2 is null-terminated and s1 has length n.
346 : // if s1 is shorter than s2 then we return -1; if s1 is longer than s2,
347 : // we return 1.
348 : static
349 : int
350 0 : compareLowerCaseToASCIINullTerminated( const char_type* s1, size_t n, const char* s2 )
351 : {
352 0 : for ( ; n--; ++s1, ++s2 )
353 : {
354 0 : if ( !*s2 )
355 0 : return 1;
356 0 : NS_ASSERTION(!(*s2 & ~0x7F), "Unexpected non-ASCII character");
357 0 : NS_ASSERTION(!(*s2 >= 'A' && *s2 <= 'Z'),
358 : "Unexpected uppercase character");
359 0 : char_type lower_s1 = ASCIIToLower(*s1);
360 0 : if ( lower_s1 != to_char_type(*s2) )
361 0 : return to_int_type(lower_s1) - to_int_type(*s2);
362 : }
363 :
364 0 : if ( *s2 )
365 0 : return -1;
366 :
367 0 : return 0;
368 : }
369 :
370 : static
371 : size_t
372 503720 : length( const char_type* s )
373 : {
374 : #ifdef USE_CPP_WCHAR_FUNCS
375 : return wcslen(s);
376 : #else
377 503720 : size_t result = 0;
378 10735688 : while ( !eq(*s++, char_type(0)) )
379 9728248 : ++result;
380 503720 : return result;
381 : #endif
382 : }
383 :
384 : static
385 : const char_type*
386 89409 : find( const char_type* s, size_t n, char_type c )
387 : {
388 : #ifdef USE_CPP_WCHAR_FUNCS
389 : return reinterpret_cast<const char_type*>(wmemchr(s, to_int_type(c), n));
390 : #else
391 1021635 : while ( n-- )
392 : {
393 885188 : if ( eq(*s, c) )
394 42371 : return s;
395 842817 : ++s;
396 : }
397 :
398 47038 : return 0;
399 : #endif
400 : }
401 :
402 : #if 0
403 : // I/O related:
404 :
405 : typedef streamoff off_type;
406 : typedef streampos pos_type;
407 : typedef mbstate_t state_type;
408 :
409 : static
410 : int_type
411 : eof()
412 : {
413 : #ifdef USE_CPP_WCHAR_FUNCS
414 : return WEOF;
415 : #else
416 : return EOF;
417 : #endif
418 : }
419 :
420 : static
421 : int_type
422 : not_eof( int_type c )
423 : {
424 : return eq_int_type(c, eof()) ? ~eof() : c;
425 : }
426 :
427 : // static state_type get_state( pos_type );
428 : #endif
429 : };
430 :
431 : template <>
432 : struct nsCharTraits<char>
433 : {
434 : typedef char char_type;
435 : typedef unsigned char unsigned_char_type;
436 : typedef PRUnichar incompatible_char_type;
437 :
438 : static char_type *sEmptyBuffer;
439 :
440 : static
441 : void
442 : assign( char_type& lhs, char_type rhs )
443 : {
444 : lhs = rhs;
445 : }
446 :
447 :
448 : // integer representation of characters:
449 :
450 : typedef int int_type;
451 :
452 : static
453 : char_type
454 : to_char_type( int_type c )
455 : {
456 : return char_type(c);
457 : }
458 :
459 : static
460 : int_type
461 1833554 : to_int_type( char_type c )
462 : {
463 1833554 : return int_type( static_cast<unsigned_char_type>(c) );
464 : }
465 :
466 : static
467 : bool
468 : eq_int_type( int_type lhs, int_type rhs )
469 : {
470 : return lhs == rhs;
471 : }
472 :
473 :
474 : // |char_type| comparisons:
475 :
476 : static
477 : bool
478 : eq( char_type lhs, char_type rhs )
479 : {
480 : return lhs == rhs;
481 : }
482 :
483 : static
484 : bool
485 : lt( char_type lhs, char_type rhs )
486 : {
487 : return lhs < rhs;
488 : }
489 :
490 :
491 : // operations on s[n] arrays:
492 :
493 : static
494 : char_type*
495 186754 : move( char_type* s1, const char_type* s2, size_t n )
496 : {
497 186754 : return static_cast<char_type*>(memmove(s1, s2, n * sizeof(char_type)));
498 : }
499 :
500 : static
501 : char_type*
502 15899423 : copy( char_type* s1, const char_type* s2, size_t n )
503 : {
504 15899423 : return static_cast<char_type*>(memcpy(s1, s2, n * sizeof(char_type)));
505 : }
506 :
507 : static
508 : char_type*
509 560049 : copyASCII( char_type* s1, const char* s2, size_t n )
510 : {
511 560049 : return copy(s1, s2, n);
512 : }
513 :
514 : static
515 : char_type*
516 : assign( char_type* s, size_t n, char_type c )
517 : {
518 : return static_cast<char_type*>(memset(s, to_int_type(c), n));
519 : }
520 :
521 : static
522 : int
523 38023262 : compare( const char_type* s1, const char_type* s2, size_t n )
524 : {
525 38023262 : return memcmp(s1, s2, n);
526 : }
527 :
528 : static
529 : int
530 671323 : compareASCII( const char_type* s1, const char* s2, size_t n )
531 : {
532 : #ifdef DEBUG
533 2361393 : for (size_t i = 0; i < n; ++i)
534 : {
535 1690070 : NS_ASSERTION(!(s2[i] & ~0x7F), "Unexpected non-ASCII character");
536 : }
537 : #endif
538 671323 : return compare(s1, s2, n);
539 : }
540 :
541 : // this version assumes that s2 is null-terminated and s1 has length n.
542 : // if s1 is shorter than s2 then we return -1; if s1 is longer than s2,
543 : // we return 1.
544 : static
545 : int
546 7162 : compareASCIINullTerminated( const char_type* s1, size_t n, const char* s2 )
547 : {
548 : // can't use strcmp here because we don't want to stop when s1
549 : // contains a null
550 7226 : for ( ; n--; ++s1, ++s2 )
551 : {
552 7213 : if ( !*s2 )
553 9 : return 1;
554 7204 : NS_ASSERTION(!(*s2 & ~0x7F), "Unexpected non-ASCII character");
555 7204 : if ( *s1 != *s2 )
556 7140 : return to_int_type(*s1) - to_int_type(*s2);
557 : }
558 :
559 13 : if ( *s2 )
560 0 : return -1;
561 :
562 13 : return 0;
563 : }
564 :
565 : /**
566 : * Convert c to its lower-case form, but only if c is ASCII.
567 : */
568 : static
569 : char_type
570 129889 : ASCIIToLower( char_type c )
571 : {
572 129889 : if (c >= 'A' && c <= 'Z')
573 1041 : return char_type(c + ('a' - 'A'));
574 :
575 128848 : return c;
576 : }
577 :
578 : static
579 : int
580 31345 : compareLowerCaseToASCII( const char_type* s1, const char* s2, size_t n )
581 : {
582 140222 : for ( ; n--; ++s1, ++s2 )
583 : {
584 124453 : NS_ASSERTION(!(*s2 & ~0x7F), "Unexpected non-ASCII character");
585 124453 : NS_ASSERTION(!(*s2 >= 'A' && *s2 <= 'Z'),
586 : "Unexpected uppercase character");
587 124453 : char_type lower_s1 = ASCIIToLower(*s1);
588 124453 : if ( lower_s1 != *s2 )
589 15576 : return to_int_type(lower_s1) - to_int_type(*s2);
590 : }
591 15769 : return 0;
592 : }
593 :
594 : // this version assumes that s2 is null-terminated and s1 has length n.
595 : // if s1 is shorter than s2 then we return -1; if s1 is longer than s2,
596 : // we return 1.
597 : static
598 : int
599 4061 : compareLowerCaseToASCIINullTerminated( const char_type* s1, size_t n, const char* s2 )
600 : {
601 5974 : for ( ; n--; ++s1, ++s2 )
602 : {
603 5443 : if ( !*s2 )
604 7 : return 1;
605 5436 : NS_ASSERTION(!(*s2 & ~0x7F), "Unexpected non-ASCII character");
606 5436 : NS_ASSERTION(!(*s2 >= 'A' && *s2 <= 'Z'),
607 : "Unexpected uppercase character");
608 5436 : char_type lower_s1 = ASCIIToLower(*s1);
609 5436 : if ( lower_s1 != *s2 )
610 3523 : return to_int_type(lower_s1) - to_int_type(*s2);
611 : }
612 :
613 531 : if ( *s2 )
614 0 : return -1;
615 :
616 531 : return 0;
617 : }
618 :
619 : static
620 : size_t
621 17371859 : length( const char_type* s )
622 : {
623 17371859 : return strlen(s);
624 : }
625 :
626 : static
627 : const char_type*
628 1781076 : find( const char_type* s, size_t n, char_type c )
629 : {
630 1781076 : return reinterpret_cast<const char_type*>(memchr(s, to_int_type(c), n));
631 : }
632 :
633 : #if 0
634 : // I/O related:
635 :
636 : typedef streamoff off_type;
637 : typedef streampos pos_type;
638 : typedef mbstate_t state_type;
639 :
640 : static
641 : int_type
642 : eof()
643 : {
644 : return EOF;
645 : }
646 :
647 : static
648 : int_type
649 : not_eof( int_type c )
650 : {
651 : return eq_int_type(c, eof()) ? ~eof() : c;
652 : }
653 :
654 : // static state_type get_state( pos_type );
655 : #endif
656 : };
657 :
658 : template <class InputIterator>
659 : struct nsCharSourceTraits
660 : {
661 : typedef typename InputIterator::difference_type difference_type;
662 :
663 : static
664 : PRUint32
665 5724295 : readable_distance( const InputIterator& first, const InputIterator& last )
666 : {
667 : // assumes single fragment
668 5724295 : return PRUint32(last.get() - first.get());
669 : }
670 :
671 : static
672 : const typename InputIterator::value_type*
673 5724295 : read( const InputIterator& iter )
674 : {
675 5724295 : return iter.get();
676 : }
677 :
678 : static
679 : void
680 : advance( InputIterator& s, difference_type n )
681 : {
682 : s.advance(n);
683 : }
684 : };
685 :
686 : #ifdef HAVE_CPP_PARTIAL_SPECIALIZATION
687 :
688 : template <class CharT>
689 : struct nsCharSourceTraits<CharT*>
690 : {
691 : typedef ptrdiff_t difference_type;
692 :
693 : static
694 : PRUint32
695 : readable_distance( CharT* s )
696 : {
697 : return PRUint32(nsCharTraits<CharT>::length(s));
698 : // return numeric_limits<PRUint32>::max();
699 : }
700 :
701 : static
702 : PRUint32
703 20936 : readable_distance( CharT* first, CharT* last )
704 : {
705 20936 : return PRUint32(last-first);
706 : }
707 :
708 : static
709 : const CharT*
710 20936 : read( CharT* s )
711 : {
712 20936 : return s;
713 : }
714 :
715 : static
716 : void
717 : advance( CharT*& s, difference_type n )
718 : {
719 : s += n;
720 : }
721 : };
722 :
723 : #else
724 :
725 : template <>
726 : struct nsCharSourceTraits<const char*>
727 : {
728 : typedef ptrdiff_t difference_type;
729 :
730 : static
731 : PRUint32
732 : readable_distance( const char* s )
733 : {
734 : return PRUint32(nsCharTraits<char>::length(s));
735 : // return numeric_limits<PRUint32>::max();
736 : }
737 :
738 : static
739 : PRUint32
740 : readable_distance( const char* first, const char* last )
741 : {
742 : return PRUint32(last-first);
743 : }
744 :
745 : static
746 : const char*
747 : read( const char* s )
748 : {
749 : return s;
750 : }
751 :
752 : static
753 : void
754 : advance( const char*& s, difference_type n )
755 : {
756 : s += n;
757 : }
758 : };
759 :
760 :
761 : template <>
762 : struct nsCharSourceTraits<const PRUnichar*>
763 : {
764 : typedef ptrdiff_t difference_type;
765 :
766 : static
767 : PRUint32
768 : readable_distance( const PRUnichar* s )
769 : {
770 : return PRUint32(nsCharTraits<PRUnichar>::length(s));
771 : // return numeric_limits<PRUint32>::max();
772 : }
773 :
774 : static
775 : PRUint32
776 : readable_distance( const PRUnichar* first, const PRUnichar* last )
777 : {
778 : return PRUint32(last-first);
779 : }
780 :
781 : static
782 : const PRUnichar*
783 : read( const PRUnichar* s )
784 : {
785 : return s;
786 : }
787 :
788 : static
789 : void
790 : advance( const PRUnichar*& s, difference_type n )
791 : {
792 : s += n;
793 : }
794 : };
795 :
796 : #endif
797 :
798 :
799 : template <class OutputIterator>
800 : struct nsCharSinkTraits
801 : {
802 : static
803 : void
804 4277217 : write( OutputIterator& iter, const typename OutputIterator::value_type* s, PRUint32 n )
805 : {
806 1383391 : iter.write(s, n);
807 4277217 : }
808 : };
809 :
810 : #ifdef HAVE_CPP_PARTIAL_SPECIALIZATION
811 :
812 : template <class CharT>
813 : struct nsCharSinkTraits<CharT*>
814 : {
815 : static
816 : void
817 1472032 : write( CharT*& iter, const CharT* s, PRUint32 n )
818 : {
819 1472032 : nsCharTraits<CharT>::move(iter, s, n);
820 1472032 : iter += n;
821 1472032 : }
822 : };
823 :
824 : #else
825 :
826 : template <>
827 : struct nsCharSinkTraits<char*>
828 : {
829 : static
830 : void
831 : write( char*& iter, const char* s, PRUint32 n )
832 : {
833 : nsCharTraits<char>::move(iter, s, n);
834 : iter += n;
835 : }
836 : };
837 :
838 : template <>
839 : struct nsCharSinkTraits<PRUnichar*>
840 : {
841 : static
842 : void
843 : write( PRUnichar*& iter, const PRUnichar* s, PRUint32 n )
844 : {
845 : nsCharTraits<PRUnichar>::move(iter, s, n);
846 : iter += n;
847 : }
848 : };
849 :
850 : #endif
851 :
852 : #endif // !defined(nsCharTraits_h___)
|