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.

678 lines
16 KiB

  1. /*++
  2. Copyright (c) Microsoft Corporation
  3. Module Name:
  4. fusionstring.h
  5. Abstract:
  6. Stuff to futz with everybody's favorite type, generally templatized
  7. to work on char, wchar_t, or anything else; occasionally
  8. templatized to work on arbitrary STL style [begin, end)
  9. sequences.
  10. Also stuff particularly for NT's UNICODE_STRING.
  11. To be merged with cfusionbuffer.h.
  12. Author:
  13. Jay Krell (a-JayK, JayKrell) May 2000
  14. Revision History:
  15. --*/
  16. #pragma once
  17. #include <stdio.h>
  18. #include "fusionntdll.h"
  19. //
  20. // This is the main bottleneck for FusionpCompareStrings.
  21. // All overloads should call this directly.
  22. //
  23. int
  24. FusionpCompareStrings(
  25. PCWSTR sz1,
  26. SIZE_T cch1,
  27. PCWSTR sz2,
  28. SIZE_T cch2,
  29. bool fCaseInsensitive
  30. );
  31. #ifdef __cplusplus
  32. class CUnicodeCharTraits;
  33. template <typename T> class CGenericBaseStringBuffer;
  34. //
  35. // This is the main bottleneck for FusionpEqualStrings.
  36. // All overloads call this directly.
  37. //
  38. inline bool
  39. FusionpEqualStrings(
  40. PCWSTR sz1,
  41. SIZE_T cch1,
  42. PCWSTR sz2,
  43. SIZE_T cch2,
  44. bool fCaseInsensitive
  45. )
  46. {
  47. /*
  48. NTRAID#NTBUG9-591667-2002/04/01-JayKrell
  49. string locale case mapping issues
  50. string can be equal even if they have different lengths,
  51. but not at the rtl/fs/ob level, so maybe this is ok
  52. It's good to have this bottleneck regardless.
  53. */
  54. return ((cch1 == cch2) && (FusionpCompareStrings(sz1, cch1, sz2, cch2, fCaseInsensitive) == 0));
  55. }
  56. inline bool
  57. FusionpEqualStringsI(
  58. PCWSTR sz1,
  59. SIZE_T cch1,
  60. PCWSTR sz2,
  61. SIZE_T cch2
  62. )
  63. {
  64. return ::FusionpEqualStrings(sz1, cch1, sz2, cch2, true);
  65. }
  66. inline bool
  67. FusionpEqualStrings(
  68. PCUNICODE_STRING s1,
  69. PCUNICODE_STRING s2,
  70. bool fCaseInsensitive
  71. )
  72. {
  73. return ::FusionpEqualStrings(
  74. s1->Buffer, RTL_STRING_GET_LENGTH_CHARS(s1),
  75. s2->Buffer, RTL_STRING_GET_LENGTH_CHARS(s2),
  76. fCaseInsensitive
  77. );
  78. }
  79. inline bool
  80. FusionpEqualStringsI(
  81. PCUNICODE_STRING s1,
  82. PCUNICODE_STRING s2
  83. )
  84. {
  85. return ::FusionpEqualStrings(
  86. s1->Buffer, RTL_STRING_GET_LENGTH_CHARS(s1),
  87. s2->Buffer, RTL_STRING_GET_LENGTH_CHARS(s2),
  88. true);
  89. }
  90. inline bool
  91. FusionpEqualStringsI(
  92. PCUNICODE_STRING s1,
  93. PCWSTR sz2,
  94. SIZE_T cch2
  95. )
  96. {
  97. return ::FusionpEqualStrings(
  98. s1->Buffer, RTL_STRING_GET_LENGTH_CHARS(s1),
  99. sz2, cch2,
  100. true
  101. );
  102. }
  103. inline bool
  104. FusionpEqualStringsI(
  105. PCWSTR sz1,
  106. SIZE_T cch1,
  107. PCUNICODE_STRING s2
  108. )
  109. {
  110. return ::FusionpEqualStrings(
  111. sz1, cch1,
  112. s2->Buffer, RTL_STRING_GET_LENGTH_CHARS(s2),
  113. true
  114. );
  115. }
  116. inline
  117. int
  118. FusionpCompareStringsI(
  119. PCWSTR sz1,
  120. SIZE_T cch1,
  121. PCUNICODE_STRING s2
  122. )
  123. {
  124. return FusionpCompareStrings(
  125. sz1, cch1,
  126. s2->Buffer, RTL_STRING_GET_LENGTH_CHARS(s2),
  127. true);
  128. }
  129. inline
  130. int
  131. FusionpCompareStringsI(
  132. PCUNICODE_STRING s1,
  133. PCWSTR sz2,
  134. SIZE_T cch2
  135. )
  136. {
  137. return FusionpCompareStrings(
  138. s1->Buffer, RTL_STRING_GET_LENGTH_CHARS(s1),
  139. sz2, cch2,
  140. true);
  141. }
  142. inline
  143. int
  144. FusionpCompareStrings(
  145. PCWSTR sz1,
  146. SIZE_T cch1,
  147. PCUNICODE_STRING s2,
  148. bool fCaseInsensitive
  149. )
  150. {
  151. return FusionpCompareStrings(
  152. sz1, cch1,
  153. s2->Buffer, RTL_STRING_GET_LENGTH_CHARS(s2),
  154. fCaseInsensitive);
  155. }
  156. inline
  157. int
  158. FusionpCompareStrings(
  159. PCUNICODE_STRING s1,
  160. PCWSTR sz2,
  161. SIZE_T cch2,
  162. bool fCaseInsensitive
  163. )
  164. {
  165. return FusionpCompareStrings(
  166. s1->Buffer, RTL_STRING_GET_LENGTH_CHARS(s1),
  167. sz2, cch2,
  168. fCaseInsensitive);
  169. }
  170. bool
  171. FusionpEqualStringsI(
  172. const CGenericBaseStringBuffer<CUnicodeCharTraits> &rbuff1,
  173. PCWSTR psz2,
  174. SIZE_T cch2
  175. );
  176. bool
  177. FusionpEqualStringsI(
  178. PCWSTR psz2,
  179. SIZE_T cch2,
  180. const CGenericBaseStringBuffer<CUnicodeCharTraits> &rbuff1
  181. );
  182. bool
  183. FusionpEqualStringsI(
  184. const CGenericBaseStringBuffer<CUnicodeCharTraits> &rbuff1,
  185. const CGenericBaseStringBuffer<CUnicodeCharTraits> &rbuff2
  186. );
  187. bool
  188. FusionpEqualStrings(
  189. PCWSTR psz1,
  190. SIZE_T cch1,
  191. const CGenericBaseStringBuffer<CUnicodeCharTraits> &rbuff2,
  192. bool fCaseInsensitive
  193. );
  194. bool
  195. FusionpEqualStrings(
  196. const CGenericBaseStringBuffer<CUnicodeCharTraits> &rbuff1,
  197. PCWSTR psz2,
  198. SIZE_T cch2,
  199. bool fCaseInsensitive
  200. );
  201. inline
  202. bool
  203. FusionpEqualStrings(
  204. PCUNICODE_STRING s1,
  205. const CGenericBaseStringBuffer<CUnicodeCharTraits> &rbuff2,
  206. bool fCaseInsensitive
  207. )
  208. {
  209. return ::FusionpEqualStrings(s1->Buffer, RTL_STRING_GET_LENGTH_CHARS(s1), rbuff2, fCaseInsensitive);
  210. }
  211. inline
  212. bool
  213. FusionpEqualStrings(
  214. const CGenericBaseStringBuffer<CUnicodeCharTraits> &rbuff1,
  215. PCUNICODE_STRING s2,
  216. bool fCaseInsensitive
  217. )
  218. {
  219. return ::FusionpEqualStrings(rbuff1, s2->Buffer, RTL_STRING_GET_LENGTH_CHARS(s2), fCaseInsensitive);
  220. }
  221. inline
  222. bool
  223. FusionpEqualStringsI(
  224. const CGenericBaseStringBuffer<CUnicodeCharTraits> &rbuff1,
  225. PCUNICODE_STRING s2
  226. )
  227. {
  228. return ::FusionpEqualStrings(rbuff1, s2->Buffer, RTL_STRING_GET_LENGTH_CHARS(s2), true);
  229. }
  230. inline
  231. bool
  232. FusionpEqualStringsI(
  233. PCUNICODE_STRING s1,
  234. const CGenericBaseStringBuffer<CUnicodeCharTraits> &rbuff2
  235. )
  236. {
  237. return ::FusionpEqualStrings(s1->Buffer, RTL_STRING_GET_LENGTH_CHARS(s1), rbuff2, true);
  238. }
  239. int
  240. FusionpCompareStrings(
  241. const CGenericBaseStringBuffer<CUnicodeCharTraits> &rbuff1,
  242. PCWSTR psz2,
  243. SIZE_T cch2,
  244. bool fCaseInsensitive
  245. );
  246. int
  247. FusionpCompareStrings(
  248. PCWSTR psz1,
  249. SIZE_T cch1,
  250. const CGenericBaseStringBuffer<CUnicodeCharTraits> &rbuff2,
  251. bool fCaseInsensitive
  252. );
  253. int
  254. FusionpCompareStrings(
  255. const CGenericBaseStringBuffer<CUnicodeCharTraits> &rbuff1,
  256. const CGenericBaseStringBuffer<CUnicodeCharTraits> &rbuff2,
  257. bool fCaseInsensitive
  258. );
  259. int
  260. FusionpCompareStrings(
  261. PCSTR sz1,
  262. SIZE_T cch1,
  263. PCSTR sz2,
  264. SIZE_T cch2,
  265. bool fCaseInsensitive
  266. );
  267. #if !defined(FUSION_CANONICAL_CASE_IS_UPPER)
  268. #define FUSION_CANONICAL_CASE_IS_UPPER 1
  269. #endif // !defined(FUSION_CANONICAL_CASE_IS_UPPER)
  270. #if FUSION_CANONICAL_CASE_IS_UPPER
  271. inline WCHAR FusionpCanonicalizeUnicodeChar(WCHAR wch) { return ::FusionpRtlUpcaseUnicodeChar(wch); }
  272. #else
  273. inline WCHAR FusionpCanonicalizeUnicodeChar(WCHAR wch) { return ::FusionpRtlDowncaseUnicodeChar(wch); }
  274. #endif
  275. inline int
  276. FusionpStrCmpI(
  277. PCWSTR psz1,
  278. PCWSTR psz2
  279. )
  280. {
  281. return ::FusionpCompareStrings(
  282. psz1,
  283. (psz1 != NULL) ? ::wcslen(psz1) : 0,
  284. psz2,
  285. (psz2 != NULL) ? ::wcslen(psz2) : 0,
  286. true);
  287. }
  288. inline bool
  289. FusionpEqualStringsI(
  290. PCWSTR psz1,
  291. PCWSTR psz2
  292. )
  293. {
  294. return ::FusionpEqualStrings(
  295. psz1,
  296. (psz1 != NULL) ? ::wcslen(psz1) : 0,
  297. psz2,
  298. (psz2 != NULL) ? ::wcslen(psz2) : 0,
  299. true);
  300. }
  301. /*-----------------------------------------------------------------------------
  302. StringLength is a generic name for getting the length, in count of
  303. characters, of various kinds of strings
  304. -----------------------------------------------------------------------------*/
  305. inline SIZE_T StringLength(LPCSTR psz)
  306. {
  307. return ::strlen(psz);
  308. }
  309. inline SIZE_T StringLength(LPCWSTR psz)
  310. {
  311. return ::wcslen(psz);
  312. }
  313. #if defined(NT_INCLUDED) // { {
  314. inline SIZE_T StringLength(const UNICODE_STRING* s)
  315. {
  316. return RTL_STRING_GET_LENGTH_CHARS(s);
  317. }
  318. inline SIZE_T StringLength(const ANSI_STRING* s)
  319. {
  320. return RTL_STRING_GET_LENGTH_CHARS(s);
  321. }
  322. extern const UNICODE_STRING g_strEmptyUnicodeString;
  323. template <typename NT_STRING, typename TChar>
  324. class CGenericNtString : public NT_STRING
  325. {
  326. public:
  327. ~CGenericNtString() { }
  328. CGenericNtString(const TChar * buffer, SIZE_T length)
  329. {
  330. this->Buffer = const_cast<TChar*>(buffer); // Careful!
  331. this->Length = static_cast<USHORT>(length * sizeof(*Buffer));
  332. this->MaximumLength = this->Length;
  333. }
  334. CGenericNtString(const TChar* buffer)
  335. {
  336. this->Buffer = const_cast<TChar*>(buffer);
  337. this->Length = static_cast<USHORT>(::StringLength(buffer) * sizeof(*Buffer));
  338. this->MaximumLength = this->Length;
  339. }
  340. //protected:
  341. CGenericNtString()
  342. {
  343. const static TChar zero;
  344. this->Buffer = const_cast<TChar*>(&zero);
  345. this->Length = sizeof(*Buffer);
  346. this->MaximumLength = this->Length;
  347. }
  348. private: // deliberately not implemented
  349. CGenericNtString(const CGenericNtString&);
  350. void operator=(const CGenericNtString&);
  351. };
  352. typedef CGenericNtString<ANSI_STRING, CHAR> CAnsiString;
  353. class CUnicodeString : public CGenericNtString<UNICODE_STRING, WCHAR>
  354. {
  355. typedef CGenericNtString<UNICODE_STRING, WCHAR> Base;
  356. public:
  357. ~CUnicodeString() { }
  358. CUnicodeString(PCWSTR buffer, SIZE_T length) : Base(buffer, length) { }
  359. CUnicodeString(PCWSTR buffer) : Base(buffer) { }
  360. operator const UNICODE_STRING *() const { return this; }
  361. void operator=(PCWSTR buffer)
  362. {
  363. this->Buffer = const_cast<PWSTR>(buffer); // Careful!
  364. this->Length = static_cast<USHORT>(::StringLength(buffer) * sizeof(*Buffer));
  365. this->MaximumLength = this->Length;
  366. }
  367. void Sync()
  368. {
  369. this->Length = static_cast<USHORT>(::StringLength(Buffer) * sizeof(*Buffer));
  370. }
  371. int FormatV(PCWSTR pszFormat, va_list args)
  372. {
  373. // note that vsnprintf doesn't nul terminate if there isn't room,
  374. // it squeezes the nul out in favor of an additional character,
  375. // we work around this by telling it one char less, and by always
  376. // putting a nul at the end
  377. int cchMaximumLength = this->MaximumLength / sizeof(*Buffer);
  378. this->Buffer[cchMaximumLength - 1] = 0;
  379. int i = _vsnwprintf(this->Buffer, cchMaximumLength - 1, pszFormat, args);
  380. if (i >= 0)
  381. {
  382. this->Buffer[i] = 0;
  383. this->Length = static_cast<USHORT>(i * sizeof(*Buffer));
  384. }
  385. return i;
  386. }
  387. int Format(PCWSTR pszFormat, ...)
  388. {
  389. va_list args;
  390. va_start(args, pszFormat);
  391. int i = FormatV(pszFormat, args);
  392. va_end(args);
  393. return i;
  394. }
  395. //protected:
  396. CUnicodeString() { }
  397. private: // deliberately not implemented
  398. CUnicodeString(const CUnicodeString&);
  399. void operator=(const CUnicodeString&);
  400. };
  401. template <int N>
  402. class CUnicodeStringN : public CUnicodeString
  403. {
  404. public:
  405. ~CUnicodeStringN() { }
  406. CUnicodeStringN()
  407. {
  408. this->Buffer = m_rgchBuffer;
  409. this->Length = 0;
  410. this->MaximumLength = sizeof(m_rgchBuffer);
  411. m_rgchBuffer[0] = 0;
  412. m_rgchBuffer[N-1] = 0;
  413. }
  414. WCHAR m_rgchBuffer[N];
  415. private: // deliberately not implemented
  416. CUnicodeStringN(const CUnicodeStringN&);
  417. void operator=(const CUnicodeStringN&);
  418. };
  419. #endif // } }
  420. /*-----------------------------------------------------------------------------
  421. genericized name for strchr and wcschr
  422. -----------------------------------------------------------------------------*/
  423. //template <typename Char> const Char* StringFindChar(const Char* s, Char ch)
  424. // Automatically provide non const, but looser type binding between s
  425. // and ch. Still requires nul termination, so doesn't really support more than
  426. // char*, const char*, wchar_t*, and const wchar_t*.
  427. //
  428. // StdFind is the obvious generalization that doesn't require a particular
  429. // terminal value, but the ability to pass a terminal pointer or iterator.
  430. template <typename String, typename Char>
  431. inline String
  432. StringFindChar(String s, Char ch)
  433. {
  434. String end = s + StringLength(s);
  435. String found = StdFind(s, end, ch);
  436. if (found == end)
  437. {
  438. found = NULL;
  439. }
  440. return found;
  441. }
  442. /*-----------------------------------------------------------------------------
  443. specialize StringFindChar for char to use strchr provided
  444. in msvcrt.dll or ntdll.dll.
  445. -----------------------------------------------------------------------------*/
  446. // strchr is getting defined to be StrChrW, which does not work.
  447. #if !defined(strchr) // { {
  448. template <>
  449. inline const char* StringFindChar<const char*>(const char* s, char ch)
  450. {
  451. s = strchr(s, ch);
  452. return s;
  453. }
  454. template <>
  455. inline char* StringFindChar<char*>(char* s, char ch)
  456. {
  457. s = strchr(s, ch);
  458. return s;
  459. }
  460. #endif // } }
  461. /*-----------------------------------------------------------------------------
  462. specialize StringFindChar for wchar_t to use wcschr provided
  463. in msvcrt.dll or ntdll.dll.
  464. -----------------------------------------------------------------------------*/
  465. template <>
  466. inline const wchar_t* StringFindChar<const wchar_t*>(const wchar_t* s, wchar_t ch)
  467. {
  468. s = wcschr(s, ch);
  469. return s;
  470. }
  471. template <>
  472. inline wchar_t* StringFindChar<wchar_t*>(wchar_t* s, wchar_t ch)
  473. {
  474. s = wcschr(s, ch);
  475. return s;
  476. }
  477. /*-----------------------------------------------------------------------------
  478. common code for StringReverseSpan and StringReverseComplementSpan
  479. -----------------------------------------------------------------------------*/
  480. template <typename Char>
  481. INT
  482. PrivateStringReverseSpanCommon(
  483. const Char* begin,
  484. const Char* end,
  485. const Char* set, // nul terminated
  486. bool breakVal
  487. )
  488. {
  489. const Char* t = end;
  490. while (t != begin)
  491. {
  492. if (breakVal == !!StringFindChar(set, *--t))
  493. {
  494. ++t; // don't count the last checked one
  495. break;
  496. }
  497. }
  498. return static_cast<INT>(end - t);
  499. }
  500. /*-----------------------------------------------------------------------------
  501. Find the length of the run of characters in set from the end of [begin, end).
  502. "wcsrspn"
  503. variants of this can be seen at
  504. \vsee\lib\xfcstr\strexw.cpp
  505. and \\jayk1\g\temp\rspn.cpp
  506. -----------------------------------------------------------------------------*/
  507. template <typename Char>
  508. inline INT
  509. StringReverseSpan(
  510. const Char* begin,
  511. const Char* end,
  512. const Char* set
  513. )
  514. {
  515. // break when not found
  516. return ::PrivateStringReverseSpanCommon(begin, end, set, false);
  517. }
  518. /*-----------------------------------------------------------------------------
  519. Find the length of the run of characters not in set from the end of [begin, end).
  520. "wcsrcspn"
  521. variants of this can be seen at
  522. \vsee\lib\xfcstr\strexw.cpp
  523. and \\jayk1\g\temp\rspn.cpp
  524. -----------------------------------------------------------------------------*/
  525. template <typename Char>
  526. inline INT
  527. StringReverseComplementSpan(
  528. const Char* begin,
  529. const Char* end,
  530. const Char* set
  531. )
  532. {
  533. // break when found
  534. return ::PrivateStringReverseSpanCommon(begin, end, set, true);
  535. }
  536. template <typename Char>
  537. inline INT
  538. StringReverseComplimentSpan( // alternate spelling
  539. const Char* begin,
  540. const Char* end,
  541. const Char* set
  542. )
  543. {
  544. return StringReverseComplementSpan(begin, end, set);
  545. }
  546. template <typename Char>
  547. inline INT
  548. PrivateStringSpanCommon(
  549. const Char* begin,
  550. const Char* end,
  551. const Char* set,
  552. bool breakVal
  553. )
  554. {
  555. const Char* t = begin;
  556. while ( t != end )
  557. {
  558. if (breakVal == !!StringFindChar(set, *t++))
  559. {
  560. --t;
  561. break;
  562. }
  563. }
  564. return static_cast<INT>(t - begin);
  565. }
  566. template <typename Char>
  567. inline INT
  568. StringSpan(
  569. const Char* begin,
  570. const Char* end,
  571. const Char* set
  572. )
  573. {
  574. return ::PrivateStringSpanCommon( begin, end, set, false );
  575. }
  576. template <typename Char>
  577. inline INT
  578. StringComplimentSpan(
  579. const Char* begin,
  580. const Char* end,
  581. const Char* set
  582. )
  583. {
  584. return ::PrivateStringSpanCommon( begin, end, set, true );
  585. }
  586. #endif