Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 71c7e4f6 authored by Dominik Laskowski's avatar Dominik Laskowski
Browse files

FTL: Allow Concat of bool and char

Also, allow references to integral types.

Bug: 185536303
Test: ftl_test
Change-Id: Ic9be008ed7f72ecdb7a369b01bc5a8235b35ac2c
parent edfce733
Loading
Loading
Loading
Loading
+3 −1
Original line number Diff line number Diff line
@@ -20,7 +20,9 @@

namespace android::ftl {

// Lightweight (not allocating nor sprintf-based) concatenation.
// Lightweight (not allocating nor sprintf-based) concatenation. The variadic arguments can be
// values of integral type (including bool and char), string literals, or strings whose length
// is constrained:
//
//   std::string_view name = "Volume";
//   ftl::Concat string(ftl::truncated<3>(name), ": ", -3, " dB");
+32 −4
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@
#include <functional>
#include <string_view>

#include <ftl/details/type_traits.h>
#include <ftl/string.h>

namespace android::ftl::details {
@@ -26,16 +27,42 @@ namespace android::ftl::details {
template <typename T, typename = void>
struct StaticString;

// Booleans.
template <typename T>
struct StaticString<T, std::enable_if_t<std::is_integral_v<T>>> {
  static constexpr std::size_t N = to_chars_length_v<T>;
struct StaticString<T, std::enable_if_t<is_bool_v<T>>> {
  static constexpr std::size_t N = 5;  // Length of "false".

  explicit StaticString(T v) : view(to_chars(buffer, v)) {}
  explicit constexpr StaticString(bool b) : view(b ? "true" : "false") {}

  to_chars_buffer_t<T> buffer;
  const std::string_view view;
};

// Characters.
template <typename T>
struct StaticString<T, std::enable_if_t<is_char_v<T>>> {
  static constexpr std::size_t N = 1;

  explicit constexpr StaticString(char c) : character(c) {}

  const char character;
  const std::string_view view{&character, 1u};
};

// Integers, including the integer value of other character types like char32_t.
template <typename T>
struct StaticString<
    T, std::enable_if_t<std::is_integral_v<remove_cvref_t<T>> && !is_bool_v<T> && !is_char_v<T>>> {
  using U = remove_cvref_t<T>;
  static constexpr std::size_t N = to_chars_length_v<U>;

  // TODO: Mark this and to_chars as `constexpr` in C++23.
  explicit StaticString(U v) : view(to_chars(buffer, v)) {}

  to_chars_buffer_t<U> buffer;
  const std::string_view view;
};

// Character arrays.
template <std::size_t M>
struct StaticString<const char (&)[M], void> {
  static constexpr std::size_t N = M - 1;
@@ -50,6 +77,7 @@ struct Truncated {
  std::string_view view;
};

// Strings with constrained length.
template <std::size_t M>
struct StaticString<Truncated<M>, void> {
  static constexpr std::size_t N = M;
+6 −0
Original line number Diff line number Diff line
@@ -24,4 +24,10 @@ namespace android::ftl::details {
template <typename U>
using remove_cvref_t = std::remove_cv_t<std::remove_reference_t<U>>;

template <typename T>
constexpr bool is_bool_v = std::is_same_v<remove_cvref_t<T>, bool>;

template <typename T>
constexpr bool is_char_v = std::is_same_v<remove_cvref_t<T>, char>;

}  // namespace android::ftl::details
+17 −0
Original line number Diff line number Diff line
@@ -28,8 +28,25 @@ TEST(Concat, Example) {
  EXPECT_EQ(string.c_str()[string.size()], '\0');
}

TEST(Concat, Characters) {
  EXPECT_EQ(ftl::Concat(u'a', ' ', U'b').str(), "97 98");
}

TEST(Concat, References) {
  int i[] = {-1, 2};
  unsigned u = 3;
  EXPECT_EQ(ftl::Concat(i[0], std::as_const(i[1]), u).str(), "-123");

  const bool b = false;
  const char c = 'o';
  EXPECT_EQ(ftl::Concat(b, "tt", c).str(), "falsetto");
}

namespace {

static_assert(ftl::Concat{true, false, true}.str() == "truefalsetrue");
static_assert(ftl::Concat{':', '-', ')'}.str() == ":-)");

static_assert(ftl::Concat{"foo"}.str() == "foo");
static_assert(ftl::Concat{ftl::truncated<3>("foobar")}.str() == "foo");