Skip to content

Commit 217261a

Browse files
committed
support variable offset sizes for real
1 parent b561f67 commit 217261a

20 files changed

+287
-110
lines changed

CMakeLists.txt

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,23 @@ option (FLATCC_ALLOW_WERROR "allow -Werror to be configured" ON)
103103
# try using this option.
104104
option (FLATCC_IGNORE_CONST_COND "silence const condition warnings" OFF)
105105

106+
# Enforces parsing of identifier size per the spec of 4 characters.
107+
# FLATBUFFERS_STRICT_IDENTIFIER_SIZE has no effect if the identifier
108+
# size is 4.
109+
# Note: Encoded identifiers will still be padded when FLATCC_OFFSET_SIZE
110+
# is greater than 4 and truncated when offset size is less than 4.
111+
option (FLATBUFFERS_STRICT_IDENTIFIER_SIZE
112+
"enforce identifier size being offset size" OFF)
113+
114+
# Relaxes the size specification for file identifier sizes to allow them
115+
# to be padded if shorter or truncated if longer.
116+
# The restriction prohibits interpreting schema oriented at other offset
117+
# sizes, so this is implied when FLATCC_OFFSET_SIZE is not 4.
118+
# This option requires FLATBUFFERS_STRICT_IDENTIFIER_SIZE to be OFF.
119+
cmake_dependent_option (FLATBUFFERS_RELAXED_IDENTIFIER_SIZE
120+
"identifier will be padded if too short or truncated if too long"
121+
OFF "FLATBUFFERS_STRICT_IDENTIFIER_SIZE" OFF)
122+
106123
if (FLATCC_RTONLY)
107124
set(FLATCC_TEST off)
108125
endif()
@@ -179,7 +196,7 @@ if (CMAKE_C_COMPILER_ID MATCHES "Clang")
179196
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pedantic -Wall -Wextra")
180197
# Fix broken C++ alignas - either will do
181198
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
182-
#set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DPORTABLE_PATCH_CPLUSPLUS_STDALIGN")
199+
#set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DPORTABLE_PATCH_CPLUSPLUS_STDALIGN")
183200
if (FLATCC_ALLOW_WERROR)
184201
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Werror")
185202
endif()
@@ -219,7 +236,7 @@ elseif (CMAKE_C_COMPILER_ID STREQUAL "GNU")
219236
# structs, but these are valid as zero-paddded, not zero terminated.
220237
#
221238
# -Wno-format-overflow:
222-
# GCC 9 warns on mistakenly assumed NULL string when
239+
# GCC 9 warns on mistakenly assumed NULL string when
223240
# printing from a required FlatBuffer string field.
224241
#
225242
message(STATUS "Disabling GNU C compiler warnings: -Wstringop-truncation -Wno-format-overflow")
@@ -294,11 +311,20 @@ if (FLATCC_PORTABLE)
294311
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DFLATCC_PORTABLE")
295312
endif()
296313

297-
298314
if (DEFINED FLATCC_OFFSET_SIZE)
299315
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DFLATCC_OFFSET_SIZE=${FLATCC_OFFSET_SIZE}")
300316
endif()
301317

318+
if (DEFINED FLATCC_VOFFSET_SIZE)
319+
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DFLATCC_VOFFSET_SIZE=${FLATCC_VOFFSET_SIZE}")
320+
endif()
321+
322+
if (DEFINED FLATCC_OFFSET_SIZE AND NOT FLATCC_OFFSET_SIZE EQUAL 4 AND NOT DEFINED FLATBUFFERS_STRICT_IDENTIFIER_SIZE)
323+
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DFLATBUFFERS_RELAXED_IDENTIFIER_SIZE")
324+
elseif(DEFINED FLATBUFFERS_RELAXED_IDENTIFIER_SIZE)
325+
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DFLATBUFFERS_RELAXED_IDENTIFIER_SIZE")
326+
endif()
327+
302328
if (CLANG_VERSION)
303329
message(STATUS "CLANG_VERSION: ${CLANG_VERSION}")
304330
endif()

