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) 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 of the GNU General Public License Version 2 or later (the "GPL"),
26 : * or 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 MPL, 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 MPL, 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 : #include "nsCharTraits.h"
57 : #include "nsUTF8Utils.h"
58 :
59 : //----------------------------------------------------------------------
60 :
61 :
62 : ////////////////////////////////////////////////////////////////////////////////
63 : // My lovely strtok routine
64 :
65 : #define IS_DELIM(m, c) ((m)[(c) >> 3] & (1 << ((c) & 7)))
66 : #define SET_DELIM(m, c) ((m)[(c) >> 3] |= (1 << ((c) & 7)))
67 : #define DELIM_TABLE_SIZE 32
68 :
69 3202178 : char* nsCRT::strtok(char* string, const char* delims, char* *newStr)
70 : {
71 3202178 : NS_ASSERTION(string, "Unlike regular strtok, the first argument cannot be null.");
72 :
73 : char delimTable[DELIM_TABLE_SIZE];
74 : PRUint32 i;
75 : char* result;
76 3202178 : char* str = string;
77 :
78 105671874 : for (i = 0; i < DELIM_TABLE_SIZE; i++)
79 102469696 : delimTable[i] = '\0';
80 :
81 9604428 : for (i = 0; delims[i]; i++) {
82 6402250 : SET_DELIM(delimTable, static_cast<PRUint8>(delims[i]));
83 : }
84 3202178 : NS_ASSERTION(delims[i] == '\0', "too many delimiters");
85 :
86 : // skip to beginning
87 6417566 : while (*str && IS_DELIM(delimTable, static_cast<PRUint8>(*str))) {
88 13210 : str++;
89 : }
90 3202178 : result = str;
91 :
92 : // fix up the end of the token
93 56198992 : while (*str) {
94 51296325 : if (IS_DELIM(delimTable, static_cast<PRUint8>(*str))) {
95 1501689 : *str++ = '\0';
96 1501689 : break;
97 : }
98 49794636 : str++;
99 : }
100 3202178 : *newStr = str;
101 :
102 3202178 : return str == result ? NULL : result;
103 : }
104 :
105 : ////////////////////////////////////////////////////////////////////////////////
106 :
107 : /**
108 : * Compare unichar string ptrs, stopping at the 1st null
109 : * NOTE: If both are null, we return 0.
110 : * NOTE: We terminate the search upon encountering a NULL
111 : *
112 : * @update gess 11/10/99
113 : * @param s1 and s2 both point to unichar strings
114 : * @return 0 if they match, -1 if s1<s2; 1 if s1>s2
115 : */
116 183841 : PRInt32 nsCRT::strcmp(const PRUnichar* s1, const PRUnichar* s2) {
117 183841 : if(s1 && s2) {
118 1168242 : for (;;) {
119 1350747 : PRUnichar c1 = *s1++;
120 1350747 : PRUnichar c2 = *s2++;
121 1350747 : if (c1 != c2) {
122 16699 : if (c1 < c2) return -1;
123 380 : return 1;
124 : }
125 1334048 : if ((0==c1) || (0==c2)) break;
126 165806 : }
127 : }
128 : else {
129 1336 : if (s1) // s2 must have been null
130 0 : return -1;
131 1336 : if (s2) // s1 must have been null
132 1336 : return 1;
133 : }
134 165806 : return 0;
135 : }
136 :
137 : /**
138 : * Compare unichar string ptrs, stopping at the 1st null or nth char.
139 : * NOTE: If either is null, we return 0.
140 : * NOTE: We DO NOT terminate the search upon encountering NULL's before N
141 : *
142 : * @update gess 11/10/99
143 : * @param s1 and s2 both point to unichar strings
144 : * @return 0 if they match, -1 if s1<s2; 1 if s1>s2
145 : */
146 4 : PRInt32 nsCRT::strncmp(const PRUnichar* s1, const PRUnichar* s2, PRUint32 n) {
147 4 : if(s1 && s2) {
148 4 : if(n != 0) {
149 2 : do {
150 6 : PRUnichar c1 = *s1++;
151 6 : PRUnichar c2 = *s2++;
152 6 : if (c1 != c2) {
153 4 : if (c1 < c2) return -1;
154 2 : return 1;
155 : }
156 : } while (--n != 0);
157 : }
158 : }
159 0 : return 0;
160 : }
161 :
162 0 : const char* nsCRT::memmem(const char* haystack, PRUint32 haystackLen,
163 : const char* needle, PRUint32 needleLen)
164 : {
165 : // Sanity checking
166 0 : if (!(haystack && needle && haystackLen && needleLen &&
167 0 : needleLen <= haystackLen))
168 0 : return NULL;
169 :
170 : #ifdef HAVE_MEMMEM
171 0 : return (const char*)::memmem(haystack, haystackLen, needle, needleLen);
172 : #else
173 : // No memmem means we need to roll our own. This isn't really optimized
174 : // for performance ... if that becomes an issue we can take some inspiration
175 : // from the js string compare code in jsstr.cpp
176 : for (PRInt32 i = 0; i < haystackLen - needleLen; i++) {
177 : if (!memcmp(haystack + i, needle, needleLen))
178 : return haystack + i;
179 : }
180 : #endif
181 : return NULL;
182 : }
183 :
184 0 : PRUnichar* nsCRT::strdup(const PRUnichar* str)
185 : {
186 0 : PRUint32 len = nsCRT::strlen(str);
187 0 : return strndup(str, len);
188 : }
189 :
190 0 : PRUnichar* nsCRT::strndup(const PRUnichar* str, PRUint32 len)
191 : {
192 0 : nsCppSharedAllocator<PRUnichar> shared_allocator;
193 0 : PRUnichar* rslt = shared_allocator.allocate(len + 1); // add one for the null
194 : // PRUnichar* rslt = new PRUnichar[len + 1];
195 :
196 0 : if (rslt == NULL) return NULL;
197 0 : memcpy(rslt, str, len * sizeof(PRUnichar));
198 0 : rslt[len] = 0;
199 0 : return rslt;
200 : }
201 :
202 : // This should use NSPR but NSPR isn't exporting its PR_strtoll function
203 : // Until then...
204 5 : PRInt64 nsCRT::atoll(const char *str)
205 : {
206 5 : if (!str)
207 0 : return LL_Zero();
208 :
209 5 : PRInt64 ll = LL_Zero(), digitll = LL_Zero();
210 :
211 64 : while (*str && *str >= '0' && *str <= '9') {
212 54 : LL_MUL(ll, ll, 10);
213 54 : LL_UI2L(digitll, (*str - '0'));
214 54 : LL_ADD(ll, ll, digitll);
215 54 : str++;
216 : }
217 :
218 5 : return ll;
219 : }
220 :
|