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 2873 : void EscapeAndAppendString(const char* value, std::string* result) {
28 : *result += '"';
29 : char number_buffer[10];
30 49265 : while (*value) {
31 46392 : char c = *value++;
32 46392 : 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 46322 : if (c < '\040') {
47 : base::OS::SNPrintF(
48 : number_buffer, arraysize(number_buffer), "\\u%04X",
49 210 : static_cast<unsigned>(static_cast<unsigned char>(c)));
50 : *result += number_buffer;
51 : } else {
52 : *result += c;
53 : }
54 : }
55 : }
56 : *result += '"';
57 2873 : }
58 :
59 : } // namespace
60 :
61 1747 : std::unique_ptr<TracedValue> TracedValue::Create() {
62 3494 : return std::unique_ptr<TracedValue>(new TracedValue());
63 : }
64 :
65 3494 : TracedValue::TracedValue() : first_item_(true) {
66 : DEBUG_PUSH_CONTAINER(kStackTypeDict);
67 0 : }
68 :
69 1747 : TracedValue::~TracedValue() {
70 : DCHECK_CURRENT_CONTAINER_IS(kStackTypeDict);
71 : DEBUG_POP_CONTAINER();
72 : DCHECK_CONTAINER_STACK_DEPTH_EQ(0u);
73 1747 : }
74 :
75 8397 : void TracedValue::SetInteger(const char* name, int value) {
76 : DCHECK_CURRENT_CONTAINER_IS(kStackTypeDict);
77 8397 : WriteName(name);
78 16794 : data_ += std::to_string(value);
79 8397 : }
80 :
81 1374 : void TracedValue::SetDouble(const char* name, double value) {
82 : DCHECK_CURRENT_CONTAINER_IS(kStackTypeDict);
83 1374 : WriteName(name);
84 : i::EmbeddedVector<char, 100> buffer;
85 1374 : data_ += DoubleToCString(value, buffer);
86 1374 : }
87 :
88 28 : void TracedValue::SetBoolean(const char* name, bool value) {
89 : DCHECK_CURRENT_CONTAINER_IS(kStackTypeDict);
90 28 : WriteName(name);
91 28 : data_ += value ? "true" : "false";
92 28 : }
93 :
94 2859 : void TracedValue::SetString(const char* name, const char* value) {
95 : DCHECK_CURRENT_CONTAINER_IS(kStackTypeDict);
96 2859 : WriteName(name);
97 2859 : EscapeAndAppendString(value, &data_);
98 2859 : }
99 :
100 3004 : void TracedValue::BeginDictionary(const char* name) {
101 : DCHECK_CURRENT_CONTAINER_IS(kStackTypeDict);
102 : DEBUG_PUSH_CONTAINER(kStackTypeDict);
103 3004 : WriteName(name);
104 3004 : data_ += '{';
105 3004 : first_item_ = true;
106 3004 : }
107 :
108 597 : void TracedValue::BeginArray(const char* name) {
109 : DCHECK_CURRENT_CONTAINER_IS(kStackTypeDict);
110 : DEBUG_PUSH_CONTAINER(kStackTypeArray);
111 597 : WriteName(name);
112 597 : data_ += '[';
113 597 : first_item_ = true;
114 597 : }
115 :
116 18491 : void TracedValue::AppendInteger(int value) {
117 : DCHECK_CURRENT_CONTAINER_IS(kStackTypeArray);
118 : WriteComma();
119 36982 : data_ += std::to_string(value);
120 18491 : }
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 7 : void TracedValue::AppendBoolean(bool value) {
130 : DCHECK_CURRENT_CONTAINER_IS(kStackTypeArray);
131 : WriteComma();
132 7 : data_ += value ? "true" : "false";
133 7 : }
134 :
135 14 : void TracedValue::AppendString(const char* value) {
136 : DCHECK_CURRENT_CONTAINER_IS(kStackTypeArray);
137 : WriteComma();
138 14 : EscapeAndAppendString(value, &data_);
139 14 : }
140 :
141 2652 : void TracedValue::BeginDictionary() {
142 : DCHECK_CURRENT_CONTAINER_IS(kStackTypeArray);
143 : DEBUG_PUSH_CONTAINER(kStackTypeDict);
144 : WriteComma();
145 2652 : data_ += '{';
146 2652 : first_item_ = true;
147 2652 : }
148 :
149 7 : void TracedValue::BeginArray() {
150 : DCHECK_CURRENT_CONTAINER_IS(kStackTypeArray);
151 : DEBUG_PUSH_CONTAINER(kStackTypeArray);
152 : WriteComma();
153 7 : data_ += '[';
154 7 : first_item_ = true;
155 7 : }
156 :
157 5656 : void TracedValue::EndDictionary() {
158 : DCHECK_CURRENT_CONTAINER_IS(kStackTypeDict);
159 : DEBUG_POP_CONTAINER();
160 5656 : data_ += '}';
161 5656 : first_item_ = false;
162 5656 : }
163 :
164 604 : void TracedValue::EndArray() {
165 : DCHECK_CURRENT_CONTAINER_IS(kStackTypeArray);
166 : DEBUG_POP_CONTAINER();
167 604 : data_ += ']';
168 604 : first_item_ = false;
169 604 : }
170 :
171 0 : void TracedValue::WriteComma() {
172 37430 : if (first_item_) {
173 7986 : first_item_ = false;
174 : } else {
175 29444 : data_ += ',';
176 : }
177 0 : }
178 :
179 16259 : void TracedValue::WriteName(const char* name) {
180 : WriteComma();
181 16259 : data_ += '"';
182 : data_ += name;
183 : data_ += "\":";
184 16259 : }
185 :
186 41 : void TracedValue::AppendAsTraceFormat(std::string* out) const {
187 : *out += '{';
188 41 : *out += data_;
189 : *out += '}';
190 41 : }
191 :
192 : } // namespace tracing
193 : } // namespace v8
|