mirror of
https://github.com/ToruNiina/toml11.git
synced 2025-09-17 17:58:09 +08:00
feat: Add a parse(FILE *) interface
The fstream classes are notorious for their non-existent error handling. This adds a C-style fILE * IO (fopen(), etc.) alternative interface, so that if a user needs reliable error handling, they can use that, albeit more inconvenient, but more robust approach.
This commit is contained in:
@@ -2377,27 +2377,14 @@ result<Value, std::string> parse_toml_file(location& loc)
|
||||
return ok(Value(std::move(data), file, comments));
|
||||
}
|
||||
|
||||
} // detail
|
||||
|
||||
template<typename Comment = TOML11_DEFAULT_COMMENT_STRATEGY,
|
||||
template<typename ...> class Table = std::unordered_map,
|
||||
template<typename ...> class Array = std::vector>
|
||||
basic_value<Comment, Table, Array>
|
||||
parse(std::istream& is, std::string fname = "unknown file")
|
||||
parse(std::vector<char>& letters, const std::string& fname)
|
||||
{
|
||||
using value_type = basic_value<Comment, Table, Array>;
|
||||
|
||||
const auto beg = is.tellg();
|
||||
is.seekg(0, std::ios::end);
|
||||
const auto end = is.tellg();
|
||||
const auto fsize = end - beg;
|
||||
is.seekg(beg);
|
||||
|
||||
// read whole file as a sequence of char
|
||||
assert(fsize >= 0);
|
||||
std::vector<char> letters(static_cast<std::size_t>(fsize));
|
||||
is.read(letters.data(), fsize);
|
||||
|
||||
// append LF.
|
||||
// Although TOML does not require LF at the EOF, to make parsing logic
|
||||
// simpler, we "normalize" the content by adding LF if it does not exist.
|
||||
@@ -2435,12 +2422,70 @@ parse(std::istream& is, std::string fname = "unknown file")
|
||||
return data.unwrap();
|
||||
}
|
||||
|
||||
} // detail
|
||||
|
||||
template<typename Comment = TOML11_DEFAULT_COMMENT_STRATEGY,
|
||||
template<typename ...> class Table = std::unordered_map,
|
||||
template<typename ...> class Array = std::vector>
|
||||
basic_value<Comment, Table, Array>
|
||||
parse(FILE * file, const std::string& fname)
|
||||
{
|
||||
const long beg = std::ftell(file);
|
||||
if (beg == -1l) {
|
||||
throw file_io_error(errno, "Failed to access", fname);
|
||||
}
|
||||
|
||||
int res = std::fseek(file, 0, SEEK_END);
|
||||
if (res != 0) {
|
||||
throw file_io_error(errno, "Failed to seek", fname);
|
||||
}
|
||||
|
||||
const long end = std::ftell(file);
|
||||
if (end == -1l) {
|
||||
throw file_io_error(errno, "Failed to access", fname);
|
||||
}
|
||||
|
||||
const auto fsize = end - beg;
|
||||
|
||||
res = std::fseek(file, beg, SEEK_SET);
|
||||
if (res != 0) {
|
||||
throw file_io_error(errno, "Failed to seek", fname);
|
||||
}
|
||||
|
||||
// read whole file as a sequence of char
|
||||
assert(fsize >= 0);
|
||||
std::vector<char> letters(static_cast<std::size_t>(fsize));
|
||||
std::fread(letters.data(), sizeof(char), static_cast<std::size_t>(fsize), file);
|
||||
|
||||
return detail::parse<Comment, Table, Array>(letters, fname);
|
||||
}
|
||||
|
||||
template<typename Comment = TOML11_DEFAULT_COMMENT_STRATEGY,
|
||||
template<typename ...> class Table = std::unordered_map,
|
||||
template<typename ...> class Array = std::vector>
|
||||
basic_value<Comment, Table, Array>
|
||||
parse(std::istream& is, std::string fname = "unknown file")
|
||||
{
|
||||
const auto beg = is.tellg();
|
||||
is.seekg(0, std::ios::end);
|
||||
const auto end = is.tellg();
|
||||
const auto fsize = end - beg;
|
||||
is.seekg(beg);
|
||||
|
||||
// read whole file as a sequence of char
|
||||
assert(fsize >= 0);
|
||||
std::vector<char> letters(static_cast<std::size_t>(fsize));
|
||||
is.read(letters.data(), fsize);
|
||||
|
||||
return detail::parse<Comment, Table, Array>(letters, fname);
|
||||
}
|
||||
|
||||
template<typename Comment = TOML11_DEFAULT_COMMENT_STRATEGY,
|
||||
template<typename ...> class Table = std::unordered_map,
|
||||
template<typename ...> class Array = std::vector>
|
||||
basic_value<Comment, Table, Array> parse(std::string fname)
|
||||
{
|
||||
std::ifstream ifs(fname.c_str(), std::ios_base::binary);
|
||||
std::ifstream ifs(fname, std::ios_base::binary);
|
||||
if(!ifs.good())
|
||||
{
|
||||
throw std::runtime_error("toml::parse: file open error -> " + fname);
|
||||
|
Reference in New Issue
Block a user