initial commit
current versions of all of my basic framework sources, build configurations/scripts, and supporting assets
This commit is contained in:
commit
c5cdddbeaa
19
.gitignore
vendored
Normal file
19
.gitignore
vendored
Normal file
|
@ -0,0 +1,19 @@
|
|||
.DS_Store
|
||||
*.sdf
|
||||
*.opensdf
|
||||
*.user
|
||||
*.suo
|
||||
*.vpwhistu
|
||||
*.vtg
|
||||
*.vpj
|
||||
*.vpw
|
||||
/*.exe
|
||||
/*.idb
|
||||
/*.ilk
|
||||
/*.pdb
|
||||
/*.dll
|
||||
/*.log
|
||||
/stdout.txt
|
||||
/stderr.txt
|
||||
/enginetest
|
||||
/build
|
BIN
assets/fonts/dlxfont.ttf
Normal file
BIN
assets/fonts/dlxfont.ttf
Normal file
Binary file not shown.
BIN
assets/ui_skin.png
Normal file
BIN
assets/ui_skin.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 24 KiB |
4
generate_makefile
Normal file
4
generate_makefile
Normal file
|
@ -0,0 +1,4 @@
|
|||
#!/bin/sh
|
||||
cd "$(dirname "$0")"
|
||||
type premake4 >/dev/null 2>&1 || { echo >&2 "'premake4' not found in your path."; exit 1; }
|
||||
premake4 --file=premake.lua gmake
|
8
generate_vs2010.bat
Normal file
8
generate_vs2010.bat
Normal file
|
@ -0,0 +1,8 @@
|
|||
@echo off
|
||||
for %%X in (premake4.exe) do (set FOUND=%%~$PATH:X)
|
||||
if not defined FOUND (
|
||||
echo 'premake4' not found in your path.
|
||||
exit /b
|
||||
)
|
||||
|
||||
premake4 --file=premake.lua vs2010
|
4
generate_xcode
Normal file
4
generate_xcode
Normal file
|
@ -0,0 +1,4 @@
|
|||
#!/bin/sh
|
||||
cd "$(dirname "$0")"
|
||||
type premake4 >/dev/null 2>&1 || { echo >&2 "'premake4' not found in your path."; exit 1; }
|
||||
premake4 --file=premake.lua xcode4
|
37
lib/eastl/eastl_basic_funcs.cpp
Normal file
37
lib/eastl/eastl_basic_funcs.cpp
Normal file
|
@ -0,0 +1,37 @@
|
|||
// These are very simple, basic, no-frills functions that
|
||||
// EASTL expects us to create for it to operate.
|
||||
|
||||
// ---- Allocator --------------------------------------------------------------
|
||||
|
||||
#include <EASTL/allocator.h>
|
||||
#include <stdlib.h> // malloc
|
||||
|
||||
void* operator new[](size_t size, const char* pName, int flags, unsigned debugFlags, const char* file, int line)
|
||||
{
|
||||
return malloc(size);
|
||||
}
|
||||
|
||||
void* operator new[](size_t size, size_t alignment, size_t alignmentOffset, const char* pName, int flags, unsigned debugFlags, const char* file, int line)
|
||||
{
|
||||
// this allocator doesn't support alignment
|
||||
EASTL_ASSERT(alignment <= 8);
|
||||
return malloc(size);
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
|
||||
// ---- For strings ------------------------------------------------------------
|
||||
|
||||
#include <EASTL/string.h>
|
||||
|
||||
int Vsnprintf8(char8_t* pDestination, size_t n, const char8_t* pFormat, va_list arguments)
|
||||
{
|
||||
#if defined(_MSC_VER) && !defined(__S3E__)
|
||||
return _vsnprintf(pDestination, n, pFormat, arguments);
|
||||
#else
|
||||
return vsnprintf(pDestination, n, pFormat, arguments);
|
||||
#endif
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
505
lib/eastl/include/EABase/config/eacompiler.h
Normal file
505
lib/eastl/include/EABase/config/eacompiler.h
Normal file
|
@ -0,0 +1,505 @@
|
|||
/*
|
||||
Copyright (C) 2009 Electronic Arts, Inc. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
3. Neither the name of Electronic Arts, Inc. ("EA") nor the names of
|
||||
its contributors may be used to endorse or promote products derived
|
||||
from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY ELECTRONIC ARTS AND ITS CONTRIBUTORS "AS IS" AND ANY
|
||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL ELECTRONIC ARTS OR ITS CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*-----------------------------------------------------------------------------
|
||||
* config/eacompiler.h
|
||||
*
|
||||
* Copyright (c) 2002 - 2005 Electronic Arts Inc. All rights reserved.
|
||||
* Maintained by Paul Pedriana, Maxis
|
||||
*
|
||||
* Modified to support Clang++ (v2.8) by Austin Seipp, 2010.
|
||||
*
|
||||
*-----------------------------------------------------------------------------
|
||||
* Currently supported defines include:
|
||||
* EA_COMPILER_GNUC
|
||||
* EA_COMPILER_CLANG
|
||||
* EA_COMPILER_ARM
|
||||
* EA_COMPILER_EDG
|
||||
* EA_COMPILER_SN
|
||||
* EA_COMPILER_MSVC
|
||||
* EA_COMPILER_METROWERKS
|
||||
* EA_COMPILER_INTEL
|
||||
* EA_COMPILER_BORLANDC
|
||||
* EA_COMPILER_IBM
|
||||
*
|
||||
* EA_COMPILER_VERSION = <integer>
|
||||
* EA_COMPILER_NAME = <string>
|
||||
* EA_COMPILER_STRING = <string>
|
||||
*
|
||||
* EA_COMPILER_NO_STATIC_CONSTANTS
|
||||
* EA_COMPILER_NO_TEMPLATE_SPECIALIZATION
|
||||
* EA_COMPILER_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
* EA_COMPILER_NO_MEMBER_TEMPLATES
|
||||
* EA_COMPILER_NO_MEMBER_TEMPLATE_SPECIALIZATION
|
||||
* EA_COMPILER_NO_TEMPLATE_TEMPLATES
|
||||
* EA_COMPILER_NO_MEMBER_TEMPLATE_FRIENDS
|
||||
* EA_COMPILER_NO_VOID_RETURNS
|
||||
* EA_COMPILER_NO_COVARIANT_RETURN_TYPE
|
||||
* EA_COMPILER_NO_DEDUCED_TYPENAME
|
||||
* EA_COMPILER_NO_ARGUMENT_DEPENDENT_LOOKUP
|
||||
* EA_COMPILER_NO_EXCEPTION_STD_NAMESPACE
|
||||
* EA_COMPILER_NO_EXPLICIT_FUNCTION_TEMPLATE_ARGUMENTS
|
||||
* EA_COMPILER_NO_RTTI
|
||||
* EA_COMPILER_NO_EXCEPTIONS
|
||||
* EA_COMPILER_NO_UNWIND
|
||||
* EA_COMPILER_NO_STANDARD_CPP_LIBRARY
|
||||
* EA_COMPILER_NO_STATIC_VARIABLE_INIT
|
||||
* EA_COMPILER_NO_STATIC_FUNCTION_INIT
|
||||
*
|
||||
*-----------------------------------------------------------------------------
|
||||
*
|
||||
* Documentation
|
||||
* EA_COMPILER_NO_STATIC_CONSTANTS
|
||||
* Code such as this is legal, but some compilers fail to compile it:
|
||||
* struct A{ static const a = 1; };
|
||||
*
|
||||
* EA_COMPILER_NO_TEMPLATE_SPECIALIZATION
|
||||
* Some compilers fail to allow template specialization, such as with this:
|
||||
* template<class U> void DoSomething(U u);
|
||||
* void DoSomething(int x);
|
||||
*
|
||||
* EA_COMPILER_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
* Some compilers fail to allow partial template specialization, such as with this:
|
||||
* template <class T, class Allocator> class vector{ }; // Primary templated class.
|
||||
* template <class Allocator> class vector<bool, Allocator>{ }; // Partially specialized version.
|
||||
*
|
||||
* EA_COMPILER_NO_MEMBER_TEMPLATES
|
||||
* Some compilers fail to allow member template functions such as this:
|
||||
* struct A{ template<class U> void DoSomething(U u); };
|
||||
*
|
||||
* EA_COMPILER_NO_MEMBER_TEMPLATE_SPECIALIZATION
|
||||
* Some compilers fail to allow member template specialization, such as with this:
|
||||
* struct A{
|
||||
* template<class U> void DoSomething(U u);
|
||||
* void DoSomething(int x);
|
||||
* };
|
||||
*
|
||||
* EA_COMPILER_NO_TEMPLATE_TEMPLATES
|
||||
* Code such as this is legal:
|
||||
* template<typename T, template<typename> class U>
|
||||
* U<T> SomeFunction(const U<T> x) { return x.DoSomething(); }
|
||||
*
|
||||
* EA_COMPILER_NO_MEMBER_TEMPLATE_FRIENDS
|
||||
* Some compilers fail to compile templated friends, as with this:
|
||||
* struct A{ template<class U> friend class SomeFriend; };
|
||||
* This is described in the C++ Standard at 14.5.3.
|
||||
*
|
||||
* EA_COMPILER_NO_VOID_RETURNS
|
||||
* This is legal C++:
|
||||
* void DoNothing1(){ };
|
||||
* void DoNothing2(){ return DoNothing1(); }
|
||||
*
|
||||
* EA_COMPILER_NO_COVARIANT_RETURN_TYPE
|
||||
* See the C++ standard sec 10.3,p5.
|
||||
*
|
||||
* EA_COMPILER_NO_DEDUCED_TYPENAME
|
||||
* Some compilers don't support the use of 'typename' for
|
||||
* dependent types in deduced contexts, as with this:
|
||||
* template <class T> void Function(T, typename T::type);
|
||||
*
|
||||
* EA_COMPILER_NO_ARGUMENT_DEPENDENT_LOOKUP
|
||||
* Also known as Koenig lookup. Basically, if you have a function
|
||||
* that is a namespace and you call that function without prefixing
|
||||
* it with the namespace the compiler should look at any arguments
|
||||
* you pass to that function call and search their namespace *first*
|
||||
* to see if the given function exists there.
|
||||
*
|
||||
* EA_COMPILER_NO_EXCEPTION_STD_NAMESPACE
|
||||
* <exception> is in namespace std. Some std libraries fail to
|
||||
* put the contents of <exception> in namespace std. The following
|
||||
* code should normally be legal:
|
||||
* void Function(){ std::terminate(); }
|
||||
*
|
||||
* EA_COMPILER_NO_EXPLICIT_FUNCTION_TEMPLATE_ARGUMENTS
|
||||
* Some compilers fail to execute DoSomething() properly, though they
|
||||
* succeed in compiling it, as with this:
|
||||
* template <int i>
|
||||
* bool DoSomething(int j){ return i == j; };
|
||||
* DoSomething<1>(2);
|
||||
*
|
||||
* EA_COMPILER_NO_EXCEPTIONS
|
||||
* The compiler is configured to disallow the use of try/throw/catch
|
||||
* syntax (often to improve performance). Use of such syntax in this
|
||||
* case will cause a compilation error.
|
||||
*
|
||||
* EA_COMPILER_NO_UNWIND
|
||||
* The compiler is configured to allow the use of try/throw/catch
|
||||
* syntax and behaviour but disables the generation of stack unwinding
|
||||
* code for responding to exceptions (often to improve performance).
|
||||
*
|
||||
*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef INCLUDED_eacompiler_H
|
||||
#define INCLUDED_eacompiler_H
|
||||
|
||||
#ifndef INCLUDED_eaplatform_H
|
||||
# include "EABase/config/eaplatform.h"
|
||||
#endif
|
||||
|
||||
// Note: This is used to generate the EA_COMPILER_STRING macros
|
||||
#ifndef INTERNAL_STRINGIZE
|
||||
# define INTERNAL_STRINGIZE(x) INTERNAL_PRIMITIVE_STRINGIZE(x)
|
||||
#endif
|
||||
#ifndef INTERNAL_PRIMITIVE_STRINGIZE
|
||||
# define INTERNAL_PRIMITIVE_STRINGIZE(x) #x
|
||||
#endif
|
||||
|
||||
// Note: this is for compatibility with non-clang compilers
|
||||
#ifndef __has_feature
|
||||
# define __has_feature(x) 0
|
||||
#endif
|
||||
|
||||
// Note: this is for compatibility with non-clang compilers
|
||||
#ifndef __has_attribute
|
||||
# define __has_attribute(x) 0
|
||||
#endif
|
||||
|
||||
// Note: this is for compatibility with non-clang compilers
|
||||
#ifndef __has_builtin
|
||||
# define __has_builtin(x) 0
|
||||
#endif
|
||||
|
||||
// EDG (EDG compiler front-end, used by other compilers such as SN)
|
||||
#if defined(__EDG_VERSION__)
|
||||
# define EA_COMPILER_EDG
|
||||
#endif
|
||||
|
||||
|
||||
// SN
|
||||
#if defined(__SNC__) // SN Systems compiler
|
||||
// Note that there are two versions of the SN compiler, one that is
|
||||
// GNUC-based and a newer one which is based on an EDG (Edison Design
|
||||
// Group) front-end with a back-end code generator made by SN.
|
||||
// The EDG-based SN compiler uses "GCC compatibility mode" and thus
|
||||
// defines __GNUC__ but isn't really GNUC. Also, as of this writing
|
||||
// it appears that the SN compiler may arrive with MSVC-compatibility
|
||||
// mode in addition as well. Thus, we define EA_COMPILER_SN
|
||||
// separately from other EA_COMPILER defines it is possible that both
|
||||
// may be defined at the same time. Note that while the newer EDG-based
|
||||
// SN compiler may emulate other compilers, it doesn't act exactly
|
||||
// the same.
|
||||
# define EA_COMPILER_SN
|
||||
#endif
|
||||
|
||||
|
||||
// Airplay SDK (third party mobile middleware compiler)
|
||||
#if defined(__S3E__)
|
||||
# define EA_COMPILER_NO_EXCEPTION_STD_NAMESPACE
|
||||
#endif
|
||||
|
||||
|
||||
// SNC (SN Systems)
|
||||
#if defined(__SNC__)
|
||||
# define EA_COMPILER_NAME "SNC"
|
||||
|
||||
# ifdef __GNUC__ // If SN is using GCC-compatibility mode (which it usually is)...
|
||||
# define EA_COMPILER_GNUC
|
||||
# define EA_COMPILER_VERSION (__GNUC__ * 1000 + __GNUC_MINOR__) // We intentionally report the GCC version here. SN
|
||||
# define EA_COMPILER_STRING EA_COMPILER_NAME " compiler, GCC version " INTERNAL_STRINGIZE( __GNUC__ ) "." INTERNAL_STRINGIZE( __GNUC_MINOR__ ) ", SNC version " INTERNAL_STRINGIZE( __SN_VER__ ) ", EDG version " INTERNAL_STRINGIZE( __EDG_VERSION__ )
|
||||
# else
|
||||
# define EA_COMPILER_VERSION __SN_VER__
|
||||
# define EA_COMPILER_STRING EA_COMPILER_NAME " compiler, version " INTERNAL_STRINGIZE( EA_COMPILER_VERSION ) ", EDG version " INTERNAL_STRINGIZE( __EDG_VERSION__ )
|
||||
# endif
|
||||
|
||||
// GCC (a.k.a. GNUC)
|
||||
#elif defined(__GNUC__) // GCC compilers exist for many platforms.
|
||||
# define EA_COMPILER_GNUC
|
||||
# define EA_COMPILER_VERSION (__GNUC__ * 1000 + __GNUC_MINOR__)
|
||||
# define EA_COMPILER_NAME "GCC"
|
||||
# define EA_COMPILER_STRING EA_COMPILER_NAME " compiler, version " INTERNAL_STRINGIZE( __GNUC__ ) "." INTERNAL_STRINGIZE( __GNUC_MINOR__ )
|
||||
|
||||
# if (__GNUC__ == 2) && (__GNUC_MINOR__ < 95) // If GCC < 2.95...
|
||||
# define EA_COMPILER_NO_MEMBER_TEMPLATES
|
||||
# endif
|
||||
# if (__GNUC__ == 2) && (__GNUC_MINOR__ <= 97) // If GCC <= 2.97...
|
||||
# define EA_COMPILER_NO_MEMBER_TEMPLATE_FRIENDS
|
||||
# endif
|
||||
# if (__GNUC__ == 3) && ((__GNUC_MINOR__ == 1) || (__GNUC_MINOR__ == 2)) // If GCC 3.1 or 3.2 (but not pre 3.1 or post 3.2)...
|
||||
# define EA_COMPILER_NO_EXPLICIT_FUNCTION_TEMPLATE_ARGUMENTS
|
||||
# endif
|
||||
|
||||
// Clang (quite compatible with GCC)
|
||||
#elif defined(__clang__)
|
||||
# define EA_COMPILER_CLANG
|
||||
# define EA_COMPILER_VERSION (__clang_major__ * 1000 + __clang_minor__)
|
||||
# define EA_COMPILER_NAME "Clang++"
|
||||
# define EA_COMPILER_STRING EA_COMPILER_NAME " compiler, version " INTERNAL_STRINGIZE( __clang_version__ )
|
||||
|
||||
// Borland C++
|
||||
#elif defined(__BORLANDC__)
|
||||
# define EA_COMPILER_BORLANDC
|
||||
# define EA_COMPILER_VERSION __BORLANDC__
|
||||
# define EA_COMPILER_NAME "Borland C"
|
||||
//#define EA_COMPILER_STRING (defined below)
|
||||
|
||||
# if (__BORLANDC__ <= 0x0550) // If Borland C++ Builder 4 and 5...
|
||||
# define EA_COMPILER_NO_MEMBER_TEMPLATE_FRIENDS
|
||||
# endif
|
||||
# if (__BORLANDC__ >= 0x561) && (__BORLANDC__ < 0x600)
|
||||
# define EA_COMPILER_NO_MEMBER_FUNCTION_SPECIALIZATION
|
||||
# endif
|
||||
|
||||
|
||||
// Intel C++ (via EDG front-end)
|
||||
#elif defined(__ICL) || defined(__ICC)
|
||||
# define EA_COMPILER_INTEL
|
||||
# if defined(__ICL)
|
||||
# define EA_COMPILER_VERSION __ICL
|
||||
# elif defined(__ICC)
|
||||
# define EA_COMPILER_VERSION __ICC
|
||||
# endif
|
||||
# define EA_COMPILER_NAME "Intel C++"
|
||||
//#define EA_COMPILER_STRING (defined below)
|
||||
|
||||
// Intel is based ont the EDG (Edison Design Group) front end and
|
||||
// all recent versions are very compliant to the C++ standard.
|
||||
|
||||
|
||||
// Metrowerks
|
||||
#elif defined(__MWERKS__) || defined(__CWCC__) // Metrowerks compilers exist for many platforms.
|
||||
# define EA_COMPILER_METROWERKS
|
||||
# ifdef __MWERKS__
|
||||
# define EA_COMPILER_VERSION __MWERKS__
|
||||
# else
|
||||
# define EA_COMPILER_VERSION __CWCC__
|
||||
# endif
|
||||
# define EA_COMPILER_NAME "Metrowerks"
|
||||
//#define EA_COMPILER_STRING (defined below)
|
||||
|
||||
# if (__MWERKS__ <= 0x2407) // If less than v7.x...
|
||||
# define EA_COMPILER_NO_MEMBER_FUNCTION_SPECIALIZATION
|
||||
# endif
|
||||
# if (__MWERKS__ <= 0x3003) // If less than v8.x...
|
||||
# define EA_COMPILER_NO_MEMBER_TEMPLATE_FRIENDS
|
||||
# endif
|
||||
|
||||
|
||||
// Microsoft VC++
|
||||
#elif defined(_MSC_VER) && !(defined(__S3E__) && defined(__arm__)) // S3E is a mobile SDK which mistakenly masquerades as VC++ on ARM.
|
||||
# define EA_COMPILER_MSVC
|
||||
# define EA_COMPILER_VERSION _MSC_VER
|
||||
# define EA_COMPILER_NAME "Microsoft Visual C++"
|
||||
//#define EA_COMPILER_STRING (defined below)
|
||||
|
||||
# if (_MSC_VER <= 1200) // If VC6.x and earlier...
|
||||
# if (_MSC_VER < 1200)
|
||||
# define EA_COMPILER_MSVCOLD
|
||||
# else
|
||||
# define EA_COMPILER_MSVC6
|
||||
# endif
|
||||
|
||||
# if (_MSC_VER < 1200) // If VC5.x or earlier...
|
||||
# define EA_COMPILER_NO_TEMPLATE_SPECIALIZATION
|
||||
# endif
|
||||
# define EA_COMPILER_NO_EXPLICIT_FUNCTION_TEMPLATE_ARGUMENTS // The compiler compiles this OK, but executes it wrong. Fixed in VC7.0
|
||||
# define EA_COMPILER_NO_VOID_RETURNS // The compiler fails to compile such cases. Fixed in VC7.0
|
||||
# define EA_COMPILER_NO_EXCEPTION_STD_NAMESPACE // The compiler fails to compile such cases. Fixed in VC7.0
|
||||
# define EA_COMPILER_NO_DEDUCED_TYPENAME // The compiler fails to compile such cases. Fixed in VC7.0
|
||||
# define EA_COMPILER_NO_STATIC_CONSTANTS // The compiler fails to compile such cases. Fixed in VC7.0
|
||||
# define EA_COMPILER_NO_COVARIANT_RETURN_TYPE // The compiler fails to compile such cases. Fixed in VC7.1
|
||||
# define EA_COMPILER_NO_ARGUMENT_DEPENDENT_LOOKUP // The compiler compiles this OK, but executes it wrong. Fixed in VC7.1
|
||||
# define EA_COMPILER_NO_TEMPLATE_TEMPLATES // The compiler fails to compile such cases. Fixed in VC7.1
|
||||
# define EA_COMPILER_NO_TEMPLATE_PARTIAL_SPECIALIZATION // The compiler fails to compile such cases. Fixed in VC7.1
|
||||
# define EA_COMPILER_NO_MEMBER_TEMPLATE_FRIENDS // The compiler fails to compile such cases. Fixed in VC7.1
|
||||
//#define EA_COMPILER_NO_MEMBER_TEMPLATES // VC6.x supports member templates properly 95% of the time. So do we flag the remaining 5%?
|
||||
//#define EA_COMPILER_NO_MEMBER_TEMPLATE_SPECIALIZATION // VC6.x supports member templates properly 95% of the time. So do we flag the remaining 5%?
|
||||
|
||||
# elif (_MSC_VER <= 1300) // If VC7.0 and earlier...
|
||||
# define EA_COMPILER_MSVC7
|
||||
|
||||
# define EA_COMPILER_NO_COVARIANT_RETURN_TYPE // The compiler fails to compile such cases. Fixed in VC7.1
|
||||
# define EA_COMPILER_NO_ARGUMENT_DEPENDENT_LOOKUP // The compiler compiles this OK, but executes it wrong. Fixed in VC7.1
|
||||
# define EA_COMPILER_NO_TEMPLATE_TEMPLATES // The compiler fails to compile such cases. Fixed in VC7.1
|
||||
# define EA_COMPILER_NO_TEMPLATE_PARTIAL_SPECIALIZATION // The compiler fails to compile such cases. Fixed in VC7.1
|
||||
# define EA_COMPILER_NO_MEMBER_TEMPLATE_FRIENDS // The compiler fails to compile such cases. Fixed in VC7.1
|
||||
# define EA_COMPILER_NO_MEMBER_FUNCTION_SPECIALIZATION // This is the case only for VC7.0 and not VC6 or VC7.1+. Fixed in VC7.1
|
||||
//#define EA_COMPILER_NO_MEMBER_TEMPLATES // VC7.0 supports member templates properly 95% of the time. So do we flag the remaining 5%?
|
||||
|
||||
# elif (_MSC_VER < 1400) // If VC7.1 ...
|
||||
// The VC7.1 and later compiler is fairly close to the C++ standard
|
||||
// and thus has no compiler limitations that we are concerned about.
|
||||
# define EA_COMPILER_MSVC7_2003
|
||||
# define EA_COMPILER_MSVC7_1
|
||||
|
||||
# else // _MSC_VER of 1400 means VC8 (VS2005), 1500 means VC9 (VS2008)
|
||||
# define EA_COMPILER_MSVC8_2005
|
||||
# define EA_COMPILER_MSVC8_0
|
||||
|
||||
# endif
|
||||
|
||||
|
||||
// IBM
|
||||
#elif defined(__xlC__)
|
||||
# define EA_COMPILER_IBM
|
||||
# define EA_COMPILER_NAME "IBM XL C"
|
||||
# define EA_COMPILER_VERSION __xlC__
|
||||
# define EA_COMPILER_STRING "IBM XL C compiler, version " INTERNAL_STRINGIZE( __xlC__ )
|
||||
|
||||
|
||||
// ARM compiler
|
||||
# if defined(__ARMCC_VERSION)
|
||||
// Note that this refers to the ARM compiler (armcc or armcpp), but there
|
||||
// are other compilers that target ARM processors, such as GCC and Microsoft VC++.
|
||||
// If you want to detect compiling for the ARM processor, check for EA_PROCESSOR_ARM
|
||||
// being defined.
|
||||
# define EA_COMPILER_ARM
|
||||
# define EA_COMPILER_VERSION __ARMCC_VERSION
|
||||
# define EA_COMPILER_NAME __CC_ARM
|
||||
//#define EA_COMPILER_STRING (defined below)
|
||||
|
||||
# endif
|
||||
|
||||
|
||||
// Unknown
|
||||
#else // Else the compiler is unknown
|
||||
|
||||
# define EA_COMPILER_VERSION 0
|
||||
# define EA_COMPILER_NAME "Unknown"
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef EA_COMPILER_STRING
|
||||
# define EA_COMPILER_STRING EA_COMPILER_NAME " compiler, version " INTERNAL_STRINGIZE(EA_COMPILER_VERSION)
|
||||
#endif
|
||||
|
||||
|
||||
// Deprecated definitions
|
||||
// For backwards compatibility, should be supported for at least the life of EABase v2.0.x.
|
||||
#ifndef EA_COMPILER_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
# define EA_COMPILER_PARTIAL_TEMPLATE_SPECIALIZATION
|
||||
#endif
|
||||
#ifndef EA_COMPILER_NO_TEMPLATE_SPECIALIZATION
|
||||
# define EA_COMPILER_TEMPLATE_SPECIALIZATION
|
||||
#endif
|
||||
#ifndef EA_COMPILER_NO_MEMBER_TEMPLATES
|
||||
# define EA_COMPILER_MEMBER_TEMPLATES
|
||||
#endif
|
||||
#ifndef EA_COMPILER_NO_MEMBER_TEMPLATE_SPECIALIZATION
|
||||
# define EA_COMPILER_MEMBER_TEMPLATE_SPECIALIZATION
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
// EA_COMPILER_NO_RTTI
|
||||
//
|
||||
// If EA_COMPILER_NO_RTTI is defined, then RTTI (run-time type information)
|
||||
// is not available (possibly due to being disabled by the user).
|
||||
//
|
||||
#if defined(__SNC__) && !defined(__RTTI)
|
||||
# define EA_COMPILER_NO_RTTI
|
||||
#elif defined(__GXX_ABI_VERSION) && !defined(__GXX_RTTI)
|
||||
# define EA_COMPILER_NO_RTTI
|
||||
#elif defined(__clang__) && !__has_feature(cxx_rtti)
|
||||
# define EA_COMPILER_NO_RTTI
|
||||
#elif defined(_MSC_VER) && !defined(_CPPRTTI)
|
||||
# define EA_COMPILER_NO_RTTI
|
||||
#elif defined(__MWERKS__)
|
||||
# if !__option(RTTI)
|
||||
# define EA_COMPILER_NO_RTTI
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
// EA_COMPILER_NO_EXCEPTIONS / EA_COMPILER_NO_UNWIND
|
||||
//
|
||||
// If EA_COMPILER_NO_EXCEPTIONS is defined, then the compiler is
|
||||
// configured to not recognize C++ exception-handling statements
|
||||
// such as try/catch/throw. Thus, when EA_COMPILER_NO_EXCEPTIONS is
|
||||
// defined, code that attempts to use exception handling statements
|
||||
// will usually cause a compilation error. If is often desirable
|
||||
// for projects to disable exception handling because exception
|
||||
// handling causes extra code and/or data generation which might
|
||||
// not be needed, especially if it is known that exceptions won't
|
||||
// be happening. When writing code that is to be portable between
|
||||
// systems of which some enable exception handling while others
|
||||
// don't, check for EA_COMPILER_NO_EXCEPTIONS being defined.
|
||||
//
|
||||
#if defined(EA_COMPILER_GNUC) && defined(_NO_EX) // GCC on some platforms (e.g. PS3) defines _NO_EX when exceptions are disabled.
|
||||
# define EA_COMPILER_NO_EXCEPTIONS
|
||||
|
||||
#elif (defined(EA_COMPILER_GNUC) || defined(EA_COMPILER_INTEL) || defined(EA_COMPILER_SN)) && !defined(__EXCEPTIONS) // GCC and most EDG-based compilers define __EXCEPTIONS when exception handling is enabled.
|
||||
# define EA_COMPILER_NO_EXCEPTIONS
|
||||
|
||||
#elif defined(EA_COMPILER_CLANG) && !__has_feature(cxx_exceptions)
|
||||
# define EA_COMPILER_NO_EXCEPTIONS
|
||||
|
||||
#elif defined(EA_COMPILER_METROWERKS)
|
||||
# if !__option(exceptions)
|
||||
# define EA_COMPILER_NO_EXCEPTIONS
|
||||
# endif
|
||||
|
||||
// Borland and Micrsoft use the _CPUUNWIND define to denote that
|
||||
// exception stack unwinding code generation is disabled. The result
|
||||
// is that you can call try/catch/throw and that exceptions will be
|
||||
// caught handled, but that no automatic object destruction will
|
||||
// happen between a throw and the resulting catch. We thus don't
|
||||
// want to define EA_COMPILER_NO_EXCEPTIONS, but perhaps users might
|
||||
// be interesting in knowing that unwinding is disabled.
|
||||
#elif (defined(EA_COMPILER_BORLAND) || defined(EA_COMPILER_MSVC)) && !defined(_CPPUNWIND)
|
||||
# define EA_COMPILER_NO_UNWIND
|
||||
|
||||
#endif // EA_COMPILER_NO_EXCEPTIONS / EA_COMPILER_NO_UNWIND
|
||||
|
||||
|
||||
|
||||
// EA_COMPILER_NO_STANDARD_CPP_LIBRARY
|
||||
//
|
||||
// If defined, then the compiler doesn't provide a Standard C++ library.
|
||||
//
|
||||
#if defined(EA_PLATFORM_ANDROID)
|
||||
# define EA_COMPILER_NO_STANDARD_CPP_LIBRARY
|
||||
#endif
|
||||
|
||||
|
||||
// EA_COMPILER_NO_STATIC_VARIABLE_INIT
|
||||
//
|
||||
// If defined, it means that global or static C++ variables will be
|
||||
// constructed. Not all compiler/platorm combinations support this.
|
||||
// User code that needs to be portable must avoid having C++ variables
|
||||
// that construct before main.
|
||||
//
|
||||
//#if defined(EA_PLATFORM_MOBILE)
|
||||
// #define EA_COMPILER_NO_STATIC_VARIABLE_INIT
|
||||
//#endif
|
||||
|
||||
|
||||
|
||||
// EA_COMPILER_NO_STATIC_FUNCTION_INIT
|
||||
//
|
||||
// If defined, it means that functions marked as startup functions
|
||||
// (e.g. __attribute__((constructor)) in GCC) are supported. It may
|
||||
// be that some compiler/platform combinations don't support this.
|
||||
//
|
||||
//#if defined(XXX) // So far, all compiler/platforms we use support this.
|
||||
// #define EA_COMPILER_NO_STATIC_VARIABLE_INIT
|
||||
//#endif
|
||||
|
||||
|
||||
|
||||
#endif // INCLUDED_eacompiler_H
|
1024
lib/eastl/include/EABase/config/eacompilertraits.h
Normal file
1024
lib/eastl/include/EABase/config/eacompilertraits.h
Normal file
File diff suppressed because it is too large
Load diff
559
lib/eastl/include/EABase/config/eaplatform.h
Normal file
559
lib/eastl/include/EABase/config/eaplatform.h
Normal file
|
@ -0,0 +1,559 @@
|
|||
/*
|
||||
Copyright (C) 2009 Electronic Arts, Inc. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
3. Neither the name of Electronic Arts, Inc. ("EA") nor the names of
|
||||
its contributors may be used to endorse or promote products derived
|
||||
from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY ELECTRONIC ARTS AND ITS CONTRIBUTORS "AS IS" AND ANY
|
||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL ELECTRONIC ARTS OR ITS CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*-----------------------------------------------------------------------------
|
||||
* config/eaplatform.h
|
||||
*
|
||||
* Copyright (c) 2002 - 2005 Electronic Arts Inc. All rights reserved.
|
||||
* Maintained by Paul Pedriana, Maxis
|
||||
*
|
||||
*-----------------------------------------------------------------------------
|
||||
* Currently supported platform indentification defines include:
|
||||
* EA_PLATFORM_PS3
|
||||
* EA_PLATFORM_PS3_PPU
|
||||
* EA_PLATFORM_PS3_SPU
|
||||
* EA_PLATFORM_XENON (a.k.a. XBox2)
|
||||
* EA_PLATFORM_MAC
|
||||
* EA_PLATFORM_OSX
|
||||
* EA_PLATFORM_LINUX
|
||||
* EA_PLATFORM_WINDOWS
|
||||
* EA_PLATFORM_WIN32
|
||||
* EA_PLATFORM_WIN64
|
||||
* EA_PLATFORM_HPUX
|
||||
* EA_PLATFORM_SUN
|
||||
* EA_PLATFORM_LRB (Larrabee)
|
||||
* EA_PLATFORM_UNIX (pseudo-platform; may be defined along with another platform like EA_PLATFORM_LINUX)
|
||||
* EA_PLATFORM_CYGWIN (pseudo-platform; may be defined along with another platform like EA_PLATFORM_LINUX)
|
||||
* EA_PLATFORM_MINGW (pseudo-platform; may be defined along with another platform like EA_PLATFORM_WINDOWS)
|
||||
* EA_PLATFORM_MICROSOFT (pseudo-platform; may be defined along with another platform like EA_PLATFORM_WINDOWS)
|
||||
*
|
||||
* Other definitions emanated from this file inclue:
|
||||
* EA_PLATFORM_NAME = <string>
|
||||
* EA_PLATFORM_DESCRIPTION = <string>
|
||||
* EA_PROCESSOR_XXX
|
||||
* EA_SYSTEM_LITTLE_ENDIAN | EA_SYSTEM_BIG_ENDIAN
|
||||
* EA_ASM_STYLE_ATT | EA_ASM_STYLE_INTEL | EA_ASM_STYLE_MOTOROLA
|
||||
* EA_PLATFORM_PTR_SIZE = <integer size in bytes>
|
||||
* EA_PLATFORM_WORD_SIZE = <integer size in bytes>
|
||||
*
|
||||
*---------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
#ifndef INCLUDED_eaplatform_H
|
||||
#define INCLUDED_eaplatform_H
|
||||
|
||||
|
||||
// Cygwin
|
||||
// This is a pseudo-platform which will be defined along with EA_PLATFORM_LINUX when
|
||||
// using the Cygwin build environment.
|
||||
#if defined(__CYGWIN__)
|
||||
#define EA_PLATFORM_CYGWIN
|
||||
#define EA_PLATFORM_DESKTOP
|
||||
#endif
|
||||
|
||||
// MinGW
|
||||
// This is a pseudo-platform which will be defined along with EA_PLATFORM_WINDOWS when
|
||||
// using the MinGW Windows build environment.
|
||||
#if defined(__MINGW32__) || defined(__MINGW64__)
|
||||
#define EA_PLATFORM_MINGW
|
||||
#define EA_PLATFORM_DESKTOP
|
||||
#endif
|
||||
|
||||
// PlayStation 3 PPU (Primary Processing Unit)
|
||||
#if defined(EA_PLATFORM_PS3_PPU) || defined(EA_PLATFORM_PS3) || defined(__PU__) || defined(__PPU__)
|
||||
#undef EA_PLATFORM_PS3_PPU
|
||||
#define EA_PLATFORM_PS3_PPU 1
|
||||
#undef EA_PLATFORM_PS3
|
||||
#define EA_PLATFORM_PS3 1
|
||||
#define EA_PLATFORM_NAME "PS3"
|
||||
#define EA_PROCESSOR_POWERPC
|
||||
#define EA_PROCESSOR_POWERPC_64
|
||||
#define EA_SYSTEM_BIG_ENDIAN
|
||||
#define EA_PLATFORM_DESCRIPTION "PS3 on PowerPC"
|
||||
#define EA_PLATFORM_CONSOLE
|
||||
|
||||
// PlayStation 3 SPU (Synergistic Processing Unit)
|
||||
#elif defined(EA_PLATFORM_PS3_SPU) || defined(__SPU__)
|
||||
#undef EA_PLATFORM_PS3_SPU
|
||||
#define EA_PLATFORM_PS3_SPU 1
|
||||
#define EA_PLATFORM_NAME "PS3 SPU"
|
||||
#define EA_PROCESSOR_SPU
|
||||
#define EA_SYSTEM_BIG_ENDIAN
|
||||
#define EA_PLATFORM_DESCRIPTION "PS3 SPU on SPU"
|
||||
#define EA_PLATFORM_CONSOLE
|
||||
|
||||
// XBox
|
||||
// _XBOX is defined by the VC++ project, not the compiler. There is no way
|
||||
// to tell if the compiler is compiling for XBox unless _XBOX is #defined
|
||||
// in the project files or otherwise. _M_IX86 is the VC++ way of detecting
|
||||
// an x86 target, which would mean XBox and not Xenon (a.k.a. XBox2).
|
||||
#elif defined(EA_PLATFORM_XBOX) || (defined(_XBOX) && defined(_M_IX86))
|
||||
#undef EA_PLATFORM_XBOX
|
||||
#define EA_PLATFORM_XBOX 1
|
||||
#define EA_PLATFORM_NAME "XBox"
|
||||
#define EA_PROCESSOR_X86
|
||||
#define EA_SYSTEM_LITTLE_ENDIAN
|
||||
#define EA_PLATFORM_DESCRIPTION "XBox on X86"
|
||||
#if defined(_MSC_VER) || defined(__ICL)
|
||||
#define EA_ASM_STYLE_INTEL
|
||||
#endif
|
||||
#define EA_PLATFORM_CONSOLE
|
||||
|
||||
// Xenon (XBox 360)
|
||||
// The Xenon compiler doesn't define anything in particular to indicate that the
|
||||
// target is the Xenon platform. The Xenon SDK, however, expects that XBOX and
|
||||
// _XBOX are #defined, so the project build file must make sure these are defined.
|
||||
// Since the Xenon compiler in fact defines _M_PPC, we can use this information
|
||||
// to infer that Xenon is the target if neither _XENON nor _XBOX2 are specifically
|
||||
// defined by the project build file.
|
||||
#elif defined(EA_PLATFORM_XENON) || defined(_XENON) || defined(_XBOX2) || ((defined(_XBOX) || defined(XBOX)) && defined(_M_PPC))
|
||||
#undef EA_PLATFORM_XENON
|
||||
#define EA_PLATFORM_XENON 1
|
||||
#define EA_PLATFORM_NAME "Xenon"
|
||||
#define EA_PROCESSOR_POWERPC
|
||||
#define EA_PROCESSOR_POWERPC_64
|
||||
#define EA_SYSTEM_BIG_ENDIAN
|
||||
#define EA_PLATFORM_DESCRIPTION "Xenon on PowerPC"
|
||||
#if defined(_MSC_VER) || defined(__ICL)
|
||||
#define EA_ASM_STYLE_INTEL
|
||||
#endif
|
||||
#define EA_PLATFORM_CONSOLE
|
||||
#define EA_PLATFORM_MICROSOFT 1
|
||||
|
||||
// Larrabee // This part to be removed once __LRB__ is supported by the Larrabee compiler in 2009.
|
||||
#elif defined(EA_PLATFORM_LRB) || defined(__LRB__) || (defined(__EDG__) && defined(__ICC) && defined(__x86_64__))
|
||||
#undef EA_PLATFORM_LRB
|
||||
#define EA_PLATFORM_LRB 1
|
||||
#define EA_PLATFORM_NAME "Larrabee"
|
||||
#define EA_PLATFORM_DESCRIPTION "Larrabee on LRB1"
|
||||
#define EA_PROCESSOR_X86_64
|
||||
#if defined(BYTE_ORDER) && (BYTE_ORDER == 4321)
|
||||
#define EA_SYSTEM_BIG_ENDIAN
|
||||
#else
|
||||
#define EA_SYSTEM_LITTLE_ENDIAN
|
||||
#endif
|
||||
#define EA_PROCESSOR_LRB
|
||||
#define EA_PROCESSOR_LRB1 // Larrabee version 1
|
||||
#define EA_ASM_STYLE_ATT // Both types of asm style
|
||||
#define EA_ASM_STYLE_INTEL // are supported.
|
||||
#define EA_PLATFORM_DESKTOP
|
||||
|
||||
// Android (Google phone OS)
|
||||
#elif defined(EA_PLATFORM_ANDROID) || defined(__ANDROID__)
|
||||
#undef EA_PLATFORM_ANDROID
|
||||
#define EA_PLATFORM_ANDROID 1
|
||||
#define EA_PLATFORM_LINUX 1
|
||||
#define EA_PLATFORM_UNIX 1
|
||||
#define EA_PLATFORM_NAME "Android"
|
||||
#define EA_ASM_STYLE_ATT
|
||||
#if defined(__arm__)
|
||||
#define EA_PROCESSOR_ARM
|
||||
#define EA_PLATFORM_DESCRIPTION "Android on ARM"
|
||||
#else
|
||||
#error Unknown processor
|
||||
#endif
|
||||
#if !defined(EA_SYSTEM_BIG_ENDIAN) && !defined(EA_SYSTEM_LITTLE_ENDIAN)
|
||||
#define EA_SYSTEM_LITTLE_ENDIAN
|
||||
#endif
|
||||
#define EA_PLATFORM_MOBILE
|
||||
|
||||
// Palm OS for Mobile (Linux variant)
|
||||
#elif defined(EA_PLATFORM_PALM)
|
||||
#undef EA_PLATFORM_PALM
|
||||
#define EA_PLATFORM_PALM 1
|
||||
#define EA_PLATFORM_LINUX 1
|
||||
#define EA_PLATFORM_UNIX 1
|
||||
#define EA_PLATFORM_NAME "Palm"
|
||||
#define EA_POSIX_THREADS_AVAILABLE 1
|
||||
#define EA_ASM_STYLE_ATT
|
||||
#if defined(__arm__)
|
||||
#define EA_PROCESSOR_ARM
|
||||
#define EA_PLATFORM_DESCRIPTION "Palm on ARM"
|
||||
#else
|
||||
#error Unknown processor
|
||||
#endif
|
||||
#if !defined(EA_SYSTEM_BIG_ENDIAN) && !defined(EA_SYSTEM_LITTLE_ENDIAN)
|
||||
#define EA_SYSTEM_LITTLE_ENDIAN
|
||||
#endif
|
||||
#define EA_PLATFORM_MOBILE
|
||||
|
||||
// Airplay
|
||||
#elif defined(EA_PLATFORM_AIRPLAY) || defined(__S3E__)
|
||||
#undef EA_PLATFORM_AIRPLAY
|
||||
#define EA_PLATFORM_AIRPLAY
|
||||
#define EA_PLATFORM_NAME "Airplay"
|
||||
#if defined(__arm__)
|
||||
#define EA_PROCESSOR_ARM
|
||||
#define EA_PLATFORM_DESCRIPTION "Airplay on ARM"
|
||||
#define EA_ASM_STYLE_ATT
|
||||
#undef _MSC_VER
|
||||
#elif defined(_M_IX86) || defined(I3D_ARCH_X86)
|
||||
#define EA_PROCESSOR_X86
|
||||
#define EA_PLATFORM_DESCRIPTION "Airplay on x86"
|
||||
#define EA_ASM_STYLE_INTEL
|
||||
#else
|
||||
#error Unknown processor
|
||||
#endif
|
||||
#if !defined(EA_SYSTEM_BIG_ENDIAN) && !defined(EA_SYSTEM_LITTLE_ENDIAN)
|
||||
#if defined(HAVE_BIG_ENDIAN) || (defined(__BYTE_ORDER) && defined(__BIG_ENDIAN) && (__BYTE_ORDER == __BIG_ENDIAN))
|
||||
#define EA_SYSTEM_BIG_ENDIAN
|
||||
#else
|
||||
#define EA_SYSTEM_LITTLE_ENDIAN
|
||||
#endif
|
||||
#endif
|
||||
#define EA_PLATFORM_MOBILE
|
||||
|
||||
// Samsung Bada OS for Mobile (Linux variant)
|
||||
#elif defined(EA_PLATFORM_BADA)
|
||||
#undef EA_PLATFORM_BADA
|
||||
#define EA_PLATFORM_BADA 1
|
||||
//#define EA_PLATFORM_LINUX 1 // The underlying OS is Linux, but the app mostly doesn't see this.
|
||||
//#define EA_PLATFORM_UNIX 1
|
||||
#define EA_PLATFORM_NAME "bada"
|
||||
#define EA_ASM_STYLE_ATT
|
||||
#if defined(__arm__)
|
||||
#define EA_PROCESSOR_ARM
|
||||
#define EA_PLATFORM_DESCRIPTION "bada on ARM"
|
||||
#elif defined(__i386__)
|
||||
#define EA_PLATFORM_BADA_SIMULATOR
|
||||
#define EA_PROCESSOR_X86
|
||||
#define EA_PLATFORM_DESCRIPTION "bada simulator on x86"
|
||||
#else
|
||||
#error Unknown processor
|
||||
#endif
|
||||
#if !defined(EA_SYSTEM_BIG_ENDIAN) && !defined(EA_SYSTEM_LITTLE_ENDIAN)
|
||||
#define EA_SYSTEM_LITTLE_ENDIAN
|
||||
#endif
|
||||
#define EA_PLATFORM_MOBILE
|
||||
|
||||
#elif defined(__APPLE__) && __APPLE__
|
||||
#include <TargetConditionals.h>
|
||||
|
||||
// Apple family of operating systems.
|
||||
#define EA_PLATFORM_APPLE
|
||||
|
||||
// iPhone
|
||||
// TARGET_OS_IPHONE will be undefined on an unknown compiler, and will be defined on gcc.
|
||||
#if defined(EA_PLATFORM_IPHONE) || defined(__IPHONE__) || (defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE) || (defined(TARGET_IPHONE_SIMULATOR) && TARGET_IPHONE_SIMULATOR)
|
||||
#undef EA_PLATFORM_IPHONE
|
||||
#define EA_PLATFORM_IPHONE 1
|
||||
#define EA_PLATFORM_NAME "iPhone"
|
||||
#define EA_ASM_STYLE_ATT
|
||||
#define EA_POSIX_THREADS_AVAILABLE 1
|
||||
#if defined(__arm__)
|
||||
#define EA_PROCESSOR_ARM
|
||||
#define EA_SYSTEM_LITTLE_ENDIAN
|
||||
#define EA_PLATFORM_DESCRIPTION "iPhone on ARM"
|
||||
#elif defined(__i386__)
|
||||
#define EA_PLATFORM_IPHONE_SIMULATOR
|
||||
#define EA_PROCESSOR_X86
|
||||
#define EA_SYSTEM_LITTLE_ENDIAN
|
||||
#define EA_PLATFORM_DESCRIPTION "iPhone simulator on x86"
|
||||
#else
|
||||
#error Unknown processor
|
||||
#endif
|
||||
#define EA_PLATFORM_MOBILE
|
||||
|
||||
// Macintosh OSX
|
||||
// TARGET_OS_MAC is defined by the Metrowerks and older AppleC compilers.
|
||||
// Howerver, TARGET_OS_MAC is defined to be 1 in all cases.
|
||||
// __i386__ and __intel__ are defined by the GCC compiler.
|
||||
// __dest_os is defined by the Metrowerks compiler.
|
||||
// __MACH__ is defined by the Metrowerks and GCC compilers.
|
||||
// powerc and __powerc are defined by the Metrowerks and GCC compilers.
|
||||
#elif defined(EA_PLATFORM_OSX) || defined(__MACH__) || (defined(__MSL__) && (__dest_os == __mac_os_x))
|
||||
#undef EA_PLATFORM_OSX
|
||||
#define EA_PLATFORM_OSX 1
|
||||
#define EA_PLATFORM_UNIX 1
|
||||
#define EA_PLATFORM_NAME "OSX"
|
||||
#if defined(__i386__) || defined(__intel__)
|
||||
#define EA_PROCESSOR_X86
|
||||
#define EA_SYSTEM_LITTLE_ENDIAN
|
||||
#define EA_PLATFORM_DESCRIPTION "OSX on x86"
|
||||
#elif defined(__x86_64) || defined(__amd64)
|
||||
#define EA_PROCESSOR_X86_64
|
||||
#define EA_SYSTEM_LITTLE_ENDIAN
|
||||
#define EA_PLATFORM_DESCRIPTION "OSX on x86-64"
|
||||
#elif defined(__arm__)
|
||||
#define EA_PROCESSOR_ARM
|
||||
#define EA_SYSTEM_LITTLE_ENDIAN
|
||||
#define EA_PLATFORM_DESCRIPTION "OSX on ARM"
|
||||
#elif defined(__POWERPC64__) || defined(__powerpc64__)
|
||||
#define EA_PROCESSOR_POWERPC
|
||||
#define EA_PROCESSOR_POWERPC_64
|
||||
#define EA_SYSTEM_BIG_ENDIAN
|
||||
#define EA_PLATFORM_DESCRIPTION "OSX on PowerPC 64"
|
||||
#elif defined(__POWERPC__) || defined(__powerpc__)
|
||||
#define EA_PROCESSOR_POWERPC
|
||||
#define EA_PROCESSOR_POWERPC_32
|
||||
#define EA_SYSTEM_BIG_ENDIAN
|
||||
#define EA_PLATFORM_DESCRIPTION "OSX on PowerPC"
|
||||
#else
|
||||
#error Unknown processor
|
||||
#endif
|
||||
#if defined(__GNUC__)
|
||||
#define EA_ASM_STYLE_ATT
|
||||
#else
|
||||
#define EA_ASM_STYLE_MOTOROLA
|
||||
#endif
|
||||
#define EA_PLATFORM_DESKTOP
|
||||
|
||||
#else
|
||||
#error Unknown Apple Platform
|
||||
#endif
|
||||
|
||||
// Linux
|
||||
// __linux and __linux__ are defined by the GCC and Borland compiler.
|
||||
// __i386__ and __intel__ are defined by the GCC compiler.
|
||||
// __i386__ is defined by the Metrowerks compiler.
|
||||
// _M_IX86 is defined by the Borland compiler.
|
||||
// __sparc__ is defined by the GCC compiler.
|
||||
// __powerpc__ is defined by the GCC compiler.
|
||||
#elif defined(EA_PLATFORM_LINUX) || (defined(__linux) || defined(__linux__))
|
||||
#undef EA_PLATFORM_LINUX
|
||||
#define EA_PLATFORM_LINUX 1
|
||||
#define EA_PLATFORM_UNIX 1
|
||||
#define EA_PLATFORM_NAME "Linux"
|
||||
#if defined(__i386__) || defined(__intel__) || defined(_M_IX86)
|
||||
#define EA_PROCESSOR_X86
|
||||
#define EA_SYSTEM_LITTLE_ENDIAN
|
||||
#define EA_PLATFORM_DESCRIPTION "Linux on x86"
|
||||
#elif defined(__x86_64__)
|
||||
#define EA_PROCESSOR_X86_64
|
||||
#define EA_SYSTEM_LITTLE_ENDIAN
|
||||
#define EA_PLATFORM_DESCRIPTION "Linux on x86-64"
|
||||
#elif defined(__powerpc64__)
|
||||
#define EA_PROCESSOR_POWERPC
|
||||
#define EA_PROCESSOR_POWERPC_64
|
||||
#define EA_SYSTEM_BIG_ENDIAN
|
||||
#define EA_PLATFORM_DESCRIPTION "Linux on PowerPC 64"
|
||||
#elif defined(__powerpc__)
|
||||
#define EA_PROCESSOR_POWERPC
|
||||
#define EA_PROCESSOR_POWERPC_32
|
||||
#define EA_SYSTEM_BIG_ENDIAN
|
||||
#define EA_PLATFORM_DESCRIPTION "Linux on PowerPC"
|
||||
#elif defined(__arm__)
|
||||
#define EA_PROCESSOR_ARM
|
||||
#define EA_SYSTEM_LITTLE_ENDIAN
|
||||
#define EA_PLATFORM_DESCRIPTION "Linux on ARM"
|
||||
#else
|
||||
#error Unknown processor
|
||||
#error Unknown endianness
|
||||
#endif
|
||||
#if defined(__GNUC__)
|
||||
#define EA_ASM_STYLE_ATT
|
||||
#endif
|
||||
#define EA_PLATFORM_DESKTOP
|
||||
|
||||
// Win CE (Windows mobile)
|
||||
#elif defined(EA_PLATFORM_WINCE) || defined(_WIN32_WCE)
|
||||
#undef EA_PLATFORM_WINCE
|
||||
#define EA_PLATFORM_WINCE 1
|
||||
#define EA_PLATFORM_NAME "WinCE"
|
||||
#define EA_ASM_STYLE_INTEL
|
||||
#define EA_SYSTEM_LITTLE_ENDIAN
|
||||
#if defined(_M_ARM) // Also there is _M_ARMT
|
||||
#define EA_PROCESSOR_ARM
|
||||
#define EA_PLATFORM_DESCRIPTION "Windows CE on ARM"
|
||||
#elif defined(_M_IX86)
|
||||
#define EA_PROCESSOR_X86
|
||||
#define EA_PLATFORM_DESCRIPTION "Windows CE on X86"
|
||||
#else //Possibly other Windows CE variants
|
||||
#error Unknown processor
|
||||
#endif
|
||||
#define EA_PLATFORM_MOBILE
|
||||
|
||||
// Windows
|
||||
// _WIN32 is defined by the VC++, Intel and GCC compilers.
|
||||
// _WIN64 is defined by the VC++, Intel and GCC compilers.
|
||||
// __WIN32__ is defined by the Borland compiler.
|
||||
// __INTEL__ is defined by the Metrowerks compiler.
|
||||
// _M_IX86, _M_AMD64 and _M_IA64 are defined by the VC++, Intel, and Borland compilers.
|
||||
// _X86_, _AMD64_, and _IA64_ are defined by the Metrowerks compiler.
|
||||
// _M_ARM is defined by the VC++ compiler.
|
||||
#elif (defined(EA_PLATFORM_WINDOWS) || (defined(_WIN32) || defined(__WIN32__) || defined(_WIN64) || (defined(__MWERKS__) && defined(_X86_)))) && !defined(_XBOX)
|
||||
#undef EA_PLATFORM_WINDOWS
|
||||
#define EA_PLATFORM_WINDOWS 1
|
||||
#define EA_PLATFORM_NAME "Windows"
|
||||
#ifdef _WIN64 // VC++ defines both _WIN32 and _WIN64 when compiling for Win64.
|
||||
#define EA_PLATFORM_WIN64
|
||||
#else
|
||||
#define EA_PLATFORM_WIN32
|
||||
#endif
|
||||
#if defined(_M_AMD64) || defined(_AMD64_) || defined(__x86_64__)
|
||||
#define EA_PROCESSOR_X86_64
|
||||
#define EA_SYSTEM_LITTLE_ENDIAN
|
||||
#define EA_PLATFORM_DESCRIPTION "Windows on X86-64"
|
||||
#elif defined(_M_IX86) || defined(_X86_)
|
||||
#define EA_PROCESSOR_X86
|
||||
#define EA_SYSTEM_LITTLE_ENDIAN
|
||||
#define EA_PLATFORM_DESCRIPTION "Windows on X86"
|
||||
#elif defined(_M_IA64) || defined(_IA64_)
|
||||
#define EA_PROCESSOR_IA64
|
||||
#define EA_SYSTEM_LITTLE_ENDIAN
|
||||
#define EA_PLATFORM_DESCRIPTION "Windows on IA-64"
|
||||
#elif defined(_M_ARM)
|
||||
#define EA_PROCESSOR_ARM
|
||||
#define EA_SYSTEM_LITTLE_ENDIAN
|
||||
#define EA_PLATFORM_DESCRIPTION "Windows CE on ARM"
|
||||
#else //Possibly other Windows CE variants
|
||||
#error Unknown processor
|
||||
#error Unknown endianness
|
||||
#endif
|
||||
#if defined(__GNUC__)
|
||||
#define EA_ASM_STYLE_ATT
|
||||
#elif defined(_MSC_VER) || defined(__BORLANDC__) || defined(__ICL)
|
||||
#define EA_ASM_STYLE_INTEL
|
||||
#endif
|
||||
#define EA_PLATFORM_DESKTOP
|
||||
#define EA_PLATFORM_MICROSOFT 1
|
||||
|
||||
// Sun (Solaris)
|
||||
// __SUNPRO_CC is defined by the Sun compiler.
|
||||
// __sun is defined by the GCC compiler.
|
||||
// __i386 is defined by the Sun and GCC compilers.
|
||||
// __sparc is defined by the Sun and GCC compilers.
|
||||
#elif defined(EA_PLATFORM_SUN) || (defined(__SUNPRO_CC) || defined(__sun))
|
||||
#undef EA_PLATFORM_SUN
|
||||
#define EA_PLATFORM_SUN 1
|
||||
#define EA_PLATFORM_UNIX 1
|
||||
#define EA_PLATFORM_NAME "SUN"
|
||||
#if defined(__i386)
|
||||
#define EA_PROCESSOR_X86
|
||||
#define EA_SYSTEM_LITTLE_ENDIAN
|
||||
#define EA_PLATFORM_DESCRIPTION "SUN on x86"
|
||||
#elif defined(__sparc)
|
||||
#define EA_PROCESSOR_SPARC
|
||||
#define EA_SYSTEM_BIG_ENDIAN
|
||||
#define EA_PLATFORM_DESCRIPTION "SUN on Sparc"
|
||||
#else
|
||||
#error Unknown processor
|
||||
#error Unknown endianness
|
||||
#endif
|
||||
#define EA_PLATFORM_DESKTOP
|
||||
|
||||
#else
|
||||
#error Unknown platform
|
||||
#error Unknown processor
|
||||
#error Unknown endianness
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
// EA_PLATFORM_PTR_SIZE
|
||||
// Platform pointer size; same as sizeof(void*).
|
||||
// This is not the same as sizeof(int), as int is usually 32 bits on
|
||||
// even 64 bit platforms.
|
||||
//
|
||||
// _WIN64 is defined by Win64 compilers, such as VC++.
|
||||
// _M_IA64 is defined by VC++ and Intel compilers for IA64 processors.
|
||||
// __LP64__ is defined by HP compilers for the LP64 standard.
|
||||
// _LP64 is defined by the GCC and Sun compilers for the LP64 standard.
|
||||
// __ia64__ is defined by the GCC compiler for IA64 processors.
|
||||
// __arch64__ is defined by the Sparc compiler for 64 bit processors.
|
||||
// __mips64__ is defined by the GCC compiler for MIPS processors.
|
||||
// __powerpc64__ is defined by the GCC compiler for PowerPC processors.
|
||||
// __64BIT__ is defined by the AIX compiler for 64 bit processors.
|
||||
// __sizeof_ptr is defined by the ARM compiler (armcc, armcpp).
|
||||
//
|
||||
#ifndef EA_PLATFORM_PTR_SIZE
|
||||
#if defined(__WORDSIZE) // Defined by some variations of GCC.
|
||||
#define EA_PLATFORM_PTR_SIZE ((__WORDSIZE) / 8)
|
||||
#elif defined(_WIN64) || defined(__LP64__) || defined(_LP64) || defined(_M_IA64) || defined(__ia64__) || defined(__arch64__) || defined(__mips64__) || defined(__64BIT__)
|
||||
#define EA_PLATFORM_PTR_SIZE 8
|
||||
#elif defined(__CC_ARM) && (__sizeof_ptr == 8)
|
||||
#define EA_PLATFORM_PTR_SIZE 8
|
||||
#else
|
||||
#define EA_PLATFORM_PTR_SIZE 4
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
// EA_PLATFORM_WORD_SIZE
|
||||
// This defines the size of a machine word. This will be the same as
|
||||
// the size of registers on the machine but not necessarily the same
|
||||
// as the size of pointers on the machine. A number of 64 bit platforms
|
||||
// have 64 bit registers but 32 bit pointers.
|
||||
//
|
||||
#ifndef EA_PLATFORM_WORD_SIZE
|
||||
#if defined(EA_PLATFORM_XENON) || defined(EA_PLATFORM_PS3)
|
||||
#define EA_PLATFORM_WORD_SIZE 8
|
||||
#else
|
||||
#define EA_PLATFORM_WORD_SIZE EA_PLATFORM_PTR_SIZE
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
// Disabled until and unless deemed useful:
|
||||
//
|
||||
// Platform integer types
|
||||
// These definitions allow us to define other things properly, such as
|
||||
// sized integer types. In order to bring some order to this chaos,
|
||||
// we follow a variation of the standard LP64 conventions defined at:
|
||||
// http://www.opengroup.org/public/tech/aspen/lp64_wp.htm
|
||||
//
|
||||
// #if defined(EA_PLATFORM_LINUX) || defined(EA_PLATFORM_OSX) || defined(EA_PLATFORM_XBOX) || defined(EA_PLATFORM_XENON)
|
||||
// #define EA_PLATFORM_ILP32_LL64 // int, long, ptr = 32 bits; long long = 64 bits.
|
||||
//
|
||||
// #elif defined(EA_PLATFORM_SUN) || defined(EA_PLATFORM_SGI)
|
||||
// #if (EA_PLATFORM_WORD_SIZE == 32)
|
||||
// #define ILP32_LL64 // int, long, ptr = 32 bits; long long = 64 bits.
|
||||
// #else // 64 bit platform
|
||||
// #define EA_PLATFORM_I32_LLLP64 // int = 32 bits; long, long long, ptr = 64 bits.
|
||||
// #endif
|
||||
//
|
||||
// #elif defined(EA_PLATFORM_WINDOWS)
|
||||
// #if (EA_PLATFORM_WORD_SIZE == 32)
|
||||
// #define ILP32_LL64 // int, long, ptr = 32 bits; long long = 64 bits.
|
||||
// #else // 64 bit platform
|
||||
// #if defined(__MWERKS__) || defined(__GNUC__)
|
||||
// #define EA_PLATFORM_I32_LLLP64 // int = 32 bits; long, long long, ptr = 64 bits.
|
||||
// #else // MSVC
|
||||
// #define EA_PLATFORM_IL32_LLP64 // int, long = 32 bits; long long, ptr = 64 bits.
|
||||
// #endif
|
||||
// #endif
|
||||
// #endif
|
||||
|
||||
|
||||
#endif // INCLUDED_eaplatform_H
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
876
lib/eastl/include/EABase/eabase.h
Normal file
876
lib/eastl/include/EABase/eabase.h
Normal file
|
@ -0,0 +1,876 @@
|
|||
/*
|
||||
Copyright (C) 2009 Electronic Arts, Inc. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
3. Neither the name of Electronic Arts, Inc. ("EA") nor the names of
|
||||
its contributors may be used to endorse or promote products derived
|
||||
from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY ELECTRONIC ARTS AND ITS CONTRIBUTORS "AS IS" AND ANY
|
||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL ELECTRONIC ARTS OR ITS CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*-----------------------------------------------------------------------------
|
||||
* eabase.h
|
||||
*
|
||||
* Copyright (c) 2002 - 2005 Electronic Arts Inc. All rights reserved.
|
||||
* Maintained by Paul Pedriana, Maxis
|
||||
*---------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
#ifndef INCLUDED_eabase_H
|
||||
#define INCLUDED_eabase_H
|
||||
|
||||
|
||||
// Identify the compiler and declare the EA_COMPILER_xxxx defines
|
||||
#ifndef INCLUDED_eacompiler_H
|
||||
# include "EABase/config/eacompiler.h"
|
||||
#endif
|
||||
|
||||
// Identify traits which this compiler supports, or does not support
|
||||
#ifndef INCLUDED_eacompilertraits_H
|
||||
# include "EABase/config/eacompilertraits.h"
|
||||
#endif
|
||||
|
||||
// Identify the platform and declare the EA_xxxx defines
|
||||
#ifndef INCLUDED_eaplatform_H
|
||||
# include "EABase/config/eaplatform.h"
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// EABASE_VERSION
|
||||
//
|
||||
// We more or less follow the conventional EA packaging approach to versioning
|
||||
// here. A primary distinction here is that minor versions are defined as two
|
||||
// digit entities (e.g. .03") instead of minimal digit entities ".3"). The logic
|
||||
// here is that the value is a counter and not a floating point fraction.
|
||||
// Note that the major version doesn't have leading zeros.
|
||||
//
|
||||
// Example version strings:
|
||||
// "0.91.00" // Major version 0, minor version 91, patch version 0.
|
||||
// "1.00.00" // Major version 1, minor and patch version 0.
|
||||
// "3.10.02" // Major version 3, minor version 10, patch version 02.
|
||||
// "12.03.01" // Major version 12, minor version 03, patch version
|
||||
//
|
||||
// Example usage:
|
||||
// printf("EABASE version: %s", EABASE_VERSION);
|
||||
// printf("EABASE version: %d.%d.%d", EABASE_VERSION_N / 10000 % 100, EABASE_VERSION_N / 100 % 100, EABASE_VERSION_N % 100);
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef EABASE_VERSION
|
||||
# define EABASE_VERSION "2.00.22"
|
||||
# define EABASE_VERSION_N 20022
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// The C++ standard defines size_t as a built-in type. Some compilers are
|
||||
// not standards-compliant in this respect, so we need an additional include.
|
||||
// The case is similar with wchar_t under C++.
|
||||
|
||||
#if defined(EA_COMPILER_GNUC) || defined(EA_COMPILER_MSVC) || defined(EA_WCHAR_T_NON_NATIVE)
|
||||
# include <stddef.h>
|
||||
#endif
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// Ensure this header file is only processed once (with certain compilers)
|
||||
// GCC doesn't need such a pragma because it has special recognition for
|
||||
// include guards (such as that above) and effectively implements the same
|
||||
// thing without having to resort to non-portable pragmas. It is possible
|
||||
// that the decision to use pragma once here is ill-advised, perhaps because
|
||||
// some compilers masquerade as MSVC but don't implement all features.
|
||||
#if defined(EA_COMPILER_MSVC) || defined(EA_COMPILER_METROWERKS)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// By default, GCC on certain platforms defines NULL as ((void*)0), which is the
|
||||
// C definition. This causes all sort of problems for C++ code, so it is
|
||||
// worked around by undefining NULL.
|
||||
|
||||
#if defined(NULL)
|
||||
# undef NULL
|
||||
#endif
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// Define the NULL pointer. This is normally defined in <stddef.h>, but we
|
||||
// don't want to force a global dependency on that header, so the definition
|
||||
// is duplicated here.
|
||||
|
||||
#if defined(__cplusplus)
|
||||
# define NULL 0
|
||||
#else
|
||||
# define NULL ((void*)0)
|
||||
#endif
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// C98/99 Standard typedefs. From the ANSI ISO/IEC 9899 standards document
|
||||
// Most recent versions of the gcc-compiler come with these defined in
|
||||
// inttypes.h or stddef.h. Determining if they are predefined can be
|
||||
// tricky, so we expect some problems on non-standard compilers
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// We need to test this after we potentially include stddef.h, otherwise we
|
||||
// would have put this into the compilertraits header.
|
||||
#if !defined(EA_COMPILER_HAS_INTTYPES) && (!defined(_MSC_VER) || (_MSC_VER > 1500)) && (defined(EA_COMPILER_IS_C99) || defined(INT8_MIN) || defined(EA_COMPILER_HAS_C99_TYPES) || defined(_SN_STDINT_H))
|
||||
# define EA_COMPILER_HAS_INTTYPES
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef EA_COMPILER_HAS_INTTYPES // If the compiler supports inttypes...
|
||||
// ------------------------------------------------------------------------
|
||||
// Include the stdint header to define and derive the required types.
|
||||
// Additionally include inttypes.h as many compilers, including variations
|
||||
// of GCC define things in inttypes.h that the C99 standard says goes
|
||||
// in stdint.h.
|
||||
//
|
||||
// The C99 standard specifies that inttypes.h only define printf/scanf
|
||||
// format macros if __STDC_FORMAT_MACROS is defined before #including
|
||||
// inttypes.h. For consistency, we do that here.
|
||||
# ifndef __STDC_FORMAT_MACROS
|
||||
# define __STDC_FORMAT_MACROS
|
||||
# endif
|
||||
# if !defined(__psp__) && defined(__GNUC__) // The GCC compiler defines standard int types (e.g. uint32_t) but not PRId8, etc.
|
||||
# include <inttypes.h> // PRId8, SCNd8, etc.
|
||||
# endif
|
||||
# include <stdint.h> // int32_t, INT64_C, UINT8_MAX, etc.
|
||||
# include <math.h> // float_t, double_t, etc.
|
||||
# include <float.h> // FLT_EVAL_METHOD.
|
||||
|
||||
# if !defined(FLT_EVAL_METHOD) && (defined(__FLT_EVAL_METHOD__) || defined(_FEVAL)) // GCC 3.x defines __FLT_EVAL_METHOD__ instead of the C99 standard FLT_EVAL_METHOD.
|
||||
# ifdef __FLT_EVAL_METHOD__
|
||||
# define FLT_EVAL_METHOD __FLT_EVAL_METHOD__
|
||||
# else
|
||||
# define FLT_EVAL_METHOD _FEVAL
|
||||
# endif
|
||||
# endif
|
||||
|
||||
// MinGW GCC (up to at least v4.3.0-20080502) mistakenly neglects to define float_t and double_t.
|
||||
// This appears to be an acknowledged bug as of March 2008 and is scheduled to be fixed.
|
||||
// Similarly, Android uses a mix of custom standard library headers which don't define float_t and double_t.
|
||||
# if defined(__MINGW32__) || defined(EA_PLATFORM_ANDROID)
|
||||
# if defined(__FLT_EVAL_METHOD__)
|
||||
# if(__FLT_EVAL_METHOD__== 0)
|
||||
typedef float float_t;
|
||||
typedef double double_t;
|
||||
# elif(__FLT_EVAL_METHOD__ == 1)
|
||||
typedef double float_t;
|
||||
typedef double double_t;
|
||||
# elif(__FLT_EVAL_METHOD__ == 2)
|
||||
typedef long double float_t;
|
||||
typedef long double double_t;
|
||||
# endif
|
||||
# else
|
||||
typedef float float_t;
|
||||
typedef double double_t;
|
||||
# endif
|
||||
# endif
|
||||
|
||||
// Airplay's pretty broken for these types (at least as of 4.1)
|
||||
# if defined __S3E__
|
||||
|
||||
typedef float float_t;
|
||||
typedef double double_t;
|
||||
|
||||
# undef INT32_C
|
||||
# undef UINT32_C
|
||||
# undef INT64_C
|
||||
# undef UINT64_C
|
||||
# define INT32_C(x) x##L
|
||||
# define UINT32_C(x) x##UL
|
||||
# define INT64_C(x) x##LL
|
||||
# define UINT64_C(x) x##ULL
|
||||
|
||||
# define EA_PRI_64_LENGTH_SPECIFIER "ll"
|
||||
# define EA_SCN_64_LENGTH_SPECIFIER "ll"
|
||||
|
||||
# define SCNd16 "hd"
|
||||
# define SCNi16 "hi"
|
||||
# define SCNo16 "ho"
|
||||
# define SCNu16 "hu"
|
||||
# define SCNx16 "hx"
|
||||
|
||||
# define SCNd32 "d" // This works for both 32 bit and 64 bit systems, as we assume LP64 conventions.
|
||||
# define SCNi32 "i"
|
||||
# define SCNo32 "o"
|
||||
# define SCNu32 "u"
|
||||
# define SCNx32 "x"
|
||||
|
||||
# define SCNd64 EA_SCN_64_LENGTH_SPECIFIER "d"
|
||||
# define SCNi64 EA_SCN_64_LENGTH_SPECIFIER "i"
|
||||
# define SCNo64 EA_SCN_64_LENGTH_SPECIFIER "o"
|
||||
# define SCNu64 EA_SCN_64_LENGTH_SPECIFIER "u"
|
||||
# define SCNx64 EA_SCN_64_LENGTH_SPECIFIER "x"
|
||||
|
||||
# define PRIdPTR PRId32 // Usage of pointer values will generate warnings with
|
||||
# define PRIiPTR PRIi32 // some compilers because they are defined in terms of
|
||||
# define PRIoPTR PRIo32 // integers. However, you can't simply use "p" because
|
||||
# define PRIuPTR PRIu32 // 'p' is interpreted in a specific and often different
|
||||
# define PRIxPTR PRIx32 // way by the library.
|
||||
# define PRIXPTR PRIX32
|
||||
|
||||
# define PRId8 "hhd"
|
||||
# define PRIi8 "hhi"
|
||||
# define PRIo8 "hho"
|
||||
# define PRIu8 "hhu"
|
||||
# define PRIx8 "hhx"
|
||||
# define PRIX8 "hhX"
|
||||
|
||||
# define PRId16 "hd"
|
||||
# define PRIi16 "hi"
|
||||
# define PRIo16 "ho"
|
||||
# define PRIu16 "hu"
|
||||
# define PRIx16 "hx"
|
||||
# define PRIX16 "hX"
|
||||
|
||||
# define PRId32 "d" // This works for both 32 bit and 64 bit systems, as we assume LP64 conventions.
|
||||
# define PRIi32 "i"
|
||||
# define PRIo32 "o"
|
||||
# define PRIu32 "u"
|
||||
# define PRIx32 "x"
|
||||
# define PRIX32 "X"
|
||||
|
||||
# define PRId64 EA_PRI_64_LENGTH_SPECIFIER "d"
|
||||
# define PRIi64 EA_PRI_64_LENGTH_SPECIFIER "i"
|
||||
# define PRIo64 EA_PRI_64_LENGTH_SPECIFIER "o"
|
||||
# define PRIu64 EA_PRI_64_LENGTH_SPECIFIER "u"
|
||||
# define PRIx64 EA_PRI_64_LENGTH_SPECIFIER "x"
|
||||
# define PRIX64 EA_PRI_64_LENGTH_SPECIFIER "X"
|
||||
# endif
|
||||
|
||||
// The CodeSourcery definitions of PRIxPTR and SCNxPTR are broken for 32 bit systems.
|
||||
# if defined(__SIZEOF_SIZE_T__) && (__SIZEOF_SIZE_T__ == 4) && (defined(__have_long64) || defined(__have_longlong64) || defined(__S3E__))
|
||||
# undef PRIdPTR
|
||||
# define PRIdPTR "d"
|
||||
# undef PRIiPTR
|
||||
# define PRIiPTR "i"
|
||||
# undef PRIoPTR
|
||||
# define PRIoPTR "o"
|
||||
# undef PRIuPTR
|
||||
# define PRIuPTR "u"
|
||||
# undef PRIxPTR
|
||||
# define PRIxPTR "x"
|
||||
# undef PRIXPTR
|
||||
# define PRIXPTR "X"
|
||||
|
||||
# undef SCNdPTR
|
||||
# define SCNdPTR "d"
|
||||
# undef SCNiPTR
|
||||
# define SCNiPTR "i"
|
||||
# undef SCNoPTR
|
||||
# define SCNoPTR "o"
|
||||
# undef SCNuPTR
|
||||
# define SCNuPTR "u"
|
||||
# undef SCNxPTR
|
||||
# define SCNxPTR "x"
|
||||
# endif
|
||||
#else // else we must implement types ourselves.
|
||||
|
||||
# if !defined(__S3E__)
|
||||
# if !defined(__BIT_TYPES_DEFINED__) && !defined(__int8_t_defined)
|
||||
typedef signed char int8_t; //< 8 bit signed integer
|
||||
# endif
|
||||
# if !defined( __int8_t_defined )
|
||||
typedef signed short int16_t; //< 16 bit signed integer
|
||||
typedef signed int int32_t; //< 32 bit signed integer. This works for both 32 bit and 64 bit platforms, as we assume the LP64 is followed.
|
||||
# define __int8_t_defined
|
||||
# endif
|
||||
typedef unsigned char uint8_t; //< 8 bit unsigned integer
|
||||
typedef unsigned short uint16_t; //< 16 bit unsigned integer
|
||||
# if !defined( __uint32_t_defined )
|
||||
typedef unsigned int uint32_t; //< 32 bit unsigned integer. This works for both 32 bit and 64 bit platforms, as we assume the LP64 is followed.
|
||||
# define __uint32_t_defined
|
||||
# endif
|
||||
# endif
|
||||
|
||||
// According to the C98/99 standard, FLT_EVAL_METHOD defines control the
|
||||
// width used for floating point _t types.
|
||||
# if defined(__MWERKS__) && ((defined(_MSL_C99) && (_MSL_C99 == 1)) || (__MWERKS__ < 0x4000))
|
||||
// Metrowerks defines FLT_EVAL_METHOD and
|
||||
// float_t/double_t under this condition.
|
||||
# elif defined(FLT_EVAL_METHOD)
|
||||
# if (FLT_EVAL_METHOD == 0)
|
||||
typedef float float_t;
|
||||
typedef double double_t;
|
||||
# elif (FLT_EVAL_METHOD == 1)
|
||||
typedef double float_t;
|
||||
typedef double double_t;
|
||||
# elif (FLT_EVAL_METHOD == 2)
|
||||
typedef long double float_t;
|
||||
typedef long double double_t;
|
||||
# endif
|
||||
# else
|
||||
# define FLT_EVAL_METHOD 0
|
||||
typedef float float_t;
|
||||
typedef double double_t;
|
||||
# endif
|
||||
|
||||
# if defined(EA_PLATFORM_LINUX) || defined(EA_PLATFORM_PS3) || defined(EA_PLATFORM_PS3_SPU)
|
||||
typedef signed long long int64_t;
|
||||
typedef unsigned long long uint64_t;
|
||||
|
||||
# elif defined(EA_PLATFORM_SUN) || defined(EA_PLATFORM_SGI)
|
||||
# if (EA_PLATFORM_PTR_SIZE == 4)
|
||||
typedef signed long long int64_t;
|
||||
typedef unsigned long long uint64_t;
|
||||
# else
|
||||
typedef signed long int64_t;
|
||||
typedef unsigned long uint64_t;
|
||||
# endif
|
||||
|
||||
# elif defined(EA_PLATFORM_WINDOWS) || defined(EA_PLATFORM_XBOX) || defined(EA_PLATFORM_XENON) || defined(EA_PLATFORM_MAC)
|
||||
# if defined(EA_COMPILER_MSVC) || defined(EA_COMPILER_BORLAND) || defined(EA_COMPILER_INTEL)
|
||||
typedef signed __int64 int64_t;
|
||||
typedef unsigned __int64 uint64_t;
|
||||
# else // GCC, Metrowerks, etc.
|
||||
typedef long long int64_t;
|
||||
typedef unsigned long long uint64_t;
|
||||
# endif
|
||||
# elif defined(EA_PLATFORM_AIRPLAY)
|
||||
# else
|
||||
typedef signed long long int64_t;
|
||||
typedef unsigned long long uint64_t;
|
||||
# endif
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// macros for declaring constants in a portable way.
|
||||
//
|
||||
// e.g. int64_t x = INT64_C(1234567812345678);
|
||||
// e.g. int64_t x = INT64_C(0x1111111122222222);
|
||||
// e.g. uint64_t x = UINT64_C(0x1111111122222222);
|
||||
|
||||
# ifndef INT8_C_DEFINED // If the user hasn't already defined these...
|
||||
# define INT8_C_DEFINED
|
||||
|
||||
// VC++ 7.0 and earlier don't handle the LL suffix.
|
||||
# if defined(EA_COMPILER_MSVC) || defined(EA_COMPILER_BORLAND)
|
||||
# ifndef INT8_C
|
||||
# define INT8_C(x) int8_t(x) // x##i8 doesn't work satisfactorilly because -128i8 generates an out of range warning.
|
||||
# endif
|
||||
# ifndef UINT8_C
|
||||
# define UINT8_C(x) uint8_t(x)
|
||||
# endif
|
||||
# ifndef INT16_C
|
||||
# define INT16_C(x) int16_t(x) // x##i16 doesn't work satisfactorilly because -32768i8 generates an out of range warning.
|
||||
# endif
|
||||
# ifndef UINT16_C
|
||||
# define UINT16_C(x) uint16_t(x)
|
||||
# endif
|
||||
# ifndef INT32_C
|
||||
# define INT32_C(x) x##i32
|
||||
# endif
|
||||
# ifndef UINT32_C
|
||||
# define UINT32_C(x) x##ui32
|
||||
# endif
|
||||
# ifndef INT64_C
|
||||
# define INT64_C(x) x##i64
|
||||
# endif
|
||||
# ifndef UINT64_C
|
||||
# define UINT64_C(x) x##ui64
|
||||
# endif
|
||||
|
||||
# elif !defined(__STDC_CONSTANT_MACROS) // __STDC_CONSTANT_MACROS is defined by GCC 3 and later when INT8_C(), etc. are defined.
|
||||
# define INT8_C(x) int8_t(x) // For the majority of compilers and platforms, long is 32 bits and long long is 64 bits.
|
||||
# define UINT8_C(x) uint8_t(x)
|
||||
# define INT16_C(x) int16_t(x)
|
||||
# define UINT16_C(x) uint16_t(x) // Possibly we should make this be uint16_t(x##u). Let's see how compilers react before changing this.
|
||||
# if defined(EA_PLATFORM_PS3) // PS3 defines long as 64 bit, so we cannot use any size suffix.
|
||||
# define INT32_C(x) int32_t(x)
|
||||
# define UINT32_C(x) uint32_t(x)
|
||||
# else // Else we are working on a platform whereby sizeof(long) == sizeof(int32_t).
|
||||
# define INT32_C(x) x##L
|
||||
# define UINT32_C(x) x##UL
|
||||
# endif
|
||||
# define INT64_C(x) x##LL // The way to deal with this is to compare ULONG_MAX to 0xffffffff and if not equal, then remove the L.
|
||||
# define UINT64_C(x) x##ULL // We need to follow a similar approach for LL.
|
||||
# endif
|
||||
# endif
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// type sizes
|
||||
# ifndef INT8_MAX_DEFINED // If the user hasn't already defined these...
|
||||
# define INT8_MAX_DEFINED
|
||||
|
||||
// The value must be 2^(n-1)-1
|
||||
# ifndef INT8_MAX
|
||||
# define INT8_MAX 127
|
||||
# endif
|
||||
# ifndef INT16_MAX
|
||||
# define INT16_MAX 32767
|
||||
# endif
|
||||
# ifndef INT32_MAX
|
||||
# define INT32_MAX 2147483647
|
||||
# endif
|
||||
# ifndef INT64_MAX
|
||||
# define INT64_MAX INT64_C(9223372036854775807)
|
||||
# endif
|
||||
|
||||
// The value must be either -2^(n-1) or 1-2(n-1).
|
||||
# ifndef INT8_MIN
|
||||
# define INT8_MIN -128
|
||||
# endif
|
||||
# ifndef INT16_MIN
|
||||
# define INT16_MIN -32768
|
||||
# endif
|
||||
# ifndef INT32_MIN
|
||||
# define INT32_MIN (-INT32_MAX - 1) // -2147483648
|
||||
# endif
|
||||
# ifndef INT64_MIN
|
||||
# define INT64_MIN (-INT64_MAX - 1) // -9223372036854775808
|
||||
# endif
|
||||
|
||||
// The value must be 2^n-1
|
||||
# ifndef UINT8_MAX
|
||||
# define UINT8_MAX 0xffU // 255
|
||||
# endif
|
||||
# ifndef UINT16_MAX
|
||||
# define UINT16_MAX 0xffffU // 65535
|
||||
# endif
|
||||
# ifndef UINT32_MAX
|
||||
# define UINT32_MAX UINT32_C(0xffffffff) // 4294967295
|
||||
# endif
|
||||
# ifndef UINT64_MAX
|
||||
# define UINT64_MAX UINT64_C(0xffffffffffffffff) // 18446744073709551615
|
||||
# endif
|
||||
# endif
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// sized printf and scanf format specifiers
|
||||
// See the C99 standard, section 7.8.1 -- Macros for format specifiers.
|
||||
//
|
||||
// The C99 standard specifies that inttypes.h only define printf/scanf
|
||||
// format macros if __STDC_FORMAT_MACROS is defined before #including
|
||||
// inttypes.h. For consistency, we define both __STDC_FORMAT_MACROS and
|
||||
// the printf format specifiers here. We also skip the "least/most"
|
||||
// variations of these specifiers, as we've decided to do so with
|
||||
// basic types.
|
||||
//
|
||||
// For 64 bit systems, we assume the LP64 standard is followed
|
||||
// (as opposed to ILP64, etc.) For 32 bit systems, we assume the
|
||||
// ILP32 standard is followed. See:
|
||||
// http://www.opengroup.org/public/tech/aspen/lp64_wp.htm
|
||||
// for information about this. Thus, on both 32 and 64 bit platforms,
|
||||
// %l refers to 32 bit data while %ll refers to 64 bit data.
|
||||
|
||||
# ifndef __STDC_FORMAT_MACROS
|
||||
# define __STDC_FORMAT_MACROS
|
||||
# endif
|
||||
|
||||
# if defined(EA_COMPILER_MSVC) || defined(EA_COMPILER_BORLAND) // VC++ 7.1+ understands long long as a data type but doesn't accept %ll as a printf specifier.
|
||||
# define EA_PRI_64_LENGTH_SPECIFIER "I64"
|
||||
# define EA_SCN_64_LENGTH_SPECIFIER "I64"
|
||||
# else
|
||||
# define EA_PRI_64_LENGTH_SPECIFIER "ll"
|
||||
# define EA_SCN_64_LENGTH_SPECIFIER "ll"
|
||||
# endif // It turns out that some platforms use %q to represent a 64 bit value, but these are not relevant to us at this time.
|
||||
|
||||
// Printf format specifiers
|
||||
# if defined(EA_COMPILER_IS_C99) || defined(EA_COMPILER_GNUC) || defined(EA_COMPILER_METROWERKS) // || defined(EA_COMPILER_INTEL) ?
|
||||
# define PRId8 "hhd"
|
||||
# define PRIi8 "hhi"
|
||||
# define PRIo8 "hho"
|
||||
# define PRIu8 "hhu"
|
||||
# define PRIx8 "hhx"
|
||||
# define PRIX8 "hhX"
|
||||
# else // VC++, Borland, etc. which have no way to specify 8 bit values other than %c.
|
||||
# define PRId8 "c" // This may not work properly but it at least will not crash. Try using 16 bit versions instead.
|
||||
# define PRIi8 "c" // "
|
||||
# define PRIo8 "o" // "
|
||||
# define PRIu8 "u" // "
|
||||
# define PRIx8 "x" // "
|
||||
# define PRIX8 "X" // "
|
||||
# endif
|
||||
|
||||
# define PRId16 "hd"
|
||||
# define PRIi16 "hi"
|
||||
# define PRIo16 "ho"
|
||||
# define PRIu16 "hu"
|
||||
# define PRIx16 "hx"
|
||||
# define PRIX16 "hX"
|
||||
|
||||
# define PRId32 "d" // This works for both 32 bit and 64 bit systems, as we assume LP64 conventions.
|
||||
# define PRIi32 "i"
|
||||
# define PRIo32 "o"
|
||||
# define PRIu32 "u"
|
||||
# define PRIx32 "x"
|
||||
# define PRIX32 "X"
|
||||
|
||||
# define PRId64 EA_PRI_64_LENGTH_SPECIFIER "d"
|
||||
# define PRIi64 EA_PRI_64_LENGTH_SPECIFIER "i"
|
||||
# define PRIo64 EA_PRI_64_LENGTH_SPECIFIER "o"
|
||||
# define PRIu64 EA_PRI_64_LENGTH_SPECIFIER "u"
|
||||
# define PRIx64 EA_PRI_64_LENGTH_SPECIFIER "x"
|
||||
# define PRIX64 EA_PRI_64_LENGTH_SPECIFIER "X"
|
||||
|
||||
# if (EA_PLATFORM_PTR_SIZE == 4)
|
||||
# define PRIdPTR PRId32 // Usage of pointer values will generate warnings with
|
||||
# define PRIiPTR PRIi32 // some compilers because they are defined in terms of
|
||||
# define PRIoPTR PRIo32 // integers. However, you can't simply use "p" because
|
||||
# define PRIuPTR PRIu32 // 'p' is interpreted in a specific and often different
|
||||
# define PRIxPTR PRIx32 // way by the library.
|
||||
# define PRIXPTR PRIX32
|
||||
# elif (EA_PLATFORM_PTR_SIZE == 8)
|
||||
# define PRIdPTR PRId64
|
||||
# define PRIiPTR PRIi64
|
||||
# define PRIoPTR PRIo64
|
||||
# define PRIuPTR PRIu64
|
||||
# define PRIxPTR PRIx64
|
||||
# define PRIXPTR PRIX64
|
||||
# endif
|
||||
|
||||
// Scanf format specifiers
|
||||
# if defined(EA_COMPILER_IS_C99) || defined(EA_COMPILER_GNUC) || defined(EA_COMPILER_METROWERKS) // || defined(EA_COMPILER_INTEL) ?
|
||||
# define SCNd8 "hhd"
|
||||
# define SCNi8 "hhi"
|
||||
# define SCNo8 "hho"
|
||||
# define SCNu8 "hhu"
|
||||
# define SCNx8 "hhx"
|
||||
# else // VC++, Borland, etc. which have no way to specify 8 bit values other than %c.
|
||||
# define SCNd8 "c" // This will not work properly but it at least will not crash. Try using 16 bit versions instead.
|
||||
# define SCNi8 "c" // "
|
||||
# define SCNo8 "c" // "
|
||||
# define SCNu8 "c" // "
|
||||
# define SCNx8 "c" // "
|
||||
# endif
|
||||
|
||||
# define SCNd16 "hd"
|
||||
# define SCNi16 "hi"
|
||||
# define SCNo16 "ho"
|
||||
# define SCNu16 "hu"
|
||||
# define SCNx16 "hx"
|
||||
|
||||
# define SCNd32 "d" // This works for both 32 bit and 64 bit systems, as we assume LP64 conventions.
|
||||
# define SCNi32 "i"
|
||||
# define SCNo32 "o"
|
||||
# define SCNu32 "u"
|
||||
# define SCNx32 "x"
|
||||
|
||||
# define SCNd64 EA_SCN_64_LENGTH_SPECIFIER "d"
|
||||
# define SCNi64 EA_SCN_64_LENGTH_SPECIFIER "i"
|
||||
# define SCNo64 EA_SCN_64_LENGTH_SPECIFIER "o"
|
||||
# define SCNu64 EA_SCN_64_LENGTH_SPECIFIER "u"
|
||||
# define SCNx64 EA_SCN_64_LENGTH_SPECIFIER "x"
|
||||
|
||||
# if (EA_PLATFORM_PTR_SIZE == 4)
|
||||
# define SCNdPTR SCNd32 // Usage of pointer values will generate warnings with
|
||||
# define SCNiPTR SCNi32 // some compilers because they are defined in terms of
|
||||
# define SCNoPTR SCNo32 // integers. However, you can't simply use "p" because
|
||||
# define SCNuPTR SCNu32 // 'p' is interpreted in a specific and often different
|
||||
# define SCNxPTR SCNx32 // way by the library.
|
||||
# elif (EA_PLATFORM_PTR_SIZE == 8)
|
||||
# define SCNdPTR SCNd64
|
||||
# define SCNiPTR SCNi64
|
||||
# define SCNoPTR SCNo64
|
||||
# define SCNuPTR SCNu64
|
||||
# define SCNxPTR SCNx64
|
||||
# endif
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// bool8_t
|
||||
// The definition of a bool8_t is controversial with some, as it doesn't
|
||||
// act just like built-in bool. For example, you can assign -100 to it.
|
||||
//
|
||||
#ifndef BOOL8_T_DEFINED // If the user hasn't already defined this...
|
||||
# define BOOL8_T_DEFINED
|
||||
# if defined(EA_COMPILER_MSVC) || defined(EA_COMPILER_METROWERKS) || (defined(EA_COMPILER_INTEL) && defined(EA_PLATFORM_WINDOWS)) || defined(EA_COMPILER_BORLAND)
|
||||
# if defined(__cplusplus)
|
||||
typedef bool bool8_t;
|
||||
# else
|
||||
typedef int8_t bool8_t;
|
||||
# endif
|
||||
# else // EA_COMPILER_GNUC generally uses 4 bytes per bool.
|
||||
typedef int8_t bool8_t;
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// intptr_t / uintptr_t
|
||||
// Integer type guaranteed to be big enough to hold
|
||||
// a native pointer ( intptr_t is defined in STDDEF.H )
|
||||
//
|
||||
#if !defined(_INTPTR_T_DEFINED) && !defined(_intptr_t_defined) && !defined(EA_COMPILER_HAS_C99_TYPES)
|
||||
# if (EA_PLATFORM_PTR_SIZE == 4)
|
||||
typedef int32_t intptr_t;
|
||||
# elif (EA_PLATFORM_PTR_SIZE == 8)
|
||||
typedef int64_t intptr_t;
|
||||
# endif
|
||||
|
||||
# define _intptr_t_defined
|
||||
# define _INTPTR_T_DEFINED
|
||||
#endif
|
||||
|
||||
#if !defined(_UINTPTR_T_DEFINED) && !defined(_uintptr_t_defined) && !defined(EA_COMPILER_HAS_C99_TYPES)
|
||||
# if (EA_PLATFORM_PTR_SIZE == 4)
|
||||
typedef uint32_t uintptr_t;
|
||||
# elif (EA_PLATFORM_PTR_SIZE == 8)
|
||||
typedef uint64_t uintptr_t;
|
||||
# endif
|
||||
|
||||
# define _uintptr_t_defined
|
||||
# define _UINTPTR_T_DEFINED
|
||||
#endif
|
||||
|
||||
#if !defined(EA_COMPILER_HAS_INTTYPES)
|
||||
# ifndef INTMAX_T_DEFINED
|
||||
# define INTMAX_T_DEFINED
|
||||
|
||||
// At this time, all supported compilers have int64_t as the max
|
||||
// integer type. Some compilers support a 128 bit inteter type,
|
||||
// but in those cases it is not a true int128_t but rather a
|
||||
// crippled data type.
|
||||
typedef int64_t intmax_t;
|
||||
typedef uint64_t uintmax_t;
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// ssize_t
|
||||
// signed equivalent to size_t.
|
||||
// This is defined by GCC but not by other compilers.
|
||||
//
|
||||
#if !defined(__GNUC__)
|
||||
// As of this writing, all non-GCC compilers significant to us implement
|
||||
// uintptr_t the same as size_t. However, this isn't guaranteed to be
|
||||
// so for all compilers, as size_t may be based on int, long, or long long.
|
||||
# if defined(_MSC_VER) && (EA_PLATFORM_PTR_SIZE == 8)
|
||||
typedef __int64 ssize_t;
|
||||
# elif !defined(__S3E__)
|
||||
typedef long ssize_t;
|
||||
# endif
|
||||
#elif defined(EA_PLATFORM_UNIX) || defined(EA_PLATFORM_MINGW) || defined(__APPLE__) || defined(_BSD_SIZE_T_) // _BSD_SIZE_T_ indicates that Unix-like headers are present, even though it may not be a true Unix platform.
|
||||
# include <sys/types.h>
|
||||
#endif
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// Character types
|
||||
|
||||
#if defined(EA_COMPILER_MSVC) || defined(EA_COMPILER_BORLAND)
|
||||
# if defined(EA_WCHAR_T_NON_NATIVE)
|
||||
// In this case, wchar_t is not defined unless we include
|
||||
// wchar.h or if the compiler makes it built-in.
|
||||
# ifdef EA_COMPILER_MSVC
|
||||
# pragma warning(push, 3)
|
||||
# endif
|
||||
# include <wchar.h>
|
||||
# ifdef EA_COMPILER_MSVC
|
||||
# pragma warning(pop)
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// char8_t -- Guaranteed to be equal to the compiler's char data type.
|
||||
// Some compilers implement char8_t as unsigned, though char
|
||||
// is usually set to be signed.
|
||||
//
|
||||
// char16_t -- This is set to be an unsigned 16 bit value. If the compiler
|
||||
// has wchar_t as an unsigned 16 bit value, then char16_t is
|
||||
// set to be the same thing as wchar_t in order to allow the
|
||||
// user to use char16_t with standard wchar_t functions.
|
||||
//
|
||||
// char32_t -- This is set to be an unsigned 32 bit value. If the compiler
|
||||
// has wchar_t as an unsigned 32 bit value, then char32_t is
|
||||
// set to be the same thing as wchar_t in order to allow the
|
||||
// user to use char32_t with standard wchar_t functions.
|
||||
//
|
||||
// VS2010 unilaterally defines char16_t and char32_t in its yvals.h header
|
||||
// unless _HAS_CHAR16_T_LANGUAGE_SUPPORT or _CHAR16T are defined.
|
||||
// However, VS2010 does not support the C++0x u"" and U"" string literals,
|
||||
// which makes its definition of char16_t and char32_t somewhat useless.
|
||||
// Until VC++ supports string literals, the buildystems should define
|
||||
// _CHAR16T and let EABase define char16_t and EA_CHAR16.
|
||||
//
|
||||
// GCC defines char16_t and char32_t in the C compiler in -std=gnu99 mode,
|
||||
// as __CHAR16_TYPE__ and __CHAR32_TYPE__, and for the C++ compiler
|
||||
// in -std=c++0x and -std=gnu++0x modes, as char16_t and char32_t too.
|
||||
|
||||
#if !defined(EA_CHAR16_NATIVE)
|
||||
# if defined(_MSC_VER) && (_MSC_VER >= 1600) && defined(_CHAR16T) || (defined(_HAS_CHAR16_T_LANGUAGE_SUPPORT) && _HAS_CHAR16_T_LANGUAGE_SUPPORT) // VS2010+
|
||||
# define EA_CHAR16_NATIVE 1
|
||||
# elif defined(__GNUC__) && ((__GNUC__ * 100 + __GNUC_MINOR__) >= 404) && (defined(__GXX_EXPERIMENTAL_CXX0X__) || defined(__STDC_VERSION__)) // g++ (C++ compiler) 4.4+ with -std=c++0x or gcc (C compiler) 4.4+ with -std=gnu99
|
||||
# define EA_CHAR16_NATIVE 1
|
||||
# else
|
||||
# define EA_CHAR16_NATIVE 0
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if !defined(EA_CHAR32_NATIVE)
|
||||
# if defined(_MSC_VER) && (_MSC_VER >= 1600) && defined(_HAS_CHAR16_T_LANGUAGE_SUPPORT) && _HAS_CHAR16_T_LANGUAGE_SUPPORT // VS2010+
|
||||
# define EA_CHAR32_NATIVE 1
|
||||
# elif defined(__GNUC__) && ((__GNUC__ * 100 + __GNUC_MINOR__) >= 404) && (defined(__GXX_EXPERIMENTAL_CXX0X__) || defined(__STDC_VERSION__)) // g++ (C++ compiler) 4.4+ with -std=c++0x or gcc (C compiler) 4.4+ with -std=gnu99
|
||||
# define EA_CHAR32_NATIVE 1
|
||||
# else
|
||||
# define EA_CHAR32_NATIVE 0
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef CHAR8_T_DEFINED // If the user hasn't already defined these...
|
||||
# define CHAR8_T_DEFINED
|
||||
|
||||
# if EA_CHAR16_NATIVE
|
||||
typedef char char8_t;
|
||||
|
||||
// In C++, char16_t and char32_t are already defined by the compiler.
|
||||
// In MS C, char16_t and char32_t are already defined by the compiler/standard library.
|
||||
// In GCC C, __CHAR16_TYPE__ and __CHAR32_TYPE__ are defined instead, and we must define char16_t and char32_t from these.
|
||||
# if defined(__GNUC__) && !defined(__GXX_EXPERIMENTAL_CXX0X__) && defined(__CHAR16_TYPE__) // If using GCC and compiling in C...
|
||||
typedef __CHAR16_TYPE__ char16_t;
|
||||
typedef __CHAR32_TYPE__ char32_t;
|
||||
# endif
|
||||
# elif defined(EA_COMPILER_HAS_CHAR_16_32)
|
||||
typedef char char8_t;
|
||||
# elif (EA_WCHAR_SIZE == 2)
|
||||
# define _CHAR16T
|
||||
typedef char char8_t;
|
||||
typedef wchar_t char16_t;
|
||||
typedef uint32_t char32_t;
|
||||
# else
|
||||
typedef char char8_t;
|
||||
typedef uint16_t char16_t;
|
||||
typedef wchar_t char32_t;
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
||||
// EA_CHAR16 / EA_CHAR32
|
||||
//
|
||||
// Supports usage of portable string constants.
|
||||
//
|
||||
// Example usage:
|
||||
// const char16_t* str = EA_CHAR16("Hello world");
|
||||
// const char32_t* str = EA_CHAR32("Hello world");
|
||||
// const char16_t c = EA_CHAR16('\x3001');
|
||||
// const char32_t c = EA_CHAR32('\x3001');
|
||||
//
|
||||
#ifndef EA_CHAR16
|
||||
# if EA_CHAR16_NATIVE && !defined(_MSC_VER) // Microsoft doesn't support char16_t string literals.
|
||||
# define EA_CHAR16(s) u ## s
|
||||
# elif (EA_WCHAR_SIZE == 2)
|
||||
# define EA_CHAR16(s) L ## s
|
||||
# else
|
||||
//#define EA_CHAR16(s) // Impossible to implement.
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef EA_CHAR32
|
||||
# if EA_CHAR32_NATIVE && !defined(_MSC_VER) // Microsoft doesn't support char32_t string literals.
|
||||
# define EA_CHAR32(s) U ## s
|
||||
# elif (EA_WCHAR_SIZE == 2)
|
||||
//#define EA_CHAR32(s) // Impossible to implement.
|
||||
# else
|
||||
# define EA_CHAR32(s) L ## s
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// EAArrayCount
|
||||
//
|
||||
// Returns the count of items in a built-in C array. This is a common technique
|
||||
// which is often used to help properly calculate the number of items in an
|
||||
// array at runtime in order to prevent overruns, etc.
|
||||
//
|
||||
// Example usage:
|
||||
// int array[75];
|
||||
// size_t arrayCount = EAArrayCount(array); // arrayCount is 75.
|
||||
//
|
||||
#ifndef EAArrayCount
|
||||
# define EAArrayCount(x) (sizeof(x) / sizeof(x[0]))
|
||||
#endif
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// static_assert
|
||||
//
|
||||
// C++0x static_assert (a.k.a. compile-time assert).
|
||||
//
|
||||
// Specification:
|
||||
// void static_assert(bool const_expression, const char* description);
|
||||
//
|
||||
// Example usage:
|
||||
// static_assert(sizeof(int) == 4, "int must be 32 bits");
|
||||
//
|
||||
#if !defined(EABASE_STATIC_ASSERT_ENABLED)
|
||||
# if defined(EA_DEBUG) || defined(_DEBUG)
|
||||
# define EABASE_STATIC_ASSERT_ENABLED 1
|
||||
# else
|
||||
# define EABASE_STATIC_ASSERT_ENABLED 0
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef EA_PREPROCESSOR_JOIN
|
||||
# define EA_PREPROCESSOR_JOIN(a, b) EA_PREPROCESSOR_JOIN1(a, b)
|
||||
# define EA_PREPROCESSOR_JOIN1(a, b) EA_PREPROCESSOR_JOIN2(a, b)
|
||||
# define EA_PREPROCESSOR_JOIN2(a, b) a##b
|
||||
#endif
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1600)
|
||||
// static_assert is defined by the compiler for both C and C++.
|
||||
#elif defined(__GNUC__) && defined(__GXX_EXPERIMENTAL_CXX0X__)
|
||||
// static_assert is defined by the compiler.
|
||||
#elif defined(__clang__) && __has_feature(cxx_static_assert)
|
||||
// static_assert is defined by the compiler.
|
||||
#else
|
||||
# if EABASE_STATIC_ASSERT_ENABLED
|
||||
# if defined(__COUNTER__) // If this VC++ extension is available...
|
||||
# define static_assert(expression, description) enum { EA_PREPROCESSOR_JOIN(static_assert_, __COUNTER__) = 1 / ((!!(expression)) ? 1 : 0) }
|
||||
# else
|
||||
# define static_assert(expression, description) enum { EA_PREPROCESSOR_JOIN(static_assert_, __LINE__) = 1 / ((!!(expression)) ? 1 : 0) }
|
||||
# endif
|
||||
# else
|
||||
# if defined(EA_COMPILER_METROWERKS)
|
||||
# if defined(__cplusplus)
|
||||
# define static_assert(expression, description) struct EA_PREPROCESSOR_JOIN(EACTAssertUnused_, __LINE__){ }
|
||||
# else
|
||||
# define static_assert(expression, description) enum { EA_PREPROCESSOR_JOIN(static_assert_, __LINE__) = 1 / ((!!(expression)) ? 1 : 0) }
|
||||
# endif
|
||||
# else
|
||||
# define static_assert(expression, description)
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
||||
#endif // Header include guard
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
78
lib/eastl/include/EABase/earesult.h
Normal file
78
lib/eastl/include/EABase/earesult.h
Normal file
|
@ -0,0 +1,78 @@
|
|||
/*
|
||||
Copyright (C) 2009 Electronic Arts, Inc. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
3. Neither the name of Electronic Arts, Inc. ("EA") nor the names of
|
||||
its contributors may be used to endorse or promote products derived
|
||||
from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY ELECTRONIC ARTS AND ITS CONTRIBUTORS "AS IS" AND ANY
|
||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL ELECTRONIC ARTS OR ITS CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*-----------------------------------------------------------------------------
|
||||
* earesult.h
|
||||
*
|
||||
* Copyright (c) 2002 - 2005 Electronic Arts Inc. All rights reserved.
|
||||
* Maintained by Paul Pedriana, Maxis
|
||||
*---------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
#ifndef INCLUDED_earesult_H
|
||||
#define INCLUDED_earesult_H
|
||||
|
||||
|
||||
#ifndef INCLUDED_eabase_H
|
||||
#include "EABase/eabase.h"
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/// \brief This result type is width-compatible with most systems
|
||||
typedef int32_t ea_result_type;
|
||||
|
||||
|
||||
namespace EA
|
||||
{
|
||||
typedef int32_t result_type;
|
||||
|
||||
enum
|
||||
{
|
||||
SUCCESS = 0,
|
||||
FAILURE = -1
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
/// \brief Macro to simplify testing for success
|
||||
#ifndef EA_SUCCEEDED
|
||||
#define EA_SUCCEEDED(result) ((result) >= 0)
|
||||
#endif
|
||||
|
||||
/// \brief Macro to simplfify testing for general failure
|
||||
#ifndef EA_FAILED
|
||||
#define EA_FAILED(result) ((result) < 0)
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
2979
lib/eastl/include/EASTL/algorithm.h
Normal file
2979
lib/eastl/include/EASTL/algorithm.h
Normal file
File diff suppressed because it is too large
Load diff
344
lib/eastl/include/EASTL/allocator.h
Normal file
344
lib/eastl/include/EASTL/allocator.h
Normal file
|
@ -0,0 +1,344 @@
|
|||
/*
|
||||
Copyright (C) 2009-2010 Electronic Arts, Inc. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
3. Neither the name of Electronic Arts, Inc. ("EA") nor the names of
|
||||
its contributors may be used to endorse or promote products derived
|
||||
from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY ELECTRONIC ARTS AND ITS CONTRIBUTORS "AS IS" AND ANY
|
||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL ELECTRONIC ARTS OR ITS CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// EASTL/allocator.h
|
||||
//
|
||||
// Copyright (c) 2005, Electronic Arts. All rights reserved.
|
||||
// Written and maintained by Paul Pedriana.
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
#ifndef EASTL_ALLOCATOR_H
|
||||
#define EASTL_ALLOCATOR_H
|
||||
|
||||
|
||||
#include <EASTL/internal/config.h>
|
||||
#include <stddef.h>
|
||||
|
||||
|
||||
#ifdef _MSC_VER
|
||||
# pragma warning(push)
|
||||
# pragma warning(disable: 4189) // local variable is initialized but not referenced
|
||||
#endif
|
||||
|
||||
|
||||
namespace eastl
|
||||
{
|
||||
|
||||
/// EASTL_ALLOCATOR_DEFAULT_NAME
|
||||
///
|
||||
/// Defines a default allocator name in the absence of a user-provided name.
|
||||
///
|
||||
#ifndef EASTL_ALLOCATOR_DEFAULT_NAME
|
||||
# define EASTL_ALLOCATOR_DEFAULT_NAME EASTL_DEFAULT_NAME_PREFIX // Unless the user overrides something, this is "EASTL".
|
||||
#endif
|
||||
|
||||
|
||||
/// alloc_flags
|
||||
///
|
||||
/// Defines allocation flags.
|
||||
///
|
||||
enum alloc_flags
|
||||
{
|
||||
MEM_TEMP = 0, // Low memory, not necessarily actually temporary.
|
||||
MEM_PERM = 1 // High memory, for things that won't be unloaded.
|
||||
};
|
||||
|
||||
|
||||
/// allocator
|
||||
///
|
||||
/// In this allocator class, note that it is not templated on any type and
|
||||
/// instead it simply allocates blocks of memory much like the C malloc and
|
||||
/// free functions. It can be thought of as similar to C++ std::allocator<char>.
|
||||
/// The flags parameter has meaning that is specific to the allocation
|
||||
///
|
||||
class EASTL_API allocator
|
||||
{
|
||||
public:
|
||||
typedef eastl_size_t size_type;
|
||||
|
||||
EASTL_ALLOCATOR_EXPLICIT allocator(const char* pName = EASTL_NAME_VAL(EASTL_ALLOCATOR_DEFAULT_NAME));
|
||||
allocator(const allocator& x);
|
||||
allocator(const allocator& x, const char* pName);
|
||||
|
||||
allocator& operator=(const allocator& x);
|
||||
|
||||
void* allocate(size_t n, int flags = 0);
|
||||
void* allocate(size_t n, size_t alignment, size_t offset, int flags = 0);
|
||||
void deallocate(void* p, size_t n);
|
||||
|
||||
const char* get_name() const;
|
||||
void set_name(const char* pName);
|
||||
|
||||
protected:
|
||||
#if EASTL_NAME_ENABLED
|
||||
const char* mpName; // Debug name, used to track memory.
|
||||
#endif
|
||||
};
|
||||
|
||||
bool operator==(const allocator& a, const allocator& b);
|
||||
bool operator!=(const allocator& a, const allocator& b);
|
||||
|
||||
EASTL_API allocator* GetDefaultAllocator();
|
||||
EASTL_API allocator* SetDefaultAllocator(allocator* pAllocator);
|
||||
|
||||
|
||||
|
||||
/// get_default_allocator
|
||||
///
|
||||
/// This templated function allows the user to implement a default allocator
|
||||
/// retrieval function that any part of EASTL can use. EASTL containers take
|
||||
/// an Allocator parameter which identifies an Allocator class to use. But
|
||||
/// different kinds of allocators have different mechanisms for retrieving
|
||||
/// a default allocator instance, and some don't even intrinsically support
|
||||
/// such functionality. The user can override this get_default_allocator
|
||||
/// function in order to provide the glue between EASTL and whatever their
|
||||
/// system's default allocator happens to be.
|
||||
///
|
||||
/// Example usage:
|
||||
/// MyAllocatorType* gpSystemAllocator;
|
||||
///
|
||||
/// MyAllocatorType* get_default_allocator(const MyAllocatorType*)
|
||||
/// { return gpSystemAllocator; }
|
||||
///
|
||||
template <typename Allocator>
|
||||
inline Allocator* get_default_allocator(const Allocator*)
|
||||
{
|
||||
return NULL; // By default we return NULL; the user must make specialization of this function in order to provide their own implementation.
|
||||
}
|
||||
|
||||
inline EASTLAllocatorType* get_default_allocator(const EASTLAllocatorType*)
|
||||
{
|
||||
return EASTLAllocatorDefault(); // For the built-in allocator EASTLAllocatorType, we happen to already have a function for returning the default allocator instance, so we provide it.
|
||||
}
|
||||
|
||||
|
||||
/// default_allocfreemethod
|
||||
///
|
||||
/// Implements a default allocfreemethod which uses the default global allocator.
|
||||
/// This version supports only default alignment.
|
||||
///
|
||||
inline void* default_allocfreemethod(size_t n, void* pBuffer, void* /*pContext*/)
|
||||
{
|
||||
EASTLAllocatorType* const pAllocator = EASTLAllocatorDefault();
|
||||
|
||||
if(pBuffer) // If freeing...
|
||||
{
|
||||
EASTLFree(*pAllocator, pBuffer, n);
|
||||
return NULL; // The return value is meaningless for the free.
|
||||
}
|
||||
else // allocating
|
||||
return EASTLAlloc(*pAllocator, n);
|
||||
}
|
||||
|
||||
|
||||
/// allocate_memory
|
||||
///
|
||||
/// This is a memory allocation dispatching function.
|
||||
/// To do: Make aligned and unaligned specializations.
|
||||
/// Note that to do this we will need to use a class with a static
|
||||
/// function instead of a standalone function like below.
|
||||
///
|
||||
template <typename Allocator>
|
||||
void* allocate_memory(Allocator& a, size_t n, size_t alignment, size_t alignmentOffset)
|
||||
{
|
||||
if(alignment <= 8)
|
||||
return EASTLAlloc(a, n);
|
||||
return EASTLAllocAligned(a, n, alignment, alignmentOffset);
|
||||
}
|
||||
|
||||
} // namespace eastl
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#ifndef EASTL_USER_DEFINED_ALLOCATOR // If the user hasn't declared that he has defined a different allocator implementation elsewhere...
|
||||
|
||||
# ifdef _MSC_VER
|
||||
# pragma warning(push, 0)
|
||||
# include <new>
|
||||
# pragma warning(pop)
|
||||
# else
|
||||
# include <new>
|
||||
# endif
|
||||
|
||||
# if !EASTL_DLL // If building a regular library and not building EASTL as a DLL...
|
||||
// It is expected that the application define the following
|
||||
// versions of operator new for the application. Either that or the
|
||||
// user needs to override the implementation of the allocator class.
|
||||
void* operator new[](size_t size, const char* pName, int flags, unsigned debugFlags, const char* file, int line);
|
||||
void* operator new[](size_t size, size_t alignment, size_t alignmentOffset, const char* pName, int flags, unsigned debugFlags, const char* file, int line);
|
||||
# endif
|
||||
|
||||
namespace eastl
|
||||
{
|
||||
inline allocator::allocator(const char* EASTL_NAME(pName))
|
||||
{
|
||||
# if EASTL_NAME_ENABLED
|
||||
mpName = pName ? pName : EASTL_ALLOCATOR_DEFAULT_NAME;
|
||||
# endif
|
||||
}
|
||||
|
||||
|
||||
inline allocator::allocator(const allocator& EASTL_NAME(alloc))
|
||||
{
|
||||
# if EASTL_NAME_ENABLED
|
||||
mpName = alloc.mpName;
|
||||
# endif
|
||||
}
|
||||
|
||||
|
||||
inline allocator::allocator(const allocator&, const char* EASTL_NAME(pName))
|
||||
{
|
||||
# if EASTL_NAME_ENABLED
|
||||
mpName = pName ? pName : EASTL_ALLOCATOR_DEFAULT_NAME;
|
||||
# endif
|
||||
}
|
||||
|
||||
|
||||
inline allocator& allocator::operator=(const allocator& EASTL_NAME(alloc))
|
||||
{
|
||||
# if EASTL_NAME_ENABLED
|
||||
mpName = alloc.mpName;
|
||||
# endif
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
inline const char* allocator::get_name() const
|
||||
{
|
||||
# if EASTL_NAME_ENABLED
|
||||
return mpName;
|
||||
# else
|
||||
return EASTL_ALLOCATOR_DEFAULT_NAME;
|
||||
# endif
|
||||
}
|
||||
|
||||
|
||||
inline void allocator::set_name(const char* EASTL_NAME(pName))
|
||||
{
|
||||
# if EASTL_NAME_ENABLED
|
||||
mpName = pName;
|
||||
# endif
|
||||
}
|
||||
|
||||
|
||||
inline void* allocator::allocate(size_t n, int flags)
|
||||
{
|
||||
# if EASTL_NAME_ENABLED
|
||||
# define pName mpName
|
||||
# else
|
||||
# define pName EASTL_ALLOCATOR_DEFAULT_NAME
|
||||
# endif
|
||||
|
||||
# if EASTL_DLL
|
||||
// We currently have no support for implementing flags when
|
||||
// using the C runtime library operator new function. The user
|
||||
// can use SetDefaultAllocator to override the default allocator.
|
||||
(void)flags;
|
||||
return ::new char[n];
|
||||
# elif (EASTL_DEBUGPARAMS_LEVEL <= 0)
|
||||
return ::new((char*)0, flags, 0, (char*)0, 0) char[n];
|
||||
# elif (EASTL_DEBUGPARAMS_LEVEL == 1)
|
||||
return ::new( pName, flags, 0, (char*)0, 0) char[n];
|
||||
# else
|
||||
return ::new( pName, flags, 0, __FILE__, __LINE__) char[n];
|
||||
# endif
|
||||
}
|
||||
|
||||
|
||||
inline void* allocator::allocate(size_t n, size_t alignment, size_t offset, int flags)
|
||||
{
|
||||
# if EASTL_DLL
|
||||
// We have a problem here. We cannot support alignment, as we don't have access
|
||||
// to a memory allocator that can provide aligned memory. The C++ standard doesn't
|
||||
// recognize such a thing. The user will need to call SetDefaultAllocator to
|
||||
// provide an alloator which supports alignment.
|
||||
EASTL_ASSERT(alignment <= 8); // 8 (sizeof(double)) is the standard alignment returned by operator new.
|
||||
(void)alignment; (void)offset; (void)flags;
|
||||
return new char[n];
|
||||
# elif (EASTL_DEBUGPARAMS_LEVEL <= 0)
|
||||
return ::new(alignment, offset, (char*)0, flags, 0, (char*)0, 0) char[n];
|
||||
# elif (EASTL_DEBUGPARAMS_LEVEL == 1)
|
||||
return ::new(alignment, offset, pName, flags, 0, (char*)0, 0) char[n];
|
||||
# else
|
||||
return ::new(alignment, offset, pName, flags, 0, __FILE__, __LINE__) char[n];
|
||||
# endif
|
||||
|
||||
# undef pName // See above for the definition of this.
|
||||
}
|
||||
|
||||
|
||||
inline void allocator::deallocate(void* p, size_t)
|
||||
{
|
||||
delete[] (char*)p;
|
||||
}
|
||||
|
||||
|
||||
inline bool operator==(const allocator&, const allocator&)
|
||||
{
|
||||
return true; // All allocators are considered equal, as they merely use global new/delete.
|
||||
}
|
||||
|
||||
|
||||
inline bool operator!=(const allocator&, const allocator&)
|
||||
{
|
||||
return false; // All allocators are considered equal, as they merely use global new/delete.
|
||||
}
|
||||
|
||||
|
||||
} // namespace eastl
|
||||
|
||||
|
||||
#endif // EASTL_USER_DEFINED_ALLOCATOR
|
||||
|
||||
|
||||
#ifdef _MSC_VER
|
||||
# pragma warning(pop)
|
||||
#endif
|
||||
|
||||
|
||||
#endif // Header include guard
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
1777
lib/eastl/include/EASTL/bitset.h
Normal file
1777
lib/eastl/include/EASTL/bitset.h
Normal file
File diff suppressed because it is too large
Load diff
482
lib/eastl/include/EASTL/bonus/sort_extra.h
Normal file
482
lib/eastl/include/EASTL/bonus/sort_extra.h
Normal file
|
@ -0,0 +1,482 @@
|
|||
/*
|
||||
Copyright (C) 2005,2009-2010 Electronic Arts, Inc. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
3. Neither the name of Electronic Arts, Inc. ("EA") nor the names of
|
||||
its contributors may be used to endorse or promote products derived
|
||||
from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY ELECTRONIC ARTS AND ITS CONTRIBUTORS "AS IS" AND ANY
|
||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL ELECTRONIC ARTS OR ITS CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// EASTL/sort_extra.h
|
||||
// Written by Paul Pedriana - 2005
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// This file implements additional sort algorithms beyond the basic set.
|
||||
// Included here are:
|
||||
// radix_sort
|
||||
// comb_sort
|
||||
// bubble_sort
|
||||
// selection_sort
|
||||
// shaker_sort
|
||||
// bucket_sort
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef EASTL_SORT_EXTRA_H
|
||||
#define EASTL_SORT_EXTRA_H
|
||||
|
||||
#include <EASTL/internal/config.h>
|
||||
#include <EASTL/iterator.h>
|
||||
#include <EASTL/algorithm.h>
|
||||
#include <EASTL/functional.h>
|
||||
#include <EASTL/heap.h>
|
||||
#include <EASTL/allocator.h>
|
||||
|
||||
namespace eastl
|
||||
{
|
||||
|
||||
/// extract_radix_key
|
||||
///
|
||||
/// Default radix sort integer value reader. It expects the sorted elements
|
||||
/// to have an integer member of type radix_type and of name "mKey".
|
||||
///
|
||||
template <typename Node>
|
||||
struct extract_radix_key
|
||||
{
|
||||
typedef typename Node::radix_type radix_type;
|
||||
|
||||
const radix_type operator()(const Node& x) const
|
||||
{ return x.mKey; }
|
||||
};
|
||||
|
||||
|
||||
/// radix_sort
|
||||
///
|
||||
/// Implements a classic LSD (least significant digit) radix sort.
|
||||
/// See http://en.wikipedia.org/wiki/Radix_sort.
|
||||
/// To consider: A static linked-list implementation may be faster than the version here.
|
||||
///
|
||||
/// Example usage:
|
||||
/// struct Element {
|
||||
/// typedef uint16_t radix_type;
|
||||
/// uint16_t mKey;
|
||||
/// uint16_t mData;
|
||||
/// };
|
||||
///
|
||||
/// Element elementArray[100];
|
||||
/// Element buffer[100];
|
||||
///
|
||||
/// radix_sort<Element*, extract_radix_key<Element> >(elementArray, elementArray + 100, buffer);
|
||||
///
|
||||
template <typename RandomAccessIterator, typename ExtractKey>
|
||||
void radix_sort_impl(RandomAccessIterator first, RandomAccessIterator last, RandomAccessIterator buffer, ExtractKey extractKey, uint8_t)
|
||||
{
|
||||
uint32_t EA_PREFIX_ALIGN(16) bucketSize[256] EA_POSTFIX_ALIGN(16);
|
||||
uint32_t EA_PREFIX_ALIGN(16) bucketPosition[256] EA_POSTFIX_ALIGN(16);
|
||||
RandomAccessIterator temp;
|
||||
uint32_t i;
|
||||
|
||||
memset(bucketSize, 0, sizeof(bucketSize));
|
||||
|
||||
for(temp = first; temp != last; ++temp)
|
||||
++bucketSize[extractKey(*temp)];
|
||||
|
||||
for(bucketPosition[0] = 0, i = 0; i < 255; i++)
|
||||
bucketPosition[i + 1] = bucketPosition[i] + bucketSize[i];
|
||||
|
||||
for(temp = first; temp != last; ++temp)
|
||||
{
|
||||
const size_t radixByte = extractKey(*temp);
|
||||
buffer[bucketPosition[radixByte]++] = *temp;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template <typename RandomAccessIterator, typename ExtractKey>
|
||||
void radix_sort_impl(RandomAccessIterator first, RandomAccessIterator last, RandomAccessIterator buffer, ExtractKey extractKey, uint16_t)
|
||||
{
|
||||
uint32_t EA_PREFIX_ALIGN(16) bucketSize[256] EA_POSTFIX_ALIGN(16);
|
||||
uint32_t EA_PREFIX_ALIGN(16) bucketPosition[256] EA_POSTFIX_ALIGN(16);
|
||||
RandomAccessIterator temp;
|
||||
uint32_t i;
|
||||
|
||||
// Process byte 0 (least significant byte).
|
||||
memset(bucketSize, 0, sizeof(bucketSize));
|
||||
|
||||
for(temp = first; temp != last; ++temp)
|
||||
++bucketSize[extractKey(*temp) & 0xff];
|
||||
|
||||
for(bucketPosition[0] = 0, i = 0; i < 255; i++)
|
||||
bucketPosition[i + 1] = bucketPosition[i] + bucketSize[i];
|
||||
|
||||
for(temp = first; temp != last; ++temp)
|
||||
{
|
||||
const size_t radixByte = extractKey(*temp) & 0xff;
|
||||
buffer[bucketPosition[radixByte]++] = *temp;
|
||||
}
|
||||
|
||||
|
||||
// Process byte 1 (second least significant byte).
|
||||
memset(bucketSize, 0, sizeof(bucketSize));
|
||||
|
||||
for(temp = buffer, last = buffer + (last - first); temp != last; ++temp)
|
||||
++bucketSize[extractKey(*temp) >> 8];
|
||||
|
||||
for(bucketPosition[0] = 0, i = 0; i < 255; i++)
|
||||
bucketPosition[i + 1] = bucketPosition[i] + bucketSize[i];
|
||||
|
||||
for(temp = buffer; temp != last; ++temp)
|
||||
{
|
||||
const size_t radixByte = extractKey(*temp) >> 8;
|
||||
first[bucketPosition[radixByte]++] = *temp;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template <typename RandomAccessIterator, typename ExtractKey, typename IntegerType>
|
||||
void radix_sort_impl(RandomAccessIterator first, RandomAccessIterator last, RandomAccessIterator buffer, ExtractKey extractKey, IntegerType)
|
||||
{
|
||||
uint32_t EA_PREFIX_ALIGN(16) bucketSize[256] EA_POSTFIX_ALIGN(16);
|
||||
uint32_t EA_PREFIX_ALIGN(16) bucketPosition[256] EA_POSTFIX_ALIGN(16);
|
||||
RandomAccessIterator temp;
|
||||
uint32_t i;
|
||||
|
||||
for(uint32_t j = 0; j < (8 * sizeof(IntegerType)); j += 8)
|
||||
{
|
||||
memset(bucketSize, 0, sizeof(bucketSize));
|
||||
|
||||
for(temp = first; temp != last; ++temp)
|
||||
++bucketSize[(extractKey(*temp) >> j) & 0xff];
|
||||
|
||||
bucketPosition[0] = 0;
|
||||
for(i = 0; i < 255; i++)
|
||||
bucketPosition[i + 1] = bucketPosition[i] + bucketSize[i];
|
||||
|
||||
for(temp = first; temp != last; ++temp)
|
||||
{
|
||||
const size_t radixByte = ((extractKey(*temp) >> j) & 0xff);
|
||||
buffer[bucketPosition[radixByte]++] = *temp;
|
||||
}
|
||||
|
||||
last = buffer + (last - first);
|
||||
temp = first;
|
||||
first = buffer;
|
||||
buffer = temp;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template <typename RandomAccessIterator, typename ExtractKey>
|
||||
void radix_sort(RandomAccessIterator first, RandomAccessIterator last, RandomAccessIterator buffer)
|
||||
{
|
||||
radix_sort_impl<RandomAccessIterator>(first, last, buffer, ExtractKey(), typename ExtractKey::radix_type());
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// comb_sort
|
||||
///
|
||||
/// Implements the CombSort algorithm; in particular, implements the CombSort11 variation
|
||||
/// of the CombSort algorithm, based on the reference to '11' in the implementation.
|
||||
///
|
||||
/// To consider: Use a comb sort table instead of the '((nSpace * 10) + 3) / 13' expression.
|
||||
/// Ideal tables can be found on the Internet by looking up "comb sort table".
|
||||
///
|
||||
template <typename ForwardIterator, typename StrictWeakOrdering>
|
||||
void comb_sort(ForwardIterator first, ForwardIterator last, StrictWeakOrdering compare)
|
||||
{
|
||||
typedef typename eastl::iterator_traits<ForwardIterator>::difference_type difference_type;
|
||||
|
||||
ForwardIterator iCurrent, iNext;
|
||||
difference_type length = eastl::distance(first, last);
|
||||
difference_type nSpace = length;
|
||||
|
||||
for(bool bSwapped = false; (nSpace > 1) || bSwapped; )
|
||||
{
|
||||
nSpace = ((nSpace * 10) + 3) / 13; // Integer division is less than ideal.
|
||||
|
||||
if((nSpace == 9) || (nSpace == 10))
|
||||
nSpace = 11;
|
||||
|
||||
iCurrent = iNext = first;
|
||||
eastl::advance(iNext, nSpace);
|
||||
|
||||
for(bSwapped = false; iNext != last; iCurrent++, iNext++)
|
||||
{
|
||||
if(compare(*iNext, *iCurrent))
|
||||
{
|
||||
EASTL_VALIDATE_COMPARE(!compare(*iCurrent, *iNext)); // Validate that the compare function is sane.
|
||||
eastl::iter_swap(iCurrent, iNext);
|
||||
bSwapped = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
} // comb_sort
|
||||
|
||||
template <typename ForwardIterator>
|
||||
inline void comb_sort(ForwardIterator first, ForwardIterator last)
|
||||
{
|
||||
typedef eastl::less<typename eastl::iterator_traits<ForwardIterator>::value_type> Less;
|
||||
|
||||
eastl::comb_sort<ForwardIterator, Less>(first, last, Less());
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/// bubble_sort
|
||||
///
|
||||
/// Implements the BubbleSort algorithm. This algorithm is only useful for
|
||||
/// small range sizes, such as 10 or less items. You may be better off using
|
||||
/// insertion_sort for cases where bubble_sort works.
|
||||
///
|
||||
template <typename ForwardIterator, typename StrictWeakOrdering>
|
||||
void bubble_sort_impl(ForwardIterator first, ForwardIterator last, StrictWeakOrdering compare, EASTL_ITC_NS::forward_iterator_tag)
|
||||
{
|
||||
ForwardIterator iCurrent, iNext;
|
||||
|
||||
while(first != last)
|
||||
{
|
||||
iNext = iCurrent = first;
|
||||
|
||||
for(++iNext; iNext != last; iCurrent = iNext, ++iNext)
|
||||
{
|
||||
if(compare(*iNext, *iCurrent))
|
||||
{
|
||||
EASTL_VALIDATE_COMPARE(!compare(*iCurrent, *iNext)); // Validate that the compare function is sane.
|
||||
eastl::iter_swap(iCurrent, iNext);
|
||||
}
|
||||
}
|
||||
last = iCurrent;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename BidirectionalIterator, typename StrictWeakOrdering>
|
||||
void bubble_sort_impl(BidirectionalIterator first, BidirectionalIterator last, StrictWeakOrdering compare, EASTL_ITC_NS::bidirectional_iterator_tag)
|
||||
{
|
||||
if(first != last)
|
||||
{
|
||||
BidirectionalIterator iCurrent, iNext, iLastModified;
|
||||
|
||||
last--;
|
||||
|
||||
while(first != last)
|
||||
{
|
||||
iLastModified = iNext = iCurrent = first;
|
||||
|
||||
for(++iNext; iCurrent != last; iCurrent = iNext, ++iNext)
|
||||
{
|
||||
if(compare(*iNext, *iCurrent))
|
||||
{
|
||||
EASTL_VALIDATE_COMPARE(!compare(*iCurrent, *iNext)); // Validate that the compare function is sane.
|
||||
iLastModified = iCurrent;
|
||||
eastl::iter_swap(iCurrent, iNext);
|
||||
}
|
||||
}
|
||||
|
||||
last = iLastModified;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename ForwardIterator, typename StrictWeakOrdering>
|
||||
inline void bubble_sort(ForwardIterator first, ForwardIterator last, StrictWeakOrdering compare)
|
||||
{
|
||||
typedef typename eastl::iterator_traits<ForwardIterator>::iterator_category IC;
|
||||
|
||||
eastl::bubble_sort_impl<ForwardIterator, StrictWeakOrdering>(first, last, compare, IC());
|
||||
}
|
||||
|
||||
template <typename ForwardIterator>
|
||||
inline void bubble_sort(ForwardIterator first, ForwardIterator last)
|
||||
{
|
||||
typedef eastl::less<typename eastl::iterator_traits<ForwardIterator>::value_type> Less;
|
||||
typedef typename eastl::iterator_traits<ForwardIterator>::iterator_category IC;
|
||||
|
||||
eastl::bubble_sort_impl<ForwardIterator, Less>(first, last, Less(), IC());
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// selection_sort
|
||||
///
|
||||
/// Implements the SelectionSort algorithm.
|
||||
///
|
||||
template <typename ForwardIterator, typename StrictWeakOrdering>
|
||||
void selection_sort(ForwardIterator first, ForwardIterator last, StrictWeakOrdering compare)
|
||||
{
|
||||
if(first != last)
|
||||
{
|
||||
ForwardIterator iCurrent, iMin;
|
||||
|
||||
for(; first != last; ++first)
|
||||
{
|
||||
iCurrent = first;
|
||||
iMin = iCurrent;
|
||||
|
||||
for(++iCurrent; iCurrent != last; ++iCurrent)
|
||||
{
|
||||
if(compare(*iCurrent, *iMin))
|
||||
{
|
||||
EASTL_VALIDATE_COMPARE(!compare(*iMin, *iCurrent)); // Validate that the compare function is sane.
|
||||
iMin = iCurrent;
|
||||
}
|
||||
}
|
||||
|
||||
if(first != iMin)
|
||||
eastl::iter_swap(first, iMin);
|
||||
}
|
||||
}
|
||||
} // selection_sort
|
||||
|
||||
template <typename ForwardIterator>
|
||||
inline void selection_sort(ForwardIterator first, ForwardIterator last)
|
||||
{
|
||||
typedef eastl::less<typename eastl::iterator_traits<ForwardIterator>::value_type> Less;
|
||||
|
||||
eastl::selection_sort<ForwardIterator, Less>(first, last, Less());
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// shaker_sort
|
||||
///
|
||||
/// Implements the ShakerSort algorithm, which is a sorting algorithm which
|
||||
/// improves on bubble_sort by sweeping both from left to right and right
|
||||
/// to left, resulting in less iteration.
|
||||
///
|
||||
template <typename BidirectionalIterator, typename StrictWeakOrdering>
|
||||
void shaker_sort(BidirectionalIterator first, BidirectionalIterator last, StrictWeakOrdering compare)
|
||||
{
|
||||
if(first != last)
|
||||
{
|
||||
BidirectionalIterator iCurrent, iNext, iLastModified;
|
||||
|
||||
--last;
|
||||
|
||||
while(first != last)
|
||||
{
|
||||
iLastModified = first;
|
||||
|
||||
for(iCurrent = first; iCurrent != last; iCurrent = iNext)
|
||||
{
|
||||
iNext = iCurrent;
|
||||
++iNext;
|
||||
|
||||
if(compare(*iNext, *iCurrent))
|
||||
{
|
||||
EASTL_VALIDATE_COMPARE(!compare(*iCurrent, *iNext)); // Validate that the compare function is sane.
|
||||
iLastModified = iCurrent;
|
||||
eastl::iter_swap(iCurrent, iNext);
|
||||
}
|
||||
}
|
||||
|
||||
last = iLastModified;
|
||||
|
||||
if(first != last)
|
||||
{
|
||||
for(iCurrent = last; iCurrent != first; iCurrent = iNext)
|
||||
{
|
||||
iNext = iCurrent;
|
||||
--iNext;
|
||||
|
||||
if(compare(*iCurrent, *iNext))
|
||||
{
|
||||
EASTL_VALIDATE_COMPARE(!compare(*iNext, *iCurrent)); // Validate that the compare function is sane.
|
||||
iLastModified = iCurrent;
|
||||
eastl::iter_swap(iNext, iCurrent);
|
||||
}
|
||||
}
|
||||
first = iLastModified;
|
||||
}
|
||||
}
|
||||
}
|
||||
} // shaker_sort
|
||||
|
||||
template <typename BidirectionalIterator>
|
||||
inline void shaker_sort(BidirectionalIterator first, BidirectionalIterator last)
|
||||
{
|
||||
typedef eastl::less<typename eastl::iterator_traits<BidirectionalIterator>::value_type> Less;
|
||||
|
||||
eastl::shaker_sort<BidirectionalIterator, Less>(first, last, Less());
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// bucket_sort
|
||||
///
|
||||
/// Implements the BucketSort algorithm.
|
||||
///
|
||||
/// Example usage:
|
||||
/// int* pArray = new int[1000];
|
||||
/// for(int i = 0; i < 1000; i++)
|
||||
/// pArray[i] = rand() % 32; // Note: The C rand function is a poor random number generator.
|
||||
/// vector<int> intVector[32];
|
||||
/// bucket_sort(pArray, pArray + 1000; intVector);
|
||||
/// delete[] pArray;
|
||||
///
|
||||
template <typename T>
|
||||
struct hash_use_self
|
||||
{
|
||||
T operator()(const T& x) const
|
||||
{ return x; }
|
||||
};
|
||||
|
||||
template <typename ForwardIterator, typename ContainerArray, typename HashFunction>
|
||||
void bucket_sort(ForwardIterator first, ForwardIterator last, ContainerArray& bucketArray, HashFunction hash /*= hash_use_self*/)
|
||||
{
|
||||
typedef typename eastl::iterator_traits<ForwardIterator>::difference_type difference_type;
|
||||
|
||||
for(ForwardIterator iInput = first; iInput != last; ++iInput)
|
||||
bucketArray[hash(*iInput)].push_back(*iInput);
|
||||
|
||||
for(typename ContainerArray::const_iterator iBucket = bucketArray.begin(); iBucket != bucketArray.end(); ++iBucket)
|
||||
first = eastl::copy((*iBucket).begin(), (*iBucket).end(), first);
|
||||
}
|
||||
|
||||
|
||||
|
||||
} // namespace eastl
|
||||
|
||||
|
||||
#endif // Header include guard
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
296
lib/eastl/include/EASTL/core_allocator_adapter.h
Normal file
296
lib/eastl/include/EASTL/core_allocator_adapter.h
Normal file
|
@ -0,0 +1,296 @@
|
|||
/*
|
||||
Copyright (C) 2009-2010 Electronic Arts, Inc. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
3. Neither the name of Electronic Arts, Inc. ("EA") nor the names of
|
||||
its contributors may be used to endorse or promote products derived
|
||||
from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY ELECTRONIC ARTS AND ITS CONTRIBUTORS "AS IS" AND ANY
|
||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL ELECTRONIC ARTS OR ITS CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// core_allocator_adapter.h
|
||||
//
|
||||
// Copyright (c) 2007, Electronic Arts. All rights reserved.
|
||||
// Maintained by Paul Pedriana
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Implements an EASTL allocator that uses an ICoreAllocator.
|
||||
// However, this header file is not dependent on ICoreAllocator or its package.
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
#ifndef EASTL_CORE_ALLOCATOR_ADAPTER_H
|
||||
#define EASTL_CORE_ALLOCATOR_ADAPTER_H
|
||||
|
||||
|
||||
#include <EASTL/allocator.h>
|
||||
|
||||
|
||||
namespace EA
|
||||
{
|
||||
namespace Allocator
|
||||
{
|
||||
/// CoreAllocatorAdapter
|
||||
///
|
||||
/// Implements the EASTL allocator interface.
|
||||
/// Allocates memory from an instance of ICoreAllocator.
|
||||
///
|
||||
/// Example usage:
|
||||
/// eastl::list<Widget, CoreAllocatorAdapter<ICoreAllocator> > widgetList("UI/WidgetList", pSomeCoreAllocator);
|
||||
/// widgetList.push_back(Widget());
|
||||
///
|
||||
/// Example usage:
|
||||
/// // Note that the CoreAllocator is declared before and thus destroyed after the widget list.
|
||||
/// typedef CoreAllocatorAdapter<ICoreAllocator> EASTLCoreAllocator;
|
||||
/// typedef eastl::list<Widget, EASTLCoreAllocator> WidgetList;
|
||||
/// CoreAllocatorFixed<WidgetList::node_type> widgetCoreAllocator(pFixedAllocatorForWidgetListValueType);
|
||||
/// WidgetList widgetList(EASTLCoreAllocator("UI/WidgetList", &widgetCoreAllocator));
|
||||
///
|
||||
template<class AllocatorType>
|
||||
class CoreAllocatorAdapter
|
||||
{
|
||||
public:
|
||||
typedef CoreAllocatorAdapter<AllocatorType> this_type;
|
||||
|
||||
public:
|
||||
CoreAllocatorAdapter(const char* pName = EASTL_NAME_VAL(EASTL_ALLOCATOR_DEFAULT_NAME));
|
||||
CoreAllocatorAdapter(const char* pName, AllocatorType* pAllocator);
|
||||
CoreAllocatorAdapter(const char* pName, AllocatorType* pAllocator, int flags);
|
||||
CoreAllocatorAdapter(const CoreAllocatorAdapter& x);
|
||||
CoreAllocatorAdapter(const CoreAllocatorAdapter& x, const char* pName);
|
||||
|
||||
CoreAllocatorAdapter& operator=(const CoreAllocatorAdapter& x);
|
||||
|
||||
void* allocate(size_t n, int flags = 0);
|
||||
void* allocate(size_t n, size_t alignment, size_t offset, int flags = 0);
|
||||
void deallocate(void* p, size_t n);
|
||||
|
||||
AllocatorType* get_allocator() const;
|
||||
void set_allocator(AllocatorType* pAllocator);
|
||||
|
||||
int get_flags() const;
|
||||
void set_flags(int flags);
|
||||
|
||||
const char* get_name() const;
|
||||
void set_name(const char* pName);
|
||||
|
||||
public: // Public because otherwise VC++ generates (possibly invalid) warnings about inline friend template specializations.
|
||||
AllocatorType* mpCoreAllocator;
|
||||
int mnFlags; // Allocation flags. See ICoreAllocator/AllocFlags.
|
||||
|
||||
#if EASTL_NAME_ENABLED
|
||||
const char* mpName; // Debug name, used to track memory.
|
||||
#endif
|
||||
};
|
||||
|
||||
template<class AllocatorType>
|
||||
bool operator==(const CoreAllocatorAdapter<AllocatorType>& a, const CoreAllocatorAdapter<AllocatorType>& b);
|
||||
|
||||
template<class AllocatorType>
|
||||
bool operator!=(const CoreAllocatorAdapter<AllocatorType>& a, const CoreAllocatorAdapter<AllocatorType>& b);
|
||||
|
||||
|
||||
|
||||
/// EASTLICoreAllocator
|
||||
///
|
||||
/// Provides a standardized typedef for ICoreAllocator;
|
||||
///
|
||||
/// Example usage:
|
||||
/// eastl::list<Widget, EASTLICoreAllocator> widgetList("UI/WidgetList", pSomeCoreAllocator);
|
||||
/// widgetList.push_back(Widget());
|
||||
///
|
||||
class ICoreAllocator;
|
||||
typedef CoreAllocatorAdapter<ICoreAllocator> EASTLICoreAllocator;
|
||||
|
||||
|
||||
} // namespace Allocator
|
||||
|
||||
} // namespace EA
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Inlines
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
namespace EA
|
||||
{
|
||||
namespace Allocator
|
||||
{
|
||||
|
||||
template<class AllocatorType>
|
||||
inline CoreAllocatorAdapter<AllocatorType>::CoreAllocatorAdapter(const char* EASTL_NAME(pName))
|
||||
: mpCoreAllocator(AllocatorType::GetDefaultAllocator()), mnFlags(0)
|
||||
{
|
||||
#if EASTL_NAME_ENABLED
|
||||
mpName = pName ? pName : EASTL_ALLOCATOR_DEFAULT_NAME;
|
||||
#endif
|
||||
}
|
||||
|
||||
template<class AllocatorType>
|
||||
inline CoreAllocatorAdapter<AllocatorType>::CoreAllocatorAdapter(const char* EASTL_NAME(pName), AllocatorType* pCoreAllocator)
|
||||
: mpCoreAllocator(pCoreAllocator), mnFlags(0)
|
||||
{
|
||||
#if EASTL_NAME_ENABLED
|
||||
mpName = pName ? pName : EASTL_ALLOCATOR_DEFAULT_NAME;
|
||||
#endif
|
||||
}
|
||||
|
||||
template<class AllocatorType>
|
||||
inline CoreAllocatorAdapter<AllocatorType>::CoreAllocatorAdapter(const char* EASTL_NAME(pName), AllocatorType* pCoreAllocator, int flags)
|
||||
: mpCoreAllocator(pCoreAllocator), mnFlags(flags)
|
||||
{
|
||||
#if EASTL_NAME_ENABLED
|
||||
mpName = pName ? pName : EASTL_ALLOCATOR_DEFAULT_NAME;
|
||||
#endif
|
||||
}
|
||||
|
||||
template<class AllocatorType>
|
||||
inline CoreAllocatorAdapter<AllocatorType>::CoreAllocatorAdapter(const CoreAllocatorAdapter& x)
|
||||
: mpCoreAllocator(x.mpCoreAllocator), mnFlags(x.mnFlags)
|
||||
{
|
||||
#if EASTL_NAME_ENABLED
|
||||
mpName = x.mpName;
|
||||
#endif
|
||||
}
|
||||
|
||||
template<class AllocatorType>
|
||||
inline CoreAllocatorAdapter<AllocatorType>::CoreAllocatorAdapter(const CoreAllocatorAdapter& x, const char* EASTL_NAME(pName))
|
||||
: mpCoreAllocator(x.mpCoreAllocator), mnFlags(x.mnFlags)
|
||||
{
|
||||
#if EASTL_NAME_ENABLED
|
||||
mpName = pName ? pName : EASTL_ALLOCATOR_DEFAULT_NAME;
|
||||
#endif
|
||||
}
|
||||
|
||||
template<class AllocatorType>
|
||||
inline CoreAllocatorAdapter<AllocatorType>& CoreAllocatorAdapter<AllocatorType>::operator=(const CoreAllocatorAdapter& x)
|
||||
{
|
||||
// In order to be consistent with EASTL's allocator implementation,
|
||||
// we don't copy the name from the source object.
|
||||
mpCoreAllocator = x.mpCoreAllocator;
|
||||
mnFlags = x.mnFlags;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<class AllocatorType>
|
||||
inline void* CoreAllocatorAdapter<AllocatorType>::allocate(size_t n, int /*flags*/)
|
||||
{
|
||||
// It turns out that EASTL itself doesn't use the flags parameter,
|
||||
// whereas the user here might well want to specify a flags
|
||||
// parameter. So we use ours instead of the one passed in.
|
||||
return mpCoreAllocator->Alloc(n, EASTL_NAME_VAL(mpName), (unsigned)mnFlags);
|
||||
}
|
||||
|
||||
template<class AllocatorType>
|
||||
inline void* CoreAllocatorAdapter<AllocatorType>::allocate(size_t n, size_t alignment, size_t offset, int /*flags*/)
|
||||
{
|
||||
// It turns out that EASTL itself doesn't use the flags parameter,
|
||||
// whereas the user here might well want to specify a flags
|
||||
// parameter. So we use ours instead of the one passed in.
|
||||
return mpCoreAllocator->Alloc(n, EASTL_NAME_VAL(mpName), (unsigned)mnFlags, (unsigned)alignment, (unsigned)offset);
|
||||
}
|
||||
|
||||
template<class AllocatorType>
|
||||
inline void CoreAllocatorAdapter<AllocatorType>::deallocate(void* p, size_t n)
|
||||
{
|
||||
return mpCoreAllocator->Free(p, n);
|
||||
}
|
||||
|
||||
template<class AllocatorType>
|
||||
inline AllocatorType* CoreAllocatorAdapter<AllocatorType>::get_allocator() const
|
||||
{
|
||||
return mpCoreAllocator;
|
||||
}
|
||||
|
||||
template<class AllocatorType>
|
||||
inline void CoreAllocatorAdapter<AllocatorType>::set_allocator(AllocatorType* pAllocator)
|
||||
{
|
||||
mpCoreAllocator = pAllocator;
|
||||
}
|
||||
|
||||
template<class AllocatorType>
|
||||
inline int CoreAllocatorAdapter<AllocatorType>::get_flags() const
|
||||
{
|
||||
return mnFlags;
|
||||
}
|
||||
|
||||
template<class AllocatorType>
|
||||
inline void CoreAllocatorAdapter<AllocatorType>::set_flags(int flags)
|
||||
{
|
||||
mnFlags = flags;
|
||||
}
|
||||
|
||||
template<class AllocatorType>
|
||||
inline const char* CoreAllocatorAdapter<AllocatorType>::get_name() const
|
||||
{
|
||||
#if EASTL_NAME_ENABLED
|
||||
return mpName;
|
||||
#else
|
||||
return EASTL_ALLOCATOR_DEFAULT_NAME;
|
||||
#endif
|
||||
}
|
||||
|
||||
template<class AllocatorType>
|
||||
inline void CoreAllocatorAdapter<AllocatorType>::set_name(const char* pName)
|
||||
{
|
||||
#if EASTL_NAME_ENABLED
|
||||
mpName = pName;
|
||||
#else
|
||||
(void)pName;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
template<class AllocatorType>
|
||||
inline bool operator==(const CoreAllocatorAdapter<AllocatorType>& a, const CoreAllocatorAdapter<AllocatorType>& b)
|
||||
{
|
||||
return (a.mpCoreAllocator == b.mpCoreAllocator) &&
|
||||
(a.mnFlags == b.mnFlags);
|
||||
}
|
||||
|
||||
template<class AllocatorType>
|
||||
inline bool operator!=(const CoreAllocatorAdapter<AllocatorType>& a, const CoreAllocatorAdapter<AllocatorType>& b)
|
||||
{
|
||||
return (a.mpCoreAllocator != b.mpCoreAllocator) ||
|
||||
(a.mnFlags != b.mnFlags);
|
||||
}
|
||||
|
||||
|
||||
} // namespace Allocator
|
||||
|
||||
} // namespace EA
|
||||
|
||||
|
||||
#endif // Header include guard
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
467
lib/eastl/include/EASTL/fixed_allocator.h
Normal file
467
lib/eastl/include/EASTL/fixed_allocator.h
Normal file
|
@ -0,0 +1,467 @@
|
|||
/*
|
||||
Copyright (C) 2009-2010 Electronic Arts, Inc. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
3. Neither the name of Electronic Arts, Inc. ("EA") nor the names of
|
||||
its contributors may be used to endorse or promote products derived
|
||||
from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY ELECTRONIC ARTS AND ITS CONTRIBUTORS "AS IS" AND ANY
|
||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL ELECTRONIC ARTS OR ITS CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// EASTL/fixed_allocator.h
|
||||
//
|
||||
// Copyright (c) 2005, Electronic Arts. All rights reserved.
|
||||
// Written and maintained by Paul Pedriana.
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// This file implements the following
|
||||
// fixed_allocator
|
||||
// fixed_allocator_with_overflow
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
#ifndef EASTL_FIXED_ALLOCATOR_H
|
||||
#define EASTL_FIXED_ALLOCATOR_H
|
||||
|
||||
|
||||
#include <EASTL/internal/config.h>
|
||||
#include <EASTL/internal/fixed_pool.h>
|
||||
#include <EASTL/functional.h>
|
||||
#include <EASTL/memory.h>
|
||||
#include <EASTL/allocator.h>
|
||||
#include <EASTL/type_traits.h>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(push, 0)
|
||||
#include <new>
|
||||
#pragma warning(pop)
|
||||
#else
|
||||
#include <new>
|
||||
#endif
|
||||
|
||||
|
||||
namespace eastl
|
||||
{
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// fixed_allocator
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/// fixed_allocator
|
||||
///
|
||||
/// Implements an allocator which allocates a single fixed size where
|
||||
/// the size, alignment, and memory used for the pool is defined at
|
||||
/// runtime by the user. This is different from fixed containers
|
||||
/// such as fixed_list whereby the size and alignment are determined
|
||||
/// at compile time and the memory is directly built into the container's
|
||||
/// member data.
|
||||
///
|
||||
/// If the pool's memory is exhausted or was never initialized, the
|
||||
/// allocate function returns NULL. Consider the fixed_allocator_with_overflow
|
||||
/// class as an alternative in order to deal with this situation.
|
||||
///
|
||||
/// This class requires the user to call container.get_allocator().init()
|
||||
/// after constructing the container. There currently isn't a way to
|
||||
/// construct the container with the initialization parameters, though
|
||||
/// with some effort such a thing could probably be made possible.
|
||||
/// It's not as simple as it might first seem, due to the non-copyable
|
||||
/// nature of fixed allocators. A side effect of this limitation is that
|
||||
/// you cannot copy-construct a container using fixed_allocators.
|
||||
///
|
||||
/// Another side-effect is that you cannot swap two containers using
|
||||
/// a fixed_allocator, as a swap requires temporary memory allocated by
|
||||
/// an equivalent allocator, and such a thing cannot be done implicitly.
|
||||
/// A workaround for the swap limitation is that you can implement your
|
||||
/// own swap whereby you provide an explicitly created temporary object.
|
||||
///
|
||||
/// Note: Be careful to set the allocator's node size to the size of the
|
||||
/// container node and not the size of the contained object. Note that the
|
||||
/// example code below uses IntListNode.
|
||||
///
|
||||
/// Example usage:
|
||||
/// typedef eastl::list<int, fixed_allocator> IntList;
|
||||
/// typedef IntList::node_type IntListNode;
|
||||
///
|
||||
/// IntListNode buffer[200];
|
||||
/// IntList intList;
|
||||
/// intList.get_allocator().init(buffer, sizeof(buffer), sizeof(IntListNode), __alignof(IntListNode));
|
||||
///
|
||||
class EASTL_API fixed_allocator : public fixed_pool_base
|
||||
{
|
||||
public:
|
||||
/// fixed_allocator
|
||||
///
|
||||
/// Default constructor. The user usually will need to call init() after
|
||||
/// constructing via this constructor.
|
||||
///
|
||||
fixed_allocator(const char* /*pName*/ = EASTL_FIXED_POOL_DEFAULT_NAME)
|
||||
: fixed_pool_base(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/// fixed_allocator
|
||||
///
|
||||
/// Copy constructor. The user usually will need to call init() after
|
||||
/// constructing via this constructor. By their nature, fixed-allocators
|
||||
/// cannot be copied in any useful way, as by their nature the user
|
||||
/// must manually initialize them.
|
||||
///
|
||||
fixed_allocator(const fixed_allocator&)
|
||||
: fixed_pool_base(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/// operator=
|
||||
///
|
||||
/// By their nature, fixed-allocators cannot be copied in any
|
||||
/// useful way, as by their nature the user must manually
|
||||
/// initialize them.
|
||||
///
|
||||
fixed_allocator& operator=(const fixed_allocator&)
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
// init
|
||||
//
|
||||
// No init here, as the base class version is sufficient.
|
||||
//
|
||||
//void init(void* pMemory, size_t memorySize, size_t nodeSize,
|
||||
// size_t alignment, size_t alignmentOffset = 0);
|
||||
|
||||
|
||||
/// allocate
|
||||
///
|
||||
/// Allocates a new object of the size specified upon class initialization.
|
||||
/// Returns NULL if there is no more memory.
|
||||
///
|
||||
void* allocate(size_t /*n*/, int /*flags*/ = 0)
|
||||
{
|
||||
// To consider: Verify that 'n' is what the user initialized us with.
|
||||
|
||||
Link* pLink = mpHead;
|
||||
|
||||
if(pLink) // If we have space...
|
||||
{
|
||||
#if EASTL_FIXED_SIZE_TRACKING_ENABLED
|
||||
if(++mnCurrentSize > mnPeakSize)
|
||||
mnPeakSize = mnCurrentSize;
|
||||
#endif
|
||||
|
||||
mpHead = pLink->mpNext;
|
||||
return pLink;
|
||||
}
|
||||
else
|
||||
{
|
||||
// If there's no free node in the free list, just
|
||||
// allocate another from the reserved memory area
|
||||
|
||||
if(mpNext != mpCapacity)
|
||||
{
|
||||
pLink = mpNext;
|
||||
|
||||
mpNext = reinterpret_cast<Link*>(reinterpret_cast<char8_t*>(mpNext) + mnNodeSize);
|
||||
|
||||
#if EASTL_FIXED_SIZE_TRACKING_ENABLED
|
||||
if(++mnCurrentSize > mnPeakSize)
|
||||
mnPeakSize = mnCurrentSize;
|
||||
#endif
|
||||
|
||||
return pLink;
|
||||
}
|
||||
|
||||
// EASTL_ASSERT(false); To consider: enable this assert. However, we intentionally disable it because this isn't necessarily an assertable error.
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// allocate
|
||||
///
|
||||
void* allocate(size_t n, size_t /*alignment*/, size_t /*offset*/, int flags = 0)
|
||||
{
|
||||
return allocate(n, flags);
|
||||
}
|
||||
|
||||
|
||||
/// deallocate
|
||||
///
|
||||
/// Frees the given object which was allocated by allocate().
|
||||
/// If the given node was not allocated by allocate() then the behaviour
|
||||
/// is undefined.
|
||||
///
|
||||
void deallocate(void* p, size_t)
|
||||
{
|
||||
#if EASTL_FIXED_SIZE_TRACKING_ENABLED
|
||||
--mnCurrentSize;
|
||||
#endif
|
||||
|
||||
((Link*)p)->mpNext = mpHead;
|
||||
mpHead = ((Link*)p);
|
||||
}
|
||||
|
||||
|
||||
using fixed_pool_base::can_allocate;
|
||||
|
||||
|
||||
const char* get_name() const
|
||||
{
|
||||
return EASTL_FIXED_POOL_DEFAULT_NAME;
|
||||
}
|
||||
|
||||
|
||||
void set_name(const char*)
|
||||
{
|
||||
// Nothing to do. We don't allocate memory.
|
||||
}
|
||||
|
||||
}; // fixed_allocator
|
||||
|
||||
bool operator==(const fixed_allocator& a, const fixed_allocator& b);
|
||||
bool operator!=(const fixed_allocator& a, const fixed_allocator& b);
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// fixed_allocator_with_overflow
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/// fixed_allocator_with_overflow
|
||||
///
|
||||
/// Implements an allocator which allocates a single fixed size where
|
||||
/// the size, alignment, and memory used for the pool is defined at
|
||||
/// runtime by the user. This is different from fixed containers
|
||||
/// such as fixed_list whereby the size and alignment are determined
|
||||
/// at compile time and the memory is directly built into the container's
|
||||
/// member data.
|
||||
///
|
||||
/// Note: Be careful to set the allocator's node size to the size of the
|
||||
/// container node and not the size of the contained object. Note that the
|
||||
/// example code below uses IntListNode.
|
||||
///
|
||||
/// This class requires the user to call container.get_allocator().init()
|
||||
/// after constructing the container. There currently isn't a way to
|
||||
/// construct the container with the initialization parameters, though
|
||||
/// with some effort such a thing could probably be made possible.
|
||||
/// It's not as simple as it might first seem, due to the non-copyable
|
||||
/// nature of fixed allocators. A side effect of this limitation is that
|
||||
/// you cannot copy-construct a container using fixed_allocators.
|
||||
///
|
||||
/// Another side-effect is that you cannot swap two containers using
|
||||
/// a fixed_allocator, as a swap requires temporary memory allocated by
|
||||
/// an equivalent allocator, and such a thing cannot be done implicitly.
|
||||
/// A workaround for the swap limitation is that you can implement your
|
||||
/// own swap whereby you provide an explicitly created temporary object.
|
||||
///
|
||||
/// Example usage:
|
||||
/// typedef eastl::list<int, fixed_allocator_with_overflow> IntList;
|
||||
/// typedef IntList::node_type IntListNode;
|
||||
///
|
||||
/// IntListNode buffer[200];
|
||||
/// IntList intList;
|
||||
/// intList.get_allocator().init(buffer, sizeof(buffer), sizeof(IntListNode), __alignof(IntListNode));
|
||||
///
|
||||
class EASTL_API fixed_allocator_with_overflow : public fixed_pool_base
|
||||
{
|
||||
public:
|
||||
/// fixed_allocator_with_overflow
|
||||
///
|
||||
/// Default constructor. The user usually will need to call init() after
|
||||
/// constructing via this constructor.
|
||||
///
|
||||
fixed_allocator_with_overflow(const char* pName = EASTL_FIXED_POOL_DEFAULT_NAME)
|
||||
: fixed_pool_base(NULL),
|
||||
mOverflowAllocator(pName)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/// fixed_allocator_with_overflow
|
||||
///
|
||||
/// Copy constructor. The user usually will need to call init() after
|
||||
/// constructing via this constructor. By their nature, fixed-allocators
|
||||
/// cannot be copied in any useful way, as by their nature the user
|
||||
/// must manually initialize them.
|
||||
///
|
||||
fixed_allocator_with_overflow(const fixed_allocator_with_overflow&)
|
||||
: fixed_pool_base(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/// operator=
|
||||
///
|
||||
/// By their nature, fixed-allocators cannot be copied in any
|
||||
/// useful way, as by their nature the user must manually
|
||||
/// initialize them.
|
||||
///
|
||||
fixed_allocator_with_overflow& operator=(const fixed_allocator_with_overflow& x)
|
||||
{
|
||||
#if EASTL_ALLOCATOR_COPY_ENABLED
|
||||
mOverflowAllocator = x.mOverflowAllocator;
|
||||
#else
|
||||
(void)x;
|
||||
#endif
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
/// init
|
||||
///
|
||||
void init(void* pMemory, size_t memorySize, size_t nodeSize,
|
||||
size_t alignment, size_t alignmentOffset = 0)
|
||||
{
|
||||
fixed_pool_base::init(pMemory, memorySize, nodeSize, alignment, alignmentOffset);
|
||||
|
||||
mpPoolBegin = pMemory;
|
||||
mpPoolEnd = (void*)((uintptr_t)pMemory + memorySize);
|
||||
mnNodeSize = (eastl_size_t)nodeSize;
|
||||
}
|
||||
|
||||
|
||||
/// allocate
|
||||
///
|
||||
/// Allocates a new object of the size specified upon class initialization.
|
||||
/// Returns NULL if there is no more memory.
|
||||
///
|
||||
void* allocate(size_t /*n*/, int /*flags*/ = 0)
|
||||
{
|
||||
// To consider: Verify that 'n' is what the user initialized us with.
|
||||
|
||||
void* p;
|
||||
|
||||
if(mpHead) // If we have space...
|
||||
{
|
||||
p = mpHead;
|
||||
mpHead = mpHead->mpNext;
|
||||
}
|
||||
else
|
||||
p = mOverflowAllocator.allocate(mnNodeSize);
|
||||
|
||||
#if EASTL_FIXED_SIZE_TRACKING_ENABLED
|
||||
if(p && (++mnCurrentSize > mnPeakSize))
|
||||
mnPeakSize = mnCurrentSize;
|
||||
#endif
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
|
||||
/// allocate
|
||||
///
|
||||
void* allocate(size_t n, size_t /*alignment*/, size_t /*offset*/, int flags = 0)
|
||||
{
|
||||
return allocate(n, flags);
|
||||
}
|
||||
|
||||
|
||||
/// deallocate
|
||||
///
|
||||
/// Frees the given object which was allocated by allocate().
|
||||
/// If the given node was not allocated by allocate() then the behaviour
|
||||
/// is undefined.
|
||||
///
|
||||
void deallocate(void* p, size_t)
|
||||
{
|
||||
#if EASTL_FIXED_SIZE_TRACKING_ENABLED
|
||||
--mnCurrentSize;
|
||||
#endif
|
||||
|
||||
if((p >= mpPoolBegin) && (p < mpPoolEnd))
|
||||
{
|
||||
((Link*)p)->mpNext = mpHead;
|
||||
mpHead = ((Link*)p);
|
||||
}
|
||||
else
|
||||
mOverflowAllocator.deallocate(p, (size_t)mnNodeSize);
|
||||
}
|
||||
|
||||
|
||||
using fixed_pool_base::can_allocate;
|
||||
|
||||
|
||||
const char* get_name() const
|
||||
{
|
||||
return mOverflowAllocator.get_name();
|
||||
}
|
||||
|
||||
|
||||
void set_name(const char* pName)
|
||||
{
|
||||
mOverflowAllocator.set_name(pName);
|
||||
}
|
||||
|
||||
protected:
|
||||
EASTLAllocatorType mOverflowAllocator; // To consider: Allow the user to define the type of this, presumably via a template parameter.
|
||||
void* mpPoolBegin; // To consider: We have these member variables and ideally we shouldn't need them. The problem is that
|
||||
void* mpPoolEnd; // the information about the pool buffer and object size is stored in the owning container
|
||||
eastl_size_t mnNodeSize; // and we can't have access to it without increasing the amount of code we need and by templating
|
||||
// more code. It may turn out that simply storing data here is smaller in the end.
|
||||
}; // fixed_allocator_with_overflow // Granted, this class is usually used for debugging purposes, but perhaps there is an elegant solution.
|
||||
|
||||
bool operator==(const fixed_allocator_with_overflow& a, const fixed_allocator_with_overflow& b);
|
||||
bool operator!=(const fixed_allocator_with_overflow& a, const fixed_allocator_with_overflow& b);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// global operators
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
|
||||
inline bool operator==(const fixed_allocator&, const fixed_allocator&)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
inline bool operator!=(const fixed_allocator&, const fixed_allocator&)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
inline bool operator==(const fixed_allocator_with_overflow&, const fixed_allocator_with_overflow&)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
inline bool operator!=(const fixed_allocator_with_overflow&, const fixed_allocator_with_overflow&)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
} // namespace eastl
|
||||
|
||||
|
||||
|
||||
|
||||
#endif // Header include guard
|
||||
|
||||
|
||||
|
419
lib/eastl/include/EASTL/fixed_hash_map.h
Normal file
419
lib/eastl/include/EASTL/fixed_hash_map.h
Normal file
|
@ -0,0 +1,419 @@
|
|||
/*
|
||||
Copyright (C) 2009-2010 Electronic Arts, Inc. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
3. Neither the name of Electronic Arts, Inc. ("EA") nor the names of
|
||||
its contributors may be used to endorse or promote products derived
|
||||
from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY ELECTRONIC ARTS AND ITS CONTRIBUTORS "AS IS" AND ANY
|
||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL ELECTRONIC ARTS OR ITS CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// EASTL/fixed_hash_map.h
|
||||
//
|
||||
// Copyright (c) 2005, Electronic Arts. All rights reserved.
|
||||
// Written and maintained by Paul Pedriana.
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// This file implements a hash_map and hash_multimap which use a fixed size
|
||||
// memory pool for its buckets and nodes.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
#ifndef EASTL_FIXED_HASH_MAP_H
|
||||
#define EASTL_FIXED_HASH_MAP_H
|
||||
|
||||
|
||||
#include <EASTL/hash_map.h>
|
||||
#include <EASTL/internal/fixed_pool.h>
|
||||
|
||||
|
||||
namespace eastl
|
||||
{
|
||||
/// EASTL_FIXED_HASH_MAP_DEFAULT_NAME
|
||||
///
|
||||
/// Defines a default container name in the absence of a user-provided name.
|
||||
/// In the case of fixed-size containers, the allocator name always refers
|
||||
/// to overflow allocations.
|
||||
///
|
||||
#ifndef EASTL_FIXED_HASH_MAP_DEFAULT_NAME
|
||||
#define EASTL_FIXED_HASH_MAP_DEFAULT_NAME EASTL_DEFAULT_NAME_PREFIX " fixed_hash_map" // Unless the user overrides something, this is "EASTL fixed_hash_map".
|
||||
#endif
|
||||
|
||||
#ifndef EASTL_FIXED_HASH_MULTIMAP_DEFAULT_NAME
|
||||
#define EASTL_FIXED_HASH_MULTIMAP_DEFAULT_NAME EASTL_DEFAULT_NAME_PREFIX " fixed_hash_multimap" // Unless the user overrides something, this is "EASTL fixed_hash_multimap".
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/// fixed_hash_map
|
||||
///
|
||||
/// Implements a hash_map with a fixed block of memory identified by the nodeCount and bucketCount
|
||||
/// template parameters.
|
||||
///
|
||||
/// Template parameters:
|
||||
/// Key The key type for the map. This is a map of Key to T (value).
|
||||
/// T The value type for the map.
|
||||
/// nodeCount The max number of objects to contain. This value must be >= 1.
|
||||
/// bucketCount The number of buckets to use. This value must be >= 2.
|
||||
/// bEnableOverflow Whether or not we should use the global heap if our object pool is exhausted.
|
||||
/// Hash hash_set hash function. See hash_set.
|
||||
/// Predicate hash_set equality testing function. See hash_set.
|
||||
///
|
||||
template <typename Key, typename T, size_t nodeCount, size_t bucketCount = nodeCount + 1, bool bEnableOverflow = true,
|
||||
typename Hash = eastl::hash<Key>, typename Predicate = eastl::equal_to<Key>, bool bCacheHashCode = false, typename Allocator = EASTLAllocatorType>
|
||||
class fixed_hash_map : public hash_map<Key,
|
||||
T,
|
||||
Hash,
|
||||
Predicate,
|
||||
fixed_hashtable_allocator<
|
||||
bucketCount + 1,
|
||||
sizeof(typename hash_map<Key, T, Hash, Predicate, Allocator, bCacheHashCode>::node_type),
|
||||
nodeCount,
|
||||
hash_map<Key, T, Hash, Predicate, Allocator, bCacheHashCode>::kValueAlignment,
|
||||
hash_map<Key, T, Hash, Predicate, Allocator, bCacheHashCode>::kValueAlignmentOffset,
|
||||
bEnableOverflow,
|
||||
Allocator>,
|
||||
bCacheHashCode>
|
||||
{
|
||||
public:
|
||||
typedef fixed_hash_map<Key, T, nodeCount, bucketCount, bEnableOverflow, Hash, Predicate, bCacheHashCode, Allocator> this_type;
|
||||
typedef fixed_hashtable_allocator<bucketCount + 1, sizeof(typename hash_map<Key, T, Hash, Predicate,
|
||||
Allocator, bCacheHashCode>::node_type), nodeCount, hash_map<Key, T, Hash, Predicate,
|
||||
Allocator, bCacheHashCode>::kValueAlignment, hash_map<Key, T, Hash, Predicate,
|
||||
Allocator, bCacheHashCode>::kValueAlignmentOffset, bEnableOverflow, Allocator> fixed_allocator_type;
|
||||
typedef hash_map<Key, T, Hash, Predicate, fixed_allocator_type, bCacheHashCode> base_type;
|
||||
typedef typename base_type::node_type node_type;
|
||||
typedef typename base_type::size_type size_type;
|
||||
|
||||
enum
|
||||
{
|
||||
kMaxSize = nodeCount
|
||||
};
|
||||
|
||||
using base_type::mAllocator;
|
||||
|
||||
protected:
|
||||
node_type** mBucketBuffer[bucketCount + 1]; // '+1' because the hash table needs a null terminating bucket.
|
||||
char mNodeBuffer[fixed_allocator_type::kBufferSize]; // kBufferSize will take into account alignment requirements.
|
||||
|
||||
public:
|
||||
/// fixed_hash_map
|
||||
///
|
||||
/// Construct an empty fixed_hash_map with a given set of parameters.
|
||||
///
|
||||
explicit fixed_hash_map(const Hash& hashFunction = Hash(),
|
||||
const Predicate& predicate = Predicate())
|
||||
: base_type(prime_rehash_policy::GetPrevBucketCountOnly(bucketCount), hashFunction,
|
||||
predicate, fixed_allocator_type(NULL, mBucketBuffer))
|
||||
{
|
||||
EASTL_CT_ASSERT((nodeCount >= 1) && (bucketCount >= 2));
|
||||
base_type::set_max_load_factor(10000.f); // Set it so that we will never resize.
|
||||
|
||||
#if EASTL_NAME_ENABLED
|
||||
mAllocator.set_name(EASTL_FIXED_HASH_MAP_DEFAULT_NAME);
|
||||
#endif
|
||||
|
||||
mAllocator.reset(mNodeBuffer);
|
||||
}
|
||||
|
||||
|
||||
/// fixed_hash_map
|
||||
///
|
||||
/// Construct a fixed_hash_map from a source sequence and with a given set of parameters.
|
||||
///
|
||||
template <typename InputIterator>
|
||||
fixed_hash_map(InputIterator first, InputIterator last,
|
||||
const Hash& hashFunction = Hash(),
|
||||
const Predicate& predicate = Predicate())
|
||||
: base_type(prime_rehash_policy::GetPrevBucketCountOnly(bucketCount), hashFunction,
|
||||
predicate, fixed_allocator_type(NULL, mBucketBuffer))
|
||||
{
|
||||
EASTL_CT_ASSERT((nodeCount >= 1) && (bucketCount >= 2));
|
||||
base_type::set_max_load_factor(10000.f); // Set it so that we will never resize.
|
||||
|
||||
#if EASTL_NAME_ENABLED
|
||||
mAllocator.set_name(EASTL_FIXED_HASH_MAP_DEFAULT_NAME);
|
||||
#endif
|
||||
|
||||
mAllocator.reset(mNodeBuffer);
|
||||
base_type::insert(first, last);
|
||||
}
|
||||
|
||||
|
||||
/// fixed_hash_map
|
||||
///
|
||||
/// Copy constructor
|
||||
///
|
||||
fixed_hash_map(const this_type& x)
|
||||
: base_type(prime_rehash_policy::GetPrevBucketCountOnly(bucketCount), x.hash_function(),
|
||||
x.equal_function(), fixed_allocator_type(NULL, mBucketBuffer))
|
||||
{
|
||||
EASTL_CT_ASSERT((nodeCount >= 1) && (bucketCount >= 2));
|
||||
base_type::set_max_load_factor(10000.f); // Set it so that we will never resize.
|
||||
|
||||
#if EASTL_NAME_ENABLED
|
||||
mAllocator.set_name(x.mAllocator.get_name());
|
||||
#endif
|
||||
|
||||
mAllocator.reset(mNodeBuffer);
|
||||
base_type::insert(x.begin(), x.end());
|
||||
}
|
||||
|
||||
|
||||
/// operator=
|
||||
///
|
||||
/// We provide an override so that assignment is done correctly.
|
||||
///
|
||||
this_type& operator=(const this_type& x)
|
||||
{
|
||||
if(this != &x)
|
||||
{
|
||||
base_type::clear();
|
||||
base_type::insert(x.begin(), x.end());
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
void swap(this_type& x)
|
||||
{
|
||||
// Fixed containers use a special swap that can deal with excessively large buffers.
|
||||
eastl::fixed_swap(*this, x);
|
||||
}
|
||||
|
||||
|
||||
void reset()
|
||||
{
|
||||
base_type::reset();
|
||||
base_type::get_allocator().reset(mNodeBuffer);
|
||||
}
|
||||
|
||||
|
||||
size_type max_size() const
|
||||
{
|
||||
return kMaxSize;
|
||||
}
|
||||
|
||||
}; // fixed_hash_map
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// global operators
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <typename Key, typename T, size_t nodeCount, size_t bucketCount, bool bEnableOverflow, typename Hash, typename Predicate, bool bCacheHashCode>
|
||||
inline void swap(fixed_hash_map<Key, T, nodeCount, bucketCount, bEnableOverflow, Hash, Predicate, bCacheHashCode>& a,
|
||||
fixed_hash_map<Key, T, nodeCount, bucketCount, bEnableOverflow, Hash, Predicate, bCacheHashCode>& b)
|
||||
{
|
||||
// Fixed containers use a special swap that can deal with excessively large buffers.
|
||||
eastl::fixed_swap(a, b);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/// fixed_hash_multimap
|
||||
///
|
||||
/// Implements a hash_multimap with a fixed block of memory identified by the nodeCount and bucketCount
|
||||
/// template parameters.
|
||||
///
|
||||
/// Template parameters:
|
||||
/// Key The key type for the map. This is a map of Key to T (value).
|
||||
/// T The value type for the map.
|
||||
/// nodeCount The max number of objects to contain. This value must be >= 1.
|
||||
/// bucketCount The number of buckets to use. This value must be >= 2.
|
||||
/// bEnableOverflow Whether or not we should use the global heap if our object pool is exhausted.
|
||||
/// Hash hash_set hash function. See hash_set.
|
||||
/// Predicate hash_set equality testing function. See hash_set.
|
||||
///
|
||||
template <typename Key, typename T, size_t nodeCount, size_t bucketCount = nodeCount + 1, bool bEnableOverflow = true,
|
||||
typename Hash = eastl::hash<Key>, typename Predicate = eastl::equal_to<Key>, bool bCacheHashCode = false, typename Allocator = EASTLAllocatorType>
|
||||
class fixed_hash_multimap : public hash_multimap<Key,
|
||||
T,
|
||||
Hash,
|
||||
Predicate,
|
||||
fixed_hashtable_allocator<
|
||||
bucketCount + 1,
|
||||
sizeof(typename hash_multimap<Key, T, Hash, Predicate, Allocator, bCacheHashCode>::node_type),
|
||||
nodeCount,
|
||||
hash_multimap<Key, T, Hash, Predicate, Allocator, bCacheHashCode>::kValueAlignment,
|
||||
hash_multimap<Key, T, Hash, Predicate, Allocator, bCacheHashCode>::kValueAlignmentOffset,
|
||||
bEnableOverflow,
|
||||
Allocator>,
|
||||
bCacheHashCode>
|
||||
{
|
||||
public:
|
||||
typedef fixed_hash_multimap<Key, T, nodeCount, bucketCount, bEnableOverflow, Hash, Predicate, bCacheHashCode, Allocator> this_type;
|
||||
typedef fixed_hashtable_allocator<bucketCount + 1, sizeof(typename hash_multimap<Key, T, Hash, Predicate,
|
||||
Allocator, bCacheHashCode>::node_type), nodeCount, hash_multimap<Key, T, Hash, Predicate,
|
||||
Allocator, bCacheHashCode>::kValueAlignment, hash_multimap<Key, T, Hash, Predicate,
|
||||
Allocator, bCacheHashCode>::kValueAlignmentOffset, bEnableOverflow, Allocator> fixed_allocator_type;
|
||||
typedef hash_multimap<Key, T, Hash, Predicate, fixed_allocator_type, bCacheHashCode> base_type;
|
||||
typedef typename base_type::node_type node_type;
|
||||
typedef typename base_type::size_type size_type;
|
||||
|
||||
enum
|
||||
{
|
||||
kMaxSize = nodeCount
|
||||
};
|
||||
|
||||
using base_type::mAllocator;
|
||||
|
||||
protected:
|
||||
node_type** mBucketBuffer[bucketCount + 1]; // '+1' because the hash table needs a null terminating bucket.
|
||||
char mNodeBuffer[fixed_allocator_type::kBufferSize]; // kBufferSize will take into account alignment requirements.
|
||||
|
||||
public:
|
||||
/// fixed_hash_multimap
|
||||
///
|
||||
/// Construct an empty fixed_hash_multimap with a given set of parameters.
|
||||
///
|
||||
explicit fixed_hash_multimap(const Hash& hashFunction = Hash(),
|
||||
const Predicate& predicate = Predicate())
|
||||
: base_type(prime_rehash_policy::GetPrevBucketCountOnly(bucketCount), hashFunction,
|
||||
predicate, fixed_allocator_type(NULL, mBucketBuffer))
|
||||
{
|
||||
EASTL_CT_ASSERT((nodeCount >= 1) && (bucketCount >= 2));
|
||||
base_type::set_max_load_factor(10000.f); // Set it so that we will never resize.
|
||||
|
||||
#if EASTL_NAME_ENABLED
|
||||
mAllocator.set_name(EASTL_FIXED_HASH_MULTIMAP_DEFAULT_NAME);
|
||||
#endif
|
||||
|
||||
mAllocator.reset(mNodeBuffer);
|
||||
}
|
||||
|
||||
|
||||
/// fixed_hash_multimap
|
||||
///
|
||||
/// Construct a fixed_hash_multimap from a source sequence and with a given set of parameters.
|
||||
///
|
||||
template <typename InputIterator>
|
||||
fixed_hash_multimap(InputIterator first, InputIterator last,
|
||||
const Hash& hashFunction = Hash(),
|
||||
const Predicate& predicate = Predicate())
|
||||
: base_type(prime_rehash_policy::GetPrevBucketCountOnly(bucketCount), hashFunction,
|
||||
predicate, fixed_allocator_type(NULL, mBucketBuffer))
|
||||
{
|
||||
EASTL_CT_ASSERT((nodeCount >= 1) && (bucketCount >= 2));
|
||||
base_type::set_max_load_factor(10000.f); // Set it so that we will never resize.
|
||||
|
||||
#if EASTL_NAME_ENABLED
|
||||
mAllocator.set_name(EASTL_FIXED_HASH_MULTIMAP_DEFAULT_NAME);
|
||||
#endif
|
||||
|
||||
mAllocator.reset(mNodeBuffer);
|
||||
base_type::insert(first, last);
|
||||
}
|
||||
|
||||
|
||||
/// fixed_hash_multimap
|
||||
///
|
||||
/// Copy constructor
|
||||
///
|
||||
fixed_hash_multimap(const this_type& x)
|
||||
: base_type(prime_rehash_policy::GetPrevBucketCountOnly(bucketCount), x.hash_function(),
|
||||
x.equal_function(),fixed_allocator_type(NULL, mBucketBuffer))
|
||||
{
|
||||
EASTL_CT_ASSERT((nodeCount >= 1) && (bucketCount >= 2));
|
||||
base_type::set_max_load_factor(10000.f); // Set it so that we will never resize.
|
||||
|
||||
#if EASTL_NAME_ENABLED
|
||||
mAllocator.set_name(x.mAllocator.get_name());
|
||||
#endif
|
||||
|
||||
mAllocator.reset(mNodeBuffer);
|
||||
base_type::insert(x.begin(), x.end());
|
||||
}
|
||||
|
||||
|
||||
/// operator=
|
||||
///
|
||||
/// We provide an override so that assignment is done correctly.
|
||||
///
|
||||
this_type& operator=(const this_type& x)
|
||||
{
|
||||
if(this != &x)
|
||||
{
|
||||
base_type::clear();
|
||||
base_type::insert(x.begin(), x.end());
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
void swap(this_type& x)
|
||||
{
|
||||
// Fixed containers use a special swap that can deal with excessively large buffers.
|
||||
eastl::fixed_swap(*this, x);
|
||||
}
|
||||
|
||||
|
||||
void reset()
|
||||
{
|
||||
base_type::reset();
|
||||
base_type::get_allocator().reset(mNodeBuffer);
|
||||
}
|
||||
|
||||
|
||||
size_type max_size() const
|
||||
{
|
||||
return kMaxSize;
|
||||
}
|
||||
|
||||
}; // fixed_hash_multimap
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// global operators
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <typename Key, typename T, size_t nodeCount, size_t bucketCount, bool bEnableOverflow, typename Hash, typename Predicate, bool bCacheHashCode>
|
||||
inline void swap(fixed_hash_multimap<Key, T, nodeCount, bucketCount, bEnableOverflow, Hash, Predicate, bCacheHashCode>& a,
|
||||
fixed_hash_multimap<Key, T, nodeCount, bucketCount, bEnableOverflow, Hash, Predicate, bCacheHashCode>& b)
|
||||
{
|
||||
// Fixed containers use a special swap that can deal with excessively large buffers.
|
||||
eastl::fixed_swap(a, b);
|
||||
}
|
||||
|
||||
|
||||
|
||||
} // namespace eastl
|
||||
|
||||
|
||||
|
||||
|
||||
#endif // Header include guard
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
422
lib/eastl/include/EASTL/fixed_hash_set.h
Normal file
422
lib/eastl/include/EASTL/fixed_hash_set.h
Normal file
|
@ -0,0 +1,422 @@
|
|||
/*
|
||||
Copyright (C) 2009-2010 Electronic Arts, Inc. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
3. Neither the name of Electronic Arts, Inc. ("EA") nor the names of
|
||||
its contributors may be used to endorse or promote products derived
|
||||
from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY ELECTRONIC ARTS AND ITS CONTRIBUTORS "AS IS" AND ANY
|
||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL ELECTRONIC ARTS OR ITS CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// EASTL/fixed_hash_set.h
|
||||
//
|
||||
// Copyright (c) 2005, Electronic Arts. All rights reserved.
|
||||
// Written and maintained by Paul Pedriana.
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// This file implements a hash_set which uses a fixed size memory pool for
|
||||
// its buckets and nodes.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
#ifndef EASTL_FIXED_HASH_SET_H
|
||||
#define EASTL_FIXED_HASH_SET_H
|
||||
|
||||
|
||||
#include <EASTL/hash_set.h>
|
||||
#include <EASTL/internal/fixed_pool.h>
|
||||
|
||||
|
||||
|
||||
namespace eastl
|
||||
{
|
||||
/// EASTL_FIXED_HASH_SET_DEFAULT_NAME
|
||||
///
|
||||
/// Defines a default container name in the absence of a user-provided name.
|
||||
/// In the case of fixed-size containers, the allocator name always refers
|
||||
/// to overflow allocations.
|
||||
///
|
||||
#ifndef EASTL_FIXED_HASH_SET_DEFAULT_NAME
|
||||
#define EASTL_FIXED_HASH_SET_DEFAULT_NAME EASTL_DEFAULT_NAME_PREFIX " fixed_hash_set" // Unless the user overrides something, this is "EASTL fixed_hash_set".
|
||||
#endif
|
||||
|
||||
#ifndef EASTL_FIXED_HASH_MULTISET_DEFAULT_NAME
|
||||
#define EASTL_FIXED_HASH_MULTISET_DEFAULT_NAME EASTL_DEFAULT_NAME_PREFIX " fixed_hash_multiset" // Unless the user overrides something, this is "EASTL fixed_hash_multiset".
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/// fixed_hash_set
|
||||
///
|
||||
/// Implements a hash_set with a fixed block of memory identified by the nodeCount and bucketCount
|
||||
/// template parameters.
|
||||
///
|
||||
/// Template parameters:
|
||||
/// Value The type of object the hash_set holds.
|
||||
/// nodeCount The max number of objects to contain. This value must be >= 1.
|
||||
/// bucketCount The number of buckets to use. This value must be >= 2.
|
||||
/// bEnableOverflow Whether or not we should use the global heap if our object pool is exhausted.
|
||||
/// Hash hash_set hash function. See hash_set.
|
||||
/// Predicate hash_set equality testing function. See hash_set.
|
||||
///
|
||||
template <typename Value, size_t nodeCount, size_t bucketCount = nodeCount + 1, bool bEnableOverflow = true,
|
||||
typename Hash = eastl::hash<Value>, typename Predicate = eastl::equal_to<Value>, bool bCacheHashCode = false, typename Allocator = EASTLAllocatorType>
|
||||
class fixed_hash_set : public hash_set<Value,
|
||||
Hash,
|
||||
Predicate,
|
||||
fixed_hashtable_allocator<
|
||||
bucketCount + 1,
|
||||
sizeof(typename hash_set<Value, Hash, Predicate, Allocator, bCacheHashCode>::node_type),
|
||||
nodeCount,
|
||||
hash_set<Value, Hash, Predicate, Allocator, bCacheHashCode>::kValueAlignment,
|
||||
hash_set<Value, Hash, Predicate, Allocator, bCacheHashCode>::kValueAlignmentOffset,
|
||||
bEnableOverflow,
|
||||
Allocator>,
|
||||
bCacheHashCode>
|
||||
{
|
||||
public:
|
||||
typedef fixed_hash_set<Value, nodeCount, bucketCount, bEnableOverflow, Hash, Predicate, bCacheHashCode, Allocator> this_type;
|
||||
typedef fixed_hashtable_allocator<bucketCount + 1, sizeof(typename hash_set<Value, Hash, Predicate,
|
||||
Allocator, bCacheHashCode>::node_type), nodeCount, hash_set<Value, Hash, Predicate,
|
||||
Allocator, bCacheHashCode>::kValueAlignment, hash_set<Value, Hash, Predicate,
|
||||
Allocator, bCacheHashCode>::kValueAlignmentOffset, bEnableOverflow, Allocator> fixed_allocator_type;
|
||||
typedef hash_set<Value, Hash, Predicate, fixed_allocator_type, bCacheHashCode> base_type;
|
||||
typedef typename base_type::node_type node_type;
|
||||
typedef typename base_type::size_type size_type;
|
||||
|
||||
enum
|
||||
{
|
||||
kMaxSize = nodeCount
|
||||
};
|
||||
|
||||
using base_type::mAllocator;
|
||||
|
||||
protected:
|
||||
node_type** mBucketBuffer[bucketCount + 1]; // '+1' because the hash table needs a null terminating bucket.
|
||||
char mNodeBuffer[fixed_allocator_type::kBufferSize]; // kBufferSize will take into account alignment requirements.
|
||||
|
||||
public:
|
||||
/// fixed_hash_set
|
||||
///
|
||||
/// Construct an empty fixed_hash_set with a given set of parameters.
|
||||
///
|
||||
explicit fixed_hash_set(const Hash& hashFunction = Hash(),
|
||||
const Predicate& predicate = Predicate())
|
||||
: base_type(prime_rehash_policy::GetPrevBucketCountOnly(bucketCount),
|
||||
hashFunction, predicate, fixed_allocator_type(NULL, mBucketBuffer))
|
||||
{
|
||||
EASTL_CT_ASSERT((nodeCount >= 1) && (bucketCount >= 2));
|
||||
base_type::set_max_load_factor(10000.f); // Set it so that we will never resize.
|
||||
|
||||
#if EASTL_NAME_ENABLED
|
||||
mAllocator.set_name(EASTL_FIXED_HASH_SET_DEFAULT_NAME);
|
||||
#endif
|
||||
|
||||
mAllocator.reset(mNodeBuffer);
|
||||
}
|
||||
|
||||
|
||||
/// fixed_hash_set
|
||||
///
|
||||
/// Construct a fixed_hash_set from a source sequence and with a given set of parameters.
|
||||
///
|
||||
template <typename InputIterator>
|
||||
fixed_hash_set(InputIterator first, InputIterator last,
|
||||
const Hash& hashFunction = Hash(),
|
||||
const Predicate& predicate = Predicate())
|
||||
: base_type(prime_rehash_policy::GetPrevBucketCountOnly(bucketCount), hashFunction,
|
||||
predicate, fixed_allocator_type(NULL, mBucketBuffer))
|
||||
{
|
||||
EASTL_CT_ASSERT((nodeCount >= 1) && (bucketCount >= 2));
|
||||
base_type::set_max_load_factor(10000.f); // Set it so that we will never resize.
|
||||
|
||||
#if EASTL_NAME_ENABLED
|
||||
mAllocator.set_name(EASTL_FIXED_HASH_SET_DEFAULT_NAME);
|
||||
#endif
|
||||
|
||||
mAllocator.reset(mNodeBuffer);
|
||||
base_type::insert(first, last);
|
||||
}
|
||||
|
||||
|
||||
/// fixed_hash_set
|
||||
///
|
||||
/// Copy constructor
|
||||
///
|
||||
fixed_hash_set(const this_type& x)
|
||||
: base_type(prime_rehash_policy::GetPrevBucketCountOnly(bucketCount), x.hash_function(),
|
||||
x.equal_function(), fixed_allocator_type(NULL, mBucketBuffer))
|
||||
{
|
||||
EASTL_CT_ASSERT((nodeCount >= 1) && (bucketCount >= 2));
|
||||
base_type::set_max_load_factor(10000.f); // Set it so that we will never resize.
|
||||
|
||||
#if EASTL_NAME_ENABLED
|
||||
mAllocator.set_name(x.mAllocator.get_name());
|
||||
#endif
|
||||
|
||||
mAllocator.reset(mNodeBuffer);
|
||||
base_type::insert(x.begin(), x.end());
|
||||
}
|
||||
|
||||
|
||||
/// operator=
|
||||
///
|
||||
/// We provide an override so that assignment is done correctly.
|
||||
///
|
||||
this_type& operator=(const this_type& x)
|
||||
{
|
||||
if(this != &x)
|
||||
{
|
||||
base_type::clear();
|
||||
base_type::insert(x.begin(), x.end());
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
void swap(this_type& x)
|
||||
{
|
||||
// We must do a brute-force swap, because fixed containers cannot share memory allocations.
|
||||
// Note that we create a temp value on the stack. This approach may fail if the size of the
|
||||
// container is too large. We have a rule against allocating memory from the heap, and so
|
||||
// if the user wants to swap two large objects of this class, the user will currently need
|
||||
// to implement it manually. To consider: add code to allocate a temporary buffer if the
|
||||
// size of the container is too large for the stack.
|
||||
EASTL_ASSERT(sizeof(x) < EASTL_MAX_STACK_USAGE); // It is dangerous to try to create objects that are too big for the stack.
|
||||
|
||||
const this_type temp(*this); // Can't call eastl::swap because that would
|
||||
*this = x; // itself call this member swap function.
|
||||
x = temp;
|
||||
}
|
||||
|
||||
|
||||
void reset()
|
||||
{
|
||||
base_type::reset();
|
||||
base_type::get_allocator().reset(mNodeBuffer);
|
||||
}
|
||||
|
||||
|
||||
size_type max_size() const
|
||||
{
|
||||
return kMaxSize;
|
||||
}
|
||||
|
||||
}; // fixed_hash_set
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// global operators
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <typename Value, size_t nodeCount, size_t bucketCount, bool bEnableOverflow, typename Hash, typename Predicate, bool bCacheHashCode>
|
||||
inline void swap(fixed_hash_set<Value, nodeCount, bucketCount, bEnableOverflow, Hash, Predicate, bCacheHashCode>& a,
|
||||
fixed_hash_set<Value, nodeCount, bucketCount, bEnableOverflow, Hash, Predicate, bCacheHashCode>& b)
|
||||
{
|
||||
a.swap(b);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/// fixed_hash_multiset
|
||||
///
|
||||
/// Implements a hash_multiset with a fixed block of memory identified by the nodeCount and bucketCount
|
||||
/// template parameters.
|
||||
///
|
||||
/// Value The type of object the hash_set holds.
|
||||
/// nodeCount The max number of objects to contain. This value must be >= 1.
|
||||
/// bucketCount The number of buckets to use. This value must be >= 2.
|
||||
/// bEnableOverflow Whether or not we should use the global heap if our object pool is exhausted.
|
||||
/// Hash hash_set hash function. See hash_set.
|
||||
/// Predicate hash_set equality testing function. See hash_set.
|
||||
///
|
||||
template <typename Value, size_t nodeCount, size_t bucketCount = nodeCount + 1, bool bEnableOverflow = true,
|
||||
typename Hash = eastl::hash<Value>, typename Predicate = eastl::equal_to<Value>, bool bCacheHashCode = false, typename Allocator = EASTLAllocatorType>
|
||||
class fixed_hash_multiset : public hash_multiset<Value,
|
||||
Hash,
|
||||
Predicate,
|
||||
fixed_hashtable_allocator<
|
||||
bucketCount + 1,
|
||||
sizeof(typename hash_multiset<Value, Hash, Predicate, Allocator, bCacheHashCode>::node_type),
|
||||
nodeCount,
|
||||
hash_multiset<Value, Hash, Predicate, Allocator, bCacheHashCode>::kValueAlignment,
|
||||
hash_multiset<Value, Hash, Predicate, Allocator, bCacheHashCode>::kValueAlignmentOffset,
|
||||
bEnableOverflow,
|
||||
Allocator>,
|
||||
bCacheHashCode>
|
||||
{
|
||||
public:
|
||||
typedef fixed_hash_multiset<Value, nodeCount, bucketCount, bEnableOverflow, Hash, Predicate, bCacheHashCode, Allocator> this_type;
|
||||
typedef fixed_hashtable_allocator<bucketCount + 1, sizeof(typename hash_multiset<Value, Hash, Predicate,
|
||||
Allocator, bCacheHashCode>::node_type), nodeCount, hash_multiset<Value, Hash, Predicate,
|
||||
Allocator, bCacheHashCode>::kValueAlignment, hash_multiset<Value, Hash, Predicate,
|
||||
Allocator, bCacheHashCode>::kValueAlignmentOffset, bEnableOverflow, Allocator> fixed_allocator_type;
|
||||
typedef hash_multiset<Value, Hash, Predicate, fixed_allocator_type, bCacheHashCode> base_type;
|
||||
typedef typename base_type::node_type node_type;
|
||||
typedef typename base_type::size_type size_type;
|
||||
|
||||
enum
|
||||
{
|
||||
kMaxSize = nodeCount
|
||||
};
|
||||
|
||||
using base_type::mAllocator;
|
||||
|
||||
protected:
|
||||
node_type** mBucketBuffer[bucketCount + 1]; // '+1' because the hash table needs a null terminating bucket.
|
||||
char mNodeBuffer[fixed_allocator_type::kBufferSize]; // kBufferSize will take into account alignment requirements.
|
||||
|
||||
public:
|
||||
/// fixed_hash_multiset
|
||||
///
|
||||
/// Construct an empty fixed_hash_multiset with a given set of parameters.
|
||||
///
|
||||
explicit fixed_hash_multiset(const Hash& hashFunction = Hash(),
|
||||
const Predicate& predicate = Predicate())
|
||||
: base_type(prime_rehash_policy::GetPrevBucketCountOnly(bucketCount), hashFunction,
|
||||
predicate, fixed_allocator_type(NULL, mBucketBuffer))
|
||||
{
|
||||
EASTL_CT_ASSERT((nodeCount >= 1) && (bucketCount >= 2));
|
||||
base_type::set_max_load_factor(10000.f); // Set it so that we will never resize.
|
||||
|
||||
#if EASTL_NAME_ENABLED
|
||||
mAllocator.set_name(EASTL_FIXED_HASH_MULTISET_DEFAULT_NAME);
|
||||
#endif
|
||||
|
||||
mAllocator.reset(mNodeBuffer);
|
||||
}
|
||||
|
||||
|
||||
/// fixed_hash_multiset
|
||||
///
|
||||
/// Construct a fixed_hash_multiset from a source sequence and with a given set of parameters.
|
||||
///
|
||||
template <typename InputIterator>
|
||||
fixed_hash_multiset(InputIterator first, InputIterator last,
|
||||
const Hash& hashFunction = Hash(),
|
||||
const Predicate& predicate = Predicate())
|
||||
: base_type(prime_rehash_policy::GetPrevBucketCountOnly(bucketCount), hashFunction,
|
||||
predicate, fixed_allocator_type(NULL, mBucketBuffer))
|
||||
{
|
||||
EASTL_CT_ASSERT((nodeCount >= 1) && (bucketCount >= 2));
|
||||
base_type::set_max_load_factor(10000.f); // Set it so that we will never resize.
|
||||
|
||||
#if EASTL_NAME_ENABLED
|
||||
mAllocator.set_name(EASTL_FIXED_HASH_MULTISET_DEFAULT_NAME);
|
||||
#endif
|
||||
|
||||
mAllocator.reset(mNodeBuffer);
|
||||
base_type::insert(first, last);
|
||||
}
|
||||
|
||||
|
||||
/// fixed_hash_multiset
|
||||
///
|
||||
/// Copy constructor
|
||||
///
|
||||
fixed_hash_multiset(const this_type& x)
|
||||
: base_type(prime_rehash_policy::GetPrevBucketCountOnly(bucketCount), x.hash_function(),
|
||||
x.equal_function(), fixed_allocator_type(NULL, mBucketBuffer))
|
||||
{
|
||||
EASTL_CT_ASSERT((nodeCount >= 1) && (bucketCount >= 2));
|
||||
base_type::set_max_load_factor(10000.f); // Set it so that we will never resize.
|
||||
|
||||
#if EASTL_NAME_ENABLED
|
||||
mAllocator.set_name(x.mAllocator.get_name());
|
||||
#endif
|
||||
|
||||
mAllocator.reset(mNodeBuffer);
|
||||
base_type::insert(x.begin(), x.end());
|
||||
}
|
||||
|
||||
|
||||
/// operator=
|
||||
///
|
||||
/// We provide an override so that assignment is done correctly.
|
||||
///
|
||||
this_type& operator=(const this_type& x)
|
||||
{
|
||||
if(this != &x)
|
||||
{
|
||||
base_type::clear();
|
||||
base_type::insert(x.begin(), x.end());
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
void swap(this_type& x)
|
||||
{
|
||||
// Fixed containers use a special swap that can deal with excessively large buffers.
|
||||
eastl::fixed_swap(*this, x);
|
||||
}
|
||||
|
||||
|
||||
void reset()
|
||||
{
|
||||
base_type::reset();
|
||||
base_type::get_allocator().reset(mNodeBuffer);
|
||||
}
|
||||
|
||||
|
||||
size_type max_size() const
|
||||
{
|
||||
return kMaxSize;
|
||||
}
|
||||
|
||||
}; // fixed_hash_multiset
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// global operators
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <typename Value, size_t nodeCount, size_t bucketCount, bool bEnableOverflow, typename Hash, typename Predicate, bool bCacheHashCode>
|
||||
inline void swap(fixed_hash_multiset<Value, nodeCount, bucketCount, bEnableOverflow, Hash, Predicate, bCacheHashCode>& a,
|
||||
fixed_hash_multiset<Value, nodeCount, bucketCount, bEnableOverflow, Hash, Predicate, bCacheHashCode>& b)
|
||||
{
|
||||
// Fixed containers use a special swap that can deal with excessively large buffers.
|
||||
eastl::fixed_swap(a, b);
|
||||
}
|
||||
|
||||
|
||||
} // namespace eastl
|
||||
|
||||
|
||||
#endif // Header include guard
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
342
lib/eastl/include/EASTL/fixed_list.h
Normal file
342
lib/eastl/include/EASTL/fixed_list.h
Normal file
|
@ -0,0 +1,342 @@
|
|||
/*
|
||||
Copyright (C) 2009-2010 Electronic Arts, Inc. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
3. Neither the name of Electronic Arts, Inc. ("EA") nor the names of
|
||||
its contributors may be used to endorse or promote products derived
|
||||
from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY ELECTRONIC ARTS AND ITS CONTRIBUTORS "AS IS" AND ANY
|
||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL ELECTRONIC ARTS OR ITS CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// EASTL/fixed_list.h
|
||||
//
|
||||
// Copyright (c) 2005, Electronic Arts. All rights reserved.
|
||||
// Written and maintained by Paul Pedriana.
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// This file implements a list which uses a fixed size memory pool for its nodes.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
#ifndef EASTL_FIXED_LIST_H
|
||||
#define EASTL_FIXED_LIST_H
|
||||
|
||||
|
||||
#include <EASTL/list.h>
|
||||
#include <EASTL/internal/fixed_pool.h>
|
||||
#include <EASTL/sort.h>
|
||||
|
||||
|
||||
namespace eastl
|
||||
{
|
||||
/// EASTL_FIXED_LIST_DEFAULT_NAME
|
||||
///
|
||||
/// Defines a default container name in the absence of a user-provided name.
|
||||
/// In the case of fixed-size containers, the allocator name always refers
|
||||
/// to overflow allocations.
|
||||
///
|
||||
#ifndef EASTL_FIXED_LIST_DEFAULT_NAME
|
||||
#define EASTL_FIXED_LIST_DEFAULT_NAME EASTL_DEFAULT_NAME_PREFIX " fixed_list" // Unless the user overrides something, this is "EASTL fixed_list".
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/// fixed_list
|
||||
///
|
||||
/// fixed_list is a list which uses a single block of contiguous memory
|
||||
/// for its nodes. The purpose of this is to reduce memory usage relative
|
||||
/// to a conventional memory allocation system (with block headers), to
|
||||
/// increase allocation speed (often due to avoidance of mutex locks),
|
||||
/// to increase performance (due to better memory locality), and to decrease
|
||||
/// memory fragmentation due to the way that fixed block allocators work.
|
||||
///
|
||||
/// The primary downside to a fixed_list is that the number of nodes it
|
||||
/// can contain is fixed upon its declaration. If you want a fixed_list
|
||||
/// that doesn't have this limitation, then you probably don't want a
|
||||
/// fixed_list. You can always create your own memory allocator that works
|
||||
/// the way you want.
|
||||
///
|
||||
/// Template parameters:
|
||||
/// T The type of object the list holds.
|
||||
/// nodeCount The max number of objects to contain.
|
||||
/// bEnableOverflow Whether or not we should use the overflow heap if our object pool is exhausted.
|
||||
/// Allocator Overflow allocator, which is only used if bEnableOverflow == true. Defaults to the global heap.
|
||||
///
|
||||
template <typename T, size_t nodeCount, bool bEnableOverflow = true, typename Allocator = EASTLAllocatorType>
|
||||
class fixed_list : public list<T, fixed_node_allocator<sizeof(typename list<T>::node_type),
|
||||
nodeCount, list<T>::kAlignment, list<T>::kAlignmentOffset, bEnableOverflow, Allocator> >
|
||||
{
|
||||
public:
|
||||
typedef fixed_list<T, nodeCount, bEnableOverflow, Allocator> this_type;
|
||||
typedef fixed_node_allocator<sizeof(typename list<T>::node_type), nodeCount,
|
||||
list<T>::kAlignment, list<T>::kAlignmentOffset, bEnableOverflow, Allocator> fixed_allocator_type;
|
||||
typedef list<T, fixed_allocator_type> base_type;
|
||||
typedef typename base_type::size_type size_type;
|
||||
typedef typename base_type::value_type value_type;
|
||||
typedef typename base_type::node_type node_type;
|
||||
typedef typename base_type::iterator iterator;
|
||||
|
||||
enum
|
||||
{
|
||||
kMaxSize = nodeCount
|
||||
};
|
||||
|
||||
using base_type::assign;
|
||||
using base_type::resize;
|
||||
|
||||
protected:
|
||||
char mBuffer[fixed_allocator_type::kBufferSize]; // kBufferSize will take into account alignment requirements.
|
||||
|
||||
using base_type::mAllocator;
|
||||
|
||||
public:
|
||||
fixed_list();
|
||||
explicit fixed_list(size_type n);
|
||||
fixed_list(size_type n, const value_type& value);
|
||||
fixed_list(const this_type& x);
|
||||
|
||||
template <typename InputIterator>
|
||||
fixed_list(InputIterator first, InputIterator last);
|
||||
|
||||
this_type& operator=(const this_type& x);
|
||||
|
||||
void swap(this_type& x);
|
||||
void reset();
|
||||
size_type max_size() const; // Returns the max fixed size, which is the user-supplied nodeCount parameter.
|
||||
bool has_overflowed() const; // Returns true if the fixed space is fully allocated. Note that if overflow is enabled, the container size can be greater than nodeCount but full() could return true because the fixed space may have a recently freed slot.
|
||||
|
||||
template<typename Compare>
|
||||
void sort(Compare compare);
|
||||
void sort();
|
||||
|
||||
template <typename Compare>
|
||||
void merge(this_type& x, Compare compare);
|
||||
void merge(this_type& x);
|
||||
|
||||
void splice(iterator position, this_type& x);
|
||||
void splice(iterator position, this_type& x, iterator i);
|
||||
void splice(iterator position, this_type& x, iterator first, iterator last);
|
||||
|
||||
// Deprecated:
|
||||
bool full() const { return has_overflowed(); }
|
||||
|
||||
}; // fixed_list
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// fixed_list
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <typename T, size_t nodeCount, bool bEnableOverflow, typename Allocator>
|
||||
inline fixed_list<T, nodeCount, bEnableOverflow, Allocator>::fixed_list()
|
||||
: base_type(fixed_allocator_type(NULL))
|
||||
{
|
||||
#if EASTL_NAME_ENABLED
|
||||
mAllocator.set_name(EASTL_FIXED_LIST_DEFAULT_NAME);
|
||||
#endif
|
||||
|
||||
mAllocator.reset(mBuffer);
|
||||
}
|
||||
|
||||
|
||||
template <typename T, size_t nodeCount, bool bEnableOverflow, typename Allocator>
|
||||
inline fixed_list<T, nodeCount, bEnableOverflow, Allocator>::fixed_list(size_type n)
|
||||
: base_type(fixed_allocator_type(NULL))
|
||||
{
|
||||
#if EASTL_NAME_ENABLED
|
||||
mAllocator.set_name(EASTL_FIXED_LIST_DEFAULT_NAME);
|
||||
#endif
|
||||
|
||||
mAllocator.reset(mBuffer);
|
||||
resize(n);
|
||||
}
|
||||
|
||||
|
||||
template <typename T, size_t nodeCount, bool bEnableOverflow, typename Allocator>
|
||||
inline fixed_list<T, nodeCount, bEnableOverflow, Allocator>::fixed_list(size_type n, const value_type& value)
|
||||
: base_type(fixed_allocator_type(NULL))
|
||||
{
|
||||
#if EASTL_NAME_ENABLED
|
||||
mAllocator.set_name(EASTL_FIXED_LIST_DEFAULT_NAME);
|
||||
#endif
|
||||
|
||||
mAllocator.reset(mBuffer);
|
||||
resize(n, value);
|
||||
}
|
||||
|
||||
|
||||
template <typename T, size_t nodeCount, bool bEnableOverflow, typename Allocator>
|
||||
inline fixed_list<T, nodeCount, bEnableOverflow, Allocator>::fixed_list(const this_type& x)
|
||||
: base_type(fixed_allocator_type(NULL))
|
||||
{
|
||||
#if EASTL_NAME_ENABLED
|
||||
mAllocator.set_name(x.mAllocator.get_name());
|
||||
#endif
|
||||
|
||||
mAllocator.reset(mBuffer);
|
||||
assign(x.begin(), x.end());
|
||||
}
|
||||
|
||||
|
||||
template <typename T, size_t nodeCount, bool bEnableOverflow, typename Allocator>
|
||||
template <typename InputIterator>
|
||||
fixed_list<T, nodeCount, bEnableOverflow, Allocator>::fixed_list(InputIterator first, InputIterator last)
|
||||
: base_type(fixed_allocator_type(NULL))
|
||||
{
|
||||
#if EASTL_NAME_ENABLED
|
||||
mAllocator.set_name(EASTL_FIXED_LIST_DEFAULT_NAME);
|
||||
#endif
|
||||
|
||||
mAllocator.reset(mBuffer);
|
||||
assign(first, last);
|
||||
}
|
||||
|
||||
|
||||
template <typename T, size_t nodeCount, bool bEnableOverflow, typename Allocator>
|
||||
inline typename fixed_list<T, nodeCount, bEnableOverflow, Allocator>::this_type&
|
||||
fixed_list<T, nodeCount, bEnableOverflow, Allocator>::operator=(const this_type& x)
|
||||
{
|
||||
if(this != &x)
|
||||
{
|
||||
base_type::clear();
|
||||
|
||||
#if EASTL_ALLOCATOR_COPY_ENABLED
|
||||
mAllocator = x.mAllocator;
|
||||
#endif
|
||||
|
||||
base_type::assign(x.begin(), x.end()); // It would probably be better to implement this like list::operator=.
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
template <typename T, size_t nodeCount, bool bEnableOverflow, typename Allocator>
|
||||
inline void fixed_list<T, nodeCount, bEnableOverflow, Allocator>::swap(this_type& x)
|
||||
{
|
||||
// Fixed containers use a special swap that can deal with excessively large buffers.
|
||||
eastl::fixed_swap(*this, x);
|
||||
}
|
||||
|
||||
|
||||
template <typename T, size_t nodeCount, bool bEnableOverflow, typename Allocator>
|
||||
inline void fixed_list<T, nodeCount, bEnableOverflow, Allocator>::reset()
|
||||
{
|
||||
base_type::reset();
|
||||
base_type::get_allocator().reset(mBuffer);
|
||||
}
|
||||
|
||||
|
||||
template <typename T, size_t nodeCount, bool bEnableOverflow, typename Allocator>
|
||||
inline typename fixed_list<T, nodeCount, bEnableOverflow, Allocator>::size_type
|
||||
fixed_list<T, nodeCount, bEnableOverflow, Allocator>::max_size() const
|
||||
{
|
||||
return kMaxSize;
|
||||
}
|
||||
|
||||
|
||||
template <typename T, size_t nodeCount, bool bEnableOverflow, typename Allocator>
|
||||
inline bool fixed_list<T, nodeCount, bEnableOverflow, Allocator>::has_overflowed() const
|
||||
{
|
||||
return !mAllocator.can_allocate();
|
||||
}
|
||||
|
||||
|
||||
template <typename T, size_t nodeCount, bool bEnableOverflow, typename Allocator>
|
||||
inline void fixed_list<T, nodeCount, bEnableOverflow, Allocator>::sort()
|
||||
{
|
||||
eastl::insertion_sort(base_type::begin(), base_type::end());
|
||||
}
|
||||
|
||||
|
||||
template <typename T, size_t nodeCount, bool bEnableOverflow, typename Allocator>
|
||||
template <typename Compare>
|
||||
inline void fixed_list<T, nodeCount, bEnableOverflow, Allocator>::sort(Compare compare)
|
||||
{
|
||||
eastl::insertion_sort(base_type::begin(), base_type::end(), compare);
|
||||
}
|
||||
|
||||
|
||||
template <typename T, size_t nodeCount, bool bEnableOverflow, typename Allocator>
|
||||
void fixed_list<T, nodeCount, bEnableOverflow, Allocator>::merge(this_type& /*x*/)
|
||||
{
|
||||
// To do.
|
||||
}
|
||||
|
||||
template <typename T, size_t nodeCount, bool bEnableOverflow, typename Allocator>
|
||||
template <typename Compare>
|
||||
void fixed_list<T, nodeCount, bEnableOverflow, Allocator>::merge(this_type& /*x*/, Compare /*compare*/)
|
||||
{
|
||||
// To do.
|
||||
}
|
||||
|
||||
template <typename T, size_t nodeCount, bool bEnableOverflow, typename Allocator>
|
||||
void fixed_list<T, nodeCount, bEnableOverflow, Allocator>::splice(iterator /*position*/, this_type& /*x*/)
|
||||
{
|
||||
// To do.
|
||||
}
|
||||
|
||||
template <typename T, size_t nodeCount, bool bEnableOverflow, typename Allocator>
|
||||
void fixed_list<T, nodeCount, bEnableOverflow, Allocator>::splice(iterator /*position*/, this_type& /*x*/, iterator /*i*/)
|
||||
{
|
||||
// To do.
|
||||
}
|
||||
|
||||
template <typename T, size_t nodeCount, bool bEnableOverflow, typename Allocator>
|
||||
void fixed_list<T, nodeCount, bEnableOverflow, Allocator>::splice(iterator /*position*/, this_type& /*x*/, iterator /*first*/, iterator /*last*/)
|
||||
{
|
||||
// To do.
|
||||
}
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// global operators
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <typename T, size_t nodeCount, bool bEnableOverflow, typename Allocator>
|
||||
inline void swap(fixed_list<T, nodeCount, bEnableOverflow, Allocator>& a,
|
||||
fixed_list<T, nodeCount, bEnableOverflow, Allocator>& b)
|
||||
{
|
||||
// Fixed containers use a special swap that can deal with excessively large buffers.
|
||||
eastl::fixed_swap(a, b);
|
||||
}
|
||||
|
||||
|
||||
} // namespace eastl
|
||||
|
||||
|
||||
#endif // Header include guard
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
358
lib/eastl/include/EASTL/fixed_map.h
Normal file
358
lib/eastl/include/EASTL/fixed_map.h
Normal file
|
@ -0,0 +1,358 @@
|
|||
/*
|
||||
Copyright (C) 2009-2010 Electronic Arts, Inc. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
3. Neither the name of Electronic Arts, Inc. ("EA") nor the names of
|
||||
its contributors may be used to endorse or promote products derived
|
||||
from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY ELECTRONIC ARTS AND ITS CONTRIBUTORS "AS IS" AND ANY
|
||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL ELECTRONIC ARTS OR ITS CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// EASTL/fixed_map.h
|
||||
//
|
||||
// Copyright (c) 2005, Electronic Arts. All rights reserved.
|
||||
// Written by Paul Pedriana.
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// This file implements a map and multimap which use a fixed size memory
|
||||
// pool for their nodes.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
#ifndef EASTL_FIXED_MAP_H
|
||||
#define EASTL_FIXED_MAP_H
|
||||
|
||||
|
||||
#include <EASTL/map.h>
|
||||
#include <EASTL/fixed_set.h> // Included because fixed_rbtree_base resides here.
|
||||
|
||||
|
||||
namespace eastl
|
||||
{
|
||||
/// EASTL_FIXED_MAP_DEFAULT_NAME
|
||||
///
|
||||
/// Defines a default container name in the absence of a user-provided name.
|
||||
/// In the case of fixed-size containers, the allocator name always refers
|
||||
/// to overflow allocations.
|
||||
///
|
||||
#ifndef EASTL_FIXED_MAP_DEFAULT_NAME
|
||||
#define EASTL_FIXED_MAP_DEFAULT_NAME EASTL_DEFAULT_NAME_PREFIX " fixed_map" // Unless the user overrides something, this is "EASTL fixed_map".
|
||||
#endif
|
||||
|
||||
#ifndef EASTL_FIXED_MULTIMAP_DEFAULT_NAME
|
||||
#define EASTL_FIXED_MULTIMAP_DEFAULT_NAME EASTL_DEFAULT_NAME_PREFIX " fixed_multimap" // Unless the user overrides something, this is "EASTL fixed_multimap".
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/// fixed_map
|
||||
///
|
||||
/// Implements a map with a fixed block of memory identified by the
|
||||
/// nodeCount template parameter.
|
||||
///
|
||||
/// Key The key object (key in the key/value pair).
|
||||
/// T The mapped object (value in the key/value pair).
|
||||
/// nodeCount The max number of objects to contain.
|
||||
/// bEnableOverflow Whether or not we should use the global heap if our object pool is exhausted.
|
||||
/// Compare Compare function/object for set ordering.
|
||||
/// Allocator Overflow allocator, which is only used if bEnableOverflow == true. Defaults to the global heap.
|
||||
///
|
||||
template <typename Key, typename T, size_t nodeCount, bool bEnableOverflow = true, typename Compare = eastl::less<Key>, typename Allocator = EASTLAllocatorType>
|
||||
class fixed_map : public map<Key, T, Compare, fixed_node_allocator<sizeof(typename map<Key, T>::node_type),
|
||||
nodeCount, map<Key, T>::kValueAlignment, map<Key, T>::kValueAlignmentOffset, bEnableOverflow, Allocator> >
|
||||
{
|
||||
public:
|
||||
typedef fixed_map<Key, T, nodeCount, bEnableOverflow, Compare, Allocator> this_type;
|
||||
typedef fixed_node_allocator<sizeof(typename map<Key, T>::node_type), nodeCount,
|
||||
map<Key, T>::kValueAlignment, map<Key, T>::kValueAlignmentOffset, bEnableOverflow, Allocator> fixed_allocator_type;
|
||||
typedef map<Key, T, Compare, fixed_allocator_type> base_type;
|
||||
typedef typename base_type::value_type value_type;
|
||||
typedef typename base_type::node_type node_type;
|
||||
typedef typename base_type::size_type size_type;
|
||||
|
||||
enum
|
||||
{
|
||||
kMaxSize = nodeCount
|
||||
};
|
||||
|
||||
using base_type::insert;
|
||||
|
||||
protected:
|
||||
char mBuffer[fixed_allocator_type::kBufferSize]; // kBufferSize will take into account alignment requirements.
|
||||
|
||||
using base_type::mAllocator;
|
||||
|
||||
public:
|
||||
/// fixed_map
|
||||
///
|
||||
fixed_map()
|
||||
: base_type(fixed_allocator_type(NULL))
|
||||
{
|
||||
#if EASTL_NAME_ENABLED
|
||||
mAllocator.set_name(EASTL_FIXED_MAP_DEFAULT_NAME);
|
||||
#endif
|
||||
|
||||
mAllocator.reset(mBuffer);
|
||||
}
|
||||
|
||||
|
||||
/// fixed_map
|
||||
///
|
||||
explicit fixed_map(const Compare& compare)
|
||||
: base_type(compare, fixed_allocator_type(NULL))
|
||||
{
|
||||
#if EASTL_NAME_ENABLED
|
||||
mAllocator.set_name(EASTL_FIXED_MAP_DEFAULT_NAME);
|
||||
#endif
|
||||
|
||||
mAllocator.reset(mBuffer);
|
||||
}
|
||||
|
||||
|
||||
/// fixed_map
|
||||
///
|
||||
fixed_map(const this_type& x)
|
||||
: base_type(x.mCompare, fixed_allocator_type(NULL))
|
||||
{
|
||||
#if EASTL_NAME_ENABLED
|
||||
mAllocator.set_name(x.mAllocator.get_name());
|
||||
#endif
|
||||
|
||||
mAllocator.reset(mBuffer);
|
||||
base_type::operator=(x);
|
||||
}
|
||||
|
||||
|
||||
/// fixed_map
|
||||
///
|
||||
template <typename InputIterator>
|
||||
fixed_map(InputIterator first, InputIterator last)
|
||||
: base_type(fixed_allocator_type(NULL))
|
||||
{
|
||||
#if EASTL_NAME_ENABLED
|
||||
mAllocator.set_name(EASTL_FIXED_MAP_DEFAULT_NAME);
|
||||
#endif
|
||||
|
||||
mAllocator.reset(mBuffer);
|
||||
insert(first, last);
|
||||
}
|
||||
|
||||
|
||||
/// operator=
|
||||
///
|
||||
this_type& operator=(const this_type& x)
|
||||
{
|
||||
base_type::operator=(x);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
void swap(this_type& x)
|
||||
{
|
||||
// Fixed containers use a special swap that can deal with excessively large buffers.
|
||||
eastl::fixed_swap(*this, x);
|
||||
}
|
||||
|
||||
|
||||
void reset()
|
||||
{
|
||||
base_type::reset();
|
||||
base_type::get_allocator().reset(mBuffer);
|
||||
}
|
||||
|
||||
|
||||
size_type max_size() const
|
||||
{
|
||||
return kMaxSize;
|
||||
}
|
||||
|
||||
}; // fixed_map
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// global operators
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <typename Key, typename T, size_t nodeCount, bool bEnableOverflow, typename Compare, typename Allocator>
|
||||
inline void swap(fixed_map<Key, T, nodeCount, bEnableOverflow, Compare, Allocator>& a,
|
||||
fixed_map<Key, T, nodeCount, bEnableOverflow, Compare, Allocator>& b)
|
||||
{
|
||||
// Fixed containers use a special swap that can deal with excessively large buffers.
|
||||
eastl::fixed_swap(a, b);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/// fixed_multimap
|
||||
///
|
||||
/// Implements a multimap with a fixed block of memory identified by the
|
||||
/// nodeCount template parameter.
|
||||
///
|
||||
/// Key The key object (key in the key/value pair).
|
||||
/// T The mapped object (value in the key/value pair).
|
||||
/// nodeCount The max number of objects to contain.
|
||||
/// bEnableOverflow Whether or not we should use the global heap if our object pool is exhausted.
|
||||
/// Compare Compare function/object for set ordering.
|
||||
/// Allocator Overflow allocator, which is only used if bEnableOverflow == true. Defaults to the global heap.
|
||||
///
|
||||
template <typename Key, typename T, size_t nodeCount, bool bEnableOverflow = true, typename Compare = eastl::less<Key>, typename Allocator = EASTLAllocatorType>
|
||||
class fixed_multimap : public multimap<Key, T, Compare, fixed_node_allocator<sizeof(typename multimap<Key, T>::node_type),
|
||||
nodeCount, multimap<Key, T>::kValueAlignment, multimap<Key, T>::kValueAlignmentOffset, bEnableOverflow, Allocator> >
|
||||
{
|
||||
public:
|
||||
typedef fixed_multimap<Key, T, nodeCount, bEnableOverflow, Compare, Allocator> this_type;
|
||||
typedef fixed_node_allocator<sizeof(typename multimap<Key, T>::node_type), nodeCount,
|
||||
multimap<Key, T>::kValueAlignment, multimap<Key, T>::kValueAlignmentOffset, bEnableOverflow, Allocator> fixed_allocator_type;
|
||||
typedef multimap<Key, T, Compare, fixed_allocator_type> base_type;
|
||||
typedef typename base_type::value_type value_type;
|
||||
typedef typename base_type::node_type node_type;
|
||||
typedef typename base_type::size_type size_type;
|
||||
|
||||
enum
|
||||
{
|
||||
kMaxSize = nodeCount
|
||||
};
|
||||
|
||||
using base_type::insert;
|
||||
|
||||
protected:
|
||||
char mBuffer[fixed_allocator_type::kBufferSize]; // kBufferSize will take into account alignment requirements.
|
||||
|
||||
using base_type::mAllocator;
|
||||
|
||||
public:
|
||||
/// fixed_multimap
|
||||
///
|
||||
fixed_multimap()
|
||||
: base_type(fixed_allocator_type(NULL))
|
||||
{
|
||||
#if EASTL_NAME_ENABLED
|
||||
mAllocator.set_name(EASTL_FIXED_MULTIMAP_DEFAULT_NAME);
|
||||
#endif
|
||||
|
||||
mAllocator.reset(mBuffer);
|
||||
}
|
||||
|
||||
|
||||
/// fixed_multimap
|
||||
///
|
||||
explicit fixed_multimap(const Compare& compare)
|
||||
: base_type(compare, fixed_allocator_type(mBuffer))
|
||||
{
|
||||
#if EASTL_NAME_ENABLED
|
||||
mAllocator.set_name(EASTL_FIXED_MULTIMAP_DEFAULT_NAME);
|
||||
#endif
|
||||
|
||||
mAllocator.reset(mBuffer);
|
||||
}
|
||||
|
||||
|
||||
/// fixed_multimap
|
||||
///
|
||||
fixed_multimap(const this_type& x)
|
||||
: base_type(x.mCompare, fixed_allocator_type(NULL))
|
||||
{
|
||||
#if EASTL_NAME_ENABLED
|
||||
mAllocator.set_name(x.mAllocator.get_name());
|
||||
#endif
|
||||
|
||||
mAllocator.reset(mBuffer);
|
||||
base_type::operator=(x);
|
||||
}
|
||||
|
||||
|
||||
/// fixed_multimap
|
||||
///
|
||||
template <typename InputIterator>
|
||||
fixed_multimap(InputIterator first, InputIterator last)
|
||||
: base_type(fixed_allocator_type(NULL))
|
||||
{
|
||||
#if EASTL_NAME_ENABLED
|
||||
mAllocator.set_name(EASTL_FIXED_MULTIMAP_DEFAULT_NAME);
|
||||
#endif
|
||||
|
||||
mAllocator.reset(mBuffer);
|
||||
insert(first, last);
|
||||
}
|
||||
|
||||
|
||||
/// operator=
|
||||
///
|
||||
this_type& operator=(const this_type& x)
|
||||
{
|
||||
base_type::operator=(x);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
void swap(this_type& x)
|
||||
{
|
||||
// Fixed containers use a special swap that can deal with excessively large buffers.
|
||||
eastl::fixed_swap(*this, x);
|
||||
}
|
||||
|
||||
|
||||
void reset()
|
||||
{
|
||||
base_type::reset();
|
||||
base_type::get_allocator().reset(mBuffer);
|
||||
}
|
||||
|
||||
|
||||
size_type max_size() const
|
||||
{
|
||||
return kMaxSize;
|
||||
}
|
||||
|
||||
}; // fixed_multimap
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// global operators
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <typename Key, typename T, size_t nodeCount, bool bEnableOverflow, typename Compare, typename Allocator>
|
||||
inline void swap(fixed_multimap<Key, T, nodeCount, bEnableOverflow, Compare, Allocator>& a,
|
||||
fixed_multimap<Key, T, nodeCount, bEnableOverflow, Compare, Allocator>& b)
|
||||
{
|
||||
// Fixed containers use a special swap that can deal with excessively large buffers.
|
||||
eastl::fixed_swap(a, b);
|
||||
}
|
||||
|
||||
|
||||
} // namespace eastl
|
||||
|
||||
|
||||
#endif // Header include guard
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
360
lib/eastl/include/EASTL/fixed_set.h
Normal file
360
lib/eastl/include/EASTL/fixed_set.h
Normal file
|
@ -0,0 +1,360 @@
|
|||
/*
|
||||
Copyright (C) 2009-2010 Electronic Arts, Inc. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
3. Neither the name of Electronic Arts, Inc. ("EA") nor the names of
|
||||
its contributors may be used to endorse or promote products derived
|
||||
from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY ELECTRONIC ARTS AND ITS CONTRIBUTORS "AS IS" AND ANY
|
||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL ELECTRONIC ARTS OR ITS CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// EASTL/fixed_set.h
|
||||
//
|
||||
// Copyright (c) 2005, Electronic Arts. All rights reserved.
|
||||
// Written by Paul Pedriana.
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// This file implements a set and multiset which use a fixed size memory
|
||||
// pool for their nodes.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
#ifndef EASTL_FIXED_SET_H
|
||||
#define EASTL_FIXED_SET_H
|
||||
|
||||
|
||||
#include <EASTL/set.h>
|
||||
#include <EASTL/internal/fixed_pool.h>
|
||||
|
||||
|
||||
namespace eastl
|
||||
{
|
||||
/// EASTL_FIXED_SET_DEFAULT_NAME
|
||||
///
|
||||
/// Defines a default container name in the absence of a user-provided name.
|
||||
/// In the case of fixed-size containers, the allocator name always refers
|
||||
/// to overflow allocations.
|
||||
///
|
||||
#ifndef EASTL_FIXED_SET_DEFAULT_NAME
|
||||
#define EASTL_FIXED_SET_DEFAULT_NAME EASTL_DEFAULT_NAME_PREFIX " fixed_set" // Unless the user overrides something, this is "EASTL fixed_set".
|
||||
#endif
|
||||
|
||||
#ifndef EASTL_FIXED_MULTISET_DEFAULT_NAME
|
||||
#define EASTL_FIXED_MULTISET_DEFAULT_NAME EASTL_DEFAULT_NAME_PREFIX " fixed_multiset" // Unless the user overrides something, this is "EASTL fixed_multiset".
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/// fixed_set
|
||||
///
|
||||
/// Implements a set with a fixed block of memory identified by the
|
||||
/// nodeCount template parameter.
|
||||
///
|
||||
/// Template parameters:
|
||||
/// Key The type of object the set holds (a.k.a. value).
|
||||
/// nodeCount The max number of objects to contain.
|
||||
/// bEnableOverflow Whether or not we should use the global heap if our object pool is exhausted.
|
||||
/// Compare Compare function/object for set ordering.
|
||||
/// Allocator Overflow allocator, which is only used if bEnableOverflow == true. Defaults to the global heap.
|
||||
///
|
||||
template <typename Key, size_t nodeCount, bool bEnableOverflow = true, typename Compare = eastl::less<Key>, typename Allocator = EASTLAllocatorType>
|
||||
class fixed_set : public set<Key, Compare, fixed_node_allocator<sizeof(typename set<Key>::node_type),
|
||||
nodeCount, set<Key>::kValueAlignment, set<Key>::kValueAlignmentOffset, bEnableOverflow, Allocator> >
|
||||
{
|
||||
public:
|
||||
typedef fixed_set<Key, nodeCount, bEnableOverflow, Compare, Allocator> this_type;
|
||||
typedef fixed_node_allocator<sizeof(typename set<Key>::node_type), nodeCount,
|
||||
set<Key>::kValueAlignment, set<Key>::kValueAlignmentOffset, bEnableOverflow, Allocator> fixed_allocator_type;
|
||||
typedef set<Key, Compare, fixed_allocator_type> base_type;
|
||||
typedef typename base_type::node_type node_type;
|
||||
typedef typename base_type::size_type size_type;
|
||||
|
||||
enum
|
||||
{
|
||||
kMaxSize = nodeCount
|
||||
};
|
||||
|
||||
using base_type::insert;
|
||||
|
||||
protected:
|
||||
char mBuffer[fixed_allocator_type::kBufferSize]; // kBufferSize will take into account alignment requirements.
|
||||
|
||||
using base_type::mAllocator;
|
||||
|
||||
public:
|
||||
/// fixed_set
|
||||
///
|
||||
fixed_set()
|
||||
: base_type(fixed_allocator_type(NULL))
|
||||
{
|
||||
#if EASTL_NAME_ENABLED
|
||||
mAllocator.set_name(EASTL_FIXED_SET_DEFAULT_NAME);
|
||||
#endif
|
||||
|
||||
mAllocator.reset(mBuffer);
|
||||
}
|
||||
|
||||
|
||||
/// fixed_set
|
||||
///
|
||||
explicit fixed_set(const Compare& compare)
|
||||
: base_type(compare, fixed_allocator_type(NULL))
|
||||
{
|
||||
#if EASTL_NAME_ENABLED
|
||||
mAllocator.set_name(EASTL_FIXED_SET_DEFAULT_NAME);
|
||||
#endif
|
||||
|
||||
mAllocator.reset(mBuffer);
|
||||
}
|
||||
|
||||
|
||||
/// fixed_set
|
||||
///
|
||||
fixed_set(const this_type& x)
|
||||
: base_type(x.mCompare, fixed_allocator_type(NULL))
|
||||
{
|
||||
#if EASTL_NAME_ENABLED
|
||||
mAllocator.set_name(x.mAllocator.get_name());
|
||||
#endif
|
||||
|
||||
mAllocator.reset(mBuffer);
|
||||
base_type::operator=(x);
|
||||
}
|
||||
|
||||
|
||||
/// fixed_set
|
||||
///
|
||||
template <typename InputIterator>
|
||||
fixed_set(InputIterator first, InputIterator last)
|
||||
: base_type(fixed_allocator_type(NULL))
|
||||
{
|
||||
#if EASTL_NAME_ENABLED
|
||||
mAllocator.set_name(EASTL_FIXED_SET_DEFAULT_NAME);
|
||||
#endif
|
||||
|
||||
mAllocator.reset(mBuffer);
|
||||
insert(first, last);
|
||||
}
|
||||
|
||||
|
||||
/// operator=
|
||||
///
|
||||
this_type& operator=(const this_type& x)
|
||||
{
|
||||
base_type::operator=(x);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
void swap(this_type& x)
|
||||
{
|
||||
// Fixed containers use a special swap that can deal with excessively large buffers.
|
||||
eastl::fixed_swap(*this, x);
|
||||
}
|
||||
|
||||
|
||||
void reset()
|
||||
{
|
||||
base_type::reset();
|
||||
base_type::get_allocator().reset(mBuffer);
|
||||
}
|
||||
|
||||
|
||||
size_type max_size() const
|
||||
{
|
||||
return kMaxSize;
|
||||
}
|
||||
|
||||
}; // fixed_set
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// global operators
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <typename Key, size_t nodeCount, bool bEnableOverflow, typename Compare, typename Allocator>
|
||||
inline void swap(fixed_set<Key, nodeCount, bEnableOverflow, Compare, Allocator>& a,
|
||||
fixed_set<Key, nodeCount, bEnableOverflow, Compare, Allocator>& b)
|
||||
{
|
||||
// Fixed containers use a special swap that can deal with excessively large buffers.
|
||||
eastl::fixed_swap(a, b);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/// fixed_multiset
|
||||
///
|
||||
/// Implements a multiset with a fixed block of memory identified by the
|
||||
/// nodeCount template parameter.
|
||||
///
|
||||
/// Key The type of object the set holds (a.k.a. value).
|
||||
/// nodeCount The max number of objects to contain.
|
||||
/// bEnableOverflow Whether or not we should use the global heap if our object pool is exhausted.
|
||||
/// Compare Compare function/object for set ordering.
|
||||
/// Allocator Overflow allocator, which is only used if bEnableOverflow == true. Defaults to the global heap.
|
||||
///
|
||||
template <typename Key, size_t nodeCount, bool bEnableOverflow = true, typename Compare = eastl::less<Key>, typename Allocator = EASTLAllocatorType>
|
||||
class fixed_multiset : public multiset<Key, Compare, fixed_node_allocator<sizeof(typename multiset<Key>::node_type),
|
||||
nodeCount, multiset<Key>::kValueAlignment, multiset<Key>::kValueAlignmentOffset, bEnableOverflow, Allocator> >
|
||||
{
|
||||
public:
|
||||
typedef fixed_multiset<Key, nodeCount, bEnableOverflow, Compare, Allocator> this_type;
|
||||
typedef fixed_node_allocator<sizeof(typename multiset<Key>::node_type), nodeCount,
|
||||
multiset<Key>::kValueAlignment, multiset<Key>::kValueAlignmentOffset, bEnableOverflow, Allocator> fixed_allocator_type;
|
||||
typedef multiset<Key, Compare, fixed_allocator_type> base_type;
|
||||
typedef typename base_type::node_type node_type;
|
||||
typedef typename base_type::size_type size_type;
|
||||
|
||||
enum
|
||||
{
|
||||
kMaxSize = nodeCount
|
||||
};
|
||||
|
||||
using base_type::insert;
|
||||
|
||||
protected:
|
||||
char mBuffer[fixed_allocator_type::kBufferSize]; // kBufferSize will take into account alignment requirements.
|
||||
|
||||
using base_type::mAllocator;
|
||||
|
||||
public:
|
||||
/// fixed_multiset
|
||||
///
|
||||
fixed_multiset()
|
||||
: base_type(fixed_allocator_type(NULL))
|
||||
{
|
||||
#if EASTL_NAME_ENABLED
|
||||
mAllocator.set_name(EASTL_FIXED_MULTISET_DEFAULT_NAME);
|
||||
#endif
|
||||
|
||||
mAllocator.reset(mBuffer);
|
||||
}
|
||||
|
||||
|
||||
/// fixed_multiset
|
||||
///
|
||||
explicit fixed_multiset(const Compare& compare)
|
||||
: base_type(compare, fixed_allocator_type(NULL))
|
||||
{
|
||||
#if EASTL_NAME_ENABLED
|
||||
mAllocator.set_name(EASTL_FIXED_MULTISET_DEFAULT_NAME);
|
||||
#endif
|
||||
|
||||
mAllocator.reset(mBuffer);
|
||||
}
|
||||
|
||||
|
||||
/// fixed_multiset
|
||||
///
|
||||
fixed_multiset(const this_type& x)
|
||||
: base_type(x.mCompare, fixed_allocator_type(NULL))
|
||||
{
|
||||
#if EASTL_NAME_ENABLED
|
||||
mAllocator.set_name(x.mAllocator.get_name());
|
||||
#endif
|
||||
|
||||
mAllocator.reset(mBuffer);
|
||||
base_type::operator=(x);
|
||||
}
|
||||
|
||||
|
||||
/// fixed_multiset
|
||||
///
|
||||
template <typename InputIterator>
|
||||
fixed_multiset(InputIterator first, InputIterator last)
|
||||
: base_type(fixed_allocator_type(NULL))
|
||||
{
|
||||
#if EASTL_NAME_ENABLED
|
||||
mAllocator.set_name(EASTL_FIXED_MULTISET_DEFAULT_NAME);
|
||||
#endif
|
||||
|
||||
mAllocator.reset(mBuffer);
|
||||
insert(first, last);
|
||||
}
|
||||
|
||||
|
||||
/// operator=
|
||||
///
|
||||
this_type& operator=(const this_type& x)
|
||||
{
|
||||
base_type::operator=(x);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
void swap(this_type& x)
|
||||
{
|
||||
// Fixed containers use a special swap that can deal with excessively large buffers.
|
||||
eastl::fixed_swap(*this, x);
|
||||
}
|
||||
|
||||
|
||||
void reset()
|
||||
{
|
||||
base_type::reset();
|
||||
base_type::get_allocator().reset(mBuffer);
|
||||
}
|
||||
|
||||
|
||||
size_type max_size() const
|
||||
{
|
||||
return kMaxSize;
|
||||
}
|
||||
|
||||
}; // fixed_multiset
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// global operators
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <typename Key, size_t nodeCount, bool bEnableOverflow, typename Compare, typename Allocator>
|
||||
inline void swap(fixed_multiset<Key, nodeCount, bEnableOverflow, Compare, Allocator>& a,
|
||||
fixed_multiset<Key, nodeCount, bEnableOverflow, Compare, Allocator>& b)
|
||||
{
|
||||
// Fixed containers use a special swap that can deal with excessively large buffers.
|
||||
eastl::fixed_swap(a, b);
|
||||
}
|
||||
|
||||
|
||||
|
||||
} // namespace eastl
|
||||
|
||||
|
||||
#endif // Header include guard
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
539
lib/eastl/include/EASTL/fixed_string.h
Normal file
539
lib/eastl/include/EASTL/fixed_string.h
Normal file
|
@ -0,0 +1,539 @@
|
|||
/*
|
||||
Copyright (C) 2009-2010 Electronic Arts, Inc. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
3. Neither the name of Electronic Arts, Inc. ("EA") nor the names of
|
||||
its contributors may be used to endorse or promote products derived
|
||||
from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY ELECTRONIC ARTS AND ITS CONTRIBUTORS "AS IS" AND ANY
|
||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL ELECTRONIC ARTS OR ITS CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// EASTL/fixed_string.h
|
||||
//
|
||||
// Copyright (c) 2005, Electronic Arts. All rights reserved.
|
||||
// Written and maintained by Paul Pedriana.
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// This file implements a string which uses a fixed size memory pool.
|
||||
// The bEnableOverflow template parameter allows the container to resort to
|
||||
// heap allocations if the memory pool is exhausted.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
#ifndef EASTL_FIXED_STRING_H
|
||||
#define EASTL_FIXED_STRING_H
|
||||
|
||||
|
||||
#include <EASTL/internal/config.h>
|
||||
#if EASTL_ABSTRACT_STRING_ENABLED
|
||||
#include <EASTL/bonus/fixed_string_abstract.h>
|
||||
#else // 'else' encompasses the entire rest of this file.
|
||||
#include <EASTL/string.h>
|
||||
#include <EASTL/internal/fixed_pool.h>
|
||||
|
||||
|
||||
|
||||
namespace eastl
|
||||
{
|
||||
/// EASTL_FIXED_STRING_DEFAULT_NAME
|
||||
///
|
||||
/// Defines a default container name in the absence of a user-provided name.
|
||||
/// In the case of fixed-size containers, the allocator name always refers
|
||||
/// to overflow allocations.
|
||||
///
|
||||
#ifndef EASTL_FIXED_STRING_DEFAULT_NAME
|
||||
#define EASTL_FIXED_STRING_DEFAULT_NAME EASTL_DEFAULT_NAME_PREFIX " fixed_string" // Unless the user overrides something, this is "EASTL fixed_string".
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/// fixed_string
|
||||
///
|
||||
/// A fixed_string with bEnableOverflow == true is identical to a regular
|
||||
/// string in terms of its behavior. All the expectations of regular string
|
||||
/// apply to it and no additional expectations come from it. When bEnableOverflow
|
||||
/// is false, fixed_string behaves like regular string with the exception that
|
||||
/// its capacity can never increase. All operations you do on such a fixed_string
|
||||
/// which require a capacity increase will result in undefined behavior or an
|
||||
/// C++ allocation exception, depending on the configuration of EASTL.
|
||||
///
|
||||
/// Note: The nodeCount value is the amount of characters to allocate, which needs to
|
||||
/// take into account a terminating zero. Thus if you want to store strings with a strlen
|
||||
/// of 30, the nodeCount value must be at least 31.
|
||||
///
|
||||
/// Template parameters:
|
||||
/// T The type of object the string holds (char, wchar_t, char8_t, char16_t, char32_t).
|
||||
/// nodeCount The max number of objects to contain.
|
||||
/// bEnableOverflow Whether or not we should use the overflow heap if our object pool is exhausted.
|
||||
/// Allocator Overflow allocator, which is only used if bEnableOverflow == true. Defaults to the global heap.
|
||||
///
|
||||
/// Notes:
|
||||
/// The nodeCount value must be at least 2, one for a character and one for a terminating 0.
|
||||
///
|
||||
/// As of this writing, the string class necessarily reallocates when an insert of
|
||||
/// self is done into self. As a result, the fixed_string class doesn't support
|
||||
/// inserting self into self unless the bEnableOverflow template parameter is true.
|
||||
///
|
||||
/// Example usage:
|
||||
/// fixed_string<char, 128 + 1, true> fixedString("hello world"); // Can hold up to a strlen of 128.
|
||||
///
|
||||
/// fixedString = "hola mundo";
|
||||
/// fixedString.clear();
|
||||
/// fixedString.resize(200);
|
||||
/// fixedString.sprintf("%f", 1.5f);
|
||||
///
|
||||
template <typename T, int nodeCount, bool bEnableOverflow = true, typename Allocator = EASTLAllocatorType>
|
||||
class fixed_string : public basic_string<T, fixed_vector_allocator<sizeof(T), nodeCount, basic_string<T>::kAlignment, basic_string<T>::kAlignmentOffset, bEnableOverflow, Allocator> >
|
||||
{
|
||||
public:
|
||||
typedef fixed_vector_allocator<sizeof(T), nodeCount, basic_string<T>::kAlignment,
|
||||
basic_string<T>::kAlignmentOffset, bEnableOverflow, Allocator> fixed_allocator_type;
|
||||
typedef typename fixed_allocator_type::overflow_allocator_type overflow_allocator_type;
|
||||
typedef basic_string<T, fixed_allocator_type> base_type;
|
||||
typedef fixed_string<T, nodeCount, bEnableOverflow, Allocator> this_type;
|
||||
typedef typename base_type::size_type size_type;
|
||||
typedef typename base_type::value_type value_type;
|
||||
typedef typename base_type::CtorDoNotInitialize CtorDoNotInitialize;
|
||||
typedef typename base_type::CtorSprintf CtorSprintf;
|
||||
typedef aligned_buffer<nodeCount * sizeof(T), basic_string<T>::kAlignment> aligned_buffer_type;
|
||||
|
||||
enum
|
||||
{
|
||||
kMaxSize = nodeCount - 1 // -1 because we need to save one element for the silent terminating null.
|
||||
};
|
||||
|
||||
using base_type::mAllocator;
|
||||
using base_type::npos;
|
||||
using base_type::mpBegin;
|
||||
using base_type::mpEnd;
|
||||
using base_type::mpCapacity;
|
||||
using base_type::append;
|
||||
using base_type::resize;
|
||||
using base_type::clear;
|
||||
using base_type::size;
|
||||
using base_type::sprintf_va_list;
|
||||
|
||||
protected:
|
||||
union // We define a union in order to avoid strict pointer aliasing issues with compilers like GCC.
|
||||
{
|
||||
value_type mArray[1];
|
||||
aligned_buffer_type mBuffer; // Question: Why are we doing this aligned_buffer thing? Why not just do an array of value_type, given that we are using just strings of char types.
|
||||
};
|
||||
|
||||
public:
|
||||
fixed_string();
|
||||
fixed_string(const base_type& x, size_type position, size_type n = base_type::npos);
|
||||
fixed_string(const value_type* p, size_type n);
|
||||
fixed_string(const value_type* p);
|
||||
fixed_string(size_type n, const value_type& value);
|
||||
fixed_string(const this_type& x);
|
||||
fixed_string(const base_type& x);
|
||||
fixed_string(const value_type* pBegin, const value_type* pEnd);
|
||||
fixed_string(CtorDoNotInitialize, size_type n);
|
||||
fixed_string(CtorSprintf, const value_type* pFormat, ...);
|
||||
|
||||
this_type& operator=(const this_type& x);
|
||||
this_type& operator=(const base_type& x);
|
||||
this_type& operator=(const value_type* p);
|
||||
this_type& operator=(const value_type c);
|
||||
|
||||
void swap(this_type& x);
|
||||
|
||||
void set_capacity(size_type n);
|
||||
void reset();
|
||||
size_type max_size() const;
|
||||
|
||||
// The inherited versions of substr/left/right call the basic_string constructor,
|
||||
// which will call the overflow allocator and fail if bEnableOverflow == false
|
||||
this_type substr(size_type position, size_type n) const;
|
||||
this_type left(size_type n) const;
|
||||
this_type right(size_type n) const;
|
||||
|
||||
// Allocator
|
||||
overflow_allocator_type& get_overflow_allocator();
|
||||
void set_overflow_allocator(const overflow_allocator_type& allocator);
|
||||
|
||||
}; // fixed_string
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// fixed_string
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <typename T, int nodeCount, bool bEnableOverflow, typename Allocator>
|
||||
inline fixed_string<T, nodeCount, bEnableOverflow, Allocator>::
|
||||
fixed_string()
|
||||
: base_type(fixed_allocator_type(mBuffer.buffer))
|
||||
{
|
||||
mpBegin = mpEnd = mArray;
|
||||
mpCapacity = mpBegin + nodeCount;
|
||||
*mpBegin = 0;
|
||||
|
||||
#if EASTL_NAME_ENABLED
|
||||
mAllocator.set_name(EASTL_FIXED_STRING_DEFAULT_NAME);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
template <typename T, int nodeCount, bool bEnableOverflow, typename Allocator>
|
||||
inline fixed_string<T, nodeCount, bEnableOverflow, Allocator>::
|
||||
fixed_string(const this_type& x)
|
||||
: base_type(fixed_allocator_type(mBuffer.buffer))
|
||||
{
|
||||
mpBegin = mpEnd = mArray;
|
||||
mpCapacity = mpBegin + nodeCount;
|
||||
*mpBegin = 0;
|
||||
|
||||
#if EASTL_NAME_ENABLED
|
||||
mAllocator.set_name(x.mAllocator.get_name());
|
||||
#endif
|
||||
|
||||
append(x);
|
||||
}
|
||||
|
||||
|
||||
template <typename T, int nodeCount, bool bEnableOverflow, typename Allocator>
|
||||
inline fixed_string<T, nodeCount, bEnableOverflow, Allocator>::
|
||||
fixed_string(const base_type& x)
|
||||
: base_type(fixed_allocator_type(mBuffer.buffer))
|
||||
{
|
||||
mpBegin = mpEnd = mArray;
|
||||
mpCapacity = mpBegin + nodeCount;
|
||||
*mpBegin = 0;
|
||||
|
||||
#if EASTL_NAME_ENABLED
|
||||
mAllocator.set_name(x.get_allocator().get_name());
|
||||
#endif
|
||||
|
||||
append(x);
|
||||
}
|
||||
|
||||
|
||||
template <typename T, int nodeCount, bool bEnableOverflow, typename Allocator>
|
||||
inline fixed_string<T, nodeCount, bEnableOverflow, Allocator>::
|
||||
fixed_string(const base_type& x, size_type position, size_type n)
|
||||
: base_type(fixed_allocator_type(mBuffer.buffer))
|
||||
{
|
||||
mpBegin = mpEnd = mArray;
|
||||
mpCapacity = mpBegin + nodeCount;
|
||||
*mpBegin = 0;
|
||||
|
||||
#if EASTL_NAME_ENABLED
|
||||
mAllocator.set_name(x.get_allocator().get_name());
|
||||
#endif
|
||||
|
||||
append(x, position, n);
|
||||
}
|
||||
|
||||
|
||||
template <typename T, int nodeCount, bool bEnableOverflow, typename Allocator>
|
||||
inline fixed_string<T, nodeCount, bEnableOverflow, Allocator>::
|
||||
fixed_string(const value_type* p, size_type n)
|
||||
: base_type(fixed_allocator_type(mBuffer.buffer))
|
||||
{
|
||||
mpBegin = mpEnd = mArray;
|
||||
mpCapacity = mpBegin + nodeCount;
|
||||
*mpBegin = 0;
|
||||
|
||||
#if EASTL_NAME_ENABLED
|
||||
mAllocator.set_name(EASTL_FIXED_STRING_DEFAULT_NAME);
|
||||
#endif
|
||||
|
||||
append(p, n);
|
||||
}
|
||||
|
||||
|
||||
template <typename T, int nodeCount, bool bEnableOverflow, typename Allocator>
|
||||
inline fixed_string<T, nodeCount, bEnableOverflow, Allocator>::
|
||||
fixed_string(const value_type* p)
|
||||
: base_type(fixed_allocator_type(mBuffer.buffer))
|
||||
{
|
||||
mpBegin = mpEnd = mArray;
|
||||
mpCapacity = mpBegin + nodeCount;
|
||||
*mpBegin = 0;
|
||||
|
||||
#if EASTL_NAME_ENABLED
|
||||
mAllocator.set_name(EASTL_FIXED_STRING_DEFAULT_NAME);
|
||||
#endif
|
||||
|
||||
append(p); // There better be enough space to hold the assigned string.
|
||||
}
|
||||
|
||||
|
||||
template <typename T, int nodeCount, bool bEnableOverflow, typename Allocator>
|
||||
inline fixed_string<T, nodeCount, bEnableOverflow, Allocator>::
|
||||
fixed_string(size_type n, const value_type& value)
|
||||
: base_type(fixed_allocator_type(mBuffer.buffer))
|
||||
{
|
||||
mpBegin = mpEnd = mArray;
|
||||
mpCapacity = mpBegin + nodeCount;
|
||||
*mpBegin = 0;
|
||||
|
||||
#if EASTL_NAME_ENABLED
|
||||
mAllocator.set_name(EASTL_FIXED_STRING_DEFAULT_NAME);
|
||||
#endif
|
||||
|
||||
append(n, value); // There better be enough space to hold the assigned string.
|
||||
}
|
||||
|
||||
|
||||
template <typename T, int nodeCount, bool bEnableOverflow, typename Allocator>
|
||||
inline fixed_string<T, nodeCount, bEnableOverflow, Allocator>::
|
||||
fixed_string(const value_type* pBegin, const value_type* pEnd)
|
||||
: base_type(fixed_allocator_type(mBuffer.buffer))
|
||||
{
|
||||
mpBegin = mpEnd = mArray;
|
||||
mpCapacity = mpBegin + nodeCount;
|
||||
*mpBegin = 0;
|
||||
|
||||
#if EASTL_NAME_ENABLED
|
||||
mAllocator.set_name(EASTL_FIXED_STRING_DEFAULT_NAME);
|
||||
#endif
|
||||
|
||||
append(pBegin, pEnd);
|
||||
}
|
||||
|
||||
|
||||
template <typename T, int nodeCount, bool bEnableOverflow, typename Allocator>
|
||||
inline fixed_string<T, nodeCount, bEnableOverflow, Allocator>::
|
||||
fixed_string(CtorDoNotInitialize, size_type n)
|
||||
: base_type(fixed_allocator_type(mBuffer.buffer))
|
||||
{
|
||||
#if EASTL_NAME_ENABLED
|
||||
mAllocator.set_name(EASTL_FIXED_STRING_DEFAULT_NAME);
|
||||
#endif
|
||||
|
||||
mpBegin = mArray;
|
||||
mpCapacity = mpBegin + nodeCount;
|
||||
|
||||
if((mpBegin + n) < mpCapacity)
|
||||
{
|
||||
mpEnd = mpBegin + n;
|
||||
*mpEnd = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
mpEnd = mArray;
|
||||
*mpEnd = 0;
|
||||
resize(n);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template <typename T, int nodeCount, bool bEnableOverflow, typename Allocator>
|
||||
inline fixed_string<T, nodeCount, bEnableOverflow, Allocator>::
|
||||
fixed_string(CtorSprintf, const value_type* pFormat, ...)
|
||||
: base_type(fixed_allocator_type(mBuffer.buffer))
|
||||
{
|
||||
mpBegin = mpEnd = mArray;
|
||||
mpCapacity = mpBegin + nodeCount;
|
||||
*mpBegin = 0;
|
||||
|
||||
#if EASTL_NAME_ENABLED
|
||||
mAllocator.set_name(EASTL_FIXED_STRING_DEFAULT_NAME);
|
||||
#endif
|
||||
|
||||
va_list arguments;
|
||||
va_start(arguments, pFormat);
|
||||
sprintf_va_list(pFormat, arguments);
|
||||
va_end(arguments);
|
||||
}
|
||||
|
||||
|
||||
template <typename T, int nodeCount, bool bEnableOverflow, typename Allocator>
|
||||
inline typename fixed_string<T, nodeCount, bEnableOverflow, Allocator>::this_type&
|
||||
fixed_string<T, nodeCount, bEnableOverflow, Allocator>::operator=(const this_type& x)
|
||||
{
|
||||
if(this != &x)
|
||||
{
|
||||
clear();
|
||||
append(x);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
template <typename T, int nodeCount, bool bEnableOverflow, typename Allocator>
|
||||
inline typename fixed_string<T, nodeCount, bEnableOverflow, Allocator>::
|
||||
this_type& fixed_string<T, nodeCount, bEnableOverflow, Allocator>::operator=(const base_type& x)
|
||||
{
|
||||
if(static_cast<base_type*>(this) != &x)
|
||||
{
|
||||
clear();
|
||||
append(x);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
template <typename T, int nodeCount, bool bEnableOverflow, typename Allocator>
|
||||
inline typename fixed_string<T, nodeCount, bEnableOverflow, Allocator>::
|
||||
this_type& fixed_string<T, nodeCount, bEnableOverflow, Allocator>::operator=(const value_type* p)
|
||||
{
|
||||
if(mpBegin != p)
|
||||
{
|
||||
clear();
|
||||
append(p);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
template <typename T, int nodeCount, bool bEnableOverflow, typename Allocator>
|
||||
inline typename fixed_string<T, nodeCount, bEnableOverflow, Allocator>::
|
||||
this_type& fixed_string<T, nodeCount, bEnableOverflow, Allocator>::operator=(const value_type c)
|
||||
{
|
||||
clear();
|
||||
append((size_type)1, c);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
template <typename T, int nodeCount, bool bEnableOverflow, typename Allocator>
|
||||
inline void fixed_string<T, nodeCount, bEnableOverflow, Allocator>::
|
||||
swap(this_type& x)
|
||||
{
|
||||
// Fixed containers use a special swap that can deal with excessively large buffers.
|
||||
eastl::fixed_swap(*this, x);
|
||||
}
|
||||
|
||||
|
||||
template <typename T, int nodeCount, bool bEnableOverflow, typename Allocator>
|
||||
inline void fixed_string<T, nodeCount, bEnableOverflow, Allocator>::
|
||||
set_capacity(size_type n)
|
||||
{
|
||||
// We act consistently with vector::set_capacity and reduce our
|
||||
// size if the new capacity is smaller than our size.
|
||||
if(n < size())
|
||||
resize(n);
|
||||
// To consider: If bEnableOverflow is true, then perhaps we should
|
||||
// switch to the overflow allocator and set the capacity.
|
||||
}
|
||||
|
||||
|
||||
template <typename T, int nodeCount, bool bEnableOverflow, typename Allocator>
|
||||
inline void fixed_string<T, nodeCount, bEnableOverflow, Allocator>::
|
||||
reset()
|
||||
{
|
||||
mpBegin = mpEnd = mArray;
|
||||
mpCapacity = mpBegin + nodeCount;
|
||||
}
|
||||
|
||||
|
||||
template <typename T, int nodeCount, bool bEnableOverflow, typename Allocator>
|
||||
inline typename fixed_string<T, nodeCount, bEnableOverflow, Allocator>::
|
||||
size_type fixed_string<T, nodeCount, bEnableOverflow, Allocator>::max_size() const
|
||||
{
|
||||
return kMaxSize;
|
||||
}
|
||||
|
||||
|
||||
template <typename T, int nodeCount, bool bEnableOverflow, typename Allocator>
|
||||
inline typename fixed_string<T, nodeCount, bEnableOverflow, Allocator>::
|
||||
this_type fixed_string<T, nodeCount, bEnableOverflow, Allocator>::substr(size_type position, size_type n) const
|
||||
{
|
||||
#if EASTL_STRING_OPT_RANGE_ERRORS
|
||||
if(position > (size_type)(mpEnd - mpBegin))
|
||||
ThrowRangeException();
|
||||
#endif
|
||||
|
||||
return fixed_string(mpBegin + position, mpBegin + position + eastl::min_alt(n, (size_type)(mpEnd - mpBegin) - position));
|
||||
}
|
||||
|
||||
|
||||
template <typename T, int nodeCount, bool bEnableOverflow, typename Allocator>
|
||||
inline typename fixed_string<T, nodeCount, bEnableOverflow, Allocator>::
|
||||
this_type fixed_string<T, nodeCount, bEnableOverflow, Allocator>::left(size_type n) const
|
||||
{
|
||||
const size_type nLength = size();
|
||||
if(n < nLength)
|
||||
return fixed_string(mpBegin, mpBegin + n);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
template <typename T, int nodeCount, bool bEnableOverflow, typename Allocator>
|
||||
inline typename fixed_string<T, nodeCount, bEnableOverflow, Allocator>::
|
||||
this_type fixed_string<T, nodeCount, bEnableOverflow, Allocator>::right(size_type n) const
|
||||
{
|
||||
const size_type nLength = size();
|
||||
if(n < nLength)
|
||||
return fixed_string(mpEnd - n, mpEnd);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
template <typename T, int nodeCount, bool bEnableOverflow, typename Allocator>
|
||||
inline typename fixed_string<T, nodeCount, bEnableOverflow, Allocator>::
|
||||
overflow_allocator_type& fixed_string<T, nodeCount, bEnableOverflow, Allocator>::get_overflow_allocator()
|
||||
{
|
||||
return mAllocator.get_overflow_allocator();
|
||||
}
|
||||
|
||||
|
||||
template <typename T, int nodeCount, bool bEnableOverflow, typename Allocator>
|
||||
inline void
|
||||
fixed_string<T, nodeCount, bEnableOverflow, Allocator>::set_overflow_allocator(const overflow_allocator_type& allocator)
|
||||
{
|
||||
mAllocator.set_overflow_allocator(allocator);
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// global operators
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
|
||||
// operator ==, !=, <, >, <=, >= come from the string implementations.
|
||||
|
||||
template <typename T, int nodeCount, bool bEnableOverflow, typename Allocator>
|
||||
inline void swap(fixed_string<T, nodeCount, bEnableOverflow, Allocator>& a,
|
||||
fixed_string<T, nodeCount, bEnableOverflow, Allocator>& b)
|
||||
{
|
||||
// Fixed containers use a special swap that can deal with excessively large buffers.
|
||||
eastl::fixed_swap(a, b);
|
||||
}
|
||||
|
||||
|
||||
} // namespace eastl
|
||||
|
||||
|
||||
#endif // EASTL_ABSTRACT_STRING_ENABLED
|
||||
|
||||
#endif // Header include guard
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
300
lib/eastl/include/EASTL/fixed_substring.h
Normal file
300
lib/eastl/include/EASTL/fixed_substring.h
Normal file
|
@ -0,0 +1,300 @@
|
|||
/*
|
||||
Copyright (C) 2009-2010 Electronic Arts, Inc. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
3. Neither the name of Electronic Arts, Inc. ("EA") nor the names of
|
||||
its contributors may be used to endorse or promote products derived
|
||||
from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY ELECTRONIC ARTS AND ITS CONTRIBUTORS "AS IS" AND ANY
|
||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL ELECTRONIC ARTS OR ITS CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// EASTL/fixed_substring.h
|
||||
//
|
||||
// Copyright (c) 2005, Electronic Arts. All rights reserved.
|
||||
// Written and maintained by Paul Pedriana.
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
#ifndef EASTL_FIXED_SUBSTRING_H
|
||||
#define EASTL_FIXED_SUBSTRING_H
|
||||
|
||||
|
||||
#include <EASTL/string.h>
|
||||
|
||||
|
||||
namespace eastl
|
||||
{
|
||||
|
||||
/// fixed_substring
|
||||
///
|
||||
/// Implements a string which is a reference to a segment of characters.
|
||||
/// This class is efficient because it allocates no memory and copies no
|
||||
/// memory during construction and assignment, but rather refers directly
|
||||
/// to the segment of chracters. A common use of this is to have a
|
||||
/// fixed_substring efficiently refer to a substring within another string.
|
||||
///
|
||||
/// You cannot directly resize a fixed_substring (e.g. via resize, insert,
|
||||
/// append, erase), but you can assign a different substring to it.
|
||||
/// You can modify the characters within a substring in place.
|
||||
/// As of this writing, in the name of being lean and simple it is the
|
||||
/// user's responsibility to not call unsupported resizing functions
|
||||
/// such as those listed above. A detailed listing of the functions which
|
||||
/// are not supported is given below in the class declaration.
|
||||
///
|
||||
/// The c_str function doesn't act as one might hope, as it simply
|
||||
/// returns the pointer to the beginning of the string segment and the
|
||||
/// 0-terminator may be beyond the end of the segment. If you want to
|
||||
/// always be able to use c_str as expected, use the fixed string solution
|
||||
/// we describe below.
|
||||
///
|
||||
/// Another use of fixed_substring is to provide C++ string-like functionality
|
||||
/// with a C character array. This allows you to work on a C character array
|
||||
/// as if it were a C++ string as opposed using the C string API. Thus you
|
||||
/// can do this:
|
||||
///
|
||||
/// void DoSomethingForUser(char* timeStr, size_t timeStrCapacity)
|
||||
/// {
|
||||
/// fixed_substring tmp(timeStr, timeStrCapacity);
|
||||
/// tmp = "hello ";
|
||||
/// tmp += "world";
|
||||
/// }
|
||||
///
|
||||
/// Note that this class constructs and assigns from const string pointers
|
||||
/// and const string objects, yet this class does not declare its member
|
||||
/// data as const. This is a concession in order to allow this implementation
|
||||
/// to be simple and lean. It is the user's responsibility to make sure
|
||||
/// that strings that should not or can not be modified are either not
|
||||
/// used by fixed_substring or are not modified by fixed_substring.
|
||||
///
|
||||
/// A more flexible alternative to fixed_substring is fixed_string.
|
||||
/// fixed_string has none of the functional limitations that fixed_substring
|
||||
/// has and like fixed_substring it doesn't allocate memory. However,
|
||||
/// fixed_string makes a *copy* of the source string and uses local
|
||||
/// memory to store that copy. Also, fixed_string objects on the stack
|
||||
/// are going to have a limit as to their maximum size.
|
||||
///
|
||||
/// Notes:
|
||||
/// As of this writing, the string class necessarily reallocates when
|
||||
/// an insert of self is done into self. As a result, the fixed_substring
|
||||
/// class doesn't support inserting self into self.
|
||||
///
|
||||
/// Example usage:
|
||||
/// basic_string<char> str("hello world");
|
||||
/// fixed_substring<char> sub(str, 2, 5); // sub == "llo w"
|
||||
///
|
||||
template <typename T>
|
||||
class fixed_substring : public basic_string<T>
|
||||
{
|
||||
public:
|
||||
typedef basic_string<T> base_type;
|
||||
typedef fixed_substring<T> this_type;
|
||||
typedef typename base_type::size_type size_type;
|
||||
typedef typename base_type::value_type value_type;
|
||||
|
||||
using base_type::npos;
|
||||
using base_type::mpBegin;
|
||||
using base_type::mpEnd;
|
||||
using base_type::mpCapacity;
|
||||
using base_type::reset;
|
||||
using base_type::mAllocator;
|
||||
|
||||
public:
|
||||
fixed_substring()
|
||||
: base_type()
|
||||
{
|
||||
}
|
||||
|
||||
fixed_substring(const base_type& x)
|
||||
: base_type()
|
||||
{
|
||||
#if EASTL_NAME_ENABLED
|
||||
mAllocator.set_name(x.get_allocator().get_name());
|
||||
#endif
|
||||
|
||||
assign(x);
|
||||
}
|
||||
|
||||
fixed_substring(const base_type& x, size_type position, size_type n = base_type::npos)
|
||||
: base_type()
|
||||
{
|
||||
#if EASTL_NAME_ENABLED
|
||||
mAllocator.set_name(x.get_allocator().get_name());
|
||||
#endif
|
||||
|
||||
assign(x, position, n);
|
||||
}
|
||||
|
||||
fixed_substring(const value_type* p, size_type n)
|
||||
: base_type()
|
||||
{
|
||||
assign(p, n);
|
||||
}
|
||||
|
||||
fixed_substring(const value_type* p)
|
||||
: base_type()
|
||||
{
|
||||
assign(p);
|
||||
}
|
||||
|
||||
fixed_substring(const value_type* pBegin, const value_type* pEnd)
|
||||
: base_type()
|
||||
{
|
||||
assign(pBegin, pEnd);
|
||||
}
|
||||
|
||||
~fixed_substring()
|
||||
{
|
||||
// We need to reset, as otherwise the parent destructor will
|
||||
// attempt to free our memory.
|
||||
reset();
|
||||
}
|
||||
|
||||
this_type& operator=(const base_type& x)
|
||||
{
|
||||
assign(x);
|
||||
return *this;
|
||||
}
|
||||
|
||||
this_type& operator=(const value_type* p)
|
||||
{
|
||||
assign(p);
|
||||
return *this;
|
||||
}
|
||||
|
||||
this_type& assign(const base_type& x)
|
||||
{
|
||||
// By design, we need to cast away const-ness here.
|
||||
mpBegin = const_cast<value_type*>(x.data());
|
||||
mpEnd = mpBegin + x.size();
|
||||
mpCapacity = mpEnd;
|
||||
return *this;
|
||||
}
|
||||
|
||||
this_type& assign(const base_type& x, size_type position, size_type n)
|
||||
{
|
||||
// By design, we need to cast away const-ness here.
|
||||
mpBegin = const_cast<value_type*>(x.data()) + position;
|
||||
mpEnd = mpBegin + n;
|
||||
mpCapacity = mpEnd;
|
||||
return *this;
|
||||
}
|
||||
|
||||
this_type& assign(const value_type* p, size_type n)
|
||||
{
|
||||
// By design, we need to cast away const-ness here.
|
||||
mpBegin = const_cast<value_type*>(p);
|
||||
mpEnd = mpBegin + n;
|
||||
mpCapacity = mpEnd;
|
||||
return *this;
|
||||
}
|
||||
|
||||
this_type& assign(const value_type* p)
|
||||
{
|
||||
// By design, we need to cast away const-ness here.
|
||||
mpBegin = const_cast<value_type*>(p);
|
||||
mpEnd = mpBegin + CharStrlen(p);
|
||||
mpCapacity = mpEnd;
|
||||
return *this;
|
||||
}
|
||||
|
||||
this_type& assign(const value_type* pBegin, const value_type* pEnd)
|
||||
{
|
||||
// By design, we need to cast away const-ness here.
|
||||
mpBegin = const_cast<value_type*>(pBegin);
|
||||
mpEnd = const_cast<value_type*>(pEnd);
|
||||
mpCapacity = mpEnd;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
// Partially supported functionality
|
||||
//
|
||||
// When using fixed_substring on a character sequence that is within another
|
||||
// string, the following functions may do one of two things:
|
||||
// 1 Attempt to reallocate
|
||||
// 2 Write a 0 char at the end of the fixed_substring
|
||||
//
|
||||
// Item #1 will result in a crash, due to the attempt by the underlying
|
||||
// string class to free the substring memory. Item #2 will result in a 0
|
||||
// char being written to the character array. Item #2 may or may not be
|
||||
// a problem, depending on how you use fixed_substring. Thus the following
|
||||
// functions should be used carefully.
|
||||
//
|
||||
// basic_string& operator=(const basic_string& x);
|
||||
// basic_string& operator=(value_type c);
|
||||
// void resize(size_type n, value_type c);
|
||||
// void resize(size_type n);
|
||||
// void reserve(size_type = 0);
|
||||
// void set_capacity(size_type n);
|
||||
// void clear();
|
||||
// basic_string& operator+=(const basic_string& x);
|
||||
// basic_string& operator+=(const value_type* p);
|
||||
// basic_string& operator+=(value_type c);
|
||||
// basic_string& append(const basic_string& x);
|
||||
// basic_string& append(const basic_string& x, size_type position, size_type n);
|
||||
// basic_string& append(const value_type* p, size_type n);
|
||||
// basic_string& append(const value_type* p);
|
||||
// basic_string& append(size_type n);
|
||||
// basic_string& append(size_type n, value_type c);
|
||||
// basic_string& append(const value_type* pBegin, const value_type* pEnd);
|
||||
// basic_string& append_sprintf_va_list(const value_type* pFormat, va_list arguments);
|
||||
// basic_string& append_sprintf(const value_type* pFormat, ...);
|
||||
// void push_back(value_type c);
|
||||
// void pop_back();
|
||||
// basic_string& assign(const value_type* p, size_type n);
|
||||
// basic_string& assign(size_type n, value_type c);
|
||||
// basic_string& insert(size_type position, const basic_string& x);
|
||||
// basic_string& insert(size_type position, const basic_string& x, size_type beg, size_type n);
|
||||
// basic_string& insert(size_type position, const value_type* p, size_type n);
|
||||
// basic_string& insert(size_type position, const value_type* p);
|
||||
// basic_string& insert(size_type position, size_type n, value_type c);
|
||||
// iterator insert(iterator p, value_type c);
|
||||
// void insert(iterator p, size_type n, value_type c);
|
||||
// void insert(iterator p, const value_type* pBegin, const value_type* pEnd);
|
||||
// basic_string& erase(size_type position = 0, size_type n = npos);
|
||||
// iterator erase(iterator p);
|
||||
// iterator erase(iterator pBegin, iterator pEnd);
|
||||
// void swap(basic_string& x);
|
||||
// basic_string& sprintf_va_list(const value_type* pFormat, va_list arguments);
|
||||
// basic_string& sprintf(const value_type* pFormat, ...);
|
||||
|
||||
|
||||
}; // fixed_substring
|
||||
|
||||
|
||||
} // namespace eastl
|
||||
|
||||
|
||||
|
||||
#endif // Header include guard
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
333
lib/eastl/include/EASTL/fixed_vector.h
Normal file
333
lib/eastl/include/EASTL/fixed_vector.h
Normal file
|
@ -0,0 +1,333 @@
|
|||
/*
|
||||
Copyright (C) 2009-2010 Electronic Arts, Inc. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
3. Neither the name of Electronic Arts, Inc. ("EA") nor the names of
|
||||
its contributors may be used to endorse or promote products derived
|
||||
from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY ELECTRONIC ARTS AND ITS CONTRIBUTORS "AS IS" AND ANY
|
||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL ELECTRONIC ARTS OR ITS CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// EASTL/fixed_vector.h
|
||||
//
|
||||
// Copyright (c) 2005, Electronic Arts. All rights reserved.
|
||||
// Written and maintained by Paul Pedriana.
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// This file implements a vector which uses a fixed size memory pool.
|
||||
// The bEnableOverflow template parameter allows the container to resort to
|
||||
// heap allocations if the memory pool is exhausted.
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
#ifndef EASTL_FIXED_VECTOR_H
|
||||
#define EASTL_FIXED_VECTOR_H
|
||||
|
||||
|
||||
#include <EASTL/vector.h>
|
||||
#include <EASTL/internal/fixed_pool.h>
|
||||
|
||||
|
||||
namespace eastl
|
||||
{
|
||||
/// EASTL_FIXED_VECTOR_DEFAULT_NAME
|
||||
///
|
||||
/// Defines a default container name in the absence of a user-provided name.
|
||||
/// In the case of fixed-size containers, the allocator name always refers
|
||||
/// to overflow allocations.
|
||||
///
|
||||
#ifndef EASTL_FIXED_VECTOR_DEFAULT_NAME
|
||||
#define EASTL_FIXED_VECTOR_DEFAULT_NAME EASTL_DEFAULT_NAME_PREFIX " fixed_vector" // Unless the user overrides something, this is "EASTL fixed_vector".
|
||||
#endif
|
||||
|
||||
|
||||
/// fixed_vector
|
||||
///
|
||||
/// A fixed_vector with bEnableOverflow == true is identical to a regular
|
||||
/// vector in terms of its behavior. All the expectations of regular vector
|
||||
/// apply to it and no additional expectations come from it. When bEnableOverflow
|
||||
/// is false, fixed_vector behaves like regular vector with the exception that
|
||||
/// its capacity can never increase. All operations you do on such a fixed_vector
|
||||
/// which require a capacity increase will result in undefined behavior or an
|
||||
/// C++ allocation exception, depending on the configuration of EASTL.
|
||||
///
|
||||
/// Template parameters:
|
||||
/// T The type of object the vector holds.
|
||||
/// nodeCount The max number of objects to contain.
|
||||
/// bEnableOverflow Whether or not we should use the overflow heap if our object pool is exhausted.
|
||||
/// Allocator Overflow allocator, which is only used if bEnableOverflow == true. Defaults to the global heap.
|
||||
///
|
||||
/// Note: The nodeCount value must be at least 1.
|
||||
///
|
||||
/// Example usage:
|
||||
/// fixed_vector<Widget, 128, true> fixedVector);
|
||||
///
|
||||
/// fixedVector.push_back(Widget());
|
||||
/// fixedVector.resize(200);
|
||||
/// fixedVector.clear();
|
||||
///
|
||||
template <typename T, size_t nodeCount, bool bEnableOverflow = true, typename Allocator = EASTLAllocatorType>
|
||||
class fixed_vector : public vector<T, fixed_vector_allocator<sizeof(T), nodeCount, vector<T>::kAlignment, vector<T>::kAlignmentOffset, bEnableOverflow, Allocator> >
|
||||
{
|
||||
public:
|
||||
typedef fixed_vector_allocator<sizeof(T), nodeCount, vector<T>::kAlignment,
|
||||
vector<T>::kAlignmentOffset, bEnableOverflow, Allocator> fixed_allocator_type;
|
||||
typedef vector<T, fixed_allocator_type> base_type;
|
||||
typedef fixed_vector<T, nodeCount, bEnableOverflow, Allocator> this_type;
|
||||
typedef typename base_type::size_type size_type;
|
||||
typedef typename base_type::value_type value_type;
|
||||
typedef aligned_buffer<nodeCount * sizeof(T), vector<T>::kAlignment> aligned_buffer_type;
|
||||
|
||||
enum
|
||||
{
|
||||
kMaxSize = nodeCount
|
||||
};
|
||||
|
||||
using base_type::mAllocator;
|
||||
using base_type::mpBegin;
|
||||
using base_type::mpEnd;
|
||||
using base_type::mpCapacity;
|
||||
using base_type::resize;
|
||||
using base_type::clear;
|
||||
using base_type::size;
|
||||
using base_type::assign;
|
||||
|
||||
protected:
|
||||
aligned_buffer_type mBuffer;
|
||||
|
||||
public:
|
||||
fixed_vector();
|
||||
explicit fixed_vector(size_type n);
|
||||
fixed_vector(size_type n, const value_type& value);
|
||||
fixed_vector(const this_type& x);
|
||||
|
||||
template <typename InputIterator>
|
||||
fixed_vector(InputIterator first, InputIterator last);
|
||||
|
||||
this_type& operator=(const this_type& x);
|
||||
|
||||
void swap(this_type& x);
|
||||
|
||||
void set_capacity(size_type n);
|
||||
void reset();
|
||||
size_type max_size() const; // Returns the max fixed size, which is the user-supplied nodeCount parameter.
|
||||
bool has_overflowed() const; // Returns true if the fixed space is fully allocated. Note that if overflow is enabled, the container size can be greater than nodeCount but full() could return true because the fixed space may have a recently freed slot.
|
||||
|
||||
void* push_back_uninitialized();
|
||||
|
||||
// Deprecated:
|
||||
bool full() const { return has_overflowed(); }
|
||||
|
||||
protected:
|
||||
void* DoPushBackUninitialized(true_type);
|
||||
void* DoPushBackUninitialized(false_type);
|
||||
|
||||
}; // fixed_vector
|
||||
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// fixed_vector
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <typename T, size_t nodeCount, bool bEnableOverflow, typename Allocator>
|
||||
inline fixed_vector<T, nodeCount, bEnableOverflow, Allocator>::fixed_vector()
|
||||
: base_type(fixed_allocator_type(mBuffer.buffer))
|
||||
{
|
||||
#if EASTL_NAME_ENABLED
|
||||
mAllocator.set_name(EASTL_FIXED_VECTOR_DEFAULT_NAME);
|
||||
#endif
|
||||
|
||||
mpBegin = mpEnd = (value_type*)&mBuffer.buffer[0];
|
||||
mpCapacity = mpBegin + nodeCount;
|
||||
}
|
||||
|
||||
template <typename T, size_t nodeCount, bool bEnableOverflow, typename Allocator>
|
||||
inline fixed_vector<T, nodeCount, bEnableOverflow, Allocator>::fixed_vector(size_type n)
|
||||
: base_type(fixed_allocator_type(mBuffer.buffer))
|
||||
{
|
||||
#if EASTL_NAME_ENABLED
|
||||
mAllocator.set_name(EASTL_FIXED_VECTOR_DEFAULT_NAME);
|
||||
#endif
|
||||
|
||||
mpBegin = mpEnd = (value_type*)&mBuffer.buffer[0];
|
||||
mpCapacity = mpBegin + nodeCount;
|
||||
resize(n);
|
||||
}
|
||||
|
||||
|
||||
template <typename T, size_t nodeCount, bool bEnableOverflow, typename Allocator>
|
||||
inline fixed_vector<T, nodeCount, bEnableOverflow, Allocator>::fixed_vector(size_type n, const value_type& value)
|
||||
: base_type(fixed_allocator_type(mBuffer.buffer))
|
||||
{
|
||||
#if EASTL_NAME_ENABLED
|
||||
mAllocator.set_name(EASTL_FIXED_VECTOR_DEFAULT_NAME);
|
||||
#endif
|
||||
|
||||
mpBegin = mpEnd = (value_type*)&mBuffer.buffer[0];
|
||||
mpCapacity = mpBegin + nodeCount;
|
||||
resize(n, value);
|
||||
}
|
||||
|
||||
|
||||
template <typename T, size_t nodeCount, bool bEnableOverflow, typename Allocator>
|
||||
inline fixed_vector<T, nodeCount, bEnableOverflow, Allocator>::fixed_vector(const this_type& x)
|
||||
: base_type(fixed_allocator_type(mBuffer.buffer))
|
||||
{
|
||||
#if EASTL_NAME_ENABLED
|
||||
mAllocator.set_name(x.mAllocator.get_name());
|
||||
#endif
|
||||
|
||||
mpBegin = mpEnd = (value_type*)&mBuffer.buffer[0];
|
||||
mpCapacity = mpBegin + nodeCount;
|
||||
assign(x.begin(), x.end());
|
||||
}
|
||||
|
||||
|
||||
template <typename T, size_t nodeCount, bool bEnableOverflow, typename Allocator>
|
||||
template <typename InputIterator>
|
||||
fixed_vector<T, nodeCount, bEnableOverflow, Allocator>::fixed_vector(InputIterator first, InputIterator last)
|
||||
: base_type(fixed_allocator_type(mBuffer.buffer))
|
||||
{
|
||||
#if EASTL_NAME_ENABLED
|
||||
mAllocator.set_name(EASTL_FIXED_VECTOR_DEFAULT_NAME);
|
||||
#endif
|
||||
|
||||
mpBegin = mpEnd = (value_type*)&mBuffer.buffer[0];
|
||||
mpCapacity = mpBegin + nodeCount;
|
||||
//assign(first, last); // Metrowerks gets confused by this.
|
||||
base_type::DoAssign(first, last, is_integral<InputIterator>());
|
||||
}
|
||||
|
||||
|
||||
template <typename T, size_t nodeCount, bool bEnableOverflow, typename Allocator>
|
||||
inline typename fixed_vector<T, nodeCount, bEnableOverflow, Allocator>::this_type&
|
||||
fixed_vector<T, nodeCount, bEnableOverflow, Allocator>::operator=(const this_type& x)
|
||||
{
|
||||
if(this != &x)
|
||||
{
|
||||
clear();
|
||||
assign(x.begin(), x.end());
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
template <typename T, size_t nodeCount, bool bEnableOverflow, typename Allocator>
|
||||
inline void fixed_vector<T, nodeCount, bEnableOverflow, Allocator>::swap(this_type& x)
|
||||
{
|
||||
// Fixed containers use a special swap that can deal with excessively large buffers.
|
||||
eastl::fixed_swap(*this, x);
|
||||
}
|
||||
|
||||
|
||||
template <typename T, size_t nodeCount, bool bEnableOverflow, typename Allocator>
|
||||
inline void fixed_vector<T, nodeCount, bEnableOverflow, Allocator>::set_capacity(size_type n)
|
||||
{
|
||||
// We act consistently with vector::set_capacity and reduce our
|
||||
// size if the new capacity is smaller than our size.
|
||||
if(n < size())
|
||||
resize(n);
|
||||
// To consider: If bEnableOverflow is true, then perhaps we should
|
||||
// switch to the overflow allocator and set the capacity.
|
||||
}
|
||||
|
||||
|
||||
template <typename T, size_t nodeCount, bool bEnableOverflow, typename Allocator>
|
||||
inline void fixed_vector<T, nodeCount, bEnableOverflow, Allocator>::reset()
|
||||
{
|
||||
mpBegin = mpEnd = (value_type*)&mBuffer.buffer[0];
|
||||
mpCapacity = mpBegin + nodeCount;
|
||||
}
|
||||
|
||||
|
||||
template <typename T, size_t nodeCount, bool bEnableOverflow, typename Allocator>
|
||||
inline typename fixed_vector<T, nodeCount, bEnableOverflow, Allocator>::size_type
|
||||
fixed_vector<T, nodeCount, bEnableOverflow, Allocator>::max_size() const
|
||||
{
|
||||
return kMaxSize;
|
||||
}
|
||||
|
||||
|
||||
template <typename T, size_t nodeCount, bool bEnableOverflow, typename Allocator>
|
||||
inline bool fixed_vector<T, nodeCount, bEnableOverflow, Allocator>::has_overflowed() const
|
||||
{
|
||||
// If size >= capacity, then we are definitely full.
|
||||
// Also, if our size is smaller but we've switched away from mBuffer due to a previous overflow, then we are considered full.
|
||||
return ((size_t)(mpEnd - mpBegin) >= kMaxSize) || ((void*)mpBegin != (void*)mBuffer.buffer);
|
||||
}
|
||||
|
||||
|
||||
template <typename T, size_t nodeCount, bool bEnableOverflow, typename Allocator>
|
||||
inline void* fixed_vector<T, nodeCount, bEnableOverflow, Allocator>::push_back_uninitialized()
|
||||
{
|
||||
return DoPushBackUninitialized(typename type_select<bEnableOverflow, true_type, false_type>::type());
|
||||
}
|
||||
|
||||
template <typename T, size_t nodeCount, bool bEnableOverflow, typename Allocator>
|
||||
inline void* fixed_vector<T, nodeCount, bEnableOverflow, Allocator>::DoPushBackUninitialized(true_type)
|
||||
{
|
||||
return base_type::push_back_uninitialized();
|
||||
}
|
||||
|
||||
template <typename T, size_t nodeCount, bool bEnableOverflow, typename Allocator>
|
||||
inline void* fixed_vector<T, nodeCount, bEnableOverflow, Allocator>::DoPushBackUninitialized(false_type)
|
||||
{
|
||||
return mpEnd++;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// global operators
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
|
||||
// operator ==, !=, <, >, <=, >= come from the vector implementations.
|
||||
|
||||
template <typename T, size_t nodeCount, bool bEnableOverflow, typename Allocator>
|
||||
inline void swap(fixed_vector<T, nodeCount, bEnableOverflow, Allocator>& a,
|
||||
fixed_vector<T, nodeCount, bEnableOverflow, Allocator>& b)
|
||||
{
|
||||
// Fixed containers use a special swap that can deal with excessively large buffers.
|
||||
eastl::fixed_swap(a, b);
|
||||
}
|
||||
|
||||
|
||||
|
||||
} // namespace eastl
|
||||
|
||||
|
||||
|
||||
#endif // Header include guard
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
936
lib/eastl/include/EASTL/functional.h
Normal file
936
lib/eastl/include/EASTL/functional.h
Normal file
|
@ -0,0 +1,936 @@
|
|||
/*
|
||||
Copyright (C) 2005,2009-2010 Electronic Arts, Inc. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
3. Neither the name of Electronic Arts, Inc. ("EA") nor the names of
|
||||
its contributors may be used to endorse or promote products derived
|
||||
from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY ELECTRONIC ARTS AND ITS CONTRIBUTORS "AS IS" AND ANY
|
||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL ELECTRONIC ARTS OR ITS CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// EASTL/functional.h
|
||||
// Written and maintained by Paul Pedriana - 2005
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
#ifndef EASTL_FUNCTIONAL_H
|
||||
#define EASTL_FUNCTIONAL_H
|
||||
|
||||
|
||||
#include <EASTL/internal/config.h>
|
||||
#include <EASTL/type_traits.h>
|
||||
|
||||
|
||||
namespace eastl
|
||||
{
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// Primary C++ functions
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <typename Argument, typename Result>
|
||||
struct unary_function
|
||||
{
|
||||
typedef Argument argument_type;
|
||||
typedef Result result_type;
|
||||
};
|
||||
|
||||
|
||||
template <typename Argument1, typename Argument2, typename Result>
|
||||
struct binary_function
|
||||
{
|
||||
typedef Argument1 first_argument_type;
|
||||
typedef Argument2 second_argument_type;
|
||||
typedef Result result_type;
|
||||
};
|
||||
|
||||
|
||||
template <typename T>
|
||||
struct plus : public binary_function<T, T, T>
|
||||
{
|
||||
T operator()(const T& a, const T& b) const
|
||||
{ return a + b; }
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct minus : public binary_function<T, T, T>
|
||||
{
|
||||
T operator()(const T& a, const T& b) const
|
||||
{ return a - b; }
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct multiplies : public binary_function<T, T, T>
|
||||
{
|
||||
T operator()(const T& a, const T& b) const
|
||||
{ return a * b; }
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct divides : public binary_function<T, T, T>
|
||||
{
|
||||
T operator()(const T& a, const T& b) const
|
||||
{ return a / b; }
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct modulus : public binary_function<T, T, T>
|
||||
{
|
||||
T operator()(const T& a, const T& b) const
|
||||
{ return a % b; }
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct negate : public unary_function<T, T>
|
||||
{
|
||||
T operator()(const T& a) const
|
||||
{ return -a; }
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct equal_to : public binary_function<T, T, bool>
|
||||
{
|
||||
bool operator()(const T& a, const T& b) const
|
||||
{ return a == b; }
|
||||
};
|
||||
|
||||
template <typename T, typename Compare>
|
||||
bool validate_equal_to(const T& a, const T& b, Compare compare)
|
||||
{
|
||||
return compare(a, b) == compare(b, a);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
struct not_equal_to : public binary_function<T, T, bool>
|
||||
{
|
||||
bool operator()(const T& a, const T& b) const
|
||||
{ return a != b; }
|
||||
};
|
||||
|
||||
template <typename T, typename Compare>
|
||||
bool validate_not_equal_to(const T& a, const T& b, Compare compare)
|
||||
{
|
||||
return compare(a, b) == compare(b, a); // We want the not equal comparison results to be equal.
|
||||
}
|
||||
|
||||
/// str_equal_to
|
||||
///
|
||||
/// Compares two 0-terminated string types.
|
||||
/// The T types are expected to be iterators or act like iterators.
|
||||
///
|
||||
/// Example usage:
|
||||
/// hash_set<const char*, hash<const char*>, str_equal_to<const char*> > stringHashSet;
|
||||
///
|
||||
/// Note:
|
||||
/// You couldn't use str_equal_to like this:
|
||||
/// bool result = equal("hi", "hi" + 2, "ho", str_equal_to<const char*>());
|
||||
/// This is because equal tests an array of something, with each element by
|
||||
/// the comparison function. But str_equal_to tests an array of something itself.
|
||||
///
|
||||
template <typename T>
|
||||
struct str_equal_to : public binary_function<T, T, bool>
|
||||
{
|
||||
bool operator()(T a, T b) const
|
||||
{
|
||||
while(*a && (*a == *b))
|
||||
{
|
||||
++a;
|
||||
++b;
|
||||
}
|
||||
return (*a == *b);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct greater : public binary_function<T, T, bool>
|
||||
{
|
||||
bool operator()(const T& a, const T& b) const
|
||||
{ return a > b; }
|
||||
};
|
||||
|
||||
template <typename T, typename Compare>
|
||||
bool validate_greater(const T& a, const T& b, Compare compare)
|
||||
{
|
||||
return !compare(a, b) || !compare(b, a); // If (a > b), then !(b > a)
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
struct less : public binary_function<T, T, bool>
|
||||
{
|
||||
bool operator()(const T& a, const T& b) const
|
||||
{ return a < b; }
|
||||
};
|
||||
|
||||
template <typename T, typename Compare>
|
||||
bool validate_less(const T& a, const T& b, Compare compare)
|
||||
{
|
||||
return !compare(a, b) || !compare(b, a); // If (a < b), then !(b < a)
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
struct greater_equal : public binary_function<T, T, bool>
|
||||
{
|
||||
bool operator()(const T& a, const T& b) const
|
||||
{ return a >= b; }
|
||||
};
|
||||
|
||||
template <typename T, typename Compare>
|
||||
bool validate_greater_equal(const T& a, const T& b, Compare compare)
|
||||
{
|
||||
return !compare(a, b) || !compare(b, a); // If (a >= b), then !(b >= a)
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
struct less_equal : public binary_function<T, T, bool>
|
||||
{
|
||||
bool operator()(const T& a, const T& b) const
|
||||
{ return a <= b; }
|
||||
};
|
||||
|
||||
template <typename T, typename Compare>
|
||||
bool validate_less_equal(const T& a, const T& b, Compare compare)
|
||||
{
|
||||
return !compare(a, b) || !compare(b, a); // If (a <= b), then !(b <= a)
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
struct logical_and : public binary_function<T, T, bool>
|
||||
{
|
||||
bool operator()(const T& a, const T& b) const
|
||||
{ return a && b; }
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct logical_or : public binary_function<T, T, bool>
|
||||
{
|
||||
bool operator()(const T& a, const T& b) const
|
||||
{ return a || b; }
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct logical_not : public unary_function<T, bool>
|
||||
{
|
||||
bool operator()(const T& a) const
|
||||
{ return !a; }
|
||||
};
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// Dual type functions
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <typename T, typename U>
|
||||
struct equal_to_2 : public binary_function<T, U, bool>
|
||||
{
|
||||
bool operator()(const T& a, const U& b) const
|
||||
{ return a == b; }
|
||||
};
|
||||
|
||||
template <typename T, typename U>
|
||||
struct not_equal_to_2 : public binary_function<T, U, bool>
|
||||
{
|
||||
bool operator()(const T& a, const U& b) const
|
||||
{ return a != b; }
|
||||
};
|
||||
|
||||
template <typename T, typename U>
|
||||
struct less_2 : public binary_function<T, U, bool>
|
||||
{
|
||||
bool operator()(const T& a, const U& b) const
|
||||
{ return a < b; }
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
/// unary_negate
|
||||
///
|
||||
template <typename Predicate>
|
||||
class unary_negate : public unary_function<typename Predicate::argument_type, bool>
|
||||
{
|
||||
protected:
|
||||
Predicate mPredicate;
|
||||
public:
|
||||
explicit unary_negate(const Predicate& a)
|
||||
: mPredicate(a) {}
|
||||
bool operator()(const typename Predicate::argument_type& a) const
|
||||
{ return !mPredicate(a); }
|
||||
};
|
||||
|
||||
template <typename Predicate>
|
||||
inline unary_negate<Predicate> not1(const Predicate& predicate)
|
||||
{ return unary_negate<Predicate>(predicate); }
|
||||
|
||||
|
||||
|
||||
/// binary_negate
|
||||
///
|
||||
template <typename Predicate>
|
||||
class binary_negate : public binary_function<typename Predicate::first_argument_type, typename Predicate::second_argument_type, bool>
|
||||
{
|
||||
protected:
|
||||
Predicate mPredicate;
|
||||
public:
|
||||
explicit binary_negate(const Predicate& a)
|
||||
: mPredicate(a) { }
|
||||
bool operator()(const typename Predicate::first_argument_type& a, const typename Predicate::second_argument_type& b) const
|
||||
{ return !mPredicate(a, b); }
|
||||
};
|
||||
|
||||
template <typename Predicate>
|
||||
inline binary_negate<Predicate> not2(const Predicate& predicate)
|
||||
{ return binary_negate<Predicate>(predicate); }
|
||||
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// bind
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
|
||||
/// bind1st
|
||||
///
|
||||
template <typename Operation>
|
||||
class binder1st : public unary_function<typename Operation::second_argument_type, typename Operation::result_type>
|
||||
{
|
||||
protected:
|
||||
typename Operation::first_argument_type value;
|
||||
Operation op;
|
||||
|
||||
public:
|
||||
binder1st(const Operation& x, const typename Operation::first_argument_type& y)
|
||||
: value(y), op(x) { }
|
||||
|
||||
typename Operation::result_type operator()(const typename Operation::second_argument_type& x) const
|
||||
{ return op(value, x); }
|
||||
|
||||
typename Operation::result_type operator()(typename Operation::second_argument_type& x) const
|
||||
{ return op(value, x); }
|
||||
};
|
||||
|
||||
|
||||
template <typename Operation, typename T>
|
||||
inline binder1st<Operation> bind1st(const Operation& op, const T& x)
|
||||
{
|
||||
typedef typename Operation::first_argument_type value;
|
||||
return binder1st<Operation>(op, value(x));
|
||||
}
|
||||
|
||||
|
||||
/// bind2nd
|
||||
///
|
||||
template <typename Operation>
|
||||
class binder2nd : public unary_function<typename Operation::first_argument_type, typename Operation::result_type>
|
||||
{
|
||||
protected:
|
||||
Operation op;
|
||||
typename Operation::second_argument_type value;
|
||||
|
||||
public:
|
||||
binder2nd(const Operation& x, const typename Operation::second_argument_type& y)
|
||||
: op(x), value(y) { }
|
||||
|
||||
typename Operation::result_type operator()(const typename Operation::first_argument_type& x) const
|
||||
{ return op(x, value); }
|
||||
|
||||
typename Operation::result_type operator()(typename Operation::first_argument_type& x) const
|
||||
{ return op(x, value); }
|
||||
};
|
||||
|
||||
|
||||
template <typename Operation, typename T>
|
||||
inline binder2nd<Operation> bind2nd(const Operation& op, const T& x)
|
||||
{
|
||||
typedef typename Operation::second_argument_type value;
|
||||
return binder2nd<Operation>(op, value(x));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// pointer_to_unary_function
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
|
||||
/// pointer_to_unary_function
|
||||
///
|
||||
/// This is an adapter template which converts a pointer to a standalone
|
||||
/// function to a function object. This allows standalone functions to
|
||||
/// work in many cases where the system requires a function object.
|
||||
///
|
||||
/// Example usage:
|
||||
/// ptrdiff_t Rand(ptrdiff_t n) { return rand() % n; } // Note: The C rand function is poor and slow.
|
||||
/// pointer_to_unary_function<ptrdiff_t, ptrdiff_t> randInstance(Rand);
|
||||
/// random_shuffle(pArrayBegin, pArrayEnd, randInstance);
|
||||
///
|
||||
template <typename Arg, typename Result>
|
||||
class pointer_to_unary_function : public unary_function<Arg, Result>
|
||||
{
|
||||
protected:
|
||||
Result (*mpFunction)(Arg);
|
||||
|
||||
public:
|
||||
pointer_to_unary_function()
|
||||
{ }
|
||||
|
||||
explicit pointer_to_unary_function(Result (*pFunction)(Arg))
|
||||
: mpFunction(pFunction) { }
|
||||
|
||||
Result operator()(Arg x) const
|
||||
{ return mpFunction(x); }
|
||||
};
|
||||
|
||||
|
||||
/// ptr_fun
|
||||
///
|
||||
/// This ptr_fun is simply shorthand for usage of pointer_to_unary_function.
|
||||
///
|
||||
/// Example usage (actually, you don't need to use ptr_fun here, but it works anyway):
|
||||
/// int factorial(int x) { return (x > 1) ? (x * factorial(x - 1)) : x; }
|
||||
/// transform(pIntArrayBegin, pIntArrayEnd, pIntArrayBegin, ptr_fun(factorial));
|
||||
///
|
||||
template <typename Arg, typename Result>
|
||||
inline pointer_to_unary_function<Arg, Result> ptr_fun(Result (*pFunction)(Arg))
|
||||
{ return pointer_to_unary_function<Arg, Result>(pFunction); }
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// pointer_to_binary_function
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
|
||||
/// pointer_to_binary_function
|
||||
///
|
||||
/// This is an adapter template which converts a pointer to a standalone
|
||||
/// function to a function object. This allows standalone functions to
|
||||
/// work in many cases where the system requires a function object.
|
||||
///
|
||||
template <typename Arg1, typename Arg2, typename Result>
|
||||
class pointer_to_binary_function : public binary_function<Arg1, Arg2, Result>
|
||||
{
|
||||
protected:
|
||||
Result (*mpFunction)(Arg1, Arg2);
|
||||
|
||||
public:
|
||||
pointer_to_binary_function()
|
||||
{ }
|
||||
|
||||
explicit pointer_to_binary_function(Result (*pFunction)(Arg1, Arg2))
|
||||
: mpFunction(pFunction) {}
|
||||
|
||||
Result operator()(Arg1 x, Arg2 y) const
|
||||
{ return mpFunction(x, y); }
|
||||
};
|
||||
|
||||
|
||||
/// This ptr_fun is simply shorthand for usage of pointer_to_binary_function.
|
||||
///
|
||||
/// Example usage (actually, you don't need to use ptr_fun here, but it works anyway):
|
||||
/// int multiply(int x, int y) { return x * y; }
|
||||
/// transform(pIntArray1Begin, pIntArray1End, pIntArray2Begin, pIntArray1Begin, ptr_fun(multiply));
|
||||
///
|
||||
template <typename Arg1, typename Arg2, typename Result>
|
||||
inline pointer_to_binary_function<Arg1, Arg2, Result> ptr_fun(Result (*pFunction)(Arg1, Arg2))
|
||||
{ return pointer_to_binary_function<Arg1, Arg2, Result>(pFunction); }
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// mem_fun
|
||||
// mem_fun1
|
||||
//
|
||||
// Note that mem_fun calls member functions via *pointers* to classes
|
||||
// and not instances of classes. mem_fun_ref is for calling functions
|
||||
// via instances of classes or references to classes.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
|
||||
/// mem_fun_t
|
||||
///
|
||||
/// Member function with no arguments.
|
||||
///
|
||||
template <typename Result, typename T>
|
||||
class mem_fun_t : public unary_function<T*, Result>
|
||||
{
|
||||
public:
|
||||
typedef Result (T::*MemberFunction)();
|
||||
|
||||
EA_FORCE_INLINE explicit mem_fun_t(MemberFunction pMemberFunction)
|
||||
: mpMemberFunction(pMemberFunction)
|
||||
{
|
||||
// Empty
|
||||
}
|
||||
|
||||
EA_FORCE_INLINE Result operator()(T* pT) const
|
||||
{
|
||||
return (pT->*mpMemberFunction)();
|
||||
}
|
||||
|
||||
protected:
|
||||
MemberFunction mpMemberFunction;
|
||||
};
|
||||
|
||||
|
||||
/// mem_fun1_t
|
||||
///
|
||||
/// Member function with one argument.
|
||||
///
|
||||
template <typename Result, typename T, typename Argument>
|
||||
class mem_fun1_t : public binary_function<T*, Argument, Result>
|
||||
{
|
||||
public:
|
||||
typedef Result (T::*MemberFunction)(Argument);
|
||||
|
||||
EA_FORCE_INLINE explicit mem_fun1_t(MemberFunction pMemberFunction)
|
||||
: mpMemberFunction(pMemberFunction)
|
||||
{
|
||||
// Empty
|
||||
}
|
||||
|
||||
EA_FORCE_INLINE Result operator()(T* pT, Argument arg) const
|
||||
{
|
||||
return (pT->*mpMemberFunction)(arg);
|
||||
}
|
||||
|
||||
protected:
|
||||
MemberFunction mpMemberFunction;
|
||||
};
|
||||
|
||||
|
||||
/// const_mem_fun_t
|
||||
///
|
||||
/// Const member function with no arguments.
|
||||
/// Note that we inherit from unary_function<const T*, Result>
|
||||
/// instead of what the C++ standard specifies: unary_function<T*, Result>.
|
||||
/// The C++ standard is in error and this has been recognized by the defect group.
|
||||
///
|
||||
template <typename Result, typename T>
|
||||
class const_mem_fun_t : public unary_function<const T*, Result>
|
||||
{
|
||||
public:
|
||||
typedef Result (T::*MemberFunction)() const;
|
||||
|
||||
EA_FORCE_INLINE explicit const_mem_fun_t(MemberFunction pMemberFunction)
|
||||
: mpMemberFunction(pMemberFunction)
|
||||
{
|
||||
// Empty
|
||||
}
|
||||
|
||||
EA_FORCE_INLINE Result operator()(const T* pT) const
|
||||
{
|
||||
return (pT->*mpMemberFunction)();
|
||||
}
|
||||
|
||||
protected:
|
||||
MemberFunction mpMemberFunction;
|
||||
};
|
||||
|
||||
|
||||
/// const_mem_fun1_t
|
||||
///
|
||||
/// Const member function with one argument.
|
||||
/// Note that we inherit from unary_function<const T*, Result>
|
||||
/// instead of what the C++ standard specifies: unary_function<T*, Result>.
|
||||
/// The C++ standard is in error and this has been recognized by the defect group.
|
||||
///
|
||||
template <typename Result, typename T, typename Argument>
|
||||
class const_mem_fun1_t : public binary_function<const T*, Argument, Result>
|
||||
{
|
||||
public:
|
||||
typedef Result (T::*MemberFunction)(Argument) const;
|
||||
|
||||
EA_FORCE_INLINE explicit const_mem_fun1_t(MemberFunction pMemberFunction)
|
||||
: mpMemberFunction(pMemberFunction)
|
||||
{
|
||||
// Empty
|
||||
}
|
||||
|
||||
EA_FORCE_INLINE Result operator()(const T* pT, Argument arg) const
|
||||
{
|
||||
return (pT->*mpMemberFunction)(arg);
|
||||
}
|
||||
|
||||
protected:
|
||||
MemberFunction mpMemberFunction;
|
||||
};
|
||||
|
||||
|
||||
/// mem_fun
|
||||
///
|
||||
/// This is the high level interface to the mem_fun_t family.
|
||||
///
|
||||
/// Example usage:
|
||||
/// struct TestClass { void print() { puts("hello"); } }
|
||||
/// TestClass* pTestClassArray[3] = { ... };
|
||||
/// for_each(pTestClassArray, pTestClassArray + 3, &TestClass::print);
|
||||
///
|
||||
template <typename Result, typename T>
|
||||
EA_FORCE_INLINE mem_fun_t<Result, T>
|
||||
mem_fun(Result (T::*MemberFunction)())
|
||||
{
|
||||
return eastl::mem_fun_t<Result, T>(MemberFunction);
|
||||
}
|
||||
|
||||
template <typename Result, typename T, typename Argument>
|
||||
EA_FORCE_INLINE mem_fun1_t<Result, T, Argument>
|
||||
mem_fun(Result (T::*MemberFunction)(Argument))
|
||||
{
|
||||
return eastl::mem_fun1_t<Result, T, Argument>(MemberFunction);
|
||||
}
|
||||
|
||||
template <typename Result, typename T>
|
||||
EA_FORCE_INLINE const_mem_fun_t<Result, T>
|
||||
mem_fun(Result (T::*MemberFunction)() const)
|
||||
{
|
||||
return eastl::const_mem_fun_t<Result, T>(MemberFunction);
|
||||
}
|
||||
|
||||
template <typename Result, typename T, typename Argument>
|
||||
EA_FORCE_INLINE const_mem_fun1_t<Result, T, Argument>
|
||||
mem_fun(Result (T::*MemberFunction)(Argument) const)
|
||||
{
|
||||
return eastl::const_mem_fun1_t<Result, T, Argument>(MemberFunction);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// mem_fun_ref
|
||||
// mem_fun1_ref
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
|
||||
/// mem_fun_ref_t
|
||||
///
|
||||
template <typename Result, typename T>
|
||||
class mem_fun_ref_t : public unary_function<T, Result>
|
||||
{
|
||||
public:
|
||||
typedef Result (T::*MemberFunction)();
|
||||
|
||||
EA_FORCE_INLINE explicit mem_fun_ref_t(MemberFunction pMemberFunction)
|
||||
: mpMemberFunction(pMemberFunction)
|
||||
{
|
||||
// Empty
|
||||
}
|
||||
|
||||
EA_FORCE_INLINE Result operator()(T& t) const
|
||||
{
|
||||
return (t.*mpMemberFunction)();
|
||||
}
|
||||
|
||||
protected:
|
||||
MemberFunction mpMemberFunction;
|
||||
};
|
||||
|
||||
|
||||
/// mem_fun1_ref_t
|
||||
///
|
||||
template <typename Result, typename T, typename Argument>
|
||||
class mem_fun1_ref_t : public binary_function<T, Argument, Result>
|
||||
{
|
||||
public:
|
||||
typedef Result (T::*MemberFunction)(Argument);
|
||||
|
||||
EA_FORCE_INLINE explicit mem_fun1_ref_t(MemberFunction pMemberFunction)
|
||||
: mpMemberFunction(pMemberFunction)
|
||||
{
|
||||
// Empty
|
||||
}
|
||||
|
||||
EA_FORCE_INLINE Result operator()(T& t, Argument arg) const
|
||||
{
|
||||
return (t.*mpMemberFunction)(arg);
|
||||
}
|
||||
|
||||
protected:
|
||||
MemberFunction mpMemberFunction;
|
||||
};
|
||||
|
||||
|
||||
/// const_mem_fun_ref_t
|
||||
///
|
||||
template <typename Result, typename T>
|
||||
class const_mem_fun_ref_t : public unary_function<T, Result>
|
||||
{
|
||||
public:
|
||||
typedef Result (T::*MemberFunction)() const;
|
||||
|
||||
EA_FORCE_INLINE explicit const_mem_fun_ref_t(MemberFunction pMemberFunction)
|
||||
: mpMemberFunction(pMemberFunction)
|
||||
{
|
||||
// Empty
|
||||
}
|
||||
|
||||
EA_FORCE_INLINE Result operator()(const T& t) const
|
||||
{
|
||||
return (t.*mpMemberFunction)();
|
||||
}
|
||||
|
||||
protected:
|
||||
MemberFunction mpMemberFunction;
|
||||
};
|
||||
|
||||
|
||||
/// const_mem_fun1_ref_t
|
||||
///
|
||||
template <typename Result, typename T, typename Argument>
|
||||
class const_mem_fun1_ref_t : public binary_function<T, Argument, Result>
|
||||
{
|
||||
public:
|
||||
typedef Result (T::*MemberFunction)(Argument) const;
|
||||
|
||||
EA_FORCE_INLINE explicit const_mem_fun1_ref_t(MemberFunction pMemberFunction)
|
||||
: mpMemberFunction(pMemberFunction)
|
||||
{
|
||||
// Empty
|
||||
}
|
||||
|
||||
EA_FORCE_INLINE Result operator()(const T& t, Argument arg) const
|
||||
{
|
||||
return (t.*mpMemberFunction)(arg);
|
||||
}
|
||||
|
||||
protected:
|
||||
MemberFunction mpMemberFunction;
|
||||
};
|
||||
|
||||
|
||||
/// mem_fun_ref
|
||||
/// Example usage:
|
||||
/// struct TestClass { void print() { puts("hello"); } }
|
||||
/// TestClass testClassArray[3];
|
||||
/// for_each(testClassArray, testClassArray + 3, &TestClass::print);
|
||||
///
|
||||
template <typename Result, typename T>
|
||||
EA_FORCE_INLINE mem_fun_ref_t<Result, T>
|
||||
mem_fun_ref(Result (T::*MemberFunction)())
|
||||
{
|
||||
return eastl::mem_fun_ref_t<Result, T>(MemberFunction);
|
||||
}
|
||||
|
||||
template <typename Result, typename T, typename Argument>
|
||||
EA_FORCE_INLINE mem_fun1_ref_t<Result, T, Argument>
|
||||
mem_fun_ref(Result (T::*MemberFunction)(Argument))
|
||||
{
|
||||
return eastl::mem_fun1_ref_t<Result, T, Argument>(MemberFunction);
|
||||
}
|
||||
|
||||
template <typename Result, typename T>
|
||||
EA_FORCE_INLINE const_mem_fun_ref_t<Result, T>
|
||||
mem_fun_ref(Result (T::*MemberFunction)() const)
|
||||
{
|
||||
return eastl::const_mem_fun_ref_t<Result, T>(MemberFunction);
|
||||
}
|
||||
|
||||
template <typename Result, typename T, typename Argument>
|
||||
EA_FORCE_INLINE const_mem_fun1_ref_t<Result, T, Argument>
|
||||
mem_fun_ref(Result (T::*MemberFunction)(Argument) const)
|
||||
{
|
||||
return eastl::const_mem_fun1_ref_t<Result, T, Argument>(MemberFunction);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// hash
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <typename T> struct hash;
|
||||
|
||||
template <typename T> struct hash<T*> // Note that we use the pointer as-is and don't divide by sizeof(T*). This is because the table is of a prime size and this division doesn't benefit distribution.
|
||||
{ size_t operator()(T* p) const { return size_t(uintptr_t(p)); } };
|
||||
|
||||
template <> struct hash<bool>
|
||||
{ size_t operator()(bool val) const { return static_cast<size_t>(val); } };
|
||||
|
||||
template <> struct hash<char>
|
||||
{ size_t operator()(char val) const { return static_cast<size_t>(val); } };
|
||||
|
||||
template <> struct hash<signed char>
|
||||
{ size_t operator()(signed char val) const { return static_cast<size_t>(val); } };
|
||||
|
||||
template <> struct hash<unsigned char>
|
||||
{ size_t operator()(unsigned char val) const { return static_cast<size_t>(val); } };
|
||||
|
||||
#ifndef EA_WCHAR_T_NON_NATIVE // If wchar_t is a native type instead of simply a define to an existing type...
|
||||
template <> struct hash<wchar_t>
|
||||
{ size_t operator()(wchar_t val) const { return static_cast<size_t>(val); } };
|
||||
#endif
|
||||
|
||||
template <> struct hash<signed short>
|
||||
{ size_t operator()(short val) const { return static_cast<size_t>(val); } };
|
||||
|
||||
template <> struct hash<unsigned short>
|
||||
{ size_t operator()(unsigned short val) const { return static_cast<size_t>(val); } };
|
||||
|
||||
template <> struct hash<signed int>
|
||||
{ size_t operator()(signed int val) const { return static_cast<size_t>(val); } };
|
||||
|
||||
template <> struct hash<unsigned int>
|
||||
{ size_t operator()(unsigned int val) const { return static_cast<size_t>(val); } };
|
||||
|
||||
template <> struct hash<signed long>
|
||||
{ size_t operator()(signed long val) const { return static_cast<size_t>(val); } };
|
||||
|
||||
template <> struct hash<unsigned long>
|
||||
{ size_t operator()(unsigned long val) const { return static_cast<size_t>(val); } };
|
||||
|
||||
template <> struct hash<signed long long>
|
||||
{ size_t operator()(signed long long val) const { return static_cast<size_t>(val); } };
|
||||
|
||||
template <> struct hash<unsigned long long>
|
||||
{ size_t operator()(unsigned long long val) const { return static_cast<size_t>(val); } };
|
||||
|
||||
template <> struct hash<float>
|
||||
{ size_t operator()(float val) const { return static_cast<size_t>(val); } };
|
||||
|
||||
template <> struct hash<double>
|
||||
{ size_t operator()(double val) const { return static_cast<size_t>(val); } };
|
||||
|
||||
template <> struct hash<long double>
|
||||
{ size_t operator()(long double val) const { return static_cast<size_t>(val); } };
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// string hashes
|
||||
//
|
||||
// Note that our string hashes here intentionally are slow for long strings.
|
||||
// The reasoning for this is so:
|
||||
// - The large majority of hashed strings are only a few bytes long.
|
||||
// - The hash function is significantly more efficient if it can make this assumption.
|
||||
// - The user is welcome to make a custom hash for those uncommon cases where
|
||||
// long strings need to be hashed. Indeed, the user can probably make a
|
||||
// special hash customized for such strings that's better than what we provide.
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <> struct hash<char8_t*>
|
||||
{
|
||||
size_t operator()(const char8_t* p) const
|
||||
{
|
||||
size_t c, result = 2166136261U; // FNV1 hash. Perhaps the best string hash.
|
||||
while((c = (uint8_t)*p++) != 0) // Using '!=' disables compiler warnings.
|
||||
result = (result * 16777619) ^ c;
|
||||
return (size_t)result;
|
||||
}
|
||||
};
|
||||
|
||||
template <> struct hash<const char8_t*>
|
||||
{
|
||||
size_t operator()(const char8_t* p) const
|
||||
{
|
||||
size_t c, result = 2166136261U;
|
||||
while((c = (uint8_t)*p++) != 0) // cast to unsigned 8 bit.
|
||||
result = (result * 16777619) ^ c;
|
||||
return (size_t)result;
|
||||
}
|
||||
};
|
||||
|
||||
template <> struct hash<char16_t*>
|
||||
{
|
||||
size_t operator()(const char16_t* p) const
|
||||
{
|
||||
size_t c, result = 2166136261U;
|
||||
while((c = (uint16_t)*p++) != 0) // cast to unsigned 16 bit.
|
||||
result = (result * 16777619) ^ c;
|
||||
return (size_t)result;
|
||||
}
|
||||
};
|
||||
|
||||
template <> struct hash<const char16_t*>
|
||||
{
|
||||
size_t operator()(const char16_t* p) const
|
||||
{
|
||||
size_t c, result = 2166136261U;
|
||||
while((c = (uint16_t)*p++) != 0) // cast to unsigned 16 bit.
|
||||
result = (result * 16777619) ^ c;
|
||||
return (size_t)result;
|
||||
}
|
||||
};
|
||||
|
||||
template <> struct hash<char32_t*>
|
||||
{
|
||||
size_t operator()(const char32_t* p) const
|
||||
{
|
||||
size_t c, result = 2166136261U;
|
||||
while((c = (uint32_t)*p++) != 0) // cast to unsigned 32 bit.
|
||||
result = (result * 16777619) ^ c;
|
||||
return (size_t)result;
|
||||
}
|
||||
};
|
||||
|
||||
template <> struct hash<const char32_t*>
|
||||
{
|
||||
size_t operator()(const char32_t* p) const
|
||||
{
|
||||
size_t c, result = 2166136261U;
|
||||
while((c = (uint32_t)*p++) != 0) // cast to unsigned 32 bit.
|
||||
result = (result * 16777619) ^ c;
|
||||
return (size_t)result;
|
||||
}
|
||||
};
|
||||
|
||||
/// string_hash
|
||||
///
|
||||
/// Defines a generic string hash for an arbitrary EASTL basic_string container.
|
||||
///
|
||||
/// Example usage:
|
||||
/// eastl::hash_set<MyString, eastl::string_hash<MyString> > hashSet;
|
||||
///
|
||||
template <typename String>
|
||||
struct string_hash
|
||||
{
|
||||
typedef String string_type;
|
||||
typedef typename String::value_type value_type;
|
||||
typedef typename eastl::add_unsigned<value_type>::type unsigned_value_type;
|
||||
|
||||
size_t operator()(const string_type& s) const
|
||||
{
|
||||
const unsigned_value_type* p = (const unsigned_value_type*)s.c_str();
|
||||
size_t c, result = 2166136261U;
|
||||
while((c = *p++) != 0)
|
||||
result = (result * 16777619) ^ c;
|
||||
return (size_t)result;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
} // namespace eastl
|
||||
|
||||
|
||||
#endif // Header include guard
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
335
lib/eastl/include/EASTL/hash_map.h
Normal file
335
lib/eastl/include/EASTL/hash_map.h
Normal file
|
@ -0,0 +1,335 @@
|
|||
/*
|
||||
Copyright (C) 2009-2010 Electronic Arts, Inc. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
3. Neither the name of Electronic Arts, Inc. ("EA") nor the names of
|
||||
its contributors may be used to endorse or promote products derived
|
||||
from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY ELECTRONIC ARTS AND ITS CONTRIBUTORS "AS IS" AND ANY
|
||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL ELECTRONIC ARTS OR ITS CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// EASTL/hash_map.h
|
||||
//
|
||||
// Copyright (c) 2005, Electronic Arts. All rights reserved.
|
||||
// Written and maintained by Paul Pedriana.
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// This file is based on the TR1 (technical report 1) reference implementation
|
||||
// of the unordered_set/unordered_map C++ classes as of about 4/2005. Most likely
|
||||
// many or all C++ library vendors' implementations of this classes will be
|
||||
// based off of the reference version and so will look pretty similar to this
|
||||
// file as well as other vendors' versions.
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
#ifndef EASTL_HASH_MAP_H
|
||||
#define EASTL_HASH_MAP_H
|
||||
|
||||
|
||||
#include <EASTL/internal/config.h>
|
||||
#include <EASTL/internal/hashtable.h>
|
||||
#include <EASTL/functional.h>
|
||||
#include <EASTL/utility.h>
|
||||
|
||||
|
||||
|
||||
namespace eastl
|
||||
{
|
||||
|
||||
/// EASTL_HASH_MAP_DEFAULT_NAME
|
||||
///
|
||||
/// Defines a default container name in the absence of a user-provided name.
|
||||
///
|
||||
#ifndef EASTL_HASH_MAP_DEFAULT_NAME
|
||||
#define EASTL_HASH_MAP_DEFAULT_NAME EASTL_DEFAULT_NAME_PREFIX " hash_map" // Unless the user overrides something, this is "EASTL hash_map".
|
||||
#endif
|
||||
|
||||
|
||||
/// EASTL_HASH_MULTIMAP_DEFAULT_NAME
|
||||
///
|
||||
/// Defines a default container name in the absence of a user-provided name.
|
||||
///
|
||||
#ifndef EASTL_HASH_MULTIMAP_DEFAULT_NAME
|
||||
#define EASTL_HASH_MULTIMAP_DEFAULT_NAME EASTL_DEFAULT_NAME_PREFIX " hash_multimap" // Unless the user overrides something, this is "EASTL hash_multimap".
|
||||
#endif
|
||||
|
||||
|
||||
/// EASTL_HASH_MAP_DEFAULT_ALLOCATOR
|
||||
///
|
||||
#ifndef EASTL_HASH_MAP_DEFAULT_ALLOCATOR
|
||||
#define EASTL_HASH_MAP_DEFAULT_ALLOCATOR allocator_type(EASTL_HASH_MAP_DEFAULT_NAME)
|
||||
#endif
|
||||
|
||||
/// EASTL_HASH_MULTIMAP_DEFAULT_ALLOCATOR
|
||||
///
|
||||
#ifndef EASTL_HASH_MULTIMAP_DEFAULT_ALLOCATOR
|
||||
#define EASTL_HASH_MULTIMAP_DEFAULT_ALLOCATOR allocator_type(EASTL_HASH_MULTIMAP_DEFAULT_NAME)
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/// hash_map
|
||||
///
|
||||
/// Implements a hash_map, which is a hashed associative container.
|
||||
/// Lookups are O(1) (that is, they are fast) but the container is
|
||||
/// not sorted.
|
||||
///
|
||||
/// set_max_load_factor
|
||||
/// If you want to make a hashtable never increase its bucket usage,
|
||||
/// call set_max_load_factor with a very high value such as 100000.f.
|
||||
///
|
||||
/// bCacheHashCode
|
||||
/// We provide the boolean bCacheHashCode template parameter in order
|
||||
/// to allow the storing of the hash code of the key within the map.
|
||||
/// When this option is disabled, the rehashing of the table will
|
||||
/// call the hash function on the key. Setting bCacheHashCode to true
|
||||
/// is useful for cases whereby the calculation of the hash value for
|
||||
/// a contained object is very expensive.
|
||||
///
|
||||
/// find_as
|
||||
/// In order to support the ability to have a hashtable of strings but
|
||||
/// be able to do efficiently lookups via char pointers (i.e. so they
|
||||
/// aren't converted to string objects), we provide the find_as
|
||||
/// function. This function allows you to do a find with a key of a
|
||||
/// type other than the hashtable key type.
|
||||
///
|
||||
/// Example find_as usage:
|
||||
/// hash_map<string, int> hashMap;
|
||||
/// i = hashMap.find_as("hello"); // Use default hash and compare.
|
||||
///
|
||||
/// Example find_as usage (namespaces omitted for brevity):
|
||||
/// hash_map<string, int> hashMap;
|
||||
/// i = hashMap.find_as("hello", hash<char*>(), equal_to_2<string, char*>());
|
||||
///
|
||||
template <typename Key, typename T, typename Hash = eastl::hash<Key>, typename Predicate = eastl::equal_to<Key>,
|
||||
typename Allocator = EASTLAllocatorType, bool bCacheHashCode = false>
|
||||
class hash_map
|
||||
: public hashtable<Key, eastl::pair<const Key, T>, Allocator, eastl::use_first<eastl::pair<const Key, T> >, Predicate,
|
||||
Hash, mod_range_hashing, default_ranged_hash, prime_rehash_policy, bCacheHashCode, true, true>
|
||||
{
|
||||
public:
|
||||
typedef hashtable<Key, eastl::pair<const Key, T>, Allocator,
|
||||
eastl::use_first<eastl::pair<const Key, T> >,
|
||||
Predicate, Hash, mod_range_hashing, default_ranged_hash,
|
||||
prime_rehash_policy, bCacheHashCode, true, true> base_type;
|
||||
typedef hash_map<Key, T, Hash, Predicate, Allocator, bCacheHashCode> this_type;
|
||||
typedef typename base_type::size_type size_type;
|
||||
typedef typename base_type::key_type key_type;
|
||||
typedef T mapped_type;
|
||||
typedef typename base_type::value_type value_type; // Note that this is pair<const key_type, mapped_type>.
|
||||
typedef typename base_type::allocator_type allocator_type;
|
||||
typedef typename base_type::node_type node_type;
|
||||
typedef typename base_type::insert_return_type insert_return_type;
|
||||
typedef typename base_type::iterator iterator;
|
||||
|
||||
#if !defined(__GNUC__) || (__GNUC__ >= 3) // GCC 2.x has a bug which we work around.
|
||||
using base_type::insert;
|
||||
#endif
|
||||
|
||||
public:
|
||||
/// hash_map
|
||||
///
|
||||
/// Default constructor.
|
||||
///
|
||||
explicit hash_map(const allocator_type& allocator = EASTL_HASH_MAP_DEFAULT_ALLOCATOR)
|
||||
: base_type(0, Hash(), mod_range_hashing(), default_ranged_hash(),
|
||||
Predicate(), eastl::use_first<eastl::pair<const Key, T> >(), allocator)
|
||||
{
|
||||
// Empty
|
||||
}
|
||||
|
||||
|
||||
/// hash_map
|
||||
///
|
||||
/// Constructor which creates an empty container, but start with nBucketCount buckets.
|
||||
/// We default to a small nBucketCount value, though the user really should manually
|
||||
/// specify an appropriate value in order to prevent memory from being reallocated.
|
||||
///
|
||||
explicit hash_map(size_type nBucketCount, const Hash& hashFunction = Hash(),
|
||||
const Predicate& predicate = Predicate(), const allocator_type& allocator = EASTL_HASH_MAP_DEFAULT_ALLOCATOR)
|
||||
: base_type(nBucketCount, hashFunction, mod_range_hashing(), default_ranged_hash(),
|
||||
predicate, eastl::use_first<eastl::pair<const Key, T> >(), allocator)
|
||||
{
|
||||
// Empty
|
||||
}
|
||||
|
||||
|
||||
/// hash_map
|
||||
///
|
||||
/// An input bucket count of <= 1 causes the bucket count to be equal to the number of
|
||||
/// elements in the input range.
|
||||
///
|
||||
template <typename ForwardIterator>
|
||||
hash_map(ForwardIterator first, ForwardIterator last, size_type nBucketCount = 0, const Hash& hashFunction = Hash(),
|
||||
const Predicate& predicate = Predicate(), const allocator_type& allocator = EASTL_HASH_MAP_DEFAULT_ALLOCATOR)
|
||||
: base_type(first, last, nBucketCount, hashFunction, mod_range_hashing(), default_ranged_hash(),
|
||||
predicate, eastl::use_first<eastl::pair<const Key, T> >(), allocator)
|
||||
{
|
||||
// Empty
|
||||
}
|
||||
|
||||
|
||||
/// insert
|
||||
///
|
||||
/// This is an extension to the C++ standard. We insert a default-constructed
|
||||
/// element with the given key. The reason for this is that we can avoid the
|
||||
/// potentially expensive operation of creating and/or copying a mapped_type
|
||||
/// object on the stack.
|
||||
insert_return_type insert(const key_type& key)
|
||||
{
|
||||
return base_type::DoInsertKey(key, true_type());
|
||||
}
|
||||
|
||||
|
||||
#if defined(__GNUC__) && (__GNUC__ < 3) // If using old GCC (GCC 2.x has a bug which we work around)
|
||||
template <typename InputIterator>
|
||||
void insert(InputIterator first, InputIterator last) { return base_type::insert(first, last); }
|
||||
insert_return_type insert(const value_type& value) { return base_type::insert(value); }
|
||||
iterator insert(const_iterator it, const value_type& value) { return base_type::insert(it, value); }
|
||||
#endif
|
||||
|
||||
|
||||
mapped_type& operator[](const key_type& key)
|
||||
{
|
||||
const typename base_type::iterator it = base_type::find(key);
|
||||
if(it != base_type::end())
|
||||
return (*it).second;
|
||||
return (*base_type::insert(value_type(key, mapped_type())).first).second;
|
||||
}
|
||||
|
||||
}; // hash_map
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/// hash_multimap
|
||||
///
|
||||
/// Implements a hash_multimap, which is the same thing as a hash_map
|
||||
/// except that contained elements need not be unique. See the
|
||||
/// documentation for hash_set for details.
|
||||
///
|
||||
template <typename Key, typename T, typename Hash = eastl::hash<Key>, typename Predicate = eastl::equal_to<Key>,
|
||||
typename Allocator = EASTLAllocatorType, bool bCacheHashCode = false>
|
||||
class hash_multimap
|
||||
: public hashtable<Key, eastl::pair<const Key, T>, Allocator, eastl::use_first<eastl::pair<const Key, T> >, Predicate,
|
||||
Hash, mod_range_hashing, default_ranged_hash, prime_rehash_policy, bCacheHashCode, true, false>
|
||||
{
|
||||
public:
|
||||
typedef hashtable<Key, eastl::pair<const Key, T>, Allocator,
|
||||
eastl::use_first<eastl::pair<const Key, T> >,
|
||||
Predicate, Hash, mod_range_hashing, default_ranged_hash,
|
||||
prime_rehash_policy, bCacheHashCode, true, false> base_type;
|
||||
typedef hash_multimap<Key, T, Hash, Predicate, Allocator, bCacheHashCode> this_type;
|
||||
typedef typename base_type::size_type size_type;
|
||||
typedef typename base_type::key_type key_type;
|
||||
typedef T mapped_type;
|
||||
typedef typename base_type::value_type value_type; // Note that this is pair<const key_type, mapped_type>.
|
||||
typedef typename base_type::allocator_type allocator_type;
|
||||
typedef typename base_type::node_type node_type;
|
||||
typedef typename base_type::insert_return_type insert_return_type;
|
||||
typedef typename base_type::iterator iterator;
|
||||
|
||||
#if !defined(__GNUC__) || (__GNUC__ >= 3) // GCC 2.x has a bug which we work around.
|
||||
using base_type::insert;
|
||||
#endif
|
||||
|
||||
public:
|
||||
/// hash_multimap
|
||||
///
|
||||
/// Default constructor.
|
||||
///
|
||||
explicit hash_multimap(const allocator_type& allocator = EASTL_HASH_MULTIMAP_DEFAULT_ALLOCATOR)
|
||||
: base_type(0, Hash(), mod_range_hashing(), default_ranged_hash(),
|
||||
Predicate(), eastl::use_first<eastl::pair<const Key, T> >(), allocator)
|
||||
{
|
||||
// Empty
|
||||
}
|
||||
|
||||
|
||||
/// hash_multimap
|
||||
///
|
||||
/// Constructor which creates an empty container, but start with nBucketCount buckets.
|
||||
/// We default to a small nBucketCount value, though the user really should manually
|
||||
/// specify an appropriate value in order to prevent memory from being reallocated.
|
||||
///
|
||||
explicit hash_multimap(size_type nBucketCount, const Hash& hashFunction = Hash(),
|
||||
const Predicate& predicate = Predicate(), const allocator_type& allocator = EASTL_HASH_MULTIMAP_DEFAULT_ALLOCATOR)
|
||||
: base_type(nBucketCount, hashFunction, mod_range_hashing(), default_ranged_hash(),
|
||||
predicate, eastl::use_first<eastl::pair<const Key, T> >(), allocator)
|
||||
{
|
||||
// Empty
|
||||
}
|
||||
|
||||
|
||||
/// hash_multimap
|
||||
///
|
||||
/// An input bucket count of <= 1 causes the bucket count to be equal to the number of
|
||||
/// elements in the input range.
|
||||
///
|
||||
template <typename ForwardIterator>
|
||||
hash_multimap(ForwardIterator first, ForwardIterator last, size_type nBucketCount = 0, const Hash& hashFunction = Hash(),
|
||||
const Predicate& predicate = Predicate(), const allocator_type& allocator = EASTL_HASH_MULTIMAP_DEFAULT_ALLOCATOR)
|
||||
: base_type(first, last, nBucketCount, hashFunction, mod_range_hashing(), default_ranged_hash(),
|
||||
predicate, eastl::use_first<eastl::pair<const Key, T> >(), allocator)
|
||||
{
|
||||
// Empty
|
||||
}
|
||||
|
||||
|
||||
/// insert
|
||||
///
|
||||
/// This is an extension to the C++ standard. We insert a default-constructed
|
||||
/// element with the given key. The reason for this is that we can avoid the
|
||||
/// potentially expensive operation of creating and/or copying a mapped_type
|
||||
/// object on the stack.
|
||||
insert_return_type insert(const key_type& key)
|
||||
{
|
||||
return base_type::DoInsertKey(key, false_type());
|
||||
}
|
||||
|
||||
|
||||
#if defined(__GNUC__) && (__GNUC__ < 3) // If using old GCC (GCC 2.x has a bug which we work around)
|
||||
template <typename InputIterator>
|
||||
void insert(InputIterator first, InputIterator last) { return base_type::insert(first, last); }
|
||||
insert_return_type insert(const value_type& value) { return base_type::insert(value); }
|
||||
iterator insert(const_iterator it, const value_type& value) { return base_type::insert(it, value); }
|
||||
#endif
|
||||
|
||||
|
||||
}; // hash_multimap
|
||||
|
||||
|
||||
|
||||
|
||||
} // namespace eastl
|
||||
|
||||
|
||||
#endif // Header include guard
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
270
lib/eastl/include/EASTL/hash_set.h
Normal file
270
lib/eastl/include/EASTL/hash_set.h
Normal file
|
@ -0,0 +1,270 @@
|
|||
/*
|
||||
Copyright (C) 2009-2010 Electronic Arts, Inc. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
3. Neither the name of Electronic Arts, Inc. ("EA") nor the names of
|
||||
its contributors may be used to endorse or promote products derived
|
||||
from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY ELECTRONIC ARTS AND ITS CONTRIBUTORS "AS IS" AND ANY
|
||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL ELECTRONIC ARTS OR ITS CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// EASTL/hash_set.h
|
||||
//
|
||||
// Copyright (c) 2005, Electronic Arts. All rights reserved.
|
||||
// Written and maintained by Paul Pedriana.
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// This file is based on the TR1 (technical report 1) reference implementation
|
||||
// of the unordered_set/unordered_map C++ classes as of about 4/2005. Most likely
|
||||
// many or all C++ library vendors' implementations of this classes will be
|
||||
// based off of the reference version and so will look pretty similar to this
|
||||
// file as well as other vendors' versions.
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
#ifndef EASTL_HASH_SET_H
|
||||
#define EASTL_HASH_SET_H
|
||||
|
||||
|
||||
#include <EASTL/internal/config.h>
|
||||
#include <EASTL/internal/hashtable.h>
|
||||
#include <EASTL/functional.h>
|
||||
#include <EASTL/utility.h>
|
||||
|
||||
|
||||
|
||||
namespace eastl
|
||||
{
|
||||
|
||||
/// EASTL_HASH_SET_DEFAULT_NAME
|
||||
///
|
||||
/// Defines a default container name in the absence of a user-provided name.
|
||||
///
|
||||
#ifndef EASTL_HASH_SET_DEFAULT_NAME
|
||||
#define EASTL_HASH_SET_DEFAULT_NAME EASTL_DEFAULT_NAME_PREFIX " hash_set" // Unless the user overrides something, this is "EASTL hash_set".
|
||||
#endif
|
||||
|
||||
|
||||
/// EASTL_HASH_MULTISET_DEFAULT_NAME
|
||||
///
|
||||
/// Defines a default container name in the absence of a user-provided name.
|
||||
///
|
||||
#ifndef EASTL_HASH_MULTISET_DEFAULT_NAME
|
||||
#define EASTL_HASH_MULTISET_DEFAULT_NAME EASTL_DEFAULT_NAME_PREFIX " hash_multiset" // Unless the user overrides something, this is "EASTL hash_multiset".
|
||||
#endif
|
||||
|
||||
|
||||
/// EASTL_HASH_SET_DEFAULT_ALLOCATOR
|
||||
///
|
||||
#ifndef EASTL_HASH_SET_DEFAULT_ALLOCATOR
|
||||
#define EASTL_HASH_SET_DEFAULT_ALLOCATOR allocator_type(EASTL_HASH_SET_DEFAULT_NAME)
|
||||
#endif
|
||||
|
||||
/// EASTL_HASH_MULTISET_DEFAULT_ALLOCATOR
|
||||
///
|
||||
#ifndef EASTL_HASH_MULTISET_DEFAULT_ALLOCATOR
|
||||
#define EASTL_HASH_MULTISET_DEFAULT_ALLOCATOR allocator_type(EASTL_HASH_MULTISET_DEFAULT_NAME)
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/// hash_set
|
||||
///
|
||||
/// Implements a hash_set, which is a hashed unique-item container.
|
||||
/// Lookups are O(1) (that is, they are fast) but the container is
|
||||
/// not sorted.
|
||||
///
|
||||
/// set_max_load_factor
|
||||
/// If you want to make a hashtable never increase its bucket usage,
|
||||
/// call set_max_load_factor with a very high value such as 100000.f.
|
||||
///
|
||||
/// bCacheHashCode
|
||||
/// We provide the boolean bCacheHashCode template parameter in order
|
||||
/// to allow the storing of the hash code of the key within the map.
|
||||
/// When this option is disabled, the rehashing of the table will
|
||||
/// call the hash function on the key. Setting bCacheHashCode to true
|
||||
/// is useful for cases whereby the calculation of the hash value for
|
||||
/// a contained object is very expensive.
|
||||
///
|
||||
/// find_as
|
||||
/// In order to support the ability to have a hashtable of strings but
|
||||
/// be able to do efficiently lookups via char pointers (i.e. so they
|
||||
/// aren't converted to string objects), we provide the find_as
|
||||
/// function. This function allows you to do a find with a key of a
|
||||
/// type other than the hashtable key type.
|
||||
///
|
||||
/// Example find_as usage:
|
||||
/// hash_set<string> hashSet;
|
||||
/// i = hashSet.find_as("hello"); // Use default hash and compare.
|
||||
///
|
||||
/// Example find_as usage (namespaces omitted for brevity):
|
||||
/// hash_set<string> hashSet;
|
||||
/// i = hashSet.find_as("hello", hash<char*>(), equal_to_2<string, char*>());
|
||||
///
|
||||
template <typename Value, typename Hash = eastl::hash<Value>, typename Predicate = eastl::equal_to<Value>,
|
||||
typename Allocator = EASTLAllocatorType, bool bCacheHashCode = false>
|
||||
class hash_set
|
||||
: public hashtable<Value, Value, Allocator, eastl::use_self<Value>, Predicate,
|
||||
Hash, mod_range_hashing, default_ranged_hash,
|
||||
prime_rehash_policy, bCacheHashCode, false, true>
|
||||
{
|
||||
public:
|
||||
typedef hashtable<Value, Value, Allocator, eastl::use_self<Value>, Predicate,
|
||||
Hash, mod_range_hashing, default_ranged_hash,
|
||||
prime_rehash_policy, bCacheHashCode, false, true> base_type;
|
||||
typedef hash_set<Value, Hash, Predicate, Allocator, bCacheHashCode> this_type;
|
||||
typedef typename base_type::size_type size_type;
|
||||
typedef typename base_type::value_type value_type;
|
||||
typedef typename base_type::allocator_type allocator_type;
|
||||
typedef typename base_type::node_type node_type;
|
||||
|
||||
public:
|
||||
/// hash_set
|
||||
///
|
||||
/// Default constructor.
|
||||
///
|
||||
explicit hash_set(const allocator_type& allocator = EASTL_HASH_SET_DEFAULT_ALLOCATOR)
|
||||
: base_type(0, Hash(), mod_range_hashing(), default_ranged_hash(), Predicate(), eastl::use_self<Value>(), allocator)
|
||||
{
|
||||
// Empty
|
||||
}
|
||||
|
||||
|
||||
/// hash_set
|
||||
///
|
||||
/// Constructor which creates an empty container, but start with nBucketCount buckets.
|
||||
/// We default to a small nBucketCount value, though the user really should manually
|
||||
/// specify an appropriate value in order to prevent memory from being reallocated.
|
||||
///
|
||||
explicit hash_set(size_type nBucketCount, const Hash& hashFunction = Hash(), const Predicate& predicate = Predicate(),
|
||||
const allocator_type& allocator = EASTL_HASH_SET_DEFAULT_ALLOCATOR)
|
||||
: base_type(nBucketCount, hashFunction, mod_range_hashing(), default_ranged_hash(), predicate, eastl::use_self<Value>(), allocator)
|
||||
{
|
||||
// Empty
|
||||
}
|
||||
|
||||
|
||||
/// hash_set
|
||||
///
|
||||
/// An input bucket count of <= 1 causes the bucket count to be equal to the number of
|
||||
/// elements in the input range.
|
||||
///
|
||||
template <typename FowardIterator>
|
||||
hash_set(FowardIterator first, FowardIterator last, size_type nBucketCount = 0, const Hash& hashFunction = Hash(),
|
||||
const Predicate& predicate = Predicate(), const allocator_type& allocator = EASTL_HASH_SET_DEFAULT_ALLOCATOR)
|
||||
: base_type(first, last, nBucketCount, hashFunction, mod_range_hashing(), default_ranged_hash(), predicate, eastl::use_self<Value>(), allocator)
|
||||
{
|
||||
// Empty
|
||||
}
|
||||
|
||||
}; // hash_set
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/// hash_multiset
|
||||
///
|
||||
/// Implements a hash_multiset, which is the same thing as a hash_set
|
||||
/// except that contained elements need not be unique. See the documentation
|
||||
/// for hash_set for details.
|
||||
///
|
||||
template <typename Value, typename Hash = eastl::hash<Value>, typename Predicate = eastl::equal_to<Value>,
|
||||
typename Allocator = EASTLAllocatorType, bool bCacheHashCode = false>
|
||||
class hash_multiset
|
||||
: public hashtable<Value, Value, Allocator, eastl::use_self<Value>, Predicate,
|
||||
Hash, mod_range_hashing, default_ranged_hash,
|
||||
prime_rehash_policy, bCacheHashCode, false, false>
|
||||
{
|
||||
public:
|
||||
typedef hashtable<Value, Value, Allocator, eastl::use_self<Value>, Predicate,
|
||||
Hash, mod_range_hashing, default_ranged_hash,
|
||||
prime_rehash_policy, bCacheHashCode, false, false> base_type;
|
||||
typedef hash_multiset<Value, Hash, Predicate, Allocator, bCacheHashCode> this_type;
|
||||
typedef typename base_type::size_type size_type;
|
||||
typedef typename base_type::value_type value_type;
|
||||
typedef typename base_type::allocator_type allocator_type;
|
||||
typedef typename base_type::node_type node_type;
|
||||
|
||||
public:
|
||||
/// hash_multiset
|
||||
///
|
||||
/// Default constructor.
|
||||
///
|
||||
explicit hash_multiset(const allocator_type& allocator = EASTL_HASH_MULTISET_DEFAULT_ALLOCATOR)
|
||||
: base_type(0, Hash(), mod_range_hashing(), default_ranged_hash(), Predicate(), eastl::use_self<Value>(), allocator)
|
||||
{
|
||||
// Empty
|
||||
}
|
||||
|
||||
|
||||
/// hash_multiset
|
||||
///
|
||||
/// Constructor which creates an empty container, but start with nBucketCount buckets.
|
||||
/// We default to a small nBucketCount value, though the user really should manually
|
||||
/// specify an appropriate value in order to prevent memory from being reallocated.
|
||||
///
|
||||
explicit hash_multiset(size_type nBucketCount, const Hash& hashFunction = Hash(),
|
||||
const Predicate& predicate = Predicate(), const allocator_type& allocator = EASTL_HASH_MULTISET_DEFAULT_ALLOCATOR)
|
||||
: base_type(nBucketCount, hashFunction, mod_range_hashing(), default_ranged_hash(), predicate, eastl::use_self<Value>(), allocator)
|
||||
{
|
||||
// Empty
|
||||
}
|
||||
|
||||
|
||||
/// hash_multiset
|
||||
///
|
||||
/// An input bucket count of <= 1 causes the bucket count to be equal to the number of
|
||||
/// elements in the input range.
|
||||
///
|
||||
template <typename FowardIterator>
|
||||
hash_multiset(FowardIterator first, FowardIterator last, size_type nBucketCount = 0, const Hash& hashFunction = Hash(),
|
||||
const Predicate& predicate = Predicate(), const allocator_type& allocator = EASTL_HASH_MULTISET_DEFAULT_ALLOCATOR)
|
||||
: base_type(first, last, nBucketCount, hashFunction, mod_range_hashing(), default_ranged_hash(), predicate, eastl::use_self<Value>(), allocator)
|
||||
{
|
||||
// Empty
|
||||
}
|
||||
|
||||
|
||||
}; // hash_multiset
|
||||
|
||||
|
||||
|
||||
|
||||
} // namespace eastl
|
||||
|
||||
|
||||
#endif // Header include guard
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
592
lib/eastl/include/EASTL/heap.h
Normal file
592
lib/eastl/include/EASTL/heap.h
Normal file
|
@ -0,0 +1,592 @@
|
|||
/*
|
||||
Copyright (C) 2009-2010 Electronic Arts, Inc. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
3. Neither the name of Electronic Arts, Inc. ("EA") nor the names of
|
||||
its contributors may be used to endorse or promote products derived
|
||||
from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY ELECTRONIC ARTS AND ITS CONTRIBUTORS "AS IS" AND ANY
|
||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL ELECTRONIC ARTS OR ITS CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// EASTL/heap.h
|
||||
//
|
||||
// Copyright (c) 2005, Electronic Arts. All rights reserved.
|
||||
// Written and maintained by Paul Pedriana.
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// This file implements heap functionality much like the std C++ heap algorithms.
|
||||
// Such heaps are not the same thing as memory heaps or pools, but rather are
|
||||
// semi-sorted random access containers which have the primary purpose of
|
||||
// supporting the implementation of priority_queue and similar data structures.
|
||||
//
|
||||
// The primary distinctions between this heap functionality and std::heap are:
|
||||
// - This heap exposes some extra functionality such as is_heap and change_heap.
|
||||
// - This heap is more efficient than versions found in typical STL
|
||||
// implementations. This comes
|
||||
// about due to better use of array dereferencing and branch prediction.
|
||||
// You should expect of 5-30%, depending on the usage and platform.
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// The publicly usable functions we define are:
|
||||
// push_heap -- Adds an entry to a heap. Same as C++ std::push_heap.
|
||||
// pop_heap -- Removes the top entry from a heap. Same as C++ std::pop_heap.
|
||||
// make_heap -- Converts an array to a heap. Same as C++ std::make_heap.
|
||||
// sort_heap -- Sorts a heap in place. Same as C++ std::sort_heap.
|
||||
// remove_heap -- Removes an arbitrary entry from a heap.
|
||||
// change_heap -- Changes the priority of an entry in the heap.
|
||||
// is_heap -- Returns true if an array appears is in heap format.
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
#ifndef EASTL_HEAP_H
|
||||
#define EASTL_HEAP_H
|
||||
|
||||
|
||||
#include <EASTL/internal/config.h>
|
||||
#include <EASTL/iterator.h>
|
||||
#include <stddef.h>
|
||||
|
||||
|
||||
|
||||
namespace eastl
|
||||
{
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// promote_heap (internal function)
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
|
||||
/// promote_heap
|
||||
///
|
||||
/// Moves a value in the heap from a given position upward until
|
||||
/// it is sorted correctly. It's kind of like bubble-sort, except that
|
||||
/// instead of moving linearly from the back of a list to the front,
|
||||
/// it moves from the bottom of the tree up the branches towards the
|
||||
/// top. But otherwise is just like bubble-sort.
|
||||
///
|
||||
/// This function requires that the value argument refer to a value
|
||||
/// that is currently not within the heap.
|
||||
///
|
||||
template <typename RandomAccessIterator, typename Distance, typename T>
|
||||
inline void promote_heap(RandomAccessIterator first, Distance topPosition, Distance position, const T& value)
|
||||
{
|
||||
for(Distance parentPosition = (position - 1) >> 1; // This formula assumes that (position > 0). // We use '>> 1' instead of '/ 2' because we have seen VC++ generate better code with >>.
|
||||
(position > topPosition) && (*(first + parentPosition) < value);
|
||||
parentPosition = (position - 1) >> 1)
|
||||
{
|
||||
*(first + position) = *(first + parentPosition); // Swap the node with its parent.
|
||||
position = parentPosition;
|
||||
}
|
||||
|
||||
*(first + position) = value;
|
||||
}
|
||||
|
||||
/// promote_heap
|
||||
///
|
||||
/// Takes a Compare(a, b) function (or function object) which returns true if a < b.
|
||||
/// For example, you could use the standard 'less' comparison object.
|
||||
///
|
||||
/// The Compare function must work equivalently to the compare function used
|
||||
/// to make and maintain the heap.
|
||||
///
|
||||
/// This function requires that the value argument refer to a value
|
||||
/// that is currently not within the heap.
|
||||
///
|
||||
template <typename RandomAccessIterator, typename Distance, typename T, typename Compare>
|
||||
inline void promote_heap(RandomAccessIterator first, Distance topPosition, Distance position, const T& value, Compare compare)
|
||||
{
|
||||
for(Distance parentPosition = (position - 1) >> 1; // This formula assumes that (position > 0). // We use '>> 1' instead of '/ 2' because we have seen VC++ generate better code with >>.
|
||||
(position > topPosition) && compare(*(first + parentPosition), value);
|
||||
parentPosition = (position - 1) >> 1)
|
||||
{
|
||||
*(first + position) = *(first + parentPosition); // Swap the node with its parent.
|
||||
position = parentPosition;
|
||||
}
|
||||
|
||||
*(first + position) = value;
|
||||
}
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// adjust_heap (internal function)
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
|
||||
/// adjust_heap
|
||||
///
|
||||
/// Given a position that has just been vacated, this function moves
|
||||
/// new values into that vacated position appropriately. The value
|
||||
/// argument is an entry which will be inserted into the heap after
|
||||
/// we move nodes into the positions that were vacated.
|
||||
///
|
||||
/// This function requires that the value argument refer to a value
|
||||
/// that is currently not within the heap.
|
||||
///
|
||||
template <typename RandomAccessIterator, typename Distance, typename T>
|
||||
void adjust_heap(RandomAccessIterator first, Distance topPosition, Distance heapSize, Distance position, const T& value)
|
||||
{
|
||||
// We do the conventional approach of moving the position down to the
|
||||
// bottom then inserting the value at the back and moving it up.
|
||||
Distance childPosition = (2 * position) + 2;
|
||||
|
||||
for(; childPosition < heapSize; childPosition = (2 * childPosition) + 2)
|
||||
{
|
||||
if(*(first + childPosition) < *(first + (childPosition - 1))) // Choose the larger of the two children.
|
||||
--childPosition;
|
||||
*(first + position) = *(first + childPosition); // Swap positions with this child.
|
||||
position = childPosition;
|
||||
}
|
||||
|
||||
if(childPosition == heapSize) // If we are at the very last index of the bottom...
|
||||
{
|
||||
*(first + position) = *(first + (childPosition - 1));
|
||||
position = childPosition - 1;
|
||||
}
|
||||
|
||||
eastl::promote_heap<RandomAccessIterator, Distance, T>(first, topPosition, position, value);
|
||||
}
|
||||
|
||||
|
||||
/// adjust_heap
|
||||
///
|
||||
/// The Compare function must work equivalently to the compare function used
|
||||
/// to make and maintain the heap.
|
||||
///
|
||||
/// This function requires that the value argument refer to a value
|
||||
/// that is currently not within the heap.
|
||||
///
|
||||
template <typename RandomAccessIterator, typename Distance, typename T, typename Compare>
|
||||
void adjust_heap(RandomAccessIterator first, Distance topPosition, Distance heapSize, Distance position, const T& value, Compare compare)
|
||||
{
|
||||
// We do the conventional approach of moving the position down to the
|
||||
// bottom then inserting the value at the back and moving it up.
|
||||
Distance childPosition = (2 * position) + 2;
|
||||
|
||||
for(; childPosition < heapSize; childPosition = (2 * childPosition) + 2)
|
||||
{
|
||||
if(compare(*(first + childPosition), *(first + (childPosition - 1)))) // Choose the larger of the two children.
|
||||
--childPosition;
|
||||
*(first + position) = *(first + childPosition); // Swap positions with this child.
|
||||
position = childPosition;
|
||||
}
|
||||
|
||||
if(childPosition == heapSize) // If we are at the bottom...
|
||||
{
|
||||
*(first + position) = *(first + (childPosition - 1));
|
||||
position = childPosition - 1;
|
||||
}
|
||||
|
||||
eastl::promote_heap<RandomAccessIterator, Distance, T, Compare>(first, topPosition, position, value, compare);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// push_heap
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
|
||||
/// push_heap
|
||||
///
|
||||
/// Adds an item to a heap (which is an array). The item necessarily
|
||||
/// comes from the back of the heap (array). Thus, the insertion of a
|
||||
/// new item in a heap is a two step process: push_back and push_heap.
|
||||
///
|
||||
/// Example usage:
|
||||
/// vector<int> heap;
|
||||
///
|
||||
/// heap.push_back(3);
|
||||
/// push_heap(heap.begin(), heap.end()); // Places '3' appropriately.
|
||||
///
|
||||
template <typename RandomAccessIterator>
|
||||
inline void push_heap(RandomAccessIterator first, RandomAccessIterator last)
|
||||
{
|
||||
typedef typename eastl::iterator_traits<RandomAccessIterator>::difference_type difference_type;
|
||||
typedef typename eastl::iterator_traits<RandomAccessIterator>::value_type value_type;
|
||||
|
||||
const value_type tempBottom(*(last - 1));
|
||||
|
||||
eastl::promote_heap<RandomAccessIterator, difference_type, value_type>
|
||||
(first, (difference_type)0, (difference_type)(last - first - 1), tempBottom);
|
||||
}
|
||||
|
||||
|
||||
/// push_heap
|
||||
///
|
||||
/// This version is useful for cases where your object comparison is unusual
|
||||
/// or where you want to have the heap store pointers to objects instead of
|
||||
/// storing the objects themselves (often in order to improve cache coherency
|
||||
/// while doing sorting).
|
||||
///
|
||||
/// The Compare function must work equivalently to the compare function used
|
||||
/// to make and maintain the heap.
|
||||
///
|
||||
template <typename RandomAccessIterator, typename Compare>
|
||||
inline void push_heap(RandomAccessIterator first, RandomAccessIterator last, Compare compare)
|
||||
{
|
||||
typedef typename eastl::iterator_traits<RandomAccessIterator>::difference_type difference_type;
|
||||
typedef typename eastl::iterator_traits<RandomAccessIterator>::value_type value_type;
|
||||
|
||||
const value_type tempBottom(*(last - 1));
|
||||
|
||||
eastl::promote_heap<RandomAccessIterator, difference_type, value_type, Compare>
|
||||
(first, (difference_type)0, (difference_type)(last - first - 1), tempBottom, compare);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// pop_heap
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
|
||||
/// pop_heap
|
||||
///
|
||||
/// Removes the first item from the heap (which is an array), and adjusts
|
||||
/// the heap so that the highest priority item becomes the new first item.
|
||||
///
|
||||
/// Example usage:
|
||||
/// vector<int> heap;
|
||||
///
|
||||
/// heap.push_back(2);
|
||||
/// heap.push_back(3);
|
||||
/// heap.push_back(1);
|
||||
/// <use heap[0], which is the highest priority item in the heap>
|
||||
/// pop_heap(heap.begin(), heap.end()); // Moves heap[0] to the back of the heap and adjusts the heap.
|
||||
/// heap.pop_back(); // Remove value that was just at the top of the heap
|
||||
///
|
||||
template <typename RandomAccessIterator>
|
||||
inline void pop_heap(RandomAccessIterator first, RandomAccessIterator last)
|
||||
{
|
||||
typedef typename eastl::iterator_traits<RandomAccessIterator>::difference_type difference_type;
|
||||
typedef typename eastl::iterator_traits<RandomAccessIterator>::value_type value_type;
|
||||
|
||||
const value_type tempBottom(*(last - 1));
|
||||
*(last - 1) = *first;
|
||||
eastl::adjust_heap<RandomAccessIterator, difference_type, value_type>
|
||||
(first, (difference_type)0, (difference_type)(last - first - 1), 0, tempBottom);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// pop_heap
|
||||
///
|
||||
/// This version is useful for cases where your object comparison is unusual
|
||||
/// or where you want to have the heap store pointers to objects instead of
|
||||
/// storing the objects themselves (often in order to improve cache coherency
|
||||
/// while doing sorting).
|
||||
///
|
||||
/// The Compare function must work equivalently to the compare function used
|
||||
/// to make and maintain the heap.
|
||||
///
|
||||
template <typename RandomAccessIterator, typename Compare>
|
||||
inline void pop_heap(RandomAccessIterator first, RandomAccessIterator last, Compare compare)
|
||||
{
|
||||
typedef typename eastl::iterator_traits<RandomAccessIterator>::difference_type difference_type;
|
||||
typedef typename eastl::iterator_traits<RandomAccessIterator>::value_type value_type;
|
||||
|
||||
const value_type tempBottom(*(last - 1));
|
||||
*(last - 1) = *first;
|
||||
eastl::adjust_heap<RandomAccessIterator, difference_type, value_type, Compare>
|
||||
(first, (difference_type)0, (difference_type)(last - first - 1), 0, tempBottom, compare);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// make_heap
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
/// make_heap
|
||||
///
|
||||
/// Given an array, this function converts it into heap format.
|
||||
/// The complexity is O(n), where n is count of the range.
|
||||
/// The input range is not required to be in any order.
|
||||
///
|
||||
template <typename RandomAccessIterator>
|
||||
void make_heap(RandomAccessIterator first, RandomAccessIterator last)
|
||||
{
|
||||
// We do bottom-up heap construction as per Sedgewick. Such construction is O(n).
|
||||
typedef typename eastl::iterator_traits<RandomAccessIterator>::difference_type difference_type;
|
||||
typedef typename eastl::iterator_traits<RandomAccessIterator>::value_type value_type;
|
||||
|
||||
const difference_type heapSize = last - first;
|
||||
|
||||
if(heapSize >= 2) // If there is anything to do... (we need this check because otherwise the math fails below).
|
||||
{
|
||||
difference_type parentPosition = ((heapSize - 2) >> 1) + 1; // We use '>> 1' instead of '/ 2' because we have seen VC++ generate better code with >>.
|
||||
|
||||
do{
|
||||
--parentPosition;
|
||||
const value_type temp(*(first + parentPosition));
|
||||
eastl::adjust_heap<RandomAccessIterator, difference_type, value_type>
|
||||
(first, parentPosition, heapSize, parentPosition, temp);
|
||||
} while(parentPosition != 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template <typename RandomAccessIterator, typename Compare>
|
||||
void make_heap(RandomAccessIterator first, RandomAccessIterator last, Compare compare)
|
||||
{
|
||||
typedef typename eastl::iterator_traits<RandomAccessIterator>::difference_type difference_type;
|
||||
typedef typename eastl::iterator_traits<RandomAccessIterator>::value_type value_type;
|
||||
|
||||
const difference_type heapSize = last - first;
|
||||
|
||||
if(heapSize >= 2) // If there is anything to do... (we need this check because otherwise the math fails below).
|
||||
{
|
||||
difference_type parentPosition = ((heapSize - 2) >> 1) + 1; // We use '>> 1' instead of '/ 2' because we have seen VC++ generate better code with >>.
|
||||
|
||||
do{
|
||||
--parentPosition;
|
||||
const value_type temp(*(first + parentPosition));
|
||||
eastl::adjust_heap<RandomAccessIterator, difference_type, value_type, Compare>
|
||||
(first, parentPosition, heapSize, parentPosition, temp, compare);
|
||||
} while(parentPosition != 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// sort_heap
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
|
||||
/// sort_heap
|
||||
///
|
||||
/// After the application if this algorithm, the range it was applied to
|
||||
/// is no longer a heap, though it will be a reverse heap (smallest first).
|
||||
/// The item with the lowest priority will be first, and the highest last.
|
||||
/// This is not a stable sort because the relative order of equivalent
|
||||
/// elements is not necessarily preserved.
|
||||
/// The range referenced must be valid; all pointers must be dereferenceable
|
||||
/// and within the sequence the last position is reachable from the first
|
||||
/// by incrementation.
|
||||
/// The complexity is at most O(n * log(n)), where n is count of the range.
|
||||
///
|
||||
template <typename RandomAccessIterator>
|
||||
inline void sort_heap(RandomAccessIterator first, RandomAccessIterator last)
|
||||
{
|
||||
for(; (last - first) > 1; --last) // We simply use the heap to sort itself.
|
||||
eastl::pop_heap<RandomAccessIterator>(first, last);
|
||||
}
|
||||
|
||||
|
||||
/// sort_heap
|
||||
///
|
||||
/// The Compare function must work equivalently to the compare function used
|
||||
/// to make and maintain the heap.
|
||||
///
|
||||
template <typename RandomAccessIterator, typename Compare>
|
||||
inline void sort_heap(RandomAccessIterator first, RandomAccessIterator last, Compare compare)
|
||||
{
|
||||
for(; (last - first) > 1; --last) // We simply use the heap to sort itself.
|
||||
eastl::pop_heap<RandomAccessIterator, Compare>(first, last, compare);
|
||||
}
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// remove_heap
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
|
||||
/// remove_heap
|
||||
///
|
||||
/// Removes an arbitrary entry from the heap and adjusts the heap appropriately.
|
||||
/// This function is unlike pop_heap in that pop_heap moves the top item
|
||||
/// to the back of the heap, whereas remove_heap moves an arbitrary item to
|
||||
/// the back of the heap.
|
||||
///
|
||||
/// Note: Since this function moves the element to the back of the heap and
|
||||
/// doesn't actually remove it from the given container, the user must call
|
||||
/// the container erase function if the user wants to erase the element
|
||||
/// from the container.
|
||||
///
|
||||
template <typename RandomAccessIterator, typename Distance>
|
||||
inline void remove_heap(RandomAccessIterator first, Distance heapSize, Distance position)
|
||||
{
|
||||
typedef typename eastl::iterator_traits<RandomAccessIterator>::difference_type difference_type;
|
||||
typedef typename eastl::iterator_traits<RandomAccessIterator>::value_type value_type;
|
||||
|
||||
const value_type tempBottom(*(first + heapSize - 1));
|
||||
*(first + heapSize - 1) = *(first + position);
|
||||
eastl::adjust_heap<RandomAccessIterator, difference_type, value_type>
|
||||
(first, (difference_type)0, (difference_type)(heapSize - 1), (difference_type)position, tempBottom);
|
||||
}
|
||||
|
||||
|
||||
/// remove_heap
|
||||
///
|
||||
/// The Compare function must work equivalently to the compare function used
|
||||
/// to make and maintain the heap.
|
||||
///
|
||||
/// Note: Since this function moves the element to the back of the heap and
|
||||
/// doesn't actually remove it from the given container, the user must call
|
||||
/// the container erase function if the user wants to erase the element
|
||||
/// from the container.
|
||||
///
|
||||
template <typename RandomAccessIterator, typename Distance, typename Compare>
|
||||
inline void remove_heap(RandomAccessIterator first, Distance heapSize, Distance position, Compare compare)
|
||||
{
|
||||
typedef typename eastl::iterator_traits<RandomAccessIterator>::difference_type difference_type;
|
||||
typedef typename eastl::iterator_traits<RandomAccessIterator>::value_type value_type;
|
||||
|
||||
const value_type tempBottom(*(first + heapSize - 1));
|
||||
*(first + heapSize - 1) = *(first + position);
|
||||
eastl::adjust_heap<RandomAccessIterator, difference_type, value_type, Compare>
|
||||
(first, (difference_type)0, (difference_type)(heapSize - 1), (difference_type)position, tempBottom, compare);
|
||||
}
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// change_heap
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
|
||||
/// change_heap
|
||||
///
|
||||
/// Given a value in the heap that has changed in priority, this function
|
||||
/// adjusts the heap appropriately. The heap size remains unchanged after
|
||||
/// this operation.
|
||||
///
|
||||
template <typename RandomAccessIterator, typename Distance>
|
||||
inline void change_heap(RandomAccessIterator first, Distance heapSize, Distance position)
|
||||
{
|
||||
typedef typename eastl::iterator_traits<RandomAccessIterator>::difference_type difference_type;
|
||||
typedef typename eastl::iterator_traits<RandomAccessIterator>::value_type value_type;
|
||||
|
||||
eastl::remove_heap<RandomAccessIterator, Distance>(first, heapSize, position);
|
||||
|
||||
value_type tempBottom(*(first + heapSize - 1));
|
||||
|
||||
eastl::promote_heap<RandomAccessIterator, difference_type, value_type>
|
||||
(first, (difference_type)0, (difference_type)(heapSize - 1), tempBottom);
|
||||
}
|
||||
|
||||
|
||||
/// change_heap
|
||||
///
|
||||
/// The Compare function must work equivalently to the compare function used
|
||||
/// to make and maintain the heap.
|
||||
///
|
||||
template <typename RandomAccessIterator, typename Distance, typename Compare>
|
||||
inline void change_heap(RandomAccessIterator first, Distance heapSize, Distance position, Compare compare)
|
||||
{
|
||||
typedef typename eastl::iterator_traits<RandomAccessIterator>::difference_type difference_type;
|
||||
typedef typename eastl::iterator_traits<RandomAccessIterator>::value_type value_type;
|
||||
|
||||
eastl::remove_heap<RandomAccessIterator, Distance, Compare>(first, heapSize, position, compare);
|
||||
|
||||
value_type tempBottom(*(first + heapSize - 1));
|
||||
|
||||
eastl::promote_heap<RandomAccessIterator, difference_type, value_type, Compare>
|
||||
(first, (difference_type)0, (difference_type)(heapSize - 1), tempBottom, compare);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// is_heap
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
|
||||
/// is_heap
|
||||
///
|
||||
/// This is a useful debugging algorithm for verifying that a random
|
||||
/// access container is in heap format.
|
||||
///
|
||||
template <typename RandomAccessIterator>
|
||||
inline bool is_heap(RandomAccessIterator first, RandomAccessIterator last)
|
||||
{
|
||||
int counter = 0;
|
||||
|
||||
for(RandomAccessIterator child = first + 1; child < last; ++child, counter ^= 1)
|
||||
{
|
||||
if(*first < *child)
|
||||
return false;
|
||||
first += counter; // counter switches between 0 and 1 every time through.
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/// is_heap
|
||||
///
|
||||
/// The Compare function must work equivalently to the compare function used
|
||||
/// to make and maintain the heap.
|
||||
///
|
||||
template <typename RandomAccessIterator, typename Compare>
|
||||
inline bool is_heap(RandomAccessIterator first, RandomAccessIterator last, Compare compare)
|
||||
{
|
||||
int counter = 0;
|
||||
|
||||
for(RandomAccessIterator child = first + 1; child < last; ++child, counter ^= 1)
|
||||
{
|
||||
if(compare(*first, *child))
|
||||
return false;
|
||||
first += counter; // counter switches between 0 and 1 every time through.
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Faster implementation for most cases:
|
||||
//
|
||||
// template <typename RandomAccessIterator>
|
||||
// inline bool is_heap(RandomAccessIterator first, RandomAccessIterator last)
|
||||
// {
|
||||
// if(((uintptr_t)(last - first) & 1) == 0)
|
||||
// --last;
|
||||
//
|
||||
// RandomAccessIterator parent = first, child = first + 1;
|
||||
//
|
||||
// for(; child < last; child += 2, ++parent)
|
||||
// {
|
||||
// if((*parent < *child) || (*parent < *(child + 1)))
|
||||
// return false;
|
||||
// }
|
||||
//
|
||||
// if((((uintptr_t)(last - first) & 1) == 0) && (*parent < *child))
|
||||
// return false;
|
||||
//
|
||||
// return true;
|
||||
// }
|
||||
|
||||
|
||||
} // namespace eastl
|
||||
|
||||
|
||||
#endif // Header include guard
|
||||
|
||||
|
||||
|
||||
|
1207
lib/eastl/include/EASTL/internal/config.h
Normal file
1207
lib/eastl/include/EASTL/internal/config.h
Normal file
File diff suppressed because it is too large
Load diff
47
lib/eastl/include/EASTL/internal/eastl_rw.h
Normal file
47
lib/eastl/include/EASTL/internal/eastl_rw.h
Normal file
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
Copyright (C) 2009-2010 Electronic Arts, Inc. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
3. Neither the name of Electronic Arts, Inc. ("EA") nor the names of
|
||||
its contributors may be used to endorse or promote products derived
|
||||
from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY ELECTRONIC ARTS AND ITS CONTRIBUTORS "AS IS" AND ANY
|
||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL ELECTRONIC ARTS OR ITS CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// To use this file, you can either copy and paste its contents right below
|
||||
// the EASTL_USER_CONFIG_HEADER section of EASTL's config.h or you can leave
|
||||
// config.h unmodified and instead #define EASTL_USER_CONFIG_HEADER be
|
||||
// config_rw.h and config.h will #include this file automatically.
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
#ifndef EASTL_RW_H
|
||||
#define EASTL_RW_H
|
||||
|
||||
// Unused
|
||||
|
||||
#endif // Header include guard
|
||||
|
||||
|
||||
|
||||
|
||||
|
1396
lib/eastl/include/EASTL/internal/fixed_pool.h
Normal file
1396
lib/eastl/include/EASTL/internal/fixed_pool.h
Normal file
File diff suppressed because it is too large
Load diff
242
lib/eastl/include/EASTL/internal/generic_iterator.h
Normal file
242
lib/eastl/include/EASTL/internal/generic_iterator.h
Normal file
|
@ -0,0 +1,242 @@
|
|||
/*
|
||||
Copyright (C) 2005,2009-2010 Electronic Arts, Inc. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
3. Neither the name of Electronic Arts, Inc. ("EA") nor the names of
|
||||
its contributors may be used to endorse or promote products derived
|
||||
from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY ELECTRONIC ARTS AND ITS CONTRIBUTORS "AS IS" AND ANY
|
||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL ELECTRONIC ARTS OR ITS CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// EASTL/internal/generic_iterator.h
|
||||
//
|
||||
// Written and maintained by Paul Pedriana - 2005.
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Implements a generic iterator from a given iteratable type, such as a pointer.
|
||||
// We cannot put this file into our own iterator.h file because we need to
|
||||
// still be able to use this file when we have our iterator.h disabled.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
#ifndef EASTL_INTERNAL_GENERIC_ITERATOR_H
|
||||
#define EASTL_INTERNAL_GENERIC_ITERATOR_H
|
||||
|
||||
|
||||
#include <EASTL/internal/config.h>
|
||||
#include <EASTL/iterator.h>
|
||||
#include <EASTL/type_traits.h>
|
||||
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(push) // VC++ generates a bogus warning that you cannot code away.
|
||||
#pragma warning(disable: 4619) // There is no warning number 'number'.
|
||||
#pragma warning(disable: 4217) // Member template functions cannot be used for copy-assignment or copy-construction.
|
||||
#endif
|
||||
|
||||
|
||||
namespace eastl
|
||||
{
|
||||
|
||||
/// generic_iterator
|
||||
///
|
||||
/// Converts something which can be iterated into a formal iterator.
|
||||
/// While this class' primary purpose is to allow the conversion of
|
||||
/// a pointer to an iterator, you can convert anything else to an
|
||||
/// iterator by defining an iterator_traits<> specialization for that
|
||||
/// object type. See EASTL iterator.h for this.
|
||||
///
|
||||
/// Example usage:
|
||||
/// typedef generic_iterator<int*> IntArrayIterator;
|
||||
/// typedef generic_iterator<int*, char> IntArrayIteratorOther;
|
||||
///
|
||||
template <typename Iterator, typename Container = void>
|
||||
class generic_iterator
|
||||
{
|
||||
protected:
|
||||
Iterator mIterator;
|
||||
|
||||
public:
|
||||
typedef typename eastl::iterator_traits<Iterator>::iterator_category iterator_category;
|
||||
typedef typename eastl::iterator_traits<Iterator>::value_type value_type;
|
||||
typedef typename eastl::iterator_traits<Iterator>::difference_type difference_type;
|
||||
typedef typename eastl::iterator_traits<Iterator>::reference reference;
|
||||
typedef typename eastl::iterator_traits<Iterator>::pointer pointer;
|
||||
typedef Iterator iterator_type;
|
||||
typedef Container container_type;
|
||||
typedef generic_iterator<Iterator, Container> this_type;
|
||||
|
||||
generic_iterator()
|
||||
: mIterator(iterator_type()) { }
|
||||
|
||||
explicit generic_iterator(const iterator_type& x)
|
||||
: mIterator(x) { }
|
||||
|
||||
this_type& operator=(const iterator_type& x)
|
||||
{ mIterator = x; return *this; }
|
||||
|
||||
template <typename Iterator2>
|
||||
generic_iterator(const generic_iterator<Iterator2, Container>& x)
|
||||
: mIterator(x.base()) { }
|
||||
|
||||
reference operator*() const
|
||||
{ return *mIterator; }
|
||||
|
||||
pointer operator->() const
|
||||
{ return mIterator; }
|
||||
|
||||
this_type& operator++()
|
||||
{ ++mIterator; return *this; }
|
||||
|
||||
this_type operator++(int)
|
||||
{ return this_type(mIterator++); }
|
||||
|
||||
this_type& operator--()
|
||||
{ --mIterator; return *this; }
|
||||
|
||||
this_type operator--(int)
|
||||
{ return this_type(mIterator--); }
|
||||
|
||||
reference operator[](const difference_type& n) const
|
||||
{ return mIterator[n]; }
|
||||
|
||||
this_type& operator+=(const difference_type& n)
|
||||
{ mIterator += n; return *this; }
|
||||
|
||||
this_type operator+(const difference_type& n) const
|
||||
{ return this_type(mIterator + n); }
|
||||
|
||||
this_type& operator-=(const difference_type& n)
|
||||
{ mIterator -= n; return *this; }
|
||||
|
||||
this_type operator-(const difference_type& n) const
|
||||
{ return this_type(mIterator - n); }
|
||||
|
||||
const iterator_type& base() const
|
||||
{ return mIterator; }
|
||||
|
||||
}; // class generic_iterator
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
template <typename IteratorL, typename IteratorR, typename Container>
|
||||
inline bool operator==(const generic_iterator<IteratorL, Container>& lhs, const generic_iterator<IteratorR, Container>& rhs)
|
||||
{ return lhs.base() == rhs.base(); }
|
||||
|
||||
template <typename Iterator, typename Container>
|
||||
inline bool operator==(const generic_iterator<Iterator, Container>& lhs, const generic_iterator<Iterator, Container>& rhs)
|
||||
{ return lhs.base() == rhs.base(); }
|
||||
|
||||
template <typename IteratorL, typename IteratorR, typename Container>
|
||||
inline bool operator!=(const generic_iterator<IteratorL, Container>& lhs, const generic_iterator<IteratorR, Container>& rhs)
|
||||
{ return lhs.base() != rhs.base(); }
|
||||
|
||||
template <typename Iterator, typename Container>
|
||||
inline bool operator!=(const generic_iterator<Iterator, Container>& lhs, const generic_iterator<Iterator, Container>& rhs)
|
||||
{ return lhs.base() != rhs.base(); }
|
||||
|
||||
template <typename IteratorL, typename IteratorR, typename Container>
|
||||
inline bool operator<(const generic_iterator<IteratorL, Container>& lhs, const generic_iterator<IteratorR, Container>& rhs)
|
||||
{ return lhs.base() < rhs.base(); }
|
||||
|
||||
template <typename Iterator, typename Container>
|
||||
inline bool operator<(const generic_iterator<Iterator, Container>& lhs, const generic_iterator<Iterator, Container>& rhs)
|
||||
{ return lhs.base() < rhs.base(); }
|
||||
|
||||
template <typename IteratorL, typename IteratorR, typename Container>
|
||||
inline bool operator>(const generic_iterator<IteratorL, Container>& lhs, const generic_iterator<IteratorR, Container>& rhs)
|
||||
{ return lhs.base() > rhs.base(); }
|
||||
|
||||
template <typename Iterator, typename Container>
|
||||
inline bool operator>(const generic_iterator<Iterator, Container>& lhs, const generic_iterator<Iterator, Container>& rhs)
|
||||
{ return lhs.base() > rhs.base(); }
|
||||
|
||||
template <typename IteratorL, typename IteratorR, typename Container>
|
||||
inline bool operator<=(const generic_iterator<IteratorL, Container>& lhs, const generic_iterator<IteratorR, Container>& rhs)
|
||||
{ return lhs.base() <= rhs.base(); }
|
||||
|
||||
template <typename Iterator, typename Container>
|
||||
inline bool operator<=(const generic_iterator<Iterator, Container>& lhs, const generic_iterator<Iterator, Container>& rhs)
|
||||
{ return lhs.base() <= rhs.base(); }
|
||||
|
||||
template <typename IteratorL, typename IteratorR, typename Container>
|
||||
inline bool operator>=(const generic_iterator<IteratorL, Container>& lhs, const generic_iterator<IteratorR, Container>& rhs)
|
||||
{ return lhs.base() >= rhs.base(); }
|
||||
|
||||
template <typename Iterator, typename Container>
|
||||
inline bool operator>=(const generic_iterator<Iterator, Container>& lhs, const generic_iterator<Iterator, Container>& rhs)
|
||||
{ return lhs.base() >= rhs.base(); }
|
||||
|
||||
template <typename IteratorL, typename IteratorR, typename Container>
|
||||
inline typename generic_iterator<IteratorL, Container>::difference_type
|
||||
operator-(const generic_iterator<IteratorL, Container>& lhs, const generic_iterator<IteratorR, Container>& rhs)
|
||||
{ return lhs.base() - rhs.base(); }
|
||||
|
||||
template <typename Iterator, typename Container>
|
||||
inline generic_iterator<Iterator, Container>
|
||||
operator+(typename generic_iterator<Iterator, Container>::difference_type n, const generic_iterator<Iterator, Container>& x)
|
||||
{ return generic_iterator<Iterator, Container>(x.base() + n); }
|
||||
|
||||
|
||||
|
||||
/// is_generic_iterator
|
||||
///
|
||||
/// Tells if an iterator is one of these generic_iterators. This is useful if you want to
|
||||
/// write code that uses miscellaneous iterators but wants to tell if they are generic_iterators.
|
||||
/// A primary reason to do so is that you can get at the pointer within the generic_iterator.
|
||||
///
|
||||
template <typename Iterator>
|
||||
struct is_generic_iterator : public false_type { };
|
||||
|
||||
template <typename Iterator, typename Container>
|
||||
struct is_generic_iterator<generic_iterator<Iterator, Container> > : public true_type { };
|
||||
|
||||
|
||||
} // namespace eastl
|
||||
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
|
||||
#endif // Header include guard
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
2261
lib/eastl/include/EASTL/internal/hashtable.h
Normal file
2261
lib/eastl/include/EASTL/internal/hashtable.h
Normal file
File diff suppressed because it is too large
Load diff
1917
lib/eastl/include/EASTL/internal/red_black_tree.h
Normal file
1917
lib/eastl/include/EASTL/internal/red_black_tree.h
Normal file
File diff suppressed because it is too large
Load diff
485
lib/eastl/include/EASTL/internal/type_compound.h
Normal file
485
lib/eastl/include/EASTL/internal/type_compound.h
Normal file
|
@ -0,0 +1,485 @@
|
|||
/*
|
||||
Copyright (C) 2005,2009-2010 Electronic Arts, Inc. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
3. Neither the name of Electronic Arts, Inc. ("EA") nor the names of
|
||||
its contributors may be used to endorse or promote products derived
|
||||
from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY ELECTRONIC ARTS AND ITS CONTRIBUTORS "AS IS" AND ANY
|
||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL ELECTRONIC ARTS OR ITS CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// EASTL/internal/type_compound.h
|
||||
// Written and maintained by Paul Pedriana - 2005.
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
#ifndef EASTL_INTERNAL_TYPE_COMPOUND_H
|
||||
#define EASTL_INTERNAL_TYPE_COMPOUND_H
|
||||
|
||||
|
||||
namespace eastl
|
||||
{
|
||||
|
||||
// The following properties or relations are defined here. If the given
|
||||
// item is missing then it simply hasn't been implemented, at least not yet.
|
||||
// is_array
|
||||
// is_pointer
|
||||
// is_reference
|
||||
// is_member_object_pointer
|
||||
// is_member_function_pointer
|
||||
// is_member_pointer
|
||||
// is_enum
|
||||
// is_union
|
||||
// is_class
|
||||
// is_polymorphic
|
||||
// is_function
|
||||
// is_object
|
||||
// is_scalar
|
||||
// is_compound
|
||||
// is_same
|
||||
// is_convertible
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// is_array
|
||||
//
|
||||
// is_array<T>::value == true if and only if T is an array type.
|
||||
// As of this writing, the SNC compiler (EDG-based) doesn't compile
|
||||
// the code below and says that returning an array is illegal.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
template <typename T>
|
||||
T (*is_array_tester1(empty<T>))(empty<T>);
|
||||
char is_array_tester1(...); // May need to use __cdecl under VC++.
|
||||
|
||||
template <typename T>
|
||||
no_type is_array_tester2(T(*)(empty<T>));
|
||||
yes_type is_array_tester2(...); // May need to use __cdecl under VC++.
|
||||
|
||||
template <typename T>
|
||||
struct is_array_helper {
|
||||
static empty<T> emptyInstance;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct is_array : public integral_constant<bool,
|
||||
sizeof(is_array_tester2(is_array_tester1(is_array_helper<T>::emptyInstance))) == 1
|
||||
>{};
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// is_reference
|
||||
//
|
||||
// is_reference<T>::value == true if and only if T is a reference type.
|
||||
// This category includes reference to function types.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
template <typename T> struct is_reference : public false_type{};
|
||||
template <typename T> struct is_reference<T&> : public true_type{};
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// is_member_function_pointer
|
||||
//
|
||||
// is_member_function_pointer<T>::value == true if and only if T is a
|
||||
// pointer to member function type.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// We detect member functions with 0 to N arguments. We can extend this
|
||||
// for additional arguments if necessary.
|
||||
// To do: Make volatile and const volatile versions of these in addition to non-const and const.
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
template <typename T> struct is_mem_fun_pointer_value : public false_type{};
|
||||
template <typename R, typename T> struct is_mem_fun_pointer_value<R (T::*)()> : public true_type{};
|
||||
template <typename R, typename T> struct is_mem_fun_pointer_value<R (T::*)() const> : public true_type{};
|
||||
template <typename R, typename T, typename Arg0> struct is_mem_fun_pointer_value<R (T::*)(Arg0)> : public true_type{};
|
||||
template <typename R, typename T, typename Arg0> struct is_mem_fun_pointer_value<R (T::*)(Arg0) const> : public true_type{};
|
||||
template <typename R, typename T, typename Arg0, typename Arg1> struct is_mem_fun_pointer_value<R (T::*)(Arg0, Arg1)> : public true_type{};
|
||||
template <typename R, typename T, typename Arg0, typename Arg1> struct is_mem_fun_pointer_value<R (T::*)(Arg0, Arg1) const> : public true_type{};
|
||||
template <typename R, typename T, typename Arg0, typename Arg1, typename Arg2> struct is_mem_fun_pointer_value<R (T::*)(Arg0, Arg1, Arg2)> : public true_type{};
|
||||
template <typename R, typename T, typename Arg0, typename Arg1, typename Arg2> struct is_mem_fun_pointer_value<R (T::*)(Arg0, Arg1, Arg2) const> : public true_type{};
|
||||
template <typename R, typename T, typename Arg0, typename Arg1, typename Arg2, typename Arg3> struct is_mem_fun_pointer_value<R (T::*)(Arg0, Arg1, Arg2, Arg3)> : public true_type{};
|
||||
template <typename R, typename T, typename Arg0, typename Arg1, typename Arg2, typename Arg3> struct is_mem_fun_pointer_value<R (T::*)(Arg0, Arg1, Arg2, Arg3) const> : public true_type{};
|
||||
template <typename R, typename T, typename Arg0, typename Arg1, typename Arg2, typename Arg3, typename Arg4> struct is_mem_fun_pointer_value<R (T::*)(Arg0, Arg1, Arg2, Arg3, Arg4)> : public true_type{};
|
||||
template <typename R, typename T, typename Arg0, typename Arg1, typename Arg2, typename Arg3, typename Arg4> struct is_mem_fun_pointer_value<R (T::*)(Arg0, Arg1, Arg2, Arg3, Arg4) const> : public true_type{};
|
||||
template <typename R, typename T, typename Arg0, typename Arg1, typename Arg2, typename Arg3, typename Arg4, typename Arg5> struct is_mem_fun_pointer_value<R (T::*)(Arg0, Arg1, Arg2, Arg3, Arg4, Arg5)> : public true_type{};
|
||||
template <typename R, typename T, typename Arg0, typename Arg1, typename Arg2, typename Arg3, typename Arg4, typename Arg5> struct is_mem_fun_pointer_value<R (T::*)(Arg0, Arg1, Arg2, Arg3, Arg4, Arg5) const> : public true_type{};
|
||||
template <typename R, typename T, typename Arg0, typename Arg1, typename Arg2, typename Arg3, typename Arg4, typename Arg5, typename Arg6> struct is_mem_fun_pointer_value<R (T::*)(Arg0, Arg1, Arg2, Arg3, Arg4, Arg5, Arg6)> : public true_type{};
|
||||
template <typename R, typename T, typename Arg0, typename Arg1, typename Arg2, typename Arg3, typename Arg4, typename Arg5, typename Arg6> struct is_mem_fun_pointer_value<R (T::*)(Arg0, Arg1, Arg2, Arg3, Arg4, Arg5, Arg6) const> : public true_type{};
|
||||
template <typename R, typename T, typename Arg0, typename Arg1, typename Arg2, typename Arg3, typename Arg4, typename Arg5, typename Arg6, typename Arg7> struct is_mem_fun_pointer_value<R (T::*)(Arg0, Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7)> : public true_type{};
|
||||
template <typename R, typename T, typename Arg0, typename Arg1, typename Arg2, typename Arg3, typename Arg4, typename Arg5, typename Arg6, typename Arg7> struct is_mem_fun_pointer_value<R (T::*)(Arg0, Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7) const> : public true_type{};
|
||||
|
||||
template <typename T>
|
||||
struct is_member_function_pointer : public integral_constant<bool, is_mem_fun_pointer_value<T>::value>{};
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// is_member_pointer
|
||||
//
|
||||
// is_member_pointer<T>::value == true if and only if:
|
||||
// is_member_object_pointer<T>::value == true, or
|
||||
// is_member_function_pointer<T>::value == true
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
template <typename T>
|
||||
struct is_member_pointer : public integral_constant<bool, is_member_function_pointer<T>::value>{};
|
||||
|
||||
template <typename T, typename U> struct is_member_pointer<U T::*> : public true_type{};
|
||||
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// is_pointer
|
||||
//
|
||||
// is_pointer<T>::value == true if and only if T is a pointer type.
|
||||
// This category includes function pointer types, but not pointer to
|
||||
// member types.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
template <typename T> struct is_pointer_helper : public false_type{};
|
||||
|
||||
template <typename T> struct is_pointer_helper<T*> : public true_type{};
|
||||
template <typename T> struct is_pointer_helper<T* const> : public true_type{};
|
||||
template <typename T> struct is_pointer_helper<T* volatile> : public true_type{};
|
||||
template <typename T> struct is_pointer_helper<T* const volatile> : public true_type{};
|
||||
|
||||
template <typename T>
|
||||
struct is_pointer_value : public type_and<is_pointer_helper<T>::value, type_not<is_member_pointer<T>::value>::value> {};
|
||||
|
||||
template <typename T>
|
||||
struct is_pointer : public integral_constant<bool, is_pointer_value<T>::value>{};
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// is_same
|
||||
//
|
||||
// Given two (possibly identical) types T and U, is_same<T, U>::value == true
|
||||
// if and only if T and U are the same type.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
template<typename T, typename U>
|
||||
struct is_same : public false_type { };
|
||||
|
||||
template<typename T>
|
||||
struct is_same<T, T> : public true_type { };
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// is_convertible
|
||||
//
|
||||
// Given two (possible identical) types From and To, is_convertible<From, To>::value == true
|
||||
// if and only if an lvalue of type From can be implicitly converted to type To,
|
||||
// or is_void<To>::value == true
|
||||
//
|
||||
// is_convertible may only be applied to complete types.
|
||||
// Type To may not be an abstract type.
|
||||
// If the conversion is ambiguous, the program is ill-formed.
|
||||
// If either or both of From and To are class types, and the conversion would invoke
|
||||
// non-public member functions of either From or To (such as a private constructor of To,
|
||||
// or a private conversion operator of From), the program is ill-formed.
|
||||
//
|
||||
// Note that without compiler help, both is_convertible and is_base
|
||||
// can produce compiler errors if the conversion is ambiguous.
|
||||
// Example:
|
||||
// struct A {};
|
||||
// struct B : A {};
|
||||
// struct C : A {};
|
||||
// struct D : B, C {};
|
||||
// is_convertible<D*, A*>::value; // Generates compiler error.
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
#if !defined(__GNUC__) || (__GNUC__ >= 3) // GCC 2.x doesn't like the code below.
|
||||
template <typename From, typename To, bool is_from_void = false, bool is_to_void = false>
|
||||
struct is_convertible_helper {
|
||||
static yes_type Test(To); // May need to use __cdecl under VC++.
|
||||
static no_type Test(...); // May need to use __cdecl under VC++.
|
||||
static From from;
|
||||
typedef integral_constant<bool, sizeof(Test(from)) == sizeof(yes_type)> result;
|
||||
};
|
||||
|
||||
// void is not convertible to non-void
|
||||
template <typename From, typename To>
|
||||
struct is_convertible_helper<From, To, true, false> { typedef false_type result; };
|
||||
|
||||
// Anything is convertible to void
|
||||
template <typename From, typename To, bool is_from_void>
|
||||
struct is_convertible_helper<From, To, is_from_void, true> { typedef true_type result; };
|
||||
|
||||
template <typename From, typename To>
|
||||
struct is_convertible : public is_convertible_helper<From, To, is_void<From>::value, is_void<To>::value>::result {};
|
||||
|
||||
#else
|
||||
template <typename From, typename To>
|
||||
struct is_convertible : public false_type{};
|
||||
#endif
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// is_union
|
||||
//
|
||||
// is_union<T>::value == true if and only if T is a union type.
|
||||
//
|
||||
// There is no way to tell if a type is a union without compiler help.
|
||||
// As of this writing, only Metrowerks v8+ supports such functionality
|
||||
// via 'msl::is_union<T>::value'. The user can force something to be
|
||||
// evaluated as a union via EASTL_DECLARE_UNION.
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
template <typename T> struct is_union : public false_type{};
|
||||
|
||||
#define EASTL_DECLARE_UNION(T) namespace eastl{ template <> struct is_union<T> : public true_type{}; template <> struct is_union<const T> : public true_type{}; }
|
||||
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// is_class
|
||||
//
|
||||
// is_class<T>::value == true if and only if T is a class or struct
|
||||
// type (and not a union type).
|
||||
//
|
||||
// Without specific compiler help, it is not possible to
|
||||
// distinguish between unions and classes. As a result, is_class
|
||||
// will erroneously evaluate to true for union types.
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
#if defined(__MWERKS__)
|
||||
// To do: Switch this to use msl_utility type traits.
|
||||
template <typename T>
|
||||
struct is_class : public false_type{};
|
||||
#elif !defined(__GNUC__) || (((__GNUC__ * 100) + __GNUC_MINOR__) >= 304) // Not GCC or GCC 3.4+
|
||||
template <typename U> static yes_type is_class_helper(void (U::*)());
|
||||
template <typename U> static no_type is_class_helper(...);
|
||||
|
||||
template <typename T>
|
||||
struct is_class : public integral_constant<bool,
|
||||
sizeof(is_class_helper<T>(0)) == sizeof(yes_type) && !is_union<T>::value
|
||||
>{};
|
||||
#else
|
||||
// GCC 2.x version, due to GCC being broken.
|
||||
template <typename T>
|
||||
struct is_class : public false_type{};
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// is_enum
|
||||
//
|
||||
// is_enum<T>::value == true if and only if T is an enumeration type.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
struct int_convertible{ int_convertible(int); };
|
||||
|
||||
template <bool is_arithmetic_or_reference>
|
||||
struct is_enum_helper { template <typename T> struct nest : public is_convertible<T, int_convertible>{}; };
|
||||
|
||||
template <>
|
||||
struct is_enum_helper<true> { template <typename T> struct nest : public false_type {}; };
|
||||
|
||||
template <typename T>
|
||||
struct is_enum_helper2
|
||||
{
|
||||
typedef type_or<is_arithmetic<T>::value, is_reference<T>::value, is_class<T>::value> selector;
|
||||
typedef is_enum_helper<selector::value> helper_t;
|
||||
typedef typename add_reference<T>::type ref_t;
|
||||
typedef typename helper_t::template nest<ref_t> result;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct is_enum : public integral_constant<bool, is_enum_helper2<T>::result::value>{};
|
||||
|
||||
template <> struct is_enum<void> : public false_type {};
|
||||
template <> struct is_enum<void const> : public false_type {};
|
||||
template <> struct is_enum<void volatile> : public false_type {};
|
||||
template <> struct is_enum<void const volatile> : public false_type {};
|
||||
|
||||
#define EASTL_DECLARE_ENUM(T) namespace eastl{ template <> struct is_enum<T> : public true_type{}; template <> struct is_enum<const T> : public true_type{}; }
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// is_polymorphic
|
||||
//
|
||||
// is_polymorphic<T>::value == true if and only if T is a class or struct
|
||||
// that declares or inherits a virtual function. is_polymorphic may only
|
||||
// be applied to complete types.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
template <typename T>
|
||||
struct is_polymorphic_imp1
|
||||
{
|
||||
typedef typename remove_cv<T>::type t;
|
||||
|
||||
struct helper_1 : public t
|
||||
{
|
||||
helper_1();
|
||||
~helper_1() throw();
|
||||
char pad[64];
|
||||
};
|
||||
|
||||
struct helper_2 : public t
|
||||
{
|
||||
helper_2();
|
||||
virtual ~helper_2() throw();
|
||||
#ifndef _MSC_VER
|
||||
virtual void foo();
|
||||
#endif
|
||||
char pad[64];
|
||||
};
|
||||
|
||||
static const bool value = (sizeof(helper_1) == sizeof(helper_2));
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct is_polymorphic_imp2{ static const bool value = false; };
|
||||
|
||||
template <bool is_class>
|
||||
struct is_polymorphic_selector{ template <typename T> struct rebind{ typedef is_polymorphic_imp2<T> type; }; };
|
||||
|
||||
template <>
|
||||
struct is_polymorphic_selector<true>{ template <typename T> struct rebind{ typedef is_polymorphic_imp1<T> type; }; };
|
||||
|
||||
template <typename T>
|
||||
struct is_polymorphic_value{
|
||||
typedef is_polymorphic_selector<is_class<T>::value> selector;
|
||||
typedef typename selector::template rebind<T> binder;
|
||||
typedef typename binder::type imp_type;
|
||||
static const bool value = imp_type::value;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct is_polymorphic : public integral_constant<bool, is_polymorphic_value<T>::value>{};
|
||||
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// is_function
|
||||
//
|
||||
// is_function<T>::value == true if and only if T is a function type.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
template <typename R> struct is_function_ptr_helper : public false_type{};
|
||||
template <typename R> struct is_function_ptr_helper<R (*)()> : public true_type{};
|
||||
template <typename R, typename Arg0> struct is_function_ptr_helper<R (*)(Arg0)> : public true_type{};
|
||||
template <typename R, typename Arg0, typename Arg1> struct is_function_ptr_helper<R (*)(Arg0, Arg1)> : public true_type{};
|
||||
template <typename R, typename Arg0, typename Arg1, typename Arg2> struct is_function_ptr_helper<R (*)(Arg0, Arg1, Arg2)> : public true_type{};
|
||||
template <typename R, typename Arg0, typename Arg1, typename Arg2, typename Arg3> struct is_function_ptr_helper<R (*)(Arg0, Arg1, Arg2, Arg3)> : public true_type{};
|
||||
template <typename R, typename Arg0, typename Arg1, typename Arg2, typename Arg3, typename Arg4> struct is_function_ptr_helper<R (*)(Arg0, Arg1, Arg2, Arg3, Arg4)> : public true_type{};
|
||||
template <typename R, typename Arg0, typename Arg1, typename Arg2, typename Arg3, typename Arg4, typename Arg5> struct is_function_ptr_helper<R (*)(Arg0, Arg1, Arg2, Arg3, Arg4, Arg5)> : public true_type{};
|
||||
template <typename R, typename Arg0, typename Arg1, typename Arg2, typename Arg3, typename Arg4, typename Arg5, typename Arg6> struct is_function_ptr_helper<R (*)(Arg0, Arg1, Arg2, Arg3, Arg4, Arg5, Arg6)> : public true_type{};
|
||||
template <typename R, typename Arg0, typename Arg1, typename Arg2, typename Arg3, typename Arg4, typename Arg5, typename Arg6, typename Arg7> struct is_function_ptr_helper<R (*)(Arg0, Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7)> : public true_type{};
|
||||
|
||||
template <bool is_ref = true>
|
||||
struct is_function_chooser{ template <typename T> struct result_ : public false_type{}; };
|
||||
|
||||
template <>
|
||||
struct is_function_chooser<false>{ template <typename T> struct result_ : public is_function_ptr_helper<T*>{}; };
|
||||
|
||||
template <typename T>
|
||||
struct is_function_value : public is_function_chooser<is_reference<T>::value>::template result_<T>{};
|
||||
|
||||
template <typename T>
|
||||
struct is_function : public integral_constant<bool, is_function_value<T>::value>{};
|
||||
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// is_object
|
||||
//
|
||||
// is_object<T>::value == true if and only if:
|
||||
// is_reference<T>::value == false, and
|
||||
// is_function<T>::value == false, and
|
||||
// is_void<T>::value == false
|
||||
//
|
||||
// The C++ standard, section 3.9p9, states: "An object type is a
|
||||
// (possibly cv-qualified) type that is not a function type, not a
|
||||
// reference type, and not incomplete (except for an incompletely
|
||||
// defined object type).
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <typename T>
|
||||
struct is_object : public integral_constant<bool,
|
||||
!is_reference<T>::value && !is_void<T>::value && !is_function<T>::value
|
||||
>{};
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// is_scalar
|
||||
//
|
||||
// is_scalar<T>::value == true if and only if:
|
||||
// is_arithmetic<T>::value == true, or
|
||||
// is_enum<T>::value == true, or
|
||||
// is_pointer<T>::value == true, or
|
||||
// is_member_pointer<T>::value
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
template <typename T>
|
||||
struct is_scalar : public integral_constant<bool, is_arithmetic<T>::value || is_enum<T>::value>{};
|
||||
|
||||
template <typename T> struct is_scalar<T*> : public true_type {};
|
||||
template <typename T> struct is_scalar<T* const> : public true_type {};
|
||||
template <typename T> struct is_scalar<T* volatile> : public true_type {};
|
||||
template <typename T> struct is_scalar<T* const volatile> : public true_type {};
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// is_compound
|
||||
//
|
||||
// Compound means anything but fundamental. See C++ standard, section 3.9.2.
|
||||
//
|
||||
// is_compound<T>::value == true if and only if:
|
||||
// is_fundamental<T>::value == false
|
||||
//
|
||||
// Thus, is_compound<T>::value == true if and only if:
|
||||
// is_floating_point<T>::value == false, and
|
||||
// is_integral<T>::value == false, and
|
||||
// is_void<T>::value == false
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
template <typename T>
|
||||
struct is_compound : public integral_constant<bool, !is_fundamental<T>::value>{};
|
||||
|
||||
|
||||
} // namespace eastl
|
||||
|
||||
|
||||
#endif // Header include guard
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
187
lib/eastl/include/EASTL/internal/type_fundamental.h
Normal file
187
lib/eastl/include/EASTL/internal/type_fundamental.h
Normal file
|
@ -0,0 +1,187 @@
|
|||
/*
|
||||
Copyright (C) 2005,2009-2010 Electronic Arts, Inc. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
3. Neither the name of Electronic Arts, Inc. ("EA") nor the names of
|
||||
its contributors may be used to endorse or promote products derived
|
||||
from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY ELECTRONIC ARTS AND ITS CONTRIBUTORS "AS IS" AND ANY
|
||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL ELECTRONIC ARTS OR ITS CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// EASTL/internal/type_fundamental.h
|
||||
//
|
||||
// Written and maintained by Paul Pedriana - 2005.
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
#ifndef EASTL_INTERNAL_TYPE_FUNDAMENTAL_H
|
||||
#define EASTL_INTERNAL_TYPE_FUNDAMENTAL_H
|
||||
|
||||
|
||||
namespace eastl
|
||||
{
|
||||
|
||||
// The following properties or relations are defined here. If the given
|
||||
// item is missing then it simply hasn't been implemented, at least not yet.
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// is_void
|
||||
//
|
||||
// is_void<T>::value == true if and only if T is one of the following types:
|
||||
// [const][volatile] void
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
template <typename T> struct is_void : public false_type{};
|
||||
|
||||
template <> struct is_void<void> : public true_type{};
|
||||
template <> struct is_void<void const> : public true_type{};
|
||||
template <> struct is_void<void volatile> : public true_type{};
|
||||
template <> struct is_void<void const volatile> : public true_type{};
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// is_integral
|
||||
//
|
||||
// is_integral<T>::value == true if and only if T is one of the following types:
|
||||
// [const] [volatile] bool
|
||||
// [const] [volatile] char
|
||||
// [const] [volatile] signed char
|
||||
// [const] [volatile] unsigned char
|
||||
// [const] [volatile] wchar_t
|
||||
// [const] [volatile] short
|
||||
// [const] [volatile] int
|
||||
// [const] [volatile] long
|
||||
// [const] [volatile] long long
|
||||
// [const] [volatile] unsigned short
|
||||
// [const] [volatile] unsigned int
|
||||
// [const] [volatile] unsigned long
|
||||
// [const] [volatile] unsigned long long
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
template <typename T> struct is_integral : public false_type{};
|
||||
|
||||
// To do: Need to define volatile and const volatile versions of these.
|
||||
template <> struct is_integral<unsigned char> : public true_type{};
|
||||
template <> struct is_integral<const unsigned char> : public true_type{};
|
||||
template <> struct is_integral<unsigned short> : public true_type{};
|
||||
template <> struct is_integral<const unsigned short> : public true_type{};
|
||||
template <> struct is_integral<unsigned int> : public true_type{};
|
||||
template <> struct is_integral<const unsigned int> : public true_type{};
|
||||
template <> struct is_integral<unsigned long> : public true_type{};
|
||||
template <> struct is_integral<const unsigned long> : public true_type{};
|
||||
template <> struct is_integral<unsigned long long> : public true_type{};
|
||||
template <> struct is_integral<const unsigned long long> : public true_type{};
|
||||
|
||||
template <> struct is_integral<signed char> : public true_type{};
|
||||
template <> struct is_integral<const signed char> : public true_type{};
|
||||
template <> struct is_integral<signed short> : public true_type{};
|
||||
template <> struct is_integral<const signed short> : public true_type{};
|
||||
template <> struct is_integral<signed int> : public true_type{};
|
||||
template <> struct is_integral<const signed int> : public true_type{};
|
||||
template <> struct is_integral<signed long> : public true_type{};
|
||||
template <> struct is_integral<const signed long> : public true_type{};
|
||||
template <> struct is_integral<signed long long> : public true_type{};
|
||||
template <> struct is_integral<const signed long long> : public true_type{};
|
||||
|
||||
template <> struct is_integral<bool> : public true_type{};
|
||||
template <> struct is_integral<const bool> : public true_type{};
|
||||
template <> struct is_integral<char> : public true_type{};
|
||||
template <> struct is_integral<const char> : public true_type{};
|
||||
#ifndef EA_WCHAR_T_NON_NATIVE // If wchar_t is a native type instead of simply a define to an existing type...
|
||||
template <> struct is_integral<wchar_t> : public true_type{};
|
||||
template <> struct is_integral<const wchar_t> : public true_type{};
|
||||
#endif
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// is_floating_point
|
||||
//
|
||||
// is_floating_point<T>::value == true if and only if T is one of the following types:
|
||||
// [const] [volatile] float
|
||||
// [const] [volatile] double
|
||||
// [const] [volatile] long double
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
template <typename T> struct is_floating_point : public false_type{};
|
||||
|
||||
// To do: Need to define volatile and const volatile versions of these.
|
||||
template <> struct is_floating_point<float> : public true_type{};
|
||||
template <> struct is_floating_point<const float> : public true_type{};
|
||||
template <> struct is_floating_point<double> : public true_type{};
|
||||
template <> struct is_floating_point<const double> : public true_type{};
|
||||
template <> struct is_floating_point<long double> : public true_type{};
|
||||
template <> struct is_floating_point<const long double> : public true_type{};
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// is_arithmetic
|
||||
//
|
||||
// is_arithmetic<T>::value == true if and only if:
|
||||
// is_floating_point<T>::value == true, or
|
||||
// is_integral<T>::value == true
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
template <typename T>
|
||||
struct is_arithmetic : public integral_constant<bool,
|
||||
is_integral<T>::value || is_floating_point<T>::value
|
||||
>{};
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// is_fundamental
|
||||
//
|
||||
// is_fundamental<T>::value == true if and only if:
|
||||
// is_floating_point<T>::value == true, or
|
||||
// is_integral<T>::value == true, or
|
||||
// is_void<T>::value == true
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
template <typename T>
|
||||
struct is_fundamental : public integral_constant<bool,
|
||||
is_void<T>::value || is_integral<T>::value || is_floating_point<T>::value
|
||||
>{};
|
||||
|
||||
} // namespace eastl
|
||||
|
||||
|
||||
#endif // Header include guard
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
306
lib/eastl/include/EASTL/internal/type_pod.h
Normal file
306
lib/eastl/include/EASTL/internal/type_pod.h
Normal file
|
@ -0,0 +1,306 @@
|
|||
/*
|
||||
Copyright (C) 2005,2009-2010 Electronic Arts, Inc. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
3. Neither the name of Electronic Arts, Inc. ("EA") nor the names of
|
||||
its contributors may be used to endorse or promote products derived
|
||||
from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY ELECTRONIC ARTS AND ITS CONTRIBUTORS "AS IS" AND ANY
|
||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL ELECTRONIC ARTS OR ITS CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// EASTL/internal/type_pod.h
|
||||
// Written and maintained by Paul Pedriana - 2005.
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
#ifndef EASTL_INTERNAL_TYPE_POD_H
|
||||
#define EASTL_INTERNAL_TYPE_POD_H
|
||||
|
||||
|
||||
#include <limits.h>
|
||||
|
||||
|
||||
namespace eastl
|
||||
{
|
||||
|
||||
|
||||
// The following properties or relations are defined here. If the given
|
||||
// item is missing then it simply hasn't been implemented, at least not yet.
|
||||
// is_empty
|
||||
// is_pod
|
||||
// has_trivial_constructor
|
||||
// has_trivial_copy
|
||||
// has_trivial_assign
|
||||
// has_trivial_destructor
|
||||
// has_trivial_relocate -- EA extension to the C++ standard proposal.
|
||||
// has_nothrow_constructor
|
||||
// has_nothrow_copy
|
||||
// has_nothrow_assign
|
||||
// has_virtual_destructor
|
||||
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// is_empty
|
||||
//
|
||||
// is_empty<T>::value == true if and only if T is an empty class or struct.
|
||||
// is_empty may only be applied to complete types.
|
||||
//
|
||||
// is_empty cannot be used with union types until is_union can be made to work.
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
template <typename T>
|
||||
struct is_empty_helper_t1 : public T { char m[64]; };
|
||||
struct is_empty_helper_t2 { char m[64]; };
|
||||
|
||||
// The inheritance in empty_helper_t1 will not work with non-class types
|
||||
template <typename T, bool is_a_class = false>
|
||||
struct is_empty_helper : public false_type{};
|
||||
|
||||
template <typename T>
|
||||
struct is_empty_helper<T, true> : public integral_constant<bool,
|
||||
sizeof(is_empty_helper_t1<T>) == sizeof(is_empty_helper_t2)
|
||||
>{};
|
||||
|
||||
template <typename T>
|
||||
struct is_empty_helper2
|
||||
{
|
||||
typedef typename remove_cv<T>::type _T;
|
||||
typedef is_empty_helper<_T, is_class<_T>::value> type;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct is_empty : public is_empty_helper2<T>::type {};
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// is_pod
|
||||
//
|
||||
// is_pod<T>::value == true if and only if, for a given type T:
|
||||
// - is_scalar<T>::value == true, or
|
||||
// - T is a class or struct that has no user-defined copy
|
||||
// assignment operator or destructor, and T has no non-static
|
||||
// data members M for which is_pod<M>::value == false, and no
|
||||
// members of reference type, or
|
||||
// - T is a class or struct that has no user-defined copy assignment
|
||||
// operator or destructor, and T has no non-static data members M for
|
||||
// which is_pod<M>::value == false, and no members of reference type, or
|
||||
// - T is the type of an array of objects E for which is_pod<E>::value == true
|
||||
//
|
||||
// is_pod may only be applied to complete types.
|
||||
//
|
||||
// Without some help from the compiler or user, is_pod will not report
|
||||
// that a struct or class is a POD, but will correctly report that
|
||||
// built-in types such as int are PODs. The user can help the compiler
|
||||
// by using the EASTL_DECLARE_POD macro on a class.
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
template <typename T> // There's not much we can do here without some compiler extension.
|
||||
struct is_pod : public integral_constant<bool, is_void<T>::value || is_scalar<T>::value>{};
|
||||
|
||||
template <typename T, size_t N>
|
||||
struct is_pod<T[N]> : public is_pod<T>{};
|
||||
|
||||
template <typename T>
|
||||
struct is_POD : public is_pod<T>{};
|
||||
|
||||
#define EASTL_DECLARE_POD(T) namespace eastl{ template <> struct is_pod<T> : public true_type{}; template <> struct is_pod<const T> : public true_type{}; }
|
||||
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// has_trivial_constructor
|
||||
//
|
||||
// has_trivial_constructor<T>::value == true if and only if T is a class
|
||||
// or struct that has a trivial constructor. A constructor is trivial if
|
||||
// - it is implicitly defined by the compiler, and
|
||||
// - is_polymorphic<T>::value == false, and
|
||||
// - T has no virtual base classes, and
|
||||
// - for every direct base class of T, has_trivial_constructor<B>::value == true,
|
||||
// where B is the type of the base class, and
|
||||
// - for every nonstatic data member of T that has class type or array
|
||||
// of class type, has_trivial_constructor<M>::value == true,
|
||||
// where M is the type of the data member
|
||||
//
|
||||
// has_trivial_constructor may only be applied to complete types.
|
||||
//
|
||||
// Without from the compiler or user, has_trivial_constructor will not
|
||||
// report that a class or struct has a trivial constructor.
|
||||
// The user can use EASTL_DECLARE_TRIVIAL_CONSTRUCTOR to help the compiler.
|
||||
//
|
||||
// A default constructor for a class X is a constructor of class X that
|
||||
// can be called without an argument.
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
|
||||
// With current compilers, this is all we can do.
|
||||
template <typename T>
|
||||
struct has_trivial_constructor : public is_pod<T> {};
|
||||
|
||||
#define EASTL_DECLARE_TRIVIAL_CONSTRUCTOR(T) namespace eastl{ template <> struct has_trivial_constructor<T> : public true_type{}; template <> struct has_trivial_constructor<const T> : public true_type{}; }
|
||||
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// has_trivial_copy
|
||||
//
|
||||
// has_trivial_copy<T>::value == true if and only if T is a class or
|
||||
// struct that has a trivial copy constructor. A copy constructor is
|
||||
// trivial if
|
||||
// - it is implicitly defined by the compiler, and
|
||||
// - is_polymorphic<T>::value == false, and
|
||||
// - T has no virtual base classes, and
|
||||
// - for every direct base class of T, has_trivial_copy<B>::value == true,
|
||||
// where B is the type of the base class, and
|
||||
// - for every nonstatic data member of T that has class type or array
|
||||
// of class type, has_trivial_copy<M>::value == true, where M is the
|
||||
// type of the data member
|
||||
//
|
||||
// has_trivial_copy may only be applied to complete types.
|
||||
//
|
||||
// Another way of looking at this is:
|
||||
// A copy constructor for class X is trivial if it is implicitly
|
||||
// declared and if all the following are true:
|
||||
// - Class X has no virtual functions (10.3) and no virtual base classes (10.1).
|
||||
// - Each direct base class of X has a trivial copy constructor.
|
||||
// - For all the nonstatic data members of X that are of class type
|
||||
// (or array thereof), each such class type has a trivial copy constructor;
|
||||
// otherwise the copy constructor is nontrivial.
|
||||
//
|
||||
// Without from the compiler or user, has_trivial_copy will not report
|
||||
// that a class or struct has a trivial copy constructor. The user can
|
||||
// use EASTL_DECLARE_TRIVIAL_COPY to help the compiler.
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <typename T>
|
||||
struct has_trivial_copy : public integral_constant<bool, is_pod<T>::value && !is_volatile<T>::value>{};
|
||||
|
||||
#define EASTL_DECLARE_TRIVIAL_COPY(T) namespace eastl{ template <> struct has_trivial_copy<T> : public true_type{}; template <> struct has_trivial_copy<const T> : public true_type{}; }
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// has_trivial_assign
|
||||
//
|
||||
// has_trivial_assign<T>::value == true if and only if T is a class or
|
||||
// struct that has a trivial copy assignment operator. A copy assignment
|
||||
// operator is trivial if:
|
||||
// - it is implicitly defined by the compiler, and
|
||||
// - is_polymorphic<T>::value == false, and
|
||||
// - T has no virtual base classes, and
|
||||
// - for every direct base class of T, has_trivial_assign<B>::value == true,
|
||||
// where B is the type of the base class, and
|
||||
// - for every nonstatic data member of T that has class type or array
|
||||
// of class type, has_trivial_assign<M>::value == true, where M is
|
||||
// the type of the data member.
|
||||
//
|
||||
// has_trivial_assign may only be applied to complete types.
|
||||
//
|
||||
// Without from the compiler or user, has_trivial_assign will not
|
||||
// report that a class or struct has trivial assignment. The user
|
||||
// can use EASTL_DECLARE_TRIVIAL_ASSIGN to help the compiler.
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <typename T>
|
||||
struct has_trivial_assign : public integral_constant<bool,
|
||||
is_pod<T>::value && !is_const<T>::value && !is_volatile<T>::value
|
||||
>{};
|
||||
|
||||
#define EASTL_DECLARE_TRIVIAL_ASSIGN(T) namespace eastl{ template <> struct has_trivial_assign<T> : public true_type{}; template <> struct has_trivial_assign<const T> : public true_type{}; }
|
||||
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// has_trivial_destructor
|
||||
//
|
||||
// has_trivial_destructor<T>::value == true if and only if T is a class
|
||||
// or struct that has a trivial destructor. A destructor is trivial if
|
||||
// - it is implicitly defined by the compiler, and
|
||||
// - for every direct base class of T, has_trivial_destructor<B>::value == true,
|
||||
// where B is the type of the base class, and
|
||||
// - for every nonstatic data member of T that has class type or
|
||||
// array of class type, has_trivial_destructor<M>::value == true,
|
||||
// where M is the type of the data member
|
||||
//
|
||||
// has_trivial_destructor may only be applied to complete types.
|
||||
//
|
||||
// Without from the compiler or user, has_trivial_destructor will not
|
||||
// report that a class or struct has a trivial destructor.
|
||||
// The user can use EASTL_DECLARE_TRIVIAL_DESTRUCTOR to help the compiler.
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
|
||||
// With current compilers, this is all we can do.
|
||||
template <typename T>
|
||||
struct has_trivial_destructor : public is_pod<T>{};
|
||||
|
||||
#define EASTL_DECLARE_TRIVIAL_DESTRUCTOR(T) namespace eastl{ template <> struct has_trivial_destructor<T> : public true_type{}; template <> struct has_trivial_destructor<const T> : public true_type{}; }
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// has_trivial_relocate
|
||||
//
|
||||
// This is an EA extension to the type traits standard.
|
||||
//
|
||||
// A trivially relocatable object is one that can be safely memmove'd
|
||||
// to uninitialized memory. construction, assignment, and destruction
|
||||
// properties are not addressed by this trait. A type that has the
|
||||
// is_fundamental trait would always have the has_trivial_relocate trait.
|
||||
// A type that has the has_trivial_constructor, has_trivial_copy or
|
||||
// has_trivial_assign traits would usally have the has_trivial_relocate
|
||||
// trait, but this is not strictly guaranteed.
|
||||
//
|
||||
// The user can use EASTL_DECLARE_TRIVIAL_RELOCATE to help the compiler.
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
|
||||
// With current compilers, this is all we can do.
|
||||
template <typename T>
|
||||
struct has_trivial_relocate : public integral_constant<bool, is_pod<T>::value && !is_volatile<T>::value>{};
|
||||
|
||||
#define EASTL_DECLARE_TRIVIAL_RELOCATE(T) namespace eastl{ template <> struct has_trivial_relocate<T> : public true_type{}; template <> struct has_trivial_relocate<const T> : public true_type{}; }
|
||||
|
||||
|
||||
} // namespace eastl
|
||||
|
||||
|
||||
#endif // Header include guard
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
283
lib/eastl/include/EASTL/internal/type_properties.h
Normal file
283
lib/eastl/include/EASTL/internal/type_properties.h
Normal file
|
@ -0,0 +1,283 @@
|
|||
/*
|
||||
Copyright (C) 2005,2009-2010 Electronic Arts, Inc. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
3. Neither the name of Electronic Arts, Inc. ("EA") nor the names of
|
||||
its contributors may be used to endorse or promote products derived
|
||||
from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY ELECTRONIC ARTS AND ITS CONTRIBUTORS "AS IS" AND ANY
|
||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL ELECTRONIC ARTS OR ITS CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// EASTL/internal/type_properties.h
|
||||
// Written and maintained by Paul Pedriana - 2005.
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
#ifndef EASTL_INTERNAL_TYPE_PROPERTIES_H
|
||||
#define EASTL_INTERNAL_TYPE_PROPERTIES_H
|
||||
|
||||
|
||||
#include <limits.h>
|
||||
|
||||
|
||||
namespace eastl
|
||||
{
|
||||
|
||||
// The following properties or relations are defined here. If the given
|
||||
// item is missing then it simply hasn't been implemented, at least not yet.
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// is_const
|
||||
//
|
||||
// is_const<T>::value == true if and only if T has const-qualification.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
template <typename T> struct is_const_value : public false_type{};
|
||||
template <typename T> struct is_const_value<const T*> : public true_type{};
|
||||
template <typename T> struct is_const_value<const volatile T*> : public true_type{};
|
||||
|
||||
template <typename T> struct is_const : public is_const_value<T*>{};
|
||||
template <typename T> struct is_const<T&> : public false_type{}; // Note here that T is const, not the reference to T. So is_const is false. See section 8.3.2p1 of the C++ standard.
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// is_volatile
|
||||
//
|
||||
// is_volatile<T>::value == true if and only if T has volatile-qualification.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <typename T> struct is_volatile_value : public false_type{};
|
||||
template <typename T> struct is_volatile_value<volatile T*> : public true_type{};
|
||||
template <typename T> struct is_volatile_value<const volatile T*> : public true_type{};
|
||||
|
||||
template <typename T> struct is_volatile : public is_volatile_value<T*>{};
|
||||
template <typename T> struct is_volatile<T&> : public false_type{}; // Note here that T is volatile, not the reference to T. So is_const is false. See section 8.3.2p1 of the C++ standard.
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// is_abstract
|
||||
//
|
||||
// is_abstract<T>::value == true if and only if T is a class or struct
|
||||
// that has at least one pure virtual function. is_abstract may only
|
||||
// be applied to complete types.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Not implemented yet.
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// is_signed
|
||||
//
|
||||
// is_signed<T>::value == true if and only if T is one of the following types:
|
||||
// [const] [volatile] char (maybe)
|
||||
// [const] [volatile] signed char
|
||||
// [const] [volatile] short
|
||||
// [const] [volatile] int
|
||||
// [const] [volatile] long
|
||||
// [const] [volatile] long long
|
||||
//
|
||||
// Used to determine if a integral type is signed or unsigned.
|
||||
// Given that there are some user-made classes which emulate integral
|
||||
// types, we provide the EASTL_DECLARE_SIGNED macro to allow you to
|
||||
// set a given class to be identified as a signed type.
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
template <typename T> struct is_signed : public false_type{};
|
||||
|
||||
template <> struct is_signed<signed char> : public true_type{};
|
||||
template <> struct is_signed<const signed char> : public true_type{};
|
||||
template <> struct is_signed<signed short> : public true_type{};
|
||||
template <> struct is_signed<const signed short> : public true_type{};
|
||||
template <> struct is_signed<signed int> : public true_type{};
|
||||
template <> struct is_signed<const signed int> : public true_type{};
|
||||
template <> struct is_signed<signed long> : public true_type{};
|
||||
template <> struct is_signed<const signed long> : public true_type{};
|
||||
template <> struct is_signed<signed long long> : public true_type{};
|
||||
template <> struct is_signed<const signed long long> : public true_type{};
|
||||
|
||||
#if (CHAR_MAX == SCHAR_MAX)
|
||||
template <> struct is_signed<char> : public true_type{};
|
||||
template <> struct is_signed<const char> : public true_type{};
|
||||
#endif
|
||||
#ifndef EA_WCHAR_T_NON_NATIVE // If wchar_t is a native type instead of simply a define to an existing type...
|
||||
#if defined(__WCHAR_MAX__) && ((__WCHAR_MAX__ == 2147483647) || (__WCHAR_MAX__ == 32767)) // GCC defines __WCHAR_MAX__ for most platforms.
|
||||
template <> struct is_signed<wchar_t> : public true_type{};
|
||||
template <> struct is_signed<const wchar_t> : public true_type{};
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define EASTL_DECLARE_SIGNED(T) namespace eastl{ template <> struct is_signed<T> : public true_type{}; template <> struct is_signed<const T> : public true_type{}; }
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// is_unsigned
|
||||
//
|
||||
// is_unsigned<T>::value == true if and only if T is one of the following types:
|
||||
// [const] [volatile] char (maybe)
|
||||
// [const] [volatile] unsigned char
|
||||
// [const] [volatile] unsigned short
|
||||
// [const] [volatile] unsigned int
|
||||
// [const] [volatile] unsigned long
|
||||
// [const] [volatile] unsigned long long
|
||||
//
|
||||
// Used to determine if a integral type is signed or unsigned.
|
||||
// Given that there are some user-made classes which emulate integral
|
||||
// types, we provide the EASTL_DECLARE_UNSIGNED macro to allow you to
|
||||
// set a given class to be identified as an unsigned type.
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
template <typename T> struct is_unsigned : public false_type{};
|
||||
|
||||
template <> struct is_unsigned<unsigned char> : public true_type{};
|
||||
template <> struct is_unsigned<const unsigned char> : public true_type{};
|
||||
template <> struct is_unsigned<unsigned short> : public true_type{};
|
||||
template <> struct is_unsigned<const unsigned short> : public true_type{};
|
||||
template <> struct is_unsigned<unsigned int> : public true_type{};
|
||||
template <> struct is_unsigned<const unsigned int> : public true_type{};
|
||||
template <> struct is_unsigned<unsigned long> : public true_type{};
|
||||
template <> struct is_unsigned<const unsigned long> : public true_type{};
|
||||
template <> struct is_unsigned<unsigned long long> : public true_type{};
|
||||
template <> struct is_unsigned<const unsigned long long> : public true_type{};
|
||||
|
||||
#if (CHAR_MAX == UCHAR_MAX)
|
||||
template <> struct is_unsigned<char> : public true_type{};
|
||||
template <> struct is_unsigned<const char> : public true_type{};
|
||||
#endif
|
||||
#ifndef EA_WCHAR_T_NON_NATIVE // If wchar_t is a native type instead of simply a define to an existing type...
|
||||
#if defined(_MSC_VER) || (defined(__WCHAR_MAX__) && ((__WCHAR_MAX__ == 4294967295U) || (__WCHAR_MAX__ == 65535))) // GCC defines __WCHAR_MAX__ for most platforms.
|
||||
template <> struct is_unsigned<wchar_t> : public true_type{};
|
||||
template <> struct is_unsigned<const wchar_t> : public true_type{};
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define EASTL_DECLARE_UNSIGNED(T) namespace eastl{ template <> struct is_unsigned<T> : public true_type{}; template <> struct is_unsigned<const T> : public true_type{}; }
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// alignment_of
|
||||
//
|
||||
// alignment_of<T>::value is an integral value representing, in bytes,
|
||||
// the memory alignment of objects of type T.
|
||||
//
|
||||
// alignment_of may only be applied to complete types.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
template <typename T>
|
||||
struct alignment_of_value{ static const size_t value = EASTL_ALIGN_OF(T); };
|
||||
|
||||
template <typename T>
|
||||
struct alignment_of : public integral_constant<size_t, alignment_of_value<T>::value>{};
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// is_aligned
|
||||
//
|
||||
// Defined as true if the type has alignment requirements greater
|
||||
// than default alignment, which is taken to be 8. This allows for
|
||||
// doing specialized object allocation and placement for such types.
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
template <typename T>
|
||||
struct is_aligned_value{ static const bool value = (EASTL_ALIGN_OF(T) > 8); };
|
||||
|
||||
template <typename T>
|
||||
struct is_aligned : public integral_constant<bool, is_aligned_value<T>::value>{};
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// rank
|
||||
//
|
||||
// rank<T>::value is an integral value representing the number of
|
||||
// dimensions possessed by an array type. For example, given a
|
||||
// multi-dimensional array type T[M][N], std::tr1::rank<T[M][N]>::value == 2.
|
||||
// For a given non-array type T, std::tr1::rank<T>::value == 0.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Not implemented yet.
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// extent
|
||||
//
|
||||
// extent<T, I>::value is an integral type representing the number of
|
||||
// elements in the Ith dimension of array type T.
|
||||
//
|
||||
// For a given array type T[N], std::tr1::extent<T[N]>::value == N.
|
||||
// For a given multi-dimensional array type T[M][N], std::tr1::extent<T[M][N], 0>::value == N.
|
||||
// For a given multi-dimensional array type T[M][N], std::tr1::extent<T[M][N], 1>::value == M.
|
||||
// For a given array type T and a given dimension I where I >= rank<T>::value, std::tr1::extent<T, I>::value == 0.
|
||||
// For a given array type of unknown extent T[], std::tr1::extent<T[], 0>::value == 0.
|
||||
// For a given non-array type T and an arbitrary dimension I, std::tr1::extent<T, I>::value == 0.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Not implemented yet.
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// is_base_of
|
||||
//
|
||||
// Given two (possibly identical) types Base and Derived, is_base_of<Base, Derived>::value == true
|
||||
// if and only if Base is a direct or indirect base class of Derived,
|
||||
// or Base and Derived are the same type.
|
||||
//
|
||||
// is_base_of may only be applied to complete types.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Not implemented yet.
|
||||
|
||||
|
||||
|
||||
} // namespace eastl
|
||||
|
||||
|
||||
#endif // Header include guard
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
244
lib/eastl/include/EASTL/internal/type_transformations.h
Normal file
244
lib/eastl/include/EASTL/internal/type_transformations.h
Normal file
|
@ -0,0 +1,244 @@
|
|||
/*
|
||||
Copyright (C) 2005,2009-2010 Electronic Arts, Inc. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
3. Neither the name of Electronic Arts, Inc. ("EA") nor the names of
|
||||
its contributors may be used to endorse or promote products derived
|
||||
from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY ELECTRONIC ARTS AND ITS CONTRIBUTORS "AS IS" AND ANY
|
||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL ELECTRONIC ARTS OR ITS CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// EASTL/internal/type_transformations.h
|
||||
// Written and maintained by Paul Pedriana - 2005
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
#ifndef EASTL_INTERNAL_TYPE_TRANFORMATIONS_H
|
||||
#define EASTL_INTERNAL_TYPE_TRANFORMATIONS_H
|
||||
|
||||
|
||||
namespace eastl
|
||||
{
|
||||
|
||||
|
||||
// The following transformations are defined here. If the given item
|
||||
// is missing then it simply hasn't been implemented, at least not yet.
|
||||
// add_unsigned
|
||||
// add_signed
|
||||
// remove_const
|
||||
// remove_volatile
|
||||
// remove_cv
|
||||
// add_const
|
||||
// add_volatile
|
||||
// add_cv
|
||||
// remove_reference
|
||||
// add_reference
|
||||
// remove_extent
|
||||
// remove_all_extents
|
||||
// remove_pointer
|
||||
// add_pointer
|
||||
// aligned_storage
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// add_signed
|
||||
//
|
||||
// Adds signed-ness to the given type.
|
||||
// Modifies only integral values; has no effect on others.
|
||||
// add_signed<int>::type is int
|
||||
// add_signed<unsigned int>::type is int
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<class T>
|
||||
struct add_signed
|
||||
{ typedef T type; };
|
||||
|
||||
template<>
|
||||
struct add_signed<unsigned char>
|
||||
{ typedef signed char type; };
|
||||
|
||||
#if (defined(CHAR_MAX) && defined(UCHAR_MAX) && (CHAR_MAX == UCHAR_MAX)) // If char is unsigned (which is usually not the case)...
|
||||
template<>
|
||||
struct add_signed<char>
|
||||
{ typedef signed char type; };
|
||||
#endif
|
||||
|
||||
template<>
|
||||
struct add_signed<unsigned short>
|
||||
{ typedef short type; };
|
||||
|
||||
template<>
|
||||
struct add_signed<unsigned int>
|
||||
{ typedef int type; };
|
||||
|
||||
template<>
|
||||
struct add_signed<unsigned long>
|
||||
{ typedef long type; };
|
||||
|
||||
template<>
|
||||
struct add_signed<unsigned long long>
|
||||
{ typedef long long type; };
|
||||
|
||||
#ifndef EA_WCHAR_T_NON_NATIVE // If wchar_t is a native type instead of simply a define to an existing type...
|
||||
#if (defined(__WCHAR_MAX__) && (__WCHAR_MAX__ == 4294967295U)) // If wchar_t is a 32 bit unsigned value...
|
||||
template<>
|
||||
struct add_signed<wchar_t>
|
||||
{ typedef int32_t type; };
|
||||
#elif (defined(__WCHAR_MAX__) && (__WCHAR_MAX__ == 65535)) // If wchar_t is a 16 bit unsigned value...
|
||||
template<>
|
||||
struct add_signed<wchar_t>
|
||||
{ typedef int16_t type; };
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// add_unsigned
|
||||
//
|
||||
// Adds unsigned-ness to the given type.
|
||||
// Modifies only integral values; has no effect on others.
|
||||
// add_unsigned<int>::type is unsigned int
|
||||
// add_unsigned<unsigned int>::type is unsigned int
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<class T>
|
||||
struct add_unsigned
|
||||
{ typedef T type; };
|
||||
|
||||
template<>
|
||||
struct add_unsigned<signed char>
|
||||
{ typedef unsigned char type; };
|
||||
|
||||
#if (defined(CHAR_MAX) && defined(SCHAR_MAX) && (CHAR_MAX == SCHAR_MAX)) // If char is signed (which is usually so)...
|
||||
template<>
|
||||
struct add_unsigned<char>
|
||||
{ typedef unsigned char type; };
|
||||
#endif
|
||||
|
||||
template<>
|
||||
struct add_unsigned<short>
|
||||
{ typedef unsigned short type; };
|
||||
|
||||
template<>
|
||||
struct add_unsigned<int>
|
||||
{ typedef unsigned int type; };
|
||||
|
||||
template<>
|
||||
struct add_unsigned<long>
|
||||
{ typedef unsigned long type; };
|
||||
|
||||
template<>
|
||||
struct add_unsigned<long long>
|
||||
{ typedef unsigned long long type; };
|
||||
|
||||
#ifndef EA_WCHAR_T_NON_NATIVE // If wchar_t is a native type instead of simply a define to an existing type...
|
||||
#if (defined(__WCHAR_MAX__) && (__WCHAR_MAX__ == 2147483647)) // If wchar_t is a 32 bit signed value...
|
||||
template<>
|
||||
struct add_unsigned<wchar_t>
|
||||
{ typedef uint32_t type; };
|
||||
#elif (defined(__WCHAR_MAX__) && (__WCHAR_MAX__ == 32767)) // If wchar_t is a 16 bit signed value...
|
||||
template<>
|
||||
struct add_unsigned<wchar_t>
|
||||
{ typedef uint16_t type; };
|
||||
#endif
|
||||
#endif
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// remove_cv
|
||||
//
|
||||
// Remove const and volatile from a type.
|
||||
//
|
||||
// The remove_cv transformation trait removes top-level const and/or volatile
|
||||
// qualification (if any) from the type to which it is applied. For a given type T,
|
||||
// remove_cv<T const volatile>::type is equivalent to T. For example,
|
||||
// remove_cv<char* volatile>::type is equivalent to char*, while remove_cv<const char*>::type
|
||||
// is equivalent to const char*. In the latter case, the const qualifier modifies
|
||||
// char, not *, and is therefore not at the top level.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
template <typename T> struct remove_cv_imp{};
|
||||
template <typename T> struct remove_cv_imp<T*> { typedef T unqualified_type; };
|
||||
template <typename T> struct remove_cv_imp<const T*> { typedef T unqualified_type; };
|
||||
template <typename T> struct remove_cv_imp<volatile T*> { typedef T unqualified_type; };
|
||||
template <typename T> struct remove_cv_imp<const volatile T*> { typedef T unqualified_type; };
|
||||
|
||||
template <typename T> struct remove_cv{ typedef typename remove_cv_imp<T*>::unqualified_type type; };
|
||||
template <typename T> struct remove_cv<T&>{ typedef T& type; }; // References are automatically not const nor volatile. See section 8.3.2p1 of the C++ standard.
|
||||
|
||||
template <typename T, size_t N> struct remove_cv<T const[N]> { typedef T type[N]; };
|
||||
template <typename T, size_t N> struct remove_cv<T volatile[N]> { typedef T type[N]; };
|
||||
template <typename T, size_t N> struct remove_cv<T const volatile[N]>{ typedef T type[N]; };
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// add_reference
|
||||
//
|
||||
// Add reference to a type.
|
||||
//
|
||||
// The add_reference transformation trait adds a level of indirection
|
||||
// by reference to the type to which it is applied. For a given type T,
|
||||
// add_reference<T>::type is equivalent to T& if is_reference<T>::value == false,
|
||||
// and T otherwise.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
template <typename T>
|
||||
struct add_reference_impl{ typedef T& type; };
|
||||
|
||||
template <typename T>
|
||||
struct add_reference_impl<T&>{ typedef T& type; };
|
||||
|
||||
template <>
|
||||
struct add_reference_impl<void>{ typedef void type; };
|
||||
|
||||
template <typename T>
|
||||
struct add_reference { typedef typename add_reference_impl<T>::type type; };
|
||||
|
||||
|
||||
} // namespace eastl
|
||||
|
||||
|
||||
#endif // Header include guard
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
621
lib/eastl/include/EASTL/iterator.h
Normal file
621
lib/eastl/include/EASTL/iterator.h
Normal file
|
@ -0,0 +1,621 @@
|
|||
/*
|
||||
Copyright (C) 2009-2010 Electronic Arts, Inc. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
3. Neither the name of Electronic Arts, Inc. ("EA") nor the names of
|
||||
its contributors may be used to endorse or promote products derived
|
||||
from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY ELECTRONIC ARTS AND ITS CONTRIBUTORS "AS IS" AND ANY
|
||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL ELECTRONIC ARTS OR ITS CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// EASTL/iterator.h
|
||||
//
|
||||
// Copyright (c) 2005, Electronic Arts. All rights reserved.
|
||||
// Written and maintained by Paul Pedriana.
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
#ifndef EASTL_ITERATOR_H
|
||||
#define EASTL_ITERATOR_H
|
||||
|
||||
|
||||
#include <EASTL/internal/config.h>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(push, 0)
|
||||
#endif
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
// If the user has specified that we use std iterator
|
||||
// categories instead of EASTL iterator categories,
|
||||
// then #include <iterator>.
|
||||
#if EASTL_STD_ITERATOR_CATEGORY_ENABLED
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(push, 0)
|
||||
#endif
|
||||
#include <iterator>
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(push) // VC++ generates a bogus warning that you cannot code away.
|
||||
#pragma warning(disable: 4619) // There is no warning number 'number'.
|
||||
#pragma warning(disable: 4217) // Member template functions cannot be used for copy-assignment or copy-construction.
|
||||
#elif defined(__SNC__)
|
||||
#pragma control %push diag
|
||||
#pragma diag_suppress=187 // Pointless comparison of unsigned integer with zero
|
||||
#endif
|
||||
|
||||
|
||||
namespace eastl
|
||||
{
|
||||
/// iterator_status_flag
|
||||
///
|
||||
/// Defines the validity status of an iterator. This is primarily used for
|
||||
/// iterator validation in debug builds. These are implemented as OR-able
|
||||
/// flags (as opposed to mutually exclusive values) in order to deal with
|
||||
/// the nature of iterator status. In particular, an iterator may be valid
|
||||
/// but not dereferencable, as in the case with an iterator to container end().
|
||||
/// An iterator may be valid but also dereferencable, as in the case with an
|
||||
/// iterator to container begin().
|
||||
///
|
||||
enum iterator_status_flag
|
||||
{
|
||||
isf_none = 0x00, /// This is called none and not called invalid because it is not strictly the opposite of invalid.
|
||||
isf_valid = 0x01, /// The iterator is valid, which means it is in the range of [begin, end].
|
||||
isf_current = 0x02, /// The iterator is valid and points to the same element it did when created. For example, if an iterator points to vector::begin() but an element is inserted at the front, the iterator is valid but not current. Modification of elements in place do not make iterators non-current.
|
||||
isf_can_dereference = 0x04 /// The iterator is dereferencable, which means it is in the range of [begin, end). It may or may not be current.
|
||||
};
|
||||
|
||||
|
||||
|
||||
// The following declarations are taken directly from the C++ standard document.
|
||||
// input_iterator_tag, etc.
|
||||
// iterator
|
||||
// iterator_traits
|
||||
// reverse_iterator
|
||||
|
||||
// Iterator categories
|
||||
// Every iterator is defined as belonging to one of the iterator categories that
|
||||
// we define here. These categories come directly from the C++ standard.
|
||||
#if !EASTL_STD_ITERATOR_CATEGORY_ENABLED // If we are to use our own iterator category definitions...
|
||||
struct input_iterator_tag { };
|
||||
struct output_iterator_tag { };
|
||||
struct forward_iterator_tag : public input_iterator_tag { };
|
||||
struct bidirectional_iterator_tag : public forward_iterator_tag { };
|
||||
struct random_access_iterator_tag : public bidirectional_iterator_tag { };
|
||||
struct contiguous_iterator_tag : public random_access_iterator_tag { }; // Extension to the C++ standard. Contiguous ranges are more than random access, they are physically contiguous.
|
||||
#endif
|
||||
|
||||
|
||||
// struct iterator
|
||||
template <typename Category, typename T, typename Distance = ptrdiff_t,
|
||||
typename Pointer = T*, typename Reference = T&>
|
||||
struct iterator
|
||||
{
|
||||
typedef Category iterator_category;
|
||||
typedef T value_type;
|
||||
typedef Distance difference_type;
|
||||
typedef Pointer pointer;
|
||||
typedef Reference reference;
|
||||
};
|
||||
|
||||
|
||||
// struct iterator_traits
|
||||
template <typename Iterator>
|
||||
struct iterator_traits
|
||||
{
|
||||
typedef typename Iterator::iterator_category iterator_category;
|
||||
typedef typename Iterator::value_type value_type;
|
||||
typedef typename Iterator::difference_type difference_type;
|
||||
typedef typename Iterator::pointer pointer;
|
||||
typedef typename Iterator::reference reference;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct iterator_traits<T*>
|
||||
{
|
||||
typedef EASTL_ITC_NS::random_access_iterator_tag iterator_category; // To consider: Change this to contiguous_iterator_tag for the case that
|
||||
typedef T value_type; // EASTL_ITC_NS is "eastl" instead of "std".
|
||||
typedef ptrdiff_t difference_type;
|
||||
typedef T* pointer;
|
||||
typedef T& reference;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct iterator_traits<const T*>
|
||||
{
|
||||
typedef EASTL_ITC_NS::random_access_iterator_tag iterator_category;
|
||||
typedef T value_type;
|
||||
typedef ptrdiff_t difference_type;
|
||||
typedef const T* pointer;
|
||||
typedef const T& reference;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/// reverse_iterator
|
||||
///
|
||||
/// From the C++ standard:
|
||||
/// Bidirectional and random access iterators have corresponding reverse
|
||||
/// iterator adaptors that iterate through the data structure in the
|
||||
/// opposite direction. They have the same signatures as the corresponding
|
||||
/// iterators. The fundamental relation between a reverse iterator and its
|
||||
/// corresponding iterator i is established by the identity:
|
||||
/// &*(reverse_iterator(i)) == &*(i - 1).
|
||||
/// This mapping is dictated by the fact that while there is always a pointer
|
||||
/// past the end of an array, there might not be a valid pointer before the
|
||||
/// beginning of an array.
|
||||
///
|
||||
template <typename Iterator>
|
||||
class reverse_iterator : public iterator<typename eastl::iterator_traits<Iterator>::iterator_category,
|
||||
typename eastl::iterator_traits<Iterator>::value_type,
|
||||
typename eastl::iterator_traits<Iterator>::difference_type,
|
||||
typename eastl::iterator_traits<Iterator>::pointer,
|
||||
typename eastl::iterator_traits<Iterator>::reference>
|
||||
{
|
||||
public:
|
||||
typedef Iterator iterator_type;
|
||||
typedef typename eastl::iterator_traits<Iterator>::pointer pointer;
|
||||
typedef typename eastl::iterator_traits<Iterator>::reference reference;
|
||||
typedef typename eastl::iterator_traits<Iterator>::difference_type difference_type;
|
||||
|
||||
protected:
|
||||
Iterator mIterator;
|
||||
|
||||
public:
|
||||
reverse_iterator() // It's important that we construct mIterator, because if Iterator
|
||||
: mIterator() { } // is a pointer, there's a difference between doing it and not.
|
||||
|
||||
explicit reverse_iterator(iterator_type i)
|
||||
: mIterator(i) { }
|
||||
|
||||
reverse_iterator(const reverse_iterator& ri)
|
||||
: mIterator(ri.mIterator) { }
|
||||
|
||||
template <typename U>
|
||||
reverse_iterator(const reverse_iterator<U>& ri)
|
||||
: mIterator(ri.base()) { }
|
||||
|
||||
// This operator= isn't in the standard, but the the C++
|
||||
// library working group has tentatively approved it, as it
|
||||
// allows const and non-const reverse_iterators to interoperate.
|
||||
template <typename U>
|
||||
reverse_iterator<Iterator>& operator=(const reverse_iterator<U>& ri)
|
||||
{ mIterator = ri.base(); return *this; }
|
||||
|
||||
iterator_type base() const
|
||||
{ return mIterator; }
|
||||
|
||||
reference operator*() const
|
||||
{
|
||||
iterator_type i(mIterator);
|
||||
return *--i;
|
||||
}
|
||||
|
||||
pointer operator->() const
|
||||
{ return &(operator*()); }
|
||||
|
||||
reverse_iterator& operator++()
|
||||
{ --mIterator; return *this; }
|
||||
|
||||
reverse_iterator operator++(int)
|
||||
{
|
||||
reverse_iterator ri(*this);
|
||||
--mIterator;
|
||||
return ri;
|
||||
}
|
||||
|
||||
reverse_iterator& operator--()
|
||||
{ ++mIterator; return *this; }
|
||||
|
||||
reverse_iterator operator--(int)
|
||||
{
|
||||
reverse_iterator ri(*this);
|
||||
++mIterator;
|
||||
return ri;
|
||||
}
|
||||
|
||||
reverse_iterator operator+(difference_type n) const
|
||||
{ return reverse_iterator(mIterator - n); }
|
||||
|
||||
reverse_iterator& operator+=(difference_type n)
|
||||
{ mIterator -= n; return *this; }
|
||||
|
||||
reverse_iterator operator-(difference_type n) const
|
||||
{ return reverse_iterator(mIterator + n); }
|
||||
|
||||
reverse_iterator& operator-=(difference_type n)
|
||||
{ mIterator += n; return *this; }
|
||||
|
||||
reference operator[](difference_type n) const
|
||||
{ return mIterator[-n - 1]; }
|
||||
};
|
||||
|
||||
|
||||
// The C++ library working group has tentatively approved the usage of two
|
||||
// template parameters (Iterator1 and Iterator2) in order to allow reverse_iterators
|
||||
// and const_reverse iterators to be comparable. This is a similar issue to the
|
||||
// C++ defect report #179 regarding comparison of container iterators and const_iterators.
|
||||
template <typename Iterator1, typename Iterator2>
|
||||
inline bool
|
||||
operator==(const reverse_iterator<Iterator1>& a, const reverse_iterator<Iterator2>& b)
|
||||
{ return a.base() == b.base(); }
|
||||
|
||||
|
||||
template <typename Iterator1, typename Iterator2>
|
||||
inline bool
|
||||
operator<(const reverse_iterator<Iterator1>& a, const reverse_iterator<Iterator2>& b)
|
||||
{ return a.base() > b.base(); }
|
||||
|
||||
|
||||
template <typename Iterator1, typename Iterator2>
|
||||
inline bool
|
||||
operator!=(const reverse_iterator<Iterator1>& a, const reverse_iterator<Iterator2>& b)
|
||||
{ return a.base() != b.base(); }
|
||||
|
||||
|
||||
template <typename Iterator1, typename Iterator2>
|
||||
inline bool
|
||||
operator>(const reverse_iterator<Iterator1>& a, const reverse_iterator<Iterator2>& b)
|
||||
{ return a.base() < b.base(); }
|
||||
|
||||
|
||||
template <typename Iterator1, typename Iterator2>
|
||||
inline bool
|
||||
operator<=(const reverse_iterator<Iterator1>& a, const reverse_iterator<Iterator2>& b)
|
||||
{ return a.base() >= b.base(); }
|
||||
|
||||
|
||||
template <typename Iterator1, typename Iterator2>
|
||||
inline bool
|
||||
operator>=(const reverse_iterator<Iterator1>& a, const reverse_iterator<Iterator2>& b)
|
||||
{ return a.base() <= b.base(); }
|
||||
|
||||
|
||||
template <typename Iterator1, typename Iterator2>
|
||||
inline typename reverse_iterator<Iterator1>::difference_type
|
||||
operator-(const reverse_iterator<Iterator1>& a, const reverse_iterator<Iterator2>& b)
|
||||
{ return b.base() - a.base(); }
|
||||
|
||||
|
||||
template <typename Iterator>
|
||||
inline reverse_iterator<Iterator>
|
||||
operator+(typename reverse_iterator<Iterator>::difference_type n, const reverse_iterator<Iterator>& a)
|
||||
{ return reverse_iterator<Iterator>(a.base() - n); }
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/// back_insert_iterator
|
||||
///
|
||||
/// A back_insert_iterator is simply a class that acts like an iterator but when you
|
||||
/// assign a value to it, it calls push_back on the container with the value.
|
||||
///
|
||||
template <typename Container>
|
||||
class back_insert_iterator : public iterator<EASTL_ITC_NS::output_iterator_tag, void, void, void, void>
|
||||
{
|
||||
public:
|
||||
typedef Container container_type;
|
||||
typedef typename Container::const_reference const_reference;
|
||||
|
||||
protected:
|
||||
Container& container;
|
||||
|
||||
public:
|
||||
explicit back_insert_iterator(Container& x)
|
||||
: container(x) { }
|
||||
|
||||
back_insert_iterator& operator=(const_reference value)
|
||||
{ container.push_back(value); return *this; }
|
||||
|
||||
back_insert_iterator& operator*()
|
||||
{ return *this; }
|
||||
|
||||
back_insert_iterator& operator++()
|
||||
{ return *this; } // This is by design.
|
||||
|
||||
back_insert_iterator operator++(int)
|
||||
{ return *this; } // This is by design.
|
||||
};
|
||||
|
||||
|
||||
/// back_inserter
|
||||
///
|
||||
/// Creates an instance of a back_insert_iterator.
|
||||
///
|
||||
template <typename Container>
|
||||
inline back_insert_iterator<Container>
|
||||
back_inserter(Container& x)
|
||||
{ return back_insert_iterator<Container>(x); }
|
||||
|
||||
|
||||
|
||||
|
||||
/// front_insert_iterator
|
||||
///
|
||||
/// A front_insert_iterator is simply a class that acts like an iterator but when you
|
||||
/// assign a value to it, it calls push_front on the container with the value.
|
||||
///
|
||||
template <typename Container>
|
||||
class front_insert_iterator : public iterator<EASTL_ITC_NS::output_iterator_tag, void, void, void, void>
|
||||
{
|
||||
public:
|
||||
typedef Container container_type;
|
||||
typedef typename Container::const_reference const_reference;
|
||||
|
||||
protected:
|
||||
Container& container;
|
||||
|
||||
public:
|
||||
explicit front_insert_iterator(Container& x)
|
||||
: container(x) { }
|
||||
|
||||
front_insert_iterator& operator=(const_reference value)
|
||||
{ container.push_front(value); return *this; }
|
||||
|
||||
front_insert_iterator& operator*()
|
||||
{ return *this; }
|
||||
|
||||
front_insert_iterator& operator++()
|
||||
{ return *this; } // This is by design.
|
||||
|
||||
front_insert_iterator operator++(int)
|
||||
{ return *this; } // This is by design.
|
||||
};
|
||||
|
||||
|
||||
/// front_inserter
|
||||
///
|
||||
/// Creates an instance of a front_insert_iterator.
|
||||
///
|
||||
template <typename Container>
|
||||
inline front_insert_iterator<Container>
|
||||
front_inserter(Container& x)
|
||||
{ return front_insert_iterator<Container>(x); }
|
||||
|
||||
|
||||
|
||||
|
||||
/// insert_iterator
|
||||
///
|
||||
/// An insert_iterator is like an iterator except that when you assign a value to it,
|
||||
/// the insert_iterator inserts the value into the container and increments the iterator.
|
||||
///
|
||||
/// insert_iterator is an iterator adaptor that functions as an OutputIterator:
|
||||
/// assignment through an insert_iterator inserts an object into a container.
|
||||
/// Specifically, if ii is an insert_iterator, then ii keeps track of a container c and
|
||||
/// an insertion point p; the expression *ii = x performs the insertion c.insert(p, x).
|
||||
///
|
||||
/// If you assign through an insert_iterator several times, then you will be inserting
|
||||
/// several elements into the underlying container. In the case of a sequence, they will
|
||||
/// appear at a particular location in the underlying sequence, in the order in which
|
||||
/// they were inserted: one of the arguments to insert_iterator's constructor is an
|
||||
/// iterator p, and the new range will be inserted immediately before p.
|
||||
///
|
||||
template <typename Container>
|
||||
class insert_iterator : public iterator<EASTL_ITC_NS::output_iterator_tag, void, void, void, void>
|
||||
{
|
||||
public:
|
||||
typedef Container container_type;
|
||||
typedef typename Container::iterator iterator_type;
|
||||
typedef typename Container::const_reference const_reference;
|
||||
|
||||
protected:
|
||||
Container& container;
|
||||
iterator_type it;
|
||||
|
||||
public:
|
||||
// This assignment operator is defined more to stop compiler warnings (e.g. VC++ C4512)
|
||||
// than to be useful. However, it does an insert_iterator to be assigned to another
|
||||
// insert iterator provided that they point to the same container.
|
||||
insert_iterator& operator=(const insert_iterator& x)
|
||||
{
|
||||
EASTL_ASSERT(&x.container == &container);
|
||||
it = x.it;
|
||||
return *this;
|
||||
}
|
||||
|
||||
insert_iterator(Container& x, iterator_type itNew)
|
||||
: container(x), it(itNew) {}
|
||||
|
||||
insert_iterator& operator=(const_reference value)
|
||||
{
|
||||
it = container.insert(it, value);
|
||||
++it;
|
||||
return *this;
|
||||
}
|
||||
|
||||
insert_iterator& operator*()
|
||||
{ return *this; }
|
||||
|
||||
insert_iterator& operator++()
|
||||
{ return *this; } // This is by design.
|
||||
|
||||
insert_iterator& operator++(int)
|
||||
{ return *this; } // This is by design.
|
||||
|
||||
}; // insert_iterator
|
||||
|
||||
|
||||
/// inserter
|
||||
///
|
||||
/// Creates an instance of an insert_iterator.
|
||||
///
|
||||
template <typename Container, typename Iterator>
|
||||
inline eastl::insert_iterator<Container>
|
||||
inserter(Container& x, Iterator i)
|
||||
{
|
||||
typedef typename Container::iterator iterator;
|
||||
return eastl::insert_iterator<Container>(x, iterator(i));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
/// distance
|
||||
///
|
||||
/// Implements the distance() function. There are two versions, one for
|
||||
/// random access iterators (e.g. with vector) and one for regular input
|
||||
/// iterators (e.g. with list). The former is more efficient.
|
||||
///
|
||||
template <typename InputIterator>
|
||||
inline typename eastl::iterator_traits<InputIterator>::difference_type
|
||||
distance_impl(InputIterator first, InputIterator last, EASTL_ITC_NS::input_iterator_tag)
|
||||
{
|
||||
typename eastl::iterator_traits<InputIterator>::difference_type n = 0;
|
||||
|
||||
while(first != last)
|
||||
{
|
||||
++first;
|
||||
++n;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
template <typename RandomAccessIterator>
|
||||
inline typename eastl::iterator_traits<RandomAccessIterator>::difference_type
|
||||
distance_impl(RandomAccessIterator first, RandomAccessIterator last, EASTL_ITC_NS::random_access_iterator_tag)
|
||||
{
|
||||
return last - first;
|
||||
}
|
||||
|
||||
// Special version defined so that std C++ iterators can be recognized by
|
||||
// this function. Unfortunately, this function treats all foreign iterators
|
||||
// as InputIterators and thus can seriously hamper performance in the case
|
||||
// of large ranges of bidirectional_iterator_tag iterators.
|
||||
//template <typename InputIterator>
|
||||
//inline typename eastl::iterator_traits<InputIterator>::difference_type
|
||||
//distance_impl(InputIterator first, InputIterator last, ...)
|
||||
//{
|
||||
// typename eastl::iterator_traits<InputIterator>::difference_type n = 0;
|
||||
//
|
||||
// while(first != last)
|
||||
// {
|
||||
// ++first;
|
||||
// ++n;
|
||||
// }
|
||||
// return n;
|
||||
//}
|
||||
|
||||
template <typename InputIterator>
|
||||
inline typename eastl::iterator_traits<InputIterator>::difference_type
|
||||
distance(InputIterator first, InputIterator last)
|
||||
{
|
||||
typedef typename eastl::iterator_traits<InputIterator>::iterator_category IC;
|
||||
|
||||
return eastl::distance_impl(first, last, IC());
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
/// advance
|
||||
///
|
||||
/// Implements the advance() function. There are three versions, one for
|
||||
/// random access iterators (e.g. with vector), one for bidirectional
|
||||
/// iterators (list) and one for regular input iterators (e.g. with slist).
|
||||
///
|
||||
template <typename InputIterator, typename Distance>
|
||||
inline void
|
||||
advance_impl(InputIterator& i, Distance n, EASTL_ITC_NS::input_iterator_tag)
|
||||
{
|
||||
while(n--)
|
||||
++i;
|
||||
}
|
||||
|
||||
template <typename BidirectionalIterator, typename Distance>
|
||||
inline void
|
||||
advance_impl(BidirectionalIterator& i, Distance n, EASTL_ITC_NS::bidirectional_iterator_tag)
|
||||
{
|
||||
if(n > 0)
|
||||
{
|
||||
while(n--)
|
||||
++i;
|
||||
}
|
||||
else
|
||||
{
|
||||
while(n++)
|
||||
--i;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename RandomAccessIterator, typename Distance>
|
||||
inline void
|
||||
advance_impl(RandomAccessIterator& i, Distance n, EASTL_ITC_NS::random_access_iterator_tag)
|
||||
{
|
||||
i += n;
|
||||
}
|
||||
|
||||
// Special version defined so that std C++ iterators can be recognized by
|
||||
// this function. Unfortunately, this function treats all foreign iterators
|
||||
// as InputIterators and thus can seriously hamper performance in the case
|
||||
// of large ranges of bidirectional_iterator_tag iterators.
|
||||
//template <typename InputIterator, typename Distance>
|
||||
//inline void
|
||||
//advance_impl(InputIterator& i, Distance n, ...)
|
||||
//{
|
||||
// while(n--)
|
||||
// ++i;
|
||||
//}
|
||||
|
||||
template <typename InputIterator, typename Distance>
|
||||
inline void
|
||||
advance(InputIterator& i, Distance n)
|
||||
{
|
||||
typedef typename eastl::iterator_traits<InputIterator>::iterator_category IC;
|
||||
|
||||
eastl::advance_impl(i, n, IC());
|
||||
}
|
||||
|
||||
|
||||
} // namespace eastl
|
||||
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#pragma warning(pop)
|
||||
#elif defined(__SNC__)
|
||||
#pragma control %pop diag
|
||||
#endif
|
||||
|
||||
|
||||
#endif // Header include guard
|
||||
|
||||
|
||||
|
||||
|
||||
|
1863
lib/eastl/include/EASTL/list.h
Normal file
1863
lib/eastl/include/EASTL/list.h
Normal file
File diff suppressed because it is too large
Load diff
520
lib/eastl/include/EASTL/map.h
Normal file
520
lib/eastl/include/EASTL/map.h
Normal file
|
@ -0,0 +1,520 @@
|
|||
/*
|
||||
Copyright (C) 2009-2010 Electronic Arts, Inc. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
3. Neither the name of Electronic Arts, Inc. ("EA") nor the names of
|
||||
its contributors may be used to endorse or promote products derived
|
||||
from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY ELECTRONIC ARTS AND ITS CONTRIBUTORS "AS IS" AND ANY
|
||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL ELECTRONIC ARTS OR ITS CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// EASTL/map.h
|
||||
//
|
||||
// Copyright (c) 2005, Electronic Arts. All rights reserved.
|
||||
// Written by Paul Pedriana.
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
#ifndef EASTL_MAP_H
|
||||
#define EASTL_MAP_H
|
||||
|
||||
|
||||
|
||||
#include <EASTL/internal/config.h>
|
||||
#include <EASTL/internal/red_black_tree.h>
|
||||
#include <EASTL/functional.h>
|
||||
#include <EASTL/utility.h>
|
||||
|
||||
|
||||
|
||||
namespace eastl
|
||||
{
|
||||
|
||||
/// EASTL_MAP_DEFAULT_NAME
|
||||
///
|
||||
/// Defines a default container name in the absence of a user-provided name.
|
||||
///
|
||||
#ifndef EASTL_MAP_DEFAULT_NAME
|
||||
#define EASTL_MAP_DEFAULT_NAME EASTL_DEFAULT_NAME_PREFIX " map" // Unless the user overrides something, this is "EASTL map".
|
||||
#endif
|
||||
|
||||
|
||||
/// EASTL_MULTIMAP_DEFAULT_NAME
|
||||
///
|
||||
/// Defines a default container name in the absence of a user-provided name.
|
||||
///
|
||||
#ifndef EASTL_MULTIMAP_DEFAULT_NAME
|
||||
#define EASTL_MULTIMAP_DEFAULT_NAME EASTL_DEFAULT_NAME_PREFIX " multimap" // Unless the user overrides something, this is "EASTL multimap".
|
||||
#endif
|
||||
|
||||
|
||||
/// EASTL_MAP_DEFAULT_ALLOCATOR
|
||||
///
|
||||
#ifndef EASTL_MAP_DEFAULT_ALLOCATOR
|
||||
#define EASTL_MAP_DEFAULT_ALLOCATOR allocator_type(EASTL_MAP_DEFAULT_NAME)
|
||||
#endif
|
||||
|
||||
/// EASTL_MULTIMAP_DEFAULT_ALLOCATOR
|
||||
///
|
||||
#ifndef EASTL_MULTIMAP_DEFAULT_ALLOCATOR
|
||||
#define EASTL_MULTIMAP_DEFAULT_ALLOCATOR allocator_type(EASTL_MULTIMAP_DEFAULT_NAME)
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/// map
|
||||
///
|
||||
/// Implements a canonical map.
|
||||
///
|
||||
/// The large majority of the implementation of this class is found in the rbtree
|
||||
/// base class. We control the behaviour of rbtree via template parameters.
|
||||
///
|
||||
/// Pool allocation
|
||||
/// If you want to make a custom memory pool for a map container, your pool
|
||||
/// needs to contain items of type map::node_type. So if you have a memory
|
||||
/// pool that has a constructor that takes the size of pool items and the
|
||||
/// count of pool items, you would do this (assuming that MemoryPool implements
|
||||
/// the Allocator interface):
|
||||
/// typedef map<Widget, int, less<Widget>, MemoryPool> WidgetMap; // Delare your WidgetMap type.
|
||||
/// MemoryPool myPool(sizeof(WidgetMap::node_type), 100); // Make a pool of 100 Widget nodes.
|
||||
/// WidgetMap myMap(&myPool); // Create a map that uses the pool.
|
||||
///
|
||||
template <typename Key, typename T, typename Compare = eastl::less<Key>, typename Allocator = EASTLAllocatorType>
|
||||
class map
|
||||
: public rbtree<Key, eastl::pair<const Key, T>, Compare, Allocator, eastl::use_first<eastl::pair<const Key, T> >, true, true>
|
||||
{
|
||||
public:
|
||||
typedef rbtree<Key, eastl::pair<const Key, T>, Compare, Allocator,
|
||||
eastl::use_first<eastl::pair<const Key, T> >, true, true> base_type;
|
||||
typedef map<Key, T, Compare, Allocator> this_type;
|
||||
typedef typename base_type::size_type size_type;
|
||||
typedef typename base_type::key_type key_type;
|
||||
typedef T mapped_type;
|
||||
typedef typename base_type::value_type value_type;
|
||||
typedef typename base_type::node_type node_type;
|
||||
typedef typename base_type::iterator iterator;
|
||||
typedef typename base_type::const_iterator const_iterator;
|
||||
typedef typename base_type::allocator_type allocator_type;
|
||||
typedef typename base_type::insert_return_type insert_return_type;
|
||||
typedef typename base_type::extract_key extract_key;
|
||||
// Other types are inherited from the base class.
|
||||
|
||||
using base_type::begin;
|
||||
using base_type::end;
|
||||
using base_type::find;
|
||||
using base_type::lower_bound;
|
||||
using base_type::upper_bound;
|
||||
using base_type::mCompare;
|
||||
|
||||
#if !defined(__GNUC__) || (__GNUC__ >= 3) // GCC 2.x has a bug which we work around.
|
||||
using base_type::insert;
|
||||
using base_type::erase;
|
||||
#endif
|
||||
|
||||
public:
|
||||
map(const allocator_type& allocator = EASTL_MAP_DEFAULT_ALLOCATOR);
|
||||
map(const Compare& compare, const allocator_type& allocator = EASTL_MAP_DEFAULT_ALLOCATOR);
|
||||
map(const this_type& x);
|
||||
|
||||
template <typename Iterator>
|
||||
map(Iterator itBegin, Iterator itEnd); // allocator arg removed because VC7.1 fails on the default arg. To consider: Make a second version of this function without a default arg.
|
||||
|
||||
public:
|
||||
/// This is an extension to the C++ standard. We insert a default-constructed
|
||||
/// element with the given key. The reason for this is that we can avoid the
|
||||
/// potentially expensive operation of creating and/or copying a mapped_type
|
||||
/// object on the stack.
|
||||
insert_return_type insert(const Key& key);
|
||||
|
||||
#if defined(__GNUC__) && (__GNUC__ < 3) // If using old GCC (GCC 2.x has a bug which we work around)
|
||||
template <typename InputIterator>
|
||||
void insert(InputIterator first, InputIterator last) { return base_type::insert(first, last); }
|
||||
insert_return_type insert(const value_type& value) { return base_type::insert(value); }
|
||||
iterator insert(iterator position, const value_type& value) { return base_type::insert(position, value); }
|
||||
iterator erase(iterator position) { return base_type::erase(position); }
|
||||
iterator erase(iterator first, iterator last) { return base_type::erase(first, last); }
|
||||
#endif
|
||||
|
||||
size_type erase(const Key& key);
|
||||
size_type count(const Key& key) const;
|
||||
|
||||
eastl::pair<iterator, iterator> equal_range(const Key& key);
|
||||
eastl::pair<const_iterator, const_iterator> equal_range(const Key& key) const;
|
||||
|
||||
T& operator[](const Key& key); // Of map, multimap, set, and multimap, only map has operator[].
|
||||
|
||||
}; // map
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/// multimap
|
||||
///
|
||||
/// Implements a canonical multimap.
|
||||
///
|
||||
/// The large majority of the implementation of this class is found in the rbtree
|
||||
/// base class. We control the behaviour of rbtree via template parameters.
|
||||
///
|
||||
/// Pool allocation
|
||||
/// If you want to make a custom memory pool for a multimap container, your pool
|
||||
/// needs to contain items of type multimap::node_type. So if you have a memory
|
||||
/// pool that has a constructor that takes the size of pool items and the
|
||||
/// count of pool items, you would do this (assuming that MemoryPool implements
|
||||
/// the Allocator interface):
|
||||
/// typedef multimap<Widget, int, less<Widget>, MemoryPool> WidgetMap; // Delare your WidgetMap type.
|
||||
/// MemoryPool myPool(sizeof(WidgetMap::node_type), 100); // Make a pool of 100 Widget nodes.
|
||||
/// WidgetMap myMap(&myPool); // Create a map that uses the pool.
|
||||
///
|
||||
template <typename Key, typename T, typename Compare = eastl::less<Key>, typename Allocator = EASTLAllocatorType>
|
||||
class multimap
|
||||
: public rbtree<Key, eastl::pair<const Key, T>, Compare, Allocator, eastl::use_first<eastl::pair<const Key, T> >, true, false>
|
||||
{
|
||||
public:
|
||||
typedef rbtree<Key, eastl::pair<const Key, T>, Compare, Allocator,
|
||||
eastl::use_first<eastl::pair<const Key, T> >, true, false> base_type;
|
||||
typedef multimap<Key, T, Compare, Allocator> this_type;
|
||||
typedef typename base_type::size_type size_type;
|
||||
typedef typename base_type::key_type key_type;
|
||||
typedef T mapped_type;
|
||||
typedef typename base_type::value_type value_type;
|
||||
typedef typename base_type::node_type node_type;
|
||||
typedef typename base_type::iterator iterator;
|
||||
typedef typename base_type::const_iterator const_iterator;
|
||||
typedef typename base_type::allocator_type allocator_type;
|
||||
typedef typename base_type::insert_return_type insert_return_type;
|
||||
typedef typename base_type::extract_key extract_key;
|
||||
// Other types are inherited from the base class.
|
||||
|
||||
using base_type::begin;
|
||||
using base_type::end;
|
||||
using base_type::find;
|
||||
using base_type::lower_bound;
|
||||
using base_type::upper_bound;
|
||||
using base_type::mCompare;
|
||||
|
||||
#if !defined(__GNUC__) || (__GNUC__ >= 3) // GCC 2.x has a bug which we work around.
|
||||
using base_type::insert;
|
||||
using base_type::erase;
|
||||
#endif
|
||||
|
||||
public:
|
||||
multimap(const allocator_type& allocator = EASTL_MULTIMAP_DEFAULT_ALLOCATOR);
|
||||
multimap(const Compare& compare, const allocator_type& allocator = EASTL_MULTIMAP_DEFAULT_ALLOCATOR);
|
||||
multimap(const this_type& x);
|
||||
|
||||
template <typename Iterator>
|
||||
multimap(Iterator itBegin, Iterator itEnd); // allocator arg removed because VC7.1 fails on the default arg. To consider: Make a second version of this function without a default arg.
|
||||
|
||||
public:
|
||||
/// This is an extension to the C++ standard. We insert a default-constructed
|
||||
/// element with the given key. The reason for this is that we can avoid the
|
||||
/// potentially expensive operation of creating and/or copying a mapped_type
|
||||
/// object on the stack.
|
||||
insert_return_type insert(const Key& key);
|
||||
|
||||
#if defined(__GNUC__) && (__GNUC__ < 3) // If using old GCC (GCC 2.x has a bug which we work around)
|
||||
template <typename InputIterator>
|
||||
void insert(InputIterator first, InputIterator last) { return base_type::insert(first, last); }
|
||||
insert_return_type insert(const value_type& value) { return base_type::insert(value); }
|
||||
iterator insert(iterator position, const value_type& value) { return base_type::insert(position, value); }
|
||||
iterator erase(iterator position) { return base_type::erase(position); }
|
||||
iterator erase(iterator first, iterator last) { return base_type::erase(first, last); }
|
||||
#endif
|
||||
|
||||
size_type erase(const Key& key);
|
||||
size_type count(const Key& key) const;
|
||||
|
||||
eastl::pair<iterator, iterator> equal_range(const Key& key);
|
||||
eastl::pair<const_iterator, const_iterator> equal_range(const Key& key) const;
|
||||
|
||||
/// equal_range_small
|
||||
/// This is a special version of equal_range which is optimized for the
|
||||
/// case of there being few or no duplicated keys in the tree.
|
||||
eastl::pair<iterator, iterator> equal_range_small(const Key& key);
|
||||
eastl::pair<const_iterator, const_iterator> equal_range_small(const Key& key) const;
|
||||
|
||||
}; // multimap
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// map
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <typename Key, typename T, typename Compare, typename Allocator>
|
||||
inline map<Key, T, Compare, Allocator>::map(const allocator_type& allocator)
|
||||
: base_type(allocator) { }
|
||||
|
||||
|
||||
template <typename Key, typename T, typename Compare, typename Allocator>
|
||||
inline map<Key, T, Compare, Allocator>::map(const Compare& compare, const allocator_type& allocator)
|
||||
: base_type(compare, allocator) { }
|
||||
|
||||
|
||||
template <typename Key, typename T, typename Compare, typename Allocator>
|
||||
inline map<Key, T, Compare, Allocator>::map(const this_type& x)
|
||||
: base_type(x) { }
|
||||
|
||||
|
||||
template <typename Key, typename T, typename Compare, typename Allocator>
|
||||
template <typename Iterator>
|
||||
inline map<Key, T, Compare, Allocator>::map(Iterator itBegin, Iterator itEnd)
|
||||
: base_type(itBegin, itEnd, Compare(), EASTL_MAP_DEFAULT_ALLOCATOR) { }
|
||||
|
||||
|
||||
template <typename Key, typename T, typename Compare, typename Allocator>
|
||||
inline typename map<Key, T, Compare, Allocator>::insert_return_type
|
||||
map<Key, T, Compare, Allocator>::insert(const Key& key)
|
||||
{
|
||||
return base_type::DoInsertKey(key, true_type());
|
||||
}
|
||||
|
||||
|
||||
template <typename Key, typename T, typename Compare, typename Allocator>
|
||||
inline typename map<Key, T, Compare, Allocator>::size_type
|
||||
map<Key, T, Compare, Allocator>::erase(const Key& key)
|
||||
{
|
||||
const iterator it(find(key));
|
||||
|
||||
if(it != end()) // If it exists...
|
||||
{
|
||||
base_type::erase(it);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
template <typename Key, typename T, typename Compare, typename Allocator>
|
||||
inline typename map<Key, T, Compare, Allocator>::size_type
|
||||
map<Key, T, Compare, Allocator>::count(const Key& key) const
|
||||
{
|
||||
const const_iterator it(find(key));
|
||||
return (it != end()) ? 1 : 0;
|
||||
}
|
||||
|
||||
|
||||
template <typename Key, typename T, typename Compare, typename Allocator>
|
||||
inline eastl::pair<typename map<Key, T, Compare, Allocator>::iterator,
|
||||
typename map<Key, T, Compare, Allocator>::iterator>
|
||||
map<Key, T, Compare, Allocator>::equal_range(const Key& key)
|
||||
{
|
||||
// The resulting range will either be empty or have one element,
|
||||
// so instead of doing two tree searches (one for lower_bound and
|
||||
// one for upper_bound), we do just lower_bound and see if the
|
||||
// result is a range of size zero or one.
|
||||
const iterator itLower(lower_bound(key));
|
||||
|
||||
if((itLower == end()) || mCompare(key, itLower.mpNode->mValue.first)) // If at the end or if (key is < itLower)...
|
||||
return eastl::pair<iterator, iterator>(itLower, itLower);
|
||||
|
||||
iterator itUpper(itLower);
|
||||
return eastl::pair<iterator, iterator>(itLower, ++itUpper);
|
||||
}
|
||||
|
||||
|
||||
template <typename Key, typename T, typename Compare, typename Allocator>
|
||||
inline eastl::pair<typename map<Key, T, Compare, Allocator>::const_iterator,
|
||||
typename map<Key, T, Compare, Allocator>::const_iterator>
|
||||
map<Key, T, Compare, Allocator>::equal_range(const Key& key) const
|
||||
{
|
||||
// See equal_range above for comments.
|
||||
const const_iterator itLower(lower_bound(key));
|
||||
|
||||
if((itLower == end()) || mCompare(key, itLower.mpNode->mValue.first)) // If at the end or if (key is < itLower)...
|
||||
return eastl::pair<const_iterator, const_iterator>(itLower, itLower);
|
||||
|
||||
const_iterator itUpper(itLower);
|
||||
return eastl::pair<const_iterator, const_iterator>(itLower, ++itUpper);
|
||||
}
|
||||
|
||||
|
||||
template <typename Key, typename T, typename Compare, typename Allocator>
|
||||
inline T& map<Key, T, Compare, Allocator>::operator[](const Key& key)
|
||||
{
|
||||
iterator itLower(lower_bound(key)); // itLower->first is >= key.
|
||||
|
||||
if((itLower == end()) || mCompare(key, (*itLower).first))
|
||||
{
|
||||
itLower = base_type::insert(itLower, value_type(key, T()));
|
||||
|
||||
// To do: Convert this to use the more efficient:
|
||||
// itLower = DoInsertKey(itLower, key, true_type());
|
||||
// when we gain confidence in that function.
|
||||
}
|
||||
|
||||
return (*itLower).second;
|
||||
|
||||
// Reference implementation of this function, which may not be as fast:
|
||||
//iterator it(base_type::insert(eastl::pair<iterator, iterator>(key, T())).first);
|
||||
//return it->second;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// multimap
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <typename Key, typename T, typename Compare, typename Allocator>
|
||||
inline multimap<Key, T, Compare, Allocator>::multimap(const allocator_type& allocator)
|
||||
: base_type(allocator)
|
||||
{
|
||||
// Empty
|
||||
}
|
||||
|
||||
|
||||
template <typename Key, typename T, typename Compare, typename Allocator>
|
||||
inline multimap<Key, T, Compare, Allocator>::multimap(const Compare& compare, const allocator_type& allocator)
|
||||
: base_type(compare, allocator)
|
||||
{
|
||||
// Empty
|
||||
}
|
||||
|
||||
|
||||
template <typename Key, typename T, typename Compare, typename Allocator>
|
||||
inline multimap<Key, T, Compare, Allocator>::multimap(const this_type& x)
|
||||
: base_type(x)
|
||||
{
|
||||
// Empty
|
||||
}
|
||||
|
||||
|
||||
template <typename Key, typename T, typename Compare, typename Allocator>
|
||||
template <typename Iterator>
|
||||
inline multimap<Key, T, Compare, Allocator>::multimap(Iterator itBegin, Iterator itEnd)
|
||||
: base_type(itBegin, itEnd, Compare(), EASTL_MULTIMAP_DEFAULT_ALLOCATOR)
|
||||
{
|
||||
// Empty
|
||||
}
|
||||
|
||||
|
||||
template <typename Key, typename T, typename Compare, typename Allocator>
|
||||
inline typename multimap<Key, T, Compare, Allocator>::insert_return_type
|
||||
multimap<Key, T, Compare, Allocator>::insert(const Key& key)
|
||||
{
|
||||
return base_type::DoInsertKey(key, false_type());
|
||||
}
|
||||
|
||||
|
||||
template <typename Key, typename T, typename Compare, typename Allocator>
|
||||
inline typename multimap<Key, T, Compare, Allocator>::size_type
|
||||
multimap<Key, T, Compare, Allocator>::erase(const Key& key)
|
||||
{
|
||||
const eastl::pair<iterator, iterator> range(equal_range(key));
|
||||
const size_type n = (size_type)eastl::distance(range.first, range.second);
|
||||
base_type::erase(range.first, range.second);
|
||||
return n;
|
||||
}
|
||||
|
||||
|
||||
template <typename Key, typename T, typename Compare, typename Allocator>
|
||||
inline typename multimap<Key, T, Compare, Allocator>::size_type
|
||||
multimap<Key, T, Compare, Allocator>::count(const Key& key) const
|
||||
{
|
||||
const eastl::pair<const_iterator, const_iterator> range(equal_range(key));
|
||||
return (size_type)eastl::distance(range.first, range.second);
|
||||
}
|
||||
|
||||
|
||||
template <typename Key, typename T, typename Compare, typename Allocator>
|
||||
inline eastl::pair<typename multimap<Key, T, Compare, Allocator>::iterator,
|
||||
typename multimap<Key, T, Compare, Allocator>::iterator>
|
||||
multimap<Key, T, Compare, Allocator>::equal_range(const Key& key)
|
||||
{
|
||||
// There are multiple ways to implement equal_range. The implementation mentioned
|
||||
// in the C++ standard and which is used by most (all?) commercial STL implementations
|
||||
// is this:
|
||||
// return eastl::pair<iterator, iterator>(lower_bound(key), upper_bound(key));
|
||||
//
|
||||
// This does two tree searches -- one for the lower bound and one for the
|
||||
// upper bound. This works well for the case whereby you have a large container
|
||||
// and there are lots of duplicated values. We provide an alternative version
|
||||
// of equal_range called equal_range_small for cases where the user is confident
|
||||
// that the number of duplicated items is only a few.
|
||||
|
||||
return eastl::pair<iterator, iterator>(lower_bound(key), upper_bound(key));
|
||||
}
|
||||
|
||||
|
||||
template <typename Key, typename T, typename Compare, typename Allocator>
|
||||
inline eastl::pair<typename multimap<Key, T, Compare, Allocator>::const_iterator,
|
||||
typename multimap<Key, T, Compare, Allocator>::const_iterator>
|
||||
multimap<Key, T, Compare, Allocator>::equal_range(const Key& key) const
|
||||
{
|
||||
// See comments above in the non-const version of equal_range.
|
||||
return eastl::pair<const_iterator, const_iterator>(lower_bound(key), upper_bound(key));
|
||||
}
|
||||
|
||||
|
||||
template <typename Key, typename T, typename Compare, typename Allocator>
|
||||
inline eastl::pair<typename multimap<Key, T, Compare, Allocator>::iterator,
|
||||
typename multimap<Key, T, Compare, Allocator>::iterator>
|
||||
multimap<Key, T, Compare, Allocator>::equal_range_small(const Key& key)
|
||||
{
|
||||
// We provide alternative version of equal_range here which works faster
|
||||
// for the case where there are at most small number of potential duplicated keys.
|
||||
const iterator itLower(lower_bound(key));
|
||||
iterator itUpper(itLower);
|
||||
|
||||
while((itUpper != end()) && !mCompare(key, itUpper.mpNode->mValue.first))
|
||||
++itUpper;
|
||||
|
||||
return eastl::pair<iterator, iterator>(itLower, itUpper);
|
||||
}
|
||||
|
||||
|
||||
template <typename Key, typename T, typename Compare, typename Allocator>
|
||||
inline eastl::pair<typename multimap<Key, T, Compare, Allocator>::const_iterator,
|
||||
typename multimap<Key, T, Compare, Allocator>::const_iterator>
|
||||
multimap<Key, T, Compare, Allocator>::equal_range_small(const Key& key) const
|
||||
{
|
||||
// We provide alternative version of equal_range here which works faster
|
||||
// for the case where there are at most small number of potential duplicated keys.
|
||||
const const_iterator itLower(lower_bound(key));
|
||||
const_iterator itUpper(itLower);
|
||||
|
||||
while((itUpper != end()) && !mCompare(key, itUpper.mpNode->mValue.first))
|
||||
++itUpper;
|
||||
|
||||
return eastl::pair<const_iterator, const_iterator>(itLower, itUpper);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
} // namespace eastl
|
||||
|
||||
|
||||
#endif // Header include guard
|
||||
|
||||
|
||||
|
||||
|
698
lib/eastl/include/EASTL/memory.h
Normal file
698
lib/eastl/include/EASTL/memory.h
Normal file
|
@ -0,0 +1,698 @@
|
|||
/*
|
||||
Copyright (C) 2009-2010 Electronic Arts, Inc. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
3. Neither the name of Electronic Arts, Inc. ("EA") nor the names of
|
||||
its contributors may be used to endorse or promote products derived
|
||||
from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY ELECTRONIC ARTS AND ITS CONTRIBUTORS "AS IS" AND ANY
|
||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL ELECTRONIC ARTS OR ITS CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// EASTL/memory.h
|
||||
//
|
||||
// Copyright (c) 2005, Electronic Arts. All rights reserved.
|
||||
// Written and maintained by Paul Pedriana.
|
||||
// The uninitialized_move function was written by Ryan Ingram.
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// This file implements the following functions from the C++ standard that
|
||||
// are found in the <memory> header:
|
||||
//
|
||||
// Temporary memory:
|
||||
// get_temporary_buffer
|
||||
// return_temporary_buffer
|
||||
//
|
||||
// Uninitialized operations:
|
||||
// These are the same as the copy, fill, and fill_n algorithms, except that
|
||||
// they *construct* the destination with the source values rather than assign
|
||||
// the destination with the source values.
|
||||
//
|
||||
// uninitialized_copy
|
||||
// uninitialized_fill
|
||||
// uninitialized_fill_n
|
||||
// uninitialized_move - Extention to standard functionality.
|
||||
// uninitialized_copy_ptr - Extention to standard functionality.
|
||||
// uninitialized_fill_ptr - Extention to standard functionality.
|
||||
// uninitialized_fill_n_ptr - Extention to standard functionality.
|
||||
// uninitialized_copy_fill - Extention to standard functionality.
|
||||
// uninitialized_fill_copy - Extention to standard functionality.
|
||||
// uninitialized_copy_copy - Extention to standard functionality.
|
||||
//
|
||||
// In-place destructor helpers:
|
||||
// destruct(T*)
|
||||
// destruct(first, last)
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
#ifndef EASTL_MEMORY_H
|
||||
#define EASTL_MEMORY_H
|
||||
|
||||
|
||||
#include <EASTL/internal/config.h>
|
||||
#include <EASTL/internal/generic_iterator.h>
|
||||
#include <EASTL/type_traits.h>
|
||||
#include <EASTL/algorithm.h>
|
||||
#include <EASTL/allocator.h>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(push, 0)
|
||||
#endif
|
||||
#include <stdlib.h>
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable: 4530) // C++ exception handler used, but unwind semantics are not enabled. Specify /EHsc
|
||||
#endif
|
||||
|
||||
|
||||
namespace eastl
|
||||
{
|
||||
|
||||
/// EASTL_TEMP_DEFAULT_NAME
|
||||
///
|
||||
/// Defines a default container name in the absence of a user-provided name.
|
||||
///
|
||||
#ifndef EASTL_TEMP_DEFAULT_NAME
|
||||
#define EASTL_TEMP_DEFAULT_NAME EASTL_DEFAULT_NAME_PREFIX " temp" // Unless the user overrides something, this is "EASTL temp".
|
||||
#endif
|
||||
|
||||
|
||||
/// get_temporary_buffer
|
||||
///
|
||||
/// From the C++ standard, section 20.4.3:
|
||||
/// 1 Effects: Obtains a pointer to storage sufficient to store up to n adjacent T objects.
|
||||
/// 2 Returns: A pair containing the buffer's address and capacity (in the units of sizeof(T)),
|
||||
/// or a pair of 0 values if no storage can be obtained.
|
||||
///
|
||||
/// Note: The return value is space to hold T elements, but no T elements are constructed.
|
||||
///
|
||||
/// Our implementation here differs slightly in that we have alignment, alignmentOffset, and pName arguments.
|
||||
/// Note that you can use the EASTL_NAME_VAL macro to make names go away in release builds.
|
||||
///
|
||||
/// Example usage:
|
||||
/// pair<int*, ptrdiff_t> pr = get_temporary_buffer<int>(100, 0, 0, EASTL_NAME_VAL("Temp int array"));
|
||||
/// memset(pr.first, 0, 100 * sizeof(int));
|
||||
/// return_temporary_buffer(pr.first);
|
||||
///
|
||||
template <typename T>
|
||||
pair<T*, ptrdiff_t> get_temporary_buffer(ptrdiff_t n, size_t alignment = 0, size_t alignmentOffset = 0, const char* pName = EASTL_TEMP_DEFAULT_NAME)
|
||||
{
|
||||
EASTLAllocatorType allocator(*EASTLAllocatorDefault(), pName);
|
||||
return eastl::pair<T*, ptrdiff_t>(static_cast<T*>(EASTLAllocAligned(allocator, n * sizeof(T), alignment, alignmentOffset)), n);
|
||||
}
|
||||
|
||||
|
||||
/// return_temporary_buffer
|
||||
///
|
||||
/// From the C++ standard, section 20.4.3:
|
||||
/// 3 Effects: Deallocates the buffer to which p points.
|
||||
/// 4 Requires: The buffer shall have been previously allocated by get_temporary_buffer.
|
||||
///
|
||||
/// Note: This function merely frees space and does not destruct any T elements.
|
||||
///
|
||||
/// Example usage:
|
||||
/// pair<int*, ptrdiff_t> pr = get_temporary_buffer<int>(300);
|
||||
/// memset(pr.first, 0, 300 * sizeof(int));
|
||||
/// return_temporary_buffer(pr.first, pr.second);
|
||||
///
|
||||
template <typename T>
|
||||
void return_temporary_buffer(T* p, ptrdiff_t n = 0)
|
||||
{
|
||||
EASTLAllocatorType& allocator(*EASTLAllocatorDefault());
|
||||
EASTLFree(allocator, p, n * sizeof(T));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// uninitialized_move
|
||||
///
|
||||
/// uninitialized_move takes a constructed sequence of objects and an
|
||||
/// uninitialized destination buffer. In the case of any exception thrown
|
||||
/// while moving the objects, any newly constructed objects are guaranteed
|
||||
/// to be destructed and the input left fully constructed.
|
||||
///
|
||||
/// In the case where you need to do multiple moves atomically, split the
|
||||
/// calls into uninitialized_move_start/abort/commit.
|
||||
///
|
||||
/// uninitialized_move_start can possibly throw an exception. If it does,
|
||||
/// you don't need to do anything. However, if it returns without throwing
|
||||
/// an exception you need to guarantee that either uninitialize_move_abort
|
||||
/// or uninitialized_move_commit is called.
|
||||
///
|
||||
/// Both uninitialize_move_abort and uninitialize_move_commit are
|
||||
/// guaranteed to not throw C++ exceptions.
|
||||
|
||||
template <bool hasTrivialMove, typename iteratorTag>
|
||||
struct uninitialized_move_impl
|
||||
{
|
||||
template <typename ForwardIterator, typename ForwardIteratorDest>
|
||||
static ForwardIteratorDest do_move_start(ForwardIterator first, ForwardIterator last, ForwardIteratorDest dest)
|
||||
{
|
||||
typedef typename eastl::iterator_traits<ForwardIterator>::value_type value_type;
|
||||
|
||||
#if EASTL_EXCEPTIONS_ENABLED
|
||||
ForwardIteratorDest origDest(dest);
|
||||
try
|
||||
{
|
||||
for(; first != last; ++first, ++dest)
|
||||
::new(&*dest) value_type(*first);
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
for(; origDest < dest; ++origDest)
|
||||
origDest->~value_type();
|
||||
throw;
|
||||
}
|
||||
#else
|
||||
for(; first != last; ++first, ++dest)
|
||||
::new(&*dest) value_type(*first);
|
||||
#endif
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
template <typename ForwardIterator, typename ForwardIteratorDest>
|
||||
static ForwardIteratorDest do_move_commit(ForwardIterator first, ForwardIterator last, ForwardIteratorDest dest) //throw()
|
||||
{
|
||||
typedef typename eastl::iterator_traits<ForwardIterator>::value_type value_type;
|
||||
for(; first != last; ++first, ++dest)
|
||||
first->~value_type();
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
template <typename ForwardIterator, typename ForwardIteratorDest>
|
||||
static ForwardIteratorDest do_move_abort(ForwardIterator first, ForwardIterator last, ForwardIteratorDest dest) //throw()
|
||||
{
|
||||
typedef typename eastl::iterator_traits<ForwardIterator>::value_type value_type;
|
||||
for(; first != last; ++first, ++dest)
|
||||
dest->~value_type();
|
||||
return dest;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct uninitialized_move_impl<true, EASTL_ITC_NS::random_access_iterator_tag>
|
||||
{
|
||||
template <typename T>
|
||||
static T* do_move_start(T* first, T* last, T* dest)
|
||||
{
|
||||
return (T*)memcpy(dest, first, (size_t)((uintptr_t)last - (uintptr_t)first)) + (last - first);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static T* do_move_commit(T* first, T* last, T* dest)
|
||||
{
|
||||
return dest + (last - first);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static T* do_move_abort(T* first, T* last, T* dest)
|
||||
{
|
||||
return dest + (last - first);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/// uninitialized_move_start, uninitialized_move_commit, uninitialized_move_abort
|
||||
///
|
||||
/// After calling uninitialized_move_start, if it doesn't throw an exception,
|
||||
/// both the source and destination iterators point to undefined data. If it
|
||||
/// does throw an exception, the destination remains uninitialized and the source
|
||||
/// is as it was before.
|
||||
///
|
||||
/// In order to make the iterators valid again you need to call either uninitialized_move_abort
|
||||
/// or uninitialized_move_commit. The abort call makes the original source
|
||||
/// iterator valid again, and commit makes the destination valid. Both abort
|
||||
/// and commit are guaranteed to not throw C++ exceptions.
|
||||
///
|
||||
/// Example usage:
|
||||
/// iterator dest2 = uninitialized_move_start(first, last, dest);
|
||||
/// try {
|
||||
/// // some code here that might throw an exception
|
||||
/// }
|
||||
/// catch(...)
|
||||
/// {
|
||||
/// uninitialized_move_abort(first, last, dest);
|
||||
/// throw;
|
||||
/// }
|
||||
/// uninitialized_move_commit(first, last, dest);
|
||||
///
|
||||
template <typename ForwardIterator, typename ForwardIteratorDest>
|
||||
inline ForwardIteratorDest uninitialized_move_start(ForwardIterator first, ForwardIterator last, ForwardIteratorDest dest)
|
||||
{
|
||||
typedef typename eastl::iterator_traits<ForwardIterator>::iterator_category IC;
|
||||
typedef typename eastl::iterator_traits<ForwardIterator>::value_type value_type_input;
|
||||
typedef typename eastl::iterator_traits<ForwardIteratorDest>::value_type value_type_output;
|
||||
|
||||
const bool bHasTrivialMove = type_and<has_trivial_relocate<value_type_input>::value,
|
||||
is_pointer<ForwardIterator>::value,
|
||||
is_pointer<ForwardIteratorDest>::value,
|
||||
is_same<value_type_input, value_type_output>::value>::value;
|
||||
|
||||
return eastl::uninitialized_move_impl<bHasTrivialMove, IC>::do_move_start(first, last, dest);
|
||||
}
|
||||
|
||||
template <typename ForwardIterator, typename ForwardIteratorDest>
|
||||
inline ForwardIteratorDest uninitialized_move_commit(ForwardIterator first, ForwardIterator last, ForwardIteratorDest dest)
|
||||
{
|
||||
typedef typename eastl::iterator_traits<ForwardIterator>::iterator_category IC;
|
||||
typedef typename eastl::iterator_traits<ForwardIterator>::value_type value_type_input;
|
||||
typedef typename eastl::iterator_traits<ForwardIteratorDest>::value_type value_type_output;
|
||||
|
||||
const bool bHasTrivialMove = type_and<has_trivial_relocate<value_type_input>::value,
|
||||
is_pointer<ForwardIterator>::value,
|
||||
is_pointer<ForwardIteratorDest>::value,
|
||||
is_same<value_type_input, value_type_output>::value>::value;
|
||||
|
||||
return eastl::uninitialized_move_impl<bHasTrivialMove, IC>::do_move_commit(first, last, dest);
|
||||
}
|
||||
|
||||
template <typename ForwardIterator, typename ForwardIteratorDest>
|
||||
inline ForwardIteratorDest uninitialized_move_abort(ForwardIterator first, ForwardIterator last, ForwardIteratorDest dest)
|
||||
{
|
||||
typedef typename eastl::iterator_traits<ForwardIterator>::iterator_category IC;
|
||||
typedef typename eastl::iterator_traits<ForwardIterator>::value_type value_type_input;
|
||||
typedef typename eastl::iterator_traits<ForwardIteratorDest>::value_type value_type_output;
|
||||
|
||||
const bool bHasTrivialMove = type_and<has_trivial_relocate<value_type_input>::value,
|
||||
is_pointer<ForwardIterator>::value,
|
||||
is_pointer<ForwardIteratorDest>::value,
|
||||
is_same<value_type_input, value_type_output>::value>::value;
|
||||
|
||||
return eastl::uninitialized_move_impl<bHasTrivialMove, IC>::do_move_abort(first, last, dest);
|
||||
}
|
||||
|
||||
/// uninitialized_move
|
||||
///
|
||||
/// uninitialized_move takes a constructed sequence of objects and an
|
||||
/// uninitialized destination buffer. In the case of any exception thrown
|
||||
/// while moving the objects, any newly constructed objects are guaranteed
|
||||
/// to be destructed and the input left as it was before.
|
||||
///
|
||||
template <typename ForwardIterator, typename ForwardIteratorDest>
|
||||
inline ForwardIteratorDest uninitialized_move(ForwardIterator first, ForwardIterator last, ForwardIteratorDest dest)
|
||||
{
|
||||
ForwardIteratorDest result = uninitialized_move_start(first, last, dest);
|
||||
uninitialized_move_commit(first, last, dest);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// uninitialized_copy
|
||||
//
|
||||
template <typename InputIterator, typename ForwardIterator>
|
||||
inline ForwardIterator uninitialized_copy_impl(InputIterator first, InputIterator last, ForwardIterator dest, true_type)
|
||||
{
|
||||
return eastl::copy(first, last, dest); // The copy() in turn will use memcpy for POD types.
|
||||
}
|
||||
|
||||
template <typename InputIterator, typename ForwardIterator>
|
||||
inline ForwardIterator uninitialized_copy_impl(InputIterator first, InputIterator last, ForwardIterator dest, false_type)
|
||||
{
|
||||
typedef typename eastl::iterator_traits<ForwardIterator>::value_type value_type;
|
||||
ForwardIterator currentDest(dest);
|
||||
|
||||
#if EASTL_EXCEPTIONS_ENABLED
|
||||
try
|
||||
{
|
||||
for(; first != last; ++first, ++currentDest)
|
||||
::new(&*currentDest) value_type(*first);
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
for(; dest < currentDest; ++dest)
|
||||
dest->~value_type();
|
||||
throw;
|
||||
}
|
||||
#else
|
||||
for(; first != last; ++first, ++currentDest)
|
||||
::new(&*currentDest) value_type(*first);
|
||||
#endif
|
||||
|
||||
return currentDest;
|
||||
}
|
||||
|
||||
/// uninitialized_copy
|
||||
///
|
||||
/// Copies a source range to a destination, copy-constructing the destination with
|
||||
/// the source values (and not *assigning* the destination with the source values).
|
||||
/// Returns the end of the destination range (i.e. dest + (last - first)).
|
||||
///
|
||||
/// Declaration:
|
||||
/// template <typename InputIterator, typename ForwardIterator>
|
||||
/// ForwardIterator uninitialized_copy(InputIterator sourceFirst, InputIterator sourceLast, ForwardIterator destination);
|
||||
///
|
||||
/// Example usage:
|
||||
/// SomeClass* pArray = malloc(10 * sizeof(SomeClass));
|
||||
/// uninitialized_copy(pSourceDataBegin, pSourceDataBegin + 10, pArray);
|
||||
///
|
||||
template <typename InputIterator, typename ForwardIterator>
|
||||
inline ForwardIterator uninitialized_copy(InputIterator first, InputIterator last, ForwardIterator result)
|
||||
{
|
||||
typedef typename eastl::iterator_traits<ForwardIterator>::value_type value_type;
|
||||
|
||||
// Note: has_trivial_assign isn't actually the right thing to use here, as it
|
||||
// refers to assignment as opposed to construction. Bug Paul Pedriana if this
|
||||
// is becoming a problem. In the meantime, this code assumes that if has_trivial_assign
|
||||
// is present for a type, then has_trivial_copy is as well.
|
||||
return uninitialized_copy_impl(first, last, result, has_trivial_assign<value_type>());
|
||||
}
|
||||
|
||||
/// uninitialized_copy_ptr
|
||||
///
|
||||
/// This is a specialization of uninitialized_copy for iterators that are pointers.
|
||||
/// It exists so that we can declare a value_type for the iterator, which you
|
||||
/// can't do with a pointer by itself.
|
||||
///
|
||||
template <typename First, typename Last, typename Result>
|
||||
inline Result uninitialized_copy_ptr(First first, Last last, Result result)
|
||||
{
|
||||
typedef typename eastl::iterator_traits<generic_iterator<Result, void> >::value_type value_type;
|
||||
const generic_iterator<Result, void> i(uninitialized_copy_impl(generic_iterator<First, void>(first),
|
||||
generic_iterator<Last, void>(last),
|
||||
generic_iterator<Result, void>(result),
|
||||
has_trivial_assign<value_type>()));
|
||||
return i.base();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// uninitialized_fill
|
||||
//
|
||||
template <typename ForwardIterator, typename T>
|
||||
inline void uninitialized_fill_impl(ForwardIterator first, ForwardIterator last, const T& value, true_type)
|
||||
{
|
||||
eastl::fill(first, last, value);
|
||||
}
|
||||
|
||||
template <typename ForwardIterator, typename T>
|
||||
void uninitialized_fill_impl(ForwardIterator first, ForwardIterator last, const T& value, false_type)
|
||||
{
|
||||
typedef typename eastl::iterator_traits<ForwardIterator>::value_type value_type;
|
||||
ForwardIterator currentDest(first);
|
||||
|
||||
#if EASTL_EXCEPTIONS_ENABLED
|
||||
try
|
||||
{
|
||||
for(; currentDest != last; ++currentDest)
|
||||
::new(&*currentDest) value_type(value);
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
for(; first < currentDest; ++first)
|
||||
first->~value_type();
|
||||
throw;
|
||||
}
|
||||
#else
|
||||
for(; currentDest != last; ++currentDest)
|
||||
::new(&*currentDest) value_type(value);
|
||||
#endif
|
||||
}
|
||||
|
||||
/// uninitialized_fill
|
||||
///
|
||||
/// Copy-constructs the elements in the destination range with the given input value.
|
||||
/// Returns void. It wouldn't be useful to return the end of the destination range,
|
||||
/// as that is the same as the 'last' input parameter.
|
||||
///
|
||||
/// Declaration:
|
||||
/// template <typename ForwardIterator, typename T>
|
||||
/// void uninitialized_fill(ForwardIterator destinationFirst, ForwardIterator destinationLast, const T& value);
|
||||
///
|
||||
template <typename ForwardIterator, typename T>
|
||||
inline void uninitialized_fill(ForwardIterator first, ForwardIterator last, const T& value)
|
||||
{
|
||||
typedef typename eastl::iterator_traits<ForwardIterator>::value_type value_type;
|
||||
uninitialized_fill_impl(first, last, value, has_trivial_assign<value_type>());
|
||||
}
|
||||
|
||||
/// uninitialized_fill_ptr
|
||||
///
|
||||
/// This is a specialization of uninitialized_fill for iterators that are pointers.
|
||||
/// It exists so that we can declare a value_type for the iterator, which you
|
||||
/// can't do with a pointer by itself.
|
||||
///
|
||||
template <typename T>
|
||||
inline void uninitialized_fill_ptr(T* first, T* last, const T& value)
|
||||
{
|
||||
typedef typename eastl::iterator_traits<generic_iterator<T*, void> >::value_type value_type;
|
||||
uninitialized_fill_impl(generic_iterator<T*, void>(first), generic_iterator<T*, void>(last), value, has_trivial_assign<value_type>());
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// uninitialized_fill_n
|
||||
//
|
||||
template <typename ForwardIterator, typename Count, typename T>
|
||||
inline void uninitialized_fill_n_impl(ForwardIterator first, Count n, const T& value, true_type)
|
||||
{
|
||||
eastl::fill_n(first, n, value);
|
||||
}
|
||||
|
||||
template <typename ForwardIterator, typename Count, typename T>
|
||||
void uninitialized_fill_n_impl(ForwardIterator first, Count n, const T& value, false_type)
|
||||
{
|
||||
typedef typename eastl::iterator_traits<ForwardIterator>::value_type value_type;
|
||||
ForwardIterator currentDest(first);
|
||||
|
||||
#if EASTL_EXCEPTIONS_ENABLED
|
||||
try
|
||||
{
|
||||
for(; n > 0; --n, ++currentDest)
|
||||
::new(&*currentDest) value_type(value);
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
for(; first < currentDest; ++first)
|
||||
first->~value_type();
|
||||
throw;
|
||||
}
|
||||
#else
|
||||
for(; n > 0; --n, ++currentDest)
|
||||
::new(&*currentDest) value_type(value);
|
||||
#endif
|
||||
}
|
||||
|
||||
/// uninitialized_fill_n
|
||||
///
|
||||
/// Copy-constructs the range of [first, first + n) with the given input value.
|
||||
/// Returns void as per the C++ standard, though returning the end input iterator
|
||||
/// value may be of use.
|
||||
///
|
||||
/// Declaration:
|
||||
/// template <typename ForwardIterator, typename Count, typename T>
|
||||
/// void uninitialized_fill_n(ForwardIterator destination, Count n, const T& value);
|
||||
///
|
||||
template <typename ForwardIterator, typename Count, typename T>
|
||||
inline void uninitialized_fill_n(ForwardIterator first, Count n, const T& value)
|
||||
{
|
||||
typedef typename eastl::iterator_traits<ForwardIterator>::value_type value_type;
|
||||
uninitialized_fill_n_impl(first, n, value, has_trivial_assign<value_type>());
|
||||
}
|
||||
|
||||
/// uninitialized_fill_n_ptr
|
||||
///
|
||||
/// This is a specialization of uninitialized_fill_n for iterators that are pointers.
|
||||
/// It exists so that we can declare a value_type for the iterator, which you
|
||||
/// can't do with a pointer by itself.
|
||||
///
|
||||
template <typename T, typename Count>
|
||||
inline void uninitialized_fill_n_ptr(T* first, Count n, const T& value)
|
||||
{
|
||||
typedef typename eastl::iterator_traits<generic_iterator<T*, void> >::value_type value_type;
|
||||
uninitialized_fill_n_impl(generic_iterator<T*, void>(first), n, value, has_trivial_assign<value_type>());
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/// uninitialized_copy_fill
|
||||
///
|
||||
/// Copies [first1, last1) into [first2, first2 + (last1 - first1)) then
|
||||
/// fills [first2 + (last1 - first1), last2) with value.
|
||||
///
|
||||
template <typename InputIterator, typename ForwardIterator, typename T>
|
||||
inline void uninitialized_copy_fill(InputIterator first1, InputIterator last1,
|
||||
ForwardIterator first2, ForwardIterator last2, const T& value)
|
||||
{
|
||||
const ForwardIterator mid(eastl::uninitialized_copy(first1, last1, first2));
|
||||
|
||||
#if EASTL_EXCEPTIONS_ENABLED
|
||||
try
|
||||
{
|
||||
#endif
|
||||
eastl::uninitialized_fill(mid, last2, value);
|
||||
#if EASTL_EXCEPTIONS_ENABLED
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
for(; first2 < mid; ++first2)
|
||||
first2->~value_type();
|
||||
throw;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/// uninitialized_fill_copy
|
||||
///
|
||||
/// Fills [result, mid) with value then copies [first, last) into [mid, mid + (last - first)).
|
||||
///
|
||||
template <typename ForwardIterator, typename T, typename InputIterator>
|
||||
inline ForwardIterator
|
||||
uninitialized_fill_copy(ForwardIterator result, ForwardIterator mid, const T& value, InputIterator first, InputIterator last)
|
||||
{
|
||||
eastl::uninitialized_fill(result, mid, value);
|
||||
|
||||
#if EASTL_EXCEPTIONS_ENABLED
|
||||
try
|
||||
{
|
||||
#endif
|
||||
return eastl::uninitialized_copy(first, last, mid);
|
||||
#if EASTL_EXCEPTIONS_ENABLED
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
for(; result < mid; ++result)
|
||||
result->~value_type();
|
||||
throw;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// uninitialized_copy_copy
|
||||
///
|
||||
/// Copies [first1, last1) into [result, result + (last1 - first1)) then
|
||||
/// copies [first2, last2) into [result, result + (last1 - first1) + (last2 - first2)).
|
||||
///
|
||||
template <typename InputIterator1, typename InputIterator2, typename ForwardIterator>
|
||||
inline ForwardIterator
|
||||
uninitialized_copy_copy(InputIterator1 first1, InputIterator1 last1,
|
||||
InputIterator2 first2, InputIterator2 last2,
|
||||
ForwardIterator result)
|
||||
{
|
||||
const ForwardIterator mid(eastl::uninitialized_copy(first1, last1, result));
|
||||
|
||||
#if EASTL_EXCEPTIONS_ENABLED
|
||||
try
|
||||
{
|
||||
#endif
|
||||
return eastl::uninitialized_copy(first2, last2, mid);
|
||||
#if EASTL_EXCEPTIONS_ENABLED
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
for(; result < mid; ++result)
|
||||
result->~value_type();
|
||||
throw;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// destruct
|
||||
///
|
||||
/// Calls the destructor of a given object.
|
||||
///
|
||||
/// Note that we don't have a specialized version of this for objects
|
||||
/// with trivial destructors, such as integers. This is because the
|
||||
/// compiler can already see in our version here that the destructor
|
||||
/// is a no-op.
|
||||
///
|
||||
template <typename T>
|
||||
inline void destruct(T* p)
|
||||
{
|
||||
p->~T();
|
||||
}
|
||||
|
||||
|
||||
|
||||
// destruct(first, last)
|
||||
//
|
||||
template <typename ForwardIterator>
|
||||
inline void destruct_impl(ForwardIterator /*first*/, ForwardIterator /*last*/, true_type) // true means the type has a trivial destructor.
|
||||
{
|
||||
// Empty. The type has a trivial destructor.
|
||||
}
|
||||
|
||||
template <typename ForwardIterator>
|
||||
inline void destruct_impl(ForwardIterator first, ForwardIterator last, false_type) // false means the type has a significant destructor.
|
||||
{
|
||||
typedef typename eastl::iterator_traits<ForwardIterator>::value_type value_type;
|
||||
|
||||
for(; first != last; ++first)
|
||||
(*first).~value_type();
|
||||
}
|
||||
|
||||
/// destruct
|
||||
///
|
||||
/// Calls the destructor on a range of objects.
|
||||
///
|
||||
/// We have a specialization for objects with trivial destructors, such as
|
||||
/// PODs. In this specialization the destruction of the range is a no-op.
|
||||
///
|
||||
template <typename ForwardIterator>
|
||||
inline void destruct(ForwardIterator first, ForwardIterator last)
|
||||
{
|
||||
typedef typename eastl::iterator_traits<ForwardIterator>::value_type value_type;
|
||||
destruct_impl(first, last, eastl::has_trivial_destructor<value_type>());
|
||||
}
|
||||
|
||||
|
||||
} // namespace eastl
|
||||
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
|
||||
#endif // Header include guard
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
567
lib/eastl/include/EASTL/set.h
Normal file
567
lib/eastl/include/EASTL/set.h
Normal file
|
@ -0,0 +1,567 @@
|
|||
/*
|
||||
Copyright (C) 2009-2010 Electronic Arts, Inc. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
3. Neither the name of Electronic Arts, Inc. ("EA") nor the names of
|
||||
its contributors may be used to endorse or promote products derived
|
||||
from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY ELECTRONIC ARTS AND ITS CONTRIBUTORS "AS IS" AND ANY
|
||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL ELECTRONIC ARTS OR ITS CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// EASTL/set.h
|
||||
//
|
||||
// Copyright (c) 2005, Electronic Arts. All rights reserved.
|
||||
// Written by Paul Pedriana.
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
#ifndef EASTL_SET_H
|
||||
#define EASTL_SET_H
|
||||
|
||||
|
||||
|
||||
#include <EASTL/internal/config.h>
|
||||
#include <EASTL/internal/red_black_tree.h>
|
||||
#include <EASTL/functional.h>
|
||||
#include <EASTL/utility.h>
|
||||
|
||||
|
||||
|
||||
namespace eastl
|
||||
{
|
||||
|
||||
/// EASTL_SET_DEFAULT_NAME
|
||||
///
|
||||
/// Defines a default container name in the absence of a user-provided name.
|
||||
///
|
||||
#ifndef EASTL_SET_DEFAULT_NAME
|
||||
#define EASTL_SET_DEFAULT_NAME EASTL_DEFAULT_NAME_PREFIX " set" // Unless the user overrides something, this is "EASTL set".
|
||||
#endif
|
||||
|
||||
|
||||
/// EASTL_MULTISET_DEFAULT_NAME
|
||||
///
|
||||
/// Defines a default container name in the absence of a user-provided name.
|
||||
///
|
||||
#ifndef EASTL_MULTISET_DEFAULT_NAME
|
||||
#define EASTL_MULTISET_DEFAULT_NAME EASTL_DEFAULT_NAME_PREFIX " multiset" // Unless the user overrides something, this is "EASTL multiset".
|
||||
#endif
|
||||
|
||||
|
||||
/// EASTL_SET_DEFAULT_ALLOCATOR
|
||||
///
|
||||
#ifndef EASTL_SET_DEFAULT_ALLOCATOR
|
||||
#define EASTL_SET_DEFAULT_ALLOCATOR allocator_type(EASTL_SET_DEFAULT_NAME)
|
||||
#endif
|
||||
|
||||
/// EASTL_MULTISET_DEFAULT_ALLOCATOR
|
||||
///
|
||||
#ifndef EASTL_MULTISET_DEFAULT_ALLOCATOR
|
||||
#define EASTL_MULTISET_DEFAULT_ALLOCATOR allocator_type(EASTL_MULTISET_DEFAULT_NAME)
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/// set
|
||||
///
|
||||
/// Implements a canonical set.
|
||||
///
|
||||
/// The large majority of the implementation of this class is found in the rbtree
|
||||
/// base class. We control the behaviour of rbtree via template parameters.
|
||||
///
|
||||
/// Note that the 'bMutableIterators' template parameter to rbtree is set to false.
|
||||
/// This means that set::iterator is const and the same as set::const_iterator.
|
||||
/// This is by design and it follows the C++ standard defect report recommendation.
|
||||
/// If the user wants to modify a container element, the user needs to either use
|
||||
/// mutable data members or use const_cast on the iterator's data member. Both of
|
||||
/// these solutions are recommended by the C++ standard defect report.
|
||||
/// To consider: Expose the bMutableIterators template policy here at the set level
|
||||
/// so the user can have non-const set iterators via a template parameter.
|
||||
///
|
||||
/// Pool allocation
|
||||
/// If you want to make a custom memory pool for a set container, your pool
|
||||
/// needs to contain items of type set::node_type. So if you have a memory
|
||||
/// pool that has a constructor that takes the size of pool items and the
|
||||
/// count of pool items, you would do this (assuming that MemoryPool implements
|
||||
/// the Allocator interface):
|
||||
/// typedef set<Widget, less<Widget>, MemoryPool> WidgetSet; // Delare your WidgetSet type.
|
||||
/// MemoryPool myPool(sizeof(WidgetSet::node_type), 100); // Make a pool of 100 Widget nodes.
|
||||
/// WidgetSet mySet(&myPool); // Create a map that uses the pool.
|
||||
///
|
||||
template <typename Key, typename Compare = eastl::less<Key>, typename Allocator = EASTLAllocatorType>
|
||||
class set
|
||||
: public rbtree<Key, Key, Compare, Allocator, eastl::use_self<Key>, false, true>
|
||||
{
|
||||
public:
|
||||
typedef rbtree<Key, Key, Compare, Allocator, eastl::use_self<Key>, false, true> base_type;
|
||||
typedef set<Key, Compare, Allocator> this_type;
|
||||
typedef typename base_type::size_type size_type;
|
||||
typedef typename base_type::value_type value_type;
|
||||
typedef typename base_type::iterator iterator;
|
||||
typedef typename base_type::const_iterator const_iterator;
|
||||
typedef typename base_type::reverse_iterator reverse_iterator;
|
||||
typedef typename base_type::const_reverse_iterator const_reverse_iterator;
|
||||
typedef typename base_type::allocator_type allocator_type;
|
||||
// Other types are inherited from the base class.
|
||||
|
||||
using base_type::begin;
|
||||
using base_type::end;
|
||||
using base_type::find;
|
||||
using base_type::lower_bound;
|
||||
using base_type::upper_bound;
|
||||
using base_type::mCompare;
|
||||
|
||||
public:
|
||||
set(const allocator_type& allocator = EASTL_SET_DEFAULT_ALLOCATOR);
|
||||
set(const Compare& compare, const allocator_type& allocator = EASTL_SET_DEFAULT_ALLOCATOR);
|
||||
set(const this_type& x);
|
||||
|
||||
template <typename Iterator>
|
||||
set(Iterator itBegin, Iterator itEnd); // allocator arg removed because VC7.1 fails on the default arg. To do: Make a second version of this function without a default arg.
|
||||
|
||||
public:
|
||||
size_type erase(const Key& k);
|
||||
iterator erase(iterator position);
|
||||
iterator erase(iterator first, iterator last);
|
||||
|
||||
reverse_iterator erase(reverse_iterator position);
|
||||
reverse_iterator erase(reverse_iterator first, reverse_iterator last);
|
||||
|
||||
size_type count(const Key& k) const;
|
||||
|
||||
eastl::pair<iterator, iterator> equal_range(const Key& k);
|
||||
eastl::pair<const_iterator, const_iterator> equal_range(const Key& k) const;
|
||||
|
||||
}; // set
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/// multiset
|
||||
///
|
||||
/// Implements a canonical multiset.
|
||||
///
|
||||
/// The large majority of the implementation of this class is found in the rbtree
|
||||
/// base class. We control the behaviour of rbtree via template parameters.
|
||||
///
|
||||
/// See notes above in 'set' regarding multable iterators.
|
||||
///
|
||||
/// Pool allocation
|
||||
/// If you want to make a custom memory pool for a multiset container, your pool
|
||||
/// needs to contain items of type multiset::node_type. So if you have a memory
|
||||
/// pool that has a constructor that takes the size of pool items and the
|
||||
/// count of pool items, you would do this (assuming that MemoryPool implements
|
||||
/// the Allocator interface):
|
||||
/// typedef multiset<Widget, less<Widget>, MemoryPool> WidgetSet; // Delare your WidgetSet type.
|
||||
/// MemoryPool myPool(sizeof(WidgetSet::node_type), 100); // Make a pool of 100 Widget nodes.
|
||||
/// WidgetSet mySet(&myPool); // Create a map that uses the pool.
|
||||
///
|
||||
template <typename Key, typename Compare = eastl::less<Key>, typename Allocator = EASTLAllocatorType>
|
||||
class multiset
|
||||
: public rbtree<Key, Key, Compare, Allocator, eastl::use_self<Key>, false, false>
|
||||
{
|
||||
public:
|
||||
typedef rbtree<Key, Key, Compare, Allocator, eastl::use_self<Key>, false, false> base_type;
|
||||
typedef multiset<Key, Compare, Allocator> this_type;
|
||||
typedef typename base_type::size_type size_type;
|
||||
typedef typename base_type::value_type value_type;
|
||||
typedef typename base_type::iterator iterator;
|
||||
typedef typename base_type::const_iterator const_iterator;
|
||||
typedef typename base_type::reverse_iterator reverse_iterator;
|
||||
typedef typename base_type::const_reverse_iterator const_reverse_iterator;
|
||||
typedef typename base_type::allocator_type allocator_type;
|
||||
// Other types are inherited from the base class.
|
||||
|
||||
using base_type::begin;
|
||||
using base_type::end;
|
||||
using base_type::find;
|
||||
using base_type::lower_bound;
|
||||
using base_type::upper_bound;
|
||||
using base_type::mCompare;
|
||||
|
||||
public:
|
||||
multiset(const allocator_type& allocator = EASTL_MULTISET_DEFAULT_ALLOCATOR);
|
||||
multiset(const Compare& compare, const allocator_type& allocator = EASTL_MULTISET_DEFAULT_ALLOCATOR);
|
||||
multiset(const this_type& x);
|
||||
|
||||
template <typename Iterator>
|
||||
multiset(Iterator itBegin, Iterator itEnd); // allocator arg removed because VC7.1 fails on the default arg. To do: Make a second version of this function without a default arg.
|
||||
|
||||
public:
|
||||
size_type erase(const Key& k);
|
||||
iterator erase(iterator position);
|
||||
iterator erase(iterator first, iterator last);
|
||||
|
||||
reverse_iterator erase(reverse_iterator position);
|
||||
reverse_iterator erase(reverse_iterator first, reverse_iterator last);
|
||||
|
||||
size_type count(const Key& k) const;
|
||||
|
||||
eastl::pair<iterator, iterator> equal_range(const Key& k);
|
||||
eastl::pair<const_iterator, const_iterator> equal_range(const Key& k) const;
|
||||
|
||||
/// equal_range_small
|
||||
/// This is a special version of equal_range which is optimized for the
|
||||
/// case of there being few or no duplicated keys in the tree.
|
||||
eastl::pair<iterator, iterator> equal_range_small(const Key& k);
|
||||
eastl::pair<const_iterator, const_iterator> equal_range_small(const Key& k) const;
|
||||
|
||||
}; // multiset
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// set
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <typename Key, typename Compare, typename Allocator>
|
||||
inline set<Key, Compare, Allocator>::set(const allocator_type& allocator)
|
||||
: base_type(allocator)
|
||||
{
|
||||
// Empty
|
||||
}
|
||||
|
||||
|
||||
template <typename Key, typename Compare, typename Allocator>
|
||||
inline set<Key, Compare, Allocator>::set(const Compare& compare, const allocator_type& allocator)
|
||||
: base_type(compare, allocator)
|
||||
{
|
||||
// Empty
|
||||
}
|
||||
|
||||
|
||||
template <typename Key, typename Compare, typename Allocator>
|
||||
inline set<Key, Compare, Allocator>::set(const this_type& x)
|
||||
: base_type(x)
|
||||
{
|
||||
// Empty
|
||||
}
|
||||
|
||||
|
||||
template <typename Key, typename Compare, typename Allocator>
|
||||
template <typename Iterator>
|
||||
inline set<Key, Compare, Allocator>::set(Iterator itBegin, Iterator itEnd)
|
||||
: base_type(itBegin, itEnd, Compare(), EASTL_SET_DEFAULT_ALLOCATOR)
|
||||
{
|
||||
// Empty
|
||||
}
|
||||
|
||||
|
||||
template <typename Key, typename Compare, typename Allocator>
|
||||
inline typename set<Key, Compare, Allocator>::size_type
|
||||
set<Key, Compare, Allocator>::erase(const Key& k)
|
||||
{
|
||||
const iterator it(find(k));
|
||||
|
||||
if(it != end()) // If it exists...
|
||||
{
|
||||
base_type::erase(it);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
template <typename Key, typename Compare, typename Allocator>
|
||||
inline typename set<Key, Compare, Allocator>::iterator
|
||||
set<Key, Compare, Allocator>::erase(iterator position)
|
||||
{
|
||||
// We need to provide this version because we override another version
|
||||
// and C++ hiding rules would make the base version of this hidden.
|
||||
return base_type::erase(position);
|
||||
}
|
||||
|
||||
|
||||
template <typename Key, typename Compare, typename Allocator>
|
||||
inline typename set<Key, Compare, Allocator>::iterator
|
||||
set<Key, Compare, Allocator>::erase(iterator first, iterator last)
|
||||
{
|
||||
// We need to provide this version because we override another version
|
||||
// and C++ hiding rules would make the base version of this hidden.
|
||||
return base_type::erase(first, last);
|
||||
}
|
||||
|
||||
|
||||
template <typename Key, typename Compare, typename Allocator>
|
||||
inline typename set<Key, Compare, Allocator>::size_type
|
||||
set<Key, Compare, Allocator>::count(const Key& k) const
|
||||
{
|
||||
const const_iterator it(find(k));
|
||||
return (it != end()) ? (size_type)1 : (size_type)0;
|
||||
}
|
||||
|
||||
|
||||
template <typename Key, typename Compare, typename Allocator>
|
||||
inline typename set<Key, Compare, Allocator>::reverse_iterator
|
||||
set<Key, Compare, Allocator>::erase(reverse_iterator position)
|
||||
{
|
||||
return reverse_iterator(erase((++position).base()));
|
||||
}
|
||||
|
||||
|
||||
template <typename Key, typename Compare, typename Allocator>
|
||||
inline typename set<Key, Compare, Allocator>::reverse_iterator
|
||||
set<Key, Compare, Allocator>::erase(reverse_iterator first, reverse_iterator last)
|
||||
{
|
||||
// Version which erases in order from first to last.
|
||||
// difference_type i(first.base() - last.base());
|
||||
// while(i--)
|
||||
// first = erase(first);
|
||||
// return first;
|
||||
|
||||
// Version which erases in order from last to first, but is slightly more efficient:
|
||||
return reverse_iterator(erase((++last).base(), (++first).base()));
|
||||
}
|
||||
|
||||
|
||||
template <typename Key, typename Compare, typename Allocator>
|
||||
inline eastl::pair<typename set<Key, Compare, Allocator>::iterator,
|
||||
typename set<Key, Compare, Allocator>::iterator>
|
||||
set<Key, Compare, Allocator>::equal_range(const Key& k)
|
||||
{
|
||||
// The resulting range will either be empty or have one element,
|
||||
// so instead of doing two tree searches (one for lower_bound and
|
||||
// one for upper_bound), we do just lower_bound and see if the
|
||||
// result is a range of size zero or one.
|
||||
const iterator itLower(lower_bound(k));
|
||||
|
||||
if((itLower == end()) || mCompare(k, *itLower)) // If at the end or if (k is < itLower)...
|
||||
return eastl::pair<iterator, iterator>(itLower, itLower);
|
||||
|
||||
iterator itUpper(itLower);
|
||||
return eastl::pair<iterator, iterator>(itLower, ++itUpper);
|
||||
}
|
||||
|
||||
|
||||
template <typename Key, typename Compare, typename Allocator>
|
||||
inline eastl::pair<typename set<Key, Compare, Allocator>::const_iterator,
|
||||
typename set<Key, Compare, Allocator>::const_iterator>
|
||||
set<Key, Compare, Allocator>::equal_range(const Key& k) const
|
||||
{
|
||||
// See equal_range above for comments.
|
||||
const const_iterator itLower(lower_bound(k));
|
||||
|
||||
if((itLower == end()) || mCompare(k, *itLower)) // If at the end or if (k is < itLower)...
|
||||
return eastl::pair<const_iterator, const_iterator>(itLower, itLower);
|
||||
|
||||
const_iterator itUpper(itLower);
|
||||
return eastl::pair<const_iterator, const_iterator>(itLower, ++itUpper);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// multiset
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <typename Key, typename Compare, typename Allocator>
|
||||
inline multiset<Key, Compare, Allocator>::multiset(const allocator_type& allocator)
|
||||
: base_type(allocator)
|
||||
{
|
||||
// Empty
|
||||
}
|
||||
|
||||
|
||||
template <typename Key, typename Compare, typename Allocator>
|
||||
inline multiset<Key, Compare, Allocator>::multiset(const Compare& compare, const allocator_type& allocator)
|
||||
: base_type(compare, allocator)
|
||||
{
|
||||
// Empty
|
||||
}
|
||||
|
||||
|
||||
template <typename Key, typename Compare, typename Allocator>
|
||||
inline multiset<Key, Compare, Allocator>::multiset(const this_type& x)
|
||||
: base_type(x)
|
||||
{
|
||||
// Empty
|
||||
}
|
||||
|
||||
|
||||
template <typename Key, typename Compare, typename Allocator>
|
||||
template <typename Iterator>
|
||||
inline multiset<Key, Compare, Allocator>::multiset(Iterator itBegin, Iterator itEnd)
|
||||
: base_type(itBegin, itEnd, Compare(), EASTL_MULTISET_DEFAULT_ALLOCATOR)
|
||||
{
|
||||
// Empty
|
||||
}
|
||||
|
||||
|
||||
template <typename Key, typename Compare, typename Allocator>
|
||||
inline typename multiset<Key, Compare, Allocator>::size_type
|
||||
multiset<Key, Compare, Allocator>::erase(const Key& k)
|
||||
{
|
||||
const eastl::pair<iterator, iterator> range(equal_range(k));
|
||||
const size_type n = (size_type)eastl::distance(range.first, range.second);
|
||||
base_type::erase(range.first, range.second);
|
||||
return n;
|
||||
}
|
||||
|
||||
|
||||
template <typename Key, typename Compare, typename Allocator>
|
||||
inline typename multiset<Key, Compare, Allocator>::iterator
|
||||
multiset<Key, Compare, Allocator>::erase(iterator position)
|
||||
{
|
||||
// We need to provide this version because we override another version
|
||||
// and C++ hiding rules would make the base version of this hidden.
|
||||
return base_type::erase(position);
|
||||
}
|
||||
|
||||
|
||||
template <typename Key, typename Compare, typename Allocator>
|
||||
inline typename multiset<Key, Compare, Allocator>::iterator
|
||||
multiset<Key, Compare, Allocator>::erase(iterator first, iterator last)
|
||||
{
|
||||
// We need to provide this version because we override another version
|
||||
// and C++ hiding rules would make the base version of this hidden.
|
||||
return base_type::erase(first, last);
|
||||
}
|
||||
|
||||
|
||||
template <typename Key, typename Compare, typename Allocator>
|
||||
inline typename multiset<Key, Compare, Allocator>::size_type
|
||||
multiset<Key, Compare, Allocator>::count(const Key& k) const
|
||||
{
|
||||
const eastl::pair<const_iterator, const_iterator> range(equal_range(k));
|
||||
return (size_type)eastl::distance(range.first, range.second);
|
||||
}
|
||||
|
||||
|
||||
template <typename Key, typename Compare, typename Allocator>
|
||||
inline typename multiset<Key, Compare, Allocator>::reverse_iterator
|
||||
multiset<Key, Compare, Allocator>::erase(reverse_iterator position)
|
||||
{
|
||||
return reverse_iterator(erase((++position).base()));
|
||||
}
|
||||
|
||||
|
||||
template <typename Key, typename Compare, typename Allocator>
|
||||
inline typename multiset<Key, Compare, Allocator>::reverse_iterator
|
||||
multiset<Key, Compare, Allocator>::erase(reverse_iterator first, reverse_iterator last)
|
||||
{
|
||||
// Version which erases in order from first to last.
|
||||
// difference_type i(first.base() - last.base());
|
||||
// while(i--)
|
||||
// first = erase(first);
|
||||
// return first;
|
||||
|
||||
// Version which erases in order from last to first, but is slightly more efficient:
|
||||
return reverse_iterator(erase((++last).base(), (++first).base()));
|
||||
}
|
||||
|
||||
|
||||
template <typename Key, typename Compare, typename Allocator>
|
||||
inline eastl::pair<typename multiset<Key, Compare, Allocator>::iterator,
|
||||
typename multiset<Key, Compare, Allocator>::iterator>
|
||||
multiset<Key, Compare, Allocator>::equal_range(const Key& k)
|
||||
{
|
||||
// There are multiple ways to implement equal_range. The implementation mentioned
|
||||
// in the C++ standard and which is used by most (all?) commercial STL implementations
|
||||
// is this:
|
||||
// return eastl::pair<iterator, iterator>(lower_bound(k), upper_bound(k));
|
||||
//
|
||||
// This does two tree searches -- one for the lower bound and one for the
|
||||
// upper bound. This works well for the case whereby you have a large container
|
||||
// and there are lots of duplicated values. We provide an alternative version
|
||||
// of equal_range called equal_range_small for cases where the user is confident
|
||||
// that the number of duplicated items is only a few.
|
||||
|
||||
return eastl::pair<iterator, iterator>(lower_bound(k), upper_bound(k));
|
||||
}
|
||||
|
||||
|
||||
template <typename Key, typename Compare, typename Allocator>
|
||||
inline eastl::pair<typename multiset<Key, Compare, Allocator>::const_iterator,
|
||||
typename multiset<Key, Compare, Allocator>::const_iterator>
|
||||
multiset<Key, Compare, Allocator>::equal_range(const Key& k) const
|
||||
{
|
||||
// See comments above in the non-const version of equal_range.
|
||||
return eastl::pair<iterator, iterator>(lower_bound(k), upper_bound(k));
|
||||
}
|
||||
|
||||
|
||||
template <typename Key, typename Compare, typename Allocator>
|
||||
inline eastl::pair<typename multiset<Key, Compare, Allocator>::iterator,
|
||||
typename multiset<Key, Compare, Allocator>::iterator>
|
||||
multiset<Key, Compare, Allocator>::equal_range_small(const Key& k)
|
||||
{
|
||||
// We provide alternative version of equal_range here which works faster
|
||||
// for the case where there are at most small number of potential duplicated keys.
|
||||
const iterator itLower(lower_bound(k));
|
||||
iterator itUpper(itLower);
|
||||
|
||||
while((itUpper != end()) && !mCompare(k, itUpper.mpNode->mValue))
|
||||
++itUpper;
|
||||
|
||||
return eastl::pair<iterator, iterator>(itLower, itUpper);
|
||||
}
|
||||
|
||||
|
||||
template <typename Key, typename Compare, typename Allocator>
|
||||
inline eastl::pair<typename multiset<Key, Compare, Allocator>::const_iterator,
|
||||
typename multiset<Key, Compare, Allocator>::const_iterator>
|
||||
multiset<Key, Compare, Allocator>::equal_range_small(const Key& k) const
|
||||
{
|
||||
// We provide alternative version of equal_range here which works faster
|
||||
// for the case where there are at most small number of potential duplicated keys.
|
||||
const const_iterator itLower(lower_bound(k));
|
||||
const_iterator itUpper(itLower);
|
||||
|
||||
while((itUpper != end()) && !mCompare(k, *itUpper))
|
||||
++itUpper;
|
||||
|
||||
return eastl::pair<const_iterator, const_iterator>(itLower, itUpper);
|
||||
}
|
||||
|
||||
|
||||
|
||||
} // namespace eastl
|
||||
|
||||
|
||||
#endif // Header include guard
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
912
lib/eastl/include/EASTL/sort.h
Normal file
912
lib/eastl/include/EASTL/sort.h
Normal file
|
@ -0,0 +1,912 @@
|
|||
/*
|
||||
Copyright (C) 2005,2009-2010 Electronic Arts, Inc. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
3. Neither the name of Electronic Arts, Inc. ("EA") nor the names of
|
||||
its contributors may be used to endorse or promote products derived
|
||||
from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY ELECTRONIC ARTS AND ITS CONTRIBUTORS "AS IS" AND ANY
|
||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL ELECTRONIC ARTS OR ITS CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// EASTL/sort.h
|
||||
// Written by Paul Pedriana - 2005.
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// This file implements sorting algorithms. Some of these are equivalent to
|
||||
// std C++ sorting algorithms, while others don't have equivalents in the
|
||||
// C++ standard. We implement the following sorting algorithms:
|
||||
// is_sorted
|
||||
// sort The implementation of this is simply mapped to quick_sort.
|
||||
// quick_sort
|
||||
// partial_sort
|
||||
// insertion_sort
|
||||
// shell_sort
|
||||
// heap_sort
|
||||
// stable_sort The implementation of this is simply mapped to merge_sort.
|
||||
// merge
|
||||
// merge_sort
|
||||
// merge_sort_buffer
|
||||
// nth_element
|
||||
// radix_sort Found in sort_extra.h.
|
||||
// comb_sort Found in sort_extra.h.
|
||||
// bubble_sort Found in sort_extra.h.
|
||||
// selection_sort Found in sort_extra.h.
|
||||
// shaker_sort Found in sort_extra.h.
|
||||
// bucket_sort Found in sort_extra.h.
|
||||
//
|
||||
// Additional sorting and related algorithms we may want to implement:
|
||||
// partial_sort_copy This would be like the std STL version.
|
||||
// paritition This would be like the std STL version. This is not categorized as a sort routine by the language standard.
|
||||
// stable_partition This would be like the std STL version.
|
||||
// counting_sort Maybe we don't want to implement this.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
#ifndef EASTL_SORT_H
|
||||
#define EASTL_SORT_H
|
||||
|
||||
|
||||
|
||||
#include <EASTL/internal/config.h>
|
||||
#include <EASTL/iterator.h>
|
||||
#include <EASTL/memory.h>
|
||||
#include <EASTL/algorithm.h>
|
||||
#include <EASTL/functional.h>
|
||||
#include <EASTL/heap.h>
|
||||
#include <EASTL/allocator.h>
|
||||
#include <EASTL/memory.h>
|
||||
|
||||
|
||||
|
||||
namespace eastl
|
||||
{
|
||||
|
||||
/// is_sorted
|
||||
///
|
||||
/// Returns true if the range [first, last) is sorted.
|
||||
/// An empty range is considered to be sorted.
|
||||
/// To test if a range is reverse-sorted, use 'greater' as the comparison
|
||||
/// instead of 'less'.
|
||||
///
|
||||
/// Example usage:
|
||||
/// vector<int> intArray;
|
||||
/// bool bIsSorted = is_sorted(intArray.begin(), intArray.end());
|
||||
/// bool bIsReverseSorted = is_sorted(intArray.begin(), intArray.end(), greater<int>());
|
||||
///
|
||||
template <typename ForwardIterator, typename StrictWeakOrdering>
|
||||
bool is_sorted(ForwardIterator first, ForwardIterator last, StrictWeakOrdering compare)
|
||||
{
|
||||
if(first != last)
|
||||
{
|
||||
ForwardIterator current = first;
|
||||
|
||||
for(++current; current != last; first = current, ++current)
|
||||
{
|
||||
if(compare(*current, *first))
|
||||
{
|
||||
EASTL_VALIDATE_COMPARE(!compare(*first, *current)); // Validate that the compare function is sane.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename ForwardIterator>
|
||||
inline bool is_sorted(ForwardIterator first, ForwardIterator last)
|
||||
{
|
||||
typedef eastl::less<typename eastl::iterator_traits<ForwardIterator>::value_type> Less;
|
||||
|
||||
return eastl::is_sorted<ForwardIterator, Less>(first, last, Less());
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// merge
|
||||
///
|
||||
/// This function merges two sorted input sorted ranges into a result sorted range.
|
||||
/// This merge is stable in that no element from the first range will be changed
|
||||
/// in order relative to other elements from the first range.
|
||||
///
|
||||
template <typename InputIterator1, typename InputIterator2, typename OutputIterator, typename Compare>
|
||||
OutputIterator merge(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, OutputIterator result, Compare compare)
|
||||
{
|
||||
while((first1 != last1) && (first2 != last2))
|
||||
{
|
||||
if(compare(*first2, *first1))
|
||||
{
|
||||
EASTL_VALIDATE_COMPARE(!compare(*first1, *first2)); // Validate that the compare function is sane.
|
||||
*result = *first2;
|
||||
++first2;
|
||||
}
|
||||
else
|
||||
{
|
||||
*result = *first1;
|
||||
++first1;
|
||||
}
|
||||
++result;
|
||||
}
|
||||
|
||||
return eastl::copy(first2, last2, eastl::copy(first1, last1, result));
|
||||
}
|
||||
|
||||
template <typename InputIterator1, typename InputIterator2, typename OutputIterator>
|
||||
inline OutputIterator merge(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, OutputIterator result)
|
||||
{
|
||||
typedef eastl::less<typename eastl::iterator_traits<InputIterator1>::value_type> Less;
|
||||
|
||||
return eastl::merge<InputIterator1, InputIterator2, OutputIterator, Less>
|
||||
(first1, last1, first2, last2, result, Less());
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// insertion_sort
|
||||
///
|
||||
/// Implements the InsertionSort algorithm.
|
||||
///
|
||||
template <typename BidirectionalIterator, typename StrictWeakOrdering>
|
||||
void insertion_sort(BidirectionalIterator first, BidirectionalIterator last, StrictWeakOrdering compare)
|
||||
{
|
||||
typedef typename eastl::iterator_traits<BidirectionalIterator>::value_type value_type;
|
||||
|
||||
if(first != last)
|
||||
{
|
||||
BidirectionalIterator iCurrent, iNext, iSorted = first;
|
||||
|
||||
for(++iSorted; iSorted != last; ++iSorted)
|
||||
{
|
||||
const value_type temp(*iSorted);
|
||||
|
||||
iNext = iCurrent = iSorted;
|
||||
|
||||
for(--iCurrent; (iNext != first) && compare(temp, *iCurrent); --iNext, --iCurrent)
|
||||
{
|
||||
EASTL_VALIDATE_COMPARE(!compare(*iCurrent, temp)); // Validate that the compare function is sane.
|
||||
*iNext = *iCurrent;
|
||||
}
|
||||
|
||||
*iNext = temp;
|
||||
}
|
||||
}
|
||||
} // insertion_sort
|
||||
|
||||
|
||||
|
||||
template <typename BidirectionalIterator>
|
||||
void insertion_sort(BidirectionalIterator first, BidirectionalIterator last)
|
||||
{
|
||||
typedef typename eastl::iterator_traits<BidirectionalIterator>::value_type value_type;
|
||||
|
||||
if(first != last)
|
||||
{
|
||||
BidirectionalIterator iCurrent, iNext, iSorted = first;
|
||||
|
||||
for(++iSorted; iSorted != last; ++iSorted)
|
||||
{
|
||||
const value_type temp(*iSorted);
|
||||
|
||||
iNext = iCurrent = iSorted;
|
||||
|
||||
for(--iCurrent; (iNext != first) && (temp < *iCurrent); --iNext, --iCurrent)
|
||||
{
|
||||
EASTL_VALIDATE_COMPARE(!(*iCurrent < temp)); // Validate that the compare function is sane.
|
||||
*iNext = *iCurrent;
|
||||
}
|
||||
|
||||
*iNext = temp;
|
||||
}
|
||||
}
|
||||
} // insertion_sort
|
||||
|
||||
|
||||
#if 0 /*
|
||||
// STLPort-like variation of insertion_sort. Doesn't seem to run quite as fast for small runs.
|
||||
//
|
||||
template <typename RandomAccessIterator, typename Compare>
|
||||
void insertion_sort(RandomAccessIterator first, RandomAccessIterator last, Compare compare)
|
||||
{
|
||||
if(first != last)
|
||||
{
|
||||
for(RandomAccessIterator i = first + 1; i != last; ++i)
|
||||
{
|
||||
const typename eastl::iterator_traits<RandomAccessIterator>::value_type value(*i);
|
||||
|
||||
if(compare(value, *first))
|
||||
{
|
||||
EASTL_VALIDATE_COMPARE(!compare(*first, value)); // Validate that the compare function is sane.
|
||||
eastl::copy_backward(first, i, i + 1);
|
||||
*first = value;
|
||||
}
|
||||
else
|
||||
{
|
||||
RandomAccessIterator end(i), prev(i);
|
||||
|
||||
for(--prev; compare(value, *prev); --end, --prev)
|
||||
{
|
||||
EASTL_VALIDATE_COMPARE(!compare(*prev, value)); // Validate that the compare function is sane.
|
||||
*end = *prev;
|
||||
}
|
||||
|
||||
*end = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// STLPort-like variation of insertion_sort. Doesn't seem to run quite as fast for small runs.
|
||||
//
|
||||
template <typename RandomAccessIterator>
|
||||
void insertion_sort(RandomAccessIterator first, RandomAccessIterator last)
|
||||
{
|
||||
if(first != last)
|
||||
{
|
||||
for(RandomAccessIterator i = first + 1; i != last; ++i)
|
||||
{
|
||||
const typename eastl::iterator_traits<RandomAccessIterator>::value_type value(*i);
|
||||
|
||||
if(value < *first)
|
||||
{
|
||||
EASTL_VALIDATE_COMPARE(!(*first < value)); // Validate that the compare function is sane.
|
||||
eastl::copy_backward(first, i, i + 1);
|
||||
*first = value;
|
||||
}
|
||||
else
|
||||
{
|
||||
RandomAccessIterator end(i), prev(i);
|
||||
|
||||
for(--prev; value < *prev; --end, --prev)
|
||||
{
|
||||
EASTL_VALIDATE_COMPARE(!(*prev < value)); // Validate that the compare function is sane.
|
||||
*end = *prev;
|
||||
}
|
||||
|
||||
*end = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
} */
|
||||
#endif
|
||||
|
||||
|
||||
/// shell_sort
|
||||
///
|
||||
/// Implements the ShellSort algorithm. This algorithm is a serious algorithm for larger
|
||||
/// data sets, as reported by Sedgewick in his discussions on QuickSort. Note that shell_sort
|
||||
/// requires a random access iterator, which usually means an array (eg. vector, deque).
|
||||
/// ShellSort has good performance with presorted sequences.
|
||||
/// The term "shell" derives from the name of the inventor, David Shell.
|
||||
///
|
||||
/// To consider: Allow the user to specify the "h-sequence" array.
|
||||
///
|
||||
template <typename RandomAccessIterator, typename StrictWeakOrdering>
|
||||
void shell_sort(RandomAccessIterator first, RandomAccessIterator last, StrictWeakOrdering compare)
|
||||
{
|
||||
typedef typename eastl::iterator_traits<RandomAccessIterator>::difference_type difference_type;
|
||||
|
||||
// We use the Knuth 'h' sequence below, as it is easy to calculate at runtime.
|
||||
// However, possibly we are better off using a different sequence based on a table.
|
||||
// One such sequence which averages slightly better than Knuth is:
|
||||
// 1, 5, 19, 41, 109, 209, 505, 929, 2161, 3905, 8929, 16001, 36289,
|
||||
// 64769, 146305, 260609, 587521, 1045505, 2354689, 4188161, 9427969, 16764929
|
||||
|
||||
if(first != last)
|
||||
{
|
||||
RandomAccessIterator iCurrent, iBack, iSorted, iInsertFirst;
|
||||
difference_type nSize = last - first;
|
||||
difference_type nSpace = 1; // nSpace is the 'h' value of the ShellSort algorithm.
|
||||
|
||||
while(nSpace < nSize)
|
||||
nSpace = (nSpace * 3) + 1; // This is the Knuth 'h' sequence: 1, 4, 13, 40, 121, 364, 1093, 3280, 9841, 29524, 88573, 265720, 797161, 2391484, 7174453, 21523360, 64570081, 193710244,
|
||||
|
||||
for(nSpace = (nSpace - 1) / 3; nSpace >= 1; nSpace = (nSpace - 1) / 3) // Integer division is less than ideal.
|
||||
{
|
||||
for(difference_type i = 0; i < nSpace; i++)
|
||||
{
|
||||
iInsertFirst = first + i;
|
||||
|
||||
for(iSorted = iInsertFirst + nSpace; iSorted < last; iSorted += nSpace)
|
||||
{
|
||||
iBack = iCurrent = iSorted;
|
||||
|
||||
for(iBack -= nSpace; (iCurrent != iInsertFirst) && compare(*iCurrent, *iBack); iCurrent = iBack, iBack -= nSpace)
|
||||
{
|
||||
EASTL_VALIDATE_COMPARE(!compare(*iBack, *iCurrent)); // Validate that the compare function is sane.
|
||||
eastl::iter_swap(iCurrent, iBack);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} // shell_sort
|
||||
|
||||
template <typename RandomAccessIterator>
|
||||
inline void shell_sort(RandomAccessIterator first, RandomAccessIterator last)
|
||||
{
|
||||
typedef eastl::less<typename eastl::iterator_traits<RandomAccessIterator>::value_type> Less;
|
||||
|
||||
eastl::shell_sort<RandomAccessIterator, Less>(first, last, Less());
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// heap_sort
|
||||
///
|
||||
/// Implements the HeapSort algorithm.
|
||||
/// Note that heap_sort requires a random access iterator, which usually means
|
||||
/// an array (eg. vector, deque).
|
||||
///
|
||||
template <typename RandomAccessIterator, typename StrictWeakOrdering>
|
||||
void heap_sort(RandomAccessIterator first, RandomAccessIterator last, StrictWeakOrdering compare)
|
||||
{
|
||||
// We simply call our heap algorithms to do the work for us.
|
||||
eastl::make_heap<RandomAccessIterator, StrictWeakOrdering>(first, last, compare);
|
||||
eastl::sort_heap<RandomAccessIterator, StrictWeakOrdering>(first, last, compare);
|
||||
}
|
||||
|
||||
template <typename RandomAccessIterator>
|
||||
inline void heap_sort(RandomAccessIterator first, RandomAccessIterator last)
|
||||
{
|
||||
typedef eastl::less<typename eastl::iterator_traits<RandomAccessIterator>::value_type> Less;
|
||||
|
||||
eastl::heap_sort<RandomAccessIterator, Less>(first, last, Less());
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/// merge_sort_buffer
|
||||
///
|
||||
/// Implements the MergeSort algorithm with a user-supplied buffer.
|
||||
/// The input buffer must be able to hold a number of items equal to 'last - first'.
|
||||
/// Note that merge_sort_buffer requires a random access iterator, which usually means
|
||||
/// an array (eg. vector, deque).
|
||||
///
|
||||
|
||||
// For reference, the following is the simple version, before inlining one level
|
||||
// of recursion and eliminating the copy:
|
||||
//
|
||||
//template <typename RandomAccessIterator, typename T, typename StrictWeakOrdering>
|
||||
//void merge_sort_buffer(RandomAccessIterator first, RandomAccessIterator last, T* pBuffer, StrictWeakOrdering compare)
|
||||
//{
|
||||
// typedef typename eastl::iterator_traits<RandomAccessIterator>::difference_type difference_type;
|
||||
//
|
||||
// const difference_type nCount = last - first;
|
||||
//
|
||||
// if(nCount > 1)
|
||||
// {
|
||||
// const difference_type nMid = nCount / 2;
|
||||
//
|
||||
// eastl::merge_sort_buffer<RandomAccessIterator, T, StrictWeakOrdering>
|
||||
// (first, first + nMid, pBuffer, compare);
|
||||
// eastl::merge_sort_buffer<RandomAccessIterator, T, StrictWeakOrdering>
|
||||
// (first + nMid, last , pBuffer, compare);
|
||||
// eastl::copy(first, last, pBuffer);
|
||||
// eastl::merge<T*, T*, RandomAccessIterator, StrictWeakOrdering>
|
||||
// (pBuffer, pBuffer + nMid, pBuffer + nMid, pBuffer + nCount, first, compare);
|
||||
// }
|
||||
//}
|
||||
|
||||
template <typename RandomAccessIterator, typename T, typename StrictWeakOrdering>
|
||||
void merge_sort_buffer(RandomAccessIterator first, RandomAccessIterator last, T* pBuffer, StrictWeakOrdering compare)
|
||||
{
|
||||
typedef typename eastl::iterator_traits<RandomAccessIterator>::difference_type difference_type;
|
||||
const difference_type nCount = last - first;
|
||||
|
||||
if(nCount > 1)
|
||||
{
|
||||
const difference_type nMid = nCount / 2;
|
||||
RandomAccessIterator half = first + nMid;
|
||||
|
||||
if(nMid > 1)
|
||||
{
|
||||
const difference_type nQ1(nMid / 2);
|
||||
RandomAccessIterator part(first + nQ1);
|
||||
|
||||
eastl::merge_sort_buffer<RandomAccessIterator, T, StrictWeakOrdering>(first, part, pBuffer, compare);
|
||||
eastl::merge_sort_buffer<RandomAccessIterator, T, StrictWeakOrdering>(part, half, pBuffer + nQ1, compare);
|
||||
eastl::merge<RandomAccessIterator, RandomAccessIterator, T*, StrictWeakOrdering>
|
||||
(first, part, part, half, pBuffer, compare);
|
||||
}
|
||||
else
|
||||
*pBuffer = *first;
|
||||
|
||||
if((nCount - nMid) > 1)
|
||||
{
|
||||
const difference_type nQ3((nMid + nCount) / 2);
|
||||
RandomAccessIterator part(first + nQ3);
|
||||
|
||||
eastl::merge_sort_buffer<RandomAccessIterator, T, StrictWeakOrdering>(half, part, pBuffer + nMid, compare);
|
||||
eastl::merge_sort_buffer<RandomAccessIterator, T, StrictWeakOrdering>(part, last, pBuffer + nQ3, compare);
|
||||
eastl::merge<RandomAccessIterator, RandomAccessIterator, T*, StrictWeakOrdering>
|
||||
(half, part, part, last, pBuffer + nMid, compare);
|
||||
}
|
||||
else
|
||||
*(pBuffer + nMid) = *half;
|
||||
|
||||
eastl::merge<T*, T*, RandomAccessIterator, StrictWeakOrdering>
|
||||
(pBuffer, pBuffer + nMid, pBuffer + nMid, pBuffer + nCount, first, compare);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename RandomAccessIterator, typename T>
|
||||
inline void merge_sort_buffer(RandomAccessIterator first, RandomAccessIterator last, T* pBuffer)
|
||||
{
|
||||
typedef eastl::less<typename eastl::iterator_traits<RandomAccessIterator>::value_type> Less;
|
||||
|
||||
eastl::merge_sort_buffer<RandomAccessIterator, T, Less>(first, last, pBuffer, Less());
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// merge_sort
|
||||
///
|
||||
/// Implements the MergeSort algorithm.
|
||||
/// This algorithm allocates memory via the user-supplied allocator. Use merge_sort_buffer
|
||||
/// function if you want a version which doesn't allocate memory.
|
||||
/// Note that merge_sort requires a random access iterator, which usually means
|
||||
/// an array (eg. vector, deque).
|
||||
///
|
||||
template <typename RandomAccessIterator, typename Allocator, typename StrictWeakOrdering>
|
||||
void merge_sort(RandomAccessIterator first, RandomAccessIterator last, Allocator& allocator, StrictWeakOrdering compare)
|
||||
{
|
||||
typedef typename eastl::iterator_traits<RandomAccessIterator>::difference_type difference_type;
|
||||
typedef typename eastl::iterator_traits<RandomAccessIterator>::value_type value_type;
|
||||
|
||||
const difference_type nCount = last - first;
|
||||
|
||||
if(nCount > 1)
|
||||
{
|
||||
// We need to allocate an array of nCount value_type objects as a temporary buffer.
|
||||
value_type* const pBuffer = (value_type*)allocate_memory(allocator, nCount * sizeof(value_type), EASTL_ALIGN_OF(value_type), 0);
|
||||
eastl::uninitialized_fill(pBuffer, pBuffer + nCount, value_type());
|
||||
|
||||
eastl::merge_sort_buffer<RandomAccessIterator, value_type, StrictWeakOrdering>
|
||||
(first, last, pBuffer, compare);
|
||||
|
||||
eastl::destruct(pBuffer, pBuffer + nCount);
|
||||
EASTLFree(allocator, pBuffer, nCount * sizeof(value_type));
|
||||
}
|
||||
}
|
||||
|
||||
template <typename RandomAccessIterator, typename Allocator>
|
||||
inline void merge_sort(RandomAccessIterator first, RandomAccessIterator last, Allocator& allocator)
|
||||
{
|
||||
typedef eastl::less<typename eastl::iterator_traits<RandomAccessIterator>::value_type> Less;
|
||||
|
||||
eastl::merge_sort<RandomAccessIterator, Allocator, Less>(first, last, allocator, Less());
|
||||
}
|
||||
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
// quick_sort
|
||||
//
|
||||
// We do the "introspection sort" variant of quick sort which is now
|
||||
// well-known and understood. You can read about this algorithm in
|
||||
// many articles on quick sort, but briefly what it does is a median-
|
||||
// of-three quick sort whereby the recursion depth is limited to a
|
||||
// some value (after which it gives up on quick sort and switches to
|
||||
// a heap sort) and whereby after a certain amount of sorting the
|
||||
// algorithm stops doing quick-sort and finishes the sorting via
|
||||
// a simple insertion sort.
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
|
||||
static const int kQuickSortLimit = 28; // For sorts of random arrays over 100 items, 28 - 32 have been found to be good numbers on VC++/Win32.
|
||||
|
||||
namespace Internal
|
||||
{
|
||||
template <typename Size>
|
||||
inline Size Log2(Size n)
|
||||
{
|
||||
int i;
|
||||
for(i = 0; n; ++i)
|
||||
n >>= 1;
|
||||
return i - 1;
|
||||
}
|
||||
|
||||
// To do: Investigate the speed of this bit-trick version of Log2.
|
||||
// It may work better on some platforms but not others.
|
||||
//
|
||||
// union FloatUnion {
|
||||
// float f;
|
||||
// uint32_t i;
|
||||
// };
|
||||
//
|
||||
// inline uint32_t Log2(uint32_t x)
|
||||
// {
|
||||
// const FloatInt32Union u = { x };
|
||||
// return (u.i >> 23) - 127;
|
||||
// }
|
||||
}
|
||||
|
||||
|
||||
/// get_partition
|
||||
///
|
||||
/// This function takes const T& instead of T because T may have special alignment
|
||||
/// requirements and some compilers (e.g. VC++) are don't respect alignment requirements
|
||||
/// for function arguments.
|
||||
///
|
||||
template <typename RandomAccessIterator, typename T>
|
||||
inline RandomAccessIterator get_partition(RandomAccessIterator first, RandomAccessIterator last, const T& pivotValue)
|
||||
{
|
||||
const T pivotCopy(pivotValue); // Need to make a temporary because the sequence below is mutating.
|
||||
|
||||
for(; ; ++first)
|
||||
{
|
||||
while(*first < pivotCopy)
|
||||
{
|
||||
EASTL_VALIDATE_COMPARE(!(pivotCopy < *first)); // Validate that the compare function is sane.
|
||||
++first;
|
||||
}
|
||||
--last;
|
||||
|
||||
while(pivotCopy < *last)
|
||||
{
|
||||
EASTL_VALIDATE_COMPARE(!(*last < pivotCopy)); // Validate that the compare function is sane.
|
||||
--last;
|
||||
}
|
||||
|
||||
if(first >= last) // Random access iterators allow operator >=
|
||||
return first;
|
||||
|
||||
eastl::iter_swap(first, last);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template <typename RandomAccessIterator, typename T, typename Compare>
|
||||
inline RandomAccessIterator get_partition(RandomAccessIterator first, RandomAccessIterator last, const T& pivotValue, Compare compare)
|
||||
{
|
||||
const T pivotCopy(pivotValue); // Need to make a temporary because the sequence below is mutating.
|
||||
|
||||
for(; ; ++first)
|
||||
{
|
||||
while(compare(*first, pivotCopy))
|
||||
{
|
||||
EASTL_VALIDATE_COMPARE(!compare(pivotCopy, *first)); // Validate that the compare function is sane.
|
||||
++first;
|
||||
}
|
||||
--last;
|
||||
|
||||
while(compare(pivotCopy, *last))
|
||||
{
|
||||
EASTL_VALIDATE_COMPARE(!compare(*last, pivotCopy)); // Validate that the compare function is sane.
|
||||
--last;
|
||||
}
|
||||
|
||||
if(first >= last) // Random access iterators allow operator >=
|
||||
return first;
|
||||
|
||||
eastl::iter_swap(first, last);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
namespace Internal
|
||||
{
|
||||
// This function is used by quick_sort and is not intended to be used by itself.
|
||||
// This is because the implementation below makes an assumption about the input
|
||||
// data that quick_sort satisfies but arbitrary data may not.
|
||||
// There is a standalone insertion_sort function.
|
||||
template <typename RandomAccessIterator>
|
||||
inline void insertion_sort_simple(RandomAccessIterator first, RandomAccessIterator last)
|
||||
{
|
||||
for(RandomAccessIterator current = first; current != last; ++current)
|
||||
{
|
||||
typedef typename eastl::iterator_traits<RandomAccessIterator>::value_type value_type;
|
||||
|
||||
RandomAccessIterator end(current), prev(current);
|
||||
const value_type value(*current);
|
||||
|
||||
for(--prev; value < *prev; --end, --prev) // We skip checking for (prev >= first) because quick_sort (our caller) makes this unnecessary.
|
||||
{
|
||||
EASTL_VALIDATE_COMPARE(!(*prev < value)); // Validate that the compare function is sane.
|
||||
*end = *prev;
|
||||
}
|
||||
|
||||
*end = value;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// This function is used by quick_sort and is not intended to be used by itself.
|
||||
// This is because the implementation below makes an assumption about the input
|
||||
// data that quick_sort satisfies but arbitrary data may not.
|
||||
// There is a standalone insertion_sort function.
|
||||
template <typename RandomAccessIterator, typename Compare>
|
||||
inline void insertion_sort_simple(RandomAccessIterator first, RandomAccessIterator last, Compare compare)
|
||||
{
|
||||
for(RandomAccessIterator current = first; current != last; ++current)
|
||||
{
|
||||
typedef typename eastl::iterator_traits<RandomAccessIterator>::value_type value_type;
|
||||
|
||||
RandomAccessIterator end(current), prev(current);
|
||||
const value_type value(*current);
|
||||
|
||||
for(--prev; compare(value, *prev); --end, --prev) // We skip checking for (prev >= first) because quick_sort (our caller) makes this unnecessary.
|
||||
{
|
||||
EASTL_VALIDATE_COMPARE(!compare(*prev, value)); // Validate that the compare function is sane.
|
||||
*end = *prev;
|
||||
}
|
||||
|
||||
*end = value;
|
||||
}
|
||||
}
|
||||
} // namespace Internal
|
||||
|
||||
|
||||
template <typename RandomAccessIterator>
|
||||
inline void partial_sort(RandomAccessIterator first, RandomAccessIterator middle, RandomAccessIterator last)
|
||||
{
|
||||
typedef typename eastl::iterator_traits<RandomAccessIterator>::difference_type difference_type;
|
||||
typedef typename eastl::iterator_traits<RandomAccessIterator>::value_type value_type;
|
||||
|
||||
eastl::make_heap<RandomAccessIterator>(first, middle);
|
||||
|
||||
for(RandomAccessIterator i = middle; i < last; ++i)
|
||||
{
|
||||
if(*i < *first)
|
||||
{
|
||||
EASTL_VALIDATE_COMPARE(!(*first < *i)); // Validate that the compare function is sane.
|
||||
const value_type temp(*i);
|
||||
*i = *first;
|
||||
eastl::adjust_heap<RandomAccessIterator, difference_type, value_type>
|
||||
(first, difference_type(0), difference_type(middle - first), difference_type(0), temp);
|
||||
}
|
||||
}
|
||||
|
||||
eastl::sort_heap<RandomAccessIterator>(first, middle);
|
||||
}
|
||||
|
||||
|
||||
template <typename RandomAccessIterator, typename Compare>
|
||||
inline void partial_sort(RandomAccessIterator first, RandomAccessIterator middle, RandomAccessIterator last, Compare compare)
|
||||
{
|
||||
typedef typename eastl::iterator_traits<RandomAccessIterator>::difference_type difference_type;
|
||||
typedef typename eastl::iterator_traits<RandomAccessIterator>::value_type value_type;
|
||||
|
||||
eastl::make_heap<RandomAccessIterator, Compare>(first, middle, compare);
|
||||
|
||||
for(RandomAccessIterator i = middle; i < last; ++i)
|
||||
{
|
||||
if(compare(*i, *first))
|
||||
{
|
||||
EASTL_VALIDATE_COMPARE(!compare(*first, *i)); // Validate that the compare function is sane.
|
||||
const value_type temp(*i);
|
||||
*i = *first;
|
||||
eastl::adjust_heap<RandomAccessIterator, difference_type, value_type, Compare>
|
||||
(first, difference_type(0), difference_type(middle - first), difference_type(0), temp, compare);
|
||||
}
|
||||
}
|
||||
|
||||
eastl::sort_heap<RandomAccessIterator, Compare>(first, middle, compare);
|
||||
}
|
||||
|
||||
|
||||
template<typename RandomAccessIterator>
|
||||
inline void nth_element(RandomAccessIterator first, RandomAccessIterator nth, RandomAccessIterator last)
|
||||
{
|
||||
typedef typename iterator_traits<RandomAccessIterator>::value_type value_type;
|
||||
|
||||
while((last - first) > 5)
|
||||
{
|
||||
const value_type midValue(eastl::median<value_type>(*first, *(first + (last - first) / 2), *(last - 1)));
|
||||
const RandomAccessIterator midPos(eastl::get_partition<RandomAccessIterator, value_type>(first, last, midValue));
|
||||
|
||||
if(midPos <= nth)
|
||||
first = midPos;
|
||||
else
|
||||
last = midPos;
|
||||
}
|
||||
|
||||
eastl::insertion_sort<RandomAccessIterator>(first, last);
|
||||
}
|
||||
|
||||
|
||||
template<typename RandomAccessIterator, typename Compare>
|
||||
inline void nth_element(RandomAccessIterator first, RandomAccessIterator nth, RandomAccessIterator last, Compare compare)
|
||||
{
|
||||
typedef typename iterator_traits<RandomAccessIterator>::value_type value_type;
|
||||
|
||||
while((last - first) > 5)
|
||||
{
|
||||
const value_type midValue(eastl::median<value_type, Compare>(*first, *(first + (last - first) / 2), *(last - 1), compare));
|
||||
const RandomAccessIterator midPos(eastl::get_partition<RandomAccessIterator, value_type, Compare>(first, last, midValue, compare));
|
||||
|
||||
if(midPos <= nth)
|
||||
first = midPos;
|
||||
else
|
||||
last = midPos;
|
||||
}
|
||||
|
||||
eastl::insertion_sort<RandomAccessIterator, Compare>(first, last, compare);
|
||||
}
|
||||
|
||||
|
||||
template <typename RandomAccessIterator, typename Size>
|
||||
inline void quick_sort_impl(RandomAccessIterator first, RandomAccessIterator last, Size kRecursionCount)
|
||||
{
|
||||
typedef typename iterator_traits<RandomAccessIterator>::value_type value_type;
|
||||
|
||||
while(((last - first) > kQuickSortLimit) && (kRecursionCount > 0))
|
||||
{
|
||||
const RandomAccessIterator position(eastl::get_partition<RandomAccessIterator, value_type>(first, last, eastl::median<value_type>(*first, *(first + (last - first) / 2), *(last - 1))));
|
||||
|
||||
eastl::quick_sort_impl<RandomAccessIterator, Size>(position, last, --kRecursionCount);
|
||||
last = position;
|
||||
}
|
||||
|
||||
if(kRecursionCount == 0)
|
||||
eastl::partial_sort<RandomAccessIterator>(first, last, last);
|
||||
}
|
||||
|
||||
|
||||
template <typename RandomAccessIterator, typename Size, typename Compare>
|
||||
inline void quick_sort_impl(RandomAccessIterator first, RandomAccessIterator last, Size kRecursionCount, Compare compare)
|
||||
{
|
||||
typedef typename iterator_traits<RandomAccessIterator>::value_type value_type;
|
||||
|
||||
while(((last - first) > kQuickSortLimit) && (kRecursionCount > 0))
|
||||
{
|
||||
const RandomAccessIterator position(eastl::get_partition<RandomAccessIterator, value_type, Compare>(first, last, eastl::median<value_type, Compare>(*first, *(first + (last - first) / 2), *(last - 1), compare), compare));
|
||||
|
||||
eastl::quick_sort_impl<RandomAccessIterator, Size, Compare>(position, last, --kRecursionCount, compare);
|
||||
last = position;
|
||||
}
|
||||
|
||||
if(kRecursionCount == 0)
|
||||
eastl::partial_sort<RandomAccessIterator, Compare>(first, last, last, compare);
|
||||
}
|
||||
|
||||
|
||||
/// quick_sort
|
||||
///
|
||||
/// quick_sort sorts the elements in [first, last) into ascending order,
|
||||
/// meaning that if i and j are any two valid iterators in [first, last)
|
||||
/// such that i precedes j, then *j is not less than *i. quick_sort is not
|
||||
/// guaranteed to be stable. That is, suppose that *i and *j are equivalent:
|
||||
/// neither one is less than the other. It is not guaranteed that the
|
||||
/// relative order of these two elements will be preserved by sort.
|
||||
///
|
||||
/// We implement the "introspective" variation of quick-sort. This is
|
||||
/// considered to be the best general-purpose variant, as it avoids
|
||||
/// worst-case behaviour and optimizes the final sorting stage by
|
||||
/// switching to an insertion sort.
|
||||
///
|
||||
template <typename RandomAccessIterator>
|
||||
void quick_sort(RandomAccessIterator first, RandomAccessIterator last)
|
||||
{
|
||||
typedef typename eastl::iterator_traits<RandomAccessIterator>::difference_type difference_type;
|
||||
|
||||
if(first != last)
|
||||
{
|
||||
eastl::quick_sort_impl<RandomAccessIterator, difference_type>(first, last, 2 * Internal::Log2(last - first));
|
||||
|
||||
if((last - first) > (difference_type)kQuickSortLimit)
|
||||
{
|
||||
eastl::insertion_sort<RandomAccessIterator>(first, first + kQuickSortLimit);
|
||||
eastl::Internal::insertion_sort_simple<RandomAccessIterator>(first + kQuickSortLimit, last);
|
||||
}
|
||||
else
|
||||
eastl::insertion_sort<RandomAccessIterator>(first, last);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template <typename RandomAccessIterator, typename Compare>
|
||||
void quick_sort(RandomAccessIterator first, RandomAccessIterator last, Compare compare)
|
||||
{
|
||||
typedef typename eastl::iterator_traits<RandomAccessIterator>::difference_type difference_type;
|
||||
|
||||
if(first != last)
|
||||
{
|
||||
eastl::quick_sort_impl<RandomAccessIterator, difference_type, Compare>(first, last, 2 * Internal::Log2(last - first), compare);
|
||||
|
||||
if((last - first) > (difference_type)kQuickSortLimit)
|
||||
{
|
||||
eastl::insertion_sort<RandomAccessIterator, Compare>(first, first + kQuickSortLimit, compare);
|
||||
eastl::Internal::insertion_sort_simple<RandomAccessIterator, Compare>(first + kQuickSortLimit, last, compare);
|
||||
}
|
||||
else
|
||||
eastl::insertion_sort<RandomAccessIterator, Compare>(first, last, compare);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// sort
|
||||
///
|
||||
/// We simply use quick_sort. See quick_sort for details.
|
||||
///
|
||||
template <typename RandomAccessIterator>
|
||||
inline void sort(RandomAccessIterator first, RandomAccessIterator last)
|
||||
{
|
||||
eastl::quick_sort<RandomAccessIterator>(first, last);
|
||||
}
|
||||
|
||||
template <typename RandomAccessIterator, typename Compare>
|
||||
inline void sort(RandomAccessIterator first, RandomAccessIterator last, Compare compare)
|
||||
{
|
||||
eastl::quick_sort<RandomAccessIterator, Compare>(first, last, compare);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// stable_sort
|
||||
///
|
||||
/// We simply use merge_sort. See merge_sort for details.
|
||||
/// Beware that the used merge_sort -- and thus stable_sort -- allocates
|
||||
/// memory during execution. Try using merge_sort_buffer if you want
|
||||
/// to avoid memory allocation.
|
||||
///
|
||||
template <typename RandomAccessIterator, typename StrictWeakOrdering>
|
||||
void stable_sort(RandomAccessIterator first, RandomAccessIterator last, StrictWeakOrdering compare)
|
||||
{
|
||||
eastl::merge_sort<RandomAccessIterator, EASTLAllocatorType, StrictWeakOrdering>
|
||||
(first, last, *get_default_allocator(0), compare);
|
||||
}
|
||||
|
||||
template <typename RandomAccessIterator>
|
||||
void stable_sort(RandomAccessIterator first, RandomAccessIterator last)
|
||||
{
|
||||
eastl::merge_sort<RandomAccessIterator, EASTLAllocatorType>
|
||||
(first, last, *get_default_allocator(0));
|
||||
}
|
||||
|
||||
template <typename RandomAccessIterator, typename Allocator, typename StrictWeakOrdering>
|
||||
void stable_sort(RandomAccessIterator first, RandomAccessIterator last, Allocator& allocator, StrictWeakOrdering compare)
|
||||
{
|
||||
eastl::merge_sort<RandomAccessIterator, Allocator, StrictWeakOrdering>(first, last, allocator, compare);
|
||||
}
|
||||
|
||||
// This is not defined because it would cause compiler errors due to conflicts with a version above.
|
||||
//template <typename RandomAccessIterator, typename Allocator>
|
||||
//void stable_sort(RandomAccessIterator first, RandomAccessIterator last, Allocator& allocator)
|
||||
//{
|
||||
// eastl::merge_sort<RandomAccessIterator, Allocator>(first, last, allocator);
|
||||
//}
|
||||
|
||||
} // namespace eastl
|
||||
|
||||
|
||||
#endif // Header include guard
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
3496
lib/eastl/include/EASTL/string.h
Normal file
3496
lib/eastl/include/EASTL/string.h
Normal file
File diff suppressed because it is too large
Load diff
359
lib/eastl/include/EASTL/type_traits.h
Normal file
359
lib/eastl/include/EASTL/type_traits.h
Normal file
|
@ -0,0 +1,359 @@
|
|||
/*
|
||||
Copyright (C) 2009-2010 Electronic Arts, Inc. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
3. Neither the name of Electronic Arts, Inc. ("EA") nor the names of
|
||||
its contributors may be used to endorse or promote products derived
|
||||
from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY ELECTRONIC ARTS AND ITS CONTRIBUTORS "AS IS" AND ANY
|
||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL ELECTRONIC ARTS OR ITS CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// EASTL/type_traits.h
|
||||
//
|
||||
// Copyright (c) 2005, Electronic Arts. All rights reserved.
|
||||
// Written and maintained by Paul Pedriana.
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Specification
|
||||
//
|
||||
// This file implements C++ type traits as proposed by the emerging C++ update
|
||||
// as of May, 2005. This update is known as "Proposed Draft Technical Report
|
||||
// on C++ Library Extensions" and is document number n1745. It can be found
|
||||
// on the Internet as n1745.pdf and as of this writing it is updated every
|
||||
// couple months to reflect current thinking.
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Description
|
||||
//
|
||||
// EASTL includes a fairly serious type traits library that is on par with the
|
||||
// one found in Boost but offers some additional performance-enhancing help as well.
|
||||
// The type_traits library provides information about class types, as opposed to
|
||||
// class instances. For example, the is_integral type trait tells if a type is
|
||||
// one of int, short, long, char, uint64_t, etc.
|
||||
//
|
||||
// There are three primary uses of type traits:
|
||||
// * Allowing for optimized operations on some data types.
|
||||
// * Allowing for different logic pathways based on data types.
|
||||
// * Allowing for compile-type assertions about data type expectations.
|
||||
//
|
||||
// Most of the type traits are automatically detected and implemented by the compiler.
|
||||
// However, EASTL allows for the user to explicitly give the compiler hints about
|
||||
// type traits that the compiler cannot know, via the EASTL_DECLARE declarations.
|
||||
// If the user has a class that is relocatable (i.e. can safely use memcpy to copy values),
|
||||
// the user can use the EASTL_DECLARE_TRIVIAL_RELOCATE declaration to tell the compiler
|
||||
// that the class can be copied via memcpy. This will automatically significantly speed
|
||||
// up some containers and algorithms that use that class.
|
||||
//
|
||||
// Here is an example of using type traits to tell if a value is a floating point
|
||||
// value or not:
|
||||
//
|
||||
// template <typename T>
|
||||
// DoSomething(T t) {
|
||||
// assert(is_floating_point<T>::value);
|
||||
// }
|
||||
//
|
||||
// Here is an example of declaring a class as relocatable and using it in a vector.
|
||||
//
|
||||
// EASTL_DECLARE_TRIVIAL_RELOCATE(Widget); // Usually you put this at the Widget class declaration.
|
||||
// vector<Widget> wVector;
|
||||
// wVector.erase(wVector.begin()); // This operation will be optimized via using memcpy.
|
||||
//
|
||||
// The following is a full list of the currently recognized type traits. Most of these
|
||||
// are implemented as of this writing, but if there is one that is missing, feel free
|
||||
// to contact the maintainer of this library and request that it be completed.
|
||||
//
|
||||
// Trait Description
|
||||
// ------------------------------------------------------------------------------
|
||||
// is_void T is void or a cv-qualified (const/void-qualified) void.
|
||||
// is_integral T is an integral type.
|
||||
// is_floating_point T is a floating point type.
|
||||
// is_arithmetic T is an arithmetic type (integral or floating point).
|
||||
// is_fundamental T is a fundamental type (void, integral, or floating point).
|
||||
// is_const T is const-qualified.
|
||||
// is_volatile T is volatile-qualified.
|
||||
// is_abstract T is an abstract class.
|
||||
// is_signed T is a signed integral type.
|
||||
// is_unsigned T is an unsigned integral type.
|
||||
// is_array T is an array type. The templated array container is not an array type.
|
||||
// is_pointer T is a pointer type. Includes function pointers, but not pointers to (data or function) members.
|
||||
// is_reference T is a reference type. Includes references to functions.
|
||||
// is_member_object_pointer T is a pointer to data member.
|
||||
// is_member_function_pointer T is a pointer to member function.
|
||||
// is_member_pointer T is a pointer to a member or member function.
|
||||
// is_enum T is an enumeration type.
|
||||
// is_union T is a union type.
|
||||
// is_class T is a class type but not a union type.
|
||||
// is_polymorphic T is a polymorphic class.
|
||||
// is_function T is a function type.
|
||||
// is_object T is an object type.
|
||||
// is_scalar T is a scalar type (arithmetic, enum, pointer, member_pointer)
|
||||
// is_compound T is a compound type (anything but fundamental).
|
||||
// is_same T and U name the same type.
|
||||
// is_convertible An imaginary lvalue of type From is implicitly convertible to type To. Special conversions involving string-literals and null-pointer constants are not considered. No function-parameter adjustments are made to type To when determining whether From is convertible to To; this implies that if type To is a function type or an array type, then the condition is false.
|
||||
// is_base_of Base is a base class of Derived or Base and Derived name the same type.
|
||||
// is_empty T is an empty class.
|
||||
// is_pod T is a POD type.
|
||||
// *is_aligned Defined as true if the type has alignment requirements greater than default alignment, which is taken to be 8.
|
||||
// has_trivial_constructor The default constructor for T is trivial.
|
||||
// has_trivial_copy The copy constructor for T is trivial.
|
||||
// has_trivial_assign The assignment operator for T is trivial.
|
||||
// has_trivial_destructor The destructor for T is trivial.
|
||||
// *has_trivial_relocate T can be moved to a new location via bitwise copy.
|
||||
// has_nothrow_constructor The default constructor for T has an empty exception specification or can otherwise be deduced never to throw an exception.
|
||||
// has_nothrow_copy The copy constructor for T has an empty exception specification or can otherwise be deduced never to throw an exception.
|
||||
// has_nothrow_assign The assignment operator for T has an empty exception specification or can otherwise be deduced never to throw an exception.
|
||||
// has_virtual_destructor T has a virtual destructor.
|
||||
// alignment_of An integer value representing the number of bytes of the alignment of objects of type T; an object of type T may be allocated at an address that is a multiple of its alignment.
|
||||
// rank An integer value representing the rank of objects of type T. The term 'rank' here is used to describe the number of dimensions of an array type.
|
||||
// extent An integer value representing the extent (dimension) of the I'th bound of objects of type T. If the type T is not an array type, has rank of less than I, or if I == 0 and T is of type 'array of unknown bound of U,' then value shall evaluate to zero; otherwise value shall evaluate to the number of elements in the I'th array bound of T. The term 'extent' here is used to describe the number of elements in an array type.
|
||||
// remove_const The member typedef type shall be the same as T except that any top level const-qualifier has been removed. remove_const<const volatile int>::type evaluates to volatile int, whereas remove_const<const int*> is const int*.
|
||||
//
|
||||
// * is_aligned is not found in Boost nor the C++ standard update proposal.
|
||||
//
|
||||
// * has_trivial_relocate is not found in Boost nor the C++ standard update proposal.
|
||||
// However, it is very useful in allowing for the generation of optimized object
|
||||
// moving operations. It is similar to the is_pod type trait, but goes further and
|
||||
// allows non-pod classes to be categorized as relocatable. Such categorization is
|
||||
// something that no compiler can do, as only the user can know if it is such.
|
||||
// Thus EASTL_DECLARE_TRIVIAL_RELOCATE is provided to allow the user to give
|
||||
// the compiler a hint.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Requirements
|
||||
//
|
||||
// As of this writing (5/2005), type_traits here requires a well-conforming
|
||||
// C++ compiler with respect to template metaprogramming. To use this library
|
||||
// you need to have at least one of the following:
|
||||
// MSVC++ 7.1 (includes Win32, XBox 360, Win64, and WinCE platforms)
|
||||
// GCC 3.2 (includes Playstation 3, and Linux platforms)
|
||||
// Metrowerks 8.0 (incluees Playstation 3, Windows, and other platforms)
|
||||
// SN Systems (not the GCC 2.95-based compilers)
|
||||
// EDG (includes any compiler with EDG as a back-end, such as the Intel compiler)
|
||||
// Comeau (this is a C++ to C generator)
|
||||
//
|
||||
// It may be useful to list the compilers/platforms the current version of
|
||||
// type_traits doesn't support:
|
||||
// Borland C++ (it simply has too many bugs with respect to templates).
|
||||
// GCC 2.96 With a little effort, type_traits can probably be made to work with this compiler.
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Implementation
|
||||
//
|
||||
// The implementation here is almost entirely based on template metaprogramming.
|
||||
// This is whereby you use the compiler's template functionality to define types
|
||||
// and values and make compilation decisions based on template declarations.
|
||||
// Many of the algorithms here are similar to those found in books such as
|
||||
// "Modern C++ Design" and C++ libraries such as Boost. The implementations here
|
||||
// are simpler and more straightforward than those found in some libraries, due
|
||||
// largely to our assumption that the compiler is good at donig template programming.
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
#ifndef EASTL_TYPE_TRAITS_H
|
||||
#define EASTL_TYPE_TRAITS_H
|
||||
|
||||
|
||||
|
||||
#include <EASTL/internal/config.h>
|
||||
#include <stddef.h> // Is needed for size_t usage by some traits.
|
||||
|
||||
|
||||
|
||||
namespace eastl
|
||||
{
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// integral_constant
|
||||
//
|
||||
// This is the base class for various type traits, as defined by the proposed
|
||||
// C++ standard. This is essentially a utility base class for defining properties
|
||||
// as both class constants (value) and as types (type).
|
||||
//
|
||||
template <typename T, T v>
|
||||
struct integral_constant
|
||||
{
|
||||
static const T value = v;
|
||||
typedef T value_type;
|
||||
typedef integral_constant<T, v> type;
|
||||
};
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// true_type / false_type
|
||||
//
|
||||
// These are commonly used types in the implementation of type_traits.
|
||||
// Other integral constant types can be defined, such as those based on int.
|
||||
//
|
||||
typedef integral_constant<bool, true> true_type;
|
||||
typedef integral_constant<bool, false> false_type;
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// yes_type / no_type
|
||||
//
|
||||
// These are used as a utility to differentiate between two things.
|
||||
//
|
||||
typedef char yes_type; // sizeof(yes_type) == 1
|
||||
struct no_type { char padding[8]; }; // sizeof(no_type) != 1
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// type_select
|
||||
//
|
||||
// This is used to declare a type from one of two type options.
|
||||
// The result is based on the condition type. This has certain uses
|
||||
// in template metaprogramming.
|
||||
//
|
||||
// Example usage:
|
||||
// typedef ChosenType = type_select<is_integral<SomeType>::value, ChoiceAType, ChoiceBType>::type;
|
||||
//
|
||||
template <bool bCondition, class ConditionIsTrueType, class ConditionIsFalseType>
|
||||
struct type_select { typedef ConditionIsTrueType type; };
|
||||
|
||||
template <typename ConditionIsTrueType, class ConditionIsFalseType>
|
||||
struct type_select<false, ConditionIsTrueType, ConditionIsFalseType> { typedef ConditionIsFalseType type; };
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// type_or
|
||||
//
|
||||
// This is a utility class for creating composite type traits.
|
||||
//
|
||||
template <bool b1, bool b2, bool b3 = false, bool b4 = false, bool b5 = false>
|
||||
struct type_or;
|
||||
|
||||
template <bool b1, bool b2, bool b3, bool b4, bool b5>
|
||||
struct type_or { static const bool value = true; };
|
||||
|
||||
template <>
|
||||
struct type_or<false, false, false, false, false> { static const bool value = false; };
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// type_and
|
||||
//
|
||||
// This is a utility class for creating composite type traits.
|
||||
//
|
||||
template <bool b1, bool b2, bool b3 = true, bool b4 = true, bool b5 = true>
|
||||
struct type_and;
|
||||
|
||||
template <bool b1, bool b2, bool b3, bool b4, bool b5>
|
||||
struct type_and{ static const bool value = false; };
|
||||
|
||||
template <>
|
||||
struct type_and<true, true, true, true, true>{ static const bool value = true; };
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// type_equal
|
||||
//
|
||||
// This is a utility class for creating composite type traits.
|
||||
//
|
||||
template <int b1, int b2>
|
||||
struct type_equal{ static const bool value = (b1 == b2); };
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// type_not_equal
|
||||
//
|
||||
// This is a utility class for creating composite type traits.
|
||||
//
|
||||
template <int b1, int b2>
|
||||
struct type_not_equal{ static const bool value = (b1 != b2); };
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// type_not
|
||||
//
|
||||
// This is a utility class for creating composite type traits.
|
||||
//
|
||||
template <bool b>
|
||||
struct type_not{ static const bool value = true; };
|
||||
|
||||
template <>
|
||||
struct type_not<true>{ static const bool value = false; };
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// empty
|
||||
//
|
||||
template <typename T>
|
||||
struct empty{ };
|
||||
|
||||
|
||||
} // namespace eastl
|
||||
|
||||
|
||||
// The following files implement the type traits themselves.
|
||||
#if defined(__GNUC__) && (__GNUC__ <= 2)
|
||||
#include <EASTL/internal/compat/type_fundamental.h>
|
||||
#include <EASTL/internal/compat/type_transformations.h>
|
||||
#include <EASTL/internal/compat/type_properties.h>
|
||||
#include <EASTL/internal/compat/type_compound.h>
|
||||
#include <EASTL/internal/compat/type_pod.h>
|
||||
#else
|
||||
#include <EASTL/internal/type_fundamental.h>
|
||||
#include <EASTL/internal/type_transformations.h>
|
||||
#include <EASTL/internal/type_properties.h>
|
||||
#include <EASTL/internal/type_compound.h>
|
||||
#include <EASTL/internal/type_pod.h>
|
||||
#endif
|
||||
|
||||
|
||||
#endif // Header include guard
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
312
lib/eastl/include/EASTL/utility.h
Normal file
312
lib/eastl/include/EASTL/utility.h
Normal file
|
@ -0,0 +1,312 @@
|
|||
/*
|
||||
Copyright (C) 2005,2009-2010 Electronic Arts, Inc. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
3. Neither the name of Electronic Arts, Inc. ("EA") nor the names of
|
||||
its contributors may be used to endorse or promote products derived
|
||||
from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY ELECTRONIC ARTS AND ITS CONTRIBUTORS "AS IS" AND ANY
|
||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL ELECTRONIC ARTS OR ITS CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// EASTL/utility.h
|
||||
// Written and maintained by Paul Pedriana - 2005.
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
#ifndef EASTL_UTILITY_H
|
||||
#define EASTL_UTILITY_H
|
||||
|
||||
|
||||
#include <EASTL/internal/config.h>
|
||||
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(push) // VC++ generates a bogus warning that you cannot code away.
|
||||
#pragma warning(disable: 4619) // There is no warning number 'number'.
|
||||
#pragma warning(disable: 4217) // Member template functions cannot be used for copy-assignment or copy-construction.
|
||||
#pragma warning(disable: 4512) // 'class' : assignment operator could not be generated. // This disabling would best be put elsewhere.
|
||||
#endif
|
||||
|
||||
|
||||
namespace eastl
|
||||
{
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
/// rel_ops
|
||||
///
|
||||
/// rel_ops allow the automatic generation of operators !=, >, <=, >= from
|
||||
/// just operators == and <. These are intentionally in the rel_ops namespace
|
||||
/// so that they don't conflict with other similar operators. To use these
|
||||
/// operators, add "using namespace std::rel_ops;" to an appropriate place in
|
||||
/// your code, usually right in the function that you need them to work.
|
||||
/// In fact, you will very likely have collision problems if you put such
|
||||
/// using statements anywhere other than in the .cpp file like so and may
|
||||
/// also have collisions when you do, as the using statement will affect all
|
||||
/// code in the module. You need to be careful about use of rel_ops.
|
||||
///
|
||||
namespace rel_ops
|
||||
{
|
||||
template <typename T>
|
||||
inline bool operator!=(const T& x, const T& y)
|
||||
{ return !(x == y); }
|
||||
|
||||
template <typename T>
|
||||
inline bool operator>(const T& x, const T& y)
|
||||
{ return (y < x); }
|
||||
|
||||
template <typename T>
|
||||
inline bool operator<=(const T& x, const T& y)
|
||||
{ return !(y < x); }
|
||||
|
||||
template <typename T>
|
||||
inline bool operator>=(const T& x, const T& y)
|
||||
{ return !(x < y); }
|
||||
}
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
/// pair
|
||||
///
|
||||
/// Implements a simple pair, just like the C++ std::pair.
|
||||
///
|
||||
template <typename T1, typename T2>
|
||||
struct pair
|
||||
{
|
||||
typedef T1 first_type;
|
||||
typedef T2 second_type;
|
||||
|
||||
T1 first;
|
||||
T2 second;
|
||||
|
||||
pair();
|
||||
pair(const T1& x);
|
||||
pair(const T1& x, const T2& y);
|
||||
|
||||
template <typename U, typename V>
|
||||
pair(const pair<U, V>& p);
|
||||
|
||||
// pair(const pair& p); // Not necessary, as default version is OK.
|
||||
// pair& operator=(const pair& p); // Not necessary, as default version is OK.
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
/// use_self
|
||||
///
|
||||
/// operator()(x) simply returns x. Used in sets, as opposed to maps.
|
||||
/// This is a template policy implementation; it is an alternative to
|
||||
/// the use_first template implementation.
|
||||
///
|
||||
/// The existance of use_self may seem odd, given that it does nothing,
|
||||
/// but these kinds of things are useful, virtually required, for optimal
|
||||
/// generic programming.
|
||||
///
|
||||
template <typename T>
|
||||
struct use_self // : public unary_function<T, T> // Perhaps we want to make it a subclass of unary_function.
|
||||
{
|
||||
typedef T result_type;
|
||||
|
||||
const T& operator()(const T& x) const
|
||||
{ return x; }
|
||||
};
|
||||
|
||||
/// use_first
|
||||
///
|
||||
/// operator()(x) simply returns x.first. Used in maps, as opposed to sets.
|
||||
/// This is a template policy implementation; it is an alternative to
|
||||
/// the use_self template implementation. This is the same thing as the
|
||||
/// SGI SGL select1st utility.
|
||||
///
|
||||
template <typename Pair>
|
||||
struct use_first // : public unary_function<Pair, typename Pair::first_type> // Perhaps we want to make it a subclass of unary_function.
|
||||
{
|
||||
typedef typename Pair::first_type result_type;
|
||||
|
||||
const result_type& operator()(const Pair& x) const
|
||||
{ return x.first; }
|
||||
};
|
||||
|
||||
/// use_second
|
||||
///
|
||||
/// operator()(x) simply returns x.second.
|
||||
/// This is the same thing as the SGI SGL select2nd utility
|
||||
///
|
||||
template <typename Pair>
|
||||
struct use_second // : public unary_function<Pair, typename Pair::second_type> // Perhaps we want to make it a subclass of unary_function.
|
||||
{
|
||||
typedef typename Pair::second_type result_type;
|
||||
|
||||
const result_type& operator()(const Pair& x) const
|
||||
{ return x.second; }
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// pair
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <typename T1, typename T2>
|
||||
inline pair<T1, T2>::pair()
|
||||
: first(), second()
|
||||
{
|
||||
// Empty
|
||||
}
|
||||
|
||||
|
||||
template <typename T1, typename T2>
|
||||
inline pair<T1, T2>::pair(const T1& x)
|
||||
: first(x), second()
|
||||
{
|
||||
// Empty
|
||||
}
|
||||
|
||||
|
||||
template <typename T1, typename T2>
|
||||
inline pair<T1, T2>::pair(const T1& x, const T2& y)
|
||||
: first(x), second(y)
|
||||
{
|
||||
// Empty
|
||||
}
|
||||
|
||||
|
||||
template <typename T1, typename T2>
|
||||
template <typename U, typename V>
|
||||
inline pair<T1, T2>::pair(const pair<U, V>& p)
|
||||
: first(p.first), second(p.second)
|
||||
{
|
||||
// Empty
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// global operators
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <typename T1, typename T2>
|
||||
inline bool operator==(const pair<T1, T2>& a, const pair<T1, T2>& b)
|
||||
{
|
||||
return ((a.first == b.first) && (a.second == b.second));
|
||||
}
|
||||
|
||||
|
||||
template <typename T1, typename T2>
|
||||
inline bool operator<(const pair<T1, T2>& a, const pair<T1, T2>& b)
|
||||
{
|
||||
// Note that we use only operator < in this expression. Otherwise we could
|
||||
// use the simpler: return (a.m1 == b.m1) ? (a.m2 < b.m2) : (a.m1 < b.m1);
|
||||
// The user can write a specialization for this operator to get around this
|
||||
// in cases where the highest performance is required.
|
||||
return ((a.first < b.first) || (!(b.first < a.first) && (a.second < b.second)));
|
||||
}
|
||||
|
||||
|
||||
template <typename T1, typename T2>
|
||||
inline bool operator!=(const pair<T1, T2>& a, const pair<T1, T2>& b)
|
||||
{
|
||||
return !(a == b);
|
||||
}
|
||||
|
||||
|
||||
template <typename T1, typename T2>
|
||||
inline bool operator>(const pair<T1, T2>& a, const pair<T1, T2>& b)
|
||||
{
|
||||
return b < a;
|
||||
}
|
||||
|
||||
|
||||
template <typename T1, typename T2>
|
||||
inline bool operator>=(const pair<T1, T2>& a, const pair<T1, T2>& b)
|
||||
{
|
||||
return !(a < b);
|
||||
}
|
||||
|
||||
|
||||
template <typename T1, typename T2>
|
||||
inline bool operator<=(const pair<T1, T2>& a, const pair<T1, T2>& b)
|
||||
{
|
||||
return !(b < a);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
/// make_pair / make_pair_ref
|
||||
///
|
||||
/// make_pair is the same as std::make_pair specified by the C++ standard.
|
||||
/// If you look at the C++ standard, you'll see that it specifies T& instead of T.
|
||||
/// However, it has been determined that the C++ standard is incorrect and has
|
||||
/// flagged it as a defect (http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#181).
|
||||
/// In case you feel that you want a more efficient version that uses references,
|
||||
/// we provide the make_pair_ref function below.
|
||||
///
|
||||
/// Note: You don't need to use make_pair in order to make a pair. The following
|
||||
/// code is equivalent, and the latter avoids one more level of inlining:
|
||||
/// return make_pair(charPtr, charPtr);
|
||||
/// return pair<char*, char*>(charPtr, charPtr);
|
||||
///
|
||||
template <typename T1, typename T2>
|
||||
inline pair<T1, T2> make_pair(T1 a, T2 b)
|
||||
{
|
||||
return pair<T1, T2>(a, b);
|
||||
}
|
||||
|
||||
|
||||
template <typename T1, typename T2>
|
||||
inline pair<T1, T2> make_pair_ref(const T1& a, const T2& b)
|
||||
{
|
||||
return pair<T1, T2>(a, b);
|
||||
}
|
||||
|
||||
|
||||
} // namespace eastl
|
||||
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
|
||||
#endif // Header include guard
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
1618
lib/eastl/include/EASTL/vector.h
Normal file
1618
lib/eastl/include/EASTL/vector.h
Normal file
File diff suppressed because it is too large
Load diff
248
lib/eastl/include/EASTL/vector_map.h
Normal file
248
lib/eastl/include/EASTL/vector_map.h
Normal file
|
@ -0,0 +1,248 @@
|
|||
#ifndef EASTL_VECTOR_MAP_H
|
||||
#define EASTL_VECTOR_MAP_H
|
||||
|
||||
#include <EASTL/internal/config.h>
|
||||
|
||||
#include <EASTL/algorithm.h>
|
||||
#include <EASTL/allocator.h>
|
||||
#include <EASTL/functional.h>
|
||||
#include <EASTL/iterator.h>
|
||||
#include <EASTL/map.h>
|
||||
#include <EASTL/sort.h>
|
||||
#include <EASTL/utility.h>
|
||||
#include <EASTL/vector.h>
|
||||
|
||||
|
||||
namespace eastl {
|
||||
|
||||
namespace detail {
|
||||
|
||||
template<class Pair, class Compare>
|
||||
struct compare_impl {
|
||||
typedef Pair pair_type;
|
||||
typedef typename pair_type::first_type first_argument_type;
|
||||
|
||||
compare_impl() {}
|
||||
compare_impl(Compare const& src) : m_cmp(src) {}
|
||||
|
||||
bool operator()(first_argument_type const& lhs, first_argument_type const& rhs) const
|
||||
{ return Compare()(lhs, rhs); }
|
||||
bool operator()(pair_type const& lhs, pair_type const& rhs) const
|
||||
{ return operator()(lhs.first, rhs.first); }
|
||||
bool operator()(pair_type const& lhs, first_argument_type const& rhs) const
|
||||
{ return operator()(lhs.first, rhs); }
|
||||
bool operator()(first_argument_type const& lhs, pair_type const& rhs) const
|
||||
{ return operator()(lhs, rhs.first); }
|
||||
|
||||
operator Compare() const { return m_cmp; }
|
||||
void swap(compare_impl& rhs) {
|
||||
using ::eastl::swap;
|
||||
swap(m_cmp, rhs.m_cmp);
|
||||
}
|
||||
private:
|
||||
Compare m_cmp;
|
||||
}; // struct compare_impl
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template<class K, class V, class C = ::eastl::less<K>, class A = EASTLAllocatorType>
|
||||
class vector_map {
|
||||
public:
|
||||
typedef K key_type;
|
||||
typedef V mapped_type;
|
||||
typedef ::eastl::pair<key_type, mapped_type> value_type;
|
||||
typedef C key_compare;
|
||||
typedef A allocator_type;
|
||||
|
||||
typedef ::eastl::vector<value_type, allocator_type> base_type;
|
||||
private:
|
||||
typedef detail::compare_impl<key_type, key_compare> compare_impl_type;
|
||||
|
||||
base_type m_base;
|
||||
detail::compare_impl<typename base_type::value_type, key_compare> m_cmp;
|
||||
public:
|
||||
typedef typename base_type::iterator iterator;
|
||||
typedef typename base_type::const_iterator const_iterator;
|
||||
typedef typename base_type::reverse_iterator reverse_iterator;
|
||||
typedef typename base_type::const_reverse_iterator const_reverse_iterator;
|
||||
|
||||
typedef typename base_type::size_type size_type;
|
||||
typedef typename base_type::difference_type difference_type;
|
||||
|
||||
typedef typename base_type::reference reference;
|
||||
typedef typename base_type::const_reference const_reference;
|
||||
typedef typename base_type::pointer pointer;
|
||||
typedef typename base_type::const_pointer const_pointer;;
|
||||
|
||||
static const size_type kMaxSize = base_type::kMaxSize;
|
||||
|
||||
class value_compare {
|
||||
friend class vector_map;
|
||||
key_compare const m_cmp;
|
||||
protected:
|
||||
value_compare(key_compare pred) : m_cmp(pred) {}
|
||||
public:
|
||||
bool operator()(value_type const& lhs, value_type const& rhs) const
|
||||
{ return m_cmp(lhs.first, rhs.first); }
|
||||
}; // struct value_compare
|
||||
|
||||
explicit vector_map(key_compare const& cmp = key_compare(), allocator_type const& alloc = EASTL_VECTOR_DEFAULT_ALLOCATOR)
|
||||
: m_base(alloc), m_cmp(cmp) {}
|
||||
template<class InputIterator>
|
||||
vector_map(InputIterator first, InputIterator last,
|
||||
key_compare const& cmp = key_compare(),
|
||||
allocator_type const& alloc = EASTL_VECTOR_DEFAULT_ALLOCATOR)
|
||||
: m_base(alloc), m_cmp(cmp)
|
||||
{
|
||||
::eastl::map<key_type, mapped_type, key_compare, allocator_type> const tmp(first, last);
|
||||
m_base.reserve(tmp.size());
|
||||
::eastl::copy(tmp.begin(), tmp.end(), ::eastl::back_inserter(m_base));
|
||||
}
|
||||
|
||||
vector_map& operator =(vector_map const& rhs) {
|
||||
vector_map(rhs).swap(*this);
|
||||
return *this;
|
||||
}
|
||||
|
||||
iterator begin() { return m_base.begin(); }
|
||||
iterator end() { return m_base.end(); }
|
||||
reverse_iterator rbegin() { return m_base.rbegin(); }
|
||||
reverse_iterator rend() { return m_base.rend(); }
|
||||
|
||||
const_iterator begin() const { return m_base.begin(); }
|
||||
const_iterator end() const { return m_base.end(); }
|
||||
const_reverse_iterator rbegin() const { return m_base.rbegin(); }
|
||||
const_reverse_iterator rend() const { return m_base.rend(); }
|
||||
|
||||
void clear() { m_base.clear(); }
|
||||
|
||||
bool empty() const { return m_base.empty(); }
|
||||
size_type size() const { return m_base.size(); }
|
||||
size_type max_size() { return base_type::kMaxSize; }
|
||||
|
||||
mapped_type& operator[](key_type const& key) {
|
||||
return insert(value_type(key, mapped_type())).first->second;
|
||||
}
|
||||
|
||||
::eastl::pair<iterator, bool> insert(value_type const& val) {
|
||||
iterator const i(lower_bound(val.first));
|
||||
|
||||
return (i == end() || m_cmp(val.first, i->first))
|
||||
? ::eastl::make_pair(m_base.insert(i, val), true)
|
||||
: ::eastl::make_pair(i, false)
|
||||
;
|
||||
}
|
||||
iterator insert(iterator const pos, value_type const& val) {
|
||||
return
|
||||
((pos == begin() || m_cmp(*(pos-1), val)) &&
|
||||
(pos == end() || m_cmp(val, *pos)))
|
||||
? m_base.insert(pos, val)
|
||||
: insert(val).first
|
||||
;
|
||||
}
|
||||
template<class InputIterator>
|
||||
void insert(InputIterator first, InputIterator const last)
|
||||
{ for(; first != last; ++first) insert(*first); }
|
||||
|
||||
void erase(iterator const pos) { m_base.erase(pos); }
|
||||
void erase(iterator const first, iterator const last)
|
||||
{ m_base.erase(first, last); }
|
||||
size_type erase(key_type const& k) {
|
||||
iterator const i(find(k));
|
||||
if(i == end()) return 0;
|
||||
else { erase(i); return 1; }
|
||||
}
|
||||
|
||||
void swap(vector_map& other) {
|
||||
m_base.swap(other.m_base);
|
||||
m_cmp.swap(other.m_cmp);
|
||||
}
|
||||
|
||||
allocator_type& get_allocator() { return m_base.get_allocator(); }
|
||||
void set_allocator(allocator_type const& alloc) { m_base.set_allocator(alloc); }
|
||||
|
||||
key_compare key_comp() const { return static_cast<key_compare>(m_cmp); }
|
||||
value_compare value_comp() const { return value_compare(m_cmp); }
|
||||
|
||||
iterator find(key_type const& k) {
|
||||
iterator const i(lower_bound(k));
|
||||
return (i != end() && m_cmp(k, i->first))? end() : i;
|
||||
}
|
||||
const_iterator find(key_type const& k) const {
|
||||
const_iterator const i(lower_bound(k));
|
||||
return (i != end() && m_cmp(k, i->first))? end() : i;
|
||||
}
|
||||
size_type count(key_type const& k) const { return find(k) != end()? 1 : 0; }
|
||||
iterator lower_bound(key_type const& k) {
|
||||
return ::eastl::lower_bound(begin(), end(), k, m_cmp);
|
||||
}
|
||||
const_iterator lower_bound(key_type const& k) const {
|
||||
return ::eastl::lower_bound(begin(), end(), k, m_cmp);
|
||||
}
|
||||
iterator upper_bound(key_type const& k) {
|
||||
return ::eastl::upper_bound(begin(), end(), k, m_cmp);
|
||||
}
|
||||
const_iterator upper_bound(key_type const& k) const {
|
||||
return ::eastl::upper_bound(begin(), end(), k, m_cmp);
|
||||
}
|
||||
|
||||
::eastl::pair<iterator, iterator> equal_range(key_type const& k) {
|
||||
return ::eastl::equal_range(begin(), end(), k, m_cmp);
|
||||
}
|
||||
::eastl::pair<const_iterator, const_iterator> equal_range(key_type const& k) const {
|
||||
return ::eastl::equal_range(begin(), end(), k, m_cmp);
|
||||
}
|
||||
|
||||
template<class Key, class T, class Compare, class Allocator>
|
||||
friend bool operator==(vector_map<Key, T, Compare, Allocator> const& lhs,
|
||||
vector_map<Key, T, Compare, Allocator> const& rhs);
|
||||
template<class Key, class T, class Compare, class Allocator>
|
||||
friend bool operator!=(vector_map<Key, T, Compare, Allocator> const& lhs,
|
||||
vector_map<Key, T, Compare, Allocator> const& rhs);
|
||||
template<class Key, class T, class Compare, class Allocator>
|
||||
friend bool operator<(vector_map<Key, T, Compare, Allocator> const& lhs,
|
||||
vector_map<Key, T, Compare, Allocator> const& rhs);
|
||||
template<class Key, class T, class Compare, class Allocator>
|
||||
friend bool operator>(vector_map<Key, T, Compare, Allocator> const& lhs,
|
||||
vector_map<Key, T, Compare, Allocator> const& rhs);
|
||||
template<class Key, class T, class Compare, class Allocator>
|
||||
friend bool operator>=(vector_map<Key, T, Compare, Allocator> const& lhs,
|
||||
vector_map<Key, T, Compare, Allocator> const& rhs);
|
||||
template<class Key, class T, class Compare, class Allocator>
|
||||
friend bool operator<=(vector_map<Key, T, Compare, Allocator> const& lhs,
|
||||
vector_map<Key, T, Compare, Allocator> const& rhs);
|
||||
}; // class vector_map
|
||||
|
||||
template<class Key, class T, class Compare, class Allocator>
|
||||
inline bool operator==(vector_map<Key, T, Compare, Allocator> const& lhs,
|
||||
vector_map<Key, T, Compare, Allocator> const& rhs)
|
||||
{ return lhs.m_base == rhs.m_base; }
|
||||
template<class Key, class T, class Compare, class Allocator>
|
||||
inline bool operator!=(vector_map<Key, T, Compare, Allocator> const& lhs,
|
||||
vector_map<Key, T, Compare, Allocator> const& rhs)
|
||||
{ return lhs.m_base != rhs.m_base; }
|
||||
template<class Key, class T, class Compare, class Allocator>
|
||||
inline bool operator<(vector_map<Key, T, Compare, Allocator> const& lhs,
|
||||
vector_map<Key, T, Compare, Allocator> const& rhs)
|
||||
{ return lhs.m_base < rhs.m_base; }
|
||||
template<class Key, class T, class Compare, class Allocator>
|
||||
inline bool operator>(vector_map<Key, T, Compare, Allocator> const& lhs,
|
||||
vector_map<Key, T, Compare, Allocator> const& rhs)
|
||||
{ return lhs.m_base > rhs.m_base; }
|
||||
template<class Key, class T, class Compare, class Allocator>
|
||||
inline bool operator>=(vector_map<Key, T, Compare, Allocator> const& lhs,
|
||||
vector_map<Key, T, Compare, Allocator> const& rhs)
|
||||
{ return lhs.m_base >= rhs.m_base; }
|
||||
template<class Key, class T, class Compare, class Allocator>
|
||||
inline bool operator<=(vector_map<Key, T, Compare, Allocator> const& lhs,
|
||||
vector_map<Key, T, Compare, Allocator> const& rhs)
|
||||
{ return lhs.m_base <= rhs.m_base; }
|
||||
|
||||
template<class Key, class T, class Compare, class Allocator>
|
||||
void swap(vector_map<Key, T, Compare, Allocator> const& lhs,
|
||||
vector_map<Key, T, Compare, Allocator> const& rhs)
|
||||
{ return lhs.swap(rhs); }
|
||||
|
||||
} // namespace eastl
|
||||
|
||||
#endif // EASTL_VECTOR_MAP_H
|
87
lib/eastl/src/allocator.cpp
Normal file
87
lib/eastl/src/allocator.cpp
Normal file
|
@ -0,0 +1,87 @@
|
|||
/*
|
||||
Copyright (C) 2009-2010 Electronic Arts, Inc. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
3. Neither the name of Electronic Arts, Inc. ("EA") nor the names of
|
||||
its contributors may be used to endorse or promote products derived
|
||||
from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY ELECTRONIC ARTS AND ITS CONTRIBUTORS "AS IS" AND ANY
|
||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL ELECTRONIC ARTS OR ITS CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// EASTL/allocator.cpp
|
||||
//
|
||||
// Copyright (c) 2005, Electronic Arts. All rights reserved.
|
||||
// Written and maintained by Paul Pedriana.
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
#include <EASTL/internal/config.h>
|
||||
#include <EASTL/allocator.h>
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// ReadMe
|
||||
//
|
||||
// This file implements the default application allocator.
|
||||
// You can replace this allocator.cpp file with a different one,
|
||||
// you can define EASTL_USER_DEFINED_ALLOCATOR below to ignore this file,
|
||||
// or you can modify the EASTL config.h file to redefine how allocators work.
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
#ifndef EASTL_USER_DEFINED_ALLOCATOR // If the user hasn't declared that he has defined an allocator implementation elsewhere...
|
||||
|
||||
namespace eastl
|
||||
{
|
||||
|
||||
/// gDefaultAllocator
|
||||
/// Default global allocator instance.
|
||||
EASTL_API allocator gDefaultAllocator;
|
||||
EASTL_API allocator* gpDefaultAllocator = &gDefaultAllocator;
|
||||
|
||||
EASTL_API allocator* GetDefaultAllocator()
|
||||
{
|
||||
return gpDefaultAllocator;
|
||||
}
|
||||
|
||||
EASTL_API allocator* SetDefaultAllocator(allocator* pAllocator)
|
||||
{
|
||||
allocator* const pPrevAllocator = gpDefaultAllocator;
|
||||
gpDefaultAllocator = pAllocator;
|
||||
return pPrevAllocator;
|
||||
}
|
||||
|
||||
} // namespace eastl
|
||||
|
||||
|
||||
#endif // EASTL_USER_DEFINED_ALLOCATOR
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
136
lib/eastl/src/assert.cpp
Normal file
136
lib/eastl/src/assert.cpp
Normal file
|
@ -0,0 +1,136 @@
|
|||
/*
|
||||
Copyright (C) 2009-2010 Electronic Arts, Inc. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
3. Neither the name of Electronic Arts, Inc. ("EA") nor the names of
|
||||
its contributors may be used to endorse or promote products derived
|
||||
from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY ELECTRONIC ARTS AND ITS CONTRIBUTORS "AS IS" AND ANY
|
||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL ELECTRONIC ARTS OR ITS CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// EASTL/assert.cpp
|
||||
//
|
||||
// Copyright (c) 2005, Electronic Arts. All rights reserved.
|
||||
// Written and maintained by Paul Pedriana.
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
#include <EASTL/internal/config.h>
|
||||
#include <EASTL/string.h>
|
||||
#include <EABase/eabase.h>
|
||||
|
||||
#if defined(EA_PLATFORM_MICROSOFT)
|
||||
#pragma warning(push, 0)
|
||||
#if defined _MSC_VER
|
||||
#include <crtdbg.h>
|
||||
#endif
|
||||
#if defined(EA_PLATFORM_WINDOWS)
|
||||
#ifndef WIN32_LEAN_AND_MEAN
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#endif
|
||||
#include <windows.h>
|
||||
#elif defined(EA_PLATFORM_XENON)
|
||||
#include <comdecl.h>
|
||||
#endif
|
||||
#pragma warning(pop)
|
||||
#else
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
namespace eastl
|
||||
{
|
||||
|
||||
/// gpAssertionFailureFunction
|
||||
///
|
||||
/// Global assertion failure function pointer. Set by SetAssertionFailureFunction.
|
||||
///
|
||||
EASTL_API EASTL_AssertionFailureFunction gpAssertionFailureFunction = AssertionFailureFunctionDefault;
|
||||
EASTL_API void* gpAssertionFailureFunctionContext = NULL;
|
||||
|
||||
|
||||
|
||||
/// SetAssertionFailureFunction
|
||||
///
|
||||
/// Sets the function called when an assertion fails. If this function is not called
|
||||
/// by the user, a default function will be used. The user may supply a context parameter
|
||||
/// which will be passed back to the user in the function call. This is typically used
|
||||
/// to store a C++ 'this' pointer, though other things are possible.
|
||||
///
|
||||
/// There is no thread safety here, so the user needs to externally make sure that
|
||||
/// this function is not called in a thread-unsafe way. The easiest way to do this is
|
||||
/// to just call this function once from the main thread on application startup.
|
||||
///
|
||||
EASTL_API void SetAssertionFailureFunction(EASTL_AssertionFailureFunction pAssertionFailureFunction, void* pContext)
|
||||
{
|
||||
gpAssertionFailureFunction = pAssertionFailureFunction;
|
||||
gpAssertionFailureFunctionContext = pContext;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// AssertionFailureFunctionDefault
|
||||
///
|
||||
EASTL_API void AssertionFailureFunctionDefault(const char* pExpression, void* /*pContext*/)
|
||||
{
|
||||
(void)pExpression;
|
||||
#if defined(EA_DEBUG) || defined(_DEBUG)
|
||||
// We cannot use puts() because it appends a newline.
|
||||
// We cannot use printf(pExpression) because pExpression might have formatting statements.
|
||||
#if defined(EA_PLATFORM_MICROSOFT)
|
||||
OutputDebugStringA(pExpression);
|
||||
#else
|
||||
printf("%s", pExpression); // Write the message to stdout, which happens to be the trace view for many console debug machines.
|
||||
#endif
|
||||
#endif
|
||||
EASTL_DEBUG_BREAK();
|
||||
}
|
||||
|
||||
|
||||
/// AssertionFailure
|
||||
///
|
||||
EASTL_API void AssertionFailure(const char* pExpression)
|
||||
{
|
||||
if(gpAssertionFailureFunction)
|
||||
gpAssertionFailureFunction(pExpression, gpAssertionFailureFunctionContext);
|
||||
}
|
||||
|
||||
|
||||
} // namespace eastl
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
102
lib/eastl/src/fixed_pool.cpp
Normal file
102
lib/eastl/src/fixed_pool.cpp
Normal file
|
@ -0,0 +1,102 @@
|
|||
/*
|
||||
Copyright (C) 2009-2010 Electronic Arts, Inc. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
3. Neither the name of Electronic Arts, Inc. ("EA") nor the names of
|
||||
its contributors may be used to endorse or promote products derived
|
||||
from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY ELECTRONIC ARTS AND ITS CONTRIBUTORS "AS IS" AND ANY
|
||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL ELECTRONIC ARTS OR ITS CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// EASTL/fixed_pool.cpp
|
||||
//
|
||||
// Copyright (c) 2005, Electronic Arts. All rights reserved.
|
||||
// Written and maintained by Paul Pedriana.
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
#include <EASTL/internal/fixed_pool.h>
|
||||
#include <EASTL/fixed_allocator.h>
|
||||
|
||||
|
||||
|
||||
namespace eastl
|
||||
{
|
||||
|
||||
|
||||
void fixed_pool_base::init(void* pMemory, size_t memorySize, size_t nodeSize,
|
||||
size_t alignment, size_t /*alignmentOffset*/)
|
||||
{
|
||||
// To do: Support alignmentOffset.
|
||||
|
||||
#if EASTL_FIXED_SIZE_TRACKING_ENABLED
|
||||
mnCurrentSize = 0;
|
||||
mnPeakSize = 0;
|
||||
#endif
|
||||
|
||||
if(pMemory)
|
||||
{
|
||||
// Assert that alignment is a power of 2 value (e.g. 1, 2, 4, 8, 16, etc.)
|
||||
EASTL_ASSERT((alignment & (alignment - 1)) == 0);
|
||||
|
||||
// Make sure alignment is a valid value.
|
||||
if(alignment < 1)
|
||||
alignment = 1;
|
||||
|
||||
mpNext = (Link*)(((uintptr_t)pMemory + (alignment - 1)) & ~(alignment - 1));
|
||||
memorySize -= (uintptr_t)mpNext - (uintptr_t)pMemory;
|
||||
pMemory = mpNext;
|
||||
|
||||
// The node size must be at least as big as a Link, which itself is sizeof(void*).
|
||||
if(nodeSize < sizeof(Link))
|
||||
nodeSize = ((sizeof(Link) + (alignment - 1))) & ~(alignment - 1);
|
||||
|
||||
// If the user passed in a memory size that wasn't a multiple of the node size,
|
||||
// we need to chop down the memory size so that the last node is not a whole node.
|
||||
memorySize = (memorySize / nodeSize) * nodeSize;
|
||||
|
||||
mpCapacity = (Link*)((uintptr_t)pMemory + memorySize);
|
||||
mpHead = NULL;
|
||||
mnNodeSize = nodeSize;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} // namespace eastl
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
233
lib/eastl/src/hashtable.cpp
Normal file
233
lib/eastl/src/hashtable.cpp
Normal file
|
@ -0,0 +1,233 @@
|
|||
/*
|
||||
Copyright (C) 2009-2010 Electronic Arts, Inc. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
3. Neither the name of Electronic Arts, Inc. ("EA") nor the names of
|
||||
its contributors may be used to endorse or promote products derived
|
||||
from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY ELECTRONIC ARTS AND ITS CONTRIBUTORS "AS IS" AND ANY
|
||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL ELECTRONIC ARTS OR ITS CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// EASTL/hashtable.cpp
|
||||
//
|
||||
// Copyright (c) 2005, Electronic Arts. All rights reserved.
|
||||
// Written and maintained by Paul Pedriana.
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
#include <EASTL/internal/hashtable.h>
|
||||
#include <EASTL/utility.h>
|
||||
#include <math.h> // Not all compilers support <cmath> and std::ceil(), which we need below.
|
||||
#include <stddef.h>
|
||||
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(disable: 4267) // 'argument' : conversion from 'size_t' to 'const uint32_t', possible loss of data. This is a bogus warning resulting from a bug in VC++.
|
||||
#endif
|
||||
|
||||
|
||||
namespace eastl
|
||||
{
|
||||
|
||||
/// gpEmptyBucketArray
|
||||
///
|
||||
/// A shared representation of an empty hash table. This is present so that
|
||||
/// a new empty hashtable allocates no memory. It has two entries, one for
|
||||
/// the first lone empty (NULL) bucket, and one for the non-NULL trailing sentinel.
|
||||
///
|
||||
EASTL_API void* gpEmptyBucketArray[2] = { NULL, (void*)uintptr_t(~0) };
|
||||
|
||||
|
||||
|
||||
/// gPrimeNumberArray
|
||||
///
|
||||
/// This is an array of prime numbers. This is the same set of prime
|
||||
/// numbers suggested by the C++ standard proposal. These are numbers
|
||||
/// which are separated by 8% per entry.
|
||||
///
|
||||
/// To consider: Allow the user to specify their own prime number array.
|
||||
///
|
||||
const uint32_t gPrimeNumberArray[] =
|
||||
{
|
||||
2u, 3u, 5u, 7u, 11u, 13u, 17u, 19u, 23u, 29u, 31u,
|
||||
37u, 41u, 43u, 47u, 53u, 59u, 61u, 67u, 71u, 73u, 79u,
|
||||
83u, 89u, 97u, 103u, 109u, 113u, 127u, 137u, 139u, 149u,
|
||||
157u, 167u, 179u, 193u, 199u, 211u, 227u, 241u, 257u,
|
||||
277u, 293u, 313u, 337u, 359u, 383u, 409u, 439u, 467u,
|
||||
503u, 541u, 577u, 619u, 661u, 709u, 761u, 823u, 887u,
|
||||
953u, 1031u, 1109u, 1193u, 1289u, 1381u, 1493u, 1613u,
|
||||
1741u, 1879u, 2029u, 2179u, 2357u, 2549u, 2753u, 2971u,
|
||||
3209u, 3469u, 3739u, 4027u, 4349u, 4703u, 5087u, 5503u,
|
||||
5953u, 6427u, 6949u, 7517u, 8123u, 8783u, 9497u, 10273u,
|
||||
11113u, 12011u, 12983u, 14033u, 15173u, 16411u, 17749u,
|
||||
19183u, 20753u, 22447u, 24281u, 26267u, 28411u, 30727u,
|
||||
33223u, 35933u, 38873u, 42043u, 45481u, 49201u, 53201u,
|
||||
57557u, 62233u, 67307u, 72817u, 78779u, 85229u, 92203u,
|
||||
99733u, 107897u, 116731u, 126271u, 136607u, 147793u,
|
||||
159871u, 172933u, 187091u, 202409u, 218971u, 236897u,
|
||||
256279u, 277261u, 299951u, 324503u, 351061u, 379787u,
|
||||
410857u, 444487u, 480881u, 520241u, 562841u, 608903u,
|
||||
658753u, 712697u, 771049u, 834181u, 902483u, 976369u,
|
||||
1056323u, 1142821u, 1236397u, 1337629u, 1447153u, 1565659u,
|
||||
1693859u, 1832561u, 1982627u, 2144977u, 2320627u, 2510653u,
|
||||
2716249u, 2938679u, 3179303u, 3439651u, 3721303u, 4026031u,
|
||||
4355707u, 4712381u, 5098259u, 5515729u, 5967347u, 6456007u,
|
||||
6984629u, 7556579u, 8175383u, 8844859u, 9569143u, 10352717u,
|
||||
11200489u, 12117689u, 13109983u, 14183539u, 15345007u,
|
||||
16601593u, 17961079u, 19431899u, 21023161u, 22744717u,
|
||||
24607243u, 26622317u, 28802401u, 31160981u, 33712729u,
|
||||
36473443u, 39460231u, 42691603u, 46187573u, 49969847u,
|
||||
54061849u, 58488943u, 63278561u, 68460391u, 74066549u,
|
||||
80131819u, 86693767u, 93793069u, 101473717u, 109783337u,
|
||||
118773397u, 128499677u, 139022417u, 150406843u, 162723577u,
|
||||
176048909u, 190465427u, 206062531u, 222936881u, 241193053u,
|
||||
260944219u, 282312799u, 305431229u, 330442829u, 357502601u,
|
||||
386778277u, 418451333u, 452718089u, 489790921u, 529899637u,
|
||||
573292817u, 620239453u, 671030513u, 725980837u, 785430967u,
|
||||
849749479u, 919334987u, 994618837u, 1076067617u, 1164186217u,
|
||||
1259520799u, 1362662261u, 1474249943u, 1594975441u,
|
||||
1725587117u, 1866894511u, 2019773507u, 2185171673u,
|
||||
2364114217u, 2557710269u, 2767159799u, 2993761039u,
|
||||
3238918481u, 3504151727u, 3791104843u, 4101556399u,
|
||||
4294967291u,
|
||||
4294967291u // Sentinel so we don't have to test result of lower_bound
|
||||
};
|
||||
|
||||
|
||||
/// kPrimeCount
|
||||
///
|
||||
/// The number of prime numbers in gPrimeNumberArray.
|
||||
///
|
||||
const uint32_t kPrimeCount = (sizeof(gPrimeNumberArray) / sizeof(gPrimeNumberArray[0]) - 1);
|
||||
|
||||
|
||||
/// GetPrevBucketCountOnly
|
||||
/// Return a bucket count no greater than nBucketCountHint.
|
||||
///
|
||||
uint32_t prime_rehash_policy::GetPrevBucketCountOnly(uint32_t nBucketCountHint)
|
||||
{
|
||||
const uint32_t nPrime = *(eastl::upper_bound(gPrimeNumberArray, gPrimeNumberArray + kPrimeCount, nBucketCountHint) - 1);
|
||||
return nPrime;
|
||||
}
|
||||
|
||||
|
||||
/// GetPrevBucketCount
|
||||
/// Return a bucket count no greater than nBucketCountHint.
|
||||
/// This function has a side effect of updating mnNextResize.
|
||||
///
|
||||
uint32_t prime_rehash_policy::GetPrevBucketCount(uint32_t nBucketCountHint) const
|
||||
{
|
||||
const uint32_t nPrime = *(eastl::upper_bound(gPrimeNumberArray, gPrimeNumberArray + kPrimeCount, nBucketCountHint) - 1);
|
||||
|
||||
mnNextResize = (uint32_t)ceil(nPrime * floor(mfMaxLoadFactor));
|
||||
return nPrime;
|
||||
}
|
||||
|
||||
|
||||
/// GetNextBucketCount
|
||||
/// Return a prime no smaller than nBucketCountHint.
|
||||
/// This function has a side effect of updating mnNextResize.
|
||||
///
|
||||
uint32_t prime_rehash_policy::GetNextBucketCount(uint32_t nBucketCountHint) const
|
||||
{
|
||||
const uint32_t nPrime = *eastl::lower_bound(gPrimeNumberArray, gPrimeNumberArray + kPrimeCount, nBucketCountHint);
|
||||
|
||||
mnNextResize = (uint32_t)ceil(nPrime * floor(mfMaxLoadFactor));
|
||||
return nPrime;
|
||||
}
|
||||
|
||||
|
||||
/// GetBucketCount
|
||||
/// Return the smallest prime p such that alpha p >= nElementCount, where alpha
|
||||
/// is the load factor. This function has a side effect of updating mnNextResize.
|
||||
///
|
||||
uint32_t prime_rehash_policy::GetBucketCount(uint32_t nElementCount) const
|
||||
{
|
||||
const uint32_t nMinBucketCount = (uint32_t)(nElementCount / floor(mfMaxLoadFactor));
|
||||
const uint32_t nPrime = *eastl::lower_bound(gPrimeNumberArray, gPrimeNumberArray + kPrimeCount, nMinBucketCount);
|
||||
|
||||
mnNextResize = (uint32_t)ceil(nPrime * floor(mfMaxLoadFactor));
|
||||
return nPrime;
|
||||
}
|
||||
|
||||
|
||||
/// GetRehashRequired
|
||||
/// Finds the smallest prime p such that alpha p > nElementCount + nElementAdd.
|
||||
/// If p > nBucketCount, return pair<bool, uint32_t>(true, p); otherwise return
|
||||
/// pair<bool, uint32_t>(false, 0). In principle this isn't very different from GetBucketCount.
|
||||
/// This function has a side effect of updating mnNextResize.
|
||||
///
|
||||
eastl::pair<bool, uint32_t>
|
||||
prime_rehash_policy::GetRehashRequired(uint32_t nBucketCount, uint32_t nElementCount, uint32_t nElementAdd) const
|
||||
{
|
||||
if((nElementCount + nElementAdd) > mnNextResize) // It is significant that we specify > next resize and not >= next resize.
|
||||
{
|
||||
if(nBucketCount == 1) // We force rehashing to occur if the bucket count is < 2.
|
||||
nBucketCount = 0;
|
||||
|
||||
float fMinBucketCount = (float)(nElementCount + nElementAdd) / mfMaxLoadFactor;
|
||||
|
||||
if(fMinBucketCount > (float)nBucketCount)
|
||||
{
|
||||
fMinBucketCount = eastl::max_alt(fMinBucketCount, mfGrowthFactor * (float)nBucketCount);
|
||||
const uint32_t nPrime = *eastl::lower_bound(gPrimeNumberArray, gPrimeNumberArray + kPrimeCount, (uint32_t)fMinBucketCount);
|
||||
mnNextResize = (uint32_t)ceil(nPrime * floor(mfMaxLoadFactor));
|
||||
|
||||
return eastl::pair<bool, uint32_t>(true, nPrime);
|
||||
}
|
||||
else
|
||||
{
|
||||
mnNextResize = (uint32_t)ceil(nBucketCount * floor(mfMaxLoadFactor));
|
||||
return eastl::pair<bool, uint32_t>(false, (uint32_t)0);
|
||||
}
|
||||
}
|
||||
|
||||
return eastl::pair<bool, uint32_t>(false, (uint32_t)0);
|
||||
}
|
||||
|
||||
|
||||
} // namespace eastl
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
535
lib/eastl/src/red_black_tree.cpp
Normal file
535
lib/eastl/src/red_black_tree.cpp
Normal file
|
@ -0,0 +1,535 @@
|
|||
/*
|
||||
Copyright (C) 2005,2009-2010 Electronic Arts, Inc. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
3. Neither the name of Electronic Arts, Inc. ("EA") nor the names of
|
||||
its contributors may be used to endorse or promote products derived
|
||||
from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY ELECTRONIC ARTS AND ITS CONTRIBUTORS "AS IS" AND ANY
|
||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL ELECTRONIC ARTS OR ITS CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// EASTL/red_black_tree.cpp
|
||||
//
|
||||
// Written and maintained by Paul Pedriana - 2005.
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// The tree insert and erase functions below are based on the original
|
||||
// HP STL tree functions. Use of these functions was been approved by
|
||||
// EA legal on November 4, 2005 and the approval documentation is available
|
||||
// from the EASTL maintainer or from the EA legal deparatment on request.
|
||||
//
|
||||
// Copyright (c) 1994
|
||||
// Hewlett-Packard Company
|
||||
//
|
||||
// Permission to use, copy, modify, distribute and sell this software
|
||||
// and its documentation for any purpose is hereby granted without fee,
|
||||
// provided that the above copyright notice appear in all copies and
|
||||
// that both that copyright notice and this permission notice appear
|
||||
// in supporting documentation. Hewlett-Packard Company makes no
|
||||
// representations about the suitability of this software for any
|
||||
// purpose. It is provided "as is" without express or implied warranty.
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
|
||||
#include <EASTL/internal/config.h>
|
||||
#include <EASTL/internal/red_black_tree.h>
|
||||
#include <stddef.h>
|
||||
|
||||
|
||||
|
||||
namespace eastl
|
||||
{
|
||||
// Forward declarations
|
||||
rbtree_node_base* RBTreeRotateLeft(rbtree_node_base* pNode, rbtree_node_base* pNodeRoot);
|
||||
rbtree_node_base* RBTreeRotateRight(rbtree_node_base* pNode, rbtree_node_base* pNodeRoot);
|
||||
|
||||
|
||||
|
||||
/// RBTreeIncrement
|
||||
/// Returns the next item in a sorted red-black tree.
|
||||
///
|
||||
EASTL_API rbtree_node_base* RBTreeIncrement(const rbtree_node_base* pNode)
|
||||
{
|
||||
if(pNode->mpNodeRight)
|
||||
{
|
||||
pNode = pNode->mpNodeRight;
|
||||
|
||||
while(pNode->mpNodeLeft)
|
||||
pNode = pNode->mpNodeLeft;
|
||||
}
|
||||
else
|
||||
{
|
||||
rbtree_node_base* pNodeTemp = pNode->mpNodeParent;
|
||||
|
||||
while(pNode == pNodeTemp->mpNodeRight)
|
||||
{
|
||||
pNode = pNodeTemp;
|
||||
pNodeTemp = pNodeTemp->mpNodeParent;
|
||||
}
|
||||
|
||||
if(pNode->mpNodeRight != pNodeTemp)
|
||||
pNode = pNodeTemp;
|
||||
}
|
||||
|
||||
return const_cast<rbtree_node_base*>(pNode);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// RBTreeIncrement
|
||||
/// Returns the previous item in a sorted red-black tree.
|
||||
///
|
||||
EASTL_API rbtree_node_base* RBTreeDecrement(const rbtree_node_base* pNode)
|
||||
{
|
||||
if((pNode->mpNodeParent->mpNodeParent == pNode) && (pNode->mColor == kRBTreeColorRed))
|
||||
return pNode->mpNodeRight;
|
||||
else if(pNode->mpNodeLeft)
|
||||
{
|
||||
rbtree_node_base* pNodeTemp = pNode->mpNodeLeft;
|
||||
|
||||
while(pNodeTemp->mpNodeRight)
|
||||
pNodeTemp = pNodeTemp->mpNodeRight;
|
||||
|
||||
return pNodeTemp;
|
||||
}
|
||||
|
||||
rbtree_node_base* pNodeTemp = pNode->mpNodeParent;
|
||||
|
||||
while(pNode == pNodeTemp->mpNodeLeft)
|
||||
{
|
||||
pNode = pNodeTemp;
|
||||
pNodeTemp = pNodeTemp->mpNodeParent;
|
||||
}
|
||||
|
||||
return const_cast<rbtree_node_base*>(pNodeTemp);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// RBTreeGetBlackCount
|
||||
/// Counts the number of black nodes in an red-black tree, from pNode down to the given bottom node.
|
||||
/// We don't count red nodes because red-black trees don't really care about
|
||||
/// red node counts; it is black node counts that are significant in the
|
||||
/// maintenance of a balanced tree.
|
||||
///
|
||||
EASTL_API size_t RBTreeGetBlackCount(const rbtree_node_base* pNodeTop, const rbtree_node_base* pNodeBottom)
|
||||
{
|
||||
size_t nCount = 0;
|
||||
|
||||
for(; pNodeBottom; pNodeBottom = pNodeBottom->mpNodeParent)
|
||||
{
|
||||
if(pNodeBottom->mColor == kRBTreeColorBlack)
|
||||
++nCount;
|
||||
|
||||
if(pNodeBottom == pNodeTop)
|
||||
break;
|
||||
}
|
||||
|
||||
return nCount;
|
||||
}
|
||||
|
||||
|
||||
/// RBTreeRotateLeft
|
||||
/// Does a left rotation about the given node.
|
||||
/// If you want to understand tree rotation, any book on algorithms will
|
||||
/// discussion the topic in good detail.
|
||||
rbtree_node_base* RBTreeRotateLeft(rbtree_node_base* pNode, rbtree_node_base* pNodeRoot)
|
||||
{
|
||||
rbtree_node_base* const pNodeTemp = pNode->mpNodeRight;
|
||||
|
||||
pNode->mpNodeRight = pNodeTemp->mpNodeLeft;
|
||||
|
||||
if(pNodeTemp->mpNodeLeft)
|
||||
pNodeTemp->mpNodeLeft->mpNodeParent = pNode;
|
||||
pNodeTemp->mpNodeParent = pNode->mpNodeParent;
|
||||
|
||||
if(pNode == pNodeRoot)
|
||||
pNodeRoot = pNodeTemp;
|
||||
else if(pNode == pNode->mpNodeParent->mpNodeLeft)
|
||||
pNode->mpNodeParent->mpNodeLeft = pNodeTemp;
|
||||
else
|
||||
pNode->mpNodeParent->mpNodeRight = pNodeTemp;
|
||||
|
||||
pNodeTemp->mpNodeLeft = pNode;
|
||||
pNode->mpNodeParent = pNodeTemp;
|
||||
|
||||
return pNodeRoot;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// RBTreeRotateRight
|
||||
/// Does a right rotation about the given node.
|
||||
/// If you want to understand tree rotation, any book on algorithms will
|
||||
/// discussion the topic in good detail.
|
||||
rbtree_node_base* RBTreeRotateRight(rbtree_node_base* pNode, rbtree_node_base* pNodeRoot)
|
||||
{
|
||||
rbtree_node_base* const pNodeTemp = pNode->mpNodeLeft;
|
||||
|
||||
pNode->mpNodeLeft = pNodeTemp->mpNodeRight;
|
||||
|
||||
if(pNodeTemp->mpNodeRight)
|
||||
pNodeTemp->mpNodeRight->mpNodeParent = pNode;
|
||||
pNodeTemp->mpNodeParent = pNode->mpNodeParent;
|
||||
|
||||
if(pNode == pNodeRoot)
|
||||
pNodeRoot = pNodeTemp;
|
||||
else if(pNode == pNode->mpNodeParent->mpNodeRight)
|
||||
pNode->mpNodeParent->mpNodeRight = pNodeTemp;
|
||||
else
|
||||
pNode->mpNodeParent->mpNodeLeft = pNodeTemp;
|
||||
|
||||
pNodeTemp->mpNodeRight = pNode;
|
||||
pNode->mpNodeParent = pNodeTemp;
|
||||
|
||||
return pNodeRoot;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/// RBTreeInsert
|
||||
/// Insert a node into the tree and rebalance the tree as a result of the
|
||||
/// disturbance the node introduced.
|
||||
///
|
||||
EASTL_API void RBTreeInsert(rbtree_node_base* pNode,
|
||||
rbtree_node_base* pNodeParent,
|
||||
rbtree_node_base* pNodeAnchor,
|
||||
RBTreeSide insertionSide)
|
||||
{
|
||||
rbtree_node_base*& pNodeRootRef = pNodeAnchor->mpNodeParent;
|
||||
|
||||
// Initialize fields in new node to insert.
|
||||
pNode->mpNodeParent = pNodeParent;
|
||||
pNode->mpNodeRight = NULL;
|
||||
pNode->mpNodeLeft = NULL;
|
||||
pNode->mColor = kRBTreeColorRed;
|
||||
|
||||
// Insert the node.
|
||||
if(insertionSide == kRBTreeSideLeft)
|
||||
{
|
||||
pNodeParent->mpNodeLeft = pNode; // Also makes (leftmost = pNode) when (pNodeParent == pNodeAnchor)
|
||||
|
||||
if(pNodeParent == pNodeAnchor)
|
||||
{
|
||||
pNodeAnchor->mpNodeParent = pNode;
|
||||
pNodeAnchor->mpNodeRight = pNode;
|
||||
}
|
||||
else if(pNodeParent == pNodeAnchor->mpNodeLeft)
|
||||
pNodeAnchor->mpNodeLeft = pNode; // Maintain leftmost pointing to min node
|
||||
}
|
||||
else
|
||||
{
|
||||
pNodeParent->mpNodeRight = pNode;
|
||||
|
||||
if(pNodeParent == pNodeAnchor->mpNodeRight)
|
||||
pNodeAnchor->mpNodeRight = pNode; // Maintain rightmost pointing to max node
|
||||
}
|
||||
|
||||
// Rebalance the tree.
|
||||
while((pNode != pNodeRootRef) && (pNode->mpNodeParent->mColor == kRBTreeColorRed))
|
||||
{
|
||||
rbtree_node_base* const pNodeParentParent = pNode->mpNodeParent->mpNodeParent;
|
||||
|
||||
if(pNode->mpNodeParent == pNodeParentParent->mpNodeLeft)
|
||||
{
|
||||
rbtree_node_base* const pNodeTemp = pNodeParentParent->mpNodeRight;
|
||||
|
||||
if(pNodeTemp && (pNodeTemp->mColor == kRBTreeColorRed))
|
||||
{
|
||||
pNode->mpNodeParent->mColor = kRBTreeColorBlack;
|
||||
pNodeTemp->mColor = kRBTreeColorBlack;
|
||||
pNodeParentParent->mColor = kRBTreeColorRed;
|
||||
pNode = pNodeParentParent;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(pNode == pNode->mpNodeParent->mpNodeRight)
|
||||
{
|
||||
pNode = pNode->mpNodeParent;
|
||||
pNodeRootRef = RBTreeRotateLeft(pNode, pNodeRootRef);
|
||||
}
|
||||
|
||||
pNode->mpNodeParent->mColor = kRBTreeColorBlack;
|
||||
pNodeParentParent->mColor = kRBTreeColorRed;
|
||||
pNodeRootRef = RBTreeRotateRight(pNodeParentParent, pNodeRootRef);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
rbtree_node_base* const pNodeTemp = pNodeParentParent->mpNodeLeft;
|
||||
|
||||
if(pNodeTemp && (pNodeTemp->mColor == kRBTreeColorRed))
|
||||
{
|
||||
pNode->mpNodeParent->mColor = kRBTreeColorBlack;
|
||||
pNodeTemp->mColor = kRBTreeColorBlack;
|
||||
pNodeParentParent->mColor = kRBTreeColorRed;
|
||||
pNode = pNodeParentParent;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(pNode == pNode->mpNodeParent->mpNodeLeft)
|
||||
{
|
||||
pNode = pNode->mpNodeParent;
|
||||
pNodeRootRef = RBTreeRotateRight(pNode, pNodeRootRef);
|
||||
}
|
||||
|
||||
pNode->mpNodeParent->mColor = kRBTreeColorBlack;
|
||||
pNodeParentParent->mColor = kRBTreeColorRed;
|
||||
pNodeRootRef = RBTreeRotateLeft(pNodeParentParent, pNodeRootRef);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pNodeRootRef->mColor = kRBTreeColorBlack;
|
||||
|
||||
} // RBTreeInsert
|
||||
|
||||
|
||||
|
||||
|
||||
/// RBTreeErase
|
||||
/// Erase a node from the tree.
|
||||
///
|
||||
EASTL_API void RBTreeErase(rbtree_node_base* pNode, rbtree_node_base* pNodeAnchor)
|
||||
{
|
||||
rbtree_node_base*& pNodeRootRef = pNodeAnchor->mpNodeParent;
|
||||
rbtree_node_base*& pNodeLeftmostRef = pNodeAnchor->mpNodeLeft;
|
||||
rbtree_node_base*& pNodeRightmostRef = pNodeAnchor->mpNodeRight;
|
||||
rbtree_node_base* pNodeSuccessor = pNode;
|
||||
rbtree_node_base* pNodeChild = NULL;
|
||||
rbtree_node_base* pNodeChildParent = NULL;
|
||||
|
||||
if(pNodeSuccessor->mpNodeLeft == NULL) // pNode has at most one non-NULL child.
|
||||
pNodeChild = pNodeSuccessor->mpNodeRight; // pNodeChild might be null.
|
||||
else if(pNodeSuccessor->mpNodeRight == NULL) // pNode has exactly one non-NULL child.
|
||||
pNodeChild = pNodeSuccessor->mpNodeLeft; // pNodeChild is not null.
|
||||
else
|
||||
{
|
||||
// pNode has two non-null children. Set pNodeSuccessor to pNode's successor. pNodeChild might be NULL.
|
||||
pNodeSuccessor = pNodeSuccessor->mpNodeRight;
|
||||
|
||||
while(pNodeSuccessor->mpNodeLeft)
|
||||
pNodeSuccessor = pNodeSuccessor->mpNodeLeft;
|
||||
|
||||
pNodeChild = pNodeSuccessor->mpNodeRight;
|
||||
}
|
||||
|
||||
// Here we remove pNode from the tree and fix up the node pointers appropriately around it.
|
||||
if(pNodeSuccessor == pNode) // If pNode was a leaf node (had both NULL children)...
|
||||
{
|
||||
pNodeChildParent = pNodeSuccessor->mpNodeParent; // Assign pNodeReplacement's parent.
|
||||
|
||||
if(pNodeChild)
|
||||
pNodeChild->mpNodeParent = pNodeSuccessor->mpNodeParent;
|
||||
|
||||
if(pNode == pNodeRootRef) // If the node being deleted is the root node...
|
||||
pNodeRootRef = pNodeChild; // Set the new root node to be the pNodeReplacement.
|
||||
else
|
||||
{
|
||||
if(pNode == pNode->mpNodeParent->mpNodeLeft) // If pNode is a left node...
|
||||
pNode->mpNodeParent->mpNodeLeft = pNodeChild; // Make pNode's replacement node be on the same side.
|
||||
else
|
||||
pNode->mpNodeParent->mpNodeRight = pNodeChild;
|
||||
// Now pNode is disconnected from the bottom of the tree (recall that in this pathway pNode was determined to be a leaf).
|
||||
}
|
||||
|
||||
if(pNode == pNodeLeftmostRef) // If pNode is the tree begin() node...
|
||||
{
|
||||
// Because pNode is the tree begin(), pNode->mpNodeLeft must be NULL.
|
||||
// Here we assign the new begin() (first node).
|
||||
if(pNode->mpNodeRight)
|
||||
pNodeLeftmostRef = RBTreeGetMinChild(pNodeChild);
|
||||
else
|
||||
pNodeLeftmostRef = pNode->mpNodeParent; // This makes (pNodeLeftmostRef == end()) if (pNode == root node)
|
||||
}
|
||||
|
||||
if(pNode == pNodeRightmostRef) // If pNode is the tree last (rbegin()) node...
|
||||
{
|
||||
// Because pNode is the tree rbegin(), pNode->mpNodeRight must be NULL.
|
||||
// Here we assign the new rbegin() (last node)
|
||||
if(pNode->mpNodeLeft)
|
||||
pNodeRightmostRef = RBTreeGetMaxChild(pNodeChild);
|
||||
else // pNodeChild == pNode->mpNodeLeft
|
||||
pNodeRightmostRef = pNode->mpNodeParent; // makes pNodeRightmostRef == &mAnchor if pNode == pNodeRootRef
|
||||
}
|
||||
}
|
||||
else // else (pNodeSuccessor != pNode)
|
||||
{
|
||||
// Relink pNodeSuccessor in place of pNode. pNodeSuccessor is pNode's successor.
|
||||
// We specifically set pNodeSuccessor to be on the right child side of pNode, so fix up the left child side.
|
||||
pNode->mpNodeLeft->mpNodeParent = pNodeSuccessor;
|
||||
pNodeSuccessor->mpNodeLeft = pNode->mpNodeLeft;
|
||||
|
||||
if(pNodeSuccessor == pNode->mpNodeRight) // If pNode's successor was at the bottom of the tree... (yes that's effectively what this statement means)
|
||||
pNodeChildParent = pNodeSuccessor; // Assign pNodeReplacement's parent.
|
||||
else
|
||||
{
|
||||
pNodeChildParent = pNodeSuccessor->mpNodeParent;
|
||||
|
||||
if(pNodeChild)
|
||||
pNodeChild->mpNodeParent = pNodeChildParent;
|
||||
|
||||
pNodeChildParent->mpNodeLeft = pNodeChild;
|
||||
|
||||
pNodeSuccessor->mpNodeRight = pNode->mpNodeRight;
|
||||
pNode->mpNodeRight->mpNodeParent = pNodeSuccessor;
|
||||
}
|
||||
|
||||
if(pNode == pNodeRootRef)
|
||||
pNodeRootRef = pNodeSuccessor;
|
||||
else if(pNode == pNode->mpNodeParent->mpNodeLeft)
|
||||
pNode->mpNodeParent->mpNodeLeft = pNodeSuccessor;
|
||||
else
|
||||
pNode->mpNodeParent->mpNodeRight = pNodeSuccessor;
|
||||
|
||||
// Now pNode is disconnected from the tree.
|
||||
|
||||
pNodeSuccessor->mpNodeParent = pNode->mpNodeParent;
|
||||
eastl::swap(pNodeSuccessor->mColor, pNode->mColor);
|
||||
}
|
||||
|
||||
// Here we do tree balancing as per the conventional red-black tree algorithm.
|
||||
if(pNode->mColor == kRBTreeColorBlack)
|
||||
{
|
||||
while((pNodeChild != pNodeRootRef) && ((pNodeChild == NULL) || (pNodeChild->mColor == kRBTreeColorBlack)))
|
||||
{
|
||||
if(pNodeChild == pNodeChildParent->mpNodeLeft)
|
||||
{
|
||||
rbtree_node_base* pNodeTemp = pNodeChildParent->mpNodeRight;
|
||||
|
||||
if(pNodeTemp->mColor == kRBTreeColorRed)
|
||||
{
|
||||
pNodeTemp->mColor = kRBTreeColorBlack;
|
||||
pNodeChildParent->mColor = kRBTreeColorRed;
|
||||
pNodeRootRef = RBTreeRotateLeft(pNodeChildParent, pNodeRootRef);
|
||||
pNodeTemp = pNodeChildParent->mpNodeRight;
|
||||
}
|
||||
|
||||
if(((pNodeTemp->mpNodeLeft == NULL) || (pNodeTemp->mpNodeLeft->mColor == kRBTreeColorBlack)) &&
|
||||
((pNodeTemp->mpNodeRight == NULL) || (pNodeTemp->mpNodeRight->mColor == kRBTreeColorBlack)))
|
||||
{
|
||||
pNodeTemp->mColor = kRBTreeColorRed;
|
||||
pNodeChild = pNodeChildParent;
|
||||
pNodeChildParent = pNodeChildParent->mpNodeParent;
|
||||
}
|
||||
else
|
||||
{
|
||||
if((pNodeTemp->mpNodeRight == NULL) || (pNodeTemp->mpNodeRight->mColor == kRBTreeColorBlack))
|
||||
{
|
||||
pNodeTemp->mpNodeLeft->mColor = kRBTreeColorBlack;
|
||||
pNodeTemp->mColor = kRBTreeColorRed;
|
||||
pNodeRootRef = RBTreeRotateRight(pNodeTemp, pNodeRootRef);
|
||||
pNodeTemp = pNodeChildParent->mpNodeRight;
|
||||
}
|
||||
|
||||
pNodeTemp->mColor = pNodeChildParent->mColor;
|
||||
pNodeChildParent->mColor = kRBTreeColorBlack;
|
||||
|
||||
if(pNodeTemp->mpNodeRight)
|
||||
pNodeTemp->mpNodeRight->mColor = kRBTreeColorBlack;
|
||||
|
||||
pNodeRootRef = RBTreeRotateLeft(pNodeChildParent, pNodeRootRef);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// The following is the same as above, with mpNodeRight <-> mpNodeLeft.
|
||||
rbtree_node_base* pNodeTemp = pNodeChildParent->mpNodeLeft;
|
||||
|
||||
if(pNodeTemp->mColor == kRBTreeColorRed)
|
||||
{
|
||||
pNodeTemp->mColor = kRBTreeColorBlack;
|
||||
pNodeChildParent->mColor = kRBTreeColorRed;
|
||||
|
||||
pNodeRootRef = RBTreeRotateRight(pNodeChildParent, pNodeRootRef);
|
||||
pNodeTemp = pNodeChildParent->mpNodeLeft;
|
||||
}
|
||||
|
||||
if(((pNodeTemp->mpNodeRight == NULL) || (pNodeTemp->mpNodeRight->mColor == kRBTreeColorBlack)) &&
|
||||
((pNodeTemp->mpNodeLeft == NULL) || (pNodeTemp->mpNodeLeft->mColor == kRBTreeColorBlack)))
|
||||
{
|
||||
pNodeTemp->mColor = kRBTreeColorRed;
|
||||
pNodeChild = pNodeChildParent;
|
||||
pNodeChildParent = pNodeChildParent->mpNodeParent;
|
||||
}
|
||||
else
|
||||
{
|
||||
if((pNodeTemp->mpNodeLeft == NULL) || (pNodeTemp->mpNodeLeft->mColor == kRBTreeColorBlack))
|
||||
{
|
||||
pNodeTemp->mpNodeRight->mColor = kRBTreeColorBlack;
|
||||
pNodeTemp->mColor = kRBTreeColorRed;
|
||||
|
||||
pNodeRootRef = RBTreeRotateLeft(pNodeTemp, pNodeRootRef);
|
||||
pNodeTemp = pNodeChildParent->mpNodeLeft;
|
||||
}
|
||||
|
||||
pNodeTemp->mColor = pNodeChildParent->mColor;
|
||||
pNodeChildParent->mColor = kRBTreeColorBlack;
|
||||
|
||||
if(pNodeTemp->mpNodeLeft)
|
||||
pNodeTemp->mpNodeLeft->mColor = kRBTreeColorBlack;
|
||||
|
||||
pNodeRootRef = RBTreeRotateRight(pNodeChildParent, pNodeRootRef);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(pNodeChild)
|
||||
pNodeChild->mColor = kRBTreeColorBlack;
|
||||
}
|
||||
|
||||
} // RBTreeErase
|
||||
|
||||
|
||||
|
||||
} // namespace eastl
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
71
lib/eastl/src/string.cpp
Normal file
71
lib/eastl/src/string.cpp
Normal file
|
@ -0,0 +1,71 @@
|
|||
/*
|
||||
Copyright (C) 2009-2010 Electronic Arts, Inc. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
3. Neither the name of Electronic Arts, Inc. ("EA") nor the names of
|
||||
its contributors may be used to endorse or promote products derived
|
||||
from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY ELECTRONIC ARTS AND ITS CONTRIBUTORS "AS IS" AND ANY
|
||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL ELECTRONIC ARTS OR ITS CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// EASTL/string.cpp
|
||||
//
|
||||
// Copyright (c) 2005, Electronic Arts. All rights reserved.
|
||||
// Written and maintained by Paul Pedriana.
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
#include <EASTL/internal/config.h>
|
||||
#include <EASTL/string.h>
|
||||
#include <EABase/eabase.h>
|
||||
|
||||
|
||||
namespace eastl
|
||||
{
|
||||
|
||||
/// gEmptyString
|
||||
///
|
||||
/// gEmptyString is used for empty strings. This allows us to avoid allocating
|
||||
/// memory for empty strings without having to add null pointer checks.
|
||||
/// The downside of this technique is that all empty strings share this same
|
||||
/// value and if any code makes an error and writes to this value with non-zero,
|
||||
/// then all existing empty strings will be wrecked and not just the one that
|
||||
/// was incorrectly overwritten.
|
||||
EASTL_API EmptyString gEmptyString = { 0 };
|
||||
|
||||
|
||||
} // namespace eastl
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
15951
lib/glew/glew.c
Normal file
15951
lib/glew/glew.c
Normal file
File diff suppressed because it is too large
Load diff
16126
lib/glew/glew.h
Normal file
16126
lib/glew/glew.h
Normal file
File diff suppressed because it is too large
Load diff
1587
lib/glew/glxew.h
Normal file
1587
lib/glew/glxew.h
Normal file
File diff suppressed because it is too large
Load diff
1363
lib/glew/wglew.h
Normal file
1363
lib/glew/wglew.h
Normal file
File diff suppressed because it is too large
Load diff
1193
lib/gwen/controls/gwen_base.cpp
Normal file
1193
lib/gwen/controls/gwen_base.cpp
Normal file
File diff suppressed because it is too large
Load diff
556
lib/gwen/controls/gwen_base.h
Normal file
556
lib/gwen/controls/gwen_base.h
Normal file
|
@ -0,0 +1,556 @@
|
|||
/*
|
||||
GWEN
|
||||
Copyright (c) 2010 Facepunch Studios
|
||||
See license in Gwen.h
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#ifndef GWEN_CONTROLS_BASE_H
|
||||
#define GWEN_CONTROLS_BASE_H
|
||||
|
||||
#include <stl/list.h>
|
||||
#include <stl/map.h>
|
||||
#include <stl/algorithm.h>
|
||||
|
||||
#include "../gwen_exports.h"
|
||||
#include "../gwen_structures.h"
|
||||
#include "../gwen_baserender.h"
|
||||
#include "../gwen_events.h"
|
||||
#include "../gwen_utility.h"
|
||||
#include "../gwen_textobject.h"
|
||||
#include "../gwen_skin.h"
|
||||
#include "../gwen_controllist.h"
|
||||
#include "../gwen_userdata.h"
|
||||
|
||||
|
||||
namespace Gwen
|
||||
{
|
||||
namespace Pos
|
||||
{
|
||||
enum
|
||||
{
|
||||
None = 0,
|
||||
Left = (1 << 1),
|
||||
Right = (1 << 2),
|
||||
Top = (1 << 3),
|
||||
Bottom = (1 << 4),
|
||||
CenterV = (1 << 5),
|
||||
CenterH = (1 << 6),
|
||||
Fill = (1 << 7),
|
||||
Center = CenterV | CenterH,
|
||||
};
|
||||
}
|
||||
|
||||
class TextObject;
|
||||
|
||||
namespace Skin
|
||||
{
|
||||
class Base;
|
||||
}
|
||||
|
||||
namespace Controls
|
||||
{
|
||||
class Canvas;
|
||||
|
||||
class GWEN_EXPORT Base : public Event::Handler
|
||||
{
|
||||
public:
|
||||
|
||||
typedef stl::list<Base*> List;
|
||||
|
||||
typedef stl::map<Gwen::String, Gwen::Event::Caller*> AccelMap;
|
||||
|
||||
Base( Base* pParent, const Gwen::String& Name = "" );
|
||||
virtual ~Base();
|
||||
|
||||
virtual const char* GetTypeName(){ return "Base"; }
|
||||
|
||||
virtual void DelayedDelete();
|
||||
virtual void PreDelete( Gwen::Skin::Base* skin ){};
|
||||
|
||||
virtual void SetParent( Controls::Base* pParent );
|
||||
virtual Controls::Base* GetParent() const { return m_Parent; }
|
||||
virtual Controls::Canvas* GetCanvas();
|
||||
|
||||
virtual Base::List& GetChildren(){ if ( m_InnerPanel ) return m_InnerPanel->GetChildren(); return Children; }
|
||||
virtual bool IsChild( Controls::Base* pChild );
|
||||
virtual unsigned int NumChildren();
|
||||
virtual Controls::Base* GetChild( unsigned int i );
|
||||
virtual bool SizeToChildren( bool w = true, bool h = true );
|
||||
virtual Gwen::Point ChildrenSize();
|
||||
virtual Controls::Base* FindChildByName( const Gwen::String& name, bool bRecursive = false );
|
||||
|
||||
template <typename T> T* FindChild( const Gwen::String& name, bool bRecursive = false );
|
||||
|
||||
virtual void SetName( const Gwen::String& name) { m_Name = name; }
|
||||
virtual const Gwen::String& GetName() { return m_Name; }
|
||||
|
||||
virtual void Think(){}
|
||||
|
||||
protected:
|
||||
|
||||
virtual void AddChild( Controls::Base* pChild );
|
||||
virtual void RemoveChild( Controls::Base* pParent );
|
||||
virtual void OnChildAdded( Controls::Base* pChild );
|
||||
virtual void OnChildRemoved( Controls::Base* pChild );
|
||||
|
||||
public:
|
||||
|
||||
virtual void RemoveAllChildren();
|
||||
|
||||
virtual void SendToBack( void );
|
||||
virtual void BringToFront( void );
|
||||
virtual void BringNextToControl( Controls::Base* pChild, bool bBehind );
|
||||
|
||||
virtual Gwen::Point LocalPosToCanvas( const Gwen::Point& in = Point( 0, 0 ) );
|
||||
virtual Gwen::Point CanvasPosToLocal( const Gwen::Point& in );
|
||||
|
||||
virtual void Dock( int iDock );
|
||||
virtual int GetDock();
|
||||
|
||||
virtual void RestrictToParent( bool restrict ) { m_bRestrictToParent = restrict; }
|
||||
virtual bool ShouldRestrictToParent() { return m_bRestrictToParent; }
|
||||
|
||||
virtual int X() const { return m_Bounds.x; }
|
||||
virtual int Y() const { return m_Bounds.y; }
|
||||
virtual int Width() const { return m_Bounds.w; }
|
||||
virtual int Height() const { return m_Bounds.h; }
|
||||
virtual int Bottom() const { return m_Bounds.y + m_Bounds.h + m_Margin.bottom; }
|
||||
virtual int Right() const { return m_Bounds.x + m_Bounds.w + m_Margin.right; }
|
||||
|
||||
virtual const Margin& GetMargin() const { return m_Margin; }
|
||||
virtual const Padding& GetPadding() const { return m_Padding; }
|
||||
|
||||
virtual void SetPos( int x, int y );
|
||||
virtual void SetPos( const Point& p ){ return SetPos( p.x, p.y ); }
|
||||
virtual void SetPosInParentBounds( int x, int y );
|
||||
virtual void SetPosInParentBounds( const Point& p ){ return SetPosInParentBounds( p.x, p.y ); }
|
||||
virtual Point GetPos(){ return Point( X(), Y() ); }
|
||||
virtual void SetWidth( int w ) { SetSize( w, Height()); }
|
||||
virtual void SetHeight( int h ) { SetSize( Width(), h); }
|
||||
virtual bool SetSize( int w, int h );
|
||||
virtual bool SetSize( const Point& p );
|
||||
virtual Point GetSize(){ return Point( Width(), Height() ); }
|
||||
virtual bool SetBounds( int x, int y, int w, int h );
|
||||
virtual bool SetBounds( const Gwen::Rect& bounds );
|
||||
|
||||
virtual void SetPadding( const Padding& padding );
|
||||
virtual void SetMargin( const Margin& margin );
|
||||
|
||||
// MoveTo is identical to SetPos except it uses ShouldRestrictToParent()
|
||||
virtual void MoveTo (int x, int y );
|
||||
virtual void MoveBy (int x, int y );
|
||||
|
||||
virtual const Gwen::Rect& GetBounds() const { return m_Bounds; }
|
||||
|
||||
virtual Controls::Base* GetControlAt( int x, int y, bool bOnlyIfMouseEnabled = true );
|
||||
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
virtual void OnBoundsChanged( Gwen::Rect oldBounds );
|
||||
virtual void OnChildBoundsChanged( Gwen::Rect oldChildBounds, Base* pChild );
|
||||
|
||||
virtual void OnScaleChanged();
|
||||
|
||||
public:
|
||||
|
||||
// Innerbounds is the area inside the control that
|
||||
// doesn't have child controls docked to it.
|
||||
virtual const Gwen::Rect& GetInnerBounds() const { return m_InnerBounds; }
|
||||
|
||||
protected:
|
||||
|
||||
Gwen::Rect m_InnerBounds;
|
||||
|
||||
public:
|
||||
|
||||
virtual const Gwen::Rect& GetRenderBounds() const{ return m_RenderBounds; }
|
||||
|
||||
protected:
|
||||
|
||||
virtual void UpdateRenderBounds();
|
||||
|
||||
public:
|
||||
|
||||
virtual void DoRender( Gwen::Skin::Base* skin );
|
||||
virtual void DoCacheRender( Gwen::Skin::Base* skin, Gwen::Controls::Base* pMaster );
|
||||
virtual void RenderRecursive( Gwen::Skin::Base* skin, const Gwen::Rect& cliprect );
|
||||
|
||||
virtual bool ShouldClip(){ return true; }
|
||||
|
||||
protected:
|
||||
|
||||
virtual void Render( Gwen::Skin::Base* skin );
|
||||
virtual void RenderUnder( Gwen::Skin::Base* /*skin*/ ){};
|
||||
virtual void RenderOver( Gwen::Skin::Base* /*skin*/ ){};
|
||||
virtual void RenderFocus( Gwen::Skin::Base* /*skin*/ );
|
||||
|
||||
public:
|
||||
|
||||
virtual void SetHidden( bool hidden ) { if ( m_bHidden == hidden ) return; m_bHidden = hidden; Invalidate(); Redraw(); }
|
||||
virtual bool Hidden() const; // Returns true only if this control is hidden
|
||||
virtual bool Visible() const; // Returns false if this control or its parents are hidden
|
||||
virtual void Hide(){ SetHidden( true ); }
|
||||
virtual void Show(){ SetHidden( false ); }
|
||||
|
||||
//Skin
|
||||
virtual void SetSkin( Skin::Base* skin, bool doChildren = false );
|
||||
virtual Gwen::Skin::Base* GetSkin( void );
|
||||
|
||||
// Background drawing
|
||||
virtual bool ShouldDrawBackground(){ return m_bDrawBackground; }
|
||||
virtual void SetShouldDrawBackground( bool b ){ m_bDrawBackground = b; }
|
||||
|
||||
protected:
|
||||
|
||||
virtual void OnSkinChanged( Gwen::Skin::Base* newSkin );
|
||||
|
||||
public:
|
||||
|
||||
virtual void OnMouseMoved( int x, int y, int deltaX, int deltaY );
|
||||
virtual bool OnMouseWheeled( int iDelta );
|
||||
virtual void OnMouseClickLeft( int /*x*/, int /*y*/, bool /*bDown*/ ){};
|
||||
virtual void OnMouseClickRight( int /*x*/, int /*y*/, bool /*bDown*/ ){}
|
||||
virtual void OnMouseDoubleClickLeft( int x, int y ){ OnMouseClickLeft( x, y, true ); };
|
||||
virtual void OnMouseDoubleClickRight( int x, int y ){ OnMouseClickRight( x, y, true ); };
|
||||
virtual void OnLostKeyboardFocus(){}
|
||||
virtual void OnKeyboardFocus(){}
|
||||
|
||||
virtual void SetMouseInputEnabled( bool b ) { m_bMouseInputEnabled = b; }
|
||||
virtual bool GetMouseInputEnabled() { return m_bMouseInputEnabled; }
|
||||
|
||||
virtual void SetKeyboardInputEnabled( bool b ){ m_bKeyboardInputEnabled = b; }
|
||||
virtual bool GetKeyboardInputEnabled() const { return m_bKeyboardInputEnabled; }
|
||||
virtual bool NeedsInputChars(){ return false; }
|
||||
|
||||
virtual bool OnChar( char /*c*/ ){ return false; }
|
||||
|
||||
virtual bool OnKeyPress( int iKey, bool bPress = true );
|
||||
virtual bool OnKeyRelease( int iKey );
|
||||
|
||||
virtual void OnPaste(Controls::Base* /*pFrom*/){}
|
||||
virtual void OnCopy(Controls::Base* /*pFrom*/){}
|
||||
virtual void OnCut(Controls::Base* /*pFrom*/){}
|
||||
virtual void OnSelectAll(Controls::Base* /*pFrom*/){}
|
||||
|
||||
virtual bool OnKeyTab( bool bDown );
|
||||
virtual bool OnKeySpace( bool /*bDown*/ ){ return false; }
|
||||
virtual bool OnKeyReturn( bool /*bDown*/ ){ return false; }
|
||||
virtual bool OnKeyBackspace( bool /*bDown*/ ){ return false; }
|
||||
virtual bool OnKeyDelete( bool /*bDown*/ ){ return false; }
|
||||
virtual bool OnKeyRight( bool /*bDown*/ ){ return false; }
|
||||
virtual bool OnKeyLeft( bool /*bDown*/ ){ return false; }
|
||||
virtual bool OnKeyHome( bool /*bDown*/ ){ return false; }
|
||||
virtual bool OnKeyEnd( bool /*bDown*/ ){ return false; }
|
||||
virtual bool OnKeyUp( bool /*bDown*/ ){ return false; }
|
||||
virtual bool OnKeyDown( bool /*bDown*/ ){ return false; }
|
||||
virtual bool OnKeyEscape( bool /*bDown*/ ) { return false; }
|
||||
|
||||
virtual void OnMouseEnter();
|
||||
virtual void OnMouseLeave();
|
||||
virtual bool IsHovered();
|
||||
virtual bool ShouldDrawHover();
|
||||
|
||||
virtual void Touch();
|
||||
virtual void OnChildTouched( Controls::Base* pChild );
|
||||
|
||||
virtual bool IsOnTop();
|
||||
|
||||
virtual bool HasFocus();
|
||||
virtual void Focus();
|
||||
virtual void Blur();
|
||||
|
||||
//Other
|
||||
virtual void SetDisabled( bool active ) { if ( m_bDisabled == active ) return; m_bDisabled = active; Redraw(); }
|
||||
virtual bool IsDisabled(){ return m_bDisabled; }
|
||||
|
||||
virtual void Redraw(){ UpdateColours(); m_bCacheTextureDirty = true; if ( m_Parent ) m_Parent->Redraw(); }
|
||||
virtual void UpdateColours(){};
|
||||
virtual void SetCacheToTexture() { m_bCacheToTexture = true; }
|
||||
virtual bool ShouldCacheToTexture() { return m_bCacheToTexture; }
|
||||
|
||||
virtual void SetCursor( unsigned char c ){ m_Cursor = c; }
|
||||
virtual void UpdateCursor();
|
||||
|
||||
virtual Gwen::Point GetMinimumSize(){ return Gwen::Point( 1, 1 ); }
|
||||
virtual Gwen::Point GetMaximumSize(){ return Gwen::Point( 4096, 4096 ); }
|
||||
|
||||
virtual void SetToolTip( const Gwen::TextObject& strText );
|
||||
virtual void SetToolTip( Base* tooltip ) { m_ToolTip = tooltip; if ( m_ToolTip ){ m_ToolTip->SetParent( this ); m_ToolTip->SetHidden( true ); } }
|
||||
virtual Base* GetToolTip() { return m_ToolTip; }
|
||||
|
||||
virtual bool IsMenuComponent();
|
||||
virtual void CloseMenus();
|
||||
|
||||
virtual bool IsTabable() { return m_Tabable; }
|
||||
virtual void SetTabable( bool isTabable ) { m_Tabable = isTabable; }
|
||||
|
||||
|
||||
|
||||
|
||||
//Accelerator functionality
|
||||
void DefaultAccel( Gwen::Controls::Base* /*pCtrl*/ ) { AcceleratePressed(); }
|
||||
virtual void AcceleratePressed() {};
|
||||
virtual bool AccelOnlyFocus() { return false; }
|
||||
virtual bool HandleAccelerator( Gwen::String& accelerator );
|
||||
|
||||
template <typename T>
|
||||
void AddAccelerator( const TextObject& accelerator, T func, Gwen::Event::Handler* handler = NULL )
|
||||
{
|
||||
if ( handler == NULL )
|
||||
handler = this;
|
||||
|
||||
Gwen::Event::Caller* caller = new Gwen::Event::Caller();
|
||||
caller->Add( handler, func );
|
||||
|
||||
Gwen::String str = accelerator.Get();
|
||||
|
||||
Gwen::Utility::Strings::ToUpper( str );
|
||||
Gwen::Utility::Strings::Strip( str, " " );
|
||||
|
||||
m_Accelerators[ str ] = caller;
|
||||
}
|
||||
|
||||
void AddAccelerator( const TextObject& accelerator )
|
||||
{
|
||||
AddAccelerator( accelerator, &Base::DefaultAccel, this );
|
||||
}
|
||||
|
||||
AccelMap m_Accelerators;
|
||||
|
||||
// Default Events
|
||||
|
||||
Gwen::Event::Caller onHoverEnter;
|
||||
Gwen::Event::Caller onHoverLeave;
|
||||
|
||||
// Childrens List
|
||||
|
||||
Base::List Children;
|
||||
|
||||
protected:
|
||||
|
||||
// The logical parent
|
||||
// It's usually what you expect, the control you've parented it to.
|
||||
Base* m_Parent;
|
||||
|
||||
// If the innerpanel exists our children will automatically
|
||||
// become children of that instead of us - allowing us to move
|
||||
// them all around by moving that panel (useful for scrolling etc)
|
||||
Base* m_InnerPanel;
|
||||
virtual Base* Inner(){ return m_InnerPanel; }
|
||||
|
||||
// This is the panel's actual parent - most likely the logical
|
||||
// parent's InnerPanel (if it has one). You should rarely need this.
|
||||
Base* m_ActualParent;
|
||||
|
||||
Base* m_ToolTip;
|
||||
|
||||
Skin::Base* m_Skin;
|
||||
|
||||
Gwen::Rect m_Bounds;
|
||||
Gwen::Rect m_RenderBounds;
|
||||
|
||||
Padding m_Padding;
|
||||
Margin m_Margin;
|
||||
|
||||
Gwen::String m_Name;
|
||||
|
||||
|
||||
bool m_bRestrictToParent;
|
||||
bool m_bDisabled;
|
||||
bool m_bHidden;
|
||||
bool m_bMouseInputEnabled;
|
||||
bool m_bKeyboardInputEnabled;
|
||||
bool m_bDrawBackground;
|
||||
|
||||
int m_iDock;
|
||||
|
||||
unsigned char m_Cursor;
|
||||
|
||||
bool m_Tabable;
|
||||
|
||||
public:
|
||||
|
||||
bool NeedsLayout(){ return m_bNeedsLayout; }
|
||||
void Invalidate();
|
||||
void InvalidateParent(){ if ( m_Parent ){ m_Parent->Invalidate(); } }
|
||||
void InvalidateChildren( bool bRecursive = false );
|
||||
void Position( int pos, int xpadding = 0, int ypadding = 0 );
|
||||
|
||||
protected:
|
||||
|
||||
virtual void RecurseLayout( Skin::Base* skin );
|
||||
virtual void Layout( Skin::Base* skin );
|
||||
virtual void PostLayout( Skin::Base* /*skin*/ ){};
|
||||
|
||||
bool m_bNeedsLayout;
|
||||
bool m_bCacheTextureDirty;
|
||||
bool m_bCacheToTexture;
|
||||
|
||||
//
|
||||
// Drag + Drop
|
||||
public:
|
||||
|
||||
// Giver
|
||||
|
||||
virtual void DragAndDrop_SetPackage( bool bDraggable, const String& strName = "", void* pUserData = NULL );
|
||||
virtual bool DragAndDrop_Draggable();
|
||||
virtual bool DragAndDrop_ShouldStartDrag(){ return true; }
|
||||
virtual void DragAndDrop_StartDragging( Gwen::DragAndDrop::Package* pPackage, int x, int y );
|
||||
virtual Gwen::DragAndDrop::Package* DragAndDrop_GetPackage( int x, int y );
|
||||
virtual void DragAndDrop_EndDragging( bool /*bSuccess*/, int /*x*/, int /*y*/ ){};
|
||||
|
||||
protected:
|
||||
|
||||
DragAndDrop::Package* m_DragAndDrop_Package;
|
||||
|
||||
public:
|
||||
|
||||
// Receiver
|
||||
virtual void DragAndDrop_HoverEnter( Gwen::DragAndDrop::Package* /*pPackage*/, int /*x*/, int /*y*/ ){ }
|
||||
virtual void DragAndDrop_HoverLeave( Gwen::DragAndDrop::Package* /*pPackage*/ ){ }
|
||||
virtual void DragAndDrop_Hover( Gwen::DragAndDrop::Package* /*pPackage*/, int /*x*/, int /*y*/ ){};
|
||||
virtual bool DragAndDrop_HandleDrop( Gwen::DragAndDrop::Package* pPackage, int x, int y );
|
||||
virtual bool DragAndDrop_CanAcceptPackage( Gwen::DragAndDrop::Package* /*pPackage*/ ){ return false; }
|
||||
|
||||
|
||||
//
|
||||
// Useful anim shortcuts
|
||||
//
|
||||
public:
|
||||
#ifndef GWEN_NO_ANIMATION
|
||||
|
||||
virtual void Anim_WidthIn( float fLength, float fDelay = 0.0f, float fEase = 1.0f );
|
||||
virtual void Anim_HeightIn( float fLength, float fDelay = 0.0f, float fEase = 1.0f );
|
||||
virtual void Anim_WidthOut( float fLength, bool bHide = true, float fDelay = 0.0f, float fEase = 1.0f );
|
||||
virtual void Anim_HeightOut( float fLength, bool bHide = true, float fDelay = 0.0f, float fEase = 1.0f );
|
||||
|
||||
#endif
|
||||
|
||||
//
|
||||
// Dynamic casting, see gwen_cast below
|
||||
//
|
||||
public:
|
||||
|
||||
static const char* GetIdentifier()
|
||||
{
|
||||
static const char* ident = "Base";
|
||||
return ident;
|
||||
};
|
||||
|
||||
virtual Gwen::Controls::Base* DynamicCast( const char* Variable )
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
public:
|
||||
|
||||
void DoNotIncludeInSize(){ m_bIncludeInSize = false; }
|
||||
bool ShouldIncludeInSize(){ return m_bIncludeInSize; }
|
||||
|
||||
protected:
|
||||
|
||||
bool m_bIncludeInSize;
|
||||
|
||||
public:
|
||||
|
||||
virtual void DoAction(){};
|
||||
virtual void SetAction( Event::Handler* pObject, Handler::FunctionWithInformation pFunction, const Gwen::Event::Packet& packet ){};
|
||||
|
||||
virtual int GetNamedChildren( Gwen::ControlList& list, const Gwen::String& strName, bool bDeep = true );
|
||||
virtual Gwen::ControlList GetNamedChildren( const Gwen::String& strName, bool bDeep = true );
|
||||
|
||||
public:
|
||||
|
||||
UserDataStorage UserData;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
/*
|
||||
To avoid using dynamic_cast we have gwen_cast.
|
||||
|
||||
Each class in Gwen includes GWEN_DYNAMIC. You don't have to include this macro anywhere as it's
|
||||
automatically included in the GWEN_CONTROL macro.
|
||||
|
||||
GWEN_DYNAMIC adds 2 functions:
|
||||
|
||||
GetIdentifier - a static function with a static variable inside, which returns
|
||||
the address of the static variable. The variable is defined as a
|
||||
string containing "BASECLASSNAME:CLASSNAME". This string should be
|
||||
as unique as possible - or the compiler might optimize the variables
|
||||
together - which means that when this function returns the address it
|
||||
could be the same on one or more variables. Something to bear in mind.
|
||||
|
||||
DynamicCast - non static, takes an address returned by GetIdentifier. Will return an
|
||||
address of a control if the control can safely be cast to the class from
|
||||
which the identifier was taken.
|
||||
|
||||
Really you shouldn't actually have to concenn yourself with that stuff. The only thing you
|
||||
should use in theory is gwen_cast - which is used just the same as dynamic cast - except for
|
||||
one difference. We pass in the class name, not a pointer to the class.
|
||||
|
||||
gwen_cast<MyControl>(control)
|
||||
dynamic_cast<MyControl*>(control)
|
||||
|
||||
*/
|
||||
|
||||
template< class T >
|
||||
T* gwen_cast( Gwen::Controls::Base* p )
|
||||
{
|
||||
if ( !p ) return NULL;
|
||||
|
||||
Gwen::Controls::Base* pReturn = p->DynamicCast( T::GetIdentifier() );
|
||||
if ( !pReturn ) return NULL;
|
||||
|
||||
return static_cast<T*>(pReturn);
|
||||
}
|
||||
|
||||
|
||||
template <typename T>
|
||||
T* Gwen::Controls::Base::FindChild( const Gwen::String& name, bool bRecursive )
|
||||
{
|
||||
return gwen_cast<T>( FindChildByName( name, bRecursive ) );
|
||||
}
|
||||
|
||||
#define GWEN_DYNAMIC( ThisName, BaseName ) \
|
||||
\
|
||||
static const char* GetIdentifier() \
|
||||
{ \
|
||||
static const char* ident = #BaseName ":" #ThisName; \
|
||||
return ident; \
|
||||
}; \
|
||||
virtual Gwen::Controls::Base* DynamicCast( const char* Variable ) \
|
||||
{ \
|
||||
if ( GetIdentifier() == Variable ) \
|
||||
return this; \
|
||||
\
|
||||
return BaseClass::DynamicCast( Variable); \
|
||||
}
|
||||
|
||||
#define GWEN_CLASS( ThisName, BaseName )\
|
||||
typedef BaseName BaseClass;\
|
||||
typedef ThisName ThisClass;\
|
||||
|
||||
// To be placed in the controls .h definition.
|
||||
#define GWEN_CONTROL( ThisName, BaseName )\
|
||||
public:\
|
||||
GWEN_CLASS( ThisName, BaseName )\
|
||||
GWEN_DYNAMIC( ThisName, BaseName )\
|
||||
virtual const char* GetTypeName(){ return #ThisName; }\
|
||||
virtual const char* GetBaseTypeName(){ return BaseClass::GetTypeName(); }\
|
||||
ThisName( Gwen::Controls::Base* pParent, const Gwen::String& pName = "" )
|
||||
|
||||
#define GWEN_CONTROL_INLINE( ThisName, BaseName )\
|
||||
GWEN_CONTROL( ThisName, BaseName ) : BaseClass( pParent, pName )
|
||||
|
||||
#define GWEN_CONTROL_CONSTRUCTOR( ThisName )\
|
||||
ThisName::ThisName( Gwen::Controls::Base* pParent, const Gwen::String& pName ) : BaseClass( pParent, pName )
|
||||
|
||||
|
||||
|
||||
#endif
|
286
lib/gwen/controls/gwen_button.cpp
Normal file
286
lib/gwen/controls/gwen_button.cpp
Normal file
|
@ -0,0 +1,286 @@
|
|||
/*
|
||||
GWEN
|
||||
Copyright (c) 2010 Facepunch Studios
|
||||
See license in Gwen.h
|
||||
*/
|
||||
|
||||
|
||||
#include "../gwen.h"
|
||||
#include "../gwen_skin.h"
|
||||
#include "gwen_button.h"
|
||||
#include "gwen_imagepanel.h"
|
||||
#include <math.h>
|
||||
|
||||
using namespace Gwen;
|
||||
using namespace Gwen::Controls;
|
||||
|
||||
|
||||
GWEN_CONTROL_CONSTRUCTOR( Button )
|
||||
{
|
||||
m_Image = NULL;
|
||||
m_bDepressed = false;
|
||||
m_bCenterImage = false;
|
||||
|
||||
SetSize( 100, 20 );
|
||||
SetMouseInputEnabled( true );
|
||||
SetIsToggle( false );
|
||||
SetAlignment( Gwen::Pos::Center );
|
||||
SetTextPadding( Padding( 3, 0, 3, 0 ) );
|
||||
m_bToggleStatus = false;
|
||||
SetKeyboardInputEnabled( false );
|
||||
SetTabable( false );
|
||||
}
|
||||
|
||||
void Button::Render( Skin::Base* skin )
|
||||
{
|
||||
if ( !ShouldDrawBackground() ) return;
|
||||
|
||||
bool bDrawDepressed = IsDepressed() && IsHovered();
|
||||
if ( IsToggle() ) bDrawDepressed = bDrawDepressed || GetToggleState();
|
||||
|
||||
bool bDrawHovered = IsHovered() && ShouldDrawHover();
|
||||
|
||||
skin->DrawButton( this, bDrawDepressed, bDrawHovered, IsDisabled() );
|
||||
}
|
||||
|
||||
void Button::OnMouseClickLeft( int /*x*/, int /*y*/, bool bDown )
|
||||
{
|
||||
if ( IsDisabled() ) return;
|
||||
|
||||
if ( bDown )
|
||||
{
|
||||
SetDepressed( true );
|
||||
Gwen::MouseFocus = this;
|
||||
onDown.Call( this );
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( IsHovered() && m_bDepressed )
|
||||
{
|
||||
OnPress();
|
||||
}
|
||||
|
||||
SetDepressed( false );
|
||||
Gwen::MouseFocus = NULL;
|
||||
onUp.Call( this );
|
||||
}
|
||||
}
|
||||
|
||||
void Button::OnMouseClickRight( int /*x*/, int /*y*/, bool bDown )
|
||||
{
|
||||
if ( IsDisabled() ) return;
|
||||
|
||||
if ( bDown )
|
||||
{
|
||||
SetDepressed( true );
|
||||
Gwen::MouseFocus = this;
|
||||
onDown.Call( this );
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( IsHovered() && m_bDepressed )
|
||||
{
|
||||
OnRightPress();
|
||||
}
|
||||
|
||||
SetDepressed( false );
|
||||
Gwen::MouseFocus = NULL;
|
||||
onUp.Call( this );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Button::SetDepressed( bool b )
|
||||
{
|
||||
if ( m_bDepressed == b ) return;
|
||||
|
||||
m_bDepressed = b;
|
||||
Redraw();
|
||||
}
|
||||
|
||||
void Button::OnRightPress()
|
||||
{
|
||||
onRightPress.Call( this );
|
||||
}
|
||||
|
||||
void Button::OnPress()
|
||||
{
|
||||
if ( IsToggle() )
|
||||
{
|
||||
SetToggleState( !GetToggleState() );
|
||||
}
|
||||
|
||||
onPress.Call( this );
|
||||
}
|
||||
|
||||
|
||||
void Button::SetImage( const Texture& texture, bool bCenter )
|
||||
{
|
||||
if ( !m_Image )
|
||||
{
|
||||
m_Image = new ImagePanel( this );
|
||||
}
|
||||
|
||||
m_Image->SetImage( texture );
|
||||
m_Image->SizeToContents();
|
||||
m_Image->SetMargin( Margin( 2, 0, 2, 0 ) );
|
||||
m_bCenterImage = bCenter;
|
||||
|
||||
// Ugh.
|
||||
Padding padding = GetTextPadding();
|
||||
padding.left = m_Image->Right() + 2;
|
||||
SetTextPadding( padding );
|
||||
}
|
||||
|
||||
void Button::SetImage( const Texture& texture, float u1, float v1, float u2, float v2, bool bCenter )
|
||||
{
|
||||
if ( !m_Image )
|
||||
{
|
||||
m_Image = new ImagePanel( this );
|
||||
}
|
||||
|
||||
//float texCoordWidth = u2 - u1;
|
||||
//float texCoordHeight = v2 - v1;
|
||||
//float width = ((float)texture.width * texCoordWidth);
|
||||
//float height = ((float)texture.height * texCoordHeight);
|
||||
//
|
||||
//// HACK: is rounding up really the best way to do this? perhaps we should
|
||||
//// allow a pixel width/height to be passed in ...
|
||||
//width = floorf(width + 0.5f);
|
||||
//height = floorf(height + 0.5f);
|
||||
|
||||
int maxWidth = Width() - 4;
|
||||
int maxHeight = Height() - 4;
|
||||
|
||||
m_Image->SetImage(texture);
|
||||
//m_Image->SizeToContents();
|
||||
m_Image->SetSize(maxWidth, maxHeight);
|
||||
m_Image->SetMargin( Margin( 2, 0, 2, 0 ) );
|
||||
m_Image->SetUV(u1, v1, u2, v2);
|
||||
m_bCenterImage = bCenter;
|
||||
|
||||
// Ugh.
|
||||
Padding padding = GetTextPadding();
|
||||
padding.left = m_Image->Right() + 2;
|
||||
SetTextPadding( padding );
|
||||
}
|
||||
|
||||
void Button::SetImage( const TextObject& strName, bool bCenter )
|
||||
{
|
||||
if ( strName.Get() == "" )
|
||||
{
|
||||
if ( m_Image )
|
||||
{
|
||||
delete m_Image;
|
||||
m_Image= NULL;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if ( !m_Image )
|
||||
{
|
||||
m_Image = new ImagePanel( this );
|
||||
}
|
||||
|
||||
m_Image->SetImage( strName );
|
||||
m_Image->SizeToContents();
|
||||
m_Image->SetMargin( Margin( 2, 0, 2, 0 ) );
|
||||
m_bCenterImage = bCenter;
|
||||
|
||||
// Ugh.
|
||||
Padding padding = GetTextPadding();
|
||||
padding.left = m_Image->Right() + 2;
|
||||
SetTextPadding( padding );
|
||||
}
|
||||
|
||||
void Button::SetToggleState( bool b )
|
||||
{
|
||||
if ( m_bToggleStatus == b ) return;
|
||||
|
||||
m_bToggleStatus = b;
|
||||
|
||||
onToggle.Call( this );
|
||||
|
||||
if ( m_bToggleStatus )
|
||||
{
|
||||
onToggleOn.Call( this );
|
||||
}
|
||||
else
|
||||
{
|
||||
onToggleOff.Call( this );
|
||||
}
|
||||
|
||||
Redraw();
|
||||
}
|
||||
|
||||
void Button::SizeToContents()
|
||||
{
|
||||
BaseClass::SizeToContents();
|
||||
|
||||
if ( m_Image )
|
||||
{
|
||||
int height = m_Image->Height() + 4;
|
||||
if ( Height() < height )
|
||||
{
|
||||
SetHeight( height );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool Button::OnKeySpace( bool bDown )
|
||||
{
|
||||
if ( bDown )
|
||||
{
|
||||
OnPress();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Button::AcceleratePressed()
|
||||
{
|
||||
OnPress();
|
||||
}
|
||||
|
||||
void Button::UpdateColours()
|
||||
{
|
||||
if ( IsDisabled() ) return SetTextColor( GetSkin()->Colors.Button.Disabled );
|
||||
if ( IsDepressed() || GetToggleState() ) return SetTextColor( GetSkin()->Colors.Button.Down );
|
||||
if ( IsHovered() ) return SetTextColor( GetSkin()->Colors.Button.Hover );
|
||||
|
||||
SetTextColor( GetSkin()->Colors.Button.Normal );
|
||||
}
|
||||
|
||||
void Button::PostLayout( Skin::Base* pSkin )
|
||||
{
|
||||
BaseClass::PostLayout( pSkin );
|
||||
|
||||
if ( m_Image )
|
||||
{
|
||||
if ( m_bCenterImage )
|
||||
m_Image->Position( Pos::Center );
|
||||
else
|
||||
m_Image->Position( Pos::Left | Pos::CenterV );
|
||||
}
|
||||
}
|
||||
|
||||
void Button::OnMouseDoubleClickLeft( int x, int y )
|
||||
{
|
||||
if ( IsDisabled() ) return;
|
||||
|
||||
OnMouseClickLeft( x, y, true );
|
||||
onDoubleClick.Call( this );
|
||||
}
|
||||
|
||||
void Button::SetImageAlpha( float f )
|
||||
{
|
||||
if ( !m_Image ) return;
|
||||
|
||||
m_Image->SetDrawColor( Gwen::Color( 255, 255, 255, 255.0f * f ) );
|
||||
}
|
||||
|
||||
void Button::SetAction( Event::Handler* pObject, Handler::FunctionWithInformation pFunction, const Gwen::Event::Packet& packet )
|
||||
{
|
||||
onPress.Add( pObject, pFunction, packet );
|
||||
}
|
88
lib/gwen/controls/gwen_button.h
Normal file
88
lib/gwen/controls/gwen_button.h
Normal file
|
@ -0,0 +1,88 @@
|
|||
/*
|
||||
GWEN
|
||||
Copyright (c) 2010 Facepunch Studios
|
||||
See license in Gwen.h
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#ifndef GWEN_CONTROLS_BUTTON_H
|
||||
#define GWEN_CONTROLS_BUTTON_H
|
||||
|
||||
#include "gwen_base.h"
|
||||
#include "gwen_label.h"
|
||||
#include "../gwen_texture.h"
|
||||
|
||||
namespace Gwen
|
||||
{
|
||||
namespace Controls
|
||||
{
|
||||
class ImagePanel;
|
||||
|
||||
class GWEN_EXPORT Button : public Label
|
||||
{
|
||||
public:
|
||||
|
||||
GWEN_CONTROL( Button, Label );
|
||||
|
||||
virtual void Render( Skin::Base* skin );
|
||||
virtual void OnMouseClickLeft( int x, int y, bool bDown );
|
||||
virtual void OnMouseClickRight( int x, int y, bool bDown );
|
||||
virtual void OnMouseDoubleClickLeft( int x, int y );
|
||||
virtual bool OnKeySpace( bool bDown );
|
||||
|
||||
virtual void OnPress();
|
||||
virtual void OnRightPress();
|
||||
|
||||
virtual void AcceleratePressed();
|
||||
|
||||
virtual bool IsDepressed() const { return m_bDepressed; }
|
||||
virtual void SetDepressed( bool b );
|
||||
|
||||
//
|
||||
// Buttons can be toggle type, which means that it is
|
||||
// toggled on and off. Its toggle status is in IsDepressed.
|
||||
//
|
||||
virtual void SetIsToggle( bool b ){ m_bToggle = b; }
|
||||
virtual bool IsToggle() const { return m_bToggle; }
|
||||
virtual bool GetToggleState() const { return m_bToggleStatus; }
|
||||
virtual void SetToggleState( bool b );
|
||||
virtual void Toggle(){ SetToggleState( !GetToggleState() ); }
|
||||
|
||||
|
||||
virtual void SetImage( const Texture& texture, bool bCenter = false );
|
||||
virtual void SetImage( const Texture& texture, float u1, float v1, float u2, float v2, bool bCenter = false );
|
||||
virtual void SetImage( const TextObject& strName, bool bCenter = false );
|
||||
|
||||
virtual void SizeToContents();
|
||||
virtual void PostLayout( Skin::Base* pSkin );
|
||||
virtual void UpdateColours();
|
||||
|
||||
virtual void SetImageAlpha( float fMultiply );
|
||||
|
||||
virtual void DoAction(){ OnPress(); }
|
||||
virtual void SetAction( Event::Handler* pObject, Handler::FunctionWithInformation pFunction, const Gwen::Event::Packet& packet );
|
||||
|
||||
public:
|
||||
|
||||
Gwen::Event::Caller onPress;
|
||||
Gwen::Event::Caller onRightPress;
|
||||
Gwen::Event::Caller onDown;
|
||||
Gwen::Event::Caller onUp;
|
||||
Gwen::Event::Caller onDoubleClick;
|
||||
Gwen::Event::Caller onToggle;
|
||||
Gwen::Event::Caller onToggleOn;
|
||||
Gwen::Event::Caller onToggleOff;
|
||||
|
||||
protected:
|
||||
|
||||
ImagePanel* m_Image;
|
||||
|
||||
bool m_bDepressed;
|
||||
bool m_bToggle;
|
||||
bool m_bToggleStatus;
|
||||
|
||||
bool m_bCenterImage;
|
||||
};
|
||||
}
|
||||
}
|
||||
#endif
|
243
lib/gwen/controls/gwen_canvas.cpp
Normal file
243
lib/gwen/controls/gwen_canvas.cpp
Normal file
|
@ -0,0 +1,243 @@
|
|||
/*
|
||||
GWEN
|
||||
Copyright (c) 2010 Facepunch Studios
|
||||
See license in Gwen.h
|
||||
*/
|
||||
|
||||
|
||||
#include "../gwen.h"
|
||||
#include "gwen_canvas.h"
|
||||
#include "../gwen_skin.h"
|
||||
#include "gwen_menu.h"
|
||||
#include "../gwen_draganddrop.h"
|
||||
#include "../gwen_tooltip.h"
|
||||
|
||||
#ifndef GWEN_NO_ANIMATION
|
||||
#include "../gwen_anim.h"
|
||||
#endif
|
||||
|
||||
using namespace Gwen::Controls;
|
||||
|
||||
|
||||
Canvas::Canvas( Gwen::Skin::Base* pSkin ) : BaseClass( NULL ), m_bAnyDelete( false )
|
||||
{
|
||||
SetBounds( 0, 0, 10000, 10000 );
|
||||
|
||||
SetScale( 1.0f );
|
||||
SetBackgroundColor( Color( 255, 255, 255, 255 ) );
|
||||
SetDrawBackground( false );
|
||||
|
||||
if ( pSkin ) SetSkin( pSkin );
|
||||
}
|
||||
|
||||
Canvas::~Canvas()
|
||||
{
|
||||
ReleaseChildren();
|
||||
}
|
||||
|
||||
void Canvas::RenderCanvas()
|
||||
{
|
||||
DoThink();
|
||||
|
||||
Gwen::Renderer::Base* render = m_Skin->GetRender();
|
||||
|
||||
render->Begin();
|
||||
|
||||
RecurseLayout( m_Skin );
|
||||
|
||||
render->SetClipRegion( GetBounds() );
|
||||
render->SetRenderOffset( Gwen::Point( 0, 0 ) );
|
||||
render->SetScale( Scale() );
|
||||
|
||||
if ( m_bDrawBackground )
|
||||
{
|
||||
render->SetDrawColor( m_BackgroundColor );
|
||||
render->DrawFilledRect( GetRenderBounds() );
|
||||
}
|
||||
|
||||
DoRender( m_Skin );
|
||||
|
||||
DragAndDrop::RenderOverlay( this, m_Skin );
|
||||
|
||||
ToolTip::RenderToolTip( m_Skin );
|
||||
|
||||
render->End();
|
||||
}
|
||||
|
||||
void Canvas::Render( Gwen::Skin::Base* /*pRender*/ )
|
||||
{
|
||||
m_bNeedsRedraw = false;
|
||||
}
|
||||
|
||||
void Canvas::OnBoundsChanged( Gwen::Rect oldBounds )
|
||||
{
|
||||
BaseClass::OnBoundsChanged( oldBounds );
|
||||
InvalidateChildren( true );
|
||||
}
|
||||
|
||||
|
||||
void Canvas::DoThink()
|
||||
{
|
||||
ProcessDelayedDeletes();
|
||||
|
||||
if ( Hidden() ) return;
|
||||
|
||||
#ifndef GWEN_NO_ANIMATION
|
||||
Gwen::Anim::Think();
|
||||
#endif
|
||||
|
||||
// Reset tabbing
|
||||
{
|
||||
NextTab = NULL;
|
||||
FirstTab = NULL;
|
||||
}
|
||||
|
||||
ProcessDelayedDeletes();
|
||||
// Check has focus etc..
|
||||
RecurseLayout( m_Skin );
|
||||
|
||||
// If we didn't have a next tab, cycle to the start.
|
||||
if ( NextTab == NULL )
|
||||
NextTab = FirstTab;
|
||||
|
||||
Gwen::Input::OnCanvasThink( this );
|
||||
|
||||
}
|
||||
|
||||
void Canvas::SetScale( float f )
|
||||
{
|
||||
if ( m_fScale == f ) return;
|
||||
|
||||
m_fScale = f;
|
||||
|
||||
if ( m_Skin && m_Skin->GetRender() )
|
||||
m_Skin->GetRender()->SetScale( m_fScale );
|
||||
|
||||
OnScaleChanged();
|
||||
Redraw();
|
||||
}
|
||||
|
||||
void Canvas::AddDelayedDelete( Gwen::Controls::Base* pControl )
|
||||
{
|
||||
if ( !m_bAnyDelete || m_DeleteSet.find( pControl ) == m_DeleteSet.end() )
|
||||
{
|
||||
m_bAnyDelete = true;
|
||||
m_DeleteSet.insert( pControl );
|
||||
m_DeleteList.push_back( pControl );
|
||||
}
|
||||
}
|
||||
|
||||
void Canvas::PreDeleteControl( Controls::Base * pControl )
|
||||
{
|
||||
if ( m_bAnyDelete )
|
||||
{
|
||||
stl::set< Controls::Base * >::iterator itFind;
|
||||
if ( ( itFind = m_DeleteSet.find( pControl ) ) != m_DeleteSet.end() )
|
||||
{
|
||||
m_DeleteList.remove( pControl );
|
||||
m_DeleteSet.erase( pControl );
|
||||
m_bAnyDelete = !m_DeleteSet.empty();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Canvas::ProcessDelayedDeletes()
|
||||
{
|
||||
|
||||
while( m_bAnyDelete )
|
||||
{
|
||||
m_bAnyDelete = false;
|
||||
|
||||
Controls::Base::List deleteList = m_DeleteList;
|
||||
|
||||
m_DeleteList.clear();
|
||||
m_DeleteSet.clear();
|
||||
|
||||
for ( Gwen::Controls::Base::List::iterator it = deleteList.begin(); it != deleteList.end(); ++it )
|
||||
{
|
||||
Gwen::Controls::Base* pControl = *it;
|
||||
pControl->PreDelete( GetSkin() );
|
||||
delete pControl;
|
||||
|
||||
Redraw();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Canvas::ReleaseChildren()
|
||||
{
|
||||
Base::List::iterator iter = Children.begin();
|
||||
while ( iter != Children.end() )
|
||||
{
|
||||
Base* pChild = *iter;
|
||||
iter = Children.erase( iter );
|
||||
delete pChild;
|
||||
}
|
||||
}
|
||||
|
||||
bool Canvas::InputMouseMoved( int x, int y, int deltaX, int deltaY )
|
||||
{
|
||||
if ( Hidden() ) return false;
|
||||
|
||||
if ( ToolTip::TooltipActive() )
|
||||
Redraw();
|
||||
|
||||
// Todo: Handle scaling here..
|
||||
//float fScale = 1.0f / Scale();
|
||||
|
||||
Gwen::Input::OnMouseMoved( this, x, y, deltaX, deltaY );
|
||||
|
||||
if ( !Gwen::HoveredControl ) return false;
|
||||
if ( Gwen::HoveredControl == this ) return false;
|
||||
if ( Gwen::HoveredControl->GetCanvas() != this ) return false;
|
||||
|
||||
Gwen::HoveredControl->OnMouseMoved( x, y, deltaX, deltaY );
|
||||
Gwen::HoveredControl->UpdateCursor();
|
||||
|
||||
DragAndDrop::OnMouseMoved( Gwen::HoveredControl, x, y );
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Canvas::InputMouseButton( int iButton, bool bDown )
|
||||
{
|
||||
if ( Hidden() ) return false;
|
||||
|
||||
return Gwen::Input::OnMouseClicked( this, iButton, bDown );
|
||||
}
|
||||
|
||||
bool Canvas::InputKey( int iKey, bool bDown )
|
||||
{
|
||||
if ( Hidden() ) return false;
|
||||
if ( iKey <= Gwen::Key::Invalid ) return false;
|
||||
if ( iKey >= Gwen::Key::Count ) return false;
|
||||
|
||||
return Gwen::Input::OnKeyEvent( this, iKey, bDown );
|
||||
}
|
||||
|
||||
bool Canvas::InputCharacter( char chr )
|
||||
{
|
||||
if ( Hidden() ) return false;
|
||||
if ( !isprint( chr ) ) return false;
|
||||
|
||||
//Handle Accelerators
|
||||
if ( Gwen::Input::HandleAccelerator( this, chr ) )
|
||||
return true;
|
||||
|
||||
//Handle characters
|
||||
if ( !Gwen::KeyboardFocus ) return false;
|
||||
if ( Gwen::KeyboardFocus->GetCanvas() != this ) return false;
|
||||
if ( !Gwen::KeyboardFocus->Visible() ) return false;
|
||||
if ( Gwen::Input::IsControlDown() ) return false;
|
||||
|
||||
return KeyboardFocus->OnChar( chr );
|
||||
}
|
||||
|
||||
bool Canvas::InputMouseWheel( int val )
|
||||
{
|
||||
if ( Hidden() ) return false;
|
||||
if ( !Gwen::HoveredControl ) return false;
|
||||
if ( Gwen::HoveredControl == this ) return false;
|
||||
if ( Gwen::HoveredControl->GetCanvas() != this ) return false;
|
||||
|
||||
return Gwen::HoveredControl->OnMouseWheeled( val );
|
||||
}
|
106
lib/gwen/controls/gwen_canvas.h
Normal file
106
lib/gwen/controls/gwen_canvas.h
Normal file
|
@ -0,0 +1,106 @@
|
|||
/*
|
||||
GWEN
|
||||
Copyright (c) 2010 Facepunch Studios
|
||||
See license in Gwen.h
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#ifndef GWEN_CONTROLS_CANVAS_H
|
||||
#define GWEN_CONTROLS_CANVAS_H
|
||||
|
||||
#include <stl/set.h>
|
||||
#include "gwen_base.h"
|
||||
#include "../gwen_inputhandler.h"
|
||||
|
||||
namespace Gwen
|
||||
{
|
||||
namespace Controls
|
||||
{
|
||||
class GWEN_EXPORT Canvas : public Base
|
||||
{
|
||||
public:
|
||||
|
||||
typedef Controls::Base BaseClass;
|
||||
|
||||
Canvas( Skin::Base* pSkin );
|
||||
virtual ~Canvas();
|
||||
|
||||
//
|
||||
// For additional initialization
|
||||
// (which is sometimes not appropriate in the constructor)
|
||||
//
|
||||
virtual void Initialize(){};
|
||||
|
||||
//
|
||||
// You should call this to render your canvas.
|
||||
//
|
||||
virtual void RenderCanvas();
|
||||
|
||||
//
|
||||
// Call this whenever you want to process input. This
|
||||
// is usually once a frame..
|
||||
//
|
||||
virtual void DoThink();
|
||||
|
||||
//
|
||||
// In most situations you will be rendering the canvas
|
||||
// every frame. But in some situations you will only want
|
||||
// to render when there have been changes. You can do this
|
||||
// by checking NeedsRedraw().
|
||||
//
|
||||
virtual bool NeedsRedraw(){ return m_bNeedsRedraw; }
|
||||
virtual void Redraw(){ m_bNeedsRedraw = true; }
|
||||
|
||||
// Internal. Do not call directly.
|
||||
virtual void Render( Skin::Base* pRender );
|
||||
|
||||
// Childpanels call parent->GetCanvas() until they get to
|
||||
// this top level function.
|
||||
virtual Controls::Canvas* GetCanvas(){ return this; }
|
||||
|
||||
virtual void SetScale( float f );
|
||||
virtual float Scale() const { return m_fScale; }
|
||||
|
||||
virtual void OnBoundsChanged( Gwen::Rect oldBounds );
|
||||
|
||||
// Delete all children (this is done called in the destructor too)
|
||||
virtual void ReleaseChildren();
|
||||
|
||||
// Delayed deletes
|
||||
virtual void AddDelayedDelete( Controls::Base* pControl );
|
||||
virtual void ProcessDelayedDeletes();
|
||||
|
||||
Controls::Base* FirstTab;
|
||||
Controls::Base* NextTab;
|
||||
|
||||
// Input
|
||||
virtual bool InputMouseMoved( int x, int y, int deltaX, int deltaY );
|
||||
virtual bool InputMouseButton( int iButton, bool bDown );
|
||||
virtual bool InputKey( int iKey, bool bDown );
|
||||
virtual bool InputCharacter( char chr );
|
||||
virtual bool InputMouseWheel( int val );
|
||||
virtual bool InputQuit(){ return true; };
|
||||
|
||||
// Background
|
||||
virtual void SetBackgroundColor( const Gwen::Color& color ){ m_BackgroundColor = color; }
|
||||
virtual void SetDrawBackground( bool bShouldDraw ){ m_bDrawBackground = bShouldDraw; }
|
||||
|
||||
protected:
|
||||
|
||||
bool m_bNeedsRedraw;
|
||||
bool m_bAnyDelete;
|
||||
float m_fScale;
|
||||
|
||||
Controls::Base::List m_DeleteList;
|
||||
stl::set< Controls::Base* > m_DeleteSet;
|
||||
friend class Controls::Base;
|
||||
void PreDeleteControl( Controls::Base * );
|
||||
|
||||
bool m_bDrawBackground;
|
||||
Gwen::Color m_BackgroundColor;
|
||||
|
||||
|
||||
};
|
||||
}
|
||||
}
|
||||
#endif
|
60
lib/gwen/controls/gwen_checkbox.cpp
Normal file
60
lib/gwen/controls/gwen_checkbox.cpp
Normal file
|
@ -0,0 +1,60 @@
|
|||
/*
|
||||
GWEN
|
||||
Copyright (c) 2010 Facepunch Studios
|
||||
See license in Gwen.h
|
||||
*/
|
||||
|
||||
|
||||
#include "gwen_checkbox.h"
|
||||
|
||||
using namespace Gwen;
|
||||
using namespace Gwen::Controls;
|
||||
|
||||
|
||||
|
||||
GWEN_CONTROL_CONSTRUCTOR( CheckBox )
|
||||
{
|
||||
SetSize( 15, 15 );
|
||||
|
||||
m_bChecked = true;
|
||||
Toggle();
|
||||
}
|
||||
|
||||
|
||||
void CheckBox::Render( Skin::Base* skin )
|
||||
{
|
||||
skin->DrawCheckBox( this, m_bChecked, IsDepressed() );
|
||||
}
|
||||
|
||||
void CheckBox::OnPress()
|
||||
{
|
||||
if ( IsDisabled())
|
||||
return;
|
||||
|
||||
if ( IsChecked() && !AllowUncheck() )
|
||||
return;
|
||||
|
||||
Toggle();
|
||||
}
|
||||
|
||||
void CheckBox::OnCheckStatusChanged()
|
||||
{
|
||||
if ( IsChecked() )
|
||||
{
|
||||
onChecked.Call( this );
|
||||
}
|
||||
else
|
||||
{
|
||||
onUnChecked.Call( this );
|
||||
}
|
||||
|
||||
onCheckChanged.Call( this );
|
||||
}
|
||||
|
||||
void CheckBox::SetChecked( bool bChecked )
|
||||
{
|
||||
if ( m_bChecked == bChecked ) return;
|
||||
|
||||
m_bChecked = bChecked;
|
||||
OnCheckStatusChanged();
|
||||
}
|
81
lib/gwen/controls/gwen_checkbox.h
Normal file
81
lib/gwen/controls/gwen_checkbox.h
Normal file
|
@ -0,0 +1,81 @@
|
|||
/*
|
||||
GWEN
|
||||
Copyright (c) 2010 Facepunch Studios
|
||||
See license in Gwen.h
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#ifndef GWEN_CONTROLS_CHECKBOX_H
|
||||
#define GWEN_CONTROLS_CHECKBOX_H
|
||||
|
||||
#include "gwen_base.h"
|
||||
#include "gwen_button.h"
|
||||
#include "../gwen.h"
|
||||
#include "../gwen_skin.h"
|
||||
#include "gwen_labelclickable.h"
|
||||
|
||||
namespace Gwen
|
||||
{
|
||||
namespace Controls
|
||||
{
|
||||
|
||||
class GWEN_EXPORT CheckBox : public Button
|
||||
{
|
||||
public:
|
||||
|
||||
GWEN_CONTROL( CheckBox, Button );
|
||||
|
||||
virtual void Render( Skin::Base* skin );
|
||||
virtual void OnPress();
|
||||
|
||||
virtual void SetChecked( bool Checked );
|
||||
virtual void Toggle() { SetChecked( !IsChecked() ); }
|
||||
virtual bool IsChecked() { return m_bChecked; }
|
||||
|
||||
Gwen::Event::Caller onChecked;
|
||||
Gwen::Event::Caller onUnChecked;
|
||||
Gwen::Event::Caller onCheckChanged;
|
||||
|
||||
private:
|
||||
|
||||
// For derived controls
|
||||
virtual bool AllowUncheck(){ return true; }
|
||||
|
||||
void OnCheckStatusChanged();
|
||||
|
||||
bool m_bChecked;
|
||||
};
|
||||
|
||||
class GWEN_EXPORT CheckBoxWithLabel : public Base
|
||||
{
|
||||
public:
|
||||
|
||||
GWEN_CONTROL_INLINE( CheckBoxWithLabel, Base )
|
||||
{
|
||||
SetSize( 200, 19 );
|
||||
|
||||
m_Checkbox = new CheckBox( this );
|
||||
m_Checkbox->Dock( Pos::Left );
|
||||
m_Checkbox->SetMargin( Margin( 0, 2, 2, 2 ) );
|
||||
m_Checkbox->SetTabable( false );
|
||||
|
||||
m_Label = new LabelClickable( this );
|
||||
m_Label->Dock( Pos::Fill );
|
||||
m_Label->onPress.Add( m_Checkbox, &CheckBox::OnPress );
|
||||
m_Label->SetTabable( false );
|
||||
|
||||
SetTabable( false );
|
||||
}
|
||||
|
||||
virtual CheckBox* Checkbox() { return m_Checkbox; }
|
||||
virtual LabelClickable* Label() { return m_Label; }
|
||||
virtual bool OnKeySpace( bool bDown ) { if ( !bDown ) m_Checkbox->SetChecked( !m_Checkbox->IsChecked() ); return true; }
|
||||
|
||||
private:
|
||||
|
||||
CheckBox* m_Checkbox;
|
||||
LabelClickable* m_Label;
|
||||
};
|
||||
}
|
||||
}
|
||||
#endif
|
181
lib/gwen/controls/gwen_collapsiblecategory.cpp
Normal file
181
lib/gwen/controls/gwen_collapsiblecategory.cpp
Normal file
|
@ -0,0 +1,181 @@
|
|||
/*
|
||||
GWEN
|
||||
Copyright (c) 2010 Facepunch Studios
|
||||
See license in Gwen.h
|
||||
*/
|
||||
|
||||
#include "gwen_collapsiblecategory.h"
|
||||
#include "gwen_collapsiblelist.h"
|
||||
|
||||
using namespace Gwen;
|
||||
using namespace Gwen::Controls;
|
||||
|
||||
class CategoryButton : public Button
|
||||
{
|
||||
GWEN_CONTROL_INLINE ( CategoryButton, Button )
|
||||
{
|
||||
SetAlignment( Pos::Left | Pos::CenterV );
|
||||
m_bAlt = false;
|
||||
}
|
||||
|
||||
virtual void Render( Skin::Base* skin )
|
||||
{
|
||||
if ( m_bAlt )
|
||||
{
|
||||
if ( IsDepressed() || GetToggleState() ) skin->GetRender()->SetDrawColor( skin->Colors.Category.LineAlt.Button_Selected );
|
||||
else if ( IsHovered() ) skin->GetRender()->SetDrawColor( skin->Colors.Category.LineAlt.Button_Hover );
|
||||
else skin->GetRender()->SetDrawColor( skin->Colors.Category.LineAlt.Button );
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( IsDepressed() || GetToggleState() ) skin->GetRender()->SetDrawColor( skin->Colors.Category.Line.Button_Selected );
|
||||
else if ( IsHovered() ) skin->GetRender()->SetDrawColor( skin->Colors.Category.Line.Button_Hover );
|
||||
else skin->GetRender()->SetDrawColor( skin->Colors.Category.Line.Button );
|
||||
}
|
||||
|
||||
skin->GetRender()->DrawFilledRect( this->GetRenderBounds() );
|
||||
}
|
||||
|
||||
void UpdateColours()
|
||||
{
|
||||
if ( m_bAlt )
|
||||
{
|
||||
if ( IsDepressed() || GetToggleState() ) return SetTextColor( GetSkin()->Colors.Category.LineAlt.Text_Selected );
|
||||
if ( IsHovered() ) return SetTextColor( GetSkin()->Colors.Category.LineAlt.Text_Hover );
|
||||
|
||||
return SetTextColor( GetSkin()->Colors.Category.LineAlt.Text );
|
||||
}
|
||||
|
||||
if ( IsDepressed() || GetToggleState() ) return SetTextColor( GetSkin()->Colors.Category.Line.Text_Selected );
|
||||
if ( IsHovered() ) return SetTextColor( GetSkin()->Colors.Category.Line.Text_Hover );
|
||||
|
||||
return SetTextColor( GetSkin()->Colors.Category.Line.Text );
|
||||
}
|
||||
|
||||
bool m_bAlt;
|
||||
};
|
||||
|
||||
class CategoryHeaderButton : public Button
|
||||
{
|
||||
GWEN_CONTROL_INLINE ( CategoryHeaderButton, Button )
|
||||
{
|
||||
SetShouldDrawBackground( false );
|
||||
SetIsToggle( true );
|
||||
SetAlignment( Pos::Center );
|
||||
}
|
||||
|
||||
void UpdateColours()
|
||||
{
|
||||
if ( IsDepressed() || GetToggleState() ) return SetTextColor( GetSkin()->Colors.Category.Header_Closed );
|
||||
return SetTextColor( GetSkin()->Colors.Category.Header );
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
GWEN_CONTROL_CONSTRUCTOR( CollapsibleCategory )
|
||||
{
|
||||
m_pList = NULL;
|
||||
|
||||
m_pButton = new CategoryHeaderButton( this );
|
||||
m_pButton->SetText( "Category Title" );
|
||||
m_pButton->Dock( Pos::Top );
|
||||
m_pButton->SetHeight( 20 );
|
||||
|
||||
SetPadding( Padding( 1, 0, 1, 5 ) );
|
||||
SetSize( 512, 512 );
|
||||
}
|
||||
|
||||
Button* CollapsibleCategory::Add( const TextObject& name )
|
||||
{
|
||||
CategoryButton* pButton = new CategoryButton( this );
|
||||
pButton->SetText( name );
|
||||
pButton->Dock( Pos::Top );
|
||||
pButton->SizeToContents();
|
||||
pButton->SetSize( pButton->Width() + 4, pButton->Height() + 4 );
|
||||
pButton->SetPadding( Padding( 5, 2, 2, 2 ) );
|
||||
pButton->onPress.Add( this, &ThisClass::OnSelection );
|
||||
|
||||
return pButton;
|
||||
}
|
||||
|
||||
void CollapsibleCategory::OnSelection( Controls::Base* control )
|
||||
{
|
||||
CategoryButton* pChild = gwen_cast<CategoryButton>(control);
|
||||
if ( !pChild ) return;
|
||||
|
||||
if ( m_pList )
|
||||
{
|
||||
m_pList->UnselectAll();
|
||||
}
|
||||
else
|
||||
{
|
||||
UnselectAll();
|
||||
}
|
||||
|
||||
pChild->SetToggleState( true );
|
||||
|
||||
onSelection.Call( this );
|
||||
|
||||
}
|
||||
|
||||
void CollapsibleCategory::Render( Skin::Base* skin )
|
||||
{
|
||||
skin->DrawCategoryInner( this, m_pButton->GetToggleState() );
|
||||
}
|
||||
|
||||
void CollapsibleCategory::SetText( const TextObject& text )
|
||||
{
|
||||
m_pButton->SetText( text );
|
||||
}
|
||||
|
||||
void CollapsibleCategory::UnselectAll()
|
||||
{
|
||||
Base::List& children = GetChildren();
|
||||
for ( Base::List::iterator iter = children.begin(); iter != children.end(); ++iter )
|
||||
{
|
||||
CategoryButton* pChild = gwen_cast<CategoryButton>(*iter);
|
||||
if ( !pChild ) continue;
|
||||
|
||||
pChild->SetToggleState( false );
|
||||
}
|
||||
}
|
||||
|
||||
void CollapsibleCategory::PostLayout( Skin::Base* /*skin*/ )
|
||||
{
|
||||
if ( m_pButton->GetToggleState() )
|
||||
{
|
||||
SetHeight( m_pButton->Height() );
|
||||
}
|
||||
else
|
||||
{
|
||||
SizeToChildren( false, true );
|
||||
}
|
||||
|
||||
Base::List& children = GetChildren();
|
||||
bool b = true;
|
||||
for ( Base::List::iterator iter = children.begin(); iter != children.end(); ++iter )
|
||||
{
|
||||
CategoryButton* pChild = gwen_cast<CategoryButton>(*iter);
|
||||
if ( !pChild ) continue;
|
||||
|
||||
pChild->m_bAlt = b;
|
||||
pChild->UpdateColours();
|
||||
b = !b;
|
||||
}
|
||||
};
|
||||
|
||||
Button* CollapsibleCategory::GetSelected()
|
||||
{
|
||||
Base::List& children = GetChildren();
|
||||
for ( Base::List::iterator iter = children.begin(); iter != children.end(); ++iter )
|
||||
{
|
||||
CategoryButton* pChild = gwen_cast<CategoryButton>(*iter);
|
||||
if ( !pChild ) continue;
|
||||
|
||||
if ( pChild->GetToggleState() )
|
||||
return pChild;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
56
lib/gwen/controls/gwen_collapsiblecategory.h
Normal file
56
lib/gwen/controls/gwen_collapsiblecategory.h
Normal file
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
GWEN
|
||||
Copyright (c) 2010 Facepunch Studios
|
||||
See license in Gwen.h
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#ifndef GWEN_CONTROLS_COLLAPSIBLECATEGORY_H
|
||||
#define GWEN_CONTROLS_COLLAPSIBLECATEGORY_H
|
||||
|
||||
#include "gwen_base.h"
|
||||
#include "gwen_button.h"
|
||||
#include "../gwen.h"
|
||||
#include "../gwen_skin.h"
|
||||
|
||||
|
||||
namespace Gwen
|
||||
{
|
||||
namespace Controls
|
||||
{
|
||||
class CollapsibleList;
|
||||
|
||||
class GWEN_EXPORT CollapsibleCategory : public Gwen::Controls::Base
|
||||
{
|
||||
public:
|
||||
|
||||
GWEN_CONTROL( CollapsibleCategory, Gwen::Controls::Base );
|
||||
|
||||
virtual void Render( Skin::Base* skin );
|
||||
|
||||
virtual void SetText( const TextObject& text );
|
||||
|
||||
virtual Button* Add( const TextObject& name );
|
||||
|
||||
virtual void PostLayout( Skin::Base* /*skin*/ );
|
||||
|
||||
virtual void SetList( Controls::CollapsibleList* p ){ m_pList = p; }
|
||||
|
||||
virtual void UnselectAll();
|
||||
virtual Button* GetSelected();
|
||||
|
||||
public:
|
||||
|
||||
Gwen::Event::Caller onSelection;
|
||||
|
||||
protected:
|
||||
|
||||
virtual void OnSelection( Controls::Base* control );
|
||||
|
||||
Controls::Button* m_pButton;
|
||||
Controls::CollapsibleList* m_pList;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
#endif
|
105
lib/gwen/controls/gwen_collapsiblelist.h
Normal file
105
lib/gwen/controls/gwen_collapsiblelist.h
Normal file
|
@ -0,0 +1,105 @@
|
|||
/*
|
||||
GWEN
|
||||
Copyright (c) 2010 Facepunch Studios
|
||||
See license in Gwen.h
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#ifndef GWEN_CONTROLS_COLLAPSIBLELIST_H
|
||||
#define GWEN_CONTROLS_COLLAPSIBLELIST_H
|
||||
|
||||
#include "gwen_base.h"
|
||||
#include "gwen_button.h"
|
||||
#include "gwen_scrollcontrol.h"
|
||||
#include "../gwen.h"
|
||||
#include "../gwen_skin.h"
|
||||
#include "gwen_collapsiblecategory.h"
|
||||
|
||||
|
||||
namespace Gwen
|
||||
{
|
||||
namespace Controls
|
||||
{
|
||||
class GWEN_EXPORT CollapsibleList : public Gwen::Controls::ScrollControl
|
||||
{
|
||||
public:
|
||||
|
||||
Gwen::Event::Caller onSelection;
|
||||
|
||||
public:
|
||||
|
||||
GWEN_CONTROL_INLINE( CollapsibleList, Gwen::Controls::ScrollControl )
|
||||
{
|
||||
SetScroll( false, true );
|
||||
SetAutoHideBars( true );
|
||||
}
|
||||
|
||||
virtual void Add( Gwen::Controls::CollapsibleCategory* pCategory )
|
||||
{
|
||||
pCategory->SetParent( this );
|
||||
pCategory->Dock( Pos::Top );
|
||||
pCategory->SetMargin( Margin( 1, 0, 1, 1 ) );
|
||||
pCategory->SetList( this );
|
||||
pCategory->onSelection.Add( this, &ThisClass::OnSelectionEvent );
|
||||
}
|
||||
|
||||
virtual Gwen::Controls::CollapsibleCategory* Add( const TextObject& name )
|
||||
{
|
||||
Gwen::Controls::CollapsibleCategory* pCategory = new CollapsibleCategory( this );
|
||||
pCategory->SetText( name );
|
||||
Add( pCategory );
|
||||
|
||||
return pCategory;
|
||||
}
|
||||
|
||||
virtual void Render( Skin::Base* skin )
|
||||
{
|
||||
skin->DrawCategoryHolder( this );
|
||||
}
|
||||
|
||||
virtual void UnselectAll()
|
||||
{
|
||||
Base::List& children = GetChildren();
|
||||
for ( Base::List::iterator iter = children.begin(); iter != children.end(); ++iter )
|
||||
{
|
||||
Gwen::Controls::CollapsibleCategory* pChild = gwen_cast<Gwen::Controls::CollapsibleCategory>(*iter);
|
||||
if ( !pChild ) continue;
|
||||
|
||||
pChild->UnselectAll();
|
||||
}
|
||||
}
|
||||
|
||||
virtual Gwen::Controls::Button* GetSelected()
|
||||
{
|
||||
Base::List& children = GetChildren();
|
||||
for ( Base::List::iterator iter = children.begin(); iter != children.end(); ++iter )
|
||||
{
|
||||
Gwen::Controls::CollapsibleCategory* pChild = gwen_cast<Gwen::Controls::CollapsibleCategory>(*iter);
|
||||
if ( !pChild ) continue;
|
||||
|
||||
Gwen::Controls::Button* pSelected = pChild->GetSelected();
|
||||
if ( pSelected ) return pSelected;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
virtual void OnSelection( Gwen::Controls::CollapsibleCategory* pControl, Gwen::Controls::Button* pSelected )
|
||||
{
|
||||
onSelection.Call( this );
|
||||
}
|
||||
|
||||
void OnSelectionEvent( Controls::Base* pControl )
|
||||
{
|
||||
Gwen::Controls::CollapsibleCategory* pChild = gwen_cast<Gwen::Controls::CollapsibleCategory>(pControl);
|
||||
if ( !pChild ) return;
|
||||
|
||||
OnSelection( pChild, pChild->GetSelected() );
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
#endif
|
326
lib/gwen/controls/gwen_colorcontrols.cpp
Normal file
326
lib/gwen/controls/gwen_colorcontrols.cpp
Normal file
|
@ -0,0 +1,326 @@
|
|||
/*
|
||||
GWEN
|
||||
Copyright (c) 2010 Facepunch Studios
|
||||
See license in Gwen.h
|
||||
*/
|
||||
|
||||
|
||||
#include "../gwen_utility.h"
|
||||
#include "gwen_colorcontrols.h"
|
||||
|
||||
using namespace Gwen;
|
||||
using namespace Gwen::Controls;
|
||||
|
||||
//Find a place to put these...
|
||||
Color HSVToColor( float h, float s, float v )
|
||||
{
|
||||
if (h < 0.0f) h += 360.0f;
|
||||
if (h > 360.0f) h -= 360.0f;
|
||||
|
||||
s *= 255.0f;
|
||||
v *= 255.0f;
|
||||
|
||||
float r, g, b;
|
||||
|
||||
if (!h && !s)
|
||||
{
|
||||
r = g = b = v;
|
||||
}
|
||||
double min,max,delta,hue;
|
||||
|
||||
max = v;
|
||||
delta = (max * s)/255.0;
|
||||
min = max - delta;
|
||||
|
||||
hue = h;
|
||||
if (h > 300 || h <= 60)
|
||||
{
|
||||
r = (int)max;
|
||||
if (h > 300)
|
||||
{
|
||||
g = (int)min;
|
||||
hue = (hue - 360.0)/60.0;
|
||||
b = (int)((hue * delta - min) * -1);
|
||||
}
|
||||
else
|
||||
{
|
||||
b = (int)min;
|
||||
hue = hue / 60.0;
|
||||
g = (int)(hue * delta + min);
|
||||
}
|
||||
}
|
||||
else if (h > 60 && h < 180)
|
||||
{
|
||||
g = (int)max;
|
||||
if (h < 120)
|
||||
{
|
||||
b = (int)min;
|
||||
hue = (hue/60.0 - 2.0 ) * delta;
|
||||
r = (int)(min - hue);
|
||||
}
|
||||
else
|
||||
{
|
||||
r = (int)min;
|
||||
hue = (hue/60 - 2.0) * delta;
|
||||
b = (int)(min + hue);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
b = (int)max;
|
||||
if (h < 240)
|
||||
{
|
||||
r = (int)min;
|
||||
hue = (hue/60.0 - 4.0 ) * delta;
|
||||
g = (int)(min - hue);
|
||||
}
|
||||
else
|
||||
{
|
||||
g = (int)min;
|
||||
hue = (hue/60 - 4.0) * delta;
|
||||
r = (int)(min + hue);
|
||||
}
|
||||
}
|
||||
|
||||
return Color( r, g, b, 255);
|
||||
}
|
||||
|
||||
HSV RGBtoHSV( int r, int g, int b )
|
||||
{
|
||||
double min,max,delta,temp;
|
||||
min = GwenUtil_Min(r,GwenUtil_Min(g,b));
|
||||
max = GwenUtil_Max(r,GwenUtil_Max(g,b));
|
||||
delta = max - min;
|
||||
|
||||
HSV hsv;
|
||||
hsv.v = (int)max;
|
||||
if (!delta)
|
||||
{
|
||||
hsv.h = hsv.s = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
temp = delta/max;
|
||||
hsv.s = (int)(temp*255);
|
||||
|
||||
if (r == (int)max)
|
||||
{
|
||||
temp = (double)(g-b)/delta;
|
||||
}
|
||||
else
|
||||
if (g == (int)max)
|
||||
{
|
||||
temp = 2.0 + ((double)(b-r)/delta);
|
||||
}
|
||||
else
|
||||
{
|
||||
temp = 4.0 + ((double)(r-g)/delta);
|
||||
}
|
||||
temp *= 60;
|
||||
if (temp < 0)
|
||||
{
|
||||
temp+=360;
|
||||
}
|
||||
if (temp == 360)
|
||||
{
|
||||
temp = 0;
|
||||
}
|
||||
hsv.h = (int)temp;
|
||||
}
|
||||
|
||||
|
||||
hsv.s /= 255.0f;
|
||||
hsv.v /= 255.0f;
|
||||
|
||||
return hsv;
|
||||
}
|
||||
|
||||
|
||||
GWEN_CONTROL_CONSTRUCTOR( ColorLerpBox )
|
||||
{
|
||||
SetColor( Gwen::Color(255, 128, 0, 255) );
|
||||
SetSize( 128, 128 );
|
||||
SetMouseInputEnabled( true );
|
||||
m_bDepressed = false;
|
||||
}
|
||||
|
||||
//Find a place to put this? color member?
|
||||
Gwen::Color LerpColor( Gwen::Color &toColor, Gwen::Color &fromColor, float amount )
|
||||
{
|
||||
Gwen::Color colorDelta = toColor - fromColor;
|
||||
|
||||
colorDelta.r *= amount;
|
||||
colorDelta.g *= amount;
|
||||
colorDelta.b *= amount;
|
||||
|
||||
Gwen::Color newColor = fromColor + colorDelta;
|
||||
return newColor;
|
||||
}
|
||||
|
||||
Gwen::Color ColorLerpBox::GetSelectedColor()
|
||||
{
|
||||
return GetColorAtPos( cursorPos.x, cursorPos.y );
|
||||
}
|
||||
|
||||
void ColorLerpBox::SetColor( Gwen::Color color, bool onlyHue )
|
||||
{
|
||||
HSV hsv = RGBtoHSV(color.r, color.g, color.b);
|
||||
m_Hue = hsv.h;
|
||||
if ( !onlyHue )
|
||||
{
|
||||
cursorPos.x = hsv.s * Width();
|
||||
cursorPos.y = (1 - hsv.v) * Height();
|
||||
}
|
||||
|
||||
onSelectionChanged.Call( this );
|
||||
}
|
||||
|
||||
void ColorLerpBox::OnMouseMoved( int x, int y, int /*deltaX*/, int /*deltaY*/ )
|
||||
{
|
||||
if ( m_bDepressed )
|
||||
{
|
||||
cursorPos = CanvasPosToLocal( Gwen::Point( x, y ) );
|
||||
//Do we have clamp?
|
||||
if ( cursorPos.x < 0)
|
||||
cursorPos.x = 0;
|
||||
if (cursorPos.x > Width())
|
||||
cursorPos.x = Width();
|
||||
|
||||
if (cursorPos.y < 0)
|
||||
cursorPos.y = 0;
|
||||
if (cursorPos.y > Height())
|
||||
cursorPos.y = Height();
|
||||
|
||||
onSelectionChanged.Call( this );
|
||||
}
|
||||
}
|
||||
|
||||
void ColorLerpBox::OnMouseClickLeft( int x, int y, bool bDown )
|
||||
{
|
||||
m_bDepressed = bDown;
|
||||
if ( bDown )
|
||||
Gwen::MouseFocus = this;
|
||||
else
|
||||
Gwen::MouseFocus = NULL;
|
||||
|
||||
OnMouseMoved( x, y, 0, 0);
|
||||
}
|
||||
|
||||
Gwen::Color ColorLerpBox::GetColorAtPos( int x, int y )
|
||||
{
|
||||
float xPercent = ( (float)x / (float)Width() );
|
||||
float yPercent = 1 - ( (float)y / (float)Height() );
|
||||
|
||||
Gwen::Color result = HSVToColor( m_Hue, xPercent, yPercent );
|
||||
|
||||
result.a = 255;
|
||||
|
||||
return result;
|
||||
}
|
||||
void ColorLerpBox::Render( Gwen::Skin::Base* skin )
|
||||
{
|
||||
//Is there any way to move this into skin? Not for now, no idea how we'll "actually" render these
|
||||
BaseClass::Render( skin );
|
||||
for ( int x = 0; x<Width(); x++)
|
||||
{
|
||||
for ( int y = 0; y<Height(); y++)
|
||||
{
|
||||
skin->GetRender()->SetDrawColor( GetColorAtPos( x, y ) );
|
||||
skin->GetRender()->DrawPixel( x, y );
|
||||
}
|
||||
}
|
||||
|
||||
skin->GetRender()->SetDrawColor( Gwen::Color( 0, 0, 0, 255 ) );
|
||||
skin->GetRender()->DrawLinedRect( GetRenderBounds() );
|
||||
|
||||
Gwen::Color selected = GetSelectedColor();
|
||||
if ( (selected.r + selected.g + selected.b) / 3 < 170 )
|
||||
skin->GetRender()->SetDrawColor( Gwen::Color( 255, 255, 255, 255 ) );
|
||||
else
|
||||
skin->GetRender()->SetDrawColor( Gwen::Color( 0, 0, 0, 255 ) );
|
||||
|
||||
Gwen::Rect testRect = Gwen::Rect( cursorPos.x -3, cursorPos.y -3, 6, 6);
|
||||
|
||||
skin->GetRender()->DrawShavedCornerRect( testRect );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
GWEN_CONTROL_CONSTRUCTOR( ColorSlider )
|
||||
{
|
||||
SetSize( 32, 128 );
|
||||
SetMouseInputEnabled( true );
|
||||
m_bDepressed = false;
|
||||
}
|
||||
|
||||
void ColorSlider::Render( Gwen::Skin::Base* skin )
|
||||
{
|
||||
//Is there any way to move this into skin? Not for now, no idea how we'll "actually" render these
|
||||
int y = 0;
|
||||
for ( y = 0; y < Height(); y++)
|
||||
{
|
||||
float yPercent = (float)y / (float)Height();
|
||||
skin->GetRender()->SetDrawColor( HSVToColor( yPercent * 360, 1, 1 ) );
|
||||
skin->GetRender()->DrawFilledRect( Gwen::Rect( 5, y, Width() - 10, 1 ) );
|
||||
}
|
||||
|
||||
int drawHeight = m_iSelectedDist - 3;
|
||||
|
||||
//Draw our selectors
|
||||
skin->GetRender()->SetDrawColor( Gwen::Color( 0, 0, 0, 255 ));
|
||||
skin->GetRender()->DrawFilledRect( Gwen::Rect( 0, drawHeight + 2, Width(), 1));
|
||||
skin->GetRender()->DrawFilledRect( Gwen::Rect( 0, drawHeight, 5, 5) );
|
||||
skin->GetRender()->DrawFilledRect( Gwen::Rect( Width() - 5, drawHeight, 5, 5) );
|
||||
skin->GetRender()->SetDrawColor( Gwen::Color( 255, 255, 255, 255 ) );
|
||||
skin->GetRender()->DrawFilledRect( Gwen::Rect( 1, drawHeight + 1, 3, 3 ) );
|
||||
skin->GetRender()->DrawFilledRect( Gwen::Rect( Width() - 4, drawHeight + 1, 3, 3 ) );
|
||||
}
|
||||
|
||||
void ColorSlider::OnMouseClickLeft( int x, int y, bool bDown )
|
||||
{
|
||||
m_bDepressed = bDown;
|
||||
if ( bDown)
|
||||
Gwen::MouseFocus = this;
|
||||
else
|
||||
Gwen::MouseFocus = NULL;
|
||||
|
||||
OnMouseMoved(x, y, 0, 0);
|
||||
}
|
||||
|
||||
Gwen::Color ColorSlider::GetColorAtHeight( int y )
|
||||
{
|
||||
float yPercent = (float)y / (float)Height();
|
||||
return HSVToColor( yPercent * 360, 1, 1);
|
||||
|
||||
}
|
||||
void ColorSlider::OnMouseMoved( int x, int y, int /*deltaX*/, int /*deltaY*/ )
|
||||
{
|
||||
if ( m_bDepressed )
|
||||
{
|
||||
Gwen::Point cursorPos = CanvasPosToLocal( Gwen::Point( x, y ) );
|
||||
|
||||
if (cursorPos.y < 0)
|
||||
cursorPos.y = 0;
|
||||
if (cursorPos.y > Height())
|
||||
cursorPos.y = Height();
|
||||
|
||||
m_iSelectedDist = cursorPos.y;
|
||||
onSelectionChanged.Call( this );
|
||||
}
|
||||
}
|
||||
|
||||
void ColorSlider::SetColor( Gwen::Color color)
|
||||
{
|
||||
HSV hsv = RGBtoHSV( color.r, color.g, color.b );
|
||||
|
||||
m_iSelectedDist = hsv.h / 360 * Height();
|
||||
|
||||
onSelectionChanged.Call( this );
|
||||
}
|
||||
|
||||
Gwen::Color ColorSlider::GetSelectedColor()
|
||||
{
|
||||
return GetColorAtHeight( m_iSelectedDist );
|
||||
}
|
61
lib/gwen/controls/gwen_colorcontrols.h
Normal file
61
lib/gwen/controls/gwen_colorcontrols.h
Normal file
|
@ -0,0 +1,61 @@
|
|||
/*
|
||||
GWEN
|
||||
Copyright (c) 2010 Facepunch Studios
|
||||
See license in Gwen.h
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#ifndef GWEN_CONTROLS_COLORCONTROLS_H
|
||||
#define GWEN_CONTROLS_COLORCONTROLS_H
|
||||
|
||||
#include "gwen_base.h"
|
||||
#include "../gwen.h"
|
||||
#include "../gwen_skin.h"
|
||||
|
||||
|
||||
namespace Gwen
|
||||
{
|
||||
namespace Controls
|
||||
{
|
||||
|
||||
class GWEN_EXPORT ColorLerpBox : public Controls::Base
|
||||
{
|
||||
public:
|
||||
GWEN_CONTROL( ColorLerpBox, Controls::Base );
|
||||
virtual void Render( Gwen::Skin::Base* skin );
|
||||
Gwen::Color GetColorAtPos(int x, int y );
|
||||
void SetColor( Gwen::Color color, bool onlyHue = true );
|
||||
virtual void OnMouseMoved( int x, int y, int deltaX, int deltaY );
|
||||
virtual void OnMouseClickLeft( int x, int y, bool bDown );
|
||||
Gwen::Color GetSelectedColor();
|
||||
|
||||
Event::Caller onSelectionChanged;
|
||||
protected:
|
||||
Gwen::Point cursorPos;
|
||||
bool m_bDepressed;
|
||||
int m_Hue;
|
||||
|
||||
};
|
||||
|
||||
class GWEN_EXPORT ColorSlider : public Controls::Base
|
||||
{
|
||||
public:
|
||||
GWEN_CONTROL( ColorSlider, Controls::Base );
|
||||
virtual void Render( Gwen::Skin::Base* skin );
|
||||
virtual void OnMouseMoved( int x, int y, int deltaX, int deltaY );
|
||||
virtual void OnMouseClickLeft( int x, int y, bool bDown );
|
||||
Gwen::Color GetSelectedColor();
|
||||
Gwen::Color GetColorAtHeight(int y );
|
||||
void SetColor( Gwen::Color color );
|
||||
|
||||
Event::Caller onSelectionChanged;
|
||||
|
||||
protected:
|
||||
int m_iSelectedDist;
|
||||
bool m_bDepressed;
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
218
lib/gwen/controls/gwen_colorpicker.cpp
Normal file
218
lib/gwen/controls/gwen_colorpicker.cpp
Normal file
|
@ -0,0 +1,218 @@
|
|||
/*
|
||||
GWEN
|
||||
Copyright (c) 2010 Facepunch Studios
|
||||
See license in Gwen.h
|
||||
*/
|
||||
|
||||
|
||||
#include "gwen_colorpicker.h"
|
||||
#include "gwen_horizontalslider.h"
|
||||
#include "gwen_groupbox.h"
|
||||
#include "gwen_textbox.h"
|
||||
#include "../gwen_utility.h"
|
||||
|
||||
using namespace Gwen;
|
||||
using namespace Gwen::Controls;
|
||||
using namespace Gwen::ControlsInternal;
|
||||
|
||||
GWEN_CONTROL_CONSTRUCTOR( ColorPicker )
|
||||
{
|
||||
SetMouseInputEnabled( true );
|
||||
|
||||
SetSize( 256, 150 );
|
||||
CreateControls();
|
||||
SetColor( Gwen::Color( 50, 60, 70, 255 ) );
|
||||
}
|
||||
|
||||
void ColorPicker::CreateColorControl( Gwen::String name, int y )
|
||||
{
|
||||
int colorSize = 12;
|
||||
|
||||
GroupBox* colorGroup = new GroupBox( this );
|
||||
colorGroup->SetPos( 10, y );
|
||||
colorGroup->SetText( name );
|
||||
colorGroup->SetSize( 160, 35 );
|
||||
colorGroup->SetName( name + "groupbox" );
|
||||
|
||||
ColorDisplay* disp = new ColorDisplay( colorGroup );
|
||||
disp->SetName(name);
|
||||
disp->SetBounds( 0 , 10, colorSize, colorSize );
|
||||
|
||||
TextBoxNumeric* numeric = new TextBoxNumeric( colorGroup );
|
||||
numeric->SetName( name + "Box" );
|
||||
numeric->SetPos( 105, 7 );
|
||||
numeric->SetSize( 26, 16 );
|
||||
numeric->SetSelectAllOnFocus( true );
|
||||
numeric->onTextChanged.Add( this, &ColorPicker::NumericTyped );
|
||||
|
||||
HorizontalSlider* slider = new HorizontalSlider( colorGroup );
|
||||
slider->SetPos( colorSize + 5 , 8 );
|
||||
slider->SetRange( 0, 255 );
|
||||
slider->SetSize( 80, Gwen::Utility::Max( colorSize, 15 ) );
|
||||
slider->SetName( name + "Slider");
|
||||
slider->onValueChanged.Add( this, &ColorPicker::SlidersMoved );
|
||||
}
|
||||
|
||||
void ColorPicker::NumericTyped( Gwen::Controls::Base* control )
|
||||
{
|
||||
TextBoxNumeric* box = gwen_cast<TextBoxNumeric>(control);
|
||||
if (!box)
|
||||
return;
|
||||
|
||||
if ( box->GetText() == "")
|
||||
return;
|
||||
|
||||
int textValue = atoi( box->GetText().c_str() );
|
||||
if ( textValue < 0) textValue = 0;
|
||||
if ( textValue > 255) textValue = 255;
|
||||
|
||||
if ( box->GetName().find("Red") != Gwen::String::npos )
|
||||
SetRed( textValue );
|
||||
|
||||
if ( box->GetName().find("Green") != Gwen::String::npos )
|
||||
SetGreen( textValue );
|
||||
|
||||
if ( box->GetName().find("Blue") != Gwen::String::npos )
|
||||
SetBlue( textValue );
|
||||
|
||||
if ( box->GetName().find("Alpha") != Gwen::String::npos )
|
||||
SetAlpha( textValue );
|
||||
|
||||
UpdateControls();
|
||||
}
|
||||
|
||||
void ColorPicker::SetColor( Gwen::Color color )
|
||||
{
|
||||
m_Color = color;
|
||||
UpdateControls();
|
||||
}
|
||||
|
||||
void ColorPicker::CreateControls()
|
||||
{
|
||||
int startY = 5;
|
||||
int height = 35;
|
||||
|
||||
CreateColorControl( "Red", startY );
|
||||
CreateColorControl( "Green", startY + height );
|
||||
CreateColorControl( "Blue", startY + height * 2 );
|
||||
CreateColorControl( "Alpha", startY + height * 3 );
|
||||
|
||||
GroupBox* finalGroup = new GroupBox( this );
|
||||
finalGroup->SetPos( 180, 40 );
|
||||
finalGroup->SetSize( 60, 60 );
|
||||
finalGroup->SetText( "Result" );
|
||||
finalGroup->SetName( "ResultGroupBox" );
|
||||
|
||||
|
||||
ColorDisplay* disp = new ColorDisplay( finalGroup );
|
||||
disp->SetName( "Result" );
|
||||
disp->SetBounds( 0 , 10, 32, 32 );
|
||||
disp->SetDrawCheckers( true );
|
||||
|
||||
//UpdateControls();
|
||||
}
|
||||
|
||||
void ColorPicker::UpdateColorControls( Gwen::String name, Gwen::Color col, int sliderVal )
|
||||
{
|
||||
ColorDisplay* disp = gwen_cast<ColorDisplay>(FindChildByName( name, true ) );
|
||||
disp->SetColor( col );
|
||||
|
||||
HorizontalSlider* slider = gwen_cast<HorizontalSlider>( FindChildByName( name + "Slider", true ) );
|
||||
slider->SetFloatValue( sliderVal );
|
||||
|
||||
TextBoxNumeric* box = gwen_cast<TextBoxNumeric>( FindChildByName( name + "Box", true ) );
|
||||
box->SetText( Gwen::Utility::ToString( sliderVal ) );
|
||||
}
|
||||
|
||||
void ColorPicker::UpdateControls()
|
||||
{
|
||||
|
||||
//This is a little weird, but whatever for now
|
||||
UpdateColorControls( "Red", Color( GetColor().r, 0, 0, 255 ), GetColor().r );
|
||||
UpdateColorControls( "Green", Color( 0, GetColor().g, 0, 255 ), GetColor().g );
|
||||
UpdateColorControls( "Blue", Color( 0, 0, GetColor().b, 255 ), GetColor().b );
|
||||
UpdateColorControls( "Alpha", Color( 255, 255, 255, GetColor().a ), GetColor().a );
|
||||
|
||||
ColorDisplay* disp = gwen_cast<ColorDisplay>( FindChildByName( "Result", true ) );
|
||||
disp->SetColor( Color( GetColor().r, GetColor().g, GetColor().b, GetColor().a ) );
|
||||
|
||||
onColorChanged.Call( this );
|
||||
}
|
||||
void ColorPicker::SlidersMoved( Gwen::Controls::Base* control )
|
||||
{
|
||||
/*
|
||||
HorizontalSlider* redSlider = gwen_cast<HorizontalSlider>( FindChildByName( "RedSlider", true ) );
|
||||
HorizontalSlider* greenSlider = gwen_cast<HorizontalSlider>( FindChildByName( "GreenSlider", true ) );
|
||||
HorizontalSlider* blueSlider = gwen_cast<HorizontalSlider>( FindChildByName( "BlueSlider", true ) );
|
||||
HorizontalSlider* alphaSlider = gwen_cast<HorizontalSlider>( FindChildByName( "AlphaSlider", true ) );
|
||||
*/
|
||||
|
||||
HorizontalSlider* slider = gwen_cast<HorizontalSlider>( control );
|
||||
if (slider)
|
||||
SetColorByName( GetColorFromName( slider->GetName() ), slider->GetFloatValue() );
|
||||
|
||||
UpdateControls();
|
||||
//SetColor( Gwen::Color( redSlider->GetValue(), greenSlider->GetValue(), blueSlider->GetValue(), alphaSlider->GetValue() ) );
|
||||
}
|
||||
|
||||
void ColorPicker::Layout( Skin::Base* skin )
|
||||
{
|
||||
BaseClass::Layout( skin );
|
||||
|
||||
SizeToChildren( false, true );
|
||||
SetSize( Width(), Height() + 5 );
|
||||
|
||||
GroupBox* groupBox = gwen_cast<GroupBox>(FindChildByName( "ResultGroupBox", true ) );
|
||||
if ( groupBox )
|
||||
groupBox->SetPos( groupBox->X(), Height() * 0.5f - groupBox->Height() * 0.5f );
|
||||
|
||||
UpdateControls();
|
||||
}
|
||||
|
||||
|
||||
int ColorPicker::GetColorByName( Gwen::String colorName )
|
||||
{
|
||||
if ( colorName == "Red")
|
||||
return GetColor().r;
|
||||
else if ( colorName == "Green")
|
||||
return GetColor().g;
|
||||
else if ( colorName == "Blue")
|
||||
return GetColor().b;
|
||||
else if ( colorName == "Alpha")
|
||||
return GetColor().a;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
Gwen::String ColorPicker::GetColorFromName( Gwen::String name )
|
||||
{
|
||||
if ( name.find("Red") != Gwen::String::npos )
|
||||
return "Red";
|
||||
if ( name.find("Green") != Gwen::String::npos )
|
||||
return "Green";
|
||||
if ( name.find("Blue") != Gwen::String::npos )
|
||||
return "Blue";
|
||||
if ( name.find("Alpha") != Gwen::String::npos )
|
||||
return "Alpha";
|
||||
else
|
||||
return "";
|
||||
}
|
||||
|
||||
void ColorPicker::SetColorByName( Gwen::String colorName, int colorValue )
|
||||
{
|
||||
if ( colorName == "Red")
|
||||
SetRed( colorValue );
|
||||
else if ( colorName == "Green")
|
||||
SetGreen( colorValue );
|
||||
else if ( colorName == "Blue")
|
||||
SetBlue( colorValue );
|
||||
else if ( colorName == "Alpha")
|
||||
SetAlpha( colorValue );
|
||||
}
|
||||
|
||||
void ColorPicker::SetAlphaVisible( bool visible )
|
||||
{
|
||||
GroupBox* groupBox = gwen_cast<GroupBox>(FindChildByName( "Alphagroupbox", true ) );
|
||||
groupBox->SetHidden( !visible );
|
||||
Invalidate();
|
||||
}
|
88
lib/gwen/controls/gwen_colorpicker.h
Normal file
88
lib/gwen/controls/gwen_colorpicker.h
Normal file
|
@ -0,0 +1,88 @@
|
|||
/*
|
||||
GWEN
|
||||
Copyright (c) 2010 Facepunch Studios
|
||||
See license in Gwen.h
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#ifndef GWEN_CONTROLS_COLORPICKER_H
|
||||
#define GWEN_CONTROLS_COLORPICKER_H
|
||||
|
||||
#include "gwen_base.h"
|
||||
#include "../gwen.h"
|
||||
#include "../gwen_skin.h"
|
||||
|
||||
|
||||
namespace Gwen
|
||||
{
|
||||
namespace ControlsInternal
|
||||
{
|
||||
class GWEN_EXPORT ColorDisplay : public Controls::Base
|
||||
{
|
||||
public:
|
||||
GWEN_CONTROL_INLINE( ColorDisplay, Controls::Base )
|
||||
{
|
||||
SetSize( 32, 32 );
|
||||
m_Color = Color( 255, 0, 0, 255 );
|
||||
m_DrawCheckers = true;
|
||||
}
|
||||
|
||||
virtual void Render( Gwen::Skin::Base* skin )
|
||||
{
|
||||
skin->DrawColorDisplay( this, m_Color );
|
||||
}
|
||||
|
||||
virtual void SetColor( Gwen::Color color ) { m_Color = color; }
|
||||
virtual Gwen::Color GetColor() { return m_Color; }
|
||||
|
||||
virtual void SetRed( int red ) { m_Color.r = red; }
|
||||
virtual void SetGreen( int green ) { m_Color.g = green;}
|
||||
virtual void SetBlue( int blue ) { m_Color.b = blue; }
|
||||
virtual void SetAlpha( int alpha ) { m_Color.a = alpha;}
|
||||
|
||||
virtual void SetDrawCheckers( bool should ) { m_DrawCheckers = should; }
|
||||
|
||||
protected:
|
||||
Gwen::Color m_Color;
|
||||
bool m_DrawCheckers;
|
||||
};
|
||||
}
|
||||
namespace Controls
|
||||
{
|
||||
|
||||
class GWEN_EXPORT ColorPicker : public Base
|
||||
{
|
||||
public:
|
||||
|
||||
GWEN_CONTROL( ColorPicker, Base );
|
||||
|
||||
virtual void Layout( Skin::Base* skin );
|
||||
virtual void CreateControls();
|
||||
virtual void SlidersMoved( Gwen::Controls::Base* control );
|
||||
virtual void NumericTyped( Gwen::Controls::Base* control );
|
||||
virtual void UpdateControls();
|
||||
virtual void UpdateColorControls( Gwen::String name, Gwen::Color col, int sliderVal );
|
||||
virtual void CreateColorControl( Gwen::String name, int y );
|
||||
|
||||
virtual void SetColor( Gwen::Color color );
|
||||
virtual Gwen::Color GetColor() { return m_Color; }
|
||||
|
||||
int GetColorByName( Gwen::String colorName );
|
||||
void SetColorByName( Gwen::String colorName, int colorValue );
|
||||
Gwen::String GetColorFromName( Gwen::String name );
|
||||
virtual void SetAlphaVisible( bool visible );
|
||||
|
||||
virtual void SetRed( int red ) { m_Color.r = red; }
|
||||
virtual void SetGreen( int green ) { m_Color.g = green;}
|
||||
virtual void SetBlue( int blue ) { m_Color.b = blue; }
|
||||
virtual void SetAlpha( int alpha ) { m_Color.a = alpha;}
|
||||
|
||||
Event::Caller onColorChanged;
|
||||
|
||||
protected:
|
||||
Gwen::Color m_Color;
|
||||
|
||||
};
|
||||
}
|
||||
}
|
||||
#endif
|
250
lib/gwen/controls/gwen_combobox.cpp
Normal file
250
lib/gwen/controls/gwen_combobox.cpp
Normal file
|
@ -0,0 +1,250 @@
|
|||
/*
|
||||
GWEN
|
||||
Copyright (c) 2010 Facepunch Studios
|
||||
See license in Gwen.h
|
||||
*/
|
||||
|
||||
|
||||
#include "gwen_combobox.h"
|
||||
#include "gwen_menu.h"
|
||||
|
||||
|
||||
using namespace Gwen;
|
||||
using namespace Gwen::Controls;
|
||||
using namespace Gwen::ControlsInternal;
|
||||
|
||||
class GWEN_EXPORT DownArrow : public Controls::Base
|
||||
{
|
||||
public:
|
||||
|
||||
GWEN_CONTROL_INLINE( DownArrow, Controls::Base )
|
||||
{
|
||||
SetMouseInputEnabled( false );
|
||||
SetSize( 15, 15 );
|
||||
}
|
||||
|
||||
void Render( Skin::Base* skin )
|
||||
{
|
||||
if ( !m_ComboBox->ShouldDrawBackground() )
|
||||
{
|
||||
return skin->DrawComboDownArrow( this, false, false, false, m_ComboBox->IsDisabled() );
|
||||
}
|
||||
|
||||
skin->DrawComboDownArrow( this, m_ComboBox->IsHovered(), m_ComboBox->IsDepressed(), m_ComboBox->IsMenuOpen(), m_ComboBox->IsDisabled() );
|
||||
}
|
||||
|
||||
void SetComboBox( ComboBox* p ){ m_ComboBox = p; }
|
||||
|
||||
protected:
|
||||
|
||||
ComboBox* m_ComboBox;
|
||||
};
|
||||
|
||||
GWEN_CONTROL_CONSTRUCTOR( ComboBox )
|
||||
{
|
||||
SetSize( 100, 20 );
|
||||
|
||||
m_Menu = new Menu( this );
|
||||
m_Menu->SetHidden( true );
|
||||
m_Menu->SetDisableIconMargin( true );
|
||||
m_Menu->SetTabable( false );
|
||||
|
||||
DownArrow* pArrow = new DownArrow( this );
|
||||
pArrow->SetComboBox( this );
|
||||
m_Button = pArrow;
|
||||
|
||||
m_SelectedItem = NULL;
|
||||
|
||||
SetAlignment( Gwen::Pos::Left | Gwen::Pos::CenterV );
|
||||
SetText( "" );
|
||||
SetMargin( Margin( 3, 0, 0, 0 ) );
|
||||
|
||||
SetTabable( true );
|
||||
SetKeyboardInputEnabled( true );
|
||||
|
||||
}
|
||||
|
||||
MenuItem* ComboBox::AddItem( const String& strLabel, const String& strName )
|
||||
{
|
||||
MenuItem* pItem = m_Menu->AddItem( strLabel, "" );
|
||||
pItem->SetName( strName );
|
||||
|
||||
pItem->onMenuItemSelected.Add( this, &ComboBox::OnItemSelected );
|
||||
|
||||
//Default
|
||||
if ( m_SelectedItem == NULL )
|
||||
OnItemSelected( pItem );
|
||||
|
||||
return pItem;
|
||||
}
|
||||
|
||||
void ComboBox::Render( Skin::Base* skin )
|
||||
{
|
||||
if ( !ShouldDrawBackground() ) return;
|
||||
|
||||
skin->DrawComboBox( this, IsDepressed(), IsMenuOpen());
|
||||
}
|
||||
|
||||
void ComboBox::Layout( Skin::Base* skin )
|
||||
{
|
||||
m_Button->Position( Pos::Right | Pos::CenterV, 4, 0 );
|
||||
|
||||
BaseClass::Layout( skin );
|
||||
}
|
||||
|
||||
void ComboBox::UpdateColours()
|
||||
{
|
||||
if ( !ShouldDrawBackground() )
|
||||
{
|
||||
return SetTextColor( GetSkin()->Colors.Button.Normal );
|
||||
}
|
||||
|
||||
BaseClass::UpdateColours();
|
||||
}
|
||||
|
||||
void ComboBox::OnPress()
|
||||
{
|
||||
if ( IsMenuOpen() )
|
||||
{
|
||||
return GetCanvas()->CloseMenus();
|
||||
}
|
||||
|
||||
bool bWasMenuHidden = m_Menu->Hidden();
|
||||
|
||||
GetCanvas()->CloseMenus();
|
||||
|
||||
if ( bWasMenuHidden )
|
||||
{
|
||||
OpenList();
|
||||
}
|
||||
}
|
||||
|
||||
void ComboBox::ClearItems()
|
||||
{
|
||||
if ( m_Menu )
|
||||
{
|
||||
m_Menu->ClearItems();
|
||||
}
|
||||
}
|
||||
|
||||
void ComboBox::SelectItem( MenuItem* pItem )
|
||||
{
|
||||
if ( m_SelectedItem == pItem ) return;
|
||||
|
||||
m_SelectedItem = pItem;
|
||||
SetText( m_SelectedItem->GetText() );
|
||||
m_Menu->SetHidden( true );
|
||||
Invalidate();
|
||||
}
|
||||
|
||||
void ComboBox::OnItemSelected( Controls::Base* pControl )
|
||||
{
|
||||
//Convert selected to a menu item
|
||||
MenuItem* pItem = gwen_cast<MenuItem>( pControl );
|
||||
if ( !pItem ) return;
|
||||
|
||||
SelectItem( pItem );
|
||||
|
||||
onSelection.Call( this );
|
||||
Focus();
|
||||
}
|
||||
|
||||
void ComboBox::SelectItemByName( const Gwen::String& name, bool bFireChangeEvents )
|
||||
{
|
||||
Base::List& children = m_Menu->GetChildren();
|
||||
Base::List::iterator it = children.begin();
|
||||
|
||||
while ( it != children.end() )
|
||||
{
|
||||
MenuItem* pChild = gwen_cast<MenuItem>( *it );
|
||||
|
||||
if ( pChild->GetName() == name )
|
||||
{
|
||||
if ( bFireChangeEvents )
|
||||
return OnItemSelected( pChild );
|
||||
|
||||
return SelectItem( pChild );
|
||||
}
|
||||
|
||||
++it;
|
||||
}
|
||||
}
|
||||
|
||||
void ComboBox::OnLostKeyboardFocus()
|
||||
{
|
||||
SetTextColor( Color( 0, 0, 0, 255 ) );
|
||||
}
|
||||
|
||||
|
||||
void ComboBox::OnKeyboardFocus()
|
||||
{
|
||||
//Until we add the blue highlighting again
|
||||
SetTextColor( Color( 0, 0, 0, 255 ) );
|
||||
//m_SelectedText->SetTextColor( Color( 255, 255, 255, 255 ) );
|
||||
}
|
||||
|
||||
Gwen::Controls::Label* ComboBox::GetSelectedItem()
|
||||
{
|
||||
return m_SelectedItem;
|
||||
}
|
||||
|
||||
bool ComboBox::IsMenuOpen()
|
||||
{
|
||||
return m_Menu && !m_Menu->Hidden();
|
||||
}
|
||||
|
||||
void ComboBox::OpenList()
|
||||
{
|
||||
if ( !m_Menu ) return;
|
||||
|
||||
m_Menu->SetParent( GetCanvas() );
|
||||
m_Menu->SetHidden( false );
|
||||
m_Menu->BringToFront();
|
||||
|
||||
Gwen::Point p = LocalPosToCanvas( Gwen::Point( 0, 0 ) );
|
||||
|
||||
m_Menu->SetBounds( Gwen::Rect ( p.x, p.y + Height(), Width(), m_Menu->Height()) );
|
||||
}
|
||||
|
||||
void ComboBox::CloseList()
|
||||
{
|
||||
if ( !m_Menu ) return;
|
||||
|
||||
m_Menu->Hide();
|
||||
}
|
||||
|
||||
|
||||
bool ComboBox::OnKeyUp( bool bDown )
|
||||
{
|
||||
if ( bDown )
|
||||
{
|
||||
Base::List& children = m_Menu->GetChildren();
|
||||
|
||||
Base::List::reverse_iterator it = stl::find( children.rbegin(), children.rend(), m_SelectedItem );
|
||||
if ( it != children.rend() && ( ++it != children.rend() ) )
|
||||
{
|
||||
Base* pUpElement = *it;
|
||||
OnItemSelected( pUpElement );
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
bool ComboBox::OnKeyDown( bool bDown )
|
||||
{
|
||||
if ( bDown )
|
||||
{
|
||||
Base::List& children = m_Menu->GetChildren();
|
||||
|
||||
Base::List::iterator it = stl::find( children.begin(), children.end(), m_SelectedItem );
|
||||
if ( it != children.end() && ( ++it != children.end() ) )
|
||||
{
|
||||
Base* pDownElement = *it;
|
||||
OnItemSelected( pDownElement );
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void ComboBox::RenderFocus( Gwen::Skin::Base* /*skin*/ )
|
||||
{
|
||||
}
|
70
lib/gwen/controls/gwen_combobox.h
Normal file
70
lib/gwen/controls/gwen_combobox.h
Normal file
|
@ -0,0 +1,70 @@
|
|||
/*
|
||||
GWEN
|
||||
Copyright (c) 2010 Facepunch Studios
|
||||
See license in Gwen.h
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#ifndef GWEN_CONTROLS_COMBOBOX_H
|
||||
#define GWEN_CONTROLS_COMBOBOX_H
|
||||
|
||||
#include "gwen_base.h"
|
||||
#include "gwen_button.h"
|
||||
#include "../gwen.h"
|
||||
#include "../gwen_skin.h"
|
||||
#include "gwen_textbox.h"
|
||||
#include "gwen_menu.h"
|
||||
|
||||
|
||||
namespace Gwen
|
||||
{
|
||||
namespace Controls
|
||||
{
|
||||
class GWEN_EXPORT ComboBox : public Button
|
||||
{
|
||||
public:
|
||||
|
||||
GWEN_CONTROL( ComboBox, Button );
|
||||
|
||||
virtual void Render( Skin::Base* skin );
|
||||
virtual void Layout( Skin::Base* skin );
|
||||
virtual void UpdateColours();
|
||||
|
||||
virtual void SelectItemByName( const Gwen::String& name, bool bFireChangeEvents = true );
|
||||
virtual Gwen::Controls::Label* GetSelectedItem();
|
||||
|
||||
virtual void OnPress();
|
||||
virtual void OnItemSelected( Controls::Base* pControl );
|
||||
virtual void OpenList();
|
||||
virtual void CloseList();
|
||||
|
||||
virtual void ClearItems();
|
||||
|
||||
virtual MenuItem* AddItem( const String& strLabel, const String& strName = "" );
|
||||
virtual bool OnKeyUp( bool bDown );
|
||||
virtual bool OnKeyDown( bool bDown );
|
||||
|
||||
virtual void RenderFocus( Gwen::Skin::Base* skin );
|
||||
virtual void OnLostKeyboardFocus();
|
||||
virtual void OnKeyboardFocus();
|
||||
|
||||
virtual bool IsMenuOpen();
|
||||
|
||||
virtual bool IsMenuComponent(){ return true; }
|
||||
|
||||
Gwen::Event::Caller onSelection;
|
||||
|
||||
protected:
|
||||
|
||||
void SelectItem( MenuItem* pItem );
|
||||
|
||||
Menu* m_Menu;
|
||||
MenuItem* m_SelectedItem;
|
||||
|
||||
Controls::Base* m_Button;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
#endif
|
182
lib/gwen/controls/gwen_crosssplitter.cpp
Normal file
182
lib/gwen/controls/gwen_crosssplitter.cpp
Normal file
|
@ -0,0 +1,182 @@
|
|||
|
||||
#include "../gwen.h"
|
||||
#include "gwen_crosssplitter.h"
|
||||
#include "gwen_button.h"
|
||||
|
||||
using namespace Gwen;
|
||||
using namespace Controls;
|
||||
|
||||
GWEN_CONTROL_CONSTRUCTOR( CrossSplitter )
|
||||
{
|
||||
m_VSplitter = new SplitterBar( this );
|
||||
m_VSplitter->SetPos( 0, 128 );
|
||||
m_VSplitter->onDragged.Add( this, &CrossSplitter::OnVerticalMoved );
|
||||
m_VSplitter->SetCursor( Gwen::CursorType::SizeNS );
|
||||
|
||||
m_HSplitter = new SplitterBar( this );
|
||||
m_HSplitter->SetPos( 128, 0 );
|
||||
m_HSplitter->onDragged.Add( this, &CrossSplitter::OnHorizontalMoved );
|
||||
m_HSplitter->SetCursor( Gwen::CursorType::SizeWE );
|
||||
|
||||
m_CSplitter = new SplitterBar( this );
|
||||
m_CSplitter->SetPos( 128, 128 );
|
||||
m_CSplitter->onDragged.Add( this, &CrossSplitter::OnCenterMoved );
|
||||
m_CSplitter->SetCursor( Gwen::CursorType::SizeAll );
|
||||
|
||||
m_fHVal = 0.5f;
|
||||
m_fVVal = 0.5f;
|
||||
|
||||
SetPanel( 0, NULL );
|
||||
SetPanel( 1, NULL );
|
||||
SetPanel( 2, NULL );
|
||||
SetPanel( 3, NULL );
|
||||
|
||||
SetSplitterSize( 5 );
|
||||
|
||||
m_iZoomedSection = -1;
|
||||
}
|
||||
|
||||
void CrossSplitter::UpdateVSplitter()
|
||||
{
|
||||
m_VSplitter->MoveTo( m_VSplitter->X(), ( Height() - m_VSplitter->Height() ) * ( m_fVVal ));
|
||||
}
|
||||
void CrossSplitter::UpdateHSplitter()
|
||||
{
|
||||
m_HSplitter->MoveTo( ( Width() - m_HSplitter->Width() ) * ( m_fHVal ), m_HSplitter->Y() );
|
||||
}
|
||||
|
||||
void CrossSplitter::OnCenterMoved( Controls::Base * /*control*/ )
|
||||
{
|
||||
//Move the other two bars into position
|
||||
CalculateValueCenter();
|
||||
Invalidate();
|
||||
}
|
||||
|
||||
void CrossSplitter::UpdateCSplitter()
|
||||
{
|
||||
m_CSplitter->MoveTo( ( Width() - m_CSplitter->Width() ) * ( m_fHVal ), ( Height() - m_CSplitter->Height() ) * ( m_fVVal ));
|
||||
}
|
||||
|
||||
void CrossSplitter::OnHorizontalMoved( Controls::Base * /*control*/ )
|
||||
{
|
||||
m_fHVal = CalculateValueHorizontal();
|
||||
Invalidate();
|
||||
}
|
||||
void CrossSplitter::OnVerticalMoved( Controls::Base * /*control*/ )
|
||||
{
|
||||
m_fVVal = CalculateValueVertical();
|
||||
Invalidate();
|
||||
}
|
||||
|
||||
void CrossSplitter::CalculateValueCenter()
|
||||
{
|
||||
m_fHVal = (float)m_CSplitter->X() / (float)( Width() - m_CSplitter->Width() );
|
||||
m_fVVal = (float)m_CSplitter->Y() / (float)( Height() - m_CSplitter->Height() );
|
||||
}
|
||||
|
||||
float CrossSplitter::CalculateValueHorizontal()
|
||||
{
|
||||
return (float)m_HSplitter->X() / (float)( Width() - m_HSplitter->Width() );
|
||||
}
|
||||
|
||||
float CrossSplitter::CalculateValueVertical()
|
||||
{
|
||||
return (float)m_VSplitter->Y() / (float)( Height() - m_VSplitter->Height() );
|
||||
}
|
||||
|
||||
void CrossSplitter::Layout( Skin::Base* /*skin*/ )
|
||||
{
|
||||
m_VSplitter->SetSize( Width(), m_fBarSize );
|
||||
m_HSplitter->SetSize( m_fBarSize, Height() );
|
||||
m_CSplitter->SetSize( m_fBarSize, m_fBarSize );
|
||||
|
||||
UpdateVSplitter();
|
||||
UpdateHSplitter();
|
||||
UpdateCSplitter();
|
||||
|
||||
if ( m_iZoomedSection == -1 )
|
||||
{
|
||||
if ( m_Sections[0] )
|
||||
m_Sections[0]->SetBounds( 0, 0, m_HSplitter->X(), m_VSplitter->Y() );
|
||||
|
||||
if ( m_Sections[1] )
|
||||
m_Sections[1]->SetBounds( m_HSplitter->X() + m_fBarSize, 0, Width() - ( m_HSplitter->X() + m_fBarSize ), m_VSplitter->Y() );
|
||||
|
||||
if ( m_Sections[2] )
|
||||
m_Sections[2]->SetBounds( 0, m_VSplitter->Y() + m_fBarSize, m_HSplitter->X(), Height() - ( m_VSplitter->Y() + m_fBarSize ) );
|
||||
|
||||
if ( m_Sections[3] )
|
||||
m_Sections[3]->SetBounds( m_HSplitter->X() + m_fBarSize, m_VSplitter->Y() + m_fBarSize, Width() - ( m_HSplitter->X() + m_fBarSize ), Height() - ( m_VSplitter->Y() + m_fBarSize ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
//This should probably use Fill docking instead
|
||||
m_Sections[(int)m_iZoomedSection]->SetBounds( 0, 0, Width(), Height() );
|
||||
}
|
||||
}
|
||||
|
||||
void CrossSplitter::SetPanel( int index, Controls::Base* pPanel)
|
||||
{
|
||||
Debug::AssertCheck( index >= 0 && index <= 3, "CrossSplitter::SetPanel out of range" );
|
||||
|
||||
m_Sections[index] = pPanel;
|
||||
|
||||
if ( pPanel )
|
||||
{
|
||||
pPanel->Dock( Pos::None );
|
||||
pPanel->SetParent( this );
|
||||
}
|
||||
|
||||
Invalidate();
|
||||
}
|
||||
|
||||
Controls::Base* CrossSplitter::GetPanel( int i )
|
||||
{
|
||||
return m_Sections[i];
|
||||
}
|
||||
|
||||
|
||||
void CrossSplitter::ZoomChanged()
|
||||
{
|
||||
onZoomChange.Call( this );
|
||||
if ( m_iZoomedSection == -1 )
|
||||
{
|
||||
onUnZoomed.Call( this );
|
||||
}
|
||||
else
|
||||
{
|
||||
onZoomed.Call( this );
|
||||
}
|
||||
}
|
||||
|
||||
void CrossSplitter::Zoom( int section )
|
||||
{
|
||||
UnZoom();
|
||||
|
||||
if ( m_Sections[section] )
|
||||
{
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
if ( i != section && m_Sections[i] )
|
||||
m_Sections[i]->SetHidden( true );
|
||||
}
|
||||
m_iZoomedSection = section;
|
||||
|
||||
Invalidate();
|
||||
}
|
||||
ZoomChanged();
|
||||
}
|
||||
|
||||
void CrossSplitter::UnZoom()
|
||||
{
|
||||
m_iZoomedSection = -1;
|
||||
|
||||
for ( int i = 0; i < 4; i++ )
|
||||
{
|
||||
if ( m_Sections[i] )
|
||||
m_Sections[i]->SetHidden( false );
|
||||
}
|
||||
|
||||
Invalidate();
|
||||
ZoomChanged();
|
||||
}
|
62
lib/gwen/controls/gwen_crosssplitter.h
Normal file
62
lib/gwen/controls/gwen_crosssplitter.h
Normal file
|
@ -0,0 +1,62 @@
|
|||
#pragma once
|
||||
#ifndef GWEN_CONTROLS_CROSSSPLITTER_H
|
||||
#define GWEN_CONTROLS_CROSSSPLITTER_H
|
||||
|
||||
#include "../gwen.h"
|
||||
#include "gwen_base.h"
|
||||
#include "gwen_splitterbar.h"
|
||||
|
||||
namespace Gwen
|
||||
{
|
||||
namespace Controls
|
||||
{
|
||||
class GWEN_EXPORT CrossSplitter : public Controls::Base
|
||||
{
|
||||
public:
|
||||
|
||||
GWEN_CONTROL( CrossSplitter, Controls::Base );
|
||||
|
||||
void Layout( Skin::Base* skin );
|
||||
|
||||
virtual float CalculateValueVertical();
|
||||
virtual float CalculateValueHorizontal();
|
||||
virtual void CalculateValueCenter();
|
||||
virtual void UpdateHSplitter();
|
||||
virtual void UpdateVSplitter();
|
||||
virtual void UpdateCSplitter();
|
||||
virtual void OnVerticalMoved( Controls::Base * control );
|
||||
virtual void OnHorizontalMoved( Controls::Base * control );
|
||||
virtual void OnCenterMoved( Controls::Base * control );
|
||||
|
||||
virtual void SetPanel( int i, Controls::Base* pPanel );
|
||||
virtual Controls::Base* GetPanel( int i );
|
||||
|
||||
virtual bool IsZoomed(){ return m_iZoomedSection != -1; }
|
||||
virtual void Zoom( int section );
|
||||
virtual void UnZoom();
|
||||
virtual void ZoomChanged();
|
||||
virtual void CenterPanels() { m_fHVal = 0.5f; m_fVVal = 0.5f; Invalidate(); }
|
||||
|
||||
virtual void SetSplitterSize( int size ) { m_fBarSize = size; }
|
||||
|
||||
private:
|
||||
|
||||
SplitterBar* m_VSplitter;
|
||||
SplitterBar* m_HSplitter;
|
||||
SplitterBar* m_CSplitter;
|
||||
|
||||
Controls::Base* m_Sections[4];
|
||||
|
||||
float m_fHVal;
|
||||
float m_fVVal;
|
||||
int m_fBarSize;
|
||||
|
||||
int m_iZoomedSection;
|
||||
|
||||
Gwen::Event::Caller onZoomed;
|
||||
Gwen::Event::Caller onUnZoomed;
|
||||
Gwen::Event::Caller onZoomChange;
|
||||
};
|
||||
}
|
||||
}
|
||||
#endif
|
338
lib/gwen/controls/gwen_dockbase.cpp
Normal file
338
lib/gwen/controls/gwen_dockbase.cpp
Normal file
|
@ -0,0 +1,338 @@
|
|||
/*
|
||||
GWEN
|
||||
Copyright (c) 2010 Facepunch Studios
|
||||
See license in Gwen.h
|
||||
*/
|
||||
|
||||
|
||||
#include "../gwen.h"
|
||||
#include "../gwen_skin.h"
|
||||
#include "gwen_dockbase.h"
|
||||
#include "gwen_dockedtabcontrol.h"
|
||||
#include "gwen_highlight.h"
|
||||
#include "../gwen_draganddrop.h"
|
||||
#include "gwen_resizer.h"
|
||||
|
||||
using namespace Gwen;
|
||||
using namespace Gwen::Controls;
|
||||
|
||||
|
||||
GWEN_CONTROL_CONSTRUCTOR( DockBase )
|
||||
{
|
||||
SetPadding( Padding( 1, 1, 1, 1 ) );
|
||||
SetSize( 200, 200 );
|
||||
|
||||
m_DockedTabControl = NULL;
|
||||
m_Left = NULL;
|
||||
m_Right = NULL;
|
||||
m_Top = NULL;
|
||||
m_Bottom = NULL;
|
||||
|
||||
m_bDrawHover = false;
|
||||
}
|
||||
|
||||
TabControl* DockBase::GetTabControl()
|
||||
{
|
||||
return m_DockedTabControl;
|
||||
}
|
||||
|
||||
void DockBase::SetupChildDock( int iPos )
|
||||
{
|
||||
if ( !m_DockedTabControl )
|
||||
{
|
||||
m_DockedTabControl = new DockedTabControl( this );
|
||||
m_DockedTabControl->onLoseTab.Add( this, &DockBase::OnTabRemoved );
|
||||
m_DockedTabControl->SetTabStripPosition( Pos::Bottom );
|
||||
m_DockedTabControl->SetShowTitlebar( true );
|
||||
}
|
||||
|
||||
Dock( iPos );
|
||||
|
||||
int iSizeDirection = Pos::Left;
|
||||
if ( iPos == Pos::Left ) iSizeDirection = Pos::Right;
|
||||
if ( iPos == Pos::Top ) iSizeDirection = Pos::Bottom;
|
||||
if ( iPos == Pos::Bottom ) iSizeDirection = Pos::Top;
|
||||
|
||||
ControlsInternal::Resizer* sizer = new ControlsInternal::Resizer( this );
|
||||
sizer->Dock( iSizeDirection );
|
||||
sizer->SetResizeDir( iSizeDirection );
|
||||
sizer->SetSize( 2, 2 );
|
||||
sizer->SetTarget( this );
|
||||
}
|
||||
|
||||
void DockBase::Render( Skin::Base* /*skin*/ )
|
||||
{
|
||||
//Gwen::Render->SetDrawColor( Colors::Black );
|
||||
//Gwen::Render->DrawLinedRect( GetRenderBounds() );
|
||||
}
|
||||
|
||||
DockBase** DockBase::GetChildDockPtr( int iPos )
|
||||
{
|
||||
if ( iPos == Pos::Left ) return &m_Left;
|
||||
if ( iPos == Pos::Right ) return &m_Right;
|
||||
if ( iPos == Pos::Top ) return &m_Top;
|
||||
if ( iPos == Pos::Bottom ) return &m_Bottom;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
DockBase* DockBase::GetChildDock( int iPos )
|
||||
{
|
||||
DockBase** pDock = GetChildDockPtr( iPos );
|
||||
|
||||
if ( !(*pDock) )
|
||||
{
|
||||
(*pDock) = new DockBase( this );
|
||||
(*pDock)->SetupChildDock( iPos );
|
||||
}
|
||||
else
|
||||
{
|
||||
(*pDock)->SetHidden( false );
|
||||
}
|
||||
|
||||
return *pDock;
|
||||
}
|
||||
|
||||
int DockBase::GetDroppedTabDirection( int x, int y )
|
||||
{
|
||||
int w = Width();
|
||||
int h = Height();
|
||||
|
||||
float top = (float)y / (float) h;
|
||||
float left = (float)x / (float) w;
|
||||
float right = (float)(w - x) /(float) w;
|
||||
float bottom = (float)(h - y) / (float) h;
|
||||
|
||||
float minimum = GwenUtil_Min( GwenUtil_Min( GwenUtil_Min( top, left ), right ), bottom );
|
||||
m_bDropFar = ( minimum < 0.2f );
|
||||
if ( minimum > 0.3 ) return Pos::Fill;
|
||||
|
||||
if ( top == minimum && (!m_Top || m_Top->Hidden()) ) return Pos::Top;
|
||||
if ( left == minimum && (!m_Left || m_Left->Hidden()) ) return Pos::Left;
|
||||
if ( right == minimum && (!m_Right || m_Right->Hidden()) ) return Pos::Right;
|
||||
if ( bottom == minimum && (!m_Bottom || m_Bottom->Hidden()) ) return Pos::Bottom;
|
||||
|
||||
return Pos::Fill;
|
||||
}
|
||||
|
||||
bool DockBase::DragAndDrop_CanAcceptPackage( Gwen::DragAndDrop::Package* pPackage )
|
||||
{
|
||||
// A TAB button dropped
|
||||
if ( pPackage->name == "TabButtonMove" )
|
||||
return true;
|
||||
|
||||
// a TAB window dropped
|
||||
if ( pPackage->name == "TabWindowMove" )
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool DockBase::DragAndDrop_HandleDrop( Gwen::DragAndDrop::Package* pPackage, int x, int y )
|
||||
{
|
||||
Gwen::Point pPos = CanvasPosToLocal( Gwen::Point( x, y ) );
|
||||
int dir = GetDroppedTabDirection( pPos.x, pPos.y );
|
||||
|
||||
DockedTabControl* pAddTo = m_DockedTabControl;
|
||||
if ( dir == Pos::Fill && pAddTo == NULL ) return false;
|
||||
|
||||
if ( dir != Pos::Fill )
|
||||
{
|
||||
DockBase* pDock = GetChildDock( dir );
|
||||
pAddTo = pDock->m_DockedTabControl;
|
||||
|
||||
if ( !m_bDropFar ) pDock->BringToFront();
|
||||
else pDock->SendToBack();
|
||||
}
|
||||
|
||||
if ( pPackage->name == "TabButtonMove" )
|
||||
{
|
||||
TabButton* pTabButton = gwen_cast<TabButton>( DragAndDrop::SourceControl );
|
||||
if ( !pTabButton ) return false;
|
||||
|
||||
pAddTo->AddPage( pTabButton );
|
||||
}
|
||||
|
||||
if ( pPackage->name == "TabWindowMove" )
|
||||
{
|
||||
DockedTabControl* pTabControl = gwen_cast<DockedTabControl>( DragAndDrop::SourceControl );
|
||||
if ( !pTabControl ) return false;
|
||||
if ( pTabControl == pAddTo ) return false;
|
||||
|
||||
pTabControl->MoveTabsTo( pAddTo );
|
||||
}
|
||||
|
||||
Invalidate();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DockBase::IsEmpty()
|
||||
{
|
||||
if ( m_DockedTabControl && m_DockedTabControl->TabCount() > 0 ) return false;
|
||||
|
||||
if ( m_Left && !m_Left->IsEmpty() ) return false;
|
||||
if ( m_Right && !m_Right->IsEmpty() ) return false;
|
||||
if ( m_Top && !m_Top->IsEmpty() ) return false;
|
||||
if ( m_Bottom && !m_Bottom->IsEmpty() ) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void DockBase::OnTabRemoved( Gwen::Controls::Base* /*pControl*/ )
|
||||
{
|
||||
DoRedundancyCheck();
|
||||
DoConsolidateCheck();
|
||||
}
|
||||
|
||||
void DockBase::DoRedundancyCheck()
|
||||
{
|
||||
if ( !IsEmpty() ) return;
|
||||
|
||||
DockBase* pDockParent = gwen_cast<DockBase>( GetParent() );
|
||||
if ( !pDockParent ) return;
|
||||
|
||||
pDockParent->OnRedundantChildDock( this );
|
||||
}
|
||||
|
||||
void DockBase::DoConsolidateCheck()
|
||||
{
|
||||
if ( IsEmpty() ) return;
|
||||
if ( !m_DockedTabControl ) return;
|
||||
if ( m_DockedTabControl->TabCount() > 0 ) return;
|
||||
|
||||
if ( m_Bottom && !m_Bottom->IsEmpty() )
|
||||
{
|
||||
m_Bottom->m_DockedTabControl->MoveTabsTo( m_DockedTabControl );
|
||||
return;
|
||||
}
|
||||
|
||||
if ( m_Top && !m_Top->IsEmpty() )
|
||||
{
|
||||
m_Top->m_DockedTabControl->MoveTabsTo( m_DockedTabControl );
|
||||
return;
|
||||
}
|
||||
|
||||
if ( m_Left && !m_Left->IsEmpty() )
|
||||
{
|
||||
m_Left->m_DockedTabControl->MoveTabsTo( m_DockedTabControl );
|
||||
return;
|
||||
}
|
||||
|
||||
if ( m_Right && !m_Right->IsEmpty() )
|
||||
{
|
||||
m_Right->m_DockedTabControl->MoveTabsTo( m_DockedTabControl );
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void DockBase::OnRedundantChildDock( DockBase* pDockBase )
|
||||
{
|
||||
pDockBase->SetHidden( true );
|
||||
DoRedundancyCheck();
|
||||
DoConsolidateCheck();
|
||||
}
|
||||
|
||||
void DockBase::DragAndDrop_HoverEnter( Gwen::DragAndDrop::Package* /*pPackage*/, int /*x*/, int /*y*/ )
|
||||
{
|
||||
m_bDrawHover = true;
|
||||
}
|
||||
|
||||
void DockBase::DragAndDrop_HoverLeave( Gwen::DragAndDrop::Package* /*pPackage*/ )
|
||||
{
|
||||
m_bDrawHover = false;
|
||||
}
|
||||
|
||||
void DockBase::DragAndDrop_Hover( Gwen::DragAndDrop::Package* /*pPackage*/, int x, int y )
|
||||
{
|
||||
Gwen::Point pPos = CanvasPosToLocal( Gwen::Point( x, y ) );
|
||||
int dir = GetDroppedTabDirection( pPos.x, pPos.y );
|
||||
|
||||
if ( dir == Pos::Fill )
|
||||
{
|
||||
if ( !m_DockedTabControl )
|
||||
{
|
||||
m_HoverRect = Gwen::Rect( 0, 0, 0, 0 );
|
||||
return;
|
||||
}
|
||||
|
||||
m_HoverRect = GetInnerBounds();
|
||||
return;
|
||||
}
|
||||
|
||||
m_HoverRect = GetRenderBounds();
|
||||
|
||||
int HelpBarWidth = 0;
|
||||
|
||||
if ( dir == Pos::Left )
|
||||
{
|
||||
HelpBarWidth = m_HoverRect.w * 0.25f;
|
||||
m_HoverRect.w = HelpBarWidth;
|
||||
}
|
||||
|
||||
if ( dir == Pos::Right )
|
||||
{
|
||||
HelpBarWidth = m_HoverRect.w * 0.25f;
|
||||
m_HoverRect.x = m_HoverRect.w - HelpBarWidth;
|
||||
m_HoverRect.w = HelpBarWidth;
|
||||
}
|
||||
|
||||
if ( dir == Pos::Top )
|
||||
{
|
||||
HelpBarWidth = m_HoverRect.h * 0.25f;
|
||||
m_HoverRect.h = HelpBarWidth;
|
||||
}
|
||||
|
||||
if ( dir == Pos::Bottom )
|
||||
{
|
||||
HelpBarWidth = m_HoverRect.h * 0.25f;
|
||||
m_HoverRect.y = m_HoverRect.h - HelpBarWidth;
|
||||
m_HoverRect.h = HelpBarWidth;
|
||||
}
|
||||
|
||||
if ( (dir == Pos::Top || dir == Pos::Bottom ) && !m_bDropFar )
|
||||
{
|
||||
if ( m_Left && m_Left->Visible() )
|
||||
{
|
||||
m_HoverRect.x += m_Left->Width();
|
||||
m_HoverRect.w -= m_Left->Width();
|
||||
}
|
||||
|
||||
if ( m_Right && m_Right->Visible() )
|
||||
{
|
||||
m_HoverRect.w -= m_Right->Width();
|
||||
}
|
||||
}
|
||||
|
||||
if ( (dir == Pos::Left || dir == Pos::Right ) && !m_bDropFar )
|
||||
{
|
||||
if ( m_Top && m_Top->Visible() )
|
||||
{
|
||||
m_HoverRect.y += m_Top->Height();
|
||||
m_HoverRect.h -= m_Top->Height();
|
||||
}
|
||||
|
||||
if ( m_Bottom && m_Bottom->Visible() )
|
||||
{
|
||||
m_HoverRect.h -= m_Bottom->Height();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DockBase::RenderOver( Skin::Base* skin )
|
||||
{
|
||||
if ( !m_bDrawHover ) return;
|
||||
|
||||
Gwen::Renderer::Base* render = skin->GetRender();
|
||||
|
||||
render->SetDrawColor( Gwen::Color( 255, 100, 255, 20 ) );
|
||||
render->DrawFilledRect( GetRenderBounds() );
|
||||
|
||||
if ( m_HoverRect.w == 0 ) return;
|
||||
|
||||
render->SetDrawColor( Gwen::Color( 255, 100, 255, 100 ) );
|
||||
render->DrawFilledRect( m_HoverRect );
|
||||
|
||||
render->SetDrawColor( Gwen::Color( 255, 100, 255, 200 ) );
|
||||
render->DrawLinedRect( m_HoverRect );
|
||||
}
|
77
lib/gwen/controls/gwen_dockbase.h
Normal file
77
lib/gwen/controls/gwen_dockbase.h
Normal file
|
@ -0,0 +1,77 @@
|
|||
/*
|
||||
GWEN
|
||||
Copyright (c) 2010 Facepunch Studios
|
||||
See license in Gwen.h
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#ifndef GWEN_CONTROLS_DOCKBASE_H
|
||||
#define GWEN_CONTROLS_DOCKBASE_H
|
||||
|
||||
#include "gwen_base.h"
|
||||
#include "gwen_button.h"
|
||||
|
||||
namespace Gwen
|
||||
{
|
||||
namespace Controls
|
||||
{
|
||||
class DockedTabControl;
|
||||
class TabControl;
|
||||
|
||||
class GWEN_EXPORT DockBase : public Base
|
||||
{
|
||||
public:
|
||||
|
||||
GWEN_CONTROL( DockBase, Base );
|
||||
|
||||
virtual void Render( Skin::Base* skin );
|
||||
virtual void RenderOver( Skin::Base* skin );
|
||||
virtual bool IsEmpty();
|
||||
|
||||
virtual TabControl* GetTabControl();
|
||||
|
||||
virtual DockBase* GetRight(){ return GetChildDock( Pos::Right ); }
|
||||
virtual DockBase* GetLeft(){ return GetChildDock( Pos::Left ); }
|
||||
virtual DockBase* GetTop(){ return GetChildDock( Pos::Top ); }
|
||||
virtual DockBase* GetBottom(){ return GetChildDock( Pos::Bottom ); }
|
||||
|
||||
// No action on space (default button action is to press)
|
||||
virtual bool OnKeySpace( bool /*bDown*/ ){ return false; }
|
||||
|
||||
private:
|
||||
|
||||
// Drag n Drop
|
||||
virtual bool DragAndDrop_HandleDrop( Gwen::DragAndDrop::Package* pPackage, int x, int y );
|
||||
virtual bool DragAndDrop_CanAcceptPackage( Gwen::DragAndDrop::Package* pPackage );
|
||||
virtual void DragAndDrop_HoverEnter( Gwen::DragAndDrop::Package* pPackage, int x, int y );
|
||||
virtual void DragAndDrop_HoverLeave( Gwen::DragAndDrop::Package* pPackage );
|
||||
virtual void DragAndDrop_Hover( Gwen::DragAndDrop::Package* pPackage, int x, int y );
|
||||
|
||||
virtual void SetupChildDock( int iPos );
|
||||
|
||||
virtual void DoRedundancyCheck();
|
||||
virtual void DoConsolidateCheck();
|
||||
virtual void OnRedundantChildDock( DockBase* pDockBase );
|
||||
|
||||
virtual int GetDroppedTabDirection( int x, int y );
|
||||
virtual void OnTabRemoved( Gwen::Controls::Base* pControl );
|
||||
|
||||
DockBase* GetChildDock( int iPos );
|
||||
DockBase** GetChildDockPtr( int iPos );
|
||||
|
||||
DockBase* m_Left;
|
||||
DockBase* m_Right;
|
||||
DockBase* m_Top;
|
||||
DockBase* m_Bottom;
|
||||
|
||||
// Only CHILD dockpanels have a tabcontrol.
|
||||
DockedTabControl* m_DockedTabControl;
|
||||
|
||||
bool m_bDrawHover;
|
||||
bool m_bDropFar;
|
||||
Gwen::Rect m_HoverRect;
|
||||
|
||||
};
|
||||
}
|
||||
}
|
||||
#endif
|
94
lib/gwen/controls/gwen_dockedtabcontrol.cpp
Normal file
94
lib/gwen/controls/gwen_dockedtabcontrol.cpp
Normal file
|
@ -0,0 +1,94 @@
|
|||
/*
|
||||
GWEN
|
||||
Copyright (c) 2010 Facepunch Studios
|
||||
See license in Gwen.h
|
||||
*/
|
||||
|
||||
|
||||
#include "../gwen.h"
|
||||
#include "../gwen_skin.h"
|
||||
#include "gwen_dockedtabcontrol.h"
|
||||
#include "gwen_highlight.h"
|
||||
#include "../gwen_draganddrop.h"
|
||||
#include "gwen_windowcontrol.h"
|
||||
|
||||
using namespace Gwen;
|
||||
using namespace Gwen::Controls;
|
||||
|
||||
GWEN_CONTROL_CONSTRUCTOR( DockedTabControl )
|
||||
{
|
||||
m_WindowControl = NULL;
|
||||
|
||||
Dock( Pos::Fill );
|
||||
|
||||
m_pTitleBar = new TabTitleBar( this );
|
||||
m_pTitleBar->Dock( Pos::Top );
|
||||
m_pTitleBar->SetHidden( true );
|
||||
|
||||
SetAllowReorder( true );
|
||||
|
||||
}
|
||||
|
||||
void DockedTabControl::Layout( Skin::Base* skin )
|
||||
{
|
||||
GetTabStrip()->SetHidden( TabCount() <= 1 );
|
||||
UpdateTitleBar();
|
||||
BaseClass::Layout( skin );
|
||||
}
|
||||
|
||||
void DockedTabControl::UpdateTitleBar()
|
||||
{
|
||||
if ( !GetCurrentButton() ) return;
|
||||
|
||||
m_pTitleBar->UpdateFromTab( GetCurrentButton() );
|
||||
}
|
||||
|
||||
void DockedTabControl::DragAndDrop_StartDragging( Gwen::DragAndDrop::Package* pPackage, int x, int y )
|
||||
{
|
||||
BaseClass::DragAndDrop_StartDragging( pPackage, x, y );
|
||||
|
||||
SetHidden( true );
|
||||
// This hiding our parent thing is kind of lousy.
|
||||
GetParent()->SetHidden( true );
|
||||
}
|
||||
|
||||
void DockedTabControl::DragAndDrop_EndDragging( bool bSuccess, int /*x*/, int /*y*/ )
|
||||
{
|
||||
SetHidden( false );
|
||||
|
||||
if ( !bSuccess )
|
||||
{
|
||||
GetParent()->SetHidden( false );
|
||||
}
|
||||
|
||||
/*
|
||||
if ( !bSuccess )
|
||||
{
|
||||
// Create our window control
|
||||
if ( !m_WindowControl )
|
||||
{
|
||||
m_WindowControl = new WindowControl( GetCanvas() );
|
||||
m_WindowControl->SetBounds( x, y, Width(), Height() );
|
||||
}
|
||||
|
||||
m_WindowControl->SetPosition( x, y );
|
||||
SetParent( m_WindowControl );
|
||||
SetPosition( 0, 0 );
|
||||
Dock( Pos::Fill );
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
void DockedTabControl::MoveTabsTo( DockedTabControl* pTarget )
|
||||
{
|
||||
Base::List Children = GetTabStrip()->Children;
|
||||
for (Base::List::iterator iter = Children.begin(); iter != Children.end(); ++iter)
|
||||
{
|
||||
TabButton* pButton = gwen_cast<TabButton>(*iter);
|
||||
if ( !pButton ) continue;
|
||||
|
||||
pTarget->AddPage( pButton );
|
||||
}
|
||||
|
||||
Invalidate();
|
||||
}
|
42
lib/gwen/controls/gwen_dockedtabcontrol.h
Normal file
42
lib/gwen/controls/gwen_dockedtabcontrol.h
Normal file
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
GWEN
|
||||
Copyright (c) 2010 Facepunch Studios
|
||||
See license in Gwen.h
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#ifndef GWEN_CONTROLS_DOCKEDTABCONTROL_H
|
||||
#define GWEN_CONTROLS_DOCKEDTABCONTROL_H
|
||||
|
||||
#include "gwen_base.h"
|
||||
#include "gwen_tabcontrol.h"
|
||||
|
||||
namespace Gwen
|
||||
{
|
||||
namespace Controls
|
||||
{
|
||||
class GWEN_EXPORT DockedTabControl : public TabControl
|
||||
{
|
||||
public:
|
||||
|
||||
GWEN_CONTROL( DockedTabControl, TabControl );
|
||||
|
||||
void SetShowTitlebar( bool bShow ){ m_pTitleBar->SetHidden( !bShow ); }
|
||||
|
||||
void Layout( Skin::Base* skin );
|
||||
void UpdateTitleBar();
|
||||
|
||||
virtual void DragAndDrop_StartDragging( Gwen::DragAndDrop::Package* pPackage, int x, int y );
|
||||
virtual void DragAndDrop_EndDragging( bool bSuccess, int x, int y );
|
||||
|
||||
void MoveTabsTo( DockedTabControl* pTarget );
|
||||
|
||||
private:
|
||||
|
||||
TabTitleBar* m_pTitleBar;
|
||||
Base* m_WindowControl;
|
||||
|
||||
};
|
||||
}
|
||||
}
|
||||
#endif
|
70
lib/gwen/controls/gwen_dragger.cpp
Normal file
70
lib/gwen/controls/gwen_dragger.cpp
Normal file
|
@ -0,0 +1,70 @@
|
|||
/*
|
||||
GWEN
|
||||
Copyright (c) 2010 Facepunch Studios
|
||||
See license in Gwen.h
|
||||
*/
|
||||
|
||||
|
||||
#include "gwen_dragger.h"
|
||||
|
||||
using namespace Gwen;
|
||||
using namespace Gwen::ControlsInternal;
|
||||
|
||||
|
||||
|
||||
GWEN_CONTROL_CONSTRUCTOR( Dragger )
|
||||
{
|
||||
m_pTarget = NULL;
|
||||
SetMouseInputEnabled( true );
|
||||
m_bDepressed = false;
|
||||
m_bDoMove = true;
|
||||
}
|
||||
|
||||
void Dragger::OnMouseClickLeft( int x, int y, bool bDown )
|
||||
{
|
||||
if ( bDown )
|
||||
{
|
||||
m_bDepressed = true;
|
||||
|
||||
if ( m_pTarget)
|
||||
m_HoldPos = m_pTarget->CanvasPosToLocal( Gwen::Point( x, y ) );
|
||||
|
||||
Gwen::MouseFocus = this;
|
||||
onDragStart.Call( this );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_bDepressed = false;
|
||||
Gwen::MouseFocus = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void Dragger::OnMouseMoved( int x, int y, int deltaX, int deltaY )
|
||||
{
|
||||
if ( !m_bDepressed ) return;
|
||||
|
||||
if ( m_bDoMove && m_pTarget )
|
||||
{
|
||||
Gwen::Point p = Gwen::Point( x - m_HoldPos.x, y - m_HoldPos.y );
|
||||
|
||||
// Translate to parent
|
||||
if ( m_pTarget->GetParent() )
|
||||
p = m_pTarget->GetParent()->CanvasPosToLocal( p );
|
||||
|
||||
m_pTarget->MoveTo( p.x, p.y );
|
||||
}
|
||||
|
||||
Gwen::Event::Information info;
|
||||
info.Point = Gwen::Point( deltaX, deltaY );
|
||||
onDragged.Call( this, info );
|
||||
}
|
||||
|
||||
void Dragger::Render( Skin::Base* skin )
|
||||
{
|
||||
//skin->DrawButton(this,false,false, false);
|
||||
}
|
||||
|
||||
void Dragger::OnMouseDoubleClickLeft( int x, int y )
|
||||
{
|
||||
onDoubleClickLeft.Call( this );
|
||||
}
|
52
lib/gwen/controls/gwen_dragger.h
Normal file
52
lib/gwen/controls/gwen_dragger.h
Normal file
|
@ -0,0 +1,52 @@
|
|||
/*
|
||||
GWEN
|
||||
Copyright (c) 2010 Facepunch Studios
|
||||
See license in Gwen.h
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#ifndef GWEN_CONTROLS_DRAGGER_H
|
||||
#define GWEN_CONTROLS_DRAGGER_H
|
||||
|
||||
#include "gwen_base.h"
|
||||
#include "../gwen.h"
|
||||
#include "../gwen_skin.h"
|
||||
|
||||
|
||||
namespace Gwen
|
||||
{
|
||||
namespace ControlsInternal
|
||||
{
|
||||
class GWEN_EXPORT Dragger : public Controls::Base
|
||||
{
|
||||
public:
|
||||
|
||||
GWEN_CONTROL( Dragger, Controls::Base );
|
||||
|
||||
virtual void OnMouseMoved( int x, int y, int deltaX, int deltaY );
|
||||
|
||||
virtual void OnMouseClickLeft( int x, int y, bool bDown );
|
||||
virtual void Render( Skin::Base* skin );
|
||||
|
||||
virtual void SetTarget( Controls::Base* pBase ){ m_pTarget = pBase; }
|
||||
virtual bool IsDepressed(){ return m_bDepressed; }
|
||||
|
||||
virtual void SetDoMove( bool b ){ m_bDoMove = b; }
|
||||
|
||||
virtual void OnMouseDoubleClickLeft( int x, int y );
|
||||
|
||||
Gwen::Event::Caller onDragged;
|
||||
Gwen::Event::Caller onDragStart;
|
||||
|
||||
Gwen::Event::Caller onDoubleClickLeft;
|
||||
|
||||
protected:
|
||||
|
||||
bool m_bDepressed;
|
||||
Gwen::Point m_HoldPos;
|
||||
Controls::Base* m_pTarget;
|
||||
bool m_bDoMove;
|
||||
};
|
||||
}
|
||||
}
|
||||
#endif
|
64
lib/gwen/controls/gwen_fieldlabel.h
Normal file
64
lib/gwen/controls/gwen_fieldlabel.h
Normal file
|
@ -0,0 +1,64 @@
|
|||
/*
|
||||
GWEN
|
||||
Copyright (c) 2010 Facepunch Studios
|
||||
See license in Gwen.h
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#ifndef GWEN_CONTROLS_FIELDLABEL_H
|
||||
#define GWEN_CONTROLS_FIELDLABEL_H
|
||||
|
||||
#include "../gwen_baserender.h"
|
||||
#include "gwen_label.h"
|
||||
|
||||
namespace Gwen
|
||||
{
|
||||
namespace Controls
|
||||
{
|
||||
class GWEN_EXPORT FieldLabel : public Controls::Label
|
||||
{
|
||||
public:
|
||||
|
||||
static inline FieldLabel* Setup( Controls::Base* pControl, const Gwen::TextObject& text )
|
||||
{
|
||||
FieldLabel* plbl = new FieldLabel( pControl->GetParent() );
|
||||
plbl->SetText( text );
|
||||
plbl->SetSize( pControl->Width(), pControl->Height() );
|
||||
plbl->Dock( pControl->GetDock() );
|
||||
|
||||
plbl->SetField( pControl );
|
||||
return plbl;
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
GWEN_CONTROL_INLINE( FieldLabel, Controls::Label )
|
||||
{
|
||||
m_pField = NULL;
|
||||
SetMargin( Margin( 0, 1, 0, 1 ) );
|
||||
SetAlignment( Pos::CenterV | Pos::Left );
|
||||
}
|
||||
|
||||
void SetField( Controls::Base* pField )
|
||||
{
|
||||
pField->SetParent( this );
|
||||
pField->Dock( Pos::Right );
|
||||
m_pField = pField;
|
||||
}
|
||||
|
||||
void Layout( Gwen::Skin::Base* pskin )
|
||||
{
|
||||
m_pField->SetWidth( Width() - 70 );
|
||||
|
||||
BaseClass::Layout( pskin );
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
Controls::Base* m_pField;
|
||||
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
44
lib/gwen/controls/gwen_groupbox.cpp
Normal file
44
lib/gwen/controls/gwen_groupbox.cpp
Normal file
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
GWEN
|
||||
Copyright (c) 2010 Facepunch Studios
|
||||
See license in Gwen.h
|
||||
*/
|
||||
|
||||
|
||||
#include "gwen_groupbox.h"
|
||||
|
||||
using namespace Gwen;
|
||||
using namespace Gwen::Controls;
|
||||
|
||||
|
||||
GWEN_CONTROL_CONSTRUCTOR( GroupBox )
|
||||
{
|
||||
// Set to true, because it's likely that our
|
||||
// children will want mouse input, and they
|
||||
// can't get it without us..
|
||||
SetMouseInputEnabled( true );
|
||||
|
||||
SetTextPadding( Padding( 10, 0, 0, 0 ) );
|
||||
|
||||
SetAlignment( Pos::Top | Pos::Left );
|
||||
Invalidate();
|
||||
|
||||
m_InnerPanel = new Base( this );
|
||||
m_InnerPanel->Dock( Pos::Fill );
|
||||
|
||||
m_InnerMargin = 6;
|
||||
|
||||
}
|
||||
|
||||
void GroupBox::Layout( Skin::Base* skin )
|
||||
{
|
||||
m_InnerPanel->SetMargin( Margin( m_InnerMargin, TextHeight() - 3 + m_InnerMargin, m_InnerMargin, m_InnerMargin ) );
|
||||
|
||||
BaseClass::Layout( skin );
|
||||
}
|
||||
|
||||
|
||||
void GroupBox::Render( Skin::Base* skin )
|
||||
{
|
||||
skin->DrawGroupBox( this, TextX(), TextHeight(), TextWidth() );
|
||||
}
|
40
lib/gwen/controls/gwen_groupbox.h
Normal file
40
lib/gwen/controls/gwen_groupbox.h
Normal file
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
GWEN
|
||||
Copyright (c) 2010 Facepunch Studios
|
||||
See license in Gwen.h
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#ifndef GWEN_CONTROLS_GROUPBOX_H
|
||||
#define GWEN_CONTROLS_GROUPBOX_H
|
||||
|
||||
#include "gwen_base.h"
|
||||
#include "gwen_label.h"
|
||||
#include "../gwen.h"
|
||||
#include "../gwen_skin.h"
|
||||
|
||||
|
||||
namespace Gwen
|
||||
{
|
||||
namespace Controls
|
||||
{
|
||||
|
||||
class GWEN_EXPORT GroupBox : public Label
|
||||
{
|
||||
public:
|
||||
|
||||
GWEN_CONTROL( GroupBox, Label );
|
||||
|
||||
virtual void Render( Skin::Base* skin );
|
||||
virtual void Layout( Skin::Base* skin );
|
||||
|
||||
virtual void SetInnerMargin( int i ){ m_InnerMargin = i; }
|
||||
|
||||
protected:
|
||||
|
||||
int m_InnerMargin;
|
||||
|
||||
};
|
||||
}
|
||||
}
|
||||
#endif
|
36
lib/gwen/controls/gwen_highlight.h
Normal file
36
lib/gwen/controls/gwen_highlight.h
Normal file
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
GWEN
|
||||
Copyright (c) 2010 Facepunch Studios
|
||||
See license in Gwen.h
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#ifndef GWEN_CONTROLS_HIGHLIGHT_H
|
||||
#define GWEN_CONTROLS_HIGHLIGHT_H
|
||||
|
||||
#include "../gwen_baserender.h"
|
||||
#include "gwen_base.h"
|
||||
#include "../gwen_skin.h"
|
||||
|
||||
namespace Gwen
|
||||
{
|
||||
namespace ControlsInternal
|
||||
{
|
||||
class GWEN_EXPORT Highlight : public Controls::Base
|
||||
{
|
||||
public:
|
||||
|
||||
GWEN_CONTROL_INLINE( Highlight, Controls::Base )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void Render( Skin::Base* skin )
|
||||
{
|
||||
skin->DrawHighlight( this );
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
136
lib/gwen/controls/gwen_horizontalscrollbar.cpp
Normal file
136
lib/gwen/controls/gwen_horizontalscrollbar.cpp
Normal file
|
@ -0,0 +1,136 @@
|
|||
/*
|
||||
GWEN
|
||||
Copyright (c) 2010 Facepunch Studios
|
||||
See license in Gwen.h
|
||||
*/
|
||||
|
||||
|
||||
#include "gwen_scrollbar.h"
|
||||
#include "gwen_horizontalscrollbar.h"
|
||||
|
||||
using namespace Gwen;
|
||||
using namespace Gwen::Controls;
|
||||
|
||||
GWEN_CONTROL_CONSTRUCTOR( HorizontalScrollBar )
|
||||
{
|
||||
m_Bar->SetHorizontal();
|
||||
|
||||
m_ScrollButton[SCROLL_BUTTON_LEFT]->SetDirectionLeft();
|
||||
m_ScrollButton[SCROLL_BUTTON_LEFT]->onPress.Add( this, &HorizontalScrollBar::NudgeLeft );
|
||||
|
||||
m_ScrollButton[SCROLL_BUTTON_RIGHT]->SetDirectionRight();
|
||||
m_ScrollButton[SCROLL_BUTTON_RIGHT]->onPress.Add( this, &HorizontalScrollBar::NudgeRight );
|
||||
|
||||
m_Bar->onDragged.Add( this, &HorizontalScrollBar::OnBarMoved );
|
||||
}
|
||||
|
||||
void HorizontalScrollBar::Layout( Skin::Base* skin )
|
||||
{
|
||||
BaseClass::Layout( skin );
|
||||
|
||||
m_ScrollButton[SCROLL_BUTTON_LEFT]->SetWidth( Height() );
|
||||
m_ScrollButton[SCROLL_BUTTON_LEFT]->Dock(Pos::Left);
|
||||
|
||||
m_ScrollButton[SCROLL_BUTTON_RIGHT]->SetWidth( Height() );
|
||||
m_ScrollButton[SCROLL_BUTTON_RIGHT]->Dock(Pos::Right);
|
||||
|
||||
m_Bar->SetHeight( GetButtonSize() );
|
||||
m_Bar->SetPadding( Padding( GetButtonSize(), 0, GetButtonSize(), 0 ) );
|
||||
|
||||
float barWidth = (m_fViewableContentSize / m_fContentSize) * (Width() - GetButtonSize());
|
||||
|
||||
if ( barWidth < GetButtonSize() * 0.5 )
|
||||
barWidth = GetButtonSize() * 0.5;
|
||||
|
||||
m_Bar->SetWidth( barWidth );
|
||||
m_Bar->SetHidden( Width() - (GetButtonSize() * 2) <= barWidth );
|
||||
|
||||
//Based on our last scroll amount, produce a position for the bar
|
||||
if ( !m_Bar->IsDepressed() )
|
||||
{
|
||||
SetScrolledAmount( GetScrolledAmount(), true );
|
||||
}
|
||||
}
|
||||
|
||||
void HorizontalScrollBar::NudgeLeft( Base* /*control*/ )
|
||||
{
|
||||
if ( !IsDisabled() )
|
||||
SetScrolledAmount( GetScrolledAmount() - GetNudgeAmount(), true);
|
||||
}
|
||||
|
||||
void HorizontalScrollBar::NudgeRight( Base* /*control*/ )
|
||||
{
|
||||
if ( !IsDisabled() )
|
||||
SetScrolledAmount( GetScrolledAmount() + GetNudgeAmount(), true);
|
||||
}
|
||||
|
||||
void HorizontalScrollBar::ScrollToLeft()
|
||||
{
|
||||
SetScrolledAmount( 0, true);
|
||||
}
|
||||
void HorizontalScrollBar::ScrollToRight()
|
||||
{
|
||||
SetScrolledAmount( 1, true);
|
||||
}
|
||||
|
||||
float HorizontalScrollBar::GetNudgeAmount()
|
||||
{
|
||||
if ( m_bDepressed )
|
||||
return m_fViewableContentSize / m_fContentSize;
|
||||
else
|
||||
return BaseClass::GetNudgeAmount();
|
||||
}
|
||||
|
||||
|
||||
|
||||
void HorizontalScrollBar::OnMouseClickLeft( int x, int y, bool bDown )
|
||||
{
|
||||
if ( bDown )
|
||||
{
|
||||
m_bDepressed = true;
|
||||
Gwen::MouseFocus = this;
|
||||
}
|
||||
else
|
||||
{
|
||||
Gwen::Point clickPos = CanvasPosToLocal( Gwen::Point( x, y ) );
|
||||
if ( clickPos.x < m_Bar->X() )
|
||||
NudgeLeft( this );
|
||||
else if ( clickPos.x > m_Bar->X() + m_Bar->Width() )
|
||||
NudgeRight( this );
|
||||
|
||||
m_bDepressed = false;
|
||||
Gwen::MouseFocus = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
float HorizontalScrollBar::CalculateScrolledAmount()
|
||||
{
|
||||
return (float)(m_Bar->X() - GetButtonSize()) / (float)(Width() - m_Bar->Width() - (GetButtonSize() * 2 ));
|
||||
}
|
||||
|
||||
bool HorizontalScrollBar::SetScrolledAmount( float amount, bool forceUpdate )
|
||||
{
|
||||
amount = Gwen::Clamp( amount, 0, 1 );
|
||||
|
||||
if ( !BaseClass::SetScrolledAmount( amount, forceUpdate ) )
|
||||
return false;
|
||||
|
||||
if ( forceUpdate )
|
||||
{
|
||||
int newX = GetButtonSize() + (amount * ((Width() - m_Bar->Width()) - (GetButtonSize()*2)));
|
||||
m_Bar->MoveTo( newX, m_Bar->Y() );
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void HorizontalScrollBar::OnBarMoved( Controls::Base* control )
|
||||
{
|
||||
if ( m_Bar->IsDepressed() )
|
||||
{
|
||||
SetScrolledAmount( CalculateScrolledAmount(), false );
|
||||
BaseClass::OnBarMoved(control);
|
||||
}
|
||||
else
|
||||
InvalidateParent();
|
||||
}
|
51
lib/gwen/controls/gwen_horizontalscrollbar.h
Normal file
51
lib/gwen/controls/gwen_horizontalscrollbar.h
Normal file
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
GWEN
|
||||
Copyright (c) 2010 Facepunch Studios
|
||||
See license in Gwen.h
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#ifndef GWEN_CONTROLS_HORIZONTALSCROLLBAR_H
|
||||
#define GWEN_CONTROLS_HORIZONTALSCROLLBAR_H
|
||||
|
||||
#include "gwen_base.h"
|
||||
#include "gwen_button.h"
|
||||
#include "../gwen.h"
|
||||
#include "../gwen_skin.h"
|
||||
#include "gwen_dragger.h"
|
||||
#include "gwen_scrollbar.h"
|
||||
|
||||
namespace Gwen
|
||||
{
|
||||
namespace Controls
|
||||
{
|
||||
class GWEN_EXPORT HorizontalScrollBar : public BaseScrollBar
|
||||
{
|
||||
public:
|
||||
|
||||
GWEN_CONTROL( HorizontalScrollBar, BaseScrollBar );
|
||||
|
||||
virtual void Layout( Skin::Base* skin );
|
||||
|
||||
virtual void OnMouseClickLeft( int x, int y, bool bDown );
|
||||
virtual void OnBarMoved( Controls::Base* control );
|
||||
|
||||
virtual int GetBarSize() { return m_Bar->Width(); }
|
||||
virtual int GetBarPos() { return m_Bar->X() - Height(); }
|
||||
virtual void SetBarSize( int size ) { m_Bar->SetWidth( size ); }
|
||||
virtual int GetButtonSize() { return Height(); }
|
||||
|
||||
virtual void ScrollToLeft();
|
||||
virtual void ScrollToRight();
|
||||
virtual void NudgeLeft( Base* control );
|
||||
virtual void NudgeRight( Base* control );
|
||||
virtual float GetNudgeAmount();
|
||||
|
||||
virtual float CalculateScrolledAmount();
|
||||
virtual bool SetScrolledAmount(float amount, bool forceUpdate);
|
||||
|
||||
virtual bool IsHorizontal(){ return true; }
|
||||
};
|
||||
}
|
||||
}
|
||||
#endif
|
46
lib/gwen/controls/gwen_horizontalslider.cpp
Normal file
46
lib/gwen/controls/gwen_horizontalslider.cpp
Normal file
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
GWEN
|
||||
Copyright (c) 2010 Facepunch Studios
|
||||
See license in Gwen.h
|
||||
*/
|
||||
|
||||
|
||||
#include "gwen_slider.h"
|
||||
#include "gwen_horizontalslider.h"
|
||||
|
||||
using namespace Gwen;
|
||||
using namespace Gwen::Controls;
|
||||
using namespace Gwen::ControlsInternal;
|
||||
|
||||
|
||||
GWEN_CONTROL_CONSTRUCTOR( HorizontalSlider )
|
||||
{
|
||||
m_SliderBar->SetHorizontal( true );
|
||||
}
|
||||
|
||||
float HorizontalSlider::CalculateValue()
|
||||
{
|
||||
return (float)m_SliderBar->X() / (float)( Width() - m_SliderBar->Width() );
|
||||
}
|
||||
|
||||
void HorizontalSlider::UpdateBarFromValue()
|
||||
{
|
||||
m_SliderBar->MoveTo( ( Width() - m_SliderBar->Width() ) * ( m_fValue ), m_SliderBar->Y() );
|
||||
}
|
||||
|
||||
void HorizontalSlider::OnMouseClickLeft( int x, int y, bool bDown )
|
||||
{
|
||||
m_SliderBar->MoveTo( CanvasPosToLocal( Gwen::Point( x, y ) ).x - m_SliderBar->Width() * 0.5, m_SliderBar->Y() );
|
||||
m_SliderBar->OnMouseClickLeft( x, y, bDown );
|
||||
OnMoved( m_SliderBar );
|
||||
}
|
||||
|
||||
void HorizontalSlider::Layout(Skin::Base* /*skin*/)
|
||||
{
|
||||
m_SliderBar->SetSize( 15, Height() );
|
||||
}
|
||||
|
||||
void HorizontalSlider::Render( Skin::Base* skin )
|
||||
{
|
||||
skin->DrawSlider( this, true, m_bClampToNotches ? m_iNumNotches : 0, m_SliderBar->Width() );
|
||||
}
|
35
lib/gwen/controls/gwen_horizontalslider.h
Normal file
35
lib/gwen/controls/gwen_horizontalslider.h
Normal file
|
@ -0,0 +1,35 @@
|
|||
/*
|
||||
GWEN
|
||||
Copyright (c) 2010 Facepunch Studios
|
||||
See license in Gwen.h
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#ifndef GWEN_CONTROLS_HORIZONTALSLIDER_H
|
||||
#define GWEN_CONTROLS_HORIZONTALSLIDER_H
|
||||
|
||||
#include "gwen_base.h"
|
||||
#include "gwen_button.h"
|
||||
#include "gwen_dragger.h"
|
||||
#include "../gwen.h"
|
||||
#include "../gwen_skin.h"
|
||||
#include "gwen_slider.h"
|
||||
|
||||
namespace Gwen
|
||||
{
|
||||
namespace Controls
|
||||
{
|
||||
class GWEN_EXPORT HorizontalSlider : public Slider
|
||||
{
|
||||
GWEN_CONTROL( HorizontalSlider, Slider );
|
||||
|
||||
virtual void Layout( Skin::Base* skin );
|
||||
virtual void Render( Skin::Base* skin );
|
||||
|
||||
virtual float CalculateValue();
|
||||
virtual void UpdateBarFromValue();
|
||||
virtual void OnMouseClickLeft( int x, int y, bool bDown );
|
||||
};
|
||||
}
|
||||
}
|
||||
#endif
|
174
lib/gwen/controls/gwen_hsvcolorpicker.cpp
Normal file
174
lib/gwen/controls/gwen_hsvcolorpicker.cpp
Normal file
|
@ -0,0 +1,174 @@
|
|||
/*
|
||||
GWEN
|
||||
Copyright (c) 2010 Facepunch Studios
|
||||
See license in Gwen.h
|
||||
*/
|
||||
|
||||
|
||||
#include "gwen_hsvcolorpicker.h"
|
||||
#include "gwen_colorcontrols.h"
|
||||
#include "gwen_colorpicker.h"
|
||||
#include "gwen_textbox.h"
|
||||
#include "gwen_label.h"
|
||||
#include "../gwen_utility.h"
|
||||
|
||||
using namespace Gwen;
|
||||
using namespace Gwen::Controls;
|
||||
|
||||
|
||||
GWEN_CONTROL_CONSTRUCTOR( HSVColorPicker )
|
||||
{
|
||||
SetMouseInputEnabled( true );
|
||||
SetSize( 256, 64 );
|
||||
SetCacheToTexture();
|
||||
|
||||
m_LerpBox = new Gwen::Controls::ColorLerpBox( this );
|
||||
m_LerpBox->onSelectionChanged.Add( this, &HSVColorPicker::ColorBoxChanged );
|
||||
m_LerpBox->Dock( Pos::Left );
|
||||
|
||||
m_ColorSlider = new Gwen::Controls::ColorSlider( this );
|
||||
m_ColorSlider->SetPos( m_LerpBox->Width() + 15, 5 );
|
||||
m_ColorSlider->onSelectionChanged.Add( this, &HSVColorPicker::ColorSliderChanged );
|
||||
m_ColorSlider->Dock( Pos::Left );
|
||||
|
||||
m_After = new Gwen::ControlsInternal::ColorDisplay( this );
|
||||
m_After->SetSize( 48, 24 );
|
||||
m_After->SetPos( m_ColorSlider->X() + m_ColorSlider->Width() + 15, 5 );
|
||||
|
||||
m_Before = new Gwen::ControlsInternal::ColorDisplay( this );
|
||||
m_Before->SetSize( 48, 24 );
|
||||
m_Before->SetPos( m_After->X(), 28 );
|
||||
|
||||
int x = m_Before->X();
|
||||
int y = m_Before->Y() + 30;
|
||||
|
||||
|
||||
{
|
||||
Label* label = new Label( this );
|
||||
label->SetText("R:");
|
||||
label->SizeToContents();
|
||||
label->SetPos( x, y );
|
||||
|
||||
TextBoxNumeric* numeric = new TextBoxNumeric( this );
|
||||
numeric->SetName( "RedBox" );
|
||||
numeric->SetPos( x + 15, y -1 );
|
||||
numeric->SetSize( 26, 16 );
|
||||
numeric->SetSelectAllOnFocus( true );
|
||||
numeric->onTextChanged.Add( this, &HSVColorPicker::NumericTyped );
|
||||
|
||||
}
|
||||
|
||||
y+= 20;
|
||||
|
||||
{
|
||||
Label* label = new Label( this );
|
||||
label->SetText("G:");
|
||||
label->SizeToContents();
|
||||
label->SetPos( x, y );
|
||||
|
||||
|
||||
TextBoxNumeric* numeric = new TextBoxNumeric( this );
|
||||
numeric->SetName( "GreenBox" );
|
||||
numeric->SetPos( x + 15, y -1 );
|
||||
numeric->SetSize( 26, 16 );
|
||||
numeric->SetSelectAllOnFocus( true );
|
||||
numeric->onTextChanged.Add( this, &HSVColorPicker::NumericTyped );
|
||||
}
|
||||
|
||||
y+= 20;
|
||||
|
||||
{
|
||||
Label* label = new Label( this );
|
||||
label->SetText("B:");
|
||||
label->SizeToContents();
|
||||
label->SetPos( x, y );
|
||||
|
||||
|
||||
TextBoxNumeric* numeric = new TextBoxNumeric( this );
|
||||
numeric->SetName( "BlueBox" );
|
||||
numeric->SetPos( x + 15, y -1 );
|
||||
numeric->SetSize( 26, 16 );
|
||||
numeric->SetSelectAllOnFocus( true );
|
||||
numeric->onTextChanged.Add( this, &HSVColorPicker::NumericTyped );
|
||||
}
|
||||
}
|
||||
|
||||
void HSVColorPicker::NumericTyped( Gwen::Controls::Base* control )
|
||||
{
|
||||
TextBoxNumeric* box = gwen_cast<TextBoxNumeric>(control);
|
||||
if ( !box ) return;
|
||||
|
||||
if ( box->GetText() == "" ) return;
|
||||
|
||||
int textValue = atoi( box->GetText().c_str() );
|
||||
if ( textValue < 0 ) textValue = 0;
|
||||
if ( textValue > 255 ) textValue = 255;
|
||||
|
||||
Gwen::Color newColor = GetColor();
|
||||
|
||||
if ( box->GetName().find( "Red" ) != Gwen::String::npos )
|
||||
{
|
||||
newColor.r = textValue;
|
||||
}
|
||||
else if ( box->GetName().find( "Green" ) != Gwen::String::npos )
|
||||
{
|
||||
newColor.g = textValue;
|
||||
}
|
||||
else if ( box->GetName().find( "Blue" ) != Gwen::String::npos )
|
||||
{
|
||||
newColor.b = textValue;
|
||||
}
|
||||
else if ( box->GetName().find( "Alpha" ) != Gwen::String::npos )
|
||||
{
|
||||
newColor.a = textValue;
|
||||
}
|
||||
|
||||
SetColor( newColor );
|
||||
}
|
||||
|
||||
void HSVColorPicker::UpdateControls(Gwen::Color color)
|
||||
{
|
||||
// What in the FUCK
|
||||
|
||||
TextBoxNumeric* redBox = gwen_cast<TextBoxNumeric>( FindChildByName( "RedBox", false ) );
|
||||
if ( redBox ) redBox->SetText( Gwen::Utility::ToString( (int)color.r), false );
|
||||
|
||||
TextBoxNumeric* greenBox = gwen_cast<TextBoxNumeric>( FindChildByName( "GreenBox", false ) );
|
||||
if ( greenBox ) greenBox->SetText( Gwen::Utility::ToString( (int)color.g ), false );
|
||||
|
||||
TextBoxNumeric* blueBox = gwen_cast<TextBoxNumeric>( FindChildByName( "BlueBox", false ) );
|
||||
if ( blueBox ) blueBox->SetText( Gwen::Utility::ToString( (int)color.b ), false );
|
||||
|
||||
m_After->SetColor( color );
|
||||
}
|
||||
void HSVColorPicker::SetColor( Gwen::Color color, bool onlyHue, bool reset )
|
||||
{
|
||||
|
||||
UpdateControls( color );
|
||||
|
||||
|
||||
if ( reset )
|
||||
m_Before->SetColor( color );
|
||||
|
||||
m_ColorSlider->SetColor( color );
|
||||
m_LerpBox->SetColor( color, onlyHue );
|
||||
m_After->SetColor( color );
|
||||
}
|
||||
|
||||
Gwen::Color HSVColorPicker::GetColor()
|
||||
{
|
||||
return m_LerpBox->GetSelectedColor();
|
||||
}
|
||||
|
||||
void HSVColorPicker::ColorBoxChanged( Gwen::Controls::Base* /*pControl*/ )
|
||||
{
|
||||
onColorChanged.Call( this );
|
||||
UpdateControls( GetColor() );
|
||||
Invalidate();
|
||||
}
|
||||
void HSVColorPicker::ColorSliderChanged( Gwen::Controls::Base* /*pControl*/ )
|
||||
{
|
||||
if ( m_LerpBox )
|
||||
m_LerpBox->SetColor( m_ColorSlider->GetSelectedColor(), true );
|
||||
Invalidate();
|
||||
}
|
47
lib/gwen/controls/gwen_hsvcolorpicker.h
Normal file
47
lib/gwen/controls/gwen_hsvcolorpicker.h
Normal file
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
GWEN
|
||||
Copyright (c) 2010 Facepunch Studios
|
||||
See license in Gwen.h
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#ifndef GWEN_CONTROLS_HSVCOLORPICKER_H
|
||||
#define GWEN_CONTROLS_HSVCOLORPICKER_H
|
||||
|
||||
#include "gwen_base.h"
|
||||
#include "../gwen.h"
|
||||
#include "../gwen_skin.h"
|
||||
#include "gwen_colorcontrols.h"
|
||||
#include "gwen_colorpicker.h"
|
||||
|
||||
|
||||
namespace Gwen
|
||||
{
|
||||
namespace Controls
|
||||
{
|
||||
class GWEN_EXPORT HSVColorPicker : public Controls::Base
|
||||
{
|
||||
public:
|
||||
GWEN_CONTROL( HSVColorPicker, Controls::Base );
|
||||
|
||||
Gwen::Color GetColor();
|
||||
Gwen::Color GetDefaultColor() { return m_Before->GetColor(); }
|
||||
void SetColor( Gwen::Color color, bool onlyHue = false, bool reset = false );
|
||||
|
||||
void ColorBoxChanged( Gwen::Controls::Base* pControl );
|
||||
void ColorSliderChanged( Gwen::Controls::Base* pControl );
|
||||
void NumericTyped( Gwen::Controls::Base* control );
|
||||
|
||||
void UpdateControls( Gwen::Color newColor );
|
||||
|
||||
Event::Caller onColorChanged;
|
||||
|
||||
protected:
|
||||
ColorLerpBox* m_LerpBox;
|
||||
ColorSlider* m_ColorSlider;
|
||||
ControlsInternal::ColorDisplay* m_Before;
|
||||
ControlsInternal::ColorDisplay* m_After;
|
||||
};
|
||||
}
|
||||
}
|
||||
#endif
|
9
lib/gwen/controls/gwen_imagepanel.cpp
Normal file
9
lib/gwen/controls/gwen_imagepanel.cpp
Normal file
|
@ -0,0 +1,9 @@
|
|||
/*
|
||||
GWEN
|
||||
Copyright (c) 2010 Facepunch Studios
|
||||
See license in Gwen.h
|
||||
*/
|
||||
|
||||
|
||||
#include "gwen_imagepanel.h"
|
||||
|
115
lib/gwen/controls/gwen_imagepanel.h
Normal file
115
lib/gwen/controls/gwen_imagepanel.h
Normal file
|
@ -0,0 +1,115 @@
|
|||
/*
|
||||
GWEN
|
||||
Copyright (c) 2010 Facepunch Studios
|
||||
See license in Gwen.h
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#ifndef GWEN_CONTROLS_IMAGEPANEL_H
|
||||
#define GWEN_CONTROLS_IMAGEPANEL_H
|
||||
|
||||
#include "../gwen.h"
|
||||
#include "gwen_base.h"
|
||||
#include "../gwen_baserender.h"
|
||||
#include "../gwen_texture.h"
|
||||
|
||||
namespace Gwen
|
||||
{
|
||||
namespace Controls
|
||||
{
|
||||
class GWEN_EXPORT ImagePanel : public Controls::Base
|
||||
{
|
||||
public:
|
||||
|
||||
GWEN_CONTROL_INLINE( ImagePanel, Controls::Base )
|
||||
{
|
||||
SetUV( 0, 0, 1, 1 );
|
||||
SetMouseInputEnabled( false );
|
||||
m_DrawColor = Colors::White;
|
||||
|
||||
SetStretch( true );
|
||||
}
|
||||
|
||||
virtual ~ImagePanel()
|
||||
{
|
||||
m_Texture.Release( GetSkin()->GetRender() );
|
||||
}
|
||||
|
||||
virtual void SetUV( float u1, float v1, float u2, float v2 )
|
||||
{
|
||||
m_uv[0] = u1;
|
||||
m_uv[1] = v1;
|
||||
m_uv[2] = u2;
|
||||
m_uv[3] = v2;
|
||||
}
|
||||
|
||||
virtual void SetImage( const TextObject& imageName )
|
||||
{
|
||||
m_Texture.Load( imageName, GetSkin()->GetRender() );
|
||||
}
|
||||
|
||||
virtual void SetImage( const Texture& texture )
|
||||
{
|
||||
m_Texture = texture;
|
||||
}
|
||||
|
||||
virtual TextObject& GetImage()
|
||||
{
|
||||
return m_Texture.name;
|
||||
}
|
||||
|
||||
virtual int TextureWidth()
|
||||
{
|
||||
return m_Texture.width;
|
||||
}
|
||||
|
||||
virtual int TextureHeight()
|
||||
{
|
||||
return m_Texture.height;
|
||||
}
|
||||
|
||||
virtual const TextObject& GetImageName()
|
||||
{
|
||||
return m_Texture.name;
|
||||
}
|
||||
|
||||
virtual void Render( Skin::Base* skin )
|
||||
{
|
||||
skin->GetRender()->SetDrawColor( m_DrawColor );
|
||||
|
||||
if ( m_bStretch )
|
||||
skin->GetRender()->DrawTexturedRect( &m_Texture, GetRenderBounds(), m_uv[0], m_uv[1], m_uv[2], m_uv[3] );
|
||||
else
|
||||
skin->GetRender()->DrawTexturedRect( &m_Texture, Gwen::Rect( 0, 0, m_Texture.width, m_Texture.height ), m_uv[0], m_uv[1], m_uv[2], m_uv[3] );
|
||||
}
|
||||
|
||||
virtual void SizeToContents()
|
||||
{
|
||||
SetSize( m_Texture.width, m_Texture.height );
|
||||
}
|
||||
|
||||
virtual void SetDrawColor( Gwen::Color color )
|
||||
{
|
||||
m_DrawColor = color;
|
||||
}
|
||||
|
||||
virtual bool FailedToLoad()
|
||||
{
|
||||
return m_Texture.FailedToLoad();
|
||||
}
|
||||
|
||||
virtual bool GetStretch(){ return m_bStretch; }
|
||||
virtual void SetStretch( bool b ){ m_bStretch = b; }
|
||||
|
||||
protected:
|
||||
|
||||
Texture m_Texture;
|
||||
float m_uv[4];
|
||||
Gwen::Color m_DrawColor;
|
||||
|
||||
bool m_bStretch;
|
||||
|
||||
};
|
||||
}
|
||||
}
|
||||
#endif
|
115
lib/gwen/controls/gwen_label.cpp
Normal file
115
lib/gwen/controls/gwen_label.cpp
Normal file
|
@ -0,0 +1,115 @@
|
|||
/*
|
||||
GWEN
|
||||
Copyright (c) 2010 Facepunch Studios
|
||||
See license in Gwen.h
|
||||
*/
|
||||
|
||||
|
||||
#include "../gwen.h"
|
||||
#include "gwen_label.h"
|
||||
#include "../gwen_utility.h"
|
||||
|
||||
using namespace Gwen;
|
||||
using namespace Gwen::Controls;
|
||||
|
||||
GWEN_CONTROL_CONSTRUCTOR( Label )
|
||||
{
|
||||
m_CreatedFont = NULL;
|
||||
|
||||
m_Text = new ControlsInternal::Text( this );
|
||||
m_Text->SetFont( GetSkin()->GetDefaultFont() );
|
||||
|
||||
SetMouseInputEnabled( false );
|
||||
SetBounds( 0, 0, 100, 10 );
|
||||
SetAlignment( Gwen::Pos::Left | Gwen::Pos::Top );
|
||||
}
|
||||
|
||||
void Label::PreDelete( Gwen::Skin::Base* skin )
|
||||
{
|
||||
if ( m_CreatedFont )
|
||||
{
|
||||
skin->ReleaseFont( m_CreatedFont );
|
||||
delete m_CreatedFont;
|
||||
m_CreatedFont = NULL;
|
||||
SetFont( NULL );
|
||||
}
|
||||
}
|
||||
|
||||
void Label::PostLayout( Skin::Base* /*skin*/ )
|
||||
{
|
||||
m_Text->Position( m_iAlign );
|
||||
}
|
||||
|
||||
void Label::SetAlignment( int iAlign )
|
||||
{
|
||||
if ( m_iAlign == iAlign ) return;
|
||||
|
||||
m_iAlign = iAlign;
|
||||
Invalidate();
|
||||
}
|
||||
|
||||
int Label::GetAlignment()
|
||||
{
|
||||
return m_iAlign;
|
||||
}
|
||||
|
||||
void Label::SetText( const TextObject& str, bool bDoEvents )
|
||||
{
|
||||
if ( m_Text->GetText() == str.Get() ) return;
|
||||
|
||||
m_Text->SetString( str );
|
||||
Redraw();
|
||||
|
||||
if ( bDoEvents )
|
||||
OnTextChanged();
|
||||
}
|
||||
|
||||
void Label::SizeToContents()
|
||||
{
|
||||
m_Text->SetPos( m_Padding.left, m_Padding.top );
|
||||
m_Text->RefreshSize();
|
||||
|
||||
SetSize( m_Text->Width() + m_Padding.left + m_Padding.right, m_Text->Height() + m_Padding.top + m_Padding.bottom );
|
||||
}
|
||||
|
||||
Gwen::Rect Label::GetCharacterPosition( int iChar )
|
||||
{
|
||||
Gwen::Rect p = m_Text->GetCharacterPosition( iChar );
|
||||
p.x += m_Text->X();
|
||||
p.y += m_Text->Y();
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
void Label::OnBoundsChanged( Gwen::Rect oldChildBounds )
|
||||
{
|
||||
BaseClass::OnBoundsChanged( oldChildBounds );
|
||||
|
||||
if ( m_Text->Wrap() )
|
||||
{
|
||||
m_Text->RefreshSize();
|
||||
Invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
void Label::SetFont( Gwen::String strFacename, int iSize, bool bBold )
|
||||
{
|
||||
if ( m_CreatedFont )
|
||||
{
|
||||
GetSkin()->ReleaseFont( m_CreatedFont );
|
||||
delete m_CreatedFont;
|
||||
m_CreatedFont = NULL;
|
||||
SetFont( NULL );
|
||||
}
|
||||
|
||||
m_CreatedFont = new Gwen::Font();
|
||||
Debug::AssertCheck( m_CreatedFont != NULL, "Couldn't Create Font!" );
|
||||
|
||||
m_CreatedFont->bold = bBold;
|
||||
m_CreatedFont->facename = strFacename;
|
||||
m_CreatedFont->size = iSize;
|
||||
|
||||
SetFont( m_CreatedFont );
|
||||
|
||||
m_Text->RefreshSize();
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show more
Reference in a new issue