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