| |
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
| |
2 /* This Source Code Form is subject to the terms of the Mozilla Public |
| |
3 * License, v. 2.0. If a copy of the MPL was not distributed with this |
| |
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
| |
5 |
| |
6 |
| |
7 /** |
| |
8 * MODULE NOTES: |
| |
9 * @update gess7/30/98 |
| |
10 * |
| |
11 * Much as I hate to do it, we were using string compares wrong. |
| |
12 * Often, programmers call functions like strcmp(s1,s2), and pass |
| |
13 * one or more null strings. Rather than blow up on these, I've |
| |
14 * added quick checks to ensure that cases like this don't cause |
| |
15 * us to fail. |
| |
16 * |
| |
17 * In general, if you pass a null into any of these string compare |
| |
18 * routines, we simply return 0. |
| |
19 */ |
| |
20 |
| |
21 |
| |
22 #include "nsCRT.h" |
| |
23 #include "nsDebug.h" |
| |
24 |
| |
25 //---------------------------------------------------------------------- |
| |
26 |
| |
27 |
| |
28 //////////////////////////////////////////////////////////////////////////////// |
| |
29 // My lovely strtok routine |
| |
30 |
| |
31 #define IS_DELIM(m, c) ((m)[(c) >> 3] & (1 << ((c) & 7))) |
| |
32 #define SET_DELIM(m, c) ((m)[(c) >> 3] |= (1 << ((c) & 7))) |
| |
33 #define DELIM_TABLE_SIZE 32 |
| |
34 |
| |
35 char* nsCRT::strtok(char* string, const char* delims, char* *newStr) |
| |
36 { |
| |
37 NS_ASSERTION(string, "Unlike regular strtok, the first argument cannot be null."); |
| |
38 |
| |
39 char delimTable[DELIM_TABLE_SIZE]; |
| |
40 uint32_t i; |
| |
41 char* result; |
| |
42 char* str = string; |
| |
43 |
| |
44 for (i = 0; i < DELIM_TABLE_SIZE; i++) |
| |
45 delimTable[i] = '\0'; |
| |
46 |
| |
47 for (i = 0; delims[i]; i++) { |
| |
48 SET_DELIM(delimTable, static_cast<uint8_t>(delims[i])); |
| |
49 } |
| |
50 NS_ASSERTION(delims[i] == '\0', "too many delimiters"); |
| |
51 |
| |
52 // skip to beginning |
| |
53 while (*str && IS_DELIM(delimTable, static_cast<uint8_t>(*str))) { |
| |
54 str++; |
| |
55 } |
| |
56 result = str; |
| |
57 |
| |
58 // fix up the end of the token |
| |
59 while (*str) { |
| |
60 if (IS_DELIM(delimTable, static_cast<uint8_t>(*str))) { |
| |
61 *str++ = '\0'; |
| |
62 break; |
| |
63 } |
| |
64 str++; |
| |
65 } |
| |
66 *newStr = str; |
| |
67 |
| |
68 return str == result ? nullptr : result; |
| |
69 } |
| |
70 |
| |
71 //////////////////////////////////////////////////////////////////////////////// |
| |
72 |
| |
73 /** |
| |
74 * Compare unichar string ptrs, stopping at the 1st null |
| |
75 * NOTE: If both are null, we return 0. |
| |
76 * NOTE: We terminate the search upon encountering a nullptr |
| |
77 * |
| |
78 * @update gess 11/10/99 |
| |
79 * @param s1 and s2 both point to unichar strings |
| |
80 * @return 0 if they match, -1 if s1<s2; 1 if s1>s2 |
| |
81 */ |
| |
82 int32_t nsCRT::strcmp(const char16_t* s1, const char16_t* s2) { |
| |
83 if(s1 && s2) { |
| |
84 for (;;) { |
| |
85 char16_t c1 = *s1++; |
| |
86 char16_t c2 = *s2++; |
| |
87 if (c1 != c2) { |
| |
88 if (c1 < c2) return -1; |
| |
89 return 1; |
| |
90 } |
| |
91 if ((0==c1) || (0==c2)) break; |
| |
92 } |
| |
93 } |
| |
94 else { |
| |
95 if (s1) // s2 must have been null |
| |
96 return -1; |
| |
97 if (s2) // s1 must have been null |
| |
98 return 1; |
| |
99 } |
| |
100 return 0; |
| |
101 } |
| |
102 |
| |
103 /** |
| |
104 * Compare unichar string ptrs, stopping at the 1st null or nth char. |
| |
105 * NOTE: If either is null, we return 0. |
| |
106 * NOTE: We DO NOT terminate the search upon encountering nullptr's before N |
| |
107 * |
| |
108 * @update gess 11/10/99 |
| |
109 * @param s1 and s2 both point to unichar strings |
| |
110 * @return 0 if they match, -1 if s1<s2; 1 if s1>s2 |
| |
111 */ |
| |
112 int32_t nsCRT::strncmp(const char16_t* s1, const char16_t* s2, uint32_t n) { |
| |
113 if(s1 && s2) { |
| |
114 if(n != 0) { |
| |
115 do { |
| |
116 char16_t c1 = *s1++; |
| |
117 char16_t c2 = *s2++; |
| |
118 if (c1 != c2) { |
| |
119 if (c1 < c2) return -1; |
| |
120 return 1; |
| |
121 } |
| |
122 } while (--n != 0); |
| |
123 } |
| |
124 } |
| |
125 return 0; |
| |
126 } |
| |
127 |
| |
128 const char* nsCRT::memmem(const char* haystack, uint32_t haystackLen, |
| |
129 const char* needle, uint32_t needleLen) |
| |
130 { |
| |
131 // Sanity checking |
| |
132 if (!(haystack && needle && haystackLen && needleLen && |
| |
133 needleLen <= haystackLen)) |
| |
134 return nullptr; |
| |
135 |
| |
136 #ifdef HAVE_MEMMEM |
| |
137 return (const char*)::memmem(haystack, haystackLen, needle, needleLen); |
| |
138 #else |
| |
139 // No memmem means we need to roll our own. This isn't really optimized |
| |
140 // for performance ... if that becomes an issue we can take some inspiration |
| |
141 // from the js string compare code in jsstr.cpp |
| |
142 for (uint32_t i = 0; i < haystackLen - needleLen; i++) { |
| |
143 if (!memcmp(haystack + i, needle, needleLen)) |
| |
144 return haystack + i; |
| |
145 } |
| |
146 #endif |
| |
147 return nullptr; |
| |
148 } |
| |
149 |
| |
150 // This should use NSPR but NSPR isn't exporting its PR_strtoll function |
| |
151 // Until then... |
| |
152 int64_t nsCRT::atoll(const char *str) |
| |
153 { |
| |
154 if (!str) |
| |
155 return 0; |
| |
156 |
| |
157 int64_t ll = 0; |
| |
158 |
| |
159 while (*str && *str >= '0' && *str <= '9') { |
| |
160 ll *= 10; |
| |
161 ll += *str - '0'; |
| |
162 str++; |
| |
163 } |
| |
164 |
| |
165 return ll; |
| |
166 } |
| |
167 |