Roc Toolkit internal modules
Roc Toolkit: real-time audio streaming
array.h
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2015 Roc authors
3  *
4  * This Source Code Form is subject to the terms of the Mozilla Public
5  * License, v. 2.0. If a copy of the MPL was not distributed with this
6  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
7  */
8 
9 //! @file roc_core/array.h
10 //! @brief Dynamic array.
11 
12 #ifndef ROC_CORE_ARRAY_H_
13 #define ROC_CORE_ARRAY_H_
14 
15 #include "roc_core/iallocator.h"
16 #include "roc_core/log.h"
17 #include "roc_core/noncopyable.h"
18 #include "roc_core/panic.h"
19 #include "roc_core/stddefs.h"
20 
21 namespace roc {
22 namespace core {
23 
24 //! Dynamic array.
25 template <class T> class Array : public NonCopyable<> {
26 public:
27  //! Initialize empty array.
28  explicit Array(IAllocator& allocator)
29  : data_(NULL)
30  , size_(0)
31  , max_size_(0)
32  , allocator_(allocator) {
33  }
34 
35  ~Array() {
36  resize(0);
37 
38  if (data_) {
39  allocator_.deallocate(data_);
40  }
41  }
42 
43  //! Get maximum number of elements.
44  size_t max_size() const {
45  return max_size_;
46  }
47 
48  //! Get number of elements.
49  size_t size() const {
50  return size_;
51  }
52 
53  //! Get element at given position.
54  T& operator[](size_t index) {
55  if (index >= size_) {
56  roc_panic("array: subscript out of range: index=%lu size=%lu",
57  (unsigned long)index, (unsigned long)size_);
58  }
59  return data_[index];
60  }
61 
62  //! Get element at given position.
63  const T& operator[](size_t index) const {
64  if (index >= size_) {
65  roc_panic("array: subscript out of range: index=%lu size=%lu",
66  (unsigned long)index, (unsigned long)size_);
67  }
68  return data_[index];
69  }
70 
71  //! Get first element.
72  //! @pre
73  //! Array should be non-empty.
74  T& front() {
75  if (size_ == 0) {
76  roc_panic("array: attempting to call front() on empty array");
77  }
78  return data_[0];
79  }
80 
81  //! Get first element.
82  //! @pre
83  //! Array should be non-empty.
84  const T& front() const {
85  if (size_ == 0) {
86  roc_panic("array: attempting to call front() on empty array");
87  }
88  return data_[0];
89  }
90 
91  //! Get last element.
92  //! @pre
93  //! Array should be non-empty.
94  T& back() {
95  if (size_ == 0) {
96  roc_panic("array: attempting to call back() on empty array");
97  }
98  return data_[size_ - 1];
99  }
100 
101  //! Get last element.
102  //! @pre
103  //! Array should be non-empty.
104  const T& back() const {
105  if (size_ == 0) {
106  roc_panic("array: attempting to call back() on empty array");
107  }
108  return data_[size_ - 1];
109  }
110 
111  //! Append element to array.
112  //! @pre
113  //! Array size() should be less than max_size().
114  void push_back(const T& value) {
115  if (size_ >= max_size_) {
116  roc_panic("array: attempting to append element to full array: size=%lu",
117  (unsigned long)size_);
118  }
119  new (data_ + size_) T(value);
120  size_++;
121  }
122 
123  //! Set array size.
124  //! @remarks
125  //! Calls grow() to ensure that there is enough space in array.
126  //! @returns
127  //! false if the allocation failed
128  bool resize(size_t sz) {
129  // Move objects to a new memory region if necessary.
130  if (!grow(sz)) {
131  return false;
132  }
133 
134  // Construct objects if size increased.
135  for (size_t n = size_; n < sz; n++) {
136  new (data_ + n) T();
137  }
138 
139  // Destruct objects (in reverse order) if size decreased.
140  for (size_t n = size_; n > sz; n--) {
141  data_[n - 1].~T();
142  }
143 
144  size_ = sz;
145 
146  return true;
147  }
148 
149  //! Increase array maximum size.
150  //! @remarks
151  //! If @p max_sz is greater than the current maximum size, a larger memory
152  //! region is allocated and the array elements are copied there.
153  //! @returns
154  //! false if the allocation failed
155  bool grow(size_t max_sz) {
156  if (max_sz <= max_size_) {
157  return true;
158  }
159 
160  T* new_data = (T*)allocator_.allocate(max_sz * sizeof(T));
161  if (!new_data) {
162  roc_log(LogError, "array: can't allocate memory: old_size=%lu new_size=%lu",
163  (unsigned long)max_size_, (unsigned long)max_sz);
164  return false;
165  }
166 
167  // Copy objects.
168  for (size_t n = 0; n < size_; n++) {
169  new (new_data + n) T(data_[n]);
170  }
171 
172  // Destruct objects (in reverse order).
173  for (size_t n = size_; n > 0; n--) {
174  data_[n - 1].~T();
175  }
176 
177  if (data_) {
178  allocator_.deallocate(data_);
179  }
180 
181  data_ = new_data;
182  max_size_ = max_sz;
183 
184  return true;
185  }
186 
187 private:
188  T* data_;
189  size_t size_;
190  size_t max_size_;
191  IAllocator& allocator_;
192 };
193 
194 } // namespace core
195 } // namespace roc
196 
197 #endif // ROC_CORE_ARRAY_H_
Memory allocator interface.
Definition: iallocator.h:23
virtual void * allocate(size_t size)=0
Allocate memory.
size_t max_size() const
Get maximum number of elements.
Definition: array.h:44
const T & front() const
Get first element.
Definition: array.h:84
Root namespace.
Array(IAllocator &allocator)
Initialize empty array.
Definition: array.h:28
const T & back() const
Get last element.
Definition: array.h:104
void push_back(const T &value)
Append element to array.
Definition: array.h:114
const T & operator[](size_t index) const
Get element at given position.
Definition: array.h:63
Commonly used types and functions.
size_t size() const
Get number of elements.
Definition: array.h:49
T & back()
Get last element.
Definition: array.h:94
T & front()
Get first element.
Definition: array.h:74
#define roc_panic(...)
Print error message and terminate program gracefully.
Definition: panic.h:42
virtual void deallocate(void *)=0
Deallocate previously allocated memory.
Base class for non-copyable objects.
Definition: noncopyable.h:23
#define roc_log(...)
Print message to log.
Definition: log.h:25
bool grow(size_t max_sz)
Increase array maximum size.
Definition: array.h:155
Error message.
Definition: log.h:33
Dynamic array.
Definition: array.h:25
Panic function.
bool resize(size_t sz)
Set array size.
Definition: array.h:128
Non-copyable object.
Logging.
Memory allocator interface.
T & operator[](size_t index)
Get element at given position.
Definition: array.h:54