/* * Copyright (c)2013-2020 ZeroTier, Inc. * * Use of this software is governed by the Business Source License included * in the LICENSE.TXT file in the project's root directory. * * Change Date: 2024-01-01 * * On the date above, in accordance with the Business Source License, use * of this software will be governed by version 2.0 of the Apache License. */ /****/ #ifndef ZT_DICTIONARY_HPP #define ZT_DICTIONARY_HPP #include "Constants.hpp" #include "Utils.hpp" #include "Address.hpp" #include "Buf.hpp" #include "Hashtable.hpp" #include #include namespace ZeroTier { /** * A simple key-value store for short keys * * This data structure is used for network configurations, node meta-data, * and other open-definition protocol objects. It consists of a key-value * store with short (under 8 characters) keys that map to strings, blobs, * or integers with the latter being by convention in hex format. * * If this seems a little odd, it is. It dates back to the very first alpha * versions of ZeroTier and if it were redesigned today we'd use some kind * of simple or standardized binary encoding. Nevertheless it is efficient * and it works so there is no need to change it and break backward * compatibility. */ class Dictionary { public: Dictionary(); ~Dictionary(); /** * Get a reference to a value * * @param k Key to look up * @return Reference to value */ std::vector &operator[](const char *k); /** * Get a const reference to a value * * @param k Key to look up * @return Reference to value or to empty vector if not found */ const std::vector &operator[](const char *k) const; /** * Add a boolean as '1' or '0' */ void add(const char *k,bool v); /** * Add an integer as a hexadecimal string value */ void add(const char *k,uint16_t v); /** * Add an integer as a hexadecimal string value */ void add(const char *k,uint32_t v); /** * Add an integer as a hexadecimal string value */ void add(const char *k,uint64_t v); ZT_INLINE void add(const char *k,int16_t v) { add(k,(uint16_t)v); } ZT_INLINE void add(const char *k,int32_t v) { add(k,(uint32_t)v); } ZT_INLINE void add(const char *k,int64_t v) { add(k,(uint64_t)v); } /** * Add an address in 10-digit hex string format */ void add(const char *k,const Address &v); /** * Add a C string as a value */ void add(const char *k,const char *v); /** * Add a binary blob as a value */ void add(const char *k,const void *data,unsigned int len); /** * Get a boolean * * @param k Key to look up * @param dfl Default value (default: false) * @return Value of key or default if not found */ bool getB(const char *k,bool dfl = false) const; /** * Get an integer * * @param k Key to look up * @param dfl Default value (default: 0) * @return Value of key or default if not found */ uint64_t getUI(const char *k,uint64_t dfl = 0) const; /** * Get a C string * * If the buffer is too small the string will be truncated, but the * buffer will always end in a terminating null no matter what. * * @param k Key to look up * @param v Buffer to hold string * @param cap Maximum size of string (including terminating null) */ void getS(const char *k,char *v,unsigned int cap) const; /** * Erase all entries in dictionary */ void clear(); /** * @return Number of entries */ ZT_INLINE unsigned int size() const noexcept { return _t.size(); } /** * @return True if dictionary is not empty */ ZT_INLINE bool empty() const noexcept { return _t.empty(); } /** * Encode to a string in the supplied vector * * This does not add a terminating zero. This must be pushed afterwords * if the result is to be handled as a C string. * * @param out String encoded dictionary */ void encode(std::vector &out) const; /** * Decode a string encoded dictionary * * This will decode up to 'len' but will also abort if it finds a * null/zero as this could be a C string. * * @param data Data to decode * @param len Length of data * @return True if dictionary was formatted correctly and valid, false on error */ bool decode(const void *data,unsigned int len); private: Hashtable< uint64_t,std::vector > _t; }; } // namespace ZeroTier #endif