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