Thanks to visit codestin.com
Credit goes to github.com

Skip to content

<stdint.h> is available only in C99 or later #115

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

Merged
merged 2 commits into from
Nov 2, 2021

Conversation

DimitriPapadopoulos
Copy link
Contributor

No description provided.

@DimitriPapadopoulos
Copy link
Contributor Author

DimitriPapadopoulos commented Aug 14, 2021

I believe there's no way to define a 64-bit integer in C89, at least not in a portable way.

In the same way, INT64_MAX is not defined in C89 (and INT32_MAX shouldn't be defined either). But that issue is not on me.

@LB--
Copy link
Member

LB-- commented Aug 14, 2021

Yes, I was aware of that. I think people on systems that only support C89 won't really be able to use a 64-bit integer much anyway, or they can define json_int_t themselves, so using just long by default under C89 should suffice. Some systems/compilers actually make long 64-bit anyway. We may also be able to convert the macro from #102 to work with a passed in type as a parameter so it can be used in more places.

@DimitriPapadopoulos
Copy link
Contributor Author

DimitriPapadopoulos commented Aug 14, 2021

Actually, I believe #102 is not ANSI C either, because of 1UL. It may well be impossible to find the size of json_int_t in pure C89. But then it's usually already defined elsewhere, so let's not reinvent the wheel.

@DimitriPapadopoulos
Copy link
Contributor Author

This change is a bit invasive for a patch release such as 1.1.1: a new JSON_INT_MAX macro is defined in json.h. But then there's no good way to fix this in a simpler way. Perhaps leave this for 1.2.0? Perhaps release 1.2.0?

@DimitriPapadopoulos
Copy link
Contributor Author

DimitriPapadopoulos commented Aug 14, 2021

What was wrong with the previous definition of JSON_INT_MAX reverted by fcfa748? It's not clear to me.

static const json_int_t JSON_INT_MAX = (((unsigned json_int_t)0 - (unsigned json_int_t)1) / (unsigned json_int_t)2);

@DimitriPapadopoulos
Copy link
Contributor Author

DimitriPapadopoulos commented Aug 14, 2021

Perhaps casting back to signed?

static const json_int_t JSON_INT_MAX = (json_int_t)(((unsigned json_int_t)0 - (unsigned json_int_t)1) / (unsigned json_int_t)2);

@DimitriPapadopoulos
Copy link
Contributor Author

Also, I would keep int64_t for 1.1.1, and switch to int_fast64_t in 1.2.0.

@DimitriPapadopoulos DimitriPapadopoulos force-pushed the int64_t branch 3 times, most recently from c17378c to 3b6ef70 Compare August 15, 2021 06:49
@LB--
Copy link
Member

LB-- commented Aug 15, 2021

What was wrong with the previous definition [...]?

It's unclear to me too. I think for simple usage we can keep the automatic calculation with the new version you propose, and just have the documentation stipulate that json_int_t must be defined as a primitive integer type without signed or unsigned included, and otherwise the user must additionally define JSON_INT_MAX. I'm not sure how useful it is to have in the header as opposed to the source file though. These changes look good so far though, I just think we should keep the automatic calculation for simple usage scenarios.

@DimitriPapadopoulos
Copy link
Contributor Author

DimitriPapadopoulos commented Aug 16, 2021

Everything happens in the header because I need to know whether:

  • json_int_t has been defined explicitly by the end-user, in which case I have no knowledge of its exact type and if JSON_INT_MAX has not been defined, I can either #error out or attempt the automatic calculation of JSON_INT_MAX,
  • or json_int_t has been defined automatically by the header, in which case JSON_INT_MAX must have been defined automatically too.

To move the above logic to json.c, I would need a two-step process and two macro variables, such as json_int_t (a macro) / internal_json_int_t (a typedef ?), just like JSON_INT_MAX /TYPED_JSON_INT_MAX.

Anyway, I can switch to the automatic calculation of JSON_INT_MAX in json.c if it has not been already defined.

@DimitriPapadopoulos DimitriPapadopoulos force-pushed the int64_t branch 2 times, most recently from 1f4ad3f to e5026c1 Compare August 16, 2021 08:25
@DimitriPapadopoulos
Copy link
Contributor Author

DimitriPapadopoulos commented Aug 16, 2021

Note that we need additional information on how to print json_int_t:

I suggest we leave that for 1.2.0...

@DimitriPapadopoulos DimitriPapadopoulos force-pushed the int64_t branch 2 times, most recently from 7ad64cc to 29aeeff Compare August 19, 2021 20:18
@DimitriPapadopoulos
Copy link
Contributor Author

DimitriPapadopoulos commented Aug 20, 2021

I could also define a private JSON__JSON_INT_T_USER_DEFINED macro in json.h:

#ifndef json_int_t
   #if defined(_MSC_VER)
      #define json_int_t __int64
   #elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
      /* C99 */
      #include <stdint.h>
      #define json_int_t int64_t
   #else
      /* C89 */
      #define json_int_t long
   #endif
#else
   #define JSON__JSON_INT_T_USER_DEFINED 1
#endif

and do the rest in json.c:

#ifndef JSON__JSON_INT_T_USER_DEFINED
   #if defined(_MSC_VER)
      /* https://docs.microsoft.com/en-us/cpp/cpp/data-type-ranges */
      #define JSON_INT_MAX 9223372036854775807LL
   #elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
      /* C99 */
      #define JSON_INT_MAX INT64_MAX
   #else
      /* C89 */
      #include <limits.h>
      #define JSON_INT_MAX LONG_MAX
   #endif
#endif
[...]
#ifndef JSON_INT_MAX
static const json_int_t TYPED_JSON_INT_MAX = (json_int_t)(((unsigned json_int_t)0 - (unsigned json_int_t)1) / (unsigned json_int_t)2);
#else
static const json_int_t TYPED_JSON_INT_MAX = JSON_INT_MAX;
#endif

I could even add printing formats, as suggested in #115 (comment).

@DimitriPapadopoulos DimitriPapadopoulos force-pushed the int64_t branch 2 times, most recently from ba3e0f9 to 72a3353 Compare August 29, 2021 13:06
@DimitriPapadopoulos
Copy link
Contributor Author

DimitriPapadopoulos commented Aug 29, 2021

I have added a new version, as explained above:

  • Macro JSON__USER_DEFINED_JSON_INT_T is set when users define json_int_t explicitly.
  • Use int_fast64_t instead of int64_t, that's the right thing to do and doesn't break the API.
  • If JSON__USER_DEFINED_JSON_INT_T is defined, hope that users have defined JSON_INT_MAX too, and if not, attempt to calculate JSON_INT_MAX.

LB-- added a commit to LB--/json-parser that referenced this pull request Oct 31, 2021
Fixes json-parser#84
Closes json-parser#102
Probably affects json-parser#115

In theory this should be guaranteed to work regardless of the underlying representation: https://stackoverflow.com/a/2711560/1959975

Demos for C++17 and C89:
https://gcc.godbolt.org/#z:OYLghAFBqd5QCxAYwPYBMCmBRdBLAF1QCcAaPECAMzwBtMA7AQwFtMQByARg9KtQYEAysib0QXACx8BBAKoBnTAAUAHpwAMvAFYTStJg1DIApACYAQuYukl9ZATwDKjdAGFUtAK4sGe1wAyeAyYAHI%2BAEaYxBIAHKQADqgKhE4MHt6%2BekkpjgJBIeEsUTFc8XaYDmlCBEzEBBk%2Bfly2mPZ5DDV1BAVhkdFxtrX1jVktCsM9wX3FA2UAlLaoXsTI7BzmAMxYNCEA1ABq2ABKAJIAYgCaAPpuAIIBbhDaCgLXwQTXBKR7DPN7LzeHy%2Bvy2W2uAFk7gANCD/EwAdgse2ImAIKwYe2erwY70EX3mUC8DBSwBC6ABOLxnwI8wAtFw9gB6LHE0nkylA/G0szzEybZGIgAiJg0d1F4rMmzwVB2e2u12QCW8CmVXgUEq2wWQ3iwe35bloeBYhA1m2wmqlO2mhxOF0u2K5NJ%2Bf31AFY3BK9t7ObjgQRQVLwSwmKo4fqkSi0Ri9hN0CAQAwfNE8MhrkaTQQzW5AX7ufzsAmQ2G%2BQKI0L3Z6xT7bWcrrcHk9c9Svi6%2BWKtm0lJbtphdpha/bB/X7o8e64ZZqxUc6w7kAg6j953VS1Zp3arhAFAgSN9Yzv6quJTP7RAPj8Pkf17OILQBMAfnejFe7ifN0/gHsP4/7x%2BX2%2BHQVD4uDMeI9mA0CXw4RZaE4N1eD8DgtFIVBOE9SxrFjZZVgHLYeFIAhNGgxYAGsQE2AA2AA6LhaK4CiNA0Lg3ViN1NjKfROEkBCiJQzheAUEANAIojFjgWAkDQFgEjoaJyEoKSZPoGJgFosw%2BDoAhokEiAIl4iJgjqABPTh8KkthBAAeQYWgTKQ3gsBDIxxHs0h8FRKoADdMEE1zMFUSovC00zeA%2BNpeKNCJiGMjwsF4ghiGNELFioAxgAUA48EwAB3SyEkYEKZEEEQxHYKQivkJQ1F43QWgMIwUGsax9DwCJBMgRZUASDpfLpON%2BSFMkvCaywuARPY6UszYJoAdTEWhZv8hKmEW4hiBIAS2kqDoXAYdxPCafw9t6IoSmyZJUgEUZmkSC6OhO/pSladpqkma69AqKoBC6eoHtmJ6Jm6d7xkmP6zq4RZXhWNY9ASzB1h4GC4J41zUI4VRYgoukKMkPZgGQZA9loqizCxdCrEsH5cEIEh9SlFo9g8aTZOIOn2PmXhCPs%2BZSPIjQqLdQW3Q0CiKOF2IuE2YWKM4jhuNIFgJEY0hEOQtGBKEkTudIcTEBQVBmeU%2BSIEUlmQFUkCNNoLTiB0vTXIM5hiDssyDYsghrNs3jHMMYAXOQ9ztrwbzfOQ/zAuC7hQsEcLXMi6Lndi9ZkISpKo5StKMqy3L8sQ/D%2BGK0RxHKgvKpUdRXN0dT6uMEabEi9q4RQ7q0l6/rNkGpNYgATgmqbZvmxbVGW1b1tZulVD2ZBNpe5wIFcYHSECaZTrmW7cjSReckuhgwbXz6Oh%2BhoDrGZ6g%2B%2B0GV8ej63pPm7Ad%2Bq//okSHsJhlo4YR6DZfglXeLRjGWMcZ4wJkTLgJMyZ1ypvgIgrM8I/CZkpaIbNeSc1ErzTYmwqKYJwbgvBst5aq14OrWwmsuZaB5rLMwKM1b8S1hQxY3lbZpBAJIIAA%3D%3D
#endif

#ifndef JSON_INT_MAX
#define JSON_INT_MAX (json_int_t)(((unsigned json_int_t)(-1)) / (unsigned json_int_t)2);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah nice... I should have looked at this more closely before trying to reinvent it myself in 3513fbe >_<

Copy link
Member

@LB-- LB-- left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is looking good so far, and after some more thinking I understand and agree with more of your rationale. As before though, we can't have the double underscores in any identifiers. I think JSON__USER_DEFINED_JSON_INT_T is quite a mouthful as well, why not simply JSON_INT_T_OVERRIDDEN?

@LB-- LB-- mentioned this pull request Oct 31, 2021
Either it has been defined explictly, or we attempt to calculate it
using the method reverted by fcfa748.

See discussion in json-parser#84 and json-parser#102.
@DimitriPapadopoulos
Copy link
Contributor Author

Identifiers should not begin with underscores, but double underscores within the identifier are OK in C. Only in C++ are consecutive underscores reserved for the implementation. Technically, this is a C program. It could be compiled by a C++ compiler, but it's still C, so I feel the double underscores are OK.

That said, I had added the double underscore because JSON__USER_DEFINED_JSON_INT_T was indeed long and complex. Your suggestion to switch to JSON_INT_T_OVERRIDDEN removes the need for it.

@LB-- LB-- linked an issue Nov 2, 2021 that may be closed by this pull request
@LB-- LB-- merged commit 24df9ad into json-parser:master Nov 2, 2021
@DimitriPapadopoulos DimitriPapadopoulos deleted the int64_t branch November 3, 2021 07:58
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

Successfully merging this pull request may close these issues.

Improve calculation of JSON_INT_MAX
2 participants