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.
 
 
 
 
 
 

494 lines
9.6 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_STRING_KEY_H
  9. #define CPPCMS_STRING_KEY_H
  10. #include <string>
  11. #include <string.h>
  12. #include <algorithm>
  13. #include <stdexcept>
  14. #include <ostream>
  15. namespace cppcms {
  16. ///
  17. /// \brief This is a special object that may hold an std::string or
  18. /// alternatively reference to external (unowned) chunk of text
  19. ///
  20. /// It is designed to be used for efficiency and reduce amount of
  21. /// memory allocations and copies.
  22. ///
  23. /// It has interface that is roughly similar to the interface of std::string,
  24. /// but it does not provide a members that can mutate it or provide a NUL terminated
  25. /// string c_str().
  26. ///
  27. class string_key {
  28. public:
  29. ///
  30. /// Iterator type
  31. ///
  32. typedef char const *const_iterator;
  33. ///
  34. /// The last position of the character in the string
  35. ///
  36. static const size_t npos = -1;
  37. ///
  38. /// Default constructor - empty key
  39. ///
  40. string_key() :
  41. begin_(0),
  42. end_(0)
  43. {
  44. }
  45. ///
  46. /// Create a new string copying the \a key
  47. ///
  48. string_key(char const *key) :
  49. begin_(0),
  50. end_(0),
  51. key_(key)
  52. {
  53. }
  54. ///
  55. /// Create a new string copying the \a key
  56. ///
  57. string_key(std::string const &key) :
  58. begin_(0),
  59. end_(0),
  60. key_(key)
  61. {
  62. }
  63. ///
  64. /// String size in bytes
  65. ///
  66. size_t size() const
  67. {
  68. return end() - begin();
  69. }
  70. ///
  71. /// Same as size()
  72. ///
  73. size_t length() const
  74. {
  75. return size();
  76. }
  77. ///
  78. /// Clear the string
  79. ///
  80. void clear()
  81. {
  82. begin_ = end_ = 0;
  83. key_.clear();
  84. }
  85. ///
  86. /// Check if the string is empty
  87. ///
  88. bool empty() const
  89. {
  90. return end() == begin();
  91. }
  92. ///
  93. /// Find first occurrence of a character \c in the string starting from
  94. /// position \a pos. Returns npos if not character found.
  95. ///
  96. size_t find(char c,size_t pos = 0) const
  97. {
  98. size_t s = size();
  99. if(pos >= s)
  100. return npos;
  101. char const *p=begin() + pos;
  102. while(pos <= s && *p!=c) {
  103. pos++;
  104. p++;
  105. }
  106. if(pos >= s)
  107. return npos;
  108. return pos;
  109. }
  110. ///
  111. /// Create a substring from this string starting from character \a pos of size at most \a n
  112. ///
  113. string_key substr(size_t pos = 0,size_t n=npos) const
  114. {
  115. string_key tmp = unowned_substr(pos,n);
  116. return string_key(std::string(tmp.begin(),tmp.end()));
  117. }
  118. ///
  119. /// Create a substring from this string starting from character \a pos of size at most \a n
  120. /// such that the memory is not copied but only reference by the created substring
  121. ///
  122. string_key unowned_substr(size_t pos = 0,size_t n=npos) const
  123. {
  124. if(pos >= size()) {
  125. return string_key();
  126. }
  127. char const *p=begin() + pos;
  128. char const *e=end();
  129. if(n > size_t(e-p)) {
  130. return string_key(p,e);
  131. }
  132. else {
  133. return string_key(p,p+n);
  134. }
  135. }
  136. ///
  137. /// Get a character at position \a n
  138. ///
  139. char const &operator[](size_t n) const
  140. {
  141. return *(begin() + n);
  142. }
  143. ///
  144. /// Get a character at position \a n, if \a n is not valid position, throws std::out_of_range exception
  145. ///
  146. char const &at(size_t n) const
  147. {
  148. if(n > size())
  149. throw std::out_of_range("cppcms::string_key::at() range error");
  150. return *(begin() + n);
  151. }
  152. ///
  153. /// Create a string from \a v without copying the memory. \a v should remain valid
  154. /// as long as this object is used
  155. ///
  156. static string_key unowned(std::string const &v)
  157. {
  158. return string_key(v.c_str(),v.c_str()+v.size());
  159. }
  160. ///
  161. /// Create a string from \a str without copying the memory. \a str should remain valid
  162. /// as long as this object is used
  163. ///
  164. static string_key unowned(char const *str)
  165. {
  166. char const *end = str;
  167. while(*end)
  168. end++;
  169. return string_key(str,end);
  170. }
  171. ///
  172. /// Create a string from \a characters at rang [begin,end) without copying the memory.
  173. /// The range should remain valid as long as this object is used
  174. ///
  175. static string_key unowned(char const *begin,char const *end)
  176. {
  177. return string_key(begin,end);
  178. }
  179. ///
  180. /// Get a pointer to the first character in the string
  181. ///
  182. char const *begin() const
  183. {
  184. if(begin_)
  185. return begin_;
  186. return key_.c_str();
  187. }
  188. ///
  189. /// Get a pointer to the one past last character in the string
  190. ///
  191. char const *end() const
  192. {
  193. if(begin_)
  194. return end_;
  195. return key_.c_str() + key_.size();
  196. }
  197. ///
  198. /// Compare two strings
  199. ///
  200. bool operator<(string_key const &other) const
  201. {
  202. return std::lexicographical_compare( begin(),end(),
  203. other.begin(),other.end(),
  204. std::char_traits<char>::lt);
  205. }
  206. ///
  207. /// Compare two strings
  208. ///
  209. bool operator>(string_key const &other) const
  210. {
  211. return other < *this;
  212. }
  213. ///
  214. /// Compare two strings
  215. ///
  216. bool operator>=(string_key const &other) const
  217. {
  218. return !(*this < other);
  219. }
  220. ///
  221. /// Compare two strings
  222. ///
  223. bool operator<=(string_key const &other) const
  224. {
  225. return !(*this > other);
  226. }
  227. ///
  228. /// Compare two strings
  229. ///
  230. bool operator==(string_key const &other) const
  231. {
  232. return (end() - begin() == other.end() - other.begin())
  233. && memcmp(begin(),other.begin(),end()-begin()) == 0;
  234. }
  235. ///
  236. /// Compare two strings
  237. ///
  238. bool operator!=(string_key const &other) const
  239. {
  240. return !(*this==other);
  241. }
  242. ///
  243. /// Get the pointer to the first character in the string. Note it should not be NUL terminated
  244. ///
  245. char const *data() const
  246. {
  247. return begin();
  248. }
  249. ///
  250. /// Create std::string from the key
  251. ///
  252. std::string str() const
  253. {
  254. if(begin_)
  255. return std::string(begin_,end_-begin_);
  256. else
  257. return key_;
  258. }
  259. ///
  260. /// Convert the key to the std::string
  261. ///
  262. operator std::string() const
  263. {
  264. return str();
  265. }
  266. private:
  267. string_key(char const *b,char const *e) :
  268. begin_(b),
  269. end_(e)
  270. {
  271. }
  272. char const *begin_;
  273. char const *end_;
  274. std::string key_;
  275. };
  276. ///
  277. /// Write the string to the stream
  278. ///
  279. inline std::ostream &operator<<(std::ostream &out,string_key const &s)
  280. {
  281. out.write(s.data(),s.size());
  282. return out;
  283. }
  284. ///
  285. /// Compare two strings
  286. ///
  287. inline bool operator==(string_key const &l,char const *r)
  288. {
  289. return l==string_key::unowned(r);
  290. }
  291. ///
  292. /// Compare two strings
  293. ///
  294. inline bool operator==(char const *l,string_key const &r)
  295. {
  296. return string_key::unowned(l) == r;
  297. }
  298. ///
  299. /// Compare two strings
  300. ///
  301. inline bool operator==(string_key const &l,std::string const &r)
  302. {
  303. return l==string_key::unowned(r);
  304. }
  305. ///
  306. /// Compare two strings
  307. ///
  308. inline bool operator==(std::string const &l,string_key const &r)
  309. {
  310. return string_key::unowned(l) == r;
  311. }
  312. ///
  313. /// Compare two strings
  314. ///
  315. inline bool operator!=(string_key const &l,char const *r)
  316. {
  317. return l!=string_key::unowned(r);
  318. }
  319. ///
  320. /// Compare two strings
  321. ///
  322. inline bool operator!=(char const *l,string_key const &r)
  323. {
  324. return string_key::unowned(l) != r;
  325. }
  326. ///
  327. /// Compare two strings
  328. ///
  329. inline bool operator!=(string_key const &l,std::string const &r)
  330. {
  331. return l!=string_key::unowned(r);
  332. }
  333. ///
  334. /// Compare two strings
  335. ///
  336. inline bool operator!=(std::string const &l,string_key const &r)
  337. {
  338. return string_key::unowned(l) != r;
  339. }
  340. ///
  341. /// Compare two strings
  342. ///
  343. inline bool operator<=(string_key const &l,char const *r)
  344. {
  345. return l<=string_key::unowned(r);
  346. }
  347. ///
  348. /// Compare two strings
  349. ///
  350. inline bool operator<=(char const *l,string_key const &r)
  351. {
  352. return string_key::unowned(l) <= r;
  353. }
  354. ///
  355. /// Compare two strings
  356. ///
  357. inline bool operator<=(string_key const &l,std::string const &r)
  358. {
  359. return l<=string_key::unowned(r);
  360. }
  361. ///
  362. /// Compare two strings
  363. ///
  364. inline bool operator<=(std::string const &l,string_key const &r)
  365. {
  366. return string_key::unowned(l) <= r;
  367. }
  368. ///
  369. /// Compare two strings
  370. ///
  371. inline bool operator>=(string_key const &l,char const *r)
  372. {
  373. return l>=string_key::unowned(r);
  374. }
  375. ///
  376. /// Compare two strings
  377. ///
  378. inline bool operator>=(char const *l,string_key const &r)
  379. {
  380. return string_key::unowned(l) >= r;
  381. }
  382. ///
  383. /// Compare two strings
  384. ///
  385. inline bool operator>=(string_key const &l,std::string const &r)
  386. {
  387. return l>=string_key::unowned(r);
  388. }
  389. ///
  390. /// Compare two strings
  391. ///
  392. inline bool operator>=(std::string const &l,string_key const &r)
  393. {
  394. return string_key::unowned(l) >= r;
  395. }
  396. ///
  397. /// Compare two strings
  398. ///
  399. inline bool operator<(string_key const &l,char const *r)
  400. {
  401. return l<string_key::unowned(r);
  402. }
  403. ///
  404. /// Compare two strings
  405. ///
  406. inline bool operator<(char const *l,string_key const &r)
  407. {
  408. return string_key::unowned(l) < r;
  409. }
  410. ///
  411. /// Compare two strings
  412. ///
  413. inline bool operator<(string_key const &l,std::string const &r)
  414. {
  415. return l<string_key::unowned(r);
  416. }
  417. ///
  418. /// Compare two strings
  419. ///
  420. inline bool operator<(std::string const &l,string_key const &r)
  421. {
  422. return string_key::unowned(l) < r;
  423. }
  424. ///
  425. /// Compare two strings
  426. ///
  427. inline bool operator>(string_key const &l,char const *r)
  428. {
  429. return l>string_key::unowned(r);
  430. }
  431. ///
  432. /// Compare two strings
  433. ///
  434. inline bool operator>(char const *l,string_key const &r)
  435. {
  436. return string_key::unowned(l) > r;
  437. }
  438. ///
  439. /// Compare two strings
  440. ///
  441. inline bool operator>(string_key const &l,std::string const &r)
  442. {
  443. return l>string_key::unowned(r);
  444. }
  445. ///
  446. /// Compare two strings
  447. ///
  448. inline bool operator>(std::string const &l,string_key const &r)
  449. {
  450. return string_key::unowned(l) > r;
  451. }
  452. }
  453. #endif