/* This file is part of Jellyfish.
Jellyfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Jellyfish is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Jellyfish. If not, see .
*/
#ifndef __JELLYFISH_CPP_ARRAY_HPP_
#define __JELLYFISH_CPP_ARRAY_HPP_
#include
#include
namespace jellyfish {
/// Fix length array of type T. An element is initialized with the init method.
/// new (this->data() + i) T(
template
class cpp_array {
protected:
std::pair data_;
std::pair init_;
size_t size_;
public:
cpp_array(size_t size) :
data_(std::get_temporary_buffer(size)),
init_(std::get_temporary_buffer(size)),
size_(size) {
if(data_.first == 0 || init_.first == 0) {
std::return_temporary_buffer(data_.first);
std::return_temporary_buffer(init_.first);
throw std::bad_alloc();
}
memset(init_.first, '\0', sizeof(bool) * size_);
}
~cpp_array() {
clear();
std::return_temporary_buffer(data_.first);
std::return_temporary_buffer(init_.first);
}
/// Initialize element i with 0 argument
void init(size_t i) {
release(i);
new (data_.first + i) T();
init_.first[i] = true;
}
/// Initialize element i with 1 argument
template
void init(size_t i, A1& a1) {
release(i);
new (data_.first + i) T(a1);
init_.first[i] = true;
}
template
void init(size_t i, A1* a1) {
release(i);
new (data_.first + i) T(a1);
init_.first[i] = true;
}
/// Initialize element i with 2 arguments
template
void init(size_t i, A1& a1, A2& a2) {
release(i);
new (data_.first + i) T(a1, a2);
init_.first[i] = true;
}
template
void init(size_t i, A1* a1, A2& a2) {
release(i);
new (data_.first + i) T(a1, a2);
init_.first[i] = true;
}
template
void init(size_t i, A1& a1, A2* a2) {
release(i);
new (data_.first + i) T(a1, a2);
init_.first[i] = true;
}
template
void init(size_t i, A1* a1, A2* a2) {
release(i);
new (data_.first + i) T(a1, a2);
init_.first[i] = true;
}
/// Initialize element i with 3 arguments
template
void init(size_t i, A1 a1, A2 a2, A3 a3) {
release(i);
new (data_.first + i) T(a1, a2, a3);
init_.first[i] = true;
}
/// Initialize element i with 4 arguments
template
void init(size_t i, A1 a1, A2 a2, A3 a3, A4 a4) {
release(i);
new (data_.first + i) T(a1, a2, a3, a4);
init_.first[i] = true;
}
/// Initialize element i with 5 arguments
template
void init(size_t i, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5) {
release(i);
new (data_.first + i) T(a1, a2, a3, a4, a5);
init_.first[i] = true;
}
void release(size_t i) {
if(init_.first[i]) {
data_.first[i].~T();
init_.first[i] = false;
}
}
size_t size() const { return size_; }
bool empty() const { return size_ == 0; }
T& operator[](size_t i) { return data_.first[i]; }
const T& operator[](size_t i) const { return data_.first[i]; }
bool initialized(size_t i) const { return init_.first[i]; }
T* begin() { return data_.first; }
T* end() { return data_.first + size_; }
const T* begin() const { return data_.first; }
const T* end() const { return data_.end + size_; }
const T* cbegin() const { return data_.first; }
const T* cend() const { return data_.end + size_; }
T* data() { return data_.first; }
const T* data() const { return data_.first; }
T& front() { return data_.first[0]; }
T& back() { return data_.first[size_ - 1]; }
const T& front() const { return data_.first[0]; }
const T& back() const { return data_.first[size_ - 1]; }
void clear() {
for(size_t i = 0; i < size_; ++i)
release(i);
}
};
} // namespace jellyfish
#endif /* __JELLYFISH_CPP_ARRAY_HPP_ */