333 lines
7.2 KiB
C++
333 lines
7.2 KiB
C++
/*
|
|
* This is a part of the BugTrap package.
|
|
* Copyright (c) 2005-2009 IntelleSoft.
|
|
* All rights reserved.
|
|
*
|
|
* Description: String (memory) stream class.
|
|
* Author: Maksim Pyatkovskiy.
|
|
*
|
|
* This source code is only intended as a supplement to the
|
|
* BugTrap package reference and related electronic documentation
|
|
* provided with the product. See these sources for detailed
|
|
* information regarding the BugTrap package.
|
|
*/
|
|
|
|
#include "StdAfx.h"
|
|
#include "StrStream.h"
|
|
#include "StrHolder.h"
|
|
#include "BugTrapUtils.h"
|
|
|
|
#ifdef _DEBUG
|
|
#define new DEBUG_NEW
|
|
#endif
|
|
|
|
void CStrStream::InitBuffer(void)
|
|
{
|
|
m_pszData = NULL;
|
|
m_nSize = m_nLength = 0;
|
|
}
|
|
|
|
/**
|
|
* @param nSize - initial buffer size.
|
|
*/
|
|
void CStrStream::InitBuffer(size_t nSize)
|
|
{
|
|
if (nSize)
|
|
{
|
|
m_nLength = 0;
|
|
m_pszData = new TCHAR[nSize];
|
|
if (m_pszData)
|
|
{
|
|
*m_pszData = _T('\0');
|
|
m_nSize = nSize;
|
|
}
|
|
else
|
|
{
|
|
m_nSize = 0;
|
|
RaiseException(STATUS_NO_MEMORY, 0, 0, NULL);
|
|
}
|
|
}
|
|
else
|
|
InitBuffer();
|
|
}
|
|
|
|
/**
|
|
* @param nSize - requested buffer size.
|
|
* @param bAdaptiveGrowth - true for adaptive growth.
|
|
*/
|
|
void CStrStream::EnsureSize(size_t nSize, bool bAdaptiveGrowth)
|
|
{
|
|
if (m_nSize < nSize)
|
|
{
|
|
if (bAdaptiveGrowth)
|
|
nSize *= 2;
|
|
PTSTR pszData = new TCHAR[nSize];
|
|
if (! pszData)
|
|
RaiseException(STATUS_NO_MEMORY, 0, 0, NULL);
|
|
if (m_pszData)
|
|
{
|
|
_tcscpy_s(pszData, nSize, m_pszData);
|
|
delete[] m_pszData;
|
|
}
|
|
m_pszData = pszData;
|
|
m_nSize = nSize;
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
* @param pszStrData - data source.
|
|
* @param nLength - string length.
|
|
*/
|
|
void CStrStream::InitData(PCTSTR pszStrData, size_t nLength)
|
|
{
|
|
if (pszStrData && *pszStrData)
|
|
{
|
|
size_t nSize = nLength + 1;
|
|
InitBuffer(nSize);
|
|
_tcsncpy_s(m_pszData, nSize, pszStrData, nLength);
|
|
m_nLength = nLength;
|
|
}
|
|
else
|
|
InitBuffer();
|
|
}
|
|
|
|
/**
|
|
* @param pszStrData - data source.
|
|
* @param nLength - string length.
|
|
*/
|
|
void CStrStream::CopyData(PCTSTR pszStrData, size_t nLength)
|
|
{
|
|
if (m_pszData != pszStrData)
|
|
{
|
|
if (pszStrData && *pszStrData)
|
|
{
|
|
size_t nSize = nLength + 1;
|
|
EnsureSize(nSize, false);
|
|
_tcsncpy_s(m_pszData, nSize, pszStrData, nLength);
|
|
m_nLength = nLength;
|
|
}
|
|
else
|
|
Reset();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @param pszStrData - data source.
|
|
* @param nLength - string length.
|
|
*/
|
|
void CStrStream::AppendData(PCTSTR pszStrData, size_t nLength)
|
|
{
|
|
if (pszStrData && *pszStrData)
|
|
{
|
|
size_t nNewLength = m_nLength + nLength;
|
|
EnsureSize(nNewLength + 1, true);
|
|
_tcsncpy_s(m_pszData + m_nLength, nLength + 1, pszStrData, nLength);
|
|
m_nLength = nNewLength;
|
|
}
|
|
}
|
|
|
|
#ifdef _UNICODE
|
|
|
|
/**
|
|
* @param pszStrData - data source.
|
|
*/
|
|
void CStrStream::InitData(PCSTR pszStrData)
|
|
{
|
|
if (pszStrData && *pszStrData)
|
|
{
|
|
int nSize = MultiByteToWideChar(CP_ACP, 0, pszStrData, -1, NULL, 0);
|
|
_ASSERTE(nSize > 0);
|
|
InitBuffer(nSize);
|
|
MultiByteToWideChar(CP_ACP, 0, pszStrData, -1, m_pszData, nSize);
|
|
m_nLength = nSize - 1;
|
|
}
|
|
else
|
|
InitBuffer();
|
|
}
|
|
|
|
/**
|
|
* @param pszStrData - data source.
|
|
*/
|
|
void CStrStream::CopyData(PCSTR pszStrData)
|
|
{
|
|
if (pszStrData && *pszStrData)
|
|
{
|
|
int nSize = MultiByteToWideChar(CP_ACP, 0, pszStrData, -1, NULL, 0);
|
|
_ASSERTE(nSize > 0);
|
|
EnsureSize(nSize, false);
|
|
MultiByteToWideChar(CP_ACP, 0, pszStrData, -1, m_pszData, nSize);
|
|
m_nLength = nSize - 1;
|
|
}
|
|
else
|
|
Reset();
|
|
}
|
|
|
|
/**
|
|
* @param pszStrData - data source.
|
|
*/
|
|
void CStrStream::AppendData(PCSTR pszStrData)
|
|
{
|
|
if (pszStrData && *pszStrData)
|
|
{
|
|
int nSize = MultiByteToWideChar(CP_ACP, 0, pszStrData, -1, NULL, 0);
|
|
_ASSERTE(nSize > 0);
|
|
size_t nNewSize = m_nLength + nSize;
|
|
EnsureSize(nNewSize, true);
|
|
MultiByteToWideChar(CP_ACP, 0, pszStrData, -1, m_pszData + m_nLength, nSize);
|
|
m_nLength = nNewSize - 1;
|
|
}
|
|
}
|
|
|
|
#else
|
|
|
|
/**
|
|
* @param pszStrData - data source.
|
|
*/
|
|
void CStrStream::InitData(PCWSTR pszStrData)
|
|
{
|
|
if (pszStrData && *pszStrData)
|
|
{
|
|
size_t nSize = WideCharToMultiByte(CP_ACP, 0, pszStrData, -1, NULL, 0, NULL, NULL);
|
|
_ASSERTE(nSize > 0);
|
|
InitBuffer(nSize);
|
|
WideCharToMultiByte(CP_ACP, 0, pszStrData, -1, m_pszData, (int)nSize, NULL, NULL);
|
|
m_nLength = nSize - 1;
|
|
}
|
|
else
|
|
InitBuffer();
|
|
}
|
|
|
|
/**
|
|
* @param pszStrData - data source.
|
|
*/
|
|
void CStrStream::CopyData(PCWSTR pszStrData)
|
|
{
|
|
if (pszStrData && *pszStrData)
|
|
{
|
|
size_t nSize = WideCharToMultiByte(CP_ACP, 0, pszStrData, -1, NULL, 0, NULL, NULL);
|
|
_ASSERTE(nSize > 0);
|
|
EnsureSize(nSize, false);
|
|
WideCharToMultiByte(CP_ACP, 0, pszStrData, -1, m_pszData, (int)nSize, NULL, NULL);
|
|
m_nLength = nSize - 1;
|
|
}
|
|
else
|
|
Reset();
|
|
}
|
|
|
|
/**
|
|
* @param pszStrData - data source.
|
|
*/
|
|
void CStrStream::AppendData(PCWSTR pszStrData)
|
|
{
|
|
if (pszStrData && *pszStrData)
|
|
{
|
|
size_t nSize = WideCharToMultiByte(CP_ACP, 0, pszStrData, -1, NULL, 0, NULL, NULL);
|
|
_ASSERTE(nSize > 0);
|
|
size_t nNewSize = m_nLength + nSize;
|
|
EnsureSize(nNewSize, true);
|
|
WideCharToMultiByte(CP_ACP, 0, pszStrData, -1, m_pszData + m_nLength, (int)nSize, NULL, NULL);
|
|
m_nLength = nNewSize - 1;
|
|
}
|
|
}
|
|
|
|
#endif
|
|
|
|
/**
|
|
* @return object string buffer.
|
|
* @note The caller is responsible to free returned string buffer.
|
|
*/
|
|
PTSTR CStrStream::Detach(void)
|
|
{
|
|
PTSTR pszData = m_pszData;
|
|
InitBuffer();
|
|
return pszData;
|
|
}
|
|
|
|
void CStrStream::Reset(void)
|
|
{
|
|
if (m_pszData)
|
|
{
|
|
*m_pszData = _T('\0');
|
|
m_nLength = 0;
|
|
}
|
|
}
|
|
|
|
void CStrStream::Free(void)
|
|
{
|
|
if (m_pszData)
|
|
{
|
|
delete[] m_pszData;
|
|
InitBuffer();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @param nPosition - start position.
|
|
* @param nLength - length of the extracted string.
|
|
*/
|
|
void CStrStream::ValidateIndex(size_t nPosition, size_t& nLength) const
|
|
{
|
|
_ASSERTE(nPosition <= m_nLength);
|
|
if (nPosition > m_nLength)
|
|
RaiseException(STATUS_ARRAY_BOUNDS_EXCEEDED, 0, 0, NULL);
|
|
size_t nMaxLength = m_nLength - nPosition;
|
|
if (nLength == MAXSIZE_T)
|
|
nLength = nMaxLength;
|
|
else
|
|
{
|
|
_ASSERTE(nLength <= nMaxLength);
|
|
if (nLength > nMaxLength)
|
|
RaiseException(STATUS_ARRAY_BOUNDS_EXCEEDED, 0, 0, NULL);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @param rStrHolder - string buffer that receives the data.
|
|
* @param nPosition - start position.
|
|
* @param nLength - length of the extracted string.
|
|
*/
|
|
void CStrStream::Substring(CStrHolder& rStrHolder, size_t nPosition, size_t nLength) const
|
|
{
|
|
ValidateIndex(nPosition, nLength);
|
|
size_t nEndPosition = nPosition + nLength;
|
|
TCHAR chData = m_pszData[nEndPosition];
|
|
m_pszData[nEndPosition] = _T('\0');
|
|
rStrHolder = m_pszData + nPosition;
|
|
m_pszData[nEndPosition] = chData;
|
|
}
|
|
|
|
/**
|
|
* @param pszSubstring - inserted string buffer.
|
|
* @param nPosition - start position.
|
|
* @param nLength - length of the inserted string.
|
|
*/
|
|
void CStrStream::Insert(PCTSTR pszSubstring, size_t nPosition, size_t nLength)
|
|
{
|
|
ValidateIndex(nPosition);
|
|
size_t nNewLength = m_nLength + nLength;
|
|
EnsureSize(nNewLength + 1, true);
|
|
size_t nNextPosition = nPosition + nLength;
|
|
size_t nNextLength = m_nLength - nPosition;
|
|
MoveMemory(m_pszData + nNextPosition, m_pszData + nPosition, (nNextLength + 1) * sizeof(TCHAR));
|
|
MoveMemory(m_pszData + nPosition, pszSubstring, nLength * sizeof(TCHAR));
|
|
m_nLength = nNewLength;
|
|
}
|
|
|
|
/**
|
|
* @param nPosition - start position.
|
|
* @param nLength - length of the extracted string.
|
|
*/
|
|
void CStrStream::Delete(size_t nPosition, size_t nLength)
|
|
{
|
|
ValidateIndex(nPosition, nLength);
|
|
size_t nNewLength = m_nLength - nLength;
|
|
MoveMemory(m_pszData + nPosition, m_pszData + nLength, (nNewLength + 1) * sizeof(TCHAR));
|
|
m_nLength = nNewLength;
|
|
}
|
|
|
|
void CStrStream::Trim(void)
|
|
{
|
|
TrimSpaces(m_pszData);
|
|
m_nLength = _tcslen(m_pszData);
|
|
}
|