1/*
2 * Copyright (c) 2021 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#ifndef ECMASCRIPT_REGEXP_DYN_BUFFER_H
17#define ECMASCRIPT_REGEXP_DYN_BUFFER_H
18
19#include <cstring>
20
21#include "ecmascript/common.h"
22#include "ecmascript/mem/regexp_cached_chunk.h"
23#include "ecmascript/mem/chunk.h"
24
25namespace panda::ecmascript {
26class PUBLIC_API DynChunk {
27public:
28    static constexpr size_t ALLOCATE_MIN_SIZE = 256;
29    static constexpr int FAILURE = -1;
30    static constexpr int SUCCESS = 0;
31    explicit DynChunk(Chunk *chunk) : chunk_(chunk)
32    {
33        ASSERT(chunk_ != nullptr);
34    };
35
36    ~DynChunk() = default;
37
38    NO_COPY_SEMANTIC(DynChunk);
39    NO_MOVE_SEMANTIC(DynChunk);
40
41    int Expand(size_t newSize);
42
43    int Insert(uint32_t position, size_t len);
44
45    int PUBLIC_API Emit(const uint8_t *data, size_t len);
46
47    int EmitSelf(size_t offset, size_t len);
48
49    int PUBLIC_API EmitChar(uint8_t c);
50
51    int EmitStr(const char *str);
52
53    inline int EmitU16(uint16_t data)
54    {
55        return Emit(reinterpret_cast<uint8_t *>(&data), U16_SIZE);
56    }
57
58    inline int EmitU32(uint32_t data)
59    {
60        return Emit(reinterpret_cast<uint8_t *>(&data), U32_SIZE);
61    }
62
63    inline int EmitU64(uint64_t data)
64    {
65        return Emit(reinterpret_cast<uint8_t *>(&data), U64_SIZE);
66    }
67
68    inline void SetError()
69    {
70        error_ = true;
71    }
72
73    inline size_t GetSize() const
74    {
75        return size_;
76    }
77
78    inline size_t GetAllocatedSize() const
79    {
80        return allocatedSize_;
81    }
82
83    inline bool GetError() const
84    {
85        return error_;
86    }
87
88    inline uint64_t GetU64(size_t offset) const
89    {
90        // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
91        return *reinterpret_cast<uint64_t *>(buf_ + offset);
92    }
93
94    inline uint32_t GetU32(size_t offset) const
95    {
96        // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
97        return *reinterpret_cast<uint32_t *>(buf_ + offset);
98    }
99
100    inline void PutU32(size_t offset, uint32_t data) const
101    {
102        // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
103        *reinterpret_cast<uint32_t *>(buf_ + offset) = data;
104    }
105
106    inline uint32_t GetU16(size_t offset) const
107    {
108        // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
109        return *reinterpret_cast<uint16_t *>(buf_ + offset);
110    }
111
112    inline void PutU16(size_t offset, uint16_t data) const
113    {
114        // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
115        *reinterpret_cast<uint16_t *>(buf_ + offset) = data;
116    }
117
118    inline uint32_t GetU8(size_t offset) const
119    {
120        // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
121        return *(buf_ + offset);
122    }
123
124    inline void PutU8(size_t offset, uint8_t data) const
125    {
126        // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
127        *(buf_ + offset) = data;
128    }
129
130    ALWAYS_INLINE static inline constexpr uint32_t GetBufferOffset()
131    {
132        return MEMBER_OFFSET(DynChunk, buf_);
133    }
134
135    uint8_t *GetBegin() const
136    {
137        return buf_;
138    }
139
140private:
141    static constexpr size_t ALLOCATE_MULTIPLIER = 2;
142    static constexpr size_t U16_SIZE = 2;
143    static constexpr size_t U32_SIZE = 4;
144    static constexpr size_t U64_SIZE = 8;
145    friend class RegExpParser;
146    friend class RegExpOpCode;
147    friend class RegExpExecutor;
148
149    DynChunk(uint8_t *buf, RegExpCachedChunk *regExpCachedChunk) : buf_(buf), regExpCachedChunk_(regExpCachedChunk)
150    {
151        ASSERT(regExpCachedChunk_ != nullptr);
152    };
153
154    uint8_t *buf_ {nullptr};
155    size_t size_ {0};
156    size_t allocatedSize_ {0};
157    bool error_ {false};
158    RegExpCachedChunk *regExpCachedChunk_ {nullptr};
159    Chunk *chunk_ {nullptr};
160};
161}  // namespace panda::ecmascript
162#endif  // ECMASCRIPT_REGEXP_DYN_BUFFER_H
163