mayah / tinytoml

A header only C++11 library for parsing TOML
BSD 2-Clause "Simplified" License
167 stars 31 forks source link

Write inline tables? #11

Open RobertBColton opened 8 years ago

RobertBColton commented 8 years ago

Using tinytoml to write a toml document, I am wondering if it is possible to specify that a nested table should be inline? Tinytoml has absolutely no problem reading inline tables, but in the following example it would be desirable to have it write size = { width = 800, height = 600 }

std::ofstream ofs(path);
toml::Table root;

toml::Table sceneValue = toml::Table();
sceneValue["name"] = scene.name;
// would be nice to have this table written inline
toml::Table sizeValue = toml::Table();
sizeValue["width"] = scene.width;
sizeValue["height"] = scene.height;
sceneValue["size"] = sizeValue;
root["scene"] = sceneValue;

ofs << root;
ofs.close();

So the desired output is:

[scene]
name = "Main Menu"
size = { width = 800, height = 600 }
mayah commented 8 years ago

toml::Value does not have any flag that the table is inline or not. After parsing toml file, we don't have any way to distinguish inline table or usual table. We might be able to have a new value type (INLINE_TABLE) or add a flag to specify the table is inline in toml::Value, though. This will require some work.

Anyway, how should we specify the table is inline? Unfortunately toml::Table is std::map<std::string, toml::Value>, so we cannot have flag for this. We might be able to add setInlineTable() in toml::Value. However, in this case, the API won't be intuitive so much. (If you can come up with a good API, please tell me.)

Excuse: As of toml v0.2, there was no inline table, and write() method was written when the toml version was v0.2. So probably we have more issues for writing a toml value.

RobertBColton commented 8 years ago

I was thinking about this some today and I knew why it's difficult before posting. Our scene reader is actually doing just fine reading the saved toml file, which is "semantically" correct. So don't beat yourself up too much, tinytoml rocks! Another idea to consider would also be creating a toml::InlineTable that simply wraps the toml::Table type. But I think the way you mention of adding setInline(bool) is better.

Going back to the official spec though, inline tables should not have line breaks in them, and it says if you feel that urge you should just use a regular table. From that I got the idea that possibly tinytoml could just automatically wrap the contents to a user specified (initialized to a default, say 100 characters) number of characters for each line and insert newlines. So if the outputted table would go past that limit, tinytoml would automatically write it as a normal table instead of an inline table. However, it would probably have to be another parameter to write() which I could do not get working because I am using ofstream instead of ostream. Only the << operator worked for me with an ofstream.

Also, from our actual scene file which we manually created, we format it like this:

[[scene.entity]]
position = { x = 100.0, y = 250.0 }

And currently it writes as:

[[scene.entity]]

[scene.entity.position]
x = 100.000000
y = 250.000000

So it would also be nice if the solution made it simply position instead of scene.entity.position as well. I will keep thinking if I can come up with a better solution and post back.

RobertBColton commented 7 years ago

After #15 I now get the following:

[scene]
name = "scene"

[scene.size]
height = 600
width = 800

I still think additional formatting options would be nice.