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.

358 lines
10 KiB

  1. /**********************************************************************/
  2. /** Microsoft Windows NT **/
  3. /** Copyright(c) Microsoft Corp., 1997 **/
  4. /**********************************************************************/
  5. /*
  6. string.cxx
  7. This module contains a light weight string class
  8. FILE HISTORY:
  9. 4/8/97 michth created
  10. */
  11. #include "precomp.hxx"
  12. #include "aucommon.hxx"
  13. /*******************************************************************
  14. NAME: STRAU::STR
  15. SYNOPSIS: Construct a string object
  16. ENTRY: Optional object initializer
  17. NOTES: If the object is not valid (i.e. !IsValid()) then GetLastError
  18. should be called.
  19. The object is guaranteed to construct successfully if nothing
  20. or NULL is passed as the initializer.
  21. ********************************************************************/
  22. // Inlined in stringau.hxx
  23. VOID
  24. STRAU::AuxInit( const LPSTR pInit )
  25. {
  26. BOOL fRet;
  27. if ( pInit && (*pInit != '\0') )
  28. {
  29. INT cbCopy = (::strlen( pInit ) + 1) * sizeof(CHAR);
  30. fRet = m_bufAnsi.Resize( cbCopy );
  31. if ( fRet ) {
  32. CopyMemory( m_bufAnsi.QueryPtr(), pInit, cbCopy );
  33. m_cbMultiByteLen = (cbCopy)/sizeof(CHAR) - 1;
  34. m_bUnicode = FALSE;
  35. m_bInSync = FALSE;
  36. } else {
  37. m_bIsValid = FALSE;
  38. }
  39. } else {
  40. Reset();
  41. }
  42. return;
  43. } // STRAU::AuxInit()
  44. VOID
  45. STRAU::AuxInit( const LPWSTR pInit )
  46. {
  47. BOOL fRet;
  48. if ( pInit && (*pInit != (WCHAR)'\0'))
  49. {
  50. INT cbCopy = (::wcslen( pInit) + 1) * sizeof(WCHAR);
  51. fRet = m_bufUnicode.Resize( cbCopy );
  52. if ( fRet ) {
  53. CopyMemory( m_bufUnicode.QueryPtr(), pInit, cbCopy );
  54. m_cchUnicodeLen = (cbCopy)/sizeof(WCHAR) - 1;
  55. m_bUnicode = TRUE;
  56. m_bInSync = FALSE;
  57. } else {
  58. m_bIsValid = FALSE;
  59. }
  60. } else {
  61. Reset();
  62. }
  63. return;
  64. } // STRAU::AuxInit()
  65. /*******************************************************************
  66. NAME: STRAU::AuxAppend
  67. SYNOPSIS: Appends the string onto this one.
  68. ENTRY: Object to append
  69. ********************************************************************/
  70. BOOL STRAU::AuxAppend( const LPSTR pStr, UINT cbStr, BOOL fAddSlop )
  71. {
  72. DBG_ASSERT( pStr != NULL );
  73. BOOL bReturn = m_bIsValid;
  74. if (m_bIsValid) {
  75. if (!m_bUnicode || (m_cchUnicodeLen == 0)) {
  76. //
  77. // Just append the ANSI string
  78. //
  79. //
  80. // Only resize when we have to. When we do resize, we tack on
  81. // some extra space to avoid extra reallocations.
  82. //
  83. // Note: QuerySize returns the requested size of the string buffer,
  84. // *not* the strlen of the buffer
  85. //
  86. if ( m_bufAnsi.QuerySize() < ((m_cbMultiByteLen + cbStr + 1) * sizeof(CHAR)) )
  87. {
  88. bReturn = m_bufAnsi.Resize( ((m_cbMultiByteLen + cbStr + 1) * sizeof(CHAR)) + ((fAddSlop) ? STR_SLOP : 0) );
  89. }
  90. if (bReturn) {
  91. // copy the exact string and append a null character
  92. memcpy( (BYTE *) (((LPSTR)m_bufAnsi.QueryPtr()) + m_cbMultiByteLen),
  93. pStr,
  94. cbStr * sizeof(char));
  95. m_cbMultiByteLen += cbStr;
  96. *((CHAR *) m_bufAnsi.QueryPtr() + m_cbMultiByteLen) = '\0'; // append an explicit null char
  97. m_bUnicode = FALSE;
  98. m_bInSync = FALSE;
  99. }
  100. else {
  101. m_bIsValid = FALSE;
  102. }
  103. }
  104. else {
  105. //
  106. // Currently have a UNICODE string
  107. // Need to convert to UNICODE and copy
  108. // Use the ANSI buffer as temporary space
  109. //
  110. int iUnicodeLen = ConvertMultiByteToUnicode(pStr, &m_bufAnsi, cbStr);
  111. if (STR_CONVERSION_SUCCEEDED(iUnicodeLen)) {
  112. if ( m_bufUnicode.QuerySize() < ((m_cchUnicodeLen + iUnicodeLen + 1) * sizeof(WCHAR)) )
  113. {
  114. bReturn = m_bufUnicode.Resize( ((m_cchUnicodeLen + iUnicodeLen + 1) * sizeof(WCHAR)) + ((fAddSlop) ? STR_SLOP : 0) );
  115. }
  116. if (bReturn) {
  117. // copy the exact string and append a null character
  118. memcpy( (BYTE *) ((LPWSTR)(m_bufUnicode.QueryPtr()) + m_cchUnicodeLen),
  119. m_bufAnsi.QueryPtr(),
  120. (iUnicodeLen * sizeof(WCHAR)));
  121. m_cchUnicodeLen += iUnicodeLen;
  122. *((LPWSTR)m_bufUnicode.QueryPtr() + m_cchUnicodeLen) = (WCHAR)'\0'; // append an explicit null char
  123. m_bInSync = FALSE;
  124. }
  125. else {
  126. m_bIsValid = FALSE;
  127. }
  128. }
  129. else {
  130. m_bIsValid = FALSE;
  131. }
  132. }
  133. }
  134. return bReturn;
  135. } // STRAU::AuxAppend()
  136. BOOL STRAU::AuxAppend( const LPWSTR pStr, UINT cchStr, BOOL fAddSlop )
  137. {
  138. DBG_ASSERT( pStr != NULL );
  139. BOOL bReturn = m_bIsValid;
  140. int iUnicodeLen;
  141. if (m_bIsValid) {
  142. if (!m_bUnicode && !m_bInSync && (m_cbMultiByteLen != 0)) {
  143. // Currently have an ANSI string
  144. // Need to convert ANSI string to UNICODE before copy
  145. //
  146. iUnicodeLen = ConvertMultiByteToUnicode((LPSTR)m_bufAnsi.QueryPtr(), &m_bufUnicode, m_cbMultiByteLen);
  147. if (STR_CONVERSION_SUCCEEDED(iUnicodeLen)) {
  148. m_cchUnicodeLen = iUnicodeLen;
  149. }
  150. else {
  151. bReturn = FALSE;
  152. m_bIsValid = FALSE;
  153. }
  154. }
  155. if (bReturn) {
  156. //
  157. // Only resize when we have to. When we do resize, we tack on
  158. // some extra space to avoid extra reallocations.
  159. //
  160. // Note: QuerySize returns the requested size of the string buffer,
  161. // *not* the strlen of the buffer
  162. //
  163. if ( m_bufUnicode.QuerySize() < ((m_cchUnicodeLen + cchStr + 1) * sizeof(WCHAR)) )
  164. {
  165. bReturn = m_bufUnicode.Resize( ((m_cchUnicodeLen + cchStr + 1) * sizeof(WCHAR)) + ((fAddSlop) ? STR_SLOP : 0) );
  166. }
  167. if (bReturn) {
  168. // copy the exact string and append a null character
  169. memcpy( (BYTE *) (((LPWSTR)m_bufUnicode.QueryPtr()) + m_cchUnicodeLen),
  170. pStr,
  171. (cchStr * sizeof(WCHAR)));
  172. m_cchUnicodeLen += cchStr;
  173. *((LPWSTR)m_bufUnicode.QueryPtr() + m_cchUnicodeLen) = (WCHAR)'\0'; // append an explicit null char
  174. m_bInSync = FALSE;
  175. m_bUnicode = TRUE;
  176. }
  177. else {
  178. m_bIsValid = FALSE;
  179. }
  180. }
  181. }
  182. return bReturn;
  183. } // STRAU::AuxAppend()
  184. BOOL
  185. STRAU::SetLen( IN DWORD cchLen)
  186. {
  187. BOOL bReturn = FALSE;
  188. if (cchLen <= QueryCCH()) {
  189. if (m_bUnicode || m_bInSync) {
  190. *((LPWSTR)m_bufUnicode.QueryPtr() + cchLen) = (WCHAR)'\0';
  191. m_cchUnicodeLen = cchLen;
  192. }
  193. if (!m_bUnicode || m_bInSync) {
  194. LPSTR pszTerminateByte = (LPSTR)m_bufAnsi.QueryPtr();
  195. WORD wPrimaryLangID = PRIMARYLANGID(GetSystemDefaultLangID());
  196. if (wPrimaryLangID == LANG_JAPANESE ||
  197. wPrimaryLangID == LANG_CHINESE ||
  198. wPrimaryLangID == LANG_KOREAN)
  199. {
  200. char *pszTop = pszTerminateByte;
  201. for (DWORD i = 0; i < QueryCCH(); i++) {
  202. pszTerminateByte = CharNextExA(CP_ACP,
  203. pszTerminateByte,
  204. 0);
  205. }
  206. m_cbMultiByteLen = DIFF(pszTerminateByte - pszTop);
  207. }
  208. else
  209. {
  210. pszTerminateByte += cchLen;
  211. m_cbMultiByteLen = cchLen;
  212. }
  213. *pszTerminateByte = '\0';
  214. }
  215. bReturn = TRUE;
  216. }
  217. return bReturn;
  218. }
  219. LPTSTR
  220. STRAU::QueryStr(BOOL bUnicode)
  221. {
  222. //
  223. // This can fail. Return a null string for either UNICODE or ANSI
  224. // So that clients expecting a valid pointer actually get one.
  225. //
  226. LPTSTR pszReturn = NULL;
  227. int iNewStrLen;
  228. if (m_bIsValid) {
  229. if ((bUnicode != m_bUnicode) && (!m_bInSync)) {
  230. //
  231. // Need to Convert First
  232. //
  233. if (bUnicode) {
  234. //
  235. // Convert current string to UNICODE
  236. //
  237. iNewStrLen = ConvertMultiByteToUnicode((LPSTR)m_bufAnsi.QueryPtr(), &m_bufUnicode, m_cbMultiByteLen);
  238. if (STR_CONVERSION_SUCCEEDED(iNewStrLen)) {
  239. m_cchUnicodeLen = iNewStrLen;
  240. m_bInSync = TRUE;
  241. }
  242. else {
  243. m_bIsValid = FALSE;
  244. }
  245. }
  246. else {
  247. //
  248. // Convert current string to Ansi
  249. //
  250. iNewStrLen = ConvertUnicodeToMultiByte((LPWSTR)m_bufUnicode.QueryPtr(), &m_bufAnsi, m_cchUnicodeLen);
  251. if (STR_CONVERSION_SUCCEEDED(iNewStrLen)) {
  252. m_cbMultiByteLen = iNewStrLen;
  253. m_bInSync = TRUE;
  254. }
  255. else {
  256. m_bIsValid = FALSE;
  257. }
  258. }
  259. }
  260. if (m_bIsValid) {
  261. if (bUnicode) {
  262. pszReturn = (LPTSTR)m_bufUnicode.QueryPtr();
  263. }
  264. else {
  265. pszReturn = (LPTSTR)m_bufAnsi.QueryPtr();
  266. }
  267. }
  268. }
  269. return pszReturn;
  270. }
  271. BOOL
  272. STRAU::SafeCopy( const LPSTR pchInit )
  273. {
  274. BOOL bReturn = TRUE;
  275. SaveState();
  276. Reset();
  277. if (pchInit != NULL) {
  278. bReturn = AuxAppend(pchInit, ::strlen( pchInit ), FALSE );
  279. if (!bReturn) {
  280. RestoreState();
  281. }
  282. }
  283. return bReturn;
  284. }
  285. BOOL
  286. STRAU::SafeCopy( const LPWSTR pchInit )
  287. {
  288. BOOL bReturn = TRUE;
  289. SaveState();
  290. Reset();
  291. if (pchInit != NULL) {
  292. bReturn = AuxAppend( pchInit, ::wcslen( pchInit ), FALSE );
  293. if (!bReturn) {
  294. RestoreState();
  295. }
  296. }
  297. return bReturn;
  298. }