Minh Nguyen / ArduinoJson
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers CollectionImpl.hpp Source File

CollectionImpl.hpp

00001 // ArduinoJson - arduinojson.org
00002 // Copyright Benoit Blanchon 2014-2021
00003 // MIT License
00004 
00005 #pragma once
00006 
00007 #include <ArduinoJson/Collection/CollectionData.hpp>
00008 #include <ArduinoJson/Variant/VariantData.hpp>
00009 
00010 namespace ARDUINOJSON_NAMESPACE {
00011 
00012 inline bool variantEquals(const VariantData* a, const VariantData* b) {
00013   return variantCompare(a, b) == COMPARE_RESULT_EQUAL;
00014 }
00015 
00016 inline VariantSlot* CollectionData::addSlot(MemoryPool* pool) {
00017   VariantSlot* slot = pool->allocVariant();
00018   if (!slot)
00019     return 0;
00020 
00021   if (_tail) {
00022     _tail->setNextNotNull(slot);
00023     _tail = slot;
00024   } else {
00025     _head = slot;
00026     _tail = slot;
00027   }
00028 
00029   slot->clear();
00030   return slot;
00031 }
00032 
00033 inline VariantData* CollectionData::addElement(MemoryPool* pool) {
00034   return slotData(addSlot(pool));
00035 }
00036 
00037 template <typename TAdaptedString>
00038 inline VariantData* CollectionData::addMember(TAdaptedString key,
00039                                               MemoryPool* pool) {
00040   VariantSlot* slot = addSlot(pool);
00041   if (!slotSetKey(slot, key, pool)) {
00042     removeSlot(slot);
00043     return 0;
00044   }
00045   return slot->data();
00046 }
00047 
00048 inline void CollectionData::clear() {
00049   _head = 0;
00050   _tail = 0;
00051 }
00052 
00053 template <typename TAdaptedString>
00054 inline bool CollectionData::containsKey(const TAdaptedString& key) const {
00055   return getSlot(key) != 0;
00056 }
00057 
00058 inline bool CollectionData::copyFrom(const CollectionData& src,
00059                                      MemoryPool* pool) {
00060   clear();
00061   for (VariantSlot* s = src._head; s; s = s->next()) {
00062     VariantData* var;
00063     if (s->key() != 0) {
00064       if (s->ownsKey())
00065         var = addMember(RamStringAdapter(s->key()), pool);
00066       else
00067         var = addMember(ConstRamStringAdapter(s->key()), pool);
00068     } else {
00069       var = addElement(pool);
00070     }
00071     if (!var)
00072       return false;
00073     if (!var->copyFrom(*s->data(), pool))
00074       return false;
00075   }
00076   return true;
00077 }
00078 
00079 inline bool CollectionData::equalsObject(const CollectionData& other) const {
00080   size_t count = 0;
00081   for (VariantSlot* slot = _head; slot; slot = slot->next()) {
00082     VariantData* v1 = slot->data();
00083     VariantData* v2 = other.getMember(adaptString(slot->key()));
00084     if (!variantEquals(v1, v2))
00085       return false;
00086     count++;
00087   }
00088   return count == other.size();
00089 }
00090 
00091 inline bool CollectionData::equalsArray(const CollectionData& other) const {
00092   VariantSlot* s1 = _head;
00093   VariantSlot* s2 = other._head;
00094   for (;;) {
00095     if (s1 == s2)
00096       return true;
00097     if (!s1 || !s2)
00098       return false;
00099     if (!variantEquals(s1->data(), s2->data()))
00100       return false;
00101     s1 = s1->next();
00102     s2 = s2->next();
00103   }
00104 }
00105 
00106 template <typename TAdaptedString>
00107 inline VariantSlot* CollectionData::getSlot(TAdaptedString key) const {
00108   VariantSlot* slot = _head;
00109   while (slot) {
00110     if (key.equals(slot->key()))
00111       break;
00112     slot = slot->next();
00113   }
00114   return slot;
00115 }
00116 
00117 inline VariantSlot* CollectionData::getSlot(size_t index) const {
00118   return _head->next(index);
00119 }
00120 
00121 inline VariantSlot* CollectionData::getPreviousSlot(VariantSlot* target) const {
00122   VariantSlot* current = _head;
00123   while (current) {
00124     VariantSlot* next = current->next();
00125     if (next == target)
00126       return current;
00127     current = next;
00128   }
00129   return 0;
00130 }
00131 
00132 template <typename TAdaptedString>
00133 inline VariantData* CollectionData::getMember(TAdaptedString key) const {
00134   VariantSlot* slot = getSlot(key);
00135   return slot ? slot->data() : 0;
00136 }
00137 
00138 template <typename TAdaptedString>
00139 inline VariantData* CollectionData::getOrAddMember(TAdaptedString key,
00140                                                    MemoryPool* pool) {
00141   // ignore null key
00142   if (key.isNull())
00143     return 0;
00144 
00145   // search a matching key
00146   VariantSlot* slot = getSlot(key);
00147   if (slot)
00148     return slot->data();
00149 
00150   return addMember(key, pool);
00151 }
00152 
00153 inline VariantData* CollectionData::getElement(size_t index) const {
00154   VariantSlot* slot = getSlot(index);
00155   return slot ? slot->data() : 0;
00156 }
00157 
00158 inline VariantData* CollectionData::getOrAddElement(size_t index,
00159                                                     MemoryPool* pool) {
00160   VariantSlot* slot = _head;
00161   while (slot && index > 0) {
00162     slot = slot->next();
00163     index--;
00164   }
00165   if (!slot)
00166     index++;
00167   while (index > 0) {
00168     slot = addSlot(pool);
00169     index--;
00170   }
00171   return slotData(slot);
00172 }
00173 
00174 inline void CollectionData::removeSlot(VariantSlot* slot) {
00175   if (!slot)
00176     return;
00177   VariantSlot* prev = getPreviousSlot(slot);
00178   VariantSlot* next = slot->next();
00179   if (prev)
00180     prev->setNext(next);
00181   else
00182     _head = next;
00183   if (!next)
00184     _tail = prev;
00185 }
00186 
00187 inline void CollectionData::removeElement(size_t index) {
00188   removeSlot(getSlot(index));
00189 }
00190 
00191 inline size_t CollectionData::memoryUsage() const {
00192   size_t total = 0;
00193   for (VariantSlot* s = _head; s; s = s->next()) {
00194     total += sizeof(VariantSlot) + s->data()->memoryUsage();
00195     if (s->ownsKey())
00196       total += strlen(s->key()) + 1;
00197   }
00198   return total;
00199 }
00200 
00201 inline size_t CollectionData::nesting() const {
00202   size_t maxChildNesting = 0;
00203   for (VariantSlot* s = _head; s; s = s->next()) {
00204     size_t childNesting = s->data()->nesting();
00205     if (childNesting > maxChildNesting)
00206       maxChildNesting = childNesting;
00207   }
00208   return maxChildNesting + 1;
00209 }
00210 
00211 inline size_t CollectionData::size() const {
00212   return slotSize(_head);
00213 }
00214 
00215 template <typename T>
00216 inline void movePointer(T*& p, ptrdiff_t offset) {
00217   if (!p)
00218     return;
00219   p = reinterpret_cast<T*>(
00220       reinterpret_cast<void*>(reinterpret_cast<char*>(p) + offset));
00221   ARDUINOJSON_ASSERT(isAligned(p));
00222 }
00223 
00224 inline void CollectionData::movePointers(ptrdiff_t stringDistance,
00225                                          ptrdiff_t variantDistance) {
00226   movePointer(_head, variantDistance);
00227   movePointer(_tail, variantDistance);
00228   for (VariantSlot* slot = _head; slot; slot = slot->next())
00229     slot->movePointers(stringDistance, variantDistance);
00230 }
00231 
00232 }  // namespace ARDUINOJSON_NAMESPACE