Repo init with mostly unchanged import of LW code

This commit is contained in:
Emmanuel BENOîT 2017-11-01 20:14:23 +01:00
commit 221f0c8ef8
161 changed files with 61414 additions and 0 deletions

3
.gitignore vendored Normal file
View file

@ -0,0 +1,3 @@
.vim.local/signature
.vim.local/data
output/*

View file

@ -0,0 +1 @@
let g:ycm_global_ycm_extra_conf = g:vim_local_path . "/ycm_extra_conf.py"

View file

@ -0,0 +1 @@
NeoBundle "Valloric/YouCompleteMe"

View file

@ -0,0 +1,2 @@
let g:uncrustify_cfg_file_path = g:vim_local_path . "/../coding-style-uncrustify.cfg"

View file

@ -0,0 +1 @@
NeoBundle "cofyc/vim-uncrustify"

View file

@ -0,0 +1,42 @@
let g:vimmake_path = g:vim_local_path . 'scripts'
let g:vimmake_mode = {}
let g:vimmake_mode['clean'] = 'async'
let g:vimmake_mode['build'] = 'async'
let g:vimmake_mode['rebuild'] = 'async'
let g:vimmake_mode['test'] = 'async'
function! DoBuild(full)
silent call vimmake#toggle_quickfix(12,1)
if a:full == 0
VimTool build
else
VimTool rebuild
endif
endfunc
function! KillBuild()
silent call vimmake#toggle_quickfix(0)
VimStop
endfunc
function! RunTest()
silent call vimmake#toggle_quickfix(12,1)
VimTool test
endfunc
augroup QuickfixStatus
au! BufWinEnter quickfix setlocal
\ statusline=%t\ [%{g:vimmake_build_status}]\ %{exists('w:quickfix_title')?\ '\ '.w:quickfix_title\ :\ ''}\ %=%-15(%l,%c%V%)\ %P
augroup END
noremap <F12> :silent call vimmake#toggle_quickfix(12)<cr>
inoremap <F12> <esc>:silent call vimmake#toggle_quickfix(12)<cr>li
noremap <F10> :silent call DoBuild(0)<cr>
inoremap <F10> <esc>:silent call DoBuild(0)<cr>li
noremap <S-F10> :silent call DoBuild(1)<cr>
inoremap <S-F10> <esc>:silent call DoBuild(1)<cr>li
noremap <C-F10> :silent call KillBuild()<cr>
inoremap <C-F10> <esc>:silent call KillBuild()<cr>li
noremap <F11> :silent call RunTest()<cr>
inoremap <F11> <esc>:silent call RunTest()<cr>li

View file

@ -0,0 +1 @@
NeoBundle 'skywind3000/vimmake'

View file

@ -0,0 +1,3 @@
setlocal colorcolumn=121
noremap <buffer> <C-f> :call Uncrustify('cpp')<CR>
vnoremap <buffer> <C-f> :call RangeUncrustify('cpp')<CR>

1
.vim.local/ftplugin/srd.vim Symbolic link
View file

@ -0,0 +1 @@
../../data/srd-ftplugin.vim

View file

@ -0,0 +1,2 @@
#!/bin/sh
make -j 8 all

View file

@ -0,0 +1,2 @@
#!/bin/sh
make clean-extra

View file

@ -0,0 +1,3 @@
#!/bin/sh
make clean-extra
make -j 8 all

14
.vim.local/scripts/vimmake.test Executable file
View file

@ -0,0 +1,14 @@
#!/bin/bash
if [ "$VIM_RELDIR" = "tests" ] && [ "$VIM_FILEEXT" = ".cc" ]; then
if make -j 8 all; then
if [ -f "output/fast/test-$VIM_FILENOEXT" ]; then
LD_LIBRARY_PATH=./output/fast \
./output/fast/test-$VIM_FILENOEXT 2>&1 \
| sed -e s/"$VIM_FILENAME"/'tests\/'"$VIM_FILENAME"/g
else
LD_LIBRARY_PATH=./output/fast \
./output/fast/run-all-tests 2>&1 \
| sed -e 's/^\([a-z\-]\+\.cc\)/tests\/\1/g'
fi
fi
fi

1
.vim.local/syntax/srd.vim Symbolic link
View file

@ -0,0 +1 @@
../../data/srd-syntax.vim

7
.vim.local/vimrc Normal file
View file

@ -0,0 +1,7 @@
let g:vim_local = {
\ "vardata" : g:vim_local_path . "/data"
\ }
au BufNewFile,BufRead *.srd setf srd
"let &wildignore=&wildignore . ',glef.c,glef.h'

View file

@ -0,0 +1,143 @@
# This file is NOT licensed under the GPLv3, which is the license for the rest
# of YouCompleteMe.
#
# Here's the license text for this file:
#
# This is free and unencumbered software released into the public domain.
#
# Anyone is free to copy, modify, publish, use, compile, sell, or
# distribute this software, either in source code form or as a compiled
# binary, for any purpose, commercial or non-commercial, and by any
# means.
#
# In jurisdictions that recognize copyright laws, the author or authors
# of this software dedicate any and all copyright interest in the
# software to the public domain. We make this dedication for the benefit
# of the public at large and to the detriment of our heirs and
# successors. We intend this dedication to be an overt act of
# relinquishment in perpetuity of all present and future rights to this
# software under copyright law.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
# IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
# OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
# OTHER DEALINGS IN THE SOFTWARE.
#
# For more information, please refer to <http://unlicense.org/>
import os
import ycm_core
# These are the compilation flags that will be used in case there's no
# compilation database set (by default, one is not set).
# CHANGE THIS LIST OF FLAGS. YES, THIS IS THE DROID YOU HAVE BEEN LOOKING FOR.
flags = [
'-Wall',
'-Wextra',
'-Werror',
'-Wno-long-long',
'-Wno-variadic-macros',
'-fexceptions',
'-std=c++14',
'-x',
'c++',
'-I' ,
'./include'
]
# Set this to the absolute path to the folder (NOT the file!) containing the
# compile_commands.json file to use that instead of 'flags'. See here for
# more details: http://clang.llvm.org/docs/JSONCompilationDatabase.html
#
# You can get CMake to generate this file for you by adding:
# set( CMAKE_EXPORT_COMPILE_COMMANDS 1 )
# to your CMakeLists.txt file.
#
# Most projects will NOT need to set this to anything; you can just change the
# 'flags' list of compilation flags. Notice that YCM itself uses that approach.
compilation_database_folder = ''
if os.path.exists( compilation_database_folder ):
database = ycm_core.CompilationDatabase( compilation_database_folder )
else:
database = None
SOURCE_EXTENSIONS = [ '.cpp', '.cxx', '.cc', '.c', '.m', '.mm' ]
def DirectoryOfThisScript():
return os.path.dirname( os.path.dirname( os.path.abspath( __file__ ) ) )
def MakeRelativePathsInFlagsAbsolute( flags, working_directory ):
if not working_directory:
return list( flags )
new_flags = []
make_next_absolute = False
path_flags = [ '-isystem', '-I', '-iquote', '--sysroot=' ]
for flag in flags:
new_flag = flag
if make_next_absolute:
make_next_absolute = False
if not flag.startswith( '/' ):
new_flag = os.path.join( working_directory, flag )
for path_flag in path_flags:
if flag == path_flag:
make_next_absolute = True
break
if flag.startswith( path_flag ):
path = flag[ len( path_flag ): ]
new_flag = path_flag + os.path.join( working_directory, path )
break
if new_flag:
new_flags.append( new_flag )
return new_flags
def IsHeaderFile( filename ):
extension = os.path.splitext( filename )[ 1 ]
return extension in [ '.h', '.hxx', '.hpp', '.hh' ]
def GetCompilationInfoForFile( filename ):
# The compilation_commands.json file generated by CMake does not have entries
# for header files. So we do our best by asking the db for flags for a
# corresponding source file, if any. If one exists, the flags for that file
# should be good enough.
if IsHeaderFile( filename ):
basename = os.path.splitext( filename )[ 0 ]
for extension in SOURCE_EXTENSIONS:
replacement_file = basename + extension
if os.path.exists( replacement_file ):
compilation_info = database.GetCompilationInfoForFile(
replacement_file )
if compilation_info.compiler_flags_:
return compilation_info
return None
return database.GetCompilationInfoForFile( filename )
def FlagsForFile( filename, **kwargs ):
if database:
# Bear in mind that compilation_info.compiler_flags_ does NOT return a
# python list, but a "list-like" StringVec object
compilation_info = GetCompilationInfoForFile( filename )
if not compilation_info:
return None
final_flags = MakeRelativePathsInFlagsAbsolute(
compilation_info.compiler_flags_,
compilation_info.compiler_working_dir_ )
else:
relative_to = DirectoryOfThisScript()
final_flags = MakeRelativePathsInFlagsAbsolute( flags, relative_to )
return { 'flags': final_flags }

240
include/ebcl/Alloc.hh Normal file
View file

@ -0,0 +1,240 @@
/******************************************************************************/
/* ALLOCATORS *****************************************************************/
/******************************************************************************/
#ifndef _H_EBCL_ALLOC
#define _H_EBCL_ALLOC
#include <lw/lib/Config.hh>
#include <lw/lib/Utilities.hh>
#include <atomic>
namespace lw {
/* Helpers for pool allocators. */
struct T_PoolHelper
{
/* Storage type for an object */
template<
size_t ObjectSize ,
size_t ObjectAlign
> using T_Object = std::aligned_storage_t< ObjectSize , ObjectAlign >;
/* List of object storage items. The storage type is assumed to
* have a void* field called list.
*/
template<
typename T_Storage ,
size_t ListSize
> struct T_List final
{
static constexpr size_t BitmapSize
= ( ListSize / 8 ) + ( ListSize % 8 ? 1 : 0 );
using T_Self = T_List< T_Storage , ListSize >;
T_Storage storage[ ListSize ]; // Stored data
T_Self* next; // Next list in chain
size_t free; // Free objects
uint8_t bitmap[ BitmapSize ]; // Allocation map
T_List( ) = delete;
T_List( T_Self const& ) = delete;
T_List( T_Self&& ) = delete;
// Create a new list, replacing the chain's head
explicit T_List( T_Self*& head ) noexcept;
// Find an unused item in the list. The list must have free
// items.
T_Storage* findUnused( ) noexcept;
// Find the index of an item. The item must be part of the list.
size_t indexOf( T_Storage const* item ) noexcept;
// Destroy a complete chain of lists
static void destroy( T_Self*& head ) noexcept;
};
/* The core of a pool allocator */
template<
typename T_Storage ,
size_t PerList ,
size_t MaxFreeLists
> struct T_Allocator final
{
static_assert( PerList > 1 , "allocator lists must contain at least 2 items" );
static_assert( MaxFreeLists > 0 , "allocator must have at least 1 free list" );
using T_List_ = T_List< T_Storage , PerList >;
using T_Self = T_Allocator< T_Storage , PerList , MaxFreeLists >;
// The chains
T_List_* free_;
T_List_* partial_;
T_List_* full_;
size_t nFree_;
T_Allocator( ) noexcept;
~T_Allocator( );
T_Allocator( T_Self const& ) = delete;
T_Allocator( T_Self&& ) = delete;
/* Allocate an object. */
T_Storage* allocate( ) noexcept;
/* Free an object */
void free( T_Storage* item ) noexcept;
/* Get the amount of lists. Mostly used for testing. */
size_t countFreeLists( ) const noexcept;
size_t countPartialLists( ) const noexcept;
size_t countFullLists( ) const noexcept;
/* Get the amount of total, free and used objects */
void getUsage( size_t& total ,
size_t& free ,
size_t& used ) const noexcept;
private:
/* Move a list of objects from one of the allocation lists to another. */
static void moveList(
T_List_* list ,
T_List_*& from ,
T_List_*& to ) noexcept;
/* Count the amount of lists in an allocation list */
static size_t countLists(
T_List_ const* head ) noexcept;
};
};
/*============================================================================*/
/* The pool allocator implements a thread-unsafe pool of objects, similar to a
* slab allocator.
*/
template<
size_t ObjectSize , size_t ObjectAlign ,
size_t PerList = std::max( size_t( 8 ) , 4096u / ObjectSize ) ,
size_t MaxFreeLists = 4
>
class T_PoolAllocator
{
public:
using T_Self = T_PoolAllocator< ObjectSize , ObjectAlign , PerList , MaxFreeLists >;
private:
// Structure that stores a single allocated item
struct T_Storage_ final
{
T_PoolHelper::T_Object< ObjectSize , ObjectAlign > data;
void* list;
};
using T_Alloc_ = T_PoolHelper::T_Allocator< T_Storage_ , PerList , MaxFreeLists >;
T_Alloc_ alloc_;
public:
T_PoolAllocator( ) noexcept = default;
T_PoolAllocator( T_Self const& ) = delete;
T_PoolAllocator( T_Self&& ) = delete;
/* Allocate an object. */
void* allocate( size_t requested ) noexcept;
/* Free an object */
void free( void* item ) noexcept;
/* Get the amount of lists. Mostly used for testing. */
size_t countFreeLists( ) const noexcept;
size_t countPartialLists( ) const noexcept;
size_t countFullLists( ) const noexcept;
/* Get the amount of total, free and used objects */
void getUsage( size_t& total ,
size_t& free ,
size_t& used ) const noexcept;
};
/*============================================================================*/
/* Pool allocator with multithreading support. Allocation is performed from
* a thread-specific pool allocator; when the memory is freed, the memory is
* either returned directly to the pool if the freeing thread is the same as
* the allocating thread, or queued for the original thread to free later.
*/
template<
size_t ObjectSize , size_t ObjectAlign ,
size_t PerList = std::max( size_t( 8 ) , 4096u / ObjectSize ) ,
size_t MaxFreeLists = 4
>
class T_ThreadedPoolAllocator
{
public:
using T_Self = T_ThreadedPoolAllocator<
ObjectSize , ObjectAlign , PerList , MaxFreeLists >;
private:
// Pointer to either the owning pool or the next object in the
// pending list
struct T_Storage_;
union T_ExtraPointer_
{
T_Storage_* next;
T_Self* pool;
};
// Structure that stores a single allocated item
struct T_Storage_ final
{
T_PoolHelper::T_Object< ObjectSize , ObjectAlign > data;
void* list;
T_ExtraPointer_ extra;
};
// The head for the "remote" freeing stack
struct T_FreeHead_ final
{
uintptr_t aba{ 0 };
T_Storage_* head{ nullptr };
};
// Atomic stack head, plus padding to prevent false sharing between
// the stack head and the actual allocator.
char padding_0_[ 64 ];
std::atomic< T_FreeHead_ > freeHead_;
char padding_1_[ 64 - sizeof( std::atomic< T_FreeHead_ > ) ];
using T_Alloc_ = T_PoolHelper::T_Allocator<
T_Storage_ , PerList , MaxFreeLists >;
T_Alloc_ alloc_;
public:
T_ThreadedPoolAllocator( ) noexcept = default;
T_ThreadedPoolAllocator( T_Self const& ) = delete;
T_ThreadedPoolAllocator( T_Self&& ) = delete;
/* Allocate an object. */
void* allocate( size_t requested ) noexcept;
/* Free an object */
void free( void* item ) noexcept;
/* Get the amount of lists. Mostly used for testing. */
size_t countFreeLists( ) const noexcept;
size_t countPartialLists( ) const noexcept;
size_t countFullLists( ) const noexcept;
/* Get the amount of total, free and used objects */
void getUsage( size_t& total ,
size_t& free ,
size_t& used ) const noexcept;
private:
// Try to take an item from the stack.
T_Storage_* takeFromStack( ) noexcept;
// Add an item to the stack
void addToStack( T_Storage_* item ) noexcept;
};
}
#endif //_H_EBCL_ALLOC
#include <lw/lib/inline/Alloc.hh>

446
include/ebcl/Arrays.hh Normal file
View file

@ -0,0 +1,446 @@
/******************************************************************************/
/* ARRAYS *********************************************************************/
/******************************************************************************/
#ifndef _H_EBCL_ARRAYS
#define _H_EBCL_ARRAYS
#include <lw/lib/Externals.hh>
#include <lw/lib/Pointers.hh>
#include <lw/lib/Utilities.hh>
#include <lw/lib/Types.hh>
namespace lw {
/*= DYNAMIC ARRAYS ===========================================================*/
template< class T >
class T_Array final
{
public:
static constexpr uint32_t DEFAULT_GROWTH( )
{
return std::max< uint32_t >( 1 , 4096 / sizeof( T ) );
}
private:
typedef T_Array< T > MyType_;
T* data_;
uint32_t capacity_;
uint32_t size_;
uint32_t growth_;
public:
M_TEMPLATE_POINTERS( MyType_ );
T_Array( ) noexcept;
explicit T_Array( uint32_t growth ) noexcept;
// ---------------------------------------------------------------------
T_Array( MyType_ const& source ) noexcept;
MyType_& operator= ( MyType_ const& other ) noexcept;
T_Array( MyType_&& source ) noexcept;
MyType_& operator= ( MyType_&& other ) noexcept;
template< typename TP >
friend void swap( T_Array< TP >& lhs ,
T_Array< TP >& rhs ) noexcept;
// ---------------------------------------------------------------------
~T_Array( );
MyType_& clear( ) noexcept;
MyType_& free( ) noexcept;
// ---------------------------------------------------------------------
uint32_t capacity( ) const noexcept;
uint32_t size( ) const noexcept;
uint32_t growth( ) const noexcept;
MyType_& ensureCapacity( uint32_t capacity ) noexcept;
// ---------------------------------------------------------------------
T& operator[] ( uint32_t index ) noexcept;
T const& operator[] ( uint32_t index ) const noexcept;
int32_t indexOf( T const& item ) const noexcept;
bool contains( T const& item ) const noexcept;
// ---------------------------------------------------------------------
uint32_t add( T const& item ) noexcept;
uint32_t add( T&& item ) noexcept;
template< typename... Args >
T& addNew( Args&& ... args );
// ---------------------------------------------------------------------
MyType_& addAll( MyType_ const& other ) noexcept;
MyType_& addAll( MyType_&& other ) noexcept;
// ---------------------------------------------------------------------
MyType_& operator<< ( T const& item ) noexcept;
MyType_& operator<< ( T&& item ) noexcept;
MyType_& operator<< ( MyType_ const& other ) noexcept;
MyType_& operator<< ( MyType_&& other ) noexcept;
// ---------------------------------------------------------------------
void insert( uint32_t index ,
T const& item ) noexcept;
void insert( uint32_t index ,
T&& item ) noexcept;
template< typename... Args >
T& insertNew( uint32_t index ,
Args&& ... args );
// ---------------------------------------------------------------------
void remove( uint32_t index ) noexcept;
void removeSwap( uint32_t index ) noexcept;
// ---------------------------------------------------------------------
void sort( F_Comparator< T > cmp = T_Comparator< T >::compare ) noexcept;
void sort( uint32_t first ,
uint32_t items ,
F_Comparator< T > cmp = T_Comparator< T >::compare ) noexcept;
// ---------------------------------------------------------------------
MyType_ copyRange( uint32_t first ,
uint32_t last = UINT32_MAX ) const noexcept;
MyType_ moveRange( uint32_t first ,
uint32_t last = UINT32_MAX ) noexcept;
};
// Instantiate some common types directly
extern template class T_Array< uint32_t >;
/*= STATICALLY ALLOCATED ARRAYS ==============================================*/
/* These arrays offer the same interface as dynamic arrays, but are in fact
* implemented as in-place storage.
*/
template< typename Type , uint32_t Size >
class T_StaticArray final
{
static_assert( Size > 0 , "Size must be greater than 0" );
public:
using T_Self = T_StaticArray< Type , Size >;
private:
// Actual storage type
using T_Storage_ = std::aligned_storage_t<
sizeof( Type ) , alignof( Type )
>;
T_Storage_ storage_[ Size ];
uint32_t size_;
public:
M_TEMPLATE_POINTERS( T_Self );
T_StaticArray( ) noexcept;
// Copy
T_StaticArray( T_Self const& source ) noexcept;
T_Self& operator= ( T_Self const& other ) noexcept;
// Move
T_StaticArray( T_Self&& source ) noexcept;
T_Self& operator= ( T_Self&& other ) noexcept;
~T_StaticArray( ) noexcept;
T_Self& clear( ) noexcept;
template< typename T , uint32_t S >
friend void swap(
T_StaticArray< T , S >& lhs ,
T_StaticArray< T , S >& rhs ) noexcept;
// ---------------------------------------------------------------------
constexpr uint32_t capacity( ) const noexcept;
uint32_t size( ) const noexcept;
// ---------------------------------------------------------------------
Type& operator[] ( uint32_t index ) noexcept;
Type const& operator[] ( uint32_t index ) const noexcept;
int32_t indexOf( Type const& item ) const noexcept;
bool contains( Type const& item ) const noexcept;
// ---------------------------------------------------------------------
uint32_t add( Type&& item ) noexcept;
uint32_t add( Type const& item ) noexcept;
template< typename... Args >
Type& addNew( Args&& ... args );
// ---------------------------------------------------------------------
T_Self& addAll( T_Self const& other ) noexcept;
T_Self& addAll( T_Self&& other ) noexcept;
// ---------------------------------------------------------------------
T_Self& operator<< ( Type const& item ) noexcept;
T_Self& operator<< ( Type&& item ) noexcept;
T_Self& operator<< ( T_Self const& other ) noexcept;
T_Self& operator<< ( T_Self&& other ) noexcept;
// ---------------------------------------------------------------------
void insert( uint32_t index ,
Type&& item ) noexcept;
void insert( uint32_t index ,
Type const& item ) noexcept;
template< typename... Args >
Type& insertNew( uint32_t index ,
Args&& ... args );
// ---------------------------------------------------------------------
void remove( uint32_t index ) noexcept;
void removeSwap( uint32_t index ) noexcept;
// ---------------------------------------------------------------------
void sort( F_Comparator< Type > cmp = T_Comparator< Type >::compare ) noexcept;
void sort( uint32_t first ,
uint32_t items ,
F_Comparator< Type > cmp = T_Comparator< Type >::compare ) noexcept;
// ---------------------------------------------------------------------
T_Self copyRange( uint32_t first ,
uint32_t last = UINT32_MAX ) const noexcept;
T_Self moveRange( uint32_t first ,
uint32_t last = UINT32_MAX ) noexcept;
};
/*= MULTI-ARRAYS ============================================================-*/
/*
* Arrays that allow storing multiple values for one entry. Values must be
* added in order.
*/
template< typename T >
class T_MultiArray
{
public:
using T_Data = T_Array< T >;
private:
typedef T_MultiArray< T > MyType_;
T_Array< uint32_t > meta_;
T_Data values_;
public:
M_TEMPLATE_POINTERS( T_MultiArray );
template< typename TP >
friend void swap( T_MultiArray< TP >& lhs , T_MultiArray< TP >& rhs );
// Start the next entry
void next( );
// Add a value to the current entry
void add( T value );
// Add a value, calling its constructor
template<
typename Q = T ,
typename... Args ,
typename = std::enable_if_t< std::is_class< Q >::value >
>
Q& addNew( Args&& ... args );
// Copy an array's contents into the current entry
void copyFrom( T_Data const& source );
// Returns the amount of entries
uint32_t size( ) const;
// Returns the index of the first value for an entry
uint32_t firstOf( uint32_t item ) const;
// Returns the amount of values for an entry
uint32_t sizeOf( uint32_t item ) const;
// Access a value in an entry
T const& get( uint32_t item , uint32_t sub ) const;
T& get( uint32_t item , uint32_t sub );
// Access a value using its index
T const& operator[] ( uint32_t index ) const;
T& operator[] ( uint32_t index );
// Is a value present in an entry?
bool contains( uint32_t index , T const& value ) const;
// Reset storage, don't free memory
void clear( );
// Reset storage and free memory
void free( );
// Copy values from an entry into the current entry
void copyFrom( uint32_t index );
// Copy another multi-array's entry into the current entry
void copyFrom( MyType_ const& other , uint32_t index );
// Copy values from another entry into the current entry if
// they are not already present. Duplicate entries in the
// source array are still copied, though.
void copyUnique( uint32_t index );
// Copy another multi-array's entry into the current entry,
// ignoring values that are already present. Duplicates in
// the source array are still copied.
void copyUnique( MyType_ const& other , uint32_t index );
// Sort an entry's values
void sort( uint32_t index , F_Comparator< T > cmp = T_Comparator< T >::compare );
};
// Instantiate some common types directly
extern template class T_MultiArray< uint32_t >;
/*= AUTOMATIC ARRAYS =========================================================*/
/* Arrays that are stored in-place up to some limit, then transform into
* dynamic arrays if necessary.
*/
template<
typename T , uint32_t StaticSize ,
uint32_t DynamicGrowth = StaticSize * 4
> class T_AutoArray
{
public:
using T_Self = T_AutoArray< T , StaticSize , DynamicGrowth >;
private:
using T_Static_ = T_StaticArray< T , StaticSize >;
using T_Dynamic_ = T_Array< T >;
T_Union< T_Static_ , T_Dynamic_ > array_;
// ---------------------------------------------------------------------
public:
M_TEMPLATE_POINTERS( T_Self );
T_AutoArray( ) noexcept;
T_AutoArray( T_Self const& source ) noexcept;
T_Self& operator =( T_Self const& source ) noexcept;
T_AutoArray( T_Self&& source ) noexcept;
T_Self& operator =( T_Self&& source ) noexcept;
// ---------------------------------------------------------------------
template< typename TP , uint32_t S , uint32_t G >
friend void swap(
T_AutoArray< TP , S , G >& lhs ,
T_AutoArray< TP , S , G >& rhs ) noexcept;
// ---------------------------------------------------------------------
T_Self& clear( ) noexcept;
T_Self& free( ) noexcept;
// ---------------------------------------------------------------------
uint32_t capacity( ) const noexcept;
uint32_t size( ) const noexcept;
constexpr uint32_t growth( ) const noexcept;
bool isStatic( ) const noexcept;
T_Self& ensureCapacity( uint32_t capacity ) noexcept;
// ---------------------------------------------------------------------
T& operator[] ( uint32_t index ) noexcept;
T const& operator[] ( uint32_t index ) const noexcept;
int32_t indexOf( T const& item ) const noexcept;
bool contains( T const& item ) const noexcept;
// ---------------------------------------------------------------------
uint32_t add( T const& item ) noexcept;
uint32_t add( T&& item ) noexcept;
template< typename... Args >
T& addNew( Args&& ... args );
// ---------------------------------------------------------------------
T_Self& addAll( T_Self const& other ) noexcept;
T_Self& addAll( T_Self&& other ) noexcept;
// ---------------------------------------------------------------------
T_Self& operator<< ( T const& item ) noexcept;
T_Self& operator<< ( T&& item ) noexcept;
T_Self& operator<< ( T_Self const& other ) noexcept;
T_Self& operator<< ( T_Self&& other ) noexcept;
// ---------------------------------------------------------------------
void insert( uint32_t index ,
T const& item ) noexcept;
void insert( uint32_t index ,
T&& item ) noexcept;
template< typename... Args >
T& insertNew( uint32_t index ,
Args&& ... args );
// ---------------------------------------------------------------------
void remove( uint32_t index ) noexcept;
void removeSwap( uint32_t index ) noexcept;
// ---------------------------------------------------------------------
void sort( F_Comparator< T > cmp = T_Comparator< T >::compare ) noexcept;
void sort( uint32_t first ,
uint32_t items ,
F_Comparator< T > cmp = T_Comparator< T >::compare ) noexcept;
// ---------------------------------------------------------------------
T_Self copyRange( uint32_t first ,
uint32_t last = UINT32_MAX ) const noexcept;
T_Self moveRange( uint32_t first ,
uint32_t last = UINT32_MAX ) noexcept;
// ---------------------------------------------------------------------
private:
void convertToDynamic_( uint32_t capacity ) noexcept;
T_Static_& static_( ) noexcept;
T_Static_ const& static_( ) const noexcept;
T_Dynamic_& dynamic_( ) noexcept;
T_Dynamic_ const& dynamic_( ) const noexcept;
};
}
#endif // _H_EBCL_ARRAYS
#include <lw/lib/inline/Arrays.hh>

View file

