tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

JSONPrinter.cpp (6117B)


      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/. */
      6 
      7 #include "vm/JSONPrinter.h"
      8 
      9 #include "mozilla/Assertions.h"
     10 #include "mozilla/IntegerPrintfMacros.h"
     11 
     12 #include <stdarg.h>
     13 
     14 #include "jsnum.h"
     15 
     16 using namespace js;
     17 
     18 void JSONPrinter::indent() {
     19  MOZ_ASSERT(indentLevel_ >= 0);
     20 
     21  if (inlineLevel_ > 0) {
     22    out_.putChar(' ');
     23    return;
     24  }
     25 
     26  if (indent_) {
     27    out_.putChar('\n');
     28    for (int i = 0; i < indentLevel_; i++) {
     29      out_.put("  ");
     30    }
     31  }
     32 }
     33 
     34 void JSONPrinter::beforeValue() {
     35  if (!first_) {
     36    out_.putChar(',');
     37  }
     38  indent();
     39 }
     40 
     41 void JSONPrinter::propertyName(const char* name) {
     42  beforeValue();
     43  out_.printf("\"%s\":", name);
     44  if (indent_) {
     45    out_.put(" ");
     46  }
     47  first_ = false;
     48 }
     49 
     50 void JSONPrinter::beginObject() {
     51  beforeValue();
     52  out_.putChar('{');
     53  indentLevel_++;
     54  first_ = true;
     55 }
     56 
     57 void JSONPrinter::beginList() {
     58  beforeValue();
     59  out_.putChar('[');
     60  indentLevel_++;
     61  first_ = true;
     62 }
     63 
     64 void JSONPrinter::beginObjectProperty(const char* name) {
     65  propertyName(name);
     66  out_.putChar('{');
     67  indentLevel_++;
     68  first_ = true;
     69 }
     70 
     71 void JSONPrinter::beginListProperty(const char* name) {
     72  propertyName(name);
     73  out_.putChar('[');
     74  indentLevel_++;
     75  first_ = true;
     76 }
     77 
     78 void JSONPrinter::beginInlineListProperty(const char* name) {
     79  beginListProperty(name);
     80  beginInline();
     81 }
     82 
     83 GenericPrinter& JSONPrinter::beginStringProperty(const char* name) {
     84  propertyName(name);
     85  out_.putChar('"');
     86  return out_;
     87 }
     88 
     89 void JSONPrinter::endStringProperty() {
     90  endString();
     91  first_ = false;
     92 }
     93 
     94 GenericPrinter& JSONPrinter::beginString() {
     95  beforeValue();
     96  out_.putChar('"');
     97  return out_;
     98 }
     99 
    100 void JSONPrinter::endString() { out_.putChar('"'); }
    101 
    102 void JSONPrinter::boolProperty(const char* name, bool value) {
    103  propertyName(name);
    104  out_.put(value ? "true" : "false");
    105 }
    106 
    107 template <typename CharT>
    108 static void JSONString(GenericPrinter& out, const CharT* s, size_t length) {
    109  const CharT* end = s + length;
    110  for (const CharT* t = s; t < end; s = ++t) {
    111    // This quote implementation is probably correct,
    112    // but uses \u even when not strictly necessary.
    113    char16_t c = *t;
    114    if (c == '"' || c == '\\') {
    115      out.printf("\\");
    116      out.printf("%c", char(c));
    117    } else if (!IsAsciiPrintable(c)) {
    118      out.printf("\\u%04x", c);
    119    } else {
    120      out.printf("%c", char(c));
    121    }
    122  }
    123 }
    124 
    125 void JSONPrinter::property(const char* name, const JSLinearString* str) {
    126  JS::AutoCheckCannotGC nogc;
    127  beginStringProperty(name);
    128 
    129  // Limit the string length to reduce the JSON file size.
    130  size_t length = std::min(str->length(), size_t(128));
    131  if (str->hasLatin1Chars()) {
    132    JSONString(out_, str->latin1Chars(nogc), length);
    133  } else {
    134    JSONString(out_, str->twoByteChars(nogc), length);
    135  }
    136  endStringProperty();
    137 }
    138 
    139 void JSONPrinter::property(const char* name, const char* value) {
    140  beginStringProperty(name);
    141  out_.put(value);
    142  endStringProperty();
    143 }
    144 
    145 void JSONPrinter::formatProperty(const char* name, const char* format, ...) {
    146  va_list ap;
    147  va_start(ap, format);
    148 
    149  beginStringProperty(name);
    150  out_.vprintf(format, ap);
    151  endStringProperty();
    152 
    153  va_end(ap);
    154 }
    155 
    156 void JSONPrinter::formatPropertyVA(const char* name, const char* format,
    157                                   va_list ap) {
    158  beginStringProperty(name);
    159  out_.vprintf(format, ap);
    160  endStringProperty();
    161 }
    162 
    163 void JSONPrinter::value(const char* format, ...) {
    164  va_list ap;
    165  va_start(ap, format);
    166 
    167  beforeValue();
    168  out_.putChar('"');
    169  out_.vprintf(format, ap);
    170  out_.putChar('"');
    171 
    172  va_end(ap);
    173  first_ = false;
    174 }
    175 
    176 void JSONPrinter::property(const char* name, int32_t value) {
    177  propertyName(name);
    178  out_.printf("%" PRId32, value);
    179 }
    180 
    181 void JSONPrinter::value(int val) {
    182  beforeValue();
    183  out_.printf("%d", val);
    184  first_ = false;
    185 }
    186 
    187 void JSONPrinter::property(const char* name, uint32_t value) {
    188  propertyName(name);
    189  out_.printf("%" PRIu32, value);
    190 }
    191 
    192 void JSONPrinter::property(const char* name, int64_t value) {
    193  propertyName(name);
    194  out_.printf("%" PRId64, value);
    195 }
    196 
    197 void JSONPrinter::property(const char* name, uint64_t value) {
    198  propertyName(name);
    199  out_.printf("%" PRIu64, value);
    200 }
    201 
    202 #if defined(XP_DARWIN) || defined(__OpenBSD__) || defined(__wasi__)
    203 void JSONPrinter::property(const char* name, size_t value) {
    204  propertyName(name);
    205  out_.printf("%zu", value);
    206 }
    207 #endif
    208 
    209 void JSONPrinter::floatProperty(const char* name, double value,
    210                                size_t precision) {
    211  if (!std::isfinite(value)) {
    212    propertyName(name);
    213    out_.put("null");
    214    return;
    215  }
    216 
    217  ToCStringBuf cbuf;
    218  const char* str = NumberToCString(&cbuf, value);
    219  MOZ_ASSERT(str);
    220 
    221  property(name, str);
    222 }
    223 
    224 void JSONPrinter::property(const char* name, const mozilla::TimeDuration& dur,
    225                           TimePrecision precision) {
    226  if (precision == MICROSECONDS) {
    227    property(name, static_cast<int64_t>(dur.ToMicroseconds()));
    228    return;
    229  }
    230 
    231  propertyName(name);
    232  lldiv_t split;
    233  switch (precision) {
    234    case SECONDS:
    235      split = lldiv(static_cast<int64_t>(dur.ToMilliseconds()), 1000);
    236      break;
    237    case MILLISECONDS:
    238      split = lldiv(static_cast<int64_t>(dur.ToMicroseconds()), 1000);
    239      break;
    240    case MICROSECONDS:
    241      MOZ_ASSERT_UNREACHABLE("");
    242  };
    243  out_.printf("%lld.%03lld", split.quot, split.rem);
    244 }
    245 
    246 void JSONPrinter::nullProperty(const char* name) {
    247  propertyName(name);
    248  out_.put("null");
    249 }
    250 
    251 void JSONPrinter::nullValue() {
    252  beforeValue();
    253  out_.put("null");
    254  first_ = false;
    255 }
    256 
    257 void JSONPrinter::endObject() {
    258  indentLevel_--;
    259  indent();
    260  out_.putChar('}');
    261  first_ = false;
    262 }
    263 
    264 void JSONPrinter::endList() {
    265  indentLevel_--;
    266  indent();
    267  out_.putChar(']');
    268  first_ = false;
    269 }
    270 
    271 void JSONPrinter::endInlineList() {
    272  endList();
    273  endInline();
    274 }
    275 
    276 void JSONPrinter::beginInline() { inlineLevel_++; }
    277 
    278 void JSONPrinter::endInline() { inlineLevel_--; }