diff --git a/CMakeLists.txt b/CMakeLists.txt index 4b095a8..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,38 +56,39 @@ 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 include/cppcore/Common/Variant.h include/cppcore/Common/Sort.h include/cppcore/Common/TBitField.h 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 @@ -96,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 @@ -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..3d3a83b 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,158 @@ 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); + /// @param[in] ptr The data buffer. + /// @param[in] size The buffer size. + TStringBase(const T *ptr, size_t size); /// @brief The class destructor. ~TStringBase(); - void set(const T *ptr); + /// @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; + + /// @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; /// @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); + /// @brief Compare operator. bool operator == (const TStringBase &rhs) const; + + /// @brief Not equal operator. 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] = {}; + 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 -} - -template -inline TStringBase::TStringBase(const T *pPtr) : - m_pStringBuffer(nullptr), - m_size(0), - m_capacity(0), - mAllocator() { - copyFrom(*this, pPtr); +inline TStringBase::TStringBase(const T *ptr, size_t size) { + copyFrom(*this, ptr, size); + mHashId = THash::toHash(c_str(), size); } template inline TStringBase::~TStringBase() { - if (m_pStringBuffer) { - mAllocator.dealloc(m_pStringBuffer); - m_pStringBuffer = nullptr; - } + clear(); } template -inline void TStringBase::set(const T *ptr) { - mAllocator.dealloc(m_pStringBuffer); +inline void TStringBase::set(const T *ptr, size_t size) { + reset(); if (nullptr != ptr) { - copyFrom(*this, ptr); + copyFrom(*this, ptr, size); } } 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 void TStringBase::reset() { + mSize = 0u; + mHashId = 0; } template -inline bool TStringBase::operator==( const TStringBase &rhs ) const { - if (rhs.m_size != m_size) { - return false; - } - - for (size_t i = 0; i < m_size; ++i) { - if (rhs.m_pStringBuffer[i] != m_pStringBuffer[i]) { - return false; - } - } +inline size_t TStringBase::size() const { + return mSize; +} - return true; +template +inline bool TStringBase::isEmpty() const { + return (mSize == 0); } template -inline bool TStringBase::operator!=(const TStringBase &rhs) const { - return !(*this == rhs); +inline size_t TStringBase::capacity() const { + return mCapacity; } - template -class TStringView { -public: - TStringView(TCharType *ptr); - ~TStringView(); - size_t size() const; - TCharType *data() const; +template +inline const T *TStringBase::c_str() const { + if (mStringBuffer != nullptr) { + return mStringBuffer; + } -private: - TCharType *mPtr; - size_t mLen; -}; + return mBuffer; +} -template -inline TStringView::TStringView(TCharType *ptr) : - mPtr(ptr), - mLen(0) { - if (nullptr != mPtr) { - mLen = strlen(ptr); +template +inline void TStringBase::clear() { + if (mStringBuffer != nullptr) { + delete [] mStringBuffer; + mStringBuffer = nullptr; + mCapacity = InitSize; } + reset(); } -template -inline TStringView::~TStringView() { - // empty +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; + } + memcpy(targetPtr, ptr, size * sizeof(T)); + base.mSize = size; + } + } } -template -inline size_t TStringView::size() const { - return mLen; +template +inline bool TStringBase::operator == (const TStringBase &rhs) const { + if (rhs.mSize != mSize) { + return false; + } + + if (mHashId != rhs.mHashId) { + return false; + } + + // Fallback to actual comparison in case of hash collision + return memcmp(c_str(), rhs.c_str(), mSize * sizeof(T)) == 0; } -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..1fe9847 --- /dev/null +++ b/include/cppcore/Common/TStringView.h @@ -0,0 +1,114 @@ +/*----------------------------------------------------------------------------------------------- +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*; + + /// @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; + + /// @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 = nullptr; + size_t mLen = 0; +}; + +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 const T *TStringView::data(size_t offset) const { + if (offset > mLen) { + return nullptr; + } + return mPtr + offset; +} + +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/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/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/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/TStringBaseTest.cpp b/test/common/TStringBaseTest.cpp new file mode 100644 index 0000000..c433e0e --- /dev/null +++ b/test/common/TStringBaseTest.cpp @@ -0,0 +1,64 @@ +/* +------------------------------------------------------------------------------------------------- +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); + + TStringBase string_3("test", 4); + EXPECT_EQ(string_3, 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); +} + +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 new file mode 100644 index 0000000..ed6a1c0 --- /dev/null +++ b/test/common/TStringViewTest.cpp @@ -0,0 +1,66 @@ +/*----------------------------------------------------------------------------------------------- +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 {}; + +using StringView = TStringView; + +TEST_F(TStringViewTest, createTest) { + + StringView sv("this is a test", 14L); + auto start = sv.begin(); + auto end = sv.end(); + + size_t d = distance(start, end); + 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) { + constexpr char tag[] = "this is a test"; + StringView sv(tag, 14L); + size_t i{0}; + for (auto 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() ); } -