All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
as_record.h
Go to the documentation of this file.
1 /*
2  * Copyright 2008-2017 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 #pragma once
18 
19 #include <aerospike/as_bin.h>
20 #include <aerospike/as_bytes.h>
21 #include <aerospike/as_integer.h>
22 #include <aerospike/as_key.h>
23 #include <aerospike/as_list.h>
24 #include <aerospike/as_map.h>
25 #include <aerospike/as_rec.h>
26 #include <aerospike/as_string.h>
27 #include <aerospike/as_geojson.h>
28 #include <aerospike/as_util.h>
29 #include <aerospike/as_val.h>
30 
31 #include <stdbool.h>
32 #include <stdint.h>
33 
34 #ifdef __cplusplus
35 extern "C" {
36 #endif
37 
38 /******************************************************************************
39  * TYPES
40  *****************************************************************************/
41 
42 /**
43  * Records in Aerospike are collections of named bins.
44  *
45  * The bins in a record are analogous to columns in relational databases.
46  * However, unlike columns, the bins themselves are not typed. Instead, bins
47  * contain values which are typed. So, it is possible to have multiple records
48  * with bins of the same name but different types for values.
49  *
50  * The bin's value can only be of the types defined in `as_bin_value`.
51  *
52  * ## Initialization
53  *
54  * There are several ways to initialize an `as_record`.
55  *
56  * You can create the `as_record` on the stack:
57  *
58  * ~~~~~~~~~~{.c}
59  * as_record rec;
60  * ~~~~~~~~~~
61  *
62  * Then initialize it using either the `as_record_init()` function or
63  * `as_record_inita()` macro.
64  *
65  * The `as_record_init()` function will initialize the variable, then
66  * allocate the specified number of bins using `malloc()`. The following
67  * initializes `rec` with 2 bins.
68  *
69  * ~~~~~~~~~~{.c}
70  * as_record_init(&rec, 2);
71  * ~~~~~~~~~~
72  *
73  * The `as_record_inita()` macro will initialize the variable, then allocate
74  * the specified number of bins using `alloca()`. The following initializes
75  * `rec` with 2 bins.
76  *
77  * ~~~~~~~~~~{.c}
78  * as_record_inita(&rec, 2);
79  * ~~~~~~~~~~
80  *
81  * The `as_record_new()` function will allocate an `as_record` on the heap
82  * using `malloc()` then allocate the specified number of bins using
83  * `malloc()`. The following creates a new `as_record` with 2 bins.
84  *
85  * ~~~~~~~~~~{.c}
86  * as_record * rec = as_record_new(2);
87  * ~~~~~~~~~~
88  *
89  * ## Destruction
90  *
91  * When you no longer require an as_record, you should call `as_record_destroy()`
92  * to release the record and associated resources.
93  *
94  * ~~~~~~~~~~{.c}
95  * as_record_destroy(rec);
96  * ~~~~~~~~~~
97  *
98  * If the record has been ref-counted, then the ref-count will be decremented,
99  * until it reaches 0 (zero), at which point, the record will be released.
100  *
101  * ## Setting Bin Values
102  *
103  * The following are functions for setting values in bins of a record. Utilize
104  * the appropriate setter for the data you want to store in a bin.
105  *
106  * Function | Description
107  * ---------------------------- | ----------------------------------------------
108  * `as_record_set_int64()` | Set the bin value to a 64-bit integer.
109  * `as_record_set_str()` | Set the bin value to a NULL-terminated string.
110  * `as_record_set_integer()` | Set the bin value to an `as_integer`.
111  * `as_record_set_double()` | Set the bin value to an `as_double`.
112  * `as_record_set_string()` | Set the bin value to an `as_string`.
113  * `as_record_set_geojson()` | Set the bin value to an `as_geojson`.
114  * `as_record_set_bytes()` | Set the bin value to an `as_bytes`.
115  * `as_record_set_list()` | Set the bin value to an `as_list`.
116  * `as_record_set_map()` | Set the bin value to an `as_map`.
117  * `as_record_set_nil()` | Set the bin value to an `as_nil`.
118  * `as_record_set()` | Set the bin value to an `as_bin_value`.
119  *
120  * ## Getting Bin Values
121  *
122  * The following are functions for getting values from bins of a record.
123  * Utilize the appropriate getter for the data you want to read from a bin.
124  *
125  *
126  * Function | Description
127  * ---------------------------- | ----------------------------------------------
128  * `as_record_get_int64()` | Get the bin as a 64-bit integer.
129  * `as_record_get_str()` | Get the bin as a NULL-terminated string.
130  * `as_record_get_integer()` | Get the bin as an `as_integer`.
131  * `as_record_get_double()` | Get the bin as an `as_double`.
132  * `as_record_get_string()` | Get the bin as an `as_string`.
133  * `as_record_get_geojson()` | Get the bin as an `as_geojson`.
134  * `as_record_get_bytes()` | Get the bin as an `as_bytes`.
135  * `as_record_get_list()` | Get the bin as an `as_list`.
136  * `as_record_get_map()` | Get the bin as an `as_map`.
137  * `as_record_get()` | Get the bin as an `as_bin_value`.
138  *
139  * If you are unsure of the type of data stored in the bin, then you should
140  * use `as_record_get()`. You can then check the type of the value using
141  * `as_val_type()`.
142  *
143  * ~~~~~~~~~~{.c}
144  * as_bin_value * value = as_record_get(rec, "bin1");
145  * switch ( as_val_type(value) ) {
146  * case AS_NIL: break;
147  * case AS_INTEGER: break;
148  * case AS_DOUBLE: break;
149  * case AS_STRING: break;
150  * case AS_GEOJSON: break;
151  * case AS_BYTES: break;
152  * case AS_LIST: break;
153  * case AS_MAP: break;
154  * case AS_REC: break;
155  * case AS_UNDEF: break;
156  * }
157  * ~~~~~~~~~~
158  *
159  * ## Traversing Bins
160  *
161  * If you want to traverse the bins of a record, then you have two options:
162  *
163  * - as_record_foreach() — Calls a function for each bin traversed.
164  * - as_record_iterator — Uses an iterator pattern to traverse bins.
165  *
166  * @extends as_rec
167  * @ingroup client_objects
168  */
169 typedef struct as_record_s {
170 
171  /**
172  * @private
173  * as_record is "derived" from as_rec.
174  * So you can actually type cast as_record to as_rec.
175  */
176  as_rec _;
177 
178  /**
179  * The key of the record.
180  * This is populated when a record is read from the database.
181  * This should not be set by the user.
182  */
184 
185  /**
186  * The generation of the record.
187  */
188  uint16_t gen;
189 
190  /**
191  * The time-to-live (expiration) of the record in seconds.
192  * There are also special values that can be set in the record TTL:
193  * (*) ZERO (defined as AS_RECORD_DEFAULT_TTL), which means that the
194  * record will adopt the default TTL value from the namespace.
195  * (*) 0xFFFFFFFF (also, -1 in a signed 32 bit int)
196  * (defined as AS_RECORD_NO_EXPIRE_TTL), which means that the record
197  * will get an internal "void_time" of zero, and thus will never expire.
198  * (*) 0xFFFFFFFE (also, -2 in a signed 32 bit int)
199  * (defined as AS_RECORD_NO_CHANGE_TTL), which means that the record
200  * ttl will not change when the record is updated.
201  *
202  * Note that the TTL value will be employed ONLY on write/update calls.
203  */
204  uint32_t ttl;
205 
206  /**
207  * The bins of the record.
208  */
210 
211 } as_record;
212 
213 /**
214  * When the record is given a TTL value of ZERO, it will adopt the TTL value
215  * that is the default TTL value for the namespace (defined in the config file).
216  */
217 #define AS_RECORD_DEFAULT_TTL 0
218 
219 /**
220  * When the record is given a TTL value of 0xFFFFFFFF, it will set the internal
221  * void_time value (the absolute clock time value that shows when a record
222  * will expire) to zero, which means the record will never expire
223  */
224 #define AS_RECORD_NO_EXPIRE_TTL 0xFFFFFFFF
225 
226 /**
227  * When the record is given a TTL value of 0xFFFFFFFE, the TTL will not change
228  * when a record is updated.
229  */
230 #define AS_RECORD_NO_CHANGE_TTL 0xFFFFFFFE
231 
232 /******************************************************************************
233  * MACROS
234  *****************************************************************************/
235 
236 /**
237  * Initialize a stack allocated `as_record` then allocate `__nbins` capacity
238  * for as_record.bins on the stack.
239  *
240  * ~~~~~~~~~~{.c}
241  * as_record record;
242  * as_record_inita(&record, 2);
243  * as_record_set_int64(&record, "bin1", 123);
244  * as_record_set_int64(&record, "bin2", 456);
245  * ~~~~~~~~~~
246  *
247  * When you are finished using the `as_record` instance, you should release the
248  * resources allocated to it by calling `as_record_destroy()`.
249  *
250  * @param __rec The `as_record *` to initialize.
251  * @param __nbins The number of `as_record.bins.entries` to allocate on the
252  * stack.
253  *
254  * @relates as_record
255  */
256 #define as_record_inita(__rec, __nbins) \
257  as_record_init(__rec, 0);\
258  (__rec)->bins._free = false;\
259  (__rec)->bins.capacity = (__nbins);\
260  (__rec)->bins.size = 0;\
261  (__rec)->bins.entries = (as_bin*) alloca(sizeof(as_bin) * (__nbins));
262 
263 /******************************************************************************
264  * FUNCTIONS
265  *****************************************************************************/
266 
267 /**
268  * Create a new as_record on the heap.
269  *
270  * ~~~~~~~~~~{.c}
271  * as_record * r = as_record_new(2);
272  * as_record_set_int64(r, "bin1", 123);
273  * as_record_set_str(r, "bin1", "abc");
274  * ~~~~~~~~~~
275  *
276  * When you are finished using the `as_record` instance, you should release the
277  * resources allocated to it by calling `as_record_destroy()`.
278  *
279  * @param nbins The number of bins to initialize.
280  *
281  * @return a pointer to the new as_record if successful, otherwise NULL.
282  *
283  * @relates as_record
284  */
285 as_record * as_record_new(uint16_t nbins);
286 
287 /**
288  * Initializes an as_record created on the stack.
289  *
290  * ~~~~~~~~~~{.c}
291  * as_record r;
292  * as_record_init(&r, 2);
293  * as_record_set_int64(&r, "bin1", 123);
294  * as_record_set_str(&r, "bin1", "abc");
295  * ~~~~~~~~~~
296  *
297  * When you are finished using the `as_record` instance, you should release the
298  * resources allocated to it by calling `as_record_destroy()`.
299  *
300  * @param rec The record to initialize.
301  * @param nbins The number of bins to initialize.
302  *
303  * @return a pointer to the initialized as_record if successful, otherwise NULL.
304  *
305  * @relates as_record
306  */
307 as_record * as_record_init(as_record * rec, uint16_t nbins);
308 
309 /**
310  * Destroy the as_record and associated resources.
311  *
312  * @param rec The record to destroy.
313  *
314  * @relates as_record
315  */
316 void as_record_destroy(as_record * rec);
317 
318 /**
319  * Get the number of bins in the record.
320  *
321  * @return the number of bins in the record.
322  *
323  * @relates as_record
324  */
325 uint16_t as_record_numbins(const as_record * rec);
326 
327 /**
328  * Set specified bin's value to an as_bin_value.
329  *
330  * @param rec The record containing the bin.
331  * @param name The name of the bin.
332  * @param value The value of the bin.
333  *
334  * @return true on success, false on failure.
335  *
336  * @relates as_record
337  */
338 bool as_record_set(as_record * rec, const as_bin_name name, as_bin_value * value);
339 
340 /**
341  * Set specified bin's value to an int64_t.
342  *
343  * ~~~~~~~~~~{.c}
344  * as_record_set_int64(rec, "bin", 123);
345  * ~~~~~~~~~~
346  *
347  * @param rec The record containing the bin.
348  * @param name The name of the bin.
349  * @param value The value of the bin.
350  *
351  * @return true on success, false on failure.
352  *
353  * @relates as_record
354  */
355 bool as_record_set_int64(as_record * rec, const as_bin_name name, int64_t value);
356 
357 /**
358  * Set specified bin's value to a double.
359  *
360  * ~~~~~~~~~~{.c}
361  * as_record_set_double(rec, "bin", 123.456);
362  * ~~~~~~~~~~
363  *
364  * @param rec The record containing the bin.
365  * @param name The name of the bin.
366  * @param value The value of the bin.
367  *
368  * @return true on success, false on failure.
369  *
370  * @relates as_record
371  */
372 bool as_record_set_double(as_record * rec, const as_bin_name name, double value);
373 
374 /**
375  * Set specified bin's value to an NULL terminated string.
376  *
377  * ~~~~~~~~~~{.c}
378  * as_record_set_strp(rec, "bin", strdup("abc"), true);
379  * ~~~~~~~~~~
380  *
381  * @param rec The record containing the bin.
382  * @param name The name of the bin.
383  * @param value The value of the bin. Must be in scope for the lifetime of the record.
384  * @param free If true, then the value will be freed when the record is destroyed.
385  *
386  * @return true on success, false on failure.
387  *
388  * @relates as_record
389  */
390 bool as_record_set_strp(as_record * rec, const as_bin_name name, const char * value, bool free);
391 
392 /**
393  * Set specified bin's value to an NULL terminated string.
394  *
395  * ~~~~~~~~~~{.c}
396  * as_record_set_str(rec, "bin", "abc");
397  * ~~~~~~~~~~
398  *
399  * @param rec The record containing the bin.
400  * @param name The name of the bin.
401  * @param value The value of the bin. Must be in scope for the lifetime of the record.
402  *
403  * @return true on success, false on failure.
404  *
405  * @relates as_record
406  */
407 static inline bool as_record_set_str(as_record * rec, const as_bin_name name, const char * value)
408 {
409  return as_record_set_strp(rec, name, value, false);
410 }
411 
412 /**
413  * Set specified bin's value to an NULL terminated GeoJSON string.
414  *
415  * ~~~~~~~~~~{.c}
416  * as_record_set_geojson_strp(rec, "bin", strdup("abc"), true);
417  * ~~~~~~~~~~
418  *
419  * @param rec The record containing the bin.
420  * @param name The name of the bin.
421  * @param value The value of the bin. Must be in scope for the lifetime of the record.
422  * @param free If true, then the value will be freed when the record is destroyed.
423  *
424  * @return true on success, false on failure.
425  *
426  * @relates as_record
427  */
428 bool as_record_set_geojson_strp(as_record * rec, const as_bin_name name, const char * value, bool free);
429 
430 /**
431  * Set specified bin's value to an NULL terminated GeoJSON string.
432  *
433  * ~~~~~~~~~~{.c}
434  * as_record_set_geojson_str(rec, "bin", "abc");
435  * ~~~~~~~~~~
436  *
437  * @param rec The record containing the bin.
438  * @param name The name of the bin.
439  * @param value The value of the bin. Must be in scope for the lifetime of the record.
440  *
441  * @return true on success, false on failure.
442  *
443  * @relates as_record
444  */
445 static inline bool as_record_set_geojson_str(as_record * rec, const as_bin_name name, const char * value)
446 {
447  return as_record_set_geojson_strp(rec, name, value, false);
448 }
449 
450 /**
451  * Set specified bin's value to an NULL terminated string.
452  *
453  * ~~~~~~~~~~{.c}
454  * uint8_t * bytes = (uint8_t *) malloc(3);
455  * bytes[0] = 1;
456  * bytes[1] = 2;
457  * bytes[3] = 3;
458  *
459  * as_record_set_raw(rec, "bin", bytes, 3, true);
460  * ~~~~~~~~~~
461  *
462  * @param rec The record containing the bin.
463  * @param name The name of the bin.
464  * @param value The value of the bin. Must be in scope for the lifetime of the record.
465  * @param size The size of the value.
466  * @param free If true, then the value will be freed when the record is destroyed.
467  *
468  * @return true on success, false on failure.
469  *
470  * @relates as_record
471  */
472 bool as_record_set_rawp(as_record * rec, const as_bin_name name, const uint8_t * value, uint32_t size, bool free);
473 
474 /**
475  * Set specified bin's value to an as_bytes value of a specified type.
476  *
477  * ~~~~~~~~~~{.c}
478  * uint8_t * bytes = (uint8_t *) malloc(3);
479  * bytes[0] = 1;
480  * bytes[1] = 2;
481  * bytes[3] = 3;
482  *
483  * as_record_set_raw(rec, "bin", bytes, 3, true);
484  * ~~~~~~~~~~
485  *
486  * @param rec The record containing the bin.
487  * @param name The name of the bin.
488  * @param value The value of the bin. Must be in scope for the lifetime of the record.
489  * @param size The size of the value.
490  * @param type The as_bytes_type designation (AS_BYTES_*)
491  * @param free If true, then the value will be freed when the record is destroyed.
492  *
493  * @return true on success, false on failure.
494  *
495  * @relates as_record
496  */
497 bool as_record_set_raw_typep(as_record * rec, const as_bin_name name, const uint8_t * value, uint32_t size, as_bytes_type type, bool free);
498 
499 /**
500  * Set specified bin's value to an NULL terminated string.
501  *
502  * ~~~~~~~~~~{.c}
503  * uint8_t bytes[3] = {1,2,3};
504  * as_record_set_raw(rec, "bin", bytes, 3);
505  * ~~~~~~~~~~
506  *
507  * @param rec The record containing the bin.
508  * @param name The name of the bin.
509  * @param value The value of the bin. Must be in scope for the lifetime of the record.
510  * @param size The size of the value.
511  *
512  * @return true on success, false on failure.
513  *
514  * @relates as_record
515  */
516 static inline bool as_record_set_raw(as_record * rec, const as_bin_name name, const uint8_t * value, uint32_t size)
517 {
518  return as_record_set_rawp(rec, name, value, size, false);
519 }
520 
521 /**
522  * Set specified bin's value to an as_integer.
523  *
524  * ~~~~~~~~~~{.c}
525  * as_record_set_integer(rec, "bin", as_integer_new(123));
526  * ~~~~~~~~~~
527  *
528  * @param rec The record containing the bin.
529  * @param name The name of the bin.
530  * @param value The value of the bin. Must be in scope for the lifetime of the record.
531  *
532  * @return true on success, false on failure.
533  *
534  * @relates as_record
535  */
536 bool as_record_set_integer(as_record * rec, const as_bin_name name, as_integer * value);
537 
538 /**
539  * Set specified bin's value to an as_double.
540  *
541  * ~~~~~~~~~~{.c}
542  * as_record_set_as_double(rec, "bin", as_double_new(123.456));
543  * ~~~~~~~~~~
544  *
545  * @param rec The record containing the bin.
546  * @param name The name of the bin.
547  * @param value The value of the bin. Must be in scope for the lifetime of the record.
548  *
549  * @return true on success, false on failure.
550  *
551  * @relates as_record
552  */
553 bool as_record_set_as_double(as_record * rec, const as_bin_name name, as_double * value);
554 
555 /**
556  * Set specified bin's value to an as_string.
557  *
558  * ~~~~~~~~~~{.c}
559  * as_record_set_string(rec, "bin", as_string_new("abc", false));
560  * ~~~~~~~~~~
561  *
562  * @param rec The record containing the bin.
563  * @param name The name of the bin.
564  * @param value The value of the bin. Must be in scope for the lifetime of the record.
565  *
566  * @return true on success, false on failure.
567  *
568  * @relates as_record
569  */
570 bool as_record_set_string(as_record * rec, const as_bin_name name, as_string * value);
571 
572 /**
573  * Set specified bin's value to an as_geojson.
574  *
575  * ~~~~~~~~~~{.c}
576  * as_record_set_geojson(rec, "bin", as_geojson_new("abc", false));
577  * ~~~~~~~~~~
578  *
579  * @param rec The record containing the bin.
580  * @param name The name of the bin.
581  * @param value The value of the bin. Must be in scope for the lifetime of the record.
582  *
583  * @return true on success, false on failure.
584  *
585  * @relates as_record
586  */
587 bool as_record_set_geojson(as_record * rec, const as_bin_name name, as_geojson * value);
588 
589 /**
590  * Set specified bin's value to an as_bytes.
591  *
592  * ~~~~~~~~~~{.c}
593  * as_record_set_integer(rec, "bin", bytes);
594  * ~~~~~~~~~~
595  *
596  * @param rec The record containing the bin.
597  * @param name The name of the bin.
598  * @param value The value of the bin. Must be in scope for the lifetime of the record.
599  *
600  * @return true on success, false on failure.
601  *
602  * @relates as_record
603  */
604 bool as_record_set_bytes(as_record * rec, const as_bin_name name, as_bytes * value);
605 
606 /**
607  * Set specified bin's value to an as_list.
608  *
609  * ~~~~~~~~~~{.c}
610  * as_arraylist list;
611  * as_arraylist_init(&list);
612  * as_arraylist_add_int64(&list, 1);
613  * as_arraylist_add_int64(&list, 2);
614  * as_arraylist_add_int64(&list, 3);
615  *
616  * as_record_set_list(rec, "bin", &list);
617  * ~~~~~~~~~~
618  *
619  * @param rec The record containing the bin.
620  * @param name The name of the bin.
621  * @param value The value of the bin. Must be in scope for the lifetime of the record.
622  *
623  * @return true on success, false on failure.
624  *
625  * @relates as_record
626  */
627 bool as_record_set_list(as_record * rec, const as_bin_name name, as_list * value);
628 
629 /**
630  * Set specified bin's value to an as_map.
631  *
632  * ~~~~~~~~~~{.c}
633  * as_hashmap map;
634  * as_hashmap_init(&map, 32);
635  * as_stringmap_set_int64(&map, "a", 1);
636  * as_stringmap_set_int64(&map, "b", 2);
637  * as_stringmap_set_int64(&map, "c", 3);
638  *
639  * as_record_set_map(rec, "bin", &map);
640  * ~~~~~~~~~~
641  *
642  * @param rec The record containing the bin.
643  * @param name The name of the bin.
644  * @param value The value of the bin. Must be in scope for the lifetime of the record.
645  *
646  * @return true on success, false on failure.
647  *
648  * @relates as_record
649  */
650 bool as_record_set_map(as_record * rec, const as_bin_name name, as_map * value);
651 
652 /**
653  * Set specified bin's value to as_nil.
654  *
655  * ~~~~~~~~~~{.c}
656  * as_record_set_nil(rec, "bin");
657  * ~~~~~~~~~~
658  *
659  * @param rec The record containing the bin.
660  * @param name The name of the bin.
661  *
662  * @return true on success, false on failure.
663  *
664  * @relates as_record
665  */
666 bool as_record_set_nil(as_record * rec, const as_bin_name name);
667 
668 /**
669  * Get specified bin's value.
670  *
671  * ~~~~~~~~~~{.c}
672  * as_val * value = as_record_get(rec, "bin");
673  * ~~~~~~~~~~
674  *
675  * @param rec The record containing the bin.
676  * @param name The name of the bin.
677  *
678  * @return the value if it exists, otherwise NULL.
679  *
680  * @relates as_record
681  */
682 as_bin_value * as_record_get(const as_record * rec, const as_bin_name name);
683 
684 /**
685  * Get specified bin's value as an int64_t.
686  *
687  * ~~~~~~~~~~{.c}
688  * int64_t value = as_record_get_int64(rec, "bin", INT64_MAX);
689  * ~~~~~~~~~~
690  *
691  * @param rec The record containing the bin.
692  * @param name The name of the bin.
693  * @param fallback The default value to use, if the bin doesn't exist or is not an integer.
694  *
695  * @return the value if it exists, otherwise 0.
696  *
697  * @relates as_record
698  */
699 int64_t as_record_get_int64(const as_record * rec, const as_bin_name name, int64_t fallback);
700 
701 /**
702  * Get specified bin's value as a double.
703  *
704  * ~~~~~~~~~~{.c}
705  * double value = as_record_get_double(rec, "bin", -1.0);
706  * ~~~~~~~~~~
707  *
708  * @param rec The record containing the bin.
709  * @param name The name of the bin.
710  * @param fallback The default value to use, if the bin doesn't exist or is not an integer.
711  *
712  * @return the value if it exists, otherwise 0.
713  *
714  * @relates as_record
715  */
716 double as_record_get_double(const as_record * rec, const as_bin_name name, double fallback);
717 
718 /**
719  * Get specified bin's value as an NULL terminated string.
720  *
721  * ~~~~~~~~~~{.c}
722  * char * value = as_record_get_str(rec, "bin");
723  * ~~~~~~~~~~
724  *
725  * @param rec The record containing the bin.
726  * @param name The name of the bin.
727  *
728  * @return the value if it exists, otherwise NULL.
729  *
730  * @relates as_record
731  */
732 char * as_record_get_str(const as_record * rec, const as_bin_name name);
733 
734 /**
735  * Get specified bin's value as an NULL terminated GeoJSON string.
736  *
737  * ~~~~~~~~~~{.c}
738  * char * value = as_record_get_geojson_str(rec, "bin");
739  * ~~~~~~~~~~
740  *
741  * @param rec The record containing the bin.
742  * @param name The name of the bin.
743  *
744  * @return the value if it exists, otherwise NULL.
745  *
746  * @relates as_record
747  */
748 char * as_record_get_geojson_str(const as_record * rec, const as_bin_name name);
749 
750 /**
751  * Get specified bin's value as an as_integer.
752  *
753  * ~~~~~~~~~~{.c}
754  * as_integer * value = as_record_get_integer(rec, "bin");
755  * ~~~~~~~~~~
756  *
757  * @param rec The record containing the bin.
758  * @param name The name of the bin.
759  *
760  * @return the value if it exists, otherwise NULL.
761  *
762  * @relates as_record
763  */
764 as_integer * as_record_get_integer(const as_record * rec, const as_bin_name name);
765 
766 /**
767  * Get specified bin's value as an as_double.
768  *
769  * ~~~~~~~~~~{.c}
770  * as_double * value = as_record_get_as_double(rec, "bin");
771  * ~~~~~~~~~~
772  *
773  * @param rec The record containing the bin.
774  * @param name The name of the bin.
775  *
776  * @return the value if it exists, otherwise NULL.
777  *
778  * @relates as_record
779  */
780 as_double * as_record_get_as_double(const as_record * rec, const as_bin_name name);
781 
782 /**
783  * Get specified bin's value as an as_string.
784  *
785  * ~~~~~~~~~~{.c}
786  * as_string * value = as_record_get_string(rec, "bin");
787  * ~~~~~~~~~~
788  *
789  * @param rec The record containing the bin.
790  * @param name The name of the bin.
791  *
792  * @return the value if it exists, otherwise NULL.
793  *
794  * @relates as_record
795  */
796 as_string * as_record_get_string(const as_record * rec, const as_bin_name name);
797 
798 /**
799  * Get specified bin's value as an as_geojson.
800  *
801  * ~~~~~~~~~~{.c}
802  * as_geojson * value = as_record_get_geojson(rec, "bin");
803  * ~~~~~~~~~~
804  *
805  * @param rec The record containing the bin.
806  * @param name The name of the bin.
807  *
808  * @return the value if it exists, otherwise NULL.
809  *
810  * @relates as_record
811  */
812 as_geojson * as_record_get_geojson(const as_record * rec, const as_bin_name name);
813 
814 /**
815  * Get specified bin's value as an as_bytes.
816  *
817  * ~~~~~~~~~~{.c}
818  * as_bytes * value = as_record_get_bytes(rec, "bin");
819  * ~~~~~~~~~~
820  *
821  * @param rec The record containing the bin.
822  * @param name The name of the bin.
823  *
824  * @return the value if it exists, otherwise NULL.
825  *
826  * @relates as_record
827  */
828 as_bytes * as_record_get_bytes(const as_record * rec, const as_bin_name name);
829 
830 /**
831  * Get specified bin's value as an as_list.
832  *
833  * ~~~~~~~~~~{.c}
834  * as_list * value = as_record_get_list(rec, "bin");
835  * ~~~~~~~~~~
836  *
837  * @param rec The record containing the bin.
838  * @param name The name of the bin.
839  *
840  * @return the value if it exists, otherwise NULL.
841  *
842  * @relates as_record
843  */
844 as_list * as_record_get_list(const as_record * rec, const as_bin_name name);
845 
846 /**
847  * Get specified bin's value as an as_map.
848  *
849  * ~~~~~~~~~~{.c}
850  * as_map * value = as_record_get_map(rec, "bin");
851  * ~~~~~~~~~~
852  *
853  * @param rec The record containing the bin.
854  * @param name The name of the bin.
855  *
856  * @return the value if it exists, otherwise NULL.
857  *
858  * @relates as_record
859  */
860 as_map * as_record_get_map(const as_record * rec, const as_bin_name name);
861 
862 /******************************************************************************
863  * ITERATION FUNCTIONS
864  ******************************************************************************/
865 
866 /**
867  * Iterate over each bin in the record and invoke the callback function.
868  *
869  * ~~~~~~~~~~{.c}
870  * bool print_bin(const char * name, const as_val * value, void * udata) {
871  * char * sval = as_val_tostring(value);
872  * printf("bin: name=%s, value=%s\n", name, sval);
873  * free(sval);
874  * return true;
875  * }
876  *
877  * as_record_foreach(rec, print_bin, NULL);
878  * ~~~~~~~~~~
879  *
880  * If the callback returns true, then iteration will continue to the next bin.
881  * Otherwise, the iteration will halt and `as_record_foreach()` will return
882  * false.
883  *
884  * @param rec The record containing the bins to iterate over.
885  * @param callback The callback to invoke for each bin.
886  * @param udata User-data provided for the callback.
887  *
888  * @return true if iteration completes fully. false if iteration was aborted.
889  *
890  * @relates as_record
891  */
892 bool as_record_foreach(const as_record * rec, as_rec_foreach_callback callback, void * udata);
893 
894 /******************************************************************************
895  * CONVERSION FUNCTIONS
896  ******************************************************************************/
897 
898 /**
899  * Convert to an as_val.
900  *
901  * @relates as_record
902  */
903 static inline as_val * as_record_toval(const as_record * rec)
904 {
905  return (as_val *) rec;
906 }
907 
908 /**
909  * Convert from an as_val.
910  *
911  * @relates as_record
912  */
913 static inline as_record * as_record_fromval(const as_val * v)
914 {
915  return (as_record *) as_util_fromval(v, AS_REC, as_rec);
916 }
917 
918 #ifdef __cplusplus
919 } // end extern "C"
920 #endif