DXR is a code search and navigation tool aimed at making sense of large projects. It supports full-text and regex searches as well as structural queries.

Header

Mercurial (fb59957df144)

VCS Links

Line Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126
/* -*- 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 <cstdarg>

#ifdef _WIN32
#  include <windows.h>
#else
#  include <unistd.h>
#endif
#include <cstring>
#include "mozilla/Assertions.h"
#include "mozilla/Unused.h"

/* Template class allowing a limited number of increments on a value */
template <typename T>
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<char*> b(buf, sizeof(buf));
  CheckedIncrement<const char*> 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<HANDLE>(aFd), buf, b - buf, &written, nullptr);
#else
  MOZ_UNUSED(write(aFd, buf, b - buf));
#endif
  va_end(ap);
}