1 /* 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 17 #ifndef INCLUDE_PERFETTO_TRACE_PROCESSOR_TRACE_BLOB_VIEW_H_ 18 #define INCLUDE_PERFETTO_TRACE_PROCESSOR_TRACE_BLOB_VIEW_H_ 19 20 #include <stddef.h> 21 #include <stdint.h> 22 23 #include <limits> 24 #include <memory> 25 26 #include "perfetto/base/logging.h" 27 #include "perfetto/trace_processor/ref_counted.h" 28 #include "perfetto/trace_processor/trace_blob.h" 29 30 namespace perfetto { 31 namespace trace_processor { 32 33 // A read-only view of a TraceBlob. 34 // This class is an equivalent of std::string_view for trace binary data, with 35 // a twist: it supports turning a TraceBlob into a refcounted reference. In this 36 // case the TraceBlobView acts directly as a shared_ptr, without requiring extra 37 // layers of indirection. 38 // The underlying TraceBlob will be freed once all the TraceBlobViews that refer 39 // to the same buffer have passed through the pipeline and been parsed. 40 // The overall idea is that a TraceBlob is passed around until it's written. 41 // When writing is done it transforms into a shared refcounted object which is 42 // held onto by one or more read-only TraceBlobView instances. 43 // 44 // In summary: 45 // - TraceBlob: writable, move-only, single-instance. 46 // - TraceBlobView: readable, copyable, multiple-instances can hold onto 47 // (different sub-slices of) the same refcounted TraceBlob. 48 class TraceBlobView { 49 public: 50 // Takes ownership of the passed |blob|. 51 static constexpr size_t kWholeBlob = std::numeric_limits<size_t>::max(); 52 explicit TraceBlobView(TraceBlob blob, 53 size_t offset = 0, 54 size_t length = kWholeBlob) { 55 PERFETTO_DCHECK(offset <= std::numeric_limits<uint32_t>::max()); 56 data_ = blob.data() + offset; 57 if (length == kWholeBlob) { 58 length_ = static_cast<uint32_t>(blob.size() - offset); 59 } else { 60 PERFETTO_DCHECK(length <= std::numeric_limits<uint32_t>::max()); 61 PERFETTO_DCHECK(offset + length_ <= blob.size()); 62 length_ = static_cast<uint32_t>(length); 63 } 64 blob_.reset(new TraceBlob(std::move(blob))); 65 } 66 67 // Trivial empty ctor. TraceBlobView()68 TraceBlobView() : data_(nullptr), length_(0) {} 69 70 ~TraceBlobView() = default; 71 72 // Allow std::move(). TraceBlobView(TraceBlobView && other)73 TraceBlobView(TraceBlobView&& other) noexcept { *this = std::move(other); } 74 75 TraceBlobView& operator=(TraceBlobView&& other) noexcept { 76 data_ = other.data_; 77 length_ = other.length_; 78 blob_ = std::move(other.blob_); 79 return *this; 80 } 81 82 // Disable copy operators. Use x.Copy() to get a copy. 83 TraceBlobView(const TraceBlobView&) = delete; 84 TraceBlobView& operator=(const TraceBlobView&) = delete; 85 86 // [data, data+length] must be <= the current TraceBlobView. slice(const uint8_t * data,size_t length)87 TraceBlobView slice(const uint8_t* data, size_t length) const { 88 PERFETTO_DCHECK(data >= data_); 89 PERFETTO_DCHECK(data + length <= data_ + length_); 90 return TraceBlobView(data, static_cast<uint32_t>(length), blob_); 91 } 92 93 // Like slice() but takes an offset rather than a pointer as 1st argument. slice_off(size_t off,size_t length)94 TraceBlobView slice_off(size_t off, size_t length) const { 95 PERFETTO_DCHECK(off + length <= length_); 96 return TraceBlobView(data_ + off, static_cast<uint32_t>(length), blob_); 97 } 98 copy()99 TraceBlobView copy() const { return slice(data_, length_); } 100 101 bool operator==(const TraceBlobView& rhs) const { 102 return (data_ == rhs.data_) && (length_ == rhs.length_) && 103 (blob_ == rhs.blob_); 104 } 105 bool operator!=(const TraceBlobView& rhs) const { return !(*this == rhs); } 106 data()107 const uint8_t* data() const { return data_; } 108 // TODO(primiano): normalize length() vs size() usage. length()109 size_t length() const { return length_; } size()110 size_t size() const { return length_; } 111 112 private: TraceBlobView(const uint8_t * data,uint32_t length,RefPtr<TraceBlob> blob)113 TraceBlobView(const uint8_t* data, uint32_t length, RefPtr<TraceBlob> blob) 114 : data_(data), length_(length), blob_(std::move(blob)) {} 115 116 const uint8_t* data_ = nullptr; 117 uint32_t length_ = 0; 118 RefPtr<TraceBlob> blob_; 119 }; 120 121 } // namespace trace_processor 122 } // namespace perfetto 123 124 #endif // INCLUDE_PERFETTO_TRACE_PROCESSOR_TRACE_BLOB_VIEW_H_ 125