Line data Source code
1 : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2 : * vim: set ts=8 sts=4 et sw=4 tw=99:
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/FloatingPoint.h"
11 : #include "mozilla/IntegerPrintfMacros.h"
12 : #include "mozilla/SizePrintfMacros.h"
13 :
14 : #include <stdarg.h>
15 :
16 : #include "jsdtoa.h"
17 :
18 : using namespace js;
19 :
20 338 : JSONPrinter::~JSONPrinter()
21 : {
22 169 : if (dtoaState_)
23 0 : DestroyDtoaState(dtoaState_);
24 169 : }
25 :
26 : void
27 0 : JSONPrinter::indent()
28 : {
29 0 : MOZ_ASSERT(indentLevel_ >= 0);
30 0 : out_.printf("\n");
31 0 : for (int i = 0; i < indentLevel_; i++)
32 0 : out_.printf(" ");
33 0 : }
34 :
35 : void
36 0 : JSONPrinter::propertyName(const char* name)
37 : {
38 0 : if (!first_)
39 0 : out_.printf(",");
40 0 : indent();
41 0 : out_.printf("\"%s\":", name);
42 0 : first_ = false;
43 0 : }
44 :
45 : void
46 0 : JSONPrinter::beginObject()
47 : {
48 0 : if (!first_) {
49 0 : out_.printf(",");
50 0 : indent();
51 : }
52 0 : out_.printf("{");
53 0 : indentLevel_++;
54 0 : first_ = true;
55 0 : }
56 :
57 : void
58 0 : JSONPrinter::beginObjectProperty(const char* name)
59 : {
60 0 : propertyName(name);
61 0 : out_.printf("{");
62 0 : indentLevel_++;
63 0 : first_ = true;
64 0 : }
65 :
66 : void
67 0 : JSONPrinter::beginListProperty(const char* name)
68 : {
69 0 : propertyName(name);
70 0 : out_.printf("[");
71 0 : first_ = true;
72 0 : }
73 :
74 : void
75 0 : JSONPrinter::beginStringProperty(const char* name)
76 : {
77 0 : propertyName(name);
78 0 : out_.printf("\"");
79 0 : }
80 :
81 : void
82 0 : JSONPrinter::endStringProperty()
83 : {
84 0 : out_.printf("\"");
85 0 : }
86 :
87 : void
88 0 : JSONPrinter::property(const char* name, const char* value)
89 : {
90 0 : beginStringProperty(name);
91 0 : out_.put(value);
92 0 : endStringProperty();
93 0 : }
94 :
95 : void
96 0 : JSONPrinter::formatProperty(const char* name, const char* format, ...)
97 : {
98 : va_list ap;
99 0 : va_start(ap, format);
100 :
101 0 : beginStringProperty(name);
102 0 : out_.vprintf(format, ap);
103 0 : endStringProperty();
104 :
105 0 : va_end(ap);
106 0 : }
107 :
108 : void
109 0 : JSONPrinter::value(const char* format, ...)
110 : {
111 : va_list ap;
112 0 : va_start(ap, format);
113 :
114 0 : if (!first_)
115 0 : out_.printf(",");
116 0 : out_.printf("\"");
117 0 : out_.vprintf(format, ap);
118 0 : out_.printf("\"");
119 :
120 0 : va_end(ap);
121 0 : first_ = false;
122 0 : }
123 :
124 : void
125 0 : JSONPrinter::property(const char* name, int32_t value)
126 : {
127 0 : propertyName(name);
128 0 : out_.printf("%" PRId32, value);
129 0 : }
130 :
131 : void
132 0 : JSONPrinter::value(int val)
133 : {
134 0 : if (!first_)
135 0 : out_.printf(",");
136 0 : out_.printf("%d", val);
137 0 : first_ = false;
138 0 : }
139 :
140 : void
141 0 : JSONPrinter::property(const char* name, uint32_t value)
142 : {
143 0 : propertyName(name);
144 0 : out_.printf("%" PRIu32, value);
145 0 : }
146 :
147 : void
148 0 : JSONPrinter::property(const char* name, int64_t value)
149 : {
150 0 : propertyName(name);
151 0 : out_.printf("%" PRId64, value);
152 0 : }
153 :
154 : void
155 0 : JSONPrinter::property(const char* name, uint64_t value)
156 : {
157 0 : propertyName(name);
158 0 : out_.printf("%" PRIu64, value);
159 0 : }
160 :
161 : #if defined(XP_DARWIN) || defined(__OpenBSD__)
162 : void
163 : JSONPrinter::property(const char* name, size_t value)
164 : {
165 : propertyName(name);
166 : out_.printf("%" PRIuSIZE, value);
167 : }
168 : #endif
169 :
170 : void
171 0 : JSONPrinter::floatProperty(const char* name, double value, size_t precision)
172 : {
173 0 : if (!mozilla::IsFinite(value)) {
174 0 : propertyName(name);
175 0 : out_.printf("null");
176 0 : return;
177 : }
178 :
179 0 : if (!dtoaState_) {
180 0 : dtoaState_ = NewDtoaState();
181 0 : if (!dtoaState_) {
182 0 : out_.reportOutOfMemory();
183 0 : return;
184 : }
185 : }
186 :
187 : char buffer[DTOSTR_STANDARD_BUFFER_SIZE];
188 0 : char* str = js_dtostr(dtoaState_, buffer, sizeof(buffer), DTOSTR_STANDARD, precision, value);
189 0 : if (!str) {
190 0 : out_.reportOutOfMemory();
191 0 : return;
192 : }
193 :
194 0 : property(name, str);
195 : }
196 :
197 : void
198 0 : JSONPrinter::property(const char* name, const mozilla::TimeDuration& dur, TimePrecision precision)
199 : {
200 0 : if (precision == MICROSECONDS) {
201 0 : property(name, static_cast<int64_t>(dur.ToMicroseconds()));
202 0 : return;
203 : }
204 :
205 0 : propertyName(name);
206 : lldiv_t split;
207 0 : switch (precision) {
208 : case SECONDS:
209 0 : split = lldiv(static_cast<int64_t>(dur.ToMilliseconds()), 1000);
210 0 : break;
211 : case MILLISECONDS:
212 0 : split = lldiv(static_cast<int64_t>(dur.ToMicroseconds()), 1000);
213 0 : break;
214 : case MICROSECONDS:
215 0 : MOZ_ASSERT_UNREACHABLE("");
216 : };
217 0 : out_.printf("%llu.%03llu", split.quot, split.rem);
218 : }
219 :
220 : void
221 0 : JSONPrinter::endObject()
222 : {
223 0 : indentLevel_--;
224 0 : indent();
225 0 : out_.printf("}");
226 0 : first_ = false;
227 0 : }
228 :
229 : void
230 0 : JSONPrinter::endList()
231 : {
232 0 : out_.printf("]");
233 0 : first_ = false;
234 0 : }
|