@ -0,0 +1,169 @@
/******************************************************************************/
/* BINARY READER/WRITER FOR STREAMS *******************************************/
/******************************************************************************/
#pragma once
#include <lw/lib/Streams.hh>
namespace lw {
/*= OBJECT READER/WRITER TEMPLATES ===========================================*/
/*
* This pair of templates must be specialized to handle specific types.
*/
struct T_BinaryReader;
struct T_BinaryWriter;
template< typename T >
struct T_ObjectReader
{
static T read( T_BinaryReader const& reader );
};
template< typename T >
struct T_ObjectWriter
{
static void write( T_BinaryWriter const& writer , T const& string );
};
// Helper macros to declare and define readers and writers
#define M_DECLARE_OBJECT_READER( Type ) \
template< > \
struct T_ObjectReader< Type > \
{ \
static Type read( T_BinaryReader const& ); \
}
#define M_DEFINE_OBJECT_READER( Type ) \
Type T_ObjectReader< Type >::read( T_BinaryReader const & reader )
#define M_DECLARE_OBJECT_WRITER( Type ) \
template< > \
struct T_ObjectWriter< Type > \
{ \
static void write( T_BinaryWriter const& , \
Type const& ); \
}
#define M_DEFINE_OBJECT_WRITER( Type ) \
void T_ObjectWriter< Type >::write( T_BinaryWriter const & writer , \
Type const & item )
/*= READER ===================================================================*/
struct T_BinaryReader
{
private:
A_InputStream& stream_;
const E_Endian endian_;
public:
T_BinaryReader( ) = delete;
explicit T_BinaryReader( A_InputStream& stream , E_Endian endian = E_Endian::NATIVE ) noexcept;
T_BinaryReader( T_BinaryReader const& other ) noexcept = delete;
T_BinaryReader( T_BinaryReader&& other ) noexcept = delete;
A_InputStream& stream( ) const;
E_Endian endian( ) const;
template< typename T >
T readNumericNative( ) const;
template< typename T >
T readNumericLittleEndian( ) const;
template< typename T >
T readNumericBigEndian( ) const;
template< typename T >
T read( ) const;
private:
template<
typename T ,
bool IsNum = std::is_integral< T >::value
|| std::is_floating_point< T >::value
>
struct T_Reader_ { };
template< typename T >
struct T_Reader_< T , true >
{
static T read( T_BinaryReader const& reader );
};
template< typename T >
struct T_Reader_< T , false >
{
static T read( T_BinaryReader const& reader );
};
};
/*= WRITER ===================================================================*/
struct T_BinaryWriter
{
private:
A_OutputStream& stream_;
const E_Endian endian_;
public:
T_BinaryWriter( ) noexcept = delete;
explicit T_BinaryWriter( A_OutputStream& stream , E_Endian endian = E_Endian::NATIVE ) noexcept;
T_BinaryWriter( T_BinaryWriter const& other ) noexcept = delete;
T_BinaryWriter( T_BinaryWriter&& other ) noexcept = delete;
A_OutputStream& stream( ) const;
E_Endian endian( ) const;
template< typename T >
void writeNumericNative( T value ) const;
template< typename T >
void writeNumericLittleEndian( T const& value ) const;
template< typename T >
void writeNumericBigEndian( T const& value ) const;
template< typename T >
void write( T const& value ) const;
private:
template<
typename T ,
bool IsNum = std::is_integral< T >::value
|| std::is_floating_point< T >::value
>
struct T_Writer_ { };
template< typename T >
struct T_Writer_< T , true >
{
static void write( T_BinaryWriter const& writer , T value );
};
template< typename T >
struct T_Writer_< T , false >
{
static void write( T_BinaryWriter const& writer , T const& value );
};
};
}
#include <lw/lib/inline/BinaryStreams.hh>

104
include/ebcl/Buffers.hh Normal file
View file

@ -0,0 +1,104 @@
/******************************************************************************/
/* BUFFERS ********************************************************************/
/******************************************************************************/
/* Buffers can be used to manipulate raw data. No constructors or destructors
* will ever be called.
*
* Buffers are available in two flavors: fixed size (where the size of the
* buffer is a template argument) and dynamic (where the size can be changed).
*/
#pragma once
#include <lw/lib/Externals.hh>
namespace lw {
/*============================================================================*/
class T_BufferBase
{
protected:
uint8_t* data_;
T_BufferBase( ) = delete;
explicit T_BufferBase( uint8_t* buffer ) noexcept;
explicit T_BufferBase( size_t size );
T_BufferBase( T_BufferBase&& source ) noexcept;
public:
~T_BufferBase( );
friend void swap( T_BufferBase& lhs , T_BufferBase& rhs );
uint8_t * data( ) const;
};
/*============================================================================*/
template< size_t SIZE , class T >
class T_FixedBuffer : public T_BufferBase
{
private:
typedef T_FixedBuffer< SIZE , T > MyType_;
static constexpr size_t BYTES_ = SIZE * sizeof( T );
public:
T_FixedBuffer( );
T_FixedBuffer( MyType_&& source ) noexcept;
T_FixedBuffer( MyType_ const& source );
template< size_t SZ , typename TP >
friend void swap( T_FixedBuffer< SZ , TP >& lhs , T_FixedBuffer< SZ , TP >& rhs ) noexcept;
MyType_& operator= ( MyType_ const& other );
MyType_& operator= ( MyType_&& other ) noexcept;
size_t bytes( ) const;
T& operator[] ( size_t index );
T const& operator[] ( size_t index ) const;
MyType_& setAll( T const& value );
};
/*============================================================================*/
template< class T >
class T_Buffer : public T_BufferBase
{
private:
typedef T_Buffer< T > MyType_;
protected:
size_t size_;
public:
T_Buffer( ) noexcept;
T_Buffer( size_t size );
T_Buffer( T const* data , size_t size );
T_Buffer( MyType_ const& other );
T_Buffer( MyType_&& other ) noexcept;
MyType_& operator= ( MyType_ const& other );
MyType_& operator= ( MyType_&& other );
template< typename TP >
friend void swap( T_Buffer< TP >& lhs , T_Buffer< TP >& rhs ) noexcept;
size_t size( ) const;
size_t bytes( ) const;
T& operator[] ( size_t index );
T const& operator[] ( size_t index ) const;
MyType_& resize( size_t newSize );
MyType_& setAll( T const& value );
MyType_& copyAll( T const* data );
};
} // namespace
#include <lw/lib/inline/Buffers.hh>

25
include/ebcl/Config.hh Normal file
View file

@ -0,0 +1,25 @@
/******************************************************************************/
/* CONFIGURATION FOR THE BUILD ************************************************/
/******************************************************************************/
#ifndef _H_EBCL_CONFIG
#define _H_EBCL_CONFIG
/*= DEBUGGING OPTIONS ========================================================*/
/* Disable memory allocators */
//#define EBCL_CFG_NO_ALLOCATORS
/*= TUNING ===================================================================*/
/* Pool allocator parameters for shared pointer references */
#define EBCL_CFG_SHAREDPTR_REFPOOL_SIZE 512
#define EBCL_CFG_SHAREDPTR_REFPOOL_MAXFREE 2
/*----------------------------------------------------------------------------*/
#endif // _H_EBCL_CONFIG

48
include/ebcl/DynLib.hh Normal file
View file

@ -0,0 +1,48 @@
/******************************************************************************/
/* DYNAMIC LIBRARIES **********************************************************/
/******************************************************************************/
#ifndef _H_EBCL_DYNLIB
#define _H_EBCL_DYNLIB
#include <lw/lib/Strings.hh>
#include <lw/lib/Utilities.hh>
namespace lw {
/*= DYNAMIC LIBRARY SUPPORT ==================================================*/
class T_DynLib : public A_PrivateImplementation
{
public:
T_DynLib( ) = delete;
T_DynLib( T_DynLib const& ) = delete;
T_DynLib& operator =( T_DynLib const& ) = delete;
/* Initialise and set the name of the library to load */
explicit T_DynLib( T_String const& name );
explicit T_DynLib( char const* const name );
/* Load/unload the library */
bool load( );
void unload( );
/* Check whether the library has been loaded */
bool isLoaded( ) const noexcept;
/* Obtain the last error that was encoutered */
T_String lastError( ) const noexcept;
/* Symbol access. The library MUST be loaded. */
void* getRawSymbol( char const* name ) const noexcept;
template< typename T >
T* getPointer( char const* name ) const noexcept;
template< typename T >
std::function< T > getFunction(
char const* name ) const noexcept;
};
M_CLASS_POINTERS( DynLib );
} // namespace lw
#endif // _H_EBCL_DYNLIB
#include <lw/lib/inline/DynLib.hh>

19
include/ebcl/Externals.hh Normal file
View file

@ -0,0 +1,19 @@
/******************************************************************************/
/* EXTERNAL HEADER FILES ******************************************************/
/******************************************************************************/
#pragma once
#include <cstddef>
#include <cstdint>
#include <cstring>
#include <cassert>
#include <condition_variable>
#include <functional>
#include <malloc.h>
#include <mutex>
#include <new>
#include <shared_mutex>
#include <thread>
#include <utility>

187
include/ebcl/Files.hh Normal file
View file

@ -0,0 +1,187 @@
/******************************************************************************/
/* FILES **********************************************************************/
/******************************************************************************/
#ifndef _H_LW_LIB_FILES
#define _H_LW_LIB_FILES
#include <lw/lib/Streams.hh>
#include <lw/lib/Strings.hh>
namespace lw {
/*= FILE ACCESS ==============================================================*/
enum class E_FileMode {
READ_ONLY ,
READ_WRITE ,
OVERWRITE
};
class T_File final
{
private:
T_String path_;
E_FileMode mode_;
FILE* file_;
size_t size_ , pos_;
T_File( );
public:
// Construct from a file path. Does not open the file.
T_File( T_String const& path , E_FileMode mode );
// Move constructor and assignment
T_File( T_File&& other ) noexcept;
T_File& operator= ( T_File&& other ) noexcept;
// Disabled copy constructor / assignment operator
T_File( T_File const& ) = delete;
T_File& operator= ( T_File const& ) = delete;
// Destructor - must close the file if it is open
~T_File( );
// Swapping
friend void swap( T_File& lhs , T_File& rhs ) noexcept;
// -------------------------------------------------------------------
// Get the path
T_String const& path( ) const noexcept;
// Get the mode
E_FileMode mode( ) const noexcept;
// Open the file. Throws an exception if that fails. Will be called
// automatically by most methods.
virtual void open( );
// Close the file. Never throws, even if the file's already closed or
// if closing fails.
void close( ) noexcept;
// Check if the file is open
bool isOpen( ) const noexcept;
// -------------------------------------------------------------------
// Get the file's size
size_t size( ) const noexcept;
// Get the current file position
size_t position( ) const noexcept;
// Set the position relative to the start or the end of the file
void position( size_t position , bool fromEnd = false );
// Set the position relative to the current position
void move( ssize_t offset );
// Read/write methods
size_t read( void* data , size_t size );
size_t write( void const* data , size_t size );
// Flushing
void flush( );
};
M_CLASS_POINTERS( File );
/*= FILE STREAMS =============================================================*/
class T_FileInputStream final : public A_InputStream
{
protected:
RP_File fileRaw_;
OP_File fileOwned_;
size_t start_;
public:
T_FileInputStream( ) = delete;
// Construct from a file instance
explicit T_FileInputStream( T_File& file , ssize_t offset = 0 ,
size_t limit = SIZE_MAX );
// Construct from a file owning pointer
explicit T_FileInputStream( OP_File&& file , ssize_t offset = 0 ,
size_t limit = SIZE_MAX );
// Copy constructor and assignment
T_FileInputStream( T_FileInputStream const& );
T_FileInputStream& operator= ( T_FileInputStream const& );
// Move constructor and assignment
T_FileInputStream( T_FileInputStream&& other ) noexcept;
T_FileInputStream& operator= ( T_FileInputStream&& other ) noexcept;
// Swapping
void swap( T_FileInputStream& rhs ) noexcept;
// Get the file
T_File& file( ) const noexcept;
// Get the start offset
size_t offset( ) const noexcept;
// -------------------------------------------------------------------
size_t read( void* data , size_t size ) override;
// -------------------------------------------------------------------
private:
void init( ssize_t offset , size_t limit );
};
M_CLASS_POINTERS( FileInputStream );
/*---------------------------------------------------------------------------*/
class T_FileOutputStream final : public A_OutputStream
{
protected:
RP_File fileRaw_;
OP_File fileOwned_;
size_t start_;
public:
T_FileOutputStream( ) = delete;
// Construct from a file.
explicit T_FileOutputStream( T_File& file , ssize_t offset = 0 );
// Construct from a file owning pointer
explicit T_FileOutputStream( OP_File&& file , ssize_t offset = 0 );
// Copy constructor and assignment
T_FileOutputStream( T_FileOutputStream const& );
T_FileOutputStream& operator= ( T_FileOutputStream const& );
// Move constructor and assignment
T_FileOutputStream( T_FileOutputStream&& other ) noexcept;
T_FileOutputStream& operator= ( T_FileOutputStream&& other ) noexcept;
// Swapping
void swap( T_FileOutputStream& rhs ) noexcept;
// Get the file
T_File& file( ) const noexcept;
// Get the start offset
size_t offset( ) const noexcept;
// -------------------------------------------------------------------
size_t write( void const* data , size_t size ) override;
void flush( ) override;
// -------------------------------------------------------------------
private:
void init( ssize_t offset );
};
M_CLASS_POINTERS( FileOutputStream );
}
#endif // _H_LW_LIB_FILES
#include <lw/lib/inline/Files.hh>

30
include/ebcl/GameLoop.hh Normal file
View file

@ -0,0 +1,30 @@
/******************************************************************************/
/* GAME'S MAIN LOOP ***********************************************************/
/******************************************************************************/
#ifndef _H_LW_LIB_GAMELOOP
#define _H_LW_LIB_GAMELOOP
#include <lw/lib/Messages.hh>
namespace lw {
/*= GAME LOOP ================================================================*/
class T_GameLoop : public A_PrivateImplementation
{
public:
T_GameLoop( ) noexcept;
T_GameLoop( T_GameLoop const& ) = delete;
T_GameLoop( T_GameLoop&& ) = delete;
bool active( ) const noexcept;
void start( ) noexcept;
void shutdown( ) noexcept;
void putMessage( T_UIMessage&& message ) noexcept;
};
M_CLASS_POINTERS( GameLoop );
}
#endif // _H_LW_LIB_GAMELOOP

79
include/ebcl/HashIndex.hh Normal file
View file

@ -0,0 +1,79 @@
/******************************************************************************/
/* HASH INDEX *****************************************************************/
/******************************************************************************/
#pragma once
#include <lw/lib/Externals.hh>
#include <lw/lib/Pointers.hh>
namespace lw {
/*
* This is based on http://glampert.com/2016/05-04/dissecting-idhashindex,
* which explains how the hash tables in idTech4 work. Not looking at the code
* to avoid GPL-related issues, so my implementation will probably suck.
*
* Unlike the original thing, this version considers that:
* - all additions are made at the end of the array (and therefore at the
* end of the index),
* - erasing is done by swapping the element being erased and the last
* element of the index.
*
* It also keeps track of the hash key for a given index in order to make
* erasing easier.
*/
class T_HashIndex
{
public:
static constexpr uint32_t INVALID_INDEX = 0xffffffff;
static constexpr uint32_t DEFAULT_SIZE = 1024;
static constexpr uint32_t DEFAULT_GROWTH = 1024;
private:
static uint32_t invalidIndex_;
uint32_t hashSize_;
uint32_t* hash_;
uint32_t indexSize_;
uint32_t indexGrowth_;
uint32_t indexUsed_;
uint32_t* index_;
uint32_t* indexReverse_;
uint32_t hashMask_;
uint32_t lookupMask_;
void enlargeIndex( uint32_t needed );
void allocateIfNecessary( );
public:
T_HashIndex( ) noexcept;
T_HashIndex( uint32_t hashSize , uint32_t indexSize , uint32_t growth = DEFAULT_GROWTH ) noexcept;
T_HashIndex( T_HashIndex const& source );
T_HashIndex( T_HashIndex&& source ) noexcept;
~T_HashIndex( );
T_HashIndex& operator =( T_HashIndex const& other );
T_HashIndex& operator =( T_HashIndex&& other ) noexcept;
friend void swap( T_HashIndex& lhs , T_HashIndex& rhs ) noexcept;
void free( );
void clear( );
void add( uint32_t key );
void remove( uint32_t index );
uint32_t first( uint32_t key ) const;
uint32_t next( uint32_t index ) const;
};
M_CLASS_POINTERS( HashIndex );
void swap( T_HashIndex& lhs , T_HashIndex& rhs ) noexcept;
} // namespace
#include <lw/lib/inline/HashIndex.hh>

203
include/ebcl/HashTables.hh Normal file
View file

@ -0,0 +1,203 @@
/******************************************************************************/
/* HASH TABLES ****************************************************************/
/******************************************************************************/
#ifndef _H_LW_LIB_HASHTABLES
#define _H_LW_LIB_HASHTABLES
#include <lw/lib/Arrays.hh>
#include <lw/lib/HashIndex.hh>
namespace lw {
// F_KeyMatch< K > - Equality check function for keys
template< typename K >
using F_KeyMatch = std::function< bool( K const& , K const& ) >;
// T_DefaultKeyMatch< K > - Default equality check for keys
template< typename K >
struct T_DefaultKeyMatch
{
static bool keysMatch( K const& , K const& );
};
/*= KEY / VALUE TABLE ========================================================*/
/*
* T_KeyValueTable - Hash table with separate key and value storage.
* This class is meant to be used when data with unrelated types need to be
* associated with each other, e.g. string -> int mapping.
*/
template<
typename KeyType ,
typename ValueType
>
class T_KeyValueTable
{
public:
typedef F_KeyMatch< KeyType > F_Match;
private:
typedef T_KeyValueTable< KeyType , ValueType > MyType_;
F_Match match_;
T_HashIndex index_;
T_Array< KeyType > keys_;
T_Array< ValueType > values_;
public:
M_TEMPLATE_POINTERS( MyType_ );
// ---------------------------------------------------------------------
T_KeyValueTable( uint32_t initialSize = T_HashIndex::DEFAULT_SIZE ,
uint32_t hashSize = T_HashIndex::DEFAULT_SIZE ,
uint32_t growth = T_HashIndex::DEFAULT_GROWTH ,
F_Match match = T_DefaultKeyMatch< KeyType >::keysMatch );
template< typename K , typename T >
friend void swap( T_KeyValueTable< K , T >& lhs , T_KeyValueTable< K , T >& rhs );
// ---------------------------------------------------------------------
// Add a new value (fails if key already present)
template<
typename A , typename B ,
T_EnableIfTypesMatch< KeyType , A > = true ,
T_EnableIfTypesMatch< ValueType , B > = true
> bool add( A&& k , B&& v );
// Update an existing value (fails if key not present)
template<
typename A ,
T_EnableIfTypesMatch< ValueType , A > = true
> bool update( KeyType const& k , A&& v );
// Add or modify a key/value pair
template<
typename A , typename B ,
T_EnableIfTypesMatch< KeyType , A > = true ,
T_EnableIfTypesMatch< ValueType , B > = true
> void set( A&& k , B&& v );
// Remove a key/value pair
bool remove( KeyType const& k );
void clear( );
void free( );
// ---------------------------------------------------------------------
uint32_t size( ) const;
T_Array< KeyType > const& keys( ) const;
T_Array< ValueType > const& values( ) const;
uint32_t indexOf( KeyType const& k ) const;
bool contains( KeyType const& k ) const;
ValueType const * get( KeyType const& k ) const;
ValueType * get( KeyType const& k );
ValueType& operator[] ( uint32_t index );
ValueType const& operator[] ( uint32_t index ) const;
// ---------------------------------------------------------------------
private:
uint32_t find( KeyType const& k , uint32_t hash ) const;
};
template< typename K , typename T >
void swap( T_KeyValueTable< K , T >& lhs , T_KeyValueTable< K , T >& rhs );
/*= OBJECT TABLE =============================================================*/
/*
* This class is meant to be used to store objects that somehow contain their
* own keys. Of course, modifying one of these objects' key after it's been
* inserted will cause major SNAFU's.
*/
template<
typename KeyType ,
typename ValueType
>
class T_ObjectTable
{
public:
typedef F_KeyMatch< KeyType > F_Match;
typedef std::function< KeyType( ValueType const& ) > F_GetKey;
private:
typedef T_ObjectTable< KeyType , ValueType > MyType_;
F_Match match_;
F_GetKey keyGetter_;
T_HashIndex index_;
T_Array< ValueType > values_;
public:
M_TEMPLATE_POINTERS( MyType_ );
T_ObjectTable( ) = delete;
// ---------------------------------------------------------------------
T_ObjectTable( F_GetKey keyGetter , uint32_t initialSize = T_HashIndex::DEFAULT_SIZE ,
uint32_t hashSize = T_HashIndex::DEFAULT_SIZE ,
uint32_t growth = T_HashIndex::DEFAULT_GROWTH ,
F_Match match = T_DefaultKeyMatch< KeyType >::keysMatch );
template< typename K , typename T >
friend void swap( T_ObjectTable< K , T >& lhs , T_ObjectTable< K , T >& rhs );
// ---------------------------------------------------------------------
template<
typename A ,
T_EnableIfTypesMatch< ValueType , A > = true
> bool add( A&& v );
template<
typename A ,
T_EnableIfTypesMatch< ValueType , A > = true
> bool update( A&& v );
template<
typename A ,
T_EnableIfTypesMatch< ValueType , A > = true
> void set( A&& v );
bool remove( KeyType const& k );
void clear( );
void free( );
// ---------------------------------------------------------------------
uint32_t size( ) const;
uint32_t indexOf( KeyType const& k ) const;
bool contains( KeyType const& k ) const;
T_Array< KeyType > keys( ) const;
T_Array< ValueType > const& values( ) const;
ValueType const * get( KeyType const& k ) const;
ValueType * get( KeyType const& k );
ValueType& operator[] ( uint32_t index );
ValueType const& operator[] ( uint32_t index ) const;
// ---------------------------------------------------------------------
private:
uint32_t find( KeyType const& k , uint32_t hash ) const;
};
template< typename K , typename T >
void swap( T_ObjectTable< K , T >& lhs , T_ObjectTable< K , T >& rhs );
}
#endif // _H_LW_LIB_HASHTABLES
#include <lw/lib/inline/HashTables.hh>

View file

@ -0,0 +1,62 @@
/******************************************************************************/
/* MEMORY STREAMS *************************************************************/
/******************************************************************************/
#pragma once
#include <lw/lib/Streams.hh>
namespace lw {
class T_MemoryInputStream final : public A_InputStream
{
private:
uint8_t const* buffer_;
public:
T_MemoryInputStream( ) = delete;
T_MemoryInputStream( void const* buffer , size_t size );
T_MemoryInputStream( T_MemoryInputStream const& other ) noexcept;
friend void swap( T_MemoryInputStream& lhs , T_MemoryInputStream& rhs ) noexcept;
T_MemoryInputStream& operator= ( T_MemoryInputStream const& other ) noexcept;
template< int S , typename T >
explicit T_MemoryInputStream( T_FixedBuffer< S , T > const& buffer );
template< typename T >
explicit T_MemoryInputStream( T_Buffer< T > const& buffer );
size_t read( void* data , size_t size ) override;
};
M_CLASS_POINTERS( MemoryInputStream );
/*----------------------------------------------------------------------------*/
class T_MemoryOutputStream final : public A_OutputStream
{
typedef std::function< uint8_t*( uint8_t* , size_t ) > F_Resizer;
private:
uint8_t* buffer_;
F_Resizer resizer_;
public:
T_MemoryOutputStream( ) = delete;
T_MemoryOutputStream( void* buffer , size_t size , F_Resizer resizer = nullptr );
template< int S , typename T >
explicit T_MemoryOutputStream( T_FixedBuffer< S , T >& buffer );
template< typename T >
explicit T_MemoryOutputStream( T_Buffer< T >& buffer );
size_t write( void const* data , size_t size ) override;
};
M_CLASS_POINTERS( MemoryOutputStream );
} // namespace
#include <lw/lib/inline/MemoryStreams.hh>

282
include/ebcl/Messages.hh Normal file
View file

@ -0,0 +1,282 @@
/******************************************************************************/
/* UI<=>GAME MESSAGES *********************************************************/
/******************************************************************************/
#ifndef _H_LW_LIB_MESSAGES
#define _H_LW_LIB_MESSAGES
#include <lw/lib/Strings.hh>
#include <lw/lib/Types.hh>
namespace lw {
/*= VIEWS ====================================================================*/
/* Empty abstract class that serves as a base for game views */
class A_GameView
{
public:
virtual ~A_GameView( ) = 0;
};
M_ABSTRACT_POINTERS( GameView );
/* Abstract class for a view builder
*
* User interfaces need to access the game's data in order to display it. View
* builders provide a way to do that; they are passed to the game's main loop
* by the UI. Once set, they will be used to create and update view data.
*/
class A_ViewBuilder
{
public:
virtual ~A_ViewBuilder( ) = 0;
/* This method creates a view instance. It is called twice when the
* builder is installed, in order to create a "double buffer" - one
* view can be sent to the UI while the other is being updated.
*/
virtual OP_GameView createView( ) = 0;
/* This method is responsible for updating a view instance. */
virtual void updateView( OP_GameView view ) = 0;
};
M_ABSTRACT_POINTERS( ViewBuilder );
/*= GAME STATE ===============================================================*/
/* State of the main loop */
enum class E_GameState {
NO_GAME , // No game loaded
GAME_PAUSED , // Game is loaded but not running
GAME_SLOW , // Game is running at slow speed
GAME_NORMAL , // Game is running at normal speed
GAME_FAST // Game is running at high speed
};
M_LSHIFT_OP( T_StringBuilder , E_GameState );
/*= PROGRESS INFORMATION =====================================================*/
/* Progress information for long operations - part (main or sub) */
class T_ProgressInfoPart
{
private:
T_String text_;
uint32_t progress_;
uint32_t total_;
public:
T_ProgressInfoPart( ) = delete;
T_ProgressInfoPart( T_String text , uint32_t progress , uint32_t total ) noexcept;
T_ProgressInfoPart( T_ProgressInfoPart&& other ) noexcept;
T_ProgressInfoPart( T_ProgressInfoPart const& other );
T_String const& text( ) const noexcept;
uint32_t progress( ) const noexcept;
uint32_t total( ) const noexcept;
};
/* Progress information for long operations - main */
class T_ProgressInfo
{
private:
T_ProgressInfoPart main_;
T_Optional< T_ProgressInfoPart > sub_;
public:
T_ProgressInfo( ) = delete;
T_ProgressInfo( T_String text , uint32_t progress , uint32_t total ) noexcept;
explicit T_ProgressInfo( T_ProgressInfoPart main ) noexcept;
T_ProgressInfo( T_ProgressInfoPart main , T_ProgressInfoPart sub ) noexcept;
T_ProgressInfo( T_ProgressInfoPart main ,
T_String sText , uint32_t sProgress , uint32_t sTotal ) noexcept;
T_ProgressInfo( T_String text , uint32_t progress , uint32_t total ,
T_String sText , uint32_t sProgress , uint32_t sTotal ) noexcept;
T_ProgressInfo( T_ProgressInfo&& other ) noexcept;
T_ProgressInfo( T_ProgressInfo const& other ) = delete;
T_ProgressInfoPart const& main( ) const noexcept;
bool hasSub( ) const noexcept;
T_ProgressInfoPart const& sub( ) const;
};
M_CLASS_POINTERS( ProgressInfo );
/*= MESSAGES =================================================================*/
/* Types of messages sent by the UI to the game */
enum class E_GameUIMessage {
/* Create a new game
* Data: XXX
*/
NEW ,
/* Load an existing game
* Data: uint32_t - game identifier
*/
LOAD ,
/* Save the current game
* Data: none
*/
SAVE ,
/* Quit the current game
* Data: none
*/
STOP ,
/* Quit current game (if any) the exit the main loop
* Data: none
*/
QUIT ,
/* Abort the current operation
* Data: none
*/
ABORT ,
/* Delete a saved game
* Data: uint32_t - game identifier
*/
DELETE ,
/* Copy or rename a saved game
* Data: XXX
*/
COPY_OR_RENAME ,
/* Set the current game's speed
* Data: E_GameState (but NO_GAME will be ignored)
*/
SET_SPEED ,
/* Execute computation steps
* Data: XXX
*/
STEPS ,
/* Set a view builder
* Data: XXX
*/
SET_VIEW ,
/* Indicate that a view has been displayed
* Data: T_String - identifier of the view
*/
VIEW_DISPLAYED ,
/* Send a query to the game
* Data: XXX
*/
QUERY ,
/* Send a command to the game
* Data: XXX
*/
COMMAND
};
M_LSHIFT_OP( T_StringBuilder , E_GameUIMessage );
/*----------------------------------------------------------------------------*/
/* Types of messages sent by the main loop to the UI */
enum class E_GameLoopMessage {
/* Main loop exiting
* Data: none
*/
TERMINATED ,
/* Progress information
* Data: T_ProgressInfo
*/
PROGRESS ,
/* Operation completed
* Data: none
*/
DONE ,
/* State changed
* Data: E_GameState
*/
STATE_CHANGED ,
/* Indicate that a view is available
* Data: XXX
*/
VIEW_AVAILABLE ,
/* Query response
* Data: XXX
*/
QUERY_RESPONSE ,
/* Command execution - success
* Data: none
*/
COMMAND_OK ,
/* Command execution - syntax error
* Data: XXX
*/
COMMAND_SYNTAX ,
/* Command execution - error
* Data: XXX
*/
COMMAND_ERROR ,
};
M_LSHIFT_OP( T_StringBuilder , E_GameLoopMessage );
/*----------------------------------------------------------------------------*/
/* Types for message data */
using T_GameUIMessageData = T_Union<
uint32_t ,
T_String ,
E_GameState
>;
using T_GameLoopMessageData = T_Union<
T_ProgressInfo ,
E_GameState
>;
/*----------------------------------------------------------------------------*/
/* Message direction */
enum class E_MessageDirection {
FROM_UI_TO_GAME ,
FROM_GAME_TO_UI
};
/* Message class template, can be used for both directions */
template<
E_MessageDirection Direction ,
typename EType = std::conditional_t<
Direction == E_MessageDirection::FROM_UI_TO_GAME ,
E_GameUIMessage , E_GameLoopMessage > ,
typename DType = std::conditional_t<
Direction == E_MessageDirection::FROM_UI_TO_GAME ,
T_GameUIMessageData , T_GameLoopMessageData >
>
class T_GameMessage
{
public:
using T_Type = EType;
using T_Data = DType;
private:
using T_Self_ = T_GameMessage< Direction >;
T_Optional< T_Type > type_;
T_Optional< T_Data > data_;
public:
constexpr T_GameMessage( ) noexcept;
constexpr T_GameMessage( T_Type type ) noexcept;
T_GameMessage( T_Type type , T_Data data ) noexcept;
T_GameMessage( T_Self_ const& ) = delete;
T_GameMessage( T_Self_&& other ) noexcept;
T_Self_& operator =( T_Self_ const& ) = delete;
T_Self_& operator =( T_Self_&& other ) noexcept;
constexpr bool hasMessage( ) const noexcept;
constexpr T_Type type( ) const noexcept;
template< typename T >
constexpr T const& data( ) const;
};
/*----------------------------------------------------------------------------*/
using T_UIMessage = T_GameMessage< E_MessageDirection::FROM_UI_TO_GAME >;
using T_LoopMessage = T_GameMessage< E_MessageDirection::FROM_GAME_TO_UI >;
} // namespace lw
#endif // _H_LW_LIB_MESSAGES
#include <lw/lib/inline/Messages.hh>

