~ubuntu-branches/ubuntu/precise/kompozer/precise

« back to all changes in this revision

Viewing changes to mozilla/xpcom/ds/nsCRT.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Anthony Yarusso
  • Date: 2007-08-27 01:11:03 UTC
  • Revision ID: james.westby@ubuntu.com-20070827011103-2jgf4s6532gqu2ka
Tags: upstream-0.7.10
ImportĀ upstreamĀ versionĀ 0.7.10

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 
2
/* ***** BEGIN LICENSE BLOCK *****
 
3
 * Version: NPL 1.1/GPL 2.0/LGPL 2.1
 
4
 *
 
5
 * The contents of this file are subject to the Netscape Public License
 
6
 * Version 1.1 (the "License"); you may not use this file except in
 
7
 * compliance with the License. You may obtain a copy of the License at
 
8
 * http://www.mozilla.org/NPL/
 
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) 1998
 
20
 * the Initial Developer. All Rights Reserved.
 
21
 *
 
22
 * Contributor(s):
 
23
 *
 
24
 * Alternatively, the contents of this file may be used under the terms of
 
25
 * either the GNU General Public License Version 2 or later (the "GPL"), or 
 
26
 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
 
27
 * in which case the provisions of the GPL or the LGPL are applicable instead
 
28
 * of those above. If you wish to allow use of your version of this file only
 
29
 * under the terms of either the GPL or the LGPL, and not to allow others to
 
30
 * use your version of this file under the terms of the NPL, indicate your
 
31
 * decision by deleting the provisions above and replace them with the notice
 
32
 * and other provisions required by the GPL or the LGPL. If you do not delete
 
33
 * the provisions above, a recipient may use your version of this file under
 
34
 * the terms of any one of the NPL, the GPL or the LGPL.
 
35
 *
 
36
 * ***** END LICENSE BLOCK ***** */
 
37
 
 
38
 
 
39
/**
 
40
 * MODULE NOTES:
 
41
 * @update  gess7/30/98
 
42
 *
 
43
 * Much as I hate to do it, we were using string compares wrong.
 
44
 * Often, programmers call functions like strcmp(s1,s2), and pass
 
45
 * one or more null strings. Rather than blow up on these, I've 
 
46
 * added quick checks to ensure that cases like this don't cause
 
47
 * us to fail.
 
48
 *
 
49
 * In general, if you pass a null into any of these string compare
 
50
 * routines, we simply return 0.
 
51
 */
 
52
 
 
53
 
 
54
#include "nsCRT.h"
 
55
#include "nsIServiceManager.h"
 
56
 
 
57
// XXX Bug: These tables don't lowercase the upper 128 characters properly
 
58
 
 
59
// This table maps uppercase characters to lower case characters;
 
60
// characters that are neither upper nor lower case are unaffected.
 
61
static const unsigned char kUpper2Lower[256] = {
 
62
    0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15,
 
63
   16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
 
64
   32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
 
65
   48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
 
66
   64,
 
67
 
 
68
    // upper band mapped to lower [A-Z] => [a-z]
 
69
       97, 98, 99,100,101,102,103,104,105,106,107,108,109,110,111,
 
70
  112,113,114,115,116,117,118,119,120,121,122,
 
71
 
 
72
                                               91, 92, 93, 94, 95,
 
73
   96, 97, 98, 99,100,101,102,103,104,105,106,107,108,109,110,111,
 
74
  112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,
 
75
  128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,
 
76
  144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,
 
77
  160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,
 
78
  176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,
 
79
  192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,
 
80
  208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,
 
81
  224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,
 
82
  240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255
 
83
};
 
84
 
 
85
static const unsigned char kLower2Upper[256] = {
 
86
    0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15,
 
87
   16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
 
88
   32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
 
89
   48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
 
90
   64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
 
91
   80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
 
92
   96,
 
93
 
 
94
    // lower band mapped to upper [a-z] => [A-Z]
 
95
       65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
 
96
   80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90,
 
97
 
 
98
                                              123,124,125,126,127,
 
99
  128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,
 
100
  144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,
 
101
  160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,
 
102
  176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,
 
103
  192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,
 
104
  208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,
 
105
  224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,
 
106
  240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255
 
107
};
 
108
 
 
109
//----------------------------------------------------------------------
 
110
 
 
111
char nsCRT::ToUpper(char aChar)
 
112
{
 
113
  return (char)kLower2Upper[(unsigned char)aChar];
 
114
}
 
