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/. */
16 #include "mozilla/Assertions.h"
17 #include "mozilla/Unused.h"
20 /* Template class allowing a limited number of increments on a value */
22 class CheckedIncrement
{
24 CheckedIncrement(T aValue
, size_t aMaxIncrement
)
25 : mValue(aValue
), mMaxIncrement(aMaxIncrement
) {}
29 MOZ_CRASH("overflow detected");
41 // Only makes sense if T is a pointer type.
42 size_t diff
= end
- mValue
;
43 if (diff
> mMaxIncrement
) {
44 MOZ_CRASH("overflow detected");
46 mMaxIncrement
-= diff
;
51 size_t diff
= mValue
- pos
;
52 mMaxIncrement
+= diff
;
56 operator T() { return mValue
; }
57 T
value() { return mValue
; }
65 static unsigned NumDigits(T n
) {
67 // We want one digit, it will be 0.
71 double l
= log10(static_cast<double>(n
));
73 return l
== cl
? unsigned(cl
) + 1 : unsigned(cl
);
76 static void LeftPad(CheckedIncrement
<char*>& b
, size_t pad
) {
82 // Write the digits into the buffer.
83 static void WriteDigits(CheckedIncrement
<char*>& b
, size_t i
,
85 size_t x
= pow(10, double(num_digits
- 1));
87 *(b
++) = "0123456789"[(i
/ x
) % 10];
92 void FdPrintf(intptr_t aFd
, const char* aFormat
, ...) {
97 CheckedIncrement
<char*> b(buf
, sizeof(buf
));
98 CheckedIncrement
<const char*> f(aFormat
, strlen(aFormat
) + 1);
100 va_start(ap
, aFormat
);
107 // The start of the format specifier is used if this specifier is
109 const char* start
= f
;
111 // Read the field width
114 size_t width
= strtoul(f
, &end
, 10);
115 // If strtol can't find a number that's okay, that means 0 in our
116 // case, but we must advance f).
122 size_t i
= va_arg(ap
, size_t);
124 size_t num_digits
= NumDigits(i
);
125 LeftPad(b
, width
> num_digits
? width
- num_digits
: 0);
126 WriteDigits(b
, i
, num_digits
);
128 // If the format specifier is unknown then write out '%' and
129 // rewind to the beginning of the specifier causing it to be
138 intptr_t ptr
= va_arg(ap
, intptr_t);
141 int x
= sizeof(intptr_t) * 8;
142 bool wrote_msb
= false;
145 size_t hex_digit
= ptr
>> x
& 0xf;
146 if (hex_digit
|| wrote_msb
) {
147 *(b
++) = "0123456789abcdef"[hex_digit
];
158 const char* str
= va_arg(ap
, const char*);
159 size_t len
= strlen(str
);
161 LeftPad(b
, width
> len
? width
- len
: 0);
171 // Print a single raw '%'.
176 // If the format specifier is unknown then write out '%' and
177 // rewind to the beginning of the specifier causing it to be
193 // See comment in FdPrintf.h as to why WriteFile is used.
195 WriteFile(reinterpret_cast<HANDLE
>(aFd
), buf
, b
- buf
, &written
, nullptr);
197 MOZ_UNUSED(write(aFd
, buf
, b
- buf
));