Bug 1690340 - Part 4: Insert the "Page Source" before the "Extensions for Developers...
[gecko.git] / xpcom / base / nsCRTGlue.cpp
blob1ad1a90be9a2631940e72bf03a7bba0dcac4b3a4
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "nsCRTGlue.h"
8 #include "nsXPCOM.h"
9 #include "nsDebug.h"
10 #include "prtime.h"
12 #include <stdlib.h>
13 #include <string.h>
14 #include <stdio.h>
15 #include <stdarg.h>
17 #include "mozilla/Sprintf.h"
19 #ifdef XP_WIN
20 # include <io.h>
21 # include <windows.h>
22 # include "mozilla/LateWriteChecks.h"
23 # include "mozilla/UniquePtr.h"
24 #endif
26 #ifdef ANDROID
27 # include <android/log.h>
28 #endif
30 using namespace mozilla;
32 const char* NS_strspnp(const char* aDelims, const char* aStr) {
33 const char* d;
34 do {
35 for (d = aDelims; *d != '\0'; ++d) {
36 if (*aStr == *d) {
37 ++aStr;
38 break;
41 } while (*d);
43 return aStr;
46 char* NS_strtok(const char* aDelims, char** aStr) {
47 if (!*aStr) {
48 return nullptr;
51 char* ret = (char*)NS_strspnp(aDelims, *aStr);
53 if (!*ret) {
54 *aStr = ret;
55 return nullptr;
58 char* i = ret;
59 do {
60 for (const char* d = aDelims; *d != '\0'; ++d) {
61 if (*i == *d) {
62 *i = '\0';
63 *aStr = ++i;
64 return ret;
67 ++i;
68 } while (*i);
70 *aStr = nullptr;
71 return ret;
74 uint32_t NS_strlen(const char16_t* aString) {
75 MOZ_ASSERT(aString);
76 const char16_t* end;
78 for (end = aString; *end; ++end) {
79 // empty loop
82 return end - aString;
85 int NS_strcmp(const char16_t* aStrA, const char16_t* aStrB) {
86 while (*aStrB) {
87 int r = *aStrA - *aStrB;
88 if (r) {
89 return r;
92 ++aStrA;
93 ++aStrB;
96 return *aStrA != '\0';
99 int NS_strncmp(const char16_t* aStrA, const char16_t* aStrB, size_t aLen) {
100 while (aLen && *aStrB) {
101 int r = *aStrA - *aStrB;
102 if (r) {
103 return r;
106 ++aStrA;
107 ++aStrB;
108 --aLen;
111 return aLen ? *aStrA != '\0' : 0;
114 char16_t* NS_xstrdup(const char16_t* aString) {
115 uint32_t len = NS_strlen(aString);
116 return NS_xstrndup(aString, len);
119 template <typename CharT>
120 CharT* NS_xstrndup(const CharT* aString, uint32_t aLen) {
121 auto newBuf = (CharT*)moz_xmalloc((aLen + 1) * sizeof(CharT));
122 memcpy(newBuf, aString, aLen * sizeof(CharT));
123 newBuf[aLen] = '\0';
124 return newBuf;
127 template char16_t* NS_xstrndup<char16_t>(const char16_t* aString,
128 uint32_t aLen);
129 template char* NS_xstrndup<char>(const char* aString, uint32_t aLen);
131 char* NS_xstrdup(const char* aString) {
132 uint32_t len = strlen(aString);
133 char* str = (char*)moz_xmalloc(len + 1);
134 memcpy(str, aString, len);
135 str[len] = '\0';
136 return str;
139 // clang-format off
141 // This table maps uppercase characters to lower case characters;
142 // characters that are neither upper nor lower case are unaffected.
143 const unsigned char nsLowerUpperUtils::kUpper2Lower[256] = {
144 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
145 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
146 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
147 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
150 // upper band mapped to lower [A-Z] => [a-z]
151 97, 98, 99,100,101,102,103,104,105,106,107,108,109,110,111,
152 112,113,114,115,116,117,118,119,120,121,122,
154 91, 92, 93, 94, 95,
155 96, 97, 98, 99,100,101,102,103,104,105,106,107,108,109,110,111,
156 112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,
157 128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,
158 144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,
159 160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,
160 176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,
161 192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,
162 208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,
163 224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,
164 240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255
167 const unsigned char nsLowerUpperUtils::kLower2Upper[256] = {
168 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
169 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
170 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
171 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
172 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
173 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
176 // lower band mapped to upper [a-z] => [A-Z]
177 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
178 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90,
180 123,124,125,126,127,
181 128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,
182 144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,
183 160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,
184 176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,
185 192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,
186 208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,
187 224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,
188 240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255
191 // clang-format on
193 bool NS_IsUpper(char aChar) {
194 return aChar != (char)nsLowerUpperUtils::kUpper2Lower[(unsigned char)aChar];
197 bool NS_IsLower(char aChar) {
198 return aChar != (char)nsLowerUpperUtils::kLower2Upper[(unsigned char)aChar];
201 #ifndef XPCOM_GLUE_AVOID_NSPR
203 void NS_MakeRandomString(char* aBuf, int32_t aBufLen) {
204 # define TABLE_SIZE 36
205 static const char table[] = {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i',
206 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r',
207 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0',
208 '1', '2', '3', '4', '5', '6', '7', '8', '9'};
210 // turn PR_Now() into milliseconds since epoch
211 // and salt rand with that.
212 static unsigned int seed = 0;
213 if (seed == 0) {
214 double fpTime = double(PR_Now());
215 seed =
216 (unsigned int)(fpTime * 1e-6 + 0.5); // use 1e-6, granularity of
217 // PR_Now() on the mac is seconds
218 srand(seed);
221 int32_t i;
222 for (i = 0; i < aBufLen; ++i) {
223 *aBuf++ = table[rand() % TABLE_SIZE];
225 *aBuf = 0;
228 #endif
230 #ifdef HAVE_VA_COPY
231 # define VARARGS_ASSIGN(foo, bar) VA_COPY(foo, bar)
232 #elif defined(HAVE_VA_LIST_AS_ARRAY)
233 # define VARARGS_ASSIGN(foo, bar) foo[0] = bar[0]
234 #else
235 # define VARARGS_ASSIGN(foo, bar) (foo) = (bar)
236 #endif
238 #if defined(XP_WIN)
239 void vprintf_stderr(const char* aFmt, va_list aArgs) {
240 if (IsDebuggerPresent()) {
241 int lengthNeeded = _vscprintf(aFmt, aArgs);
242 if (lengthNeeded) {
243 lengthNeeded++;
244 auto buf = MakeUnique<char[]>(lengthNeeded);
245 if (buf) {
246 va_list argsCpy;
247 VARARGS_ASSIGN(argsCpy, aArgs);
248 vsnprintf(buf.get(), lengthNeeded, aFmt, argsCpy);
249 buf[lengthNeeded - 1] = '\0';
250 va_end(argsCpy);
251 OutputDebugStringA(buf.get());
256 FILE* fp = _fdopen(_dup(2), "a");
257 if (!fp) {
258 return;
261 vfprintf(fp, aFmt, aArgs);
263 AutoSuspendLateWriteChecks suspend;
264 fclose(fp);
267 #elif defined(ANDROID)
268 void vprintf_stderr(const char* aFmt, va_list aArgs) {
269 __android_log_vprint(ANDROID_LOG_INFO, "Gecko", aFmt, aArgs);
271 #else
272 void vprintf_stderr(const char* aFmt, va_list aArgs) {
273 vfprintf(stderr, aFmt, aArgs);
275 #endif
277 void printf_stderr(const char* aFmt, ...) {
278 va_list args;
279 va_start(args, aFmt);
280 vprintf_stderr(aFmt, args);
281 va_end(args);
284 void fprintf_stderr(FILE* aFile, const char* aFmt, ...) {
285 va_list args;
286 va_start(args, aFmt);
287 if (aFile == stderr) {
288 vprintf_stderr(aFmt, args);
289 } else {
290 vfprintf(aFile, aFmt, args);
292 va_end(args);
295 void print_stderr(std::stringstream& aStr) {
296 #if defined(ANDROID)
297 // On Android logcat output is truncated to 1024 chars per line, and
298 // we usually use std::stringstream to build up giant multi-line gobs
299 // of output. So to avoid the truncation we find the newlines and
300 // print the lines individually.
301 std::string line;
302 while (std::getline(aStr, line)) {
303 printf_stderr("%s\n", line.c_str());
305 #else
306 printf_stderr("%s", aStr.str().c_str());
307 #endif
310 void fprint_stderr(FILE* aFile, std::stringstream& aStr) {
311 if (aFile == stderr) {
312 print_stderr(aStr);
313 } else {
314 fprintf_stderr(aFile, "%s", aStr.str().c_str());