From 7fce157bc3940f997e9ac8566c55021b9af43b0a Mon Sep 17 00:00:00 2001 From: David Robillard Date: Sun, 19 Feb 2012 02:19:30 +0000 Subject: atom/atom-helpers.h => atom/util.h. --- lv2/lv2plug.in/ns/ext/atom/atom-helpers.h | 372 ------------------------------ lv2/lv2plug.in/ns/ext/atom/atom-test.c | 2 +- lv2/lv2plug.in/ns/ext/atom/atom.ttl | 2 +- lv2/lv2plug.in/ns/ext/atom/forge.h | 2 +- lv2/lv2plug.in/ns/ext/atom/util.h | 372 ++++++++++++++++++++++++++++++ 5 files changed, 375 insertions(+), 375 deletions(-) delete mode 100644 lv2/lv2plug.in/ns/ext/atom/atom-helpers.h create mode 100644 lv2/lv2plug.in/ns/ext/atom/util.h (limited to 'lv2/lv2plug.in/ns/ext') diff --git a/lv2/lv2plug.in/ns/ext/atom/atom-helpers.h b/lv2/lv2plug.in/ns/ext/atom/atom-helpers.h deleted file mode 100644 index e6ecd9c..0000000 --- a/lv2/lv2plug.in/ns/ext/atom/atom-helpers.h +++ /dev/null @@ -1,372 +0,0 @@ -/* - Copyright 2008-2012 David Robillard - - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - - THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ - -/** - @file atom-helpers.h Helper functions for the LV2 Atom extension. - - Note these functions are all static inline, do not take their address. - - This header is non-normative, it is provided for convenience. -*/ - -#ifndef LV2_ATOM_HELPERS_H -#define LV2_ATOM_HELPERS_H - -#include -#include -#include -#include - -#include "lv2/lv2plug.in/ns/ext/atom/atom.h" - -#ifdef __cplusplus -extern "C" { -#else -# include -#endif - -/** Pad a size to 64 bits. */ -static inline uint32_t -lv2_atom_pad_size(uint32_t size) -{ - return (size + 7) & (~7); -} - -/** Return the total size of @p atom, including the header. */ -static inline uint32_t -lv2_atom_total_size(const LV2_Atom* atom) -{ - return sizeof(LV2_Atom) + atom->size; -} - -/** Return true iff @p atom is null. */ -static inline bool -lv2_atom_is_null(const LV2_Atom* atom) -{ - return !atom || (atom->type == 0 && atom->size == 0); -} - -/** Return true iff @p a is equal to @p b. */ -static inline bool -lv2_atom_equals(const LV2_Atom* a, const LV2_Atom* b) -{ - return (a == b) || ( - (a->type == b->type) && - (a->size == b->size) && - !memcmp(LV2_ATOM_CONTENTS(LV2_Atom, a), - LV2_ATOM_CONTENTS(LV2_Atom, b), - a->size)); -} - -/** - @name Sequence Iterator - @{ -*/ - -/** An iterator over the elements of an LV2_Atom_Sequence. */ -typedef LV2_Atom_Event* LV2_Atom_Sequence_Iter; - -/** Get an iterator pointing to the first element in @p tup. */ -static inline LV2_Atom_Sequence_Iter -lv2_sequence_begin(const LV2_Atom_Sequence* seq) -{ - return (LV2_Atom_Sequence_Iter)(LV2_ATOM_CONTENTS(LV2_Atom_Sequence, seq)); -} - -/** Return true iff @p i has reached the end of @p tup. */ -static inline bool -lv2_sequence_is_end(const LV2_Atom_Sequence* seq, LV2_Atom_Sequence_Iter i) -{ - return (uint8_t*)i >= ((uint8_t*)seq + sizeof(LV2_Atom) + seq->atom.size); -} - -/** Return an iterator to the element following @p i. */ -static inline LV2_Atom_Sequence_Iter -lv2_sequence_iter_next(const LV2_Atom_Sequence_Iter i) -{ - return (LV2_Atom_Sequence_Iter)((uint8_t*)i - + sizeof(LV2_Atom_Event) - + lv2_atom_pad_size(i->body.size)); -} - -/** Return the element pointed to by @p i. */ -static inline LV2_Atom_Event* -lv2_sequence_iter_get(LV2_Atom_Sequence_Iter i) -{ - return (LV2_Atom_Event*)i; -} - -/** - A macro for iterating over all events in a Sequence. - @param sequence The sequence to iterate over - @param iter The name of the iterator - - This macro is used similarly to a for loop (which it expands to), e.g.: - @code - LV2_SEQUENCE_FOREACH(sequence, i) { - LV2_Atom_Event* ev = lv2_sequence_iter_get(i); - // Do something with ev here... - } - @endcode -*/ -#define LV2_SEQUENCE_FOREACH(sequence, iter) \ - for (LV2_Atom_Sequence_Iter (iter) = lv2_sequence_begin(sequence); \ - !lv2_sequence_is_end(sequence, (iter)); \ - (iter) = lv2_sequence_iter_next(iter)) - -/** - @} - @name Tuple Iterator - @{ -*/ - -/** An iterator over the elements of an LV2_Atom_Tuple. */ -typedef LV2_Atom* LV2_Atom_Tuple_Iter; - -/** Get an iterator pointing to the first element in @p tup. */ -static inline LV2_Atom_Tuple_Iter -lv2_tuple_begin(const LV2_Atom_Tuple* tup) -{ - return (LV2_Atom_Tuple_Iter)(LV2_ATOM_BODY(tup)); -} - -/** Return true iff @p i has reached the end of @p tup. */ -static inline bool -lv2_tuple_is_end(const LV2_Atom_Tuple* tup, LV2_Atom_Tuple_Iter i) -{ - return (uint8_t*)i >= ((uint8_t*)tup + sizeof(LV2_Atom) + tup->atom.size); -} - -/** Return an iterator to the element following @p i. */ -static inline LV2_Atom_Tuple_Iter -lv2_tuple_iter_next(const LV2_Atom_Tuple_Iter i) -{ - return (LV2_Atom_Tuple_Iter)( - (uint8_t*)i + sizeof(LV2_Atom) + lv2_atom_pad_size(i->size)); -} - -/** Return the element pointed to by @p i. */ -static inline LV2_Atom* -lv2_tuple_iter_get(LV2_Atom_Tuple_Iter i) -{ - return (LV2_Atom*)i; -} - -/** - A macro for iterating over all properties of a Tuple. - @param tuple The tuple to iterate over - @param iter The name of the iterator - - This macro is used similarly to a for loop (which it expands to), e.g.: - @code - LV2_TUPLE_FOREACH(tuple, i) { - LV2_Atom* elem = lv2_tuple_iter_get(i); - // Do something with elem here... - } - @endcode -*/ -#define LV2_TUPLE_FOREACH(tuple, iter) \ - for (LV2_Atom_Tuple_Iter (iter) = lv2_tuple_begin(tuple); \ - !lv2_tuple_is_end(tuple, (iter)); \ - (iter) = lv2_tuple_iter_next(iter)) - -/** - @} - @name Object Iterator - @{ -*/ - -/** An iterator over the properties of an LV2_Atom_Object. */ -typedef LV2_Atom_Property_Body* LV2_Atom_Object_Iter; - -/** Get an iterator pointing to the first property in @p obj. */ -static inline LV2_Atom_Object_Iter -lv2_object_begin(const LV2_Atom_Object* obj) -{ - return (LV2_Atom_Object_Iter)(LV2_ATOM_CONTENTS(LV2_Atom_Object, obj)); -} - -/** Return true iff @p i has reached the end of @p obj. */ -static inline bool -lv2_object_is_end(const LV2_Atom_Object* obj, LV2_Atom_Object_Iter i) -{ - return (uint8_t*)i >= ((uint8_t*)obj + sizeof(LV2_Atom) + obj->atom.size); -} - -/** Return true iff @p l points to the same property as @p r. */ -static inline bool -lv2_object_iter_equals(const LV2_Atom_Object_Iter l, - const LV2_Atom_Object_Iter r) -{ - return l == r; -} - -/** Return an iterator to the property following @p i. */ -static inline LV2_Atom_Object_Iter -lv2_object_iter_next(const LV2_Atom_Object_Iter i) -{ - const LV2_Atom* const value = (LV2_Atom*)((uint8_t*)i + sizeof(i)); - return (LV2_Atom_Object_Iter)((uint8_t*)i - + sizeof(LV2_Atom_Property_Body) - + lv2_atom_pad_size(value->size)); -} - -/** Return the property pointed to by @p i. */ -static inline LV2_Atom_Property_Body* -lv2_object_iter_get(LV2_Atom_Object_Iter i) -{ - return (LV2_Atom_Property_Body*)i; -} - -/** - A macro for iterating over all properties of an Object. - @param object The object to iterate over - @param iter The name of the iterator - - This macro is used similarly to a for loop (which it expands to), e.g.: - @code - LV2_OBJECT_FOREACH(object, i) { - LV2_Atom_Property_Body* prop = lv2_object_iter_get(i); - // Do something with prop here... - } - @endcode -*/ -#define LV2_OBJECT_FOREACH(object, iter) \ - for (LV2_Atom_Object_Iter (iter) = lv2_object_begin(object); \ - !lv2_object_is_end(object, (iter)); \ - (iter) = lv2_object_iter_next(iter)) - -/** - @} - @name Object Query - @{ -*/ - -/** A single entry in an Object query. */ -typedef struct { - uint32_t key; /**< Key to query (input set by user) */ - const LV2_Atom** value; /**< Found value (output set by query function) */ -} LV2_Atom_Object_Query; - -static const LV2_Atom_Object_Query LV2_OBJECT_QUERY_END = { 0, NULL }; - -/** - Get an object's values for various keys. - - The value pointer of each item in @p query will be set to the location of - the corresponding value in @p object. Every value pointer in @p query MUST - be initialised to NULL. This function reads @p object in a single linear - sweep. By allocating @p query on the stack, objects can be "queried" - quickly without allocating any memory. This function is realtime safe. - - For example: - @code - const LV2_Atom* name = NULL; - const LV2_Atom* age = NULL; - LV2_Atom_Object_Query q[] = { - { urids.eg_name, &name }, - { urids.eg_age, &age }, - LV2_OBJECT_QUERY_END - }; - lv2_object_get(obj, q); - // name and age are now set to the appropriate values in obj, or NULL. - @endcode -*/ -static inline int -lv2_object_get(const LV2_Atom_Object* object, LV2_Atom_Object_Query* query) -{ - int matches = 0; - int n_queries = 0; - - /* Count number of query keys so we can short-circuit when done */ - for (LV2_Atom_Object_Query* q = query; q->key; ++q) { - ++n_queries; - } - - LV2_OBJECT_FOREACH(object, o) { - const LV2_Atom_Property_Body* prop = lv2_object_iter_get(o); - for (LV2_Atom_Object_Query* q = query; q->key; ++q) { - if (q->key == prop->key && !*q->value) { - *q->value = &prop->value; - if (++matches == n_queries) { - return matches; - } - break; - } - } - } - return matches; -} - -/** - Variable argument version of lv2_object_get(). - - This is nicer-looking in code, but a bit more error-prone since it is not - type safe and the argument list must be terminated. - - The arguments should be a series of uint32_t key and const LV2_Atom** value - pairs, terminated by a zero key. The value pointers MUST be initialized to - NULL. For example: - - @code - const LV2_Atom* name = NULL; - const LV2_Atom* age = NULL; - lv2_object_getv(obj, - uris.name_key, &name, - uris.age_key, &age, - 0); - @endcode -*/ -static inline int -lv2_object_getv(const LV2_Atom_Object* object, ...) -{ - int matches = 0; - int n_queries = 0; - - /* Count number of query keys so we can short-circuit when done */ - va_list args; - va_start(args, object); - for (n_queries = 0; va_arg(args, uint32_t); ++n_queries) { - if (!va_arg(args, const LV2_Atom**)) { - return -1; - } - } - va_end(args); - - LV2_OBJECT_FOREACH(object, o) { - const LV2_Atom_Property_Body* prop = lv2_object_iter_get(o); - va_start(args, object); - for (int i = 0; i < n_queries; ++i) { - uint32_t qkey = va_arg(args, uint32_t); - const LV2_Atom** qval = va_arg(args, const LV2_Atom**); - if (qkey == prop->key && !*qval) { - *qval = &prop->value; - if (++matches == n_queries) { - return matches; - } - break; - } - } - va_end(args); - } - return matches; -} - -/** - @} -*/ - -#endif /* LV2_ATOM_HELPERS_H */ diff --git a/lv2/lv2plug.in/ns/ext/atom/atom-test.c b/lv2/lv2plug.in/ns/ext/atom/atom-test.c index 2011f68..c81f581 100644 --- a/lv2/lv2plug.in/ns/ext/atom/atom-test.c +++ b/lv2/lv2plug.in/ns/ext/atom/atom-test.c @@ -18,8 +18,8 @@ #include #include -#include "lv2/lv2plug.in/ns/ext/atom/atom-helpers.h" #include "lv2/lv2plug.in/ns/ext/atom/forge.h" +#include "lv2/lv2plug.in/ns/ext/atom/util.h" char** uris = NULL; size_t n_uris = 0; diff --git a/lv2/lv2plug.in/ns/ext/atom/atom.ttl b/lv2/lv2plug.in/ns/ext/atom/atom.ttl index 677a159..2e82e32 100644 --- a/lv2/lv2plug.in/ns/ext/atom/atom.ttl +++ b/lv2/lv2plug.in/ns/ext/atom/atom.ttl @@ -27,7 +27,7 @@ doap:name "LV2 Atom" ; doap:shortdesc "A generic value container and several data types." ; doap:license ; - rdfs:seeAlso , + rdfs:seeAlso , ; doap:release [ doap:revision "0.4" ; diff --git a/lv2/lv2plug.in/ns/ext/atom/forge.h b/lv2/lv2plug.in/ns/ext/atom/forge.h index d13f549..52ba635 100644 --- a/lv2/lv2plug.in/ns/ext/atom/forge.h +++ b/lv2/lv2plug.in/ns/ext/atom/forge.h @@ -43,8 +43,8 @@ #include -#include "lv2/lv2plug.in/ns/ext/atom/atom-helpers.h" #include "lv2/lv2plug.in/ns/ext/atom/atom.h" +#include "lv2/lv2plug.in/ns/ext/atom/util.h" #include "lv2/lv2plug.in/ns/ext/urid/urid.h" #ifdef __cplusplus diff --git a/lv2/lv2plug.in/ns/ext/atom/util.h b/lv2/lv2plug.in/ns/ext/atom/util.h new file mode 100644 index 0000000..6ba792c --- /dev/null +++ b/lv2/lv2plug.in/ns/ext/atom/util.h @@ -0,0 +1,372 @@ +/* + Copyright 2008-2012 David Robillard + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + +/** + @file util.h Helper functions for the LV2 Atom extension. + + Note these functions are all static inline, do not take their address. + + This header is non-normative, it is provided for convenience. +*/ + +#ifndef LV2_ATOM_HELPERS_H +#define LV2_ATOM_HELPERS_H + +#include +#include +#include +#include + +#include "lv2/lv2plug.in/ns/ext/atom/atom.h" + +#ifdef __cplusplus +extern "C" { +#else +# include +#endif + +/** Pad a size to 64 bits. */ +static inline uint32_t +lv2_atom_pad_size(uint32_t size) +{ + return (size + 7) & (~7); +} + +/** Return the total size of @p atom, including the header. */ +static inline uint32_t +lv2_atom_total_size(const LV2_Atom* atom) +{ + return sizeof(LV2_Atom) + atom->size; +} + +/** Return true iff @p atom is null. */ +static inline bool +lv2_atom_is_null(const LV2_Atom* atom) +{ + return !atom || (atom->type == 0 && atom->size == 0); +} + +/** Return true iff @p a is equal to @p b. */ +static inline bool +lv2_atom_equals(const LV2_Atom* a, const LV2_Atom* b) +{ + return (a == b) || ( + (a->type == b->type) && + (a->size == b->size) && + !memcmp(LV2_ATOM_CONTENTS(LV2_Atom, a), + LV2_ATOM_CONTENTS(LV2_Atom, b), + a->size)); +} + +/** + @name Sequence Iterator + @{ +*/ + +/** An iterator over the elements of an LV2_Atom_Sequence. */ +typedef LV2_Atom_Event* LV2_Atom_Sequence_Iter; + +/** Get an iterator pointing to the first element in @p tup. */ +static inline LV2_Atom_Sequence_Iter +lv2_sequence_begin(const LV2_Atom_Sequence* seq) +{ + return (LV2_Atom_Sequence_Iter)(LV2_ATOM_CONTENTS(LV2_Atom_Sequence, seq)); +} + +/** Return true iff @p i has reached the end of @p tup. */ +static inline bool +lv2_sequence_is_end(const LV2_Atom_Sequence* seq, LV2_Atom_Sequence_Iter i) +{ + return (uint8_t*)i >= ((uint8_t*)seq + sizeof(LV2_Atom) + seq->atom.size); +} + +/** Return an iterator to the element following @p i. */ +static inline LV2_Atom_Sequence_Iter +lv2_sequence_iter_next(const LV2_Atom_Sequence_Iter i) +{ + return (LV2_Atom_Sequence_Iter)((uint8_t*)i + + sizeof(LV2_Atom_Event) + + lv2_atom_pad_size(i->body.size)); +} + +/** Return the element pointed to by @p i. */ +static inline LV2_Atom_Event* +lv2_sequence_iter_get(LV2_Atom_Sequence_Iter i) +{ + return (LV2_Atom_Event*)i; +} + +/** + A macro for iterating over all events in a Sequence. + @param sequence The sequence to iterate over + @param iter The name of the iterator + + This macro is used similarly to a for loop (which it expands to), e.g.: + @code + LV2_SEQUENCE_FOREACH(sequence, i) { + LV2_Atom_Event* ev = lv2_sequence_iter_get(i); + // Do something with ev here... + } + @endcode +*/ +#define LV2_SEQUENCE_FOREACH(sequence, iter) \ + for (LV2_Atom_Sequence_Iter (iter) = lv2_sequence_begin(sequence); \ + !lv2_sequence_is_end(sequence, (iter)); \ + (iter) = lv2_sequence_iter_next(iter)) + +/** + @} + @name Tuple Iterator + @{ +*/ + +/** An iterator over the elements of an LV2_Atom_Tuple. */ +typedef LV2_Atom* LV2_Atom_Tuple_Iter; + +/** Get an iterator pointing to the first element in @p tup. */ +static inline LV2_Atom_Tuple_Iter +lv2_tuple_begin(const LV2_Atom_Tuple* tup) +{ + return (LV2_Atom_Tuple_Iter)(LV2_ATOM_BODY(tup)); +} + +/** Return true iff @p i has reached the end of @p tup. */ +static inline bool +lv2_tuple_is_end(const LV2_Atom_Tuple* tup, LV2_Atom_Tuple_Iter i) +{ + return (uint8_t*)i >= ((uint8_t*)tup + sizeof(LV2_Atom) + tup->atom.size); +} + +/** Return an iterator to the element following @p i. */ +static inline LV2_Atom_Tuple_Iter +lv2_tuple_iter_next(const LV2_Atom_Tuple_Iter i) +{ + return (LV2_Atom_Tuple_Iter)( + (uint8_t*)i + sizeof(LV2_Atom) + lv2_atom_pad_size(i->size)); +} + +/** Return the element pointed to by @p i. */ +static inline LV2_Atom* +lv2_tuple_iter_get(LV2_Atom_Tuple_Iter i) +{ + return (LV2_Atom*)i; +} + +/** + A macro for iterating over all properties of a Tuple. + @param tuple The tuple to iterate over + @param iter The name of the iterator + + This macro is used similarly to a for loop (which it expands to), e.g.: + @code + LV2_TUPLE_FOREACH(tuple, i) { + LV2_Atom* elem = lv2_tuple_iter_get(i); + // Do something with elem here... + } + @endcode +*/ +#define LV2_TUPLE_FOREACH(tuple, iter) \ + for (LV2_Atom_Tuple_Iter (iter) = lv2_tuple_begin(tuple); \ + !lv2_tuple_is_end(tuple, (iter)); \ + (iter) = lv2_tuple_iter_next(iter)) + +/** + @} + @name Object Iterator + @{ +*/ + +/** An iterator over the properties of an LV2_Atom_Object. */ +typedef LV2_Atom_Property_Body* LV2_Atom_Object_Iter; + +/** Get an iterator pointing to the first property in @p obj. */ +static inline LV2_Atom_Object_Iter +lv2_object_begin(const LV2_Atom_Object* obj) +{ + return (LV2_Atom_Object_Iter)(LV2_ATOM_CONTENTS(LV2_Atom_Object, obj)); +} + +/** Return true iff @p i has reached the end of @p obj. */ +static inline bool +lv2_object_is_end(const LV2_Atom_Object* obj, LV2_Atom_Object_Iter i) +{ + return (uint8_t*)i >= ((uint8_t*)obj + sizeof(LV2_Atom) + obj->atom.size); +} + +/** Return true iff @p l points to the same property as @p r. */ +static inline bool +lv2_object_iter_equals(const LV2_Atom_Object_Iter l, + const LV2_Atom_Object_Iter r) +{ + return l == r; +} + +/** Return an iterator to the property following @p i. */ +static inline LV2_Atom_Object_Iter +lv2_object_iter_next(const LV2_Atom_Object_Iter i) +{ + const LV2_Atom* const value = (LV2_Atom*)((uint8_t*)i + sizeof(i)); + return (LV2_Atom_Object_Iter)((uint8_t*)i + + sizeof(LV2_Atom_Property_Body) + + lv2_atom_pad_size(value->size)); +} + +/** Return the property pointed to by @p i. */ +static inline LV2_Atom_Property_Body* +lv2_object_iter_get(LV2_Atom_Object_Iter i) +{ + return (LV2_Atom_Property_Body*)i; +} + +/** + A macro for iterating over all properties of an Object. + @param object The object to iterate over + @param iter The name of the iterator + + This macro is used similarly to a for loop (which it expands to), e.g.: + @code + LV2_OBJECT_FOREACH(object, i) { + LV2_Atom_Property_Body* prop = lv2_object_iter_get(i); + // Do something with prop here... + } + @endcode +*/ +#define LV2_OBJECT_FOREACH(object, iter) \ + for (LV2_Atom_Object_Iter (iter) = lv2_object_begin(object); \ + !lv2_object_is_end(object, (iter)); \ + (iter) = lv2_object_iter_next(iter)) + +/** + @} + @name Object Query + @{ +*/ + +/** A single entry in an Object query. */ +typedef struct { + uint32_t key; /**< Key to query (input set by user) */ + const LV2_Atom** value; /**< Found value (output set by query function) */ +} LV2_Atom_Object_Query; + +static const LV2_Atom_Object_Query LV2_OBJECT_QUERY_END = { 0, NULL }; + +/** + Get an object's values for various keys. + + The value pointer of each item in @p query will be set to the location of + the corresponding value in @p object. Every value pointer in @p query MUST + be initialised to NULL. This function reads @p object in a single linear + sweep. By allocating @p query on the stack, objects can be "queried" + quickly without allocating any memory. This function is realtime safe. + + For example: + @code + const LV2_Atom* name = NULL; + const LV2_Atom* age = NULL; + LV2_Atom_Object_Query q[] = { + { urids.eg_name, &name }, + { urids.eg_age, &age }, + LV2_OBJECT_QUERY_END + }; + lv2_object_get(obj, q); + // name and age are now set to the appropriate values in obj, or NULL. + @endcode +*/ +static inline int +lv2_object_get(const LV2_Atom_Object* object, LV2_Atom_Object_Query* query) +{ + int matches = 0; + int n_queries = 0; + + /* Count number of query keys so we can short-circuit when done */ + for (LV2_Atom_Object_Query* q = query; q->key; ++q) { + ++n_queries; + } + + LV2_OBJECT_FOREACH(object, o) { + const LV2_Atom_Property_Body* prop = lv2_object_iter_get(o); + for (LV2_Atom_Object_Query* q = query; q->key; ++q) { + if (q->key == prop->key && !*q->value) { + *q->value = &prop->value; + if (++matches == n_queries) { + return matches; + } + break; + } + } + } + return matches; +} + +/** + Variable argument version of lv2_object_get(). + + This is nicer-looking in code, but a bit more error-prone since it is not + type safe and the argument list must be terminated. + + The arguments should be a series of uint32_t key and const LV2_Atom** value + pairs, terminated by a zero key. The value pointers MUST be initialized to + NULL. For example: + + @code + const LV2_Atom* name = NULL; + const LV2_Atom* age = NULL; + lv2_object_getv(obj, + uris.name_key, &name, + uris.age_key, &age, + 0); + @endcode +*/ +static inline int +lv2_object_getv(const LV2_Atom_Object* object, ...) +{ + int matches = 0; + int n_queries = 0; + + /* Count number of query keys so we can short-circuit when done */ + va_list args; + va_start(args, object); + for (n_queries = 0; va_arg(args, uint32_t); ++n_queries) { + if (!va_arg(args, const LV2_Atom**)) { + return -1; + } + } + va_end(args); + + LV2_OBJECT_FOREACH(object, o) { + const LV2_Atom_Property_Body* prop = lv2_object_iter_get(o); + va_start(args, object); + for (int i = 0; i < n_queries; ++i) { + uint32_t qkey = va_arg(args, uint32_t); + const LV2_Atom** qval = va_arg(args, const LV2_Atom**); + if (qkey == prop->key && !*qval) { + *qval = &prop->value; + if (++matches == n_queries) { + return matches; + } + break; + } + } + va_end(args); + } + return matches; +} + +/** + @} +*/ + +#endif /* LV2_ATOM_HELPERS_H */ -- cgit v1.2.1