Search code examples
c++toml

toml11 weird serialization of file path string


I have a desktop app where I am reading and writing configuration from a toml file.

I have a preferences dialog where a user can toggle the options of the configuration. One of the options stores a directory. Once a user clicks 'OK', I save the options they selected and persist them to the toml file. The particular issue affects how the toml11 library serializes strings that are file/directory paths.

I have created a MRE that reproduces the issue

#include <iostream>
#include <toml.hpp>
#include <string>
#include <Windows.h>
#include <locale>
#include <codecvt>

int main()
{
    TCHAR path[MAX_PATH];
    GetModuleFileName(NULL, path, ARRAYSIZE(path));
    std::wstring exePath(path);
    std::wcout << exePath << " \n";

    using convert_type = std::codecvt_utf8<TCHAR>;
    std::wstring_convert<convert_type, TCHAR> converter;
    std::string sExePath = converter.to_bytes(exePath);

    auto parsedData = toml::parse("sample.toml");
    auto& parsedExePath = toml::find<std::string>(parsedData, "exePath");
    std::cout << parsedExePath << " \n";

    const toml::value data{ { {"exePath", sExePath} } };

    const std::string configString = toml::format(data);

    std::cout << configString << " \n";

    return 0;
}

The output of this is:

C:\Users\segmentation_fault\source\repos\Toml11FilePathsMre\x64\Debug\Toml11FilePathsMre.exe
C:\Development\cpp
exePath = """
C:\\Users\\segmentation_fault\\source\\repos\\Toml11FilePathsMre\\x64\\Deb\
ug\\Toml11FilePathsMre.exe\
"""


C:\Users\segmentation_fault\source\repos\Toml11FilePathsMre\x64\Debug\Toml11FilePathsMre.exe (process 13700) exited with code 0.

What I expect:

exePath = "C:\\Users\\segmentation_fault\\source\\repos\\Toml11FilePathsMre\\x64\\Debug\\Toml11FilePathsMre.exe"

This seems to only affect string that are file/directory paths. A random as long string serializes fine with toml. Parsing and reading a directory path is fine. This only happens with serialization. I don't see anything special with regards to serializing strings that are paths

I have a feeling I am doing something wrong, this doesn't seem like a bug with toml11 and I can't see what I might be doing wrong...


Solution

  • I have resolved the issue. According to author here, toml11's serializer will use a multi-line version if a (fuzzy) threshold is reached.

    You can change the max width by specifying a parameter when serializing your data:

    const std::string configString = toml::format(data, 200);
    

    Which gives me the, correct, following output:

    exePath = "C:\\Users\\segmentation_fault\\source\\repos\\Toml11FilePathsMre\\x64\\Debug\\Toml11FilePathsMre.exe"
    

    In the issue linked, the author of the library explains another way to achieve the same result, but setting the width worked for me and I didn't try the other method.