115
 
 
116
char nsCRT::ToLower(char aChar)
 
117
{
 
118
  return (char)kUpper2Lower[(unsigned char)aChar];
 
119
}
 
120
 
 
121
PRBool nsCRT::IsUpper(char aChar)
 
122
{
 
123
  return aChar != nsCRT::ToLower(aChar);
 
124
}
 
125
 
 
126
PRBool nsCRT::IsLower(char aChar)
 
127
{
 
128
  return aChar != nsCRT::ToUpper(aChar);
 
129
}
 
130
 
 
131
////////////////////////////////////////////////////////////////////////////////
 
132
// My lovely strtok routine
 
133
 
 
134
#define IS_DELIM(m, c)          ((m)[(c) >> 3] & (1 << ((c) & 7)))
 
135
#define SET_DELIM(m, c)         ((m)[(c) >> 3] |= (1 << ((c) & 7)))
 
136
#define DELIM_TABLE_SIZE        32
 
137
 
 
138
char* nsCRT::strtok(char* string, const char* delims, char* *newStr)
 
139
{
 
140
  NS_ASSERTION(string, "Unlike regular strtok, the first argument cannot be null.");
 
141
 
 
142
  char delimTable[DELIM_TABLE_SIZE];
 
143
  PRUint32 i;
 
144
  char* result;
 
145
  char* str = string;
 
146
 
 
147
  for (i = 0; i < DELIM_TABLE_SIZE; i++)
 
148
    delimTable[i] = '\0';
 
149
 
 
150
  for (i = 0; delims[i]; i++) {
 
151
    SET_DELIM(delimTable, NS_STATIC_CAST(PRUint8, delims[i]));
 
152
  }
 
153
  NS_ASSERTION(delims[i] == '\0', "too many delimiters");
 
154
 
 
155
  // skip to beginning
 
156
  while (*str && IS_DELIM(delimTable, NS_STATIC_CAST(PRUint8, *str))) {
 
157
    str++;
 
158
  }
 
159
  result = str;
 
160
 
 
161
  // fix up the end of the token
 
162
  while (*str) {
 
163
    if (IS_DELIM(delimTable, NS_STATIC_CAST(PRUint8, *str))) {
 
164
      *str++ = '\0';
 
165
      break;
 
166
    }
 
167
    str++;
 
168
  }
 
169
  *newStr = str;
 
170
 
 
171
  return str == result ? NULL : result;
 
172
}
 
173
 
 
174
////////////////////////////////////////////////////////////////////////////////
 
175
 
 
176
PRUint32 nsCRT::strlen(const PRUnichar* s)
 
177
{
 
178
  PRUint32 len = 0;
 
179
  if(s) {
 
180
    while (*s++ != 0) {
 
181
      len++;
 
182
    }
 
183
  }
 
184
  return len;
 
185
}
 
186
 
 
187
 
 
188
/**
 
189
 * Compare unichar string ptrs, stopping at the 1st null 
 
190
 * NOTE: If both are null, we return 0.
 
191
 * NOTE: We terminate the search upon encountering a NULL
 
192
 *
 
193
 * @update  gess 11/10/99
 
194
 * @param   s1 and s2 both point to unichar strings
 
195
 * @return  0 if they match, -1 if s1<s2; 1 if s1>s2
 
196
 */
 
197
PRInt32 nsCRT::strcmp(const PRUnichar* s1, const PRUnichar* s2) {
 
198
  if(s1 && s2) {
 
199
    for (;;) {
 
200
      PRUnichar c1 = *s1++;
 
201
      PRUnichar c2 = *s2++;
 
202
      if (c1 != c2) {
 
203
        if (c1 < c2) return -1;
 
204
        return 1;
 
205
      }
 
206
      if ((0==c1) || (0==c2)) break;
 
207
    }
 
208
  }
 
209
  else {
 
210
    if (s1)                     // s2 must have been null
 
211
      return -1;
 
212
    if (s2)                     // s1 must have been null
 
213
      return 1;
 
214
  }
 
215
  return 0;
 
216
}
 
217
 
 
218
/**
 
219
 * Compare unichar string ptrs, stopping at the 1st null or nth char.
 
220
 * NOTE: If either is null, we return 0.
 
221
 * NOTE: We DO NOT terminate the search upon encountering NULL's before N
 
222
 *
 
223
 * @update  gess 11/10/99
 
224
 * @param   s1 and s2 both point to unichar strings
 
225
 * @return  0 if they match, -1 if s1<s2; 1 if s1>s2
 
226
 */
 
