More Doc (Murdoch ?) for TSTL

This commit is contained in:
Baptiste Wicht 2016-09-27 23:39:18 +02:00
parent c9bb3ca9d7
commit 4d586bf1f8
No known key found for this signature in database
GPG Key ID: C5566B6C7F884532
6 changed files with 268 additions and 69 deletions

View File

@ -12,16 +12,37 @@
namespace std { namespace std {
/*!
* \brief Helper to handle a value as a bit field.
* \param S The type of the source value
* \param T The type of the bit value
* \param Position The starting position from the right (LSB)
* \param Size The number of bits
*/
template<typename S, typename T, size_t Position, size_t Size> template<typename S, typename T, size_t Position, size_t Size>
struct bit_field { struct bit_field {
S* value; /*!
* \brief Construct a bit field around the given value
*/
bit_field(S* value) : value(value) {} bit_field(S* value) : value(value) {}
T operator*() const { /*!
* \brief Extract the value of the bit field
*/
T get() const {
return (*value >> Position) & ((1ULL << Size) - 1); return (*value >> Position) & ((1ULL << Size) - 1);
} }
/*!
* \brief Extract the value of the bit field
*/
T operator*() const {
return get();
}
/*!
* \brief Assign a new value to the bit field
*/
bit_field& operator=(T new_value_real){ bit_field& operator=(T new_value_real){
S new_value(new_value_real); S new_value(new_value_real);
@ -29,6 +50,9 @@ struct bit_field {
*value = (*value & ~mask) | ((new_value << Position) & mask); *value = (*value & ~mask) | ((new_value << Position) & mask);
return *this; return *this;
} }
private:
S* value; ///< Pointer to the source value
}; };
} //end of namespace std } //end of namespace std

View File

@ -13,35 +13,55 @@
namespace std { namespace std {
/*!
* \brief Container adapter to provide a queue (FIFO)
*/
template<typename T, typename C = std::list<T>> template<typename T, typename C = std::list<T>>
struct queue { struct queue {
private: /*!
C container; * \brief Indicates if the queue is empty
*/
public:
bool empty() const { bool empty() const {
return size() == 0; return size() == 0;
} }
/*!
* \brief Returns the size of the queue
*/
size_t size() const { size_t size() const {
return container.size(); return container.size();
} }
/*!
* \brief Push a new element onto the queue
*/
void push(const T& value){ void push(const T& value){
container.push_back(value); container.push_back(value);
} }
/*!
* \brief Pop the top element from the queue
*/
void pop(){ void pop(){
container.pop_front(); container.pop_front();
} }
/*!
* \brief Returns a reference to the top element
*/
T& top(){ T& top(){
return container.front(); return container.front();
} }
/*!
* \brief Returns a const reference to the top element
*/
const T& top() const { const T& top() const {
return container.front(); return container.front();
} }
private:
C container; ///< The underlying container
}; };
} //end of namespace std } //end of namespace std

View File

@ -14,7 +14,7 @@
namespace std { namespace std {
/*! /*!
* \brief Container adapter to provide a stack * \brief Container adapter to provide a stack (LIFO)
*/ */
template<typename T, typename C = std::vector<T>> template<typename T, typename C = std::vector<T>>
struct stack { struct stack {

View File

@ -87,11 +87,15 @@ static_assert(min_capacity == sizeof(base_short<char>), "base_short must be the
static_assert(min_capacity == sizeof(base_long<char>), "base_long must be the correct SSO size"); static_assert(min_capacity == sizeof(base_long<char>), "base_long must be the correct SSO size");
static_assert(min_capacity == sizeof(base_raw), "base_raw must be the correct SSO size"); static_assert(min_capacity == sizeof(base_raw), "base_raw must be the correct SSO size");
/*!
* \brief A string of the given character type.
*
* This implementation uses SSO to not allocate any dynamic memory on short strings (<16 chars)
*/
template<typename CharT> template<typename CharT>
struct basic_string { struct basic_string {
public: using iterator = CharT*; ///< The iterator type
typedef CharT* iterator; using const_iterator = const CharT*; ///< The const iterator type
typedef const CharT* const_iterator;
static constexpr const size_t npos = -1; static constexpr const size_t npos = -1;
@ -137,12 +141,18 @@ private:
public: public:
//Constructors //Constructors
/*!
* \brief Construct an empty string
*/
basic_string() : _size(0){ basic_string() : _size(0){
set_small(true); set_small(true);
(*this)[0] = '\0'; (*this)[0] = '\0';
} }
/*!
* \brief Construct a new string from the given raw string
*/
basic_string(const CharT* s) : _size(str_len(s)) { basic_string(const CharT* s) : _size(str_len(s)) {
auto capacity = size() + 1; auto capacity = size() + 1;
@ -155,6 +165,9 @@ public:
std::copy_n(s, capacity, begin()); std::copy_n(s, capacity, begin());
} }
/*!
* \brief Construct a new string of the given capacity.
*/
explicit basic_string(size_t __capacity) : _size(0) { explicit basic_string(size_t __capacity) : _size(0) {
set_small(__capacity <= 16); set_small(__capacity <= 16);
@ -165,6 +178,9 @@ public:
(*this)[0] = '\0'; (*this)[0] = '\0';
} }
/*!
* \brief Construct a new string from the given range of characters
*/
template <typename It> template <typename It>
basic_string(It it, It end) { basic_string(It it, It end) {
_size = std::distance(it, end); _size = std::distance(it, end);
@ -262,6 +278,9 @@ public:
//Destructors //Destructors
/*!
* \brief Destructs the string and releases all its associated memory
*/
~basic_string(){ ~basic_string(){
if(is_long()){ if(is_long()){
storage.big.~base_long(); storage.big.~base_long();
@ -274,20 +293,32 @@ public:
set_size(size); set_size(size);
} }
/*!
* \brief Clear the string
*/
void clear(){ void clear(){
set_size(0); set_size(0);
(*this)[0] = '\0'; (*this)[0] = '\0';
} }
/*!
* \brief Pop the last character of the string.
*/
void pop_back(){ void pop_back(){
set_size(size() - 1); set_size(size() - 1);
(*this)[size()] = '\0'; (*this)[size()] = '\0';
} }
/*!
* \brief Ensures a capacity of at least new_capacity
*/
void reserve(size_t new_capacity){ void reserve(size_t new_capacity){
ensure_capacity(new_capacity); ensure_capacity(new_capacity);
} }
/*!
* \brief Creates a string resulting of the concatenation of this string the given char
*/
basic_string operator+(CharT c) const { basic_string operator+(CharT c) const {
basic_string copy(*this); basic_string copy(*this);
@ -296,6 +327,9 @@ public:
return move(copy); return move(copy);
} }
/*!
* \brief Concatenates the given char to the current string
*/
basic_string& operator+=(CharT c){ basic_string& operator+=(CharT c){
ensure_capacity(size() + 2); ensure_capacity(size() + 2);
@ -307,29 +341,6 @@ public:
return *this; return *this;
} }
void ensure_capacity(size_t new_capacity){
if(new_capacity > 0 && (capacity() < new_capacity)){
auto new_cap = capacity() * 2;
if(new_cap < new_capacity){
new_cap = new_capacity;
}
auto new_data = new CharT[new_cap];
std::copy_n(begin(), size() + 1, new_data);
if(is_small()){
new (&storage.big) base_long<CharT>(new_cap, new_data);
set_small(false);
} else {
storage.big.data.reset(new_data);
storage.big.capacity = new_cap;
}
}
}
basic_string& operator+=(const char* rhs){ basic_string& operator+=(const char* rhs){
auto len = str_len(rhs); auto len = str_len(rhs);
@ -358,10 +369,16 @@ public:
//Accessors //Accessors
/*!
* \brief Returns the size of the string
*/
size_t size() const { size_t size() const {
return _size & ~(1UL << 63); return _size & ~(1UL << 63);
} }
/*!
* \brief Returns the capacity of the string
*/
size_t capacity() const { size_t capacity() const {
if(is_small()){ if(is_small()){
return 16; return 16;
@ -370,6 +387,9 @@ public:
} }
} }
/*
* \brief Indicates if the string is empty
*/
bool empty() const { bool empty() const {
return size() == 0; return size() == 0;
} }
@ -390,18 +410,30 @@ public:
} }
} }
/*!
* \return the raw string
*/
CharT* c_str(){ CharT* c_str(){
return data_ptr(); return data_ptr();
} }
/*!
* \return the raw string
*/
const CharT* c_str() const { const CharT* c_str() const {
return data_ptr(); return data_ptr();
} }
/*!
* \brief Returns a reference to the ith character
*/
CharT& operator[](size_t i){ CharT& operator[](size_t i){
return *(data_ptr() + i); return *(data_ptr() + i);
} }
/*!
* \brief Returns a const reference to the ith character
*/
const CharT& operator[](size_t i) const { const CharT& operator[](size_t i) const {
return *(data_ptr() + i); return *(data_ptr() + i);
} }
@ -456,21 +488,57 @@ public:
//Iterators //Iterators
/*!
* \brief Returns an iterator to the first character of the string
*/
iterator begin(){ iterator begin(){
return iterator(data_ptr()); return iterator(data_ptr());
} }
iterator end(){ /*!
return iterator(data_ptr() + size()); * \brief Returns a const iterator to the first character of the string
} */
const_iterator begin() const { const_iterator begin() const {
return const_iterator(data_ptr()); return const_iterator(data_ptr());
} }
/*!
* \brief Returns an iterator the past-the-end character of the string
*/
iterator end(){
return iterator(data_ptr() + size());
}
/*!
* \brief Returns a const iterator the past-the-end character of the string
*/
const_iterator end() const { const_iterator end() const {
return const_iterator(data_ptr() + size()); return const_iterator(data_ptr() + size());
} }
private:
void ensure_capacity(size_t new_capacity){
if(new_capacity > 0 && (capacity() < new_capacity)){
auto new_cap = capacity() * 2;
if(new_cap < new_capacity){
new_cap = new_capacity;
}
auto new_data = new CharT[new_cap];
std::copy_n(begin(), size() + 1, new_data);
if(is_small()){
new (&storage.big) base_long<CharT>(new_cap, new_data);
set_small(false);
} else {
storage.big.data.reset(new_data);
storage.big.capacity = new_cap;
}
}
}
}; };
template<typename C> template<typename C>

View File

@ -8,15 +8,15 @@
#ifndef TYPES_H #ifndef TYPES_H
#define TYPES_H #define TYPES_H
typedef unsigned int uint8_t __attribute__((__mode__(__QI__))); typedef unsigned int uint8_t __attribute__((__mode__(__QI__))); ///< An unsigned 8-bit number
typedef unsigned int uint16_t __attribute__ ((__mode__ (__HI__))); typedef unsigned int uint16_t __attribute__ ((__mode__ (__HI__))); ///< An unsigned 16-bit number
typedef unsigned int uint32_t __attribute__ ((__mode__ (__SI__))); typedef unsigned int uint32_t __attribute__ ((__mode__ (__SI__))); ///< An unsigned 32-bit number
typedef unsigned int uint64_t __attribute__ ((__mode__ (__DI__))); typedef unsigned int uint64_t __attribute__ ((__mode__ (__DI__))); ///< An unsigned 64-bit number
typedef int int8_t __attribute__((__mode__(__QI__))); typedef int int8_t __attribute__((__mode__(__QI__))); ///< A signed 8-bit number
typedef int int16_t __attribute__ ((__mode__ (__HI__))); typedef int int16_t __attribute__ ((__mode__ (__HI__))); ///< A signed 16-bit number
typedef int int32_t __attribute__ ((__mode__ (__SI__))); typedef int int32_t __attribute__ ((__mode__ (__SI__))); ///< A signed 32-bit number
typedef int int64_t __attribute__ ((__mode__ (__DI__))); typedef int int64_t __attribute__ ((__mode__ (__DI__))); ///< A signed 64-bit number
typedef uint64_t uintptr_t; typedef uint64_t uintptr_t;
typedef uint64_t size_t; typedef uint64_t size_t;

View File

@ -38,22 +38,30 @@ struct default_delete<T[]> {
} }
}; };
/*!
* \brief An unique ptr of type T.
*
* An unique ptr represents unique ownership of dynamically allocated data.
*/
template <typename T, typename D = default_delete<T>> template <typename T, typename D = default_delete<T>>
class unique_ptr { struct unique_ptr {
public: using pointer_type = T*; ///< The pointer type
using pointer_type = T*; using element_type = T; ///< The element type
using element_type = T; using deleter_type = D; ///< The deleter type
using deleter_type = D;
private: /*!
using data_impl = tuple<pointer_type, deleter_type>; * \brief Construct an empty (nullptr) unique_ptr
*/
data_impl _data;
public:
unique_ptr() : _data() {} unique_ptr() : _data() {}
/*!
* \brief Construct an empty (nullptr) unique_ptr
*/
unique_ptr(decltype(nullptr)) : unique_ptr() {} unique_ptr(decltype(nullptr)) : unique_ptr() {}
/*!
* \brief Construct a new unique_ptr from the given pointer
*/
explicit unique_ptr(pointer_type p) : _data(make_tuple(p, deleter_type())) {} explicit unique_ptr(pointer_type p) : _data(make_tuple(p, deleter_type())) {}
unique_ptr(unique_ptr&& u) : _data(make_tuple(u.unlock(), u.get_deleter())) {} unique_ptr(unique_ptr&& u) : _data(make_tuple(u.unlock(), u.get_deleter())) {}
@ -63,6 +71,9 @@ public:
return *this; return *this;
} }
/*!
* \brief Destructs the object and releases its memory if it still references any
*/
~unique_ptr(){ ~unique_ptr(){
reset(); reset();
} }
@ -71,6 +82,9 @@ public:
unique_ptr(const unique_ptr& rhs) = delete; unique_ptr(const unique_ptr& rhs) = delete;
unique_ptr& operator=(const unique_ptr& rhs) = delete; unique_ptr& operator=(const unique_ptr& rhs) = delete;
/*!
* \brief Assign nullptr to the unique ptr (reset it)
*/
unique_ptr& operator=(decltype(nullptr)){ unique_ptr& operator=(decltype(nullptr)){
reset(); reset();
return *this; return *this;
@ -78,36 +92,63 @@ public:
//Access //Access
/*!
* \brief Returns a reference to the owned object
*/
element_type& operator*() const { element_type& operator*() const {
return *get(); return *get();
} }
/*!
* \brief Returns a pointer to the owned object
*/
pointer_type operator->() const { pointer_type operator->() const {
return get(); return get();
} }
/*!
* \brief Returns a pointer to the owned object
*/
pointer_type get() const { pointer_type get() const {
return std::get<0>(_data); return std::get<0>(_data);
} }
/*!
* \brief Returns a reference to the deleter
*/
deleter_type& get_deleter(){ deleter_type& get_deleter(){
return std::get<1>(_data); return std::get<1>(_data);
} }
/*!
* \brief Returns a const reference to the deleter
*/
const deleter_type& get_deleter() const { const deleter_type& get_deleter() const {
return std::get<1>(_data); return std::get<1>(_data);
} }
/*!
* \brief Converts the unique ptr to a boolean, indicating if it points to something or not
*/
explicit operator bool() const { explicit operator bool() const {
return get() == pointer_type() ? false : true; return get() == pointer_type() ? false : true;
} }
/*!
* \brief Extract the owned object out of the unique ptr.
*
* After this, the unique ptr will not own the objet anymore.
*/
pointer_type unlock(){ pointer_type unlock(){
pointer_type p = get(); pointer_type p = get();
std::get<0>(_data) = pointer_type(); std::get<0>(_data) = pointer_type();
return p; return p;
} }
/*!
* \brief Resets the unique pointer to a new state
* \param p The new pointer value
*/
void reset(pointer_type p = pointer_type()){ void reset(pointer_type p = pointer_type()){
if(get() != pointer_type()){ if(get() != pointer_type()){
get_deleter()(get()); get_deleter()(get());
@ -117,23 +158,30 @@ public:
} }
}; };
//Partial specialization for array /*!
* \brief Unique pointer implementation for an array.
*
* This has the same semantics, but allow random accesss as an array.
*/
template <typename T, typename D> template <typename T, typename D>
class unique_ptr<T[], D> { struct unique_ptr<T[], D> {
public: using pointer_type = T*; ///< The pointer type
using pointer_type = T*; using element_type = T; ///< The element type
using element_type = T; using deleter_type = D; ///< The deleter type
using deleter_type = D;
private: /*!
using data_impl = tuple<pointer_type, deleter_type>; * \brief Construct an empty (nullptr) unique_ptr
*/
data_impl _data;
public:
unique_ptr() : _data() {} unique_ptr() : _data() {}
/*!
* \brief Construct an empty (nullptr) unique_ptr
*/
unique_ptr(decltype(nullptr)) : unique_ptr() {} unique_ptr(decltype(nullptr)) : unique_ptr() {}
/*!
* \brief Construct a new unique_ptr from the given pointer
*/
explicit unique_ptr(pointer_type p) : _data(make_tuple(p, deleter_type())) {} explicit unique_ptr(pointer_type p) : _data(make_tuple(p, deleter_type())) {}
unique_ptr(unique_ptr&& u) : _data(make_tuple(u.unlock(), u.get_deleter())) {} unique_ptr(unique_ptr&& u) : _data(make_tuple(u.unlock(), u.get_deleter())) {}
@ -143,6 +191,9 @@ public:
return *this; return *this;
} }
/*!
* \brief Destructs the object and releases its memory if it still references any
*/
~unique_ptr(){ ~unique_ptr(){
reset(); reset();
} }
@ -156,36 +207,64 @@ public:
return *this; return *this;
} }
/*!
* \brief Returns a pointer to the owned object
*/
pointer_type get() const { pointer_type get() const {
return std::get<0>(_data); return std::get<0>(_data);
} }
/*!
* \brief Returns a reference to the deleter
*/
deleter_type& get_deleter(){ deleter_type& get_deleter(){
return std::get<1>(_data); return std::get<1>(_data);
} }
/*!
* \brief Returns a const reference to the deleter
*/
const deleter_type& get_deleter() const { const deleter_type& get_deleter() const {
return std::get<1>(_data); return std::get<1>(_data);
} }
/*!
* \brief Returns a reference to an element of the array
* \param i The index inside the array
*/
element_type& operator[](size_t i) const { element_type& operator[](size_t i) const {
return get()[i]; return get()[i];
} }
/*!
* \brief Converts the unique ptr to a boolean, indicating if it points to something or not
*/
explicit operator bool() const { explicit operator bool() const {
return get() == pointer_type() ? false : true; return get() == pointer_type() ? false : true;
} }
/*!
* \brief Extract the owned object out of the unique ptr.
*
* After this, the unique ptr will not own the objet anymore.
*/
pointer_type unlock(){ pointer_type unlock(){
pointer_type p = get(); pointer_type p = get();
std::get<0>(_data) = pointer_type(); std::get<0>(_data) = pointer_type();
return p; return p;
} }
/*!
* \brief Resets the unique pointer to an empty state
*/
void reset(){ void reset(){
reset(pointer_type()); reset(pointer_type());
} }
/*!
* \brief Resets the unique pointer to a new state
* \param p The new pointer value
*/
void reset(pointer_type p){ void reset(pointer_type p){
auto tmp = get(); auto tmp = get();
std::get<0>(_data) = p; std::get<0>(_data) = p;
@ -193,11 +272,19 @@ public:
get_deleter()(tmp); get_deleter()(tmp);
} }
} }
private:
using data_impl = tuple<pointer_type, deleter_type>; ///< The type of internal data
data_impl _data; ///< The internal data storage
}; };
static_assert(sizeof(unique_ptr<long>) == sizeof(long), "unique_ptr must have zero overhead with default deleter"); static_assert(sizeof(unique_ptr<long>) == sizeof(long), "unique_ptr must have zero overhead with default deleter");
static_assert(sizeof(unique_ptr<long[]>) == sizeof(long), "unique_ptr must have zero overhead with default deleter"); static_assert(sizeof(unique_ptr<long[]>) == sizeof(long), "unique_ptr must have zero overhead with default deleter");
/*!
* \brief Helper to create an unique_ptr from the args
*/
template <typename T, typename... Args> template <typename T, typename... Args>
std::unique_ptr<T> make_unique(Args&&... args){ std::unique_ptr<T> make_unique(Args&&... args){
return std::unique_ptr<T>(new T(std::forward<Args>(args)...)); return std::unique_ptr<T>(new T(std::forward<Args>(args)...));