Line data Source code
1 : // Copyright 2016 the V8 project authors. All rights reserved.
2 : // Use of this source code is governed by a BSD-style license that can be
3 : // found in the LICENSE file.
4 :
5 : #include "src/tracing/traced-value.h"
6 :
7 : #include "src/base/platform/platform.h"
8 : #include "src/conversions.h"
9 :
10 : namespace v8 {
11 : namespace tracing {
12 :
13 : namespace {
14 :
15 : #define DCHECK_CURRENT_CONTAINER_IS(x) DCHECK_EQ(x, nesting_stack_.back())
16 : #define DCHECK_CONTAINER_STACK_DEPTH_EQ(x) DCHECK_EQ(x, nesting_stack_.size())
17 : #ifdef DEBUG
18 : const bool kStackTypeDict = false;
19 : const bool kStackTypeArray = true;
20 : #define DEBUG_PUSH_CONTAINER(x) nesting_stack_.push_back(x)
21 : #define DEBUG_POP_CONTAINER() nesting_stack_.pop_back()
22 : #else
23 : #define DEBUG_PUSH_CONTAINER(x) ((void)0)
24 : #define DEBUG_POP_CONTAINER() ((void)0)
25 : #endif
26 :
27 3235 : void EscapeAndAppendString(const char* value, std::string* result) {
28 : *result += '"';
29 44091 : while (*value) {
30 40856 : unsigned char c = *value++;
31 40856 : switch (c) {
32 : case '\b':
33 : *result += "\\b";
34 : break;
35 : case '\f':
36 : *result += "\\f";
37 : break;
38 : case '\n':
39 : *result += "\\n";
40 : break;
41 : case '\r':
42 : *result += "\\r";
43 : break;
44 : case '\t':
45 : *result += "\\t";
46 : break;
47 : case '\"':
48 : *result += "\\\"";
49 : break;
50 : case '\\':
51 : *result += "\\\\";
52 : break;
53 : default:
54 40791 : if (c < '\x20' || c == '\x7F') {
55 : char number_buffer[8];
56 : base::OS::SNPrintF(number_buffer, arraysize(number_buffer), "\\u%04X",
57 140 : static_cast<unsigned>(c));
58 : *result += number_buffer;
59 : } else {
60 : *result += c;
61 : }
62 : }
63 : }
64 : *result += '"';
65 3235 : }
66 :
67 : } // namespace
68 :
69 2824 : std::unique_ptr<TracedValue> TracedValue::Create() {
70 5648 : return std::unique_ptr<TracedValue>(new TracedValue());
71 : }
72 :
73 5648 : TracedValue::TracedValue() : first_item_(true) {
74 : DEBUG_PUSH_CONTAINER(kStackTypeDict);
75 0 : }
76 :
77 2824 : TracedValue::~TracedValue() {
78 : DCHECK_CURRENT_CONTAINER_IS(kStackTypeDict);
79 : DEBUG_POP_CONTAINER();
80 : DCHECK_CONTAINER_STACK_DEPTH_EQ(0u);
81 2824 : }
82 :
83 8923 : void TracedValue::SetInteger(const char* name, int value) {
84 : DCHECK_CURRENT_CONTAINER_IS(kStackTypeDict);
85 8923 : WriteName(name);
86 17846 : data_ += std::to_string(value);
87 8923 : }
88 :
89 2071 : void TracedValue::SetDouble(const char* name, double value) {
90 : DCHECK_CURRENT_CONTAINER_IS(kStackTypeDict);
91 2071 : WriteName(name);
92 : i::EmbeddedVector<char, 100> buffer;
93 2071 : data_ += DoubleToCString(value, buffer);
94 2071 : }
95 :
96 20 : void TracedValue::SetBoolean(const char* name, bool value) {
97 : DCHECK_CURRENT_CONTAINER_IS(kStackTypeDict);
98 20 : WriteName(name);
99 20 : data_ += value ? "true" : "false";
100 20 : }
101 :
102 3225 : void TracedValue::SetString(const char* name, const char* value) {
103 : DCHECK_CURRENT_CONTAINER_IS(kStackTypeDict);
104 3225 : WriteName(name);
105 3225 : EscapeAndAppendString(value, &data_);
106 3225 : }
107 :
108 3789 : void TracedValue::BeginDictionary(const char* name) {
109 : DCHECK_CURRENT_CONTAINER_IS(kStackTypeDict);
110 : DEBUG_PUSH_CONTAINER(kStackTypeDict);
111 3789 : WriteName(name);
112 3789 : data_ += '{';
113 3789 : first_item_ = true;
114 3789 : }
115 :
116 835 : void TracedValue::BeginArray(const char* name) {
117 : DCHECK_CURRENT_CONTAINER_IS(kStackTypeDict);
118 : DEBUG_PUSH_CONTAINER(kStackTypeArray);
119 835 : WriteName(name);
120 835 : data_ += '[';
121 835 : first_item_ = true;
122 835 : }
123 :
124 141 : void TracedValue::AppendInteger(int value) {
125 : DCHECK_CURRENT_CONTAINER_IS(kStackTypeArray);
126 : WriteComma();
127 282 : data_ += std::to_string(value);
128 141 : }
129 :
130 0 : void TracedValue::AppendDouble(double value) {
131 : DCHECK_CURRENT_CONTAINER_IS(kStackTypeArray);
132 : WriteComma();
133 : i::EmbeddedVector<char, 100> buffer;
134 0 : data_ += DoubleToCString(value, buffer);
135 0 : }
136 :
137 5 : void TracedValue::AppendBoolean(bool value) {
138 : DCHECK_CURRENT_CONTAINER_IS(kStackTypeArray);
139 : WriteComma();
140 5 : data_ += value ? "true" : "false";
141 5 : }
142 :
143 10 : void TracedValue::AppendString(const char* value) {
144 : DCHECK_CURRENT_CONTAINER_IS(kStackTypeArray);
145 : WriteComma();
146 10 : EscapeAndAppendString(value, &data_);
147 10 : }
148 :
149 3061 : void TracedValue::BeginDictionary() {
150 : DCHECK_CURRENT_CONTAINER_IS(kStackTypeArray);
151 : DEBUG_PUSH_CONTAINER(kStackTypeDict);
152 : WriteComma();
153 3061 : data_ += '{';
154 3061 : first_item_ = true;
155 3061 : }
156 :
157 5 : void TracedValue::BeginArray() {
158 : DCHECK_CURRENT_CONTAINER_IS(kStackTypeArray);
159 : DEBUG_PUSH_CONTAINER(kStackTypeArray);
160 : WriteComma();
161 5 : data_ += '[';
162 5 : first_item_ = true;
163 5 : }
164 :
165 6850 : void TracedValue::EndDictionary() {
166 : DCHECK_CURRENT_CONTAINER_IS(kStackTypeDict);
167 : DEBUG_POP_CONTAINER();
168 6850 : data_ += '}';
169 6850 : first_item_ = false;
170 6850 : }
171 :
172 840 : void TracedValue::EndArray() {
173 : DCHECK_CURRENT_CONTAINER_IS(kStackTypeArray);
174 : DEBUG_POP_CONTAINER();
175 840 : data_ += ']';
176 840 : first_item_ = false;
177 840 : }
178 :
179 0 : void TracedValue::WriteComma() {
180 22085 : if (first_item_) {
181 10494 : first_item_ = false;
182 : } else {
183 11591 : data_ += ',';
184 : }
185 0 : }
186 :
187 18863 : void TracedValue::WriteName(const char* name) {
188 : WriteComma();
189 18863 : data_ += '"';
190 : data_ += name;
191 : data_ += "\":";
192 18863 : }
193 :
194 35 : void TracedValue::AppendAsTraceFormat(std::string* out) const {
195 : *out += '{';
196 35 : *out += data_;
197 : *out += '}';
198 35 : }
199 :
200 : } // namespace tracing
201 183867 : } // namespace v8
|