• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

bblanchon / ArduinoJson / 4655935094

pending completion
4655935094

push

github

Benoit Blanchon
Remove unused `MemoryPool::_left`

5 of 5 new or added lines in 1 file covered. (100.0%)

3305 of 3322 relevant lines covered (99.49%)

6124.39 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

99.4
/src/ArduinoJson/Memory/MemoryPool.hpp
1
// ArduinoJson - https://arduinojson.org
2
// Copyright © 2014-2023, Benoit BLANCHON
3
// MIT License
4

5
#pragma once
6

7
#include <ArduinoJson/Memory/Alignment.hpp>
8
#include <ArduinoJson/Memory/Allocator.hpp>
9
#include <ArduinoJson/Polyfills/assert.hpp>
10
#include <ArduinoJson/Polyfills/mpl/max.hpp>
11
#include <ArduinoJson/Strings/StringAdapters.hpp>
12
#include <ArduinoJson/Variant/VariantSlot.hpp>
13

14
#include <string.h>  // memmove
15

16
ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
17

18
// Returns the size (in bytes) of an array with n elements.
19
constexpr size_t sizeofArray(size_t n) {
93✔
20
  return n * sizeof(VariantSlot);
93✔
21
}
22

23
// Returns the size (in bytes) of an object with n members.
24
constexpr size_t sizeofObject(size_t n) {
161✔
25
  return n * sizeof(VariantSlot);
161✔
26
}
27

28
struct StringNode {
29
  struct StringNode* next;
30
  uint16_t length;
31
  uint16_t references;
32
  char data[1];
33
};
34

35
// Returns the size (in bytes) of an string with n characters.
36
constexpr size_t sizeofString(size_t n) {
3,513✔
37
  return n + 1 + offsetof(StringNode, data);
3,513✔
38
}
39

