10 Commits
Author SHA1 Message Date
Thiago Macieira ff7a23a8f1 CI: Disable building the tools for macOS small
CI / macos-15-intel/clang (push) Canceled after 0s
CI / ubuntu-latest/clang (push) Canceled after 0s
CI / ubuntu-latest/linux-g++ (push) Canceled after 0s
CI / macos-latest/clang-small (push) Canceled after 0s
CI / ubuntu-latest/clang-small (push) Canceled after 0s
CI / ubuntu-latest/gcc-small (push) Canceled after 0s
CI / ubuntu-latest/gcc-no-math (push) Canceled after 0s
CI / ubuntu-latest/gcc-freestanding (push) Canceled after 0s
The build fails after the transition to Apple silicon and I don't know
why:
```
: && /usr/bin/clang -Oz -g -Werror -arch arm64 -Wl,-search_paths_first -Wl,-headerpad_max_install_names tools/json2cbor/CMakeFiles/json2cbor.dir/json2cbor.c.o -o tools/json2cbor/json2cbor  libtinycbor.a  -lcjson  -lm && :
ld: library 'cjson' not found
```

Homebrew says it installed and CMake says it found it.
```
-- Checking for module 'libcjson'
--   Found libcjson, version 1.7.19
```

I won't investigate.

Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2026-02-05 15:01:24 -08:00
Thiago Macieira 91d1c50d60 compilersupport: fix compilation in C23 mode
GCC15 added support for C23's `unreachable()`, causing a warning:

```
src/compilersupport_p.h:215:11: warning: ‘unreachable’ redefined
  215 | #  define unreachable() __builtin_unreachable()
      |           ^~~~~~~~~~~
stddef.h:468:9: note: this is the previous definition
  468 | #define unreachable() (__builtin_unreachable ())
      |         ^~~~~~~~~~~
```

Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2026-02-05 14:16:59 -08:00
Thiago Macieira 0cd8b054a1 cbortojson: don't hardcode OS support for fopencookie()
Instead of saying Linux (a.k.a. glibc) has it and Apple has funopen(),
use the fact that we've just detected them and inform the .c source
which one it was.

Fixes #306

Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2026-02-05 14:16:39 -08:00
Thiago Macieira 7a3b6ab7bc CMake: fix the option() order
I'd forgot to save the file before Git commit...

Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2026-02-05 14:16:24 -08:00
Thiago Macieira 64da0f471a CBOR-to-JSON: print integers with full precision
Instead of performing a lossy conversion to double and printing that.
It's irrelevant whether the parser on the other side can store this
precision, only that it can parse this. That includes numbers outside
the range of int64_t, which CBOR does support.

We do this by simply removing code from cbortojson.c and instead just
relying on what cborpretty.c already has.

Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2026-02-05 14:15:50 -08:00
Thiago Macieira ef6f92349f simplereader: Fix warning about use of pointer variable after free()
We weren't dereferencing the variable, so this should have been safe.
However, it isn't clear in the C and C++ standards whether it
legitimately was safe. So let's just fix it.

