Roc Toolkit internal modules
Roc Toolkit: real-time audio streaming
Loading...
Searching...
No Matches
slice.h
Go to the documentation of this file.
1/*
2 * Copyright (c) 2015 Roc Streaming 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/slice.h
10//! @brief Slice.
11
12#ifndef ROC_CORE_SLICE_H_
13#define ROC_CORE_SLICE_H_
14
15#include "roc_core/buffer.h"
17#include "roc_core/shared_ptr.h"
18
19namespace roc {
20namespace core {
21
22//! Slice.
23//!
24//! Slice points to a subrange of data in pool-allocated Buffer.
25//! Copying a slice produces a new slice referring the same data.
26//!
27//! Slice also acts as a kind of shared pointer to Buffer. A buffer won't be freed
28//! (returned to pool) until there are slices referring it. Copying a slice
29//! increments the buffer reference counter, and destroying a slice decrements it.
30//!
31//! While Buffer works with raw bytes, Slice<T> interprets it as array of elements
32//! of type T, and works in terms of those elements.
33//!
34//! Slice has two important characteristics:
35//! - size - the difference between the ending end beginning pointer
36//! - capacity - the difference between the actual buffer end and the
37//! slice beginning pointer
38//!
39//! Buffers are not resizable. They're allocated from pool and have fixed size,
40//! defined by the pool parameters.
41//!
42//! Slices are reslicable, which means that their pointers to the buffer data
43//! may be moved within the buffer.
44//!
45//! The beginning pointer may be moved only forward. Once moved, it's not allowed
46//! to move it backward again. Moving it decreases the slice size and capacity.
47//! Capacity is affected because it's relative to the beginning pointer.
48//!
49//! The ending pointer may be freely moved forward and backward within the slice
50//! capacity. Moving it affects the slice size, but not capacity.
51//!
52//! In other words, slice capacity may be only decreased by moving beginning pointer,
53//! and slice size may be freely changed within the slice capacity by moving both
54//! beginning and ending pointers.
55template <class T> class Slice {
56public:
57 //! Construct empty slice.
59 : buffer_()
60 , data_(NULL)
61 , size_(0) {
62 }
63
64 //! Construct slice pointing to the whole buffer.
65 Slice(const BufferPtr& buffer) {
66 buffer_ = buffer;
67 if (buffer_) {
68 data_ = (T*)buffer->data();
69 size_ = buffer->size() / sizeof(T);
70 } else {
71 data_ = NULL;
72 size_ = 0;
73 }
74 }
75
76 //! Construct slice pointing to a part of a buffer.
77 Slice(Buffer& buffer, size_t from, size_t to) {
78 if (from > to) {
79 roc_panic("slice: invalid range: [%lu,%lu)", (unsigned long)from,
80 (unsigned long)to);
81 }
82 if (to > buffer.size() / sizeof(T)) {
83 roc_panic("slice: out of bounds: available=[%lu,%lu) requested=[%lu,%lu)",
84 (unsigned long)0, (unsigned long)buffer.size() / sizeof(T),
85 (unsigned long)from, (unsigned long)to);
86 }
87 buffer_ = &buffer;
88 data_ = (T*)buffer.data() + from;
89 size_ = to - from;
90 }
91
92 //! Get slice data.
93 T* data() const {
94 if (data_ == NULL) {
95 roc_panic("slice: null slice");
96 }
97 return data_;
98 }
99
100 //! Pointer to the next after the last element in slice.
101 T* data_end() const {
102 if (data_ == NULL) {
103 roc_panic("slice: null slice");
104 }
105 return data_ + size_;
106 }
107
108 //! Get number of elements in slice.
109 size_t size() const {
110 return size_;
111 }
112
113 //! Get maximum possible number of elements in slice.
114 size_t capacity() const {
115 if (data_ == NULL) {
116 return 0;
117 } else {
118 return buffer_->size() / sizeof(T) - size_t(data_ - (T*)buffer_->data());
119 }
120 }
121
122 //! Change slice beginning and ending inside the buffer.
123 //! @remarks
124 //! - @p from and @p to are relative to slice beginning.
125 //! - @p to value can be up to capacity().
126 void reslice(size_t from, size_t to) {
127 const size_t cap = capacity();
128 if (from > to) {
129 roc_panic("slice: invalid range: [%lu,%lu)", (unsigned long)from,
130 (unsigned long)to);
131 }
132 if (to > cap) {
133 roc_panic("slice: out of bounds: available=[%lu,%lu) requested=[%lu,%lu)",
134 (unsigned long)0, (unsigned long)cap, (unsigned long)from,
135 (unsigned long)to);
136 }
137 if (data_) {
138 data_ = data_ + from;
139 size_ = to - from;
140 }
141 }
142
143 //! Increase size() by @p add_sz.
144 //! @returns
145 //! Pointer to the first element of extended range.
146 T* extend(const size_t add_sz) {
147 if (data_ == NULL) {
148 roc_panic("slice: null slice");
149 }
150 if (add_sz == 0) {
151 roc_panic("slice: extend with zero size");
152 }
153 T* ret = data_ + size_;
154 reslice(0, size() + add_sz);
155 return ret;
156 }
157
158 //! Construct a slice pointing to a part of this slice.
159 //! @remarks
160 //! - @p from and @p to are relative to slice beginning.
161 //! - @p to value can be up to size().
162 Slice subslice(size_t from, size_t to) const {
163 if (from > to) {
164 roc_panic("slice: invalid range: [%lu,%lu)", (unsigned long)from,
165 (unsigned long)to);
166 }
167 if (to > size_) {
168 roc_panic("slice: out of bounds: available=[%lu,%lu) requested=[%lu,%lu)",
169 (unsigned long)0, (unsigned long)size_, (unsigned long)from,
170 (unsigned long)to);
171 }
172 Slice ret;
173 ret.buffer_ = buffer_;
174 ret.data_ = data_ + from;
175 ret.size_ = to - from;
176 return ret;
177 }
178
179 //! Print slice to stderr.
180 void print() const {
181 if (buffer_) {
182 core::print_memory_slice(data_, size_, (T*)buffer_->data(),
183 buffer_->size() / sizeof(T));
184 } else {
185 core::print_memory_slice(data_, size_, NULL, 0);
186 }
187 }
188
189 //! Access to an element of the Slice with an array style.
190 T& operator[](const size_t i) const {
191 if (data_ == NULL) {
192 roc_panic("slice: null slice");
193 }
194 if (i > size_) {
195 roc_panic("slice: out of bounds: available=[%lu,%lu) requested=%lu",
196 (unsigned long)0, (unsigned long)size_, (unsigned long)i);
197 }
198 return data_[i];
199 }
200
201 //! Convert to bool.
202 //! @returns
203 //! true if the slice is attached to buffer, even if it has zero length.
204 operator const struct unspecified_bool *() const {
205 return (const unspecified_bool*)data_;
206 }
207
208private:
209 BufferPtr buffer_;
210 T* data_;
211 size_t size_;
212};
213
214} // namespace core
215} // namespace roc
216
217#endif // ROC_CORE_SLICE_H_
Buffer.
Fixed-size dynamically-allocated byte buffer.
Definition buffer.h:40
size_t size() const
Get buffer size in bytes.
Definition buffer.h:46
uint8_t * data()
Get buffer data.
Definition buffer.h:51
Shared ownership intrusive pointer.
Definition shared_ptr.h:32
Slice subslice(size_t from, size_t to) const
Construct a slice pointing to a part of this slice.
Definition slice.h:162
T * extend(const size_t add_sz)
Increase size() by add_sz.
Definition slice.h:146
size_t capacity() const
Get maximum possible number of elements in slice.
Definition slice.h:114
Slice(Buffer &buffer, size_t from, size_t to)
Construct slice pointing to a part of a buffer.
Definition slice.h:77
T * data_end() const
Pointer to the next after the last element in slice.
Definition slice.h:101
T & operator[](const size_t i) const
Access to an element of the Slice with an array style.
Definition slice.h:190
void reslice(size_t from, size_t to)
Change slice beginning and ending inside the buffer.
Definition slice.h:126
void print() const
Print slice to stderr.
Definition slice.h:180
Slice(const BufferPtr &buffer)
Construct slice pointing to the whole buffer.
Definition slice.h:65
T * data() const
Get slice data.
Definition slice.h:93
Slice()
Construct empty slice.
Definition slice.h:58
size_t size() const
Get number of elements in slice.
Definition slice.h:109
void print_memory_slice(const uint8_t *inner, size_t inner_size, const uint8_t *outer, size_t outer_size)
Print memory slice.
Root namespace.
#define roc_panic(...)
Print error message and terminate program gracefully.
Definition panic.h:50
Print memory to console.
Shared ownership intrusive pointer.