247
include/ebcl/Mods.hh Normal file
View file

@ -0,0 +1,247 @@
/******************************************************************************/
/* MODDING SYSTEM *************************************************************/
/******************************************************************************/
#ifndef _H_LW_LIB_MODS
#define _H_LW_LIB_MODS
#include <lw/lib/Log.hh>
#include <lw/lib/ModInterface.hh>
namespace lw {
/*= MOD INFORMATION ==========================================================*/
/* Mod identifier (name + version) */
struct T_ModIdentifier {
T_String name;
uint32_t version; // Main version number used for dependencies
bool operator ==( T_ModIdentifier const& other ) const noexcept;
bool operator !=( T_ModIdentifier const& other ) const noexcept;
int compare( T_ModIdentifier const& other ) const noexcept;
};
M_CLASS_POINTERS( ModIdentifier );
M_DECLARE_HASH( T_ModIdentifier );
M_DECLARE_COMPARATOR( T_ModIdentifier );
M_LSHIFT_OP( T_StringBuilder , T_ModIdentifier const& );
/* Types of mods */
enum class E_ModType {
DATA , // This mod consists of data only
NATIVE , // This mod consists of native code
UI , // This mod is an user interface
};
/*----------------------------------------------------------------------------*/
/* Mod information record */
struct T_ModInfo
{
T_String path;
E_ModType type;
/* Mod name, version and revision (the latter is for changes that don't
* affect the interface).
*/
T_ModIdentifier identifier;
uint32_t revision;
/* Required library version number */
uint32_t libVersion;
/* List of dependencies */
T_Array< T_ModIdentifier > modDeps;
/* Is this mod an user interface mod? */
bool isUserInterface( ) const noexcept;
};
M_CLASS_POINTERS( ModInfo );
M_LSHIFT_OP( T_StringBuilder , T_ModInfo const& );
/*= MODS MANAGER CONFIGURATION ===============================================*/
/* Loading mode for a mod */
enum class E_ModMode {
EXCLUDE , // Never load this mod
AUTO , // Load the most appropriate version of the mod
VERSION , // Load a specific version of the mod, fails
// if the mod in the specified version is not
// present
REQUIRE // Require that the specified mod be present
// Note that both VERSION and REQUIRE can apply to an UI-specific mod;
// while the mod will not be loaded if the corresponding UI isn't,
// its presence will still be required.
};
/* Mods manager configuration */
class T_ModsManagerConfiguration : public A_PrivateImplementation
{
public:
T_ModsManagerConfiguration( ) noexcept;
T_ModsManagerConfiguration(
T_ModsManagerConfiguration const& ) = delete;
T_ModsManagerConfiguration& operator =(
T_ModsManagerConfiguration const& ) = delete;
T_ModsManagerConfiguration(
T_ModsManagerConfiguration&& ) noexcept;
T_ModsManagerConfiguration& operator =(
T_ModsManagerConfiguration&& other ) noexcept;
// ---------------------------------------------------------------------
/* Set a mod configuration entry */
void setAuto( T_String const& name ) noexcept;
void setRequired( T_String const& name ) noexcept;
void setExcluded( T_String const& name ) noexcept;
void setVersion( T_String const& name ,
uint32_t version ) noexcept;
void setVersion( T_String const& name ,
uint32_t version ,
uint32_t revision ) noexcept;
/* Query mod configuration */
T_Array< T_String > configured( ) const noexcept;
E_ModMode modeFor( T_String const& name ) const noexcept;
uint32_t requiredVersion( T_String const& name ) const noexcept;
T_Optional< uint32_t > requiredRevision(
T_String const& name ) const noexcept;
// ---------------------------------------------------------------------
/* Set or clear an UI preference */
void setUIPreference(
T_String const& name ,
int32_t weight ) noexcept;
void clearUIPreference(
T_String const& name ) noexcept;
/* List UI preferences */
T_Array< T_String > uiPreferences( ) const noexcept;
/* Get the preference for an UI */
int32_t uiPreference(
T_String const& name ) const noexcept;
// ---------------------------------------------------------------------
/* Filter a list of mods using the configuration's exclusions and
* version limits.
*/
T_Array< RPC_ModInfo > filterMods(
T_Array< RPC_ModInfo > const& mods ) const noexcept;
/* Generate the list of required mods. This includes all mods that
* have been set as required, and all mods that have a version
* requirement.
*/
T_Array< T_String > requiredMods( ) const noexcept;
// ---------------------------------------------------------------------
/* Get a default configuration */
static T_ModsManagerConfiguration DefaultConfiguration( ) noexcept;
/* Get the parser's configuration used to load mods manager configuration */
static T_SRDParserConfig GetParserConfig( );
};
M_CLASS_POINTERS( ModsManagerConfiguration );
/*= MODS DEPENDENCY GRAPH ====================================================*/
class T_ModsDependencies : public A_PrivateImplementation
{
public:
T_ModsDependencies( ) noexcept;
T_ModsDependencies(
T_Logger& logger ,
T_Array< RPC_ModInfo > const& mods ,
T_ModsManagerConfiguration const& config ) noexcept;
T_ModsDependencies(
T_ModsDependencies const& other ) noexcept;
T_ModsDependencies& operator =(
T_ModsDependencies const& other ) noexcept;
T_ModsDependencies(
T_ModsDependencies&& other ) noexcept;
T_ModsDependencies& operator =(
T_ModsDependencies&& other ) noexcept;
friend M_DECLARE_SWAP( T_ModsDependencies );
// ---------------------------------------------------------------------
bool resolved( ) const;
bool ambiguous( ) const;
T_Array< T_String > userInterfaces( ) const;
T_Array< RPC_ModInfo > const& commonMods( ) const;
T_Array< RPC_ModInfo >::RPC forUserInterface(
T_String const& name ) const;
};
M_CLASS_POINTERS( ModsDependencies );
M_DECLARE_SWAP( T_ModsDependencies );
/*= MODS MANAGER =============================================================*/
/* Function type for a function that generates a feedback function used to
* update the initialisation progress when the mods are being initialised.
*/
using F_CreateInitUpdater = std::function< F_UpdateInitProgress( RPC_ModInfo ) >;
class T_ModsManager : public A_PrivateImplementation
{
public:
T_ModsManager( ) = delete;
T_ModsManager( T_ModsManager const& ) = delete;
T_ModsManager( T_ModsManager&& ) noexcept = delete;
T_ModsManager( T_ModsManagerConfiguration&& config ) noexcept;
// ---------------------------------------------------------------------
/* Find available mods, load their descriptions */
bool scanForMods( );
/* Get the list of available mods */
T_Array< RPC_ModInfo > availableMods( ) const noexcept;
/* Resolve dependencies between mods using the configuration;
* returns true if there is a valid set of mods.
*/
bool resolveDependencies( ) noexcept;
// ---------------------------------------------------------------------
/* Pre-initialise common mods */
bool preinitCommon( ) noexcept;
/* Pre-initialise UI mods and try to start the user interface. */
OP_UserInterface preinitUIMods(
T_String const& ui ) noexcept;
/* Try to pre-initialise an UI mod. */
OP_UserInterface preinitUIMods( ) noexcept;
// ---------------------------------------------------------------------
/* Get the amount of loaded mods */
uint32_t modsCount( ) const noexcept;
/* Initialise the mods, sending progress updates along the way */
bool initialise(
F_CreateInitUpdater const& fciu ) noexcept;
// ---------------------------------------------------------------------
/* Shutdown all initialised mods. */
void shutdown( ) noexcept;
/* Unload all mods, calling post-shutdown routines if available */
void unload( ) noexcept;
};
M_CLASS_POINTERS( ModsManager );
} // namespace lw
#endif // _H_LW_LIB_MODS
#include <lw/lib/inline/Mods.hh>

423
include/ebcl/Pointers.hh Normal file
View file

@ -0,0 +1,423 @@
/******************************************************************************/
/* POINTERS *******************************************************************/
/******************************************************************************/
#ifndef _H_LW_LIB_POINTERS
#define _H_LW_LIB_POINTERS
#include <lw/lib/Utilities.hh>
namespace lw {
template< typename T > class T_OwnPtr;
template< typename T > class T_SharedPtr;
template< typename T > class T_WeakPtr;
/*= OWNING POINTERS ==========================================================*/
template< typename T >
class T_OwnPtr
{
template< typename RT , typename... AT >
friend T_OwnPtr< RT > NewOwned( AT&& ... arguments );
template<
typename RT
> friend T_OwnPtr< RT > OwnRawPointer( RT*& ) noexcept;
template<
typename RT , typename OT ,
T_EnableForChild< RT , OT >
> friend T_OwnPtr< RT > OwnRawPointer( OT*& ) noexcept;
template<
typename RT , typename OT ,
T_EnableForParent< RT , OT >
> friend T_OwnPtr< RT > OwnRawPointer( OT*& );
template< typename >
friend class T_OwnPtr;
friend T_SharedPtr< T >;
private:
typedef T_OwnPtr< T > MyType_;
T* p_;
T_OwnPtr( T* p ) noexcept;
public:
T_OwnPtr( );
~T_OwnPtr( );
T_OwnPtr( MyType_ const& ) = delete;
MyType_& operator= ( MyType_ const& ) = delete;
// ---------------------------------------------------------------------
template< typename Q , T_EnableForChild< T , Q > = true >
T_OwnPtr( T_OwnPtr< Q >&& source ) noexcept;
template< typename Q , T_EnableForParent< T , Q > = false >
explicit T_OwnPtr( T_OwnPtr< Q >&& source );
// ---------------------------------------------------------------------
template< typename Q , T_EnableForChild< T , Q > = true >
MyType_& operator= ( T_OwnPtr< Q >&& source ) noexcept;
template< typename Q , T_EnableForParent< T , Q > = false >
MyType_& operator= ( T_OwnPtr< Q >&& source );
// ---------------------------------------------------------------------
template< typename TP >
friend void swap( T_OwnPtr< TP >& lhs , T_OwnPtr< TP >& rhs ) noexcept;
void clear( );
bool operator== ( const T* p ) const;
bool operator!= ( const T* p ) const;
operator bool ( ) const;
bool operator! ( ) const;
T * get( ) const;
T* operator-> ( ) const;
T& operator* ( ) const;
T_SharedPtr< T > makeShared( );
};
// NewOwned< T >( ... ) - New T as an owned pointer
template<
typename Type ,
typename... ArgTypes
>
T_OwnPtr< Type > NewOwned( ArgTypes&& ... arguments );
// OwnRawPointer< T >( pointer ) - Transfer a raw pointer to an owned pointer.
// The raw pointer will be set to nullptr.
template< typename Type >
T_OwnPtr< Type > OwnRawPointer( Type*& pointer ) noexcept;
template<
typename Type , typename Other ,
T_EnableForChild< Type , Other > = true ,
std::enable_if_t< !std::is_same< Type , Other >::value , bool > = true
> T_OwnPtr< Type > OwnRawPointer( Other*& pointer ) noexcept;
template<
typename Type , typename Other ,
T_EnableForParent< Type , Other > = false
> T_OwnPtr< Type > OwnRawPointer( Other*& pointer );
/*= SHARED POINTERS ==========================================================*/
/* WARNING: these pointers are NOT thread-safe! */
class T_Reference_;
// Weak pointer chaining
struct T_WeakChain_
{
T_Reference_* * const ref;
T_WeakChain_* prev;
T_WeakChain_* next;
explicit T_WeakChain_( T_Reference_*& ref );
void unchain( );
void init( );
};
// Base class for shared and weak pointers
template< typename T >
class T_BasePtr_
{
protected:
typedef T_BasePtr_< T > T_Base_;
T_Reference_* ref_;
explicit T_BasePtr_( T_Reference_* ref ) noexcept;
T_BasePtr_( ) = delete;
T_BasePtr_( T_Base_ const& ) = delete;
T_BasePtr_( T_Base_&& ) = delete;
public:
operator bool ( ) const;
bool operator! ( ) const;
T* operator-> ( ) const;
explicit operator T* ( ) const;
T& operator* ( ) const;
};
// Exception thrown when makeOwned( ) is called on a shared pointers that has
// more than one reference.
class X_TooManyReferences : public std::runtime_error
{
public:
X_TooManyReferences( );
};
// T_SharedPtr< T > - Shared pointer implementation
template< typename T >
class T_SharedPtr : public T_BasePtr_< T >
{
private:
typedef T_BasePtr_< T > T_Base_;
typedef T_SharedPtr< T > T_Self_;
typedef T_WeakPtr< T > T_Weak_;
template< typename >
friend class T_SharedPtr;
template< typename >
friend class T_WeakPtr;
template<
typename RT
> friend T_SharedPtr< RT > ShareRawPointer( RT*& ) noexcept;
template<
typename RT , typename OT ,
T_EnableForChild< RT , OT >
> friend T_SharedPtr< RT > ShareRawPointer( OT*& ) noexcept;
template<
typename RT , typename OT ,
T_EnableForParent< RT , OT >
> friend T_SharedPtr< RT > ShareRawPointer( OT*& );
template< typename OT , typename... AT >
friend T_SharedPtr< OT > NewShared( AT&& ... arguments );
friend T_OwnPtr< T >;
using T_Base_::ref_;
T_Reference_ * setRef( T_Reference_* from );
void clearRef( );
explicit T_SharedPtr( T* ptr );
public:
T_SharedPtr( ) noexcept;
~T_SharedPtr( );
// ---------------------------------------------------------------------
// Copy constructors
T_SharedPtr( T_Self_ const& source );
template< typename Q , T_EnableForChild< T , Q > = true >
T_SharedPtr( T_SharedPtr< Q > const& source );
template< typename Q , T_EnableForParent< T , Q > = false >
explicit T_SharedPtr( T_SharedPtr< Q > const& source );
// ---------------------------------------------------------------------
// Move constructors
template< typename Q , T_EnableForChild< T , Q > = true >
T_SharedPtr( T_SharedPtr< Q >&& source ) noexcept;
template< typename Q , T_EnableForParent< T , Q > = false >
explicit T_SharedPtr( T_SharedPtr< Q >&& source );
// ---------------------------------------------------------------------
// Copy assignment operators
T_Self_& operator= ( T_Self_ const& other );
template< typename Q , T_EnableForChild< T , Q > = true >
T_Self_& operator= ( T_SharedPtr< Q > const& other );
template< typename Q , T_EnableForParent< T , Q > = false >
T_Self_& operator= ( T_SharedPtr< Q > const& other );
// ---------------------------------------------------------------------
// Move assignment operators
template< typename Q , T_EnableForChild< T , Q > = true >
T_Self_& operator= ( T_SharedPtr< Q >&& other ) noexcept;
template< typename Q , T_EnableForParent< T , Q > = false >
T_Self_& operator= ( T_SharedPtr< Q >&& other );
// ---------------------------------------------------------------------
template< typename TP >
friend void swap( T_SharedPtr< TP >& lhs , T_SharedPtr< TP >& rhs ) noexcept;
bool operator== ( T_Self_ const& other ) const;
bool operator!= ( T_Self_ const& other ) const;
bool operator== ( T_Weak_ const& other ) const;
bool operator!= ( T_Weak_ const& other ) const;
void clear( );
T_OwnPtr< T > makeOwned( );
};
// T_WeakPtr< T > - Weak pointer implementation
template< typename T >
class T_WeakPtr : public T_BasePtr_< T >
{
private:
typedef T_BasePtr_< T > T_Base_;
typedef T_SharedPtr< T > T_Shared_;
typedef T_WeakPtr< T > T_Self_;
template< typename > friend class T_SharedPtr;
template< typename > friend class T_WeakPtr;
friend T_Reference_;
using T_Base_::ref_;
T_WeakChain_ chain_;
T_WeakPtr( T_Reference_* ref );
public:
T_WeakPtr( );
~T_WeakPtr( );
// ---------------------------------------------------------------------
// Copy constructors
T_WeakPtr( T_Self_ const& other );
template< typename Q , T_EnableForChild< T , Q > = true >
T_WeakPtr( T_WeakPtr< Q > const& other );
template< typename Q , T_EnableForParent< T , Q > = false >
explicit T_WeakPtr( T_WeakPtr< Q > const& other );
// ---------------------------------------------------------------------
// Move constructors
template< typename Q , T_EnableForChild< T , Q > = true >
T_WeakPtr( T_WeakPtr< Q >&& other ) noexcept;
template< typename Q , T_EnableForParent< T , Q > = false >
explicit T_WeakPtr( T_WeakPtr< Q >&& other );
// ---------------------------------------------------------------------
// Construct from shared pointer
explicit T_WeakPtr( T_Shared_ const& shared );
template< typename Q , T_EnableForChild< T , Q > = true >
explicit T_WeakPtr( T_SharedPtr< Q > const& shared );
template< typename Q , T_EnableForParent< T , Q > = false >
explicit T_WeakPtr( T_SharedPtr< Q > const& shared );
explicit T_WeakPtr( T_Shared_&& shared ) = delete;
// ---------------------------------------------------------------------
// Copy assignment operators
T_Self_& operator= ( T_Self_ const& other );
template< typename Q , T_EnableForChild< T , Q > = true >
T_Self_& operator =( T_WeakPtr< Q > const& other );
template< typename Q , T_EnableForParent< T , Q > = false >
T_Self_& operator =( T_WeakPtr< Q > const& other );
// ---------------------------------------------------------------------
// Move assignment operators
template< typename Q , T_EnableForChild< T , Q > = true >
T_Self_& operator =( T_WeakPtr< Q >&& other );
template< typename Q , T_EnableForParent< T , Q > = false >
T_Self_& operator =( T_WeakPtr< Q >&& other );
// ---------------------------------------------------------------------
// Assign from shared pointer
T_Self_& operator= ( T_Shared_ const& shared );
template< typename Q , T_EnableForChild< T , Q > = true >
T_Self_& operator= ( T_SharedPtr< Q > const& shared );
template< typename Q , T_EnableForParent< T , Q > = false >
T_Self_& operator= ( T_SharedPtr< Q > const& shared );
T_Self_& operator= ( T_Shared_&& ) = delete;
// ---------------------------------------------------------------------
template< typename TP >
friend void swap( T_WeakPtr< TP >& lhs , T_WeakPtr< TP >& rhs );
bool operator== ( T_Self_ const& other ) const;
bool operator!= ( T_Self_ const& other ) const;
bool operator== ( T_Shared_ const& other ) const;
bool operator!= ( T_Shared_ const& other ) const;
void clear( );
};
// NewShared< T >( ... ) - New T as shared pointer
template<
typename Type ,
typename... ArgTypes
>
T_SharedPtr< Type > NewShared( ArgTypes&& ... arguments );
// ShareRawPointer< T >( pointer ) - Transfer a raw pointer to a shared pointer.
// The raw pointer will be set to nullptr.
template< typename Type >
T_SharedPtr< Type > ShareRawPointer(
Type*& pointer ) noexcept;
template<
typename Type , typename Other ,
T_EnableForChild< Type , Other > = true ,
std::enable_if_t< !std::is_same< Type , Other >::value , bool > = true
> T_SharedPtr< Type > ShareRawPointer(
Other*& pointer ) noexcept;
template<
typename Type , typename Other ,
T_EnableForParent< Type , Other > = false
> T_SharedPtr< Type > ShareRawPointer( Other*& pointer );
/*= HELPER MACROS ============================================================*/
#define M_CLASS_POINTERS( NAME ) \
typedef T_ ## NAME* RP_ ## NAME; \
typedef T_ ## NAME const* RPC_ ## NAME; \
typedef T_OwnPtr< T_ ## NAME > OP_ ## NAME; \
typedef T_SharedPtr< T_ ## NAME > SP_ ## NAME; \
typedef T_WeakPtr< T_ ## NAME > WP_ ## NAME
#define M_ABSTRACT_POINTERS( NAME ) \
typedef A_ ## NAME* RP_ ## NAME; \
typedef A_ ## NAME const* RPC_ ## NAME; \
typedef T_OwnPtr< A_ ## NAME > OP_ ## NAME; \
typedef T_SharedPtr< A_ ## NAME > SP_ ## NAME; \
typedef T_WeakPtr< A_ ## NAME > WP_ ## NAME
#define M_TEMPLATE_POINTERS( NAME ) \
typedef NAME* RP; \
typedef NAME const* RPC; \
typedef T_OwnPtr< NAME > OP; \
typedef T_SharedPtr< NAME > SP; \
typedef T_WeakPtr< NAME > WP
} // namespace
#endif // _H_LW_LIB_POINTERS
#include <lw/lib/inline/Pointers.hh>

View file

@ -0,0 +1,85 @@
/******************************************************************************/
/* REGISTRATION SUPPORT *******************************************************/
/******************************************************************************/
#ifndef _H_LW_LIB_REGISTRATION
#define _H_LW_LIB_REGISTRATION
#include <lw/lib/Utilities.hh>
#include <lw/lib/Pointers.hh>
namespace lw {
/*= REGISTRATION SUPPORT =====================================================*/
/* This class is meant to be used with any class that supports registration of
* items (for example the VFS to which VFS drivers are added).
*
* It must be returned from registration methods, and will serve as a way to
* unregister an item, either directly using the unregister() method, or
* automatically when the instance is destroyed (if automatic unregistration
* is active, which is the default).
*/
class T_RegisteredItem
{
public:
using F_Unregister = std::function< void( void* ) >;
using SP_Unregister = T_SharedPtr< F_Unregister >;
private:
using F_Destructor_ = std::function< void( void* ) >;
using WP_Unregister_ = T_WeakPtr< F_Unregister >;
bool automatic_;
WP_Unregister_ unregisterFunction_;
void* data_;
F_Destructor_ dataDestructor_;
public:
/* Initialise an empty item (indicates registration failure) */
T_RegisteredItem( ) noexcept;
/* Initialise a registered item */
T_RegisteredItem( SP_Unregister& unregisterFunction ,
void* data ,
F_Destructor_ destructor ) noexcept;
template< typename T >
T_RegisteredItem( SP_Unregister& unregisterFunction ,
T* data ) noexcept;
/* Destructor. Will unregister the item if automatic mode is
* enabled */
~T_RegisteredItem( );
/* Copy is disabled */
T_RegisteredItem( T_RegisteredItem const& ) = delete;
T_RegisteredItem& operator =( T_RegisteredItem const& ) = delete;
/* Move and swap */
T_RegisteredItem( T_RegisteredItem&& other ) noexcept;
T_RegisteredItem& operator =( T_RegisteredItem&& other ) noexcept;
friend M_DECLARE_SWAP( T_RegisteredItem );
/* Set whether this registrable will unregister automatically when
* it is deleted. */
void automatic( bool v ) noexcept;
bool automatic( ) const noexcept;
/* Unregister this item. May be called multiple times; the first
* call will unregister the item, other calls will be ignored.
*/
void unregister( ) noexcept;
/* Registration check */
operator bool( ) const noexcept;
private:
void clear( ) noexcept;
void deleteData( ) noexcept;
};
M_CLASS_POINTERS( RegisteredItem );
M_DECLARE_SWAP( T_RegisteredItem );
} // namespace
#endif // _H_LW_LIB_REGISTRATION
#include <lw/lib/inline/Registration.hh>

78
include/ebcl/SRDBinary.hh Normal file
View file

@ -0,0 +1,78 @@
/******************************************************************************/
/* SRD - BINARY STORAGE *******************************************************/
/******************************************************************************/
#ifndef _H_LW_LIB_SRDBINARY
#define _H_LW_LIB_SRDBINARY
#include <lw/lib/SRDIO.hh>
#include <lw/lib/HashIndex.hh>
namespace lw {
/*= WRITER ===================================================================*/
class T_SRDBinaryWriter : public A_SRDWriter
{
private:
T_BinaryWriter writer_;
T_HashIndex wordsIndex_;
T_Array< T_String > words_;
T_StringBuilder comment_;
uint32_t depth_;
void flushComment( );
void writeWord( T_String const& word );
public:
T_SRDBinaryWriter( ) = delete;
T_SRDBinaryWriter( T_SRDBinaryWriter const& ) = delete;
T_SRDBinaryWriter( T_SRDBinaryWriter&& ) = delete;
explicit T_SRDBinaryWriter( A_OutputStream& output );
T_SRDBinaryWriter& start( ) override;
T_SRDBinaryWriter& startList( ) override;
T_SRDBinaryWriter& endList( ) override;
T_SRDBinaryWriter& putText( T_String const& text ) override;
T_SRDBinaryWriter& putWord( T_String const& word ) override;
T_SRDBinaryWriter& putString( T_String const& string ) override;
T_SRDBinaryWriter& putComment( T_String const& comment ) override;
T_SRDBinaryWriter& putVariable( T_String const& variable ) override;
T_SRDBinaryWriter& putBinary( T_Buffer< uint8_t > const& binary ) override;
T_SRDBinaryWriter& putInteger( int64_t value ) override;
T_SRDBinaryWriter& putInt32( int32_t value ) override;
T_SRDBinaryWriter& putInt64( int64_t value ) override;
T_SRDBinaryWriter& putFloat( double value ) override;
T_SRDBinaryWriter& end( ) override;
};
void SRDBinaryWriteTo( A_OutputStream& output , T_SRDList const& data );
/*= READER ===================================================================*/
class T_SRDBinaryReader : public A_SRDReader
{
public:
T_SRDBinaryReader( ) = delete;
T_SRDBinaryReader( T_SRDBinaryReader const& ) = delete;
T_SRDBinaryReader( T_SRDBinaryReader&& ) = delete;
T_SRDBinaryReader( A_SRDReaderTarget& target );
void read( T_String const& name , A_InputStream& input ) override;
};
T_SRDList SRDBinaryReadFrom( T_String const& name , A_InputStream& input , bool structured = true );
} // namespace
#include <lw/lib/inline/SRDBinary.hh>
#endif // _H_LW_LIB_SRDBINARY

