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.

1520 lines
64 KiB

  1. #if !defined(_WINDOWS_BCL_PURESTRING_H_INCLUDED_)
  2. #define _WINDOWS_BCL_PURESTRING_H_INCLUDED_
  3. #pragma once
  4. /*++
  5. Copyright (c) 2000 Microsoft Corporation
  6. Module Name:
  7. bcl_purestring.h
  8. Abstract:
  9. Abstract algorithms and definitions for a string class.
  10. Author:
  11. Michael Grier (MGrier) 2/6/2002
  12. Revision History:
  13. --*/
  14. #include <bcl_common.h>
  15. namespace BCL {
  16. class CBaseString { };
  17. template <typename TTraits> class CPureString;
  18. //
  19. // This is a pair of classes that manage buffers containing characters.
  20. //
  21. // We don't call it a "string class" because we want to have a more
  22. // pure model of a string (poolable non-mutable bodies); instead this is
  23. // a glorified "<x>CHAR *" where as you do common operations the buffer
  24. // is resized appropriately.
  25. //
  26. //
  27. // Important note:
  28. //
  29. // This class will not be fully functional with the BCL CUnicodeCharTraits class
  30. // since here in the BCL, we can't take a position about case insensitive
  31. // behavior or memory allocation.
  32. //
  33. // Thus, this is clearly just a base class that needs to be specialized in
  34. // conjunction with other specializations of the char traits class(es) to be
  35. // usable.
  36. //
  37. // -mgrier (1/23/2002)
  38. //
  39. template <typename TTraits> class CPureString : public CBaseString
  40. {
  41. friend TTraits;
  42. friend typename TTraits::TAccessor;
  43. protected:
  44. typedef typename TTraits::TChar TChar; // e.g. WCHAR (alternately, CHAR)
  45. typedef typename TTraits::TNonNativeChar TNonNativeChar; // e.g. CHAR (alternately, WCHAR)
  46. typedef typename TTraits::TMetaChar TMetaChar; // e.g. ULONG for a UCS-4 character
  47. typedef typename TTraits::TMutableString TMutableString; // PWSTR
  48. typedef typename TTraits::TConstantString TConstantString; // PCWSTR
  49. typedef typename TTraits::TSizeT TSizeT; // SIZE_T
  50. typedef typename TTraits::TCallDisposition TCallDisposition;
  51. typedef typename TTraits::TPublicErrorReturnType TPublicErrorReturnType;
  52. typedef typename TTraits::TAccessor TAccessor;
  53. typedef typename TTraits::TCaseInsensitivityData TCaseInsensitivityData;
  54. typedef typename TTraits::TComparisonResult TComparisonResult;
  55. typedef typename TTraits::TEncodingDataIn TEncodingDataIn;
  56. typedef typename TTraits::TEncodingDataOut TEncodingDataOut;
  57. typedef typename TTraits::TDecodingDataIn TDecodingDataIn;
  58. typedef typename TTraits::TDecodingDataOut TDecodingDataOut;
  59. typedef typename TTraits::TMutableNonNativeString TMutableNonNativeString;
  60. typedef typename TTraits::TConstantNonNativeString TConstantNonNativeString;
  61. typedef typename TTraits::TConstantNonNativePair TConstantNonNativePair;
  62. typedef typename TTraits::TMutableNonNativePair TMutableNonNativePair;
  63. typedef typename TTraits::TConstantPair TConstantPair;
  64. typedef typename TTraits::TMutablePair TMutablePair;
  65. // You may not instantiate an instance of this class directly; you need to provide a derived
  66. // class which adds allocation/deallocation particulars.
  67. inline CPureString() { }
  68. //
  69. // Note that somewhat counter-intuitively, there is neither an assignment operator,
  70. // copy constructor or constructor taking a TConstantString. This is necessary
  71. // because such a constructor would need to perform a dynamic allocation
  72. // if the path passed in were longer than nInlineChars which could fail and
  73. // since we do not throw exceptions, constructors may not fail. Instead the caller
  74. // must just perform the default construction and then use the Assign() member
  75. // function, remembering of course to check its return status.
  76. //
  77. ~CPureString()
  78. {
  79. BCL_ASSERT(this->NoAccessors());
  80. }
  81. inline void IntegrityCheck() const { TTraits::IntegrityCheck(this); }
  82. inline TCallDisposition __fastcall NoAccessorsCheck() const { return TTraits::NoAccessorsCheck(this); }
  83. inline bool AnyAccessors() const { return TTraits::AnyAccessors(this); }
  84. inline bool NoAccessors() const { return TTraits::NoAccessors(this); }
  85. inline TSizeT GetAccessorCount() const { return TTraits::GetAccessorCount(this); }
  86. inline TCallDisposition AttachAccessor(TAccessor *pAccessor) { return TTraits::AddAccessor(this, pAccessor); }
  87. inline void DetachAccessor(TAccessor *pAccessor) { TTraits::RemoveAccessor(this, pAccessor); }
  88. inline TConstantString GetBufferPtr() const { return TTraits::GetBufferPtr(this); }
  89. inline TSizeT GetBufferCch() const { return TTraits::GetBufferCch(this); }
  90. inline void SetBufferPointerAndCount(TMutableString psz, TSizeT cch) { TTraits::SetBufferPointerAndCount(this, psz, cch); }
  91. inline TSizeT GetStringCch() const { return TTraits::GetStringCch(this); }
  92. inline bool StringCchLegal(TSizeT cch) const { return TTraits::StringCchLegal(cch); }
  93. inline bool StringCchLegal(const TConstantPair &rpair) const { return TTraits::StringCchLegal(rpair.GetCount()); }
  94. inline TMutableString GetMutableBufferPtr() { return TTraits::GetMutableBufferPtr(this); }
  95. inline void SetStringCch(TSizeT cch) { TTraits::SetStringCch(this, cch); }
  96. // We make an explicit assumption here that the derived type holds a pair object for the
  97. // buffer length and pointer, but the "effective string length and pointer" aren't
  98. // stored together in a single pair object. (This would require having two copies of
  99. // the buffer pointer - one in the buffer pair and one in the string pair.)
  100. //
  101. // Instead we do not provide a mutable string pair operation; you can get a constant
  102. // string pair but almost certainly what you'll get back is a temporary object.
  103. inline const TConstantPair &BufferPair() const { return TTraits::BufferPair(this); }
  104. inline TMutablePair &MutableBufferPair() { return TTraits::MutableBufferPair(this); }
  105. inline TMutablePair GetMutableBufferPair() { return TTraits::MutableBufferPair(this); } // return a copy
  106. inline const TMutablePair GetOffsetMutableBufferPair(TSizeT cchOffset) { return TTraits::GetOffsetMutableBufferPair(this, cchOffset); }
  107. inline const TConstantPair GetStringPair() const { return TTraits::GetStringPair(this); }
  108. inline const TConstantString GetStringPtr() const { return TTraits::GetStringPair(this).GetPointer(); }
  109. template <typename TSomeCharType>
  110. static inline bool IsValidParameter(const CConstantPointerAndCountPair<TSomeCharType, TSizeT> &rpair)
  111. {
  112. return (rpair.GetPointer() != NULL) || (rpair.GetCount() == 0);
  113. }
  114. template <typename TSomeCharType>
  115. static inline bool IsValidParameter(const CMutablePointerAndCountPair<TSomeCharType, TSizeT> &rpair)
  116. {
  117. return (rpair.GetPointer() != NULL) || (rpair.GetCount() == 0);
  118. }
  119. static inline bool IsValidParameter(TChar ch)
  120. {
  121. return true;
  122. }
  123. static inline bool IsValidParameter(TConstantString psz) { return true; }
  124. static inline bool IsValidParameter(TMutableString psz) { return true; }
  125. static inline bool IsValidParameter(TConstantNonNativeString psz) { return true; }
  126. static inline bool IsValidParameter(TMutableNonNativeString psz) { return true; }
  127. template <typename TSomeCharType>
  128. static inline TSizeT GetTemplateParameterBufferCch(const CConstantPointerAndCountPair<TSomeCharType, TSizeT> &rpair) { return rpair.GetCount(); }
  129. template <typename TSomeCharType>
  130. static inline TSizeT GetTemplateParameterBufferCch(const CMutablePointerAndCountPair<TSomeCharType, TSizeT> &rpair) { return rpair.GetCount(); }
  131. inline TCallDisposition EnsureBufferLargeEnoughPreserve(TSizeT cch)
  132. {
  133. return TTraits::EnsureBufferLargeEnoughPreserve(this, cch);
  134. }
  135. inline TCallDisposition EnsureBufferLargeEnoughNoPreserve(TSizeT cch)
  136. {
  137. return TTraits::EnsureBufferLargeEnoughNoPreserve(this, cch);
  138. }
  139. template <typename TSomeInputType>
  140. inline TCallDisposition ExpandBufferForInputPreserve(const TSomeInputType &rinput, TSizeT cchExtra, TSizeT &rcchString)
  141. {
  142. BCL_MAYFAIL_PROLOG
  143. TSizeT cch;
  144. TSizeT cchSum;
  145. rcchString = 0;
  146. BCL_PARAMETER_CHECK(this->IsValidParameter(rinput));
  147. BCL_PARAMETER_CHECK(this->StringCchLegal(cchExtra));
  148. BCL_IFCALLFAILED_EXIT(TTraits::DetermineRequiredCharacters(rinput, cch));
  149. BCL_IFCALLFAILED_EXIT(TTraits::AddWithOverflowCheck(cchExtra, cch, cchSum));
  150. BCL_IFCALLFAILED_EXIT(this->EnsureBufferLargeEnoughPreserve(cchSum));
  151. rcchString = cch;
  152. BCL_MAYFAIL_EPILOG_INTERNAL
  153. }
  154. template <typename TSomeInputType>
  155. inline TCallDisposition ExpandBufferForInputNoPreserve(const TSomeInputType &rinput, TSizeT cchExtra, TSizeT &rcchString)
  156. {
  157. BCL_MAYFAIL_PROLOG
  158. TSizeT cch;
  159. TSizeT cchSum;
  160. rcchString = 0;
  161. BCL_PARAMETER_CHECK(this->IsValidParameter(rinput));
  162. BCL_PARAMETER_CHECK(this->StringCchLegal(cchExtra));
  163. BCL_IFCALLFAILED_EXIT(TTraits::DetermineRequiredCharacters(rinput, cch));
  164. BCL_IFCALLFAILED_EXIT(TTraits::AddWithOverflowCheck(cchExtra, cch, cchSum));
  165. BCL_IFCALLFAILED_EXIT(this->EnsureBufferLargeEnoughNoPreserve(cchSum));
  166. rcchString = cch;
  167. BCL_MAYFAIL_EPILOG_INTERNAL
  168. }
  169. template <typename TSomeInputType>
  170. inline
  171. TPublicErrorReturnType
  172. __fastcall
  173. public_Assign(
  174. const TSomeInputType &rinput
  175. )
  176. {
  177. BCL_MAYFAIL_PROLOG
  178. BCL_PARAMETER_CHECK(this->IsValidParameter(rinput));
  179. this->IntegrityCheck();
  180. TSizeT cch;
  181. // it would seem innocuous to allow assigns that don't resize the buffer to not
  182. // invalidate accessors, but that makes finding such bugs subject to even more
  183. // strenuous coverage problems than this simple error. The simple rule is that
  184. // you should not have an accessor attached to a string buffer when you use
  185. // any of member functions that may mutate the value.
  186. BCL_IFCALLFAILED_EXIT(this->NoAccessorsCheck());
  187. BCL_IFCALLFAILED_EXIT(this->ExpandBufferForInputNoPreserve(rinput, 0, cch));
  188. if (cch > 0)
  189. {
  190. TSizeT cchWritten;
  191. BCL_IFCALLFAILED_EXIT(TTraits::CopyIntoBuffer(this->MutableBufferPair(), rinput, cchWritten));
  192. // cch was the buffer size we needed (including the trailing null); we don't need the trailing
  193. // null any more...
  194. this->SetStringCch(cch);
  195. }
  196. BCL_MAYFAIL_EPILOG_PUBLIC
  197. }
  198. template <typename TSomeConstantStringType>
  199. inline TPublicErrorReturnType
  200. public_AssignVa(TSomeConstantStringType pUnusedPrototype, TSizeT cStrings, va_list ap)
  201. {
  202. BCL_MAYFAIL_PROLOG
  203. this->IntegrityCheck();
  204. TMutablePair pairCursor;
  205. TSizeT cch = 0;
  206. TSizeT i;
  207. va_list ap2 = ap;
  208. BCL_PARAMETER_CHECK(cStrings >= 0);
  209. // it would seem innocuous to allow assigns that don't resize the buffer to not
  210. // invalidate accessors, but that makes finding such bugs subject to even more
  211. // strenuous coverage problems than this simple error. The simple rule is that
  212. // you should not have an accessor attached to a string buffer when you use
  213. // any of member functions that may mutate the value.
  214. BCL_IFCALLFAILED_EXIT(this->NoAccessorsCheck());
  215. for (i=0; i<cStrings; i++)
  216. {
  217. TSomeConstantStringType psz = va_arg(ap, TSomeConstantStringType);
  218. int cchArg = va_arg(ap, int);
  219. TSizeT cchThis = (cchArg < 0) ? TTraits::NullTerminatedStringLength(psz) : static_cast<TSizeT>(cchArg);
  220. TSizeT cchRequired;
  221. BCL_IFCALLFAILED_EXIT(TTraits::DetermineRequiredCharacters(TConstantPair(psz, cchThis), cchRequired));
  222. BCL_IFCALLFAILED_EXIT(TTraits::AddWithOverflowCheck(cch, cchRequired, cch));
  223. }
  224. BCL_IFCALLFAILED_EXIT(this->EnsureBufferLargeEnoughNoPreserve(cch));
  225. pairCursor.SetPointerAndCount(this->GetMutableBufferPtr(), cch);
  226. for (i=0; i<cStrings; i++)
  227. {
  228. TSomeConstantStringType psz = va_arg(ap2, TSomeConstantStringType);
  229. int cchArg = va_arg(ap2, int);
  230. TSizeT cchThis = (cchArg < 0) ? TTraits::NullTerminatedStringLength(psz) : static_cast<TSizeT>(cchArg);
  231. BCL_IFCALLFAILED_EXIT(TTraits::CopyIntoBufferAndAdvanceCursor(pairCursor, TConstantPair(psz, cchThis)));
  232. }
  233. this->SetStringCch(cch);
  234. BCL_MAYFAIL_EPILOG_PUBLIC
  235. }
  236. template <typename TSomePairType>
  237. inline TPublicErrorReturnType
  238. public_AssignArray(TSizeT cStrings, const TSomePairType *prgpairs)
  239. {
  240. BCL_MAYFAIL_PROLOG
  241. this->IntegrityCheck();
  242. TMutablePair pairCursor;
  243. TSizeT cch = 0;
  244. TSizeT i;
  245. BCL_PARAMETER_CHECK(cStrings >= 0);
  246. // it would seem innocuous to allow assigns that don't resize the buffer to not
  247. // invalidate accessors, but that makes finding such bugs subject to even more
  248. // strenuous coverage problems than this simple error. The simple rule is that
  249. // you should not have an accessor attached to a string buffer when you use
  250. // any of member functions that may mutate the value.
  251. BCL_IFCALLFAILED_EXIT(this->NoAccessorsCheck());
  252. for (i=0; i<cStrings; i++)
  253. {
  254. TSizeT cchRequired;
  255. BCL_IFCALLFAILED_EXIT(TTraits::DetermineRequiredCharacters(prgpairs[i], cchRequired));
  256. BCL_IFCALLFAILED_EXIT(TTraits::AddWithOverflowCheck(cch, cchRequired, cch));
  257. }
  258. BCL_IFCALLFAILED_EXIT(this->EnsureBufferLargeEnoughNoPreserve(cch));
  259. pairCursor.SetPointerAndCount(this->GetMutableBufferPtr(), cch);
  260. for (i=0; i<cStrings; i++)
  261. BCL_IFCALLFAILED_EXIT(TTraits::CopyIntoBufferAndAdvanceCursor(pairCursor, prgpairs[i]));
  262. this->SetStringCch(cch);
  263. BCL_MAYFAIL_EPILOG_PUBLIC
  264. }
  265. template <typename TSomeInputType>
  266. inline
  267. TPublicErrorReturnType
  268. public_Assign(
  269. const TDecodingDataIn &rddi,
  270. const TSomeInputType &rinput,
  271. TDecodingDataOut &rddo
  272. )
  273. {
  274. BCL_MAYFAIL_PROLOG
  275. this->IntegrityCheck();
  276. BCL_PARAMETER_CHECK(this->IsValidParameter(rinput));
  277. SIZE_T cch;
  278. BCL_IFCALLFAILED_EXIT(TTraits::DetermineRequiredCharacters(rddi, rinput, rddo, cch));
  279. BCL_IFCALLFAILED_EXIT(this->EnsureBufferLargeEnoughNoPreserve(cch));
  280. BCL_IFCALLFAILED_EXIT(TTraits::CopyIntoBuffer(this->GetMutableBufferPair(), rddi, rinput, rddo));
  281. this->SetStringCch(cch);
  282. BCL_MAYFAIL_EPILOG_PUBLIC
  283. }
  284. // Note: the sematics of the *Fill() functions is to try to get the
  285. // string to a particular length, not to add "n" instances of the
  286. // input. Thus you might use this to pad a string with dots to get to
  287. // a certain number of characters. If you want to work with repetitions
  288. // of the input, use the *Repeat() functions.
  289. template <typename TSomeInputType>
  290. inline TPublicErrorReturnType
  291. public_AssignFill(
  292. const TSomeInputType &rinput,
  293. TSizeT cchResultantStringMaxLength,
  294. TSizeT &rcchExtra // if the length of rinput converted to the native buffer type
  295. // (think Unicode -> NonNative or vice versa) is not a multiple
  296. // of cchResultantStringMaxLength, the remainder is
  297. // returned here in rcchExtra.
  298. )
  299. {
  300. BCL_MAYFAIL_PROLOG
  301. // TSizeT cchSum;
  302. TSizeT cchInput;
  303. TSizeT cchActual = 0;
  304. TSizeT cchExtra = 0;
  305. BCL_PARAMETER_CHECK(this->IsValidParameter(rinput));
  306. BCL_IFCALLFAILED_EXIT(this->NoAccessorsCheck());
  307. if (cchResultantStringMaxLength > 0)
  308. {
  309. BCL_IFCALLFAILED_EXIT(TTraits::DetermineRequiredCharacters(rinput, cchInput));
  310. if (cchInput > 0)
  311. {
  312. TSizeT cRepetitions;
  313. TMutablePair pairCursor;
  314. cRepetitions = cchResultantStringMaxLength / cchInput;
  315. cchExtra = cchResultantStringMaxLength % cchInput;
  316. BCL_IFCALLFAILED_EXIT(this->EnsureBufferLargeEnoughNoPreserve(cchResultantStringMaxLength));
  317. pairCursor = this->GetMutableBufferPair();
  318. while (cRepetitions > 0)
  319. {
  320. BCL_IFCALLFAILED_EXIT(TTraits::CopyIntoBufferAndAdvanceCursor(pairCursor, rinput));
  321. cRepetitions--;
  322. }
  323. cchActual = cchResultantStringMaxLength - cchExtra;
  324. }
  325. else
  326. {
  327. cchExtra = cchResultantStringMaxLength;
  328. }
  329. }
  330. this->SetStringCch(cchActual);
  331. rcchExtra = cchExtra;
  332. BCL_MAYFAIL_EPILOG_PUBLIC
  333. }
  334. template <typename TSomeInputType>
  335. inline TPublicErrorReturnType
  336. public_AssignRepeat(
  337. const TSomeInputType &rinput,
  338. TSizeT cRepetitions
  339. )
  340. {
  341. BCL_MAYFAIL_PROLOG
  342. TSizeT cchTotal = 0;
  343. BCL_PARAMETER_CHECK(this->IsValidParameter(rinput));
  344. BCL_IFCALLFAILED_EXIT(this->NoAccessorsCheck());
  345. if (cRepetitions > 0)
  346. {
  347. TSizeT cchInput;
  348. BCL_IFCALLFAILED_EXIT(TTraits::DetermineRequiredCharacters(rinput, cchInput));
  349. if (cchInput > 0)
  350. {
  351. TMutablePair pairCursor;
  352. BCL_IFCALLFAILED_EXIT(TTraits::MultiplyWithOverflowCheck(cchInput, cRepetitions, cchTotal));
  353. BCL_IFCALLFAILED_EXIT(this->EnsureBufferLargeEnoughNoPreserve(cchTotal));
  354. pairCursor = this->GetMutableBufferPair();
  355. while (cRepetitions > 0)
  356. {
  357. BCL_IFCALLFAILED_EXIT(TTraits::CopyIntoBufferAndAdvanceCursor(pairCursor, rinput));
  358. cRepetitions--;
  359. }
  360. }
  361. }
  362. this->SetStringCch(cchTotal);
  363. BCL_MAYFAIL_EPILOG_PUBLIC
  364. }
  365. template <typename TSomeConstantStringType>
  366. inline TPublicErrorReturnType
  367. public_AppendVa(TSomeConstantStringType pUnusedPrototype, TSizeT cStrings, va_list ap)
  368. {
  369. BCL_MAYFAIL_PROLOG
  370. this->IntegrityCheck();
  371. TMutablePair pairCursor;
  372. TSizeT cch = 0;
  373. TSizeT cchTemp;
  374. TSizeT i;
  375. va_list ap2 = ap;
  376. BCL_PARAMETER_CHECK(cStrings >= 0);
  377. // it would seem innocuous to allow assigns that don't resize the buffer to not
  378. // invalidate accessors, but that makes finding such bugs subject to even more
  379. // strenuous coverage problems than this simple error. The simple rule is that
  380. // you should not have an accessor attached to a string buffer when you use
  381. // any of member functions that may mutate the value.
  382. BCL_IFCALLFAILED_EXIT(this->NoAccessorsCheck());
  383. for (i=0; i<cStrings; i++)
  384. {
  385. TSomeConstantStringType psz = va_arg(ap, TSomeConstantStringType);
  386. int cchArg = va_arg(ap, int);
  387. TSizeT cchThis = (cchArg < 0) ? TTraits::NullTerminatedStringLength(psz) : static_cast<TSizeT>(cchArg);
  388. TSizeT cchRequired;
  389. BCL_IFCALLFAILED_EXIT(TTraits::DetermineRequiredCharacters(TConstantPair(psz, cchThis), cchRequired));
  390. BCL_IFCALLFAILED_EXIT(TTraits::AddWithOverflowCheck(cch, cchRequired, cch));
  391. }
  392. BCL_IFCALLFAILED_EXIT(TTraits::AddWithOverflowCheck(cch, this->GetStringCch(), cch));
  393. BCL_IFCALLFAILED_EXIT(this->EnsureBufferLargeEnoughPreserve(cch));
  394. pairCursor.SetPointerAndCount(this->GetOffsetMutableBufferPtr(this->GetStringCch()), cch);
  395. for (i=0; i<cStrings; i++)
  396. {
  397. TSomeConstantStringType psz = va_arg(ap2, TSomeConstantStringType);
  398. int cchArg = va_arg(ap2, int);
  399. TSizeT cchThis = (cchArg < 0) ? TTraits::NullTerminatedStringLength(psz) : static_cast<TSizeT>(cchArg);
  400. BCL_IFCALLFAILED_EXIT(TTraits::CopyIntoBufferAndAdvanceCursor(pairCursor, TConstantPair(psz, cchThis)));
  401. }
  402. this->SetStringCch(cch);
  403. BCL_MAYFAIL_EPILOG_PUBLIC
  404. }
  405. template <typename TSomeInputType>
  406. inline TPublicErrorReturnType
  407. public_Append(
  408. const TSomeInputType &rinput
  409. )
  410. {
  411. BCL_MAYFAIL_PROLOG
  412. this->IntegrityCheck();
  413. BCL_PARAMETER_CHECK(this->IsValidParameter(rinput));
  414. TSizeT cch;
  415. BCL_IFCALLFAILED_EXIT(this->NoAccessorsCheck());
  416. BCL_IFCALLFAILED_EXIT(this->ExpandBufferForInputPreserve(rinput, this->GetStringCch(), cch));
  417. if (cch > 0)
  418. {
  419. TSizeT cchWritten;
  420. BCL_IFCALLFAILED_EXIT(
  421. TTraits::CopyIntoBuffer(
  422. this->GetOffsetMutableBufferPair(this->GetStringCch()),
  423. rinput,
  424. cchWritten));
  425. // We can assume that adding cch to the current string cch does not
  426. // overflow since ExpandBufferForInputPreserve would have had the same
  427. // overflow
  428. this->SetStringCch(this->GetStringCch() + cch);
  429. }
  430. BCL_MAYFAIL_EPILOG_PUBLIC
  431. }
  432. template <typename TSomeInputType>
  433. inline
  434. TPublicErrorReturnType
  435. public_Append(
  436. const TDecodingDataIn &rddi,
  437. const TSomeInputType &rinput,
  438. TDecodingDataOut &rddo
  439. )
  440. {
  441. BCL_MAYFAIL_PROLOG
  442. this->IntegrityCheck();
  443. BCL_PARAMETER_CHECK(this->IsValidParameter(rinput));
  444. SIZE_T cch;
  445. BCL_IFCALLFAILED_EXIT(TTraits::DetermineRequiredCharacters(rddi, rinput, rddo, cch));
  446. BCL_IFCALLFAILED_EXIT(TTraits::AddWithOverflowCheck(cch, this->GetStringCch(), cch));
  447. BCL_IFCALLFAILED_EXIT(this->EnsureBufferLargeEnoughPreserve(cch));
  448. BCL_IFCALLFAILED_EXIT(TTraits::CopyIntoBuffer(this->GetOffsetMutableBufferPair(this->GetStringCch()), rddi, rinput, rddo));
  449. this->SetStringCch(cch);
  450. BCL_MAYFAIL_EPILOG_PUBLIC
  451. }
  452. template <typename TSomeInputType>
  453. inline TPublicErrorReturnType
  454. public_AppendArray(TSizeT cStrings, const TSomeInputType *prginput)
  455. {
  456. BCL_MAYFAIL_PROLOG
  457. this->IntegrityCheck();
  458. TMutablePair pairCursor;
  459. TSizeT cch = 0;
  460. TSizeT i;
  461. BCL_PARAMETER_CHECK((prginput != NULL) || (cStrings == 0));
  462. BCL_PARAMETER_CHECK(cStrings >= 0);
  463. // it would seem innocuous to allow assigns that don't resize the buffer to not
  464. // invalidate accessors, but that makes finding such bugs subject to even more
  465. // strenuous coverage problems than this simple error. The simple rule is that
  466. // you should not have an accessor attached to a string buffer when you use
  467. // any of member functions that may mutate the value.
  468. BCL_IFCALLFAILED_EXIT(this->NoAccessorsCheck());
  469. for (i=0; i<cStrings; i++)
  470. {
  471. TSizeT cchRequired;
  472. BCL_IFCALLFAILED_EXIT(TTraits::DetermineRequiredCharacters(prginput[i], cchRequired));
  473. BCL_IFCALLFAILED_EXIT(TTraits::AddWithOverflowCheck(cch, cchRequired, cch));
  474. }
  475. BCL_IFCALLFAILED_EXIT(TTraits::AddWithOverflowCheck(cch, this->GetStringCch(), cch));
  476. BCL_IFCALLFAILED_EXIT(this->EnsureBufferLargeEnoughPreserve(cch));
  477. pairCursor = this->GetOffsetMutableBufferPair(this->GetStringCch());
  478. for (i=0; i<cStrings; i++)
  479. BCL_IFCALLFAILED_EXIT(TTraits::CopyIntoBufferAndAdvanceCursor(pairCursor, prginput[i]));
  480. this->SetStringCch(cch);
  481. BCL_MAYFAIL_EPILOG_PUBLIC
  482. }
  483. // Note: the sematics of the *Fill() functions is to try to get the
  484. // string to a particular length, not to add "n" instances of the
  485. // input. Thus you might use this to pad a string with dots to get to
  486. // a certain number of characters. If you want to work with repetitions
  487. // of the input, use the *Repeat() functions.
  488. template <typename TSomeInputType>
  489. inline TPublicErrorReturnType
  490. public_AppendFill(
  491. const TSomeInputType &rinput,
  492. TSizeT cchResultantStringMaxLength,
  493. TSizeT &rcchExtra // if the length of rinput converted to the native buffer type
  494. // (think Unicode -> NonNative or vice versa) is not a multiple
  495. // of cchResultantStringMaxLength, the remainder is
  496. // returned here in rcchExtra.
  497. )
  498. {
  499. BCL_MAYFAIL_PROLOG
  500. TSizeT cchInput;
  501. TSizeT cchExtra = 0;
  502. TSizeT cchString = this->GetStringCch();
  503. TSizeT cchActual = cchString;
  504. BCL_PARAMETER_CHECK(this->IsValidParameter(rinput));
  505. BCL_IFCALLFAILED_EXIT(this->NoAccessorsCheck());
  506. if (cchResultantStringMaxLength > cchString)
  507. {
  508. BCL_IFCALLFAILED_EXIT(TTraits::DetermineRequiredCharacters(rinput, cchInput));
  509. if (cchInput > 0)
  510. {
  511. TSizeT cRepetitions;
  512. TMutablePair pairBuffer;
  513. TSizeT cchAppendPartMaxLength = cchResultantStringMaxLength - cchString;
  514. cRepetitions = cchAppendPartMaxLength / cchInput;
  515. cchExtra = cchAppendPartMaxLength % cchInput;
  516. BCL_IFCALLFAILED_EXIT(this->EnsureBufferLargeEnoughPreserve(cchResultantStringMaxLength - cchExtra));
  517. pairBuffer = this->GetOffsetMutableBufferPair(cchString);
  518. while (cRepetitions > 0)
  519. {
  520. BCL_IFCALLFAILED_EXIT(TTraits::CopyIntoBufferAndAdvanceCursor(pairBuffer, rinput));
  521. cRepetitions--;
  522. }
  523. }
  524. else
  525. {
  526. // Zero input string; extra chars is simple diff (no
  527. // underflow since we already know that cchResultantStringMaxLength
  528. // is greater than cchString).
  529. cchExtra = cchResultantStringMaxLength - cchString;
  530. }
  531. cchActual = cchResultantStringMaxLength - cchExtra;
  532. }
  533. this->SetStringCch(cchActual);
  534. rcchExtra = cchExtra;
  535. BCL_MAYFAIL_EPILOG_PUBLIC
  536. }
  537. template <typename TSomeInputType>
  538. inline TPublicErrorReturnType
  539. public_AppendRepeat(
  540. const TSomeInputType &rinput,
  541. TSizeT cRepetitions
  542. )
  543. {
  544. BCL_MAYFAIL_PROLOG
  545. TSizeT cchString = this->GetStringCch();
  546. TSizeT cchTotal = cchString;
  547. BCL_PARAMETER_CHECK(this->IsValidParameter(rinput));
  548. BCL_IFCALLFAILED_EXIT(this->NoAccessorsCheck());
  549. if (cRepetitions > 0)
  550. {
  551. TSizeT cchInput;
  552. BCL_IFCALLFAILED_EXIT(TTraits::DetermineRequiredCharacters(rinput, cchInput));
  553. if (cchInput > 0)
  554. {
  555. TMutablePair pairCursor;
  556. BCL_IFCALLFAILED_EXIT(TTraits::MultiplyWithOverflowCheck(cchInput, cRepetitions, cchTotal));
  557. BCL_IFCALLFAILED_EXIT(TTraits::AddWithOverflowCheck(cchTotal, cchString, cchTotal));
  558. BCL_IFCALLFAILED_EXIT(this->EnsureBufferLargeEnoughPreserve(cchTotal));
  559. pairCursor = this->GetOffsetMutableBufferPair(cchString);
  560. while (cRepetitions > 0)
  561. {
  562. BCL_IFCALLFAILED_EXIT(TTraits::CopyIntoBufferAndAdvanceCursor(pairCursor, rinput));
  563. cRepetitions--;
  564. }
  565. }
  566. }
  567. this->SetStringCch(cchTotal);
  568. BCL_MAYFAIL_EPILOG_PUBLIC
  569. }
  570. template <typename TSomeInputType>
  571. inline TPublicErrorReturnType
  572. public_Prepend(
  573. const TSomeInputType &rinput
  574. )
  575. {
  576. BCL_MAYFAIL_PROLOG
  577. this->IntegrityCheck();
  578. BCL_PARAMETER_CHECK(this->IsValidParameter(rinput));
  579. TSizeT cchInput;
  580. BCL_IFCALLFAILED_EXIT(this->NoAccessorsCheck());
  581. TSizeT cchSum;
  582. TSizeT cchWritten;
  583. BCL_IFCALLFAILED_EXIT(TTraits::DetermineRequiredCharacters(rinput, cchInput));
  584. BCL_IFCALLFAILED_EXIT(TTraits::AddWithOverflowCheck(this->GetStringCch(), cchInput, cchSum));
  585. BCL_IFCALLFAILED_EXIT(this->EnsureBufferLargeEnoughPreserve(cchSum));
  586. // Move current buffer "up"
  587. BCL::MoveBytes(this->GetMutableBufferPtr() + cchInput, this->GetBufferPtr(), this->GetStringCch() * sizeof(TChar));
  588. // Copy from the source string into the buffer.
  589. BCL_IFCALLFAILED_EXIT(
  590. TTraits::CopyIntoBuffer(
  591. this->MutableBufferPair(),
  592. rinput,
  593. cchWritten));
  594. this->SetStringCch(cchSum);
  595. BCL_MAYFAIL_EPILOG_PUBLIC
  596. }
  597. template <typename TSomeInputType>
  598. inline
  599. TPublicErrorReturnType
  600. public_Prepend(
  601. const TDecodingDataIn &rddi,
  602. const TSomeInputType &rinput,
  603. TDecodingDataOut &rddo
  604. )
  605. {
  606. BCL_MAYFAIL_PROLOG
  607. this->IntegrityCheck();
  608. BCL_PARAMETER_CHECK(this->IsValidParameter(rinput));
  609. SIZE_T cch;
  610. BCL_IFCALLFAILED_EXIT(TTraits::DetermineRequiredCharacters(rddi, rinput, rddo, cch));
  611. BCL_IFCALLFAILED_EXIT(TTraits::AddWithOverflowCheck(cch, this->GetStringCch(), cch));
  612. BCL_IFCALLFAILED_EXIT(this->EnsureBufferLargeEnoughPreserve(cch));
  613. BCL_IFCALLFAILED_EXIT(TTraits::CopyIntoBuffer(this->GetMutableBufferPair(), rddi, rinput, rddo));
  614. this->SetStringCch(cch);
  615. BCL_MAYFAIL_EPILOG_PUBLIC
  616. }
  617. template <typename TSomeInputType>
  618. inline TPublicErrorReturnType
  619. public_PrependArray(TSizeT cStrings, const TSomeInputType *prginput)
  620. {
  621. BCL_MAYFAIL_PROLOG
  622. this->IntegrityCheck();
  623. TMutablePair pairCursor;
  624. TSizeT cch = 0;
  625. TSizeT i;
  626. TSizeT cchString = this->GetStringCch();
  627. BCL_PARAMETER_CHECK((prginput != NULL) || (cStrings == 0));
  628. BCL_PARAMETER_CHECK(cStrings >= 0);
  629. // it would seem innocuous to allow assigns that don't resize the buffer to not
  630. // invalidate accessors, but that makes finding such bugs subject to even more
  631. // strenuous coverage problems than this simple error. The simple rule is that
  632. // you should not have an accessor attached to a string buffer when you use
  633. // any of member functions that may mutate the value.
  634. BCL_IFCALLFAILED_EXIT(this->NoAccessorsCheck());
  635. for (i=0; i<cStrings; i++)
  636. {
  637. TSizeT cchRequired;
  638. BCL_IFCALLFAILED_EXIT(TTraits::DetermineRequiredCharacters(prginput[i], cchRequired));
  639. BCL_IFCALLFAILED_EXIT(TTraits::AddWithOverflowCheck(cch, cchRequired, cch));
  640. }
  641. BCL_IFCALLFAILED_EXIT(TTraits::AddWithOverflowCheck(cch, cchString, cch));
  642. BCL_IFCALLFAILED_EXIT(this->EnsureBufferLargeEnoughPreserve(cch));
  643. // Move current buffer "up"
  644. BCL::MoveBytes(this->GetMutableBufferPtr() + cchString, this->GetBufferPtr(), cchString * sizeof(TChar));
  645. pairCursor = this->GetMutableBufferPair();
  646. for (i=0; i<cStrings; i++)
  647. BCL_IFCALLFAILED_EXIT(TTraits::CopyIntoBufferAndAdvanceCursor(pairCursor, prginput[i]));
  648. this->SetStringCch(cch);
  649. BCL_MAYFAIL_EPILOG_PUBLIC
  650. }
  651. template <typename TSomeOutputType>
  652. inline
  653. TPublicErrorReturnType
  654. public_CopyOut(
  655. const TEncodingDataIn &rddi,
  656. const TSomeOutputType &routput,
  657. TEncodingDataOut &rddo,
  658. TSizeT &rcchWritten
  659. ) const
  660. {
  661. BCL_MAYFAIL_PROLOG
  662. this->IntegrityCheck();
  663. TConstantPair pairString = this->GetStringPair();
  664. TSizeT cchOriginal, cchToCopy, cchBufferWritten;
  665. BCL_PARAMETER_CHECK(this->IsValidParameter(routput));
  666. cchOriginal = pairString.GetCount();
  667. BCL_IFCALLFAILED_EXIT(TTraits::MapStringCchToBufferCch(cchOriginal, cchToCopy));
  668. pairString.SetCount(cchToCopy);
  669. BCL_IFCALLFAILED_EXIT(TTraits::CopyIntoBuffer(routput, rddi, pairString, rddo, cchBufferWritten));
  670. BCL_IFCALLFAILED_EXIT(TTraits::MapBufferCchToStringCch(cchBufferWritten, rcchWritten));
  671. BCL_MAYFAIL_EPILOG_PUBLIC
  672. }
  673. inline
  674. TPublicErrorReturnType
  675. public_CopyOut(
  676. const TEncodingDataIn &rddi,
  677. TMutableNonNativeString &routput,
  678. TEncodingDataOut &rddo,
  679. TSizeT &rcchWritten
  680. ) const
  681. {
  682. BCL_MAYFAIL_PROLOG
  683. this->IntegrityCheck();
  684. BCL_PARAMETER_CHECK(this->IsValidParameter(routput));
  685. BCL_IFCALLFAILED_EXIT(TTraits::AllocateAndCopyIntoBuffer(routput, rddi, this->GetStringPair(), rddo, rcchWritten));
  686. BCL_MAYFAIL_EPILOG_PUBLIC
  687. }
  688. inline
  689. TPublicErrorReturnType
  690. public_CopyOut(
  691. const TMutablePair &routput,
  692. TSizeT &rcchWritten
  693. ) const
  694. {
  695. BCL_MAYFAIL_PROLOG
  696. this->IntegrityCheck();
  697. TConstantPair pairString = this->GetStringPair();
  698. TSizeT cchOriginal;
  699. TSizeT cchToCopy;
  700. TSizeT cchBufferWritten;
  701. BCL_PARAMETER_CHECK(this->IsValidParameter(routput));
  702. // Apply null termination length as applicable
  703. cchOriginal = pairString.GetCount();
  704. BCL_IFCALLFAILED_EXIT(TTraits::MapStringCchToBufferCch(pairString.GetCount(), cchToCopy));
  705. pairString.SetCount(cchToCopy);
  706. BCL_IFCALLFAILED_EXIT(TTraits::CopyIntoBuffer(routput, pairString, cchBufferWritten));
  707. BCL_IFCALLFAILED_EXIT(TTraits::MapBufferCchToStringCch(cchBufferWritten, rcchWritten));
  708. BCL_MAYFAIL_EPILOG_PUBLIC
  709. }
  710. inline
  711. TPublicErrorReturnType
  712. public_CopyOut(
  713. TMutableString &rstringout,
  714. TSizeT &rcchWritten
  715. ) const
  716. {
  717. BCL_MAYFAIL_PROLOG
  718. this->IntegrityCheck();
  719. BCL_PARAMETER_CHECK(this->IsValidParameter(rstringout));
  720. BCL_IFCALLFAILED_EXIT(TTraits::AllocateAndCopyIntoBuffer(rstringout, this->GetStringPair(), rcchWritten));
  721. BCL_MAYFAIL_EPILOG_PUBLIC
  722. }
  723. inline VOID public_Clear(bool fFreeStorage = false)
  724. {
  725. this->IntegrityCheck();
  726. // You can't free the storage if there's an attached accessor
  727. BCL_ASSERT(!fFreeStorage || this->NoAccessors());
  728. if (this->NoAccessors())
  729. {
  730. if (fFreeStorage)
  731. TTraits::DeallocateDynamicBuffer(this);
  732. this->SetStringCch(0);
  733. }
  734. }
  735. inline TPublicErrorReturnType public_UpperCase(const TCaseInsensitivityData &rcid)
  736. {
  737. BCL_MAYFAIL_PROLOG
  738. this->IntegrityCheck();
  739. BCL_IFCALLFAILED_EXIT(TTraits::UpperCase(this, rcid));
  740. BCL_MAYFAIL_EPILOG_PUBLIC
  741. }
  742. inline TPublicErrorReturnType public_LowerCase(const TCaseInsensitivityData &rcid)
  743. {
  744. BCL_MAYFAIL_PROLOG
  745. this->IntegrityCheck();
  746. BCL_IFCALLFAILED_EXIT(TTraits::LowerCase(this, rcid));
  747. BCL_MAYFAIL_EPILOG_PUBLIC
  748. }
  749. template <typename TSomeInputType>
  750. inline TPublicErrorReturnType public_Compare(
  751. const TSomeInputType &rinput,
  752. TComparisonResult &rcrOut
  753. ) const
  754. {
  755. BCL_MAYFAIL_PROLOG
  756. this->IntegrityCheck();
  757. BCL_PARAMETER_CHECK(this->IsValidParameter(rinput));
  758. BCL_IFCALLFAILED_EXIT(TTraits::CompareStrings(this->GetStringPair(), rinput, rcrOut));
  759. BCL_MAYFAIL_EPILOG_PUBLIC
  760. }
  761. template <typename TSomeInputType>
  762. inline TPublicErrorReturnType public_CompareI(
  763. const TSomeInputType &rinput,
  764. const TCaseInsensitivityData &rcid,
  765. TComparisonResult &rcrOut
  766. ) const
  767. {
  768. BCL_MAYFAIL_PROLOG
  769. this->IntegrityCheck();
  770. BCL_PARAMETER_CHECK(this->IsValidParameter(rinput));
  771. BCL_IFCALLFAILED_EXIT(TTraits::CompareStringsI(this->GetStringPair(), rinput, rcid, rcrOut));
  772. BCL_MAYFAIL_EPILOG_PUBLIC
  773. }
  774. template <typename TSomeInputType>
  775. inline TPublicErrorReturnType public_Equals(
  776. const TSomeInputType &rinputCandidate,
  777. bool &rfMatches
  778. ) const
  779. {
  780. BCL_MAYFAIL_PROLOG
  781. this->IntegrityCheck();
  782. BCL_PARAMETER_CHECK(this->IsValidParameter(rinputCandidate));
  783. BCL_IFCALLFAILED_EXIT(
  784. TTraits::EqualStrings(
  785. this->GetStringPair(),
  786. rinputCandidate,
  787. rfMatches));
  788. BCL_MAYFAIL_EPILOG_PUBLIC
  789. }
  790. template <typename TSomeInputType>
  791. inline TPublicErrorReturnType public_EqualsI(
  792. const TSomeInputType &rinputCandidate,
  793. const TCaseInsensitivityData &rcid,
  794. bool &rfMatches
  795. ) const
  796. {
  797. BCL_MAYFAIL_PROLOG
  798. this->IntegrityCheck();
  799. BCL_PARAMETER_CHECK(this->IsValidParameter(rinputCandidate));
  800. BCL_IFCALLFAILED_EXIT(
  801. TTraits::EqualStringsI(
  802. this->GetStringPair(),
  803. rinputCandidate,
  804. rcid,
  805. rfMatches));
  806. BCL_MAYFAIL_EPILOG_PUBLIC
  807. }
  808. inline __int8 GetBufferCchAs_int8() const { this->IntegrityCheck(); if (this->GetBufferCch() > _I8_MAX) return _I8_MAX; return static_cast<__int8>(this->GetBufferCch()); }
  809. inline __int8 GetStringCchAs_int8() const { this->IntegrityCheck(); if (this->GetStringCch() > _I8_MAX) return _I8_MAX; return static_cast<__int8>(this->GetStringCch()); }
  810. inline unsigned __int8 GetBufferCchAs_unsigned_int8() const { this->IntegrityCheck(); if (this->GetBufferCch() > _UI8_MAX) return _UI8_MAX; return static_cast<unsigned __int8>(this->GetBufferCch()); }
  811. inline unsigned __int8 GetStringCchAs_unsigned_int8() const { this->IntegrityCheck(); if (this->GetStringCch() > _UI8_MAX) return _UI8_MAX; return static_cast<unsigned __int8>(this->GetStringCch()); }
  812. inline __int16 GetBufferCchAs_int16() const { this->IntegrityCheck(); if (this->GetBufferCch() > _I16_MAX) return _I16_MAX; return static_cast<__int16>(this->GetBufferCch()); }
  813. inline __int16 GetStringCchAs_int16() const { this->IntegrityCheck(); if (this->GetStringCch() > _I16_MAX) return _I16_MAX; return static_cast<__int16>(this->GetStringCch()); }
  814. inline unsigned __int16 GetBufferCchAs_unsigned_int16() const { this->IntegrityCheck(); if (this->GetBufferCch() > _UI16_MAX) return _UI16_MAX; return static_cast<unsigned __int16>(this->GetBufferCch()); }
  815. inline unsigned __int16 GetStringCchAs_unsigned_int16() const { this->IntegrityCheck(); if (this->GetStringCch() > _UI16_MAX) return _UI16_MAX; return static_cast<unsigned __int16>(this->GetStringCch()); }
  816. inline __int32 GetBufferCchAs_int32() const { this->IntegrityCheck(); if (this->GetBufferCch() > _I32_MAX) return _I32_MAX; return static_cast<__int32>(this->GetBufferCch()); }
  817. inline __int32 GetStringCchAs_int32() const { this->IntegrityCheck(); if (this->GetStringCch() > _I32_MAX) return _I32_MAX; return static_cast<__int32>(this->GetStringCch()); }
  818. inline unsigned __int32 GetBufferCchAs_unsigned_int32() const { this->IntegrityCheck(); if (this->GetBufferCch() > _UI32_MAX) return _UI32_MAX; return static_cast<unsigned __int32>(this->GetBufferCch()); }
  819. inline unsigned __int32 GetStringCchAs_unsigned_int32() const { this->IntegrityCheck(); if (this->GetStringCch() > _UI32_MAX) return _UI32_MAX; return static_cast<unsigned __int32>(this->GetStringCch()); }
  820. inline __int64 GetBufferCchAs_int64() const { this->IntegrityCheck(); if (this->GetBufferCch() > _I64_MAX) return _I64_MAX; return static_cast<__int64>(this->GetBufferCch()); }
  821. inline __int64 GetStringCchAs_int64() const { this->IntegrityCheck(); if (this->GetStringCch() > _I64_MAX) return _I64_MAX; return static_cast<__int64>(this->GetStringCch()); }
  822. inline unsigned __int64 GetBufferCchAs_unsigned_int64() const { this->IntegrityCheck(); if (this->GetBufferCch() > _UI64_MAX) return _UI64_MAX; return static_cast<unsigned __int64>(this->GetBufferCch()); }
  823. inline unsigned __int64 GetStringCchAs_unsigned_int64() const { this->IntegrityCheck(); if (this->GetStringCch() > _UI64_MAX) return _UI64_MAX; return static_cast<unsigned __int64>(this->GetStringCch()); }
  824. inline char GetBufferCchAs_char() const { this->IntegrityCheck(); if (this->GetBufferCch() > CHAR_MAX) return CHAR_MAX; return static_cast<char>(this->GetBufferCch()); }
  825. inline char GetStringCchAs_char() const { this->IntegrityCheck(); if (this->GetStringCch() > CHAR_MAX) return CHAR_MAX; return static_cast<char>(this->GetStringCch()); }
  826. inline unsigned char GetBufferCchAs_unsigned_char() const { this->IntegrityCheck(); if (this->GetBufferCch() > UCHAR_MAX) return UCHAR_MAX; return static_cast<unsigned char>(this->GetBufferCch()); }
  827. inline unsigned char GetStringCchAs_unsigned_char() const { this->IntegrityCheck(); if (this->GetStringCch() > UCHAR_MAX) return UCHAR_MAX; return static_cast<unsigned char>(this->GetStringCch()); }
  828. inline unsigned char GetBufferCchAs_signed_char() const { this->IntegrityCheck(); if (this->GetBufferCch() > SCHAR_MAX) return SCHAR_MAX; return static_cast<signed char>(this->GetBufferCch()); }
  829. inline unsigned char GetStringCchAs_signed_char() const { this->IntegrityCheck(); if (this->GetStringCch() > SCHAR_MAX) return SCHAR_MAX; return static_cast<signed char>(this->GetStringCch()); }
  830. inline short GetBufferCchAs_short() const { this->IntegrityCheck(); if (this->GetBufferCch() > SHRT_MAX) return SHRT_MAX; return static_cast<short>(this->GetBufferCch()); }
  831. inline short GetStringCchAs_short() const { this->IntegrityCheck(); if (this->GetStringCch() > SHRT_MAX) return SHRT_MAX; return static_cast<short>(this->GetStringCch()); }
  832. inline unsigned short GetBufferCchAs_unsigned_short() const { this->IntegrityCheck(); if (this->GetBufferCch() > USHRT_MAX) return USHRT_MAX; return static_cast<unsigned short>(this->GetBufferCch()); }
  833. inline unsigned short GetStringCchAs_unsigned_short() const { this->IntegrityCheck(); if (this->GetStringCch() > USHRT_MAX) return USHRT_MAX; return static_cast<unsigned short>(this->GetStringCch()); }
  834. inline int GetBufferCchAs_int() const { this->IntegrityCheck(); if (this->GetBufferCch() > INT_MAX) return INT_MAX; return static_cast<int>(this->GetBufferCch()); }
  835. inline int GetStringCchAs_int() const { this->IntegrityCheck(); if (this->GetStringCch() > INT_MAX) return INT_MAX; return static_cast<int>(this->GetStringCch()); }
  836. inline unsigned int GetBufferCchAs_unsigned_int() const { this->IntegrityCheck(); if (this->GetBufferCch() > UINT_MAX) return UINT_MAX; return static_cast<unsigned int>(this->GetBufferCch()); }
  837. inline unsigned int GetStringCchAs_unsigned_int() const { this->IntegrityCheck(); if (this->GetStringCch() > UINT_MAX) return UINT_MAX; return static_cast<unsigned int>(this->GetStringCch()); }
  838. inline long GetBufferCchAs_long() const { this->IntegrityCheck(); if (this->GetBufferCch() > LONG_MAX) return LONG_MAX; return static_cast<long>(this->GetBufferCch()); }
  839. inline long GetStringCchAs_long() const { this->IntegrityCheck(); if (this->GetStringCch() > LONG_MAX) return LONG_MAX; return static_cast<long>(this->GetStringCch()); }
  840. inline unsigned long GetBufferCchAs_unsigned_long() const { this->IntegrityCheck(); if (this->GetBufferCch() > ULONG_MAX) return ULONG_MAX; return static_cast<unsigned long>(this->GetBufferCch()); }
  841. inline unsigned long GetStringCchAs_unsigned_long() const { this->IntegrityCheck(); if (this->GetStringCch() > ULONG_MAX) return ULONG_MAX; return static_cast<unsigned long>(this->GetStringCch()); }
  842. inline TSizeT GetBufferCb() const { this->IntegrityCheck(); return this->GetBufferCch() * sizeof(TChar); }
  843. inline int GetBufferCbAs_int() const { this->IntegrityCheck(); if ((this->GetBufferCch() * sizeof(TChar)) > INT_MAX) return INT_MAX; return static_cast<int>(this->GetBufferCch() * sizeof(TChar)); }
  844. inline unsigned long GetBufferCbAs_unsigned_long() const { this->IntegrityCheck(); if ((this->GetBufferCch() * sizeof(TChar)) > ULONG_MAX) return ULONG_MAX; return static_cast<unsigned long>(this->GetBufferCch() * sizeof(TChar)); }
  845. inline unsigned long GetStringCbAs_unsigned_long() const { this->IntegrityCheck(); if ((this->GetStringCch() * sizeof(TChar)) > ULONG_MAX) return ULONG_MAX; return static_cast<unsigned long>(this->GetStringCch() * sizeof(TChar)); }
  846. template <typename TSomeInputType>
  847. inline TPublicErrorReturnType public_Span(const TSomeInputType &rinput, TSizeT &rich) const
  848. {
  849. BCL_MAYFAIL_PROLOG
  850. BCL_PARAMETER_CHECK(this->IsValidParameter(rinput));
  851. BCL_IFCALLFAILED_EXIT(TTraits::Span(this->GetStringPair(), rinput, rich));
  852. BCL_MAYFAIL_EPILOG_PUBLIC
  853. }
  854. template <typename TSomeInputType>
  855. inline TPublicErrorReturnType public_SpanI(const TSomeInputType &rinput, const TCaseInsensitivityData &rcid, TSizeT &rich) const
  856. {
  857. BCL_MAYFAIL_PROLOG
  858. BCL_PARAMETER_CHECK(this->IsValidParameter(rinput));
  859. BCL_IFCALLFAILED_EXIT(TTraits::SpanI(this->GetStringPair(), rinput, rcid, rich));
  860. BCL_MAYFAIL_EPILOG_PUBLIC
  861. }
  862. template <typename TSomeInputType>
  863. inline TPublicErrorReturnType public_ReverseSpan(const TSomeInputType &rinput, TSizeT &rich) const
  864. {
  865. BCL_MAYFAIL_PROLOG
  866. BCL_PARAMETER_CHECK(this->IsValidParameter(rinput));
  867. BCL_IFCALLFAILED_EXIT(TTraits::ReverseSpan(this->GetStringPair(), rinput, rich));
  868. BCL_MAYFAIL_EPILOG_PUBLIC
  869. }
  870. template <typename TSomeInputType>
  871. inline TPublicErrorReturnType public_ReverseSpanI(const TSomeInputType &rinput, const TCaseInsensitivityData &rcid, TSizeT &rich) const
  872. {
  873. BCL_MAYFAIL_PROLOG
  874. BCL_PARAMETER_CHECK(this->IsValidParameter(rinput));
  875. BCL_IFCALLFAILED_EXIT(TTraits::ReverseSpanI(this->GetStringPair(), rinput, rcid, rich));
  876. BCL_MAYFAIL_EPILOG_PUBLIC
  877. }
  878. template <typename TSomeInputType>
  879. inline TPublicErrorReturnType public_ComplementSpan(const TSomeInputType &rinput, TSizeT &rich) const
  880. {
  881. BCL_MAYFAIL_PROLOG
  882. BCL_PARAMETER_CHECK(this->IsValidParameter(rinput));
  883. BCL_IFCALLFAILED_EXIT(TTraits::ComplementSpan(this->GetStringPair(), rinput, rich));
  884. BCL_MAYFAIL_EPILOG_PUBLIC
  885. }
  886. template <typename TSomeInputType>
  887. inline TPublicErrorReturnType public_ComplementSpanI(const TSomeInputType &rinput, const TCaseInsensitivityData &rcid, TSizeT &rich) const
  888. {
  889. BCL_MAYFAIL_PROLOG
  890. BCL_PARAMETER_CHECK(this->IsValidParameter(rinput));
  891. BCL_IFCALLFAILED_EXIT(TTraits::ComplementSpanI(this->GetStringPair(), rinput, rcid, rich));
  892. BCL_MAYFAIL_EPILOG_PUBLIC
  893. }
  894. template <typename TSomeInputType>
  895. inline TPublicErrorReturnType public_ReverseComplementSpan(const TSomeInputType &rinput, TSizeT &rich) const
  896. {
  897. BCL_MAYFAIL_PROLOG
  898. BCL_PARAMETER_CHECK(this->IsValidParameter(rinput));
  899. BCL_IFCALLFAILED_EXIT(TTraits::ReverseComplementSpan(this->GetStringPair(), rinput, rich));
  900. BCL_MAYFAIL_EPILOG_PUBLIC
  901. }
  902. template <typename TSomeInputType>
  903. inline TPublicErrorReturnType public_ReverseComplementSpanI(const TSomeInputType &rinput, const TCaseInsensitivityData &rcid, TSizeT &rich) const
  904. {
  905. BCL_MAYFAIL_PROLOG
  906. BCL_PARAMETER_CHECK(this->IsValidParameter(rinput));
  907. BCL_IFCALLFAILED_EXIT(TTraits::ReverseComplementSpanI(this->GetStringPair(), rinput, rcid, rich));
  908. BCL_MAYFAIL_EPILOG_PUBLIC
  909. }
  910. template <typename TSomeInputType>
  911. inline TPublicErrorReturnType public_Contains(const TSomeInputType &rinput, bool &rfContainsCharacter) const
  912. {
  913. BCL_MAYFAIL_PROLOG
  914. BCL_PARAMETER_CHECK(this->IsValidParameter(rinput));
  915. BCL_IFCALLFAILED_EXIT(TTraits::Contains(this->GetStringPair(), rinput, rfContainsCharacter));
  916. BCL_MAYFAIL_EPILOG_PUBLIC
  917. }
  918. template <typename TSomeInputType>
  919. inline TPublicErrorReturnType public_ContainsI(const TSomeInputType &rinput, const TCaseInsensitivityData &rcid, bool &rfContainsCharacter) const
  920. {
  921. BCL_MAYFAIL_PROLOG
  922. BCL_PARAMETER_CHECK(this->IsValidParameter(rinput));
  923. BCL_IFCALLFAILED_EXIT(TTraits::ContainsI(this->GetStringPair(), rinput, rcid, rfContainsCharacter));
  924. BCL_MAYFAIL_EPILOG_PUBLIC
  925. }
  926. template <typename TSomeInputType>
  927. inline TPublicErrorReturnType public_FindFirst(const TSomeInputType &rinput, TSizeT &rich) const
  928. {
  929. BCL_MAYFAIL_PROLOG
  930. BCL_PARAMETER_CHECK(this->IsValidParameter(rinput));
  931. BCL_IFCALLFAILED_EXIT(TTraits::FindFirst(this->GetStringPair(), rinput, rich));
  932. BCL_MAYFAIL_EPILOG_PUBLIC
  933. }
  934. template <typename TSomeInputType>
  935. inline TPublicErrorReturnType public_Count(const TSomeInputType &rinput, TSizeT &rich) const
  936. {
  937. BCL_MAYFAIL_PROLOG
  938. BCL_PARAMETER_CHECK(this->IsValidParameter(rinput));
  939. BCL_IFCALLFAILED_EXIT(TTraits::Count(this->GetStringPair(), rinput, rich));
  940. BCL_MAYFAIL_EPILOG_PUBLIC
  941. }
  942. template <typename TSomeInputType>
  943. inline TPublicErrorReturnType public_FindLast(const TSomeInputType &rinput, TSizeT &rich) const
  944. {
  945. BCL_MAYFAIL_PROLOG
  946. BCL_PARAMETER_CHECK(this->IsValidParameter(rinput));
  947. BCL_IFCALLFAILED_EXIT(TTraits::FindLast(this->GetStringPair(), rinput, rich));
  948. BCL_MAYFAIL_EPILOG_PUBLIC
  949. }
  950. template <typename TSomeInputType>
  951. inline TPublicErrorReturnType public_FindFirstI(const TSomeInputType &rinput, const TCaseInsensitivityData &rcid, TSizeT &rich) const
  952. {
  953. BCL_MAYFAIL_PROLOG
  954. BCL_PARAMETER_CHECK(this->IsValidParameter(rinput));
  955. BCL_IFCALLFAILED_EXIT(TTraits::FindFirstI(this->GetStringPair(), rinput, rcid, rich));
  956. BCL_MAYFAIL_EPILOG_PUBLIC
  957. }
  958. template <typename TSomeInputType>
  959. inline TPublicErrorReturnType public_FindLastI(const TSomeInputType &rinput, const TCaseInsensitivityData &rcid, TSizeT &rich) const
  960. {
  961. BCL_MAYFAIL_PROLOG
  962. BCL_PARAMETER_CHECK(this->IsValidParameter(rinput));
  963. BCL_IFCALLFAILED_EXIT(TTraits::FindLastI(this->GetStringPair(), rinput, rcid, rich));
  964. BCL_MAYFAIL_EPILOG_PUBLIC
  965. }
  966. inline bool IsEmpty() const
  967. {
  968. return this->GetBufferPtr()[0] == 0;
  969. }
  970. template <typename TSomeCharType>
  971. inline TPublicErrorReturnType public_EnsureTrailingChar(TSomeCharType ch)
  972. {
  973. BCL_MAYFAIL_PROLOG
  974. bool fDoAppend = false;
  975. this->IntegrityCheck();
  976. // it would seem innocuous to allow assigns that don't resize the buffer to not
  977. // invalidate accessors, but that makes finding such bugs subject to even more
  978. // strenuous coverage problems than this simple error. The simple rule is that
  979. // you should not have an accessor attached to a string buffer when you use
  980. // any of member functions that may mutate the value.
  981. BCL_IFCALLFAILED_EXIT(this->NoAccessorsCheck());
  982. if (this->GetStringCch() == 0)
  983. fDoAppend = true;
  984. else
  985. {
  986. bool fMatches = false;
  987. BCL_IFCALLFAILED_EXIT(TTraits::EqualsLastCharacter(this->GetBufferPtr(), this->GetStringCch(), ch, fMatches));
  988. if (!fMatches)
  989. fDoAppend = true;
  990. }
  991. if (fDoAppend)
  992. {
  993. TSizeT cch;
  994. BCL_IFCALLFAILED_EXIT(TTraits::DetermineRequiredCharacters(ch, cch));
  995. if (cch > 1)
  996. {
  997. TSizeT cchTotal;
  998. BCL_IFCALLFAILED_EXIT(TTraits::AddWithOverflowCheck(this->GetStringCch(), cch, cchTotal));
  999. BCL_IFCALLFAILED_EXIT(this->EnsureBufferLargeEnoughPreserve(cchTotal));
  1000. // subtraction should only underflow if stringcch > buffercch which is bad anyways.
  1001. BCL_INTERNAL_ERROR_CHECK(this->GetStringCch() <= this->GetBufferCch());
  1002. BCL_IFCALLFAILED_EXIT(TTraits::CopyIntoBuffer(this->GetBufferPtr()[this->GetStringCch()], this->GetBufferCch() - this->GetStringCch(), ch));
  1003. this->SetStringCch(cchTotal);
  1004. }
  1005. }
  1006. BCL_MAYFAIL_EPILOG_PUBLIC
  1007. }
  1008. template <typename TSomeCharType>
  1009. inline TPublicErrorReturnType public_EnsureTrailingCharCaseInsensitive(TSomeCharType ch, const TCaseInsensitivityData &rcid)
  1010. {
  1011. BCL_MAYFAIL_PROLOG
  1012. bool fDoAppend = false;
  1013. this->IntegrityCheck();
  1014. // it would seem innocuous to allow assigns that don't resize the buffer to not
  1015. // invalidate accessors, but that makes finding such bugs subject to even more
  1016. // strenuous coverage problems than this simple error. The simple rule is that
  1017. // you should not have an accessor attached to a string buffer when you use
  1018. // any of member functions that may mutate the value.
  1019. BCL_IFCALLFAILED_EXIT(this->NoAccessorsCheck());
  1020. if (this->GetStringCch() == 0)
  1021. fDoAppend = true;
  1022. else
  1023. {
  1024. bool fMatches = false;
  1025. BCL_IFCALLFAILED_EXIT(TTraits::EqualsLastCharacterCaseInsensitive(this->GetBufferPtr(), this->GetStringCch(), ch, rcid, fMatches));
  1026. if (!fMatches)
  1027. fDoAppend = true;
  1028. }
  1029. if (fDoAppend)
  1030. {
  1031. TSizeT cch;
  1032. BCL_IFCALLFAILED_EXIT(TTraits::DetermineRequiredCharacters(ch, cch));
  1033. if (cch > 1)
  1034. {
  1035. TSizeT cchSum;
  1036. BCL_IFCALLFAILED_EXIT(TTraits::AddWithOverflowCheck(this->GetStringCch(), cch, cchSum));
  1037. BCL_IFCALLFAILED_EXIT(this->EnsureBufferLargeEnoughPreserve(cchSum));
  1038. BCL_INTERNAL_ERROR_CHECK(this->GetStringCch() <= this->GetBufferCch());
  1039. BCL_IFCALLFAILED_EXIT(TTraits::CopyIntoBuffer(this->GetBufferPtr()[this->GetStringCch()], this->GetBufferCch() - this->GetStringCch(), ch));
  1040. this->SetStringCch(cchSum);
  1041. }
  1042. }
  1043. BCL_MAYFAIL_EPILOG_PUBLIC
  1044. }
  1045. inline TCallDisposition Left(TSizeT newLength)
  1046. {
  1047. BCL_MAYFAIL_PROLOG
  1048. this->IntegrityCheck();
  1049. BCL_PARAMETER_CHECK(newLength <= this->GetStringCch());
  1050. BCL_IFCALLFAILED_EXIT(this->NoAccessorsCheck());
  1051. this->SetStringCch(newLength);
  1052. BCL_MAYFAIL_EPILOG_INTERNAL
  1053. }
  1054. inline TPublicErrorReturnType public_Left(TSizeT newLength)
  1055. {
  1056. BCL_MAYFAIL_PROLOG
  1057. BCL_IFCALLFAILED_EXIT(this->Left(newLength));
  1058. BCL_MAYFAIL_EPILOG_PUBLIC
  1059. }
  1060. inline TCallDisposition Right(TSizeT cchRightCount)
  1061. {
  1062. BCL_MAYFAIL_PROLOG
  1063. this->IntegrityCheck();
  1064. BCL_IFCALLFAILED_EXIT(this->NoAccessorsCheck());
  1065. BCL_PARAMETER_CHECK(cchRightCount <= this->GetStringCch());
  1066. if (cchRightCount < this->GetStringCch())
  1067. {
  1068. BCL::MoveBytes(
  1069. this->GetMutableBufferPtr(),
  1070. &this->GetBufferPtr()[this->GetStringCch() - cchRightCount],
  1071. cchRightCount * sizeof(TTraits::TChar));
  1072. this->SetStringCch(cchRightCount);
  1073. }
  1074. BCL_MAYFAIL_EPILOG_INTERNAL
  1075. }
  1076. TPublicErrorReturnType public_Right(TSizeT cchRightCount)
  1077. {
  1078. BCL_MAYFAIL_PROLOG
  1079. this->IntegrityCheck();
  1080. BCL_IFCALLFAILED_EXIT(this->NoAccessorsCheck());
  1081. BCL_PARAMETER_CHECK(cchRightCount <= this->GetStringCch());
  1082. if (cchRightCount < this->GetStringCch())
  1083. {
  1084. BCL::MoveBytes(
  1085. this->GetMutableBufferPtr(),
  1086. &this->GetBufferPtr()[this->GetStringCch() - cchRightCount],
  1087. (cchRightCount + 1)*sizeof(TTraits::TChar));
  1088. this->SetStringCch(cchRightCount);
  1089. }
  1090. BCL_MAYFAIL_EPILOG_PUBLIC
  1091. }
  1092. TPublicErrorReturnType public_Mid(TSizeT ichStart, TSizeT cch)
  1093. {
  1094. BCL_MAYFAIL_PROLOG
  1095. TSizeT cchSum;
  1096. BCL_IFCALLFAILED_EXIT(TTraits::AddWithOverflowCheck(ichStart, cch, cchSum));
  1097. // It's not unreasonable to end up with a zero length string, so this is <=, not <
  1098. BCL_PARAMETER_CHECK(cchSum <= this->GetStringCch());
  1099. BCL_IFCALLFAILED_EXIT(this->Right(this->GetStringCch() - ichStart));
  1100. BCL_IFCALLFAILED_EXIT(this->Left(cch));
  1101. BCL_MAYFAIL_EPILOG_PUBLIC
  1102. }
  1103. };
  1104. template <typename TTraits> class CPureStringAccessor
  1105. {
  1106. public:
  1107. typedef CPureString<TTraits> TBuffer;
  1108. typedef typename TTraits::TChar TChar;
  1109. typedef typename TTraits::TCallDisposition TCallDisposition;
  1110. typedef typename TTraits::TMutableString TMutableString;
  1111. typedef typename TTraits::TConstantString TConstantString;
  1112. typedef typename TTraits::TSizeT TSizeT;
  1113. typedef typename TTraits::TPublicErrorReturnType TPublicErrorReturnType;
  1114. typedef BCL::CMutablePointerAndCountPair<TChar, TSizeT> TMutablePair;
  1115. typedef BCL::CConstantPointerAndCountPair<TChar, TSizeT> TConstantPair;
  1116. CPureStringAccessor(TBuffer* pBuffer) : m_pStringBuffer(NULL)
  1117. {
  1118. this->Attach(pBuffer);
  1119. }
  1120. CPureStringAccessor() : m_pStringBuffer(NULL) { }
  1121. ~CPureStringAccessor()
  1122. {
  1123. if (m_pStringBuffer != NULL)
  1124. {
  1125. m_pStringBuffer->SetStringCch(TTraits::NullTerminatedStringLengthWithLimit(this->GetBufferPtr(), this->GetBufferCch()));
  1126. m_pStringBuffer->DetachAccessor(this);
  1127. m_pStringBuffer = NULL;
  1128. }
  1129. }
  1130. bool IsAttached() const
  1131. {
  1132. return (m_pStringBuffer != NULL);
  1133. }
  1134. inline TPublicErrorReturnType Attach(TBuffer *pBuffer)
  1135. {
  1136. BCL_MAYFAIL_PROLOG
  1137. BCL_INTERNAL_ERROR_CHECK(!this->IsAttached());
  1138. BCL_IFCALLFAILED_EXIT(pBuffer->AttachAccessor(this));
  1139. m_pStringBuffer = pBuffer;
  1140. BCL_MAYFAIL_EPILOG_PUBLIC
  1141. }
  1142. inline void Detach()
  1143. {
  1144. BCL_ASSERT (this->IsAttached());
  1145. if (this->IsAttached())
  1146. {
  1147. m_pStringBuffer->SetStringCch(TTraits::NullTerminatedStringLengthWithLimit(this->GetBufferPtr(), this->GetBufferCch()));
  1148. m_pStringBuffer->DetachAccessor(this);
  1149. m_pStringBuffer = NULL;
  1150. }
  1151. }
  1152. inline operator TMutableString() const { BCL_ASSERT(this->IsAttached()); return this->GetBufferPtr(); }
  1153. inline typename TTraits::TMutableString GetBufferPtr() const { BCL_ASSERT(IsAttached()); return m_pStringBuffer->GetBufferPtr(); }
  1154. inline TSizeT GetBufferCch() const { BCL_ASSERT(this->IsAttached()); return m_pStringBuffer->GetBufferCch(); }
  1155. inline short GetBufferCchAs_short() const { BCL_ASSERT(this->IsAttached()); if (this->GetBufferCch() > SHORT_MAX) return SHORT_MAX; return static_cast<short>(this->GetBufferCch()) }
  1156. inline unsigned short GetBufferCchAs_unsigned_short() const { BCL_ASSERT(this->IsAttached()); if (this->GetBufferCch() > USHORT_MAX) return USHORT_MAX; return static_cast<unsigned short>(this->GetBufferCch()) }
  1157. inline int GetBufferCchAs_int() const { BCL_ASSERT(this->IsAttached()); if (this->GetBufferCch() > INT_MAX) return INT_MAX; return static_cast<int>(this->GetBufferCch()); }
  1158. inline unsigned int GetBufferCchAs_unsigned_int() const { BCL_ASSERT(this->IsAttached()); if (this->GetBufferCch() > UINT_MAX) return UINT_MAX; return static_cast<unsigned int>(this->GetBufferCch()); }
  1159. inline long GetBufferCchAs_long() const { BCL_ASSERT(this->IsAttached()); if (this->GetBufferCch() > LONG_MAX) return LONG_MAX; return static_cast<long>(this->GetBufferCch()); }
  1160. inline unsigned long GetBufferCchAs_unsigned_long() const { BCL_ASSERT(this->IsAttached()); if (this->GetBufferCch() > ULONG_MAX) return ULONG_MAX; return static_cast<unsigned long>(this->GetBufferCch()); }
  1161. inline TSizeT GetStringCch() const { BCL_ASSERT(this->IsAttached()); return TTraits::NullTerminatedStringLengthWithLimit(this->GetBufferPtr(), this->GetBufferCch()); }
  1162. inline short GetStringCchAs_short() const { BCL_ASSERT(this->IsAttached()); if (this->GetStringCch() > SHORT_MAX) return SHORT_MAX; return static_cast<short>(this->GetStringCch()) }
  1163. inline unsigned short GetStringCchAs_unsigned_short() const { BCL_ASSERT(this->IsAttached()); if (this->GetStringCch() > USHORT_MAX) return USHORT_MAX; return static_cast<unsigned short>(this->GetStringCch()) }
  1164. inline int GetStringCchAs_int() const { BCL_ASSERT(this->IsAttached()); if (this->GetStringCch() > INT_MAX) return INT_MAX; return static_cast<int>(this->GetStringCch()); }
  1165. inline unsigned int GetStringCchAs_unsigned_int() const { BCL_ASSERT(this->IsAttached()); if (this->GetStringCch() > UINT_MAX) return UINT_MAX; return static_cast<unsigned int>(this->GetStringCch()); }
  1166. inline long GetStringCchAs_long() const { BCL_ASSERT(this->IsAttached()); if (this->GetStringCch() > LONG_MAX) return LONG_MAX; return static_cast<long>(this->GetStringCch()); }
  1167. inline unsigned long GetStringCchAs_unsigned_long() const { BCL_ASSERT(this->IsAttached()); if (this->GetStringCch() > ULONG_MAX) return ULONG_MAX; return static_cast<unsigned long>(this->GetStringCch()); }
  1168. inline TSizeT GetBufferCb() const { BCL_ASSERT(this->IsAttached()); return m_pStringBuffer->GetBufferCb(); }
  1169. inline short GetBufferCbAs_short() const { BCL_ASSERT(this->IsAttached()); if (this->GetBufferCb() > SHORT_MAX) return SHORT_MAX; return static_cast<short>(this->GetBufferCb()) }
  1170. inline unsigned short GetBufferCbAs_unsigned_short() const { BCL_ASSERT(this->IsAttached()); if (this->GetBufferCb() > USHORT_MAX) return USHORT_MAX; return static_cast<unsigned short>(this->GetBufferCb()) }
  1171. inline int GetBufferCbAs_int() const { BCL_ASSERT(this->IsAttached()); if (this->GetBufferCb() > INT_MAX) return INT_MAX; return static_cast<int>(this->GetBufferCb()); }
  1172. inline unsigned int GetBufferCbAs_unsigned_int() const { BCL_ASSERT(this->IsAttached()); if (this->GetBufferCb() > UINT_MAX) return UINT_MAX; return static_cast<unsigned int>(this->GetBufferCb()); }
  1173. inline long GetBufferCbAs_long() const { BCL_ASSERT(this->IsAttached()); if (this->GetBufferCb() > LONG_MAX) return LONG_MAX; return static_cast<long>(this->GetBufferCb()); }
  1174. inline unsigned long GetBufferCbAs_unsigned_long() const { BCL_ASSERT(this->IsAttached()); if (this->GetBufferCb() > ULONG_MAX) return ULONG_MAX; return static_cast<unsigned long>(this->GetBufferCb()); }
  1175. inline TSizeT GetStringCb() const { BCL_ASSERT(this->IsAttached()); return m_cch * sizeof(TChar); }
  1176. inline short GetStringCbAs_short() const { BCL_ASSERT(this->IsAttached()); if (this->GetStringCb() > SHORT_MAX) return SHORT_MAX; return static_cast<short>(this->GetStringCb()) }
  1177. inline unsigned short GetStringCbAs_unsigned_short() const { BCL_ASSERT(this->IsAttached()); if (this->GetStringCb() > USHORT_MAX) return USHORT_MAX; return static_cast<unsigned short>(this->GetStringCb()) }
  1178. inline int GetStringCbAs_int() const { BCL_ASSERT(this->IsAttached()); if (this->GetStringCb() > INT_MAX) return INT_MAX; return static_cast<int>(this->GetStringCb()); }
  1179. inline unsigned int GetStringCbAs_unsigned_int() const { BCL_ASSERT(this->IsAttached()); if (this->GetStringCb() > UINT_MAX) return UINT_MAX; return static_cast<unsigned int>(this->GetStringCb()); }
  1180. inline long GetStringCbAs_long() const { BCL_ASSERT(this->IsAttached()); if (this->GetStringCb() > LONG_MAX) return LONG_MAX; return static_cast<long>(this->GetStringCb()); }
  1181. inline unsigned long GetStringCbAs_unsigned_long() const { BCL_ASSERT(this->IsAttached()); if (this->GetStringCb() > ULONG_MAX) return ULONG_MAX; return static_cast<unsigned long>(this->GetStringCb()); }
  1182. protected:
  1183. TBuffer *m_pStringBuffer;
  1184. TMutablePair m_pairBuffer;
  1185. private:
  1186. //
  1187. // These two are to induce build breaks on people doing sb1 = sb2
  1188. //
  1189. void operator=(const CPureStringAccessor &rOtherString);
  1190. CPureStringAccessor(const CPureStringAccessor &r);
  1191. };
  1192. }; // namespace BCL
  1193. #endif // !defined(_WINDOWS_BCL_PURESTRING_H_INCLUDED_)