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.

525 lines
12 KiB

  1. /*++
  2. Copyright (c) 1995 Microsoft Corporation
  3. Module Name:
  4. icstring.hxx
  5. Abstract:
  6. Contains ICSTRING class implementation. Lightweight version of familiar
  7. counted string class, used mainly to avoid calling strxxx functions.
  8. Private to WININET project.
  9. The ICSTRING class has the notion of copies, or references to a string.
  10. When an ICSTRING is created, we allocate a buffer for the string. Subsequent
  11. assignment (=) and augmentation (+=) operations can be made against this
  12. buffer, and possibly reallocate it, changing its address.
  13. As soon as an ICSTRING is copied, we disallow any modifications to the
  14. buffer pointer, since the copied object will get the old pointer value.
  15. ICSTRINGs can also be used to point to a substring in a larger buffer. In
  16. such a case, Reference will be TRUE. If the buffer pointed at is one that
  17. may be reallocated and potentially moved, then we maintain offsets into the
  18. buffer, and have to be supplied with the current address of the buffer when
  19. generating the pointer. Obviously, buffers are not expected to move while
  20. we are using the generated pointer into it.
  21. If a string is an offset, then Offset will be TRUE.
  22. This scheme is workable for WININET because we are typically creating a
  23. string in one place (e.g. INTERNET_CONNECT_OBJECT_HANDLE) and because of
  24. the way the handle objects are derived, we make copies of the string objects
  25. (e.g. in HTTP_REQUEST_HANDLE_OBJECT)
  26. Contents:
  27. ICSTRING
  28. Author:
  29. Richard L Firth (rfirth) 18-Dec-1995
  30. Revision History:
  31. 18-Dec-1995 rfirth
  32. Created
  33. 05-Oct-1996 rajeevd
  34. Added a very simple string class: XSTRING.
  35. --*/
  36. //
  37. // class implementation of XSTRING
  38. //
  39. class XSTRING {
  40. LPSTR _lpsz;
  41. public:
  42. XSTRING() {
  43. _lpsz = NULL;
  44. }
  45. ~XSTRING() {
  46. Free();
  47. }
  48. void Free (void) {
  49. if (_lpsz) {
  50. FREE_MEMORY (_lpsz);
  51. }
  52. _lpsz = NULL;
  53. }
  54. LPSTR GetPtr(void) {
  55. return _lpsz;
  56. }
  57. LPSTR ClearPtr (void) {
  58. // Relinquish ownership of the pointer.
  59. LPSTR lpszRet = _lpsz;
  60. _lpsz = NULL;
  61. return lpszRet;
  62. }
  63. void SetPtr (LPSTR* lplpszIn) {
  64. // Take ownership of the pointer.
  65. INET_ASSERT((lplpszIn != NULL) && (*lplpszIn != '\0'));
  66. if (_lpsz)
  67. FREE_MEMORY(_lpsz);
  68. _lpsz = *lplpszIn;
  69. *lplpszIn = NULL;
  70. }
  71. BOOL SetData(LPSTR lpszIn) {
  72. // Make a copy of the data passed in.
  73. INET_ASSERT(lpszIn != NULL);
  74. lpszIn = NewString(lpszIn);
  75. if (!lpszIn)
  76. return FALSE;
  77. if (_lpsz)
  78. FREE_MEMORY(_lpsz);
  79. _lpsz = lpszIn;
  80. return TRUE;
  81. }
  82. };
  83. //
  84. // class implementation
  85. //
  86. class ICSTRING {
  87. protected:
  88. //
  89. // _String - pointer to string buffer. This is allocated using ResizeBuffer()
  90. // which makes assigning new or NULL strings easy
  91. //
  92. LPSTR _String;
  93. //
  94. // _StringLength - the strlen() of _String
  95. //
  96. DWORD _StringLength;
  97. //
  98. // _BufferLength - the number of bytes in the _String buffer, Initially,
  99. // this will be 1 more than _StringLength
  100. //
  101. DWORD _BufferLength;
  102. //
  103. // _Union - access Flags also as a DWORD for initialization
  104. //
  105. union {
  106. struct {
  107. //
  108. // Flags - collection of boolean flags
  109. //
  110. //
  111. // HaveString - TRUE when a value has been assigned to this ICSTRING
  112. //
  113. BOOL HaveString : 1;
  114. //
  115. // Reference - if TRUE then this ICSTRING object simply references
  116. // another - that is, its a copy, and _String shouldn't be freed in
  117. // the destructor
  118. //
  119. BOOL Reference : 1;
  120. //
  121. // Referenced - if TRUE then this ICSTRING object has been copied.
  122. // If the string pointer is changed then the copies will be invalid
  123. //
  124. BOOL Referenced : 1;
  125. //
  126. // Offset - TRUE if the string is an offset into a moveable buffer
  127. //
  128. BOOL Offset : 1;
  129. //
  130. // Error - TRUE if the caller should call GetLastError() to find out
  131. // why the operation failed
  132. //
  133. BOOL Error : 1;
  134. } Flags;
  135. //
  136. // Dword - used to zap the entire contents of Flags to 0
  137. //
  138. DWORD Dword;
  139. //
  140. // There are 32 bits in this Union, and only 5 are used.
  141. // its a really shame to waste it, so lets make the
  142. // other parts of the DWORD availble for use by others.
  143. //
  144. struct {
  145. BYTE FlagsByte;
  146. BYTE ExtraByte1;
  147. BYTE ExtraByte2;
  148. BYTE ExtraByte3;
  149. } Bytes;
  150. } _Union;
  151. //
  152. // Initialize - initializes the ICSTRING to NULLs
  153. //
  154. VOID Initialize(VOID) {
  155. _String = NULL;
  156. _StringLength = 0;
  157. _BufferLength = 0;
  158. ZapFlags();
  159. }
  160. public:
  161. //
  162. // constructors
  163. //
  164. ICSTRING() {
  165. Initialize();
  166. }
  167. ICSTRING(LPSTR String) {
  168. Initialize();
  169. *this = String;
  170. }
  171. //
  172. // copy constructor
  173. //
  174. ICSTRING(ICSTRING& String);
  175. //
  176. // destructor
  177. //
  178. ~ICSTRING();
  179. //
  180. // operators
  181. //
  182. ICSTRING& operator=(LPSTR String);
  183. ICSTRING& operator=(ICSTRING& String);
  184. VOID operator+=(LPSTR String);
  185. VOID operator+=(char Ch);
  186. //
  187. // member functions
  188. //
  189. VOID Clear(VOID) {
  190. Initialize();
  191. }
  192. //
  193. // flags functions
  194. //
  195. VOID ZapFlags(VOID) {
  196. _Union.Dword = 0;
  197. }
  198. VOID SetHaveString(BOOL Value) {
  199. _Union.Flags.HaveString = Value;
  200. }
  201. BOOL HaveString(VOID) const {
  202. return _Union.Flags.HaveString;
  203. }
  204. VOID SetReference(BOOL Value) {
  205. _Union.Flags.Reference = Value;
  206. }
  207. BOOL IsReference(VOID) const {
  208. return _Union.Flags.Reference;
  209. }
  210. VOID SetReferenced(BOOL Value) {
  211. _Union.Flags.Referenced = Value;
  212. }
  213. BOOL IsReferenced(VOID) const {
  214. return _Union.Flags.Referenced;
  215. }
  216. VOID SetOffset(BOOL Value) {
  217. _Union.Flags.Offset = Value;
  218. }
  219. BOOL IsOffset(VOID) const {
  220. return _Union.Flags.Offset;
  221. }
  222. VOID SetError(BOOL Value) {
  223. _Union.Flags.Error = Value;
  224. }
  225. BOOL IsError(VOID) {
  226. return _Union.Flags.Error;
  227. }
  228. //
  229. // LPSTR StringAddress(VOID)
  230. //
  231. // returns the string pointer
  232. //
  233. LPSTR StringAddress(VOID) const {
  234. INET_ASSERT(!IsOffset());
  235. return _String;
  236. }
  237. //
  238. // LPSTR StringAddress(LPSTR)
  239. //
  240. // returns the address of the string. The string may or may not be based
  241. //
  242. LPSTR StringAddress(LPSTR Base) const {
  243. //INET_ASSERT(IsOffset() ? (Base != NULL) : (Base == NULL));
  244. //
  245. // assume the caller passes in Base == NULL for non-based strings
  246. //
  247. if (IsOffset()) {
  248. return Base + (DWORD_PTR)_String;
  249. } else {
  250. return _String;
  251. }
  252. }
  253. //
  254. // int StringLength(VOID)
  255. //
  256. // returns strlen() of the string
  257. //
  258. DWORD StringLength(VOID) {
  259. return _StringLength;
  260. }
  261. void SetLength (DWORD NewLength) {
  262. INET_ASSERT (NewLength <= _StringLength);
  263. _StringLength = NewLength;
  264. }
  265. VOID Strncat(LPVOID Pointer, DWORD Length);
  266. VOID CreateStringBuffer(LPVOID Pointer, DWORD StringLength, DWORD BufferLength);
  267. VOID CreateOffsetString(DWORD Offset, DWORD Length);
  268. VOID CopyTo(LPSTR Buffer);
  269. VOID CopyTo(LPSTR Base, LPSTR Buffer);
  270. VOID CopyTo(LPSTR Buffer, DWORD Length);
  271. VOID CopyTo(LPSTR Buffer, LPDWORD Length);
  272. //
  273. // VOID MakeCopy(LPSTR, DWORD)
  274. //
  275. // Given a pointer to a string and its length, create an ICSTRING copy of it
  276. //
  277. VOID MakeCopy(LPSTR String, DWORD Length) {
  278. CreateStringBuffer((LPVOID)String, Length, Length + 1);
  279. }
  280. //
  281. // VOID ResizeString(DWORD dwByteSizeToAdd) - allows us to strncat more efficently.
  282. //
  283. VOID ResizeString(DWORD dwByteSizeToAdd) {
  284. INET_ASSERT(dwByteSizeToAdd > 0);
  285. INET_ASSERT(_String != NULL);
  286. INET_ASSERT(!IsReference());
  287. INET_ASSERT(!IsReferenced());
  288. DWORD newLength;
  289. newLength = _StringLength + dwByteSizeToAdd + 1;
  290. INET_ASSERT ((newLength > _StringLength) && (newLength > dwByteSizeToAdd));
  291. if (_BufferLength < newLength) {
  292. _String = (LPSTR)ResizeBuffer((HLOCAL)_String, newLength, FALSE);
  293. _BufferLength = newLength;
  294. }
  295. }
  296. //
  297. // VOID MakeLowerCase(VOID)
  298. //
  299. // Convert the string to all low-case characters
  300. //
  301. VOID MakeLowerCase(VOID) {
  302. INET_ASSERT(_String != NULL);
  303. _strlwr(_String);
  304. }
  305. //
  306. // string comparison methods
  307. //
  308. //
  309. // DWORD Strnicmp(LPSTR, LPSTR, DWORD)
  310. //
  311. // perform strnicmp on string that may or may not be based
  312. //
  313. DWORD Strnicmp(LPSTR Base, LPCSTR String, DWORD Length) {
  314. INET_ASSERT(String != NULL);
  315. INET_ASSERT(HaveString());
  316. //INET_ASSERT(IsOffset() ? (Base != NULL) : (Base == NULL));
  317. //
  318. // make sure the base is NULL if the string really isn't based
  319. //
  320. if (!IsOffset()) {
  321. Base = NULL;
  322. }
  323. return (Length <= _StringLength)
  324. ? _strnicmp(Base + (DWORD_PTR)_String, String, Length)
  325. : -1;
  326. }
  327. //
  328. // DWORD Strnicmp(LPSTR, DWORD)
  329. //
  330. // perform strnicmp() on unbased string. Results:
  331. //
  332. // -1 _StringLength < Length OR _String < String
  333. // 0 _StringLength == Length AND _String == String
  334. // 1 _StringLength > Length OR _String > String
  335. //
  336. DWORD Strnicmp(LPSTR String, DWORD Length) {
  337. //
  338. // only compare the strings if the lengths match
  339. //
  340. return (Length == _StringLength)
  341. ? ::_strnicmp(_String, String, Length)
  342. : (_StringLength - Length);
  343. }
  344. //
  345. // DWORD Stricmp(LPSTR)
  346. //
  347. // perform stricmp on unbased string
  348. //
  349. DWORD Stricmp(LPSTR String) {
  350. INET_ASSERT(String != NULL);
  351. INET_ASSERT(HaveString());
  352. INET_ASSERT(!IsOffset());
  353. //
  354. // we assume that the caller supplies a NULL base if the string really
  355. // isn't based
  356. //
  357. DWORD slen = lstrlen(String);
  358. return (slen == _StringLength)
  359. ? ::lstrcmpi(_String, String)
  360. : (_StringLength - slen);
  361. }
  362. //
  363. // DWORD Strcmp(LPSTR)
  364. //
  365. // perform strcmp on unbased string. Returns only match or not-match
  366. //
  367. BOOL Strcmp(LPSTR String) {
  368. INET_ASSERT(String != NULL);
  369. INET_ASSERT(HaveString());
  370. INET_ASSERT(!IsOffset());
  371. //
  372. // BUGBUG - ::lstrcmp() treats www.foo-bar.com and www.foobar.com as
  373. // equivalent!
  374. //
  375. DWORD slen = lstrlen(String);
  376. return (slen == _StringLength)
  377. ? (memcmp(_String, String, _StringLength) == 0)
  378. ? TRUE
  379. : FALSE
  380. : FALSE;
  381. }
  382. };