Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Populating the toml table as required by the user #157

Open
ravipathuri opened this issue Apr 14, 2021 · 5 comments
Open

Populating the toml table as required by the user #157

ravipathuri opened this issue Apr 14, 2021 · 5 comments

Comments

@ravipathuri
Copy link

ravipathuri commented Apr 14, 2021

Hello
I currently use v3.6.0 version of the tomll11 header only library. The parsing part work as expected. But i see few issues w.r.t populating the toml table content in the order as required by the user.
This is a demo program
#include "toml.hpp" // that's all! now you can use it.
#include
#include
#include
int main()
{
toml::value data{{"foo", 42}, {"bar", 3.14}, {"baz", "qux"}};
data["hoge"] = "piyo";
std::stringstream ss;
ss << std::setw(0) << data;
std::cout<<"Actual toml content\n"<<ss.str();
return 0;
}
The output is
Actual toml content
hoge = "piyo"
baz = "qux"
foo = 42
bar = 3.14

It should have been
Actual toml content
hoge = "piyo"
baz = "qux"
bar = 3.14
foo = 42

Any reason for this behaviour?
over-riding the type the std::map will just place the keys in alphabetical order(sorted manner). But in my case i want the key value pairs to be in the order as they are passed. How can we achieve this?
Please give your inputs

@ravipathuri ravipathuri changed the title Populating the toml table as requrired by the user Populating the toml table as required by the user Apr 14, 2021
@ToruNiina
Copy link
Owner

Hi,

In toml11, the underlying map type is responsible for the order of key-value pairs. By default, it uses std::unordered_map that is essentially does not preserve the order because it uses hash value, so it is the reason why the serialization result changes the order (note that the TOML spec says that it is designed to map to a hash table.)

To keep the order of the key-value pairs in a table, you need to use order-preserving map class, like https://github.com/Tessil/ordered-map. This map class keeps the insertion order. So,

#include "toml.hpp"
#include "tsl/ordered_map.h"
#include <iostream>

int main()
{
    using value_type = toml::basic_value<toml::preserve_comments, tsl::ordered_map>;
    value_type v;
    v["hoge"] = "piyo";
    v["baz"]  = "qux";
    v["bar"]  = 3.14;
    v["foo"]  = 42;

    std::cout << v << std::endl;
    // hoge = "piyo"
    // baz = "qux"
    // bar = 3.14
    // foo = 42
    //
    return 0;
}

You can also parse a file keeping the order of key-value pairs in the following way.

#include "toml.hpp"
#include "tsl/ordered_map.h"
#include <iostream>

int main()
{
    auto data = toml::parse<toml::preserve_comments, tsl::ordered_map>("issue157.toml");
    data["hoge"] = "piyo";
    std::cout << data << std::endl;
    return 0;
}

Note that, by doing this, the hoge key is assigned to the table as the last element.

@ravipathuri
Copy link
Author

Thanks for the suggestion :) .
This works when a simple application using g++ (on ubuntu) is built and tested.
But when I try to incorporate the above logic in my application(QNX) using the alias
using tomlTableType = toml::basic_value<toml::preserve_comments, tsl::ordered_map>;
I get the below error
error: no type named 'value_type' in 'struct std::__1::allocator_traits<std::__1::allocator<std::__1::pair<std::__1::basic_string<char, std::__1::char_traits, std::__1::allocator >, toml::basic_value<toml::preserve_comments, tsl::ordered_map> > > >::rebind_alloc<tsl::detail_ordered_hash::bucket_entry >'
typedef typename __pointer_type<value_type, allocator_type>::type pointer;

error: no type named 'value_type' in 'struct std::__1::allocator_traits<std::__1::allocator<std::__1::pair<std::__1::basic_string<char, std::__1::char_traits, std::__1::allocator >, toml::basic_value<toml::preserve_comments, tsl::ordered_map> > > >::rebind_alloc<tsl::detail_ordered_hash::bucket_entry >'
typedef typename __const_pointer<value_type, pointer, allocator_type>::type const_pointer;

I am not sure if it is a general issue. Can you please suggest on how i can resolve this

@ToruNiina
Copy link
Owner

The following code does not reproduce the error you reported. I compiled with g++-10 -std=c++11 issue157.cpp -Wall -Wextra -Wpedantic -O2. And I don't know if I can do anything about a problem.

#include "toml.hpp"
#include "ordered-map/include/tsl/ordered_map.h"
#include <iostream>

int main(int argc, char** argv)
{
    using tomlTableType = toml::basic_value<toml::preserve_comments, tsl::ordered_map>;

    tomlTableType t;
    t["foo"] = "bar";

    return 0;
}

I think the error may be caused by the inclusion or definition order. You can try several patterns.

@monkeydom
Copy link

To chime in: I do think it is nice to have some sort of canonical output that is always the same for the same input (for many cases, versioning etc.). So e.g. making all tables have a defined alphabetical order would be a great define to have as behavior (or as output stream option like precision/inline tables)

@NaturalUser
Copy link

#include "toml.hpp"
#include "tsl/ordered_map.h"
#include

int main()
{
using value_type = toml::basic_value<toml::preserve_comments, tsl::ordered_map>;
value_type v;
v["hoge"] = "piyo";
v["baz"] = "qux";
v["bar"] = 3.14;
v["foo"] = 42;

//hello, with the similar question
//value_type& v = toml::find<toml::table>(data, testTable);  this has error, so how to get the reference to the table?
//v[]="";

}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants