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 {
/*!
* \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>
struct bit_field {
S* value;
/*!
* \brief Construct a bit field around the given 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);
}
/*!
* \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){
S new_value(new_value_real);
@ -29,6 +50,9 @@ struct bit_field {
*value = (*value & ~mask) | ((new_value << Position) & mask);
return *this;
}
private:
S* value; ///< Pointer to the source value
};
} //end of namespace std

View File

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

View File

@ -14,7 +14,7 @@
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>>
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_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>
struct basic_string {
public:
typedef CharT* iterator;
typedef const CharT* const_iterator;
using iterator = CharT*; ///< The iterator type
using const_iterator = const CharT*; ///< The const iterator type
static constexpr const size_t npos = -1;
@ -137,12 +141,18 @@ private:
public:
//Constructors
/*!
* \brief Construct an empty string
*/
basic_string() : _size(0){
set_small(true);
(*this)[0] = '\0';
}
/*!
* \brief Construct a new string from the given raw string
*/
basic_string(const CharT* s) : _size(str_len(s)) {
auto capacity = size() + 1;
@ -155,6 +165,9 @@ public:
std::copy_n(s, capacity, begin());
}
/*!
* \brief Construct a new string of the given capacity.
*/
explicit basic_string(size_t __capacity) : _size(0) {
set_small(__capacity <= 16);
@ -165,6 +178,9 @@ public:
(*this)[0] = '\0';
}
/*!
* \brief Construct a new string from the given range of characters
*/
template <typename It>
basic_string(It it, It end) {
_size = std::distance(it, end);
@ -262,6 +278,9 @@ public:
//Destructors
/*!
* \brief Destructs the string and releases all its associated memory
*/
~basic_string(){
if(is_long()){
storage.big.~base_long();
@ -274,20 +293,32 @@ public:
set_size(size);
}
/*!
* \brief Clear the string
*/
void clear(){
set_size(0);
(*this)[0] = '\0';
}
/*!
* \brief Pop the last character of the string.
*/
void pop_back(){
set_size(size() - 1);
(*this)[size()] = '\0';
}
/*!
* \brief Ensures a capacity of at least new_capacity
*/
void reserve(size_t 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 copy(*this);
@ -296,6 +327,9 @@ public:
return move(copy);
}
/*!
* \brief Concatenates the given char to the current string
*/
basic_string& operator+=(CharT c){
ensure_capacity(size() + 2);
@ -307,29 +341,6 @@ public:
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){
auto len = str_len(rhs);
@ -358,10 +369,16 @@ public:
//Accessors
/*!
* \brief Returns the size of the string
*/
size_t size() const {
return _size & ~(1UL << 63);
}
/*!
* \brief Returns the capacity of the string
*/
size_t capacity() const {
if(is_small()){
return 16;
@ -370,6 +387,9 @@ public:
}
}
/*
* \brief Indicates if the string is empty
*/
bool empty() const {
return size() == 0;
}
@ -390,18 +410,30 @@ public:
}
}
/*!
* \return the raw string
*/
CharT* c_str(){
return data_ptr();
}
/*!
* \return the raw string
*/
const CharT* c_str() const {
return data_ptr();
}
/*!
* \brief Returns a reference to the ith character
*/
CharT& operator[](size_t i){
return *(data_ptr() + i);
}
/*!
* \brief Returns a const reference to the ith character
*/
const CharT& operator[](size_t i) const {
return *(data_ptr() + i);
}
@ -456,21 +488,57 @@ public:
//Iterators
/*!
* \brief Returns an iterator to the first character of the string
*/
iterator begin(){
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 {
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 {
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>

View File

@ -8,15 +8,15 @@
#ifndef TYPES_H
#define TYPES_H
typedef unsigned int uint8_t __attribute__((__mode__(__QI__)));
typedef unsigned int uint16_t __attribute__ ((__mode__ (__HI__)));
typedef unsigned int uint32_t __attribute__ ((__mode__ (__SI__)));
typedef unsigned int uint64_t __attribute__ ((__mode__ (__DI__)));
typedef unsigned int uint8_t __attribute__((__mode__(__QI__))); ///< An unsigned 8-bit number
typedef unsigned int uint16_t __attribute__ ((__mode__ (__HI__))); ///< An unsigned 16-bit number
typedef unsigned int uint32_t __attribute__ ((__mode__ (__SI__))); ///< An unsigned 32-bit number
typedef unsigned int uint64_t __attribute__ ((__mode__ (__DI__))); ///< An unsigned 64-bit number
typedef int int8_t __attribute__((__mode__(__QI__)));
typedef int int16_t __attribute__ ((__mode__ (__HI__)));
typedef int int32_t __attribute__ ((__mode__ (__SI__)));
typedef int int64_t __attribute__ ((__mode__ (__DI__)));
typedef int int8_t __attribute__((__mode__(__QI__))); ///< A signed 8-bit number
typedef int int16_t __attribute__ ((__mode__ (__HI__))); ///< A signed 16-bit number
typedef int int32_t __attribute__ ((__mode__ (__SI__))); ///< A signed 32-bit number
typedef int int64_t __attribute__ ((__mode__ (__DI__))); ///< A signed 64-bit number
typedef uint64_t uintptr_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>>
class unique_ptr {
public:
using pointer_type = T*;
using element_type = T;
using deleter_type = D;
struct unique_ptr {
using pointer_type = T*; ///< The pointer type
using element_type = T; ///< The element type
using deleter_type = D; ///< The deleter type
private:
using data_impl = tuple<pointer_type, deleter_type>;
data_impl _data;
public:
/*!
* \brief Construct an empty (nullptr) unique_ptr
*/
unique_ptr() : _data() {}
/*!
* \brief Construct an empty (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())) {}
unique_ptr(unique_ptr&& u) : _data(make_tuple(u.unlock(), u.get_deleter())) {}
@ -63,6 +71,9 @@ public:
return *this;
}
/*!
* \brief Destructs the object and releases its memory if it still references any
*/
~unique_ptr(){
reset();
}
@ -71,6 +82,9 @@ public:
unique_ptr(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)){
reset();
return *this;
@ -78,36 +92,63 @@ public:
//Access
/*!
* \brief Returns a reference to the owned object
*/
element_type& operator*() const {
return *get();
}
/*!
* \brief Returns a pointer to the owned object
*/
pointer_type operator->() const {
return get();
}
/*!
* \brief Returns a pointer to the owned object
*/
pointer_type get() const {
return std::get<0>(_data);
}
/*!
* \brief Returns a reference to the deleter
*/
deleter_type& get_deleter(){
return std::get<1>(_data);
}
/*!
* \brief Returns a const reference to the deleter
*/
const deleter_type& get_deleter() const {
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 {
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 p = get();
std::get<0>(_data) = pointer_type();
return p;
}
/*!
* \brief Resets the unique pointer to a new state
* \param p The new pointer value
*/
void reset(pointer_type p = pointer_type()){
if(get() != pointer_type()){
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>
class unique_ptr<T[], D> {
public:
using pointer_type = T*;
using element_type = T;
using deleter_type = D;
struct unique_ptr<T[], D> {
using pointer_type = T*; ///< The pointer type
using element_type = T; ///< The element type
using deleter_type = D; ///< The deleter type
private:
using data_impl = tuple<pointer_type, deleter_type>;
data_impl _data;
public:
/*!
* \brief Construct an empty (nullptr) unique_ptr
*/
unique_ptr() : _data() {}
/*!
* \brief Construct an empty (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())) {}
unique_ptr(unique_ptr&& u) : _data(make_tuple(u.unlock(), u.get_deleter())) {}
@ -143,6 +191,9 @@ public:
return *this;
}
/*!
* \brief Destructs the object and releases its memory if it still references any
*/
~unique_ptr(){
reset();
}
@ -156,36 +207,64 @@ public:
return *this;
}
/*!
* \brief Returns a pointer to the owned object
*/
pointer_type get() const {
return std::get<0>(_data);
}
/*!
* \brief Returns a reference to the deleter
*/
deleter_type& get_deleter(){
return std::get<1>(_data);
}
/*!
* \brief Returns a const reference to the deleter
*/
const deleter_type& get_deleter() const {
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 {
return get()[i];
}
/*!
* \brief Converts the unique ptr to a boolean, indicating if it points to something or not
*/
explicit operator bool() const {
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 p = get();
std::get<0>(_data) = pointer_type();
return p;
}
/*!
* \brief Resets the unique pointer to an empty state
*/
void reset(){
reset(pointer_type());
}
/*!
* \brief Resets the unique pointer to a new state
* \param p The new pointer value
*/
void reset(pointer_type p){
auto tmp = get();
std::get<0>(_data) = p;
@ -193,11 +272,19 @@ public:
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");
/*!
* \brief Helper to create an unique_ptr from the args
*/
template <typename T, typename... Args>
std::unique_ptr<T> make_unique(Args&&... args){
return std::unique_ptr<T>(new T(std::forward<Args>(args)...));