From af8eff60a66236cc6b88e61a57c0edb3b5d92ad6 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Tue, 24 Jun 2025 15:16:17 +0200 Subject: [PATCH 01/14] New string concept --- CMakeLists.txt | 3 + include/cppcore/CPPCoreCommon.h | 16 +-- include/cppcore/Common/Sort.h | 2 +- include/cppcore/Common/TStringBase.h | 172 +++++++++++---------------- include/cppcore/Common/TStringView.h | 88 ++++++++++++++ include/cppcore/Memory/MemUtils.h | 1 - test/common/TStringBaseTest.cpp | 49 ++++++++ test/common/TStringViewTest.cpp | 52 ++++++++ test/container/THashMapTest.cpp | 18 +-- test/container/TQueueTest.cpp | 1 - 10 files changed, 281 insertions(+), 121 deletions(-) create mode 100644 include/cppcore/Common/TStringView.h create mode 100644 test/common/TStringBaseTest.cpp create mode 100644 test/common/TStringViewTest.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 4b095a8..9bded49 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -76,6 +76,7 @@ SET ( cppcore_src SET ( cppcore_common_src include/cppcore/Common/Hash.h include/cppcore/Common/TStringBase.h + include/cppcore/Common/TStringView.h include/cppcore/Common/Variant.h include/cppcore/Common/Sort.h include/cppcore/Common/TBitField.h @@ -137,6 +138,8 @@ IF( CPPCORE_BUILD_UNITTESTS ) test/common/SortTest.cpp test/common/TBitFieldTest.cpp test/common/TOptionalTest.cpp + test/common/TStringViewTest.cpp + test/common/TStringBaseTest.cpp ) SET( cppcore_container_test_src diff --git a/include/cppcore/CPPCoreCommon.h b/include/cppcore/CPPCoreCommon.h index 613c8e6..a37d753 100644 --- a/include/cppcore/CPPCoreCommon.h +++ b/include/cppcore/CPPCoreCommon.h @@ -45,19 +45,19 @@ namespace cppcore { #endif #ifdef CPPCORE_WINDOWS -# define CPPCORE_TAG_DLL_EXPORT __declspec(dllexport) -# define CPPCORE_TAG_DLL_IMPORT __declspec(dllimport ) +# define CPPCORE_TAG_DLL_EXPORT __declspec(dllexport) +# define CPPCORE_TAG_DLL_IMPORT __declspec(dllimport ) # ifdef CPPCORE_BUILD -# define DLL_CPPCORE_EXPORT CPPCORE_TAG_DLL_EXPORT +# define DLL_CPPCORE_EXPORT CPPCORE_TAG_DLL_EXPORT # else -# define DLL_CPPCORE_EXPORT CPPCORE_TAG_DLL_IMPORT +# define DLL_CPPCORE_EXPORT CPPCORE_TAG_DLL_IMPORT # endif // All disabled warnings for windows # pragma warning( disable : 4251 ) // needs to have dll-interface to be used by clients of class -# define CPPCORE_STACK_ALLOC(size) ::alloca(size) +# define CPPCORE_STACK_ALLOC(size) ::alloca(size) #else -# define DLL_CPPCORE_EXPORT __attribute__((visibility("default"))) -# define CPPCORE_STACK_ALLOC(size) __builtin_alloca(size) +# define DLL_CPPCORE_EXPORT __attribute__((visibility("default"))) +# define CPPCORE_STACK_ALLOC(size) __builtin_alloca(size) #endif //------------------------------------------------------------------------------------------------- @@ -107,4 +107,6 @@ public: \ //------------------------------------------------------------------------------------------------- #define CPPCORE_ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) +using HashId = uint64_t; + } // Namespace cppcore diff --git a/include/cppcore/Common/Sort.h b/include/cppcore/Common/Sort.h index e90f7ca..ed19445 100644 --- a/include/cppcore/Common/Sort.h +++ b/include/cppcore/Common/Sort.h @@ -177,7 +177,7 @@ namespace cppcore { } /// @brief Implements a binary search algorithm. - /// @tparam T The type of the value + /// @tparam T The type of the value /// @param key The key to search for /// @param array The data to search in /// @param num The number of elements to search diff --git a/include/cppcore/Common/TStringBase.h b/include/cppcore/Common/TStringBase.h index c6cce64..b5ef748 100644 --- a/include/cppcore/Common/TStringBase.h +++ b/include/cppcore/Common/TStringBase.h @@ -23,30 +23,11 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #pragma once #include "string.h" +#include #include -#include namespace cppcore { -template -struct Allocator { - inline T *alloc(size_t size, size_t alignment) { - return (T*) _aligned_malloc(size, alignment); - } - - inline void dealloc(T *ptr) { - _aligned_free(ptr); - } - - inline static size_t countChars(const T *ptr) { - if (nullptr != ptr) { - return 0; - } - - return (::strlen(ptr)); - } -}; - //------------------------------------------------------------------------------------------------- /// @class TStringBase /// @ingroup CPPCore @@ -57,135 +38,122 @@ template class TStringBase { public: /// @brief The default class constructor. - TStringBase() noexcept; + TStringBase() noexcept = default; /// @brief The class constructor with a pointer showing to the data buffer. /// @param pPtr [in] The data buffer. - TStringBase(const T *pPtr); + TStringBase(const T *pPtr, size_t size); /// @brief The class destructor. ~TStringBase(); - void set(const T *ptr); + void set(const T *ptr, size_t size); + void clear(); + void reset(); + size_t size() const; + size_t capacity() const; + const T *c_str() const; /// @brief Helper method to copy data into the string. /// @param base [inout] The string data to copy in. /// @param pPtr [in] The data source. - static void copyFrom(TStringBase &base, const T *pPtr); + static void copyFrom(TStringBase &base, const T *pPtr, size_t size); bool operator == (const TStringBase &rhs) const; bool operator != (const TStringBase &rhs) const; - T *m_pStringBuffer; - size_t m_size; - size_t m_capacity; - Allocator mAllocator; +private: + static constexpr size_t InitSize = 256; + T mBuffer[InitSize] = {'\0'}; + T *mStringBuffer{nullptr}; + size_t mSize{0}; + size_t mCapacity{256}; + HashId mHashId{0}; }; template -inline TStringBase::TStringBase() noexcept : - m_pStringBuffer(nullptr), - m_size(0), - m_capacity(0), - mAllocator() { - // empty +inline TStringBase::TStringBase(const T *pPtr, size_t size) { + copyFrom(*this, pPtr, size); + mHashId = THash::toHash(pPtr, mSize); } template -inline TStringBase::TStringBase(const T *pPtr) : - m_pStringBuffer(nullptr), - m_size(0), - m_capacity(0), - mAllocator() { - copyFrom(*this, pPtr); +inline TStringBase::~TStringBase() { + clear(); } template -inline TStringBase::~TStringBase() { - if (m_pStringBuffer) { - mAllocator.dealloc(m_pStringBuffer); - m_pStringBuffer = nullptr; +inline void TStringBase::set(const T *ptr, size_t size) { + void reset(); + if (nullptr != ptr) { + copyFrom(*this, ptr, size); } } template -inline void TStringBase::set(const T *ptr) { - mAllocator.dealloc(m_pStringBuffer); - if (nullptr != ptr) { - copyFrom(*this, ptr); - } +inline void TStringBase::reset() { + mSize = 0u; } template -inline void TStringBase::copyFrom(TStringBase &base, const T *ptr) { - if (nullptr != ptr) { - base.m_size = Allocator::countChars(ptr); - if (base.m_size) { - base.m_capacity = base.m_size + 1; - base.m_pStringBuffer = base.mAllocator.alloc(base.m_capacity, 16); -#ifdef CPPCORE_WINDOWS - ::strncpy_s(base.m_pStringBuffer, base.m_capacity, ptr, base.m_size); -#else - ::strncpy(base.m_pStringBuffer, ptr, base.m_size); -#endif - base.m_pStringBuffer[base.m_size] = '\0'; - } - } +inline size_t TStringBase::size() const { + return mSize; } template -inline bool TStringBase::operator==( const TStringBase &rhs ) const { - if (rhs.m_size != m_size) { - return false; - } +inline size_t TStringBase::capacity() const { + return mCapacity; +} - for (size_t i = 0; i < m_size; ++i) { - if (rhs.m_pStringBuffer[i] != m_pStringBuffer[i]) { - return false; - } +template +inline const T *TStringBase::c_str() const { + if (mStringBuffer != nullptr) { + return mStringBuffer; } - return true; + return mBuffer; } template -inline bool TStringBase::operator!=(const TStringBase &rhs) const { - return !(*this == rhs); +inline void TStringBase::clear() { + if (mStringBuffer != nullptr) { + delete [] mStringBuffer; + mStringBuffer = nullptr; + mCapacity = InitSize; + } + mSize = 0; } - template -class TStringView { -public: - TStringView(TCharType *ptr); - ~TStringView(); - size_t size() const; - TCharType *data() const; - -private: - TCharType *mPtr; - size_t mLen; -}; - -template -inline TStringView::TStringView(TCharType *ptr) : - mPtr(ptr), - mLen(0) { - if (nullptr != mPtr) { - mLen = strlen(ptr); +template +inline void TStringBase::copyFrom(TStringBase &base, const T *ptr, size_t size) { + if (ptr != nullptr) { + T *targetPtr = base.mBuffer; + + if (size > 0) { + if (size > base.mCapacity) { + base.mStringBuffer = new T[size]; + base.mCapacity = size; + targetPtr = base.mStringBuffer; + } + memcpy(targetPtr, ptr, size); + base.mSize = size; + } } } -template -inline TStringView::~TStringView() { - // empty -} +template +inline bool TStringBase::operator == (const TStringBase &rhs) const { + if (rhs.mSize != mSize) { + return false; + } -template -inline size_t TStringView::size() const { - return mLen; + + return mHashId == rhs.mHashId; } -template -inline TCharType *TStringView::data() const { +template +inline bool TStringBase::operator != (const TStringBase &rhs) const { + return !(*this == rhs); } +} // namespace cppcore diff --git a/include/cppcore/Common/TStringView.h b/include/cppcore/Common/TStringView.h new file mode 100644 index 0000000..e5b02a7 --- /dev/null +++ b/include/cppcore/Common/TStringView.h @@ -0,0 +1,88 @@ +/*----------------------------------------------------------------------------------------------- +The MIT License (MIT) + +Copyright (c) 2014-2025 Kim Kulling + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +-----------------------------------------------------------------------------------------------*/ +#pragma once + +#include + +namespace cppcore { + +//------------------------------------------------------------------------------------------------- +/// @class TStringView +/// @ingroup CPPCore +/// +/// @brief +//------------------------------------------------------------------------------------------------- +template +class TStringView { +public: + using const_iterator = const T*; + + TStringView(const T *ptr, size_t len); + ~TStringView() = default; + size_t size() const; + T *data() const; + bool isEmpty() const; + const_iterator begin() const; + const_iterator end() const; + +private: + const T *mPtr; + size_t mLen; +}; + +template +inline TStringView::TStringView(const T *ptr, size_t len) : + mPtr(ptr), + mLen(len) { + // empty +} + +template +inline size_t TStringView::size() const { + return mLen; +} + +template +inline T *TStringView::data() const { + return mPtr; +} + +template +inline bool TStringView::isEmpty() const { + return mLen == 0; +} + +template +inline typename TStringView::const_iterator TStringView::begin() const { + if (isEmpty()) { + return end(); + } + return mPtr; +} + +template +inline typename TStringView::const_iterator TStringView::end() const { + return mPtr + mLen; +} + +} // namespace cppcore diff --git a/include/cppcore/Memory/MemUtils.h b/include/cppcore/Memory/MemUtils.h index 2bc9103..ffac60d 100644 --- a/include/cppcore/Memory/MemUtils.h +++ b/include/cppcore/Memory/MemUtils.h @@ -23,7 +23,6 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #pragma once #include -#include #include namespace cppcore { diff --git a/test/common/TStringBaseTest.cpp b/test/common/TStringBaseTest.cpp new file mode 100644 index 0000000..af2e234 --- /dev/null +++ b/test/common/TStringBaseTest.cpp @@ -0,0 +1,49 @@ +/* +------------------------------------------------------------------------------------------------- +The MIT License (MIT) + +Copyright (c) 2014-2025 Kim Kulling + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +------------------------------------------------------------------------------------------------- +*/ +#include + +#include + +using namespace cppcore; + +class TStringBaseTest : public ::testing::Test {}; + +TEST_F(TStringBaseTest, createTest) { + TStringBase string_1; + string_1.set("test", 4); + TStringBase string_2("test", 4); + EXPECT_EQ(string_1, string_2); +} + +TEST_F(TStringBaseTest, setResetTest) { + TStringBase string_1; + EXPECT_EQ(string_1.size(), 0); + EXPECT_EQ(string_1.capacity(), 256); + string_1.set("test", 4); + EXPECT_EQ(string_1.size(), 4); + EXPECT_EQ(0, strncmp(string_1.c_str(), "test", 4)); + string_1.reset(); + EXPECT_EQ(string_1.size(), 0); +} diff --git a/test/common/TStringViewTest.cpp b/test/common/TStringViewTest.cpp new file mode 100644 index 0000000..434e970 --- /dev/null +++ b/test/common/TStringViewTest.cpp @@ -0,0 +1,52 @@ +/*----------------------------------------------------------------------------------------------- +The MIT License (MIT) + +Copyright (c) 2014-2025 Kim Kulling + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +-----------------------------------------------------------------------------------------------*/ +#include + +#include +#include +#include + +using namespace cppcore; + +class TStringViewTest : public ::testing::Test {}; + +TEST_F(TStringViewTest, createTest) { + using StringView = TStringView; + + StringView sv("this is a test", 14l); + StringView::const_iterator start = sv.begin(); + StringView::const_iterator end = sv.end(); + + size_t d = distance(start, end); + EXPECT_EQ(d, 14); +} + +TEST_F(TStringViewTest, iterateTest) { + using StringView = TStringView; + constexpr char tag[] = "this is a test"; + StringView sv(tag, 14l); + size_t i{0}; + for (StringView::const_iterator it = sv.begin(); it != sv.end(); ++it) { + EXPECT_EQ(tag[i++], *it); + } +} diff --git a/test/container/THashMapTest.cpp b/test/container/THashMapTest.cpp index 9aba9c7..372f547 100644 --- a/test/container/THashMapTest.cpp +++ b/test/container/THashMapTest.cpp @@ -30,8 +30,8 @@ using namespace ::cppcore; class THashMapTest : public ::testing::Test {}; -TEST_F( THashMapTest, constructTest ) { - bool ok( true ); +TEST_F(THashMapTest, constructTest ) { + bool ok{ true }; try { THashMap myHashMap; } catch( ... ) { @@ -39,23 +39,23 @@ TEST_F( THashMapTest, constructTest ) { } // Assert - EXPECT_TRUE( ok ); + EXPECT_TRUE(ok); } -TEST_F( THashMapTest, clearTest ) { +TEST_F(THashMapTest, clearTest ) { THashMap myHashMap( 1 ); - myHashMap.insert( 1, 10 ); - myHashMap.insert( 2, 10 ); - myHashMap.insert( 3, 10 ); + myHashMap.insert(1, 10); + myHashMap.insert(2, 10); + myHashMap.insert(3, 10); myHashMap.clear(); - EXPECT_EQ( myHashMap.size(), 0u ); + EXPECT_EQ(myHashMap.size(), 0u); } TEST_F( THashMapTest, insertTest ) { THashMap myHashMap; - bool hasKey( true ); + bool hasKey{true}; size_t size = 0; size = myHashMap.size(); diff --git a/test/container/TQueueTest.cpp b/test/container/TQueueTest.cpp index 7072f20..39252b3 100644 --- a/test/container/TQueueTest.cpp +++ b/test/container/TQueueTest.cpp @@ -103,4 +103,3 @@ TEST_F( TQueueTest, clearTest ) { EXPECT_TRUE( f32Queue.isEmpty() ); EXPECT_EQ( 0u, f32Queue.size() ); } - From 7db585eac872d47770d2aaa60bcfdc19bbd6f77f Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Wed, 25 Jun 2025 11:04:20 +0200 Subject: [PATCH 02/14] Fix review findings --- CMakeLists.txt | 38 ++++++++++++++-------------- include/cppcore/Common/TStringBase.h | 2 +- include/cppcore/Common/TStringView.h | 4 +-- test/common/HashTest.cpp | 3 --- test/common/TOptionalTest.cpp | 4 +-- test/common/TStringViewTest.cpp | 6 ++--- 6 files changed, 27 insertions(+), 30 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 9bded49..7a1453f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,10 +1,10 @@ CMAKE_MINIMUM_REQUIRED( VERSION 3.10 ) PROJECT( cppcore ) -SET ( CPPCORE_VERSION_MAJOR 0 ) -SET ( CPPCORE_VERSION_MINOR 1 ) -SET ( CPPCORE_VERSION_PATCH 0 ) -SET ( CPPCORE_VERSION ${CPPCORE_VERSION_MAJOR}.${CPPCORE_VERSION_MINOR}.${CPPCORE_VERSION_PATCH} ) -SET ( PROJECT_VERSION "${CPPCORE_VERSION}" ) +SET( CPPCORE_VERSION_MAJOR 0 ) +SET( CPPCORE_VERSION_MINOR 1 ) +SET( CPPCORE_VERSION_PATCH 0 ) +SET( CPPCORE_VERSION ${CPPCORE_VERSION_MAJOR}.${CPPCORE_VERSION_MINOR}.${CPPCORE_VERSION_PATCH} ) +SET( PROJECT_VERSION "${CPPCORE_VERSION}" ) find_package(GTest) @@ -17,11 +17,11 @@ option( CPPCORE_BUILD_UNITTESTS "Build unit tests." ON ) -option( CPPCORE_ASAN +option(CPPCORE_ASAN "Enable AddressSanitizer." OFF ) -option( CPPCORE_UBSAN +option(CPPCORE_UBSAN "Enable Undefined Behavior sanitizer." OFF ) @@ -38,9 +38,9 @@ link_directories( ${CMAKE_HOME_DIRECTORY}/ ) -SET( CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_HOME_DIRECTORY}/lib ) -SET( CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_HOME_DIRECTORY}/lib ) -SET( CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_HOME_DIRECTORY}/bin ) +SET(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_HOME_DIRECTORY}/lib ) +SET(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_HOME_DIRECTORY}/lib ) +SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_HOME_DIRECTORY}/bin ) if( WIN32 AND NOT CYGWIN ) set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /EHsc" ) # Force to always compile with W4 @@ -56,24 +56,24 @@ elseif ( "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" ) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wno-long-long -g -pedantic -std=c++11") endif() -IF (ASSIMP_ASAN) +IF(CPPCORE_ASAN) MESSAGE(STATUS "AddressSanitizer enabled") SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address") SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address") ENDIF() -IF (ASSIMP_UBSAN) +IF(CPPCORE_UBSAN) MESSAGE(STATUS "Undefined Behavior sanitizer enabled") - SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=undefined -fno-sanitize-recover=all") - SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=undefined -fno-sanitize-recover=all") + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=undefined -fno-sanitize-recover=all") + SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=undefined -fno-sanitize-recover=all") ENDIF() -SET ( cppcore_src +SET(cppcore_src code/cppcore.cpp include/cppcore/CPPCoreCommon.h ) -SET ( cppcore_common_src +SET(cppcore_common_src include/cppcore/Common/Hash.h include/cppcore/Common/TStringBase.h include/cppcore/Common/TStringView.h @@ -83,12 +83,12 @@ SET ( cppcore_common_src include/cppcore/Common/TOptional.h ) -SET( cppcore_random_src +SET(cppcore_random_src include/cppcore/Random/RandomGenerator.h code/Random/RandomGenerator.cpp ) -SET ( cppcore_container_src +SET(cppcore_container_src include/cppcore/Container/THashMap.h include/cppcore/Container/TArray.h include/cppcore/Container/TStaticArray.h @@ -97,7 +97,7 @@ SET ( cppcore_container_src include/cppcore/Container/TStaticArray.h ) - SET ( cppcore_memory_src + SET(cppcore_memory_src include/cppcore/Memory/MemUtils.h include/cppcore/Memory/TDefaultAllocator.h include/cppcore/Memory/TStackAllocator.h diff --git a/include/cppcore/Common/TStringBase.h b/include/cppcore/Common/TStringBase.h index b5ef748..c4ef5bc 100644 --- a/include/cppcore/Common/TStringBase.h +++ b/include/cppcore/Common/TStringBase.h @@ -84,7 +84,7 @@ inline TStringBase::~TStringBase() { template inline void TStringBase::set(const T *ptr, size_t size) { - void reset(); + reset(); if (nullptr != ptr) { copyFrom(*this, ptr, size); } diff --git a/include/cppcore/Common/TStringView.h b/include/cppcore/Common/TStringView.h index e5b02a7..2117404 100644 --- a/include/cppcore/Common/TStringView.h +++ b/include/cppcore/Common/TStringView.h @@ -40,7 +40,7 @@ class TStringView { TStringView(const T *ptr, size_t len); ~TStringView() = default; size_t size() const; - T *data() const; + const T *data() const; bool isEmpty() const; const_iterator begin() const; const_iterator end() const; @@ -63,7 +63,7 @@ inline size_t TStringView::size() const { } template -inline T *TStringView::data() const { +inline const T *TStringView::data() const { return mPtr; } diff --git a/test/common/HashTest.cpp b/test/common/HashTest.cpp index dd40c9b..7d3e958 100644 --- a/test/common/HashTest.cpp +++ b/test/common/HashTest.cpp @@ -31,9 +31,6 @@ using namespace cppcore; class HashTest : public testing::Test { public: using UiHash = THash; - -protected: - // empty }; TEST_F( HashTest, CreateTest ) { diff --git a/test/common/TOptionalTest.cpp b/test/common/TOptionalTest.cpp index 980facb..c7c1b5f 100644 --- a/test/common/TOptionalTest.cpp +++ b/test/common/TOptionalTest.cpp @@ -28,7 +28,7 @@ using namespace ::cppcore; class TOptionalTest : public ::testing::Test {}; TEST_F(TOptionalTest, createInstance_success) { - constexpr int ValInt = 1; + constexpr int ValInt{1}; TOptional test_int(ValInt); EXPECT_FALSE(test_int.isInited()); @@ -36,7 +36,7 @@ TEST_F(TOptionalTest, createInstance_success) { EXPECT_TRUE(test_int.isInited()); EXPECT_EQ(test_int.value(), ValInt); - constexpr float ValFloat = 1.0f; + constexpr float ValFloat{1.0f}; TOptional test_float(ValFloat); EXPECT_FALSE(test_float.isInited()); diff --git a/test/common/TStringViewTest.cpp b/test/common/TStringViewTest.cpp index 434e970..df55f9b 100644 --- a/test/common/TStringViewTest.cpp +++ b/test/common/TStringViewTest.cpp @@ -34,8 +34,8 @@ TEST_F(TStringViewTest, createTest) { using StringView = TStringView; StringView sv("this is a test", 14l); - StringView::const_iterator start = sv.begin(); - StringView::const_iterator end = sv.end(); + auto start = sv.begin(); + auto end = sv.end(); size_t d = distance(start, end); EXPECT_EQ(d, 14); @@ -46,7 +46,7 @@ TEST_F(TStringViewTest, iterateTest) { constexpr char tag[] = "this is a test"; StringView sv(tag, 14l); size_t i{0}; - for (StringView::const_iterator it = sv.begin(); it != sv.end(); ++it) { + for (auto it = sv.begin(); it != sv.end(); ++it) { EXPECT_EQ(tag[i++], *it); } } From 4ef0fb025d0a22910fcf32f5043c44d2489c3cb0 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Wed, 25 Jun 2025 11:41:20 +0200 Subject: [PATCH 03/14] Fix review finging --- test/common/TStringViewTest.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/common/TStringViewTest.cpp b/test/common/TStringViewTest.cpp index df55f9b..ec646e3 100644 --- a/test/common/TStringViewTest.cpp +++ b/test/common/TStringViewTest.cpp @@ -33,7 +33,7 @@ class TStringViewTest : public ::testing::Test {}; TEST_F(TStringViewTest, createTest) { using StringView = TStringView; - StringView sv("this is a test", 14l); + StringView sv("this is a test", 14L); auto start = sv.begin(); auto end = sv.end(); @@ -44,7 +44,7 @@ TEST_F(TStringViewTest, createTest) { TEST_F(TStringViewTest, iterateTest) { using StringView = TStringView; constexpr char tag[] = "this is a test"; - StringView sv(tag, 14l); + StringView sv(tag, 14L); size_t i{0}; for (auto it = sv.begin(); it != sv.end(); ++it) { EXPECT_EQ(tag[i++], *it); From 96a7161e163e9e939926820271bb55f5b877d8c6 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Wed, 25 Jun 2025 13:06:12 +0200 Subject: [PATCH 04/14] Fix review finging --- include/cppcore/Common/TStringBase.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/cppcore/Common/TStringBase.h b/include/cppcore/Common/TStringBase.h index c4ef5bc..a3dfcde 100644 --- a/include/cppcore/Common/TStringBase.h +++ b/include/cppcore/Common/TStringBase.h @@ -93,6 +93,7 @@ inline void TStringBase::set(const T *ptr, size_t size) { template inline void TStringBase::reset() { mSize = 0u; + mHashId = 0; } template From e50c38b1007434747b6ec3ae6f9a3dff47a89cce Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Wed, 25 Jun 2025 13:08:18 +0200 Subject: [PATCH 05/14] Fix review finging --- include/cppcore/Common/TStringBase.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/cppcore/Common/TStringBase.h b/include/cppcore/Common/TStringBase.h index a3dfcde..a6f5f1b 100644 --- a/include/cppcore/Common/TStringBase.h +++ b/include/cppcore/Common/TStringBase.h @@ -64,7 +64,7 @@ class TStringBase { private: static constexpr size_t InitSize = 256; - T mBuffer[InitSize] = {'\0'}; + T mBuffer[InitSize] = {}; T *mStringBuffer{nullptr}; size_t mSize{0}; size_t mCapacity{256}; From e1412d40652ce389dc863382f92c544d1dc5460c Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Wed, 25 Jun 2025 21:33:17 +0200 Subject: [PATCH 06/14] Update TStringBase.h --- include/cppcore/Common/TStringBase.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/include/cppcore/Common/TStringBase.h b/include/cppcore/Common/TStringBase.h index a6f5f1b..0fdfd26 100644 --- a/include/cppcore/Common/TStringBase.h +++ b/include/cppcore/Common/TStringBase.h @@ -148,8 +148,12 @@ inline bool TStringBase::operator == (const TStringBase &rhs) const { return false; } + if (mHashId != rhs.mHashId) { + return false; + } - return mHashId == rhs.mHashId; + // Fallback to actual comparison in case of hash collision + return memcmp(c_str(), rhs.c_str(), mSize * sizeof(T)) == 0; } template From d2048269e840e8d1a677ea670b3274085f92aaa7 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Wed, 25 Jun 2025 21:36:07 +0200 Subject: [PATCH 07/14] Fix review findings --- include/cppcore/Common/TStringBase.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/include/cppcore/Common/TStringBase.h b/include/cppcore/Common/TStringBase.h index 0fdfd26..ab9f43b 100644 --- a/include/cppcore/Common/TStringBase.h +++ b/include/cppcore/Common/TStringBase.h @@ -122,11 +122,12 @@ inline void TStringBase::clear() { mStringBuffer = nullptr; mCapacity = InitSize; } - mSize = 0; + reset(); } template inline void TStringBase::copyFrom(TStringBase &base, const T *ptr, size_t size) { + static_assert(std::is_trivially_copyable_v, "T must be trivially copyable"); if (ptr != nullptr) { T *targetPtr = base.mBuffer; From 76bd06aa7e8ac777e3162834c32b7ac141bb2227 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Wed, 25 Jun 2025 22:28:59 +0200 Subject: [PATCH 08/14] Update TStringBase.h: Fix the build --- include/cppcore/Common/TStringBase.h | 1 - 1 file changed, 1 deletion(-) diff --git a/include/cppcore/Common/TStringBase.h b/include/cppcore/Common/TStringBase.h index ab9f43b..cbb5e5c 100644 --- a/include/cppcore/Common/TStringBase.h +++ b/include/cppcore/Common/TStringBase.h @@ -127,7 +127,6 @@ inline void TStringBase::clear() { template inline void TStringBase::copyFrom(TStringBase &base, const T *ptr, size_t size) { - static_assert(std::is_trivially_copyable_v, "T must be trivially copyable"); if (ptr != nullptr) { T *targetPtr = base.mBuffer; From 5c5dbf5f5ef4265487289095fd94a0d4f20a4e2c Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Fri, 27 Jun 2025 16:19:35 +0200 Subject: [PATCH 09/14] Add string append --- include/cppcore/Common/TStringBase.h | 36 ++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/include/cppcore/Common/TStringBase.h b/include/cppcore/Common/TStringBase.h index a6f5f1b..a733f5e 100644 --- a/include/cppcore/Common/TStringBase.h +++ b/include/cppcore/Common/TStringBase.h @@ -51,8 +51,10 @@ class TStringBase { void clear(); void reset(); size_t size() const; + void resize(size_t size); size_t capacity() const; const T *c_str() const; + void append(const T *ptr, size_t size); /// @brief Helper method to copy data into the string. /// @param base [inout] The string data to copy in. @@ -101,6 +103,28 @@ inline size_t TStringBase::size() const { return mSize; } +template +inline void TStringBase::resize(size_t size) { + if (size <= mCapacity) { + return; + } + + if (mStringBuffer == nullptr) { + mStringBuffer = new T[size]; + mCapacity = size; + if (mSize > 0) { + memcpy(mStringBuffer, mBuffer, size()); + } + } else { + T *ptr = new T[size]; + mCapacity = size; + if (mSize > 0) { + memcpy(ptr, mBuffer, size()); + } + mStringBuffer = ptr + } +} + template inline size_t TStringBase::capacity() const { return mCapacity; @@ -115,6 +139,18 @@ inline const T *TStringBase::c_str() const { return mBuffer; } +template +inline void TStringBase::append(const T* ptr, size_t size) { + if (ptr == nullptr) { + return; + } + + size_t newLen = mSize + size; + if (newLen > mCapacity) { + + } +} + template inline void TStringBase::clear() { if (mStringBuffer != nullptr) { From cee59bda4443b5ef0d63434d9dee6331d66f21b4 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Tue, 1 Jul 2025 16:12:39 +0200 Subject: [PATCH 10/14] rework --- include/cppcore/Common/TStringBase.h | 58 ++++----- include/cppcore/Common/TStringView.h | 42 +++++-- include/cppcore/Common/Variant.h | 172 +++++++++++++-------------- test/common/TStringBaseTest.cpp | 15 +++ test/common/TStringViewTest.cpp | 18 ++- 5 files changed, 176 insertions(+), 129 deletions(-) diff --git a/include/cppcore/Common/TStringBase.h b/include/cppcore/Common/TStringBase.h index bd78c9d..575014e 100644 --- a/include/cppcore/Common/TStringBase.h +++ b/include/cppcore/Common/TStringBase.h @@ -47,21 +47,42 @@ class TStringBase { /// @brief The class destructor. ~TStringBase(); + /// @brief Will set a new string. + /// @param ptr Pointer to the buffer. + /// @param size Size of the buffer. void set(const T *ptr, size_t size); + + /// @brief Will clear the string buffer. void clear(); + + /// @brief Will reset the string buffer, not internal storage will be released. void reset(); + + /// @brief Returns the size of the string buffer. + /// @return The size of the string buffer. size_t size() const; - void resize(size_t size); + + /// @brief Will return true, if the string is empty. + /// @return true for empty. + bool isEmpty() const; + + /// @brief Will return the whole capacity of the string. + /// @return The capacity of the string size_t capacity() const; + + /// @brief Will return the string pointer. + /// @return The string pointer. const T *c_str() const; - void append(const T *ptr, size_t size); /// @brief Helper method to copy data into the string. /// @param base [inout] The string data to copy in. /// @param pPtr [in] The data source. static void copyFrom(TStringBase &base, const T *pPtr, size_t size); + /// @brief Compare operator. bool operator == (const TStringBase &rhs) const; + + /// @brief Not equal operator. bool operator != (const TStringBase &rhs) const; private: @@ -104,25 +125,8 @@ inline size_t TStringBase::size() const { } template -inline void TStringBase::resize(size_t size) { - if (size <= mCapacity) { - return; - } - - if (mStringBuffer == nullptr) { - mStringBuffer = new T[size]; - mCapacity = size; - if (mSize > 0) { - memcpy(mStringBuffer, mBuffer, size()); - } - } else { - T *ptr = new T[size]; - mCapacity = size; - if (mSize > 0) { - memcpy(ptr, mBuffer, size()); - } - mStringBuffer = ptr - } +inline bool TStringBase::isEmpty() const { + return mSize == 0; } template @@ -139,18 +143,6 @@ inline const T *TStringBase::c_str() const { return mBuffer; } -template -inline void TStringBase::append(const T* ptr, size_t size) { - if (ptr == nullptr) { - return; - } - - size_t newLen = mSize + size; - if (newLen > mCapacity) { - - } -} - template inline void TStringBase::clear() { if (mStringBuffer != nullptr) { diff --git a/include/cppcore/Common/TStringView.h b/include/cppcore/Common/TStringView.h index 2117404..1fe9847 100644 --- a/include/cppcore/Common/TStringView.h +++ b/include/cppcore/Common/TStringView.h @@ -30,30 +30,53 @@ namespace cppcore { /// @class TStringView /// @ingroup CPPCore /// -/// @brief +/// @brief //------------------------------------------------------------------------------------------------- template class TStringView { public: using const_iterator = const T*; + /// @brief The default constructor. + TStringView() = default; + + /// @brief The constructor with the buffer. + /// @param ptr Pointer to the buffer + /// @param len The buffer size TStringView(const T *ptr, size_t len); + + /// @brief The class destructor. ~TStringView() = default; + + /// @brief Will return the size of the view. + /// @return The size of the view size_t size() const; - const T *data() const; + + /// @brief Will return the data with an offset, if given. + /// @param offset The offset in the view. + /// @return Pointer to the data + const T *data(size_t offset = 0) const; + + /// @brief Will return true, if there is no string to view. + /// @return true for empty bool isEmpty() const; + + /// @brief Will return the first entry. + /// @return The first entry const_iterator begin() const; + + /// @brief Will return the end entry. + /// @return The end entry const_iterator end() const; private: - const T *mPtr; - size_t mLen; + const T *mPtr = nullptr; + size_t mLen = 0; }; template inline TStringView::TStringView(const T *ptr, size_t len) : - mPtr(ptr), - mLen(len) { + mPtr(ptr), mLen(len) { // empty } @@ -63,8 +86,11 @@ inline size_t TStringView::size() const { } template -inline const T *TStringView::data() const { - return mPtr; +inline const T *TStringView::data(size_t offset) const { + if (offset > mLen) { + return nullptr; + } + return mPtr + offset; } template diff --git a/include/cppcore/Common/Variant.h b/include/cppcore/Common/Variant.h index b220254..250b44e 100644 --- a/include/cppcore/Common/Variant.h +++ b/include/cppcore/Common/Variant.h @@ -48,7 +48,7 @@ class Variant { /// @enum Type /// @brief This enum describes the variable type of the variant instance. enum Type { - None = -1, ///< Initialization value. + Invalid = -1, ///< Initialization value. Byte, ///< 1 Byte type. Int, ///< Integer value. Int3, ///< Integer vector, 3 components. @@ -59,7 +59,7 @@ class Variant { Float4x4, ///< Float matrix, 4 x 4 components. String, ///< String value. Boolean, ///< Boolean type. - MaxType ///< Upper limit. + Count ///< Upper limit. }; /// @brief The class default constructor. @@ -97,42 +97,42 @@ class Variant { /// @brief Will set the payload to the given value. /// @param value [in] The new given payload. - void setByte(unsigned char value); + void setByte(uint8_t value); /// @brief Will return the current payload as a byte value. /// @return The byte value. - unsigned char getByte() const; + uint8_t getByte() const; /// @brief Sets a new integer value, old values will be released and destroyed. /// @param val [in] A new integer value. - void setInt(int val); + void setInt(int32_t val); /// @brief Returns the integer value of the instance. /// @return The stored integer value will be returned. - int getInt() const; + int32_t getInt() const; /// @brief Set a new integer vector, the old data will be released and destroyed. /// @param val1 Component 1, integer. /// @param val2 Component 2, integer. /// @param val3 Component 3, integer. - void setInt3(int val1, int val2, int val3); + void setInt3(int32_t val1, int32_t val2, int32_t val3); /// @brief Returns a pointer to the first element of the integer vector. You can access the 2 /// following with the index operator for instance. /// @return Pointer to the first component of th vector array. - int *getInt3() const; + int32_t *getInt3() const; /// @brief Set a new integer vector, the old data will be released and destroyed. /// @param val1 Component 1, integer. /// @param val2 Component 2, integer. /// @param val3 Component 3, integer. /// @param val4 Component 3, integer. - void setInt4(int val1, int val2, int val3, int val4); + void setInt4(int32_t val1, int32_t val2, int32_t val3, int32_t val4); /// @brief Returns a pointer to the first element of the integer vector. You can access the 3 /// following with the index operator for instance. /// @return Pointer to the first component of th vector array. - int *getInt4() const; + int32_t *getInt4() const; /// @brief Returns the float value of the instance. /// @param val A new float value. @@ -214,54 +214,54 @@ class Variant { void reserve(Type type, size_t size); private: - Type m_Type; - size_t m_BufferSize; - void *m_pData; + Type mType; + size_t mBufferSize; + void *mData; }; inline Variant::Variant() : - m_Type(None), - m_BufferSize(0), - m_pData(nullptr) { + mType(Invalid), + mBufferSize(0), + mData(nullptr) { // empty } inline Variant::Variant(Type type, void *pData, size_t numItems) : - m_Type(None), - m_BufferSize(0), - m_pData(nullptr) { + mType(Invalid), + mBufferSize(0), + mData(nullptr) { if (isValid(type, numItems)) { size_t size = 0; - m_Type = type; + mType = type; if (type == String) { assert(nullptr != pData); std::string str((char *)pData); setStdString(str); } else { reserve(type, size); - ::memcpy(m_pData, pData, m_BufferSize); + ::memcpy(mData, pData, mBufferSize); } } } inline Variant::Variant(bool value) : - m_Type(Boolean), - m_BufferSize(0), - m_pData(nullptr) { + mType(Boolean), + mBufferSize(0), + mData(nullptr) { reserve(Boolean, 0); - ::memcpy(m_pData, &value, m_BufferSize); + ::memcpy(mData, &value, mBufferSize); } inline Variant::Variant(const Variant &other) : - m_Type(None), - m_BufferSize(0), - m_pData(nullptr) { - m_Type = other.m_Type; - if (String == m_Type) { + mType(Invalid), + mBufferSize(0), + mData(nullptr) { + mType = other.mType; + if (String == mType) { setStdString(other.getString()); } else { - reserve(m_Type, 0); - ::memcpy(m_pData, other.m_pData, m_BufferSize); + reserve(mType, 0); + ::memcpy(mData, other.mData, mBufferSize); } } @@ -270,43 +270,43 @@ inline Variant::~Variant() { } inline Variant::Type Variant::getType() const { - return m_Type; + return mType; } inline size_t Variant::getSize() const { - return m_BufferSize; + return mBufferSize; } inline void *Variant::getPtr() const { - return m_pData; + return mData; } inline void Variant::setByte(unsigned char value) { clear(); reserve(Byte, 0); - ::memcpy(m_pData, &value, sizeof(unsigned char)); + ::memcpy(mData, &value, sizeof(unsigned char)); } inline unsigned char Variant::getByte() const { - return (*reinterpret_cast(m_pData)); + return (*reinterpret_cast(mData)); } -inline void Variant::setInt(int val) { +inline void Variant::setInt(int32_t val) { clear(); reserve(Int, 0); - ::memcpy(m_pData, &val, sizeof(int)); + ::memcpy(mData, &val, sizeof(int32_t)); } inline int Variant::getInt() const { - assert(m_Type == Int); + assert(mType == Int); - return (*reinterpret_cast(m_pData)); + return (*reinterpret_cast(mData)); } inline void Variant::setInt3(int val1, int val2, int val3) { clear(); reserve(Int3, 0); - int *ptr = reinterpret_cast(m_pData); + int *ptr = reinterpret_cast(mData); *ptr = val1; ++ptr; *ptr = val2; @@ -315,14 +315,14 @@ inline void Variant::setInt3(int val1, int val2, int val3) { } inline int *Variant::getInt3() const { - assert(m_Type == Int3); - return (reinterpret_cast(m_pData)); + assert(mType == Int3); + return (reinterpret_cast(mData)); } inline void Variant::setInt4(int val1, int val2, int val3, int val4) { clear(); reserve(Int4, 0); - int *ptr = reinterpret_cast(m_pData); + int *ptr = reinterpret_cast(mData); *ptr = val1; ++ptr; *ptr = val2; @@ -333,26 +333,26 @@ inline void Variant::setInt4(int val1, int val2, int val3, int val4) { } inline int *Variant::getInt4() const { - assert(m_Type == Int4); + assert(mType == Int4); - return (reinterpret_cast(m_pData)); + return (reinterpret_cast(mData)); } inline void Variant::setFloat(float val) { clear(); reserve(Float, 0); - ::memcpy(m_pData, &val, sizeof(float)); + ::memcpy(mData, &val, sizeof(float)); } inline float Variant::getFloat() const { - assert(m_Type == Float); - return (*reinterpret_cast(m_pData)); + assert(mType == Float); + return (*reinterpret_cast(mData)); } inline void Variant::setFloat3(float val1, float val2, float val3) { clear(); reserve(Float3, 0); - float *ptr = reinterpret_cast(m_pData); + float *ptr = reinterpret_cast(mData); *ptr = val1; ++ptr; *ptr = val2; @@ -361,14 +361,14 @@ inline void Variant::setFloat3(float val1, float val2, float val3) { } inline float *Variant::getFloat3() const { - assert(m_Type == Float3); - return (reinterpret_cast(m_pData)); + assert(mType == Float3); + return (reinterpret_cast(mData)); } inline void Variant::setFloat4(float val1, float val2, float val3, float val4) { clear(); reserve(Float4, 0); - float *ptr = reinterpret_cast(m_pData); + float *ptr = reinterpret_cast(mData); *ptr = val1; ++ptr; *ptr = val2; @@ -379,66 +379,66 @@ inline void Variant::setFloat4(float val1, float val2, float val3, float val4) { } inline float *Variant::getFloat4() const { - assert(m_Type == Float4); - return (reinterpret_cast(m_pData)); + assert(mType == Float4); + return (reinterpret_cast(mData)); } inline void Variant::setFloat4x4(float *pData) { clear(); reserve(Float4x4, 0); - ::memcpy(m_pData, pData, sizeof(float) * 16); + ::memcpy(mData, pData, sizeof(float) * 16); } inline float *Variant::getFloat4x4() const { - assert(m_Type == Float4x4); - return (reinterpret_cast(m_pData)); + assert(mType == Float4x4); + return (reinterpret_cast(mData)); } inline void Variant::setStdString(const std::string &value) { clear(); - m_Type = String; + mType = String; if (value.empty()) { - m_pData = nullptr; - m_BufferSize = 0; + mData = nullptr; + mBufferSize = 0; } - m_BufferSize = sizeof(char) * (value.size() + 1); - m_pData = (char*) ::malloc(m_BufferSize); - if (m_pData == nullptr) { + mBufferSize = sizeof(char) * (value.size() + 1); + mData = (char*) ::malloc(mBufferSize); + if (mData == nullptr) { clear(); return; } - ::memcpy(m_pData, value.c_str(), sizeof(char) * value.size()); - char *ptr = (char *) m_pData; + ::memcpy(mData, value.c_str(), sizeof(char) * value.size()); + char *ptr = (char *) mData; ptr[value.size()] = '\0'; } inline const char *Variant::getString() const { - assert(m_Type == String); + assert(mType == String); - return static_cast(m_pData); + return static_cast(mData); } inline void Variant::setBool(bool value) { clear(); reserve(Boolean, 0); - ::memcpy(m_pData, &value, sizeof(bool)); + ::memcpy(mData, &value, sizeof(bool)); } inline bool Variant::getBool() const { - assert(Boolean == m_Type); + assert(Boolean == mType); - return (*reinterpret_cast(m_pData)); + return (*reinterpret_cast(mData)); } inline void Variant::clear() { - if (None == m_Type) { + if (Invalid == mType) { return; } - ::free(m_pData); - m_pData = nullptr; - m_Type = None; + ::free(mData); + mData = nullptr; + mType = Invalid; } inline Variant *Variant::createFromString( const std::string &value ) { @@ -449,15 +449,15 @@ inline Variant *Variant::createFromString( const std::string &value ) { } inline bool Variant::operator==(const Variant &rOther) const { - if (rOther.m_Type != m_Type) { + if (rOther.mType != mType) { return false; } - if (rOther.m_BufferSize != m_BufferSize) { + if (rOther.mBufferSize != mBufferSize) { return false; } - if (0 != ::memcmp(rOther.m_pData, m_pData, m_BufferSize)) { + if (0 != ::memcmp(rOther.mData, mData, mBufferSize)) { return false; } @@ -466,9 +466,9 @@ inline bool Variant::operator==(const Variant &rOther) const { inline Variant &Variant::operator=(const Variant &rOther) { if (!(rOther == *this)) { - m_Type = rOther.m_Type; - reserve(m_Type, 0); - ::memcpy(m_pData, rOther.m_pData, m_BufferSize); + mType = rOther.mType; + reserve(mType, 0); + ::memcpy(mData, rOther.mData, mBufferSize); } return *this; @@ -496,7 +496,7 @@ inline bool Variant::isValid(Type type, size_t numItems) const { if (0 != numItems) { res = true; } - } else if (type == None) { + } else if (type == Invalid) { res = true; } @@ -526,9 +526,9 @@ inline void Variant::reserve(Type type, size_t size) { } } - m_BufferSize = size; - m_pData = ::malloc(size); - m_Type = type; + mBufferSize = size; + mData = ::malloc(size); + mType = type; } } // Namespace cppcore diff --git a/test/common/TStringBaseTest.cpp b/test/common/TStringBaseTest.cpp index af2e234..c433e0e 100644 --- a/test/common/TStringBaseTest.cpp +++ b/test/common/TStringBaseTest.cpp @@ -33,8 +33,12 @@ class TStringBaseTest : public ::testing::Test {}; TEST_F(TStringBaseTest, createTest) { TStringBase string_1; string_1.set("test", 4); + TStringBase string_2("test", 4); EXPECT_EQ(string_1, string_2); + + TStringBase string_3("test", 4); + EXPECT_EQ(string_3, string_2); } TEST_F(TStringBaseTest, setResetTest) { @@ -47,3 +51,14 @@ TEST_F(TStringBaseTest, setResetTest) { string_1.reset(); EXPECT_EQ(string_1.size(), 0); } + +TEST_F(TStringBaseTest, setClearTest) { + TStringBase string_1("test", 4); + EXPECT_EQ(string_1.capacity(), 256); + EXPECT_EQ(string_1.size(), 4); + EXPECT_FALSE(string_1.isEmpty()); + + string_1.clear(); + EXPECT_EQ(string_1.size(), 0); + EXPECT_TRUE(string_1.isEmpty()); +} diff --git a/test/common/TStringViewTest.cpp b/test/common/TStringViewTest.cpp index ec646e3..ed6a1c0 100644 --- a/test/common/TStringViewTest.cpp +++ b/test/common/TStringViewTest.cpp @@ -30,8 +30,9 @@ using namespace cppcore; class TStringViewTest : public ::testing::Test {}; +using StringView = TStringView; + TEST_F(TStringViewTest, createTest) { - using StringView = TStringView; StringView sv("this is a test", 14L); auto start = sv.begin(); @@ -41,8 +42,21 @@ TEST_F(TStringViewTest, createTest) { EXPECT_EQ(d, 14); } +TEST_F(TStringViewTest, dataTest) { + StringView sv("this is a test", 14L); + const char *ptr = sv.data(4); + EXPECT_NE(ptr, nullptr); + + auto end = sv.end(); + + size_t d = distance(ptr, end); + EXPECT_EQ(d, 10); + + const char *invalidPtr = sv.data(16); + EXPECT_EQ(invalidPtr, nullptr); +} + TEST_F(TStringViewTest, iterateTest) { - using StringView = TStringView; constexpr char tag[] = "this is a test"; StringView sv(tag, 14L); size_t i{0}; From 7742b4e9b01bfb6d72c10392931e17290eea1244 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Wed, 2 Jul 2025 08:56:47 +0200 Subject: [PATCH 11/14] TStringBase: Fix review findings --- include/cppcore/Common/TStringBase.h | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/include/cppcore/Common/TStringBase.h b/include/cppcore/Common/TStringBase.h index 575014e..60a2e47 100644 --- a/include/cppcore/Common/TStringBase.h +++ b/include/cppcore/Common/TStringBase.h @@ -41,8 +41,9 @@ class TStringBase { TStringBase() noexcept = default; /// @brief The class constructor with a pointer showing to the data buffer. - /// @param pPtr [in] The data buffer. - TStringBase(const T *pPtr, size_t size); + /// @param[in] ptr The data buffer. + /// @param[in] size The buffer size. + TStringBase(const T *ptr, size_t size); /// @brief The class destructor. ~TStringBase(); @@ -95,9 +96,9 @@ class TStringBase { }; template -inline TStringBase::TStringBase(const T *pPtr, size_t size) { - copyFrom(*this, pPtr, size); - mHashId = THash::toHash(pPtr, mSize); +inline TStringBase::TStringBase(const T *ptr, size_t size) { + copyFrom(*this, ptr, size); + mHashId = THash::toHash(c_str(), size()); } template @@ -126,7 +127,7 @@ inline size_t TStringBase::size() const { template inline bool TStringBase::isEmpty() const { - return mSize == 0; + return (mSize == 0); } template From 4aa63aa66d13a212e5ba96808526d61c64c33d0e Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Wed, 2 Jul 2025 11:03:33 +0200 Subject: [PATCH 12/14] Fix review finding --- include/cppcore/Common/TStringBase.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/include/cppcore/Common/TStringBase.h b/include/cppcore/Common/TStringBase.h index 60a2e47..8d12dfc 100644 --- a/include/cppcore/Common/TStringBase.h +++ b/include/cppcore/Common/TStringBase.h @@ -158,9 +158,11 @@ template inline void TStringBase::copyFrom(TStringBase &base, const T *ptr, size_t size) { if (ptr != nullptr) { T *targetPtr = base.mBuffer; - if (size > 0) { if (size > base.mCapacity) { + if (base.mStringBuffer != nullptr) { + delete [] base.mStringBuffer; + } base.mStringBuffer = new T[size]; base.mCapacity = size; targetPtr = base.mStringBuffer; From 985df940a7ffdb1c9973b1a2bdc81ebeaae66714 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Wed, 2 Jul 2025 11:06:13 +0200 Subject: [PATCH 13/14] Update TStringBase.h --- include/cppcore/Common/TStringBase.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/cppcore/Common/TStringBase.h b/include/cppcore/Common/TStringBase.h index 8d12dfc..17f3813 100644 --- a/include/cppcore/Common/TStringBase.h +++ b/include/cppcore/Common/TStringBase.h @@ -167,7 +167,7 @@ inline void TStringBase::copyFrom(TStringBase &base, const T *ptr, size_t base.mCapacity = size; targetPtr = base.mStringBuffer; } - memcpy(targetPtr, ptr, size); + memcpy(targetPtr, ptr, size * sizeof(T)); base.mSize = size; } } From c1e06224f16d3348e586e7eb9beaaf833ad569b3 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Wed, 2 Jul 2025 11:33:57 +0200 Subject: [PATCH 14/14] Update TStringBase.h --- include/cppcore/Common/TStringBase.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/cppcore/Common/TStringBase.h b/include/cppcore/Common/TStringBase.h index 17f3813..3d3a83b 100644 --- a/include/cppcore/Common/TStringBase.h +++ b/include/cppcore/Common/TStringBase.h @@ -98,7 +98,7 @@ class TStringBase { template inline TStringBase::TStringBase(const T *ptr, size_t size) { copyFrom(*this, ptr, size); - mHashId = THash::toHash(c_str(), size()); + mHashId = THash::toHash(c_str(), size); } template