2
0

Dictionary.cpp 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  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: 2025-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[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(k));
  25. return (e == m_entries.end()) ? s_emptyEntry : e->second;
  26. }
  27. void Dictionary::add(const char *k, const Address &v)
  28. {
  29. char tmp[ZT_ADDRESS_STRING_SIZE_MAX];
  30. v.toString(tmp);
  31. add(k, tmp);
  32. }
  33. void Dictionary::add(const char *k, const char *v)
  34. {
  35. Vector< uint8_t > &e = (*this)[k];
  36. e.clear();
  37. if (v) {
  38. while (*v)
  39. e.push_back((uint8_t)*(v++));
  40. }
  41. }
  42. void Dictionary::add(const char *k, const void *data, unsigned int len)
  43. {
  44. Vector< uint8_t > &e = (*this)[k];
  45. if (likely(len != 0)) {
  46. e.assign((const uint8_t *)data, (const uint8_t *)data + len);
  47. } else {
  48. e.clear();
  49. }
  50. }
  51. uint64_t Dictionary::getUI(const char *k, uint64_t dfl) const
  52. {
  53. char tmp[32];
  54. getS(k, tmp, sizeof(tmp));
  55. if (tmp[0])
  56. return Utils::unhex(tmp);
  57. return dfl;
  58. }
  59. char *Dictionary::getS(const char *k, char *v, const unsigned int cap) const
  60. {
  61. if (cap == 0) // sanity check
  62. return v;
  63. const Vector< uint8_t > &e = (*this)[k];
  64. if (e.empty()) {
  65. v[0] = 0;
  66. return v;
  67. }
  68. for (unsigned int i = 0, last = (cap - 1);; ++i) {
  69. if ((i >= last) || (i >= (unsigned int)e.size())) {
  70. v[i] = 0;
  71. break;
  72. }
  73. if ((v[i] = (char)e[i]) == 0)
  74. break;
  75. }
  76. return v;
  77. }
  78. void Dictionary::clear()
  79. {
  80. m_entries.clear();
  81. }
  82. void Dictionary::encode(Vector< uint8_t > &out) const
  83. {
  84. out.clear();
  85. for (SortedMap< String, Vector< uint8_t > >::const_iterator ti(m_entries.begin()); ti != m_entries.end(); ++ti) {
  86. s_appendKey(out, ti->first.data());
  87. for (Vector< uint8_t >::const_iterator i(ti->second.begin()); i != ti->second.end(); ++i)
  88. s_appendValueByte(out, *i);
  89. out.push_back((uint8_t)'\n');
  90. }
  91. }
  92. bool Dictionary::decode(const void *data, unsigned int len)
  93. {
  94. clear();
  95. String k;
  96. Vector< uint8_t > *v = nullptr;
  97. bool escape = false;
  98. for (unsigned int di = 0; di < len; ++di) {
  99. const uint8_t c = reinterpret_cast<const uint8_t *>(data)[di];
  100. if (c) {
  101. if (v) {
  102. if (escape) {
  103. escape = false;
  104. switch (c) {
  105. case 48:
  106. v->push_back(0);
  107. break;
  108. case 101:
  109. v->push_back(61);
  110. break;
  111. case 110:
  112. v->push_back(10);
  113. break;
  114. case 114:
  115. v->push_back(13);
  116. break;
  117. default:
  118. v->push_back(c);
  119. break;
  120. }
  121. } else {
  122. if (c == (uint8_t)'\n') {
  123. k.clear();
  124. v = nullptr;
  125. } else if (c == 92) { // backslash
  126. escape = true;
  127. } else {
  128. v->push_back(c);
  129. }
  130. }
  131. } else {
  132. if (c == (uint8_t)'=') {
  133. v = &m_entries[k];
  134. } else {
  135. k.push_back(c);
  136. }
  137. }
  138. } else {
  139. break;
  140. }
  141. }
  142. return true;
  143. }
  144. char *Dictionary::arraySubscript(char *buf, unsigned int bufSize, const char *name, const unsigned long sub) noexcept
  145. {
  146. if (bufSize < 17) { // sanity check
  147. buf[0] = 0;
  148. return buf;
  149. }
  150. for (unsigned int i = 0; i < (bufSize - 17); ++i) {
  151. if ((buf[i] = name[i]) == 0) {
  152. buf[i++] = '#';
  153. Utils::hex(sub, buf + i);
  154. return buf;
  155. }
  156. }
  157. buf[0] = 0;
  158. return buf;
  159. }
  160. } // namespace ZeroTier