| /* | |
| * 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_ |