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

Commit 285ff62d authored by Ady Abraham's avatar Ady Abraham Committed by Android (Google) Code Review
Browse files

Merge changes I6d24998c,I235275b5 into main

* changes:
  SF: add requestedLaterState to Hierarchy dump
  ftl: add enum_string_full which includes the enum class name
parents ab85f59f 4cb525bc
Loading
Loading
Loading
Loading
+72 −7
Original line number Diff line number Diff line
@@ -25,12 +25,12 @@

#include <ftl/string.h>

// Returns the name of enumerator E::V (i.e. "V") as std::optional<std::string_view> by parsing the
// compiler-generated string literal for the signature of this function. The function is defined in
// the global namespace with a short name and inferred return type to reduce bloat in the read-only
// data segment.
template <typename E, E V>
constexpr auto ftl_enum() {
// Returns the name of enumerator E::V and optionally the class (i.e. "E::V" or "V") as
// std::optional<std::string_view> by parsing the compiler-generated string literal for the
// signature of this function. The function is defined in the global namespace with a short name
// and inferred return type to reduce bloat in the read-only data segment.
template <bool S, typename E, E V>
constexpr auto ftl_enum_builder() {
  static_assert(std::is_enum_v<E>);

  using R = std::optional<std::string_view>;
@@ -58,7 +58,9 @@ constexpr auto ftl_enum() {
  //   V = android::test::Enum::kValue
  //
  view = view.substr(value_begin);
  const auto name_begin = view.rfind("::"sv);
  const auto pos = S ? view.rfind("::"sv) - 2 : view.npos;

  const auto name_begin = view.rfind("::"sv, pos);
  if (name_begin == view.npos) return R{};

  // Chop off the leading "::".
@@ -68,6 +70,18 @@ constexpr auto ftl_enum() {
  return name.find(')') == view.npos ? R{name} : R{};
}

// Returns the name of enumerator E::V (i.e. "V") as std::optional<std::string_view>
template <typename E, E V>
constexpr auto ftl_enum() {
  return ftl_enum_builder<false, E, V>();
}

// Returns the name of enumerator and class E::V (i.e. "E::V") as std::optional<std::string_view>
template <typename E, E V>
constexpr auto ftl_enum_full() {
  return ftl_enum_builder<true, E, V>();
}

namespace android::ftl {

// Trait for determining whether a type is specifically a scoped enum or not. By definition, a
@@ -191,6 +205,11 @@ struct EnumName {
  static constexpr auto value = ftl_enum<decltype(V), V>();
};

template <auto V>
struct EnumNameFull {
  static constexpr auto value = ftl_enum_full<decltype(V), V>();
};

template <auto I>
struct FlagName {
  using E = decltype(I);
@@ -230,6 +249,18 @@ constexpr std::string_view enum_name() {
  return *kName;
}

// Returns a stringified enumerator with class at compile time.
//
//   enum class E { A, B, C };
//   static_assert(ftl::enum_name<E::B>() == "E::B");
//
template <auto V>
constexpr std::string_view enum_name_full() {
  constexpr auto kName = ftl_enum_full<decltype(V), V>();
  static_assert(kName, "Unknown enumerator");
  return *kName;
}

// Returns a stringified enumerator, possibly at compile time.
//
//   enum class E { A, B, C, F = 5, ftl_last = F };
@@ -249,6 +280,25 @@ constexpr std::optional<std::string_view> enum_name(E v) {
  return kRange.values[value - kBegin];
}

// Returns a stringified enumerator with class, possibly at compile time.
//
//   enum class E { A, B, C, F = 5, ftl_last = F };
//
//   static_assert(ftl::enum_name(E::C).value_or("?") == "E::C");
//   static_assert(ftl::enum_name(E{3}).value_or("?") == "?");
//
template <typename E>
constexpr std::optional<std::string_view> enum_name_full(E v) {
  const auto value = to_underlying(v);

  constexpr auto kBegin = to_underlying(enum_begin_v<E>);
  constexpr auto kLast = to_underlying(enum_last_v<E>);
  if (value < kBegin || value > kLast) return {};

  constexpr auto kRange = details::EnumRange<E, details::EnumNameFull>{};
  return kRange.values[value - kBegin];
}

// Returns a stringified flag enumerator, possibly at compile time.
//
//   enum class F : std::uint16_t { X = 0b1, Y = 0b10, Z = 0b100 };
@@ -282,6 +332,21 @@ inline std::string enum_string(E v) {
  return to_string(to_underlying(v));
}

// Returns a stringified enumerator with class, or its integral value if not named.
//
//   enum class E { A, B, C, F = 5, ftl_last = F };
//
//   assert(ftl::enum_string(E::C) == "E::C");
//   assert(ftl::enum_string(E{3}) == "3");
//
template <typename E>
inline std::string enum_string_full(E v) {
  if (const auto name = enum_name_full(v)) {
      return std::string(*name);
  }
  return to_string(to_underlying(v));
}

// Returns a stringified flag enumerator, or its integral value if not named.
//
//   enum class F : std::uint16_t { X = 0b1, Y = 0b10, Z = 0b100 };
+38 −0
Original line number Diff line number Diff line
@@ -33,6 +33,11 @@ static_assert(ftl::enum_name<E::ftl_last>() == "F");
static_assert(ftl::enum_name(E::C).value_or("?") == "C");
static_assert(ftl::enum_name(E{3}).value_or("?") == "?");

static_assert(ftl::enum_name_full<E::B>() == "E::B");
static_assert(ftl::enum_name_full<E::ftl_last>() == "E::F");
static_assert(ftl::enum_name_full(E::C).value_or("?") == "E::C");
static_assert(ftl::enum_name_full(E{3}).value_or("?") == "?");

enum class F : std::uint16_t { X = 0b1, Y = 0b10, Z = 0b100 };

static_assert(ftl::enum_begin_v<F> == F{0});
@@ -60,6 +65,10 @@ static_assert(ftl::enum_name<Flags::kNone>() == "kNone");
static_assert(ftl::enum_name<Flags::kFlag4>() == "kFlag4");
static_assert(ftl::enum_name<Flags::kFlag7>() == "kFlag7");

static_assert(ftl::enum_name_full<Flags::kNone>() == "Flags::kNone");
static_assert(ftl::enum_name_full<Flags::kFlag4>() == "Flags::kFlag4");
static_assert(ftl::enum_name_full<Flags::kFlag7>() == "Flags::kFlag7");

// Though not flags, the enumerators are within the implicit range of bit indices.
enum class Planet : std::uint8_t {
  kMercury,
@@ -81,6 +90,9 @@ static_assert(ftl::enum_size_v<Planet> == 8);
static_assert(ftl::enum_name<Planet::kMercury>() == "kMercury");
static_assert(ftl::enum_name<Planet::kSaturn>() == "kSaturn");

static_assert(ftl::enum_name_full<Planet::kMercury>() == "Planet::kMercury");
static_assert(ftl::enum_name_full<Planet::kSaturn>() == "Planet::kSaturn");

// Unscoped enum must define explicit range, even if the underlying type is fixed.
enum Temperature : int {
  kRoom = 20,
@@ -122,16 +134,28 @@ TEST(Enum, Name) {
    EXPECT_EQ(ftl::enum_name(Planet::kEarth), "kEarth");
    EXPECT_EQ(ftl::enum_name(Planet::kNeptune), "kNeptune");

    EXPECT_EQ(ftl::enum_name_full(Planet::kEarth), "Planet::kEarth");
    EXPECT_EQ(ftl::enum_name_full(Planet::kNeptune), "Planet::kNeptune");

    EXPECT_EQ(ftl::enum_name(kPluto), std::nullopt);
    EXPECT_EQ(ftl::enum_name_full(kPluto), std::nullopt);
  }
  {
    EXPECT_EQ(ftl::enum_name(kRoom), "kRoom");
    EXPECT_EQ(ftl::enum_name(kFridge), "kFridge");
    EXPECT_EQ(ftl::enum_name(kFreezer), "kFreezer");

    EXPECT_EQ(ftl::enum_name(kRoom), "kRoom");
    EXPECT_EQ(ftl::enum_name(kFridge), "kFridge");
    EXPECT_EQ(ftl::enum_name(kFreezer), "kFreezer");

    EXPECT_EQ(ftl::enum_name(static_cast<Temperature>(-30)), std::nullopt);
    EXPECT_EQ(ftl::enum_name(static_cast<Temperature>(0)), std::nullopt);
    EXPECT_EQ(ftl::enum_name(static_cast<Temperature>(100)), std::nullopt);

    EXPECT_EQ(ftl::enum_name_full(static_cast<Temperature>(-30)), std::nullopt);
    EXPECT_EQ(ftl::enum_name_full(static_cast<Temperature>(0)), std::nullopt);
    EXPECT_EQ(ftl::enum_name_full(static_cast<Temperature>(100)), std::nullopt);
  }
}

@@ -158,16 +182,30 @@ TEST(Enum, String) {
    EXPECT_EQ(ftl::enum_string(Planet::kEarth), "kEarth");
    EXPECT_EQ(ftl::enum_string(Planet::kNeptune), "kNeptune");

    EXPECT_EQ(ftl::enum_string_full(Planet::kEarth), "Planet::kEarth");
    EXPECT_EQ(ftl::enum_string_full(Planet::kNeptune), "Planet::kNeptune");

    EXPECT_EQ(ftl::enum_string(kPluto), "8");

    EXPECT_EQ(ftl::enum_string_full(kPluto), "8");

  }
  {
    EXPECT_EQ(ftl::enum_string(kRoom), "kRoom");
    EXPECT_EQ(ftl::enum_string(kFridge), "kFridge");
    EXPECT_EQ(ftl::enum_string(kFreezer), "kFreezer");

    EXPECT_EQ(ftl::enum_string_full(kRoom), "20");
    EXPECT_EQ(ftl::enum_string_full(kFridge), "4");
    EXPECT_EQ(ftl::enum_string_full(kFreezer), "-18");

    EXPECT_EQ(ftl::enum_string(static_cast<Temperature>(-30)), "-30");
    EXPECT_EQ(ftl::enum_string(static_cast<Temperature>(0)), "0");
    EXPECT_EQ(ftl::enum_string(static_cast<Temperature>(100)), "100");

    EXPECT_EQ(ftl::enum_string_full(static_cast<Temperature>(-30)), "-30");
    EXPECT_EQ(ftl::enum_string_full(static_cast<Temperature>(0)), "0");
    EXPECT_EQ(ftl::enum_string_full(static_cast<Temperature>(100)), "100");
  }
}

+9 −0
Original line number Diff line number Diff line
@@ -405,10 +405,19 @@ std::string RequestedLayerState::getDebugString() const {
    return debug.str();
}

std::ostream& operator<<(std::ostream& out, const scheduler::LayerInfo::FrameRate& obj) {
    out << obj.vote.rate;
    out << " " << ftl::enum_string_full(obj.vote.type);
    out << " " << ftl::enum_string_full(obj.category);
    return out;
}

std::ostream& operator<<(std::ostream& out, const RequestedLayerState& obj) {
    out << obj.debugName;
    if (obj.relativeParentId != UNASSIGNED_LAYER_ID) out << " parent=" << obj.parentId;
    if (!obj.handleAlive) out << " handleNotAlive";
    if (obj.requestedFrameRate.isValid())
        out << " requestedFrameRate: {" << obj.requestedFrameRate << "}";
    return out;
}