|
@@ -31,8 +31,9 @@
|
|
#include <stdint.h>
|
|
#include <stdint.h>
|
|
|
|
|
|
#include <string>
|
|
#include <string>
|
|
-#include <map>
|
|
|
|
|
|
+#include <vector>
|
|
#include <stdexcept>
|
|
#include <stdexcept>
|
|
|
|
+#include <algorithm>
|
|
|
|
|
|
#include "Constants.hpp"
|
|
#include "Constants.hpp"
|
|
#include "Utils.hpp"
|
|
#include "Utils.hpp"
|
|
@@ -56,12 +57,12 @@ class Identity;
|
|
*
|
|
*
|
|
* Keys beginning with "~!" are reserved for signature data fields.
|
|
* Keys beginning with "~!" are reserved for signature data fields.
|
|
*
|
|
*
|
|
- * Note: the signature code depends on std::map<> being sorted, but no
|
|
|
|
- * other code does. So if the underlying data structure is ever swapped
|
|
|
|
- * out for an unsorted one, the signature code will have to be updated
|
|
|
|
- * to sort before composing the string to sign.
|
|
|
|
|
|
+ * It's stored as a simple vector and can be linearly scanned or
|
|
|
|
+ * binary searched. Dictionaries are only used for very small things
|
|
|
|
+ * outside the core loop, so this is not a significant performance
|
|
|
|
+ * issue and it reduces memory use and code footprint.
|
|
*/
|
|
*/
|
|
-class Dictionary : public std::map<std::string,std::string>
|
|
|
|
|
|
+class Dictionary : public std::vector< std::pair<std::string,std::string> >
|
|
{
|
|
{
|
|
public:
|
|
public:
|
|
Dictionary() {}
|
|
Dictionary() {}
|
|
@@ -77,21 +78,8 @@ public:
|
|
*/
|
|
*/
|
|
Dictionary(const std::string &s) { fromString(s.c_str(),(unsigned int)s.length()); }
|
|
Dictionary(const std::string &s) { fromString(s.c_str(),(unsigned int)s.length()); }
|
|
|
|
|
|
- /**
|
|
|
|
- * Get a key, throwing an exception if it is not present
|
|
|
|
- *
|
|
|
|
- * @param key Key to look up
|
|
|
|
- * @return Reference to value
|
|
|
|
- * @throws std::invalid_argument Key not found
|
|
|
|
- */
|
|
|
|
- inline const std::string &get(const std::string &key) const
|
|
|
|
- throw(std::invalid_argument)
|
|
|
|
- {
|
|
|
|
- const_iterator e(find(key));
|
|
|
|
- if (e == end())
|
|
|
|
- throw std::invalid_argument(std::string("missing required field: ")+key);
|
|
|
|
- return e->second;
|
|
|
|
- }
|
|
|
|
|
|
+ iterator find(const std::string &key);
|
|
|
|
+ const_iterator find(const std::string &key) const;
|
|
|
|
|
|
/**
|
|
/**
|
|
* Get a key, returning a default if not present
|
|
* Get a key, returning a default if not present
|
|
@@ -113,23 +101,7 @@ public:
|
|
* @param dfl Default boolean result if key not found or empty (default: false)
|
|
* @param dfl Default boolean result if key not found or empty (default: false)
|
|
* @return Boolean value of key
|
|
* @return Boolean value of key
|
|
*/
|
|
*/
|
|
- inline bool getBoolean(const std::string &key,bool dfl = false) const
|
|
|
|
- {
|
|
|
|
- const_iterator e(find(key));
|
|
|
|
- if (e == end())
|
|
|
|
- return dfl;
|
|
|
|
- if (e->second.length() < 1)
|
|
|
|
- return dfl;
|
|
|
|
- switch(e->second[0]) {
|
|
|
|
- case '1':
|
|
|
|
- case 't':
|
|
|
|
- case 'T':
|
|
|
|
- case 'y':
|
|
|
|
- case 'Y':
|
|
|
|
- return true;
|
|
|
|
- }
|
|
|
|
- return false;
|
|
|
|
- }
|
|
|
|
|
|
+ bool getBoolean(const std::string &key,bool dfl = false) const;
|
|
|
|
|
|
/**
|
|
/**
|
|
* @param key Key to get
|
|
* @param key Key to get
|
|
@@ -170,6 +142,8 @@ public:
|
|
return Utils::strTo64(e->second.c_str());
|
|
return Utils::strTo64(e->second.c_str());
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ std::string &operator[](const std::string &key);
|
|
|
|
+
|
|
/**
|
|
/**
|
|
* @param key Key to set
|
|
* @param key Key to set
|
|
* @param value String value
|
|
* @param value String value
|
|
@@ -239,17 +213,7 @@ public:
|
|
/**
|
|
/**
|
|
* @return String-serialized dictionary
|
|
* @return String-serialized dictionary
|
|
*/
|
|
*/
|
|
- inline std::string toString() const
|
|
|
|
- {
|
|
|
|
- std::string s;
|
|
|
|
- for(const_iterator kv(begin());kv!=end();++kv) {
|
|
|
|
- _appendEsc(kv->first.data(),(unsigned int)kv->first.length(),s);
|
|
|
|
- s.push_back('=');
|
|
|
|
- _appendEsc(kv->second.data(),(unsigned int)kv->second.length(),s);
|
|
|
|
- s.append(ZT_EOL_S);
|
|
|
|
- }
|
|
|
|
- return s;
|
|
|
|
- }
|
|
|
|
|
|
+ std::string toString() const;
|
|
|
|
|
|
/**
|
|
/**
|
|
* Clear and initialize from a string
|
|
* Clear and initialize from a string
|
|
@@ -278,14 +242,19 @@ public:
|
|
*/
|
|
*/
|
|
uint64_t signatureTimestamp() const;
|
|
uint64_t signatureTimestamp() const;
|
|
|
|
|
|
|
|
+ /**
|
|
|
|
+ * @param key Key to erase
|
|
|
|
+ */
|
|
|
|
+ void eraseKey(const std::string &key);
|
|
|
|
+
|
|
/**
|
|
/**
|
|
* Remove any signature from this dictionary
|
|
* Remove any signature from this dictionary
|
|
*/
|
|
*/
|
|
inline void removeSignature()
|
|
inline void removeSignature()
|
|
{
|
|
{
|
|
- erase(ZT_DICTIONARY_SIGNATURE);
|
|
|
|
- erase(ZT_DICTIONARY_SIGNATURE_IDENTITY);
|
|
|
|
- erase(ZT_DICTIONARY_SIGNATURE_TIMESTAMP);
|
|
|
|
|
|
+ eraseKey(ZT_DICTIONARY_SIGNATURE);
|
|
|
|
+ eraseKey(ZT_DICTIONARY_SIGNATURE_IDENTITY);
|
|
|
|
+ eraseKey(ZT_DICTIONARY_SIGNATURE_TIMESTAMP);
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
/**
|
|
@@ -305,21 +274,6 @@ public:
|
|
*/
|
|
*/
|
|
bool verify(const Identity &id) const;
|
|
bool verify(const Identity &id) const;
|
|
|
|
|
|
- inline bool operator==(const Dictionary &d) const
|
|
|
|
- {
|
|
|
|
- // std::map::operator== is broken on uclibc++
|
|
|
|
- if (size() != d.size())
|
|
|
|
- return false;
|
|
|
|
- const_iterator a(begin());
|
|
|
|
- const_iterator b(d.begin());
|
|
|
|
- while (a != end()) {
|
|
|
|
- if (*(a++) != *(b++))
|
|
|
|
- return false;
|
|
|
|
- }
|
|
|
|
- return true;
|
|
|
|
- }
|
|
|
|
- inline bool operator!=(const Dictionary &d) const { return (!(*this == d)); }
|
|
|
|
-
|
|
|
|
private:
|
|
private:
|
|
void _mkSigBuf(std::string &buf) const;
|
|
void _mkSigBuf(std::string &buf) const;
|
|
static void _appendEsc(const char *data,unsigned int len,std::string &to);
|
|
static void _appendEsc(const char *data,unsigned int len,std::string &to);
|