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.

508 lines
11 KiB

  1. /**********************************************************************/
  2. /** Microsoft Windows NT **/
  3. /** Copyright(c) Microsoft Corp., 1999 **/
  4. /**********************************************************************/
  5. /*
  6. string.hxx
  7. This module contains a light weight string class.
  8. FILE HISTORY:
  9. Johnl 15-Aug-1994 Created
  10. MuraliK 09-July-1996 Rewrote for efficiency with no unicode support
  11. MCourage 12-Feb-1999 Another rewrite. All unicode of course.
  12. */
  13. #ifndef _STRING_HXX_
  14. #define _STRING_HXX_
  15. # include <irtlmisc.h>
  16. # include <buffer.hxx>
  17. LONG
  18. CompareStringNoCase(
  19. IN const WCHAR * String1,
  20. IN const WCHAR * String2,
  21. IN DWORD cchString1 = 0,
  22. IN DWORD cchString2 = 0
  23. );
  24. class IRTL_DLLEXP STRU;
  25. /*++
  26. class STRU:
  27. Intention:
  28. A light-weight string class supporting encapsulated string class.
  29. This object is derived from BUFFER class.
  30. It maintains following state:
  31. m_cchLen - string length cached when we update the string.
  32. --*/
  33. class STRU
  34. {
  35. public:
  36. STRU()
  37. : m_Buff(),
  38. m_cchLen( 0)
  39. {
  40. *QueryStr() = L'\0';
  41. }
  42. //
  43. // creates a stack version of the STR object - uses passed in stack buffer
  44. // STR does not free this pbInit on its own.
  45. //
  46. STRU(
  47. WCHAR * pbInit,
  48. DWORD cbInit
  49. ) : m_Buff( (BYTE *) pbInit, cbInit),
  50. m_cchLen(0)
  51. {
  52. DBG_ASSERT(cbInit > 0);
  53. *pbInit = L'\0';
  54. }
  55. //
  56. // Checks and returns TRUE if this string has no valid data else FALSE
  57. //
  58. BOOL
  59. IsEmpty(
  60. VOID
  61. ) const
  62. { return ( m_cchLen == 0 ); }
  63. //
  64. // Returns TRUE if str has the same value as this string.
  65. //
  66. BOOL
  67. Equals(
  68. const STRU & str
  69. ) const
  70. {
  71. return (str.QueryCCH() == QueryCCH()) &&
  72. (wcscmp(str.QueryStr(), QueryStr()) == 0);
  73. }
  74. //
  75. // Returns TRUE if str has the same value as this string.
  76. //
  77. BOOL
  78. Equals(
  79. const WCHAR * pchInit
  80. ) const
  81. {
  82. if (pchInit == NULL || pchInit[0] == '\0')
  83. {
  84. return (IsEmpty());
  85. }
  86. return (wcscmp(pchInit, QueryStr()) == 0);
  87. }
  88. //
  89. // Returns TRUE if str has the same value as this string.
  90. //
  91. BOOL
  92. EqualsNoCase(
  93. const STRU & str
  94. ) const
  95. {
  96. return (str.QueryCCH() == QueryCCH()) &&
  97. ( CompareStringNoCase(str.QueryStr(),
  98. QueryStr(),
  99. str.QueryCCH(),
  100. QueryCCH()) == 0 );
  101. }
  102. //
  103. // Returns TRUE if str has the same value as this string.
  104. //
  105. BOOL
  106. EqualsNoCase(
  107. const WCHAR * pchInit
  108. ) const
  109. {
  110. if (pchInit == NULL || pchInit[0] == '\0')
  111. {
  112. return (IsEmpty());
  113. }
  114. return ( CompareStringNoCase( pchInit,
  115. QueryStr(),
  116. 0, // the function will calculate the length
  117. QueryCCH()) == 0 );
  118. }
  119. //
  120. // Returns the number of bytes in the string excluding the terminating
  121. // NUL
  122. //
  123. UINT
  124. QueryCB(
  125. VOID
  126. ) const
  127. { return ( m_cchLen * sizeof(WCHAR)); }
  128. //
  129. // Returns # of characters in the string excluding the terminating NUL
  130. //
  131. UINT
  132. QueryCCH(
  133. VOID
  134. ) const
  135. { return (m_cchLen); }
  136. //
  137. // Return the string buffer
  138. //
  139. WCHAR *
  140. QueryStr(
  141. VOID
  142. )
  143. { return ((WCHAR *) m_Buff.QueryPtr()); }
  144. const WCHAR *
  145. QueryStr(
  146. VOID
  147. ) const
  148. { return ((const WCHAR *) m_Buff.QueryPtr()); }
  149. //
  150. // Resets the internal string to be NULL string. Buffer remains cached.
  151. //
  152. VOID
  153. Reset(
  154. VOID
  155. )
  156. {
  157. DBG_ASSERT( QueryStr() );
  158. *(QueryStr()) = L'\0';
  159. m_cchLen = 0;
  160. }
  161. //
  162. // Resize the internal buffer
  163. //
  164. HRESULT Resize( DWORD cbSize )
  165. {
  166. if (!m_Buff.Resize( cbSize ) )
  167. {
  168. return HRESULT_FROM_WIN32( GetLastError() );
  169. }
  170. return S_OK;
  171. }
  172. //
  173. // Append something to the end of the string
  174. //
  175. HRESULT
  176. Append(
  177. const WCHAR * pchInit
  178. )
  179. {
  180. if (pchInit) {
  181. return AuxAppend(
  182. (const BYTE *) pchInit,
  183. (ULONG) ::wcslen(pchInit) * sizeof(WCHAR),
  184. QueryCB()
  185. );
  186. } else {
  187. return S_OK;
  188. }
  189. }
  190. HRESULT
  191. Append(
  192. const WCHAR * pchInit,
  193. DWORD cchLen
  194. )
  195. {
  196. if (pchInit && cchLen) {
  197. return AuxAppend(
  198. (const BYTE *) pchInit,
  199. cchLen * sizeof(WCHAR),
  200. QueryCB()
  201. );
  202. } else {
  203. return S_OK;
  204. }
  205. }
  206. HRESULT
  207. Append(
  208. const STRU & str
  209. )
  210. {
  211. if (str.QueryCCH()) {
  212. return AuxAppend(
  213. (const BYTE *) str.QueryStr(),
  214. str.QueryCCH() * sizeof(WCHAR),
  215. QueryCB()
  216. );
  217. } else {
  218. return S_OK;
  219. }
  220. }
  221. HRESULT
  222. AppendA(
  223. const CHAR * pchInit
  224. )
  225. {
  226. return AuxAppendA(
  227. (const BYTE*) pchInit,
  228. (ULONG) strlen( pchInit ),
  229. QueryCB()
  230. );
  231. }
  232. //
  233. // Copy the contents of another string to this one
  234. //
  235. HRESULT
  236. Copy(
  237. const WCHAR * pchInit
  238. )
  239. {
  240. if (pchInit) {
  241. return AuxAppend(
  242. (const BYTE *) pchInit,
  243. (ULONG) ::wcslen(pchInit) * sizeof(WCHAR),
  244. 0
  245. );
  246. } else {
  247. return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
  248. }
  249. }
  250. HRESULT
  251. Copy(
  252. const WCHAR * pchInit,
  253. DWORD cchLen
  254. )
  255. {
  256. if (pchInit) {
  257. return AuxAppend(
  258. (const BYTE *) pchInit,
  259. cchLen * sizeof(WCHAR),
  260. 0
  261. );
  262. } else {
  263. return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
  264. }
  265. }
  266. HRESULT
  267. Copy(
  268. const STRU & str
  269. )
  270. {
  271. return AuxAppend(
  272. (const BYTE *) str.QueryStr(),
  273. str.QueryCCH() * sizeof(WCHAR),
  274. 0
  275. );
  276. }
  277. HRESULT
  278. CopyA(
  279. const CHAR * pchInit
  280. )
  281. {
  282. return AuxAppendA(
  283. (const BYTE*) pchInit,
  284. (ULONG) strlen( pchInit ),
  285. 0
  286. );
  287. }
  288. HRESULT
  289. CopyA(
  290. const CHAR * pchInit,
  291. DWORD cchLen
  292. )
  293. {
  294. return AuxAppendA(
  295. (const BYTE*) pchInit,
  296. cchLen,
  297. 0
  298. );
  299. }
  300. //
  301. // Allow access to the internal buffer, for direct manipulation.
  302. //
  303. BUFFER *
  304. QueryBuffer(
  305. VOID
  306. )
  307. {
  308. return &m_Buff;
  309. }
  310. //
  311. // Recalculate the length of the string, etc. because we've modified
  312. // the buffer directly.
  313. //
  314. VOID
  315. SyncWithBuffer(
  316. VOID
  317. )
  318. {
  319. m_cchLen = (LONG) wcslen( QueryStr() );
  320. }
  321. //
  322. // Makes a copy of the stored string into the given buffer
  323. // NYI
  324. //
  325. HRESULT
  326. CopyToBuffer(
  327. WCHAR * lpszBuffer,
  328. LPDWORD lpcb
  329. ) const;
  330. //
  331. //
  332. BOOL
  333. SetLen(
  334. IN DWORD cchLen
  335. )
  336. /*++
  337. Routine Description:
  338. Set the length of the string and null terminate, if there
  339. is sufficient buffer already allocated. Will not reallocate.
  340. NOTE: The actual wcslen may be less than cchLen if you are
  341. expanding the string. If this is the case SyncWithBuffer
  342. should be called to ensure consistency. The real use of this
  343. method is to truncate.
  344. Arguments:
  345. cchLen - The number of characters in the new string.
  346. Return Value:
  347. TRUE - if the buffer size is sufficient to hold the string.
  348. FALSE - insufficient buffer.
  349. --*/
  350. {
  351. if( cchLen >= m_Buff.QuerySize() / sizeof(WCHAR) )
  352. {
  353. return FALSE;
  354. }
  355. *((WCHAR *) m_Buff.QueryPtr() + cchLen) = L'\0';
  356. m_cchLen = cchLen;
  357. return TRUE;
  358. }
  359. //
  360. // Useful for unescaping URL, QueryString etc
  361. //
  362. HRESULT Unescape();
  363. HRESULT Escape();
  364. private:
  365. //
  366. // Avoid C++ errors. This object should never go through a copy
  367. // constructor, unintended cast or assignment.
  368. //
  369. STRU( const STRU & )
  370. {}
  371. STRU( const WCHAR * )
  372. {}
  373. STRU( WCHAR * )
  374. {}
  375. STRU & operator = ( const STRU & )
  376. { return *this; }
  377. HRESULT
  378. STRU::AuxAppend(
  379. const BYTE * pStr,
  380. ULONG cbStr,
  381. ULONG cbOffset,
  382. BOOL fAddSlop = TRUE
  383. );
  384. HRESULT
  385. STRU::AuxAppendA(
  386. const BYTE * pStr,
  387. ULONG cbStr,
  388. ULONG cbOffset,
  389. BOOL fAddSlop = TRUE
  390. );
  391. BUFFER m_Buff;
  392. LONG m_cchLen;
  393. };
  394. //
  395. // Quick macro for declaring a STR that will use stack memory of <size>
  396. // bytes. If the buffer overflows then a heap buffer will be allocated
  397. //
  398. #define STACK_STRU( name, size ) WCHAR __ach##name[size]; \
  399. STRU name( __ach##name, sizeof( __ach##name ))
  400. //
  401. // Macros for declaring and initializing a STRU that will use inline memory
  402. // of <size> bytes as a member of an object.
  403. //
  404. #define INLINE_STRU(name, size) WCHAR __ach##name[size]; \
  405. STRU name;
  406. #define INLINE_STRU_INIT(name) name( __ach##name, sizeof( __ach##name ) )
  407. //
  408. // General string utilities
  409. //
  410. #define ISWHITEW( wch ) ((wch) == L' ' || (wch) == L'\t' || (wch) == L'\r')
  411. WCHAR * SkipWhite(
  412. WCHAR * pwch
  413. );
  414. WCHAR * SkipTo(
  415. WCHAR * pwch, WCHAR wch
  416. );
  417. WCHAR *
  418. FlipSlashes(
  419. WCHAR * pszPath
  420. );
  421. HRESULT
  422. MakePathCanonicalizationProof(
  423. IN LPWSTR pszName,
  424. OUT STRU * pstrPath
  425. );
  426. #endif // !_STRING_HXX_