From da642482dee91921fc16786208aa497d3ee31d94 Mon Sep 17 00:00:00 2001 From: Mike Buland Date: Fri, 24 Aug 2012 18:15:11 +0000 Subject: Adding new Bu::Settings system, which works more or less like QSettings from Qt, only...without qt. It's the first real system in libbu++ that is going to be all unicode, which is exciting, but I'm having to actually finish the Bu::UtfString class while I work on it. Also exciting. --- src/tests/settings.cpp | 9 ++++ src/tests/utf.cpp | 6 +++ src/unstable/settings.cpp | 40 ++++++++++++++ src/unstable/settings.h | 34 ++++++++++++ src/unstable/settingsdriver.cpp | 10 ++++ src/unstable/settingsdriver.h | 26 +++++++++ src/unstable/settingsdrivertaf.cpp | 29 ++++++++++ src/unstable/settingsdrivertaf.h | 24 +++++++++ src/unstable/utfstring.cpp | 78 ++++++++++++++++++++++----- src/unstable/utfstring.h | 105 +++++++++++++++++++++++++++++++++---- 10 files changed, 336 insertions(+), 25 deletions(-) create mode 100644 src/tests/settings.cpp create mode 100644 src/unstable/settings.cpp create mode 100644 src/unstable/settings.h create mode 100644 src/unstable/settingsdriver.cpp create mode 100644 src/unstable/settingsdriver.h create mode 100644 src/unstable/settingsdrivertaf.cpp create mode 100644 src/unstable/settingsdrivertaf.h diff --git a/src/tests/settings.cpp b/src/tests/settings.cpp new file mode 100644 index 0000000..0738cb7 --- /dev/null +++ b/src/tests/settings.cpp @@ -0,0 +1,9 @@ +#include "bu/settings.h" + +int main() +{ + Bu::Settings s("Xagasoft", "Settings"); + + +} + diff --git a/src/tests/utf.cpp b/src/tests/utf.cpp index 3418e68..923b611 100644 --- a/src/tests/utf.cpp +++ b/src/tests/utf.cpp @@ -1,9 +1,15 @@ #include #include #include +#include + +using namespace Bu; int main() { + sio << "Code: " << Bu::__calcHashCode( Bu::UtfString("Hello there") ) + << sio.nl; + Bu::File fIn("utf8.in", Bu::File::Read ); Bu::String sUtf8; char buf[4096]; diff --git a/src/unstable/settings.cpp b/src/unstable/settings.cpp new file mode 100644 index 0000000..e993250 --- /dev/null +++ b/src/unstable/settings.cpp @@ -0,0 +1,40 @@ +#include "bu/settings.h" + +#include "bu/settingsdrivertaf.h" + +Bu::Settings::Settings( const Bu::UtfString &sCompany, + const Bu::UtfString &sProduct, Bu::Settings::Driver eDriver ) : + sCompany( sCompany ), + sProduct( sProduct ), + pDriver( NULL ) +{ + switch( eDriver ) + { + case DriverNative: +#if defined( WIN32 ) +#else + pDriver = new Bu::SettingsDriverTaf(); +#endif + break; + + case DriverTaf: + pDriver = new Bu::SettingsDriverTaf(); + break; + + case DriverIni: + throw Bu::ExceptionBase("Not supported"); + break; + } + + pDriver->init( sCompany, sProduct ); +} + +Bu::Settings::~Settings() +{ + delete pDriver; +} + +void Bu::Settings::set( const Bu::UtfString &sKey, const Bu::UtfString &sValue ) +{ +} + diff --git a/src/unstable/settings.h b/src/unstable/settings.h new file mode 100644 index 0000000..0736ee5 --- /dev/null +++ b/src/unstable/settings.h @@ -0,0 +1,34 @@ +#ifndef BU_SETTINGS_H +#define BU_SETTINGS_H + +#include "bu/utfstring.h" + +namespace Bu +{ + /** + * Simple access to configuration data. Provides a consistant, cross + * platform interface to configuration data using native storage. + */ + class Settings + { + public: + enum Driver + { + DriverNative, + DriverTaf, + DriverIni + }; + Settings( const Bu::UtfString &sCompany, const Bu::UtfString &sProduct, + Driver driver=DriverNative ); + virtual ~Settings(); + + void set( const Bu::UtfString &sKey, const Bu::UtfString &sValue ); + + private: + Bu::UtfString sCompany; + Bu::UtfString sProduct; + class SettingsDriver *pDriver; + }; +}; + +#endif diff --git a/src/unstable/settingsdriver.cpp b/src/unstable/settingsdriver.cpp new file mode 100644 index 0000000..92cac77 --- /dev/null +++ b/src/unstable/settingsdriver.cpp @@ -0,0 +1,10 @@ +#include "bu/settingsdriver.h" + +Bu::SettingsDriver::SettingsDriver() +{ +} + +Bu::SettingsDriver::~SettingsDriver() +{ +} + diff --git a/src/unstable/settingsdriver.h b/src/unstable/settingsdriver.h new file mode 100644 index 0000000..0a63106 --- /dev/null +++ b/src/unstable/settingsdriver.h @@ -0,0 +1,26 @@ +#ifndef BU_SETTINGS_DRIVER_H +#define BU_SETTINGS_DRIVER_H + +#include "bu/utfstring.h" + +namespace Bu +{ + class Settings; + + /** + * Base class for i/o interfaces for Bu::Settings. By subclassing this you + * can provide custom storage for application settings. + */ + class SettingsDriver + { + friend class Bu::Settings; + public: + SettingsDriver(); + virtual ~SettingsDriver(); + + protected: + virtual void init( const Bu::UtfString &sCompany, const Bu::UtfString &sProduct )=0; + }; +}; + +#endif diff --git a/src/unstable/settingsdrivertaf.cpp b/src/unstable/settingsdrivertaf.cpp new file mode 100644 index 0000000..164bf0b --- /dev/null +++ b/src/unstable/settingsdrivertaf.cpp @@ -0,0 +1,29 @@ +#include "bu/settingsdrivertaf.h" + +#include "bu/file.h" +#include "bu/taf.h" + +#include + +Bu::SettingsDriverTaf::SettingsDriverTaf() : + pRoot( NULL ) +{ +} + +Bu::SettingsDriverTaf::~SettingsDriverTaf() +{ +} + +void Bu::SettingsDriverTaf::init( const Bu::UtfString &sCompany, + const Bu::UtfString &sProduct ) +{ + Bu::UtfString us( getenv("HOME") ); + us += "/"; + us += sCompany; + us += "/"; + us += sProduct; + Bu::File fIn( us.get(), Bu::File::Read|Bu::File::Create ); + Bu::TafReader tr( fIn ); + pRoot = tr.readGroup(); +} + diff --git a/src/unstable/settingsdrivertaf.h b/src/unstable/settingsdrivertaf.h new file mode 100644 index 0000000..d7d751b --- /dev/null +++ b/src/unstable/settingsdrivertaf.h @@ -0,0 +1,24 @@ +#ifndef BU_SETTINGS_DRIVER_TAF_H +#define BU_SETTINGS_DRIVER_TAF_H + +#include "bu/settingsdriver.h" + +namespace Bu +{ + class TafGroup; + + class SettingsDriverTaf : public SettingsDriver + { + public: + SettingsDriverTaf(); + virtual ~SettingsDriverTaf(); + + protected: + virtual void init( const Bu::UtfString &sCompany, const Bu::UtfString &sProduct ); + + private: + class Bu::TafGroup *pRoot; + }; +}; + +#endif diff --git a/src/unstable/utfstring.cpp b/src/unstable/utfstring.cpp index 1c6813c..9fe2d02 100644 --- a/src/unstable/utfstring.cpp +++ b/src/unstable/utfstring.cpp @@ -23,10 +23,25 @@ Bu::UtfString::UtfString( const Bu::String &sInput, Encoding eEnc ) set( sInput, eEnc ); } +Bu::UtfString::UtfString( const char *sInput, Encoding eEnc ) +{ + set( sInput, eEnc ); +} + Bu::UtfString::~UtfString() { } +Bu::UtfString::iterator Bu::UtfString::begin() +{ + return Bu::UtfString::iterator( this, 0 ); +} + +Bu::UtfString::const_iterator Bu::UtfString::begin() const +{ + return Bu::UtfString::const_iterator( this, 0 ); +} + void Bu::UtfString::set( const Bu::String &sInput, Encoding eEnc ) { switch( eEnc ) @@ -258,7 +273,7 @@ void Bu::UtfString::setUtf32le( const Bu::String &sInput ) } } -void Bu::UtfString::write( Bu::Stream &sOut, Encoding eEnc ) +void Bu::UtfString::write( Bu::Stream &sOut, Encoding eEnc ) const { switch( eEnc ) { @@ -306,7 +321,7 @@ void Bu::UtfString::write( Bu::Stream &sOut, Encoding eEnc ) } } -void Bu::UtfString::writeUtf8( Bu::Stream &sOut ) +void Bu::UtfString::writeUtf8( Bu::Stream &sOut ) const { int iPos = 0; while( iPos < aData.getSize() ) @@ -359,12 +374,12 @@ void Bu::UtfString::writeUtf16( Bu::Stream &sOut ) { } */ -void Bu::UtfString::writeUtf16be( Bu::Stream &sOut ) +void Bu::UtfString::writeUtf16be( Bu::Stream &sOut ) const { #if BYTE_ORDER == BIG_ENDIAN uint16_t iTmp = 0xFEFF; // Byte Order Marker sOut.write( &iTmp, 2 ); - for( Array::iterator i = aData.begin(); i; i++ ) + for( Array::const_iterator i = aData.begin(); i; i++ ) { iTmp = *i; sOut.write( &iTmp, 2 ); @@ -373,7 +388,7 @@ void Bu::UtfString::writeUtf16be( Bu::Stream &sOut ) uint16_t iTmp = 0xFEFF; // Byte Order Marker iTmp = (iTmp>>8) | (iTmp<<8); sOut.write( &iTmp, 2 ); - for( Array::iterator i = aData.begin(); i; i++ ) + for( Array::const_iterator i = aData.begin(); i; i++ ) { iTmp = *i; iTmp = (iTmp>>8) | (iTmp<<8); @@ -382,12 +397,12 @@ void Bu::UtfString::writeUtf16be( Bu::Stream &sOut ) #endif } -void Bu::UtfString::writeUtf16le( Bu::Stream &sOut ) +void Bu::UtfString::writeUtf16le( Bu::Stream &sOut ) const { #if BYTE_ORDER == LITTLE_ENDIAN uint16_t iTmp = 0xFEFF; // Byte Order Marker sOut.write( &iTmp, 2 ); - for( Array::iterator i = aData.begin(); i; i++ ) + for( Array::const_iterator i = aData.begin(); i; i++ ) { iTmp = *i; sOut.write( &iTmp, 2 ); @@ -396,7 +411,7 @@ void Bu::UtfString::writeUtf16le( Bu::Stream &sOut ) uint16_t iTmp = 0xFEFF; // Byte Order Marker iTmp = (iTmp>>8) | (iTmp<<8); sOut.write( &iTmp, 2 ); - for( Array::iterator i = aData.begin(); i; i++ ) + for( Array::const_iterator i = aData.begin(); i; i++ ) { iTmp = *i; iTmp = (iTmp>>8) | (iTmp<<8); @@ -405,7 +420,7 @@ void Bu::UtfString::writeUtf16le( Bu::Stream &sOut ) #endif } -void Bu::UtfString::writeUtf32be( Bu::Stream &sOut ) +void Bu::UtfString::writeUtf32be( Bu::Stream &sOut ) const { #if BYTE_ORDER == BIG_ENDIAN uint32_t iTmp = 0xFEFF; // Byte Order Marker @@ -430,7 +445,7 @@ void Bu::UtfString::writeUtf32be( Bu::Stream &sOut ) #endif } -void Bu::UtfString::writeUtf32le( Bu::Stream &sOut ) +void Bu::UtfString::writeUtf32le( Bu::Stream &sOut ) const { #if BYTE_ORDER == LITTLE_ENDIAN uint32_t iTmp = 0xFEFF; // Byte Order Marker @@ -455,12 +470,12 @@ void Bu::UtfString::writeUtf32le( Bu::Stream &sOut ) #endif } -Bu::UtfChar Bu::UtfString::get( int iIndex ) +Bu::UtfChar Bu::UtfString::get( int iIndex ) const { return nextChar( iIndex ); } -Bu::UtfChar Bu::UtfString::nextChar( int &iIndex ) +Bu::UtfChar Bu::UtfString::nextChar( int &iIndex ) const { Bu::UtfChar i = aData[iIndex++]; switch( i&0xFC00 ) @@ -476,14 +491,31 @@ Bu::UtfChar Bu::UtfString::nextChar( int &iIndex ) } } -Bu::String Bu::UtfString::get( Encoding eEnc ) +bool Bu::UtfString::operator==( const Bu::UtfString &rhs ) const +{ + return aData == rhs.aData; +} + +Bu::UtfString &Bu::UtfString::operator+=( const Bu::UtfString &rhs ) +{ + append( rhs ); + return *this; +} + +Bu::UtfString &Bu::UtfString::operator+=( const UtfChar &rhs ) +{ + append( rhs ); + return *this; +} + +Bu::String Bu::UtfString::get( Encoding eEnc ) const { Bu::MemBuf mb; write( mb, eEnc ); return mb.getString(); } -void Bu::UtfString::debug() +void Bu::UtfString::debug() const { sio << "Raw Utf16: "; for( int i = 0; i < aData.getSize(); i++ ) @@ -552,3 +584,21 @@ void Bu::UtfString::debugUtf8( const Bu::String &sUtf8 ) sio << sio.nl; } */ + +template<> uint32_t Bu::__calcHashCode( const Bu::UtfString &k ) +{ + uint32_t uCode = 0; + + for( Bu::UtfString::const_iterator i = k.begin(); i; i++ ) + { + uCode = *i + (uCode<<6) + (uCode<<16) - uCode; + } + + return uCode; +} + +template<> bool Bu::__cmpHashKeys( + const Bu::UtfString &a, const Bu::UtfString &b ) +{ + return a == b; +} diff --git a/src/unstable/utfstring.h b/src/unstable/utfstring.h index af233e8..1bd4cce 100644 --- a/src/unstable/utfstring.h +++ b/src/unstable/utfstring.h @@ -72,10 +72,12 @@ namespace Bu UtfString(); UtfString( const Bu::String &sInput, Encoding eEnc=Utf8 ); + UtfString( const char *sInput, Encoding eEnc=Utf8 ); virtual ~UtfString(); class iterator { + friend class UtfString; private: iterator( UtfString *pSrc, int iCodePos ) : pSrc( pSrc ), iCodePos( iCodePos ) @@ -92,13 +94,77 @@ namespace Bu { if( !pSrc ) throw Bu::ExceptionBase("invalid UtfString::iterator dereferenced."); - return pSrc->nextChar( iCodePos ); + return pSrc->get( iCodePos ); + } + + iterator operator++() + { + pSrc->nextChar( iCodePos ); + return *this; + } + + iterator operator++( int ) + { + pSrc->nextChar( iCodePos ); + return *this; + } + + operator bool() const + { + return iCodePos < pSrc->aData.getSize(); } private: UtfString *pSrc; int iCodePos; }; + + class const_iterator + { + friend class UtfString; + private: + const_iterator( const UtfString *pSrc, int iCodePos ) : + pSrc( pSrc ), iCodePos( iCodePos ) + { + } + + public: + const_iterator() : + pSrc( NULL ), iCodePos( 0 ) + { + } + + UtfChar operator*() + { + if( !pSrc ) + throw Bu::ExceptionBase("invalid UtfString::iterator dereferenced."); + return pSrc->get( iCodePos ); + } + + const_iterator operator++() + { + pSrc->nextChar( iCodePos ); + return *this; + } + + const_iterator operator++( int ) + { + pSrc->nextChar( iCodePos ); + return *this; + } + + operator bool() const + { + return iCodePos < pSrc->aData.getSize(); + } + + private: + const UtfString *pSrc; + int iCodePos; + }; + + iterator begin(); + const_iterator begin() const; /** * Append a UtfChar (A unicode code point) to the string. This can be @@ -122,23 +188,23 @@ namespace Bu * the provided stream. all Utf16 and Utf32 encodings will have the * correct BOM (byte order marker) at the begining. */ - void write( Bu::Stream &sOut, Encoding eEnc=Utf8 ); + void write( Bu::Stream &sOut, Encoding eEnc=Utf8 ) const; /** * This encodes the UtfString in the given encoding and returns it as * a binary Bu::String. Like write, this also includes the proper BOM * at the begining. */ - Bu::String get( Encoding eEnc=Utf8 ); + Bu::String get( Encoding eEnc=Utf8 ) const; - void debug(); + void debug() const; /** * This may or may not stick around, given an index, this returns a * codepoint, however there isn't necesarilly a 1:1 ratio between * indexes and code points. */ - UtfChar get( int iIndex ); + UtfChar get( int iIndex ) const; /** * This is what to use if you want to iterate through a section of the @@ -147,7 +213,11 @@ namespace Bu * will return the codepoint at that position and increment iIndex an * appropriate amount for it to point to the next code point. */ - UtfChar nextChar( int &iIndex ); + UtfChar nextChar( int &iIndex ) const; + + bool operator==( const Bu::UtfString &rhs ) const; + UtfString &operator+=( const Bu::UtfString &rhs ); + UtfString &operator+=( const UtfChar &rhs ); private: void append16( uint16_t i ) { aData.append( i ); } @@ -160,17 +230,30 @@ namespace Bu void setUtf32be( const Bu::String &sInput ); void setUtf32le( const Bu::String &sInput ); - void writeUtf8( Bu::Stream &sOut ); - void writeUtf16be( Bu::Stream &sOut ); - void writeUtf16le( Bu::Stream &sOut ); - void writeUtf32be( Bu::Stream &sOut ); - void writeUtf32le( Bu::Stream &sOut ); + void writeUtf8( Bu::Stream &sOut ) const; + void writeUtf16be( Bu::Stream &sOut ) const; + void writeUtf16le( Bu::Stream &sOut ) const; + void writeUtf32be( Bu::Stream &sOut ) const; + void writeUtf32le( Bu::Stream &sOut ) const; private: Bu::Array aData; int iRawLen; int iCharLen; }; + + // + // Hash support + // + template + uint32_t __calcHashCode( const T &k ); + + template + bool __cmpHashKeys( const T &a, const T &b ); + + template<> uint32_t __calcHashCode( const UtfString &k ); + template<> bool __cmpHashKeys( + const UtfString &a, const UtfString &b ); }; #endif -- cgit v1.2.3