1/*
2 * Copyright (c) 2015-2021 Nicholas Fraser and the MPack authors
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a copy of
5 * this software and associated documentation files (the "Software"), to deal in
6 * the Software without restriction, including without limitation the rights to
7 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
8 * the Software, and to permit persons to whom the Software is furnished to do so,
9 * subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in all
12 * copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
16 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
17 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
18 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20 */
21
22/**
23 * @file
24 *
25 * Declares the MPack Writer.
26 */
27
28#ifndef MPACK_WRITER_H
29#define MPACK_WRITER_H 1
30
31#include "mpack-common.h"
32
33#if MPACK_WRITER
34
35MPACK_SILENCE_WARNINGS_BEGIN
36MPACK_EXTERN_C_BEGIN
37
38#if MPACK_WRITE_TRACKING
39struct mpack_track_t;
40#endif
41
42/**
43 * @defgroup writer Write API
44 *
45 * The MPack Write API encodes structured data of a fixed (hardcoded) schema to MessagePack.
46 *
47 * @{
48 */
49
50/**
51 * @def MPACK_WRITER_MINIMUM_BUFFER_SIZE
52 *
53 * The minimum buffer size for a writer with a flush function.
54 */
55#define MPACK_WRITER_MINIMUM_BUFFER_SIZE 32
56
57/**
58 * A buffered MessagePack encoder.
59 *
60 * The encoder wraps an existing buffer and, optionally, a flush function.
61 * This allows efficiently encoding to an in-memory buffer or to a stream.
62 *
63 * All write operations are synchronous; they will block until the
64 * data is fully written, or an error occurs.
65 */
66typedef struct mpack_writer_t mpack_writer_t;
67
68/**
69 * The MPack writer's flush function to flush the buffer to the output stream.
70 * It should flag an appropriate error on the writer if flushing fails (usually
71 * mpack_error_io or mpack_error_memory.)
72 *
73 * The specified context for callbacks is at writer->context.
74 */
75typedef void (*mpack_writer_flush_t)(mpack_writer_t* writer, const char* buffer, size_t count);
76
77/**
78 * An error handler function to be called when an error is flagged on
79 * the writer.
80 *
81 * The error handler will only be called once on the first error flagged;
82 * any subsequent writes and errors are ignored, and the writer is
83 * permanently in that error state.
84 *
85 * MPack is safe against non-local jumps out of error handler callbacks.
86 * This means you are allowed to longjmp or throw an exception (in C++,
87 * Objective-C, or with SEH) out of this callback.
88 *
89 * Bear in mind when using longjmp that local non-volatile variables that
90 * have changed are undefined when setjmp() returns, so you can't put the
91 * writer on the stack in the same activation frame as the setjmp without
92 * declaring it volatile.
93 *
94 * You must still eventually destroy the writer. It is not destroyed
95 * automatically when an error is flagged. It is safe to destroy the
96 * writer within this error callback, but you will either need to perform
97 * a non-local jump, or store something in your context to identify
98 * that the writer is destroyed since any future accesses to it cause
99 * undefined behavior.
100 */
101typedef void (*mpack_writer_error_t)(mpack_writer_t* writer, mpack_error_t error);
102
103/**
104 * A teardown function to be called when the writer is destroyed.
105 */
106typedef void (*mpack_writer_teardown_t)(mpack_writer_t* writer);
107
108/* Hide internals from documentation */
109/** @cond */
110
111#if MPACK_BUILDER
112/**
113 * Build buffer pages form a linked list.
114 *
115 * They don't always fill up. If there is not enough space within them to write
116 * a tag or place an mpack_build_t, a new page is allocated. For this reason
117 * they store the number of used bytes.
118 */
119typedef struct mpack_builder_page_t {
120 struct mpack_builder_page_t* next;
121 size_t bytes_used;
122} mpack_builder_page_t;
123
124/**
125 * Builds form a linked list of mpack_build_t, interleaved with their encoded
126 * contents directly in the paged builder buffer.
127 */
128typedef struct mpack_build_t {
129 //mpack_builder_page_t* page;
130 struct mpack_build_t* parent;
131 //struct mpack_build_t* next;
132
133 size_t bytes; // number of bytes between this build and the next one
134 uint32_t count; // number of elements (or key/value pairs) in this map/array
135 mpack_type_t type;
136
137 // depth of nested non-build compound elements within this
138 // build.
139 uint32_t nested_compound_elements;
140
141 // indicates that a value still needs to be written for an already
142 // written key. count is not incremented until both key and value are
143 // written.
144 bool key_needs_value;
145} mpack_build_t;
146
147/**
148 * The builder state. This is stored within mpack_writer_t.
149 */
150typedef struct mpack_builder_t {
151 mpack_build_t* current_build; // build which is accumulating elements
152 mpack_build_t* latest_build; // build which is accumulating bytes
153 mpack_builder_page_t* current_page;
154 mpack_builder_page_t* pages;
155 char* stash_buffer;
156 char* stash_position;
157 char* stash_end;
158 #if MPACK_BUILDER_INTERNAL_STORAGE
159 char internal[MPACK_BUILDER_INTERNAL_STORAGE_SIZE];
160 #endif
161} mpack_builder_t;
162#endif
163
164struct mpack_writer_t {
165 #if MPACK_COMPATIBILITY
166 mpack_version_t version; /* Version of the MessagePack spec to write */
167 #endif
168 mpack_writer_flush_t flush; /* Function to write bytes to the output stream */
169 mpack_writer_error_t error_fn; /* Function to call on error */
170 mpack_writer_teardown_t teardown; /* Function to teardown the context on destroy */
171 void* context; /* Context for writer callbacks */
172
173 char* buffer; /* Byte buffer */
174 char* position; /* Current position within the buffer */
175 char* end; /* The end of the buffer */
176 mpack_error_t error; /* Error state */
177
178 #if MPACK_WRITE_TRACKING
179 mpack_track_t track; /* Stack of map/array/str/bin/ext writes */
180 #endif
181
182 #ifdef MPACK_MALLOC
183 /* Reserved. You can use this space to allocate a custom
184 * context in order to reduce heap allocations. */
185 void* reserved[2];
186 #endif
187
188 #if MPACK_BUILDER
189 mpack_builder_t builder;
190 #endif
191};
192
193
194#if MPACK_WRITE_TRACKING
195void mpack_writer_track_push(mpack_writer_t* writer, mpack_type_t type, uint32_t count);
196void mpack_writer_track_push_builder(mpack_writer_t* writer, mpack_type_t type);
197void mpack_writer_track_pop(mpack_writer_t* writer, mpack_type_t type);
198void mpack_writer_track_pop_builder(mpack_writer_t* writer, mpack_type_t type);
199void mpack_writer_track_bytes(mpack_writer_t* writer, size_t count);
200#else
201MPACK_INLINE void mpack_writer_track_push(mpack_writer_t* writer, mpack_type_t type, uint32_t count) {
202 MPACK_UNUSED(writer);
203 MPACK_UNUSED(type);
204 MPACK_UNUSED(count);
205}
206MPACK_INLINE void mpack_writer_track_push_builder(mpack_writer_t* writer, mpack_type_t type) {
207 MPACK_UNUSED(writer);
208 MPACK_UNUSED(type);
209}
210MPACK_INLINE void mpack_writer_track_pop(mpack_writer_t* writer, mpack_type_t type) {
211 MPACK_UNUSED(writer);
212 MPACK_UNUSED(type);
213}
214MPACK_INLINE void mpack_writer_track_pop_builder(mpack_writer_t* writer, mpack_type_t type) {
215 MPACK_UNUSED(writer);
216 MPACK_UNUSED(type);
217}
218MPACK_INLINE void mpack_writer_track_bytes(mpack_writer_t* writer, size_t count) {
219 MPACK_UNUSED(writer);
220 MPACK_UNUSED(count);
221}
222#endif
223
224/** @endcond */
225
226/**
227 * @name Lifecycle Functions
228 * @{
229 */
230
231/**
232 * Initializes an MPack writer with the given buffer. The writer
233 * does not assume ownership of the buffer.
234 *
235 * Trying to write past the end of the buffer will result in mpack_error_too_big
236 * unless a flush function is set with mpack_writer_set_flush(). To use the data
237 * without flushing, call mpack_writer_buffer_used() to determine the number of
238 * bytes written.
239 *
240 * @param writer The MPack writer.
241 * @param buffer The buffer into which to write MessagePack data.
242 * @param size The size of the buffer.
243 */
244void mpack_writer_init(mpack_writer_t* writer, char* buffer, size_t size);
245
246#ifdef MPACK_MALLOC
247/**
248 * Initializes an MPack writer using a growable buffer.
249 *
250 * The data is placed in the given data pointer if and when the writer
251 * is destroyed without error. The data pointer is NULL during writing,
252 * and will remain NULL if an error occurs.
253 *
254 * The allocated data must be freed with MPACK_FREE() (or simply free()
255 * if MPack's allocator hasn't been customized.)
256 *
257 * @throws mpack_error_memory if the buffer fails to grow when
258 * flushing.
259 *
260 * @param writer The MPack writer.
261 * @param data Where to place the allocated data.
262 * @param size Where to write the size of the data.
263 */
264void mpack_writer_init_growable(mpack_writer_t* writer, char** data, size_t* size);
265#endif
266
267/**
268 * Initializes an MPack writer directly into an error state. Use this if you
269 * are writing a wrapper to mpack_writer_init() which can fail its setup.
270 */
271void mpack_writer_init_error(mpack_writer_t* writer, mpack_error_t error);
272
273#if MPACK_STDIO
274/**
275 * Initializes an MPack writer that writes to a file.
276 *
277 * @throws mpack_error_memory if allocation fails
278 * @throws mpack_error_io if the file cannot be opened
279 */
280void mpack_writer_init_filename(mpack_writer_t* writer, const char* filename);
281
282/**
283 * Deprecated.
284 *
285 * \deprecated Renamed to mpack_writer_init_filename().
286 */
287MPACK_INLINE void mpack_writer_init_file(mpack_writer_t* writer, const char* filename) {
288 mpack_writer_init_filename(writer, filename);
289}
290
291/**
292 * Initializes an MPack writer that writes to a libc FILE. This can be used to
293 * write to stdout or stderr, or to a file opened separately.
294 *
295 * @param writer The MPack writer.
296 * @param stdfile The FILE.
297 * @param close_when_done If true, fclose() will be called on the FILE when it
298 * is no longer needed. If false, the file will not be flushed or
299 * closed when writing is done.
300 *
301 * @note The writer is buffered. If you want to write other data to the FILE in
302 * between messages, you must flush it first.
303 *
304 * @see mpack_writer_flush_message
305 */
306void mpack_writer_init_stdfile(mpack_writer_t* writer, FILE* stdfile, bool close_when_done);
307#endif
308
309/** @cond */
310
311#define mpack_writer_init_stack_line_ex(line, writer) \
312 char mpack_buf_##line[MPACK_STACK_SIZE]; \
313 mpack_writer_init(writer, mpack_buf_##line, sizeof(mpack_buf_##line))
314
315#define mpack_writer_init_stack_line(line, writer) \
316 mpack_writer_init_stack_line_ex(line, writer)
317
318/*
319 * Initializes an MPack writer using stack space as a buffer. A flush function
320 * should be added to the writer to flush the buffer.
321 *
322 * This is currently undocumented since it's not entirely useful on its own.
323 */
324
325#define mpack_writer_init_stack(writer) \
326 mpack_writer_init_stack_line(__LINE__, (writer))
327
328/** @endcond */
329
330/**
331 * Cleans up the MPack writer, flushing and closing the underlying stream,
332 * if any. Returns the final error state of the writer.
333 *
334 * No flushing is performed if the writer is in an error state. The attached
335 * teardown function is called whether or not the writer is in an error state.
336 *
337 * This will assert in tracking mode if the writer is not in an error
338 * state and has any unclosed compound types. If you want to cancel
339 * writing in the middle of a document, you need to flag an error on
340 * the writer before destroying it (such as mpack_error_data).
341 *
342 * Note that a writer may raise an error and call your error handler during
343 * the final flush. It is safe to longjmp or throw out of this error handler,
344 * but if you do, the writer will not be destroyed, and the teardown function
345 * will not be called. You can still get the writer's error state, and you
346 * must call @ref mpack_writer_destroy() again. (The second call is guaranteed
347 * not to call your error handler again since the writer is already in an error
348 * state.)
349 *
350 * @see mpack_writer_set_error_handler
351 * @see mpack_writer_set_flush
352 * @see mpack_writer_set_teardown
353 * @see mpack_writer_flag_error
354 * @see mpack_error_data
355 */
356mpack_error_t mpack_writer_destroy(mpack_writer_t* writer);
357
358/**
359 * @}
360 */
361
362/**
363 * @name Configuration
364 * @{
365 */
366
367#if MPACK_COMPATIBILITY
368/**
369 * Sets the version of the MessagePack spec that will be generated.
370 *
371 * This can be used to interface with older libraries that do not support
372 * the newest MessagePack features (such as the @c str8 type.)
373 *
374 * @note This requires @ref MPACK_COMPATIBILITY.
375 */
376MPACK_INLINE void mpack_writer_set_version(mpack_writer_t* writer, mpack_version_t version) {
377 writer->version = version;
378}
379#endif
380
381/**
382 * Sets the custom pointer to pass to the writer callbacks, such as flush
383 * or teardown.
384 *
385 * @param writer The MPack writer.
386 * @param context User data to pass to the writer callbacks.
387 *
388 * @see mpack_writer_context()
389 */
390MPACK_INLINE void mpack_writer_set_context(mpack_writer_t* writer, void* context) {
391 writer->context = context;
392}
393
394/**
395 * Returns the custom context for writer callbacks.
396 *
397 * @see mpack_writer_set_context
398 * @see mpack_writer_set_flush
399 */
400MPACK_INLINE void* mpack_writer_context(mpack_writer_t* writer) {
401 return writer->context;
402}
403
404/**
405 * Sets the flush function to write out the data when the buffer is full.
406 *
407 * If no flush function is used, trying to write past the end of the
408 * buffer will result in mpack_error_too_big.
409 *
410 * This should normally be used with mpack_writer_set_context() to register
411 * a custom pointer to pass to the flush function.
412 *
413 * @param writer The MPack writer.
414 * @param flush The function to write out data from the buffer.
415 *
416 * @see mpack_writer_context()
417 */
418void mpack_writer_set_flush(mpack_writer_t* writer, mpack_writer_flush_t flush);
419
420/**
421 * Sets the error function to call when an error is flagged on the writer.
422 *
423 * This should normally be used with mpack_writer_set_context() to register
424 * a custom pointer to pass to the error function.
425 *
426 * See the definition of mpack_writer_error_t for more information about
427 * what you can do from an error callback.
428 *
429 * @see mpack_writer_error_t
430 * @param writer The MPack writer.
431 * @param error_fn The function to call when an error is flagged on the writer.
432 */
433MPACK_INLINE void mpack_writer_set_error_handler(mpack_writer_t* writer, mpack_writer_error_t error_fn) {
434 writer->error_fn = error_fn;
435}
436
437/**
438 * Sets the teardown function to call when the writer is destroyed.
439 *
440 * This should normally be used with mpack_writer_set_context() to register
441 * a custom pointer to pass to the teardown function.
442 *
443 * @param writer The MPack writer.
444 * @param teardown The function to call when the writer is destroyed.
445 */
446MPACK_INLINE void mpack_writer_set_teardown(mpack_writer_t* writer, mpack_writer_teardown_t teardown) {
447 writer->teardown = teardown;
448}
449
450/**
451 * @}
452 */
453
454/**
455 * @name Core Writer Functions
456 * @{
457 */
458
459/**
460 * Flushes any buffered data to the underlying stream.
461 *
462 * If the writer is connected to a socket and you are keeping it open,
463 * you will want to call this after writing a message (or set of
464 * messages) so that the data is actually sent.
465 *
466 * It is not necessary to call this if you are not keeping the writer
467 * open afterwards. You can just call `mpack_writer_destroy()` and it
468 * will flush before cleaning up.
469 *
470 * This will assert if no flush function is assigned to the writer.
471 *
472 * If write tracking is enabled, this will break and flag @ref
473 * mpack_error_bug if the writer has any open compound types, ensuring
474 * that no compound types are still open. This prevents a "missing
475 * finish" bug from causing a never-ending message.
476 */
477void mpack_writer_flush_message(mpack_writer_t* writer);
478
479/**
480 * Returns the number of bytes currently stored in the buffer. This
481 * may be less than the total number of bytes written if bytes have
482 * been flushed to an underlying stream.
483 */
484MPACK_INLINE size_t mpack_writer_buffer_used(mpack_writer_t* writer) {
485 return (size_t)(writer->position - writer->buffer);
486}
487
488/**
489 * Returns the amount of space left in the buffer. This may be reset
490 * after a write if bytes are flushed to an underlying stream.
491 */
492MPACK_INLINE size_t mpack_writer_buffer_left(mpack_writer_t* writer) {
493 return (size_t)(writer->end - writer->position);
494}
495
496/**
497 * Returns the (current) size of the buffer. This may change after a write if
498 * the flush callback changes the buffer.
499 */
500MPACK_INLINE size_t mpack_writer_buffer_size(mpack_writer_t* writer) {
501 return (size_t)(writer->end - writer->buffer);
502}
503
504/**
505 * Places the writer in the given error state, calling the error callback if one
506 * is set.
507 *
508 * This allows you to externally flag errors, for example if you are validating
509 * data as you write it, or if you want to cancel writing in the middle of a
510 * document. (The writer will assert if you try to destroy it without error and
511 * with unclosed compound types. In this case you should flag mpack_error_data
512 * before destroying it.)
513 *
514 * If the writer is already in an error state, this call is ignored and no
515 * error callback is called.
516 *
517 * @see mpack_writer_destroy
518 * @see mpack_error_data
519 */
520void mpack_writer_flag_error(mpack_writer_t* writer, mpack_error_t error);
521
522/**
523 * Queries the error state of the MPack writer.
524 *
525 * If a writer is in an error state, you should discard all data since the
526 * last time the error flag was checked. The error flag cannot be cleared.
527 */
528MPACK_INLINE mpack_error_t mpack_writer_error(mpack_writer_t* writer) {
529 return writer->error;
530}
531
532/**
533 * Writes a MessagePack object header (an MPack Tag.)
534 *
535 * If the value is a map, array, string, binary or extension type, the
536 * containing elements or bytes must be written separately and the
537 * appropriate finish function must be called (as though one of the
538 * mpack_start_*() functions was called.)
539 *
540 * @see mpack_write_bytes()
541 * @see mpack_finish_map()
542 * @see mpack_finish_array()
543 * @see mpack_finish_str()
544 * @see mpack_finish_bin()
545 * @see mpack_finish_ext()
546 * @see mpack_finish_type()
547 */
548void mpack_write_tag(mpack_writer_t* writer, mpack_tag_t tag);
549
550/**
551 * @}
552 */
553
554/**
555 * @name Integers
556 * @{
557 */
558
559/** Writes an 8-bit integer in the most efficient packing available. */
560void mpack_write_i8(mpack_writer_t* writer, int8_t value);
561
562/** Writes a 16-bit integer in the most efficient packing available. */
563void mpack_write_i16(mpack_writer_t* writer, int16_t value);
564
565/** Writes a 32-bit integer in the most efficient packing available. */
566void mpack_write_i32(mpack_writer_t* writer, int32_t value);
567
568/** Writes a 64-bit integer in the most efficient packing available. */
569void mpack_write_i64(mpack_writer_t* writer, int64_t value);
570
571/** Writes an integer in the most efficient packing available. */
572MPACK_INLINE void mpack_write_int(mpack_writer_t* writer, int64_t value) {
573 mpack_write_i64(writer, value);
574}
575
576/** Writes an 8-bit unsigned integer in the most efficient packing available. */
577void mpack_write_u8(mpack_writer_t* writer, uint8_t value);
578
579/** Writes an 16-bit unsigned integer in the most efficient packing available. */
580void mpack_write_u16(mpack_writer_t* writer, uint16_t value);
581
582/** Writes an 32-bit unsigned integer in the most efficient packing available. */
583void mpack_write_u32(mpack_writer_t* writer, uint32_t value);
584
585/** Writes an 64-bit unsigned integer in the most efficient packing available. */
586void mpack_write_u64(mpack_writer_t* writer, uint64_t value);
587
588/** Writes an unsigned integer in the most efficient packing available. */
589MPACK_INLINE void mpack_write_uint(mpack_writer_t* writer, uint64_t value) {
590 mpack_write_u64(writer, value);
591}
592
593/**
594 * @}
595 */
596
597/**
598 * @name Other Basic Types
599 * @{
600 */
601
602#if MPACK_FLOAT
603/** Writes a float. */
604void mpack_write_float(mpack_writer_t* writer, float value);
605#else
606/** Writes a float from a raw uint32_t. */
607void mpack_write_raw_float(mpack_writer_t* writer, uint32_t raw_value);
608#endif
609
610#if MPACK_DOUBLE
611/** Writes a double. */
612void mpack_write_double(mpack_writer_t* writer, double value);
613#else
614/** Writes a double from a raw uint64_t. */
615void mpack_write_raw_double(mpack_writer_t* writer, uint64_t raw_value);
616#endif
617
618/** Writes a boolean. */
619void mpack_write_bool(mpack_writer_t* writer, bool value);
620
621/** Writes a boolean with value true. */
622void mpack_write_true(mpack_writer_t* writer);
623
624/** Writes a boolean with value false. */
625void mpack_write_false(mpack_writer_t* writer);
626
627/** Writes a nil. */
628void mpack_write_nil(mpack_writer_t* writer);
629
630/** Write a pre-encoded messagepack object */
631void mpack_write_object_bytes(mpack_writer_t* writer, const char* data, size_t bytes);
632
633#if MPACK_EXTENSIONS
634/**
635 * Writes a timestamp.
636 *
637 * @note This requires @ref MPACK_EXTENSIONS.
638 *
639 * @param writer The writer
640 * @param seconds The (signed) number of seconds since 1970-01-01T00:00:00Z.
641 * @param nanoseconds The additional number of nanoseconds from 0 to 999,999,999 inclusive.
642 */
643void mpack_write_timestamp(mpack_writer_t* writer, int64_t seconds, uint32_t nanoseconds);
644
645/**
646 * Writes a timestamp with the given number of seconds (and zero nanoseconds).
647 *
648 * @note This requires @ref MPACK_EXTENSIONS.
649 *
650 * @param writer The writer
651 * @param seconds The (signed) number of seconds since 1970-01-01T00:00:00Z.
652 */
653MPACK_INLINE void mpack_write_timestamp_seconds(mpack_writer_t* writer, int64_t seconds) {
654 mpack_write_timestamp(writer, seconds, 0);
655}
656
657/**
658 * Writes a timestamp.
659 *
660 * @note This requires @ref MPACK_EXTENSIONS.
661 */
662MPACK_INLINE void mpack_write_timestamp_struct(mpack_writer_t* writer, mpack_timestamp_t timestamp) {
663 mpack_write_timestamp(writer, timestamp.seconds, timestamp.nanoseconds);
664}
665#endif
666
667/**
668 * @}
669 */
670
671/**
672 * @name Map and Array Functions
673 * @{
674 */
675
676/**
677 * Opens an array.
678 *
679 * `count` elements must follow, and mpack_finish_array() must be called
680 * when done.
681 *
682 * If you do not know the number of elements to be written ahead of time, call
683 * mpack_build_array() instead.
684 *
685 * @see mpack_finish_array()
686 * @see mpack_build_array() to count the number of elements automatically
687 */
688void mpack_start_array(mpack_writer_t* writer, uint32_t count);
689
690/**
691 * Opens a map.
692 *
693 * `count * 2` elements must follow, and mpack_finish_map() must be called
694 * when done.
695 *
696 * If you do not know the number of elements to be written ahead of time, call
697 * mpack_build_map() instead.
698 *
699 * Remember that while map elements in MessagePack are implicitly ordered,
700 * they are not ordered in JSON. If you need elements to be read back
701 * in the order they are written, consider use an array instead.
702 *
703 * @see mpack_finish_map()
704 * @see mpack_build_map() to count the number of key/value pairs automatically
705 */
706void mpack_start_map(mpack_writer_t* writer, uint32_t count);
707
708MPACK_INLINE void mpack_builder_compound_push(mpack_writer_t* writer) {
709 MPACK_UNUSED(writer);
710
711 #if MPACK_BUILDER
712 mpack_build_t* build = writer->builder.current_build;
713 if (build != NULL) {
714 ++build->nested_compound_elements;
715 }
716 #endif
717}
718
719MPACK_INLINE void mpack_builder_compound_pop(mpack_writer_t* writer) {
720 MPACK_UNUSED(writer);
721
722 #if MPACK_BUILDER
723 mpack_build_t* build = writer->builder.current_build;
724 if (build != NULL) {
725 mpack_assert(build->nested_compound_elements > 0);
726 --build->nested_compound_elements;
727 }
728 #endif
729}
730
731/**
732 * Finishes writing an array.
733 *
734 * This should be called only after a corresponding call to mpack_start_array()
735 * and after the array contents are written.
736 *
737 * In debug mode (or if MPACK_WRITE_TRACKING is not 0), this will track writes
738 * to ensure that the correct number of elements are written.
739 *
740 * @see mpack_start_array()
741 */
742MPACK_INLINE void mpack_finish_array(mpack_writer_t* writer) {
743 mpack_writer_track_pop(writer, mpack_type_array);
744 mpack_builder_compound_pop(writer);
745}
746
747/**
748 * Finishes writing a map.
749 *
750 * This should be called only after a corresponding call to mpack_start_map()
751 * and after the map contents are written.
752 *
753 * In debug mode (or if MPACK_WRITE_TRACKING is not 0), this will track writes
754 * to ensure that the correct number of elements are written.
755 *
756 * @see mpack_start_map()
757 */
758MPACK_INLINE void mpack_finish_map(mpack_writer_t* writer) {
759 mpack_writer_track_pop(writer, mpack_type_map);
760 mpack_builder_compound_pop(writer);
761}
762
763/**
764 * Starts building an array.
765 *
766 * Elements must follow, and mpack_complete_array() must be called when done. The
767 * number of elements is determined automatically.
768 *
769 * If you know ahead of time the number of elements in the array, it is more
770 * efficient to call mpack_start_array() instead, even if you are already
771 * within another open build.
772 *
773 * Builder containers can be nested within normal (known size) containers and
774 * vice versa. You can call mpack_build_array(), then mpack_start_array()
775 * inside it, then mpack_build_array() inside that, and so forth.
776 *
777 * @see mpack_complete_array() to complete this array
778 * @see mpack_start_array() if you already know the size of the array
779 * @see mpack_build_map() for implementation details
780 */
781void mpack_build_array(struct mpack_writer_t* writer);
782
783/**
784 * Starts building a map.
785 *
786 * An even number of elements must follow, and mpack_complete_map() must be
787 * called when done. The number of elements is determined automatically.
788 *
789 * If you know ahead of time the number of elements in the map, it is more
790 * efficient to call mpack_start_map() instead, even if you are already within
791 * another open build.
792 *
793 * Builder containers can be nested within normal (known size) containers and
794 * vice versa. You can call mpack_build_map(), then mpack_start_map() inside
795 * it, then mpack_build_map() inside that, and so forth.
796 *
797 * A writer in build mode diverts writes to a builder buffer that allocates as
798 * needed. Once the last map or array being built is completed, the deferred
799 * message is composed with computed array and map sizes into the writer.
800 * Builder maps and arrays are encoded exactly the same as ordinary maps and
801 * arrays in the final message.
802 *
803 * This indirect encoding is costly, as it incurs at least an extra copy of all
804 * data written within a builder (but not additional copies for nested
805 * builders.) Expect a speed penalty of half or more.
806 *
807 * A good strategy is to use this during early development when your messages
808 * are constantly changing, and then closer to release when your message
809 * formats have stabilized, replace all your build calls with start calls with
810 * pre-computed sizes. Or don't, if you find the builder has little impact on
811 * performance, because even with builders MPack is extremely fast.
812 *
813 * @note When an array or map starts being built, nothing will be flushed
814 * until it is completed. If you are building a large message that
815 * does not fit in the output stream, you won't get an error about it
816 * until everything is written.
817 *
818 * @see mpack_complete_map() to complete this map
819 * @see mpack_start_map() if you already know the size of the map
820 */
821void mpack_build_map(struct mpack_writer_t* writer);
822
823/**
824 * Completes an array being built.
825 *
826 * @see mpack_build_array()
827 */
828void mpack_complete_array(struct mpack_writer_t* writer);
829
830/**
831 * Completes a map being built.
832 *
833 * @see mpack_build_map()
834 */
835void mpack_complete_map(struct mpack_writer_t* writer);
836
837/**
838 * @}
839 */
840
841/**
842 * @name Data Helpers
843 * @{
844 */
845
846/**
847 * Writes a string.
848 *
849 * To stream a string in chunks, use mpack_start_str() instead.
850 *
851 * MPack does not care about the underlying encoding, but UTF-8 is highly
852 * recommended, especially for compatibility with JSON. You should consider
853 * calling mpack_write_utf8() instead, especially if you will be reading
854 * it back as UTF-8.
855 *
856 * You should not call mpack_finish_str() after calling this; this
857 * performs both start and finish.
858 */
859void mpack_write_str(mpack_writer_t* writer, const char* str, uint32_t length);
860
861/**
862 * Writes a string, ensuring that it is valid UTF-8.
863 *
864 * This does not accept any UTF-8 variant such as Modified UTF-8, CESU-8 or
865 * WTF-8. Only pure UTF-8 is allowed.
866 *
867 * You should not call mpack_finish_str() after calling this; this
868 * performs both start and finish.
869 *
870 * @throws mpack_error_invalid if the string is not valid UTF-8
871 */
872void mpack_write_utf8(mpack_writer_t* writer, const char* str, uint32_t length);
873
874/**
875 * Writes a null-terminated string. (The null-terminator is not written.)
876 *
877 * MPack does not care about the underlying encoding, but UTF-8 is highly
878 * recommended, especially for compatibility with JSON. You should consider
879 * calling mpack_write_utf8_cstr() instead, especially if you will be reading
880 * it back as UTF-8.
881 *
882 * You should not call mpack_finish_str() after calling this; this
883 * performs both start and finish.
884 */
885void mpack_write_cstr(mpack_writer_t* writer, const char* cstr);
886
887/**
888 * Writes a null-terminated string, or a nil node if the given cstr pointer
889 * is NULL. (The null-terminator is not written.)
890 *
891 * MPack does not care about the underlying encoding, but UTF-8 is highly
892 * recommended, especially for compatibility with JSON. You should consider
893 * calling mpack_write_utf8_cstr_or_nil() instead, especially if you will
894 * be reading it back as UTF-8.
895 *
896 * You should not call mpack_finish_str() after calling this; this
897 * performs both start and finish.
898 */
899void mpack_write_cstr_or_nil(mpack_writer_t* writer, const char* cstr);
900
901/**
902 * Writes a null-terminated string, ensuring that it is valid UTF-8. (The
903 * null-terminator is not written.)
904 *
905 * This does not accept any UTF-8 variant such as Modified UTF-8, CESU-8 or
906 * WTF-8. Only pure UTF-8 is allowed.
907 *
908 * You should not call mpack_finish_str() after calling this; this
909 * performs both start and finish.
910 *
911 * @throws mpack_error_invalid if the string is not valid UTF-8
912 */
913void mpack_write_utf8_cstr(mpack_writer_t* writer, const char* cstr);
914
915/**
916 * Writes a null-terminated string ensuring that it is valid UTF-8, or
917 * writes nil if the given cstr pointer is NULL. (The null-terminator
918 * is not written.)
919 *
920 * This does not accept any UTF-8 variant such as Modified UTF-8, CESU-8 or
921 * WTF-8. Only pure UTF-8 is allowed.
922 *
923 * You should not call mpack_finish_str() after calling this; this
924 * performs both start and finish.
925 *
926 * @throws mpack_error_invalid if the string is not valid UTF-8
927 */
928void mpack_write_utf8_cstr_or_nil(mpack_writer_t* writer, const char* cstr);
929
930/**
931 * Writes a binary blob.
932 *
933 * To stream a binary blob in chunks, use mpack_start_bin() instead.
934 *
935 * You should not call mpack_finish_bin() after calling this; this
936 * performs both start and finish.
937 */
938void mpack_write_bin(mpack_writer_t* writer, const char* data, uint32_t count);
939
940#if MPACK_EXTENSIONS
941/**
942 * Writes an extension type.
943 *
944 * To stream an extension blob in chunks, use mpack_start_ext() instead.
945 *
946 * Extension types [0, 127] are available for application-specific types. Extension
947 * types [-128, -1] are reserved for future extensions of MessagePack.
948 *
949 * You should not call mpack_finish_ext() after calling this; this
950 * performs both start and finish.
951 *
952 * @note This requires @ref MPACK_EXTENSIONS.
953 */
954void mpack_write_ext(mpack_writer_t* writer, int8_t exttype, const char* data, uint32_t count);
955#endif
956
957/**
958 * @}
959 */
960
961/**
962 * @name Chunked Data Functions
963 * @{
964 */
965
966/**
967 * Opens a string. `count` bytes should be written with calls to
968 * mpack_write_bytes(), and mpack_finish_str() should be called
969 * when done.
970 *
971 * To write an entire string at once, use mpack_write_str() or
972 * mpack_write_cstr() instead.
973 *
974 * MPack does not care about the underlying encoding, but UTF-8 is highly
975 * recommended, especially for compatibility with JSON.
976 */
977void mpack_start_str(mpack_writer_t* writer, uint32_t count);
978
979/**
980 * Opens a binary blob. `count` bytes should be written with calls to
981 * mpack_write_bytes(), and mpack_finish_bin() should be called
982 * when done.
983 */
984void mpack_start_bin(mpack_writer_t* writer, uint32_t count);
985
986#if MPACK_EXTENSIONS
987/**
988 * Opens an extension type. `count` bytes should be written with calls
989 * to mpack_write_bytes(), and mpack_finish_ext() should be called
990 * when done.
991 *
992 * Extension types [0, 127] are available for application-specific types. Extension
993 * types [-128, -1] are reserved for future extensions of MessagePack.
994 *
995 * @note This requires @ref MPACK_EXTENSIONS.
996 */
997void mpack_start_ext(mpack_writer_t* writer, int8_t exttype, uint32_t count);
998#endif
999
1000/**
1001 * Writes a portion of bytes for a string, binary blob or extension type which
1002 * was opened by mpack_write_tag() or one of the mpack_start_*() functions.
1003 *
1004 * This can be called multiple times to write the data in chunks, as long as
1005 * the total amount of bytes written matches the count given when the compound
1006 * type was started.
1007 *
1008 * The corresponding mpack_finish_*() function must be called when done.
1009 *
1010 * To write an entire string, binary blob or extension type at
1011 * once, use one of the mpack_write_*() functions instead.
1012 *
1013 * @see mpack_write_tag()
1014 * @see mpack_start_str()
1015 * @see mpack_start_bin()
1016 * @see mpack_start_ext()
1017 * @see mpack_finish_str()
1018 * @see mpack_finish_bin()
1019 * @see mpack_finish_ext()
1020 * @see mpack_finish_type()
1021 */
1022void mpack_write_bytes(mpack_writer_t* writer, const char* data, size_t count);
1023
1024/**
1025 * Finishes writing a string.
1026 *
1027 * This should be called only after a corresponding call to mpack_start_str()
1028 * and after the string bytes are written with mpack_write_bytes().
1029 *
1030 * This will track writes to ensure that the correct number of elements are written.
1031 *
1032 * @see mpack_start_str()
1033 * @see mpack_write_bytes()
1034 */
1035MPACK_INLINE void mpack_finish_str(mpack_writer_t* writer) {
1036 mpack_writer_track_pop(writer, mpack_type_str);
1037}
1038
1039/**
1040 * Finishes writing a binary blob.
1041 *
1042 * This should be called only after a corresponding call to mpack_start_bin()
1043 * and after the binary bytes are written with mpack_write_bytes().
1044 *
1045 * This will track writes to ensure that the correct number of bytes are written.
1046 *
1047 * @see mpack_start_bin()
1048 * @see mpack_write_bytes()
1049 */
1050MPACK_INLINE void mpack_finish_bin(mpack_writer_t* writer) {
1051 mpack_writer_track_pop(writer, mpack_type_bin);
1052}
1053
1054#if MPACK_EXTENSIONS
1055/**
1056 * Finishes writing an extended type binary data blob.
1057 *
1058 * This should be called only after a corresponding call to mpack_start_bin()
1059 * and after the binary bytes are written with mpack_write_bytes().
1060 *
1061 * This will track writes to ensure that the correct number of bytes are written.
1062 *
1063 * @note This requires @ref MPACK_EXTENSIONS.
1064 *
1065 * @see mpack_start_ext()
1066 * @see mpack_write_bytes()
1067 */
1068MPACK_INLINE void mpack_finish_ext(mpack_writer_t* writer) {
1069 mpack_writer_track_pop(writer, mpack_type_ext);
1070}
1071#endif
1072
1073/**
1074 * Finishes writing the given compound type.
1075 *
1076 * This will track writes to ensure that the correct number of elements
1077 * or bytes are written.
1078 *
1079 * This can be called with the appropriate type instead the corresponding
1080 * mpack_finish_*() function if you want to finish a dynamic type.
1081 */
1082MPACK_INLINE void mpack_finish_type(mpack_writer_t* writer, mpack_type_t type) {
1083 mpack_writer_track_pop(writer, type);
1084}
1085
1086/**
1087 * @}
1088 */
1089
1090#if MPACK_HAS_GENERIC && !defined(__cplusplus)
1091
1092/**
1093 * @name Type-Generic Writers
1094 * @{
1095 */
1096
1097/**
1098 * @def mpack_write(writer, value)
1099 *
1100 * Type-generic writer for primitive types.
1101 *
1102 * The compiler will dispatch to an appropriate write function based
1103 * on the type of the @a value parameter.
1104 *
1105 * @note This requires C11 `_Generic` support. (A set of inline overloads
1106 * are used in C++ to provide the same functionality.)
1107 *
1108 * @warning In C11, the indentifiers `true`, `false` and `NULL` are
1109 * all of type `int`, not `bool` or `void*`! They will emit unexpected
1110 * types when passed uncast, so be careful when using them.
1111 */
1112#if MPACK_FLOAT
1113 #define MPACK_WRITE_GENERIC_FLOAT float: mpack_write_float,
1114#else
1115 #define MPACK_WRITE_GENERIC_FLOAT /*nothing*/
1116#endif
1117#if MPACK_DOUBLE
1118 #define MPACK_WRITE_GENERIC_DOUBLE double: mpack_write_double,
1119#else
1120 #define MPACK_WRITE_GENERIC_DOUBLE /*nothing*/
1121#endif
1122#define mpack_write(writer, value) \
1123 _Generic(((void)0, value), \
1124 int8_t: mpack_write_i8, \
1125 int16_t: mpack_write_i16, \
1126 int32_t: mpack_write_i32, \
1127 int64_t: mpack_write_i64, \
1128 uint8_t: mpack_write_u8, \
1129 uint16_t: mpack_write_u16, \
1130 uint32_t: mpack_write_u32, \
1131 uint64_t: mpack_write_u64, \
1132 bool: mpack_write_bool, \
1133 MPACK_WRITE_GENERIC_FLOAT \
1134 MPACK_WRITE_GENERIC_DOUBLE \
1135 char *: mpack_write_cstr_or_nil, \
1136 const char *: mpack_write_cstr_or_nil \
1137 )(writer, value)
1138
1139/**
1140 * @def mpack_write_kv(writer, key, value)
1141 *
1142 * Type-generic writer for key-value pairs of null-terminated string
1143 * keys and primitive values.
1144 *
1145 * @warning @a writer may be evaluated multiple times.
1146 *
1147 * @warning In C11, the indentifiers `true`, `false` and `NULL` are
1148 * all of type `int`, not `bool` or `void*`! They will emit unexpected
1149 * types when passed uncast, so be careful when using them.
1150 *
1151 * @param writer The writer.
1152 * @param key A null-terminated C string.
1153 * @param value A primitive type supported by mpack_write().
1154 */
1155#define mpack_write_kv(writer, key, value) do { \
1156 mpack_write_cstr(writer, key); \
1157 mpack_write(writer, value); \
1158} while (0)
1159
1160/**
1161 * @}
1162 */
1163
1164#endif // MPACK_HAS_GENERIC && !defined(__cplusplus)
1165
1166// The rest of this file contains C++ overloads, so we end extern "C" here.
1167MPACK_EXTERN_C_END
1168
1169#if defined(__cplusplus) || defined(MPACK_DOXYGEN)
1170
1171/**
1172 * @name C++ write overloads
1173 * @{
1174 */
1175
1176/*
1177 * C++ generic writers for primitive values
1178 */
1179
1180#ifdef MPACK_DOXYGEN
1181#undef mpack_write
1182#undef mpack_write_kv
1183#endif
1184
1185MPACK_INLINE void mpack_write(mpack_writer_t* writer, int8_t value) {
1186 mpack_write_i8(writer, value);
1187}
1188
1189MPACK_INLINE void mpack_write(mpack_writer_t* writer, int16_t value) {
1190 mpack_write_i16(writer, value);
1191}
1192
1193MPACK_INLINE void mpack_write(mpack_writer_t* writer, int32_t value) {
1194 mpack_write_i32(writer, value);
1195}
1196
1197MPACK_INLINE void mpack_write(mpack_writer_t* writer, int64_t value) {
1198 mpack_write_i64(writer, value);
1199}
1200
1201MPACK_INLINE void mpack_write(mpack_writer_t* writer, uint8_t value) {
1202 mpack_write_u8(writer, value);
1203}
1204
1205MPACK_INLINE void mpack_write(mpack_writer_t* writer, uint16_t value) {
1206 mpack_write_u16(writer, value);
1207}
1208
1209MPACK_INLINE void mpack_write(mpack_writer_t* writer, uint32_t value) {
1210 mpack_write_u32(writer, value);
1211}
1212
1213MPACK_INLINE void mpack_write(mpack_writer_t* writer, uint64_t value) {
1214 mpack_write_u64(writer, value);
1215}
1216
1217MPACK_INLINE void mpack_write(mpack_writer_t* writer, bool value) {
1218 mpack_write_bool(writer, value);
1219}
1220
1221MPACK_INLINE void mpack_write(mpack_writer_t* writer, float value) {
1222 mpack_write_float(writer, value);
1223}
1224
1225MPACK_INLINE void mpack_write(mpack_writer_t* writer, double value) {
1226 mpack_write_double(writer, value);
1227}
1228
1229MPACK_INLINE void mpack_write(mpack_writer_t* writer, char *value) {
1230 mpack_write_cstr_or_nil(writer, value);
1231}
1232
1233MPACK_INLINE void mpack_write(mpack_writer_t* writer, const char *value) {
1234 mpack_write_cstr_or_nil(writer, value);
1235}
1236
1237/* C++ generic write for key-value pairs */
1238
1239MPACK_INLINE void mpack_write_kv(mpack_writer_t* writer, const char *key, int8_t value) {
1240 mpack_write_cstr(writer, key);
1241 mpack_write_i8(writer, value);
1242}
1243
1244MPACK_INLINE void mpack_write_kv(mpack_writer_t* writer, const char *key, int16_t value) {
1245 mpack_write_cstr(writer, key);
1246 mpack_write_i16(writer, value);
1247}
1248
1249MPACK_INLINE void mpack_write_kv(mpack_writer_t* writer, const char *key, int32_t value) {
1250 mpack_write_cstr(writer, key);
1251 mpack_write_i32(writer, value);
1252}
1253
1254MPACK_INLINE void mpack_write_kv(mpack_writer_t* writer, const char *key, int64_t value) {
1255 mpack_write_cstr(writer, key);
1256 mpack_write_i64(writer, value);
1257}
1258
1259MPACK_INLINE void mpack_write_kv(mpack_writer_t* writer, const char *key, uint8_t value) {
1260 mpack_write_cstr(writer, key);
1261 mpack_write_u8(writer, value);
1262}
1263
1264MPACK_INLINE void mpack_write_kv(mpack_writer_t* writer, const char *key, uint16_t value) {
1265 mpack_write_cstr(writer, key);
1266 mpack_write_u16(writer, value);
1267}
1268
1269MPACK_INLINE void mpack_write_kv(mpack_writer_t* writer, const char *key, uint32_t value) {
1270 mpack_write_cstr(writer, key);
1271 mpack_write_u32(writer, value);
1272}
1273
1274MPACK_INLINE void mpack_write_kv(mpack_writer_t* writer, const char *key, uint64_t value) {
1275 mpack_write_cstr(writer, key);
1276 mpack_write_u64(writer, value);
1277}
1278
1279MPACK_INLINE void mpack_write_kv(mpack_writer_t* writer, const char *key, bool value) {
1280 mpack_write_cstr(writer, key);
1281 mpack_write_bool(writer, value);
1282}
1283
1284MPACK_INLINE void mpack_write_kv(mpack_writer_t* writer, const char *key, float value) {
1285 mpack_write_cstr(writer, key);
1286 mpack_write_float(writer, value);
1287}
1288
1289MPACK_INLINE void mpack_write_kv(mpack_writer_t* writer, const char *key, double value) {
1290 mpack_write_cstr(writer, key);
1291 mpack_write_double(writer, value);
1292}
1293
1294MPACK_INLINE void mpack_write_kv(mpack_writer_t* writer, const char *key, char *value) {
1295 mpack_write_cstr(writer, key);
1296 mpack_write_cstr_or_nil(writer, value);
1297}
1298
1299MPACK_INLINE void mpack_write_kv(mpack_writer_t* writer, const char *key, const char *value) {
1300 mpack_write_cstr(writer, key);
1301 mpack_write_cstr_or_nil(writer, value);
1302}
1303
1304/**
1305 * @}
1306 */
1307
1308#endif /* __cplusplus */
1309
1310/**
1311 * @}
1312 */
1313
1314MPACK_SILENCE_WARNINGS_END
1315
1316#endif // MPACK_WRITER
1317
1318#endif
1319