From dd9319245ef8907909e8aa58c53728fed75ac70f Mon Sep 17 00:00:00 2001 From: ToruNiina Date: Wed, 13 Feb 2019 19:18:09 +0900 Subject: [PATCH] fix: open file as binary-mode #16 to avoid inconsistency between file size (obtained by tellg) and the size of the actual contents that would be read later --- README.md | 8 +++++++- tests/test_parse_file.cpp | 28 ++++++++++++++++++++++++++++ toml/parser.hpp | 2 +- 3 files changed, 36 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 4983315..0d5f4ac 100644 --- a/README.md +++ b/README.md @@ -42,8 +42,14 @@ In the case of file open error, it will throw `std::runtime_error`. You can also pass a `stream` to the `toml::parse` function after checking the status. +Note that on __Windows OS__, stream that is opened as text-mode automatically converts +CRLF ("\r\n") into LF ("\n") and this leads inconsistency between file size and +the contents that would be read. This causes weird error. To use a file stream +with `toml::parse`, don't forget to pass binary mode flag when you open the +stream. + ```cpp -std::ifstream ifs("sample.toml"); +std::ifstream ifs("sample.toml", std::ios_base::binary); assert(ifs.good()); const auto data = toml::parse(ifs /*, "filename" (optional)*/); ``` diff --git a/tests/test_parse_file.cpp b/tests/test_parse_file.cpp index 8bdf7f4..66e9d7c 100644 --- a/tests/test_parse_file.cpp +++ b/tests/test_parse_file.cpp @@ -213,6 +213,20 @@ BOOST_AUTO_TEST_CASE(test_file_with_BOM) BOOST_CHECK_EQUAL(toml::get (data.at("key")), "value"); BOOST_CHECK_EQUAL(toml::find(data.at("table"), "key"), "value"); } + { + const std::string table( + "\xEF\xBB\xBF" // BOM + "key = \"value\"\n" + "[table]\n" + "key = \"value\"\n" + ); + std::ofstream ofs("tmp.toml"); + ofs << table; + const auto data = toml::parse("tmp.toml"); + + BOOST_CHECK_EQUAL(toml::get (data.at("key")), "value"); + BOOST_CHECK_EQUAL(toml::find(data.at("table"), "key"), "value"); + } { const std::string table( "\xEF\xBB\xBF" // BOM @@ -223,6 +237,20 @@ BOOST_AUTO_TEST_CASE(test_file_with_BOM) std::istringstream iss(table); const auto data = toml::parse(iss, "test_file_with_BOM_CRLF.toml"); + BOOST_CHECK_EQUAL(toml::get (data.at("key")), "value"); + BOOST_CHECK_EQUAL(toml::find(data.at("table"), "key"), "value"); + } + { + const std::string table( + "\xEF\xBB\xBF" // BOM + "key = \"value\"\r\n" + "[table]\r\n" + "key = \"value\"\r\n" + ); + std::ofstream ofs("tmp.toml"); + ofs << table; + const auto data = toml::parse("tmp.toml"); + BOOST_CHECK_EQUAL(toml::get (data.at("key")), "value"); BOOST_CHECK_EQUAL(toml::find(data.at("table"), "key"), "value"); } diff --git a/toml/parser.hpp b/toml/parser.hpp index 2aa6c76..357368f 100644 --- a/toml/parser.hpp +++ b/toml/parser.hpp @@ -1517,7 +1517,7 @@ inline table parse(std::istream& is, std::string fname = "unknown file") inline table parse(const std::string& fname) { - std::ifstream ifs(fname.c_str()); + std::ifstream ifs(fname.c_str(), std::ios_base::binary); if(!ifs.good()) { throw std::runtime_error("toml::parse: file open error -> " + fname);