Home | History | Annotate | Download | only in tracing
      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 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 
     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   i::EmbeddedVector<char, 100> buffer;
     85   data_ += DoubleToCString(value, buffer);
     86 }
     87 
     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 
     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 
    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 
    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 
    116 void TracedValue::AppendInteger(int value) {
    117   DCHECK_CURRENT_CONTAINER_IS(kStackTypeArray);
    118   WriteComma();
    119   data_ += std::to_string(value);
    120 }
    121 
    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 
    129 void TracedValue::AppendBoolean(bool value) {
    130   DCHECK_CURRENT_CONTAINER_IS(kStackTypeArray);
    131   WriteComma();
    132   data_ += value ? "true" : "false";
    133 }
    134 
    135 void TracedValue::AppendString(const char* value) {
    136   DCHECK_CURRENT_CONTAINER_IS(kStackTypeArray);
    137   WriteComma();
    138   EscapeAndAppendString(value, &data_);
    139 }
    140 
    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 
    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 
    157 void TracedValue::EndDictionary() {
    158   DCHECK_CURRENT_CONTAINER_IS(kStackTypeDict);
    159   DEBUG_POP_CONTAINER();
    160   data_ += '}';
    161   first_item_ = false;
    162 }
    163 
    164 void TracedValue::EndArray() {
    165   DCHECK_CURRENT_CONTAINER_IS(kStackTypeArray);
    166   DEBUG_POP_CONTAINER();
    167   data_ += ']';
    168   first_item_ = false;
    169 }
    170 
    171 void TracedValue::WriteComma() {
    172   if (first_item_) {
    173     first_item_ = false;
    174   } else {
    175     data_ += ',';
    176   }
    177 }
    178 
    179 void TracedValue::WriteName(const char* name) {
    180   WriteComma();
    181   data_ += '"';
    182   data_ += name;
    183   data_ += "\":";
    184 }
    185 
    186 void TracedValue::AppendAsTraceFormat(std::string* out) const {
    187   *out += '{';
    188   *out += data_;
    189   *out += '}';
    190 }
    191 
    192 }  // namespace tracing
    193 }  // namespace v8
    194