1b1994897Sopenharmony_ci/** 2b1994897Sopenharmony_ci * Copyright (c) 2021-2022 Huawei Device Co., Ltd. 3b1994897Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 4b1994897Sopenharmony_ci * you may not use this file except in compliance with the License. 5b1994897Sopenharmony_ci * You may obtain a copy of the License at 6b1994897Sopenharmony_ci * 7b1994897Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 8b1994897Sopenharmony_ci * 9b1994897Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 10b1994897Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 11b1994897Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12b1994897Sopenharmony_ci * See the License for the specific language governing permissions and 13b1994897Sopenharmony_ci * limitations under the License. 14b1994897Sopenharmony_ci */ 15b1994897Sopenharmony_ci 16b1994897Sopenharmony_ci#ifndef LIBPANDAFILE_FILE_WRITER_H 17b1994897Sopenharmony_ci#define LIBPANDAFILE_FILE_WRITER_H 18b1994897Sopenharmony_ci 19b1994897Sopenharmony_ci#include "os/file.h" 20b1994897Sopenharmony_ci#include "utils/span.h" 21b1994897Sopenharmony_ci#include "utils/type_helpers.h" 22b1994897Sopenharmony_ci#include "utils/leb128.h" 23b1994897Sopenharmony_ci#include "securec.h" 24b1994897Sopenharmony_ci 25b1994897Sopenharmony_ci#include <cstdint> 26b1994897Sopenharmony_ci#include <cerrno> 27b1994897Sopenharmony_ci 28b1994897Sopenharmony_ci#include <limits> 29b1994897Sopenharmony_ci#include <vector> 30b1994897Sopenharmony_ci 31b1994897Sopenharmony_cinamespace panda::panda_file { 32b1994897Sopenharmony_ci 33b1994897Sopenharmony_ciclass Writer { 34b1994897Sopenharmony_cipublic: 35b1994897Sopenharmony_ci virtual bool WriteByte(uint8_t byte) = 0; 36b1994897Sopenharmony_ci 37b1994897Sopenharmony_ci virtual bool WriteBytes(const std::vector<uint8_t> &bytes) = 0; 38b1994897Sopenharmony_ci 39b1994897Sopenharmony_ci virtual size_t GetOffset() const = 0; 40b1994897Sopenharmony_ci 41b1994897Sopenharmony_ci virtual void CountChecksum(bool /* counting */) {} 42b1994897Sopenharmony_ci 43b1994897Sopenharmony_ci virtual bool RewriteChecksum(size_t /* offset */) 44b1994897Sopenharmony_ci { 45b1994897Sopenharmony_ci return false; 46b1994897Sopenharmony_ci } 47b1994897Sopenharmony_ci 48b1994897Sopenharmony_ci bool Align(size_t alignment) 49b1994897Sopenharmony_ci { 50b1994897Sopenharmony_ci size_t offset = GetOffset(); 51b1994897Sopenharmony_ci size_t n = RoundUp(offset, alignment) - offset; 52b1994897Sopenharmony_ci while (n-- > 0) { 53b1994897Sopenharmony_ci if (!WriteByte(0)) { 54b1994897Sopenharmony_ci return false; 55b1994897Sopenharmony_ci } 56b1994897Sopenharmony_ci } 57b1994897Sopenharmony_ci return true; 58b1994897Sopenharmony_ci } 59b1994897Sopenharmony_ci 60b1994897Sopenharmony_ci template <class T> 61b1994897Sopenharmony_ci bool Write(T data) 62b1994897Sopenharmony_ci { 63b1994897Sopenharmony_ci static constexpr size_t BYTE_MASK = 0xff; 64b1994897Sopenharmony_ci static constexpr size_t BYTE_WIDTH = std::numeric_limits<uint8_t>::digits; 65b1994897Sopenharmony_ci 66b1994897Sopenharmony_ci for (size_t i = 0; i < sizeof(T); i++) { 67b1994897Sopenharmony_ci if (!WriteByte(data & BYTE_MASK)) { 68b1994897Sopenharmony_ci return false; 69b1994897Sopenharmony_ci } 70b1994897Sopenharmony_ci 71b1994897Sopenharmony_ci if (sizeof(T) > sizeof(uint8_t)) { 72b1994897Sopenharmony_ci data >>= BYTE_WIDTH; 73b1994897Sopenharmony_ci } 74b1994897Sopenharmony_ci } 75b1994897Sopenharmony_ci return true; 76b1994897Sopenharmony_ci } 77b1994897Sopenharmony_ci 78b1994897Sopenharmony_ci template <class T> 79b1994897Sopenharmony_ci bool WriteUleb128(T v) 80b1994897Sopenharmony_ci { 81b1994897Sopenharmony_ci size_t n = leb128::UnsignedEncodingSize(v); 82b1994897Sopenharmony_ci std::vector<uint8_t> out(n); 83b1994897Sopenharmony_ci leb128::EncodeUnsigned(v, out.data()); 84b1994897Sopenharmony_ci return WriteBytes(out); 85b1994897Sopenharmony_ci } 86b1994897Sopenharmony_ci 87b1994897Sopenharmony_ci template <class T> 88b1994897Sopenharmony_ci bool WriteSleb128(T v) 89b1994897Sopenharmony_ci { 90b1994897Sopenharmony_ci size_t n = leb128::SignedEncodingSize(v); 91b1994897Sopenharmony_ci std::vector<uint8_t> out(n); 92b1994897Sopenharmony_ci leb128::EncodeSigned(v, out.data()); 93b1994897Sopenharmony_ci return WriteBytes(out); 94b1994897Sopenharmony_ci } 95b1994897Sopenharmony_ci 96b1994897Sopenharmony_ci virtual void ReserveBufferCapacity([[maybe_unused]] size_t size) {} 97b1994897Sopenharmony_ci 98b1994897Sopenharmony_ci virtual bool FinishWrite() 99b1994897Sopenharmony_ci { 100b1994897Sopenharmony_ci return true; 101b1994897Sopenharmony_ci } 102b1994897Sopenharmony_ci 103b1994897Sopenharmony_ci // default methods 104b1994897Sopenharmony_ci Writer() = default; 105b1994897Sopenharmony_ci virtual ~Writer() = default; 106b1994897Sopenharmony_ci 107b1994897Sopenharmony_ci NO_COPY_SEMANTIC(Writer); 108b1994897Sopenharmony_ci NO_MOVE_SEMANTIC(Writer); 109b1994897Sopenharmony_ci}; 110b1994897Sopenharmony_ci 111b1994897Sopenharmony_ciclass MemoryWriter : public Writer { 112b1994897Sopenharmony_cipublic: 113b1994897Sopenharmony_ci bool WriteByte(uint8_t byte) override 114b1994897Sopenharmony_ci { 115b1994897Sopenharmony_ci data_.push_back(byte); 116b1994897Sopenharmony_ci return true; 117b1994897Sopenharmony_ci } 118b1994897Sopenharmony_ci 119b1994897Sopenharmony_ci bool WriteBytes(const std::vector<uint8_t> &bytes) override 120b1994897Sopenharmony_ci { 121b1994897Sopenharmony_ci data_.insert(data_.end(), bytes.cbegin(), bytes.cend()); 122b1994897Sopenharmony_ci return true; 123b1994897Sopenharmony_ci } 124b1994897Sopenharmony_ci 125b1994897Sopenharmony_ci const std::vector<uint8_t> &GetData() 126b1994897Sopenharmony_ci { 127b1994897Sopenharmony_ci return data_; 128b1994897Sopenharmony_ci } 129b1994897Sopenharmony_ci 130b1994897Sopenharmony_ci size_t GetOffset() const override 131b1994897Sopenharmony_ci { 132b1994897Sopenharmony_ci return data_.size(); 133b1994897Sopenharmony_ci } 134b1994897Sopenharmony_ci 135b1994897Sopenharmony_ciprivate: 136b1994897Sopenharmony_ci std::vector<uint8_t> data_; 137b1994897Sopenharmony_ci}; 138b1994897Sopenharmony_ci 139b1994897Sopenharmony_ciclass MemoryBufferWriter : public Writer { 140b1994897Sopenharmony_cipublic: 141b1994897Sopenharmony_ci explicit MemoryBufferWriter(uint8_t *buffer, size_t size) : sp_(buffer, size) {} 142b1994897Sopenharmony_ci 143b1994897Sopenharmony_ci ~MemoryBufferWriter() override = default; 144b1994897Sopenharmony_ci 145b1994897Sopenharmony_ci NO_COPY_SEMANTIC(MemoryBufferWriter); 146b1994897Sopenharmony_ci NO_MOVE_SEMANTIC(MemoryBufferWriter); 147b1994897Sopenharmony_ci 148b1994897Sopenharmony_ci bool WriteByte(uint8_t byte) override 149b1994897Sopenharmony_ci { 150b1994897Sopenharmony_ci sp_[offset_++] = byte; 151b1994897Sopenharmony_ci return true; 152b1994897Sopenharmony_ci } 153b1994897Sopenharmony_ci 154b1994897Sopenharmony_ci bool WriteBytes(const std::vector<uint8_t> &bytes) override 155b1994897Sopenharmony_ci { 156b1994897Sopenharmony_ci if (bytes.empty()) { 157b1994897Sopenharmony_ci return true; 158b1994897Sopenharmony_ci } 159b1994897Sopenharmony_ci 160b1994897Sopenharmony_ci auto sub_sp = sp_.SubSpan(offset_, bytes.size()); 161b1994897Sopenharmony_ci if (memcpy_s(sub_sp.data(), sub_sp.size(), bytes.data(), bytes.size()) != 0) { 162b1994897Sopenharmony_ci return false; 163b1994897Sopenharmony_ci } 164b1994897Sopenharmony_ci offset_ += bytes.size(); 165b1994897Sopenharmony_ci return true; 166b1994897Sopenharmony_ci } 167b1994897Sopenharmony_ci 168b1994897Sopenharmony_ci size_t GetOffset() const override 169b1994897Sopenharmony_ci { 170b1994897Sopenharmony_ci return offset_; 171b1994897Sopenharmony_ci } 172b1994897Sopenharmony_ci 173b1994897Sopenharmony_ciprivate: 174b1994897Sopenharmony_ci Span<uint8_t> sp_; 175b1994897Sopenharmony_ci size_t offset_ {0}; 176b1994897Sopenharmony_ci}; 177b1994897Sopenharmony_ci 178b1994897Sopenharmony_ciclass FileWriter : public Writer { 179b1994897Sopenharmony_cipublic: 180b1994897Sopenharmony_ci explicit FileWriter(const std::string &file_name); 181b1994897Sopenharmony_ci 182b1994897Sopenharmony_ci ~FileWriter() override; 183b1994897Sopenharmony_ci 184b1994897Sopenharmony_ci NO_COPY_SEMANTIC(FileWriter); 185b1994897Sopenharmony_ci NO_MOVE_SEMANTIC(FileWriter); 186b1994897Sopenharmony_ci 187b1994897Sopenharmony_ci void CountChecksum(bool counting) override 188b1994897Sopenharmony_ci { 189b1994897Sopenharmony_ci count_checksum_ = counting; 190b1994897Sopenharmony_ci } 191b1994897Sopenharmony_ci 192b1994897Sopenharmony_ci bool RewriteChecksum(size_t offset) override 193b1994897Sopenharmony_ci { 194b1994897Sopenharmony_ci static constexpr size_t MASK = 0xff; 195b1994897Sopenharmony_ci static constexpr size_t WIDTH = std::numeric_limits<uint8_t>::digits; 196b1994897Sopenharmony_ci 197b1994897Sopenharmony_ci size_t length = sizeof(uint32_t); 198b1994897Sopenharmony_ci if (offset + length > buffer_.size()) { 199b1994897Sopenharmony_ci return false; 200b1994897Sopenharmony_ci } 201b1994897Sopenharmony_ci uint32_t temp = checksum_; 202b1994897Sopenharmony_ci for (size_t i = 0; i < length; i++) { 203b1994897Sopenharmony_ci buffer_[offset + i] = temp & MASK; 204b1994897Sopenharmony_ci temp >>= WIDTH; 205b1994897Sopenharmony_ci } 206b1994897Sopenharmony_ci return true; 207b1994897Sopenharmony_ci } 208b1994897Sopenharmony_ci 209b1994897Sopenharmony_ci bool WriteByte(uint8_t data) override; 210b1994897Sopenharmony_ci 211b1994897Sopenharmony_ci bool WriteBytes(const std::vector<uint8_t> &bytes) override; 212b1994897Sopenharmony_ci 213b1994897Sopenharmony_ci size_t GetOffset() const override 214b1994897Sopenharmony_ci { 215b1994897Sopenharmony_ci return buffer_.size(); 216b1994897Sopenharmony_ci } 217b1994897Sopenharmony_ci 218b1994897Sopenharmony_ci uint32_t GetChecksum() const 219b1994897Sopenharmony_ci { 220b1994897Sopenharmony_ci return checksum_; 221b1994897Sopenharmony_ci } 222b1994897Sopenharmony_ci 223b1994897Sopenharmony_ci explicit operator bool() const 224b1994897Sopenharmony_ci { 225b1994897Sopenharmony_ci return file_ != nullptr; 226b1994897Sopenharmony_ci } 227b1994897Sopenharmony_ci 228b1994897Sopenharmony_ci void ReserveBufferCapacity(size_t size) override 229b1994897Sopenharmony_ci { 230b1994897Sopenharmony_ci buffer_.reserve(size); 231b1994897Sopenharmony_ci } 232b1994897Sopenharmony_ci 233b1994897Sopenharmony_ci const std::vector<uint8_t> &GetBuffer() const 234b1994897Sopenharmony_ci { 235b1994897Sopenharmony_ci return buffer_; 236b1994897Sopenharmony_ci } 237b1994897Sopenharmony_ci 238b1994897Sopenharmony_ci bool FinishWrite() override; 239b1994897Sopenharmony_ci 240b1994897Sopenharmony_ciprivate: 241b1994897Sopenharmony_ci FILE *file_; 242b1994897Sopenharmony_ci uint32_t checksum_; 243b1994897Sopenharmony_ci bool count_checksum_ {false}; 244b1994897Sopenharmony_ci std::vector<uint8_t> buffer_; 245b1994897Sopenharmony_ci}; 246b1994897Sopenharmony_ci 247b1994897Sopenharmony_ci} // namespace panda::panda_file 248b1994897Sopenharmony_ci 249b1994897Sopenharmony_ci#endif // LIBPANDAFILE_FILE_WRITER_H 250