summaryrefslogtreecommitdiff
path: root/plugins/Dbx_tree/src/Settings.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/Dbx_tree/src/Settings.cpp')
-rw-r--r--plugins/Dbx_tree/src/Settings.cpp1479
1 files changed, 1479 insertions, 0 deletions
diff --git a/plugins/Dbx_tree/src/Settings.cpp b/plugins/Dbx_tree/src/Settings.cpp
new file mode 100644
index 0000000000..b4ba799c55
--- /dev/null
+++ b/plugins/Dbx_tree/src/Settings.cpp
@@ -0,0 +1,1479 @@
+/*
+
+dbx_tree: tree database driver for Miranda IM
+
+Copyright 2007-2010 Michael "Protogenes" Kunz,
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+
+#include "Settings.h"
+#include <math.h> // floor function
+#include "Hash.h"
+#ifndef _MSC_VER
+#include "savestrings_gcc.h"
+#endif
+
+TDBTSettingHandle CSettingsTree::_FindSetting(const uint32_t Hash, const char * Name, const uint32_t Length)
+{
+ TSettingKey key = {0,0};
+ key.Hash = Hash;
+ iterator i = LowerBound(key);
+ uint16_t l;
+
+ TDBTSettingHandle res = 0;
+
+ char * str = NULL;
+
+ while ((res == 0) && (i) && (i->Hash == Hash))
+ {
+ l = Length;
+ if (m_Owner._ReadSettingName(m_BlockManager, i->Setting, l, str) &&
+ (strncmp(str, Name, Length) == 0))
+ {
+ res = i->Setting;
+ } else {
+ ++i;
+ }
+ }
+
+ if (str)
+ free(str);
+
+ return res;
+}
+
+bool CSettingsTree::_DeleteSetting(const uint32_t Hash, const TDBTSettingHandle hSetting)
+{
+ TSettingKey key = {0,0};
+ key.Hash = Hash;
+ iterator i = LowerBound(key);
+
+ while ((i) && (i->Hash == Hash) && (i->Setting != hSetting))
+ ++i;
+
+ if ((i) && (i->Hash == Hash))
+ {
+ Delete(*i);
+ return true;
+ }
+
+ return false;
+}
+
+bool CSettingsTree::_AddSetting(const uint32_t Hash, const TDBTSettingHandle hSetting)
+{
+ TSettingKey key;
+ key.Hash = Hash;
+ key.Setting = hSetting;
+ Insert(key);
+ return true;
+}
+
+CSettings::CSettings(
+ CBlockManager & BlockManagerSet,
+ CBlockManager & BlockManagerPri,
+ CSettingsTree::TNodeRef SettingsRoot,
+ CEntities & Entities
+)
+: m_BlockManagerSet(BlockManagerSet),
+ m_BlockManagerPri(BlockManagerPri),
+ m_Entities(Entities),
+ m_SettingsMap(),
+ m_sigRootChanged(),
+ m_Modules()
+{
+ CSettingsTree * settree = new CSettingsTree(*this, m_BlockManagerSet, SettingsRoot, 0);
+
+ settree->sigRootChanged().connect(this, &CSettings::onRootChanged);
+ m_SettingsMap.insert(std::make_pair(0, settree));
+
+ m_Entities._sigDeleteSettings().connect(this, &CSettings::onDeleteSettings);
+ m_Entities._sigMergeSettings().connect (this, &CSettings::onMergeSettings);
+
+ _LoadModules();
+ _EnsureModuleExists("$Modules");
+}
+
+CSettings::~CSettings()
+{
+ TSettingsTreeMap::iterator it = m_SettingsMap.begin();
+
+ while (it != m_SettingsMap.end())
+ {
+ delete it->second;
+ ++it;
+ }
+
+ TModulesMap::iterator it2 = m_Modules.begin();
+ while (it2 != m_Modules.end())
+ {
+ if (it2->second)
+ delete [] it2->second;
+ ++it2;
+ }
+}
+
+
+CSettingsTree * CSettings::getSettingsTree(TDBTEntityHandle hEntity)
+{
+ TSettingsTreeMap::iterator i = m_SettingsMap.find(hEntity);
+ if (i != m_SettingsMap.end())
+ return i->second;
+
+ uint32_t root = m_Entities._getSettingsRoot(hEntity);
+ if (root == DBT_INVALIDPARAM)
+ return NULL;
+
+ CSettingsTree * tree = new CSettingsTree(*this, m_BlockManagerPri, root, hEntity);
+ tree->sigRootChanged().connect(this, &CSettings::onRootChanged);
+ m_SettingsMap.insert(std::make_pair(hEntity, tree));
+
+ return tree;
+}
+
+// TODO check if we need to copy the name or if we can just use the cache
+inline bool CSettings::_ReadSettingName(CBlockManager & BlockManager, TDBTSettingHandle Setting, uint16_t & NameLength, char *& NameBuf)
+{
+ uint32_t sig = cSettingSignature;
+ uint32_t size = 0;
+
+ TSetting * setting = BlockManager.ReadBlock<TSetting>(Setting, size, sig);
+ if (!setting)
+ return false;
+
+ if ((NameLength != 0) && (NameLength != setting->NameLength))
+ return false;
+
+ NameLength = setting->NameLength;
+ NameBuf = (char*) realloc(NameBuf, NameLength + 1);
+
+ memcpy(NameBuf, setting + 1, NameLength + 1);
+ NameBuf[NameLength] = 0;
+
+ return true;
+}
+
+void CSettings::_EnsureModuleExists(char * Module)
+{
+ if ((Module == NULL) || (*Module == 0))
+ return;
+
+ char * e = strchr(Module, '/');
+ if (e)
+ *e = 0;
+
+ TModulesMap::iterator i = m_Modules.find(*((uint16_t*)Module));
+ while ((i != m_Modules.end()) && (i->first == *((uint16_t*)Module)) && (strcmp(i->second, Module) != 0))
+ {
+ ++i;
+ }
+
+ if ((i == m_Modules.end()) || (i->first != *reinterpret_cast<uint16_t*>(Module)))
+ {
+ size_t l = strlen(Module);
+ char * tmp = new char [l + 1];
+ memcpy(tmp, Module, l + 1);
+ m_Modules.insert(std::make_pair(*reinterpret_cast<uint16_t*>(tmp), tmp));
+
+ char namebuf[512];
+ strcpy_s(namebuf, "$Modules/");
+ strcat_s(namebuf, Module);
+
+ TDBTSettingDescriptor desc = {0,0,0,0,0,0,0,0};
+ desc.cbSize = sizeof(desc);
+ desc.pszSettingName = namebuf;
+
+ TDBTSetting set = {0,0,0,0};
+ set.cbSize = sizeof(set);
+ set.Descriptor = &desc;
+ set.Type = DBT_ST_DWORD;
+
+ WriteSetting(set, cSettingsFileFlag);
+ }
+
+ if (e)
+ *e = '/';
+}
+
+void CSettings::_LoadModules()
+{
+ TDBTSettingDescriptor desc = {0,0,0,0,0,0,0,0};
+ desc.cbSize = sizeof(desc);
+
+ TDBTSettingIterFilter f = {0,0,0,0,0,0,0,0};
+ f.cbSize = sizeof(f);
+ f.Descriptor = &desc;
+ f.NameStart = "$Modules/";
+
+ TDBTSettingIterationHandle hiter = IterationInit(f);
+
+ if ((hiter != 0) && (hiter != DBT_INVALIDPARAM))
+ {
+ TDBTSettingHandle res = IterationNext(hiter);
+ while ((res != 0) && (res != DBT_INVALIDPARAM))
+ {
+ size_t l = strlen(desc.pszSettingName);
+ char * tmp = new char [l - 9 + 1];
+ memcpy(tmp, desc.pszSettingName + 9, l - 9 + 1);
+ m_Modules.insert(std::make_pair(*reinterpret_cast<uint16_t*>(tmp), tmp));
+ res = IterationNext(hiter);
+ }
+
+ IterationClose(hiter);
+ }
+}
+
+void CSettings::onRootChanged(void* SettingsTree, CSettingsTree::TNodeRef NewRoot)
+{
+ if (((CSettingsTree*)SettingsTree)->Entity() == 0)
+ m_sigRootChanged.emit(this, NewRoot);
+ else
+ m_Entities._setSettingsRoot(((CSettingsTree*)SettingsTree)->Entity(), NewRoot);
+}
+
+void CSettings::onDeleteSettingCallback(void * Tree, const TSettingKey & Key, uint32_t Param)
+{
+ if (Param == 0)
+ {
+ m_BlockManagerSet.DeleteBlock(Key.Setting);
+ } else {
+ m_BlockManagerPri.DeleteBlock(Key.Setting);
+ }
+}
+void CSettings::onDeleteSettings(CEntities * Entities, TDBTEntityHandle hEntity)
+{
+ CSettingsTree * tree = getSettingsTree(hEntity);
+
+ m_Entities._setSettingsRoot(hEntity, 0);
+
+ if (tree)
+ {
+ CSettingsTree::TDeleteCallback callback;
+ callback.connect(this, &CSettings::onDeleteSettingCallback);
+
+ tree->DeleteTree(&callback, hEntity);
+
+ TSettingsTreeMap::iterator i = m_SettingsMap.find(hEntity);
+ delete i->second; // tree
+ m_SettingsMap.erase(i);
+ }
+}
+
+
+typedef struct TSettingMergeHelper
+{
+ TDBTEntityHandle Source;
+ TDBTEntityHandle Dest;
+ CSettingsTree * SourceTree;
+
+} TSettingMergeHelper, *PSettingMergeHelper;
+
+
+void CSettings::onMergeSettingCallback(void * Tree, const TSettingKey & Key,uint32_t Param)
+{
+ PSettingMergeHelper hlp = (PSettingMergeHelper)Param;
+
+ uint16_t dnl = 0;
+ char * dnb = NULL;
+
+ _ReadSettingName(m_BlockManagerPri, Key.Setting, dnl, dnb);
+
+ TSettingKey k = {0,0};
+ k.Hash = Key.Hash;
+
+ CSettingsTree::iterator i = hlp->SourceTree->LowerBound(k);
+ TDBTSettingHandle res = 0;
+ while ((res == 0) && i && (i->Hash == Key.Hash))
+ {
+ uint16_t snl = dnl;
+ char * snb = NULL;
+
+ if (_ReadSettingName(m_BlockManagerPri, i->Setting, snl, snb)
+ && (strcmp(dnb, snb) == 0)) // found it
+ {
+ res = i->Setting;
+ }
+ }
+
+ if (res == 0)
+ {
+ hlp->SourceTree->Insert(Key);
+ } else {
+ hlp->SourceTree->Delete(*i);
+ hlp->SourceTree->Insert(Key);
+ m_BlockManagerPri.DeleteBlock(res);
+ }
+}
+
+void CSettings::onMergeSettings(CEntities * Entities, TDBTEntityHandle Source, TDBTEntityHandle Dest)
+{
+
+ if ((Source != 0) && (Dest != 0))
+ {
+ LOG(logERROR, _T("Cannot Merge with global settings!\nSource %d Dest %d"), Source, Dest);
+ return;
+ }
+
+ CSettingsTree * stree = getSettingsTree(Source);
+ CSettingsTree * dtree = getSettingsTree(Dest);
+
+ if (stree && dtree)
+ {
+ m_Entities._setSettingsRoot(Source, 0);
+
+ stree->Entity(Dest);
+ m_Entities._setSettingsRoot(Dest, stree->getRoot());
+
+ TSettingKey key = {0,0};
+ CSettingsTree::iterator it = stree->LowerBound(key);
+
+ while (it) // transfer all source settings to new Entity
+ {
+ uint32_t sig = cSettingSignature;
+ uint32_t size = 0;
+ TSetting * tmp = m_BlockManagerPri.ReadBlock<TSetting>(it->Setting, size, sig);
+ if (tmp)
+ {
+ tmp->Entity = Dest;
+ m_BlockManagerPri.UpdateBlock(it->Setting);
+ }
+ ++it;
+ }
+
+ // merge the dest tree into the source tree. override existing items
+ // do it this way, because source tree should be much larger
+ TSettingMergeHelper hlp;
+ hlp.Source = Source;
+ hlp.Dest = Dest;
+ hlp.SourceTree = stree;
+
+ CSettingsTree::TDeleteCallback callback;
+ callback.connect(this, &CSettings::onMergeSettingCallback);
+ dtree->DeleteTree(&callback, (uint32_t)&hlp);
+
+ TSettingsTreeMap::iterator i = m_SettingsMap.find(Dest);
+ delete i->second; // dtree
+ i->second = stree;
+ m_SettingsMap.erase(Source);
+
+ }
+}
+
+
+
+
+TDBTSettingHandle CSettings::FindSetting(TDBTSettingDescriptor & Descriptor)
+{
+ if (Descriptor.Flags & DBT_SDF_FoundValid)
+ return Descriptor.FoundHandle;
+
+ uint32_t namelength = static_cast<uint32_t>( strlen(Descriptor.pszSettingName));
+ uint32_t namehash;
+
+ if (Descriptor.Flags & DBT_SDF_HashValid)
+ {
+ namehash = Descriptor.Hash;
+ } else {
+ namehash = Hash(Descriptor.pszSettingName, namelength);
+ Descriptor.Hash = namehash;
+ Descriptor.Flags = Descriptor.Flags | DBT_SDF_HashValid;
+ }
+
+ Descriptor.Flags = Descriptor.Flags & ~DBT_SDF_FoundValid;
+
+ CSettingsTree * tree;
+ TDBTSettingHandle res = 0;
+ CBlockManager * file = &m_BlockManagerPri;
+ if (Descriptor.Entity == 0)
+ file = &m_BlockManagerSet;
+
+ CBlockManager::ReadTransaction trans(*file);
+
+ if ((Descriptor.Entity == 0) || (Descriptor.Options == 0))
+ {
+ tree = getSettingsTree(Descriptor.Entity);
+ if (tree == NULL)
+ return DBT_INVALIDPARAM;
+
+ res = tree->_FindSetting(namehash, Descriptor.pszSettingName, namelength);
+
+ if (res)
+ {
+ Descriptor.FoundInEntity = Descriptor.Entity;
+ Descriptor.FoundHandle = res;
+ Descriptor.Flags = Descriptor.Flags | DBT_SDF_FoundValid;
+ }
+
+ if (Descriptor.Entity == 0)
+ res = res | cSettingsFileFlag;
+
+ return res;
+ }
+
+ uint32_t cf = m_Entities.getFlags(Descriptor.Entity);
+ if (cf == DBT_INVALIDPARAM)
+ return DBT_INVALIDPARAM;
+
+ // search the setting
+ res = 0;
+
+ TDBTEntityIterFilter f;
+ f.cbSize = sizeof(f);
+ if (cf & DBT_NF_IsGroup)
+ {
+ f.fDontHasFlags = 0;
+ f.fHasFlags = DBT_NF_IsGroup;
+ } else {
+ f.fDontHasFlags = DBT_NF_IsGroup;
+ f.fHasFlags = 0;
+ }
+ f.Options = Descriptor.Options;
+
+ TDBTEntityIterationHandle i = m_Entities.IterationInit(f, Descriptor.Entity);
+ if ((i == DBT_INVALIDPARAM) || (i == 0))
+ return DBT_INVALIDPARAM;
+
+ TDBTEntityHandle e = m_Entities.IterationNext(i);
+ TDBTEntityHandle found = 0;
+ while ((res == 0) && (e != 0))
+ {
+ tree = getSettingsTree(e);
+ if (tree)
+ {
+ res = tree->_FindSetting(namehash, Descriptor.pszSettingName, namelength);
+ found = e;
+ }
+
+ e = m_Entities.IterationNext(i);
+ }
+
+ m_Entities.IterationClose(i);
+
+ if (res)
+ {
+ Descriptor.FoundInEntity = found;
+ Descriptor.FoundHandle = res;
+ Descriptor.Flags = Descriptor.Flags | DBT_SDF_FoundValid;
+ }
+
+ return res;
+}
+
+unsigned int CSettings::DeleteSetting(TDBTSettingDescriptor & Descriptor)
+{
+ TDBTSettingHandle hset = FindSetting(Descriptor);
+ if ((hset == 0) || (hset == DBT_INVALIDPARAM))
+ {
+ return DBT_INVALIDPARAM;
+ }
+
+ unsigned int res = 0;
+ if ((Descriptor.Flags & DBT_SDF_FoundValid) && (Descriptor.Flags & DBT_SDF_HashValid))
+ {
+ CBlockManager * file = &m_BlockManagerPri;
+
+ if (Descriptor.FoundInEntity == 0)
+ {
+ file = &m_BlockManagerSet;
+ hset = hset & ~cSettingsFileFlag;
+ }
+
+ CBlockManager::WriteTransaction trans(*file);
+
+ uint32_t sig = cSettingSignature;
+ uint32_t size = 0;
+ TSetting * setting = file->ReadBlock<TSetting>(hset, size, sig);
+ if (setting && (setting->Entity == Descriptor.FoundInEntity))
+ {
+ CSettingsTree * tree = getSettingsTree(setting->Entity);
+ if (tree)
+ {
+ tree->_DeleteSetting(Descriptor.Hash, hset);
+ file->DeleteBlock(hset);
+ }
+ }
+
+ } else {
+ res = DeleteSetting(hset);
+ }
+
+ return res;
+}
+unsigned int CSettings::DeleteSetting(TDBTSettingHandle hSetting)
+{
+ CBlockManager * file = &m_BlockManagerPri;
+
+ if (hSetting & cSettingsFileFlag)
+ {
+ file = &m_BlockManagerSet;
+ hSetting = hSetting & ~cSettingsFileFlag;
+ }
+
+ CBlockManager::WriteTransaction trans(*file);
+
+ uint32_t sig = cSettingSignature;
+ uint32_t size = 0;
+ TSetting * setting = file->ReadBlock<TSetting>(hSetting, size, sig);
+
+ if (!setting)
+ return DBT_INVALIDPARAM;
+
+ CSettingsTree * tree = getSettingsTree(setting->Entity);
+ if (tree == NULL)
+ return DBT_INVALIDPARAM;
+
+ char * str = reinterpret_cast<char*>(setting + 1);
+ tree->_DeleteSetting(Hash(str, setting->NameLength), hSetting);
+
+ file->DeleteBlock(hSetting);
+
+ return 0;
+}
+TDBTSettingHandle CSettings::WriteSetting(TDBTSetting & Setting)
+{
+ CBlockManager * file = &m_BlockManagerPri;
+ if (Setting.Descriptor->Entity == 0)
+ file = &m_BlockManagerSet;
+
+ CBlockManager::WriteTransaction trans(*file);
+
+ TDBTSettingHandle hset = FindSetting(*Setting.Descriptor);
+ if (hset == DBT_INVALIDPARAM)
+ return hset;
+
+ hset = WriteSetting(Setting, hset);
+
+ return hset;
+}
+
+TDBTSettingHandle CSettings::WriteSetting(TDBTSetting & Setting, TDBTSettingHandle hSetting)
+{
+ uint32_t sig = cSettingSignature;
+ uint32_t size = 0;
+ TSetting * setting = NULL;
+
+ if (!hSetting && !(Setting.Descriptor && Setting.Descriptor->Entity))
+ return DBT_INVALIDPARAM;
+
+ CBlockManager * file = &m_BlockManagerPri;
+ bool fileflag = false;
+
+ if (hSetting & cSettingsFileFlag)
+ {
+ file = &m_BlockManagerSet;
+ hSetting = hSetting & ~cSettingsFileFlag;
+ fileflag = true;
+ }
+
+ CSettingsTree * tree = NULL;
+
+ if (hSetting == 0)
+ {
+ if (Setting.Descriptor->Entity == 0)
+ {
+ file = &m_BlockManagerSet;
+ fileflag = true;
+ }
+
+ CBlockManager::WriteTransaction trans(*file);
+
+ if ((Setting.Descriptor) && (Setting.Descriptor->pszSettingName)) // setting needs a name
+ {
+ tree = getSettingsTree(Setting.Descriptor->Entity);
+ _EnsureModuleExists(Setting.Descriptor->pszSettingName);
+ }
+
+ } else {
+ CBlockManager::WriteTransaction trans(*file);
+
+ setting = file->ReadBlock<TSetting>(hSetting, size, sig);
+
+ if (setting) // check if hSetting is valid
+ tree = getSettingsTree(setting->Entity);
+ }
+
+ if (tree == NULL)
+ return DBT_INVALIDPARAM;
+
+ uint32_t blobsize = 0;
+
+ if (Setting.Type & DBT_STF_VariableLength)
+ {
+ switch (Setting.Type)
+ {
+ case DBT_ST_ANSI: case DBT_ST_UTF8:
+ {
+ if (Setting.Value.Length == 0)
+ blobsize = static_cast<uint32_t>(strlen(Setting.Value.pAnsi) + 1);
+ else
+ blobsize = Setting.Value.Length;
+ } break;
+ case DBT_ST_WCHAR:
+ {
+ if (Setting.Value.Length == 0)
+ blobsize = sizeof(wchar_t) * static_cast<uint32_t>(wcslen(Setting.Value.pWide) + 1);
+ else
+ blobsize = sizeof(wchar_t) * (Setting.Value.Length);
+ } break;
+ default:
+ blobsize = Setting.Value.Length;
+ break;
+ }
+ }
+
+ size = sizeof(TSetting) + static_cast<uint32_t>(strlen(Setting.Descriptor->pszSettingName)) + 1 + blobsize;
+
+ if (hSetting == 0) // create new setting
+ {
+ setting = file->CreateBlock<TSetting>(hSetting, cSettingSignature, size);
+
+ setting->Entity = Setting.Descriptor->Entity;
+ setting->Flags = 0;
+ setting->AllocSize = blobsize;
+
+ if (Setting.Descriptor && (Setting.Descriptor->Flags & DBT_SDF_HashValid))
+ {
+ tree->_AddSetting(Setting.Descriptor->Hash, hSetting);
+ } else {
+ tree->_AddSetting(Hash(Setting.Descriptor->pszSettingName, static_cast<uint32_t>(strlen(Setting.Descriptor->pszSettingName))), hSetting);
+ }
+
+ } else {
+ uint32_t tmp = 0;
+ setting = file->ReadBlock<TSetting>(hSetting, tmp, sig);
+
+ if (((Setting.Type & DBT_STF_VariableLength) == 0) && (setting->Type & DBT_STF_VariableLength))
+ { // shrink setting (variable size->fixed size)
+ file->ResizeBlock(hSetting, setting, size);
+ }
+
+ if ((Setting.Type & DBT_STF_VariableLength) && ((setting->Type & DBT_STF_VariableLength) == 0))
+ { // trick it
+ setting->AllocSize = 0;
+ }
+ }
+
+ setting->Type = Setting.Type;
+ setting->NameLength = static_cast<uint32_t>(strlen(Setting.Descriptor->pszSettingName));
+ memcpy(setting + 1, Setting.Descriptor->pszSettingName, setting->NameLength + 1);
+
+ if (Setting.Type & DBT_STF_VariableLength)
+ {
+ setting->AllocSize = file->ResizeBlock(hSetting, setting, size) -
+ (sizeof(TSetting) + setting->NameLength + 1);
+
+ setting->BlobLength = blobsize;
+
+ memcpy(reinterpret_cast<uint8_t*>(setting + 1) + setting->NameLength + 1, Setting.Value.pBlob, blobsize);
+ } else {
+ memset(&(setting->Value), 0, sizeof(setting->Value));
+ switch (Setting.Type)
+ {
+ case DBT_ST_BOOL:
+ setting->Value.Bool = Setting.Value.Bool; break;
+ case DBT_ST_BYTE: case DBT_ST_CHAR:
+ setting->Value.Byte = Setting.Value.Byte; break;
+ case DBT_ST_SHORT: case DBT_ST_WORD:
+ setting->Value.Short = Setting.Value.Short; break;
+ case DBT_ST_INT: case DBT_ST_DWORD:
+ setting->Value.Int = Setting.Value.Int; break;
+ default:
+ setting->Value.QWord = Setting.Value.QWord; break;
+ }
+ }
+
+ file->UpdateBlock(hSetting);
+
+ if (fileflag)
+ hSetting = hSetting | cSettingsFileFlag;
+
+ return hSetting;
+}
+
+unsigned int CSettings::ReadSetting(TDBTSetting & Setting)
+{
+ CBlockManager * file = &m_BlockManagerPri;
+ if (Setting.Descriptor->Entity == 0)
+ file = &m_BlockManagerSet;
+
+ CBlockManager::ReadTransaction trans(*file);
+
+ TDBTSettingHandle hset = FindSetting(*Setting.Descriptor);
+ if ((hset == 0) || (hset == DBT_INVALIDPARAM))
+ return DBT_INVALIDPARAM;
+
+ PDBTSettingDescriptor back = Setting.Descriptor;
+ Setting.Descriptor = NULL;
+
+ if (ReadSetting(Setting, hset) == DBT_INVALIDPARAM)
+ hset = DBT_INVALIDPARAM;
+
+ Setting.Descriptor = back;
+
+ return hset;
+}
+
+unsigned int CSettings::ReadSetting(TDBTSetting & Setting, TDBTSettingHandle hSetting)
+{
+ CBlockManager * file = &m_BlockManagerPri;
+
+ if (hSetting & cSettingsFileFlag)
+ {
+ file = &m_BlockManagerSet;
+ hSetting = hSetting & ~cSettingsFileFlag;
+ }
+
+ uint32_t sig = cSettingSignature;
+ uint32_t size = 0;
+
+ if (hSetting == 0)
+ return DBT_INVALIDPARAM;
+
+ CBlockManager::ReadTransaction trans(*file);
+
+ TSetting * setting = file->ReadBlock<TSetting>(hSetting, size, sig);
+
+ if (!setting)
+ return DBT_INVALIDPARAM;
+
+ uint8_t* str = reinterpret_cast<uint8_t*>(setting + 1) + setting->NameLength + 1;
+
+ if (Setting.Type == 0)
+ {
+ Setting.Type = setting->Type;
+ if (setting->Type & DBT_STF_VariableLength)
+ {
+ Setting.Value.Length = setting->BlobLength;
+ switch (setting->Type)
+ {
+ case DBT_ST_WCHAR:
+ {
+ Setting.Value.Length = setting->BlobLength / sizeof(wchar_t);
+ Setting.Value.pWide = (wchar_t*) mir_realloc(Setting.Value.pWide, sizeof(wchar_t) * Setting.Value.Length);
+ memcpy(Setting.Value.pWide, str, setting->BlobLength);
+ Setting.Value.pWide[Setting.Value.Length - 1] = 0;
+
+ } break;
+ case DBT_ST_ANSI: case DBT_ST_UTF8:
+ {
+ Setting.Value.Length = setting->BlobLength;
+ Setting.Value.pAnsi = (char *) mir_realloc(Setting.Value.pAnsi, setting->BlobLength);
+ memcpy(Setting.Value.pAnsi, str, setting->BlobLength);
+ Setting.Value.pAnsi[Setting.Value.Length - 1] = 0;
+
+ } break;
+ default:
+ {
+ Setting.Value.Length = setting->BlobLength;
+ Setting.Value.pBlob = (uint8_t *) mir_realloc(Setting.Value.pBlob, setting->BlobLength);
+ memcpy(Setting.Value.pBlob, str, setting->BlobLength);
+ } break;
+ }
+ } else {
+ Setting.Value.QWord = setting->Value.QWord;
+ }
+ } else {
+ switch (setting->Type)
+ {
+ case DBT_ST_BYTE: case DBT_ST_WORD: case DBT_ST_DWORD: case DBT_ST_QWORD:
+ {
+ switch (Setting.Type)
+ {
+ case DBT_ST_BYTE: Setting.Value.Byte = (uint8_t) setting->Value.QWord; break;
+ case DBT_ST_WORD: Setting.Value.Word = (uint16_t) setting->Value.QWord; break;
+ case DBT_ST_DWORD: Setting.Value.DWord = (uint32_t) setting->Value.QWord; break;
+ case DBT_ST_QWORD: Setting.Value.QWord = (uint64_t) setting->Value.QWord; break;
+ case DBT_ST_CHAR: Setting.Value.Char = ( int8_t) setting->Value.QWord; break;
+ case DBT_ST_SHORT: Setting.Value.Short = ( int16_t) setting->Value.QWord; break;
+ case DBT_ST_INT: Setting.Value.Int = ( int32_t) setting->Value.QWord; break;
+ case DBT_ST_INT64: Setting.Value.Int64 = ( int64_t) setting->Value.QWord; break;
+ case DBT_ST_BOOL: Setting.Value.Bool = setting->Value.QWord != 0; break;
+
+ case DBT_ST_ANSI: case DBT_ST_UTF8:
+ {
+ char buffer[24];
+ buffer[0] = 0;
+ Setting.Value.Length = 1 + sprintf_s(buffer, "%llu", setting->Value.QWord);
+ Setting.Value.pAnsi = (char *) mir_realloc(Setting.Value.pAnsi, Setting.Value.Length);
+ memcpy(Setting.Value.pAnsi, buffer, Setting.Value.Length);
+
+ } break;
+ case DBT_ST_WCHAR:
+ {
+ wchar_t buffer[24];
+ buffer[0] = 0;
+ Setting.Value.Length = 1 + swprintf_s(buffer, L"%llu", setting->Value.QWord);
+ Setting.Value.pWide = (wchar_t *) mir_realloc(Setting.Value.pWide, Setting.Value.Length * sizeof(wchar_t));
+ memcpy(Setting.Value.pWide, buffer, Setting.Value.Length * sizeof(wchar_t));
+
+ } break;
+ case DBT_ST_BLOB:
+ {
+ Setting.Value.Length = 0;
+ switch (setting->Type)
+ {
+ case DBT_ST_BYTE: Setting.Value.Length = 1; break;
+ case DBT_ST_WORD: Setting.Value.Length = 2; break;
+ case DBT_ST_DWORD: Setting.Value.Length = 4; break;
+ case DBT_ST_QWORD: Setting.Value.Length = 8; break;
+ }
+
+ Setting.Value.pBlob = (uint8_t *) mir_realloc(Setting.Value.pBlob, Setting.Value.Length);
+ memcpy(Setting.Value.pBlob, &setting->Value, Setting.Value.Length);
+
+
+ } break;
+ }
+
+ } break;
+ case DBT_ST_CHAR: case DBT_ST_SHORT: case DBT_ST_INT: case DBT_ST_INT64:
+ {
+ int64_t val = 0;
+ switch (setting->Type)
+ {
+ case DBT_ST_CHAR: val = setting->Value.Char; break;
+ case DBT_ST_SHORT: val = setting->Value.Short; break;
+ case DBT_ST_INT: val = setting->Value.Int; break;
+ case DBT_ST_INT64: val = setting->Value.Int64; break;
+ }
+ switch (Setting.Type)
+ {
+ case DBT_ST_BYTE: Setting.Value.Byte = (uint8_t) val; break;
+ case DBT_ST_WORD: Setting.Value.Word = (uint16_t) val; break;
+ case DBT_ST_DWORD: Setting.Value.DWord = (uint32_t) val; break;
+ case DBT_ST_QWORD: Setting.Value.QWord = (uint64_t) val; break;
+ case DBT_ST_CHAR: Setting.Value.Char = ( int8_t) val; break;
+ case DBT_ST_SHORT: Setting.Value.Short = ( int16_t) val; break;
+ case DBT_ST_INT: Setting.Value.Int = ( int32_t) val; break;
+ case DBT_ST_INT64: Setting.Value.Int64 = ( int64_t) val; break;
+ case DBT_ST_BOOL: Setting.Value.Bool = val != 0; break;
+
+ case DBT_ST_ANSI: case DBT_ST_UTF8:
+ {
+ char buffer[24];
+ buffer[0] = 0;
+ Setting.Value.Length = 1 + sprintf_s(buffer, "%lli", val);
+ Setting.Value.pAnsi = (char *) mir_realloc(Setting.Value.pAnsi, Setting.Value.Length);
+ memcpy(Setting.Value.pAnsi, buffer, Setting.Value.Length);
+
+ } break;
+ case DBT_ST_WCHAR:
+ {
+ wchar_t buffer[24];
+ buffer[0] = 0;
+ Setting.Value.Length = 1 + swprintf_s(buffer, L"%lli", val);
+ Setting.Value.pWide = (wchar_t *) mir_realloc(Setting.Value.pWide, Setting.Value.Length * sizeof(wchar_t));
+ memcpy(Setting.Value.pWide, buffer, Setting.Value.Length * sizeof(wchar_t));
+
+ } break;
+ case DBT_ST_BLOB:
+ {
+ Setting.Value.Length = 0;
+ switch (setting->Type)
+ {
+ case DBT_ST_CHAR: Setting.Value.Length = 1; break;
+ case DBT_ST_SHORT: Setting.Value.Length = 2; break;
+ case DBT_ST_INT: Setting.Value.Length = 4; break;
+ case DBT_ST_INT64: Setting.Value.Length = 8; break;
+ }
+
+ Setting.Value.pBlob = (unsigned char *) mir_realloc(Setting.Value.pBlob, Setting.Value.Length);
+ memcpy(Setting.Value.pBlob, &setting->Value, Setting.Value.Length);
+
+ } break;
+ }
+
+ } break;
+ case DBT_ST_FLOAT: case DBT_ST_DOUBLE:
+ {
+ double val = 0;
+ if (setting->Type == DBT_ST_DOUBLE)
+ val = setting->Value.Double;
+ else
+ val = setting->Value.Float;
+
+ switch (Setting.Type)
+ {
+ case DBT_ST_BYTE: Setting.Value.Byte = (uint8_t) floor(val); break;
+ case DBT_ST_WORD: Setting.Value.Word = (uint16_t) floor(val); break;
+ case DBT_ST_DWORD: Setting.Value.DWord = (uint32_t) floor(val); break;
+ case DBT_ST_QWORD: Setting.Value.QWord = (uint64_t) floor(val); break;
+ case DBT_ST_CHAR: Setting.Value.Char = ( int8_t) floor(val); break;
+ case DBT_ST_SHORT: Setting.Value.Short = ( int16_t) floor(val); break;
+ case DBT_ST_INT: Setting.Value.Int = ( int32_t) floor(val); break;
+ case DBT_ST_INT64: Setting.Value.Int64 = ( int64_t) floor(val); break;
+ case DBT_ST_BOOL: Setting.Value.Bool = val != 0; break;
+
+ case DBT_ST_ANSI: case DBT_ST_UTF8:
+ {
+ char buffer[128];
+ buffer[0] = 0;
+ Setting.Value.Length = 1 + sprintf_s(buffer, "%lf", setting->Value.QWord);
+ Setting.Value.pAnsi = (char *) mir_realloc(Setting.Value.pAnsi, Setting.Value.Length);
+ memcpy(Setting.Value.pAnsi, buffer, Setting.Value.Length);
+ } break;
+ case DBT_ST_WCHAR:
+ {
+ wchar_t buffer[128];
+ buffer[0] = 0;
+ Setting.Value.Length = 1 + swprintf_s(buffer, L"%lf", setting->Value.QWord);
+ Setting.Value.pWide = (wchar_t *) mir_realloc(Setting.Value.pWide, Setting.Value.Length * sizeof(wchar_t));
+ memcpy(Setting.Value.pWide, buffer, Setting.Value.Length * sizeof(wchar_t));
+ } break;
+ case DBT_ST_BLOB:
+ {
+ Setting.Value.Length = 4;
+ if (setting->Type == DBT_ST_DOUBLE)
+ Setting.Value.Length = 8;
+
+ Setting.Value.pBlob = (uint8_t*) mir_realloc(Setting.Value.pBlob, Setting.Value.Length);
+ memcpy(Setting.Value.pBlob, &setting->Value, Setting.Value.Length);
+
+ } break;
+ }
+
+ } break;
+ case DBT_ST_BOOL:
+ {
+ switch (Setting.Type)
+ {
+ case DBT_ST_BYTE: case DBT_ST_WORD: case DBT_ST_DWORD: case DBT_ST_QWORD:
+ case DBT_ST_CHAR: case DBT_ST_SHORT: case DBT_ST_INT: case DBT_ST_INT64:
+ {
+ if (setting->Value.Bool)
+ Setting.Value.QWord = 1;
+ else
+ Setting.Value.QWord = 0;
+ } break;
+ case DBT_ST_FLOAT:
+ {
+ if (setting->Value.Bool)
+ Setting.Value.Float = 1;
+ else
+ Setting.Value.Float = 0;
+ } break;
+ case DBT_ST_DOUBLE:
+ {
+ if (setting->Value.Bool)
+ Setting.Value.Double = 1;
+ else
+ Setting.Value.Double = 0;
+ } break;
+ case DBT_ST_ANSI: case DBT_ST_UTF8:
+ {
+ char * buffer = "false";
+ Setting.Value.Length = 5;
+ if (setting->Value.Bool)
+ {
+ buffer = "true";
+ Setting.Value.Length = 4;
+ }
+
+ Setting.Value.pAnsi = (char *) mir_realloc(Setting.Value.pAnsi, Setting.Value.Length);
+ memcpy(Setting.Value.pAnsi, buffer, Setting.Value.Length);
+ } break;
+ case DBT_ST_WCHAR:
+ {
+ wchar_t * buffer = L"false";
+ Setting.Value.Length = 5;
+ if (setting->Value.Bool)
+ {
+ buffer = L"true";
+ Setting.Value.Length = 4;
+ }
+
+ Setting.Value.pWide = (wchar_t *) mir_realloc(Setting.Value.pWide, Setting.Value.Length * sizeof(wchar_t));
+ memcpy(Setting.Value.pWide, buffer, Setting.Value.Length * sizeof(wchar_t));
+ } break;
+ case DBT_ST_BLOB:
+ {
+ Setting.Value.pBlob = (uint8_t*) mir_realloc(Setting.Value.pBlob, sizeof(bool));
+ (*((bool*)Setting.Value.pBlob)) = setting->Value.Bool;
+ Setting.Value.Length = sizeof(bool);
+ } break;
+ }
+ } break;
+ case DBT_ST_ANSI:
+ {
+ str[setting->BlobLength - 1] = 0;
+
+ switch (Setting.Type)
+ {
+ case DBT_ST_BYTE: case DBT_ST_WORD: case DBT_ST_DWORD: case DBT_ST_QWORD: case DBT_ST_BOOL:
+ case DBT_ST_CHAR: case DBT_ST_SHORT: case DBT_ST_INT: case DBT_ST_INT64:
+ {
+ Setting.Value.QWord = 0;
+ } break;
+ case DBT_ST_ANSI:
+ {
+ Setting.Value.Length = setting->BlobLength;
+ Setting.Value.pAnsi = (char *) mir_realloc(Setting.Value.pAnsi, setting->BlobLength);
+ memcpy(Setting.Value.pAnsi, str, setting->BlobLength);
+ } break;
+ case DBT_ST_UTF8:
+ {
+ Setting.Value.pUTF8 = mir_utf8encode((char*)str);
+ Setting.Value.Length = static_cast<uint32_t>(strlen(Setting.Value.pUTF8) + 1);
+ } break;
+ case DBT_ST_WCHAR:
+ {
+ Setting.Value.pWide = mir_a2u((char*)str);
+ Setting.Value.Length = static_cast<uint32_t>(wcslen(Setting.Value.pWide) + 1);
+ } break;
+ case DBT_ST_BLOB:
+ {
+ Setting.Value.Length = setting->BlobLength;
+ Setting.Value.pBlob = (uint8_t *) mir_realloc(Setting.Value.pBlob, setting->BlobLength);
+ memcpy(Setting.Value.pBlob, str, setting->BlobLength);
+ } break;
+ }
+ } break;
+ case DBT_ST_UTF8:
+ {
+ str[setting->BlobLength - 1] = 0;
+
+ switch (Setting.Type)
+ {
+ case DBT_ST_BYTE: case DBT_ST_WORD: case DBT_ST_DWORD: case DBT_ST_QWORD: case DBT_ST_BOOL:
+ case DBT_ST_CHAR: case DBT_ST_SHORT: case DBT_ST_INT: case DBT_ST_INT64:
+ {
+ Setting.Value.QWord = 0;
+ } break;
+ case DBT_ST_ANSI:
+ {
+ mir_utf8decode((char*)str, NULL);
+ Setting.Value.Length = static_cast<uint32_t>(strlen((char*)str) + 1);
+ Setting.Value.pAnsi = (char *) mir_realloc(Setting.Value.pAnsi, Setting.Value.Length);
+ memcpy(Setting.Value.pAnsi, str, Setting.Value.Length);
+ } break;
+ case DBT_ST_UTF8:
+ {
+ Setting.Value.Length = setting->BlobLength;
+ Setting.Value.pUTF8 = (char *) mir_realloc(Setting.Value.pUTF8, setting->BlobLength);
+ memcpy(Setting.Value.pUTF8, str, setting->BlobLength);
+ } break;
+ case DBT_ST_WCHAR:
+ {
+ Setting.Value.pWide = mir_utf8decodeW((char*)str);
+ if (Setting.Value.pWide)
+ {
+ Setting.Value.Length = static_cast<uint32_t>(wcslen(Setting.Value.pWide) + 1);
+ } else {
+ Setting.Value.Length = 0;
+ Setting.Type = 0;
+ }
+ } break;
+ case DBT_ST_BLOB:
+ {
+ Setting.Value.pBlob = (uint8_t *) mir_realloc(Setting.Value.pBlob, setting->BlobLength);
+ memcpy(Setting.Value.pBlob, str, setting->BlobLength);
+ Setting.Value.Length = setting->BlobLength;
+ } break;
+ }
+ } break;
+ case DBT_ST_WCHAR:
+ {
+ ((wchar_t*)str)[setting->BlobLength / sizeof(wchar_t) - 1] = 0;
+
+ switch (Setting.Type)
+ {
+ case DBT_ST_BYTE: case DBT_ST_WORD: case DBT_ST_DWORD: case DBT_ST_QWORD: case DBT_ST_BOOL:
+ case DBT_ST_CHAR: case DBT_ST_SHORT: case DBT_ST_INT: case DBT_ST_INT64:
+ {
+ Setting.Value.QWord = 0;
+ } break;
+ case DBT_ST_ANSI:
+ {
+ Setting.Value.pAnsi = mir_u2a((wchar_t*)str);
+ Setting.Value.Length = static_cast<uint32_t>(strlen(Setting.Value.pAnsi) + 1);
+ } break;
+ case DBT_ST_UTF8:
+ {
+ Setting.Value.pUTF8 = mir_utf8encodeW((wchar_t*)str);
+ Setting.Value.Length = static_cast<uint32_t>(strlen(Setting.Value.pUTF8) + 1);
+ } break;
+ case DBT_ST_WCHAR:
+ {
+ Setting.Value.Length = setting->BlobLength / sizeof(wchar_t);
+ Setting.Value.pWide = (wchar_t*) mir_realloc(Setting.Value.pWide, Setting.Value.Length * sizeof(wchar_t));
+ memcpy(Setting.Value.pWide, str, Setting.Value.Length * sizeof(wchar_t));
+ } break;
+ case DBT_ST_BLOB:
+ {
+ Setting.Value.pBlob = (uint8_t *) mir_realloc(Setting.Value.pBlob, setting->BlobLength);
+ memcpy(Setting.Value.pBlob, str, setting->BlobLength);
+ Setting.Value.Length = setting->BlobLength;
+ } break;
+ }
+ } break;
+ case DBT_ST_BLOB:
+ {
+ switch (Setting.Type)
+ {
+ case DBT_ST_BYTE: case DBT_ST_WORD: case DBT_ST_DWORD: case DBT_ST_QWORD: case DBT_ST_BOOL:
+ case DBT_ST_CHAR: case DBT_ST_SHORT: case DBT_ST_INT: case DBT_ST_INT64:
+ {
+ Setting.Value.QWord = 0;
+ } break;
+ case DBT_ST_ANSI: case DBT_ST_WCHAR: case DBT_ST_UTF8:
+ {
+ Setting.Value.Length = 0;
+ if (Setting.Value.pBlob)
+ mir_free(Setting.Value.pBlob);
+
+ Setting.Value.pBlob = NULL;
+ } break;
+ case DBT_ST_BLOB:
+ {
+ Setting.Value.pBlob = (uint8_t *) mir_realloc(Setting.Value.pBlob, setting->BlobLength);
+ memcpy(Setting.Value.pBlob, str, setting->BlobLength);
+ Setting.Value.Length = setting->BlobLength;
+ } break;
+ }
+ } break;
+
+ }
+ }
+
+
+ if (Setting.Descriptor)
+ {
+ Setting.Descriptor->Entity = setting->Entity;
+ Setting.Descriptor->FoundInEntity = setting->Entity;
+
+ Setting.Descriptor->pszSettingName = (char *) mir_realloc(Setting.Descriptor->pszSettingName, setting->NameLength + 1);
+ memcpy(Setting.Descriptor->pszSettingName, setting + 1, setting->NameLength + 1);
+ Setting.Descriptor->pszSettingName[setting->NameLength] = 0;
+ }
+
+ return setting->Type;
+}
+
+
+
+
+TDBTSettingIterationHandle CSettings::IterationInit(TDBTSettingIterFilter & Filter)
+{
+ CBlockManager::ReadTransaction transset(m_BlockManagerSet);
+ CBlockManager::ReadTransaction transpri(m_BlockManagerPri);
+
+ std::queue<TDBTEntityHandle> Entities;
+ Entities.push(Filter.hEntity);
+
+ CSettingsTree * tree = getSettingsTree(Filter.hEntity);
+
+ if (tree == NULL)
+ return DBT_INVALIDPARAM;
+
+ if (Filter.hEntity != 0)
+ {
+ uint32_t cf = m_Entities.getFlags(Filter.hEntity);
+
+ if (cf == DBT_INVALIDPARAM)
+ return DBT_INVALIDPARAM;
+
+ TDBTEntityIterFilter f = {0,0,0,0};
+ f.cbSize = sizeof(f);
+ if (cf & DBT_NF_IsGroup)
+ {
+ f.fHasFlags = DBT_NF_IsGroup;
+ } else {
+ f.fDontHasFlags = DBT_NF_IsGroup;
+ }
+ f.Options = Filter.Options;
+
+ TDBTEntityIterationHandle citer = m_Entities.IterationInit(f, Filter.hEntity);
+ if (citer != DBT_INVALIDPARAM)
+ {
+ m_Entities.IterationNext(citer); // the initial Entity was already added
+ TDBTEntityHandle e = m_Entities.IterationNext(citer);
+ while (e != 0)
+ {
+ Entities.push(e);
+ e = m_Entities.IterationNext(citer);
+ }
+
+ m_Entities.IterationClose(citer);
+ }
+ }
+
+ for (unsigned int j = 0; j < Filter.ExtraCount; ++j)
+ Entities.push(Filter.ExtraEntities[j]);
+
+
+ PSettingIteration iter = new TSettingIteration;
+ iter->Filter = Filter;
+ iter->FilterNameStartLength = 0;
+ iter->LockSetting = (Filter.hEntity == 0);
+ iter->LockPrivate = (Filter.hEntity != 0);
+ if (Filter.NameStart)
+ {
+ uint16_t l = static_cast<uint32_t>(strlen(Filter.NameStart));
+ iter->Filter.NameStart = new char[l + 1];
+ memcpy(iter->Filter.NameStart, Filter.NameStart, l + 1);
+ iter->FilterNameStartLength = l;
+ }
+
+ TSettingKey key = {0, 0};
+
+ // pop first Entity. we have always one and always its tree
+ Entities.pop();
+
+ CSettingsTree::iterator * tmp = new CSettingsTree::iterator(tree->LowerBound(key));
+ tmp->setManaged();
+ iter->Heap = new TSettingsHeap(*tmp, TSettingsHeap::ITForward, true);
+
+ while (!Entities.empty())
+ {
+ TDBTEntityHandle e = Entities.front();
+ Entities.pop();
+
+ tree = getSettingsTree(e);
+ if (tree != NULL)
+ {
+ tmp = new CSettingsTree::iterator(tree->LowerBound(key));
+ tmp->setManaged();
+ iter->Heap->Insert(*tmp);
+
+ iter->LockSetting = iter->LockSetting || (e == 0);
+ iter->LockPrivate = iter->LockPrivate || (e != 0);
+ }
+ }
+
+ iter->Frame = new std::queue<TSettingIterationResult>;
+
+ return reinterpret_cast<TDBTSettingIterationHandle>(iter);
+}
+
+
+typedef struct TSettingIterationHelper {
+ TDBTSettingHandle Handle;
+ CSettingsTree * Tree;
+ uint16_t NameLen;
+ char * Name;
+ } TSettingIterationHelper;
+
+TDBTSettingHandle CSettings::IterationNext(TDBTSettingIterationHandle Iteration)
+{
+ PSettingIteration iter = reinterpret_cast<PSettingIteration>(Iteration);
+ CBlockManager::ReadTransaction transset;
+ CBlockManager::ReadTransaction transpri;
+
+ if (iter->LockSetting)
+ transset = CBlockManager::ReadTransaction(m_BlockManagerSet);
+ if (iter->LockPrivate)
+ transpri = CBlockManager::ReadTransaction(m_BlockManagerPri);
+
+ while (iter->Frame->empty() && iter->Heap->Top())
+ {
+ while (iter->Heap->Top() && iter->Heap->Top().wasDeleted())
+ iter->Heap->Pop();
+
+ if (iter->Heap->Top())
+ {
+ uint32_t h = iter->Heap->Top()->Hash;
+ std::queue<TSettingIterationHelper> q;
+ TSettingIterationHelper help;
+ help.NameLen = 0;
+ help.Name = NULL;
+
+ help.Handle = iter->Heap->Top()->Setting;
+ help.Tree = (CSettingsTree *) iter->Heap->Top().Tree();
+ if (help.Tree)
+ q.push(help);
+
+ iter->Heap->Pop();
+
+ // add all candidates
+ while (iter->Heap->Top() && (iter->Heap->Top()->Hash == h))
+ {
+ if (!iter->Heap->Top().wasDeleted())
+ {
+ help.Handle = iter->Heap->Top()->Setting;
+ help.Tree = (CSettingsTree *) iter->Heap->Top().Tree();
+ q.push(help);
+ }
+ iter->Heap->Pop();
+ }
+
+ while (!q.empty())
+ {
+ help = q.front();
+ q.pop();
+
+ if (help.Name == NULL)
+ {
+ if (help.Tree->Entity() == 0)
+ _ReadSettingName(m_BlockManagerSet, help.Handle, help.NameLen, help.Name);
+ else
+ _ReadSettingName(m_BlockManagerPri, help.Handle, help.NameLen, help.Name);
+ }
+
+
+ q.push(help);
+ while (q.front().Handle != help.Handle) // remove all queued settings with same name
+ {
+ bool namereadres = false;
+
+ TSettingIterationHelper tmp;
+ tmp = q.front();
+ q.pop();
+
+ if (tmp.Name == NULL)
+ {
+ if (tmp.Tree->Entity() == 0)
+ namereadres = _ReadSettingName(m_BlockManagerSet, tmp.Handle, tmp.NameLen, tmp.Name);
+ else
+ namereadres = _ReadSettingName(m_BlockManagerPri, tmp.Handle, tmp.NameLen, tmp.Name);
+ }
+
+ if (!namereadres)
+ {
+ q.push(tmp);
+ } else {
+ if (strcmp(tmp.Name, help.Name) != 0)
+ {
+ q.push(tmp);
+ } else {
+ free(tmp.Name);
+ }
+ }
+ }
+
+ // namefilter
+ if ((iter->Filter.NameStart == NULL) || ((iter->FilterNameStartLength <= help.NameLen) && (memcmp(iter->Filter.NameStart, help.Name, iter->FilterNameStartLength) == 0)))
+ {
+ TSettingIterationResult tmp;
+ if (help.Tree->Entity() == 0)
+ help.Handle |= cSettingsFileFlag;
+
+ tmp.Handle = help.Handle;
+ tmp.Entity = help.Tree->Entity();
+ tmp.Name = help.Name;
+ tmp.NameLen = help.NameLen;
+ iter->Frame->push(tmp);
+ } else {
+ free(help.Name);
+ }
+
+ q.pop();
+ }
+ }
+ }
+
+
+ TSettingIterationResult res = {0,0,0,0};
+ if (!iter->Frame->empty())
+ {
+ res = iter->Frame->front();
+ iter->Frame->pop();
+
+ if ((iter->Filter.Descriptor) && ((iter->Filter.Setting == NULL) || (iter->Filter.Setting->Descriptor != iter->Filter.Descriptor)))
+ {
+ iter->Filter.Descriptor->Entity = res.Entity;
+ iter->Filter.Descriptor->pszSettingName = (char *) mir_realloc(iter->Filter.Descriptor->pszSettingName, res.NameLen + 1);
+ memcpy(iter->Filter.Descriptor->pszSettingName, res.Name, res.NameLen + 1);
+ iter->Filter.Descriptor->FoundInEntity = res.Entity;
+ }
+ if (iter->Filter.Setting)
+ {
+ if ((iter->Filter.Setting->Type & DBT_STF_VariableLength) && (iter->Filter.Setting->Value.pBlob))
+ {
+ mir_free(iter->Filter.Setting->Value.pBlob);
+ iter->Filter.Setting->Value.pBlob = NULL;
+ }
+ iter->Filter.Setting->Type = 0;
+
+ ReadSetting(*iter->Filter.Setting, res.Handle);
+ }
+
+ free(res.Name);
+ }
+
+ return res.Handle;
+}
+unsigned int CSettings::IterationClose(TDBTSettingIterationHandle Iteration)
+{
+ PSettingIteration iter = reinterpret_cast<PSettingIteration>(Iteration);
+ {
+ CBlockManager::ReadTransaction transset;
+ CBlockManager::ReadTransaction transpri;
+
+ if (iter->LockSetting)
+ transset = CBlockManager::ReadTransaction(m_BlockManagerSet);
+ if (iter->LockPrivate)
+ transpri = CBlockManager::ReadTransaction(m_BlockManagerPri);
+
+ delete iter->Heap; // only this needs synchronization
+ }
+
+ if (iter->Filter.NameStart)
+ delete [] iter->Filter.NameStart;
+
+ if (iter->Filter.Descriptor && iter->Filter.Descriptor->pszSettingName)
+ {
+ mir_free(iter->Filter.Descriptor->pszSettingName);
+ iter->Filter.Descriptor->pszSettingName = NULL;
+ }
+ if (iter->Filter.Setting)
+ {
+ if (iter->Filter.Setting->Descriptor)
+ {
+ mir_free(iter->Filter.Setting->Descriptor->pszSettingName);
+ iter->Filter.Setting->Descriptor->pszSettingName = NULL;
+ }
+
+ if (iter->Filter.Setting->Type & DBT_STF_VariableLength)
+ {
+ mir_free(iter->Filter.Setting->Value.pBlob);
+ iter->Filter.Setting->Value.pBlob = NULL;
+ }
+ }
+
+ while (!iter->Frame->empty())
+ {
+ if (iter->Frame->front().Name)
+ free(iter->Frame->front().Name);
+
+ iter->Frame->pop();
+ }
+ delete iter->Frame;
+ delete iter;
+
+ return 0;
+}
+
+
+int CSettings::CompEnumModules(DBMODULEENUMPROC CallBack, LPARAM lParam)
+{
+ CBlockManager::ReadTransaction trans(m_BlockManagerSet);
+
+ TModulesMap::iterator i = m_Modules.begin();
+ int res = 0;
+ while ((i != m_Modules.end()) && (res == 0))
+ {
+ char * tmp = i->second;
+ trans.Close();
+
+ res = CallBack(tmp, 0, lParam);
+
+ trans = CBlockManager::ReadTransaction(m_BlockManagerSet);
+ ++i;
+ }
+
+ return res;
+}