-
-
Notifications
You must be signed in to change notification settings - Fork 6.7k
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
Parse throw std::ios_base::failure exception when failbit set to true #714
Comments
The problem is that inside the lexer, Example code: #include <iostream>
#include <fstream>
#include <array>
int main() {
std::ifstream is;
is.exceptions(
is.exceptions()
| std::ios_base::failbit
| std::ios_base::badbit
); // handle different exceptions as 'file not found', 'permission denied'
try {
is.open("file.json");
std::array<char, 10000> buffer;
is.read(buffer.data(), static_cast<std::streamsize>(buffer.size()));
}
catch (const std::ios_base::failure &e) {
std::cerr << "error: " << e.code().message() << std::endl;
}
} Any ideas how to implement this without a try/catch? |
I don't know, is a fast and right this method or not: is.get(buffer.data(), static_cast<std::streamsize>(buffer.size()), '\0'); but it works with non-empty input streams. |
The null character does not help here, because the same code is also used for binary formats like CBOR or MsgPack. Changing this line to is.get(buffer.data(), static_cast<std::streamsize>(buffer.size()), std::char_traits<char>::eof()); works, but still has the issue that
This happens if we check that the input actually ended with EOF, so we call |
Good news! If Also, is.get(buffer.data(), static_cast<std::streamsize>(5), std::char_traits<char>::eof()); read |
Yes, this may help. void fill_buffer()
{
// fill
is.get(buffer.data(), static_cast<std::streamsize>(buffer.size()), std::char_traits<char>::eof());
// store number of bytes in the buffer
fill_size = static_cast<size_t>(is.gcount());
// set EOF
eof = is.eof();
} This fixes nearly all issues - just two test cases with CBOR/MessagePack are still failing. Is there a difference in |
However,
Note that it uses |
I see // ....
_M_gcount = this->rdbuf()->sgetn(__s, __n);
if (_M_gcount != __n)
__err |= (ios_base::eofbit | ios_base::failbit);
// .... If other compilers have similar code, the best solution is: void fill_buffer()
{
// fill
fill_size = is.rdbuf()->sgetn(buffer.data(), static_cast<std::streamsize>(buffer.size()));
// set EOF
eof = ( fill_size != static_cast<std::streamsize>(buffer.size()) );
} |
@dPavelDev This works, thanks a lot! @gregmarr I tried to be clever by explicitly passing a non-char value... :-S |
5439307 does not yet work with MSVC:
|
#367 does not fix this issue. With MSVC, I experience the same error as #714 (comment):
Any ideas on this? Maybe @pjkundert? |
This just seems to be due to a missing With this flag the tests pass for me (MSVC). |
@abolz Thanks so much for noting! (I did not mean to close the issue with the commit, but the CI builds seem to succeed) 👍 |
In brief:
The line (*) produce std::ios_base::failure exception when parse function reaches end of stream even if json document is valid. Without std::ios_base::failbit function works OK.
The text was updated successfully, but these errors were encountered: