Minh Nguyen / ArduinoJson
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers VariantSlot.hpp Source File

VariantSlot.hpp

00001 // ArduinoJson - arduinojson.org
00002 // Copyright Benoit Blanchon 2014-2021
00003 // MIT License
00004 
00005 #pragma once
00006 
00007 #include <ArduinoJson/Polyfills/integer.hpp>
00008 #include <ArduinoJson/Polyfills/limits.hpp>
00009 #include <ArduinoJson/Polyfills/type_traits.hpp>
00010 #include <ArduinoJson/Strings/StoragePolicy.hpp>
00011 #include <ArduinoJson/Variant/VariantContent.hpp>
00012 
00013 namespace ARDUINOJSON_NAMESPACE {
00014 
00015 typedef int_t<ARDUINOJSON_SLOT_OFFSET_SIZE * 8>::type VariantSlotDiff;
00016 
00017 class VariantSlot {
00018   // CAUTION: same layout as VariantData
00019   // we cannot use composition because it adds padding
00020   // (+20% on ESP8266 for example)
00021   VariantContent _content;
00022   uint8_t _flags;
00023   VariantSlotDiff _next;
00024   const char* _key;
00025 
00026  public:
00027   // Must be a POD!
00028   // - no constructor
00029   // - no destructor
00030   // - no virtual
00031   // - no inheritance
00032 
00033   VariantData* data() {
00034     return reinterpret_cast<VariantData*>(&_content);
00035   }
00036 
00037   const VariantData* data() const {
00038     return reinterpret_cast<const VariantData*>(&_content);
00039   }
00040 
00041   VariantSlot* next() {
00042     return _next ? this + _next : 0;
00043   }
00044 
00045   const VariantSlot* next() const {
00046     return const_cast<VariantSlot*>(this)->next();
00047   }
00048 
00049   VariantSlot* next(size_t distance) {
00050     VariantSlot* slot = this;
00051     while (distance--) {
00052       if (!slot->_next)
00053         return 0;
00054       slot += slot->_next;
00055     }
00056     return slot;
00057   }
00058 
00059   const VariantSlot* next(size_t distance) const {
00060     return const_cast<VariantSlot*>(this)->next(distance);
00061   }
00062 
00063   void setNext(VariantSlot* slot) {
00064     ARDUINOJSON_ASSERT(!slot || slot - this >=
00065                                     numeric_limits<VariantSlotDiff>::lowest());
00066     ARDUINOJSON_ASSERT(!slot || slot - this <=
00067                                     numeric_limits<VariantSlotDiff>::highest());
00068     _next = VariantSlotDiff(slot ? slot - this : 0);
00069   }
00070 
00071   void setNextNotNull(VariantSlot* slot) {
00072     ARDUINOJSON_ASSERT(slot != 0);
00073     ARDUINOJSON_ASSERT(slot - this >=
00074                        numeric_limits<VariantSlotDiff>::lowest());
00075     ARDUINOJSON_ASSERT(slot - this <=
00076                        numeric_limits<VariantSlotDiff>::highest());
00077     _next = VariantSlotDiff(slot - this);
00078   }
00079 
00080   void setKey(const char* k, storage_policies::store_by_copy) {
00081     ARDUINOJSON_ASSERT(k != NULL);
00082     _flags |= KEY_IS_OWNED;
00083     _key = k;
00084   }
00085 
00086   void setKey(const char* k, storage_policies::store_by_address) {
00087     ARDUINOJSON_ASSERT(k != NULL);
00088     _flags &= VALUE_MASK;
00089     _key = k;
00090   }
00091 
00092   const char* key() const {
00093     return _key;
00094   }
00095 
00096   bool ownsKey() const {
00097     return (_flags & KEY_IS_OWNED) != 0;
00098   }
00099 
00100   void clear() {
00101     _next = 0;
00102     _flags = 0;
00103     _key = 0;
00104   }
00105 
00106   void movePointers(ptrdiff_t stringDistance, ptrdiff_t variantDistance) {
00107     if (_flags & KEY_IS_OWNED)
00108       _key += stringDistance;
00109     if (_flags & VALUE_IS_OWNED)
00110       _content.asString += stringDistance;
00111     if (_flags & COLLECTION_MASK)
00112       _content.asCollection.movePointers(stringDistance, variantDistance);
00113   }
00114 };
00115 
00116 }  // namespace ARDUINOJSON_NAMESPACE