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
87 changes: 37 additions & 50 deletions CxxTypeRegistration/src/MyReflection.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@

#include <filesystem>

#include "MyReflection.h"
#include "CxxMirrorToJson.h"

//User defined types to be reflected.
#include "Date.h"
Expand All @@ -8,9 +11,8 @@
#include "Complex.h"

/*
TestUtils provide the interface to test/compare reflected type objects with actual objects (retrived/created using
strict Types) without exposing the actual type objects to "CxxReflectionTests" project.
*/
TestUtils, provides the interface to test/compare reflected type objects with actual objects (created via strict typing)
without exposing the actual type objects to "CxxReflectionTests" project.*/
#include "TestUtilsBook.h"
#include "TestUtilsDate.h"
#include "TestUtilsPerson.h"
Expand All @@ -26,76 +28,61 @@ CxxMirror& MyReflection::instance()
{
static CxxMirror cxxMirror = CxxMirror({

//Global function, not contained in any namespace.
//No need to specify "function<>" template types, since its a unique function, no overloads.
Reflect().function(str_getComplexNumAsString).build(getComplexNumAsString),

//Overloads, Specify the overload signature as template in "function<_signature...>"
//if one of the function takes zero params, <void> must be used, else complie error.
Reflect().function<void>(str_reverseString).build(reverseString),
Reflect().function<string>(str_reverseString).build(reverseString),
Reflect().function<const char*>(str_reverseString).build(reverseString),
//global functions, not contained in any namespace.
Reflect().function<void>(str_reverseString).build(reverseString), //function taking no arguments. '<void>' must be specified if other overload exists else not needed. compiler error otherwise.
Reflect().function<string>(str_reverseString).build(reverseString), //overloaded function, takes 'string' arguments. '<string>' must be specified as template parameter.
Reflect().function<const char*>(str_reverseString).build(reverseString), //overloaded function, takes 'const char*' arguments.
Reflect().function(str_getComplexNumAsString).build(getComplexNumAsString), //unique function, no overloads, no need to specify signature as template parameters.

//Global functions, in "complex" namespace.
//Grouping functions under a namespace, which is optional. they can be registered without it as well.
Reflect().nameSpace(str_complex).function(str_setReal).build(complex::setReal),
Reflect().nameSpace(str_complex).function(str_setImaginary).build(complex::setImaginary),
Reflect().nameSpace(str_complex).function(str_getMagnitude).build(complex::getMagnitude),

//Date struct, in nsdate namespace. Ctors, Date()
Reflect().nameSpace(date::ns).record<nsdate::Date>(date::struct_).constructor().build(),
Reflect().nameSpace(date::ns).record<nsdate::Date>(date::struct_).constructor<string>().build(),
Reflect().nameSpace(date::ns).record<nsdate::Date>(date::struct_).constructor<unsigned, unsigned, unsigned>().build(),
//Constructors registration, class/struct name and type must be passed 'record<TYPE>("NAME")'.
Reflect().nameSpace(date::ns).record<nsdate::Date>(date::struct_).constructor().build(), //default constructor. Destructor gets registered automatically if any constructor is registered.
Reflect().nameSpace(date::ns).record<nsdate::Date>(date::struct_).constructor<string>().build(), //overloaded constructor, taking 'string' as argument, must be specified as template param.
Reflect().nameSpace(date::ns).record<nsdate::Date>(date::struct_).constructor<unsigned, unsigned, unsigned>().build(), //again, the overloaded constructor.
Reflect().nameSpace(date::ns).record<nsdate::Date>(date::struct_).constructor<nsdate::Date&>().build(), //Copy constructor, taking non-const ref as argument.

//Copy Ctor with non-const ref, Date()
Reflect().nameSpace(date::ns).record<nsdate::Date>(date::struct_).constructor<nsdate::Date&>().build(),

//Calender, in nsdate namespace. Ctor only.
//class Calender, default constructor. Instances will always be created on heap and managed using shared_ptr.
Reflect().nameSpace(calender::ns).record<nsdate::Calender>(calender::struct_).constructor().build(),
Reflect().record<Library>(library::class_).methodStatic(library::str_addBook).build(&Library::addBook), //Static method registration, 'methodStatic()' function must be used. compiler error otherwise.

//class 'Book', no namespace. constructor overloads.
//class 'Book', methods & constructors.
Reflect().record<Book>(book::class_).constructor().build(),
Reflect().record<Book>(book::class_).constructor<const Book&>().build(), //copy constructor, taking const-ref.
Reflect().record<Book>(book::class_).constructor<double, string>().build(),
//copy constructor with const ref
Reflect().record<Book>(book::class_).constructor<const Book&>().build(),

//Library class, no constructors.
Reflect().record<Library>(library::class_).methodStatic(library::str_addBook).build(&Library::addBook),

//unique methods.
Reflect().record<Book>(book::class_).method(book::str_setAuthor).build(&Book::setAuthor),
Reflect().record<Book>(book::class_).method(book::str_setAuthor).build(&Book::setAuthor), //unique methods, no overloads.
Reflect().record<Book>(book::class_).method(book::str_setDescription).build(&Book::setDescription),
Reflect().record<Book>(book::class_).method(book::str_getPublishedOn).build(&Book::getPublishedOn),

//method overloads.
Reflect().record<Book>(book::class_).method<void>(book::str_updateBookInfo).build(&Book::updateBookInfo),
Reflect().record<Book>(book::class_).method<const char*, double, string>(book::str_updateBookInfo).build(&Book::updateBookInfo),
Reflect().record<Book>(book::class_).method<void>(book::str_updateBookInfo).build(&Book::updateBookInfo), //method overloading, '<void>' must be specified since other overloads exists.
Reflect().record<Book>(book::class_).method<const char*, double, string>(book::str_updateBookInfo).build(&Book::updateBookInfo),
Reflect().record<Book>(book::class_).method<string, double, const char*>(book::str_updateBookInfo).build(&Book::updateBookInfo),

//Class 'Person', constructor.
//class 'Person', methods & constructors.
Reflect().record<Person>(person::class_).constructor().build(),
Reflect().record<Person>(person::class_).constructor<string>().build(),

//Copy constructor overload based on const argument
Reflect().record<Person>(person::class_).constructor<Person&>().build(),
Reflect().record<Person>(person::class_).constructor<const Person&>().build(),

//const method. must use 'methodConst()'. Unique method, so no need to specify signature as template params.
Reflect().record<Person>(person::class_).methodConst(person::str_updateLastName).build(&Person::updateLastName),

//const based method overloads. same signatures, but one is const, registered via 'methodConst()'.
Reflect().record<Person>(person::class_).constructor<Person&>().build(), //copy constructor taking non-const ref argument.
Reflect().record<Person>(person::class_).constructor<const Person&>().build(), //copy constructor taking const ref argument.
Reflect().record<Person>(person::class_).method<void>(person::str_updateAddress).build(&Person::updateAddress),
Reflect().record<Person>(person::class_).methodConst<void>(person::str_updateAddress).build(&Person::updateAddress),
Reflect().record<Person>(person::class_).method<string>(person::str_updateAddress).build(&Person::updateAddress),
Reflect().record<Person>(person::class_).methodConst<string>(person::str_updateAddress).build(&Person::updateAddress),

//Static method. unique.
Reflect().record<Person>(person::class_).methodConst(person::str_updateLastName).build(&Person::updateLastName), //const method registration, 'methodConst()' function must be used. compiler error otherwise.
Reflect().record<Person>(person::class_).methodConst<void>(person::str_updateAddress).build(&Person::updateAddress),
Reflect().record<Person>(person::class_).methodConst<string>(person::str_updateAddress).build(&Person::updateAddress), //overloaded method based on 'const'.
Reflect().record<Person>(person::class_).methodStatic(person::str_getDefaults).build(&Person::getDefaults),

//Static method overloads.
Reflect().record<Person>(person::class_).methodStatic<void>(person::str_getProfile).build(&Person::getProfile),
Reflect().record<Person>(person::class_).methodStatic<bool>(person::str_getProfile).build(&Person::getProfile),
Reflect().record<Person>(person::class_).methodStatic<string, size_t>(person::str_getProfile).build(&Person::getProfile)
});


static bool dumped = false;
if (!dumped) {
const std::string pathStr = std::filesystem::current_path().string() + "/MyReflection.json";
rtl::CxxMirrorToJson::dump(cxxMirror, pathStr);
dumped = true;
}

return cxxMirror;
}
4 changes: 1 addition & 3 deletions ReflectionTemplateLib/access/inc/CxxMirror.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,12 @@ namespace rtl {
class Record;
class Function;

class CxxMirror : detail::CxxReflection
class CxxMirror : public detail::CxxReflection
{
public:

CxxMirror(const std::vector<Function>& pFunctions);

void dumpReflectionJson(const std::string& pFilePath);

std::optional<Record> getRecord(const std::string& pFunction);

std::optional<Function> getFunction(const std::string& pFunction);
Expand Down
13 changes: 13 additions & 0 deletions ReflectionTemplateLib/access/inc/CxxMirrorToJson.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#pragma once

namespace rtl {

namespace access {
class CxxMirror;
}

struct CxxMirrorToJson
{
static void dump(access::CxxMirror& pCxxMirror, const std::string& pFilePathStr);
};
}
8 changes: 3 additions & 5 deletions ReflectionTemplateLib/access/inc/Function.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,11 @@ namespace rtl {
const std::string m_function;
const std::string m_namespace;

mutable std::string m_signatures;
mutable std::vector<detail::FunctorId> m_functorIds;

Function();
Function(const std::string& pNamespace, const std::string& pClassName, const std::string& pFuncName,
const std::string& pSignature, const detail::FunctorId& pFunctorId,
std::size_t pRecordTypeId, const TypeQ pQualifier);
const detail::FunctorId& pFunctorId, std::size_t pRecordTypeId, const TypeQ pQualifier);

void addOverload(const Function& pOtherFunc) const;

Expand All @@ -41,7 +39,7 @@ namespace rtl {
protected:

Function(const Function& pOther, const detail::FunctorId& pFunctorId,
const std::string& pFunctorName, const std::string& pSignatureStr);
const std::string& pFunctorName);

const std::size_t hasSignatureId(const std::size_t& pSignatureId) const;

Expand All @@ -51,8 +49,8 @@ namespace rtl {
GETTER(std::string, RecordName, m_record)
GETTER(std::string, Namespace, m_namespace)
GETTER(std::string, FunctionName, m_function)
GETTER(std::string, Signatures, m_signatures)
GETTER(std::size_t, RecordTypeId, m_recordTypeId)
GETTER(std::vector<detail::FunctorId>, Functors, m_functorIds)

const std::string getHashCode() const;

Expand Down
3 changes: 1 addition & 2 deletions ReflectionTemplateLib/access/inc/Method.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,7 @@ namespace rtl {
{
Method(const Function& pFunction);

Method(const Function& pFunction, const detail::FunctorId& pFunctorId,
const std::string& pFunctorName, const std::string& pSignatureStr);
Method(const Function& pFunction, const detail::FunctorId& pFunctorId, const std::string& pFunctorName);

template<class ..._args>
RStatus invokeCtor(_args...params) const;
Expand Down
4 changes: 2 additions & 2 deletions ReflectionTemplateLib/access/inc/Record.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,12 @@ namespace rtl {
template<class ..._ctorArgs>
inline const std::pair<RStatus, Instance> Record::instance(_ctorArgs ...params) const
{
const std::string& ctor = (m_recordName + Ctor::CTOR);
const std::string& ctor = CtorName::ctor(m_recordName);
const auto& itr = m_methods.find(ctor);
if (itr != m_methods.end()) {
const RStatus& status = itr->second.invokeCtor(params...);
if (status) {
const std::string& dctor = (m_recordName + Ctor::DCTOR);
const std::string& dctor = CtorName::dctor(m_recordName);
return std::make_pair(status, Instance(status.getReturn(), status, *getMethod(dctor)));
}
return std::make_pair(status, Instance());
Expand Down
2 changes: 2 additions & 0 deletions ReflectionTemplateLib/access/src/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# Create a variable containing the source files for your target
set(LOCAL_SOURCES
"${CMAKE_CURRENT_LIST_DIR}/CxxMirror.cpp"
"${CMAKE_CURRENT_LIST_DIR}/CxxMirrorToJson.cpp"
"${CMAKE_CURRENT_LIST_DIR}/Function.cpp"
"${CMAKE_CURRENT_LIST_DIR}/Instance.cpp"
"${CMAKE_CURRENT_LIST_DIR}/Method.cpp"
Expand All @@ -15,6 +16,7 @@ SET(COMMON_HEADERS

SET(LOCAL_HEADERS
"${PROJECT_SOURCE_DIR}/access/inc/CxxMirror.h"
"${PROJECT_SOURCE_DIR}/access/inc/CxxMirrorToJson.h"
"${PROJECT_SOURCE_DIR}/access/inc/Function.h"
"${PROJECT_SOURCE_DIR}/access/inc/Function.hpp"
"${PROJECT_SOURCE_DIR}/access/inc/Instance.h"
Expand Down
107 changes: 107 additions & 0 deletions ReflectionTemplateLib/access/src/CxxMirrorToJson.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@

#include <fstream>
#include <filesystem>

#include "Method.h"
#include "Record.h"
#include "Function.h"
#include "CxxMirror.h"
#include "CxxMirrorToJson.h"

using namespace rtl::access;
using namespace rtl::detail;

namespace
{
const std::string toJson(const FunctorId& pFunctorId)
{
std::stringstream sout;
sout << "{\"hash_code\": \"" << std::to_string(pFunctorId.getHashCode()) << "\",";
sout << "\"signature\": \"" << pFunctorId.getSignatureStr() << "\"}";
return sout.str();
}

const std::string toJson(const Function& pFunction)
{
std::stringstream sout;
const auto& functors = pFunction.getFunctors();
const std::string& record = pFunction.getRecordName();
const std::string& nmspace = pFunction.getNamespace();

sout << "{" << (record.empty() ? "\"function\"" : "\"method\"") << ": \"" << pFunction.getFunctionName() << "\",";
if (nmspace != rtl::NAMESPACE_GLOBAL) {
sout << "\"namespace\": \"" << nmspace << "\",";
}
if (!record.empty()) {
sout << "\"record\": \"" << record << "\",";
}

int index = 0;
sout << "\"functorId\": [";
for (const auto& funtorId : functors) {
sout << toJson(funtorId);
if (++index < functors.size()) {
sout << ", ";
}
}
sout << "]}";
return sout.str();
}


const std::string toJson(CxxMirror& pCxxMirror)
{
std::stringstream sout;
sout << "[";
bool atLeastOne = false;
const auto& nsfuncMap = pCxxMirror.getNamespaceFunctionsMap();
for (const auto& itr : nsfuncMap)
{
for (const auto& itr0 : itr.second)
{
const std::string& functionStr = toJson(itr0.second);
sout << functionStr << ",";
atLeastOne = true;
}
}

const auto& recfuncMap = pCxxMirror.getNamespaceRecordMap();
for (const auto& itr : recfuncMap)
{
for (const auto& itr0 : itr.second)
{
for (const auto& itr1 : itr0.second.getMethodMap())
{
const std::string& methodStr = toJson(itr1.second);
sout << methodStr << ",";
atLeastOne = true;
}
}
}

std::string str = sout.str();
if (str.back() == ',') str.pop_back();
str.push_back(']');
return str;
}
}


namespace rtl
{
void CxxMirrorToJson::dump(CxxMirror& pCxxMirror, const std::string& pFilePathStr)
{
std::string fileStr = pFilePathStr;
std::replace(fileStr.begin(), fileStr.end(), '\\', '/');
std::fstream fout(fileStr, std::ios::out);
if (!fout.is_open()) {
return;
}
fout << toJson(pCxxMirror);
fout.flush();
fout.close();
if (fout.fail() || fout.bad()) {
return;
}
}
}
9 changes: 2 additions & 7 deletions ReflectionTemplateLib/access/src/Function.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,33 +13,29 @@ namespace rtl {
, m_recordTypeId(detail::TypeId<>::None)
, m_record("")
, m_function("")
, m_signatures("")
, m_namespace("")
{
}


Function::Function(const std::string& pNamespace, const std::string& pRecord, const std::string& pFunction,
const std::string& pSignature, const detail::FunctorId& pFunctorId,
std::size_t pRecordTypeId, const TypeQ pQualifier)
const detail::FunctorId& pFunctorId, std::size_t pRecordTypeId, const TypeQ pQualifier)
: m_qualifier(pQualifier)
, m_recordTypeId(pRecordTypeId)
, m_functorIds({ pFunctorId })
, m_record(pRecord)
, m_function(pFunction)
, m_signatures(pSignature)
, m_namespace(pNamespace) {
}


Function::Function(const Function& pOther, const detail::FunctorId& pFunctorId,
const std::string& pFunctorName, const std::string& pSignatureStr)
const std::string& pFunctorName)
: m_qualifier(pOther.m_qualifier)
, m_recordTypeId(pOther.m_recordTypeId)
, m_functorIds({ pFunctorId })
, m_record(pOther.m_record)
, m_function(pFunctorName)
, m_signatures(pSignatureStr)
, m_namespace(pOther.m_namespace) {
}

Expand Down Expand Up @@ -80,7 +76,6 @@ namespace rtl {
}

m_functorIds.push_back(pOtherFunc.m_functorIds[0]);
m_signatures.append("\n" + pOtherFunc.m_signatures);
}
}
}
Loading