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.

697 lines
10 KiB

  1. /*++
  2. Copyright (c) 1998-1999 Microsoft Corporation
  3. All rights reserved.
  4. Module Name:
  5. dbgstr.cxx
  6. Abstract:
  7. Debug string class
  8. Author:
  9. Steve Kiraly (SteveKi) 23-May-1998
  10. Revision History:
  11. --*/
  12. #include "precomp.hxx"
  13. #pragma hdrstop
  14. //
  15. // Class specific NULL state.
  16. //
  17. TCHAR TDebugString::gszNullState[2] = {0,0};
  18. /*++
  19. Title:
  20. TDebugString
  21. Routine Description:
  22. Default construction.
  23. Arguments:
  24. None.
  25. Return Value:
  26. None.
  27. --*/
  28. TDebugString::
  29. TDebugString(
  30. VOID
  31. ) : m_pszString( &TDebugString::gszNullState[kValid] )
  32. {
  33. }
  34. /*++
  35. Title:
  36. TDebugString
  37. Routine Description:
  38. Construction using an existing LPCTSTR string.
  39. Arguments:
  40. None.
  41. Return Value:
  42. None.
  43. Last Error:
  44. None.
  45. --*/
  46. TDebugString::
  47. TDebugString(
  48. IN LPCTSTR psz
  49. ) : m_pszString( &TDebugString::gszNullState[kValid] )
  50. {
  51. (VOID)bUpdate( psz );
  52. }
  53. /*++
  54. Title:
  55. ~TDebugString
  56. Routine Description:
  57. Destruction, ensure we don't free our NULL state.
  58. Arguments:
  59. None.
  60. Return Value:
  61. None.
  62. --*/
  63. TDebugString::
  64. ~TDebugString(
  65. VOID
  66. )
  67. {
  68. vFree( m_pszString );
  69. }
  70. /*++
  71. Title:
  72. TDebugString
  73. Routine Description:
  74. Copy constructor.
  75. Arguments:
  76. None.
  77. Return Value:
  78. None.
  79. --*/
  80. TDebugString::
  81. TDebugString(
  82. const TDebugString &String
  83. ) : m_pszString( &TDebugString::gszNullState[kValid] )
  84. {
  85. (VOID)bUpdate( String.m_pszString );
  86. }
  87. /*++
  88. Title:
  89. bEmpty
  90. Routine Description:
  91. Indicates if a string has any usable data.
  92. Arguments:
  93. None.
  94. Return Value:
  95. None.
  96. --*/
  97. BOOL
  98. TDebugString::
  99. bEmpty(
  100. VOID
  101. ) const
  102. {
  103. return *m_pszString == NULL;
  104. }
  105. /*++
  106. Title:
  107. bValid
  108. Routine Description:
  109. Indicates if a string object is valid.
  110. Arguments:
  111. None.
  112. Return Value:
  113. None.
  114. --*/
  115. BOOL
  116. TDebugString::
  117. bValid(
  118. VOID
  119. ) const
  120. {
  121. return m_pszString != &TDebugString::gszNullState[kInValid];
  122. }
  123. /*++
  124. Title:
  125. uLen
  126. Routine Description:
  127. Return the length of the string in characters
  128. does not include the null terminator.
  129. Arguments:
  130. None.
  131. Return Value:
  132. None.
  133. --*/
  134. UINT
  135. TDebugString::
  136. uLen(
  137. VOID
  138. ) const
  139. {
  140. return _tcslen( m_pszString );
  141. }
  142. /*++
  143. Title:
  144. operator LPCTSTR
  145. Routine Description:
  146. Conversion operator from string object to pointer
  147. to constant zero terminated string.
  148. Arguments:
  149. None.
  150. Return Value:
  151. None.
  152. --*/
  153. TDebugString::
  154. operator LPCTSTR(
  155. VOID
  156. ) const
  157. {
  158. return m_pszString;
  159. }
  160. /*++
  161. Title:
  162. bCat
  163. Routine Description:
  164. Safe concatenation of the specified string to the string
  165. object. If the allocation fails, return FALSE and the
  166. original string is not lost.
  167. Arguments:
  168. psz - Input string, may be NULL.
  169. Return Value:
  170. TRUE concatination was successful
  171. FALSE concatination failed, orginal string is not modified
  172. --*/
  173. BOOL
  174. TDebugString::
  175. bCat(
  176. IN LPCTSTR psz
  177. )
  178. {
  179. BOOL bReturn;
  180. //
  181. // If a valid string was passed.
  182. //
  183. if (psz && *psz)
  184. {
  185. //
  186. // Allocate the new buffer consisting of the size of the orginal
  187. // string plus the sizeof of the new string plus the null terminator.
  188. //
  189. LPTSTR pszTemp = INTERNAL_NEW TCHAR [ _tcslen( m_pszString ) + _tcslen( psz ) + 1 ];
  190. //
  191. // If memory was not available.
  192. //
  193. if (!pszTemp)
  194. {
  195. //
  196. // Indicate failure, original string not modified.
  197. //
  198. bReturn = FALSE;
  199. }
  200. else
  201. {
  202. //
  203. // Copy the original string and tack on the provided string.
  204. //
  205. _tcscpy( pszTemp, m_pszString );
  206. _tcscat( pszTemp, psz );
  207. //
  208. // Release the original buffer.
  209. //
  210. vFree( m_pszString );
  211. //
  212. // Save pointer to new string.
  213. //
  214. m_pszString = pszTemp;
  215. //
  216. // Indicate success.
  217. //
  218. bReturn = TRUE;
  219. }
  220. }
  221. else
  222. {
  223. //
  224. // NULL pointers and NULL strings are silently ignored.
  225. //
  226. bReturn = TRUE;
  227. }
  228. return bReturn;
  229. }
  230. /*++
  231. Title:
  232. bUpdate
  233. Routine Description:
  234. Safe updating of string. If the allocation fails the
  235. orginal string is lost and the object becomes invalid.
  236. A null pointer can be passed which is basically a
  237. request to clear the contents of the string.
  238. Arguments:
  239. psz - Input string. The input string can be the null pointer
  240. in this case the contents of the string cleared.
  241. Return Value:
  242. TRUE update successful
  243. FALSE update failed
  244. --*/
  245. BOOL
  246. TDebugString::
  247. bUpdate(
  248. IN LPCTSTR psz OPTIONAL
  249. )
  250. {
  251. BOOL bReturn;
  252. //
  253. // Check if the null pointer is passed.
  254. //
  255. if (!psz)
  256. {
  257. //
  258. // Release the original string.
  259. //
  260. vFree( m_pszString );
  261. //
  262. // Mark the object as valid.
  263. //
  264. m_pszString = &TDebugString::gszNullState[kValid];
  265. //
  266. // Indicate success.
  267. //
  268. bReturn = TRUE;
  269. }
  270. else
  271. {
  272. //
  273. // Create temp pointer to the previous string.
  274. //
  275. LPTSTR pszTmp = m_pszString;
  276. //
  277. // Allocate storage for the new string.
  278. //
  279. m_pszString = INTERNAL_NEW TCHAR [ _tcslen(psz) + 1 ];
  280. //
  281. // If memory was not available.
  282. //
  283. if (!m_pszString)
  284. {
  285. //
  286. // Mark the string object as invalid.
  287. //
  288. m_pszString = &TDebugString::gszNullState[kInValid];
  289. //
  290. // Indicate failure.
  291. //
  292. bReturn = FALSE;
  293. }
  294. else
  295. {
  296. //
  297. // Copy the string to the new buffer.
  298. //
  299. _tcscpy( m_pszString, psz );
  300. //
  301. // Indicate success.
  302. //
  303. bReturn = TRUE;
  304. }
  305. //
  306. // Release the previous string.
  307. //
  308. vFree( pszTmp );
  309. }
  310. return bReturn;
  311. }
  312. /*++
  313. Title:
  314. vFree
  315. Routine Description:
  316. Safe free, frees the string memory. Ensures
  317. we do not try an free our global memory block.
  318. Arguments:
  319. pszString pointer to string meory to free.
  320. Return Value:
  321. Nothing.
  322. --*/
  323. VOID
  324. TDebugString::
  325. vFree(
  326. IN LPTSTR pszString OPTIONAL
  327. )
  328. {
  329. //
  330. // If this memory was not pointing to our
  331. // class specific gszNullStates then release the memory.
  332. //
  333. if (pszString &&
  334. pszString != &TDebugString::gszNullState[kValid] &&
  335. pszString != &TDebugString::gszNullState[kInValid])
  336. {
  337. INTERNAL_DELETE [] pszString;
  338. }
  339. }
  340. /*++
  341. Title:
  342. bFormat
  343. Routine Description:
  344. Format the string opbject similar to sprintf.
  345. Arguments:
  346. pszFmt pointer format string.
  347. .. variable number of arguments similar to sprintf.
  348. Return Value:
  349. TRUE if string was format successfully. FALSE if error
  350. occurred creating the format string, string object will be
  351. invalid and the previous string lost.
  352. --*/
  353. BOOL
  354. TDebugString::
  355. bFormat(
  356. IN LPCTSTR pszFmt,
  357. IN ...
  358. )
  359. {
  360. BOOL bReturn;
  361. va_list pArgs;
  362. va_start( pArgs, pszFmt );
  363. bReturn = bvFormat( pszFmt, pArgs );
  364. va_end( pArgs );
  365. return bReturn;
  366. }
  367. /*++
  368. Title:
  369. bvFormat
  370. Routine Description:
  371. Format the string opbject similar to vsprintf.
  372. Arguments:
  373. pszFmt pointer format string.
  374. pointer to variable number of arguments similar to vsprintf.
  375. Return Value:
  376. TRUE if string was format successfully. FALSE if error
  377. occurred creating the format string, string object will be
  378. left unaltered.
  379. --*/
  380. BOOL
  381. TDebugString::
  382. bvFormat(
  383. IN LPCTSTR pszFmt,
  384. IN va_list avlist
  385. )
  386. {
  387. BOOL bReturn;
  388. //
  389. // Save previous string value.
  390. //
  391. LPTSTR pszTemp = m_pszString;
  392. //
  393. // Format the string.
  394. //
  395. m_pszString = vsntprintf( pszFmt, avlist );
  396. //
  397. // If format failed mark object as invalid and
  398. // set the return value.
  399. //
  400. if (!m_pszString)
  401. {
  402. //
  403. // Restore the orginal pointer.
  404. //
  405. m_pszString = pszTemp;
  406. //
  407. // Indicate success.
  408. //
  409. bReturn = FALSE;
  410. }
  411. else
  412. {
  413. //
  414. // Release the previous string.
  415. //
  416. vFree( pszTemp );
  417. //
  418. // Indicate success.
  419. //
  420. bReturn = TRUE;
  421. }
  422. return bReturn;
  423. }
  424. /*++
  425. Title:
  426. vsntprintf
  427. Routine Description:
  428. Formats a string and returns a heap allocated string with the
  429. formated data. This routine can be used to for extremely
  430. long format strings. Note: If a valid pointer is returned
  431. the callng functions must release the data with a call to delete.
  432. Example:
  433. LPCTSTR p = vsntprintf( _T("Test %s"), pString );
  434. if (p)
  435. {
  436. SetTitle( p );
  437. }
  438. INTERNAL_DELETE [] p;
  439. Arguments:
  440. psFmt - format string
  441. pArgs - pointer to a argument list.
  442. Return Value:
  443. Pointer to formated string. NULL if error.
  444. --*/
  445. LPTSTR
  446. TDebugString::
  447. vsntprintf(
  448. IN LPCTSTR szFmt,
  449. IN va_list pArgs
  450. ) const
  451. {
  452. LPTSTR pszBuff;
  453. INT iSize = 256;
  454. for( ; ; )
  455. {
  456. //
  457. // Allocate the message buffer.
  458. //
  459. pszBuff = INTERNAL_NEW TCHAR [iSize];
  460. //
  461. // Allocating the buffer failed, we are done.
  462. //
  463. if (!pszBuff)
  464. {
  465. break;
  466. }
  467. //
  468. // Attempt to format the string. snprintf fails with a
  469. // negative number when the buffer is too small.
  470. //
  471. INT iReturn = _vsntprintf(pszBuff, iSize, szFmt, pArgs);
  472. //
  473. // If the return value positive and not equal to the buffer size
  474. // then the format succeeded. _vsntprintf will not null terminate
  475. // the string if the resultant string is exactly the length of the
  476. // provided buffer.
  477. //
  478. if (iReturn > 0 && iReturn != iSize)
  479. {
  480. break;
  481. }
  482. //
  483. // String did not fit release the current buffer.
  484. //
  485. INTERNAL_DELETE [] pszBuff;
  486. //
  487. // Null the buffer pointer.
  488. //
  489. pszBuff = NULL;
  490. //
  491. // Double the buffer size after each failure.
  492. //
  493. iSize *= 2;
  494. //
  495. // If the size is greater than 100k exit without formatting a string.
  496. //
  497. if (iSize > kMaxFormatStringLength)
  498. {
  499. break;
  500. }
  501. }
  502. return pszBuff;
  503. }