You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
130 lines
3.1 KiB
130 lines
3.1 KiB
#ifndef ANDROID_RENDERSCRIPT_LIST_H |
|
#define ANDROID_RENDERSCRIPT_LIST_H |
|
|
|
namespace android { |
|
namespace renderscript { |
|
|
|
namespace { |
|
|
|
constexpr size_t BUFFER_SIZE = 64; |
|
|
|
} // anonymous namespace |
|
|
|
template <class T> |
|
class List { |
|
private: |
|
class LinkedBuffer { |
|
public: |
|
LinkedBuffer() : next(nullptr) {} |
|
|
|
union { |
|
char raw[BUFFER_SIZE - sizeof(LinkedBuffer*)]; |
|
T typed; |
|
} data; |
|
LinkedBuffer* next; |
|
}; |
|
|
|
public: |
|
class iterator; |
|
|
|
List() : last(nullptr), first(&firstBuffer.data.typed), |
|
beginIterator(this, &firstBuffer, const_cast<T*>(first)), |
|
_size(0) { |
|
current = const_cast<T*>(first); |
|
currentBuffer = &firstBuffer; |
|
} |
|
|
|
template <class InputIterator> |
|
List(InputIterator first, InputIterator last) : List() { |
|
for (InputIterator it = first; it != last; ++it) { |
|
push_back(*it); |
|
} |
|
} |
|
|
|
~List() { |
|
LinkedBuffer* p = firstBuffer.next; |
|
LinkedBuffer* next; |
|
while (p != nullptr) { |
|
next = p->next; |
|
delete p; |
|
p = next; |
|
} |
|
} |
|
|
|
void push_back(const T& value) { |
|
last = current; |
|
*current++ = value; |
|
_size++; |
|
if ((void*)current >= (void*)¤tBuffer->next) { |
|
LinkedBuffer* newBuffer = new LinkedBuffer(); |
|
currentBuffer->next = newBuffer; |
|
currentBuffer = newBuffer; |
|
current = ¤tBuffer->data.typed; |
|
} |
|
} |
|
|
|
class iterator { |
|
friend class List; |
|
public: |
|
iterator& operator++() { |
|
p++; |
|
if ((void*)p >= (void*)&buffer->next) { |
|
buffer = buffer->next; |
|
if (buffer != nullptr) { |
|
p = &buffer->data.typed; |
|
} else { |
|
p = nullptr; |
|
} |
|
} |
|
return *this; |
|
} |
|
|
|
bool operator==(const iterator& other) const { |
|
return p == other.p && buffer == other.buffer && list == other.list; |
|
} |
|
|
|
bool operator!=(const iterator& other) const { |
|
return p != other.p || buffer != other.buffer || list != other.list; |
|
} |
|
|
|
const T& operator*() const { return *p; } |
|
|
|
T* operator->() { return p; } |
|
|
|
protected: |
|
explicit iterator(const List* list_) : list(list_) {} |
|
iterator(const List* list_, LinkedBuffer* buffer_, T* p_) : |
|
p(p_), buffer(buffer_), list(list_) {} |
|
|
|
private: |
|
T* p; |
|
LinkedBuffer* buffer; |
|
const List* list; |
|
}; |
|
|
|
const iterator& begin() const { return beginIterator; } |
|
|
|
iterator end() const { return iterator(this, currentBuffer, current); } |
|
|
|
bool empty() const { return current == first; } |
|
|
|
T& front() const { return *const_cast<T*>(first); } |
|
|
|
T& back() const { return *last; } |
|
|
|
size_t size() const { return _size; } |
|
|
|
private: |
|
T* current; |
|
T* last; |
|
LinkedBuffer* currentBuffer; |
|
LinkedBuffer firstBuffer; |
|
const T* first; |
|
const iterator beginIterator; |
|
size_t _size; |
|
}; |
|
|
|
} // namespace renderscript |
|
} // namespace android |
|
|
|
#endif // ANDROID_RENDERSCRIPT_LIST_H
|
|
|