Skip to content

Commit 30fe142

Browse files
authoredNov 28, 2024
Merge pull request #32 from rock-cpp/TypeWrapper
TypeWrapper class to easily introspect and use fields of typelib types
2 parents a697322 + aa53379 commit 30fe142

File tree

6 files changed

+593
-2
lines changed

6 files changed

+593
-2
lines changed
 

‎CMakeLists.txt

-2
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,6 @@ cmake_minimum_required(VERSION 2.6)
44
find_package(Rock)
55
rock_init(orocos_cpp 0.1)
66

7-
SET( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x" )
8-
97
set(OROCOS_TARGET "gnulinux")
108
rock_standard_layout()
119

‎src/CMakeLists.txt

+10
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ rock_library(orocos_cpp
1313
PluginHelper.cpp
1414
PkgConfigRegistry.cpp
1515
orocos_cpp.cpp
16+
TypeWrapper.cpp
1617
OrocosCppConfig.hpp
1718
HEADERS
1819
ConfigurationHelper.hpp
@@ -26,6 +27,7 @@ rock_library(orocos_cpp
2627
PluginHelper.hpp
2728
PkgConfigRegistry.hpp
2829
orocos_cpp.hpp
30+
TypeWrapper.hpp
2931
OrocosCppConfig.hpp
3032
DEPS_PKGCONFIG
3133
orocos_cpp_base
@@ -56,3 +58,11 @@ rock_executable(config main3.cpp
5658
rock_executable(nameservice main4.cpp
5759
DEPS orocos_cpp
5860
NOINSTALL)
61+
62+
rock_executable(typewrapper main5.cpp
63+
DEPS orocos_cpp
64+
NOINSTALL)
65+
66+
rock_executable(config_wrapper main6.cpp
67+
DEPS orocos_cpp
68+
NOINSTALL)

‎src/TypeWrapper.cpp

+153
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
2+
#include "TypeWrapper.hpp"
3+
#include <iostream>
4+
5+
6+
// /home/planthaber/dfki/workspace/terrain_exploration/workspace/gui/rock-display/src/configuration.cpp
7+
8+
namespace orocos_cpp {
9+
10+
TypeWrapper::TypeWrapper(Typelib::Value& value):value(value) {
11+
switch (value.getType().getCategory()) {
12+
case Typelib::Type::Category::Compound:
13+
addCompound();
14+
break;
15+
case Typelib::Type::Category::Container:
16+
addContainer();
17+
break;
18+
case Typelib::Type::Category::Array:
19+
addArray();
20+
break;
21+
case Typelib::Type::Category::Numeric:
22+
category = Typelib::Type::Category::Numeric;
23+
break;
24+
default:
25+
std::cout << "category "<< value.getType().getCategory() << " of type " << value.getType().getName() << std::endl;
26+
break;
27+
}
28+
}
29+
30+
void TypeWrapper::addCompound() {
31+
category = Typelib::Type::Category::Compound;
32+
// iterate fields
33+
const Typelib::Compound& compound = static_cast<const Typelib::Compound&>(value.getType());
34+
35+
uint8_t *data = static_cast<uint8_t *>(value.getData());
36+
for (const auto& field : compound.getFields()) {
37+
Typelib::Value newvalue(data + field.getOffset(), field.getType());
38+
// as the [] operator is overloaded, we need to call directly
39+
std::map<std::string, std::shared_ptr<TypeWrapper>>::operator[](field.getName()) = std::make_shared<TypeWrapper>(newvalue);
40+
}
41+
}
42+
43+
void TypeWrapper::addContainer() {
44+
category = Typelib::Type::Category::Container;
45+
const Typelib::Container& container = dynamic_cast<const Typelib::Container&>(value.getType());
46+
47+
if (container.isRandomAccess()) {
48+
for (size_t i = 0; i < container.getElementCount(value.getData()); ++i) {
49+
Typelib::Value newvalue = container.getElement(value.getData(), i);
50+
// as the [] operator is overloaded, we need to call directly
51+
std::map<std::string, std::shared_ptr<TypeWrapper>>::operator[](std::to_string(i)) = std::make_shared<TypeWrapper>(newvalue);
52+
}
53+
} else {
54+
// should be a /std/string
55+
//printf("%s:%i\n", __PRETTY_FUNCTION__, __LINE__);
56+
}
57+
}
58+
59+
void TypeWrapper::addArray() {
60+
category = Typelib::Type::Category::Array;
61+
const Typelib::Array& array = dynamic_cast<const Typelib::Array&>(value.getType());
62+
const Typelib::Type &indirect(array.getIndirection());
63+
64+
for (size_t i = 0; i < array.getDimension(); ++i) {
65+
Typelib::Value newvalue(static_cast<uint8_t *>(value.getData()) + i * indirect.getSize(), indirect);
66+
// as the [] operator is overloaded, we need to call directly
67+
std::map<std::string, std::shared_ptr<TypeWrapper>>::operator[](std::to_string(i)) = std::make_shared<TypeWrapper>(newvalue);
68+
}
69+
}
70+
71+
std::string TypeWrapper::toString() {
72+
switch (value.getType().getCategory()) {
73+
//case Typelib::Type::Category::Compound: return compoundToString();
74+
case Typelib::Type::Category::Numeric: return numericToString();
75+
case Typelib::Type::Category::Container: return containerToString();
76+
default: return "";
77+
}
78+
}
79+
80+
double TypeWrapper::toDouble() {
81+
if (value.getType().getCategory() != Typelib::Type::Category::Numeric) {
82+
throw std::runtime_error("Type is not numeric");
83+
}
84+
if (value.getType().getCategory() == Typelib::Type::Category::Numeric) {
85+
const Typelib::Numeric& numeric = dynamic_cast<const Typelib::Numeric&>(value.getType());
86+
switch (numeric.getNumericCategory()) {
87+
// "/bool" is encoded as uint8_t, no need for extra treatment
88+
case Typelib::Numeric::Float:
89+
if (numeric.getSize() == sizeof(float)) {
90+
return *static_cast<float*>(value.getData());
91+
} else {
92+
return *static_cast<double*>(value.getData());
93+
}
94+
case Typelib::Numeric::SInt:
95+
switch (numeric.getSize()) {
96+
case sizeof(int8_t): return static_cast<int>(*static_cast<int8_t *>(value.getData()));
97+
case sizeof(int16_t): return *static_cast<int16_t*>(value.getData());
98+
case sizeof(int32_t): return *static_cast<int32_t*>(value.getData());
99+
case sizeof(int64_t): return *static_cast<int64_t*>(value.getData());
100+
default:
101+
std::cerr << "Error, got integer of unexpected size " << numeric.getSize() << std::endl;
102+
throw std::runtime_error("got integer of unexpected size");
103+
}
104+
case Typelib::Numeric::UInt: {
105+
switch (numeric.getSize()) {
106+
case sizeof(uint8_t): return static_cast<unsigned int>(*static_cast<uint8_t *>(value.getData()));
107+
case sizeof(uint16_t): return *static_cast<uint16_t*>(value.getData());
108+
case sizeof(uint32_t): return *static_cast<uint32_t*>(value.getData());
109+
case sizeof(uint64_t): return *static_cast<uint64_t*>(value.getData());
110+
default:
111+
std::cout << "Error, got integer of unexpected size " << numeric.getSize() << std::endl;
112+
throw std::runtime_error("got integer of unexpected size");
113+
}
114+
}
115+
case Typelib::Numeric::NumberOfValidCategories:
116+
default: throw std::runtime_error("Internal Error: Got invalid Category");
117+
}
118+
}
119+
return 0;
120+
121+
}
122+
123+
std::string TypeWrapper::numericToString() {
124+
if (value.getType().getCategory() == Typelib::Type::Category::Numeric) {
125+
if (value.getType().getName() == "/bool") {
126+
return (*static_cast<bool *>(value.getData())?"true":"false");
127+
}
128+
return std::to_string(toDouble());
129+
}
130+
return "";
131+
}
132+
133+
std::string TypeWrapper::containerToString() {
134+
const Typelib::Container& container = dynamic_cast<const Typelib::Container&>(value.getType());
135+
136+
if (container.getName() == "/std/string") {
137+
return *static_cast<const std::string *>(value.getData());
138+
}
139+
// this is a real container, will be represented by other typewrappers
140+
return "";
141+
}
142+
143+
144+
void TypeWrapper::printType(std::string ident) {
145+
std::cout << ident << this->value.getType().getName() << ": \t" << this->toString() << std::endl;
146+
ident = ident + " ";
147+
for (auto& entry : *this) {
148+
std::cout << ident << entry.first << "\t";
149+
entry.second->printType(ident);
150+
}
151+
}
152+
153+
} // namespace orocos_cpp

‎src/TypeWrapper.hpp

+95
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
#pragma once
2+
3+
#include <typelib/typemodel.hh>
4+
#include <typelib/value.hh>
5+
#include <map>
6+
#include <string>
7+
#include <memory>
8+
9+
namespace orocos_cpp {
10+
11+
12+
/**
13+
* @brief This wrapper gived convinoent access to the data of a typelib type without linking the actual type
14+
*
15+
* The constructor creates a map so that a call on e.g. /base/samples/Joints data linke thsi is possible
16+
* Typelib::Value joints;
17+
* TypeWrapper jointwrapper(joints);
18+
* TypeWrapper element = jointwrapper["elements"][0];
19+
* std::cout << element.toString() << std::endl;
20+
*
21+
* see main5.cpp for an example to get values from an unidentified port
22+
*
23+
*
24+
*/
25+
class TypeWrapper : public std::map<std::string, std::shared_ptr<TypeWrapper> > {
26+
public:
27+
TypeWrapper(Typelib::Value& value);
28+
29+
bool isValid() {
30+
return value.getData();
31+
}
32+
33+
/**
34+
* @brief prints the whole type introspection to the console
35+
*/
36+
void printType() {
37+
printType("");
38+
}
39+
40+
const Typelib::Value& getTypelibValue() {
41+
return value;
42+
}
43+
44+
std::string getTypelibTypeName() {
45+
return value.getType().getName();
46+
}
47+
48+
template<class TYPE> TYPE* getAs(const std::string& type_name) {
49+
if (value.getType().getName() == type_name) {
50+
return reinterpret_cast<TYPE*>(value.getData());
51+
}
52+
return nullptr;
53+
}
54+
55+
std::string toString();
56+
57+
double toDouble();
58+
59+
60+
// double toValue();
61+
62+
/**
63+
* @brief overload operator to skip the shared_ptr content in the map of the base class
64+
*/
65+
TypeWrapper& operator[](const std::string& key) {
66+
auto type = this->find(key);
67+
if (type != this->end()) {
68+
// std::shared_ptr<TypeWrapper> wrap = std::map<std::string, std::shared_ptr<TypeWrapper>>::operator[](key);
69+
return *(type->second);
70+
}
71+
throw(std::runtime_error(key + " is not a valid field of this type"));
72+
}
73+
74+
75+
protected:
76+
void printType(std::string ident);
77+
78+
private:
79+
80+
// void add(Typelib::Value& value);
81+
std::string numericToString();
82+
83+
std::string containerToString();
84+
85+
void addCompound();
86+
87+
void addContainer();
88+
89+
void addArray();
90+
91+
Typelib::Type::Category category;
92+
Typelib::Value value;
93+
94+
};
95+
} // namespace orocos_cpp

‎src/main5.cpp

+138
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
#include <memory>
2+
#include <rtt/typelib/TypelibMarshallerBase.hpp>
3+
#include <orocos_cpp/CorbaNameService.hpp>
4+
5+
#include <orocos_cpp_base/OrocosHelpers.hpp>
6+
#include "orocos_cpp.hpp"
7+
#include "NameService.hpp"
8+
#include "TypeWrapper.hpp"
9+
10+
using namespace orocos_cpp;
11+
12+
13+
RTT::base::InputPortInterface* createInputPort(RTT::TaskContext* task_context, RTT::types::TypeInfo const * type, ::std::string const & port_name) {
14+
std::string name = port_name + "_input";
15+
RTT::base::PortInterface *pi = task_context->getPort(port_name);
16+
if (pi) {
17+
// Port exists. Returns success.
18+
RTT::log(RTT::Info) << "Port " << port_name << " is already registered." << RTT::endlog();
19+
return 0;
20+
}
21+
/* Create port */
22+
RTT::base::InputPortInterface *new_port = type->inputPort(name);
23+
if (!new_port) {
24+
RTT::log(RTT::Error) << "An error occurred during port generation." << RTT::endlog();
25+
return NULL;
26+
}
27+
task_context->ports()->addEventPort(new_port->getName(), *(new_port) );
28+
return new_port;
29+
}
30+
31+
32+
33+
34+
int main(int argc, char **argv)
35+
{
36+
37+
std::unique_ptr<orocos_cpp::NameService> ns = std::make_unique<orocos_cpp::CorbaNameService>();
38+
39+
if (!ns->connect()) {
40+
std::cout << "Could not connect to Nameserver " << std::endl;
41+
return 0;
42+
}
43+
44+
orocos_cpp::OrocosCppConfig config;
45+
config.load_all_packages = false;
46+
config.load_typekits = true;
47+
config.package_initialization_whitelist = {"base", "base-types"};
48+
std::shared_ptr<orocos_cpp::OrocosCpp> orocos = std::make_shared<orocos_cpp::OrocosCpp>();
49+
orocos->initialize(config, false);
50+
51+
OrocosHelpers::initClientTask("main5");
52+
53+
RTT::TaskContext* localtask = OrocosHelpers::getClientTask();
54+
55+
std::map<std::string, RTT::base::InputPortInterface*> input_ports;
56+
57+
std::vector<std::string> tasks = ns->getRegisteredTasks();
58+
for (const std::string &tname : tasks) {
59+
RTT::TaskContext* tc = ns->getTaskContext(tname);
60+
if (tc) {
61+
for (auto& portname : tc->ports()->getPortNames()) {
62+
RTT::base::OutputPortInterface* portInterfacePtr = dynamic_cast<RTT::base::OutputPortInterface*>(tc->getPort(portname));
63+
if (portInterfacePtr) {
64+
std::string type = portInterfacePtr->getTypeInfo()->getTypeName();
65+
// if (type == "/base/samples/Joints") {
66+
// create local port the "/" is the identifier for subgroups
67+
std::string identifier = tname+"/"+portname;
68+
const RTT::types::TypeInfo* typeinfo = portInterfacePtr->getTypeInfo();
69+
RTT::base::InputPortInterface* input_port = createInputPort(localtask, typeinfo, identifier);
70+
input_ports[identifier] = input_port;
71+
// connect all ports
72+
portInterfacePtr->connectTo(input_port);
73+
// }
74+
}
75+
}
76+
}
77+
}
78+
79+
//while (true) {
80+
for (const auto& port : input_ports) {
81+
if (port.second != nullptr) {
82+
std::string identifier = port.first;
83+
84+
const RTT::types::TypeInfo* typeinfo = port.second->getTypeInfo();
85+
orogen_transports::TypelibMarshallerBase * transport = dynamic_cast<orogen_transports::TypelibMarshallerBase *>(typeinfo->getProtocol(orogen_transports::TYPELIB_MARSHALLER_ID));
86+
orogen_transports::TypelibMarshallerBase::Handle* transportHandle = transport->createSample();
87+
const Typelib::Registry& registry = transport->getRegistry();
88+
const Typelib::Type *typeptr = registry.get(transport->getMarshallingType());
89+
RTT::base::DataSourceBase::shared_ptr datasource = transport->getDataSource(transportHandle);
90+
91+
while (port.second->read(datasource) == RTT::NewData) {
92+
// convert the native, Orocos sample back to its marshallable and inspectable Typelib form
93+
transport->refreshTypelibSample(transportHandle);
94+
Typelib::Value val(transport->getTypelibSample(transportHandle), *(typeptr));
95+
96+
orocos_cpp::TypeWrapper wrap(val);
97+
wrap.printType();
98+
99+
if (wrap.getTypelibTypeName() == "/base/samples/joints") {
100+
std::cout << "printing subtype" << std::endl;
101+
TypeWrapper& element = wrap["elements"][0];
102+
std::cout << element.toString() << std::endl;
103+
}
104+
105+
106+
// example to get all numeric values
107+
std::shared_ptr<orocos_cpp::TypeWrapper> wrapptr = std::make_shared<orocos_cpp::TypeWrapper>(val);
108+
std::list<std::shared_ptr<orocos_cpp::TypeWrapper>> typelist;
109+
std::list<std::string> namelist;
110+
typelist.push_back(wrapptr);
111+
namelist.push_back(identifier);
112+
while (typelist.size()) {
113+
std::shared_ptr<orocos_cpp::TypeWrapper> current = typelist.front();
114+
std::string name = namelist.front();
115+
typelist.pop_front();
116+
namelist.pop_front();
117+
if (current->getTypelibValue().getType().getCategory() == Typelib::Type::Numeric) {
118+
// set value
119+
double data = current->toDouble();
120+
std::cout << name << ": " << data << std::endl;
121+
} else {
122+
// add other entries
123+
for (const auto& newentry : *current) {
124+
typelist.push_back(newentry.second);
125+
std::string newname = name + "/" + newentry.first;
126+
namelist.push_back(newname);
127+
}
128+
}
129+
}
130+
131+
}
132+
}
133+
}
134+
//}
135+
136+
137+
return 0;
138+
}

‎src/main6.cpp

+197
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,197 @@
1+
#include <memory>
2+
#include <rtt/typelib/TypelibMarshallerBase.hpp>
3+
#include <orocos_cpp/CorbaNameService.hpp>
4+
#include <stdlib.h>
5+
6+
#include <orocos_cpp_base/OrocosHelpers.hpp>
7+
#include "orocos_cpp.hpp"
8+
#include "NameService.hpp"
9+
#include <lib_config/Configuration.hpp>
10+
#include <lib_config/TypelibConfiguration.hpp>
11+
12+
using namespace orocos_cpp;
13+
14+
15+
RTT::base::InputPortInterface* createInputPort(RTT::TaskContext* task_context, RTT::types::TypeInfo const * type, ::std::string const & port_name) {
16+
std::string name = port_name + "_input";
17+
RTT::base::PortInterface *pi = task_context->getPort(port_name);
18+
if (pi) {
19+
// Port exists. Returns success.
20+
RTT::log(RTT::Info) << "Port " << port_name << " is already registered." << RTT::endlog();
21+
return 0;
22+
}
23+
/* Create port */
24+
RTT::base::InputPortInterface *new_port = type->inputPort(name);
25+
if (!new_port) {
26+
RTT::log(RTT::Error) << "An error occurred during port generation." << RTT::endlog();
27+
return NULL;
28+
}
29+
task_context->ports()->addEventPort(new_port->getName(), *(new_port) );
30+
return new_port;
31+
}
32+
33+
bool is_number(const std::string& s)
34+
{
35+
return !s.empty() && std::find_if(s.begin(),
36+
s.end(), [](unsigned char c) { return !std::isdigit(c); }) == s.end();
37+
}
38+
39+
40+
std::shared_ptr<libConfig::ConfigValue> extract_field(const std::shared_ptr<libConfig::ConfigValue> data, const std::vector<std::string>& path)
41+
{
42+
//No path specified --> return whole type
43+
if(path.size() == 0)
44+
return data;
45+
46+
std::shared_ptr<libConfig::ConfigValue> parent = data;
47+
std::string prev_field = "";
48+
for(const std::string& field : path){
49+
if(field != ""){
50+
if(is_number(field)){
51+
std::shared_ptr<libConfig::ArrayConfigValue> aparent = std::dynamic_pointer_cast<libConfig::ArrayConfigValue>(parent);
52+
if(!aparent)
53+
throw std::runtime_error("Tried to access element index "+field+" of data "+ parent->getCxxTypeName()+", but data is not an array.");
54+
55+
int idx = std::stoi(field);
56+
if(idx < 0){
57+
idx = aparent->getValues().size()-idx;
58+
}
59+
60+
if((int) aparent->getValues().size() <= idx){
61+
std::cout << "WARNING: Trying to access index "+std::to_string(idx)+" of field "+prev_field+", but the field has only the size of "+std::to_string(aparent->getValues().size());
62+
throw std::runtime_error("Invalid field access");
63+
}
64+
parent = aparent->getValues().at(idx);
65+
66+
}else{
67+
std::shared_ptr<libConfig::ComplexConfigValue> cparent = std::dynamic_pointer_cast<libConfig::ComplexConfigValue>(parent);
68+
if(!cparent)
69+
throw std::runtime_error("Tried to access field "+field+" of data "+ parent->getCxxTypeName()+", but data is not a complex structure.");
70+
parent = cparent->getValues().at(field);
71+
}
72+
}
73+
prev_field = field;
74+
}
75+
return parent;
76+
}
77+
78+
79+
80+
int main(int argc, char **argv)
81+
{
82+
83+
std::unique_ptr<orocos_cpp::NameService> ns = std::make_unique<orocos_cpp::CorbaNameService>();
84+
85+
if (!ns->connect()) {
86+
std::cout << "Could not connect to Nameserver " << std::endl;
87+
return 0;
88+
}
89+
90+
orocos_cpp::OrocosCppConfig config;
91+
config.load_all_packages = false;
92+
config.load_typekits = true;
93+
config.package_initialization_whitelist = {"base", "base-types"};
94+
std::shared_ptr<orocos_cpp::OrocosCpp> orocos = std::make_shared<orocos_cpp::OrocosCpp>();
95+
orocos->initialize(config, false);
96+
97+
RTT::TaskContext* localtask = new RTT::TaskContext("dummy");
98+
RTT::DataFlowInterface df;
99+
100+
std::map<std::string, RTT::base::InputPortInterface*> input_ports;
101+
102+
std::vector<std::string> tasks = ns->getRegisteredTasks();
103+
for (const std::string &tname : tasks) {
104+
RTT::TaskContext* tc = ns->getTaskContext(tname);
105+
if (tc) {
106+
for (auto& portname : tc->ports()->getPortNames()) {
107+
RTT::base::OutputPortInterface* portInterfacePtr = dynamic_cast<RTT::base::OutputPortInterface*>(tc->getPort(portname));
108+
if (portInterfacePtr) {
109+
std::string type = portInterfacePtr->getTypeInfo()->getTypeName();
110+
// if (type == "/base/samples/Joints") {
111+
// create local port the "/" is the identifier for subgroups
112+
std::string identifier = tname+"/"+portname;
113+
RTT::base::InputPortInterface* input_port = dynamic_cast<RTT::base::InputPortInterface *>(portInterfacePtr->antiClone());
114+
df.addPort(identifier+"-reader", *input_port);
115+
input_ports[identifier] = input_port;
116+
// connect all ports
117+
portInterfacePtr->connectTo(input_port, RTT::ConnPolicy::data());
118+
// }
119+
}
120+
}
121+
}
122+
}
123+
124+
//while (true) {
125+
for (const auto& port : input_ports) {
126+
if (port.second != nullptr) {
127+
std::string identifier = port.first;
128+
129+
const RTT::types::TypeInfo* typeinfo = port.second->getTypeInfo();
130+
orogen_transports::TypelibMarshallerBase * transport = dynamic_cast<orogen_transports::TypelibMarshallerBase *>(typeinfo->getProtocol(orogen_transports::TYPELIB_MARSHALLER_ID));
131+
orogen_transports::TypelibMarshallerBase::Handle* transportHandle = transport->createSample();
132+
const Typelib::Registry& registry = transport->getRegistry();
133+
const Typelib::Type *typeptr = registry.get(transport->getMarshallingType());
134+
RTT::base::DataSourceBase::shared_ptr datasource = transport->getDataSource(transportHandle);
135+
136+
while (port.second->read(datasource) == RTT::NewData) {
137+
// convert the native, Orocos sample back to its marshallable and inspectable Typelib form
138+
transport->refreshTypelibSample(transportHandle);
139+
Typelib::Value val(transport->getTypelibSample(transportHandle), *(typeptr));
140+
141+
//orocos_cpp::TypeWrapper wrap(val);
142+
libConfig::TypelibConfiguration tlconf;
143+
std::shared_ptr<libConfig::ConfigValue> sample;
144+
std::shared_ptr<libConfig::ConfigValue> field;
145+
sample = tlconf.getFromValue(val);
146+
147+
//wrap.printType();
148+
sample->print(std::cout);
149+
150+
if (sample->getName() == "/base/samples/joints") {
151+
std::cout << "printing subtype" << std::endl;
152+
field = extract_field(sample, {"elements", 0});
153+
field->print(std::cout);
154+
155+
}
156+
157+
158+
// example to get all numeric values
159+
std::shared_ptr<libConfig::ConfigValue> wrapptr = tlconf.getFromValue(val);
160+
std::list<std::shared_ptr<libConfig::ConfigValue>> typelist;
161+
std::list<std::string> namelist;
162+
typelist.push_back(wrapptr);
163+
namelist.push_back(identifier);
164+
while (typelist.size()) {
165+
std::shared_ptr<libConfig::ConfigValue> current = typelist.front();
166+
std::string name = namelist.front();
167+
typelist.pop_front();
168+
if (current->getType() == libConfig::ConfigValue::Type::SIMPLE) {
169+
// set value
170+
std::shared_ptr<libConfig::SimpleConfigValue> val = std::dynamic_pointer_cast<libConfig::SimpleConfigValue>(current);
171+
double data = atof(val->getValue().c_str());
172+
std::cout << name << ": " << data << std::endl;
173+
} else {
174+
// add other entries
175+
if (current->getType() == libConfig::ConfigValue::Type::ARRAY){
176+
std::shared_ptr<libConfig::ArrayConfigValue> val = std::dynamic_pointer_cast<libConfig::ArrayConfigValue>(current);
177+
typelist.insert(typelist.end(), val->getValues().begin(), val->getValues().end());
178+
}
179+
if (current->getType() == libConfig::ConfigValue::Type::COMPLEX){
180+
std::shared_ptr<libConfig::ComplexConfigValue> val = std::dynamic_pointer_cast<libConfig::ComplexConfigValue>(current);
181+
for( const auto& [key, value] : val->getValues()){
182+
typelist.push_back(value);
183+
std::string newname = name + "/" + key;
184+
namelist.push_back(newname);
185+
}
186+
}
187+
}
188+
}
189+
190+
}
191+
}
192+
}
193+
//}
194+
195+
196+
return 0;
197+
}

0 commit comments

Comments
 (0)
Please sign in to comment.