headercontainer.H 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  1. /*
  2. This program is free software: you can redistribute it and/or modify
  3. it under the terms of the GNU General Public License as published by
  4. the Free Software Foundation, either version 3 of the License, or
  5. (at your option) any later version.
  6. This program is distributed in the hope that it will be useful,
  7. but WITHOUT ANY WARRANTY; without even the implied warranty of
  8. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  9. GNU General Public License for more details.
  10. You should have received a copy of the GNU General Public License
  11. along with this program. If not, see <http://www.gnu.org/licenses/>.
  12. * */
  13. /*
  14. * headerContainer.H
  15. *
  16. * Created on: Apr 28, 2013
  17. * Author: xaxaxa
  18. */
  19. #ifndef HEADERCONTAINER_H_
  20. #define HEADERCONTAINER_H_
  21. #include <ctype.h>
  22. #include <sys/types.h>
  23. #include <algorithm>
  24. #include "stringutils.H"
  25. namespace cppsp
  26. {
  27. typedef CP::String String;
  28. #ifndef __CPPSP_TOLOWER
  29. #define __CPPSP_TOLOWER
  30. static inline char tolower(char c) {
  31. if (c <= 'Z' && c >= 'A') c = c - 'A' + 'a';
  32. return c;
  33. }
  34. #endif
  35. struct Header
  36. {
  37. String name;
  38. String value;
  39. };
  40. //sorted
  41. struct headerContainer
  42. {
  43. RGC::Allocator* a;
  44. struct item
  45. {
  46. const char* name;
  47. const char* value;
  48. int nameLength;
  49. int valueLength;
  50. String n() {
  51. return {name,nameLength};
  52. }
  53. String v() {
  54. return {value,valueLength};
  55. }
  56. };
  57. static bool compareItem(const item& i1, const item& i2) {
  58. return ci_compare( { i1.name, i1.nameLength }, { i2.name, i2.nameLength }) < 0;
  59. }
  60. struct iterator
  61. {
  62. headerContainer* c;
  63. item* i;
  64. void operator+=(int i) {
  65. this->i += i;
  66. if (this->i >= (c->items + c->length)) this->i = NULL;
  67. }
  68. void operator++(int) {
  69. operator+=(1);
  70. }
  71. bool operator==(const iterator& other) {
  72. return i == other.i;
  73. }
  74. bool operator!=(const iterator& other) {
  75. return !operator==(other);
  76. }
  77. Header operator*() {
  78. item& it = *i;
  79. return { {it.name,it.nameLength}, {it.value,it.valueLength}};
  80. }
  81. item& get() {
  82. return *i;
  83. }
  84. };
  85. item* items;
  86. int length;
  87. headerContainer(RGC::Allocator* a) :
  88. a(a), items(NULL), length(0) {
  89. }
  90. item* beginReplace(int length) {
  91. items = (item*) a->alloc(length * sizeof(item));
  92. this->length = length;
  93. return items;
  94. }
  95. void endReplace() {
  96. std::sort(items, items + length, compareItem);
  97. }
  98. String operator[](String name) const {
  99. item it { name.data(), NULL, name.length(), 0 };
  100. item* tmp = std::lower_bound(items, items + length, it, compareItem);
  101. if (tmp != NULL && (tmp - items) < length && ci_compare(tmp->n(), name) == 0) return tmp->v();
  102. return {(char*)nullptr,0};
  103. }
  104. iterator find(String name) {
  105. item it { name.data(), NULL, name.length(), 0 };
  106. item* tmp = std::lower_bound(items, items + length, it, compareItem);
  107. if (tmp != NULL && (tmp - items) < length && ci_compare(tmp->n(), name) == 0) return {this,tmp};
  108. return end();
  109. }
  110. iterator begin() {
  111. return {this,items};
  112. }
  113. iterator end() {
  114. return {this,NULL};
  115. }
  116. void clear() {
  117. items = NULL;
  118. length = 0;
  119. }
  120. };
  121. //not sorted; for response headers
  122. struct headerContainer2
  123. {
  124. CP::StringPool* sp;
  125. struct item
  126. {
  127. const char* name;
  128. const char* value;
  129. int nameLength;
  130. int valueLength;
  131. };
  132. static const int bucketSize = 8;
  133. struct bucket
  134. {
  135. bucket* next;
  136. item items[bucketSize];
  137. int length;
  138. };
  139. struct iterator
  140. {
  141. bucket* b;
  142. int i;
  143. void operator+=(int i) {
  144. this->i += i;
  145. while (this->i > bucketSize && b != NULL) {
  146. b = b->next;
  147. this->i -= bucketSize;
  148. }
  149. if (b != NULL && this->i >= b->length) b = NULL;
  150. }
  151. void operator++(int) {
  152. operator+=(1);
  153. }
  154. bool operator==(const iterator& other) {
  155. if (b == NULL && other.b == NULL) return true;
  156. return b == other.b && i == other.i;
  157. }
  158. bool operator!=(const iterator& other) {
  159. return !operator==(other);
  160. }
  161. Header operator*() {
  162. item& it = b->items[i];
  163. return { {it.name,it.nameLength}, {it.value,it.valueLength}};
  164. }
  165. item& get() {
  166. return b->items[i];
  167. }
  168. };
  169. bucket* _first = NULL;
  170. bucket* _last = NULL;
  171. headerContainer2(CP::StringPool* sp) :
  172. sp(sp) {
  173. }
  174. void add(item it) {
  175. if (_last == NULL || _last->length >= bucketSize) addBucket();
  176. _last->items[_last->length] = it;
  177. _last->length++;
  178. }
  179. void add(String name, String value) {
  180. add( { name.data(), value.data(), name.length(), value.length() });
  181. }
  182. void addCopy(String name, String value) {
  183. name = sp->addString(name);
  184. value = sp->addString(value);
  185. add( { name.data(), value.data(), name.length(), value.length() });
  186. }
  187. void addBucket() {
  188. bucket* b = (bucket*) sp->add(sizeof(bucket));
  189. b->next = NULL;
  190. b->length = 0;
  191. if (_last != NULL) _last->next = b;
  192. _last = b;
  193. if (_first == NULL) _first = b;
  194. }
  195. String operator[](String name) {
  196. for (bucket* b = _first; b != NULL; b = b->next) {
  197. for (int i = 0; i < b->length; i++)
  198. if (ci_compare(name, { b->items[i].name, b->items[i].nameLength }) == 0) return {b->items[i].value,b->items[i].valueLength};
  199. }
  200. return {(char*)nullptr,0};
  201. }
  202. iterator find(String name) {
  203. for (bucket* b = _first; b != NULL; b = b->next) {
  204. for (int i = 0; i < b->length; i++)
  205. if (ci_compare(name, { b->items[i].name, b->items[i].nameLength }) == 0) return {b,i};
  206. }
  207. return end();
  208. }
  209. void set(String name, String value) {
  210. iterator it = find(name);
  211. if (it == end()) add(name, value);
  212. else {
  213. it.get().value = value.data();
  214. it.get().valueLength = value.length();
  215. }
  216. }
  217. iterator begin() {
  218. return {_first,0};
  219. }
  220. iterator end() {
  221. return {NULL,0};
  222. }
  223. void clear() {
  224. _first = _last = NULL;
  225. }
  226. };
  227. }
  228. #endif /* HEADERCONTAINER_H_ */