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