Hello i'v the following function that exports a single instance of a struct :
struct UserIdentity
{
std::string name;
int id;
};
std::map<std::string, int> g_UserIdentities = { { "Bob", 100 }, { "Jone", 101 },
{ "Alice", 102 }, { "Doe", 103 } };
/*
* Will be used in a DLL that will export UserIdentity struct
* OUT _UserIdentity
*/
void Ui_export(UserIdentity *_UserIdentity)
{
for (auto& t : g_UserIdentities)
{
_UserIdentity->name = t.first;
_UserIdentity->id = t.second;
}
}
So please how could i export an array of _UserIdentity instead of a single instance in my function
void Ui_export(UserIdentity *_UserIdentity)
thank you .
Related
I'm trying to implement json serialization of a class using eigen::VectorXd and nlohmann-json library. It's not a problem to store the class as JSON string. How to parse VectorXd from JSON? Is there an other library more suitable for this task?
#include "json.hpp"
class TransformationStep {
public:
VectorXd support_vector;
int number;
TransformationStep(int number_param, VectorXd support_vectorParam) {
number = number_param;
support_vector = support_vectorParam;
}
~TransformationStep() {
}
//json serialization
void to_json(nlohmann::json &j);
void from_json(const nlohmann::json &j);
};
void TransformationStep::to_json(nlohmann::json &j) {
j["number"] = number;
j["support_vector"] = support_vector;
}
void Ftf::from_json(const nlohmann::json &j)
{
number = (j.at("number").get<int>());
//support_vector = j["support_vector"].get<VectorXd>()); //???
}
------ output calling to_json(nlohmann::json &j) ------
{
"number": 3,
"support_vector": [
-0.00036705693279489064,
0.020505439899631835,
0.3531380358938106,
0.0017673029092790872,
-0.9333248513057808,
0.04670404618976708,
-0.21905858722244081,
-1.011945322347849,
-0.09172040021815037,
0.008526811888809391,
0.05187648010664058
]
}
I came up with
void vector_from_json(VectorXd& vector, const nlohmann::json &j) {
vector.resize(j.size());
size_t element_index=0;
for (const auto& element : j) {
vector(element_index++) = (double) element;
}
}
I have the following code:
struct MyArrayEntry
{
int type;
int id;
};
template<size_t arraySize>
struct MyArray
{
template<typename T, typename... Types>
MyArray(T t, Types... ts) : data{ { t, ts... } } {}
int dataSize = arraySize;
MyArrayEntry data[arraySize];
};
void Blah()
{
static MyArray<3> kTest
(
{ 1, 4 },
{ 2, 5 },
{ 3, 6 }
);
}
But this fails to build with:
error C2661: 'MyArray<3>::MyArray': no overloaded function takes 3
arguments
What am I doing wrong here?
With the imformation you provide, I would suggest using a std::initializer_list and an std::copy call:
template<size_t arraySize>
struct MyArray
{
const int dataSize = arraySize; // Could as well make it constant
MyArrayEntry data[arraySize];
MyArray(std::initializer_list<MyArrayEntry> elements)
{
std::copy(begin(elements), end(elements), std::begin(data));
}
};
Create as
MyArray<3> kTest({ { 1, 4 }, { 2, 5 }, { 3, 6 } });
Sure it's an extra pair of curly-brackets {}, but it will make your code simpler.
With my tree looking like this:
{
"Library":
{
"L_ID": "1",
"Book":
{
"B_ID": "1",
"Title": "Moby Dick"
},
"Book":
{
"B_ID": "2",
"Title": "Jurassic Park"
}
},
"Library":
{
"L_ID": "2",
"Book":
{
"B_ID": "1",
"Title": "Velocity"
},
"Book":
{
"B_ID": "2",
"Title": "Creeper"
}
}
}
What i am looking to do is iterate through the libraries. When i find the L_ID that i am looking for, iterate through the books until i find the B_ID i'm looking for. At that point, i'd like to access all the leaves in that section.
I.e. looking for library 2, book 1, title
Note: There's likely a better way than this.
boost::property_tree::ptree libraries = config_.get_child("Library");
for (const auto &lib : libraries)
{
if (lib.second.get<uint16_6>("L_ID") == 2)
{
//at this point, i know i'm the correct library...
boost::property_tree::ptree books = lib.get_child("Book");
for (const auto &book : books)
{
if (book.second.get<uint16_t>("B_ID") == 1)
{
std::string mybook = book.second.get<std::string>("Title");
}
}
}
I fail out as soon as i try looking into my first sub tree. What's going wrong here??
For starters, the "JSON" is wildly flawed. At least fix the missing quotes and commas:
{
"Library": {
"L_ID": "1",
"Book": {
"B_ID": "1",
"Title": "Moby Dick"
},
"Book": {
"B_ID": "2",
"Title": "Jurassic Park"
}
},
"Library": {
"L_ID": "2",
"Book": {
"B_ID": "1",
"Title": "Velocity"
},
"Book": {
"B_ID": "2",
"Title": "Creeper"
}
}
}
Next up, you seem to be confused. get_child("Library") gets the first child by that name, not a node containing child nodes called "Library" (that would be the root node, by the way).
May I suggest adding some abstraction, and perhaps some facilities to query by some names/properties:
int main() {
Config cfg;
{
std::ifstream ifs("input.txt");
read_json(ifs, cfg.data_);
}
std::cout << "Book title: " << cfg.library(2).book(1).title() << "\n";
}
As you can see, we assume a Config type that can find a library:
Library library(Id id) const {
for (const auto& lib : libraries())
if (lib.id() == id) return lib;
throw std::out_of_range("library");
}
What is libraries()? We'll delve into it deeper, but lets just look at it for a second:
auto libraries() const {
using namespace PtreeTools;
return data_ | named("Library") | having("L_ID") | as<Library>();
}
That magic should be read as "give me all nodes that are named Library, which have a L_ID property but wrap them in a Library object". Skipping on the detail for now, lets look at the Library object, which apparently knows about books():
struct Library {
ptree const& data_;
Id id() const { return data_.get<Id>("L_ID"); }
auto books() const {
using namespace PtreeTools;
return data_ | named("Book") | having("B_ID") | as<Book>();
}
Book book(Id id) const {
for (const auto& book : books())
if (book.id() == id) return book;
throw std::out_of_range("book");
}
};
We see the same pattern in books() and book(id) to find a specific item.
The Magic
The magic uses Boost Range adaptors and lurks in PtreeTools:
namespace PtreeTools {
namespace detail {
// ...
}
auto named(std::string const& name) {
return detail::filtered(detail::KeyName{name});
}
auto having(std::string const& name) {
return detail::filtered(detail::HaveProperty{name});
}
template <typename T>
auto as() {
return detail::transformed(detail::As<T>{});
}
}
That's deceptively simple, right. That's because we're standing on the shoulders of Boost Range:
namespace detail {
using boost::adaptors::filtered;
using boost::adaptors::transformed;
Next, we only define the predicates that know how to filter for a specific ptree node:
using Value = ptree::value_type;
struct KeyName {
std::string const _target;
bool operator()(Value const& v) const {
return v.first == _target;
}
};
struct HaveProperty {
std::string const _target;
bool operator()(Value const& v) const {
return v.second.get_optional<std::string>(_target).is_initialized();
}
};
And one transformation to project to our wrapper objects:
template <typename T>
struct As {
T operator()(Value const& v) const {
return T { v.second };
}
};
}
Full Live Demo
Live On Coliru
#include <boost/property_tree/json_parser.hpp>
#include <boost/range/adaptors.hpp>
using boost::property_tree::ptree;
namespace PtreeTools {
namespace detail {
using boost::adaptors::filtered;
using boost::adaptors::transformed;
using Value = ptree::value_type;
struct KeyName {
std::string const _target;
bool operator()(Value const& v) const {
return v.first == _target;
}
};
struct HaveProperty {
std::string const _target;
bool operator()(Value const& v) const {
return v.second.get_optional<std::string>(_target).is_initialized();
}
};
template <typename T>
struct As {
T operator()(Value const& v) const {
return T { v.second };
}
};
}
auto named(std::string const& name) {
return detail::filtered(detail::KeyName{name});
}
auto having(std::string const& name) {
return detail::filtered(detail::HaveProperty{name});
}
template <typename T>
auto as() {
return detail::transformed(detail::As<T>{});
}
}
struct Config {
ptree data_;
using Id = uint16_t;
struct Book {
ptree const& data_;
Id id() const { return data_.get<Id>("B_ID"); }
std::string title() const { return data_.get<std::string>("Title"); }
};
struct Library {
ptree const& data_;
Id id() const { return data_.get<Id>("L_ID"); }
auto books() const {
using namespace PtreeTools;
return data_ | named("Book") | having("B_ID") | as<Book>();
}
Book book(Id id) const {
for (const auto& book : books())
if (book.id() == id) return book;
throw std::out_of_range("book");
}
};
auto libraries() const {
using namespace PtreeTools;
return data_ | named("Library") | having("L_ID") | as<Library>();
}
Library library(Id id) const {
for (const auto& lib : libraries())
if (lib.id() == id) return lib;
throw std::out_of_range("library");
}
};
#include <iostream>
int main() {
Config cfg;
{
std::ifstream ifs("input.txt");
read_json(ifs, cfg.data_);
}
std::cout << "Book title: " << cfg.library(2).book(1).title() << "\n";
}
Prints:
Book title: Velocity
#Sehe fixed your JSON to be syntactically correct, but I think it would make sense to go a bit further than that. Given the data you're representing, it would make a great deal more sense to have an array of libraries, each of which contains an array of books, giving data something like this:
{
"Libraries": [
{
"L_ID": 1,
"Books": [
{
"B_ID": 1,
"Title": "Moby Dick"
},
{
"B_ID": 2,
"Title": "Jurassic Park"
}
]
},
{
"L_ID": 2,
"Books": [
{
"B_ID": 1,
"Title": "Velocity"
},
{
"B_ID": 2,
"Title": "Creeper"
}
]
}
]
}
Then, if at all possible, I'd choose a library that's actually suited to the job at hand. Boost property tree isn't really intended as a general-purpose JSON library. You can push it into that role if you really insist, but at least for what you've outlined in the question, it puts you through quite a bit of extra work to get what you want.
Personally, I'd probably use nlohmann's JSON library instead. Using it, we can proceed a little more directly to a solution. Basically, once it's parsed a JSON file, we can treat the result a great deal like we would normal collections from the standard library--we can use all the normal algorithms, range-based for loops, and so on. So, we can load a JSON file something like:
using json=nlohmann::json;
std::ifstream in("libraries.json");
json lib_data;
in >> lib_data;
Then we can look through the libraries for a particular ID number with code something like this:
for (auto const &lib : libs["Libraries"])
if (lib["L_ID"] == lib_num)
// we've found the library we want
Looking for a particular book is nearly identical:
for (auto const &book : lib["Books"])
if (book["B_ID"] == book_num)
// we've found the book we want
From there, printing out the title looks something like: std::cout << book["Title"];
Putting those together, we could end up with code something like this:
#include "json.hpp"
#include <fstream>
#include <iostream>
using json = nlohmann::json;
std::string find_title(json lib_data, int lib_num, int book_num) {
for (auto const &lib : lib_data["Libraries"])
if (lib["L_ID"] == lib_num)
for (auto const &book : lib["Books"])
if (book["B_ID"] == book_num)
return book["Title"];
return "";
}
int main() {
std::ifstream in("libraries.json");
json lib_data;
in >> lib_data;
std::cout << find_title(lib_data, 1, 2);
}
If you really want to convert each JSON object into a C++ object, you can do that fairly easily as well. It would look something like this:
namespace library_stuff {
struct Book {
int B_ID;
std::string title;
};
void from_json(json &j, Book &b) {
b.B_ID = j["B_ID"];
b.title = j["Title"];
}
}
So there are two points here: you must name the function from_json, and it must be defined in the same namespace as the struct/class it's associated with. With this bit of scaffolding in place, we can convert from JSON to struct with a simple assignment, something like this:
book b = lib_data["Libraries"][0]["Books"][1];
I'd consider it highly questionable whether that's really useful in this particular case though.
My C++11 is too weak to find a solution. I have lot of std::vector<std::pair<const char *, int>> variables in my project and therefore the code to check if an entry does exist repeats:
std::vector<std::pair<const char *, RunningProgramMode>> vProgramMode =
{
{ "server", RunningProgramModeServer },
{ "shell", RunningProgramModeShell },
{ "client", RunningProgramModeClient },
};
// the following code repeats for each variable
for ( auto const &it : vProgramMode )
{
if ( !strcmp(sParameter, it.first) )
{
programParameters->requestedProgramMode = it.second;
}
}
Of course I can write a function [which receives std::vector<std::pair<..>> as parameter] which iterates through the vector but I think it would be more elegant when I can extend the std::vector template with my find_member() function which checks with !strcmp(sParameter, it.first) if the vector has the requested entry and returns then .second value.
Something like this:
std::my_vector<std::pair<const char *, RunningProgramMode>> vProgramMode =
{
{ "server", RunningProgramModeServer },
{ "shell", RunningProgramModeShell },
{ "client", RunningProgramModeClient },
};
result = vProgramMode.find_member("shell");
For the moment there is no need to check if the value does exist. I want to keep the example simple and focus on the problem.
My solution:
template<typename T>
class MyVectorForPair
{
private:
std::vector<std::pair<const char *, T>> classObject;
public:
MyVectorForPair(std::vector<std::pair<const char *, T>> initVector)
{ classObject = initVector; }
auto find_member(const char * sMember, T defaultReturn) -> T;
};
template<typename T>
auto MyVectorForPair<T>::find_member(const char * sMember, T defaultReturn) -> T
{
for ( auto const &it : classObject )
{
if ( !strcmp(sMember, it.first) )
{
return it.second;
}
}
return defaultReturn;
}
I can use it then like this - now it is general:
MyVectorForPair<RunningProgramMode> vProgramMode
(
{
{ "server", RunningProgramModeServer },
{ "shell", RunningProgramModeShell },
{ "client", RunningProgramModeClient },
}
);
RunningProgramMode result;
result = vProgramMode.find_member(sParameter, RunningProgramModeNotSelected));
Is it possible to embed a structure of varying type inside another structure in C?
Basically I want to do something like this.
struct A { int n; void *config; }
struct AConfig { int a; char *b; }
struct BConfig { int a; float b; }
const struct A table[] = {
{ 103, (void*)(struct AConfig){ 1932, "hello" } },
{ 438, (void*)(struct BConfig){ 14829, 33.4f } }
}
Is this possible in C or do I have to define the structures separately?
No, it doesn't work like that. You need explicit storage for each structure:
struct A { int n; void *config; };
struct AConfig { int a; char *b; };
struct BConfig { int a; float b; };
struct AConfig ac = { 1932, "hello" };
struct BConfig bc = { 14829, 33.4f };
const struct A table[] = {
{ 103, &ac },
{ 438, &bc }
};
Edit:
Another possibility is to utilize a union and C99 (-std=c99) named initializers:
enum config_type { CT_INT, CT_FLOAT, CT_STRING };
union config_value {
int int_value;
float float_value;
const char* string_value;
};
struct config {
enum config_type ctype;
union config_value cvalue;
};
struct config sys_config[] = {
{ CT_INT, { .int_value = 12 }},
{ CT_FLOAT, { .float_value = 3.14f }},
{ CT_STRING, { .string_value = "humppa" }}};
void print_config( const struct config* cfg ) {
switch ( cfg->ctype ) {
case CT_INT:
printf( "%d\n", cfg->cvalue.int_value ); break;
case CT_FLOAT:
printf( "%f\n", cfg->cvalue.float_value ); break;
case CT_STRING:
printf( "%s\n", cfg->cvalue.string_value ); break;
default:
printf( "unknown config type\n" );
}
}
You can use a union:
struct AConfig { int a; char *b; };
struct BConfig { int a; float b; };
struct A {
int n;
union {
struct AConfig a;
struct BConfig b;
};
};
Note that a and b are in the exact same space in memory. So if you are going to use the A.a you should not use A.b and vice versa.
Since this is an anonymous union, you can reference both a and b as if they were direct fields of struct A:
struct A sa;
sa.n = 3;
sa.b.a = 4;
sa.b.b = 3.14;
It would work if BConfig had a float pointer to b.
By the way, maybe you need to refactor your code to fit to C syntax.
#include <stdio.h>
#include <stdlib.h>
typedef struct { int n; void *config; } Config;
typedef struct { int a; char *b; } AConfig;
typedef struct { int a; float *b; } BConfig;
int main(void) {
AConfig A;
BConfig B;
A.a= 103;
A.b= "hello";
B.a= 438;
B.b=(float *) malloc (sizeof(float));
*(B.b)= 33.4f;
const Config table[] = {
{ A.a, (void *) A.b },
{ B.a, (void *) B.b }
};
printf("Hi\n");
return 0;
}
You may prefer a union. My union syntax is a little rusty, but something like this:
union config { char* c; float d; };
struct A {int n; int a; union config b;};
const struct A table[] = {
{103, 1932, { .c = "hello" } },
{14829, 438, { .d = 33.4f } }
};
You need C99 for the designated initalizer (the .c or .d in the table), and obviously some way to tell if you're accessing a char* or a float, but I assume you have that covered somewhere else.