118 Commits
Author SHA1 Message Date
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 7b607eb5e8 Remove the old Makefile and qmake buildsystem files
Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2025-03-18 17:14:19 -07:00
Thiago Macieira 814b8eac22 CMake: add the other, Qt-based tests
Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2025-03-18 16:43:48 -07:00
Thiago Macieira 0e2b305e3f tst_Encoder: stop using QVariant::Type in favour of QMetaType::Type
The former has been deprecated since Qt 6.0 and produces warnings when
used.

Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2025-03-18 15:21:51 -07:00
Samuel Debionne 37d1a6dee3 Add CMake support 2025-03-12 16:49:17 -07:00
Thiago Macieira c60b710ff0 tst_Parser: fix build: define CBOR_PARSER_MAX_RECURSIONS
I don't know how this was compiling.

Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2025-03-12 15:39:02 -07:00
Thiago Macieira 4050fa58c2 tst_Parser: add some testing rows for floating point data
Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2025-03-12 15:21:35 -07:00
Thiago Macieira 1577f3b538 tst_ToJson: add a test for the ExpectedBase64url tag too
Just to confirm it works.

Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2025-03-12 15:21:35 -07:00
Thiago Macieira 6e3333ebe0 Encoder: add unit test for cbor_encode_raw
Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2025-03-12 15:21:35 -07:00
Thiago Macieira e072bc1d78 CBOR-to-JSON: do properly escape JSON strings
We hadn't bothered, as this was just example-like code to show how one
could convert from CBOR to JSON. But as it was added to the library (no
extra dependency), we should Do The Right Thing (DTRT) and escape.

This patch could have used cbor_value_to_pretty() to print the string,
which has better support for UTF-8 escaping and thus checks for UTF-8
correctness, but that would make map_to_json()'s metadata functionality
much more complex, especially since we cannot rely on open_memstream()
always being available. Therefore, we are partially duplicating
cborpretty.c's utf8EscapedDump().

Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2025-03-11 14:42:41 -07:00
Thiago Macieira e6924451a9 CBOR-to-JSON: Limit how deep we process nested containers
1024 levels will probably be good enough for everyone, like
cborparser.c. For those for whom it isn't, they can set the limit during
the build.

We already had this for the plain parser, so TinyCBOR wouldn't cause a
stack overflow in case of a malformed stream (intentionally or not) when
simply parsing and advancing over the stream. This same protection
wasn't applied to the content converting from CBOR to JSON.

Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2025-03-11 10:55:26 -07:00
Thiago Macieira 53ff130af9 tst_Parser: replace Q_ASSERT(false) with Q_UNREACHABLE()
`Q_ASSERT()` disappears in release mode, leading Clang to print a static
analysis warning about an impossible condition:
```
tst_parser.cpp:251:16: warning: variable 'err' is used uninitialized whenever 'if' condition is false [-Wsometimes-uninitialized]
  251 |     } else if (ourType == CborTextStringType) {
      |                ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
tst_parser.cpp:263:12: note: uninitialized use occurs here
  263 |     return err;
      |            ^~~
tst_parser.cpp:251:12: note: remove the 'if' if its condition is always true
```

`Q_UNREACHABLE()` becomes a plain `__builtin_unreachable()` in release
mode.

Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2025-02-13 17:19:28 -08:00
Thiago Macieira 4df5e4f700 Tests: disable the C90 test
We don't support this any more.
```
../../src/cbor.h:255:69: error: '_Bool' is a C99 extension [-Werror,-Wc99-extensions]
CBOR_INLINE_API CborError cbor_encode_boolean(CborEncoder *encoder, bool value)
                                                                    ^
```

Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2024-05-01 18:29:45 -07:00
Martin Jansa fd2f6cf9a7 tinycbor: fix build with gcc-13
* fixes:
  http://errors.yoctoproject.org/Errors/Details/701753/

qtbase/6.5.0-r0/git/tests/auto/corelib/serialization/qcborstreamwriter/../../../../../src/3rdparty/tinycbor/tests/encoder/data.cpp:242:90: error: invalid user-defined conversion from 'float' to 'const qfloat16&' [-fpermissive]
  242 |     QTest::newRow("nan_f16") << raw("\xf9\x7e\0") << QVariant::fromValue<qfloat16>(myNaNf());
      |                                                                                    ~~~~~~^~
