Bug 1867190 - Add prefs for PHC probablities r=glandium
[gecko.git] / js / src / vm / JSONPrinter.cpp
blobd028e0926ebdf5919910f2eb9fe26653b714de2f
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 "vm/JSONPrinter.h"
9 #include "mozilla/Assertions.h"
10 #include "mozilla/FloatingPoint.h"
11 #include "mozilla/IntegerPrintfMacros.h"
13 #include <stdarg.h>
15 #include "jsnum.h"
17 using namespace js;
19 void JSONPrinter::indent() {
20 MOZ_ASSERT(indentLevel_ >= 0);
21 if (indent_) {
22 out_.putChar('\n');
23 for (int i = 0; i < indentLevel_; i++) {
24 out_.put(" ");
29 void JSONPrinter::propertyName(const char* name) {
30 if (!first_) {
31 out_.putChar(',');
33 indent();
34 out_.printf("\"%s\":", name);
35 if (indent_) {
36 out_.put(" ");
38 first_ = false;
41 void JSONPrinter::beginObject() {
42 if (!first_) {
43 out_.putChar(',');
45 indent();
46 out_.putChar('{');
47 indentLevel_++;
48 first_ = true;
51 void JSONPrinter::beginList() {
52 if (!first_) {
53 out_.putChar(',');
55 indent();
56 out_.putChar('[');
57 indentLevel_++;
58 first_ = true;
61 void JSONPrinter::beginObjectProperty(const char* name) {
62 propertyName(name);
63 out_.putChar('{');
64 indentLevel_++;
65 first_ = true;
68 void JSONPrinter::beginListProperty(const char* name) {
69 propertyName(name);
70 out_.putChar('[');
71 indentLevel_++;
72 first_ = true;
75 GenericPrinter& JSONPrinter::beginStringProperty(const char* name) {
76 propertyName(name);
77 out_.putChar('"');
78 return out_;
81 void JSONPrinter::endStringProperty() {
82 endString();
83 first_ = false;
86 GenericPrinter& JSONPrinter::beginString() {
87 if (!first_) {
88 out_.putChar(',');
90 indent();
91 out_.putChar('"');
92 return out_;
95 void JSONPrinter::endString() { out_.putChar('"'); }
97 void JSONPrinter::boolProperty(const char* name, bool value) {
98 propertyName(name);
99 out_.put(value ? "true" : "false");
102 template <typename CharT>
103 static void JSONString(GenericPrinter& out, const CharT* s, size_t length) {
104 const CharT* end = s + length;
105 for (const CharT* t = s; t < end; s = ++t) {
106 // This quote implementation is probably correct,
107 // but uses \u even when not strictly necessary.
108 char16_t c = *t;
109 if (c == '"' || c == '\\') {
110 out.printf("\\");
111 out.printf("%c", char(c));
112 } else if (!IsAsciiPrintable(c)) {
113 out.printf("\\u%04x", c);
114 } else {
115 out.printf("%c", char(c));
120 void JSONPrinter::property(const char* name, JSLinearString* str) {
121 JS::AutoCheckCannotGC nogc;
122 beginStringProperty(name);
124 // Limit the string length to reduce the JSON file size.
125 size_t length = std::min(str->length(), size_t(128));
126 if (str->hasLatin1Chars()) {
127 JSONString(out_, str->latin1Chars(nogc), length);
128 } else {
129 JSONString(out_, str->twoByteChars(nogc), length);
131 endStringProperty();
134 void JSONPrinter::property(const char* name, const char* value) {
135 beginStringProperty(name);
136 out_.put(value);
137 endStringProperty();
140 void JSONPrinter::formatProperty(const char* name, const char* format, ...) {
141 va_list ap;
142 va_start(ap, format);
144 beginStringProperty(name);
145 out_.vprintf(format, ap);
146 endStringProperty();
148 va_end(ap);
151 void JSONPrinter::formatProperty(const char* name, const char* format,
152 va_list ap) {
153 beginStringProperty(name);
154 out_.vprintf(format, ap);
155 endStringProperty();
158 void JSONPrinter::value(const char* format, ...) {
159 va_list ap;
160 va_start(ap, format);
162 if (!first_) {
163 out_.putChar(',');
165 indent();
166 out_.putChar('"');
167 out_.vprintf(format, ap);
168 out_.putChar('"');
170 va_end(ap);
171 first_ = false;
174 void JSONPrinter::property(const char* name, int32_t value) {
175 propertyName(name);
176 out_.printf("%" PRId32, value);
179 void JSONPrinter::value(int val) {
180 if (!first_) {
181 out_.putChar(',');
183 indent();
184 out_.printf("%d", val);
185 first_ = false;
188 void JSONPrinter::property(const char* name, uint32_t value) {
189 propertyName(name);
190 out_.printf("%" PRIu32, value);
193 void JSONPrinter::property(const char* name, int64_t value) {
194 propertyName(name);
195 out_.printf("%" PRId64, value);
198 void JSONPrinter::property(const char* name, uint64_t value) {
199 propertyName(name);
200 out_.printf("%" PRIu64, value);
203 #if defined(XP_DARWIN) || defined(__OpenBSD__) || defined(__wasi__)
204 void JSONPrinter::property(const char* name, size_t value) {
205 propertyName(name);
206 out_.printf("%zu", value);
208 #endif
210 void JSONPrinter::floatProperty(const char* name, double value,
211 size_t precision) {
212 if (!std::isfinite(value)) {
213 propertyName(name);
214 out_.put("null");
215 return;
218 ToCStringBuf cbuf;
219 const char* str = NumberToCString(&cbuf, value);
220 MOZ_ASSERT(str);
222 property(name, str);
225 void JSONPrinter::property(const char* name, const mozilla::TimeDuration& dur,
226 TimePrecision precision) {
227 if (precision == MICROSECONDS) {
228 property(name, static_cast<int64_t>(dur.ToMicroseconds()));
229 return;
232 propertyName(name);
233 lldiv_t split;
234 switch (precision) {
235 case SECONDS:
236 split = lldiv(static_cast<int64_t>(dur.ToMilliseconds()), 1000);
237 break;
238 case MILLISECONDS:
239 split = lldiv(static_cast<int64_t>(dur.ToMicroseconds()), 1000);
240 break;
241 case MICROSECONDS:
242 MOZ_ASSERT_UNREACHABLE("");
244 out_.printf("%lld.%03lld", split.quot, split.rem);
247 void JSONPrinter::nullProperty(const char* name) {
248 propertyName(name);
249 out_.put("null");
252 void JSONPrinter::nullValue() {
253 if (!first_) {
254 out_.putChar(',');
256 indent();
257 out_.put("null");
258 first_ = false;
261 void JSONPrinter::endObject() {
262 indentLevel_--;
263 indent();
264 out_.putChar('}');
265 first_ = false;
268 void JSONPrinter::endList() {
269 indentLevel_--;
270 indent();
271 out_.putChar(']');
272 first_ = false;