/* $Revision: 27 $ $Date: 3/11/04 21:51 $ Copyright © 2000-2003, FSL Technologies Limited. Contact "http://fost3.fsltech.com". */ #include "stdafx.h" using namespace std; using namespace FSLib; // Enable the below line to force the Settings database to use fully exclusive locking //#define WRITELOCKONLY //#define SAFECOPY namespace { Revision c_revision( L"$Archive: /FOST.3/F3Util/setting.cpp $", __DATE__, L"$Revision: 27 $", L"$Date: 3/11/04 21:51 $" ); const wchar_t MissingSettingMsg[]=L"Setting is missing"; const wchar_t SettingsFaultMsg[]=L"Internal Setting library fault"; typedef list< Setting * > t_settingStack; typedef pair< FSLib::wstring, FSLib::wstring > t_settingKey; typedef map< t_settingKey, t_settingStack > t_settings; #ifdef WRITELOCKONLY Mutex &g_mutex() { static Mutex mutex; return mutex; } #else ExclusiveWrite &g_exw() { static ExclusiveWrite exw( 20 ); return exw; } #endif t_settings &g_settingsSettings() { static t_settings settings; return settings; } inline #ifdef WRITELOCKONLY t_settings &g_writeSettings( Mutex::Lock & ) { #else t_settings &g_writeSettings( ExclusiveWrite::WriteLock & ) { #endif return g_settingsSettings(); } inline #ifdef WRITELOCKONLY const t_settings &g_readSettings( Mutex::Lock &) { #else const t_settings &g_readSettings( ExclusiveWrite::ReadLock & ) { #endif return g_settingsSettings(); } } /* FSLib::Exceptions::MissingSetting */ inline FSLib::Exceptions::MissingSetting::MissingSetting( const FSLib::wstring §ion, const FSLib::wstring &name ) : Exception() { m_info << L"Section: " << section << endl << L"Name: " << name << endl; } inline const wchar_t * const FSLib::Exceptions::MissingSetting::message() const { return MissingSettingMsg; } /* FSLib::Exceptions::SettingFault */ inline FSLib::Exceptions::SettingsFault::SettingsFault( const FSLib::wstring &error, const FSLib::wstring &domain, const FSLib::wstring §ion, const FSLib::wstring &name, const FSLib::wstring &value ) : Exception( error ) { m_info << L"Domain: " << domain << endl << L"Section: " << section << endl << L"Name: " << name << endl << L"Value: " << value << endl; } inline const wchar_t * const FSLib::Exceptions::SettingsFault::message() const { return SettingsFaultMsg; } /* FSLib::Setting */ inline Setting::Setting( const FSLib::wstring &domain, const FSLib::wstring §ion, const FSLib::wstring &name, const FSLib::wstring &value, bool def ) : m_domain( domain ), m_section( section ), m_name( name ), m_value( value ) { #ifdef WRITELOCKONLY Mutex::Lock lock( g_mutex() ); #else ExclusiveWrite::WriteLock lock( g_exw() ); #endif if ( def ) { g_writeSettings( lock )[ make_pair( m_section, m_name ) ].push_front( this ); } else { g_writeSettings( lock )[ make_pair( m_section, m_name ) ].push_back( this ); } } inline Setting::~Setting() { try { #ifdef WRITELOCKONLY Mutex::Lock lock( g_mutex() ); #else ExclusiveWrite::WriteLock lock( g_exw() ); #endif t_settings::iterator pos( g_writeSettings( lock ).find( make_pair( m_section, m_name ) ) ); if ( pos == g_writeSettings( lock ).end() ) { //throw Exceptions::MissingSetting( m_section, m_name ); // This is bad, but we don't want to be throwing an exception here, but we can log losing one // Lose exception absorbException(); } else { (*pos).second.remove( this ); // Now check to see if the section/name is empty. If so then we ought to remove that too. if ( (*pos).second.empty() ) { g_writeSettings( lock ).erase( pos ); } } } catch ( exception & ) { absorbException(); } } inline wostream &Setting::printOn( wostream &o ) const { return o << L"setting," << m_section << L"," << m_name << L"," << m_value << L"," << m_domain; } const FSLib::wstring Setting::value() const { return value( m_section, m_name ); } const FSLib::wstring Setting::value( const FSLib::wstring §ion, const FSLib::wstring &name ) { #ifdef WRITELOCKONLY Mutex::Lock lock( g_mutex() ); #else ExclusiveWrite::ReadLock lock( g_exw() ); #endif t_settings::const_iterator pos( g_readSettings( lock ).find( make_pair( section, name ) ) ); if ( pos == g_readSettings( lock ).end() ) { throw Exceptions::MissingSetting( section, name ); } else { if ( (*pos).second.rbegin() == (*pos).second.rend() ) { throw Exceptions::MissingSetting( section, name ); } else { #ifdef SAFECOPY wstringstream strstr; strstr << (*(*pos).second.rbegin())->m_value; return strstr.str(); #else return (*(*pos).second.rbegin())->m_value; #endif } } } const pair< bool, FSLib::wstring > Setting::value( const FSLib::wstring §ion, const FSLib::wstring &name, const FSLib::wstring &def ) { Nullable< FSLib::wstring > ret = Setting::value( section, name, Nullable< FSLib::wstring >() ); if ( ret.isnull() ) { return make_pair( true, def ); } else { return make_pair( false, ret.value() ); } } const Nullable< FSLib::wstring > Setting::value( const FSLib::wstring §ion, const FSLib::wstring &name, const Nullable< FSLib::wstring > &def ) { #ifdef WRITELOCKONLY Mutex::Lock lock( g_mutex() ); #else ExclusiveWrite::ReadLock lock( g_exw() ); #endif t_settings::const_iterator pos( g_readSettings( lock ).find( make_pair( section, name ) ) ); if ( pos == g_readSettings( lock ).end() ) { #ifdef SAFECOPY if ( def ) { wstringstream strstr; strstr << def.value(); return FSLib::wstring( strstr.str() ); } else { return Nullable< FSLib::wstring >(); } #else return def; #endif } else { if ( (*pos).second.rbegin() == (*pos).second.rend() ) { #ifdef SAFECOPY if ( def ) { wstringstream strstr; strstr << def.value(); return FSLib::wstring( strstr.str() ); } else { return Nullable< FSLib::wstring >(); } #else return def; #endif } else { #ifdef SAFECOPY wstringstream strstr; strstr << (*(*pos).second.rbegin())->m_value; return FSLib::wstring( strstr.str() ); #else return (*(*pos).second.rbegin())->m_value; #endif } } } Setting::t_sections Setting::current() { t_sections sections; FSLib::wstring section; #ifdef WRITELOCKONLY Mutex::Lock lock( g_mutex() ); #else ExclusiveWrite::ReadLock lock( g_exw() ); #endif for ( t_settings::const_iterator setting( g_readSettings( lock ).begin() ); setting != g_readSettings( lock ).end(); ++setting ) { if ( (*setting).first.first != section ) { section = (*setting).first.first; sections.push_back( make_pair( section, t_values() ) ); } sections.back().second.push_back( make_pair( (*setting).first.second, t_definitions() ) ); const t_settingStack stack( (*setting).second ); for ( t_settingStack::const_iterator val( stack.begin() ); val != stack.end(); ++val ) { sections.back().second.back().second.push_back( make_pair( (*val)->m_domain, (*val)->m_value ) ); } } return sections; } wostream &Setting::printAllOn( wostream &o ) { #ifdef WRITELOCKONLY Mutex::Lock lock( g_mutex() ); #else ExclusiveWrite::ReadLock lock( g_exw() ); #endif for ( t_settings::const_iterator setting( g_readSettings( lock ).begin() ); setting != g_readSettings( lock ).end(); ++setting ) { const t_settingStack stack( (*setting).second ); for ( t_settingStack::const_iterator val( stack.begin() ); val != stack.end(); ) { (*val)->printOn( o ); o << ( ++val == stack.end() ? L",Used" : L",Overridden" ) << endl; } } return o; } /* $History: setting.cpp $ * * ***************** Version 27 ***************** * User: Kirit Date: 3/11/04 Time: 21:51 * Updated in $/FOST.3/F3Util * First working version of FSLib::wstring using UTF-16. * * ***************** Version 26 ***************** * User: Kirit Date: 5/07/04 Time: 11:38 * Updated in $/FOST.3/F3Util * Parts now use newer string library functions. * * ***************** Version 25 ***************** * User: Kirit Date: 11/10/03 Time: 15:50 * Updated in $/FOST.3/F3Util * Added new string handling functions from RoseDoc. * * ***************** Version 24 ***************** * User: Kirit Date: 9/10/03 Time: 15:44 * Updated in $/FOST.3/F3Util * Headers re-arranged to give a proper SDK feel and to make determination * of required headers simpler. * * ***************** Version 22 ***************** * User: Kirit Date: 3/10/03 Time: 20:03 * Updated in $/FOST.3/F3Util * Added FSSettings files to F3Util.DLL * * ***************** Version 21 ***************** * User: Kirit Date: 3/10/03 Time: 16:09 * Updated in $/FOST/Cpp/FSSettings * Added stdafx.h and stdafx.cpp pre-compiled header support. * * ***************** Version 20 ***************** * User: Kirit Date: 18/09/02 Time: 13:17 * Updated in $/FOST/Cpp/FSSettings * Setting value (normally a default) can be used to fetch the current * value. * * ***************** Version 19 ***************** * User: Kirit Date: 7/07/02 Time: 15:57 * Updated in $/FOST/Cpp/FSSettings * Now distinguishes between settings for default purposes and those that * are created to override a default. * * ***************** Version 18 ***************** * User: Kirit Date: 7/05/02 Time: 12:01 * Updated in $/FOST/Cpp/FSSettings * Wrapped std::basic_string<> in order to change the copy semantics to * stop the problems with using C++ in the COM layer for IIS. * * ***************** Version 17 ***************** * User: Kirit Date: 3/05/02 Time: 19:46 * Updated in $/FOST/Cpp/FSSettings * Various updates to Setting library to try to isolate IIS process * failures. * * ***************** Version 16 ***************** * User: Kirit Date: 28/04/02 Time: 21:18 * Updated in $/FOST/Cpp/FSSettings * Added support for converting Windows Structured Exceptions to the * std::exception hierarchy. * Updated exceptions so that catch (...) is only done where necessary and * correct. * * ***************** Version 15 ***************** * User: Kirit Date: 4/04/02 Time: 10:14 * Updated in $/FOST/Cpp/FSSettings * Set the number of readers allowed at any one time to 20 for the * settings database. * * ***************** Version 14 ***************** * User: Kirit Date: 19/03/02 Time: 20:54 * Updated in $/FOST/Cpp/FSSettings * Corrected history from last check-in. * Updated TestAX.IDL to remove registry entries from removed classes. * * ***************** Version 13 ***************** * User: Kirit Date: 19/03/02 Time: 19:48 * Updated in $/FOST/Cpp/FSSettings * Debug compiles now all end in '_d'. * The C++ implementation names (Type.cppName) have been changed to also * include the DLL that the implementation is in as per the documentation. * In all source files the following have been done: * * Ensured that every header file has a revision object. * * Ensured that every translation unit has a revision object. * * Ensured that every source file (which understands comments) * has a history section. * * Changed all copyright notices to be for Obsideon Ltd. * * Changed copyright notices to use the longest possible timeframe. * * ***************** Version 12 ***************** * User: Kirit Date: 11/03/02 Time: 16:13 * Updated in $/FOST/Cpp/FSSettings * Addition of TestAX.HTML01.Block and changes in the class HTML search * order. * * ***************** Version 11 ***************** * User: Kirit Date: 25/02/02 Time: 23:22 * Updated in $/FOST/Cpp/FSSettings * New HTML generation component. * Required addition to FSLib::Setting interface to read a value with a * default provided at runtime. * * ***************** Version 10 ***************** * User: Kirit Date: 20/02/02 Time: 0:55 * Updated in $/FOST/Cpp/FSSettings * Destructors corrected to give correct behaviour with exceptions. * * ***************** Version 9 ***************** * User: Kirit Date: 2/12/01 Time: 16:03 * Updated in $/FOST/Cpp/FSSettings * The removal of the last setting in a section now leads to the removal * of that section. * Added a method for iterating through all settings in the library. * * ***************** Version 8 ***************** * User: Kirit Date: 12/11/01 Time: 15:30 * Updated in $/FOST/Cpp/FSSettings * Changed Setting locking to use new ExclusiveWrite lock to be more * efficient. * * ***************** Version 7 ***************** * User: Kirit Date: 23/07/01 Time: 15:48 * Updated in $/FOST/FSSettings * Log file corrections. * Use of Settings now thread safe (one global set of settings for all * threads). * * ***************** Version 6 ***************** * User: Kirit Date: 10/07/01 Time: 18:06 * Updated in $/FOST/FSSettings * Full support for command line argument parsing and INI file parsing. * Also fixes to errors within exception handling and unicode support. * * ***************** Version 5 ***************** * User: Kirit Date: 9/07/01 Time: 18:37 * Updated in $/FOST/FSSettings * Improved settings handling and reporting. * * ***************** Version 4 ***************** * User: Kirit Date: 9/07/01 Time: 17:13 * Updated in $/FOST/FSSettings * Settings can now be created and are removed when out of scope. * * ***************** Version 3 ***************** * User: Kirit Date: 5/07/01 Time: 17:41 * Updated in $/FOST/FSSettings * First Unicode only version of FOST. * * ***************** Version 2 ***************** * User: Kirit Date: 2/07/01 Time: 14:19 * Updated in $/FOST/FSSettings * Addition of FSSettings DLL to handle simple default setting values. * * ***************** Version 1 ***************** * User: Kirit Date: 2/07/01 Time: 13:58 * Created in $/FOST/FSSettings */