-
-
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
replace strtold with non locale dependent version #337
Conversation
Thanks for the PR! I'll check it as soon as I find the time. |
Just one question: Can the code be licensed under the MIT license? |
Yeah I think it's fine, it's basically all rewritten so I don't think there is much of an issue that way... plus if they attempted to sue for using a similar variable name or if statement we'd probably become famous. If you want to be extra safe we can change the comments to be unique as they are just copied verbatim, though I think that'd be horrid as their comments are quite nice. |
standard floating point number parsing function based on the type | ||
supplied via the first parameter. Set this to @a | ||
static_cast<number_float_t*>(nullptr). | ||
while (nl_isspace(*fst)) |
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.
Whitespace is already skipped by the lexer, so I think it is safe to skip this loop.
if (cp == '-' or cp == '+') | ||
{ | ||
++fst; | ||
successful_parse = true; |
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.
The lexer discards any string that violates JSON's specification for numbers. Therefore, we do not need additional verification here.
Since it is relying on other conditions now with these 2 changes, I think we can strip out endptr and errno as well. |
this changes a few things. the name of the function to better represent what it does (string to json number) - we aren't strtoul compliant so best not to lie about that. we remove template code and just use one function. this makes it a bit simpler and we can always add it back if it buys us anything. the penalty for casting down from long double seems to be inconsequential.
The
|
if (*str == 'e' or *str == 'E') | ||
{ | ||
cp = *++str; | ||
bool negative_exp = cp == '-'; // read in exponent sign (+/-) |
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.
negative_exp
could be const bool
while (nl_isdigit(cp = *str)) | ||
{ | ||
result = result * 10 + (cp - '0'); | ||
++str; |
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.
Couldn't str
be incremented in the while
condition just like in the loop below?
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.
No, we may not want to increment if nl_isdigit fails so it must be in body.
supplied via the first parameter. Set this to @a | ||
static_cast<number_float_t*>(nullptr). | ||
int count = 0; // exponent calculation | ||
if (! nl_isdigit(cp)) |
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.
please use not
rather than !
{1.e1L, 1.e2L, 1.e4L, 1.e8L, 1.e16L, 1.e32L, 1.e64L, 1.e128L, 1.e256L} | ||
}; | ||
|
||
if (exp > std::numeric_limits<long double>::max_exponent10) |
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.
Starting here, there a now comments in the code. Please briefly describe each conditional and loop.
@nlohmann could you add help-wanted tag to this, I am too busy right now to do anything with this right now but it is very close. |
Hey @whackashoe do you need help with this? |
@nlohmann Yes. I haven't had time to figure out the last issues with this, though iirc its basically at a level where it works except for an edge case (maybe more than one). |
I'll have a look. I may open a feature branch myself for the moment to fix the conflicts and fiddle around a bit. |
I opened a feature branch. I changed the parser to reject incomplete numbers. This helped to simplify the number parser. There are still three tests failing - I'll check tomorrow. |
{ | ||
if (plus_or_minus) | ||
{ | ||
*--str; |
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.
Why is there a '*' here?
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 taking a look! @nlohmann want to incorp these into your feature branch?
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 makes no sense. Please have a look at https://github.com/nlohmann/json/blob/feature/strtold/src/json.hpp.re2c#L8139 where I started an overworked version of this PR.
|
||
@param[in] type the @ref number_float_t in use | ||
*--str; |
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.
ditto.
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.
See above.
Please have a look at https://github.com/nlohmann/json/blob/feature/strtold/src/json.hpp.re2c#L8139 where I started an overworked version of this PR, and also the discussion in #302. |
I see the code parses to long double, and then the return value is cast to float_number_t. |
Apparently implementing strtod correctly is harder than it seems. |
@whackashoe Any idea how to proceed here? I agree with @TurpentineDistillery that correct floating-point handling is really hard... |
What about this PR? Is it likely that the remaining issues can be fixed? There is also PR #378 dealing with the same issue. |
It seems like it will need significant changes to work. You can close this if it's dirtying up the queue, I don't have time to work on it for a while. |
Thanks for checking back. I close this for now. |
Move definition of common macros (e.g., JSON_HAS_CPP_*) into macros.hpp header file and update unit test sources. Incidentally enables the regression tests for nlohmann#2546 and nlohmann#3070. A CHECK_THROWS_WITH_AS in nlohmann#3070 was disabled, which is tracked here: nlohmann#337
Move definition of common macros (e.g., JSON_HAS_CPP_*) into macros.hpp header file and update unit test sources. Incidentally enables the regression tests for nlohmann#2546 and nlohmann#3070. A CHECK_THROWS_WITH_AS in nlohmann#3070 was disabled, which is tracked here: nlohmann#337
Move definition of common macros (e.g., JSON_HAS_CPP_*) into macros.hpp header file and update unit test sources. Incidentally enables the regression tests for nlohmann#2546 and nlohmann#3070. A CHECK_THROWS_WITH_AS in nlohmann#3070 was disabled, which is tracked here: nlohmann#337
Hi!
I've taken and reworked a strtod implementation from TI in order to provide this. It's rewritten in an attempt to be solid C++11 rather than C.
Using this fixes #302. It does not support octal or hexadecimal which JSON doesn't recognize in its number type anyway. This seems to be a bit more efficient (possibly due to non support of octal/hexadecimal) though I wouldn't be surprised if these gains disappear once the last few bugs are fixed heh.
Not all tests are passing yet but it's pretty close, perhaps someone can figure out the ones I haven't.
BEFORE:
AFTER:
UNIT TESTS:
(these are run with
CXX=clang++ make check
)