361
include/ebcl/SRDData.hh Normal file
View file

@ -0,0 +1,361 @@
/******************************************************************************/
/* SRD - DATA *****************************************************************/
/******************************************************************************/
#ifndef _H_LW_LIB_SRDDATA
#define _H_LW_LIB_SRDDATA
#include <lw/lib/Externals.hh>
#include <lw/lib/Strings.hh>
#include <lw/lib/Types.hh>
namespace lw {
class T_Logger;
// Forward declarations
struct T_SRDLocationChaining;
M_CLASS_POINTERS( SRDLocationChaining );
class T_SRDLocation;
M_CLASS_POINTERS( SRDLocation );
class T_SRDToken;
M_CLASS_POINTERS( SRDToken );
/*= SOURCE LOCATIONS =========================================================*/
// E_SRDLocationChaining - Token location chaining circumstances
enum class E_SRDLocationChaining {
INCLUDED ,
LOADED ,
CALLED ,
GENERATED ,
SUBSTITUTED ,
EVALUATED ,
EXPANDED
};
/*----------------------------------------------------------------------------*/
// T_SRDLocationChaining - Token location chaining structure
struct T_SRDLocationChaining
{
E_SRDLocationChaining circumstances;
uint32_t depth;
SP_SRDLocation location;
T_SRDLocationChaining(
E_SRDLocationChaining how ,
uint32_t depth ,
SP_SRDLocation const& to ) noexcept;
bool isGenerated( ) const noexcept;
};
/*----------------------------------------------------------------------------*/
// T_SRDLocation - Token source location information
class T_SRDLocation
{
private:
T_String source_;
uint32_t line_;
size_t character_;
T_Optional< T_SRDLocationChaining > chaining_;
public:
// SRD locations are pooled
void* operator new( size_t count ) noexcept;
void operator delete( void* object ) noexcept;
// ---------------------------------------------------------------------
// Unknown location
T_SRDLocation( ) noexcept;
// Text input location
T_SRDLocation( T_String const& source ,
uint32_t line ,
size_t character ) noexcept;
// Binary input location
T_SRDLocation( T_String const& source ,
size_t byte ) noexcept;
// Location of a token
explicit T_SRDLocation(
T_SRDToken const& token ) noexcept;
T_SRDLocation( T_SRDLocation const& other ) noexcept;
T_SRDLocation& operator= ( T_SRDLocation const& other ) noexcept;
T_SRDLocation( T_SRDLocation&& other ) noexcept;
T_SRDLocation& operator= ( T_SRDLocation&& other ) noexcept;
friend M_DECLARE_SWAP( T_SRDLocation );
// ---------------------------------------------------------------------
void chain( E_SRDLocationChaining how ,
SP_SRDLocation const& to ) noexcept;
void chain( E_SRDLocationChaining how ,
uint32_t depth ,
SP_SRDLocation const& to ) noexcept;
void clearChain( ) noexcept;
// ---------------------------------------------------------------------
bool unknown( ) const noexcept;
T_String const& source( ) const noexcept;
bool binary( ) const noexcept;
uint32_t line( ) const noexcept;
size_t character( ) const noexcept;
size_t byte( ) const noexcept;
bool isChained( ) const noexcept;
T_SRDLocationChaining const& chaining( ) const noexcept;
};
M_DECLARE_SWAP( T_SRDLocation );
M_LSHIFT_OP( T_StringBuilder , T_SRDLocation ) noexcept;
/*= ERRORS ===================================================================*/
// An error that occurred during SRD processing
class T_SRDError
{
private:
T_String error_;
T_SRDLocation location_;
bool isDetails_;
public:
T_SRDError( ) = delete;
T_SRDError( T_String error ,
T_SRDLocation location ,
bool details = false ) noexcept;
T_SRDError( T_SRDError const& other ) noexcept;
T_SRDError& operator= ( T_SRDError const& other ) noexcept;
T_SRDError( T_SRDError&& other ) noexcept;
T_SRDError& operator= ( T_SRDError&& other ) noexcept;
friend M_DECLARE_SWAP( T_SRDError );
// ---------------------------------------------------------------------
T_String const& error( ) const noexcept;
T_SRDLocation const& location( ) const noexcept;
bool isDetails( ) const noexcept;
};
M_DECLARE_SWAP( T_SRDError );
/*----------------------------------------------------------------------------*/
// List of errors
class T_SRDErrors
{
public:
enum : uint32_t { MAX_ERRORS = 40 };
private:
T_AutoArray< T_SRDError , MAX_ERRORS / 2 > errors_;
uint32_t errCount_ = 0;
public:
// ---------------------------------------------------------------------
template< typename ... ArgTypes >
void add( char const* error ,
ArgTypes&&... locationArgs );
template< typename ... ArgTypes >
void add( T_String const& error ,
ArgTypes&&... locationArgs );
template< typename ... ArgTypes >
void details( char const* message ,
ArgTypes&&... locationArgs );
template< typename ... ArgTypes >
void details( T_String const& message ,
ArgTypes&&... locationArgs );
template< typename ... ArgTypes >
void add( InPlace , ArgTypes&&... args );
void add( T_SRDError const& error );
void add( T_SRDError&& error );
void addAll( T_SRDErrors const& errors );
// ---------------------------------------------------------------------
uint32_t size( ) const noexcept;
T_SRDError const& operator[] ( uint32_t index ) const noexcept;
void clear( ) noexcept;
// ---------------------------------------------------------------------
private:
void checkAdded( T_SRDError const& last );
};
M_CLASS_POINTERS( SRDErrors );
/*----------------------------------------------------------------------------*/
// SRD processing exception
class X_SRDErrors : public std::exception
{
public:
const T_SRDErrors errors;
X_SRDErrors( T_SRDErrors const& errors );
char const * what( ) const noexcept override;
#ifndef LW_MINLIB
void log( T_Logger& logger ) const;
#endif // LW_MINLIB
};
/*= TOKENS ===================================================================*/
// E_SRDTokenType - Token types
enum class E_SRDTokenType {
LIST , // Complete list
START , // List start
END , // List end
WORD , // Word
VAR , // Variable
STRING , // Quoted string
BINARY , // Binary data
INT , // Integer (32 bits)
LONG , // Integer (64 bits)
FLOAT , // Floating point value
COMMENT , // Commented text
FLUSH , // Special token that causes a parser to flush
};
T_StringBuilder& operator<< ( T_StringBuilder& sb , E_SRDTokenType tt );
// T_SRDList - Token lists
using T_SRDList = T_Array< T_SRDToken >;
M_CLASS_POINTERS( SRDList );
// T_SRDToken - Token data
class T_SRDToken
{
private:
using T_BinData_ = T_SharedPtr< T_Buffer< uint8_t > >;
E_SRDTokenType type_; // Token type
T_String text_; // Token's full string
OP_SRDList list_; // List of tokens (type == LIST)
int64_t longValue_; // 64-bit integer value
double floatValue_; // 64-bit floating point value
T_String stringValue_; // String value
T_BinData_ binary_; // Binary data
SP_SRDLocation location_;
T_SRDToken( ) = default;
T_SRDToken( const E_SRDTokenType type ) noexcept;
public:
// ---------------------------------------------------------------------
static bool IsWord( T_String const& string );
// ---------------------------------------------------------------------
static T_SRDToken ListStart( );
static T_SRDToken ListEnd( );
static T_SRDToken List( );
static T_SRDToken List( T_SRDList const& list );
static T_SRDToken List( T_SRDList&& list );
// Either a Word or a String, depending on the contents
static T_SRDToken AutoText( T_String text );
static T_SRDToken Word( T_String word );
static T_SRDToken String( T_String string );
static T_SRDToken Variable( T_String variable );
static T_SRDToken Comment( T_String text );
// Binary data
static T_SRDToken Binary(
T_BinData_ const& data ) noexcept;
template< typename T >
static T_SRDToken Binary(
T const* data ,
uint32_t count ) noexcept;
template< typename T >
static T_SRDToken Binary(
T_Buffer< T > const& data ) noexcept;
// A Long or an Int, depending on the value
static T_SRDToken AutoInteger( int64_t value );
static T_SRDToken Integer( int32_t value );
static T_SRDToken Long( int64_t value );
static T_SRDToken Float( double value );
// A special "flush" token
static T_SRDToken Flush( ) noexcept;
// ---------------------------------------------------------------------
T_SRDToken( T_SRDToken const& other );
T_SRDToken( T_SRDToken&& other ) noexcept;
T_SRDToken& operator= ( T_SRDToken const& other );
T_SRDToken& operator= ( T_SRDToken&& other ) noexcept;
friend void swap( T_SRDToken& lhs , T_SRDToken& rhs ) noexcept;
// ---------------------------------------------------------------------
E_SRDTokenType type( ) const;
bool isText( ) const;
bool isNumeric( ) const;
bool isInteger( ) const;
T_String const& text( ) const;
T_SRDList const& list( ) const;
T_SRDList& list( );
int64_t longValue( ) const;
double floatValue( ) const;
T_String const& stringValue( ) const;
T_Buffer< uint8_t > const& binary( ) const;
// ---------------------------------------------------------------------
int compare( T_SRDToken const& other ) const;
bool operator ==( T_SRDToken const& other ) const;
bool operator !=( T_SRDToken const& other ) const;
bool operator >( T_SRDToken const& other ) const;
bool operator <( T_SRDToken const& other ) const;
bool operator >=( T_SRDToken const& other ) const;
bool operator <=( T_SRDToken const& other ) const;
// ---------------------------------------------------------------------
bool hasFullText( ) const;
T_String fullText( ) const;
T_SRDToken& setFullText( T_String text );
T_SRDToken& generateFullText( );
// ---------------------------------------------------------------------
bool hasLocation( ) const noexcept;
T_SRDLocation const& location( ) const noexcept;
T_SRDLocation& location( ) noexcept;
T_SRDToken& location( T_String const& source , size_t byte );
T_SRDToken& location( T_String const& source , uint32_t line , size_t character );
T_SRDToken& location( T_SRDLocation const& other );
T_SRDToken& location( T_SRDLocation&& other );
T_SRDToken& copyLocationOf( T_SRDToken const& other );
};
void swap( T_SRDToken& lhs , T_SRDToken& rhs ) noexcept;
M_DECLARE_COMPARATOR( T_SRDToken );
extern template class T_Array< T_SRDToken >;
} // namespace
#include <lw/lib/inline/SRDData.hh>
#endif // _H_LW_LIB_SRDDATA

View file

@ -0,0 +1,321 @@
/******************************************************************************/
/* SRD - PARSER DEFINITIONS ***************************************************/
/******************************************************************************/
#ifndef _H_LW_LIB_SRDDEFINITIONS
#define _H_LW_LIB_SRDDEFINITIONS
#include <lw/lib/SRDData.hh>
#include <lw/lib/HashTables.hh>
namespace lw {
/*= DEFINITION DATA ==========================================================*/
// Full definition -> {contexts}, default context, {enums}
// Context -> name, {rules}
// Rule -> Accepted input, [context, [init], [exit]], [executor]
// Input def -> Word
// | Enum
// | Token type
// | Alternatives
// | Repetition
// Alternatives -> {input def}
// Repetition -> Input sequence, min count, max count
// Forward declarations
struct T_SRDParserData;
/*----------------------------------------------------------------------------*/
// F_SRDHandler - Parser callbacks
using F_SRDHandler = std::function< bool( T_SRDParserData const& ) >;
/*----------------------------------------------------------------------------*/
// T_SRDEnum - an enumeration
// i.e. set of words with associated sequence of integers, that can be
// recognized as a single input token.
class T_SRDEnum
{
private:
T_String name_;
T_HashIndex index_;
T_Array< T_String > words_;
public:
T_SRDEnum( ) = delete;
T_SRDEnum( T_String name );
T_SRDEnum( T_SRDEnum const& ) = default;
T_SRDEnum( T_SRDEnum && ) = default;
T_SRDEnum & operator <<( T_String && word );
T_SRDEnum & operator <<( char const* word );
T_String const& name( ) const;
auto size( ) const;
T_String const& operator[]( int index ) const;
T_String const& operator[]( uint32_t index ) const;
uint32_t operator[]( T_String const& word ) const;
uint32_t operator[]( char const* word ) const;
bool contains( T_String const& word ) const;
bool contains( char const* word ) const;
};
/*----------------------------------------------------------------------------*/
// E_SRDInputItem - Possible types for input definition elements
enum class E_SRDInputItem
{
WORD , // A specific word
ENUM , // A word from an enumeration
TOKEN , // An arbitrary token
ALTERNATIVE , // A set of alternative rules
REPETITION , // Repetition of a sequence
};
/*----------------------------------------------------------------------------*/
// T_SRDInputItem - An element from an input definition
class T_SRDInputItem
{
public:
struct T_ListHelper {
T_Array< T_SRDInputItem > items;
T_ListHelper( );
T_ListHelper& operator <<( T_SRDInputItem item );
};
private:
E_SRDInputItem type_;
T_String word_;
E_SRDTokenType token_;
T_Array< T_SRDInputItem > items_;
uint32_t min_ , max_;
public:
// Construct an ALTERNATIVE input element
T_SRDInputItem( );
// Construct either a WORD or an ENUM input element
T_SRDInputItem( T_String wordOrName , bool isWord );
// Construct a WORD from a C string
T_SRDInputItem( char const* cString );
// Construct a TOKEN input element
T_SRDInputItem( E_SRDTokenType type );
// Construct a REPETITION input element
T_SRDInputItem( uint32_t min , uint32_t max );
friend void swap( T_SRDInputItem & lhs , T_SRDInputItem & rhs ) noexcept;
T_SRDInputItem( T_SRDInputItem const& ) = default;
T_SRDInputItem( T_SRDInputItem && ) noexcept = default;
T_SRDInputItem & operator=( T_SRDInputItem const& ) = default;
T_SRDInputItem & operator=( T_SRDInputItem && ) = default;
E_SRDInputItem type( ) const;
T_String const& word( ) const;
E_SRDTokenType token( ) const;
T_Array< T_SRDInputItem > items( ) const;
uint32_t min( ) const;
uint32_t max( ) const;
T_SRDInputItem & operator <<( T_SRDInputItem item );
T_SRDInputItem& operator <<( T_ListHelper list );
// This operator is not actually used. It's only here to make the template
// instantiation happy. It actually returns false.
bool operator ==( T_SRDInputItem const& other ) const;
};
void swap( T_SRDInputItem & lhs , T_SRDInputItem & rhs ) noexcept;
T_StringBuilder & operator <<( T_StringBuilder & sb , T_SRDInputItem const& item );
T_Array< T_SRDInputItem >& operator <<( T_Array< T_SRDInputItem > & items ,
T_SRDInputItem::T_ListHelper& list );
extern template class T_Array< T_SRDInputItem >;
/*----------------------------------------------------------------------------*/
// T_SRDInputRule - A full rule from a context
class T_SRDInputRule
{
public:
struct T_SetContextExecutor {
const bool exit;
const F_SRDHandler executor;
T_SetContextExecutor( bool exit , F_SRDHandler executor );
};
struct T_SetContext {
const T_String name;
T_SetContext( T_String string );
};
private:
F_SRDHandler executor_;
T_Array< T_SRDInputItem > items_;
T_String context_;
F_SRDHandler contextEnter_;
F_SRDHandler contextExit_;
public:
T_SRDInputRule & operator <<( T_SRDInputItem item );
T_SRDInputRule & operator <<( F_SRDHandler executor );
T_SRDInputRule & operator <<( T_SetContextExecutor sce );
T_SRDInputRule & operator <<( T_SetContext sc );
T_SRDInputRule & operator <<( T_SRDInputItem::T_ListHelper sc );
F_SRDHandler const& handler( ) const;
T_Array< T_SRDInputItem > const& rule( ) const;
T_String const& context( ) const;
F_SRDHandler const& onEnter( ) const;
F_SRDHandler const& onExit( ) const;
};
T_StringBuilder & operator <<( T_StringBuilder & sb , T_SRDInputRule const& item );
/*----------------------------------------------------------------------------*/
// T_SRDContext - A set of rules that will share common data
class T_SRDContext
{
private:
T_String name_;
T_String parent_;
T_Array< T_SRDInputRule > rules_;
public:
T_SRDContext( ) = delete;
explicit T_SRDContext( T_String name , T_String parent = T_String( ) );
T_SRDContext & operator <<( T_SRDInputRule rule );
T_String const& name( ) const;
T_String const& parent( ) const;
T_Array< T_SRDInputRule > const& rules( ) const;
T_StringBuilder & dump( T_StringBuilder & sb , T_String const& separator );
};
/*----------------------------------------------------------------------------*/
// T_SRDParserDefs - All definitions for a parser
class T_SRDParserDefs
{
public:
// SetHandler - Used to set start/end handlers
struct SetHandler
{
const F_SRDHandler handler;
const bool start;
SetHandler( F_SRDHandler const& handler , bool start );
};
private:
T_String dfCtx_;
T_ObjectTable< T_String , T_SRDContext > ctx_;
T_ObjectTable< T_String , T_SRDEnum > enums_;
F_SRDHandler onStart_;
F_SRDHandler onFinish_;
public:
T_SRDParserDefs( ) = delete;
explicit T_SRDParserDefs( T_String defaultContext );
explicit T_SRDParserDefs( char const* defaultContext );
T_String const& defaultContext( ) const;
void defaultContext( T_String const& name );
void defaultContext( char const* name );
T_SRDParserDefs & operator <<( SetHandler sh );
F_SRDHandler const& onStart( ) const;
F_SRDHandler const& onFinish( ) const;
uint32_t contexts( ) const;
T_SRDContext & operator[]( uint32_t idx );
T_SRDContext const& operator[]( uint32_t idx ) const;
uint32_t contextId( T_String const& name ) const;
T_SRDContext & context( T_String const& name );
T_SRDContext & context( char const* name );
T_SRDContext & context( T_String const& name , T_String const& parent );
T_SRDContext & context( char const* name , char const* parent );
uint32_t enums( ) const;
bool hasEnum( T_String const& name ) const;
T_SRDEnum & enumeration( char const* name );
T_SRDEnum & enumeration( T_String const& name );
T_SRDEnum const& enumeration( T_String const& name ) const;
};
M_CLASS_POINTERS( SRDParserDefs );
/*= PARSER DEFINITIONS HELPERS ===============================================*/
namespace SRD {
T_SRDParserDefs::SetHandler OnStart( F_SRDHandler const& handler );
T_SRDParserDefs::SetHandler OnFinish( F_SRDHandler const& handler );
T_SRDContext Context( T_String name );
T_SRDContext Context( char const* name );
T_SRDContext Context( char const* name , char const* parent );
T_SRDContext Context( T_String name , T_String parent );
T_SRDInputRule Rule( );
T_SRDEnum CreateEnum( T_String name );
T_SRDEnum CreateEnum( char const* name );
T_SRDInputItem Word( T_String const& word );
T_SRDInputItem Word( char const* word );
T_SRDInputItem Word( );
T_SRDInputItem String( );
T_SRDInputItem Binary( );
T_SRDInputItem LStart( );
T_SRDInputItem LEnd( );
T_SRDInputItem Int32( );
T_SRDInputItem Int64( );
T_SRDInputItem Float( );
T_SRDInputItem Enum( T_String name );
T_SRDInputItem Enum( char const* name );
T_SRDInputItem::T_ListHelper List( );
T_SRDInputItem Alt( );
T_SRDInputItem Sub( );
T_SRDInputItem Opt( );
T_SRDInputItem Opt( T_SRDInputItem item );
T_SRDInputItem AtLeast( uint32_t n );
T_SRDInputItem AtMost( uint32_t n );
T_SRDInputItem Times( uint32_t n );
T_SRDInputItem Between( uint32_t a , uint32_t b );
T_SRDInputItem Integer( );
T_SRDInputItem Numeric( );
T_SRDInputItem Text( );
T_SRDInputRule::T_SetContext EnterContext( T_String name );
T_SRDInputRule::T_SetContext EnterContext( char const* name );
T_SRDInputRule::T_SetContextExecutor OnEnter( F_SRDHandler f );
T_SRDInputRule::T_SetContextExecutor OnExit( F_SRDHandler f );
} // namespace SRD
} // namespace
#include <lw/lib/inline/SRDDefinitions.hh>
#endif // _H_LW_LIB_SRDDEFINITIONS

187
include/ebcl/SRDIO.hh Normal file
View file

@ -0,0 +1,187 @@
/******************************************************************************/
/* SRD - INPUT AND OUTPUT *****************************************************/
/******************************************************************************/
#ifndef _H_LW_LIB_SRDIO
#define _H_LW_LIB_SRDIO
#include <lw/lib/SRDData.hh>
namespace lw {
/*= INPUT / OUTPUT ABSTRACTIONS ==============================================*/
// A_SRDWriter - Abstract SRD writer
class A_SRDWriter
{
protected:
A_SRDWriter( ) = default;
public:
A_SRDWriter( A_SRDWriter const& ) = delete;
A_SRDWriter( A_SRDWriter&& ) = delete;
virtual ~A_SRDWriter( ) = 0;
virtual A_SRDWriter& start( ) = 0;
virtual A_SRDWriter& startList( ) = 0;
virtual A_SRDWriter& endList( ) = 0;
A_SRDWriter& putList( T_SRDList const& list );
A_SRDWriter& putToken( T_SRDToken const& token );
virtual A_SRDWriter& putText( T_String const& text ) = 0;
virtual A_SRDWriter& putWord( T_String const& word ) = 0;
virtual A_SRDWriter& putString( T_String const& string ) = 0;
virtual A_SRDWriter& putComment( T_String const& comment ) = 0;
virtual A_SRDWriter& putVariable( T_String const& var ) = 0;
virtual A_SRDWriter& putBinary( T_Buffer< uint8_t > const& binary ) = 0;
virtual A_SRDWriter& putInteger( int64_t value ) = 0;
virtual A_SRDWriter& putInt32( int32_t value ) = 0;
virtual A_SRDWriter& putInt64( int64_t value ) = 0;
virtual A_SRDWriter& putFloat( double value ) = 0;
virtual A_SRDWriter& end( ) = 0;
};
M_ABSTRACT_POINTERS( SRDWriter );
/*----------------------------------------------------------------------------*/
// A_SRDReaderTarget - Abstract token receiver for SRD readers
class A_SRDReaderTarget
{
public:
virtual ~A_SRDReaderTarget( ) = 0;
virtual void start( T_SRDErrors& errors ) = 0;
virtual void push( T_SRDErrors& errors , T_SRDToken&& token ) = 0;
virtual void end( T_SRDErrors& errors ) = 0;
};
M_ABSTRACT_POINTERS( SRDReaderTarget );
/*----------------------------------------------------------------------------*/
// A_SRDReader - Abstract token reader
class A_SRDReader
{
protected:
A_SRDReaderTarget& target_;
public:
A_SRDReader( A_SRDReaderTarget& target );
virtual ~A_SRDReader( ) = 0;
virtual void read( T_String const& name , A_InputStream& input ) = 0;
};
M_ABSTRACT_POINTERS( SRDReader );
/*----------------------------------------------------------------------------*/
// X_SRDWriterError - SRD writer exception
class X_SRDWriterError : public std::exception
{
private:
char const* msg_;
public:
X_SRDWriterError( char const* msg ) noexcept;
X_SRDWriterError( ) = delete;
X_SRDWriterError( X_SRDWriterError const& ) = default;
X_SRDWriterError( X_SRDWriterError&& ) = default;
char const * what( ) const noexcept override;
};
/*= HELPERS ==================================================================*/
// T_SRDReaderTargetHelper - Calls start() and end() using RAII
class T_SRDReaderTargetHelper
{
private:
A_SRDReaderTarget& target_;
T_SRDErrors& errors_;
public:
T_SRDReaderTargetHelper( A_SRDReaderTarget& target , T_SRDErrors& errors );
~T_SRDReaderTargetHelper( );
};
/*----------------------------------------------------------------------------*/
// T_SRDListFixer - A stage that adds missing EOL's and discards extraneous
// EOL's, emitting errors as it does so.
class T_SRDListFixer final : public A_SRDReaderTarget
{
private:
A_SRDReaderTarget& output_;
T_AutoArray< T_SRDLocation , 32 > listStarts_;
public:
explicit T_SRDListFixer( A_SRDReaderTarget& output ) noexcept;
void start( T_SRDErrors& errors ) override;
void push( T_SRDErrors& errors ,
T_SRDToken&& token ) override;
void end( T_SRDErrors& errors ) override;
};
/*----------------------------------------------------------------------------*/
// T_SRDMemoryTarget - Stores the reader's output as a T_SRDList
class T_SRDMemoryTarget : public A_SRDReaderTarget
{
private:
const bool structured_;
bool clearFlushToken_;
T_SRDToken list_;
RP_SRDToken current_;
T_Array< RP_SRDToken > stack_;
public:
// If structured is set, the generated token list will include sub-lists
// as E_SRDTokenType::LIST tokens; if it isn't, the list will feature
// only start and end of list tokens.
explicit T_SRDMemoryTarget( bool structured = true );
// Set/get flush token handling
void clearFlushToken( bool clearIt ) noexcept;
bool clearFlushToken( ) const noexcept;
void start( T_SRDErrors& errors ) override;
void push( T_SRDErrors& errors , T_SRDToken&& token ) override;
void end( T_SRDErrors& errors ) override;
// Get the list
T_SRDList const& list( ) const;
// Does the list only contains complete items?
bool complete( ) const;
};
M_CLASS_POINTERS( SRDMemoryTarget );
/*----------------------------------------------------------------------------*/
// T_SRDWriterTarget - Forwards token that are read to a writer
class T_SRDWriterTarget : public A_SRDReaderTarget
{
private:
A_SRDWriter& writer_;
public:
explicit T_SRDWriterTarget( A_SRDWriter& writer );
void start( T_SRDErrors& errors ) override;
void push( T_SRDErrors& errors , T_SRDToken&& token ) override;
void end( T_SRDErrors& errors ) override;
};
M_CLASS_POINTERS( SRDWriterTarget );
} // namespace
#include <lw/lib/inline/SRDIO.hh>
#endif // _H_LW_LIB_SRDIO

View file

