Coverage Report

Created: 2026-01-17 07:03

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/valijson/thirdparty/rapidjson/include/rapidjson/internal/stack.h
Line
Count
Source
1
// Tencent is pleased to support the open source community by making RapidJSON available.
2
// 
3
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
4
//
5
// Licensed under the MIT License (the "License"); you may not use this file except
6
// in compliance with the License. You may obtain a copy of the License at
7
//
8
// http://opensource.org/licenses/MIT
9
//
10
// Unless required by applicable law or agreed to in writing, software distributed 
11
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 
12
// CONDITIONS OF ANY KIND, either express or implied. See the License for the 
13
// specific language governing permissions and limitations under the License.
14
15
#ifndef RAPIDJSON_INTERNAL_STACK_H_
16
#define RAPIDJSON_INTERNAL_STACK_H_
17
18
#include "../allocators.h"
19
#include "swap.h"
20
#include <cstddef>
21
22
#if defined(__clang__)
23
RAPIDJSON_DIAG_PUSH
24
RAPIDJSON_DIAG_OFF(c++98-compat)
25
#endif
26
27
RAPIDJSON_NAMESPACE_BEGIN
28
namespace internal {
29
30
///////////////////////////////////////////////////////////////////////////////
31
// Stack
32
33
//! A type-unsafe stack for storing different types of data.
34
/*! \tparam Allocator Allocator for allocating stack memory.
35
*/
36
template <typename Allocator>
37
class Stack {
38
public:
39
    // Optimization note: Do not allocate memory for stack_ in constructor.
40
    // Do it lazily when first Push() -> Expand() -> Resize().
41
22.1k
    Stack(Allocator* allocator, size_t stackCapacity) : allocator_(allocator), ownAllocator_(0), stack_(0), stackTop_(0), stackEnd_(0), initialCapacity_(stackCapacity) {
42
22.1k
    }
43
44
#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
45
    Stack(Stack&& rhs)
46
        : allocator_(rhs.allocator_),
47
          ownAllocator_(rhs.ownAllocator_),
48
          stack_(rhs.stack_),
49
          stackTop_(rhs.stackTop_),
50
          stackEnd_(rhs.stackEnd_),
51
          initialCapacity_(rhs.initialCapacity_)
52
    {
53
        rhs.allocator_ = 0;
54
        rhs.ownAllocator_ = 0;
55
        rhs.stack_ = 0;
56
        rhs.stackTop_ = 0;
57
        rhs.stackEnd_ = 0;
58
        rhs.initialCapacity_ = 0;
59
    }
60
#endif
61
62
22.1k
    ~Stack() {
63
22.1k
        Destroy();
64
22.1k
    }
65
66
#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
67
    Stack& operator=(Stack&& rhs) {
68
        if (&rhs != this)
69
        {
70
            Destroy();
71
72
            allocator_ = rhs.allocator_;
73
            ownAllocator_ = rhs.ownAllocator_;
74
            stack_ = rhs.stack_;
75
            stackTop_ = rhs.stackTop_;
76
            stackEnd_ = rhs.stackEnd_;
77
            initialCapacity_ = rhs.initialCapacity_;
78
79
            rhs.allocator_ = 0;
80
            rhs.ownAllocator_ = 0;
81
            rhs.stack_ = 0;
82
            rhs.stackTop_ = 0;
83
            rhs.stackEnd_ = 0;
84
            rhs.initialCapacity_ = 0;
85
        }
86
        return *this;
87
    }
88
#endif
89
90
    void Swap(Stack& rhs) RAPIDJSON_NOEXCEPT {
91
        internal::Swap(allocator_, rhs.allocator_);
92
        internal::Swap(ownAllocator_, rhs.ownAllocator_);
93
        internal::Swap(stack_, rhs.stack_);
94
        internal::Swap(stackTop_, rhs.stackTop_);
95
        internal::Swap(stackEnd_, rhs.stackEnd_);
96
        internal::Swap(initialCapacity_, rhs.initialCapacity_);
97
    }
98
99
22.1k
    void Clear() { stackTop_ = stack_; }
100
101
11.0k
    void ShrinkToFit() { 
102
11.0k
        if (Empty()) {
103
            // If the stack is empty, completely deallocate the memory.
104
11.0k
            Allocator::Free(stack_); // NOLINT (+clang-analyzer-unix.Malloc)
105
11.0k
            stack_ = 0;
106
11.0k
            stackTop_ = 0;
107
11.0k
            stackEnd_ = 0;
108
11.0k
        }
109
0
        else
110
0
            Resize(GetSize());
111
11.0k
    }
112
113
    // Optimization note: try to minimize the size of this function for force inline.
114
    // Expansion is run very infrequently, so it is moved to another (probably non-inline) function.
115
    template<typename T>
116
231M
    RAPIDJSON_FORCEINLINE void Reserve(size_t count = 1) {
117
         // Expand the stack if needed
118
231M
        if (RAPIDJSON_UNLIKELY(static_cast<std::ptrdiff_t>(sizeof(T) * count) > (stackEnd_ - stackTop_)))
119
47.2k
            Expand<T>(count);
120
231M
    }
void rapidjson::internal::Stack<rapidjson::CrtAllocator>::Reserve<unsigned int>(unsigned long)
Line
Count
Source
116
23.2M
    RAPIDJSON_FORCEINLINE void Reserve(size_t count = 1) {
117
         // Expand the stack if needed
118
23.2M
        if (RAPIDJSON_UNLIKELY(static_cast<std::ptrdiff_t>(sizeof(T) * count) > (stackEnd_ - stackTop_)))
119
11.5k
            Expand<T>(count);
120
23.2M
    }
void rapidjson::internal::Stack<rapidjson::CrtAllocator>::Reserve<rapidjson::GenericValue<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator> > >(unsigned long)
Line
Count
Source
116
13.2M
    RAPIDJSON_FORCEINLINE void Reserve(size_t count = 1) {
117
         // Expand the stack if needed
118
13.2M
        if (RAPIDJSON_UNLIKELY(static_cast<std::ptrdiff_t>(sizeof(T) * count) > (stackEnd_ - stackTop_)))
119
14.8k
            Expand<T>(count);
120
13.2M
    }
void rapidjson::internal::Stack<rapidjson::CrtAllocator>::Reserve<char>(unsigned long)
Line
Count
Source
116
195M
    RAPIDJSON_FORCEINLINE void Reserve(size_t count = 1) {
117
         // Expand the stack if needed
118
195M
        if (RAPIDJSON_UNLIKELY(static_cast<std::ptrdiff_t>(sizeof(T) * count) > (stackEnd_ - stackTop_)))
119
20.8k
            Expand<T>(count);
120
195M
    }
121
122
    template<typename T>
123
231M
    RAPIDJSON_FORCEINLINE T* Push(size_t count = 1) {
124
231M
        Reserve<T>(count);
125
231M
        return PushUnsafe<T>(count);
126
231M
    }
unsigned int* rapidjson::internal::Stack<rapidjson::CrtAllocator>::Push<unsigned int>(unsigned long)
Line
Count
Source
123
23.2M
    RAPIDJSON_FORCEINLINE T* Push(size_t count = 1) {
124
23.2M
        Reserve<T>(count);
125
23.2M
        return PushUnsafe<T>(count);
126
23.2M
    }
rapidjson::GenericValue<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator> >* rapidjson::internal::Stack<rapidjson::CrtAllocator>::Push<rapidjson::GenericValue<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator> > >(unsigned long)
Line
Count
Source
123
13.2M
    RAPIDJSON_FORCEINLINE T* Push(size_t count = 1) {
124
13.2M
        Reserve<T>(count);
125
13.2M
        return PushUnsafe<T>(count);
126
13.2M
    }
char* rapidjson::internal::Stack<rapidjson::CrtAllocator>::Push<char>(unsigned long)
Line
Count
Source
123
195M
    RAPIDJSON_FORCEINLINE T* Push(size_t count = 1) {
124
195M
        Reserve<T>(count);
125
195M
        return PushUnsafe<T>(count);
126
195M
    }
127
128
    template<typename T>
129
231M
    RAPIDJSON_FORCEINLINE T* PushUnsafe(size_t count = 1) {
130
231M
        RAPIDJSON_ASSERT(stackTop_);
131
231M
        RAPIDJSON_ASSERT(static_cast<std::ptrdiff_t>(sizeof(T) * count) <= (stackEnd_ - stackTop_));
132
231M
        T* ret = reinterpret_cast<T*>(stackTop_);
133
231M
        stackTop_ += sizeof(T) * count;
134
231M
        return ret;
135
231M
    }
unsigned int* rapidjson::internal::Stack<rapidjson::CrtAllocator>::PushUnsafe<unsigned int>(unsigned long)
Line
Count
Source
129
23.2M
    RAPIDJSON_FORCEINLINE T* PushUnsafe(size_t count = 1) {
130
23.2M
        RAPIDJSON_ASSERT(stackTop_);
131
23.2M
        RAPIDJSON_ASSERT(static_cast<std::ptrdiff_t>(sizeof(T) * count) <= (stackEnd_ - stackTop_));
132
23.2M
        T* ret = reinterpret_cast<T*>(stackTop_);
133
23.2M
        stackTop_ += sizeof(T) * count;
134
23.2M
        return ret;
135
23.2M
    }
rapidjson::GenericValue<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator> >* rapidjson::internal::Stack<rapidjson::CrtAllocator>::PushUnsafe<rapidjson::GenericValue<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator> > >(unsigned long)
Line
Count
Source
129
13.2M
    RAPIDJSON_FORCEINLINE T* PushUnsafe(size_t count = 1) {
130
13.2M
        RAPIDJSON_ASSERT(stackTop_);
131
13.2M
        RAPIDJSON_ASSERT(static_cast<std::ptrdiff_t>(sizeof(T) * count) <= (stackEnd_ - stackTop_));
132
13.2M
        T* ret = reinterpret_cast<T*>(stackTop_);
133
13.2M
        stackTop_ += sizeof(T) * count;
134
13.2M
        return ret;
135
13.2M
    }
char* rapidjson::internal::Stack<rapidjson::CrtAllocator>::PushUnsafe<char>(unsigned long)
Line
Count
Source
129
195M
    RAPIDJSON_FORCEINLINE T* PushUnsafe(size_t count = 1) {
130
195M
        RAPIDJSON_ASSERT(stackTop_);
131
195M
        RAPIDJSON_ASSERT(static_cast<std::ptrdiff_t>(sizeof(T) * count) <= (stackEnd_ - stackTop_));
132
195M
        T* ret = reinterpret_cast<T*>(stackTop_);
133
195M
        stackTop_ += sizeof(T) * count;
134
195M
        return ret;
135
195M
    }
136
137
    template<typename T>
138
3.73M
    T* Pop(size_t count) {
139
3.73M
        RAPIDJSON_ASSERT(GetSize() >= count * sizeof(T));
140
3.73M
        stackTop_ -= count * sizeof(T);
141
3.73M
        return reinterpret_cast<T*>(stackTop_);
142
3.73M
    }
char* rapidjson::internal::Stack<rapidjson::CrtAllocator>::Pop<char>(unsigned long)
Line
Count
Source
138
1.22M
    T* Pop(size_t count) {
139
1.22M
        RAPIDJSON_ASSERT(GetSize() >= count * sizeof(T));
140
1.22M
        stackTop_ -= count * sizeof(T);
141
1.22M
        return reinterpret_cast<T*>(stackTop_);
142
1.22M
    }
unsigned int* rapidjson::internal::Stack<rapidjson::CrtAllocator>::Pop<unsigned int>(unsigned long)
Line
Count
Source
138
1.66M
    T* Pop(size_t count) {
139
1.66M
        RAPIDJSON_ASSERT(GetSize() >= count * sizeof(T));
140
1.66M
        stackTop_ -= count * sizeof(T);
141
1.66M
        return reinterpret_cast<T*>(stackTop_);
142
1.66M
    }
rapidjson::GenericMember<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator> >* rapidjson::internal::Stack<rapidjson::CrtAllocator>::Pop<rapidjson::GenericMember<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator> > >(unsigned long)
Line
Count
Source
138
678k
    T* Pop(size_t count) {
139
678k
        RAPIDJSON_ASSERT(GetSize() >= count * sizeof(T));
140
678k
        stackTop_ -= count * sizeof(T);
141
678k
        return reinterpret_cast<T*>(stackTop_);
142
678k
    }
rapidjson::GenericValue<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator> >* rapidjson::internal::Stack<rapidjson::CrtAllocator>::Pop<rapidjson::GenericValue<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator> > >(unsigned long)
Line
Count
Source
138
163k
    T* Pop(size_t count) {
139
163k
        RAPIDJSON_ASSERT(GetSize() >= count * sizeof(T));
140
163k
        stackTop_ -= count * sizeof(T);
141
163k
        return reinterpret_cast<T*>(stackTop_);
142
163k
    }
143
144
    template<typename T>
145
2.80M
    T* Top() { 
146
2.80M
        RAPIDJSON_ASSERT(GetSize() >= sizeof(T));
147
2.80M
        return reinterpret_cast<T*>(stackTop_ - sizeof(T));
148
2.80M
    }
unsigned int* rapidjson::internal::Stack<rapidjson::CrtAllocator>::Top<unsigned int>()
Line
Count
Source
145
1.97M
    T* Top() { 
146
1.97M
        RAPIDJSON_ASSERT(GetSize() >= sizeof(T));
147
1.97M
        return reinterpret_cast<T*>(stackTop_ - sizeof(T));
148
1.97M
    }
rapidjson::GenericValue<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator> >* rapidjson::internal::Stack<rapidjson::CrtAllocator>::Top<rapidjson::GenericValue<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator> > >()
Line
Count
Source
145
832k
    T* Top() { 
146
832k
        RAPIDJSON_ASSERT(GetSize() >= sizeof(T));
147
832k
        return reinterpret_cast<T*>(stackTop_ - sizeof(T));
148
832k
    }
149
150
    template<typename T>
151
    const T* Top() const {
152
        RAPIDJSON_ASSERT(GetSize() >= sizeof(T));
153
        return reinterpret_cast<T*>(stackTop_ - sizeof(T));
154
    }
155
156
    template<typename T>
157
    T* End() { return reinterpret_cast<T*>(stackTop_); }
158
159
    template<typename T>
160
    const T* End() const { return reinterpret_cast<T*>(stackTop_); }
161
162
    template<typename T>
163
    T* Bottom() { return reinterpret_cast<T*>(stack_); }
164
165
    template<typename T>
166
    const T* Bottom() const { return reinterpret_cast<T*>(stack_); }
167
168
11.0k
    bool HasAllocator() const {
169
11.0k
        return allocator_ != 0;
170
11.0k
    }
171
172
0
    Allocator& GetAllocator() {
173
0
        RAPIDJSON_ASSERT(allocator_);
174
0
        return *allocator_;
175
0
    }
176
177
11.0k
    bool Empty() const { return stackTop_ == stack_; }
178
6.64M
    size_t GetSize() const { return static_cast<size_t>(stackTop_ - stack_); }
179
73.5k
    size_t GetCapacity() const { return static_cast<size_t>(stackEnd_ - stack_); }
180
181
private:
182
    template<typename T>
183
47.2k
    void Expand(size_t count) {
184
        // Only expand the capacity if the current stack exists. Otherwise just create a stack with initial capacity.
185
47.2k
        size_t newCapacity;
186
47.2k
        if (stack_ == 0) {
187
20.8k
            if (!allocator_)
188
20.8k
                ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator)();
189
20.8k
            newCapacity = initialCapacity_;
190
26.3k
        } else {
191
26.3k
            newCapacity = GetCapacity();
192
26.3k
            newCapacity += (newCapacity + 1) / 2;
193
26.3k
        }
194
47.2k
        size_t newSize = GetSize() + sizeof(T) * count;
195
47.2k
        if (newCapacity < newSize)
196
0
            newCapacity = newSize;
197
198
47.2k
        Resize(newCapacity);
199
47.2k
    }
void rapidjson::internal::Stack<rapidjson::CrtAllocator>::Expand<unsigned int>(unsigned long)
Line
Count
Source
183
11.5k
    void Expand(size_t count) {
184
        // Only expand the capacity if the current stack exists. Otherwise just create a stack with initial capacity.
185
11.5k
        size_t newCapacity;
186
11.5k
        if (stack_ == 0) {
187
10.0k
            if (!allocator_)
188
10.0k
                ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator)();
189
10.0k
            newCapacity = initialCapacity_;
190
10.0k
        } else {
191
1.45k
            newCapacity = GetCapacity();
192
1.45k
            newCapacity += (newCapacity + 1) / 2;
193
1.45k
        }
194
11.5k
        size_t newSize = GetSize() + sizeof(T) * count;
195
11.5k
        if (newCapacity < newSize)
196
0
            newCapacity = newSize;
197
198
11.5k
        Resize(newCapacity);
199
11.5k
    }
