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