Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 42 additions & 23 deletions Src/Concerto/PackageGenerator/CppGenerator/CppGenerator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ namespace cct
Write("#include <Concerto/Core/TypeInfo/TypeInfo.hpp>");
Write("#include \"Concerto/Reflection/GlobalNamespace/GlobalNamespace.hpp\"");
Write("#include <Concerto/Reflection/GenericClass/GenericClass.hpp>");
Write("#include <Concerto/Reflection/Enumeration/EnumerationClass.hpp>");
Write("#include \"{}Package.gen.hpp\"", package.name);

for (auto& header : args)
Expand All @@ -29,7 +30,7 @@ namespace cct
Write("using namespace cct::refl;");

for (auto& enum_ : package.enums)
GenerateEnum(enum_);
GenerateEnum(enum_, "");
for (auto& klass : package.classes)
{
if (klass.isGenericClass)
Expand All @@ -53,7 +54,7 @@ namespace cct
for (auto& nestedNs : ns.namespaces)
GenerateNamespace(nestedNs, namespaceChain + "::"s + std::string(ns.name));
for (auto& enum_ : ns.enums)
GenerateEnum(enum_);
GenerateEnum(enum_, namespaceChain + "::"s + std::string(ns.name));
for (auto& klass : ns.classes)
{
if (klass.isGenericClass)
Expand Down Expand Up @@ -103,6 +104,10 @@ namespace cct
EnterScope();
Write("ns->LoadClasses();");
LeaveScope();
for (auto& enum_ : ns.enums)
{
Write("AddClass(std::make_unique<{}::Internal{}EnumerationClass>());", ns.name, enum_.name);
}
for (auto& klass : ns.classes)
{
if (klass.isGenericClass)
Expand Down Expand Up @@ -676,41 +681,55 @@ namespace cct
}
}

void CppGenerator::GenerateEnum(const Enum& enum_)
void CppGenerator::GenerateEnum(const Enum& enum_, std::string_view ns)
{
Write("std::string_view {}ToString({} value)", enum_.name, enum_.name);

Write("class Internal{}EnumerationClass : public cct::refl::EnumerationClass", enum_.name);
EnterScope();
{
Write("switch(value)");
Write("public:");
Write("Internal{}EnumerationClass()", enum_.name);
Write(": cct::refl::EnumerationClass(nullptr, \"{}\"s)", enum_.name);
EnterScope();
{
}
LeaveScope();

for (auto& elem : enum_.elements)
NewLine();
Write("~Internal{}EnumerationClass() override", enum_.name);
EnterScope();
{
}
LeaveScope();

NewLine();
Write("void Initialize() override");
EnterScope();
{
for (const auto& elem : enum_.elements)
{
Write("case {}::{}:", enum_.name, elem.name);
Write("return \"{}\"sv;", elem.name);
Write("AddEnumValue(\"{}\", {});", elem.name, elem.value);
}
}
LeaveScope();
Write("CCT_ASSERT_FALSE(\"Invalid enum value\");");
Write("return {{}};");
}
LeaveScope();

Write("{} {}FromString(std::string_view value)", enum_.name, enum_.name);
EnterScope();
{
for (auto& elem : enum_.elements)
NewLine();
Write("cct::refl::Object* GetMemberVariable(std::size_t, const cct::refl::Object&) const override");
EnterScope();
{
Write("if (value == \"{}\"sv)", elem.name);
EnterScope();
Write("return {}::{};", enum_.name, elem.name);
LeaveScope();
Write("return nullptr;");
}
LeaveScope();

NewLine();
Write("void* GetNativeMemberVariable(std::size_t, const cct::refl::Object&) const override");
EnterScope();
{
Write("return nullptr;");
}
Write("CCT_ASSERT_FALSE(\"Invalid enum value: {{}}\", value);");
Write("return {{}};");
LeaveScope();
}
LeaveScope();
LeaveScope(";");
}

void CppGenerator::GeneratePackage(const Package& pkg)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ namespace cct
void GenerateGenericClass(std::string_view ns, const Class& klass);
void GenerateTemplateClass(std::string_view ns, const Class& klass);
void GenerateClassMethod(std::string_view className, const Class::Method& method, std::string_view ns, std::size_t methodIndex);
void GenerateEnum(const Enum& enum_);
void GenerateEnum(const Enum& enum_, std::string_view ns = "");
void GeneratePackage(const Package& pkg);
};
}
Expand Down
34 changes: 34 additions & 0 deletions Src/Concerto/Reflection/EnumValue/EnumValue.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
//
// Created by arthur on 31/12/2025
//

#include "Concerto/Reflection/EnumValue/EnumValue.hpp"
#include "Concerto/Core/Assert.hpp"

namespace cct::refl
{
EnumValue::EnumValue(std::string name, cct::Int64 value, std::size_t index)
: m_name(std::move(name)), m_value(value), m_index(index)
{
}

bool EnumValue::HasAttribute(std::string_view attribute) const
{
return m_attributes.find(std::string(attribute)) != m_attributes.end();
}

std::string_view EnumValue::GetAttribute(std::string_view attribute) const
{
const auto it = m_attributes.find(std::string(attribute));
if (it != m_attributes.end())
return it->second;

CCT_ASSERT_FALSE("EnumValue::GetAttribute: attribute '{}' not found", attribute);
return "";
}

void EnumValue::AddAttribute(std::string name, std::string value)
{
m_attributes[std::move(name)] = std::move(value);
}
}
52 changes: 52 additions & 0 deletions Src/Concerto/Reflection/EnumValue/EnumValue.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
//
// Created by arthur on 31/12/2025
//