void rapidjson::internal::Stack<rapidjson::CrtAllocator>::Expand<rapidjson::GenericValue<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator> > >(unsigned long)
Line
Count
Source
183
14.8k
    void Expand(size_t count) {
184
        // Only expand the capacity if the current stack exists. Otherwise just create a stack with initial capacity.
185
14.8k
        size_t newCapacity;
186
14.8k
        if (stack_ == 0) {
187
10.6k
            if (!allocator_)
188
10.6k
                ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator)();
189
10.6k
            newCapacity = initialCapacity_;
190
10.6k
        } else {
191
4.18k
            newCapacity = GetCapacity();
192
4.18k
            newCapacity += (newCapacity + 1) / 2;
193
4.18k
        }
194
14.8k
        size_t newSize = GetSize() + sizeof(T) * count;
195
14.8k
        if (newCapacity < newSize)
196
0
            newCapacity = newSize;
197
198
14.8k
        Resize(newCapacity);
199
14.8k
    }
void rapidjson::internal::Stack<rapidjson::CrtAllocator>::Expand<char>(unsigned long)
Line
Count
Source
183
20.8k
    void Expand(size_t count) {
184
        // Only expand the capacity if the current stack exists. Otherwise just create a stack with initial capacity.
185
20.8k
        size_t newCapacity;
186
20.8k
        if (stack_ == 0) {
187
155
            if (!allocator_)
188
155
                ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator)();
189
155
            newCapacity = initialCapacity_;
190
20.7k
        } else {
191
20.7k
            newCapacity = GetCapacity();
192
20.7k
            newCapacity += (newCapacity + 1) / 2;
193
20.7k
        }
