Skip to content
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

NK_STRTOD has extra const qualifier that blocks using standard library #700

Open
Xeverous opened this issue Sep 23, 2024 · 5 comments
Open

Comments

@Xeverous
Copy link
Contributor

Nuklear's code:

NK_API float
nk_strtof(const char *str, const char **endptr)
{
    float float_value;
    double double_value;
    double_value = NK_STRTOD(str, endptr);
    float_value = (float)double_value;
    return float_value;
}

The problem - standard library is incompatible:

// C89
double strtod(const char *restrict str, char **restrict str_end);
// C++ (any version)
double strtod(const char* str, char** str_end);

If I #define NK_STRTOD strtod then I'm getting the following error:

[...]/Nuklear/nuklear.h: In function ‘float nk_strtof(const char*, const char**)’:
[...]/Nuklear/nuklear.h:6841:35: error: invalid conversion from ‘const char**’ to ‘char**’ [-fpermissive]
 6841 |     double_value = NK_STRTOD(str, endptr);
      |                                   ^~~~~~
      |                                   |
      |                                   const char**
/usr/include/stdlib.h:118:27: note:   initializing argument 2 of ‘double strtod(const char*, char**)’
  118 |         char **__restrict __endptr)
      |         ~~~~~~~~~~~~~~~~~~^~~~~~~~

Can you change the implementation so that it supports the standard library (without const)?

@PROP65
Copy link
Contributor

PROP65 commented Feb 9, 2025

This should have been fixed in #682, but I forgot to rebuild nuklear.h at the time.

It's been rebuilt since, so this issue should be resolved.

@Xeverous
Copy link
Contributor Author

I have seen some commits changing this back and forth so I worry that someone later might open an issue that the function has no const but it should.

The root cause of the problem is that the standard library function is missing const. So Nuklear has to decide whether to go for const-correctness or stdlib compatibility (I would choose the latter). And ideally, Nuklear should apply this logic consistently to the entire implementation.

If Nuklear does not form specific consistent approach it risks 1) inconsistency in API 2) back-and-forth issues to "fix" the code to the other way.

@PROP65
Copy link
Contributor

PROP65 commented Feb 10, 2025

I'm not sure why endptr was made const to begin with (I checked the git blame and I belive Cong made the change in 2e4db87 after vurtun fixed it in f675cea), but the function needs to write to endptr to behave correctly. The incorrect const was there for at least 7 years, but I guess no one had tried utilizing that behavior.

strtof is from c99 but is just a float version of the c89 function strtod.

"A pointer to the final string is stored in the object pointed to by endptr, provided that endptr is not a null pointer." - 1989 ANSI C standard 4.10.1.4 "The strtod Function"

@PROP65
Copy link
Contributor

PROP65 commented Feb 10, 2025

We could try to prevent problems like this by adding a rule to the Reviewers guide stating implementations of libc functions must have an equivalent signature.

@Xeverous
Copy link
Contributor Author

the function needs to write to endptr to behave correctly. The incorrect const was there for at least 7 years, but I guess no one had tried utilizing that behavior.

Bottom-level const is fine, that is, the function can theoretically have signature (const char* str, const char** str_end) (but not (const char* str, char* const* str_end)). C standard requires char** str_end which is bad, because the first argument is a read-only C-string. Output parameter should be a pointer to read-only C-string but in the stdlib it is a pointer to modifiable C-string, allowing to break the constness. You could pass a literal string and get a pointer back that allows its modification.

I would still follow standard library signature. It's better than trying to improve the API by breaking compatibility.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants