*.*#
core
.qmake.cache
+.qmake.stash
.qmake.vars
.device.vars
tags
lib
src/cjson
src/doxygen.log
-!Makefile
+!/Makefile
.config
src/cborparser_dup_string.c \
src/cborpretty.c \
src/cbortojson.c \
- $(if $(open_memstream-pass),,src/open_memstream.c) \
#
CBORDUMP_SOURCES = tools/cbordump/cbordump.c
-include .config
+# if open_memstream is unavailable on the system, try to implement our own
+# version using funopen or fopencookie
+ifeq ($(open_memstream-pass),)
+ ifeq ($(funopen-pass)$(fopencookie-pass),)
+ CFLAGS += -DWITHOUT_OPEN_MEMSTREAM
+ $(warning warning: funopen and fopencookie unavailable, open_memstream can not be implemented and conversion to JSON will not work properly!)
+ else
+ TINYCBOR_SOURCES += src/open_memstream.c
+ endif
+endif
+
# json2cbor depends on an external library (cJSON)
ifneq ($(cjson-pass)$(system-cjson-pass),)
JSON2CBOR_SOURCES = tools/json2cbor/json2cbor.c
release: .git
$(MAKE) -f $(MAKEFILE) distcheck
+ifeq ($(VERSION),)
git -C $(SRCDIR). show HEAD:VERSION | \
perl -l -n -e '@_ = split /\./; print "$$_[0]." . ($$_[1] + 1)' > $(SRCDIR)VERSION
- git -C $(SRCDIR). commit -s -m "Update version number" VERSION
+else
+ echo "$(VERSION)" > VERSION
+endif
+ if test -n "`git diff VERSION`"; then \
+ git -C $(SRCDIR). commit -s -m "Update version number" VERSION; \
+ fi
{ echo "TinyCBOR release `cat $(SRCDIR)VERSION`"; \
echo; \
echo '# Write something nice about this release here'; \
} > $(SRCDIR).git/TAG_EDITMSG
@`git -C $(SRCDIR). var GIT_EDITOR` $(SRCDIR).git/TAG_EDITMSG
git -C $(SRCDIR). tag -a -F $(SRCDIR).git/TAG_EDITMSG $(GITTAGFLAGS) v`cat $(SRCDIR)VERSION`
- $(MAKE) -f $(MAKEFILE) dist
.PHONY: all check silentcheck configure install uninstall
.PHONY: mostlyclean clean distclean
--- /dev/null
+ALLTESTS = open_memstream funopen fopencookie gc_sections \
+ system-cjson cjson
+MAKEFILE := $(lastword $(MAKEFILE_LIST))
+OUT :=
+
+PROGRAM-open_memstream = extern int open_memstream(); int main() { return open_memstream(); }
+PROGRAM-funopen = extern int funopen(); int main() { return funopen(); }
+PROGRAM-fopencookie = extern int fopencookie(); int main() { return fopencookie(); }
+PROGRAM-gc_sections = int main() {}
+CCFLAGS-gc_sections = -Wl,--gc-sections
+
+PROGRAM-cjson = \#include <stdlib.h>\n
+PROGRAM-cjson += \#include <cJSON.h>\n
+PROGRAM-cjson += int main() { return cJSON_False; }
+CCFLAGS-cjson = -I$(dir $(MAKEFILE))src/cjson
+PROGRAM-system-cjson = $(PROGRAM-cjson)
+CCFLAGS-system-cjson = -lcJSON
+
+sink:
+ @echo >&2 Please run from the top-level Makefile.
+
+configure: $(foreach it,$(ALLTESTS),check-$(it))
+
+check-%:
+ @echo $(subst check-,,$@)-tested := 1 $(OUT)
+ $(if $(V),,@)if printf "$($(subst check-,PROGRAM-,$@))" | \
+ $(CC) -xc $($(subst check-,CCFLAGS-,$@)) -o /dev/null - $(if $(V),,>/dev/null 2>&1); \
+ then \
+ echo $(subst check-,,$@)-pass := 1 $(OUT); \
+ fi
--- /dev/null
+CFLAGS = -W3
+
+TINYCBOR_HEADERS = src\cbor.h src\cborjson.h
+TINYCBOR_SOURCES = \
+ src\cborerrorstrings.c \
+ src\cborencoder.c \
+ src\cborencoder_close_container_checked.c \
+ src\cborparser.c \
+ src\cborparser_dup_string.c \
+ src\cborpretty.c
+TINYCBOR_OBJS = \
+ src\cborerrorstrings.obj \
+ src\cborencoder.obj \
+ src\cborencoder_close_container_checked.obj \
+ src\cborparser_dup_string.obj \
+ src\cborpretty.obj
+
+all: lib\tinycbor.lib
+check: tests\Makefile lib\tinycbor.lib
+ cd tests & $(MAKE) check
+silentcheck:
+ cd tests & set TESTARGS=-silent & $(MAKE) -s check
+tests\Makefile: tests\tests.pro
+ qmake -o $@ $**
+
+lib\tinycbor.lib: $(TINYCBOR_OBJS)
+ -if not exist lib\NUL md lib
+ lib -nologo /out:$@ $**
+
+mostlyclean:
+ -del $(TINYCBOR_OBJS)
+clean: mostlyclean
+ -del lib\tinycbor.lib
+ if exist tests\Makefile (cd tests & $(MAKE) clean)
+distclean: clean
+ if exist tests\Makefile (cd tests & $(MAKE) distclean)
+
+{src\}.c{src\}.obj:
+ $(CC) -nologo $(CFLAGS) -Isrc -DTINYCBOR_VERSION="" -c -Fo$@ $<
+
/* errors in converting to JSON */
CborErrorJsonObjectKeyIsAggregate,
CborErrorJsonObjectKeyNotString,
+ CborErrorJsonNotImplemented,
CborErrorOutOfMemory = ~0U / 2 + 1,
CborErrorInternalError = ~0U
union {
uint8_t *ptr;
ptrdiff_t bytes_needed;
- };
+ } data;
const uint8_t *end;
size_t added;
int flags;
CBOR_INLINE_API size_t cbor_encoder_get_buffer_size(const CborEncoder *encoder, const uint8_t *buffer)
{
- return (size_t)(encoder->ptr - buffer);
+ return (size_t)(encoder->data.ptr - buffer);
}
CBOR_INLINE_API size_t cbor_encoder_get_extra_bytes_needed(const CborEncoder *encoder)
{
- return encoder->end ? 0 : (size_t)encoder->bytes_needed;
+ return encoder->end ? 0 : (size_t)encoder->data.bytes_needed;
}
/* Parser API */
if (!cbor_value_is_length_known(value))
return CborErrorUnknownLength;
uint64_t v = _cbor_value_extract_int64_helper(value);
- *length = v;
+ *length = (size_t)v;
if (*length != v)
return CborErrorDataTooLarge;
return CborNoError;
if (!cbor_value_is_length_known(value))
return CborErrorUnknownLength;
uint64_t v = _cbor_value_extract_int64_helper(value);
- *length = v;
+ *length = (size_t)v;
if (*length != v)
return CborErrorDataTooLarge;
return CborNoError;
if (!cbor_value_is_length_known(value))
return CborErrorUnknownLength;
uint64_t v = _cbor_value_extract_int64_helper(value);
- *length = v;
+ *length = (size_t)v;
if (*length != v)
return CborErrorDataTooLarge;
return CborNoError;
#define _BSD_SOURCE 1
#define _DEFAULT_SOURCE 1
+#ifndef __STDC_LIMIT_MACROS
+# define __STDC_LIMIT_MACROS 1
+#endif
+
#include "cbor.h"
#include "cborconstants_p.h"
#include "compilersupport_p.h"
*/
void cbor_encoder_init(CborEncoder *encoder, uint8_t *buffer, size_t size, int flags)
{
- encoder->ptr = buffer;
+ encoder->data.ptr = buffer;
encoder->end = buffer + size;
encoder->added = 0;
encoder->flags = flags;
static inline bool would_overflow(CborEncoder *encoder, size_t len)
{
ptrdiff_t remaining = (ptrdiff_t)encoder->end;
- remaining -= remaining ? (ptrdiff_t)encoder->ptr : encoder->bytes_needed;
+ remaining -= remaining ? (ptrdiff_t)encoder->data.ptr : encoder->data.bytes_needed;
remaining -= (ptrdiff_t)len;
return unlikely(remaining < 0);
}
static inline void advance_ptr(CborEncoder *encoder, size_t n)
{
if (encoder->end)
- encoder->ptr += n;
+ encoder->data.ptr += n;
else
- encoder->bytes_needed += n;
+ encoder->data.bytes_needed += n;
}
static inline CborError append_to_buffer(CborEncoder *encoder, const void *data, size_t len)
{
if (would_overflow(encoder, len)) {
if (encoder->end != NULL) {
- len -= encoder->end - encoder->ptr;
+ len -= encoder->end - encoder->data.ptr;
encoder->end = NULL;
- encoder->bytes_needed = 0;
+ encoder->data.bytes_needed = 0;
}
advance_ptr(encoder, len);
return CborErrorOutOfMemory;
}
- memcpy(encoder->ptr, data, len);
- encoder->ptr += len;
+ memcpy(encoder->data.ptr, data, len);
+ encoder->data.ptr += len;
return CborNoError;
}
if (ui < Value8Bit) {
*bufstart += shiftedMajorType;
} else {
- unsigned more = 0;
+ uint8_t more = 0;
if (ui > 0xffU)
++more;
if (ui > 0xffffU)
static CborError create_container(CborEncoder *encoder, CborEncoder *container, size_t length, uint8_t shiftedMajorType)
{
CborError err;
- container->ptr = encoder->ptr;
+ container->data.ptr = encoder->data.ptr;
container->end = encoder->end;
++encoder->added;
container->added = 0;
} else {
err = encode_number_no_update(container, length, shiftedMajorType);
}
- if (err && !isOomError(err))
- return err;
-
- return CborNoError;
+ return err;
}
/**
CborError cbor_encoder_close_container(CborEncoder *encoder, const CborEncoder *containerEncoder)
{
if (encoder->end)
- encoder->ptr = containerEncoder->ptr;
+ encoder->data.ptr = containerEncoder->data.ptr;
else
- encoder->bytes_needed = containerEncoder->bytes_needed;
+ encoder->data.bytes_needed = containerEncoder->data.bytes_needed;
encoder->end = containerEncoder->end;
if (containerEncoder->flags & CborIteratorFlag_UnknownLength)
return append_byte_to_buffer(encoder, BreakByte);
#define _BSD_SOURCE 1
#define _DEFAULT_SOURCE 1
+#ifndef __STDC_LIMIT_MACROS
+# define __STDC_LIMIT_MACROS 1
+#endif
+
#include "cbor.h"
#include "cborconstants_p.h"
#include "compilersupport_p.h"
*/
CborError cbor_encoder_close_container_checked(CborEncoder *encoder, const CborEncoder *containerEncoder)
{
- const uint8_t *ptr = encoder->ptr;
+ const uint8_t *ptr = encoder->data.ptr;
CborError err = cbor_encoder_close_container(encoder, containerEncoder);
if (containerEncoder->flags & CborIteratorFlag_UnknownLength || encoder->end == NULL)
return err;
/* check what the original length was */
uint64_t actually_added;
- err = extract_number(&ptr, encoder->ptr, &actually_added);
+ err = extract_number(&ptr, encoder->data.ptr, &actually_added);
if (err)
return err;
case CborErrorJsonObjectKeyNotString:
return _("conversion to JSON failed: key in object is not a string");
+ case CborErrorJsonNotImplemented:
+ return _("conversion to JSON failed: open_memstream unavailable");
case CborErrorInternalError:
return _("internal error");
#define _BSD_SOURCE 1
#define _DEFAULT_SOURCE 1
+#ifndef __STDC_LIMIT_MACROS
+# define __STDC_LIMIT_MACROS 1
+#endif
+
#include "cbor.h"
#include "cborconstants_p.h"
#include "compilersupport_p.h"
return err;
}
- *len = v;
+ *len = (size_t)v;
if (v != *len)
return CborErrorDataTooLarge;
return CborNoError;
if (unlikely(v > (unsigned) -(INT_MIN + 1)))
return CborErrorDataTooLarge;
- *result = v;
+ *result = (int)v;
*result = -*result - 1;
} else {
if (unlikely(v > (uint64_t)INT_MAX))
return CborErrorDataTooLarge;
- *result = v;
+ *result = (int)v;
}
return CborNoError;
#define _BSD_SOURCE 1
#define _DEFAULT_SOURCE 1
+#ifndef __STDC_LIMIT_MACROS
+# define __STDC_LIMIT_MACROS 1
+#endif
+
#include "cbor.h"
#include <stdlib.h>
#define _BSD_SOURCE 1
#define _DEFAULT_SOURCE 1
+#ifndef __STDC_LIMIT_MACROS
+# define __STDC_LIMIT_MACROS 1
+#endif
+
#include "cbor.h"
#include "compilersupport_p.h"
#include "math_support_p.h"
if (n < charsNeeded - 1)
return CborErrorInvalidUtf8TextString;
+ n -= charsNeeded - 1;
/* first continuation character */
uint8_t b = (uint8_t)*buffer++;
#define _DEFAULT_SOURCE 1
#define _GNU_SOURCE 1
#define _POSIX_C_SOURCE 200809L
+#ifndef __STDC_LIMIT_MACROS
+# define __STDC_LIMIT_MACROS 1
+#endif
+
#include "cbor.h"
#include "cborjson.h"
#include "compilersupport_p.h"
{
(void)flags; /* unused */
(void)type; /* unused */
+#ifdef WITHOUT_OPEN_MEMSTREAM
+ (void)key; /* unused */
+ (void)it; /* unused */
+ return CborErrorJsonNotImplemented;
+#else
size_t size;
FILE *memstream = open_memstream(key, &size);
if (unlikely(fclose(memstream) < 0 || *key == NULL))
return CborErrorInternalError;
return err;
+#endif
}
static CborError array_to_json(FILE *out, CborValue *it, int flags, ConversionStatus *status)
# define inline CBOR_INLINE
#endif
+#ifndef STRINGIFY
#define STRINGIFY(x) STRINGIFY2(x)
+#endif
#define STRINGIFY2(x) #x
-#ifndef UINT32_MAX
-/* C99 requires it in stdint.h, but some systems lack it */
-# define UINT32_MAX (0xffffffffU)
+#if !defined(UINT32_MAX) || !defined(INT64_MAX)
+/* C89? We can define UINT32_MAX portably, but not INT64_MAX */
+# error "Your system has stdint.h but that doesn't define UINT32_MAX or INT64_MAX"
#endif
+
#ifndef DBL_DECIMAL_DIG
/* DBL_DECIMAL_DIG is C11 */
# define DBL_DECIMAL_DIG 17
#endif
#ifdef __GNUC__
+#ifndef likely
# 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)
/* underflow, make zero */
return 0;
}
- return sign | ((exp + 15) << 10) | mant;
+
+ /* safe cast here as bit operations above guarantee not to overflow */
+ return (unsigned short)(sign | ((exp + 15) << 10) | mant);
#endif
}
Makefile
debug
+moc_predefs.h
release
target_wrapper.*
+
+# The executables
+cpp/cpp
+cpp/cpp.exe
+encoder/encoder
+encoder/encoder.exe
+parser/parser
+parser/parser.exe
+tojson/tojson
+tojson/tojson.exe
QFETCH(QByteArray, output);
QByteArray buffer(output.length(), Qt::Uninitialized);
- for (int len = 0; len < output.length() - 1; ++len) {
+ for (int len = 0; len < output.length(); ++len) {
CborEncoder encoder;
cbor_encoder_init(&encoder, reinterpret_cast<quint8 *>(buffer.data()), len, 0);
QCOMPARE(int(encodeVariant(&encoder, input)), int(CborErrorOutOfMemory));
QTest::newRow("textstring256") << raw("\x79\1\0") + QByteArray(256, '3')
<< '"' + QString(256, '3') + '"';
+ // some strings with UTF-8 content
+ // we had a bug in the pretty dumper - see issue #54
+ QTest::newRow("textstringutf8-2char") << raw("\x62\xc2\xa0") << "\"\\u00A0\"";
+ QTest::newRow("textstringutf8-2char2") << raw("\x64\xc2\xa0\xc2\xa9") << "\"\\u00A0\\u00A9\"";
+ QTest::newRow("textstringutf8-3char") << raw("\x63\xe2\x88\x80") << "\"\\u2200\"";
+ QTest::newRow("textstringutf8-4char") << raw("\x64\xf0\x90\x88\x83") << "\"\\uD800\\uDE03\"";
+
// strings with overlong length
QTest::newRow("emptybytestring*1") << raw("\x58\x00") << "h''";
QTest::newRow("emptytextstring*1") << raw("\x78\x00") << "\"\"";
return err;
*encoder = container; // restore state
- encoder->ptr = newbuffer + (container.ptr - buffer);
+ encoder->data.ptr = newbuffer + (container.data.ptr - buffer);
encoder->end = newbuffer + buffersize;
buffer = newbuffer;
goto encode_double;
return EXIT_FAILURE;
}
- fwrite(buffer, 1, encoder.ptr - buffer, stdout);
+ fwrite(buffer, 1, encoder.data.ptr - buffer, stdout);
free(buffer);
return EXIT_SUCCESS;
}