LUMIERA.clone/src/lib/meta/size-trait.hpp

173 lines
5.8 KiB
C++

/*
SIZE-TRAIT.hpp - helpers and definitions to deal with the size of some known types
Copyright (C) Lumiera.org
2011, Hermann Vosseler <Ichthyostega@web.de>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of
the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/** @file size-trait.hpp
** Metaprogramming definitions to deal with dependency on implementation size and layout.
** Sometimes we need to build our code based on very specific assumptions regarding the
** implementation data layout of library classes we rely on. Typically such happens when
** we're forced to work around limitations the library provider never intended to be relevant
** for any client. Which places us into the very unfortunate situation either to abandon some
** design concept we prefer to use for some other relevant reason, or to do something very
** evil and nasty (namely to rely on magic numbers, which may break silently when the
** library provider changes implementation).
**
** While this situation can not be solved in principle, at least we may concentrate all
** these nasty dependencies in a single location. Moreover, we can deal with this situation
** by constructing our _magic numbers_ at least in a systematic way, which allows us to
** intersperse static assertions to trigger an alarm when adjustments need to be made.
**
** \par typical example
** A prominent example is boost::format, which causes a lot of code size bloat when used
** liberally. For that reason, we built a front-end to encapsulate the boost implementation,
** so any typed flavour of any call needs to be instantiated only once per application.
** This allows us to use type safe formatting in error messages, but unfortunately forces
** us to rely on the precise size of the boost::format implementation.
*/
#ifndef LIB_META_SIZE_TRAIT_H
#define LIB_META_SIZE_TRAIT_H
#include <vector>
#include <string>
namespace lib {
namespace meta {
/**
* A collection of constants to describe the expected size
* of some known classes, without needing to include the
* respective headers. This is an optimisation to improve
* compilation times and/or reduce size of the generated
* object files in debug mode. To get those sizes computed
* in a fairly portable way, but without much overhead,
* we mimic the memory layout of "the real thing"
* with some reasonable simplifications:
* - the size of vectors doesn't really depend on the elements
* - our strings, streams and buffers use just simple chars
*
* \par Interface
* The purpose of this whole construction is to pull off
* some constants based on sizeof expressions:
* - the size of a string
* - the size of a vector
* - the size of a boost::format
*
* @warning this setup is quite fragile and directly relies
* on the implementation layout of the GNU STL and Boost.
* Whenever using this stuff, make sure to place an assertion
* somewhere down in the implementation level to check against
* the size of the real thing.
*/
class SizeTrait
{
//-------------------------------------mimicked-definitions--
typedef std::vector<size_t> Vector;
typedef std::vector<bool> BVector;
struct CompatAllocator
: std::allocator<char>
{ };
struct Locale
{
void* _M_impl;
};
template<class T>
struct Optional
{
bool m_initialized_;
T m_storage_;
};
enum IOS_Openmode
{
_S_app = 1L << 0,
_S_ate = 1L << 1,
_S_bin = 1L << 2,
_S_in = 1L << 3,
_S_out = 1L << 4,
_S_trunc = 1L << 5,
_S_ios_openmode_end = 1L << 16
};
struct BasicStringbuf
{
char * _M_in_beg;
char * _M_in_cur;
char * _M_in_end;
char * _M_out_beg;
char * _M_out_cur;
char * _M_out_end;
Locale _M_buf_locale;
virtual ~BasicStringbuf() { }
};
struct BasicAltstringbuf
: BasicStringbuf
{
char * putend_;
bool is_allocated_;
IOS_Openmode mode_;
CompatAllocator alloc_;
};
struct BoostFormat
{
Vector items_;
BVector bound_; // note: differs in size
int style_;
int cur_arg_;
int num_args_;
mutable bool dumped_;
std::string prefix_;
unsigned char exceptions;
BasicAltstringbuf buf_;
Optional<Locale> loc_;
};
//-------------------------------------mimicked-definitions--
public:/* ===== Interface: size constants ===== */
enum { ALIGNMENT = sizeof(size_t)
, STRING = sizeof(std::string)
, VECTOR = sizeof(Vector)
, BVECTOR = sizeof(BVector)
, BOOST_FORMAT = sizeof(BoostFormat)
};
};
}} // namespace lib::meta
#endif