All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
as_bytes.h
Go to the documentation of this file.
1 /*
2  * Copyright 2008-2015 Aerospike, Inc.
3  *
4  * Portions may be licensed to Aerospike, Inc. under one or more contributor
5  * license agreements.
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License"); you may not
8  * use this file except in compliance with the License. You may obtain a copy of
9  * the License at http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14  * License for the specific language governing permissions and limitations under
15  * the License.
16  */
17 
18 #pragma once
19 
20 #include <aerospike/as_util.h>
21 #include <aerospike/as_val.h>
22 
23 #include <stdbool.h>
24 #include <stdint.h>
25 #include <string.h>
26 
27 #ifdef __cplusplus
28 extern "C" {
29 #endif
30 
31 /******************************************************************************
32  * TYPES
33  *****************************************************************************/
34 
35 /**
36  * Types for `as_bytes.type`
37  */
38 typedef enum as_bytes_type_e {
39 
40  /**
41  * Type is Undefined
42  */
44 
45  /**
46  * String
47  */
49 
50  /**
51  * Double
52  */
54 
55  /**
56  * String
57  */
59 
60  /**
61  * Generic BLOB
62  */
64 
65  /**
66  * Serialized Java Object
67  */
69 
70  /**
71  * Serialized C# Object
72  */
74 
75  /**
76  * Pickled Python Object
77  */
79 
80  /**
81  * Marshalled Ruby Object
82  */
84 
85  /**
86  * Serialized PHP Object
87  */
89 
90  /**
91  * Serialized Erlang Data
92  */
94 
95  /**
96  * Map
97  */
99 
100  /**
101  * List
102  */
104 
105  /**
106  * Large Date Type
107  */
109 
110  /**
111  * Upper bounds for the enum
112  */
114 
115 } as_bytes_type;
116 
117 /**
118  * Container for byte arrays.
119  *
120  * ## Initialization
121  *
122  * An as_bytes should be initialized via one of the provided function.
123  * - as_bytes_inita()
124  * - as_bytes_init()
125  * - as_bytes_new()
126  *
127  * The as_bytes_inita(), as_bytes_init() and as_bytes_new() are used to
128  * initialize empty internal buffers of a specified size.
129  *
130  * To initialize a stack allocated as_string, use as_bytes_init():
131  *
132  * ~~~~~~~~~~{.c}
133  * as_bytes b;
134  * as_bytes_init(&b, 20);
135  * ~~~~~~~~~~
136  *
137  * The above initialized the variable, and allocated 20 bytes to the buffer
138  * using `cf_malloc()`.
139  *
140  * To use only stack allocated buffer for as_bytes, ten you should use
141  * as_bytes_inita():
142  *
143  * ~~~~~~~~~~{.c}
144  * as_bytes b;
145  * as_bytes_inita(&b, 20);
146  * ~~~~~~~~~~
147  *
148  * You will see the APIs of the two are very similar. The key difference is
149  * as_bytes_inita() is a macro, which performs stack allocation inline.
150  *
151  * If you need a heap allocated as_bytes instance, then you should use
152  * as_bytes_new():
153  *
154  * ~~~~~~~~~~{.c}
155  * as_bytes * b = as_bytes_new(20);
156  * ~~~~~~~~~~
157  *
158  * ## Wrapping Byte Arrays
159  *
160  * If you already have a byte array allocated and want to simply wrap it
161  * in an as_bytes, then use either:
162  * - as_bytes_init_wrap()
163  * - as_bytes_new_wrap()
164  *
165  * The as_bytes_init_wrap() function is used to initialize a stack allocated
166  * as_bytes, then set the internal buffer to the byte array provided.
167  *
168  * The as_bytes_new_wrap() function is used to create an initialize a new
169  * heap allocated as_bytes, then it will set the internal buffer to the
170  * byte array provided.
171  *
172  *
173  * ## Destruction
174  *
175  * When the as_bytes instance is no longer required, then you should
176  * release the resources associated with it via as_bytes_destroy():
177  *
178  * ~~~~~~~~~~{.c}
179  * as_bytes_destroy(b);
180  * ~~~~~~~~~~
181  *
182  * ## Usage
183  *
184  * as_bytes has a number of functions for reading and writing data to its
185  * internal buffer.
186  *
187  * For reading at specified index:
188  *
189  * | Function | Description |
190  * | -------- | ----------- |
191  * | as_bytes_get() | Copy the bytes in the buffer to another buffer. |
192  * | as_bytes_get_byte() | Read a byte from the buffer |
193  * | as_bytes_get_int16() | Read a 16-bit integer from the buffer |
194  * | as_bytes_get_int32() | Read a 32-bit integer from the buffer |
195  * | as_bytes_get_int64() | Read a 64-bit integer from the buffer |
196  *
197  * For writing at specified index:
198  *
199  * | Function | Description |
200  * | -------- | ----------- |
201  * | as_bytes_set() | Copy a byte array into the buffer. |
202  * | as_bytes_set_byte() | Write a byte from the buffer |
203  * | as_bytes_set_int16() | Write a 16-bit integer from the buffer |
204  * | as_bytes_set_int32() | Write a 32-bit integer from the buffer |
205  * | as_bytes_set_int64() | Write a 64-bit integer from the buffer |
206  *
207  * For writing at to the end of the buffer:
208  *
209  * | Function | Description |
210  * | -------- | ----------- |
211  * | as_bytes_append() | Copy a byte array into the buffer. |
212  * | as_bytes_append_byte() | Write a byte from the buffer |
213  * | as_bytes_append_int16() | Write a 16-bit integer from the buffer |
214  * | as_bytes_append_int32() | Write a 32-bit integer from the buffer |
215  * | as_bytes_append_int64() | Write a 64-bit integer from the buffer |
216  *
217  *
218  * ## Conversions
219  *
220  * as_bytes is derived from as_val, so it is generally safe to down cast:
221  *
222  * ~~~~~~~~~~{.c}
223  * as_val val = (as_val) b;
224  * ~~~~~~~~~~
225  *
226  * However, upcasting is more error prone. When doing so, you should use
227  * as_bytes_fromval(). If conversion fails, then the return value is NULL.
228  *
229  * ~~~~~~~~~~{.c}
230  * as_bytes * i = as_bytes_fromval(val);
231  * ~~~~~~~~~~
232  *
233  *
234  *
235  * @extends as_val
236  * @ingroup aerospike_t
237  */
238 typedef struct as_bytes_s {
239 
240  /**
241  * @private
242  * as_boolean is a subtype of as_val.
243  * You can cast as_boolean to as_val.
244  */
246 
247  /**
248  * The number of bytes allocated to `as_bytes.value`.
249  */
250  uint32_t capacity;
251 
252  /**
253  * The number of bytes used by `as_bytes.value`.
254  */
255  uint32_t size;
256 
257  /**
258  * A sequence of bytes.
259  */
260  uint8_t * value;
261 
262  /**
263  * If true, then `as_bytes.value` will be freed when as_bytes_destroy()
264  * is called.
265  */
266  bool free;
267 
268  /**
269  * The type of bytes.
270  */
272 
273 } as_bytes;
274 
275 /******************************************************************************
276  * MACROS
277  *****************************************************************************/
278 
279 /**
280  * Initializes a stack allocated `as_bytes`. Allocates an internal buffer
281  * on the stack of specified capacity using `alloca()`.
282  *
283  * ~~~~~~~~~~{.c}
284  * as_bytes bytes;
285  * as_bytes_inita(&bytes, 10);
286  * ~~~~~~~~~~
287  *
288  * @param __bytes The bytes to initialize.
289  * @param __capacity The number of bytes to allocate on the heap.
290  */
291 #define as_bytes_inita(__bytes, __capacity)\
292  as_bytes_init(__bytes, 0);\
293  (__bytes)->type = AS_BYTES_BLOB;\
294  (__bytes)->free = false;\
295  (__bytes)->capacity = __capacity;\
296  (__bytes)->size = 0;\
297  (__bytes)->value = (uint8_t *) alloca(__capacity * sizeof(uint8_t));
298 
299 
300 /******************************************************************************
301  * INSTANCE FUNCTIONS
302  *****************************************************************************/
303 
304 /**
305  * Initializes a stack allocated `as_bytes`. Allocates an internal buffer
306  * on the heap of specified capacity using `cf_malloc()`.
307  *
308  * ~~~~~~~~~~{.c}
309  * as_bytes bytes;
310  * as_bytes_init_empty(&bytes, 10);
311  * ~~~~~~~~~~
312  *
313  * @param bytes The bytes to initialize.
314  * @param capacity The number of bytes to allocate on the heap.
315  *
316  * @return On success, the initializes bytes. Otherwise NULL.
317  *
318  * @relatesalso as_bytes
319  */
320 as_bytes * as_bytes_init(as_bytes * bytes, uint32_t capacity);
321 
322 /**
323  * Initializes a stack allocated `as_bytes`, wrapping the given buffer.
324  *
325  * ~~~~~~~~~~{.c}
326  * uint8_t raw[10] = {0};
327  *
328  * as_bytes bytes;
329  * as_bytes_init_wrap(&bytes, raw, 10, false);
330  * ~~~~~~~~~~
331  *
332  * @param bytes The bytes to initialize.
333  * @param value The initial value.
334  * @param size The number of bytes of the initial value.
335  * @param free If true, then `as_bytes_destroy()` will free the value.
336  *
337  * @return On success, the initializes bytes. Otherwise NULL.
338  *
339  * @relatesalso as_bytes
340  */
341 as_bytes * as_bytes_init_wrap(as_bytes * bytes, uint8_t * value, uint32_t size, bool free);
342 
343 /**
344  * Create and initialize a new heap allocated `as_bytes`. Allocates an
345  * internal buffer on the heap of specified capacity using `cf_malloc()`.
346  *
347  * ~~~~~~~~~~{.c}
348  * as_bytes * bytes = as_bytes_new(10);
349  * ~~~~~~~~~~
350  *
351  * @param capacity The number of bytes to allocate.
352  *
353  * @return On success, the initializes bytes. Otherwise NULL.
354  *
355  * @relatesalso as_bytes
356  */
357 as_bytes * as_bytes_new(uint32_t capacity);
358 
359 /**
360  * Creates a new heap allocated `as_bytes`, wrapping the given buffer.
361  *
362  * ~~~~~~~~~~{.c}
363  * uint8_t raw[10] = {0};
364  *
365  * as_bytes * bytes = as_bytes_new_wrap(raw, 10, false);
366  * ~~~~~~~~~~
367  *
368  * @param value The initial value.
369  * @param size The number of bytes of the initial value.
370  * @param free If true, then `as_bytes_destroy()` will free the value.
371  *
372  * @return On success, the initializes bytes. Otherwise NULL.
373  *
374  * @relatesalso as_bytes
375  */
376 as_bytes * as_bytes_new_wrap(uint8_t * value, uint32_t size, bool free);
377 
378 /**
379  * Destroy the `as_bytes` and release associated resources.
380  *
381  * ~~~~~~~~~~{.c}
382  * as_bytes_destroy(bytes);
383  * ~~~~~~~~~~
384  *
385  * @param bytes The bytes to destroy.
386  *
387  * @relatesalso as_bytes
388  */
389 static inline void as_bytes_destroy(as_bytes * bytes)
390 {
391  as_val_destroy((as_val *) bytes);
392 }
393 
394 /******************************************************************************
395  * VALUE FUNCTIONS
396  *****************************************************************************/
397 
398 /**
399  * Get the number of bytes used.
400  *
401  * @param bytes The bytes to get the size of.
402  *
403  * @return The number of bytes used.
404  *
405  * @relatesalso as_bytes
406  */
407 static inline uint32_t as_bytes_size(const as_bytes * bytes)
408 {
409  if ( !bytes ) return 0;
410  return bytes->size;
411 }
412 
413 /**
414  * Get the number of bytes allocated.
415  *
416  * @param bytes The bytes to get the capacity of.
417  *
418  * @return The number of bytes allocated.
419  *
420  * @relatesalso as_bytes
421  */
422 static inline uint32_t as_bytes_capacity(const as_bytes * bytes)
423 {
424  if ( !bytes ) return 0;
425  return bytes->capacity;
426 }
427 
428 /**
429  * Get the type of bytes.
430  *
431  * @param bytes The bytes to get the type of.
432  *
433  * @return The type of bytes.
434  *
435  * @relatesalso as_bytes
436  */
437 static inline as_bytes_type as_bytes_get_type(const as_bytes * bytes)
438 {
439  if ( !bytes ) return AS_BYTES_UNDEF;
440  return bytes->type;
441 }
442 
443 /**
444  * Set the type of bytes.
445  *
446  * @param bytes The bytes to set the type of.
447  * @param type The type for the bytes.
448  *
449  * @relatesalso as_bytes
450  */
451 static inline void as_bytes_set_type(as_bytes * bytes, as_bytes_type type)
452 {
453  if ( !bytes ) return;
454  bytes->type = type;
455 }
456 
457 /**
458  * Get the raw value of this instance. If the instance is NULL, then
459  * return the fallback value.
460  *
461  * ~~~~~~~~~~{.c}
462  * uint8_t * raw = as_bytes_getorelse(&bytes, NULL);
463  * ~~~~~~~~~~
464  *
465  * @param bytes The bytes to get the raw value from.
466  * @param fallback The value to return if bytes is NULL.
467  *
468  * @return The pointer to the raw value if bytes is not NULL. Otherwise
469  * return the fallback.
470  *
471  * @relatesalso as_bytes
472  */
473 static inline uint8_t * as_bytes_getorelse(const as_bytes * bytes, uint8_t * fallback)
474 {
475  return bytes ? bytes->value : fallback;
476 }
477 
478 /**
479  * Get the raw value of this instance.
480  *
481  * ~~~~~~~~~~{.c}
482  * uint8_t * raw = as_bytes_get(&bytes);
483  * ~~~~~~~~~~
484  *
485  * @param bytes The bytes to get the raw value from.
486  *
487  * @return The pointer to the raw value.
488  *
489  * @relatesalso as_bytes
490  */
491 static inline uint8_t * as_bytes_get(const as_bytes * bytes)
492 {
493  return as_bytes_getorelse(bytes, NULL);
494 }
495 
496 
497 /******************************************************************************
498  * GET AT INDEX
499  *****************************************************************************/
500 
501 
502 /**
503  * Copy into value up to size bytes from the given `as_bytes`, returning
504  * the number of bytes copied.
505  *
506  * ~~~~~~~~~~{.c}
507  * uint8_t value[3] = {0};
508  * uint32_t sz = as_bytes_copy(&bytes, 0, value, 3);
509  * if ( sz == 0 ) {
510  * // sz == 0, means that an error occurred
511  * }
512  * ~~~~~~~~~~
513  *
514  * @param bytes The bytes to read from.
515  * @param index The positing in bytes to read from.
516  * @param value The byte buffer to copy into.
517  * @param size The number of bytes to copy into the buffer.
518  *
519  *
520  * @return The number of bytes read and stored into value. 0 (zero) indicates
521  * an error has occurred.
522  *
523  * @relatesalso as_bytes
524  */
525 uint32_t as_bytes_copy(const as_bytes * bytes, uint32_t index, uint8_t * value, uint32_t size);
526 
527 /**
528  * Read a single byte from the given bytes.
529  *
530  * ~~~~~~~~~~{.c}
531  * uint8_t value = 0;
532  * uint32_t sz = as_bytes_get_byte(&bytes, 0, &value);
533  * if ( sz == 0 ) {
534  * // sz == 0, means that an error occurred
535  * }
536  * ~~~~~~~~~~
537  *
538  * @return The number of bytes read and stored into value. 0 (zero) indicates
539  * an error has occurred.
540  *
541  * @relatesalso as_bytes
542  */
543 static inline uint32_t as_bytes_get_byte(const as_bytes * bytes, uint32_t index, uint8_t * value)
544 {
545  return as_bytes_copy(bytes, index, (uint8_t *) value, 1);
546 }
547 
548 /**
549  * Read an int16_t from the given bytes.
550  *
551  * ~~~~~~~~~~{.c}
552  * int16_t value = 0;
553  * uint32_t sz = as_bytes_get_int16(&bytes, 0, &value);
554  * if ( sz == 0 ) {
555  * // sz == 0, means that an error occurred
556  * }
557  * ~~~~~~~~~~
558  *
559  * @return The number of bytes read and stored into value. 0 (zero) indicates
560  * an error has occurred.
561  *
562  * @relatesalso as_bytes
563  */
564 static inline uint32_t as_bytes_get_int16(const as_bytes * bytes, uint32_t index, int16_t * value)
565 {
566  return as_bytes_copy(bytes, index, (uint8_t *) value, 2);
567 }
568 
569 /**
570  * Read an int32_t from the given bytes.
571  *
572  * ~~~~~~~~~~{.c}
573  * int32_t value = 0;
574  * uint32_t sz = as_bytes_get_int32(&bytes, 0, &value);
575  * if ( sz == 0 ) {
576  * // sz == 0, means that an error occurred
577  * }
578  * ~~~~~~~~~~
579  *
580  * @return The number of bytes read and stored into value. 0 (zero) indicates
581  * an error has occurred.
582  *
583  * @relatesalso as_bytes
584  */
585 static inline uint32_t as_bytes_get_int32(const as_bytes * bytes, uint32_t index, int32_t * value)
586 {
587  return as_bytes_copy(bytes, index, (uint8_t *) value, 4);
588 }
589 
590 /**
591  * Read an int64_t from the given bytes.
592  *
593  * ~~~~~~~~~~{.c}
594  * int64_t value = 0;
595  * uint32_t sz = as_bytes_get_int64(&bytes, 0, &value);
596  * if ( sz == 0 ) {
597  * // sz == 0, means that an error occurred
598  * }
599  * ~~~~~~~~~~
600  *
601  * @return The number of bytes read and stored into value. 0 (zero) indicates
602  * an error has occurred.
603  *
604  * @relatesalso as_bytes
605  */
606 static inline uint32_t as_bytes_get_int64(const as_bytes * bytes, uint32_t index, int64_t * value)
607 {
608  return as_bytes_copy(bytes, index, (uint8_t *) value, 8);
609 }
610 
611 /**
612  * Read a double from the given bytes.
613  *
614  * ~~~~~~~~~~{.c}
615  * double value = 0;
616  * uint32_t sz = as_bytes_get_double(&bytes, 0, &value);
617  * if ( sz == 0 ) {
618  * // sz == 0, means that an error occurred
619  * }
620  * ~~~~~~~~~~
621  *
622  * @return The number of bytes read and stored into value. 0 (zero) indicates
623  * an error has occurred.
624  *
625  * @relatesalso as_bytes
626  */
627 static inline uint32_t as_bytes_get_double(const as_bytes * bytes, uint32_t index, double * value)
628 {
629  return as_bytes_copy(bytes, index, (uint8_t *) value, 8);
630 }
631 
632 /**
633  * Decode an integer in variable 7-bit format.
634  * The high bit indicates if more bytes are used.
635  *
636  * ~~~~~~~~~~{.c}
637  * uint32_t value = 0;
638  * uint32_t sz = as_bytes_get_var_int(&bytes, 0, &value);
639  * if ( sz == 0 ) {
640  * // sz == 0, means that an error occurred
641  * }
642  * ~~~~~~~~~~
643  *
644  * @return The number of bytes copied in to value.
645  *
646  * @relatesalso as_bytes
647  */
648 uint32_t as_bytes_get_var_int(const as_bytes * bytes, uint32_t index, uint32_t * value);
649 
650 /******************************************************************************
651  * SET AT INDEX
652  *****************************************************************************/
653 
654 /**
655  * Copy raw bytes of given size into the given `as_bytes` starting at
656  * specified index.
657  *
658  * ~~~~~~~~~~{.c}
659  * as_bytes_set(&bytes, 0, (uint8_t[]){'a','b','c'}, 3);
660  * ~~~~~~~~~~
661  *
662  * @param bytes The bytes to write to.
663  * @param index The position to write to.
664  * @param value The buffer to read from.
665  * @param size The number of bytes to read from the value.
666  *
667  * @return On success, true. Otherwise an error occurred.
668  *
669  * @relatesalso as_bytes
670  */
671 bool as_bytes_set(as_bytes * bytes, uint32_t index, const uint8_t * value, uint32_t size);
672 
673 /**
674  * Set a byte at given index.
675  *
676  * ~~~~~~~~~~{.c}
677  * as_bytes_set_byte(&bytes, 0, 'a');
678  * ~~~~~~~~~~
679  *
680  * @return On success, true. Otherwise an error occurred.
681  *
682  * @relatesalso as_bytes
683  */
684 static inline bool as_bytes_set_byte(as_bytes * bytes, uint32_t index, uint8_t value)
685 {
686  return as_bytes_set(bytes, index, (uint8_t *) &value, 1);
687 }
688 
689 /**
690  * Set 16 bit integer at given index.
691  *
692  * ~~~~~~~~~~{.c}
693  * as_bytes_set_int16(&bytes, 0, 1);
694  * ~~~~~~~~~~
695  *
696  * @return On success, true. Otherwise an error occurred.
697  *
698  * @relatesalso as_bytes
699  */
700 static inline bool as_bytes_set_int16(as_bytes * bytes, uint32_t index, int16_t value)
701 {
702  return as_bytes_set(bytes, index, (uint8_t *) &value, 2);
703 }
704 
705 /**
706  * Set 32 bit integer at given index.
707  *
708  * ~~~~~~~~~~{.c}
709  * as_bytes_set_int32(&bytes, 0, 2);
710  * ~~~~~~~~~~
711  *
712  * @return On success, true. Otherwise an error occurred.
713  *
714  * @relatesalso as_bytes
715  */
716 static inline bool as_bytes_set_int32(as_bytes * bytes, uint32_t index, int32_t value)
717 {
718  return as_bytes_set(bytes, index, (uint8_t *) &value, 4);
719 }
720 
721 /**
722  * Set 64 bit integer at given index.
723  *
724  * ~~~~~~~~~~{.c}
725  * as_bytes_set_int64(&bytes, 0, 3);
726  * ~~~~~~~~~~
727  *
728  * @return On success, true. Otherwise an error occurred.
729  *
730  * @relatesalso as_bytes
731  */
732 static inline bool as_bytes_set_int64(as_bytes * bytes, uint32_t index, int64_t value)
733 {
734  return as_bytes_set(bytes, index, (uint8_t *) &value, 8);
735 }
736 
737 /**
738  * Set double at given index.
739  *
740  * ~~~~~~~~~~{.c}
741  * as_bytes_set_double(&bytes, 0, 4.4);
742  * ~~~~~~~~~~
743  *
744  * @return On success, true. Otherwise an error occurred.
745  *
746  * @relatesalso as_bytes
747  */
748 static inline bool as_bytes_set_double(as_bytes * bytes, uint32_t index, double value)
749 {
750  return as_bytes_set(bytes, index, (uint8_t *) &value, 8);
751 }
752 
753 /**
754  * Encode an integer in 7-bit format.
755  * The high bit indicates if more bytes are used.
756  *
757  * ~~~~~~~~~~{.c}
758  * as_bytes_set_var_int(&bytes, 0, 36);
759  * ~~~~~~~~~~
760  *
761  * The `bytes` must be sufficiently sized for the data being written.
762  * To ensure the `bytes` is allocated sufficiently, you will need to call
763  * `as_bytes_ensure()`.
764  *
765  * @return The number of bytes copied into byte array.
766  *
767  * @relatesalso as_bytes
768  */
769 uint32_t as_bytes_set_var_int(const as_bytes * bytes, uint32_t index, uint32_t value);
770 
771 /******************************************************************************
772  * APPEND TO THE END
773  *****************************************************************************/
774 
775 /**
776  * Append raw bytes of given size.
777  *
778  * ~~~~~~~~~~{.c}
779  * uint8_t value[3] = {'a','b','c'};
780  *
781  * as_bytes_append(&bytes, value, 3);
782  * ~~~~~~~~~~
783  *
784  * @param bytes The bytes to append to.
785  * @param value The buffer to read from.
786  * @param size The number of bytes to read from the value.
787  *
788  * @return On success, true. Otherwise an error occurred.
789  *
790  * @relatesalso as_bytes
791  */
792 bool as_bytes_append(as_bytes * bytes, const uint8_t * value, uint32_t size);
793 
794 /**
795  * Append a uint8_t (byte).
796  *
797  * ~~~~~~~~~~{.c}
798  * as_bytes_append_byte(&bytes, 'a');
799  * ~~~~~~~~~~
800  *
801  * @return On success, true. Otherwise an error occurred.
802  *
803  * @relatesalso as_bytes
804  */
805 static inline bool as_bytes_append_byte(as_bytes * bytes, uint8_t value)
806 {
807  return as_bytes_append(bytes, (uint8_t *) &value, 1);
808 }
809 
810 /**
811  * Append an int16_t value.
812  *
813  * ~~~~~~~~~~{.c}
814  * as_bytes_append_int16(&bytes, 123);
815  * ~~~~~~~~~~
816  *
817  * @return On success, true. Otherwise an error occurred.
818  *
819  * @relatesalso as_bytes
820  */
821 static inline bool as_bytes_append_int16(as_bytes * bytes, int16_t value)
822 {
823  return as_bytes_append(bytes, (uint8_t *) &value, 2);
824 }
825 
826 /**
827  * Append an int32_t value.
828  *
829  * ~~~~~~~~~~{.c}
830  * as_bytes_append_int32(&bytes, 123);
831  * ~~~~~~~~~~
832  *
833  * @return On success, true. Otherwise an error occurred.
834  *
835  * @relatesalso as_bytes
836  */
837 static inline bool as_bytes_append_int32(as_bytes * bytes, int32_t value)
838 {
839  return as_bytes_append(bytes, (uint8_t *) &value, 4);
840 }
841 
842 /**
843  * Append an int64_t value.
844  *
845  * ~~~~~~~~~~{.c}
846  * as_bytes_append_int64(&bytes, 123);
847  * ~~~~~~~~~~
848  *
849  * @return On success, true. Otherwise an error occurred.
850  *
851  * @relatesalso as_bytes
852  */
853 static inline bool as_bytes_append_int64(as_bytes * bytes, int64_t value)
854 {
855  return as_bytes_append(bytes, (uint8_t *) &value, 8);
856 }
857 
858 /**
859  * Append a double value.
860  *
861  * ~~~~~~~~~~{.c}
862  * as_bytes_append_double(&bytes, 123.456);
863  * ~~~~~~~~~~
864  *
865  * @return On success, true. Otherwise an error occurred.
866  *
867  * @relatesalso as_bytes
868  */
869 static inline bool as_bytes_append_double(as_bytes * bytes, double value)
870 {
871  return as_bytes_append(bytes, (uint8_t *) &value, 8);
872 }
873 
874 /******************************************************************************
875  * MODIFIES BUFFER
876  *****************************************************************************/
877 
878 /**
879  * Truncate the bytes' buffer. The size specifies the number of bytes to
880  * remove from the end of the buffer.
881  *
882  * This means, if the buffer has size of 100, and we truncate 10, then
883  * the remaining size is 90.
884 
885  * Truncation does not modify the capacity of the buffer.
886  *
887  * ~~~~~~~~~~{.c}
888  * as_bytes_truncate(&bytes, 10);
889  * ~~~~~~~~~~
890  *
891  * @param bytes The bytes to truncate.
892  * @param n The number of bytes to remove from the end.
893  *
894  * @return On success, true. Otherwise an error occurred.
895  *
896  * @relatesalso as_bytes
897  */
898 bool as_bytes_truncate(as_bytes * bytes, uint32_t n);
899 
900 /**
901  * Ensure the bytes buffer can handle `capacity` bytes.
902  *
903  * If `resize` is true and `capacity` exceeds the capacity of the bytes's
904  * buffer, then resize the capacity of the buffer to `capacity` bytes. If the
905  * buffer was heap allocated, then `cf_realloc()` will be used to resize. If the
906  * buffer was stack allocated, it will be converted to a heap allocated buffer
907  * using cf_malloc() and then its contents will be copied into the new heap
908  * allocated buffer.
909  *
910  * If `resize` is false, and if the capacity is not sufficient, then return
911  * false.
912  *
913  * ~~~~~~~~~~{.c}
914  * as_bytes_ensure(&bytes, 100, true);
915  * ~~~~~~~~~~
916  *
917  * @param bytes The bytes to ensure the capacity of.
918  * @param capacity The total number of bytes to ensure bytes can handle.
919  * @param resize If true and capacity is not sufficient, then resize the buffer.
920  *
921  * @return On success, true. Otherwise an error occurred.
922  *
923  * @relatesalso as_bytes
924  */
925 bool as_bytes_ensure(as_bytes * bytes, uint32_t capacity, bool resize);
926 
927 
928 /**
929  * Get the bytes value.
930  *
931  * @deprecated Use as_bytes_get() instead.
932  *
933  * @relatesalso as_bytes
934  */
935 static inline uint8_t * as_bytes_tobytes(const as_bytes * bytes, uint32_t * size)
936 {
937  if ( !bytes ) return NULL;
938 
939  if ( size ) {
940  *size = bytes->size;
941  }
942 
943  return bytes->value;
944 }
945 
946 /******************************************************************************
947  * CONVERSION FUNCTIONS
948  *****************************************************************************/
949 
950 /**
951  * Convert to an as_val.
952  *
953  * @relatesalso as_bytes
954  */
955 static inline as_val * as_bytes_toval(const as_bytes * b)
956 {
957  return (as_val *) b;
958 }
959 
960 /**
961  * Convert from an as_val.
962  *
963  * @relatesalso as_bytes
964  */
965 static inline as_bytes * as_bytes_fromval(const as_val * v)
966 {
967  return as_util_fromval(v, AS_BYTES, as_bytes);
968 }
969 
970 /******************************************************************************
971  * as_val FUNCTIONS
972  *****************************************************************************/
973 
974 /**
975  * @private
976  * Internal helper function for destroying an as_val.
977  */
978 void as_bytes_val_destroy(as_val * v);
979 
980 /**
981  * @private
982  * Internal helper function for getting the hashcode of an as_val.
983  */
984 uint32_t as_bytes_val_hashcode(const as_val * v);
985 
986 /**
987  * @private
988  * Internal helper function for getting the string representation of an as_val.
989  */
990 char * as_bytes_val_tostring(const as_val * v);
991 
992 #ifdef __cplusplus
993 } // end extern "C"
994 #endif