VirtualBox

source: vbox/trunk/src/libs/xpcom18a4/xpcom/string/public/nsCharTraits.h@ 33896

Last change on this file since 33896 was 1, checked in by vboxsync, 55 years ago

import

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 17.5 KB
Line 
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 <[email protected]> (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#ifndef nsDebug_h__
66#include "nsDebug.h"
67 // for NS_ASSERTION
68#endif
69
70#ifdef HAVE_CPP_BOOL
71 typedef bool nsCharTraits_bool;
72#else
73 typedef PRBool nsCharTraits_bool;
74#endif
75
76template <class CharT> struct nsCharTraits {};
77
78NS_SPECIALIZE_TEMPLATE
79struct nsCharTraits<PRUnichar>
80 {
81 typedef PRUnichar char_type;
82 typedef PRUint16 unsigned_char_type;
83 typedef char incompatible_char_type;
84
85 NS_COM static const char_type *sEmptyBuffer;
86
87 static
88 void
89 assign( char_type& lhs, char_type rhs )
90 {
91 lhs = rhs;
92 }
93
94
95 // integer representation of characters:
96
97#ifdef USE_CPP_WCHAR_FUNCS
98 typedef wint_t int_type;
99#else
100 typedef int int_type;
101#endif
102
103 static
104 char_type
105 to_char_type( int_type c )
106 {
107 return char_type(c);
108 }
109
110 static
111 int_type
112 to_int_type( char_type c )
113 {
114 return int_type( NS_STATIC_CAST(unsigned_char_type, c) );
115 }
116
117 static
118 nsCharTraits_bool
119 eq_int_type( int_type lhs, int_type rhs )
120 {
121 return lhs == rhs;
122 }
123
124
125 // |char_type| comparisons:
126
127 static
128 nsCharTraits_bool
129 eq( char_type lhs, char_type rhs )
130 {
131 return lhs == rhs;
132 }
133
134 static
135 nsCharTraits_bool
136 lt( char_type lhs, char_type rhs )
137 {
138 return lhs < rhs;
139 }
140
141
142 // operations on s[n] arrays:
143
144 static
145 char_type*
146 move( char_type* s1, const char_type* s2, size_t n )
147 {
148 return NS_STATIC_CAST(char_type*, memmove(s1, s2, n * sizeof(char_type)));
149 }
150
151 static
152 char_type*
153 copy( char_type* s1, const char_type* s2, size_t n )
154 {
155 return NS_STATIC_CAST(char_type*, memcpy(s1, s2, n * sizeof(char_type)));
156 }
157
158 static
159 char_type*
160 copyASCII( char_type* s1, const char* s2, size_t n )
161 {
162 for (char_type* s = s1; n--; ++s, ++s2) {
163 NS_ASSERTION(!(*s2 & ~0x7F), "Unexpected non-ASCII character");
164 *s = *s2;
165 }
166 return s1;
167 }
168
169 static
170 char_type*
171 assign( char_type* s, size_t n, char_type c )
172 {
173#ifdef USE_CPP_WCHAR_FUNCS
174 return NS_STATIC_CAST(char_type*, wmemset(s, to_int_type(c), n));
175#else
176 char_type* result = s;
177 while ( n-- )
178 assign(*s++, c);
179 return result;
180#endif
181 }
182
183 static
184 int
185 compare( const char_type* s1, const char_type* s2, size_t n )
186 {
187#ifdef USE_CPP_WCHAR_FUNCS
188 return wmemcmp(s1, s2, n);
189#else
190 for ( ; n--; ++s1, ++s2 )
191 {
192 if ( !eq(*s1, *s2) )
193 return to_int_type(*s1) - to_int_type(*s2);
194 }
195
196 return 0;
197#endif
198 }
199
200 static
201 int
202 compareASCII( const char_type* s1, const char* s2, size_t n )
203 {
204 for ( ; n--; ++s1, ++s2 )
205 {
206 NS_ASSERTION(!(*s2 & ~0x7F), "Unexpected non-ASCII character");
207 if ( !eq_int_type(to_int_type(*s1), to_int_type(*s2)) )
208 return to_int_type(*s1) - to_int_type(*s2);
209 }
210
211 return 0;
212 }
213
214 // this version assumes that s2 is null-terminated and s1 has length n.
215 // if s1 is shorter than s2 then we return -1; if s1 is longer than s2,
216 // we return 1.
217 static
218 int
219 compareASCIINullTerminated( const char_type* s1, size_t n, const char* s2 )
220 {
221 for ( ; n--; ++s1, ++s2 )
222 {
223 if ( !*s2 )
224 return 1;
225 NS_ASSERTION(!(*s2 & ~0x7F), "Unexpected non-ASCII character");
226 if ( !eq_int_type(to_int_type(*s1), to_int_type(*s2)) )
227 return to_int_type(*s1) - to_int_type(*s2);
228 }
229
230 if ( *s2 )
231 return -1;
232
233 return 0;
234 }
235
236 /**
237 * Convert c to its lower-case form, but only if the lower-case form is
238 * ASCII. Otherwise leave it alone.
239 *
240 * There are only two non-ASCII Unicode characters whose lowercase
241 * equivalents are ASCII: KELVIN SIGN and LATIN CAPITAL LETTER I WITH
242 * DOT ABOVE. So it's a simple matter to handle those explicitly.
243 */
244 static
245 char_type
246 ASCIIToLower( char_type c )
247 {
248 if (c < 0x100)
249 return (c >= 'A' && c <= 'Z') ? c + ('a' - 'A') : c;
250 else
251 {
252 if (c == 0x212A) // KELVIN SIGN
253 return 'k';
254 if (c == 0x0130) // LATIN CAPITAL LETTER I WITH DOT ABOVE
255 return 'i';
256 return c;
257 }
258 }
259
260 static
261 int
262 compareLowerCaseToASCII( const char_type* s1, const char* s2, size_t n )
263 {
264 for ( ; n--; ++s1, ++s2 )
265 {
266 NS_ASSERTION(!(*s2 & ~0x7F), "Unexpected non-ASCII character");
267 NS_ASSERTION(!(*s2 >= 'A' && *s2 <= 'Z'),
268 "Unexpected uppercase character");
269 char_type lower_s1 = ASCIIToLower(*s1);
270 if ( lower_s1 != to_char_type(*s2) )
271 return to_int_type(lower_s1) - to_int_type(*s2);
272 }
273
274 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 compareLowerCaseToASCIINullTerminated( const char_type* s1, size_t n, const char* s2 )
283 {
284 for ( ; n--; ++s1, ++s2 )
285 {
286 if ( !*s2 )
287 return 1;
288 NS_ASSERTION(!(*s2 & ~0x7F), "Unexpected non-ASCII character");
289 NS_ASSERTION(!(*s2 >= 'A' && *s2 <= 'Z'),
290 "Unexpected uppercase character");
291 char_type lower_s1 = ASCIIToLower(*s1);
292 if ( lower_s1 != to_char_type(*s2) )
293 return to_int_type(lower_s1) - to_int_type(*s2);
294 }
295
296 if ( *s2 )
297 return -1;
298
299 return 0;
300 }
301
302 static
303 size_t
304 length( const char_type* s )
305 {
306#ifdef USE_CPP_WCHAR_FUNCS
307 return wcslen(s);
308#else
309 size_t result = 0;
310 while ( !eq(*s++, char_type(0)) )
311 ++result;
312 return result;
313#endif
314 }
315
316 static
317 const char_type*
318 find( const char_type* s, size_t n, char_type c )
319 {
320#ifdef USE_CPP_WCHAR_FUNCS
321 return NS_REINTERPRET_CAST(const char_type*, wmemchr(s, to_int_type(c), n));
322#else
323 while ( n-- )
324 {
325 if ( eq(*s, c) )
326 return s;
327 ++s;
328 }
329
330 return 0;
331#endif
332 }
333
334#if 0
335 // I/O related:
336
337 typedef streamoff off_type;
338 typedef streampos pos_type;
339 typedef mbstate_t state_type;
340
341 static
342 int_type
343 eof()
344 {
345#ifdef USE_CPP_WCHAR_FUNCS
346 return WEOF;
347#else
348 return EOF;
349#endif
350 }
351
352 static
353 int_type
354 not_eof( int_type c )
355 {
356 return eq_int_type(c, eof()) ? ~eof() : c;
357 }
358
359 // static state_type get_state( pos_type );
360#endif
361 };
362
363NS_SPECIALIZE_TEMPLATE
364struct nsCharTraits<char>
365 {
366 typedef char char_type;
367 typedef unsigned char unsigned_char_type;
368 typedef PRUnichar incompatible_char_type;
369
370 NS_COM static const char_type *sEmptyBuffer;
371
372 static
373 void
374 assign( char_type& lhs, char_type rhs )
375 {
376 lhs = rhs;
377 }
378
379
380 // integer representation of characters:
381
382 typedef int int_type;
383
384 static
385 char_type
386 to_char_type( int_type c )
387 {
388 return char_type(c);
389 }
390
391 static
392 int_type
393 to_int_type( char_type c )
394 {
395 return int_type( NS_STATIC_CAST(unsigned_char_type, c) );
396 }
397
398 static
399 nsCharTraits_bool
400 eq_int_type( int_type lhs, int_type rhs )
401 {
402 return lhs == rhs;
403 }
404
405
406 // |char_type| comparisons:
407
408 static
409 nsCharTraits_bool
410 eq( char_type lhs, char_type rhs )
411 {
412 return lhs == rhs;
413 }
414
415 static
416 nsCharTraits_bool
417 lt( char_type lhs, char_type rhs )
418 {
419 return lhs < rhs;
420 }
421
422
423 // operations on s[n] arrays:
424
425 static
426 char_type*
427 move( char_type* s1, const char_type* s2, size_t n )
428 {
429 return NS_STATIC_CAST(char_type*, memmove(s1, s2, n * sizeof(char_type)));
430 }
431
432 static
433 char_type*
434 copy( char_type* s1, const char_type* s2, size_t n )
435 {
436 return NS_STATIC_CAST(char_type*, memcpy(s1, s2, n * sizeof(char_type)));
437 }
438
439 static
440 char_type*
441 copyASCII( char_type* s1, const char* s2, size_t n )
442 {
443 return copy(s1, s2, n);
444 }
445
446 static
447 char_type*
448 assign( char_type* s, size_t n, char_type c )
449 {
450 return NS_STATIC_CAST(char_type*, memset(s, to_int_type(c), n));
451 }
452
453 static
454 int
455 compare( const char_type* s1, const char_type* s2, size_t n )
456 {
457 return memcmp(s1, s2, n);
458 }
459
460 static
461 int
462 compareASCII( const char_type* s1, const char* s2, size_t n )
463 {
464#ifdef DEBUG
465 for (size_t i = 0; i < n; ++i)
466 {
467 NS_ASSERTION(!(s2[i] & ~0x7F), "Unexpected non-ASCII character");
468 }
469#endif
470 return compare(s1, s2, n);
471 }
472
473 // this version assumes that s2 is null-terminated and s1 has length n.
474 // if s1 is shorter than s2 then we return -1; if s1 is longer than s2,
475 // we return 1.
476 static
477 int
478 compareASCIINullTerminated( const char_type* s1, size_t n, const char* s2 )
479 {
480 // can't use strcmp here because we don't want to stop when s1
481 // contains a null
482 for ( ; n--; ++s1, ++s2 )
483 {
484 if ( !*s2 )
485 return 1;
486 NS_ASSERTION(!(*s2 & ~0x7F), "Unexpected non-ASCII character");
487 if ( *s1 != *s2 )
488 return to_int_type(*s1) - to_int_type(*s2);
489 }
490
491 if ( *s2 )
492 return -1;
493
494 return 0;
495 }
496
497 /**
498 * Convert c to its lower-case form, but only if c is ASCII.
499 */
500 static
501 char_type
502 ASCIIToLower( char_type c )
503 {
504 return (c >= 'A' && c <= 'Z') ? (c + ('a' - 'A')) : c;
505 }
506
507 static
508 int
509 compareLowerCaseToASCII( const char_type* s1, const char* s2, size_t n )
510 {
511 for ( ; n--; ++s1, ++s2 )
512 {
513 NS_ASSERTION(!(*s2 & ~0x7F), "Unexpected non-ASCII character");
514 NS_ASSERTION(!(*s2 >= 'A' && *s2 <= 'Z'),
515 "Unexpected uppercase character");
516 char_type lower_s1 = ASCIIToLower(*s1);
517 if ( lower_s1 != *s2 )
518 return to_int_type(lower_s1) - to_int_type(*s2);
519 }
520 return 0;
521 }
522
523 // this version assumes that s2 is null-terminated and s1 has length n.
524 // if s1 is shorter than s2 then we return -1; if s1 is longer than s2,
525 // we return 1.
526 static
527 int
528 compareLowerCaseToASCIINullTerminated( const char_type* s1, size_t n, const char* s2 )
529 {
530 for ( ; n--; ++s1, ++s2 )
531 {
532 if ( !*s2 )
533 return 1;
534 NS_ASSERTION(!(*s2 & ~0x7F), "Unexpected non-ASCII character");
535 NS_ASSERTION(!(*s2 >= 'A' && *s2 <= 'Z'),
536 "Unexpected uppercase character");
537 char_type lower_s1 = ASCIIToLower(*s1);
538 if ( lower_s1 != *s2 )
539 return to_int_type(lower_s1) - to_int_type(*s2);
540 }
541
542 if ( *s2 )
543 return -1;
544
545 return 0;
546 }
547
548 static
549 size_t
550 length( const char_type* s )
551 {
552 return strlen(s);
553 }
554
555 static
556 const char_type*
557 find( const char_type* s, size_t n, char_type c )
558 {
559 return NS_REINTERPRET_CAST(const char_type*, memchr(s, to_int_type(c), n));
560 }
561
562#if 0
563 // I/O related:
564
565 typedef streamoff off_type;
566 typedef streampos pos_type;
567 typedef mbstate_t state_type;
568
569 static
570 int_type
571 eof()
572 {
573 return EOF;
574 }
575
576 static
577 int_type
578 not_eof( int_type c )
579 {
580 return eq_int_type(c, eof()) ? ~eof() : c;
581 }
582
583 // static state_type get_state( pos_type );
584#endif
585 };
586
587template <class InputIterator>
588struct nsCharSourceTraits
589 {
590 typedef typename InputIterator::difference_type difference_type;
591
592 static
593 PRUint32
594 readable_distance( const InputIterator& first, const InputIterator& last )
595 {
596 // assumes single fragment
597 return last.get() - first.get();
598 }
599
600 static
601 const typename InputIterator::value_type*
602 read( const InputIterator& iter )
603 {
604 return iter.get();
605 }
606
607 static
608 void
609 advance( InputIterator& s, difference_type n )
610 {
611 s.advance(n);
612 }
613 };
614
615#ifdef HAVE_CPP_PARTIAL_SPECIALIZATION
616
617template <class CharT>
618struct nsCharSourceTraits<CharT*>
619 {
620 typedef ptrdiff_t difference_type;
621
622 static
623 PRUint32
624 readable_distance( CharT* s )
625 {
626 return PRUint32(nsCharTraits<CharT>::length(s));
627// return numeric_limits<PRUint32>::max();
628 }
629
630 static
631 PRUint32
632 readable_distance( CharT* first, CharT* last )
633 {
634 return PRUint32(last-first);
635 }
636
637 static
638 const CharT*
639 read( CharT* s )
640 {
641 return s;
642 }
643
644 static
645 void
646 advance( CharT*& s, difference_type n )
647 {
648 s += n;
649 }
650 };
651
652#else
653
654NS_SPECIALIZE_TEMPLATE
655struct nsCharSourceTraits<const char*>
656 {
657 typedef ptrdiff_t difference_type;
658
659 static
660 PRUint32
661 readable_distance( const char* s )
662 {
663 return PRUint32(nsCharTraits<char>::length(s));
664// return numeric_limits<PRUint32>::max();
665 }
666
667 static
668 PRUint32
669 readable_distance( const char* first, const char* last )
670 {
671 return PRUint32(last-first);
672 }
673
674 static
675 const char*
676 read( const char* s )
677 {
678 return s;
679 }
680
681 static
682 void
683 advance( const char*& s, difference_type n )
684 {
685 s += n;
686 }
687 };
688
689
690NS_SPECIALIZE_TEMPLATE
691struct nsCharSourceTraits<const PRUnichar*>
692 {
693 typedef ptrdiff_t difference_type;
694
695 static
696 PRUint32
697 readable_distance( const PRUnichar* s )
698 {
699 return PRUint32(nsCharTraits<PRUnichar>::length(s));
700// return numeric_limits<PRUint32>::max();
701 }
702
703 static
704 PRUint32
705 readable_distance( const PRUnichar* first, const PRUnichar* last )
706 {
707 return PRUint32(last-first);
708 }
709
710 static
711 const PRUnichar*
712 read( const PRUnichar* s )
713 {
714 return s;
715 }
716
717 static
718 void
719 advance( const PRUnichar*& s, difference_type n )
720 {
721 s += n;
722 }
723 };
724
725#endif
726
727
728template <class OutputIterator>
729struct nsCharSinkTraits
730 {
731 static
732 PRUint32
733 write( OutputIterator& iter, const typename OutputIterator::value_type* s, PRUint32 n )
734 {
735 return iter.write(s, n);
736 }
737 };
738
739#ifdef HAVE_CPP_PARTIAL_SPECIALIZATION
740
741template <class CharT>
742struct nsCharSinkTraits<CharT*>
743 {
744 static
745 PRUint32
746 write( CharT*& iter, const CharT* s, PRUint32 n )
747 {
748 nsCharTraits<CharT>::move(iter, s, n);
749 iter += n;
750 return n;
751 }
752 };
753
754#else
755
756NS_SPECIALIZE_TEMPLATE
757struct nsCharSinkTraits<char*>
758 {
759 static
760 PRUint32
761 write( char*& iter, const char* s, PRUint32 n )
762 {
763 nsCharTraits<char>::move(iter, s, n);
764 iter += n;
765 return n;
766 }
767 };
768
769NS_SPECIALIZE_TEMPLATE
770struct nsCharSinkTraits<PRUnichar*>
771 {
772 static
773 PRUint32
774 write( PRUnichar*& iter, const PRUnichar* s, PRUint32 n )
775 {
776 nsCharTraits<PRUnichar>::move(iter, s, n);
777 iter += n;
778 return n;
779 }
780 };
781
782#endif
783
784#endif // !defined(nsCharTraits_h___)
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette