Index: base/trace_event/trace_event_argument.cc |
diff --git a/base/trace_event/trace_event_argument.cc b/base/trace_event/trace_event_argument.cc |
index 65965b1b286664c6d988e64bdef371cf2734c02d..c27a2f9ef3a6a6478199701ad5dfa2039ea82b49 100644 |
--- a/base/trace_event/trace_event_argument.cc |
+++ b/base/trace_event/trace_event_argument.cc |
@@ -6,11 +6,14 @@ |
#include <stdint.h> |
+#include <stack> |
#include <utility> |
#include "base/bits.h" |
-#include "base/json/json_writer.h" |
+#include "base/json/string_escape.h" |
#include "base/memory/ptr_util.h" |
+#include "base/trace_event/common/trace_event_common.h" |
+#include "base/trace_event/trace_event_impl.h" |
#include "base/trace_event/trace_event_memory_overhead.h" |
#include "base/values.h" |
@@ -26,7 +29,7 @@ const char kTypeBool = 'b'; |
const char kTypeInt = 'i'; |
const char kTypeDouble = 'd'; |
const char kTypeString = 's'; |
-const char kTypeCStr = '*'; |
+const char kTypeCStr = '*'; // only used for key names |
#ifndef NDEBUG |
const bool kStackTypeDict = false; |
@@ -454,12 +457,100 @@ void TracedValue::AppendAsTraceFormat(std::string* out) const { |
DCHECK_CURRENT_CONTAINER_IS(kStackTypeDict); |
DCHECK_CONTAINER_STACK_DEPTH_EQ(1u); |
- // TODO(primiano): this could be smarter, skip the ToBaseValue encoding and |
- // produce the JSON on its own. This will require refactoring JSONWriter |
- // to decouple the base::Value traversal from the JSON writing bits |
- std::string tmp; |
- JSONWriter::Write(*ToBaseValue(), &tmp); |
- *out += tmp; |
+ struct State { |
+ enum Type { kTypeDict, kTypeArray }; |
+ Type type; |
+ bool needs_comma; |
+ }; |
+ |
+ auto maybe_append_key_name = [](State current_state, PickleIterator* it, |
+ std::string* out) { |
+ if (current_state.type == State::kTypeDict) { |
+ EscapeJSONString(ReadKeyName(*it), true, out); |
+ out->append(":"); |
+ } |
+ }; |
+ |
+ std::stack<State> state_stack; |
+ |
+ out->append("{"); |
+ state_stack.push({State::kTypeDict}); |
+ |
+ PickleIterator it(pickle_); |
+ for (const char* type; it.ReadBytes(&type, 1);) { |
+ switch (*type) { |
+ case kTypeEndDict: |
+ out->append("}"); |
+ state_stack.pop(); |
+ continue; |
+ |
+ case kTypeEndArray: |
+ out->append("]"); |
+ state_stack.pop(); |
+ continue; |
+ } |
+ |
+ State& current_state = state_stack.top(); |
+ if (current_state.needs_comma) { |
+ out->append(","); |
+ } |
+ |
+ switch (*type) { |
+ case kTypeStartDict: |
+ maybe_append_key_name(current_state, &it, out); |
+ out->append("{"); |
+ state_stack.push({State::kTypeDict}); |
+ break; |
+ |
+ case kTypeStartArray: |
+ maybe_append_key_name(current_state, &it, out); |
+ out->append("["); |
+ state_stack.push({State::kTypeArray}); |
+ break; |
+ |
+ case kTypeBool: { |
+ TraceEvent::TraceValue json_value; |
+ CHECK(it.ReadBool(&json_value.as_bool)); |
+ maybe_append_key_name(current_state, &it, out); |
+ TraceEvent::AppendValueAsJSON(TRACE_VALUE_TYPE_BOOL, json_value, out); |
+ } break; |
+ |
+ case kTypeInt: { |
+ int value; |
+ CHECK(it.ReadInt(&value)); |
+ maybe_append_key_name(current_state, &it, out); |
+ TraceEvent::TraceValue json_value; |
+ json_value.as_int = value; |
+ TraceEvent::AppendValueAsJSON(TRACE_VALUE_TYPE_INT, json_value, out); |
+ } break; |
+ |
+ case kTypeDouble: { |
+ TraceEvent::TraceValue json_value; |
+ CHECK(it.ReadDouble(&json_value.as_double)); |
+ maybe_append_key_name(current_state, &it, out); |
+ TraceEvent::AppendValueAsJSON(TRACE_VALUE_TYPE_DOUBLE, json_value, out); |
+ } break; |
+ |
+ case kTypeString: { |
+ std::string value; |
+ CHECK(it.ReadString(&value)); |
+ maybe_append_key_name(current_state, &it, out); |
+ TraceEvent::TraceValue json_value; |
+ json_value.as_string = value.c_str(); |
+ TraceEvent::AppendValueAsJSON(TRACE_VALUE_TYPE_STRING, json_value, out); |
+ } break; |
+ |
+ default: |
+ NOTREACHED(); |
+ } |
+ |
+ current_state.needs_comma = true; |
+ } |
+ |
+ out->append("}"); |
+ state_stack.pop(); |
+ |
+ DCHECK(state_stack.empty()); |
} |
void TracedValue::EstimateTraceMemoryOverhead( |