-
-
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
locale-independent str-to-num #379
locale-independent str-to-num #379
Conversation
// this is a helper to determine whether to | ||
// parse the token into floating-point or | ||
// integral type. We wouldn't need it if | ||
// we had separate token types for interal |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
typo: interal
std::string tempstr; | ||
std::array<char, 64> buf; | ||
do { | ||
if (decimal_point_char == '.') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
do/while(0) instead of a pair of nested if statements seems a bit too tricky.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
do{...}while(0) was originally the technique to group statements in C macros, but it can also be used as a local scope that you can break
out of, kind of a disciplined scoped goto
. I just have really strong aversion to nesting control flow and modifying state; to a fault perhaps : )
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, I'm familiar. I don't particularly like nesting either, but this saves only one level of nesting.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As it is now: http://pastebin.com/UVTzUF6u
Simpler with no lambda capture, no lambda call at the end, fewer break/return statements: http://pastebin.com/vQu7y0CA
Personally, I don't think avoiding the one level of indentation for 10 lines of code is worth the extra complexity.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's not just about avoiding an extra level of control flow, however. I usually prefer the lambda style for the following reasons:
- manifests intent by declaring what we're about to compute and what the inputs are (especially handy in in-person code reviews)
- instead of the result being assigned as a side-effect in various control-flow branches, all control flow is "joined" into the return value, and the result of the lambda can be assigned to a const variable.
- there's no (or may be minimal) runtime overhead.
In short-enough cases, however, this approach would probably be considered an overkill by many (but not by me - there’s no lambda small enough!)
Stylistic issues aside, if I could only manage to make setlocale
affect the behavior of snprintf in the unit test on all compilers... That's even before any json-specific checks are triggered.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
setlocale is not thread specific or thread safe, so I would recommend avoiding it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
setlocale
with C locales is the equivalent of std::locale::global
with C++ locales, which is not thread-specific or thread-safe either.
We're not calling it it from the library code, however, but from the unit test to simulate the current state of a locale-specific application. All locale-dependent functions, including std::to_string()
or printf()
or cout <<
are not thread-safe in that sense, as a rogue thread may change C or C++ locale from under your feet by changing the locale in-flight because "they" needed it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay, missed that you were referring to test code.
…ocales (localeconv) rather than std::locale
…the behavior appears to be compiler/platform-specific
…xceptionless mode
@brief parse floating point number | ||
public: | ||
template<typename T> | ||
struct maybe |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This class isn't used in this PR.
|
||
@param[in] type the @ref number_float_t in use | ||
throw if can't parse the entire string as a number, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If exceptions are being removed, this comment needs to be updated.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for reviewing; will clean up in the next push.
…to manifest in AppVeyor
I shall have a look at the PR this week. |
@TurpentineDistillery Could you update the PR or resolve the conflicts, please? |
Will do. |
In lieu of better approaches, here are the number using Google Benchmark:
|
From the theoretical standpoint, the numbers are expected to be about the same, except that integral types are parsed with |
I forked the branch to https://github.com/nlohmann/json/tree/TurpentineDistillery-feature/locale_independent_str_to_num and made some changes. Once Travis is done checking, I shall merge it to develop. Thanks @TurpentineDistillery for the effort and @gregmarr for the comments! |
Closed with #450. |
This implements #302