/* * This is a part of the BugTrap package. * Copyright (c) 2005-2009 IntelleSoft. * All rights reserved. * * Description: String (in-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. */ #pragma once class CStrHolder; /// Dynamic string builder. class CStrStream { public: /// Initialize the object. CStrStream(void); /// Initialize the object. explicit CStrStream(size_t nSize); /// Makes a copy of string data. CStrStream(PCSTR pszStrData); /// Makes a copy of string data. CStrStream(PCWSTR pszStrData); /// Makes a copy of string data. CStrStream(const CStrHolder& rStrHolder); /// Makes a copy of string data. CStrStream(const CStrStream& rStrStream); /// Destroy the object. ~CStrStream(void); /// Get string data. operator PCTSTR(void) const; /// Get string length. size_t GetLength(void) const; /// Return true if string is empty. bool IsEmpty(void) const; /// Get string character. TCHAR operator[](size_t nPosition) const; /// Get/set string character. TCHAR& operator[](size_t nPosition); /// Get string character. TCHAR GetAt(size_t nPosition) const; /// Set string character. void SetAt(size_t nPosition, TCHAR chData); /// Extract substring from the stream. void Substring(CStrHolder& rStrHolder, size_t nPosition, size_t nLength = MAXSIZE_T) const; /// Extract substring from the stream. void Substring(CStrStream& rStrStream, size_t nPosition, size_t nLength = MAXSIZE_T) const; /// Insert single character to the stream. void Insert(TCHAR chData, size_t nPosition); /// Insert substring to the stream. void Insert(PCTSTR pszSubstring, size_t nPosition); /// Insert substring to the stream. void Insert(const CStrHolder& rStrHolder, size_t nPosition); /// Insert substring to the stream. void Insert(const CStrStream& rStrStream, size_t nPosition); /// Delete substring from the string. void Delete(size_t nPosition, size_t nLength = MAXSIZE_T); /// Trim a string. void Trim(void); /// Makes a copy of string data. CStrStream& operator=(CHAR chData); /// Makes a copy of string data. CStrStream& operator=(WCHAR chData); /// Makes a copy of string data. CStrStream& operator=(PCSTR pszStrData); /// Makes a copy of string data. CStrStream& operator=(PCWSTR pszStrData); /// Makes a copy of string data. CStrStream& operator=(const CStrHolder& rStrHolder); /// Makes a copy of string data. CStrStream& operator=(const CStrStream& rStrStream); /// Appends data to stream. CStrStream& operator<<(CHAR chData); /// Appends data to stream. CStrStream& operator<<(WCHAR chData); /// Appends data to stream. CStrStream& operator<<(PCSTR pszStrData); /// Appends data to stream. CStrStream& operator<<(PCWSTR pszStrData); /// Appends data to stream. CStrStream& operator<<(const CStrHolder& rStrHolder); /// Appends data to stream. CStrStream& operator<<(const CStrStream& rStrStream); /// Detach string data from the object. PTSTR Detach(void); /// Reset stream contents. void Reset(void); /// Free stream object memory. void Free(void); /// Object comparison. friend bool operator==(const CStrStream& rStrStream1, const CStrStream& rStrStream2); /// Object comparison. friend bool operator!=(const CStrStream& rStrStream1, const CStrStream& rStrStream2); /// Object comparison. friend bool operator<(const CStrStream& rStrStream1, const CStrStream& rStrStream2); /// Object comparison. friend bool operator<=(const CStrStream& rStrStream1, const CStrStream& rStrStream2); /// Object comparison. friend bool operator>(const CStrStream& rStrStream1, const CStrStream& rStrStream2); /// Object comparison. friend bool operator>=(const CStrStream& rStrStream1, const CStrStream& rStrStream2); private: /// Clear internal data. void InitBuffer(void); /// Initialize new string. void InitBuffer(size_t nSize); /// Reallocates string buffer if necessary. void EnsureSize(size_t nSize, bool bAdaptiveGrowth); /// Initialize new string. void InitData(PCTSTR pszStrData, size_t nLength); /// Copy string into the existing buffer. void CopyData(PCTSTR pszStrData, size_t nLength); /// Append string to the existing data. void AppendData(PCTSTR pszStrData, size_t nLength); #ifdef _UNICODE /// Initialize new string. void InitData(PCSTR pszStrData); /// Copy string into the existing buffer. void CopyData(PCSTR pszStrData); /// Append string to the existing data. void AppendData(PCSTR pszStrData); #else /// Initialize new string. void InitData(PCWSTR pszStrData); /// Copy string into existing buffer. void CopyData(PCWSTR pszStrData); /// Append string to existing data. void AppendData(PCWSTR pszStrData); #endif /// Insert substring to the stream. void Insert(PCTSTR pszSubstring, size_t nPosition, size_t nLength); /// Validate string position. void ValidateIndex(size_t nPosition) const; /// Validate string position and length. void ValidateIndex(size_t nPosition, size_t& nLength) const; /// Stream data data. PTSTR m_pszData; /// String length. size_t m_nLength; /// Buffer size. size_t m_nSize; }; inline CStrStream::CStrStream(void) { InitBuffer(); } /** * @param nSize - initial buffer size. */ inline CStrStream::CStrStream(size_t nSize) { InitBuffer(nSize); } inline CStrStream::~CStrStream(void) { delete[] m_pszData; } /** * @return stream length. */ inline size_t CStrStream::GetLength(void) const { return m_nLength; } /** * @return true if string is empty. */ inline bool CStrStream::IsEmpty(void) const { return (m_nLength == 0); } /** * @return pointer to stream buffer. */ inline CStrStream::operator PCTSTR(void) const { return (m_pszData ? m_pszData : _T("")); } /** * @param pszStrData - string data to copy. */ inline CStrStream::CStrStream(PCSTR pszStrData) { #ifdef _UNICODE InitData(pszStrData); #else InitData(pszStrData, strlen(pszStrData)); #endif } /** * @param pszStrData - string data to copy. */ inline CStrStream::CStrStream(PCWSTR pszStrData) { #ifdef _UNICODE InitData(pszStrData, wcslen(pszStrData)); #else InitData(pszStrData); #endif } /** * @param rStrStream - another stream object. */ inline CStrStream::CStrStream(const CStrStream& rStrStream) { InitData(rStrStream.m_pszData, rStrStream.m_nLength); } /** * @param chData - character data to copy. * @return reference to itself. */ inline CStrStream& CStrStream::operator=(CHAR chData) { #ifdef _UNICODE WCHAR chTemp; MultiByteToWideChar(CP_ACP, 0, &chData, 1, &chTemp, 1); CopyData(&chTemp, 1); #else CopyData(&chData, 1); #endif return *this; } /** * @param chData - character data to copy. * @return reference to itself. */ inline CStrStream& CStrStream::operator=(WCHAR chData) { #ifdef _UNICODE CopyData(&chData, 1); #else CHAR chTemp; WideCharToMultiByte(CP_ACP, 0, &chData, 1, &chTemp, 1, NULL, NULL); CopyData(&chTemp, 1); #endif return *this; } /** * @param pszStrData - string data to copy. * @return reference to itself. */ inline CStrStream& CStrStream::operator=(PCSTR pszStrData) { #ifdef _UNICODE CopyData(pszStrData); #else CopyData(pszStrData, strlen(pszStrData)); #endif return *this; } /** * @param pszStrData - string data to copy. * @return reference to itself. */ inline CStrStream& CStrStream::operator=(PCWSTR pszStrData) { #ifdef _UNICODE CopyData(pszStrData, wcslen(pszStrData)); #else CopyData(pszStrData); #endif return *this; } /** * @param rStrStream - another stream object. * @return reference to itself. */ inline CStrStream& CStrStream::operator=(const CStrStream& rStrStream) { if (this != &rStrStream) CopyData(rStrStream.m_pszData, rStrStream.m_nLength); return *this; } /** * @param chData - character data to append. * @return reference to itself. */ inline CStrStream& CStrStream::operator<<(CHAR chData) { #ifdef _UNICODE WCHAR chTemp; MultiByteToWideChar(CP_ACP, 0, &chData, 1, &chTemp, 1); AppendData(&chTemp, 1); #else AppendData(&chData, 1); #endif return *this; } /** * @param chData - character data to append. * @return reference to itself. */ inline CStrStream& CStrStream::operator<<(WCHAR chData) { #ifdef _UNICODE AppendData(&chData, 1); #else CHAR chTemp; WideCharToMultiByte(CP_ACP, 0, &chData, 1, &chTemp, 1, NULL, NULL); AppendData(&chTemp, 1); #endif return *this; } /** * @param pszStrData - string data to append. * @return reference to itself. */ inline CStrStream& CStrStream::operator<<(PCSTR pszStrData) { #ifdef _UNICODE AppendData(pszStrData); #else AppendData(pszStrData, strlen(pszStrData)); #endif return *this; } /** * @param pszStrData - string data to append. * @return reference to itself. */ inline CStrStream& CStrStream::operator<<(PCWSTR pszStrData) { #ifdef _UNICODE AppendData(pszStrData, wcslen(pszStrData)); #else AppendData(pszStrData); #endif return *this; } /** * @param rStrStream - another stream object. * @return reference to itself. */ inline CStrStream& CStrStream::operator<<(const CStrStream& rStrStream) { AppendData(rStrStream.m_pszData, rStrStream.m_nLength); return *this; } /** * @param nPosition - character position within the string. * @return character value. */ inline TCHAR CStrStream::GetAt(size_t nPosition) const { ValidateIndex(nPosition); return m_pszData[nPosition]; } /** * @param nPosition - character position within the string. * @return character value. */ inline TCHAR CStrStream::operator[](size_t nPosition) const { ValidateIndex(nPosition); return m_pszData[nPosition]; } /** * @param nPosition - character position within the string. * @param chData - character value. */ inline void CStrStream::SetAt(size_t nPosition, TCHAR chData) { ValidateIndex(nPosition); m_pszData[nPosition] = chData; } /** * @param nPosition - character position within the string. * @return reference to character value. */ inline TCHAR& CStrStream::operator[](size_t nPosition) { ValidateIndex(nPosition); return m_pszData[nPosition]; } /** * @param rStrStream - string buffer that receives the data. * @param nPosition - start position. * @param nLength - length of the extracted string. */ inline void CStrStream::Substring(CStrStream& rStrStream, size_t nPosition, size_t nLength) const { ValidateIndex(nPosition, nLength); rStrStream.CopyData(m_pszData + nPosition, nLength); } /** * @param nPosition - start position. */ inline void CStrStream::ValidateIndex(size_t nPosition) const { _ASSERTE(nPosition < m_nLength); if (nPosition >= m_nLength) RaiseException(STATUS_ARRAY_BOUNDS_EXCEEDED, 0, 0, NULL); } /** * @param chData - character value. * @param nPosition - start position. */ inline void CStrStream::Insert(TCHAR chData, size_t nPosition) { Insert(&chData, nPosition, 1); } /** * @param pszSubstring - inserted string buffer. * @param nPosition - start position. */ inline void CStrStream::Insert(PCTSTR pszSubstring, size_t nPosition) { Insert(pszSubstring, nPosition, _tcslen(pszSubstring)); } /** * @param rStrStream - inserted string buffer. * @param nPosition - start position. */ inline void CStrStream::Insert(const CStrStream& rStrStream, size_t nPosition) { Insert(rStrStream.m_pszData, nPosition, rStrStream.m_nLength); } #include "StrHolder.h" /** * @param rStrHolder - string data to copy. */ inline CStrStream::CStrStream(const CStrHolder& rStrHolder) { InitData((PCTSTR)rStrHolder, rStrHolder.GetLength()); } /** * @param rStrHolder - string data to copy. * @return reference to itself. */ inline CStrStream& CStrStream::operator=(const CStrHolder& rStrHolder) { CopyData((PCTSTR)rStrHolder, rStrHolder.GetLength()); return *this; } /** * @param rStrHolder - string data to append. * @return reference to itself. */ inline CStrStream& CStrStream::operator<<(const CStrHolder& rStrHolder) { AppendData((PCTSTR)rStrHolder, rStrHolder.GetLength()); return *this; } /** * @param rStrHolder - inserted string buffer. * @param nPosition - start position. */ inline void CStrStream::Insert(const CStrHolder& rStrHolder, size_t nPosition) { Insert((PCTSTR)rStrHolder, nPosition, rStrHolder.GetLength()); } /** * @param rStrStream1 - 1st object. * @param rStrStream2 - 2nd object. * @return comparison result. */ inline bool operator==(const CStrStream& rStrStream1, const CStrStream& rStrStream2) { return (_tcscmp(rStrStream1.m_pszData, rStrStream2.m_pszData) == 0); } /** * @param rStrStream1 - 1st object. * @param rStrStream2 - 2nd object. * @return comparison result. */ inline bool operator!=(const CStrStream& rStrStream1, const CStrStream& rStrStream2) { return (_tcscmp(rStrStream1.m_pszData, rStrStream2.m_pszData) != 0); } /** * @param rStrStream1 - 1st object. * @param rStrStream2 - 2nd object. * @return comparison result. */ inline bool operator<(const CStrStream& rStrStream1, const CStrStream& rStrStream2) { return (_tcscmp(rStrStream1.m_pszData, rStrStream2.m_pszData) < 0); } /** * @param rStrStream1 - 1st object. * @param rStrStream2 - 2nd object. * @return comparison result. */ inline bool operator<=(const CStrStream& rStrStream1, const CStrStream& rStrStream2) { return (_tcscmp(rStrStream1.m_pszData, rStrStream2.m_pszData) <= 0); } /** * @param rStrStream1 - 1st object. * @param rStrStream2 - 2nd object. * @return comparison result. */ inline bool operator>(const CStrStream& rStrStream1, const CStrStream& rStrStream2) { return (_tcscmp(rStrStream1.m_pszData, rStrStream2.m_pszData) > 0); } /** * @param rStrStream1 - 1st object. * @param rStrStream2 - 2nd object. * @return comparison result. */ inline bool operator>=(const CStrStream& rStrStream1, const CStrStream& rStrStream2) { return (_tcscmp(rStrStream1.m_pszData, rStrStream2.m_pszData) >= 0); }