OLD | NEW |
---|---|
(Empty) | |
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 | |
9 namespace v8 { | |
10 namespace tracing { | |
11 | |
12 namespace { | |
13 | |
14 #define DCHECK_CURRENT_CONTAINER_IS(x) DCHECK_EQ(x, nesting_stack_.back()) | |
15 #define DCHECK_CONTAINER_STACK_DEPTH_EQ(x) DCHECK_EQ(x, nesting_stack_.size()) | |
16 #ifdef DEBUG | |
17 const bool kStackTypeDict = false; | |
18 const bool kStackTypeArray = true; | |
19 #define DEBUG_PUSH_CONTAINER(x) nesting_stack_.push_back(x) | |
20 #define DEBUG_POP_CONTAINER() nesting_stack_.pop_back() | |
21 #else | |
22 #define DEBUG_PUSH_CONTAINER(x) ((void)0) | |
23 #define DEBUG_POP_CONTAINER() ((void)0) | |
24 #endif | |
25 | |
26 std::string EscapeString(const std::string& value) { | |
27 std::string result("\""); | |
Primiano Tucci (use gerrit)
2016/10/05 19:50:48
maybe you can reserve(length+2) to optimistically
alph
2016/10/06 00:03:10
Done.
| |
28 size_t length = value.length(); | |
29 char number_buffer[10]; | |
30 for (size_t src = 0; src < length; ++src) { | |
31 unsigned char c = value[src]; | |
Primiano Tucci (use gerrit)
2016/10/05 19:50:48
why unsigned, operator[] is signed IIRC.
alph
2016/10/06 00:03:10
Done.
| |
32 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 if (c < '\040') { | |
47 base::OS::SNPrintF(number_buffer, arraysize(number_buffer), "\\u%04X", | |
48 static_cast<unsigned>(c)); | |
49 result += number_buffer; | |
50 } else { | |
51 result += c; | |
52 } | |
53 } | |
54 } | |
55 result += '"'; | |
56 return result; | |
57 } | |
58 | |
59 } // namespace | |
60 | |
61 std::unique_ptr<TracedValue> TracedValue::Create() { | |
62 return std::unique_ptr<TracedValue>(new TracedValue()); | |
63 } | |
64 | |
65 TracedValue::TracedValue() : first_item_(true) { | |
66 DEBUG_PUSH_CONTAINER(kStackTypeDict); | |
67 } | |
68 | |
69 TracedValue::~TracedValue() { | |
70 DCHECK_CURRENT_CONTAINER_IS(kStackTypeDict); | |
71 DEBUG_POP_CONTAINER(); | |
72 DCHECK_CONTAINER_STACK_DEPTH_EQ(0u); | |
73 } | |
74 | |
75 void TracedValue::SetInteger(const char* name, int value) { | |
76 DCHECK_CURRENT_CONTAINER_IS(kStackTypeDict); | |
77 WriteName(name); | |
78 data_ += std::to_string(value); | |
79 } | |
80 | |
81 void TracedValue::SetDouble(const char* name, double value) { | |
82 DCHECK_CURRENT_CONTAINER_IS(kStackTypeDict); | |
83 WriteName(name); | |
84 data_ += std::to_string(value); | |
85 } | |
86 | |
87 void TracedValue::SetBoolean(const char* name, bool value) { | |
88 DCHECK_CURRENT_CONTAINER_IS(kStackTypeDict); | |
89 WriteName(name); | |
90 data_ += value ? "true" : "false"; | |
91 } | |
92 | |
93 void TracedValue::SetString(const char* name, const std::string& value) { | |
94 DCHECK_CURRENT_CONTAINER_IS(kStackTypeDict); | |
95 WriteName(name); | |
96 data_ += EscapeString(value); | |
97 } | |
98 | |
99 void TracedValue::BeginDictionary(const char* name) { | |
100 DCHECK_CURRENT_CONTAINER_IS(kStackTypeDict); | |
101 DEBUG_PUSH_CONTAINER(kStackTypeDict); | |
102 WriteName(name); | |
103 data_ += '{'; | |
104 first_item_ = true; | |
105 } | |
106 | |
107 void TracedValue::BeginArray(const char* name) { | |
108 DCHECK_CURRENT_CONTAINER_IS(kStackTypeDict); | |
109 DEBUG_PUSH_CONTAINER(kStackTypeArray); | |
110 WriteName(name); | |
111 data_ += '['; | |
112 first_item_ = true; | |
113 } | |
114 | |
115 void TracedValue::AppendInteger(int value) { | |
116 DCHECK_CURRENT_CONTAINER_IS(kStackTypeArray); | |
117 WriteComma(); | |
118 data_ += std::to_string(value); | |
119 } | |
120 | |
121 void TracedValue::AppendDouble(double value) { | |
122 DCHECK_CURRENT_CONTAINER_IS(kStackTypeArray); | |
123 WriteComma(); | |
124 data_ += std::to_string(value); | |
125 } | |
126 | |
127 void TracedValue::AppendBoolean(bool value) { | |
128 DCHECK_CURRENT_CONTAINER_IS(kStackTypeArray); | |
129 WriteComma(); | |
130 data_ += value ? "true" : "false"; | |
131 } | |
132 | |
133 void TracedValue::AppendString(const std::string& value) { | |
134 DCHECK_CURRENT_CONTAINER_IS(kStackTypeArray); | |
135 WriteComma(); | |
136 data_ += EscapeString(value); | |
137 } | |
138 | |
139 void TracedValue::BeginDictionary() { | |
140 DCHECK_CURRENT_CONTAINER_IS(kStackTypeArray); | |
141 DEBUG_PUSH_CONTAINER(kStackTypeDict); | |
142 WriteComma(); | |
143 data_ += '{'; | |
144 first_item_ = true; | |
145 } | |
146 | |
147 void TracedValue::BeginArray() { | |
148 DCHECK_CURRENT_CONTAINER_IS(kStackTypeArray); | |
149 DEBUG_PUSH_CONTAINER(kStackTypeArray); | |
150 WriteComma(); | |
151 data_ += '['; | |
152 first_item_ = true; | |
153 } | |
154 | |
155 void TracedValue::EndDictionary() { | |
156 DCHECK_CURRENT_CONTAINER_IS(kStackTypeDict); | |
157 DEBUG_POP_CONTAINER(); | |
158 data_ += '}'; | |
159 first_item_ = false; | |
160 } | |
161 | |
162 void TracedValue::EndArray() { | |
163 DCHECK_CURRENT_CONTAINER_IS(kStackTypeArray); | |
164 DEBUG_POP_CONTAINER(); | |
165 data_ += ']'; | |
166 first_item_ = false; | |
167 } | |
168 | |
169 void TracedValue::WriteComma() { | |
170 if (first_item_) { | |
171 first_item_ = false; | |
172 } else { | |
173 data_ += ','; | |
174 } | |
175 } | |
176 | |
177 void TracedValue::WriteName(const char* name) { | |
178 WriteComma(); | |
179 data_ += '"'; | |
180 data_ += name; | |
181 data_ += "\":"; | |
182 } | |
183 | |
184 void TracedValue::AppendAsTraceFormat(std::string* out) const { | |
185 *out += '{'; | |
186 *out += data_; | |
187 *out += '}'; | |
188 } | |
189 | |
190 } // namespace tracing | |
191 } // namespace v8 | |
OLD | NEW |