Index: src/ch/ch.cpp =================================================================== diff -u -rffdee64cb0f2d472bb4102abe80ee12783e794c8 -r7b830c34855c8aaa81aac2c6e0ca0fa6bae95e66 --- src/ch/ch.cpp (.../ch.cpp) (revision ffdee64cb0f2d472bb4102abe80ee12783e794c8) +++ src/ch/ch.cpp (.../ch.cpp) (revision 7b830c34855c8aaa81aac2c6e0ca0fa6bae95e66) @@ -206,30 +206,43 @@ #ifdef DO_TEST using namespace chcore; + DeleteFile(_T("C:\\Users\\ixen\\AppData\\Local\\Copy Handler\\Tasks\\test.sqlite")); + TSQLiteTaskSchemaPtr spTaskSchema(new TSQLiteTaskSchema); + + TSQLiteSerializer serializer(PathFromString(_T("C:\\Users\\ixen\\AppData\\Local\\Copy Handler\\Tasks\\test.sqlite")), spTaskSchema); + //TSQLiteSerializer serializer(PathFromString(_T(":memory:")), spTaskSchema); + TSimpleTimer timer(true); { - DeleteFile(_T("C:\\Users\\ixen\\AppData\\Local\\Copy Handler\\Tasks\\test.sqlite")); - TSQLiteTaskSchemaPtr spTaskSchema(new TSQLiteTaskSchema); - - // TSQLiteSerializer serializer(PathFromString(_T("C:\\Users\\ixen\\AppData\\Local\\Copy Handler\\Tasks\\test.sqlite")), spTaskSchema); - TSQLiteSerializer serializer(PathFromString(_T(":memory:")), spTaskSchema); ISerializerContainerPtr spContainer = serializer.GetContainer(_T("scanned_files")); IColumnsDefinition& rColumns = spContainer->GetColumnsDefinition(); TFileInfo::InitColumns(rColumns); + const size_t rel_path = rColumns.GetColumnIndex(_T("rel_path")); + const size_t base_path_id = rColumns.GetColumnIndex(_T("base_path_id")); + const size_t attr = rColumns.GetColumnIndex(_T("attr")); + const size_t size = rColumns.GetColumnIndex(_T("size")); + const size_t time_created = rColumns.GetColumnIndex(_T("time_created")); + const size_t time_last_write = rColumns.GetColumnIndex(_T("time_last_write")); + const size_t time_last_access = rColumns.GetColumnIndex(_T("time_last_access")); + const size_t flags = rColumns.GetColumnIndex(_T("flags")); + + TString strPath(_T("C:\\Users\\ixen\\AppData\\Local\\Copy Handler\\Tasks\\sometask.xxx")); + TSmartPath path(PathFromString(_T("C:\\Users\\ixen\\AppData\\Local\\Copy Handler\\Tasks\\sometask.xxx"))); + for(size_t stIndex = 0; stIndex < 200000; ++stIndex) { ISerializerRowData& rRow = spContainer->GetRow(stIndex, true); - rRow.SetValue(_T("rel_path"), PathFromString(_T("C:\\Users\\ixen\\AppData\\Local\\Copy Handler\\Tasks\\sometask.xxx"))); - rRow.SetValue(_T("base_path_id"), 24735275ull); - rRow.SetValue(_T("attr"), 0x56533234ul); - rRow.SetValue(_T("size"), 0x565332340897ff12ull); - rRow.SetValue(_T("time_created"), 0x565332340897ff12ull); - rRow.SetValue(_T("time_last_write"), 0x565122340897ff12ull); - rRow.SetValue(_T("time_last_access"), 0x565517840897ff12ull); - rRow.SetValue(_T("flags"), 0x56551114u); + rRow.SetValue(rel_path, path); //C:\\Users\\ixen\\AppData\\Local\\Copy Handler\\Tasks\\sometask.xxx + rRow.SetValue(base_path_id, 24735275ull); + rRow.SetValue(attr, 0x56533234ul); + rRow.SetValue(size, 0x565332340897ff12ull); + rRow.SetValue(time_created, 0x565332340897ff12ull); + rRow.SetValue(time_last_write, 0x565122340897ff12ull); + rRow.SetValue(time_last_access, 0x565517840897ff12ull); + rRow.SetValue(flags, 0x56551114u); } unsigned long long ullFillTime = timer.Checkpoint(); ullFillTime; @@ -238,6 +251,10 @@ serializer.Flush(); unsigned long long ullFlushTime = timer.Checkpoint(); ullFlushTime; GTRACE1(_T("***** [FlushTime]: %I64u ms\n"), ullFlushTime); + + spContainer.reset(); + unsigned long long ullDeleteContainerTime = timer.Checkpoint(); ullDeleteContainerTime; + GTRACE1(_T("***** [DeleteContainer]: %I64u ms\n"), ullDeleteContainerTime); } unsigned long long ullDestructTime = timer.Checkpoint(); ullDestructTime; Index: src/libchcore/IColumnsDefinition.h =================================================================== diff -u -rffdee64cb0f2d472bb4102abe80ee12783e794c8 -r7b830c34855c8aaa81aac2c6e0ca0fa6bae95e66 --- src/libchcore/IColumnsDefinition.h (.../IColumnsDefinition.h) (revision ffdee64cb0f2d472bb4102abe80ee12783e794c8) +++ src/libchcore/IColumnsDefinition.h (.../IColumnsDefinition.h) (revision 7b830c34855c8aaa81aac2c6e0ca0fa6bae95e66) @@ -52,8 +52,8 @@ virtual size_t AddColumn(const TString& strColumnName, ETypes eColType) = 0; virtual void Clear() = 0; - virtual size_t GetColumnIndex(const TString& strColumnName) = 0; - virtual TString GetColumnName(size_t stIndex) const = 0; + virtual size_t GetColumnIndex(const wchar_t* strColumnName) = 0; + virtual const TString& GetColumnName(size_t stIndex) const = 0; virtual size_t GetCount() const = 0; virtual bool IsEmpty() const = 0; }; Index: src/libchcore/ISerializerRowData.h =================================================================== diff -u -r3933d378c75e0b245a6ccb91099eaeb2c5728209 -r7b830c34855c8aaa81aac2c6e0ca0fa6bae95e66 --- src/libchcore/ISerializerRowData.h (.../ISerializerRowData.h) (revision 3933d378c75e0b245a6ccb91099eaeb2c5728209) +++ src/libchcore/ISerializerRowData.h (.../ISerializerRowData.h) (revision 7b830c34855c8aaa81aac2c6e0ca0fa6bae95e66) @@ -46,18 +46,18 @@ virtual ISerializerRowData& SetValue(size_t stColIndex, const TString& strValue) = 0; virtual ISerializerRowData& SetValue(size_t stColIndex, const TSmartPath& pathValue) = 0; - virtual ISerializerRowData& SetValue(const TString& strColumnName, bool bValue) = 0; - virtual ISerializerRowData& SetValue(const TString& strColumnName, short iValue) = 0; - virtual ISerializerRowData& SetValue(const TString& strColumnName, unsigned short uiValue) = 0; - virtual ISerializerRowData& SetValue(const TString& strColumnName, int iValue) = 0; - virtual ISerializerRowData& SetValue(const TString& strColumnName, unsigned int uiValue) = 0; - virtual ISerializerRowData& SetValue(const TString& strColumnName, long lValue) = 0; - virtual ISerializerRowData& SetValue(const TString& strColumnName, unsigned long ulValue) = 0; - virtual ISerializerRowData& SetValue(const TString& strColumnName, long long llValue) = 0; - virtual ISerializerRowData& SetValue(const TString& strColumnName, unsigned long long llValue) = 0; - virtual ISerializerRowData& SetValue(const TString& strColumnName, double dValue) = 0; - virtual ISerializerRowData& SetValue(const TString& strColumnName, const TString& strValue) = 0; - virtual ISerializerRowData& SetValue(const TString& strColumnName, const TSmartPath& pathValue) = 0; + virtual ISerializerRowData& SetValue(const wchar_t* strColumnName, bool bValue) = 0; + virtual ISerializerRowData& SetValue(const wchar_t* strColumnName, short iValue) = 0; + virtual ISerializerRowData& SetValue(const wchar_t* strColumnName, unsigned short uiValue) = 0; + virtual ISerializerRowData& SetValue(const wchar_t* strColumnName, int iValue) = 0; + virtual ISerializerRowData& SetValue(const wchar_t* strColumnName, unsigned int uiValue) = 0; + virtual ISerializerRowData& SetValue(const wchar_t* strColumnName, long lValue) = 0; + virtual ISerializerRowData& SetValue(const wchar_t* strColumnName, unsigned long ulValue) = 0; + virtual ISerializerRowData& SetValue(const wchar_t* strColumnName, long long llValue) = 0; + virtual ISerializerRowData& SetValue(const wchar_t* strColumnName, unsigned long long llValue) = 0; + virtual ISerializerRowData& SetValue(const wchar_t* strColumnName, double dValue) = 0; + virtual ISerializerRowData& SetValue(const wchar_t* strColumnName, const TString& strValue) = 0; + virtual ISerializerRowData& SetValue(const wchar_t* strColumnName, const TSmartPath& pathValue) = 0; }; END_CHCORE_NAMESPACE Index: src/libchcore/TPath.cpp =================================================================== diff -u -rb1e03eb232a784d6e2d40f67cbbbb33be0972228 -r7b830c34855c8aaa81aac2c6e0ca0fa6bae95e66 --- src/libchcore/TPath.cpp (.../TPath.cpp) (revision b1e03eb232a784d6e2d40f67cbbbb33be0972228) +++ src/libchcore/TPath.cpp (.../TPath.cpp) (revision 7b830c34855c8aaa81aac2c6e0ca0fa6bae95e66) @@ -35,104 +35,14 @@ #define DEFAULT_PATH_SEPARATOR _T("\\") -namespace details -{ - // ============================================================================ - /// TPath::TPath - /// @date 2009/11/29 - /// - /// @brief Constructs the TPath object. - // ============================================================================ - TPath::TPath() : - m_strPath(), - m_lRefCount(1) - { - } - - // ============================================================================ - /// TPath::TPath - /// @date 2009/11/29 - /// - /// @brief Constructs the TPath object. - // ============================================================================ - TPath::TPath(const TPath& rSrc) : - m_strPath(rSrc.m_strPath), - m_lRefCount(1) - { - } - - // ============================================================================ - /// TPath::~TPath - /// @date 2009/11/29 - /// - /// @brief Destructs the TPath object. - // ============================================================================ - TPath::~TPath() - { - } - - // ============================================================================ - /// TPath::Release - /// @date 2009/11/29 - /// - /// @brief Releases a reference to this object. Deletes the object if no reference exists. - /// @return Current reference count. - // ============================================================================ - long TPath::Release() - { - if(--m_lRefCount == 0) - { - delete this; - return 0; - } - return m_lRefCount; - } - - // ============================================================================ - /// TPath::New - /// @date 2009/11/29 - /// - /// @brief Allocates a new, empty TPath object. - /// @return Pointer to the newly allocated object. - // ============================================================================ - TPath* TPath::New() - { - return new TPath(); - } - - // ============================================================================ - /// TPath::New - /// @date 2010/10/07 - /// - /// @brief Clones this object. - /// @return Pointer to the newly allocated object. - // ============================================================================ - TPath* TPath::Clone() - { - return new TPath(*this); - } - - // ============================================================================ - /// TPath::Delete - /// @date 2009/11/29 - /// - /// @brief Deletes the TPath object - /// @param[in] pPath - pointer to the object to delete. - // ============================================================================ - void TPath::Delete(TPath* pPath) - { - delete pPath; - } -} - // ============================================================================ /// TSmartPath::TSmartPath /// @date 2009/11/29 /// /// @brief Constructs an empty path. // ============================================================================ TSmartPath::TSmartPath() : - m_pPath(NULL) + m_strPath() { } @@ -144,10 +54,8 @@ /// @param[in] spPath - reference to another path object. // ============================================================================ TSmartPath::TSmartPath(const TSmartPath& spPath) : - m_pPath(spPath.m_pPath) + m_strPath(spPath.m_strPath) { - if(m_pPath) - m_pPath->AddRef(); } // ============================================================================ @@ -170,11 +78,7 @@ // ============================================================================ void TSmartPath::Clear() throw() { - if(m_pPath) - { - m_pPath->Release(); // Release will delete object if unused anymore - m_pPath = NULL; - } + m_strPath.Clear(); } @@ -189,34 +93,31 @@ TSmartPath& TSmartPath::Append(const TSmartPath& pathToAppend, bool bEnsurePathSeparatorExists) { // if there is no path inside rPath, then there is no point in doing anything - if(pathToAppend.m_pPath && pathToAppend.m_pPath->m_strPath.GetLength() > 0) + if(!pathToAppend.m_strPath.IsEmpty()) { // if this path is empty, then optimize by just assigning the input path to this one - if(!m_pPath || m_pPath->m_strPath.GetLength() == 0) + if(m_strPath.IsEmpty()) *this = pathToAppend; else { - // both paths are not empty - do regular concatenation - PrepareToWrite(); - if(bEnsurePathSeparatorExists) { // detect separators bool bThisEndsWithSeparator = EndsWithSeparator(); bool bInStartsWithSeparator = pathToAppend.StartsWithSeparator(); if(!bThisEndsWithSeparator && !bInStartsWithSeparator) - m_pPath->m_strPath += _T("\\") + pathToAppend.m_pPath->m_strPath; + m_strPath += _T("\\") + pathToAppend.m_strPath; else if(bThisEndsWithSeparator ^ bInStartsWithSeparator) - m_pPath->m_strPath += pathToAppend.m_pPath->m_strPath; + m_strPath += pathToAppend.m_strPath; else { - m_pPath->m_strPath.Delete(m_pPath->m_strPath.GetLength() - 1, 1); - m_pPath->m_strPath += pathToAppend.m_pPath->m_strPath; + m_strPath.Delete(m_strPath.GetLength() - 1, 1); + m_strPath += pathToAppend.m_strPath; } } else - m_pPath->m_strPath += pathToAppend.m_pPath->m_strPath; + m_strPath += pathToAppend.m_strPath; } } @@ -233,11 +134,10 @@ // ============================================================================ TSmartPath& TSmartPath::operator=(const TSmartPath& spPath) { - if(this != &spPath && m_pPath != spPath.m_pPath) + if(this != &spPath) { Clear(); - m_pPath = spPath.m_pPath; - m_pPath->AddRef(); + m_strPath = spPath.m_strPath; } return *this; @@ -326,8 +226,7 @@ if(!pszPath) THROW_CORE_EXCEPTION(eErr_InvalidArgument); - PrepareToWrite(); - m_pPath->m_strPath = pszPath; + m_strPath = pszPath; } // ============================================================================ @@ -339,8 +238,7 @@ // ============================================================================ void TSmartPath::FromString(const TString& strPath) { - PrepareToWrite(); - m_pPath->m_strPath = strPath; + m_strPath = strPath; } // ============================================================================ @@ -352,9 +250,7 @@ // ============================================================================ const wchar_t* TSmartPath::ToString() const { - if(m_pPath) - return m_pPath->m_strPath; - return _T(""); + return m_strPath; } // ============================================================================ @@ -366,10 +262,7 @@ // ============================================================================ TString TSmartPath::ToWString() const { - TString wstrPath; - if(m_pPath) - wstrPath = m_pPath->m_strPath; - return wstrPath; + return m_strPath; } // ============================================================================ @@ -382,25 +275,10 @@ // ============================================================================ int TSmartPath::Compare(const TSmartPath& rPath, bool bCaseSensitive) const { - if(m_pPath == rPath.m_pPath) - return 0; - else if(m_pPath == NULL || rPath.m_pPath == NULL) - { - TString strThis = m_pPath ? m_pPath->m_strPath : _T(""); - TString strOther = rPath.m_pPath ? rPath.m_pPath->m_strPath : _T(""); - - if(bCaseSensitive) - return strThis.Compare(strOther); - else - return strThis.CompareNoCase(strOther); - } + if(bCaseSensitive) + return m_strPath.Compare(rPath.m_strPath); else - { - if(bCaseSensitive) - return m_pPath->m_strPath.Compare(rPath.m_pPath->m_strPath); - else - return m_pPath->m_strPath.CompareNoCase(rPath.m_pPath->m_strPath); - } + return m_strPath.CompareNoCase(rPath.m_strPath); } // ============================================================================ @@ -432,7 +310,7 @@ else { TStringArray vStrings; - m_pPath->m_strPath.Split(_T("\\/"), vStrings); + m_strPath.Split(_T("\\/"), vStrings); for(size_t stIndex = 0; stIndex < vStrings.GetCount(); ++stIndex) { @@ -453,13 +331,10 @@ // ============================================================================ bool TSmartPath::IsChildOf(const TSmartPath& rPath, bool bCaseSensitive) const { - if(!m_pPath || !rPath.m_pPath) - return false; - if(bCaseSensitive) - return m_pPath->m_strPath.StartsWith(rPath.m_pPath->m_strPath); + return m_strPath.StartsWith(rPath.m_strPath); else - return m_pPath->m_strPath.StartsWithNoCase(rPath.m_pPath->m_strPath); + return m_strPath.StartsWithNoCase(rPath.m_strPath); } // ============================================================================ @@ -473,19 +348,15 @@ // ============================================================================ bool TSmartPath::MakeRelativePath(const TSmartPath& rReferenceBasePath, bool bCaseSensitive) { - if(!m_pPath || !rReferenceBasePath.m_pPath) - return true; // nothing to do; in this case we might as well treat the path as relative one - bool bStartsWith = false; if(bCaseSensitive) - bStartsWith = m_pPath->m_strPath.StartsWith(rReferenceBasePath.m_pPath->m_strPath); + bStartsWith = m_strPath.StartsWith(rReferenceBasePath.m_strPath); else - bStartsWith = m_pPath->m_strPath.StartsWithNoCase(rReferenceBasePath.m_pPath->m_strPath); + bStartsWith = m_strPath.StartsWithNoCase(rReferenceBasePath.m_strPath); if(bStartsWith) { - PrepareToWrite(); - m_pPath->m_strPath.Delete(0, rReferenceBasePath.m_pPath->m_strPath.GetLength()); + m_strPath.Delete(0, rReferenceBasePath.m_strPath.GetLength()); return true; } else @@ -503,8 +374,7 @@ else StripSeparatorAtFront(); - PrepareToWrite(); - m_pPath->m_strPath = rReferenceBasePath.ToString() + m_pPath->m_strPath; + m_strPath = rReferenceBasePath.ToString() + m_strPath; return true; } @@ -524,15 +394,12 @@ bool bEndsWith = false; if(bCaseSensitive) - bEndsWith = m_pPath && m_pPath->m_strPath.EndsWith(pszPostfix); + bEndsWith = m_strPath.EndsWith(pszPostfix); else - bEndsWith = m_pPath && m_pPath->m_strPath.EndsWithNoCase(pszPostfix); + bEndsWith = m_strPath.EndsWithNoCase(pszPostfix); if(!bEndsWith) - { - PrepareToWrite(); - m_pPath->m_strPath += pszPostfix; - } + m_strPath += pszPostfix; } // ============================================================================ @@ -550,15 +417,12 @@ bool bEndsWith = false; if(bCaseSensitive) - bEndsWith = m_pPath && m_pPath->m_strPath.EndsWith(pszPostfix); + bEndsWith = m_strPath.EndsWith(pszPostfix); else - bEndsWith = m_pPath && m_pPath->m_strPath.EndsWithNoCase(pszPostfix); + bEndsWith = m_strPath.EndsWithNoCase(pszPostfix); if(bEndsWith) - { - PrepareToWrite(); - m_pPath->m_strPath.Delete(m_pPath->m_strPath.GetLength() - _tcslen(pszPostfix), m_pPath->m_strPath.GetLength() - _tcslen(pszPostfix)); - } + m_strPath.Delete(m_strPath.GetLength() - _tcslen(pszPostfix), m_strPath.GetLength() - _tcslen(pszPostfix)); } // ============================================================================ @@ -570,10 +434,7 @@ // ============================================================================ bool TSmartPath::IsNetworkPath() const { - if(!m_pPath) - return false; - - return (m_pPath->m_strPath.GetLength() > 2 && IsSeparator(m_pPath->m_strPath.GetAt(0)) && IsSeparator(m_pPath->m_strPath.GetAt(1))); // "\\server_name" + return (m_strPath.GetLength() > 2 && IsSeparator(m_strPath.GetAt(0)) && IsSeparator(m_strPath.GetAt(1))); // "\\server_name" } // ============================================================================ @@ -585,10 +446,7 @@ // ============================================================================ bool TSmartPath::IsDrive() const { - if(!m_pPath) - return false; - - return (m_pPath->m_strPath.GetLength() == 2 && m_pPath->m_strPath.GetAt(1) == _T(':')); + return (m_strPath.GetLength() == 2 && m_strPath.GetAt(1) == _T(':')); } // ============================================================================ @@ -600,10 +458,7 @@ // ============================================================================ bool TSmartPath::HasDrive() const { - if(!m_pPath) - return false; - - return (m_pPath->m_strPath.GetLength() >= 2 && m_pPath->m_strPath.GetAt(1) == _T(':')); + return (m_strPath.GetLength() >= 2 && m_strPath.GetAt(1) == _T(':')); } // ============================================================================ @@ -615,15 +470,12 @@ // ============================================================================ TSmartPath TSmartPath::GetDrive() const { - if(!m_pPath) - return TSmartPath(); - - if(m_pPath->m_strPath.GetLength() >= 2 && m_pPath->m_strPath.GetAt(1) == _T(':')) + if(m_strPath.GetLength() >= 2 && m_strPath.GetAt(1) == _T(':')) { - if(m_pPath->m_strPath.GetLength() == 2) + if(m_strPath.GetLength() == 2) return *this; else - return PathFromWString(m_pPath->m_strPath.Left(2)); // c: for c:\windows\test.cpp + return PathFromWString(m_strPath.Left(2)); // c: for c:\windows\test.cpp } return TSmartPath(); @@ -638,12 +490,9 @@ // ============================================================================ wchar_t TSmartPath::GetDriveLetter() const { - if(!m_pPath) - return L'\0'; - - if(m_pPath->m_strPath.GetLength() >= 2 && m_pPath->m_strPath.GetAt(1) == _T(':')) + if(m_strPath.GetLength() >= 2 && m_strPath.GetAt(1) == _T(':')) { - wchar_t wchDrive = m_pPath->m_strPath.GetAt(0); + wchar_t wchDrive = m_strPath.GetAt(0); if(wchDrive >= L'a' && wchDrive <= L'z') wchDrive = L'A' + wchDrive - L'a'; return wchDrive; @@ -661,13 +510,10 @@ // ============================================================================ bool TSmartPath::IsServerName() const { - if(!m_pPath) - return false; - - return (m_pPath->m_strPath.GetLength() > 2 && // must have at least 3 characters... - IsSeparator(m_pPath->m_strPath.GetAt(0)) && IsSeparator(m_pPath->m_strPath.GetAt(1)) && // ... the first two of which are separators... - std::isalnum(m_pPath->m_strPath.GetAt(2)) && // ... followed by at least one alphanumeric character... - m_pPath->m_strPath.FindFirstOf(_T("\\/"), 3) == TString::npos); // ... with no additional separators (so \\abc is true, \\abc\ is not). + return (m_strPath.GetLength() > 2 && // must have at least 3 characters... + IsSeparator(m_strPath.GetAt(0)) && IsSeparator(m_strPath.GetAt(1)) && // ... the first two of which are separators... + std::isalnum(m_strPath.GetAt(2)) && // ... followed by at least one alphanumeric character... + m_strPath.FindFirstOf(_T("\\/"), 3) == TString::npos); // ... with no additional separators (so \\abc is true, \\abc\ is not). } // ============================================================================ @@ -679,10 +525,7 @@ // ============================================================================ bool TSmartPath::HasServerName() const { - if(!m_pPath) - return false; - - return (m_pPath->m_strPath.GetLength() > 2 && IsSeparator(m_pPath->m_strPath.GetAt(0)) && IsSeparator(m_pPath->m_strPath.GetAt(1)) && std::isalnum(m_pPath->m_strPath.GetAt(2))); + return (m_strPath.GetLength() > 2 && IsSeparator(m_strPath.GetAt(0)) && IsSeparator(m_strPath.GetAt(1)) && std::isalnum(m_strPath.GetAt(2))); } // ============================================================================ @@ -694,17 +537,14 @@ // ============================================================================ TSmartPath TSmartPath::GetServerName() const { - if(!m_pPath) - return TSmartPath(); - TString wstrPath; - if(m_pPath->m_strPath.GetLength() > 2 && IsSeparator(m_pPath->m_strPath.GetAt(0)) && IsSeparator(m_pPath->m_strPath.GetAt(1)) && std::isalnum(m_pPath->m_strPath.GetAt(2))) + if(m_strPath.GetLength() > 2 && IsSeparator(m_strPath.GetAt(0)) && IsSeparator(m_strPath.GetAt(1)) && std::isalnum(m_strPath.GetAt(2))) { - size_t stEndPos = m_pPath->m_strPath.FindFirstOf(_T("\\/"), 2); + size_t stEndPos = m_strPath.FindFirstOf(_T("\\/"), 2); if(stEndPos == TString::npos) - wstrPath = m_pPath->m_strPath; + wstrPath = m_strPath; else - wstrPath = m_pPath->m_strPath.Left(stEndPos); + wstrPath = m_strPath.Left(stEndPos); return PathFromWString(wstrPath); } @@ -720,10 +560,7 @@ // ============================================================================ bool TSmartPath::HasFileRoot() const { - if(!m_pPath) - return false; - - size_t stIndex = m_pPath->m_strPath.FindLastOf(_T("\\/")); + size_t stIndex = m_strPath.FindLastOf(_T("\\/")); return (stIndex != TString::npos); } @@ -736,12 +573,9 @@ // ============================================================================ TSmartPath TSmartPath::GetFileRoot() const { - if(!m_pPath) - return TSmartPath(); - - size_t stIndex = m_pPath->m_strPath.FindLastOf(_T("\\/")); + size_t stIndex = m_strPath.FindLastOf(_T("\\/")); if(stIndex != TString::npos) - return PathFromWString(m_pPath->m_strPath.Left(stIndex + 1)); + return PathFromWString(m_strPath.Left(stIndex + 1)); return TSmartPath(); } @@ -755,16 +589,13 @@ // ============================================================================ bool TSmartPath::HasFileDir() const { - if(!m_pPath) - return false; - size_t stStart = 0; if(IsNetworkPath()) - stStart = m_pPath->m_strPath.FindFirstOf(_T("/\\"), 2); + stStart = m_strPath.FindFirstOf(_T("/\\"), 2); else - stStart = m_pPath->m_strPath.FindFirstOf(_T("/\\")); + stStart = m_strPath.FindFirstOf(_T("/\\")); - size_t stEnd = m_pPath->m_strPath.FindLastOf(_T("/\\")); + size_t stEnd = m_strPath.FindLastOf(_T("/\\")); return (stStart != TString::npos && stEnd >= stStart); } @@ -777,20 +608,17 @@ // ============================================================================ TSmartPath TSmartPath::GetFileDir() const { - if(!m_pPath) - return TSmartPath(); - size_t stStart = 0; if(IsNetworkPath()) - stStart = m_pPath->m_strPath.FindFirstOf(_T("/\\"), 2); + stStart = m_strPath.FindFirstOf(_T("/\\"), 2); else if(HasDrive()) - stStart = m_pPath->m_strPath.FindFirstOf(_T("/\\")); + stStart = m_strPath.FindFirstOf(_T("/\\")); else stStart = 0; - size_t stEnd = m_pPath->m_strPath.FindLastOf(_T("/\\")); + size_t stEnd = m_strPath.FindLastOf(_T("/\\")); if(stStart != TString::npos && stEnd >= stStart) - return PathFromWString(m_pPath->m_strPath.MidRange(stStart, stEnd + 1)); + return PathFromWString(m_strPath.MidRange(stStart, stEnd + 1)); return TSmartPath(); } @@ -804,17 +632,14 @@ // ============================================================================ bool TSmartPath::HasFileTitle() const { - if(!m_pPath) - return false; - - size_t stStart = m_pPath->m_strPath.FindLastOf(_T("/\\")); - size_t stEnd = m_pPath->m_strPath.FindLastOf(_T(".")); + size_t stStart = m_strPath.FindLastOf(_T("/\\")); + size_t stEnd = m_strPath.FindLastOf(_T(".")); if((stStart == TString::npos && stEnd == TString::npos)) return !IsEmpty(); if(stStart == TString::npos) // if does not exist, start from beginning stStart = 0; if(stEnd == TString::npos || stEnd < stStart) // if does not exist or we have ".\\", use up to the end - stEnd = m_pPath->m_strPath.GetLength(); + stEnd = m_strPath.GetLength(); return stEnd > stStart + 1; } @@ -828,21 +653,18 @@ // ============================================================================ TSmartPath TSmartPath::GetFileTitle() const { - if(!m_pPath) - return TSmartPath(); - - size_t stStart = m_pPath->m_strPath.FindLastOf(_T("/\\")); - size_t stEnd = m_pPath->m_strPath.FindLastOf(_T(".")); + size_t stStart = m_strPath.FindLastOf(_T("/\\")); + size_t stEnd = m_strPath.FindLastOf(_T(".")); if((stStart == TString::npos && stEnd == TString::npos)) return *this; if(stStart == TString::npos) // if does not exist, start from beginning stStart = 0; else ++stStart; if(stEnd == TString::npos || stEnd < stStart) // if does not exist or we have ".\\", use up to the end - stEnd = m_pPath->m_strPath.GetLength(); + stEnd = m_strPath.GetLength(); - return PathFromWString(m_pPath->m_strPath.MidRange(stStart, stEnd)); + return PathFromWString(m_strPath.MidRange(stStart, stEnd)); } // ============================================================================ @@ -854,12 +676,9 @@ // ============================================================================ bool TSmartPath::HasExtension() const { - if(!m_pPath) - return false; + size_t stIndex = m_strPath.FindLastOf(_T("\\/.")); - size_t stIndex = m_pPath->m_strPath.FindLastOf(_T("\\/.")); - - return stIndex != TString::npos && (m_pPath->m_strPath.GetAt(stIndex) == _T('.')); + return stIndex != TString::npos && (m_strPath.GetAt(stIndex) == _T('.')); } // ============================================================================ @@ -871,14 +690,11 @@ // ============================================================================ TSmartPath TSmartPath::GetExtension() const { - if(!m_pPath) - return TSmartPath(); + size_t stIndex = m_strPath.FindLastOf(_T("\\/.")); - size_t stIndex = m_pPath->m_strPath.FindLastOf(_T("\\/.")); + if(stIndex != TString::npos && m_strPath.GetAt(stIndex) == _T('.')) + return PathFromWString(m_strPath.MidRange(stIndex, m_strPath.GetLength())); // ".txt" for "c:\windows\test.txt" - if(stIndex != TString::npos && m_pPath->m_strPath.GetAt(stIndex) == _T('.')) - return PathFromWString(m_pPath->m_strPath.MidRange(stIndex, m_pPath->m_strPath.GetLength())); // ".txt" for "c:\windows\test.txt" - return TSmartPath(); } @@ -891,14 +707,11 @@ // ============================================================================ bool TSmartPath::HasFileName() const { - if(!m_pPath) - return false; - - size_t stIndex = m_pPath->m_strPath.FindLastOf(_T("\\/")); + size_t stIndex = m_strPath.FindLastOf(_T("\\/")); if(stIndex == TString::npos) // no path separator? return true; else - return (stIndex != TString::npos && stIndex != m_pPath->m_strPath.GetLength() - 1); + return (stIndex != TString::npos && stIndex != m_strPath.GetLength() - 1); } // ============================================================================ @@ -910,12 +723,9 @@ // ============================================================================ TSmartPath TSmartPath::GetFileName() const { - if(!m_pPath) - return TSmartPath(); - - size_t stIndex = m_pPath->m_strPath.FindLastOf(_T("\\/")); + size_t stIndex = m_strPath.FindLastOf(_T("\\/")); if(stIndex != TString::npos) - return PathFromWString(m_pPath->m_strPath.MidRange(stIndex + 1, m_pPath->m_strPath.GetLength())); // "test.txt" for "c:\windows\test.txt" + return PathFromWString(m_strPath.MidRange(stIndex + 1, m_strPath.GetLength())); // "test.txt" for "c:\windows\test.txt" else return *this; } @@ -928,15 +738,9 @@ // ============================================================================ void TSmartPath::DeleteFileName() { - if(!m_pPath) - return; - - size_t stIndex = m_pPath->m_strPath.FindLastOf(_T("\\/")); + size_t stIndex = m_strPath.FindLastOf(_T("\\/")); if(stIndex != TString::npos) - { - PrepareToWrite(); - m_pPath->m_strPath.Delete(stIndex + 1, m_pPath->m_strPath.GetLength() - stIndex - 1); // "test.txt" for "c:\windows\test.txt" - } + m_strPath.Delete(stIndex + 1, m_strPath.GetLength() - stIndex - 1); // "test.txt" for "c:\windows\test.txt" else { // no path separator inside - everything in this path is a filename @@ -953,13 +757,10 @@ // ============================================================================ bool TSmartPath::EndsWithSeparator() const { - if(!m_pPath) - return false; - - size_t stThisSize = m_pPath->m_strPath.GetLength(); + size_t stThisSize = m_strPath.GetLength(); if(stThisSize > 0) { - wchar_t wchLastChar = m_pPath->m_strPath.GetAt(stThisSize - 1); + wchar_t wchLastChar = m_strPath.GetAt(stThisSize - 1); return (wchLastChar == _T('\\') || wchLastChar == _T('/')); } @@ -975,10 +776,7 @@ void TSmartPath::AppendSeparatorIfDoesNotExist() { if(!EndsWithSeparator()) - { - PrepareToWrite(); - m_pPath->m_strPath += _T("\\"); - } + m_strPath += _T("\\"); } // ============================================================================ @@ -990,10 +788,7 @@ void TSmartPath::StripSeparatorAtEnd() { if(EndsWithSeparator()) - { - PrepareToWrite(); - m_pPath->m_strPath.Delete(m_pPath->m_strPath.GetLength() - 1, 1); - } + m_strPath.Delete(m_strPath.GetLength() - 1, 1); } // ============================================================================ @@ -1005,12 +800,9 @@ // ============================================================================ bool TSmartPath::StartsWithSeparator() const { - if(!m_pPath) - return false; - wchar_t wchLastChar = 0; - if(m_pPath->m_strPath.GetLength() > 0) - wchLastChar = m_pPath->m_strPath.GetAt(0); + if(m_strPath.GetLength() > 0) + wchLastChar = m_strPath.GetAt(0); return (wchLastChar == _T('\\') || wchLastChar == _T('/')); } @@ -1024,10 +816,7 @@ void TSmartPath::PrependSeparatorIfDoesNotExist() { if(!StartsWithSeparator()) - { - PrepareToWrite(); - m_pPath->m_strPath = _T("\\") + m_pPath->m_strPath; - } + m_strPath = _T("\\") + m_strPath; } // ============================================================================ @@ -1039,11 +828,7 @@ void TSmartPath::StripSeparatorAtFront() { if(StartsWithSeparator()) - { - PrepareToWrite(); - - m_pPath->m_strPath.Delete(0, 1); - } + m_strPath.Delete(0, 1); } // ============================================================================ @@ -1054,7 +839,7 @@ // ============================================================================ bool TSmartPath::IsEmpty() const { - return !m_pPath || m_pPath->m_strPath.IsEmpty(); + return m_strPath.IsEmpty(); } // ============================================================================ @@ -1066,32 +851,10 @@ // ============================================================================ size_t TSmartPath::GetLength() const { - if(!m_pPath) - return 0; - return m_pPath->m_strPath.GetLength(); + return m_strPath.GetLength(); } // ============================================================================ -/// TSmartPath::AppendIfNotExists -/// @date 2009/11/29 -/// -/// @brief Prepares the path to be written to. -// ============================================================================ -void TSmartPath::PrepareToWrite() -{ - if(m_pPath && m_pPath->IsShared()) - { - details::TPath* pPath = m_pPath->Clone(); - Clear(); - m_pPath = pPath; - } - - // create new internal path if does not exist - if(!m_pPath) - m_pPath = details::TPath::New(); -} - -// ============================================================================ /// chcore::TSmartPath::IsSeparator /// @date 2010/10/17 /// Index: src/libchcore/TPath.h =================================================================== diff -u -rb1e03eb232a784d6e2d40f67cbbbb33be0972228 -r7b830c34855c8aaa81aac2c6e0ca0fa6bae95e66 --- src/libchcore/TPath.h (.../TPath.h) (revision b1e03eb232a784d6e2d40f67cbbbb33be0972228) +++ src/libchcore/TPath.h (.../TPath.h) (revision 7b830c34855c8aaa81aac2c6e0ca0fa6bae95e66) @@ -27,35 +27,6 @@ class TSmartPath; class TPathContainer; -namespace details -{ - class TPath - { - public: - TPath(); - TPath(const TPath& rSrc); - ~TPath(); - - long AddRef() { return ++m_lRefCount; } - long Release(); - bool IsShared() const { return m_lRefCount > 1; } - - protected: - static TPath* New(); - TPath* Clone(); - static void Delete(TPath* pPath); - - protected: -#pragma warning(push) -#pragma warning(disable: 4251) - TString m_strPath; -#pragma warning(pop) - long m_lRefCount; - - friend class TSmartPath; - }; -} - class LIBCHCORE_API TSmartPath { protected: @@ -143,12 +114,10 @@ size_t GetLength() const; protected: - void PrepareToWrite(); - static bool IsSeparator(wchar_t wchSeparator); protected: - details::TPath* m_pPath; + TString m_strPath; }; LIBCHCORE_API TSmartPath PathFromString(const wchar_t* pszPath); Index: src/libchcore/TPlainStringPool.cpp =================================================================== diff -u --- src/libchcore/TPlainStringPool.cpp (revision 0) +++ src/libchcore/TPlainStringPool.cpp (revision 7b830c34855c8aaa81aac2c6e0ca0fa6bae95e66) @@ -0,0 +1,96 @@ +// ============================================================================ +// Copyright (C) 2001-2014 by Jozef Starosczyk +// ixen@copyhandler.com +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU Library General Public License +// (version 2) as published by the Free Software Foundation; +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this program; if not, write to the +// Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// ============================================================================ +#include "stdafx.h" +#include "TPlainStringPool.h" +#include "TCoreException.h" +#include "ErrorCodes.h" + +BEGIN_CHCORE_NAMESPACE + +TPlainStringPool::TPlainStringPool() +{ +} + +TPlainStringPool::~TPlainStringPool() +{ + Clear(); +} + +wchar_t* TPlainStringPool::Alloc(size_t stCount) +{ + if(stCount > BlockSize) + THROW_CORE_EXCEPTION(eErr_InvalidArgument); + + // find block where the new string would fit + size_t stBlockCount = m_vBlocks.size(); + for(size_t stIndex = 0; stIndex < stBlockCount; ++stIndex) + { + if(m_vBlocks[stIndex].second >= stCount) + { + wchar_t* pszResult = m_vBlocks[stIndex].first + BlockSize - m_vBlocks[stIndex].second; + m_vBlocks[stIndex].second -= stCount; + return pszResult; + } + } + + wchar_t* pszBuffer = AllocNewBlock(); + m_vBlocks.back().second -= stCount; + + return pszBuffer; +} + +wchar_t* TPlainStringPool::AllocForString(const wchar_t* pszString) +{ + size_t stLen = wcslen(pszString) + 1; + + wchar_t* pszBuffer = Alloc(stLen); + wmemcpy_s(pszBuffer, BlockSize, pszString, stLen); + + return pszBuffer; +} + +void TPlainStringPool::Clear(bool bLeaveSingleEmptyBlock) +{ + size_t stBlockCount = m_vBlocks.size(); + for(size_t stIndex = 0; stIndex < stBlockCount; ++stIndex) + { + if(!bLeaveSingleEmptyBlock || stIndex != 0) + { + delete [] m_vBlocks[stIndex].first; + } + } + + if(bLeaveSingleEmptyBlock) + { + if(m_vBlocks.size() > 1) + m_vBlocks.erase(m_vBlocks.begin() + 1, m_vBlocks.end()); + } + else + m_vBlocks.clear(); +} + +wchar_t* TPlainStringPool::AllocNewBlock() +{ + wchar_t* pszBlock = new wchar_t[BlockSize]; + m_vBlocks.push_back(std::make_pair(pszBlock, BlockSize)); + + return pszBlock; +} + +END_CHCORE_NAMESPACE Index: src/libchcore/TPlainStringPool.h =================================================================== diff -u --- src/libchcore/TPlainStringPool.h (revision 0) +++ src/libchcore/TPlainStringPool.h (revision 7b830c34855c8aaa81aac2c6e0ca0fa6bae95e66) @@ -0,0 +1,52 @@ +// ============================================================================ +// Copyright (C) 2001-2014 by Jozef Starosczyk +// ixen@copyhandler.com +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU Library General Public License +// (version 2) as published by the Free Software Foundation; +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this program; if not, write to the +// Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// ============================================================================ +#ifndef __TPLAINSTRINGPOOL_H__ +#define __TPLAINSTRINGPOOL_H__ + +#include "libchcore.h" + +BEGIN_CHCORE_NAMESPACE + +class LIBCHCORE_API TPlainStringPool +{ +public: + static const size_t BlockSize = 256*1024; + +public: + TPlainStringPool(); + ~TPlainStringPool(); + + wchar_t* Alloc(size_t stCount); + wchar_t* AllocForString(const wchar_t* pszString); + + void Clear(bool bLeaveSingleEmptyBlock = true); + +private: + wchar_t* AllocNewBlock(); + +private: +#pragma warning(push) +#pragma warning(disable: 4251) + std::vector > m_vBlocks; // memory blocks of size BlockSize => remaining size +#pragma warning(pop) +}; + +END_CHCORE_NAMESPACE + +#endif Index: src/libchcore/TSQLiteColumnDefinition.cpp =================================================================== diff -u -rffdee64cb0f2d472bb4102abe80ee12783e794c8 -r7b830c34855c8aaa81aac2c6e0ca0fa6bae95e66 --- src/libchcore/TSQLiteColumnDefinition.cpp (.../TSQLiteColumnDefinition.cpp) (revision ffdee64cb0f2d472bb4102abe80ee12783e794c8) +++ src/libchcore/TSQLiteColumnDefinition.cpp (.../TSQLiteColumnDefinition.cpp) (revision 7b830c34855c8aaa81aac2c6e0ca0fa6bae95e66) @@ -42,7 +42,7 @@ m_vColumns.clear(); } -size_t TSQLiteColumnsDefinition::GetColumnIndex(const TString& strColumnName) +size_t TSQLiteColumnsDefinition::GetColumnIndex(const wchar_t* strColumnName) { size_t stPos = 0; for(VecColumns::const_iterator iterFnd = m_vColumns.begin(); iterFnd != m_vColumns.end(); ++iterFnd) @@ -55,7 +55,7 @@ THROW_CORE_EXCEPTION(eErr_BoundsExceeded); } -TString TSQLiteColumnsDefinition::GetColumnName(size_t stIndex) const +const TString& TSQLiteColumnsDefinition::GetColumnName(size_t stIndex) const { return m_vColumns.at(stIndex).first; } Index: src/libchcore/TSQLiteColumnDefinition.h =================================================================== diff -u -rffdee64cb0f2d472bb4102abe80ee12783e794c8 -r7b830c34855c8aaa81aac2c6e0ca0fa6bae95e66 --- src/libchcore/TSQLiteColumnDefinition.h (.../TSQLiteColumnDefinition.h) (revision ffdee64cb0f2d472bb4102abe80ee12783e794c8) +++ src/libchcore/TSQLiteColumnDefinition.h (.../TSQLiteColumnDefinition.h) (revision 7b830c34855c8aaa81aac2c6e0ca0fa6bae95e66) @@ -35,9 +35,9 @@ virtual size_t AddColumn(const TString& strColumnName, ETypes eColType); virtual void Clear(); - virtual size_t GetColumnIndex(const TString& strColumnName); + virtual size_t GetColumnIndex(const wchar_t* strColumnName); virtual ETypes GetColumnType(size_t stIndex) const; - virtual TString GetColumnName(size_t stIndex) const; + virtual const TString& GetColumnName(size_t stIndex) const; virtual size_t GetCount() const; virtual bool IsEmpty() const; Index: src/libchcore/TSQLiteSerializer.cpp =================================================================== diff -u -rc8e73b75027d5e17fb8b1e1eb40e64f40fc62547 -r7b830c34855c8aaa81aac2c6e0ca0fa6bae95e66 --- src/libchcore/TSQLiteSerializer.cpp (.../TSQLiteSerializer.cpp) (revision c8e73b75027d5e17fb8b1e1eb40e64f40fc62547) +++ src/libchcore/TSQLiteSerializer.cpp (.../TSQLiteSerializer.cpp) (revision 7b830c34855c8aaa81aac2c6e0ca0fa6bae95e66) @@ -43,13 +43,20 @@ m_spSchema->Setup(m_spDatabase); } +TSQLiteSerializer::~TSQLiteSerializer() +{ + // clear the containers first, so that we can safely get rid of the strings pool + m_mapContainers.clear(); + m_poolStrings.Clear(false); +} + ISerializerContainerPtr TSQLiteSerializer::GetContainer(const TString& strContainerName) { ContainerMap::iterator iterMap = m_mapContainers.find(strContainerName); if(iterMap == m_mapContainers.end()) iterMap = m_mapContainers.insert(std::make_pair( strContainerName, - TSQLiteSerializerContainerPtr(new TSQLiteSerializerContainer(strContainerName, m_spDatabase)))).first; + TSQLiteSerializerContainerPtr(new TSQLiteSerializerContainer(strContainerName, m_spDatabase, m_poolStrings)))).first; return iterMap->second; } @@ -80,6 +87,7 @@ DBTRACE2(_T(" ## Serializer::Flush() - container flushes: %I64u ms, transaction commit: %I64u ms\n"), ullFlushGatherTime, ullFlushCommitTime); m_mapContainers.clear(); + m_poolStrings.Clear(); unsigned long long ullFlushClearTime = timer.Checkpoint(); ullFlushClearTime; DBTRACE1(_T(" ## Serializer::Flush() - container clearing: %I64u ms\n"), ullFlushClearTime); Index: src/libchcore/TSQLiteSerializer.h =================================================================== diff -u -r5693271a6736f524997e3951fc7b7b6323bc6447 -r7b830c34855c8aaa81aac2c6e0ca0fa6bae95e66 --- src/libchcore/TSQLiteSerializer.h (.../TSQLiteSerializer.h) (revision 5693271a6736f524997e3951fc7b7b6323bc6447) +++ src/libchcore/TSQLiteSerializer.h (.../TSQLiteSerializer.h) (revision 7b830c34855c8aaa81aac2c6e0ca0fa6bae95e66) @@ -28,13 +28,15 @@ #include "TPath.h" #include "TSQLiteSerializerContainer.h" #include "ISQLiteSerializerSchema.h" +#include "TPlainStringPool.h" BEGIN_CHCORE_NAMESPACE class LIBCHCORE_API TSQLiteSerializer : public ISerializer { public: TSQLiteSerializer(const TSmartPath& pathDB, const ISerializerSchemaPtr& spSchema); + virtual ~TSQLiteSerializer(); virtual TSmartPath GetLocation() const; @@ -50,6 +52,8 @@ typedef std::map ContainerMap; ContainerMap m_mapContainers; + + TPlainStringPool m_poolStrings; #pragma warning(pop) }; Index: src/libchcore/TSQLiteSerializerContainer.cpp =================================================================== diff -u -rffdee64cb0f2d472bb4102abe80ee12783e794c8 -r7b830c34855c8aaa81aac2c6e0ca0fa6bae95e66 --- src/libchcore/TSQLiteSerializerContainer.cpp (.../TSQLiteSerializerContainer.cpp) (revision ffdee64cb0f2d472bb4102abe80ee12783e794c8) +++ src/libchcore/TSQLiteSerializerContainer.cpp (.../TSQLiteSerializerContainer.cpp) (revision 7b830c34855c8aaa81aac2c6e0ca0fa6bae95e66) @@ -33,10 +33,11 @@ using namespace sqlite; -TSQLiteSerializerContainer::TSQLiteSerializerContainer(const TString& strName, const sqlite::TSQLiteDatabasePtr& spDB) : +TSQLiteSerializerContainer::TSQLiteSerializerContainer(const TString& strName, const sqlite::TSQLiteDatabasePtr& spDB, TPlainStringPool& poolStrings) : m_strName(strName), m_spDB(spDB), - m_pPoolRows(NULL) + m_pPoolRows(NULL), + m_poolStrings(poolStrings) { } @@ -58,7 +59,7 @@ if(!pMemoryBlock) THROW_SERIALIZER_EXCEPTION(eErr_InternalProblem, _T("Cannot allocate memory")); - iterFnd = m_mapRows.insert(std::make_pair(stRowID, TSQLiteSerializerRowData(stRowID, m_tColumns, bMarkAsAdded, (unsigned long long*)pMemoryBlock, GetPool().get_requested_size()))).first; + iterFnd = m_mapRows.insert(std::make_pair(stRowID, TSQLiteSerializerRowData(stRowID, m_tColumns, bMarkAsAdded, (unsigned long long*)pMemoryBlock, GetPool().get_requested_size(), m_poolStrings))).first; } else if(bMarkAsAdded) iterFnd->second.MarkAsAdded(); Index: src/libchcore/TSQLiteSerializerContainer.h =================================================================== diff -u -rffdee64cb0f2d472bb4102abe80ee12783e794c8 -r7b830c34855c8aaa81aac2c6e0ca0fa6bae95e66 --- src/libchcore/TSQLiteSerializerContainer.h (.../TSQLiteSerializerContainer.h) (revision ffdee64cb0f2d472bb4102abe80ee12783e794c8) +++ src/libchcore/TSQLiteSerializerContainer.h (.../TSQLiteSerializerContainer.h) (revision 7b830c34855c8aaa81aac2c6e0ca0fa6bae95e66) @@ -34,8 +34,12 @@ class LIBCHCORE_API TSQLiteSerializerContainer : public ISerializerContainer { +private: + TSQLiteSerializerContainer(const TSQLiteSerializerContainer&); + TSQLiteSerializerContainer& operator=(const TSQLiteSerializerContainer&); + public: - TSQLiteSerializerContainer(const TString& strName, const sqlite::TSQLiteDatabasePtr& spDB); + TSQLiteSerializerContainer(const TString& strName, const sqlite::TSQLiteDatabasePtr& spDB, TPlainStringPool& poolStrings); virtual ~TSQLiteSerializerContainer(); virtual IColumnsDefinition& GetColumnsDefinition(); @@ -67,6 +71,8 @@ TString m_strName; sqlite::TSQLiteDatabasePtr m_spDB; + + TPlainStringPool& m_poolStrings; #pragma warning(pop) }; Index: src/libchcore/TSQLiteSerializerRowData.cpp =================================================================== diff -u -rffdee64cb0f2d472bb4102abe80ee12783e794c8 -r7b830c34855c8aaa81aac2c6e0ca0fa6bae95e66 --- src/libchcore/TSQLiteSerializerRowData.cpp (.../TSQLiteSerializerRowData.cpp) (revision ffdee64cb0f2d472bb4102abe80ee12783e794c8) +++ src/libchcore/TSQLiteSerializerRowData.cpp (.../TSQLiteSerializerRowData.cpp) (revision 7b830c34855c8aaa81aac2c6e0ca0fa6bae95e66) @@ -23,13 +23,15 @@ #include "TSerializerException.h" #include "ErrorCodes.h" #include "SerializerTrace.h" +#include "TPlainStringPool.h" BEGIN_CHCORE_NAMESPACE /////////////////////////////////////////////////////////////////////////// -TSQLiteSerializerRowData::TSQLiteSerializerRowData(size_t stRowID, TSQLiteColumnsDefinition& rColumnDefinition, bool bAdded, unsigned long long* pPoolMemory, size_t stPoolMemorySizeInBytes) : +TSQLiteSerializerRowData::TSQLiteSerializerRowData(size_t stRowID, TSQLiteColumnsDefinition& rColumnDefinition, bool bAdded, unsigned long long* pPoolMemory, size_t stPoolMemorySizeInBytes, TPlainStringPool& poolStrings) : m_rColumns(rColumnDefinition), - m_pPoolMemory(pPoolMemory) + m_pPoolMemory(pPoolMemory), + m_poolStrings(poolStrings) { if(!m_pPoolMemory) THROW_SERIALIZER_EXCEPTION(eErr_InvalidArgument, _T("Null memory provided")); @@ -49,15 +51,13 @@ TSQLiteSerializerRowData::TSQLiteSerializerRowData(const TSQLiteSerializerRowData& rSrc) : m_rColumns(rSrc.m_rColumns), - m_pPoolMemory(rSrc.m_pPoolMemory) + m_pPoolMemory(rSrc.m_pPoolMemory), + m_poolStrings(rSrc.m_poolStrings) { } TSQLiteSerializerRowData::~TSQLiteSerializerRowData() { - // do not delete m_pPoolMemory as it does not belong to us - // but delete all additional memory allocated for items - FreeAllColumnData(); } ISerializerRowData& TSQLiteSerializerRowData::SetValue(size_t stColIndex, bool bValue) @@ -160,9 +160,7 @@ ModifyColumnData(stColIndex) = (unsigned long long)0; else { - const size_t stBufferChars = strValue.GetLength() + 1; - wchar_t* pszBuffer = new wchar_t[stBufferChars]; - wcsncpy_s(pszBuffer, stBufferChars, (const wchar_t*)strValue, stBufferChars); + wchar_t* pszBuffer = m_poolStrings.AllocForString(strValue); ModifyColumnData(stColIndex) = (unsigned long long)(void*)pszBuffer; } @@ -178,71 +176,69 @@ ModifyColumnData(stColIndex) = (unsigned long long)0; else { - const size_t stBufferChars = pathValue.GetLength() + 1; - wchar_t* pszBuffer = new wchar_t[stBufferChars]; - wcsncpy_s(pszBuffer, stBufferChars, pathValue.ToString(), stBufferChars); + wchar_t* pszBuffer = m_poolStrings.AllocForString(pathValue.ToString()); ModifyColumnData(stColIndex) = (unsigned long long)(void*)pszBuffer; } return *this; } -ISerializerRowData& TSQLiteSerializerRowData::SetValue(const TString& strColumnName, bool bValue) +ISerializerRowData& TSQLiteSerializerRowData::SetValue(const wchar_t* strColumnName, bool bValue) { return SetValue(m_rColumns.GetColumnIndex(strColumnName), bValue); } -ISerializerRowData& TSQLiteSerializerRowData::SetValue(const TString& strColumnName, short iValue) +ISerializerRowData& TSQLiteSerializerRowData::SetValue(const wchar_t* strColumnName, short iValue) { return SetValue(m_rColumns.GetColumnIndex(strColumnName), iValue); } -ISerializerRowData& TSQLiteSerializerRowData::SetValue(const TString& strColumnName, unsigned short uiValue) +ISerializerRowData& TSQLiteSerializerRowData::SetValue(const wchar_t* strColumnName, unsigned short uiValue) { return SetValue(m_rColumns.GetColumnIndex(strColumnName), uiValue); } -ISerializerRowData& TSQLiteSerializerRowData::SetValue(const TString& strColumnName, int iValue) +ISerializerRowData& TSQLiteSerializerRowData::SetValue(const wchar_t* strColumnName, int iValue) { return SetValue(m_rColumns.GetColumnIndex(strColumnName), iValue); } -ISerializerRowData& TSQLiteSerializerRowData::SetValue(const TString& strColumnName, unsigned int uiValue) +ISerializerRowData& TSQLiteSerializerRowData::SetValue(const wchar_t* strColumnName, unsigned int uiValue) { return SetValue(m_rColumns.GetColumnIndex(strColumnName), uiValue); } -ISerializerRowData& TSQLiteSerializerRowData::SetValue(const TString& strColumnName, long lValue) +ISerializerRowData& TSQLiteSerializerRowData::SetValue(const wchar_t* strColumnName, long lValue) { return SetValue(m_rColumns.GetColumnIndex(strColumnName), lValue); } -ISerializerRowData& TSQLiteSerializerRowData::SetValue(const TString& strColumnName, unsigned long ulValue) +ISerializerRowData& TSQLiteSerializerRowData::SetValue(const wchar_t* strColumnName, unsigned long ulValue) { return SetValue(m_rColumns.GetColumnIndex(strColumnName), ulValue); } -ISerializerRowData& TSQLiteSerializerRowData::SetValue(const TString& strColumnName, long long llValue) +ISerializerRowData& TSQLiteSerializerRowData::SetValue(const wchar_t* strColumnName, long long llValue) { return SetValue(m_rColumns.GetColumnIndex(strColumnName), llValue); } -ISerializerRowData& TSQLiteSerializerRowData::SetValue(const TString& strColumnName, unsigned long long llValue) +ISerializerRowData& TSQLiteSerializerRowData::SetValue(const wchar_t* strColumnName, unsigned long long llValue) { return SetValue(m_rColumns.GetColumnIndex(strColumnName), llValue); } -ISerializerRowData& TSQLiteSerializerRowData::SetValue(const TString& strColumnName, double dValue) +ISerializerRowData& TSQLiteSerializerRowData::SetValue(const wchar_t* strColumnName, double dValue) { return SetValue(m_rColumns.GetColumnIndex(strColumnName), dValue); } -ISerializerRowData& TSQLiteSerializerRowData::SetValue(const TString& strColumnName, const TString& strValue) +ISerializerRowData& TSQLiteSerializerRowData::SetValue(const wchar_t* strColumnName, const TString& strValue) { return SetValue(m_rColumns.GetColumnIndex(strColumnName), strValue); } -ISerializerRowData& TSQLiteSerializerRowData::SetValue(const TString& strColumnName, const TSmartPath& pathValue) +ISerializerRowData& TSQLiteSerializerRowData::SetValue(const wchar_t* strColumnName, const TSmartPath& pathValue) { return SetValue(m_rColumns.GetColumnIndex(strColumnName), pathValue); } @@ -476,17 +472,17 @@ case IColumnsDefinition::eType_string: { - const wchar_t* pszValue = (const wchar_t*)(unsigned long long*)&GetDataForColumn(stColumn); - DBTRACE1_D(_T("- param(string): %s\n"), pszValue); - tStatement.BindValue(iSQLiteColumnNumber++, pszValue); + const wchar_t* pszValue = (const wchar_t*)(unsigned long long*)GetDataForColumn(stColumn); + DBTRACE1_D(_T("- param(string): %s\n"), pszValue ? pszValue : _T("")); + tStatement.BindValue(iSQLiteColumnNumber++, pszValue ? pszValue : _T("")); break; } case IColumnsDefinition::eType_path: { - const wchar_t* pszValue = (const wchar_t*)(unsigned long long*)&GetDataForColumn(stColumn); - DBTRACE1_D(_T("- param(path): %s\n"), pszValue); - tStatement.BindValue(iSQLiteColumnNumber++, PathFromString(pszValue)); + const wchar_t* pszValue = (const wchar_t*)(unsigned long long*)GetDataForColumn(stColumn); + DBTRACE1_D(_T("- param(path): %s\n"), pszValue ? pszValue : _T("")); + tStatement.BindValue(iSQLiteColumnNumber++, pszValue ? PathFromString(pszValue) : TSmartPath()); break; } @@ -513,9 +509,6 @@ case IColumnsDefinition::eType_string: { unsigned long long& ullColumnData = m_pPoolMemory[stColumnID + 1]; - wchar_t* pszData = (wchar_t*)ullColumnData; - delete [] pszData; - ullColumnData = 0ULL; break; Index: src/libchcore/TSQLiteSerializerRowData.h =================================================================== diff -u -rffdee64cb0f2d472bb4102abe80ee12783e794c8 -r7b830c34855c8aaa81aac2c6e0ca0fa6bae95e66 --- src/libchcore/TSQLiteSerializerRowData.h (.../TSQLiteSerializerRowData.h) (revision ffdee64cb0f2d472bb4102abe80ee12783e794c8) +++ src/libchcore/TSQLiteSerializerRowData.h (.../TSQLiteSerializerRowData.h) (revision 7b830c34855c8aaa81aac2c6e0ca0fa6bae95e66) @@ -31,13 +31,15 @@ BEGIN_CHCORE_NAMESPACE +class TPlainStringPool; + class LIBCHCORE_API TSQLiteSerializerRowData : public ISerializerRowData { private: static const unsigned long long AddedBit = 1; private: - TSQLiteSerializerRowData(size_t stRowID, TSQLiteColumnsDefinition& rColumnDefinition, bool bAdded, unsigned long long* pPoolMemory, size_t stPoolMemorySizeInBytes); + TSQLiteSerializerRowData(size_t stRowID, TSQLiteColumnsDefinition& rColumnDefinition, bool bAdded, unsigned long long* pPoolMemory, size_t stPoolMemorySizeInBytes, TPlainStringPool& poolStrings); public: TSQLiteSerializerRowData(const TSQLiteSerializerRowData& rSrc); @@ -58,18 +60,18 @@ virtual ISerializerRowData& SetValue(size_t stColIndex, const TString& strValue); virtual ISerializerRowData& SetValue(size_t stColIndex, const TSmartPath& pathValue); - virtual ISerializerRowData& SetValue(const TString& strColumnName, bool bValue); - virtual ISerializerRowData& SetValue(const TString& strColumnName, short iValue); - virtual ISerializerRowData& SetValue(const TString& strColumnName, unsigned short uiValue); - virtual ISerializerRowData& SetValue(const TString& strColumnName, int iValue); - virtual ISerializerRowData& SetValue(const TString& strColumnName, unsigned int uiValue); - virtual ISerializerRowData& SetValue(const TString& strColumnName, long lValue); - virtual ISerializerRowData& SetValue(const TString& strColumnName, unsigned long ulValue); - virtual ISerializerRowData& SetValue(const TString& strColumnName, long long llValue); - virtual ISerializerRowData& SetValue(const TString& strColumnName, unsigned long long llValue); - virtual ISerializerRowData& SetValue(const TString& strColumnName, double dValue); - virtual ISerializerRowData& SetValue(const TString& strColumnName, const TString& strValue); - virtual ISerializerRowData& SetValue(const TString& strColumnName, const TSmartPath& pathValue); + virtual ISerializerRowData& SetValue(const wchar_t* strColumnName, bool bValue); + virtual ISerializerRowData& SetValue(const wchar_t* strColumnName, short iValue); + virtual ISerializerRowData& SetValue(const wchar_t* strColumnName, unsigned short uiValue); + virtual ISerializerRowData& SetValue(const wchar_t* strColumnName, int iValue); + virtual ISerializerRowData& SetValue(const wchar_t* strColumnName, unsigned int uiValue); + virtual ISerializerRowData& SetValue(const wchar_t* strColumnName, long lValue); + virtual ISerializerRowData& SetValue(const wchar_t* strColumnName, unsigned long ulValue); + virtual ISerializerRowData& SetValue(const wchar_t* strColumnName, long long llValue); + virtual ISerializerRowData& SetValue(const wchar_t* strColumnName, unsigned long long llValue); + virtual ISerializerRowData& SetValue(const wchar_t* strColumnName, double dValue); + virtual ISerializerRowData& SetValue(const wchar_t* strColumnName, const TString& strValue); + virtual ISerializerRowData& SetValue(const wchar_t* strColumnName, const TSmartPath& pathValue); TString GetQuery(const TString& strContainerName) const; unsigned long long GetChangeIdentification() const; @@ -96,6 +98,7 @@ unsigned long long* m_pPoolMemory; TSQLiteColumnsDefinition& m_rColumns; + TPlainStringPool& m_poolStrings; friend class TSQLiteSerializerContainer; }; Index: src/libchcore/TString.cpp =================================================================== diff -u -rb1e03eb232a784d6e2d40f67cbbbb33be0972228 -r7b830c34855c8aaa81aac2c6e0ca0fa6bae95e66 --- src/libchcore/TString.cpp (.../TString.cpp) (revision b1e03eb232a784d6e2d40f67cbbbb33be0972228) +++ src/libchcore/TString.cpp (.../TString.cpp) (revision 7b830c34855c8aaa81aac2c6e0ca0fa6bae95e66) @@ -40,89 +40,11 @@ BEGIN_CHCORE_NAMESPACE -namespace details -{ - TInternalStringData::TInternalStringData() : - m_lRefCount(1), - m_stStringLength(0), - m_pszData(NULL), - m_stBufferSize(0) - { - } - - TInternalStringData::TInternalStringData(const TInternalStringData& rSrc, size_t stReserveLen) : - m_pszData(NULL), - m_stBufferSize(0), - m_stStringLength(0), - m_lRefCount(1) - { - Reserve(std::max(rSrc.m_stBufferSize, stReserveLen)); - - if(rSrc.m_pszData) - _tcsncpy_s(m_pszData, m_stBufferSize, rSrc.m_pszData, rSrc.m_stStringLength + 1); - else - m_pszData[0] = _T('\0'); - - m_stStringLength = rSrc.m_stStringLength; - } - - TInternalStringData::~TInternalStringData() - { - delete [] m_pszData; - } - - void TInternalStringData::Reserve(size_t stLen) - { - if(m_stBufferSize < stLen) - { - size_t stNewLen = ROUNDUP(stLen, CHUNK_INCSIZE); - - wchar_t* pszNewBuffer = new wchar_t[stNewLen]; - if(m_pszData) - _tcsncpy_s(pszNewBuffer, stNewLen, m_pszData, m_stStringLength + 1); - else - pszNewBuffer[0] = _T('\0'); - - delete [] m_pszData; - m_pszData = pszNewBuffer; - m_stBufferSize = stNewLen; - } - } - - void TInternalStringData::Clear() - { - delete [] m_pszData; - m_pszData = NULL; - m_stStringLength = 0; - m_stBufferSize = 0; - m_lRefCount = 0; - } - - void TInternalStringData::SetString(const wchar_t* pszString, size_t stCount) - { - Reserve(stCount + 1); // +1 - additional space for \0 - - wcsncpy_s(m_pszData, m_stBufferSize, pszString, stCount); - m_pszData[stCount] = _T('\0'); - m_stStringLength = _tcslen(m_pszData); // calculating length as we don't know if the input string did not have \0's inside - } - - void TInternalStringData::ClearString() - { - if(m_pszData) - m_pszData[0] = _T('\0'); - m_stStringLength = 0; - } -} - -using namespace details; - -const size_t TString::npos = std::numeric_limits::max(); - /** Standard constructor - allocates the underlying data object */ TString::TString() : - m_pData(new details::TInternalStringData) + m_pszData(NULL), + m_stBufferSize(0) { } @@ -131,17 +53,15 @@ * \param[in] pszStr - source unicode TString */ TString::TString(const wchar_t* pszStr) : - m_pData(new details::TInternalStringData) + m_pszData(NULL), + m_stBufferSize(0) { - if(pszStr == NULL) - return; - - size_t stLen = wcslen(pszStr); - m_pData->SetString(pszStr, stLen); + SetString(pszStr); } TString::TString(const wchar_t* pszStart, const wchar_t* pszEnd, size_t stMaxStringSize) : - m_pData(new details::TInternalStringData) + m_pszData(NULL), + m_stBufferSize(0) { // we support either both arguments != NULL or both == NULL if(pszEnd != NULL && pszStart == NULL || pszEnd == NULL && pszStart != NULL) @@ -155,43 +75,40 @@ if(stCount > stMaxStringSize) THROW_STRING_EXCEPTION(eErr_InvalidArgument, _T("Exceeded maximum expected string size")); - m_pData->SetString(pszStart, stCount); + SetString(pszStart, stCount); } TString::TString(const wchar_t* pszStart, size_t stCount) : - m_pData(new details::TInternalStringData) + m_pszData(NULL), + m_stBufferSize(0) { if(!pszStart) THROW_STRING_EXCEPTION(eErr_InvalidArgument, _T("String not specified")); if(stCount == 0) return; - m_pData->SetString(pszStart, stCount); + SetString(pszStart, stCount); } /** Constructor increases the reference count in the parameter's data object * and copies only the data object address. * \param[in] rSrc - source TString object */ TString::TString(const TString& rSrc) : - m_pData(NULL) + m_pszData(NULL), + m_stBufferSize(0) { - if(InterlockedCompareExchange(&rSrc.m_pData->m_lRefCount, 0, 0) > 0) - { - m_pData = rSrc.m_pData; - InterlockedIncrement(&m_pData->m_lRefCount); - } - else - m_pData = new details::TInternalStringData(*rSrc.m_pData); + SetString(rSrc.m_pszData); } /** Destructor releases the underlying data object. */ TString::~TString() { - if(InterlockedDecrement(&m_pData->m_lRefCount) < 1) - delete m_pData; + delete [] m_pszData; + m_pszData = NULL; + m_stBufferSize = 0; } /** Operator releases the current data object, stores a pointer to @@ -202,20 +119,9 @@ */ const TString& TString::operator=(const TString& rSrc) { - if(this != &rSrc && m_pData != rSrc.m_pData) - { - if(InterlockedDecrement(&m_pData->m_lRefCount) < 1) - delete m_pData; + if(this != &rSrc) + SetString(rSrc.m_pszData); - if(InterlockedCompareExchange(&rSrc.m_pData->m_lRefCount, 0, 0) > 0) - { - m_pData = rSrc.m_pData; - InterlockedIncrement(&m_pData->m_lRefCount); - } - else - m_pData = new details::TInternalStringData(*rSrc.m_pData); - } - return *this; } @@ -226,16 +132,9 @@ */ const TString& TString::operator=(const wchar_t* pszSrc) { - Release(); - if(!pszSrc) - { - m_pData->Clear(); - return *this; - } + if(pszSrc != m_pszData) + SetString(pszSrc); - size_t stLen = wcslen(pszSrc); - m_pData->SetString(pszSrc, stLen); - return *this; } @@ -293,24 +192,24 @@ */ size_t TString::GetLength() const { - return m_pData->m_stStringLength; + return m_pszData ? _tcslen(m_pszData) : 0; } /** Function makes own data object writable and clears it. Does not delete the * internal buffer - only sets the content to '\\0'. */ void TString::Clear() { - // make sure we have the modifiable object without allocated TString buffer - Release(); + if(m_pszData) + m_pszData[0] = L'\0'; } /** Function checks if the TString is empty. * \return True if this TString is empty, false otherwise. */ bool TString::IsEmpty() const { - return m_pData->m_stStringLength == 0; + return !m_pszData || m_pszData[0] == L'\0'; } /** Function merges the given unicode TString with the current content of an internal buffer. @@ -322,10 +221,11 @@ return; size_t stAddLen = wcslen(pszSrc); - EnsureWritable(m_pData->m_stStringLength + stAddLen + 1); + size_t stThisLen = GetLength(); - wcsncpy_s(m_pData->m_pszData + m_pData->m_stStringLength, m_pData->m_stBufferSize - m_pData->m_stStringLength, pszSrc, stAddLen + 1); - m_pData->m_stStringLength += stAddLen; + Reserve(stThisLen + stAddLen + 1); + + wcsncpy_s(m_pszData + stThisLen, m_stBufferSize - stThisLen, pszSrc, stAddLen + 1); } /** Function merges the given TString object with the current content of an internal buffer. @@ -337,10 +237,11 @@ return; size_t stAddLen = rSrc.GetLength(); - EnsureWritable(m_pData->m_stStringLength + stAddLen + 1); + size_t stThisLen = GetLength(); - wcsncpy_s(m_pData->m_pszData + m_pData->m_stStringLength, m_pData->m_stBufferSize - m_pData->m_stStringLength, rSrc.m_pData->m_pszData, stAddLen + 1); - m_pData->m_stStringLength += stAddLen; + Reserve(stThisLen + stAddLen + 1); + + wcsncpy_s(m_pszData + stThisLen, m_stBufferSize - stThisLen, rSrc.m_pszData, stAddLen + 1); } /** Returns a new TString object with the Left part of this TString object. @@ -349,13 +250,15 @@ */ TString TString::Left(size_t tLen) const { - if(m_pData->m_stStringLength == 0 || tLen == 0) + size_t stThisLen = GetLength(); + + if(stThisLen == 0 || tLen == 0) return TString(); - if(tLen >= m_pData->m_stStringLength) + if(tLen >= stThisLen) return *this; else - return TString(m_pData->m_pszData, tLen); + return TString(m_pszData, tLen); } /** Returns a new TString object with the Right part of this TString object. @@ -364,13 +267,15 @@ */ TString TString::Right(size_t tLen) const { - if(m_pData->m_stStringLength == 0 || tLen == 0) + size_t stThisLen = GetLength(); + + if(stThisLen == 0 || tLen == 0) return TString(); - if(tLen >= m_pData->m_stStringLength) + if(tLen >= stThisLen) return *this; else - return TString(m_pData->m_pszData + m_pData->m_stStringLength - tLen, tLen); + return TString(m_pszData + stThisLen - tLen, tLen); } /** Returns a new TString object with the middle part of this TString object. @@ -380,15 +285,17 @@ */ TString TString::Mid(size_t tStart, size_t tLen) const { - if(m_pData->m_stStringLength == 0 || tLen == 0) + size_t stThisLen = GetLength(); + + if(stThisLen == 0 || tLen == 0) return TString(); - if(tStart >= m_pData->m_stStringLength) + if(tStart >= stThisLen) return TString(); - size_t stRealLength = std::min(tLen, m_pData->m_stStringLength - tStart); + size_t stRealLength = std::min(tLen, stThisLen - tStart); - TString strNew(m_pData->m_pszData + tStart, stRealLength); + TString strNew(m_pszData + tStart, stRealLength); return strNew; } @@ -408,16 +315,14 @@ */ void TString::LeftSelf(size_t tLen) { + size_t stThisLen = GetLength(); + // nothing to do if nothing inside - if(m_pData->m_stStringLength == 0) + if(stThisLen == 0) return; - if(tLen < m_pData->m_stStringLength) // otherwise there is nothing to do - { - EnsureWritable(0); - m_pData->m_pszData[tLen] = _T('\0'); - m_pData->m_stStringLength = tLen; - } + if(tLen < stThisLen) // otherwise there is nothing to do + m_pszData[tLen] = _T('\0'); } /** Makes this TString it's Right part. Much faster than using standard @@ -429,17 +334,14 @@ */ void TString::RightSelf(size_t tLen) { + size_t stThisLen = GetLength(); + // nothing to do if nothing inside - if(m_pData->m_stStringLength == 0) + if(stThisLen == 0) return; - if(tLen < m_pData->m_stStringLength) // otherwise there is nothing to do - { - EnsureWritable(0); - - wmemmove(m_pData->m_pszData, m_pData->m_pszData + m_pData->m_stStringLength - tLen, tLen + 1); - m_pData->m_stStringLength = tLen; - } + if(tLen < stThisLen) // otherwise there is nothing to do + wmemmove(m_pszData, m_pszData + stThisLen - tLen, tLen + 1); } /** Makes this TString it's middle part. Much faster than using standard @@ -452,84 +354,75 @@ */ void TString::MidSelf(size_t tStart, size_t tLen) { - if(m_pData->m_stStringLength == 0) + size_t stThisLen = GetLength(); + + if(stThisLen == 0) return; - if(tStart >= m_pData->m_stStringLength) - { - EnsureWritable(0); - m_pData->ClearString(); - } + if(tStart >= stThisLen) + Clear(); else { - size_t stRealLength = std::min(tLen, m_pData->m_stStringLength - tStart); + size_t stRealNewLength = std::min(tLen, stThisLen - tStart); - EnsureWritable(stRealLength + 1); - wmemmove(m_pData->m_pszData, m_pData->m_pszData + tStart, stRealLength); - m_pData->m_pszData[stRealLength] = _T('\0'); - - m_pData->m_stStringLength = stRealLength; + wmemmove(m_pszData, m_pszData + tStart, stRealNewLength); + m_pszData[stRealNewLength] = _T('\0'); } } - void TString::TrimRightSelf(const wchar_t* pszElements) { if(!pszElements || pszElements[0] == L'\0') return; - if(m_pData->m_stStringLength == 0) + size_t stThisLen = GetLength(); + if(stThisLen == 0) return; - EnsureWritable(0); + size_t stLen = stThisLen; - size_t stLen = m_pData->m_stStringLength; - const wchar_t* pszElementsEnd = pszElements + wcslen(pszElements); while(stLen-- > 0) { - if(std::find(pszElements, pszElementsEnd, m_pData->m_pszData[stLen]) != pszElementsEnd) - { - m_pData->m_pszData[stLen] = _T('\0'); - m_pData->m_stStringLength = stLen; - } + if(std::find(pszElements, pszElementsEnd, m_pszData[stLen]) != pszElementsEnd) + m_pszData[stLen] = _T('\0'); else break; } } bool TString::Delete(size_t stIndex, size_t stCount) { - if(stIndex >= m_pData->m_stStringLength || stCount == 0) + size_t stThisLen = GetLength(); + + if(stIndex >= stThisLen || stCount == 0) return false; bool bResult = true; - if(stIndex + stCount > m_pData->m_stStringLength) // in case there is not enough data to delete, then we want to delete what we can, but return false + if(stIndex + stCount > stThisLen) // in case there is not enough data to delete, then we want to delete what we can, but return false bResult = false; - EnsureWritable(0); + size_t stCountToDelete = std::min(stThisLen - stIndex, stCount); - size_t stCountToDelete = std::min(m_pData->m_stStringLength - stIndex, stCount); - // should also copy the terminating null character - errno_t err = wmemmove_s(m_pData->m_pszData + stIndex, m_pData->m_stStringLength - stIndex + 1, m_pData->m_pszData + stIndex + stCountToDelete, m_pData->m_stStringLength - stIndex - stCountToDelete + 1); + errno_t err = wmemmove_s(m_pszData + stIndex, stThisLen - stIndex + 1, m_pszData + stIndex + stCountToDelete, stThisLen - stIndex - stCountToDelete + 1); if(err != 0) THROW_CORE_EXCEPTION(eErr_InternalProblem); - m_pData->m_stStringLength -= stCountToDelete; - return bResult; } void TString::Split(const wchar_t* pszSeparators, TStringArray& rStrings) const { rStrings.Clear(); - if(m_pData->m_stStringLength == 0 || !pszSeparators) + + size_t stThisLen = GetLength(); + if(stThisLen == 0 || !pszSeparators) return; // ugly version - many reallocations due to the usage of stl wstrings std::vector vStrings; - boost::split(vStrings, m_pData->m_pszData, boost::is_any_of(pszSeparators)); + boost::split(vStrings, m_pszData, boost::is_any_of(pszSeparators)); BOOST_FOREACH(const std::wstring& strPart, vStrings) { @@ -543,7 +436,7 @@ */ int_t TString::Compare(const wchar_t* psz) const { - return wcscmp(m_pData->m_pszData ? m_pData->m_pszData : L"", psz ? psz : L""); + return wcscmp(m_pszData ? m_pszData : L"", psz ? psz : L""); } /** Compares a TString with the given TString object. Comparison is case sensitive. @@ -552,7 +445,7 @@ */ int_t TString::Compare(const TString& str) const { - return Compare(str.m_pData->m_pszData); + return Compare(str.m_pszData); } /** Compares a TString with the given unicode TString. Comparison is case insensitive. @@ -561,7 +454,7 @@ */ int_t TString::CompareNoCase(const wchar_t* psz) const { - return _wcsicmp(m_pData->m_pszData ? m_pData->m_pszData : L"", psz ? psz : L""); + return _wcsicmp(m_pszData ? m_pszData : L"", psz ? psz : L""); } /** Compares a TString with the given TString object. Comparison is case insensitive. @@ -570,50 +463,50 @@ */ int_t TString::CompareNoCase(const TString& str) const { - return CompareNoCase(str.m_pData->m_pszData); + return CompareNoCase(str.m_pszData); } bool TString::StartsWith(const wchar_t* pszText) const { - if(!m_pData || !pszText) + if(!m_pszData || !pszText) return false; - return boost::starts_with(m_pData->m_pszData, pszText); + return boost::starts_with(m_pszData, pszText); } bool TString::StartsWithNoCase(const wchar_t* pszText) const { - if(!m_pData || !pszText) + if(!m_pszData || !pszText) return false; - return boost::istarts_with(m_pData->m_pszData, pszText); + return boost::istarts_with(m_pszData, pszText); } bool TString::EndsWith(const wchar_t* pszText) const { - if(!m_pData || !pszText) + if(!m_pszData || !pszText) return false; - return boost::ends_with(m_pData->m_pszData, pszText); + return boost::ends_with(m_pszData, pszText); } bool TString::EndsWithNoCase(const wchar_t* pszText) const { - if(!m_pData || !pszText) + if(!m_pszData || !pszText) return false; - return boost::iends_with(m_pData->m_pszData, pszText); + return boost::iends_with(m_pszData, pszText); } size_t TString::FindFirstOf(const wchar_t* pszChars, size_t stStartFromPos) const { - if(!m_pData || !pszChars) + if(!m_pszData || !pszChars) return npos; size_t stCurrentLength = GetLength(); for(size_t stIndex = stStartFromPos; stIndex < stCurrentLength; ++stIndex) { - if(wcschr(pszChars, m_pData->m_pszData[stIndex])) + if(wcschr(pszChars, m_pszData[stIndex])) return stIndex; } @@ -622,12 +515,12 @@ size_t TString::FindLastOf(const wchar_t* pszChars) const { - if(!m_pData || !pszChars) + if(!m_pszData || !pszChars) return npos; for(size_t stIndex = GetLength(); stIndex != 0; --stIndex) { - if(wcschr(pszChars, m_pData->m_pszData[stIndex - 1])) + if(wcschr(pszChars, m_pszData[stIndex - 1])) return stIndex - 1; } @@ -636,18 +529,18 @@ size_t TString::Find(const wchar_t* pszFindText, size_t stStartPos) { - if(!pszFindText || m_pData->m_stStringLength == 0) + size_t stThisLen = GetLength(); + if(!pszFindText || stThisLen == 0) return npos; size_t stFindTextLen = _tcslen(pszFindText); - size_t stThisLen = GetLength(); if(stFindTextLen > stThisLen) return TString::npos; if(stStartPos > stThisLen - stFindTextLen) return TString::npos; - boost::iterator_range rangeText = boost::make_iterator_range(m_pData->m_pszData + stStartPos, m_pData->m_pszData + stThisLen); + boost::iterator_range rangeText = boost::make_iterator_range(m_pszData + stStartPos, m_pszData + stThisLen); boost::iterator_range rangeFind = boost::find_first(rangeText, pszFindText); if(rangeFind.begin() != rangeText.end()) @@ -658,21 +551,18 @@ void TString::Replace(const wchar_t* pszWhat, const wchar_t* pszWithWhat) { - if(m_pData->m_stStringLength == 0) + size_t stThisLen = GetLength(); + if(stThisLen == 0) return; if(!pszWhat || !pszWithWhat) return; - // make sure nobody modifies the internal text while we process it - EnsureWritable(0); - // find all occurrences of pszWhat in this string, so we can calculate new required size of the string - size_t stCurrentLength = GetLength(); size_t stWhatLen = _tcslen(pszWhat); size_t stWithWhatLen = _tcslen(pszWithWhat); - size_t stNewLen = stCurrentLength; + size_t stNewLen = stThisLen; // resize internal string if needed if(stWithWhatLen > stWhatLen) @@ -687,10 +577,10 @@ } if(stSizeDiff > 0) - stNewLen = stCurrentLength + stSizeDiff + 1; + stNewLen = stThisLen + stSizeDiff + 1; } - EnsureWritable(stNewLen); + Reserve(stNewLen); // replace size_t stStartPos = 0; @@ -701,17 +591,14 @@ // found string pos is: [stFindPos, stFindPos + stWhatLen) -- sample ref: [3, 3 + 2) // we need to // - move string from position [stFindPos + stWhatLen, stCurrentLength) to position [stFindPos + stWithWhatLen, stCurrentLength + stWithWhatLen - stWhatLen] -- sample ref: [3+2, 6) to [3+1, 5) - size_t stCountToCopy = stCurrentLength - stFindPos - stWhatLen + 1; + size_t stCountToCopy = stThisLen - stFindPos - stWhatLen + 1; - memmove_s((void*)(m_pData->m_pszData + stFindPos + stWithWhatLen), stCountToCopy * sizeof(wchar_t), (void*)(m_pData->m_pszData + stFindPos + stWhatLen), stCountToCopy * sizeof(wchar_t)); + memmove_s((void*)(m_pszData + stFindPos + stWithWhatLen), stCountToCopy * sizeof(wchar_t), (void*)(m_pszData + stFindPos + stWhatLen), stCountToCopy * sizeof(wchar_t)); // - copy pszWithWhat to position (stFindPos + stWhatLen) - memcpy_s((void*)(m_pData->m_pszData + stFindPos), stWithWhatLen * sizeof(wchar_t), pszWithWhat, stWithWhatLen * sizeof(wchar_t)); + memcpy_s((void*)(m_pszData + stFindPos), stWithWhatLen * sizeof(wchar_t), pszWithWhat, stWithWhatLen * sizeof(wchar_t)); stStartPos = stFindPos + stWithWhatLen; // offset by stWithWhatLen because we replaced text - stCurrentLength = stCurrentLength + stWithWhatLen - stWhatLen; - - m_pData->m_stStringLength = stCurrentLength; } } @@ -724,9 +611,9 @@ */ bool TString::GetAt(size_t tPos, wchar_t& wch) const { - if(tPos < m_pData->m_stStringLength) + if(tPos < GetLength()) { - wch = m_pData->m_pszData[tPos]; + wch = m_pszData[tPos]; return true; } else @@ -738,8 +625,8 @@ wchar_t TString::GetAt(size_t tPos) const { - if(tPos < m_pData->m_stStringLength) - return m_pData->m_pszData[tPos]; + if(tPos < GetLength()) + return m_pszData[tPos]; else return L'\0'; } @@ -753,8 +640,9 @@ */ wchar_t* TString::GetBuffer(size_t tMinSize) { - EnsureUnshareable(tMinSize); - return m_pData->m_pszData; + Reserve(tMinSize + 1); + + return m_pszData; } /** Releases buffer got by user by calling get_bufferx functions. The current @@ -763,18 +651,14 @@ */ void TString::ReleaseBuffer() { - EnsureWritable(0); - - m_pData->m_pszData[m_pData->m_stBufferSize - 1] = L'\0'; - m_pData->m_stStringLength = wcslen(m_pData->m_pszData); + m_pszData[m_stBufferSize - 1] = L'\0'; } void TString::ReleaseBufferSetLength(size_t tSize) { - EnsureWritable(tSize + 1); + Reserve(tSize + 1); - m_pData->m_pszData[tSize] = L'\0'; - m_pData->m_stStringLength = tSize; + m_pszData[tSize] = L'\0'; } /** Cast operator - tries to return a pointer to wchar_t* using the current internal @@ -784,65 +668,51 @@ */ TString::operator const wchar_t*() const { - return m_pData->m_pszData ? m_pData->m_pszData : L""; + return m_pszData ? m_pszData : L""; } void TString::SetString(const wchar_t* pszStart, size_t stCount) { if(!pszStart || stCount == 0) - { - EnsureWritable(stCount); - m_pData->ClearString(); - } + Clear(); else { - EnsureWritable(stCount + 1); - m_pData->SetString(pszStart, stCount); + Reserve(stCount + 1); + + wcsncpy_s(m_pszData, m_stBufferSize, pszStart, stCount); + m_pszData[stCount] = _T('\0'); } } -void TString::EnsureWritable(size_t stRequestedSize) +void TString::SetString(const wchar_t* pszString) { - if(InterlockedCompareExchange(&m_pData->m_lRefCount, 1, 1) > 1) - { - TInternalStringData* pNewData = new TInternalStringData(*m_pData, stRequestedSize); - if(InterlockedDecrement(&m_pData->m_lRefCount) < 1) - { - delete pNewData; - m_pData->m_lRefCount = 1; - } - else - m_pData = pNewData; - } + if(!pszString) + Clear(); else { - m_pData->Reserve(stRequestedSize); - m_pData->m_lRefCount = 1; + size_t stLen = _tcslen(pszString); + SetString(pszString, stLen); } } -void TString::EnsureUnshareable(size_t stRequestedSize) +void TString::Reserve(size_t stLen) { - EnsureWritable(stRequestedSize); - m_pData->m_lRefCount = -1; -} - -void TString::Release() -{ - if(InterlockedDecrement(&m_pData->m_lRefCount) < 1) + if(m_stBufferSize < stLen) { - m_pData->ClearString(); // buffer is preserved here - m_pData->m_lRefCount = 1; + size_t stNewLen = stLen;//ROUNDUP(stLen, CHUNK_INCSIZE); + + wchar_t* pszNewBuffer = new wchar_t[stNewLen]; + if(m_pszData && m_pszData[0] != L'\0') + _tcsncpy_s(pszNewBuffer, stNewLen, m_pszData, GetLength() + 1); + else + pszNewBuffer[0] = _T('\0'); + + delete [] m_pszData; + m_pszData = pszNewBuffer; + m_stBufferSize = stNewLen; } - else - m_pData = new details::TInternalStringData; } -size_t TString::GetCurrentBufferSize() const -{ - return m_pData->m_stBufferSize; -} - END_CHCORE_NAMESPACE chcore::TString operator+(const wchar_t* pszString, const chcore::TString& str) Index: src/libchcore/TString.h =================================================================== diff -u -r14d99757fbeaa3e55d43b45b043033d8ba81980b -r7b830c34855c8aaa81aac2c6e0ca0fa6bae95e66 --- src/libchcore/TString.h (.../TString.h) (revision 14d99757fbeaa3e55d43b45b043033d8ba81980b) +++ src/libchcore/TString.h (.../TString.h) (revision 7b830c34855c8aaa81aac2c6e0ca0fa6bae95e66) @@ -31,35 +31,6 @@ class TStringArray; -// structure containing all string data -namespace details { - -// class manages the internal contents of TString -class TInternalStringData -{ -private: - TInternalStringData& operator=(const TInternalStringData&); - -public: - TInternalStringData(); - TInternalStringData(const TInternalStringData& rSrc, size_t stReserveLen = 0); - ~TInternalStringData(); - - void Reserve(size_t stLen); - void Clear(); - - void SetString(const wchar_t* pszString, size_t stCount); - void ClearString(); - -public: - long m_lRefCount; - size_t m_stStringLength; // string GetLength without terminating null - wchar_t* m_pszData; // contains the real string inside - size_t m_stBufferSize; // allocated string buffer size -}; - -} // end of namespace details - /////////////////////////////////////////////////////////////// // TString manipulation class /** \brief String manipulation class @@ -179,19 +150,15 @@ protected: void SetString(const wchar_t* pszStart, size_t stCount); + void SetString(const wchar_t* pszString); + void Reserve(size_t stLen); - void EnsureWritable(size_t stRequestedSize); - void EnsureUnshareable(size_t stRequestedSize); - - void Release(); - - size_t GetCurrentBufferSize() const; - protected: - details::TInternalStringData* m_pData; ///< Pointer to internal data + wchar_t* m_pszData; // contains the real string inside + size_t m_stBufferSize; // allocated string buffer size public: - static const size_t npos; + static const size_t npos = (size_t)-1; static const size_t DefaultMaxStringSize = 65536; }; Index: src/libchcore/libchcore.vc90.vcproj =================================================================== diff -u -ra3d1e4c03280ece94af75d9aef32a65266cf8050 -r7b830c34855c8aaa81aac2c6e0ca0fa6bae95e66 --- src/libchcore/libchcore.vc90.vcproj (.../libchcore.vc90.vcproj) (revision a3d1e4c03280ece94af75d9aef32a65266cf8050) +++ src/libchcore/libchcore.vc90.vcproj (.../libchcore.vc90.vcproj) (revision 7b830c34855c8aaa81aac2c6e0ca0fa6bae95e66) @@ -1140,6 +1140,14 @@ > + + + +