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