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/trace_blob_view.h b/src/trace_processor/util/trace_blob_view.h
new file mode 100644
index 0000000..7d9c1a4
--- /dev/null
+++ b/src/trace_processor/util/trace_blob_view.h
@@ -0,0 +1,148 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef SRC_TRACE_PROCESSOR_UTIL_TRACE_BLOB_VIEW_H_
+#define SRC_TRACE_PROCESSOR_UTIL_TRACE_BLOB_VIEW_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include <limits>
+#include <memory>
+
+#include "perfetto/base/logging.h"
+
+namespace perfetto {
+namespace trace_processor {
+
+// This class is an equivalent of std::string_view for trace binary data.
+// The main difference is that this class has also shared ownership of a portion
+// of the raw trace.
+// The underlying buffer will be freed once all the TraceBlobViews that refer
+// to the same buffer have passed through the pipeline and been parsed.
+class TraceBlobView {
+ public:
+ TraceBlobView(std::unique_ptr<uint8_t[]> buffer, size_t offset, size_t length)
+ : shbuf_(SharedBuf(std::move(buffer))),
+ offset_(static_cast<uint32_t>(offset)),
+ length_(static_cast<uint32_t>(length)) {
+ PERFETTO_DCHECK(offset <= std::numeric_limits<uint32_t>::max());
+ PERFETTO_DCHECK(length <= std::numeric_limits<uint32_t>::max());
+ }
+
+ // Allow std::move().
+ TraceBlobView(TraceBlobView&&) noexcept = default;
+ TraceBlobView& operator=(TraceBlobView&&) = default;
+
+ // Disable implicit copy.
+ TraceBlobView(const TraceBlobView&) = delete;
+ TraceBlobView& operator=(const TraceBlobView&) = delete;
+
+ TraceBlobView slice(size_t offset, size_t length) const {
+ PERFETTO_DCHECK(offset + length <= offset_ + length_);
+ return TraceBlobView(shbuf_, offset, length);
+ }
+
+ bool operator==(const TraceBlobView& rhs) const {
+ return (shbuf_ == rhs.shbuf_) && (offset_ == rhs.offset_) &&
+ (length_ == rhs.length_);
+ }
+ bool operator!=(const TraceBlobView& rhs) const { return !(*this == rhs); }
+
+ inline const uint8_t* data() const { return start() + offset_; }
+
+ size_t offset_of(const uint8_t* data) const {
+ // When a field is size 0, data can be equal to start() + offset_ + length_.
+ PERFETTO_DCHECK(data >= start() && data <= (start() + offset_ + length_));
+ return static_cast<size_t>(data - start());
+ }
+
+ size_t length() const { return length_; }
+ size_t offset() const { return offset_; }
+
+ private:
+ // An equivalent to std::shared_ptr<uint8_t>, with the differnce that:
+ // - Supports array types, available for shared_ptr only in C++17.
+ // - Is not thread safe, which is not needed for our purposes.
+ class SharedBuf {
+ public:
+ explicit SharedBuf(std::unique_ptr<uint8_t[]> mem) {
+ rcbuf_ = new RefCountedBuf(std::move(mem));
+ }
+
+ SharedBuf(const SharedBuf& copy) : rcbuf_(copy.rcbuf_) {
+ PERFETTO_DCHECK(rcbuf_->refcount > 0);
+ rcbuf_->refcount++;
+ }
+
+ ~SharedBuf() {
+ if (!rcbuf_)
+ return;
+ PERFETTO_DCHECK(rcbuf_->refcount > 0);
+ if (--rcbuf_->refcount == 0) {
+ RefCountedBuf* rcbuf = rcbuf_;
+ rcbuf_ = nullptr;
+ delete rcbuf;
+ }
+ }
+
+ SharedBuf(SharedBuf&& other) noexcept {
+ rcbuf_ = other.rcbuf_;
+ other.rcbuf_ = nullptr;
+ }
+
+ SharedBuf& operator=(SharedBuf&& other) {
+ if (this != &other) {
+ // A bit of a ugly but pragmatic pattern to implement move assignment.
+ // First invoke the distructor and then invoke the move constructor
+ // inline via placement-new.
+ this->~SharedBuf();
+ new (this) SharedBuf(std::move(other));
+ }
+ return *this;
+ }
+
+ bool operator==(const SharedBuf& x) const { return x.rcbuf_ == rcbuf_; }
+ bool operator!=(const SharedBuf& x) const { return !(x == *this); }
+ const uint8_t* data() const { return rcbuf_->mem.get(); }
+
+ private:
+ struct RefCountedBuf {
+ explicit RefCountedBuf(std::unique_ptr<uint8_t[]> buf)
+ : refcount(1), mem(std::move(buf)) {}
+ int refcount;
+ std::unique_ptr<uint8_t[]> mem;
+ };
+
+ RefCountedBuf* rcbuf_ = nullptr;
+ };
+
+ inline const uint8_t* start() const { return shbuf_.data(); }
+
+ TraceBlobView(SharedBuf b, size_t o, size_t l)
+ : shbuf_(b),
+ offset_(static_cast<uint32_t>(o)),
+ length_(static_cast<uint32_t>(l)) {}
+
+ SharedBuf shbuf_;
+ uint32_t offset_;
+ uint32_t length_; // Measured from |offset_|, not from |data()|.
+};
+
+} // namespace trace_processor
+} // namespace perfetto
+
+#endif // SRC_TRACE_PROCESSOR_UTIL_TRACE_BLOB_VIEW_H_