blob: 7d9c1a4cc9da8b708b3fb19d67cf1df2b3aceb1d [file] [log] [blame]
Primiano Tuccid933d912018-09-04 09:15:07 +01001/*
2 * Copyright (C) 2018 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Alexander Timin97d87852021-05-17 18:01:33 +000017#ifndef SRC_TRACE_PROCESSOR_UTIL_TRACE_BLOB_VIEW_H_
18#define SRC_TRACE_PROCESSOR_UTIL_TRACE_BLOB_VIEW_H_
Primiano Tuccid933d912018-09-04 09:15:07 +010019
20#include <stddef.h>
21#include <stdint.h>
Primiano Tucci81d0a392018-09-04 15:15:37 +010022
23#include <limits>
Primiano Tuccid933d912018-09-04 09:15:07 +010024#include <memory>
25
26#include "perfetto/base/logging.h"
27
28namespace perfetto {
29namespace trace_processor {
30
31// This class is an equivalent of std::string_view for trace binary data.
32// The main difference is that this class has also shared ownership of a portion
33// of the raw trace.
34// The underlying buffer will be freed once all the TraceBlobViews that refer
35// to the same buffer have passed through the pipeline and been parsed.
36class TraceBlobView {
37 public:
38 TraceBlobView(std::unique_ptr<uint8_t[]> buffer, size_t offset, size_t length)
39 : shbuf_(SharedBuf(std::move(buffer))),
Primiano Tucci81d0a392018-09-04 15:15:37 +010040 offset_(static_cast<uint32_t>(offset)),
41 length_(static_cast<uint32_t>(length)) {
42 PERFETTO_DCHECK(offset <= std::numeric_limits<uint32_t>::max());
43 PERFETTO_DCHECK(length <= std::numeric_limits<uint32_t>::max());
44 }
Primiano Tuccid933d912018-09-04 09:15:07 +010045
46 // Allow std::move().
47 TraceBlobView(TraceBlobView&&) noexcept = default;
48 TraceBlobView& operator=(TraceBlobView&&) = default;
49
50 // Disable implicit copy.
51 TraceBlobView(const TraceBlobView&) = delete;
52 TraceBlobView& operator=(const TraceBlobView&) = delete;
53
Eric Seckler1edbe002019-12-16 18:08:57 +000054 TraceBlobView slice(size_t offset, size_t length) const {
Primiano Tuccid933d912018-09-04 09:15:07 +010055 PERFETTO_DCHECK(offset + length <= offset_ + length_);
56 return TraceBlobView(shbuf_, offset, length);
57 }
58
59 bool operator==(const TraceBlobView& rhs) const {
60 return (shbuf_ == rhs.shbuf_) && (offset_ == rhs.offset_) &&
61 (length_ == rhs.length_);
62 }
63 bool operator!=(const TraceBlobView& rhs) const { return !(*this == rhs); }
64
65 inline const uint8_t* data() const { return start() + offset_; }
66
67 size_t offset_of(const uint8_t* data) const {
Isabelle Taylorde2bc3a2019-01-15 16:56:10 +000068 // When a field is size 0, data can be equal to start() + offset_ + length_.
69 PERFETTO_DCHECK(data >= start() && data <= (start() + offset_ + length_));
Primiano Tuccid933d912018-09-04 09:15:07 +010070 return static_cast<size_t>(data - start());
71 }
72
Primiano Tuccid933d912018-09-04 09:15:07 +010073 size_t length() const { return length_; }
Primiano Tuccic1678872019-03-20 11:30:54 +000074 size_t offset() const { return offset_; }
Primiano Tuccid933d912018-09-04 09:15:07 +010075
76 private:
77 // An equivalent to std::shared_ptr<uint8_t>, with the differnce that:
78 // - Supports array types, available for shared_ptr only in C++17.
79 // - Is not thread safe, which is not needed for our purposes.
80 class SharedBuf {
81 public:
82 explicit SharedBuf(std::unique_ptr<uint8_t[]> mem) {
83 rcbuf_ = new RefCountedBuf(std::move(mem));
84 }
85
86 SharedBuf(const SharedBuf& copy) : rcbuf_(copy.rcbuf_) {
87 PERFETTO_DCHECK(rcbuf_->refcount > 0);
88 rcbuf_->refcount++;
89 }
90
91 ~SharedBuf() {
92 if (!rcbuf_)
93 return;
94 PERFETTO_DCHECK(rcbuf_->refcount > 0);
95 if (--rcbuf_->refcount == 0) {
96 RefCountedBuf* rcbuf = rcbuf_;
97 rcbuf_ = nullptr;
98 delete rcbuf;
99 }
100 }
101
102 SharedBuf(SharedBuf&& other) noexcept {
103 rcbuf_ = other.rcbuf_;
104 other.rcbuf_ = nullptr;
105 }
106
107 SharedBuf& operator=(SharedBuf&& other) {
108 if (this != &other) {
109 // A bit of a ugly but pragmatic pattern to implement move assignment.
110 // First invoke the distructor and then invoke the move constructor
111 // inline via placement-new.
112 this->~SharedBuf();
113 new (this) SharedBuf(std::move(other));
114 }
115 return *this;
116 }
117
118 bool operator==(const SharedBuf& x) const { return x.rcbuf_ == rcbuf_; }
119 bool operator!=(const SharedBuf& x) const { return !(x == *this); }
120 const uint8_t* data() const { return rcbuf_->mem.get(); }
121
122 private:
123 struct RefCountedBuf {
124 explicit RefCountedBuf(std::unique_ptr<uint8_t[]> buf)
125 : refcount(1), mem(std::move(buf)) {}
126 int refcount;
127 std::unique_ptr<uint8_t[]> mem;
128 };
129
130 RefCountedBuf* rcbuf_ = nullptr;
131 };
132
133 inline const uint8_t* start() const { return shbuf_.data(); }
134
135 TraceBlobView(SharedBuf b, size_t o, size_t l)
Primiano Tucci81d0a392018-09-04 15:15:37 +0100136 : shbuf_(b),
137 offset_(static_cast<uint32_t>(o)),
138 length_(static_cast<uint32_t>(l)) {}
Primiano Tuccid933d912018-09-04 09:15:07 +0100139
140 SharedBuf shbuf_;
Primiano Tucci81d0a392018-09-04 15:15:37 +0100141 uint32_t offset_;
142 uint32_t length_; // Measured from |offset_|, not from |data()|.
Primiano Tuccid933d912018-09-04 09:15:07 +0100143};
144
145} // namespace trace_processor
146} // namespace perfetto
147
Alexander Timin97d87852021-05-17 18:01:33 +0000148#endif // SRC_TRACE_PROCESSOR_UTIL_TRACE_BLOB_VIEW_H_