Dictionary.cpp 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218
  1. /*
  2. * Copyright (c)2013-2020 ZeroTier, Inc.
  3. *
  4. * Use of this software is governed by the Business Source License included
  5. * in the LICENSE.TXT file in the project's root directory.
  6. *
  7. * Change Date: 2024-01-01
  8. *
  9. * On the date above, in accordance with the Business Source License, use
  10. * of this software will be governed by version 2.0 of the Apache License.
  11. */
  12. /****/
  13. #include "Dictionary.hpp"
  14. namespace ZeroTier {
  15. Dictionary::Dictionary()
  16. {}
  17. Dictionary::~Dictionary()
  18. {}
  19. Vector< uint8_t > &Dictionary::operator[](const char *const k)
  20. { return m_entries[s_key(k)]; }
  21. const Vector< uint8_t > &Dictionary::operator[](const char *const k) const
  22. {
  23. static const Vector< uint8_t > s_emptyEntry;
  24. const SortedMap< String, Vector< uint8_t > >::const_iterator e(m_entries.find(s_key(k)));
  25. return (e == m_entries.end()) ? s_emptyEntry : e->second;
  26. }
  27. void Dictionary::add(const char *k, bool v)
  28. {
  29. Vector< uint8_t > &e = (*this)[k];
  30. e.resize(2);
  31. e[0] = (uint8_t)(v ? '1' : '0');
  32. e[1] = 0;
  33. }
  34. void Dictionary::add(const char *k, const Address &v)
  35. {
  36. char tmp[ZT_ADDRESS_STRING_SIZE_MAX];
  37. v.toString(tmp);
  38. add(k, tmp);
  39. }
  40. void Dictionary::add(const char *k, const char *v)
  41. {
  42. Vector< uint8_t > &e = (*this)[k];
  43. e.clear();
  44. if (v) {
  45. while (*v)
  46. e.push_back((uint8_t)*(v++));
  47. }
  48. }
  49. void Dictionary::add(const char *k, const void *data, unsigned int len)
  50. {
  51. Vector< uint8_t > &e = (*this)[k];
  52. if (likely(len != 0)) {
  53. e.assign((const uint8_t *)data, (const uint8_t *)data + len);
  54. } else {
  55. e.clear();
  56. }
  57. }
  58. bool Dictionary::getB(const char *k, bool dfl) const
  59. {
  60. const Vector< uint8_t > &e = (*this)[k];
  61. if (!e.empty()) {
  62. switch ((char)e[0]) {
  63. case '1':
  64. case 't':
  65. case 'T':
  66. case 'y':
  67. case 'Y':
  68. return true;
  69. default:
  70. return false;
  71. }
  72. }
  73. return dfl;
  74. }
  75. uint64_t Dictionary::getUI(const char *k, uint64_t dfl) const
  76. {
  77. char tmp[32];
  78. getS(k, tmp, sizeof(tmp));
  79. if (tmp[0])
  80. return Utils::unhex(tmp);
  81. return dfl;
  82. }
  83. char *Dictionary::getS(const char *k, char *v, const unsigned int cap) const
  84. {
  85. if (cap == 0) // sanity check
  86. return v;
  87. const Vector< uint8_t > &e = (*this)[k];
  88. if (e.empty()) {
  89. v[0] = 0;
  90. return v;
  91. }
  92. unsigned int i = 0;
  93. const unsigned int last = cap - 1;
  94. for (;;) {
  95. if ((i >= last) || (i >= (unsigned int)e.size())) {
  96. v[i] = 0;
  97. break;
  98. }
  99. if ((v[i] = (char)e[i]) == 0) {
  100. break;
  101. }
  102. ++i;
  103. }
  104. return v;
  105. }
  106. void Dictionary::clear()
  107. {
  108. m_entries.clear();
  109. }
  110. void Dictionary::encode(Vector< uint8_t > &out) const
  111. {
  112. out.clear();
  113. for (SortedMap< String, Vector< uint8_t > >::const_iterator ti(m_entries.begin()); ti != m_entries.end(); ++ti) {
  114. s_appendKey(out, ti->first.data());
  115. for (Vector< uint8_t >::const_iterator i(ti->second.begin()); i != ti->second.end(); ++i)
  116. s_appendValueByte(out, *i);
  117. out.push_back((uint8_t)'\n');
  118. }
  119. out.push_back(0);
  120. }
  121. bool Dictionary::decode(const void *data, unsigned int len)
  122. {
  123. clear();
  124. String k;
  125. Vector< uint8_t > *v = nullptr;
  126. bool escape = false;
  127. for (unsigned int di = 0; di < len; ++di) {
  128. const uint8_t c = reinterpret_cast<const uint8_t *>(data)[di];
  129. if (c) {
  130. if (v) {
  131. if (escape) {
  132. escape = false;
  133. switch (c) {
  134. case 48:
  135. v->push_back(0);
  136. break;
  137. case 101:
  138. v->push_back(61);
  139. break;
  140. case 110:
  141. v->push_back(10);
  142. break;
  143. case 114:
  144. v->push_back(13);
  145. break;
  146. default:
  147. v->push_back(c);
  148. break;
  149. }
  150. } else {
  151. if (c == (uint8_t)'\n') {
  152. k.clear();
  153. v = nullptr;
  154. } else if (c == 92) { // backslash
  155. escape = true;
  156. } else {
  157. v->push_back(c);
  158. }
  159. }
  160. } else {
  161. if (c == (uint8_t)'=') {
  162. v = &m_entries[k];
  163. } else if ((c < 33) || (c > 126) || (c == 92)) {
  164. return false;
  165. } else {
  166. k.push_back(c);
  167. }
  168. }
  169. } else break;
  170. }
  171. return true;
  172. }
  173. char *Dictionary::arraySubscript(char buf[256],const char *name,const unsigned long sub) noexcept
  174. {
  175. for(unsigned int i=0;i<(256 - 17);++i) {
  176. if ((buf[i] = name[i]) == 0) {
  177. buf[i++] = '#';
  178. Utils::hex(sub, buf + i);
  179. return buf;
  180. }
  181. }
  182. buf[0] = 0;
  183. return buf;
  184. }
  185. String Dictionary::s_key(const char *k) noexcept
  186. {
  187. String buf;
  188. if (likely(k != nullptr)) {
  189. for (;;) {
  190. const char c = *(k++);
  191. if ((c >= 33) && (c <= 126) && (c != 61) && (c != 92)) // printable ASCII with no spaces, equals, or backslash
  192. buf.push_back(c);
  193. else if (c == 0)
  194. break;
  195. }
  196. }
  197. return buf;
  198. }
  199. } // namespace ZeroTier