Introduce DebugAnnotationParser

Refactor the debug annotation parsing logic into a standalone class,
which later will be used to parse debug annotations for console
interceptor.

R=eseckler@google.com,lalitm@google.com

Change-Id: I6b53706c4b63d455f4df1600b30029b02cc92139
diff --git a/src/trace_processor/util/proto_to_args_parser.cc b/src/trace_processor/util/proto_to_args_parser.cc
index 6fec35e..8e4eb22 100644
--- a/src/trace_processor/util/proto_to_args_parser.cc
+++ b/src/trace_processor/util/proto_to_args_parser.cc
@@ -63,6 +63,33 @@
     : flat_key(fk), key(k) {}
 ProtoToArgsParser::Key::~Key() = default;
 
+ProtoToArgsParser::ScopedNestedKeyContext::ScopedNestedKeyContext(Key& key)
+    : key_(key),
+      old_flat_key_length_(key.flat_key.length()),
+      old_key_length_(key.key.length()) {}
+
+ProtoToArgsParser::ScopedNestedKeyContext::ScopedNestedKeyContext(
+    ProtoToArgsParser::ScopedNestedKeyContext&& other)
+    : key_(other.key_),
+      old_flat_key_length_(other.old_flat_key_length_),
+      old_key_length_(other.old_key_length_) {
+  other.old_flat_key_length_ = base::nullopt;
+  other.old_key_length_ = base::nullopt;
+}
+
+ProtoToArgsParser::ScopedNestedKeyContext::~ScopedNestedKeyContext() {
+  Reset();
+}
+
+void ProtoToArgsParser::ScopedNestedKeyContext::Reset() {
+  if (old_flat_key_length_)
+    key_.flat_key.resize(old_flat_key_length_.value());
+  if (old_key_length_)
+    key_.key.resize(old_key_length_.value());
+  old_flat_key_length_ = base::nullopt;
+  old_key_length_ = base::nullopt;
+}
+
 ProtoToArgsParser::Delegate::~Delegate() = default;
 
 ProtoToArgsParser::ProtoToArgsParser(const DescriptorPool& pool) : pool_(pool) {
@@ -238,6 +265,25 @@
   }
 }
 
+ProtoToArgsParser::ScopedNestedKeyContext ProtoToArgsParser::EnterArray(
+    size_t index) {
+  auto context = ScopedNestedKeyContext(key_prefix_);
+  key_prefix_.key += "[" + std::to_string(index) + "]";
+  return context;
+}
+
+ProtoToArgsParser::ScopedNestedKeyContext ProtoToArgsParser::EnterDictionary(
+    const std::string& name) {
+  auto context = ScopedNestedKeyContext(key_prefix_);
+  if (!key_prefix_.key.empty())
+    key_prefix_.key += '.';
+  key_prefix_.key += name;
+  if (!key_prefix_.flat_key.empty())
+    key_prefix_.flat_key += '.';
+  key_prefix_.flat_key += name;
+  return context;
+}
+
 }  // namespace util
 }  // namespace trace_processor
 }  // namespace perfetto