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 2292 : void EscapeAndAppendString(const char* value, std::string* result) {
28 : *result += '"';
29 : char number_buffer[10];
30 39962 : while (*value) {
31 37670 : char c = *value++;
32 37670 : switch (c) {
33 : case '\t':
34 : *result += "\\t";
35 : break;
36 : case '\n':
37 : *result += "\\n";
38 : break;
39 : case '\"':
40 : *result += "\\\"";
41 : break;
42 : case '\\':
43 : *result += "\\\\";
44 : break;
45 : default:
46 37610 : if (c < '\040') {
47 : base::OS::SNPrintF(
48 : number_buffer, arraysize(number_buffer), "\\u%04X",
49 180 : static_cast<unsigned>(static_cast<unsigned char>(c)));
50 : *result += number_buffer;
51 : } else {
52 : *result += c;
53 : }
54 : }
55 : }
56 : *result += '"';
57 2292 : }
58 :
59 : } // namespace
60 :
61 1476 : std::unique_ptr<TracedValue> TracedValue::Create() {
62 2952 : return std::unique_ptr<TracedValue>(new TracedValue());
63 : }
64 :
65 2952 : TracedValue::TracedValue() : first_item_(true) {
66 : DEBUG_PUSH_CONTAINER(kStackTypeDict);
67 0 : }
68 :
69 1476 : TracedValue::~TracedValue() {
70 : DCHECK_CURRENT_CONTAINER_IS(kStackTypeDict);
71 : DEBUG_POP_CONTAINER();
72 : DCHECK_CONTAINER_STACK_DEPTH_EQ(0u);
73 1476 : }
74 :
75 6702 : void TracedValue::SetInteger(const char* name, int value) {
76 : DCHECK_CURRENT_CONTAINER_IS(kStackTypeDict);
77 6702 : WriteName(name);
78 13404 : data_ += std::to_string(value);
79 6702 : }
80 :
81 1164 : void TracedValue::SetDouble(const char* name, double value) {
82 : DCHECK_CURRENT_CONTAINER_IS(kStackTypeDict);
83 1164 : WriteName(name);
84 : i::EmbeddedVector<char, 100> buffer;
85 1164 : data_ += DoubleToCString(value, buffer);
86 1164 : }
87 :
88 24 : void TracedValue::SetBoolean(const char* name, bool value) {
89 : DCHECK_CURRENT_CONTAINER_IS(kStackTypeDict);
90 24 : WriteName(name);
91 24 : data_ += value ? "true" : "false";
92 24 : }
93 :
94 2280 : void TracedValue::SetString(const char* name, const char* value) {
95 : DCHECK_CURRENT_CONTAINER_IS(kStackTypeDict);
96 2280 : WriteName(name);
97 2280 : EscapeAndAppendString(value, &data_);
98 2280 : }
99 :
100 2421 : void TracedValue::BeginDictionary(const char* name) {
101 : DCHECK_CURRENT_CONTAINER_IS(kStackTypeDict);
102 : DEBUG_PUSH_CONTAINER(kStackTypeDict);
103 2421 : WriteName(name);
104 2421 : data_ += '{';
105 2421 : first_item_ = true;
106 2421 : }
107 :
108 503 : void TracedValue::BeginArray(const char* name) {
109 : DCHECK_CURRENT_CONTAINER_IS(kStackTypeDict);
110 : DEBUG_PUSH_CONTAINER(kStackTypeArray);
111 503 : WriteName(name);
112 503 : data_ += '[';
113 503 : first_item_ = true;
114 503 : }
115 :
116 16090 : void TracedValue::AppendInteger(int value) {
117 : DCHECK_CURRENT_CONTAINER_IS(kStackTypeArray);
118 : WriteComma();
119 32180 : data_ += std::to_string(value);
120 16090 : }
121 :
122 0 : void TracedValue::AppendDouble(double value) {
123 : DCHECK_CURRENT_CONTAINER_IS(kStackTypeArray);
124 : WriteComma();
125 : i::EmbeddedVector<char, 100> buffer;
126 0 : data_ += DoubleToCString(value, buffer);
127 0 : }
128 :
129 6 : void TracedValue::AppendBoolean(bool value) {
130 : DCHECK_CURRENT_CONTAINER_IS(kStackTypeArray);
131 : WriteComma();
132 6 : data_ += value ? "true" : "false";
133 6 : }
134 :
135 12 : void TracedValue::AppendString(const char* value) {
136 : DCHECK_CURRENT_CONTAINER_IS(kStackTypeArray);
137 : WriteComma();
138 12 : EscapeAndAppendString(value, &data_);
139 12 : }
140 :
141 2127 : void TracedValue::BeginDictionary() {
142 : DCHECK_CURRENT_CONTAINER_IS(kStackTypeArray);
143 : DEBUG_PUSH_CONTAINER(kStackTypeDict);
144 : WriteComma();
145 2127 : data_ += '{';
146 2127 : first_item_ = true;
147 2127 : }
148 :
149 6 : void TracedValue::BeginArray() {
150 : DCHECK_CURRENT_CONTAINER_IS(kStackTypeArray);
151 : DEBUG_PUSH_CONTAINER(kStackTypeArray);
152 : WriteComma();
153 6 : data_ += '[';
154 6 : first_item_ = true;
155 6 : }
156 :
157 4548 : void TracedValue::EndDictionary() {
158 : DCHECK_CURRENT_CONTAINER_IS(kStackTypeDict);
159 : DEBUG_POP_CONTAINER();
160 4548 : data_ += '}';
161 4548 : first_item_ = false;
162 4548 : }
163 :
164 509 : void TracedValue::EndArray() {
165 : DCHECK_CURRENT_CONTAINER_IS(kStackTypeArray);
166 : DEBUG_POP_CONTAINER();
167 509 : data_ += ']';
168 509 : first_item_ = false;
169 509 : }
170 :
171 0 : void TracedValue::WriteComma() {
172 31335 : if (first_item_) {
173 6515 : first_item_ = false;
174 : } else {
175 24820 : data_ += ',';
176 : }
177 0 : }
178 :
179 13094 : void TracedValue::WriteName(const char* name) {
180 : WriteComma();
181 13094 : data_ += '"';
182 : data_ += name;
183 : data_ += "\":";
184 13094 : }
185 :
186 35 : void TracedValue::AppendAsTraceFormat(std::string* out) const {
187 : *out += '{';
188 35 : *out += data_;
189 : *out += '}';
190 35 : }
191 :
192 : } // namespace tracing
193 : } // namespace v8
|