First import
Files taken directly from dindexer
This commit is contained in:
commit
ccb2fc7ae5
15 changed files with 2336 additions and 0 deletions
117
include/duckhandy/MaxSizedArray.hpp
Normal file
117
include/duckhandy/MaxSizedArray.hpp
Normal file
|
@ -0,0 +1,117 @@
|
|||
/* Copyright 2016, Michele Santullo
|
||||
* This file is part of "duckhandy".
|
||||
*
|
||||
* "duckhandy" 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.
|
||||
*
|
||||
* "duckhandy" 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 "duckhandy". If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef idBC9F804ADD33468A9C7657E823FFC706
|
||||
#define idBC9F804ADD33468A9C7657E823FFC706
|
||||
|
||||
#include "implem/AutomemBase.hpp"
|
||||
#include "implem/IteratorOnPtr.hpp"
|
||||
#include <memory>
|
||||
#include <cstddef>
|
||||
#include <type_traits>
|
||||
#include <cassert>
|
||||
#include <utility>
|
||||
|
||||
namespace dhandy {
|
||||
const size_t MAXSZARR_MAX_STACK_ALLOC_SIZE = MAX_STACK_ALLOC_SIZE;
|
||||
|
||||
//TODO: add a template parameter to force stack allocation regardless of
|
||||
//sizeof(T) * S
|
||||
template <typename T, size_t S, typename A=std::allocator<T> >
|
||||
class MaxSizedArray :
|
||||
private std::conditional<
|
||||
(sizeof(T) * S > (MAXSZARR_MAX_STACK_ALLOC_SIZE > 4 * sizeof(T*) ? MAXSZARR_MAX_STACK_ALLOC_SIZE - sizeof(T*) : MAXSZARR_MAX_STACK_ALLOC_SIZE)),
|
||||
AutomemRawBase_heap<T, S, A>,
|
||||
AutomemRawBase_stack<T, S>
|
||||
>::type
|
||||
{
|
||||
typedef typename std::conditional<
|
||||
(sizeof(T) * S > (MAXSZARR_MAX_STACK_ALLOC_SIZE > 4 * sizeof(T*) ? MAXSZARR_MAX_STACK_ALLOC_SIZE - sizeof(T*) : MAXSZARR_MAX_STACK_ALLOC_SIZE)),
|
||||
AutomemRawBase_heap<T, S, A>,
|
||||
AutomemRawBase_stack<T, S>
|
||||
>::type parent_type;
|
||||
|
||||
public:
|
||||
typedef IteratorOnPtr<T*, T, false> iterator;
|
||||
typedef IteratorOnPtr<const T*, const T, false> const_iterator;
|
||||
typedef IteratorOnPtr<T*, T, true> reverse_iterator;
|
||||
typedef IteratorOnPtr<const T*, const T, true> const_reverse_iterator;
|
||||
typedef T& reference;
|
||||
typedef T&& mov_reference;
|
||||
typedef const T& const_reference;
|
||||
typedef size_t size_type;
|
||||
typedef ptrdiff_t difference_type;
|
||||
typedef T value_type;
|
||||
typedef T* pointer;
|
||||
typedef const T* const_pointer;
|
||||
|
||||
enum MAX_SIZE_ENUM {
|
||||
MAX_SIZE = S
|
||||
};
|
||||
|
||||
MaxSizedArray ( void );
|
||||
MaxSizedArray ( const MaxSizedArray& parOther );
|
||||
MaxSizedArray ( MaxSizedArray&& parOther );
|
||||
~MaxSizedArray ( void );
|
||||
|
||||
bool empty ( void ) const;
|
||||
size_type size ( void ) const;
|
||||
size_type capacity ( void ) const { return S; }
|
||||
size_type max_size ( void ) const { return S; }
|
||||
void push_back ( const value_type& parNewItem );
|
||||
void push_back ( value_type&& parNewItem );
|
||||
void pop_back ( void );
|
||||
iterator erase ( const iterator& parDele );
|
||||
iterator erase ( const iterator& parFrom, const iterator& parToExcl );
|
||||
void clear ( void );
|
||||
reference operator[] ( size_type parIndex ) &;
|
||||
mov_reference operator[] ( size_type parIndex ) &&;
|
||||
const_reference operator[] ( size_type parIndex ) const &;
|
||||
MaxSizedArray& operator= ( const MaxSizedArray& parOther );
|
||||
bool operator== ( const MaxSizedArray& parOther ) const;
|
||||
bool operator!= ( const MaxSizedArray& parOther ) const;
|
||||
pointer GetPointer ( void );
|
||||
const_pointer GetPointer ( void ) const;
|
||||
void reserve ( size_type parReserve );
|
||||
|
||||
iterator begin ( void );
|
||||
const_iterator begin ( void ) const;
|
||||
iterator end ( void );
|
||||
const_iterator end ( void ) const;
|
||||
reverse_iterator rbegin ( void );
|
||||
const_reverse_iterator rbegin ( void ) const;
|
||||
reverse_iterator rend ( void );
|
||||
const_reverse_iterator rend ( void ) const;
|
||||
reference front ( void ) & { return (*this)[0]; }
|
||||
reference back ( void ) & { return (*this)[size() - 1]; }
|
||||
mov_reference front ( void ) && { return (*this)[0]; }
|
||||
mov_reference back ( void ) && { return (*this)[size() - 1]; }
|
||||
const_reference front ( void ) const & { return (*this)[0]; }
|
||||
const_reference back ( void ) const & { return (*this)[size() - 1]; }
|
||||
|
||||
private:
|
||||
pointer GetPointer_NoAssert ( void ) { return m_localMem; }
|
||||
const_pointer GetPointer_NoAssert ( void ) const { return m_localMem; }
|
||||
|
||||
T* m_localMem; //A copy of memory pointer is required
|
||||
size_type m_used;
|
||||
};
|
||||
} //namespace dhandy
|
||||
|
||||
#include "MaxSizedArray.inl"
|
||||
|
||||
#endif
|
289
include/duckhandy/MaxSizedArray.inl
Normal file
289
include/duckhandy/MaxSizedArray.inl
Normal file
|
@ -0,0 +1,289 @@
|
|||
/* Copyright 2016, Michele Santullo
|
||||
* This file is part of "duckhandy".
|
||||
*
|
||||
* "duckhandy" 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.
|
||||
*
|
||||
* "duckhandy" 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 "duckhandy". If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
namespace dhandy {
|
||||
///-------------------------------------------------------------------------
|
||||
///-------------------------------------------------------------------------
|
||||
template <typename T, size_t S, typename A>
|
||||
MaxSizedArray<T, S, A>::MaxSizedArray() {
|
||||
m_localMem = this->AllocMemory();
|
||||
m_used = 0;
|
||||
}
|
||||
|
||||
///-------------------------------------------------------------------------
|
||||
///-------------------------------------------------------------------------
|
||||
template <typename T, size_t S, typename A>
|
||||
MaxSizedArray<T, S, A>::MaxSizedArray (const MaxSizedArray& parOther) :
|
||||
parent_type(),
|
||||
m_used(0)
|
||||
{
|
||||
m_localMem = this->AllocMemory();
|
||||
const size_type count = parOther.size();
|
||||
for (size_type z = 0; z < count; ++z) {
|
||||
this->push_back(parOther[z]);
|
||||
}
|
||||
}
|
||||
|
||||
///-------------------------------------------------------------------------
|
||||
///-------------------------------------------------------------------------
|
||||
template <typename T, size_t S, typename A>
|
||||
MaxSizedArray<T, S, A>::MaxSizedArray (MaxSizedArray&& parOther) :
|
||||
parent_type(),
|
||||
m_used(0)
|
||||
{
|
||||
m_localMem = this->AllocMemory();
|
||||
const size_type count = parOther.size();
|
||||
for (size_type z = 0; z < count; ++z) {
|
||||
this->push_back(std::move(parOther[z]));
|
||||
}
|
||||
}
|
||||
|
||||
///-------------------------------------------------------------------------
|
||||
///-------------------------------------------------------------------------
|
||||
template <typename T, size_t S, typename A>
|
||||
MaxSizedArray<T, S, A>::~MaxSizedArray() {
|
||||
this->clear();
|
||||
this->FreeMemory();
|
||||
}
|
||||
|
||||
///-------------------------------------------------------------------------
|
||||
///-------------------------------------------------------------------------
|
||||
template <typename T, size_t S, typename A>
|
||||
bool MaxSizedArray<T, S, A>::empty() const {
|
||||
return 0 == m_used;
|
||||
}
|
||||
|
||||
///-------------------------------------------------------------------------
|
||||
///-------------------------------------------------------------------------
|
||||
template <typename T, size_t S, typename A>
|
||||
typename MaxSizedArray<T, S, A>::size_type MaxSizedArray<T, S, A>::size() const {
|
||||
return m_used;
|
||||
}
|
||||
|
||||
///-------------------------------------------------------------------------
|
||||
///-------------------------------------------------------------------------
|
||||
template <typename T, size_t S, typename A>
|
||||
void MaxSizedArray<T, S, A>::push_back (value_type&& parNewItem) {
|
||||
assert(size() < capacity());
|
||||
this->GetNewT(m_used, std::move(parNewItem));
|
||||
++m_used;
|
||||
}
|
||||
|
||||
///-------------------------------------------------------------------------
|
||||
///-------------------------------------------------------------------------
|
||||
template <typename T, size_t S, typename A>
|
||||
void MaxSizedArray<T, S, A>::push_back (const value_type& parNewItem) {
|
||||
assert(size() < capacity());
|
||||
this->GetNewT(m_used, parNewItem);
|
||||
++m_used;
|
||||
}
|
||||
|
||||
///-------------------------------------------------------------------------
|
||||
///-------------------------------------------------------------------------
|
||||
template <typename T, size_t S, typename A>
|
||||
void MaxSizedArray<T, S, A>::pop_back() {
|
||||
assert(not empty());
|
||||
m_localMem[m_used - 1].~T();
|
||||
--m_used;
|
||||
}
|
||||
|
||||
///-------------------------------------------------------------------------
|
||||
///-------------------------------------------------------------------------
|
||||
template <typename T, size_t S, typename A>
|
||||
typename MaxSizedArray<T, S, A>::reference MaxSizedArray<T, S, A>::operator[] (size_type parIndex) & {
|
||||
assert(parIndex < size());
|
||||
return m_localMem[parIndex];
|
||||
}
|
||||
|
||||
///-------------------------------------------------------------------------
|
||||
///-------------------------------------------------------------------------
|
||||
template <typename T, size_t S, typename A>
|
||||
typename MaxSizedArray<T, S, A>::mov_reference MaxSizedArray<T, S, A>::operator[] (size_type parIndex) && {
|
||||
assert(parIndex < size());
|
||||
return std::move(m_localMem[parIndex]);
|
||||
}
|
||||
|
||||
///-------------------------------------------------------------------------
|
||||
///-------------------------------------------------------------------------
|
||||
template <typename T, size_t S, typename A>
|
||||
typename MaxSizedArray<T, S, A>::const_reference MaxSizedArray<T, S, A>::operator[] (size_type parIndex) const & {
|
||||
assert(parIndex < size());
|
||||
return m_localMem[parIndex];
|
||||
}
|
||||
|
||||
///-------------------------------------------------------------------------
|
||||
///-------------------------------------------------------------------------
|
||||
template <typename T, size_t S, typename A>
|
||||
MaxSizedArray<T, S, A>& MaxSizedArray<T, S, A>::operator= (const MaxSizedArray& parOther) {
|
||||
m_used = parOther.m_used;
|
||||
std::copy(parOther.GetMemPtr(), parOther.GetMemPtr() + parOther.size(), this->GetMemPtr());
|
||||
return *this;
|
||||
}
|
||||
|
||||
///-------------------------------------------------------------------------
|
||||
///-------------------------------------------------------------------------
|
||||
template <typename T, size_t S, typename A>
|
||||
bool MaxSizedArray<T, S, A>::operator== (const MaxSizedArray& parOther) const {
|
||||
if (size() != parOther.size())
|
||||
return false;
|
||||
for (size_type z = 0; z < size(); ++z) {
|
||||
if ((*this)[z] != parOther[z])
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
///-------------------------------------------------------------------------
|
||||
///-------------------------------------------------------------------------
|
||||
template <typename T, size_t S, typename A>
|
||||
bool MaxSizedArray<T, S, A>::operator!= (const MaxSizedArray& parOther) const {
|
||||
return not (*this == parOther);
|
||||
}
|
||||
|
||||
///-------------------------------------------------------------------------
|
||||
///-------------------------------------------------------------------------
|
||||
template <typename T, size_t S, typename A>
|
||||
typename MaxSizedArray<T, S, A>::pointer MaxSizedArray<T, S, A>::GetPointer() {
|
||||
assert(size() > 0);
|
||||
return GetPointer_NoAssert();
|
||||
}
|
||||
|
||||
///-------------------------------------------------------------------------
|
||||
///-------------------------------------------------------------------------
|
||||
template <typename T, size_t S, typename A>
|
||||
typename MaxSizedArray<T, S, A>::const_pointer MaxSizedArray<T, S, A>::GetPointer() const {
|
||||
assert(size() > 0);
|
||||
return GetPointer_NoAssert();
|
||||
}
|
||||
|
||||
///-------------------------------------------------------------------------
|
||||
///-------------------------------------------------------------------------
|
||||
template <typename T, size_t S, typename A>
|
||||
void MaxSizedArray<T, S, A>::clear() {
|
||||
const size_type count = this->size();
|
||||
for (size_type z = 0; z < count; ++z) {
|
||||
(*this)[z].~T();
|
||||
}
|
||||
m_used = 0;
|
||||
}
|
||||
|
||||
///-------------------------------------------------------------------------
|
||||
///-------------------------------------------------------------------------
|
||||
template <typename T, size_t S, typename A>
|
||||
typename MaxSizedArray<T, S, A>::iterator MaxSizedArray<T, S, A>::begin() {
|
||||
return iterator(GetPointer_NoAssert(), size());
|
||||
}
|
||||
|
||||
///-------------------------------------------------------------------------
|
||||
///-------------------------------------------------------------------------
|
||||
template <typename T, size_t S, typename A>
|
||||
typename MaxSizedArray<T, S, A>::const_iterator MaxSizedArray<T, S, A>::begin() const {
|
||||
return const_iterator(GetPointer_NoAssert(), size());
|
||||
}
|
||||
|
||||
///-------------------------------------------------------------------------
|
||||
///-------------------------------------------------------------------------
|
||||
template <typename T, size_t S, typename A>
|
||||
typename MaxSizedArray<T, S, A>::iterator MaxSizedArray<T, S, A>::end() {
|
||||
return iterator(GetPointer_NoAssert() + size(), 0);
|
||||
}
|
||||
|
||||
///-------------------------------------------------------------------------
|
||||
///-------------------------------------------------------------------------
|
||||
template <typename T, size_t S, typename A>
|
||||
typename MaxSizedArray<T, S, A>::const_iterator MaxSizedArray<T, S, A>::end() const {
|
||||
return const_iterator(GetPointer_NoAssert() + size(), 0);
|
||||
}
|
||||
|
||||
///-------------------------------------------------------------------------
|
||||
///-------------------------------------------------------------------------
|
||||
template <typename T, size_t S, typename A>
|
||||
typename MaxSizedArray<T, S, A>::reverse_iterator MaxSizedArray<T, S, A>::rbegin() {
|
||||
return reverse_iterator(GetPointer_NoAssert() + size() - 1, size());
|
||||
}
|
||||
|
||||
///-------------------------------------------------------------------------
|
||||
///-------------------------------------------------------------------------
|
||||
template <typename T, size_t S, typename A>
|
||||
typename MaxSizedArray<T, S, A>::const_reverse_iterator MaxSizedArray<T, S, A>::rbegin() const {
|
||||
return const_reverse_iterator(GetPointer_NoAssert() + size() - 1, size());
|
||||
}
|
||||
|
||||
///-------------------------------------------------------------------------
|
||||
///-------------------------------------------------------------------------
|
||||
template <typename T, size_t S, typename A>
|
||||
typename MaxSizedArray<T, S, A>::reverse_iterator MaxSizedArray<T, S, A>::rend() {
|
||||
return reverse_iterator(GetPointer_NoAssert() - 1, 0);
|
||||
}
|
||||
|
||||
///-------------------------------------------------------------------------
|
||||
///-------------------------------------------------------------------------
|
||||
template <typename T, size_t S, typename A>
|
||||
typename MaxSizedArray<T, S, A>::const_reverse_iterator MaxSizedArray<T, S, A>::rend() const {
|
||||
return const_reverse_iterator(GetPointer_NoAssert() - 1, 0);
|
||||
}
|
||||
|
||||
///-------------------------------------------------------------------------
|
||||
///-------------------------------------------------------------------------
|
||||
template <typename T, size_t S, typename A>
|
||||
typename MaxSizedArray<T, S, A>::iterator MaxSizedArray<T, S, A>::erase (const iterator& parDele) {
|
||||
assert(end() != parDele);
|
||||
return erase(parDele, parDele + 1);
|
||||
}
|
||||
|
||||
///-------------------------------------------------------------------------
|
||||
///-------------------------------------------------------------------------
|
||||
template <typename T, size_t S, typename A>
|
||||
typename MaxSizedArray<T, S, A>::iterator MaxSizedArray<T, S, A>::erase (const iterator& parFrom, const iterator& parToExcl) {
|
||||
assert(parFrom >= begin());
|
||||
assert(parToExcl <= end());
|
||||
assert(parToExcl >= parFrom);
|
||||
|
||||
//I'm doing this in two passes: first, I'm deleting as many elements as
|
||||
//the ones that would be left at the end (that is, delete and move),
|
||||
//then delete everything to the end of the buffer, if necessary.
|
||||
const size_type deleCount = static_cast<size_type>(parToExcl - parFrom);
|
||||
const size_type firstIndexToDele = static_cast<size_type>(parFrom - begin());
|
||||
const size_type& sz = m_used;
|
||||
assert(firstIndexToDele + deleCount <= sz);
|
||||
const size_type deleAndCopyCount = sz - (firstIndexToDele + deleCount);
|
||||
|
||||
//As said, make room and copy from the cut tail
|
||||
for (size_type z = firstIndexToDele; z < firstIndexToDele + deleAndCopyCount; z++) {
|
||||
(*this)[z].~T();
|
||||
new(&(*this)[z]) T((*this)[z + deleCount]);
|
||||
}
|
||||
|
||||
//Any leftover is rubbish
|
||||
for (size_type z = firstIndexToDele + deleAndCopyCount; z < sz; z++) {
|
||||
(*this)[z].~T();
|
||||
}
|
||||
|
||||
m_used -= deleCount;
|
||||
return begin() + firstIndexToDele;
|
||||
}
|
||||
|
||||
///-------------------------------------------------------------------------
|
||||
///-------------------------------------------------------------------------
|
||||
template <typename T, size_t S, typename A>
|
||||
void MaxSizedArray<T, S, A>::reserve (size_type parReserve) {
|
||||
assert(parReserve <= S);
|
||||
if (parReserve > S) {
|
||||
throw std::length_error("Unable to reserve more memory than the build-time size for MaxSizedArray");
|
||||
}
|
||||
}
|
||||
} //namespace dhandy
|
38
include/duckhandy/cmake_on_off.h
Normal file
38
include/duckhandy/cmake_on_off.h
Normal file
|
@ -0,0 +1,38 @@
|
|||
/* Copyright 2016, Michele Santullo
|
||||
* This file is part of "duckhandy".
|
||||
*
|
||||
* "duckhandy" 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.
|
||||
*
|
||||
* "duckhandy" 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 "duckhandy". If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef id9B6B373E88404330ADEE51A4EC861787
|
||||
#define id9B6B373E88404330ADEE51A4EC861787
|
||||
|
||||
#if !defined(CMAKE_ON)
|
||||
# define CMAKE_ON 1
|
||||
# define CMAKE_on 1
|
||||
# define CMAKE_On 1
|
||||
# define CMAKE_oN 1
|
||||
#endif
|
||||
#if !defined(CMAKE_OFF)
|
||||
# define CMAKE_OFF 0
|
||||
# define CMAKE_OFf 0
|
||||
# define CMAKE_OfF 0
|
||||
# define CMAKE_Off 0
|
||||
# define CMAKE_oFF 0
|
||||
# define CMAKE_oFf 0
|
||||
# define CMAKE_ofF 0
|
||||
# define CMAKE_off 0
|
||||
#endif
|
||||
|
||||
#endif
|
62
include/duckhandy/compatibility.h
Normal file
62
include/duckhandy/compatibility.h
Normal file
|
@ -0,0 +1,62 @@
|
|||
/* Copyright 2016, Michele Santullo
|
||||
* This file is part of "duckhandy".
|
||||
*
|
||||
* "duckhandy" 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.
|
||||
*
|
||||
* "duckhandy" 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 "duckhandy". If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef id45CDD1DAEF4F42968E3C89F68FDDA9BC
|
||||
#define id45CDD1DAEF4F42968E3C89F68FDDA9BC
|
||||
|
||||
#if defined(__GNUC__)
|
||||
# if defined(__clang__)
|
||||
# if !defined(__has_attribute)
|
||||
//Fall back to version number comparing
|
||||
# else
|
||||
# if __has_attribute(flatten)
|
||||
# define a_flatten __attribute__((flatten))
|
||||
# else
|
||||
# define a_flatten
|
||||
# endif
|
||||
# if __has_attribute(always_inline)
|
||||
# define a_always_inline __attribute__((always_inline))
|
||||
# else
|
||||
# define a_always_inline
|
||||
# endif
|
||||
# if __has_attribute(pure)
|
||||
# define a_pure __attribute__((pure))
|
||||
# else
|
||||
# define a_pure
|
||||
# endif
|
||||
# if __has_attribute(deprecated)
|
||||
# define a_deprecated __attribute__((deprecated))
|
||||
# else
|
||||
# define a_deprecated
|
||||
#endif
|
||||
# endif
|
||||
# else
|
||||
//Fix here if you get warnings about unsupported attributes on your compiler
|
||||
# define a_flatten __attribute__((flatten))
|
||||
# define a_always_inline __attribute__((always_inline))
|
||||
# define a_pure __attribute__((pure))
|
||||
# define a_deprecated __attribute__((deprecated))
|
||||
# endif
|
||||
#else
|
||||
# warning "Unsupported compiler, please fill this section or file a bug"
|
||||
# define a_flatten
|
||||
# define a_always_inline
|
||||
# define a_pure
|
||||
# define a_deprecated
|
||||
#endif
|
||||
|
||||
#endif
|
54
include/duckhandy/has_method.hpp
Normal file
54
include/duckhandy/has_method.hpp
Normal file
|
@ -0,0 +1,54 @@
|
|||
/*
|
||||
* Copyright 2015 Michele "King_DuckZ" Santullo
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef idFBC29C5127784D35BE62F7BAC16E3687
|
||||
#define idFBC29C5127784D35BE62F7BAC16E3687
|
||||
|
||||
#define define_has_method(method_name,pretty_name) \
|
||||
template <typename T> \
|
||||
struct Has ## pretty_name ## Method { \
|
||||
private: \
|
||||
struct TrueType { int a[2]; }; \
|
||||
typedef int FalseType; \
|
||||
template <typename C> static TrueType has_method ( decltype(&C::method_name) ); \
|
||||
template <typename C> static FalseType has_method ( ... ); \
|
||||
public: \
|
||||
enum { value = sizeof(has_method<T>(0)) == sizeof(TrueType) }; \
|
||||
}
|
||||
#define define_has_typedef(typedef_name,pretty_name) \
|
||||
template <typename T> \
|
||||
struct Has ## pretty_name ## Typedef { \
|
||||
private: \
|
||||
struct TrueType { int a[2]; }; \
|
||||
typedef int FalseType; \
|
||||
template <typename C> static TrueType has_typedef ( const typename C::typedef_name* ); \
|
||||
template <typename C> static FalseType has_typedef ( ... ); \
|
||||
public: \
|
||||
enum { value = sizeof(has_typedef<T>(nullptr)) == sizeof(TrueType) }; \
|
||||
}
|
||||
#define define_has_enum(enum_name,pretty_name) \
|
||||
template <typename T> \
|
||||
struct Has ## pretty_name ## Enum { \
|
||||
private: \
|
||||
struct TrueType { int a[2]; }; \
|
||||
typedef int FalseType; \
|
||||
template <typename C> static TrueType has_enum ( decltype(C::enum_name)* ); \
|
||||
template <typename C> static FalseType has_enum ( ... ); \
|
||||
public:\
|
||||
enum { value = sizeof(has_enum<T>(nullptr)) == sizeof(TrueType) }; \
|
||||
}
|
||||
|
||||
#endif
|
91
include/duckhandy/implem/AutomemBase.hpp
Normal file
91
include/duckhandy/implem/AutomemBase.hpp
Normal file
|
@ -0,0 +1,91 @@
|
|||
/* Copyright 2016, Michele Santullo
|
||||
* This file is part of "duckhandy".
|
||||
*
|
||||
* "duckhandy" 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.
|
||||
*
|
||||
* "duckhandy" 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 "duckhandy". If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef idDB299AE3079F4830BB1D543C07F7B594
|
||||
#define idDB299AE3079F4830BB1D543C07F7B594
|
||||
|
||||
//Classes in this file are low level and only intended to be used by library
|
||||
//code. They don't do much by themselves and shoud never be used from outside.
|
||||
|
||||
#include <memory>
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <cstdint>
|
||||
|
||||
#if !defined(NDEBUG)
|
||||
# define ASSERTIONSENABLED
|
||||
#endif
|
||||
|
||||
namespace dhandy {
|
||||
const size_t MAX_STACK_ALLOC_SIZE = 128;
|
||||
|
||||
///-------------------------------------------------------------------------
|
||||
///Heap-based allocation, only gets raw memory
|
||||
///-------------------------------------------------------------------------
|
||||
template <typename T, size_t S, typename A=std::allocator<T> >
|
||||
class AutomemRawBase_heap {
|
||||
protected:
|
||||
AutomemRawBase_heap ( void );
|
||||
AutomemRawBase_heap ( const AutomemRawBase_heap& ) = delete; //Copy ctor can't be implemented at this level
|
||||
AutomemRawBase_heap ( AutomemRawBase_heap&& parOther );
|
||||
|
||||
template <typename... Args>
|
||||
T* GetNewT ( size_t parIndex, Args&&... parArgs );
|
||||
T* AllocMemory ( void );
|
||||
void FreeMemory ( void ) noexcept;
|
||||
void swap ( AutomemRawBase_heap& parOther ) noexcept { std::swap(m_localMem, parOther.m_localMem); }
|
||||
private:
|
||||
void operator= (const AutomemRawBase_heap&);
|
||||
|
||||
#if defined(ASSERTIONSENABLED)
|
||||
typedef uintptr_t PTR_INT_TYPE;
|
||||
static_assert(sizeof(PTR_INT_TYPE) == sizeof(char*), "Wrong uintptr_t size");
|
||||
#endif
|
||||
T* m_localMem;
|
||||
};
|
||||
|
||||
///-------------------------------------------------------------------------
|
||||
///Stack-based allocation, only gets raw memory
|
||||
///-------------------------------------------------------------------------
|
||||
template <typename T, size_t S>
|
||||
class AutomemRawBase_stack {
|
||||
protected:
|
||||
AutomemRawBase_stack ( void ) = default;
|
||||
AutomemRawBase_stack ( const AutomemRawBase_stack& ) = delete; //Copy ctor can't be implemented at this level
|
||||
AutomemRawBase_stack ( AutomemRawBase_stack&& ) = delete;
|
||||
~AutomemRawBase_stack ( void ) = default;
|
||||
|
||||
template <typename... Args>
|
||||
T* GetNewT ( size_t parIndex, Args&&... parArgs );
|
||||
T* AllocMemory ( void );
|
||||
void FreeMemory ( void ) noexcept { return; }
|
||||
private:
|
||||
#if defined(ASSERTIONSENABLED)
|
||||
typedef uintptr_t PTR_INT_TYPE;
|
||||
static_assert(sizeof(PTR_INT_TYPE) == sizeof(char*), "Wrong uintptr_t size");
|
||||
#endif
|
||||
void operator= (const AutomemRawBase_stack&);
|
||||
typename std::aligned_storage<sizeof(T), alignof(T)>::type m_localMem[S];
|
||||
};
|
||||
} //namespace dhandy
|
||||
|
||||
#include "AutomemBase.inl"
|
||||
|
||||
#if defined(ASSERTIONSENABLED)
|
||||
# undef ASSERTIONSENABLED
|
||||
#endif
|
||||
#endif
|
118
include/duckhandy/implem/AutomemBase.inl
Normal file
118
include/duckhandy/implem/AutomemBase.inl
Normal file
|
@ -0,0 +1,118 @@
|
|||
/* Copyright 2016, Michele Santullo
|
||||
* This file is part of "duckhandy".
|
||||
*
|
||||
* "duckhandy" 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.
|
||||
*
|
||||
* "duckhandy" 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 "duckhandy". If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
namespace dhandy {
|
||||
namespace {
|
||||
#if defined(ASSERTIONSENABLED)
|
||||
const char g_guard = 0xAB;
|
||||
#endif
|
||||
} //unnamed namespace
|
||||
|
||||
///-------------------------------------------------------------------------
|
||||
///-------------------------------------------------------------------------
|
||||
template <typename T, size_t S, typename A>
|
||||
AutomemRawBase_heap<T, S, A>::AutomemRawBase_heap() {
|
||||
#if !defined(NDEBUG)
|
||||
m_localMem = nullptr;
|
||||
#endif
|
||||
}
|
||||
|
||||
///-------------------------------------------------------------------------
|
||||
///-------------------------------------------------------------------------
|
||||
template <typename T, size_t S, typename A>
|
||||
AutomemRawBase_heap<T, S, A>::AutomemRawBase_heap (AutomemRawBase_heap&& parOther) {
|
||||
#if !defined(NDEBUG)
|
||||
m_localMem = nullptr;
|
||||
#endif
|
||||
this->swap(parOther);
|
||||
}
|
||||
|
||||
///-------------------------------------------------------------------------
|
||||
///-------------------------------------------------------------------------
|
||||
template <typename T, size_t S, typename A>
|
||||
T* AutomemRawBase_heap<T, S, A>::AllocMemory() {
|
||||
#if !defined(NDEBUG)
|
||||
assert(nullptr == m_localMem);
|
||||
#endif
|
||||
m_localMem = A().allocate(S);
|
||||
#if defined(ASSERTIONSENABLED)
|
||||
assert(reinterpret_cast<PTR_INT_TYPE>(m_localMem) % alignof(T) == 0); //Make sure alignment is correct
|
||||
std::fill(
|
||||
reinterpret_cast<char*>(&m_localMem[0]),
|
||||
reinterpret_cast<char*>(&m_localMem[0]) + sizeof(m_localMem),
|
||||
g_guard
|
||||
);
|
||||
#endif
|
||||
return m_localMem;
|
||||
}
|
||||
|
||||
///-------------------------------------------------------------------------
|
||||
///-------------------------------------------------------------------------
|
||||
template <typename T, size_t S, typename A>
|
||||
void AutomemRawBase_heap<T, S, A>::FreeMemory() noexcept {
|
||||
#if !defined(NDEBUG)
|
||||
assert(nullptr != m_localMem);
|
||||
#endif
|
||||
A().deallocate(m_localMem, S);
|
||||
#if !defined(NDEBUG)
|
||||
m_localMem = nullptr;
|
||||
#endif
|
||||
}
|
||||
|
||||
///-------------------------------------------------------------------------
|
||||
///-------------------------------------------------------------------------
|
||||
template <typename T, size_t S, typename A>
|
||||
template <typename... Args>
|
||||
T* AutomemRawBase_heap<T, S, A>::GetNewT (size_t parIndex, Args&&... parArgs) {
|
||||
assert(parIndex < S);
|
||||
T* const location = m_localMem + parIndex;
|
||||
#if defined(ASSERTIONSENABLED)
|
||||
assert(reinterpret_cast<PTR_INT_TYPE>(location) % alignof(T) == 0);
|
||||
assert(g_guard == *reinterpret_cast<const char*>(location));
|
||||
#endif
|
||||
return new(location) T(std::forward<Args...>(parArgs)...);
|
||||
}
|
||||
|
||||
///-------------------------------------------------------------------------
|
||||
///-------------------------------------------------------------------------
|
||||
template <typename T, size_t S>
|
||||
T* AutomemRawBase_stack<T, S>::AllocMemory() {
|
||||
#if defined(ASSERTIONSENABLED)
|
||||
assert(reinterpret_cast<PTR_INT_TYPE>(m_localMem) % alignof(T) == 0); //Make sure alignment is correct
|
||||
std::fill(
|
||||
reinterpret_cast<char*>(&m_localMem[0]),
|
||||
reinterpret_cast<char*>(&m_localMem[0]) + sizeof(m_localMem),
|
||||
g_guard
|
||||
);
|
||||
#endif
|
||||
return reinterpret_cast<T*>(&m_localMem[0]);
|
||||
}
|
||||
|
||||
///-------------------------------------------------------------------------
|
||||
///-------------------------------------------------------------------------
|
||||
template <typename T, size_t S>
|
||||
template <typename... Args>
|
||||
T* AutomemRawBase_stack<T, S>::GetNewT (size_t parIndex, Args&&... parArgs) {
|
||||
assert(parIndex < S);
|
||||
auto* const location = &m_localMem[parIndex];
|
||||
#if defined(ASSERTIONSENABLED)
|
||||
assert(reinterpret_cast<PTR_INT_TYPE>(location) % alignof(T) == 0);
|
||||
assert(g_guard == *reinterpret_cast<const char*>(location));
|
||||
#endif
|
||||
return new(location) T(std::forward<Args...>(parArgs)...);
|
||||
}
|
||||
} //namespace dhandy
|
314
include/duckhandy/implem/IteratorOnPtr.hpp
Normal file
314
include/duckhandy/implem/IteratorOnPtr.hpp
Normal file
|
@ -0,0 +1,314 @@
|
|||
/* Copyright 2016, Michele Santullo
|
||||
* This file is part of "duckhandy".
|
||||
*
|
||||
* "duckhandy" 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.
|
||||
*
|
||||
* "duckhandy" 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 "duckhandy". If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef id1B822B1775424D879AA6AD1739B5BC91
|
||||
#define id1B822B1775424D879AA6AD1739B5BC91
|
||||
|
||||
#include <iterator>
|
||||
#include <cstdint>
|
||||
#include <type_traits>
|
||||
#include <cassert>
|
||||
|
||||
namespace dhandy {
|
||||
namespace implem_iop {
|
||||
template <typename P, typename T, int32_t I>
|
||||
class IteratorOnPtr_base : public std::iterator<std::random_access_iterator_tag, T> {
|
||||
typedef std::iterator<std::random_access_iterator_tag, T> parent_type;
|
||||
public:
|
||||
//Typedefs to be STL-compliant
|
||||
typedef typename parent_type::iterator_category iterator_category;
|
||||
typedef typename parent_type::value_type value_type;
|
||||
typedef typename parent_type::difference_type difference_type;
|
||||
typedef typename parent_type::pointer pointer;
|
||||
typedef typename std::remove_reference<T>::type& reference;
|
||||
|
||||
IteratorOnPtr_base ( P parPointer, difference_type parSize );
|
||||
IteratorOnPtr_base ( const IteratorOnPtr_base& parOther );
|
||||
template <typename P1, typename T1>
|
||||
explicit IteratorOnPtr_base ( const IteratorOnPtr_base<P1, T1, I>& parOther );
|
||||
~IteratorOnPtr_base ( void );
|
||||
|
||||
difference_type operator- ( const IteratorOnPtr_base& parOther ) const;
|
||||
|
||||
bool operator== ( const IteratorOnPtr_base& parOther ) const { return m_pointer == parOther.m_pointer; }
|
||||
bool operator!= ( const IteratorOnPtr_base& parOther ) const { return not operator==(parOther); }
|
||||
bool operator< ( const IteratorOnPtr_base& parOther ) const { return m_pointer < parOther.m_pointer; }
|
||||
bool operator>= ( const IteratorOnPtr_base& parOther ) const { return not operator<(parOther); }
|
||||
bool operator> ( const IteratorOnPtr_base& parOther ) const { return parOther < *this; }
|
||||
bool operator<= ( const IteratorOnPtr_base& parOther ) const { return not operator>(parOther); }
|
||||
|
||||
P GetPointer ( void ) { return m_pointer; }
|
||||
const P GetPointer ( void ) const { return m_pointer; }
|
||||
#if !defined(NDEBUG)
|
||||
difference_type GetSize ( void ) const { return GetSize(0); }
|
||||
#endif
|
||||
|
||||
protected:
|
||||
enum {
|
||||
STEP = (I < 0 ? -I : I)
|
||||
};
|
||||
|
||||
#if !defined(NDEBUG)
|
||||
difference_type GetSize ( difference_type parAdvance ) const;
|
||||
bool CanAdvance ( difference_type parAdvance ) const;
|
||||
void AlterSize ( difference_type parAdvance );
|
||||
#endif
|
||||
void MoveIterator ( difference_type parAdvance );
|
||||
|
||||
P m_pointer;
|
||||
|
||||
private:
|
||||
#if !defined(NDEBUG)
|
||||
difference_type m_size;
|
||||
#endif
|
||||
};
|
||||
} //namespace implem_iop
|
||||
|
||||
template <typename P, typename T, bool R>
|
||||
class IteratorOnPtr : public implem_iop::IteratorOnPtr_base<P, T, (R ? -1 : 1)> {
|
||||
typedef implem_iop::IteratorOnPtr_base<P, T, (R ? -1 : 1)> parent_type;
|
||||
enum {
|
||||
STEP = parent_type::STEP
|
||||
};
|
||||
public:
|
||||
typedef typename parent_type::iterator_category iterator_category;
|
||||
typedef typename parent_type::value_type value_type;
|
||||
typedef typename parent_type::difference_type difference_type;
|
||||
typedef typename parent_type::pointer pointer;
|
||||
typedef typename parent_type::reference reference;
|
||||
|
||||
IteratorOnPtr ( void );
|
||||
IteratorOnPtr ( P parPointer, difference_type parSize );
|
||||
IteratorOnPtr ( const IteratorOnPtr& parOther ) : parent_type(parOther) { return; }
|
||||
template <typename P1, typename T1>
|
||||
IteratorOnPtr ( const IteratorOnPtr<P1, T1, R>& parOther ) : parent_type(parOther) {}
|
||||
~IteratorOnPtr ( void );
|
||||
|
||||
IteratorOnPtr& operator++ ( void ); //pre
|
||||
IteratorOnPtr operator++ ( int ); //post
|
||||
IteratorOnPtr& operator-- ( void );
|
||||
IteratorOnPtr operator-- ( int );
|
||||
reference operator* ( void );
|
||||
pointer operator-> ( void );
|
||||
|
||||
using parent_type::operator-;
|
||||
IteratorOnPtr operator+ ( difference_type parOther ) const;
|
||||
IteratorOnPtr operator- ( difference_type parOther ) const;
|
||||
IteratorOnPtr& operator+= ( difference_type parOther );
|
||||
IteratorOnPtr& operator-= ( difference_type parOther );
|
||||
protected:
|
||||
private:
|
||||
};
|
||||
|
||||
namespace implem_iop {
|
||||
///---------------------------------------------------------------------
|
||||
///---------------------------------------------------------------------
|
||||
template <typename P, typename T, int32_t I>
|
||||
#if !defined(NDEBUG)
|
||||
IteratorOnPtr_base<P, T, I>::IteratorOnPtr_base (P parPointer, difference_type parSize) :
|
||||
m_pointer(parPointer),
|
||||
m_size(parSize)
|
||||
#else
|
||||
IteratorOnPtr_base<P, T, I>::IteratorOnPtr_base (P parPointer, difference_type) :
|
||||
m_pointer(parPointer)
|
||||
#endif
|
||||
{
|
||||
static_assert(I != 0, "Step must be non-zero");
|
||||
}
|
||||
|
||||
///---------------------------------------------------------------------
|
||||
///---------------------------------------------------------------------
|
||||
template <typename P, typename T, int32_t I>
|
||||
template <typename P1, typename T1>
|
||||
IteratorOnPtr_base<P, T, I>::IteratorOnPtr_base (const IteratorOnPtr_base<P1, T1, I>& parOther) {
|
||||
m_pointer = parOther.GetPointer();
|
||||
#if !defined(NDEBUG)
|
||||
m_size = parOther.GetSize();
|
||||
#endif
|
||||
}
|
||||
|
||||
///---------------------------------------------------------------------
|
||||
///---------------------------------------------------------------------
|
||||
template <typename P, typename T, int32_t I>
|
||||
IteratorOnPtr_base<P, T, I>::IteratorOnPtr_base (const IteratorOnPtr_base& parOther) {
|
||||
m_pointer = parOther.m_pointer;
|
||||
#if !defined(NDEBUG)
|
||||
m_size = parOther.m_size;
|
||||
#endif
|
||||
}
|
||||
|
||||
///---------------------------------------------------------------------
|
||||
///---------------------------------------------------------------------
|
||||
template <typename P, typename T, int32_t I>
|
||||
IteratorOnPtr_base<P, T, I>::~IteratorOnPtr_base() {
|
||||
}
|
||||
|
||||
///---------------------------------------------------------------------
|
||||
///---------------------------------------------------------------------
|
||||
template <typename P, typename T, int32_t I>
|
||||
typename IteratorOnPtr_base<P, T, I>::difference_type IteratorOnPtr_base<P, T, I>::operator- (const IteratorOnPtr_base& parOther) const {
|
||||
if (I > 0)
|
||||
return m_pointer - parOther.m_pointer;
|
||||
else
|
||||
return parOther.m_pointer - m_pointer;
|
||||
}
|
||||
|
||||
#if !defined(NDEBUG)
|
||||
///---------------------------------------------------------------------
|
||||
///---------------------------------------------------------------------
|
||||
template <typename P, typename T, int32_t I>
|
||||
typename IteratorOnPtr_base<P, T, I>::difference_type IteratorOnPtr_base<P, T, I>::GetSize (difference_type parAdvance) const {
|
||||
return m_size - STEP * parAdvance;
|
||||
}
|
||||
|
||||
///---------------------------------------------------------------------
|
||||
///---------------------------------------------------------------------
|
||||
template <typename P, typename T, int32_t I>
|
||||
bool IteratorOnPtr_base<P, T, I>::CanAdvance (difference_type parAdvance) const {
|
||||
return (m_size >= STEP * parAdvance);
|
||||
}
|
||||
|
||||
///---------------------------------------------------------------------
|
||||
///---------------------------------------------------------------------
|
||||
template <typename P, typename T, int32_t I>
|
||||
void IteratorOnPtr_base<P, T, I>::AlterSize (difference_type parAdvance) {
|
||||
m_size = GetSize(parAdvance);
|
||||
}
|
||||
#endif
|
||||
|
||||
///---------------------------------------------------------------------
|
||||
///---------------------------------------------------------------------
|
||||
template <typename P, typename T, int32_t I>
|
||||
void IteratorOnPtr_base<P, T, I>::MoveIterator (difference_type parAdvance) {
|
||||
#if !defined(NDEBUG)
|
||||
assert(CanAdvance(parAdvance));
|
||||
AlterSize(parAdvance);
|
||||
#endif
|
||||
m_pointer += I * parAdvance;
|
||||
}
|
||||
} //namespace implem_iop
|
||||
|
||||
///-------------------------------------------------------------------------
|
||||
///-------------------------------------------------------------------------
|
||||
template <typename P, typename T, bool R>
|
||||
IteratorOnPtr<P, T, R>::IteratorOnPtr() :
|
||||
parent_type(NULL, 0)
|
||||
{
|
||||
}
|
||||
|
||||
///-------------------------------------------------------------------------
|
||||
///-------------------------------------------------------------------------
|
||||
template <typename P, typename T, bool R>
|
||||
IteratorOnPtr<P, T, R>::IteratorOnPtr (P parPointer, difference_type parSize) :
|
||||
parent_type(parPointer, parSize)
|
||||
{
|
||||
}
|
||||
|
||||
///-------------------------------------------------------------------------
|
||||
///-------------------------------------------------------------------------
|
||||
template <typename P, typename T, bool R>
|
||||
IteratorOnPtr<P, T, R>::~IteratorOnPtr() {
|
||||
}
|
||||
|
||||
///-------------------------------------------------------------------------
|
||||
///Pre-increment.
|
||||
///-------------------------------------------------------------------------
|
||||
template <typename P, typename T, bool R>
|
||||
IteratorOnPtr<P, T, R>& IteratorOnPtr<P, T, R>::operator++() {
|
||||
this->MoveIterator(1);
|
||||
return *this;
|
||||
}
|
||||
|
||||
///-------------------------------------------------------------------------
|
||||
///Post-increment.
|
||||
///-------------------------------------------------------------------------
|
||||
template <typename P, typename T, bool R>
|
||||
IteratorOnPtr<P, T, R> IteratorOnPtr<P, T, R>::operator++ (int) {
|
||||
IteratorOnPtr<P, T, R> retVal(*this);
|
||||
this->MoveIterator(1);
|
||||
return retVal;
|
||||
}
|
||||
|
||||
///-------------------------------------------------------------------------
|
||||
///Pre-decrement.
|
||||
///-------------------------------------------------------------------------
|
||||
template <typename P, typename T, bool R>
|
||||
IteratorOnPtr<P, T, R>& IteratorOnPtr<P, T, R>::operator--() {
|
||||
this->MoveIterator(-1);
|
||||
return *this;
|
||||
}
|
||||
|
||||
///-------------------------------------------------------------------------
|
||||
///Post-decrement.
|
||||
///-------------------------------------------------------------------------
|
||||
template <typename P, typename T, bool R>
|
||||
IteratorOnPtr<P, T, R> IteratorOnPtr<P, T, R>::operator-- (int) {
|
||||
IteratorOnPtr<P, T, R> retVal(*this);
|
||||
this->MoveIterator(-1);
|
||||
return retVal;
|
||||
}
|
||||
|
||||
///-------------------------------------------------------------------------
|
||||
///-------------------------------------------------------------------------
|
||||
template <typename P, typename T, bool R>
|
||||
typename IteratorOnPtr<P, T, R>::reference IteratorOnPtr<P, T, R>::operator*() {
|
||||
return *(this->m_pointer);
|
||||
}
|
||||
|
||||
///-------------------------------------------------------------------------
|
||||
///-------------------------------------------------------------------------
|
||||
template <typename P, typename T, bool R>
|
||||
typename IteratorOnPtr<P, T, R>::pointer IteratorOnPtr<P, T, R>::operator->() {
|
||||
return this->m_pointer;
|
||||
}
|
||||
|
||||
///-------------------------------------------------------------------------
|
||||
///-------------------------------------------------------------------------
|
||||
template <typename P, typename T, bool R>
|
||||
IteratorOnPtr<P, T, R> IteratorOnPtr<P, T, R>::operator+ (difference_type parOther) const {
|
||||
IteratorOnPtr<P, T, R> retVal(*this);
|
||||
retVal += parOther;
|
||||
return retVal;
|
||||
}
|
||||
|
||||
///-------------------------------------------------------------------------
|
||||
///-------------------------------------------------------------------------
|
||||
template <typename P, typename T, bool R>
|
||||
IteratorOnPtr<P, T, R> IteratorOnPtr<P, T, R>::operator- (difference_type parOther) const {
|
||||
IteratorOnPtr<P, T, R> retVal(*this);
|
||||
retVal -= parOther;
|
||||
return retVal;
|
||||
}
|
||||
|
||||
///-------------------------------------------------------------------------
|
||||
///-------------------------------------------------------------------------
|
||||
template <typename P, typename T, bool R>
|
||||
IteratorOnPtr<P, T, R>& IteratorOnPtr<P, T, R>::operator+= (difference_type parOther) {
|
||||
this->MoveIterator(parOther);
|
||||
return *this;
|
||||
}
|
||||
|
||||
///-------------------------------------------------------------------------
|
||||
///-------------------------------------------------------------------------
|
||||
template <typename P, typename T, bool R>
|
||||
IteratorOnPtr<P, T, R>& IteratorOnPtr<P, T, R>::operator-= (difference_type parOther) {
|
||||
this->MoveIterator(-parOther);
|
||||
return *this;
|
||||
}
|
||||
} //namespace dhandy
|
||||
|
||||
#endif
|
48
include/duckhandy/infix_iterator.hpp
Normal file
48
include/duckhandy/infix_iterator.hpp
Normal file
|
@ -0,0 +1,48 @@
|
|||
// see http://stackoverflow.com/questions/3496982/printing-lists-with-commas-c/3497021#3497021
|
||||
// infix_iterator.h
|
||||
//
|
||||
// Lifted from Jerry Coffin's 's prefix_ostream_iterator
|
||||
#if !defined(INFIX_ITERATOR_H_)
|
||||
#define INFIX_ITERATOR_H_
|
||||
#include <ostream>
|
||||
#include <iterator>
|
||||
template <class T,
|
||||
class charT=char,
|
||||
class traits=std::char_traits<charT> >
|
||||
class infix_ostream_iterator :
|
||||
public std::iterator<std::output_iterator_tag,void,void,void,void>
|
||||
{
|
||||
std::basic_ostream<charT,traits> *os;
|
||||
charT const* delimiter;
|
||||
bool first_elem;
|
||||
public:
|
||||
typedef charT char_type;
|
||||
typedef traits traits_type;
|
||||
typedef std::basic_ostream<charT,traits> ostream_type;
|
||||
infix_ostream_iterator(ostream_type& s)
|
||||
: os(&s),delimiter(0), first_elem(true)
|
||||
{}
|
||||
infix_ostream_iterator(ostream_type& s, charT const *d)
|
||||
: os(&s),delimiter(d), first_elem(true)
|
||||
{}
|
||||
infix_ostream_iterator<T,charT,traits>& operator=(T const &item)
|
||||
{
|
||||
// Here's the only real change from ostream_iterator:
|
||||
// Normally, the '*os << item;' would come before the 'if'.
|
||||
if (!first_elem && delimiter != 0)
|
||||
*os << delimiter;
|
||||
*os << item;
|
||||
first_elem = false;
|
||||
return *this;
|
||||
}
|
||||
infix_ostream_iterator<T,charT,traits> &operator*() {
|
||||
return *this;
|
||||
}
|
||||
infix_ostream_iterator<T,charT,traits> &operator++() {
|
||||
return *this;
|
||||
}
|
||||
infix_ostream_iterator<T,charT,traits> &operator++(int) {
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
#endif
|
37
include/duckhandy/lengthof.h
Normal file
37
include/duckhandy/lengthof.h
Normal file
|
@ -0,0 +1,37 @@
|
|||
/* Copyright 2016, Michele Santullo
|
||||
* This file is part of "duckhandy".
|
||||
*
|
||||
* "duckhandy" 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.
|
||||
*
|
||||
* "duckhandy" 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 "duckhandy". If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef id19B690A53A9546D5BD95D89FFF388283
|
||||
#define id19B690A53A9546D5BD95D89FFF388283
|
||||
|
||||
#if defined(__cplusplus)
|
||||
# include <cstddef>
|
||||
#else
|
||||
# include <stddef.h>
|
||||
#endif
|
||||
|
||||
#if defined(lengthof)
|
||||
# undef lengthof
|
||||
#endif
|
||||
//http://stackoverflow.com/questions/4415524/common-array-length-macro-for-c#4415646
|
||||
#if defined(__cplusplus)
|
||||
# define lengthof(x) ((sizeof(x)/sizeof(0[x])) / ((std::size_t)(!(sizeof(x) % sizeof(0[x])))))
|
||||
#else
|
||||
# define lengthof(x) ((sizeof(x)/sizeof(0[x])) / ((size_t)(!(sizeof(x) % sizeof(0[x])))))
|
||||
#endif
|
||||
|
||||
#endif
|
304
include/duckhandy/lexical_cast.hpp
Normal file
304
include/duckhandy/lexical_cast.hpp
Normal file
|
@ -0,0 +1,304 @@
|
|||
/* Copyright 2016, Michele Santullo
|
||||
* This file is part of "duckhandy".
|
||||
*
|
||||
* "duckhandy" 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.
|
||||
*
|
||||
* "duckhandy" 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 "duckhandy". If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef id942A6B5AB2AF443C82D4321775BFC9E8
|
||||
#define id942A6B5AB2AF443C82D4321775BFC9E8
|
||||
|
||||
#include "compatibility.h"
|
||||
#include "helpers/sequence_bt.hpp"
|
||||
#include "helpers/MaxSizedArray.hpp"
|
||||
#include "sprout/math/log10.hpp"
|
||||
#include "sprout/math/log2.hpp"
|
||||
#include "sprout/math/pow.hpp"
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
#include <limits>
|
||||
#include <cstdint>
|
||||
#include <algorithm>
|
||||
#include <string>
|
||||
#include <ciso646>
|
||||
#include <climits>
|
||||
#include <boost/range/adaptor/reversed.hpp>
|
||||
#include <cstddef>
|
||||
|
||||
namespace dhandy {
|
||||
namespace customize {
|
||||
template<typename T>
|
||||
struct index_array_to_string;
|
||||
|
||||
template<typename C, typename T>
|
||||
struct char_to_int;
|
||||
} //namespace customize
|
||||
|
||||
namespace implem {
|
||||
template <typename T>
|
||||
typename std::make_unsigned<T>::type abs ( T parValue ) a_pure;
|
||||
|
||||
template <typename T> int count_leading_zeroes ( typename std::enable_if<std::numeric_limits<T>::is_signed, T>::type parValue ) a_always_inline;
|
||||
template <typename T> int count_leading_zeroes ( typename std::enable_if<not std::numeric_limits<T>::is_signed, T>::type parValue ) a_always_inline;
|
||||
int count_leading_zeroes_overload ( unsigned char parValue ) a_always_inline;
|
||||
int count_leading_zeroes_overload ( unsigned short int parValue ) a_always_inline;
|
||||
int count_leading_zeroes_overload ( unsigned int parValue ) a_always_inline;
|
||||
int count_leading_zeroes_overload ( unsigned long parValue ) a_always_inline;
|
||||
int count_leading_zeroes_overload ( unsigned long long parValue ) a_always_inline;
|
||||
|
||||
template <std::size_t Base, std::size_t Val>
|
||||
struct power {
|
||||
enum { value = Base * power<Base, Val - 1>::value };
|
||||
};
|
||||
template <std::size_t Base>
|
||||
struct power<Base, 0> {
|
||||
enum { value = 1 };
|
||||
};
|
||||
|
||||
template <typename T, bool=std::numeric_limits<T>::is_signed>
|
||||
struct is_negative;
|
||||
template <typename T>
|
||||
struct is_negative<T, true> {
|
||||
static int check (T parValue) { return (parValue < 0 ? 1 : 0); }
|
||||
};
|
||||
template <typename T>
|
||||
struct is_negative<T, false> {
|
||||
static constexpr int check (T) { return 0; }
|
||||
};
|
||||
|
||||
template <template <typename> class Tag, typename T, typename F>
|
||||
inline auto int_to_string (const F parFrom) -> MaxSizedArray<uint8_t, Tag<F>::count_digits_bt(std::numeric_limits<typename std::make_unsigned<F>::type>::max())> {
|
||||
using ArrayRetType = MaxSizedArray<uint8_t, Tag<F>::count_digits_bt(std::numeric_limits<typename std::make_unsigned<F>::type>::max())>;
|
||||
|
||||
ArrayRetType retval;
|
||||
F div = 1;
|
||||
constexpr const std::size_t charset_offs = (Tag<F>::lower_case ? Tag<F>::base : 0);
|
||||
const auto sign_length = (is_negative<F>::check(parFrom) and Tag<F>::sign_allowed ? 1 : 0);
|
||||
for (std::size_t z = 0; z < Tag<F>::count_digits(parFrom) - sign_length; ++z) {
|
||||
retval.push_back(static_cast<uint8_t>(((Tag<F>::make_unsigned(parFrom) / div) % Tag<F>::base) + charset_offs));
|
||||
div *= Tag<F>::base;
|
||||
}
|
||||
std::reverse(retval.begin(), retval.end());
|
||||
return retval;
|
||||
};
|
||||
|
||||
template <template <typename> class Tag, typename T, typename F>
|
||||
inline T string_to_int (const F& parFrom) {
|
||||
T retval(0);
|
||||
T mul(1);
|
||||
for (auto chara : boost::adaptors::reverse(parFrom)) {
|
||||
retval += dhandy::customize::char_to_int<decltype(chara), T>::make(chara) * mul;
|
||||
mul *= Tag<T>::base;
|
||||
}
|
||||
return retval * dhandy::customize::char_to_int<typename F::value_type, T>::sgn(parFrom);
|
||||
};
|
||||
|
||||
template <typename T, bool LowerCase>
|
||||
struct hex {
|
||||
enum {
|
||||
base = 16,
|
||||
sign_allowed = 0,
|
||||
lower_case = (LowerCase ? 1 : 0)
|
||||
};
|
||||
|
||||
static std::size_t count_digits ( T parValue ) a_pure;
|
||||
static typename std::make_unsigned<T>::type make_unsigned ( T parValue ) a_pure;
|
||||
static constexpr std::size_t count_digits_bt (std::size_t parNum) {
|
||||
return (parNum == 0 ? 0 : static_cast<std::size_t>(sprout::log10(static_cast<double>(parNum)) / sprout::log10(static_cast<double>(base)))) + 1;
|
||||
}
|
||||
};
|
||||
} //namespace implem
|
||||
|
||||
namespace tags {
|
||||
template <typename T>
|
||||
struct dec {
|
||||
enum {
|
||||
base = 10,
|
||||
sign_allowed = 1,
|
||||
lower_case = 0
|
||||
};
|
||||
|
||||
template <std::size_t... Powers, std::size_t... Digits>
|
||||
static std::size_t count_digits_implem (T parValue, dhandy::bt::index_seq<Powers...>, dhandy::bt::index_seq<Digits...>) a_pure;
|
||||
|
||||
static std::size_t count_digits (T parValue) a_pure;
|
||||
|
||||
static typename std::make_unsigned<T>::type make_unsigned ( T parValue ) a_pure;
|
||||
static constexpr std::size_t count_digits_bt (std::size_t parNum) {
|
||||
return (parNum == 0 ? 0 : static_cast<std::size_t>(sprout::log10(static_cast<double>(parNum)))) + 1 + (std::numeric_limits<T>::is_signed ? 1 : 0);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
using hex = dhandy::implem::hex<T, false>;
|
||||
template <typename T>
|
||||
using hexl = dhandy::implem::hex<T, true>;
|
||||
|
||||
template <typename T>
|
||||
struct bin {
|
||||
enum {
|
||||
base = 2,
|
||||
sign_allowed = 0,
|
||||
lower_case = 0
|
||||
};
|
||||
|
||||
static std::size_t count_digits ( T parValue ) a_pure;
|
||||
static typename std::make_unsigned<T>::type make_unsigned ( T parValue ) a_pure;
|
||||
static constexpr std::size_t count_digits_bt (std::size_t parNum) {
|
||||
return (parNum == 0 ? 0 : static_cast<std::size_t>(sprout::log2(static_cast<double>(parNum)))) + 1;
|
||||
}
|
||||
};
|
||||
|
||||
//See: http://stackoverflow.com/questions/9721042/count-number-of-digits-which-method-is-most-efficient#9721113
|
||||
template <typename T>
|
||||
template <std::size_t... Powers, std::size_t... Digits>
|
||||
std::size_t dec<T>::count_digits_implem (T parValue, dhandy::bt::index_seq<Powers...>, dhandy::bt::index_seq<Digits...>) {
|
||||
typedef typename std::make_unsigned<T>::type UT;
|
||||
static constexpr UT powers[] = { 0, static_cast<UT>(dhandy::implem::power<10, Powers + 1>::value)... };
|
||||
static constexpr std::size_t maxdigits[] = { count_digits_bt(static_cast<std::size_t>(sprout::pow(2.0, Digits))) - (std::numeric_limits<T>::is_signed ? 1 : 0)... };
|
||||
const auto bits = sizeof(parValue) * CHAR_BIT - dhandy::implem::count_leading_zeroes<T>(dhandy::implem::abs(parValue));
|
||||
static_assert(std::is_same<UT, decltype(dhandy::implem::abs(parValue))>::value, "Unexpected type");
|
||||
return (dhandy::implem::abs(parValue) < powers[maxdigits[bits] - 1] ? maxdigits[bits] - 1 : maxdigits[bits]) + dhandy::implem::is_negative<T>::check(parValue);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
std::size_t dec<T>::count_digits (T parValue) {
|
||||
return count_digits_implem(
|
||||
parValue,
|
||||
dhandy::bt::index_range<0, count_digits_bt(std::numeric_limits<T>::max()) - (std::numeric_limits<T>::is_signed ? 1 : 0) - 1>(),
|
||||
dhandy::bt::index_range<0, CHAR_BIT * sizeof(T) + 1>()
|
||||
);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
typename std::make_unsigned<T>::type dec<T>::make_unsigned (T parValue) {
|
||||
return dhandy::implem::abs(parValue);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
std::size_t bin<T>::count_digits (T parValue) {
|
||||
return std::max<std::size_t>((sizeof(parValue) * CHAR_BIT - dhandy::implem::count_leading_zeroes<typename std::make_unsigned<T>::type>(make_unsigned(parValue))), 1);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
typename std::make_unsigned<T>::type bin<T>::make_unsigned (T parValue) {
|
||||
return static_cast<typename std::make_unsigned<T>::type>(parValue);
|
||||
}
|
||||
} //namespace tags
|
||||
|
||||
namespace implem {
|
||||
template <template <typename> class Tag>
|
||||
struct lexical_cast {
|
||||
template <typename T, typename F>
|
||||
static T convert ( const typename std::enable_if<std::is_integral<F>::value, F>::type& parFrom ) {
|
||||
const auto indices = int_to_string<Tag, T, F>(parFrom);
|
||||
return dhandy::customize::index_array_to_string<T>::make(indices, is_negative<F>::check(parFrom) bitand Tag<F>::sign_allowed);
|
||||
}
|
||||
|
||||
template <typename T, typename F>
|
||||
static typename std::enable_if<std::is_integral<T>::value, T>::type convert ( const F& parFrom ) {
|
||||
return string_to_int<Tag, T, F>(parFrom);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
inline int count_leading_zeroes (typename std::enable_if<std::numeric_limits<T>::is_signed, T>::type parValue) {
|
||||
return count_leading_zeroes<decltype(dhandy::implem::abs(parValue))>(dhandy::implem::abs(parValue));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline int count_leading_zeroes (typename std::enable_if<not std::numeric_limits<T>::is_signed, T>::type parValue) {
|
||||
return count_leading_zeroes_overload(parValue) + sizeof(T) * CHAR_BIT;
|
||||
}
|
||||
|
||||
inline int count_leading_zeroes_overload (unsigned char parValue) {
|
||||
return __builtin_clz(parValue) - sizeof(unsigned int) * CHAR_BIT;
|
||||
}
|
||||
inline int count_leading_zeroes_overload (unsigned short int parValue) {
|
||||
return __builtin_clz(parValue) - sizeof(unsigned int) * CHAR_BIT;
|
||||
}
|
||||
inline int count_leading_zeroes_overload (unsigned int parValue) {
|
||||
return __builtin_clz(parValue) - sizeof(unsigned int) * CHAR_BIT;
|
||||
}
|
||||
inline int count_leading_zeroes_overload (unsigned long parValue) {
|
||||
return __builtin_clzl(parValue) - sizeof(unsigned long) * CHAR_BIT;
|
||||
}
|
||||
inline int count_leading_zeroes_overload (unsigned long long parValue) {
|
||||
return __builtin_clzll(parValue) - sizeof(unsigned long long) * CHAR_BIT;
|
||||
}
|
||||
|
||||
//See: http://stackoverflow.com/questions/16101062/why-does-stdabs-return-signed-types
|
||||
template <typename T>
|
||||
typename std::make_unsigned<T>::type abs (T parValue) {
|
||||
//We need to cast before negating x to avoid the overflow.
|
||||
return (parValue < 0 ? -static_cast<typename std::make_unsigned<T>::type>(parValue) : parValue);
|
||||
}
|
||||
|
||||
template <typename T, bool LowerCase>
|
||||
std::size_t hex<T, LowerCase>::count_digits (T parValue) {
|
||||
return std::max<std::size_t>(((sizeof(parValue) * CHAR_BIT - dhandy::implem::count_leading_zeroes<typename std::make_unsigned<T>::type>(make_unsigned(parValue))) + (CHAR_BIT / 2 - 1)) / (CHAR_BIT / 2), 1);
|
||||
}
|
||||
|
||||
template <typename T, bool LowerCase>
|
||||
typename std::make_unsigned<T>::type hex<T, LowerCase>::make_unsigned (T parValue) {
|
||||
return static_cast<typename std::make_unsigned<T>::type>(parValue);
|
||||
}
|
||||
} //namespace implem
|
||||
|
||||
template <typename T, template <typename> class Tag=tags::dec, typename F=void>
|
||||
inline T lexical_cast (const F& parFrom) {
|
||||
return dhandy::implem::lexical_cast<Tag>::template convert<T, F>(parFrom);
|
||||
}
|
||||
|
||||
namespace customize {
|
||||
template<>
|
||||
struct index_array_to_string<std::string> {
|
||||
template<std::size_t N>
|
||||
static std::string make (const MaxSizedArray<uint8_t, N> &parIndices, int parNegative) {
|
||||
static const char symbols[] = {'0', '1', '2', '3', '4', '5',
|
||||
'6', '7', '8', '9', 'A', 'B',
|
||||
'C', 'D', 'E', 'F',
|
||||
'0', '1', '2', '3', '4', '5',
|
||||
'6', '7', '8', '9', 'a', 'b',
|
||||
'c', 'd', 'e', 'f'
|
||||
};
|
||||
std::string retval(parIndices.size() + parNegative, '-');
|
||||
for (auto z = parNegative; z < static_cast<int>(parIndices.size()) + parNegative; ++z) {
|
||||
retval[z] = symbols[parIndices[z - parNegative]];
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct char_to_int<char, T> {
|
||||
static T make (char parChar) {
|
||||
if (parChar >= '0' and parChar <= '9')
|
||||
return parChar - '0';
|
||||
else if (parChar >= 'a' and parChar <= 'f')
|
||||
return 10 + parChar - 'a';
|
||||
else if (parChar >= 'A' and parChar <= 'F')
|
||||
return 10 + parChar - 'A';
|
||||
else if (parChar == '-')
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
template <typename Container>
|
||||
static T sgn (const Container& parString) {
|
||||
return static_cast<T>(std::numeric_limits<T>::is_signed and parString.begin() != parString.end() and *parString.begin() == '-' ? -1 : 1);
|
||||
}
|
||||
};
|
||||
} //namespace customize
|
||||
} //namespace dhandy
|
||||
#endif
|
54
include/duckhandy/sequence_bt.hpp
Normal file
54
include/duckhandy/sequence_bt.hpp
Normal file
|
@ -0,0 +1,54 @@
|
|||
/* Copyright 2016, Michele Santullo
|
||||
* This file is part of "duckhandy".
|
||||
*
|
||||
* "duckhandy" 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.
|
||||
*
|
||||
* "duckhandy" 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 "duckhandy". If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef id4FAEF395B9ED47CB9D6B50B54C9A289A
|
||||
#define id4FAEF395B9ED47CB9D6B50B54C9A289A
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
namespace dhandy {
|
||||
namespace bt {
|
||||
template <typename T, T... I>
|
||||
struct number_seq {
|
||||
};
|
||||
|
||||
template <std::size_t... I>
|
||||
using index_seq = number_seq<std::size_t, I...>;
|
||||
|
||||
namespace implem {
|
||||
template <typename T, T MIN, T MAX, T... I>
|
||||
struct range_builder;
|
||||
|
||||
template <typename T, T MIN, T... I>
|
||||
struct range_builder<T, MIN, MIN, I...> {
|
||||
typedef number_seq<T, I...> type;
|
||||
};
|
||||
|
||||
template <typename T, T MIN, T N, T... I>
|
||||
struct range_builder : public range_builder<T, MIN, N - 1, N - 1, I...> {
|
||||
};
|
||||
} //namespace implem
|
||||
|
||||
template <typename T, T MIN, T MAX>
|
||||
using number_range = typename implem::range_builder<T, MIN, MAX>::type;
|
||||
|
||||
template <std::size_t MIN, std::size_t MAX>
|
||||
using index_range = number_range<std::size_t, MIN, MAX>;
|
||||
} //namespace bt
|
||||
} //namespace dhandy
|
||||
|
||||
#endif
|
112
include/duckhandy/string_bt.hpp
Normal file
112
include/duckhandy/string_bt.hpp
Normal file
|
@ -0,0 +1,112 @@
|
|||
/* Copyright 2016, Michele Santullo
|
||||
* This file is part of "duckhandy".
|
||||
*
|
||||
* "duckhandy" 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.
|
||||
*
|
||||
* "duckhandy" 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 "duckhandy". If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef id170B0E6C34D14EBA9B92A35977BDBFB3
|
||||
#define id170B0E6C34D14EBA9B92A35977BDBFB3
|
||||
|
||||
#include "sequence_bt.hpp"
|
||||
#include <cstddef>
|
||||
#include <iostream>
|
||||
#include <stdexcept>
|
||||
|
||||
namespace dhandy {
|
||||
namespace bt {
|
||||
template <std::size_t S>
|
||||
class string;
|
||||
|
||||
template <std::size_t S>
|
||||
std::ostream& operator<< ( std::ostream& parStream, const string<S>& parString );
|
||||
|
||||
template <std::size_t S>
|
||||
class string {
|
||||
public:
|
||||
friend std::ostream& operator<< <>( std::ostream& parStream, const string<S>& parString );
|
||||
constexpr string ( const char* parString );
|
||||
|
||||
constexpr std::size_t size ( void ) const { return S - 1; }
|
||||
template <std::size_t S2>
|
||||
constexpr string<S + S2 - 1> operator+ ( const string<S2>& parOther ) const;
|
||||
constexpr char operator[] ( std::size_t parIndex ) const;
|
||||
|
||||
template <typename... Args>
|
||||
constexpr string ( Args... );
|
||||
|
||||
constexpr const char (&data_arr() const)[S] { return m_data; }
|
||||
constexpr const char* data() const { return m_data; }
|
||||
|
||||
private:
|
||||
template <std::size_t... I>
|
||||
constexpr string ( const index_seq<I...>&, const char* parString );
|
||||
|
||||
const char m_data[S];
|
||||
};
|
||||
|
||||
namespace implem {
|
||||
template <std::size_t S, std::size_t S2, std::size_t... I>
|
||||
constexpr string<S + S2 - 1> concat ( const index_seq<I...>&, const string<S>& parLeft, const string<S2>& parRight ) {
|
||||
return string<S + S2 - 1>(
|
||||
(I < S - 1 ? parLeft[I] : (I < S + S2 - 2 ? parRight[I - (S - 1)] : '\0'))...
|
||||
);
|
||||
}
|
||||
|
||||
} //namespace implem
|
||||
|
||||
template <std::size_t S>
|
||||
template <std::size_t... I>
|
||||
constexpr string<S>::string (const index_seq<I...>&, const char* parString) :
|
||||
m_data{parString[I]...}
|
||||
{
|
||||
}
|
||||
|
||||
template <std::size_t S>
|
||||
inline constexpr string<S>::string (const char* parString) :
|
||||
string(index_range<0, S>(), parString)
|
||||
{
|
||||
}
|
||||
|
||||
template <std::size_t S>
|
||||
template <typename... Args>
|
||||
inline constexpr string<S>::string (Args... parArgs) :
|
||||
m_data{parArgs...}
|
||||
{
|
||||
}
|
||||
|
||||
template <std::size_t S>
|
||||
template <std::size_t S2>
|
||||
constexpr inline string<S + S2 - 1> string<S>::operator+ (const string<S2>& parOther) const {
|
||||
return implem::concat(index_range<0, S + S2 - 1>(), string<S>(m_data), parOther);
|
||||
}
|
||||
|
||||
template <std::size_t S>
|
||||
inline std::ostream& operator<< (std::ostream& parStream, const string<S>& parString) {
|
||||
parStream << parString.m_data;
|
||||
return parStream;
|
||||
}
|
||||
|
||||
template <std::size_t S>
|
||||
constexpr char string<S>::operator[] (std::size_t parIndex) const {
|
||||
return (parIndex < S ? m_data[parIndex] : throw std::out_of_range(""));
|
||||
}
|
||||
|
||||
template <std::size_t S>
|
||||
constexpr string<S> make_string (const char (&parData)[S]) {
|
||||
return string<S>(parData);
|
||||
}
|
||||
} //namespace bt
|
||||
} //namespace dhandy
|
||||
|
||||
#endif
|
24
include/duckhandy/stringize.h
Normal file
24
include/duckhandy/stringize.h
Normal file
|
@ -0,0 +1,24 @@
|
|||
/* Copyright 2016, Michele Santullo
|
||||
* This file is part of "duckhandy".
|
||||
*
|
||||
* "duckhandy" 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.
|
||||
*
|
||||
* "duckhandy" 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 "duckhandy". If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef id8B9FF1807C05459DAE8CD05312147416
|
||||
#define id8B9FF1807C05459DAE8CD05312147416
|
||||
|
||||
#define STRINGIZE_IMPL(s) #s
|
||||
#define STRINGIZE(s) STRINGIZE_IMPL(s)
|
||||
|
||||
#endif
|
Loading…
Add table
Add a link
Reference in a new issue