@ -0,0 +1,101 @@
/******************************************************************************/
/* SRD - PREPROCESSOR COMMANDS ************************************************/
/******************************************************************************/
#ifndef _H_LW_LIB_SRDPPCOMMANDS
#define _H_LW_LIB_SRDPPCOMMANDS
#include <lw/lib/SRDPreproc.hh>
namespace lw {
M_SRDPP_COMMAND_DECL( Add ); M_SRDPP_COMMAND_INIT( Add , "add" );
M_SRDPP_COMMAND_DECL( And ); M_SRDPP_COMMAND_INIT( And , "and" );
M_SRDPP_COMMAND_DECL( Bless ); M_SRDPP_COMMAND_INIT( Bless , "bless" );
M_SRDPP_COMMAND_DECL( Break ); M_SRDPP_COMMAND_INIT( Break , "break" );
M_SRDPP_COMMAND_DECL( BwAnd ); M_SRDPP_COMMAND_INIT( BwAnd , "bw-and" );
M_SRDPP_COMMAND_DECL( BwNot ); M_SRDPP_COMMAND_INIT( BwNot , "bw-not" );
M_SRDPP_COMMAND_DECL( BwOr ); M_SRDPP_COMMAND_INIT( BwOr , "bw-or" );
M_SRDPP_COMMAND_DECL( BwXor ); M_SRDPP_COMMAND_INIT( BwXor , "bw-xor" );
M_SRDPP_COMMAND_DECL( Call ); M_SRDPP_COMMAND_INIT( Call , "call" );
M_SRDPP_COMMAND_DECL( CastString ); M_SRDPP_COMMAND_INIT( CastString , "to-string" );
M_SRDPP_COMMAND_DECL( CastWord ); M_SRDPP_COMMAND_INIT( CastWord , "to-word" );
M_SRDPP_COMMAND_DECL( CastInt ); M_SRDPP_COMMAND_INIT( CastInt , "to-integer" );
M_SRDPP_COMMAND_DECL( CastLong ); M_SRDPP_COMMAND_INIT( CastLong , "to-long" );
M_SRDPP_COMMAND_DECL( CastBestInt ); M_SRDPP_COMMAND_INIT( CastBestInt , "to-best-integer" );
M_SRDPP_COMMAND_DECL( CastReal ); M_SRDPP_COMMAND_INIT( CastReal , "to-real" );
M_SRDPP_COMMAND_DECL( CastVar ); M_SRDPP_COMMAND_INIT( CastVar , "to-variable" );
M_SRDPP_COMMAND_DECL( CastList ); M_SRDPP_COMMAND_INIT( CastList , "to-list" );
M_SRDPP_COMMAND_DECL( ClearScope ); M_SRDPP_COMMAND_INIT_N( ClearScope , "clear-scope" , 0 );
M_SRDPP_COMMAND_DECL( Cmp ); M_SRDPP_COMMAND_INIT( Cmp , "cmp" );
M_SRDPP_COMMAND_DECL( CmpEq ); M_SRDPP_COMMAND_INIT( CmpEq , "eq" );
M_SRDPP_COMMAND_DECL( CmpNe ); M_SRDPP_COMMAND_INIT( CmpNe , "ne" );
M_SRDPP_COMMAND_DECL( CmpLt ); M_SRDPP_COMMAND_INIT( CmpLt , "lt" );
M_SRDPP_COMMAND_DECL( CmpGt ); M_SRDPP_COMMAND_INIT( CmpGt , "gt" );
M_SRDPP_COMMAND_DECL( CmpLe ); M_SRDPP_COMMAND_INIT( CmpLe , "le" );
M_SRDPP_COMMAND_DECL( CmpGe ); M_SRDPP_COMMAND_INIT( CmpGe , "ge" );
M_SRDPP_COMMAND_DECL( Concat ); M_SRDPP_COMMAND_INIT( Concat , "concat" );
M_SRDPP_COMMAND_DECL( Div ); M_SRDPP_COMMAND_INIT( Div , "div" );
M_SRDPP_COMMAND_DECL( EndsWith ); M_SRDPP_COMMAND_INIT( EndsWith , "ends-with" );
M_SRDPP_COMMAND_DECL( Eval ); M_SRDPP_COMMAND_INIT( Eval , "eval" );
M_SRDPP_COMMAND_DECL( Error ); M_SRDPP_COMMAND_INIT( Error , "error" );
M_SRDPP_COMMAND_DECL( FromSource ); M_SRDPP_COMMAND_INIT( FromSource , "from-source" );
M_SRDPP_COMMAND_DECL( FromSRB ); M_SRDPP_COMMAND_INIT( FromSRB , "from-srb" );
M_SRDPP_COMMAND_DECL( Get ); M_SRDPP_COMMAND_INIT( Get , "get" );
M_SRDPP_COMMAND_DECL( If ); M_SRDPP_COMMAND_INIT_N( If , "if" , 1 );
M_SRDPP_COMMAND_DECL( Ignore ); M_SRDPP_COMMAND_INIT_N( Ignore , "ignore" , 0 );
M_SRDPP_COMMAND_DECL( IsBlessed ); M_SRDPP_COMMAND_INIT( IsBlessed , "is-blessed" );
M_SRDPP_COMMAND_DECL( IsMacro ); M_SRDPP_COMMAND_INIT( IsMacro , "is-macro" );
M_SRDPP_COMMAND_DECL( IsSet ); M_SRDPP_COMMAND_INIT( IsSet , "is-set" );
M_SRDPP_COMMAND_DECL( Length ); M_SRDPP_COMMAND_INIT( Length , "length" );
M_SRDPP_COMMAND_DECL( ListMacros ); M_SRDPP_COMMAND_INIT_N( ListMacros , "ls-macros" , 0 );
M_SRDPP_COMMAND_DECL( ListVariables ); M_SRDPP_COMMAND_INIT_N( ListVariables , "ls-variables" , 0 );
M_SRDPP_COMMAND_DECL( Mod ); M_SRDPP_COMMAND_INIT( Mod , "mod" );
M_SRDPP_COMMAND_DECL( Mul ); M_SRDPP_COMMAND_INIT( Mul , "mul" );
M_SRDPP_COMMAND_DECL( Neg ); M_SRDPP_COMMAND_INIT( Neg , "neg" );
M_SRDPP_COMMAND_DECL( Not ); M_SRDPP_COMMAND_INIT( Not , "not" );
M_SRDPP_COMMAND_DECL( Or ); M_SRDPP_COMMAND_INIT( Or , "or" );
M_SRDPP_COMMAND_DECL( Output ); M_SRDPP_COMMAND_INIT( Output , "output" );
M_SRDPP_COMMAND_DECL( Raw ); M_SRDPP_COMMAND_INIT_N( Raw , "raw" , 0 );
M_SRDPP_COMMAND_DECL( Rethrow ); M_SRDPP_COMMAND_INIT( Rethrow , "rethrow" );
M_SRDPP_COMMAND_DECL( Scope ); M_SRDPP_COMMAND_INIT_N( Scope , "scope" , 0 );
M_SRDPP_COMMAND_DECL( Set ); M_SRDPP_COMMAND_INIT( Set , "set" );
M_SRDPP_COMMAND_DECL( SetMacro ); M_SRDPP_COMMAND_INIT( SetMacro , "set-macro" );
M_SRDPP_COMMAND_DECL( StartsWith ); M_SRDPP_COMMAND_INIT( StartsWith , "starts-with" );
M_SRDPP_COMMAND_DECL( StrFind ); M_SRDPP_COMMAND_INIT( StrFind , "str-find" );
M_SRDPP_COMMAND_DECL( StrSplit ); M_SRDPP_COMMAND_INIT( StrSplit , "str-split" );
M_SRDPP_COMMAND_DECL( Sub ); M_SRDPP_COMMAND_INIT( Sub , "sub" );
M_SRDPP_COMMAND_DECL( Substr ); M_SRDPP_COMMAND_INIT( Substr , "substr" );
M_SRDPP_COMMAND_DECL( ToSource ); M_SRDPP_COMMAND_INIT( ToSource , "to-source" );
M_SRDPP_COMMAND_DECL( Try ); M_SRDPP_COMMAND_INIT_N( Try , "try" , 0 );
M_SRDPP_COMMAND_DECL( TypeOf ); M_SRDPP_COMMAND_INIT( TypeOf , "type-of" );
M_SRDPP_COMMAND_DECL( Unset ); M_SRDPP_COMMAND_INIT( Unset , "unset" );
M_SRDPP_COMMAND_DECL( UnsetMacro ); M_SRDPP_COMMAND_INIT( UnsetMacro , "unset-macro" );
M_SRDPP_COMMAND_DECL( Unwrap ); M_SRDPP_COMMAND_INIT( Unwrap , "unwrap" );
M_SRDPP_COMMAND_DECL_OBJ( VFSList , T_VFS& , vfs_ );
M_SRDPP_COMMAND_INIT_OBJ( VFSList , "vfs-list" , T_VFS& , vfs_ );
M_SRDPP_COMMAND_DECL_OBJ( VFSLoad , T_VFS& , vfs_ );
M_SRDPP_COMMAND_INIT_OBJ( VFSLoad , "vfs-load" , T_VFS& , vfs_ );
M_SRDPP_COMMAND_DECL_OBJ( VFSType , T_VFS& , vfs_ );
M_SRDPP_COMMAND_INIT_OBJ( VFSType , "vfs-type" , T_VFS& , vfs_ );
M_SRDPP_COMMAND_DECL( Xor ); M_SRDPP_COMMAND_INIT( Xor , "xor" );
} // namespace lw
#endif // _H_LW_LIB_SRDPPCOMMANDS

90
include/ebcl/SRDParser.hh Normal file
View file

@ -0,0 +1,90 @@
/******************************************************************************/
/* SRD PARSER AND PREPROCESSOR ************************************************/
/******************************************************************************/
#pragma once
#include <lw/lib/SRDIO.hh>
#include <lw/lib/SRDParserConfig.hh>
namespace lw {
// T_SRDParserData - Run-time data passed to the handlers when parsing
struct T_SRDParserData
{
// Parser configuration
T_SRDParserConfig const& config;
// Error output
T_SRDErrors & errors;
// Input list (if any) for the current rule
RPC_SRDList input;
// Name of the current context
T_String currentContext;
// Current context's data
RP_Variant currentData;
// Target context when entering or exiting
T_String targetContext;
// Data for the target context; must be initialised at entrance
RP_Variant targetData;
explicit T_SRDParserData(
T_SRDParserConfig const& parser ,
T_SRDErrors & errors );
};
M_CLASS_POINTERS( SRDParserData );
/*----------------------------------------------------------------------------*/
// E_SRDFlushMode - How the parser flushes its command list
enum class E_SRDFlushMode {
MANUAL , // The parser never flushes the command list, it
// must be done manually by calling flush()
END , // Flush the command list after parsing has been
// completed. This is the default.
SENTENCE // Flush after each sentence (start() and end()
// will also cause flushes)
};
// T_SRDParser - The parser's main class
class T_SRDParser : public A_SRDReaderTarget , public A_PrivateImplementation
{
public:
T_SRDParser( ) = delete;
T_SRDParser( T_SRDParserConfig const& cfg );
void start( T_SRDErrors & errors ) override;
void push( T_SRDErrors & errors , T_SRDToken && token ) override;
void end( T_SRDErrors & errors ) override;
// Execute all currently queued commands
void flush( );
// Set/get the flush mode
void flushMode( E_SRDFlushMode mode ) noexcept;
E_SRDFlushMode flushMode( ) const noexcept;
// Set/get flush token handling
void handleFlushToken( bool handleIt ) noexcept;
bool handleFlushToken( ) const noexcept;
template< typename T >
T const& getData( ) const;
private:
T_Variant const& getExecStackTop( ) const;
};
M_CLASS_POINTERS( SRDParser );
template< typename T >
inline T const& T_SRDParser::getData( ) const
{
return getExecStackTop( ).value< T >( );
}
} // namespace

View file

@ -0,0 +1,99 @@
/******************************************************************************/
/* SRD - PARSER CONFIGURATION *************************************************/
/******************************************************************************/
#ifndef _H_LW_LIB_SRDPARSERCONFIG
#define _H_LW_LIB_SRDPARSERCONFIG
#include <lw/lib/SRDDefinitions.hh>
#include <lw/lib/Types.hh>
namespace lw {
/*= PROCESSED PARSER CONFIGURATION ===========================================*/
// E_SRDTransitionType - Type of a parser state transition
enum class E_SRDTransitionType {
WORD ,
ENUM ,
TOKEN
};
// T_SRDTransition - A parser transition (condition + next state)
struct T_SRDTransition
{
// Match type
E_SRDTransitionType type;
// Match value: word or enum index, or token type.
union {
uint32_t index;
E_SRDTokenType tokenType;
};
// Next state
uint32_t next;
T_SRDTransition( E_SRDTokenType tokenType , uint32_t next );
T_SRDTransition( E_SRDTransitionType type , uint32_t index , uint32_t next );
};
/*----------------------------------------------------------------------------*/
// T_SRDParserConfig - Parser configuration
struct T_SRDParserConfig
{
enum : uint32_t { INVALID_END = 0xffffffff };
F_SRDHandler onStart;
F_SRDHandler onFinish;
T_Array< T_SRDContext > contexts;
T_ObjectTable< T_String , T_SRDEnum > enums;
// Index of words used in the rules
T_HashIndex wordsIndex;
T_Array< T_String > words;
// Start indices for the contexts' automatons
T_Array< uint32_t > startStates;
// End states. Either 0xffffffff for states that are not end states,
// or the rule ID for valid end states.
T_Array< uint32_t > endStates;
// State transitions
T_MultiArray< T_SRDTransition > transitions;
// Rule contexts
T_MultiArray< uint32_t > ruleContexts;
T_SRDParserConfig( ) = delete;
T_SRDParserConfig( T_SRDParserDefs const& defs );
// Try to find a transition matching the token
bool transition( uint32_t& state , T_SRDToken const& token ) const;
// Find the value of an enumeration member
T_Optional< uint32_t > enumValue( char const* name , T_String const& member ) const noexcept;
T_Optional< uint32_t > enumValue( T_String const& name , T_String const& member ) const noexcept;
};
M_CLASS_POINTERS( SRDParserConfig );
/*----------------------------------------------------------------------------*/
// X_SRDParserConfig - Exception indicating that definitions were incorrect
class X_SRDParserConfig : public std::exception
{
private:
T_Buffer< char > errorString_;
public:
explicit X_SRDParserConfig( T_StringBuilder const& error );
explicit X_SRDParserConfig( T_String const& error );
char const * what( ) const noexcept override;
};
} // namespace
#include <lw/lib/inline/SRDParserConfig.hh>
#endif // _H_LW_LIB_SRDPARSERCONFIG

93
include/ebcl/SRDText.hh Normal file
View file

@ -0,0 +1,93 @@
/******************************************************************************/
/* SRD - TEXT STORAGE *********************************************************/
/******************************************************************************/
#ifndef _H_LW_LIB_SRDTEXT
#define _H_LW_LIB_SRDTEXT
#include <lw/lib/SRDIO.hh>
namespace lw {
/*= READER ===================================================================*/
// Streaming lexer for SRD text
class T_SRDLexer : public A_PrivateImplementation
{
public:
T_SRDLexer( ) = delete;
T_SRDLexer( T_SRDLexer const& ) = delete;
T_SRDLexer( T_SRDLexer&& ) = delete;
T_SRDLexer( T_String const& name , T_SRDErrors& errors , A_SRDReaderTarget& target );
void processCharacter( T_Character c );
void processEnd( );
};
M_CLASS_POINTERS( SRDLexer );
/*----------------------------------------------------------------------------*/
// Text reader - wraps the lexer inside a SRD reader
class T_SRDTextReader : public A_SRDReader
{
public:
T_SRDTextReader( ) = delete;
T_SRDTextReader( T_SRDTextReader const& ) = delete;
T_SRDTextReader( T_SRDTextReader&& ) = delete;
T_SRDTextReader( A_SRDReaderTarget& target );
void read( T_String const& name , A_InputStream& input ) override;
};
M_CLASS_POINTERS( SRDTextReader );
/*----------------------------------------------------------------------------*/
T_SRDList SRDFromText( T_String const& name , T_String const& string , bool structured = true );
T_SRDList SRDFromText( T_String const& name , char const* string , bool structured = true );
/*= WRITER ===================================================================*/
// T_SRDTextWriter - Writer for the text form of SRD
class T_SRDTextWriter : public A_SRDWriter , public A_PrivateImplementation
{
public:
T_SRDTextWriter( ) = delete;
T_SRDTextWriter( T_SRDTextWriter const& ) = delete;
T_SRDTextWriter( T_SRDTextWriter&& ) = delete;
explicit T_SRDTextWriter( A_OutputStream& output );
T_SRDTextWriter& start( ) override;
T_SRDTextWriter& startList( ) override;
T_SRDTextWriter& endList( ) override;
T_SRDTextWriter& putText( T_String const& text ) override;
T_SRDTextWriter& putWord( T_String const& word ) override;
T_SRDTextWriter& putString( T_String const& string ) override;
T_SRDTextWriter& putComment( T_String const& comment ) override;
T_SRDTextWriter& putVariable( T_String const& variable ) override;
T_SRDTextWriter& putBinary( T_Buffer< uint8_t > const& binary ) override;
T_SRDTextWriter& putInteger( int64_t value ) override;
T_SRDTextWriter& putInt32( int32_t value ) override;
T_SRDTextWriter& putInt64( int64_t value ) override;
T_SRDTextWriter& putFloat( double value ) override;
T_SRDTextWriter& end( ) override;
};
M_CLASS_POINTERS( SRDTextWriter );
/*----------------------------------------------------------------------------*/
void SRDWriteAsText( A_OutputStream& output , T_SRDList const& data );
} // namespace
#include <lw/lib/inline/SRDText.hh>
#endif // _H_LW_LIB_SRDTEXT

110
include/ebcl/Streams.hh Normal file
View file

@ -0,0 +1,110 @@
/******************************************************************************/
/* STREAMS ********************************************************************/
/******************************************************************************/
#pragma once
#include <lw/lib/Externals.hh>
#include <lw/lib/Utilities.hh>
#include <lw/lib/Pointers.hh>
#include <lw/lib/Buffers.hh>
namespace lw {
/*= STREAM ERRORS ============================================================*/
enum class E_StreamError {
NOT_SUPPORTED , // Operation not supported
INVALID_POSITION ,
END , // End of stream
BAD_DATA , // Invalid data read from the stream
SYSTEM_ERROR ,
UNAVAILABLE , // Stream is no longer available
};
class X_StreamError : public std::exception
{
private:
E_StreamError error_;
int sysError_;
public:
explicit X_StreamError( E_StreamError e );
explicit X_StreamError( int error );
X_StreamError( ) = delete;
X_StreamError( X_StreamError const& ) = default;
X_StreamError( X_StreamError&& ) noexcept = default;
virtual X_StreamError& operator= ( X_StreamError const& ) = default;
virtual X_StreamError& operator= ( X_StreamError&& ) = default;
E_StreamError code( ) const;
int systemError( ) const;
char const * what( ) const noexcept;
};
/*= BASE ABSTRACT CLASSES FOR STREAMS ========================================*/
class A_Stream
{
private:
const bool isInput_;
const bool knownSize_;
protected:
size_t size_;
size_t position_;
A_Stream( bool isInput , size_t position ) noexcept;
A_Stream( bool isInput , size_t position , size_t size ) noexcept;
public:
A_Stream( ) = delete;
A_Stream( A_Stream const& ) = delete;
A_Stream( A_Stream&& ) = delete;
virtual ~A_Stream( ) = 0;
bool isInput( ) const;
bool isSizeKnown( ) const;
size_t position( ) const;
size_t size( ) const;
};
M_ABSTRACT_POINTERS( Stream );
/*----------------------------------------------------------------------------*/
class A_InputStream : public A_Stream
{
protected:
explicit A_InputStream( size_t position ) noexcept;
A_InputStream( size_t position , size_t size ) noexcept;
public:
virtual size_t read( void* data , size_t size ) = 0;
};
M_ABSTRACT_POINTERS( InputStream );
/*----------------------------------------------------------------------------*/
class A_OutputStream : public A_Stream
{
protected:
A_OutputStream( size_t position ) noexcept;
A_OutputStream( size_t position , size_t size ) noexcept;
public:
virtual size_t write( void const* data , size_t size ) = 0;
virtual void flush( );
};
M_ABSTRACT_POINTERS( OutputStream );
} // namespace
#include <lw/lib/inline/Streams.hh>

457
include/ebcl/Strings.hh Normal file
View file

@ -0,0 +1,457 @@
/******************************************************************************/
/* STRINGS AND RELATED UTILITIES **********************************************/
/******************************************************************************/
#ifndef _H_LW_LIB_STRINGS
#define _H_LW_LIB_STRINGS
#include <lw/lib/Externals.hh>
#include <lw/lib/Pointers.hh>
#include <lw/lib/Arrays.hh>
#include <lw/lib/BinaryStreams.hh>
namespace lw {
/*= UTF-8 UTILITY FUNCTIONS ==================================================*/
// Is the specified C string valid UTF-8 ?
bool UTF8IsValid( char const* string );
// Get the length (in characters) of the specified UTF-8 0-terminated string
uint32_t UTF8Length( char const* string );
// Get the size (in bytes) of the specified UTF-8 0-terminated string
uint32_t UTF8Size( char const* string );
// Combined function that does all the above
bool UTF8Info( char const* string , uint32_t& size , uint32_t& length );
// Check if the specified data is a valid UTF-8 string, and compute its length
// (in characters).
bool UTF8BufferInfo( char const* data , uint32_t size , uint32_t& length );
// Get the codepoint from a sequence of UTF-8 bytes. Sets "bytes" to the amount
// of bytes read from the input.
uint32_t UTF8GetCodepoint( char const* data , uint32_t& bytes );
// Similar to the above, without the amount of bytes output.
uint32_t UTF8GetCodepoint( char const* data );
// Write an UTF-8 encoded codepoint to a string, returns the amount of bytes
// that were written, or 0 if there wasn't enough space.
uint32_t UTF8PutCodepoint( char* output , uint32_t available , uint32_t codepoint );
// Get the memory offset of a codepoint in an UTF-8 sequence based on its index.
uint32_t UTF8GetMemoryOffset( char const* input , uint32_t index );
// Convert an UTF-8 sequence into an unsigned integer.
uint64_t UTF8ToUnsignedInteger( char const* input , uint32_t size ,
bool * ok = nullptr , int base = 10 , bool useSep = false ,
uint32_t separator = ' ' );
// Convert an UTF-8 sequence into a signed integer.
int64_t UTF8ToInteger( char const* input , uint32_t size ,
bool * ok = nullptr , int base = 10 , bool useSep = false ,
uint32_t separator = ' ' );
// Convert an UTF-8 sequence into a double precision floating point number. The
// sequence will be checked, converted into a C string and passed to strtod()
// for actual conversion.
double UTF8ToDouble( char const* input , uint32_t size ,
bool * ok = nullptr , uint32_t decimalPoint = '.' ,
bool useSep = false , uint32_t separator = ' ' );
/*= UNICODE CHARACTERS =======================================================*/
struct T_Character
{
const uint32_t codepoint;
T_Character( ) noexcept;
T_Character( T_Character const& other ) noexcept;
M_WITH_INT( T ) T_Character( T codepoint ) noexcept;
// ---------------------------------------------------------------------
bool isValid( ) const;
bool isAscii( ) const;
bool isControl( ) const;
bool isUppercase( ) const;
bool isLowercase( ) const;
bool isAlpha( ) const;
bool isNumeric( ) const;
bool isAlphanumeric( ) const;
bool isWhitespace( ) const;
// ---------------------------------------------------------------------
bool operator== ( T_Character const& other ) const;
bool operator!= ( T_Character const& other ) const;
bool operator< ( T_Character const& other ) const;
bool operator> ( T_Character const& other ) const;
bool operator<= ( T_Character const& other ) const;
bool operator>= ( T_Character const& other ) const;
M_WITH_INT( T ) bool operator== ( T other ) const;
M_WITH_INT( T ) bool operator!= ( T other ) const;
M_WITH_INT( T ) bool operator< ( T other ) const;
M_WITH_INT( T ) bool operator<= ( T other ) const;
M_WITH_INT( T ) bool operator> ( T other ) const;
M_WITH_INT( T ) bool operator>= ( T other ) const;
operator uint32_t ( ) const;
// ---------------------------------------------------------------------
uint32_t writeTo( char* output , uint32_t avail ) const;
// ---------------------------------------------------------------------
T_Character toUpper( ) const;
T_Character toLower( ) const;
};
M_CLASS_POINTERS( Character );
M_DECLARE_OBJECT_READER( T_Character );
M_DECLARE_OBJECT_WRITER( T_Character );
/*= IMMUTABLE UTF8 STRINGS ===================================================*/
/*
* NOTE: the *objects* are NOT immutable. The strings they contain, however,
* are.
*/
class T_StringBuilder;
class T_StringIterator;
// T_StringData - Abstract base for the various types of string storage.
class A_StringData
{
protected:
char* data_;
uint32_t size_;
bool valid_;
uint32_t length_;
A_StringData( ) = default;
A_StringData( A_StringData const& ) = delete;
A_StringData( A_StringData&& ) = delete;
public:
virtual ~A_StringData( ) = 0;
// Is valid UTF-8?
bool valid( ) const;
// Get a pointer to the data
char const * data( ) const;
// Length in characters
uint32_t length( ) const;
// Size in bytes
uint32_t size( ) const;
};
M_ABSTRACT_POINTERS( StringData );
/*----------------------------------------------------------------------------*/
// T_String - Main UTF-8 string class
class T_String
{
private:
RP_StringData data_;
public:
// Construct an empty string. No overhead whatsoever, just an assignment
T_String( ) noexcept;
// This constructor will try to:
// - use the empty string if initial is null or ""
// - use a pooled string if one matches initial
// - create a dynamic string otherwise.
// Because of this, it is relatively slow and should be avoided in
// general.
explicit T_String( char const* initial );
T_String( T_StringBuilder&& sb );
T_String( T_StringBuilder const& sb );
// Construct a dynamic string, either using the provided memory
// or duplicating it. Doesn't use the pools at all.
T_String( char const* data , uint32_t size , bool nodup = false );
T_String( T_String const& source );
T_String( T_String&& source ) noexcept;
~T_String( );
// ---------------------------------------------------------------------
// Get a pooled string. Faster than constructing then calling
// addToPool( ) if the string is already pooled. If it isn't, it will
// be added as a dynamic string.
static T_String Pooled( char const* string );
static T_String Pooled( char const* data , uint32_t size );
// ---------------------------------------------------------------------
T_String& operator= ( T_String&& string ) noexcept;
T_String& operator= ( T_String const& string );
T_String& operator= ( T_StringBuilder&& sb );
T_String& operator= ( T_StringBuilder const& sb );
friend void swap( T_String& lhs , T_String& rhs ) noexcept;
// ---------------------------------------------------------------------
// Adds the string to the pool if it isn't pooled already. If the pool
// already contains a pooled version of this string, use it instead.
T_String& addToPool( );
// Attempts to use the pooled version of a string if it exists. If it
// doesn't, keep using the current version.
T_String& usePool( );
// ---------------------------------------------------------------------
bool valid( ) const;
uint32_t size( ) const;
uint32_t length( ) const;
char const * data( ) const;
operator bool ( ) const;
bool operator! ( ) const;
// ---------------------------------------------------------------------
// Return the character at the specified index
T_Character operator[] ( uint32_t index ) const;
// Return a substring from the left side of the string
T_String left( uint32_t count ) const;
// Return a substring from the right side of the string
T_String right( uint32_t count ) const;
// Return a substring from the specified offset
T_String substr( uint32_t offset , uint32_t count = UINT32_MAX ) const;
// Return the substring between the two specified offsets
T_String range( uint32_t start , uint32_t end ) const;
// Remove whitespace from the start and end of the string
T_String trim( ) const noexcept;
// ---------------------------------------------------------------------
bool equals( T_String const& other ) const;
bool equals( char const* string ) const;
int32_t compare( T_String const& other ) const;
int32_t compareIgnoreCase( T_String const& other ) const;
bool startsWith( T_String const& other ) const;
bool endsWith( T_String const& other ) const;
// Finds a sub-string. Returns -1 if it isn't found.
int32_t find( T_String const& other , uint32_t from = 0 ) const;
// Finds a character. Returns -1 if it isn't found.
int32_t find( T_Character character , uint32_t from = 0 ) const;
bool operator== ( T_String const& other ) const;
bool operator!= ( T_String const& other ) const;
bool operator< ( T_String const& other ) const;
bool operator> ( T_String const& other ) const;
bool operator>= ( T_String const& other ) const;
bool operator<= ( T_String const& other ) const;
bool operator== ( char const* string ) const;
bool operator!= ( char const* string ) const;
// ---------------------------------------------------------------------
T_String replace( T_Character initial , T_Character replacement ) const;
T_String replace( T_String const& initial , T_String const& replacement ) const;
// ---------------------------------------------------------------------
uint64_t toUnsignedInteger( bool * ok = nullptr , int base = 10 ,
bool useSep = false , T_Character separator = ' ' ) const;
int64_t toInteger( bool * ok = nullptr , int base = 10 , bool useSep = false ,
T_Character separator = ' ' ) const;
double toDouble( bool * ok = nullptr , T_Character decimalPoint = '.' ,
bool useSep = false , T_Character separator = ' ' ) const;
// ---------------------------------------------------------------------
T_StringIterator getIterator( uint32_t offset ) const;
operator T_StringIterator( ) const;
// Converts the string to an array of bytes suitable for use with the
// operating system's functions (e.g. UTF-8 C string on Linux, or
// UTF-16 strings on Windows)
T_Buffer< char > toOSString( ) const;
};
M_CLASS_POINTERS( String );
M_DECLARE_HASH( T_String );
M_DECLARE_COMPARATOR( T_String );
M_DECLARE_OBJECT_READER( T_String );
M_DECLARE_OBJECT_WRITER( T_String );
void swap( T_String& lhs , T_String& rhs ) noexcept;
extern template class T_Array< T_String >;
extern template class T_MultiArray< T_String >;
/*= STRING ITERATORS =========================================================*/
class T_StringIterator final
{
friend class T_String;
private:
RP_StringData data_;
uint32_t pos_;
uint32_t index_;
uint32_t codepoint_;
uint32_t bytes_;
T_StringIterator( RP_StringData data , uint32_t index );
public:
T_StringIterator( ) = delete;
T_StringIterator( T_StringIterator const& other );
T_StringIterator( T_StringIterator&& other ) noexcept;
~T_StringIterator( );
T_StringIterator& operator= ( T_StringIterator const& other );
T_StringIterator& operator= ( T_StringIterator&& other ) noexcept;
friend void swap( T_StringIterator& lhs , T_StringIterator& rhs ) noexcept;
// ---------------------------------------------------------------------
bool next( );
uint32_t index( ) const;
bool atEnd( ) const;
T_Character character( ) const;
operator T_Character ( ) const;
};
M_CLASS_POINTERS( StringIterator );
void swap( T_StringIterator& lhs , T_StringIterator& rhs ) noexcept;
/*= STRING BUILDERS ==========================================================*/
class T_StringBuilder
{
public:
enum : uint32_t { C_GROWTH = 32 };
private:
char* data_;
uint32_t capacity_;
uint32_t size_;
uint32_t length_;
friend class T_String;
public:
T_StringBuilder( ) noexcept;
T_StringBuilder( T_StringBuilder const& other );
T_StringBuilder( T_StringBuilder&& other ) noexcept;
T_StringBuilder( char const* data , uint32_t size );
explicit T_StringBuilder( T_String const& string );
explicit T_StringBuilder( char const* string );
~T_StringBuilder( );
T_StringBuilder& operator =( T_StringBuilder const& other );
T_StringBuilder& operator =( T_StringBuilder&& other ) noexcept;
friend void swap( T_StringBuilder& lhs , T_StringBuilder& rhs );
// ---------------------------------------------------------------------
char const * data( ) const;
uint32_t capacity( ) const;
uint32_t size( ) const;
uint32_t length( ) const;
operator bool ( ) const;
bool operator! ( ) const;
// ---------------------------------------------------------------------
T_StringBuilder& ensureCapacity( uint32_t minCap );
T_StringBuilder& clear( );
T_StringBuilder& free( );
// ---------------------------------------------------------------------
T_StringBuilder& append( T_StringBuilder const& other );
T_StringBuilder& append( T_StringBuilder&& other );
T_StringBuilder& append( T_String const& string );
T_StringBuilder& append( char const* string , uint32_t size );
T_StringBuilder& append( char character );
T_StringBuilder& append( T_Character character );
T_StringBuilder& appendNumeric( int64_t value , int base = 10 , bool useSep = false ,
T_Character sep = ' ' , int sepEvery = 3 );
T_StringBuilder& appendNumeric( uint64_t value , int base = 10 , bool useSep = false ,
T_Character sep = ' ' , int sepEvery = 3 );
T_StringBuilder& appendDouble( double value , uint32_t precision = 6 , bool trailingZeros = false );
// ---------------------------------------------------------------------
bool operator== ( T_StringBuilder const& other ) const;
bool operator!= ( T_StringBuilder const& other ) const;
bool operator== ( T_String const& string ) const;
bool operator!= ( T_String const& string ) const;
bool operator== ( char const* string ) const;
bool operator!= ( char const* string ) const;
// ---------------------------------------------------------------------
uint64_t toUnsignedInteger( bool * ok = nullptr , int base = 10 ,
bool useSep = false , T_Character separator = ' ' ) const;
int64_t toInteger( bool * ok = nullptr , int base = 10 , bool useSep = false ,
T_Character separator = ' ' ) const;
double toDouble( bool * ok = nullptr , T_Character decimalPoint = '.' ,
bool useSep = false , T_Character separator = ' ' ) const;
};
M_CLASS_POINTERS( StringBuilder );
M_DECLARE_OBJECT_WRITER( T_StringBuilder );
void swap( T_StringBuilder& lhs , T_StringBuilder& rhs );
// Operator <<
M_LSHIFT_OP( T_StringBuilder , T_StringBuilder const& );
M_LSHIFT_OP( T_StringBuilder , T_StringBuilder && );
M_LSHIFT_OP( T_StringBuilder , T_String const& );
M_LSHIFT_OP( T_StringBuilder , char const* );
M_LSHIFT_OP( T_StringBuilder , char );
M_LSHIFT_OP( T_StringBuilder , T_Character );
M_LSHIFT_OP( T_StringBuilder , int16_t );
M_LSHIFT_OP( T_StringBuilder , int32_t );
M_LSHIFT_OP( T_StringBuilder , int64_t );
M_LSHIFT_OP( T_StringBuilder , uint16_t );
M_LSHIFT_OP( T_StringBuilder , uint32_t );
M_LSHIFT_OP( T_StringBuilder , uint64_t );
M_LSHIFT_OP( T_StringBuilder , float );
M_LSHIFT_OP( T_StringBuilder , double );
} // namespace
#endif // _H_LW_LIB_STRINGS
#include <lw/lib/inline/Strings.hh>

