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"
19 void JSONPrinter::indent() {
20 MOZ_ASSERT(indentLevel_
>= 0);
23 for (int i
= 0; i
< indentLevel_
; i
++) {
29 void JSONPrinter::propertyName(const char* name
) {
34 out_
.printf("\"%s\":", name
);
41 void JSONPrinter::beginObject() {
51 void JSONPrinter::beginList() {
61 void JSONPrinter::beginObjectProperty(const char* name
) {
68 void JSONPrinter::beginListProperty(const char* name
) {
75 GenericPrinter
& JSONPrinter::beginStringProperty(const char* name
) {
81 void JSONPrinter::endStringProperty() {
86 GenericPrinter
& JSONPrinter::beginString() {
95 void JSONPrinter::endString() { out_
.putChar('"'); }
97 void JSONPrinter::boolProperty(const char* name
, bool value
) {
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.
109 if (c
== '"' || c
== '\\') {
111 out
.printf("%c", char(c
));
112 } else if (!IsAsciiPrintable(c
)) {
113 out
.printf("\\u%04x", c
);
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
);
129 JSONString(out_
, str
->twoByteChars(nogc
), length
);
134 void JSONPrinter::property(const char* name
, const char* value
) {
135 beginStringProperty(name
);
140 void JSONPrinter::formatProperty(const char* name
, const char* format
, ...) {
142 va_start(ap
, format
);
144 beginStringProperty(name
);
145 out_
.vprintf(format
, ap
);
151 void JSONPrinter::formatProperty(const char* name
, const char* format
,
153 beginStringProperty(name
);
154 out_
.vprintf(format
, ap
);
158 void JSONPrinter::value(const char* format
, ...) {
160 va_start(ap
, format
);
167 out_
.vprintf(format
, ap
);
174 void JSONPrinter::property(const char* name
, int32_t value
) {
176 out_
.printf("%" PRId32
, value
);
179 void JSONPrinter::value(int val
) {
184 out_
.printf("%d", val
);
188 void JSONPrinter::property(const char* name
, uint32_t value
) {
190 out_
.printf("%" PRIu32
, value
);
193 void JSONPrinter::property(const char* name
, int64_t value
) {
195 out_
.printf("%" PRId64
, value
);
198 void JSONPrinter::property(const char* name
, uint64_t value
) {
200 out_
.printf("%" PRIu64
, value
);
203 #if defined(XP_DARWIN) || defined(__OpenBSD__) || defined(__wasi__)
204 void JSONPrinter::property(const char* name
, size_t value
) {
206 out_
.printf("%zu", value
);
210 void JSONPrinter::floatProperty(const char* name
, double value
,
212 if (!std::isfinite(value
)) {
219 const char* str
= NumberToCString(&cbuf
, value
);
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()));
236 split
= lldiv(static_cast<int64_t>(dur
.ToMilliseconds()), 1000);
239 split
= lldiv(static_cast<int64_t>(dur
.ToMicroseconds()), 1000);
242 MOZ_ASSERT_UNREACHABLE("");
244 out_
.printf("%lld.%03lld", split
.quot
, split
.rem
);
247 void JSONPrinter::nullProperty(const char* name
) {
252 void JSONPrinter::nullValue() {
261 void JSONPrinter::endObject() {
268 void JSONPrinter::endList() {