initial commit

This commit is contained in:
Roland Conybeare 2024-06-24 22:25:45 -04:00
commit 37ff6c2b01
6 changed files with 308 additions and 0 deletions

8
.gitignore vendored Normal file
View file

@ -0,0 +1,8 @@
# emacs project control file
.projectile
# clangd working space (see emacs+lsp)
.cache
# typical cmake build directory (source-tree-nephew)
.build*
# symlink to builddir/compile_commands.json; should be set manually in dev sandbox
compile_commands.json

46
CMakeLists.txt Normal file
View file

@ -0,0 +1,46 @@
# xo-reflectutil/CMakeLists.txt
cmake_minimum_required(VERSION 3.10)
project(xo_reflectutil VERSION 1.0)
enable_language(CXX)
include(GNUInstallDirs)
include(cmake/xo-bootstrap-macros.cmake)
xo_cxx_toplevel_options3()
# ----------------------------------------------------------------
# c++ settings
# one-time project-specific c++ flags. usually empty
set(PROJECT_CXX_FLAGS "")
#set(PROJECT_CXX_FLAGS "-fconcepts-diagnostics-depth=2")
add_definitions(${PROJECT_CXX_FLAGS})
# ----------------------------------------------------------------
#add_subdirectory(example)
#add_subdirectory(utest)
# ----------------------------------------------------------------
# provide find_package() support for projects using this library
set(SELF_LIB xo_reflectutil)
xo_add_headeronly_library(${SELF_LIB})
xo_install_library4(${SELF_LIB} ${PROJECT_NAME}Targets)
xo_export_cmake_config(${PROJECT_NAME} ${PROJECT_VERSION} ${PROJECT_NAME}Targets)
# ----------------------------------------------------------------
# docs targets depend on all the other library/utest targets
#
#add_subdirectory(docs)
# ----------------------------------------------------------------
# dependencies
xo_headeronly_dependency(${SELF_LIB} xo_flatstring)
#xo_headeronly_dependency(${SELF_LIB} randomgen)
# etc..
# end CMakeLists.txt

29
LICENSE Normal file
View file

@ -0,0 +1,29 @@
Copyright (c) 2024 Roland Conybeare <git3ub@nym.hush.com>, All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Please also refer to the file .github/CONTRIBUTING.md, which clarifies licensing of
external contributions to this project including patches, pull requests, etc.

View file

@ -0,0 +1,33 @@
# ----------------------------------------------------------------
# for example:
# $ PREFIX=/usr/local # for example
# $ cmake -DCMAKE_MODULE_PATH=prefix -DCMAKE_INSTALL_PREFIX=$PREFIX -B .build
#
# will get
# CMAKE_MODULE_PATH
# from xo-cmake-config --cmake-module-path
#
# and expect .cmake macros in
# CMAKE_MODULE_PATH/xo_macros/xo_cxx.cmake
# ----------------------------------------------------------------
find_program(XO_CMAKE_CONFIG_EXECUTABLE NAMES xo-cmake-config REQUIRED)
if (("${CMAKE_MODULE_PATH}" STREQUAL "") OR ("${CMAKE_MODULE_PATH}" STREQUAL "prefix"))
message(FATAL "could not find xo-cmake-config executable")
endif()
if (NOT XO_SUBMODULE_BUILD)
if (("${CMAKE_MODULE_PATH}" STREQUAL "") OR ("${CMAKE_MODULE_PATH}" STREQUAL prefix))
# default to typical install location for xo-project-macros
execute_process(COMMAND ${XO_CMAKE_CONFIG_EXECUTABLE} --cmake-module-path OUTPUT_VARIABLE CMAKE_MODULE_PATH)
message(STATUS "CMAKE_MODULE_PATH=${CMAKE_MODULE_PATH}")
endif()
endif()
# needs to have been installed somewhere on CMAKE_MODULE_PATH,
# (e.g. from xo-cmake with the same value for CMAKE_INSTALL_PREFIX)
#
include(xo_macros/xo_cxx)
xo_cxx_bootstrap_message()

View file

@ -0,0 +1,17 @@
@PACKAGE_INIT@
include(CMakeFindDependencyMacro)
# note: changes to find_dependency() calls here
# must coordinate with xo_dependency() calls
# in xo-reactor/src/reactor/CMakeLists.txt
#
find_dependency(xo_flatstring)
#find_dependency(subsys)
#find_dependency(Eigen3)
#find_dependency(webutil)
#find_dependency(printjson)
#find_dependency(callback)
include("${CMAKE_CURRENT_LIST_DIR}/@PROJECT_NAME@Targets.cmake")
check_required_components("@PROJECT_NAME@")

View file

@ -0,0 +1,175 @@
/** @file reflect_struct_info.hpp
*
* Author: Roland Conybeare
**/
#pragma once
#include <cstdint>
namespace xo {
namespace reflect {
/** Instructions for reflecting a struct:
*
* #include "xo/reflectutil/reflect_struct_info.hpp" // this file
*
* namespace xo {
* namespace reflect {
* // replacing X with the number of member variables in foo:
* REFLECT_BASE_STRUCT_INFO(some::ns::foo, X);
*
* // for each member {member_0, member_1, ...} of foo,
* // in the same order as they appear in class/struct decl:
* REFLECT_STRUCT_MEMBER_INFO(some::ns::foo, 0, member(0));
* REFLECT_STRUCT_MEMBER_INFO(some::ns::foo, 1, member(1);
* ..
* // (last member will have index number X-1)
* }
* }
*
* These decls can appear anywhere after decl for some::ns::foo;
* they must be made in the global namespace
* (so that specializations appear in the xo::reflect namespace)
*
* Finally to permanently capture struct ingredients,
* this statement must run at least once:
*
* xo::reflect::reflect_struct<some::ns::foo>();
*
**/
#define REFLECT_BASE_STRUCT_INFO_TBODY(qualified_struct_name, member_count) \
struct reflect_struct_traits<qualified_struct_name> { \
static constexpr std::size_t n_members = member_count; \
static constexpr std::size_t n_parents = 0; \
}
#define REFLECT_BASE_STRUCT_INFO(qualified_struct_name, member_count) \
template<> \
REFLECT_BASE_STRUCT_INFO_TBODY(qualified_struct_name, member_count)
#define REFLECT_STRUCT_MEMBER_INFO_TBODY(qualified_struct_name, member_ix, member_name) \
struct reflect_struct_member<qualified_struct_name, member_ix> { \
constexpr auto get() const { \
return reflect_struct_member_aux(xo::flatstring(#member_name), \
&qualified_struct_name::member_name##_); \
} \
};
#define REFLECT_STRUCT_MEMBER_INFO(qualified_struct_name, member_ix, member_name) \
template <> \
REFLECT_STRUCT_MEMBER_INFO_TBODY(qualified_struct_name, member_ix, member_name)
/** @class reflect_struct_traits
*
* @brief header-only ingredients for reflecting a struct
*
* A class/struct T to be reflected should provide specializations
* of
* - xo::reflect::reflect_struct_traits<>
* - xo::reflect::reflect_struct_member<>
* - xo::reflect::reflect_struct_parent<> [aspirational, not yet]
*
* For example:
*
* @code
*
* namespace foo {
* struct mycomplex { double real_, double imag_; };
* }
*
* namespace xo {
* namespace reflect {
* template <>
* struct reflect_struct_traits<foo::mycomplex> {
*
* // number of member variables
* static constexpr std::size_t n_members = 2;
*
* // number of parent structs
* // (i.e. directly inherited structs)
* static constexpr std::size_t n_parents = 0;
* };
* }
* }
*
* // or use convenience macro (must be in global namespace)
* REFLECT_BASE_STRUCT_INFO(foo::mycomplex, 2);
*
* @endcode
**/
template <typename T>
struct reflect_struct_traits;
/** @class reflect_struct_member
* @brief reflection ingredients for a particular struct member
*
* A class/struct T to be reflected should provide specializations
* of
* - xo::reflect::reflect_struct_traits<>
* - xo::reflect::reflect_struct_member<>
* - xo::reflect::reflect_struct_parent<> [aspirational, not yet]
*
* For example:
*
* @code
*
* namespace foo {
* struct mycomplex { double real_, double imag_; };
* }
*
* namespace xo {
* namespace reflect {
* // reflect foo::mycomplex::real_
* template <>
* struct reflect_struct_member<foo::mycomplex, 0> {
* constexpr auto operator()() const { return reflect_struct_member_aux(xo::flatstring("real"), &foo::mycomplex::real_); }
* };
*
* // reflect foo::mycomplex::imag_
* template <>
* struct reflect_struct_member<foo::mycomplex, 1> {
* constexpr auto operator()() const { return reflect_struct_member_aux(xo::flatstring("imag"), &foo::mycomplex::imag_); }
* };
* }
* }
*
* // or use convenience macro (must be invoked from global namespace)
* REFLECT_STRUCT_MEMBER_INFO(foo::mycomplex, 0, real);
* REFLECT_STRUCT_MEMBER_INFO(foo::mycomplex, 1, imag);
*
* @endcode
**/
template <typename T, std::size_t N>
struct reflect_struct_member;
// ----------------------------------------------------------------
template <typename OwnerT, typename MemberT, typename MemberNameT>
struct reflect_struct_member_info {
//using struct_type = StructT;
using owner_type = OwnerT;
using member_type = MemberT;
using member_name_type = MemberNameT;
constexpr reflect_struct_member_info(const MemberNameT & member_name,
MemberT OwnerT::* member_addr)
: member_name_{member_name}, member_addr_{member_addr} {}
MemberNameT member_name_;
MemberT OwnerT::* member_addr_;
};
// ----------------------------------------------------------------
template <typename OwnerT, typename MemberT, typename MemberNameT>
constexpr auto reflect_struct_member_aux(const MemberNameT & member_name,
MemberT OwnerT:: * member_addr) {
return reflect_struct_member_info<OwnerT, MemberT, MemberNameT>
(member_name, member_addr);
};
} /*namespace reflect*/
} /*namespace xo*/
/** end reflect_struct_info.hpp **/