Windows2003-3790/inetcore/wininet/common/icstring.cxx
2020-09-30 16:53:55 +02:00

662 lines
12 KiB
C++
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*++
Copyright (c) 1995 Microsoft Corporation
Module Name:
icstring.cxx
Abstract:
Contains ICSTRING class methods. Split from ICSTRING.HXX (inline methods)
Contents:
ICSTRING::ICSTRING(ICSTRING&)
ICSTRING::~ICSTRING()
ICSTRING::operator=(LPSTR)
ICSTRING::operator=(ICSTRING&)
ICSTRING::operator+=(LPSTR)
ICSTRING::operator+=(char)
ICSTRING::strncat(LPVOID, DWORD)
ICSTRING::CreateStringBuffer(LPVOID, DWORD, DWORD)
ICSTRING::CreateOffsetString(DWORD, DWORD)
ICSTRING::CopyTo(LPSTR)
ICSTRING::CopyTo(LPSTR, LPSTR)
ICSTRING::CopyTo(LPSTR, DWORD)
ICSTRING::CopyTo(LPSTR, LPDWORD)
Author:
Richard L Firth (rfirth) 18-Dec-1995
Revision History:
18-Dec-1995 rfirth
Created
--*/
#include <wininetp.h>
//
// methods
//
//
//ICSTRING::ICSTRING(
// IN ICSTRING& String
// )
//
///*++
//
//Routine Description:
//
// copy constructor. We now create an entirely new string (used to be just a
// reference of the rvalue)
//
//Arguments:
//
// String - to copy
//
//Return Value:
//
// None.
//
//--*/
//
//{
// //
// // can't already have string in lvalue, & rvalue mustn't be an offset string
// //
//
// INET_ASSERT(!HaveString());
// INET_ASSERT(!String.IsOffset());
// INET_ASSERT(!String.IsError());
//
// *this = String.StringAddress();
//}
ICSTRING::~ICSTRING(
VOID
)
/*++
Routine Description:
destructor
Arguments:
None.
Return Value:
None.
--*/
{
//
// can only free the string if it is not a reference. Offset type
// implies reference
//
if (!IsReference() && (_String != NULL)) {
INET_ASSERT(!IsOffset());
(VOID)ResizeBuffer((HLOCAL)_String, 0, FALSE);
_String = NULL;
}
}
ICSTRING&
ICSTRING::operator=(
IN LPSTR String
)
/*++
Routine Description:
Copy/assigment. Copies a string to this object. If NULL, frees up the
current buffer
Arguments:
String - to be assigned
Return Value:
ICSTRING&
--*/
{
//
// if this is an offset string then there's not much to do
//
if (IsOffset()) {
Initialize();
return *this;
}
//
// string MUST NOT be a copy (we'll free the real string pointer, owned
// by another object) and SHOULD NOT be copied itself (the objects with
// copies of the string will potentially have a bad pointer)
//
INET_ASSERT((String == NULL) ? TRUE : !IsReference());
INET_ASSERT(!IsReferenced());
//
// if the pointer is NULL or the string is empty then we are freeing the
// string pointer
//
DWORD len;
if (String == NULL) {
len = 0;
} else {
len = ::strlen(String);
if (len != 0) {
INET_ASSERT(len < 0xffffffff);
++len;
}
}
//
// free or grow the buffer, depending on requirements
//
if ((len > _BufferLength) || ((len == 0) && (_String != NULL))) {
_String = (LPSTR)ResizeBuffer((HLOCAL)_String, len, FALSE);
_BufferLength = (_String != NULL) ? len : 0;
}
if (_String != NULL) {
INET_ASSERT(len != 0);
memcpy((LPVOID)_String, (LPVOID)String, len);
_StringLength = len - 1;
SetHaveString(TRUE);
SetError(FALSE);
} else {
_StringLength = 0;
SetHaveString(FALSE);
SetError(len != 0); // an error might have occurred
}
return *this;
}
ICSTRING&
ICSTRING::operator=(
IN ICSTRING& String
)
/*++
Routine Description:
Copy/assignment. Makes new copy of object (used to just make a reference)
Arguments:
String - ICSTRING object to be assigned
Return Value:
ICSTRING&
--*/
{
INET_ASSERT(!IsReferenced());
INET_ASSERT(!String.IsReferenced());
INET_ASSERT(!String.IsError());
//
// if we're copying an offset, make sure that any string we may already
// have is freed
//
if (String.IsOffset()) {
if (_String != NULL) {
ResizeBuffer(_String, 0, FALSE);
}
_String = String._String;
_StringLength = String._StringLength;
_BufferLength = String._BufferLength;
_Union.Dword = String._Union.Dword;
} else {
INET_ASSERT(!IsOffset() && !String.IsOffset());
//
// use string assignment to correctly setup this object
//
*this = String.StringAddress();
}
return *this;
}
VOID
ICSTRING::operator+=(
IN LPSTR String
)
/*++
Routine Description:
Concatenates a string to the buffer. Reallocates it if necessary. String
CANNOT be NULL
Arguments:
String - to concatenate
Return Value:
None.
--*/
{
INET_ASSERT(!IsReference());
INET_ASSERT(!IsReferenced());
INET_ASSERT(!IsOffset());
INET_ASSERT(String != NULL);
if (IsError()) {
return;
}
if (*String == '\0') {
return;
}
DWORD len = ::strlen(String);
DWORD newlen = _StringLength + len + 1;
INET_ASSERT ((newlen > _StringLength) && (newlen > len));
if (_BufferLength < newlen) {
_String = (LPSTR)ResizeBuffer((HLOCAL)_String, newlen, FALSE);
INET_ASSERT((_String == NULL) ? (newlen == 0) : TRUE);
_BufferLength = newlen;
}
if (_String != NULL) {
memcpy((LPVOID)((LPBYTE)_String + _StringLength),
(LPVOID)String,
len + 1
);
_StringLength += len;
} else {
_StringLength = 0;
_BufferLength = 0;
SetError(TRUE);
}
}
VOID
ICSTRING::operator+=(
IN char Ch
)
/*++
Routine Description:
Concatenates a character to the buffer. Reallocates it if necessary. Ch
CAN be '\0'
Arguments:
Ch - to concatenate
Return Value:
None.
--*/
{
INET_ASSERT(!IsReference());
INET_ASSERT(!IsReferenced());
INET_ASSERT(!IsOffset());
if (IsError()) {
return;
}
DWORD newlen = _StringLength + 2;
INET_ASSERT (newlen > _StringLength);
if (_BufferLength < newlen) {
_String = (LPSTR)ResizeBuffer((HLOCAL)_String, newlen, FALSE);
INET_ASSERT((_String == NULL) ? (newlen == 0) : TRUE);
_BufferLength = newlen;
}
if (_String != NULL) {
_String[_StringLength] = Ch;
++_StringLength;
_String[_StringLength] = '\0';
} else {
_StringLength = 0;
_BufferLength = 0;
SetError(TRUE);
}
}
VOID
ICSTRING::Strncat(
IN LPVOID Pointer,
IN DWORD Length
)
/*++
Routine Description:
Copies Length characters from Pointer to the end of _String
Arguments:
Pointer - place to copy from
Length - number of characters to copy
Return Value:
None.
--*/
{
if (IsError()) {
return;
}
INET_ASSERT(Pointer != NULL);
INET_ASSERT(Length != 0);
INET_ASSERT(_String != NULL);
INET_ASSERT(!IsReference());
INET_ASSERT(!IsReferenced());
DWORD newLength;
newLength = _StringLength + Length + 1;
INET_ASSERT ((newLength > _StringLength) && (newLength > Length));
if (_BufferLength < newLength) {
_String = (LPSTR)ResizeBuffer((HLOCAL)_String, newLength, FALSE);
_BufferLength = newLength;
}
if (_String != NULL) {
memcpy((LPVOID)&_String[_StringLength], Pointer, Length);
_StringLength += Length;
INET_ASSERT(_StringLength < _BufferLength);
_String[_StringLength] = '\0';
} else {
_StringLength = 0;
_BufferLength = 0;
SetError(TRUE);
}
}
VOID
ICSTRING::CreateStringBuffer(
IN LPVOID Pointer,
IN DWORD StringLength,
IN DWORD BufferLength
)
/*++
Routine Description:
In order to avoid reallocations, if we know the size of the buffer we
want for several strcat()'s, e.g., we can allocate it once, copy the
initial string here, then perform multiple concatenate operations (+=)
Arguments:
Pointer - place to start copying from
StringLength - length of string
BufferLength - length of buffer required
Return Value:
None.
--*/
{
INET_ASSERT(Pointer != NULL);
INET_ASSERT(BufferLength > StringLength);
INET_ASSERT(BufferLength != 0);
//
// if we currently have an offset string then initialize to a non-offset
//
if (IsOffset()) {
Initialize();
}
_String = (LPSTR)ResizeBuffer(_String, BufferLength, FALSE);
if (_String != NULL) {
_StringLength = StringLength;
_BufferLength = BufferLength;
memcpy((LPVOID)_String, Pointer, _StringLength);
_String[_StringLength] = '\0';
SetHaveString(TRUE);
SetReference(FALSE);
SetReferenced(FALSE);
SetOffset(FALSE);
SetError(FALSE);
} else {
SetError(TRUE);
}
}
VOID
ICSTRING::CreateOffsetString(
IN DWORD Offset,
IN DWORD Length
)
/*++
Routine Description:
Create a reference ICSTRING that is an offset within another buffer
Arguments:
Offset - offset into buffer
Length - of string
Return Value:
None.
--*/
{
_String = (LPSTR)(DWORD_PTR)Offset;
_StringLength = Length;
_BufferLength = Length;
ZapFlags();
SetHaveString(TRUE); // ICSTRING initialized with non-NULL
SetReference(TRUE); // reference to another string buffer
SetOffset(TRUE); // offset from base
SetError(FALSE);
}
VOID
ICSTRING::CopyTo(
IN LPSTR Buffer
)
/*++
Routine Description:
Copies source _String to destination Buffer
Arguments:
Buffer - place to copy to
Return Value:
None.
--*/
{
INET_ASSERT(Buffer != NULL);
INET_ASSERT(!IsOffset());
memcpy((LPVOID)Buffer, (LPVOID)_String, _StringLength);
Buffer[_StringLength] = '\0';
}
VOID
ICSTRING::CopyTo(
IN LPSTR Base,
IN LPSTR Buffer
)
/*++
Routine Description:
Copies a based (offset) string from source Base + _String to destination
Buffer
Arguments:
Base - value for base
Buffer - place to write string
Return Value:
None.
--*/
{
INET_ASSERT(Buffer != NULL);
//INET_ASSERT(IsOffset() ? (Base != NULL) : (Base == NULL));
memcpy((LPVOID)Buffer,
IsOffset() ? (Base + (DWORD_PTR)_String) : _String,
_StringLength
);
Buffer[_StringLength] = '\0';
}
VOID
ICSTRING::CopyTo(
IN LPSTR Buffer,
IN DWORD Length
)
/*++
Routine Description:
Copies at most Length characters from source _String to destination
Buffer
Arguments:
Buffer - place to write string
Length - number of characters to copy
Return Value:
None.
--*/
{
INET_ASSERT(Buffer != NULL);
INET_ASSERT(!IsOffset());
DWORD length = min(Length - 1, _StringLength);
memcpy((LPVOID)Buffer, (LPVOID)_String, length);
Buffer[length] = '\0';
}
VOID
ICSTRING::CopyTo(
IN LPSTR Buffer,
IN OUT LPDWORD Length
)
/*++
Routine Description:
Copies at most *Length characters from source _String to destination
Buffer. Updates *Length to be number of characters copied, not including
terminating NUL
Arguments:
Buffer - place to write string
Length - IN: length of buffer
OUT: number of characters copied
Return Value:
None.
--*/
{
INET_ASSERT(Buffer != NULL);
INET_ASSERT(!IsOffset());
DWORD length = min(*Length - 1, _StringLength);
memcpy((LPVOID)Buffer, (LPVOID)_String, length);
Buffer[length] = '\0';
*Length = length;
}