150
include/ebcl/Threading.hh Normal file
View file

@ -0,0 +1,150 @@
/******************************************************************************/
/* THREADING ******************************************************************/
/******************************************************************************/
#ifndef _H_LW_LIB_THREADING
#define _H_LW_LIB_THREADING
#include <lw/lib/Pointers.hh>
#include <lw/lib/Arrays.hh>
namespace lw {
/*= ALIASES ==================================================================*/
using T_Mutex = std::mutex;
using T_ScopeLock = std::lock_guard< std::mutex >;
using T_ExclusiveLock = std::unique_lock< std::mutex >;
using T_Condition = std::condition_variable;
using T_Thread = std::thread;
M_CLASS_POINTERS( Mutex );
M_CLASS_POINTERS( ExclusiveLock );
M_CLASS_POINTERS( Condition );
M_CLASS_POINTERS( Thread );
/*= READ/WRITE LOCKING =======================================================*/
// A mutex that supports multiple readers and one writer. Based on the
// implementation from G++ 6's standard library.
class T_ReadWriteMutex
{
private:
static constexpr uint32_t C_WLOCKED_ = 1 << 31;
static constexpr uint32_t C_READERS_ = ~C_WLOCKED_;
T_Mutex mutex_;
T_Condition readerBlock_;
T_Condition writerBlock_;
uint32_t state_;
public:
T_ReadWriteMutex( );
T_ReadWriteMutex( T_ReadWriteMutex const& ) = delete;
T_ReadWriteMutex( T_ReadWriteMutex&& ) = default;
~T_ReadWriteMutex( );
T_ReadWriteMutex& operator=( T_ReadWriteMutex const& ) = delete;
T_ReadWriteMutex& operator=( T_ReadWriteMutex&& ) = default;
// ---------------------------------------------------------------------
// Write lock
void lock( );
bool try_lock( );
void unlock( );
// ---------------------------------------------------------------------
// Read lock
void lock_shared( );
bool try_lock_shared( );
void unlock_shared( );
// ---------------------------------------------------------------------
void upgradeLock( );
};
M_CLASS_POINTERS( ReadWriteMutex );
// Write lock / scoped write lock aliases
using T_WriteLock = std::unique_lock< T_ReadWriteMutex >;
using T_ScopeWriteLock = std::lock_guard< T_ReadWriteMutex >;
M_CLASS_POINTERS( WriteLock );
// Read lock based on std::shared_lock, but that can be
// upgraded to a write lock without releasing
class T_ReadLock : public std::shared_lock< T_ReadWriteMutex >
{
public:
T_ReadLock( ) noexcept;
T_ReadLock( T_ReadLock&& other );
explicit T_ReadLock( T_ReadWriteMutex& m );
T_ReadLock( T_ReadWriteMutex& m , std::defer_lock_t t );
T_ReadLock( T_ReadWriteMutex& m , std::try_to_lock_t t );
T_ReadLock( T_ReadWriteMutex& m , std::adopt_lock_t t );
T_WriteLock upgrade( );
};
M_CLASS_POINTERS( ReadLock );
/*= RING BUFFER ==============================================================*/
template< typename ElementType >
class T_RingBuffer
{
private:
typedef T_RingBuffer< ElementType > T_Self;
uint32_t expand_;
ElementType * data_;
uint32_t allocated_;
uint32_t used_;
uint32_t readPos_;
public:
M_TEMPLATE_POINTERS( T_Self );
explicit T_RingBuffer( uint32_t expand = 64 );
T_RingBuffer( T_Self const& other );
T_RingBuffer( T_Self&& other ) noexcept;
~T_RingBuffer( );
T_Self& operator=( T_Self const& other );
T_Self& operator=( T_Self&& other ) noexcept;
template< typename T >
friend void swap( T_RingBuffer< T >& lhs , T_RingBuffer< T >& rhs ) noexcept;
void free( );
uint32_t size( ) const;
uint32_t capacity( ) const;
uint32_t growth( ) const;
bool readNext( ElementType& output );
bool readAll( T_Array< ElementType >& output );
void put( ElementType const& input );
void put( ElementType&& input );
template< typename... ArgTypes >
void putNew( ArgTypes&&... arguments );
private:
void expand( );
};
template< typename T >
void swap( T_RingBuffer< T >& lhs , T_RingBuffer< T >& rhs ) noexcept;
}
#endif // _H_LW_LIB_THREADING
#include <lw/lib/inline/Threading.hh>

498
include/ebcl/Types.hh Normal file
View file

@ -0,0 +1,498 @@
/******************************************************************************/
/* CONTAINER TYPES ************************************************************/
/******************************************************************************/
#ifndef _H_LW_LIB_TYPES
#define _H_LW_LIB_TYPES
#include <lw/lib/Utilities.hh>
#include <lw/lib/Pointers.hh>
namespace lw {
/*= VARIANT TYPE =============================================================*/
// Forward declaration of the main variant type
template< size_t InPlaceSize = sizeof( void* ) >
class T_VariantExt;
/*----------------------------------------------------------------------------*/
/* Helper class for the variant type. Contains the handlers for both in-place
* and heap-allocated storage.
*/
struct T_VariantHelper
{
// Copy handler - Can be used to copy objects, will abort if the
// type doesn't support copy construction.
template<
typename Type ,
bool CanCopy = std::is_copy_constructible< Type >::value
> struct T_CopyHandler;
template< typename Type > struct T_CopyHandler< Type , true >
{ static void copy( void* , Type const& ); };
template< typename Type > struct T_CopyHandler< Type , false >
{ static void copy( void* , Type const& ); };
// Move handler - Can be used to move objects, will abort if the
// type doesn't support move construction.
template<
typename Type ,
bool CanMove = std::is_move_constructible< Type >::value
> struct T_MoveHandler;
template< typename Type > struct T_MoveHandler< Type , true >
{ static void move( void* , Type& ); };
template< typename Type > struct T_MoveHandler< Type , false >
{ static void move( void* , Type& ); };
// E_HandlerMode - Whether a handler uses in-place storage or
// heap allocation
enum class E_HandlerMode {
IN_PLACE ,
HEAP_ALLOC
};
// T_HandlerInfo - Information about the handler, used when assigning
// between variants with different in-place sizes.
struct T_HandlerInfo
{
size_t size , align;
E_HandlerMode mode;
};
// E_HandlerOp - An operation that can be executed by the data handler
enum class E_HandlerOp {
ALLOC , // Allocate item storage
// Arg0: N/A
// Arg1: data storage
ACCESS , // Access the item
// Arg0: data storage
// Arg1: pointer to the item
DESTRUCT , // Call the item's destructor
// Arg0: N/A
// Arg1: data storage
TYPEID , // Return type information
// Arg0: N/A
// Arg1: type info
COPY , // Create a copy of the item
// Arg0: source pointer
// Arg1: destination pointer
MOVE , // Move the item
// Arg0: source pointer
// Arg1: destination pointer
HINFO , // Return information about the handler
// Arg0: N/A
// Arg1: handler info
MKHDL , // Initialise another handler for the same type
// Input: E_HandlerMode
// Output: handler pointer
};
// F_Handler - Handler function pointer
typedef void (*F_Handler)(
E_HandlerOp op ,
void const* source ,
void* argument );
// T_InPlaceHandler - Handler for items that can be stored in-place
template< typename Type >
struct T_InPlaceHandler
{
template< typename Raw >
static void init( void* storage ,
F_Handler& handler ,
Raw const& value );
template< typename Raw >
static void init( void* storage ,
F_Handler& handler ,
Raw&& value );
template< typename... Arguments >
static void init( Construct< Type > ,
void* storage ,
F_Handler& handler ,
Arguments&&... arguments );
static void action( E_HandlerOp op ,
void const* source ,
void* target );
};
// T_HeapHandler - Handler for items that require memory allocation
template< typename Type >
struct T_HeapHandler
{
template< typename Raw >
static void init( void* storage ,
F_Handler& handler ,
Raw const& value );
template< typename Raw >
static void init( void* storage ,
F_Handler& handler ,
Raw&& value );
template< typename... Arguments >
static void init( Construct< Type > ,
void* storage ,
F_Handler& handler ,
Arguments&&... arguments );
static void action( E_HandlerOp op ,
void const* source ,
void* target );
};
// T_BestHandlerFor - Handler for some item type, based on whether it
// requires heap allocation or not.
template< typename Type , size_t Size >
using T_BestHandlerFor = std::conditional_t<
std::is_move_constructible< Type >::value
&& sizeof( Type ) <= Size
&& alignof( Type ) <= alignof( void* ) ,
T_InPlaceHandler< Type > ,
T_HeapHandler< Type > >;
// T_IsVariant - Templated horror to check whether something is a
// variant of arbitrary size.
template< typename T >
struct T_IsVariant
{
static constexpr bool value = false;
};
template< size_t S >
struct T_IsVariant< T_VariantExt< S > >
{
static constexpr bool value = true;
};
// T_CanFit - Templated horror that compares two variant's storage sizes.
template<
size_t A , size_t B
> struct T_CanFit
{
using T_A = T_VariantExt< A >;
using T_B = T_VariantExt< B >;
static constexpr bool value = T_A::StorageSize <= T_B::StorageSize;
};
};
/*----------------------------------------------------------------------------*/
template< size_t InPlaceSize >
class T_VariantExt
{
template< size_t >
friend class T_VariantExt;
public:
using T_Self = T_VariantExt< InPlaceSize >;
static constexpr size_t StorageSize
= std::max( sizeof( void* ) , InPlaceSize );
M_TEMPLATE_POINTERS( T_VariantExt );
private:
// T_RawOther_ - Raw type, provided it's not a T_VariantExt
template<
typename T ,
typename Raw = std::decay_t< T >
> using T_RawOther_ = std::enable_if_t<
!T_VariantHelper::T_IsVariant< Raw >::value , Raw
>;
// T_DataStorage_ - Contains the data or pointer to the data
union T_DataStorage_
{
void* pointer;
std::aligned_storage_t< StorageSize , alignof( void* ) > inPlace;
T_DataStorage_( ) = default;
T_DataStorage_( T_DataStorage_ const& ) = delete;
T_DataStorage_& operator =( T_DataStorage_ const& ) = delete;
};
// Handler function and storage area
T_VariantHelper::F_Handler handler_;
T_DataStorage_ storage_;
public:
T_VariantExt( ) noexcept;
~T_VariantExt( );
// ---------------------------------------------------------------------
// Constructors from other T_VariantExt instances
T_VariantExt( T_Self const& other );
T_VariantExt( T_Self&& other );
template< size_t S >
T_VariantExt( T_VariantExt< S > const& other );
template< size_t S >
T_VariantExt( T_VariantExt< S >&& other );
// Assignment from other T_VariantExt instances
T_Self& operator=( T_Self const& source );
T_Self& operator=( T_Self&& source );
template< size_t S >
T_Self& operator=( T_VariantExt< S > const& source );
template< size_t S >
T_Self& operator=( T_VariantExt< S >&& source );
// ---------------------------------------------------------------------
// Constructors from other types
template<
typename T ,
typename Raw = T_RawOther_< T > ,
typename std::enable_if_t< std::is_constructible< Raw , T&& >::value , bool > = true
> T_VariantExt( T&& value );
template<
typename T ,
typename Raw = T_RawOther_< T > ,
typename std::enable_if_t< !std::is_constructible< Raw , T&& >::value , bool > = false
> T_VariantExt( T&& value );
// Assignment from other types
template<
typename T ,
typename Raw = T_RawOther_< T > ,
typename std::enable_if_t< std::is_constructible< Raw , T&& >::value , bool > = true
> T_Self& operator= ( T&& value );
template<
typename T ,
typename Raw = T_RawOther_< T > ,
typename std::enable_if_t< !std::is_constructible< Raw , T&& >::value , bool > = false
> T_Self& operator= ( T&& value );
// In-place construction for another type
template< typename Type , typename... Arguments >
void setNew( Arguments&&... arguments );
// ---------------------------------------------------------------------
template< size_t A , size_t B >
friend void swap(
T_VariantExt< A >& lhs ,
T_VariantExt< B >& rhs ) noexcept;
void clear( ) noexcept;
// ---------------------------------------------------------------------
std::type_info const& typeInfo( ) const;
template< typename T >
T const& value( ) const;
template< typename T >
T& value( );
operator bool( ) const noexcept;
bool operator !( ) const noexcept;
// ---------------------------------------------------------------------
private:
// Copy implementation
template< size_t S >
void copyFrom_( T_VariantExt< S > const& other );
// Different move implementations based on source size
template<
size_t S ,
std::enable_if_t< T_VariantHelper::T_CanFit< S , InPlaceSize >::value , bool > = true
> void moveFrom_( T_VariantExt< S >&& source );
template<
size_t S ,
std::enable_if_t< !T_VariantHelper::T_CanFit< S , InPlaceSize >::value , bool > = false
> void moveFrom_( T_VariantExt< S >&& source );
};
using T_Variant = T_VariantExt< >;
M_CLASS_POINTERS( Variant );
/*= OPTIONAL TYPE ============================================================*/
template< typename Type >
class T_Optional
{
private:
using T_Self_ = T_Optional< Type >;
bool present_;
std::aligned_storage_t< sizeof( Type ) , alignof( Type ) > storage_;
public:
M_TEMPLATE_POINTERS( T_Optional );
// Construct as empty
constexpr T_Optional( ) noexcept;
// Copy/move constructors
T_Optional( T_Self_ const& other );
T_Optional( T_Self_&& other ) noexcept;
// Delete the value if necessary
~T_Optional( ) noexcept;
// Copy/move assignment
T_Self_& operator =( T_Self_ const& other );
T_Self_& operator =( T_Self_ && other ) noexcept;
template< typename T >
friend M_DECLARE_SWAP( T_Optional< T > );
// Initialise or assign from values
T_Optional( Type const& value );
T_Optional( Type&& value ) noexcept;
T_Self_& operator =( Type const& value );
T_Self_& operator =( Type&& value ) noexcept;
// Initialise or set to new value
template< typename... Arguments >
T_Optional( Construct< Type > , Arguments&&... arguments );
template< typename... Arguments >
void setNew( Arguments&&... arguments );
// Clear current value
void clear( ) noexcept;
// Is there a value?
constexpr bool present( ) const noexcept;
// Pointer to value or nullptr if no value
constexpr Type const* target( ) const noexcept;
constexpr Type* target( ) noexcept;
// Reference to value or std::bad_cast if no value
operator Type const&( ) const;
operator Type& ( );
};
template< typename Type >
M_DECLARE_SWAP( T_Optional< Type > );
/*= UNION TYPE ===============================================================*/
template< typename... Types >
class T_Union
{
private:
static_assert( MetaAnd< CanCopyOrMove< Types >... >::value ,
"types must be either copiable or movable" );
static_assert( MetaLength< Types... >::value > 0 ,
"empty unions are not allowed" );
using T_Self_ = T_Union< Types... >;
using T_Storage_ = std::aligned_union_t< 0 , Types... >;
// Supported_< T > - Checks whether the type is in the union's type list
template< typename T >
using Supported_ = MetaContains< T , std::decay_t< Types >... >;
// IndexOf_< T > - Finds the type's index in the union's list
template< typename T >
using IndexOf_ = MetaIndexOf< T , std::decay_t< Types >... >;
// GetType_< I > - Finds the type at the specified index in the union's list
template< unsigned I >
using GetType_ = T_MetaGet< I , std::decay_t< Types >... >;
// RawType_< T > - Raw type of one of the union's supported types
template< typename T , typename R = std::decay_t< T > >
using RawType_ = std::enable_if_t< Supported_< R >::value , R >;
uint32_t type_;
T_Storage_ storage_;
public:
M_TEMPLATE_POINTERS( T_Union );
// Default constructor - only available if the first type in the union's
// type list is default constructible.
template<
typename T0 = GetType_< 0 > ,
typename std::enable_if_t< std::is_default_constructible< T0 >::value , bool > = true
> T_Union( );
// Copy and move constructors - only available if all the types in the
// union are copy- or move-constructible, respectively.
T_Union( T_Self_ const& other );
T_Union( T_Self_&& other ) noexcept;
~T_Union( );
// Swap - only available if all the types in the union are
// move-constructible
template< typename... TL >
friend M_DECLARE_SWAP( T_Union< TL... > );
// Copy and move assignment - only available if all the types in the
// union are copy- or move-constructible, respectively.
T_Self_& operator =( T_Self_ const& );
T_Self_& operator =( T_Self_ && ) noexcept;
template< typename T , typename... ArgTypes >
T_Union( Construct< T > , ArgTypes&&... arguments );
// Construct from an instance of one of the union's types. Move and copy
// are both supported.
template<
typename T ,
typename Raw = RawType_< T > ,
typename std::enable_if_t< std::is_constructible< Raw , T&& >::value , bool > = true
> T_Union( T&& );
template<
typename T ,
typename Raw = RawType_< T > ,
typename std::enable_if_t< !std::is_constructible< Raw , T&& >::value , bool > = false
> T_Union( T&& );
// Assign from an instance of one of the union's types. Move and copy
// are both supported.
template<
typename T ,
typename Raw = RawType_< T > ,
typename std::enable_if_t< std::is_constructible< Raw , T&& >::value , bool > = true
> T_Self_& operator =( T&& );
template<
typename T ,
typename Raw = RawType_< T > ,
typename std::enable_if_t< !std::is_constructible< Raw , T&& >::value , bool > = false
> T_Self_& operator =( T&& );
// Checks whether the instance contains an instance of the specified
// type
template< typename T >
constexpr bool hasType( ) const noexcept;
// Returns the type information for the instance's current contents
std::type_info const& typeInfo( ) const noexcept;
// Obtains a pointer to the contents; may be nullptr if the union
// does not contain an instance of that type at the time
template< typename T >
constexpr T const* target( ) const noexcept;
template< typename T >
constexpr T* target( ) noexcept;
// Obtains a reference to the contents. Will throw std::bad_cast
// if the contents' type doesn't match.
template< typename T >
T const& value( ) const;
template< typename T >
T& value( );
private:
// Destroying contents
void destroy( );
template< typename T >
static void destroyImpl( T_Storage_* storage );
// Copying contents
void copy( T_Storage_* to ) const;
template< typename T >
static void copyImpl( T_Storage_ const* from , T_Storage_* to );
// Moving contents
void move( T_Storage_* to );
template< typename T >
static void moveImpl( T_Storage_* from , T_Storage_* to );
};
template< typename... Types >
M_DECLARE_SWAP( T_Union< Types... > );
} // namespace
#endif // _H_LW_LIB_TYPES
#include <lw/lib/inline/Types.hh>

393
include/ebcl/Utilities.hh Normal file
View file

@ -0,0 +1,393 @@
/******************************************************************************/
/* VARIOUS UTILITIES **********************************************************/
/******************************************************************************/
#ifndef _H_LW_LIB_UTILITIES
#define _H_LW_LIB_UTILITIES
#include <lw/lib/Externals.hh>
namespace lw {
// IsPowerOf2( v ) - Is some integer a power of 2 ?
template< typename T >
static constexpr bool IsPowerOf2( T value );
/*= TEMPLATED HORRORS ========================================================*/
// MetaOr< ... > - Logical OR for templates
template< typename... >
struct MetaOr : std::false_type
{ };
template< typename T >
struct MetaOr< T > : T
{ };
template< typename T , typename... Rest >
struct MetaOr< T , Rest... >
: std::conditional_t< bool( T::value ) , T , MetaOr< Rest... > >
{ };
/*----------------------------------------------------------------------------*/
// MetaAnd< ... > - Logical AND for templates
template< typename... >
struct MetaAnd : std::true_type
{ };
template< typename T >
struct MetaAnd< T > : T
{ };
template< typename T , typename... Rest >
struct MetaAnd< T , Rest... >
: std::conditional_t< bool( T::value ) , MetaAnd< Rest... > , T >
{ };
/*----------------------------------------------------------------------------*/
// MetaNot< ... > - Logical NOT
template< typename T >
struct MetaNot : std::integral_constant< bool , !bool( T::value ) >
{ };
/*----------------------------------------------------------------------------*/
// MetaGet< N , List... > - Get the Nth element in a list
template< unsigned , typename... >
struct MetaGet { };
template< typename T , typename... Rest >
struct MetaGet< 0 , T , Rest... >
{ using type = T; };
template< unsigned N , typename First , typename... Rest >
struct MetaGet< N , First , Rest... >
: MetaGet< N - 1 , Rest... >
{ };
template< unsigned N , typename... List >
using T_MetaGet = typename MetaGet< N , List... >::type;
/*----------------------------------------------------------------------------*/
// MetaLength< List... > - Get the length of a list
template< typename... >
struct MetaLength
: std::integral_constant< unsigned , 0 >
{ };
template< typename T >
struct MetaLength< T >
: std::integral_constant< unsigned , 1 >
{ };
template< typename First , typename... Rest >
struct MetaLength< First , Rest... >
: std::integral_constant< unsigned , MetaLength< Rest... >::value + 1 >
{ };
/*----------------------------------------------------------------------------*/
// MetaContains< Type , List... > - Checks whether Type is in List
template< typename Type , typename... List >
using MetaContains = MetaOr< std::is_same< Type , List >... >;
/*----------------------------------------------------------------------------*/
// MetaIndexOf< Type , List... > - Gets the index of Type in List. If Type is
// not in the list, the length of the list is returned.
template< typename Type , typename... List >
struct MetaIndexOf { };
template< typename Type >
struct MetaIndexOf< Type >
: std::integral_constant< unsigned , 0 >
{ };
template< typename Type , typename First , typename... Rest >
struct MetaIndexOf< Type , First , Rest... >
: std::conditional_t< std::is_same< Type , First >::value ,
std::integral_constant< unsigned , 0 > ,
std::integral_constant< unsigned ,
MetaIndexOf< Type , Rest... >::value + 1 > >
{ };
/*----------------------------------------------------------------------------*/
// CanCopyOrMove< Type > - Check whether a type can be copy- or move-constructed.
template< typename T >
using CanCopyOrMove = MetaOr<
std::is_copy_constructible< T > ,
std::is_move_constructible< T > >;
/*----------------------------------------------------------------------------*/
// CanCopyConsAll< List... > - Checks that all listed types are copy-constructible
template< typename... List >
using CanCopyConsAll = MetaOr< std::is_copy_constructible< List >... >;
// CanMoveConsAll< List... > - Checks that all listed types are move-constructible
template< typename... List >
using CanMoveConsAll = MetaOr< std::is_move_constructible< List >... >;
// CanCopyAssAll< List... > - Checks that all listed types are copy-constructible
template< typename... List >
using CanCopyAssAll = MetaOr< std::is_copy_assignable< List >... >;
// CanMoveAssAll< List... > - Checks that all listed types are move-constructible
template< typename... List >
using CanMoveAssAll = MetaOr< std::is_move_assignable< List >... >;
/*----------------------------------------------------------------------------*/
// EnableForChild< P , C > - Enable if P is a parent class of C, or if P and C
// are the same.
template<
typename Parent ,
typename Child
>
using EnableForChild =
std::enable_if<
std::is_base_of< Parent , Child >::value ,
bool
>;
template< typename C , typename P >
using T_EnableForChild = typename EnableForChild<C, P>::type;
// EnableForParent< C , P > - Enable if P is a parent class of C, and if P and
// C are distinct.
template<
typename Child ,
typename Parent
>
using EnableForParent =
std::enable_if<
std::is_base_of< Parent , Child >::value
&& !std::is_same< Parent , Child >::value ,
bool
>;
template< typename C , typename P >
using T_EnableForParent = typename EnableForParent<C, P>::type;
/*----------------------------------------------------------------------------*/
// Remove const and topmost reference
template< typename T >
using RemoveConstRef = std::remove_const< std::remove_reference_t< T > >;
template< typename T >
using T_RemoveConstRef = typename RemoveConstRef< T >::type;
/*----------------------------------------------------------------------------*/
// T_EnableIfTypesMatch - Make sure that the A type actually matches the V type.
template<
typename V , typename A ,
typename RA = T_RemoveConstRef< A >
> using EnableIfTypesMatch =
std::enable_if< std::is_same< RA , V >::value , bool >;
template<
typename V , typename A
> using T_EnableIfTypesMatch = typename EnableIfTypesMatch< V , A >::type;
/*----------------------------------------------------------------------------*/
/* In-place construction tag */
template< typename Type >
struct Construct
{
explicit constexpr Construct( ) = default;
static constexpr Construct< Type > v = Construct< Type >( );
};
using InPlace = Construct< void >;
/*----------------------------------------------------------------------------*/
template< typename T >
struct T_CFunc { };
template< typename RT , typename... AT >
struct T_CFunc< RT( AT... ) >
{
typedef RT (* type )( AT... );
};
template< typename T >
using F_CFunc = typename T_CFunc< T >::type;
/*= MACRO HORRORS ============================================================*/
// M_LSHIFT_OP( Type , Target ) - Declare a left-shift operator using the
// specified types
#define M_LSHIFT_OP( Type , Target ) \
Type & operator<< ( Type& obj , Target value )
// M_WITH_INT( Name ) - Declare a template with a type that needs to be some
// sort of integer.
#define M_WITH_INT( Name ) \
template< \
typename Name , \
typename = std::enable_if_t< std::is_integral< Name >::value > \
>
// M_DECLARE_SWAP( Type ) - Declare the swap function for a given type
#define M_DECLARE_SWAP( Type ) \
void swap( Type& lhs , Type& rhs ) noexcept
// M_DEFINE_SWAP( Type ) - Define the swap function for a given type
#define M_DEFINE_SWAP( Type ) \
void lw::swap( Type& lhs , Type& rhs ) noexcept
/*= ENDIAN DETECTION =========================================================*/
/*
* Unfortunately there's no standard way to do this so we depend on some
* GCC-specific stuff.
*/
#ifndef __BYTE_ORDER__
# error "We need the __BYTE_ORDER__ macro to exist :("
#endif
enum class E_Endian {
LITTLE = __ORDER_LITTLE_ENDIAN__ ,
BIG = __ORDER_BIG_ENDIAN__ ,
NATIVE = __BYTE_ORDER__
};
static constexpr bool IsBigEndian( );
static constexpr bool IsLittleEndian( );
/*= ENDIAN CONVERSION ========================================================*/
template<
typename T ,
E_Endian E = E_Endian::NATIVE ,
typename = std::enable_if_t<
std::is_integral< T >::value
|| std::is_floating_point< T >::value
>
>
struct T_LittleEndian
{
static T convert( T value );
};
template<
typename T ,
E_Endian E = E_Endian::NATIVE ,
typename = std::enable_if_t<
std::is_integral< T >::value
|| std::is_floating_point< T >::value
>
>
struct T_BigEndian
{
static T convert( T value );
};
/*= COMPARATORS AND SORTING ==================================================*/
// F_Comparator< T > - T_Comparator function type
template< typename T >
using F_Comparator = std::function< int( T const& a , T const& b ) >;
// T_Comparator< T > - Default comparison function implementation
template< typename T >
struct T_Comparator
{
static int compare( T const& a , T const& b );
};
// Helper macros to declare and define specialised hash functions.
#define M_DECLARE_COMPARATOR( Type ) \
template< > \
struct T_Comparator< Type > \
{ \
static int compare( Type const& , Type const& ); \
}
#define M_DEFINE_COMPARATOR( Type ) \
int T_Comparator< Type >::compare( Type const & a , Type const & b )
// Instantiate some commonly used comparators
extern template struct T_Comparator< uint32_t >;
// Sort - Sort an array
template< typename T >
void Sort( T* array , uint32_t items , F_Comparator< T > comparator = T_Comparator< T >::compare );
/*= HASHING ==================================================================*/
// HashData( data , size ) - General hash function (Jenkin's one-at-a-time)
uint32_t HashData( uint8_t const* data , uint32_t size );
// Hash function template struct. Meant to be specialized. By default it uses
// the function above.
template< typename T , int S = sizeof( T ) >
struct T_HashFunction
{
static uint32_t hash( T const& item );
};
// ComputeHash( T ) - The actual hash function.
template< typename T >
uint32_t ComputeHash( T const& item );
// Helper macros to declare and define specialised hash functions.
#define M_DECLARE_HASH( Type ) \
template< > \
struct T_HashFunction< Type > \
{ \
static uint32_t hash( Type const& ); \
}
#define M_DEFINE_HASH( Type ) \
uint32_t T_HashFunction< Type >::hash( Type const & item )
/*= PRIVATE IMPLEMENTATION BASE ==============================================*/
/* This class should be used as a base class for any non-performance-critical
* class that contains a lot of private stuff. The idea is to limit the amount
* of stuff exposed through the API, which in turns makes binary compatibility
* somewhat easier.
*/
class A_PrivateImplementation
{
private:
using T_Destructor_ = std::function< void( void* ) >;
void* p_;
T_Destructor_ piDestructor_;
protected:
A_PrivateImplementation( ) = delete;
A_PrivateImplementation( A_PrivateImplementation const& ) = delete;
A_PrivateImplementation& operator=( A_PrivateImplementation const& ) = delete;
A_PrivateImplementation( void* p , T_Destructor_ destructor );
template< typename T >
explicit A_PrivateImplementation( T* p );
A_PrivateImplementation( A_PrivateImplementation&& ) noexcept;
A_PrivateImplementation& operator=( A_PrivateImplementation&& ) noexcept;
public:
virtual ~A_PrivateImplementation( );
protected:
template< typename T >
T& p( ) const;
private:
void callPrivateDestructor( ) noexcept;
};
} // namespace
#endif // _H_LW_LIB_UTILITIES
#include <lw/lib/inline/Utilities.hh>

