Skip to content

Commit

Permalink
update join_strings
Browse files Browse the repository at this point in the history
  • Loading branch information
i80287 committed Dec 24, 2024
1 parent c1a42e3 commit 5bded55
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 33 deletions.
52 changes: 25 additions & 27 deletions misc/join_strings.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -88,18 +88,18 @@ ATTRIBUTE_ALWAYS_INLINE inline std::basic_string<CharType> ToStringOneArg(const
template <class CharType, class... Args>
[[nodiscard]]
ATTRIBUTE_ALWAYS_INLINE
constexpr std::enable_if_t<is_char_v<CharType>, std::size_t> CalculateStringArgsSize(CharType /*c*/, const Args&... args) noexcept;
constexpr std::enable_if_t<is_char_v<CharType>, std::size_t> CalculateStringArgsSize(CharType /*c*/, Args... args) noexcept;

template <class CharType, class... Args>
[[nodiscard]]
ATTRIBUTE_ALWAYS_INLINE
constexpr std::enable_if_t<is_char_v<CharType>, std::size_t> CalculateStringArgsSize(std::basic_string_view<CharType> s, const Args&... args) noexcept;
constexpr std::enable_if_t<is_char_v<CharType>, std::size_t> CalculateStringArgsSize(std::basic_string_view<CharType> s, Args... args) noexcept;

// clang-format on

template <class CharType, class... Args>
constexpr std::enable_if_t<is_char_v<CharType>, std::size_t> CalculateStringArgsSize(
CharType /*c*/, const Args &...args) noexcept {
CharType /*c*/, Args... args) noexcept {
size_t size = 1;
if constexpr (sizeof...(args) > 0) {
size += join_strings_detail::CalculateStringArgsSize<CharType>(args...);
Expand All @@ -109,7 +109,7 @@ constexpr std::enable_if_t<is_char_v<CharType>, std::size_t> CalculateStringArgs

template <class CharType, class... Args>
constexpr std::enable_if_t<is_char_v<CharType>, std::size_t> CalculateStringArgsSize(
std::basic_string_view<CharType> s, const Args &...args) noexcept {
std::basic_string_view<CharType> s, Args... args) noexcept {
size_t size = s.size();
if constexpr (sizeof...(args) > 0) {
size += join_strings_detail::CalculateStringArgsSize<CharType>(args...);
Expand All @@ -123,19 +123,20 @@ template <class CharType, class... Args>
ATTRIBUTE_NONNULL_ALL_ARGS
ATTRIBUTE_ACCESS(write_only, 1)
ATTRIBUTE_ALWAYS_INLINE
constexpr std::enable_if_t<is_char_v<CharType>, void> WriteStringsInplace(CharType* result, CharType c, const Args&... args) noexcept;
constexpr std::enable_if_t<is_char_v<CharType>, void> WriteStringsInplace(CharType* result, CharType c, Args... args) noexcept;

template <class CharType, class... Args>
ATTRIBUTE_NONNULL_ALL_ARGS
ATTRIBUTE_ACCESS(write_only, 1)
ATTRIBUTE_ALWAYS_INLINE
constexpr std::enable_if_t<is_char_v<CharType>, void> WriteStringsInplace(CharType* result, std::basic_string_view<CharType> s, const Args&... args) noexcept;
constexpr std::enable_if_t<is_char_v<CharType>, void> WriteStringsInplace(CharType* result, std::basic_string_view<CharType> s, Args... args) noexcept;

// clang-format on

template <class CharType, class... Args>
constexpr std::enable_if_t<is_char_v<CharType>, void> WriteStringsInplace(
CharType *result, CharType c, const Args &...args) noexcept {
constexpr std::enable_if_t<is_char_v<CharType>, void> WriteStringsInplace(CharType *result,
CharType c,
Args... args) noexcept {
*result = c;
if constexpr (sizeof...(args) > 0) {
join_strings_detail::WriteStringsInplace<CharType>(result + 1, args...);
Expand All @@ -144,7 +145,7 @@ constexpr std::enable_if_t<is_char_v<CharType>, void> WriteStringsInplace(

template <class CharType, class... Args>
constexpr std::enable_if_t<is_char_v<CharType>, void> WriteStringsInplace(
CharType *result, std::basic_string_view<CharType> s, const Args &...args) noexcept {
CharType *result, std::basic_string_view<CharType> s, Args... args) noexcept {
std::char_traits<CharType>::copy(result, s.data(), s.size());
if constexpr (sizeof...(args) > 0) {
join_strings_detail::WriteStringsInplace<CharType>(result + s.size(), args...);
Expand All @@ -157,18 +158,17 @@ template <class CharType, class... Args>
ATTRIBUTE_NONNULL_ALL_ARGS
ATTRIBUTE_SIZED_ACCESS(write_only, 1, 2)
ATTRIBUTE_ALWAYS_INLINE
constexpr std::enable_if_t<is_char_v<CharType>, void> WriteStringToBuffer(CharType* buffer, size_t /*buffer_size*/, const Args&... args) noexcept {
constexpr std::enable_if_t<is_char_v<CharType>, void> WriteStringToBuffer(CharType* buffer, size_t /*buffer_size*/, Args... args) noexcept {
join_strings_detail::WriteStringsInplace<CharType>(buffer, args...);
}

// clang-format on

template <class CharType, class... Args>
[[nodiscard]]
ATTRIBUTE_ALWAYS_INLINE inline std::enable_if_t<is_char_v<CharType>, std::basic_string<CharType>>
JoinStringsImpl(const Args &...args) {
[[nodiscard]] inline std::enable_if_t<is_char_v<CharType>, std::basic_string<CharType>>
JoinStringsImpl(Args... args) {
if constexpr (sizeof...(args) >= 2) {
std::size_t size = CalculateStringArgsSize<CharType>(args...);
const std::size_t size = CalculateStringArgsSize<CharType>(args...);
std::basic_string<CharType> result(size, CharType{});
join_strings_detail::WriteStringToBuffer<CharType>(result.data(), result.size(), args...);
return result;
Expand All @@ -182,44 +182,44 @@ JoinStringsImpl(const Args &...args) {
template <class CharType, size_t I, class... Args>
[[nodiscard]]
ATTRIBUTE_ALWAYS_INLINE
inline std::enable_if_t<is_char_v<CharType>, std::basic_string<CharType>> JoinStringsConvArgsToStrViewImpl(std::basic_string_view<CharType> str, const Args&... args);
inline
std::enable_if_t<is_char_v<CharType>, std::basic_string<CharType>> JoinStringsConvArgsToStrViewImpl(std::basic_string_view<CharType> str, const Args&... args);

template <class CharType, size_t I, class... Args>
[[nodiscard]]
ATTRIBUTE_ACCESS(read_only, 1)
ATTRIBUTE_ALWAYS_INLINE
inline std::enable_if_t<is_char_v<CharType>, std::basic_string<CharType>> JoinStringsConvArgsToStrViewImpl(const CharType* str, const Args&... args);
inline
std::enable_if_t<is_char_v<CharType>, std::basic_string<CharType>> JoinStringsConvArgsToStrViewImpl(const CharType* str, const Args&... args);

template <class CharType, size_t I, class T, class... Args>
[[nodiscard]]
ATTRIBUTE_ALWAYS_INLINE
inline std::enable_if_t<is_char_v<CharType> && std::is_arithmetic_v<T>, std::basic_string<CharType>> JoinStringsConvArgsToStrViewImpl(T num, const Args&... args);
inline
std::enable_if_t<is_char_v<CharType> && std::is_arithmetic_v<T>, std::basic_string<CharType>> JoinStringsConvArgsToStrViewImpl(T num, const Args&... args);

// clang-format on

template <class CharType, size_t I, class... Args>
[[nodiscard]]
ATTRIBUTE_ALWAYS_INLINE inline std::enable_if_t<is_char_v<CharType>, std::basic_string<CharType>>
inline std::enable_if_t<is_char_v<CharType>, std::basic_string<CharType>>
JoinStringsConvArgsToStrViewImpl(std::basic_string_view<CharType> str, const Args &...args) {
if constexpr (I == 1 + sizeof...(args)) {
return join_strings_detail::JoinStringsImpl<CharType>(str, args...);
} else {
return join_strings_detail::JoinStringsConvArgsToStrViewImpl<CharType, I + 1>(args..., str);
}
}

template <class CharType, size_t I, class... Args>
[[nodiscard]]
ATTRIBUTE_ALWAYS_INLINE inline std::enable_if_t<is_char_v<CharType>, std::basic_string<CharType>>
inline std::enable_if_t<is_char_v<CharType>, std::basic_string<CharType>>
JoinStringsConvArgsToStrViewImpl(const CharType *str, const Args &...args) {
static_assert(I < 1 + sizeof...(args));
return join_strings_detail::JoinStringsConvArgsToStrViewImpl<CharType, I + 1>(
args..., str ? std::basic_string_view<CharType>{str} : std::basic_string_view<CharType>{});
}

template <class CharType, size_t I, class T, class... Args>
[[nodiscard]]
ATTRIBUTE_ALWAYS_INLINE inline std::enable_if_t<is_char_v<CharType> && std::is_arithmetic_v<T>,
std::basic_string<CharType>>
inline std::enable_if_t<is_char_v<CharType> && std::is_arithmetic_v<T>, std::basic_string<CharType>>
JoinStringsConvArgsToStrViewImpl(T num, const Args &...args) {
if constexpr (std::is_same_v<T, CharType>) {
if constexpr (I == 1 + sizeof...(args)) {
Expand Down Expand Up @@ -338,9 +338,7 @@ using determine_char_t = typename determine_char_type<Args...>::type;
/// where CharType is deducted by the @a Args... or HintCharType
/// if @a Args... is pack of numeric types
template <class HintCharType = char, class... Args>
[[nodiscard]]
ATTRIBUTE_ALWAYS_INLINE
inline auto JoinStrings(const Args&... args) {
[[nodiscard]] ATTRIBUTE_ALWAYS_INLINE inline auto JoinStrings(const Args&... args) {
static_assert(sizeof...(args) >= 1, "Empty input is explicitly prohibited");

using DeducedCharType = join_strings_detail::determine_char_t<Args...>;
Expand Down
12 changes: 6 additions & 6 deletions misc/test_join_strings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

#include "join_strings.hpp"

#define MAKE_JOIN_STRINGS_TEST_BLOCK(CHAR_TYPE) \
#define MAKE_JOIN_STRINGS_TESTS_SUITE(CHAR_TYPE) \
do { \
assert(misc::JoinStrings(STR_LITERAL("")) == STR_LITERAL("")); \
assert(misc::JoinStrings(STR_LITERAL("ab"), STR_LITERAL("cde")) == STR_LITERAL("abcde")); \
Expand Down Expand Up @@ -70,26 +70,26 @@

int main() {
#define STR_LITERAL(expr) expr
MAKE_JOIN_STRINGS_TEST_BLOCK(char);
MAKE_JOIN_STRINGS_TESTS_SUITE(char);
#undef STR_LITERAL

#define STR_LITERAL(expr) L##expr
MAKE_JOIN_STRINGS_TEST_BLOCK(wchar_t);
MAKE_JOIN_STRINGS_TESTS_SUITE(wchar_t);
#undef STR_LITERAL

#if CONFIG_HAS_AT_LEAST_CXX_20 && defined(__cpp_char8_t) && __cpp_char8_t >= 201811L

#define STR_LITERAL(expr) u8##expr
MAKE_JOIN_STRINGS_TEST_BLOCK(char8_t);
MAKE_JOIN_STRINGS_TESTS_SUITE(char8_t);
#undef STR_LITERAL

#endif

#define STR_LITERAL(expr) u##expr
MAKE_JOIN_STRINGS_TEST_BLOCK(char16_t);
MAKE_JOIN_STRINGS_TESTS_SUITE(char16_t);
#undef STR_LITERAL

#define STR_LITERAL(expr) U##expr
MAKE_JOIN_STRINGS_TEST_BLOCK(char32_t);
MAKE_JOIN_STRINGS_TESTS_SUITE(char32_t);
#undef STR_LITERAL
}

0 comments on commit 5bded55

Please sign in to comment.