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

bblanchon / ArduinoJson / 9550679578

17 Jun 2024 03:44PM CUT coverage: 99.484%. Remained the same
9550679578

push

github

bblanchon
Add DevContainer files for Clang 13 to 17

3854 of 3874 relevant lines covered (99.48%)

10863.07 hits per line

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

97.87
/src/ArduinoJson/Memory/VariantPoolList.hpp
1
// ArduinoJson - https://arduinojson.org
2
// Copyright © 2014-2024, Benoit BLANCHON
3
// MIT License
4

5
#pragma once
6

7
#include <ArduinoJson/Memory/VariantPool.hpp>
8
#include <ArduinoJson/Polyfills/assert.hpp>
9

10
ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
11

12
using PoolCount = SlotId;
13

14
class VariantPoolList {
15
 public:
16
  VariantPoolList() = default;
2,008✔
17

18
  ~VariantPoolList() {
2,008✔
19
    ARDUINOJSON_ASSERT(count_ == 0);
20
  }
2,008✔
21

22
  friend void swap(VariantPoolList& a, VariantPoolList& b) {
11✔
23
    bool aUsedPreallocated = a.pools_ == a.preallocatedPools_;
11✔
24
    bool bUsedPreallocated = b.pools_ == b.preallocatedPools_;
11✔
25

26
    // Who is using preallocated pools?
27
    if (aUsedPreallocated && bUsedPreallocated) {
11✔
28
      // both of us => swap preallocated pools
29
      for (PoolCount i = 0; i < ARDUINOJSON_INITIAL_POOL_COUNT; i++)
40✔
30
        swap_(a.preallocatedPools_[i], b.preallocatedPools_[i]);
40✔
31
    } else if (bUsedPreallocated) {
3✔
32
      // only b => copy b's preallocated pools and give him a's pointer
33
      for (PoolCount i = 0; i < b.count_; i++)
2✔
34
        a.preallocatedPools_[i] = b.preallocatedPools_[i];
1✔
35
      b.pools_ = a.pools_;
1✔
36
      a.pools_ = a.preallocatedPools_;
1✔
37
    } else if (aUsedPreallocated) {
2✔
38
      // only a => copy a's preallocated pools and give him b's pointer
39
      for (PoolCount i = 0; i < a.count_; i++)
2✔
40
        b.preallocatedPools_[i] = a.preallocatedPools_[i];
1✔
41
      a.pools_ = b.pools_;
1✔
42
      b.pools_ = b.preallocatedPools_;
1✔
43
    } else {
44
      // neither => swap pointers
45
      swap_(a.pools_, b.pools_);
1✔
46
    }
47

48
    swap_(a.count_, b.count_);
11✔
49
    swap_(a.capacity_, b.capacity_);
11✔
50
    swap_(a.freeList_, b.freeList_);
11✔
51
  }
11✔
52

53
  VariantPoolList& operator=(VariantPoolList&& src) {
54
    ARDUINOJSON_ASSERT(count_ == 0);
55
    if (src.pools_ == src.preallocatedPools_) {
56
      memcpy(preallocatedPools_, src.preallocatedPools_,
57
             sizeof(preallocatedPools_));
58
      pools_ = preallocatedPools_;
59
    } else {
60
      pools_ = src.pools_;
61
      src.pools_ = nullptr;
62
    }
63
    count_ = src.count_;
64
    capacity_ = src.capacity_;
65
    src.count_ = 0;
66
    src.capacity_ = 0;
67
    return *this;
68
  }
69

70
  SlotWithId allocSlot(Allocator* allocator) {
71,869✔
71
    // try to allocate from free list
72
    if (freeList_ != NULL_SLOT) {
71,869✔
73
      return allocFromFreeList();
131✔
74
    }
75

76
    // try to allocate from last pool (other pools are full)
77
    if (count_) {
71,738✔
78
      auto slot = allocFromLastPool();
70,539✔
79
      if (slot)
70,539✔
80
        return slot;
69,974✔
81
    }
82

83
    // create a new pool and try again
84
    auto pool = addPool(allocator);
1,764✔
85
    if (!pool)
1,764✔
86
      return {};
10✔
87

88
    return allocFromLastPool();
1,754✔
89
  }
90

91
  void freeSlot(SlotWithId slot);
92

93
  VariantSlot* getSlot(SlotId id) const {
351,572✔
94
    if (id == NULL_SLOT)
351,572✔
95
      return nullptr;
4,498✔
96
    auto poolIndex = SlotId(id / ARDUINOJSON_POOL_CAPACITY);
347,074✔
97
    auto indexInPool = SlotId(id % ARDUINOJSON_POOL_CAPACITY);
347,074✔
98
    ARDUINOJSON_ASSERT(poolIndex < count_);
99
    return pools_[poolIndex].getSlot(indexInPool);
347,074✔
100
  }
101

102
  void clear(Allocator* allocator) {
3,891✔
103
    for (PoolCount i = 0; i < count_; i++)
5,645✔
104
      pools_[i].destroy(allocator);
1,754✔
105
    count_ = 0;
3,891✔
106
    freeList_ = NULL_SLOT;
3,891✔
107
    if (pools_ != preallocatedPools_) {
3,891✔
108
      allocator->deallocate(pools_);
7✔
109
      pools_ = preallocatedPools_;
7✔
110
      capacity_ = ARDUINOJSON_INITIAL_POOL_COUNT;
7✔
111
    }
112
  }
3,891✔
113

114
  SlotCount usage() const {
14✔
115
    SlotCount total = 0;
14✔
116
    for (PoolCount i = 0; i < count_; i++)
17✔
117
      total = SlotCount(total + pools_[i].usage());
3✔
118
    return total;
14✔
119
  }
120

121
  void shrinkToFit(Allocator* allocator) {
1,329✔
122
    if (count_ > 0)
1,329✔
123
      pools_[count_ - 1].shrinkToFit(allocator);
505✔
124
    if (pools_ != preallocatedPools_ && count_ != capacity_) {
1,329✔
125
      pools_ = static_cast<VariantPool*>(
1✔
126
          allocator->reallocate(pools_, count_ * sizeof(VariantPool)));
1✔
127
      ARDUINOJSON_ASSERT(pools_ != nullptr);  // realloc to smaller can't fail
128
      capacity_ = count_;
1✔
129
    }
130
  }
1,329✔
131

132
 private:
133
  SlotWithId allocFromFreeList();
134

135
  SlotWithId allocFromLastPool() {
72,293✔
136
    ARDUINOJSON_ASSERT(count_ > 0);
137
    auto poolIndex = SlotId(count_ - 1);
72,293✔
138
    auto slot = pools_[poolIndex].allocSlot();
72,293✔
139
    if (!slot)
72,293✔
140
      return {};
592✔
141
    return {slot, SlotId(poolIndex * ARDUINOJSON_POOL_CAPACITY + slot.id())};
71,701✔
142
  }
143

144
  VariantPool* addPool(Allocator* allocator) {
1,764✔
145
    if (count_ == capacity_ && !increaseCapacity(allocator))
1,764✔
146
      return nullptr;
10✔
147
    auto pool = &pools_[count_++];
1,754✔
148
    SlotCount poolCapacity = ARDUINOJSON_POOL_CAPACITY;
1,754✔
149
    if (count_ == maxPools)  // last pool is smaller because of NULL_SLOT
1,754✔
150
      poolCapacity--;
1✔
151
    pool->create(poolCapacity, allocator);
1,754✔
152
    return pool;
1,754✔
153
  }
154

155
  bool increaseCapacity(Allocator* allocator) {
24✔
156
    if (capacity_ == maxPools)
24✔
157
      return false;
10✔
158
    void* newPools;
159
    auto newCapacity = PoolCount(capacity_ * 2);
14✔
160

161
    if (pools_ == preallocatedPools_) {
14✔
162
      newPools = allocator->allocate(newCapacity * sizeof(VariantPool));
7✔
163
      if (!newPools)
7✔
164
        return false;
×
165
      memcpy(newPools, preallocatedPools_, sizeof(preallocatedPools_));
7✔
166
    } else {
167
      newPools =
168
          allocator->reallocate(pools_, newCapacity * sizeof(VariantPool));
7✔
169
      if (!newPools)
7✔
170
        return false;
×
171
    }
172

173
    pools_ = static_cast<VariantPool*>(newPools);
14✔
174
    capacity_ = newCapacity;
14✔
175
    return true;
14✔
176
  }
177

178
  VariantPool preallocatedPools_[ARDUINOJSON_INITIAL_POOL_COUNT];
179
  VariantPool* pools_ = preallocatedPools_;
180
  PoolCount count_ = 0;
181
  PoolCount capacity_ = ARDUINOJSON_INITIAL_POOL_COUNT;
182
  SlotId freeList_ = NULL_SLOT;
183

184
 public:
185
  static const PoolCount maxPools =
186
      PoolCount(NULL_SLOT / ARDUINOJSON_POOL_CAPACITY + 1);
187
};
188

189
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