Fix float32_mode integer parsing: preserve int64 precision for integer-only tokens

Co-authored-by: syoyo <18676+syoyo@users.noreply.github.com>
Agent-Logs-Url: https://github.com/syoyo/tinygltf/sessions/a77fd614-00f3-49c1-bb4a-0498771cc63b
diff --git a/tests/tester.cc b/tests/tester.cc
index fe5981f..845a613 100644
--- a/tests/tester.cc
+++ b/tests/tester.cc
@@ -1249,3 +1249,37 @@
   // WriteImageData should be invoked for both images
   CHECK(counter == 2);
 }
+
+#ifdef TINYGLTF_USE_CUSTOM_JSON
+/* Regression test: in float32_mode, integer-only tokens with more than 9
+ * digits must still be parsed as integers (is_int == 1), not floats.
+ * Previously, max_sig=9 was applied to the integer part too, causing excess
+ * digits to bump exp10, which broke the exp10==0 guard in the integer
+ * fast-path and mis-classified the value as a float. */
+TEST_CASE("cj-float32-long-integer", "[customjson]") {
+    // Values chosen to cover exactly-at, just-over, and near int64 boundaries.
+    struct {
+        const char *text;
+        int64_t     expected;
+    } cases[] = {
+        { "1234567890",           1234567890LL        }, /* 10 digits */
+        { "12345678901",          12345678901LL       }, /* 11 digits */
+        { "1000000000000",        1000000000000LL     }, /* 13 digits */
+        { "9223372036854775807",  INT64_MAX           }, /* max int64 (19 digits) */
+        { "-1234567890",         -1234567890LL        }, /* negative 10 digits */
+        { "-9223372036854775808", INT64_MIN           }, /* min int64 */
+    };
+
+    for (auto &tc : cases) {
+        int      is_int = 0;
+        int64_t  ival   = 0;
+        double   dval   = 0.0;
+        const char *end = tc.text + strlen(tc.text);
+        const char *ret = cj_parse_number(tc.text, end, &is_int, &ival, &dval, /*float32_mode=*/1);
+        CAPTURE(tc.text);
+        REQUIRE(ret != nullptr);
+        CHECK(is_int == 1);
+        CHECK(ival == tc.expected);
+    }
+}
+#endif /* TINYGLTF_USE_CUSTOM_JSON */
diff --git a/tinygltf_json.h b/tinygltf_json.h
index 1260543..c33f22f 100644
--- a/tinygltf_json.h
+++ b/tinygltf_json.h
@@ -422,9 +422,11 @@
  * Returns pointer past the last character consumed, or NULL on error.
  *
  * float32_mode: when non-zero, floating-point values are parsed at float
- * (single) precision — fewer digits are significant, and the result is
- * stored as (double)(float)value.  This is faster but not JSON-conformant
- * for high-precision doubles.
+ * (single) precision — only 9 significant digits are tracked for the
+ * fraction part, and the result is stored as (double)(float)value.  This
+ * is faster but not JSON-conformant for high-precision doubles.  Integer-
+ * only tokens (no '.'/'e') are always parsed at full int64 precision
+ * regardless of this flag.
  *
  * Uses Clinger's fast path (no strtod) for ~99% of JSON float values.
  * Falls back to strtod only for extreme exponents or >19 significant digits. */
@@ -444,8 +446,12 @@
     int mantissa_overflow = 0; /* set if >19 significant digits */
     int has_frac = 0, has_exp = 0;
 
-    /* Max significant digits we track: 19 for double, 9 for float32 */
-    int max_sig = float32_mode ? 9 : 19;
+    /* Max significant digits we track:
+     *   Integer part: always 19, so integer-only tokens (no '.'/'e') are always
+     *     accumulated fully and can be typed as int64 regardless of float32_mode.
+     *   Fraction part: 9 in float32_mode (single precision), 19 otherwise. */
+    int max_sig_int  = 19;
+    int max_sig_frac = float32_mode ? 9 : 19;
 
     /* Integer part */
     if (*p == '0') {
@@ -453,7 +459,7 @@
     } else if ((unsigned)(*p - '1') <= 8u) {
         while (p < end && (unsigned)(*p - '0') <= 9u) {
             unsigned d = (unsigned)(*p - '0');
-            if (ndigits < max_sig) {
+            if (ndigits < max_sig_int) {
                 mantissa = mantissa * 10 + d;
             } else {
                 exp10++; /* excess digit: bump exponent instead */
@@ -474,7 +480,7 @@
         if (p >= end || (unsigned)(*p - '0') > 9u) return NULL;
         while (p < end && (unsigned)(*p - '0') <= 9u) {
             unsigned d = (unsigned)(*p - '0');
-            if (ndigits < max_sig) {
+            if (ndigits < max_sig_frac) {
                 mantissa = mantissa * 10 + d;
                 exp10--;
             }