/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim: set ts=8 sts=2 et sw=2 tw=80: */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include #ifdef _WIN32 #include #else #include #endif #include #include "mozilla/Assertions.h" #include "mozilla/Unused.h" /* Template class allowing a limited number of increments on a value */ template class CheckedIncrement { public: CheckedIncrement(T aValue, size_t aMaxIncrement) : mValue(aValue), mMaxIncrement(aMaxIncrement) {} T operator ++(int) { if (!mMaxIncrement) { MOZ_CRASH("overflow detected"); } mMaxIncrement--; return mValue++; } T& operator ++() { (*this)++; return mValue; } operator T() { return mValue; } private: T mValue; size_t mMaxIncrement; }; void FdPrintf(intptr_t aFd, const char* aFormat, ...) { if (aFd == 0) { return; } char buf[256]; CheckedIncrement b(buf, sizeof(buf)); CheckedIncrement f(aFormat, strlen(aFormat) + 1); va_list ap; va_start(ap, aFormat); while (true) { switch (*f) { case '\0': goto out; case '%': switch (*++f) { case 'z': { if (*(++f) == 'u') { size_t i = va_arg(ap, size_t); size_t x = 1; // Compute the number of digits. while (x <= i / 10) { x *= 10; } // Write the digits into the buffer. do { *(b++) = "0123456789"[(i / x) % 10]; x /= 10; } while (x > 0); } else { // Write out the format specifier if it's unknown. *(b++) = '%'; *(b++) = 'z'; *(b++) = *f; } break; } case 'p': { intptr_t ptr = va_arg(ap, intptr_t); *(b++) = '0'; *(b++) = 'x'; int x = sizeof(intptr_t) * 8; bool wrote_msb = false; do { x -= 4; size_t hex_digit = ptr >> x & 0xf; if (hex_digit || wrote_msb) { *(b++) = "0123456789abcdef"[hex_digit]; wrote_msb = true; } } while (x > 0); if (!wrote_msb) { *(b++) = '0'; } break; } default: // Write out the format specifier if it's unknown. *(b++) = '%'; *(b++) = *f; break; } break; default: *(b++) = *f; break; } f++; } out: #ifdef _WIN32 // See comment in FdPrintf.h as to why WriteFile is used. DWORD written; WriteFile(reinterpret_cast(aFd), buf, b - buf, &written, nullptr); #else MOZ_UNUSED(write(aFd, buf, b - buf)); #endif va_end(ap); }