Iterator over serialised dbus data. More...
#include <adbus-iterator.h>
Data Fields | |
| const char * | data |
| Current data pointer. | |
| size_t | size |
| Data left. | |
| const char * | sig |
| Current signature pointer. | |
Related Functions | |
(Note that these are not member functions.) | |
| static int | adbus_iter_bool (adbus_Iterator *i, const adbus_Bool **v) |
| Pulls out a boolean (dbus sig "b"). | |
| static int | adbus_iter_u8 (adbus_Iterator *i, const uint8_t **v) |
| Pulls out a uint8_t (dbus sig "y"). | |
| static int | adbus_iter_i16 (adbus_Iterator *i, const int16_t **v) |
| Pulls out a int16_t (dbus sig "n"). | |
| static int | adbus_iter_u16 (adbus_Iterator *i, const uint16_t **v) |
| Pulls out a uint16_t (dbus sig "q"). | |
| static int | adbus_iter_i32 (adbus_Iterator *i, const int32_t **v) |
| Pulls out a int32_t (dbus sig "i"). | |
| static int | adbus_iter_u32 (adbus_Iterator *i, const uint32_t **v) |
| Pulls out a uint32_t (dbus sig "u"). | |
| static int | adbus_iter_i64 (adbus_Iterator *i, const int64_t **v) |
| Pulls out a int64_t (dbus sig "x"). | |
| static int | adbus_iter_u64 (adbus_Iterator *i, const uint64_t **v) |
| Pulls out a uint64_t (dbus sig "t"). | |
| static int | adbus_iter_double (adbus_Iterator *i, const double **v) |
| Pulls out a double (dbus sig "d"). | |
| static int | adbus_iter_string (adbus_Iterator *i, const char **str, size_t *strsz) |
| Pulls out a string (dbus sig "s"). | |
| static int | adbus_iter_objectpath (adbus_Iterator *i, const char **str, size_t *strsz) |
| Pulls out a object path (dbus sig "o"). | |
| static int | adbus_iter_signature (adbus_Iterator *i, const char **str, size_t *strsz) |
| Pulls out a signature (dbus sig "g"). | |
| static int | adbus_iter_beginarray (adbus_Iterator *i, adbus_IterArray *a) |
| Begins an array scope (dbus sig "a"). | |
| static adbus_Bool | adbus_iter_inarray (adbus_Iterator *i, adbus_IterArray *a) |
| Checks that the iterator is still inside the array. | |
| static int | adbus_iter_endarray (adbus_Iterator *i, adbus_IterArray *a) |
| Ends an array scope (dbus sig "a"). | |
| static int | adbus_iter_begindictentry (adbus_Iterator *i) |
| Begins a dict entry scope (dbus sig "{"). | |
| static int | adbus_iter_enddictentry (adbus_Iterator *i) |
| Ends a dict entry scope (dbus sig "}"). | |
| static int | adbus_iter_beginstruct (adbus_Iterator *i) |
| Begins a struct scope (dbus sig "("). | |
| static int | adbus_iter_endstruct (adbus_Iterator *i) |
| Ends a struct scope (dbus sig ")"). | |
| static int | adbus_iter_beginvariant (adbus_Iterator *i, adbus_IterVariant *v) |
| Begins a variant scope (dbus sig "v"). | |
| static int | adbus_iter_endvariant (adbus_Iterator *i, adbus_IterVariant *v) |
| Ends a variant scope (dbus sig "v"). | |
| int | adbus_iter_value (adbus_Iterator *i) |
| Skip over a single complete type. | |
| void | adbus_iter_buffer (adbus_Iterator *i, const adbus_Buffer *buf) |
| Setup an iterator for the data in an adbus_Buffer. | |
| void | adbus_iter_args (adbus_Iterator *i, const adbus_Message *msg) |
| Setup an iterator for the arguments in an adbus_Message. | |
Iterator over serialised dbus data.
All iterate functions return the data via a pointer out param and return an int. The returned int is zero on success and non-zero on a parse failure or invalid data.
The iterate functions will track along the signature in the iterator, but expect that the signature has already been checked (they will assert when there is a signature mismatch). For argument iteration with built in argument checking see the check functions (eg adbus_check_bool()).
The functions are mainly designed for speed, will do minimal data checking, and are all inlined. The only real checking done is to check null terminators for strings.
Arrays can be iterated over in two fashions. You can either use adbus_buf_inarray() in a loop to pull out each entry in the array or simply copy the data directly out of the data and size members of adbus_IterArray.
For example using adbus_buf_inarray() to iterator over "au" (an array of uint32s);
std::vector<uint32_t> vec; adbus_IterArray a; if (adbus_iter_beginarray(buf, &a)) return -1; while (adbus_iter_inarray(buf, &a)) { uint32_t v; if (adbus_iter_u32(buf, &v)) return -1; vec.push_back(v); } if (adbus_iter_endarray(buf, &a)) return -1;
Equivalently by pulling the array data out directly:
std::vector<uint32_t> vec; adbus_IterArray a; if (adbus_iter_beginarray(iter, &a)) return -1; vec.insert(vec.end(), (uint32_t*) a.data, (uint32_t*) (a.data + a.size)); if (adbus_iter_endarray(iter, &a)) return -1;
adbus_IterArray is an exposed type with the following members:
struct adbus_IterArray { const char* sig; // signature of array entry - not null terminated const char* data; // beginning of array data size_t size; // size of array data };
Dict entries can only be used as a scope directly inside an array. Thus the signature will always look like a{...}. The begin/end dictentry calls should be inside an inarray loop.
For example to iterate over "a{is}" (a map of int to string):
std::map<int, std::string> map; adbus_IterArray a; if (adbus_iter_beginarray(iter, &a)) return -1; while (adbus_iter_inarray(iter, &a)) { int32_t i32; const char* str; if (adbus_iter_begindictentry(iter)) return -1; if (adbus_iter_i32(iter, &i32)) return -1; if (adbus_iter_string(iter, &str, NULL)) return -1; if (adbus_iter_enddictentry(iter)) return -1; map[i32] = str; } if (adbus_iter_endarray(iter, &a)) return -1;
Structs can be iterated over by begin and end functions with no scoped data.
For example to iterate over "(iis)" (a struct of int, int, string):
int32_t i1, i2; const char* str; if (adbus_iter_beginstruct(iter)) return -1; if (adbus_iter_i32(iter, &i1)) return -1; if (adbus_iter_i32(iter, &i1)) return -1; if (adbus_iter_string(iter, &str)) return -1; if (adbus_iter_endstruct(iter)) return -1;
Variants have begin and functions and scoped data. After the begin variant call, the sig member of the iterator is set to the signature of the variant data. This can be used to check the signature of the variant, which must be checked before iterating over specific value types.
adbus_IterVariant is an exposed type with the following members:
struct adbus_IterVariant { const char* origsig; const char* sig; const char* data; size_t size; };
For example to iterate over a variant which we expect to be either "s" (string) or "u" (uint32_t):
uint32_t u; const char* str; adbus_IterVariant v; if (adbus_iter_beginvariant(iter, &v)) return -1; if (strcmp(iter->sig, "u") == 0) { // We have a u32 variant if (adbus_iter_u32(iter->sig, &u)) return -1; } else if (strcmp(iter->sig, "s") == 0) { // We have a string variant if (adbus_iter_string(iter->sig, &str)) return -1; } else { // We have some other variant return -1; } if (adbus_iter_endvariant(iter, &v)) return -1;
Alternatively if we don't care too much about the type just yet, we can copy around the variant in its marshalled form with the associated signature. We can do this by using adbus_iter_value() to skip to the end of the variant and finishing it. Then the data, size, and sig members of the adbus_IterVariant will have the needed info.
For example:
adbus_IterVariant v; if (adbus_iter_beginvariant(iter, &v)) return -1; if (adbus_iter_value(iter)) return -1; if (adbus_iter_endvariant(iter, &v)) return -1; adbus_Buffer* buf = adbus_buf_new(); adbus_buf_setsig(buf, v.sig, -1); adbus_buf_append(buf, v.data, v.size); // some time later adbus_Iterator iter; adbus_iter_buffer(&iter, buf); // iterate over the data ... // once we are done with the data adbus_buf_free(buf);
To pull out the information later we simply setup a new iterator and iterate over the copy of the data. Note that the data must still by 8 byte aligned and thus it is often easiest to cart around the data in an adbus_Buffer.
This method has the advantage of keeping the data in dbus marshalled form and thus can hold any dbus type.
1.6.1