Skip to content

Commit e95f7d9

Browse files
committed
to_string(): define long long overloads even in C++98 mode
Since `uint64_t` is an alias for `unsigned long long` on macOS, I think this is the only way (except for templates that we used until #76) to ensure that `to_string()` supports an `uint64_t` argument. `long long` is technically not in C++98, but if we detect that the `LLONG_MAX` macro is defined, we should be able to use it. And as I mentioned in `Common.cmake`, I don't think we currently support any compiler without `long long` support, given that we already require `int64_t`/`uint64_t`, which are also only part of C++11 and not C++98.
1 parent cf85fea commit e95f7d9

File tree

4 files changed

+24
-20
lines changed

4 files changed

+24
-20
lines changed

Common.cmake

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,13 @@ target_compile_options(${PROJECT_NAME} PRIVATE
1515
$<$<CXX_COMPILER_ID:MSVC>:/W4 /WX>
1616
$<$<NOT:$<CXX_COMPILER_ID:MSVC>>:
1717
-Wall -Wextra -Wpedantic -Werror
18+
19+
# We're using the `long long` type intentionally. Although it's not part of C++98, in
20+
# practice it is usually supported even by ancient compilers with very limited C++11
21+
# support. And we already unconditionally require `uint64_t`, so it would be strange if
22+
# the compiler supported `uint64_t` and not `long long`.
23+
-Wno-error=long-long
24+
1825
# See <https://gcc.gnu.org/onlinedocs/gcc-13.3.0/gcc/Warning-Options.html#index-Wstrict-aliasing_003dn>:
1926
#
2027
# > Level 1: (...) it has very few false negatives. However, it has many false positives.

gcc4.mk

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,12 @@ OBJS := \
1313

1414
CXXFLAGS := -std=c++98 -Wall -Wextra -pedantic
1515

16+
# `-pedantic` enables `-Wlong-long`, which for some reason turns into
17+
# `error: ISO C++ does not support 'long long'`, even though we don't use `-Werror`. Since
18+
# we're using `long long` intentionally, we suppress this error using `-Wno-long-long`
19+
# (see https://gcc.gnu.org/onlinedocs/gcc-4.1.2/gcc/Warning-Options.html#index-Wlong_002dlong-305).
20+
CXXFLAGS += -Wno-long-long
21+
1622
# NOTE: the meaning of `<n>` values in `-Wstrict-aliasing=<n>` is different in GCC 4.1.2
1723
# than in recent versions of GCC. According to
1824
# https://gcc.gnu.org/onlinedocs/gcc-4.1.2/gcc/Warning-Options.html#index-Wstrict_002daliasing-246,

kaitai/kaitaistream.h

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
#include <ios> // std::streamsize, forward declaration of std::istream // IWYU pragma: keep
1515
#include <cstddef> // std::size_t
16+
#include <climits> // LLONG_MAX, ULLONG_MAX
1617
#include <sstream> // std::istringstream // IWYU pragma: keep
1718
#include <string> // std::string
1819

@@ -252,8 +253,11 @@ class kstream {
252253
return to_string_signed(val);
253254
}
254255

255-
// The `long long` type is only available since C++11, so we use it only in C++11 mode.
256-
#ifdef KAITAI_STREAM_H_CPP11_SUPPORT
256+
// The `long long` type is technically available only since C++11. It is usually
257+
// supported even by ancient compilers that have very limited C++11 support, but we can
258+
// still check if the `LLONG_MAX` macro is defined (it seems very unlikely that it is not,
259+
// though).
260+
#ifdef LLONG_MAX
257261
/**
258262
* Converts given integer `val` to a decimal string representation.
259263
* Should be used in place of `std::to_string(long long)` (which is available only
@@ -282,8 +286,11 @@ class kstream {
282286
return to_string_unsigned(val);
283287
}
284288

285-
// The `unsigned long long` type is only available since C++11, so we use it only in C++11 mode.
286-
#ifdef KAITAI_STREAM_H_CPP11_SUPPORT
289+
// The `unsigned long long` type is technically available only since C++11. It is usually
290+
// supported even by ancient compilers that have very limited C++11 support, but we can
291+
// still check if the `LLONG_MAX` macro is defined (it seems very unlikely that it is not,
292+
// though).
293+
#ifdef ULLONG_MAX
287294
/**
288295
* Converts given integer `val` to a decimal string representation.
289296
* Should be used in place of `std::to_string(unsigned long long)` (which is available only

tests/unittest.cpp

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -154,8 +154,6 @@ TEST(KaitaiStreamTest, to_string_long)
154154
#pragma warning(pop)
155155
#endif
156156

157-
// The `long long` type is only available since C++11, so we use it only in C++11 mode.
158-
#ifdef KAITAI_STREAM_H_CPP11_SUPPORT
159157
TEST(KaitaiStreamTest, to_string_unsigned_long_long)
160158
{
161159
EXPECT_EQ(kaitai::kstream::to_string(std::numeric_limits<unsigned long long>::min()), "0");
@@ -167,20 +165,6 @@ TEST(KaitaiStreamTest, to_string_long_long)
167165
EXPECT_EQ(kaitai::kstream::to_string(std::numeric_limits<long long>::min()), "-9223372036854775808");
168166
EXPECT_EQ(kaitai::kstream::to_string(std::numeric_limits<long long>::max()), "9223372036854775807");
169167
}
170-
#else
171-
// Make sure we still support 64-bit integers.
172-
TEST(KaitaiStreamTest, to_string_uint64)
173-
{
174-
EXPECT_EQ(kaitai::kstream::to_string(std::numeric_limits<uint64_t>::min()), "0");
175-
EXPECT_EQ(kaitai::kstream::to_string(std::numeric_limits<uint64_t>::max()), "18446744073709551615");
176-
}
177-
178-
TEST(KaitaiStreamTest, to_string_int64)
179-
{
180-
EXPECT_EQ(kaitai::kstream::to_string(std::numeric_limits<int64_t>::min()), "-9223372036854775808");
181-
EXPECT_EQ(kaitai::kstream::to_string(std::numeric_limits<int64_t>::max()), "9223372036854775807");
182-
}
183-
#endif
184168

185169
TEST(KaitaiStreamTest, string_to_int)
186170
{

0 commit comments

Comments
 (0)