include/flatcc/flatcc_identifier.h

Lines changed: 56 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -66,19 +66,41 @@ static inline void flatbuffers_identifier_from_type_hash(flatbuffers_thash_t typ
6666
out_identifier[0] = (char)(type_hash & 0xff);
6767
type_hash >>= 8;
6868
out_identifier[1] = (char)(type_hash & 0xff);
69+
70+
#if FLATBUFFERS_THASH_WIDTH > 16
6971
type_hash >>= 8;
7072
out_identifier[2] = (char)(type_hash & 0xff);
7173
type_hash >>= 8;
7274
out_identifier[3] = (char)(type_hash & 0xff);
75+
#endif
76+
77+
#if FLATBUFFERS_THASH_WIDTH > 32
78+
type_hash >>= 8;
79+
out_identifier[4] = (char)(type_hash & 0xff);
80+
type_hash >>= 8;
81+
out_identifier[5] = (char)(type_hash & 0xff);
82+
type_hash >>= 8;
83+
out_identifier[6] = (char)(type_hash & 0xff);
84+
type_hash >>= 8;
85+
out_identifier[7] = (char)(type_hash & 0xff);
86+
#endif
7387
}
7488

7589
/* Native integer encoding of file identifier. */
7690
static inline flatbuffers_thash_t flatbuffers_type_hash_from_identifier(const flatbuffers_fid_t identifier)
7791
{
7892
uint8_t *p = (uint8_t *)identifier;
7993

80-
return identifier ?
81-
(uint32_t)p[0] + (((uint32_t)p[1]) << 8) + (((uint32_t)p[2]) << 16) + (((uint32_t)p[3]) << 24) : 0;
94+
return !identifier ? 0 :
95+
96+
#if FLATBUFFERS_THASH_WIDTH == 16
97+
(uint16_t)p[0] + (((uint16_t)p[1]) << 8);
98+
#elif FLATBUFFERS_THASH_WIDTH == 32
99+
(uint32_t)p[0] + (((uint32_t)p[1]) << 8) + (((uint32_t)p[2]) << 16) + (((uint32_t)p[3]) << 24);
100+
#elif FLATBUFFERS_THASH_WIDTH == 64
101+
(uint64_t)p[0] + (((uint64_t)p[1]) << 8) + (((uint64_t)p[2]) << 16) + (((uint64_t)p[3]) << 24) +
102+
(((uint64_t)p[4]) << 32) + (((uint64_t)p[5]) << 40) + (((uint64_t)p[6]) << 48) + (((uint64_t)p[7]) << 56);
103+
#endif
82104
}
83105

84106
/*
@@ -91,14 +113,31 @@ static inline flatbuffers_thash_t flatbuffers_type_hash_from_string(const char *
91113
flatbuffers_thash_t h = 0;
92114
const uint8_t *p = (const uint8_t *)identifier;
93115

116+
if (!p) return 0;
117+
94118
if (!p[0]) return h;
95119
h += ((flatbuffers_thash_t)p[0]);
96120
if (!p[1]) return h;
97121
h += ((flatbuffers_thash_t)p[1]) << 8;
122+
123+
#if FLATBUFFERS_THASH_WIDTH > 16
98124
if (!p[2]) return h;
99125
h += ((flatbuffers_thash_t)p[2]) << 16;
100-
/* No need to test for termination here. */
126+
if (!p[3]) return h;
101127
h += ((flatbuffers_thash_t)p[3]) << 24;
128+
#endif
129+
130+
#if FLATBUFFERS_THASH_WIDTH > 32
131+
if (!p[4]) return h;
132+
h += ((flatbuffers_thash_t)p[4]) << 32;
133+
if (!p[5]) return h;
134+
h += ((flatbuffers_thash_t)p[5]) << 40;
135+
if (!p[6]) return h;
136+
h += ((flatbuffers_thash_t)p[6]) << 48;
137+
if (!p[7]) return h;
138+
h += ((flatbuffers_thash_t)p[7]) << 56;
139+
#endif
140+
102141
return h;
103142
}
104143