40
class MemoryPool {
41
 public:
42
  MemoryPool(size_t capa, Allocator* allocator = DefaultAllocator::instance())
1,982✔
43
      : _allocator(allocator), _overflowed(false) {
1,982✔
44
    allocPool(addPadding(capa));
1,982✔
45
  }
1,982✔
46

47
  ~MemoryPool() {
3,964✔
48
    deallocAllStrings();
1,982✔
49
    deallocPool();
1,982✔
50
  }
1,982✔
51

52
  MemoryPool(const MemoryPool&) = delete;
53
  MemoryPool& operator=(const MemoryPool& src) = delete;
54

55
  MemoryPool& operator=(MemoryPool&& src) {
7✔
56
    deallocAllStrings();
7✔
57
    deallocPool();
7✔
58
    _allocator = src._allocator;
7✔
59
    _begin = src._begin;
7✔
60
    _end = src._end;
7✔
61
    _right = src._right;
7✔
62
    _overflowed = src._overflowed;
7✔
63
    src._begin = src._end = src._right = nullptr;
7✔
64
    _strings = src._strings;
7✔
65
    src._strings = nullptr;
7✔
66
    return *this;
7✔
67
  }
68

69
  Allocator* allocator() const {
6✔
70
    return _allocator;
6✔
71
  }
72

73
  void reallocPool(size_t requiredSize) {
3✔
74
    size_t capa = addPadding(requiredSize);
3✔
75
    if (capa == capacity())
3✔
76
      return;
1✔
77
    _allocator->deallocate(_begin);
2✔
78
    allocPool(requiredSize);
2✔
79
  }
80

81
  void* buffer() {
82
    return _begin;  // NOLINT(clang-analyzer-unix.Malloc)
83
                    // movePointers() alters this pointer
84
  }
85

86
  // Gets the capacity of the memoryPool in bytes
87
  size_t capacity() const {
33✔
88
    return size_t(_end - _begin);
33✔
89
  }
90

91
  size_t size() const {
273✔
92
    size_t total = size_t(_end - _right);
273✔
93
    for (auto node = _strings; node; node = node->next)
517✔
94
      total += sizeofString(node->length);
244✔
95
    return total;
273✔
96
  }
97

98
  bool overflowed() const {
66,960✔
99
    return _overflowed;
66,960✔
100
  }
101

102
  VariantSlot* allocVariant() {
70,870✔
103
    return allocRight<VariantSlot>();
70,870✔
104
  }
105

106
  template <typename TAdaptedString>
107
  const char* saveString(TAdaptedString str) {
183✔
108
    if (str.isNull())
183✔
109
      return 0;
1✔
110

111
    auto node = findString(str);
182✔
112
    if (node) {
182✔
113
      node->references++;
12✔
114
      return node->data;
12✔
115
    }
116

117
    size_t n = str.size();
170✔
118

119
    node = allocString(n);
170✔
120
    if (!node)
170✔
121
      return nullptr;
5✔
122

123
    stringGetChars(str, node->data, n);
165✔
124
    node->data[n] = 0;  // force NUL terminator
165✔
125
    addStringToList(node);
165✔
126
    return node->data;
165✔
127
  }
128

129
  void addStringToList(StringNode* node) {
1,493✔
130
    ARDUINOJSON_ASSERT(node != nullptr);
131
    node->references = 1;
1,493✔
132
    node->next = _strings;
1,493✔
133
    _strings = node;
1,493✔
134
  }
1,493✔
135

136
  template <typename TAdaptedString>
137
  StringNode* findString(const TAdaptedString& str) const {
1,841✔
138
    for (auto node = _strings; node; node = node->next) {
16,016✔
139
      if (stringEquals(str, adaptString(node->data, node->length)))
14,518✔
140
        return node;
343✔
141
    }
142
    return nullptr;
1,498✔
143
  }
144

145
  StringNode* allocString(size_t length) {
1,634✔
146
    auto node = reinterpret_cast<StringNode*>(
147
        _allocator->allocate(sizeofString(length)));
1,634✔
148
    if (node) {
1,634✔
149
      node->length = uint16_t(length);
1,611✔
150
      node->references = 1;
1,611✔
151
    } else {
152
      _overflowed = true;
23✔
153
    }
154
    return node;
1,634✔
155
  }
156

157
  StringNode* reallocString(StringNode* node, size_t length) {
1,423✔
158
    ARDUINOJSON_ASSERT(node != nullptr);
159
    auto newNode = reinterpret_cast<StringNode*>(
160
        _allocator->reallocate(node, sizeofString(length)));
1,423✔
161
    if (newNode) {
1,423✔
162
      newNode->length = uint16_t(length);
1,420✔
163
    } else {
164
      _overflowed = true;
3✔
165
      _allocator->deallocate(node);
3✔
166
    }
167
    return newNode;
1,423✔
168
  }
169

170
  void deallocString(StringNode* node) {
1,605✔
171
    _allocator->deallocate(node);
1,605✔
172
  }
1,605✔
173

174
  void dereferenceString(const char* s) {
3✔
175
    StringNode* prev = nullptr;
3✔
176
    for (auto node = _strings; node; node = node->next) {
6✔
177
      if (node->data == s) {
6✔
178
        if (--node->references == 0) {
3✔
179
          if (prev)
3✔
180
            prev->next = node->next;
3✔
181
          else
182
            _strings = node->next;
×
183
          _allocator->deallocate(node);
3✔
184
        }
185
        return;
3✔
186
      }
187
      prev = node;
3✔
188
    }
189
  }
190

191
  void clear() {
1,756✔
192
    _right = _end;
1,756✔
193
    _overflowed = false;
1,756✔
194
    deallocAllStrings();
1,756✔
195
  }
1,756✔
196

197
  bool canAlloc(size_t bytes) const {
70,870✔
198
    return _begin + bytes <= _right;
70,870✔
199
  }
200

201
  bool owns(void* p) const {
202
    return _begin <= p && p < _end;
203
  }
204

205
  // Workaround for missing placement new
206
  void* operator new(size_t, void* p) {
207
    return p;
208
  }
209

210
  void shrinkToFit(VariantData& variant) {
15✔
211
    ptrdiff_t bytes_reclaimed = squash();
15✔
212
    if (bytes_reclaimed == 0)
15✔
213
      return;
2✔
214

215
    void* old_ptr = _begin;
13✔
216
    void* new_ptr = _allocator->reallocate(old_ptr, capacity());
13✔
217

218
    ptrdiff_t ptr_offset =
13✔
219
        static_cast<char*>(new_ptr) - static_cast<char*>(old_ptr);
220

221
    movePointers(ptr_offset);
13✔
222
    reinterpret_cast<VariantSlot&>(variant).movePointers(ptr_offset -
13✔
223
                                                         bytes_reclaimed);
224
  }
225

226
 private:
227
  ptrdiff_t squash() {
15✔
228
    char* new_right = addPadding(_begin);
15✔
229
    if (new_right >= _right)
15✔
230
      return 0;
2✔
231

232
    size_t right_size = static_cast<size_t>(_end - _right);
13✔
233
    memmove(new_right, _right, right_size);
13✔
234

235
    ptrdiff_t bytes_reclaimed = _right - new_right;
13✔
236
    _right = new_right;
13✔
237
    _end = new_right + right_size;
13✔
238
    return bytes_reclaimed;
13✔
239
  }
240

241
  // Move all pointers together
242
  // This funcion is called after a realloc.
243
  void movePointers(ptrdiff_t offset) {
13✔
244
    _begin += offset;
13✔
245
    _right += offset;
13✔
246
    _end += offset;
13✔
247
  }
13✔
248

249
  void checkInvariants() {
250
    ARDUINOJSON_ASSERT(_begin <= _right);
251
    ARDUINOJSON_ASSERT(_right <= _end);
252
    ARDUINOJSON_ASSERT(isAligned(_right));
253
  }
254

255
  void deallocAllStrings() {
5,235✔
256
    while (_strings) {
5,235✔
257
      auto node = _strings;
1,490✔
258
      _strings = node->next;
1,490✔
259
      deallocString(node);
1,490✔
260
    }
261
  }
3,745✔
262

263
  template <typename T>
264
  T* allocRight() {
70,870✔
265
    return reinterpret_cast<T*>(allocRight(sizeof(T)));
70,870✔
266
  }
267

268
  void* allocRight(size_t bytes) {
70,870✔
269
    if (!canAlloc(bytes)) {
70,870✔
270
      _overflowed = true;
28✔
271
      return 0;
28✔
272
    }
273
    _right -= bytes;
70,842✔
274
    return _right;
70,842✔
275
  }
276

277
  void allocPool(size_t capa) {
1,984✔
278
    auto buf = capa ? reinterpret_cast<char*>(_allocator->allocate(capa)) : 0;
1,984✔
279
    _begin = buf;
1,984✔
280
    _end = _right = buf ? buf + capa : 0;
1,984✔
281
    ARDUINOJSON_ASSERT(isAligned(_begin));
282
    ARDUINOJSON_ASSERT(isAligned(_right));
283
    ARDUINOJSON_ASSERT(isAligned(_end));
284
  }
1,984✔
285

286
  void deallocPool() {
1,989✔
287
    if (_begin)
1,989✔
288
      _allocator->deallocate(_begin);
1,928✔
289
  }
1,989✔
290

291
  Allocator* _allocator;
292
  char *_begin, *_right, *_end;
293
  bool _overflowed;
294
  StringNode* _strings = nullptr;
295
};
296

