summaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
authorAndreas Baumann <abaumann@yahoo.com>2012-09-05 18:51:26 +0200
committerAndreas Baumann <abaumann@yahoo.com>2012-09-05 18:51:26 +0200
commitdf2c44401f8dd736a903e73813e5f83fb15b36b6 (patch)
treeb845f54b2dbb3f14dab435d2640c58b7b85e7975 /include
parent43aaf39cc828f4e1cec12a944560571993fb24f7 (diff)
downloadcrawler-df2c44401f8dd736a903e73813e5f83fb15b36b6.tar.gz
crawler-df2c44401f8dd736a903e73813e5f83fb15b36b6.tar.bz2
split away util, logger, and module
made a liblogger adapted all tests
Diffstat (limited to 'include')
-rwxr-xr-xinclude/logger/ConsoleLogSink.hpp14
-rwxr-xr-xinclude/logger/FileLogSink.hpp23
-rwxr-xr-xinclude/logger/LogSink.hpp23
-rwxr-xr-xinclude/logger/Logger.hpp73
-rwxr-xr-xinclude/logger/SyslogLogSink.hpp25
-rwxr-xr-xinclude/logger/WinDbgLogSink.hpp14
-rwxr-xr-xinclude/module/ModuleLoader.hpp262
-rwxr-xr-xinclude/module/ModuleRegistry.hpp190
-rw-r--r--include/util/Exportable.hpp21
-rwxr-xr-xinclude/util/NonCopyable.hpp24
-rw-r--r--include/util/Noreturn.hpp11
-rw-r--r--include/util/ScopedPtr.hpp33
-rwxr-xr-xinclude/util/Singleton.hpp65
-rw-r--r--include/util/TypeDetect.hpp15
-rwxr-xr-xinclude/util/TypeInfo.hpp82
-rw-r--r--include/util/TypeList.hpp28
-rw-r--r--include/util/TypeTraits.hpp9
17 files changed, 912 insertions, 0 deletions
diff --git a/include/logger/ConsoleLogSink.hpp b/include/logger/ConsoleLogSink.hpp
new file mode 100755
index 0000000..f700825
--- /dev/null
+++ b/include/logger/ConsoleLogSink.hpp
@@ -0,0 +1,14 @@
+#ifndef __CONSOLE_LOGSINK_H
+#define __CONSOLE_LOGSINK_H
+
+#include "LogSink.hpp"
+
+class ConsoleLogSink : public LogSink
+{
+ public:
+ ConsoleLogSink( const LogLevel level ) : LogSink( level ) { }
+
+ void log( const LogLevel level, const std::string &msg );
+};
+
+#endif
diff --git a/include/logger/FileLogSink.hpp b/include/logger/FileLogSink.hpp
new file mode 100755
index 0000000..f488a87
--- /dev/null
+++ b/include/logger/FileLogSink.hpp
@@ -0,0 +1,23 @@
+#ifndef __FILE_LOGSINK_H
+#define __FILE_LOGSINK_H
+
+#include "LogSink.hpp"
+
+#include <string>
+#include <fstream>
+
+class FileLogSink : public LogSink
+{
+ public:
+ FileLogSink( const LogLevel level, const std::string &filename );
+
+ ~FileLogSink( );
+
+ void log( const LogLevel level, const std::string &msg );
+
+ private:
+ std::string m_filename;
+ std::ofstream m_file;
+};
+
+#endif
diff --git a/include/logger/LogSink.hpp b/include/logger/LogSink.hpp
new file mode 100755
index 0000000..322e546
--- /dev/null
+++ b/include/logger/LogSink.hpp
@@ -0,0 +1,23 @@
+#ifndef __LOGSINK_H
+#define __LOGSINK_H
+
+#include "Logger.hpp"
+
+class LogSink
+{
+ public:
+ LogSink( const LogLevel level ) : m_level( level ) { }
+
+ virtual ~LogSink( ) { }
+
+ virtual void log( const LogLevel level, const std::string &msg ) = 0;
+
+ void setReportingLevel( const LogLevel level ) { m_level = level; }
+
+ LogLevel reportingLevel( ) { return m_level; }
+
+ private:
+ LogLevel m_level;
+};
+
+#endif
diff --git a/include/logger/Logger.hpp b/include/logger/Logger.hpp
new file mode 100755
index 0000000..dc514ae
--- /dev/null
+++ b/include/logger/Logger.hpp
@@ -0,0 +1,73 @@
+#ifndef __LOGGER_H
+#define __LOGGER_H
+
+#include "Singleton.hpp"
+#include "ScopedPtr.hpp"
+
+#include <sstream>
+
+enum LogLevel {
+ logNONE,
+ logFATAL,
+ logCRITICAL,
+ logERROR,
+ logWARNING,
+ logNOTICE,
+ logINFO,
+ logDEBUG,
+ logDEBUG1,
+ logDEBUG2,
+ logDEBUG3,
+ logDEBUG4
+};
+
+class LogSink;
+class LoggerImpl;
+
+class Logger : public Singleton< Logger >
+{
+ public:
+ DECLARE_SINGLETON( Logger )
+
+ void addSink( LogSink *sink );
+ void removeSink( LogSink *sink );
+ void log( const LogLevel level, const std::string &msg );
+
+ static std::string toString( const LogLevel level );
+ static LogLevel fromString( const std::string &s );
+
+ void openConsoleLog( const LogLevel level );
+ void openFileLog( const LogLevel level, const std::string &filename );
+ void openSyslog( const LogLevel level, const std::string &ident, const std::string &facility );
+ void openWinDbgLog( const LogLevel level );
+
+ protected:
+ Logger( );
+ virtual ~Logger( );
+
+ private:
+ scopedPtr< LoggerImpl > m_impl;
+};
+
+DEFINE_SINGLETON( Logger )
+
+class LogStream : private noncopyable, public std::ostringstream
+{
+ public:
+ LogStream( Logger &logger, const LogLevel level );
+ ~LogStream( );
+ std::ostream &get( );
+
+ private:
+ LogStream( );
+ LogStream( const LogStream & );
+ LogStream &operator=( const LogStream &);
+
+ private:
+ Logger &m_logger;
+ LogLevel m_level;
+};
+
+#define LOG( level ) LogStream( Logger::instance( ), level ).get( )
+
+#endif
diff --git a/include/logger/SyslogLogSink.hpp b/include/logger/SyslogLogSink.hpp
new file mode 100755
index 0000000..64e52f1
--- /dev/null
+++ b/include/logger/SyslogLogSink.hpp
@@ -0,0 +1,25 @@
+#ifndef __SYSLOG_LOGSINK_H
+#define __SYSLOG_LOGSINK_H
+
+#include "LogSink.hpp"
+
+#include <string>
+
+class SyslogLogSink : public LogSink
+{
+ public:
+ SyslogLogSink( const LogLevel level, const std::string &ident, const std::string &facility );
+
+ ~SyslogLogSink( );
+
+ void log( const LogLevel level, const std::string &msg );
+
+ static int levelToSyslogLevel( const LogLevel level );
+ static int facilityFromString( const std::string &facility );
+
+ private:
+ std::string m_ident;
+ std::string m_facility;
+};
+
+#endif
diff --git a/include/logger/WinDbgLogSink.hpp b/include/logger/WinDbgLogSink.hpp
new file mode 100755
index 0000000..f7caa86
--- /dev/null
+++ b/include/logger/WinDbgLogSink.hpp
@@ -0,0 +1,14 @@
+#ifndef __WINDBG_LOGSINK_H
+#define __WINDBG_LOGSINK_H
+
+#include "LogSink.hpp"
+
+class WinDbgLogSink : public LogSink
+{
+ public:
+ WinDbgLogSink( const LogLevel level ) : LogSink( level ) { }
+
+ void log( const LogLevel level, const std::string &msg );
+};
+
+#endif
diff --git a/include/module/ModuleLoader.hpp b/include/module/ModuleLoader.hpp
new file mode 100755
index 0000000..a5416bb
--- /dev/null
+++ b/include/module/ModuleLoader.hpp
@@ -0,0 +1,262 @@
+#ifndef __MODULELOADER_H
+#define __MODULELOADER_H
+
+#include <vector>
+#include <map>
+#include <string>
+#include <stdexcept>
+#include <typeinfo>
+#include <sstream>
+
+#ifndef _WIN32
+#include <dlfcn.h>
+#else
+#define WIN32_MEAN_AND_LEAN
+#include <windows.h>
+#include "win32/errormsg.hpp"
+#endif
+
+#include "ModuleRegistry.hpp"
+
+#include "TypeList.hpp"
+#include "TypeInfo.hpp"
+
+template< typename Interface, typename CtorParams = NullType >
+struct Module {
+#ifndef _WIN32
+ void *handle;
+#else
+ HMODULE handle;
+#endif
+ ModuleRegistry< Interface, CtorParams > *registry;
+};
+
+template< typename Interface, typename CtorParams = NullType >
+class BaseModuleLoader {
+
+ public:
+
+ typedef typename std::map<std::string, Module< Interface, CtorParams > > mapType;
+
+ protected:
+
+ mapType m_modules;
+
+ public:
+
+ BaseModuleLoader( const std::vector<std::string> files )
+ {
+ Module< Interface, CtorParams> m;
+
+ for( std::vector<std::string>::const_iterator it = files.begin( ); it != files.end( ); it++ ) {
+#ifndef _WIN32
+ m.handle = dlopen( it->c_str( ), RTLD_NOW );
+#else
+ m.handle = LoadLibrary( it->c_str( ) );
+#endif
+ if( !m.handle ) {
+#ifndef _WIN32
+ throw std::runtime_error( dlerror( ) );
+#else
+ std::ostringstream ss;
+ ss << "Module '" << *it << "' loading error: " << getLastError( );
+ throw std::runtime_error( ss.str( ) );
+#endif
+ }
+
+ std::string registryName = "registry_" + demangle( typeid( Interface ) );
+
+#ifndef _WIN32
+ m.registry = static_cast< ModuleRegistry< Interface, CtorParams > *>( dlsym( m.handle, registryName.c_str( ) ) );
+#else
+ m.registry = ( ModuleRegistry< Interface, CtorParams > *)( GetProcAddress( m.handle, registryName.c_str( ) ) );
+#endif
+ if( !m.registry ) {
+#ifndef _WIN32
+ dlclose( m.handle );
+#else
+ (void)FreeLibrary( m.handle );
+#endif
+ throw std::runtime_error( "missing module registry" );
+ }
+
+ m_modules.insert( std::make_pair( m.registry->name, m ) );
+ }
+ }
+
+ virtual ~BaseModuleLoader< Interface, CtorParams >( )
+ {
+ for( typename mapType::iterator it = m_modules.begin( ); it != m_modules.end( ); it++ ) {
+ if( (*it).second.handle ) {
+#ifndef _WIN32
+ dlclose( (*it).second.handle );
+#else
+ (void)FreeLibrary( (*it).second.handle );
+#endif
+ (*it).second.handle = 0;
+ }
+ }
+ }
+
+ void destroy( Interface *obj )
+ {
+ std::string clazz = demangle( typeid( *obj ) );
+
+ typename mapType::const_iterator it = m_modules.find( clazz );
+ if( it == m_modules.end( ) ) {
+ throw std::runtime_error( "calling unknown destructor" );
+ }
+
+ (*it).second.registry->destroy( obj );
+ }
+};
+
+template< typename Interface, typename CtorParams = NullType >
+class ModuleLoader;
+
+// no param
+
+template< typename Interface >
+class ModuleLoader< Interface, NullType > : public BaseModuleLoader< Interface, NullType >
+{
+ public:
+
+ ModuleLoader< Interface >( const std::vector<std::string> files )
+ : BaseModuleLoader< Interface >(files ) { }
+
+ Interface *create( std::string subclass )
+ {
+ typename BaseModuleLoader< Interface >::mapType::const_iterator it = BaseModuleLoader< Interface >::m_modules.find( subclass );
+ if( it == BaseModuleLoader< Interface >::m_modules.end( ) ) {
+ std::ostringstream ss;
+ ss << "calling unknown constructor for class '" << subclass << "'";
+ throw std::runtime_error( ss.str( ) );
+ }
+
+ Interface *obj = (*it).second.registry->create( );
+
+ std::string clazz = demangle( typeid( *obj ) );
+
+ BaseModuleLoader< Interface >::m_modules.insert( std::make_pair( clazz, (*it).second ) );
+
+ return obj;
+ }
+};
+
+// one param
+
+template< typename Interface, typename T1 >
+class ModuleLoader< Interface, TYPELIST_1( T1 ) > : public BaseModuleLoader< Interface, TYPELIST_1( T1 ) >
+{
+ public:
+
+ ModuleLoader< Interface, TYPELIST_1( T1 ) >( const std::vector<std::string> files )
+ : BaseModuleLoader< Interface, TYPELIST_1( T1 ) >( files ) { }
+
+ Interface *create( std::string subclass, T1 t1 )
+ {
+ typename BaseModuleLoader< Interface, TYPELIST_1( T1 ) >::mapType::const_iterator it = BaseModuleLoader< Interface, TYPELIST_1( T1 ) >::m_modules.find( subclass );
+ if( it == BaseModuleLoader< Interface, TYPELIST_1( T1 ) >::m_modules.end( ) ) {
+ std::ostringstream ss;
+ ss << "calling unknown constructor for class '" << subclass << "'";
+ throw std::runtime_error( ss.str( ) );
+ }
+
+ Interface *obj = (*it).second.registry->create( t1 );
+
+ std::string clazz = demangle( typeid( *obj ) );
+
+ BaseModuleLoader< Interface, TYPELIST_1( T1 ) >::m_modules.insert( std::make_pair( clazz, (*it).second ) );
+
+ return obj;
+ }
+};
+
+// two params
+
+template< typename Interface, typename T1, typename T2 >
+class ModuleLoader< Interface, TYPELIST_2( T1, T2 ) > : public BaseModuleLoader< Interface, TYPELIST_2( T1, T2 ) >
+{
+ public:
+
+ ModuleLoader< Interface, TYPELIST_2( T1, T2 ) >( const std::vector<std::string> files )
+ : BaseModuleLoader< Interface, TYPELIST_2( T1, T2 ) >( files ) { }
+
+ Interface *create( std::string subclass, T1 t1, T2 t2 )
+ {
+ typename BaseModuleLoader< Interface, TYPELIST_2( T1, T2 ) >::mapType::const_iterator it = BaseModuleLoader< Interface, TYPELIST_2( T1, T2 ) >::m_modules.find( subclass );
+ if( it == BaseModuleLoader< Interface, TYPELIST_2( T1, T2 ) >::m_modules.end( ) ) {
+ std::ostringstream ss;
+ ss << "calling unknown constructor for class '" << subclass << "'";
+ throw std::runtime_error( ss.str( ) );
+ }
+
+ Interface *obj = (*it).second.registry->create( t1, t2 );
+
+ std::string clazz = demangle( typeid( *obj ) );
+
+ BaseModuleLoader< Interface, TYPELIST_2( T1, T2 ) >::m_modules.insert( std::make_pair( clazz, (*it).second ) );
+
+ return obj;
+ }
+};
+
+// three params
+
+template< typename Interface, typename T1, typename T2, typename T3 >
+class ModuleLoader< Interface, TYPELIST_3( T1, T2, T3 ) > : public BaseModuleLoader< Interface, TYPELIST_3( T1, T2, T3 ) >
+{
+ public:
+
+ ModuleLoader< Interface, TYPELIST_3( T1, T2, T3 ) >( const std::vector<std::string> files )
+ : BaseModuleLoader< Interface, TYPELIST_3( T1, T2, T3 ) >( files ) { }
+
+ Interface *create( std::string subclass, T1 t1, T2 t2, T3 t3 )
+ {
+ typename BaseModuleLoader< Interface, TYPELIST_3( T1, T2, T3 ) >::mapType::const_iterator it = BaseModuleLoader< Interface, TYPELIST_3( T1, T2, T3 ) >::m_modules.find( subclass );
+ if( it == BaseModuleLoader< Interface, TYPELIST_3( T1, T2, T3 ) >::m_modules.end( ) ) {
+ std::ostringstream ss;
+ ss << "calling unknown constructor for class '" << subclass << "'";
+ throw std::runtime_error( ss.str( ) );
+ }
+
+ Interface *obj = (*it).second.registry->create( t1, t2, t3 );
+
+ std::string clazz = demangle( typeid( *obj ) );
+
+ BaseModuleLoader< Interface, TYPELIST_3( T1, T2, T3 ) >::m_modules.insert( std::make_pair( clazz, (*it).second ) );
+
+ return obj;
+ }
+};
+
+// four params
+
+template< typename Interface, typename T1, typename T2, typename T3, typename T4 >
+class ModuleLoader< Interface, TYPELIST_4( T1, T2, T3, T4 ) > : public BaseModuleLoader< Interface, TYPELIST_4( T1, T2, T3, T4 ) >
+{
+ public:
+
+ ModuleLoader< Interface, TYPELIST_4( T1, T2, T3, T4 ) >( const std::vector<std::string> files )
+ : BaseModuleLoader< Interface, TYPELIST_4( T1, T2, T3, T4 ) >( files ) { }
+
+ Interface *create( std::string subclass, T1 t1, T2 t2, T3 t3, T4 t4 )
+ {
+ typename BaseModuleLoader< Interface, TYPELIST_4( T1, T2, T3, T4 ) >::mapType::const_iterator it = BaseModuleLoader< Interface, TYPELIST_4( T1, T2, T3, T4 ) >::m_modules.find( subclass );
+ if( it == BaseModuleLoader< Interface, TYPELIST_4( T1, T2, T3, T4 ) >::m_modules.end( ) ) {
+ std::ostringstream ss;
+ ss << "calling unknown constructor for class '" << subclass << "'";
+ throw std::runtime_error( ss.str( ) );
+ }
+
+ Interface *obj = (*it).second.registry->create( t1, t2, t3, t4 );
+
+ std::string clazz = demangle( typeid( *obj ) );
+
+ BaseModuleLoader< Interface, TYPELIST_4( T1, T2, T3, T4 ) >::m_modules.insert( std::make_pair( clazz, (*it).second ) );
+
+ return obj;
+ }
+};
+
+#endif
diff --git a/include/module/ModuleRegistry.hpp b/include/module/ModuleRegistry.hpp
new file mode 100755
index 0000000..e217092
--- /dev/null
+++ b/include/module/ModuleRegistry.hpp
@@ -0,0 +1,190 @@
+#ifndef __MODULEINTERFACE_H
+#define __MODULEINTERFACE_H
+
+#include <string>
+
+#include "TypeList.hpp"
+
+template< typename Interface, typename CtorParams = NullType >
+struct ModuleRegistry;
+
+template< typename Interface>
+struct ModuleRegistry< Interface > {
+ std::string name;
+ Interface *(*create)( );
+ void (*destroy)( Interface *obj );
+
+ ModuleRegistry( std::string _name, Interface *(*_create)( ),
+ void (*_destroy)( Interface *obj ) )
+ : name( _name ), create( _create ), destroy( _destroy )
+ {
+ }
+};
+
+template< typename Interface, typename P1 >
+struct ModuleRegistry< Interface, TYPELIST_1( P1 ) > {
+ std::string name;
+ Interface *(*create)( P1 );
+ void (*destroy)( Interface *obj );
+
+ ModuleRegistry( std::string _name, Interface *(*_create)( P1 ),
+ void (*_destroy)( Interface *obj ) )
+ : name( _name ), create( _create ), destroy( _destroy )
+ {
+ }
+};
+
+template< typename Interface, typename P1, typename P2 >
+struct ModuleRegistry< Interface, TYPELIST_2( P1, P2 ) > {
+ std::string name;
+ Interface *(*create)( P1, P2 );
+ void (*destroy)( Interface *obj );
+
+ ModuleRegistry( std::string _name, Interface *(*_create)( P1, P2 ),
+ void (*_destroy)( Interface *obj ) )
+ : name( _name ), create( _create ), destroy( _destroy )
+ {
+ }
+};
+
+template< typename Interface, typename P1, typename P2, typename P3 >
+struct ModuleRegistry< Interface, TYPELIST_3( P1, P2, P3 ) > {
+ std::string name;
+ Interface *(*create)( P1, P2, P3 );
+ void (*destroy)( Interface *obj );
+
+ ModuleRegistry( std::string _name, Interface *(*_create)( P1, P2, P3 ),
+ void (*_destroy)( Interface *obj ) )
+ : name( _name ), create( _create ), destroy( _destroy )
+ {
+ }
+};
+
+template< typename Interface, typename P1, typename P2, typename P3, typename P4 >
+struct ModuleRegistry< Interface, TYPELIST_4( P1, P2, P3, P4 ) > {
+ std::string name;
+ Interface *(*create)( P1, P2, P3, P4 );
+ void (*destroy)( Interface *obj );
+
+ ModuleRegistry( std::string _name, Interface *(*_create)( P1, P2, P3, P4 ),
+ void (*_destroy)( Interface *obj ) )
+ : name( _name ), create( _create ), destroy( _destroy )
+ {
+ }
+};
+
+#ifdef SHARED
+
+#ifndef _WIN32
+#define DLLEXPORT
+#else
+#define DLLEXPORT __declspec( dllexport )
+#endif
+
+// no param macro
+
+#define DECLARE_MODULE( baseClass ) \
+ extern "C" DLLEXPORT ModuleRegistry<baseClass> registry ## _ ## baseClass;
+
+#define REGISTER_MODULE( name, baseClass, subClass ) \
+static baseClass *create( ) \
+{ \
+ return new subClass( ); \
+} \
+ \
+static void destroy( baseClass *obj ) \
+{ \
+ delete obj; \
+} \
+ \
+ModuleRegistry<baseClass> registry ## _ ## baseClass( name, &create, &destroy );
+
+// 1 param macro
+
+#define DECLARE_MODULE_1( baseClass, T1 ) \
+ extern "C" DLLEXPORT ModuleRegistry<baseClass, TYPELIST_1( T1 ) > registry ## _ ## baseClass;
+
+#define REGISTER_MODULE_1( name, baseClass, subClass, T1 ) \
+static baseClass *create( T1 t1 ) \
+{ \
+ return new subClass( t1 ); \
+} \
+ \
+static void destroy( baseClass *obj ) \
+{ \
+ delete obj; \
+} \
+ \
+ModuleRegistry<baseClass, TYPELIST_1( T1 )> registry ## _ ## baseClass( name, &create, &destroy );
+
+// 2 param macro
+
+#define DECLARE_MODULE_2( baseClass, T1, T2 ) \
+ extern "C" DLLEXPORT ModuleRegistry<baseClass, TYPELIST_2( T1, T2 ) > registry ## _ ## baseClass;
+
+#define REGISTER_MODULE_2( name, baseClass, subClass, T1, T2 ) \
+static baseClass *create( T1 t1, T2 t2 ) \
+{ \
+ return new subClass( t1, t2 ); \
+} \
+ \
+static void destroy( baseClass *obj ) \
+{ \
+ delete obj; \
+} \
+ \
+ModuleRegistry<baseClass, TYPELIST_2( T1, T2 )> registry ## _ ## baseClass( name, &create, &destroy );
+
+// 3 param macro
+
+#define DECLARE_MODULE_3( baseClass, T1, T2, T3 ) \
+ extern "C" DLLEXPORT ModuleRegistry<baseClass, TYPELIST_3( T1, T2, T3 ) > registry ## _ ## baseClass;
+
+#define REGISTER_MODULE_3( name, baseClass, subClass, T1, T2, T3 ) \
+static baseClass *create( T1 t1, T2 t2, T3 t3 ) \
+{ \
+ return new subClass( t1, t2, t3 ); \
+} \
+ \
+static void destroy( baseClass *obj ) \
+{ \
+ delete obj; \
+} \
+ \
+ModuleRegistry<baseClass, TYPELIST_3( T1, T2, T3 )> registry ## _ ## baseClass( name, &create, &destroy );
+
+// 4 param macro
+
+#define DECLARE_MODULE_4( baseClass, T1, T2, T3, T4 ) \
+ extern "C" DLLEXPORT ModuleRegistry<baseClass, TYPELIST_4( T1, T2, T3, T4 ) > registry ## _ ## baseClass;
+
+#define REGISTER_MODULE_4( name, baseClass, subClass, T1, T2, T3, T4 ) \
+static baseClass *create( T1 t1, T2 t2, T3 t3, T4 t4 ) \
+{ \
+ return new subClass( t1, t2, t3, t4 ); \
+} \
+ \
+static void destroy( baseClass *obj ) \
+{ \
+ delete obj; \
+} \
+ \
+ModuleRegistry<baseClass, TYPELIST_4( T1, T2, T3, T4 )> registry ## _ ## baseClass( name, &create, &destroy );
+
+#else // SHARED
+
+#define DECLARE_MODULE( baseClass )
+#define DECLARE_MODULE_1( baseClass, T1 )
+#define DECLARE_MODULE_2( baseClass, T1, T2 )
+#define DECLARE_MODULE_3( baseClass, T1, T2, T3 )
+#define DECLARE_MODULE_4( baseClass, T1, T2, T3, T4 )
+
+#define REGISTER_MODULE( name, baseClass, subClass )
+#define REGISTER_MODULE_1( name, baseClass, subClass, T1 )
+#define REGISTER_MODULE_2( name, baseClass, subClass, T1, T2 )
+#define REGISTER_MODULE_3( name, baseClass, subClass, T1, T2, T3 )
+#define REGISTER_MODULE_4( name, baseClass, subClass, T1, T2, T3, T4 )
+
+#endif // SHARED
+
+#endif // __MODULEINTERFACE_H
diff --git a/include/util/Exportable.hpp b/include/util/Exportable.hpp
new file mode 100644
index 0000000..28ac7ff
--- /dev/null
+++ b/include/util/Exportable.hpp
@@ -0,0 +1,21 @@
+#ifndef __EXPORTABLE_H
+#define __EXPORTABLE_H
+
+#ifndef _WIN32
+
+#define SINGLETON_EXPORT
+#define SINGLETON_EXTERN
+
+#else
+
+#ifndef SHARED
+#define SINGLETON_EXPORT __declspec(dllexport)
+#define SINGLETON_EXTERN
+#else
+#define SINGLETON_EXPORT __declspec(dllimport)
+#define SINGLETON_EXTERN extern
+#endif
+
+#endif // _WIN32
+
+#endif
diff --git a/include/util/NonCopyable.hpp b/include/util/NonCopyable.hpp
new file mode 100755
index 0000000..44d1a93
--- /dev/null
+++ b/include/util/NonCopyable.hpp
@@ -0,0 +1,24 @@
+#ifndef __NONCOPYABLE_H
+#define __NONCOPYABLE_H
+
+#include "Exportable.hpp"
+
+namespace __dont_touch
+{
+
+class SINGLETON_EXPORT noncopyable
+{
+ protected:
+ noncopyable( ) { }
+ ~noncopyable( ) { }
+
+ private:
+ noncopyable( const noncopyable & );
+ const noncopyable & operator=( const noncopyable & );
+};
+
+}
+
+typedef __dont_touch::noncopyable noncopyable;
+
+#endif
diff --git a/include/util/Noreturn.hpp b/include/util/Noreturn.hpp
new file mode 100644
index 0000000..9f9862c
--- /dev/null
+++ b/include/util/Noreturn.hpp
@@ -0,0 +1,11 @@
+#ifndef __NORETURN_H_
+#define __NORETURN_H
+
+#ifdef __GNUC__
+#define CRAWLER_NORETURN __attribute__((noreturn))
+#else
+#define CRAWLER_NORETURN
+#endif
+
+#endif
+
diff --git a/include/util/ScopedPtr.hpp b/include/util/ScopedPtr.hpp
new file mode 100644
index 0000000..19a41d2
--- /dev/null
+++ b/include/util/ScopedPtr.hpp
@@ -0,0 +1,33 @@
+#ifndef __SCOPEDPTR_H
+#define __SCOPEDPTR_H
+
+#include "NonCopyable.hpp"
+
+template< typename T >
+class scopedPtr : private noncopyable
+{
+ public:
+ explicit scopedPtr( T *p = 0 ) : m_p( p ) { }
+
+ ~scopedPtr( ) { delete m_p; }
+
+ T& operator*( ) const { return *m_p; }
+ T* operator->( ) const { return m_p; }
+ T* get( ) const { return m_p; }
+
+ bool operator==( const T* p ) const { return m_p == p; }
+ bool operator!=( const T* p ) const { return m_p != p; }
+
+ void reset( T *p = 0 )
+ {
+ if( m_p != p ) {
+ delete m_p;
+ m_p = p;
+ }
+ }
+
+ private:
+ T *m_p;
+};
+
+#endif
diff --git a/include/util/Singleton.hpp b/include/util/Singleton.hpp
new file mode 100755
index 0000000..1bfb460
--- /dev/null
+++ b/include/util/Singleton.hpp
@@ -0,0 +1,65 @@
+#ifndef __SINGLETON_H
+#define __SINGLETON_H
+
+#include "ScopedPtr.hpp"
+#include "NonCopyable.hpp"
+#include "Exportable.hpp"
+#include "Noreturn.hpp"
+
+#include <cstdlib>
+#include <stdexcept>
+
+#define DECLARE_SINGLETON( T ) \
+ friend class scopedPtr< T >; \
+ friend class Singleton< T >;
+
+#define DEFINE_SINGLETON( T ) \
+ SINGLETON_EXTERN template class SINGLETON_EXPORT Singleton< T >;
+
+template< class T >
+class Singleton : private noncopyable
+{
+ public:
+ static T& instance( )
+ {
+ if( destroyed ) {
+ onDeadReference( );
+ }
+
+ if( t == 0 ) {
+ create( );
+ }
+
+ return *t;
+ }
+
+ protected:
+ Singleton( )
+ {
+ }
+
+ virtual ~Singleton( )
+ {
+ destroyed = true;
+ }
+
+ private:
+ static void create( )
+ {
+ t.reset( new T );
+ }
+
+ static void onDeadReference( ) CRAWLER_NORETURN
+ {
+ throw std::runtime_error( "singleton has already been destroyed!" );
+ }
+
+ static scopedPtr<T> t;
+ static bool destroyed;
+};
+
+template< class T > scopedPtr<T> Singleton<T>::t( 0 );
+template< class T > bool Singleton<T>::destroyed( false );
+
+#endif
+
diff --git a/include/util/TypeDetect.hpp b/include/util/TypeDetect.hpp
new file mode 100644
index 0000000..7db714b
--- /dev/null
+++ b/include/util/TypeDetect.hpp
@@ -0,0 +1,15 @@
+#ifndef __TYPE_DETECTION_H
+#define __TYPE_DETECTION_H
+
+#include "RewindInputStream.hpp"
+#include "MIMEType.hpp"
+
+class TypeDetect
+{
+ public:
+ virtual ~TypeDetect( ) { };
+
+ virtual MIMEType detect( RewindInputStream *s ) = 0;
+};
+
+#endif
diff --git a/include/util/TypeInfo.hpp b/include/util/TypeInfo.hpp
new file mode 100755
index 0000000..3ca4b57
--- /dev/null
+++ b/include/util/TypeInfo.hpp
@@ -0,0 +1,82 @@
+#ifndef __TYPEINFO_H
+#define __TYPEINFO_H
+
+#include <typeinfo>
+#include <string>
+#include <stdexcept>
+#include <cstdlib>
+
+#if defined( __GNUG__ ) && defined( __GLIBCXX__ )
+
+#include <cxxabi.h>
+
+std::string demangle( const std::type_info &info )
+{
+ enum { BUFLEN = 200 };
+ char *buf;
+ std::size_t buflen = BUFLEN;
+ int status;
+ char *res;
+
+ // pass a malloced buffer (required by cxa_demangle)
+ buf = (char *)malloc( BUFLEN );
+
+ // res may point to buf or be realloced depending on whether the
+ // demangling had enough space or not
+ res = __cxxabiv1::__cxa_demangle( info.name( ), buf, &buflen, &status );
+
+ // throw exception if this goes wrong, because we don't want to have
+ // have code reacting on failed demangling or wrong type information!
+ if( status != 0 || res == NULL ) {
+ throw std::runtime_error( "__cxa_demangle failed!" );
+ }
+
+ // construct string on stack and return it, free original buffer
+ std::string s( res );
+ free( res );
+
+ return s;
+}
+
+#else
+
+#ifdef _WIN32
+
+// TODO: maybe extract into a generic stringutils module
+void replaceAll( std::string &s, const std::string &from, const std::string &to )
+{
+ if( from.empty( ) ) {
+ return;
+ }
+
+ size_t pos = 0;
+ while( ( pos = s.find( from, pos ) ) != std::string::npos ) {
+ s.replace( pos, from.length( ), to );
+ pos += to.length( );
+ }
+}
+
+std::string demangle( const std::type_info &info )
+{
+ std::string name = info.name( );
+
+ // MSVC marks metatypes, nice, but gcc doesn't, falling
+ // back as we can't do the same for gcc
+ replaceAll( name, "class ", "" );
+ // TODO: much more to follow, this is currently just enough
+ // for the module registry structure with base class
+ // signature only
+
+ return name;
+}
+
+#else
+
+#error "type.name() demangling not implemented!"
+
+#endif // _WIN32
+
+
+#endif // defined( __GNUG__ ) && defined( __GLIBCXX__ )
+
+#endif // __TYPEINFO_H
diff --git a/include/util/TypeList.hpp b/include/util/TypeList.hpp
new file mode 100644
index 0000000..bc8c49b
--- /dev/null
+++ b/include/util/TypeList.hpp
@@ -0,0 +1,28 @@
+#ifndef __TYPELIST_H
+#define __TYPELIST_H
+
+class NullType {};
+
+template< class T, class U >
+struct TypeList {
+ typedef T Head;
+ typedef U Tail;
+};
+
+#define TYPELIST_1( T1 ) TypeList< T1, NullType >
+#define TYPELIST_2( T1, T2 ) TypeList< T1, TYPELIST_1( T2 ) >
+#define TYPELIST_3( T1, T2, T3 ) TypeList< T1, TYPELIST_2( T2, T3 ) >
+#define TYPELIST_4( T1, T2, T3, T4 ) TypeList< T1, TYPELIST_3( T2, T3, T4 ) >
+
+template< class T> struct Length;
+template< > struct Length< NullType >
+{
+ enum { value = 0 };
+};
+template< class T, class U >
+struct Length< TypeList< T, U > >
+{
+ enum { value = 1 + Length< U >::value };
+};
+
+#endif
diff --git a/include/util/TypeTraits.hpp b/include/util/TypeTraits.hpp
new file mode 100644
index 0000000..b01051e
--- /dev/null
+++ b/include/util/TypeTraits.hpp
@@ -0,0 +1,9 @@
+#ifndef __TYPETRAITS_H
+#define __TYPETRAITS_H
+
+template< typename T >
+class TypeTraits {
+ typedef typename
+};
+
+#endif