@@ -125,21 +164,31 @@ static inline void flatbuffers_identifier_from_name(const char *name, flatbuffer
125164
* additional information and just complicates matters. Furthermore, the
126165
* unmodified type hash has the benefit that it can seed a child namespace.
127166
*/
128-
static inline uint32_t flatbuffers_disperse_type_hash(flatbuffers_thash_t type_hash)
167+
static inline flatbuffers_thash_t flatbuffers_disperse_type_hash(flatbuffers_thash_t type_hash)
129168
{
169+
flatbuffers_thash_t x = type_hash;
170+
171+
#if FLATBUFFERS_THASH_WIDTH == 32
130172
/* http://stackoverflow.com/a/12996028 */
131-
uint32_t x = type_hash;
132173

133174
x = ((x >> 16) ^ x) * UINT32_C(0x45d9f3b);
134175
x = ((x >> 16) ^ x) * UINT32_C(0x45d9f3b);
135176
x = ((x >> 16) ^ x);
177+
#elif FLATBUFFERS_THASH_WIDTH == 64
178+
/* http://stackoverflow.com/a/12996028 */
179+
180+
x = (x ^ (x >> 30)) * UINT64_C(0xbf58476d1ce4e5b9);
181+
x = (x ^ (x >> 27)) * UINT64_C(0x94d049bb133111eb);
182+
x = x ^ (x >> 31);
183+
#endif
184+
136185
return x;
137186
}
138187

139188

140189
/* We have hardcoded assumptions about identifier size. */
141-
static_assert(sizeof(flatbuffers_fid_t) == 4, "unexpected file identifier size");
142-
static_assert(sizeof(flatbuffers_thash_t) == 4, "unexpected type hash size");
190+
//static_assert(sizeof(flatbuffers_fid_t) == 4, "unexpected file identifier size");
191+
//static_assert(sizeof(flatbuffers_thash_t) == 4, "unexpected type hash size");
143192

144193
#ifdef __cplusplus
145194
}

