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.

535 lines
14 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. */
  12. #ifndef _STRINGA_HXX_
  13. #define _STRINGA_HXX_
  14. # include <irtlmisc.h>
  15. # include <buffer.hxx>
  16. class STRU;
  17. //
  18. // These are the characters that are considered to be white space
  19. //
  20. #define ISWHITE( ch ) ((ch) == L'\t' || (ch) == L' ' || (ch) == L'\r')
  21. #define ISWHITEA( ch ) ((ch) == '\t' || (ch) == ' ' || (ch) == '\r')
  22. //
  23. // Is the specified character ASCII printable when dumping binary data?
  24. //
  25. #define IS_ASCII_PRINTABLE( ch ) ((ch > 31 && ch < 127) ? TRUE : FALSE)
  26. #define IS_EXTENDED_ASCII_PRINTABLE( ch ) ((ch > 31 && ch < 176 ) ? TRUE : FALSE)
  27. //
  28. // Maximum number of characters a loadable string resource can be
  29. //
  30. #ifndef STR_MAX_RES_SIZE
  31. #define STR_MAX_RES_SIZE ( 320 )
  32. #endif
  33. //
  34. // If an application defines STR_MODULE_NAME, it will be used
  35. // as the default module name on string loads
  36. //
  37. #ifndef STR_MODULE_NAME
  38. #define STR_MODULE_NAME NULL
  39. #endif
  40. /*++
  41. class STRA:
  42. Intention:
  43. A light-weight string class supporting encapsulated string class.
  44. This object is derived from BUFFER class.
  45. It maintains following state:
  46. m_cchLen - string length cached when we update the string.
  47. --*/
  48. class IRTL_DLLEXP STRA;
  49. class STRA
  50. {
  51. public:
  52. STRA()
  53. : m_Buff(),
  54. m_cchLen( 0)
  55. {
  56. *QueryStr() = '\0';
  57. }
  58. //
  59. // creates a stack version of the STRA object - uses passed in stack buffer
  60. // STRA does not free this pbInit on its own.
  61. //
  62. STRA(CHAR *pbInit,
  63. DWORD cbInit)
  64. : m_Buff((BYTE *)pbInit, cbInit),
  65. m_cchLen(0)
  66. {
  67. DBG_ASSERT(cbInit > 0);
  68. *pbInit = '\0';
  69. }
  70. BOOL IsValid( VOID ) const { return ( m_Buff.IsValid() ) ; }
  71. //
  72. // Checks and returns TRUE if this string has no valid data else FALSE
  73. //
  74. BOOL IsEmpty() const
  75. {
  76. return (m_cchLen == 0);
  77. }
  78. //
  79. // Returns TRUE if str has the same value as this string.
  80. //
  81. BOOL Equals(const STRA &str) const
  82. {
  83. return (str.QueryCCH() == QueryCCH()) &&
  84. (strcmp(str.QueryStr(), QueryStr()) == 0);
  85. }
  86. //
  87. // Returns TRUE if str has the same value as this string.
  88. //
  89. BOOL Equals(const PCHAR pchInit) const
  90. {
  91. if (pchInit == NULL || pchInit[0] == '\0')
  92. {
  93. return (IsEmpty());
  94. }
  95. return (strcmp(pchInit, QueryStr()) == 0);
  96. }
  97. //
  98. // Case insensitive comparison
  99. // Returns TRUE if str has the same value as this string.
  100. //
  101. BOOL EqualsNoCase(const STRA &str) const
  102. {
  103. return (str.QueryCCH() == QueryCCH()) &&
  104. (_stricmp(str.QueryStr(), QueryStr()) == 0);
  105. }
  106. //
  107. // Case insensitive comparison
  108. // Returns TRUE if str has the same value as this string.
  109. //
  110. BOOL EqualsNoCase(const PCHAR pchInit) const
  111. {
  112. if (pchInit == NULL || pchInit[0] == '\0')
  113. {
  114. return (IsEmpty());
  115. }
  116. return (_stricmp(pchInit, QueryStr()) == 0);
  117. }
  118. //
  119. // Returns the number of bytes in the string excluding the terminating
  120. // NULL
  121. //
  122. UINT QueryCB() const
  123. {
  124. return m_cchLen;
  125. }
  126. //
  127. // Returns # of characters in the string excluding the terminating NULL
  128. //
  129. UINT QueryCCH() const
  130. {
  131. return m_cchLen;
  132. }
  133. //
  134. // Returns number of bytes in storage buffer
  135. //
  136. UINT QuerySize() const
  137. {
  138. return m_Buff.QuerySize();
  139. }
  140. //
  141. // Return the string buffer
  142. //
  143. CHAR *QueryStr()
  144. {
  145. return (CHAR *)m_Buff.QueryPtr();
  146. }
  147. const CHAR *QueryStr() const
  148. {
  149. return (const CHAR *)m_Buff.QueryPtr();
  150. }
  151. //
  152. // Resets the internal string to be NULL string. Buffer remains cached.
  153. //
  154. VOID Reset()
  155. {
  156. DBG_ASSERT( QueryStr() );
  157. *(QueryStr()) = '\0';
  158. m_cchLen = 0;
  159. }
  160. //
  161. // Resize the internal buffer
  162. //
  163. HRESULT Resize(DWORD size)
  164. {
  165. if (!m_Buff.Resize(size))
  166. {
  167. return HRESULT_FROM_WIN32(GetLastError());
  168. }
  169. return S_OK;
  170. }
  171. //
  172. // Append something to the end of the string
  173. //
  174. HRESULT Append(const CHAR *pchInit)
  175. {
  176. if (pchInit)
  177. {
  178. return AuxAppend((const BYTE *)pchInit,
  179. (ULONG) strlen(pchInit),
  180. QueryCB());
  181. }
  182. return S_OK;
  183. }
  184. HRESULT Append(const CHAR * pchInit,
  185. DWORD cchLen)
  186. {
  187. if (pchInit && cchLen)
  188. {
  189. return AuxAppend((const BYTE *) pchInit,
  190. cchLen,
  191. QueryCB());
  192. }
  193. return S_OK;
  194. }
  195. HRESULT Append(const STRA & str)
  196. {
  197. if (str.QueryCCH())
  198. {
  199. return AuxAppend((const BYTE *)str.QueryStr(),
  200. str.QueryCCH(),
  201. QueryCCH());
  202. }
  203. return S_OK;
  204. }
  205. HRESULT AppendW(const WCHAR *pchInit)
  206. {
  207. return AuxAppendW( pchInit,
  208. (ULONG) wcslen( pchInit ),
  209. QueryCB());
  210. }
  211. HRESULT AppendW(const WCHAR *pchInit,
  212. DWORD cchLen)
  213. {
  214. return AuxAppendW( pchInit,
  215. cchLen,
  216. QueryCB());
  217. }
  218. //
  219. // The "Truncate" methods do not do proper conversion, use them only if
  220. // the data is guaranteed to be in English (in effect, DO NOT use this
  221. // for any data obtained from the wire)
  222. //
  223. HRESULT AppendWTruncate(const WCHAR *pchInit,
  224. DWORD cchLen)
  225. {
  226. return AuxAppendWTruncate( pchInit,
  227. cchLen,
  228. QueryCB() );
  229. }
  230. HRESULT AppendWTruncate(const WCHAR *pchInit)
  231. {
  232. return AuxAppendWTruncate( pchInit,
  233. (ULONG) wcslen( pchInit ),
  234. QueryCB() );
  235. }
  236. //
  237. // Copy the contents of another string to this one
  238. //
  239. HRESULT Copy(const CHAR *pchInit)
  240. {
  241. if (pchInit)
  242. {
  243. return AuxAppend((const BYTE *)pchInit,
  244. (ULONG) strlen(pchInit),
  245. 0);
  246. }
  247. return HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER);
  248. }
  249. HRESULT Copy(const CHAR * pchInit,
  250. DWORD cchLen)
  251. {
  252. if (pchInit && cchLen)
  253. {
  254. return AuxAppend((const BYTE *)pchInit,
  255. cchLen,
  256. 0);
  257. }
  258. if (cchLen)
  259. {
  260. return HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER);
  261. }
  262. return S_OK;
  263. }
  264. HRESULT Copy(const STRA & str)
  265. {
  266. return AuxAppend((const BYTE *)str.QueryStr(),
  267. str.QueryCB(),
  268. 0);
  269. }
  270. HRESULT CopyW(const WCHAR *pchInit)
  271. {
  272. Reset();
  273. return AuxAppendW( pchInit,
  274. (ULONG) wcslen( pchInit ),
  275. 0 );
  276. }
  277. HRESULT CopyW(const WCHAR *pchInit,
  278. DWORD cchLen)
  279. {
  280. Reset();
  281. return AuxAppendW( pchInit,
  282. cchLen,
  283. 0);
  284. }
  285. //
  286. // The "Truncate" methods do not do proper conversion, use them only if
  287. // the data is guaranteed to be in English (in effect, DO NOT use this
  288. // for any data obtained from the wire)
  289. //
  290. HRESULT CopyWTruncate(const WCHAR *pchInit)
  291. {
  292. return AuxAppendWTruncate( pchInit,
  293. (ULONG) wcslen( pchInit ),
  294. 0 );
  295. }
  296. HRESULT CopyWTruncate(const WCHAR *pchInit,
  297. DWORD cchLen)
  298. {
  299. Reset();
  300. return AuxAppendWTruncate( pchInit,
  301. cchLen,
  302. 0 );
  303. }
  304. HRESULT CopyWToUTF8(const STRU& stru);
  305. HRESULT CopyWToUTF8(LPCWSTR cpchStr)
  306. { return STRA::CopyWToUTF8(cpchStr, (DWORD) wcslen(cpchStr)); }
  307. HRESULT CopyWToUTF8(LPCWSTR cpchStr,
  308. DWORD cchLen);
  309. HRESULT CopyWToUTF8Unescaped(const STRU& stru);
  310. HRESULT CopyWToUTF8Unescaped(LPCWSTR cpchStr)
  311. { return STRA::CopyWToUTF8Unescaped(cpchStr, (DWORD) wcslen(cpchStr)); }
  312. HRESULT CopyWToUTF8Unescaped(LPCWSTR cpchStr,
  313. DWORD cchLen);
  314. //
  315. // Makes a copy of the stored string into the given buffer
  316. //
  317. HRESULT CopyToBuffer(CHAR *lpszBuffer,
  318. LPDWORD lpcb) const;
  319. BOOL SetLen(IN DWORD cchLen)
  320. /*++
  321. Routine Description:
  322. Set the length of the string and null terminate, if there
  323. is sufficient buffer already allocated. Will not reallocate.
  324. NOTE: The actual wcslen may be less than cchLen if you are
  325. expanding the string. If this is the case SyncWithBuffer
  326. should be called to ensure consistency. The real use of this
  327. method is to truncate.
  328. Arguments:
  329. cchLen - The number of characters in the new string.
  330. Return Value:
  331. TRUE - if the buffer size is sufficient to hold the string.
  332. FALSE - insufficient buffer.
  333. --*/
  334. {
  335. if(cchLen >= m_Buff.QuerySize())
  336. {
  337. return FALSE;
  338. }
  339. *((CHAR *) m_Buff.QueryPtr() + cchLen) = '\0';
  340. m_cchLen = cchLen;
  341. return TRUE;
  342. }
  343. //
  344. // Recalculate the length of the string, etc. because we've modified
  345. // the buffer directly.
  346. //
  347. VOID
  348. SyncWithBuffer(
  349. VOID
  350. )
  351. {
  352. m_cchLen = (LONG) strlen( QueryStr() );
  353. }
  354. //
  355. // Makes a clone of the current string in the string pointer passed in.
  356. //
  357. HRESULT
  358. Clone( OUT STRA * pstrClone ) const
  359. {
  360. return ( ( pstrClone == NULL ) ?
  361. ( HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER ) ) :
  362. ( pstrClone->Copy( *this ) )
  363. );
  364. } // STR::Clone()
  365. //
  366. // Loads a string from this module's string resource table
  367. //
  368. HRESULT LoadString( IN DWORD dwResID,
  369. IN LPCSTR lpszModuleName = STR_MODULE_NAME,
  370. IN DWORD dwLangID = 0);
  371. HRESULT LoadString( IN DWORD dwResID,
  372. IN HMODULE hModule);
  373. //
  374. // Loads a string with insert params from this module's .mc resource
  375. // table. Pass zero for the resource ID to use *this.
  376. //
  377. HRESULT
  378. FormatString( IN DWORD dwResID,
  379. IN LPCSTR apszInsertParams[],
  380. IN LPCSTR lpszModuleName = STR_MODULE_NAME OPTIONAL,
  381. IN DWORD cbMaxMsg = 1024 OPTIONAL );
  382. //
  383. // Useful for unescaping URL, QueryString etc
  384. //
  385. HRESULT Unescape();
  386. HRESULT Escape(BOOL fEscapeHighBitCharsOnly = FALSE,
  387. BOOL fDontEscapeQueryString = FALSE );
  388. HRESULT HTMLEncode();
  389. //
  390. // Accept binary input and store it as a printable dump
  391. //
  392. HRESULT CopyBinary( LPVOID pData, DWORD cbData );
  393. private:
  394. //
  395. // Avoid C++ errors. This object should never go through a copy
  396. // constructor, unintended cast or assignment.
  397. //
  398. STRA( const STRA &)
  399. {}
  400. STRA( const CHAR *)
  401. {}
  402. STRA(CHAR *)
  403. {}
  404. STRA & operator = (const STRA &)
  405. { return *this; }
  406. HRESULT AuxAppend(const BYTE *pStr,
  407. ULONG cbStr,
  408. ULONG cbOffset,
  409. BOOL fAddSlop = TRUE);
  410. HRESULT AuxAppendW(const WCHAR *pStr,
  411. ULONG cchStr,
  412. ULONG cbOffset,
  413. BOOL fAddSlop = TRUE);
  414. HRESULT AuxAppendWTruncate(const WCHAR *pStr,
  415. ULONG cchStr,
  416. ULONG cbOffset,
  417. BOOL fAddSlop = TRUE);
  418. BUFFER m_Buff;
  419. LONG m_cchLen;
  420. };
  421. //
  422. // Quick macro for declaring a STRA that will use stack memory of <size>
  423. // bytes. If the buffer overflows then a heap buffer will be allocated
  424. //
  425. #define STACK_STRA(name, size) CHAR __ach##name[size]; \
  426. STRA name( __ach##name, sizeof( __ach##name ))
  427. //
  428. // Macros for declaring and initializing a STRA that will use inline memory
  429. // of <size> bytes as a member of an object.
  430. //
  431. #define INLINE_STRA(name, size) CHAR __ach##name[size]; \
  432. STRA name;
  433. #define INLINE_STRA_INIT(name) name( __ach##name, sizeof( __ach##name ) )
  434. #endif