194
20.8k
        size_t newSize = GetSize() + sizeof(T) * count;
195
20.8k
        if (newCapacity < newSize)
196
0
            newCapacity = newSize;
197
198
20.8k
        Resize(newCapacity);
199
20.8k
    }
200
201
47.2k
    void Resize(size_t newCapacity) {
202
47.2k
        const size_t size = GetSize();  // Backup the current size
203
47.2k
        stack_ = static_cast<char*>(allocator_->Realloc(stack_, GetCapacity(), newCapacity));
204
47.2k
        stackTop_ = stack_ + size;
205
47.2k
        stackEnd_ = stack_ + newCapacity;
206
47.2k
    }
207
208
22.1k
    void Destroy() {
209
22.1k
        Allocator::Free(stack_);
210
22.1k
        RAPIDJSON_DELETE(ownAllocator_); // Only delete if it is owned by the stack
211
22.1k
    }
212
213
    // Prohibit copy constructor & assignment operator.
214
    Stack(const Stack&);
215
    Stack& operator=(const Stack&);
216
217
    Allocator* allocator_;
218
    Allocator* ownAllocator_;
219
    char *stack_;
220
    char *stackTop_;
221
    char *stackEnd_;
222
    size_t initialCapacity_;
223
};
224
225
} // namespace internal
226
RAPIDJSON_NAMESPACE_END
227
228
#if defined(__clang__)
229
RAPIDJSON_DIAG_POP
230
#endif
231
232
#endif // RAPIDJSON_STACK_H_