/** Similar to memcpy, but accounts for the size of an element. */ 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)
{
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)
{
static_assert(std::is_trivial<T>::value, "Requires trivial type");
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];
}
}
/** * 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());
}
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();
}
}
/** * 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());
}
/** Get a constant pointer to the underlying data. */
T * data() const { return data_; }
T * end() const { return data_ + length_; }
const T & at(size_t index) const
{
assert(index < length_ && "out of range"); return data_[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_; }
/** Get how much elements this auto_array contains. */
size_t length() const { return length_; }
/** Keeps the storage, but removes all the elements from the array. */ 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.
*/ bool reserve(size_t new_capacity)
{ if (new_capacity < length_) { returnfalse;
}
T * new_data = new T[new_capacity]; if (data_ && length_) {
PodCopy(new_data, data_, length_);
}
capacity_ = new_capacity; delete[] data_;
data_ = new_data;
returntrue;
}
/** 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_) {
reserve(length_ + length);
} if (data_) {
PodCopy(data_ + length_, elements, length);
}
length_ += length;
}
/** Append `length` zero-ed elements to the end of the array, resizing the * array if needed. * @parameter length the number of elements to append to the array.
*/ void push_silence(size_t length)
{ if (length_ + length > capacity_) {
reserve(length + length_);
} if (data_) {
PodZero(data_ + length_, length);
}
length_ += length;
}
/** Prepend `length` zero-ed elements to the front of the array, resizing and * shifting the array if needed. * @parameter length the number of elements to prepend to the array.
*/ void push_front_silence(size_t length)
{ if (length_ + length > capacity_) {
reserve(length + length_);
} if (data_) {
PodMove(data_ + length, data_, length_);
PodZero(data_, length);
}
length_ += length;
}
/** Return the number of free elements in the array. */
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. */ bool pop(T * elements, size_t length)
{ if (length > length_) { returnfalse;
} if (!data_) { returntrue;
} if (elements) {
PodCopy(elements, data_, length);
}
PodMove(data_, data_ + length, length_ - length);
private: /** The underlying storage */
T * data_; /** The size, in number of elements, of the storage. */
size_t capacity_; /** The number of elements the array contains. */
size_t length_;
};
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.