|
|
/*++
Copyright (c) 1995 Microsoft Corporation
Module Name:
icstring.hxx
Abstract:
Contains ICSTRING class implementation. Lightweight version of familiar counted string class, used mainly to avoid calling strxxx functions.
Private to WININET project.
The ICSTRING class has the notion of copies, or references to a string. When an ICSTRING is created, we allocate a buffer for the string. Subsequent assignment (=) and augmentation (+=) operations can be made against this buffer, and possibly reallocate it, changing its address.
As soon as an ICSTRING is copied, we disallow any modifications to the buffer pointer, since the copied object will get the old pointer value.
ICSTRINGs can also be used to point to a substring in a larger buffer. In such a case, Reference will be TRUE. If the buffer pointed at is one that may be reallocated and potentially moved, then we maintain offsets into the buffer, and have to be supplied with the current address of the buffer when generating the pointer. Obviously, buffers are not expected to move while we are using the generated pointer into it.
If a string is an offset, then Offset will be TRUE.
This scheme is workable for WININET because we are typically creating a string in one place (e.g. INTERNET_CONNECT_OBJECT_HANDLE) and because of the way the handle objects are derived, we make copies of the string objects (e.g. in HTTP_REQUEST_HANDLE_OBJECT)
Contents: ICSTRING
Author:
Richard L Firth (rfirth) 18-Dec-1995
Revision History:
18-Dec-1995 rfirth Created
05-Oct-1996 rajeevd Added a very simple string class: XSTRING.
--*/
//
// class implementation of XSTRING
//
class XSTRING {
LPSTR _lpsz;
public:
XSTRING() { _lpsz = NULL; }
~XSTRING() { Free(); }
void Free (void) { if (_lpsz) { FREE_MEMORY (_lpsz); } _lpsz = NULL; }
LPSTR GetPtr(void) { return _lpsz; }
LPSTR ClearPtr (void) {
// Relinquish ownership of the pointer.
LPSTR lpszRet = _lpsz; _lpsz = NULL; return lpszRet; }
void SetPtr (LPSTR* lplpszIn) {
// Take ownership of the pointer.
INET_ASSERT((lplpszIn != NULL) && (*lplpszIn != '\0'));
if (_lpsz) FREE_MEMORY(_lpsz); _lpsz = *lplpszIn; *lplpszIn = NULL; }
BOOL SetData(LPSTR lpszIn) {
// Make a copy of the data passed in.
INET_ASSERT(lpszIn != NULL);
lpszIn = NewString(lpszIn); if (!lpszIn) return FALSE; if (_lpsz) FREE_MEMORY(_lpsz); _lpsz = lpszIn; return TRUE; }
};
//
// class implementation
//
class ICSTRING {
protected:
//
// _String - pointer to string buffer. This is allocated using ResizeBuffer()
// which makes assigning new or NULL strings easy
//
LPSTR _String;
//
// _StringLength - the strlen() of _String
//
DWORD _StringLength;
//
// _BufferLength - the number of bytes in the _String buffer, Initially,
// this will be 1 more than _StringLength
//
DWORD _BufferLength;
//
// _Union - access Flags also as a DWORD for initialization
//
union {
struct {
//
// Flags - collection of boolean flags
//
//
// HaveString - TRUE when a value has been assigned to this ICSTRING
//
BOOL HaveString : 1;
//
// Reference - if TRUE then this ICSTRING object simply references
// another - that is, its a copy, and _String shouldn't be freed in
// the destructor
//
BOOL Reference : 1;
//
// Referenced - if TRUE then this ICSTRING object has been copied.
// If the string pointer is changed then the copies will be invalid
//
BOOL Referenced : 1;
//
// Offset - TRUE if the string is an offset into a moveable buffer
//
BOOL Offset : 1;
//
// Error - TRUE if the caller should call GetLastError() to find out
// why the operation failed
//
BOOL Error : 1;
} Flags;
//
// Dword - used to zap the entire contents of Flags to 0
//
DWORD Dword;
//
// There are 32 bits in this Union, and only 5 are used.
// its a really shame to waste it, so lets make the
// other parts of the DWORD availble for use by others.
//
struct {
BYTE FlagsByte; BYTE ExtraByte1; BYTE ExtraByte2; BYTE ExtraByte3; } Bytes;
} _Union;
//
// Initialize - initializes the ICSTRING to NULLs
//
VOID Initialize(VOID) { _String = NULL; _StringLength = 0; _BufferLength = 0; ZapFlags(); }
public:
//
// constructors
//
ICSTRING() { Initialize(); }
ICSTRING(LPSTR String) { Initialize(); *this = String; }
//
// copy constructor
//
ICSTRING(ICSTRING& String);
//
// destructor
//
~ICSTRING();
//
// operators
//
ICSTRING& operator=(LPSTR String); ICSTRING& operator=(ICSTRING& String); VOID operator+=(LPSTR String); VOID operator+=(char Ch);
//
// member functions
//
VOID Clear(VOID) { Initialize(); }
//
// flags functions
//
VOID ZapFlags(VOID) { _Union.Dword = 0; }
VOID SetHaveString(BOOL Value) { _Union.Flags.HaveString = Value; }
BOOL HaveString(VOID) const { return _Union.Flags.HaveString; }
VOID SetReference(BOOL Value) { _Union.Flags.Reference = Value; }
BOOL IsReference(VOID) const { return _Union.Flags.Reference; }
VOID SetReferenced(BOOL Value) { _Union.Flags.Referenced = Value; }
BOOL IsReferenced(VOID) const { return _Union.Flags.Referenced; }
VOID SetOffset(BOOL Value) { _Union.Flags.Offset = Value; }
BOOL IsOffset(VOID) const { return _Union.Flags.Offset; }
VOID SetError(BOOL Value) { _Union.Flags.Error = Value; }
BOOL IsError(VOID) { return _Union.Flags.Error; }
//
// LPSTR StringAddress(VOID)
//
// returns the string pointer
//
LPSTR StringAddress(VOID) const {
INET_ASSERT(!IsOffset());
return _String; }
//
// LPSTR StringAddress(LPSTR)
//
// returns the address of the string. The string may or may not be based
//
LPSTR StringAddress(LPSTR Base) const {
//INET_ASSERT(IsOffset() ? (Base != NULL) : (Base == NULL));
//
// assume the caller passes in Base == NULL for non-based strings
//
if (IsOffset()) { return Base + (DWORD_PTR)_String; } else { return _String; } }
//
// int StringLength(VOID)
//
// returns strlen() of the string
//
DWORD StringLength(VOID) { return _StringLength; }
void SetLength (DWORD NewLength) { INET_ASSERT (NewLength <= _StringLength); _StringLength = NewLength; }
VOID Strncat(LPVOID Pointer, DWORD Length); VOID CreateStringBuffer(LPVOID Pointer, DWORD StringLength, DWORD BufferLength); VOID CreateOffsetString(DWORD Offset, DWORD Length); VOID CopyTo(LPSTR Buffer); VOID CopyTo(LPSTR Base, LPSTR Buffer); VOID CopyTo(LPSTR Buffer, DWORD Length); VOID CopyTo(LPSTR Buffer, LPDWORD Length);
//
// VOID MakeCopy(LPSTR, DWORD)
//
// Given a pointer to a string and its length, create an ICSTRING copy of it
//
VOID MakeCopy(LPSTR String, DWORD Length) { CreateStringBuffer((LPVOID)String, Length, Length + 1); }
//
// VOID ResizeString(DWORD dwByteSizeToAdd) - allows us to strncat more efficently.
//
VOID ResizeString(DWORD dwByteSizeToAdd) {
INET_ASSERT(dwByteSizeToAdd > 0); INET_ASSERT(_String != NULL); INET_ASSERT(!IsReference()); INET_ASSERT(!IsReferenced());
DWORD newLength;
newLength = _StringLength + dwByteSizeToAdd + 1;
INET_ASSERT ((newLength > _StringLength) && (newLength > dwByteSizeToAdd));
if (_BufferLength < newLength) { _String = (LPSTR)ResizeBuffer((HLOCAL)_String, newLength, FALSE); _BufferLength = newLength; } }
//
// VOID MakeLowerCase(VOID)
//
// Convert the string to all low-case characters
//
VOID MakeLowerCase(VOID) {
INET_ASSERT(_String != NULL);
_strlwr(_String); }
//
// string comparison methods
//
//
// DWORD Strnicmp(LPSTR, LPSTR, DWORD)
//
// perform strnicmp on string that may or may not be based
//
DWORD Strnicmp(LPSTR Base, LPCSTR String, DWORD Length) {
INET_ASSERT(String != NULL); INET_ASSERT(HaveString()); //INET_ASSERT(IsOffset() ? (Base != NULL) : (Base == NULL));
//
// make sure the base is NULL if the string really isn't based
//
if (!IsOffset()) { Base = NULL; } return (Length <= _StringLength) ? _strnicmp(Base + (DWORD_PTR)_String, String, Length) : -1; }
//
// DWORD Strnicmp(LPSTR, DWORD)
//
// perform strnicmp() on unbased string. Results:
//
// -1 _StringLength < Length OR _String < String
// 0 _StringLength == Length AND _String == String
// 1 _StringLength > Length OR _String > String
//
DWORD Strnicmp(LPSTR String, DWORD Length) {
//
// only compare the strings if the lengths match
//
return (Length == _StringLength) ? ::_strnicmp(_String, String, Length) : (_StringLength - Length); }
//
// DWORD Stricmp(LPSTR)
//
// perform stricmp on unbased string
//
DWORD Stricmp(LPSTR String) {
INET_ASSERT(String != NULL); INET_ASSERT(HaveString()); INET_ASSERT(!IsOffset());
//
// we assume that the caller supplies a NULL base if the string really
// isn't based
//
DWORD slen = lstrlen(String);
return (slen == _StringLength) ? ::lstrcmpi(_String, String) : (_StringLength - slen); }
//
// DWORD Strcmp(LPSTR)
//
// perform strcmp on unbased string. Returns only match or not-match
//
BOOL Strcmp(LPSTR String) {
INET_ASSERT(String != NULL); INET_ASSERT(HaveString()); INET_ASSERT(!IsOffset());
//
// BUGBUG - ::lstrcmp() treats www.foo-bar.com and www.foobar.com as
// equivalent!
//
DWORD slen = lstrlen(String);
return (slen == _StringLength) ? (memcmp(_String, String, _StringLength) == 0) ? TRUE : FALSE : FALSE; } };
|