19
include/ebcl/Version.hh Normal file
View file

@ -0,0 +1,19 @@
/******************************************************************************/
/* VERSION NUMBERS ************************************************************/
/******************************************************************************/
#ifndef _H_LW_LIB_VERSION
#define _H_LW_LIB_VERSION
#include <lw/lib/Externals.hh>
namespace lw {
static constexpr inline uint32_t LibVersion( )
{ return 0; }
static constexpr inline uint32_t LibRevision( )
{ return 0; }
}
#endif // _H_LW_LIB_VERSION

View file

@ -0,0 +1,19 @@
/******************************************************************************/
/* VERSION NUMBERS ************************************************************/
/******************************************************************************/
#ifndef _H_LW_LIB_VERSION
#define _H_LW_LIB_VERSION
#include <lw/lib/Externals.hh>
namespace lw {
static constexpr inline uint32_t LibVersion( )
{ return __VERSION__; }
static constexpr inline uint32_t LibRevision( )
{ return __REVISION__; }
}
#endif // _H_LW_LIB_VERSION

View file

@ -0,0 +1,376 @@
/******************************************************************************/
/* ALLOCATORS - INLINE CODE ***************************************************/
/******************************************************************************/
#ifndef _H_LW_LIB_INLINE_ALLOC
#define _H_LW_LIB_INLINE_ALLOC
#include <lw/lib/Alloc.hh>
namespace lw {
/*= T_PoolHelper::T_List =====================================================*/
template< typename T , size_t P >
inline T_PoolHelper::T_List< T , P >::T_List(
T_List< T , P >*& n ) noexcept
: next( n ) , free( P )
{
for ( size_t i = 0 ; i < P ; i ++ ) {
storage[ i ].list = this;
}
for ( size_t i = 0 ; i < BitmapSize ; i ++ ) {
bitmap[ i ] = 0;
}
n = this;
}
template< typename T , size_t P >
inline T* T_PoolHelper::T_List< T , P >::findUnused( ) noexcept
{
size_t i = 0;
while ( bitmap[ i ] == 255 ) {
assert( i < BitmapSize );
i ++;
}
size_t j = 0;
while ( ( bitmap[ i ] & ( 1 << j ) ) != 0 ) {
j ++;
}
assert( i * 8 + j < P );
bitmap[ i ] = bitmap[ i ] | ( 1 << j );
free --;
return &storage[ i * 8 + j ];
}
template< typename T , size_t P >
inline size_t T_PoolHelper::T_List< T , P >::indexOf(
T const* const item ) noexcept
{
assert( item >= &storage[ 0 ] );
const size_t offset( ( (char*) item ) - ( (char*) &storage[ 0 ] ) );
assert( offset % sizeof( T ) == 0 );
const size_t index( offset / sizeof( T ) );
assert( index < P );
return index;
}
template< typename T , size_t P >
inline void T_PoolHelper::T_List< T , P >::destroy(
T_List< T , P >*& head ) noexcept
{
while ( head != nullptr ) {
T_Self* const n( head->next );
delete head;
head = n;
}
}
/*= T_PoolHelper::T_Allocator ================================================*/
template< typename T , size_t P , size_t M >
inline T_PoolHelper::T_Allocator< T , P , M >::T_Allocator( ) noexcept
: free_( nullptr ) , partial_( nullptr ) , full_( nullptr ) ,
nFree_( 1 )
{
new T_List_( free_ );
}
template< typename T , size_t P , size_t M >
inline T_PoolHelper::T_Allocator< T , P , M >::~T_Allocator( )
{
T_List_::destroy( free_ );
T_List_::destroy( partial_ );
T_List_::destroy( full_ );
}
/*----------------------------------------------------------------------------*/
template< typename T , size_t P , size_t M >
inline T* T_PoolHelper::T_Allocator< T , P , M >::allocate( ) noexcept
{
if ( partial_ == nullptr ) {
if ( free_ == nullptr ) {
new T_List_( partial_ );
} else {
assert( nFree_ > 0 );
partial_ = free_;
free_ = free_->next;
partial_->next = nullptr;
nFree_ --;
}
}
T* const data( partial_->findUnused( ) );
if ( partial_->free == 0 ) {
T_List_* const nf( partial_ );
partial_ = nf->next;
nf->next = full_;
full_ = nf;
}
return data;
}
template< typename T , size_t P , size_t M >
void T_PoolHelper::T_Allocator< T , P , M >::free(
T* const item ) noexcept
{
T_List_* const list( reinterpret_cast< T_List_* >( item->list ) );
const size_t index( list->indexOf( item ) );
list->bitmap[ index / 8 ] = list->bitmap[ index / 8 ] & ~( 1 << ( index & 7 ) );
list->free ++;
if ( list->free == 1 ) {
// Full list is now partial
moveList( list , full_ , partial_ );
} else if ( list->free == P ) {
// Partial list is now free
if ( nFree_ == M ) {
T_List_* p( nullptr );
moveList( list , partial_ , p );
delete list;
} else {
moveList( list , partial_ , free_ );
nFree_ ++;
}
}
}
/*----------------------------------------------------------------------------*/
template< typename T , size_t P , size_t M >
size_t T_PoolHelper::T_Allocator< T , P , M >::countFreeLists( ) const noexcept
{
return nFree_;
}
template< typename T , size_t P , size_t M >
size_t T_PoolHelper::T_Allocator< T , P , M >::countPartialLists( ) const noexcept
{
return countLists( partial_ );
}
template< typename T , size_t P , size_t M >
size_t T_PoolHelper::T_Allocator< T , P , M >::countFullLists( ) const noexcept
{
return countLists( full_ );
}
template< typename T , size_t P , size_t M >
void T_PoolHelper::T_Allocator< T , P , M >::getUsage(
size_t& total ,
size_t& free ,
size_t& used ) const noexcept
{
free = countFreeLists( ) * P;
used = countFullLists( ) * P;
total = free + used;
T_List_ const* p( partial_ );
while ( p != nullptr ) {
free += p->free;
used += P - p->free;
total += P;
p = p->next;
}
}
/*----------------------------------------------------------------------------*/
template< typename T , size_t P , size_t M >
void T_PoolHelper::T_Allocator< T , P , M >::moveList(
T_List_* const list ,
T_List_*& from ,
T_List_*& to ) noexcept
{
T_List_** ptr( &from );
while ( *ptr != list ) {
ptr = &( (*ptr)->next );
assert( *ptr != nullptr );
}
*ptr = list->next;
list->next = to;
to = list;
}
template< typename T , size_t P , size_t M >
size_t T_PoolHelper::T_Allocator< T , P , M >::countLists(
T_List_ const* head ) noexcept
{
size_t nLists( 0 );
while ( head != nullptr ) {
nLists ++;
head = head->next;
}
return nLists;
}
/*= T_PoolAllocator ==========================================================*/
template< size_t OS , size_t OA , size_t P , size_t M >
inline void* T_PoolAllocator< OS , OA , P , M >::allocate(
const size_t requested ) noexcept
{
#ifdef LW_CFG_NO_ALLOCATORS
return ::operator new( requested );
#else
assert( requested <= OS );
return reinterpret_cast< char* >( alloc_.allocate( ) );
#endif
}
template< size_t OS , size_t OA , size_t P , size_t M >
void T_PoolAllocator< OS , OA , P , M >::free(
void* const item ) noexcept
{
#ifdef LW_CFG_NO_ALLOCATORS
::operator delete( item );
#else
alloc_.free( reinterpret_cast< T_Storage_* >( item ) );
#endif
}
/*----------------------------------------------------------------------------*/
template< size_t OS , size_t OA , size_t P , size_t M >
size_t T_PoolAllocator< OS , OA , P , M >::countFreeLists( ) const noexcept
{
return alloc_.countFreeLists( );
}
template< size_t OS , size_t OA , size_t P , size_t M >
size_t T_PoolAllocator< OS , OA , P , M >::countPartialLists( ) const noexcept
{
return alloc_.countPartialLists( );
}
template< size_t OS , size_t OA , size_t P , size_t M >
size_t T_PoolAllocator< OS , OA , P , M >::countFullLists( ) const noexcept
{
return alloc_.countFullLists( );
}
template< size_t OS , size_t OA , size_t P , size_t M >
void T_PoolAllocator< OS , OA , P , M >::getUsage(
size_t& total ,
size_t& free ,
size_t& used ) const noexcept
{
return alloc_.getUsage( total , free , used );
}
/*= T_ThreadedPoolAllocator ==================================================*/
template< size_t OS , size_t OA , size_t P , size_t M >
inline void* T_ThreadedPoolAllocator< OS , OA , P , M >::allocate(
const size_t requested ) noexcept
{
#ifdef LW_CFG_NO_ALLOCATORS
return ::operator new( requested );
#else
assert( requested <= OS );
T_Storage_* const alloc( ([this](){
T_Storage_* const fs( takeFromStack( ) );
return fs ? fs : alloc_.allocate( );
})() );
alloc->extra.pool = this;
return reinterpret_cast< char* >( alloc );
#endif
}
template< size_t OS , size_t OA , size_t P , size_t M >
void T_ThreadedPoolAllocator< OS , OA , P , M >::free(
void* const item ) noexcept
{
#ifdef LW_CFG_NO_ALLOCATORS
::operator delete( item );
#else
T_Storage_* const storage( reinterpret_cast< T_Storage_* >( item ) );
if ( storage->extra.pool == this ) {
alloc_.free( storage );
} else {
storage->extra.pool->addToStack( storage );
}
T_Storage_* const fs( takeFromStack( ) );
if ( fs ) {
alloc_.free( fs );
}
#endif
}
/*----------------------------------------------------------------------------*/
template< size_t OS , size_t OA , size_t P , size_t M >
size_t T_ThreadedPoolAllocator< OS , OA , P , M >::countFreeLists( ) const noexcept
{
return alloc_.countFreeLists( );
}
template< size_t OS , size_t OA , size_t P , size_t M >
size_t T_ThreadedPoolAllocator< OS , OA , P , M >::countPartialLists( ) const noexcept
{
return alloc_.countPartialLists( );
}
template< size_t OS , size_t OA , size_t P , size_t M >
size_t T_ThreadedPoolAllocator< OS , OA , P , M >::countFullLists( ) const noexcept
{
return alloc_.countFullLists( );
}
template< size_t OS , size_t OA , size_t P , size_t M >
void T_ThreadedPoolAllocator< OS , OA , P , M >::getUsage(
size_t& total ,
size_t& free ,
size_t& used ) const noexcept
{
return alloc_.getUsage( total , free , used );
}
/*----------------------------------------------------------------------------*/
template< size_t OS , size_t OA , size_t P , size_t M >
typename T_ThreadedPoolAllocator< OS , OA , P , M >::T_Storage_*
T_ThreadedPoolAllocator< OS , OA , P , M >::takeFromStack( ) noexcept
{
T_FreeHead_ o( freeHead_.load( std::memory_order_relaxed ) );
if ( o.head == nullptr ) {
return nullptr;
}
T_FreeHead_ next;
do {
next.aba = o.aba + 1;
next.head = o.head->extra.next;
} while ( !freeHead_.compare_exchange_weak( o , next ,
std::memory_order_acq_rel ,
std::memory_order_acquire ) );
return o.head;
}
template< size_t OS , size_t OA , size_t P , size_t M >
void T_ThreadedPoolAllocator< OS , OA , P , M >::addToStack(
T_Storage_* storage ) noexcept
{
assert( storage->extra.pool == this );
T_FreeHead_ o( freeHead_.load( std::memory_order_relaxed ) );
T_FreeHead_ r;
do {
storage->extra.next = o.head;
r.aba = o.aba + 1;
r.head = storage;
} while ( !freeHead_.compare_exchange_weak( o , r ,
std::memory_order_acq_rel ,
std::memory_order_acquire ) );
}
}
#endif //_H_LW_LIB_INLINE_ALLOC

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,145 @@
/******************************************************************************/
/* BINARY READER/WRITER FOR STREAMS - INLINE CODE *****************************/
/******************************************************************************/
#pragma once
#include <lw/lib/BinaryStreams.hh>
namespace lw {
/*= T_BinaryReader ===========================================================*/
inline T_BinaryReader::T_BinaryReader( A_InputStream& stream , E_Endian endian ) noexcept
: stream_( stream ) , endian_( endian )
{ }
inline A_InputStream& T_BinaryReader::stream( ) const
{
return stream_;
}
inline E_Endian T_BinaryReader::endian( ) const
{
return endian_;
}
/*----------------------------------------------------------------------------*/
template< typename T >
inline T T_BinaryReader::readNumericNative( ) const
{
static_assert( std::is_integral< T >( ) || std::is_floating_point< T >( ) ,
"numeric type expected" );
T value = 0;
auto r = stream_.read( &value , sizeof( T ) );
if ( r != sizeof( T ) ) {
throw X_StreamError( E_StreamError::BAD_DATA );
}
return value;
}
template< typename T >
inline T T_BinaryReader::readNumericLittleEndian( ) const
{
return T_LittleEndian< T >::convert( readNumericNative< T >( ) );
}
template< typename T >
inline T T_BinaryReader::readNumericBigEndian( ) const
{
return T_BigEndian< T >::convert( readNumericNative< T >( ) );
}
template< typename T >
inline T T_BinaryReader::read( ) const
{
return T_Reader_< T >::read( *this );
}
/*----------------------------------------------------------------------------*/
template< typename T >
inline T T_BinaryReader::T_Reader_< T , true >::read( T_BinaryReader const& reader )
{
if ( reader.endian_ == E_Endian::BIG ) {
return reader.readNumericBigEndian< T >( );
} else {
return reader.readNumericLittleEndian< T >( );
}
}
template< typename T >
inline T T_BinaryReader::T_Reader_< T , false >::read( T_BinaryReader const& reader )
{
typedef T_ObjectReader< T > Reader;
return Reader::read( reader );
}
/*= T_BinaryWriter ===========================================================*/
inline T_BinaryWriter::T_BinaryWriter( A_OutputStream& stream , E_Endian endian ) noexcept
: stream_( stream ) , endian_( endian )
{ }
/*----------------------------------------------------------------------------*/
inline A_OutputStream& T_BinaryWriter::stream( ) const
{
return stream_;
}
inline E_Endian T_BinaryWriter::endian( ) const
{
return endian_;
}
/*----------------------------------------------------------------------------*/
template< typename T >
inline void T_BinaryWriter::writeNumericNative( T value ) const
{
static_assert( std::is_integral< T >( ) || std::is_floating_point< T >( ) ,
"numeric type expected" );
stream_.write( &value , sizeof( T ) );
}
template< typename T >
inline void T_BinaryWriter::writeNumericLittleEndian( T const& value ) const
{
writeNumericNative( T_LittleEndian< T >::convert( value ) );
}
template< typename T >
inline void T_BinaryWriter::writeNumericBigEndian( T const& value ) const
{
writeNumericNative( T_BigEndian< T >::convert( value ) );
}
template< typename T >
inline void T_BinaryWriter::write( T const& value ) const
{
T_Writer_< T >::write( *this , value );
}
/*----------------------------------------------------------------------------*/
template< typename T >
inline void T_BinaryWriter::T_Writer_< T , true >::write( T_BinaryWriter const& writer , T value )
{
if ( writer.endian_ == E_Endian::BIG ) {
writer.writeNumericBigEndian( value );
} else {
writer.writeNumericLittleEndian( value );
}
}
template< typename T >
inline void T_BinaryWriter::T_Writer_< T , false >::write( T_BinaryWriter const& writer , T const& value )
{
typedef T_ObjectWriter< T > Writer;
Writer::write( writer , value );
}
} // namespace

View file

@ -0,0 +1,263 @@
/******************************************************************************/
/* BUFFERS - INLINE CODE ******************************************************/
/******************************************************************************/
#pragma once
#include <lw/lib/Buffers.hh>
namespace lw {
/*= T_BufferBase =============================================================*/
inline T_BufferBase::T_BufferBase( uint8_t* buffer ) noexcept
: data_( buffer )
{ }
inline T_BufferBase::T_BufferBase( size_t size )
: data_( ( uint8_t* ) malloc( size ) )
{
if ( size != 0 && data_ == nullptr ) {
throw std::bad_alloc( );
}
}
inline T_BufferBase::T_BufferBase( T_BufferBase&& source ) noexcept
: T_BufferBase( nullptr )
{
swap( *this , source );
}
inline T_BufferBase::~T_BufferBase( )
{
free( data_ );
}
/*----------------------------------------------------------------------------*/
inline void swap( T_BufferBase& lhs , T_BufferBase& rhs )
{
using std::swap;
swap( lhs.data_ , rhs.data_ );
}
/*----------------------------------------------------------------------------*/
inline uint8_t* T_BufferBase::data( ) const
{
return data_;
}
/*= T_FixedBuffer ============================================================*/
template< size_t S , typename T >
inline T_FixedBuffer< S , T >::T_FixedBuffer( )
: T_BufferBase( BYTES_ )
{ }
template< size_t S , typename T >
inline T_FixedBuffer< S , T >::T_FixedBuffer(
T_FixedBuffer< S , T >&& source ) noexcept
: T_BufferBase( std::move( source ) )
{ }
template< size_t S , typename T >
inline T_FixedBuffer< S , T >::T_FixedBuffer(
T_FixedBuffer< S , T > const& source )
: T_BufferBase( BYTES_ )
{
*this = source;
}
/*----------------------------------------------------------------------------*/
template< size_t S , typename T >
inline T_FixedBuffer< S , T >& T_FixedBuffer< S , T >::operator= ( T_FixedBuffer< S , T > const& other )
{
memcpy( data_ , other.data_ , BYTES_ );
return *this;
}
template< size_t S , typename T >
inline T_FixedBuffer< S , T >& T_FixedBuffer< S , T >::operator= ( T_FixedBuffer< S , T >&& other ) noexcept
{
swap( *this , other );
return *this;
}
/*----------------------------------------------------------------------------*/
template< size_t S , typename T >
inline void swap( T_FixedBuffer< S , T >& lhs , T_FixedBuffer< S , T >& rhs ) noexcept
{
swap( ( T_BufferBase& ) lhs , ( T_BufferBase& ) rhs );
}
/*----------------------------------------------------------------------------*/
template< size_t S , typename T >
inline size_t T_FixedBuffer< S , T >::bytes( ) const
{
return BYTES_;
}
template< size_t S , typename T >
inline T& T_FixedBuffer< S , T >::operator[] ( size_t index )
{
assert( index < S );
return *reinterpret_cast< T* >( data_ + index * sizeof( T ) );
}
template< size_t S , typename T >
inline T const& T_FixedBuffer< S , T >::operator[] ( size_t index ) const
{
assert( index < S );
return *reinterpret_cast< T* >( data_ + index * sizeof( T ) );
}
/*----------------------------------------------------------------------------*/
template< size_t S , typename T >
inline T_FixedBuffer< S , T >& T_FixedBuffer< S , T >::setAll( T const& value )
{
for ( size_t i = 0 ; i < S ; i ++ ) {
memcpy( &(*this)[ i ] , &value , sizeof( T ) );
}
return *this;
}
/*= T_Buffer =================================================================*/
template< typename T >
inline T_Buffer< T >::T_Buffer( ) noexcept
: T_BufferBase( nullptr ) , size_( 0 )
{ }
template< typename T >
inline T_Buffer< T >::T_Buffer( size_t size )
: T_BufferBase( size * sizeof( T ) ) , size_( size )
{ }
template< typename T >
inline T_Buffer< T >::T_Buffer( T const* data , size_t size )
: T_BufferBase( size * sizeof( T ) ) , size_( size )
{
memcpy( data_ , data , bytes( ) );
}
/*----------------------------------------------------------------------------*/
template< typename T >
inline T_Buffer< T >::T_Buffer( T_Buffer< T > const& other )
: T_Buffer( reinterpret_cast< T const* >( other.data_ ) , other.size( ) )
{ }
template< typename T >
inline T_Buffer< T >::T_Buffer( T_Buffer< T >&& other ) noexcept
: T_Buffer( )
{
swap( *this , other );
}
/*----------------------------------------------------------------------------*/
template< typename T >
inline T_Buffer< T >& T_Buffer< T >::operator= ( T_Buffer< T > const& other )
{
if ( size_ != other.size_ ) {
free( data_ );
size_ = other.size_;
if ( size_ == 0 ) {
data_ = nullptr;
} else {
data_ = ( uint8_t* ) malloc( bytes( ) );
if ( data_ == nullptr ) {
throw std::bad_alloc( );
}
}
}
memcpy( data_ , other.data_ , bytes( ) );
return *this;
}
template< typename T >
inline T_Buffer< T >& T_Buffer< T >::operator= ( T_Buffer< T >&& other )
{
swap( *this , other );
return *this;
}
/*----------------------------------------------------------------------------*/
template< typename T >
inline void swap( T_Buffer< T >& lhs , T_Buffer< T >& rhs ) noexcept
{
using std::swap;
swap( ( T_BufferBase& ) lhs , ( T_BufferBase& ) rhs );
swap( lhs.size_ , rhs.size_ );
}
/*----------------------------------------------------------------------------*/
template< typename T >
inline size_t T_Buffer< T >::size( ) const
{
return size_;
}
template< typename T >
inline size_t T_Buffer< T >::bytes( ) const
{
return size_ * sizeof( T );
}
/*----------------------------------------------------------------------------*/
template< typename T >
inline T& T_Buffer< T >::operator[] ( size_t index )
{
assert( index < size_ );
return *reinterpret_cast< T* >( data_ + index * sizeof( T ) );
}
template< typename T >
inline T const& T_Buffer< T >::operator[] ( size_t index ) const
{
assert( index < size_ );
return *reinterpret_cast< T* >( data_ + index * sizeof( T ) );
}
/*----------------------------------------------------------------------------*/
template< typename T >
inline T_Buffer< T >& T_Buffer< T >::resize( size_t newSize )
{
if ( newSize != size_ ) {
size_ = newSize;
data_ = ( uint8_t* ) realloc( data_ , bytes( ) );
if ( bytes( ) != 0 && data_ == nullptr ) {
throw std::bad_alloc( );
}
}
return *this;
}
template< typename T >
inline T_Buffer< T >& T_Buffer< T >::setAll( T const& value )
{
for ( size_t i = 0 ; i < size_ ; i ++ ) {
memcpy( &(*this)[ i ] , &value , sizeof( T ) );
}
return *this;
}
template< typename T >
inline T_Buffer< T >& T_Buffer< T >::copyAll( T const* data )
{
memcpy( data_ , data , bytes( ) );
return *this;
}
} // namespace

View file

@ -0,0 +1,30 @@
/******************************************************************************/
/* DYNAMIC LIBRARIES - INLINE CODE ********************************************/
/******************************************************************************/
#ifndef _H_LW_LIB_INLINE_DYNLIB
#define _H_LW_LIB_INLINE_DYNLIB
#include <lw/lib/DynLib.hh>
namespace lw {
/*= T_DynLib =================================================================*/
template< typename T >
inline T* T_DynLib::getPointer(
char const* const name ) const noexcept
{
return reinterpret_cast< T* >( getRawSymbol( name ) );
}
template< typename T >
inline std::function< T > T_DynLib::getFunction(
char const* const name ) const noexcept
{
return std::function< T >{ (F_CFunc< T >) getRawSymbol( name ) };
}
}
#endif // _H_LW_LIB_INLINE_DYNLIB

View file

