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.

476 lines
11 KiB

  1. /******************************************************************************
  2. Header File: String Array.CPP
  3. Implements the String Array class- see the related header for the declaration
  4. of this class.
  5. This class will do arrays in chunks- if the total array exceeds the size of
  6. one chunk, we chain more instances together, then use recursion to do the
  7. work.
  8. Copyright (c) 1996 by Microsoft Corporation
  9. A Pretty Penny Enterprises Production
  10. Change History:
  11. 11-01-96 a-robkj@microsoft.com- original version
  12. 12-04-96 a-robkj@microsoft.com Added LoadString and IsEmpty to CString
  13. Also fixed bug in Remove where
  14. u > ChunkSize (wasn't exiting)
  15. 12-11-96 a-robkj@microsoft.com Let CString do ANSI/UNICODE conversions
  16. automagically to ease some API issues
  17. 01-07-97 KjelgaardR@acm.org Fixed CStringArray::Empty and CUintArray::Empty
  18. to NULL pointer to next chunk after deleting it. Led to GP faults
  19. if we needed to use the chunk again.
  20. ******************************************************************************/
  21. #include "ICMUI.H"
  22. // Convert a UNICODE string to a new ANSI buffer
  23. void CString::Flip(LPCWSTR lpstrIn, LPSTR& lpstrOut) {
  24. if (!lpstrIn) {
  25. lpstrOut = NULL;
  26. return;
  27. }
  28. int iLength = WideCharToMultiByte(CP_ACP, 0, lpstrIn, -1, NULL, 0, NULL,
  29. NULL);
  30. if (!iLength) {
  31. lpstrOut = NULL;
  32. return;
  33. }
  34. lpstrOut = (LPSTR) malloc(++iLength);
  35. if(lpstrOut) {
  36. WideCharToMultiByte(CP_ACP, 0, lpstrIn, -1, lpstrOut, iLength, NULL,
  37. NULL);
  38. }
  39. }
  40. // Convert an ANSI string to a new UNICODE buffer
  41. void CString::Flip(LPCSTR lpstrIn, LPWSTR& lpstrOut) {
  42. if (!lpstrIn) {
  43. lpstrOut = NULL;
  44. return;
  45. }
  46. int iLength = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, lpstrIn, -1,
  47. NULL, 0);
  48. if (!iLength) {
  49. lpstrOut = NULL;
  50. return;
  51. }
  52. lpstrOut = (LPWSTR) malloc(++iLength * sizeof (WCHAR));
  53. if(lpstrOut) {
  54. MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, lpstrIn, -1, lpstrOut,
  55. iLength);
  56. }
  57. }
  58. // Empty the string, and free all memory.
  59. void CString::Empty() {
  60. if (m_acContents)
  61. free(m_acContents);
  62. if (m_acConverted)
  63. free(m_acConverted);
  64. m_acContents = NULL;
  65. m_acConverted = NULL;
  66. m_bConverted = FALSE;
  67. }
  68. // Compare with other CString
  69. BOOL CString::IsEqualString(CString& csRef1)
  70. {
  71. if (IsEmpty() || csRef1.IsEmpty())
  72. return (FALSE);
  73. return (_tcsicmp(m_acContents,(LPTSTR)csRef1) == 0);
  74. }
  75. CString::CString() {
  76. m_acContents = NULL;
  77. m_acConverted = NULL;
  78. m_bConverted = FALSE;
  79. }
  80. CString::CString(const CString& csRef) {
  81. m_acContents = csRef.m_acContents ? _tcsdup(csRef.m_acContents) : NULL;
  82. m_acConverted = NULL;
  83. m_bConverted = FALSE;
  84. }
  85. CString::CString(LPCTSTR lpstrRef) {
  86. m_acContents = lpstrRef ? _tcsdup(lpstrRef) : NULL;
  87. m_acConverted = NULL;
  88. m_bConverted = FALSE;
  89. }
  90. CString::CString(LPCOSTR lpstrRef) {
  91. m_acConverted = NULL;
  92. m_bConverted = FALSE;
  93. if (!lpstrRef) {
  94. m_acContents = NULL;
  95. return;
  96. }
  97. Flip(lpstrRef, m_acContents);
  98. }
  99. // Class destructor
  100. CString::~CString() {
  101. Empty();
  102. }
  103. // Report string in non-native encoding
  104. CString::operator LPCOSTR() {
  105. if (!m_bConverted) {
  106. Flip(m_acContents, m_acConverted);
  107. m_bConverted = TRUE;
  108. }
  109. return m_acConverted;
  110. }
  111. const CString& CString::operator =(const CString& csSrc) {
  112. Empty();
  113. m_acContents = csSrc.m_acContents ? _tcsdup(csSrc.m_acContents) : NULL;
  114. return *this;
  115. }
  116. const CString& CString::operator =(LPCTSTR lpstrSrc) {
  117. Empty();
  118. m_acContents = lpstrSrc ? _tcsdup(lpstrSrc) : NULL;
  119. return *this;
  120. }
  121. const CString& CString::operator =(LPCOSTR lpstrSrc) {
  122. Empty();
  123. Flip(lpstrSrc, m_acContents);
  124. return *this;
  125. }
  126. CString CString::NameOnly() const {
  127. TCHAR acName[_MAX_FNAME];
  128. if (!m_acContents)
  129. return *this;
  130. _tsplitpath(m_acContents, NULL, NULL, acName, NULL);
  131. return acName;
  132. }
  133. CString CString::NameAndExtension() const {
  134. TCHAR acName[_MAX_FNAME], acExtension[_MAX_EXT];
  135. if (!m_acContents)
  136. return *this;
  137. _tsplitpath(m_acContents, NULL, NULL, acName, acExtension);
  138. lstrcat(acName, acExtension);
  139. return acName;
  140. }
  141. void CString::Load(int id, HINSTANCE hi) {
  142. if (!hi)
  143. hi = CGlobals::Instance();
  144. TCHAR acWork[MAX_PATH];
  145. if(LoadString(hi, id, acWork, MAX_PATH) > 0)
  146. *this = acWork;
  147. else
  148. *this = TEXT("");
  149. }
  150. // 03-20-1997 [email protected] Part of RAID 22289.
  151. // Add a method for loading text from a windows handle
  152. void CString::Load(HWND hwnd) {
  153. Empty();
  154. int iccNeeded = GetWindowTextLength(hwnd);
  155. if (!iccNeeded)
  156. return;
  157. m_acContents = (LPTSTR) malloc(++iccNeeded * sizeof (TCHAR));
  158. if(m_acContents) {
  159. GetWindowText(hwnd, m_acContents, iccNeeded);
  160. }
  161. }
  162. void CString::LoadAndFormat(int id, HINSTANCE hiWhere, BOOL bSystemMessage,
  163. DWORD dwNumMsg, va_list *argList) {
  164. Empty();
  165. TCHAR acWork[1024];
  166. CString csTemplate;
  167. LPTSTR lpSource;
  168. DWORD dwFlags;
  169. if (bSystemMessage) {
  170. lpSource = NULL;
  171. dwFlags = FORMAT_MESSAGE_FROM_SYSTEM;
  172. } else {
  173. csTemplate.Load(id);
  174. lpSource = csTemplate;
  175. dwFlags = FORMAT_MESSAGE_FROM_STRING;
  176. id = 0;
  177. }
  178. if (FormatMessage(dwFlags,lpSource, id, 0, acWork, 1024, argList)) {
  179. *this = acWork;
  180. }
  181. }
  182. CString operator +(const CString& csRef, LPCTSTR lpstrRef) {
  183. if (!lpstrRef || !*lpstrRef)
  184. return csRef;
  185. if (csRef.IsEmpty())
  186. return lpstrRef;
  187. CString csReturn;
  188. csReturn.m_acContents = (LPTSTR) malloc((1 + lstrlen(csRef.m_acContents) +
  189. lstrlen(lpstrRef)) * sizeof(TCHAR));
  190. if(csReturn.m_acContents) {
  191. lstrcat(lstrcpy(csReturn.m_acContents, csRef.m_acContents), lpstrRef);
  192. }
  193. return csReturn;
  194. }
  195. // CStringArray classes- these manage an array of strings,
  196. // but the methods are geared to list-style management.
  197. // Borrow first element from next chunk
  198. LPCTSTR CStringArray::Borrow() {
  199. LPCTSTR lpstrReturn = m_aStore[0];
  200. memcpy((LPSTR) m_aStore, (LPSTR) (m_aStore + 1),
  201. (ChunkSize() - 1) * sizeof m_aStore[0]);
  202. if (m_ucUsed > ChunkSize())
  203. m_aStore[ChunkSize() - 1] = m_pcsaNext -> Borrow();
  204. else
  205. m_aStore[ChunkSize() - 1] = (LPCTSTR) NULL;
  206. m_ucUsed--;
  207. if (m_ucUsed <= ChunkSize() && m_pcsaNext) {
  208. delete m_pcsaNext;
  209. m_pcsaNext = NULL;
  210. }
  211. return lpstrReturn;
  212. }
  213. // ctor
  214. CStringArray::CStringArray() {
  215. m_ucUsed = 0;
  216. m_pcsaNext = NULL;
  217. }
  218. // dtor
  219. CStringArray::~CStringArray() {
  220. Empty();
  221. }
  222. // Empty the list/array
  223. void CStringArray::Empty() {
  224. if (!m_ucUsed) return;
  225. if (m_pcsaNext) {
  226. delete m_pcsaNext;
  227. m_pcsaNext = NULL;
  228. }
  229. m_ucUsed = 0;
  230. }
  231. unsigned CStringArray::Map(LPCTSTR lpstrRef) {
  232. for (unsigned u = 0; u < m_ucUsed; u++)
  233. if (!lstrcmpi(operator[](u), lpstrRef))
  234. break;
  235. return u;
  236. }
  237. // Add an item
  238. void CStringArray::Add(LPCTSTR lpstrNew) {
  239. if (m_ucUsed < ChunkSize()) {
  240. m_aStore[m_ucUsed++] = lpstrNew;
  241. return;
  242. }
  243. // Not enough space! Add another record, if there isn't one
  244. if (!m_pcsaNext)
  245. m_pcsaNext = new CStringArray;
  246. // Add the string to the next array (recursive call!)
  247. if (m_pcsaNext) {
  248. m_pcsaNext -> Add(lpstrNew);
  249. m_ucUsed++;
  250. }
  251. }
  252. // define an indexing operator
  253. CString& CStringArray::operator [](unsigned u) const {
  254. _ASSERTE(u < m_ucUsed);
  255. return u < ChunkSize() ?
  256. (CString&)m_aStore[u] : m_pcsaNext -> operator[](u - ChunkSize());
  257. }
  258. // Remove the string at some index, shifting the rest down one slot
  259. void CStringArray::Remove(unsigned u) {
  260. if (u > m_ucUsed)
  261. return;
  262. if (u >= ChunkSize()) {
  263. m_pcsaNext -> Remove(u - ChunkSize());
  264. return;
  265. }
  266. memmove((LPSTR) (m_aStore + u), (LPSTR) (m_aStore + u + 1),
  267. (ChunkSize() - (u + 1)) * sizeof m_aStore[0]);
  268. if (m_ucUsed > ChunkSize())
  269. m_aStore[ChunkSize() - 1] = m_pcsaNext -> Borrow();
  270. else
  271. m_aStore[ChunkSize() - 1] = (LPCTSTR) NULL;
  272. m_ucUsed--;
  273. if (m_ucUsed <= ChunkSize() && m_pcsaNext) {
  274. delete m_pcsaNext;
  275. m_pcsaNext = NULL;
  276. }
  277. }
  278. // CUintArray class- this manages an array/list of unsigned integers
  279. // The implementation is quite similar to the CStringArray's. Why
  280. // bother to do it different, after all?
  281. unsigned CUintArray::Borrow() {
  282. unsigned uReturn = m_aStore[0];
  283. memcpy((LPSTR) m_aStore, (LPSTR) (m_aStore + 1),
  284. (ChunkSize() - 1) * sizeof m_aStore[0]);
  285. if (m_ucUsed > ChunkSize())
  286. m_aStore[ChunkSize() - 1] = m_pcuaNext -> Borrow();
  287. else
  288. m_aStore[ChunkSize() - 1] = 0;
  289. m_ucUsed--;
  290. if (m_ucUsed <= ChunkSize() && m_pcuaNext) {
  291. delete m_pcuaNext;
  292. m_pcuaNext = NULL;
  293. }
  294. return uReturn;
  295. }
  296. CUintArray::CUintArray() {
  297. m_ucUsed = 0;
  298. m_pcuaNext = NULL;
  299. }
  300. CUintArray::~CUintArray() {
  301. Empty();
  302. }
  303. void CUintArray::Empty() {
  304. if (!m_ucUsed) return;
  305. if (m_pcuaNext) {
  306. delete m_pcuaNext;
  307. m_pcuaNext = NULL;
  308. }
  309. m_ucUsed = 0;
  310. }
  311. // Add an item
  312. void CUintArray::Add(unsigned uNew) {
  313. if (m_ucUsed < ChunkSize()) {
  314. m_aStore[m_ucUsed++] = uNew;
  315. return;
  316. }
  317. // Not enough space! Add another record, if there isn't one
  318. if (!m_pcuaNext)
  319. m_pcuaNext = new CUintArray;
  320. // Add the item to the next array (recursive call!)
  321. if (m_pcuaNext) {
  322. m_pcuaNext -> Add(uNew);
  323. m_ucUsed++;
  324. }
  325. }
  326. unsigned CUintArray::operator [](unsigned u) const {
  327. return u < m_ucUsed ? u < ChunkSize() ?
  328. m_aStore[u] : m_pcuaNext -> operator[](u - ChunkSize()) : 0;
  329. }
  330. void CUintArray::Remove(unsigned u) {
  331. if (u > m_ucUsed)
  332. return;
  333. if (u >= ChunkSize()) {
  334. m_pcuaNext -> Remove(u - ChunkSize());
  335. return;
  336. }
  337. memmove((LPSTR) (m_aStore + u), (LPSTR) (m_aStore + u + 1),
  338. (ChunkSize() - (u + 1)) * sizeof m_aStore[0]);
  339. if (m_ucUsed > ChunkSize())
  340. m_aStore[ChunkSize() - 1] = m_pcuaNext -> Borrow();
  341. else
  342. m_aStore[ChunkSize() - 1] = 0;
  343. m_ucUsed--;
  344. if (m_ucUsed <= ChunkSize() && m_pcuaNext) {
  345. delete m_pcuaNext;
  346. m_pcuaNext = NULL;
  347. }
  348. }