227
PRInt32 nsCRT::strncmp(const PRUnichar* s1, const PRUnichar* s2, PRUint32 n) {
 
228
  if(s1 && s2) { 
 
229
    if(n != 0) {
 
230
      do {
 
231
        PRUnichar c1 = *s1++;
 
232
        PRUnichar c2 = *s2++;
 
233
        if (c1 != c2) {
 
234
          if (c1 < c2) return -1;
 
235
          return 1;
 
236
        }
 
237
      } while (--n != 0);
 
238
    }
 
239
  }
 
240
  return 0;
 
241
}
 
242
 
 
243
PRUnichar* nsCRT::strdup(const PRUnichar* str)
 
244
{
 
245
  PRUint32 len = nsCRT::strlen(str);
 
246
  return strndup(str, len);
 
247
}
 
248
 
 
249
PRUnichar* nsCRT::strndup(const PRUnichar* str, PRUint32 len)
 
250
{
 
251
        nsCppSharedAllocator<PRUnichar> shared_allocator;
 
252
        PRUnichar* rslt = shared_allocator.allocate(len + 1); // add one for the null
 
253
  // PRUnichar* rslt = new PRUnichar[len + 1];
 
254
 
 
255
  if (rslt == NULL) return NULL;
 
256
  memcpy(rslt, str, len * sizeof(PRUnichar));
 
257
  rslt[len] = 0;
 
258
  return rslt;
 
259
}
 
260
 
 
261
  /**
 
262
   * |nsCRT::HashCode| is identical to |PL_HashString|, which tests
 
263
   *  (http://bugzilla.mozilla.org/showattachment.cgi?attach_id=26596)
 
264
   *  show to be the best hash among several other choices.
 
265
   *
 
266
   * We re-implement it here rather than calling it for two reasons:
 
267
   *  (1) in this interface, we also calculate the length of the
 
268
   *  string being hashed; and (2) the narrow and wide and `buffer' versions here
 
269
   *  will hash equivalent strings to the same value, e.g., "Hello" and L"Hello".
 
270
   */
 
271
PRUint32 nsCRT::HashCode(const char* str, PRUint32* resultingStrLen)
 
272
{
 
273
  PRUint32 h = 0;
 
274
  const char* s = str;
 
275
 
 
276
  if (!str) return h;
 
277
 
 
278
  unsigned char c;
 
279
  while ( (c = *s++) )
 
280
    h = (h>>28) ^ (h<<4) ^ c;
 
281
 
 
282
  if ( resultingStrLen )
 
283
    *resultingStrLen = (s-str)-1;
 
284
  return h;
 
285
}
 
286
 
 
287
PRUint32 nsCRT::HashCode(const PRUnichar* str, PRUint32* resultingStrLen)
 
288
{
 
289
  PRUint32 h = 0;
 
290
  const PRUnichar* s = str;
 
291
 
 
292
  if (!str) return h;
 
293
 
 
294
  PRUnichar c;
 
295
  while ( (c = *s++) )
 
296
    h = (h>>28) ^ (h<<4) ^ c;
 
297
 
 
298
  if ( resultingStrLen )
 
299
    *resultingStrLen = (s-str)-1;
 
300
  return h;
 
301
}
 
302
 
 
303
PRUint32 nsCRT::HashCodeAsUTF8(const PRUnichar* str, PRUint32* resultingStrLen)
 