include/flatcc/flatcc_json_parser.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,7 @@ static inline const char *flatcc_json_parser_string_end(flatcc_json_parser_t *ct
168168
* and raise errors according to overflow/underflow runtime flags. Zero
169169
* and truncate as needed. A trailing zero is not inserted if the input
170170
* is at least the same length as the char array.
171-
*
171+
*
172172
* Runtime flags: `skip_array_overflow`, `pad_array_underflow`.
173173
*/
174174
const char *flatcc_json_parser_char_array(flatcc_json_parser_t *ctx,
@@ -875,15 +875,15 @@ const char *flatcc_json_parser_union_type_vector(flatcc_json_parser_t *ctx,
875875
* `flags` default to 0. See also `flatcc_json_parser_flags`.
876876
*/
877877
int flatcc_json_parser_table_as_root(flatcc_builder_t *B, flatcc_json_parser_t *ctx,
878-
const char *buf, size_t bufsiz, int flags, const char *fid,
878+
const char *buf, size_t bufsiz, int flags, const flatbuffers_fid_t fid,
879879
flatcc_json_parser_table_f *parser);
880880

881881
/*
882882
* Similar to `flatcc_json_parser_table_as_root` but parses a struct as
883883
* root.
884884
*/
885885
int flatcc_json_parser_struct_as_root(flatcc_builder_t *B, flatcc_json_parser_t *ctx,
886-
const char *buf, size_t bufsiz, int flags, const char *fid,
886+
const char *buf, size_t bufsiz, int flags, const flatbuffers_fid_t fid,
887887
flatcc_json_parser_struct_f *parser);
888888

889889
#include "flatcc/portable/pdiagnostic_pop.h"

include/flatcc/flatcc_json_printer.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -679,11 +679,11 @@ void flatcc_json_printer_uint8_vector_base64_field(flatcc_json_printer_t *ctx,
679679
* require aligned memory addresses (as always for flatbuffers).
680680
*/
681681
int flatcc_json_printer_table_as_root(flatcc_json_printer_t *ctx,
682-
const void *buf, size_t bufsiz, const char *fid,
682+
const void *buf, size_t bufsiz, const flatbuffers_fid_t fid,
683683
flatcc_json_printer_table_f *pf);
684684

685685
int flatcc_json_printer_struct_as_root(flatcc_json_printer_t *ctx,
686-
const void *buf, size_t bufsiz, const char *fid,
686+
const void *buf, size_t bufsiz, const flatbuffers_fid_t fid,
687687
flatcc_json_printer_struct_f *pf);
688688

689689
/*
@@ -756,13 +756,13 @@ void flatcc_json_printer_union_vector_field(flatcc_json_printer_t *ctx,
756756
void flatcc_json_printer_struct_as_nested_root(flatcc_json_printer_t *ctx,
757757
flatcc_json_printer_table_descriptor_t *td,
758758
int id, const char *name, size_t len,
759-
const char *fid,
759+
const flatbuffers_fid_t fid,
760760
flatcc_json_printer_struct_f *pf);
761761

762762
void flatcc_json_printer_table_as_nested_root(flatcc_json_printer_t *ctx,
763763
flatcc_json_printer_table_descriptor_t *td,
764764
int id, const char *name, size_t len,
765-
const char *fid,
765+
const flatbuffers_fid_t fid,
766766
flatcc_json_printer_table_f pf);
767767

768768
void flatcc_json_printer_union_field(flatcc_json_printer_t *ctx,

include/flatcc/flatcc_types.h

Lines changed: 65 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ extern "C" {
1111
#include <stdint.h>
1212
#endif
1313

14+
#include "../../config/config.h"
15+
1416
/*
1517
* This should match generated type declaratios in
1618
* `flatbuffers_common_reader.h` (might have different name prefix).
@@ -42,52 +44,95 @@ extern "C" {
4244
#define flatbuffers_utype_t_defined
4345
#define flatbuffers_bool_t_defined
4446
#define flatbuffers_thash_t_defined
45-
#define flatbuffers_fid_t_defined
46-
47-
/* uoffset_t is also used for vector and string headers. */
48-
#define FLATBUFFERS_UOFFSET_MAX UINT32_MAX
49-
#define FLATBUFFERS_SOFFSET_MAX INT32_MAX
50-
#define FLATBUFFERS_SOFFSET_MIN INT32_MIN
51-
#define FLATBUFFERS_VOFFSET_MAX UINT16_MAX
52-
#define FLATBUFFERS_UTYPE_MAX UINT8_MAX
53-
/* Well - the max of the underlying type. */
54-
#define FLATBUFFERS_BOOL_MAX UINT8_MAX
55-
#define FLATBUFFERS_THASH_MAX UINT32_MAX
5647

5748
#define FLATBUFFERS_ID_MAX (FLATBUFFERS_VOFFSET_MAX / sizeof(flatbuffers_voffset_t) - 3)
5849
/* Vectors of empty structs can yield div by zero, so we must guard against this. */
5950
#define FLATBUFFERS_COUNT_MAX(elem_size) (FLATBUFFERS_UOFFSET_MAX/((elem_size) == 0 ? 1 : (elem_size)))
6051

61-
#define FLATBUFFERS_UOFFSET_WIDTH 32
62-
#define FLATBUFFERS_COUNT_WIDTH 32
63-
#define FLATBUFFERS_SOFFSET_WIDTH 32
64-
#define FLATBUFFERS_VOFFSET_WIDTH 16
65-
#define FLATBUFFERS_UTYPE_WIDTH 8
66-
#define FLATBUFFERS_BOOL_WIDTH 8
67-
#define FLATBUFFERS_THASH_WIDTH 32
6852

6953
#define FLATBUFFERS_TRUE 1
7054
#define FLATBUFFERS_FALSE 0
7155

7256
#define FLATBUFFERS_PROTOCOL_IS_LE 1
7357
#define FLATBUFFERS_PROTOCOL_IS_BE 0
7458

59+
/* uoffset_t is also used for vector and string headers. */
60+
#if FLATCC_OFFSET_SIZE == 4
7561
typedef uint32_t flatbuffers_uoffset_t;
7662
typedef int32_t flatbuffers_soffset_t;
63+
typedef uint32_t flatbuffers_thash_t;
64+
#define FLATBUFFERS_UOFFSET_MAX UINT32_MAX
65+
#define FLATBUFFERS_SOFFSET_MAX INT32_MAX
66+
#define FLATBUFFERS_SOFFSET_MIN INT32_MIN
67+
#define FLATBUFFERS_THASH_MAX UINT32_MAX
68+
#define FLATBUFFERS_UOFFSET_WIDTH 32
69+
#define FLATBUFFERS_SOFFSET_WIDTH 32
70+
#define FLATBUFFERS_THASH_WIDTH 32
71+
#elif FLATCC_OFFSET_SIZE == 8
72+
typedef uint64_t flatbuffers_uoffset_t;
73+
typedef int64_t flatbuffers_soffset_t;
74+
typedef uint64_t flatbuffers_thash_t;
75+
#define FLATBUFFERS_UOFFSET_MAX UINT64_MAX
76+
#define FLATBUFFERS_SOFFSET_MAX INT64_MAX
77+
#define FLATBUFFERS_SOFFSET_MIN INT64_MIN
78+
#define FLATBUFFERS_THASH_MAX UINT64_MAX
79+
#define FLATBUFFERS_UOFFSET_WIDTH 64
80+
#define FLATBUFFERS_SOFFSET_WIDTH 64
81+
#define FLATBUFFERS_THASH_WIDTH 64
82+
#elif FLATCC_OFFSET_SIZE == 2
83+
typedef uint16_t flatbuffers_uoffset_t;
84+
typedef int16_t flatbuffers_soffset_t;
85+
typedef uint16_t flatbuffers_thash_t;
86+
#define FLATBUFFERS_UOFFSET_MAX UINT16_MAX
87+
#define FLATBUFFERS_SOFFSET_MAX INT16_MAX
88+
#define FLATBUFFERS_SOFFSET_MIN INT16_MIN
89+
#define FLATBUFFERS_THASH_MAX UINT16_MAX
90+
#define FLATBUFFERS_UOFFSET_WIDTH 16
91+
#define FLATBUFFERS_SOFFSET_WIDTH 16
92+
#define FLATBUFFERS_THASH_WIDTH 16
93+
#else
94+
#error FLATCC_OFFSET_SIZE must be defined.
95+
#endif
96+
97+
#if FLATCC_VOFFSET_SIZE == 2
7798
typedef uint16_t flatbuffers_voffset_t;
99+
#define FLATBUFFERS_VOFFSET_MAX UINT16_MAX
100+
#define FLATBUFFERS_VOFFSET_WIDTH 16
101+
#elif FLATCC_VOFFSET_SIZE == 8
102+
typedef uint64_t flatbuffers_voffset_t;
103+
#define FLATBUFFERS_VOFFSET_MAX UINT64_MAX
104+
#define FLATBUFFERS_VOFFSET_WIDTH 64
105+
#elif FLATCC_VOFFSET_SIZE == 4
106+
typedef uint32_t flatbuffers_voffset_t;
107+
#define FLATBUFFERS_VOFFSET_MAX UINT32_MAX
108+
#define FLATBUFFERS_VOFFSET_WIDTH 32
109+
#else
110+
#error FLATCC_VOFFSET_SIZE must be defined.
111+
#endif
112+
113+
#define FLATBUFFERS_UTYPE_MAX UINT8_MAX
114+
#define FLATBUFFERS_UTYPE_WIDTH 8
78115
typedef uint8_t flatbuffers_utype_t;
116+
117+
/* Well - the max of the underlying type. */
118+
#define FLATBUFFERS_BOOL_MAX UINT8_MAX
119+
#define FLATBUFFERS_BOOL_WIDTH 8
79120
typedef uint8_t flatbuffers_bool_t;
80-
typedef uint32_t flatbuffers_thash_t;
121+
81122
/* Public facing type operations. */
82123
typedef flatbuffers_utype_t flatbuffers_union_type_t;
83124

84125
static const flatbuffers_bool_t flatbuffers_true = FLATBUFFERS_TRUE;
85126
static const flatbuffers_bool_t flatbuffers_false = FLATBUFFERS_FALSE;
86127

87-
#define FLATBUFFERS_IDENTIFIER_SIZE (FLATBUFFERS_THASH_WIDTH / 8)
128+
#ifndef flatbuffers_fid_t_defined
129+
#define FLATBUFFERS_IDENTIFIER_SIZE FLATCC_OFFSET_SIZE
88130

89131
typedef char flatbuffers_fid_t[FLATBUFFERS_IDENTIFIER_SIZE];
90132

133+
#define flatbuffers_fid_t_defined
134+
#endif
135+
91136
#endif /* flatbuffers_types_defined */
92137

93138
#ifdef __cplusplus

include/flatcc/flatcc_verifier.h

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -164,13 +164,13 @@ typedef int flatcc_union_verifier_f(flatcc_union_verifier_descriptor_t *ud);
164164
* require aligned memory addresses. The buffer pointers alignment is
165165
* not significant to internal verification of the buffer.
166166
*/
167-
int flatcc_verify_struct_as_root(const void *buf, size_t bufsiz, const char *fid,
167+
int flatcc_verify_struct_as_root(const void *buf, size_t bufsiz, const flatbuffers_fid_t fid,
168168
size_t size, uint16_t align);
169169

170170
int flatcc_verify_struct_as_typed_root(const void *buf, size_t bufsiz, flatbuffers_thash_t thash,
171171
size_t size, uint16_t align);
172172

173-
int flatcc_verify_table_as_root(const void *buf, size_t bufsiz, const char *fid,
173+
int flatcc_verify_table_as_root(const void *buf, size_t bufsiz, const flatbuffers_fid_t fid,
174174
flatcc_table_verifier_f *root_tvf);
175175

176176
int flatcc_verify_table_as_typed_root(const void *buf, size_t bufsiz, flatbuffers_thash_t thash,
@@ -179,7 +179,7 @@ int flatcc_verify_table_as_typed_root(const void *buf, size_t bufsiz, flatbuffer
179179
* The buffer header is verified by any of the `_as_root` verifiers, but
180180
* this function may be used as a quick sanity check.
181181
*/
182-
int flatcc_verify_buffer_header(const void *buf, size_t bufsiz, const char *fid);
182+
int flatcc_verify_buffer_header(const void *buf, size_t bufsiz, const flatbuffers_fid_t fid);
183183

184184
int flatcc_verify_typed_buffer_header(const void *buf, size_t bufsiz, flatbuffers_thash_t type_hash);
185185

@@ -204,10 +204,10 @@ int flatcc_verify_table_vector_field(flatcc_table_verifier_descriptor_t *td,
204204
flatbuffers_voffset_t id, int required, flatcc_table_verifier_f tvf);
205205
/* Table verifiers pass 0 as fid. */
206206
int flatcc_verify_struct_as_nested_root(flatcc_table_verifier_descriptor_t *td,
207-
flatbuffers_voffset_t id, int required, const char *fid,
207+
flatbuffers_voffset_t id, int required, const flatbuffers_fid_t fid,
208208
size_t size, uint16_t align);
209209
int flatcc_verify_table_as_nested_root(flatcc_table_verifier_descriptor_t *td,
210-
flatbuffers_voffset_t id, int required, const char *fid,
210+
flatbuffers_voffset_t id, int required, const flatbuffers_fid_t fid,
211211
uint16_t align, flatcc_table_verifier_f tvf);
212212

213213
/*

0 commit comments

Comments
 (0)