1 /*
2  * Copyright 2020 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef ANDROID_AUDIO_METADATA_H
18 #define ANDROID_AUDIO_METADATA_H
19 
20 #include <stdint.h>
21 #include <sys/cdefs.h>
22 #include <unistd.h>
23 
24 #ifdef __cplusplus
25 
26 #include <any>
27 #include <map>
28 #include <string>
29 #include <tuple>
30 #include <vector>
31 
32 /**
33  * Audio Metadata: a C++ Object based map.
34  *
35  * Data is a map of strings to Datum Objects.
36  *
37  * Datum is a C++ "Object", a direct instance of std::any, but limited
38  * to only the following allowed types:
39  *
40  * Native                              Java equivalent
41  * int32                               (int)
42  * int64                               (long)
43  * float                               (float)
44  * double                              (double)
45  * std::string                         (String)
46  * Data (std::map<std::string, Datum>) (Map<String, Object>)
47  *
48  * Metadata code supports advanced automatic parceling.
49  * TEST ONLY:
50  * std::vector<Datum>                  (Object[])             --> vector of Objects
51  * std::pair<Datum, Datum>             (Pair<Object, Object>) --> pair of Objects
52  * std::vector<std::vector<std::pair<std::string, short>>>    --> recursive containers
53  * struct { int i0; std::vector<int> v1; std::pair<int, int> p2; } --> struct parceling
54  *
55  * The Data map accepts typed Keys, which designate the type T of the
56  * value associated with the Key<T> in the template parameter.
57  *
58  * CKey<T> is the constexpr version suitable for fixed compile-time constants.
59  * Key<T> is the non-constexpr version.
60  *
61  * Notes: for future extensibility:
62  *
63  * In order to add a new type in.
64  *
65  * 1) Add the new type to the END of the metadata_types lists below.
66  *
67  * 2) The new type can be a primitive, or make use of containers std::map, std::vector,
68  * std::pair, or be simple structs (see below).
69  *
70  * 3) Simple structs contain no pointers and all public data. The members can be based
71  * on existing types.
72  *   a) If trivially copyable (packed) primitive data,
73  *      add to primitive_metadata_types.
74  *   b) If the struct requires member-wise parceling, add to structural_metadata_types
75  *      (current limit is 4 members).
76  *
77  * 4) The type system is recursive.
78  *
79  * Design notes:
80  * 1) Tuple is intentionally not implemented as it isn't that readable.  This can
81  * be revisited if the need comes up.  If you have more than a couple of elements,
82  * we suggest embedding in a Data typed map or a Simple struct.
83  *
84  * 2) Each custom type e.g. vector<int>, pair<short, char> takes one
85  * slot in the type index.  A full type description language is not implemented
86  * here for brevity and clarity.
87  */
88 
89 namespace android::audio_utils::metadata {
90 
91 // Determine if a type is a specialization of a templated type
92 // Example: is_specialization_v<T, std::vector>
93 // https://stackoverflow.com/questions/16337610/how-to-know-if-a-type-is-a-specialization-of-stdvector
94 
95 template <typename Test, template <typename...> class Ref>
96 struct is_specialization : std::false_type {};
97 
98 template <template <typename...> class Ref, typename... Args>
99 struct is_specialization<Ref<Args...>, Ref>: std::true_type {};
100 
101 template <typename Test, template <typename...> class Ref>
102 inline constexpr bool is_specialization_v = is_specialization<Test, Ref>::value;
103 
104 // For static assert(false) we need a template version to avoid early failure.
105 // See: https://stackoverflow.com/questions/51523965/template-dependent-false
106 template <typename T>
107 inline constexpr bool dependent_false_v = false;
108 
109 // Determine the number of arguments required for structured binding.
110 // See the discussion here and follow the links:
111 // https://isocpp.org/blog/2016/08/cpp17-structured-bindings-convert-struct-to-a-tuple-simple-reflection
112 struct any_type {
113   template<class T>
114   constexpr operator T(); // non explicit
115 };
116 
117 template <typename T, typename... TArgs>
118 decltype(void(T{std::declval<TArgs>()...}), std::true_type{}) test_is_braces_constructible(int);
119 
120 template <typename, typename...>
121 std::false_type test_is_braces_constructible(...);
122 
123 template <typename T, typename... TArgs>
124 using is_braces_constructible = decltype(test_is_braces_constructible<T, TArgs...>(0));
125 
126 // Set up type comparison system
127 // see std::variant for the how the type_index() may be used.
128 
129 /*
130  * returns the index of type T in the type parameter list Ts.
131  */
132 template <typename T, typename... Ts>
133 inline constexpr ssize_t type_index() {
134     constexpr bool checks[] = {std::is_same_v<std::decay_t<T>, std::decay_t<Ts>>...};
135     for (size_t i = 0; i < sizeof...(Ts); ++i) {
136         if (checks[i]) return i; // the index in Ts.
137     }
138     return -1; // none found.
139 }
140 
141 // compound_type is a holder of types. There are concatenation tricks of type lists
142 // but we don't need them here.
143 template <typename... Ts>
144 struct compound_type {
145     inline static constexpr size_t size_v = sizeof...(Ts);
146     template <typename T>
147     inline static constexpr bool contains_v = type_index<T, Ts...>() >= 0;
148     template <typename T>
149     inline static constexpr ssize_t index_of() { return type_index<T, Ts...>(); }
150 
151     // create a tupe equivalent of the compound type. This is useful for
152     // finding the nth type by std::tuple_element
153     using tuple_t = std::tuple<Ts...>;
154 
155     /**
156      * Applies function f to a datum pointer a.
157      *
158      * \param f is the function to apply.  It should take one argument,
159      *     which is a (typed) pointer to the value stored in a.
160      * \param a is the Datum object (derived from std::any).
161      * \param result if non-null stores the return value of f (if f has a return value).
162      *     result may be nullptr if one does not care about the return value of f.
163      * \return true on success, false if there is no applicable data stored in a.
164      */
165     template <typename F, typename A>
166     static bool apply(F f, A *a, std::any *result = nullptr) {
167         return apply_impl<F, A, Ts...>(f, a, result);
168     }
169 
170     // helper
171     // Linear search in the number of types because of non-cached std:any_cast
172     // lookup.  See std::visit for std::variant for constant time implementation.
173     template <typename F, typename A, typename T, typename... Ts2>
174     static bool apply_impl(F f, A *a, std::any *result) {
175         auto t = std::any_cast<T>(a); // may be const ptr or not.
176         if (t == nullptr) {
177             return apply_impl<F, A, Ts2...>(f, a, result);
178         }
179 
180         // only save result if the function has a non-void return type.
181         // and result is not nullptr.
182         using result_type = std::invoke_result_t<F, T*>;
183         if constexpr (!std::is_same_v<result_type, void>) {
184             if (result != nullptr) {
185                 *result = (result_type)f(t);
186                 return true;
187             }
188         }
189 
190         f(t); // discard the result
191         return true;
192     }
193 
194     // helper base class
195     template <typename F, typename A>
196     static bool apply_impl(F f __attribute__((unused)), A *a __attribute__((unused)),
197             std::any *result __attribute__((unused))) {
198         return false;
199     }
200 };
201 
202 #ifdef METADATA_TESTING
203 
204 // This is a helper struct to verify that we are moving Datums instead
205 // of copying them.
206 struct MoveCount {
207     int32_t mMoveCount = 0;
208     int32_t mCopyCount = 0;
209 
210     MoveCount() = default;
211     MoveCount(MoveCount&& other) {
212         mMoveCount = other.mMoveCount + 1;
213         mCopyCount = other.mCopyCount;
214     }
215     MoveCount(const MoveCount& other) {
216         mMoveCount = other.mMoveCount;
217         mCopyCount = other.mCopyCount + 1;
218     }
219     MoveCount &operator=(MoveCount&& other) {
220         mMoveCount = other.mMoveCount + 1;
221         mCopyCount = other.mCopyCount;
222         return *this;
223     }
224     MoveCount &operator=(const MoveCount& other) {
225         mMoveCount = other.mMoveCount;
226         mCopyCount = other.mCopyCount + 1;
227         return *this;
228     }
229 };
230 
231 // We can automatically parcel this "Arbitrary" struct
232 // since it has no pointers and all public members.
233 struct Arbitrary {
234     int i0;
235     std::vector<int> v1;
236     std::pair<int, int> p2;
237 };
238 
239 #endif
240 
241 class Data;
242 class Datum;
243 
244 // The order of this list must be maintained for binary compatibility
245 using metadata_types = compound_type<
246     int32_t,
247     int64_t,
248     float,
249     double,
250     std::string,
251     Data /* std::map<std::string, Datum> */
252     // OK to add at end.
253 #ifdef METADATA_TESTING
254     , std::vector<Datum>      // another complex object for testing
255     , std::pair<Datum, Datum> // another complex object for testing
256     , std::vector<std::vector<std::pair<std::string, short>>> // complex object
257     , MoveCount
258     , Arbitrary
259 #endif
260     >;
261 
262 // A subset of the metadata types may be directly copied as bytes
263 using primitive_metadata_types = compound_type<int32_t, int64_t, float, double
264 #ifdef METADATA_TESTING
265     , MoveCount
266 #endif
267     >;
268 
269 // A subset of metadata types which are a struct-based.
270 using structural_metadata_types = compound_type<
271 #ifdef METADATA_TESTING
272     Arbitrary
273 #endif
274     >;
275 
276 template <typename T>
277 inline constexpr bool is_primitive_metadata_type_v =
278     primitive_metadata_types::contains_v<T>;
279 
280 template <typename T>
281 inline constexpr bool is_structural_metadata_type_v =
282     structural_metadata_types::contains_v<T>;
283 
284 template <typename T>
285 inline constexpr bool is_metadata_type_v =
286     metadata_types::contains_v<T>;
287 
288 /**
289  * Datum is the C++ version of Object, based on std::any
290  * to be portable to other Data Object systems on std::any. For C++, there
291  * are two forms of generalized Objects, std::variant and std::any.
292  *
293  * What is a variant?
294  * std::variant is like a std::pair<type_index, union>, where the types
295  * are kept in the template parameter list, and you only need to store
296  * the type_index of the current value's type in the template parameter
297  * list to find the value's type (to access data in the union).
298  *
299  * What is an any?
300  * std::any is a std::pair<type_func, pointer> (though the standard encourages
301  * small buffer optimization of the pointer for small data types,
302  * so the pointer might actually be data).  The type_func is cleverly
303  * implemented templated, so that one type_func exists per type.
304  *
305  * For datum, we use std::any, which is different than mediametrics::Item
306  * (which uses std::variant).
307  *
308  * std::any is the C++ version of Java's Object.  One benefit of std::any
309  * over std::variant is that it is portable outside of this package as a
310  * std::any, to another C++ Object system based on std::any
311  * (as we any_cast to discover the type). std::variant does not have this
312  * portability (without copy conversion) because it requires an explicit
313  * type list to be known in the template, so you can't exchange them freely
314  * as the union size and the type/type ordering will be different in general
315  * between two variant-based Object systems.
316  *
317  * std::any may work better with some recursive types than variants,
318  * as it uses pointers so that physical size need not be known for type
319  * definition.
320  *
321  * This is a design choice: mediametrics::Item as a closed system,
322  * metadata::Datum as an open system.
323  *
324  * CAUTION:
325  * For efficiency, prefer the use of std::any_cast<T>(std::any *)
326  *       which returns a pointer to T (no extra copies.)
327  *
328  * std::any_cast<T>(std::any) returns an instance of T (copy constructor).
329  * std::get<N>(std::variant) returns a reference (no extra copies).
330  *
331  * The Data map operations are optimized to return references to
332  * avoid unnecessary copies.
333  */
334 
335 class Datum : public std::any {
336 public:
337     // Don't add any virtual functions or non-static member variables.
338 
339     Datum() = default;
340 
341     // Do not make these explicit
342     // Force type of std::any to exactly the values we permit to be parceled.
343     template <typename T, typename = std::enable_if_t<is_metadata_type_v<T>>>
344     Datum(T && t) : std::any(std::forward<T>(t)) {};
345 
346     template <typename T, typename = std::enable_if_t<is_metadata_type_v<T>>>
347     Datum& operator=(T&& t) {
348         static_cast<std::any *>(this)->operator=(std::forward<T>(t));
349         return *this;
350     }
351 
352     Datum(const char *t) : std::any(std::string(t)) {}; // special string handling
353 };
354 
355 // PREVENT INCORRECT MODIFICATIONS
356 // Datum is a helping wrapper on std::any
357 // Don't add any non-static members
358 static_assert(sizeof(Datum) == sizeof(std::any));
359 // Nothing is virtual
360 static_assert(!std::is_polymorphic_v<Datum>);
361 
362 /**
363  * Keys
364  *
365  * Audio Metadata keys are typed.  Similar to variant's template typenames,
366  * which directly indicate possible types in the union, the Audio Metadata
367  * Keys contain the Value's Type in the Key's template type parameter.
368  *
369  * Example:
370  *
371  * inline constexpr CKey<int64_t> MY_BIGINT("bigint_is_mine");
372  * inline constexpr CKey<Data> TABLE("table");
373  *
374  * Thus if we have a Data object d:
375  *
376  * decltype(d[TABLE]) is Data
377  * decltype(d[MY_BIGINT) is int64_t
378  */
379 
380 /**
381  * Key is a non-constexpr key which has local storage in a string.
382  */
383 template <typename T, typename = std::enable_if_t<is_metadata_type_v<T>>>
384 class Key : private std::string {
385 public:
386     using std::string::string; // base constructor
387     const char *getName() const { return c_str(); }
388 };
389 
390 /**
391  * CKey is a constexpr key, which is preferred.
392  *
393  * inline constexpr CKey<int64_t> MY_BIGINT("bigint_is_mine");
394  */
395 template <typename T, typename = std::enable_if_t<is_metadata_type_v<T>>>
396 class CKey  {
397     const char * const mName;
398 public:
399     explicit constexpr CKey(const char *name) : mName(name) {}
400     CKey(const Key<T> &key) : mName(key.getName()) {}
401     const char *getName() const { return mName; }
402 };
403 
404 /**
405  * Data is the storage for our Datums.
406  *
407  * It is implemented on top of std::map<std::string, Datum>
408  * but we augment it with typed Key
409  * getters and setters, as well as operator[] overloads.
410  */
411 class Data : public std::map<std::string, Datum> {
412 public:
413     // Don't add any virtual functions or non-static member variables.
414 
415     // We supplement the raw form of map with
416     // the following typed form using Key.
417 
418     // Intentionally there is no get(), we suggest *get_ptr()
419     template <template <typename /* T */, typename... /* enable-ifs */> class K, typename T>
420     T* get_ptr(const K<T>& key, bool allocate = false) {
421         auto it = find(key.getName());
422         if (it == this->end()) {
423             if (!allocate) return nullptr;
424             it = emplace(key.getName(), T{}).first;
425         }
426         return std::any_cast<T>(&it->second);
427     }
428 
429     template <template <typename, typename...> class K, typename T>
430     const T* get_ptr(const K<T>& key) const {
431         auto it = find(key.getName());
432         if (it == this->end()) return nullptr;
433         return std::any_cast<T>(&it->second);
434     }
435 
436     template <template <typename, typename...> class K, typename T>
437     void put(const K<T>& key, T && t) {
438         (*this)[key.getName()] = std::forward<T>(t);
439     }
440 
441     template <template <typename, typename...> class K>
442     void put(const K<std::string>& key, const char *value) {
443         (*this)[key.getName()] = value;
444     }
445 
446     // We overload our operator[] so we unhide the one in the base class.
447     using std::map<std::string, Datum>::operator[];
448 
449     template <template <typename, typename...> class K, typename T>
450     T& operator[](const K<T> &key) {
451         return *get_ptr(key, /* allocate */ true);
452     }
453 
454     template <template <typename, typename...> class K, typename T>
455     const T& operator[](const K<T> &key) const {
456         return *get_ptr(key);
457     }
458 };
459 
460 // PREVENT INCORRECT MODIFICATIONS
461 // Data is a helping wrapper on std::map
462 // Don't add any non-static members
463 static_assert(sizeof(Data) == sizeof(std::map<std::string, Datum>));
464 // Nothing is virtual
465 static_assert(!std::is_polymorphic_v<Data>);
466 
467 /**
468  * Parceling of Datum by recursive descent to a ByteString
469  *
470  * Parceling Format:
471  * All values are native endian order.
472  *
473  * Datum = {
474  *           (type_size_t)  Type (the type index from type_as_value<T>.)
475  *           (datum_size_t) Size (size of Payload)
476  *           (byte string)  Payload<Type>
477  *         }
478  *
479  * Payload<Primitive_Type> = { bytes in native endian order }
480  *
481  * Payload<String> = { (index_size_t) number of elements (not including zero termination)
482  *                     bytes of string data.
483  *                   }
484  *
485  * Vector, Map, Container types:
486  * Payload<Type> = { (index_size_t) number of elements
487  *                   (byte string)  Payload<Element_Type> * number
488  *                 }
489  *
490  * Pair container types:
491  * Payload<Type> = { (byte string) Payload<first>,
492  *                   (byte string) Payload<second>
493  *                 }
494  *
495  * Note: Data is a std::map<std::string, Datum>
496  *
497  * Design notes:
498  *
499  * 1) The size of each datum allows skipping of unknown types for compatibility
500  * of older code with newer Datums.
501  *
502  * Examples:
503  * Payload<Int32> of 123
504  * [ value of 123                   ] =  0x7b 0x00 0x00 0x00       123
505  *
506  * Example of Payload<String> of std::string("hi"):
507  * [ (index_size_t) length          ] = 0x02 0x00 0x00 0x00        2 strlen("hi")
508  * [ raw bytes "hi"                 ] = 0x68 0x69                  "hi"
509  *
510  * Payload<Data>
511  * [ (index_size_t) entries ]
512  * [ raw bytes   (entry 1) Key   (Payload<String>)
513  *                         Value (Datum)
514  *                ...  (until #entries) ]
515  *
516  * Example of Payload<Data> of {{"hello", "world"},
517  *                              {"value", (int32_t)1000}};
518  * [ (index_size_t) #entries        ] = 0x02 0x00 0x00 0x00        2 entries
519  *    Key (Payload<String>)
520  *    [ index_size_t length         ] = 0x05 0x00 0x00 0x00        5 strlen("hello")
521  *    [ raw bytes "hello"           ] = 0x68 0x65 0x6c 0x6c 0x6f   "hello"
522  *    Value (Datum)
523  *    [ (type_size_t) type          ] = 0x05 0x00 0x00 0x00        5 (TYPE_STRING)
524  *    [ (datum_size_t) size         ] = 0x09 0x00 0x00 0x00        sizeof(index_size_t) +
525  *                                                                 strlen("world")
526  *       Payload<String>
527  *       [ (index_size_t) length    ] = 0x05 0x00 0x00 0x00        5 strlen("world")
528  *       [ raw bytes "world"        ] = 0x77 0x6f 0x72 0x6c 0x64   "world"
529  *    Key (Payload<String>)
530  *    [ index_size_t length         ] = 0x05 0x00 0x00 0x00        5 strlen("value")
531  *    [ raw bytes "value"           ] = 0x76 0x61 0x6c 0x75 0x65   "value"
532  *    Value (Datum)
533  *    [ (type_size_t) type          ] = 0x01 0x00 0x00 0x00        1 (TYPE_INT32)
534  *    [ (datum_size_t) size         ] = 0x04 0x00 0x00 0x00        4 sizeof(int32_t)
535  *        Payload<Int32>
536  *        [ raw bytes 1000          ] = 0xe8 0x03 0x00 0x00        1000
537  *
538  * Metadata is passed as a Payload<Data>.
539  * An implementation dependent detail is that the Keys are always
540  * stored sorted, so the byte string representation generated is unique.
541  */
542 
543 // Platform Apex compatibility note:
544 // type_size_t may not change.
545 using type_size_t = uint32_t;
546 
547 // Platform Apex compatibility note:
548 // index_size_t must not change.
549 using index_size_t = uint32_t;
550 
551 // Platform Apex compatibility note:
552 // datum_size_t must not change.
553 using datum_size_t = uint32_t;
554 
555 // The particular implementation of ByteString may change
556 // without affecting compatibility.
557 using ByteString = std::basic_string<uint8_t>;
558 
559 /*
560     These should correspond to the Java AudioMetadata.java
561 
562     Permitted type indexes:
563 
564     TYPE_NONE = 0,
565     TYPE_INT32 = 1,
566     TYPE_INT64 = 2,
567     TYPE_FLOAT = 3,
568     TYPE_DOUBLE = 4,
569     TYPE_STRING = 5,
570     TYPE_DATA = 6,
571 */
572 
573 template <typename T>
574 inline constexpr type_size_t get_type_as_value() {
575     return (type_size_t)(metadata_types::index_of<T>() + 1);
576 }
577 
578 template <typename T>
579 inline constexpr type_size_t type_as_value = get_type_as_value<T>();
580 
581 // forward decl for recursion - do not remove.
582 bool copyToByteString(const Datum& datum, ByteString &bs);
583 
584 template <template <typename ...> class V, typename... Args>
585 bool copyToByteString(const V<Args...>& v, ByteString&bs);
586 // end forward decl
587 
588 // primitives handled here
589 template <typename T>
590 std::enable_if_t<
591     is_primitive_metadata_type_v<T> || std::is_arithmetic_v<std::decay_t<T>>,
592     bool
593     >
594 copyToByteString(const T& t, ByteString& bs) {
595     bs.append((uint8_t*)&t, sizeof(t));
596     return true;
597 }
598 
599 // pairs handled here
600 template <typename A, typename B>
601 bool copyToByteString(const std::pair<A, B>& p, ByteString& bs) {
602     return copyToByteString(p.first, bs) && copyToByteString(p.second, bs);
603 }
604 
605 // containers
606 template <template <typename ...> class V, typename... Args>
607 bool copyToByteString(const V<Args...>& v, ByteString& bs) {
608     if (v.size() > std::numeric_limits<index_size_t>::max()) return false;
609     index_size_t size = v.size();
610     if (!copyToByteString(size, bs)) return false;
611     if constexpr (std::is_same_v<std::decay_t<V<Args...>>, std::string>) {
612         bs.append((uint8_t*)v.c_str());
613     }  else /* constexpr */ {
614         for (const auto &d : v) { // handles std::vector and std::map
615             if (!copyToByteString(d, bs)) return false;
616         }
617     }
618     return true;
619 }
620 
621 // simple struct data (use structured binding to extract members)
622 template <typename T>
623 std::enable_if_t<
624     is_structural_metadata_type_v<T>,
625     bool
626     >
627 copyToByteString(const T& t, ByteString& bs) {
628     using type = std::decay_t<T>;
629     if constexpr (is_braces_constructible<type, any_type, any_type, any_type, any_type>{}) {
630         const auto& [e1, e2, e3, e4] = t;
631         return copyToByteString(e1, bs)
632             && copyToByteString(e2, bs)
633             && copyToByteString(e3, bs)
634             && copyToByteString(e4, bs);
635     } else if constexpr (is_braces_constructible<type, any_type, any_type, any_type>{}) {
636         const auto& [e1, e2, e3] = t;
637         return copyToByteString(e1, bs)
638             && copyToByteString(e2, bs)
639             && copyToByteString(e3, bs);
640     } else if constexpr (is_braces_constructible<type, any_type, any_type>{}) {
641         const auto& [e1, e2] = t;
642         return copyToByteString(e1, bs)
643             && copyToByteString(e2, bs);
644     } else if constexpr(is_braces_constructible<type, any_type>{}) {
645         const auto& [e1] = t;
646         return copyToByteString(e1, bs);
647     } else if constexpr (is_braces_constructible<type>{}) {
648         return true; // like std::monostate - no members
649     } else /* constexpr */ {
650         static_assert(dependent_false_v<T>);
651     }
652 }
653 
654 // TODO Consider moving to .cpp, but one advantage of keeping in the header
655 // is that C++ invocations don't need to link with the shared library.
656 
657 // Datum
658 inline
659 bool copyToByteString(const Datum& datum, ByteString &bs) {
660     bool success = false;
661     return metadata_types::apply([&bs, &success](auto ptr) {
662              // save type
663              const type_size_t type = type_as_value<decltype(*ptr)>;
664              if (!copyToByteString(type, bs)) return;
665 
666              // get current location
667              const size_t idx = bs.size();
668 
669              // save size (replaced later)
670              datum_size_t datum_size = 0;
671              if (!copyToByteString(datum_size, bs)) return;
672 
673              // copy data
674              if (!copyToByteString(*ptr, bs)) return;
675 
676              // save correct size
677              const size_t diff = bs.size() - idx - sizeof(datum_size);
678              if (diff > std::numeric_limits<datum_size_t>::max()) return;
679              datum_size = diff;
680              bs.replace(idx, sizeof(datum_size), (uint8_t*)&datum_size, sizeof(datum_size));
681              success = true;
682          }, &datum) && success;
683 }
684 
685 /**
686  * Obtaining the Datum back from ByteString
687  */
688 
689 // A container that lists all the unknown types found during parsing.
690 using ByteStringUnknowns = std::vector<type_size_t>;
691 
692 // forward decl for recursion - do not remove.
693 bool copyFromByteString(Datum *datum, const ByteString &bs, size_t& idx,
694         ByteStringUnknowns *unknowns);
695 
696 template <template <typename ...> class V, typename... Args>
697 bool copyFromByteString(V<Args...> *v, const ByteString& bs, size_t& idx,
698         ByteStringUnknowns *unknowns);
699 
700 // primitive
701 template <typename T>
702 std::enable_if_t<
703         is_primitive_metadata_type_v<T> ||
704         std::is_arithmetic_v<std::decay_t<T>>,
705         bool
706         >
707 copyFromByteString(T *dest, const ByteString& bs, size_t& idx,
708         ByteStringUnknowns *unknowns __attribute__((unused))) {
709     if (idx + sizeof(T) > bs.size()) return false;
710     bs.copy((uint8_t*)dest, sizeof(T), idx);
711     idx += sizeof(T);
712     return true;
713 }
714 
715 // pairs
716 template <typename A, typename B>
717 bool copyFromByteString(std::pair<A, B>* p, const ByteString& bs, size_t& idx,
718         ByteStringUnknowns *unknowns) {
719     return copyFromByteString(&p->first, bs, idx, unknowns)
720             && copyFromByteString(&p->second, bs, idx, unknowns);
721 }
722 
723 // containers
724 template <template <typename ...> class V, typename... Args>
725 bool copyFromByteString(V<Args...> *v, const ByteString& bs, size_t& idx,
726         ByteStringUnknowns *unknowns) {
727     index_size_t size;
728     if (!copyFromByteString(&size, bs, idx, unknowns)) return false;
729 
730     if constexpr (std::is_same_v<std::decay_t<V<Args...>>, std::string>) {
731         if (size > bs.size() - idx) return false;
732         v->resize(size);
733         for (index_size_t i = 0; i < size; ++i) {
734             (*v)[i] = bs[idx++];
735         }
736     } else if constexpr (is_specialization_v<std::decay_t<V<Args...>>, std::vector>) {
737         for (index_size_t i = 0; i < size; ++i) {
738             std::decay_t<decltype(*v->begin())> value{};
739             if (!copyFromByteString(&value, bs, idx, unknowns)) {
740                 return false;
741             }
742             if constexpr (std::is_same_v<std::decay_t<decltype(value)>, Datum>) {
743                 if (!value.has_value()) {
744                     continue;  // ignore empty datum values in a vector.
745                 }
746             }
747             v->emplace_back(std::move(value));
748         }
749     } else if constexpr (is_specialization_v<std::decay_t<V<Args...>>, std::map>) {
750         for (index_size_t i = 0; i < size; ++i) {
751             // we can't directly use pair because there may be internal const decls.
752             std::decay_t<decltype(v->begin()->first)> key{};
753             std::decay_t<decltype(v->begin()->second)> value{};
754             if (!copyFromByteString(&key, bs, idx, unknowns) ||
755                     !copyFromByteString(&value, bs, idx, unknowns)) {
756                 return false;
757             }
758             if constexpr (std::is_same_v<std::decay_t<decltype(value)>, Datum>) {
759                 if (!value.has_value()) {
760                     continue;  // ignore empty datum values in a map.
761                 }
762             }
763             v->emplace(std::move(key), std::move(value));
764         }
765     } else /* constexpr */ {
766         for (index_size_t i = 0; i < size; ++i) {
767             std::decay_t<decltype(*v->begin())> value{};
768             if (!copyFromByteString(&value, bs, idx, unknowns)) {
769                 return false;
770             }
771             v->emplace(std::move(value));
772         }
773     }
774     return true;
775 }
776 
777 // simple structs (use structured binding to extract members)
778 template <typename T>
779 typename std::enable_if_t<is_structural_metadata_type_v<T>, bool>
780 copyFromByteString(T *t, const ByteString& bs, size_t& idx,
781         ByteStringUnknowns *unknowns) {
782     using type = std::decay_t<T>;
783     if constexpr (is_braces_constructible<type, any_type, any_type, any_type, any_type>{}) {
784         auto& [e1, e2, e3, e4] =  *t;
785         return copyFromByteString(&e1, bs, idx, unknowns)
786             && copyFromByteString(&e2, bs, idx, unknowns)
787             && copyFromByteString(&e3, bs, idx, unknowns)
788             && copyFromByteString(&e4, bs, idx, unknowns);
789     } else if constexpr (is_braces_constructible<type, any_type, any_type, any_type>{}) {
790         auto& [e1, e2, e3] =  *t;
791         return copyFromByteString(&e1, bs, idx, unknowns)
792             && copyFromByteString(&e2, bs, idx, unknowns)
793             && copyFromByteString(&e3, bs, idx, unknowns);
794     } else if constexpr (is_braces_constructible<type, any_type, any_type>{}) {
795         auto& [e1, e2] =  *t;
796         return copyFromByteString(&e1, bs, idx, unknowns)
797             && copyFromByteString(&e2, bs, idx, unknowns);
798     } else if constexpr (is_braces_constructible<type, any_type>{}) {
799         auto& [e1] =  *t;
800         return copyFromByteString(&e1, bs, idx, unknowns);
801     } else if constexpr (is_braces_constructible<type>{}) {
802         return true; // like std::monostate - no members
803     } else /* constexpr */ {
804         static_assert(dependent_false_v<T>);
805     }
806 }
807 
808 namespace tedious_details {
809 //
810 // We build a function table at compile time to lookup the proper copyFromByteString method.
811 // See:
812 // https://stackoverflow.com/questions/36785345/void-to-the-nth-element-of-stdtuple-at-runtime
813 // Constant time implementation of std::visit (variant)
814 
815 template <typename CompoundT, size_t Index>
816 bool copyFromByteString(Datum *datum, const ByteString &bs, size_t &idx, size_t endIdx,
817         ByteStringUnknowns *unknowns) {
818    using T = std::tuple_element_t<Index, typename CompoundT::tuple_t>;
819    T value;
820    if (!android::audio_utils::metadata::copyFromByteString(
821            &value, bs, idx, unknowns)) return false;  // have we parsed correctly?
822    if (idx != endIdx) return false;  // have we consumed the correct number of bytes?
823    *datum = std::move(value);
824    return true;
825 }
826 
827 template <typename CompoundT, size_t... Indexes>
828 constexpr bool copyFromByteString(Datum *datum, const ByteString &bs,
829         size_t &idx, size_t endIdx, ByteStringUnknowns *unknowns,
830         size_t typeIndex, std::index_sequence<Indexes...>)
831 {
832     using function_type =
833             bool (*)(Datum*, const ByteString&, size_t&, size_t, ByteStringUnknowns*);
834     function_type constexpr ptrs[] = {
835         &copyFromByteString<CompoundT, Indexes>...
836     };
837     return ptrs[typeIndex](datum, bs, idx, endIdx, unknowns);
838 }
839 
840 template <typename CompoundT>
841 __attribute__((noinline))
842 constexpr bool copyFromByteString(Datum *datum, const ByteString &bs,
843         size_t &idx, size_t endIdx, ByteStringUnknowns *unknowns, size_t typeIndex) {
844   return copyFromByteString<CompoundT>(
845           datum, bs, idx, endIdx, unknowns,
846           typeIndex, std::make_index_sequence<CompoundT::size_v>());
847 }
848 
849 } // namespace tedious_details
850 
851 // TODO Ditto about moving to .cpp.
852 
853 inline
854 bool copyFromByteString(Datum *datum, const ByteString &bs, size_t& idx,
855         ByteStringUnknowns *unknowns) {
856     type_size_t type;
857     if (!copyFromByteString(&type, bs, idx, unknowns)) return false;
858 
859     datum_size_t datum_size;
860     if (!copyFromByteString(&datum_size, bs, idx, unknowns)) return false;
861     if (datum_size > bs.size() - idx) return false;
862     const size_t endIdx = idx + datum_size;
863 
864     if (type == 0 || type > metadata_types::size_v) {
865         idx = endIdx; // skip unrecognized type.
866         if (unknowns != nullptr) {
867             unknowns->push_back(type);
868             return true;  // allow further recursion.
869         }
870         return false;
871     }
872 
873     // use special trick to instantiate all the types for copyFromByteString
874     // in a table and find the right method from table lookup.
875     return tedious_details::copyFromByteString<metadata_types>(
876             datum, bs, idx, endIdx, unknowns, type - 1);
877 }
878 
879 // Handy helpers - these are the most efficient ways to parcel Data.
880 /**
881  * Returns the Data map from a byte string.
882  *
883  * If unknowns is nullptr, then any unknown entries during parsing will cause
884  * an empty map to be returned.
885  *
886  * If unknowns is non-null, then it contains all of the unknown types
887  * encountered during parsing, and a partial map will be returned excluding all
888  * unknown types encountered.
889  */
890 inline
891 Data dataFromByteString(const ByteString &bs,
892         ByteStringUnknowns *unknowns = nullptr) {
893     Data d;
894     size_t idx = 0;
895     if (!copyFromByteString(&d, bs, idx, unknowns)) {
896         return {};
897     }
898     return d; // copy elision
899 }
900 
901 inline
902 ByteString byteStringFromData(const Data &data) {
903     ByteString bs;
904     copyToByteString(data, bs);
905     return bs; // copy elision
906 }
907 
908 /**
909  * \brief Returns the length of the byte string buffer from the raw pointer.
910  *
911  * The raw pointer comes from the Data object's ByteString.data()
912  * or from the C API byte_string_from_audio_metadata().
913  * This is a helper method for C implementations which may pass the raw
914  * byte string buffer pointer (which does not directly contain the length).
915  * C++ methods should always use the ByteString object.
916  *
917  * \param byteString       byte string buffer raw pointer.
918  * \return size in bytes of metadata in the buffer or 0 if something went wrong.
919  */
920 
921 inline size_t dataByteStringLen(const uint8_t *ptr) {
922     index_size_t elements;
923     const uint8_t * const origPtr = ptr;
924     memcpy(&elements, ptr, sizeof(elements));
925     ptr += sizeof(elements);
926     for (index_size_t i = 0; i < elements; ++i) {
927         // get key (string)
928         index_size_t keyLen;
929         memcpy(&keyLen, ptr, sizeof(keyLen));
930         ptr += keyLen + sizeof(keyLen);
931         // get type
932         type_size_t type;
933         memcpy(&type, ptr, sizeof(type));
934         ptr += sizeof(type_size_t);
935         // Note: could check type validity.
936         // payload size
937         datum_size_t datumSize;
938         memcpy(&datumSize, ptr, sizeof(datumSize));
939         ptr += datumSize + sizeof(datumSize);
940     }
941     const ptrdiff_t size = ptr - origPtr;
942     return size < 0 ? 0 : size;
943 }
944 
945 } // namespace android::audio_utils::metadata
946 
947 #endif // __cplusplus
948 
949 // C API (see C++ API above for details)
950 
951 /** \cond */
952 __BEGIN_DECLS
953 /** \endcond */
954 
955 typedef struct audio_metadata_t audio_metadata_t;
956 
957 // Used by audio_metadata_put_unknown() and audio_metadata_get_unknown(), but not part of public API
958 // The name and data structure representation discourage accidental use.
959 typedef struct { char c; } audio_metadata_unknown_t;
960 
961 /**
962  * \brief Creates a metadata object
963  *
964  * \return the metadata object or NULL on failure. Caller must call
965  *         audio_metadata_destroy to free memory.
966  */
967 audio_metadata_t *audio_metadata_create();
968 
969 /**
970  * \brief Put key value pair where the value type is int32_t to audio metadata.
971  *
972  * \param metadata         the audio metadata object.
973  * \param key              the key of the element to be put.
974  * \param value            the value of the element to be put.
975  * \return 0 if the key value pair is put successfully into the audio metadata.
976  *         -EINVAL if metadata or key is null.
977  */
978 int audio_metadata_put_int32(audio_metadata_t *metadata, const char *key, int32_t value);
979 
980 /**
981  * \brief Put key value pair where the value type is int64_t to audio metadata.
982  *
983  * \param metadata         the audio metadata object.
984  * \param key              the key of the element to be put.
985  * \param value            the value of the element to be put.
986  * \return 0 if the key value pair is put successfully into the audio metadata.
987  *         -EINVAL if metadata or key is null.
988  */
989 int audio_metadata_put_int64(audio_metadata_t *metadata, const char *key, int64_t value);
990 
991 /**
992  * \brief Put key value pair where the value type is float to audio metadata.
993  *
994  * \param metadata         the audio metadata object.
995  * \param key              the key of the element to be put.
996  * \param value            the value of the element to be put.
997  * \return 0 if the key value pair is put successfully into the audio metadata.
998  *         -EINVAL if metadata or key is null.
999  */
1000 int audio_metadata_put_float(audio_metadata_t *metadata, const char *key, float value);
1001 
1002 /**
1003  * \brief Put key value pair where the value type is double to audio metadata.
1004  *
1005  * \param metadata         the audio metadata object.
1006  * \param key              the key of the element to be put.
1007  * \param value            the value of the element to be put.
1008  * \return 0 if the key value pair is put successfully into the audio metadata.
1009  *         -EINVAL if metadata or key is null.
1010  */
1011 int audio_metadata_put_double(audio_metadata_t *metadata, const char *key, double value);
1012 
1013 /**
1014  * \brief Put key value pair where the value type is `const char *` to audio metadata.
1015  *
1016  * \param metadata         the audio metadata object.
1017  * \param key              the key of the element to be put.
1018  * \param value            the value of the element to be put.
1019  * \return 0 if the key value pair is put successfully into the audio metadata.
1020  *         -EINVAL if metadata, key or value is null.
1021  */
1022 int audio_metadata_put_string(audio_metadata_t *metadata, const char *key, const char *value);
1023 
1024 /**
1025  * \brief Put key value pair where the value type is audio_metadata_t to audio metadata.
1026  *
1027  * \param metadata         the audio metadata object.
1028  * \param key              the key of the element to be put.
1029  * \param value            the value of the element to be put.
1030  * \return 0 if the key value pair is put successfully into the audio metadata.
1031  *         -EINVAL if metadata, key or value is null.
1032  */
1033 int audio_metadata_put_data(audio_metadata_t *metadata, const char *key, audio_metadata_t *value);
1034 
1035 /**
1036  * \brief Declared but not implemented, as any potential caller won't supply a correct value.
1037  */
1038 int audio_metadata_put_unknown(audio_metadata_t *metadata, const char *key,
1039         audio_metadata_unknown_t value);
1040 
1041 #ifndef __cplusplus // Only C11 has _Generic; C++ uses overloaded declarations instead
1042 
1043 // use C Generics to provide interfaces for put/get functions
1044 // See: https://en.cppreference.com/w/c/language/generic
1045 
1046 /**
1047  * A generic interface to put key value pair into the audio metadata.
1048  * Fails at compile-time if type isn't supported.
1049  */
1050 #define audio_metadata_put(metadata, key, value) _Generic((value), \
1051     int32_t: audio_metadata_put_int32,                             \
1052     int64_t: audio_metadata_put_int64,                             \
1053     float: audio_metadata_put_float,                               \
1054     double: audio_metadata_put_double,                             \
1055     /* https://stackoverflow.com/questions/18857056/c11-generic-how-to-deal-with-string-literals */ \
1056     const char*: audio_metadata_put_string,                        \
1057     char*: audio_metadata_put_string,                              \
1058     audio_metadata_t*: audio_metadata_put_data,                    \
1059     default: audio_metadata_put_unknown                            \
1060     )(metadata, key, value)
1061 
1062 #endif  // !__cplusplus
1063 
1064 /**
1065  * \brief Get mapped value whose type is int32_t by a given key from audio metadata.
1066  *
1067  * \param metadata         the audio metadata object.
1068  * \param key              the key value to get value.
1069  * \param value            the mapped value to be written.
1070  * \return -EINVAL when 1) metadata is null, 2) key is null, or 3) value is null.
1071  *         -ENOENT when 1) key is found in the audio metadata,
1072  *                      2) the type of mapped value is not int32_t.
1073  *         0 if successfully find the mapped value.
1074  */
1075 int audio_metadata_get_int32(audio_metadata_t *metadata, const char *key, int32_t *value);
1076 
1077 /**
1078  * \brief Get mapped value whose type is int64_t by a given key from audio metadata.
1079  *
1080  * \param metadata         the audio metadata object.
1081  * \param key              the key value to get value.
1082  * \param value            the mapped value to be written.
1083  * \return -EINVAL when 1) metadata is null, 2) key is null, or 3) value is null.
1084  *         -ENOENT when 1) key is found in the audio metadata,
1085  *                      2) the type of mapped value is not int32_t.
1086  *         0 if successfully find the mapped value.
1087  */
1088 int audio_metadata_get_int64(audio_metadata_t *metadata, const char *key, int64_t *value);
1089 
1090 /**
1091  * \brief Get mapped value whose type is float by a given key from audio metadata.
1092  *
1093  * \param metadata         the audio metadata object.
1094  * \param key              the key value to get value.
1095  * \param value            the mapped value to be written.
1096  * \return -EINVAL when 1) metadata is null, 2) key is null, or 3) value is null.
1097  *         -ENOENT when 1) key is found in the audio metadata,
1098  *                      2) the type of mapped value is not float.
1099  *         0 if successfully find the mapped value.
1100  */
1101 int audio_metadata_get_float(audio_metadata_t *metadata, const char *key, float *value);
1102 
1103 /**
1104  * \brief Get mapped value whose type is double by a given key from audio metadata.
1105  *
1106  * \param metadata         the audio metadata object.
1107  * \param key              the key value to get value.
1108  * \param value            the mapped value to be written.
1109  * \return -EINVAL when 1) metadata is null, 2) key is null, or 3) value is null.
1110  *         -ENOENT when 1) key is found in the audio metadata,
1111  *                      2) the type of mapped value is not double.
1112  *         0 if successfully find the mapped value.
1113  */
1114 int audio_metadata_get_double(audio_metadata_t *metadata, const char *key, double *value);
1115 
1116 /**
1117  * \brief Get mapped value whose type is std::string by a given key from audio metadata.
1118  *
1119  * \param metadata         the audio metadata object.
1120  * \param key              the key value to get value.
1121  * \param value            the mapped value to be written. The memory will be allocated in the
1122  *                         function, which must be freed by caller.
1123  * \return -EINVAL when 1) metadata is null, 2) key is null, or 3) value is null.
1124  *         -ENOENT when 1) key is found in the audio metadata,
1125  *                      2) the type of mapped value is not std::string.
1126  *         -ENOMEM when fails allocating memory for value.
1127  *         0 if successfully find the mapped value.
1128  */
1129 int audio_metadata_get_string(audio_metadata_t *metadata, const char *key, char **value);
1130 
1131 /**
1132  * \brief Get mapped value whose type is audio_metadata_t by a given key from audio metadata.
1133  *
1134  * \param metadata         the audio metadata object.
1135  * \param key              the key value to get value.
1136  * \param value            the mapped value to be written. The memory will be allocated in the
1137  *                         function, which should be free by caller via audio_metadata_destroy.
1138  * \return -EINVAL when 1) metadata is null, 2) key is null, or 3) value is null.
1139  *         -ENOENT when 1) key is found in the audio metadata,
1140  *                      2) the type of mapped value is not audio_utils::metadata::Data.
1141  *         -ENOMEM when fails allocating memory for value.
1142  *         0 if successfully find the mapped value.
1143  */
1144 int audio_metadata_get_data(audio_metadata_t *metadata, const char *key, audio_metadata_t **value);
1145 
1146 /**
1147  * \brief Declared but not implemented, as any potential caller won't supply a correct value.
1148  */
1149 int audio_metadata_get_unknown(audio_metadata_t *metadata, const char *key,
1150         audio_metadata_unknown_t *value);
1151 
1152 #ifndef __cplusplus // Only C11 has _Generic; C++ uses overloaded declarations instead
1153 
1154 /**
1155  * A generic interface to get mapped value by a given key from audio metadata. The value object
1156  * will remain the same if the key is not found in the audio metadata.
1157  * Fails at compile-time if type isn't supported.
1158  */
1159 #define audio_metadata_get(metadata, key, value) _Generic((value), \
1160     int32_t*: audio_metadata_get_int32,                            \
1161     int64_t*: audio_metadata_get_int64,                            \
1162     float*: audio_metadata_get_float,                              \
1163     double*: audio_metadata_get_double,                            \
1164     char**: audio_metadata_get_string,                             \
1165     audio_metadata_t**: audio_metadata_get_data,                   \
1166     default: audio_metadata_get_unknown                            \
1167     )(metadata, key, value)
1168 
1169 #endif  // !__cplusplus
1170 
1171 /**
1172  * \brief Remove item from audio metadata.
1173  *
1174  * \param metadata         the audio metadata object.
1175  * \param key              the key of the item that is going to be removed.
1176  * \return -EINVAL if metadata or key is null. Otherwise, return the number of elements erased.
1177  */
1178 ssize_t audio_metadata_erase(audio_metadata_t *metadata, const char *key);
1179 
1180 /**
1181  * \brief Destroys the metadata object
1182  *
1183  * \param metadata         object returned by create, if NULL nothing happens.
1184  */
1185 void audio_metadata_destroy(audio_metadata_t *metadata);
1186 
1187 /**
1188  * \brief Unpack byte string into a given audio metadata
1189  *
1190  * \param byteString       a byte string that contains data to convert to audio metadata.
1191  * \param length           the length of the byte string
1192  * \return the audio metadata object that contains the converted data. Caller must call
1193  *         audio_metadata_destroy to free the memory.
1194  */
1195 audio_metadata_t *audio_metadata_from_byte_string(const uint8_t *byteString, size_t length);
1196 
1197 /**
1198  * \brief Pack the audio metadata into a byte string
1199  *
1200  * \param metadata         the audio metadata object to be converted.
1201  * \param byteString       the buffer to write data to. The memory will be allocated
1202  *                         in the function, which must be freed by caller via free().
1203  * \return -EINVAL if metadata or byteString is null.
1204  *         -ENOMEM if fails to allocate memory for byte string.
1205  *         The length of the byte string.
1206  */
1207 ssize_t byte_string_from_audio_metadata(audio_metadata_t *metadata, uint8_t **byteString);
1208 
1209 /**
1210  * \brief Return the size in bytes of the metadata byte string
1211  *
1212  * Note: strlen() cannot be used as there are embedded 0's in the byte string.
1213  *
1214  * \param byteString       a valid byte string buffer from byte_string_from_audio_metadata().
1215  * \return size in bytes of metadata in the buffer or 0 if something went wrong.
1216  */
1217 size_t audio_metadata_byte_string_len(const uint8_t *byteString);
1218 
1219 /** \cond */
1220 __END_DECLS
1221 /** \endcond */
1222 
1223 #ifdef __cplusplus
1224 
1225 inline
1226 int audio_metadata_put(audio_metadata_t *metadata, const char *key, int32_t value)
1227 {
1228     return audio_metadata_put_int32(metadata, key, value);
1229 }
1230 
1231 inline
1232 int audio_metadata_put(audio_metadata_t *metadata, const char *key, int64_t value)
1233 {
1234     return audio_metadata_put_int64(metadata, key, value);
1235 }
1236 
1237 inline
1238 int audio_metadata_put(audio_metadata_t *metadata, const char *key, float value)
1239 {
1240     return audio_metadata_put_float(metadata, key, value);
1241 }
1242 
1243 inline
1244 int audio_metadata_put(audio_metadata_t *metadata, const char *key, double value)
1245 {
1246     return audio_metadata_put_double(metadata, key, value);
1247 }
1248 
1249 inline
1250 int audio_metadata_put(audio_metadata_t *metadata, const char *key, const char *value)
1251 {
1252     return audio_metadata_put_string(metadata, key, value);
1253 }
1254 
1255 inline
1256 int audio_metadata_put(audio_metadata_t *metadata, const char *key, audio_metadata_t *value)
1257 {
1258     return audio_metadata_put_data(metadata, key, value);
1259 }
1260 
1261 // No overload for default type
1262 
1263 inline
1264 int audio_metadata_get(audio_metadata_t *metadata, const char *key, int32_t *value)
1265 {
1266     return audio_metadata_get_int32(metadata, key, value);
1267 }
1268 
1269 inline
1270 int audio_metadata_get(audio_metadata_t *metadata, const char *key, int64_t *value)
1271 {
1272     return audio_metadata_get_int64(metadata, key, value);
1273 }
1274 
1275 inline
1276 int audio_metadata_get(audio_metadata_t *metadata, const char *key, float *value)
1277 {
1278     return audio_metadata_get_float(metadata, key, value);
1279 }
1280 
1281 inline
1282 int audio_metadata_get(audio_metadata_t *metadata, const char *key, double *value)
1283 {
1284     return audio_metadata_get_double(metadata, key, value);
1285 }
1286 
1287 inline
1288 int audio_metadata_get(audio_metadata_t *metadata, const char *key, char **value)
1289 {
1290     return audio_metadata_get_string(metadata, key, value);
1291 }
1292 
1293 inline
1294 int audio_metadata_get(audio_metadata_t *metadata, const char *key, audio_metadata_t **value)
1295 {
1296     return audio_metadata_get_data(metadata, key, value);
1297 }
1298 
1299 // No overload for default type
1300 
1301 #endif  // __cplusplus
1302 
1303 #endif // !ANDROID_AUDIO_METADATA_H
1304