n file included from TOPDIR/tmp-glibc/work/core2-64-oe-linux/qtbase/6.5.0-r0/image/usr/include/QtCore/qmetatype.h:14,
                 from TOPDIR/tmp-glibc/work/core2-64-oe-linux/qtbase/6.5.0-r0/image/usr/include/QtTest/qtestcase.h:11,
                 from TOPDIR/tmp-glibc/work/core2-64-oe-linux/qtbase/6.5.0-r0/image/usr/include/QtTest/qtest.h:13,
                 from TOPDIR/tmp-glibc/work/core2-64-oe-linux/qtbase/6.5.0-r0/image/usr/include/QtTest/QTest:1,
                 from TOPDIR/tmp-glibc/work/core2-64-oe-linux/qtbase/6.5.0-r0/git/tests/auto/corelib/serialization/qcborstreamwriter/tst_qcborstreamwriter.cpp:4:
TOPDIR/tmp-glibc/work/core2-64-oe-linux/qtbase/6.5.0-r0/image/usr/include/QtCore/qfloat16.h:81:22: note: candidate is: 'constexpr qfloat16::qfloat16(NativeType)' (near match)
   81 |     constexpr inline qfloat16(NativeType f) : f(f) {}
      |                      ^~~~~~~~
TOPDIR/tmp-glibc/work/core2-64-oe-linux/qtbase/6.5.0-r0/image/usr/include/QtCore/qfloat16.h:81:22: note:   conversion of argument 1 would be ill-formed:
TOPDIR/tmp-glibc/work/core2-64-oe-linux/qtbase/6.5.0-r0/git/tests/auto/corelib/serialization/qcborstreamwriter/../../../../../src/3rdparty/tinycbor/tests/encoder/data.cpp:242:90: warning: converting to 'qfloat16::NativeType' {aka '_Float16'} from 'float' with greater conversion rank
  242 |     QTest::newRow("nan_f16") << raw("\xf9\x7e\0") << QVariant::fromValue<qfloat16>(myNaNf());
      |                                                                                    ~~~~~~^~
TOPDIR/tmp-glibc/work/core2-64-oe-linux/qtbase/6.5.0-r0/git/tests/auto/corelib/serialization/qcborstreamwriter/../../../../../src/3rdparty/tinycbor/tests/encoder/data.cpp:242:90: warning: converting to 'qfloat16::NativeType' {aka '_Float16'} from 'float' with greater conversion rank
TOPDIR/tmp-glibc/work/core2-64-oe-linux/qtbase/6.5.0-r0/image/usr/include/QtCore/qfloat16.h:81:42: note:   initializing argument 1 of 'constexpr qfloat16::qfloat16(NativeType)'
   81 |     constexpr inline qfloat16(NativeType f) : f(f) {}
      |                               ~~~~~~~~~~~^
In file included from TOPDIR/tmp-glibc/work/core2-64-oe-linux/qtbase/6.5.0-r0/image/usr/include/QtCore/qmetaobject.h:9,
                 from TOPDIR/tmp-glibc/work/core2-64-oe-linux/qtbase/6.5.0-r0/image/usr/include/QtTest/qtestcase.h:12:
TOPDIR/tmp-glibc/work/core2-64-oe-linux/qtbase/6.5.0-r0/image/usr/include/QtCore/qvariant.h:435:43: note:   initializing argument 1 of 'static std::enable_if_t<(is_copy_constructible_v<T> && is_destructible_v<T>), QVariant> QVariant::fromValue(const T&) [with T = qfloat16; std::enable_if_t<(is_copy_constructible_v<T> && is_destructible_v<T>), QVariant> = QVariant]'
  435 |     static inline auto fromValue(const T &value)
      |                                  ~~~~~~~~~^~~~~

Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2023-11-26 17:27:09 -07:00
Piotr Wierciński 04b306c447 Use internal linkage for data.cpp files
The Qt uses test batching and potentially encoder/data.cpp
and parser/data.cpp can end up in the same translation unit.
This can be problematic as they declare symbols with the
same names.
Change both files to use internal linkage in order to avoid
symbols clashing.
2023-08-14 07:58:57 -07:00
Marc Mutz aee4f97f52 tst_Encoder: port away from Q_FOREACH
Qt is defaulting to QT_NO_FOREACH these days, so make sure we
integrate nicely with downstream and fix the single Q_FOREACH/foreach
user, in tst_encoder.cpp.

Unfortunately, the container's initialization code doesn't exactly
lend itself to making the container const (not even IILE
(Immediately-Invoked Lambda Expression) would help here, due to the
interdependency with `len`), so the idiomatic solution would be to use
std::as_const()/qAsConst().

The former is available from C++17, which we don't require, yet, and
the latter is not available under QT_NO_AS_CONST (the default for Qt
these days), so grab the nettle and implement a t17::as_const() that
switches between a manual implementation of std::as_const and the real
thing, depending on __cpp_lib_as_const. The `t17` here mimicks the qNN
(q20::remove_cvref_t/q23::forward_like/etc) mechanism used in Qt
itself for backports, with s/q/t/ because ... _T_inyCbor.

The t17 implementation is local to tst_encoder.cpp, but can easily be
extracted into a separate header once more users emerge.
2023-08-07 09:08:56 -07:00
Thiago Macieira e27261ed5e Parser/Validation: Add a test for good data
We had tests for cbor_validate* API for the errors it would find, but not
that it did correctly reported CborNoError where no errors were
expected.

Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2022-09-07 10:47:25 -07:00
Thiago Macieira 10f739921d .gitignore: ignore the c90 test too 2021-09-03 13:19:19 -07:00
Thiago Macieira 8adc3cf3f4 Parser: modify the zero-copy string API
Instead of just one function (_cbor_value_get_string_chunk), we now have
_cbor_value_begin_string_iteration, _cbor_value_finish_string_iteration,
_cbor_value_get_string_chunk_size, and _cbor_value_get_string_chunk.

The "begin" function positions the pointer at the first chunk. That's
what makes "get_size" possible, since it doesn't need to check for any
state. The "finish" funcntion allows the caller to distinguish an error
parsing the string from an error parsing the next value.

Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2021-09-03 13:08:25 -07:00
Thiago Macieira 5159ec39df Parser: add a way to parse the current element again
We need to re-parse if the input buffer was too short to read the
current element's information. When that happens, the current element
will be CborInvalidType, so we can't easily resume.

Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2021-09-03 13:08:25 -07:00
Thiago Macieira 87a7a9308c Move the testdata out to a separate .cpp so they can be reused
Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2021-09-03 13:08:25 -07:00
Thiago Macieira e26ff9a2dc WIP Initial API for delegated streaming out
Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2021-09-03 13:08:25 -07:00
Thiago Macieira 34c84520a7 WIP Initial API for delegated streaming in
Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2021-09-03 13:08:25 -07:00
Thiago Macieira d503c111a2 Pretty & Validation: remove the last direct accesses to CborValue::ptr
Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2021-09-03 13:08:25 -07:00
Thiago Macieira 2d8e73ba6c Tests: Catch an earlier QCOMPARE failure in compare()
QCOMPARE macro has a return in case of failure. If a test fails inside
the encodeOne function, we log that error, but were proceeding to
perform more tests (which could fail again and produce more errors).

Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2021-09-03 13:08:25 -07:00
Thiago Macieira 7dce551629 Merge branch 'master' into dev 2021-01-13 09:05:42 -08:00
Thiago Macieira 4a13b3ed3e parser: add a test that the string copy functions properly terminate
Or don't terminate, as the case may be.

Relates to #194.

Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2021-01-13 00:25:18 -03:00
Thiago Macieira 755f9ef932 Parser: validate that maps have both key and value items
If a map end (Break byte) occurs before we've read the concrete item for
the value, then the map is invalid.

Fixes #167

Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2019-10-22 08:11:21 -07:00
Thiago Macieira 9a13e9252d Merge remote-tracking branch 'origin/master' into dev 2019-04-04 12:40:39 -07:00
Thiago Macieira e52b1d5bec Tests: Catch an earlier QCOMPARE failure in compare()
QCOMPARE macro has a return in case of failure. If a test fails inside
the encodeOne function, we log that error, but were proceeding to
perform more tests (which could fail again and produce more errors).

Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2019-04-04 12:39:00 -07:00
Thiago Macieira 878eb01b96 Tests: remove useless comment
It's implemented.

Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2019-04-04 10:18:16 -07:00
Thiago Macieira 6643c174e4 Merge branch 'master' into dev 2019-03-15 10:12:23 -07:00
phirsov f1db0abccd enhancement #149 implemented: access half-precision floating point data as single float
Motivation: half-precision floating point format is used to minimize storage
and traffic mostly.  Application level manipulates with single and double
precision usually. So, two routines added to public API to encode/decode given
single precision value in the half precision format

Signed-off-by: S.Phirsov
Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2019-03-15 10:11:00 -07:00
Thiago Macieira 0362274505 Parser: apply the same memory-check update
See previous commit for more details. This just applies the same
technique using malloc/mmap to the the rest of the parser tests.

Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2019-03-06 09:50:04 -08:00
Thiago Macieira 57b66a8353 Validation: fix out-of-bounds access when content ends in a string
We can only validate_number() if we know that we have a number to
validate in the first place. If we've reached the end of our string, the
content that follows is not necessarily a number (it could be a Break
byte). More importantly, we could reach the end of the buffer.

