Leaked source code of windows server 2003
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.

506 lines
12 KiB

  1. /*++
  2. Copyright (c) Microsoft Corporation. All rights reserved.
  3. Module Name:
  4. INFSCAN
  5. safestring.h
  6. Abstract:
  7. Define SafeString<> template
  8. SafeString is our alternative to basic_string
  9. as basic_string is not thread-safe
  10. a basic_string can be obtained from SafeString and vice-versa
  11. History:
  12. Created July 2001 - JamieHun
  13. --*/
  14. #ifndef _INFSCAN_SAFESTRING_H_
  15. #define _INFSCAN_SAFESTRING_H_
  16. #include <string>
  17. template<class _E,
  18. class _Tr = std::char_traits<_E> >
  19. class SafeString_ {
  20. typedef SafeString_<_E, _Tr> _Myt;
  21. _E* pData;
  22. size_t nLen;
  23. //
  24. // safe ref-counting
  25. //
  26. long & RefCount(_E* p) {
  27. return reinterpret_cast<long*>(p)[-1];
  28. }
  29. void IncRef(_E* p) {
  30. if(p) {
  31. InterlockedIncrement(&RefCount(p));
  32. }
  33. }
  34. void DecRef(_E* p) {
  35. if(p && (InterlockedDecrement(&RefCount(p))==0)) {
  36. //
  37. // if this is the final release, delete
  38. //
  39. FreeString(p);
  40. }
  41. }
  42. _E* AllocString(size_t len) {
  43. //
  44. // allocate enough data for the refcount, the data
  45. // and terminating NULL
  46. // return pointer to data part
  47. //
  48. LPBYTE data = new BYTE[((len+1)*sizeof(_E)+sizeof(long))];
  49. return reinterpret_cast<_E*>(data+sizeof(long));
  50. }
  51. void FreeString(_E* p) {
  52. if(p) {
  53. //
  54. // translate to actual allocated data and delete
  55. //
  56. delete [] (reinterpret_cast<BYTE*>(p)-sizeof(long));
  57. }
  58. }
  59. void Erase() {
  60. //
  61. // release data (final release deletes)
  62. //
  63. DecRef(pData);
  64. pData = NULL;
  65. nLen = 0;
  66. }
  67. void Init(const _E* p,size_t len) {
  68. //
  69. // create a new string given pointer to string and length
  70. //
  71. if(!len) {
  72. Erase();
  73. } else {
  74. pData = AllocString(len);
  75. RefCount(pData)=1;
  76. _Tr::copy(pData,p,len);
  77. nLen = len;
  78. pData[nLen] = 0;
  79. }
  80. }
  81. void Init(const _E* p) {
  82. //
  83. // in this case, length is not known and p may be NULL
  84. //
  85. if(!p) {
  86. Erase();
  87. } else {
  88. Init(p,_Tr::length(p));
  89. }
  90. }
  91. void Copy(const _E *p) {
  92. //
  93. // copy, in the case where length is not known
  94. //
  95. if(p && p[0]) {
  96. _E *old = pData;
  97. Init(p);
  98. DecRef(old);
  99. } else {
  100. Erase();
  101. }
  102. }
  103. void Copy(const _E *p,size_t len) {
  104. //
  105. // copy in the case where length is known
  106. //
  107. if(len) {
  108. _E *old = pData;
  109. Init(p,len);
  110. DecRef(old);
  111. } else {
  112. Erase();
  113. }
  114. }
  115. void Copy(const _Myt & other) {
  116. //
  117. // don't need to do byte copy, just add a ref to original string
  118. //
  119. if(other.nLen) {
  120. _E *old = pData;
  121. IncRef(other.pData);
  122. pData = other.pData;
  123. nLen = other.nLen;
  124. DecRef(old);
  125. } else {
  126. Erase();
  127. }
  128. }
  129. void Copy(const std::basic_string<_E,_Tr> & other) {
  130. //
  131. // copying from basic string, need to make copy of actual data
  132. // in this case
  133. //
  134. if(other.length()) {
  135. _E *old = pData;
  136. Init(other.c_str(),other.length());
  137. DecRef(old);
  138. } else {
  139. Erase();
  140. }
  141. }
  142. void Concat(const _E *first,size_t flen,const _E *second,size_t slen) {
  143. //
  144. // concat second to end of first, both lengths known
  145. //
  146. if(flen && slen) {
  147. _E *old = pData;
  148. pData = AllocString(flen+slen);
  149. RefCount(pData)=1;
  150. _Tr::copy(pData,first,flen);
  151. _Tr::copy(pData+flen,second,slen);
  152. nLen=flen+slen;
  153. pData[nLen] = 0;
  154. DecRef(old);
  155. } else if(flen) {
  156. Init(first,flen);
  157. } else if(slen) {
  158. Init(second,slen);
  159. } else {
  160. Erase();
  161. }
  162. }
  163. void Concat(const _E *first,size_t flen,const _E *second) {
  164. //
  165. // concat second to end of first.
  166. // second length not known and pointer may be null
  167. //
  168. if(second) {
  169. Concat(first,flen,second,_Tr::length(second));
  170. } else {
  171. Init(first,flen);
  172. }
  173. }
  174. public:
  175. SafeString_() {
  176. //
  177. // Initializer, create empty string
  178. //
  179. pData = NULL;
  180. nLen = 0;
  181. }
  182. SafeString_(const _E *p) {
  183. //
  184. // Initializer, given LPCxSTR
  185. //
  186. pData = NULL;
  187. Copy(p);
  188. }
  189. SafeString_(const _E *p,size_t len) {
  190. //
  191. // Initializer, given LPCxSTR and length
  192. //
  193. pData = NULL;
  194. Copy(p,len);
  195. }
  196. SafeString_(const _Myt & other) {
  197. //
  198. // Initializer, refcount other string
  199. //
  200. pData = NULL;
  201. Copy(other);
  202. }
  203. SafeString_(const std::basic_string<_E,_Tr> & other) {
  204. //
  205. // Initializer, copy from basic_string
  206. //
  207. pData = NULL;
  208. Copy(other);
  209. }
  210. ~SafeString_() {
  211. //
  212. // destructor, delete(deref) string
  213. //
  214. Erase();
  215. }
  216. _Myt & operator =(const _E *p) {
  217. //
  218. // assignment
  219. //
  220. Copy(p);
  221. return *this;
  222. }
  223. _Myt & operator =(const _Myt & other) {
  224. //
  225. // assignment
  226. //
  227. Copy(other);
  228. return *this;
  229. }
  230. _Myt & operator =(const std::basic_string<_E,_Tr> & other) {
  231. //
  232. // assignment
  233. //
  234. Copy(other);
  235. return *this;
  236. }
  237. _Myt & operator +=(const _E *p) {
  238. //
  239. // append. If p is NULL, do nothing
  240. //
  241. if(p) {
  242. if(nLen) {
  243. Concat(pData,nLen,p);
  244. } else {
  245. Copy(p);
  246. }
  247. }
  248. return *this;
  249. }
  250. _Myt & operator +=(const _Myt & other) {
  251. //
  252. // append
  253. //
  254. if(other.nLen) {
  255. if(nLen) {
  256. Concat(pData,nLen,other.c_str(),other.nLen);
  257. } else {
  258. Copy(other);
  259. }
  260. }
  261. return *this;
  262. }
  263. _Myt & operator +=(const std::basic_string<_E,_Tr> & other) {
  264. //
  265. // append
  266. //
  267. if(other.length()) {
  268. if(nLen) {
  269. Concat(pData,nLen,other.c_str(),other.length());
  270. } else {
  271. Copy(other);
  272. }
  273. }
  274. return *this;
  275. }
  276. _Myt operator +(const _E *p) const {
  277. //
  278. // concat into new, or copy (left native)
  279. //
  280. if(p) {
  281. if(nLen) {
  282. _Myt n;
  283. n.Concat(pData,nLen,p);
  284. return n;
  285. } else {
  286. return _Myt(p);
  287. }
  288. } else {
  289. return *this;
  290. }
  291. }
  292. _Myt operator +(const _Myt & other) const {
  293. //
  294. // concat into new, or copy (left native)
  295. //
  296. if(other.nLen) {
  297. if(nLen) {
  298. _Myt n;
  299. n.Concat(pData,nLen,other.c_str(),other.nLen);
  300. return n;
  301. } else {
  302. return other;
  303. }
  304. } else {
  305. return *this;
  306. }
  307. }
  308. _Myt operator +(const std::basic_string<_E,_Tr> & other) const {
  309. //
  310. // concat into new, or copy (left native)
  311. //
  312. if(other.length()) {
  313. if(nLen) {
  314. _Myt n;
  315. n.Concat(pData,nLen,other.c_str(),other.length());
  316. return n;
  317. } else {
  318. return _Myt(other);
  319. }
  320. } else {
  321. return *this;
  322. }
  323. }
  324. friend _Myt operator +(const _E *first,const _Myt & second) {
  325. //
  326. // concat where left is not native but right is
  327. //
  328. if(first) {
  329. _Myt n;
  330. n.Concat(first,_Tr::length(first),second.c_str(),second.length());
  331. return n;
  332. } else {
  333. return second;
  334. }
  335. }
  336. friend _Myt operator +(const std::basic_string<_E,_Tr> & first,const _Myt & second) {
  337. //
  338. // concat where left is not native but right is
  339. //
  340. if(first.length()) {
  341. _Myt n;
  342. n.Concat(first.c_str(),first.length(),second.c_str(),second.length());
  343. return n;
  344. } else {
  345. return second;
  346. }
  347. }
  348. int compare(const _Myt & other) const {
  349. //
  350. // compare this string with another string
  351. // (force other string into SafeString if needed)
  352. //
  353. int sz = min(nLen,other.nLen);
  354. if(sz) {
  355. int cmp = _Tr::compare(pData,other.pData,sz);
  356. if(cmp != 0) {
  357. return cmp;
  358. }
  359. }
  360. if(nLen<other.nLen) {
  361. return -1;
  362. } else if(nLen>other.nLen) {
  363. return 1;
  364. } else {
  365. return 0;
  366. }
  367. }
  368. bool operator < (const _Myt & other) const {
  369. //
  370. // specific compare
  371. //
  372. return compare(other)<0;
  373. }
  374. bool operator > (const _Myt & other) const {
  375. //
  376. // specific compare
  377. //
  378. return compare(other)>0;
  379. }
  380. bool operator == (const _Myt & other) const {
  381. //
  382. // specific compare
  383. //
  384. return compare(other)==0;
  385. }
  386. operator const _E* () const {
  387. //
  388. // natively convert to LPCxSTR if needed
  389. // (temporary string)
  390. //
  391. return pData;
  392. }
  393. const _E & operator[](unsigned int pos) const {
  394. //
  395. // index into string (unsigned)
  396. //
  397. return pData[pos];
  398. }
  399. const _E & operator[](int pos) const {
  400. //
  401. // index into string (signed)
  402. //
  403. return pData[pos];
  404. }
  405. bool empty(void) const {
  406. //
  407. // return true if empty
  408. //
  409. return nLen==0;
  410. }
  411. const _E* c_str(void) const {
  412. //
  413. // explicit conversion to LPCxSTR
  414. // (temporary string)
  415. //
  416. return pData;
  417. }
  418. size_t length(void) const {
  419. //
  420. // length of string
  421. //
  422. return nLen;
  423. }
  424. _Myt substr(size_t base,size_t len = (size_t)(-1)) const {
  425. //
  426. // part of string
  427. // unless it returns the full string, creates new string
  428. //
  429. if(base>=nLen) {
  430. base = 0;
  431. len = 0;
  432. } else {
  433. len = min(len,nLen-base);
  434. }
  435. if(len == 0) {
  436. //
  437. // returns empty string
  438. //
  439. return SafeString();
  440. } else if(len == nLen) {
  441. //
  442. // returns full string
  443. //
  444. return *this;
  445. } else {
  446. //
  447. // returns literal copy of part of string
  448. //
  449. return SafeString(pData+base,len);
  450. }
  451. }
  452. };
  453. //
  454. // ostream/istream helpers
  455. //
  456. template<class _E, class _Tr> inline
  457. basic_ostream<_E, _Tr>& __cdecl operator<<(
  458. basic_ostream<_E, _Tr>& Output,
  459. const SafeString_<_E, _Tr>& Str)
  460. {
  461. size_t i;
  462. size_t len = Str.length();
  463. const _E* data = Str.c_str();
  464. for (i = 0; i < len; i++,data++) {
  465. if (_Tr::eq_int_type(_Tr::eof(),Output.rdbuf()->sputc(*data))) {
  466. break;
  467. }
  468. }
  469. return Output;
  470. }
  471. //
  472. // 3 variations of SafeString
  473. //
  474. typedef SafeString_<TCHAR> SafeString;
  475. typedef SafeString_<CHAR> SafeStringA;
  476. typedef SafeString_<WCHAR> SafeStringW;
  477. #endif //!_INFSCAN_SAFESTRING_H_