From ec05778d5718a7912e506764d443a78d6a6179e3 Mon Sep 17 00:00:00 2001 From: Mike Buland Date: Mon, 5 Nov 2012 22:41:51 +0000 Subject: Converted tabs to spaces with tabconv. --- src/compat/win32.cpp | 134 +- src/compat/win32.h | 104 +- src/config.h | 6 +- src/experimental/blowfish.h | 874 +++++------ src/experimental/cache.h | 828 +++++----- src/experimental/cachecalc.h | 88 +- src/experimental/cachestore.h | 52 +- src/experimental/cachestorefiles.h | 358 ++--- src/experimental/cachestoremyriad.h | 270 ++-- src/experimental/cipher.h | 218 +-- src/experimental/ciphermodecbc.h | 86 +- src/experimental/ciphermodecfb.h | 84 +- src/experimental/ciphermodeecb.h | 44 +- src/experimental/ciphermodeofb.h | 90 +- src/experimental/dir.h | 16 +- src/experimental/fastcgi.cpp | 592 +++---- src/experimental/fastcgi.h | 224 +-- src/experimental/filesystem.h | 30 +- src/experimental/httpget.cpp | 48 +- src/experimental/httpget.h | 72 +- src/experimental/lexer.cpp | 16 +- src/experimental/lexer.h | 82 +- src/experimental/parser.cpp | 342 ++-- src/experimental/parser.h | 218 +-- src/experimental/regex.cpp | 94 +- src/experimental/regex.h | 46 +- src/experimental/regexengine.h | 260 +-- src/experimental/xmlreader.cpp | 250 +-- src/experimental/xmlreader.h | 76 +- src/extra/myriadfs.cpp | 500 +++--- src/stable/archival.cpp | 12 +- src/stable/archival.h | 66 +- src/stable/archive.cpp | 76 +- src/stable/archive.h | 216 +-- src/stable/archivebase.cpp | 120 +- src/stable/archivebase.h | 106 +- src/stable/array.h | 1382 ++++++++-------- src/stable/atom.h | 254 +-- src/stable/base64.cpp | 346 ++-- src/stable/base64.h | 82 +- src/stable/buffer.cpp | 250 +-- src/stable/buffer.h | 82 +- src/stable/bzip2.cpp | 344 ++-- src/stable/bzip2.h | 60 +- src/stable/client.cpp | 220 +-- src/stable/client.h | 224 +-- src/stable/clientlink.h | 14 +- src/stable/clientlinkfactory.h | 18 +- src/stable/condition.cpp | 28 +- src/stable/condition.h | 130 +- src/stable/conduit.cpp | 240 +-- src/stable/conduit.h | 80 +- src/stable/crypt.cpp | 38 +- src/stable/crypt.h | 4 +- src/stable/cryptohash.cpp | 26 +- src/stable/cryptohash.h | 28 +- src/stable/csvreader.cpp | 118 +- src/stable/csvreader.h | 52 +- src/stable/csvwriter.cpp | 76 +- src/stable/csvwriter.h | 52 +- src/stable/deflate.cpp | 380 ++--- src/stable/deflate.h | 82 +- src/stable/exceptionbase.cpp | 76 +- src/stable/exceptionbase.h | 304 ++-- src/stable/extratypes.h | 8 +- src/stable/file.cpp | 298 ++-- src/stable/file.h | 158 +- src/stable/filter.cpp | 40 +- src/stable/filter.h | 110 +- src/stable/fmt.h | 158 +- src/stable/formatter.cpp | 516 +++--- src/stable/formatter.h | 572 +++---- src/stable/formula.cpp | 2 +- src/stable/formula.h | 808 +++++----- src/stable/hash.cpp | 68 +- src/stable/hash.h | 2610 +++++++++++++++---------------- src/stable/heap.h | 1180 +++++++------- src/stable/hex.cpp | 70 +- src/stable/hex.h | 74 +- src/stable/list.h | 2032 ++++++++++++------------ src/stable/logger.cpp | 312 ++-- src/stable/logger.h | 154 +- src/stable/lzma.cpp | 368 ++--- src/stable/lzma.h | 80 +- src/stable/md5.cpp | 218 +-- src/stable/md5.h | 74 +- src/stable/membuf.cpp | 122 +- src/stable/membuf.h | 86 +- src/stable/minicron.cpp | 622 ++++---- src/stable/minicron.h | 630 ++++---- src/stable/multiserver.cpp | 20 +- src/stable/multiserver.h | 78 +- src/stable/mutex.cpp | 10 +- src/stable/mutex.h | 94 +- src/stable/mutexlocker.cpp | 10 +- src/stable/mutexlocker.h | 22 +- src/stable/myriad.cpp | 1130 ++++++------- src/stable/myriad.h | 426 ++--- src/stable/myriadstream.cpp | 344 ++-- src/stable/myriadstream.h | 86 +- src/stable/nullstream.cpp | 44 +- src/stable/nullstream.h | 92 +- src/stable/optparser.cpp | 732 ++++----- src/stable/optparser.h | 398 ++--- src/stable/pearsonhash.cpp | 50 +- src/stable/pearsonhash.h | 54 +- src/stable/plugger.h | 420 ++--- src/stable/process.cpp | 820 +++++----- src/stable/process.h | 284 ++-- src/stable/protocol.h | 30 +- src/stable/protocolhttp.cpp | 362 ++--- src/stable/protocolhttp.h | 146 +- src/stable/protocoltelnet.cpp | 942 +++++------ src/stable/protocoltelnet.h | 386 ++--- src/stable/queue.h | 42 +- src/stable/queuebuf.cpp | 316 ++-- src/stable/queuebuf.h | 90 +- src/stable/random.cpp | 18 +- src/stable/random.h | 88 +- src/stable/randombase.h | 36 +- src/stable/randombasic.cpp | 12 +- src/stable/randombasic.h | 20 +- src/stable/randomcmwc.cpp | 58 +- src/stable/randomcmwc.h | 20 +- src/stable/randomsystem.cpp | 40 +- src/stable/randomsystem.h | 34 +- src/stable/ringbuffer.h | 462 +++--- src/stable/server.cpp | 252 +-- src/stable/server.h | 138 +- src/stable/sha1.cpp | 282 ++-- src/stable/sha1.h | 70 +- src/stable/sharedcore.h | 340 ++-- src/stable/singleton.h | 98 +- src/stable/sio.cpp | 54 +- src/stable/sio.h | 18 +- src/stable/sptr.h | 422 ++--- src/stable/stack.h | 116 +- src/stable/staticmembuf.cpp | 62 +- src/stable/staticmembuf.h | 84 +- src/stable/stdstream.cpp | 32 +- src/stable/stdstream.h | 78 +- src/stable/stream.cpp | 48 +- src/stable/stream.h | 366 ++--- src/stable/streamstack.cpp | 134 +- src/stable/streamstack.h | 250 +-- src/stable/strfilter.h | 218 +-- src/stable/string.cpp | 1778 ++++++++++----------- src/stable/string.h | 2098 ++++++++++++------------- src/stable/substream.cpp | 88 +- src/stable/substream.h | 92 +- src/stable/synchroatom.h | 88 +- src/stable/synchrocounter.h | 58 +- src/stable/synchroheap.h | 262 ++-- src/stable/synchroqueue.h | 454 +++--- src/stable/tafcomment.cpp | 16 +- src/stable/tafcomment.h | 32 +- src/stable/tafgroup.cpp | 224 +-- src/stable/tafgroup.h | 92 +- src/stable/tafnode.cpp | 4 +- src/stable/tafnode.h | 42 +- src/stable/tafproperty.cpp | 16 +- src/stable/tafproperty.h | 32 +- src/stable/tafreader.cpp | 326 ++-- src/stable/tafreader.h | 56 +- src/stable/tafwriter.cpp | 112 +- src/stable/tafwriter.h | 52 +- src/stable/tcpserversocket.cpp | 278 ++-- src/stable/tcpserversocket.h | 66 +- src/stable/tcpsocket.cpp | 554 +++---- src/stable/tcpsocket.h | 200 +-- src/stable/thread.cpp | 36 +- src/stable/thread.h | 228 +-- src/stable/trace.cpp | 46 +- src/stable/trace.h | 310 ++-- src/stable/unitsuite.cpp | 394 ++--- src/stable/unitsuite.h | 230 +-- src/stable/util.cpp | 86 +- src/stable/util.h | 294 ++-- src/stable/variant.cpp | 92 +- src/stable/variant.h | 418 ++--- src/tests/base64.cpp | 126 +- src/tests/bigmyriad.cpp | 26 +- src/tests/blowfish.cpp | 118 +- src/tests/bnfcompile.cpp | 750 ++++----- src/tests/bzip2.cpp | 38 +- src/tests/deflate.cpp | 78 +- src/tests/lzma.cpp | 78 +- src/tests/myriadfs.cpp | 64 +- src/tests/optparser.cpp | 126 +- src/tests/parser.cpp | 576 +++---- src/tests/print.cpp | 28 +- src/tests/random.cpp | 62 +- src/tests/regex.cpp | 42 +- src/tests/settings.cpp | 12 +- src/tests/synchroqueue.cpp | 198 +-- src/tests/taf.cpp | 52 +- src/tests/threadid.cpp | 78 +- src/tests/utf.cpp | 112 +- src/tests/uuid.cpp | 8 +- src/tools/bin2cpp.cpp | 414 ++--- src/tools/mkunit.cpp | 962 ++++++------ src/tools/myriad.cpp | 438 +++--- src/tools/viewcsv.cpp | 868 +++++----- src/unit/archive.unit | 352 ++--- src/unit/array.unit | 174 +-- src/unit/base64.unit | 24 +- src/unit/blowfish.unit | 44 +- src/unit/buffer.unit | 22 +- src/unit/file.unit | 160 +- src/unit/hash.unit | 378 ++--- src/unit/list.unit | 264 ++-- src/unit/md5.unit | 124 +- src/unit/membuf.unit | 60 +- src/unit/myriad.unit | 678 ++++---- src/unit/queuebuf.unit | 154 +- src/unit/sha1.unit | 112 +- src/unit/string.unit | 1148 +++++++------- src/unit/substream.unit | 72 +- src/unit/taf.unit | 94 +- src/unit/variant.unit | 70 +- src/unit/xml.unit | 12 +- src/unstable/bitstring.cpp | 660 ++++---- src/unstable/bitstring.h | 412 ++--- src/unstable/fifo.cpp | 118 +- src/unstable/fifo.h | 80 +- src/unstable/itoserver.cpp | 312 ++-- src/unstable/itoserver.h | 224 +-- src/unstable/minimacro.cpp | 252 +-- src/unstable/minimacro.h | 212 +-- src/unstable/myriadfs.cpp | 1078 ++++++------- src/unstable/myriadfs.h | 368 ++--- src/unstable/newline.cpp | 66 +- src/unstable/newline.h | 42 +- src/unstable/settings.cpp | 44 +- src/unstable/settings.h | 46 +- src/unstable/settingsdriver.h | 32 +- src/unstable/settingsdriverini.cpp | 258 +-- src/unstable/settingsdriverini.h | 30 +- src/unstable/settingsdriverregistry.cpp | 116 +- src/unstable/settingsdriverregistry.h | 24 +- src/unstable/settingsdrivertaf.cpp | 148 +- src/unstable/settingsdrivertaf.h | 34 +- src/unstable/udpsocket.cpp | 216 +-- src/unstable/udpsocket.h | 92 +- src/unstable/url.cpp | 378 ++--- src/unstable/url.h | 114 +- src/unstable/utfstring.cpp | 842 +++++----- src/unstable/utfstring.h | 482 +++--- src/unstable/uuid.cpp | 150 +- src/unstable/uuid.h | 84 +- 250 files changed, 29800 insertions(+), 29800 deletions(-) (limited to 'src') diff --git a/src/compat/win32.cpp b/src/compat/win32.cpp index e1151b0..38b9ad7 100644 --- a/src/compat/win32.cpp +++ b/src/compat/win32.cpp @@ -10,7 +10,7 @@ #ifdef WIN32 #define deffunc( name ) \ - Bu::Winsock2::FNDEF_DYN_ ##name Bu::Winsock2::_fnptr_ ##name = NULL + Bu::Winsock2::FNDEF_DYN_ ##name Bu::Winsock2::_fnptr_ ##name = NULL char Bu::Winsock2::scode[32]; @@ -33,133 +33,133 @@ deffunc( getpeername ); deffunc( setsockopt ); deffunc( bind ); deffunc( listen ); -deffunc( accept ); +deffunc( accept ); deffunc( recv ); deffunc( send ); deffunc( __WSAFDIsSet ); // Safely get a function from the library #define getfunc( name ) \ - Bu::Winsock2::_fnptr_ ##name = (FNDEF_DYN_ ##name) \ - GetProcAddress( Ws2_32, #name ); \ - if( Bu::Winsock2::_fnptr_ ##name == NULL ) { \ - throw Bu::ExceptionBase("Error loading function " #name " from dll.");\ - } (void)0 + Bu::Winsock2::_fnptr_ ##name = (FNDEF_DYN_ ##name) \ + GetProcAddress( Ws2_32, #name ); \ + if( Bu::Winsock2::_fnptr_ ##name == NULL ) { \ + throw Bu::ExceptionBase("Error loading function " #name " from dll.");\ + } (void)0 Bu::Winsock2::Winsock2() { - Ws2_32 = LoadLibrary(TEXT("WS2_32.DLL")); - - getfunc( WSAStartup ); - getfunc( WSACleanup ); - getfunc( WSAGetLastError ); - getfunc( inet_ntoa ); - getfunc( inet_addr ); - getfunc( select ); - getfunc( socket ); - getfunc( shutdown ); - getfunc( ioctlsocket ); - getfunc( htons ); - getfunc( htonl ); - getfunc( gethostbyname ); - getfunc( freeaddrinfo ); - getfunc( getaddrinfo ); - getfunc( connect ); - getfunc( getpeername ); - getfunc( setsockopt ); - getfunc( bind ); - getfunc( listen ); - getfunc( accept ); - getfunc( recv ); - getfunc( send ); - getfunc( __WSAFDIsSet ); - - Bu::Winsock2::WSAStartup( MAKEWORD(2, 2), &wsaData ); + Ws2_32 = LoadLibrary(TEXT("WS2_32.DLL")); + + getfunc( WSAStartup ); + getfunc( WSACleanup ); + getfunc( WSAGetLastError ); + getfunc( inet_ntoa ); + getfunc( inet_addr ); + getfunc( select ); + getfunc( socket ); + getfunc( shutdown ); + getfunc( ioctlsocket ); + getfunc( htons ); + getfunc( htonl ); + getfunc( gethostbyname ); + getfunc( freeaddrinfo ); + getfunc( getaddrinfo ); + getfunc( connect ); + getfunc( getpeername ); + getfunc( setsockopt ); + getfunc( bind ); + getfunc( listen ); + getfunc( accept ); + getfunc( recv ); + getfunc( send ); + getfunc( __WSAFDIsSet ); + + Bu::Winsock2::WSAStartup( MAKEWORD(2, 2), &wsaData ); } Bu::Winsock2::~Winsock2() { - Bu::Winsock2::WSACleanup(); - FreeLibrary( Ws2_32 ); + Bu::Winsock2::WSACleanup(); + FreeLibrary( Ws2_32 ); } char *Bu::Winsock2::gai_strerror( int iCode ) { - sprintf( scode, "%d (%d)", iCode, Bu::Winsock2::WSAGetLastError() ); - return scode; + sprintf( scode, "%d (%d)", iCode, Bu::Winsock2::WSAGetLastError() ); + return scode; } int Bu::Winsock2::WSAStartup( WORD a, LPWSADATA b ) { - return (*Bu::Winsock2::_fnptr_WSAStartup)( a, b ); + return (*Bu::Winsock2::_fnptr_WSAStartup)( a, b ); } int Bu::Winsock2::WSACleanup( ) { - return (*Bu::Winsock2::_fnptr_WSACleanup)(); + return (*Bu::Winsock2::_fnptr_WSACleanup)(); } int Bu::Winsock2::WSAGetLastError( ) { - return (*Bu::Winsock2::_fnptr_WSAGetLastError)(); + return (*Bu::Winsock2::_fnptr_WSAGetLastError)(); } char * Bu::Winsock2::inet_ntoa( struct in_addr a ) { - return (*Bu::Winsock2::_fnptr_inet_ntoa)( a ); + return (*Bu::Winsock2::_fnptr_inet_ntoa)( a ); } unsigned long Bu::Winsock2::inet_addr( const char *s_in ) { - return (*Bu::Winsock2::_fnptr_inet_addr)( s_in ); + return (*Bu::Winsock2::_fnptr_inet_addr)( s_in ); } int Bu::Winsock2::select( int a, fd_set *b, fd_set *c, fd_set *d, - const struct timeval *e ) { - return (*Bu::Winsock2::_fnptr_select)( a, b, c, d, e ); + const struct timeval *e ) { + return (*Bu::Winsock2::_fnptr_select)( a, b, c, d, e ); } SOCKET Bu::Winsock2::socket( int domain, int type, int protocol ) { - return (*Bu::Winsock2::_fnptr_socket)( domain, type, protocol ); + return (*Bu::Winsock2::_fnptr_socket)( domain, type, protocol ); } int Bu::Winsock2::shutdown( SOCKET s, int how ) { - return (*Bu::Winsock2::_fnptr_shutdown)( s, how ); + return (*Bu::Winsock2::_fnptr_shutdown)( s, how ); } int Bu::Winsock2::ioctlsocket( SOCKET s, long cmd, u_long *argp ) { - return (*Bu::Winsock2::_fnptr_ioctlsocket)( s, cmd, argp ); + return (*Bu::Winsock2::_fnptr_ioctlsocket)( s, cmd, argp ); } u_short Bu::Winsock2::htons( u_short in ) { - return (*Bu::Winsock2::_fnptr_htons)( in ); + return (*Bu::Winsock2::_fnptr_htons)( in ); } u_long Bu::Winsock2::htonl( u_long in ) { - return (*Bu::Winsock2::_fnptr_htonl)( in ); + return (*Bu::Winsock2::_fnptr_htonl)( in ); } struct hostent * Bu::Winsock2::gethostbyname( const char *name ) { - return (*Bu::Winsock2::_fnptr_gethostbyname)( name ); + return (*Bu::Winsock2::_fnptr_gethostbyname)( name ); } void Bu::Winsock2::freeaddrinfo( struct addrinfo *ai ) { - return (*Bu::Winsock2::_fnptr_freeaddrinfo)( ai ); + return (*Bu::Winsock2::_fnptr_freeaddrinfo)( ai ); } int Bu::Winsock2::getaddrinfo( const char *a, const char *b, - const struct addrinfo *c, struct addrinfo **d ) { - return (*Bu::Winsock2::_fnptr_getaddrinfo)( a, b, c, d ); + const struct addrinfo *c, struct addrinfo **d ) { + return (*Bu::Winsock2::_fnptr_getaddrinfo)( a, b, c, d ); } int Bu::Winsock2::connect( SOCKET s, const struct sockaddr *a, int b ) { - return (*Bu::Winsock2::_fnptr_connect)( s, a, b ); + return (*Bu::Winsock2::_fnptr_connect)( s, a, b ); } int Bu::Winsock2::getpeername( SOCKET s, struct sockaddr *a, int *b ) { - return (*Bu::Winsock2::_fnptr_getpeername)( s, a, b); + return (*Bu::Winsock2::_fnptr_getpeername)( s, a, b); } int Bu::Winsock2::setsockopt( SOCKET s, int a, int b, - const char *c, int d ) { - return (*Bu::Winsock2::_fnptr_setsockopt)( s, a, b, c, d ); + const char *c, int d ) { + return (*Bu::Winsock2::_fnptr_setsockopt)( s, a, b, c, d ); } int Bu::Winsock2::bind( SOCKET s, const struct sockaddr *a, int b ) { - return (*Bu::Winsock2::_fnptr_bind)( s, a, b ); + return (*Bu::Winsock2::_fnptr_bind)( s, a, b ); } int Bu::Winsock2::listen( SOCKET s, int backlog ) { - return (*Bu::Winsock2::_fnptr_listen)( s, backlog ); + return (*Bu::Winsock2::_fnptr_listen)( s, backlog ); } -SOCKET Bu::Winsock2::accept( SOCKET s, struct sockaddr *a, int *b ) { - return (*Bu::Winsock2::_fnptr_accept)( s, a, b ); +SOCKET Bu::Winsock2::accept( SOCKET s, struct sockaddr *a, int *b ) { + return (*Bu::Winsock2::_fnptr_accept)( s, a, b ); } int Bu::Winsock2::recv( SOCKET s, char *buf, int len, int flags ) { - return (*Bu::Winsock2::_fnptr_recv)( s, buf, len, flags ); + return (*Bu::Winsock2::_fnptr_recv)( s, buf, len, flags ); } int Bu::Winsock2::send( SOCKET s, const char *buf, int len, int flags ) { - return (*Bu::Winsock2::_fnptr_send)( s, buf, len, flags ); + return (*Bu::Winsock2::_fnptr_send)( s, buf, len, flags ); } int Bu::Winsock2::__WSAFDIsSet( SOCKET s, fd_set *set ) { - return (*Bu::Winsock2::_fnptr___WSAFDIsSet)( s, set ); + return (*Bu::Winsock2::_fnptr___WSAFDIsSet)( s, set ); } Bu::String Bu::getLastWinError() @@ -177,11 +177,11 @@ Bu::String Bu::getLastWinError() (LPSTR) &lpMsgBuf, 0, NULL ); - Bu::String sRet( (char *)lpMsgBuf ); + Bu::String sRet( (char *)lpMsgBuf ); LocalFree(lpMsgBuf); - return sRet; + return sRet; } #endif diff --git a/src/compat/win32.h b/src/compat/win32.h index 7e44c13..0cc42b6 100644 --- a/src/compat/win32.h +++ b/src/compat/win32.h @@ -32,9 +32,9 @@ extern "C" #endif #define decltype( ret, name, ... ) \ - typedef ret (__cdecl *FNDEF_DYN_ ##name)( __VA_ARGS__ ); \ - static FNDEF_DYN_ ##name _fnptr_ ##name; \ - static ret name( __VA_ARGS__ ) + typedef ret (__cdecl *FNDEF_DYN_ ##name)( __VA_ARGS__ ); \ + static FNDEF_DYN_ ##name _fnptr_ ##name; \ + static ret name( __VA_ARGS__ ) __extension__ typedef int socklen_t; @@ -44,54 +44,54 @@ __extension__ typedef int socklen_t; namespace Bu { - class Winsock2 : public Bu::Singleton - { - friend class Bu::Singleton; - private: - Winsock2(); - virtual ~Winsock2(); - - WSADATA wsaData; - HINSTANCE Ws2_32; - - public: - // decltype( return type, function name<, optional parameters> ) - decltype( int, WSAStartup, WORD, LPWSADATA ); - decltype( int, WSACleanup ); - decltype( int, WSAGetLastError ); - decltype( char *, inet_ntoa, struct in_addr ); - decltype( unsigned long, inet_addr, const char *s_in ); - decltype( int, select, int nfds, fd_set *readfds, fd_set *writefds, - fd_set *exceptfds, const struct timeval *timeout ); - decltype( SOCKET, socket, int domain, int type, int protocol ); - decltype( int, shutdown, SOCKET s, int how ); - decltype( int, ioctlsocket, SOCKET s, long cmd, u_long *argp ); - decltype( u_short, htons, u_short in ); - decltype( u_long, htonl, u_long in ); - decltype( struct hostent *, gethostbyname, const char *name ); - decltype( void, freeaddrinfo, struct addrinfo *ai ); - decltype( int, getaddrinfo, const char *nodename, const char *servname, - const struct addrinfo *hints, struct addrinfo **res ); - decltype( int, connect, SOCKET s, const struct sockaddr *serv_addr, - int addrlen ); - decltype( int, getpeername, SOCKET s, struct sockaddr *name, - int *namelen ); - decltype( int, setsockopt, SOCKET s, int level, int optname, - const char *optval, int optlen ); - decltype( int, bind, SOCKET s, const struct sockaddr *my_addr, - int addrlen ); - decltype( int, listen, SOCKET s, int backlog ); - decltype( SOCKET, accept, SOCKET s, struct sockaddr *addr, - int *addrlen); - decltype( int, recv, SOCKET s, char *buf, int len, int flags ); - decltype( int, send, SOCKET s, const char *buf, int len, int flags ); - decltype( int, __WSAFDIsSet, SOCKET s, fd_set *set ); - - static char scode[32]; - static char *gai_strerror( int iCode ); - }; - - Bu::String getLastWinError(); + class Winsock2 : public Bu::Singleton + { + friend class Bu::Singleton; + private: + Winsock2(); + virtual ~Winsock2(); + + WSADATA wsaData; + HINSTANCE Ws2_32; + + public: + // decltype( return type, function name<, optional parameters> ) + decltype( int, WSAStartup, WORD, LPWSADATA ); + decltype( int, WSACleanup ); + decltype( int, WSAGetLastError ); + decltype( char *, inet_ntoa, struct in_addr ); + decltype( unsigned long, inet_addr, const char *s_in ); + decltype( int, select, int nfds, fd_set *readfds, fd_set *writefds, + fd_set *exceptfds, const struct timeval *timeout ); + decltype( SOCKET, socket, int domain, int type, int protocol ); + decltype( int, shutdown, SOCKET s, int how ); + decltype( int, ioctlsocket, SOCKET s, long cmd, u_long *argp ); + decltype( u_short, htons, u_short in ); + decltype( u_long, htonl, u_long in ); + decltype( struct hostent *, gethostbyname, const char *name ); + decltype( void, freeaddrinfo, struct addrinfo *ai ); + decltype( int, getaddrinfo, const char *nodename, const char *servname, + const struct addrinfo *hints, struct addrinfo **res ); + decltype( int, connect, SOCKET s, const struct sockaddr *serv_addr, + int addrlen ); + decltype( int, getpeername, SOCKET s, struct sockaddr *name, + int *namelen ); + decltype( int, setsockopt, SOCKET s, int level, int optname, + const char *optval, int optlen ); + decltype( int, bind, SOCKET s, const struct sockaddr *my_addr, + int addrlen ); + decltype( int, listen, SOCKET s, int backlog ); + decltype( SOCKET, accept, SOCKET s, struct sockaddr *addr, + int *addrlen); + decltype( int, recv, SOCKET s, char *buf, int len, int flags ); + decltype( int, send, SOCKET s, const char *buf, int len, int flags ); + decltype( int, __WSAFDIsSet, SOCKET s, fd_set *set ); + + static char scode[32]; + static char *gai_strerror( int iCode ); + }; + + Bu::String getLastWinError(); }; #ifdef FD_ISSET @@ -117,7 +117,7 @@ namespace Bu #define bu_setsockopt (*Bu::Winsock2::setsockopt) #define bu_bind (*Bu::Winsock2::bind) #define bu_listen (*Bu::Winsock2::listen) -#define bu_accept (*Bu::Winsock2::accept) +#define bu_accept (*Bu::Winsock2::accept) #define bu_recv (*Bu::Winsock2::recv) #define bu_send (*Bu::Winsock2::send) #define bu___WSAFDIsSet (*Bu::Winsock2::__WSAFDIsSet) diff --git a/src/config.h b/src/config.h index fa304bb..c73906b 100644 --- a/src/config.h +++ b/src/config.h @@ -20,9 +20,9 @@ #ifndef WIN32 # include "bu/autoconfig.h" #else -# define __LITTLE_ENDIAN 1234 -# define __BIG_ENDIAN 4321 -# define __PDP_ENDIAN 3412 +# define __LITTLE_ENDIAN 1234 +# define __BIG_ENDIAN 4321 +# define __PDP_ENDIAN 3412 # define __BYTE_ORDER __LITTLE_ENDIAN # ifndef LITTLE_ENDIAN diff --git a/src/experimental/blowfish.h b/src/experimental/blowfish.h index 0308026..b287bd4 100644 --- a/src/experimental/blowfish.h +++ b/src/experimental/blowfish.h @@ -23,454 +23,454 @@ #define MAX_STRING 256 #define MAX_PASSWD 56 // 448bits #define F(x) \ - (((SB[0][x.byte.zero] + SB[1][x.byte.one]) ^ SB[2][x.byte.two]) + \ - SB[3][x.byte.three]) + (((SB[0][x.byte.zero] + SB[1][x.byte.one]) ^ SB[2][x.byte.two]) + \ + SB[3][x.byte.three]) #define revBytes( x ) x = (((x&0xff)<<24)|((x&0xff00)<<8)|((x&0xff0000)>>8)|((x&0xff000000)>>24)) namespace Bu { - template - class Blowfish : public Bu::Cipher<8> - { - public: - Blowfish( Bu::Stream &rNext ) : - Bu::Cipher<8>( rNext ) - { - } - - virtual ~Blowfish() - { - stop(); - reset(); - } - - void setPassword( const Bu::String &sPass ) - { - reset(); - - uint32_t i,j,len=sPass.getSize(); - Word Work,null0,null1; - - if (len > 0) - { - j = 0; - for (i=0;i + class Blowfish : public Bu::Cipher<8> + { + public: + Blowfish( Bu::Stream &rNext ) : + Bu::Cipher<8>( rNext ) + { + } + + virtual ~Blowfish() + { + stop(); + reset(); + } + + void setPassword( const Bu::String &sPass ) + { + reset(); + + uint32_t i,j,len=sPass.getSize(); + Word Work,null0,null1; + + if (len > 0) + { + j = 0; + for (i=0;iword0, &w2 = dwWork->word1; - - w1.word = be32toh( w1.word ); - w2.word = be32toh( w2.word ); - - keyEncipher( w1, w2 ); - - revBytes( w1.word ); - revBytes( w2.word ); - } - - virtual void decipher( void *pData ) - { - DWord *dwWork = (DWord *)pData; - Word &w1 = dwWork->word0, &w2 = dwWork->word1; - - revBytes( w1.word ); - revBytes( w2.word ); - - w1.word ^= PA[17]; - w2.word ^= F(w1)^PA[16]; w1.word ^= F(w2)^PA[15]; - w2.word ^= F(w1)^PA[14]; w1.word ^= F(w2)^PA[13]; - w2.word ^= F(w1)^PA[12]; w1.word ^= F(w2)^PA[11]; - w2.word ^= F(w1)^PA[10]; w1.word ^= F(w2)^PA[9]; - w2.word ^= F(w1)^PA[8]; w1.word ^= F(w2)^PA[7]; - w2.word ^= F(w1)^PA[6]; w1.word ^= F(w2)^PA[5]; - w2.word ^= F(w1)^PA[4]; w1.word ^= F(w2)^PA[3]; - w2.word ^= F(w1)^PA[2]; w1.word ^= F(w2)^PA[1]; - w2.word ^= PA[0]; - - Bu::swap( w1, w2 ); - - w1.word = htobe32( w1.word ); - w2.word = htobe32( w2.word ); - } - - inline void keyEncipher( Word &w1, Word &w2 ) - { - w1.word ^= PA[0]; - w2.word ^= F(w1)^PA[1]; w1.word ^= F(w2)^PA[2]; - w2.word ^= F(w1)^PA[3]; w1.word ^= F(w2)^PA[4]; - w2.word ^= F(w1)^PA[5]; w1.word ^= F(w2)^PA[6]; - w2.word ^= F(w1)^PA[7]; w1.word ^= F(w2)^PA[8]; - w2.word ^= F(w1)^PA[9]; w1.word ^= F(w2)^PA[10]; - w2.word ^= F(w1)^PA[11]; w1.word ^= F(w2)^PA[12]; - w2.word ^= F(w1)^PA[13]; w1.word ^= F(w2)^PA[14]; - w2.word ^= F(w1)^PA[15]; w1.word ^= F(w2)^PA[16]; - w2.word ^= PA[17]; - - Bu::swap( w1, w2 ); - } - }; - - typedef CipherModeEcb<8, Blowfish<1> > BlowfishEcb; - typedef CipherModeCfb<8, Blowfish<1> > BlowfishCfb; - typedef CipherModeCbc<8, Blowfish<1> > BlowfishCbc; - typedef CipherModeOfb<8, Blowfish<1> > BlowfishOfb; + union Word + { + uint32_t word; + WordByte byte; + }; + + struct DWord + { + Word word0; + Word word1; + }; + + void reset() + { + uint32_t i,j; + + static uint32_t PA_Init[NUM_SUBKEYS] = + { + 0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344, + 0xa4093822, 0x299f31d0, 0x082efa98, 0xec4e6c89, + 0x452821e6, 0x38d01377, 0xbe5466cf, 0x34e90c6c, + 0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5, 0xb5470917, + 0x9216d5d9, 0x8979fb1b + }; + + static uint32_t SB_Init[NUM_S_BOXES][NUM_ENTRIES] = { + { + 0xd1310ba6, 0x98dfb5ac, 0x2ffd72db, 0xd01adfb7, + 0xb8e1afed, 0x6a267e96, 0xba7c9045, 0xf12c7f99, + 0x24a19947, 0xb3916cf7, 0x0801f2e2, 0x858efc16, + 0x636920d8, 0x71574e69, 0xa458fea3, 0xf4933d7e, + 0x0d95748f, 0x728eb658, 0x718bcd58, 0x82154aee, + 0x7b54a41d, 0xc25a59b5, 0x9c30d539, 0x2af26013, + 0xc5d1b023, 0x286085f0, 0xca417918, 0xb8db38ef, + 0x8e79dcb0, 0x603a180e, 0x6c9e0e8b, 0xb01e8a3e, + 0xd71577c1, 0xbd314b27, 0x78af2fda, 0x55605c60, + 0xe65525f3, 0xaa55ab94, 0x57489862, 0x63e81440, + 0x55ca396a, 0x2aab10b6, 0xb4cc5c34, 0x1141e8ce, + 0xa15486af, 0x7c72e993, 0xb3ee1411, 0x636fbc2a, + 0x2ba9c55d, 0x741831f6, 0xce5c3e16, 0x9b87931e, + 0xafd6ba33, 0x6c24cf5c, 0x7a325381, 0x28958677, + 0x3b8f4898, 0x6b4bb9af, 0xc4bfe81b, 0x66282193, + 0x61d809cc, 0xfb21a991, 0x487cac60, 0x5dec8032, + 0xef845d5d, 0xe98575b1, 0xdc262302, 0xeb651b88, + 0x23893e81, 0xd396acc5, 0x0f6d6ff3, 0x83f44239, + 0x2e0b4482, 0xa4842004, 0x69c8f04a, 0x9e1f9b5e, + 0x21c66842, 0xf6e96c9a, 0x670c9c61, 0xabd388f0, + 0x6a51a0d2, 0xd8542f68, 0x960fa728, 0xab5133a3, + 0x6eef0b6c, 0x137a3be4, 0xba3bf050, 0x7efb2a98, + 0xa1f1651d, 0x39af0176, 0x66ca593e, 0x82430e88, + 0x8cee8619, 0x456f9fb4, 0x7d84a5c3, 0x3b8b5ebe, + 0xe06f75d8, 0x85c12073, 0x401a449f, 0x56c16aa6, + 0x4ed3aa62, 0x363f7706, 0x1bfedf72, 0x429b023d, + 0x37d0d724, 0xd00a1248, 0xdb0fead3, 0x49f1c09b, + 0x075372c9, 0x80991b7b, 0x25d479d8, 0xf6e8def7, + 0xe3fe501a, 0xb6794c3b, 0x976ce0bd, 0x04c006ba, + 0xc1a94fb6, 0x409f60c4, 0x5e5c9ec2, 0x196a2463, + 0x68fb6faf, 0x3e6c53b5, 0x1339b2eb, 0x3b52ec6f, + 0x6dfc511f, 0x9b30952c, 0xcc814544, 0xaf5ebd09, + + 0xbee3d004, 0xde334afd, 0x660f2807, 0x192e4bb3, + 0xc0cba857, 0x45c8740f, 0xd20b5f39, 0xb9d3fbdb, + 0x5579c0bd, 0x1a60320a, 0xd6a100c6, 0x402c7279, + 0x679f25fe, 0xfb1fa3cc, 0x8ea5e9f8, 0xdb3222f8, + 0x3c7516df, 0xfd616b15, 0x2f501ec8, 0xad0552ab, + 0x323db5fa, 0xfd238760, 0x53317b48, 0x3e00df82, + 0x9e5c57bb, 0xca6f8ca0, 0x1a87562e, 0xdf1769db, + 0xd542a8f6, 0x287effc3, 0xac6732c6, 0x8c4f5573, + 0x695b27b0, 0xbbca58c8, 0xe1ffa35d, 0xb8f011a0, + 0x10fa3d98, 0xfd2183b8, 0x4afcb56c, 0x2dd1d35b, + 0x9a53e479, 0xb6f84565, 0xd28e49bc, 0x4bfb9790, + 0xe1ddf2da, 0xa4cb7e33, 0x62fb1341, 0xcee4c6e8, + 0xef20cada, 0x36774c01, 0xd07e9efe, 0x2bf11fb4, + 0x95dbda4d, 0xae909198, 0xeaad8e71, 0x6b93d5a0, + 0xd08ed1d0, 0xafc725e0, 0x8e3c5b2f, 0x8e7594b7, + 0x8ff6e2fb, 0xf2122b64, 0x8888b812, 0x900df01c, + 0x4fad5ea0, 0x688fc31c, 0xd1cff191, 0xb3a8c1ad, + 0x2f2f2218, 0xbe0e1777, 0xea752dfe, 0x8b021fa1, + 0xe5a0cc0f, 0xb56f74e8, 0x18acf3d6, 0xce89e299, + 0xb4a84fe0, 0xfd13e0b7, 0x7cc43b81, 0xd2ada8d9, + 0x165fa266, 0x80957705, 0x93cc7314, 0x211a1477, + 0xe6ad2065, 0x77b5fa86, 0xc75442f5, 0xfb9d35cf, + 0xebcdaf0c, 0x7b3e89a0, 0xd6411bd3, 0xae1e7e49, + 0x00250e2d, 0x2071b35e, 0x226800bb, 0x57b8e0af, + 0x2464369b, 0xf009b91e, 0x5563911d, 0x59dfa6aa, + 0x78c14389, 0xd95a537f, 0x207d5ba2, 0x02e5b9c5, + 0x83260376, 0x6295cfa9, 0x11c81968, 0x4e734a41, + 0xb3472dca, 0x7b14a94a, 0x1b510052, 0x9a532915, + 0xd60f573f, 0xbc9bc6e4, 0x2b60a476, 0x81e67400, + 0x08ba6fb5, 0x571be91f, 0xf296ec6b, 0x2a0dd915, + 0xb6636521, 0xe7b9f9b6, 0xff34052e, 0xc5855664, + 0x53b02d5d, 0xa99f8fa1, 0x08ba4799, 0x6e85076a + }, { + 0x4b7a70e9, 0xb5b32944, 0xdb75092e, 0xc4192623, + 0xad6ea6b0, 0x49a7df7d, 0x9cee60b8, 0x8fedb266, + 0xecaa8c71, 0x699a17ff, 0x5664526c, 0xc2b19ee1, + 0x193602a5, 0x75094c29, 0xa0591340, 0xe4183a3e, + 0x3f54989a, 0x5b429d65, 0x6b8fe4d6, 0x99f73fd6, + 0xa1d29c07, 0xefe830f5, 0x4d2d38e6, 0xf0255dc1, + 0x4cdd2086, 0x8470eb26, 0x6382e9c6, 0x021ecc5e, + 0x09686b3f, 0x3ebaefc9, 0x3c971814, 0x6b6a70a1, + 0x687f3584, 0x52a0e286, 0xb79c5305, 0xaa500737, + 0x3e07841c, 0x7fdeae5c, 0x8e7d44ec, 0x5716f2b8, + 0xb03ada37, 0xf0500c0d, 0xf01c1f04, 0x0200b3ff, + 0xae0cf51a, 0x3cb574b2, 0x25837a58, 0xdc0921bd, + 0xd19113f9, 0x7ca92ff6, 0x94324773, 0x22f54701, + 0x3ae5e581, 0x37c2dadc, 0xc8b57634, 0x9af3dda7, + 0xa9446146, 0x0fd0030e, 0xecc8c73e, 0xa4751e41, + 0xe238cd99, 0x3bea0e2f, 0x3280bba1, 0x183eb331, + 0x4e548b38, 0x4f6db908, 0x6f420d03, 0xf60a04bf, + 0x2cb81290, 0x24977c79, 0x5679b072, 0xbcaf89af, + 0xde9a771f, 0xd9930810, 0xb38bae12, 0xdccf3f2e, + 0x5512721f, 0x2e6b7124, 0x501adde6, 0x9f84cd87, + 0x7a584718, 0x7408da17, 0xbc9f9abc, 0xe94b7d8c, + 0xec7aec3a, 0xdb851dfa, 0x63094366, 0xc464c3d2, + 0xef1c1847, 0x3215d908, 0xdd433b37, 0x24c2ba16, + 0x12a14d43, 0x2a65c451, 0x50940002, 0x133ae4dd, + 0x71dff89e, 0x10314e55, 0x81ac77d6, 0x5f11199b, + 0x043556f1, 0xd7a3c76b, 0x3c11183b, 0x5924a509, + 0xf28fe6ed, 0x97f1fbfa, 0x9ebabf2c, 0x1e153c6e, + 0x86e34570, 0xeae96fb1, 0x860e5e0a, 0x5a3e2ab3, + 0x771fe71c, 0x4e3d06fa, 0x2965dcb9, 0x99e71d0f, + 0x803e89d6, 0x5266c825, 0x2e4cc978, 0x9c10b36a, + 0xc6150eba, 0x94e2ea78, 0xa5fc3c53, 0x1e0a2df4, + 0xf2f74ea7, 0x361d2b3d, 0x1939260f, 0x19c27960, + + 0x5223a708, 0xf71312b6, 0xebadfe6e, 0xeac31f66, + 0xe3bc4595, 0xa67bc883, 0xb17f37d1, 0x018cff28, + 0xc332ddef, 0xbe6c5aa5, 0x65582185, 0x68ab9802, + 0xeecea50f, 0xdb2f953b, 0x2aef7dad, 0x5b6e2f84, + 0x1521b628, 0x29076170, 0xecdd4775, 0x619f1510, + 0x13cca830, 0xeb61bd96, 0x0334fe1e, 0xaa0363cf, + 0xb5735c90, 0x4c70a239, 0xd59e9e0b, 0xcbaade14, + 0xeecc86bc, 0x60622ca7, 0x9cab5cab, 0xb2f3846e, + 0x648b1eaf, 0x19bdf0ca, 0xa02369b9, 0x655abb50, + 0x40685a32, 0x3c2ab4b3, 0x319ee9d5, 0xc021b8f7, + 0x9b540b19, 0x875fa099, 0x95f7997e, 0x623d7da8, + 0xf837889a, 0x97e32d77, 0x11ed935f, 0x16681281, + 0x0e358829, 0xc7e61fd6, 0x96dedfa1, 0x7858ba99, + 0x57f584a5, 0x1b227263, 0x9b83c3ff, 0x1ac24696, + 0xcdb30aeb, 0x532e3054, 0x8fd948e4, 0x6dbc3128, + 0x58ebf2ef, 0x34c6ffea, 0xfe28ed61, 0xee7c3c73, + 0x5d4a14d9, 0xe864b7e3, 0x42105d14, 0x203e13e0, + 0x45eee2b6, 0xa3aaabea, 0xdb6c4f15, 0xfacb4fd0, + 0xc742f442, 0xef6abbb5, 0x654f3b1d, 0x41cd2105, + 0xd81e799e, 0x86854dc7, 0xe44b476a, 0x3d816250, + 0xcf62a1f2, 0x5b8d2646, 0xfc8883a0, 0xc1c7b6a3, + 0x7f1524c3, 0x69cb7492, 0x47848a0b, 0x5692b285, + 0x095bbf00, 0xad19489d, 0x1462b174, 0x23820e00, + 0x58428d2a, 0x0c55f5ea, 0x1dadf43e, 0x233f7061, + 0x3372f092, 0x8d937e41, 0xd65fecf1, 0x6c223bdb, + 0x7cde3759, 0xcbee7460, 0x4085f2a7, 0xce77326e, + 0xa6078084, 0x19f8509e, 0xe8efd855, 0x61d99735, + 0xa969a7aa, 0xc50c06c2, 0x5a04abfc, 0x800bcadc, + 0x9e447a2e, 0xc3453484, 0xfdd56705, 0x0e1e9ec9, + 0xdb73dbd3, 0x105588cd, 0x675fda79, 0xe3674340, + 0xc5c43465, 0x713e38d8, 0x3d28f89e, 0xf16dff20, + 0x153e21e7, 0x8fb03d4a, 0xe6e39f2b, 0xdb83adf7 + }, { + 0xe93d5a68, 0x948140f7, 0xf64c261c, 0x94692934, + 0x411520f7, 0x7602d4f7, 0xbcf46b2e, 0xd4a20068, + 0xd4082471, 0x3320f46a, 0x43b7d4b7, 0x500061af, + 0x1e39f62e, 0x97244546, 0x14214f74, 0xbf8b8840, + 0x4d95fc1d, 0x96b591af, 0x70f4ddd3, 0x66a02f45, + 0xbfbc09ec, 0x03bd9785, 0x7fac6dd0, 0x31cb8504, + 0x96eb27b3, 0x55fd3941, 0xda2547e6, 0xabca0a9a, + 0x28507825, 0x530429f4, 0x0a2c86da, 0xe9b66dfb, + 0x68dc1462, 0xd7486900, 0x680ec0a4, 0x27a18dee, + 0x4f3ffea2, 0xe887ad8c, 0xb58ce006, 0x7af4d6b6, + 0xaace1e7c, 0xd3375fec, 0xce78a399, 0x406b2a42, + 0x20fe9e35, 0xd9f385b9, 0xee39d7ab, 0x3b124e8b, + 0x1dc9faf7, 0x4b6d1856, 0x26a36631, 0xeae397b2, + 0x3a6efa74, 0xdd5b4332, 0x6841e7f7, 0xca7820fb, + 0xfb0af54e, 0xd8feb397, 0x454056ac, 0xba489527, + 0x55533a3a, 0x20838d87, 0xfe6ba9b7, 0xd096954b, + 0x55a867bc, 0xa1159a58, 0xcca92963, 0x99e1db33, + 0xa62a4a56, 0x3f3125f9, 0x5ef47e1c, 0x9029317c, + 0xfdf8e802, 0x04272f70, 0x80bb155c, 0x05282ce3, + 0x95c11548, 0xe4c66d22, 0x48c1133f, 0xc70f86dc, + 0x07f9c9ee, 0x41041f0f, 0x404779a4, 0x5d886e17, + 0x325f51eb, 0xd59bc0d1, 0xf2bcc18f, 0x41113564, + 0x257b7834, 0x602a9c60, 0xdff8e8a3, 0x1f636c1b, + 0x0e12b4c2, 0x02e1329e, 0xaf664fd1, 0xcad18115, + 0x6b2395e0, 0x333e92e1, 0x3b240b62, 0xeebeb922, + 0x85b2a20e, 0xe6ba0d99, 0xde720c8c, 0x2da2f728, + 0xd0127845, 0x95b794fd, 0x647d0862, 0xe7ccf5f0, + 0x5449a36f, 0x877d48fa, 0xc39dfd27, 0xf33e8d1e, + 0x0a476341, 0x992eff74, 0x3a6f6eab, 0xf4f8fd37, + 0xa812dc60, 0xa1ebddf8, 0x991be14c, 0xdb6e6b0d, + 0xc67b5510, 0x6d672c37, 0x2765d43b, 0xdcd0e804, + 0xf1290dc7, 0xcc00ffa3, 0xb5390f92, 0x690fed0b, + + 0x667b9ffb, 0xcedb7d9c, 0xa091cf0b, 0xd9155ea3, + 0xbb132f88, 0x515bad24, 0x7b9479bf, 0x763bd6eb, + 0x37392eb3, 0xcc115979, 0x8026e297, 0xf42e312d, + 0x6842ada7, 0xc66a2b3b, 0x12754ccc, 0x782ef11c, + 0x6a124237, 0xb79251e7, 0x06a1bbe6, 0x4bfb6350, + 0x1a6b1018, 0x11caedfa, 0x3d25bdd8, 0xe2e1c3c9, + 0x44421659, 0x0a121386, 0xd90cec6e, 0xd5abea2a, + 0x64af674e, 0xda86a85f, 0xbebfe988, 0x64e4c3fe, + 0x9dbc8057, 0xf0f7c086, 0x60787bf8, 0x6003604d, + 0xd1fd8346, 0xf6381fb0, 0x7745ae04, 0xd736fccc, + 0x83426b33, 0xf01eab71, 0xb0804187, 0x3c005e5f, + 0x77a057be, 0xbde8ae24, 0x55464299, 0xbf582e61, + 0x4e58f48f, 0xf2ddfda2, 0xf474ef38, 0x8789bdc2, + 0x5366f9c3, 0xc8b38e74, 0xb475f255, 0x46fcd9b9, + 0x7aeb2661, 0x8b1ddf84, 0x846a0e79, 0x915f95e2, + 0x466e598e, 0x20b45770, 0x8cd55591, 0xc902de4c, + 0xb90bace1, 0xbb8205d0, 0x11a86248, 0x7574a99e, + 0xb77f19b6, 0xe0a9dc09, 0x662d09a1, 0xc4324633, + 0xe85a1f02, 0x09f0be8c, 0x4a99a025, 0x1d6efe10, + 0x1ab93d1d, 0x0ba5a4df, 0xa186f20f, 0x2868f169, + 0xdcb7da83, 0x573906fe, 0xa1e2ce9b, 0x4fcd7f52, + 0x50115e01, 0xa70683fa, 0xa002b5c4, 0x0de6d027, + 0x9af88c27, 0x773f8641, 0xc3604c06, 0x61a806b5, + 0xf0177a28, 0xc0f586e0, 0x006058aa, 0x30dc7d62, + 0x11e69ed7, 0x2338ea63, 0x53c2dd94, 0xc2c21634, + 0xbbcbee56, 0x90bcb6de, 0xebfc7da1, 0xce591d76, + 0x6f05e409, 0x4b7c0188, 0x39720a3d, 0x7c927c24, + 0x86e3725f, 0x724d9db9, 0x1ac15bb4, 0xd39eb8fc, + 0xed545578, 0x08fca5b5, 0xd83d7cd3, 0x4dad0fc4, + 0x1e50ef5e, 0xb161e6f8, 0xa28514d9, 0x6c51133c, + 0x6fd5c7e7, 0x56e14ec4, 0x362abfce, 0xddc6c837, + 0xd79a3234, 0x92638212, 0x670efa8e, 0x406000e0 + }, { + 0x3a39ce37, 0xd3faf5cf, 0xabc27737, 0x5ac52d1b, + 0x5cb0679e, 0x4fa33742, 0xd3822740, 0x99bc9bbe, + 0xd5118e9d, 0xbf0f7315, 0xd62d1c7e, 0xc700c47b, + 0xb78c1b6b, 0x21a19045, 0xb26eb1be, 0x6a366eb4, + 0x5748ab2f, 0xbc946e79, 0xc6a376d2, 0x6549c2c8, + 0x530ff8ee, 0x468dde7d, 0xd5730a1d, 0x4cd04dc6, + 0x2939bbdb, 0xa9ba4650, 0xac9526e8, 0xbe5ee304, + 0xa1fad5f0, 0x6a2d519a, 0x63ef8ce2, 0x9a86ee22, + 0xc089c2b8, 0x43242ef6, 0xa51e03aa, 0x9cf2d0a4, + 0x83c061ba, 0x9be96a4d, 0x8fe51550, 0xba645bd6, + 0x2826a2f9, 0xa73a3ae1, 0x4ba99586, 0xef5562e9, + 0xc72fefd3, 0xf752f7da, 0x3f046f69, 0x77fa0a59, + 0x80e4a915, 0x87b08601, 0x9b09e6ad, 0x3b3ee593, + 0xe990fd5a, 0x9e34d797, 0x2cf0b7d9, 0x022b8b51, + 0x96d5ac3a, 0x017da67d, 0xd1cf3ed6, 0x7c7d2d28, + 0x1f9f25cf, 0xadf2b89b, 0x5ad6b472, 0x5a88f54c, + 0xe029ac71, 0xe019a5e6, 0x47b0acfd, 0xed93fa9b, + 0xe8d3c48d, 0x283b57cc, 0xf8d56629, 0x79132e28, + 0x785f0191, 0xed756055, 0xf7960e44, 0xe3d35e8c, + 0x15056dd4, 0x88f46dba, 0x03a16125, 0x0564f0bd, + 0xc3eb9e15, 0x3c9057a2, 0x97271aec, 0xa93a072a, + 0x1b3f6d9b, 0x1e6321f5, 0xf59c66fb, 0x26dcf319, + 0x7533d928, 0xb155fdf5, 0x03563482, 0x8aba3cbb, + 0x28517711, 0xc20ad9f8, 0xabcc5167, 0xccad925f, + 0x4de81751, 0x3830dc8e, 0x379d5862, 0x9320f991, + 0xea7a90c2, 0xfb3e7bce, 0x5121ce64, 0x774fbe32, + 0xa8b6e37e, 0xc3293d46, 0x48de5369, 0x6413e680, + 0xa2ae0810, 0xdd6db224, 0x69852dfd, 0x09072166, + 0xb39a460a, 0x6445c0dd, 0x586cdecf, 0x1c20c8ae, + 0x5bbef7dd, 0x1b588d40, 0xccd2017f, 0x6bb4e3bb, + 0xdda26a7e, 0x3a59ff45, 0x3e350a44, 0xbcb4cdd5, + 0x72eacea8, 0xfa6484bb, 0x8d6612ae, 0xbf3c6f47, + + 0xd29be463, 0x542f5d9e, 0xaec2771b, 0xf64e6370, + 0x740e0d8d, 0xe75b1357, 0xf8721671, 0xaf537d5d, + 0x4040cb08, 0x4eb4e2cc, 0x34d2466a, 0x0115af84, + 0xe1b00428, 0x95983a1d, 0x06b89fb4, 0xce6ea048, + 0x6f3f3b82, 0x3520ab82, 0x011a1d4b, 0x277227f8, + 0x611560b1, 0xe7933fdc, 0xbb3a792b, 0x344525bd, + 0xa08839e1, 0x51ce794b, 0x2f32c9b7, 0xa01fbac9, + 0xe01cc87e, 0xbcc7d1f6, 0xcf0111c3, 0xa1e8aac7, + 0x1a908749, 0xd44fbd9a, 0xd0dadecb, 0xd50ada38, + 0x0339c32a, 0xc6913667, 0x8df9317c, 0xe0b12b4f, + 0xf79e59b7, 0x43f5bb3a, 0xf2d519ff, 0x27d9459c, + 0xbf97222c, 0x15e6fc2a, 0x0f91fc71, 0x9b941525, + 0xfae59361, 0xceb69ceb, 0xc2a86459, 0x12baa8d1, + 0xb6c1075e, 0xe3056a0c, 0x10d25065, 0xcb03a442, + 0xe0ec6e0e, 0x1698db3b, 0x4c98a0be, 0x3278e964, + 0x9f1f9532, 0xe0d392df, 0xd3a0342b, 0x8971f21e, + 0x1b0a7441, 0x4ba3348c, 0xc5be7120, 0xc37632d8, + 0xdf359f8d, 0x9b992f2e, 0xe60b6f47, 0x0fe3f11d, + 0xe54cda54, 0x1edad891, 0xce6279cf, 0xcd3e7e6f, + 0x1618b166, 0xfd2c1d05, 0x848fd2c5, 0xf6fb2299, + 0xf523f357, 0xa6327623, 0x93a83531, 0x56cccd02, + 0xacf08162, 0x5a75ebb5, 0x6e163697, 0x88d273cc, + 0xde966292, 0x81b949d0, 0x4c50901b, 0x71c65614, + 0xe6c6c7bd, 0x327a140a, 0x45e1d006, 0xc3f27b9a, + 0xc9aa53fd, 0x62a80f00, 0xbb25bfe2, 0x35bdd2f6, + 0x71126905, 0xb2040222, 0xb6cbcf7c, 0xcd769c2b, + 0x53113ec0, 0x1640e3d3, 0x38abbd60, 0x2547adf0, + 0xba38209c, 0xf746ce76, 0x77afa1c5, 0x20756060, + 0x85cbfe4e, 0x8ae88dd8, 0x7aaaf9b0, 0x4cf9aa7e, + 0x1948c25c, 0x02fb8a8c, 0x01c36ae4, 0xd6ebe1f9, + 0x90d4f869, 0xa65cdea0, 0x3f09252d, 0xc208e69f, + 0xb74e6132, 0xce77e25b, 0x578fdfe3, 0x3ac372e6 + } + }; + + for (i=0;iword0, &w2 = dwWork->word1; + + w1.word = be32toh( w1.word ); + w2.word = be32toh( w2.word ); + + keyEncipher( w1, w2 ); + + revBytes( w1.word ); + revBytes( w2.word ); + } + + virtual void decipher( void *pData ) + { + DWord *dwWork = (DWord *)pData; + Word &w1 = dwWork->word0, &w2 = dwWork->word1; + + revBytes( w1.word ); + revBytes( w2.word ); + + w1.word ^= PA[17]; + w2.word ^= F(w1)^PA[16]; w1.word ^= F(w2)^PA[15]; + w2.word ^= F(w1)^PA[14]; w1.word ^= F(w2)^PA[13]; + w2.word ^= F(w1)^PA[12]; w1.word ^= F(w2)^PA[11]; + w2.word ^= F(w1)^PA[10]; w1.word ^= F(w2)^PA[9]; + w2.word ^= F(w1)^PA[8]; w1.word ^= F(w2)^PA[7]; + w2.word ^= F(w1)^PA[6]; w1.word ^= F(w2)^PA[5]; + w2.word ^= F(w1)^PA[4]; w1.word ^= F(w2)^PA[3]; + w2.word ^= F(w1)^PA[2]; w1.word ^= F(w2)^PA[1]; + w2.word ^= PA[0]; + + Bu::swap( w1, w2 ); + + w1.word = htobe32( w1.word ); + w2.word = htobe32( w2.word ); + } + + inline void keyEncipher( Word &w1, Word &w2 ) + { + w1.word ^= PA[0]; + w2.word ^= F(w1)^PA[1]; w1.word ^= F(w2)^PA[2]; + w2.word ^= F(w1)^PA[3]; w1.word ^= F(w2)^PA[4]; + w2.word ^= F(w1)^PA[5]; w1.word ^= F(w2)^PA[6]; + w2.word ^= F(w1)^PA[7]; w1.word ^= F(w2)^PA[8]; + w2.word ^= F(w1)^PA[9]; w1.word ^= F(w2)^PA[10]; + w2.word ^= F(w1)^PA[11]; w1.word ^= F(w2)^PA[12]; + w2.word ^= F(w1)^PA[13]; w1.word ^= F(w2)^PA[14]; + w2.word ^= F(w1)^PA[15]; w1.word ^= F(w2)^PA[16]; + w2.word ^= PA[17]; + + Bu::swap( w1, w2 ); + } + }; + + typedef CipherModeEcb<8, Blowfish<1> > BlowfishEcb; + typedef CipherModeCfb<8, Blowfish<1> > BlowfishCfb; + typedef CipherModeCbc<8, Blowfish<1> > BlowfishCbc; + typedef CipherModeOfb<8, Blowfish<1> > BlowfishOfb; }; #endif diff --git a/src/experimental/cache.h b/src/experimental/cache.h index e3c8483..795d180 100644 --- a/src/experimental/cache.h +++ b/src/experimental/cache.h @@ -18,420 +18,420 @@ namespace Bu { -// template -// keytype __cacheGetKey( obtype *&pObj ); - template - keytype __cacheGetKey( const obtype *pObj ) - { - return pObj->getKey(); - } - - template - class Cache - { - public: - /** - * Cache Pointer - Provides access to data that is held within the - * cache. This provides safe, refcounting access to data stored in - * the cache, with support for lazy loading. - */ - class Ptr - { - friend class Bu::Cache; - private: - Ptr( Cache *pCache, obtype *pData, - const keytype &kId ) : - pCache( pCache ), - pData( pData ), - kId( kId ) - { - if( pCache ) - pCache->incRef( kId ); - } - - Ptr( Cache *pCache, const keytype &kId ) : - pCache( pCache ), - pData( NULL ), - kId( kId ) - { - } - - public: - Ptr( const Ptr &rSrc ) : - pCache( rSrc.pCache ), - pData( rSrc.pData ), - kId( rSrc.kId ) - { - if( pCache && pData ) - pCache->incRef( kId ); - } - - Ptr() : - pCache( 0 ), - pData( 0 ) - { - } - - virtual ~Ptr() - { - if( pCache && pData ) - pCache->decRef( kId ); - } - - obtype &operator*() - { - checkPtr(); - return *pData; - } - - const obtype &operator*() const - { - checkPtr(); - return *pData; - } - - obtype *operator->() - { - checkPtr(); - return pData; - } - - const obtype *operator->() const - { - checkPtr(); - return pData; - } - - bool isValid() const - { - return pCache != NULL; - } - - bool isBound() const - { - return pData != NULL; - } - - bool isSet() const - { - return pCache != NULL; - } - - const keytype &getKey() const - { - return kId; - } - - void unbind() - { - if( pCache && pData ) - pCache->decRef( kId ); - pData = NULL; - } - - void clear() - { - unbind(); - pCache = NULL; - } - - void unset() - { - clear(); - } - - Ptr &operator=( const Ptr &rRhs ) - { - if( pCache && pData ) - pCache->decRef( kId ); - pCache = rRhs.pCache; - pData = rRhs.pData; - kId = rRhs.kId; - if( pCache && pData ) - pCache->incRef( kId ); - return *this; - } - - bool operator==( const Ptr &rRhs ) const - { - return pCache == rRhs.pCache && kId == rRhs.kId; - } - - bool operator!=( const Ptr &rRhs ) const - { - return pCache != rRhs.pCache || kId != rRhs.kId; - } - - private: - void checkPtr() const - { - if( pCache && !pData ) - { - pData = pCache->getRaw( kId ); - pCache->incRef( kId ); - } - } - - private: - Bu::Cache *pCache; - mutable obtype *pData; - mutable keytype kId; - }; - - private: - typedef Bu::CacheStore Store; - typedef Bu::List StoreList; - typedef Bu::CacheCalc Calc; - - typedef struct CacheEntry - { - obtype *pData; - int iRefs; - time_t tLastSync; - } CacheEntry; - - typedef Bu::Hash CidHash; - - public: - typedef keytype Key; - Cache( Calc *pCalc, Store *pStore ) : - pCalc( pCalc ), - pStore( pStore ) - { - TRACE(); - pCalc->setCache( this ); - } - - virtual ~Cache() - { - TRACE(); - - // Better safe than sorry, better try a sync before anything - // else happens. - sync(); - - // Cycle through and unload all objects from the system. - for( typename CidHash::iterator i = hEnt.begin(); - i != hEnt.end(); i++ ) - { - if( i.getValue().iRefs > 0 ) - { - // TODO: Throw an error in this case? iRefs != 0 for an - // object when the Cache is destroyed. - throw Bu::ExceptionBase("iRefs not zero."); - } - pStore->unload( - i.getValue().pData, - i.getKey() - ); - } - delete pCalc; - delete pStore; - } - - Ptr insert( obtype *pData ) - { - TRACE( pData ); - if( pStore->has( __cacheGetKey( pData ) ) ) - throw Bu::ExceptionBase("Key already exists in cache."); - CacheEntry e = {pData, 0, 0}; - keytype k = pStore->create( pData ); - hEnt.insert( k, e ); - - pCalc->onLoad( pData, k ); - - pStore->sync(); - - return Ptr( this, pData, k ); - } - - bool has( const keytype &cId ) - { - return hEnt.has( cId ) || pStore->has( cId ); - } - - /** - * Retrieve an object from the cache and return a pointer to it. - * The object returned may be loaded from backend storage if needed, - * or the currently live object will be returned. - *@param cId The id of the object to load. - *@returns A pointer to the object. - */ - Ptr get( const keytype &cId ) - { - TRACE( cId ); - try { - return Ptr( this, hEnt.get( cId ).pData, cId ); - } - catch( Bu::HashException &e ) { - CacheEntry e = {pStore->load( cId ), 0, time( NULL )}; - pCalc->onLoad( e.pData, cId ); - hEnt.insert( cId, e ); - return Ptr( this, e.pData, cId ); - } - } - - /** - * Retrieve a handle to an object without loading it now. This function - * will return a pointer that has not yet been "realized" but can be - * used normally. Upon initial use in any way the object will be - * loaded from the cache, either linking against the already loaded - * object or loading it fresh from the backend storage. The advantage - * of this is that you recieve a usable handle to the data, but it - * does not count as a reference yet, meaning that the data is loaded - * when you need it, not before. - */ - Ptr getLazy( const keytype &cId ) - { - TRACE( cId ); - return Ptr( this, cId ); - } - - int getRefCount( const keytype &cId ) - { - TRACE( cId ); - return hEnt.get( cId ).iRefs; - } - - void unload( const keytype &cId ) - { - TRACE( cId ); - try { - if( hEnt.get( cId ).iRefs > 0 ) - { - printf("Shouldn't unload, references still exist!\n"); - return; - } - } - catch( Bu::HashException &e ) { - // It's not here? Eh, return. - return; - } - obtype *pObj = hEnt.get( cId ).pData; - pCalc->onUnload( pObj, cId ); - hEnt.erase( cId ); - - // The unload has to happen last just in case cId is a reference - // to data that is about to be deleted from memory by the unload. - pStore->unload( pObj, cId ); - } - - void erase( const keytype &cId ) - { - TRACE( cId ); - try { - if( hEnt.get( cId ).iRefs > 0 ) - { - printf("Shouldn't erase, references still exist!\n"); - return; - } - - obtype *pObj = hEnt.get( cId ).pData; - pCalc->onDestroy( pObj, cId ); - hEnt.erase( cId ); - - pStore->destroy( pObj, cId ); - pStore->sync(); - } - catch( Bu::HashException &e ) { - pCalc->onDestroy( cId ); - - if( hEnt.has( cId ) ) - { - // The object was loaded by onDestroy - erase( cId ); - } - else - { - pStore->destroy( cId ); - pStore->sync(); - } - } - } - - typedef Bu::List KeyList; - KeyList getKeys() - { - return pStore->getKeys(); - } - - KeyList getActiveKeys() - { - return hEnt.getKeys(); - } - - int getSize() - { - return pStore->getSize(); - } - - /** - * Make sure all currently loaded but not-in-use objects are synced to - * the store. - */ - void sync() - { - TRACE(); - int iSynced = 0; - for( typename CidHash::iterator i = hEnt.begin(); - i != hEnt.end(); i++ ) - { - if( i.getValue().iRefs == 0 ) - { - if( pCalc->shouldSync( - i.getValue().pData, - i.getKey(), - i.getValue().tLastSync - ) ) - { - pStore->sync( - i.getValue().pData, - i.getKey() - ); - iSynced++; - i.getValue().tLastSync = time( NULL ); - } - } - } - if( iSynced > 0 ) - { - pStore->sync(); - } - } - - private: - void incRef( const keytype &cId ) - { - TRACE( cId ); - hEnt.get( cId ).iRefs++; - } - - void decRef( const keytype &cId ) - { - TRACE( cId ); - CacheEntry &e = hEnt.get( cId ); - e.iRefs--; - } - - obtype *getRaw( const keytype &cId ) - { - TRACE( cId ); - try { - return hEnt.get( cId ).pData; - } - catch( Bu::HashException &e ) { - CacheEntry e = {pStore->load( cId ), 0, time( NULL )}; - pCalc->onLoad( e.pData, cId ); - hEnt.insert( cId, e ); - return e.pData; - } - } - - private: - CidHash hEnt; - Calc *pCalc; - Store *pStore; - }; +// template +// keytype __cacheGetKey( obtype *&pObj ); + template + keytype __cacheGetKey( const obtype *pObj ) + { + return pObj->getKey(); + } + + template + class Cache + { + public: + /** + * Cache Pointer - Provides access to data that is held within the + * cache. This provides safe, refcounting access to data stored in + * the cache, with support for lazy loading. + */ + class Ptr + { + friend class Bu::Cache; + private: + Ptr( Cache *pCache, obtype *pData, + const keytype &kId ) : + pCache( pCache ), + pData( pData ), + kId( kId ) + { + if( pCache ) + pCache->incRef( kId ); + } + + Ptr( Cache *pCache, const keytype &kId ) : + pCache( pCache ), + pData( NULL ), + kId( kId ) + { + } + + public: + Ptr( const Ptr &rSrc ) : + pCache( rSrc.pCache ), + pData( rSrc.pData ), + kId( rSrc.kId ) + { + if( pCache && pData ) + pCache->incRef( kId ); + } + + Ptr() : + pCache( 0 ), + pData( 0 ) + { + } + + virtual ~Ptr() + { + if( pCache && pData ) + pCache->decRef( kId ); + } + + obtype &operator*() + { + checkPtr(); + return *pData; + } + + const obtype &operator*() const + { + checkPtr(); + return *pData; + } + + obtype *operator->() + { + checkPtr(); + return pData; + } + + const obtype *operator->() const + { + checkPtr(); + return pData; + } + + bool isValid() const + { + return pCache != NULL; + } + + bool isBound() const + { + return pData != NULL; + } + + bool isSet() const + { + return pCache != NULL; + } + + const keytype &getKey() const + { + return kId; + } + + void unbind() + { + if( pCache && pData ) + pCache->decRef( kId ); + pData = NULL; + } + + void clear() + { + unbind(); + pCache = NULL; + } + + void unset() + { + clear(); + } + + Ptr &operator=( const Ptr &rRhs ) + { + if( pCache && pData ) + pCache->decRef( kId ); + pCache = rRhs.pCache; + pData = rRhs.pData; + kId = rRhs.kId; + if( pCache && pData ) + pCache->incRef( kId ); + return *this; + } + + bool operator==( const Ptr &rRhs ) const + { + return pCache == rRhs.pCache && kId == rRhs.kId; + } + + bool operator!=( const Ptr &rRhs ) const + { + return pCache != rRhs.pCache || kId != rRhs.kId; + } + + private: + void checkPtr() const + { + if( pCache && !pData ) + { + pData = pCache->getRaw( kId ); + pCache->incRef( kId ); + } + } + + private: + Bu::Cache *pCache; + mutable obtype *pData; + mutable keytype kId; + }; + + private: + typedef Bu::CacheStore Store; + typedef Bu::List StoreList; + typedef Bu::CacheCalc Calc; + + typedef struct CacheEntry + { + obtype *pData; + int iRefs; + time_t tLastSync; + } CacheEntry; + + typedef Bu::Hash CidHash; + + public: + typedef keytype Key; + Cache( Calc *pCalc, Store *pStore ) : + pCalc( pCalc ), + pStore( pStore ) + { + TRACE(); + pCalc->setCache( this ); + } + + virtual ~Cache() + { + TRACE(); + + // Better safe than sorry, better try a sync before anything + // else happens. + sync(); + + // Cycle through and unload all objects from the system. + for( typename CidHash::iterator i = hEnt.begin(); + i != hEnt.end(); i++ ) + { + if( i.getValue().iRefs > 0 ) + { + // TODO: Throw an error in this case? iRefs != 0 for an + // object when the Cache is destroyed. + throw Bu::ExceptionBase("iRefs not zero."); + } + pStore->unload( + i.getValue().pData, + i.getKey() + ); + } + delete pCalc; + delete pStore; + } + + Ptr insert( obtype *pData ) + { + TRACE( pData ); + if( pStore->has( __cacheGetKey( pData ) ) ) + throw Bu::ExceptionBase("Key already exists in cache."); + CacheEntry e = {pData, 0, 0}; + keytype k = pStore->create( pData ); + hEnt.insert( k, e ); + + pCalc->onLoad( pData, k ); + + pStore->sync(); + + return Ptr( this, pData, k ); + } + + bool has( const keytype &cId ) + { + return hEnt.has( cId ) || pStore->has( cId ); + } + + /** + * Retrieve an object from the cache and return a pointer to it. + * The object returned may be loaded from backend storage if needed, + * or the currently live object will be returned. + *@param cId The id of the object to load. + *@returns A pointer to the object. + */ + Ptr get( const keytype &cId ) + { + TRACE( cId ); + try { + return Ptr( this, hEnt.get( cId ).pData, cId ); + } + catch( Bu::HashException &e ) { + CacheEntry e = {pStore->load( cId ), 0, time( NULL )}; + pCalc->onLoad( e.pData, cId ); + hEnt.insert( cId, e ); + return Ptr( this, e.pData, cId ); + } + } + + /** + * Retrieve a handle to an object without loading it now. This function + * will return a pointer that has not yet been "realized" but can be + * used normally. Upon initial use in any way the object will be + * loaded from the cache, either linking against the already loaded + * object or loading it fresh from the backend storage. The advantage + * of this is that you recieve a usable handle to the data, but it + * does not count as a reference yet, meaning that the data is loaded + * when you need it, not before. + */ + Ptr getLazy( const keytype &cId ) + { + TRACE( cId ); + return Ptr( this, cId ); + } + + int getRefCount( const keytype &cId ) + { + TRACE( cId ); + return hEnt.get( cId ).iRefs; + } + + void unload( const keytype &cId ) + { + TRACE( cId ); + try { + if( hEnt.get( cId ).iRefs > 0 ) + { + printf("Shouldn't unload, references still exist!\n"); + return; + } + } + catch( Bu::HashException &e ) { + // It's not here? Eh, return. + return; + } + obtype *pObj = hEnt.get( cId ).pData; + pCalc->onUnload( pObj, cId ); + hEnt.erase( cId ); + + // The unload has to happen last just in case cId is a reference + // to data that is about to be deleted from memory by the unload. + pStore->unload( pObj, cId ); + } + + void erase( const keytype &cId ) + { + TRACE( cId ); + try { + if( hEnt.get( cId ).iRefs > 0 ) + { + printf("Shouldn't erase, references still exist!\n"); + return; + } + + obtype *pObj = hEnt.get( cId ).pData; + pCalc->onDestroy( pObj, cId ); + hEnt.erase( cId ); + + pStore->destroy( pObj, cId ); + pStore->sync(); + } + catch( Bu::HashException &e ) { + pCalc->onDestroy( cId ); + + if( hEnt.has( cId ) ) + { + // The object was loaded by onDestroy + erase( cId ); + } + else + { + pStore->destroy( cId ); + pStore->sync(); + } + } + } + + typedef Bu::List KeyList; + KeyList getKeys() + { + return pStore->getKeys(); + } + + KeyList getActiveKeys() + { + return hEnt.getKeys(); + } + + int getSize() + { + return pStore->getSize(); + } + + /** + * Make sure all currently loaded but not-in-use objects are synced to + * the store. + */ + void sync() + { + TRACE(); + int iSynced = 0; + for( typename CidHash::iterator i = hEnt.begin(); + i != hEnt.end(); i++ ) + { + if( i.getValue().iRefs == 0 ) + { + if( pCalc->shouldSync( + i.getValue().pData, + i.getKey(), + i.getValue().tLastSync + ) ) + { + pStore->sync( + i.getValue().pData, + i.getKey() + ); + iSynced++; + i.getValue().tLastSync = time( NULL ); + } + } + } + if( iSynced > 0 ) + { + pStore->sync(); + } + } + + private: + void incRef( const keytype &cId ) + { + TRACE( cId ); + hEnt.get( cId ).iRefs++; + } + + void decRef( const keytype &cId ) + { + TRACE( cId ); + CacheEntry &e = hEnt.get( cId ); + e.iRefs--; + } + + obtype *getRaw( const keytype &cId ) + { + TRACE( cId ); + try { + return hEnt.get( cId ).pData; + } + catch( Bu::HashException &e ) { + CacheEntry e = {pStore->load( cId ), 0, time( NULL )}; + pCalc->onLoad( e.pData, cId ); + hEnt.insert( cId, e ); + return e.pData; + } + } + + private: + CidHash hEnt; + Calc *pCalc; + Store *pStore; + }; }; #endif diff --git a/src/experimental/cachecalc.h b/src/experimental/cachecalc.h index ecfa3f4..cb5c755 100644 --- a/src/experimental/cachecalc.h +++ b/src/experimental/cachecalc.h @@ -14,50 +14,50 @@ namespace Bu { - template class Cache; - - template - class CacheCalc - { - friend class Cache; - private: - typedef Cache MyCache; - public: - CacheCalc() : - pCache( (MyCache *)0 ) - { - TRACE(); - } - - virtual ~CacheCalc() - { - TRACE(); - } - - virtual void onLoad( obtype *pSrc, const keytype &key )=0; - virtual void onUnload( obtype *pSrc, const keytype &key )=0; - virtual void onDestroy( obtype *pSrc, const keytype &key )=0; - virtual void onDestroy( const keytype &key )=0; - virtual bool shouldSync( obtype *pSrc, const keytype &key, - time_t tLastSync )=0; - virtual void onTick() { }; - - protected: - MyCache *getCache() - { - TRACE(); - return pCache; - } - - private: - void setCache( MyCache *pCache ) - { - TRACE(); - this->pCache = pCache; - } - - MyCache *pCache; - }; + template class Cache; + + template + class CacheCalc + { + friend class Cache; + private: + typedef Cache MyCache; + public: + CacheCalc() : + pCache( (MyCache *)0 ) + { + TRACE(); + } + + virtual ~CacheCalc() + { + TRACE(); + } + + virtual void onLoad( obtype *pSrc, const keytype &key )=0; + virtual void onUnload( obtype *pSrc, const keytype &key )=0; + virtual void onDestroy( obtype *pSrc, const keytype &key )=0; + virtual void onDestroy( const keytype &key )=0; + virtual bool shouldSync( obtype *pSrc, const keytype &key, + time_t tLastSync )=0; + virtual void onTick() { }; + + protected: + MyCache *getCache() + { + TRACE(); + return pCache; + } + + private: + void setCache( MyCache *pCache ) + { + TRACE(); + this->pCache = pCache; + } + + MyCache *pCache; + }; }; #endif diff --git a/src/experimental/cachestore.h b/src/experimental/cachestore.h index a332e49..5052670 100644 --- a/src/experimental/cachestore.h +++ b/src/experimental/cachestore.h @@ -12,35 +12,35 @@ namespace Bu { - /** - * Handles I/O for data in the cache. This also assigns ID's to the newly - * created objects that are requested through this system. - */ - template - class CacheStore - { - public: - CacheStore() - { - } + /** + * Handles I/O for data in the cache. This also assigns ID's to the newly + * created objects that are requested through this system. + */ + template + class CacheStore + { + public: + CacheStore() + { + } - virtual ~CacheStore() - { - } + virtual ~CacheStore() + { + } - virtual obtype *load( const keytype &key )=0; - virtual void unload( obtype *pObj, const keytype &key )=0; - virtual keytype create( obtype *pSrc )=0; - virtual void sync()=0; - virtual void sync( obtype *pObj, const keytype &key )=0; - virtual void destroy( obtype *pObj, const keytype &key )=0; - virtual void destroy( const keytype &key )=0; - virtual bool has( const keytype &key )=0; - virtual Bu::List getKeys() { return Bu::List(); } - virtual int getSize() { return -1; } + virtual obtype *load( const keytype &key )=0; + virtual void unload( obtype *pObj, const keytype &key )=0; + virtual keytype create( obtype *pSrc )=0; + virtual void sync()=0; + virtual void sync( obtype *pObj, const keytype &key )=0; + virtual void destroy( obtype *pObj, const keytype &key )=0; + virtual void destroy( const keytype &key )=0; + virtual bool has( const keytype &key )=0; + virtual Bu::List getKeys() { return Bu::List(); } + virtual int getSize() { return -1; } - private: - }; + private: + }; }; #endif diff --git a/src/experimental/cachestorefiles.h b/src/experimental/cachestorefiles.h index d3a6894..0805e7b 100644 --- a/src/experimental/cachestorefiles.h +++ b/src/experimental/cachestorefiles.h @@ -23,188 +23,188 @@ namespace Bu { - template - keytype __cacheGetKey( const obtype *pObj ); - - template - obtype *__cacheStoreFilesAlloc( const keytype &key ) - { - return new obtype(); - } - - template - void __cacheStoreFilesStore( Bu::Stream &s, obtype &rObj, - const keytype & ) - { - Bu::Archive ar( s, Bu::Archive::save ); - ar << rObj; - } - - template - obtype *__cacheStoreFilesLoad( Bu::Stream &s, const keytype &key ) - { - obtype *pObj = __cacheStoreFilesAlloc( key ); - Bu::Archive ar( s, Bu::Archive::load ); - ar >> (*pObj); - return pObj; - } - - template - class CacheStoreFiles : public CacheStore - { - public: - CacheStoreFiles( const Bu::String &sPrefix ) : - sPrefix( sPrefix ) - { - if( access( sPrefix.getStr(), W_OK|R_OK|X_OK ) ) - { + template + keytype __cacheGetKey( const obtype *pObj ); + + template + obtype *__cacheStoreFilesAlloc( const keytype &key ) + { + return new obtype(); + } + + template + void __cacheStoreFilesStore( Bu::Stream &s, obtype &rObj, + const keytype & ) + { + Bu::Archive ar( s, Bu::Archive::save ); + ar << rObj; + } + + template + obtype *__cacheStoreFilesLoad( Bu::Stream &s, const keytype &key ) + { + obtype *pObj = __cacheStoreFilesAlloc( key ); + Bu::Archive ar( s, Bu::Archive::load ); + ar >> (*pObj); + return pObj; + } + + template + class CacheStoreFiles : public CacheStore + { + public: + CacheStoreFiles( const Bu::String &sPrefix ) : + sPrefix( sPrefix ) + { + if( access( sPrefix.getStr(), W_OK|R_OK|X_OK ) ) + { #ifdef WIN32 - mkdir( sPrefix.getStr() ); + mkdir( sPrefix.getStr() ); #else - mkdir( sPrefix.getStr(), 0755 ); + mkdir( sPrefix.getStr(), 0755 ); #endif - } - } - - virtual ~CacheStoreFiles() - { - } - - virtual obtype *load( const keytype &key ) - { -// try -// { - Bu::MemBuf mb; - Bu::Formatter f( mb ); - f << sPrefix << "/" << key; - Bu::File fIn( mb.getString(), Bu::File::Read ); - obtype *pOb = __cacheStoreFilesLoad( fIn, key ); - return pOb; -// } -// catch( std::exception &e ) -// { -// throw Bu::HashException( e.what() ); -// } - } - - virtual void unload( obtype *pObj, const keytype & ) - { - delete pObj; - } - - virtual keytype create( obtype *pSrc ) - { - keytype key = __cacheGetKey( pSrc ); - Bu::MemBuf mb; - Bu::Formatter f( mb ); - f << sPrefix << "/" << key; - - Bu::File fTouch( mb.getString(), Bu::File::WriteNew ); - - return key; - } - - virtual void sync() - { - } - - virtual void sync( obtype *pSrc, const keytype &key ) - { - Bu::MemBuf mb; - Bu::Formatter f( mb ); - f << sPrefix << "/" << key; - - Bu::File fOut( mb.getString(), Bu::File::WriteNew ); - __cacheStoreFilesStore( fOut, *pSrc, key ); - } - - virtual void destroy( obtype *pObj, const keytype &key ) - { - Bu::MemBuf mb; - Bu::Formatter f( mb ); - f << sPrefix << "/" << key; - - unlink( mb.getString().getStr() ); - delete pObj; - } - - virtual void destroy( const keytype &key ) - { - Bu::MemBuf mb; - Bu::Formatter f( mb ); - f << sPrefix << "/" << key; - - unlink( mb.getString().getStr() ); - } - - virtual bool has( const keytype &key ) - { - Bu::MemBuf mb; - Bu::Formatter f( mb ); - f << sPrefix << "/"; - Bu::String sBase = mb.getString(); - f << key; - - if( sBase == mb.getString() ) - return false; - - return access( mb.getString().getStr(), F_OK ) == 0; - } - - virtual Bu::List getKeys() - { - DIR *dir = opendir( sPrefix.getStr() ); - struct dirent *de; - Bu::List lKeys; - - while( (de = readdir( dir ) ) ) - { - if( de->d_type != DT_REG ) - continue; - - keytype tmp; - Bu::MemBuf mb( de->d_name ); - Bu::Formatter f( mb ); - try - { - Fmt fm; - fm.tokenize( false ); - f << fm; - f >> tmp; - } - catch( Bu::ExceptionBase &e ) - { - Bu::sio << "Parse error in dir-scan: " << e.what() - << Bu::sio.nl; - } - lKeys.append( tmp ); - } - closedir( dir ); - - return lKeys; - } - - virtual int getSize() - { - DIR *dir = opendir( sPrefix.getStr() ); - struct dirent *de; - int iCount = 0; - - while( (de = readdir( dir ) ) ) - { - if( de->d_type != DT_REG ) - continue; - - iCount++; - } - closedir( dir ); - - return iCount; - } - - private: - Bu::String sPrefix; - }; + } + } + + virtual ~CacheStoreFiles() + { + } + + virtual obtype *load( const keytype &key ) + { +// try +// { + Bu::MemBuf mb; + Bu::Formatter f( mb ); + f << sPrefix << "/" << key; + Bu::File fIn( mb.getString(), Bu::File::Read ); + obtype *pOb = __cacheStoreFilesLoad( fIn, key ); + return pOb; +// } +// catch( std::exception &e ) +// { +// throw Bu::HashException( e.what() ); +// } + } + + virtual void unload( obtype *pObj, const keytype & ) + { + delete pObj; + } + + virtual keytype create( obtype *pSrc ) + { + keytype key = __cacheGetKey( pSrc ); + Bu::MemBuf mb; + Bu::Formatter f( mb ); + f << sPrefix << "/" << key; + + Bu::File fTouch( mb.getString(), Bu::File::WriteNew ); + + return key; + } + + virtual void sync() + { + } + + virtual void sync( obtype *pSrc, const keytype &key ) + { + Bu::MemBuf mb; + Bu::Formatter f( mb ); + f << sPrefix << "/" << key; + + Bu::File fOut( mb.getString(), Bu::File::WriteNew ); + __cacheStoreFilesStore( fOut, *pSrc, key ); + } + + virtual void destroy( obtype *pObj, const keytype &key ) + { + Bu::MemBuf mb; + Bu::Formatter f( mb ); + f << sPrefix << "/" << key; + + unlink( mb.getString().getStr() ); + delete pObj; + } + + virtual void destroy( const keytype &key ) + { + Bu::MemBuf mb; + Bu::Formatter f( mb ); + f << sPrefix << "/" << key; + + unlink( mb.getString().getStr() ); + } + + virtual bool has( const keytype &key ) + { + Bu::MemBuf mb; + Bu::Formatter f( mb ); + f << sPrefix << "/"; + Bu::String sBase = mb.getString(); + f << key; + + if( sBase == mb.getString() ) + return false; + + return access( mb.getString().getStr(), F_OK ) == 0; + } + + virtual Bu::List getKeys() + { + DIR *dir = opendir( sPrefix.getStr() ); + struct dirent *de; + Bu::List lKeys; + + while( (de = readdir( dir ) ) ) + { + if( de->d_type != DT_REG ) + continue; + + keytype tmp; + Bu::MemBuf mb( de->d_name ); + Bu::Formatter f( mb ); + try + { + Fmt fm; + fm.tokenize( false ); + f << fm; + f >> tmp; + } + catch( Bu::ExceptionBase &e ) + { + Bu::sio << "Parse error in dir-scan: " << e.what() + << Bu::sio.nl; + } + lKeys.append( tmp ); + } + closedir( dir ); + + return lKeys; + } + + virtual int getSize() + { + DIR *dir = opendir( sPrefix.getStr() ); + struct dirent *de; + int iCount = 0; + + while( (de = readdir( dir ) ) ) + { + if( de->d_type != DT_REG ) + continue; + + iCount++; + } + closedir( dir ); + + return iCount; + } + + private: + Bu::String sPrefix; + }; }; diff --git a/src/experimental/cachestoremyriad.h b/src/experimental/cachestoremyriad.h index 1953b61..01fe307 100644 --- a/src/experimental/cachestoremyriad.h +++ b/src/experimental/cachestoremyriad.h @@ -18,141 +18,141 @@ namespace Bu { - template - keytype __cacheGetKey( const obtype *pObj ); - - template - obtype *__cacheStoreMyriadAlloc( const keytype &key ) - { - return new obtype(); - } - - template - void __cacheStoreMyriadStore( Bu::Stream &s, obtype &rObj, - const keytype & ) - { - Bu::Archive ar( s, Bu::Archive::save ); - ar << rObj; - } - - template - obtype *__cacheStoreMyriadLoad( Bu::Stream &s, const keytype &key ) - { - obtype *pObj = __cacheStoreMyriadAlloc( key ); - Bu::Archive ar( s, Bu::Archive::load ); - ar >> (*pObj); - return pObj; - } - - template - class CacheStoreMyriad : public CacheStore - { - public: - CacheStoreMyriad( Bu::Stream &sArch, - int iBlockSize=512, int iPreAllocate=8 ) : - mStore( sArch, iBlockSize, iPreAllocate ) - { - try - { - MyriadStream ns = mStore.openStream( 1 ); - Bu::Archive ar( ns, Bu::Archive::load ); - ar >> hId; - } - catch( Bu::MyriadException &e ) - { - int iStream = mStore.createStream(); - if( iStream != 1 ) - throw Bu::ExceptionBase("That's...horrible...id = %d.\n\n", - iStream ); - MyriadStream ns = mStore.openStream( 1 ); - Bu::Archive ar( ns, Bu::Archive::save ); - ar << hId; - } - } - - virtual ~CacheStoreMyriad() - { - MyriadStream ns = mStore.openStream( 1 ); - Bu::Archive ar( ns, Bu::Archive::save ); - ar << hId; - } - - virtual obtype *load( const keytype &key ) - { - int iStream = hId.get( key ); - MyriadStream ns = mStore.openStream( iStream ); - obtype *pOb = __cacheStoreMyriadLoad( ns, key ); - return pOb; - } - - virtual void unload( obtype *pObj, const keytype & ) - { - delete pObj; - } - - virtual keytype create( obtype *pSrc ) - { - keytype key = __cacheGetKey( pSrc ); - int iStream = mStore.createStream(); - hId.insert( key, iStream ); - MyriadStream ns = mStore.openStream( iStream ); - __cacheStoreMyriadStore( ns, *pSrc, key ); - ns.setSize( ns.tell() ); - return key; - } - - virtual void sync() - { - MyriadStream ns = mStore.openStream( 1 ); - Bu::Archive ar( ns, Bu::Archive::save ); - ar << hId; - ns.setSize( ns.tell() ); - mStore.sync(); - } - - virtual void sync( obtype *pSrc, const keytype &key ) - { - int iStream = hId.get( key ); - MyriadStream ns = mStore.openStream( iStream ); - __cacheStoreMyriadStore( ns, *pSrc, key ); - ns.setSize( ns.tell() ); - } - - virtual void destroy( obtype *pObj, const keytype &key ) - { - int iStream = hId.get( key ); - mStore.deleteStream( iStream ); - hId.erase( key ); - delete pObj; - } - - virtual void destroy( const keytype &key ) - { - int iStream = hId.get( key ); - mStore.deleteStream( iStream ); - hId.erase( key ); - } - - virtual bool has( const keytype &key ) - { - return hId.has( key ); - } - - virtual Bu::List getKeys() - { - return hId.getKeys(); - } - - virtual int getSize() - { - return hId.getSize(); - } - - private: - Myriad mStore; - typedef Bu::Hash StreamHash; - StreamHash hId; - }; + template + keytype __cacheGetKey( const obtype *pObj ); + + template + obtype *__cacheStoreMyriadAlloc( const keytype &key ) + { + return new obtype(); + } + + template + void __cacheStoreMyriadStore( Bu::Stream &s, obtype &rObj, + const keytype & ) + { + Bu::Archive ar( s, Bu::Archive::save ); + ar << rObj; + } + + template + obtype *__cacheStoreMyriadLoad( Bu::Stream &s, const keytype &key ) + { + obtype *pObj = __cacheStoreMyriadAlloc( key ); + Bu::Archive ar( s, Bu::Archive::load ); + ar >> (*pObj); + return pObj; + } + + template + class CacheStoreMyriad : public CacheStore + { + public: + CacheStoreMyriad( Bu::Stream &sArch, + int iBlockSize=512, int iPreAllocate=8 ) : + mStore( sArch, iBlockSize, iPreAllocate ) + { + try + { + MyriadStream ns = mStore.openStream( 1 ); + Bu::Archive ar( ns, Bu::Archive::load ); + ar >> hId; + } + catch( Bu::MyriadException &e ) + { + int iStream = mStore.createStream(); + if( iStream != 1 ) + throw Bu::ExceptionBase("That's...horrible...id = %d.\n\n", + iStream ); + MyriadStream ns = mStore.openStream( 1 ); + Bu::Archive ar( ns, Bu::Archive::save ); + ar << hId; + } + } + + virtual ~CacheStoreMyriad() + { + MyriadStream ns = mStore.openStream( 1 ); + Bu::Archive ar( ns, Bu::Archive::save ); + ar << hId; + } + + virtual obtype *load( const keytype &key ) + { + int iStream = hId.get( key ); + MyriadStream ns = mStore.openStream( iStream ); + obtype *pOb = __cacheStoreMyriadLoad( ns, key ); + return pOb; + } + + virtual void unload( obtype *pObj, const keytype & ) + { + delete pObj; + } + + virtual keytype create( obtype *pSrc ) + { + keytype key = __cacheGetKey( pSrc ); + int iStream = mStore.createStream(); + hId.insert( key, iStream ); + MyriadStream ns = mStore.openStream( iStream ); + __cacheStoreMyriadStore( ns, *pSrc, key ); + ns.setSize( ns.tell() ); + return key; + } + + virtual void sync() + { + MyriadStream ns = mStore.openStream( 1 ); + Bu::Archive ar( ns, Bu::Archive::save ); + ar << hId; + ns.setSize( ns.tell() ); + mStore.sync(); + } + + virtual void sync( obtype *pSrc, const keytype &key ) + { + int iStream = hId.get( key ); + MyriadStream ns = mStore.openStream( iStream ); + __cacheStoreMyriadStore( ns, *pSrc, key ); + ns.setSize( ns.tell() ); + } + + virtual void destroy( obtype *pObj, const keytype &key ) + { + int iStream = hId.get( key ); + mStore.deleteStream( iStream ); + hId.erase( key ); + delete pObj; + } + + virtual void destroy( const keytype &key ) + { + int iStream = hId.get( key ); + mStore.deleteStream( iStream ); + hId.erase( key ); + } + + virtual bool has( const keytype &key ) + { + return hId.has( key ); + } + + virtual Bu::List getKeys() + { + return hId.getKeys(); + } + + virtual int getSize() + { + return hId.getSize(); + } + + private: + Myriad mStore; + typedef Bu::Hash StreamHash; + StreamHash hId; + }; }; #endif diff --git a/src/experimental/cipher.h b/src/experimental/cipher.h index 5d5cb07..6e58613 100644 --- a/src/experimental/cipher.h +++ b/src/experimental/cipher.h @@ -13,115 +13,115 @@ namespace Bu { - template - class Cipher : public Bu::Filter - { - public: - Cipher( Bu::Stream &rNext ) : - Bu::Filter( rNext ), - iReadBufFill( 0 ), - iReadBufPos( 0 ), - iWriteBufFill( 0 ) - { - } - - virtual ~Cipher() - { - } - - virtual void start() - { - } - - virtual Bu::size stop() - { - flush(); - return 0; - } - - virtual Bu::size read( void *pBuf, Bu::size iBytes ) - { - Bu::size iRead = 0; - while( iRead < iBytes ) - { - if( iReadBufFill < iBlockSize ) - { - int iR = rNext.read( - aReadBuf+iReadBufFill, - iBlockSize-iReadBufFill - ); - if( iR == 0 ) - return iRead; - - iReadBufFill += iR; - - if( iReadBufFill == iBlockSize ) - decipher( aReadBuf ); - } - - if( iReadBufFill == iBlockSize ) - { - int iCpy = Bu::buMin( (int)(iBytes-iRead), iBlockSize-iReadBufPos ); - memcpy( ((char *)pBuf)+iRead, aReadBuf+iReadBufPos, iCpy ); - iRead += iCpy; - iReadBufPos += iCpy; - if( iReadBufPos == iBlockSize ) - { - iReadBufPos = iReadBufFill = 0; - } - } - } - - return iRead; - } - - virtual Bu::size write( const void *pBuf, Bu::size iBytes ) - { - Bu::size iPos = 0; - - while( iPos < iBytes ) - { - int iLeft = Bu::buMin((int)(iBytes-iPos),iBlockSize-iWriteBufFill); - memcpy( aWriteBuf+iWriteBufFill, (char *)pBuf+iPos, iLeft ); - iPos += iLeft; - iWriteBufFill += iLeft; - if( iWriteBufFill == iBlockSize ) - { - encipher( aWriteBuf ); - rNext.write( aWriteBuf, iBlockSize ); - iWriteBufFill = 0; - } - } - - return iPos; - } - - virtual void flush() - { - if( iWriteBufFill > 0 && iWriteBufFill < iBlockSize ) - { - memset( aWriteBuf+iWriteBufFill, 0, iBlockSize-iWriteBufFill ); - encipher( aWriteBuf ); - rNext.write( aWriteBuf, iBlockSize ); - iWriteBufFill = 0; - } - rNext.flush(); - } - - using Bu::Stream::read; - using Bu::Stream::write; - - protected: - virtual void encipher( void *pData )=0; - virtual void decipher( void *pData )=0; - - private: - char aReadBuf[iBlockSize]; - char aWriteBuf[iBlockSize]; - int iReadBufFill; - int iReadBufPos; - int iWriteBufFill; - }; + template + class Cipher : public Bu::Filter + { + public: + Cipher( Bu::Stream &rNext ) : + Bu::Filter( rNext ), + iReadBufFill( 0 ), + iReadBufPos( 0 ), + iWriteBufFill( 0 ) + { + } + + virtual ~Cipher() + { + } + + virtual void start() + { + } + + virtual Bu::size stop() + { + flush(); + return 0; + } + + virtual Bu::size read( void *pBuf, Bu::size iBytes ) + { + Bu::size iRead = 0; + while( iRead < iBytes ) + { + if( iReadBufFill < iBlockSize ) + { + int iR = rNext.read( + aReadBuf+iReadBufFill, + iBlockSize-iReadBufFill + ); + if( iR == 0 ) + return iRead; + + iReadBufFill += iR; + + if( iReadBufFill == iBlockSize ) + decipher( aReadBuf ); + } + + if( iReadBufFill == iBlockSize ) + { + int iCpy = Bu::buMin( (int)(iBytes-iRead), iBlockSize-iReadBufPos ); + memcpy( ((char *)pBuf)+iRead, aReadBuf+iReadBufPos, iCpy ); + iRead += iCpy; + iReadBufPos += iCpy; + if( iReadBufPos == iBlockSize ) + { + iReadBufPos = iReadBufFill = 0; + } + } + } + + return iRead; + } + + virtual Bu::size write( const void *pBuf, Bu::size iBytes ) + { + Bu::size iPos = 0; + + while( iPos < iBytes ) + { + int iLeft = Bu::buMin((int)(iBytes-iPos),iBlockSize-iWriteBufFill); + memcpy( aWriteBuf+iWriteBufFill, (char *)pBuf+iPos, iLeft ); + iPos += iLeft; + iWriteBufFill += iLeft; + if( iWriteBufFill == iBlockSize ) + { + encipher( aWriteBuf ); + rNext.write( aWriteBuf, iBlockSize ); + iWriteBufFill = 0; + } + } + + return iPos; + } + + virtual void flush() + { + if( iWriteBufFill > 0 && iWriteBufFill < iBlockSize ) + { + memset( aWriteBuf+iWriteBufFill, 0, iBlockSize-iWriteBufFill ); + encipher( aWriteBuf ); + rNext.write( aWriteBuf, iBlockSize ); + iWriteBufFill = 0; + } + rNext.flush(); + } + + using Bu::Stream::read; + using Bu::Stream::write; + + protected: + virtual void encipher( void *pData )=0; + virtual void decipher( void *pData )=0; + + private: + char aReadBuf[iBlockSize]; + char aWriteBuf[iBlockSize]; + int iReadBufFill; + int iReadBufPos; + int iWriteBufFill; + }; }; #endif diff --git a/src/experimental/ciphermodecbc.h b/src/experimental/ciphermodecbc.h index 8fbf9f6..b06a972 100644 --- a/src/experimental/ciphermodecbc.h +++ b/src/experimental/ciphermodecbc.h @@ -6,49 +6,49 @@ namespace Bu { - template - class CipherModeCbc : public CipherType - { - public: - CipherModeCbc(class Stream &rNext ) : - CipherType( rNext ), - bStart( true ) - { - memset( aVector, 0, iBlockSize ); - } - - virtual ~CipherModeCbc() - { - } - - void setIv( const Bu::String &sIv ) - { - memcpy( aVector, sIv.getStr(), iBlockSize ); - } - - protected: - void decipher( void *pBuf ) - { - uint8_t aTmp[iBlockSize]; - memcpy( aTmp, pBuf, iBlockSize ); - CipherType::decipher( pBuf ); - for( int j = 0; j < iBlockSize; j++ ) - ((uint8_t *)pBuf)[j] ^= aVector[j]; - memcpy( aVector, aTmp, iBlockSize ); - } - - void encipher( void *pBuf ) - { - for( int j = 0; j < iBlockSize; j++ ) - ((uint8_t *)pBuf)[j] ^= aVector[j]; - CipherType::encipher( pBuf ); - memcpy( aVector, pBuf, iBlockSize ); - } - - private: - bool bStart; - uint8_t aVector[iBlockSize]; - }; + template + class CipherModeCbc : public CipherType + { + public: + CipherModeCbc(class Stream &rNext ) : + CipherType( rNext ), + bStart( true ) + { + memset( aVector, 0, iBlockSize ); + } + + virtual ~CipherModeCbc() + { + } + + void setIv( const Bu::String &sIv ) + { + memcpy( aVector, sIv.getStr(), iBlockSize ); + } + + protected: + void decipher( void *pBuf ) + { + uint8_t aTmp[iBlockSize]; + memcpy( aTmp, pBuf, iBlockSize ); + CipherType::decipher( pBuf ); + for( int j = 0; j < iBlockSize; j++ ) + ((uint8_t *)pBuf)[j] ^= aVector[j]; + memcpy( aVector, aTmp, iBlockSize ); + } + + void encipher( void *pBuf ) + { + for( int j = 0; j < iBlockSize; j++ ) + ((uint8_t *)pBuf)[j] ^= aVector[j]; + CipherType::encipher( pBuf ); + memcpy( aVector, pBuf, iBlockSize ); + } + + private: + bool bStart; + uint8_t aVector[iBlockSize]; + }; }; #endif diff --git a/src/experimental/ciphermodecfb.h b/src/experimental/ciphermodecfb.h index dab6c2e..34c682f 100644 --- a/src/experimental/ciphermodecfb.h +++ b/src/experimental/ciphermodecfb.h @@ -6,48 +6,48 @@ namespace Bu { - template - class CipherModeCfb : public CipherType - { - public: - CipherModeCfb(class Stream &rNext ) : - CipherType( rNext ), - bStart( true ) - { - memset( aVector, 0, iBlockSize ); - } - - virtual ~CipherModeCfb() - { - } - - void setIv( const Bu::String &sIv ) - { - memcpy( aVector, sIv.getStr(), iBlockSize ); - } - - protected: - void decipher( void *pBuf ) - { - uint8_t aTmp[iBlockSize]; - memcpy( aTmp, pBuf, iBlockSize ); - CipherType::encipher( aVector ); - for( int j = 0; j < iBlockSize; j++ ) - ((uint8_t *)pBuf)[j] ^= aVector[j]; - memcpy( aVector, aTmp, iBlockSize ); - } - - void encipher( void *pBuf ) - { - CipherType::encipher( aVector ); - for( int j = 0; j < iBlockSize; j++ ) - aVector[j] = ((uint8_t *)pBuf)[j] ^= aVector[j]; - } - - private: - bool bStart; - uint8_t aVector[iBlockSize]; - }; + template + class CipherModeCfb : public CipherType + { + public: + CipherModeCfb(class Stream &rNext ) : + CipherType( rNext ), + bStart( true ) + { + memset( aVector, 0, iBlockSize ); + } + + virtual ~CipherModeCfb() + { + } + + void setIv( const Bu::String &sIv ) + { + memcpy( aVector, sIv.getStr(), iBlockSize ); + } + + protected: + void decipher( void *pBuf ) + { + uint8_t aTmp[iBlockSize]; + memcpy( aTmp, pBuf, iBlockSize ); + CipherType::encipher( aVector ); + for( int j = 0; j < iBlockSize; j++ ) + ((uint8_t *)pBuf)[j] ^= aVector[j]; + memcpy( aVector, aTmp, iBlockSize ); + } + + void encipher( void *pBuf ) + { + CipherType::encipher( aVector ); + for( int j = 0; j < iBlockSize; j++ ) + aVector[j] = ((uint8_t *)pBuf)[j] ^= aVector[j]; + } + + private: + bool bStart; + uint8_t aVector[iBlockSize]; + }; }; #endif diff --git a/src/experimental/ciphermodeecb.h b/src/experimental/ciphermodeecb.h index 006741a..cac2beb 100644 --- a/src/experimental/ciphermodeecb.h +++ b/src/experimental/ciphermodeecb.h @@ -3,30 +3,30 @@ namespace Bu { - template - class CipherModeEcb : public CipherType - { - public: - CipherModeEcb( class Stream &rNext ) : - CipherType( rNext ) - { - } + template + class CipherModeEcb : public CipherType + { + public: + CipherModeEcb( class Stream &rNext ) : + CipherType( rNext ) + { + } - virtual ~CipherModeEcb() - { - } - - protected: - virtual void decipher( void *pBuf ) - { - CipherType::decipher( pBuf ); - } + virtual ~CipherModeEcb() + { + } + + protected: + virtual void decipher( void *pBuf ) + { + CipherType::decipher( pBuf ); + } - virtual void encipher( void *pBuf ) - { - CipherType::encipher( pBuf ); - } - }; + virtual void encipher( void *pBuf ) + { + CipherType::encipher( pBuf ); + } + }; }; #endif diff --git a/src/experimental/ciphermodeofb.h b/src/experimental/ciphermodeofb.h index 8c2aa20..e1b5108 100644 --- a/src/experimental/ciphermodeofb.h +++ b/src/experimental/ciphermodeofb.h @@ -6,51 +6,51 @@ namespace Bu { - template - class CipherModeOfb : public CipherType - { - public: - CipherModeOfb(class Stream &rNext ) : - CipherType( rNext ), - bStart( true ) - { - memset( aVector, 0, iBlockSize ); - } - - virtual ~CipherModeOfb() - { - } - - void setIv( const Bu::String &sIv ) - { - memcpy( aVector, sIv.getStr(), iBlockSize ); - } - - protected: - void decipher( void *pBuf ) - { - CipherType::encipher( aVector ); - uint8_t aTmp[iBlockSize]; - memcpy( aTmp, aVector, iBlockSize ); - for( int j = 0; j < iBlockSize; j++ ) - ((uint8_t *)pBuf)[j] ^= aVector[j]; - memcpy( aVector, aTmp, iBlockSize ); - } - - void encipher( void *pBuf ) - { - CipherType::encipher( aVector ); - uint8_t aTmp[iBlockSize]; - memcpy( aTmp, aVector, iBlockSize ); - for( int j = 0; j < iBlockSize; j++ ) - ((uint8_t *)pBuf)[j] ^= aVector[j]; - memcpy( aVector, aTmp, iBlockSize ); - } - - private: - bool bStart; - uint8_t aVector[iBlockSize]; - }; + template + class CipherModeOfb : public CipherType + { + public: + CipherModeOfb(class Stream &rNext ) : + CipherType( rNext ), + bStart( true ) + { + memset( aVector, 0, iBlockSize ); + } + + virtual ~CipherModeOfb() + { + } + + void setIv( const Bu::String &sIv ) + { + memcpy( aVector, sIv.getStr(), iBlockSize ); + } + + protected: + void decipher( void *pBuf ) + { + CipherType::encipher( aVector ); + uint8_t aTmp[iBlockSize]; + memcpy( aTmp, aVector, iBlockSize ); + for( int j = 0; j < iBlockSize; j++ ) + ((uint8_t *)pBuf)[j] ^= aVector[j]; + memcpy( aVector, aTmp, iBlockSize ); + } + + void encipher( void *pBuf ) + { + CipherType::encipher( aVector ); + uint8_t aTmp[iBlockSize]; + memcpy( aTmp, aVector, iBlockSize ); + for( int j = 0; j < iBlockSize; j++ ) + ((uint8_t *)pBuf)[j] ^= aVector[j]; + memcpy( aVector, aTmp, iBlockSize ); + } + + private: + bool bStart; + uint8_t aVector[iBlockSize]; + }; }; #endif diff --git a/src/experimental/dir.h b/src/experimental/dir.h index 8e885d1..9e518eb 100644 --- a/src/experimental/dir.h +++ b/src/experimental/dir.h @@ -6,15 +6,15 @@ namespace Bu { - class Dir : public FileSystem - { - public: - Dir(); - Dir( const Bu::String &sPath ); - virtual ~Dir(); + class Dir : public FileSystem + { + public: + Dir(); + Dir( const Bu::String &sPath ); + virtual ~Dir(); - private: - }; + private: + }; }; #endif diff --git a/src/experimental/fastcgi.cpp b/src/experimental/fastcgi.cpp index 7068fa8..71426b9 100644 --- a/src/experimental/fastcgi.cpp +++ b/src/experimental/fastcgi.cpp @@ -8,7 +8,7 @@ #include "bu/fastcgi.h" #ifndef WIN32 - #include + #include #endif #include @@ -21,17 +21,17 @@ using Bu::sio; using Bu::Fmt; Bu::FastCgi::FastCgi() : - pSrv( NULL ), - bRunning( true ) + pSrv( NULL ), + bRunning( true ) { - pSrv = new Bu::TcpServerSocket( (Bu::TcpServerSocket::socket_t)STDIN_FILENO, false ); + pSrv = new Bu::TcpServerSocket( (Bu::TcpServerSocket::socket_t)STDIN_FILENO, false ); } Bu::FastCgi::FastCgi( int iPort ) : - pSrv( NULL ), - bRunning( true ) + pSrv( NULL ), + bRunning( true ) { - pSrv = new Bu::TcpServerSocket( iPort ); + pSrv = new Bu::TcpServerSocket( iPort ); } Bu::FastCgi::~FastCgi() @@ -41,332 +41,332 @@ Bu::FastCgi::~FastCgi() bool Bu::FastCgi::isEmbedded() { #ifndef WIN32 - struct sockaddr name; - socklen_t namelen = sizeof(name); - if( getpeername( STDIN_FILENO, &name, &namelen ) != 0 && - errno == ENOTCONN ) - { - sio << "errno = " << errno << " (" << strerror( errno ) << ")" << - sio.nl; - sio << "Socket found" << sio.nl; - return true; - } - else - { - sio << "errno = " << errno << " (" << strerror( errno ) << ")" << - sio.nl; - sio << "No socket detected, running in standalone mode" << sio.nl; - return false; - } + struct sockaddr name; + socklen_t namelen = sizeof(name); + if( getpeername( STDIN_FILENO, &name, &namelen ) != 0 && + errno == ENOTCONN ) + { + sio << "errno = " << errno << " (" << strerror( errno ) << ")" << + sio.nl; + sio << "Socket found" << sio.nl; + return true; + } + else + { + sio << "errno = " << errno << " (" << strerror( errno ) << ")" << + sio.nl; + sio << "No socket detected, running in standalone mode" << sio.nl; + return false; + } #else - #warning Bu::FastCgi::isEmbedded IS A STUB for WIN32!!!! - return false; + #warning Bu::FastCgi::isEmbedded IS A STUB for WIN32!!!! + return false; #endif } void Bu::FastCgi::read( Bu::TcpSocket &s, Bu::FastCgi::Record &r ) { - int iRead = s.read( &r, sizeof(Record) ); - if( iRead != sizeof(Record) ) - throw Bu::TcpSocketException("Hey, the size %d is wrong for Record. (%s)", - iRead, strerror( errno ) ); - r.uRequestId = ntohs( r.uRequestId ); - r.uContentLength = ntohs( r.uContentLength ); + int iRead = s.read( &r, sizeof(Record) ); + if( iRead != sizeof(Record) ) + throw Bu::TcpSocketException("Hey, the size %d is wrong for Record. (%s)", + iRead, strerror( errno ) ); + r.uRequestId = ntohs( r.uRequestId ); + r.uContentLength = ntohs( r.uContentLength ); } void Bu::FastCgi::write( Bu::TcpSocket &s, Bu::FastCgi::Record r ) { -// sio << "Out -> " << r << sio.nl; - r.uRequestId = htons( r.uRequestId ); - r.uContentLength = htons( r.uContentLength ); - s.write( &r, sizeof(Record) ); +// sio << "Out -> " << r << sio.nl; + r.uRequestId = htons( r.uRequestId ); + r.uContentLength = htons( r.uContentLength ); + s.write( &r, sizeof(Record) ); } void Bu::FastCgi::read( Bu::TcpSocket &s, Bu::FastCgi::BeginRequestBody &b ) { - s.read( &b, sizeof(BeginRequestBody) ); - b.uRole = ntohs( b.uRole ); + s.read( &b, sizeof(BeginRequestBody) ); + b.uRole = ntohs( b.uRole ); } void Bu::FastCgi::write( Bu::TcpSocket &s, Bu::FastCgi::EndRequestBody b ) { - b.uStatus = htonl( b.uStatus ); - s.write( &b, sizeof(b) ); + b.uStatus = htonl( b.uStatus ); + s.write( &b, sizeof(b) ); } uint32_t Bu::FastCgi::readLen( Bu::TcpSocket &s, uint16_t &uRead ) { - uint8_t uByte[4]; - s.read( uByte, 1 ); - uRead++; - if( uByte[0] >> 7 == 0 ) - return uByte[0]; - - s.read( uByte+1, 3 ); - uRead += 3; - return ((uByte[0]&0x7f)<<24)|(uByte[1]<<16)|(uByte[2]<<8)|(uByte[3]); + uint8_t uByte[4]; + s.read( uByte, 1 ); + uRead++; + if( uByte[0] >> 7 == 0 ) + return uByte[0]; + + s.read( uByte+1, 3 ); + uRead += 3; + return ((uByte[0]&0x7f)<<24)|(uByte[1]<<16)|(uByte[2]<<8)|(uByte[3]); } void Bu::FastCgi::readPair( Bu::TcpSocket &s, StrHash &hParams, uint16_t &uRead ) { - uint32_t uName = readLen( s, uRead ); - uint32_t uValue = readLen( s, uRead ); - uRead += uName + uValue; - unsigned char *sName = new unsigned char[uName]; - s.read( sName, uName ); - Bu::String fsName( (char *)sName, uName ); - delete[] sName; - - if( uValue > 0 ) - { - unsigned char *sValue = new unsigned char[uValue]; - s.read( sValue, uValue ); - Bu::String fsValue( (char *)sValue, uValue ); - hParams.insert( fsName, fsValue ); - delete[] sValue; - } - else - { - hParams.insert( fsName, "" ); - } + uint32_t uName = readLen( s, uRead ); + uint32_t uValue = readLen( s, uRead ); + uRead += uName + uValue; + unsigned char *sName = new unsigned char[uName]; + s.read( sName, uName ); + Bu::String fsName( (char *)sName, uName ); + delete[] sName; + + if( uValue > 0 ) + { + unsigned char *sValue = new unsigned char[uValue]; + s.read( sValue, uValue ); + Bu::String fsValue( (char *)sValue, uValue ); + hParams.insert( fsName, fsValue ); + delete[] sValue; + } + else + { + hParams.insert( fsName, "" ); + } } bool Bu::FastCgi::hasChannel( int iChan ) { - if( aChannel.getSize() < iChan ) - return false; - if( aChannel[iChan-1] == NULL ) - return false; - return true; + if( aChannel.getSize() < iChan ) + return false; + if( aChannel[iChan-1] == NULL ) + return false; + return true; } Bu::Formatter &Bu::operator<<( Bu::Formatter &f, const Bu::FastCgi::Record &r ) { - f << "[Ver=" << (uint32_t)r.uVersion << - ", Type=" << (uint32_t)r.uType << - ", Req=" << (uint32_t)r.uRequestId << - ", clen=" << (uint32_t)r.uContentLength << - ", plen=" << (uint32_t)r.uPaddingLength << - ", resv=" << (uint32_t)r.uReserved << - "]"; - return f; + f << "[Ver=" << (uint32_t)r.uVersion << + ", Type=" << (uint32_t)r.uType << + ", Req=" << (uint32_t)r.uRequestId << + ", clen=" << (uint32_t)r.uContentLength << + ", plen=" << (uint32_t)r.uPaddingLength << + ", resv=" << (uint32_t)r.uReserved << + "]"; + return f; } void Bu::FastCgi::run() { -// sio << "sizeof(Bu::FastCgi::Record) = " << sizeof(Record) << sio.nl; - bRunning = true; - while( bRunning ) - { - int iSock = pSrv->accept( 5 ); - if( iSock < 0 ) - continue; - - Bu::TcpSocket s( iSock ); - s.setBlocking( true ); -// sio << "Got connection, blocking? " << s.isBlocking() << sio.nl; - try - { - for(;;) - { - Record r; - memset( &r, 0, sizeof(r) ); -// try -// { - read( s, r ); -// } -// catch( Bu::ExceptionBase &e ) -// { -// sio << "Error: " << e.what() << ", " << s.isOpen() << -// sio.nl; -// continue; -// } - Channel *pChan = NULL; - if( r.uRequestId > 0 ) - { - if( !hasChannel( r.uRequestId ) && - r.uType != typeBeginRequest ) - { - sio << "Error, stream data without stream." << sio.nl; - sio << r << sio.nl; - if( r.uContentLength > 0 ) - { - char *buf = new char[r.uContentLength]; - sio << " (read " << s.read( buf, r.uContentLength ) - << "/" << r.uContentLength << "):" << sio.nl; - sio.write( buf, r.uContentLength ); - sio << sio.nl << sio.nl; - } - } - while( aChannel.getSize() < r.uRequestId ) - aChannel.append( NULL ); - if( r.uRequestId > 0 ) - pChan = aChannel[r.uRequestId-1]; - } - -// sio << "Record (id=" << r.uRequestId << ", len=" << -// r.uContentLength << ", pad=" << -// (unsigned int)r.uPaddingLength << "): "; -// fflush( stdout ); - - switch( (RequestType)r.uType ) - { - case typeBeginRequest: -// sio << "Begin Request."; - { - BeginRequestBody b; - read( s, b ); - if( pChan != NULL ) - { - sio << "Error!!!" << sio.nl; - return; - } - pChan = aChannel[r.uRequestId-1] = new Channel(); - } - break; - - case typeParams: -// sio << "Params."; - if( r.uContentLength == 0 ) - { - pChan->uFlags |= chflgParamsDone; - } - else - { - uint16_t uUsed = 0; - while( uUsed < r.uContentLength ) - { - readPair( s, pChan->hParams, uUsed ); - } - } - break; - - case typeStdIn: -// sio << "StdIn."; - if( r.uContentLength == 0 ) - { - pChan->uFlags |= chflgStdInDone; - } - else - { - char *buf = new char[r.uContentLength]; - int iTotal = 0; - do - { - size_t iRead = s.read( - buf, r.uContentLength-iTotal ); - iTotal += iRead; -// sio << " (read " << iRead << " " << iTotal -// << "/" << r.uContentLength << ")"; - pChan->sStdIn.append( buf, iRead ); - } while( iTotal < r.uContentLength ); - delete[] buf; - } - break; - - case typeData: -// sio << "Data."; - if( r.uContentLength == 0 ) - { - pChan->uFlags |= chflgDataDone; - } - else - { - char *buf = new char[r.uContentLength]; - s.read( buf, r.uContentLength ); - pChan->sData.append( buf, r.uContentLength ); - delete[] buf; - } - break; - - case typeStdOut: - case typeStdErr: - case typeEndRequest: - case typeAbortRequest: - case typeGetValuesResult: -// sio << "Scary."; - // ??? we shouldn't get these. - break; - - case typeGetValues: - break; - } - -// sio << sio.nl; - - if( pChan ) - { - if( pChan->uFlags == chflgAllDone ) - { -// sio << "All done, generating output." << sio.nl; - Bu::MemBuf mStdOut, mStdErr; - int iRet = onRequest( - pChan->hParams, pChan->sStdIn, - mStdOut, mStdErr - ); - - Bu::String &sStdOut = mStdOut.getString(); - Bu::String &sStdErr = mStdErr.getString(); - - Record rOut; - memset( &rOut, 0, sizeof(rOut) ); - rOut.uVersion = 1; - rOut.uRequestId = r.uRequestId; - rOut.uPaddingLength = 0; - rOut.uType = typeStdOut; - if( sStdOut.getSize() > 0 ) - { - for( int iPos = 0; iPos < sStdOut.getSize(); - iPos += 65528 ) - { - int iSize = sStdOut.getSize()-iPos; - if( iSize > 65528 ) - iSize = 65528; - rOut.uContentLength = iSize; - write( s, rOut ); - s.write( sStdOut.getStr()+iPos, iSize ); - } - } - rOut.uContentLength = 0; - write( s, rOut ); - - rOut.uType = typeStdErr; - if( sStdErr.getSize() > 0 ) - { - for( int iPos = 0; iPos < sStdErr.getSize(); - iPos += 65528 ) - { - int iSize = sStdErr.getSize()-iPos; - if( iSize > 65528 ) - iSize = 65528; - rOut.uContentLength = iSize; - write( s, rOut ); - s.write( sStdErr.getStr()+iPos, iSize ); - } - } - rOut.uContentLength = 0; - write( s, rOut ); - - rOut.uType = typeEndRequest; - rOut.uContentLength = 8; - write( s, rOut ); - - EndRequestBody b; - memset( &b, 0, sizeof(b) ); - b.uStatus = iRet; - write( s, b ); - - delete pChan; - aChannel[r.uRequestId-1] = NULL; - } - } - } - } - catch( Bu::TcpSocketException &e ) - { -// sio << "Bu::SocketException: " << e.what() << sio.nl << -// "\tSocket open: " << s.isOpen() << sio.nl; - } - } +// sio << "sizeof(Bu::FastCgi::Record) = " << sizeof(Record) << sio.nl; + bRunning = true; + while( bRunning ) + { + int iSock = pSrv->accept( 5 ); + if( iSock < 0 ) + continue; + + Bu::TcpSocket s( iSock ); + s.setBlocking( true ); +// sio << "Got connection, blocking? " << s.isBlocking() << sio.nl; + try + { + for(;;) + { + Record r; + memset( &r, 0, sizeof(r) ); +// try +// { + read( s, r ); +// } +// catch( Bu::ExceptionBase &e ) +// { +// sio << "Error: " << e.what() << ", " << s.isOpen() << +// sio.nl; +// continue; +// } + Channel *pChan = NULL; + if( r.uRequestId > 0 ) + { + if( !hasChannel( r.uRequestId ) && + r.uType != typeBeginRequest ) + { + sio << "Error, stream data without stream." << sio.nl; + sio << r << sio.nl; + if( r.uContentLength > 0 ) + { + char *buf = new char[r.uContentLength]; + sio << " (read " << s.read( buf, r.uContentLength ) + << "/" << r.uContentLength << "):" << sio.nl; + sio.write( buf, r.uContentLength ); + sio << sio.nl << sio.nl; + } + } + while( aChannel.getSize() < r.uRequestId ) + aChannel.append( NULL ); + if( r.uRequestId > 0 ) + pChan = aChannel[r.uRequestId-1]; + } + +// sio << "Record (id=" << r.uRequestId << ", len=" << +// r.uContentLength << ", pad=" << +// (unsigned int)r.uPaddingLength << "): "; +// fflush( stdout ); + + switch( (RequestType)r.uType ) + { + case typeBeginRequest: +// sio << "Begin Request."; + { + BeginRequestBody b; + read( s, b ); + if( pChan != NULL ) + { + sio << "Error!!!" << sio.nl; + return; + } + pChan = aChannel[r.uRequestId-1] = new Channel(); + } + break; + + case typeParams: +// sio << "Params."; + if( r.uContentLength == 0 ) + { + pChan->uFlags |= chflgParamsDone; + } + else + { + uint16_t uUsed = 0; + while( uUsed < r.uContentLength ) + { + readPair( s, pChan->hParams, uUsed ); + } + } + break; + + case typeStdIn: +// sio << "StdIn."; + if( r.uContentLength == 0 ) + { + pChan->uFlags |= chflgStdInDone; + } + else + { + char *buf = new char[r.uContentLength]; + int iTotal = 0; + do + { + size_t iRead = s.read( + buf, r.uContentLength-iTotal ); + iTotal += iRead; +// sio << " (read " << iRead << " " << iTotal +// << "/" << r.uContentLength << ")"; + pChan->sStdIn.append( buf, iRead ); + } while( iTotal < r.uContentLength ); + delete[] buf; + } + break; + + case typeData: +// sio << "Data."; + if( r.uContentLength == 0 ) + { + pChan->uFlags |= chflgDataDone; + } + else + { + char *buf = new char[r.uContentLength]; + s.read( buf, r.uContentLength ); + pChan->sData.append( buf, r.uContentLength ); + delete[] buf; + } + break; + + case typeStdOut: + case typeStdErr: + case typeEndRequest: + case typeAbortRequest: + case typeGetValuesResult: +// sio << "Scary."; + // ??? we shouldn't get these. + break; + + case typeGetValues: + break; + } + +// sio << sio.nl; + + if( pChan ) + { + if( pChan->uFlags == chflgAllDone ) + { +// sio << "All done, generating output." << sio.nl; + Bu::MemBuf mStdOut, mStdErr; + int iRet = onRequest( + pChan->hParams, pChan->sStdIn, + mStdOut, mStdErr + ); + + Bu::String &sStdOut = mStdOut.getString(); + Bu::String &sStdErr = mStdErr.getString(); + + Record rOut; + memset( &rOut, 0, sizeof(rOut) ); + rOut.uVersion = 1; + rOut.uRequestId = r.uRequestId; + rOut.uPaddingLength = 0; + rOut.uType = typeStdOut; + if( sStdOut.getSize() > 0 ) + { + for( int iPos = 0; iPos < sStdOut.getSize(); + iPos += 65528 ) + { + int iSize = sStdOut.getSize()-iPos; + if( iSize > 65528 ) + iSize = 65528; + rOut.uContentLength = iSize; + write( s, rOut ); + s.write( sStdOut.getStr()+iPos, iSize ); + } + } + rOut.uContentLength = 0; + write( s, rOut ); + + rOut.uType = typeStdErr; + if( sStdErr.getSize() > 0 ) + { + for( int iPos = 0; iPos < sStdErr.getSize(); + iPos += 65528 ) + { + int iSize = sStdErr.getSize()-iPos; + if( iSize > 65528 ) + iSize = 65528; + rOut.uContentLength = iSize; + write( s, rOut ); + s.write( sStdErr.getStr()+iPos, iSize ); + } + } + rOut.uContentLength = 0; + write( s, rOut ); + + rOut.uType = typeEndRequest; + rOut.uContentLength = 8; + write( s, rOut ); + + EndRequestBody b; + memset( &b, 0, sizeof(b) ); + b.uStatus = iRet; + write( s, b ); + + delete pChan; + aChannel[r.uRequestId-1] = NULL; + } + } + } + } + catch( Bu::TcpSocketException &e ) + { +// sio << "Bu::SocketException: " << e.what() << sio.nl << +// "\tSocket open: " << s.isOpen() << sio.nl; + } + } } diff --git a/src/experimental/fastcgi.h b/src/experimental/fastcgi.h index 63d975f..50b10f5 100644 --- a/src/experimental/fastcgi.h +++ b/src/experimental/fastcgi.h @@ -16,118 +16,118 @@ namespace Bu { - class Stream; - - class FastCgi - { - public: - FastCgi( int iPort ); - FastCgi(); - virtual ~FastCgi(); - - static bool isEmbedded(); - - typedef Bu::Hash StrHash; - enum RequestType - { - typeBeginRequest = 1, - typeAbortRequest = 2, - typeEndRequest = 3, - typeParams = 4, - typeStdIn = 5, - typeStdOut = 6, - typeStdErr = 7, - typeData = 8, - typeGetValues = 9, - typeGetValuesResult = 10 - }; - - enum Role - { - roleResponder = 1, - roleAuthorizer = 2, - roleFilter = 3 - }; - - enum Flags - { - flagsKeepConn = 1 - }; - - enum Status - { - statusRequestComplete = 0, - statusCantMpxConn = 1, - statusOverloaded = 2, - statusUnknownRole = 3 - }; - - typedef struct { - uint8_t uVersion; - uint8_t uType; - uint16_t uRequestId; - uint16_t uContentLength; - uint8_t uPaddingLength; - uint8_t uReserved; - } Record; - - typedef struct { - uint16_t uRole; - uint8_t uFlags; - uint8_t reserved[5]; - } BeginRequestBody; - - typedef struct { - uint32_t uStatus; - uint8_t uProtocolStatus; - uint8_t reserved[3]; - } EndRequestBody; - - typedef struct Channel { - Channel() : uFlags( 0 ) { } - StrHash hParams; - Bu::String sStdIn; - Bu::String sData; - uint8_t uFlags; - } Channel; - - enum ChannelFlags - { - chflgParamsDone = 0x01, - chflgStdInDone = 0x02, - chflgDataDone = 0x04, - - chflgAllDone = 0x03 - }; - - virtual void run(); - - void stopRunning() { bRunning = false; } - - virtual void onInit() { }; - virtual int onRequest( const StrHash &hParams, - const Bu::String &sStdIn, Bu::Stream &sStdOut, - Bu::Stream &sStdErr )=0; - virtual void onUninit() { }; - - private: - void read( Bu::TcpSocket &s, Record &r ); - void read( Bu::TcpSocket &s, BeginRequestBody &b ); - uint32_t readLen( Bu::TcpSocket &s, uint16_t &uUsed ); - void readPair( Bu::TcpSocket &s, StrHash &hParams, uint16_t &uUsed ); - - void write( Bu::TcpSocket &s, Record r ); - void write( Bu::TcpSocket &s, EndRequestBody b ); - - bool hasChannel( int iChan ); - - private: - Bu::TcpServerSocket *pSrv; - bool bRunning; - Bu::Array aChannel; - }; - - Bu::Formatter &operator<<( Bu::Formatter &f, const Bu::FastCgi::Record &r ); + class Stream; + + class FastCgi + { + public: + FastCgi( int iPort ); + FastCgi(); + virtual ~FastCgi(); + + static bool isEmbedded(); + + typedef Bu::Hash StrHash; + enum RequestType + { + typeBeginRequest = 1, + typeAbortRequest = 2, + typeEndRequest = 3, + typeParams = 4, + typeStdIn = 5, + typeStdOut = 6, + typeStdErr = 7, + typeData = 8, + typeGetValues = 9, + typeGetValuesResult = 10 + }; + + enum Role + { + roleResponder = 1, + roleAuthorizer = 2, + roleFilter = 3 + }; + + enum Flags + { + flagsKeepConn = 1 + }; + + enum Status + { + statusRequestComplete = 0, + statusCantMpxConn = 1, + statusOverloaded = 2, + statusUnknownRole = 3 + }; + + typedef struct { + uint8_t uVersion; + uint8_t uType; + uint16_t uRequestId; + uint16_t uContentLength; + uint8_t uPaddingLength; + uint8_t uReserved; + } Record; + + typedef struct { + uint16_t uRole; + uint8_t uFlags; + uint8_t reserved[5]; + } BeginRequestBody; + + typedef struct { + uint32_t uStatus; + uint8_t uProtocolStatus; + uint8_t reserved[3]; + } EndRequestBody; + + typedef struct Channel { + Channel() : uFlags( 0 ) { } + StrHash hParams; + Bu::String sStdIn; + Bu::String sData; + uint8_t uFlags; + } Channel; + + enum ChannelFlags + { + chflgParamsDone = 0x01, + chflgStdInDone = 0x02, + chflgDataDone = 0x04, + + chflgAllDone = 0x03 + }; + + virtual void run(); + + void stopRunning() { bRunning = false; } + + virtual void onInit() { }; + virtual int onRequest( const StrHash &hParams, + const Bu::String &sStdIn, Bu::Stream &sStdOut, + Bu::Stream &sStdErr )=0; + virtual void onUninit() { }; + + private: + void read( Bu::TcpSocket &s, Record &r ); + void read( Bu::TcpSocket &s, BeginRequestBody &b ); + uint32_t readLen( Bu::TcpSocket &s, uint16_t &uUsed ); + void readPair( Bu::TcpSocket &s, StrHash &hParams, uint16_t &uUsed ); + + void write( Bu::TcpSocket &s, Record r ); + void write( Bu::TcpSocket &s, EndRequestBody b ); + + bool hasChannel( int iChan ); + + private: + Bu::TcpServerSocket *pSrv; + bool bRunning; + Bu::Array aChannel; + }; + + Bu::Formatter &operator<<( Bu::Formatter &f, const Bu::FastCgi::Record &r ); }; #endif diff --git a/src/experimental/filesystem.h b/src/experimental/filesystem.h index 0c992a5..d25cb67 100644 --- a/src/experimental/filesystem.h +++ b/src/experimental/filesystem.h @@ -3,22 +3,22 @@ namespace Bu { - /** - * Represents an abstract baseclass for any file organization structure. - * If you're looking for acessing a local filesystem, try Bu::Dir. This - * is used to make switching between different types of filesystems - * seamless. FileSystems could be anything that organizes and grants - * access to file data, local filesystems, FTP servers, zip or myriadfs - * files, etc. - */ - class FileSystem - { - public: - FileSystem(); - virtual ~FileSystem(); + /** + * Represents an abstract baseclass for any file organization structure. + * If you're looking for acessing a local filesystem, try Bu::Dir. This + * is used to make switching between different types of filesystems + * seamless. FileSystems could be anything that organizes and grants + * access to file data, local filesystems, FTP servers, zip or myriadfs + * files, etc. + */ + class FileSystem + { + public: + FileSystem(); + virtual ~FileSystem(); - - }; + + }; }; #endif diff --git a/src/experimental/httpget.cpp b/src/experimental/httpget.cpp index 7a8a89a..70c722c 100644 --- a/src/experimental/httpget.cpp +++ b/src/experimental/httpget.cpp @@ -8,11 +8,11 @@ #include "bu/httpget.h" Bu::HttpGet::HttpGet( const Bu::Url &uSrc, const Bu::String &sMethod ) : - uSrc( uSrc ), - sMethod( sMethod ), - sSrv( uSrc.getHost(), uSrc.getPort() ) + uSrc( uSrc ), + sMethod( sMethod ), + sSrv( uSrc.getHost(), uSrc.getPort() ) { - sSrv.write( sMethod + " " + uSrc.getFullPath() + " HTTP/1.1\r\n" ); + sSrv.write( sMethod + " " + uSrc.getFullPath() + " HTTP/1.1\r\n" ); } Bu::HttpGet::~HttpGet() @@ -25,28 +25,28 @@ void Bu::HttpGet::close() void Bu::HttpGet::get() { - for( MimeHash::iterator i = hMimeOut.begin(); i; i++ ) - { - sSrv.write( i.getKey() + ": " + i.getValue() + "\r\n" ); - } - sSrv.write("\r\n", 2 ); + for( MimeHash::iterator i = hMimeOut.begin(); i; i++ ) + { + sSrv.write( i.getKey() + ": " + i.getValue() + "\r\n" ); + } + sSrv.write("\r\n", 2 ); -// sSrv.read( +// sSrv.read( } Bu::size Bu::HttpGet::read( void * /*pBuf*/, Bu::size /*nBytes*/ ) { - return 0; + return 0; } Bu::size Bu::HttpGet::write( const void * /*pBuf*/, Bu::size /*nBytes*/ ) { - return 0; + return 0; } Bu::size Bu::HttpGet::tell() { - return 0; + return 0; } void Bu::HttpGet::seek( Bu::size ) @@ -63,12 +63,12 @@ void Bu::HttpGet::setPosEnd( Bu::size ) bool Bu::HttpGet::isEos() { - return false; + return false; } bool Bu::HttpGet::isOpen() { - return true; + return true; } void Bu::HttpGet::flush() @@ -77,32 +77,32 @@ void Bu::HttpGet::flush() bool Bu::HttpGet::canRead() { - return true; + return true; } bool Bu::HttpGet::canWrite() { - return false; + return false; } bool Bu::HttpGet::isReadable() { - return true; + return true; } bool Bu::HttpGet::isWritable() { - return false; + return false; } bool Bu::HttpGet::isSeekable() { - return false; + return false; } bool Bu::HttpGet::isBlocking() { - return true; + return true; } void Bu::HttpGet::setBlocking( bool /*bBlocking*/ ) @@ -111,16 +111,16 @@ void Bu::HttpGet::setBlocking( bool /*bBlocking*/ ) Bu::size Bu::HttpGet::getSize() const { - return 0; + return 0; } Bu::size Bu::HttpGet::getBlockSize() const { - return 0; + return 0; } Bu::String Bu::HttpGet::getLocation() const { - return uSrc.getUrl(); + return uSrc.getUrl(); } diff --git a/src/experimental/httpget.h b/src/experimental/httpget.h index e8092e5..21e69d6 100644 --- a/src/experimental/httpget.h +++ b/src/experimental/httpget.h @@ -16,51 +16,51 @@ namespace Bu { - class HttpGet : public Bu::Stream - { - public: - HttpGet( const Bu::Url &uSrc, const Bu::String &sMethod="GET" ); - virtual ~HttpGet(); + class HttpGet : public Bu::Stream + { + public: + HttpGet( const Bu::Url &uSrc, const Bu::String &sMethod="GET" ); + virtual ~HttpGet(); - void get(); + void get(); - // From Bu::Stream - virtual void close(); - virtual Bu::size read( void *pBuf, Bu::size nBytes ); - virtual Bu::size write( const void *pBuf, Bu::size nBytes ); - using Stream::write; + // From Bu::Stream + virtual void close(); + virtual Bu::size read( void *pBuf, Bu::size nBytes ); + virtual Bu::size write( const void *pBuf, Bu::size nBytes ); + using Stream::write; - virtual Bu::size tell(); - virtual void seek( Bu::size offset ); - virtual void setPos( Bu::size pos ); - virtual void setPosEnd( Bu::size pos ); - virtual bool isEos(); - virtual bool isOpen(); + virtual Bu::size tell(); + virtual void seek( Bu::size offset ); + virtual void setPos( Bu::size pos ); + virtual void setPosEnd( Bu::size pos ); + virtual bool isEos(); + virtual bool isOpen(); - virtual void flush(); + virtual void flush(); - virtual bool canRead(); - virtual bool canWrite(); + virtual bool canRead(); + virtual bool canWrite(); - virtual bool isReadable(); - virtual bool isWritable(); - virtual bool isSeekable(); + virtual bool isReadable(); + virtual bool isWritable(); + virtual bool isSeekable(); - virtual bool isBlocking(); - virtual void setBlocking( bool bBlocking=true ); + virtual bool isBlocking(); + virtual void setBlocking( bool bBlocking=true ); - virtual size getSize() const; - virtual size getBlockSize() const; - virtual Bu::String getLocation() const; + virtual size getSize() const; + virtual size getBlockSize() const; + virtual Bu::String getLocation() const; - private: - Bu::Url uSrc; - Bu::String sMethod; - Bu::TcpSocket sSrv; - typedef Bu::Hash MimeHash; - MimeHash hMimeIn; - MimeHash hMimeOut; - }; + private: + Bu::Url uSrc; + Bu::String sMethod; + Bu::TcpSocket sSrv; + typedef Bu::Hash MimeHash; + MimeHash hMimeIn; + MimeHash hMimeOut; + }; }; #endif diff --git a/src/experimental/lexer.cpp b/src/experimental/lexer.cpp index 48ee017..ae95d09 100644 --- a/src/experimental/lexer.cpp +++ b/src/experimental/lexer.cpp @@ -18,23 +18,23 @@ Bu::Lexer::~Lexer() } Bu::Lexer::Token::Token() : - iToken( -1 ) + iToken( -1 ) { } Bu::Lexer::Token::Token( Bu::Lexer::TokenType iToken ) : - iToken( iToken ) + iToken( iToken ) { } Bu::String Bu::Lexer::tokenToString( const Bu::Lexer::Token &t ) { - Bu::MemBuf mb; - Bu::Formatter f( mb ); - f << "<" << t.iToken << ">"; - if( t.vExtra.isSet() ) - f << " (" << t.vExtra << ")"; + Bu::MemBuf mb; + Bu::Formatter f( mb ); + f << "<" << t.iToken << ">"; + if( t.vExtra.isSet() ) + f << " (" << t.vExtra << ")"; - return mb.getString(); + return mb.getString(); } diff --git a/src/experimental/lexer.h b/src/experimental/lexer.h index 69f4106..273f3cf 100644 --- a/src/experimental/lexer.h +++ b/src/experimental/lexer.h @@ -12,47 +12,47 @@ namespace Bu { - class Stream; - - /** - * The base class for creating a lexical analyzer. This is designed to work - * in tandem with the Bu::Parser class, which uses this to tokenize textual - * input. It can be used by just about anything that cares about tokens - * more than raw input, though. - */ - class Lexer - { - public: - Lexer(); - virtual ~Lexer(); - - typedef int TokenType; - - class Token - { - public: - Token(); - Token( TokenType iToken ); - - template - Token( TokenType iToken, const t &v ) : - iToken( iToken )//, -// vExtra( v ) - { - vExtra = v; - } - TokenType iToken; - Bu::Variant vExtra; - int iStartCol; - int iStartRow; - int iEndCol; - int iEndRow; - }; - - virtual Token *nextToken()=0; - - virtual Bu::String tokenToString( const Token &t ); - }; + class Stream; + + /** + * The base class for creating a lexical analyzer. This is designed to work + * in tandem with the Bu::Parser class, which uses this to tokenize textual + * input. It can be used by just about anything that cares about tokens + * more than raw input, though. + */ + class Lexer + { + public: + Lexer(); + virtual ~Lexer(); + + typedef int TokenType; + + class Token + { + public: + Token(); + Token( TokenType iToken ); + + template + Token( TokenType iToken, const t &v ) : + iToken( iToken )//, +// vExtra( v ) + { + vExtra = v; + } + TokenType iToken; + Bu::Variant vExtra; + int iStartCol; + int iStartRow; + int iEndCol; + int iEndRow; + }; + + virtual Token *nextToken()=0; + + virtual Bu::String tokenToString( const Token &t ); + }; }; #endif diff --git a/src/experimental/parser.cpp b/src/experimental/parser.cpp index 9f10256..5d0d7eb 100644 --- a/src/experimental/parser.cpp +++ b/src/experimental/parser.cpp @@ -21,231 +21,231 @@ Bu::Parser::~Parser() void Bu::Parser::pushLexer( Lexer *pLex ) { - sLexer.push( pLex ); + sLexer.push( pLex ); } void Bu::Parser::popLexer() { - delete sLexer.peekPop(); + delete sLexer.peekPop(); } Lexer::Token *Bu::Parser::popToken() { - return sToken.peekPop(); + return sToken.peekPop(); } void Bu::Parser::pushToken( Lexer::Token *pTok ) { - sToken.push( pTok ); + sToken.push( pTok ); } void Bu::Parser::parse() { - int iCurNt = iRootNonTerminal; - Lexer::Token *ptCur = sLexer.peek()->nextToken(); - sio << "Token(a): " << sLexer.peek()->tokenToString( *ptCur ) << sio.nl; - selectProduction( iCurNt, ptCur ); - - while( !sState.isEmpty() ) - { - switch( (*sState.peek()).eType ) - { - case State::typeTerminal: - sio << "terminal: " << ptCur->iToken << " == " - << (*sState.peek()).iIndex << sio.nl; - if( ptCur->iToken == (*sState.peek()).iIndex ) - { - advanceState(); - delete ptCur; - ptCur = sLexer.peek()->nextToken(); - sio << "Token(b): " << sLexer.peek()->tokenToString( *ptCur ) << sio.nl; - } - else - { - throw Bu::ExceptionBase("Error parsing code."); - } - break; - - case State::typeTerminalPush: - sio << "terminalpush: " << ptCur->iToken << " == " - << (*sState.peek()).iIndex << sio.nl; - if( ptCur->iToken == (*sState.peek()).iIndex ) - { - advanceState(); - sToken.push( ptCur ); - - ptCur = sLexer.peek()->nextToken(); - sio << "Token(c): " << sLexer.peek()->tokenToString( *ptCur ) << sio.nl; - } - else - { - throw Bu::ExceptionBase("Error parsing code."); - } - break; - - case State::typeNonTerminal: - sio << "nonterminal: " << ptCur->iToken << " --> " - << (*sState.peek()).iIndex << sio.nl; - { - int iNt = (*sState.peek()).iIndex; - sio << "Current state: " << *sState.peek() << sio.nl; - if( !selectProduction( iNt, ptCur ) ) - { - throw Bu::ExceptionBase("Error parsing code."); - } - } - break; - - case State::typeReduction: - sio << "reduction" << sio.nl; - aReduction[(*sState.peek()).iIndex]( *this ); - advanceState(); - break; - } - } + int iCurNt = iRootNonTerminal; + Lexer::Token *ptCur = sLexer.peek()->nextToken(); + sio << "Token(a): " << sLexer.peek()->tokenToString( *ptCur ) << sio.nl; + selectProduction( iCurNt, ptCur ); + + while( !sState.isEmpty() ) + { + switch( (*sState.peek()).eType ) + { + case State::typeTerminal: + sio << "terminal: " << ptCur->iToken << " == " + << (*sState.peek()).iIndex << sio.nl; + if( ptCur->iToken == (*sState.peek()).iIndex ) + { + advanceState(); + delete ptCur; + ptCur = sLexer.peek()->nextToken(); + sio << "Token(b): " << sLexer.peek()->tokenToString( *ptCur ) << sio.nl; + } + else + { + throw Bu::ExceptionBase("Error parsing code."); + } + break; + + case State::typeTerminalPush: + sio << "terminalpush: " << ptCur->iToken << " == " + << (*sState.peek()).iIndex << sio.nl; + if( ptCur->iToken == (*sState.peek()).iIndex ) + { + advanceState(); + sToken.push( ptCur ); + + ptCur = sLexer.peek()->nextToken(); + sio << "Token(c): " << sLexer.peek()->tokenToString( *ptCur ) << sio.nl; + } + else + { + throw Bu::ExceptionBase("Error parsing code."); + } + break; + + case State::typeNonTerminal: + sio << "nonterminal: " << ptCur->iToken << " --> " + << (*sState.peek()).iIndex << sio.nl; + { + int iNt = (*sState.peek()).iIndex; + sio << "Current state: " << *sState.peek() << sio.nl; + if( !selectProduction( iNt, ptCur ) ) + { + throw Bu::ExceptionBase("Error parsing code."); + } + } + break; + + case State::typeReduction: + sio << "reduction" << sio.nl; + aReduction[(*sState.peek()).iIndex]( *this ); + advanceState(); + break; + } + } } bool Bu::Parser::selectProduction( int iNt, Lexer::Token *ptCur ) { - NonTerminal &nt = aNonTerminal[iNt]; - int j = 0; - for( NonTerminal::ProductionList::iterator i = nt.lProduction.begin(); - i; i++,j++ ) - { - if( (*i).isEmpty() ) - continue; - sio << "-->(Attempting production " << iNt << ":" << j << ": " - << (*i).first() << ")" << sio.nl; - if( (*i).first().eType == State::typeTerminal || - (*i).first().eType == State::typeTerminalPush ) - { - if( (*i).first().iIndex == ptCur->iToken ) - { - sState.push( (*i).begin() ); - sio.incIndent(); - sio << "Pushing production " << j << " from nt " << iNt - << sio.nl; - return true; - } - } - else if( (*i).first().eType == State::typeNonTerminal ) - { - sState.push( (*i).begin() ); - sio.incIndent(); - sio << "Pushing production " << j << " from nt " << iNt - << " as test." << sio.nl; - if( !selectProduction( (*i).first().iIndex, ptCur ) ) - { - sio.decIndent(); - sState.pop(); - sio << "Production " << j << " from nt " << iNt - << " didn't work out." << sio.nl; - } - else - { - return true; - } - } - } - if( nt.bCanSkip ) - { - sio << "Nothing matches, skipping non-terminal." << sio.nl; - advanceState(); - return true; - } - sio << "-->(Found nothing)" << sio.nl; - return false; + NonTerminal &nt = aNonTerminal[iNt]; + int j = 0; + for( NonTerminal::ProductionList::iterator i = nt.lProduction.begin(); + i; i++,j++ ) + { + if( (*i).isEmpty() ) + continue; + sio << "-->(Attempting production " << iNt << ":" << j << ": " + << (*i).first() << ")" << sio.nl; + if( (*i).first().eType == State::typeTerminal || + (*i).first().eType == State::typeTerminalPush ) + { + if( (*i).first().iIndex == ptCur->iToken ) + { + sState.push( (*i).begin() ); + sio.incIndent(); + sio << "Pushing production " << j << " from nt " << iNt + << sio.nl; + return true; + } + } + else if( (*i).first().eType == State::typeNonTerminal ) + { + sState.push( (*i).begin() ); + sio.incIndent(); + sio << "Pushing production " << j << " from nt " << iNt + << " as test." << sio.nl; + if( !selectProduction( (*i).first().iIndex, ptCur ) ) + { + sio.decIndent(); + sState.pop(); + sio << "Production " << j << " from nt " << iNt + << " didn't work out." << sio.nl; + } + else + { + return true; + } + } + } + if( nt.bCanSkip ) + { + sio << "Nothing matches, skipping non-terminal." << sio.nl; + advanceState(); + return true; + } + sio << "-->(Found nothing)" << sio.nl; + return false; } void Bu::Parser::advanceState() { - if( sState.isEmpty() ) - return; - - sState.peek()++; - if( !sState.peek() ) - { - sio.decIndent(); - sState.pop(); - sio << "State advanced, End of production." << sio.nl; - advanceState(); - return; - } - sio << "State advanced, now: " << *(sState.peek()) << sio.nl; + if( sState.isEmpty() ) + return; + + sState.peek()++; + if( !sState.peek() ) + { + sio.decIndent(); + sState.pop(); + sio << "State advanced, End of production." << sio.nl; + advanceState(); + return; + } + sio << "State advanced, now: " << *(sState.peek()) << sio.nl; } void Bu::Parser::setRootNonTerminal( int iRoot ) { - iRootNonTerminal = iRoot; + iRootNonTerminal = iRoot; } void Bu::Parser::setRootNonTerminal( const Bu::String &sRoot ) { - setRootNonTerminal( hNonTerminalName.get( sRoot ) ); + setRootNonTerminal( hNonTerminalName.get( sRoot ) ); } int Bu::Parser::addNonTerminal( const Bu::String &sName, NonTerminal &nt ) { - int iId = aNonTerminal.getSize(); - aNonTerminal.append( nt ); - hNonTerminalName.insert( sName, iId ); - sio << "nt '" << sName << "' = " << iId << sio.nl; - return iId; + int iId = aNonTerminal.getSize(); + aNonTerminal.append( nt ); + hNonTerminalName.insert( sName, iId ); + sio << "nt '" << sName << "' = " << iId << sio.nl; + return iId; } int Bu::Parser::addNonTerminal( const Bu::String &sName ) { - int iId = aNonTerminal.getSize(); - aNonTerminal.append( NonTerminal() ); - hNonTerminalName.insert( sName, iId ); - sio << "nt '" << sName << "' = " << iId << sio.nl; - return iId; + int iId = aNonTerminal.getSize(); + aNonTerminal.append( NonTerminal() ); + hNonTerminalName.insert( sName, iId ); + sio << "nt '" << sName << "' = " << iId << sio.nl; + return iId; } void Bu::Parser::setNonTerminal( const Bu::String &sName, NonTerminal &nt ) { - aNonTerminal[hNonTerminalName.get(sName)] = nt; + aNonTerminal[hNonTerminalName.get(sName)] = nt; } int Bu::Parser::getNonTerminalId( const Bu::String &sName ) { - return hNonTerminalName.get( sName ); + return hNonTerminalName.get( sName ); } bool Bu::Parser::hasNonTerminal( const Bu::String &sName ) { - return hNonTerminalName.has( sName ); + return hNonTerminalName.has( sName ); } int Bu::Parser::addReduction( const Bu::String &sName, const Reduction &r ) { - int iId = aReduction.getSize(); - aReduction.append( r ); - hReductionName.insert( sName, iId ); - return iId; + int iId = aReduction.getSize(); + aReduction.append( r ); + hReductionName.insert( sName, iId ); + return iId; } int Bu::Parser::addReduction( const Bu::String &sName ) { - int iId = aReduction.getSize(); - aReduction.append( Reduction() ); - hReductionName.insert( sName, iId ); - return iId; + int iId = aReduction.getSize(); + aReduction.append( Reduction() ); + hReductionName.insert( sName, iId ); + return iId; } void Bu::Parser::setReduction( const Bu::String &sName, const Reduction &r ) { - aReduction[hReductionName.get(sName)] = r; + aReduction[hReductionName.get(sName)] = r; } int Bu::Parser::getReductionId( const Bu::String &sName ) { - return hReductionName.get( sName ); + return hReductionName.get( sName ); } bool Bu::Parser::hasReduction( const Bu::String &sName ) { - return hReductionName.has( sName ); + return hReductionName.has( sName ); } // @@ -253,8 +253,8 @@ bool Bu::Parser::hasReduction( const Bu::String &sName ) // Bu::Parser::State::State( Bu::Parser::State::Type eType, int iIndex ) : - eType( eType ), - iIndex( iIndex ) + eType( eType ), + iIndex( iIndex ) { } @@ -267,7 +267,7 @@ Bu::Parser::State::~State() // Bu::Parser::NonTerminal::NonTerminal() : - bCanSkip( false ) + bCanSkip( false ) { } @@ -277,35 +277,35 @@ Bu::Parser::NonTerminal::~NonTerminal() void Bu::Parser::NonTerminal::addProduction( Production p ) { - lProduction.append( p ); + lProduction.append( p ); } void Bu::Parser::NonTerminal::setCanSkip() { - bCanSkip = true; + bCanSkip = true; } Bu::Formatter &Bu::operator<<( Bu::Formatter &f, Bu::Parser::State::Type t ) { - switch( t ) - { - case Bu::Parser::State::typeTerminal: - return f << "typeTerminal"; + switch( t ) + { + case Bu::Parser::State::typeTerminal: + return f << "typeTerminal"; - case Bu::Parser::State::typeTerminalPush: - return f << "typeTerminalPush"; + case Bu::Parser::State::typeTerminalPush: + return f << "typeTerminalPush"; - case Bu::Parser::State::typeNonTerminal: - return f << "typeNonTerminal"; + case Bu::Parser::State::typeNonTerminal: + return f << "typeNonTerminal"; - case Bu::Parser::State::typeReduction: - return f << "typeReduction"; - } - return f << "***error***"; + case Bu::Parser::State::typeReduction: + return f << "typeReduction"; + } + return f << "***error***"; } Bu::Formatter &Bu::operator<<( Bu::Formatter &f, const Bu::Parser::State &s ) { - return f << "{" << s.eType << ": " << s.iIndex << "}"; + return f << "{" << s.eType << ": " << s.iIndex << "}"; } diff --git a/src/experimental/parser.h b/src/experimental/parser.h index 953202d..50b6afb 100644 --- a/src/experimental/parser.h +++ b/src/experimental/parser.h @@ -18,115 +18,115 @@ namespace Bu { - /** - * The base framework for a LR(1) grammar parser. Provided a proper set of - * ParserStates this will prase any input the lexer can provide. - */ - class Parser - { - public: - Parser(); - virtual ~Parser(); - - /** - * When a Lexer is pushed onto the stack it becomes the source for - * future tokens read by the parser until it is popped off the stack. - * The Parser takes ownership of every Lexer pushed onto the stack, - * and will delete it when it is popped off the stack. - */ - void pushLexer( Lexer *pLex ); - - /** - * Pop a lexer off the stack, and delete it. - */ - void popLexer(); - - Lexer::Token *popToken(); - void pushToken( Lexer::Token *pTok ); - - /** - * Execute a parse. - */ - void parse(); - - void setRootNonTerminal( int iRoot ); - void setRootNonTerminal( const Bu::String &sRoot ); - - typedef Bu::Signal1 Reduction; - - /** - * Represents a possible state, either a terminal or non-terminal symbol - * in a Production. - */ - class State - { - public: - enum Type - { - typeTerminal, - typeTerminalPush, - typeNonTerminal, - typeReduction - }; - - State( Type eType, int iIndex ); - virtual ~State(); - - //private: - Type eType; - int iIndex; - }; - - typedef Bu::List Production; - - class NonTerminal - { - public: - NonTerminal(); - virtual ~NonTerminal(); - - void addProduction( Production p ); - void setCanSkip(); - -// private: - typedef Bu::List ProductionList; - ProductionList lProduction; - bool bCanSkip; - }; - - int addNonTerminal( const Bu::String &sName, NonTerminal &nt ); - int addNonTerminal( const Bu::String &sName ); - void setNonTerminal( const Bu::String &sName, NonTerminal &nt ); - int getNonTerminalId( const Bu::String &sName ); - bool hasNonTerminal( const Bu::String &sName ); - - int addReduction( const Bu::String &sName, const Reduction &r ); - int addReduction( const Bu::String &sName ); - void setReduction( const Bu::String &sName, const Reduction &r ); - int getReductionId( const Bu::String &sName ); - bool hasReduction( const Bu::String &sName ); - - private: - bool selectProduction( int iNt, Lexer::Token *ptCur ); - void advanceState(); - - private: - typedef Bu::List LexerStack; - typedef Bu::List TokenStack; - typedef Bu::List StateStack; - typedef Bu::Array ReductionArray; - typedef Bu::Hash NameIndexHash; - typedef Bu::Array NonTerminalArray; - - LexerStack sLexer; - TokenStack sToken; - StateStack sState; - ReductionArray aReduction; - NameIndexHash hReductionName; - NonTerminalArray aNonTerminal; - NameIndexHash hNonTerminalName; - int iRootNonTerminal; - }; + /** + * The base framework for a LR(1) grammar parser. Provided a proper set of + * ParserStates this will prase any input the lexer can provide. + */ + class Parser + { + public: + Parser(); + virtual ~Parser(); + + /** + * When a Lexer is pushed onto the stack it becomes the source for + * future tokens read by the parser until it is popped off the stack. + * The Parser takes ownership of every Lexer pushed onto the stack, + * and will delete it when it is popped off the stack. + */ + void pushLexer( Lexer *pLex ); + + /** + * Pop a lexer off the stack, and delete it. + */ + void popLexer(); + + Lexer::Token *popToken(); + void pushToken( Lexer::Token *pTok ); + + /** + * Execute a parse. + */ + void parse(); + + void setRootNonTerminal( int iRoot ); + void setRootNonTerminal( const Bu::String &sRoot ); + + typedef Bu::Signal1 Reduction; + + /** + * Represents a possible state, either a terminal or non-terminal symbol + * in a Production. + */ + class State + { + public: + enum Type + { + typeTerminal, + typeTerminalPush, + typeNonTerminal, + typeReduction + }; + + State( Type eType, int iIndex ); + virtual ~State(); + + //private: + Type eType; + int iIndex; + }; + + typedef Bu::List Production; + + class NonTerminal + { + public: + NonTerminal(); + virtual ~NonTerminal(); + + void addProduction( Production p ); + void setCanSkip(); + +// private: + typedef Bu::List ProductionList; + ProductionList lProduction; + bool bCanSkip; + }; + + int addNonTerminal( const Bu::String &sName, NonTerminal &nt ); + int addNonTerminal( const Bu::String &sName ); + void setNonTerminal( const Bu::String &sName, NonTerminal &nt ); + int getNonTerminalId( const Bu::String &sName ); + bool hasNonTerminal( const Bu::String &sName ); + + int addReduction( const Bu::String &sName, const Reduction &r ); + int addReduction( const Bu::String &sName ); + void setReduction( const Bu::String &sName, const Reduction &r ); + int getReductionId( const Bu::String &sName ); + bool hasReduction( const Bu::String &sName ); + + private: + bool selectProduction( int iNt, Lexer::Token *ptCur ); + void advanceState(); + + private: + typedef Bu::List LexerStack; + typedef Bu::List TokenStack; + typedef Bu::List StateStack; + typedef Bu::Array ReductionArray; + typedef Bu::Hash NameIndexHash; + typedef Bu::Array NonTerminalArray; + + LexerStack sLexer; + TokenStack sToken; + StateStack sState; + ReductionArray aReduction; + NameIndexHash hReductionName; + NonTerminalArray aNonTerminal; + NameIndexHash hNonTerminalName; + int iRootNonTerminal; + }; Bu::Formatter &operator<<( Bu::Formatter &f, Bu::Parser::State::Type t ); Bu::Formatter &operator<<( Bu::Formatter &f, const Bu::Parser::State &s ); }; diff --git a/src/experimental/regex.cpp b/src/experimental/regex.cpp index de24935..dbe0e85 100644 --- a/src/experimental/regex.cpp +++ b/src/experimental/regex.cpp @@ -13,83 +13,83 @@ #define aSubStr ((regmatch_t *)paSubStr) Bu::RegEx::RegEx() : - pRegEx( NULL ), - bCompiled( false ), - paSubStr( NULL ) + pRegEx( NULL ), + bCompiled( false ), + paSubStr( NULL ) { } Bu::RegEx::RegEx( const Bu::String &sSrc ) : - pRegEx( NULL ), - bCompiled( false ), - paSubStr( NULL ) + pRegEx( NULL ), + bCompiled( false ), + paSubStr( NULL ) { - compile( sSrc ); + compile( sSrc ); } Bu::RegEx::~RegEx() { - if( bCompiled ) - { - regfree( re ); - delete re; - delete[] aSubStr; - } + if( bCompiled ) + { + regfree( re ); + delete re; + delete[] aSubStr; + } } void Bu::RegEx::compile( const Bu::String &sSrc ) { - if( bCompiled ) - { - regfree( re ); - delete re; - delete[] aSubStr; - bCompiled = false; - } - pRegEx = (void *)(new regex_t); + if( bCompiled ) + { + regfree( re ); + delete re; + delete[] aSubStr; + bCompiled = false; + } + pRegEx = (void *)(new regex_t); - int nErr = regcomp( re, sSrc.getStr(), REG_EXTENDED|REG_NEWLINE ); - if( nErr ) - { - size_t length = regerror( nErr, re, NULL, 0 ); - char *buffer = new char[length]; - (void) regerror( nErr, re, buffer, length ); - Bu::String s( buffer ); - delete[] buffer; - throw "???"; // BuildException( s.getStr() ); - } - bCompiled = true; - this->sSrc = sSrc; + int nErr = regcomp( re, sSrc.getStr(), REG_EXTENDED|REG_NEWLINE ); + if( nErr ) + { + size_t length = regerror( nErr, re, NULL, 0 ); + char *buffer = new char[length]; + (void) regerror( nErr, re, buffer, length ); + Bu::String s( buffer ); + delete[] buffer; + throw "???"; // BuildException( s.getStr() ); + } + bCompiled = true; + this->sSrc = sSrc; - nSubStr = re->re_nsub+1; - paSubStr = (void *)(new regmatch_t[nSubStr]); + nSubStr = re->re_nsub+1; + paSubStr = (void *)(new regmatch_t[nSubStr]); } int Bu::RegEx::getNumSubStrings() { - return nSubStr; + return nSubStr; } bool Bu::RegEx::execute( const Bu::String &sSrc ) { - sTest = sSrc; - if( regexec( re, sSrc.getStr(), nSubStr, aSubStr, 0 ) ) - return false; - return true; + sTest = sSrc; + if( regexec( re, sSrc.getStr(), nSubStr, aSubStr, 0 ) ) + return false; + return true; } void Bu::RegEx::getSubStringRange( int nIndex, int &iStart, int &iEnd ) { - iStart = aSubStr[nIndex].rm_so; - iEnd = aSubStr[nIndex].rm_eo; + iStart = aSubStr[nIndex].rm_so; + iEnd = aSubStr[nIndex].rm_eo; } Bu::String Bu::RegEx::getSubString( int nIndex ) { -// regmatch_t *Subs = aSubStr; - return Bu::String( - sTest.getStr()+aSubStr[nIndex].rm_so, - aSubStr[nIndex].rm_eo - aSubStr[nIndex].rm_so - ); +// regmatch_t *Subs = aSubStr; + return Bu::String( + sTest.getStr()+aSubStr[nIndex].rm_so, + aSubStr[nIndex].rm_eo - aSubStr[nIndex].rm_so + ); } diff --git a/src/experimental/regex.h b/src/experimental/regex.h index c83ebe8..e723450 100644 --- a/src/experimental/regex.h +++ b/src/experimental/regex.h @@ -14,31 +14,31 @@ namespace Bu { - class RegEx - { - public: - RegEx(); - RegEx( const Bu::String &sSrc ); - virtual ~RegEx(); + class RegEx + { + public: + RegEx(); + RegEx( const Bu::String &sSrc ); + virtual ~RegEx(); - void compile( const Bu::String &sSrc ); - int getNumSubStrings(); - bool execute( const Bu::String &sSrc ); - void getSubStringRange( int nIndex, int &iStart, int &iEnd ); - Bu::String getSubString( int nIndex ); - const Bu::String &getSource() - { - return sSrc; - } + void compile( const Bu::String &sSrc ); + int getNumSubStrings(); + bool execute( const Bu::String &sSrc ); + void getSubStringRange( int nIndex, int &iStart, int &iEnd ); + Bu::String getSubString( int nIndex ); + const Bu::String &getSource() + { + return sSrc; + } - private: - Bu::String sSrc; - Bu::String sTest; - void *pRegEx; - bool bCompiled; - int nSubStr; - void *paSubStr; - }; + private: + Bu::String sSrc; + Bu::String sTest; + void *pRegEx; + bool bCompiled; + int nSubStr; + void *paSubStr; + }; }; #endif diff --git a/src/experimental/regexengine.h b/src/experimental/regexengine.h index ec181c1..133d418 100644 --- a/src/experimental/regexengine.h +++ b/src/experimental/regexengine.h @@ -7,136 +7,136 @@ namespace Bu { - template class RegExEngine; - - template - class RegExEngineCore - { - friend class RegExEngine; - friend class SharedCore, RegExEngineCore >; - private: - RegExEngineCore() - { - } - - virtual ~RegExEngineCore() - { - } - - class Range - { - public: - Range( chr cLower, chr cUpper, int iTrgState ) : - cLower( cLower ), cUpper( cUpper ), iTrgState( iTrgState ) - { - } - - chr cLower; - chr cUpper; - int iTrgState; - }; - - class State - { - public: - Bu::Array aRange; - }; - - int addState() - { - aState.append( State() ); - return aState.getSize()-1; - } - - void addCompletion( int iState, chr cLower, chr cUpper, int iTrgState ) - { - aState[iState].aRange.append( Range( cLower, cUpper, iTrgState ) ); - } - - template - bool match( const str &sIn, int &iSize, int &iCompletion ) - { - bool bMatch; - int iState = 0; - iSize = 0; - for( typename str::const_iterator i = sIn.begin(); i; i++ ) - { - Bu::sio << "Finding char " << *i << " in state " << iState - << ":" << Bu::sio.nl; - bMatch = false; - for( typename Bu::Array::iterator j = - aState[iState].aRange.begin(); j; j++ ) - { - Bu::sio << " Testing range " << (*j).cLower << " - " << (*j).cUpper << Bu::sio.nl; - if( *i >= (*j).cLower && *i <= (*j).cUpper ) - { - iState = (*j).iTrgState; - bMatch = true; - iSize++; - if( iState < 0 ) - { - iCompletion = iState; - return true; - } - } - } - if( bMatch == false ) - { - return false; - } - } - - iCompletion = 0; - return true; - } - - typedef Bu::Array StateArray; - StateArray aState; - }; - - template - class RegExEngine : public SharedCore, - RegExEngineCore > - { - private: - typedef class RegExEngine MyType; - typedef class RegExEngineCore Core; - typedef class Core::Range Range; - typedef class Core::State State; - - protected: - using SharedCore::core; - using SharedCore::_hardCopy; - using SharedCore::_resetCore; - using SharedCore::_allocateCore; - - public: - RegExEngine() - { - } - - virtual ~RegExEngine() - { - } - - int addState() - { - return core->addState(); - } - - void addCompletion( int iState, chr cLower, chr cUpper, int iTrgState ) - { - core->addCompletion( iState, cLower, cUpper, iTrgState ); - } - - template - bool match( const str &sIn, int &iSize, int &iCompletion ) - { - return core->match( sIn, iSize, iCompletion ); - } - - private: - }; + template class RegExEngine; + + template + class RegExEngineCore + { + friend class RegExEngine; + friend class SharedCore, RegExEngineCore >; + private: + RegExEngineCore() + { + } + + virtual ~RegExEngineCore() + { + } + + class Range + { + public: + Range( chr cLower, chr cUpper, int iTrgState ) : + cLower( cLower ), cUpper( cUpper ), iTrgState( iTrgState ) + { + } + + chr cLower; + chr cUpper; + int iTrgState; + }; + + class State + { + public: + Bu::Array aRange; + }; + + int addState() + { + aState.append( State() ); + return aState.getSize()-1; + } + + void addCompletion( int iState, chr cLower, chr cUpper, int iTrgState ) + { + aState[iState].aRange.append( Range( cLower, cUpper, iTrgState ) ); + } + + template + bool match( const str &sIn, int &iSize, int &iCompletion ) + { + bool bMatch; + int iState = 0; + iSize = 0; + for( typename str::const_iterator i = sIn.begin(); i; i++ ) + { + Bu::sio << "Finding char " << *i << " in state " << iState + << ":" << Bu::sio.nl; + bMatch = false; + for( typename Bu::Array::iterator j = + aState[iState].aRange.begin(); j; j++ ) + { + Bu::sio << " Testing range " << (*j).cLower << " - " << (*j).cUpper << Bu::sio.nl; + if( *i >= (*j).cLower && *i <= (*j).cUpper ) + { + iState = (*j).iTrgState; + bMatch = true; + iSize++; + if( iState < 0 ) + { + iCompletion = iState; + return true; + } + } + } + if( bMatch == false ) + { + return false; + } + } + + iCompletion = 0; + return true; + } + + typedef Bu::Array StateArray; + StateArray aState; + }; + + template + class RegExEngine : public SharedCore, + RegExEngineCore > + { + private: + typedef class RegExEngine MyType; + typedef class RegExEngineCore Core; + typedef class Core::Range Range; + typedef class Core::State State; + + protected: + using SharedCore::core; + using SharedCore::_hardCopy; + using SharedCore::_resetCore; + using SharedCore::_allocateCore; + + public: + RegExEngine() + { + } + + virtual ~RegExEngine() + { + } + + int addState() + { + return core->addState(); + } + + void addCompletion( int iState, chr cLower, chr cUpper, int iTrgState ) + { + core->addCompletion( iState, cLower, cUpper, iTrgState ); + } + + template + bool match( const str &sIn, int &iSize, int &iCompletion ) + { + return core->match( sIn, iSize, iCompletion ); + } + + private: + }; }; #endif diff --git a/src/experimental/xmlreader.cpp b/src/experimental/xmlreader.cpp index f11ac04..82f4684 100644 --- a/src/experimental/xmlreader.cpp +++ b/src/experimental/xmlreader.cpp @@ -11,13 +11,13 @@ namespace Bu { subExceptionDef( XmlException ) } Bu::XmlReader::XmlReader( Stream &rInput ) : - rInput( rInput ), - iCurToken( 0 ), - iNextToken( 0 ), - bIgnoreWS( true ) + rInput( rInput ), + iCurToken( 0 ), + iNextToken( 0 ), + bIgnoreWS( true ) { - nextToken(); - stDocument(); + nextToken(); + stDocument(); } Bu::XmlReader::~XmlReader() @@ -26,148 +26,148 @@ Bu::XmlReader::~XmlReader() void Bu::XmlReader::fillBuffer() { - if( rInput.isEos() ) - return; - char buf[1024]; - int iSize = rInput.read( buf, 1024 ); - sBuf.append( buf, iSize ); + if( rInput.isEos() ) + return; + char buf[1024]; + int iSize = rInput.read( buf, 1024 ); + sBuf.append( buf, iSize ); } void Bu::XmlReader::cleanupBuffer( int iUsed ) { - for( int j = 0; j < iUsed; j++ ) - { - if( sBuf[j] == '\n' ) - { - spNextToken.iLine++; - spNextToken.iChar = 1; - } - else - { - spNextToken.iChar++; - } - } - - printf("--Deleting %d bytes from front of buffer.\n", iUsed ); - sBuf.trimFront( iUsed ); + for( int j = 0; j < iUsed; j++ ) + { + if( sBuf[j] == '\n' ) + { + spNextToken.iLine++; + spNextToken.iChar = 1; + } + else + { + spNextToken.iChar++; + } + } + + printf("--Deleting %d bytes from front of buffer.\n", iUsed ); + sBuf.trimFront( iUsed ); } int Bu::XmlReader::nextToken() { - fillBuffer(); - - int iUsed = 1; - - iCurToken = iNextToken; - spCurToken = spNextToken; - - switch( sBuf[0] ) - { - case '<': - if( !strncmp( sBuf.getStr(), "' ) - { - iNextToken = tokXmlDeclEnd; - iUsed = 2; - } - else - { - iNextToken = '?'; - } - break; - - case ' ': - case '\t': - case '\n': - case '\r': - for( int j = 1;; j++ ) - { - if( j == sBuf.getSize() ) - { - if( rInput.isEos() ) - error("Reached end of input while waiting for whitespace to end."); - - fillBuffer(); - } - if( sBuf[j] == ' ' || sBuf[j] == '\t' || - sBuf[j] == '\n' || sBuf[j] == '\r' ) - iUsed++; - else - break; - } - sStr.clear(); - sStr.append( sBuf, iUsed ); - iNextToken = tokWS; - break; - - case '=': - iNextToken = sBuf[0]; - break; - - default: - if( (sBuf[0] >= 'a' && sBuf[0] <= 'z') || - (sBuf[0] >= 'A' && sBuf[0] <= 'Z') ) - { - for( int j = 1;; j++ ) - { - if( j == sBuf.getSize() ) - { - if( rInput.isEos() ) - error("Reached end of input while waiting for a string to end."); - - fillBuffer(); - } - if( (sBuf[j] >= 'a' && sBuf[j] <= 'z') || - (sBuf[j] >= 'A' && sBuf[j] <= 'Z') ) - iUsed++; - else - break; - } - sStr.clear(); - sStr.append( sBuf, iUsed ); - iNextToken = tokIdent; - } - } - - cleanupBuffer( iUsed ); - - return iCurToken; + fillBuffer(); + + int iUsed = 1; + + iCurToken = iNextToken; + spCurToken = spNextToken; + + switch( sBuf[0] ) + { + case '<': + if( !strncmp( sBuf.getStr(), "' ) + { + iNextToken = tokXmlDeclEnd; + iUsed = 2; + } + else + { + iNextToken = '?'; + } + break; + + case ' ': + case '\t': + case '\n': + case '\r': + for( int j = 1;; j++ ) + { + if( j == sBuf.getSize() ) + { + if( rInput.isEos() ) + error("Reached end of input while waiting for whitespace to end."); + + fillBuffer(); + } + if( sBuf[j] == ' ' || sBuf[j] == '\t' || + sBuf[j] == '\n' || sBuf[j] == '\r' ) + iUsed++; + else + break; + } + sStr.clear(); + sStr.append( sBuf, iUsed ); + iNextToken = tokWS; + break; + + case '=': + iNextToken = sBuf[0]; + break; + + default: + if( (sBuf[0] >= 'a' && sBuf[0] <= 'z') || + (sBuf[0] >= 'A' && sBuf[0] <= 'Z') ) + { + for( int j = 1;; j++ ) + { + if( j == sBuf.getSize() ) + { + if( rInput.isEos() ) + error("Reached end of input while waiting for a string to end."); + + fillBuffer(); + } + if( (sBuf[j] >= 'a' && sBuf[j] <= 'z') || + (sBuf[j] >= 'A' && sBuf[j] <= 'Z') ) + iUsed++; + else + break; + } + sStr.clear(); + sStr.append( sBuf, iUsed ); + iNextToken = tokIdent; + } + } + + cleanupBuffer( iUsed ); + + return iCurToken; } void Bu::XmlReader::error( const char *sMessage ) { - throw Bu::XmlException("%d:%d: %s", - spCurToken.iLine, spCurToken.iChar, sMessage ); + throw Bu::XmlException("%d:%d: %s", + spCurToken.iLine, spCurToken.iChar, sMessage ); } void Bu::XmlReader::stDocument() { - stProlog(); + stProlog(); } void Bu::XmlReader::stProlog() { - stXmlDecl(); + stXmlDecl(); } void Bu::XmlReader::stXmlDecl() { - if( nextToken() != tokXmlDeclHead ) - error("You must begin your xml file with a declaration: "); - if( nextToken() != tokIdent ) - error("A version comes first!"); - if( sStr != "version" ) - error("No, a version!"); + if( nextToken() != tokXmlDeclHead ) + error("You must begin your xml file with a declaration: "); + if( nextToken() != tokIdent ) + error("A version comes first!"); + if( sStr != "version" ) + error("No, a version!"); } diff --git a/src/experimental/xmlreader.h b/src/experimental/xmlreader.h index d4bad1e..9615cfb 100644 --- a/src/experimental/xmlreader.h +++ b/src/experimental/xmlreader.h @@ -13,52 +13,52 @@ namespace Bu { - class Stream; + class Stream; - subExceptionDecl( XmlException ); + subExceptionDecl( XmlException ); - class XmlReader - { - public: - XmlReader( Stream &rInput ); - virtual ~XmlReader(); + class XmlReader + { + public: + XmlReader( Stream &rInput ); + virtual ~XmlReader(); - private: - Stream &rInput; - int iCurToken; - int iNextToken; - Bu::String sBuf; - Bu::String sStr; - bool bIgnoreWS; - typedef struct StreamPos - { - StreamPos() : iLine( 1 ), iChar( 1 ) { } - int iLine; - int iChar; - } StreamPos; - StreamPos spCurToken; - StreamPos spNextToken; + private: + Stream &rInput; + int iCurToken; + int iNextToken; + Bu::String sBuf; + Bu::String sStr; + bool bIgnoreWS; + typedef struct StreamPos + { + StreamPos() : iLine( 1 ), iChar( 1 ) { } + int iLine; + int iChar; + } StreamPos; + StreamPos spCurToken; + StreamPos spNextToken; - enum - { - tokXmlDeclHead = 0x100, - tokXmlDeclEnd, - tokWS, - tokIdent, - tokString - }; + enum + { + tokXmlDeclHead = 0x100, + tokXmlDeclEnd, + tokWS, + tokIdent, + tokString + }; - void fillBuffer(); - void cleanupBuffer( int iUsed ); - int nextToken(); + void fillBuffer(); + void cleanupBuffer( int iUsed ); + int nextToken(); - void stDocument(); - void stProlog(); - void stXmlDecl(); + void stDocument(); + void stProlog(); + void stXmlDecl(); - void error( const char *sMessage ); - }; + void error( const char *sMessage ); + }; }; #endif diff --git a/src/extra/myriadfs.cpp b/src/extra/myriadfs.cpp index 867a595..6dc3ff4 100644 --- a/src/extra/myriadfs.cpp +++ b/src/extra/myriadfs.cpp @@ -28,307 +28,307 @@ int64_t iNextFileId = 0; #define TRACE extern "C" { - static int myriadfs_getattr( const char *sPath, struct stat *stbuf ) - { + static int myriadfs_getattr( const char *sPath, struct stat *stbuf ) + { #ifdef TRACE - printf("myriadfs_getattr(\"%s\", ... );\n", sPath ); + printf("myriadfs_getattr(\"%s\", ... );\n", sPath ); #endif - try - { - Bu::MyriadFs::Stat st; - pFs->stat( sPath, st ); - stbuf->st_ino = st.iNode; - stbuf->st_mode = st.uPerms; - stbuf->st_nlink = st.iLinks; - stbuf->st_uid = st.iUser; - stbuf->st_gid = st.iGroup; - stbuf->st_rdev = Bu::MyriadFs::devToSys( st.uDev ); - stbuf->st_size = st.iSize; - stbuf->st_blocks = 8; - stbuf->st_atime = st.iATime; - stbuf->st_mtime = st.iMTime; - stbuf->st_ctime = st.iCTime; - return 0; - } - catch(...) - { - return -ENOENT; - } - } + try + { + Bu::MyriadFs::Stat st; + pFs->stat( sPath, st ); + stbuf->st_ino = st.iNode; + stbuf->st_mode = st.uPerms; + stbuf->st_nlink = st.iLinks; + stbuf->st_uid = st.iUser; + stbuf->st_gid = st.iGroup; + stbuf->st_rdev = Bu::MyriadFs::devToSys( st.uDev ); + stbuf->st_size = st.iSize; + stbuf->st_blocks = 8; + stbuf->st_atime = st.iATime; + stbuf->st_mtime = st.iMTime; + stbuf->st_ctime = st.iCTime; + return 0; + } + catch(...) + { + return -ENOENT; + } + } - static int myriadfs_readdir( const char *sPath, void *buf, - fuse_fill_dir_t filler, off_t offset, struct fuse_file_info *fi ) - { + static int myriadfs_readdir( const char *sPath, void *buf, + fuse_fill_dir_t filler, off_t offset, struct fuse_file_info *fi ) + { #ifdef TRACE - printf("myriadfs_readdir(\"%s\", ... );\n", sPath ); + printf("myriadfs_readdir(\"%s\", ... );\n", sPath ); #endif - Bu::MyriadFs::Dir lDir = pFs->readDir( sPath ); - filler( buf, ".", NULL, 0 ); - filler( buf, "..", NULL, 0 ); - for( Bu::MyriadFs::Dir::iterator i = lDir.begin(); i; i++ ) - { - filler( buf, (*i).sName.getStr(), NULL, 0 ); - } + Bu::MyriadFs::Dir lDir = pFs->readDir( sPath ); + filler( buf, ".", NULL, 0 ); + filler( buf, "..", NULL, 0 ); + for( Bu::MyriadFs::Dir::iterator i = lDir.begin(); i; i++ ) + { + filler( buf, (*i).sName.getStr(), NULL, 0 ); + } - return 0; - } + return 0; + } - static int myriadfs_mkdir( const char *sPath, mode_t uMode ) - { + static int myriadfs_mkdir( const char *sPath, mode_t uMode ) + { #ifdef TRACE - printf("myriadfs_mkdir(\"%s\", 0%o );\n", sPath, uMode ); + printf("myriadfs_mkdir(\"%s\", 0%o );\n", sPath, uMode ); #endif - pFs->mkDir( sPath, uMode ); - return 0; - } + pFs->mkDir( sPath, uMode ); + return 0; + } - static int myriadfs_open( const char *sPath, struct fuse_file_info *fi ) - { + static int myriadfs_open( const char *sPath, struct fuse_file_info *fi ) + { #ifdef TRACE - printf("myriadfs_open(\"%s\", ... );\n", sPath ); + printf("myriadfs_open(\"%s\", ... );\n", sPath ); #endif - try - { - Bu::MyriadStream ms = pFs->open( sPath, 0 ); - fi->fh = iNextFileId; - hOpenFiles.insert( iNextFileId++, ms ); -// printf("File '%s' opened, %d files open now.\n", -// sPath, hOpenFiles.getSize() ); - return 0; - } - catch(...) - { - return -EACCES; - } - } + try + { + Bu::MyriadStream ms = pFs->open( sPath, 0 ); + fi->fh = iNextFileId; + hOpenFiles.insert( iNextFileId++, ms ); +// printf("File '%s' opened, %d files open now.\n", +// sPath, hOpenFiles.getSize() ); + return 0; + } + catch(...) + { + return -EACCES; + } + } - static int myriadfs_read( const char *sPath, char *buf, size_t iSize, - off_t iOffset, struct fuse_file_info *fi ) - { + static int myriadfs_read( const char *sPath, char *buf, size_t iSize, + off_t iOffset, struct fuse_file_info *fi ) + { #ifdef TRACE - printf("myriadfs_read(\"%s\", ..., %d, %d, ... );\n", sPath, iSize, - iOffset ); + printf("myriadfs_read(\"%s\", ..., %d, %d, ... );\n", sPath, iSize, + iOffset ); #endif - Bu::MyriadStream &ms = hOpenFiles.get( fi->fh ); - ms.setPos( iOffset ); - return ms.read( buf, iSize ); - } + Bu::MyriadStream &ms = hOpenFiles.get( fi->fh ); + ms.setPos( iOffset ); + return ms.read( buf, iSize ); + } - static int myriadfs_write( const char *sPath, const char *buf, size_t iSize, - off_t iOffset, struct fuse_file_info *fi ) - { + static int myriadfs_write( const char *sPath, const char *buf, size_t iSize, + off_t iOffset, struct fuse_file_info *fi ) + { #ifdef TRACE - printf("myriadfs_write(\"%s\", ..., %d, %d, ... );\n", sPath, iSize, - iOffset ); + printf("myriadfs_write(\"%s\", ..., %d, %d, ... );\n", sPath, iSize, + iOffset ); #endif - Bu::MyriadStream &ms = hOpenFiles.get( fi->fh ); - ms.setPos( iOffset ); - return ms.write( buf, iSize ); - } + Bu::MyriadStream &ms = hOpenFiles.get( fi->fh ); + ms.setPos( iOffset ); + return ms.write( buf, iSize ); + } - static int myriadfs_create( const char *sPath, mode_t uPerms, - struct fuse_file_info *fi ) - { + static int myriadfs_create( const char *sPath, mode_t uPerms, + struct fuse_file_info *fi ) + { #ifdef TRACE - printf("myriadfs_create(\"%s\", 0%o, ... );\n", sPath, uPerms ); + printf("myriadfs_create(\"%s\", 0%o, ... );\n", sPath, uPerms ); #endif - try - { - Bu::MyriadStream ms = pFs->open( sPath, 0, uPerms ); - fi->fh = iNextFileId; - hOpenFiles.insert( iNextFileId++, ms ); -// printf("File '%s' created, %d files open now.\n", -// sPath, hOpenFiles.getSize() ); - return 0; - } - catch(...) - { - return -EACCES; - } - } - - static int myriadfs_mknod( const char *sPath, mode_t uPerms, dev_t Dev ) - { + try + { + Bu::MyriadStream ms = pFs->open( sPath, 0, uPerms ); + fi->fh = iNextFileId; + hOpenFiles.insert( iNextFileId++, ms ); +// printf("File '%s' created, %d files open now.\n", +// sPath, hOpenFiles.getSize() ); + return 0; + } + catch(...) + { + return -EACCES; + } + } + + static int myriadfs_mknod( const char *sPath, mode_t uPerms, dev_t Dev ) + { #ifdef TRACE - printf("myriadfs_mknod(\"%s\", 0%o, %x );\n", sPath, uPerms, Dev ); + printf("myriadfs_mknod(\"%s\", 0%o, %x );\n", sPath, uPerms, Dev ); #endif - try - { - pFs->create( sPath, uPerms, Bu::MyriadFs::sysToDev( Dev ) ); - return 0; - } - catch(...) - { - return -EACCES; - } - } + try + { + pFs->create( sPath, uPerms, Bu::MyriadFs::sysToDev( Dev ) ); + return 0; + } + catch(...) + { + return -EACCES; + } + } - static int myriadfs_release( const char *sPath, struct fuse_file_info *fi ) - { + static int myriadfs_release( const char *sPath, struct fuse_file_info *fi ) + { #ifdef TRACE - printf("myriadfs_release(\"%s\", ... );\n", sPath ); + printf("myriadfs_release(\"%s\", ... );\n", sPath ); #endif - hOpenFiles.erase( fi->fh ); -// printf("File '%s' released, %d files open now.\n", -// sPath, hOpenFiles.getSize() ); + hOpenFiles.erase( fi->fh ); +// printf("File '%s' released, %d files open now.\n", +// sPath, hOpenFiles.getSize() ); - return 0; - } + return 0; + } - static int myriadfs_utimens( const char *sPath, - const struct timespec tv[2] ) - { + static int myriadfs_utimens( const char *sPath, + const struct timespec tv[2] ) + { #ifdef TRACE - printf("myriadfs_utimens(\"%s\", ... );\n", sPath ); + printf("myriadfs_utimens(\"%s\", ... );\n", sPath ); #endif - try - { - pFs->setTimes( sPath, tv[0].tv_sec, tv[1].tv_sec ); - } - catch(...) - { - return -EACCES; - } - return 0; - } + try + { + pFs->setTimes( sPath, tv[0].tv_sec, tv[1].tv_sec ); + } + catch(...) + { + return -EACCES; + } + return 0; + } - static int myriadfs_unlink( const char *sPath ) - { + static int myriadfs_unlink( const char *sPath ) + { #ifdef TRACE - printf("myriadfs_unlink(\"%s\");\n", sPath ); + printf("myriadfs_unlink(\"%s\");\n", sPath ); #endif - try - { - pFs->unlink( sPath ); - } - catch( Bu::MyriadFsException &e ) - { - printf("MyriadFsException: %s\n", e.what() ); - return -EACCES; - } - return 0; - } + try + { + pFs->unlink( sPath ); + } + catch( Bu::MyriadFsException &e ) + { + printf("MyriadFsException: %s\n", e.what() ); + return -EACCES; + } + return 0; + } - static int myriadfs_symlink( const char *sTarget, const char *sPath ) - { + static int myriadfs_symlink( const char *sTarget, const char *sPath ) + { #ifdef TRACE - printf("myriadfs_symlink(\"%s\", \"%s\");\n", sTarget, sPath ); + printf("myriadfs_symlink(\"%s\", \"%s\");\n", sTarget, sPath ); #endif - try - { - pFs->mkSymLink( sTarget, sPath ); - } - catch( Bu::MyriadFsException &e ) - { - printf("MyriadFsException: %s\n", e.what() ); - return -EACCES; - } - return 0; - } + try + { + pFs->mkSymLink( sTarget, sPath ); + } + catch( Bu::MyriadFsException &e ) + { + printf("MyriadFsException: %s\n", e.what() ); + return -EACCES; + } + return 0; + } - static int myriadfs_readlink( const char *sPath, char *sOut, size_t s ) - { + static int myriadfs_readlink( const char *sPath, char *sOut, size_t s ) + { #ifdef TRACE - printf("myriadfs_readlink(\"%s\", ... );\n", sPath ); + printf("myriadfs_readlink(\"%s\", ... );\n", sPath ); #endif - try - { - Bu::String sTrg = pFs->readSymLink( sPath ); - size_t iLen = (s-1>sTrg.getSize())?(sTrg.getSize()):(s-1); - memcpy( sOut, sTrg.getStr(), iLen ); - sOut[iLen] = '\0'; - } - catch( Bu::MyriadFsException &e ) - { - printf("MyriadFsException: %s\n", e.what() ); - return -EACCES; - } - return 0; - } + try + { + Bu::String sTrg = pFs->readSymLink( sPath ); + size_t iLen = (s-1>sTrg.getSize())?(sTrg.getSize()):(s-1); + memcpy( sOut, sTrg.getStr(), iLen ); + sOut[iLen] = '\0'; + } + catch( Bu::MyriadFsException &e ) + { + printf("MyriadFsException: %s\n", e.what() ); + return -EACCES; + } + return 0; + } - static int myriadfs_truncate( const char *sPath, off_t iSize ) - { + static int myriadfs_truncate( const char *sPath, off_t iSize ) + { #ifdef TRACE - printf("myriadfs_truncate(\"%s\", %d );\n", sPath, iSize ); + printf("myriadfs_truncate(\"%s\", %d );\n", sPath, iSize ); #endif - try - { - pFs->setFileSize( sPath, iSize ); - } - catch( Bu::MyriadFsException &e ) - { - printf("MyriadFsException: %s\n", e.what() ); - return -ENOENT; - } - return 0; - } + try + { + pFs->setFileSize( sPath, iSize ); + } + catch( Bu::MyriadFsException &e ) + { + printf("MyriadFsException: %s\n", e.what() ); + return -ENOENT; + } + return 0; + } - static int myriadfs_link( const char *sTarget, const char *sPath ) - { + static int myriadfs_link( const char *sTarget, const char *sPath ) + { #ifdef TRACE - printf("myriadfs_link(\"%s\", \"%s\");\n", sTarget, sPath ); + printf("myriadfs_link(\"%s\", \"%s\");\n", sTarget, sPath ); #endif - try - { - pFs->mkHardLink( sTarget, sPath ); - } - catch( Bu::MyriadFsException &e ) - { - printf("MyriadFsException: %s\n", e.what() ); - return -EACCES; - } - return 0; - } + try + { + pFs->mkHardLink( sTarget, sPath ); + } + catch( Bu::MyriadFsException &e ) + { + printf("MyriadFsException: %s\n", e.what() ); + return -EACCES; + } + return 0; + } - static int myriadfs_rename( const char *sFrom, const char *sTo ) - { + static int myriadfs_rename( const char *sFrom, const char *sTo ) + { #ifdef TRACE - printf("myriadfs_rename(\"%s\", \"%s\");\n", sFrom, sTo ); + printf("myriadfs_rename(\"%s\", \"%s\");\n", sFrom, sTo ); #endif - try - { - pFs->rename( sFrom, sTo ); - } - catch( Bu::MyriadFsException &e ) - { - printf("MyriadFsException: %s\n", e.what() ); - return -EACCES; - } - return 0; - } + try + { + pFs->rename( sFrom, sTo ); + } + catch( Bu::MyriadFsException &e ) + { + printf("MyriadFsException: %s\n", e.what() ); + return -EACCES; + } + return 0; + } - static struct fuse_operations myriadfs_oper; + static struct fuse_operations myriadfs_oper; - int main( int argc, char *argv[] ) - { - pF = new Bu::File("store.myr", Bu::File::Read|Bu::File::Write|Bu::File::Create ); - pFs = new Bu::MyriadFs( *pF, 512 ); - memset( &myriadfs_oper, sizeof(myriadfs_oper), 0 ); - myriadfs_oper.getattr = myriadfs_getattr; - myriadfs_oper.readdir = myriadfs_readdir; - myriadfs_oper.mkdir = myriadfs_mkdir; - myriadfs_oper.open = myriadfs_open; - myriadfs_oper.read = myriadfs_read; - myriadfs_oper.write = myriadfs_write; - myriadfs_oper.create = myriadfs_create; - myriadfs_oper.mknod = myriadfs_mknod; - myriadfs_oper.release = myriadfs_release; - myriadfs_oper.utimens = myriadfs_utimens; - myriadfs_oper.unlink = myriadfs_unlink; - myriadfs_oper.rmdir = myriadfs_unlink; - myriadfs_oper.symlink = myriadfs_symlink; - myriadfs_oper.readlink = myriadfs_readlink; - myriadfs_oper.truncate = myriadfs_truncate; - myriadfs_oper.link = myriadfs_link; - myriadfs_oper.rename = myriadfs_rename; - printf("Starting fuse_main.\n"); - int iRet = fuse_main( argc, argv, &myriadfs_oper, NULL ); - printf("Done with fuse_main.\n"); - delete pFs; - delete pF; - return iRet; - } + int main( int argc, char *argv[] ) + { + pF = new Bu::File("store.myr", Bu::File::Read|Bu::File::Write|Bu::File::Create ); + pFs = new Bu::MyriadFs( *pF, 512 ); + memset( &myriadfs_oper, sizeof(myriadfs_oper), 0 ); + myriadfs_oper.getattr = myriadfs_getattr; + myriadfs_oper.readdir = myriadfs_readdir; + myriadfs_oper.mkdir = myriadfs_mkdir; + myriadfs_oper.open = myriadfs_open; + myriadfs_oper.read = myriadfs_read; + myriadfs_oper.write = myriadfs_write; + myriadfs_oper.create = myriadfs_create; + myriadfs_oper.mknod = myriadfs_mknod; + myriadfs_oper.release = myriadfs_release; + myriadfs_oper.utimens = myriadfs_utimens; + myriadfs_oper.unlink = myriadfs_unlink; + myriadfs_oper.rmdir = myriadfs_unlink; + myriadfs_oper.symlink = myriadfs_symlink; + myriadfs_oper.readlink = myriadfs_readlink; + myriadfs_oper.truncate = myriadfs_truncate; + myriadfs_oper.link = myriadfs_link; + myriadfs_oper.rename = myriadfs_rename; + printf("Starting fuse_main.\n"); + int iRet = fuse_main( argc, argv, &myriadfs_oper, NULL ); + printf("Done with fuse_main.\n"); + delete pFs; + delete pF; + return iRet; + } } diff --git a/src/stable/archival.cpp b/src/stable/archival.cpp index 5e6e612..9ba10f2 100644 --- a/src/stable/archival.cpp +++ b/src/stable/archival.cpp @@ -17,19 +17,19 @@ Bu::Archival::~Archival() Bu::ArchiveBase &Bu::operator<<(Bu::ArchiveBase &s, const Bu::Archival &p) { - const_cast(p).archive( s ); - return s; + const_cast(p).archive( s ); + return s; } Bu::ArchiveBase &Bu::operator<<(Bu::ArchiveBase &s, Bu::Archival &p) { - p.archive( s ); - return s; + p.archive( s ); + return s; } Bu::ArchiveBase &Bu::operator>>(Bu::ArchiveBase &s, Bu::Archival &p) { - p.archive( s ); - return s; + p.archive( s ); + return s; } diff --git a/src/stable/archival.h b/src/stable/archival.h index 664bc98..78faffb 100644 --- a/src/stable/archival.h +++ b/src/stable/archival.h @@ -12,40 +12,40 @@ namespace Bu { - /** - * The base class for any class you want to archive. Simply include this as - * a base class, implement the purely virtual archive function and you've - * got an easily archiveable class. - * - * Archival: "of or pertaining to archives or valuable records; contained + /** + * The base class for any class you want to archive. Simply include this as + * a base class, implement the purely virtual archive function and you've + * got an easily archiveable class. + * + * Archival: "of or pertaining to archives or valuable records; contained * in or comprising such archives or records." - */ - class Archival - { - public: - /** - * Does nothing, here for completeness. - */ - Archival(); - - /** - * Here to ensure the deconstructor is virtual. - */ - virtual ~Archival(); - - /** - * This is the main workhorse of the archive system, just override and - * you've got a archiveable class. A reference to the Archive - * used is passed in as your only parameter, query it to discover if - * you are loading or saving. - * @param ar A reference to the Archive object to use. - */ - virtual void archive( class ArchiveBase &ar )=0; - }; - - ArchiveBase &operator<<(ArchiveBase &, const class Bu::Archival &); - ArchiveBase &operator<<(ArchiveBase &, class Bu::Archival &); - ArchiveBase &operator>>(ArchiveBase &, class Bu::Archival &); + */ + class Archival + { + public: + /** + * Does nothing, here for completeness. + */ + Archival(); + + /** + * Here to ensure the deconstructor is virtual. + */ + virtual ~Archival(); + + /** + * This is the main workhorse of the archive system, just override and + * you've got a archiveable class. A reference to the Archive + * used is passed in as your only parameter, query it to discover if + * you are loading or saving. + * @param ar A reference to the Archive object to use. + */ + virtual void archive( class ArchiveBase &ar )=0; + }; + + ArchiveBase &operator<<(ArchiveBase &, const class Bu::Archival &); + ArchiveBase &operator<<(ArchiveBase &, class Bu::Archival &); + ArchiveBase &operator>>(ArchiveBase &, class Bu::Archival &); } diff --git a/src/stable/archive.cpp b/src/stable/archive.cpp index 13480e1..3769e0e 100644 --- a/src/stable/archive.cpp +++ b/src/stable/archive.cpp @@ -12,9 +12,9 @@ #include "bu/sio.h" Bu::Archive::Archive( Stream &rStream, bool bLoading ) : - bLoading( bLoading ), - rStream( rStream ), - nNextID( 1 ) + bLoading( bLoading ), + rStream( rStream ), + nNextID( 1 ) { } @@ -24,66 +24,66 @@ Bu::Archive::~Archive() void Bu::Archive::write( const void *pData, size_t nSize ) { - if( nSize == 0 || pData == NULL ) - return; + if( nSize == 0 || pData == NULL ) + return; - rStream.write( (const char *)pData, nSize ); + rStream.write( (const char *)pData, nSize ); } void Bu::Archive::read( void *pData, size_t nSize ) { - if( nSize == 0 || pData == NULL ) - return; + if( nSize == 0 || pData == NULL ) + return; - if( (size_t)rStream.read( (char *)pData, nSize ) < nSize ) - throw Bu::ExceptionBase("Insufficient data to unarchive object."); + if( (size_t)rStream.read( (char *)pData, nSize ) < nSize ) + throw Bu::ExceptionBase("Insufficient data to unarchive object."); } void Bu::Archive::close() { - rStream.close(); + rStream.close(); } bool Bu::Archive::isLoading() { - return bLoading; + return bLoading; } uint32_t Bu::Archive::getID( const void *ptr ) { - if( hPtrID.has( (ptrdiff_t)ptr ) ) - return hPtrID.get( (ptrdiff_t)ptr ); - hPtrID.insert( (ptrdiff_t)ptr, nNextID ); - return nNextID++; + if( hPtrID.has( (ptrdiff_t)ptr ) ) + return hPtrID.get( (ptrdiff_t)ptr ); + hPtrID.insert( (ptrdiff_t)ptr, nNextID ); + return nNextID++; } void Bu::Archive::assocPtrID( void **ptr, uint32_t id ) { - if( hPtrID.has( id ) ) - { - *ptr = (void *)hPtrID.get( id ); - return; - } - - if( !hPtrDest.has( id ) ) - hPtrDest.insert( id, List() ); - - hPtrDest[id].getValue().append( ptr ); + if( hPtrID.has( id ) ) + { + *ptr = (void *)hPtrID.get( id ); + return; + } + + if( !hPtrDest.has( id ) ) + hPtrDest.insert( id, List() ); + + hPtrDest[id].getValue().append( ptr ); } void Bu::Archive::readID( const void *ptr, uint32_t id ) { - hPtrID.insert( id, (ptrdiff_t)ptr ); - - if( hPtrDest.has( id ) ) - { - Bu::List &l = hPtrDest.get( id ); - for( Bu::List::iterator i = l.begin(); i != l.end(); i++ ) - { - *(*i) = (void *)ptr; - } - - hPtrDest.erase( id ); - } + hPtrID.insert( id, (ptrdiff_t)ptr ); + + if( hPtrDest.has( id ) ) + { + Bu::List &l = hPtrDest.get( id ); + for( Bu::List::iterator i = l.begin(); i != l.end(); i++ ) + { + *(*i) = (void *)ptr; + } + + hPtrDest.erase( id ); + } } diff --git a/src/stable/archive.h b/src/stable/archive.h index 9716bb1..f98402d 100644 --- a/src/stable/archive.h +++ b/src/stable/archive.h @@ -16,123 +16,123 @@ namespace Bu { - class Archival; - class Stream; + class Archival; + class Stream; - /** - * Provides a framework for serialization of objects and primitives. The - * archive will handle any basic primitive, a few special types, like char * - * strings, as well as STL classes and anything that inherits from the - * Archival class. Each Archive operates on a Stream, so you can send the - * data using an Archive almost anywhere. - * - * In order to use an Archive to store something to a file, try something - * like: - *@code + /** + * Provides a framework for serialization of objects and primitives. The + * archive will handle any basic primitive, a few special types, like char * + * strings, as well as STL classes and anything that inherits from the + * Archival class. Each Archive operates on a Stream, so you can send the + * data using an Archive almost anywhere. + * + * In order to use an Archive to store something to a file, try something + * like: + *@code * File sOut("output", "wb"); // This is a stream subclass - * Archive ar( sOut, Archive::save ); - * ar << myClass; - @endcode - * In this example myClass is any class that inherits from Archival. When - * the storage operator is called, the Archival::archive() function in the - * myClass object is called with a reference to the Archive. This can be - * handled in one of two ways: - *@code - * void MyClass::archive( Archive &ar ) - * { - * ar && sName && nAge && sJob; - * } - @endcode - * Here we don't worry about weather we're loading or saving by using the - * smart && operator. This allows us to write very consistent, very simple - * archive functions that really do a lot of work. If we wanted to do - * something different in the case of loading or saving we would do: - *@code - * void MyClass::archive( Archive &ar ) - * { - * if( ar.isLoading() ) - * { - * ar >> sName >> nAge >> sJob; - * } else - * { - * ar << sName << nAge << sJob; - * } - * } - @endcode - * Archive currently does not provide facility to make fully portable - * archives. For example, it will not convert between endianness for you, - * nor will it take into account differences between primitive sizes on - * different platforms. This, at the moment, is up to the user to ensure. - * One way of dealing with the latter problem is to make sure and use - * explicit primitive types from the stdint.h header, i.e. int32_t. - */ - class Archive : public ArchiveBase - { - private: - bool bLoading; - public: - bool isLoading(); + * Archive ar( sOut, Archive::save ); + * ar << myClass; + @endcode + * In this example myClass is any class that inherits from Archival. When + * the storage operator is called, the Archival::archive() function in the + * myClass object is called with a reference to the Archive. This can be + * handled in one of two ways: + *@code + * void MyClass::archive( Archive &ar ) + * { + * ar && sName && nAge && sJob; + * } + @endcode + * Here we don't worry about weather we're loading or saving by using the + * smart && operator. This allows us to write very consistent, very simple + * archive functions that really do a lot of work. If we wanted to do + * something different in the case of loading or saving we would do: + *@code + * void MyClass::archive( Archive &ar ) + * { + * if( ar.isLoading() ) + * { + * ar >> sName >> nAge >> sJob; + * } else + * { + * ar << sName << nAge << sJob; + * } + * } + @endcode + * Archive currently does not provide facility to make fully portable + * archives. For example, it will not convert between endianness for you, + * nor will it take into account differences between primitive sizes on + * different platforms. This, at the moment, is up to the user to ensure. + * One way of dealing with the latter problem is to make sure and use + * explicit primitive types from the stdint.h header, i.e. int32_t. + */ + class Archive : public ArchiveBase + { + private: + bool bLoading; + public: + bool isLoading(); - enum - { - load = true, - save = false - }; - - Archive( Stream &rStream, bool bLoading ); - virtual ~Archive(); - virtual void close(); + enum + { + load = true, + save = false + }; + + Archive( Stream &rStream, bool bLoading ); + virtual ~Archive(); + virtual void close(); - virtual void write( const void *pData, size_t iSize ); - virtual void read( void *pData, size_t iSize ); - - /** - * For storage, get an ID for the pointer to the object you're going to - * write. - */ - uint32_t getID( const void *ptr ); + virtual void write( const void *pData, size_t iSize ); + virtual void read( void *pData, size_t iSize ); + + /** + * For storage, get an ID for the pointer to the object you're going to + * write. + */ + uint32_t getID( const void *ptr ); - /** - * For loading. Assosiates an empty pointer with an id. When you wind - * up loading an id reference to a pointer for an object that may or - * may not have loaded yet, call this with the id, if it has been loaded - * already, you'll immediately get a pointer, if not, it will write one - * for you when the time comes. - */ - void assocPtrID( void **ptr, uint32_t id ); + /** + * For loading. Assosiates an empty pointer with an id. When you wind + * up loading an id reference to a pointer for an object that may or + * may not have loaded yet, call this with the id, if it has been loaded + * already, you'll immediately get a pointer, if not, it will write one + * for you when the time comes. + */ + void assocPtrID( void **ptr, uint32_t id ); - /** - * For loading. Call this when you load an object that other things may - * have pointers to. It will assosiate every pointer that's been - * registered with assocPtrID to the pointer passed in, and id passed - * in. It will also set things up so future calls to assocPtrID will - * automatically succeed immediately. - */ - void readID( const void *ptr, uint32_t id ); + /** + * For loading. Call this when you load an object that other things may + * have pointers to. It will assosiate every pointer that's been + * registered with assocPtrID to the pointer passed in, and id passed + * in. It will also set things up so future calls to assocPtrID will + * automatically succeed immediately. + */ + void readID( const void *ptr, uint32_t id ); - template - void setProp( const Bu::String &sId, const t &val ) - { - if( !hProps.has( sId ) ) - { - hProps.insert( sId, Variant() ); - } - hProps.get( sId ) = val; - } + template + void setProp( const Bu::String &sId, const t &val ) + { + if( !hProps.has( sId ) ) + { + hProps.insert( sId, Variant() ); + } + hProps.get( sId ) = val; + } - template - t getProp( const Bu::String &sId ) - { - return hProps.get( sId ); - } + template + t getProp( const Bu::String &sId ) + { + return hProps.get( sId ); + } - private: - Stream &rStream; - uint32_t nNextID; - Hash hPtrID; - Hash > hPtrDest; - Hash hProps; - }; + private: + Stream &rStream; + uint32_t nNextID; + Hash hPtrID; + Hash > hPtrDest; + Hash hProps; + }; } #endif diff --git a/src/stable/archivebase.cpp b/src/stable/archivebase.cpp index dcf08f4..d0d22ce 100644 --- a/src/stable/archivebase.cpp +++ b/src/stable/archivebase.cpp @@ -17,181 +17,181 @@ Bu::ArchiveBase::~ArchiveBase() Bu::ArchiveBase &Bu::operator<<( Bu::ArchiveBase &ar, bool p) { - ar.write( &p, sizeof(p) ); - return ar; + ar.write( &p, sizeof(p) ); + return ar; } Bu::ArchiveBase &Bu::operator<<( Bu::ArchiveBase &ar, char p) { - ar.write( &p, sizeof(p) ); - return ar; + ar.write( &p, sizeof(p) ); + return ar; } Bu::ArchiveBase &Bu::operator<<( Bu::ArchiveBase &ar, signed char p) { - ar.write( &p, sizeof(p) ); - return ar; + ar.write( &p, sizeof(p) ); + return ar; } Bu::ArchiveBase &Bu::operator<<( Bu::ArchiveBase &ar, unsigned char p) { - ar.write( &p, sizeof(p) ); - return ar; + ar.write( &p, sizeof(p) ); + return ar; } Bu::ArchiveBase &Bu::operator<<( Bu::ArchiveBase &ar, signed short p) { - ar.write( &p, sizeof(p) ); - return ar; + ar.write( &p, sizeof(p) ); + return ar; } Bu::ArchiveBase &Bu::operator<<( Bu::ArchiveBase &ar, unsigned short p) { - ar.write( &p, sizeof(p) ); - return ar; + ar.write( &p, sizeof(p) ); + return ar; } Bu::ArchiveBase &Bu::operator<<( Bu::ArchiveBase &ar, signed int p) { - ar.write( &p, sizeof(p) ); - return ar; + ar.write( &p, sizeof(p) ); + return ar; } Bu::ArchiveBase &Bu::operator<<( Bu::ArchiveBase &ar, unsigned int p) { - ar.write( &p, sizeof(p) ); - return ar; + ar.write( &p, sizeof(p) ); + return ar; } Bu::ArchiveBase &Bu::operator<<( Bu::ArchiveBase &ar, signed long p) { - ar.write( &p, sizeof(p) ); - return ar; + ar.write( &p, sizeof(p) ); + return ar; } Bu::ArchiveBase &Bu::operator<<( Bu::ArchiveBase &ar, unsigned long p) { - ar.write( &p, sizeof(p) ); - return ar; + ar.write( &p, sizeof(p) ); + return ar; } Bu::ArchiveBase &Bu::operator<<( Bu::ArchiveBase &ar, signed long long p) { - ar.write( &p, sizeof(p) ); - return ar; + ar.write( &p, sizeof(p) ); + return ar; } Bu::ArchiveBase &Bu::operator<<( Bu::ArchiveBase &ar, unsigned long long p) { - ar.write( &p, sizeof(p) ); - return ar; + ar.write( &p, sizeof(p) ); + return ar; } Bu::ArchiveBase &Bu::operator<<( Bu::ArchiveBase &ar, float p) { - ar.write( &p, sizeof(p) ); - return ar; + ar.write( &p, sizeof(p) ); + return ar; } Bu::ArchiveBase &Bu::operator<<( Bu::ArchiveBase &ar, double p) { - ar.write( &p, sizeof(p) ); - return ar; + ar.write( &p, sizeof(p) ); + return ar; } Bu::ArchiveBase &Bu::operator<<( Bu::ArchiveBase &ar, long double p) { - ar.write( &p, sizeof(p) ); - return ar; + ar.write( &p, sizeof(p) ); + return ar; } Bu::ArchiveBase &Bu::operator>>( Bu::ArchiveBase &ar, bool &p) { - ar.read( &p, sizeof(p) ); - return ar; + ar.read( &p, sizeof(p) ); + return ar; } Bu::ArchiveBase &Bu::operator>>( Bu::ArchiveBase &ar, char &p) { - ar.read( &p, sizeof(p) ); - return ar; + ar.read( &p, sizeof(p) ); + return ar; } Bu::ArchiveBase &Bu::operator>>( Bu::ArchiveBase &ar, signed char &p) { - ar.read( &p, sizeof(p) ); - return ar; + ar.read( &p, sizeof(p) ); + return ar; } Bu::ArchiveBase &Bu::operator>>( Bu::ArchiveBase &ar, unsigned char &p) { - ar.read( &p, sizeof(p) ); - return ar; + ar.read( &p, sizeof(p) ); + return ar; } Bu::ArchiveBase &Bu::operator>>( Bu::ArchiveBase &ar, signed short &p) { - ar.read( &p, sizeof(p) ); - return ar; + ar.read( &p, sizeof(p) ); + return ar; } Bu::ArchiveBase &Bu::operator>>( Bu::ArchiveBase &ar, unsigned short &p) { - ar.read( &p, sizeof(p) ); - return ar; + ar.read( &p, sizeof(p) ); + return ar; } Bu::ArchiveBase &Bu::operator>>( Bu::ArchiveBase &ar, signed int &p) { - ar.read( &p, sizeof(p) ); - return ar; + ar.read( &p, sizeof(p) ); + return ar; } Bu::ArchiveBase &Bu::operator>>( Bu::ArchiveBase &ar, unsigned int &p) { - ar.read( &p, sizeof(p) ); - return ar; + ar.read( &p, sizeof(p) ); + return ar; } Bu::ArchiveBase &Bu::operator>>( Bu::ArchiveBase &ar, signed long &p) { - ar.read( &p, sizeof(p) ); - return ar; + ar.read( &p, sizeof(p) ); + return ar; } Bu::ArchiveBase &Bu::operator>>( Bu::ArchiveBase &ar, unsigned long &p) { - ar.read( &p, sizeof(p) ); - return ar; + ar.read( &p, sizeof(p) ); + return ar; } Bu::ArchiveBase &Bu::operator>>( Bu::ArchiveBase &ar, signed long long &p) { - ar.read( &p, sizeof(p) ); - return ar; + ar.read( &p, sizeof(p) ); + return ar; } Bu::ArchiveBase &Bu::operator>>( Bu::ArchiveBase &ar, unsigned long long &p) { - ar.read( &p, sizeof(p) ); - return ar; + ar.read( &p, sizeof(p) ); + return ar; } Bu::ArchiveBase &Bu::operator>>( Bu::ArchiveBase &ar, float &p) { - ar.read( &p, sizeof(p) ); - return ar; + ar.read( &p, sizeof(p) ); + return ar; } Bu::ArchiveBase &Bu::operator>>( Bu::ArchiveBase &ar, double &p) { - ar.read( &p, sizeof(p) ); - return ar; + ar.read( &p, sizeof(p) ); + return ar; } Bu::ArchiveBase &Bu::operator>>( Bu::ArchiveBase &ar, long double &p) { - ar.read( &p, sizeof(p) ); - return ar; + ar.read( &p, sizeof(p) ); + return ar; } diff --git a/src/stable/archivebase.h b/src/stable/archivebase.h index 34ec1af..3f9e30f 100644 --- a/src/stable/archivebase.h +++ b/src/stable/archivebase.h @@ -13,63 +13,63 @@ namespace Bu { - class ArchiveBase - { - public: - ArchiveBase(); - virtual ~ArchiveBase(); + class ArchiveBase + { + public: + ArchiveBase(); + virtual ~ArchiveBase(); - virtual void close()=0; - virtual void write( const void *pData, size_t iLength )=0; - virtual void read( void *pData, size_t iLength )=0; - virtual bool isLoading()=0; - }; + virtual void close()=0; + virtual void write( const void *pData, size_t iLength )=0; + virtual void read( void *pData, size_t iLength )=0; + virtual bool isLoading()=0; + }; - template ArchiveBase &operator&&( ArchiveBase &ar, T &dat ) - { - if( ar.isLoading() ) - { - return ar >> dat; - } - else - { - return ar << dat; - } - } + template ArchiveBase &operator&&( ArchiveBase &ar, T &dat ) + { + if( ar.isLoading() ) + { + return ar >> dat; + } + else + { + return ar << dat; + } + } - ArchiveBase &operator<<( ArchiveBase &ar, bool p ); - ArchiveBase &operator<<( ArchiveBase &ar, char p ); - ArchiveBase &operator<<( ArchiveBase &ar, signed char p ); - ArchiveBase &operator<<( ArchiveBase &ar, unsigned char p ); - ArchiveBase &operator<<( ArchiveBase &ar, signed short p ); - ArchiveBase &operator<<( ArchiveBase &ar, unsigned short p ); - ArchiveBase &operator<<( ArchiveBase &ar, signed int p ); - ArchiveBase &operator<<( ArchiveBase &ar, unsigned int p ); - ArchiveBase &operator<<( ArchiveBase &ar, signed long p ); - ArchiveBase &operator<<( ArchiveBase &ar, unsigned long p ); - ArchiveBase &operator<<( ArchiveBase &ar, signed long long p ); - ArchiveBase &operator<<( ArchiveBase &ar, unsigned long long p ); - ArchiveBase &operator<<( ArchiveBase &ar, float p ); - ArchiveBase &operator<<( ArchiveBase &ar, double p ); - ArchiveBase &operator<<( ArchiveBase &ar, long double p ); - - ArchiveBase &operator>>( ArchiveBase &ar, bool &p ); - ArchiveBase &operator>>( ArchiveBase &ar, char &p ); - ArchiveBase &operator>>( ArchiveBase &ar, signed char &p ); - ArchiveBase &operator>>( ArchiveBase &ar, unsigned char &p ); - ArchiveBase &operator>>( ArchiveBase &ar, signed short &p ); - ArchiveBase &operator>>( ArchiveBase &ar, unsigned short &p ); - ArchiveBase &operator>>( ArchiveBase &ar, signed int &p ); - ArchiveBase &operator>>( ArchiveBase &ar, unsigned int &p ); - ArchiveBase &operator>>( ArchiveBase &ar, signed long &p ); - ArchiveBase &operator>>( ArchiveBase &ar, unsigned long &p ); - ArchiveBase &operator>>( ArchiveBase &ar, signed long long &p ); - ArchiveBase &operator>>( ArchiveBase &ar, unsigned long long &p ); - ArchiveBase &operator>>( ArchiveBase &ar, float &p ); - ArchiveBase &operator>>( ArchiveBase &ar, double &p ); - ArchiveBase &operator>>( ArchiveBase &ar, long double &p ); + ArchiveBase &operator<<( ArchiveBase &ar, bool p ); + ArchiveBase &operator<<( ArchiveBase &ar, char p ); + ArchiveBase &operator<<( ArchiveBase &ar, signed char p ); + ArchiveBase &operator<<( ArchiveBase &ar, unsigned char p ); + ArchiveBase &operator<<( ArchiveBase &ar, signed short p ); + ArchiveBase &operator<<( ArchiveBase &ar, unsigned short p ); + ArchiveBase &operator<<( ArchiveBase &ar, signed int p ); + ArchiveBase &operator<<( ArchiveBase &ar, unsigned int p ); + ArchiveBase &operator<<( ArchiveBase &ar, signed long p ); + ArchiveBase &operator<<( ArchiveBase &ar, unsigned long p ); + ArchiveBase &operator<<( ArchiveBase &ar, signed long long p ); + ArchiveBase &operator<<( ArchiveBase &ar, unsigned long long p ); + ArchiveBase &operator<<( ArchiveBase &ar, float p ); + ArchiveBase &operator<<( ArchiveBase &ar, double p ); + ArchiveBase &operator<<( ArchiveBase &ar, long double p ); + + ArchiveBase &operator>>( ArchiveBase &ar, bool &p ); + ArchiveBase &operator>>( ArchiveBase &ar, char &p ); + ArchiveBase &operator>>( ArchiveBase &ar, signed char &p ); + ArchiveBase &operator>>( ArchiveBase &ar, unsigned char &p ); + ArchiveBase &operator>>( ArchiveBase &ar, signed short &p ); + ArchiveBase &operator>>( ArchiveBase &ar, unsigned short &p ); + ArchiveBase &operator>>( ArchiveBase &ar, signed int &p ); + ArchiveBase &operator>>( ArchiveBase &ar, unsigned int &p ); + ArchiveBase &operator>>( ArchiveBase &ar, signed long &p ); + ArchiveBase &operator>>( ArchiveBase &ar, unsigned long &p ); + ArchiveBase &operator>>( ArchiveBase &ar, signed long long &p ); + ArchiveBase &operator>>( ArchiveBase &ar, unsigned long long &p ); + ArchiveBase &operator>>( ArchiveBase &ar, float &p ); + ArchiveBase &operator>>( ArchiveBase &ar, double &p ); + ArchiveBase &operator>>( ArchiveBase &ar, long double &p ); - + }; #endif diff --git a/src/stable/array.h b/src/stable/array.h index f765e75..324c9ac 100644 --- a/src/stable/array.h +++ b/src/stable/array.h @@ -15,697 +15,697 @@ namespace Bu { - subExceptionDecl( ArrayException ) - - template - class Array; - - /** @cond DEVEL */ - template - class ArrayCore - { - friend class Array; - friend class SharedCore< - Array, - ArrayCore - >; - private: - ArrayCore() : - pData( NULL ), - iSize( 0 ), - iCapacity( 0 ) - { } - - void setCapacity( int iNewLen ) - { - //clear(); - //iCapacity = iCapacity; - //pData = va.allocate( iCapacity ); - if( iNewLen <= iCapacity ) return; - value *pNewData = va.allocate( iNewLen ); - if( pData ) - { - for( int j = 0; j < iSize; j++ ) - { - va.construct( &pNewData[j], pData[j] ); - va.destroy( &pData[j] ); - } - va.deallocate( pData, iCapacity ); - } - pData = pNewData; - iCapacity = iNewLen; - } - - virtual ~ArrayCore() - { - clear(); - } - - void clear() - { - if( pData ) - { - for( int j = 0; j < iSize; j++ ) - { - va.destroy( &pData[j] ); - } - va.deallocate( pData, iCapacity ); - pData = NULL; - } - iSize = 0; - iCapacity = 0; - } - - void erase( int iPos ) - { - for( int j = iPos; j < iSize; j++ ) - { - va.destroy( &pData[j] ); - if( j == iSize-1 ) - { - iSize--; - return; - } - va.construct( &pData[j], pData[j+1] ); - } - } - - void swapErase( int iPos ) - { - if( iPos == iSize-1 ) - { - erase( iPos ); - return; - } - va.destroy( &pData[iPos] ); - va.construct( &pData[iPos], pData[iSize-1] ); - va.destroy( &pData[iSize-1] ); - iSize--; - } - - valuealloc va; - value *pData; - long iSize; - long iCapacity; - }; - /** @endcond */ - - /** - * Array type container, just like a normal array only flexible and keeps - * track of your memory for you. - * - *@param value (typename) The type of data to store in your list - *@param valuealloc (typename) Memory Allocator for your value type - *@param linkalloc (typename) Memory Allocator for the list links. - *@ingroup Containers - */ - template > - class Array : public SharedCore< - Array, - ArrayCore - > - { - private: - typedef class Array MyType; - typedef class ArrayCore Core; - - protected: - using SharedCore::core; - using SharedCore::_hardCopy; - using SharedCore::_resetCore; - using SharedCore::_allocateCore; - - public: - struct const_iterator; - struct iterator; - - Array() - { - } - - Array( const MyType &src ) : - SharedCore( src ) - { - } - - Array( long iSetCap ) - { - setCapacity( iSetCap ); - } - - ~Array() - { - } - - bool operator==( const MyType &src ) const - { - if( core == src.core ) - return true; - if( core->iSize != src.core->iSize ) - return false; - - for( int j = 0; j < core->iSize; j++ ) - { - if( core->pData[j] != src.core->pData[j] ) - return false; - } - return true; - } - - bool operator!=( const MyType &src ) const - { - return !(*this == src); - } - - /** - * Clear the array. - */ - void clear() - { - _resetCore(); - } - - MyType &append( const value &rVal ) - { - _hardCopy(); - if( core->iSize == core->iCapacity ) - { - core->setCapacity( core->iCapacity + inc ); - } - - core->va.construct( &core->pData[core->iSize++], rVal ); - - return *this; - } - - MyType &append( const MyType &rVal ) - { - _hardCopy(); - - if( core->iSize + rVal.core->iSize > core->iCapacity ) - { - core->setCapacity( core->iSize + rVal.core->iSize + inc ); - } - - for( int j = 0; j < rVal.core->iSize; j++ ) - { - core->va.construct( - &core->pData[core->iSize++], - rVal.core->pData[j] - ); - } - - return *this; - } - - //operator - value &operator[]( long iIndex ) - { - _hardCopy(); - if( iIndex < 0 || iIndex >= core->iSize ) - throw ArrayException( - "Index %d out of range 0:%d", iIndex, core->iSize ); - - return core->pData[iIndex]; - } - - const value &operator[]( long iIndex ) const - { - if( iIndex < 0 || iIndex >= core->iSize ) - throw ArrayException( - "Index %d out of range 0:%d", iIndex, core->iSize ); - - return core->pData[iIndex]; - } - - value &get( long iIndex ) - { - _hardCopy(); - if( iIndex < 0 || iIndex >= core->iSize ) - throw ArrayException( - "Index %d out of range 0:%d", iIndex, core->iSize ); - - return core->pData[iIndex]; - } - - const value &get( long iIndex ) const - { - if( iIndex < 0 || iIndex >= core->iSize ) - throw ArrayException( - "Index %d out of range 0:%d", iIndex, core->iSize ); - - return core->pData[iIndex]; - } - - value &first() - { - _hardCopy(); - return core->pData[0]; - } - - const value &first() const - { - return core->pData[0]; - } - - value &last() - { - _hardCopy(); - return core->pData[core->iSize-1]; - } - - const value &last() const - { - return core->pData[core->iSize-1]; - } - - /** - * Returns true if the array is empty. The capacity has no bearing on - * this, only the size. - */ - bool isEmpty() const - { - return core->iSize==0; - } - - /** - * Get the current size of the array. - *@returns The current size of the array. - */ - long getSize() const - { - return core->iSize; - } - - /** - * Get the capacity of the array. This number will grow as data is - * added, and is mainly for the curious, it doesn't really determine - * much for the end user. - *@returns The current capacity of the array. - */ - long getCapacity() const - { - return core->iCapacity; - } - - /** - * Change the capacity of the array, very useful if you know you'll be - * adding a large amount of already counted items to the array, makes - * the appending much faster afterwords. - *@param iNewLen The new capacity of the array. - *@todo Set this up so it can reduce the size of the array as well as - * make it bigger. - */ - void setCapacity( long iNewLen ) - { - _hardCopy(); - core->setCapacity( iNewLen ); - } - - typedef struct iterator - { - friend class Array; - private: - iterator( MyType &src, long iPos=0 ) : - src( src ), - iPos( iPos ) - { - if( this->iPos >= src.getSize() ) - this->iPos = -1; - } - - MyType &src; - long iPos; - - public: - iterator operator++( int ) - { - if( iPos < 0 ) - throw ArrayException( - "Cannot increment iterator past end of array."); - iPos++; - if( iPos >= src.getSize() ) - iPos = -1; - return *this; - } - - iterator operator++() - { - if( iPos >= 0 ) - iPos++; - if( iPos >= src.getSize() ) - iPos = -1; - return *this; - } - - iterator operator+( int iAmnt ) - { - if( iPos < 0 ) - throw ArrayException( - "Cannot increment iterator past end of array."); - iPos += iAmnt; - if( iPos >= src.getSize() ) - iPos = -1; - return *this; - } - - iterator operator--( int ) - { - if( iPos < 0 ) - throw ArrayException( - "Cannot increment iterator past end of array."); - iPos--; - if( iPos < 0 ) - iPos = -1; - return *this; - } - - iterator operator--() - { - if( iPos < src.getSize() ) - iPos--; - if( iPos <= 0 ) - iPos = -1; - return *this; - } - - iterator operator-( int iAmnt ) - { - if( iPos < src.getSize() ) - iPos -= iAmnt; - if( iPos <= 0 ) - iPos = -1; - return *this; - } - - bool operator==( const iterator &oth ) const - { - return iPos == oth.iPos; - } - - bool operator!=( const iterator &oth ) const - { - return iPos != oth.iPos; - } - - iterator operator=( const iterator &oth ) - { - if( &src != &oth.src ) - throw ArrayException( - "Cannot mix iterators from different array objects."); - iPos = oth.iPos; - } - - value &operator*() - { - if( iPos < 0 ) - throw ArrayException( - "Cannot dereference finished iterator."); - return src[iPos]; - } - - long getIndex() const - { - return iPos; - } - - operator bool() const - { - return iPos >= 0; - } - - bool isValid() const - { - return iPos >= 0; - } - } iterator; - - typedef struct const_iterator - { - friend class Array; - private: - const_iterator( const MyType &src, long iPos=0 ) : - src( src ), - iPos( iPos ) - { - if( this->iPos >= src.getSize() ) - this->iPos = -1; - } - - const MyType &src; - long iPos; - - public: - const_iterator( iterator &rSrc ) : - src( rSrc.src ), - iPos( rSrc.iPos ) - { - } - const_iterator operator++( int ) - { - if( iPos < 0 ) - throw ArrayException( - "Cannot increment iterator past end of array."); - iPos++; - if( iPos >= src.getSize() ) - iPos = -1; - return *this; - } - - const_iterator operator++() - { - if( iPos >= 0 ) - iPos++; - if( iPos >= src.getSize() ) - iPos = -1; - return *this; - } - - const_iterator operator--( int ) - { - if( iPos < 0 ) - throw ArrayException( - "Cannot increment iterator past end of array."); - iPos--; - if( iPos < 0 ) - iPos = -1; - return *this; - } - - const_iterator operator--() - { - if( iPos < src.getSize() ) - iPos--; - if( iPos <= 0 ) - iPos = -1; - return *this; - } - - bool operator==( const const_iterator &oth ) const - { - return iPos == oth.iPos; - } - - bool operator!=( const const_iterator &oth ) const - { - return iPos != oth.iPos; - } - - const_iterator operator=( const const_iterator &oth ) - { - if( &src != &oth.src ) - throw ArrayException( - "Cannot mix iterators from different array objects."); - iPos = oth.iPos; - } - - const value &operator*() const - { - if( iPos < 0 ) - throw ArrayException( - "Cannot dereference finished iterator."); - return src[iPos]; - } - - long getIndex() const - { - return iPos; - } - - operator bool() const - { - return iPos >= 0; - } - - bool isValid() const - { - return iPos >= 0; - } - } const_iterator; - - iterator begin() - { - return iterator( *this ); - } - - const_iterator begin() const - { - return const_iterator( *this ); - } - - iterator end() - { - return iterator( *this, -1 ); - } - - const_iterator end() const - { - return const_iterator( *this, -1 ); - } - - MyType &insert( iterator i, const value &rVal ) - { - if( i.iPos == -1 ) - { - append( rVal ); - return *this; - } - - _hardCopy(); - if( core->iSize == core->iCapacity ) - { - core->setCapacity( core->iCapacity + inc ); - } - core->iSize++; - - core->va.construct( - &core->pData[core->iSize-1], - core->pData[core->iSize-2] - ); - for( int iPos = core->iSize-2; iPos > i.iPos; iPos-- ) - { - core->va.destroy( &core->pData[iPos] ); - core->va.construct( &core->pData[iPos], core->pData[iPos-1] ); - } - core->va.destroy( &core->pData[i.iPos] ); - core->va.construct( &core->pData[i.iPos], rVal ); - - return *this; - } - - /** - * If order is important, use this. It will delete the suggested item - * and move the rest of the data up a spot. This is a time O(n) - * operation. If the order isn't important, check swapErase - */ - void erase( iterator i ) - { - _hardCopy(); - core->erase( i.iPos ); - } - - void erase( const value &v ) - { - _hardCopy(); - for( int j = 0; j < core->iSize; j++ ) - { - if( core->pData[j] == v ) - { - core->erase( j ); - return; - } - } - } - - void eraseLast() - { - _hardCopy(); - core->erase( core->iSize-1 ); - } - - void eraseFirst() - { - _hardCopy(); - core->erase( 0 ); - } - - /** - * In order to make swapErase faster, what it does is swap the given - * item in the array with the last item, then make the array shorter - * by one. It changes the order of the elements in the array, so it - * should be used carefully, but it is time O(1) instead of O(n) like - * erase. - */ - void swapErase( iterator i ) - { - _hardCopy(); - core->swapErase( i.iPos ); - } - - protected: - virtual Core *_copyCore( Core *src ) - { - Core *pRet = _allocateCore(); - pRet->setCapacity( src->iCapacity ); - pRet->iSize = src->iSize; - for( int j = 0; j < src->iSize; j++ ) - { - pRet->va.construct( &pRet->pData[j], src->pData[j] ); - } - return pRet; - } - - private: - }; - - class Formatter; - Formatter &operator<<( Formatter &rOut, char *sStr ); - Formatter &operator<<( Formatter &rOut, signed char c ); - template - Formatter &operator<<( Formatter &f, const Bu::Array &a ) - { - f << '['; - for( typename Bu::Array::const_iterator i = a.begin(); i; i++ ) - { - if( i != a.begin() ) - f << ", "; - f << *i; - } - f << ']'; - - return f; - } - - template - ArchiveBase &operator<<( ArchiveBase &ar, - const Array &h ) - { - ar << h.getSize(); - for( typename Array::const_iterator i = - h.begin(); i != h.end(); i++ ) - { - ar << (*i); - } - - return ar; - } - - template - ArchiveBase &operator>>(ArchiveBase &ar, Array &h ) - { - h.clear(); - long nSize; - ar >> nSize; - - h.setCapacity( nSize ); - for( long j = 0; j < nSize; j++ ) - { - value v; - ar >> v; - h.append( v ); - } - return ar; - } + subExceptionDecl( ArrayException ) + + template + class Array; + + /** @cond DEVEL */ + template + class ArrayCore + { + friend class Array; + friend class SharedCore< + Array, + ArrayCore + >; + private: + ArrayCore() : + pData( NULL ), + iSize( 0 ), + iCapacity( 0 ) + { } + + void setCapacity( int iNewLen ) + { + //clear(); + //iCapacity = iCapacity; + //pData = va.allocate( iCapacity ); + if( iNewLen <= iCapacity ) return; + value *pNewData = va.allocate( iNewLen ); + if( pData ) + { + for( int j = 0; j < iSize; j++ ) + { + va.construct( &pNewData[j], pData[j] ); + va.destroy( &pData[j] ); + } + va.deallocate( pData, iCapacity ); + } + pData = pNewData; + iCapacity = iNewLen; + } + + virtual ~ArrayCore() + { + clear(); + } + + void clear() + { + if( pData ) + { + for( int j = 0; j < iSize; j++ ) + { + va.destroy( &pData[j] ); + } + va.deallocate( pData, iCapacity ); + pData = NULL; + } + iSize = 0; + iCapacity = 0; + } + + void erase( int iPos ) + { + for( int j = iPos; j < iSize; j++ ) + { + va.destroy( &pData[j] ); + if( j == iSize-1 ) + { + iSize--; + return; + } + va.construct( &pData[j], pData[j+1] ); + } + } + + void swapErase( int iPos ) + { + if( iPos == iSize-1 ) + { + erase( iPos ); + return; + } + va.destroy( &pData[iPos] ); + va.construct( &pData[iPos], pData[iSize-1] ); + va.destroy( &pData[iSize-1] ); + iSize--; + } + + valuealloc va; + value *pData; + long iSize; + long iCapacity; + }; + /** @endcond */ + + /** + * Array type container, just like a normal array only flexible and keeps + * track of your memory for you. + * + *@param value (typename) The type of data to store in your list + *@param valuealloc (typename) Memory Allocator for your value type + *@param linkalloc (typename) Memory Allocator for the list links. + *@ingroup Containers + */ + template > + class Array : public SharedCore< + Array, + ArrayCore + > + { + private: + typedef class Array MyType; + typedef class ArrayCore Core; + + protected: + using SharedCore::core; + using SharedCore::_hardCopy; + using SharedCore::_resetCore; + using SharedCore::_allocateCore; + + public: + struct const_iterator; + struct iterator; + + Array() + { + } + + Array( const MyType &src ) : + SharedCore( src ) + { + } + + Array( long iSetCap ) + { + setCapacity( iSetCap ); + } + + ~Array() + { + } + + bool operator==( const MyType &src ) const + { + if( core == src.core ) + return true; + if( core->iSize != src.core->iSize ) + return false; + + for( int j = 0; j < core->iSize; j++ ) + { + if( core->pData[j] != src.core->pData[j] ) + return false; + } + return true; + } + + bool operator!=( const MyType &src ) const + { + return !(*this == src); + } + + /** + * Clear the array. + */ + void clear() + { + _resetCore(); + } + + MyType &append( const value &rVal ) + { + _hardCopy(); + if( core->iSize == core->iCapacity ) + { + core->setCapacity( core->iCapacity + inc ); + } + + core->va.construct( &core->pData[core->iSize++], rVal ); + + return *this; + } + + MyType &append( const MyType &rVal ) + { + _hardCopy(); + + if( core->iSize + rVal.core->iSize > core->iCapacity ) + { + core->setCapacity( core->iSize + rVal.core->iSize + inc ); + } + + for( int j = 0; j < rVal.core->iSize; j++ ) + { + core->va.construct( + &core->pData[core->iSize++], + rVal.core->pData[j] + ); + } + + return *this; + } + + //operator + value &operator[]( long iIndex ) + { + _hardCopy(); + if( iIndex < 0 || iIndex >= core->iSize ) + throw ArrayException( + "Index %d out of range 0:%d", iIndex, core->iSize ); + + return core->pData[iIndex]; + } + + const value &operator[]( long iIndex ) const + { + if( iIndex < 0 || iIndex >= core->iSize ) + throw ArrayException( + "Index %d out of range 0:%d", iIndex, core->iSize ); + + return core->pData[iIndex]; + } + + value &get( long iIndex ) + { + _hardCopy(); + if( iIndex < 0 || iIndex >= core->iSize ) + throw ArrayException( + "Index %d out of range 0:%d", iIndex, core->iSize ); + + return core->pData[iIndex]; + } + + const value &get( long iIndex ) const + { + if( iIndex < 0 || iIndex >= core->iSize ) + throw ArrayException( + "Index %d out of range 0:%d", iIndex, core->iSize ); + + return core->pData[iIndex]; + } + + value &first() + { + _hardCopy(); + return core->pData[0]; + } + + const value &first() const + { + return core->pData[0]; + } + + value &last() + { + _hardCopy(); + return core->pData[core->iSize-1]; + } + + const value &last() const + { + return core->pData[core->iSize-1]; + } + + /** + * Returns true if the array is empty. The capacity has no bearing on + * this, only the size. + */ + bool isEmpty() const + { + return core->iSize==0; + } + + /** + * Get the current size of the array. + *@returns The current size of the array. + */ + long getSize() const + { + return core->iSize; + } + + /** + * Get the capacity of the array. This number will grow as data is + * added, and is mainly for the curious, it doesn't really determine + * much for the end user. + *@returns The current capacity of the array. + */ + long getCapacity() const + { + return core->iCapacity; + } + + /** + * Change the capacity of the array, very useful if you know you'll be + * adding a large amount of already counted items to the array, makes + * the appending much faster afterwords. + *@param iNewLen The new capacity of the array. + *@todo Set this up so it can reduce the size of the array as well as + * make it bigger. + */ + void setCapacity( long iNewLen ) + { + _hardCopy(); + core->setCapacity( iNewLen ); + } + + typedef struct iterator + { + friend class Array; + private: + iterator( MyType &src, long iPos=0 ) : + src( src ), + iPos( iPos ) + { + if( this->iPos >= src.getSize() ) + this->iPos = -1; + } + + MyType &src; + long iPos; + + public: + iterator operator++( int ) + { + if( iPos < 0 ) + throw ArrayException( + "Cannot increment iterator past end of array."); + iPos++; + if( iPos >= src.getSize() ) + iPos = -1; + return *this; + } + + iterator operator++() + { + if( iPos >= 0 ) + iPos++; + if( iPos >= src.getSize() ) + iPos = -1; + return *this; + } + + iterator operator+( int iAmnt ) + { + if( iPos < 0 ) + throw ArrayException( + "Cannot increment iterator past end of array."); + iPos += iAmnt; + if( iPos >= src.getSize() ) + iPos = -1; + return *this; + } + + iterator operator--( int ) + { + if( iPos < 0 ) + throw ArrayException( + "Cannot increment iterator past end of array."); + iPos--; + if( iPos < 0 ) + iPos = -1; + return *this; + } + + iterator operator--() + { + if( iPos < src.getSize() ) + iPos--; + if( iPos <= 0 ) + iPos = -1; + return *this; + } + + iterator operator-( int iAmnt ) + { + if( iPos < src.getSize() ) + iPos -= iAmnt; + if( iPos <= 0 ) + iPos = -1; + return *this; + } + + bool operator==( const iterator &oth ) const + { + return iPos == oth.iPos; + } + + bool operator!=( const iterator &oth ) const + { + return iPos != oth.iPos; + } + + iterator operator=( const iterator &oth ) + { + if( &src != &oth.src ) + throw ArrayException( + "Cannot mix iterators from different array objects."); + iPos = oth.iPos; + } + + value &operator*() + { + if( iPos < 0 ) + throw ArrayException( + "Cannot dereference finished iterator."); + return src[iPos]; + } + + long getIndex() const + { + return iPos; + } + + operator bool() const + { + return iPos >= 0; + } + + bool isValid() const + { + return iPos >= 0; + } + } iterator; + + typedef struct const_iterator + { + friend class Array; + private: + const_iterator( const MyType &src, long iPos=0 ) : + src( src ), + iPos( iPos ) + { + if( this->iPos >= src.getSize() ) + this->iPos = -1; + } + + const MyType &src; + long iPos; + + public: + const_iterator( iterator &rSrc ) : + src( rSrc.src ), + iPos( rSrc.iPos ) + { + } + const_iterator operator++( int ) + { + if( iPos < 0 ) + throw ArrayException( + "Cannot increment iterator past end of array."); + iPos++; + if( iPos >= src.getSize() ) + iPos = -1; + return *this; + } + + const_iterator operator++() + { + if( iPos >= 0 ) + iPos++; + if( iPos >= src.getSize() ) + iPos = -1; + return *this; + } + + const_iterator operator--( int ) + { + if( iPos < 0 ) + throw ArrayException( + "Cannot increment iterator past end of array."); + iPos--; + if( iPos < 0 ) + iPos = -1; + return *this; + } + + const_iterator operator--() + { + if( iPos < src.getSize() ) + iPos--; + if( iPos <= 0 ) + iPos = -1; + return *this; + } + + bool operator==( const const_iterator &oth ) const + { + return iPos == oth.iPos; + } + + bool operator!=( const const_iterator &oth ) const + { + return iPos != oth.iPos; + } + + const_iterator operator=( const const_iterator &oth ) + { + if( &src != &oth.src ) + throw ArrayException( + "Cannot mix iterators from different array objects."); + iPos = oth.iPos; + } + + const value &operator*() const + { + if( iPos < 0 ) + throw ArrayException( + "Cannot dereference finished iterator."); + return src[iPos]; + } + + long getIndex() const + { + return iPos; + } + + operator bool() const + { + return iPos >= 0; + } + + bool isValid() const + { + return iPos >= 0; + } + } const_iterator; + + iterator begin() + { + return iterator( *this ); + } + + const_iterator begin() const + { + return const_iterator( *this ); + } + + iterator end() + { + return iterator( *this, -1 ); + } + + const_iterator end() const + { + return const_iterator( *this, -1 ); + } + + MyType &insert( iterator i, const value &rVal ) + { + if( i.iPos == -1 ) + { + append( rVal ); + return *this; + } + + _hardCopy(); + if( core->iSize == core->iCapacity ) + { + core->setCapacity( core->iCapacity + inc ); + } + core->iSize++; + + core->va.construct( + &core->pData[core->iSize-1], + core->pData[core->iSize-2] + ); + for( int iPos = core->iSize-2; iPos > i.iPos; iPos-- ) + { + core->va.destroy( &core->pData[iPos] ); + core->va.construct( &core->pData[iPos], core->pData[iPos-1] ); + } + core->va.destroy( &core->pData[i.iPos] ); + core->va.construct( &core->pData[i.iPos], rVal ); + + return *this; + } + + /** + * If order is important, use this. It will delete the suggested item + * and move the rest of the data up a spot. This is a time O(n) + * operation. If the order isn't important, check swapErase + */ + void erase( iterator i ) + { + _hardCopy(); + core->erase( i.iPos ); + } + + void erase( const value &v ) + { + _hardCopy(); + for( int j = 0; j < core->iSize; j++ ) + { + if( core->pData[j] == v ) + { + core->erase( j ); + return; + } + } + } + + void eraseLast() + { + _hardCopy(); + core->erase( core->iSize-1 ); + } + + void eraseFirst() + { + _hardCopy(); + core->erase( 0 ); + } + + /** + * In order to make swapErase faster, what it does is swap the given + * item in the array with the last item, then make the array shorter + * by one. It changes the order of the elements in the array, so it + * should be used carefully, but it is time O(1) instead of O(n) like + * erase. + */ + void swapErase( iterator i ) + { + _hardCopy(); + core->swapErase( i.iPos ); + } + + protected: + virtual Core *_copyCore( Core *src ) + { + Core *pRet = _allocateCore(); + pRet->setCapacity( src->iCapacity ); + pRet->iSize = src->iSize; + for( int j = 0; j < src->iSize; j++ ) + { + pRet->va.construct( &pRet->pData[j], src->pData[j] ); + } + return pRet; + } + + private: + }; + + class Formatter; + Formatter &operator<<( Formatter &rOut, char *sStr ); + Formatter &operator<<( Formatter &rOut, signed char c ); + template + Formatter &operator<<( Formatter &f, const Bu::Array &a ) + { + f << '['; + for( typename Bu::Array::const_iterator i = a.begin(); i; i++ ) + { + if( i != a.begin() ) + f << ", "; + f << *i; + } + f << ']'; + + return f; + } + + template + ArchiveBase &operator<<( ArchiveBase &ar, + const Array &h ) + { + ar << h.getSize(); + for( typename Array::const_iterator i = + h.begin(); i != h.end(); i++ ) + { + ar << (*i); + } + + return ar; + } + + template + ArchiveBase &operator>>(ArchiveBase &ar, Array &h ) + { + h.clear(); + long nSize; + ar >> nSize; + + h.setCapacity( nSize ); + for( long j = 0; j < nSize; j++ ) + { + value v; + ar >> v; + h.append( v ); + } + return ar; + } } diff --git a/src/stable/atom.h b/src/stable/atom.h index 105c29a..9679ab6 100644 --- a/src/stable/atom.h +++ b/src/stable/atom.h @@ -15,133 +15,133 @@ namespace Bu { - /** - * - *@ingroup Containers - */ - template > - class Atom - { - private: - typedef struct Atom MyType; - - public: - Atom() : - pData( NULL ) - { - } - - Atom( const MyType &oth ) : - pData( NULL ) - { - if( oth.pData ) - set( *oth.pData ); - } - - Atom( const t &oth ) : - pData( NULL ) - { - set( oth ); - } - - virtual ~Atom() - { - clear(); - } - - bool has() const - { - return (pData != NULL); - } - - void set( const t &val ) - { - clear(); - pData = ta.allocate( 1 ); - ta.construct( pData, val ); - } - - t &get() - { - if( !pData ) - throw Bu::ExceptionBase("Not set"); - return *pData; - } - - const t &get() const - { - if( !pData ) - throw Bu::ExceptionBase("Not set"); - return *pData; - } - - void clear() - { - if( pData ) - { - ta.destroy( pData ); - ta.deallocate( pData, 1 ); - pData = NULL; - } - } - - operator const t &() const - { - if( !pData ) - throw Bu::ExceptionBase("Not set"); - return *pData; - } - - operator t &() - { - if( !pData ) - throw Bu::ExceptionBase("Not set"); - return *pData; - } - - MyType &operator =( const t &oth ) - { - set( oth ); - - return *this; - } - - MyType &operator =( const MyType &oth ) - { - if( oth.pData ) - set( *oth.pData ); - - return *this; - } - - bool operator ==( const MyType &oth ) - { - return (*pData) == (*oth.pData); - } - - bool operator ==( const t &oth ) - { - return (*pData) == oth; - } - - t *operator ->() - { - if( !pData ) - throw Bu::ExceptionBase("Not set"); - return pData; - } - - t &operator *() - { - if( !pData ) - throw Bu::ExceptionBase("Not set"); - return *pData; - } - - private: - t *pData; - talloc ta; - }; + /** + * + *@ingroup Containers + */ + template > + class Atom + { + private: + typedef struct Atom MyType; + + public: + Atom() : + pData( NULL ) + { + } + + Atom( const MyType &oth ) : + pData( NULL ) + { + if( oth.pData ) + set( *oth.pData ); + } + + Atom( const t &oth ) : + pData( NULL ) + { + set( oth ); + } + + virtual ~Atom() + { + clear(); + } + + bool has() const + { + return (pData != NULL); + } + + void set( const t &val ) + { + clear(); + pData = ta.allocate( 1 ); + ta.construct( pData, val ); + } + + t &get() + { + if( !pData ) + throw Bu::ExceptionBase("Not set"); + return *pData; + } + + const t &get() const + { + if( !pData ) + throw Bu::ExceptionBase("Not set"); + return *pData; + } + + void clear() + { + if( pData ) + { + ta.destroy( pData ); + ta.deallocate( pData, 1 ); + pData = NULL; + } + } + + operator const t &() const + { + if( !pData ) + throw Bu::ExceptionBase("Not set"); + return *pData; + } + + operator t &() + { + if( !pData ) + throw Bu::ExceptionBase("Not set"); + return *pData; + } + + MyType &operator =( const t &oth ) + { + set( oth ); + + return *this; + } + + MyType &operator =( const MyType &oth ) + { + if( oth.pData ) + set( *oth.pData ); + + return *this; + } + + bool operator ==( const MyType &oth ) + { + return (*pData) == (*oth.pData); + } + + bool operator ==( const t &oth ) + { + return (*pData) == oth; + } + + t *operator ->() + { + if( !pData ) + throw Bu::ExceptionBase("Not set"); + return pData; + } + + t &operator *() + { + if( !pData ) + throw Bu::ExceptionBase("Not set"); + return *pData; + } + + private: + t *pData; + talloc ta; + }; } #endif diff --git a/src/stable/base64.cpp b/src/stable/base64.cpp index 5ace999..2dc123f 100644 --- a/src/stable/base64.cpp +++ b/src/stable/base64.cpp @@ -10,210 +10,210 @@ namespace Bu { subExceptionDef( Base64Exception ) } const char Bu::Base64::tblEnc[65] = { - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" }; Bu::Base64::Base64( Bu::Stream &rNext, int iChunkSize ) : - Bu::Filter( rNext ), - iBPos( 0 ), - iBuf( 0 ), - iRPos( 0 ), - iChars( 0 ), - bEosIn( false ), - iTotalIn( 0 ), - iTotalOut( 0 ), - eMode( Nothing ), - iChunkSize( iChunkSize ), - iCurChunk( 0 ) + Bu::Filter( rNext ), + iBPos( 0 ), + iBuf( 0 ), + iRPos( 0 ), + iChars( 0 ), + bEosIn( false ), + iTotalIn( 0 ), + iTotalOut( 0 ), + eMode( Nothing ), + iChunkSize( iChunkSize ), + iCurChunk( 0 ) { - start(); - - memset( tblDec, 0, 80 ); - for( int j = 0; j < 64; j++ ) - { - tblDec[tblEnc[j]-'+'] = j; - // printf("'%c' = %d\n", tblEnc[j], j ); - } - /* - for( int j = 0; j < 64; j++ ) - { - printf("'%c' = '%c' (%d = %d)\n", - tblEnc[j], tblEnc[tblDec[tblEnc[j]-'+']], - j, tblDec[tblEnc[j]-'+'] ); - }*/ - - // The following is used to compute the table size for the decoding table. - /* - char low='A', high='A'; - for( int j = 0; j < 64; j++ ) - { - if( tblEnc[j] < low ) - low = tblEnc[j]; - if( tblEnc[j] > high ) - high = tblEnc[j]; - } - - printf("'%c' - '%c' (%d - %d) (%d)\n", low, high, low, high, high-low ); - */ + start(); + + memset( tblDec, 0, 80 ); + for( int j = 0; j < 64; j++ ) + { + tblDec[tblEnc[j]-'+'] = j; + // printf("'%c' = %d\n", tblEnc[j], j ); + } + /* + for( int j = 0; j < 64; j++ ) + { + printf("'%c' = '%c' (%d = %d)\n", + tblEnc[j], tblEnc[tblDec[tblEnc[j]-'+']], + j, tblDec[tblEnc[j]-'+'] ); + }*/ + + // The following is used to compute the table size for the decoding table. + /* + char low='A', high='A'; + for( int j = 0; j < 64; j++ ) + { + if( tblEnc[j] < low ) + low = tblEnc[j]; + if( tblEnc[j] > high ) + high = tblEnc[j]; + } + + printf("'%c' - '%c' (%d - %d) (%d)\n", low, high, low, high, high-low ); + */ } Bu::Base64::~Base64() { - stop(); + stop(); } void Bu::Base64::start() { - iCurChunk = 0; + iCurChunk = 0; } Bu::size Bu::Base64::stop() { - if( eMode == Encode ) - { - char outBuf[4]; - int iBUsed = 4-(3-iBPos); - if( iBPos == 0 ) - return iTotalOut; - for( int k = 0; k < 4; k++ ) - { - outBuf[3-k] = tblEnc[(iBuf>>(6*k))&0x3f]; - } - for( int k = iBUsed; k < 4; k++ ) - { - outBuf[k] = '='; - } - iCurChunk += 4; - if( iChunkSize && iCurChunk >= iChunkSize ) - { - iCurChunk = iCurChunk-iChunkSize; - iTotalOut += rNext.write( outBuf, 4-iCurChunk ); - iTotalOut += rNext.write("\r\n", 2 ); - iTotalOut += rNext.write( outBuf+(4-iCurChunk), iCurChunk ); - } - else - iTotalOut += rNext.write( outBuf, 4 ); - return iTotalOut; - } - else - { - return iTotalIn; - } + if( eMode == Encode ) + { + char outBuf[4]; + int iBUsed = 4-(3-iBPos); + if( iBPos == 0 ) + return iTotalOut; + for( int k = 0; k < 4; k++ ) + { + outBuf[3-k] = tblEnc[(iBuf>>(6*k))&0x3f]; + } + for( int k = iBUsed; k < 4; k++ ) + { + outBuf[k] = '='; + } + iCurChunk += 4; + if( iChunkSize && iCurChunk >= iChunkSize ) + { + iCurChunk = iCurChunk-iChunkSize; + iTotalOut += rNext.write( outBuf, 4-iCurChunk ); + iTotalOut += rNext.write("\r\n", 2 ); + iTotalOut += rNext.write( outBuf+(4-iCurChunk), iCurChunk ); + } + else + iTotalOut += rNext.write( outBuf, 4 ); + return iTotalOut; + } + else + { + return iTotalIn; + } } Bu::size Bu::Base64::read( void *pBuf, Bu::size nBytes ) { - if( eMode == Encode ) - throw Bu::Base64Exception("Cannot read from an output stream."); - eMode = Decode; - - if( bEosIn == true && iRPos == iChars ) - return 0; - Bu::size sIn = 0; - char buf[4]; - while( sIn < nBytes ) - { - for(; iRPos < iChars && sIn < nBytes; iRPos++, sIn++ ) - { - ((unsigned char *)pBuf)[sIn] = (iBuf>>(8*(2-iRPos)))&0xFF; - } - if( iRPos == iChars ) - { - if( bEosIn == true ) - return sIn; - else - iRPos = 0; - } - else if( sIn == nBytes ) - return sIn; - //if( rNext.read( buf, 4 ) == 0 ) - // return sIn; - for( int j = 0; j < 4; j++ ) - { - if( rNext.read( &buf[j], 1 ) == 0 ) - { - if( rNext.isEos() ) - { - if( iRPos == 0 ) - iRPos = iChars; - bEosIn = true; - if( j != 0 ) - { - throw Base64Exception( - "Premature end of stream detected while " - "decoding Base64 data." - ); - } - } - return sIn; - } - if( buf[j] == ' ' || buf[j] == '\t' || - buf[j] == '\n' || buf[j] == '\r' ) - { - j--; - } - } - iChars = 3; - iBuf = 0; - for( int j = 0; j < 4; j++ ) - { - if( buf[j] == '=' ) - { - iChars--; - bEosIn = true; - } - else - iBuf |= (tblDec[buf[j]-'+']&0x3f)<<((3-j)*6); - //printf("%d: %06X (%02X)\n", j, iBuf, (tblDec[buf[j]-'+']&0x3f) ); - } - } - - return sIn; + if( eMode == Encode ) + throw Bu::Base64Exception("Cannot read from an output stream."); + eMode = Decode; + + if( bEosIn == true && iRPos == iChars ) + return 0; + Bu::size sIn = 0; + char buf[4]; + while( sIn < nBytes ) + { + for(; iRPos < iChars && sIn < nBytes; iRPos++, sIn++ ) + { + ((unsigned char *)pBuf)[sIn] = (iBuf>>(8*(2-iRPos)))&0xFF; + } + if( iRPos == iChars ) + { + if( bEosIn == true ) + return sIn; + else + iRPos = 0; + } + else if( sIn == nBytes ) + return sIn; + //if( rNext.read( buf, 4 ) == 0 ) + // return sIn; + for( int j = 0; j < 4; j++ ) + { + if( rNext.read( &buf[j], 1 ) == 0 ) + { + if( rNext.isEos() ) + { + if( iRPos == 0 ) + iRPos = iChars; + bEosIn = true; + if( j != 0 ) + { + throw Base64Exception( + "Premature end of stream detected while " + "decoding Base64 data." + ); + } + } + return sIn; + } + if( buf[j] == ' ' || buf[j] == '\t' || + buf[j] == '\n' || buf[j] == '\r' ) + { + j--; + } + } + iChars = 3; + iBuf = 0; + for( int j = 0; j < 4; j++ ) + { + if( buf[j] == '=' ) + { + iChars--; + bEosIn = true; + } + else + iBuf |= (tblDec[buf[j]-'+']&0x3f)<<((3-j)*6); + //printf("%d: %06X (%02X)\n", j, iBuf, (tblDec[buf[j]-'+']&0x3f) ); + } + } + + return sIn; } Bu::size Bu::Base64::write( const void *pBuf, Bu::size nBytes ) { - if( eMode == Decode ) - throw Bu::Base64Exception("Cannot write to an input stream."); - eMode = Encode; - - Bu::size sOut = 0; - char outBuf[4]; - for( Bu::size j = 0; j < nBytes; j++ ) - { - iBuf |= (((uint8_t *)pBuf)[j])<<((2-iBPos++)*8); - if( iBPos == 3 ) - { - for( int k = 0; k < 4; k++ ) - { - outBuf[3-k] = tblEnc[(iBuf>>(6*k))&0x3f]; - } - iCurChunk += 4; - if( iChunkSize && iCurChunk >= iChunkSize ) - { - iCurChunk = iCurChunk-iChunkSize; - sOut += rNext.write( outBuf, 4-iCurChunk ); - sOut += rNext.write("\r\n", 2 ); - sOut += rNext.write( outBuf+(4-iCurChunk), iCurChunk ); - } - else - sOut += rNext.write( outBuf, 4 ); - iBPos = iBuf = 0; - } - } - iTotalOut += sOut; - return sOut; + if( eMode == Decode ) + throw Bu::Base64Exception("Cannot write to an input stream."); + eMode = Encode; + + Bu::size sOut = 0; + char outBuf[4]; + for( Bu::size j = 0; j < nBytes; j++ ) + { + iBuf |= (((uint8_t *)pBuf)[j])<<((2-iBPos++)*8); + if( iBPos == 3 ) + { + for( int k = 0; k < 4; k++ ) + { + outBuf[3-k] = tblEnc[(iBuf>>(6*k))&0x3f]; + } + iCurChunk += 4; + if( iChunkSize && iCurChunk >= iChunkSize ) + { + iCurChunk = iCurChunk-iChunkSize; + sOut += rNext.write( outBuf, 4-iCurChunk ); + sOut += rNext.write("\r\n", 2 ); + sOut += rNext.write( outBuf+(4-iCurChunk), iCurChunk ); + } + else + sOut += rNext.write( outBuf, 4 ); + iBPos = iBuf = 0; + } + } + iTotalOut += sOut; + return sOut; } bool Bu::Base64::isOpen() { - return true; + return true; } bool Bu::Base64::isEos() { - if( bEosIn == true && iRPos == iChars ) - return true; - return false; + if( bEosIn == true && iRPos == iChars ) + return true; + return false; } diff --git a/src/stable/base64.h b/src/stable/base64.h index b10aaeb..695a5ea 100644 --- a/src/stable/base64.h +++ b/src/stable/base64.h @@ -13,47 +13,47 @@ namespace Bu { - subExceptionDecl( Base64Exception ); - - /** - * - *@ingroup Streams - */ - class Base64 : public Bu::Filter - { - public: - Base64( Bu::Stream &rNext, int iChunkSize=0 ); - virtual ~Base64(); - - virtual void start(); - virtual Bu::size stop(); - virtual Bu::size read( void *pBuf, Bu::size nBytes ); - virtual Bu::size write( const void *pBuf, Bu::size nBytes ); - - virtual bool isOpen(); - - virtual bool isEos(); - - private: - int iBPos; - int iBuf; - int iRPos; - int iChars; - bool bEosIn; - Bu::size iTotalIn; - Bu::size iTotalOut; - static const char tblEnc[65]; - char tblDec[80]; - enum Mode - { - Nothing = 0x00, - Encode = 0x01, - Decode = 0x02, - }; - Mode eMode; - int iChunkSize; - int iCurChunk; - }; + subExceptionDecl( Base64Exception ); + + /** + * + *@ingroup Streams + */ + class Base64 : public Bu::Filter + { + public: + Base64( Bu::Stream &rNext, int iChunkSize=0 ); + virtual ~Base64(); + + virtual void start(); + virtual Bu::size stop(); + virtual Bu::size read( void *pBuf, Bu::size nBytes ); + virtual Bu::size write( const void *pBuf, Bu::size nBytes ); + + virtual bool isOpen(); + + virtual bool isEos(); + + private: + int iBPos; + int iBuf; + int iRPos; + int iChars; + bool bEosIn; + Bu::size iTotalIn; + Bu::size iTotalOut; + static const char tblEnc[65]; + char tblDec[80]; + enum Mode + { + Nothing = 0x00, + Encode = 0x01, + Decode = 0x02, + }; + Mode eMode; + int iChunkSize; + int iCurChunk; + }; }; #endif diff --git a/src/stable/buffer.cpp b/src/stable/buffer.cpp index 16c3e2f..c787499 100644 --- a/src/stable/buffer.cpp +++ b/src/stable/buffer.cpp @@ -8,26 +8,26 @@ #include "bu/buffer.h" Bu::Buffer::Buffer( Bu::Stream &rNext, int iWhat, int iBufSize ) : - Bu::Filter( rNext ), - sSoFar( 0 ), - iBufSize( iBufSize ), - sReadBuf( NULL ), - sWriteBuf( NULL ), - iReadBufFill( 0 ), - iReadPos( 0 ), - iWriteBufFill( 0 ), - iWritePos( 0 ), - iWhat( iWhat ) + Bu::Filter( rNext ), + sSoFar( 0 ), + iBufSize( iBufSize ), + sReadBuf( NULL ), + sWriteBuf( NULL ), + iReadBufFill( 0 ), + iReadPos( 0 ), + iWriteBufFill( 0 ), + iWritePos( 0 ), + iWhat( iWhat ) { - sReadBuf = new char[iBufSize]; - sWriteBuf = new char[iBufSize]; + sReadBuf = new char[iBufSize]; + sWriteBuf = new char[iBufSize]; } Bu::Buffer::~Buffer() { - flush(); - delete[] sReadBuf; - delete[] sWriteBuf; + flush(); + delete[] sReadBuf; + delete[] sWriteBuf; } void Bu::Buffer::start() @@ -36,135 +36,135 @@ void Bu::Buffer::start() Bu::size Bu::Buffer::stop() { - flush(); - iReadBufFill = iReadPos = iWriteBufFill = iWritePos = 0; - return sSoFar; + flush(); + iReadBufFill = iReadPos = iWriteBufFill = iWritePos = 0; + return sSoFar; } void Bu::Buffer::fillReadBuf() { - if( iReadBufFill+iReadPos < iBufSize ) - { - iReadBufFill += rNext.read( - sReadBuf+iReadPos+iReadBufFill, - iBufSize-iReadBufFill-iReadPos - ); - } + if( iReadBufFill+iReadPos < iBufSize ) + { + iReadBufFill += rNext.read( + sReadBuf+iReadPos+iReadBufFill, + iBufSize-iReadBufFill-iReadPos + ); + } } Bu::size Bu::Buffer::read( void *pBuf, Bu::size nBytes ) { - if( (iWhat&Read) == 0 ) - return rNext.read( pBuf, nBytes ); - - if( nBytes <= 0 ) - { - fillReadBuf(); - return 0; - } - - Bu::size nTotRead = 0; -// fillReadBuf(); - - do - { - int iAmnt = nBytes-nTotRead; - if( iAmnt > iReadBufFill ) - { - iAmnt = iReadBufFill; - } - if( iAmnt > 0 ) - { - memcpy( ((char *)pBuf)+nTotRead, sReadBuf+iReadPos, iAmnt ); - iReadPos += iAmnt; - nTotRead += iAmnt; - iReadBufFill -= iAmnt; - } - if( iReadBufFill == 0 ) - { - iReadPos = 0; - fillReadBuf(); - } - } - while( nTotRead < nBytes && iReadBufFill > 0 ); - - //printf("Buffer: %db returned, %db remain in buffer.\n", nTotRead, iReadBufFill ); - - return nTotRead; + if( (iWhat&Read) == 0 ) + return rNext.read( pBuf, nBytes ); + + if( nBytes <= 0 ) + { + fillReadBuf(); + return 0; + } + + Bu::size nTotRead = 0; +// fillReadBuf(); + + do + { + int iAmnt = nBytes-nTotRead; + if( iAmnt > iReadBufFill ) + { + iAmnt = iReadBufFill; + } + if( iAmnt > 0 ) + { + memcpy( ((char *)pBuf)+nTotRead, sReadBuf+iReadPos, iAmnt ); + iReadPos += iAmnt; + nTotRead += iAmnt; + iReadBufFill -= iAmnt; + } + if( iReadBufFill == 0 ) + { + iReadPos = 0; + fillReadBuf(); + } + } + while( nTotRead < nBytes && iReadBufFill > 0 ); + + //printf("Buffer: %db returned, %db remain in buffer.\n", nTotRead, iReadBufFill ); + + return nTotRead; } Bu::size Bu::Buffer::write( const void *pBuf, Bu::size nBytes ) { - if( (iWhat&Write) == 0 ) - return rNext.write( pBuf, nBytes ); - - Bu::size nTotWrote = 0; - - do - { - int iAmnt = nBytes-nTotWrote; - if( iAmnt > iBufSize-iWritePos-iWriteBufFill ) - { - iAmnt = iBufSize-iWritePos-iWriteBufFill; - } - if( iAmnt > 0 ) - { - memcpy( - sWriteBuf+iWritePos+iWriteBufFill, - ((char *)pBuf)+nTotWrote, - iAmnt - ); - nTotWrote += iAmnt; - iWriteBufFill += iAmnt; - //printf("Buffer: Moved %db to write buffer, %db filled now.\n", - //iAmnt, iWriteBufFill ); - } - while( iWritePos+iWriteBufFill == iBufSize ) - { - //printf("iWritePos = %d\n", iWritePos ); - int iWr = rNext.write( sWriteBuf+iWritePos, iWriteBufFill ); - //printf("Buffer: Wrote %db from buffer to stream, %db filled now.\n", iWr, iWriteBufFill-iWr ); - if( iWr == 0 ) - { - return nTotWrote; - } - else if( iWr == iWriteBufFill ) - { - iWritePos = iWriteBufFill = 0; - } - else - { - iWritePos += iWr; - iWriteBufFill -= iWr; - } - } - } - while( nTotWrote < nBytes && iWriteBufFill < iBufSize+iWritePos ); - - return nTotWrote; + if( (iWhat&Write) == 0 ) + return rNext.write( pBuf, nBytes ); + + Bu::size nTotWrote = 0; + + do + { + int iAmnt = nBytes-nTotWrote; + if( iAmnt > iBufSize-iWritePos-iWriteBufFill ) + { + iAmnt = iBufSize-iWritePos-iWriteBufFill; + } + if( iAmnt > 0 ) + { + memcpy( + sWriteBuf+iWritePos+iWriteBufFill, + ((char *)pBuf)+nTotWrote, + iAmnt + ); + nTotWrote += iAmnt; + iWriteBufFill += iAmnt; + //printf("Buffer: Moved %db to write buffer, %db filled now.\n", + //iAmnt, iWriteBufFill ); + } + while( iWritePos+iWriteBufFill == iBufSize ) + { + //printf("iWritePos = %d\n", iWritePos ); + int iWr = rNext.write( sWriteBuf+iWritePos, iWriteBufFill ); + //printf("Buffer: Wrote %db from buffer to stream, %db filled now.\n", iWr, iWriteBufFill-iWr ); + if( iWr == 0 ) + { + return nTotWrote; + } + else if( iWr == iWriteBufFill ) + { + iWritePos = iWriteBufFill = 0; + } + else + { + iWritePos += iWr; + iWriteBufFill -= iWr; + } + } + } + while( nTotWrote < nBytes && iWriteBufFill < iBufSize+iWritePos ); + + return nTotWrote; } void Bu::Buffer::flush() { - if( (iWhat&Write) == 0 ) - return rNext.flush(); - - if( iWriteBufFill > 0 ) - { - //printf("Buffer: Flushing remaining data, %db.\n", iWriteBufFill ); - int iWr = 0; - do - { - iWr = rNext.write( sWriteBuf+iWritePos, iWriteBufFill ); - //printf("Buffer: %db written to stream.\n", iWr ); - iWritePos += iWr; - iWriteBufFill -= iWr; - } while( iWriteBufFill > 0 && iWr > 0 ); - } + if( (iWhat&Write) == 0 ) + return rNext.flush(); + + if( iWriteBufFill > 0 ) + { + //printf("Buffer: Flushing remaining data, %db.\n", iWriteBufFill ); + int iWr = 0; + do + { + iWr = rNext.write( sWriteBuf+iWritePos, iWriteBufFill ); + //printf("Buffer: %db written to stream.\n", iWr ); + iWritePos += iWr; + iWriteBufFill -= iWr; + } while( iWriteBufFill > 0 && iWr > 0 ); + } } bool Bu::Buffer::isEos() { - return (iReadPos >= (iReadBufFill-1)) && (rNext.isEos()); + return (iReadPos >= (iReadBufFill-1)) && (rNext.isEos()); } diff --git a/src/stable/buffer.h b/src/stable/buffer.h index a8303fa..21a5812 100644 --- a/src/stable/buffer.h +++ b/src/stable/buffer.h @@ -12,47 +12,47 @@ namespace Bu { - class Buffer : public Bu::Filter - { - public: - Buffer( Bu::Stream &rNext, int iWhat=Both, int iBufSize=4096 ); - virtual ~Buffer(); - - enum - { - Write = 1, - Read = 2, - Both = 3 - }; - - virtual void start(); - virtual Bu::size stop(); - - virtual Bu::size read( void *pBuf, Bu::size nBytes ); - virtual Bu::size write( const void *pBuf, Bu::size nBytes ); - using Stream::write; - - Bu::size getReadFill() { return iReadBufFill; } - bool isWritePending() { return iWriteBufFill > 0; } - - virtual void flush(); - - virtual bool isEos(); - - private: - void fillReadBuf(); - - private: - Bu::size sSoFar; - int iBufSize; - char *sReadBuf; - char *sWriteBuf; - int iReadBufFill; - int iReadPos; - int iWriteBufFill; - int iWritePos; - int iWhat; - }; + class Buffer : public Bu::Filter + { + public: + Buffer( Bu::Stream &rNext, int iWhat=Both, int iBufSize=4096 ); + virtual ~Buffer(); + + enum + { + Write = 1, + Read = 2, + Both = 3 + }; + + virtual void start(); + virtual Bu::size stop(); + + virtual Bu::size read( void *pBuf, Bu::size nBytes ); + virtual Bu::size write( const void *pBuf, Bu::size nBytes ); + using Stream::write; + + Bu::size getReadFill() { return iReadBufFill; } + bool isWritePending() { return iWriteBufFill > 0; } + + virtual void flush(); + + virtual bool isEos(); + + private: + void fillReadBuf(); + + private: + Bu::size sSoFar; + int iBufSize; + char *sReadBuf; + char *sWriteBuf; + int iReadBufFill; + int iReadPos; + int iWriteBufFill; + int iWritePos; + int iWhat; + }; }; #endif diff --git a/src/stable/bzip2.cpp b/src/stable/bzip2.cpp index 11b8873..5e660d0 100644 --- a/src/stable/bzip2.cpp +++ b/src/stable/bzip2.cpp @@ -15,222 +15,222 @@ using namespace Bu; Bu::BZip2::BZip2( Bu::Stream &rNext, int nCompression ) : - Bu::Filter( rNext ), - prState( NULL ), - nCompression( nCompression ), - sTotalOut( 0 ) + Bu::Filter( rNext ), + prState( NULL ), + nCompression( nCompression ), + sTotalOut( 0 ) { - TRACE( nCompression ); - start(); + TRACE( nCompression ); + start(); } Bu::BZip2::~BZip2() { - TRACE(); - stop(); + TRACE(); + stop(); } void Bu::BZip2::start() { - TRACE(); + TRACE(); - prState = new bz_stream; - pState->state = NULL; - pState->bzalloc = NULL; - pState->bzfree = NULL; - pState->opaque = NULL; + prState = new bz_stream; + pState->state = NULL; + pState->bzalloc = NULL; + pState->bzfree = NULL; + pState->opaque = NULL; - nBufSize = 64*1024; - pBuf = new char[nBufSize]; + nBufSize = 64*1024; + pBuf = new char[nBufSize]; } Bu::size Bu::BZip2::stop() { - TRACE(); - if( !pState ) - return 0; - - if( pState->state ) - { - if( bReading ) - { - BZ2_bzDecompressEnd( pState ); - delete[] pBuf; - pBuf = NULL; - delete pState; - prState = NULL; - return 0; - } - else - { -// Bu::size sTotal = 0; - for(;;) - { - pState->next_in = NULL; - pState->avail_in = 0; - pState->avail_out = nBufSize; - pState->next_out = pBuf; - int res = BZ2_bzCompress( pState, BZ_FINISH ); - if( pState->avail_out < nBufSize ) - { - sTotalOut += rNext.write( pBuf, nBufSize-pState->avail_out ); - } - if( res == BZ_STREAM_END ) - break; - } - BZ2_bzCompressEnd( pState ); - delete[] pBuf; - pBuf = NULL; - delete pState; - prState = NULL; - return sTotalOut; - } - } - return 0; + TRACE(); + if( !pState ) + return 0; + + if( pState->state ) + { + if( bReading ) + { + BZ2_bzDecompressEnd( pState ); + delete[] pBuf; + pBuf = NULL; + delete pState; + prState = NULL; + return 0; + } + else + { +// Bu::size sTotal = 0; + for(;;) + { + pState->next_in = NULL; + pState->avail_in = 0; + pState->avail_out = nBufSize; + pState->next_out = pBuf; + int res = BZ2_bzCompress( pState, BZ_FINISH ); + if( pState->avail_out < nBufSize ) + { + sTotalOut += rNext.write( pBuf, nBufSize-pState->avail_out ); + } + if( res == BZ_STREAM_END ) + break; + } + BZ2_bzCompressEnd( pState ); + delete[] pBuf; + pBuf = NULL; + delete pState; + prState = NULL; + return sTotalOut; + } + } + return 0; } void Bu::BZip2::bzError( int code ) { - TRACE( code ); - switch( code ) - { - case BZ_OK: - case BZ_RUN_OK: - case BZ_FLUSH_OK: - case BZ_FINISH_OK: - return; + TRACE( code ); + switch( code ) + { + case BZ_OK: + case BZ_RUN_OK: + case BZ_FLUSH_OK: + case BZ_FINISH_OK: + return; - case BZ_CONFIG_ERROR: - throw ExceptionBase("BZip2: Library configured improperly, reinstall."); + case BZ_CONFIG_ERROR: + throw ExceptionBase("BZip2: Library configured improperly, reinstall."); - case BZ_SEQUENCE_ERROR: - throw ExceptionBase("BZip2: Functions were called in an invalid sequence."); + case BZ_SEQUENCE_ERROR: + throw ExceptionBase("BZip2: Functions were called in an invalid sequence."); - case BZ_PARAM_ERROR: - throw ExceptionBase("BZip2: Invalid parameter was passed into a function."); + case BZ_PARAM_ERROR: + throw ExceptionBase("BZip2: Invalid parameter was passed into a function."); - case BZ_MEM_ERROR: - throw ExceptionBase("BZip2: Couldn't allocate sufficient memory."); + case BZ_MEM_ERROR: + throw ExceptionBase("BZip2: Couldn't allocate sufficient memory."); - case BZ_DATA_ERROR: - throw ExceptionBase("BZip2: Data was corrupted before decompression."); + case BZ_DATA_ERROR: + throw ExceptionBase("BZip2: Data was corrupted before decompression."); - case BZ_DATA_ERROR_MAGIC: - throw ExceptionBase("BZip2: Stream does not appear to be bzip2 data."); + case BZ_DATA_ERROR_MAGIC: + throw ExceptionBase("BZip2: Stream does not appear to be bzip2 data."); - case BZ_IO_ERROR: - throw ExceptionBase("BZip2: File couldn't be read from / written to."); + case BZ_IO_ERROR: + throw ExceptionBase("BZip2: File couldn't be read from / written to."); - case BZ_UNEXPECTED_EOF: - throw ExceptionBase("BZip2: End of file encountered before end of stream."); + case BZ_UNEXPECTED_EOF: + throw ExceptionBase("BZip2: End of file encountered before end of stream."); - case BZ_OUTBUFF_FULL: - throw ExceptionBase("BZip2: Buffer not large enough to accomidate data."); + case BZ_OUTBUFF_FULL: + throw ExceptionBase("BZip2: Buffer not large enough to accomidate data."); - default: - throw ExceptionBase("BZip2: Unknown error encountered."); - - } + default: + throw ExceptionBase("BZip2: Unknown error encountered."); + + } } Bu::size Bu::BZip2::read( void *pData, Bu::size nBytes ) { - TRACE( pData, nBytes ); - if( !pState->state ) - { - bReading = true; - BZ2_bzDecompressInit( pState, 0, 0 ); - pState->next_in = pBuf; - pState->avail_in = 0; - } - if( bReading == false ) - throw ExceptionBase("This bzip2 filter is in writing mode, you can't read."); - - int nRead = 0; - int nReadTotal = pState->total_out_lo32; - pState->next_out = (char *)pData; - pState->avail_out = nBytes; - for(;;) - { - int ret = BZ2_bzDecompress( pState ); - - nReadTotal += nRead-pState->avail_out; - - if( ret == BZ_STREAM_END ) - { - if( pState->avail_in > 0 ) - { - if( rNext.isSeekable() ) - { - rNext.seek( -(Bu::size)pState->avail_in ); - } - } - return nBytes-pState->avail_out; - } - bzError( ret ); - - if( pState->avail_out ) - { - if( pState->avail_in == 0 ) - { - nRead = rNext.read( pBuf, nBufSize ); - if( nRead == 0 && rNext.isEos() ) - { - throw Bu::ExceptionBase("Premature end of underlying " - "stream found reading bzip2 stream."); - } - pState->next_in = pBuf; - pState->avail_in = nRead; - } - } - else - { - return nBytes-pState->avail_out; - } - } - return 0; + TRACE( pData, nBytes ); + if( !pState->state ) + { + bReading = true; + BZ2_bzDecompressInit( pState, 0, 0 ); + pState->next_in = pBuf; + pState->avail_in = 0; + } + if( bReading == false ) + throw ExceptionBase("This bzip2 filter is in writing mode, you can't read."); + + int nRead = 0; + int nReadTotal = pState->total_out_lo32; + pState->next_out = (char *)pData; + pState->avail_out = nBytes; + for(;;) + { + int ret = BZ2_bzDecompress( pState ); + + nReadTotal += nRead-pState->avail_out; + + if( ret == BZ_STREAM_END ) + { + if( pState->avail_in > 0 ) + { + if( rNext.isSeekable() ) + { + rNext.seek( -(Bu::size)pState->avail_in ); + } + } + return nBytes-pState->avail_out; + } + bzError( ret ); + + if( pState->avail_out ) + { + if( pState->avail_in == 0 ) + { + nRead = rNext.read( pBuf, nBufSize ); + if( nRead == 0 && rNext.isEos() ) + { + throw Bu::ExceptionBase("Premature end of underlying " + "stream found reading bzip2 stream."); + } + pState->next_in = pBuf; + pState->avail_in = nRead; + } + } + else + { + return nBytes-pState->avail_out; + } + } + return 0; } Bu::size Bu::BZip2::write( const void *pData, Bu::size nBytes ) { - TRACE( pData, nBytes ); - if( !pState->state ) - { - bReading = false; - BZ2_bzCompressInit( pState, nCompression, 0, 30 ); - } - if( bReading == true ) - throw ExceptionBase("This bzip2 filter is in reading mode, you can't write."); - -// Bu::size sTotalOut = 0; - pState->next_in = (char *)pData; - pState->avail_in = nBytes; - for(;;) - { - pState->avail_out = nBufSize; - pState->next_out = pBuf; - - bzError( BZ2_bzCompress( pState, BZ_RUN ) ); - - if( pState->avail_out < nBufSize ) - { - sTotalOut += rNext.write( pBuf, nBufSize-pState->avail_out ); - } - if( pState->avail_in == 0 ) - break; - } - - return nBytes; + TRACE( pData, nBytes ); + if( !pState->state ) + { + bReading = false; + BZ2_bzCompressInit( pState, nCompression, 0, 30 ); + } + if( bReading == true ) + throw ExceptionBase("This bzip2 filter is in reading mode, you can't write."); + +// Bu::size sTotalOut = 0; + pState->next_in = (char *)pData; + pState->avail_in = nBytes; + for(;;) + { + pState->avail_out = nBufSize; + pState->next_out = pBuf; + + bzError( BZ2_bzCompress( pState, BZ_RUN ) ); + + if( pState->avail_out < nBufSize ) + { + sTotalOut += rNext.write( pBuf, nBufSize-pState->avail_out ); + } + if( pState->avail_in == 0 ) + break; + } + + return nBytes; } bool Bu::BZip2::isOpen() { - TRACE(); - return (pState->state != NULL); + TRACE(); + return (pState->state != NULL); } Bu::size Bu::BZip2::getCompressedSize() { - return sTotalOut; + return sTotalOut; } diff --git a/src/stable/bzip2.h b/src/stable/bzip2.h index d92dd2f..d53f325 100644 --- a/src/stable/bzip2.h +++ b/src/stable/bzip2.h @@ -14,36 +14,36 @@ namespace Bu { - /** - * Provides BZip2 type compression and decompression. - * - *@ingroup Streams - *@ingroup Compression - */ - class BZip2 : public Bu::Filter - { - public: - BZip2( Bu::Stream &rNext, int nCompression=9 ); - virtual ~BZip2(); - - virtual void start(); - virtual Bu::size stop(); - virtual Bu::size read( void *pBuf, Bu::size nBytes ); - virtual Bu::size write( const void *pBuf, Bu::size nBytes ); - - virtual bool isOpen(); - - Bu::size getCompressedSize(); - - private: - void bzError( int code ); - void *prState; - bool bReading; - int nCompression; - char *pBuf; - uint32_t nBufSize; - Bu::size sTotalOut; - }; + /** + * Provides BZip2 type compression and decompression. + * + *@ingroup Streams + *@ingroup Compression + */ + class BZip2 : public Bu::Filter + { + public: + BZip2( Bu::Stream &rNext, int nCompression=9 ); + virtual ~BZip2(); + + virtual void start(); + virtual Bu::size stop(); + virtual Bu::size read( void *pBuf, Bu::size nBytes ); + virtual Bu::size write( const void *pBuf, Bu::size nBytes ); + + virtual bool isOpen(); + + Bu::size getCompressedSize(); + + private: + void bzError( int code ); + void *prState; + bool bReading; + int nCompression; + char *pBuf; + uint32_t nBufSize; + Bu::size sTotalOut; + }; } #endif diff --git a/src/stable/client.cpp b/src/stable/client.cpp index 7ae10f7..f5cc75f 100644 --- a/src/stable/client.cpp +++ b/src/stable/client.cpp @@ -14,307 +14,307 @@ #include "bu/clientlinkfactory.h" /** Read buffer size. */ -#define RBS (2000) // 1500 is the nominal MTU for ethernet, it's a good guess +#define RBS (2000) // 1500 is the nominal MTU for ethernet, it's a good guess Bu::Client::Client( Bu::TcpSocket *pSocket, - class Bu::ClientLinkFactory *pfLink ) : - pTopStream( pSocket ), - pSocket( pSocket ), - pProto( NULL ), - bWantsDisconnect( false ), - pfLink( pfLink ) + class Bu::ClientLinkFactory *pfLink ) : + pTopStream( pSocket ), + pSocket( pSocket ), + pProto( NULL ), + bWantsDisconnect( false ), + pfLink( pfLink ) { - lFilts.prepend( pSocket ); + lFilts.prepend( pSocket ); } Bu::Client::~Client() { - for( FilterList::iterator i = lFilts.begin(); i; i++ ) - { - delete *i; - } - pTopStream = pSocket = NULL; - delete pfLink; + for( FilterList::iterator i = lFilts.begin(); i; i++ ) + { + delete *i; + } + pTopStream = pSocket = NULL; + delete pfLink; } void Bu::Client::processInput() { - char buf[RBS]; - Bu::size nRead, nTotal=0; - - for(;;) - { - try - { - nRead = pTopStream->read( buf, RBS ); - - if( nRead == 0 ) - { - break; - } - else - { - nTotal += nRead; - qbRead.write( buf, nRead ); - if( !pTopStream->canRead() ) - break; - } - } - catch( Bu::TcpSocketException &e ) - { - pTopStream->close(); - bWantsDisconnect = true; - break; - } - } - - if( nTotal == 0 ) - { - pTopStream->close(); - bWantsDisconnect = true; - } - - if( pProto && nTotal ) - { - pProto->onNewData( this ); - } + char buf[RBS]; + Bu::size nRead, nTotal=0; + + for(;;) + { + try + { + nRead = pTopStream->read( buf, RBS ); + + if( nRead == 0 ) + { + break; + } + else + { + nTotal += nRead; + qbRead.write( buf, nRead ); + if( !pTopStream->canRead() ) + break; + } + } + catch( Bu::TcpSocketException &e ) + { + pTopStream->close(); + bWantsDisconnect = true; + break; + } + } + + if( nTotal == 0 ) + { + pTopStream->close(); + bWantsDisconnect = true; + } + + if( pProto && nTotal ) + { + pProto->onNewData( this ); + } } void Bu::Client::processOutput() { - char buf[RBS]; - if( qbWrite.getSize() > 0 ) - { - int nAmnt = RBS; - nAmnt = qbWrite.peek( buf, nAmnt ); - int nReal = pTopStream->write( buf, nAmnt ); - qbWrite.seek( nReal ); - pTopStream->flush(); - } + char buf[RBS]; + if( qbWrite.getSize() > 0 ) + { + int nAmnt = RBS; + nAmnt = qbWrite.peek( buf, nAmnt ); + int nReal = pTopStream->write( buf, nAmnt ); + qbWrite.seek( nReal ); + pTopStream->flush(); + } } void Bu::Client::setProtocol( Protocol *pProto ) { - this->pProto = pProto; - this->pProto->onNewConnection( this ); + this->pProto = pProto; + this->pProto->onNewConnection( this ); } Bu::Protocol *Bu::Client::getProtocol() { - return pProto; + return pProto; } void Bu::Client::clearProtocol() { - pProto = NULL; + pProto = NULL; } /* Bu::String &Bu::Client::getInput() { - return sReadBuf; + return sReadBuf; } Bu::String &Bu::Client::getOutput() { - return sWriteBuf; + return sWriteBuf; } */ bool Bu::Client::isOpen() { - if( !pTopStream ) return false; - return pTopStream->isOpen(); + if( !pTopStream ) return false; + return pTopStream->isOpen(); } Bu::size Bu::Client::write( const Bu::String &sData ) { - return qbWrite.write( sData.getStr(), sData.getSize() ); + return qbWrite.write( sData.getStr(), sData.getSize() ); } Bu::size Bu::Client::write( const void *pData, Bu::size nBytes ) { - return qbWrite.write( pData, nBytes ); + return qbWrite.write( pData, nBytes ); } Bu::size Bu::Client::write( int8_t nData ) { - return qbWrite.write( (const char *)&nData, sizeof(nData) ); + return qbWrite.write( (const char *)&nData, sizeof(nData) ); } Bu::size Bu::Client::write( int16_t nData ) { - return qbWrite.write( (const char *)&nData, sizeof(nData) ); + return qbWrite.write( (const char *)&nData, sizeof(nData) ); } Bu::size Bu::Client::write( int32_t nData ) { - return qbWrite.write( (const char *)&nData, sizeof(nData) ); + return qbWrite.write( (const char *)&nData, sizeof(nData) ); } Bu::size Bu::Client::write( int64_t nData ) { - return qbWrite.write( (const char *)&nData, sizeof(nData) ); + return qbWrite.write( (const char *)&nData, sizeof(nData) ); } Bu::size Bu::Client::write( uint8_t nData ) { - return qbWrite.write( (const char *)&nData, sizeof(nData) ); + return qbWrite.write( (const char *)&nData, sizeof(nData) ); } Bu::size Bu::Client::write( uint16_t nData ) { - return qbWrite.write( (const char *)&nData, sizeof(nData) ); + return qbWrite.write( (const char *)&nData, sizeof(nData) ); } Bu::size Bu::Client::write( uint32_t nData ) { - return qbWrite.write( (const char *)&nData, sizeof(nData) ); + return qbWrite.write( (const char *)&nData, sizeof(nData) ); } Bu::size Bu::Client::write( uint64_t nData ) { - return qbWrite.write( (const char *)&nData, sizeof(nData) ); + return qbWrite.write( (const char *)&nData, sizeof(nData) ); } Bu::size Bu::Client::read( void *pData, Bu::size nBytes ) { - return qbRead.read( pData, nBytes ); + return qbRead.read( pData, nBytes ); } Bu::size Bu::Client::peek( void *pData, int nBytes, int nOffset ) { - return qbRead.peek( pData, nBytes, nOffset ); + return qbRead.peek( pData, nBytes, nOffset ); } Bu::size Bu::Client::getInputSize() { - return qbRead.getSize(); + return qbRead.getSize(); } Bu::size Bu::Client::getOutputSize() { - return qbWrite.getSize(); + return qbWrite.getSize(); } const Bu::TcpSocket *Bu::Client::getSocket() const { - return pSocket; + return pSocket; } void Bu::Client::disconnect() { - bWantsDisconnect = true; + bWantsDisconnect = true; } bool Bu::Client::wantsDisconnect() { - return bWantsDisconnect; + return bWantsDisconnect; } void Bu::Client::close() { - pTopStream->close(); + pTopStream->close(); } Bu::ClientLink *Bu::Client::getLink() { - return pfLink->createLink( this ); + return pfLink->createLink( this ); } void Bu::Client::onMessage( const Bu::String &sMsg ) { - if( pProto ) - pProto->onMessage( this, sMsg ); + if( pProto ) + pProto->onMessage( this, sMsg ); } void Bu::Client::tick() { - if( pProto ) - pProto->onTick( this ); + if( pProto ) + pProto->onTick( this ); } Bu::size Bu::Client::tell() { - return 0; + return 0; } void Bu::Client::seek( Bu::size offset ) { - return qbRead.seek( offset ); + return qbRead.seek( offset ); } void Bu::Client::setPos( Bu::size ) { - throw Bu::ExceptionBase(); + throw Bu::ExceptionBase(); } void Bu::Client::setPosEnd( Bu::size ) { - throw Bu::ExceptionBase(); + throw Bu::ExceptionBase(); } bool Bu::Client::isEos() { - return true; + return true; } void Bu::Client::flush() { - processOutput(); + processOutput(); } bool Bu::Client::canRead() { - return qbRead.getSize() > 0; + return qbRead.getSize() > 0; } bool Bu::Client::canWrite() { - return true; + return true; } bool Bu::Client::isReadable() { - return true; + return true; } bool Bu::Client::isWritable() { - return true; + return true; } bool Bu::Client::isSeekable() { - return false; + return false; } bool Bu::Client::isBlocking() { - return false; + return false; } void Bu::Client::setBlocking( bool ) { - throw Bu::ExceptionBase(); + throw Bu::ExceptionBase(); } void Bu::Client::setSize( Bu::size ) { - throw Bu::ExceptionBase(); + throw Bu::ExceptionBase(); } Bu::size Bu::Client::getSize() const { - return 0; + return 0; } Bu::size Bu::Client::getBlockSize() const { - return pSocket->getBlockSize(); + return pSocket->getBlockSize(); } Bu::String Bu::Client::getLocation() const { - return pSocket->getLocation(); + return pSocket->getLocation(); } diff --git a/src/stable/client.h b/src/stable/client.h index 6bd41af..cacc8aa 100644 --- a/src/stable/client.h +++ b/src/stable/client.h @@ -16,118 +16,118 @@ namespace Bu { - class Protocol; - class Stream; - class TcpSocket; - class ClientLinkFactory; - - /** - *@ingroup Serving - */ - class Client : public Bu::Stream - { - public: - Client( Bu::TcpSocket *pSocket, Bu::ClientLinkFactory *pfLink ); - virtual ~Client(); - - void processInput(); - void processOutput(); - - //Bu::String &getInput(); - //Bu::String &getOutput(); - Bu::size write( const Bu::String &sData ); - Bu::size write( const void *pData, Bu::size nBytes ); - Bu::size write( int8_t nData ); - Bu::size write( int16_t nData ); - Bu::size write( int32_t nData ); - Bu::size write( int64_t nData ); - Bu::size write( uint8_t nData ); - Bu::size write( uint16_t nData ); - Bu::size write( uint32_t nData ); - Bu::size write( uint64_t nData ); - Bu::size read( void *pData, Bu::size nBytes ); - Bu::size peek( void *pData, int nBytes, int nOffset=0 ); -// void seek( int nBytes ); - Bu::size getInputSize(); - Bu::size getOutputSize(); - - void setProtocol( Protocol *pProto ); - Bu::Protocol *getProtocol(); - void clearProtocol(); - - bool isOpen(); - void close(); - void tick(); - - const Bu::TcpSocket *getSocket() const; - - void disconnect(); - bool wantsDisconnect(); - - class ClientLink *getLink(); - - void onMessage( const Bu::String &sMsg ); - - bool hasOutput() { return qbWrite.getSize() > 0; } - bool hasInput() { return qbRead.getSize() > 0; } - - template - void pushFilter() - { - filter *pFlt = new filter( *pTopStream ); - pTopStream = pFlt; - lFilts.prepend( pFlt ); - } - - template - void pushFilter( p1t p1 ) - { - filter *pFlt = new filter( *pTopStream, p1 ); - pTopStream = pFlt; - lFilts.prepend( pFlt ); - } - - template - void pushFilter( p1t p1, p2t p2 ) - { - filter *pFlt = new filter( *pTopStream, p1, p2 ); - pTopStream = pFlt; - lFilts.prepend( pFlt ); - } - - /* - * These are required to qualify as a stream, I dunno how many will - * be implemented. - */ - virtual Bu::size tell(); - virtual void seek( Bu::size offset ); - virtual void setPos( Bu::size pos ); - virtual void setPosEnd( Bu::size pos ); - virtual bool isEos(); - virtual void flush(); - virtual bool canRead(); - virtual bool canWrite(); - virtual bool isReadable(); - virtual bool isWritable(); - virtual bool isSeekable(); - virtual bool isBlocking(); - virtual void setBlocking( bool bBlocking=true ); - virtual void setSize( Bu::size iSize ); - virtual size getSize() const; - virtual size getBlockSize() const; - virtual Bu::String getLocation() const; - - private: - typedef Bu::List FilterList; - FilterList lFilts; - Bu::Stream *pTopStream; - Bu::TcpSocket *pSocket; - Bu::Protocol *pProto; - Bu::QueueBuf qbRead; - Bu::QueueBuf qbWrite; - bool bWantsDisconnect; - class Bu::ClientLinkFactory *pfLink; - }; + class Protocol; + class Stream; + class TcpSocket; + class ClientLinkFactory; + + /** + *@ingroup Serving + */ + class Client : public Bu::Stream + { + public: + Client( Bu::TcpSocket *pSocket, Bu::ClientLinkFactory *pfLink ); + virtual ~Client(); + + void processInput(); + void processOutput(); + + //Bu::String &getInput(); + //Bu::String &getOutput(); + Bu::size write( const Bu::String &sData ); + Bu::size write( const void *pData, Bu::size nBytes ); + Bu::size write( int8_t nData ); + Bu::size write( int16_t nData ); + Bu::size write( int32_t nData ); + Bu::size write( int64_t nData ); + Bu::size write( uint8_t nData ); + Bu::size write( uint16_t nData ); + Bu::size write( uint32_t nData ); + Bu::size write( uint64_t nData ); + Bu::size read( void *pData, Bu::size nBytes ); + Bu::size peek( void *pData, int nBytes, int nOffset=0 ); +// void seek( int nBytes ); + Bu::size getInputSize(); + Bu::size getOutputSize(); + + void setProtocol( Protocol *pProto ); + Bu::Protocol *getProtocol(); + void clearProtocol(); + + bool isOpen(); + void close(); + void tick(); + + const Bu::TcpSocket *getSocket() const; + + void disconnect(); + bool wantsDisconnect(); + + class ClientLink *getLink(); + + void onMessage( const Bu::String &sMsg ); + + bool hasOutput() { return qbWrite.getSize() > 0; } + bool hasInput() { return qbRead.getSize() > 0; } + + template + void pushFilter() + { + filter *pFlt = new filter( *pTopStream ); + pTopStream = pFlt; + lFilts.prepend( pFlt ); + } + + template + void pushFilter( p1t p1 ) + { + filter *pFlt = new filter( *pTopStream, p1 ); + pTopStream = pFlt; + lFilts.prepend( pFlt ); + } + + template + void pushFilter( p1t p1, p2t p2 ) + { + filter *pFlt = new filter( *pTopStream, p1, p2 ); + pTopStream = pFlt; + lFilts.prepend( pFlt ); + } + + /* + * These are required to qualify as a stream, I dunno how many will + * be implemented. + */ + virtual Bu::size tell(); + virtual void seek( Bu::size offset ); + virtual void setPos( Bu::size pos ); + virtual void setPosEnd( Bu::size pos ); + virtual bool isEos(); + virtual void flush(); + virtual bool canRead(); + virtual bool canWrite(); + virtual bool isReadable(); + virtual bool isWritable(); + virtual bool isSeekable(); + virtual bool isBlocking(); + virtual void setBlocking( bool bBlocking=true ); + virtual void setSize( Bu::size iSize ); + virtual size getSize() const; + virtual size getBlockSize() const; + virtual Bu::String getLocation() const; + + private: + typedef Bu::List FilterList; + FilterList lFilts; + Bu::Stream *pTopStream; + Bu::TcpSocket *pSocket; + Bu::Protocol *pProto; + Bu::QueueBuf qbRead; + Bu::QueueBuf qbWrite; + bool bWantsDisconnect; + class Bu::ClientLinkFactory *pfLink; + }; } #endif diff --git a/src/stable/clientlink.h b/src/stable/clientlink.h index b5cd74d..d822c93 100644 --- a/src/stable/clientlink.h +++ b/src/stable/clientlink.h @@ -12,14 +12,14 @@ namespace Bu { - class ClientLink - { - public: - ClientLink(); - virtual ~ClientLink(); + class ClientLink + { + public: + ClientLink(); + virtual ~ClientLink(); - virtual void sendMessage( const Bu::String &sMsg )=0; - }; + virtual void sendMessage( const Bu::String &sMsg )=0; + }; }; #endif diff --git a/src/stable/clientlinkfactory.h b/src/stable/clientlinkfactory.h index b1b7670..bd64f6b 100644 --- a/src/stable/clientlinkfactory.h +++ b/src/stable/clientlinkfactory.h @@ -10,17 +10,17 @@ namespace Bu { - class Client; - class ClientLink; + class Client; + class ClientLink; - class ClientLinkFactory - { - public: - ClientLinkFactory(); - virtual ~ClientLinkFactory(); + class ClientLinkFactory + { + public: + ClientLinkFactory(); + virtual ~ClientLinkFactory(); - virtual Bu::ClientLink *createLink( Bu::Client *pClient )=0; - }; + virtual Bu::ClientLink *createLink( Bu::Client *pClient )=0; + }; }; #endif diff --git a/src/stable/condition.cpp b/src/stable/condition.cpp index 79af262..f02eca7 100644 --- a/src/stable/condition.cpp +++ b/src/stable/condition.cpp @@ -11,39 +11,39 @@ Bu::Condition::Condition() { - pthread_cond_init( &cond, NULL ); + pthread_cond_init( &cond, NULL ); } Bu::Condition::~Condition() { - pthread_cond_destroy( &cond ); + pthread_cond_destroy( &cond ); } int Bu::Condition::wait() { - return pthread_cond_wait( &cond, &mutex ); + return pthread_cond_wait( &cond, &mutex ); } int Bu::Condition::wait( int nSec, int nUSec ) { - struct timeval now; - struct timespec timeout; - struct timezone tz; - - gettimeofday( &now, &tz ); - timeout.tv_sec = now.tv_sec + nSec + ((now.tv_usec + nUSec)/1000000); - timeout.tv_nsec = ((now.tv_usec + nUSec)%1000000)*1000; - - return pthread_cond_timedwait( &cond, &mutex, &timeout ); + struct timeval now; + struct timespec timeout; + struct timezone tz; + + gettimeofday( &now, &tz ); + timeout.tv_sec = now.tv_sec + nSec + ((now.tv_usec + nUSec)/1000000); + timeout.tv_nsec = ((now.tv_usec + nUSec)%1000000)*1000; + + return pthread_cond_timedwait( &cond, &mutex, &timeout ); } int Bu::Condition::signal() { - return pthread_cond_signal( &cond ); + return pthread_cond_signal( &cond ); } int Bu::Condition::broadcast() { - return pthread_cond_broadcast( &cond ); + return pthread_cond_broadcast( &cond ); } diff --git a/src/stable/condition.h b/src/stable/condition.h index 2c27720..53eb9ff 100644 --- a/src/stable/condition.h +++ b/src/stable/condition.h @@ -14,77 +14,77 @@ namespace Bu { - /** - * Ito condition. This is a fairly simple condition mechanism. As you may - * notice this class inherits from the Mutex class, this is because all - * conditions must be within a locked block. The standard usage of a - * condition is to pause one thread, perhaps indefinately, until another - * thread signals that it is alright to procede. - *
- * Standard usage for the thread that wants to wait is as follows: - *
-	 * Condition cond;
-	 * ... // Perform setup and enter your run loop
-	 * cond.lock();
-	 * while( !isFinished() ) // Could be anything you're waiting for
-	 *     cond.wait();
-	 * ...  // Take care of what you have to.
-	 * cond.unlock();
-	 * 
- * The usage for the triggering thread is much simpler, when it needs to - * tell the others that it's time to grab some data it calls either signal - * or broadcast. See both of those functions for the difference. - *@ingroup Threading - */ - class Condition : public Mutex - { - public: - /** - * Create a condition. - */ - Condition(); + /** + * Ito condition. This is a fairly simple condition mechanism. As you may + * notice this class inherits from the Mutex class, this is because all + * conditions must be within a locked block. The standard usage of a + * condition is to pause one thread, perhaps indefinately, until another + * thread signals that it is alright to procede. + *
+ * Standard usage for the thread that wants to wait is as follows: + *
+     * Condition cond;
+     * ... // Perform setup and enter your run loop
+     * cond.lock();
+     * while( !isFinished() ) // Could be anything you're waiting for
+     *     cond.wait();
+     * ...  // Take care of what you have to.
+     * cond.unlock();
+     * 
+ * The usage for the triggering thread is much simpler, when it needs to + * tell the others that it's time to grab some data it calls either signal + * or broadcast. See both of those functions for the difference. + *@ingroup Threading + */ + class Condition : public Mutex + { + public: + /** + * Create a condition. + */ + Condition(); - /** - * Destroy a condition. - */ - ~Condition(); + /** + * Destroy a condition. + */ + ~Condition(); - /** - * Wait forever, or until signalled. This has to be called from within - * a locked section, i.e. before calling this this object's lock - * function should be called. - */ - int wait(); + /** + * Wait forever, or until signalled. This has to be called from within + * a locked section, i.e. before calling this this object's lock + * function should be called. + */ + int wait(); - /** - * Wait for a maximum of nSec seconds and nUSec micro-seconds or until - * signalled. This is a little more friendly function if you want to - * perform other operations in the thrad loop that calls this function. - * Like the other wait function, this must be inside a locked section. - *@param nSec The seconds to wait. - *@param nUSec the micro-seconds to wait. - */ - int wait( int nSec, int nUSec ); + /** + * Wait for a maximum of nSec seconds and nUSec micro-seconds or until + * signalled. This is a little more friendly function if you want to + * perform other operations in the thrad loop that calls this function. + * Like the other wait function, this must be inside a locked section. + *@param nSec The seconds to wait. + *@param nUSec the micro-seconds to wait. + */ + int wait( int nSec, int nUSec ); - /** - * Notify the next thread waiting on this condition that they can go - * ahead. This only signals one thread, the next one in the condition - * queue, that it is safe to procede with whatever operation was being - * waited on. - */ - int signal(); + /** + * Notify the next thread waiting on this condition that they can go + * ahead. This only signals one thread, the next one in the condition + * queue, that it is safe to procede with whatever operation was being + * waited on. + */ + int signal(); - /** - * Notify all threads waiting on this condition that they can go ahead - * now. This function is slower than signal, but more effective in - * certain situations where you may not know how many threads should be - * activated. - */ - int broadcast(); + /** + * Notify all threads waiting on this condition that they can go ahead + * now. This function is slower than signal, but more effective in + * certain situations where you may not know how many threads should be + * activated. + */ + int broadcast(); - private: - pthread_cond_t cond; /**< Internal condition reference. */ - }; + private: + pthread_cond_t cond; /**< Internal condition reference. */ + }; } #endif diff --git a/src/stable/conduit.cpp b/src/stable/conduit.cpp index 8f5eba5..4c2fda6 100644 --- a/src/stable/conduit.cpp +++ b/src/stable/conduit.cpp @@ -8,9 +8,9 @@ #include "bu/conduit.h" Bu::Conduit::Conduit( int iBlockSize ) : - qb( iBlockSize ), - bBlocking( true ), - bOpen( true ) + qb( iBlockSize ), + bBlocking( true ), + bOpen( true ) { } @@ -20,100 +20,100 @@ Bu::Conduit::~Conduit() void Bu::Conduit::close() { - im.lock(); -// qb.close(); - bOpen = false; - - cBlock.signal(); - im.unlock(); + im.lock(); +// qb.close(); + bOpen = false; + + cBlock.signal(); + im.unlock(); } #include Bu::size Bu::Conduit::read( void *pBuf, Bu::size nBytes ) { - if( !isOpen() ) - { - return 0; - } - im.lock(); - if( bBlocking ) - { - im.unlock(); - cBlock.lock(); - for(;;) - { - im.lock(); - if( qb.getSize() == 0 && bOpen == false ) - { - im.unlock(); - cBlock.unlock(); - return 0; - } - else if( qb.getSize() > 0 ) - { - im.unlock(); - break; - } - im.unlock(); - - cBlock.wait(); - } - - im.lock(); - Bu::size iRet = qb.read( pBuf, nBytes ); - im.unlock(); - - cBlock.unlock(); - return iRet; - } - else - { - Bu::size iRet = qb.read( pBuf, nBytes ); - im.unlock(); - - return iRet; - } + if( !isOpen() ) + { + return 0; + } + im.lock(); + if( bBlocking ) + { + im.unlock(); + cBlock.lock(); + for(;;) + { + im.lock(); + if( qb.getSize() == 0 && bOpen == false ) + { + im.unlock(); + cBlock.unlock(); + return 0; + } + else if( qb.getSize() > 0 ) + { + im.unlock(); + break; + } + im.unlock(); + + cBlock.wait(); + } + + im.lock(); + Bu::size iRet = qb.read( pBuf, nBytes ); + im.unlock(); + + cBlock.unlock(); + return iRet; + } + else + { + Bu::size iRet = qb.read( pBuf, nBytes ); + im.unlock(); + + return iRet; + } } Bu::size Bu::Conduit::peek( void *pBuf, Bu::size nBytes ) { - im.lock(); - Bu::size iRet = qb.peek( pBuf, nBytes ); - im.unlock(); + im.lock(); + Bu::size iRet = qb.peek( pBuf, nBytes ); + im.unlock(); - return iRet; + return iRet; } Bu::size Bu::Conduit::peek( void *pBuf, Bu::size nBytes, Bu::size nSkip ) { - im.lock(); - Bu::size iRet = qb.peek( pBuf, nBytes, nSkip ); - im.unlock(); + im.lock(); + Bu::size iRet = qb.peek( pBuf, nBytes, nSkip ); + im.unlock(); - return iRet; + return iRet; } Bu::size Bu::Conduit::write( const void *pBuf, Bu::size nBytes ) { - im.lock(); - if( bOpen == false ) - { - im.unlock(); - return 0; - } - Bu::size sRet = qb.write( pBuf, nBytes ); - cBlock.signal(); - im.unlock(); + im.lock(); + if( bOpen == false ) + { + im.unlock(); + return 0; + } + Bu::size sRet = qb.write( pBuf, nBytes ); + cBlock.signal(); + im.unlock(); - return sRet; + return sRet; } Bu::size Bu::Conduit::tell() { - im.lock(); - Bu::size sRet = qb.tell(); - im.unlock(); - return sRet; + im.lock(); + Bu::size sRet = qb.tell(); + im.unlock(); + return sRet; } void Bu::Conduit::seek( Bu::size ) @@ -130,18 +130,18 @@ void Bu::Conduit::setPosEnd( Bu::size ) bool Bu::Conduit::isEos() { - im.lock(); - bool bRet = qb.isEos(); - im.unlock(); - return bRet; + im.lock(); + bool bRet = qb.isEos(); + im.unlock(); + return bRet; } bool Bu::Conduit::isOpen() { - im.lock(); - bool bRet = bOpen || (qb.getSize() > 0); - im.unlock(); - return bRet; + im.lock(); + bool bRet = bOpen || (qb.getSize() > 0); + im.unlock(); + return bRet; } void Bu::Conduit::flush() @@ -150,57 +150,57 @@ void Bu::Conduit::flush() bool Bu::Conduit::canRead() { - im.lock(); - bool bRet = qb.canRead(); - im.unlock(); - return bRet; + im.lock(); + bool bRet = qb.canRead(); + im.unlock(); + return bRet; } bool Bu::Conduit::canWrite() { - im.lock(); - bool bRet = qb.canWrite(); - im.unlock(); - return bRet; + im.lock(); + bool bRet = qb.canWrite(); + im.unlock(); + return bRet; } bool Bu::Conduit::isReadable() { - im.lock(); - bool bRet = qb.isReadable(); - im.unlock(); - return bRet; + im.lock(); + bool bRet = qb.isReadable(); + im.unlock(); + return bRet; } bool Bu::Conduit::isWritable() { - im.lock(); - bool bRet = qb.isWritable(); - im.unlock(); - return bRet; + im.lock(); + bool bRet = qb.isWritable(); + im.unlock(); + return bRet; } bool Bu::Conduit::isSeekable() { - im.lock(); - bool bRet = qb.isSeekable(); - im.unlock(); - return bRet; + im.lock(); + bool bRet = qb.isSeekable(); + im.unlock(); + return bRet; } bool Bu::Conduit::isBlocking() { - im.lock(); - bool bRet = bBlocking; - im.unlock(); - return bRet; + im.lock(); + bool bRet = bBlocking; + im.unlock(); + return bRet; } void Bu::Conduit::setBlocking( bool bBlocking ) { - im.lock(); - this->bBlocking = bBlocking; - im.unlock(); + im.lock(); + this->bBlocking = bBlocking; + im.unlock(); } void Bu::Conduit::setSize( Bu::size ) @@ -209,25 +209,25 @@ void Bu::Conduit::setSize( Bu::size ) Bu::size Bu::Conduit::getSize() const { - im.lock(); - Bu::size sRet = qb.getSize(); - im.unlock(); - return sRet; + im.lock(); + Bu::size sRet = qb.getSize(); + im.unlock(); + return sRet; } Bu::size Bu::Conduit::getBlockSize() const { - im.lock(); - Bu::size sRet = qb.getBlockSize(); - im.unlock(); - return sRet; + im.lock(); + Bu::size sRet = qb.getBlockSize(); + im.unlock(); + return sRet; } Bu::String Bu::Conduit::getLocation() const { - im.lock(); - Bu::String sRet = qb.getLocation(); - im.unlock(); - return sRet; + im.lock(); + Bu::String sRet = qb.getLocation(); + im.unlock(); + return sRet; } diff --git a/src/stable/conduit.h b/src/stable/conduit.h index a1959a9..78d24eb 100644 --- a/src/stable/conduit.h +++ b/src/stable/conduit.h @@ -16,49 +16,49 @@ namespace Bu { - /** - * Simple inter-thread communication stream. This acts like a pair of - * pipes for stream communication between any two things, but without the - * use of pipes, making this a bad choice for IPC. - */ - class Conduit : public Stream - { - public: - Conduit( int iBlockSize=256 ); - virtual ~Conduit(); + /** + * Simple inter-thread communication stream. This acts like a pair of + * pipes for stream communication between any two things, but without the + * use of pipes, making this a bad choice for IPC. + */ + class Conduit : public Stream + { + public: + Conduit( int iBlockSize=256 ); + virtual ~Conduit(); - virtual void close(); - virtual Bu::size read( void *pBuf, Bu::size nBytes ); - virtual Bu::size peek( void *pBuf, Bu::size nBytes ); - virtual Bu::size peek( void *pBuf, Bu::size nBytes, Bu::size nSkip ); - virtual Bu::size write( const void *pBuf, Bu::size nBytes ); - virtual Bu::size tell(); - virtual void seek( Bu::size offset ); - virtual void setPos( Bu::size pos ); - virtual void setPosEnd( Bu::size pos ); - virtual bool isEos(); - virtual bool isOpen(); - virtual void flush(); - virtual bool canRead(); - virtual bool canWrite(); - virtual bool isReadable(); - virtual bool isWritable(); - virtual bool isSeekable(); - virtual bool isBlocking(); - virtual void setBlocking( bool bBlocking=true ); - virtual void setSize( Bu::size iSize ); + virtual void close(); + virtual Bu::size read( void *pBuf, Bu::size nBytes ); + virtual Bu::size peek( void *pBuf, Bu::size nBytes ); + virtual Bu::size peek( void *pBuf, Bu::size nBytes, Bu::size nSkip ); + virtual Bu::size write( const void *pBuf, Bu::size nBytes ); + virtual Bu::size tell(); + virtual void seek( Bu::size offset ); + virtual void setPos( Bu::size pos ); + virtual void setPosEnd( Bu::size pos ); + virtual bool isEos(); + virtual bool isOpen(); + virtual void flush(); + virtual bool canRead(); + virtual bool canWrite(); + virtual bool isReadable(); + virtual bool isWritable(); + virtual bool isSeekable(); + virtual bool isBlocking(); + virtual void setBlocking( bool bBlocking=true ); + virtual void setSize( Bu::size iSize ); - virtual size getSize() const; - virtual size getBlockSize() const; - virtual Bu::String getLocation() const; + virtual size getSize() const; + virtual size getBlockSize() const; + virtual Bu::String getLocation() const; - private: - QueueBuf qb; - mutable Mutex im; - Condition cBlock; - bool bBlocking; - bool bOpen; - }; + private: + QueueBuf qb; + mutable Mutex im; + Condition cBlock; + bool bBlocking; + bool bOpen; + }; } #endif diff --git a/src/stable/crypt.cpp b/src/stable/crypt.cpp index 3f7fc83..2915cf4 100644 --- a/src/stable/crypt.cpp +++ b/src/stable/crypt.cpp @@ -13,35 +13,35 @@ Bu::String Bu::cryptPass( const Bu::String &sPass, const Bu::String &sSalt ) { - Bu::Md5 md5; - Bu::MemBuf mbOut; - Bu::Base64 b64Out( mbOut ); - - Bu::String::const_iterator i = sSalt.find('$'); - Bu::String sSaltSml = sSalt.getSubStr( sSalt.begin(), i ); + Bu::Md5 md5; + Bu::MemBuf mbOut; + Bu::Base64 b64Out( mbOut ); + + Bu::String::const_iterator i = sSalt.find('$'); + Bu::String sSaltSml = sSalt.getSubStr( sSalt.begin(), i ); - md5.addData( sPass ); - md5.addData( sSaltSml ); - md5.writeResult( b64Out ); + md5.addData( sPass ); + md5.addData( sSaltSml ); + md5.writeResult( b64Out ); - b64Out.stop(); + b64Out.stop(); - return sSaltSml + "$" + mbOut.getString(); + return sSaltSml + "$" + mbOut.getString(); } Bu::String Bu::cryptPass( const Bu::String &sPass ) { - Bu::MemBuf mbSalt; - Bu::Base64 b64Salt( mbSalt ); - Bu::File fRand("/dev/urandom", Bu::File::Read ); + Bu::MemBuf mbSalt; + Bu::Base64 b64Salt( mbSalt ); + Bu::File fRand("/dev/urandom", Bu::File::Read ); #define STR 6 - char buf[STR]; - fRand.read( buf, STR ); - b64Salt.write( buf, STR ); + char buf[STR]; + fRand.read( buf, STR ); + b64Salt.write( buf, STR ); - b64Salt.stop(); + b64Salt.stop(); - return cryptPass( sPass, mbSalt.getString() ); + return cryptPass( sPass, mbSalt.getString() ); } diff --git a/src/stable/crypt.h b/src/stable/crypt.h index 14adc3a..5093610 100644 --- a/src/stable/crypt.h +++ b/src/stable/crypt.h @@ -12,8 +12,8 @@ namespace Bu { - String cryptPass( const Bu::String &sPass, const Bu::String &sSalt ); - String cryptPass( const Bu::String &sPass ); + String cryptPass( const Bu::String &sPass, const Bu::String &sSalt ); + String cryptPass( const Bu::String &sPass ); }; #endif diff --git a/src/stable/cryptohash.cpp b/src/stable/cryptohash.cpp index dda734c..99a7d92 100644 --- a/src/stable/cryptohash.cpp +++ b/src/stable/cryptohash.cpp @@ -17,22 +17,22 @@ Bu::CryptoHash::~CryptoHash() void Bu::CryptoHash::addData( const Bu::String &sData ) { - addData( sData.getStr(), sData.getSize() ); + addData( sData.getStr(), sData.getSize() ); } Bu::String Bu::CryptoHash::getHexResult() { - Bu::String sResult = getResult(); - Bu::String sRet( 2*sResult.getSize() ); - static const char hex_tab[] = {"0123456789abcdef"}; - - int k = 0; - for( int i = 0; i < sResult.getSize(); i++ ) - { - sRet[k++] = hex_tab[(((unsigned char)sResult[i])>>4) & 0xF]; - sRet[k++] = hex_tab[((unsigned char)sResult[i]) & 0xF]; - } - - return sRet; + Bu::String sResult = getResult(); + Bu::String sRet( 2*sResult.getSize() ); + static const char hex_tab[] = {"0123456789abcdef"}; + + int k = 0; + for( int i = 0; i < sResult.getSize(); i++ ) + { + sRet[k++] = hex_tab[(((unsigned char)sResult[i])>>4) & 0xF]; + sRet[k++] = hex_tab[((unsigned char)sResult[i]) & 0xF]; + } + + return sRet; } diff --git a/src/stable/cryptohash.h b/src/stable/cryptohash.h index 3f13b05..a943590 100644 --- a/src/stable/cryptohash.h +++ b/src/stable/cryptohash.h @@ -12,22 +12,22 @@ namespace Bu { - class Stream; + class Stream; - class CryptoHash - { - public: - CryptoHash(); - virtual ~CryptoHash(); + class CryptoHash + { + public: + CryptoHash(); + virtual ~CryptoHash(); - virtual void reset() = 0; - virtual void setSalt( const Bu::String &sSalt ) = 0; - virtual void addData( const void *sData, int iSize ) = 0; - virtual void addData( const Bu::String &sData ); - virtual String getResult() = 0; - virtual void writeResult( Stream &sOut ) = 0; - virtual Bu::String getHexResult(); - }; + virtual void reset() = 0; + virtual void setSalt( const Bu::String &sSalt ) = 0; + virtual void addData( const void *sData, int iSize ) = 0; + virtual void addData( const Bu::String &sData ); + virtual String getResult() = 0; + virtual void writeResult( Stream &sOut ) = 0; + virtual Bu::String getHexResult(); + }; }; #endif diff --git a/src/stable/csvreader.cpp b/src/stable/csvreader.cpp index ddc68f0..c27c8ee 100644 --- a/src/stable/csvreader.cpp +++ b/src/stable/csvreader.cpp @@ -12,24 +12,24 @@ using namespace Bu; Bu::CsvReader::CsvReader( Bu::Stream &sIn, Bu::CsvReader::Style eStyle ) : - sIn( sIn ) + sIn( sIn ) { - switch( eStyle ) - { - case styleExcel: - sDecode = Bu::slot( &decodeExcel ); - break; - - case styleC: - sDecode = Bu::slot( &decodeC ); - break; - } + switch( eStyle ) + { + case styleExcel: + sDecode = Bu::slot( &decodeExcel ); + break; + + case styleC: + sDecode = Bu::slot( &decodeC ); + break; + } } Bu::CsvReader::CsvReader( Bu::Stream &sIn, - Bu::CsvReader::DecodeSignal sDecode ) : - sIn( sIn ), - sDecode( sDecode ) + Bu::CsvReader::DecodeSignal sDecode ) : + sIn( sIn ), + sDecode( sDecode ) { } @@ -39,61 +39,61 @@ Bu::CsvReader::~CsvReader() Bu::StrArray Bu::CsvReader::readLine() { - Bu::StrArray aVals; - - Bu::String sLine = sIn.readLine(); - - if( !sLine.isSet() ) - return Bu::StrArray(); - - Bu::String::iterator i = sLine.begin(); - - aVals.append( sDecode( i ) ); - - while( i ) - { - if( *i == ',' ) - { - i++; - if( !i ) - { - aVals.append(""); - break; - } - aVals.append( sDecode( i ) ); - } - else - { - // Blanks and stuff? - sio << "Out of bound: '" << *i << "'" << sio.nl; - i++; - } - } - - return aVals; + Bu::StrArray aVals; + + Bu::String sLine = sIn.readLine(); + + if( !sLine.isSet() ) + return Bu::StrArray(); + + Bu::String::iterator i = sLine.begin(); + + aVals.append( sDecode( i ) ); + + while( i ) + { + if( *i == ',' ) + { + i++; + if( !i ) + { + aVals.append(""); + break; + } + aVals.append( sDecode( i ) ); + } + else + { + // Blanks and stuff? + sio << "Out of bound: '" << *i << "'" << sio.nl; + i++; + } + } + + return aVals; } Bu::String Bu::CsvReader::decodeExcel( Bu::String::iterator &i ) { - Bu::String sRet; + Bu::String sRet; - for(; i && (*i == ' ' || *i == '\t'); i++ ) { } - - if( !i ) - return sRet; + for(; i && (*i == ' ' || *i == '\t'); i++ ) { } + + if( !i ) + return sRet; - if( *i == '\"' ) + if( *i == '\"' ) { for( i++ ; i; i++ ) { if( *i == '\"' ) - { - i++; - if( !i ) - { - return sRet; - } - else if( *i == '\"' ) + { + i++; + if( !i ) + { + return sRet; + } + else if( *i == '\"' ) { sRet += *i; } diff --git a/src/stable/csvreader.h b/src/stable/csvreader.h index 6825da3..cb2a560 100644 --- a/src/stable/csvreader.h +++ b/src/stable/csvreader.h @@ -14,32 +14,32 @@ namespace Bu { - class Stream; - typedef Bu::Array StrArray; - - class CsvReader - { - public: - typedef Bu::Signal1 DecodeSignal; - enum Style - { - styleExcel, ///< Excel style quotes around things that need em - styleC ///< Escape things that need it C-style - }; - - CsvReader( Stream &sIn, Style eStyle=styleExcel ); - CsvReader( Stream &sIn, DecodeSignal sDecode ); - virtual ~CsvReader(); - - StrArray readLine(); - - private: - Stream &sIn; - DecodeSignal sDecode; - - static Bu::String decodeExcel( Bu::String::iterator &i ); - static Bu::String decodeC( Bu::String::iterator &i ); - }; + class Stream; + typedef Bu::Array StrArray; + + class CsvReader + { + public: + typedef Bu::Signal1 DecodeSignal; + enum Style + { + styleExcel, ///< Excel style quotes around things that need em + styleC ///< Escape things that need it C-style + }; + + CsvReader( Stream &sIn, Style eStyle=styleExcel ); + CsvReader( Stream &sIn, DecodeSignal sDecode ); + virtual ~CsvReader(); + + StrArray readLine(); + + private: + Stream &sIn; + DecodeSignal sDecode; + + static Bu::String decodeExcel( Bu::String::iterator &i ); + static Bu::String decodeC( Bu::String::iterator &i ); + }; }; #endif diff --git a/src/stable/csvwriter.cpp b/src/stable/csvwriter.cpp index a89b309..8b51115 100644 --- a/src/stable/csvwriter.cpp +++ b/src/stable/csvwriter.cpp @@ -9,24 +9,24 @@ #include "bu/stream.h" Bu::CsvWriter::CsvWriter( Bu::Stream &sOut, Bu::CsvWriter::Style eStyle ) : - sOut( sOut ) + sOut( sOut ) { - switch( eStyle ) - { - case styleExcel: - sEncode = Bu::slot( &encodeExcel ); - break; + switch( eStyle ) + { + case styleExcel: + sEncode = Bu::slot( &encodeExcel ); + break; - case styleC: - sEncode = Bu::slot( &encodeExcel ); - break; - } + case styleC: + sEncode = Bu::slot( &encodeExcel ); + break; + } } Bu::CsvWriter::CsvWriter( Bu::Stream &sOut, - Bu::CsvWriter::EncodeSignal sEncode ) : - sOut( sOut ), - sEncode( sEncode ) + Bu::CsvWriter::EncodeSignal sEncode ) : + sOut( sOut ), + sEncode( sEncode ) { } @@ -36,46 +36,46 @@ Bu::CsvWriter::~CsvWriter() void Bu::CsvWriter::writeLine( const StrArray &aStrs ) { - Bu::String sBuf; - for( StrArray::const_iterator i = aStrs.begin(); i; i++ ) - { - if( i != aStrs.begin() ) - sBuf += ","; - sBuf += sEncode( *i ); - } - sBuf += "\n"; + Bu::String sBuf; + for( StrArray::const_iterator i = aStrs.begin(); i; i++ ) + { + if( i != aStrs.begin() ) + sBuf += ","; + sBuf += sEncode( *i ); + } + sBuf += "\n"; - sOut.write( sBuf ); + sOut.write( sBuf ); } Bu::String Bu::CsvWriter::encodeExcel( const Bu::String &sIn ) { - if( sIn.find('\"') || sIn.find(',') ) + if( sIn.find('\"') || sIn.find(',') ) { Bu::String sOut = "\""; - for( Bu::String::const_iterator i = sIn.begin(); i; i++ ) - { - if( *i == '\"' ) + for( Bu::String::const_iterator i = sIn.begin(); i; i++ ) + { + if( *i == '\"' ) sOut += "\"\""; else sOut += *i; } sOut += '\"'; - return sOut; - } - return sIn; + return sOut; + } + return sIn; } Bu::String Bu::CsvWriter::encodeC( const Bu::String &sIn ) { - Bu::String sOut = ""; - for( Bu::String::const_iterator i = sIn.begin(); i; i++ ) - { - if( *i == ',' ) - sOut += "\\,"; - else - sOut += *i; - } - return sOut; + Bu::String sOut = ""; + for( Bu::String::const_iterator i = sIn.begin(); i; i++ ) + { + if( *i == ',' ) + sOut += "\\,"; + else + sOut += *i; + } + return sOut; } diff --git a/src/stable/csvwriter.h b/src/stable/csvwriter.h index bae1e1d..233f4ed 100644 --- a/src/stable/csvwriter.h +++ b/src/stable/csvwriter.h @@ -14,32 +14,32 @@ namespace Bu { - class Stream; - typedef Bu::Array StrArray; - - class CsvWriter - { - public: - typedef Bu::Signal1 EncodeSignal; - enum Style - { - styleExcel, ///< Excel style quotes around things that need em - styleC ///< Escape things that need it C-style - }; - - CsvWriter( Stream &sOut, Style eStyle=styleExcel ); - CsvWriter( Stream &sOut, EncodeSignal sEncode ); - virtual ~CsvWriter(); - - void writeLine( const StrArray &aStrs ); - - private: - Stream &sOut; - EncodeSignal sEncode; - - static Bu::String encodeExcel( const Bu::String &sIn ); - static Bu::String encodeC( const Bu::String &sIn ); - }; + class Stream; + typedef Bu::Array StrArray; + + class CsvWriter + { + public: + typedef Bu::Signal1 EncodeSignal; + enum Style + { + styleExcel, ///< Excel style quotes around things that need em + styleC ///< Escape things that need it C-style + }; + + CsvWriter( Stream &sOut, Style eStyle=styleExcel ); + CsvWriter( Stream &sOut, EncodeSignal sEncode ); + virtual ~CsvWriter(); + + void writeLine( const StrArray &aStrs ); + + private: + Stream &sOut; + EncodeSignal sEncode; + + static Bu::String encodeExcel( const Bu::String &sIn ); + static Bu::String encodeC( const Bu::String &sIn ); + }; }; #endif diff --git a/src/stable/deflate.cpp b/src/stable/deflate.cpp index b7e1804..57aa4aa 100644 --- a/src/stable/deflate.cpp +++ b/src/stable/deflate.cpp @@ -15,239 +15,239 @@ using namespace Bu; Bu::Deflate::Deflate( Bu::Stream &rNext, int nCompression, Format eFmt ) : - Bu::Filter( rNext ), - prState( NULL ), - nCompression( nCompression ), - sTotalOut( 0 ), - eFmt( eFmt ), - bEos( false ) + Bu::Filter( rNext ), + prState( NULL ), + nCompression( nCompression ), + sTotalOut( 0 ), + eFmt( eFmt ), + bEos( false ) { - TRACE( nCompression ); - start(); + TRACE( nCompression ); + start(); } Bu::Deflate::~Deflate() { - TRACE(); - stop(); + TRACE(); + stop(); } void Bu::Deflate::start() { - TRACE(); - prState = new z_stream; - pState->zalloc = NULL; - pState->zfree = NULL; - pState->opaque = NULL; - pState->state = NULL; - - nBufSize = 64*1024; - pBuf = new char[nBufSize]; + TRACE(); + prState = new z_stream; + pState->zalloc = NULL; + pState->zfree = NULL; + pState->opaque = NULL; + pState->state = NULL; + + nBufSize = 64*1024; + pBuf = new char[nBufSize]; } Bu::size Bu::Deflate::stop() { - TRACE(); - if( pState && pState->state ) - { - if( bReading ) - { - inflateEnd( pState ); - delete[] pBuf; - pBuf = NULL; - delete pState; - prState = NULL; - return 0; - } - else - { - for(;;) - { - pState->next_in = NULL; - pState->avail_in = 0; - pState->avail_out = nBufSize; - pState->next_out = (Bytef *)pBuf; - int res = deflate( pState, Z_FINISH ); - if( pState->avail_out < nBufSize ) - { - sTotalOut += rNext.write( pBuf, nBufSize-pState->avail_out ); - } - if( res == Z_STREAM_END ) - break; - } - deflateEnd( pState ); - delete[] pBuf; - pBuf = NULL; - delete pState; - prState = NULL; - return sTotalOut; - } - } - return 0; + TRACE(); + if( pState && pState->state ) + { + if( bReading ) + { + inflateEnd( pState ); + delete[] pBuf; + pBuf = NULL; + delete pState; + prState = NULL; + return 0; + } + else + { + for(;;) + { + pState->next_in = NULL; + pState->avail_in = 0; + pState->avail_out = nBufSize; + pState->next_out = (Bytef *)pBuf; + int res = deflate( pState, Z_FINISH ); + if( pState->avail_out < nBufSize ) + { + sTotalOut += rNext.write( pBuf, nBufSize-pState->avail_out ); + } + if( res == Z_STREAM_END ) + break; + } + deflateEnd( pState ); + delete[] pBuf; + pBuf = NULL; + delete pState; + prState = NULL; + return sTotalOut; + } + } + return 0; } void Bu::Deflate::zError( int code ) { - TRACE( code ); - switch( code ) - { - case Z_OK: - case Z_STREAM_END: - case Z_NEED_DICT: - return; + TRACE( code ); + switch( code ) + { + case Z_OK: + case Z_STREAM_END: + case Z_NEED_DICT: + return; - case Z_ERRNO: - throw ExceptionBase("Deflate: Errno - %s", pState->msg ); + case Z_ERRNO: + throw ExceptionBase("Deflate: Errno - %s", pState->msg ); - case Z_STREAM_ERROR: - throw ExceptionBase("Deflate: Stream Error - %s", pState->msg ); + case Z_STREAM_ERROR: + throw ExceptionBase("Deflate: Stream Error - %s", pState->msg ); - case Z_DATA_ERROR: - throw ExceptionBase("Deflate: Data Error - %s", pState->msg ); + case Z_DATA_ERROR: + throw ExceptionBase("Deflate: Data Error - %s", pState->msg ); - case Z_MEM_ERROR: - throw ExceptionBase("Deflate: Mem Error - %s", pState->msg ); + case Z_MEM_ERROR: + throw ExceptionBase("Deflate: Mem Error - %s", pState->msg ); - case Z_BUF_ERROR: - throw ExceptionBase("Deflate: Buf Error - %s", pState->msg ); + case Z_BUF_ERROR: + throw ExceptionBase("Deflate: Buf Error - %s", pState->msg ); - case Z_VERSION_ERROR: - throw ExceptionBase("Deflate: Version Error - %s", pState->msg ); + case Z_VERSION_ERROR: + throw ExceptionBase("Deflate: Version Error - %s", pState->msg ); - default: - throw ExceptionBase("Deflate: Unknown error encountered - %s.", pState->msg ); - - } + default: + throw ExceptionBase("Deflate: Unknown error encountered - %s.", pState->msg ); + + } } Bu::size Bu::Deflate::read( void *pData, Bu::size nBytes ) { - TRACE( pData, nBytes ); - if( nBytes <= 0 ) - return 0; - if( !pState->state ) - { - bReading = true; - if( eFmt&AutoDetect ) - inflateInit2( pState, 32+15 ); // Auto-detect, large window - else if( eFmt == Raw ) - inflateInit2( pState, -15 ); // Raw - else if( eFmt == Zlib ) - inflateInit2( pState, 15 ); // Zlib - else if( eFmt == Gzip ) - inflateInit2( pState, 16+15 ); // GZip - else - throw Bu::ExceptionBase("Format mode for deflate read."); - pState->next_in = (Bytef *)pBuf; - pState->avail_in = 0; - } - if( bReading == false ) - throw ExceptionBase("This deflate filter is in writing mode, you can't read."); - - int nRead = 0; - int nReadTotal = pState->total_out; - pState->next_out = (Bytef *)pData; - pState->avail_out = nBytes; - for(;;) - { - int ret = inflate( pState, Z_NO_FLUSH ); - nReadTotal += nRead-pState->avail_out; - - if( ret == Z_STREAM_END ) - { - bEos = true; - if( pState->avail_in > 0 ) - { - if( rNext.isSeekable() ) - { - rNext.seek( -pState->avail_in ); - } - } - return nBytes-pState->avail_out; - } - if( ret != Z_BUF_ERROR ) - zError( ret ); - - if( pState->avail_out ) - { - if( pState->avail_in == 0 ) - { - nRead = rNext.read( pBuf, nBufSize ); - if( nRead == 0 && rNext.isEos() ) - { - throw Bu::ExceptionBase("Premature end of underlying " - "stream found reading deflate stream."); - } - pState->next_in = (Bytef *)pBuf; - pState->avail_in = nRead; - } - } - else - { - return nBytes-pState->avail_out; - } - } - return 0; + TRACE( pData, nBytes ); + if( nBytes <= 0 ) + return 0; + if( !pState->state ) + { + bReading = true; + if( eFmt&AutoDetect ) + inflateInit2( pState, 32+15 ); // Auto-detect, large window + else if( eFmt == Raw ) + inflateInit2( pState, -15 ); // Raw + else if( eFmt == Zlib ) + inflateInit2( pState, 15 ); // Zlib + else if( eFmt == Gzip ) + inflateInit2( pState, 16+15 ); // GZip + else + throw Bu::ExceptionBase("Format mode for deflate read."); + pState->next_in = (Bytef *)pBuf; + pState->avail_in = 0; + } + if( bReading == false ) + throw ExceptionBase("This deflate filter is in writing mode, you can't read."); + + int nRead = 0; + int nReadTotal = pState->total_out; + pState->next_out = (Bytef *)pData; + pState->avail_out = nBytes; + for(;;) + { + int ret = inflate( pState, Z_NO_FLUSH ); + nReadTotal += nRead-pState->avail_out; + + if( ret == Z_STREAM_END ) + { + bEos = true; + if( pState->avail_in > 0 ) + { + if( rNext.isSeekable() ) + { + rNext.seek( -pState->avail_in ); + } + } + return nBytes-pState->avail_out; + } + if( ret != Z_BUF_ERROR ) + zError( ret ); + + if( pState->avail_out ) + { + if( pState->avail_in == 0 ) + { + nRead = rNext.read( pBuf, nBufSize ); + if( nRead == 0 && rNext.isEos() ) + { + throw Bu::ExceptionBase("Premature end of underlying " + "stream found reading deflate stream."); + } + pState->next_in = (Bytef *)pBuf; + pState->avail_in = nRead; + } + } + else + { + return nBytes-pState->avail_out; + } + } + return 0; } Bu::size Bu::Deflate::write( const void *pData, Bu::size nBytes ) { - TRACE( pData, nBytes ); - if( nBytes <= 0 ) - return 0; - if( !pState->state ) - { - bReading = false; - int iFmt = eFmt&Gzip; - if( iFmt == Raw ) - deflateInit2( pState, nCompression, Z_DEFLATED, -15, 9, - Z_DEFAULT_STRATEGY ); - else if( iFmt == Zlib ) - deflateInit2( pState, nCompression, Z_DEFLATED, 15, 9, - Z_DEFAULT_STRATEGY ); - else if( iFmt == Gzip ) - deflateInit2( pState, nCompression, Z_DEFLATED, 16+15, 9, - Z_DEFAULT_STRATEGY ); - else - throw Bu::ExceptionBase("Invalid format for deflate."); - } - if( bReading == true ) - throw ExceptionBase("This deflate filter is in reading mode, you can't write."); - - pState->next_in = (Bytef *)pData; - pState->avail_in = nBytes; - for(;;) - { - pState->avail_out = nBufSize; - pState->next_out = (Bytef *)pBuf; - - zError( deflate( pState, Z_NO_FLUSH ) ); - - if( pState->avail_out < nBufSize ) - { - sTotalOut += rNext.write( pBuf, nBufSize-pState->avail_out ); - } - if( pState->avail_in == 0 ) - break; - } - - return nBytes; + TRACE( pData, nBytes ); + if( nBytes <= 0 ) + return 0; + if( !pState->state ) + { + bReading = false; + int iFmt = eFmt&Gzip; + if( iFmt == Raw ) + deflateInit2( pState, nCompression, Z_DEFLATED, -15, 9, + Z_DEFAULT_STRATEGY ); + else if( iFmt == Zlib ) + deflateInit2( pState, nCompression, Z_DEFLATED, 15, 9, + Z_DEFAULT_STRATEGY ); + else if( iFmt == Gzip ) + deflateInit2( pState, nCompression, Z_DEFLATED, 16+15, 9, + Z_DEFAULT_STRATEGY ); + else + throw Bu::ExceptionBase("Invalid format for deflate."); + } + if( bReading == true ) + throw ExceptionBase("This deflate filter is in reading mode, you can't write."); + + pState->next_in = (Bytef *)pData; + pState->avail_in = nBytes; + for(;;) + { + pState->avail_out = nBufSize; + pState->next_out = (Bytef *)pBuf; + + zError( deflate( pState, Z_NO_FLUSH ) ); + + if( pState->avail_out < nBufSize ) + { + sTotalOut += rNext.write( pBuf, nBufSize-pState->avail_out ); + } + if( pState->avail_in == 0 ) + break; + } + + return nBytes; } bool Bu::Deflate::isOpen() { - TRACE(); - return (pState != NULL && pState->state != NULL); + TRACE(); + return (pState != NULL && pState->state != NULL); } bool Bu::Deflate::isEos() { - TRACE(); - return bEos; + TRACE(); + return bEos; } Bu::size Bu::Deflate::getCompressedSize() { - return sTotalOut; + return sTotalOut; } diff --git a/src/stable/deflate.h b/src/stable/deflate.h index 114b173..2ccd53f 100644 --- a/src/stable/deflate.h +++ b/src/stable/deflate.h @@ -14,53 +14,53 @@ namespace Bu { - /** - * Provides Deflate (LZ77) support via zlib. This provides zlib, raw, and - * gzip stream types. By default it will autodetect the input type and - * encode into a raw deflate stream. - * - *@ingroup Streams - *@ingroup Compression - */ - class Deflate : public Bu::Filter - { - public: - enum Format - { - Raw = 0x01, - Zlib = 0x02, - Gzip = 0x03, - AutoDetect = 0x04, + /** + * Provides Deflate (LZ77) support via zlib. This provides zlib, raw, and + * gzip stream types. By default it will autodetect the input type and + * encode into a raw deflate stream. + * + *@ingroup Streams + *@ingroup Compression + */ + class Deflate : public Bu::Filter + { + public: + enum Format + { + Raw = 0x01, + Zlib = 0x02, + Gzip = 0x03, + AutoDetect = 0x04, - AutoRaw = 0x04|0x01, - AutoZlib = 0x04|0x02, - AutoGzip = 0x04|0x03 - }; + AutoRaw = 0x04|0x01, + AutoZlib = 0x04|0x02, + AutoGzip = 0x04|0x03 + }; - Deflate( Bu::Stream &rNext, int nCompression=-1, Format eFmt=AutoZlib ); - virtual ~Deflate(); + Deflate( Bu::Stream &rNext, int nCompression=-1, Format eFmt=AutoZlib ); + virtual ~Deflate(); - virtual void start(); - virtual Bu::size stop(); - virtual Bu::size read( void *pBuf, Bu::size nBytes ); - virtual Bu::size write( const void *pBuf, Bu::size nBytes ); + virtual void start(); + virtual Bu::size stop(); + virtual Bu::size read( void *pBuf, Bu::size nBytes ); + virtual Bu::size write( const void *pBuf, Bu::size nBytes ); - virtual bool isOpen(); - virtual bool isEos(); + virtual bool isOpen(); + virtual bool isEos(); - Bu::size getCompressedSize(); + Bu::size getCompressedSize(); - private: - void zError( int code ); - void *prState; - bool bReading; - int nCompression; - char *pBuf; - uint32_t nBufSize; - Bu::size sTotalOut; - Format eFmt; - bool bEos; - }; + private: + void zError( int code ); + void *prState; + bool bReading; + int nCompression; + char *pBuf; + uint32_t nBufSize; + Bu::size sTotalOut; + Format eFmt; + bool bEos; + }; } #endif diff --git a/src/stable/exceptionbase.cpp b/src/stable/exceptionbase.cpp index 87e7127..22f338f 100644 --- a/src/stable/exceptionbase.cpp +++ b/src/stable/exceptionbase.cpp @@ -11,83 +11,83 @@ #include Bu::ExceptionBase::ExceptionBase( const char *lpFormat, ... ) throw() : - nErrorCode( 0 ), - sWhat( NULL ) + nErrorCode( 0 ), + sWhat( NULL ) { - va_list ap; + va_list ap; - va_start(ap, lpFormat); - setWhat( lpFormat, ap ); - va_end(ap); + va_start(ap, lpFormat); + setWhat( lpFormat, ap ); + va_end(ap); } Bu::ExceptionBase::ExceptionBase( int nCode, const char *lpFormat, ... ) throw() : - nErrorCode( nCode ), - sWhat( NULL ) + nErrorCode( nCode ), + sWhat( NULL ) { - va_list ap; + va_list ap; - va_start(ap, lpFormat); - setWhat( lpFormat, ap ); - va_end(ap); + va_start(ap, lpFormat); + setWhat( lpFormat, ap ); + va_end(ap); } Bu::ExceptionBase::ExceptionBase( int nCode ) throw() : - nErrorCode( nCode ), - sWhat( NULL ) + nErrorCode( nCode ), + sWhat( NULL ) { } Bu::ExceptionBase::ExceptionBase( const ExceptionBase &e ) throw () : - std::exception( e ), - nErrorCode( e.nErrorCode ), - sWhat( NULL ) + std::exception( e ), + nErrorCode( e.nErrorCode ), + sWhat( NULL ) { - setWhat( e.sWhat ); + setWhat( e.sWhat ); } Bu::ExceptionBase::~ExceptionBase() throw() { - delete[] sWhat; - sWhat = NULL; + delete[] sWhat; + sWhat = NULL; } void Bu::ExceptionBase::setWhat( const char *lpFormat, va_list &vargs ) { - if( sWhat ) delete[] sWhat; - int nSize; - - va_list vargs2; - va_copy( vargs2, vargs ); - nSize = vsnprintf( NULL, 0, lpFormat, vargs2 ); - va_end( vargs2 ); - sWhat = new char[nSize+1]; - vsnprintf( sWhat, nSize+1, lpFormat, vargs ); + if( sWhat ) delete[] sWhat; + int nSize; + + va_list vargs2; + va_copy( vargs2, vargs ); + nSize = vsnprintf( NULL, 0, lpFormat, vargs2 ); + va_end( vargs2 ); + sWhat = new char[nSize+1]; + vsnprintf( sWhat, nSize+1, lpFormat, vargs ); } void Bu::ExceptionBase::setWhat( const char *lpText ) { - if( sWhat ) delete[] sWhat; - int nSize; + if( sWhat ) delete[] sWhat; + int nSize; - nSize = strlen( lpText ); - sWhat = new char[nSize+1]; - strcpy( sWhat, lpText ); + nSize = strlen( lpText ); + sWhat = new char[nSize+1]; + strcpy( sWhat, lpText ); } const char *Bu::ExceptionBase::what() const throw() { - return sWhat; + return sWhat; } int Bu::ExceptionBase::getErrorCode() { - return nErrorCode; + return nErrorCode; } Bu::UnsupportedException::UnsupportedException() throw() : - ExceptionBase( 0 ) + ExceptionBase( 0 ) { - setWhat("An unsupperted operation was attempted."); + setWhat("An unsupperted operation was attempted."); } diff --git a/src/stable/exceptionbase.h b/src/stable/exceptionbase.h index 9e6c72d..8f651b7 100644 --- a/src/stable/exceptionbase.h +++ b/src/stable/exceptionbase.h @@ -18,173 +18,173 @@ namespace Bu { - /** - * A generalized Exception base class. This is nice for making general and - * flexible child classes that can create new error code classes. - * - * In order to create your own exception class use these two lines. - * - * in your header: subExceptionDecl( NewClassName ); - * - * in your source: subExcpetienDef( NewClassName ); - */ - class ExceptionBase : public std::exception - { - public: - /** - * Construct an exception with an error code of zero, but with a - * description. The use of this is not reccomended most of the time, - * it's generally best to include an error code with the exception so - * your program can handle the exception in a better way. - * @param sFormat The format of the text. See printf for more info. - */ - ExceptionBase( const char *sFormat, ... ) throw(); - - /** - * - * @param nCode - * @param sFormat - */ - ExceptionBase( int nCode, const char *sFormat, ... ) throw(); - - /** - * - * @param nCode - * @return - */ - ExceptionBase( int nCode=0 ) throw(); - - ExceptionBase( const ExceptionBase &e ) throw (); - - /** - * - * @return - */ - virtual ~ExceptionBase() throw(); - - /** - * - * @return - */ - virtual const char *what() const throw(); - - /** - * - * @return - */ - int getErrorCode(); - - /** - * - * @param lpFormat - * @param vargs - */ - void setWhat( const char *lpFormat, va_list &vargs ); - - /** - * - * @param lpText - */ - void setWhat( const char *lpText ); - - private: - int nErrorCode; /**< The code for the error that occured. */ - char *sWhat; /**< The text string telling people what went wrong. */ - }; + /** + * A generalized Exception base class. This is nice for making general and + * flexible child classes that can create new error code classes. + * + * In order to create your own exception class use these two lines. + * + * in your header: subExceptionDecl( NewClassName ); + * + * in your source: subExcpetienDef( NewClassName ); + */ + class ExceptionBase : public std::exception + { + public: + /** + * Construct an exception with an error code of zero, but with a + * description. The use of this is not reccomended most of the time, + * it's generally best to include an error code with the exception so + * your program can handle the exception in a better way. + * @param sFormat The format of the text. See printf for more info. + */ + ExceptionBase( const char *sFormat, ... ) throw(); + + /** + * + * @param nCode + * @param sFormat + */ + ExceptionBase( int nCode, const char *sFormat, ... ) throw(); + + /** + * + * @param nCode + * @return + */ + ExceptionBase( int nCode=0 ) throw(); + + ExceptionBase( const ExceptionBase &e ) throw (); + + /** + * + * @return + */ + virtual ~ExceptionBase() throw(); + + /** + * + * @return + */ + virtual const char *what() const throw(); + + /** + * + * @return + */ + int getErrorCode(); + + /** + * + * @param lpFormat + * @param vargs + */ + void setWhat( const char *lpFormat, va_list &vargs ); + + /** + * + * @param lpText + */ + void setWhat( const char *lpText ); + + private: + int nErrorCode; /**< The code for the error that occured. */ + char *sWhat; /**< The text string telling people what went wrong. */ + }; } -#define subExceptionDecl( name ) \ -class name : public Bu::ExceptionBase \ -{ \ - public: \ - name( const char *sFormat, ... ) throw (); \ - name( int nCode, const char *sFormat, ... ) throw(); \ - name( int nCode=0 ) throw (); \ - name( const name &e ) throw (); \ +#define subExceptionDecl( name ) \ +class name : public Bu::ExceptionBase \ +{ \ + public: \ + name( const char *sFormat, ... ) throw (); \ + name( int nCode, const char *sFormat, ... ) throw(); \ + name( int nCode=0 ) throw (); \ + name( const name &e ) throw (); \ }; -#define subExceptionDeclChild( name, parent ) \ -class name : public parent \ -{ \ - public: \ - name( const char *sFormat, ... ) throw (); \ - name( int nCode, const char *sFormat, ... ) throw(); \ - name( int nCode=0 ) throw (); \ - name( const name &e ) throw (); \ +#define subExceptionDeclChild( name, parent ) \ +class name : public parent \ +{ \ + public: \ + name( const char *sFormat, ... ) throw (); \ + name( int nCode, const char *sFormat, ... ) throw(); \ + name( int nCode=0 ) throw (); \ + name( const name &e ) throw (); \ }; -#define subExceptionDeclBegin( name ) \ -class name : public Bu::ExceptionBase \ -{ \ - public: \ - name( const char *sFormat, ... ) throw (); \ - name( int nCode, const char *sFormat, ... ) throw(); \ - name( int nCode=0 ) throw (); \ - name( const name &e ) throw (); +#define subExceptionDeclBegin( name ) \ +class name : public Bu::ExceptionBase \ +{ \ + public: \ + name( const char *sFormat, ... ) throw (); \ + name( int nCode, const char *sFormat, ... ) throw(); \ + name( int nCode=0 ) throw (); \ + name( const name &e ) throw (); -#define subExceptionDeclEnd() \ +#define subExceptionDeclEnd() \ }; -#define subExceptionDef( name ) \ -name::name( const char *lpFormat, ... ) throw() : \ - ExceptionBase( 0 ) \ -{ \ - va_list ap; \ - va_start( ap, lpFormat ); \ - setWhat( lpFormat, ap ); \ - va_end( ap ); \ -} \ -name::name( int nCode, const char *lpFormat, ... ) throw() : \ - ExceptionBase( nCode ) \ -{ \ - va_list ap; \ - va_start( ap, lpFormat ); \ - setWhat( lpFormat, ap ); \ - va_end( ap ); \ -} \ -name::name( int nCode ) throw() : \ - ExceptionBase( nCode ) \ -{ \ -} \ -name::name( const name &e ) throw() : \ - ExceptionBase( e ) \ -{ \ +#define subExceptionDef( name ) \ +name::name( const char *lpFormat, ... ) throw() : \ + ExceptionBase( 0 ) \ +{ \ + va_list ap; \ + va_start( ap, lpFormat ); \ + setWhat( lpFormat, ap ); \ + va_end( ap ); \ +} \ +name::name( int nCode, const char *lpFormat, ... ) throw() : \ + ExceptionBase( nCode ) \ +{ \ + va_list ap; \ + va_start( ap, lpFormat ); \ + setWhat( lpFormat, ap ); \ + va_end( ap ); \ +} \ +name::name( int nCode ) throw() : \ + ExceptionBase( nCode ) \ +{ \ +} \ +name::name( const name &e ) throw() : \ + ExceptionBase( e ) \ +{ \ } -#define subExceptionDefChild( name, parent ) \ -name::name( const char *lpFormat, ... ) throw() : \ - parent( 0 ) \ -{ \ - va_list ap; \ - va_start( ap, lpFormat ); \ - setWhat( lpFormat, ap ); \ - va_end( ap ); \ -} \ -name::name( int nCode, const char *lpFormat, ... ) throw() : \ - parent( nCode ) \ -{ \ - va_list ap; \ - va_start( ap, lpFormat ); \ - setWhat( lpFormat, ap ); \ - va_end( ap ); \ -} \ -name::name( int nCode ) throw() : \ - parent( nCode ) \ -{ \ -} \ -name::name( const name &e ) throw() : \ - ExceptionBase( e ) \ -{ \ +#define subExceptionDefChild( name, parent ) \ +name::name( const char *lpFormat, ... ) throw() : \ + parent( 0 ) \ +{ \ + va_list ap; \ + va_start( ap, lpFormat ); \ + setWhat( lpFormat, ap ); \ + va_end( ap ); \ +} \ +name::name( int nCode, const char *lpFormat, ... ) throw() : \ + parent( nCode ) \ +{ \ + va_list ap; \ + va_start( ap, lpFormat ); \ + setWhat( lpFormat, ap ); \ + va_end( ap ); \ +} \ +name::name( int nCode ) throw() : \ + parent( nCode ) \ +{ \ +} \ +name::name( const name &e ) throw() : \ + ExceptionBase( e ) \ +{ \ } namespace Bu { - // Exceptions that are so general they could be used anywhere go here. - class UnsupportedException : public Bu::ExceptionBase - { - public: - UnsupportedException() throw (); - }; + // Exceptions that are so general they could be used anywhere go here. + class UnsupportedException : public Bu::ExceptionBase + { + public: + UnsupportedException() throw (); + }; } #endif diff --git a/src/stable/extratypes.h b/src/stable/extratypes.h index 2961920..3549529 100644 --- a/src/stable/extratypes.h +++ b/src/stable/extratypes.h @@ -19,11 +19,11 @@ namespace Bu { #ifdef USE_64BIT_IO - typedef int64_t size; - typedef uint64_t usize; + typedef int64_t size; + typedef uint64_t usize; #else - typedef int32_t size; - typedef uint32_t usize; + typedef int32_t size; + typedef uint32_t usize; #endif }; diff --git a/src/stable/file.cpp b/src/stable/file.cpp index 14e4f3c..7ae2484 100644 --- a/src/stable/file.cpp +++ b/src/stable/file.cpp @@ -19,298 +19,298 @@ namespace Bu { subExceptionDef( FileException ) } Bu::File::File( const Bu::String &sName, int iFlags ) : - fd( -1 ), - bEos( true ) + fd( -1 ), + bEos( true ) { #ifdef USE_64BIT_IO - fd = ::open64( sName.getStr(), getPosixFlags( iFlags ), 0666 ); + fd = ::open64( sName.getStr(), getPosixFlags( iFlags ), 0666 ); #else - fd = ::open( sName.getStr(), getPosixFlags( iFlags ), 0666 ); + fd = ::open( sName.getStr(), getPosixFlags( iFlags ), 0666 ); #endif - if( fd < 0 ) - { - throw Bu::FileException( errno, "%s: %s", - strerror(errno), sName.getStr() ); - } - bEos = false; + if( fd < 0 ) + { + throw Bu::FileException( errno, "%s: %s", + strerror(errno), sName.getStr() ); + } + bEos = false; } Bu::File::File( int fd ) : - fd( fd ) + fd( fd ) { - bEos = false; + bEos = false; } Bu::File::~File() { - close(); + close(); } void Bu::File::close() { - if( fd >= 0 ) - { - if( ::close( fd ) ) - { - throw Bu::FileException( errno, "%s", - strerror(errno) ); - } - fd = -1; - bEos = true; - } + if( fd >= 0 ) + { + if( ::close( fd ) ) + { + throw Bu::FileException( errno, "%s", + strerror(errno) ); + } + fd = -1; + bEos = true; + } } Bu::size Bu::File::read( void *pBuf, Bu::size nBytes ) { - if( fd < 0 ) - throw FileException("File not open."); - - Bu::size iRead = ::read( fd, pBuf, nBytes ); - if( iRead == 0 ) - bEos = true; - else if( iRead == -1 && errno == EAGAIN ) - return 0; - else if( iRead < 0 ) - throw FileException( errno, "%s", strerror( errno ) ); - return iRead; + if( fd < 0 ) + throw FileException("File not open."); + + Bu::size iRead = ::read( fd, pBuf, nBytes ); + if( iRead == 0 ) + bEos = true; + else if( iRead == -1 && errno == EAGAIN ) + return 0; + else if( iRead < 0 ) + throw FileException( errno, "%s", strerror( errno ) ); + return iRead; } Bu::size Bu::File::write( const void *pBuf, Bu::size nBytes ) { - if( fd < 0 ) - throw FileException("File not open."); + if( fd < 0 ) + throw FileException("File not open."); - Bu::size iWrote = ::write( fd, pBuf, nBytes ); - if( iWrote < 0 ) - throw FileException( errno, "%s", strerror( errno ) ); - return iWrote; + Bu::size iWrote = ::write( fd, pBuf, nBytes ); + if( iWrote < 0 ) + throw FileException( errno, "%s", strerror( errno ) ); + return iWrote; } Bu::size Bu::File::tell() { - if( fd < 0 ) - throw FileException("File not open."); + if( fd < 0 ) + throw FileException("File not open."); #ifdef USE_64BIT_IO - return lseek64( fd, 0, SEEK_CUR ); + return lseek64( fd, 0, SEEK_CUR ); #else - return lseek( fd, 0, SEEK_CUR ); + return lseek( fd, 0, SEEK_CUR ); #endif } void Bu::File::seek( Bu::size offset ) { - if( fd < 0 ) - throw FileException("File not open."); + if( fd < 0 ) + throw FileException("File not open."); #ifdef USE_64BIT_IO - lseek64( fd, offset, SEEK_CUR ); + lseek64( fd, offset, SEEK_CUR ); #else - lseek( fd, offset, SEEK_CUR ); + lseek( fd, offset, SEEK_CUR ); #endif - bEos = false; + bEos = false; } void Bu::File::setPos( Bu::size pos ) { - if( fd < 0 ) - throw FileException("File not open."); + if( fd < 0 ) + throw FileException("File not open."); #ifdef USE_64BIT_IO - lseek64( fd, pos, SEEK_SET ); + lseek64( fd, pos, SEEK_SET ); #else - lseek( fd, pos, SEEK_SET ); + lseek( fd, pos, SEEK_SET ); #endif - bEos = false; + bEos = false; } void Bu::File::setPosEnd( Bu::size pos ) { - if( fd < 0 ) - throw FileException("File not open."); - - lseek64( fd, pos, SEEK_END ); - bEos = false; + if( fd < 0 ) + throw FileException("File not open."); + + lseek64( fd, pos, SEEK_END ); + bEos = false; } bool Bu::File::isEos() { - return bEos; + return bEos; } bool Bu::File::canRead() { #ifdef WIN32 - return true; + return true; #else - int iMode = fcntl( fd, F_GETFL, 0 )&O_ACCMODE; - if( iMode == O_RDONLY || iMode == O_RDWR ) - return true; - return false; + int iMode = fcntl( fd, F_GETFL, 0 )&O_ACCMODE; + if( iMode == O_RDONLY || iMode == O_RDWR ) + return true; + return false; #endif } bool Bu::File::canWrite() { #ifdef WIN32 - return true; + return true; #else - int iMode = fcntl( fd, F_GETFL, 0 )&O_ACCMODE; - if( iMode == O_WRONLY || iMode == O_RDWR ) - return true; - return false; + int iMode = fcntl( fd, F_GETFL, 0 )&O_ACCMODE; + if( iMode == O_WRONLY || iMode == O_RDWR ) + return true; + return false; #endif } bool Bu::File::isReadable() { - return true; + return true; } bool Bu::File::isWritable() { - return true; + return true; } bool Bu::File::isSeekable() { - return true; + return true; } bool Bu::File::isBlocking() { - return true; + return true; } void Bu::File::setBlocking( bool bBlocking ) { #ifdef WIN32 - fprintf(stderr, "STUB: Bu::File::setBlocking\n"); + fprintf(stderr, "STUB: Bu::File::setBlocking\n"); #else - if( bBlocking ) - fcntl( - fd, - F_SETFL, fcntl( fd, F_GETFL, 0 )&(~O_NONBLOCK) - ); - else - fcntl( - fd, - F_SETFL, fcntl( fd, F_GETFL, 0 )|O_NONBLOCK - ); + if( bBlocking ) + fcntl( + fd, + F_SETFL, fcntl( fd, F_GETFL, 0 )&(~O_NONBLOCK) + ); + else + fcntl( + fd, + F_SETFL, fcntl( fd, F_GETFL, 0 )|O_NONBLOCK + ); #endif } Bu::File Bu::File::tempFile( Bu::String &sName ) { - int iXes; - for( iXes = sName.getSize()-1; iXes >= 0; iXes-- ) - { - if( sName[iXes] != 'X' ) - break; - } - iXes++; - if( iXes == sName.getSize() ) - throw Bu::ExceptionBase("Invalid temporary filename template."); - for( int iter = 0; iter < 1000; iter++ ) - { - for( int j = iXes; j < sName.getSize(); j++ ) - { - uint32_t iX = Bu::Random::rand(); - sName[j] = ('A'+(iX%26)) | ((iX&0x1000)?(0x20):(0)); - } - - try - { - return Bu::File( sName, Bu::File::Read|Bu::File::Write - |Bu::File::Create|Bu::File::Exclusive ); - } catch(...) { } - } - throw Bu::FileException("Failed to create unique temporary file after 1000" - " iterations."); + int iXes; + for( iXes = sName.getSize()-1; iXes >= 0; iXes-- ) + { + if( sName[iXes] != 'X' ) + break; + } + iXes++; + if( iXes == sName.getSize() ) + throw Bu::ExceptionBase("Invalid temporary filename template."); + for( int iter = 0; iter < 1000; iter++ ) + { + for( int j = iXes; j < sName.getSize(); j++ ) + { + uint32_t iX = Bu::Random::rand(); + sName[j] = ('A'+(iX%26)) | ((iX&0x1000)?(0x20):(0)); + } + + try + { + return Bu::File( sName, Bu::File::Read|Bu::File::Write + |Bu::File::Create|Bu::File::Exclusive ); + } catch(...) { } + } + throw Bu::FileException("Failed to create unique temporary file after 1000" + " iterations."); } void Bu::File::setSize( Bu::size iSize ) { #ifdef WIN32 - chsize( fd, iSize ); + chsize( fd, iSize ); #else - ftruncate( fd, iSize ); + ftruncate( fd, iSize ); #endif } Bu::size Bu::File::getSize() const { - struct stat st; - fstat( fd, &st ); - return st.st_size; + struct stat st; + fstat( fd, &st ); + return st.st_size; } Bu::size Bu::File::getBlockSize() const { #ifdef WIN32 - return 4096; + return 4096; #else - struct stat st; - fstat( fd, &st ); - return st.st_blksize; + struct stat st; + fstat( fd, &st ); + return st.st_blksize; #endif } Bu::String Bu::File::getLocation() const { - return "to be implemented"; + return "to be implemented"; } #ifndef WIN32 void Bu::File::chmod( mode_t t ) { - fchmod( fd, t ); + fchmod( fd, t ); } #endif void Bu::File::flush() { - // There is no flushing with direct I/O... - //fflush( fh ); + // There is no flushing with direct I/O... + //fflush( fh ); } bool Bu::File::isOpen() { - return (fd > -1); + return (fd > -1); } int Bu::File::getPosixFlags( int iFlags ) { - int iRet = 0; - switch( (iFlags&ReadWrite) ) - { - // According to posix, O_RDWR is not necesarilly O_RDONLY|O_WRONLY, so - // lets be proper and use the right value in the right place. - case Read: iRet = O_RDONLY; break; - case Write: iRet = O_WRONLY; break; - case ReadWrite: iRet = O_RDWR; break; - default: - throw FileException( - "You must specify Read, Write, or both when opening a file."); - } - - if( (iFlags&Create) ) - iRet |= O_CREAT; - if( (iFlags&Append) ) - iRet |= O_APPEND; - if( (iFlags&Truncate) ) - iRet |= O_TRUNC; + int iRet = 0; + switch( (iFlags&ReadWrite) ) + { + // According to posix, O_RDWR is not necesarilly O_RDONLY|O_WRONLY, so + // lets be proper and use the right value in the right place. + case Read: iRet = O_RDONLY; break; + case Write: iRet = O_WRONLY; break; + case ReadWrite: iRet = O_RDWR; break; + default: + throw FileException( + "You must specify Read, Write, or both when opening a file."); + } + + if( (iFlags&Create) ) + iRet |= O_CREAT; + if( (iFlags&Append) ) + iRet |= O_APPEND; + if( (iFlags&Truncate) ) + iRet |= O_TRUNC; #ifndef WIN32 - if( (iFlags&NonBlock) ) - iRet |= O_NONBLOCK; + if( (iFlags&NonBlock) ) + iRet |= O_NONBLOCK; #endif - if( (iFlags&Exclusive) == Exclusive ) - iRet |= O_EXCL; + if( (iFlags&Exclusive) == Exclusive ) + iRet |= O_EXCL; #ifdef O_BINARY - iRet |= O_BINARY; + iRet |= O_BINARY; #endif - return iRet; + return iRet; } diff --git a/src/stable/file.h b/src/stable/file.h index eaf2974..2ecb27e 100644 --- a/src/stable/file.h +++ b/src/stable/file.h @@ -17,90 +17,90 @@ namespace Bu { - subExceptionDecl( FileException ); - - /** - * A file stream. - *@ingroup Streams - */ - class File : public Bu::Stream - { - public: - File( const Bu::String &sName, int iFlags ); - File( int fd ); - virtual ~File(); - - virtual void close(); - virtual Bu::size read( void *pBuf, Bu::size nBytes ); - virtual Bu::size write( const void *pBuf, Bu::size nBytes ); - using Stream::write; - - virtual Bu::size tell(); - virtual void seek( Bu::size offset ); - virtual void setPos( Bu::size pos ); - virtual void setPosEnd( Bu::size pos ); - virtual bool isEos(); - virtual bool isOpen(); - - virtual void flush(); - - virtual bool canRead(); - virtual bool canWrite(); - - virtual bool isReadable(); - virtual bool isWritable(); - virtual bool isSeekable(); - - virtual bool isBlocking(); - virtual void setBlocking( bool bBlocking=true ); - - enum { - // Flags - Read = 0x01, ///< Open file for reading - Write = 0x02, ///< Open file for writing - Create = 0x04, ///< Create file if it doesn't exist - Truncate = 0x08, ///< Truncate file if it does exist - Append = 0x10, ///< Always append on every write - NonBlock = 0x20, ///< Open file in non-blocking mode - Exclusive = 0x44, ///< Create file, if it exists then fail - - // Helpful mixes - ReadWrite = 0x03, ///< Open for reading and writing - WriteNew = 0x0E ///< Create a file (or truncate) for writing. - /// Same as Write|Create|Truncate - }; - - virtual void setSize( Bu::size iSize ); - - virtual size getSize() const; - virtual size getBlockSize() const; - virtual Bu::String getLocation() const; - - /** - * Create a temp file and return its handle. The file is opened - * Read/Write. - *@param sName (Bu::String) Give in the form: "/tmp/tmpfileXXXXXXXX" - * It will alter your (sName) setting the 'X's to random - * characters. - *@returns (Bu::File) A file object representing your temp file. - */ - static Bu::File tempFile( Bu::String &sName ); + subExceptionDecl( FileException ); + + /** + * A file stream. + *@ingroup Streams + */ + class File : public Bu::Stream + { + public: + File( const Bu::String &sName, int iFlags ); + File( int fd ); + virtual ~File(); + + virtual void close(); + virtual Bu::size read( void *pBuf, Bu::size nBytes ); + virtual Bu::size write( const void *pBuf, Bu::size nBytes ); + using Stream::write; + + virtual Bu::size tell(); + virtual void seek( Bu::size offset ); + virtual void setPos( Bu::size pos ); + virtual void setPosEnd( Bu::size pos ); + virtual bool isEos(); + virtual bool isOpen(); + + virtual void flush(); + + virtual bool canRead(); + virtual bool canWrite(); + + virtual bool isReadable(); + virtual bool isWritable(); + virtual bool isSeekable(); + + virtual bool isBlocking(); + virtual void setBlocking( bool bBlocking=true ); + + enum { + // Flags + Read = 0x01, ///< Open file for reading + Write = 0x02, ///< Open file for writing + Create = 0x04, ///< Create file if it doesn't exist + Truncate = 0x08, ///< Truncate file if it does exist + Append = 0x10, ///< Always append on every write + NonBlock = 0x20, ///< Open file in non-blocking mode + Exclusive = 0x44, ///< Create file, if it exists then fail + + // Helpful mixes + ReadWrite = 0x03, ///< Open for reading and writing + WriteNew = 0x0E ///< Create a file (or truncate) for writing. + /// Same as Write|Create|Truncate + }; + + virtual void setSize( Bu::size iSize ); + + virtual size getSize() const; + virtual size getBlockSize() const; + virtual Bu::String getLocation() const; + + /** + * Create a temp file and return its handle. The file is opened + * Read/Write. + *@param sName (Bu::String) Give in the form: "/tmp/tmpfileXXXXXXXX" + * It will alter your (sName) setting the 'X's to random + * characters. + *@returns (Bu::File) A file object representing your temp file. + */ + static Bu::File tempFile( Bu::String &sName ); #ifndef WIN32 - /** - * Change the file access permissions. - *@param t (mode_t) The new file access permissions. - */ - void chmod( mode_t t ); + /** + * Change the file access permissions. + *@param t (mode_t) The new file access permissions. + */ + void chmod( mode_t t ); #endif - private: - int getPosixFlags( int iFlags ); + private: + int getPosixFlags( int iFlags ); - private: - int fd; - bool bEos; - }; + private: + int fd; + bool bEos; + }; } #endif diff --git a/src/stable/filter.cpp b/src/stable/filter.cpp index 9c1d66f..e7929e7 100644 --- a/src/stable/filter.cpp +++ b/src/stable/filter.cpp @@ -8,7 +8,7 @@ #include "bu/filter.h" Bu::Filter::Filter( Bu::Stream &rNext ) : - rNext( rNext ) + rNext( rNext ) { } @@ -18,73 +18,73 @@ Bu::Filter::~Filter() void Bu::Filter::close() { - stop(); - rNext.close(); + stop(); + rNext.close(); } Bu::size Bu::Filter::tell() { - return rNext.tell(); + return rNext.tell(); } void Bu::Filter::seek( Bu::size offset ) { - rNext.seek( offset ); + rNext.seek( offset ); } void Bu::Filter::setPos( Bu::size pos ) { - rNext.setPos( pos ); + rNext.setPos( pos ); } void Bu::Filter::setPosEnd( Bu::size pos ) { - rNext.setPosEnd( pos ); + rNext.setPosEnd( pos ); } bool Bu::Filter::isEos() { - return rNext.isEos(); + return rNext.isEos(); } bool Bu::Filter::isOpen() { - return rNext.isOpen(); + return rNext.isOpen(); } bool Bu::Filter::canRead() { - return rNext.canRead(); + return rNext.canRead(); } bool Bu::Filter::canWrite() { - return rNext.canWrite(); + return rNext.canWrite(); } bool Bu::Filter::isReadable() { - return rNext.isReadable(); + return rNext.isReadable(); } bool Bu::Filter::isWritable() { - return rNext.isWritable(); + return rNext.isWritable(); } bool Bu::Filter::isSeekable() { - return rNext.isSeekable(); + return rNext.isSeekable(); } bool Bu::Filter::isBlocking() { - return rNext.isBlocking(); + return rNext.isBlocking(); } void Bu::Filter::setBlocking( bool bBlocking ) { - rNext.setBlocking( bBlocking ); + rNext.setBlocking( bBlocking ); } void Bu::Filter::setSize( Bu::size ) @@ -93,21 +93,21 @@ void Bu::Filter::setSize( Bu::size ) void Bu::Filter::flush() { - rNext.flush(); + rNext.flush(); } Bu::size Bu::Filter::getSize() const { - return rNext.getSize(); + return rNext.getSize(); } Bu::size Bu::Filter::getBlockSize() const { - return rNext.getBlockSize(); + return rNext.getBlockSize(); } Bu::String Bu::Filter::getLocation() const { - return rNext.getLocation(); + return rNext.getLocation(); } diff --git a/src/stable/filter.h b/src/stable/filter.h index 3e1c7d8..49a6664 100644 --- a/src/stable/filter.h +++ b/src/stable/filter.h @@ -14,70 +14,70 @@ namespace Bu { - /** - * Data filter base class. Each data filter should contain a read and write - * section. Effectively, the write applies the filter, the read un-applies - * the filter, if possible. For example, BZip2 is a filter that compresses - * on write and decompresses on read. All bi-directional filters should - * follow: x == read( write( x ) ) (byte-for-byte comparison) - * - * Also, all returned buffers should be owned by the filter, and deleted - * when the filter is deleted. This means that the output of a read or - * write operation must be used before the next call to read or write or the - * data will be destroyed. Also, the internal buffer may be changed or - * recreated between calls, so always get a new pointer from a call to - * read or write. - * - * The close function can also return data, so make sure to check for it, - * many filters such as compression filters will buffer data until they have - * enough to create a compression block, in these cases the leftover data - * will be returned by close. - *@ingroup Streams - */ - class Filter : public Bu::Stream - { - public: - Filter( Bu::Stream &rNext ); - virtual ~Filter(); + /** + * Data filter base class. Each data filter should contain a read and write + * section. Effectively, the write applies the filter, the read un-applies + * the filter, if possible. For example, BZip2 is a filter that compresses + * on write and decompresses on read. All bi-directional filters should + * follow: x == read( write( x ) ) (byte-for-byte comparison) + * + * Also, all returned buffers should be owned by the filter, and deleted + * when the filter is deleted. This means that the output of a read or + * write operation must be used before the next call to read or write or the + * data will be destroyed. Also, the internal buffer may be changed or + * recreated between calls, so always get a new pointer from a call to + * read or write. + * + * The close function can also return data, so make sure to check for it, + * many filters such as compression filters will buffer data until they have + * enough to create a compression block, in these cases the leftover data + * will be returned by close. + *@ingroup Streams + */ + class Filter : public Bu::Stream + { + public: + Filter( Bu::Stream &rNext ); + virtual ~Filter(); - virtual void start()=0; - virtual Bu::size stop()=0; - virtual void close(); - virtual Bu::size tell(); - virtual void seek( Bu::size offset ); - virtual void setPos( Bu::size pos ); - virtual void setPosEnd( Bu::size pos ); - virtual bool isEos(); - virtual bool isOpen(); + virtual void start()=0; + virtual Bu::size stop()=0; + virtual void close(); + virtual Bu::size tell(); + virtual void seek( Bu::size offset ); + virtual void setPos( Bu::size pos ); + virtual void setPosEnd( Bu::size pos ); + virtual bool isEos(); + virtual bool isOpen(); - virtual void flush(); + virtual void flush(); - virtual bool canRead(); - virtual bool canWrite(); + virtual bool canRead(); + virtual bool canWrite(); - virtual bool isReadable(); - virtual bool isWritable(); - virtual bool isSeekable(); + virtual bool isReadable(); + virtual bool isWritable(); + virtual bool isSeekable(); - virtual bool isBlocking(); - virtual void setBlocking( bool bBlocking=true ); + virtual bool isBlocking(); + virtual void setBlocking( bool bBlocking=true ); - /** - * Most filters won't re-implement this, it doesn't make a lot of sense - * for filters, in general. - */ - virtual void setSize( Bu::size iSize ); + /** + * Most filters won't re-implement this, it doesn't make a lot of sense + * for filters, in general. + */ + virtual void setSize( Bu::size iSize ); - virtual size getSize() const; - virtual size getBlockSize() const; - virtual Bu::String getLocation() const; - - protected: - Bu::Stream &rNext; + virtual size getSize() const; + virtual size getBlockSize() const; + virtual Bu::String getLocation() const; + + protected: + Bu::Stream &rNext; - private: + private: - }; + }; } #endif diff --git a/src/stable/fmt.h b/src/stable/fmt.h index bcc5240..9ecaf80 100644 --- a/src/stable/fmt.h +++ b/src/stable/fmt.h @@ -3,92 +3,92 @@ namespace Bu { - typedef struct Fmt - { - enum Alignment - { - Left = 0, - Center = 1, - Right = 2 - }; - Fmt() : - uMinWidth( 0 ), - cFillChar(' '), - uRadix( 10 ), - uAlign( Right ), - bPlus( false ), - bCaps( false ), - bTokenize( true ) - { - } + typedef struct Fmt + { + enum Alignment + { + Left = 0, + Center = 1, + Right = 2 + }; + Fmt() : + uMinWidth( 0 ), + cFillChar(' '), + uRadix( 10 ), + uAlign( Right ), + bPlus( false ), + bCaps( false ), + bTokenize( true ) + { + } - Fmt( unsigned int uMinWidth, unsigned int uRadix=10, - Alignment a=Right, bool bPlus=false, bool bCaps=true, - char cFill=' ') : - uMinWidth( uMinWidth ), - cFillChar(cFill), - uRadix( uRadix ), - uAlign( a ), - bPlus( bPlus ), - bCaps( bCaps ), - bTokenize( true ) - { - } - Fmt( unsigned int uMinWidth, Alignment a, - unsigned int uRadix=10, bool bPlus=false, bool bCaps=true, - char cFill=' ') : - uMinWidth( uMinWidth ), - cFillChar(cFill), - uRadix( uRadix ), - uAlign( a ), - bPlus( bPlus ), - bCaps( bCaps ), - bTokenize( true ) - { - } + Fmt( unsigned int uMinWidth, unsigned int uRadix=10, + Alignment a=Right, bool bPlus=false, bool bCaps=true, + char cFill=' ') : + uMinWidth( uMinWidth ), + cFillChar(cFill), + uRadix( uRadix ), + uAlign( a ), + bPlus( bPlus ), + bCaps( bCaps ), + bTokenize( true ) + { + } + Fmt( unsigned int uMinWidth, Alignment a, + unsigned int uRadix=10, bool bPlus=false, bool bCaps=true, + char cFill=' ') : + uMinWidth( uMinWidth ), + cFillChar(cFill), + uRadix( uRadix ), + uAlign( a ), + bPlus( bPlus ), + bCaps( bCaps ), + bTokenize( true ) + { + } - static Fmt hex( unsigned int uWidth=0, bool bCaps=false ) - { - return Fmt( uWidth, 16, Right, false, bCaps, '0' ); - } - - static Fmt oct( unsigned int uWidth=0 ) - { - return Fmt( uWidth, 8, Right, false, false, '0' ); - } + static Fmt hex( unsigned int uWidth=0, bool bCaps=false ) + { + return Fmt( uWidth, 16, Right, false, bCaps, '0' ); + } + + static Fmt oct( unsigned int uWidth=0 ) + { + return Fmt( uWidth, 8, Right, false, false, '0' ); + } - static Fmt bin( unsigned int uWidth=0 ) - { - return Fmt( uWidth, 1, Right, false, false, '0' ); - } + static Fmt bin( unsigned int uWidth=0 ) + { + return Fmt( uWidth, 1, Right, false, false, '0' ); + } - static Fmt ptr( bool bCaps=true ) - { - return Fmt( sizeof(ptrdiff_t)*2, 16, Right, false, bCaps, '0' ); - } + static Fmt ptr( bool bCaps=true ) + { + return Fmt( sizeof(ptrdiff_t)*2, 16, Right, false, bCaps, '0' ); + } - Fmt &width( unsigned int uWidth ); - Fmt &fill( char cFill='0' ); - Fmt &radix( unsigned int uRadix ); - Fmt &align( Alignment eAlign ); - Fmt &plus( bool bPlus=true ); - Fmt &caps( bool bCaps=true ); - Fmt &upper(); - Fmt &lower(); - Fmt &tokenize( bool bTokenize=true ); + Fmt &width( unsigned int uWidth ); + Fmt &fill( char cFill='0' ); + Fmt &radix( unsigned int uRadix ); + Fmt &align( Alignment eAlign ); + Fmt &plus( bool bPlus=true ); + Fmt &caps( bool bCaps=true ); + Fmt &upper(); + Fmt &lower(); + Fmt &tokenize( bool bTokenize=true ); - Fmt &left(); - Fmt &right(); - Fmt ¢er(); + Fmt &left(); + Fmt &right(); + Fmt ¢er(); - unsigned char uMinWidth; - char cFillChar; - unsigned short uRadix : 6; - unsigned short uAlign : 2; - unsigned short bPlus : 1; - unsigned short bCaps : 1; - unsigned short bTokenize : 1; - } Fmt; + unsigned char uMinWidth; + char cFillChar; + unsigned short uRadix : 6; + unsigned short uAlign : 2; + unsigned short bPlus : 1; + unsigned short bCaps : 1; + unsigned short bTokenize : 1; + } Fmt; }; #endif diff --git a/src/stable/formatter.cpp b/src/stable/formatter.cpp index a04f7a6..9a42c99 100644 --- a/src/stable/formatter.cpp +++ b/src/stable/formatter.cpp @@ -12,54 +12,54 @@ template<> float Bu::tlog( float x ) { - return logf( x ); + return logf( x ); } template<> double Bu::tlog( double x ) { - return log( x ); + return log( x ); } template<> long double Bu::tlog( long double x ) { - return logl( x ); + return logl( x ); } template<> float Bu::tfloor( float x ) { - return floorf( x ); + return floorf( x ); } template<> double Bu::tfloor( double x ) { - return floor( x ); + return floor( x ); } template<> long double Bu::tfloor( long double x ) { - return floorl( x ); + return floorl( x ); } template<> float Bu::tpow( float x, float y ) { - return powf( x, y ); + return powf( x, y ); } template<> double Bu::tpow( double x, double y ) { - return pow( x, y ); + return pow( x, y ); } template<> long double Bu::tpow( long double x, long double y ) { - return powl( x, y ); + return powl( x, y ); } Bu::Formatter::Formatter( Stream &rStream ) : - rStream( rStream ), - bTempFmt( false ), - uIndent( 0 ), - cIndent( '\t' ) + rStream( rStream ), + bTempFmt( false ), + uIndent( 0 ), + cIndent( '\t' ) { } @@ -69,491 +69,491 @@ Bu::Formatter::~Formatter() void Bu::Formatter::write( const Bu::String &sStr ) { - rStream.write( sStr ); + rStream.write( sStr ); } void Bu::Formatter::write( const void *sStr, int iLen ) { - rStream.write( sStr, iLen ); + rStream.write( sStr, iLen ); } void Bu::Formatter::writeAligned( const Bu::String &sStr ) { - int iLen = sStr.getSize(); - if( iLen > fLast.uMinWidth ) - { - write( sStr ); - } - else - { - int iRem = fLast.uMinWidth - iLen; - switch( fLast.uAlign ) - { - case Fmt::Right: - for( int k = 0; k < iRem; k++ ) - write( &fLast.cFillChar, 1 ); - write( sStr ); - break; - - case Fmt::Center: - { - int iHlf = iRem/2; - for( int k = 0; k < iHlf; k++ ) - write( &fLast.cFillChar, 1 ); - write( sStr ); - iHlf = iRem-iHlf;; - for( int k = 0; k < iHlf; k++ ) - write( &fLast.cFillChar, 1 ); - } - break; - - case Fmt::Left: - write( sStr ); - for( int k = 0; k < iRem; k++ ) - write( &fLast.cFillChar, 1 ); - break; - } - } - - usedFormat(); + int iLen = sStr.getSize(); + if( iLen > fLast.uMinWidth ) + { + write( sStr ); + } + else + { + int iRem = fLast.uMinWidth - iLen; + switch( fLast.uAlign ) + { + case Fmt::Right: + for( int k = 0; k < iRem; k++ ) + write( &fLast.cFillChar, 1 ); + write( sStr ); + break; + + case Fmt::Center: + { + int iHlf = iRem/2; + for( int k = 0; k < iHlf; k++ ) + write( &fLast.cFillChar, 1 ); + write( sStr ); + iHlf = iRem-iHlf;; + for( int k = 0; k < iHlf; k++ ) + write( &fLast.cFillChar, 1 ); + } + break; + + case Fmt::Left: + write( sStr ); + for( int k = 0; k < iRem; k++ ) + write( &fLast.cFillChar, 1 ); + break; + } + } + + usedFormat(); } void Bu::Formatter::writeAligned( const char *sStr, int iLen ) { - if( iLen > fLast.uMinWidth ) - { - write( sStr, iLen ); - } - else - { - int iRem = fLast.uMinWidth - iLen; - switch( fLast.uAlign ) - { - case Fmt::Right: - for( int k = 0; k < iRem; k++ ) - write( &fLast.cFillChar, 1 ); - write( sStr, iLen ); - break; - - case Fmt::Center: - { - int iHlf = iRem/2; - for( int k = 0; k < iHlf; k++ ) - write( &fLast.cFillChar, 1 ); - write( sStr, iLen ); - iHlf = iRem-iHlf;; - for( int k = 0; k < iHlf; k++ ) - write( &fLast.cFillChar, 1 ); - } - break; - - case Fmt::Left: - write( sStr, iLen ); - for( int k = 0; k < iRem; k++ ) - write( &fLast.cFillChar, 1 ); - break; - } - } - - usedFormat(); + if( iLen > fLast.uMinWidth ) + { + write( sStr, iLen ); + } + else + { + int iRem = fLast.uMinWidth - iLen; + switch( fLast.uAlign ) + { + case Fmt::Right: + for( int k = 0; k < iRem; k++ ) + write( &fLast.cFillChar, 1 ); + write( sStr, iLen ); + break; + + case Fmt::Center: + { + int iHlf = iRem/2; + for( int k = 0; k < iHlf; k++ ) + write( &fLast.cFillChar, 1 ); + write( sStr, iLen ); + iHlf = iRem-iHlf;; + for( int k = 0; k < iHlf; k++ ) + write( &fLast.cFillChar, 1 ); + } + break; + + case Fmt::Left: + write( sStr, iLen ); + for( int k = 0; k < iRem; k++ ) + write( &fLast.cFillChar, 1 ); + break; + } + } + + usedFormat(); } void Bu::Formatter::read( void *sStr, int iLen ) { - rStream.read( sStr, iLen ); + rStream.read( sStr, iLen ); } Bu::String Bu::Formatter::readToken() { - Bu::String sRet; - if( fLast.bTokenize ) - { - for(;;) - { - char buf; - int iRead = rStream.read( &buf, 1 ); - if( iRead == 0 ) - return sRet; - if( buf == ' ' || buf == '\t' || buf == '\n' || buf == '\r' ) - continue; - else - { - sRet += buf; - break; - } - } - for(;;) - { - char buf; - int iRead = rStream.read( &buf, 1 ); - if( iRead == 0 ) - return sRet; - if( buf == ' ' || buf == '\t' || buf == '\n' || buf == '\r' ) - return sRet; - else - sRet += buf; - } - } - else - { - for(;;) - { - char buf; - int iRead = rStream.read( &buf, 1 ); - if( iRead == 0 ) - return sRet; - else - sRet += buf; - } - } + Bu::String sRet; + if( fLast.bTokenize ) + { + for(;;) + { + char buf; + int iRead = rStream.read( &buf, 1 ); + if( iRead == 0 ) + return sRet; + if( buf == ' ' || buf == '\t' || buf == '\n' || buf == '\r' ) + continue; + else + { + sRet += buf; + break; + } + } + for(;;) + { + char buf; + int iRead = rStream.read( &buf, 1 ); + if( iRead == 0 ) + return sRet; + if( buf == ' ' || buf == '\t' || buf == '\n' || buf == '\r' ) + return sRet; + else + sRet += buf; + } + } + else + { + for(;;) + { + char buf; + int iRead = rStream.read( &buf, 1 ); + if( iRead == 0 ) + return sRet; + else + sRet += buf; + } + } } void Bu::Formatter::incIndent() { - if( uIndent < 0xFFU ) - uIndent++; + if( uIndent < 0xFFU ) + uIndent++; } void Bu::Formatter::decIndent() { - if( uIndent > 0 ) - uIndent--; + if( uIndent > 0 ) + uIndent--; } void Bu::Formatter::setIndent( uint8_t uLevel ) { - uIndent = uLevel; + uIndent = uLevel; } void Bu::Formatter::clearIndent() { - uIndent = 0; + uIndent = 0; } void Bu::Formatter::setIndentChar( char cIndent ) { - this->cIndent = cIndent; + this->cIndent = cIndent; } void Bu::Formatter::doFlush() { - rStream.flush(); + rStream.flush(); } Bu::Fmt &Bu::Fmt::width( unsigned int uWidth ) { - this->uMinWidth = uWidth; - return *this; + this->uMinWidth = uWidth; + return *this; } Bu::Fmt &Bu::Fmt::fill( char cFill ) { - this->cFillChar = (unsigned char)cFill; - return *this; + this->cFillChar = (unsigned char)cFill; + return *this; } Bu::Fmt &Bu::Fmt::radix( unsigned int uRadix ) { - this->uRadix = uRadix; - return *this; + this->uRadix = uRadix; + return *this; } Bu::Fmt &Bu::Fmt::align( Alignment eAlign ) { - this->uAlign = eAlign; - return *this; + this->uAlign = eAlign; + return *this; } Bu::Fmt &Bu::Fmt::left() { - this->uAlign = Fmt::Left; - return *this; + this->uAlign = Fmt::Left; + return *this; } Bu::Fmt &Bu::Fmt::center() { - this->uAlign = Fmt::Center; - return *this; + this->uAlign = Fmt::Center; + return *this; } Bu::Fmt &Bu::Fmt::right() { - this->uAlign = Fmt::Right; - return *this; + this->uAlign = Fmt::Right; + return *this; } Bu::Fmt &Bu::Fmt::plus( bool bPlus ) { - this->bPlus = bPlus; - return *this; + this->bPlus = bPlus; + return *this; } Bu::Fmt &Bu::Fmt::caps( bool bCaps ) { - this->bCaps = bCaps; - return *this; + this->bCaps = bCaps; + return *this; } Bu::Fmt &Bu::Fmt::upper() { - this->bCaps = true; - return *this; + this->bCaps = true; + return *this; } Bu::Fmt &Bu::Fmt::lower() { - this->bCaps = false; - return *this; + this->bCaps = false; + return *this; } Bu::Fmt &Bu::Fmt::tokenize( bool bTokenize ) { - this->bTokenize = bTokenize; - return *this; + this->bTokenize = bTokenize; + return *this; } Bu::Formatter &Bu::operator<<( Bu::Formatter &f, const Bu::Fmt &fmt ) { - f.setTempFormat( fmt ); - return f; + f.setTempFormat( fmt ); + return f; } Bu::Formatter &Bu::operator<<( Bu::Formatter &f, Bu::Formatter::Special s ) { - switch( s ) - { - case Formatter::nl: - { + switch( s ) + { + case Formatter::nl: + { #ifdef WIN32 - f.write("\r\n", 2 ); + f.write("\r\n", 2 ); #else - f.write("\n", 1 ); + f.write("\n", 1 ); #endif - char ci = f.getIndentChar(); - for( int j = 0; j < f.getIndent(); j++ ) - f.write( &ci, 1 ); - f.doFlush(); - } - break; + char ci = f.getIndentChar(); + for( int j = 0; j < f.getIndent(); j++ ) + f.write( &ci, 1 ); + f.doFlush(); + } + break; - case Formatter::flush: - f.doFlush(); - break; - } - return f; + case Formatter::flush: + f.doFlush(); + break; + } + return f; } Bu::Formatter &Bu::operator<<( Bu::Formatter &f, const char *sStr ) { - f.writeAligned( sStr, strlen( sStr ) ); - return f; + f.writeAligned( sStr, strlen( sStr ) ); + return f; } Bu::Formatter &Bu::operator<<( Bu::Formatter &f, char *sStr ) { - f.writeAligned( sStr, strlen( sStr ) ); - return f; + f.writeAligned( sStr, strlen( sStr ) ); + return f; } Bu::Formatter &Bu::operator<<( Bu::Formatter &f, const Bu::String &sStr ) { - f.writeAligned( sStr ); - return f; + f.writeAligned( sStr ); + return f; } Bu::Formatter &Bu::operator<<( Bu::Formatter &f, signed char c ) { - f.ifmt( c ); - //f.write( (char *)&c, 1 ); - return f; + f.ifmt( c ); + //f.write( (char *)&c, 1 ); + return f; } Bu::Formatter &Bu::operator<<( Bu::Formatter &f, char c ) { - f.write( (char *)&c, 1 ); - return f; + f.write( (char *)&c, 1 ); + return f; } Bu::Formatter &Bu::operator<<( Bu::Formatter &f, unsigned char c ) { - f.ufmt( c ); - //f.write( (char *)&c, 1 ); - return f; + f.ufmt( c ); + //f.write( (char *)&c, 1 ); + return f; } Bu::Formatter &Bu::operator<<( Bu::Formatter &f, signed short i ) { - f.ifmt( i ); - return f; + f.ifmt( i ); + return f; } Bu::Formatter &Bu::operator<<( Bu::Formatter &f, unsigned short i ) { - f.ufmt( i ); - return f; + f.ufmt( i ); + return f; } Bu::Formatter &Bu::operator<<( Bu::Formatter &f, signed int i ) { - f.ifmt( i ); - return f; + f.ifmt( i ); + return f; } Bu::Formatter &Bu::operator<<( Bu::Formatter &f, unsigned int i ) { - f.ufmt( i ); - return f; + f.ufmt( i ); + return f; } Bu::Formatter &Bu::operator<<( Bu::Formatter &f, signed long i ) { - f.ifmt( i ); - return f; + f.ifmt( i ); + return f; } Bu::Formatter &Bu::operator<<( Bu::Formatter &f, unsigned long i ) { - f.ufmt( i ); - return f; + f.ufmt( i ); + return f; } Bu::Formatter &Bu::operator<<( Bu::Formatter &f, signed long long i ) { - f.ifmt( i ); - return f; + f.ifmt( i ); + return f; } Bu::Formatter &Bu::operator<<( Bu::Formatter &f, unsigned long long i ) { - f.ufmt( i ); - return f; + f.ufmt( i ); + return f; } Bu::Formatter &Bu::operator<<( Bu::Formatter &f, float flt ) { - f.ffmt( flt ); - return f; + f.ffmt( flt ); + return f; } Bu::Formatter &Bu::operator<<( Bu::Formatter &f, double flt ) { - f.ffmt( flt ); - return f; + f.ffmt( flt ); + return f; } Bu::Formatter &Bu::operator<<( Bu::Formatter &f, long double flt ) { - f.ffmt( flt ); - return f; + f.ffmt( flt ); + return f; } Bu::Formatter &Bu::operator<<( Bu::Formatter &f, bool b ) { - f.writeAligned( b?("true"):("false") ); - return f; + f.writeAligned( b?("true"):("false") ); + return f; } Bu::Formatter &Bu::operator>>( Bu::Formatter &f, Bu::String &sStr ) { - sStr = f.readToken(); - return f; + sStr = f.readToken(); + return f; } Bu::Formatter &Bu::operator>>( Bu::Formatter &f, signed char &c ) { - f.read( &c, 1 ); - return f; + f.read( &c, 1 ); + return f; } Bu::Formatter &Bu::operator>>( Bu::Formatter &f, char &c ) { - f.read( &c, 1 ); - return f; + f.read( &c, 1 ); + return f; } Bu::Formatter &Bu::operator>>( Bu::Formatter &f, unsigned char &c ) { - f.read( &c, 1 ); - return f; + f.read( &c, 1 ); + return f; } Bu::Formatter &Bu::operator>>( Bu::Formatter &f, signed short &i ) { - f.iparse( i, f.readToken() ); - return f; + f.iparse( i, f.readToken() ); + return f; } Bu::Formatter &Bu::operator>>( Bu::Formatter &f, unsigned short &i ) { - f.uparse( i, f.readToken() ); - return f; + f.uparse( i, f.readToken() ); + return f; } Bu::Formatter &Bu::operator>>( Bu::Formatter &f, signed int &i ) { - f.iparse( i, f.readToken() ); - return f; + f.iparse( i, f.readToken() ); + return f; } Bu::Formatter &Bu::operator>>( Bu::Formatter &f, unsigned int &i ) { - f.uparse( i, f.readToken() ); - return f; + f.uparse( i, f.readToken() ); + return f; } Bu::Formatter &Bu::operator>>( Bu::Formatter &f, signed long &i ) { - f.iparse( i, f.readToken() ); - return f; + f.iparse( i, f.readToken() ); + return f; } Bu::Formatter &Bu::operator>>( Bu::Formatter &f, unsigned long &i ) { - f.uparse( i, f.readToken() ); - return f; + f.uparse( i, f.readToken() ); + return f; } Bu::Formatter &Bu::operator>>( Bu::Formatter &f, signed long long &i ) { - f.iparse( i, f.readToken() ); - return f; + f.iparse( i, f.readToken() ); + return f; } Bu::Formatter &Bu::operator>>( Bu::Formatter &f, unsigned long long &i ) { - f.uparse( i, f.readToken() ); - return f; + f.uparse( i, f.readToken() ); + return f; } Bu::Formatter &Bu::operator>>( Bu::Formatter &f, float &flt ) { - f.fparse( flt, f.readToken() ); - return f; + f.fparse( flt, f.readToken() ); + return f; } Bu::Formatter &Bu::operator>>( Bu::Formatter &f, double &flt ) { - f.fparse( flt, f.readToken() ); - return f; + f.fparse( flt, f.readToken() ); + return f; } Bu::Formatter &Bu::operator>>( Bu::Formatter &f, long double &flt ) { - f.fparse( flt, f.readToken() ); - return f; + f.fparse( flt, f.readToken() ); + return f; } Bu::Formatter &Bu::operator>>( Bu::Formatter &f, bool &b ) { - Bu::String sStr = f.readToken(); - if( !sStr.isSet() ) - return f; - char c = *sStr.begin(); - if( c == 'y' || c == 'Y' || c == 't' || c == 'T' ) - b = true; - else if( c == 'n' || c == 'N' || c == 'f' || c == 'F' ) - b = false; + Bu::String sStr = f.readToken(); + if( !sStr.isSet() ) + return f; + char c = *sStr.begin(); + if( c == 'y' || c == 'Y' || c == 't' || c == 'T' ) + b = true; + else if( c == 'n' || c == 'N' || c == 'f' || c == 'F' ) + b = false; - return f; + return f; } diff --git a/src/stable/formatter.h b/src/stable/formatter.h index d92a53b..94794b5 100644 --- a/src/stable/formatter.h +++ b/src/stable/formatter.h @@ -15,292 +15,292 @@ namespace Bu { - class Stream; - - template t tlog( t x ); - template<> float tlog( float x ); - template<> double tlog( double x ); - template<> long double tlog( long double x ); - - template t tfloor( t x ); - template<> float tfloor( float x ); - template<> double tfloor( double x ); - template<> long double tfloor( long double x ); - - template t tpow( t x, t y ); - template<> float tpow( float x, float y ); - template<> double tpow( double x, double y ); - template<> long double tpow( long double x, long double y ); - - class Formatter - { - public: - Formatter( Stream &rStream ); - virtual ~Formatter(); - - void write( const Bu::String &sStr ); - void write( const void *sStr, int iLen ); - void writeAligned( const Bu::String &sStr ); - void writeAligned( const char *sStr, int iLen ); - - void read( void *sStr, int iLen ); - Bu::String readToken(); - - void incIndent(); - void decIndent(); - void setIndent( uint8_t uLevel ); - void clearIndent(); - uint8_t getIndent() const { return uIndent; } - void setIndentChar( char cIndent ); - char getIndentChar() const { return cIndent; } - - void setFormat( const Fmt &f ) - { - fLast = f; - bTempFmt = false; - } - - void setTempFormat( const Fmt &f ) - { - fLast = f; - bTempFmt = true; - } - - void usedFormat() - { - if( bTempFmt ) - fLast = Fmt(); - } - - template - void ifmt( type i ) - { - // This code is taken from Nango, hopefully we can make it better. - bool bNeg = i<0; - char cBase = fLast.bCaps?'A':'a'; - char buf[sizeof(type)*8+1]; - if( bNeg ) i = -i; - if( fLast.uRadix < 2 || fLast.uRadix > 36 ) - { - usedFormat(); - return; - } - - for( int j = sizeof(type)*8; j >= 0; j-- ) - { - int c = i%fLast.uRadix; - i /= fLast.uRadix; - buf[j] = (char)((c<10)?('0'+c):(cBase+c-10)); - if( i == 0 ) - { - if( bNeg ) buf[--j] = '-'; - else if( fLast.bPlus ) buf[--j] = '+'; - writeAligned( buf+j, sizeof(type)*8-j+1 ); - - return; - } - } - usedFormat(); - } - - template - void ufmt( type i ) - { - // This code is taken from Nango, hopefully we can make it better. - char buf[sizeof(type)*8+1]; - char cBase = fLast.bCaps?'A':'a'; - if( fLast.uRadix < 2 || fLast.uRadix > 36 ) - { - usedFormat(); - return; - } - - for( int j = sizeof(type)*8; j >= 0; j-- ) - { - int c = i%fLast.uRadix; - i /= fLast.uRadix; - buf[j] = (char)((c<10)?('0'+c):(cBase+c-10)); - if( i == 0 ) - { - if( fLast.bPlus ) buf[--j] = '+'; - writeAligned( buf+j, sizeof(type)*8-j+1 ); - - return; - } - } - usedFormat(); - } - - template - void ffmt( type f ) - { - Bu::String fTmp; - char cBase = fLast.bCaps?'A':'a'; - if( fLast.uRadix < 2 || fLast.uRadix > 36 ) - { - usedFormat(); - return; - } - - if( signbit(f) ) - { - f = -f; - fTmp += "-"; - } - int iScale = tfloor(tlog( f ) / tlog( (type)fLast.uRadix )); - f /= tpow( (type)fLast.uRadix, (type)iScale ); - - if( iScale < 0 ) - { - fTmp += "0."; - for( int j = 1; j < -iScale; j++ ) - fTmp += '0'; - } - int c = f; - fTmp += (char)((c<10)?('0'+c):(cBase+c-10)); - f -= (int)f; - int j; - for( j = 0; j < 8 && f; j++ ) - { - if( iScale - j == 0 ) - fTmp += '.'; - f = f*fLast.uRadix; - int c = f; - fTmp += (char)((c<10)?('0'+c):(cBase+c-10)); - f -= (int)f; - } - if( iScale >= j ) - { - for( int k = j; k < iScale; k++ ) - fTmp += '0'; - fTmp += ".0"; - } - - writeAligned( fTmp ); - usedFormat(); - } - - template - void iparse( type &i, const Bu::String &sBuf ) - { - if( !sBuf.isSet() ) - return; - if( sBuf[0] != '+' && sBuf[0] != '-' && - (sBuf[0] < '0' && sBuf[0] > '9') ) - return; - int j = 1; - int iMax = sBuf.getSize(); - for(; j < iMax && (sBuf[j] >= '0' && sBuf[j] <= '9'); j++ ) { } - i = 0; - type iPos = 1; - for(j--; j >= 0; j-- ) - { - if( sBuf[j] == '+' || sBuf[j] == '-' ) - continue; - i += (sBuf[j]-'0')*iPos; - iPos *= fLast.uRadix; - } - if( sBuf[0] == '-' ) - i = -i; - - usedFormat(); - } - - template - void uparse( type &i, const Bu::String &sBuf ) - { - if( !sBuf.isSet() ) - return; - if( sBuf[0] != '+' && - (sBuf[0] < '0' && sBuf[0] > '9') ) - return; - int j = 1; - int iMax = sBuf.getSize(); - for(; j < iMax && (sBuf[j] >= '0' && sBuf[j] <= '9'); j++ ) { } - i = 0; - type iPos = 1; - for(j--; j >= 0; j-- ) - { - if( sBuf[j] == '+' ) - continue; - i += (sBuf[j]-'0')*iPos; - iPos *= fLast.uRadix; - } - - usedFormat(); - } - - template - void fparse( type &f, const Bu::String &sBuf ) - { - double fIn; - sscanf( sBuf.getStr(), "%lf", &fIn ); - f = fIn; - usedFormat(); - } - - enum Special - { - nl, - flush - }; - - void doFlush(); - - Stream &getStream() { return rStream; } - operator Stream&() { return rStream; } - - private: - Stream &rStream; - Fmt fLast; - bool bTempFmt; - uint8_t uIndent; - char cIndent; - }; - - Formatter &operator<<( Formatter &f, const Fmt &fmt ); - Formatter &operator<<( Formatter &f, Formatter::Special s ); - Formatter &operator<<( Formatter &f, const char *sStr ); - Formatter &operator<<( Formatter &f, char *sStr ); - Formatter &operator<<( Formatter &f, const Bu::String &sStr ); - Formatter &operator<<( Formatter &f, signed char c ); - Formatter &operator<<( Formatter &f, char c ); - Formatter &operator<<( Formatter &f, unsigned char c ); - Formatter &operator<<( Formatter &f, signed short i ); - Formatter &operator<<( Formatter &f, unsigned short i ); - Formatter &operator<<( Formatter &f, signed int i ); - Formatter &operator<<( Formatter &f, unsigned int i ); - Formatter &operator<<( Formatter &f, signed long i ); - Formatter &operator<<( Formatter &f, unsigned long i ); - Formatter &operator<<( Formatter &f, signed long long i ); - Formatter &operator<<( Formatter &f, unsigned long long i ); - Formatter &operator<<( Formatter &f, float flt ); - Formatter &operator<<( Formatter &f, double flt ); - Formatter &operator<<( Formatter &f, long double flt ); - Formatter &operator<<( Formatter &f, bool b ); - - Formatter &operator>>( Formatter &f, Bu::String &sStr ); - Formatter &operator>>( Formatter &f, signed char &c ); - Formatter &operator>>( Formatter &f, char &c ); - Formatter &operator>>( Formatter &f, unsigned char &c ); - Formatter &operator>>( Formatter &f, signed short &i ); - Formatter &operator>>( Formatter &f, unsigned short &i ); - Formatter &operator>>( Formatter &f, signed int &i ); - Formatter &operator>>( Formatter &f, unsigned int &i ); - Formatter &operator>>( Formatter &f, signed long &i ); - Formatter &operator>>( Formatter &f, unsigned long &i ); - Formatter &operator>>( Formatter &f, signed long long &i ); - Formatter &operator>>( Formatter &f, unsigned long long &i ); - Formatter &operator>>( Formatter &f, float &flt ); - Formatter &operator>>( Formatter &f, double &flt ); - Formatter &operator>>( Formatter &f, long double &flt ); - Formatter &operator>>( Formatter &f, bool &b ); - - template - Formatter &operator<<( Formatter &f, const type *p ) - { - return f << "0x" << Fmt::hex(sizeof(ptrdiff_t)*2) << (ptrdiff_t)(p); - } + class Stream; + + template t tlog( t x ); + template<> float tlog( float x ); + template<> double tlog( double x ); + template<> long double tlog( long double x ); + + template t tfloor( t x ); + template<> float tfloor( float x ); + template<> double tfloor( double x ); + template<> long double tfloor( long double x ); + + template t tpow( t x, t y ); + template<> float tpow( float x, float y ); + template<> double tpow( double x, double y ); + template<> long double tpow( long double x, long double y ); + + class Formatter + { + public: + Formatter( Stream &rStream ); + virtual ~Formatter(); + + void write( const Bu::String &sStr ); + void write( const void *sStr, int iLen ); + void writeAligned( const Bu::String &sStr ); + void writeAligned( const char *sStr, int iLen ); + + void read( void *sStr, int iLen ); + Bu::String readToken(); + + void incIndent(); + void decIndent(); + void setIndent( uint8_t uLevel ); + void clearIndent(); + uint8_t getIndent() const { return uIndent; } + void setIndentChar( char cIndent ); + char getIndentChar() const { return cIndent; } + + void setFormat( const Fmt &f ) + { + fLast = f; + bTempFmt = false; + } + + void setTempFormat( const Fmt &f ) + { + fLast = f; + bTempFmt = true; + } + + void usedFormat() + { + if( bTempFmt ) + fLast = Fmt(); + } + + template + void ifmt( type i ) + { + // This code is taken from Nango, hopefully we can make it better. + bool bNeg = i<0; + char cBase = fLast.bCaps?'A':'a'; + char buf[sizeof(type)*8+1]; + if( bNeg ) i = -i; + if( fLast.uRadix < 2 || fLast.uRadix > 36 ) + { + usedFormat(); + return; + } + + for( int j = sizeof(type)*8; j >= 0; j-- ) + { + int c = i%fLast.uRadix; + i /= fLast.uRadix; + buf[j] = (char)((c<10)?('0'+c):(cBase+c-10)); + if( i == 0 ) + { + if( bNeg ) buf[--j] = '-'; + else if( fLast.bPlus ) buf[--j] = '+'; + writeAligned( buf+j, sizeof(type)*8-j+1 ); + + return; + } + } + usedFormat(); + } + + template + void ufmt( type i ) + { + // This code is taken from Nango, hopefully we can make it better. + char buf[sizeof(type)*8+1]; + char cBase = fLast.bCaps?'A':'a'; + if( fLast.uRadix < 2 || fLast.uRadix > 36 ) + { + usedFormat(); + return; + } + + for( int j = sizeof(type)*8; j >= 0; j-- ) + { + int c = i%fLast.uRadix; + i /= fLast.uRadix; + buf[j] = (char)((c<10)?('0'+c):(cBase+c-10)); + if( i == 0 ) + { + if( fLast.bPlus ) buf[--j] = '+'; + writeAligned( buf+j, sizeof(type)*8-j+1 ); + + return; + } + } + usedFormat(); + } + + template + void ffmt( type f ) + { + Bu::String fTmp; + char cBase = fLast.bCaps?'A':'a'; + if( fLast.uRadix < 2 || fLast.uRadix > 36 ) + { + usedFormat(); + return; + } + + if( signbit(f) ) + { + f = -f; + fTmp += "-"; + } + int iScale = tfloor(tlog( f ) / tlog( (type)fLast.uRadix )); + f /= tpow( (type)fLast.uRadix, (type)iScale ); + + if( iScale < 0 ) + { + fTmp += "0."; + for( int j = 1; j < -iScale; j++ ) + fTmp += '0'; + } + int c = f; + fTmp += (char)((c<10)?('0'+c):(cBase+c-10)); + f -= (int)f; + int j; + for( j = 0; j < 8 && f; j++ ) + { + if( iScale - j == 0 ) + fTmp += '.'; + f = f*fLast.uRadix; + int c = f; + fTmp += (char)((c<10)?('0'+c):(cBase+c-10)); + f -= (int)f; + } + if( iScale >= j ) + { + for( int k = j; k < iScale; k++ ) + fTmp += '0'; + fTmp += ".0"; + } + + writeAligned( fTmp ); + usedFormat(); + } + + template + void iparse( type &i, const Bu::String &sBuf ) + { + if( !sBuf.isSet() ) + return; + if( sBuf[0] != '+' && sBuf[0] != '-' && + (sBuf[0] < '0' && sBuf[0] > '9') ) + return; + int j = 1; + int iMax = sBuf.getSize(); + for(; j < iMax && (sBuf[j] >= '0' && sBuf[j] <= '9'); j++ ) { } + i = 0; + type iPos = 1; + for(j--; j >= 0; j-- ) + { + if( sBuf[j] == '+' || sBuf[j] == '-' ) + continue; + i += (sBuf[j]-'0')*iPos; + iPos *= fLast.uRadix; + } + if( sBuf[0] == '-' ) + i = -i; + + usedFormat(); + } + + template + void uparse( type &i, const Bu::String &sBuf ) + { + if( !sBuf.isSet() ) + return; + if( sBuf[0] != '+' && + (sBuf[0] < '0' && sBuf[0] > '9') ) + return; + int j = 1; + int iMax = sBuf.getSize(); + for(; j < iMax && (sBuf[j] >= '0' && sBuf[j] <= '9'); j++ ) { } + i = 0; + type iPos = 1; + for(j--; j >= 0; j-- ) + { + if( sBuf[j] == '+' ) + continue; + i += (sBuf[j]-'0')*iPos; + iPos *= fLast.uRadix; + } + + usedFormat(); + } + + template + void fparse( type &f, const Bu::String &sBuf ) + { + double fIn; + sscanf( sBuf.getStr(), "%lf", &fIn ); + f = fIn; + usedFormat(); + } + + enum Special + { + nl, + flush + }; + + void doFlush(); + + Stream &getStream() { return rStream; } + operator Stream&() { return rStream; } + + private: + Stream &rStream; + Fmt fLast; + bool bTempFmt; + uint8_t uIndent; + char cIndent; + }; + + Formatter &operator<<( Formatter &f, const Fmt &fmt ); + Formatter &operator<<( Formatter &f, Formatter::Special s ); + Formatter &operator<<( Formatter &f, const char *sStr ); + Formatter &operator<<( Formatter &f, char *sStr ); + Formatter &operator<<( Formatter &f, const Bu::String &sStr ); + Formatter &operator<<( Formatter &f, signed char c ); + Formatter &operator<<( Formatter &f, char c ); + Formatter &operator<<( Formatter &f, unsigned char c ); + Formatter &operator<<( Formatter &f, signed short i ); + Formatter &operator<<( Formatter &f, unsigned short i ); + Formatter &operator<<( Formatter &f, signed int i ); + Formatter &operator<<( Formatter &f, unsigned int i ); + Formatter &operator<<( Formatter &f, signed long i ); + Formatter &operator<<( Formatter &f, unsigned long i ); + Formatter &operator<<( Formatter &f, signed long long i ); + Formatter &operator<<( Formatter &f, unsigned long long i ); + Formatter &operator<<( Formatter &f, float flt ); + Formatter &operator<<( Formatter &f, double flt ); + Formatter &operator<<( Formatter &f, long double flt ); + Formatter &operator<<( Formatter &f, bool b ); + + Formatter &operator>>( Formatter &f, Bu::String &sStr ); + Formatter &operator>>( Formatter &f, signed char &c ); + Formatter &operator>>( Formatter &f, char &c ); + Formatter &operator>>( Formatter &f, unsigned char &c ); + Formatter &operator>>( Formatter &f, signed short &i ); + Formatter &operator>>( Formatter &f, unsigned short &i ); + Formatter &operator>>( Formatter &f, signed int &i ); + Formatter &operator>>( Formatter &f, unsigned int &i ); + Formatter &operator>>( Formatter &f, signed long &i ); + Formatter &operator>>( Formatter &f, unsigned long &i ); + Formatter &operator>>( Formatter &f, signed long long &i ); + Formatter &operator>>( Formatter &f, unsigned long long &i ); + Formatter &operator>>( Formatter &f, float &flt ); + Formatter &operator>>( Formatter &f, double &flt ); + Formatter &operator>>( Formatter &f, long double &flt ); + Formatter &operator>>( Formatter &f, bool &b ); + + template + Formatter &operator<<( Formatter &f, const type *p ) + { + return f << "0x" << Fmt::hex(sizeof(ptrdiff_t)*2) << (ptrdiff_t)(p); + } }; #endif diff --git a/src/stable/formula.cpp b/src/stable/formula.cpp index 6bc2c58..c5ba1ae 100644 --- a/src/stable/formula.cpp +++ b/src/stable/formula.cpp @@ -9,6 +9,6 @@ namespace Bu { - subExceptionDef( FormulaException ); + subExceptionDef( FormulaException ); } diff --git a/src/stable/formula.h b/src/stable/formula.h index 36a0398..b12afd6 100644 --- a/src/stable/formula.h +++ b/src/stable/formula.h @@ -21,410 +21,410 @@ namespace Bu { - subExceptionDecl( FormulaException ); - /** - * Implements a very simple formula parser that allows use of variables and - * custom functions. This is based on a simple calculator-type parser that - * executes as it processes, accounting for operator precedence and - * grouping. - * - * prec = precision, a type to use for all math (except binary ops) - * bin = binary type, a type to hard cast all data to for binary ops - */ - template - class Formula - { - public: - class Func - { - public: - virtual prec operator()( prec )=0; - }; - - typedef Hash varHash; - typedef Hash funcHash; - - Formula() - { - } - - virtual ~Formula() - { - for( typename funcHash::iterator i = hFunc.begin(); - i != hFunc.end(); i++ ) - { - delete (*i); - } - } - - prec run( const Bu::String &sFormulaSrc ) - { - if( sFormulaSrc.isEmpty() ) - throw FormulaException("Empty formula, nothing to do."); - try - { - const char *sFormula = sFormulaSrc.getStr(); - for(;;) - { - uint8_t tNum = nextToken( &sFormula ); - if( tNum == symSubtract ) - { - sOper.push( symNegate ); - continue; - } - else if( tNum == symNot ) - { - sOper.push( symNot ); - continue; - } - else if( tNum == symOpenParen ) - { - sOper.push( tNum ); - continue; - } - else if( tNum == symFunction ) - { - sOper.push( symFunction ); - continue; - } - else if( tNum == symEOS ) - { - throw Bu::FormulaException( - "Cannot end with an operator."); - } - - oppart: uint8_t tOpr = nextToken( &sFormula ); - if( tOpr == symEOS ) - { - reduce(); - prec ret = sValue.top(); - sValue.clear(); - sFunc.clear(); - sOper.clear(); - return ret; - } - if( !sOper.isEmpty() && getPrec( sOper.top() ) > - getPrec( tOpr ) ) - { - reduce(); - } - if( tOpr != symCloseParen ) - { - sOper.push( tOpr ); - } - else - { - reduce( true ); - goto oppart; - } - } - } - catch( ... ) - { - sValue.clear(); - sFunc.clear(); - sOper.clear(); - throw; - } - } - - varHash hVars; - funcHash hFunc; - - private: - enum - { - symEOS, - symAdd, - symSubtract, - symMultiply, - symDivide, - symOpenParen, - symCloseParen, - symNumber, - symVariable, - symFunction, - symExponent, - symNegate, - symModulus, - - symAnd, - symOr, - symXor, - symNot - }; - - typedef uint8_t symType; - - Bu::Stack sOper; - Bu::Stack sValue; - Bu::Stack sFunc; - - private: - symType getPrec( symType nOper ) - { - switch( nOper ) - { - case symNumber: - case symVariable: - case symOpenParen: - case symCloseParen: - return 0; - - case symAdd: - case symSubtract: - return 1; - - case symMultiply: - case symDivide: - case symModulus: - return 2; - - case symAnd: - case symOr: - case symXor: - return 2; - - case symExponent: - case symNot: - case symNegate: - case symFunction: - return 3; - - default: - return 0; - } - } - - symType nextToken( const char **sBuf ) - { - for(;;) - { - char cbuf = **sBuf; - ++(*sBuf); - switch( cbuf ) - { - case '+': - return symAdd; - - case '-': - return symSubtract; - - case '*': - return symMultiply; - - case '/': - return symDivide; - - case '^': - return symExponent; - - case '%': - return symModulus; - - case '(': - return symOpenParen; - - case ')': - return symCloseParen; - - case '|': - return symOr; - - case '&': - return symAnd; - - case '#': - return symXor; - - case '~': - return symNot; - - case ' ': - case '\t': - case '\n': - case '\r': - break; - - case '\0': - return symEOS; - - default: - if( cbuf == '.' || (cbuf >= '0' && cbuf <= '9') ) - { - char num[50]={cbuf}; - int nPos = 1; - bool bDot = false; - - for(;;) - { - cbuf = **sBuf; - if( cbuf == '.' ) - { - if( bDot == false ) - bDot = true; - else - throw FormulaException( - "Numbers cannot have more than one " - ". in them." - ); - } - if( cbuf == '.' || - (cbuf >= '0' && cbuf <= '9') ) - { - num[nPos++] = cbuf; - } - else - { - num[nPos] = '\0'; - sValue.push( - static_cast( - strtod( num, NULL ) - ) - ); - return symNumber; - } - ++(*sBuf); - } - } - else if( (cbuf >= 'a' && cbuf <= 'z') || - (cbuf >= 'A' && cbuf <= 'Z') || - (cbuf == '_') ) - { - char tok[50]={cbuf}; - int nPos = 1; - - for(;;) - { - cbuf = **sBuf; - if( (cbuf >= 'a' && cbuf <= 'z') || - (cbuf >= 'A' && cbuf <= 'Z') || - (cbuf >= '0' && cbuf <= '9') || - cbuf == '_' || cbuf == '.' || cbuf == ':' ) - { - tok[nPos++] = cbuf; - } - else - { - tok[nPos] = '\0'; - if( hVars.has( tok ) ) - { - sValue.push( hVars[tok] ); - return symNumber; - } - else if( hFunc.has( tok ) ) - { - sFunc.push( tok ); - return symFunction; - } - else - { - throw FormulaException( - "No variable or function named " - "\"%s\" exists.", - tok - ); - } - } - ++(*sBuf); - } - } - break; - } - } - } - - void reduce( bool bCloseParen = false ) - { - while( !sOper.isEmpty() ) - { - uint8_t nOpr = sOper.top(); - if( nOpr == symOpenParen ) - { - if( bCloseParen == true ) - sOper.pop(); - return; - } - sOper.pop(); - - prec dTop = sValue.top(); - sValue.pop(); - - switch( nOpr ) - { - case symAdd: - sValue.top() += dTop; - break; - - case symSubtract: - sValue.top() -= dTop; - break; - - case symMultiply: - sValue.top() *= dTop; - break; - - case symDivide: - sValue.top() /= dTop; - break; - - case symExponent: - sValue.top() = static_cast( - pow( sValue.top(), dTop ) - ); - break; - - case symModulus: - sValue.top() = static_cast( - fmod( sValue.top(), dTop ) - ); - break; - - case symOr: - sValue.top() = static_cast( - static_cast(sValue.top()) | - static_cast(dTop) - ); - break; - - case symAnd: - sValue.top() = static_cast( - static_cast(sValue.top()) & - static_cast(dTop) - ); - break; - - case symXor: - sValue.top() = static_cast( - static_cast(sValue.top()) ^ - static_cast(dTop) - ); - break; - - case symFunction: - sValue.push( (*hFunc.get( sFunc.pop() ))( dTop ) ); - break; - - case symNegate: - sValue.push( -dTop ); - break; - - case symNot: - sValue.push( static_cast( - ~static_cast(dTop) - ) ); - break; - } - } - - if( bCloseParen == true ) - { - throw FormulaException( - "Close-paren found without matching open-paren." - ); - } - } - }; + subExceptionDecl( FormulaException ); + /** + * Implements a very simple formula parser that allows use of variables and + * custom functions. This is based on a simple calculator-type parser that + * executes as it processes, accounting for operator precedence and + * grouping. + * + * prec = precision, a type to use for all math (except binary ops) + * bin = binary type, a type to hard cast all data to for binary ops + */ + template + class Formula + { + public: + class Func + { + public: + virtual prec operator()( prec )=0; + }; + + typedef Hash varHash; + typedef Hash funcHash; + + Formula() + { + } + + virtual ~Formula() + { + for( typename funcHash::iterator i = hFunc.begin(); + i != hFunc.end(); i++ ) + { + delete (*i); + } + } + + prec run( const Bu::String &sFormulaSrc ) + { + if( sFormulaSrc.isEmpty() ) + throw FormulaException("Empty formula, nothing to do."); + try + { + const char *sFormula = sFormulaSrc.getStr(); + for(;;) + { + uint8_t tNum = nextToken( &sFormula ); + if( tNum == symSubtract ) + { + sOper.push( symNegate ); + continue; + } + else if( tNum == symNot ) + { + sOper.push( symNot ); + continue; + } + else if( tNum == symOpenParen ) + { + sOper.push( tNum ); + continue; + } + else if( tNum == symFunction ) + { + sOper.push( symFunction ); + continue; + } + else if( tNum == symEOS ) + { + throw Bu::FormulaException( + "Cannot end with an operator."); + } + + oppart: uint8_t tOpr = nextToken( &sFormula ); + if( tOpr == symEOS ) + { + reduce(); + prec ret = sValue.top(); + sValue.clear(); + sFunc.clear(); + sOper.clear(); + return ret; + } + if( !sOper.isEmpty() && getPrec( sOper.top() ) > + getPrec( tOpr ) ) + { + reduce(); + } + if( tOpr != symCloseParen ) + { + sOper.push( tOpr ); + } + else + { + reduce( true ); + goto oppart; + } + } + } + catch( ... ) + { + sValue.clear(); + sFunc.clear(); + sOper.clear(); + throw; + } + } + + varHash hVars; + funcHash hFunc; + + private: + enum + { + symEOS, + symAdd, + symSubtract, + symMultiply, + symDivide, + symOpenParen, + symCloseParen, + symNumber, + symVariable, + symFunction, + symExponent, + symNegate, + symModulus, + + symAnd, + symOr, + symXor, + symNot + }; + + typedef uint8_t symType; + + Bu::Stack sOper; + Bu::Stack sValue; + Bu::Stack sFunc; + + private: + symType getPrec( symType nOper ) + { + switch( nOper ) + { + case symNumber: + case symVariable: + case symOpenParen: + case symCloseParen: + return 0; + + case symAdd: + case symSubtract: + return 1; + + case symMultiply: + case symDivide: + case symModulus: + return 2; + + case symAnd: + case symOr: + case symXor: + return 2; + + case symExponent: + case symNot: + case symNegate: + case symFunction: + return 3; + + default: + return 0; + } + } + + symType nextToken( const char **sBuf ) + { + for(;;) + { + char cbuf = **sBuf; + ++(*sBuf); + switch( cbuf ) + { + case '+': + return symAdd; + + case '-': + return symSubtract; + + case '*': + return symMultiply; + + case '/': + return symDivide; + + case '^': + return symExponent; + + case '%': + return symModulus; + + case '(': + return symOpenParen; + + case ')': + return symCloseParen; + + case '|': + return symOr; + + case '&': + return symAnd; + + case '#': + return symXor; + + case '~': + return symNot; + + case ' ': + case '\t': + case '\n': + case '\r': + break; + + case '\0': + return symEOS; + + default: + if( cbuf == '.' || (cbuf >= '0' && cbuf <= '9') ) + { + char num[50]={cbuf}; + int nPos = 1; + bool bDot = false; + + for(;;) + { + cbuf = **sBuf; + if( cbuf == '.' ) + { + if( bDot == false ) + bDot = true; + else + throw FormulaException( + "Numbers cannot have more than one " + ". in them." + ); + } + if( cbuf == '.' || + (cbuf >= '0' && cbuf <= '9') ) + { + num[nPos++] = cbuf; + } + else + { + num[nPos] = '\0'; + sValue.push( + static_cast( + strtod( num, NULL ) + ) + ); + return symNumber; + } + ++(*sBuf); + } + } + else if( (cbuf >= 'a' && cbuf <= 'z') || + (cbuf >= 'A' && cbuf <= 'Z') || + (cbuf == '_') ) + { + char tok[50]={cbuf}; + int nPos = 1; + + for(;;) + { + cbuf = **sBuf; + if( (cbuf >= 'a' && cbuf <= 'z') || + (cbuf >= 'A' && cbuf <= 'Z') || + (cbuf >= '0' && cbuf <= '9') || + cbuf == '_' || cbuf == '.' || cbuf == ':' ) + { + tok[nPos++] = cbuf; + } + else + { + tok[nPos] = '\0'; + if( hVars.has( tok ) ) + { + sValue.push( hVars[tok] ); + return symNumber; + } + else if( hFunc.has( tok ) ) + { + sFunc.push( tok ); + return symFunction; + } + else + { + throw FormulaException( + "No variable or function named " + "\"%s\" exists.", + tok + ); + } + } + ++(*sBuf); + } + } + break; + } + } + } + + void reduce( bool bCloseParen = false ) + { + while( !sOper.isEmpty() ) + { + uint8_t nOpr = sOper.top(); + if( nOpr == symOpenParen ) + { + if( bCloseParen == true ) + sOper.pop(); + return; + } + sOper.pop(); + + prec dTop = sValue.top(); + sValue.pop(); + + switch( nOpr ) + { + case symAdd: + sValue.top() += dTop; + break; + + case symSubtract: + sValue.top() -= dTop; + break; + + case symMultiply: + sValue.top() *= dTop; + break; + + case symDivide: + sValue.top() /= dTop; + break; + + case symExponent: + sValue.top() = static_cast( + pow( sValue.top(), dTop ) + ); + break; + + case symModulus: + sValue.top() = static_cast( + fmod( sValue.top(), dTop ) + ); + break; + + case symOr: + sValue.top() = static_cast( + static_cast(sValue.top()) | + static_cast(dTop) + ); + break; + + case symAnd: + sValue.top() = static_cast( + static_cast(sValue.top()) & + static_cast(dTop) + ); + break; + + case symXor: + sValue.top() = static_cast( + static_cast(sValue.top()) ^ + static_cast(dTop) + ); + break; + + case symFunction: + sValue.push( (*hFunc.get( sFunc.pop() ))( dTop ) ); + break; + + case symNegate: + sValue.push( -dTop ); + break; + + case symNot: + sValue.push( static_cast( + ~static_cast(dTop) + ) ); + break; + } + } + + if( bCloseParen == true ) + { + throw FormulaException( + "Close-paren found without matching open-paren." + ); + } + } + }; } #endif diff --git a/src/stable/hash.cpp b/src/stable/hash.cpp index f44104b..85a13c7 100644 --- a/src/stable/hash.cpp +++ b/src/stable/hash.cpp @@ -12,58 +12,58 @@ namespace Bu { subExceptionDef( HashException ) } template<> uint32_t Bu::__calcHashCode( const char * const &k ) { - if (k == NULL) - { - return 0; - } - - unsigned long int nPos = 0; - for( const char *s = k; *s; s++ ) - { - nPos = *s + (nPos << 6) + (nPos << 16) - nPos; - } + if (k == NULL) + { + return 0; + } + + unsigned long int nPos = 0; + for( const char *s = k; *s; s++ ) + { + nPos = *s + (nPos << 6) + (nPos << 16) - nPos; + } - return nPos; + return nPos; } template<> bool Bu::__cmpHashKeys( const char * const &a, const char * const &b ) { - if( a == b ) - return true; + if( a == b ) + return true; - for(int j=0; a[j] == b[j]; j++ ) - if( a[j] == '\0' ) - return true; + for(int j=0; a[j] == b[j]; j++ ) + if( a[j] == '\0' ) + return true; - return false; + return false; } template<> uint32_t Bu::__calcHashCode( char * const &k ) { - if (k == NULL) - { - return 0; - } - - unsigned long int nPos = 0; - for( const char *s = k; *s; s++ ) - { - nPos = *s + (nPos << 6) + (nPos << 16) - nPos; - } + if (k == NULL) + { + return 0; + } + + unsigned long int nPos = 0; + for( const char *s = k; *s; s++ ) + { + nPos = *s + (nPos << 6) + (nPos << 16) - nPos; + } - return nPos; + return nPos; } template<> bool Bu::__cmpHashKeys( char * const &a, char * const &b ) { - if( a == b ) - return true; + if( a == b ) + return true; - for(int j=0; a[j] == b[j]; j++ ) - if( a[j] == '\0' ) - return true; + for(int j=0; a[j] == b[j]; j++ ) + if( a[j] == '\0' ) + return true; - return false; + return false; } diff --git a/src/stable/hash.h b/src/stable/hash.h index 86f189e..1574a1c 100644 --- a/src/stable/hash.h +++ b/src/stable/hash.h @@ -17,1311 +17,1311 @@ namespace Bu { - subExceptionDecl( HashException ) - - enum eHashException - { - excodeNotFilled - }; - - template - uint32_t __calcHashCode( const T &k ); - - template - bool __cmpHashKeys( const T &a, const T &b ); - - /** - * Default functor used to compute the size of hash tables. This version - * effectively doubles the size of the table when space is low, ensuring - * that you always wind up with an odd number for the table size. A - * better but slower option is to always find the next prime number that's - * above double your current table size, but that has the potential to be - * slower. - */ - struct __calcNextTSize_fast - { - uint32_t operator()( uint32_t nCapacity, uint32_t nFilled, - uint32_t nDeleted ) const - { - // This frist case will allow hashtables that are mostly deleted - // items to reset to small allocations - if( nFilled-nDeleted <= nCapacity/4 ) - { - nCapacity = 11; - while( nCapacity < nFilled*5/4 ) - nCapacity = nCapacity*2+1; - return nCapacity; - } - // This will hopefully prevent hash tables from growing needlessly - if( nFilled-nDeleted <= nCapacity/2 ) - { - if( nDeleted == 0 ) - return nCapacity/4*5+1; // Grow just a little - else - return nCapacity; // We're going to delete things - } - // Otherwise, just increase the capacity - return nCapacity*2+1; - } - }; - - template - int bitsTo( int iCount ) - { - return ( (iCount/(sizeof(totype)*8)) - + (iCount%(sizeof(totype)*8)>0 ? 1 : 0)); - } - - template - class Hash; - - /** @cond DEVEL */ - template - class HashCore - { - friend class Hash; - friend class SharedCore< - Hash, - HashCore - >; - private: - HashCore() : - nCapacity( 0 ), - nFilled( 0 ), - nDeleted( 0 ), - bFilled( NULL ), - bDeleted( NULL ), - aKeys( NULL ), - aValues( NULL ), - aHashCodes( NULL ) - { - } - - virtual ~HashCore() - { - clear(); - } - - void init() - { - if( nCapacity > 0 ) - return; - - nCapacity = 11; - nKeysSize = bitsTo( nCapacity ); - bFilled = ca.allocate( nKeysSize ); - bDeleted = ca.allocate( nKeysSize ); - clearBits(); - - aHashCodes = ca.allocate( nCapacity ); - aKeys = ka.allocate( nCapacity ); - aValues = va.allocate( nCapacity ); - } - - void clearBits() - { - if( nCapacity == 0 ) - return; - - for( uint32_t j = 0; j < nKeysSize; j++ ) - { - bFilled[j] = bDeleted[j] = 0; - } - } - - void fill( uint32_t loc, const key &k, const value &v, uint32_t hash ) - { - init(); - - bFilled[loc/32] |= (1<<(loc%32)); - va.construct( &aValues[loc], v ); - ka.construct( &aKeys[loc], k ); - aHashCodes[loc] = hash; - nFilled++; - //printf("Filled: %d, Deleted: %d, Capacity: %d\n", - // nFilled, nDeleted, nCapacity ); - } - - void _erase( uint32_t loc ) - { - if( nCapacity == 0 ) - return; - - bDeleted[loc/32] |= (1<<(loc%32)); - va.destroy( &aValues[loc] ); - ka.destroy( &aKeys[loc] ); - nDeleted++; - //printf("Filled: %d, Deleted: %d, Capacity: %d\n", - // nFilled, nDeleted, nCapacity ); - } - - key &getKeyAtPos( uint32_t nPos ) - { - if( nPos >= nCapacity ) - throw HashException("Referenced position invalid."); - return aKeys[nPos]; - } - - const key &getKeyAtPos( uint32_t nPos ) const - { - if( nPos >= nCapacity ) - throw HashException("Referenced position invalid."); - return aKeys[nPos]; - } - - value &getValueAtPos( uint32_t nPos ) - { - if( nPos >= nCapacity ) - throw HashException("Referenced position invalid."); - return aValues[nPos]; - } - - const value &getValueAtPos( uint32_t nPos ) const - { - if( nPos >= nCapacity ) - throw HashException("Referenced position invalid."); - return aValues[nPos]; - } - - uint32_t getFirstPos( bool &bFinished ) const - { - for( uint32_t j = 0; j < nCapacity; j++ ) - { - if( isFilled( j ) ) - if( !isDeleted( j ) ) - return j; - } - - bFinished = true; - return 0; - } - - uint32_t getNextPos( uint32_t nPos, bool &bFinished ) const - { - for( uint32_t j = nPos+1; j < nCapacity; j++ ) - { - if( isFilled( j ) ) - if( !isDeleted( j ) ) - return j; - } - - bFinished = true; - return 0; - } - - uint32_t probe( uint32_t hash, const key &k, bool &bFill, bool rehash=true ) - { - init(); - - uint32_t nCur = hash%nCapacity; - - // First we scan to see if the key is already there, abort if we - // run out of probing room, or we find a non-filled entry - int8_t j; - for( j = 0; - isFilled( nCur ) && j < 32; - nCur = (nCur + (1< %d (%d, %d)\n", nCapacity, nNewSize, nFilled, nDeleted ); - //printf("---REHASH---"); - //printf("Filled: %d, Deleted: %d, Capacity: %d\n", - // nFilled, nDeleted, nCapacity ); - - // Save all the old data - uint32_t nOldCapacity = nCapacity; - uint32_t *bOldFilled = bFilled; - uint32_t *aOldHashCodes = aHashCodes; - uint32_t nOldKeysSize = nKeysSize; - uint32_t *bOldDeleted = bDeleted; - value *aOldValues = aValues; - key *aOldKeys = aKeys; - - // Calculate new sizes - nCapacity = nNewSize; - nKeysSize = bitsTo( nCapacity ); - - // Allocate new memory + prep - bFilled = ca.allocate( nKeysSize ); - bDeleted = ca.allocate( nKeysSize ); - clearBits(); - - aHashCodes = ca.allocate( nCapacity ); - aKeys = ka.allocate( nCapacity ); - aValues = va.allocate( nCapacity ); - - nDeleted = nFilled = 0; - - // Re-insert all of the old data (except deleted items) - for( uint32_t j = 0; j < nOldCapacity; j++ ) - { - if( (bOldFilled[j/32]&(1<<(j%32)))!=0 && - (bOldDeleted[j/32]&(1<<(j%32)))==0 ) - { - insert( aOldKeys[j], aOldValues[j] ); - } - } - - // Delete all of the old data - for( uint32_t j = 0; j < nOldCapacity; j++ ) - { - if( (bOldFilled[j/32]&(1<<(j%32)))!=0 && - (bOldDeleted[j/32]&(1<<(j%32)))==0 ) - { - va.destroy( &aOldValues[j] ); - ka.destroy( &aOldKeys[j] ); - } - } - va.deallocate( aOldValues, nOldCapacity ); - ka.deallocate( aOldKeys, nOldCapacity ); - ca.deallocate( bOldFilled, nOldKeysSize ); - ca.deallocate( bOldDeleted, nOldKeysSize ); - ca.deallocate( aOldHashCodes, nOldCapacity ); - } - - bool isFilled( uint32_t loc ) const - { - if( loc >= nCapacity ) - throw HashException("Referenced position invalid."); - return (bFilled[loc/32]&(1<<(loc%32)))!=0; - } - - bool isDeleted( uint32_t loc ) const - { - if( loc >= nCapacity ) - throw HashException("Referenced position invalid."); - return (bDeleted[loc/32]&(1<<(loc%32)))!=0; - } - - void clear() - { - for( uint32_t j = 0; j < nCapacity; j++ ) - { - if( isFilled( j ) ) - if( !isDeleted( j ) ) - { - va.destroy( &aValues[j] ); - ka.destroy( &aKeys[j] ); - } - } - va.deallocate( aValues, nCapacity ); - ka.deallocate( aKeys, nCapacity ); - ca.deallocate( bFilled, nKeysSize ); - ca.deallocate( bDeleted, nKeysSize ); - ca.deallocate( aHashCodes, nCapacity ); - - bFilled = NULL; - bDeleted = NULL; - aKeys = NULL; - aValues = NULL; - aHashCodes = NULL; - - nCapacity = 0; - nFilled = 0; - nDeleted = 0; - } - - uint32_t nCapacity; - uint32_t nFilled; - uint32_t nDeleted; - uint32_t *bFilled; - uint32_t *bDeleted; - uint32_t nKeysSize; - key *aKeys; - value *aValues; - uint32_t *aHashCodes; - valuealloc va; - keyalloc ka; - challoc ca; - sizecalc szCalc; - }; - /** @endcond */ - - /** - * Libbu++ Template Hash Table. This is your average hash table, that uses - * template functions in order to do fast, efficient, generalized hashing. - * It's pretty easy to use, and works well with all other libbu++ types so - * far. - * - * In order to use it, I recommend the following for all basic usage: - *@code - // Define a Hash typedef with strings as keys and ints as values. - typedef Bu::Hash StrIntHash; - - // Create one - StrIntHash hInts; - - // Insert some integers - hInts["one"] = 1; - hInts["forty-two"] = 42; - hInts.insert("forty two", 42 ); - - // Get values out of the hash, the last two options are the most explicit, - // and must be used if the hash's value type does not match what you're - // comparing to exactly. - if( hInts["one"] == 1 ) doSomething(); - if( hInts["forty-two"].value() == 42 ) doSomething(); - if( hInts.get("forty two") == 42 ) doSomething(); - - // Iterate through the Hash - for( StrIntHash::iterator i = hInts.begin(); i != hInts.end(); i++ ) - { - // i.getValue() works too - print("'%s' = %d\n", i.getKey().getStr(), (*i) ); - } - - @endcode - *@param key (typename) The datatype of the hashtable keys - *@param value (typename) The datatype of the hashtable data - *@param sizecalc (typename) Functor to compute new table size on rehash - *@param keyalloc (typename) Memory allocator for hashtable keys - *@param valuealloc (typename) Memory allocator for hashtable values - *@param challoc (typename) Byte allocator for bitflags - *@ingroup Containers - */ - template, - typename valuealloc = std::allocator, - typename challoc = std::allocator - > - class Hash : public SharedCore< - Hash, - HashCore - > - { - private: - typedef class HashCore Core; - typedef class Hash MyType; - protected: - using SharedCore::core; - using SharedCore::_hardCopy; - using SharedCore::_resetCore; - using SharedCore::_allocateCore; - - public: - Hash() - { - } - - Hash( const MyType &src ) : - SharedCore( src ) - { - } - - virtual ~Hash() - { - } - - /** - * Get the current hash table capacity. (Changes at re-hash) - *@returns (uint32_t) The current capacity. - */ - uint32_t getCapacity() const - { - return core->nCapacity; - } - - /** - * Get the number of hash locations spoken for. (Including - * not-yet-cleaned-up deleted items.) - *@returns (uint32_t) The current fill state. - */ - uint32_t getFill() const - { - return core->nFilled; - } - - /** - * Get the number of items stored in the hash table. - *@returns (uint32_t) The number of items stored in the hash table. - */ - uint32_t getSize() const - { - return core->nFilled-core->nDeleted; - } - - bool isEmpty() const - { - return (core->nFilled-core->nDeleted) == 0; - } - - /** - * Get the number of items which have been deleted, but not yet - * cleaned up. - *@returns (uint32_t) The number of deleted items. - */ - uint32_t getDeleted() const - { - return core->nDeleted; - } - - struct HashProxy - { - friend class Hash; - private: - HashProxy( MyType &h, const key *k, uint32_t nPos, uint32_t hash ) : - hsh( h ), - pKey( k ), - nPos( nPos ), - hash( hash ), - bFilled( false ) - { - } - - HashProxy( MyType &h, uint32_t nPos, value *pValue ) : - hsh( h ), - nPos( nPos ), - pValue( pValue ), - bFilled( true ) - { - } - - MyType &hsh; - const key *pKey; - uint32_t nPos; - value *pValue; - uint32_t hash; - bool bFilled; - - public: - /** - * Cast operator for HashProxy. - *@returns (value_type &) The value the HashProxy is pointing to. - */ - operator value &() - { - if( bFilled == false ) - throw HashException( - excodeNotFilled, - "No data associated with that key." - ); - return *pValue; - } - - /** - * Direct function for retrieving a value out of the HashProxy. - *@returns (value_type &) The value pointed to by this HashProxy. - */ - value &getValue() - { - if( bFilled == false ) - throw HashException( - excodeNotFilled, - "No data associated with that key." - ); - return *pValue; - } - - /** - * Whether this HashProxy points to something real or not. - */ - bool isFilled() - { - return bFilled; - } - - /** - * Erase the data pointed to by this HashProxy. - */ - void erase() - { - if( bFilled ) - { - hsh.core->_erase( nPos ); - } - } - - /** - * Assign data to this point in the hash table. - *@param nval (value_type) the data to assign. - */ - value operator=( value nval ) - { - if( bFilled ) - { - hsh.core->va.destroy( &hsh.core->aValues[nPos] ); - hsh.core->va.construct( &hsh.core->aValues[nPos], nval ); - } - else - { - hsh.core->fill( nPos, *pKey, nval, hash ); - } - - return nval; - } - - /** - * Pointer extraction operator. Access to members of data pointed to - * by HashProxy. - *@returns (value_type *) - */ - value *operator->() - { - if( bFilled == false ) - throw HashException( - excodeNotFilled, - "No data associated with that key." - ); - return pValue; - } - }; - - /** - * Hash table index operator - *@param k (key_type) Key of data to be retrieved. - *@returns (HashProxy) Proxy pointing to the data. - */ - HashProxy operator[]( const key &k ) - { - _hardCopy(); - - uint32_t hash = __calcHashCode( k ); - bool bFill; - uint32_t nPos = core->probe( hash, k, bFill ); - - if( bFill ) - { - return HashProxy( *this, nPos, &core->aValues[nPos] ); - } - else - { - return HashProxy( *this, &k, nPos, hash ); - } - } - - /** - * Insert a value (v) under key (k) into the hash table - *@param k (key_type) Key to list the value under. - *@param v (value_type) Value to store in the hash table. - */ - void insert( const key &k, const value &v ) - { - _hardCopy(); - - core->insert( k, v ); - } - - /** - * Remove a value from the hash table. - *@param k (key_type) The data under this key will be erased. - */ - void erase( const key &k ) - { - _hardCopy(); - - uint32_t hash = __calcHashCode( k ); - bool bFill; - uint32_t nPos = core->probe( hash, k, bFill ); - - if( bFill ) - { - core->_erase( nPos ); - } - } - - struct iterator; - - /** - * Remove a value from the hash pointed to from an iterator. - *@param i (iterator &) The data to be erased. - */ - void erase( struct iterator &i ) - { - if( this != i.hsh ) - throw HashException("This iterator didn't come from this Hash."); - - _hardCopy(); - - if( core->isFilled( i.nPos ) && !core->isDeleted( i.nPos ) ) - { - core->_erase( i.nPos ); - } - } - - /** - * Remove all data from the hash table. - */ - virtual void clear() - { - _resetCore(); - } - - /** - * Get an item of data from the hash table. - *@param k (key_type) Key pointing to the data to be retrieved. - *@returns (value_type &) The data pointed to by (k). - */ - value &get( const key &k ) - { - _hardCopy(); - - uint32_t hash = __calcHashCode( k ); - bool bFill; - uint32_t nPos = core->probe( hash, k, bFill, false ); - - if( bFill ) - { - return core->aValues[nPos]; - } - else - { - throw HashException( - excodeNotFilled, - "No data associated with that key." - ); - } - } - - /** - * Get a const item of data from the hash table. - *@param k (key_type) Key pointing to the data to be retrieved. - *@returns (const value_type &) A const version of the data pointed - * to by (k). - */ - const value &get( const key &k ) const - { - uint32_t hash = __calcHashCode( k ); - bool bFill; - uint32_t nPos = core->probe( hash, k, bFill ); - - if( bFill ) - { - return core->aValues[nPos]; - } - else - { - throw HashException( - excodeNotFilled, - "No data associated with that key." - ); - } - } - - /** - * Does the hash table contain an item under key (k). - *@param k (key_type) The key to check. - *@returns (bool) Whether there was an item in the hash under key (k). - */ - bool has( const key &k ) const - { - bool bFill; - core->probe( __calcHashCode( k ), k, bFill ); - - return bFill; - } - - /** - * Iteration structure for iterating through the hash. - */ - typedef struct iterator - { - friend class Hash; - private: - iterator( MyType *hsh ) : - hsh( hsh ), - nPos( 0 ), - bFinished( false ) - { - nPos = hsh->core->getFirstPos( bFinished ); - } - - iterator( MyType *hsh, bool bDone ) : - hsh( hsh ), - nPos( 0 ), - bFinished( bDone ) - { - } - - MyType *hsh; - uint32_t nPos; - bool bFinished; - - public: - iterator( const iterator &i ) : - hsh( i.hsh ), - nPos( i.nPos ), - bFinished( i.bFinished ) - { - } - - iterator() : - hsh( NULL ), - nPos( NULL ), - bFinished( true ) - { - } - - bool isValid() const - { - return !bFinished; - } - - operator bool() const - { - return !bFinished; - } - - /** - * Iterator incrementation operator. Move the iterator forward. - */ - iterator operator++( int ) - { - if( bFinished == false ) - nPos = hsh->core->getNextPos( nPos, bFinished ); - - return *this; - } - - /** - * Iterator incrementation operator. Move the iterator forward. - */ - iterator operator++() - { - if( bFinished == false ) - nPos = hsh->core->getNextPos( nPos, bFinished ); - - return *this; - } - - /** - * Iterator equality comparison operator. Iterators the same? - */ - bool operator==( const iterator &oth ) const - { - if( bFinished != oth.bFinished ) - return false; - if( bFinished == true ) - { - return true; - } - else - { - if( oth.nPos == nPos ) - return true; - return false; - } - } - - /** - * Iterator not equality comparison operator. Not the same? - */ - bool operator!=( const iterator &oth ) const - { - return !(*this == oth ); - } - - /** - * Iterator assignment operator. - */ - iterator operator=( const iterator &oth ) - { - hsh = oth.hsh; - nPos = oth.nPos; - bFinished = oth.bFinished; - return *this; - } - - /** - * Iterator dereference operator... err.. get the value - *@returns (value_type &) The value behind this iterator. - */ - value &operator *() - { - hsh->_hardCopy(); - return hsh->core->getValueAtPos( nPos ); - } - - const value &operator *() const - { - return hsh->core->getValueAtPos( nPos ); - } - - /** - * Get the key behind this iterator. - *@returns (key_type &) The key behind this iterator. - */ - const key &getKey() const - { - return hsh->core->getKeyAtPos( nPos ); - } - - /** - * Get the value behind this iterator. - *@returns (value_type &) The value behind this iterator. - */ - value &getValue() - { - hsh->_hardCopy(); - return hsh->core->getValueAtPos( nPos ); - } - - /** - * Get the value behind this iterator. - *@returns (value_type &) The value behind this iterator. - */ - const value &getValue() const - { - return hsh->core->getValueAtPos( nPos ); - } - } iterator; - - /** - * Iteration structure for iterating through the hash (const). - */ - typedef struct const_iterator - { - friend class Hash; - private: - const_iterator( const MyType *hsh ) : - hsh( hsh ), - nPos( 0 ), - bFinished( false ) - { - nPos = hsh->core->getFirstPos( bFinished ); - } - - const_iterator( const MyType *hsh, bool bDone ) : - hsh( hsh ), - nPos( 0 ), - bFinished( bDone ) - { - } - - const MyType *hsh; - uint32_t nPos; - bool bFinished; - - public: - const_iterator() : - hsh( NULL ), - nPos( 0 ), - bFinished( true ) - { - } - - const_iterator( const const_iterator &src ) : - hsh( src.hsh ), - nPos( src.nPos ), - bFinished( src.bFinished ) - { - } - - const_iterator( const iterator &src ) : - hsh( src.hsh ), - nPos( src.nPos ), - bFinished( src.bFinished ) - { - } - - bool isValid() const - { - return !bFinished; - } - - operator bool() const - { - return !bFinished; - } - - /** - * Iterator incrementation operator. Move the iterator forward. - */ - const_iterator operator++( int ) - { - if( bFinished == false ) - nPos = hsh->core->getNextPos( nPos, bFinished ); - - return *this; - } - - /** - * Iterator incrementation operator. Move the iterator forward. - */ - const_iterator operator++() - { - if( bFinished == false ) - nPos = hsh->core->getNextPos( nPos, bFinished ); - - return *this; - } - - /** - * Iterator equality comparison operator. Iterators the same? - */ - bool operator==( const const_iterator &oth ) const - { - if( bFinished != oth.bFinished ) - return false; - if( bFinished == true ) - { - return true; - } - else - { - if( oth.nPos == nPos ) - return true; - return false; - } - } - - /** - * Iterator not equality comparison operator. Not the same? - */ - bool operator!=( const const_iterator &oth ) const - { - return !(*this == oth ); - } - - /** - * Iterator assignment operator. - */ - const_iterator operator=( const const_iterator &oth ) - { - hsh = oth.hsh; - nPos = oth.nPos; - bFinished = oth.bFinished; - return *this; - } - - /** - * Iterator dereference operator... err.. get the value - *@returns (value_type &) The value behind this iterator. - */ - const value &operator *() const - { - return hsh->core->getValueAtPos( nPos ); - } - - /** - * Get the key behind this iterator. - *@returns (key_type &) The key behind this iterator. - */ - const key &getKey() const - { - return hsh->core->getKeyAtPos( nPos ); - } - - /** - * Get the value behind this iterator. - *@returns (value_type &) The value behind this iterator. - */ - const value &getValue() const - { - return hsh->core->getValueAtPos( nPos ); - } - } const_iterator; - - /** - * Get an iterator pointing to the first item in the hash table. - *@returns (iterator) An iterator pointing to the first item in the - * hash table. - */ - iterator begin() - { - return iterator( this ); - } - - const_iterator begin() const - { - return const_iterator( this ); - } - - /** - * Get an iterator pointing to a point just past the last item in the - * hash table. - *@returns (iterator) An iterator pointing to a point just past the - * last item in the hash table. - */ - iterator end() - { - return iterator( this, true ); - } - - const_iterator end() const - { - return const_iterator( this, true ); - } - - /** - * Get a list of all the keys in the hash table. - *@returns (std::list) The list of keys in the hash table. - */ - Bu::List getKeys() const - { - Bu::List lKeys; - - for( uint32_t j = 0; j < core->nCapacity; j++ ) - { - if( core->isFilled( j ) ) - { - if( !core->isDeleted( j ) ) - { - lKeys.append( core->aKeys[j] ); - } - } - } - - return lKeys; - } - - Bu::List getValues() const - { - Bu::List lValues; - - for( uint32_t j = 0; j < core->nCapacity; j++ ) - { - if( core->isFilled( j ) ) - { - if( !core->isDeleted( j ) ) - { - lValues.append( core->aValues[j] ); - } - } - } - - return lValues; - } - - bool operator==( const MyType &rhs ) const - { - if( this == &rhs ) - return true; - if( core == rhs.core ) - return true; - if( core == NULL || rhs.core == NULL ) - return false; - if( getSize() != rhs.getSize() ) - return false; - - for( uint32_t j = 0; j < core->nCapacity; j++ ) - { - if( core->isFilled( j ) ) - { - if( !core->isDeleted( j ) ) - { - // Check to see if this key is in the other hash - if( rhs.has( core->aKeys[j] ) ) - { - if( !(core->aValues[j] == rhs.get( core->aKeys[j]) ) ) - { - return false; - } - } - else - { - return false; - } - } - } - } - - return true; - } - - bool operator!=( const MyType &rhs ) const - { - return !(*this == rhs); - } - - MyType &operator+=( const MyType &rhs ) - { - if( this == &rhs ) - return *this; - if( core == rhs.core ) - return *this; - if( core == NULL || rhs.core == NULL ) - return *this; - - for( const_iterator i = rhs.begin(); i; i++ ) - insert( i.getKey(), i.getValue() ); - - return *this; - } - - protected: - virtual Core *_copyCore( Core *src ) - { - Core *pRet = _allocateCore(); - - pRet->nFilled = 0; - pRet->nDeleted = 0; - pRet->nCapacity = src->nCapacity; - pRet->nKeysSize = bitsTo( pRet->nCapacity ); - pRet->bFilled = pRet->ca.allocate( pRet->nKeysSize ); - pRet->bDeleted = pRet->ca.allocate( pRet->nKeysSize ); - pRet->clearBits(); - - pRet->aHashCodes = pRet->ca.allocate( pRet->nCapacity ); - pRet->aKeys = pRet->ka.allocate( pRet->nCapacity ); - pRet->aValues = pRet->va.allocate( pRet->nCapacity ); - - for( uint32_t j = 0; j < src->nCapacity; j++ ) - { - if( src->isFilled( j ) && !src->isDeleted( j ) ) - { - pRet->insert( src->aKeys[j], src->aValues[j] ); - } - } - - return pRet; - } - }; - - template uint32_t __calcHashCode( const T &k ) - { - return static_cast( k ); - } - - template bool __cmpHashKeys( const T &a, const T &b ) - { - return (a == b); - } - - template<> uint32_t __calcHashCode( const char * const &k ); - template<> bool __cmpHashKeys( const char * const &a, const char * const &b ); - - template<> uint32_t __calcHashCode( char * const &k ); - template<> bool __cmpHashKeys( char * const &a, char * const &b ); - - class Formatter; - Formatter &operator<<( Formatter &rOut, char *sStr ); - Formatter &operator<<( Formatter &rOut, signed char c ); - template - Formatter &operator<<( Formatter &f, const Bu::Hash &l ) - { - f << '{'; - for( typename Bu::Hash::const_iterator i = l.begin(); i; i++ ) - { - if( i != l.begin() ) - f << ", "; - f << i.getKey() << ": " << i.getValue(); - } - f << '}'; - - return f; - } - - template - ArchiveBase &operator<<( ArchiveBase &ar, const Hash &h ) - { - long iSize = h.getSize(); - ar << iSize; - for( typename Hash::const_iterator i = h.begin(); i != h.end(); i++ ) - { - ar << (i.getKey()); - ar << (i.getValue()); - } - - return ar; - } - - template - ArchiveBase &operator>>( ArchiveBase &ar, Hash &h ) - { - h.clear(); - long nSize; - ar >> nSize; - - for( long j = 0; j < nSize; j++ ) - { - key k; value v; - ar >> k >> v; - h.insert( k, v ); - } - - return ar; - } + subExceptionDecl( HashException ) + + enum eHashException + { + excodeNotFilled + }; + + template + uint32_t __calcHashCode( const T &k ); + + template + bool __cmpHashKeys( const T &a, const T &b ); + + /** + * Default functor used to compute the size of hash tables. This version + * effectively doubles the size of the table when space is low, ensuring + * that you always wind up with an odd number for the table size. A + * better but slower option is to always find the next prime number that's + * above double your current table size, but that has the potential to be + * slower. + */ + struct __calcNextTSize_fast + { + uint32_t operator()( uint32_t nCapacity, uint32_t nFilled, + uint32_t nDeleted ) const + { + // This frist case will allow hashtables that are mostly deleted + // items to reset to small allocations + if( nFilled-nDeleted <= nCapacity/4 ) + { + nCapacity = 11; + while( nCapacity < nFilled*5/4 ) + nCapacity = nCapacity*2+1; + return nCapacity; + } + // This will hopefully prevent hash tables from growing needlessly + if( nFilled-nDeleted <= nCapacity/2 ) + { + if( nDeleted == 0 ) + return nCapacity/4*5+1; // Grow just a little + else + return nCapacity; // We're going to delete things + } + // Otherwise, just increase the capacity + return nCapacity*2+1; + } + }; + + template + int bitsTo( int iCount ) + { + return ( (iCount/(sizeof(totype)*8)) + + (iCount%(sizeof(totype)*8)>0 ? 1 : 0)); + } + + template + class Hash; + + /** @cond DEVEL */ + template + class HashCore + { + friend class Hash; + friend class SharedCore< + Hash, + HashCore + >; + private: + HashCore() : + nCapacity( 0 ), + nFilled( 0 ), + nDeleted( 0 ), + bFilled( NULL ), + bDeleted( NULL ), + aKeys( NULL ), + aValues( NULL ), + aHashCodes( NULL ) + { + } + + virtual ~HashCore() + { + clear(); + } + + void init() + { + if( nCapacity > 0 ) + return; + + nCapacity = 11; + nKeysSize = bitsTo( nCapacity ); + bFilled = ca.allocate( nKeysSize ); + bDeleted = ca.allocate( nKeysSize ); + clearBits(); + + aHashCodes = ca.allocate( nCapacity ); + aKeys = ka.allocate( nCapacity ); + aValues = va.allocate( nCapacity ); + } + + void clearBits() + { + if( nCapacity == 0 ) + return; + + for( uint32_t j = 0; j < nKeysSize; j++ ) + { + bFilled[j] = bDeleted[j] = 0; + } + } + + void fill( uint32_t loc, const key &k, const value &v, uint32_t hash ) + { + init(); + + bFilled[loc/32] |= (1<<(loc%32)); + va.construct( &aValues[loc], v ); + ka.construct( &aKeys[loc], k ); + aHashCodes[loc] = hash; + nFilled++; + //printf("Filled: %d, Deleted: %d, Capacity: %d\n", + // nFilled, nDeleted, nCapacity ); + } + + void _erase( uint32_t loc ) + { + if( nCapacity == 0 ) + return; + + bDeleted[loc/32] |= (1<<(loc%32)); + va.destroy( &aValues[loc] ); + ka.destroy( &aKeys[loc] ); + nDeleted++; + //printf("Filled: %d, Deleted: %d, Capacity: %d\n", + // nFilled, nDeleted, nCapacity ); + } + + key &getKeyAtPos( uint32_t nPos ) + { + if( nPos >= nCapacity ) + throw HashException("Referenced position invalid."); + return aKeys[nPos]; + } + + const key &getKeyAtPos( uint32_t nPos ) const + { + if( nPos >= nCapacity ) + throw HashException("Referenced position invalid."); + return aKeys[nPos]; + } + + value &getValueAtPos( uint32_t nPos ) + { + if( nPos >= nCapacity ) + throw HashException("Referenced position invalid."); + return aValues[nPos]; + } + + const value &getValueAtPos( uint32_t nPos ) const + { + if( nPos >= nCapacity ) + throw HashException("Referenced position invalid."); + return aValues[nPos]; + } + + uint32_t getFirstPos( bool &bFinished ) const + { + for( uint32_t j = 0; j < nCapacity; j++ ) + { + if( isFilled( j ) ) + if( !isDeleted( j ) ) + return j; + } + + bFinished = true; + return 0; + } + + uint32_t getNextPos( uint32_t nPos, bool &bFinished ) const + { + for( uint32_t j = nPos+1; j < nCapacity; j++ ) + { + if( isFilled( j ) ) + if( !isDeleted( j ) ) + return j; + } + + bFinished = true; + return 0; + } + + uint32_t probe( uint32_t hash, const key &k, bool &bFill, bool rehash=true ) + { + init(); + + uint32_t nCur = hash%nCapacity; + + // First we scan to see if the key is already there, abort if we + // run out of probing room, or we find a non-filled entry + int8_t j; + for( j = 0; + isFilled( nCur ) && j < 32; + nCur = (nCur + (1< %d (%d, %d)\n", nCapacity, nNewSize, nFilled, nDeleted ); + //printf("---REHASH---"); + //printf("Filled: %d, Deleted: %d, Capacity: %d\n", + // nFilled, nDeleted, nCapacity ); + + // Save all the old data + uint32_t nOldCapacity = nCapacity; + uint32_t *bOldFilled = bFilled; + uint32_t *aOldHashCodes = aHashCodes; + uint32_t nOldKeysSize = nKeysSize; + uint32_t *bOldDeleted = bDeleted; + value *aOldValues = aValues; + key *aOldKeys = aKeys; + + // Calculate new sizes + nCapacity = nNewSize; + nKeysSize = bitsTo( nCapacity ); + + // Allocate new memory + prep + bFilled = ca.allocate( nKeysSize ); + bDeleted = ca.allocate( nKeysSize ); + clearBits(); + + aHashCodes = ca.allocate( nCapacity ); + aKeys = ka.allocate( nCapacity ); + aValues = va.allocate( nCapacity ); + + nDeleted = nFilled = 0; + + // Re-insert all of the old data (except deleted items) + for( uint32_t j = 0; j < nOldCapacity; j++ ) + { + if( (bOldFilled[j/32]&(1<<(j%32)))!=0 && + (bOldDeleted[j/32]&(1<<(j%32)))==0 ) + { + insert( aOldKeys[j], aOldValues[j] ); + } + } + + // Delete all of the old data + for( uint32_t j = 0; j < nOldCapacity; j++ ) + { + if( (bOldFilled[j/32]&(1<<(j%32)))!=0 && + (bOldDeleted[j/32]&(1<<(j%32)))==0 ) + { + va.destroy( &aOldValues[j] ); + ka.destroy( &aOldKeys[j] ); + } + } + va.deallocate( aOldValues, nOldCapacity ); + ka.deallocate( aOldKeys, nOldCapacity ); + ca.deallocate( bOldFilled, nOldKeysSize ); + ca.deallocate( bOldDeleted, nOldKeysSize ); + ca.deallocate( aOldHashCodes, nOldCapacity ); + } + + bool isFilled( uint32_t loc ) const + { + if( loc >= nCapacity ) + throw HashException("Referenced position invalid."); + return (bFilled[loc/32]&(1<<(loc%32)))!=0; + } + + bool isDeleted( uint32_t loc ) const + { + if( loc >= nCapacity ) + throw HashException("Referenced position invalid."); + return (bDeleted[loc/32]&(1<<(loc%32)))!=0; + } + + void clear() + { + for( uint32_t j = 0; j < nCapacity; j++ ) + { + if( isFilled( j ) ) + if( !isDeleted( j ) ) + { + va.destroy( &aValues[j] ); + ka.destroy( &aKeys[j] ); + } + } + va.deallocate( aValues, nCapacity ); + ka.deallocate( aKeys, nCapacity ); + ca.deallocate( bFilled, nKeysSize ); + ca.deallocate( bDeleted, nKeysSize ); + ca.deallocate( aHashCodes, nCapacity ); + + bFilled = NULL; + bDeleted = NULL; + aKeys = NULL; + aValues = NULL; + aHashCodes = NULL; + + nCapacity = 0; + nFilled = 0; + nDeleted = 0; + } + + uint32_t nCapacity; + uint32_t nFilled; + uint32_t nDeleted; + uint32_t *bFilled; + uint32_t *bDeleted; + uint32_t nKeysSize; + key *aKeys; + value *aValues; + uint32_t *aHashCodes; + valuealloc va; + keyalloc ka; + challoc ca; + sizecalc szCalc; + }; + /** @endcond */ + + /** + * Libbu++ Template Hash Table. This is your average hash table, that uses + * template functions in order to do fast, efficient, generalized hashing. + * It's pretty easy to use, and works well with all other libbu++ types so + * far. + * + * In order to use it, I recommend the following for all basic usage: + *@code + // Define a Hash typedef with strings as keys and ints as values. + typedef Bu::Hash StrIntHash; + + // Create one + StrIntHash hInts; + + // Insert some integers + hInts["one"] = 1; + hInts["forty-two"] = 42; + hInts.insert("forty two", 42 ); + + // Get values out of the hash, the last two options are the most explicit, + // and must be used if the hash's value type does not match what you're + // comparing to exactly. + if( hInts["one"] == 1 ) doSomething(); + if( hInts["forty-two"].value() == 42 ) doSomething(); + if( hInts.get("forty two") == 42 ) doSomething(); + + // Iterate through the Hash + for( StrIntHash::iterator i = hInts.begin(); i != hInts.end(); i++ ) + { + // i.getValue() works too + print("'%s' = %d\n", i.getKey().getStr(), (*i) ); + } + + @endcode + *@param key (typename) The datatype of the hashtable keys + *@param value (typename) The datatype of the hashtable data + *@param sizecalc (typename) Functor to compute new table size on rehash + *@param keyalloc (typename) Memory allocator for hashtable keys + *@param valuealloc (typename) Memory allocator for hashtable values + *@param challoc (typename) Byte allocator for bitflags + *@ingroup Containers + */ + template, + typename valuealloc = std::allocator, + typename challoc = std::allocator + > + class Hash : public SharedCore< + Hash, + HashCore + > + { + private: + typedef class HashCore Core; + typedef class Hash MyType; + protected: + using SharedCore::core; + using SharedCore::_hardCopy; + using SharedCore::_resetCore; + using SharedCore::_allocateCore; + + public: + Hash() + { + } + + Hash( const MyType &src ) : + SharedCore( src ) + { + } + + virtual ~Hash() + { + } + + /** + * Get the current hash table capacity. (Changes at re-hash) + *@returns (uint32_t) The current capacity. + */ + uint32_t getCapacity() const + { + return core->nCapacity; + } + + /** + * Get the number of hash locations spoken for. (Including + * not-yet-cleaned-up deleted items.) + *@returns (uint32_t) The current fill state. + */ + uint32_t getFill() const + { + return core->nFilled; + } + + /** + * Get the number of items stored in the hash table. + *@returns (uint32_t) The number of items stored in the hash table. + */ + uint32_t getSize() const + { + return core->nFilled-core->nDeleted; + } + + bool isEmpty() const + { + return (core->nFilled-core->nDeleted) == 0; + } + + /** + * Get the number of items which have been deleted, but not yet + * cleaned up. + *@returns (uint32_t) The number of deleted items. + */ + uint32_t getDeleted() const + { + return core->nDeleted; + } + + struct HashProxy + { + friend class Hash; + private: + HashProxy( MyType &h, const key *k, uint32_t nPos, uint32_t hash ) : + hsh( h ), + pKey( k ), + nPos( nPos ), + hash( hash ), + bFilled( false ) + { + } + + HashProxy( MyType &h, uint32_t nPos, value *pValue ) : + hsh( h ), + nPos( nPos ), + pValue( pValue ), + bFilled( true ) + { + } + + MyType &hsh; + const key *pKey; + uint32_t nPos; + value *pValue; + uint32_t hash; + bool bFilled; + + public: + /** + * Cast operator for HashProxy. + *@returns (value_type &) The value the HashProxy is pointing to. + */ + operator value &() + { + if( bFilled == false ) + throw HashException( + excodeNotFilled, + "No data associated with that key." + ); + return *pValue; + } + + /** + * Direct function for retrieving a value out of the HashProxy. + *@returns (value_type &) The value pointed to by this HashProxy. + */ + value &getValue() + { + if( bFilled == false ) + throw HashException( + excodeNotFilled, + "No data associated with that key." + ); + return *pValue; + } + + /** + * Whether this HashProxy points to something real or not. + */ + bool isFilled() + { + return bFilled; + } + + /** + * Erase the data pointed to by this HashProxy. + */ + void erase() + { + if( bFilled ) + { + hsh.core->_erase( nPos ); + } + } + + /** + * Assign data to this point in the hash table. + *@param nval (value_type) the data to assign. + */ + value operator=( value nval ) + { + if( bFilled ) + { + hsh.core->va.destroy( &hsh.core->aValues[nPos] ); + hsh.core->va.construct( &hsh.core->aValues[nPos], nval ); + } + else + { + hsh.core->fill( nPos, *pKey, nval, hash ); + } + + return nval; + } + + /** + * Pointer extraction operator. Access to members of data pointed to + * by HashProxy. + *@returns (value_type *) + */ + value *operator->() + { + if( bFilled == false ) + throw HashException( + excodeNotFilled, + "No data associated with that key." + ); + return pValue; + } + }; + + /** + * Hash table index operator + *@param k (key_type) Key of data to be retrieved. + *@returns (HashProxy) Proxy pointing to the data. + */ + HashProxy operator[]( const key &k ) + { + _hardCopy(); + + uint32_t hash = __calcHashCode( k ); + bool bFill; + uint32_t nPos = core->probe( hash, k, bFill ); + + if( bFill ) + { + return HashProxy( *this, nPos, &core->aValues[nPos] ); + } + else + { + return HashProxy( *this, &k, nPos, hash ); + } + } + + /** + * Insert a value (v) under key (k) into the hash table + *@param k (key_type) Key to list the value under. + *@param v (value_type) Value to store in the hash table. + */ + void insert( const key &k, const value &v ) + { + _hardCopy(); + + core->insert( k, v ); + } + + /** + * Remove a value from the hash table. + *@param k (key_type) The data under this key will be erased. + */ + void erase( const key &k ) + { + _hardCopy(); + + uint32_t hash = __calcHashCode( k ); + bool bFill; + uint32_t nPos = core->probe( hash, k, bFill ); + + if( bFill ) + { + core->_erase( nPos ); + } + } + + struct iterator; + + /** + * Remove a value from the hash pointed to from an iterator. + *@param i (iterator &) The data to be erased. + */ + void erase( struct iterator &i ) + { + if( this != i.hsh ) + throw HashException("This iterator didn't come from this Hash."); + + _hardCopy(); + + if( core->isFilled( i.nPos ) && !core->isDeleted( i.nPos ) ) + { + core->_erase( i.nPos ); + } + } + + /** + * Remove all data from the hash table. + */ + virtual void clear() + { + _resetCore(); + } + + /** + * Get an item of data from the hash table. + *@param k (key_type) Key pointing to the data to be retrieved. + *@returns (value_type &) The data pointed to by (k). + */ + value &get( const key &k ) + { + _hardCopy(); + + uint32_t hash = __calcHashCode( k ); + bool bFill; + uint32_t nPos = core->probe( hash, k, bFill, false ); + + if( bFill ) + { + return core->aValues[nPos]; + } + else + { + throw HashException( + excodeNotFilled, + "No data associated with that key." + ); + } + } + + /** + * Get a const item of data from the hash table. + *@param k (key_type) Key pointing to the data to be retrieved. + *@returns (const value_type &) A const version of the data pointed + * to by (k). + */ + const value &get( const key &k ) const + { + uint32_t hash = __calcHashCode( k ); + bool bFill; + uint32_t nPos = core->probe( hash, k, bFill ); + + if( bFill ) + { + return core->aValues[nPos]; + } + else + { + throw HashException( + excodeNotFilled, + "No data associated with that key." + ); + } + } + + /** + * Does the hash table contain an item under key (k). + *@param k (key_type) The key to check. + *@returns (bool) Whether there was an item in the hash under key (k). + */ + bool has( const key &k ) const + { + bool bFill; + core->probe( __calcHashCode( k ), k, bFill ); + + return bFill; + } + + /** + * Iteration structure for iterating through the hash. + */ + typedef struct iterator + { + friend class Hash; + private: + iterator( MyType *hsh ) : + hsh( hsh ), + nPos( 0 ), + bFinished( false ) + { + nPos = hsh->core->getFirstPos( bFinished ); + } + + iterator( MyType *hsh, bool bDone ) : + hsh( hsh ), + nPos( 0 ), + bFinished( bDone ) + { + } + + MyType *hsh; + uint32_t nPos; + bool bFinished; + + public: + iterator( const iterator &i ) : + hsh( i.hsh ), + nPos( i.nPos ), + bFinished( i.bFinished ) + { + } + + iterator() : + hsh( NULL ), + nPos( NULL ), + bFinished( true ) + { + } + + bool isValid() const + { + return !bFinished; + } + + operator bool() const + { + return !bFinished; + } + + /** + * Iterator incrementation operator. Move the iterator forward. + */ + iterator operator++( int ) + { + if( bFinished == false ) + nPos = hsh->core->getNextPos( nPos, bFinished ); + + return *this; + } + + /** + * Iterator incrementation operator. Move the iterator forward. + */ + iterator operator++() + { + if( bFinished == false ) + nPos = hsh->core->getNextPos( nPos, bFinished ); + + return *this; + } + + /** + * Iterator equality comparison operator. Iterators the same? + */ + bool operator==( const iterator &oth ) const + { + if( bFinished != oth.bFinished ) + return false; + if( bFinished == true ) + { + return true; + } + else + { + if( oth.nPos == nPos ) + return true; + return false; + } + } + + /** + * Iterator not equality comparison operator. Not the same? + */ + bool operator!=( const iterator &oth ) const + { + return !(*this == oth ); + } + + /** + * Iterator assignment operator. + */ + iterator operator=( const iterator &oth ) + { + hsh = oth.hsh; + nPos = oth.nPos; + bFinished = oth.bFinished; + return *this; + } + + /** + * Iterator dereference operator... err.. get the value + *@returns (value_type &) The value behind this iterator. + */ + value &operator *() + { + hsh->_hardCopy(); + return hsh->core->getValueAtPos( nPos ); + } + + const value &operator *() const + { + return hsh->core->getValueAtPos( nPos ); + } + + /** + * Get the key behind this iterator. + *@returns (key_type &) The key behind this iterator. + */ + const key &getKey() const + { + return hsh->core->getKeyAtPos( nPos ); + } + + /** + * Get the value behind this iterator. + *@returns (value_type &) The value behind this iterator. + */ + value &getValue() + { + hsh->_hardCopy(); + return hsh->core->getValueAtPos( nPos ); + } + + /** + * Get the value behind this iterator. + *@returns (value_type &) The value behind this iterator. + */ + const value &getValue() const + { + return hsh->core->getValueAtPos( nPos ); + } + } iterator; + + /** + * Iteration structure for iterating through the hash (const). + */ + typedef struct const_iterator + { + friend class Hash; + private: + const_iterator( const MyType *hsh ) : + hsh( hsh ), + nPos( 0 ), + bFinished( false ) + { + nPos = hsh->core->getFirstPos( bFinished ); + } + + const_iterator( const MyType *hsh, bool bDone ) : + hsh( hsh ), + nPos( 0 ), + bFinished( bDone ) + { + } + + const MyType *hsh; + uint32_t nPos; + bool bFinished; + + public: + const_iterator() : + hsh( NULL ), + nPos( 0 ), + bFinished( true ) + { + } + + const_iterator( const const_iterator &src ) : + hsh( src.hsh ), + nPos( src.nPos ), + bFinished( src.bFinished ) + { + } + + const_iterator( const iterator &src ) : + hsh( src.hsh ), + nPos( src.nPos ), + bFinished( src.bFinished ) + { + } + + bool isValid() const + { + return !bFinished; + } + + operator bool() const + { + return !bFinished; + } + + /** + * Iterator incrementation operator. Move the iterator forward. + */ + const_iterator operator++( int ) + { + if( bFinished == false ) + nPos = hsh->core->getNextPos( nPos, bFinished ); + + return *this; + } + + /** + * Iterator incrementation operator. Move the iterator forward. + */ + const_iterator operator++() + { + if( bFinished == false ) + nPos = hsh->core->getNextPos( nPos, bFinished ); + + return *this; + } + + /** + * Iterator equality comparison operator. Iterators the same? + */ + bool operator==( const const_iterator &oth ) const + { + if( bFinished != oth.bFinished ) + return false; + if( bFinished == true ) + { + return true; + } + else + { + if( oth.nPos == nPos ) + return true; + return false; + } + } + + /** + * Iterator not equality comparison operator. Not the same? + */ + bool operator!=( const const_iterator &oth ) const + { + return !(*this == oth ); + } + + /** + * Iterator assignment operator. + */ + const_iterator operator=( const const_iterator &oth ) + { + hsh = oth.hsh; + nPos = oth.nPos; + bFinished = oth.bFinished; + return *this; + } + + /** + * Iterator dereference operator... err.. get the value + *@returns (value_type &) The value behind this iterator. + */ + const value &operator *() const + { + return hsh->core->getValueAtPos( nPos ); + } + + /** + * Get the key behind this iterator. + *@returns (key_type &) The key behind this iterator. + */ + const key &getKey() const + { + return hsh->core->getKeyAtPos( nPos ); + } + + /** + * Get the value behind this iterator. + *@returns (value_type &) The value behind this iterator. + */ + const value &getValue() const + { + return hsh->core->getValueAtPos( nPos ); + } + } const_iterator; + + /** + * Get an iterator pointing to the first item in the hash table. + *@returns (iterator) An iterator pointing to the first item in the + * hash table. + */ + iterator begin() + { + return iterator( this ); + } + + const_iterator begin() const + { + return const_iterator( this ); + } + + /** + * Get an iterator pointing to a point just past the last item in the + * hash table. + *@returns (iterator) An iterator pointing to a point just past the + * last item in the hash table. + */ + iterator end() + { + return iterator( this, true ); + } + + const_iterator end() const + { + return const_iterator( this, true ); + } + + /** + * Get a list of all the keys in the hash table. + *@returns (std::list) The list of keys in the hash table. + */ + Bu::List getKeys() const + { + Bu::List lKeys; + + for( uint32_t j = 0; j < core->nCapacity; j++ ) + { + if( core->isFilled( j ) ) + { + if( !core->isDeleted( j ) ) + { + lKeys.append( core->aKeys[j] ); + } + } + } + + return lKeys; + } + + Bu::List getValues() const + { + Bu::List lValues; + + for( uint32_t j = 0; j < core->nCapacity; j++ ) + { + if( core->isFilled( j ) ) + { + if( !core->isDeleted( j ) ) + { + lValues.append( core->aValues[j] ); + } + } + } + + return lValues; + } + + bool operator==( const MyType &rhs ) const + { + if( this == &rhs ) + return true; + if( core == rhs.core ) + return true; + if( core == NULL || rhs.core == NULL ) + return false; + if( getSize() != rhs.getSize() ) + return false; + + for( uint32_t j = 0; j < core->nCapacity; j++ ) + { + if( core->isFilled( j ) ) + { + if( !core->isDeleted( j ) ) + { + // Check to see if this key is in the other hash + if( rhs.has( core->aKeys[j] ) ) + { + if( !(core->aValues[j] == rhs.get( core->aKeys[j]) ) ) + { + return false; + } + } + else + { + return false; + } + } + } + } + + return true; + } + + bool operator!=( const MyType &rhs ) const + { + return !(*this == rhs); + } + + MyType &operator+=( const MyType &rhs ) + { + if( this == &rhs ) + return *this; + if( core == rhs.core ) + return *this; + if( core == NULL || rhs.core == NULL ) + return *this; + + for( const_iterator i = rhs.begin(); i; i++ ) + insert( i.getKey(), i.getValue() ); + + return *this; + } + + protected: + virtual Core *_copyCore( Core *src ) + { + Core *pRet = _allocateCore(); + + pRet->nFilled = 0; + pRet->nDeleted = 0; + pRet->nCapacity = src->nCapacity; + pRet->nKeysSize = bitsTo( pRet->nCapacity ); + pRet->bFilled = pRet->ca.allocate( pRet->nKeysSize ); + pRet->bDeleted = pRet->ca.allocate( pRet->nKeysSize ); + pRet->clearBits(); + + pRet->aHashCodes = pRet->ca.allocate( pRet->nCapacity ); + pRet->aKeys = pRet->ka.allocate( pRet->nCapacity ); + pRet->aValues = pRet->va.allocate( pRet->nCapacity ); + + for( uint32_t j = 0; j < src->nCapacity; j++ ) + { + if( src->isFilled( j ) && !src->isDeleted( j ) ) + { + pRet->insert( src->aKeys[j], src->aValues[j] ); + } + } + + return pRet; + } + }; + + template uint32_t __calcHashCode( const T &k ) + { + return static_cast( k ); + } + + template bool __cmpHashKeys( const T &a, const T &b ) + { + return (a == b); + } + + template<> uint32_t __calcHashCode( const char * const &k ); + template<> bool __cmpHashKeys( const char * const &a, const char * const &b ); + + template<> uint32_t __calcHashCode( char * const &k ); + template<> bool __cmpHashKeys( char * const &a, char * const &b ); + + class Formatter; + Formatter &operator<<( Formatter &rOut, char *sStr ); + Formatter &operator<<( Formatter &rOut, signed char c ); + template + Formatter &operator<<( Formatter &f, const Bu::Hash &l ) + { + f << '{'; + for( typename Bu::Hash::const_iterator i = l.begin(); i; i++ ) + { + if( i != l.begin() ) + f << ", "; + f << i.getKey() << ": " << i.getValue(); + } + f << '}'; + + return f; + } + + template + ArchiveBase &operator<<( ArchiveBase &ar, const Hash &h ) + { + long iSize = h.getSize(); + ar << iSize; + for( typename Hash::const_iterator i = h.begin(); i != h.end(); i++ ) + { + ar << (i.getKey()); + ar << (i.getValue()); + } + + return ar; + } + + template + ArchiveBase &operator>>( ArchiveBase &ar, Hash &h ) + { + h.clear(); + long nSize; + ar >> nSize; + + for( long j = 0; j < nSize; j++ ) + { + key k; value v; + ar >> k >> v; + h.insert( k, v ); + } + + return ar; + } } #endif diff --git a/src/stable/heap.h b/src/stable/heap.h index a813f92..5033618 100644 --- a/src/stable/heap.h +++ b/src/stable/heap.h @@ -17,596 +17,596 @@ namespace Bu { - subExceptionDecl( HeapException ); - - template - class Heap; - - /** @cond DEVEL */ - template - class HeapCore - { - friend class Heap; - friend class SharedCore< - Heap, HeapCore - >; - private: - HeapCore() : - iSize( 0 ), - iFill( 0 ), - aItem( NULL ) - { - } - - virtual ~HeapCore() - { - clear(); - } - - void init() - { - if( iSize > 0 ) - return; - - iSize = 7; - iFill = 0; - aItem = ia.allocate( iSize ); - } - - void init( int iCap ) - { - if( iSize > 0 ) - return; - - for( iSize = 1; iSize < iCap; iSize=iSize*2+1 ) { } - iFill = 0; - aItem = ia.allocate( iSize ); - } - - void clear() - { - if( iSize == 0 ) - return; - - for( int j = 0; j < iFill; j++ ) - ia.destroy( &aItem[j] ); - ia.deallocate( aItem, iSize ); - aItem = NULL; - iSize = 0; - iFill = 0; - } - - void upSize() - { - if( iSize == 0 ) - { - init(); - return; - } - - item *aNewItems = ia.allocate( iSize*2+1 ); - // - // We cannot use a memcopy here because we don't know what kind - // of datastructures are being used, we have to copy them one at - // a time. - // - for( int j = 0; j < iFill; j++ ) - { - ia.construct( &aNewItems[j], aItem[j] ); - ia.destroy( &aItem[j] ); - } - ia.deallocate( aItem, iSize ); - aItem = aNewItems; - iSize = iSize*2+1; - } - - virtual void enqueue( const item &it ) - { - item i = it; // TODO: This is a silly workaround, put the i item - // at the end. - if( iFill+1 >= iSize ) - upSize(); - - for( int j = 0; j < iFill; ) - { - if( cmp( i, aItem[j] ) ) - { - Bu::swap( i, aItem[j] ); - } - - if( j*2+1 >= iFill ) - break; - if( cmp( i, aItem[j*2+1] ) ) - { - j = j*2+1; - } - else - { - j = j*2+2; - } - } - ia.construct( &aItem[iFill], i ); - if( iFill > 0 ) - { - for( int j = iFill; j >= 0; ) - { - int k = (j-1)/2; - if( j == k ) - break; - if( cmp( aItem[k], aItem[j] ) ) - break; - - Bu::swap( aItem[k], aItem[j] ); - j = k; - } - } - iFill++; - } - - virtual item dequeue() - { - if( iFill == 0 ) - throw HeapException("Heap empty."); - item iRet = aItem[0]; - int j; - for( j = 0; j < iFill; ) - { - int k = j*2+1; - if( k+1 < iFill && cmp( aItem[k+1], aItem[k] ) ) - { - if( k+1 < iFill-1 && cmp( aItem[iFill-1], aItem[k+1] ) ) - break; - aItem[j] = aItem[k+1]; - j = k+1; - } - else if( k < iFill ) - { - if( k < iFill-1 && cmp( aItem[iFill-1], aItem[k] ) ) - break; - aItem[j] = aItem[k]; - j = k; - } - else - break; - } - if( j < iFill-1 ) - aItem[j] = aItem[iFill-1]; - ia.destroy( &aItem[iFill-1] ); - iFill--; - - return iRet; - } - - private: - int iSize; - int iFill; - item *aItem; - cmpfunc cmp; - itemalloc ia; - }; - /** @endcond */ - - /** - * A priority queue that allows for an unlimited number of priorities. All - * objects enqueued must support less-than-comparison. Then every time an - * item is dequeued it is always the least item in the heap. The heap - * operates using a binary tree for storage, which allows most operations - * to be very fast. Enqueueing and dequeueing are both O(log(N)) operatoins - * whereas peeking is constant time. - * - * This heap implementation allows iterating, however please note that any - * enqueue or dequeue operation will invalidate the iterator and make it - * unusable (if it still works, you shouldn't trust the results). Also, - * the items are not stored in memory in order, they are optomized into a - * tree. This means that the items will be in effectively random order - * while iterating through them, and the order cannot be trusted. Also, - * modifying an item in the heap will not cause that item to be re-sorted. - * If you want to change the position of an item in the heap you will have - * to dequeue every item before it, dequeue that item, change it, and - * re-enqueue all of the items removed. - */ - template, typename itemalloc=std::allocator > - class Heap : public Queue, public SharedCore< - Heap, - HeapCore - > - { - private: - typedef class Heap MyType; - typedef class HeapCore Core; - - protected: - using SharedCore::core; - using SharedCore::_hardCopy; - using SharedCore::_resetCore; - using SharedCore::_allocateCore; - - public: - Heap() - { - } - - Heap( cmpfunc cmpin ) - { - core->cmp = cmpin; - } - - Heap( int iInitialCapacity ) - { - core->init( iInitialCapacity ); - } - - Heap( cmpfunc cmpin, int iInitialCapacity ) - { - core->cmp = cmpin; - core->init( iInitialCapacity ); - } - - Heap( const MyType &rSrc ) : - SharedCore( rSrc ) - { - } - - virtual ~Heap() - { - } - - virtual void enqueue( const item &it ) - { - _hardCopy(); - - core->enqueue( it ); - } - - virtual item &peek() - { - _hardCopy(); - - if( core->iFill == 0 ) - throw HeapException("Heap empty."); - return core->aItem[0]; - } - - virtual const item &peek() const - { - if( core->iFill == 0 ) - throw HeapException("Heap empty."); - return core->aItem[0]; - } - - virtual item dequeue() - { - _hardCopy(); - - return core->dequeue(); - } - - virtual bool isEmpty() const - { - return (core->iFill==0); - } - - virtual int getSize() const - { - return core->iFill; - } - - class iterator - { - friend class const_iterator; - friend class Heap; - private: - Heap *pHeap; - int iIndex; - - iterator( Heap *pHeap, int iIndex ) : - pHeap( pHeap ), iIndex( iIndex ) - { - } - - void checkValid() - { - if( pHeap == NULL ) - throw Bu::ExceptionBase("Iterator not initialized."); - if( iIndex < 0 || iIndex >= pHeap->core->iFill ) - throw Bu::ExceptionBase("Iterator out of bounds."); - } - - public: - iterator() : - pHeap( NULL ), - iIndex( -1 ) - { - } - - iterator( const iterator &i ) : - pHeap( i.pHeap ), - iIndex( i.iIndex ) - { - } - - bool operator==( const iterator &oth ) const - { - return (oth.pHeap == pHeap) && (oth.iIndex == iIndex); - } - - bool operator!=( const iterator &oth ) const - { - return (oth.pHeap != pHeap) || (oth.iIndex != iIndex); - } - - item &operator*() - { - pHeap->_hardCopy(); - - return pHeap->core->aItem[iIndex]; - } - - item *operator->() - { - pHeap->_hardCopy(); - - return &(pHeap->core->aItem[iIndex]); - } - - iterator &operator++() - { - checkValid(); - iIndex++; - if( iIndex >= pHeap->iFill ) - iIndex = -1; - - return *this; - } - - iterator &operator--() - { - checkValid(); - iIndex--; - - return *this; - } - - iterator &operator++( int ) - { - checkValid(); - iIndex++; - if( iIndex >= pHeap->core->iFill ) - iIndex = -1; - - return *this; - } - - iterator &operator--( int ) - { - checkValid(); - iIndex--; - - return *this; - } - - iterator operator+( int iDelta ) - { - checkValid(); - iterator ret( *this ); - ret.iIndex += iDelta; - if( ret.iIndex >= pHeap->core->iFill ) - ret.iIndex = -1; - return ret; - } - - iterator operator-( int iDelta ) - { - checkValid(); - iterator ret( *this ); - ret.iIndex -= iDelta; - if( ret.iIndex < 0 ) - ret.iIndex = -1; - return ret; - } - - operator bool() const - { - return iIndex != -1; - } - - bool isValid() const - { - return iIndex != -1; - } - - iterator &operator=( const iterator &oth ) - { - pHeap = oth.pHeap; - iIndex = oth.iIndex; - } - }; - - class const_iterator - { - friend class Heap; - private: - Heap *pHeap; - int iIndex; - - const_iterator( Heap *pHeap, - int iIndex ) : - pHeap( pHeap ), iIndex( iIndex ) - { - } - - void checkValid() - { - if( pHeap == NULL ) - throw Bu::ExceptionBase("Iterator not initialized."); - if( iIndex < 0 || iIndex >= pHeap->core->iFill ) - throw Bu::ExceptionBase("Iterator out of bounds."); - } - - public: - const_iterator() : - pHeap( NULL ), - iIndex( -1 ) - { - } - - const_iterator( const const_iterator &i ) : - pHeap( i.pHeap ), - iIndex( i.iIndex ) - { - } - - const_iterator( const iterator &i ) : - pHeap( i.pHeap ), - iIndex( i.iIndex ) - { - } - - bool operator==( const const_iterator &oth ) const - { - return (oth.pHeap == pHeap) && (oth.iIndex == iIndex); - } - - bool operator!=( const const_iterator &oth ) const - { - return (oth.pHeap != pHeap) || (oth.iIndex != iIndex); - } - - const item &operator*() - { - pHeap->_hardCopy(); - - return pHeap->core->aItem[iIndex]; - } - - const item *operator->() - { - pHeap->_hardCopy(); - - return &(pHeap->core->aItem[iIndex]); - } - - const_iterator &operator++() - { - checkValid(); - iIndex++; - if( iIndex >= pHeap->core->iFill ) - iIndex = -1; - - return *this; - } - - const_iterator &operator--() - { - checkValid(); - iIndex--; - - return *this; - } - - const_iterator &operator++( int ) - { - checkValid(); - iIndex++; - if( iIndex >= pHeap->core->iFill ) - iIndex = -1; - - return *this; - } - - const_iterator &operator--( int ) - { - checkValid(); - iIndex--; - - return *this; - } - - const_iterator operator+( int iDelta ) - { - checkValid(); - const_iterator ret( *this ); - ret.iIndex += iDelta; - if( ret.iIndex >= pHeap->iFill ) - ret.iIndex = -1; - return ret; - } - - const_iterator operator-( int iDelta ) - { - checkValid(); - const_iterator ret( *this ); - ret.iIndex -= iDelta; - if( ret.iIndex < 0 ) - ret.iIndex = -1; - return ret; - } - - operator bool() const - { - return iIndex != -1; - } - - bool isValid() const - { - return iIndex != -1; - } - - const_iterator &operator=( const const_iterator &oth ) - { - pHeap = oth.pHeap; - iIndex = oth.iIndex; - } - - const_iterator &operator=( const iterator &oth ) - { - pHeap = oth.pHeap; - iIndex = oth.iIndex; - } - }; - - iterator begin() - { - if( core->iFill == 0 ) - return end(); - return iterator( this, 0 ); - } - - const_iterator begin() const - { - if( core->iFill == 0 ) - return end(); - return const_iterator( this, 0 ); - } - - iterator end() - { - return iterator( this, -1 ); - } - - const_iterator end() const - { - return const_iterator( this, -1 ); - } - - - protected: - virtual Core *_copyCore( Core *src ) - { - Core *pRet = _allocateCore(); - - pRet->iSize = src->iSize; - pRet->iFill = src->iFill; - pRet->cmp = src->cmp; - pRet->aItem = pRet->ia.allocate( pRet->iSize ); - for( int j = 0; j < pRet->iFill; j++ ) - { - pRet->ia.construct( &pRet->aItem[j], src->aItem[j] ); - } - - return pRet; - } - }; + subExceptionDecl( HeapException ); + + template + class Heap; + + /** @cond DEVEL */ + template + class HeapCore + { + friend class Heap; + friend class SharedCore< + Heap, HeapCore + >; + private: + HeapCore() : + iSize( 0 ), + iFill( 0 ), + aItem( NULL ) + { + } + + virtual ~HeapCore() + { + clear(); + } + + void init() + { + if( iSize > 0 ) + return; + + iSize = 7; + iFill = 0; + aItem = ia.allocate( iSize ); + } + + void init( int iCap ) + { + if( iSize > 0 ) + return; + + for( iSize = 1; iSize < iCap; iSize=iSize*2+1 ) { } + iFill = 0; + aItem = ia.allocate( iSize ); + } + + void clear() + { + if( iSize == 0 ) + return; + + for( int j = 0; j < iFill; j++ ) + ia.destroy( &aItem[j] ); + ia.deallocate( aItem, iSize ); + aItem = NULL; + iSize = 0; + iFill = 0; + } + + void upSize() + { + if( iSize == 0 ) + { + init(); + return; + } + + item *aNewItems = ia.allocate( iSize*2+1 ); + // + // We cannot use a memcopy here because we don't know what kind + // of datastructures are being used, we have to copy them one at + // a time. + // + for( int j = 0; j < iFill; j++ ) + { + ia.construct( &aNewItems[j], aItem[j] ); + ia.destroy( &aItem[j] ); + } + ia.deallocate( aItem, iSize ); + aItem = aNewItems; + iSize = iSize*2+1; + } + + virtual void enqueue( const item &it ) + { + item i = it; // TODO: This is a silly workaround, put the i item + // at the end. + if( iFill+1 >= iSize ) + upSize(); + + for( int j = 0; j < iFill; ) + { + if( cmp( i, aItem[j] ) ) + { + Bu::swap( i, aItem[j] ); + } + + if( j*2+1 >= iFill ) + break; + if( cmp( i, aItem[j*2+1] ) ) + { + j = j*2+1; + } + else + { + j = j*2+2; + } + } + ia.construct( &aItem[iFill], i ); + if( iFill > 0 ) + { + for( int j = iFill; j >= 0; ) + { + int k = (j-1)/2; + if( j == k ) + break; + if( cmp( aItem[k], aItem[j] ) ) + break; + + Bu::swap( aItem[k], aItem[j] ); + j = k; + } + } + iFill++; + } + + virtual item dequeue() + { + if( iFill == 0 ) + throw HeapException("Heap empty."); + item iRet = aItem[0]; + int j; + for( j = 0; j < iFill; ) + { + int k = j*2+1; + if( k+1 < iFill && cmp( aItem[k+1], aItem[k] ) ) + { + if( k+1 < iFill-1 && cmp( aItem[iFill-1], aItem[k+1] ) ) + break; + aItem[j] = aItem[k+1]; + j = k+1; + } + else if( k < iFill ) + { + if( k < iFill-1 && cmp( aItem[iFill-1], aItem[k] ) ) + break; + aItem[j] = aItem[k]; + j = k; + } + else + break; + } + if( j < iFill-1 ) + aItem[j] = aItem[iFill-1]; + ia.destroy( &aItem[iFill-1] ); + iFill--; + + return iRet; + } + + private: + int iSize; + int iFill; + item *aItem; + cmpfunc cmp; + itemalloc ia; + }; + /** @endcond */ + + /** + * A priority queue that allows for an unlimited number of priorities. All + * objects enqueued must support less-than-comparison. Then every time an + * item is dequeued it is always the least item in the heap. The heap + * operates using a binary tree for storage, which allows most operations + * to be very fast. Enqueueing and dequeueing are both O(log(N)) operatoins + * whereas peeking is constant time. + * + * This heap implementation allows iterating, however please note that any + * enqueue or dequeue operation will invalidate the iterator and make it + * unusable (if it still works, you shouldn't trust the results). Also, + * the items are not stored in memory in order, they are optomized into a + * tree. This means that the items will be in effectively random order + * while iterating through them, and the order cannot be trusted. Also, + * modifying an item in the heap will not cause that item to be re-sorted. + * If you want to change the position of an item in the heap you will have + * to dequeue every item before it, dequeue that item, change it, and + * re-enqueue all of the items removed. + */ + template, typename itemalloc=std::allocator > + class Heap : public Queue, public SharedCore< + Heap, + HeapCore + > + { + private: + typedef class Heap MyType; + typedef class HeapCore Core; + + protected: + using SharedCore::core; + using SharedCore::_hardCopy; + using SharedCore::_resetCore; + using SharedCore::_allocateCore; + + public: + Heap() + { + } + + Heap( cmpfunc cmpin ) + { + core->cmp = cmpin; + } + + Heap( int iInitialCapacity ) + { + core->init( iInitialCapacity ); + } + + Heap( cmpfunc cmpin, int iInitialCapacity ) + { + core->cmp = cmpin; + core->init( iInitialCapacity ); + } + + Heap( const MyType &rSrc ) : + SharedCore( rSrc ) + { + } + + virtual ~Heap() + { + } + + virtual void enqueue( const item &it ) + { + _hardCopy(); + + core->enqueue( it ); + } + + virtual item &peek() + { + _hardCopy(); + + if( core->iFill == 0 ) + throw HeapException("Heap empty."); + return core->aItem[0]; + } + + virtual const item &peek() const + { + if( core->iFill == 0 ) + throw HeapException("Heap empty."); + return core->aItem[0]; + } + + virtual item dequeue() + { + _hardCopy(); + + return core->dequeue(); + } + + virtual bool isEmpty() const + { + return (core->iFill==0); + } + + virtual int getSize() const + { + return core->iFill; + } + + class iterator + { + friend class const_iterator; + friend class Heap; + private: + Heap *pHeap; + int iIndex; + + iterator( Heap *pHeap, int iIndex ) : + pHeap( pHeap ), iIndex( iIndex ) + { + } + + void checkValid() + { + if( pHeap == NULL ) + throw Bu::ExceptionBase("Iterator not initialized."); + if( iIndex < 0 || iIndex >= pHeap->core->iFill ) + throw Bu::ExceptionBase("Iterator out of bounds."); + } + + public: + iterator() : + pHeap( NULL ), + iIndex( -1 ) + { + } + + iterator( const iterator &i ) : + pHeap( i.pHeap ), + iIndex( i.iIndex ) + { + } + + bool operator==( const iterator &oth ) const + { + return (oth.pHeap == pHeap) && (oth.iIndex == iIndex); + } + + bool operator!=( const iterator &oth ) const + { + return (oth.pHeap != pHeap) || (oth.iIndex != iIndex); + } + + item &operator*() + { + pHeap->_hardCopy(); + + return pHeap->core->aItem[iIndex]; + } + + item *operator->() + { + pHeap->_hardCopy(); + + return &(pHeap->core->aItem[iIndex]); + } + + iterator &operator++() + { + checkValid(); + iIndex++; + if( iIndex >= pHeap->iFill ) + iIndex = -1; + + return *this; + } + + iterator &operator--() + { + checkValid(); + iIndex--; + + return *this; + } + + iterator &operator++( int ) + { + checkValid(); + iIndex++; + if( iIndex >= pHeap->core->iFill ) + iIndex = -1; + + return *this; + } + + iterator &operator--( int ) + { + checkValid(); + iIndex--; + + return *this; + } + + iterator operator+( int iDelta ) + { + checkValid(); + iterator ret( *this ); + ret.iIndex += iDelta; + if( ret.iIndex >= pHeap->core->iFill ) + ret.iIndex = -1; + return ret; + } + + iterator operator-( int iDelta ) + { + checkValid(); + iterator ret( *this ); + ret.iIndex -= iDelta; + if( ret.iIndex < 0 ) + ret.iIndex = -1; + return ret; + } + + operator bool() const + { + return iIndex != -1; + } + + bool isValid() const + { + return iIndex != -1; + } + + iterator &operator=( const iterator &oth ) + { + pHeap = oth.pHeap; + iIndex = oth.iIndex; + } + }; + + class const_iterator + { + friend class Heap; + private: + Heap *pHeap; + int iIndex; + + const_iterator( Heap *pHeap, + int iIndex ) : + pHeap( pHeap ), iIndex( iIndex ) + { + } + + void checkValid() + { + if( pHeap == NULL ) + throw Bu::ExceptionBase("Iterator not initialized."); + if( iIndex < 0 || iIndex >= pHeap->core->iFill ) + throw Bu::ExceptionBase("Iterator out of bounds."); + } + + public: + const_iterator() : + pHeap( NULL ), + iIndex( -1 ) + { + } + + const_iterator( const const_iterator &i ) : + pHeap( i.pHeap ), + iIndex( i.iIndex ) + { + } + + const_iterator( const iterator &i ) : + pHeap( i.pHeap ), + iIndex( i.iIndex ) + { + } + + bool operator==( const const_iterator &oth ) const + { + return (oth.pHeap == pHeap) && (oth.iIndex == iIndex); + } + + bool operator!=( const const_iterator &oth ) const + { + return (oth.pHeap != pHeap) || (oth.iIndex != iIndex); + } + + const item &operator*() + { + pHeap->_hardCopy(); + + return pHeap->core->aItem[iIndex]; + } + + const item *operator->() + { + pHeap->_hardCopy(); + + return &(pHeap->core->aItem[iIndex]); + } + + const_iterator &operator++() + { + checkValid(); + iIndex++; + if( iIndex >= pHeap->core->iFill ) + iIndex = -1; + + return *this; + } + + const_iterator &operator--() + { + checkValid(); + iIndex--; + + return *this; + } + + const_iterator &operator++( int ) + { + checkValid(); + iIndex++; + if( iIndex >= pHeap->core->iFill ) + iIndex = -1; + + return *this; + } + + const_iterator &operator--( int ) + { + checkValid(); + iIndex--; + + return *this; + } + + const_iterator operator+( int iDelta ) + { + checkValid(); + const_iterator ret( *this ); + ret.iIndex += iDelta; + if( ret.iIndex >= pHeap->iFill ) + ret.iIndex = -1; + return ret; + } + + const_iterator operator-( int iDelta ) + { + checkValid(); + const_iterator ret( *this ); + ret.iIndex -= iDelta; + if( ret.iIndex < 0 ) + ret.iIndex = -1; + return ret; + } + + operator bool() const + { + return iIndex != -1; + } + + bool isValid() const + { + return iIndex != -1; + } + + const_iterator &operator=( const const_iterator &oth ) + { + pHeap = oth.pHeap; + iIndex = oth.iIndex; + } + + const_iterator &operator=( const iterator &oth ) + { + pHeap = oth.pHeap; + iIndex = oth.iIndex; + } + }; + + iterator begin() + { + if( core->iFill == 0 ) + return end(); + return iterator( this, 0 ); + } + + const_iterator begin() const + { + if( core->iFill == 0 ) + return end(); + return const_iterator( this, 0 ); + } + + iterator end() + { + return iterator( this, -1 ); + } + + const_iterator end() const + { + return const_iterator( this, -1 ); + } + + + protected: + virtual Core *_copyCore( Core *src ) + { + Core *pRet = _allocateCore(); + + pRet->iSize = src->iSize; + pRet->iFill = src->iFill; + pRet->cmp = src->cmp; + pRet->aItem = pRet->ia.allocate( pRet->iSize ); + for( int j = 0; j < pRet->iFill; j++ ) + { + pRet->ia.construct( &pRet->aItem[j], src->aItem[j] ); + } + + return pRet; + } + }; }; #endif diff --git a/src/stable/hex.cpp b/src/stable/hex.cpp index 3e6a22e..45679b5 100644 --- a/src/stable/hex.cpp +++ b/src/stable/hex.cpp @@ -8,11 +8,11 @@ #include "bu/hex.h" Bu::Hex::Hex( Bu::Stream &rNext, bool bUpperCase, int iChunk ) : - Bu::Filter( rNext ), - iChunk( iChunk ), - iPos( 0 ), - iIn( 0 ), - sChrs(bUpperCase?"0123456789ABCDEF":"0123456789abcdef") + Bu::Filter( rNext ), + iChunk( iChunk ), + iPos( 0 ), + iIn( 0 ), + sChrs(bUpperCase?"0123456789ABCDEF":"0123456789abcdef") { } @@ -22,48 +22,48 @@ Bu::Hex::~Hex() void Bu::Hex::start() { - iPos = iIn = 0; + iPos = iIn = 0; } Bu::size Bu::Hex::stop() { - return iPos; + return iPos; } Bu::size Bu::Hex::read( void *pBuf, Bu::size iBytes ) { - Bu::size j; - uint8_t *puBuf = (uint8_t *)pBuf; - for( j = 0; j < iBytes; j++ ) - { - for(; iIn < 2; iIn++ ) - { - if( rNext.read( &cIn[iIn], 1 ) == 0 ) - return j; - if( cIn[iIn] == ' ' || cIn[iIn] == '\t' || - cIn[iIn] == '\n' || cIn[iIn] == '\r' ) - iIn--; - } + Bu::size j; + uint8_t *puBuf = (uint8_t *)pBuf; + for( j = 0; j < iBytes; j++ ) + { + for(; iIn < 2; iIn++ ) + { + if( rNext.read( &cIn[iIn], 1 ) == 0 ) + return j; + if( cIn[iIn] == ' ' || cIn[iIn] == '\t' || + cIn[iIn] == '\n' || cIn[iIn] == '\r' ) + iIn--; + } #define chr2nibble( c ) ((c>='0'&&c<='9')?(c-'0'):((c|0x60)-'a'+10)) - puBuf[j] = ((chr2nibble(cIn[0])<<4)|chr2nibble(cIn[1])); - iIn = 0; - } - return j; + puBuf[j] = ((chr2nibble(cIn[0])<<4)|chr2nibble(cIn[1])); + iIn = 0; + } + return j; } Bu::size Bu::Hex::write( const void *pBuf, Bu::size iBytes ) { - char cOut[2]; - uint8_t *puBuf = (uint8_t *)pBuf; - for( Bu::size j = 0; j < iBytes; j++ ) - { - cOut[0] = sChrs[(puBuf[j]&0xf0)>>4]; - cOut[1] = sChrs[(puBuf[j]&0x0f)]; - if( iChunk > 0 && iPos%iChunk == 0 && iPos>0 ) - rNext.write(" ", 1 ); - rNext.write( cOut, 2 ); - iPos++; - } - return iBytes; + char cOut[2]; + uint8_t *puBuf = (uint8_t *)pBuf; + for( Bu::size j = 0; j < iBytes; j++ ) + { + cOut[0] = sChrs[(puBuf[j]&0xf0)>>4]; + cOut[1] = sChrs[(puBuf[j]&0x0f)]; + if( iChunk > 0 && iPos%iChunk == 0 && iPos>0 ) + rNext.write(" ", 1 ); + rNext.write( cOut, 2 ); + iPos++; + } + return iBytes; } diff --git a/src/stable/hex.h b/src/stable/hex.h index a89e93d..c010173 100644 --- a/src/stable/hex.h +++ b/src/stable/hex.h @@ -12,46 +12,46 @@ namespace Bu { - /** - * This very simple filter encodes to/decodes from hex encoded string data. - * The primary use of this filter is in debugging, use it with - * Bu::encodeStr to easily create hex dumps of string data, even other raw - * structures. - * - *@code - Bu::println("Hexdump: " + Bu::encodeStr("Test data ;)") ); - @endcode - * Or... - *@code - complex_struct data; - ... - Bu::println("Hexdump: " + - Bu::encodeStr( - Bu::String( &data, sizeof(data) ) - ) - ); - @endcode - **/ - class Hex : public Bu::Filter - { - public: - Hex( Bu::Stream &rNext, bool bUpperCase=false, int iChunk=-1 ); - virtual ~Hex(); + /** + * This very simple filter encodes to/decodes from hex encoded string data. + * The primary use of this filter is in debugging, use it with + * Bu::encodeStr to easily create hex dumps of string data, even other raw + * structures. + * + *@code + Bu::println("Hexdump: " + Bu::encodeStr("Test data ;)") ); + @endcode + * Or... + *@code + complex_struct data; + ... + Bu::println("Hexdump: " + + Bu::encodeStr( + Bu::String( &data, sizeof(data) ) + ) + ); + @endcode + **/ + class Hex : public Bu::Filter + { + public: + Hex( Bu::Stream &rNext, bool bUpperCase=false, int iChunk=-1 ); + virtual ~Hex(); - virtual void start(); - virtual Bu::size stop(); + virtual void start(); + virtual Bu::size stop(); - virtual Bu::size read( void *pBuf, Bu::size iBytes ); - virtual Bu::size write( const void *pBuf, Bu::size iBytes ); - using Bu::Stream::write; + virtual Bu::size read( void *pBuf, Bu::size iBytes ); + virtual Bu::size write( const void *pBuf, Bu::size iBytes ); + using Bu::Stream::write; - private: - int iChunk; - Bu::size iPos; - char cIn[2]; - int iIn; - const char *sChrs; - }; + private: + int iChunk; + Bu::size iPos; + char cIn[2]; + int iIn; + const char *sChrs; + }; }; #endif diff --git a/src/stable/list.h b/src/stable/list.h index 4f9d4aa..b7fb1d1 100644 --- a/src/stable/list.h +++ b/src/stable/list.h @@ -16,1022 +16,1022 @@ namespace Bu { - /** @cond DEVEL */ - template - struct ListLink - { - value *pValue; - ListLink *pNext; - ListLink *pPrev; - }; - - template - class List; - - template - struct ListCore - { - friend class List; - friend class SharedCore< - List, - ListCore - >; - private: - typedef struct ListLink Link; - ListCore() : - pFirst( NULL ), - pLast( NULL ), - nSize( 0 ) - { } - - virtual ~ListCore() - { - clear(); - } - - Link *pFirst; - Link *pLast; - long nSize; - linkalloc la; - valuealloc va; - - /** - * Append a value to the list. - *@param v (const value_type &) The value to append. - */ - Link *append( const value &v ) - { - Link *pNew = la.allocate( 1 ); - pNew->pValue = va.allocate( 1 ); - va.construct( pNew->pValue, v ); - nSize++; - if( pFirst == NULL ) - { - // Empty list - pFirst = pLast = pNew; - pNew->pNext = pNew->pPrev = NULL; - } - else - { - pNew->pNext = NULL; - pNew->pPrev = pLast; - pLast->pNext = pNew; - pLast = pNew; - } - return pNew; - } - - /** - * Prepend a value to the list. - *@param v (const value_type &) The value to prepend. - */ - Link *prepend( const value &v ) - { - Link *pNew = la.allocate( 1 ); - pNew->pValue = va.allocate( 1 ); - va.construct( pNew->pValue, v ); - nSize++; - if( pFirst == NULL ) - { - // Empty list - pFirst = pLast = pNew; - pNew->pNext = pNew->pPrev = NULL; - } - else - { - pNew->pNext = pFirst; - pNew->pPrev = NULL; - pFirst->pPrev = pNew; - pFirst = pNew; - } - return pNew; - } - - void clear() - { - Link *pCur = pFirst; - for(;;) - { - if( pCur == NULL ) break; - va.destroy( pCur->pValue ); - va.deallocate( pCur->pValue, 1 ); - Link *pTmp = pCur->pNext; - la.destroy( pCur ); - la.deallocate( pCur, 1 ); - pCur = pTmp; - } - pFirst = pLast = NULL; - nSize = 0; - } - - Link *insert( Link *pLink, const value &v ) - { - Link *pAfter = pLink; - if( pAfter == NULL ) - { - return append( v ); - } - Link *pPrev = pAfter->pPrev; - if( pPrev == NULL ) - { - return prepend( v ); - } - - Link *pNew = la.allocate( 1 ); - pNew->pValue = va.allocate( 1 ); - va.construct( pNew->pValue, v ); - nSize++; - - pNew->pNext = pAfter; - pNew->pPrev = pPrev; - pAfter->pPrev = pNew; - pPrev->pNext = pNew; - - return pNew; - } - - /** - * Erase an item from the list. - *@param i (iterator) The item to erase. - */ - void erase( Link *pLink ) - { - Link *pCur = pLink; - if( pCur == NULL ) return; - Link *pPrev = pCur->pPrev; - if( pPrev == NULL ) - { - va.destroy( pCur->pValue ); - va.deallocate( pCur->pValue, 1 ); - pFirst = pCur->pNext; - la.destroy( pCur ); - la.deallocate( pCur, 1 ); - if( pFirst == NULL ) - pLast = NULL; - else - pFirst->pPrev = NULL; - nSize--; - } - else - { - va.destroy( pCur->pValue ); - va.deallocate( pCur->pValue, 1 ); - Link *pTmp = pCur->pNext; - la.destroy( pCur ); - la.deallocate( pCur, 1 ); - pPrev->pNext = pTmp; - if( pTmp != NULL ) - pTmp->pPrev = pPrev; - else - pLast = pPrev; - nSize--; - } - } - }; - /** @endcond */ - - /** - * Linked list template container. This class is similar to the stl list - * class except for a few minor changes. First, when const, all - * members are only accessable const. Second, erasing a location does not - * invalidate the iterator used, it simply points to the next valid - * location, or end() if there are no more. Other iterators pointing to - * the deleted record will, of course, no longer be valid. - * - *@param value (typename) The type of data to store in your list - *@param valuealloc (typename) Memory Allocator for your value type - *@param linkalloc (typename) Memory Allocator for the list links. - *@extends SharedCore - *@ingroup Containers - */ - template, - typename linkalloc=std::allocator > > - class List /** @cond */ : public SharedCore< - List, - ListCore - > /** @endcond */ - { - private: - typedef struct ListLink Link; - typedef class List MyType; - typedef struct ListCore Core; - - protected: - using SharedCore::core; - using SharedCore::_hardCopy; - using SharedCore::_allocateCore; - - public: - struct const_iterator; - struct iterator; - - List() - { - } - - List( const MyType &src ) : - SharedCore( src ) - { - } - - List( const value &v ) - { - append( v ); - } - - ~List() - { - } - - MyType &operator+=( const value &v ) - { - _hardCopy(); - append( v ); - return *this; - } - - MyType &operator+=( const MyType &src ) - { - _hardCopy(); - append( src ); - return *this; - } - - MyType operator+( const MyType &src ) - { - MyType lNew( *this ); - lNew += src; - return lNew; - } - - bool operator==( const MyType &rhs ) const - { - if( getSize() != rhs.getSize() ) - return false; - - for( typename MyType::const_iterator a = begin(), b = rhs.begin(); - a; a++, b++ ) - { - if( *a != *b ) - return false; - } - - return true; - } - - bool operator!=( const MyType &rhs ) const - { - return !(*this == rhs); - } - - /** - * Clear the data from the list. - */ - void clear() - { - _hardCopy(); - core->clear(); - } - - MyType &enqueue( const value &v ) - { - _hardCopy(); - append( v ); - - return *this; - } - - value dequeue() - { - // _hardCopy(); erase will call this for me - value v = *core->pFirst->pValue; - - erase( begin() ); - - return v; - } - - MyType &push( const value &v ) - { - _hardCopy(); - prepend( v ); - - return *this; - } - - MyType &pop() - { - _hardCopy(); - erase( begin() ); - - return *this; - } - - value peekPop() - { - value v = first(); - pop(); - return v; - } - - value &peek() - { - return first(); - } - - /** - * Append a value to the list. - *@param v (const value_type &) The value to append. - */ - MyType &append( const value &v ) - { - _hardCopy(); - core->append( v ); - - return *this; - } - - MyType &append( const MyType &rSrc ) - { - _hardCopy(); - for( typename MyType::const_iterator i = rSrc.begin(); - i != rSrc.end(); i++ ) - { - core->append( *i ); - } - - return *this; - } - - /** - * Prepend a value to the list. - *@param v (const value_type &) The value to prepend. - */ - MyType &prepend( const value &v ) - { - _hardCopy(); - core->prepend( v ); - - return *this; - } - - /** - * Prepend another list to the front of this one. This will prepend - * the rSrc list in reverse order...I may fix that later. - */ - MyType &prepend( const MyType &rSrc ) - { - _hardCopy(); - for( typename MyType::const_iterator i = rSrc.begin(); - i != rSrc.end(); i++ ) - { - core->prepend( *i ); - } - - return *this; - } - - MyType &insert( MyType::iterator &i, const value &v ) - { - _hardCopy(); - - core->insert( i.pLink, v ); - - return *this; - } - - template - void sort( cmptype cmp ) - { - Heap hSort( cmp, getSize() ); - for( typename MyType::iterator i = begin(); i; i++ ) - { - hSort.enqueue( *i ); - } - clear(); - while( !hSort.isEmpty() ) - { - append( hSort.dequeue() ); - } - } - - void sort() - { - sort<__basicLTCmp >(); - } - - template - void sort() - { - Heap hSort( getSize() ); - for( typename MyType::iterator i = begin(); i; i++ ) - { - hSort.enqueue( *i ); - } - clear(); - while( !hSort.isEmpty() ) - { - append( hSort.dequeue() ); - } - } - - /** - * Insert a new item in sort order by searching for the first item that - * is larger and inserting this before it, or at the end if none are - * larger. If this is the only function used to insert data in the - * List all items will be sorted. To use this, the value type must - * support the > operator. - */ - template - iterator insertSorted( cmptype cmp, const value &v ) - { - _hardCopy(); - if( core->pFirst == NULL ) - { - // Empty list - return iterator( core->append( v ) ); - } - else - { - Link *pCur = core->pFirst; - for(;;) - { - if( cmp( v, *(pCur->pValue)) ) - { - return iterator( core->insert( pCur, v ) ); - } - pCur = pCur->pNext; - if( pCur == NULL ) - { - return iterator( core->append( v ) ); - } - } - } - } - - iterator insertSorted( const value &v ) - { - return insertSorted<__basicLTCmp >( v ); - } - - template - iterator insertSorted( const value &v ) - { - cmptype cmp; - return insertSorted( cmp, v ); - } - - /** - * An iterator to iterate through your list. - */ - typedef struct iterator - { - friend struct const_iterator; - friend class List; - private: - Link *pLink; - - iterator( Link *pLink ) : - pLink( pLink ) - { - } - - public: - iterator() : - pLink( NULL ) - { - } - - iterator( const iterator &i ) : - pLink( i.pLink ) - { - } - - /** - * Equals comparison operator. - *@param oth (const iterator &) The iterator to compare to. - *@returns (bool) Are they equal? - */ - bool operator==( const iterator &oth ) const - { - return ( pLink == oth.pLink ); - } - - /** - * Equals comparison operator. - *@param pOth (const Link *) The link to compare to. - *@returns (bool) Are they equal? - */ - bool operator==( const Link *pOth ) const - { - return ( pLink == pOth ); - } - - /** - * Not equals comparison operator. - *@param oth (const iterator &) The iterator to compare to. - *@returns (bool) Are they not equal? - */ - bool operator!=( const iterator &oth ) const - { - return ( pLink != oth.pLink ); - } - - /** - * Not equals comparison operator. - *@param pOth (const Link *) The link to compare to. - *@returns (bool) Are they not equal? - */ - bool operator!=( const Link *pOth ) const - { - return ( pLink != pOth ); - } - - /** - * Dereference operator. - *@returns (value_type &) The value. - */ - value &operator*() - { - return *(pLink->pValue); - } - - /** - * Pointer access operator. - *@returns (value_type *) A pointer to the value. - */ - value *operator->() - { - return pLink->pValue; - } - - iterator &operator++() - { - if( pLink == NULL ) - throw Bu::ExceptionBase( - "Attempt to iterate past end of list."); - pLink = pLink->pNext; - return *this; - } - - iterator &operator--() - { - if( pLink == NULL ) - throw Bu::ExceptionBase( - "Attempt to iterate past begining of list."); - pLink = pLink->pPrev; - return *this; - } - - iterator &operator++( int ) - { - if( pLink == NULL ) - throw Bu::ExceptionBase( - "Attempt to iterate past end of list."); - pLink = pLink->pNext; - return *this; - } - - iterator &operator--( int ) - { - if( pLink == NULL ) - throw Bu::ExceptionBase( - "Attempt to iterate past begining of list."); - pLink = pLink->pPrev; - return *this; - } - - iterator operator+( int iDelta ) - { - iterator ret( *this ); - for( int j = 0; j < iDelta; j++ ) - { - if( ret.pLink == NULL ) - throw Bu::ExceptionBase( - "Attempt to iterate past begining of list."); - ret.pLink = ret.pLink->pNext; - } - return ret; - } - - iterator operator-( int iDelta ) - { - iterator ret( *this ); - for( int j = 0; j < iDelta; j++ ) - { - if( ret.pLink == NULL ) - throw Bu::ExceptionBase( - "Attempt to iterate past begining of list."); - ret.pLink = ret.pLink->pPrev; - } - return ret; - } - - operator bool() - { - return pLink != NULL; - } - - bool isValid() - { - return pLink != NULL; - } - - /** - * Assignment operator. - *@param oth (const iterator &) The other iterator to set this - * one to. - */ - iterator &operator=( const iterator &oth ) - { - pLink = oth.pLink; - return *this; - } - } iterator; - - /** - *@see iterator - */ - typedef struct const_iterator - { - friend class List; - private: - Link *pLink; - - const_iterator( Link *pLink ) : - pLink( pLink ) - { - } - - public: - const_iterator() : - pLink( NULL ) - { - } - - const_iterator( const iterator &i ) : - pLink( i.pLink ) - { - } - - bool operator==( const const_iterator &oth ) const - { - return ( pLink == oth.pLink ); - } - - bool operator==( const Link *pOth ) const - { - return ( pLink == pOth ); - } - - bool operator!=( const const_iterator &oth ) const - { - return ( pLink != oth.pLink ); - } - - bool operator!=( const Link *pOth ) const - { - return ( pLink != pOth ); - } - - const value &operator*() - { - return *(pLink->pValue); - } - - const value *operator->() - { - return pLink->pValue; - } - - const_iterator &operator++() - { - if( pLink == NULL ) - throw Bu::ExceptionBase( - "Attempt to iterate past end of list."); - pLink = pLink->pNext; - return *this; - } - - const_iterator &operator--() - { - if( pLink == NULL ) - throw Bu::ExceptionBase( - "Attempt to iterate past begining of list."); - pLink = pLink->pPrev; - return *this; - } - - const_iterator &operator++( int ) - { - if( pLink == NULL ) - throw Bu::ExceptionBase( - "Attempt to iterate past end of list."); - pLink = pLink->pNext; - return *this; - } - - const_iterator &operator--( int ) - { - if( pLink == NULL ) - throw Bu::ExceptionBase( - "Attempt to iterate past begining of list."); - pLink = pLink->pPrev; - return *this; - } - - const_iterator operator+( int iDelta ) - { - const_iterator ret( *this ); - for( int j = 0; j < iDelta; j++ ) - { - if( ret.pLink == NULL ) - throw Bu::ExceptionBase( - "Attempt to iterate past begining of list."); - ret.pLink = ret.pLink->pNext; - } - return ret; - } - - const_iterator operator-( int iDelta ) - { - const_iterator ret( *this ); - for( int j = 0; j < iDelta; j++ ) - { - if( ret.pLink == NULL ) - throw Bu::ExceptionBase( - "Attempt to iterate past begining of list."); - ret.pLink = ret.pLink->pPrev; - } - return ret; - } - - const_iterator &operator=( const iterator &oth ) - { - pLink = oth.pLink; - return *this; - } - - const_iterator &operator=( const const_iterator &oth ) - { - pLink = oth.pLink; - return *this; - } - - operator bool() - { - return pLink != NULL; - } - - bool isValid() - { - return pLink != NULL; - } - } const_iterator; - - /** - * Get an iterator pointing to the first item in the list. - *@returns (iterator) - */ - iterator begin() - { - _hardCopy(); - return iterator( core->pFirst ); - } - - /** - * Get a const iterator pointing to the first item in the list. - *@returns (const const_iterator) - */ - const_iterator begin() const - { - return const_iterator( core->pFirst ); - } - - /** - * Get an iterator pointing to a place just past the last item in - * the list. - *@returns (const Link *) - */ - const iterator end() - { - return iterator( NULL ); - } - - /** - * Get an iterator pointing to a place just past the last item in - * the list. - *@returns (const Link *) - */ - const const_iterator end() const - { - return const_iterator( NULL ); - } - - /** - * Erase an item from the list. - *@param i (iterator) The item to erase. - */ - MyType &erase( iterator i ) - { - _hardCopy(); - core->erase( i.pLink ); - - return *this; - } - - /** - * Erase an item from the list. - *@param i (iterator) The item to erase. - */ - MyType &erase( const_iterator i ) - { - _hardCopy(); - core->erase( i.pLink ); - - return *this; - } - - /** - * Erase an item from the list if you already know the item. - *@param v The item to find and erase. - */ - MyType &erase( const value &v ) - { - for( const_iterator i = begin(); i != end(); i++ ) - { - if( (*i) == v ) - { - erase( i ); - return *this; - } - } - - return *this; - } - - /** - * Erases the first item in the list, identical to pop, but better for - * lists that aren't built as stacks, since you know where it will be - * erasing from. - */ - MyType &eraseFirst() - { - _hardCopy(); - erase( begin() ); - - return *this; - } - - /** - * Erases the last item in the list. - */ - MyType &eraseLast() - { - _hardCopy(); - core->erase( core->pLast ); - - return *this; - } - - iterator find( const value &v ) - { - for( iterator i = begin(); i; i++ ) - { - if( (*i) == v ) - return i; - } - - return end(); - } - - const_iterator find( const value &v ) const - { - for( const_iterator i = begin(); i; i++ ) - { - if( (*i) == v ) - return i; - } - - return end(); - } - - /** - * Get the current size of the list. - *@returns (int) The current size of the list. - */ - long getSize() const - { - return core->nSize; - } - - /** - * Get the first item in the list. - *@returns (value_type &) The first item in the list. - */ - value &first() - { - if( core->pFirst->pValue == NULL ) - throw Bu::ExceptionBase("Attempt to read first element from empty list."); - _hardCopy(); - return *core->pFirst->pValue; - } - - /** - * Get the first item in the list. - *@returns (const value_type &) The first item in the list. - */ - const value &first() const - { - if( core->pFirst->pValue == NULL ) - throw Bu::ExceptionBase("Attempt to read first element from empty list."); - return *core->pFirst->pValue; - } - - /** - * Get the last item in the list. - *@returns (value_type &) The last item in the list. - */ - value &last() - { - _hardCopy(); - return *core->pLast->pValue; - } - - /** - * Get the last item in the list. - *@returns (const value_type &) The last item in the list. - */ - const value &last() const - { - return *core->pLast->pValue; - } - - bool isEmpty() const - { - return (core->nSize == 0); - } - - protected: - virtual Core *_copyCore( Core *src ) - { - Core *pRet = _allocateCore(); - for( Link *pCur = src->pFirst; pCur; pCur = pCur->pNext ) - { - pRet->append( *pCur->pValue ); - } - return pRet; - } - - private: - }; - - class Formatter; - Formatter &operator<<( Formatter &rOut, char *sStr ); - Formatter &operator<<( Formatter &rOut, signed char c ); - template - Formatter &operator<<( Formatter &f, const Bu::List &l ) - { - f << '['; - for( typename Bu::List::const_iterator i = l.begin(); i; i++ ) - { - if( i != l.begin() ) - f << ", "; - f << *i; - } - f << ']'; - - return f; - } - - template - ArchiveBase &operator<<( ArchiveBase &ar, const List &h ) - { - ar << h.getSize(); - for( typename List::const_iterator i = h.begin(); i != h.end(); i++ ) - { - ar << (*i); - } - - return ar; - } - - template - ArchiveBase &operator>>( ArchiveBase &ar, List &h ) - { - h.clear(); - long nSize; - ar >> nSize; - - for( long j = 0; j < nSize; j++ ) - { - value v; - ar >> v; - h.append( v ); - } - - return ar; - } + /** @cond DEVEL */ + template + struct ListLink + { + value *pValue; + ListLink *pNext; + ListLink *pPrev; + }; + + template + class List; + + template + struct ListCore + { + friend class List; + friend class SharedCore< + List, + ListCore + >; + private: + typedef struct ListLink Link; + ListCore() : + pFirst( NULL ), + pLast( NULL ), + nSize( 0 ) + { } + + virtual ~ListCore() + { + clear(); + } + + Link *pFirst; + Link *pLast; + long nSize; + linkalloc la; + valuealloc va; + + /** + * Append a value to the list. + *@param v (const value_type &) The value to append. + */ + Link *append( const value &v ) + { + Link *pNew = la.allocate( 1 ); + pNew->pValue = va.allocate( 1 ); + va.construct( pNew->pValue, v ); + nSize++; + if( pFirst == NULL ) + { + // Empty list + pFirst = pLast = pNew; + pNew->pNext = pNew->pPrev = NULL; + } + else + { + pNew->pNext = NULL; + pNew->pPrev = pLast; + pLast->pNext = pNew; + pLast = pNew; + } + return pNew; + } + + /** + * Prepend a value to the list. + *@param v (const value_type &) The value to prepend. + */ + Link *prepend( const value &v ) + { + Link *pNew = la.allocate( 1 ); + pNew->pValue = va.allocate( 1 ); + va.construct( pNew->pValue, v ); + nSize++; + if( pFirst == NULL ) + { + // Empty list + pFirst = pLast = pNew; + pNew->pNext = pNew->pPrev = NULL; + } + else + { + pNew->pNext = pFirst; + pNew->pPrev = NULL; + pFirst->pPrev = pNew; + pFirst = pNew; + } + return pNew; + } + + void clear() + { + Link *pCur = pFirst; + for(;;) + { + if( pCur == NULL ) break; + va.destroy( pCur->pValue ); + va.deallocate( pCur->pValue, 1 ); + Link *pTmp = pCur->pNext; + la.destroy( pCur ); + la.deallocate( pCur, 1 ); + pCur = pTmp; + } + pFirst = pLast = NULL; + nSize = 0; + } + + Link *insert( Link *pLink, const value &v ) + { + Link *pAfter = pLink; + if( pAfter == NULL ) + { + return append( v ); + } + Link *pPrev = pAfter->pPrev; + if( pPrev == NULL ) + { + return prepend( v ); + } + + Link *pNew = la.allocate( 1 ); + pNew->pValue = va.allocate( 1 ); + va.construct( pNew->pValue, v ); + nSize++; + + pNew->pNext = pAfter; + pNew->pPrev = pPrev; + pAfter->pPrev = pNew; + pPrev->pNext = pNew; + + return pNew; + } + + /** + * Erase an item from the list. + *@param i (iterator) The item to erase. + */ + void erase( Link *pLink ) + { + Link *pCur = pLink; + if( pCur == NULL ) return; + Link *pPrev = pCur->pPrev; + if( pPrev == NULL ) + { + va.destroy( pCur->pValue ); + va.deallocate( pCur->pValue, 1 ); + pFirst = pCur->pNext; + la.destroy( pCur ); + la.deallocate( pCur, 1 ); + if( pFirst == NULL ) + pLast = NULL; + else + pFirst->pPrev = NULL; + nSize--; + } + else + { + va.destroy( pCur->pValue ); + va.deallocate( pCur->pValue, 1 ); + Link *pTmp = pCur->pNext; + la.destroy( pCur ); + la.deallocate( pCur, 1 ); + pPrev->pNext = pTmp; + if( pTmp != NULL ) + pTmp->pPrev = pPrev; + else + pLast = pPrev; + nSize--; + } + } + }; + /** @endcond */ + + /** + * Linked list template container. This class is similar to the stl list + * class except for a few minor changes. First, when const, all + * members are only accessable const. Second, erasing a location does not + * invalidate the iterator used, it simply points to the next valid + * location, or end() if there are no more. Other iterators pointing to + * the deleted record will, of course, no longer be valid. + * + *@param value (typename) The type of data to store in your list + *@param valuealloc (typename) Memory Allocator for your value type + *@param linkalloc (typename) Memory Allocator for the list links. + *@extends SharedCore + *@ingroup Containers + */ + template, + typename linkalloc=std::allocator > > + class List /** @cond */ : public SharedCore< + List, + ListCore + > /** @endcond */ + { + private: + typedef struct ListLink Link; + typedef class List MyType; + typedef struct ListCore Core; + + protected: + using SharedCore::core; + using SharedCore::_hardCopy; + using SharedCore::_allocateCore; + + public: + struct const_iterator; + struct iterator; + + List() + { + } + + List( const MyType &src ) : + SharedCore( src ) + { + } + + List( const value &v ) + { + append( v ); + } + + ~List() + { + } + + MyType &operator+=( const value &v ) + { + _hardCopy(); + append( v ); + return *this; + } + + MyType &operator+=( const MyType &src ) + { + _hardCopy(); + append( src ); + return *this; + } + + MyType operator+( const MyType &src ) + { + MyType lNew( *this ); + lNew += src; + return lNew; + } + + bool operator==( const MyType &rhs ) const + { + if( getSize() != rhs.getSize() ) + return false; + + for( typename MyType::const_iterator a = begin(), b = rhs.begin(); + a; a++, b++ ) + { + if( *a != *b ) + return false; + } + + return true; + } + + bool operator!=( const MyType &rhs ) const + { + return !(*this == rhs); + } + + /** + * Clear the data from the list. + */ + void clear() + { + _hardCopy(); + core->clear(); + } + + MyType &enqueue( const value &v ) + { + _hardCopy(); + append( v ); + + return *this; + } + + value dequeue() + { + // _hardCopy(); erase will call this for me + value v = *core->pFirst->pValue; + + erase( begin() ); + + return v; + } + + MyType &push( const value &v ) + { + _hardCopy(); + prepend( v ); + + return *this; + } + + MyType &pop() + { + _hardCopy(); + erase( begin() ); + + return *this; + } + + value peekPop() + { + value v = first(); + pop(); + return v; + } + + value &peek() + { + return first(); + } + + /** + * Append a value to the list. + *@param v (const value_type &) The value to append. + */ + MyType &append( const value &v ) + { + _hardCopy(); + core->append( v ); + + return *this; + } + + MyType &append( const MyType &rSrc ) + { + _hardCopy(); + for( typename MyType::const_iterator i = rSrc.begin(); + i != rSrc.end(); i++ ) + { + core->append( *i ); + } + + return *this; + } + + /** + * Prepend a value to the list. + *@param v (const value_type &) The value to prepend. + */ + MyType &prepend( const value &v ) + { + _hardCopy(); + core->prepend( v ); + + return *this; + } + + /** + * Prepend another list to the front of this one. This will prepend + * the rSrc list in reverse order...I may fix that later. + */ + MyType &prepend( const MyType &rSrc ) + { + _hardCopy(); + for( typename MyType::const_iterator i = rSrc.begin(); + i != rSrc.end(); i++ ) + { + core->prepend( *i ); + } + + return *this; + } + + MyType &insert( MyType::iterator &i, const value &v ) + { + _hardCopy(); + + core->insert( i.pLink, v ); + + return *this; + } + + template + void sort( cmptype cmp ) + { + Heap hSort( cmp, getSize() ); + for( typename MyType::iterator i = begin(); i; i++ ) + { + hSort.enqueue( *i ); + } + clear(); + while( !hSort.isEmpty() ) + { + append( hSort.dequeue() ); + } + } + + void sort() + { + sort<__basicLTCmp >(); + } + + template + void sort() + { + Heap hSort( getSize() ); + for( typename MyType::iterator i = begin(); i; i++ ) + { + hSort.enqueue( *i ); + } + clear(); + while( !hSort.isEmpty() ) + { + append( hSort.dequeue() ); + } + } + + /** + * Insert a new item in sort order by searching for the first item that + * is larger and inserting this before it, or at the end if none are + * larger. If this is the only function used to insert data in the + * List all items will be sorted. To use this, the value type must + * support the > operator. + */ + template + iterator insertSorted( cmptype cmp, const value &v ) + { + _hardCopy(); + if( core->pFirst == NULL ) + { + // Empty list + return iterator( core->append( v ) ); + } + else + { + Link *pCur = core->pFirst; + for(;;) + { + if( cmp( v, *(pCur->pValue)) ) + { + return iterator( core->insert( pCur, v ) ); + } + pCur = pCur->pNext; + if( pCur == NULL ) + { + return iterator( core->append( v ) ); + } + } + } + } + + iterator insertSorted( const value &v ) + { + return insertSorted<__basicLTCmp >( v ); + } + + template + iterator insertSorted( const value &v ) + { + cmptype cmp; + return insertSorted( cmp, v ); + } + + /** + * An iterator to iterate through your list. + */ + typedef struct iterator + { + friend struct const_iterator; + friend class List; + private: + Link *pLink; + + iterator( Link *pLink ) : + pLink( pLink ) + { + } + + public: + iterator() : + pLink( NULL ) + { + } + + iterator( const iterator &i ) : + pLink( i.pLink ) + { + } + + /** + * Equals comparison operator. + *@param oth (const iterator &) The iterator to compare to. + *@returns (bool) Are they equal? + */ + bool operator==( const iterator &oth ) const + { + return ( pLink == oth.pLink ); + } + + /** + * Equals comparison operator. + *@param pOth (const Link *) The link to compare to. + *@returns (bool) Are they equal? + */ + bool operator==( const Link *pOth ) const + { + return ( pLink == pOth ); + } + + /** + * Not equals comparison operator. + *@param oth (const iterator &) The iterator to compare to. + *@returns (bool) Are they not equal? + */ + bool operator!=( const iterator &oth ) const + { + return ( pLink != oth.pLink ); + } + + /** + * Not equals comparison operator. + *@param pOth (const Link *) The link to compare to. + *@returns (bool) Are they not equal? + */ + bool operator!=( const Link *pOth ) const + { + return ( pLink != pOth ); + } + + /** + * Dereference operator. + *@returns (value_type &) The value. + */ + value &operator*() + { + return *(pLink->pValue); + } + + /** + * Pointer access operator. + *@returns (value_type *) A pointer to the value. + */ + value *operator->() + { + return pLink->pValue; + } + + iterator &operator++() + { + if( pLink == NULL ) + throw Bu::ExceptionBase( + "Attempt to iterate past end of list."); + pLink = pLink->pNext; + return *this; + } + + iterator &operator--() + { + if( pLink == NULL ) + throw Bu::ExceptionBase( + "Attempt to iterate past begining of list."); + pLink = pLink->pPrev; + return *this; + } + + iterator &operator++( int ) + { + if( pLink == NULL ) + throw Bu::ExceptionBase( + "Attempt to iterate past end of list."); + pLink = pLink->pNext; + return *this; + } + + iterator &operator--( int ) + { + if( pLink == NULL ) + throw Bu::ExceptionBase( + "Attempt to iterate past begining of list."); + pLink = pLink->pPrev; + return *this; + } + + iterator operator+( int iDelta ) + { + iterator ret( *this ); + for( int j = 0; j < iDelta; j++ ) + { + if( ret.pLink == NULL ) + throw Bu::ExceptionBase( + "Attempt to iterate past begining of list."); + ret.pLink = ret.pLink->pNext; + } + return ret; + } + + iterator operator-( int iDelta ) + { + iterator ret( *this ); + for( int j = 0; j < iDelta; j++ ) + { + if( ret.pLink == NULL ) + throw Bu::ExceptionBase( + "Attempt to iterate past begining of list."); + ret.pLink = ret.pLink->pPrev; + } + return ret; + } + + operator bool() + { + return pLink != NULL; + } + + bool isValid() + { + return pLink != NULL; + } + + /** + * Assignment operator. + *@param oth (const iterator &) The other iterator to set this + * one to. + */ + iterator &operator=( const iterator &oth ) + { + pLink = oth.pLink; + return *this; + } + } iterator; + + /** + *@see iterator + */ + typedef struct const_iterator + { + friend class List; + private: + Link *pLink; + + const_iterator( Link *pLink ) : + pLink( pLink ) + { + } + + public: + const_iterator() : + pLink( NULL ) + { + } + + const_iterator( const iterator &i ) : + pLink( i.pLink ) + { + } + + bool operator==( const const_iterator &oth ) const + { + return ( pLink == oth.pLink ); + } + + bool operator==( const Link *pOth ) const + { + return ( pLink == pOth ); + } + + bool operator!=( const const_iterator &oth ) const + { + return ( pLink != oth.pLink ); + } + + bool operator!=( const Link *pOth ) const + { + return ( pLink != pOth ); + } + + const value &operator*() + { + return *(pLink->pValue); + } + + const value *operator->() + { + return pLink->pValue; + } + + const_iterator &operator++() + { + if( pLink == NULL ) + throw Bu::ExceptionBase( + "Attempt to iterate past end of list."); + pLink = pLink->pNext; + return *this; + } + + const_iterator &operator--() + { + if( pLink == NULL ) + throw Bu::ExceptionBase( + "Attempt to iterate past begining of list."); + pLink = pLink->pPrev; + return *this; + } + + const_iterator &operator++( int ) + { + if( pLink == NULL ) + throw Bu::ExceptionBase( + "Attempt to iterate past end of list."); + pLink = pLink->pNext; + return *this; + } + + const_iterator &operator--( int ) + { + if( pLink == NULL ) + throw Bu::ExceptionBase( + "Attempt to iterate past begining of list."); + pLink = pLink->pPrev; + return *this; + } + + const_iterator operator+( int iDelta ) + { + const_iterator ret( *this ); + for( int j = 0; j < iDelta; j++ ) + { + if( ret.pLink == NULL ) + throw Bu::ExceptionBase( + "Attempt to iterate past begining of list."); + ret.pLink = ret.pLink->pNext; + } + return ret; + } + + const_iterator operator-( int iDelta ) + { + const_iterator ret( *this ); + for( int j = 0; j < iDelta; j++ ) + { + if( ret.pLink == NULL ) + throw Bu::ExceptionBase( + "Attempt to iterate past begining of list."); + ret.pLink = ret.pLink->pPrev; + } + return ret; + } + + const_iterator &operator=( const iterator &oth ) + { + pLink = oth.pLink; + return *this; + } + + const_iterator &operator=( const const_iterator &oth ) + { + pLink = oth.pLink; + return *this; + } + + operator bool() + { + return pLink != NULL; + } + + bool isValid() + { + return pLink != NULL; + } + } const_iterator; + + /** + * Get an iterator pointing to the first item in the list. + *@returns (iterator) + */ + iterator begin() + { + _hardCopy(); + return iterator( core->pFirst ); + } + + /** + * Get a const iterator pointing to the first item in the list. + *@returns (const const_iterator) + */ + const_iterator begin() const + { + return const_iterator( core->pFirst ); + } + + /** + * Get an iterator pointing to a place just past the last item in + * the list. + *@returns (const Link *) + */ + const iterator end() + { + return iterator( NULL ); + } + + /** + * Get an iterator pointing to a place just past the last item in + * the list. + *@returns (const Link *) + */ + const const_iterator end() const + { + return const_iterator( NULL ); + } + + /** + * Erase an item from the list. + *@param i (iterator) The item to erase. + */ + MyType &erase( iterator i ) + { + _hardCopy(); + core->erase( i.pLink ); + + return *this; + } + + /** + * Erase an item from the list. + *@param i (iterator) The item to erase. + */ + MyType &erase( const_iterator i ) + { + _hardCopy(); + core->erase( i.pLink ); + + return *this; + } + + /** + * Erase an item from the list if you already know the item. + *@param v The item to find and erase. + */ + MyType &erase( const value &v ) + { + for( const_iterator i = begin(); i != end(); i++ ) + { + if( (*i) == v ) + { + erase( i ); + return *this; + } + } + + return *this; + } + + /** + * Erases the first item in the list, identical to pop, but better for + * lists that aren't built as stacks, since you know where it will be + * erasing from. + */ + MyType &eraseFirst() + { + _hardCopy(); + erase( begin() ); + + return *this; + } + + /** + * Erases the last item in the list. + */ + MyType &eraseLast() + { + _hardCopy(); + core->erase( core->pLast ); + + return *this; + } + + iterator find( const value &v ) + { + for( iterator i = begin(); i; i++ ) + { + if( (*i) == v ) + return i; + } + + return end(); + } + + const_iterator find( const value &v ) const + { + for( const_iterator i = begin(); i; i++ ) + { + if( (*i) == v ) + return i; + } + + return end(); + } + + /** + * Get the current size of the list. + *@returns (int) The current size of the list. + */ + long getSize() const + { + return core->nSize; + } + + /** + * Get the first item in the list. + *@returns (value_type &) The first item in the list. + */ + value &first() + { + if( core->pFirst->pValue == NULL ) + throw Bu::ExceptionBase("Attempt to read first element from empty list."); + _hardCopy(); + return *core->pFirst->pValue; + } + + /** + * Get the first item in the list. + *@returns (const value_type &) The first item in the list. + */ + const value &first() const + { + if( core->pFirst->pValue == NULL ) + throw Bu::ExceptionBase("Attempt to read first element from empty list."); + return *core->pFirst->pValue; + } + + /** + * Get the last item in the list. + *@returns (value_type &) The last item in the list. + */ + value &last() + { + _hardCopy(); + return *core->pLast->pValue; + } + + /** + * Get the last item in the list. + *@returns (const value_type &) The last item in the list. + */ + const value &last() const + { + return *core->pLast->pValue; + } + + bool isEmpty() const + { + return (core->nSize == 0); + } + + protected: + virtual Core *_copyCore( Core *src ) + { + Core *pRet = _allocateCore(); + for( Link *pCur = src->pFirst; pCur; pCur = pCur->pNext ) + { + pRet->append( *pCur->pValue ); + } + return pRet; + } + + private: + }; + + class Formatter; + Formatter &operator<<( Formatter &rOut, char *sStr ); + Formatter &operator<<( Formatter &rOut, signed char c ); + template + Formatter &operator<<( Formatter &f, const Bu::List &l ) + { + f << '['; + for( typename Bu::List::const_iterator i = l.begin(); i; i++ ) + { + if( i != l.begin() ) + f << ", "; + f << *i; + } + f << ']'; + + return f; + } + + template + ArchiveBase &operator<<( ArchiveBase &ar, const List &h ) + { + ar << h.getSize(); + for( typename List::const_iterator i = h.begin(); i != h.end(); i++ ) + { + ar << (*i); + } + + return ar; + } + + template + ArchiveBase &operator>>( ArchiveBase &ar, List &h ) + { + h.clear(); + long nSize; + ar >> nSize; + + for( long j = 0; j < nSize; j++ ) + { + value v; + ar >> v; + h.append( v ); + } + + return ar; + } } diff --git a/src/stable/logger.cpp b/src/stable/logger.cpp index fa0987e..7d49193 100644 --- a/src/stable/logger.cpp +++ b/src/stable/logger.cpp @@ -14,7 +14,7 @@ Bu::Logger::Logger() { - setFormat("%t"); + setFormat("%t"); } Bu::Logger::~Logger() @@ -24,186 +24,186 @@ Bu::Logger::~Logger() void Bu::Logger::log( uint32_t nLevel, const char *sFile, const char *sFunction, int nLine, const char *sFormat, ...) { #ifndef WIN32 - if( (nLevel&nLevelMask) == 0 ) - return; + if( (nLevel&nLevelMask) == 0 ) + return; - va_list ap; - va_start( ap, sFormat ); - char *text; - if( vasprintf( &text, sFormat, ap ) < 0 ) - { - printf("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! WTF?\n"); - return; - } - va_end(ap); - - time_t t = time(NULL); - - char *line = NULL; - struct tm *pTime; - pTime = localtime( &t ); - if ( asprintf( - &line, - sLogFormat.getStr(), - pTime->tm_year+1900, - pTime->tm_mon+1, - pTime->tm_mday, - pTime->tm_hour, - pTime->tm_min, - pTime->tm_sec, - nLevel, - sFile, - nLine, - text, - sFunction - ) < 0 ) - { - //printf("LOGGER: ERROR ALLOCATING STRING: %s\n", strerror( errno ) ); - return; - } - write( fileno(stdout), line, strlen(line) ); - free( text ); - free( line ); + va_list ap; + va_start( ap, sFormat ); + char *text; + if( vasprintf( &text, sFormat, ap ) < 0 ) + { + printf("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! WTF?\n"); + return; + } + va_end(ap); + + time_t t = time(NULL); + + char *line = NULL; + struct tm *pTime; + pTime = localtime( &t ); + if ( asprintf( + &line, + sLogFormat.getStr(), + pTime->tm_year+1900, + pTime->tm_mon+1, + pTime->tm_mday, + pTime->tm_hour, + pTime->tm_min, + pTime->tm_sec, + nLevel, + sFile, + nLine, + text, + sFunction + ) < 0 ) + { + //printf("LOGGER: ERROR ALLOCATING STRING: %s\n", strerror( errno ) ); + return; + } + write( fileno(stdout), line, strlen(line) ); + free( text ); + free( line ); #else - #warning Bu::Logger::log IS A STUB for WIN32!!!! + #warning Bu::Logger::log IS A STUB for WIN32!!!! #endif } void Bu::Logger::setFormat( const Bu::String &str ) { - sLogFormat = ""; + sLogFormat = ""; - static char fmts[][4]={ - {'y', 'd', '0', '1'}, - {'m', 'd', '0', '2'}, - {'d', 'd', '0', '3'}, - {'h', 'd', '0', '4'}, - {'M', 'd', '0', '5'}, - {'s', 'd', '0', '6'}, - {'L', 'd', '0', '7'}, - {'f', 's', '0', '8'}, - {'l', 'd', '0', '9'}, - {'t', 's', '1', '0'}, - {'F', 's', '1', '1'}, - {'\0', '\0', '\0', '\0'}, - }; - - for( const char *s = str.getStr(); *s; s++ ) - { - if( *s == '%' ) - { - sLogFormat += '%'; - Bu::String sBuf; - for(;;) - { - s++; - int l; - for( l = 0;; l++ ) - { - if( fmts[l][0] == '\0' ) - { - sBuf += *s; - break; - } - else if( *s == fmts[l][0] ) - { - sLogFormat += fmts[l][2]; - sLogFormat += fmts[l][3]; - sLogFormat += '$'; - sLogFormat += sBuf; - sLogFormat += fmts[l][1]; - break; - } - } - if( fmts[l][0] != '\0' ) - break; - } - } - else - { - sLogFormat += *s; - } - } - sLogFormat += '\n'; + static char fmts[][4]={ + {'y', 'd', '0', '1'}, + {'m', 'd', '0', '2'}, + {'d', 'd', '0', '3'}, + {'h', 'd', '0', '4'}, + {'M', 'd', '0', '5'}, + {'s', 'd', '0', '6'}, + {'L', 'd', '0', '7'}, + {'f', 's', '0', '8'}, + {'l', 'd', '0', '9'}, + {'t', 's', '1', '0'}, + {'F', 's', '1', '1'}, + {'\0', '\0', '\0', '\0'}, + }; + + for( const char *s = str.getStr(); *s; s++ ) + { + if( *s == '%' ) + { + sLogFormat += '%'; + Bu::String sBuf; + for(;;) + { + s++; + int l; + for( l = 0;; l++ ) + { + if( fmts[l][0] == '\0' ) + { + sBuf += *s; + break; + } + else if( *s == fmts[l][0] ) + { + sLogFormat += fmts[l][2]; + sLogFormat += fmts[l][3]; + sLogFormat += '$'; + sLogFormat += sBuf; + sLogFormat += fmts[l][1]; + break; + } + } + if( fmts[l][0] != '\0' ) + break; + } + } + else + { + sLogFormat += *s; + } + } + sLogFormat += '\n'; - //write( fileno(stdout), sLogFormat.getStr(), sLogFormat.getSize() ); + //write( fileno(stdout), sLogFormat.getStr(), sLogFormat.getSize() ); } void Bu::Logger::setMask( uint32_t n ) { - nLevelMask = n; + nLevelMask = n; } uint32_t Bu::Logger::getMask() { - return nLevelMask; + return nLevelMask; } void Bu::Logger::setLevel( uint32_t n ) { - int j; - for( j = 31; j > 0; j-- ) - { - if( (n&(1<= 0; j-- ) - { - n |= (1< 0; j-- ) + { + if( (n&(1<= 0; j-- ) + { + n |= (1<32 && pData[j+k]<=128)?(pData[j+k]):('.') ); - sLine += buf; - } - log( nLevel, sFile, sFunction, nLine, sLine.getStr() ); - sLine = ""; - j += kmax; - if( j >= nDataLen ) break; - } - log( nLevel, sFile, sFunction, nLine, sBorder.getStr() ); + log( nLevel, sFile, sFunction, nLine, "Displaying %ld bytes of %s.", nDataLen, lpName ); + const unsigned char *pData = (const unsigned char *)pDataV; + int j = 0; + Bu::String sBorder; + for( int l = 0; l < 8*3+2*8+2+5; l++ ) sBorder += ((l!=11&&l!=37)?("-"):("+")); + log( nLevel, sFile, sFunction, nLine, sBorder.getStr() ); + Bu::String sLine; + for(;;) + { + { + char buf[16]; + sprintf( buf, "%010d | ", j ); + sLine += buf; + } + int kmax = 8; + if( nDataLen-j < 8 ) kmax = nDataLen-j; + for(int k = 0; k < 8; k++ ) + { + if( k < kmax ) + { + char buf[4]; + sprintf( buf, "%02X ", (int)((unsigned char)pData[j+k]) ); + sLine += buf; + } + else + { + sLine += "-- "; + } + } + sLine += "| "; + for(int k = 0; k < kmax; k++ ) + { + char buf[3]; + sprintf( buf, "%c", (pData[j+k]>32 && pData[j+k]<=128)?(pData[j+k]):('.') ); + sLine += buf; + } + log( nLevel, sFile, sFunction, nLine, sLine.getStr() ); + sLine = ""; + j += kmax; + if( j >= nDataLen ) break; + } + log( nLevel, sFile, sFunction, nLine, sBorder.getStr() ); } diff --git a/src/stable/logger.h b/src/stable/logger.h index 198ffa2..bcc5a83 100644 --- a/src/stable/logger.h +++ b/src/stable/logger.h @@ -13,82 +13,82 @@ namespace Bu { - /** - * Simple logging facility. All output goes straight to stdout, unlike the - * old multi-log system. Generally we expect any program complex enough to - * want to use this will have other facilities for processing the logging - * output, but if we need it we can add other output methods. - * - * Currently implemented as a singleton to avoid clutter with globals, you - * generally never want to use the logging system directly, it's annoying. - * Instead use the handy macros lineLog, setLogMask, setLogFormat, and - * setLogLevel. They do all the real work for you. - * - * In the log format, you can specify extra information that will be written - * to the log with every message, and extras in printf style. Use %X flags - * where X is one of the following: - * - L - Logging level of the log message (not the current mask) - * - y - Full year - * - m - Month - * - d - Day of month - * - h - Hour (24-hour format) - * - M - Minutes - * - s - Seconds - * - f - Source file - * - l - Line number - * - F - function name - * - t - Text of message (usually important) - * - * You can include anything extra that you would like, a newline will always - * be added automatically, so no need to worry about that. You can also - * include any extra printf style formatting that you would like, for - * example: "%h:%02M:%02s" for the time 4:02:09 instead of 4:2:9. - * - * It's generally handy to create an enum of values you use as levels during - * program execution (such as error, warning, info, debug, etc). These - * levels should be treated as bitflags, and the most desirable messages, - * i.e. serious errors and the like should be low order (0x01), and the much - * less desirable messages, like debugging info, should be higher order - * (0xF0). During operation you can then set either an explicit mask, - * selecting just the levels that you would like to see printed, or set the - * mask using the setLevel helper function, which simulates verbosity - * levels, enabling every flag lower order than the highest order set bit - * passed. I.E. if you had the following enumerated levels: - * - *@code - enum { - logError = 0x01, - logWarning = 0x02, - logInfo = 0x04, - logDebug = 0x08 - }; - @endcode - * And you set the mask with setMask( logInfo ) the only messages you would - * see are the ones catagorized logInfo. However, if you used - * setLevel( logInfo ) then you would see logInfo, logWarning, and logError - * type messages, since they are lower order. - */ - class Logger : public Bu::Singleton - { - friend class Bu::Singleton; - private: - Logger(); - virtual ~Logger(); + /** + * Simple logging facility. All output goes straight to stdout, unlike the + * old multi-log system. Generally we expect any program complex enough to + * want to use this will have other facilities for processing the logging + * output, but if we need it we can add other output methods. + * + * Currently implemented as a singleton to avoid clutter with globals, you + * generally never want to use the logging system directly, it's annoying. + * Instead use the handy macros lineLog, setLogMask, setLogFormat, and + * setLogLevel. They do all the real work for you. + * + * In the log format, you can specify extra information that will be written + * to the log with every message, and extras in printf style. Use %X flags + * where X is one of the following: + * - L - Logging level of the log message (not the current mask) + * - y - Full year + * - m - Month + * - d - Day of month + * - h - Hour (24-hour format) + * - M - Minutes + * - s - Seconds + * - f - Source file + * - l - Line number + * - F - function name + * - t - Text of message (usually important) + * + * You can include anything extra that you would like, a newline will always + * be added automatically, so no need to worry about that. You can also + * include any extra printf style formatting that you would like, for + * example: "%h:%02M:%02s" for the time 4:02:09 instead of 4:2:9. + * + * It's generally handy to create an enum of values you use as levels during + * program execution (such as error, warning, info, debug, etc). These + * levels should be treated as bitflags, and the most desirable messages, + * i.e. serious errors and the like should be low order (0x01), and the much + * less desirable messages, like debugging info, should be higher order + * (0xF0). During operation you can then set either an explicit mask, + * selecting just the levels that you would like to see printed, or set the + * mask using the setLevel helper function, which simulates verbosity + * levels, enabling every flag lower order than the highest order set bit + * passed. I.E. if you had the following enumerated levels: + * + *@code + enum { + logError = 0x01, + logWarning = 0x02, + logInfo = 0x04, + logDebug = 0x08 + }; + @endcode + * And you set the mask with setMask( logInfo ) the only messages you would + * see are the ones catagorized logInfo. However, if you used + * setLevel( logInfo ) then you would see logInfo, logWarning, and logError + * type messages, since they are lower order. + */ + class Logger : public Bu::Singleton + { + friend class Bu::Singleton; + private: + Logger(); + virtual ~Logger(); - public: - void log( uint32_t nLevel, const char *sFile, const char *sFunction, int nLine, const char *sFormat, ...); + public: + void log( uint32_t nLevel, const char *sFile, const char *sFunction, int nLine, const char *sFormat, ...); - void setFormat( const Bu::String &str ); - void setMask( uint32_t n ); - void setLevel( uint32_t n ); - uint32_t getMask(); + void setFormat( const Bu::String &str ); + void setMask( uint32_t n ); + void setLevel( uint32_t n ); + uint32_t getMask(); - void hexDump( uint32_t nLevel, const char *sFile, const char *sFunction, int nLine, const void *pData, long nDataLen, const char *lpName ); + void hexDump( uint32_t nLevel, const char *sFile, const char *sFunction, int nLine, const void *pData, long nDataLen, const char *lpName ); - private: - Bu::String sLogFormat; - uint32_t nLevelMask; - }; + private: + Bu::String sLogFormat; + uint32_t nLevelMask; + }; } /** @@ -97,29 +97,29 @@ namespace Bu * file, line number, and function. */ #define lineLog( nLevel, sFrmt, ...) \ - Bu::Logger::getInstance().log( nLevel, __FILE__, __PRETTY_FUNCTION__, __LINE__, sFrmt, ##__VA_ARGS__ ) + Bu::Logger::getInstance().log( nLevel, __FILE__, __PRETTY_FUNCTION__, __LINE__, sFrmt, ##__VA_ARGS__ ) #define logHexDump( nLevel, pData, iSize, sName ) \ - Bu::Logger::getInstance().hexDump( nLevel, __FILE__, __PRETTY_FUNCTION__, __LINE__, pData, iSize, sName ) + Bu::Logger::getInstance().hexDump( nLevel, __FILE__, __PRETTY_FUNCTION__, __LINE__, pData, iSize, sName ) /** * Set the Bu::Logger logging mask directly. See Bu::Logger::setMask for * details. */ #define setLogMask( nLevel ) \ - Bu::Logger::getInstance().setMask( nLevel ) + Bu::Logger::getInstance().setMask( nLevel ) /** * Set the Bu::Logger format. See Bu::Logger::setFormat for details. */ #define setLogFormat( sFrmt ) \ - Bu::Logger::getInstance().setFormat( sFrmt ) + Bu::Logger::getInstance().setFormat( sFrmt ) /** * Set the Bu::Logger logging mask simulating levels. See Bu::Logger::setLevel * for details. */ #define setLogLevel( nLevel ) \ - Bu::Logger::getInstance().setLevel( nLevel ) + Bu::Logger::getInstance().setLevel( nLevel ) #endif diff --git a/src/stable/lzma.cpp b/src/stable/lzma.cpp index 9df8f57..9ec2ce0 100644 --- a/src/stable/lzma.cpp +++ b/src/stable/lzma.cpp @@ -15,234 +15,234 @@ using namespace Bu; Bu::Lzma::Lzma( Bu::Stream &rNext, int nCompression, Format eFmt ) : - Bu::Filter( rNext ), - prState( NULL ), - nCompression( nCompression ), - sTotalOut( 0 ), - eFmt( eFmt ), - bEos( false ) + Bu::Filter( rNext ), + prState( NULL ), + nCompression( nCompression ), + sTotalOut( 0 ), + eFmt( eFmt ), + bEos( false ) { - TRACE( nCompression ); - start(); + TRACE( nCompression ); + start(); } Bu::Lzma::~Lzma() { - TRACE(); - stop(); + TRACE(); + stop(); } void Bu::Lzma::start() { - TRACE(); - nBufSize = 64*1024; - pBuf = new char[nBufSize]; + TRACE(); + nBufSize = 64*1024; + pBuf = new char[nBufSize]; } Bu::size Bu::Lzma::stop() { - TRACE(); - if( pState ) - { - if( bReading ) - { - lzma_end( pState ); - delete[] pBuf; - pBuf = NULL; - delete pState; - prState = NULL; - return 0; - } - else - { - for(;;) - { - pState->next_in = NULL; - pState->avail_in = 0; - pState->avail_out = nBufSize; - pState->next_out = (uint8_t *)pBuf; - int res = lzma_code( pState, LZMA_FINISH ); - if( pState->avail_out < nBufSize ) - { - sTotalOut += rNext.write( pBuf, nBufSize-pState->avail_out ); - } - if( res == LZMA_STREAM_END ) - break; - } - lzma_end( pState ); - delete[] pBuf; - pBuf = NULL; - delete pState; - prState = NULL; - return sTotalOut; - } - } - return 0; + TRACE(); + if( pState ) + { + if( bReading ) + { + lzma_end( pState ); + delete[] pBuf; + pBuf = NULL; + delete pState; + prState = NULL; + return 0; + } + else + { + for(;;) + { + pState->next_in = NULL; + pState->avail_in = 0; + pState->avail_out = nBufSize; + pState->next_out = (uint8_t *)pBuf; + int res = lzma_code( pState, LZMA_FINISH ); + if( pState->avail_out < nBufSize ) + { + sTotalOut += rNext.write( pBuf, nBufSize-pState->avail_out ); + } + if( res == LZMA_STREAM_END ) + break; + } + lzma_end( pState ); + delete[] pBuf; + pBuf = NULL; + delete pState; + prState = NULL; + return sTotalOut; + } + } + return 0; } void Bu::Lzma::lzmaError( int code ) { - TRACE( code ); - switch( code ) - { - case LZMA_OK: - case LZMA_STREAM_END: - case LZMA_NO_CHECK: - case LZMA_UNSUPPORTED_CHECK: - break; + TRACE( code ); + switch( code ) + { + case LZMA_OK: + case LZMA_STREAM_END: + case LZMA_NO_CHECK: + case LZMA_UNSUPPORTED_CHECK: + break; - case LZMA_MEM_ERROR: - throw ExceptionBase("Lzma: Memory allocation error."); + case LZMA_MEM_ERROR: + throw ExceptionBase("Lzma: Memory allocation error."); - case LZMA_MEMLIMIT_ERROR: - throw ExceptionBase("Lzma: Memory usage limit was reached."); + case LZMA_MEMLIMIT_ERROR: + throw ExceptionBase("Lzma: Memory usage limit was reached."); - case LZMA_FORMAT_ERROR: - throw ExceptionBase("Lzma: File format not recognized."); + case LZMA_FORMAT_ERROR: + throw ExceptionBase("Lzma: File format not recognized."); - case LZMA_OPTIONS_ERROR: - throw ExceptionBase("Lzma: Invalid or unsupported options."); + case LZMA_OPTIONS_ERROR: + throw ExceptionBase("Lzma: Invalid or unsupported options."); - case LZMA_DATA_ERROR: - throw ExceptionBase("Lzma: Data is corrupt."); + case LZMA_DATA_ERROR: + throw ExceptionBase("Lzma: Data is corrupt."); - case LZMA_BUF_ERROR: - throw ExceptionBase("Lzma: No progress is possible."); + case LZMA_BUF_ERROR: + throw ExceptionBase("Lzma: No progress is possible."); - case LZMA_PROG_ERROR: - throw ExceptionBase("Lzma: Programming error."); + case LZMA_PROG_ERROR: + throw ExceptionBase("Lzma: Programming error."); - default: - throw ExceptionBase("Lzma: Unknown error encountered." ); - } + default: + throw ExceptionBase("Lzma: Unknown error encountered." ); + } } Bu::size Bu::Lzma::read( void *pData, Bu::size nBytes ) { - TRACE( pData, nBytes ); - if( !pState ) - { - prState = new ::lzma_stream; - lzma_stream zEmpty = LZMA_STREAM_INIT; - Bu::memcpy( prState, &zEmpty, sizeof(lzma_stream) ); - - bReading = true; - lzmaError( lzma_auto_decoder( pState, UINT64_MAX, 0 ) ); - pState->next_in = (uint8_t *)pBuf; - pState->avail_in = 0; - } - if( bReading == false ) - throw ExceptionBase("This lzma filter is in writing mode, you can't read."); - - int nRead = 0; - int nReadTotal = pState->total_out; - pState->next_out = (uint8_t *)pData; - pState->avail_out = nBytes; - for(;;) - { - int ret = lzma_code( pState, LZMA_RUN ); -// printf("inflate returned %d; avail in=%d, out=%d\n", ret, -// pState->avail_in, pState->avail_out ); - - nReadTotal += nRead-pState->avail_out; - - if( ret == LZMA_STREAM_END ) - { - bEos = true; - if( pState->avail_in > 0 ) - { - if( rNext.isSeekable() ) - { - rNext.seek( -pState->avail_in ); - } - } - return nBytes-pState->avail_out; - } -// if( ret != LZMA_BUF_ERROR ) - lzmaError( ret ); - - if( pState->avail_out ) - { - if( pState->avail_in == 0 ) - { - nRead = rNext.read( pBuf, nBufSize ); - if( nRead == 0 && rNext.isEos() ) - { - throw Bu::ExceptionBase("Premature end of underlying " - "stream found reading deflate stream."); - } - pState->next_in = (uint8_t *)pBuf; - pState->avail_in = nRead; - } - } - else - { - return nBytes-pState->avail_out; - } - } - return 0; + TRACE( pData, nBytes ); + if( !pState ) + { + prState = new ::lzma_stream; + lzma_stream zEmpty = LZMA_STREAM_INIT; + Bu::memcpy( prState, &zEmpty, sizeof(lzma_stream) ); + + bReading = true; + lzmaError( lzma_auto_decoder( pState, UINT64_MAX, 0 ) ); + pState->next_in = (uint8_t *)pBuf; + pState->avail_in = 0; + } + if( bReading == false ) + throw ExceptionBase("This lzma filter is in writing mode, you can't read."); + + int nRead = 0; + int nReadTotal = pState->total_out; + pState->next_out = (uint8_t *)pData; + pState->avail_out = nBytes; + for(;;) + { + int ret = lzma_code( pState, LZMA_RUN ); +// printf("inflate returned %d; avail in=%d, out=%d\n", ret, +// pState->avail_in, pState->avail_out ); + + nReadTotal += nRead-pState->avail_out; + + if( ret == LZMA_STREAM_END ) + { + bEos = true; + if( pState->avail_in > 0 ) + { + if( rNext.isSeekable() ) + { + rNext.seek( -pState->avail_in ); + } + } + return nBytes-pState->avail_out; + } +// if( ret != LZMA_BUF_ERROR ) + lzmaError( ret ); + + if( pState->avail_out ) + { + if( pState->avail_in == 0 ) + { + nRead = rNext.read( pBuf, nBufSize ); + if( nRead == 0 && rNext.isEos() ) + { + throw Bu::ExceptionBase("Premature end of underlying " + "stream found reading deflate stream."); + } + pState->next_in = (uint8_t *)pBuf; + pState->avail_in = nRead; + } + } + else + { + return nBytes-pState->avail_out; + } + } + return 0; } Bu::size Bu::Lzma::write( const void *pData, Bu::size nBytes ) { - TRACE( pData, nBytes ); - if( !pState ) - { - prState = new ::lzma_stream; - lzma_stream zEmpty = LZMA_STREAM_INIT; - Bu::memcpy( prState, &zEmpty, sizeof(lzma_stream) ); - - bReading = false; - if( eFmt == Xz ) - lzmaError( - lzma_easy_encoder( pState, nCompression, LZMA_CHECK_CRC64 ) - ); - else if( eFmt == LzmaAlone ) - { - lzma_options_lzma opt; - lzma_lzma_preset( &opt, nCompression ); - lzmaError( lzma_alone_encoder( pState, &opt ) ); - } - else - throw Bu::ExceptionBase("Invalid format for lzma."); - } - if( bReading == true ) - throw ExceptionBase("This lzma filter is in reading mode, you can't write."); - - pState->next_in = (uint8_t *)pData; - pState->avail_in = nBytes; - for(;;) - { - pState->avail_out = nBufSize; - pState->next_out = (uint8_t *)pBuf; - - lzmaError( lzma_code( pState, LZMA_RUN ) ); - - if( pState->avail_out < nBufSize ) - { - sTotalOut += rNext.write( pBuf, nBufSize-pState->avail_out ); - } - if( pState->avail_in == 0 ) - break; - } - - return nBytes; + TRACE( pData, nBytes ); + if( !pState ) + { + prState = new ::lzma_stream; + lzma_stream zEmpty = LZMA_STREAM_INIT; + Bu::memcpy( prState, &zEmpty, sizeof(lzma_stream) ); + + bReading = false; + if( eFmt == Xz ) + lzmaError( + lzma_easy_encoder( pState, nCompression, LZMA_CHECK_CRC64 ) + ); + else if( eFmt == LzmaAlone ) + { + lzma_options_lzma opt; + lzma_lzma_preset( &opt, nCompression ); + lzmaError( lzma_alone_encoder( pState, &opt ) ); + } + else + throw Bu::ExceptionBase("Invalid format for lzma."); + } + if( bReading == true ) + throw ExceptionBase("This lzma filter is in reading mode, you can't write."); + + pState->next_in = (uint8_t *)pData; + pState->avail_in = nBytes; + for(;;) + { + pState->avail_out = nBufSize; + pState->next_out = (uint8_t *)pBuf; + + lzmaError( lzma_code( pState, LZMA_RUN ) ); + + if( pState->avail_out < nBufSize ) + { + sTotalOut += rNext.write( pBuf, nBufSize-pState->avail_out ); + } + if( pState->avail_in == 0 ) + break; + } + + return nBytes; } bool Bu::Lzma::isOpen() { - TRACE(); - return (pState != NULL); + TRACE(); + return (pState != NULL); } bool Bu::Lzma::isEos() { - TRACE(); - return bEos; + TRACE(); + return bEos; } Bu::size Bu::Lzma::getCompressedSize() { - return sTotalOut; + return sTotalOut; } diff --git a/src/stable/lzma.h b/src/stable/lzma.h index 7118a6b..40963cc 100644 --- a/src/stable/lzma.h +++ b/src/stable/lzma.h @@ -14,46 +14,46 @@ namespace Bu { - /** - * Provides XZ compression and decompression, both LZMA1 (LzmaAlone) as - * well as the newer LZMA2 (xz) format. This uses .xz by default. - * - *@ingroup Streams - *@ingroup Compression - */ - class Lzma : public Bu::Filter - { - public: - enum Format - { - Xz = 0x01, - LzmaAlone = 0x02, - }; - - Lzma( Bu::Stream &rNext, int nCompression=6, Format eFmt=Xz ); - virtual ~Lzma(); - - virtual void start(); - virtual Bu::size stop(); - virtual Bu::size read( void *pBuf, Bu::size nBytes ); - virtual Bu::size write( const void *pBuf, Bu::size nBytes ); - - virtual bool isOpen(); - virtual bool isEos(); - - Bu::size getCompressedSize(); - - private: - void lzmaError( int code ); - void *prState; - bool bReading; - int nCompression; - char *pBuf; - uint32_t nBufSize; - Bu::size sTotalOut; - Format eFmt; - bool bEos; - }; + /** + * Provides XZ compression and decompression, both LZMA1 (LzmaAlone) as + * well as the newer LZMA2 (xz) format. This uses .xz by default. + * + *@ingroup Streams + *@ingroup Compression + */ + class Lzma : public Bu::Filter + { + public: + enum Format + { + Xz = 0x01, + LzmaAlone = 0x02, + }; + + Lzma( Bu::Stream &rNext, int nCompression=6, Format eFmt=Xz ); + virtual ~Lzma(); + + virtual void start(); + virtual Bu::size stop(); + virtual Bu::size read( void *pBuf, Bu::size nBytes ); + virtual Bu::size write( const void *pBuf, Bu::size nBytes ); + + virtual bool isOpen(); + virtual bool isEos(); + + Bu::size getCompressedSize(); + + private: + void lzmaError( int code ); + void *prState; + bool bReading; + int nCompression; + char *pBuf; + uint32_t nBufSize; + Bu::size sTotalOut; + Format eFmt; + bool bEos; + }; } #endif diff --git a/src/stable/md5.cpp b/src/stable/md5.cpp index c1d993f..e62cbf4 100644 --- a/src/stable/md5.cpp +++ b/src/stable/md5.cpp @@ -19,7 +19,7 @@ Bu::Md5::Md5() { - reset(); + reset(); } Bu::Md5::~Md5() @@ -28,15 +28,15 @@ Bu::Md5::~Md5() void Bu::Md5::reset() { - // These are the magic seed numbers... + // These are the magic seed numbers... - sum[0] = 0x67452301U; - sum[1] = 0xEFCDAB89U; - sum[2] = 0x98BADCFEU; - sum[3] = 0x10325476U; + sum[0] = 0x67452301U; + sum[1] = 0xEFCDAB89U; + sum[2] = 0x98BADCFEU; + sum[3] = 0x10325476U; - uBits[0] = 0; - uBits[1] = 0; + uBits[0] = 0; + uBits[1] = 0; } void Bu::Md5::setSalt( const Bu::String & /*sSalt*/ ) @@ -45,102 +45,102 @@ void Bu::Md5::setSalt( const Bu::String & /*sSalt*/ ) void Bu::Md5::addData( const void *sVData, int iSize ) { - const char *sData = (const char *)sVData; - uint32_t t; - - t = uBits[0]; - if( (uBits[0] = t + ((uint32_t)iSize << 3)) < t ) - uBits[1]++; - uBits[1] += iSize >> 29; - - t = (t >> 3) & 0x3f; /* How many bytes we have buffered */ - - /* Handle any leading odd-sized chunks */ - if( t ) - { - unsigned char *p = (unsigned char *) inbuf + t; - - t = 64 - t; - if( (uint32_t)iSize < t ) { - memcpy( p, sData, iSize ); - return; - } - memcpy( p, sData, t ); - toLittleEndian( inbuf, 16 ); - compBlock( sum, (uint32_t *)inbuf ); - sData += t; - iSize -= t; - } - - /* Process data in 64-byte chunks */ - while( iSize >= 64 ) - { - memcpy( inbuf, sData, 64 ); - toLittleEndian( inbuf, 16 ); - compBlock( sum, (uint32_t *)inbuf ); - sData += 64; - iSize -= 64; - } - - /* Handle any remaining bytes of data. */ - memcpy( inbuf, sData, iSize ); + const char *sData = (const char *)sVData; + uint32_t t; + + t = uBits[0]; + if( (uBits[0] = t + ((uint32_t)iSize << 3)) < t ) + uBits[1]++; + uBits[1] += iSize >> 29; + + t = (t >> 3) & 0x3f; /* How many bytes we have buffered */ + + /* Handle any leading odd-sized chunks */ + if( t ) + { + unsigned char *p = (unsigned char *) inbuf + t; + + t = 64 - t; + if( (uint32_t)iSize < t ) { + memcpy( p, sData, iSize ); + return; + } + memcpy( p, sData, t ); + toLittleEndian( inbuf, 16 ); + compBlock( sum, (uint32_t *)inbuf ); + sData += t; + iSize -= t; + } + + /* Process data in 64-byte chunks */ + while( iSize >= 64 ) + { + memcpy( inbuf, sData, 64 ); + toLittleEndian( inbuf, 16 ); + compBlock( sum, (uint32_t *)inbuf ); + sData += 64; + iSize -= 64; + } + + /* Handle any remaining bytes of data. */ + memcpy( inbuf, sData, iSize ); } Bu::String Bu::Md5::getResult() { - uint32_t lsum[4]; - compCap( lsum ); - return Bu::String( (const char *)lsum, 4*4 ); + uint32_t lsum[4]; + compCap( lsum ); + return Bu::String( (const char *)lsum, 4*4 ); } void Bu::Md5::writeResult( Bu::Stream &sOut ) { - uint32_t lsum[4]; - compCap( lsum ); - sOut.write( lsum, 4*4 ); + uint32_t lsum[4]; + compCap( lsum ); + sOut.write( lsum, 4*4 ); } void Bu::Md5::compCap( uint32_t *sumout ) { - uint8_t tmpbuf[64]; - memcpy( sumout, sum, 4*4 ); - memcpy( tmpbuf, inbuf, 64 ); - - uint32_t count; - uint8_t *p; - - /* Compute number of bytes mod 64 */ - count = (uBits[0] >> 3) & 0x3F; - - /* Set the first char of padding to 0x80. This is safe since there is - always at least one byte free */ - p = tmpbuf + count; - *p++ = 0x80; - - /* Bytes of padding needed to make 64 bytes */ - count = 64 - 1 - count; - - /* Pad out to 56 mod 64 */ - if (count < 8) { - /* Two lots of padding: Pad the first block to 64 bytes */ - memset( p, 0, count ); - toLittleEndian( tmpbuf, 16 ); - compBlock( sumout, (uint32_t *)tmpbuf ); - - /* Now fill the next block with 56 bytes */ - memset( tmpbuf, 0, 56); - } else { - /* Pad block to 56 bytes */ - memset( p, 0, count - 8); - } - toLittleEndian( tmpbuf, 14 ); - - /* Append length in bits and transform */ - ((uint32_t *) tmpbuf)[14] = uBits[0]; - ((uint32_t *) tmpbuf)[15] = uBits[1]; - - compBlock( sumout, (uint32_t *)tmpbuf ); - toLittleEndian((unsigned char *)sumout, 4); + uint8_t tmpbuf[64]; + memcpy( sumout, sum, 4*4 ); + memcpy( tmpbuf, inbuf, 64 ); + + uint32_t count; + uint8_t *p; + + /* Compute number of bytes mod 64 */ + count = (uBits[0] >> 3) & 0x3F; + + /* Set the first char of padding to 0x80. This is safe since there is + always at least one byte free */ + p = tmpbuf + count; + *p++ = 0x80; + + /* Bytes of padding needed to make 64 bytes */ + count = 64 - 1 - count; + + /* Pad out to 56 mod 64 */ + if (count < 8) { + /* Two lots of padding: Pad the first block to 64 bytes */ + memset( p, 0, count ); + toLittleEndian( tmpbuf, 16 ); + compBlock( sumout, (uint32_t *)tmpbuf ); + + /* Now fill the next block with 56 bytes */ + memset( tmpbuf, 0, 56); + } else { + /* Pad block to 56 bytes */ + memset( p, 0, count - 8); + } + toLittleEndian( tmpbuf, 14 ); + + /* Append length in bits and transform */ + ((uint32_t *) tmpbuf)[14] = uBits[0]; + ((uint32_t *) tmpbuf)[15] = uBits[1]; + + compBlock( sumout, (uint32_t *)tmpbuf ); + toLittleEndian((unsigned char *)sumout, 4); } #define F1(x, y, z) (z ^ (x & (y ^ z))) @@ -150,15 +150,15 @@ void Bu::Md5::compCap( uint32_t *sumout ) /* This is the central step in the MD5 algorithm. */ #define MD5STEP(f, w, x, y, z, data, s) \ - ( w += f(x, y, z) + data, w = w<>(32-s), w += x ) + ( w += f(x, y, z) + data, w = w<>(32-s), w += x ) void Bu::Md5::compBlock( uint32_t *lsum, uint32_t *x ) { - register uint32_t a, b, c, d; - a = lsum[0]; - b = lsum[1]; - c = lsum[2]; - d = lsum[3]; + register uint32_t a, b, c, d; + a = lsum[0]; + b = lsum[1]; + c = lsum[2]; + d = lsum[3]; MD5STEP(F1, a, b, c, d, x[0] + 0xd76aa478, 7); MD5STEP(F1, d, a, b, c, x[1] + 0xe8c7b756, 12); @@ -228,19 +228,19 @@ void Bu::Md5::compBlock( uint32_t *lsum, uint32_t *x ) MD5STEP(F4, c, d, a, b, x[2] + 0x2ad7d2bb, 15); MD5STEP(F4, b, c, d, a, x[9] + 0xeb86d391, 21); - lsum[0] += a; - lsum[1] += b; - lsum[2] += c; - lsum[3] += d; + lsum[0] += a; + lsum[1] += b; + lsum[2] += c; + lsum[3] += d; } void Bu::Md5::_toLittleEndian( uint8_t *buf, uint32_t count ) { - uint32_t t; - do { - t = (uint32_t) ((unsigned) buf[3] << 8 | buf[2]) << 16 | - ((unsigned) buf[1] << 8 | buf[0]); - *(uint32_t *) buf = t; - buf += 4; - } while( --count ); + uint32_t t; + do { + t = (uint32_t) ((unsigned) buf[3] << 8 | buf[2]) << 16 | + ((unsigned) buf[1] << 8 | buf[0]); + *(uint32_t *) buf = t; + buf += 4; + } while( --count ); } diff --git a/src/stable/md5.h b/src/stable/md5.h index cb7d396..8845082 100644 --- a/src/stable/md5.h +++ b/src/stable/md5.h @@ -12,43 +12,43 @@ namespace Bu { - /** - * Class for easily calculating MD5 sums of just about any data. - * This code is based on some public domain code written by Colin Plumb in - * 1993. - *@author Mike Buland - */ - class Md5 : public Bu::CryptoHash - { - public: - /** Build an MD5 sum builder. */ - Md5(); - - /** Deconstruct */ - virtual ~Md5(); - - virtual void reset(); - virtual void setSalt( const Bu::String &sSalt ); - virtual void addData( const void *sData, int iSize ); - using Bu::CryptoHash::addData; - virtual String getResult(); - virtual void writeResult( Bu::Stream &sOut ); - - private: - /** - * Compute one block of input data. - */ - void compBlock( uint32_t *lsum, uint32_t *x ); - void compCap( uint32_t *sumout ); - - void _addData( uint8_t *target, int &iCurFill, const void *sData, - int iSize ); - void _toLittleEndian( uint8_t *buf, uint32_t count ); - - uint8_t inbuf[64]; - uint32_t sum[4]; - uint32_t uBits[2]; - }; + /** + * Class for easily calculating MD5 sums of just about any data. + * This code is based on some public domain code written by Colin Plumb in + * 1993. + *@author Mike Buland + */ + class Md5 : public Bu::CryptoHash + { + public: + /** Build an MD5 sum builder. */ + Md5(); + + /** Deconstruct */ + virtual ~Md5(); + + virtual void reset(); + virtual void setSalt( const Bu::String &sSalt ); + virtual void addData( const void *sData, int iSize ); + using Bu::CryptoHash::addData; + virtual String getResult(); + virtual void writeResult( Bu::Stream &sOut ); + + private: + /** + * Compute one block of input data. + */ + void compBlock( uint32_t *lsum, uint32_t *x ); + void compCap( uint32_t *sumout ); + + void _addData( uint8_t *target, int &iCurFill, const void *sData, + int iSize ); + void _toLittleEndian( uint8_t *buf, uint32_t count ); + + uint8_t inbuf[64]; + uint32_t sum[4]; + uint32_t uBits[2]; + }; }; #endif diff --git a/src/stable/membuf.cpp b/src/stable/membuf.cpp index dea9a0e..4d6e8e6 100644 --- a/src/stable/membuf.cpp +++ b/src/stable/membuf.cpp @@ -10,13 +10,13 @@ using namespace Bu; Bu::MemBuf::MemBuf() : - nPos( 0 ) + nPos( 0 ) { } Bu::MemBuf::MemBuf( const Bu::String &str ) : - sBuf( str ), - nPos( 0 ) + sBuf( str ), + nPos( 0 ) { } @@ -30,76 +30,76 @@ void Bu::MemBuf::close() size Bu::MemBuf::read( void *pBuf, size nBytes ) { - if( (size)sBuf.getSize()-(size)nPos < nBytes ) - nBytes = sBuf.getSize()-nPos; + if( (size)sBuf.getSize()-(size)nPos < nBytes ) + nBytes = sBuf.getSize()-nPos; - memcpy( pBuf, sBuf.getStr()+nPos, nBytes ); - nPos += nBytes; + memcpy( pBuf, sBuf.getStr()+nPos, nBytes ); + nPos += nBytes; - return nBytes; + return nBytes; } - + size Bu::MemBuf::write( const void *pBuf, size nBytes ) { - if( nPos == sBuf.getSize() ) - { - // Easiest, just append the data. - sBuf.append( (const char *)pBuf, nBytes ); - nPos += nBytes; - return nBytes; - } - else - { - // Trickier, we must do this in two parts, overwrite, then append - // Frist, overwrite. - size iOver = sBuf.getSize() - nPos; - if( iOver > nBytes ) - iOver = nBytes; - memcpy( sBuf.getStr()+nPos, pBuf, iOver ); - // Then append - if( iOver < nBytes ) - { - sBuf.append( ((const char *)pBuf)+iOver, nBytes-iOver ); - } - nPos += nBytes; - return nBytes; - } + if( nPos == sBuf.getSize() ) + { + // Easiest, just append the data. + sBuf.append( (const char *)pBuf, nBytes ); + nPos += nBytes; + return nBytes; + } + else + { + // Trickier, we must do this in two parts, overwrite, then append + // Frist, overwrite. + size iOver = sBuf.getSize() - nPos; + if( iOver > nBytes ) + iOver = nBytes; + memcpy( sBuf.getStr()+nPos, pBuf, iOver ); + // Then append + if( iOver < nBytes ) + { + sBuf.append( ((const char *)pBuf)+iOver, nBytes-iOver ); + } + nPos += nBytes; + return nBytes; + } } size Bu::MemBuf::tell() { - return nPos; + return nPos; } void Bu::MemBuf::seek( size offset ) { - nPos += offset; - if( nPos < 0 ) nPos = 0; - else if( nPos > sBuf.getSize() ) nPos = sBuf.getSize(); + nPos += offset; + if( nPos < 0 ) nPos = 0; + else if( nPos > sBuf.getSize() ) nPos = sBuf.getSize(); } void Bu::MemBuf::setPos( size pos ) { - nPos = pos; - if( nPos < 0 ) nPos = 0; - else if( nPos > sBuf.getSize() ) nPos = sBuf.getSize(); + nPos = pos; + if( nPos < 0 ) nPos = 0; + else if( nPos > sBuf.getSize() ) nPos = sBuf.getSize(); } void Bu::MemBuf::setPosEnd( size pos ) { - nPos = sBuf.getSize()-pos; - if( nPos < 0 ) nPos = 0; - else if( nPos > sBuf.getSize() ) nPos = sBuf.getSize(); + nPos = sBuf.getSize()-pos; + if( nPos < 0 ) nPos = 0; + else if( nPos > sBuf.getSize() ) nPos = sBuf.getSize(); } bool Bu::MemBuf::isEos() { - return (nPos == sBuf.getSize()); + return (nPos == sBuf.getSize()); } bool Bu::MemBuf::isOpen() { - return true; + return true; } void Bu::MemBuf::flush() @@ -108,32 +108,32 @@ void Bu::MemBuf::flush() bool Bu::MemBuf::canRead() { - return !isEos(); + return !isEos(); } bool Bu::MemBuf::canWrite() { - return true; + return true; } bool Bu::MemBuf::isReadable() { - return true; + return true; } bool Bu::MemBuf::isWritable() { - return true; + return true; } bool Bu::MemBuf::isSeekable() { - return true; + return true; } bool Bu::MemBuf::isBlocking() { - return true; + return true; } void Bu::MemBuf::setBlocking( bool ) @@ -142,36 +142,36 @@ void Bu::MemBuf::setBlocking( bool ) void Bu::MemBuf::setSize( size iSize ) { - if( iSize < 0 ) - iSize = 0; - sBuf.setSize( iSize ); - if( nPos > iSize ) - nPos = iSize; + if( iSize < 0 ) + iSize = 0; + sBuf.setSize( iSize ); + if( nPos > iSize ) + nPos = iSize; } Bu::size Bu::MemBuf::getSize() const { - return sBuf.getSize(); + return sBuf.getSize(); } Bu::size Bu::MemBuf::getBlockSize() const { - return sBuf.getSize(); + return sBuf.getSize(); } Bu::String Bu::MemBuf::getLocation() const { - return ""; + return ""; } Bu::String &Bu::MemBuf::getString() { - return sBuf; + return sBuf; } void Bu::MemBuf::setString( const Bu::String &sNewData ) { - sBuf = sNewData; - nPos = 0; + sBuf = sNewData; + nPos = 0; } diff --git a/src/stable/membuf.h b/src/stable/membuf.h index f016974..f36e0bc 100644 --- a/src/stable/membuf.h +++ b/src/stable/membuf.h @@ -16,53 +16,53 @@ namespace Bu { - /** - * A memory buffer stream. This provides a read/write stream in memory that - * works exactly like a file stream...only in memory. You can seed the - * memory buffer with a Bu::String of your own, or start with an empty one. - * Due to Bu::String using Bu::SharedCore starting with a string will not - * necesarilly cause the MemBuf to make a copy of your memory, but if you're - * sure you're not going to need to change the stream then use StaticMemBuf. - *@ingroup Streams - */ - class MemBuf : public Stream - { - public: - MemBuf(); - MemBuf( const Bu::String &str ); - virtual ~MemBuf(); + /** + * A memory buffer stream. This provides a read/write stream in memory that + * works exactly like a file stream...only in memory. You can seed the + * memory buffer with a Bu::String of your own, or start with an empty one. + * Due to Bu::String using Bu::SharedCore starting with a string will not + * necesarilly cause the MemBuf to make a copy of your memory, but if you're + * sure you're not going to need to change the stream then use StaticMemBuf. + *@ingroup Streams + */ + class MemBuf : public Stream + { + public: + MemBuf(); + MemBuf( const Bu::String &str ); + virtual ~MemBuf(); - virtual void close(); - virtual size read( void *pBuf, size iBytes ); + virtual void close(); + virtual size read( void *pBuf, size iBytes ); - virtual size write( const void *pBuf, size iBytes ); - using Stream::write; - virtual size tell(); - virtual void seek( size offset ); - virtual void setPos( size pos ); - virtual void setPosEnd( size pos ); - virtual bool isEos(); - virtual bool isOpen(); - virtual void flush(); - virtual bool canRead(); - virtual bool canWrite(); - virtual bool isReadable(); - virtual bool isWritable(); - virtual bool isSeekable(); - virtual bool isBlocking(); - virtual void setBlocking( bool bBlocking=true ); - virtual void setSize( size iSize ); - virtual size getSize() const; - virtual size getBlockSize() const; - virtual Bu::String getLocation() const; + virtual size write( const void *pBuf, size iBytes ); + using Stream::write; + virtual size tell(); + virtual void seek( size offset ); + virtual void setPos( size pos ); + virtual void setPosEnd( size pos ); + virtual bool isEos(); + virtual bool isOpen(); + virtual void flush(); + virtual bool canRead(); + virtual bool canWrite(); + virtual bool isReadable(); + virtual bool isWritable(); + virtual bool isSeekable(); + virtual bool isBlocking(); + virtual void setBlocking( bool bBlocking=true ); + virtual void setSize( size iSize ); + virtual size getSize() const; + virtual size getBlockSize() const; + virtual Bu::String getLocation() const; - Bu::String &getString(); - void setString( const Bu::String &sNewData ); + Bu::String &getString(); + void setString( const Bu::String &sNewData ); - private: - Bu::String sBuf; - size nPos; - }; + private: + Bu::String sBuf; + size nPos; + }; } #endif diff --git a/src/stable/minicron.cpp b/src/stable/minicron.cpp index 87296ae..c83cd44 100644 --- a/src/stable/minicron.cpp +++ b/src/stable/minicron.cpp @@ -11,260 +11,260 @@ #include Bu::MiniCron::MiniCron() : - jidNext( 1 ) + jidNext( 1 ) { } Bu::MiniCron::~MiniCron() { - while( !hJobs.isEmpty() ) - { - delete hJobs.dequeue(); - } + while( !hJobs.isEmpty() ) + { + delete hJobs.dequeue(); + } } bool Bu::MiniCron::hasJobs() { - return !hJobs.isEmpty(); + return !hJobs.isEmpty(); } time_t Bu::MiniCron::getNextRun() { - if( hasJobs() ) - return hJobs.peek()->getNextRun(); - return -1; + if( hasJobs() ) + return hJobs.peek()->getNextRun(); + return -1; } time_t Bu::MiniCron::getNextRun( Bu::MiniCron::JobId jid ) { - for( JobHeap::iterator i = hJobs.begin(); i; i++ ) - { - if( (*i)->getId() == jid ) - { - return (*i)->getNextRunTime(); - } - } - return -1; + for( JobHeap::iterator i = hJobs.begin(); i; i++ ) + { + if( (*i)->getId() == jid ) + { + return (*i)->getNextRunTime(); + } + } + return -1; } void Bu::MiniCron::poll() { - time_t tNow = time( NULL ); - - while( !hJobs.isEmpty() ) - { - if( hJobs.peek()->getNextRun() <= tNow ) - { - Job *pJob = hJobs.dequeue(); - pJob->run(); - if( pJob->bContinue ) - { - hJobs.enqueue( pJob ); - } - else - { - delete pJob; - } - } - else - { - break; - } - } + time_t tNow = time( NULL ); + + while( !hJobs.isEmpty() ) + { + if( hJobs.peek()->getNextRun() <= tNow ) + { + Job *pJob = hJobs.dequeue(); + pJob->run(); + if( pJob->bContinue ) + { + hJobs.enqueue( pJob ); + } + else + { + delete pJob; + } + } + else + { + break; + } + } } Bu::MiniCron::JobId Bu::MiniCron::addJob( const Bu::String &sName, - Bu::MiniCron::CronSignal sigJob, const Bu::MiniCron::Timer &t ) + Bu::MiniCron::CronSignal sigJob, const Bu::MiniCron::Timer &t ) { - JobId jid = jidNext++; - Job *pJob = new Job( sName, jid ); - pJob->sigJob = sigJob; - pJob->pTimer = t.clone(); - pJob->tNextRun = pJob->pTimer->nextTime(); - hJobs.enqueue( pJob ); + JobId jid = jidNext++; + Job *pJob = new Job( sName, jid ); + pJob->sigJob = sigJob; + pJob->pTimer = t.clone(); + pJob->tNextRun = pJob->pTimer->nextTime(); + hJobs.enqueue( pJob ); - return jid; + return jid; } Bu::MiniCron::JobId Bu::MiniCron::addJobOnce( const Bu::String &sName, - Bu::MiniCron::CronSignal sigJob, const Bu::MiniCron::Timer &t ) + Bu::MiniCron::CronSignal sigJob, const Bu::MiniCron::Timer &t ) { - JobId jid = jidNext++; - Job *pJob = new Job( sName, jid, false ); - pJob->sigJob = sigJob; - pJob->pTimer = t.clone(); - pJob->tNextRun = pJob->pTimer->nextTime(); - hJobs.enqueue( pJob ); + JobId jid = jidNext++; + Job *pJob = new Job( sName, jid, false ); + pJob->sigJob = sigJob; + pJob->pTimer = t.clone(); + pJob->tNextRun = pJob->pTimer->nextTime(); + hJobs.enqueue( pJob ); - return jid; + return jid; } void Bu::MiniCron::removeJob( JobId jid ) { - Bu::List lJobs; - while( !hJobs.isEmpty() ) - { - Job *pJob = hJobs.dequeue(); - if( pJob->getId() == jid ) - { - delete pJob; - } - else - lJobs.append( pJob ); - } + Bu::List lJobs; + while( !hJobs.isEmpty() ) + { + Job *pJob = hJobs.dequeue(); + if( pJob->getId() == jid ) + { + delete pJob; + } + else + lJobs.append( pJob ); + } - for( Bu::List::iterator i = lJobs.begin(); i; i++ ) - { - hJobs.enqueue( *i ); - } + for( Bu::List::iterator i = lJobs.begin(); i; i++ ) + { + hJobs.enqueue( *i ); + } } void Bu::MiniCron::runJob( JobId jid, bool bReschedule ) { - Bu::List lJobs; - while( !hJobs.isEmpty() ) - { - Job *pJob = hJobs.dequeue(); - if( pJob->getId() == jid ) - { - pJob->run( bReschedule ); - if( !pJob->bContinue ) - { - delete pJob; - break; - } - lJobs.append( pJob ); - break; - } - lJobs.append( pJob ); - } - - for( Bu::List::iterator i = lJobs.begin(); i; i++ ) - { - hJobs.enqueue( *i ); - } + Bu::List lJobs; + while( !hJobs.isEmpty() ) + { + Job *pJob = hJobs.dequeue(); + if( pJob->getId() == jid ) + { + pJob->run( bReschedule ); + if( !pJob->bContinue ) + { + delete pJob; + break; + } + lJobs.append( pJob ); + break; + } + lJobs.append( pJob ); + } + + for( Bu::List::iterator i = lJobs.begin(); i; i++ ) + { + hJobs.enqueue( *i ); + } } void Bu::MiniCron::runJob( const Bu::String &sName, bool bReschedule ) { - Bu::List lJobs; - while( !hJobs.isEmpty() ) - { - Job *pJob = hJobs.dequeue(); - if( pJob->getName() == sName ) - { - pJob->run( bReschedule ); - if( !pJob->bContinue ) - { - delete pJob; - break; - } - lJobs.append( pJob ); - break; - } - lJobs.append( pJob ); - } - - for( Bu::List::iterator i = lJobs.begin(); i; i++ ) - { - hJobs.enqueue( *i ); - } + Bu::List lJobs; + while( !hJobs.isEmpty() ) + { + Job *pJob = hJobs.dequeue(); + if( pJob->getName() == sName ) + { + pJob->run( bReschedule ); + if( !pJob->bContinue ) + { + delete pJob; + break; + } + lJobs.append( pJob ); + break; + } + lJobs.append( pJob ); + } + + for( Bu::List::iterator i = lJobs.begin(); i; i++ ) + { + hJobs.enqueue( *i ); + } } Bu::MiniCron::JobInfoList Bu::MiniCron::getJobInfo() { - JobInfoList lRet; - for( JobHeap::iterator i = hJobs.begin(); i; i++ ) - { - lRet.append( - JobInfo( (*i)->getName(), (*i)->getId(), (*i)->getNextRun() ) - ); - } - lRet.sort(); - return lRet; + JobInfoList lRet; + for( JobHeap::iterator i = hJobs.begin(); i; i++ ) + { + lRet.append( + JobInfo( (*i)->getName(), (*i)->getId(), (*i)->getNextRun() ) + ); + } + lRet.sort(); + return lRet; } Bu::MiniCron::Job::Job( const Bu::String &sName, JobId jid, bool bRepeat ) : - sName( sName ), - pTimer( NULL ), - bContinue( bRepeat ), - jid( jid ), - tAdded( time( NULL ) ), - iRunCount( 0 ) + sName( sName ), + pTimer( NULL ), + bContinue( bRepeat ), + jid( jid ), + tAdded( time( NULL ) ), + iRunCount( 0 ) { } Bu::MiniCron::Job::~Job() { - delete pTimer; - pTimer = NULL; + delete pTimer; + pTimer = NULL; } void Bu::MiniCron::Job::run( bool bReschedule ) { - iRunCount++; - if( bReschedule ) - tNextRun = pTimer->nextTime(); - sigJob( *this ); + iRunCount++; + if( bReschedule ) + tNextRun = pTimer->nextTime(); + sigJob( *this ); } time_t Bu::MiniCron::Job::getNextRun() const { - return tNextRun; + return tNextRun; } void Bu::MiniCron::Job::calcNextRun() { - if( pTimer ) - tNextRun = pTimer->nextTime(); + if( pTimer ) + tNextRun = pTimer->nextTime(); } void Bu::MiniCron::Job::setTimer( const Timer &t ) { - delete pTimer; - pTimer = t.clone(); + delete pTimer; + pTimer = t.clone(); } void Bu::MiniCron::Job::stop() { - bContinue = false; + bContinue = false; } void Bu::MiniCron::Job::resume() { - bContinue = true; + bContinue = true; } Bu::MiniCron::JobId Bu::MiniCron::Job::getId() const { - return jid; + return jid; } time_t Bu::MiniCron::Job::getTimeCreated() const { - return tAdded; + return tAdded; } int Bu::MiniCron::Job::getRunCount() const { - return iRunCount; + return iRunCount; } time_t Bu::MiniCron::Job::getNextRunTime() const { - return tNextRun; + return tNextRun; } Bu::String Bu::MiniCron::Job::getName() const { - return sName; + return sName; } Bu::MiniCron::JobInfo::JobInfo( const Bu::String &sName, JobId jid, - time_t tNext ) : - sName( sName ), - jid( jid ), - tNext( tNext ) + time_t tNext ) : + sName( sName ), + jid( jid ), + tNext( tNext ) { } @@ -274,7 +274,7 @@ Bu::MiniCron::JobInfo::~JobInfo() bool Bu::MiniCron::JobInfo::operator<( const JobInfo &rhs ) const { - return jid < rhs.jid; + return jid < rhs.jid; } Bu::MiniCron::Timer::Timer() @@ -286,8 +286,8 @@ Bu::MiniCron::Timer::~Timer() } Bu::MiniCron::TimerInterval::TimerInterval( time_t tFirst, time_t tInterval ) : - tNext( tFirst ), - tInterval( tInterval ) + tNext( tFirst ), + tInterval( tInterval ) { } @@ -297,14 +297,14 @@ Bu::MiniCron::TimerInterval::~TimerInterval() time_t Bu::MiniCron::TimerInterval::nextTime() { - time_t tRet = tNext; - tNext += tInterval; - return tRet; + time_t tRet = tNext; + tNext += tInterval; + return tRet; } Bu::MiniCron::TimerBasic::TimerBasic( const Bu::String &s ) : - tLast( -1 ), - sSpec( s ) + tLast( -1 ), + sSpec( s ) { } @@ -314,164 +314,164 @@ Bu::MiniCron::TimerBasic::~TimerBasic() time_t Bu::MiniCron::TimerBasic::nextTime() { - if( tLast == -1 ) - tLast = time( NULL ); - - Bu::String::const_iterator i = sSpec.begin(); - switch( lex( i ) ) - { - case tokDaily: - { - int iHour = lexInt( i ); - int iMin = lexInt( i ); - - struct tm t; - ::memcpy( &t, localtime( &tLast ), sizeof(struct tm) ); - if( iHour < t.tm_hour || - (iHour == t.tm_hour && iMin <= t.tm_min) ) - { - t.tm_mday++; - } - t.tm_hour = iHour; - t.tm_min = iMin; - t.tm_sec = 0; - tLast = mktime( &t ); - } - break; - - case tokHourly: - { - int iMin = lexInt( i ); - - struct tm t; - ::memcpy( &t, localtime( &tLast ), sizeof(struct tm) ); - if( iMin <= t.tm_min ) - t.tm_hour++; - t.tm_min = iMin; - t.tm_sec = 0; - tLast = mktime( &t ); - } - break; - - case tokWeekly: - { - int iDay = lexInt( i ); - int iHour = lexInt( i ); - int iMin = lexInt( i ); - - struct tm t; - ::memcpy( &t, localtime( &tLast ), sizeof(struct tm) ); - if( iDay < t.tm_wday || - (iDay == t.tm_wday && iHour < t.tm_hour) || - (iDay == t.tm_wday && iHour == t.tm_hour - && iMin <= t.tm_min) ) - { - if( iDay <= t.tm_wday ) - t.tm_mday += 7 - (t.tm_wday-iDay); - else - t.tm_mday += 7 - (iDay-t.tm_wday); - } - else - { - t.tm_mday += (iDay-t.tm_wday); - } - t.tm_hour = iHour; - t.tm_min = iMin; - t.tm_sec = 0; - tLast = mktime( &t ); - } - break; - - case tokMonthly: - break; - - case tokYearly: - break; - - default: - break; - } - - return tLast; + if( tLast == -1 ) + tLast = time( NULL ); + + Bu::String::const_iterator i = sSpec.begin(); + switch( lex( i ) ) + { + case tokDaily: + { + int iHour = lexInt( i ); + int iMin = lexInt( i ); + + struct tm t; + ::memcpy( &t, localtime( &tLast ), sizeof(struct tm) ); + if( iHour < t.tm_hour || + (iHour == t.tm_hour && iMin <= t.tm_min) ) + { + t.tm_mday++; + } + t.tm_hour = iHour; + t.tm_min = iMin; + t.tm_sec = 0; + tLast = mktime( &t ); + } + break; + + case tokHourly: + { + int iMin = lexInt( i ); + + struct tm t; + ::memcpy( &t, localtime( &tLast ), sizeof(struct tm) ); + if( iMin <= t.tm_min ) + t.tm_hour++; + t.tm_min = iMin; + t.tm_sec = 0; + tLast = mktime( &t ); + } + break; + + case tokWeekly: + { + int iDay = lexInt( i ); + int iHour = lexInt( i ); + int iMin = lexInt( i ); + + struct tm t; + ::memcpy( &t, localtime( &tLast ), sizeof(struct tm) ); + if( iDay < t.tm_wday || + (iDay == t.tm_wday && iHour < t.tm_hour) || + (iDay == t.tm_wday && iHour == t.tm_hour + && iMin <= t.tm_min) ) + { + if( iDay <= t.tm_wday ) + t.tm_mday += 7 - (t.tm_wday-iDay); + else + t.tm_mday += 7 - (iDay-t.tm_wday); + } + else + { + t.tm_mday += (iDay-t.tm_wday); + } + t.tm_hour = iHour; + t.tm_min = iMin; + t.tm_sec = 0; + tLast = mktime( &t ); + } + break; + + case tokMonthly: + break; + + case tokYearly: + break; + + default: + break; + } + + return tLast; } Bu::MiniCron::TimerBasic::Token Bu::MiniCron::TimerBasic::lex( - Bu::String::const_iterator &i ) -{ - if( !i ) - { - return tokEos; - } - - Bu::String::const_iterator b = i; - - for(; b && (*b == ' ' || *b == '\t'); b++ ) { i = b+1; } - for(; b && *b != ' ' && *b != '\t'; b++ ) { } - - Bu::String sTok( i, b ); - i = b; - - if( sTok == "daily" ) - return tokDaily; - else if( sTok == "hourly" ) - return tokHourly; - else if( sTok == "weekly" ) - return tokWeekly; - else if( sTok == "monthly" ) - return tokMonthly; - else if( sTok == "yearly" ) - return tokYearly; - else if( sTok == "sun" ) - { - iVal = 0; - return valInt; - } - else if( sTok == "mon" ) - { - iVal = 1; - return valInt; - } - else if( sTok == "tue" ) - { - iVal = 2; - return valInt; - } - else if( sTok == "wed" ) - { - iVal = 3; - return valInt; - } - else if( sTok == "thu" ) - { - iVal = 4; - return valInt; - } - else if( sTok == "fri" ) - { - iVal = 5; - return valInt; - } - else if( sTok == "sat" ) - { - iVal = 6; - return valInt; - } - else if( sTok[0] >= '0' && sTok[0] <= '9' ) - { - iVal = strtol( sTok.getStr(), NULL, 0 ); - return valInt; - } - - return tokErr; + Bu::String::const_iterator &i ) +{ + if( !i ) + { + return tokEos; + } + + Bu::String::const_iterator b = i; + + for(; b && (*b == ' ' || *b == '\t'); b++ ) { i = b+1; } + for(; b && *b != ' ' && *b != '\t'; b++ ) { } + + Bu::String sTok( i, b ); + i = b; + + if( sTok == "daily" ) + return tokDaily; + else if( sTok == "hourly" ) + return tokHourly; + else if( sTok == "weekly" ) + return tokWeekly; + else if( sTok == "monthly" ) + return tokMonthly; + else if( sTok == "yearly" ) + return tokYearly; + else if( sTok == "sun" ) + { + iVal = 0; + return valInt; + } + else if( sTok == "mon" ) + { + iVal = 1; + return valInt; + } + else if( sTok == "tue" ) + { + iVal = 2; + return valInt; + } + else if( sTok == "wed" ) + { + iVal = 3; + return valInt; + } + else if( sTok == "thu" ) + { + iVal = 4; + return valInt; + } + else if( sTok == "fri" ) + { + iVal = 5; + return valInt; + } + else if( sTok == "sat" ) + { + iVal = 6; + return valInt; + } + else if( sTok[0] >= '0' && sTok[0] <= '9' ) + { + iVal = strtol( sTok.getStr(), NULL, 0 ); + return valInt; + } + + return tokErr; } int Bu::MiniCron::TimerBasic::lexInt( Bu::String::const_iterator &i ) { - Token t = lex( i ); - if( t == tokEos ) - return 0; - if( t != valInt ) - throw Bu::ExceptionBase("Expected int, got something else."); - return iVal; + Token t = lex( i ); + if( t == tokEos ) + return 0; + if( t != valInt ) + throw Bu::ExceptionBase("Expected int, got something else."); + return iVal; } diff --git a/src/stable/minicron.h b/src/stable/minicron.h index 53e5156..953b82a 100644 --- a/src/stable/minicron.h +++ b/src/stable/minicron.h @@ -16,321 +16,321 @@ namespace Bu { - /** - * A simple cron like system designed to be embedded in any program. This - * class creates a simple cron system that can run any number of jobs at - * customizable intervals or schedules. It does not support some of the - * more complex scheduling that some cron systems can do such as load - * balancing directly, but this could be done on the job side. - * - * This system is synchronous, it does not use any threads on it's own, but - * it is threadsafe, so a cron thread could be created if desired. - * - * The operation is fairly simple, jobs can be added at any time, and use - * any timer they would like, even custom timers. When it is time for a - * job to be run it signals the slot provided when the job was added. Every - * job slot recieves a handle to the job object so that it may control it's - * own lifetime and get information about itself. In addition, every job - * is assigned a unique ID that can be used to control it's operation - * at any time. - * - * By default a job will continually reschedule itself after being run - * unless it calls stop() on it's job object, it is removed using - * removeJob() on the cron object, or it is added with addJobOnce. - * - *@todo A minor change to the job execution system could allow a Timer to - * defer or reschedule execution instead of the job executing. This would, - * in effect, allow us to do every type of interesting scheduling that - * systems like fcron offer, including time constrained load-balanced - * execution. - */ - class MiniCron - { - public: - class Job; - class Timer; - typedef Bu::Signal1 CronSignal; - typedef int JobId; - - MiniCron(); - virtual ~MiniCron(); - - /** - * Tells you if there are jobs registered in the MiniCron. - *@returns true if there are jobs, false otherwise. - */ - virtual bool hasJobs(); - - /** - * If there are jobs, tells you the time the next one will execute. - *@returns The timestamp that the next job will execute at. - */ - virtual time_t getNextRun(); - - /** - * Tells you the time the job matching jid will run next. - *@returns The timestamp that the job jid will next run. - */ - virtual time_t getNextRun( JobId jid ); - - /** - * Call this regularly to execute all jobs that should be executed. - * This will loop until all jobs who's run time match the current time - * or are below the current time (we've missed them). - * If there is nothing to run, the runtime of this funcion is constant, - * it is very fast. Otherwise it executes at log(N) per job run, - * O(N*log(N)). - */ - virtual void poll(); - - /** - * Add a job for repeated scheduling. Pass in a slot to signal, and a - * Timer object to use to do the scheduling. This function returns a - * JobId which can be used at a later time to control the execution of - * the job. - */ - virtual JobId addJob( const Bu::String &sName, CronSignal sigJob, - const Timer &t ); - - /** - * Add a job for one time scheduling. Pass in a slot to signal, and a - * Timer object to use to schodule the one run of this job. This - * function returns a JobId which can be used at a later time to control - * the execution of the job. - */ - virtual JobId addJobOnce( const Bu::String &sName, CronSignal sigJob, - const Timer &t ); - - /** - * Remove a job, preventing all future runs of the job. If there is no - * job matching the given JobId then nothing will happen. However, this - * function is relatively expensive compared to the others in this class - * and has a worse case runtime of 2*N*log(N), still not that bad, and - * a O(N*log(N)). - */ - virtual void removeJob( JobId jid ); - - /** - * Executes the job specified right now. If bReschedule is true then - * the job is then removed from the queue and rescheduled as though - * it's time had come naturally to be run. Otherwise, it's run without - * interrupting the normal schedule. - */ - virtual void runJob( JobId jid, bool bReschedule=false ); - - /** - * Executes the job specified right now. If bReschedule is true then - * the job is then removed from the queue and rescheduled as though - * it's time had come naturally to be run. Otherwise, it's run without - * interrupting the normal schedule. - */ - virtual void runJob( const Bu::String &sName, bool bReschedule=false ); - - class JobInfo - { - public: - JobInfo( const Bu::String &sName, JobId jid, time_t tNext ); - virtual ~JobInfo(); - - bool operator<( const JobInfo &rhs ) const; - - Bu::String sName; - JobId jid; - time_t tNext; - }; - typedef Bu::List JobInfoList; - - JobInfoList getJobInfo(); - - /** - * The baseclass for timer/schedulers for MiniCron jobs. Classes that - * inherit from this are used to determine when jobs will run and at - * what interval. - */ - class Timer - { - public: - Timer(); - virtual ~Timer(); - - /** - * Called by MiniCron when each job is run to determine the next - * time that a job should be run. When a job is run, this function - * is actually called before the job is executed again so that the - * job can tell when the next time it will be run will be. - */ - virtual time_t nextTime()=0; - - /** - * This function should return a copy of the child class. - */ - virtual Timer *clone() const = 0; - }; - - /** - * Execute the job every tInterval seconds, also you can delay the - * first run by a different amount of time from the job's creation. - */ - class TimerInterval : public Timer - { - public: - TimerInterval( time_t tFirst, time_t tInterval ); - virtual ~TimerInterval(); - - virtual time_t nextTime(); - virtual Timer *clone() const - { return new TimerInterval( *this ); } - private: - time_t tNext; - time_t tInterval; - }; - - /** - * A much more general timer class that can be used for much more - * "cron-like" functionality. The constructor takes a string that - * describes the times that the job should be run. At the moment the - * following schemes are understood: - * - * "daily [hour] [minute]" - * "hourly [minute]" - * "weekly [day] [hour] [minute]" - * - * In these examples each word in [brackets] represents a number that - * matches the data type in the brackets. [day] is the number of days - * since sunday, 0-6. You can also use lowercase three character - * abbreviations for the day names. - * - * Many more forms follow. - */ - class TimerBasic : public Timer - { - public: - TimerBasic( const Bu::String &s ); - virtual ~TimerBasic(); - - virtual time_t nextTime(); - virtual Timer *clone() const - { return new TimerBasic( *this ); } - - private: - enum Token - { - tokDaily, - tokHourly, - tokWeekly, - tokMonthly, - tokYearly, - valInt, - tokErr, - tokEos - }; - Token lex( Bu::String::const_iterator &i ); - int lexInt( Bu::String::const_iterator &i ); - int iVal; //< A temp variable for parsing. - time_t tLast; - Bu::String sSpec; - }; - - /** - * Represents a MiniCron Job. This class is used for both internal - * job management as well as job slot interaction and control. Objects - * of this class are passed into the slots that are signaled when a job - * is executed. - */ - class Job - { - friend class Bu::MiniCron; - private: - Job( const Bu::String &sName, JobId jid, bool bRepeat=true ); - virtual ~Job(); - - public: - - /** - * Execute this job once, increment the runcount and schedule the - * next occurance of it. - */ - void run( bool bReschedule=true ); - - /** - * Get the time this job will next run. - */ - time_t getNextRun() const; - - /** - * Compute the time this job will next run. - */ - void calcNextRun(); - - /** - * Replace the current job timer with a new one, this will trigger - * a re-schedule. - */ - void setTimer( const Timer &t ); - - /** - * Stop execution of this job, never execute this job again. - */ - void stop(); - - /** - * Undo a previous stop. This will cause a job that has been - * stopped or even added with addJobOnce to be set for repeated - * scheduling. - */ - void resume(); - - /** - * Get the unique ID of this job. - */ - JobId getId() const; - - /** - * Get the timestamp this job was created. - */ - time_t getTimeCreated() const; - - /** - * Get the current run count of this job, how many times it has been - * executed. This is incremented before the slot is signaled. - */ - int getRunCount() const; - - /** - * Get the next time that this job will be run. Certain timers may - * have the ability to delay job executions, so this is the earliest - * time that the job may run. - */ - time_t getNextRunTime() const; - - /** - * Gets the name that was set when the job was created. - */ - Bu::String getName() const; - - private: - Bu::String sName; - CronSignal sigJob; - time_t tNextRun; - Timer *pTimer; - bool bContinue; - JobId jid; - time_t tAdded; - int iRunCount; - }; - - private: - struct JobPtrCmp - { - bool operator()( const Job *pLeft, const Job *pRight ) - { - return pLeft->tNextRun < pRight->tNextRun; - } - }; - typedef Bu::Heap JobHeap; - JobHeap hJobs; - JobId jidNext; - }; + /** + * A simple cron like system designed to be embedded in any program. This + * class creates a simple cron system that can run any number of jobs at + * customizable intervals or schedules. It does not support some of the + * more complex scheduling that some cron systems can do such as load + * balancing directly, but this could be done on the job side. + * + * This system is synchronous, it does not use any threads on it's own, but + * it is threadsafe, so a cron thread could be created if desired. + * + * The operation is fairly simple, jobs can be added at any time, and use + * any timer they would like, even custom timers. When it is time for a + * job to be run it signals the slot provided when the job was added. Every + * job slot recieves a handle to the job object so that it may control it's + * own lifetime and get information about itself. In addition, every job + * is assigned a unique ID that can be used to control it's operation + * at any time. + * + * By default a job will continually reschedule itself after being run + * unless it calls stop() on it's job object, it is removed using + * removeJob() on the cron object, or it is added with addJobOnce. + * + *@todo A minor change to the job execution system could allow a Timer to + * defer or reschedule execution instead of the job executing. This would, + * in effect, allow us to do every type of interesting scheduling that + * systems like fcron offer, including time constrained load-balanced + * execution. + */ + class MiniCron + { + public: + class Job; + class Timer; + typedef Bu::Signal1 CronSignal; + typedef int JobId; + + MiniCron(); + virtual ~MiniCron(); + + /** + * Tells you if there are jobs registered in the MiniCron. + *@returns true if there are jobs, false otherwise. + */ + virtual bool hasJobs(); + + /** + * If there are jobs, tells you the time the next one will execute. + *@returns The timestamp that the next job will execute at. + */ + virtual time_t getNextRun(); + + /** + * Tells you the time the job matching jid will run next. + *@returns The timestamp that the job jid will next run. + */ + virtual time_t getNextRun( JobId jid ); + + /** + * Call this regularly to execute all jobs that should be executed. + * This will loop until all jobs who's run time match the current time + * or are below the current time (we've missed them). + * If there is nothing to run, the runtime of this funcion is constant, + * it is very fast. Otherwise it executes at log(N) per job run, + * O(N*log(N)). + */ + virtual void poll(); + + /** + * Add a job for repeated scheduling. Pass in a slot to signal, and a + * Timer object to use to do the scheduling. This function returns a + * JobId which can be used at a later time to control the execution of + * the job. + */ + virtual JobId addJob( const Bu::String &sName, CronSignal sigJob, + const Timer &t ); + + /** + * Add a job for one time scheduling. Pass in a slot to signal, and a + * Timer object to use to schodule the one run of this job. This + * function returns a JobId which can be used at a later time to control + * the execution of the job. + */ + virtual JobId addJobOnce( const Bu::String &sName, CronSignal sigJob, + const Timer &t ); + + /** + * Remove a job, preventing all future runs of the job. If there is no + * job matching the given JobId then nothing will happen. However, this + * function is relatively expensive compared to the others in this class + * and has a worse case runtime of 2*N*log(N), still not that bad, and + * a O(N*log(N)). + */ + virtual void removeJob( JobId jid ); + + /** + * Executes the job specified right now. If bReschedule is true then + * the job is then removed from the queue and rescheduled as though + * it's time had come naturally to be run. Otherwise, it's run without + * interrupting the normal schedule. + */ + virtual void runJob( JobId jid, bool bReschedule=false ); + + /** + * Executes the job specified right now. If bReschedule is true then + * the job is then removed from the queue and rescheduled as though + * it's time had come naturally to be run. Otherwise, it's run without + * interrupting the normal schedule. + */ + virtual void runJob( const Bu::String &sName, bool bReschedule=false ); + + class JobInfo + { + public: + JobInfo( const Bu::String &sName, JobId jid, time_t tNext ); + virtual ~JobInfo(); + + bool operator<( const JobInfo &rhs ) const; + + Bu::String sName; + JobId jid; + time_t tNext; + }; + typedef Bu::List JobInfoList; + + JobInfoList getJobInfo(); + + /** + * The baseclass for timer/schedulers for MiniCron jobs. Classes that + * inherit from this are used to determine when jobs will run and at + * what interval. + */ + class Timer + { + public: + Timer(); + virtual ~Timer(); + + /** + * Called by MiniCron when each job is run to determine the next + * time that a job should be run. When a job is run, this function + * is actually called before the job is executed again so that the + * job can tell when the next time it will be run will be. + */ + virtual time_t nextTime()=0; + + /** + * This function should return a copy of the child class. + */ + virtual Timer *clone() const = 0; + }; + + /** + * Execute the job every tInterval seconds, also you can delay the + * first run by a different amount of time from the job's creation. + */ + class TimerInterval : public Timer + { + public: + TimerInterval( time_t tFirst, time_t tInterval ); + virtual ~TimerInterval(); + + virtual time_t nextTime(); + virtual Timer *clone() const + { return new TimerInterval( *this ); } + private: + time_t tNext; + time_t tInterval; + }; + + /** + * A much more general timer class that can be used for much more + * "cron-like" functionality. The constructor takes a string that + * describes the times that the job should be run. At the moment the + * following schemes are understood: + * + * "daily [hour] [minute]" + * "hourly [minute]" + * "weekly [day] [hour] [minute]" + * + * In these examples each word in [brackets] represents a number that + * matches the data type in the brackets. [day] is the number of days + * since sunday, 0-6. You can also use lowercase three character + * abbreviations for the day names. + * + * Many more forms follow. + */ + class TimerBasic : public Timer + { + public: + TimerBasic( const Bu::String &s ); + virtual ~TimerBasic(); + + virtual time_t nextTime(); + virtual Timer *clone() const + { return new TimerBasic( *this ); } + + private: + enum Token + { + tokDaily, + tokHourly, + tokWeekly, + tokMonthly, + tokYearly, + valInt, + tokErr, + tokEos + }; + Token lex( Bu::String::const_iterator &i ); + int lexInt( Bu::String::const_iterator &i ); + int iVal; //< A temp variable for parsing. + time_t tLast; + Bu::String sSpec; + }; + + /** + * Represents a MiniCron Job. This class is used for both internal + * job management as well as job slot interaction and control. Objects + * of this class are passed into the slots that are signaled when a job + * is executed. + */ + class Job + { + friend class Bu::MiniCron; + private: + Job( const Bu::String &sName, JobId jid, bool bRepeat=true ); + virtual ~Job(); + + public: + + /** + * Execute this job once, increment the runcount and schedule the + * next occurance of it. + */ + void run( bool bReschedule=true ); + + /** + * Get the time this job will next run. + */ + time_t getNextRun() const; + + /** + * Compute the time this job will next run. + */ + void calcNextRun(); + + /** + * Replace the current job timer with a new one, this will trigger + * a re-schedule. + */ + void setTimer( const Timer &t ); + + /** + * Stop execution of this job, never execute this job again. + */ + void stop(); + + /** + * Undo a previous stop. This will cause a job that has been + * stopped or even added with addJobOnce to be set for repeated + * scheduling. + */ + void resume(); + + /** + * Get the unique ID of this job. + */ + JobId getId() const; + + /** + * Get the timestamp this job was created. + */ + time_t getTimeCreated() const; + + /** + * Get the current run count of this job, how many times it has been + * executed. This is incremented before the slot is signaled. + */ + int getRunCount() const; + + /** + * Get the next time that this job will be run. Certain timers may + * have the ability to delay job executions, so this is the earliest + * time that the job may run. + */ + time_t getNextRunTime() const; + + /** + * Gets the name that was set when the job was created. + */ + Bu::String getName() const; + + private: + Bu::String sName; + CronSignal sigJob; + time_t tNextRun; + Timer *pTimer; + bool bContinue; + JobId jid; + time_t tAdded; + int iRunCount; + }; + + private: + struct JobPtrCmp + { + bool operator()( const Job *pLeft, const Job *pRight ) + { + return pLeft->tNextRun < pRight->tNextRun; + } + }; + typedef Bu::Heap JobHeap; + JobHeap hJobs; + JobId jidNext; + }; }; #endif diff --git a/src/stable/multiserver.cpp b/src/stable/multiserver.cpp index 8856117..bb1cacc 100644 --- a/src/stable/multiserver.cpp +++ b/src/stable/multiserver.cpp @@ -20,36 +20,36 @@ Bu::MultiServer::~MultiServer() } void Bu::MultiServer::addProtocol( Bu::Protocol *(*proc)(), int iPort, - int nPoolSize ) + int nPoolSize ) { - hProtos[iPort] = proc; - addPort( iPort, nPoolSize ); + hProtos[iPort] = proc; + addPort( iPort, nPoolSize ); } void Bu::MultiServer::addProtocol( Protocol *(*proc)(), const String &sAddr, - int iPort, int nPoolSize ) + int iPort, int nPoolSize ) { - hProtos[iPort] = proc; - addPort( sAddr, iPort, nPoolSize ); + hProtos[iPort] = proc; + addPort( sAddr, iPort, nPoolSize ); } void Bu::MultiServer::onNewConnection( Bu::Client *pClient, int nPort ) { - pClient->setProtocol( hProtos.get( nPort )() ); + pClient->setProtocol( hProtos.get( nPort )() ); } void Bu::MultiServer::onClosedConnection( Bu::Client *pClient ) { - delete pClient->getProtocol(); + delete pClient->getProtocol(); } void Bu::MultiServer::shutdown() { - Bu::Server::shutdown(); + Bu::Server::shutdown(); } void Bu::MultiServer::tick() { - Bu::Server::tick(); + Bu::Server::tick(); } diff --git a/src/stable/multiserver.h b/src/stable/multiserver.h index b2f633a..8a49bbd 100644 --- a/src/stable/multiserver.h +++ b/src/stable/multiserver.h @@ -13,45 +13,45 @@ namespace Bu { - class Protocol; - class Client; - - template - Protocol *genProtocol() - { - return new T; - } - - class MultiServer : protected Server - { - public: - MultiServer(); - virtual ~MultiServer(); - - void addProtocol( Protocol *(*proc)(), int iPort, int nPoolSize=40 ); - void addProtocol( Protocol *(*proc)(), const String &sAddr, int iPort, - int nPoolSize=40 ); - - void scan() - { - Server::scan(); - } - - void setTimeout( int nTimeoutSec, int nTimeoutUSec=0 ) - { - Server::setTimeout( nTimeoutSec, nTimeoutUSec ); - } - - virtual void onNewConnection( Client *pClient, int nPort ); - virtual void onClosedConnection( Client *pClient ); - - void shutdown(); - - void tick(); - - private: - Bu::Hash hProtos; - }; + class Protocol; + class Client; + + template + Protocol *genProtocol() + { + return new T; + } + + class MultiServer : protected Server + { + public: + MultiServer(); + virtual ~MultiServer(); + + void addProtocol( Protocol *(*proc)(), int iPort, int nPoolSize=40 ); + void addProtocol( Protocol *(*proc)(), const String &sAddr, int iPort, + int nPoolSize=40 ); + + void scan() + { + Server::scan(); + } + + void setTimeout( int nTimeoutSec, int nTimeoutUSec=0 ) + { + Server::setTimeout( nTimeoutSec, nTimeoutUSec ); + } + + virtual void onNewConnection( Client *pClient, int nPort ); + virtual void onClosedConnection( Client *pClient ); + + void shutdown(); + + void tick(); + + private: + Bu::Hash hProtos; + }; } #endif diff --git a/src/stable/mutex.cpp b/src/stable/mutex.cpp index 947364c..0391d7a 100644 --- a/src/stable/mutex.cpp +++ b/src/stable/mutex.cpp @@ -9,26 +9,26 @@ Bu::Mutex::Mutex() { - pthread_mutex_init( &mutex, NULL ); + pthread_mutex_init( &mutex, NULL ); } Bu::Mutex::~Mutex() { - pthread_mutex_destroy( &mutex ); + pthread_mutex_destroy( &mutex ); } int Bu::Mutex::lock() { - return pthread_mutex_lock( &mutex ); + return pthread_mutex_lock( &mutex ); } int Bu::Mutex::unlock() { - return pthread_mutex_unlock( &mutex ); + return pthread_mutex_unlock( &mutex ); } int Bu::Mutex::trylock() { - return pthread_mutex_trylock( &mutex ); + return pthread_mutex_trylock( &mutex ); } diff --git a/src/stable/mutex.h b/src/stable/mutex.h index 1898118..23963e3 100644 --- a/src/stable/mutex.h +++ b/src/stable/mutex.h @@ -12,57 +12,57 @@ namespace Bu { - /** - * Simple mutex wrapper. Currently this doesn't do anything extra for you - * except keep all of the functionality together in an OO sorta' way and - * keep you from having to worry about cleaning up your mutexes properly, - * or initing them. - *@ingroup Threading - */ - class Mutex - { - public: - /** - * Create an unlocked mutex. - */ - Mutex(); - - /** - * Destroy a mutex. This can only be done when a mutex is unlocked. - * Failure to unlock before destroying a mutex object could cause it to - * wait for the mutex to unlock, the odds of which are usually farily - * low at deconstruction time. - */ - ~Mutex(); + /** + * Simple mutex wrapper. Currently this doesn't do anything extra for you + * except keep all of the functionality together in an OO sorta' way and + * keep you from having to worry about cleaning up your mutexes properly, + * or initing them. + *@ingroup Threading + */ + class Mutex + { + public: + /** + * Create an unlocked mutex. + */ + Mutex(); + + /** + * Destroy a mutex. This can only be done when a mutex is unlocked. + * Failure to unlock before destroying a mutex object could cause it to + * wait for the mutex to unlock, the odds of which are usually farily + * low at deconstruction time. + */ + ~Mutex(); - /** - * Lock the mutex. This causes all future calls to lock on this - * instance of mutex to block until the first thread that called mutex - * unlocks it. At that point the next thread that called lock will get - * a chance to go to work. Because of the nature of a mutex lock it is - * a very bad idea to do any kind of serious or rather time consuming - * computation within a locked section. This can cause thread-deadlock - * and your program may hang. - */ - int lock(); + /** + * Lock the mutex. This causes all future calls to lock on this + * instance of mutex to block until the first thread that called mutex + * unlocks it. At that point the next thread that called lock will get + * a chance to go to work. Because of the nature of a mutex lock it is + * a very bad idea to do any kind of serious or rather time consuming + * computation within a locked section. This can cause thread-deadlock + * and your program may hang. + */ + int lock(); - /** - * Unlock the mutex. This allows the next thread that asked for a lock - * to lock the mutex and continue with execution. - */ - int unlock(); + /** + * Unlock the mutex. This allows the next thread that asked for a lock + * to lock the mutex and continue with execution. + */ + int unlock(); - /** - * Try to lock the mutex. This is the option to go with if you cannot - * avoid putting lengthy operations within a locked section. trylock - * will attempt to lock the mutex, if the mutex is already locked this - * function returns immediately with an error code. - */ - int trylock(); + /** + * Try to lock the mutex. This is the option to go with if you cannot + * avoid putting lengthy operations within a locked section. trylock + * will attempt to lock the mutex, if the mutex is already locked this + * function returns immediately with an error code. + */ + int trylock(); - protected: - pthread_mutex_t mutex; /**< The internal mutex reference. */ - }; + protected: + pthread_mutex_t mutex; /**< The internal mutex reference. */ + }; } #endif diff --git a/src/stable/mutexlocker.cpp b/src/stable/mutexlocker.cpp index 90b730e..c8465a3 100644 --- a/src/stable/mutexlocker.cpp +++ b/src/stable/mutexlocker.cpp @@ -2,23 +2,23 @@ #include "bu/mutex.h" Bu::MutexLocker::MutexLocker( Bu::Mutex &mu ) : - mu( mu ) + mu( mu ) { - mu.lock(); + mu.lock(); } Bu::MutexLocker::~MutexLocker() { - mu.unlock(); + mu.unlock(); } void Bu::MutexLocker::unlock() { - mu.unlock(); + mu.unlock(); } void Bu::MutexLocker::relock() { - mu.lock(); + mu.lock(); } diff --git a/src/stable/mutexlocker.h b/src/stable/mutexlocker.h index 7c3c97e..30e71e6 100644 --- a/src/stable/mutexlocker.h +++ b/src/stable/mutexlocker.h @@ -3,19 +3,19 @@ namespace Bu { - class Mutex; - class MutexLocker - { - public: - MutexLocker( Mutex &mu ); - virtual ~MutexLocker(); + class Mutex; + class MutexLocker + { + public: + MutexLocker( Mutex &mu ); + virtual ~MutexLocker(); - void unlock(); - void relock(); + void unlock(); + void relock(); - private: - Mutex μ - }; + private: + Mutex μ + }; }; #endif diff --git a/src/stable/myriad.cpp b/src/stable/myriad.cpp index 4be82f0..2a6a725 100644 --- a/src/stable/myriad.cpp +++ b/src/stable/myriad.cpp @@ -16,720 +16,720 @@ using Bu::sio; using Bu::Fmt; -#define Myriad_MAGIC_CODE ((unsigned char *)"\x0a\xd3\xfa\x84") +#define Myriad_MAGIC_CODE ((unsigned char *)"\x0a\xd3\xfa\x84") namespace Bu { - subExceptionDef( MyriadException ) - template t blkDiv( t total, t block ) { - return (total/block)+((total%block==0)?(0):(1)); - } + subExceptionDef( MyriadException ) + template t blkDiv( t total, t block ) { + return (total/block)+((total%block==0)?(0):(1)); + } } Bu::Myriad::Myriad( Bu::Stream &sStore, int iBlockSize, int iPreallocate ) : - sStore( sStore ), - iBlockSize( iBlockSize ), - iBlocks( 0 ), - iUsed( 0 ), - bHeaderChanged( false ) -{ - try - { - initialize(); - } - catch( Bu::MyriadException &e ) - { - if( e.getErrorCode() == MyriadException::emptyStream ) - { - initialize( iBlockSize, iPreallocate ); - } - else - { - throw; - } - } + sStore( sStore ), + iBlockSize( iBlockSize ), + iBlocks( 0 ), + iUsed( 0 ), + bHeaderChanged( false ) +{ + try + { + initialize(); + } + catch( Bu::MyriadException &e ) + { + if( e.getErrorCode() == MyriadException::emptyStream ) + { + initialize( iBlockSize, iPreallocate ); + } + else + { + throw; + } + } } Bu::Myriad::~Myriad() { - mActiveBlocks.lock(); - if( !hActiveBlocks.isEmpty() ) - { - sio << "Bu::Myriad::~Myriad(): Error: There are " - << hActiveBlocks.getSize() << " unsynced blocks!" << sio.nl; - } - mActiveBlocks.unlock(); - sync(); + mActiveBlocks.lock(); + if( !hActiveBlocks.isEmpty() ) + { + sio << "Bu::Myriad::~Myriad(): Error: There are " + << hActiveBlocks.getSize() << " unsynced blocks!" << sio.nl; + } + mActiveBlocks.unlock(); + sync(); - for( StreamArray::iterator i = aStreams.begin(); i; i++ ) - { - delete *i; - } + for( StreamArray::iterator i = aStreams.begin(); i; i++ ) + { + delete *i; + } } void Bu::Myriad::sync() { - updateHeader(); + updateHeader(); - mActiveBlocks.lock(); - for( BlockHash::iterator i = hActiveBlocks.begin(); i; i++ ) - { - if( (*i)->bChanged ) - { - syncBlock( *i ); - } - } - mActiveBlocks.unlock(); + mActiveBlocks.lock(); + for( BlockHash::iterator i = hActiveBlocks.begin(); i; i++ ) + { + if( (*i)->bChanged ) + { + syncBlock( *i ); + } + } + mActiveBlocks.unlock(); } void Bu::Myriad::initialize() { - MutexLocker mLock( mHeader ); - lFreeBlocks.clear(); - sStore.setPosEnd( 0 ); - Bu::size iSize = sStore.tell(); - sStore.setPos( 0 ); - - unsigned char buf[4]; - if( sStore.read( buf, 4 ) < 4 ) - throw MyriadException( MyriadException::emptyStream, - "Input stream appears to be empty."); - if( memcmp( buf, Myriad_MAGIC_CODE, 4 ) ) - { - throw MyriadException( MyriadException::invalidFormat, - "Stream does not appear to be a valid Myriad format."); - } - sStore.read( buf, 2 ); - if( buf[0] != 1 ) - throw MyriadException( MyriadException::badVersion, - "We can only handle version 1 for now."); - if( buf[1] != 32 ) - throw MyriadException( MyriadException::invalidWordSize, - "We can only handle 32-bit words at the moment."); - sStore.read( &iBlockSize, 4 ); - int iStreams; - sStore.read( &iStreams, 4 ); - - iBlocks = iSize/iBlockSize; - //sio << "Myriad: iSize=" << iSize << ", iBlockSize=" << iBlockSize - // << ", iBlocks=" << iBlocks << ", iStreams=" << iStreams << sio.nl; - - int iHeaderSize = 14 + 8 + 4; - int iHeaderBlocks = 0; //blkDiv( iHeaderSize+4, iBlockSize ); - - while( iHeaderSize > iHeaderBlocks*iBlockSize ) - { - iHeaderBlocks = blkDiv( iHeaderSize+4, iBlockSize ); - iHeaderSize = 14 + 8 + 4*iHeaderBlocks; - } - - //sio << "Myriad: iHeaderSize=" << iHeaderSize - // << ", iHeaderBlocks=" << iHeaderBlocks << sio.nl; - - Stream *pFakeHdr = new Stream; - pFakeHdr->iId = 0; - pFakeHdr->iSize = iHeaderSize; - for( int j = 0; j < iHeaderBlocks; j++ ) - { - pFakeHdr->aBlocks.append( j ); - } - -// sio << "Blocks: " << iBlocks << " (size = " << iSize << "/" << iBlockSize -// << ")" << sio.nl; - Bu::BitString bsBlockUsed( iBlocks, false ); - bsBlockUsed.clear(); - -// bool bCanSkip = false; // Can skip around, post initial header stream i/o - MyriadStream *pIn = new MyriadStream( *this, pFakeHdr ); - pIn->setPos( sStore.tell() ); - for( int j = 0; j < iStreams; j++ ) - { - aStreams.append( new Stream() ); - Stream &s = *aStreams[j]; - pIn->read( &s.iId, 4 ); - pIn->read( &s.iSize, 4 ); - int iSBlocks = blkDiv(s.iSize, iBlockSize); - // sio << "Myriad: - Stream::iId=" << s.iId - // << ", Stream::iSize=" << s.iSize - // << ", Stream::aBlocks=" << iSBlocks - // << ", pIn->tell()=" << pIn->tell() << sio.nl; - for( int k = 0; k < iSBlocks; k++ ) - { - int iBId; - pIn->read( &iBId, 4 ); - // sio << "Myriad: - iBId=" << iBId - // << ", iStartPos=" << iBId*iBlockSize - // << ", pIn->tell()=" << pIn->tell() << sio.nl; - s.aBlocks.append( iBId ); - bsBlockUsed.setBit( iBId ); - iUsed++; - if( (j == 0 && k == iHeaderBlocks-1) ) - { - // sio << "Myriad: - End of prepartition, unlocking skipping." - // << sio.nl; -// bCanSkip = true; - MyriadStream *pTmp = new MyriadStream( *this, aStreams[0] ); - // sio << "Myriad - Position = " << pIn->tell() << sio.nl; - pTmp->setPos( pIn->tell() ); - delete pIn; - delete pFakeHdr; - pIn = pTmp; - } - } - } - delete pIn; - - for( int j = 0; j < iBlocks; j++ ) - { - if( bsBlockUsed.getBit( j ) == false ) - { -// sio << "Preinitialized block " << j << " is free." << sio.nl; - lFreeBlocks.append( j ); - } - } -// sio << "Myriad: Blocks used: " << bsBlockUsed.toString() << sio.nl; + MutexLocker mLock( mHeader ); + lFreeBlocks.clear(); + sStore.setPosEnd( 0 ); + Bu::size iSize = sStore.tell(); + sStore.setPos( 0 ); + + unsigned char buf[4]; + if( sStore.read( buf, 4 ) < 4 ) + throw MyriadException( MyriadException::emptyStream, + "Input stream appears to be empty."); + if( memcmp( buf, Myriad_MAGIC_CODE, 4 ) ) + { + throw MyriadException( MyriadException::invalidFormat, + "Stream does not appear to be a valid Myriad format."); + } + sStore.read( buf, 2 ); + if( buf[0] != 1 ) + throw MyriadException( MyriadException::badVersion, + "We can only handle version 1 for now."); + if( buf[1] != 32 ) + throw MyriadException( MyriadException::invalidWordSize, + "We can only handle 32-bit words at the moment."); + sStore.read( &iBlockSize, 4 ); + int iStreams; + sStore.read( &iStreams, 4 ); + + iBlocks = iSize/iBlockSize; + //sio << "Myriad: iSize=" << iSize << ", iBlockSize=" << iBlockSize + // << ", iBlocks=" << iBlocks << ", iStreams=" << iStreams << sio.nl; + + int iHeaderSize = 14 + 8 + 4; + int iHeaderBlocks = 0; //blkDiv( iHeaderSize+4, iBlockSize ); + + while( iHeaderSize > iHeaderBlocks*iBlockSize ) + { + iHeaderBlocks = blkDiv( iHeaderSize+4, iBlockSize ); + iHeaderSize = 14 + 8 + 4*iHeaderBlocks; + } + + //sio << "Myriad: iHeaderSize=" << iHeaderSize + // << ", iHeaderBlocks=" << iHeaderBlocks << sio.nl; + + Stream *pFakeHdr = new Stream; + pFakeHdr->iId = 0; + pFakeHdr->iSize = iHeaderSize; + for( int j = 0; j < iHeaderBlocks; j++ ) + { + pFakeHdr->aBlocks.append( j ); + } + +// sio << "Blocks: " << iBlocks << " (size = " << iSize << "/" << iBlockSize +// << ")" << sio.nl; + Bu::BitString bsBlockUsed( iBlocks, false ); + bsBlockUsed.clear(); + +// bool bCanSkip = false; // Can skip around, post initial header stream i/o + MyriadStream *pIn = new MyriadStream( *this, pFakeHdr ); + pIn->setPos( sStore.tell() ); + for( int j = 0; j < iStreams; j++ ) + { + aStreams.append( new Stream() ); + Stream &s = *aStreams[j]; + pIn->read( &s.iId, 4 ); + pIn->read( &s.iSize, 4 ); + int iSBlocks = blkDiv(s.iSize, iBlockSize); + // sio << "Myriad: - Stream::iId=" << s.iId + // << ", Stream::iSize=" << s.iSize + // << ", Stream::aBlocks=" << iSBlocks + // << ", pIn->tell()=" << pIn->tell() << sio.nl; + for( int k = 0; k < iSBlocks; k++ ) + { + int iBId; + pIn->read( &iBId, 4 ); + // sio << "Myriad: - iBId=" << iBId + // << ", iStartPos=" << iBId*iBlockSize + // << ", pIn->tell()=" << pIn->tell() << sio.nl; + s.aBlocks.append( iBId ); + bsBlockUsed.setBit( iBId ); + iUsed++; + if( (j == 0 && k == iHeaderBlocks-1) ) + { + // sio << "Myriad: - End of prepartition, unlocking skipping." + // << sio.nl; +// bCanSkip = true; + MyriadStream *pTmp = new MyriadStream( *this, aStreams[0] ); + // sio << "Myriad - Position = " << pIn->tell() << sio.nl; + pTmp->setPos( pIn->tell() ); + delete pIn; + delete pFakeHdr; + pIn = pTmp; + } + } + } + delete pIn; + + for( int j = 0; j < iBlocks; j++ ) + { + if( bsBlockUsed.getBit( j ) == false ) + { +// sio << "Preinitialized block " << j << " is free." << sio.nl; + lFreeBlocks.append( j ); + } + } +// sio << "Myriad: Blocks used: " << bsBlockUsed.toString() << sio.nl; } void Bu::Myriad::initialize( int iBlockSize, int iPreAllocate ) { - MutexLocker mLock( mHeader ); - lFreeBlocks.clear(); - - for( StreamArray::iterator i = aStreams.begin(); i; i++ ) - { - delete *i; - } - aStreams.clear(); - iUsed = 0; - - int iHeaderSize = 14 + 8 + 4; - int iHeaderBlocks = 0; //blkDiv( iHeaderSize+4, iBlockSize ); - char cBuf = 1; - int iBuf = 0; - - Stream *pStr = new Stream; - pStr->iId = 0; - - while( iHeaderSize > iHeaderBlocks*iBlockSize ) - { - iHeaderBlocks = blkDiv( iHeaderSize+4, iBlockSize ); - iHeaderSize = 14 + 8 + 4*iHeaderBlocks; - } - - iPreAllocate += iHeaderBlocks; - - //sio << "Myriad: iHeaderSize=" << iHeaderSize << ", iBlockSize=" - // << iBlockSize << ", iHeaderBlocks=" << iHeaderBlocks << sio.nl; - -// bsBlockUsed.setSize( iPreAllocate, true ); - iUsed++; - - char *pBlock = new char[iBlockSize]; - memset( pBlock, 0, iBlockSize ); - for( int j = 0; j < iPreAllocate; j++ ) - { - sStore.write( pBlock, iBlockSize ); - } - delete[] (char *)pBlock; - - sStore.setPos( 0 ); - - // Magic number - sStore.write( Myriad_MAGIC_CODE, 4 ); - - // Version (0) - sStore.write( &cBuf, 1 ); - - // Bits per int - cBuf = 32; - sStore.write( &cBuf, 1 ); - - // The size of each block - sStore.write( &iBlockSize, 4 ); - - iBuf = 1; - // The number of streams - sStore.write( &iBuf, 4 ); - - // Stream header - iBuf = 0; - sStore.write( &iBuf, 4 ); - sStore.write( &iHeaderSize, 4 ); - for( iBuf = 0; iBuf < iHeaderBlocks; iBuf++ ) - { - sStore.write( &iBuf, 4 ); - } - - this->iBlockSize = iBlockSize; - this->iBlocks = iPreAllocate; - - pStr->iSize = sStore.tell(); -// sio << "Myriad: Actual end of header stream = " << pStr->iSize << sio.nl; - - pStr->iSize = iHeaderSize; - for( int j = 0; j < iHeaderBlocks; j++ ) - { -// sio << "Started block " << j << " is header." << sio.nl; - pStr->aBlocks.append( j ); -// bsBlockUsed.setBit( j ); - iUsed++; - } - for( int j = iHeaderBlocks; j < this->iBlocks; j++ ) - { -// sio << "Started block " << j << " is free." << sio.nl; - lFreeBlocks.append( j ); - } - - aStreams.append( pStr ); - - //sio << bsBlockUsed.toString() << " - " << pStr->aBlocks << sio.nl; - - bHeaderChanged = true; - //hStreams.insert( 0, BlockArray( 0 ) ); + MutexLocker mLock( mHeader ); + lFreeBlocks.clear(); + + for( StreamArray::iterator i = aStreams.begin(); i; i++ ) + { + delete *i; + } + aStreams.clear(); + iUsed = 0; + + int iHeaderSize = 14 + 8 + 4; + int iHeaderBlocks = 0; //blkDiv( iHeaderSize+4, iBlockSize ); + char cBuf = 1; + int iBuf = 0; + + Stream *pStr = new Stream; + pStr->iId = 0; + + while( iHeaderSize > iHeaderBlocks*iBlockSize ) + { + iHeaderBlocks = blkDiv( iHeaderSize+4, iBlockSize ); + iHeaderSize = 14 + 8 + 4*iHeaderBlocks; + } + + iPreAllocate += iHeaderBlocks; + + //sio << "Myriad: iHeaderSize=" << iHeaderSize << ", iBlockSize=" + // << iBlockSize << ", iHeaderBlocks=" << iHeaderBlocks << sio.nl; + +// bsBlockUsed.setSize( iPreAllocate, true ); + iUsed++; + + char *pBlock = new char[iBlockSize]; + memset( pBlock, 0, iBlockSize ); + for( int j = 0; j < iPreAllocate; j++ ) + { + sStore.write( pBlock, iBlockSize ); + } + delete[] (char *)pBlock; + + sStore.setPos( 0 ); + + // Magic number + sStore.write( Myriad_MAGIC_CODE, 4 ); + + // Version (0) + sStore.write( &cBuf, 1 ); + + // Bits per int + cBuf = 32; + sStore.write( &cBuf, 1 ); + + // The size of each block + sStore.write( &iBlockSize, 4 ); + + iBuf = 1; + // The number of streams + sStore.write( &iBuf, 4 ); + + // Stream header + iBuf = 0; + sStore.write( &iBuf, 4 ); + sStore.write( &iHeaderSize, 4 ); + for( iBuf = 0; iBuf < iHeaderBlocks; iBuf++ ) + { + sStore.write( &iBuf, 4 ); + } + + this->iBlockSize = iBlockSize; + this->iBlocks = iPreAllocate; + + pStr->iSize = sStore.tell(); +// sio << "Myriad: Actual end of header stream = " << pStr->iSize << sio.nl; + + pStr->iSize = iHeaderSize; + for( int j = 0; j < iHeaderBlocks; j++ ) + { +// sio << "Started block " << j << " is header." << sio.nl; + pStr->aBlocks.append( j ); +// bsBlockUsed.setBit( j ); + iUsed++; + } + for( int j = iHeaderBlocks; j < this->iBlocks; j++ ) + { +// sio << "Started block " << j << " is free." << sio.nl; + lFreeBlocks.append( j ); + } + + aStreams.append( pStr ); + + //sio << bsBlockUsed.toString() << " - " << pStr->aBlocks << sio.nl; + + bHeaderChanged = true; + //hStreams.insert( 0, BlockArray( 0 ) ); } void Bu::Myriad::updateHeader() { - MutexLocker mLock( mHeader ); - - if( bHeaderChanged == false ) - return; - if( !sStore.canWrite() ) - return; - - char cBuf; - int iBuf; - - //for( StreamArray::iterator i = aStreams.begin(); i; i++ ) - //{ - // sio << "Myriad: Stream " << Fmt(4) << (*i)->iId << ": " << (*i)->aBlocks << sio.nl; - //} - - // Compute the new size of the header. - int iHeaderSize = 14 + 8*aStreams.getSize(); -// sio << "Myriad: updateHeader: aStreams.getSize() = " << aStreams.getSize() -// << sio.nl; - for( StreamArray::iterator i = aStreams.begin(); i; i++ ) - { - iHeaderSize += 4*(*i)->aBlocks.getSize(); -// sio << "Myriad: updateHeader: (*i)->aBlocks.getSize() = " -// << (*i)->aBlocks.getSize() << sio.nl; - } - int iNewBlocks = blkDiv( iHeaderSize, iBlockSize ); - while( iNewBlocks > aStreams[0]->aBlocks.getSize() ) - { - int iBlock = findEmptyBlock(); -// sio << "Myriad: updateHeader: Appending block " << iBlock -// << " to header." << sio.nl; - aStreams[0]->aBlocks.append( iBlock ); -// bsBlockUsed.setBit( iBlock ); - iUsed++; - iHeaderSize += 4; - iNewBlocks = blkDiv( iHeaderSize, iBlockSize ); - } - aStreams[0]->iSize = iHeaderSize; -// sio << "Myriad: updateHeader: iHeaderSize=" << iHeaderSize -// << ", iNewBlocks=" << iNewBlocks << ", curBlocks=" -// << aStreams[0]->aBlocks.getSize() << sio.nl; - - MyriadStream sHdr( *this, aStreams[0] ); - sHdr.write( Myriad_MAGIC_CODE, 4 ); - - // Version (1) - cBuf = 1; - sHdr.write( &cBuf, 1 ); - - // Bits per int - cBuf = 32; - sHdr.write( &cBuf, 1 ); - - // The size of each block - sHdr.write( &iBlockSize, 4 ); - - iBuf = aStreams.getSize(); - // The number of streams - sHdr.write( &iBuf, 4 ); - - for( StreamArray::iterator i = aStreams.begin(); i; i++ ) - { - sHdr.write( &(*i)->iId, 4 ); - sHdr.write( &(*i)->iSize, 4 ); - int iUsedBlocks = blkDiv( (*i)->iSize, iBlockSize ); -// for( BlockArray::iterator j = (*i)->aBlocks.begin(); j; j++ ) - for( int j = 0; j < iUsedBlocks; j++ ) - { - sHdr.write( &(*i)->aBlocks[j], 4 ); - } - } - - bHeaderChanged = false; + MutexLocker mLock( mHeader ); + + if( bHeaderChanged == false ) + return; + if( !sStore.canWrite() ) + return; + + char cBuf; + int iBuf; + + //for( StreamArray::iterator i = aStreams.begin(); i; i++ ) + //{ + // sio << "Myriad: Stream " << Fmt(4) << (*i)->iId << ": " << (*i)->aBlocks << sio.nl; + //} + + // Compute the new size of the header. + int iHeaderSize = 14 + 8*aStreams.getSize(); +// sio << "Myriad: updateHeader: aStreams.getSize() = " << aStreams.getSize() +// << sio.nl; + for( StreamArray::iterator i = aStreams.begin(); i; i++ ) + { + iHeaderSize += 4*(*i)->aBlocks.getSize(); +// sio << "Myriad: updateHeader: (*i)->aBlocks.getSize() = " +// << (*i)->aBlocks.getSize() << sio.nl; + } + int iNewBlocks = blkDiv( iHeaderSize, iBlockSize ); + while( iNewBlocks > aStreams[0]->aBlocks.getSize() ) + { + int iBlock = findEmptyBlock(); +// sio << "Myriad: updateHeader: Appending block " << iBlock +// << " to header." << sio.nl; + aStreams[0]->aBlocks.append( iBlock ); +// bsBlockUsed.setBit( iBlock ); + iUsed++; + iHeaderSize += 4; + iNewBlocks = blkDiv( iHeaderSize, iBlockSize ); + } + aStreams[0]->iSize = iHeaderSize; +// sio << "Myriad: updateHeader: iHeaderSize=" << iHeaderSize +// << ", iNewBlocks=" << iNewBlocks << ", curBlocks=" +// << aStreams[0]->aBlocks.getSize() << sio.nl; + + MyriadStream sHdr( *this, aStreams[0] ); + sHdr.write( Myriad_MAGIC_CODE, 4 ); + + // Version (1) + cBuf = 1; + sHdr.write( &cBuf, 1 ); + + // Bits per int + cBuf = 32; + sHdr.write( &cBuf, 1 ); + + // The size of each block + sHdr.write( &iBlockSize, 4 ); + + iBuf = aStreams.getSize(); + // The number of streams + sHdr.write( &iBuf, 4 ); + + for( StreamArray::iterator i = aStreams.begin(); i; i++ ) + { + sHdr.write( &(*i)->iId, 4 ); + sHdr.write( &(*i)->iSize, 4 ); + int iUsedBlocks = blkDiv( (*i)->iSize, iBlockSize ); +// for( BlockArray::iterator j = (*i)->aBlocks.begin(); j; j++ ) + for( int j = 0; j < iUsedBlocks; j++ ) + { + sHdr.write( &(*i)->aBlocks[j], 4 ); + } + } + + bHeaderChanged = false; } int Bu::Myriad::createStream( int iPreAllocate ) { - MutexLocker mLock( mHeader ); + MutexLocker mLock( mHeader ); - Stream *pStr = new Stream(); - pStr->iId = aStreams.last()->iId+1; - //sio << "Myriad: New stream id=" << pStr->iId << ", iPreAllocate=" - // << iPreAllocate << sio.nl; - pStr->iSize = 0; - aStreams.append( pStr ); + Stream *pStr = new Stream(); + pStr->iId = aStreams.last()->iId+1; + //sio << "Myriad: New stream id=" << pStr->iId << ", iPreAllocate=" + // << iPreAllocate << sio.nl; + pStr->iSize = 0; + aStreams.append( pStr ); - for( int j = 0; j < iPreAllocate; j++ ) - { - int iFreeBlock = findEmptyBlock(); -// sio << "Myriad: Adding block " << iFreeBlock << sio.nl; - pStr->aBlocks.append( iFreeBlock ); -// bsBlockUsed.setBit( iFreeBlock ); - iUsed++; - } + for( int j = 0; j < iPreAllocate; j++ ) + { + int iFreeBlock = findEmptyBlock(); +// sio << "Myriad: Adding block " << iFreeBlock << sio.nl; + pStr->aBlocks.append( iFreeBlock ); +// bsBlockUsed.setBit( iFreeBlock ); + iUsed++; + } - bHeaderChanged = true; + bHeaderChanged = true; - return pStr->iId; + return pStr->iId; } int Bu::Myriad::createStreamWithId( int iId, int iPreAllocate ) { - MutexLocker mLock( mHeader ); - - try - { - findStream( iId ); - throw MyriadException( MyriadException::streamExists, - "There is already a stream with the given id."); - } - catch( MyriadException &e ) - { - Stream *pStr = new Stream(); - pStr->iId = iId; - //sio << "Myriad: New stream id=" << pStr->iId << ", iPreAllocate=" - // << iPreAllocate << sio.nl; - pStr->iSize = 0; - if( aStreams.last()->iId < iId ) - { - aStreams.append( pStr ); - } - else - { - for( StreamArray::iterator i = aStreams.begin(); i; i++ ) - { - if( (*i)->iId > iId ) - { - aStreams.insert( i, pStr ); - break; - } - } - } - - for( int j = 0; j < iPreAllocate; j++ ) - { - int iFreeBlock = findEmptyBlock(); - // sio << "Myriad: Adding block " << iFreeBlock << sio.nl; - pStr->aBlocks.append( iFreeBlock ); -// bsBlockUsed.setBit( iFreeBlock ); - iUsed++; - } - - bHeaderChanged = true; - - return pStr->iId; - } + MutexLocker mLock( mHeader ); + + try + { + findStream( iId ); + throw MyriadException( MyriadException::streamExists, + "There is already a stream with the given id."); + } + catch( MyriadException &e ) + { + Stream *pStr = new Stream(); + pStr->iId = iId; + //sio << "Myriad: New stream id=" << pStr->iId << ", iPreAllocate=" + // << iPreAllocate << sio.nl; + pStr->iSize = 0; + if( aStreams.last()->iId < iId ) + { + aStreams.append( pStr ); + } + else + { + for( StreamArray::iterator i = aStreams.begin(); i; i++ ) + { + if( (*i)->iId > iId ) + { + aStreams.insert( i, pStr ); + break; + } + } + } + + for( int j = 0; j < iPreAllocate; j++ ) + { + int iFreeBlock = findEmptyBlock(); + // sio << "Myriad: Adding block " << iFreeBlock << sio.nl; + pStr->aBlocks.append( iFreeBlock ); +// bsBlockUsed.setBit( iFreeBlock ); + iUsed++; + } + + bHeaderChanged = true; + + return pStr->iId; + } } int Bu::Myriad::findEmptyBlock() { - bHeaderChanged = true; + bHeaderChanged = true; - if( lFreeBlocks.isEmpty() ) - { - sStore.setSize( (iBlocks+1)*(Bu::size)iBlockSize ); - return iBlocks++; - } - else - { - return lFreeBlocks.dequeue(); - } + if( lFreeBlocks.isEmpty() ) + { + sStore.setSize( (iBlocks+1)*(Bu::size)iBlockSize ); + return iBlocks++; + } + else + { + return lFreeBlocks.dequeue(); + } } void Bu::Myriad::deleteStream( int iId ) { - MutexLocker mLock( mHeader ); - - if( iId < 0 ) - throw MyriadException( MyriadException::invalidStreamId, - "Invalid stream id."); - if( iId == 0 ) - throw MyriadException( MyriadException::protectedStream, - "You cannot delete stream zero, it is protected."); - for( StreamArray::iterator i = aStreams.begin(); i; i++ ) - { - if( (*i)->iId == iId ) - { - Stream *pStream = *i; - for( BlockArray::iterator j = pStream->aBlocks.begin(); j; j++ ) - { - lFreeBlocks.append( *j ); -// bsBlockUsed.setBit( *j, false ); - iUsed--; - } - aStreams.erase( i ); - bHeaderChanged = true; - delete pStream; - return; - } - } + MutexLocker mLock( mHeader ); + + if( iId < 0 ) + throw MyriadException( MyriadException::invalidStreamId, + "Invalid stream id."); + if( iId == 0 ) + throw MyriadException( MyriadException::protectedStream, + "You cannot delete stream zero, it is protected."); + for( StreamArray::iterator i = aStreams.begin(); i; i++ ) + { + if( (*i)->iId == iId ) + { + Stream *pStream = *i; + for( BlockArray::iterator j = pStream->aBlocks.begin(); j; j++ ) + { + lFreeBlocks.append( *j ); +// bsBlockUsed.setBit( *j, false ); + iUsed--; + } + aStreams.erase( i ); + bHeaderChanged = true; + delete pStream; + return; + } + } } Bu::Array Bu::Myriad::getStreamIds() { - MutexLocker mLock( mHeader ); + MutexLocker mLock( mHeader ); - Bu::Array aRet( aStreams.getSize() ); - for( StreamArray::iterator i = aStreams.begin(); i; i++ ) - { - aRet.append( (*i)->iId ); - } + Bu::Array aRet( aStreams.getSize() ); + for( StreamArray::iterator i = aStreams.begin(); i; i++ ) + { + aRet.append( (*i)->iId ); + } - return aRet; + return aRet; } int Bu::Myriad::getStreamSize( int iId ) { - MutexLocker mLock( mHeader ); + MutexLocker mLock( mHeader ); - return findStream( iId )->iSize; + return findStream( iId )->iSize; } bool Bu::Myriad::hasStream( int iId ) { - MutexLocker mLock( mHeader ); + MutexLocker mLock( mHeader ); - try - { - findStream( iId ); - return true; - }catch(...) - { - return false; - } + try + { + findStream( iId ); + return true; + }catch(...) + { + return false; + } } Bu::MyriadStream Bu::Myriad::openStream( int iId ) { - MutexLocker mLock( mHeader ); + MutexLocker mLock( mHeader ); - //sio << "Myriad: Request to open stream: " << iId << sio.nl; - return MyriadStream( *this, findStream( iId ) ); + //sio << "Myriad: Request to open stream: " << iId << sio.nl; + return MyriadStream( *this, findStream( iId ) ); } int Bu::Myriad::getNumStreams() { - MutexLocker mLock( mHeader ); + MutexLocker mLock( mHeader ); - return aStreams.getSize(); + return aStreams.getSize(); } int Bu::Myriad::getBlockSize() { - return iBlockSize; + return iBlockSize; } int Bu::Myriad::getNumBlocks() { - return iBlocks; + return iBlocks; } int Bu::Myriad::getNumUsedBlocks() { - return iUsed; + return iUsed; } Bu::size Bu::Myriad::getTotalUsedBytes() { - MutexLocker mLock( mHeader ); + MutexLocker mLock( mHeader ); - Bu::size iTotalSize = 0; - for( StreamArray::iterator i = aStreams.begin(); i; i++ ) - { - iTotalSize += (*i)->iSize; - } - return iTotalSize; + Bu::size iTotalSize = 0; + for( StreamArray::iterator i = aStreams.begin(); i; i++ ) + { + iTotalSize += (*i)->iSize; + } + return iTotalSize; } Bu::size Bu::Myriad::getTotalUnusedBytes() { - MutexLocker mLock( mHeader ); + MutexLocker mLock( mHeader ); - Bu::size iTotalSize = (iBlocks-iUsed)*iBlockSize; - for( StreamArray::iterator i = aStreams.begin(); i; i++ ) - { - iTotalSize += iBlockSize - ((Bu::size)(*i)->iSize%iBlockSize); - } - return iTotalSize; + Bu::size iTotalSize = (iBlocks-iUsed)*iBlockSize; + for( StreamArray::iterator i = aStreams.begin(); i; i++ ) + { + iTotalSize += iBlockSize - ((Bu::size)(*i)->iSize%iBlockSize); + } + return iTotalSize; } Bu::size Bu::Myriad::getTotalUnusedBytes( int iFakeBlockSize ) { - MutexLocker mLock( mHeader ); + MutexLocker mLock( mHeader ); - Bu::size iTotalSize = (iBlocks-iUsed)*iFakeBlockSize; - for( StreamArray::iterator i = aStreams.begin(); i; i++ ) - { - iTotalSize += iFakeBlockSize - ((*i)->iSize%iFakeBlockSize); - } - return iTotalSize; + Bu::size iTotalSize = (iBlocks-iUsed)*iFakeBlockSize; + for( StreamArray::iterator i = aStreams.begin(); i; i++ ) + { + iTotalSize += iFakeBlockSize - ((*i)->iSize%iFakeBlockSize); + } + return iTotalSize; } Bu::Myriad::Stream *Bu::Myriad::findStream( int iId ) { - for( StreamArray::iterator i = aStreams.begin(); i; i++ ) - { - if( (*i)->iId == iId ) - return *i; - } + for( StreamArray::iterator i = aStreams.begin(); i; i++ ) + { + if( (*i)->iId == iId ) + return *i; + } - throw MyriadException( MyriadException::noSuchStream, - "The requested stream doesn't exist and cannot be opened." ); + throw MyriadException( MyriadException::noSuchStream, + "The requested stream doesn't exist and cannot be opened." ); - return NULL; + return NULL; } Bu::Myriad::Block *Bu::Myriad::getBlock( int iBlock ) { -// sio << "Myriad: Reading block " << iBlock << ", bytes " -// << iBlockSize*iBlock << "-" << iBlockSize*(iBlock+1) << sio.nl; - Block *pBlock = new Block; - pBlock->pData = new char[iBlockSize]; - sStore.setPos( iBlockSize * (Bu::size)iBlock ); - sStore.read( pBlock->pData, iBlockSize ); - pBlock->bChanged = false; - pBlock->iBlockIndex = iBlock; +// sio << "Myriad: Reading block " << iBlock << ", bytes " +// << iBlockSize*iBlock << "-" << iBlockSize*(iBlock+1) << sio.nl; + Block *pBlock = new Block; + pBlock->pData = new char[iBlockSize]; + sStore.setPos( iBlockSize * (Bu::size)iBlock ); + sStore.read( pBlock->pData, iBlockSize ); + pBlock->bChanged = false; + pBlock->iBlockIndex = iBlock; - mActiveBlocks.lock(); - hActiveBlocks.insert( iBlock, pBlock ); - mActiveBlocks.unlock(); + mActiveBlocks.lock(); + hActiveBlocks.insert( iBlock, pBlock ); + mActiveBlocks.unlock(); - return pBlock; + return pBlock; } void Bu::Myriad::releaseBlock( Bu::Myriad::Block *pBlock ) { - if( pBlock == NULL ) - return; -// sio << "Myriad: Releasing block " << pBlock->iBlockIndex << sio.nl; - syncBlock( pBlock ); - mActiveBlocks.lock(); - hActiveBlocks.erase( pBlock->iBlockIndex ); - mActiveBlocks.unlock(); + if( pBlock == NULL ) + return; +// sio << "Myriad: Releasing block " << pBlock->iBlockIndex << sio.nl; + syncBlock( pBlock ); + mActiveBlocks.lock(); + hActiveBlocks.erase( pBlock->iBlockIndex ); + mActiveBlocks.unlock(); - delete[] pBlock->pData; - delete pBlock; + delete[] pBlock->pData; + delete pBlock; } void Bu::Myriad::syncBlock( Block *pBlock ) { - if( pBlock->bChanged ) - { -// sio << "Myriad: - Block changed, writing back to stream." << sio.nl; - sStore.setPos( iBlockSize * (Bu::size)pBlock->iBlockIndex ); - sStore.write( pBlock->pData, iBlockSize ); - pBlock->bChanged = false; - } + if( pBlock->bChanged ) + { +// sio << "Myriad: - Block changed, writing back to stream." << sio.nl; + sStore.setPos( iBlockSize * (Bu::size)pBlock->iBlockIndex ); + sStore.write( pBlock->pData, iBlockSize ); + pBlock->bChanged = false; + } } int Bu::Myriad::streamAddBlock( Stream *pStream ) { - MutexLocker mLock( mHeader ); + MutexLocker mLock( mHeader ); - int iBlock = findEmptyBlock(); - pStream->aBlocks.append( iBlock ); -// bsBlockUsed.setBit( iBlock ); -// bHeaderChanged = true; - iUsed++; - return iBlock; + int iBlock = findEmptyBlock(); + pStream->aBlocks.append( iBlock ); +// bsBlockUsed.setBit( iBlock ); +// bHeaderChanged = true; + iUsed++; + return iBlock; } void Bu::Myriad::setStreamSize( Stream *pStream, long iSize ) { - MutexLocker mLock( mHeader ); - - if( pStream->iSize == iSize ) - { - return; - } - else if( pStream->iSize > iSize ) - { - // Shrink - for( int iNewSize = pStream->aBlocks.getSize()*iBlockSize; - iNewSize-iBlockSize > iSize; iNewSize -= iBlockSize ) - { -// if( bsBlockUsed.getBit( pStream->aBlocks.last() ) ) - iUsed--; -// else -// sio << "Unused block used in stream? " << pStream->aBlocks.last() << sio.nl; - lFreeBlocks.enqueue( pStream->aBlocks.last() ); -// bsBlockUsed.setBit( pStream->aBlocks.last(), false ); - pStream->aBlocks.eraseLast(); - } - pStream->iSize = iSize; - bHeaderChanged = true; - } - else - { - // Grow - for( int iNewSize = pStream->aBlocks.getSize()*iBlockSize; - iNewSize < iSize; iNewSize += iBlockSize ) - { - //streamAddBlock( pStream ); - int iBlock = findEmptyBlock(); - pStream->aBlocks.append( iBlock ); -// bsBlockUsed.setBit( iBlock ); -// bHeaderChanged = true; - iUsed++; - } - pStream->iSize = iSize; - bHeaderChanged = true; - } + MutexLocker mLock( mHeader ); + + if( pStream->iSize == iSize ) + { + return; + } + else if( pStream->iSize > iSize ) + { + // Shrink + for( int iNewSize = pStream->aBlocks.getSize()*iBlockSize; + iNewSize-iBlockSize > iSize; iNewSize -= iBlockSize ) + { +// if( bsBlockUsed.getBit( pStream->aBlocks.last() ) ) + iUsed--; +// else +// sio << "Unused block used in stream? " << pStream->aBlocks.last() << sio.nl; + lFreeBlocks.enqueue( pStream->aBlocks.last() ); +// bsBlockUsed.setBit( pStream->aBlocks.last(), false ); + pStream->aBlocks.eraseLast(); + } + pStream->iSize = iSize; + bHeaderChanged = true; + } + else + { + // Grow + for( int iNewSize = pStream->aBlocks.getSize()*iBlockSize; + iNewSize < iSize; iNewSize += iBlockSize ) + { + //streamAddBlock( pStream ); + int iBlock = findEmptyBlock(); + pStream->aBlocks.append( iBlock ); +// bsBlockUsed.setBit( iBlock ); +// bHeaderChanged = true; + iUsed++; + } + pStream->iSize = iSize; + bHeaderChanged = true; + } } void Bu::Myriad::headerChanged() { - bHeaderChanged = true; + bHeaderChanged = true; } bool Bu::Myriad::isMyriad( Bu::Stream &sStore ) { - uint8_t uTmp; + uint8_t uTmp; - return isMyriad( sStore, uTmp ); + return isMyriad( sStore, uTmp ); } bool Bu::Myriad::isMyriad( Bu::Stream &sStore, uint8_t &uTmp ) { - sStore.setPos( 0 ); + sStore.setPos( 0 ); - unsigned char buf[4]; - if( sStore.read( buf, 4 ) < 4 ) - throw MyriadException( MyriadException::emptyStream, - "Input stream appears to be empty."); - sStore.read( &uTmp, 1 ); - sStore.setPos( 0 ); - if( memcmp( buf, Myriad_MAGIC_CODE, 4 ) ) - { - return false; - } - return true; + unsigned char buf[4]; + if( sStore.read( buf, 4 ) < 4 ) + throw MyriadException( MyriadException::emptyStream, + "Input stream appears to be empty."); + sStore.read( &uTmp, 1 ); + sStore.setPos( 0 ); + if( memcmp( buf, Myriad_MAGIC_CODE, 4 ) ) + { + return false; + } + return true; } const Bu::BitString Bu::Myriad::getBlocksUsed() const { - Bu::BitString bs( iBlocks, false ); - for( int j = 0; j < iBlocks; j++ ) - bs.setBit( j ); - for( IndexList::const_iterator i = lFreeBlocks.begin(); i; i++ ) - bs.setBit( *i, false ); - return bs; + Bu::BitString bs( iBlocks, false ); + for( int j = 0; j < iBlocks; j++ ) + bs.setBit( j ); + for( IndexList::const_iterator i = lFreeBlocks.begin(); i; i++ ) + bs.setBit( *i, false ); + return bs; } diff --git a/src/stable/myriad.h b/src/stable/myriad.h index 6b1db41..4bfd88e 100644 --- a/src/stable/myriad.h +++ b/src/stable/myriad.h @@ -18,219 +18,219 @@ namespace Bu { - class Stream; - class MyriadStream; - - subExceptionDeclBegin( MyriadException ) - enum - { - emptyStream, - invalidFormat, - badVersion, - invalidWordSize, - noSuchStream, - streamExists, - invalidStreamId, - protectedStream - }; - subExceptionDeclEnd(); - - /** - * Myriad block-allocated stream multiplexing system. This is a system for - * creating streams that contain other streams in a flexible and lightweight - * manner. Basically, you can create a file (or any other stream) that can - * store any number of flexible, growing streams. The streams within the - * Myriad stream are automatically numbered, not named. This works more - * or less like a filesystem, but without the extra layer for managing - * file and directory links. This would actually be very easy to add - * on top of Myriad, but is not required. - * - * Header format is as follows: - * - * MMMMvBssssSSSS* - * M = Magic number (0AD3FA84) - * v = version number - * B = Bits per int - * s = Blocksize in bytes - * S = Number of Streams - * - * The * represents the Stream headers, one per stream, as follows: - * IIIIssss$ - * I = Id number of the stream - * s = size of stream in bytes - * - * The $ represents the Block headers, one per used block, as follows: - * IIII - * I = Index of the block - * - * The stream/block data is interleaved in the header, so all blocks stored - * with one stream are together. The block headers are in order, and the - * data in them is required to be "solid" you cannot fill partial blocks - * mid-way through a stream. - * - * The initial block starts with the nids header, and is both the zero block - * and the zero stream. For now, the minimum block size is the size needed - * to store the base header, the zero stream header, and the first two - * blocks of the zero stream, so 30 bytes. Since it's reccomended to use - * a size that will fit evenly into filesystem blocks, then a size of 32 is - * probably the smallest reccomended size because all powers of two equal - * to or greater than 32 are evenly divisible by 32. - * - * I have had a thought that if the block size were smaller than 42 bytes - * the header would consume the first N blocks where N * block size is - * enough space to house the initial header, the first stream header, and - * the first N block headers. This, of course, causes you to hit an - * infinite header if the block size is small enough. - */ - class Myriad - { - friend class MyriadStream; - public: - /** - * Create a Myriad object that uses the given stream to store data. - * This stream must be random access. The block size and preallocate - * values passed in are values that will be used if the given stream - * is empty. In that case the stream will be "formatted" for myriad - * with the specified block size. If there is already a viable Myriad - * format present in the stream, then the blocksize and preallocate - * values will be ignored and the values from the stream will be used - * instead. If the stream doesn't appear to be Myriad formatted an - * exception will be thrown. - */ - Myriad( Bu::Stream &sStore, int iBlockSize=512, int iPreallocate=8 ); - virtual ~Myriad(); - - /** - * Destroy whatever data may be in the base stream and create a new - * Myriad system there with the given blocksize. Use this with care, - * it will destroy anything that was already in the stream, and - * generally, should not ever have to be used. - */ - void initialize( int iBlockSize, int iPreAllocate=1 ); - - /** - * Create a new stream within the Myriad system. The ID of the new - * stream is returned. - */ - int createStream( int iPreAllocate=1 ); - - /** - * Create a new stream within the Myriad system with a given id. The - * id that you provide will be the new id of the stream unless it's - * already used, in which case an error is thrown. This is primarilly - * useful when copying an old Myriad file into a new one. - */ - int createStreamWithId( int iId, int iPreAllocate=1 ); - - /** - * Delete a stream that's already within the Myriad. - */ - void deleteStream( int iId ); - - /** - * Return a new Stream object assosiated with the given stream ID. - */ - MyriadStream openStream( int iId ); - - Bu::Array getStreamIds(); - int getStreamSize( int iId ); - bool hasStream( int iId ); - - int getNumStreams(); - int getBlockSize(); - int getNumBlocks(); - int getNumUsedBlocks(); - Bu::size getTotalUsedBytes(); - Bu::size getTotalUnusedBytes(); - Bu::size getTotalUnusedBytes( int iFakeBlockSize ); - - /** - * Syncronize the header data, etc. with the storage stream. It's not - * a bad idea to call this periodically. - */ - void sync(); - - /** - * Read the first few bytes from the given stream and return true/false - * depending on weather or not it's a Myriad stream. This will throw - * an exception if the stream is empty, or is not random access. - */ - static bool isMyriad( Bu::Stream &sStore, uint8_t &uVer ); - - /** - * Read the first few bytes from the given stream and return true/false - * depending on weather or not it's a Myriad stream. This will throw - * an exception if the stream is empty, or is not random access. - */ - static bool isMyriad( Bu::Stream &sStore ); - - const Bu::BitString getBlocksUsed() const; - - private: - /** - * Initialize this object based on the data already in the assosiated - * stream. This will be called automatically for you if you forget, - * but if you want to pre-initialize for some reason, just call this - * once before you actually start doing anything with your Myriad. - */ - void initialize(); - - enum - { - blockUnused = 0xFFFFFFFFUL - }; - - typedef Bu::Array BlockArray; - class Stream - { - public: - int iId; - int iSize; - BlockArray aBlocks; - }; - typedef Bu::Array StreamArray; - - class Block - { - public: - char *pData; - bool bChanged; - int iBlockIndex; - }; - - void updateHeader(); - int findEmptyBlock(); - - /** - *@todo Change this to use a binary search, it's nicer. - */ - Stream *findStream( int iId ); - - Block *getBlock( int iBlock ); - void releaseBlock( Block *pBlock ); - void syncBlock( Block *pBlock ); - - int streamAddBlock( Stream *pStream ); - void setStreamSize( Stream *pStream, long iSize ); - - void headerChanged(); - - private: - Bu::Stream &sStore; - int iBlockSize; - int iBlocks; - int iUsed; - typedef Bu::List IndexList; - IndexList lFreeBlocks; -// Bu::BitString bsBlockUsed; - StreamArray aStreams; - typedef Bu::Hash BlockHash; - BlockHash hActiveBlocks; - bool bHeaderChanged; - - Bu::Mutex mHeader; - Bu::Mutex mActiveBlocks; - }; + class Stream; + class MyriadStream; + + subExceptionDeclBegin( MyriadException ) + enum + { + emptyStream, + invalidFormat, + badVersion, + invalidWordSize, + noSuchStream, + streamExists, + invalidStreamId, + protectedStream + }; + subExceptionDeclEnd(); + + /** + * Myriad block-allocated stream multiplexing system. This is a system for + * creating streams that contain other streams in a flexible and lightweight + * manner. Basically, you can create a file (or any other stream) that can + * store any number of flexible, growing streams. The streams within the + * Myriad stream are automatically numbered, not named. This works more + * or less like a filesystem, but without the extra layer for managing + * file and directory links. This would actually be very easy to add + * on top of Myriad, but is not required. + * + * Header format is as follows: + * + * MMMMvBssssSSSS* + * M = Magic number (0AD3FA84) + * v = version number + * B = Bits per int + * s = Blocksize in bytes + * S = Number of Streams + * + * The * represents the Stream headers, one per stream, as follows: + * IIIIssss$ + * I = Id number of the stream + * s = size of stream in bytes + * + * The $ represents the Block headers, one per used block, as follows: + * IIII + * I = Index of the block + * + * The stream/block data is interleaved in the header, so all blocks stored + * with one stream are together. The block headers are in order, and the + * data in them is required to be "solid" you cannot fill partial blocks + * mid-way through a stream. + * + * The initial block starts with the nids header, and is both the zero block + * and the zero stream. For now, the minimum block size is the size needed + * to store the base header, the zero stream header, and the first two + * blocks of the zero stream, so 30 bytes. Since it's reccomended to use + * a size that will fit evenly into filesystem blocks, then a size of 32 is + * probably the smallest reccomended size because all powers of two equal + * to or greater than 32 are evenly divisible by 32. + * + * I have had a thought that if the block size were smaller than 42 bytes + * the header would consume the first N blocks where N * block size is + * enough space to house the initial header, the first stream header, and + * the first N block headers. This, of course, causes you to hit an + * infinite header if the block size is small enough. + */ + class Myriad + { + friend class MyriadStream; + public: + /** + * Create a Myriad object that uses the given stream to store data. + * This stream must be random access. The block size and preallocate + * values passed in are values that will be used if the given stream + * is empty. In that case the stream will be "formatted" for myriad + * with the specified block size. If there is already a viable Myriad + * format present in the stream, then the blocksize and preallocate + * values will be ignored and the values from the stream will be used + * instead. If the stream doesn't appear to be Myriad formatted an + * exception will be thrown. + */ + Myriad( Bu::Stream &sStore, int iBlockSize=512, int iPreallocate=8 ); + virtual ~Myriad(); + + /** + * Destroy whatever data may be in the base stream and create a new + * Myriad system there with the given blocksize. Use this with care, + * it will destroy anything that was already in the stream, and + * generally, should not ever have to be used. + */ + void initialize( int iBlockSize, int iPreAllocate=1 ); + + /** + * Create a new stream within the Myriad system. The ID of the new + * stream is returned. + */ + int createStream( int iPreAllocate=1 ); + + /** + * Create a new stream within the Myriad system with a given id. The + * id that you provide will be the new id of the stream unless it's + * already used, in which case an error is thrown. This is primarilly + * useful when copying an old Myriad file into a new one. + */ + int createStreamWithId( int iId, int iPreAllocate=1 ); + + /** + * Delete a stream that's already within the Myriad. + */ + void deleteStream( int iId ); + + /** + * Return a new Stream object assosiated with the given stream ID. + */ + MyriadStream openStream( int iId ); + + Bu::Array getStreamIds(); + int getStreamSize( int iId ); + bool hasStream( int iId ); + + int getNumStreams(); + int getBlockSize(); + int getNumBlocks(); + int getNumUsedBlocks(); + Bu::size getTotalUsedBytes(); + Bu::size getTotalUnusedBytes(); + Bu::size getTotalUnusedBytes( int iFakeBlockSize ); + + /** + * Syncronize the header data, etc. with the storage stream. It's not + * a bad idea to call this periodically. + */ + void sync(); + + /** + * Read the first few bytes from the given stream and return true/false + * depending on weather or not it's a Myriad stream. This will throw + * an exception if the stream is empty, or is not random access. + */ + static bool isMyriad( Bu::Stream &sStore, uint8_t &uVer ); + + /** + * Read the first few bytes from the given stream and return true/false + * depending on weather or not it's a Myriad stream. This will throw + * an exception if the stream is empty, or is not random access. + */ + static bool isMyriad( Bu::Stream &sStore ); + + const Bu::BitString getBlocksUsed() const; + + private: + /** + * Initialize this object based on the data already in the assosiated + * stream. This will be called automatically for you if you forget, + * but if you want to pre-initialize for some reason, just call this + * once before you actually start doing anything with your Myriad. + */ + void initialize(); + + enum + { + blockUnused = 0xFFFFFFFFUL + }; + + typedef Bu::Array BlockArray; + class Stream + { + public: + int iId; + int iSize; + BlockArray aBlocks; + }; + typedef Bu::Array StreamArray; + + class Block + { + public: + char *pData; + bool bChanged; + int iBlockIndex; + }; + + void updateHeader(); + int findEmptyBlock(); + + /** + *@todo Change this to use a binary search, it's nicer. + */ + Stream *findStream( int iId ); + + Block *getBlock( int iBlock ); + void releaseBlock( Block *pBlock ); + void syncBlock( Block *pBlock ); + + int streamAddBlock( Stream *pStream ); + void setStreamSize( Stream *pStream, long iSize ); + + void headerChanged(); + + private: + Bu::Stream &sStore; + int iBlockSize; + int iBlocks; + int iUsed; + typedef Bu::List IndexList; + IndexList lFreeBlocks; +// Bu::BitString bsBlockUsed; + StreamArray aStreams; + typedef Bu::Hash BlockHash; + BlockHash hActiveBlocks; + bool bHeaderChanged; + + Bu::Mutex mHeader; + Bu::Mutex mActiveBlocks; + }; }; #endif diff --git a/src/stable/myriadstream.cpp b/src/stable/myriadstream.cpp index 58d3936..c33445a 100644 --- a/src/stable/myriadstream.cpp +++ b/src/stable/myriadstream.cpp @@ -9,7 +9,7 @@ #include -// #define MYRIAD_STREAM_DEBUG 1 +// #define MYRIAD_STREAM_DEBUG 1 #ifdef MYRIAD_STREAM_DEBUG #include "bu/sio.h" @@ -19,27 +19,27 @@ using Bu::Fmt; #endif Bu::MyriadStream::MyriadStream( Bu::Myriad &rMyriad, - Bu::Myriad::Stream *pStream ) : - rMyriad( rMyriad ), - pStream( pStream ), - pCurBlock( NULL ), - iPos( 0 ) + Bu::Myriad::Stream *pStream ) : + rMyriad( rMyriad ), + pStream( pStream ), + pCurBlock( NULL ), + iPos( 0 ) { #ifdef MYRIAD_STREAM_DEBUG - sio << "MyriadStream: " << __LINE__ << ": Created, iId=" << pStream->iId << ", iSize=" - << pStream->iSize << sio.nl; + sio << "MyriadStream: " << __LINE__ << ": Created, iId=" << pStream->iId << ", iSize=" + << pStream->iSize << sio.nl; #endif - //pCurBlock = rMyriad.newBlock(); - //rMyriad.getBlock( uStream, pCurBlock ); - //uSize = pCurBlock->uBytesUsed; + //pCurBlock = rMyriad.newBlock(); + //rMyriad.getBlock( uStream, pCurBlock ); + //uSize = pCurBlock->uBytesUsed; } Bu::MyriadStream::~MyriadStream() { - if( pCurBlock ) - rMyriad.releaseBlock( pCurBlock ); - //rMyriad.updateStreamSize( uStream, uSize ); - //rMyriad.deleteBlock( pCurBlock ); + if( pCurBlock ) + rMyriad.releaseBlock( pCurBlock ); + //rMyriad.updateStreamSize( uStream, uSize ); + //rMyriad.deleteBlock( pCurBlock ); } void Bu::MyriadStream::close() @@ -49,200 +49,200 @@ void Bu::MyriadStream::close() Bu::size Bu::MyriadStream::read( void *pBuf, Bu::size nBytes ) { #ifdef MYRIAD_STREAM_DEBUG - sio << "MyriadStream: read: " << __LINE__ << ": Started, asked to read " << nBytes << "b." - << sio.nl; + sio << "MyriadStream: read: " << __LINE__ << ": Started, asked to read " << nBytes << "b." + << sio.nl; #endif - if( nBytes > (Bu::size)pStream->iSize-iPos ) - nBytes = pStream->iSize-iPos; - if( nBytes <= 0 ) - return 0; - int iLeft = nBytes; + if( nBytes > (Bu::size)pStream->iSize-iPos ) + nBytes = pStream->iSize-iPos; + if( nBytes <= 0 ) + return 0; + int iLeft = nBytes; #ifdef MYRIAD_STREAM_DEBUG - sio << "MyriadStream: read: " << __LINE__ << ": Started, going to read " << nBytes << "b." - << sio.nl; + sio << "MyriadStream: read: " << __LINE__ << ": Started, going to read " << nBytes << "b." + << sio.nl; #endif - if( pCurBlock == NULL ) - { + if( pCurBlock == NULL ) + { #ifdef MYRIAD_STREAM_DEBUG - sio << "MyriadStream: read: " << __LINE__ << ": No block loaded, loading initial block." - << sio.nl; + sio << "MyriadStream: read: " << __LINE__ << ": No block loaded, loading initial block." + << sio.nl; #endif - pCurBlock = rMyriad.getBlock( - pStream->aBlocks[iPos/rMyriad.iBlockSize] - ); - } - while( iLeft > 0 ) - { - int iCurBlock = pStream->aBlocks[iPos/rMyriad.iBlockSize]; - if( pCurBlock->iBlockIndex != iCurBlock ) - { + pCurBlock = rMyriad.getBlock( + pStream->aBlocks[iPos/rMyriad.iBlockSize] + ); + } + while( iLeft > 0 ) + { + int iCurBlock = pStream->aBlocks[iPos/rMyriad.iBlockSize]; + if( pCurBlock->iBlockIndex != iCurBlock ) + { #ifdef MYRIAD_STREAM_DEBUG - sio << "MyriadStream: read: " << __LINE__ << ": Loading new block " << iCurBlock << "." - << sio.nl; + sio << "MyriadStream: read: " << __LINE__ << ": Loading new block " << iCurBlock << "." + << sio.nl; #endif - rMyriad.releaseBlock( pCurBlock ); - pCurBlock = rMyriad.getBlock( iCurBlock ); - } - - int iAmnt = Bu::buMin( - Bu::buMin( - rMyriad.iBlockSize - iPos%rMyriad.iBlockSize, - iLeft - ), - pStream->iSize-iPos - ); + rMyriad.releaseBlock( pCurBlock ); + pCurBlock = rMyriad.getBlock( iCurBlock ); + } + + int iAmnt = Bu::buMin( + Bu::buMin( + rMyriad.iBlockSize - iPos%rMyriad.iBlockSize, + iLeft + ), + pStream->iSize-iPos + ); #ifdef MYRIAD_STREAM_DEBUG - sio << "MyriadStream: read: " << __LINE__ << ": Copying out bytes: " - << iPos << "(" << (iPos%rMyriad.iBlockSize) << ")+" - << iAmnt - << ", " << iLeft << "b left." << sio.nl; + sio << "MyriadStream: read: " << __LINE__ << ": Copying out bytes: " + << iPos << "(" << (iPos%rMyriad.iBlockSize) << ")+" + << iAmnt + << ", " << iLeft << "b left." << sio.nl; #endif - memcpy( - pBuf, - pCurBlock->pData+(iPos%rMyriad.iBlockSize), - iAmnt - ); - iPos += iAmnt; - pBuf = &((char *)pBuf)[iAmnt]; - iLeft -= iAmnt; - } - return nBytes; + memcpy( + pBuf, + pCurBlock->pData+(iPos%rMyriad.iBlockSize), + iAmnt + ); + iPos += iAmnt; + pBuf = &((char *)pBuf)[iAmnt]; + iLeft -= iAmnt; + } + return nBytes; } Bu::size Bu::MyriadStream::write( const void *pBuf, Bu::size nBytes ) { - if( nBytes <= 0 ) - return 0; + if( nBytes <= 0 ) + return 0; #ifdef MYRIAD_STREAM_DEBUG - sio << "MyriadStream: write: " << __LINE__ << ": Started, asked to write " << nBytes << "b." - << sio.nl; + sio << "MyriadStream: write: " << __LINE__ << ": Started, asked to write " << nBytes << "b." + << sio.nl; #endif - if( nBytes <= 0 ) - return 0; - int iLeft = nBytes; - /* - if( pCurBlock == NULL ) - { + if( nBytes <= 0 ) + return 0; + int iLeft = nBytes; + /* + if( pCurBlock == NULL ) + { #ifdef MYRIAD_STREAM_DEBUG - sio << "MyriadStream: write: No block loaded, loading initial block." - << sio.nl; + sio << "MyriadStream: write: No block loaded, loading initial block." + << sio.nl; #endif - pCurBlock = rMyriad.getBlock( - pStream->aBlocks[iPos/rMyriad.iBlockSize] - ); - }*/ - - while( iLeft > 0 ) - { - int iCurBlock; - if( iPos/rMyriad.iBlockSize < pStream->aBlocks.getSize() ) - { - iCurBlock = pStream->aBlocks[iPos/rMyriad.iBlockSize]; - } - else - { - iCurBlock = rMyriad.streamAddBlock( pStream ); + pCurBlock = rMyriad.getBlock( + pStream->aBlocks[iPos/rMyriad.iBlockSize] + ); + }*/ + + while( iLeft > 0 ) + { + int iCurBlock; + if( iPos/rMyriad.iBlockSize < pStream->aBlocks.getSize() ) + { + iCurBlock = pStream->aBlocks[iPos/rMyriad.iBlockSize]; + } + else + { + iCurBlock = rMyriad.streamAddBlock( pStream ); #ifdef MYRIAD_STREAM_DEBUG - sio << "MyriadStream: write: " << __LINE__ << ": New block allocated and appended: " - << iCurBlock << "." << sio.nl; + sio << "MyriadStream: write: " << __LINE__ << ": New block allocated and appended: " + << iCurBlock << "." << sio.nl; #endif - } - if( !pCurBlock || pCurBlock->iBlockIndex != iCurBlock ) - { + } + if( !pCurBlock || pCurBlock->iBlockIndex != iCurBlock ) + { #ifdef MYRIAD_STREAM_DEBUG - sio << "MyriadStream: write: " << __LINE__ << ": Loading new block " << iCurBlock << "." - << sio.nl; + sio << "MyriadStream: write: " << __LINE__ << ": Loading new block " << iCurBlock << "." + << sio.nl; #endif - rMyriad.releaseBlock( pCurBlock ); - pCurBlock = rMyriad.getBlock( iCurBlock ); - } - pCurBlock->bChanged = true; - - // There are two main writing modes when it comes down to it. - // Overwrite mode and append mode. Append is what pretty much always - // happens when creating a new stream. - if( iPos < pStream->iSize ) - { - int iAmnt = Bu::buMin( - Bu::buMin( - rMyriad.iBlockSize - iPos%rMyriad.iBlockSize, - iLeft - ), - pStream->iSize-iPos - ); + rMyriad.releaseBlock( pCurBlock ); + pCurBlock = rMyriad.getBlock( iCurBlock ); + } + pCurBlock->bChanged = true; + + // There are two main writing modes when it comes down to it. + // Overwrite mode and append mode. Append is what pretty much always + // happens when creating a new stream. + if( iPos < pStream->iSize ) + { + int iAmnt = Bu::buMin( + Bu::buMin( + rMyriad.iBlockSize - iPos%rMyriad.iBlockSize, + iLeft + ), + pStream->iSize-iPos + ); #ifdef MYRIAD_STREAM_DEBUG - sio << "MyriadStream: write (ovr): " << __LINE__ << ": Copying in bytes: " - << (iPos%rMyriad.iBlockSize) << "+" - << iAmnt - << ", " << iLeft << "b left." << sio.nl; + sio << "MyriadStream: write (ovr): " << __LINE__ << ": Copying in bytes: " + << (iPos%rMyriad.iBlockSize) << "+" + << iAmnt + << ", " << iLeft << "b left." << sio.nl; #endif - memcpy( - pCurBlock->pData+(iPos%rMyriad.iBlockSize), - pBuf, - iAmnt - ); - iPos += iAmnt; - pBuf = &((char *)pBuf)[iAmnt]; - iLeft -= iAmnt; - } - else - { - int iAmnt = Bu::buMin( - rMyriad.iBlockSize - iPos%rMyriad.iBlockSize, - iLeft - ); + memcpy( + pCurBlock->pData+(iPos%rMyriad.iBlockSize), + pBuf, + iAmnt + ); + iPos += iAmnt; + pBuf = &((char *)pBuf)[iAmnt]; + iLeft -= iAmnt; + } + else + { + int iAmnt = Bu::buMin( + rMyriad.iBlockSize - iPos%rMyriad.iBlockSize, + iLeft + ); #ifdef MYRIAD_STREAM_DEBUG - sio << "MyriadStream: write (app): " << __LINE__ << ": Copying in bytes: " - << (iPos%rMyriad.iBlockSize) << "+" - << iAmnt - << ", " << iLeft << "b left." << sio.nl; + sio << "MyriadStream: write (app): " << __LINE__ << ": Copying in bytes: " + << (iPos%rMyriad.iBlockSize) << "+" + << iAmnt + << ", " << iLeft << "b left." << sio.nl; #endif - memcpy( - pCurBlock->pData+(iPos%rMyriad.iBlockSize), - pBuf, - iAmnt - ); - iPos += iAmnt; - pStream->iSize += iAmnt; - rMyriad.headerChanged(); - pBuf = &((char *)pBuf)[iAmnt]; - iLeft -= iAmnt; - } - } - - return nBytes; + memcpy( + pCurBlock->pData+(iPos%rMyriad.iBlockSize), + pBuf, + iAmnt + ); + iPos += iAmnt; + pStream->iSize += iAmnt; + rMyriad.headerChanged(); + pBuf = &((char *)pBuf)[iAmnt]; + iLeft -= iAmnt; + } + } + + return nBytes; } Bu::size Bu::MyriadStream::tell() { - return iPos; + return iPos; } void Bu::MyriadStream::seek( Bu::size offset ) { - iPos += offset; + iPos += offset; } void Bu::MyriadStream::setPos( Bu::size pos ) { - iPos = pos; + iPos = pos; } void Bu::MyriadStream::setPosEnd( Bu::size pos ) { - iPos = pStream->iSize-pos; + iPos = pStream->iSize-pos; } bool Bu::MyriadStream::isEos() { - return iPos >= pStream->iSize; + return iPos >= pStream->iSize; } bool Bu::MyriadStream::isOpen() { - return true; + return true; } void Bu::MyriadStream::flush() @@ -251,32 +251,32 @@ void Bu::MyriadStream::flush() bool Bu::MyriadStream::canRead() { - return true; + return true; } bool Bu::MyriadStream::canWrite() { - return true; + return true; } bool Bu::MyriadStream::isReadable() { - return true; + return true; } bool Bu::MyriadStream::isWritable() { - return true; + return true; } bool Bu::MyriadStream::isSeekable() { - return true; + return true; } bool Bu::MyriadStream::isBlocking() { - return true; + return true; } void Bu::MyriadStream::setBlocking( bool /*bBlocking*/ ) @@ -285,25 +285,25 @@ void Bu::MyriadStream::setBlocking( bool /*bBlocking*/ ) void Bu::MyriadStream::setSize( Bu::size iSize ) { - if( iSize < 0 ) - iSize = 0; - rMyriad.setStreamSize( pStream, iSize ); - if( iPos > iSize ) - iPos = iSize; + if( iSize < 0 ) + iSize = 0; + rMyriad.setStreamSize( pStream, iSize ); + if( iPos > iSize ) + iPos = iSize; } Bu::size Bu::MyriadStream::getSize() const { - return pStream->iSize; + return pStream->iSize; } Bu::size Bu::MyriadStream::getBlockSize() const { - return rMyriad.getBlockSize(); + return rMyriad.getBlockSize(); } Bu::String Bu::MyriadStream::getLocation() const { - return Bu::String("%1").arg( pStream->iId ); + return Bu::String("%1").arg( pStream->iId ); } diff --git a/src/stable/myriadstream.h b/src/stable/myriadstream.h index 7cc2fc0..fe7453f 100644 --- a/src/stable/myriadstream.h +++ b/src/stable/myriadstream.h @@ -13,49 +13,49 @@ namespace Bu { - class MyriadStream : public Bu::Stream - { - friend class Myriad; - private: - /** - * These can only be created by the Myriad class. - */ - MyriadStream( Myriad &rMyriad, Myriad::Stream *pStream ); - - public: - virtual ~MyriadStream(); - - virtual void close(); - virtual Bu::size read( void *pBuf, Bu::size nBytes ); - virtual Bu::size write( const void *pBuf, Bu::size nBytes ); - using Stream::write; - virtual Bu::size tell(); - virtual void seek( Bu::size offset ); - virtual void setPos( Bu::size pos ); - virtual void setPosEnd( Bu::size pos ); - virtual bool isEos(); - virtual bool isOpen(); - virtual void flush(); - virtual bool canRead(); - virtual bool canWrite(); - virtual bool isReadable(); - virtual bool isWritable(); - virtual bool isSeekable(); - virtual bool isBlocking(); - virtual void setBlocking( bool bBlocking=true ); - virtual void setSize( Bu::size iSize ); - - virtual size getSize() const; - virtual size getBlockSize() const; - virtual Bu::String getLocation() const; - - private: - Myriad &rMyriad; - Myriad::Stream *pStream; - Myriad::Block *pCurBlock; - int iBlockSize; - int iPos; - }; + class MyriadStream : public Bu::Stream + { + friend class Myriad; + private: + /** + * These can only be created by the Myriad class. + */ + MyriadStream( Myriad &rMyriad, Myriad::Stream *pStream ); + + public: + virtual ~MyriadStream(); + + virtual void close(); + virtual Bu::size read( void *pBuf, Bu::size nBytes ); + virtual Bu::size write( const void *pBuf, Bu::size nBytes ); + using Stream::write; + virtual Bu::size tell(); + virtual void seek( Bu::size offset ); + virtual void setPos( Bu::size pos ); + virtual void setPosEnd( Bu::size pos ); + virtual bool isEos(); + virtual bool isOpen(); + virtual void flush(); + virtual bool canRead(); + virtual bool canWrite(); + virtual bool isReadable(); + virtual bool isWritable(); + virtual bool isSeekable(); + virtual bool isBlocking(); + virtual void setBlocking( bool bBlocking=true ); + virtual void setSize( Bu::size iSize ); + + virtual size getSize() const; + virtual size getBlockSize() const; + virtual Bu::String getLocation() const; + + private: + Myriad &rMyriad; + Myriad::Stream *pStream; + Myriad::Block *pCurBlock; + int iBlockSize; + int iPos; + }; }; #endif diff --git a/src/stable/nullstream.cpp b/src/stable/nullstream.cpp index 0dcede2..5f568b9 100644 --- a/src/stable/nullstream.cpp +++ b/src/stable/nullstream.cpp @@ -8,8 +8,8 @@ #include "bu/nullstream.h" Bu::NullStream::NullStream() : - sRead( 0 ), - sWrote( 0 ) + sRead( 0 ), + sWrote( 0 ) { } @@ -19,31 +19,31 @@ Bu::NullStream::~NullStream() void Bu::NullStream::close() { - sRead = sWrote = 0; + sRead = sWrote = 0; } Bu::size Bu::NullStream::read( void *pBuf, Bu::size nBytes ) { - memset( pBuf, 0, nBytes ); - sRead += nBytes; - return nBytes; + memset( pBuf, 0, nBytes ); + sRead += nBytes; + return nBytes; } Bu::String Bu::NullStream::readLine() { - sRead++; - return Bu::String("\0", 1 ); + sRead++; + return Bu::String("\0", 1 ); } Bu::size Bu::NullStream::write( const void *, Bu::size nBytes ) { - sWrote += nBytes; - return nBytes; + sWrote += nBytes; + return nBytes; } Bu::size Bu::NullStream::tell() { - return sRead + sWrote; + return sRead + sWrote; } void Bu::NullStream::seek( Bu::size ) @@ -60,12 +60,12 @@ void Bu::NullStream::setPosEnd( Bu::size ) bool Bu::NullStream::isEos() { - return false; + return false; } bool Bu::NullStream::isOpen() { - return true; + return true; } void Bu::NullStream::flush() @@ -74,32 +74,32 @@ void Bu::NullStream::flush() bool Bu::NullStream::canRead() { - return true; + return true; } bool Bu::NullStream::canWrite() { - return true; + return true; } bool Bu::NullStream::isReadable() { - return true; + return true; } bool Bu::NullStream::isWritable() { - return true; + return true; } bool Bu::NullStream::isSeekable() { - return false; + return false; } bool Bu::NullStream::isBlocking() { - return true; + return true; } void Bu::NullStream::setBlocking( bool ) @@ -112,16 +112,16 @@ void Bu::NullStream::setSize( Bu::size ) Bu::size Bu::NullStream::getSize() const { - return 0; + return 0; } Bu::size Bu::NullStream::getBlockSize() const { - return 0; + return 0; } Bu::String Bu::NullStream::getLocation() const { - return ""; + return ""; } diff --git a/src/stable/nullstream.h b/src/stable/nullstream.h index 034b0c5..a8b24e3 100644 --- a/src/stable/nullstream.h +++ b/src/stable/nullstream.h @@ -12,56 +12,56 @@ namespace Bu { - /** - * Works a lot like /dev/null on *nix style systems. This class allows - * infinite reading and writing. All operatorns "succeed" even if they - * don't seem to do anything. This is great for testing writing code or - * doing dry runs. When reading, it will produce NULL bytes, so any - * application that would like the ability to produce null streams as a - * snap-in replacement for any other Bu::Stream, this is the right option. - * - * As an added feature, the NullStream will track how many bytes it was - * asked to read and write, allowing you to use it to determine how many - * bytes a write opretion would use without actually writing anything. - */ - class NullStream : public Bu::Stream - { - public: - NullStream(); - virtual ~NullStream(); + /** + * Works a lot like /dev/null on *nix style systems. This class allows + * infinite reading and writing. All operatorns "succeed" even if they + * don't seem to do anything. This is great for testing writing code or + * doing dry runs. When reading, it will produce NULL bytes, so any + * application that would like the ability to produce null streams as a + * snap-in replacement for any other Bu::Stream, this is the right option. + * + * As an added feature, the NullStream will track how many bytes it was + * asked to read and write, allowing you to use it to determine how many + * bytes a write opretion would use without actually writing anything. + */ + class NullStream : public Bu::Stream + { + public: + NullStream(); + virtual ~NullStream(); - virtual void close(); - virtual Bu::size read( void *pBuf, Bu::size nBytes ); - virtual Bu::String readLine(); - virtual Bu::size write( const void *pBuf, Bu::size nBytes ); - using Bu::Stream::write; - virtual Bu::size tell(); - virtual void seek( Bu::size offset ); - virtual void setPos( Bu::size pos ); - virtual void setPosEnd( Bu::size pos ); - virtual bool isEos(); - virtual bool isOpen(); - virtual void flush(); - virtual bool canRead(); - virtual bool canWrite(); - virtual bool isReadable(); - virtual bool isWritable(); - virtual bool isSeekable(); - virtual bool isBlocking(); - virtual void setBlocking( bool bBlocking=true ); - virtual void setSize( Bu::size iSize ); + virtual void close(); + virtual Bu::size read( void *pBuf, Bu::size nBytes ); + virtual Bu::String readLine(); + virtual Bu::size write( const void *pBuf, Bu::size nBytes ); + using Bu::Stream::write; + virtual Bu::size tell(); + virtual void seek( Bu::size offset ); + virtual void setPos( Bu::size pos ); + virtual void setPosEnd( Bu::size pos ); + virtual bool isEos(); + virtual bool isOpen(); + virtual void flush(); + virtual bool canRead(); + virtual bool canWrite(); + virtual bool isReadable(); + virtual bool isWritable(); + virtual bool isSeekable(); + virtual bool isBlocking(); + virtual void setBlocking( bool bBlocking=true ); + virtual void setSize( Bu::size iSize ); - virtual size getSize() const; - virtual size getBlockSize() const; - virtual Bu::String getLocation() const; + virtual size getSize() const; + virtual size getBlockSize() const; + virtual Bu::String getLocation() const; - Bu::size getBytesRead() { return sRead; } - Bu::size getByetsWritten() { return sWrote; } + Bu::size getBytesRead() { return sRead; } + Bu::size getByetsWritten() { return sWrote; } - private: - Bu::size sRead; - Bu::size sWrote; - }; + private: + Bu::size sRead; + Bu::size sWrote; + }; }; #endif diff --git a/src/stable/optparser.cpp b/src/stable/optparser.cpp index 10a8fb6..aca36a2 100644 --- a/src/stable/optparser.cpp +++ b/src/stable/optparser.cpp @@ -21,168 +21,168 @@ Bu::OptParser::~OptParser() void Bu::OptParser::parse( int argc, char **argv ) { - for( int j = 1; j < argc; j++ ) - { - if( argv[j][0] == '-' ) - { - // Now we're on to something, which kind is it? - if( argv[j][1] == '-' ) - { - int iEPos; - for( iEPos = 2; argv[j][iEPos] != '\0' && - argv[j][iEPos] != '='; iEPos++ ) { } - - Bu::String sOpt; - int iCount = argc-j; - Bu::String sExtraParam; - if( argv[j][iEPos] == '=' ) - { - sOpt.set( argv[j]+2, iEPos-2 ); - iCount++; - sExtraParam.set( argv[j]+iEPos+1 ); - } - else - { - sOpt.set( argv[j]+2 ); - } - if( !hlOption.has( sOpt ) ) - { - optionError( "--" + sOpt ); - } - else - { - // Long param, cool, that's easy, first search for = - Option *pOpt = hlOption.get( sOpt ); - if( pOpt->sUsed ) - { - Bu::StrArray aParams( iCount ); - aParams.append( sOpt ); - if( sExtraParam.isSet() ) - { - aParams.append( argv[j]+iEPos+1 ); - } - for( int k = j+1; k < argc; k++ ) - { - aParams.append( argv[k] ); - } - j += pOpt->sUsed( aParams ); - } - else if( pOpt->pProxy ) - { - if( pOpt->sOverride.isSet() ) - { - pOpt->pProxy->setValue( pOpt->sOverride ); - } - else if( sExtraParam.isSet() ) - { - pOpt->pProxy->setValueFromStr( sExtraParam ); - } - else if( argv[j+1] != '\0' ) - { - pOpt->pProxy->setValueFromStr( argv[j+1] ); - j++; - } - } - } - } - else - { - int iCPos; - for( iCPos = 1; argv[j][iCPos] != '\0'; iCPos++ ) - { - if( !hsOption.has( argv[j][iCPos] ) ) - { - Bu::String sOpt("-"); - sOpt += argv[j][iCPos]; - optionError( sOpt ); - } - else - { - Option *pOpt = hsOption.get( argv[j][iCPos] ); - char buf[2] = {argv[j][iCPos], '\0'}; - if( pOpt->sUsed ) - { - Bu::StrArray aParams( argc-j+1 ); - aParams.append( buf ); - int iMod = 0; - if( argv[j][iCPos+1] != '\0' ) - { - aParams.append( argv[j]+iCPos+1 ); - iMod = -1; - } - for( int k = j+1; k < argc; k++ ) - { - aParams.append( argv[k] ); - } - int iUsed = pOpt->sUsed( aParams ); - if( iUsed > 0 ) - { - j += iUsed + iMod; - break; - } - } - else if( pOpt->pProxy ) - { - if( pOpt->sOverride.isSet() ) - { - pOpt->pProxy->setValue( pOpt->sOverride ); - } - else if( argv[j][iCPos+1] != '\0' ) - { - pOpt->pProxy->setValueFromStr( - argv[j]+iCPos+1 - ); - break; - } - else if( argv[j+1] ) - { - pOpt->pProxy->setValueFromStr( - argv[j+1] - ); - j++; - break; - } - } - } - } - } - } - else - { - if( !sNonOption ) - { - optionError( argv[j] ); - } - else - { - int iCount = argc-j; - Bu::StrArray aParams( iCount ); - for( int k = j; k < argc; k++ ) - { - aParams.append( argv[k] ); - } - j += sNonOption( aParams ); - } - } - } + for( int j = 1; j < argc; j++ ) + { + if( argv[j][0] == '-' ) + { + // Now we're on to something, which kind is it? + if( argv[j][1] == '-' ) + { + int iEPos; + for( iEPos = 2; argv[j][iEPos] != '\0' && + argv[j][iEPos] != '='; iEPos++ ) { } + + Bu::String sOpt; + int iCount = argc-j; + Bu::String sExtraParam; + if( argv[j][iEPos] == '=' ) + { + sOpt.set( argv[j]+2, iEPos-2 ); + iCount++; + sExtraParam.set( argv[j]+iEPos+1 ); + } + else + { + sOpt.set( argv[j]+2 ); + } + if( !hlOption.has( sOpt ) ) + { + optionError( "--" + sOpt ); + } + else + { + // Long param, cool, that's easy, first search for = + Option *pOpt = hlOption.get( sOpt ); + if( pOpt->sUsed ) + { + Bu::StrArray aParams( iCount ); + aParams.append( sOpt ); + if( sExtraParam.isSet() ) + { + aParams.append( argv[j]+iEPos+1 ); + } + for( int k = j+1; k < argc; k++ ) + { + aParams.append( argv[k] ); + } + j += pOpt->sUsed( aParams ); + } + else if( pOpt->pProxy ) + { + if( pOpt->sOverride.isSet() ) + { + pOpt->pProxy->setValue( pOpt->sOverride ); + } + else if( sExtraParam.isSet() ) + { + pOpt->pProxy->setValueFromStr( sExtraParam ); + } + else if( argv[j+1] != '\0' ) + { + pOpt->pProxy->setValueFromStr( argv[j+1] ); + j++; + } + } + } + } + else + { + int iCPos; + for( iCPos = 1; argv[j][iCPos] != '\0'; iCPos++ ) + { + if( !hsOption.has( argv[j][iCPos] ) ) + { + Bu::String sOpt("-"); + sOpt += argv[j][iCPos]; + optionError( sOpt ); + } + else + { + Option *pOpt = hsOption.get( argv[j][iCPos] ); + char buf[2] = {argv[j][iCPos], '\0'}; + if( pOpt->sUsed ) + { + Bu::StrArray aParams( argc-j+1 ); + aParams.append( buf ); + int iMod = 0; + if( argv[j][iCPos+1] != '\0' ) + { + aParams.append( argv[j]+iCPos+1 ); + iMod = -1; + } + for( int k = j+1; k < argc; k++ ) + { + aParams.append( argv[k] ); + } + int iUsed = pOpt->sUsed( aParams ); + if( iUsed > 0 ) + { + j += iUsed + iMod; + break; + } + } + else if( pOpt->pProxy ) + { + if( pOpt->sOverride.isSet() ) + { + pOpt->pProxy->setValue( pOpt->sOverride ); + } + else if( argv[j][iCPos+1] != '\0' ) + { + pOpt->pProxy->setValueFromStr( + argv[j]+iCPos+1 + ); + break; + } + else if( argv[j+1] ) + { + pOpt->pProxy->setValueFromStr( + argv[j+1] + ); + j++; + break; + } + } + } + } + } + } + else + { + if( !sNonOption ) + { + optionError( argv[j] ); + } + else + { + int iCount = argc-j; + Bu::StrArray aParams( iCount ); + for( int k = j; k < argc; k++ ) + { + aParams.append( argv[k] ); + } + j += sNonOption( aParams ); + } + } + } } void Bu::OptParser::parse( const Bu::String &sLine ) { - Bu::String sCmd = sLine.clone(); - int iParams = 0; - bool bInGap = true; - bool bInQuote = false; - for( Bu::String::iterator i = sCmd.begin(); i; i++ ) - { - if( bInQuote == false && (*i == ' ' || *i == '\t') ) - { - if( bInGap == false ) - { - bInGap = true; - } - } - else if( *i == '"' ) + Bu::String sCmd = sLine.clone(); + int iParams = 0; + bool bInGap = true; + bool bInQuote = false; + for( Bu::String::iterator i = sCmd.begin(); i; i++ ) + { + if( bInQuote == false && (*i == ' ' || *i == '\t') ) + { + if( bInGap == false ) + { + bInGap = true; + } + } + else if( *i == '"' ) { bInQuote = !bInQuote; } @@ -211,242 +211,242 @@ void Bu::OptParser::parse( const Bu::String &sLine ) } } else if( *i == '"' ) - { - bInQuote = !bInQuote; - } - else - { - if( bInGap ) - { - asParam[iParams++] = i; - bInGap = false; - } - } - } - - parse( iParams, asParam ); - - delete[] asParam; + { + bInQuote = !bInQuote; + } + else + { + if( bInGap ) + { + asParam[iParams++] = i; + bInGap = false; + } + } + } + + parse( iParams, asParam ); + + delete[] asParam; } void Bu::OptParser::addOption( const Option &opt ) { - lOption.append( opt ); - if( opt.cOpt != '\0' ) - hsOption.insert( opt.cOpt, &lOption.last() ); - if( opt.sOpt.isSet() ) - hlOption.insert( opt.sOpt, &lOption.last() ); + lOption.append( opt ); + if( opt.cOpt != '\0' ) + hsOption.insert( opt.cOpt, &lOption.last() ); + if( opt.sOpt.isSet() ) + hlOption.insert( opt.sOpt, &lOption.last() ); } void Bu::OptParser::setOverride( char cOpt, const Bu::Variant &sOverride ) { - hsOption.get( cOpt )->sOverride = sOverride; + hsOption.get( cOpt )->sOverride = sOverride; } void Bu::OptParser::setOverride( const Bu::String &sOpt, const Bu::Variant &sOverride ) { - hlOption.get( sOpt )->sOverride = sOverride; + hlOption.get( sOpt )->sOverride = sOverride; } void Bu::OptParser::setHelpDefault( const Bu::String &sOpt, const Bu::String &sTxt ) { - hlOption.get( sOpt )->sHelpDefault = sTxt; + hlOption.get( sOpt )->sHelpDefault = sTxt; } void Bu::OptParser::addHelpOption( char c, const Bu::String &s, const Bu::String &sHelp ) { - Option o; - o.sUsed = slot( this, &OptParser::optHelp ); - o.cOpt = c; - o.sOpt = s; - o.sHelp = sHelp; - addOption( o ); + Option o; + o.sUsed = slot( this, &OptParser::optHelp ); + o.cOpt = c; + o.sOpt = s; + o.sHelp = sHelp; + addOption( o ); } void Bu::OptParser::addHelpBanner( const Bu::String &sText, bool bFormatted ) { - Banner b; - b.sText = sText; - b.bFormatted = bFormatted; - if( lOption.getSize() > 0 ) - { - for( b.iAfter = lOption.begin(); b.iAfter+1; b.iAfter++ ) { } - } - lBanner.append( b ); + Banner b; + b.sText = sText; + b.bFormatted = bFormatted; + if( lOption.getSize() > 0 ) + { + for( b.iAfter = lOption.begin(); b.iAfter+1; b.iAfter++ ) { } + } + lBanner.append( b ); } int Bu::OptParser::optHelp( StrArray /*aParams*/ ) { - bool bHasShort = false; - int iMaxWidth = 0; - int iScrWidth = 80; - char *env = getenv("COLUMNS"); - if( env ) - iScrWidth = strtol( env, NULL, 10 ); - for( OptionList::iterator i = lOption.begin(); i; i++ ) - { - if( (*i).cOpt != '\0' ) - bHasShort = true; - int lOptSize = (*i).sOpt.getSize() + (*i).sHelpDefault.getSize(); - if( (*i).sOpt.isSet() && iMaxWidth < lOptSize ) - iMaxWidth = lOptSize; - } - int iIndent = 4; - if( bHasShort ) - iIndent += 4; - if( iMaxWidth > 0 ) - iIndent += 4 + iMaxWidth; - - BannerList::iterator iBanner; - for( iBanner = lBanner.begin(); iBanner; iBanner++ ) - { - if( (*iBanner).iAfter ) - break; - - if( (*iBanner).bFormatted ) - sio << format( (*iBanner).sText, iScrWidth-1, 0 ); - else - sio << (*iBanner).sText; - sio << sio.nl; - } - for( OptionList::iterator i = lOption.begin(); i; i++ ) - { - sio << " "; - if( bHasShort ) - { - if( (*i).cOpt == '\0' ) - sio << " "; - else - sio << "-" << (*i).cOpt; - sio << " "; - } - if( iMaxWidth > 0 ) - { - if( (*i).sOpt.isSet() ) - { - sio << "--" << Fmt(iMaxWidth, Fmt::Left) - << (*i).sOpt + (*i).sHelpDefault; - } - else - { - sio << " " << Fmt(iMaxWidth) << ""; - } - sio << " "; - } - sio << format( (*i).sHelp, iScrWidth-iIndent-1, iIndent ); - sio << sio.nl; - - for( ; iBanner; iBanner++ ) - { - if( (*iBanner).iAfter != i ) - break; - - if( (*iBanner).bFormatted ) - sio << format( (*iBanner).sText, iScrWidth-1, 0 ); - else - sio << (*iBanner).sText; - sio << sio.nl; - } - } - exit( 0 ); - return 0; + bool bHasShort = false; + int iMaxWidth = 0; + int iScrWidth = 80; + char *env = getenv("COLUMNS"); + if( env ) + iScrWidth = strtol( env, NULL, 10 ); + for( OptionList::iterator i = lOption.begin(); i; i++ ) + { + if( (*i).cOpt != '\0' ) + bHasShort = true; + int lOptSize = (*i).sOpt.getSize() + (*i).sHelpDefault.getSize(); + if( (*i).sOpt.isSet() && iMaxWidth < lOptSize ) + iMaxWidth = lOptSize; + } + int iIndent = 4; + if( bHasShort ) + iIndent += 4; + if( iMaxWidth > 0 ) + iIndent += 4 + iMaxWidth; + + BannerList::iterator iBanner; + for( iBanner = lBanner.begin(); iBanner; iBanner++ ) + { + if( (*iBanner).iAfter ) + break; + + if( (*iBanner).bFormatted ) + sio << format( (*iBanner).sText, iScrWidth-1, 0 ); + else + sio << (*iBanner).sText; + sio << sio.nl; + } + for( OptionList::iterator i = lOption.begin(); i; i++ ) + { + sio << " "; + if( bHasShort ) + { + if( (*i).cOpt == '\0' ) + sio << " "; + else + sio << "-" << (*i).cOpt; + sio << " "; + } + if( iMaxWidth > 0 ) + { + if( (*i).sOpt.isSet() ) + { + sio << "--" << Fmt(iMaxWidth, Fmt::Left) + << (*i).sOpt + (*i).sHelpDefault; + } + else + { + sio << " " << Fmt(iMaxWidth) << ""; + } + sio << " "; + } + sio << format( (*i).sHelp, iScrWidth-iIndent-1, iIndent ); + sio << sio.nl; + + for( ; iBanner; iBanner++ ) + { + if( (*iBanner).iAfter != i ) + break; + + if( (*iBanner).bFormatted ) + sio << format( (*iBanner).sText, iScrWidth-1, 0 ); + else + sio << (*iBanner).sText; + sio << sio.nl; + } + } + exit( 0 ); + return 0; } void Bu::OptParser::optionError( const Bu::String &sOption ) { - sio << "Unregcognized option discovered: " << sOption << sio.nl << sio.nl; - exit( 1 ); + sio << "Unregcognized option discovered: " << sOption << sio.nl << sio.nl; + exit( 1 ); } void Bu::OptParser::setNonOption( OptionSignal sSignal ) { - sNonOption = sSignal; + sNonOption = sSignal; } Bu::String Bu::OptParser::format( const Bu::String &sIn, int iWidth, - int iIndent ) + int iIndent ) { - Bu::String sOut; - Bu::String sIndent; - for( int j = 0; j < iIndent; j++ ) - sIndent.append(" ", 1); - bool bFirst = true; - int iSpaceCount = 0; - bool bSpace = false; - int iPrevLineLen; - int iLineLen = 0; - Bu::String::const_iterator iLastSpace, iStart; - for( Bu::String::const_iterator i = iLastSpace = iStart = sIn.begin(); i; i++ ) - { - if( *i == ' ' ) - { - if( bSpace == false ) - { - iLastSpace = i; - iSpaceCount++; - bSpace = true; - iPrevLineLen = iLineLen; - } - } - else - { - bSpace = false; - } - iLineLen++; - - if( iLineLen >= iWidth ) - { - iSpaceCount--; - if( bFirst == true ) - bFirst = false; - else - sOut += sIndent; - int iExtraSpaces = iWidth-iPrevLineLen; - bSpace = false; - float fFill = 0.0; - int iSubSpaceCount = 0; - float fAdd = ((float)iExtraSpaces/(float)iSpaceCount); - for( Bu::String::const_iterator k = iStart; k != iLastSpace; k++ ) - { - sOut += *k; - if( *k == ' ' ) - { - if( bSpace == false && iExtraSpaces > 0 ) - { - bSpace = true; - fFill += fAdd; - iSubSpaceCount++; - for( int sp = 0; sp < (int)(fFill); sp++ ) - { - sOut += ' '; - iExtraSpaces--; - } - fFill -= (int)fFill; - if( iSubSpaceCount == iSpaceCount && iExtraSpaces > 0 ) - { - for(; iExtraSpaces > 0; iExtraSpaces-- ) - { - sOut += ' '; - } - } - } - } - else - bSpace = false; - } - //sOut.append( iStart, iLastSpace ); - sOut.append("\n"); - for(; iLastSpace && *iLastSpace == ' '; iLastSpace++ ) { } - iStart = i = iLastSpace; - bSpace = false; - iLineLen = 1; - iSpaceCount = 0; - } - } - if( !bFirst ) - sOut += sIndent; - sOut.append( iStart ); - return sOut; + Bu::String sOut; + Bu::String sIndent; + for( int j = 0; j < iIndent; j++ ) + sIndent.append(" ", 1); + bool bFirst = true; + int iSpaceCount = 0; + bool bSpace = false; + int iPrevLineLen; + int iLineLen = 0; + Bu::String::const_iterator iLastSpace, iStart; + for( Bu::String::const_iterator i = iLastSpace = iStart = sIn.begin(); i; i++ ) + { + if( *i == ' ' ) + { + if( bSpace == false ) + { + iLastSpace = i; + iSpaceCount++; + bSpace = true; + iPrevLineLen = iLineLen; + } + } + else + { + bSpace = false; + } + iLineLen++; + + if( iLineLen >= iWidth ) + { + iSpaceCount--; + if( bFirst == true ) + bFirst = false; + else + sOut += sIndent; + int iExtraSpaces = iWidth-iPrevLineLen; + bSpace = false; + float fFill = 0.0; + int iSubSpaceCount = 0; + float fAdd = ((float)iExtraSpaces/(float)iSpaceCount); + for( Bu::String::const_iterator k = iStart; k != iLastSpace; k++ ) + { + sOut += *k; + if( *k == ' ' ) + { + if( bSpace == false && iExtraSpaces > 0 ) + { + bSpace = true; + fFill += fAdd; + iSubSpaceCount++; + for( int sp = 0; sp < (int)(fFill); sp++ ) + { + sOut += ' '; + iExtraSpaces--; + } + fFill -= (int)fFill; + if( iSubSpaceCount == iSpaceCount && iExtraSpaces > 0 ) + { + for(; iExtraSpaces > 0; iExtraSpaces-- ) + { + sOut += ' '; + } + } + } + } + else + bSpace = false; + } + //sOut.append( iStart, iLastSpace ); + sOut.append("\n"); + for(; iLastSpace && *iLastSpace == ' '; iLastSpace++ ) { } + iStart = i = iLastSpace; + bSpace = false; + iLineLen = 1; + iSpaceCount = 0; + } + } + if( !bFirst ) + sOut += sIndent; + sOut.append( iStart ); + return sOut; } @@ -467,26 +467,26 @@ Bu::OptParser::_ValueProxy::~_ValueProxy() // Bu::OptParser::Option::Option() : - cOpt( '\0' ), - pProxy( NULL ) + cOpt( '\0' ), + pProxy( NULL ) { } Bu::OptParser::Option::Option( const Option &rSrc ) : - cOpt( rSrc.cOpt ), - sOpt( rSrc.sOpt ), - sHelp( rSrc.sHelp ), - sUsed( rSrc.sUsed ), - pProxy( NULL ), - sOverride( rSrc.sOverride ) + cOpt( rSrc.cOpt ), + sOpt( rSrc.sOpt ), + sHelp( rSrc.sHelp ), + sUsed( rSrc.sUsed ), + pProxy( NULL ), + sOverride( rSrc.sOverride ) { - if( rSrc.pProxy ) - pProxy = rSrc.pProxy->clone(); + if( rSrc.pProxy ) + pProxy = rSrc.pProxy->clone(); } Bu::OptParser::Option::~Option() { - delete pProxy; - pProxy = NULL; + delete pProxy; + pProxy = NULL; } diff --git a/src/stable/optparser.h b/src/stable/optparser.h index 2da93c9..412f262 100644 --- a/src/stable/optparser.h +++ b/src/stable/optparser.h @@ -19,205 +19,205 @@ namespace Bu { - typedef Bu::Array StrArray; - - /** - * POSIX/Gnu style command line parser. Handles long and short options in - * a variety of fun and useful ways, along with singal based callbacks and - * automatic variable setting. It's pretty easy to use, and very flexible. - * - * OptParser supports it's own builtin help mechanism which automatically - * enumerates the available options and their help in a well formatted and - * easy to read way, automatically formatting your help text per option and - * allows for addition "help banners" which can be placed wherever you - * would like. - */ - class OptParser - { - private: - class _ValueProxy - { - public: - _ValueProxy(); - virtual ~_ValueProxy(); - - virtual void setValueFromStr( const Bu::String & )=0; - virtual void setValue( const Bu::Variant &vVar )=0; - virtual _ValueProxy *clone()=0; - }; - - template - class ValueProxy : public _ValueProxy - { - public: - ValueProxy( ptype &v ) : - v( v ) - { - } - - virtual ~ValueProxy() - { - } - - virtual void setValueFromStr( const Bu::String &sVal ) - { - Bu::MemBuf mb( sVal ); - Bu::Formatter f( mb ); - f << Bu::Fmt().tokenize( false ); - f >> v; - } - - virtual void setValue( const Bu::Variant &vVar ) - { - if( vVar.getType() == typeid(ptype) ) - { - v = vVar.get(); - } - else if( vVar.getType() == typeid(Bu::String) ) - { - setValueFromStr( vVar.get() ); - } - else - { - Bu::MemBuf mb; - Bu::Formatter f( mb ); -// f << vVar; - setValueFromStr( mb.getString() ); - } - } - - virtual _ValueProxy *clone() - { - return new ValueProxy( v ); - } - - private: - ptype &v; - }; - - public: - typedef Signal1 OptionSignal; - class Option - { - public: - Option(); - Option( const Option &rSrc ); - virtual ~Option(); - - char cOpt; - Bu::String sOpt; - Bu::String sHelp; - OptionSignal sUsed; - _ValueProxy *pProxy; - Bu::Variant sOverride; - Bu::String sHelpDefault; - }; - - private: - typedef Bu::List