Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

stringar.cpp

Go to the documentation of this file.
00001 /****************************************************************************** 00002 00003 Header File: String Array.CPP 00004 00005 Implements the String Array class- see the related header for the declaration 00006 of this class. 00007 00008 This class will do arrays in chunks- if the total array exceeds the size of 00009 one chunk, we chain more instances together, then use recursion to do the 00010 work. 00011 00012 Copyright (c) 1996 by Microsoft Corporation 00013 00014 A Pretty Penny Enterprises Production 00015 00016 Change History: 00017 00018 11-01-96 [email protected] original version 00019 12-04-96 [email protected] Added LoadString and IsEmpty to CString 00020 Also fixed bug in Remove where 00021 u > ChunkSize (wasn't exiting) 00022 12-11-96 [email protected] Let CString do ANSI/UNICODE conversions 00023 automagically to ease some API issues 00024 01-07-97 [email protected] Fixed CStringArray::Empty and CUintArray::Empty 00025 to NULL pointer to next chunk after deleting it. Led to GP faults 00026 if we needed to use the chunk again. 00027 00028 ******************************************************************************/ 00029 00030 #include "ICMUI.H" 00031 00032 // Convert a UNICODE string to a new ANSI buffer 00033 00034 void CString::Flip(LPCWSTR lpstrIn, LPSTR& lpstrOut) { 00035 if (!lpstrIn) { 00036 lpstrOut = NULL; 00037 return; 00038 } 00039 int iLength = WideCharToMultiByte(CP_ACP, 0, lpstrIn, -1, NULL, 0, NULL, 00040 NULL); 00041 00042 if (!iLength) { 00043 lpstrOut = NULL; 00044 return; 00045 } 00046 00047 lpstrOut = (LPSTR) malloc(++iLength); 00048 if(lpstrOut) { 00049 WideCharToMultiByte(CP_ACP, 0, lpstrIn, -1, lpstrOut, iLength, NULL, 00050 NULL); 00051 } 00052 } 00053 00054 // Convert an ANSI string to a new UNICODE buffer 00055 00056 void CString::Flip(LPCSTR lpstrIn, LPWSTR& lpstrOut) { 00057 if (!lpstrIn) { 00058 lpstrOut = NULL; 00059 return; 00060 } 00061 00062 int iLength = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, lpstrIn, -1, 00063 NULL, 0); 00064 00065 if (!iLength) { 00066 lpstrOut = NULL; 00067 return; 00068 } 00069 00070 lpstrOut = (LPWSTR) malloc(++iLength * sizeof (WCHAR)); 00071 if(lpstrOut) { 00072 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, lpstrIn, -1, lpstrOut, 00073 iLength); 00074 } 00075 } 00076 00077 // Empty the string, and free all memory. 00078 00079 void CString::Empty() { 00080 if (m_acContents) 00081 free(m_acContents); 00082 00083 if (m_acConverted) 00084 free(m_acConverted); 00085 00086 m_acContents = NULL; 00087 m_acConverted = NULL; 00088 m_bConverted = FALSE; 00089 } 00090 00091 // Compare with other CString 00092 00093 BOOL CString::IsEqualString(CString& csRef1) 00094 { 00095 if (IsEmpty() || csRef1.IsEmpty()) 00096 return (FALSE); 00097 00098 return (_tcsicmp(m_acContents,(LPTSTR)csRef1) == 0); 00099 } 00100 00101 CString::CString() { 00102 m_acContents = NULL; 00103 m_acConverted = NULL; 00104 m_bConverted = FALSE; 00105 } 00106 00107 CString::CString(const CString& csRef) { 00108 m_acContents = csRef.m_acContents ? _tcsdup(csRef.m_acContents) : NULL; 00109 m_acConverted = NULL; 00110 m_bConverted = FALSE; 00111 } 00112 00113 CString::CString(LPCTSTR lpstrRef) { 00114 m_acContents = lpstrRef ? _tcsdup(lpstrRef) : NULL; 00115 m_acConverted = NULL; 00116 m_bConverted = FALSE; 00117 } 00118 00119 CString::CString(LPCOSTR lpstrRef) { 00120 m_acConverted = NULL; 00121 m_bConverted = FALSE; 00122 00123 if (!lpstrRef) { 00124 m_acContents = NULL; 00125 return; 00126 } 00127 00128 Flip(lpstrRef, m_acContents); 00129 } 00130 00131 // Class destructor 00132 00133 CString::~CString() { 00134 Empty(); 00135 } 00136 00137 // Report string in non-native encoding 00138 00139 CString::operator LPCOSTR() { 00140 if (!m_bConverted) { 00141 Flip(m_acContents, m_acConverted); 00142 m_bConverted = TRUE; 00143 } 00144 return m_acConverted; 00145 } 00146 00147 const CString& CString::operator =(const CString& csSrc) { 00148 Empty(); 00149 m_acContents = csSrc.m_acContents ? _tcsdup(csSrc.m_acContents) : NULL; 00150 return *this; 00151 } 00152 00153 const CString& CString::operator =(LPCTSTR lpstrSrc) { 00154 Empty(); 00155 m_acContents = lpstrSrc ? _tcsdup(lpstrSrc) : NULL; 00156 return *this; 00157 } 00158 00159 const CString& CString::operator =(LPCOSTR lpstrSrc) { 00160 Empty(); 00161 Flip(lpstrSrc, m_acContents); 00162 return *this; 00163 } 00164 00165 CString CString::NameOnly() const { 00166 TCHAR acName[_MAX_FNAME]; 00167 00168 if (!m_acContents) 00169 return *this; 00170 00171 _tsplitpath(m_acContents, NULL, NULL, acName, NULL); 00172 00173 return acName; 00174 } 00175 00176 CString CString::NameAndExtension() const { 00177 TCHAR acName[_MAX_FNAME], acExtension[_MAX_EXT]; 00178 00179 if (!m_acContents) 00180 return *this; 00181 00182 _tsplitpath(m_acContents, NULL, NULL, acName, acExtension); 00183 00184 lstrcat(acName, acExtension); 00185 00186 return acName; 00187 } 00188 00189 void CString::Load(int id, HINSTANCE hi) { 00190 00191 if (!hi) 00192 hi = CGlobals::Instance(); 00193 00194 TCHAR acWork[MAX_PATH]; 00195 LoadString(hi, id, acWork, MAX_PATH); 00196 *this = acWork; 00197 } 00198 00199 // 03-20-1997 [email protected] Part of RAID 22289. 00200 // Add a method for loading text from a windows handle 00201 00202 void CString::Load(HWND hwnd) { 00203 Empty(); 00204 00205 int iccNeeded = GetWindowTextLength(hwnd); 00206 if (!iccNeeded) 00207 return; 00208 m_acContents = (LPTSTR) malloc(++iccNeeded * sizeof (TCHAR)); 00209 if(m_acContents) { 00210 GetWindowText(hwnd, m_acContents, iccNeeded); 00211 } 00212 } 00213 00214 void CString::LoadAndFormat(int id, HINSTANCE hiWhere, BOOL bSystemMessage, 00215 DWORD dwNumMsg, va_list *argList) { 00216 Empty(); 00217 00218 TCHAR acWork[1024]; 00219 CString csTemplate; 00220 LPTSTR lpSource; 00221 DWORD dwFlags; 00222 00223 if (bSystemMessage) { 00224 lpSource = NULL; 00225 dwFlags = FORMAT_MESSAGE_FROM_SYSTEM; 00226 } else { 00227 csTemplate.Load(id); 00228 lpSource = csTemplate; 00229 dwFlags = FORMAT_MESSAGE_FROM_STRING; 00230 id = 0; 00231 } 00232 00233 if (FormatMessage(dwFlags,lpSource, id, 0, acWork, 1024, argList)) { 00234 *this = acWork; 00235 } 00236 } 00237 00238 CString operator +(const CString& csRef, LPCTSTR lpstrRef) { 00239 if (!lpstrRef || !*lpstrRef) 00240 return csRef; 00241 00242 if (csRef.IsEmpty()) 00243 return lpstrRef; 00244 00245 CString csReturn; 00246 00247 csReturn.m_acContents = (LPTSTR) malloc((1 + lstrlen(csRef.m_acContents) + 00248 lstrlen(lpstrRef)) * sizeof(TCHAR)); 00249 if(csReturn.m_acContents) { 00250 lstrcat(lstrcpy(csReturn.m_acContents, csRef.m_acContents), lpstrRef); 00251 } 00252 00253 return csReturn; 00254 } 00255 00256 // CStringArray classes- these manage an array of strings, 00257 // but the methods are geared to list-style management. 00258 00259 // Borrow first element from next chunk 00260 00261 LPCTSTR CStringArray::Borrow() { 00262 00263 LPCTSTR lpstrReturn = m_aStore[0]; 00264 00265 memcpy((LPSTR) m_aStore, (LPSTR) (m_aStore + 1), 00266 (ChunkSize() - 1) * sizeof m_aStore[0]); 00267 00268 if (m_ucUsed > ChunkSize()) 00269 m_aStore[ChunkSize() - 1] = m_pcsaNext -> Borrow(); 00270 else 00271 m_aStore[ChunkSize() - 1] = (LPCTSTR) NULL; 00272 00273 m_ucUsed--; 00274 00275 if (m_ucUsed <= ChunkSize() && m_pcsaNext) { 00276 delete m_pcsaNext; 00277 m_pcsaNext = NULL; 00278 } 00279 00280 return lpstrReturn; 00281 } 00282 00283 // ctor 00284 00285 CStringArray::CStringArray() { 00286 m_ucUsed = 0; 00287 m_pcsaNext = NULL; 00288 } 00289 00290 // dtor 00291 00292 CStringArray::~CStringArray() { 00293 Empty(); 00294 } 00295 00296 // Empty the list/array 00297 00298 void CStringArray::Empty() { 00299 00300 if (!m_ucUsed) return; 00301 00302 if (m_pcsaNext) { 00303 delete m_pcsaNext; 00304 m_pcsaNext = NULL; 00305 } 00306 m_ucUsed = 0; 00307 } 00308 00309 unsigned CStringArray::Map(LPCTSTR lpstrRef) { 00310 00311 for (unsigned u = 0; u < m_ucUsed; u++) 00312 if (!lstrcmpi(operator[](u), lpstrRef)) 00313 break; 00314 00315 return u; 00316 } 00317 00318 // Add an item 00319 00320 void CStringArray::Add(LPCTSTR lpstrNew) { 00321 00322 if (m_ucUsed < ChunkSize()) { 00323 m_aStore[m_ucUsed++] = lpstrNew; 00324 return; 00325 } 00326 00327 // Not enough space! Add another record, if there isn't one 00328 00329 if (!m_pcsaNext) 00330 m_pcsaNext = new CStringArray; 00331 00332 // Add the string to the next array (recursive call!) 00333 00334 if (m_pcsaNext) { 00335 m_pcsaNext -> Add(lpstrNew); 00336 m_ucUsed++; 00337 } 00338 } 00339 00340 // define an indexing operator 00341 00342 CString& CStringArray::operator [](unsigned u) const { 00343 _ASSERTE(u < m_ucUsed); 00344 00345 return u < ChunkSize() ? 00346 (CString&)m_aStore[u] : m_pcsaNext -> operator[](u - ChunkSize()); 00347 } 00348 00349 // Remove the string at some index, shifting the rest down one slot 00350 00351 void CStringArray::Remove(unsigned u) { 00352 00353 if (u > m_ucUsed) 00354 return; 00355 00356 if (u >= ChunkSize()) { 00357 m_pcsaNext -> Remove(u - ChunkSize()); 00358 return; 00359 } 00360 00361 memmove((LPSTR) (m_aStore + u), (LPSTR) (m_aStore + u + 1), 00362 (ChunkSize() - (u + 1)) * sizeof m_aStore[0]); 00363 00364 if (m_ucUsed > ChunkSize()) 00365 m_aStore[ChunkSize() - 1] = m_pcsaNext -> Borrow(); 00366 else 00367 m_aStore[ChunkSize() - 1] = (LPCTSTR) NULL; 00368 00369 m_ucUsed--; 00370 00371 if (m_ucUsed <= ChunkSize() && m_pcsaNext) { 00372 delete m_pcsaNext; 00373 m_pcsaNext = NULL; 00374 } 00375 } 00376 00377 // CUintArray class- this manages an array/list of unsigned integers 00378 // The implementation is quite similar to the CStringArray's. Why 00379 // bother to do it different, after all? 00380 00381 unsigned CUintArray::Borrow() { 00382 00383 unsigned uReturn = m_aStore[0]; 00384 00385 memcpy((LPSTR) m_aStore, (LPSTR) (m_aStore + 1), 00386 (ChunkSize() - 1) * sizeof m_aStore[0]); 00387 00388 if (m_ucUsed > ChunkSize()) 00389 m_aStore[ChunkSize() - 1] = m_pcuaNext -> Borrow(); 00390 else 00391 m_aStore[ChunkSize() - 1] = 0; 00392 00393 m_ucUsed--; 00394 00395 if (m_ucUsed <= ChunkSize() && m_pcuaNext) { 00396 delete m_pcuaNext; 00397 m_pcuaNext = NULL; 00398 } 00399 00400 return uReturn; 00401 } 00402 00403 CUintArray::CUintArray() { 00404 m_ucUsed = 0; 00405 m_pcuaNext = NULL; 00406 } 00407 00408 CUintArray::~CUintArray() { 00409 Empty(); 00410 } 00411 00412 void CUintArray::Empty() { 00413 00414 if (!m_ucUsed) return; 00415 00416 if (m_pcuaNext) { 00417 delete m_pcuaNext; 00418 m_pcuaNext = NULL; 00419 } 00420 m_ucUsed = 0; 00421 } 00422 00423 // Add an item 00424 void CUintArray::Add(unsigned uNew) { 00425 00426 if (m_ucUsed < ChunkSize()) { 00427 m_aStore[m_ucUsed++] = uNew; 00428 return; 00429 } 00430 00431 // Not enough space! Add another record, if there isn't one 00432 00433 if (!m_pcuaNext) 00434 m_pcuaNext = new CUintArray; 00435 00436 // Add the item to the next array (recursive call!) 00437 00438 if (m_pcuaNext) { 00439 m_pcuaNext -> Add(uNew); 00440 m_ucUsed++; 00441 } 00442 } 00443 00444 unsigned CUintArray::operator [](unsigned u) const { 00445 return u < m_ucUsed ? u < ChunkSize() ? 00446 m_aStore[u] : m_pcuaNext -> operator[](u - ChunkSize()) : 0; 00447 } 00448 00449 void CUintArray::Remove(unsigned u) { 00450 00451 if (u > m_ucUsed) 00452 return; 00453 00454 if (u >= ChunkSize()) { 00455 m_pcuaNext -> Remove(u - ChunkSize()); 00456 return; 00457 } 00458 00459 memmove((LPSTR) (m_aStore + u), (LPSTR) (m_aStore + u + 1), 00460 (ChunkSize() - (u + 1)) * sizeof m_aStore[0]); 00461 00462 if (m_ucUsed > ChunkSize()) 00463 m_aStore[ChunkSize() - 1] = m_pcuaNext -> Borrow(); 00464 else 00465 m_aStore[ChunkSize() - 1] = 0; 00466 00467 m_ucUsed--; 00468 00469 if (m_ucUsed <= ChunkSize() && m_pcuaNext) { 00470 delete m_pcuaNext; 00471 m_pcuaNext = NULL; 00472 } 00473 } 00474

Generated on Sat May 15 19:41:53 2004 for test by doxygen 1.3.7