```
simplereader.c:180:9: warning: pointer ‘buf’ may be used after ‘free’ [-Wuse-after-free]
simplereader.c:177:5: note: call to ‘free’ here
```

Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2026-02-05 14:09:42 -08:00
Thiago Macieira 9487c1b3b4 CI: update the macOS images to more modern versions
macos-13 no longer exists in GitHub Actions.

Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2026-02-05 14:07:12 -08:00
Thiago Macieira 09496c6432 compilersupport: add support for C23's nullptr
It has the same semantics as C++11's `nullptr`.

Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2025-12-01 13:25:03 -08:00
dependabot[bot] 17362494e2 Bump actions/checkout from 5 to 6
Bumps [actions/checkout](https://github.com/actions/checkout) from 5 to 6.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v5...v6)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: '6'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-11-24 09:47:16 -08:00
Florian Larysch 48a22bddfc fix build on i386 without SSE2
Commit 3cba6b1 ("Use _Float16 for half conversions if available") added
support for using half-width float support in the compiler to perform
encoding operations, using the FLT16_MANT_DIG macro to check for
support on the given target.

However, on x86 GCC only supports this when SSE2 is enabled[1]. Unlike
clang and the other architectures where support for this is conditional,
GCC *does* define those macros even without SSE2 support, causing a
build failure:

  In file included from cborencoder_float.c:29:
  cborinternal_p.h: In function ‘encode_half’:
  cborinternal_p.h:56:5: error: invalid conversion to type ‘_Float16’ without option ‘-msse2’
     56 |     _Float16 f = (_Float16)x;
        |     ^~~~~~~~
  cborinternal_p.h: In function ‘decode_half’:
  cborinternal_p.h:65:5: error: invalid conversion from type ‘_Float16’ without option ‘-msse2’
     65 |     return (float)f;
        |

Work around this by additionally checking for this specific condition.

[1] https://gcc.gnu.org/onlinedocs/gcc/Half-Precision.html

Signed-off-by: Florian Larysch <fl@n621.de>
2025-08-19 13:46:12 -07:00
8 changed files with 55 additions and 77 deletions
+4 -3
View File
@@ -63,7 +63,7 @@ jobs:
-DCMAKE_CXX_COMPILER=g++
-DCMAKE_CXX_FLAGS_DEBUG="-Werror"
include:
- os: macos-13
- os: macos-latest
build_cfg:
name: clang-small
cmakeflags: >-
@@ -72,7 +72,8 @@ jobs:
-DCMAKE_C_FLAGS="-Oz -g -Werror"
-DCMAKE_CXX_COMPILER=clang++
-DCMAKE_CXX_FLAGS="-O2 -g -Werror"
- os: macos-13
-DWITH_TOOLS=OFF
- os: macos-15-intel
build_cfg:
name: clang
cmakeflags: >-
@@ -92,7 +93,7 @@ jobs:
runs-on: ${{ matrix.os }}
steps:
- name: Clone tinycbor
uses: actions/checkout@v5
uses: actions/checkout@v6
- name: install Linux software
if: matrix.os == 'ubuntu-latest'
+9 -4
View File
@@ -31,10 +31,10 @@ set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake ${CMAKE_MODULE_PATH})
set(TARGETS_EXPORT_NAME "TinyCBOR-targets")
option(WITH_CBOR2JSON "Compile code to convert from CBOR to JSON" ON)
option(WITH_FLOATING_POINT "Use floating point code in TinyCBOR" ON)
option(WITH_FREESTANDING "Compile TinyCBOR in C freestanding mode" OFF)
if(WITH_FLOATING_POINT AND NOT WITH_FREESTANDING)
option(WITH_FLOATING_POINT "Use floating point code in TinyCBOR" ON)
option(WITH_CBOR2JSON "Compile code to convert from CBOR to JSON" ON)
option(WITH_TOOLS "Compile the TinyCBOR tools" ON)
endif()
@@ -131,8 +131,13 @@ check_symbol_exists(funopen stdio.h HAVE_OPEN_FUNOPEN)
check_symbol_exists(fopencookie stdio.h HAVE_OPEN_FOPENCOOKIE)
if(NOT HAVE_OPEN_MEMSTREAM)
if (HAVE_OPEN_FUNOPEN AND HAVE_OPEN_FOPENCOOKIE)
message(STATUS "using open_memstream implementation")
if (HAVE_OPEN_FUNOPEN)
message(STATUS "implementing open_memstream using funopen()")
target_compile_definitions(tinycbor PRIVATE HAVE_OPEN_FUNOPEN)
target_sources(tinycbor PRIVATE src/open_memstream.c)
elseif (HAVE_OPEN_FOPENCOOKIE)
message(STATUS "implementing open_memstream using fopencookie()")
target_compile_definitions(tinycbor PRIVATE HAVE_OPEN_FOPENCOOKIE)
target_sources(tinycbor PRIVATE src/open_memstream.c)
else()
target_compile_definitions(tinycbor PRIVATE WITHOUT_OPEN_MEMSTREAM)
+2 -1
View File
@@ -174,12 +174,13 @@ int main(int argc, char **argv)
CborError err = cbor_parser_init(buf, length, 0, &parser, &it);
if (!err)
err = dumprecursive(&it, 0);
free(buf);
if (err) {
fprintf(stderr, "CBOR parsing failure at offset %ld: %s\n",
cbor_value_get_next_byte(&it) - buf, cbor_error_string(err));
free(buf);
return 1;
}
free(buf);
return 0;
}
+5 -1
View File
@@ -48,8 +48,12 @@
/* Check for FLT16_MANT_DIG using integer comparison. Clang headers incorrectly
* define this macro unconditionally when __STDC_WANT_IEC_60559_TYPES_EXT__
* is defined (regardless of actual support for _Float16).
*
* GCC defines these macros but doesn't support arithmetic including
* conversions on x86 without SSE2.
*/
# if FLT16_MANT_DIG > 0 || __FLT16_MANT_DIG__ > 0
# if (FLT16_MANT_DIG > 0 || __FLT16_MANT_DIG__ > 0) && \
!(defined(__i386__) && !defined(__SSE2__))
static inline unsigned short encode_half(float x)
{
unsigned short h;
+5 -35
View File
@@ -644,28 +644,11 @@ static CborError value_to_json(FILE *out, CborValue *it, int flags, CborType typ
return CborNoError;
}
case CborIntegerType: {
double num; /* JS numbers are IEEE double precision */
uint64_t val;
cbor_value_get_raw_integer(it, &val); /* can't fail */
num = (double)val;
if (cbor_value_is_negative_integer(it)) {
num = -num - 1; /* convert to negative */
if ((uint64_t)(-num - 1) != val) {
status->flags = NumberPrecisionWasLost | NumberWasNegative;
status->originalNumber = val;
}
} else {
if ((uint64_t)num != val) {
status->flags = NumberPrecisionWasLost;
status->originalNumber = val;
}
}
if (fprintf(out, "%.0f", num) < 0) /* this number has no fraction, so no decimal points please */
return CborErrorIO;
break;
}
case CborIntegerType:
case CborNullType:
case CborBooleanType:
/* just use cborpretty.c */
return cbor_value_to_pretty_advance(out, it);
case CborByteStringType:
case CborTextStringType: {
@@ -696,25 +679,12 @@ static CborError value_to_json(FILE *out, CborValue *it, int flags, CborType typ
break;
}
case CborNullType:
if (fprintf(out, "null") < 0)
return CborErrorIO;
break;
case CborUndefinedType:
status->flags = TypeWasNotNative;
if (fprintf(out, "\"undefined\"") < 0)
return CborErrorIO;
break;
case CborBooleanType: {
bool val;
cbor_value_get_boolean(it, &val); /* can't fail */
if (fprintf(out, val ? "true" : "false") < 0)
return CborErrorIO;
break;
}
#ifndef CBOR_NO_FLOATING_POINT
case CborDoubleType: {
double val;
+17 -17
View File
@@ -52,14 +52,10 @@
# define cbor_static_assert(x) ((void)sizeof(char[2*!!(x) - 1]))
#endif
#if defined(__has_cpp_attribute) && defined(__cplusplus) // C++17
#if defined(__has_cpp_attribute) // C23 and C++17
# if __has_cpp_attribute(fallthrough)
# define CBOR_FALLTHROUGH [[fallthrough]]
# endif
#elif defined(__has_c_attribute) && !defined(__cplusplus) // C23
# if __has_c_attribute(fallthrough)
# define CBOR_FALLTHROUGH [[fallthrough]]
# endif
#endif
#ifndef CBOR_FALLTHROUGH
# ifdef __GNUC__
@@ -202,29 +198,33 @@
#ifdef __cplusplus
# define CONST_CAST(t, v) const_cast<t>(v)
# define CBOR_NULLPTR nullptr
#else
/* C-style const_cast without triggering a warning with -Wcast-qual */
# define CONST_CAST(t, v) (t)(uintptr_t)(v)
#endif
#if defined(__cplusplus) || __STDC_VERSION__ >= 202311
# define CBOR_NULLPTR nullptr
#else
# define CBOR_NULLPTR NULL
#endif
#ifdef __GNUC__
#ifndef likely
#ifdef likely
/* something has already defined likely(), accept it */
#elif defined(__GNUC__)
# define likely(x) __builtin_expect(!!(x), 1)
#endif
#ifndef unlikely
# define unlikely(x) __builtin_expect(!!(x), 0)
#endif
# define unreachable() __builtin_unreachable()
#elif defined(_MSC_VER)
# define likely(x) (x)
# define unlikely(x) (x)
# define unreachable() __assume(0)
#else
# define likely(x) (x)
# define unlikely(x) (x)
# define unreachable() do {} while (0)
#endif
#ifdef unreachable
/* C23 has unreachable() */
#elif defined(__GNUC__)
# define unreachable() __builtin_unreachable()
#elif defined(_MSC_VER)
# define unreachable() __assume(0)
#endif
static inline bool add_check_overflow(size_t v1, size_t v2, size_t *r)
+4 -4
View File
@@ -35,10 +35,10 @@
#if defined(__unix__) || defined(__APPLE__)
# include <unistd.h>
#endif
#ifdef __APPLE__
#if defined(HAVE_OPEN_FUNOPEN)
typedef int RetType;
typedef int LenType;
#elif __linux__
#elif defined(HAVE_OPEN_FOPENCOOKIE)
typedef ssize_t RetType;
typedef size_t LenType;
#else
@@ -99,9 +99,9 @@ FILE *open_memstream(char **bufptr, size_t *lenptr)
*bufptr = NULL;
*lenptr = 0;
#ifdef __APPLE__
#if defined(HAVE_OPEN_FUNOPEN)
return funopen(b, NULL, write_to_buffer, NULL, close_buffer);
#elif __linux__
#elif defined(HAVE_OPEN_FOPENCOOKIE)
static const cookie_io_functions_t vtable = {
NULL,
write_to_buffer,
+9 -12
View File
@@ -100,13 +100,20 @@ void addFixedData()
QTest::newRow("0") << raw("\x00") << "0";
QTest::newRow("1") << raw("\x01") << "1";
QTest::newRow("2^53-1") << raw("\x1b\0\x1f\xff\xff""\xff\xff\xff\xff") << "9007199254740991";
QTest::newRow("2^64-epsilon") << raw("\x1b\xff\xff\xff\xff""\xff\xff\xf8\x00") << "18446744073709549568";
QTest::newRow("2^53+1") << raw("\x1b\0\x20\0\0""\0\0\0\1") << "9007199254740993";
QTest::newRow("2^63-1") << raw("\x1b\x7f\xff\xff\xff""\xff\xff\xff\xff") << "9223372036854775807";
QTest::newRow("2^64-1") << raw("\x1b\xff\xff\xff\xff""\xff\xff\xff\xff") << "18446744073709551615";
// negative integers
QTest::newRow("-1") << raw("\x20") << "-1";
QTest::newRow("-2") << raw("\x21") << "-2";
QTest::newRow("-2^53+1") << raw("\x3b\0\x1f\xff\xff""\xff\xff\xff\xfe") << "-9007199254740991";
QTest::newRow("-2^64+epsilon") << raw("\x3b\xff\xff\xff\xff""\xff\xff\xf8\x00") << "-18446744073709549568";
QTest::newRow("-2^53-1") << raw("\x3b\0\x20\0\0""\0\0\0\0") << "-9007199254740993";
QTest::newRow("-2^63+1") << raw("\x3b\x7f\xff\xff\xff""\xff\xff\xff\xfe") << "-9223372036854775807";
QTest::newRow("-2^63") << raw("\x3b\x7f\xff\xff\xff""\xff\xff\xff\xff") << "-9223372036854775808";
QTest::newRow("-2^63-1") << raw("\x3b\x80\0\0\0""\0\0\0\0") << "-9223372036854775809";
QTest::newRow("-2^64+1") << raw("\x3b\xff\xff\xff\xff""\xff\xff\xff\xfe") << "-18446744073709551615";
QTest::newRow("-2^64") << raw("\x3b\xff\xff\xff\xff""\xff\xff\xff\xff") << "-18446744073709551616";
QTest::newRow("false") << raw("\xf4") << "false";
QTest::newRow("true") << raw("\xf5") << "true";
@@ -618,16 +625,6 @@ void tst_ToJson::metaData_data()
QTest::newRow("2.^53-1") << raw("\xfb\x43\x3f\xff\xff""\xff\xff\xff\xff") << "\"t\":251";
QTest::newRow("2.^64-epsilon") << raw("\xfb\x43\xef\xff\xff""\xff\xff\xff\xff") << "\"t\":251";
// integers that are too precise for double
QTest::newRow("2^53+1") << raw("\x1b\0\x20\0\0""\0\0\0\1")
<< "\"t\":0,\"v\":\"+20000000000001\"";
QTest::newRow("INT64_MAX-1") << raw("\x1b\x7f\xff\xff\xff""\xff\xff\xff\xfe")
<< "\"t\":0,\"v\":\"+7ffffffffffffffe\"";
QTest::newRow("INT64_MAX+1") << raw("\x1b\x80\0\0\0""\0\0\0\1")
<< "\"t\":0,\"v\":\"+8000000000000001\"";
QTest::newRow("-2^53-1") << raw("\x3b\0\x20\0\0""\0\0\0\0")
<< "\"t\":0,\"v\":\"-20000000000000\"";
// simple values
QTest::newRow("simple0") << raw("\xe0") << "\"t\":224,\"v\":0";
QTest::newRow("simple19") << raw("\xf3") << "\"t\":224,\"v\":19";