PageRenderTime 48ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/src/String.cc

https://bitbucket.org/drainware/squid
C++ | 498 lines | 372 code | 77 blank | 49 comment | 33 complexity | 736aecf07ead8d4a27d88fb448e21151 MD5 | raw file
Possible License(s): GPL-2.0, BSD-3-Clause
  1. /*
  2. * $Id$
  3. *
  4. * DEBUG: section 67 String
  5. * AUTHOR: Duane Wessels
  6. *
  7. * SQUID Web Proxy Cache http://www.squid-cache.org/
  8. * ----------------------------------------------------------
  9. *
  10. * Squid is the result of efforts by numerous individuals from
  11. * the Internet community; see the CONTRIBUTORS file for full
  12. * details. Many organizations have provided support for Squid's
  13. * development; see the SPONSORS file for full details. Squid is
  14. * Copyrighted (C) 2001 by the Regents of the University of
  15. * California; see the COPYRIGHT file for full details. Squid
  16. * incorporates software developed and/or copyrighted by other
  17. * sources; see the CREDITS file for full details.
  18. *
  19. * This program is free software; you can redistribute it and/or modify
  20. * it under the terms of the GNU General Public License as published by
  21. * the Free Software Foundation; either version 2 of the License, or
  22. * (at your option) any later version.
  23. *
  24. * This program is distributed in the hope that it will be useful,
  25. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  26. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  27. * GNU General Public License for more details.
  28. *
  29. * You should have received a copy of the GNU General Public License
  30. * along with this program; if not, write to the Free Software
  31. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
  32. *
  33. */
  34. #include "squid.h"
  35. #include "Store.h"
  36. #include "TextException.h"
  37. int
  38. String::psize() const
  39. {
  40. Must(size() < INT_MAX);
  41. return size();
  42. }
  43. // low-level buffer allocation,
  44. // does not free old buffer and does not adjust or look at len_
  45. void
  46. String::allocBuffer(String::size_type sz)
  47. {
  48. PROF_start(StringInitBuf);
  49. assert (undefined());
  50. char *newBuffer = (char*)memAllocString(sz, &sz);
  51. setBuffer(newBuffer, sz);
  52. PROF_stop(StringInitBuf);
  53. }
  54. // low-level buffer assignment
  55. // does not free old buffer and does not adjust or look at len_
  56. void
  57. String::setBuffer(char *aBuf, String::size_type aSize)
  58. {
  59. assert(undefined());
  60. assert(aSize < 65536);
  61. buf_ = aBuf;
  62. size_ = aSize;
  63. }
  64. String::String (char const *aString) : size_(0), len_(0), buf_(NULL)
  65. {
  66. if (aString)
  67. allocAndFill(aString, strlen(aString));
  68. #if DEBUGSTRINGS
  69. StringRegistry::Instance().add(this);
  70. #endif
  71. }
  72. String &
  73. String::operator =(char const *aString)
  74. {
  75. reset(aString);
  76. return *this;
  77. }
  78. String &
  79. String::operator = (String const &old)
  80. {
  81. clean(); // TODO: optimize to avoid cleaning the buffer we can use
  82. if (old.size() > 0)
  83. allocAndFill(old.rawBuf(), old.size());
  84. return *this;
  85. }
  86. bool
  87. String::operator == (String const &that) const
  88. {
  89. if (0 == this->cmp(that))
  90. return true;
  91. return false;
  92. }
  93. bool
  94. String::operator != (String const &that) const
  95. {
  96. if (0 == this->cmp(that))
  97. return false;
  98. return true;
  99. }
  100. // public interface, makes sure that we clean the old buffer first
  101. void
  102. String::limitInit(const char *str, int len)
  103. {
  104. clean(); // TODO: optimize to avoid cleaning the buffer we can use
  105. allocAndFill(str, len);
  106. }
  107. // Allocates the buffer to fit the supplied string and fills it.
  108. // Does not clean.
  109. void
  110. String::allocAndFill(const char *str, int len)
  111. {
  112. PROF_start(StringAllocAndFill);
  113. assert(this && str);
  114. allocBuffer(len + 1);
  115. len_ = len;
  116. xmemcpy(buf_, str, len);
  117. buf_[len] = '\0';
  118. PROF_stop(StringAllocAndFill);
  119. }
  120. String::String (String const &old) : size_(0), len_(0), buf_(NULL)
  121. {
  122. if (old.size() > 0)
  123. allocAndFill(old.rawBuf(), old.size());
  124. #if DEBUGSTRINGS
  125. StringRegistry::Instance().add(this);
  126. #endif
  127. }
  128. void
  129. String::clean()
  130. {
  131. PROF_start(StringClean);
  132. assert(this);
  133. /* TODO if mempools has already closed this will FAIL!! */
  134. if (defined())
  135. memFreeString(size_, buf_);
  136. len_ = 0;
  137. size_ = 0;
  138. buf_ = NULL;
  139. PROF_stop(StringClean);
  140. }
  141. String::~String()
  142. {
  143. clean();
  144. #if DEBUGSTRINGS
  145. StringRegistry::Instance().remove(this);
  146. #endif
  147. }
  148. void
  149. String::reset(const char *str)
  150. {
  151. PROF_start(StringReset);
  152. clean(); // TODO: optimize to avoid cleaning the buffer if we can reuse it
  153. if (str)
  154. allocAndFill(str, strlen(str));
  155. PROF_stop(StringReset);
  156. }
  157. void
  158. String::append(const char *str, int len)
  159. {
  160. assert(this);
  161. assert(str && len >= 0);
  162. PROF_start(StringAppend);
  163. if (len_ + len < size_) {
  164. strncat(buf_, str, len);
  165. len_ += len;
  166. } else {
  167. // Create a temporary string and absorb it later.
  168. String snew;
  169. assert(len_ + len < 65536); // otherwise snew.len_ overflows below
  170. snew.len_ = len_ + len;
  171. snew.allocBuffer(snew.len_ + 1);
  172. if (len_)
  173. xmemcpy(snew.buf_, rawBuf(), len_);
  174. if (len)
  175. xmemcpy(snew.buf_ + len_, str, len);
  176. snew.buf_[snew.len_] = '\0';
  177. absorb(snew);
  178. }
  179. PROF_stop(StringAppend);
  180. }
  181. void
  182. String::append(char const *str)
  183. {
  184. assert (str);
  185. append (str, strlen(str));
  186. }
  187. void
  188. String::append (char chr)
  189. {
  190. char myString[2];
  191. myString[0]=chr;
  192. myString[1]='\0';
  193. append (myString, 1);
  194. }
  195. void
  196. String::append(String const &old)
  197. {
  198. append (old.rawBuf(), old.len_);
  199. }
  200. void
  201. String::absorb(String &old)
  202. {
  203. clean();
  204. setBuffer(old.buf_, old.size_);
  205. len_ = old.len_;
  206. old.size_ = 0;
  207. old.buf_ = NULL;
  208. old.len_ = 0;
  209. }
  210. String
  211. String::substr(String::size_type from, String::size_type to) const
  212. {
  213. // Must(from >= 0 && from < size());
  214. Must(from < size());
  215. Must(to > 0 && to <= size());
  216. Must(to > from);
  217. String rv;
  218. rv.limitInit(rawBuf()+from,to-from);
  219. return rv;
  220. }
  221. #if DEBUGSTRINGS
  222. void
  223. String::stat(StoreEntry *entry) const
  224. {
  225. storeAppendPrintf(entry, "%p : %d/%d \"%.*s\"\n",this,len_, size_, size(), rawBuf());
  226. }
  227. StringRegistry &
  228. StringRegistry::Instance()
  229. {
  230. return Instance_;
  231. }
  232. template <class C>
  233. int
  234. ptrcmp(C const &lhs, C const &rhs)
  235. {
  236. return lhs - rhs;
  237. }
  238. StringRegistry::StringRegistry()
  239. {
  240. #if DEBUGSTRINGS
  241. CacheManager::GetInstance()->registerAction("strings",
  242. "Strings in use in squid", Stat, 0, 1);
  243. #endif
  244. }
  245. void
  246. StringRegistry::add
  247. (String const *entry)
  248. {
  249. entries.insert(entry, ptrcmp);
  250. }
  251. void
  252. StringRegistry::remove
  253. (String const *entry)
  254. {
  255. entries.remove(entry, ptrcmp);
  256. }
  257. StringRegistry StringRegistry::Instance_;
  258. extern String::size_type memStringCount();
  259. void
  260. StringRegistry::Stat(StoreEntry *entry)
  261. {
  262. storeAppendPrintf(entry, "%lu entries, %lu reported from MemPool\n", (unsigned long) Instance().entries.elements, (unsigned long) memStringCount());
  263. Instance().entries.head->walk(Stater, entry);
  264. }
  265. void
  266. StringRegistry::Stater(String const * const & nodedata, void *state)
  267. {
  268. StoreEntry *entry = (StoreEntry *) state;
  269. nodedata->stat(entry);
  270. }
  271. #endif
  272. /* TODO: move onto String */
  273. int
  274. stringHasWhitespace(const char *s)
  275. {
  276. return strpbrk(s, w_space) != NULL;
  277. }
  278. /* TODO: move onto String */
  279. int
  280. stringHasCntl(const char *s)
  281. {
  282. unsigned char c;
  283. while ((c = (unsigned char) *s++) != '\0') {
  284. if (c <= 0x1f)
  285. return 1;
  286. if (c >= 0x7f && c <= 0x9f)
  287. return 1;
  288. }
  289. return 0;
  290. }
  291. /*
  292. * Similar to strtok, but has some rudimentary knowledge
  293. * of quoting
  294. */
  295. char *
  296. strwordtok(char *buf, char **t)
  297. {
  298. unsigned char *word = NULL;
  299. unsigned char *p = (unsigned char *) buf;
  300. unsigned char *d;
  301. unsigned char ch;
  302. int quoted = 0;
  303. if (!p)
  304. p = (unsigned char *) *t;
  305. if (!p)
  306. goto error;
  307. while (*p && xisspace(*p))
  308. p++;
  309. if (!*p)
  310. goto error;
  311. word = d = p;
  312. while ((ch = *p)) {
  313. switch (ch) {
  314. case '\\':
  315. p++;
  316. switch (*p) {
  317. case 'n':
  318. ch = '\n';
  319. break;
  320. case 'r':
  321. ch = '\r';
  322. break;
  323. default:
  324. ch = *p;
  325. break;
  326. }
  327. *d++ = ch;
  328. if (ch)
  329. p++;
  330. break;
  331. case '"':
  332. quoted = !quoted;
  333. p++;
  334. break;
  335. default:
  336. if (!quoted && xisspace(*p)) {
  337. p++;
  338. goto done;
  339. }
  340. *d++ = *p++;
  341. break;
  342. }
  343. }
  344. done:
  345. *d++ = '\0';
  346. error:
  347. *t = (char *) p;
  348. return (char *) word;
  349. }
  350. const char *
  351. checkNullString(const char *p)
  352. {
  353. return p ? p : "(NULL)";
  354. }
  355. const char *
  356. String::pos(char const *aString) const
  357. {
  358. if (undefined())
  359. return NULL;
  360. return strstr(termedBuf(), aString);
  361. }
  362. const char *
  363. String::pos(char const ch) const
  364. {
  365. if (undefined())
  366. return NULL;
  367. return strchr(termedBuf(), ch);
  368. }
  369. const char *
  370. String::rpos(char const ch) const
  371. {
  372. if (undefined())
  373. return NULL;
  374. return strrchr(termedBuf(), (ch));
  375. }
  376. String::size_type
  377. String::find(char const ch) const
  378. {
  379. const char *c;
  380. c=pos(ch);
  381. if (c==NULL)
  382. return npos;
  383. return c-rawBuf();
  384. }
  385. String::size_type
  386. String::find(char const *aString) const
  387. {
  388. const char *c;
  389. c=pos(aString);
  390. if (c==NULL)
  391. return npos;
  392. return c-rawBuf();
  393. }
  394. String::size_type
  395. String::rfind(char const ch) const
  396. {
  397. const char *c;
  398. c=rpos(ch);
  399. if (c==NULL)
  400. return npos;
  401. return c-rawBuf();
  402. }
  403. #ifndef _USE_INLINE_
  404. #include "String.cci"
  405. #endif