297
template <typename TAdaptedString, typename TCallback>
298
bool storeString(MemoryPool* pool, TAdaptedString str,
159✔
299
                 StringStoragePolicy::Copy, TCallback callback) {
300
  const char* copy = pool->saveString(str);
159✔
301
  JsonString storedString(copy, str.size(), JsonString::Copied);
159✔
302
  callback(storedString);
159✔
303
  return copy != 0;
159✔
304
}
305

306
template <typename TAdaptedString, typename TCallback>
307
bool storeString(MemoryPool*, TAdaptedString str, StringStoragePolicy::Link,
1,014✔
308
                 TCallback callback) {
309
  JsonString storedString(str.data(), str.size(), JsonString::Linked);
1,014✔
310
  callback(storedString);
1,014✔
311
  return !str.isNull();
1,014✔
312
}
313

314
template <typename TAdaptedString, typename TCallback>
315
bool storeString(MemoryPool* pool, TAdaptedString str,
31✔
316
                 StringStoragePolicy::LinkOrCopy policy, TCallback callback) {
317
  if (policy.link)
31✔
318
    return storeString(pool, str, StringStoragePolicy::Link(), callback);
12✔
319
  else
320
    return storeString(pool, str, StringStoragePolicy::Copy(), callback);
19✔
321
}
322

323
template <typename TAdaptedString, typename TCallback>
324
bool storeString(MemoryPool* pool, TAdaptedString str, TCallback callback) {
1,173✔
325
  return storeString(pool, str, str.storagePolicy(), callback);
1,173✔
326
}
327

328
ARDUINOJSON_END_PRIVATE_NAMESPACE
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc