+ xo-printable2 + build fixes for cmake config

This commit is contained in:
Roland Conybeare 2026-01-04 23:03:18 -05:00
commit 402cf9b852
29 changed files with 724 additions and 72 deletions

View file

@ -90,8 +90,9 @@ add_subdirectory(xo-ratio)
add_subdirectory(xo-unit)
add_subdirectory(xo-pyunit)
add_subdirectory(xo-callback)
add_subdirectory(xo-printable2) # experiment w/ facet object model
add_subdirectory(xo-alloc)
add_subdirectory(xo-alloc2) # experiment w/ sep iface,data
add_subdirectory(xo-alloc2) # experiment w/ facet object model
add_subdirectory(xo-gc)
add_subdirectory(xo-object)
add_subdirectory(xo-object2) # experiment w/ facet object model

View file

@ -21,7 +21,8 @@ add_definitions(${PROJECT_CXX_FLAGS})
# must complete definition of expression lib before configuring examples
add_subdirectory(src/alloc2)
add_subdirectory(utest)
#xo_export_cmake_config(${PROJECT_NAME} ${PROJECT_VERSION} ${PROJECT_NAME}Targets)
xo_export_cmake_config(${PROJECT_NAME} ${PROJECT_VERSION} ${PROJECT_NAME}Targets)
# ----------------------------------------------------------------
# docs targets depend on other library/utest/exec targets above,

View file

@ -64,6 +64,11 @@ macro(xo_cxx_toplevel_options2)
set_property(
TARGET docs_${PROJECT_NAME}
PROPERTY targets "")
add_custom_target(idl_${PROJECT_NAME})
set_property(
TARGET idl_${PROJECT_NAME}
PROPERTY path ${PROJECT_SOURCE_DIR}/idl)
endif()
endmacro()
@ -1625,7 +1630,7 @@ endmacro()
# for faceted object model
#
macro(xo_add_genfacet)
function(xo_add_genfacet)
# Parse arguments
set(options "")
set(oneValueArgs
@ -1638,8 +1643,26 @@ macro(xo_add_genfacet)
)
set(multiValueArgs "")
message(STATUS "oneValueArgs=${oneValueArgs}")
cmake_parse_arguments(GF "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
if(NOT DEFINED GF_TARGET)
message(FATAL_ERROR "xo_add_genfacet: TARGET is required")
endif()
if(NOT DEFINED GF_FACET)
message(FATAL_ERROR "xo_add_genfacet: FACET is required")
endif()
if(NOT DEFINED GF_OUTPUT_HPP_DIR)
message(FATAL_ERROR "xo_add_genfacet: OUTPUT_HPP_DIR is required")
endif()
if(NOT DEFINED GF_OUTPUT_IMPL_SUBDIR)
message(FATAL_ERROR "xo_add_genfacet: OUTPUT_IMPL_SUBDIR is required")
endif()
if(NOT DEFINED GF_OUTPUT_CPP_DIR)
message(FATAL_ERROR "xo_add_genfacet: OUTPUT_CPP_DIR is required")
endif()
find_program(GENFACET_EXECUTABLE NAMES genfacet
HINTS ${CMAKE_SOURCE_DIR}/xo-facet/codegen
DOC "path to xo genfacet code generator"
@ -1647,57 +1670,16 @@ macro(xo_add_genfacet)
message(STATUS "GENFACET_EXECUTABLE=${GENFACET_EXECUTABLE}")
set(generatedFiles
${GF_OUTPUT_HPP_DIR}/${FACET}.hpp
${GF_OUTPUT_HPP_DIR}/${GF_OUTPUT_IMPL_SUBDIR}/A${FACET}.hpp
${GF_OUTPUT_HPP_DIR}/${GF_OUTPUT_IMPL_SUBDIR}/I${FACET}_Any.hpp
${GF_OUTPUT_HPP_DIR}/${GF_OUTPUT_IMPL_SUBDIR}/I${FACET}_Xfer.hpp
${GF_OUTPUT_HPP_DIR}/${GF_OUTPUT_IMPL_SUBDIR}/R${FACET}.hpp
${GF_OUTPUT_CPP_DIR}/I${FACET}_Any.cpp)
${GF_OUTPUT_HPP_DIR}/${GF_FACET}.hpp
${GF_OUTPUT_HPP_DIR}/${GF_OUTPUT_IMPL_SUBDIR}/A${GF_FACET}.hpp
${GF_OUTPUT_HPP_DIR}/${GF_OUTPUT_IMPL_SUBDIR}/I${GF_FACET}_Any.hpp
${GF_OUTPUT_HPP_DIR}/${GF_OUTPUT_IMPL_SUBDIR}/I${GF_FACET}_Xfer.hpp
${GF_OUTPUT_HPP_DIR}/${GF_OUTPUT_IMPL_SUBDIR}/R${GF_FACET}.hpp
${GF_OUTPUT_CPP_DIR}/I${GF_FACET}_Any.cpp)
# Build the genfacet command
add_custom_command(
OUTPUT $generatedFiles
COMMAND ${GENFACET_EXECUTABLE}
--input ${GF_INPUT}
--output-hpp ${GF_OUTPUT_HPP_DIR}
--output-impl-hpp ${GF_OUTPUT_IMPL_SUBDIR}
--output-cpp ${GF_OUTPUT_CPP_DIR}
DEPENDS ${GF_INPUT}
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
COMMENT "Generating facet source files from ${GF_INPUT}"
VERBATIM
)
message(STATUS "generatedFiles=${generatedFiles}")
# Create a target for this generation
add_custom_target(${GF_TARGET} DEPENDS ${generatedFiles})
endmacro()
macro(xo_add_genfacetimpl)
# Parse arguments
set(options "")
set(oneValueArgs
TARGET # Name for this generation target
FACET # facet name
REPR # representation name
INPUT # Input .json5 file
OUTPUT_HPP_DIR # Directory for .hpp files
OUTPUT_IMPL_SUBDIR # Subdirectory name for impl headers
OUTPUT_CPP_DIR # Directory for .cpp files
)
set(multiValueArgs "")
cmake_parse_arguments(GF "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
find_program(GENFACET_EXECUTABLE NAMES genfacet
HINTS ${CMAKE_SOURCE_DIR}/xo-facet/codegen
DOC "path to xo genfacet code generator"
REQUIRED)
message(STATUS "GENFACET_EXECUTABLE=${GENFACET_EXECUTABLE}")
set(generatedFiles
${GF_OUTPUT_HPP_DIR}/${FACET}.hpp
${GF_OUTPUT_HPP_DIR}/${GF_OUTPUT_IMPL_SUBDIR}/I${FACET}_D${REPR}.hpp
${GF_OUTPUT_CPP_DIR}/I${FACET}_D${REPR}.cpp)
message(ERROR "epic fail")
# Build the genfacet command
add_custom_command(
@ -1715,4 +1697,72 @@ macro(xo_add_genfacetimpl)
# Create a target for this generation
add_custom_target(${GF_TARGET} DEPENDS ${generatedFiles})
endmacro()
endfunction()
function(xo_add_genfacetimpl)
# Parse arguments
set(options "")
set(oneValueArgs
TARGET # Name for this generation target
FACET # facet name
REPR # representation name
INPUT # Input .json5 file
OUTPUT_HPP_DIR # Directory for .hpp files
OUTPUT_IMPL_SUBDIR # Subdirectory name for impl headers
OUTPUT_CPP_DIR # Directory for .cpp files
)
set(multiValueArgs "")
cmake_parse_arguments(GF "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
if(NOT DEFINED GF_TARGET)
message(FATAL_ERROR "xo_add_genfacetimpl: TARGET is required")
endif()
if(NOT DEFINED GF_FACET)
message(FATAL_ERROR "xo_add_genfacetimpl: FACET is required")
endif()
if(NOT DEFINED GF_REPR)
message(FATAL_ERROR "xo_add_genfacetimpl: REPR is required")
endif()
if(NOT DEFINED GF_INPUT)
message(FATAL_ERROR "xo_add_genfacetimpl: INPUT is required")
endif()
if(NOT DEFINED GF_OUTPUT_HPP_DIR)
message(FATAL_ERROR "xo_add_genfacetimpl: OUTPUT_HPP_DIR is required")
endif()
if(NOT DEFINED GF_OUTPUT_IMPL_SUBDIR)
message(FATAL_ERROR "xo_add_genfacetimpl: OUTPUT_IMPL_SUBDIR is required")
endif()
if(NOT DEFINED GF_OUTPUT_CPP_DIR)
message(FATAL_ERROR "xo_add_genfacetimpl: OUTPUT_CPP_DIR is required")
endif()
find_program(GENFACET_EXECUTABLE NAMES genfacet
HINTS ${CMAKE_SOURCE_DIR}/xo-facet/codegen
DOC "path to xo genfacet code generator"
REQUIRED)
message(STATUS "GENFACET_EXECUTABLE=${GENFACET_EXECUTABLE}")
set(generatedFiles
${GF_OUTPUT_HPP_DIR}/${GF_OUTPUT_IMPL_SUBDIR}/I${GF_FACET}_D${GF_REPR}.hpp
${GF_OUTPUT_CPP_DIR}/I${GF_FACET}_D${GF_REPR}.cpp)
# Build the genfacet command.
# But careful: can't have the same generated files in two different rules,
# so need to remove overlaps here
add_custom_command(
OUTPUT ${generatedFiles}
COMMAND ${GENFACET_EXECUTABLE}
--input ${GF_INPUT}
--output-hpp ${GF_OUTPUT_HPP_DIR}
--output-impl-hpp ${GF_OUTPUT_IMPL_SUBDIR}
--output-cpp ${GF_OUTPUT_CPP_DIR}
DEPENDS ${GF_INPUT}
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
COMMENT "Generating facet source files from ${GF_INPUT}"
VERBATIM
)
# Create a target for this generation
add_custom_target(${GF_TARGET} DEPENDS ${generatedFiles})
endfunction()

View file

@ -1 +1,56 @@
# xo-facet
## Codegen
To scaffold a new facet Foo we need several c++ classes
* `AFoo` abstract FOMO interface, with opaque data pointer
* `IFoo_Any` variant placeholder, all methods terminate
* `IFoo_Xfer` template, delegates methods to a separate implementation class
* `RFoo` template, inherits from a 2x-wide fat pointer (iface+data).
These classes all have parallel methods
Can generate these as follows:
1. write `xo-foo/idl/Foo.json5`.
Supply attributes:
- mode :: string
- includes :: [string]
- namespace1 :: string
- namespace2 :: string
- facet :: string
- detail_subdir :: string
- brief :: string
- using_doxygen :: bool
- doc :: [string]
- types :: [{name, doc, definition}]
- const_methods :: [{name, doc, return_type, args, const, noexcept, attributes}]
- nonconst_methods :: [{name, doc, return_type, args, const, noexcept, attributes}]
Example in xo-object2/idl/Sequence.json5
2. generate:
```
$ cd xo-foo
$ ../xo-facet/codegen/genfacet.py --input ./idl/Foo.json5 --output include/xo/foo2
```
Alternatively in `xo-foo/CMakeLists.txt`
```
xo_add_genfacet(
TARGET xo-foo2-facet-foo
FACET Foo
INPUT idl/Foo.json5
OUTPUT_HTTP_DIR include/xo/foo2
OUTPUT_IMPL_SUBDIR detail
OUTPUT_CPP_DIR src/foo2)
```
then generate with:
```
cmake --build path/to/build -- xo-foo2-facet-foo
```

View file

@ -37,6 +37,8 @@ public:
///@{
{% endif %}
// types
/** integer identifying a type **/
using typeseq = xo::facet::typeseq;
{% for ty in types %}
/** {{ty.doc}} **/
using {{ty.name}} = {{ty.definition}};
@ -51,7 +53,7 @@ public:
{% endif %}
// const methods
/** RTTI: unique id# for actual runtime data representation **/
virtual int32_t _typeseq() const noexcept = 0;
virtual typeseq _typeseq() const noexcept = 0;
{% for md in const_methods %}
/** {{md.doc}} **/
virtual {{md.return_type}} {{md.name}}({{md.args | args}}) {{md | qualifiers}} = 0;

View file

@ -77,9 +77,8 @@ def format_args_impl(args, drepr):
def gen_facet(env,
idl_fname,
idl,
input_json5,
output_hpp_dir,
output_impl_hpp_dir,
#output_impl_hpp_subdir,
output_cpp_dir):
@ -88,6 +87,8 @@ def gen_facet(env,
# extra include files (or perhaps other definitions)
facet_includes = idl['includes']
# detail
facet_detail_subdir = idl['detail_subdir']
facet_ns1 = idl['namespace1']
facet_ns2 = idl['namespace2']
facet_name = idl['facet'] # e.g. Sequence
@ -95,6 +96,8 @@ def gen_facet(env,
facet_brief = idl['brief']
facet_doc = '\n'.join(idl['doc'])
output_impl_hpp_dir = output_hpp_dir / facet_detail_subdir
types = idl['types']
for ty in types:
ty['doc'] = '\n'.join(ty['doc'])
@ -143,7 +146,7 @@ def gen_facet(env,
'genfacet': __file__,
'genfacet_input': idl_fname,
'using_dox': using_dox,
'impl_hpp_subdir': output_impl_hpp_subdir,
'impl_hpp_subdir': facet_detail_subdir,
#
'facet_hpp_j2': 'facet.hpp.j2',
'facet_includes': facet_includes,
@ -475,23 +478,23 @@ def main():
env.filters['argimpl'] = format_args_impl
if idl['mode'] == 'facet':
gen_facet(env,
idl_fname,
idl,
output_hpp_dir,
output_impl_hpp_dir,
output_cpp_dir)
gen_facet(env=env,
idl_fname=idl_fname,
idl=idl,
output_hpp_dir=output_hpp_dir,
#output_impl_hpp_dir=output_impl_hpp_dir,
output_cpp_dir=output_cpp_dir)
elif idl['mode'] == 'implementation':
facet_idl_fname = idl['facet_idl']
facet_idl = load_idl(facet_idl_fname)
gen_facet_impl(env,
idl_fname,
idl,
facet_idl,
output_hpp_dir,
output_impl_hpp_dir,
output_cpp_dir)
gen_facet_impl(env=env,
idl_fname=idl_fname,
idl=idl,
facet_idl=facet_idl,
output_hpp_dir=output_hpp_dir,
output_impl_hpp_dir=output_impl_hpp_dir,
output_cpp_dir=output_cpp_dir)
if __name__ == '__main__':
main()

View file

@ -25,7 +25,7 @@ void
std::terminate();
}
int32_t
typeseq
{{iface_facet_any}}::s_typeseq = typeseq::id<DVariantPlaceholder>();
bool

View file

@ -44,6 +44,8 @@ namespace {{facet_ns2}} {
///@{
{% endif %}
/** integer identifying a type **/
using typeseq = xo::facet::typeseq;
{% for ty in types %}
using {{ty.name}} = {{abstract_facet}}::{{ty.name}};
{% endfor %}
@ -61,14 +63,14 @@ namespace {{facet_ns2}} {
// from {{abstract_facet}}
// const methods
int32_t _typeseq() const noexcept override { return s_typeseq; }
typeseq _typeseq() const noexcept override { return s_typeseq; }
{% for md in const_methods %}
[[noreturn]] {{md.return_type}} {{md.name}}({{md.args | argtypes}}) {{md | qualifiers}} override { _fatal(); }
{% endfor %}
// nonconst methods
{% for md in nonconst_methods %}
[[noreturn]] {{md.return_type}} {{md.name}}({{md.args | argtypes}}) {{md | qualifiers}} override { _fatail(); }
[[noreturn]] {{md.return_type}} {{md.name}}({{md.args | argtypes}}) {{md | qualifiers}} override { _fatal(); }
{% endfor %}
{% if using_dox %}
@ -89,11 +91,11 @@ namespace {{facet_ns2}} {
public:
{% if using_dox %}
/** @defgraoup {{facet_ns2}}-{{facet_name_lc}}-any-member-vars **/
/** @defgroup {{facet_ns2}}-{{facet_name_lc}}-any-member-vars **/
///@{
{% endif %}
static int32_t s_typeseq;
static typeseq s_typeseq;
static bool _valid;
{% if using_dox %}

View file

@ -68,7 +68,7 @@ namespace {{facet_ns2}} {
public:
{% if using_dox %}
/** @defgraoup {{facet_ns2}}-{{facet_name_lc}}-xfer-member-vars **/
/** @defgroup {{facet_ns2}}-{{facet_name_lc}}-xfer-member-vars **/
///@{
{% endif %}

View file

@ -21,7 +21,8 @@ add_definitions(${PROJECT_CXX_FLAGS})
# must complete definition of expression lib before configuring examples
add_subdirectory(src/gc)
add_subdirectory(utest)
#xo_export_cmake_config(${PROJECT_NAME} ${PROJECT_VERSION} ${PROJECT_NAME}Targets)
xo_export_cmake_config(${PROJECT_NAME} ${PROJECT_VERSION} ${PROJECT_NAME}Targets)
# ----------------------------------------------------------------
# docs targets depend on other library/utest/exec targets above,

View file

@ -1,17 +1,17 @@
/* ppdetail_atomic.hpp
/** @file ppdetail_atomic.hpp
*
* author: Roland Conybeare, Jul 2025
*/
* @author Roland Conybeare, Jul 2025
**/
#pragma once
#include "ppindentinfo.hpp"
#include <string>
#include <cstdint>
namespace xo {
namespace print {
struct ppstate; // see pretty.hpp
struct ppindentinfo;
// Defining this means ppdetail_atomic -> ppdetail.
// For debugging suppress the #define; causes specialization of ppdetail_atomic to be required for every T
@ -22,28 +22,6 @@ namespace xo {
//
#define ppdetail_atomic ppdetail
struct ppindentinfo {
ppindentinfo(ppstate * pps, std::uint32_t ci0, std::uint32_t indent_width, bool upto)
: pps_{pps}, ci0_{ci0}, ci1_{ci0 + indent_width}, upto_{upto} {}
ppstate * pps() const { return pps_; }
std::uint32_t ci0_unused() const { return ci0_; }
std::uint32_t ci1() const { return ci1_; }
bool upto() const { return upto_; }
private:
ppstate * pps_ = nullptr;
/** current indent **/
std::uint32_t ci0_ = 0;
/** ci0 +1 indent level **/
std::uint32_t ci1_ = 0;
/**
* true -> print on remainder of current line, unless past right margin
* false -> pretty across across multiple lines
**/
bool upto_;
};
/** @class ppdetail
* @brief template for opt-in to pretty-printer
*

View file

@ -0,0 +1,43 @@
/** @file ppindentinfo.hpp
*
* @author Roland Conybeare, Jul 2025
**/
#pragma once
#include <cstdint>
namespace xo {
namespace print {
struct ppstate;
/** @class ppindentinfo
* @brief pretty-printing state passed down the stack while traversing object graph
**/
struct ppindentinfo {
ppindentinfo(ppstate * pps, std::uint32_t ci0, std::uint32_t indent_width, bool upto)
: pps_{pps}, ci0_{ci0}, ci1_{ci0 + indent_width}, upto_{upto} {}
ppstate * pps() const { return pps_; }
std::uint32_t ci0_unused() const { return ci0_; }
std::uint32_t ci1() const { return ci1_; }
bool upto() const { return upto_; }
private:
/** pretty-printing state. flyweight. See [xo/indentlog/print/pretty.hpp] **/
ppstate * pps_ = nullptr;
/** current indent **/
std::uint32_t ci0_ = 0;
/** ci0 +1 indent level **/
std::uint32_t ci1_ = 0;
/**
* true -> print on remainder of current line, unless past right margin
* false -> pretty across across multiple lines
**/
bool upto_;
};
}
}
/* end ppindentinfo.hpp */

View file

@ -37,12 +37,26 @@ xo_add_genfacetimpl(
OUTPUT_CPP_DIR src/object2
)
get_target_property(xo_printable2_src_dir xo-printable2 xo_srcdir)
message(STATUS "xo_printable2_src_dir=${xo_printable_src_dir}")
xo_add_genfacetimpl(
TARGET xo-object2-facetimpl-printable-float
FACET Printable
REPR Float
INPUT idl/IPrintable_DFloat.json5
OUTPUT_HPP_DIR include/xo/object2
OUTPUT_IMPL_SUBDIR .
OUTPUT_CPP_DIR src/object2
)
# ----------------------------------------------------------------
# must complete definition of expression lib before configuring examples
add_subdirectory(src/object2)
add_subdirectory(utest)
#xo_export_cmake_config(${PROJECT_NAME} ${PROJECT_VERSION} ${PROJECT_NAME}Targets)
xo_export_cmake_config(${PROJECT_NAME} ${PROJECT_VERSION} ${PROJECT_NAME}Targets)
# ----------------------------------------------------------------
# docs targets depend on other library/utest/exec targets above,

View file

@ -0,0 +1,11 @@
{
mode: "implementation",
includes: [],
namespace1: "xo",
namespace2: "print",
facet_idl: "idl/Printable.json5",
brief: "provide APrintable interface for DFloat",
using_doxygen: true,
repr: "DFloat",
doc: [ "doc for something or other" ],
}

View file

@ -66,7 +66,7 @@ namespace scm {
///@}
private:
/** @defgraoup scm-sequence-any-private-methods **/
/** @defgroup scm-sequence-any-private-methods **/
///@{
[[noreturn]] static void _fatal();
@ -74,7 +74,7 @@ namespace scm {
///@}
public:
/** @defgraoup scm-sequence-any-member-vars **/
/** @defgroup scm-sequence-any-member-vars **/
///@{
static typeseq s_typeseq;

View file

@ -57,7 +57,7 @@ namespace scm {
using I = Impl;
public:
/** @defgraoup scm-sequence-xfer-member-vars **/
/** @defgroup scm-sequence-xfer-member-vars **/
///@{
/** typeseq for template parameter DRepr **/

View file

@ -16,4 +16,3 @@ xo_add_shared_library4(${SELF_LIB} ${PROJECT_NAME}Targets ${PROJECT_VERSION} 1 $
# note: deps here must also appear in cmake/xo_alloc2Config.cmake.in
xo_dependency(${SELF_LIB} xo_gc)
#xo_dependency(${SELF_LIB} indentlog)
#add_dependencies(${SELF_LIB} xo-object2-facetimpl-sequence-list)

View file

@ -0,0 +1,43 @@
# xo-printable2/CMakeLists.txt
cmake_minimum_required(VERSION 3.10)
project(xo_printable2 VERSION 0.1)
include(GNUInstallDirs)
include(cmake/xo-bootstrap-macros.cmake)
xo_cxx_toplevel_options3()
# ----------------------------------------------------------------
# c++ settings
set(PROJECT_CXX_FLAGS "")
#set(PROJECT_CXX_FLAGS "-fconcepts-diagnostics-depth=2") # gcc-only!
add_definitions(${PROJECT_CXX_FLAGS})
# ----------------------------------------------------------------
xo_add_genfacet(
TARGET xo-printable2-facet-printable
FACET Printable
INPUT idl/Printable.json5
OUTPUT_HPP_DIR include/xo/printable2
OUTPUT_IMPL_SUBDIR detail
OUTPUT_CPP_DIR src/printable2
)
# ----------------------------------------------------------------
add_subdirectory(src/printable2)
#add_subdirectory(utest)
xo_export_cmake_config(${PROJECT_NAME} ${PROJECT_VERSION} ${PROJECT_NAME}Targets)
# ----------------------------------------------------------------
# docs targets depend on other library/utest/exec targets above,
# --> must come after them.
#
#add_subdirectory(docs)
# end CMakeLists.txt

View file

@ -0,0 +1,35 @@
# ----------------------------------------------------------------
# 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 ("${XO_CMAKE_CONFIG_EXECUTABLE}" STREQUAL "XO_CMAKE_CONFIG_EXECUTABLE-NOT_FOUND")
message(FATAL "could not find xo-cmake-config executable")
endif()
message(STATUS "XO_CMAKE_CONFIG_EXECUTABLE=${XO_CMAKE_CONFIG_EXECUTABLE}")
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,7 @@
@PACKAGE_INIT@
include(CMakeFindDependencyMacro)
find_dependency(indentlog)
find_dependency(xo_facet)
include("${CMAKE_CURRENT_LIST_DIR}/@PROJECT_NAME@Targets.cmake")
check_required_components("@PROJECT_NAME@")

View file

@ -0,0 +1,29 @@
{
mode: "facet",
includes: ["<xo/indentlog/print/ppindentinfo.hpp>"],
namespace1: "xo",
namespace2: "print",
facet: "Printable",
detail_subdir: "detail",
brief: "pretty-printable objects",
using_doxygen: true,
doc: [
"Trait for data types that support pretty-printing"
],
types: [],
const_methods: [
// bool pretty(const ppindentinfo & ppii) const
{
name: "pretty",
doc: [
"Pretty-printing support for this object.",
"See [xo-indentlog/xo/indentlog/pretty.hpp]",
],
return_type: "bool",
args: [
{type: "const ppindentinfo &", name: "ppii"},
],
},
],
nonconst_methods: [],
}

View file

@ -0,0 +1,21 @@
/** @file Printable.hpp
*
* Generated automagically from ingredients:
* 1. code generator:
* [/home/roland/proj/xo-umbrella2/xo-facet/codegen/genfacet]
* arguments:
* --input [idl/Printable.json5]
* 2. jinja2 template for facet .hpp file:
* [facet.hpp.j2]
* 3. idl for facet methods
* [idl/Printable.json5]
**/
#pragma once
#include "detail/APrintable.hpp"
#include "detail/IPrintable_Any.hpp"
#include "detail/IPrintable_Xfer.hpp"
#include "detail/RPrintable.hpp"
/* end Printable.hpp */

View file

@ -0,0 +1,69 @@
/** @file APrintable.hpp
*
* Generated automagically from ingredients:
* 1. code generator:
* [/home/roland/proj/xo-umbrella2/xo-facet/codegen/genfacet]
* arguments:
* --input [idl/Printable.json5]
* 2. jinja2 template for abstract facet .hpp file:
* [abstract_facet.hpp.j2]
* 3. idl for facet methods
* [idl/Printable.json5]
**/
#pragma once
// includes (via {facet_includes})
#include <xo/indentlog/print/ppindentinfo.hpp>
#include <xo/facet/obj.hpp>
#include <xo/facet/facet_implementation.hpp>
#include <xo/facet/typeseq.hpp>
namespace xo {
namespace print {
using Copaque = const void *;
using Opaque = void *;
/**
Trait for data types that support pretty-printing
**/
class APrintable {
public:
/** @defgroup print-printable-type-traits **/
///@{
// types
/** integer identifying a type **/
using typeseq = xo::facet::typeseq;
///@}
/** @defgroup print-printable-methods **/
///@{
// const methods
/** RTTI: unique id# for actual runtime data representation **/
virtual typeseq _typeseq() const noexcept = 0;
/** Pretty-printing support for this object.
See [xo-indentlog/xo/indentlog/pretty.hpp] **/
virtual bool pretty(Copaque data, const ppindentinfo & ppii) = 0;
// nonconst methods
///@}
}; /*APrintable*/
/** Implementation IPrintable_DRepr of APrintable for state DRepr
* should provide a specialization:
*
* template <>
* struct xo::facet::FacetImplementation<APrintable, DRepr> {
* using Impltype = IPrintable_DRepr;
* };
*
* then IPrintable_ImplType<DRepr> --> IPrintable_DRepr
**/
template <typename DRepr>
using IPrintable_ImplType = xo::facet::FacetImplType<APrintable, DRepr>;
} /*namespace print*/
} /*namespace xo*/
/* */

View file

@ -0,0 +1,85 @@
/** @file IPrintable_Any.hpp
*
* Generated automagically from ingredients:
* 1. code generator:
* [/home/roland/proj/xo-umbrella2/xo-facet/codegen/genfacet]
* arguments:
* --input [idl/Printable.json5]
* 2. jinja2 template for abstract facet .hpp file:
* [iface_facet_any.hpp.j2]
* 3. idl for facet methods
* [idl/Printable.json5]
**/
#pragma once
#include "APrintable.hpp"
#include <xo/facet/obj.hpp>
namespace xo { namespace print { class IPrintable_Any; } }
namespace xo {
namespace facet {
template <>
struct FacetImplementation<xo::print::APrintable,
DVariantPlaceholder>
{
using ImplType = xo::print::IPrintable_Any;
};
}
}
namespace xo {
namespace print {
/** @class IPrintable_Any
* @brief APrintable implementation for empty variant instance
**/
class IPrintable_Any : public APrintable {
public:
/** @defgroup print-printable-any-type-traits **/
///@{
/** integer identifying a type **/
using typeseq = xo::facet::typeseq;
///@}
/** @defgroup print-printable-any-methods **/
///@{
const APrintable * iface() const { return std::launder(this); }
// from APrintable
// const methods
typeseq _typeseq() const noexcept override { return s_typeseq; }
[[noreturn]] bool pretty(Copaque, const ppindentinfo &) override { _fatal(); }
// nonconst methods
///@}
private:
/** @defgraoup print-printable-any-private-methods **/
///@{
[[noreturn]] static void _fatal();
///@}
public:
/** @defgraoup print-printable-any-member-vars **/
///@{
static typeseq s_typeseq;
static bool _valid;
///@}
};
} /*namespace print */
} /*namespace xo */
/* IPrintable_Any.hpp */

View file

@ -0,0 +1,77 @@
/** @file IPrintable_Xfer.hpp
*
* Generated automagically from ingredients:
* 1. code generator:
* [/home/roland/proj/xo-umbrella2/xo-facet/codegen/genfacet]
* arguments:
* --input [idl/Printable.json5]
* 2. jinja2 template for abstract facet .hpp file:
* [iface_facet_any.hpp.j2]
* 3. idl for facet methods
* [idl/Printable.json5]
**/
#pragma once
#include "APrintable.hpp"
namespace xo {
namespace print {
/** @class IPrintable_Xfer
**/
template <typename DRepr, typename IPrintable_DRepr>
class IPrintable_Xfer : public APrintable {
public:
/** @defgroup print-printable-xfer-type-traits **/
///@{
using Impl = IPrintable_DRepr;
///@}
/** @defgroup print-printable-xfer-methods **/
///@{
static const DRepr & _dcast(Copaque d) { return *(const DRepr *)d; }
static DRepr & _dcast(Opaque d) { return *(DRepr *)d; }
// from APrintable
// const methods
int32_t _typeseq() const noexcept override { return s_typeseq; }
bool pretty(Copaque data, const ppindentinfo & ppii) override {
return I::pretty(_dcast(data), ppii);
}
// non-const methods
///@}
private:
using I = Impl;
public:
/** @defgraoup print-printable-xfer-member-vars **/
///@{
/** typeseq for template parameter DRepr **/
static int32_t s_typeseq;
/** true iff satisfies facet implementation **/
static bool _valid;
///@}
};
template <typename DRepr, typename IPrintable_DRepr>
int32_t
IPrintable_Xfer<DRepr, IPrintable_DRepr>::s_typeseq
= xo::facet::typeseq::id<DRepr>();
template <typename DRepr, typename IPrintable_DRepr>
bool
IPrintable_Xfer<DRepr, IPrintable_DRepr>::_valid
= xo::facet::valid_facet_implementation<APrintable,
IPrintable_Xfer>();
} /*namespace print */
} /*namespace xo*/
/* end IPrintable_Xfer.hpp */

View file

@ -0,0 +1,77 @@
/** @file RPrintable.hpp
*
* Generated automagically from ingredients:
* 1. code generator:
* [/home/roland/proj/xo-umbrella2/xo-facet/codegen/genfacet]
* arguments:
* --input [idl/Printable.json5]
* 2. jinja2 template for abstract facet .hpp file:
* [iface_facet_any.hpp.j2]
* 3. idl for facet methods
* [idl/Printable.json5]
**/
#pragma once
#include "APrintable.hpp"
namespace xo {
namespace print {
/** @class RPrintable
**/
template <typename Object>
class RPrintable : public Object {
private:
using O = Object;
public:
/** @defgroup print-printable-router-type-traits **/
///@{
using ObjectType = Object;
using DataPtr = Object::DataPtr;
///@}
/** @defgroup print-printable-router-ctors **/
///@{
RPrintable() {}
RPrintable(Object::DataPtr data) : Object{std::move(data)} {}
///@}
/** @defgroup print-printable-router-methods **/
///@{
// const methods
int32_t _typeseq() const noexcept { return O::iface()->_typeseq(); }
bool pretty(const ppindentinfo & ppii) override {
return O::iface()->pretty(O::data(), ppii);
}
// non-const methods
// << do something for non-const methods >>
//
///@}
/** @defgroup print-printable-member-vars **/
///@{
static bool _valid;
///@}
};
template <typename Object>
bool
RPrintable<Object>::_valid = xo::facet::valid_object_router<Object>();
} /*namespace print*/
} /*namespace xo*/
namespace xo { namespace facet {
template <typename Object>
struct RoutingFor<xo::print::APrintable, Object> {
using RoutingType = xo::print::RPrintable<Object>;
};
} }
/* end RPrintable.hpp */

View file

@ -0,0 +1,11 @@
# printable2/CMakeLists.txt
set(SELF_LIB xo_printable2)
set(SELF_SRCS
IPrintable_Any.cpp
)
xo_add_shared_library4(${SELF_LIB} ${PROJECT_NAME}Targets ${PROJECT_VERSION} 1 ${SELF_SRCS})
# note: deps here must coord with cmake/xo_printable2Config.cmake.in
xo_dependency(${SELF_LIB} indentlog)
xo_dependency(${SELF_LIB} xo_facet)

View file

@ -0,0 +1,38 @@
/** @file IPrintable_Any.cpp
*
**/
#include "detail/IPrintable_Any.hpp"
#include <iostream>
namespace xo {
namespace print {
using xo::facet::DVariantPlaceholder;
using xo::facet::typeseq;
using xo::facet::valid_facet_implementation;
void
IPrintable_Any::_fatal()
{
/* control here on uninitialized IAllocator_Any.
* Initialized instance will have specific implementation type
*/
std::cerr << "fatal"
<< ": attempt to call uninitialized"
<< " IPrintable_Any method"
<< std::endl;
std::terminate();
}
typeseq
IPrintable_Any::s_typeseq = typeseq::id<DVariantPlaceholder>();
bool
IPrintable_Any::_valid
= valid_facet_implementation<APrintable, IPrintable_Any>();
} /*namespace print*/
} /*namespace xo*/
/* end IPrintable_Any.cpp */