LCOV - code coverage report
Current view: top level - media/libcubeb/src - cubeb_utils.h (source / functions) Hit Total Coverage
Test: output.info Lines: 0 78 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 33 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * Copyright © 2016 Mozilla Foundation
       3             :  *
       4             :  * This program is made available under an ISC-style license.  See the
       5             :  * accompanying file LICENSE for details.
       6             :  */
       7             : 
       8             : #if !defined(CUBEB_UTILS)
       9             : #define CUBEB_UTILS
      10             : 
      11             : #include "cubeb/cubeb.h"
      12             : 
      13             : #ifdef __cplusplus
      14             : 
      15             : #include <stdint.h>
      16             : #include <string.h>
      17             : #include <assert.h>
      18             : #include <mutex>
      19             : #include <type_traits>
      20             : #if defined(WIN32)
      21             : #include "cubeb_utils_win.h"
      22             : #else
      23             : #include "cubeb_utils_unix.h"
      24             : #endif
      25             : 
      26             : /** Similar to memcpy, but accounts for the size of an element. */
      27             : template<typename T>
      28           0 : void PodCopy(T * destination, const T * source, size_t count)
      29             : {
      30             :   static_assert(std::is_trivial<T>::value, "Requires trivial type");
      31           0 :   assert(destination && source);
      32           0 :   memcpy(destination, source, count * sizeof(T));
      33           0 : }
      34             : 
      35             : /** Similar to memmove, but accounts for the size of an element. */
      36             : template<typename T>
      37           0 : void PodMove(T * destination, const T * source, size_t count)
      38             : {
      39             :   static_assert(std::is_trivial<T>::value, "Requires trivial type");
      40           0 :   assert(destination && source);
      41           0 :   memmove(destination, source, count * sizeof(T));
      42           0 : }
      43             : 
      44             : /** Similar to a memset to zero, but accounts for the size of an element. */
      45             : template<typename T>
      46           0 : void PodZero(T * destination, size_t count)
      47             : {
      48             :   static_assert(std::is_trivial<T>::value, "Requires trivial type");
      49           0 :   assert(destination);
      50           0 :   memset(destination, 0,  count * sizeof(T));
      51           0 : }
      52             : 
      53             : namespace {
      54             : template<typename T, typename Trait>
      55           0 : void Copy(T * destination, const T * source, size_t count, Trait)
      56             : {
      57           0 :   for (size_t i = 0; i < count; i++) {
      58           0 :     destination[i] = source[i];
      59             :   }
      60           0 : }
      61             : 
      62             : template<typename T>
      63             : void Copy(T * destination, const T * source, size_t count, std::true_type)
      64             : {
      65             :   PodCopy(destination, source, count);
      66             : }
      67             : }
      68             : 
      69             : /**
      70             :  * This allows copying a number of elements from a `source` pointer to a
      71             :  * `destination` pointer, using `memcpy` if it is safe to do so, or a loop that
      72             :  * calls the constructors and destructors otherwise.
      73             :  */
      74             : template<typename T>
      75           0 : void Copy(T * destination, const T * source, size_t count)
      76             : {
      77           0 :   assert(destination && source);
      78           0 :   Copy(destination, source, count, typename std::is_trivial<T>::type());
      79           0 : }
      80             : 
      81             : namespace {
      82             : template<typename T, typename Trait>
      83           0 : void ConstructDefault(T * destination, size_t count, Trait)
      84             : {
      85           0 :   for (size_t i = 0; i < count; i++) {
      86           0 :     destination[i] = T();
      87             :   }
      88           0 : }
      89             : 
      90             : template<typename T>
      91             : void ConstructDefault(T * destination,
      92             :                       size_t count, std::true_type)
      93             : {
      94             :   PodZero(destination, count);
      95             : }
      96             : }
      97             : 
      98             : /**
      99             :  * This allows zeroing (using memset) or default-constructing a number of
     100             :  * elements calling the constructors and destructors if necessary.
     101             :  */
     102             : template<typename T>
     103           0 : void ConstructDefault(T * destination, size_t count)
     104             : {
     105           0 :   assert(destination);
     106           0 :   ConstructDefault(destination, count,
     107             :                    typename std::is_arithmetic<T>::type());
     108           0 : }
     109             : 
     110             : template<typename T>
     111             : class auto_array
     112             : {
     113             : public:
     114           0 :   explicit auto_array(uint32_t capacity = 0)
     115           0 :     : data_(capacity ? new T[capacity] : nullptr)
     116             :     , capacity_(capacity)
     117           0 :     , length_(0)
     118           0 :   {}
     119             : 
     120           0 :   ~auto_array()
     121             :   {
     122           0 :     delete [] data_;
     123           0 :   }
     124             : 
     125             :   /** Get a constant pointer to the underlying data. */
     126           0 :   T * data() const
     127             :   {
     128           0 :     return data_;
     129             :   }
     130             : 
     131             :   T * end() const
     132             :   {
     133             :     return data_ + length_;
     134             :   }
     135             : 
     136             :   const T& at(size_t index) const
     137             :   {
     138             :     assert(index < length_ && "out of range");
     139             :     return data_[index];
     140             :   }
     141             : 
     142             :   T& at(size_t index)
     143             :   {
     144             :     assert(index < length_ && "out of range");
     145             :     return data_[index];
     146             :   }
     147             : 
     148             :   /** Get how much underlying storage this auto_array has. */
     149           0 :   size_t capacity() const
     150             :   {
     151           0 :     return capacity_;
     152             :   }
     153             : 
     154             :   /** Get how much elements this auto_array contains. */
     155           0 :   size_t length() const
     156             :   {
     157           0 :     return length_;
     158             :   }
     159             : 
     160             :   /** Keeps the storage, but removes all the elements from the array. */
     161           0 :   void clear()
     162             :   {
     163           0 :     length_ = 0;
     164           0 :   }
     165             : 
     166             :    /** Change the storage of this auto array, copying the elements to the new
     167             :     * storage.
     168             :     * @returns true in case of success
     169             :     * @returns false if the new capacity is not big enough to accomodate for the
     170             :     *                elements in the array.
     171             :     */
     172           0 :   bool reserve(size_t new_capacity)
     173             :   {
     174           0 :     if (new_capacity < length_) {
     175           0 :       return false;
     176             :     }
     177           0 :     T * new_data = new T[new_capacity];
     178           0 :     if (data_ && length_) {
     179           0 :       PodCopy(new_data, data_, length_);
     180             :     }
     181           0 :     capacity_ = new_capacity;
     182           0 :     delete [] data_;
     183           0 :     data_ = new_data;
     184             : 
     185           0 :     return true;
     186             :   }
     187             : 
     188             :    /** Append `length` elements to the end of the array, resizing the array if
     189             :     * needed.
     190             :     * @parameter elements the elements to append to the array.
     191             :     * @parameter length the number of elements to append to the array.
     192             :     */
     193           0 :   void push(const T * elements, size_t length)
     194             :   {
     195           0 :     if (length_ + length > capacity_) {
     196           0 :       reserve(length_ + length);
     197             :     }
     198           0 :     PodCopy(data_ + length_, elements, length);
     199           0 :     length_ += length;
     200           0 :   }
     201             : 
     202             :   /** Append `length` zero-ed elements to the end of the array, resizing the
     203             :    * array if needed.
     204             :    * @parameter length the number of elements to append to the array.
     205             :    */
     206           0 :   void push_silence(size_t length)
     207             :   {
     208           0 :     if (length_ + length > capacity_) {
     209           0 :       reserve(length + length_);
     210             :     }
     211           0 :     PodZero(data_ + length_, length);
     212           0 :     length_ += length;
     213           0 :   }
     214             : 
     215             :   /** Prepend `length` zero-ed elements to the end of the array, resizing the
     216             :    * array if needed.
     217             :    * @parameter length the number of elements to prepend to the array.
     218             :    */
     219             :   void push_front_silence(size_t length)
     220             :   {
     221             :     if (length_ + length > capacity_) {
     222             :       reserve(length + length_);
     223             :     }
     224             :     PodMove(data_ + length, data_, length_);
     225             :     PodZero(data_, length);
     226             :     length_ += length;
     227             :   }
     228             : 
     229             :   /** Return the number of free elements in the array. */
     230             :   size_t available() const
     231             :   {
     232             :     return capacity_ - length_;
     233             :   }
     234             : 
     235             :   /** Copies `length` elements to `elements` if it is not null, and shift
     236             :     * the remaining elements of the `auto_array` to the beginning.
     237             :     * @parameter elements a buffer to copy the elements to, or nullptr.
     238             :     * @parameter length the number of elements to copy.
     239             :     * @returns true in case of success.
     240             :     * @returns false if the auto_array contains less than `length` elements. */
     241           0 :   bool pop(T * elements, size_t length)
     242             :   {
     243           0 :     if (length > length_) {
     244           0 :       return false;
     245             :     }
     246           0 :     if (elements) {
     247           0 :       PodCopy(elements, data_, length);
     248             :     }
     249           0 :     PodMove(data_, data_ + length, length_ - length);
     250             : 
     251           0 :     length_ -= length;
     252             : 
     253           0 :     return true;
     254             :   }
     255             : 
     256           0 :   void set_length(size_t length)
     257             :   {
     258           0 :     assert(length <= capacity_);
     259           0 :     length_ = length;
     260           0 :   }
     261             : 
     262             : private:
     263             :   /** The underlying storage */
     264             :   T * data_;
     265             :   /** The size, in number of elements, of the storage. */
     266             :   size_t capacity_;
     267             :   /** The number of elements the array contains. */
     268             :   size_t length_;
     269             : };
     270             : 
     271             : struct auto_array_wrapper {
     272             :   virtual void push(void * elements, size_t length) = 0;
     273             :   virtual size_t length() = 0;
     274             :   virtual void push_silence(size_t length) = 0;
     275             :   virtual bool pop(size_t length) = 0;
     276             :   virtual void * data() = 0;
     277             :   virtual void * end() = 0;
     278             :   virtual void clear() = 0;
     279             :   virtual bool reserve(size_t capacity) = 0;
     280             :   virtual void set_length(size_t length) = 0;
     281             :   virtual ~auto_array_wrapper() {}
     282             : };
     283             : 
     284             : template <typename T>
     285             : struct auto_array_wrapper_impl : public auto_array_wrapper {
     286             :   auto_array_wrapper_impl() {}
     287             : 
     288             :   explicit auto_array_wrapper_impl(uint32_t size)
     289             :     : ar(size)
     290             :   {}
     291             : 
     292             :   void push(void * elements, size_t length) override {
     293             :     ar.push(static_cast<T *>(elements), length);
     294             :   }
     295             : 
     296             :   size_t length() override {
     297             :     return ar.length();
     298             :   }
     299             : 
     300             :   void push_silence(size_t length) override {
     301             :     ar.push_silence(length);
     302             :   }
     303             : 
     304             :   bool pop(size_t length) override {
     305             :     return ar.pop(nullptr, length);
     306             :   }
     307             : 
     308             :   void * data() override {
     309             :     return ar.data();
     310             :   }
     311             : 
     312             :   void * end() override {
     313             :     return ar.end();
     314             :   }
     315             : 
     316             :   void clear() override {
     317             :     ar.clear();
     318             :   }
     319             : 
     320             :   bool reserve(size_t capacity) override {
     321             :     return ar.reserve(capacity);
     322             :   }
     323             : 
     324             :   void set_length(size_t length) override {
     325             :     ar.set_length(length);
     326             :   }
     327             : 
     328             :   ~auto_array_wrapper_impl() {
     329             :     ar.clear();
     330             :   }
     331             : 
     332             : private:
     333             :   auto_array<T> ar;
     334             : };
     335             : 
     336             : using auto_lock = std::lock_guard<owned_critical_section>;
     337             : #endif // __cplusplus
     338             : 
     339             : // C language helpers
     340             : 
     341             : #ifdef __cplusplus
     342             : extern "C" {
     343             : #endif
     344             : 
     345             : int cubeb_utils_default_device_collection_destroy(cubeb * context,
     346             :                                                   cubeb_device_collection * collection);
     347             : 
     348             : #ifdef __cplusplus
     349             : }
     350             : #endif
     351             : 
     352             : #endif /* CUBEB_UTILS */

Generated by: LCOV version 1.13