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.

558 lines
14 KiB

  1. // This is a part of the Microsoft Foundation Classes C++ library.
  2. // Copyright (c) 1992-2001 Microsoft Corporation, All Rights Reserved
  3. // All rights reserved.
  4. //
  5. // This source code is only intended as a supplement to the
  6. // Microsoft Foundation Classes Reference and related
  7. // electronic documentation provided with the library.
  8. // See these sources for detailed information regarding the
  9. // Microsoft Foundation Classes product.
  10. #include "precomp.h"
  11. #include <snmpstd.h>
  12. #include <snmptempl.h>
  13. #include <snmpstr.h>
  14. //////////////////////////////////////////////////////////////////////////////
  15. // More sophisticated construction
  16. CString::CString(TCHAR ch, int nLength)
  17. {
  18. Init();
  19. if (nLength >= 1)
  20. {
  21. AllocBuffer(nLength);
  22. #ifdef _UNICODE
  23. for (int i = 0; i < nLength; i++)
  24. m_pchData[i] = ch;
  25. #else
  26. memset(m_pchData, ch, nLength);
  27. #endif
  28. }
  29. }
  30. CString::CString(LPCTSTR lpch, int nLength)
  31. {
  32. Init();
  33. if (nLength != 0)
  34. {
  35. AllocBuffer(nLength);
  36. memcpy(m_pchData, lpch, nLength*sizeof(TCHAR));
  37. }
  38. }
  39. //////////////////////////////////////////////////////////////////////////////
  40. // Assignment operators
  41. const CString& CString::operator=(TCHAR ch)
  42. {
  43. AssignCopy(1, &ch);
  44. return *this;
  45. }
  46. //////////////////////////////////////////////////////////////////////////////
  47. // less common string expressions
  48. CString AFXAPI operator+(const CString& string1, TCHAR ch)
  49. {
  50. CString s;
  51. s.ConcatCopy(string1.GetData()->nDataLength, string1.m_pchData, 1, &ch);
  52. return s;
  53. }
  54. CString AFXAPI operator+(TCHAR ch, const CString& string)
  55. {
  56. CString s;
  57. s.ConcatCopy(1, &ch, string.GetData()->nDataLength, string.m_pchData);
  58. return s;
  59. }
  60. //////////////////////////////////////////////////////////////////////////////
  61. // Very simple sub-string extraction
  62. CString CString::Mid(int nFirst) const
  63. {
  64. return Mid(nFirst, GetData()->nDataLength - nFirst);
  65. }
  66. CString CString::Mid(int nFirst, int nCount) const
  67. {
  68. // out-of-bounds requests return sensible things
  69. if (nFirst < 0)
  70. nFirst = 0;
  71. if (nCount < 0)
  72. nCount = 0;
  73. if (nFirst + nCount > GetData()->nDataLength)
  74. nCount = GetData()->nDataLength - nFirst;
  75. if (nFirst > GetData()->nDataLength)
  76. nCount = 0;
  77. CString dest;
  78. AllocCopy(dest, nCount, nFirst, 0);
  79. return dest;
  80. }
  81. CString CString::Right(int nCount) const
  82. {
  83. if (nCount < 0)
  84. nCount = 0;
  85. else if (nCount > GetData()->nDataLength)
  86. nCount = GetData()->nDataLength;
  87. CString dest;
  88. AllocCopy(dest, nCount, GetData()->nDataLength-nCount, 0);
  89. return dest;
  90. }
  91. CString CString::Left(int nCount) const
  92. {
  93. if (nCount < 0)
  94. nCount = 0;
  95. else if (nCount > GetData()->nDataLength)
  96. nCount = GetData()->nDataLength;
  97. CString dest;
  98. AllocCopy(dest, nCount, 0, 0);
  99. return dest;
  100. }
  101. // strspn equivalent
  102. CString CString::SpanIncluding(LPCTSTR lpszCharSet) const
  103. {
  104. return Left(_tcsspn(m_pchData, lpszCharSet));
  105. }
  106. // strcspn equivalent
  107. CString CString::SpanExcluding(LPCTSTR lpszCharSet) const
  108. {
  109. return Left(_tcscspn(m_pchData, lpszCharSet));
  110. }
  111. //////////////////////////////////////////////////////////////////////////////
  112. // Finding
  113. int CString::ReverseFind(TCHAR ch) const
  114. {
  115. // find last single character
  116. LPTSTR lpsz = _tcsrchr(m_pchData, (_TUCHAR)ch);
  117. // return -1 if not found, distance from beginning otherwise
  118. return (lpsz == NULL) ? -1 : (int)(lpsz - m_pchData);
  119. }
  120. // find a sub-string (like strstr)
  121. int CString::Find(LPCTSTR lpszSub) const
  122. {
  123. // find first matching substring
  124. LPTSTR lpsz = _tcsstr(m_pchData, lpszSub);
  125. // return -1 for not found, distance from beginning otherwise
  126. return (lpsz == NULL) ? -1 : (int)(lpsz - m_pchData);
  127. }
  128. /////////////////////////////////////////////////////////////////////////////
  129. // CString formatting
  130. #ifdef _MAC
  131. #define TCHAR_ARG int
  132. #define WCHAR_ARG unsigned
  133. #define CHAR_ARG int
  134. #else
  135. #define TCHAR_ARG TCHAR
  136. #define WCHAR_ARG WCHAR
  137. #define CHAR_ARG char
  138. #endif
  139. #if defined(_68K_) || defined(_X86_)
  140. #define DOUBLE_ARG _AFX_DOUBLE
  141. #else
  142. #define DOUBLE_ARG double
  143. #endif
  144. #define FORCE_ANSI 0x10000
  145. #define FORCE_UNICODE 0x20000
  146. void CString::FormatV(LPCTSTR lpszFormat, va_list argList)
  147. {
  148. va_list argListSave = argList;
  149. // make a guess at the maximum length of the resulting string
  150. int nMaxLen = 0;
  151. for (LPCTSTR lpsz = lpszFormat; *lpsz != '\0'; lpsz = _tcsinc(lpsz))
  152. {
  153. // handle '%' character, but watch out for '%%'
  154. if (*lpsz != '%' || *(lpsz = _tcsinc(lpsz)) == '%')
  155. {
  156. nMaxLen += _tclen(lpsz);
  157. continue;
  158. }
  159. int nItemLen = 0;
  160. // handle '%' character with format
  161. int nWidth = 0;
  162. for (; *lpsz != '\0'; lpsz = _tcsinc(lpsz))
  163. {
  164. // check for valid flags
  165. if (*lpsz == '#')
  166. nMaxLen += 2; // for '0x'
  167. else if (*lpsz == '*')
  168. nWidth = va_arg(argList, int);
  169. else if (*lpsz == '-' || *lpsz == '+' || *lpsz == '0' ||
  170. *lpsz == ' ')
  171. ;
  172. else // hit non-flag character
  173. break;
  174. }
  175. // get width and skip it
  176. if (nWidth == 0)
  177. {
  178. // width indicated by
  179. nWidth = _ttoi(lpsz);
  180. for (; *lpsz != '\0' && _istdigit(*lpsz); lpsz = _tcsinc(lpsz))
  181. ;
  182. }
  183. int nPrecision = 0;
  184. if (*lpsz == '.')
  185. {
  186. // skip past '.' separator (width.precision)
  187. lpsz = _tcsinc(lpsz);
  188. // get precision and skip it
  189. if (*lpsz == '*')
  190. {
  191. nPrecision = va_arg(argList, int);
  192. lpsz = _tcsinc(lpsz);
  193. }
  194. else
  195. {
  196. nPrecision = _ttoi(lpsz);
  197. for (; *lpsz != '\0' && _istdigit(*lpsz); lpsz = _tcsinc(lpsz))
  198. ;
  199. }
  200. }
  201. // should be on type modifier or specifier
  202. int nModifier = 0;
  203. switch (*lpsz)
  204. {
  205. // modifiers that affect size
  206. case 'h':
  207. nModifier = FORCE_ANSI;
  208. lpsz = _tcsinc(lpsz);
  209. break;
  210. case 'l':
  211. nModifier = FORCE_UNICODE;
  212. lpsz = _tcsinc(lpsz);
  213. break;
  214. // modifiers that do not affect size
  215. case 'F':
  216. case 'N':
  217. case 'L':
  218. lpsz = _tcsinc(lpsz);
  219. break;
  220. }
  221. // now should be on specifier
  222. switch (*lpsz | nModifier)
  223. {
  224. // single characters
  225. case 'c':
  226. case 'C':
  227. nItemLen = 2;
  228. va_arg(argList, TCHAR_ARG);
  229. break;
  230. case 'c'|FORCE_ANSI:
  231. case 'C'|FORCE_ANSI:
  232. nItemLen = 2;
  233. va_arg(argList, CHAR_ARG);
  234. break;
  235. case 'c'|FORCE_UNICODE:
  236. case 'C'|FORCE_UNICODE:
  237. nItemLen = 2;
  238. va_arg(argList, WCHAR_ARG);
  239. break;
  240. // strings
  241. case 's':
  242. {
  243. LPCTSTR pstrNextArg = va_arg(argList, LPCTSTR);
  244. if (pstrNextArg == NULL)
  245. nItemLen = 6; // "(null)"
  246. else
  247. {
  248. nItemLen = lstrlen(pstrNextArg);
  249. nItemLen = max(1, nItemLen);
  250. }
  251. break;
  252. }
  253. case 'S':
  254. {
  255. #ifndef _UNICODE
  256. LPWSTR pstrNextArg = va_arg(argList, LPWSTR);
  257. if (pstrNextArg == NULL)
  258. nItemLen = 6; // "(null)"
  259. else
  260. {
  261. nItemLen = wcslen(pstrNextArg);
  262. nItemLen = max(1, nItemLen);
  263. }
  264. #else
  265. LPCSTR pstrNextArg = va_arg(argList, LPCSTR);
  266. if (pstrNextArg == NULL)
  267. nItemLen = 6; // "(null)"
  268. else
  269. {
  270. nItemLen = lstrlenA(pstrNextArg);
  271. nItemLen = max(1, nItemLen);
  272. }
  273. #endif
  274. break;
  275. }
  276. case 's'|FORCE_ANSI:
  277. case 'S'|FORCE_ANSI:
  278. {
  279. LPCSTR pstrNextArg = va_arg(argList, LPCSTR);
  280. if (pstrNextArg == NULL)
  281. nItemLen = 6; // "(null)"
  282. else
  283. {
  284. nItemLen = lstrlenA(pstrNextArg);
  285. nItemLen = max(1, nItemLen);
  286. }
  287. break;
  288. }
  289. #ifndef _MAC
  290. case 's'|FORCE_UNICODE:
  291. case 'S'|FORCE_UNICODE:
  292. {
  293. LPWSTR pstrNextArg = va_arg(argList, LPWSTR);
  294. if (pstrNextArg == NULL)
  295. nItemLen = 6; // "(null)"
  296. else
  297. {
  298. nItemLen = wcslen(pstrNextArg);
  299. nItemLen = max(1, nItemLen);
  300. }
  301. break;
  302. }
  303. #endif
  304. }
  305. // adjust nItemLen for strings
  306. if (nItemLen != 0)
  307. {
  308. nItemLen = max(nItemLen, nWidth);
  309. if (nPrecision != 0)
  310. nItemLen = min(nItemLen, nPrecision);
  311. }
  312. else
  313. {
  314. switch (*lpsz)
  315. {
  316. // integers
  317. case 'd':
  318. case 'i':
  319. case 'u':
  320. case 'x':
  321. case 'X':
  322. case 'o':
  323. va_arg(argList, int);
  324. nItemLen = 32;
  325. nItemLen = max(nItemLen, nWidth+nPrecision);
  326. break;
  327. case 'e':
  328. case 'f':
  329. case 'g':
  330. case 'G':
  331. va_arg(argList, DOUBLE_ARG);
  332. nItemLen = 128;
  333. nItemLen = max(nItemLen, nWidth+nPrecision);
  334. break;
  335. case 'p':
  336. va_arg(argList, void*);
  337. nItemLen = 32;
  338. nItemLen = max(nItemLen, nWidth+nPrecision);
  339. break;
  340. // no output
  341. case 'n':
  342. va_arg(argList, int*);
  343. break;
  344. default:
  345. break ;
  346. }
  347. }
  348. // adjust nMaxLen for output nItemLen
  349. nMaxLen += nItemLen;
  350. }
  351. GetBuffer(nMaxLen);
  352. _vstprintf(m_pchData, lpszFormat, argListSave);
  353. ReleaseBuffer();
  354. va_end(argListSave);
  355. }
  356. // formatting (using wsprintf style formatting)
  357. void AFX_CDECL CString::Format(LPCTSTR lpszFormat, ...)
  358. {
  359. va_list argList;
  360. va_start(argList, lpszFormat);
  361. FormatV(lpszFormat, argList);
  362. va_end(argList);
  363. }
  364. #ifndef _MAC
  365. // formatting (using FormatMessage style formatting)
  366. void AFX_CDECL CString::FormatMessage(LPCTSTR lpszFormat, ...)
  367. {
  368. // format message into temporary buffer lpszTemp
  369. va_list argList;
  370. va_start(argList, lpszFormat);
  371. LPTSTR lpszTemp;
  372. if (::FormatMessage(FORMAT_MESSAGE_FROM_STRING|FORMAT_MESSAGE_ALLOCATE_BUFFER,
  373. lpszFormat, 0, 0, (LPTSTR)&lpszTemp, 0, &argList) == 0 ||
  374. lpszTemp == NULL)
  375. {
  376. throw Heap_Exception(Heap_Exception::HEAP_ERROR::E_ALLOCATION_ERROR) ;
  377. }
  378. // assign lpszTemp into the resulting string and free the temporary
  379. *this = lpszTemp;
  380. LocalFree(lpszTemp);
  381. va_end(argList);
  382. }
  383. #endif //!_MAC
  384. void CString::TrimRight()
  385. {
  386. CopyBeforeWrite();
  387. // find beginning of trailing spaces by starting at beginning (DBCS aware)
  388. LPTSTR lpsz = m_pchData;
  389. LPTSTR lpszLast = NULL;
  390. while (*lpsz != '\0')
  391. {
  392. if (_istspace(*lpsz))
  393. {
  394. if (lpszLast == NULL)
  395. lpszLast = lpsz;
  396. }
  397. else
  398. lpszLast = NULL;
  399. lpsz = _tcsinc(lpsz);
  400. }
  401. if (lpszLast != NULL)
  402. {
  403. // truncate at trailing space start
  404. *lpszLast = '\0';
  405. GetData()->nDataLength = (int)(lpszLast - m_pchData);
  406. }
  407. }
  408. void CString::TrimLeft()
  409. {
  410. CopyBeforeWrite();
  411. // find first non-space character
  412. LPCTSTR lpsz = m_pchData;
  413. while (_istspace(*lpsz))
  414. lpsz = _tcsinc(lpsz);
  415. // fix up data and length
  416. int nDataLength = GetData()->nDataLength - (int)(lpsz - m_pchData);
  417. memmove(m_pchData, lpsz, (nDataLength+1)*sizeof(TCHAR));
  418. GetData()->nDataLength = nDataLength;
  419. }
  420. ///////////////////////////////////////////////////////////////////////////////
  421. // CString support for template collections
  422. #if _MSC_VER >= 1100
  423. template<> void AFXAPI ConstructElements<CString> (CString* pElements, int nCount)
  424. #else
  425. void AFXAPI ConstructElements(CString* pElements, int nCount)
  426. #endif
  427. {
  428. for (; nCount--; ++pElements)
  429. memcpy(pElements, &afxEmptyString, sizeof(*pElements));
  430. }
  431. #if _MSC_VER >= 1100
  432. template<> void AFXAPI DestructElements<CString> (CString* pElements, int nCount)
  433. #else
  434. void AFXAPI DestructElements(CString* pElements, int nCount)
  435. #endif
  436. {
  437. for (; nCount--; ++pElements)
  438. pElements->~CString();
  439. }
  440. #if _MSC_VER >= 1100
  441. template<> void AFXAPI CopyElements<CString> (CString* pDest, const CString* pSrc, int nCount)
  442. #else
  443. void AFXAPI CopyElements(CString* pDest, const CString* pSrc, int nCount)
  444. #endif
  445. {
  446. for (; nCount--; ++pDest, ++pSrc)
  447. *pDest = *pSrc;
  448. }
  449. /*
  450. #ifndef OLE2ANSI
  451. #if _MSC_VER >= 1100
  452. template<> UINT AFXAPI HashKey<LPCWSTR> (LPCWSTR key)
  453. #else
  454. UINT AFXAPI HashKey(LPCWSTR key)
  455. #endif
  456. {
  457. UINT nHash = 0;
  458. while (*key)
  459. nHash = (nHash<<5) + nHash + *key++;
  460. return nHash;
  461. }
  462. #endif
  463. #if _MSC_VER >= 1100
  464. template<> UINT AFXAPI HashKey<LPCSTR> (LPCSTR key)
  465. #else
  466. UINT AFXAPI HashKey(LPCSTR key)
  467. #endif
  468. {
  469. UINT nHash = 0;
  470. while (*key)
  471. nHash = (nHash<<5) + nHash + *key++;
  472. return nHash;
  473. }
  474. */
  475. UINT AFXAPI HashKeyLPCWSTR(LPCWSTR key)
  476. {
  477. UINT nHash = 0;
  478. while (*key)
  479. nHash = (nHash<<5) + nHash + *key++;
  480. return nHash;
  481. }
  482. UINT AFXAPI HashKeyLPCSTR(LPCSTR key)
  483. {
  484. UINT nHash = 0;
  485. while (*key)
  486. nHash = (nHash<<5) + nHash + *key++;
  487. return nHash;
  488. }
  489. ///////////////////////////////////////////////////////////////////////////////