Backed out 2 changesets (bug 1853057) for causing mda failures on test_video_low_powe...
[gecko.git] / xpcom / base / nsCRTGlue.cpp
blob925379f716ffe0a6a0602f0a6bc4c500aa17e3b1
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 #ifdef FUZZING_SNAPSHOT
31 # include <mozilla/fuzzing/NyxWrapper.h>
32 #endif
34 using namespace mozilla;
36 const char* NS_strspnp(const char* aDelims, const char* aStr) {
37 const char* d;
38 do {
39 for (d = aDelims; *d != '\0'; ++d) {
40 if (*aStr == *d) {
41 ++aStr;
42 break;
45 } while (*d);
47 return aStr;
50 char* NS_strtok(const char* aDelims, char** aStr) {
51 if (!*aStr) {
52 return nullptr;
55 char* ret = (char*)NS_strspnp(aDelims, *aStr);
57 if (!*ret) {
58 *aStr = ret;
59 return nullptr;
62 char* i = ret;
63 do {
64 for (const char* d = aDelims; *d != '\0'; ++d) {
65 if (*i == *d) {
66 *i = '\0';
67 *aStr = ++i;
68 return ret;
71 ++i;
72 } while (*i);
74 *aStr = nullptr;
75 return ret;
78 uint32_t NS_strlen(const char16_t* aString) {
79 MOZ_ASSERT(aString);
80 const char16_t* end;
82 for (end = aString; *end; ++end) {
83 // empty loop
86 return end - aString;
89 int NS_strcmp(const char16_t* aStrA, const char16_t* aStrB) {
90 while (*aStrB) {
91 int r = *aStrA - *aStrB;
92 if (r) {
93 return r;
96 ++aStrA;
97 ++aStrB;
100 return *aStrA != '\0';
103 int NS_strncmp(const char16_t* aStrA, const char16_t* aStrB, size_t aLen) {
104 while (aLen && *aStrB) {
105 int r = *aStrA - *aStrB;
106 if (r) {
107 return r;
110 ++aStrA;
111 ++aStrB;
112 --aLen;
115 return aLen ? *aStrA != '\0' : 0;
118 char16_t* NS_xstrdup(const char16_t* aString) {
119 uint32_t len = NS_strlen(aString);
120 return NS_xstrndup(aString, len);
123 template <typename CharT>
124 CharT* NS_xstrndup(const CharT* aString, uint32_t aLen) {
125 auto newBuf = (CharT*)moz_xmalloc((aLen + 1) * sizeof(CharT));
126 memcpy(newBuf, aString, aLen * sizeof(CharT));
127 newBuf[aLen] = '\0';
128 return newBuf;
131 template char16_t* NS_xstrndup<char16_t>(const char16_t* aString,
132 uint32_t aLen);
133 template char* NS_xstrndup<char>(const char* aString, uint32_t aLen);
135 char* NS_xstrdup(const char* aString) {
136 uint32_t len = strlen(aString);
137 char* str = (char*)moz_xmalloc(len + 1);
138 memcpy(str, aString, len);
139 str[len] = '\0';
140 return str;
143 // clang-format off
145 // This table maps uppercase characters to lower case characters;
146 // characters that are neither upper nor lower case are unaffected.
147 const unsigned char nsLowerUpperUtils::kUpper2Lower[256] = {
148 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
149 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
150 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
151 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
154 // upper band mapped to lower [A-Z] => [a-z]
155 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,
158 91, 92, 93, 94, 95,
159 96, 97, 98, 99,100,101,102,103,104,105,106,107,108,109,110,111,
160 112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,
161 128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,
162 144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,
163 160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,
164 176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,
165 192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,
166 208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,
167 224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,
168 240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255
171 const unsigned char nsLowerUpperUtils::kLower2Upper[256] = {
172 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
173 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
174 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
175 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
176 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
177 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
180 // lower band mapped to upper [a-z] => [A-Z]
181 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
182 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90,
184 123,124,125,126,127,
185 128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,
186 144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,
187 160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,
188 176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,
189 192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,
190 208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,
191 224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,
192 240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255
195 // clang-format on
197 bool NS_IsUpper(char aChar) {
198 return aChar != (char)nsLowerUpperUtils::kUpper2Lower[(unsigned char)aChar];
201 bool NS_IsLower(char aChar) {
202 return aChar != (char)nsLowerUpperUtils::kLower2Upper[(unsigned char)aChar];
205 #ifndef XPCOM_GLUE_AVOID_NSPR
207 void NS_MakeRandomString(char* aBuf, int32_t aBufLen) {
208 # define TABLE_SIZE 36
209 static const char table[] = {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i',
210 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r',
211 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0',
212 '1', '2', '3', '4', '5', '6', '7', '8', '9'};
214 // turn PR_Now() into milliseconds since epoch
215 // and salt rand with that.
216 static unsigned int seed = 0;
217 if (seed == 0) {
218 double fpTime = double(PR_Now());
219 seed =
220 (unsigned int)(fpTime * 1e-6 + 0.5); // use 1e-6, granularity of
221 // PR_Now() on the mac is seconds
222 srand(seed);
225 int32_t i;
226 for (i = 0; i < aBufLen; ++i) {
227 *aBuf++ = table[rand() % TABLE_SIZE];
229 *aBuf = 0;
232 #endif
234 #if defined(XP_WIN)
235 void vprintf_stderr(const char* aFmt, va_list aArgs) {
236 if (IsDebuggerPresent()) {
237 int lengthNeeded = _vscprintf(aFmt, aArgs);
238 if (lengthNeeded) {
239 lengthNeeded++;
240 auto buf = MakeUnique<char[]>(lengthNeeded);
241 if (buf) {
242 va_list argsCpy;
243 va_copy(argsCpy, aArgs);
244 vsnprintf(buf.get(), lengthNeeded, aFmt, argsCpy);
245 buf[lengthNeeded - 1] = '\0';
246 va_end(argsCpy);
247 OutputDebugStringA(buf.get());
252 // stderr is unbuffered by default so we open a new FILE (which is buffered)
253 // so that calls to printf_stderr are not as likely to get mixed together.
254 int fd = _fileno(stderr);
255 if (fd == -2) {
256 return;
259 FILE* fp = _fdopen(_dup(fd), "a");
260 if (!fp) {
261 return;
264 vfprintf(fp, aFmt, aArgs);
266 AutoSuspendLateWriteChecks suspend;
267 fclose(fp);
270 #elif defined(ANDROID)
271 void vprintf_stderr(const char* aFmt, va_list aArgs) {
272 __android_log_vprint(ANDROID_LOG_INFO, "Gecko", aFmt, aArgs);
274 #elif defined(FUZZING_SNAPSHOT)
275 void vprintf_stderr(const char* aFmt, va_list aArgs) {
276 if (nyx_puts) {
277 auto msgbuf = mozilla::Vsmprintf(aFmt, aArgs);
278 nyx_puts(msgbuf.get());
279 } else {
280 vfprintf(stderr, aFmt, aArgs);
283 #else
284 void vprintf_stderr(const char* aFmt, va_list aArgs) {
285 vfprintf(stderr, aFmt, aArgs);
287 #endif
289 void printf_stderr(const char* aFmt, ...) {
290 va_list args;
291 va_start(args, aFmt);
292 vprintf_stderr(aFmt, args);
293 va_end(args);
296 void fprintf_stderr(FILE* aFile, const char* aFmt, ...) {
297 va_list args;
298 va_start(args, aFmt);
299 if (aFile == stderr) {
300 vprintf_stderr(aFmt, args);
301 } else {
302 vfprintf(aFile, aFmt, args);
304 va_end(args);
307 void print_stderr(std::stringstream& aStr) {
308 #if defined(ANDROID)
309 // On Android logcat output is truncated to 1024 chars per line, and
310 // we usually use std::stringstream to build up giant multi-line gobs
311 // of output. So to avoid the truncation we find the newlines and
312 // print the lines individually.
313 std::string line;
314 while (std::getline(aStr, line)) {
315 printf_stderr("%s\n", line.c_str());
317 #else
318 printf_stderr("%s", aStr.str().c_str());
319 #endif
322 void fprint_stderr(FILE* aFile, std::stringstream& aStr) {
323 if (aFile == stderr) {
324 print_stderr(aStr);
325 } else {
326 fprintf_stderr(aFile, "%s", aStr.str().c_str());