ChipMaster's trial hacks on C++CMS starting with v1.2.1. Not sure I'll follow on with the v2 since it looks to be breaking and mostly frivolous.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

207 lines
4.0 KiB

  1. ///////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright (C) 2008-2012 Artyom Beilis (Tonkikh) <artyomtnk@yahoo.com>
  4. //
  5. // See accompanying file COPYING.TXT file for licensing details.
  6. //
  7. ///////////////////////////////////////////////////////////////////////////////
  8. #ifndef CPPCMS_IMPL_STRING_MAP_H
  9. #define CPPCMS_IMPL_STRING_MAP_H
  10. #include <string.h>
  11. #include <stdlib.h>
  12. #include <string>
  13. #include <vector>
  14. #include <limits>
  15. #include <booster/noncopyable.h>
  16. namespace cppcms {
  17. namespace impl {
  18. class string_pool : public booster::noncopyable {
  19. public:
  20. string_pool(size_t page_size = 2048) :
  21. page_size_(page_size),
  22. pages_(0),
  23. free_space_(0),
  24. data_(0)
  25. {
  26. add_page();
  27. }
  28. void clear()
  29. {
  30. destroy();
  31. add_page();
  32. }
  33. ~string_pool()
  34. {
  35. destroy();
  36. }
  37. char *alloc(size_t n)
  38. {
  39. char *s = allocate_space(n);
  40. memset(s,0,n);
  41. return s;
  42. }
  43. char *add(std::string const &s)
  44. {
  45. return add(s.c_str());
  46. }
  47. char *add_substr(std::string const &s,size_t pos = 0,size_t len=std::string::npos)
  48. {
  49. if(pos > s.size())
  50. return add("");
  51. return add(s.c_str() + pos,len);
  52. }
  53. char *add(char const *s)
  54. {
  55. return add_bounded_string(s,strlen(s));
  56. }
  57. char *add(char const *b,char const *e)
  58. {
  59. return add(b,e-b);
  60. }
  61. char *add(char const *s,size_t len)
  62. {
  63. char const *tmp = s;
  64. size_t real_len = 0;
  65. while(real_len < len && *tmp!=0) {
  66. real_len ++;
  67. tmp++;
  68. }
  69. return add_bounded_string(s,real_len);
  70. }
  71. private:
  72. void destroy()
  73. {
  74. while(pages_) {
  75. page *p = pages_;
  76. pages_ = pages_->next;
  77. free(p);
  78. }
  79. }
  80. /// data
  81. struct page {
  82. page *next;
  83. char data[1];
  84. };
  85. size_t page_size_;
  86. page *pages_;
  87. size_t free_space_;
  88. char *data_;
  89. char *allocate_space(size_t size)
  90. {
  91. if(size * 2 > page_size_) {
  92. page *p=(page *)malloc(size + sizeof(page));
  93. if(!p)
  94. throw std::bad_alloc();
  95. p->next = pages_->next;
  96. pages_->next = p;
  97. return p->data;
  98. }
  99. if(size > free_space_) {
  100. add_page();
  101. }
  102. char *result = data_;
  103. data_+=size;
  104. free_space_ -= size;
  105. return result;
  106. }
  107. char *add_bounded_string(char const *str,size_t size)
  108. {
  109. char *s=allocate_space(size + 1);
  110. memcpy(s,str,size);
  111. s[size]=0;
  112. return s;
  113. }
  114. void add_page()
  115. {
  116. page *p=(page *)malloc(sizeof(page) + page_size_);
  117. if(!p)
  118. throw std::bad_alloc();
  119. p->next = pages_;
  120. pages_ = p;
  121. data_ = p->data;
  122. free_space_ = page_size_;
  123. }
  124. };
  125. class string_map {
  126. public:
  127. struct entry {
  128. char const *key;
  129. char const *value;
  130. entry(char const *k ="",char const *v="") : key(k),value(v) {}
  131. bool operator<(entry const &other) const
  132. {
  133. return strcmp(key,other.key) < 0;
  134. }
  135. bool operator==(entry const &other) const
  136. {
  137. return strcmp(key,other.key) == 0;
  138. }
  139. };
  140. string_map() : sorted_(true)
  141. {
  142. data_.reserve(64);
  143. }
  144. typedef std::vector<entry>::iterator iterator;
  145. iterator begin()
  146. {
  147. sort();
  148. return data_.begin();
  149. }
  150. iterator end()
  151. {
  152. sort();
  153. return data_.end();
  154. }
  155. void add(char const *key,char const *value)
  156. {
  157. data_.push_back(entry(key,value));
  158. sorted_=false;
  159. }
  160. void sort()
  161. {
  162. if(!sorted_) {
  163. std::sort(data_.begin(),data_.end());
  164. sorted_ = true;
  165. }
  166. }
  167. char const *get(char const *ckey)
  168. {
  169. sort();
  170. entry key(ckey);
  171. iterator p = std::lower_bound(data_.begin(),data_.end(),key);
  172. if(p!=data_.end() && *p==key)
  173. return p->value;
  174. return 0;
  175. }
  176. char const *get_safe(char const *key)
  177. {
  178. char const *value =get(key);
  179. if(value)
  180. return value;
  181. return "";
  182. }
  183. void clear()
  184. {
  185. data_.clear();
  186. sorted_ = false;
  187. }
  188. private:
  189. bool sorted_;
  190. std::vector<entry> data_;
  191. };
  192. } // impl
  193. }
  194. #endif