304
{
 
305
  PRUint32 h = 0;
 
306
  const PRUnichar* s = str;
 
307
 
 
308
  {
 
309
    PRUint16 W1 = 0;      // the first UTF-16 word in a two word tuple
 
310
    PRUint32 U = 0;       // the current char as UCS-4
 
311
    int code_length = 0;  // the number of bytes in the UTF-8 sequence for the current char
 
312
 
 
313
    PRUint16 W;
 
314
    while ( (W = *s++) )
 
315
      {
 
316
          /*
 
317
           * On the fly, decoding from UTF-16 (and/or UCS-2) into UTF-8 as per
 
318
           *  http://www.ietf.org/rfc/rfc2781.txt
 
319
           *  http://www.ietf.org/rfc/rfc2279.txt
 
320
           */
 
321
 
 
322
        if ( !W1 )
 
323
          {
 
324
            if ( W < 0xD800 || 0xDFFF < W )
 
325
              {
 
326
                U = W;
 
327
                if ( W <= 0x007F )
 
328
                  code_length = 1;
 
329
                else if ( W <= 0x07FF )
 
330
                  code_length = 2;
 
331
                else
 
332
                  code_length = 3;
 
333
              }
 
334
            else if ( /* 0xD800 <= W1 && */ W <= 0xDBFF )
 
335
              W1 = W;
 
336
          }
 
337
        else
 
338
          {
 
339
              // as required by the standard, this code is careful to
 
340
              //  throw out illegal sequences
 
341
 
 
342
            if ( 0xDC00 <= W && W <= 0xDFFF )
 
343
              {
 
344
                U = PRUint32( (W1&0x03FF)<<10 | (W&0x3FFF) );
 
345
                if ( U <= 0x001FFFFF )
 
346
                  code_length = 4;
 
347
                else if ( U <= 0x3FFFFFF )
 
348
                  code_length = 5;
 
349
                else
 
350
                  code_length = 6;
 
351
              }
 
352
            W1 = 0;
 
353
          }
 
354
 
 
355
 
 
356
        if ( code_length > 0 )
 
357
          {
 
358
            static const PRUint16 sBytePrefix[7]  = { 0x0000, 0x0000, 0x00C0, 0x00E0, 0x00F0, 0x00F8, 0x00FC };
 
359
            static const PRUint16 sShift[7]       = { 0, 0, 6, 12, 18, 24, 30 };
 
360
 
 
361
              /*
 
362
               * Unlike the algorithm in http://www.ietf.org/rfc/rfc2279.txt
 
363
               *  we must calculate the bytes in left to right order so that
 
364
               *  our hash result matches what the narrow version would calculate
 
365
               *  on an already UTF-8 string.
 
366
               */
 
367
 
 
368
              // hash the first (and often, only, byte)
 
369
            h = (h>>28) ^ (h<<4) ^ (sBytePrefix[code_length] | (U>>sShift[code_length]));
 
370
 
 
371
              // an unrolled loop for hashing any remaining bytes in this sequence
 
372
            switch ( code_length )
 
373
              {  // falling through in each case
 
374
                case 6:   h = (h>>28) ^ (h<<4) ^ (0x80 | ((U>>24) & 0x003F));
 
375
                case 5:   h = (h>>28) ^ (h<<4) ^ (0x80 | ((U>>18) & 0x003F));
 
376
                case 4:   h = (h>>28) ^ (h<<4) ^ (0x80 | ((U>>12) & 0x003F));
 
377
                case 3:   h = (h>>28) ^ (h<<4) ^ (0x80 | ((U>>6 ) & 0x003F));
 
378
                case 2:   h = (h>>28) ^ (h<<4) ^ (0x80 | ( U      & 0x003F));
 
379
                default:  code_length = 0;
 
380
                  break;
 
381
              }
 
382
          }
 
383
      }
 
384
  }
 
385
 
 
386
  if ( resultingStrLen )
 
387
    *resultingStrLen = (s-str)-1;
 
388
  return h;
 
389
}
 
390
 
 
391
PRUint32 nsCRT::BufferHashCode(const char* s, PRUint32 len)
 
392
{
 
393
  PRUint32 h = 0;
 
394
  const char* done = s + len;
 
395
 
 
396
  while ( s < done )
 
397
    h = (h>>28) ^ (h<<4) ^ PRUint8(*s++); // cast to unsigned to prevent possible sign extension
 
398
 
 
399
  return h;
 
400
}
 
401
 
 
402
PRUint32 nsCRT::BufferHashCode(const PRUnichar* s, PRUint32 len)
 
403
{
 
404
  PRUint32 h = 0;
 
405
  const PRUnichar* done = s + len;
 
406
 
 
407
  while ( s < done )
 
408
    h = (h>>28) ^ (h<<4) ^ PRUint16(*s++); // cast to unsigned to prevent possible sign extension
 
409
 
 
410
  return h;
 
411
}
 
412
 
 
413
// This should use NSPR but NSPR isn't exporting its PR_strtoll function
 
414
// Until then...
 
415
PRInt64 nsCRT::atoll(const char *str)
 
416
{
 
417
    if (!str)
 
418
        return LL_Zero();
 
419
 
 
420
    PRInt64 ll = LL_Zero(), digitll = LL_Zero();
 
421
 
 
422
    while (*str && *str >= '0' && *str <= '9') {
 
423
        LL_MUL(ll, ll, 10);
 
424
        LL_UI2L(digitll, (*str - '0'));
 
425
        LL_ADD(ll, ll, digitll);
 
426
        str++;
 
427
    }
 
428
 
 
429
    return ll;
 
430
}
 
