Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
VariantData.hpp
00001 // ArduinoJson - arduinojson.org 00002 // Copyright Benoit Blanchon 2014-2021 00003 // MIT License 00004 00005 #pragma once 00006 00007 #include <ArduinoJson/Memory/MemoryPool.hpp> 00008 #include <ArduinoJson/Misc/SerializedValue.hpp> 00009 #include <ArduinoJson/Numbers/convertNumber.hpp> 00010 #include <ArduinoJson/Strings/RamStringAdapter.hpp> 00011 #include <ArduinoJson/Variant/VariantContent.hpp> 00012 00013 // VariantData can't have a constructor (to be a POD), so we have no way to fix 00014 // this warning 00015 #if defined(__GNUC__) 00016 #if __GNUC__ >= 7 00017 #pragma GCC diagnostic push 00018 #pragma GCC diagnostic ignored "-Wmaybe-uninitialized" 00019 #pragma GCC diagnostic ignored "-Wuninitialized" 00020 #endif 00021 #endif 00022 00023 namespace ARDUINOJSON_NAMESPACE { 00024 00025 class VariantData { 00026 VariantContent _content; // must be first to allow cast from array to variant 00027 uint8_t _flags; 00028 00029 public: 00030 // Must be a POD! 00031 // - no constructor 00032 // - no destructor 00033 // - no virtual 00034 // - no inheritance 00035 void init() { 00036 _flags = 0; 00037 } 00038 00039 template <typename TVisitor> 00040 typename TVisitor::result_type accept(TVisitor &visitor) const { 00041 switch (type()) { 00042 case VALUE_IS_FLOAT: 00043 return visitor.visitFloat(_content.asFloat); 00044 00045 case VALUE_IS_ARRAY: 00046 return visitor.visitArray(_content.asCollection); 00047 00048 case VALUE_IS_OBJECT: 00049 return visitor.visitObject(_content.asCollection); 00050 00051 case VALUE_IS_LINKED_STRING: 00052 case VALUE_IS_OWNED_STRING: 00053 return visitor.visitString(_content.asString); 00054 00055 case VALUE_IS_OWNED_RAW: 00056 case VALUE_IS_LINKED_RAW: 00057 return visitor.visitRawJson(_content.asRaw.data, _content.asRaw.size); 00058 00059 case VALUE_IS_NEGATIVE_INTEGER: 00060 return visitor.visitNegativeInteger(_content.asInteger); 00061 00062 case VALUE_IS_POSITIVE_INTEGER: 00063 return visitor.visitPositiveInteger(_content.asInteger); 00064 00065 case VALUE_IS_BOOLEAN: 00066 return visitor.visitBoolean(_content.asInteger != 0); 00067 00068 default: 00069 return visitor.visitNull(); 00070 } 00071 } 00072 00073 template <typename T> 00074 T asIntegral() const; 00075 00076 template <typename T> 00077 T asFloat() const; 00078 00079 const char *asString() const; 00080 00081 bool asBoolean() const; 00082 00083 CollectionData *asArray() { 00084 return isArray() ? &_content.asCollection : 0; 00085 } 00086 00087 const CollectionData *asArray() const { 00088 return const_cast<VariantData *>(this)->asArray(); 00089 } 00090 00091 CollectionData *asObject() { 00092 return isObject() ? &_content.asCollection : 0; 00093 } 00094 00095 const CollectionData *asObject() const { 00096 return const_cast<VariantData *>(this)->asObject(); 00097 } 00098 00099 bool copyFrom(const VariantData &src, MemoryPool *pool) { 00100 switch (src.type()) { 00101 case VALUE_IS_ARRAY: 00102 return toArray().copyFrom(src._content.asCollection, pool); 00103 case VALUE_IS_OBJECT: 00104 return toObject().copyFrom(src._content.asCollection, pool); 00105 case VALUE_IS_OWNED_STRING: 00106 return setString(RamStringAdapter(src._content.asString), pool); 00107 case VALUE_IS_OWNED_RAW: 00108 return setOwnedRaw( 00109 serialized(src._content.asRaw.data, src._content.asRaw.size), pool); 00110 default: 00111 setType(src.type()); 00112 _content = src._content; 00113 return true; 00114 } 00115 } 00116 00117 bool isArray() const { 00118 return (_flags & VALUE_IS_ARRAY) != 0; 00119 } 00120 00121 bool isBoolean() const { 00122 return type() == VALUE_IS_BOOLEAN; 00123 } 00124 00125 bool isCollection() const { 00126 return (_flags & COLLECTION_MASK) != 0; 00127 } 00128 00129 template <typename T> 00130 bool isInteger() const { 00131 switch (type()) { 00132 case VALUE_IS_POSITIVE_INTEGER: 00133 return canStorePositiveInteger<T>(_content.asInteger); 00134 00135 case VALUE_IS_NEGATIVE_INTEGER: 00136 return canStoreNegativeInteger<T>(_content.asInteger); 00137 00138 default: 00139 return false; 00140 } 00141 } 00142 00143 bool isFloat() const { 00144 return type() == VALUE_IS_FLOAT || type() == VALUE_IS_POSITIVE_INTEGER || 00145 type() == VALUE_IS_NEGATIVE_INTEGER; 00146 } 00147 00148 bool isString() const { 00149 return type() == VALUE_IS_LINKED_STRING || type() == VALUE_IS_OWNED_STRING; 00150 } 00151 00152 bool isObject() const { 00153 return (_flags & VALUE_IS_OBJECT) != 0; 00154 } 00155 00156 bool isNull() const { 00157 return type() == VALUE_IS_NULL; 00158 } 00159 00160 bool isEnclosed() const { 00161 return !isFloat(); 00162 } 00163 00164 void remove(size_t index) { 00165 if (isArray()) 00166 _content.asCollection.removeElement(index); 00167 } 00168 00169 template <typename TAdaptedString> 00170 void remove(TAdaptedString key) { 00171 if (isObject()) 00172 _content.asCollection.removeMember(key); 00173 } 00174 00175 void setBoolean(bool value) { 00176 setType(VALUE_IS_BOOLEAN); 00177 _content.asInteger = static_cast<UInt>(value); 00178 } 00179 00180 void setFloat(Float value) { 00181 setType(VALUE_IS_FLOAT); 00182 _content.asFloat = value; 00183 } 00184 00185 void setLinkedRaw(SerializedValue<const char *> value) { 00186 if (value.data()) { 00187 setType(VALUE_IS_LINKED_RAW); 00188 _content.asRaw.data = value.data(); 00189 _content.asRaw.size = value.size(); 00190 } else { 00191 setType(VALUE_IS_NULL); 00192 } 00193 } 00194 00195 template <typename T> 00196 bool setOwnedRaw(SerializedValue<T> value, MemoryPool *pool) { 00197 const char *dup = pool->saveString(adaptString(value.data(), value.size())); 00198 if (dup) { 00199 setType(VALUE_IS_OWNED_RAW); 00200 _content.asRaw.data = dup; 00201 _content.asRaw.size = value.size(); 00202 return true; 00203 } else { 00204 setType(VALUE_IS_NULL); 00205 return false; 00206 } 00207 } 00208 00209 template <typename T> 00210 typename enable_if<is_unsigned<T>::value>::type setInteger(T value) { 00211 setUnsignedInteger(value); 00212 } 00213 00214 template <typename T> 00215 typename enable_if<is_signed<T>::value>::type setInteger(T value) { 00216 setSignedInteger(value); 00217 } 00218 00219 template <typename T> 00220 void setSignedInteger(T value) { 00221 if (value >= 0) { 00222 setPositiveInteger(static_cast<UInt>(value)); 00223 } else { 00224 setNegativeInteger(~static_cast<UInt>(value) + 1); 00225 } 00226 } 00227 00228 void setUnsignedInteger(UInt value) { 00229 setType(VALUE_IS_POSITIVE_INTEGER); 00230 _content.asInteger = static_cast<UInt>(value); 00231 } 00232 00233 void setPositiveInteger(UInt value) { 00234 setType(VALUE_IS_POSITIVE_INTEGER); 00235 _content.asInteger = value; 00236 } 00237 00238 void setNegativeInteger(UInt value) { 00239 setType(VALUE_IS_NEGATIVE_INTEGER); 00240 _content.asInteger = value; 00241 } 00242 00243 void setNull() { 00244 setType(VALUE_IS_NULL); 00245 } 00246 00247 void setStringPointer(const char *s, storage_policies::store_by_copy) { 00248 setType(VALUE_IS_OWNED_STRING); 00249 _content.asString = s; 00250 } 00251 00252 void setStringPointer(const char *s, storage_policies::store_by_address) { 00253 setType(VALUE_IS_LINKED_STRING); 00254 _content.asString = s; 00255 } 00256 00257 template <typename TAdaptedString> 00258 bool setString(TAdaptedString value, MemoryPool *pool) { 00259 return setString(value, pool, typename TAdaptedString::storage_policy()); 00260 } 00261 00262 template <typename TAdaptedString> 00263 inline bool setString(TAdaptedString value, MemoryPool *pool, 00264 storage_policies::decide_at_runtime) { 00265 if (value.isStatic()) 00266 return setString(value, pool, storage_policies::store_by_address()); 00267 else 00268 return setString(value, pool, storage_policies::store_by_copy()); 00269 } 00270 00271 template <typename TAdaptedString> 00272 inline bool setString(TAdaptedString value, MemoryPool *, 00273 storage_policies::store_by_address) { 00274 if (value.isNull()) 00275 setNull(); 00276 else 00277 setStringPointer(value.data(), storage_policies::store_by_address()); 00278 return true; 00279 } 00280 00281 template <typename TAdaptedString> 00282 inline bool setString(TAdaptedString value, MemoryPool *pool, 00283 storage_policies::store_by_copy) { 00284 if (value.isNull()) { 00285 setNull(); 00286 return true; 00287 } 00288 const char *copy = pool->saveString(value); 00289 if (!copy) { 00290 setNull(); 00291 return false; 00292 } 00293 setStringPointer(copy, storage_policies::store_by_copy()); 00294 return true; 00295 } 00296 00297 CollectionData &toArray() { 00298 setType(VALUE_IS_ARRAY); 00299 _content.asCollection.clear(); 00300 return _content.asCollection; 00301 } 00302 00303 CollectionData &toObject() { 00304 setType(VALUE_IS_OBJECT); 00305 _content.asCollection.clear(); 00306 return _content.asCollection; 00307 } 00308 00309 size_t memoryUsage() const { 00310 switch (type()) { 00311 case VALUE_IS_OWNED_STRING: 00312 return strlen(_content.asString) + 1; 00313 case VALUE_IS_OWNED_RAW: 00314 return _content.asRaw.size; 00315 case VALUE_IS_OBJECT: 00316 case VALUE_IS_ARRAY: 00317 return _content.asCollection.memoryUsage(); 00318 default: 00319 return 0; 00320 } 00321 } 00322 00323 size_t nesting() const { 00324 return isCollection() ? _content.asCollection.nesting() : 0; 00325 } 00326 00327 size_t size() const { 00328 return isCollection() ? _content.asCollection.size() : 0; 00329 } 00330 00331 VariantData *addElement(MemoryPool *pool) { 00332 if (isNull()) 00333 toArray(); 00334 if (!isArray()) 00335 return 0; 00336 return _content.asCollection.addElement(pool); 00337 } 00338 00339 VariantData *getElement(size_t index) const { 00340 return isArray() ? _content.asCollection.getElement(index) : 0; 00341 } 00342 00343 VariantData *getOrAddElement(size_t index, MemoryPool *pool) { 00344 if (isNull()) 00345 toArray(); 00346 if (!isArray()) 00347 return 0; 00348 return _content.asCollection.getOrAddElement(index, pool); 00349 } 00350 00351 template <typename TAdaptedString> 00352 VariantData *getMember(TAdaptedString key) const { 00353 return isObject() ? _content.asCollection.getMember(key) : 0; 00354 } 00355 00356 template <typename TAdaptedString> 00357 VariantData *getOrAddMember(TAdaptedString key, MemoryPool *pool) { 00358 if (isNull()) 00359 toObject(); 00360 if (!isObject()) 00361 return 0; 00362 return _content.asCollection.getOrAddMember(key, pool); 00363 } 00364 00365 void movePointers(ptrdiff_t stringDistance, ptrdiff_t variantDistance) { 00366 if (_flags & VALUE_IS_OWNED) 00367 _content.asString += stringDistance; 00368 if (_flags & COLLECTION_MASK) 00369 _content.asCollection.movePointers(stringDistance, variantDistance); 00370 } 00371 00372 uint8_t type() const { 00373 return _flags & VALUE_MASK; 00374 } 00375 00376 private: 00377 void setType(uint8_t t) { 00378 _flags &= KEY_IS_OWNED; 00379 _flags |= t; 00380 } 00381 }; 00382 00383 } // namespace ARDUINOJSON_NAMESPACE 00384 00385 #if defined(__GNUC__) 00386 #if __GNUC__ >= 8 00387 #pragma GCC diagnostic pop 00388 #endif 00389 #endif
Generated on Wed Jul 13 2022 01:10:37 by
1.7.2