summaryrefslogtreecommitdiff
path: root/media/libcubeb/src/cubeb_utils.h
diff options
context:
space:
mode:
Diffstat (limited to 'media/libcubeb/src/cubeb_utils.h')
-rw-r--r--media/libcubeb/src/cubeb_utils.h226
1 files changed, 160 insertions, 66 deletions
diff --git a/media/libcubeb/src/cubeb_utils.h b/media/libcubeb/src/cubeb_utils.h
index d8e9928fe..fd7a3d740 100644
--- a/media/libcubeb/src/cubeb_utils.h
+++ b/media/libcubeb/src/cubeb_utils.h
@@ -8,97 +8,154 @@
#if !defined(CUBEB_UTILS)
#define CUBEB_UTILS
+#include "cubeb/cubeb.h"
+
+#ifdef __cplusplus
+
+#include <assert.h>
+#include <mutex>
#include <stdint.h>
#include <string.h>
-#include <assert.h>
#include <type_traits>
-#if defined(WIN32)
+#if defined(_WIN32)
#include "cubeb_utils_win.h"
#else
#include "cubeb_utils_unix.h"
#endif
/** Similar to memcpy, but accounts for the size of an element. */
-template<typename T>
-void PodCopy(T * destination, const T * source, size_t count)
+template <typename T>
+void
+PodCopy(T * destination, const T * source, size_t count)
{
static_assert(std::is_trivial<T>::value, "Requires trivial type");
+ assert(destination && source);
memcpy(destination, source, count * sizeof(T));
}
/** Similar to memmove, but accounts for the size of an element. */
-template<typename T>
-void PodMove(T * destination, const T * source, size_t count)
+template <typename T>
+void
+PodMove(T * destination, const T * source, size_t count)
{
static_assert(std::is_trivial<T>::value, "Requires trivial type");
+ assert(destination && source);
memmove(destination, source, count * sizeof(T));
}
/** Similar to a memset to zero, but accounts for the size of an element. */
-template<typename T>
-void PodZero(T * destination, size_t count)
+template <typename T>
+void
+PodZero(T * destination, size_t count)
{
static_assert(std::is_trivial<T>::value, "Requires trivial type");
- memset(destination, 0, count * sizeof(T));
+ assert(destination);
+ memset(destination, 0, count * sizeof(T));
+}
+
+namespace {
+template <typename T, typename Trait>
+void
+Copy(T * destination, const T * source, size_t count, Trait)
+{
+ for (size_t i = 0; i < count; i++) {
+ destination[i] = source[i];
+ }
+}
+
+template <typename T>
+void
+Copy(T * destination, const T * source, size_t count, std::true_type)
+{
+ PodCopy(destination, source, count);
+}
+} // namespace
+
+/**
+ * This allows copying a number of elements from a `source` pointer to a
+ * `destination` pointer, using `memcpy` if it is safe to do so, or a loop that
+ * calls the constructors and destructors otherwise.
+ */
+template <typename T>
+void
+Copy(T * destination, const T * source, size_t count)
+{
+ assert(destination && source);
+ Copy(destination, source, count, typename std::is_trivial<T>::type());
}
-template<typename T>
-class auto_array
+namespace {
+template <typename T, typename Trait>
+void
+ConstructDefault(T * destination, size_t count, Trait)
{
+ for (size_t i = 0; i < count; i++) {
+ destination[i] = T();
+ }
+}
+
+template <typename T>
+void
+ConstructDefault(T * destination, size_t count, std::true_type)
+{
+ PodZero(destination, count);
+}
+} // namespace
+
+/**
+ * This allows zeroing (using memset) or default-constructing a number of
+ * elements calling the constructors and destructors if necessary.
+ */
+template <typename T>
+void
+ConstructDefault(T * destination, size_t count)
+{
+ assert(destination);
+ ConstructDefault(destination, count, typename std::is_arithmetic<T>::type());
+}
+
+template <typename T> class auto_array {
public:
explicit auto_array(uint32_t capacity = 0)
- : data_(capacity ? new T[capacity] : nullptr)
- , capacity_(capacity)
- , length_(0)
- {}
-
- ~auto_array()
+ : data_(capacity ? new T[capacity] : nullptr), capacity_(capacity),
+ length_(0)
{
- delete [] data_;
}
+ ~auto_array() { delete[] data_; }
+
/** Get a constant pointer to the underlying data. */
- T * data() const
- {
- return data_;
- }
+ T * data() const { return data_; }
+
+ T * end() const { return data_ + length_; }
- const T& at(size_t index) const
+ const T & at(size_t index) const
{
assert(index < length_ && "out of range");
return data_[index];
}
- T& at(size_t index)
+ T & at(size_t index)
{
assert(index < length_ && "out of range");
return data_[index];
}
/** Get how much underlying storage this auto_array has. */
- size_t capacity() const
- {
- return capacity_;
- }
+ size_t capacity() const { return capacity_; }
/** Get how much elements this auto_array contains. */
- size_t length() const
- {
- return length_;
- }
+ size_t length() const { return length_; }
/** Keeps the storage, but removes all the elements from the array. */
- void clear()
- {
- length_ = 0;
- }
+ void clear() { length_ = 0; }
- /** Change the storage of this auto array, copying the elements to the new
- * storage.
- * @returns true in case of success
- * @returns false if the new capacity is not big enough to accomodate for the
- * elements in the array.
- */
+ /** Change the storage of this auto array, copying the elements to the new
+ * storage.
+ * @returns true in case of success
+ * @returns false if the new capacity is not big enough to accomodate for the
+ * elements in the array.
+ */
bool reserve(size_t new_capacity)
{
if (new_capacity < length_) {
@@ -109,17 +166,17 @@ public:
PodCopy(new_data, data_, length_);
}
capacity_ = new_capacity;
- delete [] data_;
+ delete[] data_;
data_ = new_data;
return true;
}
- /** Append `length` elements to the end of the array, resizing the array if
- * needed.
- * @parameter elements the elements to append to the array.
- * @parameter length the number of elements to append to the array.
- */
+ /** Append `length` elements to the end of the array, resizing the array if
+ * needed.
+ * @parameter elements the elements to append to the array.
+ * @parameter length the number of elements to append to the array.
+ */
void push(const T * elements, size_t length)
{
if (length_ + length > capacity_) {
@@ -157,17 +214,14 @@ public:
}
/** Return the number of free elements in the array. */
- size_t available() const
- {
- return capacity_ - length_;
- }
+ size_t available() const { return capacity_ - length_; }
/** Copies `length` elements to `elements` if it is not null, and shift
- * the remaining elements of the `auto_array` to the beginning.
- * @parameter elements a buffer to copy the elements to, or nullptr.
- * @parameter length the number of elements to copy.
- * @returns true in case of success.
- * @returns false if the auto_array contains less than `length` elements. */
+ * the remaining elements of the `auto_array` to the beginning.
+ * @parameter elements a buffer to copy the elements to, or nullptr.
+ * @parameter length the number of elements to copy.
+ * @returns true in case of success.
+ * @returns false if the auto_array contains less than `length` elements. */
bool pop(T * elements, size_t length)
{
if (length > length_) {
@@ -198,18 +252,58 @@ private:
size_t length_;
};
-struct auto_lock {
- explicit auto_lock(owned_critical_section & lock)
- : lock(lock)
- {
- lock.enter();
- }
- ~auto_lock()
+struct auto_array_wrapper {
+ virtual void push(void * elements, size_t length) = 0;
+ virtual size_t length() = 0;
+ virtual void push_silence(size_t length) = 0;
+ virtual bool pop(size_t length) = 0;
+ virtual void * data() = 0;
+ virtual void * end() = 0;
+ virtual void clear() = 0;
+ virtual bool reserve(size_t capacity) = 0;
+ virtual void set_length(size_t length) = 0;
+ virtual ~auto_array_wrapper() {}
+};
+
+template <typename T>
+struct auto_array_wrapper_impl : public auto_array_wrapper {
+ auto_array_wrapper_impl() {}
+
+ explicit auto_array_wrapper_impl(uint32_t size) : ar(size) {}
+
+ void push(void * elements, size_t length) override
{
- lock.leave();
+ ar.push(static_cast<T *>(elements), length);
}
+
+ size_t length() override { return ar.length(); }
+
+ void push_silence(size_t length) override { ar.push_silence(length); }
+
+ bool pop(size_t length) override { return ar.pop(nullptr, length); }
+
+ void * data() override { return ar.data(); }
+
+ void * end() override { return ar.end(); }
+
+ void clear() override { ar.clear(); }
+
+ bool reserve(size_t capacity) override { return ar.reserve(capacity); }
+
+ void set_length(size_t length) override { ar.set_length(length); }
+
+ ~auto_array_wrapper_impl() { ar.clear(); }
+
private:
- owned_critical_section & lock;
+ auto_array<T> ar;
};
+extern "C" {
+size_t
+cubeb_sample_size(cubeb_sample_format format);
+}
+
+using auto_lock = std::lock_guard<owned_critical_section>;
+#endif // __cplusplus
+
#endif /* CUBEB_UTILS */