webrtc_m130/webrtc/base/array_view.h
minyue a6f495c7c2 Simplifying audio network adaptor by moving receiver frame length range to ctor.
It turns out that that audio network adaptor can always be created with knowledge of receiver frame length range. There is no need to keep some infrastructure that is used for runtime setting of receiver frame length ranges.

BUG=webrtc:6303

Review-Url: https://codereview.webrtc.org/2429503002
Cr-Commit-Position: refs/heads/master@{#14748}
2016-10-24 16:19:22 +00:00

147 lines
5.3 KiB
C++

/*
* Copyright 2015 The WebRTC Project Authors. All rights reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef WEBRTC_BASE_ARRAY_VIEW_H_
#define WEBRTC_BASE_ARRAY_VIEW_H_
#include "webrtc/base/checks.h"
#include "webrtc/base/type_traits.h"
namespace rtc {
// Many functions read from or write to arrays. The obvious way to do this is
// to use two arguments, a pointer to the first element and an element count:
//
// bool Contains17(const int* arr, size_t size) {
// for (size_t i = 0; i < size; ++i) {
// if (arr[i] == 17)
// return true;
// }
// return false;
// }
//
// This is flexible, since it doesn't matter how the array is stored (C array,
// std::vector, rtc::Buffer, ...), but it's error-prone because the caller has
// to correctly specify the array length:
//
// Contains17(arr, arraysize(arr)); // C array
// Contains17(&arr[0], arr.size()); // std::vector
// Contains17(arr, size); // pointer + size
// ...
//
// It's also kind of messy to have two separate arguments for what is
// conceptually a single thing.
//
// Enter rtc::ArrayView<T>. It contains a T pointer (to an array it doesn't
// own) and a count, and supports the basic things you'd expect, such as
// indexing and iteration. It allows us to write our function like this:
//
// bool Contains17(rtc::ArrayView<const int> arr) {
// for (auto e : arr) {
// if (e == 17)
// return true;
// }
// return false;
// }
//
// And even better, because a bunch of things will implicitly convert to
// ArrayView, we can call it like this:
//
// Contains17(arr); // C array
// Contains17(arr); // std::vector
// Contains17(rtc::ArrayView<int>(arr, size)); // pointer + size
// Contains17(nullptr); // nullptr -> empty ArrayView
// ...
//
// One important point is that ArrayView<T> and ArrayView<const T> are
// different types, which allow and don't allow mutation of the array elements,
// respectively. The implicit conversions work just like you'd hope, so that
// e.g. vector<int> will convert to either ArrayView<int> or ArrayView<const
// int>, but const vector<int> will convert only to ArrayView<const int>.
// (ArrayView itself can be the source type in such conversions, so
// ArrayView<int> will convert to ArrayView<const int>.)
//
// Note: ArrayView is tiny (just a pointer and a count) and trivially copyable,
// so it's probably cheaper to pass it by value than by const reference.
template <typename T>
class ArrayView final {
public:
using value_type = T;
using const_iterator = const T*;
// Construct an empty ArrayView.
ArrayView() : ArrayView(static_cast<T*>(nullptr), 0) {}
ArrayView(std::nullptr_t) : ArrayView() {}
// Construct an ArrayView for a (pointer,size) pair.
template <typename U>
ArrayView(U* data, size_t size)
: data_(size == 0 ? nullptr : data), size_(size) {
CheckInvariant();
}
// Construct an ArrayView for an array.
template <typename U, size_t N>
ArrayView(U (&array)[N]) : ArrayView(&array[0], N) {}
// Construct an ArrayView for any type U that has a size() method whose
// return value converts implicitly to size_t, and a data() method whose
// return value converts implicitly to T*. In particular, this means we allow
// conversion from ArrayView<T> to ArrayView<const T>, but not the other way
// around. Other allowed conversions include std::vector<T> to ArrayView<T>
// or ArrayView<const T>, const std::vector<T> to ArrayView<const T>, and
// rtc::Buffer to ArrayView<uint8_t> (with the same const behavior as
// std::vector).
template <
typename U,
typename std::enable_if<HasDataAndSize<U, T>::value>::type* = nullptr>
ArrayView(U& u) : ArrayView(u.data(), u.size()) {}
// Indexing, size, and iteration. These allow mutation even if the ArrayView
// is const, because the ArrayView doesn't own the array. (To prevent
// mutation, use ArrayView<const T>.)
size_t size() const { return size_; }
bool empty() const { return size_ == 0; }
T* data() const { return data_; }
T& operator[](size_t idx) const {
RTC_DCHECK_LT(idx, size_);
RTC_DCHECK(data_); // Follows from size_ > idx and the class invariant.
return data_[idx];
}
T* begin() const { return data_; }
T* end() const { return data_ + size_; }
const T* cbegin() const { return data_; }
const T* cend() const { return data_ + size_; }
// Comparing two ArrayViews compares their (pointer,size) pairs; it does
// *not* dereference the pointers.
friend bool operator==(const ArrayView& a, const ArrayView& b) {
return a.data_ == b.data_ && a.size_ == b.size_;
}
friend bool operator!=(const ArrayView& a, const ArrayView& b) {
return !(a == b);
}
private:
// Invariant: !data_ iff size_ == 0.
void CheckInvariant() const { RTC_DCHECK_EQ(!data_, size_ == 0); }
T* data_;
size_t size_;
};
template <typename T>
inline ArrayView<T> MakeArrayView(T* data, size_t size) {
return ArrayView<T>(data, size);
}
} // namespace rtc
#endif // WEBRTC_BASE_ARRAY_VIEW_H_