@ -0,0 +1,99 @@
/******************************************************************************/
/* FILES - INLINE CODE ********************************************************/
/******************************************************************************/
#ifndef _H_LW_LIB_INLINE_FILES
#define _H_LW_LIB_INLINE_FILES
#include <lw/lib/Files.hh>
namespace lw {
/*= T_File ===================================================================*/
inline T_File::~T_File( )
{
close( );
}
/*---------------------------------------------------------------------------*/
inline void swap( T_File& lhs , T_File& rhs ) noexcept
{
using std::swap;
swap( lhs.path_ , rhs.path_ );
swap( lhs.mode_ , rhs.mode_ );
swap( lhs.file_ , rhs.file_ );
swap( lhs.size_ , rhs.size_ );
swap( lhs.pos_ , rhs.pos_ );
}
/*---------------------------------------------------------------------------*/
inline T_String const& T_File::path( ) const noexcept
{
return path_;
}
inline E_FileMode T_File::mode( ) const noexcept
{
return mode_;
}
inline bool T_File::isOpen( ) const noexcept
{
return file_ != nullptr;
}
inline size_t T_File::size( ) const noexcept
{
return isOpen( ) ? size_ : 0;
}
inline size_t T_File::position( ) const noexcept
{
return isOpen( ) ? pos_ : 0;
}
/*= T_FileInputStream ========================================================*/
inline void swap( T_FileInputStream& lhs , T_FileInputStream& rhs ) noexcept
{
lhs.swap( rhs );
}
/*---------------------------------------------------------------------------*/
inline T_File& T_FileInputStream::file( ) const noexcept
{
return fileRaw_ ? *fileRaw_ : *fileOwned_;
}
inline size_t T_FileInputStream::offset( ) const noexcept
{
return start_;
}
/*= T_FileOutputStream =======================================================*/
inline void swap( T_FileOutputStream& lhs , T_FileOutputStream& rhs ) noexcept
{
lhs.swap( rhs );
}
/*---------------------------------------------------------------------------*/
inline T_File& T_FileOutputStream::file( ) const noexcept
{
return fileRaw_ ? *fileRaw_ : *fileOwned_;
}
inline size_t T_FileOutputStream::offset( ) const noexcept
{
return start_;
}
} // namespace
#endif // _H_LW_LIB_INLINE_FILES

View file

@ -0,0 +1,29 @@
/******************************************************************************/
/* HASH INDEX - INLINE CODE ***************************************************/
/******************************************************************************/
#pragma once
#include <lw/lib/HashIndex.hh>
namespace lw {
/*= T_HashIndex ==============================================================*/
inline T_HashIndex::~T_HashIndex( )
{
free( );
}
inline uint32_t T_HashIndex::first( uint32_t key ) const
{
return hash_[ key & hashMask_ & lookupMask_ ];
}
inline uint32_t T_HashIndex::next( uint32_t index ) const
{
assert( index < indexSize_ );
return index_[ index & lookupMask_ ];
}
}

View file

@ -0,0 +1,421 @@
/******************************************************************************/
/* HASH TABLES - INLINE CODE **************************************************/
/******************************************************************************/
#ifndef _H_LW_LIB_INLINE_HASHTABLES
#define _H_LW_LIB_INLINE_HASHTABLES
#include <lw/lib/HashTables.hh>
namespace lw {
/*= T_DefaultKeyMatch ========================================================*/
template< typename K >
inline bool T_DefaultKeyMatch< K >::keysMatch( K const& a , K const& b )
{
return a == b;
}
/*= T_KeyValueTable ==========================================================*/
template< typename K , typename V >
inline T_KeyValueTable< K , V >::T_KeyValueTable(
uint32_t initialSize , uint32_t hashSize , uint32_t growth ,
F_KeyMatch< K > match )
: match_( match ) , index_( hashSize , initialSize , growth ) ,
keys_( growth ) , values_( growth )
{ }
/*----------------------------------------------------------------------------*/
template< typename K , typename T >
void swap( T_KeyValueTable< K , T >& lhs , T_KeyValueTable< K , T >& rhs )
{
using std::swap;
swap( lhs.match_ , rhs.match_ );
swap( lhs.index_ , rhs.index_ );
swap( lhs.keys_ , rhs.keys_ );
swap( lhs.values_ , rhs.values_ );
}
/*----------------------------------------------------------------------------*/
template< typename K , typename V >
template<
typename A , typename B ,
T_EnableIfTypesMatch< K , A > ,
T_EnableIfTypesMatch< V , B >
> inline bool T_KeyValueTable< K , V >::add(
A&& k ,
B&& v )
{
const uint32_t hash = ComputeHash( k );
uint32_t idx = find( k , hash );
if ( idx != T_HashIndex::INVALID_INDEX ) {
return false;
}
keys_.add( std::forward< A >( k ) );
values_.add( std::forward< B >( v ) );
index_.add( hash );
return true;
}
template< typename K , typename V >
template< typename B , T_EnableIfTypesMatch< V , B > >
inline bool T_KeyValueTable< K , V >::update(
K const& k ,
B&& v )
{
const uint32_t hash = ComputeHash( k );
uint32_t idx = find( k , hash );
if ( idx == T_HashIndex::INVALID_INDEX ) {
return false;
}
values_[ idx ] = std::forward< B >( v );
return true;
}
template< typename K , typename V >
template<
typename A , typename B ,
T_EnableIfTypesMatch< K , A > ,
T_EnableIfTypesMatch< V , B >
> inline void T_KeyValueTable< K , V >::set(
A&& k ,
B&& v )
{
const uint32_t hash = ComputeHash( k );
uint32_t idx = find( k , hash );
if ( idx == T_HashIndex::INVALID_INDEX ) {
keys_.add( std::forward< A >( k ) );
values_.add( std::forward< B >( v ) );
index_.add( hash );
} else {
values_[ idx ] = std::forward< B >( v );
}
}
template< typename K , typename V >
inline bool T_KeyValueTable< K , V >::remove( K const& k )
{
const uint32_t hash = ComputeHash( k );
uint32_t idx = find( k , hash );
if ( idx == T_HashIndex::INVALID_INDEX ) {
return false;
}
keys_.removeSwap( idx );
values_.removeSwap( idx );
index_.remove( idx );
return true;
}
/*----------------------------------------------------------------------------*/
template< typename K , typename V >
inline void T_KeyValueTable< K , V >::clear( )
{
values_.clear( );
keys_.clear( );
index_.clear( );
}
template< typename K , typename V >
inline void T_KeyValueTable< K , V >::free( )
{
values_.free( );
keys_.free( );
index_.free( );
}
/*----------------------------------------------------------------------------*/
template< typename K , typename V >
inline uint32_t T_KeyValueTable< K , V >::size( ) const
{
return keys_.size( );
}
template< typename K , typename V >
T_Array< K > const& T_KeyValueTable< K , V >::keys( ) const
{
return keys_;
}
template< typename K , typename V >
T_Array< V > const& T_KeyValueTable< K , V >::values( ) const
{
return values_;
}
template< typename K , typename V >
inline uint32_t T_KeyValueTable< K , V >::indexOf( K const& k ) const
{
return find( k , ComputeHash( k ) );
}
template< typename K , typename V >
inline bool T_KeyValueTable< K , V >::contains( K const& k ) const
{
const uint32_t hash = ComputeHash( k );
return find( k , hash ) != T_HashIndex::INVALID_INDEX;
}
/*----------------------------------------------------------------------------*/
template< typename K , typename V >
inline V const* T_KeyValueTable< K , V >::get( K const& k ) const
{
const uint32_t hash = ComputeHash( k );
uint32_t idx = find( k , hash );
if ( idx == T_HashIndex::INVALID_INDEX ) {
return nullptr;
}
return &values_[ idx ];
}
template< typename K , typename V >
inline V* T_KeyValueTable< K , V >::get( K const& k )
{
const uint32_t hash = ComputeHash( k );
uint32_t idx = find( k , hash );
if ( idx == T_HashIndex::INVALID_INDEX ) {
return nullptr;
}
return &values_[ idx ];
}
/*----------------------------------------------------------------------------*/
template< typename K , typename V >
inline V& T_KeyValueTable< K , V >::operator[] ( uint32_t index )
{
return values_[ index ];
}
template< typename K , typename V >
inline V const& T_KeyValueTable< K , V >::operator[] ( uint32_t index ) const
{
return values_[ index ];
}
/*----------------------------------------------------------------------------*/
template< typename K , typename V >
inline uint32_t T_KeyValueTable< K , V >::find( K const& k , uint32_t hash ) const
{
uint32_t idx = index_.first( hash );
while ( idx != T_HashIndex::INVALID_INDEX ) {
if ( match_( keys_[ idx ] , k ) ) {
break;
}
idx = index_.next( idx );
}
return idx;
}
/*= T_ObjectTable ============================================================*/
template< typename K , typename V >
inline T_ObjectTable< K , V >::T_ObjectTable(
T_ObjectTable< K , V >::F_GetKey keyGetter ,
uint32_t initialSize , uint32_t hashSize , uint32_t growth ,
T_ObjectTable< K , V >::F_Match match )
: match_( match ) , keyGetter_( keyGetter ) ,
index_( hashSize , initialSize , growth ) ,
values_( growth )
{ }
/*----------------------------------------------------------------------------*/
template< typename K , typename T >
void swap( T_ObjectTable< K , T >& lhs , T_ObjectTable< K , T >& rhs )
{
using std::swap;
swap( lhs.keyGetter_ , rhs.keyGetter_ );
swap( lhs.match_ , rhs.match_ );
swap( lhs.index_ , rhs.index_ );
swap( lhs.values_ , rhs.values_ );
}
/*----------------------------------------------------------------------------*/
template< typename K , typename V >
template< typename A , T_EnableIfTypesMatch< V , A > >
inline bool T_ObjectTable< K , V >::add(
A&& v )
{
K k = keyGetter_( v );
const uint32_t hash = ComputeHash( k );
uint32_t idx = find( k , hash );
if ( idx != T_HashIndex::INVALID_INDEX ) {
return false;
}
values_.add( std::forward< A >( v ) );
index_.add( hash );
return true;
}
/*----------------------------------------------------------------------------*/
template< typename K , typename V >
template< typename A , T_EnableIfTypesMatch< V , A > >
inline bool T_ObjectTable< K , V >::update(
A&& v )
{
K k = keyGetter_( v );
const uint32_t hash = ComputeHash( k );
uint32_t idx = find( k , hash );
if ( idx == T_HashIndex::INVALID_INDEX ) {
return false;
}
values_[ idx ] = std::forward< A >( v );
return true;
}
/*----------------------------------------------------------------------------*/
template< typename K , typename V >
template< typename A , T_EnableIfTypesMatch< V , A > >
inline void T_ObjectTable< K , V >::set(
A&& v )
{
K k = keyGetter_( v );
const uint32_t hash = ComputeHash( k );
uint32_t idx = find( k , hash );
if ( idx == T_HashIndex::INVALID_INDEX ) {
values_.add( std::forward< A >( v ) );
index_.add( hash );
} else {
values_[ idx ] = std::forward< A >( v );
}
}
/*----------------------------------------------------------------------------*/
template< typename K , typename V >
inline bool T_ObjectTable< K , V >::remove( K const& k )
{
const uint32_t hash = ComputeHash( k );
uint32_t idx = find( k , hash );
if ( idx == T_HashIndex::INVALID_INDEX ) {
return false;
}
values_.removeSwap( idx );
index_.remove( idx );
return true;
}
/*----------------------------------------------------------------------------*/
template< typename K , typename V >
inline void T_ObjectTable< K , V >::clear( )
{
values_.clear( );
index_.clear( );
}
template< typename K , typename V >
inline void T_ObjectTable< K , V >::free( )
{
values_.free( );
index_.free( );
}
/*----------------------------------------------------------------------------*/
template< typename K , typename V >
inline uint32_t T_ObjectTable< K , V >::size( ) const
{
return values_.size( );
}
template< typename K , typename V >
inline uint32_t T_ObjectTable< K , V >::indexOf( K const& k ) const
{
return find( k , ComputeHash( k ) );
}
template< typename K , typename V >
inline bool T_ObjectTable< K , V >::contains( K const& k ) const
{
const uint32_t hash = ComputeHash( k );
return find( k , hash ) != T_HashIndex::INVALID_INDEX;
}
/*----------------------------------------------------------------------------*/
template< typename K , typename V >
inline T_Array< K > T_ObjectTable< K , V >::keys( ) const
{
const auto sz( size( ) );
T_Array< K > k( sz ? sz : 1 );
for ( uint32_t i = 0 ; i < sz ; i ++ ) {
k.add( keyGetter_( values_[ i ] ) );
}
return k;
}
template< typename K , typename V >
inline T_Array< V > const& T_ObjectTable< K , V >::values( ) const
{
return values_;
}
/*----------------------------------------------------------------------------*/
template< typename K , typename V >
inline V const* T_ObjectTable< K , V >::get( K const& k ) const
{
const uint32_t hash = ComputeHash( k );
uint32_t idx = find( k , hash );
if ( idx == T_HashIndex::INVALID_INDEX ) {
return nullptr;
}
return &values_[ idx ];
}
template< typename K , typename V >
inline V* T_ObjectTable< K , V >::get( K const& k )
{
const uint32_t hash = ComputeHash( k );
uint32_t idx = find( k , hash );
if ( idx == T_HashIndex::INVALID_INDEX ) {
return nullptr;
}
return &values_[ idx ];
}
/*----------------------------------------------------------------------------*/
template< typename K , typename V >
inline V& T_ObjectTable< K , V >::operator[] ( uint32_t index )
{
return values_[ index ];
}
template< typename K , typename V >
inline V const& T_ObjectTable< K , V >::operator[] ( uint32_t index ) const
{
return values_[ index ];
}
/*----------------------------------------------------------------------------*/
template< typename K , typename V >
inline uint32_t T_ObjectTable< K , V >::find( K const& k , uint32_t hash ) const
{
uint32_t idx = index_.first( hash );
while ( idx != T_HashIndex::INVALID_INDEX ) {
if ( match_( keyGetter_( values_[ idx ] ) , k ) ) {
break;
}
idx = index_.next( idx );
}
return idx;
}
} // namespace
#endif // _H_LW_LIB_INLINE_HASHTABLES

View file

@ -0,0 +1,43 @@
/******************************************************************************/
/* MEMORY STREAMS - INLINE CODE ***********************************************/
/******************************************************************************/
#pragma once
#include <lw/lib/MemoryStreams.hh>
namespace lw {
/*= T_MemoryInputStream ======================================================*/
template< int S , typename T >
inline T_MemoryInputStream::T_MemoryInputStream( T_FixedBuffer< S , T > const& buffer )
: T_MemoryInputStream( buffer.data( ) , buffer.bytes( ) )
{ }
template< typename T >
inline T_MemoryInputStream::T_MemoryInputStream( T_Buffer< T > const& buffer )
: T_MemoryInputStream( buffer.data( ) , buffer.bytes( ) )
{ }
/*= T_MemoryOutputStream =====================================================*/
template< int S , typename T >
inline T_MemoryOutputStream::T_MemoryOutputStream( T_FixedBuffer< S , T >& buffer )
: T_MemoryOutputStream( buffer.data( ) , buffer.bytes( ) )
{ }
template< typename T >
inline T_MemoryOutputStream::T_MemoryOutputStream( T_Buffer< T >& buffer )
: T_MemoryOutputStream( buffer.data( ) , buffer.bytes( ) ,
[&buffer] ( uint8_t* , size_t reqSize ) -> uint8_t*
{
const size_t mod( reqSize % sizeof( T ) );
const size_t nItems( reqSize / sizeof( T ) + ( mod ? 1 : 0 ) );
buffer.resize( nItems );
return buffer.data( );
} )
{ }
} // namespace

View file

@ -0,0 +1,154 @@
/******************************************************************************/
/* UI<=>GAME MESSAGES - INLINE CODE *******************************************/
/******************************************************************************/
#ifndef _H_LW_LIB_INLINE_MESSAGES
#define _H_LW_LIB_INLINE_MESSAGES
#include <lw/lib/GameLoop.hh>
namespace lw {
/*= T_ProgressInfoPart =======================================================*/
inline T_ProgressInfoPart::T_ProgressInfoPart( T_String text ,
uint32_t progress , uint32_t total ) noexcept
: text_( std::move( text ) ) , progress_( progress ) , total_( total )
{ }
inline T_ProgressInfoPart::T_ProgressInfoPart( T_ProgressInfoPart&& other ) noexcept
: text_( std::move( other.text_ ) ) , progress_( other.progress_ ) ,
total_( other.total_ )
{ }
inline T_ProgressInfoPart::T_ProgressInfoPart( T_ProgressInfoPart const& other )
: text_( other.text_ ) , progress_( other.progress_ ) , total_( other.total_ )
{ }
/*----------------------------------------------------------------------------*/
inline T_String const& T_ProgressInfoPart::text( ) const noexcept
{
return text_;
}
inline uint32_t T_ProgressInfoPart::progress( ) const noexcept
{
return progress_;
}
inline uint32_t T_ProgressInfoPart::total( ) const noexcept
{
return total_;
}
/*= T_ProgressInfo ===========================================================*/
inline T_ProgressInfo::T_ProgressInfo( T_String text , uint32_t progress , uint32_t total ) noexcept
: main_( std::move( text ) , progress , total ) , sub_( )
{ }
inline T_ProgressInfo::T_ProgressInfo( T_ProgressInfoPart main ) noexcept
: main_( std::move( main ) )
{ }
inline T_ProgressInfo::T_ProgressInfo(
T_ProgressInfoPart main ,
T_ProgressInfoPart sub ) noexcept
: main_( std::move( main ) ) ,
sub_( std::move( sub ) )
{ }
inline T_ProgressInfo::T_ProgressInfo( T_ProgressInfoPart main ,
T_String sText , uint32_t sProgress , uint32_t sTotal ) noexcept
: main_( std::move( main ) ) ,
sub_( T_ProgressInfoPart{ std::move( sText ) , sProgress , sTotal } )
{ }
inline T_ProgressInfo::T_ProgressInfo( T_String text , uint32_t progress , uint32_t total ,
T_String sText , uint32_t sProgress , uint32_t sTotal ) noexcept
: main_( std::move( text ) , progress , total ) ,
sub_( T_ProgressInfoPart{ std::move( sText ) , sProgress , sTotal } )
{ }
inline T_ProgressInfo::T_ProgressInfo( T_ProgressInfo&& other ) noexcept
: main_( std::move( other.main_ ) ) , sub_( std::move( other.sub_ ) )
{ }
/*----------------------------------------------------------------------------*/
inline T_ProgressInfoPart const& T_ProgressInfo::main( ) const noexcept
{
return main_;
}
inline bool T_ProgressInfo::hasSub( ) const noexcept
{
return sub_.present( );
}
inline T_ProgressInfoPart const& T_ProgressInfo::sub( ) const
{
return (T_ProgressInfoPart const&) sub_;
}
/*= T_GameMessage ============================================================*/
template< E_MessageDirection D , typename MT , typename MD >
inline constexpr T_GameMessage< D , MT , MD >::T_GameMessage( ) noexcept
: type_( ) , data_( )
{ }
template< E_MessageDirection D , typename MT , typename MD >
inline constexpr T_GameMessage< D , MT , MD >::T_GameMessage(
T_Type type ) noexcept
: type_( type ) , data_( )
{ }
template< E_MessageDirection D , typename MT , typename MD >
inline T_GameMessage< D , MT , MD >::T_GameMessage(
T_Type type ,
T_Data data ) noexcept
: type_( type ) , data_( data )
{ }
template< E_MessageDirection D , typename MT , typename MD >
inline T_GameMessage< D , MT , MD >::T_GameMessage(
T_Self_&& other ) noexcept
: type_( other.type_ ) , data_( std::move( other.data_ ) )
{ }
template< E_MessageDirection D , typename MT , typename MD >
inline T_GameMessage< D >& T_GameMessage< D , MT , MD >::operator =(
T_Self_&& other ) noexcept
{
type_ = other.type_;
data_ = std::move( other.data_ );
return *this;
}
/*----------------------------------------------------------------------------*/
template< E_MessageDirection D , typename MT , typename MD >
inline constexpr bool T_GameMessage< D , MT , MD >::hasMessage( ) const noexcept
{
return type_.present( );
}
template< E_MessageDirection D , typename MT , typename MD >
inline constexpr MT T_GameMessage< D , MT , MD >::type( ) const noexcept
{
return type_;
}
template< E_MessageDirection D , typename MT , typename MD >
template< typename T >
constexpr T const& T_GameMessage< D , MT , MD >::data( ) const
{
return (T const&)( (MD const&) data_ );
}
} // namespace lw
#endif // _H_LW_LIB_INLINE_MESSAGES

View file

@ -0,0 +1,59 @@
/******************************************************************************/
/* MODDING SYSTEM - INLINE CODE ***********************************************/
/******************************************************************************/
#ifndef _H_LW_LIB_INLINE_MODS
#define _H_LW_LIB_INLINE_MODS
#include <lw/lib/Mods.hh>
namespace lw {
/*= T_ModIdentifier ==========================================================*/
inline bool T_ModIdentifier::operator ==(
T_ModIdentifier const& other ) const noexcept
{
return &other == this || ( name == other.name
&& version == other.version );
}
inline bool T_ModIdentifier::operator !=(
T_ModIdentifier const& other ) const noexcept
{
return &other != this && ( name != other.name
|| version != other.version );
}
inline M_DEFINE_HASH( T_ModIdentifier )
{
return ComputeHash( item.name ) * 47 + item.version;
}
inline M_DEFINE_COMPARATOR( T_ModIdentifier )
{
return a.compare( b );
}
inline M_LSHIFT_OP( T_StringBuilder , T_ModIdentifier const& )
{
obj << value.name << ':' << value.version;
return obj;
}
/*= T_ModInfo ================================================================*/
inline bool T_ModInfo::isUserInterface( ) const noexcept
{
return type == E_ModType::UI;
}
inline M_LSHIFT_OP( T_StringBuilder , T_ModInfo const& )
{
obj << value.identifier << '.' << value.revision;
return obj;
}
}
#endif // _H_LW_LIB_INLINE_MODS

View file

@ -0,0 +1,854 @@
/******************************************************************************/
/* POINTERS - INLINE CODE *****************************************************/
/******************************************************************************/
#ifndef _H_LW_LIB_INLINE_POINTERS
#define _H_LW_LIB_INLINE_POINTERS
#include <lw/lib/Pointers.hh>
namespace lw {
/*= T_OwnPtr =================================================================*/
template< typename T >
inline T_OwnPtr< T >::T_OwnPtr( T* p ) noexcept
: p_( p )
{ }
template< typename T >
inline T_OwnPtr< T >::T_OwnPtr( )
: T_OwnPtr( nullptr )
{ }
/*----------------------------------------------------------------------------*/
template< typename T >
template<
typename Q ,
T_EnableForChild< T , Q >
> inline T_OwnPtr< T >::T_OwnPtr( T_OwnPtr< Q >&& source ) noexcept
: p_( nullptr )
{
T* temp( source.p_ );
source.p_ = nullptr;
p_ = temp;
}
template< typename T >
template<
typename Q ,
T_EnableForParent< T , Q >
> inline T_OwnPtr< T >::T_OwnPtr( T_OwnPtr< Q >&& source )
: p_( nullptr )
{
T* temp( dynamic_cast< T* >( source.p_ ) );
if ( source.p_ && !temp ) {
throw std::bad_cast( );
}
source.p_ = nullptr;
p_ = temp;
}
template< typename T >
template<
typename Q ,
T_EnableForChild< T , Q >
> inline T_OwnPtr< T >& T_OwnPtr< T >::operator= ( T_OwnPtr< Q >&& source ) noexcept
{
T* temp( source.p_ );
clear( );
source.p_ = nullptr;
p_ = temp;
return *this;
}
template< typename T >
template<
typename Q ,
T_EnableForParent< T , Q >
> inline T_OwnPtr< T >& T_OwnPtr< T >::operator= (
T_OwnPtr< Q >&& source )
{
T* temp( dynamic_cast< T* >( source.p_ ) );
if ( source.p_ && !temp ) {
throw std::bad_cast( );
}
clear( );
source.p_ = nullptr;
p_ = temp;
return *this;
}
/*----------------------------------------------------------------------------*/
template< typename T >
inline T_OwnPtr< T >::~T_OwnPtr( )
{
clear( );
}
/*----------------------------------------------------------------------------*/
template< typename T >
inline void swap( T_OwnPtr< T >& lhs , T_OwnPtr< T >& rhs ) noexcept
{
std::swap( lhs.p_ , rhs.p_ );
}
/*----------------------------------------------------------------------------*/
template< typename T >
inline void T_OwnPtr< T >::clear( )
{
T* ptr( nullptr );
std::swap( p_ , ptr );
delete ptr;
}
/*----------------------------------------------------------------------------*/
template< typename T >
inline bool T_OwnPtr< T >::operator== ( const T* p ) const
{
return p == p_;
}
template< typename T >
inline bool T_OwnPtr< T >::operator!= ( const T* p ) const
{
return p != p_;
}
template< typename T >
inline T_OwnPtr< T >::operator bool ( ) const
{
return p_ != nullptr;
}
template< typename T >
inline bool T_OwnPtr< T >::operator! ( ) const
{
return p_ == nullptr;
}
/*----------------------------------------------------------------------------*/
template< typename T >
inline T* T_OwnPtr< T >::get( ) const
{
return p_;
}
template< typename T >
inline T* T_OwnPtr< T >::operator-> ( ) const
{
assert( p_ != nullptr );
return p_;
}
template< typename T >
inline T& T_OwnPtr< T >::operator* ( ) const
{
assert( p_ != nullptr );
return *p_;
}
/*----------------------------------------------------------------------------*/
template< typename T >
inline T_SharedPtr< T > T_OwnPtr< T >::makeShared( )
{
T* temp( nullptr );
std::swap( p_ , temp );
return T_SharedPtr< T >( temp );
}
/*= NewOwned / OwnRawPointer =================================================*/
template<
typename Type ,
typename... ArgTypes
>
inline T_OwnPtr< Type > NewOwned( ArgTypes&& ... arguments )
{
return T_OwnPtr< Type >( new Type( std::forward< ArgTypes >( arguments ) ... ) );
}
template< typename Type >
inline T_OwnPtr< Type > OwnRawPointer( Type*& pointer ) noexcept
{
assert( pointer != nullptr );
T_OwnPtr< Type > p( pointer );
pointer = nullptr;
return p;
}
template<
typename Type , typename Other ,
T_EnableForChild< Type , Other >
> inline T_OwnPtr< Type > OwnRawPointer( Other*& pointer ) noexcept
{
assert( pointer != nullptr );
T_OwnPtr< Type > p( pointer );
pointer = nullptr;
return p;
}
template<
typename Type , typename Other ,
T_EnableForParent< Type , Other >
> inline T_OwnPtr< Type > OwnRawPointer( Other*& pointer )
{
assert( pointer != nullptr );
Type* temp( dynamic_cast< Type* >( pointer ) );
if ( temp == nullptr ) {
throw std::bad_cast( );
}
T_OwnPtr< Type > p( temp );
pointer = nullptr;
return p;
}
/*= T_Reference_ =============================================================*/
// Reference counter for shared pointers
class T_Reference_
{
private:
typedef std::function< void ( void* ) > F_Destr_;
friend struct T_WeakChain_;
void* pointer_;
F_Destr_ destr_;
uint32_t count_;
T_WeakChain_* weaks_;
public:
/* References are pooled */
void* operator new( size_t count ) noexcept;
void operator delete( void* object ) noexcept;
T_Reference_( ) = delete;
T_Reference_( T_Reference_ const& ) = delete;
T_Reference_( T_Reference_&& ) = delete;
T_Reference_( void* ptr , F_Destr_ destructor );
~T_Reference_( );
void* pointer( ) const;
T_Reference_ * increase( );
void decrease( );
void* extract( );
};
/*----------------------------------------------------------------------------*/
inline void* T_Reference_::pointer( ) const
{
return pointer_;
}
inline T_Reference_* T_Reference_::increase( )
{
assert( count_ > 0 );
count_ ++;
return this;
}
inline void T_Reference_::decrease( )
{
assert( count_ > 0 );
count_ --;
if ( count_ == 0 ) {
delete this;
}
}
/*= T_BasePtr_ ===============================================================*/
template< typename T >
inline T_BasePtr_< T >::T_BasePtr_( T_Reference_* ref ) noexcept
: ref_( ref )
{ }
template< typename T >
inline T_BasePtr_< T >::operator bool ( ) const
{
return ref_ != nullptr;
}
template< typename T >
inline bool T_BasePtr_< T >::operator! ( ) const
{
return ref_ == nullptr;
}
template< typename T >
inline T* T_BasePtr_< T >::operator-> ( ) const
{
assert( ref_ != nullptr );