431
 
 
432
/**
 
433
 *  Determine if given char in valid ascii range
 
434
 *  
 
435
 *  @update  ftang 04.27.2000
 
436
 *  @param   aChar is character to be tested
 
437
 *  @return  TRUE if in ASCII range
 
438
 */
 
439
PRBool nsCRT::IsAscii(PRUnichar aChar) {
 
440
  return (0x0080 > aChar);
 
441
}
 
442
/**
 
443
 *  Determine if given char in valid ascii range
 
444
 *  
 
445
 *  @update  ftang 10.02.2001
 
446
 *  @param   aString is null terminated to be tested
 
447
 *  @return  TRUE if all characters aare in ASCII range
 
448
 */
 
449
PRBool nsCRT::IsAscii(const PRUnichar *aString) {
 
450
  while(*aString) {
 
451
     if( 0x0080 <= *aString)
 
452
        return PR_FALSE;
 
453
     aString++;
 
454
  }
 
455
  return PR_TRUE;
 
456
}
 
457
/**
 
458
 *  Determine if given char in valid ascii range
 
459
 *  
 
460
 *  @update  ftang 10.02.2001
 
461
 *  @param   aString is null terminated to be tested
 
462
 *  @return  TRUE if all characters aare in ASCII range
 
463
 */
 
464
PRBool nsCRT::IsAscii(const char *aString) {
 
465
  while(*aString) {
 
466
     if( 0x80 & *aString)
 
467
        return PR_FALSE;
 
468
     aString++;
 
469
  }
 
470
  return PR_TRUE;
 
471
}
 
472
/**
 
473
 *  Determine whether the given string consists of valid ascii chars
 
474
 *  
 
475
 *  @param   aString is null terminated
 
476
 *  @param   aLength is the number of chars to test.  This must be at most
 
477
 *           the number of chars in aString before the null terminator
 
478
 *  @return  PR_TRUE if all chars are valid ASCII chars, PR_FALSE otherwise
 
479
 */
 
480
PRBool nsCRT::IsAscii(const char* aString, PRUint32 aLength)
 
481
{
 
482
    const char* end = aString + aLength;
 
483
    while (aString < end) {
 
484
        NS_ASSERTION(*aString, "Null byte before end of data!");
 
485
        if (0x80 & *aString)
 
486
            return PR_FALSE;
 
487
        ++aString;
 
488
    }
 
489
    return PR_TRUE;
 
490
}
 
491
 
 
492
/**
 
493
 *  Determine if given char in valid alpha range
 
494
 *  
 
495
 *  @update  rickg 03.10.2000
 
496
 *  @param   aChar is character to be tested
 
497
 *  @return  TRUE if in alpha range
 
498
 */
 
499
PRBool nsCRT::IsAsciiAlpha(PRUnichar aChar) {
 
500
  // XXX i18n
 
501
  if (((aChar >= 'A') && (aChar <= 'Z')) || ((aChar >= 'a') && (aChar <= 'z'))) {
 
502
    return PR_TRUE;
 
503
  }
 
504
  return PR_FALSE;
 
505
}
 
506
 
 
507
/**
 
508
 *  Determine if given char is a valid space character
 
509
 *  
 
510
 *  @update  rickg 03.10.2000
 
511
 *  @param   aChar is character to be tested
 
512
 *  @return  TRUE if is valid space char
 
513
 */
 
514
PRBool nsCRT::IsAsciiSpace(PRUnichar aChar) {
 
515
  // XXX i18n
 
516
  if ((aChar == ' ') || (aChar == '\r') || (aChar == '\n') || (aChar == '\t')) {
 
517
    return PR_TRUE;
 
518
  }
 
519
  return PR_FALSE;
 
520
}
 
521
 
 
522
 
 
523
 
 
524
/**
 
525
 *  Determine if given char is valid digit
 
526
 *  
 
527
 *  @update  rickg 03.10.2000
 
528
 *  @param   aChar is character to be tested
 
529
 *  @return  TRUE if char is a valid digit
 
530
 */
 
531
PRBool nsCRT::IsAsciiDigit(PRUnichar aChar) {
 
532
  // XXX i18n
 
533
  return PRBool((aChar >= '0') && (aChar <= '9'));
 
534
}