#ifndef CONCERTO_REFLECTION_ENUM_VALUE_HPP
#define CONCERTO_REFLECTION_ENUM_VALUE_HPP

#include <string>
#include <string_view>
#include <unordered_map>

#include <Concerto/Core/Types/Types.hpp>

#include "Concerto/Reflection/Defines.hpp"

namespace cct::refl
{
class CCT_REFLECTION_API EnumValue
{
public:
EnumValue(std::string name, cct::Int64 value, std::size_t index);
~EnumValue() = default;

EnumValue(const EnumValue&) = delete;
EnumValue(EnumValue&&) = default;

EnumValue& operator=(const EnumValue&) = delete;
EnumValue& operator=(EnumValue&&) = default;

[[nodiscard]] std::string_view GetName() const;
[[nodiscard]] cct::Int64 GetValue() const;
[[nodiscard]] std::size_t GetIndex() const;

[[nodiscard]] bool HasAttribute(std::string_view attribute) const;
[[nodiscard]] std::string_view GetAttribute(std::string_view attribute) const;

protected:
void AddAttribute(std::string name, std::string value);

private:
std::string m_name;
cct::Int64 m_value;
std::size_t m_index;
std::unordered_map<std::string /*name*/, std::string /*value*/> m_attributes;

friend class Enumeration;
};
}

#include "Concerto/Reflection/EnumValue/EnumValue.inl"

#endif // CONCERTO_REFLECTION_ENUM_VALUE_HPP
23 changes: 23 additions & 0 deletions Src/Concerto/Reflection/EnumValue/EnumValue.inl
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
//
// Created by arthur on 31/12/2025
//

#pragma once

namespace cct::refl
{
inline std::string_view EnumValue::GetName() const
{
return m_name;
}

inline cct::Int64 EnumValue::GetValue() const
{
return m_value;
}

inline std::size_t EnumValue::GetIndex() const
{
return m_index;
}
}
98 changes: 98 additions & 0 deletions Src/Concerto/Reflection/Enumeration/EnumIterator.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
//
// Created by arthur on 31/12/2025
//

#ifndef CONCERTO_REFLECTION_ENUM_ITERATOR_HPP
#define CONCERTO_REFLECTION_ENUM_ITERATOR_HPP

#include <string_view>
#include <span>
#include <memory>

#include <Concerto/Core/Types/Types.hpp>

namespace cct::refl
{
class EnumValue;

class EnumIterator
{
public:
explicit EnumIterator(std::span<const std::unique_ptr<EnumValue>> enumValues, std::size_t index = 0)
: m_enumValues(enumValues), m_index(index)
{
}

inline std::string_view GetName() const;
inline cct::Int64 GetValue() const;
inline std::size_t GetIndex() const;

inline EnumIterator& operator++();
inline bool operator!=(const EnumIterator& other) const;
inline EnumIterator operator*() const { return *this; }

private:
std::span<const std::unique_ptr<EnumValue>> m_enumValues;
std::size_t m_index;

friend class EnumerationClass;
friend class Enumeration;
};

class EnumIterable
{
public:
explicit EnumIterable(std::span<const std::unique_ptr<EnumValue>> enumValues)
: m_enumValues(enumValues)
{
}

EnumIterator begin() const
{
return EnumIterator(m_enumValues, 0);
}

EnumIterator end() const
{
return EnumIterator(m_enumValues, m_enumValues.size());
}

private:
std::span<const std::unique_ptr<EnumValue>> m_enumValues;
};
}

namespace std
{
template<>
struct tuple_size<cct::refl::EnumIterator> : std::integral_constant<std::size_t, 2> {};

template<>
struct tuple_element<0, cct::refl::EnumIterator>
{
using type = std::string_view;
};

template<>
struct tuple_element<1, cct::refl::EnumIterator>
{
using type = cct::Int64;
};
}

namespace cct::refl
{
template<std::size_t N>
auto get(const EnumIterator& it) noexcept
{
static_assert(N < 2, "EnumIterator has only 2 elements: name and value");
if constexpr (N == 0)
return it.GetName();
else if constexpr (N == 1)
return it.GetValue();
}
}

#include "Concerto/Reflection/Enumeration/EnumIterator.inl"

#endif // CONCERTO_REFLECTION_ENUM_ITERATOR_HPP
43 changes: 43 additions & 0 deletions Src/Concerto/Reflection/Enumeration/EnumIterator.inl
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
//
// Created by arthur on 31/12/2025
//

#pragma once

#include "Concerto/Reflection/Enumeration/EnumIterator.hpp"
#include "Concerto/Reflection/EnumValue/EnumValue.hpp"

namespace cct::refl
{
inline std::string_view EnumIterator::GetName() const
{
if (m_index >= m_enumValues.size() || !m_enumValues[m_index])
return {};
return m_enumValues[m_index]->GetName();
}

inline cct::Int64 EnumIterator::GetValue() const
{
if (m_index >= m_enumValues.size() || !m_enumValues[m_index])
return 0;
return m_enumValues[m_index]->GetValue();
}

inline std::size_t EnumIterator::GetIndex() const
{
if (m_index >= m_enumValues.size() || !m_enumValues[m_index])
return 0;
return m_enumValues[m_index]->GetIndex();
}

inline EnumIterator& EnumIterator::operator++()
{
++m_index;
return *this;
}

inline bool EnumIterator::operator!=(const EnumIterator& other) const
{
return m_index != other.m_index;
}
}
Loading
Loading