Source code of Windows XP (NT5)
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.

427 lines
10 KiB

  1. /*++
  2. Copyright (c) 2000 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 M. Krell (a-JayK) May 2000
  14. Revision History:
  15. --*/
  16. #pragma once
  17. #include <stdio.h>
  18. #include "fusionntdll.h"
  19. //#include "fusionalgorithm.h"
  20. class CUnicodeCharTraits;
  21. template <typename T> class CGenericBaseStringBuffer;
  22. int
  23. FusionpCompareStrings(
  24. PCWSTR sz1,
  25. SIZE_T cch1,
  26. PCWSTR sz2,
  27. SIZE_T cch2,
  28. bool fCaseInsensitive
  29. );
  30. inline bool
  31. FusionpEqualStrings(
  32. PCWSTR sz1,
  33. SIZE_T cch1,
  34. PCWSTR sz2,
  35. SIZE_T cch2,
  36. bool fCaseInsensitive
  37. )
  38. {
  39. return ((cch1 == cch2) && (FusionpCompareStrings(sz1, cch1, sz2, cch2, fCaseInsensitive) == 0));
  40. }
  41. int
  42. FusionpCompareStrings(
  43. const CGenericBaseStringBuffer<CUnicodeCharTraits> &rbuff1,
  44. PCWSTR psz2,
  45. SIZE_T cch2,
  46. bool fCaseInsensitive
  47. );
  48. int
  49. FusionpCompareStrings(
  50. PCWSTR psz1,
  51. SIZE_T cch1,
  52. const CGenericBaseStringBuffer<CUnicodeCharTraits> &rbuff2,
  53. bool fCaseInsensitive
  54. );
  55. int
  56. FusionpCompareStrings(
  57. const CGenericBaseStringBuffer<CUnicodeCharTraits> &rbuff1,
  58. const CGenericBaseStringBuffer<CUnicodeCharTraits> &rbuff2,
  59. bool fCaseInsensitive
  60. );
  61. int
  62. FusionpCompareStrings(
  63. PCSTR sz1,
  64. SIZE_T cch1,
  65. PCSTR sz2,
  66. SIZE_T cch2,
  67. bool fCaseInsensitive
  68. );
  69. #if !defined(FUSION_CANONICAL_CASE_IS_UPPER)
  70. #define FUSION_CANONICAL_CASE_IS_UPPER 1
  71. #endif // !defined(FUSION_CANONICAL_CASE_IS_UPPER)
  72. #if FUSION_CANONICAL_CASE_IS_UPPER
  73. inline WCHAR FusionpCanonicalizeUnicodeChar(WCHAR wch) { return ::FusionpRtlUpcaseUnicodeChar(wch); }
  74. #else
  75. inline WCHAR FusionpCanonicalizeUnicodeChar(WCHAR wch) { return ::FusionpRtlDowncaseUnicodeChar(wch); }
  76. #endif
  77. inline int
  78. FusionpStrCmpI(
  79. PCWSTR psz1,
  80. PCWSTR psz2
  81. )
  82. {
  83. return ::FusionpCompareStrings(
  84. psz1,
  85. (psz1 != NULL) ? ::wcslen(psz1) : 0,
  86. psz2,
  87. (psz2 != NULL) ? ::wcslen(psz2) : 0,
  88. true);
  89. }
  90. /*-----------------------------------------------------------------------------
  91. StringLength is a generic name for getting the length, in count of
  92. characters, of various kinds of strings
  93. -----------------------------------------------------------------------------*/
  94. inline SIZE_T StringLength(LPCSTR psz)
  95. {
  96. return ::strlen(psz);
  97. }
  98. inline SIZE_T StringLength(LPCWSTR psz)
  99. {
  100. return ::wcslen(psz);
  101. }
  102. #if defined(NT_INCLUDED) // { {
  103. inline SIZE_T StringLength(const UNICODE_STRING* s)
  104. {
  105. return s->Length / sizeof(*s->Buffer);
  106. }
  107. inline SIZE_T StringLength(const ANSI_STRING* s)
  108. {
  109. return s->Length / sizeof(*s->Buffer);
  110. }
  111. /*
  112. perhaps half backed, like UNICODE_STRING itself, should probably call
  113. these CContantUnicodeString or CUnicodeStringNoFree, to indicate
  114. they do no allocation or deallocation
  115. ..
  116. ..
  117. darn, really just need to merge this with existing FusionBuffer...
  118. */
  119. #define CONSTANT_UNICODE_STRING(x) \
  120. { \
  121. /* the subtraction is to not count the terminal nul */ \
  122. static_cast<unsigned short>(sizeof(x) - sizeof((x)[0])), \
  123. static_cast<unsigned short>(sizeof(x) - sizeof((x)[0])), \
  124. const_cast<PWSTR>(x) \
  125. }
  126. extern const UNICODE_STRING g_strEmptyUnicodeString;
  127. class CUnicodeString : public UNICODE_STRING
  128. {
  129. public:
  130. ~CUnicodeString() { }
  131. CUnicodeString(PCWSTR buffer, SIZE_T length)
  132. {
  133. this->Buffer = const_cast<PWSTR>(buffer); // Careful!
  134. this->Length = static_cast<USHORT>(length * sizeof(*Buffer));
  135. this->MaximumLength = this->Length;
  136. }
  137. CUnicodeString(PCWSTR buffer)
  138. {
  139. this->Buffer = const_cast<PWSTR>(buffer);
  140. this->Length = static_cast<USHORT>(::wcslen(buffer) * sizeof(*Buffer));
  141. this->MaximumLength = this->Length;
  142. }
  143. operator const UNICODE_STRING *() const { return this; }
  144. void operator=(PCWSTR buffer)
  145. {
  146. this->Buffer = const_cast<PWSTR>(buffer); // Careful!
  147. this->Length = static_cast<USHORT>(::wcslen(buffer) * sizeof(*Buffer));
  148. this->MaximumLength = this->Length;
  149. }
  150. void Sync()
  151. {
  152. this->Length = static_cast<USHORT>(::wcslen(Buffer) * sizeof(*Buffer));
  153. }
  154. int FormatV(PCWSTR pszFormat, va_list args)
  155. {
  156. // note that vsnprintf doesn't nul terminate if there isn't room,
  157. // it squeezes the nul out in favor of an additional character,
  158. // we work around this by telling it one char less, and by always
  159. // putting a nul at the end
  160. int cchMaximumLength = this->MaximumLength / sizeof(*Buffer);
  161. this->Buffer[cchMaximumLength - 1] = 0;
  162. int i = _vsnwprintf(this->Buffer, cchMaximumLength - 1, pszFormat, args);
  163. if (i >= 0)
  164. {
  165. this->Buffer[i] = 0;
  166. this->Length = static_cast<USHORT>(i * sizeof(*Buffer));
  167. }
  168. return i;
  169. }
  170. int Format(PCWSTR pszFormat, ...)
  171. {
  172. va_list args;
  173. va_start(args, pszFormat);
  174. int i = FormatV(pszFormat, args);
  175. va_end(args);
  176. return i;
  177. }
  178. //protected:
  179. CUnicodeString()
  180. {
  181. this->Buffer = L"";
  182. this->Length = sizeof(*Buffer);
  183. this->MaximumLength = this->Length;
  184. }
  185. private: // deliberately not implemented
  186. CUnicodeString(const CUnicodeString&);
  187. void operator=(const CUnicodeString&);
  188. };
  189. template <int N>
  190. class CUnicodeStringN : public CUnicodeString
  191. {
  192. public:
  193. ~CUnicodeStringN() { }
  194. CUnicodeStringN()
  195. {
  196. this->Buffer = m_rgchBuffer;
  197. this->Length = 0;
  198. this->MaximumLength = sizeof(m_rgchBuffer);
  199. m_rgchBuffer[0] = 0;
  200. m_rgchBuffer[N-1] = 0;
  201. }
  202. WCHAR m_rgchBuffer[N];
  203. private: // deliberately not implemented
  204. CUnicodeStringN(const CUnicodeStringN&);
  205. void operator=(const CUnicodeStringN&);
  206. };
  207. #endif // } }
  208. /*-----------------------------------------------------------------------------
  209. genericized name for strchr and wcschr
  210. -----------------------------------------------------------------------------*/
  211. //template <typename Char> const Char* StringFindChar(const Char* s, Char ch)
  212. // Automatically provide non const, but looser type binding between s
  213. // and ch. Still requires nul termination, so doesn't really support more than
  214. // char*, const char*, wchar_t*, and const wchar_t*.
  215. //
  216. // StdFind is the obvious generalization that doesn't require a particular
  217. // terminal value, but the ability to pass a terminal pointer or iterator.
  218. template <typename String, typename Char>
  219. inline String
  220. StringFindChar(String s, Char ch)
  221. {
  222. String end = s + StringLength(s);
  223. String found = StdFind(s, end, ch);
  224. if (found == end)
  225. {
  226. found = NULL;
  227. }
  228. return found;
  229. }
  230. /*-----------------------------------------------------------------------------
  231. specialize StringFindChar for char to use strchr provided
  232. in msvcrt.dll or ntdll.dll.
  233. -----------------------------------------------------------------------------*/
  234. // strchr is getting defined to be StrChrW, which does not work.
  235. #if !defined(strchr) // { {
  236. template <>
  237. inline const char* StringFindChar<const char*>(const char* s, char ch)
  238. {
  239. s = strchr(s, ch);
  240. return s;
  241. }
  242. template <>
  243. inline char* StringFindChar<char*>(char* s, char ch)
  244. {
  245. s = strchr(s, ch);
  246. return s;
  247. }
  248. #endif // } }
  249. /*-----------------------------------------------------------------------------
  250. specialize StringFindChar for wchar_t to use wcschr provided
  251. in msvcrt.dll or ntdll.dll.
  252. -----------------------------------------------------------------------------*/
  253. template <>
  254. inline const wchar_t* StringFindChar<const wchar_t*>(const wchar_t* s, wchar_t ch)
  255. {
  256. s = wcschr(s, ch);
  257. return s;
  258. }
  259. template <>
  260. inline wchar_t* StringFindChar<wchar_t*>(wchar_t* s, wchar_t ch)
  261. {
  262. s = wcschr(s, ch);
  263. return s;
  264. }
  265. /*-----------------------------------------------------------------------------
  266. common code for StringReverseSpan and StringReverseComplementSpan
  267. -----------------------------------------------------------------------------*/
  268. template <typename Char>
  269. INT
  270. PrivateStringReverseSpanCommon(
  271. const Char* begin,
  272. const Char* end,
  273. const Char* set, // nul terminated
  274. bool breakVal
  275. )
  276. {
  277. const Char* t = end;
  278. while (t != begin)
  279. {
  280. if (breakVal == !!StringFindChar(set, *--t))
  281. {
  282. ++t; // don't count the last checked one
  283. break;
  284. }
  285. }
  286. return static_cast<INT>(end - t);
  287. }
  288. /*-----------------------------------------------------------------------------
  289. Find the length of the run of characters in set from the end of [begin, end).
  290. "wcsrspn"
  291. variants of this can be seen at
  292. \vsee\lib\xfcstr\strexw.cpp
  293. and \\jayk1\g\temp\rspn.cpp
  294. -----------------------------------------------------------------------------*/
  295. template <typename Char>
  296. inline INT
  297. StringReverseSpan(
  298. const Char* begin,
  299. const Char* end,
  300. const Char* set
  301. )
  302. {
  303. // break when not found
  304. return ::PrivateStringReverseSpanCommon(begin, end, set, false);
  305. }
  306. /*-----------------------------------------------------------------------------
  307. Find the length of the run of characters not in set from the end of [begin, end).
  308. "wcsrcspn"
  309. variants of this can be seen at
  310. \vsee\lib\xfcstr\strexw.cpp
  311. and \\jayk1\g\temp\rspn.cpp
  312. -----------------------------------------------------------------------------*/
  313. template <typename Char>
  314. inline INT
  315. StringReverseComplementSpan(
  316. const Char* begin,
  317. const Char* end,
  318. const Char* set
  319. )
  320. {
  321. // break when found
  322. return ::PrivateStringReverseSpanCommon(begin, end, set, true);
  323. }
  324. template <typename Char>
  325. inline INT
  326. PrivateStringSpanCommon(
  327. const Char* begin,
  328. const Char* end,
  329. const Char* set,
  330. bool breakVal
  331. )
  332. {
  333. const Char* t = begin;
  334. while ( t != end )
  335. {
  336. if (breakVal == !!StringFindChar(set, *t++))
  337. {
  338. --t;
  339. break;
  340. }
  341. }
  342. return static_cast<INT>(t - begin);
  343. }
  344. template <typename Char>
  345. inline INT
  346. StringSpan(
  347. const Char* begin,
  348. const Char* end,
  349. const Char* set
  350. )
  351. {
  352. return ::PrivateStringSpanCommon( begin, end, set, false );
  353. }
  354. template <typename Char>
  355. inline INT
  356. StringComplimentSpan(
  357. const Char* begin,
  358. const Char* end,
  359. const Char* set
  360. )
  361. {
  362. return ::PrivateStringSpanCommon( begin, end, set, true );
  363. }