| /* |
| * Copyright (C) 2026 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_SQL_BUNDLE_H_ |
| #define SRC_TRACE_PROCESSOR_UTIL_SQL_BUNDLE_H_ |
| |
| #include <array> |
| #include <cstddef> |
| #include <cstdint> |
| #include <cstring> |
| #include <string_view> |
| |
| #include "perfetto/base/logging.h" |
| |
| namespace perfetto::trace_processor { |
| |
| // Iterates a packed (path, sql) bundle generated by |
| // tools/gen_amalgamated_sql.py and embedded as a `constexpr std::array<uint8_t, |
| // N>` via the perfetto_cpp_blob_header build primitive. |
| // |
| // Wire format (all integers little-endian, no padding): |
| // uint32_t count; |
| // for (count) { |
| // uint32_t path_size; // excluding the trailing NUL. |
| // char path[path_size]; |
| // char nul; // 0x00. |
| // uint32_t sql_size; |
| // char sql[sql_size]; |
| // } |
| class SqlBundle { |
| public: |
| struct FileToSql { |
| const char* path; // NUL-terminated, points into the blob. |
| std::string_view sql; // Points into the blob. |
| std::string_view sql_view() const { return sql; } |
| }; |
| |
| SqlBundle(const uint8_t* data, size_t size) : data_(data), size_(size) { |
| PERFETTO_CHECK(size_ >= sizeof(uint32_t)); |
| } |
| |
| template <size_t N> |
| explicit SqlBundle(const std::array<uint8_t, N>& blob) |
| : SqlBundle(blob.data(), blob.size()) {} |
| |
| class Iterator { |
| public: |
| Iterator(const uint8_t* p, const uint8_t* end) : next_(p), end_(end) { |
| Advance(); |
| } |
| |
| bool operator!=(const Iterator& o) const { return cur_ != o.cur_; } |
| const FileToSql& operator*() const { return entry_; } |
| const FileToSql* operator->() const { return &entry_; } |
| Iterator& operator++() { |
| Advance(); |
| return *this; |
| } |
| |
| private: |
| void Advance() { |
| cur_ = next_; |
| if (cur_ >= end_) |
| return; |
| uint32_t path_size; |
| std::memcpy(&path_size, next_, sizeof(path_size)); |
| next_ += sizeof(path_size); |
| entry_.path = reinterpret_cast<const char*>(next_); |
| next_ += path_size + 1; // +1 for the NUL terminator. |
| |
| uint32_t sql_size; |
| std::memcpy(&sql_size, next_, sizeof(sql_size)); |
| next_ += sizeof(sql_size); |
| entry_.sql = |
| std::string_view(reinterpret_cast<const char*>(next_), sql_size); |
| next_ += sql_size; |
| } |
| |
| const uint8_t* cur_ = nullptr; |
| const uint8_t* next_; |
| const uint8_t* end_; |
| FileToSql entry_{}; |
| }; |
| |
| Iterator begin() const { |
| return Iterator(data_ + sizeof(uint32_t), data_ + size_); |
| } |
| Iterator end() const { return Iterator(data_ + size_, data_ + size_); } |
| |
| private: |
| const uint8_t* data_; |
| size_t size_; |
| }; |
| |
| } // namespace perfetto::trace_processor |
| |
| #endif // SRC_TRACE_PROCESSOR_UTIL_SQL_BUNDLE_H_ |