mirror of
https://github.com/zerotier/ZeroTierOne.git
synced 2025-04-26 17:03:43 +02:00
176 lines
4.3 KiB
C++
176 lines
4.3 KiB
C++
/*
|
|
* 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 <cstdint>
|
|
#include <vector>
|
|
|
|
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<uint8_t> &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<uint8_t> &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_ALWAYS_INLINE void add(const char *k,int16_t v) { add(k,(uint16_t)v); }
|
|
ZT_ALWAYS_INLINE void add(const char *k,int32_t v) { add(k,(uint32_t)v); }
|
|
ZT_ALWAYS_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_ALWAYS_INLINE unsigned int size() const noexcept { return _t.size(); }
|
|
|
|
/**
|
|
* @return True if dictionary is not empty
|
|
*/
|
|
ZT_ALWAYS_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<uint8_t> &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<uint8_t> > _t;
|
|
};
|
|
|
|
} // namespace ZeroTier
|
|
|
|
#endif
|