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