mirror of
https://github.com/transmission/transmission.git
synced 2025-12-20 02:18:42 +00:00
feat: add tr_strbuf (#2810)
* feat: add tr_strbuf class for building tmp strings Based on fmt::basic_memory_buf, this is a growable string buffer that has an initial size that's large enough to build most filenames or URLs without needing heap allocations. Adds a couple of extra helpers such as a `c_str()` method to make dealing with old zero-terminated string APIs easier.
This commit is contained in:
@@ -147,6 +147,9 @@ if(WIN32)
|
|||||||
endif()
|
endif()
|
||||||
|
|
||||||
find_package(Fmt)
|
find_package(Fmt)
|
||||||
|
add_definitions(-DFMT_HEADER_ONLY)
|
||||||
|
include_directories(SYSTEM ${LIBFMT_INCLUDE_DIRS})
|
||||||
|
|
||||||
find_package(UtfCpp)
|
find_package(UtfCpp)
|
||||||
find_package(Threads)
|
find_package(Threads)
|
||||||
find_package(PkgConfig QUIET)
|
find_package(PkgConfig QUIET)
|
||||||
@@ -343,8 +346,6 @@ if(NOT USE_SYSTEM_NATPMP)
|
|||||||
set(NATPMP_DEFINITIONS -DNATPMP_STATICLIB)
|
set(NATPMP_DEFINITIONS -DNATPMP_STATICLIB)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
set(LIBFMT_DEFINITIONS -DFMT_HEADER_ONLY)
|
|
||||||
|
|
||||||
tr_add_external_auto_library(MINIUPNPC miniupnpc miniupnpc
|
tr_add_external_auto_library(MINIUPNPC miniupnpc miniupnpc
|
||||||
CMAKE_ARGS
|
CMAKE_ARGS
|
||||||
-DUPNPC_BUILD_STATIC=ON
|
-DUPNPC_BUILD_STATIC=ON
|
||||||
|
|||||||
@@ -344,6 +344,7 @@
|
|||||||
C1305EBE186A13B100F03351 /* file.cc in Sources */ = {isa = PBXBuildFile; fileRef = C1305EB8186A134000F03351 /* file.cc */; };
|
C1305EBE186A13B100F03351 /* file.cc in Sources */ = {isa = PBXBuildFile; fileRef = C1305EB8186A134000F03351 /* file.cc */; };
|
||||||
C1425B361EE9C605001DB85F /* tr-assert.h in Headers */ = {isa = PBXBuildFile; fileRef = C1425B331EE9C5EA001DB85F /* tr-assert.h */; };
|
C1425B361EE9C605001DB85F /* tr-assert.h in Headers */ = {isa = PBXBuildFile; fileRef = C1425B331EE9C5EA001DB85F /* tr-assert.h */; };
|
||||||
C1425B371EE9C705001DB85F /* tr-macros.h in Headers */ = {isa = PBXBuildFile; fileRef = C1425B341EE9C5EA001DB85F /* tr-macros.h */; };
|
C1425B371EE9C705001DB85F /* tr-macros.h in Headers */ = {isa = PBXBuildFile; fileRef = C1425B341EE9C5EA001DB85F /* tr-macros.h */; };
|
||||||
|
888A256631B3DE536FEB8B00 /* tr-strbuf.h in Headers */ = {isa = PBXBuildFile; fileRef = 888A256631B3DE536FEB8B01 /* tr-strbuf.h */; };
|
||||||
C1425B381EE9C805001DB85F /* peer-socket.h in Headers */ = {isa = PBXBuildFile; fileRef = C1425B351EE9C5EA001DB85F /* peer-socket.h */; };
|
C1425B381EE9C805001DB85F /* peer-socket.h in Headers */ = {isa = PBXBuildFile; fileRef = C1425B351EE9C5EA001DB85F /* peer-socket.h */; };
|
||||||
C1639A741A55F4E000E42033 /* libb64.a in Frameworks */ = {isa = PBXBuildFile; fileRef = C1639A6F1A55F4D600E42033 /* libb64.a */; };
|
C1639A741A55F4E000E42033 /* libb64.a in Frameworks */ = {isa = PBXBuildFile; fileRef = C1639A6F1A55F4D600E42033 /* libb64.a */; };
|
||||||
C1639A781A55F56600E42033 /* cdecode.c in Sources */ = {isa = PBXBuildFile; fileRef = C1639A761A55F56600E42033 /* cdecode.c */; };
|
C1639A781A55F56600E42033 /* cdecode.c in Sources */ = {isa = PBXBuildFile; fileRef = C1639A761A55F56600E42033 /* cdecode.c */; };
|
||||||
@@ -1070,6 +1071,7 @@
|
|||||||
C1425B321EE9C5EA001DB85F /* tr-assert.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "tr-assert.cc"; sourceTree = "<group>"; };
|
C1425B321EE9C5EA001DB85F /* tr-assert.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "tr-assert.cc"; sourceTree = "<group>"; };
|
||||||
C1425B331EE9C5EA001DB85F /* tr-assert.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "tr-assert.h"; sourceTree = "<group>"; };
|
C1425B331EE9C5EA001DB85F /* tr-assert.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "tr-assert.h"; sourceTree = "<group>"; };
|
||||||
C1425B341EE9C5EA001DB85F /* tr-macros.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "tr-macros.h"; sourceTree = "<group>"; };
|
C1425B341EE9C5EA001DB85F /* tr-macros.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "tr-macros.h"; sourceTree = "<group>"; };
|
||||||
|
888A256631B3DE536FEB8B01 /* tr-strbuf.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "tr-macros.h"; sourceTree = "<group>"; };
|
||||||
C1425B351EE9C5EA001DB85F /* peer-socket.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "peer-socket.h"; sourceTree = "<group>"; };
|
C1425B351EE9C5EA001DB85F /* peer-socket.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "peer-socket.h"; sourceTree = "<group>"; };
|
||||||
C1639A6F1A55F4D600E42033 /* libb64.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libb64.a; sourceTree = BUILT_PRODUCTS_DIR; };
|
C1639A6F1A55F4D600E42033 /* libb64.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libb64.a; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
C1639A761A55F56600E42033 /* cdecode.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = cdecode.c; path = src/cdecode.c; sourceTree = "<group>"; };
|
C1639A761A55F56600E42033 /* cdecode.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = cdecode.c; path = src/cdecode.c; sourceTree = "<group>"; };
|
||||||
@@ -1542,6 +1544,7 @@
|
|||||||
A22CFCA60FC24ED80009BD3E /* tr-dht.cc */,
|
A22CFCA60FC24ED80009BD3E /* tr-dht.cc */,
|
||||||
A22CFCA70FC24ED80009BD3E /* tr-dht.h */,
|
A22CFCA70FC24ED80009BD3E /* tr-dht.h */,
|
||||||
C1425B341EE9C5EA001DB85F /* tr-macros.h */,
|
C1425B341EE9C5EA001DB85F /* tr-macros.h */,
|
||||||
|
888A256631B3DE536FEB8B01 /* tr-strbuf.h */,
|
||||||
C1425B351EE9C5EA001DB85F /* peer-socket.h */,
|
C1425B351EE9C5EA001DB85F /* peer-socket.h */,
|
||||||
A284214212DA663E00FBDDBB /* tr-udp.cc */,
|
A284214212DA663E00FBDDBB /* tr-udp.cc */,
|
||||||
A284214312DA663E00FBDDBB /* tr-udp.h */,
|
A284214312DA663E00FBDDBB /* tr-udp.h */,
|
||||||
@@ -2067,6 +2070,7 @@
|
|||||||
BEFC1E3B0C07861A00B0BB3C /* platform.h in Headers */,
|
BEFC1E3B0C07861A00B0BB3C /* platform.h in Headers */,
|
||||||
C1425B361EE9C605001DB85F /* tr-assert.h in Headers */,
|
C1425B361EE9C605001DB85F /* tr-assert.h in Headers */,
|
||||||
C1425B371EE9C705001DB85F /* tr-macros.h in Headers */,
|
C1425B371EE9C705001DB85F /* tr-macros.h in Headers */,
|
||||||
|
888A256631B3DE536FEB8B00 /* tr-strbuf.h in Headers */,
|
||||||
C1425B381EE9C805001DB85F /* peer-socket.h in Headers */,
|
C1425B381EE9C805001DB85F /* peer-socket.h in Headers */,
|
||||||
BEFC1E450C07861A00B0BB3C /* net.h in Headers */,
|
BEFC1E450C07861A00B0BB3C /* net.h in Headers */,
|
||||||
BEFC1E4D0C07861A00B0BB3C /* session.h in Headers */,
|
BEFC1E4D0C07861A00B0BB3C /* session.h in Headers */,
|
||||||
|
|||||||
@@ -13,11 +13,6 @@ include_directories(
|
|||||||
SYSTEM
|
SYSTEM
|
||||||
${CURL_INCLUDE_DIRS}
|
${CURL_INCLUDE_DIRS}
|
||||||
${EVENT2_INCLUDE_DIRS}
|
${EVENT2_INCLUDE_DIRS}
|
||||||
${LIBFMT_INCLUDE_DIRS}
|
|
||||||
)
|
|
||||||
|
|
||||||
add_definitions(
|
|
||||||
${LIBFMT_DEFINITIONS}
|
|
||||||
)
|
)
|
||||||
|
|
||||||
set(${PROJECT_NAME}_SOURCES
|
set(${PROJECT_NAME}_SOURCES
|
||||||
|
|||||||
@@ -130,7 +130,6 @@ include_directories(
|
|||||||
)
|
)
|
||||||
include_directories(
|
include_directories(
|
||||||
SYSTEM
|
SYSTEM
|
||||||
${LIBFMT_INCLUDE_DIRS}
|
|
||||||
${LIBAPPINDICATOR_INCLUDE_DIRS}
|
${LIBAPPINDICATOR_INCLUDE_DIRS}
|
||||||
${GTK_INCLUDE_DIRS}
|
${GTK_INCLUDE_DIRS}
|
||||||
${CURL_INCLUDE_DIRS}
|
${CURL_INCLUDE_DIRS}
|
||||||
@@ -159,7 +158,6 @@ add_definitions(
|
|||||||
-DPANGOMM_DISABLE_DEPRECATED
|
-DPANGOMM_DISABLE_DEPRECATED
|
||||||
-DSIGCXX_DISABLE_DEPRECATED
|
-DSIGCXX_DISABLE_DEPRECATED
|
||||||
${GTK_CFLAGS_OTHER}
|
${GTK_CFLAGS_OTHER}
|
||||||
${LIBFMT_DEFINITIONS}
|
|
||||||
)
|
)
|
||||||
|
|
||||||
tr_win32_app_info(${PROJECT_NAME}_WIN32_RC_FILE
|
tr_win32_app_info(${PROJECT_NAME}_WIN32_RC_FILE
|
||||||
|
|||||||
@@ -144,6 +144,7 @@ set(${PROJECT_NAME}_PUBLIC_HEADERS
|
|||||||
tr-assert.h
|
tr-assert.h
|
||||||
tr-getopt.h
|
tr-getopt.h
|
||||||
tr-macros.h
|
tr-macros.h
|
||||||
|
tr-strbuf.h
|
||||||
transmission.h
|
transmission.h
|
||||||
utils.h
|
utils.h
|
||||||
variant.h
|
variant.h
|
||||||
@@ -216,7 +217,6 @@ endif()
|
|||||||
add_definitions(
|
add_definitions(
|
||||||
-D__TRANSMISSION__
|
-D__TRANSMISSION__
|
||||||
"-DPACKAGE_DATA_DIR=\"${CMAKE_INSTALL_FULL_DATAROOTDIR}\""
|
"-DPACKAGE_DATA_DIR=\"${CMAKE_INSTALL_FULL_DATAROOTDIR}\""
|
||||||
${LIBFMT_DEFINITIONS}
|
|
||||||
${NATPMP_DEFINITIONS}
|
${NATPMP_DEFINITIONS}
|
||||||
${MINIUPNPC_DEFINITIONS}
|
${MINIUPNPC_DEFINITIONS}
|
||||||
)
|
)
|
||||||
@@ -257,7 +257,6 @@ include_directories(
|
|||||||
|
|
||||||
include_directories(
|
include_directories(
|
||||||
SYSTEM
|
SYSTEM
|
||||||
${LIBFMT_INCLUDE_DIRS}
|
|
||||||
${UTFCPP_INCLUDE_DIRS}
|
${UTFCPP_INCLUDE_DIRS}
|
||||||
${DEFLATE_INCLUDE_DIRS}
|
${DEFLATE_INCLUDE_DIRS}
|
||||||
${CRYPTO_INCLUDE_DIRS}
|
${CRYPTO_INCLUDE_DIRS}
|
||||||
|
|||||||
180
libtransmission/tr-strbuf.h
Normal file
180
libtransmission/tr-strbuf.h
Normal file
@@ -0,0 +1,180 @@
|
|||||||
|
// This file Copyright © 2022 Mnemosyne LLC.
|
||||||
|
// It may be used under GPLv2 (SPDX: GPL-2.0), GPLv3 (SPDX: GPL-3.0),
|
||||||
|
// or any future license endorsed by Mnemosyne LLC.
|
||||||
|
// License text can be found in the licenses/ folder.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <string_view>
|
||||||
|
|
||||||
|
#include <fmt/format.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A memory buffer which uses a builtin array of N bytes,
|
||||||
|
* but falls back to heap allocation when necessary.
|
||||||
|
* Useful for building temp strings without heap allocation.
|
||||||
|
*
|
||||||
|
* `fmt::basic_memory_buffer` is final, so aggregate intead
|
||||||
|
* of subclassing ¯\_(ツ)_/¯
|
||||||
|
*/
|
||||||
|
template<typename T, size_t N>
|
||||||
|
class tr_strbuf
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
fmt::basic_memory_buffer<T, N> buffer_;
|
||||||
|
|
||||||
|
public:
|
||||||
|
using value_type = T;
|
||||||
|
using const_reference = const T&;
|
||||||
|
|
||||||
|
tr_strbuf() = default;
|
||||||
|
|
||||||
|
auto& operator=(tr_strbuf&& other)
|
||||||
|
{
|
||||||
|
buffer_ = std::move(other.buffer_);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename ContiguousRange>
|
||||||
|
tr_strbuf(ContiguousRange const& in)
|
||||||
|
{
|
||||||
|
buffer_.append(in);
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] constexpr auto begin()
|
||||||
|
{
|
||||||
|
return buffer_.begin();
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] constexpr auto end()
|
||||||
|
{
|
||||||
|
return buffer_.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] constexpr auto begin() const
|
||||||
|
{
|
||||||
|
return buffer_.begin();
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] constexpr auto end() const
|
||||||
|
{
|
||||||
|
return buffer_.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] T& operator[](size_t pos)
|
||||||
|
{
|
||||||
|
return buffer_[pos];
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] constexpr T const& operator[](size_t pos) const
|
||||||
|
{
|
||||||
|
return buffer_[pos];
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] auto size() const
|
||||||
|
{
|
||||||
|
return buffer_.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] bool empty() const
|
||||||
|
{
|
||||||
|
return size() == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] auto* data()
|
||||||
|
{
|
||||||
|
return buffer_.data();
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] auto const* data() const
|
||||||
|
{
|
||||||
|
return buffer_.data();
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
|
||||||
|
auto clear()
|
||||||
|
{
|
||||||
|
return buffer_.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
auto resize(size_t n)
|
||||||
|
{
|
||||||
|
return buffer_.resize(n);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto push_back(T const& value)
|
||||||
|
{
|
||||||
|
return buffer_.push_back(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename ContiguousRange>
|
||||||
|
auto append(ContiguousRange const& range)
|
||||||
|
{
|
||||||
|
return buffer_.append(std::data(range), std::data(range) + std::size(range));
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename ContiguousRange>
|
||||||
|
auto& operator+=(ContiguousRange const& range)
|
||||||
|
{
|
||||||
|
append(range);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename ContiguousRange>
|
||||||
|
auto& operator=(ContiguousRange const& range)
|
||||||
|
{
|
||||||
|
clear();
|
||||||
|
append(range);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename... ContiguousRange>
|
||||||
|
void buildPath(ContiguousRange const&... args)
|
||||||
|
{
|
||||||
|
buffer_.reserve(sizeof...(args) + (std::size(args) + ...));
|
||||||
|
((append(args), push_back('/')), ...);
|
||||||
|
resize(size() - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ensure that the buffer's string is zero-terminated, e.g. for
|
||||||
|
* external APIs that require char* strings.
|
||||||
|
*
|
||||||
|
* Note that the added trailing '\0' does not increment size().
|
||||||
|
* This is to ensure that strlen(buf.c_str()) == buf.size().
|
||||||
|
*/
|
||||||
|
void ensure_sz()
|
||||||
|
{
|
||||||
|
auto const n = size();
|
||||||
|
buffer_.try_reserve(n + 1);
|
||||||
|
buffer_[n] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
auto const* c_str()
|
||||||
|
{
|
||||||
|
ensure_sz();
|
||||||
|
return data();
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] constexpr auto sv() const
|
||||||
|
{
|
||||||
|
return std::string_view{ data(), size() };
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Good for building short-term URLs.
|
||||||
|
* The initial size is big enough to avoid heap allocs in most cases,
|
||||||
|
* but that also makes it a poor choice for longer-term storage.
|
||||||
|
* https://stackoverflow.com/a/417184
|
||||||
|
*/
|
||||||
|
using tr_urlbuf = tr_strbuf<char, 2000>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Good for building short-term filenames.
|
||||||
|
* The initial size is big enough to avoid heap allocs in most cases,
|
||||||
|
* but that also makes it a poor choice for longer-term storage.
|
||||||
|
* https://stackoverflow.com/a/65174437
|
||||||
|
*/
|
||||||
|
using tr_pathbuf = tr_strbuf<char, 4096>;
|
||||||
@@ -26,6 +26,7 @@ add_executable(libtransmission-test
|
|||||||
rename-test.cc
|
rename-test.cc
|
||||||
rpc-test.cc
|
rpc-test.cc
|
||||||
session-test.cc
|
session-test.cc
|
||||||
|
strbuf-test.cc
|
||||||
subprocess-test-script.cmd
|
subprocess-test-script.cmd
|
||||||
subprocess-test.cc
|
subprocess-test.cc
|
||||||
test-fixtures.h
|
test-fixtures.h
|
||||||
@@ -38,7 +39,6 @@ add_executable(libtransmission-test
|
|||||||
|
|
||||||
target_compile_definitions(libtransmission-test
|
target_compile_definitions(libtransmission-test
|
||||||
PRIVATE
|
PRIVATE
|
||||||
${LIBFMT_DEFINITIONS}
|
|
||||||
-DLIBTRANSMISSION_TEST_ASSETS_DIR="${CMAKE_CURRENT_SOURCE_DIR}/assets"
|
-DLIBTRANSMISSION_TEST_ASSETS_DIR="${CMAKE_CURRENT_SOURCE_DIR}/assets"
|
||||||
__TRANSMISSION__)
|
__TRANSMISSION__)
|
||||||
|
|
||||||
|
|||||||
133
tests/libtransmission/strbuf-test.cc
Normal file
133
tests/libtransmission/strbuf-test.cc
Normal file
@@ -0,0 +1,133 @@
|
|||||||
|
// This file Copyright (C) 2022 Mnemosyne LLC.
|
||||||
|
// It may be used under GPLv2 (SPDX: GPL-2.0), GPLv3 (SPDX: GPL-3.0),
|
||||||
|
// or any future license endorsed by Mnemosyne LLC.
|
||||||
|
// License text can be found in the licenses/ folder.
|
||||||
|
|
||||||
|
#include <string_view>
|
||||||
|
|
||||||
|
#include "transmission.h"
|
||||||
|
|
||||||
|
#include "tr-strbuf.h"
|
||||||
|
|
||||||
|
#include "test-fixtures.h"
|
||||||
|
|
||||||
|
using StrbufTest = ::testing::Test;
|
||||||
|
using namespace std::literals;
|
||||||
|
|
||||||
|
TEST_F(StrbufTest, append)
|
||||||
|
{
|
||||||
|
static auto constexpr Value = "Hello, World!"sv;
|
||||||
|
|
||||||
|
auto buf = tr_pathbuf{};
|
||||||
|
|
||||||
|
buf.append(Value.substr(0, 5));
|
||||||
|
EXPECT_EQ(Value.substr(0, 5), buf.sv());
|
||||||
|
|
||||||
|
buf.append(Value.substr(5));
|
||||||
|
EXPECT_EQ(Value, buf.sv());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(StrbufTest, assign)
|
||||||
|
{
|
||||||
|
static auto constexpr Value = "Hello, World!"sv;
|
||||||
|
|
||||||
|
auto buf = tr_pathbuf{};
|
||||||
|
buf = Value;
|
||||||
|
EXPECT_EQ(Value, buf.sv());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(StrbufTest, buildPath)
|
||||||
|
{
|
||||||
|
auto buf = tr_pathbuf{};
|
||||||
|
buf.buildPath("foo"sv, "bar"sv, "baz"sv);
|
||||||
|
EXPECT_EQ("foo/bar/baz", buf.sv());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(StrbufTest, clear)
|
||||||
|
{
|
||||||
|
static auto constexpr Value = "Hello, World!"sv;
|
||||||
|
auto buf = tr_pathbuf{ Value };
|
||||||
|
EXPECT_EQ(Value, buf.sv());
|
||||||
|
buf.clear();
|
||||||
|
EXPECT_TRUE(std::empty(buf));
|
||||||
|
EXPECT_EQ(0U, std::size(buf));
|
||||||
|
EXPECT_EQ(""sv, buf.sv());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(StrbufTest, constructorDefault)
|
||||||
|
{
|
||||||
|
auto buf = tr_pathbuf{};
|
||||||
|
EXPECT_EQ(0, std::size(buf));
|
||||||
|
EXPECT_TRUE(std::empty(buf));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(StrbufTest, constructorAssign)
|
||||||
|
{
|
||||||
|
static auto constexpr Value = "Hello, World!"sv;
|
||||||
|
|
||||||
|
auto buf = tr_pathbuf{ Value };
|
||||||
|
EXPECT_EQ(Value, buf.sv());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(StrbufTest, heap)
|
||||||
|
{
|
||||||
|
static auto constexpr Value = "Hello, World!"sv;
|
||||||
|
|
||||||
|
auto buf = tr_strbuf<char, 10>{};
|
||||||
|
buf.append(Value.substr(0, 5));
|
||||||
|
auto const* const data_stack = std::data(buf);
|
||||||
|
buf.append(Value.substr(5));
|
||||||
|
auto const* const data_heap = std::data(buf);
|
||||||
|
EXPECT_EQ(Value, buf.sv());
|
||||||
|
EXPECT_NE(data_stack, data_heap);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(StrbufTest, indexOperator)
|
||||||
|
{
|
||||||
|
static auto constexpr Value1 = "Hello, World!"sv;
|
||||||
|
static auto constexpr Value2 = "Wello, World!"sv;
|
||||||
|
|
||||||
|
// mutable
|
||||||
|
{
|
||||||
|
auto buf = tr_pathbuf{ Value1 };
|
||||||
|
buf[0] = 'W';
|
||||||
|
EXPECT_EQ(Value2, buf.sv());
|
||||||
|
}
|
||||||
|
|
||||||
|
// const
|
||||||
|
{
|
||||||
|
auto const buf = tr_pathbuf{ Value1 };
|
||||||
|
EXPECT_EQ(Value1.front(), buf[0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(StrbufTest, iterators)
|
||||||
|
{
|
||||||
|
static auto constexpr Value = "Hello, World!"sv;
|
||||||
|
|
||||||
|
// mutable
|
||||||
|
{
|
||||||
|
auto buf = tr_pathbuf{ Value };
|
||||||
|
auto begin = std::begin(buf);
|
||||||
|
auto end = std::end(buf);
|
||||||
|
EXPECT_EQ(Value.front(), *begin);
|
||||||
|
EXPECT_EQ(std::size(Value), std::distance(begin, end));
|
||||||
|
}
|
||||||
|
|
||||||
|
// const
|
||||||
|
{
|
||||||
|
auto const buf = tr_pathbuf{ Value };
|
||||||
|
auto const begin = std::begin(buf);
|
||||||
|
auto const end = std::end(buf);
|
||||||
|
EXPECT_EQ(Value.front(), *begin);
|
||||||
|
EXPECT_EQ(std::size(Value), std::distance(begin, end));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(StrbufTest, sz)
|
||||||
|
{
|
||||||
|
static char const* const Value = "Hello, World!";
|
||||||
|
auto buf = tr_pathbuf{ std::string_view{ Value } };
|
||||||
|
EXPECT_STREQ(Value, buf.c_str());
|
||||||
|
EXPECT_EQ(strlen(Value), std::size(buf));
|
||||||
|
}
|
||||||
@@ -2,10 +2,6 @@ project(trutils)
|
|||||||
|
|
||||||
add_compile_options(${CXX_WARNING_FLAGS})
|
add_compile_options(${CXX_WARNING_FLAGS})
|
||||||
|
|
||||||
add_definitions(
|
|
||||||
${LIBFMT_DEFINITIONS}
|
|
||||||
)
|
|
||||||
|
|
||||||
include_directories(
|
include_directories(
|
||||||
${CMAKE_SOURCE_DIR}
|
${CMAKE_SOURCE_DIR}
|
||||||
)
|
)
|
||||||
@@ -13,7 +9,6 @@ include_directories(
|
|||||||
SYSTEM
|
SYSTEM
|
||||||
${EVENT2_INCLUDE_DIRS}
|
${EVENT2_INCLUDE_DIRS}
|
||||||
${CURL_INCLUDE_DIRS}
|
${CURL_INCLUDE_DIRS}
|
||||||
${LIBFMT_INCLUDE_DIRS}
|
|
||||||
)
|
)
|
||||||
|
|
||||||
foreach(P create edit remote show)
|
foreach(P create edit remote show)
|
||||||
|
|||||||
Reference in New Issue
Block a user