diff --git a/Source/kwsys/Registry.cxx b/Source/kwsys/Registry.cxx new file mode 100644 index 000000000..48f205398 --- /dev/null +++ b/Source/kwsys/Registry.cxx @@ -0,0 +1,658 @@ +/*========================================================================= + + Program: KWSys - Kitware System Library + Module: $RCSfile$ + + Copyright (c) Kitware, Inc., Insight Consortium. All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ +#include "kwsysPrivate.h" +#include KWSYS_HEADER(Registry.hxx) + +#include KWSYS_HEADER(Configure.hxx) +#include KWSYS_HEADER(ios/iostream) +#include KWSYS_HEADER(stl/string) +#include KWSYS_HEADER(stl/map) +#include KWSYS_HEADER(ios/iostream) +#include KWSYS_HEADER(ios/fstream) +#include KWSYS_HEADER(ios/sstream) + +#include // for isspace +#include + +#ifdef KWSYS_IOS_USE_ANSI +# define VTK_IOS_NOCREATE +#else +# define VTK_IOS_NOCREATE | kwsys_ios::ios::nocreate +#endif +#define BUFFER_SIZE 8192 + +namespace KWSYS_NAMESPACE +{ +class RegistryHelper { +public: + RegistryHelper(Registry::RegistryType registryType); + virtual ~RegistryHelper(); + + // Read a value from the registry. + virtual bool ReadValue(const char *key, char *value); + + // Delete a key from the registry. + virtual bool DeleteKey(const char *key); + + // Delete a value from a given key. + virtual bool DeleteValue(const char *key); + + // Set value in a given key. + virtual bool SetValue(const char *key, + const char *value); + + // Open the registry at toplevel/subkey. + virtual bool Open(const char *toplevel, const char *subkey, + int readonly); + + // Close the registry. + virtual bool Close(); + + // Set the value of changed + void SetChanged(bool b) { m_Changed = b; } + void SetTopLevel(const char* tl); + const char* GetTopLevel() { return m_TopLevel.c_str(); } + +protected: + bool m_Changed; + kwsys_stl::string m_TopLevel; + +#ifdef WIN32 + HKEY HKey; +#endif + // Strip trailing and ending spaces. + char *Strip(char *str); + void SetSubKey(const char* sk); + char *CreateKey(const char *key); + + typedef kwsys_stl::map StringToStringMap; + StringToStringMap EntriesMap; + kwsys_stl::string m_SubKey; + bool m_Empty; + bool m_SubKeySpecified; + + Registry::RegistryType m_RegistryType; +}; + + +//---------------------------------------------------------------------------- +Registry::Registry(Registry::RegistryType registryType) +{ + m_Opened = false; + m_Locked = false; + m_GlobalScope = false; + this->Helper = 0; + this->Helper = new RegistryHelper(registryType); +} + +//---------------------------------------------------------------------------- +Registry::~Registry() +{ + if ( m_Opened ) + { + kwsys_ios::cerr << "Registry::Close should be " + "called here. The registry is not closed." + << kwsys_ios::endl; + } + delete this->Helper; +} + +//---------------------------------------------------------------------------- +bool Registry::Open(const char *toplevel, + const char *subkey, int readonly) +{ + bool res = false; + if ( m_Locked ) + { + return 0; + } + if ( m_Opened ) + { + if ( !this->Close() ) + { + return false; + } + } + if ( !toplevel || !*toplevel ) + { + kwsys_ios::cerr << "Registry::Opened() Toplevel not defined" << kwsys_ios::endl; + return false; + } + + if ( isspace(toplevel[0]) || + isspace(toplevel[strlen(toplevel)-1]) ) + { + kwsys_ios::cerr << "Toplevel has to start with letter or number and end" + " with one" << kwsys_ios::endl; + return 0; + } + + res = this->Helper->Open(toplevel, subkey, readonly); + if ( readonly != Registry::READONLY ) + { + m_Locked = true; + } + + if ( res ) + { + m_Opened = true; + this->Helper->SetTopLevel(toplevel); + } + return res; +} + +//---------------------------------------------------------------------------- +bool Registry::Close() +{ + bool res = false; + if ( m_Opened ) + { + res = this->Helper->Close(); + } + + if ( res ) + { + m_Opened = false; + m_Locked = false; + this->Helper->SetChanged(false); + } + return res; +} + +//---------------------------------------------------------------------------- +bool Registry::ReadValue(const char *subkey, + const char *key, + char *value) +{ + *value = 0; + bool res = true; + bool open = false; + if ( ! value ) + { + return false; + } + if ( !m_Opened ) + { + if ( !this->Open(this->GetTopLevel(), subkey, + Registry::READONLY) ) + { + return false; + } + open = true; + } + res = this->Helper->ReadValue(key, value); + + if ( open ) + { + if ( !this->Close() ) + { + res = false; + } + } + return res; +} + +//---------------------------------------------------------------------------- +bool Registry::DeleteKey(const char *subkey, const char *key) +{ + bool res = true; + bool open = false; + if ( !m_Opened ) + { + if ( !this->Open(this->GetTopLevel(), subkey, + Registry::READWRITE) ) + { + return false; + } + open = true; + } + + res = this->Helper->DeleteKey(key); + if ( res ) + { + this->Helper->SetChanged(true); + } + + if ( open ) + { + if ( !this->Close() ) + { + res = false; + } + } + return res; +} + +//---------------------------------------------------------------------------- +bool Registry::DeleteValue(const char *subkey, const char *key) +{ + bool res = true; + bool open = false; + if ( !m_Opened ) + { + if ( !this->Open(this->GetTopLevel(), subkey, + Registry::READWRITE) ) + { + return false; + } + open = true; + } + + res = this->Helper->DeleteValue(key); + if ( res ) + { + this->Helper->SetChanged(true); + } + + if ( open ) + { + if ( !this->Close() ) + { + res = false; + } + } + return res; +} + +//---------------------------------------------------------------------------- +bool Registry::SetValue(const char *subkey, const char *key, + const char *value) +{ + bool res = true; + bool open = false; + if ( !m_Opened ) + { + if ( !this->Open(this->GetTopLevel(), subkey, + Registry::READWRITE) ) + { + return false; + } + open = true; + } + + res = this->Helper->SetValue( key, value ); + if ( res ) + { + this->Helper->SetChanged(true); + } + + if ( open ) + { + if ( !this->Close() ) + { + res = false; + } + } + return res; +} + +//---------------------------------------------------------------------------- +const char* Registry::GetTopLevel() +{ + return this->Helper->GetTopLevel(); +} + +//---------------------------------------------------------------------------- +void Registry::SetTopLevel(const char* tl) +{ + this->Helper->SetTopLevel(tl); +} + +//---------------------------------------------------------------------------- +void RegistryHelper::SetTopLevel(const char* tl) +{ + if ( tl ) + { + m_TopLevel = tl; + } + else + { + m_TopLevel = ""; + } +} + +//---------------------------------------------------------------------------- +RegistryHelper::RegistryHelper(Registry::RegistryType registryType) +{ + m_Changed = false; + m_TopLevel = ""; + m_SubKey = ""; + m_SubKeySpecified = false; + m_Empty = true; + m_RegistryType = registryType; +} + +//---------------------------------------------------------------------------- +RegistryHelper::~RegistryHelper() +{ +} + + +//---------------------------------------------------------------------------- +bool RegistryHelper::Open(const char *toplevel, const char *subkey, + int readonly) +{ +#ifdef WIN32 + if ( m_RegistryType == Registry::RegistryType::WIN32) + { + HKEY scope = HKEY_CURRENT_USER; + if ( this->GetGlobalScope() ) + { + scope = HKEY_LOCAL_MACHINE; + } + int res = 0; + ostrstream str; + DWORD dwDummy; + str << "Software\\Kitware\\" << toplevel << "\\" << subkey << ends; + if ( readonly == vtkKWRegistryUtilities::READONLY ) + { + res = ( RegOpenKeyEx(scope, str.str(), + 0, KEY_READ, &this->HKey) == ERROR_SUCCESS ); + } + else + { + res = ( RegCreateKeyEx(scope, str.str(), + 0, "", REG_OPTION_NON_VOLATILE, KEY_READ|KEY_WRITE, + NULL, &this->HKey, &dwDummy) == ERROR_SUCCESS ); + } + str.rdbuf()->freeze(0); + return res; + } +#endif + if ( m_RegistryType == Registry::UNIX_REGISTRY ) + { + int res = 0; + int cc; + kwsys_ios::ostringstream str; + if ( !getenv("HOME") ) + { + return 0; + } + str << getenv("HOME") << "/." << toplevel << "rc"; + if ( readonly == Registry::READWRITE ) + { + kwsys_ios::ofstream ofs( str.str().c_str(), kwsys_ios::ios::out|kwsys_ios::ios::app ); + if ( ofs.fail() ) + { + return 0; + } + ofs.close(); + } + + kwsys_ios::ifstream *ifs = new kwsys_ios::ifstream(str.str().c_str(), kwsys_ios::ios::in VTK_IOS_NOCREATE); + if ( !ifs ) + { + return 0; + } + if ( ifs->fail()) + { + delete ifs; + return 0; + } + + res = 1; + char buffer[BUFFER_SIZE]; + while( !ifs->fail() ) + { + int found = 0; + ifs->getline(buffer, BUFFER_SIZE); + if ( ifs->fail() || ifs->eof() ) + { + break; + } + char *line = this->Strip(buffer); + if ( *line == '#' || *line == 0 ) + { + // Comment + continue; + } + int linelen = static_cast(strlen(line)); + for ( cc = 0; cc < linelen; cc++ ) + { + if ( line[cc] == '=' ) + { + char *key = new char[ cc+1 ]; + strncpy( key, line, cc ); + key[cc] = 0; + char *value = line + cc + 1; + char *nkey = this->Strip(key); + char *nvalue = this->Strip(value); + this->EntriesMap[nkey] = nvalue; + m_Empty = 0; + delete [] key; + found = 1; + break; + } + } + } + ifs->close(); + this->SetSubKey( subkey ); + delete ifs; + return res; + } +} + +//---------------------------------------------------------------------------- +bool RegistryHelper::Close() +{ +#ifdef WIN32 + int res; + res = ( RegCloseKey(this->HKey) == ERROR_SUCCESS ); + return res; +#else + int res = 0; + if ( !m_Changed ) + { + this->EntriesMap.erase( + this->EntriesMap.begin(), + this->EntriesMap.end()); + m_Empty = 1; + this->SetSubKey(0); + return 1; + } + + kwsys_ios::ostringstream str; + if ( !getenv("HOME") ) + { + return 0; + } + str << getenv("HOME") << "/." << this->GetTopLevel() << "rc"; + kwsys_ios::ofstream *ofs = new kwsys_ios::ofstream(str.str().c_str(), kwsys_ios::ios::out); + if ( !ofs ) + { + return 0; + } + if ( ofs->fail()) + { + delete ofs; + return 0; + } + *ofs << "# This file is automatically generated by the application" << kwsys_ios::endl + << "# If you change any lines or add new lines, note that all" << kwsys_ios::endl + << "# coments and empty lines will be deleted. Every line has" << kwsys_ios::endl + << "# to be in format: " << kwsys_ios::endl + << "# key = value" << kwsys_ios::endl + << "#" << kwsys_ios::endl; + + if ( !this->EntriesMap.empty() ) + { + RegistryHelper::StringToStringMap::iterator it; + for ( it = this->EntriesMap.begin(); + it != this->EntriesMap.end(); + ++ it ) + { + *ofs << it->first.c_str() << " = " << it->second.c_str()<< kwsys_ios::endl; + } + } + this->EntriesMap.erase( + this->EntriesMap.begin(), + this->EntriesMap.end()); + ofs->close(); + delete ofs; + res = 1; + this->SetSubKey(0); + m_Empty = 1; + return res; +#endif +} + +//---------------------------------------------------------------------------- +bool RegistryHelper::ReadValue(const char *skey, char *value) + +{ +#ifdef WIN32 + int res = 1; + DWORD dwType, dwSize; + dwType = REG_SZ; + dwSize = BUFFER_SIZE; + res = ( RegQueryValueEx(this->HKey, key, NULL, &dwType, + (BYTE *)value, &dwSize) == ERROR_SUCCESS ); + return res; +#else + int res = 0; + char *key = this->CreateKey( skey ); + if ( !key ) + { + return 0; + } + RegistryHelper::StringToStringMap::iterator it + = this->EntriesMap.find(key); + if ( it != this->EntriesMap.end() ) + { + strcpy(value, it->second.c_str()); + res = 1; + } + delete [] key; + return res; +#endif +} + +//---------------------------------------------------------------------------- +bool RegistryHelper::DeleteKey(const char* key) +{ +#ifdef WIN32 + int res = 1; + res = ( RegDeleteKey( this->HKey, key ) == ERROR_SUCCESS ); + return res; +#else + (void)key; + int res = 0; + return res; +#endif +} + +//---------------------------------------------------------------------------- +bool RegistryHelper::DeleteValue(const char *skey) +{ +#ifdef WIN32 + int res = 1; + res = ( RegDeleteValue( this->HKey, key ) == ERROR_SUCCESS ); + return res; +#else + char *key = this->CreateKey( skey ); + if ( !key ) + { + return 0; + } + this->EntriesMap.erase(key); + delete [] key; + return 1; +#endif +} + +//---------------------------------------------------------------------------- +bool RegistryHelper::SetValue(const char *skey, const char *value) +{ +#ifdef WIN32 + int res = 1; + DWORD len = (DWORD)(value ? strlen(value) : 0); + res = ( RegSetValueEx(this->HKey, key, 0, REG_SZ, + (CONST BYTE *)(const char *)value, + len+1) == ERROR_SUCCESS ); + return res; +#else + char *key = this->CreateKey( skey ); + if ( !key ) + { + return 0; + } + this->EntriesMap[key] = value; + delete [] key; + return 1; +#endif +} + +//---------------------------------------------------------------------------- +char *RegistryHelper::CreateKey( const char *key ) +{ +#ifdef WIN32 +#else + char *newkey; + if ( !m_SubKeySpecified || m_SubKey.empty() || !key ) + { + return 0; + } + int len = strlen(this->m_SubKey.c_str()) + strlen(key) + 1; + newkey = new char[ len+1 ] ; + ::sprintf(newkey, "%s\\%s", this->m_SubKey.c_str(), key); + return newkey; +#endif +} + +void RegistryHelper::SetSubKey(const char* sk) +{ + if ( !sk ) + { + m_SubKey = ""; + m_SubKeySpecified = false; + } + else + { + m_SubKey = sk; + m_SubKeySpecified = true; + } +} + +//---------------------------------------------------------------------------- +char *RegistryHelper::Strip(char *str) +{ + int cc; + int len; + char *nstr; + if ( !str ) + { + return NULL; + } + len = strlen(str); + nstr = str; + for( cc=0; cc=0; cc-- ) + { + if ( !isspace( nstr[cc] ) ) + { + nstr[cc+1] = 0; + break; + } + } + return nstr; +} + +} // namespace KWSYS_NAMESPACE diff --git a/Source/kwsys/Registry.hxx.in b/Source/kwsys/Registry.hxx.in new file mode 100644 index 000000000..408534abb --- /dev/null +++ b/Source/kwsys/Registry.hxx.in @@ -0,0 +1,110 @@ +/*========================================================================= + + Program: KWSys - Kitware System Library + Module: $RCSfile$ + + Copyright (c) Kitware, Inc., Insight Consortium. All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ +#ifndef @KWSYS_NAMESPACE@_Registry_hxx +#define @KWSYS_NAMESPACE@_Registry_hxx + +#include <@KWSYS_NAMESPACE@/Configure.h> + +#include <@KWSYS_NAMESPACE@/stl/string> + +namespace @KWSYS_NAMESPACE@ +{ + +class RegistryHelper; + +/** \class Registry + * \brief Portable registry class + * + * This class abstracts the storing of data that can be restored + * when the program executes again. On Win32 platform it is + * implemented using the registry and on unix as a file in + * the user's home directory. + */ +class @KWSYS_NAMESPACE@_EXPORT Registry +{ +public: + enum RegistryType + { +#ifdef WIN32 + WIN32_REGISTRY, +#endif + UNIX_REGISTRY + }; + +#ifdef WIN32 + Registry(RegistryType registryType = WIN32_REGISTRY); +#else + Registry(RegistryType registryType = UNIX_REGISTRY); +#endif + + virtual ~Registry(); + + //! Read a value from the registry. + bool ReadValue(const char *subkey, const char *key, char *value); + + //! Delete a key from the registry. + bool DeleteKey(const char *subkey, const char *key); + + //! Delete a value from a given key. + bool DeleteValue(const char *subkey, const char *key); + + //! Set value in a given key. + bool SetValue(const char *subkey, const char *key, + const char *value); + + //! Open the registry at toplevel/subkey. + bool Open(const char *toplevel, const char *subkey, + int readonly); + + //! Close the registry. + bool Close(); + + //! Read from local or global scope. On Windows this mean from local machine + // or local user. On unix this will read from $HOME/.Projectrc or + // /etc/Project + void GlobalScopeOn() { this->SetGlobalScope(1); } + void GlobalScopeOff() { this->SetGlobalScope(0); } + void SetGlobalScope(bool b) { m_GlobalScope = b; } + bool GetGlobalScope() { return m_GlobalScope; } + + // Set or get the toplevel registry key. + void SetTopLevel(const char* tl); + const char* GetTopLevel(); + + // Return true if registry opened + bool GetOpened() { return m_Opened; } + + // Should the registry be locked? + bool GetLocked() { return m_Locked; } + + enum { + READONLY, + READWRITE + }; + + // Return true if the character is space. + int IsSpace(char c); + +private: + RegistryHelper* Helper; + + bool m_Opened; + + bool m_Locked; + bool m_GlobalScope; +}; // End Class: Registry + +} // namespace @KWSYS_NAMESPACE@ + +#endif diff --git a/Source/kwsys/testFail.c b/Source/kwsys/testFail.c new file mode 100644 index 000000000..c33ca8ab0 --- /dev/null +++ b/Source/kwsys/testFail.c @@ -0,0 +1,7 @@ +#include + +int main(int argc, char* argv[]) +{ + printf("%s: This test intentionally fails\n", argv[0]); + return argc; +} diff --git a/Source/kwsys/testRegistry.cxx b/Source/kwsys/testRegistry.cxx new file mode 100644 index 000000000..4f304d849 --- /dev/null +++ b/Source/kwsys/testRegistry.cxx @@ -0,0 +1,94 @@ +/*========================================================================= + + Program: ParaView + Module: $RCSfile$ + + Copyright (c) Kitware, Inc. + All rights reserved. + See Copyright.txt or http://www.paraview.org/HTML/Copyright.html for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ +#include "kwsysPrivate.h" + +#include KWSYS_HEADER(Registry.hxx) +#include KWSYS_HEADER(ios/iostream) + +// Work-around CMake dependency scanning limitation. This must +// duplicate the above list of headers. +#if 0 +# include "Registry.hxx.in" +# include "kwsys_ios_iostream.h.in" +#endif + +#define IFT(x,res) if ( !x ) \ + { \ + res = 1; \ + kwsys_ios::cout << "Error in: " << #x << kwsys_ios::endl; \ + } +#define IFNT(x,res) if ( x ) \ + { \ + res = 1; \ + kwsys_ios::cout << "Error in: " << #x << kwsys_ios::endl; \ + } + +#define CHE(x,y,res) if ( strcmp(x,y) ) \ + { \ + res = 1; \ + kwsys_ios::cout << "Error, " << x << " != " << y << kwsys_ios::endl; \ + } + +int main(int, char**) +{ + int res = 0; + + kwsys::Registry reg; + reg.SetTopLevel("TestRegistry"); + + IFT(reg.SetValue("TestSubkey", "TestKey1", "Test Value 1"), res); + IFT(reg.SetValue("TestSubkey1", "TestKey2", "Test Value 2"), res); + IFT(reg.SetValue("TestSubkey", "TestKey3", "Test Value 3"), res); + IFT(reg.SetValue("TestSubkey2", "TestKey4", "Test Value 4"), res); + + char buffer[1024]; + IFT(reg.ReadValue("TestSubkey", "TestKey1", buffer), res); + CHE(buffer, "Test Value 1", res); + IFT(reg.ReadValue("TestSubkey1", "TestKey2", buffer), res); + CHE(buffer, "Test Value 2", res); + IFT(reg.ReadValue("TestSubkey", "TestKey3", buffer), res); + CHE(buffer, "Test Value 3", res); + IFT(reg.ReadValue("TestSubkey2", "TestKey4", buffer), res); + CHE(buffer, "Test Value 4", res); + + IFT(reg.SetValue("TestSubkey", "TestKey1", "New Test Value 1"), res); + IFT(reg.SetValue("TestSubkey1", "TestKey2", "New Test Value 2"), res); + IFT(reg.SetValue("TestSubkey", "TestKey3", "New Test Value 3"), res); + IFT(reg.SetValue("TestSubkey2", "TestKey4", "New Test Value 4"), res); + + IFT(reg.ReadValue("TestSubkey", "TestKey1", buffer), res); + CHE(buffer, "New Test Value 1", res); + IFT(reg.ReadValue("TestSubkey1", "TestKey2", buffer), res); + CHE(buffer, "New Test Value 2", res); + IFT(reg.ReadValue("TestSubkey", "TestKey3", buffer), res); + CHE(buffer, "New Test Value 3", res); + IFT(reg.ReadValue("TestSubkey2", "TestKey4", buffer), res); + CHE(buffer, "New Test Value 4", res); + + IFT( reg.DeleteValue("TestSubkey", "TestKey1"), res); + IFNT(reg.ReadValue( "TestSubkey", "TestKey1", buffer), res); + IFT( reg.DeleteValue("TestSubkey1", "TestKey2"), res); + IFNT(reg.ReadValue( "TestSubkey1", "TestKey2", buffer), res); + IFT( reg.DeleteValue("TestSubkey", "TestKey3"), res); + IFNT(reg.ReadValue( "TestSubkey", "TestKey3", buffer), res); + IFT( reg.DeleteValue("TestSubkey2", "TestKey4"), res); + IFNT(reg.ReadValue( "TestSubkey2", "TestKey5", buffer), res); + + if ( res ) + { + kwsys_ios::cout << "Test failed" << kwsys_ios::endl; + } + return res; +}