Merge pull request 'billboard example error fix + string wrapper first implementation' (#146) from features/string-wrapper into master
Reviewed-on: https://git.madvoxel.net/OpenVulkano/OpenVulkano/pulls/146 Reviewed-by: Georg Hagen <georg.hagen@madvoxel.com>
This commit is contained in:
325
openVulkanoCpp/Data/Containers/String.hpp
Normal file
325
openVulkanoCpp/Data/Containers/String.hpp
Normal file
@@ -0,0 +1,325 @@
|
|||||||
|
/*
|
||||||
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <string_view>
|
||||||
|
#include <vector>
|
||||||
|
#include <c4/substr.hpp>
|
||||||
|
#include <c4/substr_fwd.hpp>
|
||||||
|
#include <c4/format.hpp>
|
||||||
|
#include <c4/charconv.hpp>
|
||||||
|
#include <utf8.h>
|
||||||
|
#include <type_traits>
|
||||||
|
|
||||||
|
namespace OpenVulkano
|
||||||
|
{
|
||||||
|
class String final
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
String() = default;
|
||||||
|
String(const char* str) : m_string(str) {}
|
||||||
|
String(const std::string& str) : m_string(str) {}
|
||||||
|
String(const std::string_view& str) : m_string(str) {}
|
||||||
|
String(const String& other) : m_string(other.m_string) {}
|
||||||
|
String(String&& other) noexcept : m_string(std::move(other.m_string)) {}
|
||||||
|
String(std::string&& other) noexcept : m_string(std::move(other)) {}
|
||||||
|
~String() = default;
|
||||||
|
|
||||||
|
template<typename T> String& operator=(const T& other)
|
||||||
|
{
|
||||||
|
m_string = other;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T> String& operator=(T&& other)
|
||||||
|
{
|
||||||
|
m_string = std::move(other);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
String& operator=(const String& other)
|
||||||
|
{
|
||||||
|
m_string = other.m_string;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
String& operator=(String&& other)
|
||||||
|
{
|
||||||
|
m_string = std::move(other.m_string);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T> String& operator+=(const T& other)
|
||||||
|
{
|
||||||
|
m_string += other;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
String& operator+=(const String& other)
|
||||||
|
{
|
||||||
|
m_string += other.m_string;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
template<typename T> String operator+(const T& other) const { return m_string + other; }
|
||||||
|
String operator+(const String& other) const { return m_string + other.m_string; }
|
||||||
|
|
||||||
|
template<typename T> auto operator<=>(const T& other) const { return m_string <=> other; }
|
||||||
|
auto operator<=>(const String& other) const = default;
|
||||||
|
explicit operator bool() const { return !m_string.empty(); }
|
||||||
|
|
||||||
|
operator std::string() const { return m_string; }
|
||||||
|
explicit operator std::string_view() const { return m_string; }
|
||||||
|
|
||||||
|
char& operator[](size_t index) noexcept { return m_string[index]; }
|
||||||
|
const char& operator[](size_t index) const noexcept { return m_string[index]; }
|
||||||
|
char& At(size_t index) { return m_string.at(index); }
|
||||||
|
const char& At(size_t index) const { return m_string.at(index); }
|
||||||
|
const char* CharString() const { return m_string.c_str(); }
|
||||||
|
const char* Data() { return m_string.data(); }
|
||||||
|
size_t Length() const { return m_string.length(); }
|
||||||
|
size_t Size() const { return m_string.size(); }
|
||||||
|
bool Empty() const { return m_string.empty(); }
|
||||||
|
size_t Capacity() const { return m_string.capacity(); }
|
||||||
|
size_t CharCount() const { return utf8::distance(m_string.begin(), m_string.end()); }
|
||||||
|
|
||||||
|
char& Front() { return m_string.front(); }
|
||||||
|
char& Back() { return m_string.back(); }
|
||||||
|
void PopBack() { m_string.pop_back(); }
|
||||||
|
void Clear() { m_string.clear(); }
|
||||||
|
void ShrinkToFit() { m_string.shrink_to_fit(); }
|
||||||
|
String SubString(size_t start, size_t elementCount) const { return m_string.substr(start, elementCount); }
|
||||||
|
bool StartsWith(const std::string_view& str) const { return m_string.find(str) == 0; }
|
||||||
|
bool EndsWith(const std::string_view& str) const { return m_string.rfind(str) == m_string.size() - str.size(); }
|
||||||
|
bool Contains(const std::string_view& str) const { return m_string.find(str) != std::string::npos; }
|
||||||
|
|
||||||
|
size_t FindStartIndexOf(const std::string_view& str) const { return m_string.find(str); }
|
||||||
|
size_t FindEndIndexOf(const std::string_view& str) const { return m_string.rfind(str); }
|
||||||
|
|
||||||
|
String& Trim() noexcept { return TrimBack().TrimFront(); }
|
||||||
|
|
||||||
|
[[nodiscard]] String Trim() const { return Trim(); }
|
||||||
|
|
||||||
|
String& TrimFront() noexcept
|
||||||
|
{
|
||||||
|
size_t start = m_string.find_first_not_of(" \t\n\r");
|
||||||
|
if (start == std::string::npos)
|
||||||
|
{
|
||||||
|
m_string.clear();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_string.erase(0, start);
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
String& TrimBack() noexcept
|
||||||
|
{
|
||||||
|
size_t end = m_string.find_last_not_of(" \t\n\r");
|
||||||
|
if (end == std::string::npos)
|
||||||
|
{
|
||||||
|
m_string.clear();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_string.resize(end + 1);
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<String> Split(const std::string_view& delimiter) const
|
||||||
|
{
|
||||||
|
std::vector<String> result;
|
||||||
|
size_t start = 0;
|
||||||
|
size_t end = m_string.find(delimiter);
|
||||||
|
while (end != std::string::npos)
|
||||||
|
{
|
||||||
|
result.push_back(m_string.substr(start, end - start));
|
||||||
|
start = end + delimiter.size();
|
||||||
|
end = m_string.find(delimiter, start);
|
||||||
|
}
|
||||||
|
result.push_back(m_string.substr(start, end));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::pair<String, String> SplitAtLastOccurrence(const std::string_view& delimiter) const
|
||||||
|
{
|
||||||
|
size_t end = m_string.rfind(delimiter);
|
||||||
|
if (end == std::string::npos)
|
||||||
|
{
|
||||||
|
return { m_string, "" };
|
||||||
|
}
|
||||||
|
return { m_string.substr(0, end), m_string.substr(end + delimiter.size()) };
|
||||||
|
}
|
||||||
|
|
||||||
|
std::pair<String, String> SplitAtFirstOccurrence(const std::string_view& delimiter) const
|
||||||
|
{
|
||||||
|
size_t end = m_string.find(delimiter);
|
||||||
|
if (end == std::string::npos)
|
||||||
|
{
|
||||||
|
return { m_string, "" };
|
||||||
|
}
|
||||||
|
return { m_string.substr(0, end), m_string.substr(end + delimiter.size()) };
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::string_view> SplitAsStringViews(const std::string_view& delimiter) const
|
||||||
|
{
|
||||||
|
std::vector<std::string_view> result;
|
||||||
|
size_t start = 0;
|
||||||
|
size_t end = m_string.find(delimiter);
|
||||||
|
while (end != std::string::npos)
|
||||||
|
{
|
||||||
|
result.push_back(std::string_view(m_string.c_str() + start, end - start));
|
||||||
|
start = end + delimiter.size();
|
||||||
|
end = m_string.find(delimiter, start);
|
||||||
|
}
|
||||||
|
result.push_back(
|
||||||
|
std::string_view(m_string.c_str() + start, m_string.size() - (start + end + delimiter.size())));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::pair<std::string_view, std::string_view>
|
||||||
|
SplitAtLastOccurenceAsStringViews(const std::string_view& delimiter) const
|
||||||
|
{
|
||||||
|
size_t end = m_string.rfind(delimiter);
|
||||||
|
if (end == std::string::npos)
|
||||||
|
{
|
||||||
|
return { m_string, "" };
|
||||||
|
}
|
||||||
|
return { std::string_view(m_string.c_str(), end),
|
||||||
|
std::string_view(m_string.c_str() + end + delimiter.size(),
|
||||||
|
m_string.size() - end - delimiter.size()) };
|
||||||
|
}
|
||||||
|
|
||||||
|
std::pair<std::string_view, std::string_view>
|
||||||
|
SplitAtFirstOccurenceAsStringViews(const std::string_view& delimiter) const
|
||||||
|
{
|
||||||
|
size_t end = m_string.find(delimiter);
|
||||||
|
if (end == std::string::npos)
|
||||||
|
{
|
||||||
|
return { m_string, "" };
|
||||||
|
}
|
||||||
|
return { std::string_view(m_string.c_str(), end),
|
||||||
|
std::string_view(m_string.c_str() + end + delimiter.size(),
|
||||||
|
m_string.size() - end - delimiter.size()) };
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int64_t OctToInt(const std::string_view& string)
|
||||||
|
{
|
||||||
|
int64_t result = 0;
|
||||||
|
for (int i = 0; i < static_cast<int>(string.length()); i++)
|
||||||
|
{
|
||||||
|
char c = string[i];
|
||||||
|
if (c == 0)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (c == ' ')
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (c < '0' || c > '7')
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
result = result * 8 + c - '0';
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
int64_t OctToInt() const { return OctToInt(m_string); }
|
||||||
|
|
||||||
|
static inline int64_t HexToInt(const std::string_view& string)
|
||||||
|
{
|
||||||
|
int64_t result = 0;
|
||||||
|
for (char c: string)
|
||||||
|
{
|
||||||
|
if (c == 0)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (c == ' ')
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (c >= '0' && c <= '9')
|
||||||
|
{
|
||||||
|
result = result * 16 + c - '0';
|
||||||
|
}
|
||||||
|
else if (c >= 'A' && c <= 'F')
|
||||||
|
{
|
||||||
|
result = result * 16 + c - 'A' + 10;
|
||||||
|
}
|
||||||
|
else if (c >= 'a' && c <= 'f')
|
||||||
|
{
|
||||||
|
result = result * 16 + c - 'a' + 10;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
int64_t HexToInt() { return HexToInt(m_string); }
|
||||||
|
|
||||||
|
static constexpr bool IsUrl(const std::string_view& str)
|
||||||
|
{
|
||||||
|
return str.find("http://") == 0 || str.find("https://") == 0 || str.find("ftp://") == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsUrl() const { return IsUrl(m_string); }
|
||||||
|
|
||||||
|
void ToUpper() noexcept
|
||||||
|
{
|
||||||
|
std::transform(m_string.begin(), m_string.end(), m_string.begin(),
|
||||||
|
[](unsigned char c) { return std::toupper(c); });
|
||||||
|
}
|
||||||
|
|
||||||
|
void ToLower() noexcept
|
||||||
|
{
|
||||||
|
std::transform(m_string.begin(), m_string.end(), m_string.begin(),
|
||||||
|
[](unsigned char c) { return std::tolower(c); });
|
||||||
|
}
|
||||||
|
|
||||||
|
void Capitalize() noexcept
|
||||||
|
{
|
||||||
|
if (!m_string.empty())
|
||||||
|
{
|
||||||
|
m_string[0] = std::toupper(m_string[0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T, typename = std::enable_if_t<std::is_arithmetic_v<T>>> T FromString() const
|
||||||
|
{
|
||||||
|
T value;
|
||||||
|
c4::csubstr str = c4::to_csubstr(m_string.c_str());
|
||||||
|
c4::from_chars(str, &value);
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
// iterators
|
||||||
|
std::string::iterator begin() { return m_string.begin(); }
|
||||||
|
std::string::iterator end() { return m_string.end(); }
|
||||||
|
std::string::const_iterator cbegin() const { return m_string.cbegin(); }
|
||||||
|
std::string::const_iterator cend() const { return m_string.cend(); }
|
||||||
|
std::string::reverse_iterator rbegin() { return m_string.rbegin(); }
|
||||||
|
std::string::reverse_iterator rend() { return m_string.rend(); }
|
||||||
|
std::reverse_iterator<std::string::const_iterator> crbegin() const { return m_string.crbegin(); }
|
||||||
|
std::reverse_iterator<std::string::const_iterator> crend() const { return m_string.crend(); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::string m_string;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T> String operator+(const T& lhs, const String& rhs) noexcept { return String(lhs) + rhs; }
|
||||||
|
}
|
||||||
@@ -87,7 +87,7 @@ namespace OpenVulkano
|
|||||||
|
|
||||||
void GraphicsAppManager::UpdateCappedFpsInfo(int32_t newFpsCap)
|
void GraphicsAppManager::UpdateCappedFpsInfo(int32_t newFpsCap)
|
||||||
{
|
{
|
||||||
if (newFpsCap < 0)
|
if (newFpsCap <= 0)
|
||||||
{
|
{
|
||||||
cappedFrameTime = std::chrono::microseconds(0);
|
cappedFrameTime = std::chrono::microseconds(0);
|
||||||
}
|
}
|
||||||
|
|||||||
281
tests/StringTest.cpp
Normal file
281
tests/StringTest.cpp
Normal file
@@ -0,0 +1,281 @@
|
|||||||
|
/*
|
||||||
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <catch2/catch_all.hpp>
|
||||||
|
|
||||||
|
#include "Data/Containers/String.hpp"
|
||||||
|
|
||||||
|
using namespace OpenVulkano;
|
||||||
|
|
||||||
|
TEST_CASE("Constructors")
|
||||||
|
{
|
||||||
|
String str1;
|
||||||
|
REQUIRE(str1 == "");
|
||||||
|
|
||||||
|
String str2("Hello");
|
||||||
|
REQUIRE(str2 == "Hello");
|
||||||
|
|
||||||
|
String str3(std::string("World"));
|
||||||
|
REQUIRE(str3 == "World");
|
||||||
|
|
||||||
|
String str4(str2);
|
||||||
|
REQUIRE(str4 == "Hello");
|
||||||
|
|
||||||
|
String str5(std::move(str3));
|
||||||
|
REQUIRE(str5 == "World");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("Assignment")
|
||||||
|
{
|
||||||
|
String str1;
|
||||||
|
str1 = "Hello";
|
||||||
|
REQUIRE(str1 == "Hello");
|
||||||
|
|
||||||
|
String str2;
|
||||||
|
str2 = std::string("World");
|
||||||
|
REQUIRE(str2 == "World");
|
||||||
|
|
||||||
|
String str3;
|
||||||
|
str3 = str1;
|
||||||
|
REQUIRE(str3 == "Hello");
|
||||||
|
|
||||||
|
String str4;
|
||||||
|
str4 = std::move(str2);
|
||||||
|
REQUIRE(str4 == "World");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("Concatenation")
|
||||||
|
{
|
||||||
|
String str1("Hello");
|
||||||
|
str1 += " World";
|
||||||
|
REQUIRE(str1 == "Hello World");
|
||||||
|
|
||||||
|
String str2("Hello");
|
||||||
|
String str3 = str2 + " World";
|
||||||
|
REQUIRE(str3 == "Hello World");
|
||||||
|
|
||||||
|
String str4("Hello");
|
||||||
|
str4 += std::string(" World");
|
||||||
|
REQUIRE(str4 == "Hello World");
|
||||||
|
|
||||||
|
String str5("Hello");
|
||||||
|
String str6 = str5 + std::string(" World");
|
||||||
|
REQUIRE(str6 == "Hello World");
|
||||||
|
|
||||||
|
String str7("Hello");
|
||||||
|
str7 += String(" World");
|
||||||
|
REQUIRE(str7 == "Hello World");
|
||||||
|
|
||||||
|
String str8("Hello");
|
||||||
|
String str9 = str8 + String(" World");
|
||||||
|
REQUIRE(str9 == "Hello World");
|
||||||
|
|
||||||
|
String str10 = String("Hello") + " World";
|
||||||
|
REQUIRE(str10 == "Hello World");
|
||||||
|
|
||||||
|
String str11 = String("Hello") + std::string(" World");
|
||||||
|
REQUIRE(str11 == "Hello World");
|
||||||
|
|
||||||
|
String str12 = std::string("Hello") + String(" World");
|
||||||
|
REQUIRE(str12 == "Hello World");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("Comparison")
|
||||||
|
{
|
||||||
|
String str1("Hello");
|
||||||
|
REQUIRE(str1 == "Hello");
|
||||||
|
REQUIRE(str1 != "World");
|
||||||
|
|
||||||
|
String str2("World");
|
||||||
|
REQUIRE(str2 == "World");
|
||||||
|
REQUIRE(str2 != "Hello");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("Trim")
|
||||||
|
{
|
||||||
|
String str1(" Hello World ");
|
||||||
|
REQUIRE(str1.Trim() == "Hello World");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("FindIndex")
|
||||||
|
{
|
||||||
|
String str1("Georg will save us all from our doom");
|
||||||
|
REQUIRE(str1.FindStartIndexOf("save") == 11);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("Upper/Lower")
|
||||||
|
{
|
||||||
|
String str1("Hello World");
|
||||||
|
str1.ToUpper();
|
||||||
|
REQUIRE(str1 == "HELLO WORLD");
|
||||||
|
|
||||||
|
String str2("Hello World");
|
||||||
|
str2.ToLower();
|
||||||
|
REQUIRE(str2 == "hello world");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("Substring")
|
||||||
|
{
|
||||||
|
String str1("Hello World");
|
||||||
|
REQUIRE(str1.SubString(0, 5) == "Hello");
|
||||||
|
REQUIRE(str1.SubString(6, 11) == "World");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("FromString")
|
||||||
|
{
|
||||||
|
String str1("42");
|
||||||
|
REQUIRE(str1.FromString<int>() == 42);
|
||||||
|
|
||||||
|
String str2("42.42");
|
||||||
|
REQUIRE(str2.FromString<float>() == 42.42f);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("StartsWith")
|
||||||
|
{
|
||||||
|
String str1("Hello World");
|
||||||
|
REQUIRE(str1.StartsWith("Hello"));
|
||||||
|
REQUIRE(!str1.StartsWith("World"));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("EndsWith")
|
||||||
|
{
|
||||||
|
String str1("Hello World");
|
||||||
|
REQUIRE(str1.EndsWith("World"));
|
||||||
|
REQUIRE(!str1.EndsWith("Hello"));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("Contains")
|
||||||
|
{
|
||||||
|
String str1("Hello World");
|
||||||
|
REQUIRE(str1.Contains("Hello"));
|
||||||
|
REQUIRE(str1.Contains("World"));
|
||||||
|
REQUIRE(!str1.Contains("Georg"));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("FindEndIndexOf")
|
||||||
|
{
|
||||||
|
String str1("Georg will save us all from our doom");
|
||||||
|
REQUIRE(str1.FindEndIndexOf("save") == 11);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("TrimFront")
|
||||||
|
{
|
||||||
|
String str1(" Hello World");
|
||||||
|
REQUIRE(str1.TrimFront() == "Hello World");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("TrimBack")
|
||||||
|
{
|
||||||
|
String str1("Hello World ");
|
||||||
|
REQUIRE(str1.TrimBack() == "Hello World");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("Empty")
|
||||||
|
{
|
||||||
|
String str1;
|
||||||
|
REQUIRE(str1.Empty());
|
||||||
|
REQUIRE(!str1);
|
||||||
|
|
||||||
|
String str2("Hello World");
|
||||||
|
REQUIRE(!str2.Empty());
|
||||||
|
REQUIRE(!!str2);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("Size")
|
||||||
|
{
|
||||||
|
String str1("Hello World");
|
||||||
|
REQUIRE(str1.Size() == 11);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("Capacity")
|
||||||
|
{
|
||||||
|
String str1("Hello World");
|
||||||
|
REQUIRE(str1.Capacity() >= 11);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("CharCount")
|
||||||
|
{
|
||||||
|
String str1("Hello World");
|
||||||
|
REQUIRE(str1.CharCount() == 11);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("PopBack")
|
||||||
|
{
|
||||||
|
String str1("Hello World");
|
||||||
|
str1.PopBack();
|
||||||
|
REQUIRE(str1 == "Hello Worl");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("Clear")
|
||||||
|
{
|
||||||
|
String str1("Hello World");
|
||||||
|
str1.Clear();
|
||||||
|
REQUIRE(str1.Empty());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("Split")
|
||||||
|
{
|
||||||
|
String str1("Hello,World");
|
||||||
|
auto split = str1.Split(",");
|
||||||
|
REQUIRE(split.size() == 2);
|
||||||
|
REQUIRE(split[0] == "Hello");
|
||||||
|
REQUIRE(split[1] == "World");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("SplitAtLastOccurrence")
|
||||||
|
{
|
||||||
|
String str1 = "Hello,World,Georg";
|
||||||
|
auto split = str1.SplitAtLastOccurrence(",");
|
||||||
|
REQUIRE(split.first == "Hello,World");
|
||||||
|
REQUIRE(split.second == "Georg");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("SplitAtFirstOccurrence")
|
||||||
|
{
|
||||||
|
String str1 = "Hello,World,Georg";
|
||||||
|
auto split = str1.SplitAtFirstOccurrence(",");
|
||||||
|
REQUIRE(split.first == "Hello");
|
||||||
|
REQUIRE(split.second == "World,Georg");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("SplitAsStringViews")
|
||||||
|
{
|
||||||
|
String str1("Hello,World");
|
||||||
|
auto split = str1.SplitAsStringViews(",");
|
||||||
|
REQUIRE(split.size() == 2);
|
||||||
|
REQUIRE(split[0] == "Hello");
|
||||||
|
REQUIRE(split[1] == "World");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("SplitAtFirstOccurrenceAsStringViews")
|
||||||
|
{
|
||||||
|
String str1 = "Hello,World,Georg";
|
||||||
|
auto split = str1.SplitAtFirstOccurenceAsStringViews(",");
|
||||||
|
REQUIRE(split.first == "Hello");
|
||||||
|
REQUIRE(split.second == "World,Georg");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("SplitAtLastOccurenceAsStringViews")
|
||||||
|
{
|
||||||
|
String str1 = "Hello,World,Georg";
|
||||||
|
auto split = str1.SplitAtLastOccurenceAsStringViews(",");
|
||||||
|
REQUIRE(split.first == "Hello,World");
|
||||||
|
REQUIRE(split.second == "Georg");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("OctToInt")
|
||||||
|
{
|
||||||
|
String str1("47");
|
||||||
|
REQUIRE(str1.OctToInt() == 39);
|
||||||
|
REQUIRE(String::OctToInt("552") == 362);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("HexToInt")
|
||||||
|
{
|
||||||
|
String str1("2A");
|
||||||
|
REQUIRE(str1.HexToInt() == 42);
|
||||||
|
REQUIRE(String::HexToInt("FF") == 255);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user