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