This issue was masked by the way we provided data to the parser. It
always came from read-only memory becausee of QByteArray::fromRawData(),
so valgrind never caught any issues. Using QByteArray directly wouldn't
have helped because it always inserts a terminating null byte, which
always validates as a correct number (unsigned 0) and fails to trigger
valgrind.

So we need to use malloc() directly to make Valgrind complain. And there
was already a test that did:

==26543== Invalid read of size 1
==26543==    at 0x483EA10: memmove (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
==26543==    by 0x43CEEA: read_bytes_unchecked (cborinternal_p.h:239)
==26543==    by 0x43CFEC: extract_number_checked (cborinternal_p.h:286)
==26543==    by 0x43D3E9: validate_number (cborvalidation.c:304)
==26543==    by 0x43DC7B: validate_value (cborvalidation.c:551)
==26543==    by 0x43DE8C: cbor_value_validate (cborvalidation.c:645)
==26543==    by 0x4328D2: tst_Parser::strictValidation() (tst_parser.cpp:1637)
==26543==    by 0x434632: tst_Parser::qt_static_metacall(QObject*, QMetaObject::Call, int, void**) (tst_parser.moc:291)
==26543==    by 0x4C0B36D: QMetaMethod::invoke(QObject*, Qt::ConnectionType, QGenericReturnArgument, QGenericArgument, QGenericArgument, QGenericArgument, QGenericArgument, QGenericArgument, QGenericArgument, QGenericArgument, QGenericArgument, QGenericArgument, QGenericArgument) const (qmetaobject.cpp:2310)
==26543==    by 0x48673E9: QMetaMethod::invoke(QObject*, Qt::ConnectionType, QGenericArgument, QGenericArgument, QGenericArgument, QGenericArgument, QGenericArgument, QGenericArgument, QGenericArgument, QGenericArgument, QGenericArgument, QGenericArgument) const (qmetaobject.h:122)
==26543==    by 0x4860256: QTest::TestMethods::invokeTestOnData(int) const (qtestcase.cpp:922)
==26543==    by 0x4860D4B: QTest::TestMethods::invokeTest(int, char const*, QTest::WatchDog*) const (qtestcase.cpp:1121)
==26543==  Address 0x61c4db1 is 0 bytes after a block of size 1 alloc'd
==26543==    at 0x483777F: malloc (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
==26543==    by 0x403891: ParserWrapper::allocateMemory(unsigned long) (tst_parser.cpp:181)
==26543==    by 0x436898: ParserWrapper::init(QByteArray const&) (tst_parser.cpp:126)
==26543==    by 0x432712: tst_Parser::strictValidation() (tst_parser.cpp:1634)
==26543==    by 0x434632: tst_Parser::qt_static_metacall(QObject*, QMetaObject::Call, int, void**) (tst_parser.moc:291)
==26543==    by 0x4C0B36D: QMetaMethod::invoke(QObject*, Qt::ConnectionType, QGenericReturnArgument, QGenericArgument, QGenericArgument, QGenericArgument, QGenericArgument, QGenericArgument, QGenericArgument, QGenericArgument, QGenericArgument, QGenericArgument, QGenericArgument) const (qmetaobject.cpp:2310)
==26543==    by 0x48673E9: QMetaMethod::invoke(QObject*, Qt::ConnectionType, QGenericArgument, QGenericArgument, QGenericArgument, QGenericArgument, QGenericArgument, QGenericArgument, QGenericArgument, QGenericArgument, QGenericArgument, QGenericArgument) const (qmetaobject.h:122)
==26543==    by 0x4860256: QTest::TestMethods::invokeTestOnData(int) const (qtestcase.cpp:922)
==26543==    by 0x4860D4B: QTest::TestMethods::invokeTest(int, char const*, QTest::WatchDog*) const (qtestcase.cpp:1121)
==26543==    by 0x4862083: QTest::TestMethods::invokeTests(QObject*) const (qtestcase.cpp:1465)
==26543==    by 0x4862C14: QTest::qRun() (qtestcase.cpp:1903)
==26543==    by 0x48626C3: QTest::qExec(QObject*, int, char**) (qtestcase.cpp:1792)
==26543==
PASS   : tst_Parser::strictValidation(bytearray-0)

This commit goes further and makes it so an out-of-bounds access will
cause a pagefault.

Fixes #156.

Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2019-03-05 20:01:37 -08:00
Thiago Macieira 2421690d44 Fix #137: off-by-one error in UTF-8 decoding
I ported this from code I had written for Qt, where the subtraction was
correct. Qt's code is roughly:

    uchar b = *src++;
    ...
    int bytesAvailable = Traits::availableBytes(src, end);
    if (Q_UNLIKELY(bytesAvailable < charsNeeded - 1)) {

Which means src was advanced by the time we call Traits::availableBytes,
meaning that call returns the number of continuation bytes only. Our
code was:

    ptrdiff_t n = end - *buffer;
    ...
    uc = *(*buffer)++;
    ...
    if (n < charsNeeded - 1)

Which means our n is the total number of bytes, including the first
byte.

Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2018-09-21 09:41:57 -07:00
Thiago Macieira dd2fa30323 Merge branch 'master' into dev 2018-08-13 21:05:09 -07:00
Thiago Macieira cf222ff986 Make the c90 test pass on Mac and on Windows
On the Mac, the Clang compiler complains about our (required) use of
uint64_t, which is typedef'ed to long long. That type didn't exist in
C90.

On Windows, I forgot the CONFIG += console, resulting in

 error LNK2019: unresolved external symbol _WinMain@16 referenced in function "int __cdecl invoke_main(void)" (?invoke_main@@YAHXZ)

Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2018-07-08 11:48:31 -07:00
Thiago Macieira 5356c1de23 Oops, enable the test too..
Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2018-07-08 11:16:12 -07:00
Thiago Macieira 85e1c18f41 Add a set of tests to ensure that the cbor.h remains C90-compatible
Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2018-07-08 11:10:14 -07:00
Thiago Macieira c3c0f7ea31 Merge branch 'master' into dev
Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2018-02-05 18:11:54 -08:00
Thiago Macieira edd2b9e1fd Revert "Parser: remove the cbor_value_get_xxxx_string_chunk() API"
This reverts commit 6587c3e1d25670d2da2514a6f1261dd409c854f0. Bringing
the API back in 0.6, but it'll change before the release.

Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2018-02-05 18:05:35 -08:00
Thiago Macieira f5a172b976 Docs and comments updates
Many thanks to Edward Welbourne for pointing them all out.

Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2018-02-05 18:02:52 -08:00
Thiago Macieira 1f84b8361a Tests: fix the checking if the current test failed
The `compareFailed` variable was never initialised or set to anything.

Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2018-02-05 15:06:30 -08:00
Thiago Macieira 8c940d264a Pretty: fix typo in enum name
Will keep the misspelt name for a few releases and remove later.

Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2018-02-04 15:50:07 -08:00
Thiago Macieira 5515a99434 Parser: remove the cbor_value_get_xxxx_string_chunk() API
It's really good, but I need to redesign it in order to support the
chained buffers found in Zephyr[1][2] and Mynewt. I'll bring it back in
0.6 when I introduce support for parsing directly from chained buffers
too.

[1] http://docs.zephyrproject.org/api/networking.html#network-buffers
[2] https://github.com/zephyrproject-rtos/zephyr/blob/master/include/net/buf.h

Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2018-01-30 12:04:05 -08:00
Thiago Macieira 497066ee87 Encoder: Fix off-by-one error encoding negative numbers
The documentation said we encoded the negative value equivalent to the
passed absolute value. That means encode_number() requires the
subtraction.

This commit takes the opportunity to unit-test the rest of the integer
API in the parser.

Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2018-01-23 10:36:41 -08:00
Thiago Macieira e5843df411 Tests: change a few more QCOMPARE to print the error message.
Commit 36bdbfb854 did not catch all cases.

Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2018-01-13 08:41:07 -08:00
Thiago Macieira cc2bfbb209 Encoder: Change the way we reckon the number of items added
Instead of counting forward the number of items added, which meant we
couldn't know in cbot_encoder_close_container() whether we had added
enough, let's count backwards. The number is offset by 1 so we should be
at 1 if we added exactly as many items as we had expected to. Zero means
we added too many. Any other number means we added too few.

Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2018-01-13 14:37:40 -02:00
Thiago Macieira ee63f791be Pretty: add the ability to stream out to a generic thing
Instead of always requiring FILE *. This does mean a slight code size
increase, since we now have to pass an extra parameter down the function
stack, plus we're making indirect calls, but it's worth it.

Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2018-01-02 17:05:44 -06:00