From 69fe21d6e2262d6fb2b14278b7a20364468cbdcf Mon Sep 17 00:00:00 2001 From: Vadim Dashevskiy Date: Fri, 12 Oct 2012 09:56:01 +0000 Subject: Dbx_tree: folders restructurization git-svn-id: http://svn.miranda-ng.org/main/trunk@1883 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c --- plugins/Dbx_tree/BTree.h | 1358 ---------- plugins/Dbx_tree/BlockManager.cpp | 965 ------- plugins/Dbx_tree/BlockManager.h | 401 --- plugins/Dbx_tree/Compatibility.cpp | 799 ------ plugins/Dbx_tree/Compatibility.h | 30 - plugins/Dbx_tree/DataBase.cpp | 371 --- plugins/Dbx_tree/DataBase.h | 189 -- plugins/Dbx_tree/DatabaseLink.cpp | 96 - plugins/Dbx_tree/DatabaseLink.h | 28 - plugins/Dbx_tree/DirectAccess.cpp | 118 - plugins/Dbx_tree/DirectAccess.h | 43 - plugins/Dbx_tree/EncryptionManager.cpp | 241 -- plugins/Dbx_tree/EncryptionManager.h | 107 - plugins/Dbx_tree/Entities.cpp | 1032 -------- plugins/Dbx_tree/Entities.h | 299 --- plugins/Dbx_tree/Events.cpp | 986 -------- plugins/Dbx_tree/Events.h | 263 -- plugins/Dbx_tree/FileAccess.cpp | 299 --- plugins/Dbx_tree/FileAccess.h | 191 -- plugins/Dbx_tree/FileBTree.h | 102 - plugins/Dbx_tree/Filestructure.txt | Bin 25894 -> 0 bytes plugins/Dbx_tree/Hash.cpp | 183 -- plugins/Dbx_tree/Hash.h | 29 - plugins/Dbx_tree/Interface.h | 55 - plugins/Dbx_tree/IterationHeap.h | 196 -- plugins/Dbx_tree/Logger.cpp | 124 - plugins/Dbx_tree/Logger.h | 73 - plugins/Dbx_tree/MREWSync.cpp | 330 --- plugins/Dbx_tree/MREWSync.h | 55 - plugins/Dbx_tree/MappedMemory.cpp | 167 -- plugins/Dbx_tree/MappedMemory.h | 47 - plugins/Dbx_tree/SHA256.cpp | 301 --- plugins/Dbx_tree/SHA256.h | 49 - plugins/Dbx_tree/Services.cpp | 402 --- plugins/Dbx_tree/Services.h | 69 - plugins/Dbx_tree/Settings.cpp | 1479 ----------- plugins/Dbx_tree/Settings.h | 235 -- plugins/Dbx_tree/TLS.h | 161 -- plugins/Dbx_tree/Thread.cpp | 114 - plugins/Dbx_tree/Thread.h | 77 - plugins/Dbx_tree/dbConfig.rc | 113 - plugins/Dbx_tree/dbConfig_rc.h | 20 - plugins/Dbx_tree/dbVersion.rc | 105 - plugins/Dbx_tree/dbVersion_rc.h | 14 - plugins/Dbx_tree/dbx_tree-translation.txt | 8 - plugins/Dbx_tree/dbx_tree_10.vcxproj | 109 +- plugins/Dbx_tree/dbx_tree_10.vcxproj.filters | 104 +- plugins/Dbx_tree/docs/Filestructure.txt | Bin 0 -> 25894 bytes plugins/Dbx_tree/docs/dbx_tree-translation.txt | 8 + plugins/Dbx_tree/encryption/ARC4.cpp | 129 - plugins/Dbx_tree/encryption/ARC4.h | 65 - plugins/Dbx_tree/encryption/ARC4.vcxproj | 160 -- plugins/Dbx_tree/encryption/ARC4.vcxproj.filters | 30 - plugins/Dbx_tree/encryption/ARC4/ARC4.vcxproj | 168 ++ .../Dbx_tree/encryption/ARC4/ARC4.vcxproj.filters | 30 + plugins/Dbx_tree/encryption/ARC4/src/ARC4.cpp | 129 + plugins/Dbx_tree/encryption/ARC4/src/ARC4.h | 65 + plugins/Dbx_tree/encryption/CAST128.cpp | 260 -- plugins/Dbx_tree/encryption/CAST128.h | 61 - plugins/Dbx_tree/encryption/CAST128.inc | 302 --- .../Dbx_tree/encryption/CAST128/Cast128.vcxproj | 171 ++ .../encryption/CAST128/Cast128.vcxproj.filters | 35 + .../Dbx_tree/encryption/CAST128/src/CAST128.cpp | 260 ++ plugins/Dbx_tree/encryption/CAST128/src/CAST128.h | 61 + .../Dbx_tree/encryption/CAST128/src/CAST128.inc | 302 +++ plugins/Dbx_tree/encryption/Cast128.vcxproj | 163 -- .../Dbx_tree/encryption/Cast128.vcxproj.filters | 35 - plugins/Dbx_tree/encryption/Cipher.h | 180 -- plugins/Dbx_tree/encryption/Common/Cipher.h | 180 ++ plugins/Dbx_tree/encryption/HC256.cpp | 243 -- plugins/Dbx_tree/encryption/HC256.h | 66 - plugins/Dbx_tree/encryption/HC256.vcxproj | 160 -- plugins/Dbx_tree/encryption/HC256.vcxproj.filters | 30 - plugins/Dbx_tree/encryption/HC256/HC256.vcxproj | 168 ++ .../encryption/HC256/HC256.vcxproj.filters | 30 + plugins/Dbx_tree/encryption/HC256/src/HC256.cpp | 243 ++ plugins/Dbx_tree/encryption/HC256/src/HC256.h | 66 + plugins/Dbx_tree/init.cpp | 73 - plugins/Dbx_tree/intrinsics.h | 407 --- plugins/Dbx_tree/inttypes.h | 305 --- plugins/Dbx_tree/lockfree_hashmap.h | 749 ------ plugins/Dbx_tree/lockfree_hashmultimap.h | 750 ------ plugins/Dbx_tree/res/dbConfig.rc | 113 + plugins/Dbx_tree/res/dbVersion.rc | 105 + plugins/Dbx_tree/savestrings_gcc.h | 127 - plugins/Dbx_tree/sigslot.h | 2639 -------------------- plugins/Dbx_tree/src/BTree.h | 1358 ++++++++++ plugins/Dbx_tree/src/BlockManager.cpp | 965 +++++++ plugins/Dbx_tree/src/BlockManager.h | 401 +++ plugins/Dbx_tree/src/Compatibility.cpp | 799 ++++++ plugins/Dbx_tree/src/Compatibility.h | 30 + plugins/Dbx_tree/src/DataBase.cpp | 371 +++ plugins/Dbx_tree/src/DataBase.h | 189 ++ plugins/Dbx_tree/src/DatabaseLink.cpp | 96 + plugins/Dbx_tree/src/DatabaseLink.h | 28 + plugins/Dbx_tree/src/DirectAccess.cpp | 118 + plugins/Dbx_tree/src/DirectAccess.h | 43 + plugins/Dbx_tree/src/EncryptionManager.cpp | 241 ++ plugins/Dbx_tree/src/EncryptionManager.h | 107 + plugins/Dbx_tree/src/Entities.cpp | 1032 ++++++++ plugins/Dbx_tree/src/Entities.h | 299 +++ plugins/Dbx_tree/src/Events.cpp | 986 ++++++++ plugins/Dbx_tree/src/Events.h | 263 ++ plugins/Dbx_tree/src/FileAccess.cpp | 299 +++ plugins/Dbx_tree/src/FileAccess.h | 191 ++ plugins/Dbx_tree/src/FileBTree.h | 102 + plugins/Dbx_tree/src/Hash.cpp | 183 ++ plugins/Dbx_tree/src/Hash.h | 29 + plugins/Dbx_tree/src/Interface.h | 55 + plugins/Dbx_tree/src/IterationHeap.h | 196 ++ plugins/Dbx_tree/src/Logger.cpp | 124 + plugins/Dbx_tree/src/Logger.h | 73 + plugins/Dbx_tree/src/MREWSync.cpp | 330 +++ plugins/Dbx_tree/src/MREWSync.h | 55 + plugins/Dbx_tree/src/MappedMemory.cpp | 167 ++ plugins/Dbx_tree/src/MappedMemory.h | 47 + plugins/Dbx_tree/src/SHA256.cpp | 301 +++ plugins/Dbx_tree/src/SHA256.h | 49 + plugins/Dbx_tree/src/Services.cpp | 402 +++ plugins/Dbx_tree/src/Services.h | 69 + plugins/Dbx_tree/src/Settings.cpp | 1479 +++++++++++ plugins/Dbx_tree/src/Settings.h | 235 ++ plugins/Dbx_tree/src/TLS.h | 161 ++ plugins/Dbx_tree/src/Thread.cpp | 114 + plugins/Dbx_tree/src/Thread.h | 77 + plugins/Dbx_tree/src/dbConfig_rc.h | 20 + plugins/Dbx_tree/src/dbVersion_rc.h | 14 + plugins/Dbx_tree/src/init.cpp | 73 + plugins/Dbx_tree/src/intrinsics.h | 407 +++ plugins/Dbx_tree/src/inttypes.h | 305 +++ plugins/Dbx_tree/src/lockfree_hashmap.h | 749 ++++++ plugins/Dbx_tree/src/lockfree_hashmultimap.h | 750 ++++++ plugins/Dbx_tree/src/savestrings_gcc.h | 127 + plugins/Dbx_tree/src/sigslot.h | 2639 ++++++++++++++++++++ plugins/Dbx_tree/src/stdint.h | 247 ++ plugins/Dbx_tree/stdint.h | 247 -- 136 files changed, 19633 insertions(+), 19614 deletions(-) delete mode 100644 plugins/Dbx_tree/BTree.h delete mode 100644 plugins/Dbx_tree/BlockManager.cpp delete mode 100644 plugins/Dbx_tree/BlockManager.h delete mode 100644 plugins/Dbx_tree/Compatibility.cpp delete mode 100644 plugins/Dbx_tree/Compatibility.h delete mode 100644 plugins/Dbx_tree/DataBase.cpp delete mode 100644 plugins/Dbx_tree/DataBase.h delete mode 100644 plugins/Dbx_tree/DatabaseLink.cpp delete mode 100644 plugins/Dbx_tree/DatabaseLink.h delete mode 100644 plugins/Dbx_tree/DirectAccess.cpp delete mode 100644 plugins/Dbx_tree/DirectAccess.h delete mode 100644 plugins/Dbx_tree/EncryptionManager.cpp delete mode 100644 plugins/Dbx_tree/EncryptionManager.h delete mode 100644 plugins/Dbx_tree/Entities.cpp delete mode 100644 plugins/Dbx_tree/Entities.h delete mode 100644 plugins/Dbx_tree/Events.cpp delete mode 100644 plugins/Dbx_tree/Events.h delete mode 100644 plugins/Dbx_tree/FileAccess.cpp delete mode 100644 plugins/Dbx_tree/FileAccess.h delete mode 100644 plugins/Dbx_tree/FileBTree.h delete mode 100644 plugins/Dbx_tree/Filestructure.txt delete mode 100644 plugins/Dbx_tree/Hash.cpp delete mode 100644 plugins/Dbx_tree/Hash.h delete mode 100644 plugins/Dbx_tree/Interface.h delete mode 100644 plugins/Dbx_tree/IterationHeap.h delete mode 100644 plugins/Dbx_tree/Logger.cpp delete mode 100644 plugins/Dbx_tree/Logger.h delete mode 100644 plugins/Dbx_tree/MREWSync.cpp delete mode 100644 plugins/Dbx_tree/MREWSync.h delete mode 100644 plugins/Dbx_tree/MappedMemory.cpp delete mode 100644 plugins/Dbx_tree/MappedMemory.h delete mode 100644 plugins/Dbx_tree/SHA256.cpp delete mode 100644 plugins/Dbx_tree/SHA256.h delete mode 100644 plugins/Dbx_tree/Services.cpp delete mode 100644 plugins/Dbx_tree/Services.h delete mode 100644 plugins/Dbx_tree/Settings.cpp delete mode 100644 plugins/Dbx_tree/Settings.h delete mode 100644 plugins/Dbx_tree/TLS.h delete mode 100644 plugins/Dbx_tree/Thread.cpp delete mode 100644 plugins/Dbx_tree/Thread.h delete mode 100644 plugins/Dbx_tree/dbConfig.rc delete mode 100644 plugins/Dbx_tree/dbConfig_rc.h delete mode 100644 plugins/Dbx_tree/dbVersion.rc delete mode 100644 plugins/Dbx_tree/dbVersion_rc.h delete mode 100644 plugins/Dbx_tree/dbx_tree-translation.txt create mode 100644 plugins/Dbx_tree/docs/Filestructure.txt create mode 100644 plugins/Dbx_tree/docs/dbx_tree-translation.txt delete mode 100644 plugins/Dbx_tree/encryption/ARC4.cpp delete mode 100644 plugins/Dbx_tree/encryption/ARC4.h delete mode 100644 plugins/Dbx_tree/encryption/ARC4.vcxproj delete mode 100644 plugins/Dbx_tree/encryption/ARC4.vcxproj.filters create mode 100644 plugins/Dbx_tree/encryption/ARC4/ARC4.vcxproj create mode 100644 plugins/Dbx_tree/encryption/ARC4/ARC4.vcxproj.filters create mode 100644 plugins/Dbx_tree/encryption/ARC4/src/ARC4.cpp create mode 100644 plugins/Dbx_tree/encryption/ARC4/src/ARC4.h delete mode 100644 plugins/Dbx_tree/encryption/CAST128.cpp delete mode 100644 plugins/Dbx_tree/encryption/CAST128.h delete mode 100644 plugins/Dbx_tree/encryption/CAST128.inc create mode 100644 plugins/Dbx_tree/encryption/CAST128/Cast128.vcxproj create mode 100644 plugins/Dbx_tree/encryption/CAST128/Cast128.vcxproj.filters create mode 100644 plugins/Dbx_tree/encryption/CAST128/src/CAST128.cpp create mode 100644 plugins/Dbx_tree/encryption/CAST128/src/CAST128.h create mode 100644 plugins/Dbx_tree/encryption/CAST128/src/CAST128.inc delete mode 100644 plugins/Dbx_tree/encryption/Cast128.vcxproj delete mode 100644 plugins/Dbx_tree/encryption/Cast128.vcxproj.filters delete mode 100644 plugins/Dbx_tree/encryption/Cipher.h create mode 100644 plugins/Dbx_tree/encryption/Common/Cipher.h delete mode 100644 plugins/Dbx_tree/encryption/HC256.cpp delete mode 100644 plugins/Dbx_tree/encryption/HC256.h delete mode 100644 plugins/Dbx_tree/encryption/HC256.vcxproj delete mode 100644 plugins/Dbx_tree/encryption/HC256.vcxproj.filters create mode 100644 plugins/Dbx_tree/encryption/HC256/HC256.vcxproj create mode 100644 plugins/Dbx_tree/encryption/HC256/HC256.vcxproj.filters create mode 100644 plugins/Dbx_tree/encryption/HC256/src/HC256.cpp create mode 100644 plugins/Dbx_tree/encryption/HC256/src/HC256.h delete mode 100644 plugins/Dbx_tree/init.cpp delete mode 100644 plugins/Dbx_tree/intrinsics.h delete mode 100644 plugins/Dbx_tree/inttypes.h delete mode 100644 plugins/Dbx_tree/lockfree_hashmap.h delete mode 100644 plugins/Dbx_tree/lockfree_hashmultimap.h create mode 100644 plugins/Dbx_tree/res/dbConfig.rc create mode 100644 plugins/Dbx_tree/res/dbVersion.rc delete mode 100644 plugins/Dbx_tree/savestrings_gcc.h delete mode 100644 plugins/Dbx_tree/sigslot.h create mode 100644 plugins/Dbx_tree/src/BTree.h create mode 100644 plugins/Dbx_tree/src/BlockManager.cpp create mode 100644 plugins/Dbx_tree/src/BlockManager.h create mode 100644 plugins/Dbx_tree/src/Compatibility.cpp create mode 100644 plugins/Dbx_tree/src/Compatibility.h create mode 100644 plugins/Dbx_tree/src/DataBase.cpp create mode 100644 plugins/Dbx_tree/src/DataBase.h create mode 100644 plugins/Dbx_tree/src/DatabaseLink.cpp create mode 100644 plugins/Dbx_tree/src/DatabaseLink.h create mode 100644 plugins/Dbx_tree/src/DirectAccess.cpp create mode 100644 plugins/Dbx_tree/src/DirectAccess.h create mode 100644 plugins/Dbx_tree/src/EncryptionManager.cpp create mode 100644 plugins/Dbx_tree/src/EncryptionManager.h create mode 100644 plugins/Dbx_tree/src/Entities.cpp create mode 100644 plugins/Dbx_tree/src/Entities.h create mode 100644 plugins/Dbx_tree/src/Events.cpp create mode 100644 plugins/Dbx_tree/src/Events.h create mode 100644 plugins/Dbx_tree/src/FileAccess.cpp create mode 100644 plugins/Dbx_tree/src/FileAccess.h create mode 100644 plugins/Dbx_tree/src/FileBTree.h create mode 100644 plugins/Dbx_tree/src/Hash.cpp create mode 100644 plugins/Dbx_tree/src/Hash.h create mode 100644 plugins/Dbx_tree/src/Interface.h create mode 100644 plugins/Dbx_tree/src/IterationHeap.h create mode 100644 plugins/Dbx_tree/src/Logger.cpp create mode 100644 plugins/Dbx_tree/src/Logger.h create mode 100644 plugins/Dbx_tree/src/MREWSync.cpp create mode 100644 plugins/Dbx_tree/src/MREWSync.h create mode 100644 plugins/Dbx_tree/src/MappedMemory.cpp create mode 100644 plugins/Dbx_tree/src/MappedMemory.h create mode 100644 plugins/Dbx_tree/src/SHA256.cpp create mode 100644 plugins/Dbx_tree/src/SHA256.h create mode 100644 plugins/Dbx_tree/src/Services.cpp create mode 100644 plugins/Dbx_tree/src/Services.h create mode 100644 plugins/Dbx_tree/src/Settings.cpp create mode 100644 plugins/Dbx_tree/src/Settings.h create mode 100644 plugins/Dbx_tree/src/TLS.h create mode 100644 plugins/Dbx_tree/src/Thread.cpp create mode 100644 plugins/Dbx_tree/src/Thread.h create mode 100644 plugins/Dbx_tree/src/dbConfig_rc.h create mode 100644 plugins/Dbx_tree/src/dbVersion_rc.h create mode 100644 plugins/Dbx_tree/src/init.cpp create mode 100644 plugins/Dbx_tree/src/intrinsics.h create mode 100644 plugins/Dbx_tree/src/inttypes.h create mode 100644 plugins/Dbx_tree/src/lockfree_hashmap.h create mode 100644 plugins/Dbx_tree/src/lockfree_hashmultimap.h create mode 100644 plugins/Dbx_tree/src/savestrings_gcc.h create mode 100644 plugins/Dbx_tree/src/sigslot.h create mode 100644 plugins/Dbx_tree/src/stdint.h delete mode 100644 plugins/Dbx_tree/stdint.h (limited to 'plugins') diff --git a/plugins/Dbx_tree/BTree.h b/plugins/Dbx_tree/BTree.h deleted file mode 100644 index 20c2abfd71..0000000000 --- a/plugins/Dbx_tree/BTree.h +++ /dev/null @@ -1,1358 +0,0 @@ -/* - -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. - -*/ - -#pragma once - -#include -#include "lockfree_hashmultimap.h" -#include "sigslot.h" -#ifdef _MSC_VER -#include "stdint.h" -#else -#include -#endif - -#include "Logger.h" - -#ifndef _MSC_VER -#ifdef offsetof -#undef offsetof -#endif -#define offsetof(TYPE, MEMBER) \ - ( (reinterpret_cast \ - (&reinterpret_cast \ - (static_cast (0)->MEMBER)))) -#endif - -template -class CBTree -{ -public: - typedef uint32_t TNodeRef; /// 32bit indices (not storing pointers) - typedef sigslot::signal2< void *, TNodeRef > TOnRootChanged; - - #pragma pack(push, 1) // push current alignment to stack, set alignment to 1 byte boundary - - typedef struct TNode { - uint16_t Info; /// Node information (IsLeaf and stored KeyCount) - uint16_t Signature; /// signature - TNodeRef Parent; /// Handle to the parent node - TKey Key[SizeParam * 2 - 1]; /// array with Keys - TNodeRef Child[SizeParam * 2]; /// array with child node handles - } TNode; - - #pragma pack(pop) - - class iterator - { - public: - iterator(); - iterator(CBTree* Tree, TNodeRef Node, uint16_t Index); - iterator(const iterator& Other); - ~iterator(); - - CBTree * Tree(); - - /** - \brief Keeps track of changes in the tree and refresh the iterator - **/ - void setManaged(); - bool wasDeleted(); - - operator bool() const; - bool operator !() const; - - const TKey & operator *(); - const TKey * operator->(); - - - bool operator == (iterator & Other); - bool operator < (iterator & Other); - bool operator > (iterator & Other); - - iterator& operator =(const iterator& Other); - - iterator& operator ++(); //pre ++i - iterator& operator --(); //pre --i - iterator operator ++(int); //post i++ - iterator operator --(int); //post i-- - - - protected: - friend class CBTree; - - TNodeRef m_Node; - uint16_t m_Index; - CBTree* m_Tree; - - bool m_Managed; - bool m_LoadedKey; - TKey m_ManagedKey; - bool m_ManagedDeleted; - - void Backup(); - void Dec(); - void Inc(); - void RemoveManaged(TNodeRef FromNode); - void InsertManaged(); - }; - - - CBTree(TNodeRef RootNode = 0); - virtual ~CBTree(); - - iterator Insert(const TKey & Key); - iterator Find(const TKey & Key); - iterator LowerBound(const TKey & Key); - iterator UpperBound(const TKey & Key); - bool Delete(const TKey & Key); - - typedef sigslot::signal3 TDeleteCallback; - void DeleteTree(TDeleteCallback * CallBack, uint32_t Param); - - TNodeRef getRoot(); - void setRoot(TNodeRef NewRoot); - - TOnRootChanged & sigRootChanged() {return m_sigRootChanged;}; - - -protected: - static const uint16_t cIsLeafMask = 0x8000; - static const uint16_t cKeyCountMask = 0x7FFF; - static const uint16_t cFullNode = SizeParam * 2 - 1; - static const uint16_t cEmptyNode = SizeParam - 1; - - typedef lockfree::hash_multimap TManagedMap; - - TNodeRef m_Root; - TOnRootChanged m_sigRootChanged; - TManagedMap m_ManagedIterators; - - bool m_DestroyTree; - - uint32_t m_AllocCount; - uint32_t m_Count; - uint32_t m_FreeIndex; - TNode * m_Alloc; - - virtual void PrepareInsertOperation(); - virtual TNode * CreateNewNode(TNodeRef & NodeRef); - virtual void DeleteNode(TNodeRef Node); - virtual TNode * Read(TNodeRef Node); - virtual void Write(TNodeRef Node); - - void DestroyTree(); - - -private: - friend class iterator; - - bool InNodeFind(const TNode * Node, const TKey & Key, uint16_t & GreaterEqual); - void SplitNode(TNodeRef Node, TNode * NodeData, TNodeRef & Left, TNodeRef & Right, TKey & UpKey, TNodeRef ParentNode, uint16_t ParentIndex); - TNodeRef MergeNodes(TNodeRef Left, TNode * LeftData, TNodeRef Right, TNode * RightData, const TKey & DownKey, TNodeRef ParentNode, uint16_t ParentIndex); - void KeyInsert(TNodeRef Node, TNode * NodeData, uint16_t Where); - void KeyDelete(TNodeRef Node, TNode * NodeData, uint16_t Where); - void KeyMove(TNodeRef Source, uint16_t SourceIndex, const TNode * SourceData, TNodeRef Dest, uint16_t DestIndex, TNode * DestData); -}; - - - - - - -template -CBTree::CBTree(TNodeRef RootNode = NULL) -: m_sigRootChanged(), - m_ManagedIterators() -{ - m_Root = RootNode; - m_DestroyTree = true; - - m_AllocCount = 0; - m_Count = 0; - m_FreeIndex = 0; - m_Alloc = NULL; -} - -template -CBTree::~CBTree() -{ - typename TManagedMap::iterator i = m_ManagedIterators.begin(); - while (i != m_ManagedIterators.end()) - { - i->second->m_Tree = NULL; - i++; - } - - if (m_DestroyTree) - DestroyTree(); -} - -template -inline bool CBTree::InNodeFind(const TNode * Node, const TKey & Key, uint16_t & GreaterEqual) -{ - uint16_t l = 0; - uint16_t r = (Node->Info & cKeyCountMask); - bool res = false; - GreaterEqual = 0; - while ((l < r) && !res) - { - GreaterEqual = (l + r) >> 1; - if (Node->Key[GreaterEqual] < Key) - { - GreaterEqual++; - l = GreaterEqual; - } else if (Node->Key[GreaterEqual] == Key) - { - //r = -1; - res = true; - } else { - r = GreaterEqual; - } - } - - return res; -} - - -template -inline void CBTree::SplitNode(TNodeRef Node, TNode * NodeData, TNodeRef & Left, TNodeRef & Right, TKey & UpKey, TNodeRef ParentNode, uint16_t ParentIndex) -{ - const uint16_t upindex = SizeParam - 1; - TNode *ldata, *rdata; - Left = Node; - ldata = NodeData; - rdata = CreateNewNode(Right); - - typename TManagedMap::iterator it = m_ManagedIterators.find(Node); - while ((it != m_ManagedIterators.end()) && (it->first == Node)) - { - if (it->second->m_Index == upindex) - { - it->second->m_Index = ParentIndex; - it->second->m_Node = ParentNode; - m_ManagedIterators.insert(std::make_pair(ParentNode, it->second)); - it = m_ManagedIterators.erase(it); - } else if (it->second->m_Index > upindex) - { - it->second->m_Index = it->second->m_Index - upindex - 1; - it->second->m_Node = Right; - m_ManagedIterators.insert(std::make_pair(Right, it->second)); - it = m_ManagedIterators.erase(it); - } else { - ++it; - } - } - - UpKey = NodeData->Key[upindex]; - - memcpy(&(rdata->Key[0]), &(NodeData->Key[upindex+1]), sizeof(TKey) * (cFullNode - upindex)); - if ((NodeData->Info & cIsLeafMask) == 0) - { - memcpy(&(rdata->Child[0]), &(NodeData->Child[upindex+1]), sizeof(TNodeRef) * (cFullNode - upindex + 1)); - - for (int i = 0; i <= upindex; i++) - { - TNode * tmp = Read(rdata->Child[i]); - tmp->Parent = Right; - Write(rdata->Child[i]); - } - } - - rdata->Info = (NodeData->Info & cIsLeafMask) | upindex; - NodeData->Info = rdata->Info; - rdata->Parent = NodeData->Parent; - - Write(Left); - Write(Right); -} - -template -inline typename CBTree::TNodeRef CBTree::MergeNodes(TNodeRef Left, TNode * LeftData, TNodeRef Right, TNode * RightData, const TKey & DownKey, TNodeRef ParentNode, uint16_t ParentIndex) -{ - uint16_t downindex = LeftData->Info & cKeyCountMask; - LeftData->Key[downindex] = DownKey; - - typename TManagedMap::iterator it = m_ManagedIterators.find(Right); - while ((it != m_ManagedIterators.end()) && (it->first == Right)) - { - it->second->m_Index = it->second->m_Index + downindex + 1; - it->second->m_Node = Left; - m_ManagedIterators.insert(std::make_pair(Left, it->second)); - it = m_ManagedIterators.erase(it); - } - - it = m_ManagedIterators.find(ParentNode); - while ((it != m_ManagedIterators.end()) && (it->first == ParentNode)) - { - if (it->second->m_Index == ParentIndex) - { - it->second->m_Index = downindex; - it->second->m_Node = Left; - m_ManagedIterators.insert(std::make_pair(Left, it->second)); - it = m_ManagedIterators.erase(it); - } else { - ++it; - } - } - - memcpy(&(LeftData->Key[downindex+1]), &(RightData->Key[0]), sizeof(TKey) * (RightData->Info & cKeyCountMask)); - if ((LeftData->Info & cIsLeafMask) == 0) - { - memcpy(&(LeftData->Child[downindex+1]), &(RightData->Child[0]), sizeof(TNodeRef) * ((RightData->Info & cKeyCountMask) + 1)); - - for (int i = 0; i <= (RightData->Info & cKeyCountMask); i++) - { - TNode * tmp = Read(RightData->Child[i]); - tmp->Parent = Left; - Write(RightData->Child[i]); - } - } - - LeftData->Info = ((LeftData->Info & cIsLeafMask) | (downindex + 1 + (RightData->Info & cKeyCountMask))); - - Write(Left); - DeleteNode(Right); - - return Left; -} - - -template -inline void CBTree::KeyInsert(TNodeRef Node, TNode * NodeData, uint16_t Where) -{ - memcpy(&(NodeData->Key[Where+1]), &(NodeData->Key[Where]), sizeof(TKey) * ((NodeData->Info & cKeyCountMask) - Where)); - - if ((NodeData->Info & cIsLeafMask) == 0) - memcpy(&(NodeData->Child[Where+1]), &(NodeData->Child[Where]), sizeof(TNodeRef) * ((NodeData->Info & cKeyCountMask) - Where + 1)); - - NodeData->Info++; - - typename TManagedMap::iterator it = m_ManagedIterators.find(Node); - while ((it != m_ManagedIterators.end()) && (it->first == Node)) - { - if (it->second->m_Index >= Where) - it->second->m_Index++; - - ++it; - } -} - -template -inline void CBTree::KeyDelete(TNodeRef Node, TNode * NodeData, uint16_t Where) -{ - NodeData->Info--; - - typename TManagedMap::iterator it = m_ManagedIterators.find(Node); - while ((it != m_ManagedIterators.end()) && (it->first == Node)) - { - if (it->second->m_Index == Where) - { - it->second->Backup(); - } else if (it->second->m_Index > Where) - { - it->second->m_Index--; - } - - ++it; - } - - memcpy(&(NodeData->Key[Where]), &(NodeData->Key[Where+1]), sizeof(TKey) * ((NodeData->Info & cKeyCountMask) - Where)); - - if ((NodeData->Info & cIsLeafMask) == 0) - memcpy(&(NodeData->Child[Where]), &(NodeData->Child[Where+1]), sizeof(TNodeRef) * ((NodeData->Info & cKeyCountMask) - Where + 1)); -} - - -template -inline void CBTree::KeyMove(TNodeRef Source, uint16_t SourceIndex, const TNode * SourceData, TNodeRef Dest, uint16_t DestIndex, TNode * DestData) -{ - DestData->Key[DestIndex] = SourceData->Key[SourceIndex]; - - typename TManagedMap::iterator it = m_ManagedIterators.find(Source); - while ((it != m_ManagedIterators.end()) && (it->first == Source)) - { - if (it->second->m_Index == SourceIndex) - { - it->second->m_Index = DestIndex; - it->second->m_Node = Dest; - m_ManagedIterators.insert(std::make_pair(Dest, it->second)); - it = m_ManagedIterators.erase(it); - } else { - ++it; - } - } -} - -template -typename CBTree::iterator -CBTree::Insert(const TKey & Key) -{ - TNode *node, *node2; - TNodeRef actnode; - TNodeRef nextnode; - bool exists; - uint16_t ge; - - PrepareInsertOperation(); - - if (!m_Root) - { - node = CreateNewNode(m_Root); - node->Info = cIsLeafMask; - Write(m_Root); - m_sigRootChanged.emit(this, m_Root); - } - - actnode = m_Root; - node = Read(actnode); - if ((node->Info & cKeyCountMask) == cFullNode) // root split - { - // be a little tricky and let the main code handle the actual splitting. - // just assign a new root with keycount to zero and one child = old root - // the InNode test will fail with GreaterEqual = 0 - node2 = CreateNewNode(nextnode); - node2->Info = 0; - node2->Child[0] = actnode; - Write(nextnode); - - node->Parent = nextnode; - Write(actnode); - - node = node2; - actnode = nextnode; - - m_Root = nextnode; - m_sigRootChanged.emit(this, m_Root); - } - - while (actnode) - { - exists = InNodeFind(node, Key, ge); - if (exists) // already exists - { - return iterator(this, actnode, ge); - } else { - if (node->Info & cIsLeafMask) // direct insert to leaf node - { - KeyInsert(actnode, node, ge); - - node->Key[ge] = Key; - - Write(actnode); - - return iterator(this, actnode, ge); - - } else { // middle node - nextnode = node->Child[ge]; - node2 = Read(nextnode); - - if ((node2->Info & cKeyCountMask) == cFullNode) // split the childnode - { - KeyInsert(actnode, node, ge); - SplitNode(nextnode, node2, node->Child[ge], node->Child[ge+1], node->Key[ge], actnode, ge); - - Write(actnode); - if (node->Key[ge] == Key) - { - return iterator(this, actnode, ge); - } else { - if (node->Key[ge] < Key) - { - nextnode = node->Child[ge+1]; - } else { - nextnode = node->Child[ge]; - } - } - - } - actnode = nextnode; - node = Read(actnode); - - } // if (node.Info & cIsLeafMask) - } // if (exists) - } // while (actnode) - - // something went wrong - return iterator(this, 0, 0xFFFF); -} - - -template -typename CBTree::iterator -CBTree::Find(const TKey & Key) -{ - TNode * node; - TNodeRef actnode = m_Root; - uint16_t ge; - - if (!m_Root) return iterator(this, 0, 0xFFFF); - - node = Read(actnode); - - while (actnode) - { - if (InNodeFind(node, Key, ge)) - { - return iterator(this, actnode, ge); - } - - if (!(node->Info & cIsLeafMask)) - { - actnode = node->Child[ge]; - node = Read(actnode); - } else { - actnode = 0; - } - } - - return iterator(this, 0, 0xFFFF); -} - -template -typename CBTree::iterator -CBTree::LowerBound(const TKey & Key) -{ - TNode * node; - TNodeRef actnode = m_Root; - uint16_t ge; - - if (!m_Root) return iterator(this, 0, 0xFFFF); - - node = Read(actnode); - - while (actnode) - { - if (InNodeFind(node, Key, ge)) - { - return iterator(this, actnode, ge); - } - - if (node->Info & cIsLeafMask) - { - if (ge >= (node->Info & cKeyCountMask)) - { - iterator i(this, actnode, ge - 1); - ++i; - return i; - } else { - return iterator(this, actnode, ge); - } - } else { - actnode = node->Child[ge]; - node = Read(actnode); - } - } - - return iterator(this, 0, 0xFFFF); -} - -template -typename CBTree::iterator -CBTree::UpperBound(const TKey & Key) -{ - TNode * node; - TNodeRef actnode = m_Root; - uint16_t ge; - if (!m_Root) return iterator(this, 0, 0xFFFF); - - node = Read(actnode); - - while (actnode) - { - if (InNodeFind(node, Key, ge)) - { - return iterator(this, actnode, ge); - } - - if (node->Info & cIsLeafMask) - { - if (ge == 0) - { - iterator i(this, actnode, 0); - --i; - return i; - } else { - return iterator(this, actnode, ge - 1); - } - } else { - actnode = node->Child[ge]; - node = Read(actnode); - } - } - - return iterator(this, 0, 0xFFFF); -} - -template -bool CBTree::Delete(const TKey& Key) -{ - if (!m_Root) return false; - - TNode *node, *node2, *lnode, *rnode; - - TNodeRef actnode = m_Root; - TNodeRef nextnode, l, r; - bool exists, skipread; - uint16_t ge; - - bool foundininnernode = false; - bool wantleftmost = false; - TNodeRef innernode = 0; - TNode * innernodedata = NULL; - uint16_t innerindex = 0xFFFF; - - node = Read(actnode); - - while (actnode) - { - skipread = false; - - if (foundininnernode) - { - exists = false; - if (wantleftmost) - ge = 0; - else - ge = node->Info & cKeyCountMask; - - } else { - exists = InNodeFind(node, Key, ge); - } - - if (exists) - { - if (node->Info & cIsLeafMask) // delete in leaf - { - KeyDelete(actnode, node, ge); - Write(actnode); - - return true; - - } else { // delete in inner node - l = node->Child[ge]; - r = node->Child[ge+1]; - lnode = Read(l); - rnode = Read(r); - - - if (((rnode->Info & cKeyCountMask) == cEmptyNode) && ((lnode->Info & cKeyCountMask) == cEmptyNode)) - { // merge childnodes and keep going - nextnode = MergeNodes(l, lnode, r, rnode, node->Key[ge], actnode, ge); - - KeyDelete(actnode, node, ge); - node->Child[ge] = nextnode; - - if ((actnode == m_Root) && ((node->Info & cKeyCountMask) == 0)) - { // root node is empty. delete it - DeleteNode(actnode); - m_Root = nextnode; - m_sigRootChanged.emit(this, m_Root); - } else { - Write(actnode); - } - - } else { // need a key-data-pair from a leaf to replace deleted pair -> save position - foundininnernode = true; - innernode = actnode; - innerindex = ge; - innernodedata = node; - - if ((lnode->Info & cKeyCountMask) == cEmptyNode) - { - wantleftmost = true; - nextnode = r; - } else { - wantleftmost = false; - nextnode = l; - } - } - } - - } else if (node->Info & cIsLeafMask) { // we are at the bottom. finish it - if (foundininnernode) - { - if (wantleftmost) - { - KeyMove(actnode, 0, node, innernode, innerindex, innernodedata); - Write(innernode); - - KeyDelete(actnode, node, 0); - Write(actnode); - - } else { - KeyMove(actnode, (node->Info & cKeyCountMask) - 1, node, innernode, innerindex, innernodedata); - Write(innernode); - - //KeyDelete(actnode, node, node.Info & cKeyCountMask); - node->Info--; - Write(actnode); - } - } - return foundininnernode; - - } else { // inner node. go on and check if moving or merging is neccessary - nextnode = node->Child[ge]; - node2 = Read(nextnode); - - if ((node2->Info & cKeyCountMask) == cEmptyNode) // move or merge - { - // set l and r for easier access - if (ge > 0) - { - l = node->Child[ge - 1]; - lnode = Read(l); - } else - l = 0; - - if (ge < (node->Info & cKeyCountMask)) - { - r = node->Child[ge + 1]; - rnode = Read(r); - } else - r = 0; - - if ((r != 0) && ((rnode->Info & cKeyCountMask) > cEmptyNode)) // move a Key-Data-pair from the right - { - // move key-data-pair down from current to the next node - KeyMove(actnode, ge, node, nextnode, node2->Info & cKeyCountMask, node2); - - // move the child from right to next node - node2->Child[(node2->Info & cKeyCountMask) + 1] = rnode->Child[0]; - - // move key-data-pair up from right to current node - KeyMove(r, 0, rnode, actnode, ge, node); - Write(actnode); - - // decrement right node key count and remove the first key-data-pair - KeyDelete(r, rnode, 0); - - // increment KeyCount of the next node - node2->Info++; - - if ((node2->Info & cIsLeafMask) == 0) // update the parent property of moved child - { - TNode * tmp = Read(node2->Child[node2->Info & cKeyCountMask]); - tmp->Parent = nextnode; - Write(node2->Child[node2->Info & cKeyCountMask]); - } - - - Write(r); - Write(nextnode); - node = node2; - skipread = true; - - } else if ((l != 0) && ((lnode->Info & cKeyCountMask) > cEmptyNode)) // move a Key-Data-pair from the left - { - // increment next node key count and make new first key-data-pair - KeyInsert(nextnode, node2, 0); - - // move key-data-pair down from current to the next node - KeyMove(actnode, ge - 1, node, nextnode, 0, node2); - - // move the child from left to next node - node2->Child[0] = lnode->Child[lnode->Info & cKeyCountMask]; - - // move key-data-pair up from left to current node - KeyMove(l, (lnode->Info & cKeyCountMask) - 1, lnode, actnode, ge - 1, node); - Write(actnode); - - // decrement left node key count - lnode->Info--; - Write(l); - - if ((node2->Info & cIsLeafMask) == 0) // update the parent property of moved child - { - TNode * tmp = Read(node2->Child[0]); - tmp->Parent = nextnode; - Write(node2->Child[0]); - } - - Write(nextnode); - node = node2; - skipread = true; - - } else { - if (l != 0) // merge with the left node - { - nextnode = MergeNodes(l, lnode, nextnode, node2, node->Key[ge - 1], actnode, ge - 1); - KeyDelete(actnode, node, ge - 1); - node->Child[ge - 1] = nextnode; - - } else { // merge with the right node - nextnode = MergeNodes(nextnode, node2, r, rnode, node->Key[ge], actnode, ge); - KeyDelete(actnode, node, ge); - node->Child[ge] = nextnode; - } - - if ((actnode == m_Root) && ((node->Info & cKeyCountMask) == 0)) - { - DeleteNode(actnode); - m_Root = nextnode; - m_sigRootChanged(this, nextnode); - } else { - Write(actnode); - } - } - } - } // if (exists) else if (node.Info & cIsLeafMask) - - actnode = nextnode; - if (!skipread) - node = Read(actnode); - - } // while(actnode) - - return false; -} - -template -typename CBTree::TNodeRef CBTree::getRoot() -{ - return m_Root; -} - -template -void CBTree::setRoot(TNodeRef NewRoot) -{ - m_Root = NewRoot; - return; -} - -template -void CBTree::PrepareInsertOperation() -{ - if (m_Count + 64 > m_AllocCount) - { - m_AllocCount += 64; - m_Alloc = (TNode *)realloc(m_Alloc, sizeof(TNode) * m_AllocCount); - - for (TNodeRef i = m_AllocCount - 64; i < m_AllocCount; ++i) - m_Alloc[i].Parent = i + 1; - - m_Alloc[m_AllocCount - 1].Parent = 0; - - if (m_FreeIndex) - { - TNodeRef i = m_FreeIndex; - while (m_Alloc[i].Parent) - i = m_Alloc[i].Parent; - - m_Alloc[i].Parent = m_AllocCount - 64; - - } else { - m_FreeIndex = m_AllocCount - 63; - } - - } -} - -template -typename CBTree::TNode * CBTree::CreateNewNode(TNodeRef & NodeRef) -{ - NodeRef = m_FreeIndex; - m_FreeIndex = m_Alloc[m_FreeIndex].Parent; - m_Count++; - memset(m_Alloc + NodeRef, 0, sizeof(TNode)); - return m_Alloc + NodeRef; -} - -template -void CBTree::DeleteNode(TNodeRef Node) -{ - CHECK((Node > 0) && (Node < m_AllocCount), logERROR, _T("Invalid Node")); - m_Alloc[Node].Parent = m_FreeIndex; - m_FreeIndex = Node; - m_Count--; -} - -template -typename CBTree::TNode * CBTree::Read(TNodeRef Node) -{ - CHECK((Node > 0) && (Node < m_AllocCount), logERROR, _T("Invalid Node")); - return m_Alloc + Node; -} - -template -void CBTree::Write(TNodeRef Node) -{ - return; -} - -template -void CBTree::DestroyTree() -{ - std::stack s; - TNodeRef node; - TNode* nodedata; - uint16_t i; - - if (m_Root) - s.push(m_Root); - while (!s.empty()) - { - node = s.top(); - nodedata = Read(node); - s.pop(); - - if ((nodedata->Info & cIsLeafMask) == 0) - { - for (i = 0; i <= (nodedata->Info & cKeyCountMask); i++) - s.push(nodedata->Child[i]); - } - - DeleteNode(node); - } - - if (m_Alloc) - free(m_Alloc); - m_Alloc = NULL; - m_AllocCount = 0; - m_Count = 0; - m_FreeIndex = 0; -} - - -template -void CBTree::DeleteTree(TDeleteCallback * CallBack, uint32_t Param) -{ - std::stack s; - TNodeRef actnode; - TNode * node; - uint16_t i; - - typename TManagedMap::iterator it = m_ManagedIterators.begin(); - while (it != m_ManagedIterators.end()) - { - it->second->m_Node = 0; - it->second->m_Index = 0xffff; - ++it; - } - - if (m_Root) - s.push(m_Root); - - m_Root = 0; - m_sigRootChanged.emit(this, m_Root); - - while (!s.empty()) - { - actnode = s.top(); - s.pop(); - - node = Read(actnode); - - if ((node->Info & cIsLeafMask) == 0) - { - for (i = 0; i <= (node->Info & cKeyCountMask); i++) - s.push(node->Child[i]); - - } - if (CallBack) - { - for (i = 0; i < (node->Info & cKeyCountMask); i++) - CallBack->emit(this, node->Key[i], Param); - } - - DeleteNode(actnode); - } -} - - - - - - - -template -CBTree::iterator::iterator() -{ - m_Tree = NULL; - m_Node = 0; - m_Index = 0xFFFF; - m_Managed = false; - m_ManagedDeleted = false; - m_LoadedKey = false; -} -template -CBTree::iterator::iterator(CBTree* Tree, TNodeRef Node, uint16_t Index) -{ - m_Tree = Tree; - m_Node = Node; - m_Index = Index; - m_Managed = false; - m_ManagedDeleted = false; - m_LoadedKey = false; -} -template -CBTree::iterator::iterator(const iterator& Other) -{ - m_Tree = Other.m_Tree; - m_Node = Other.m_Node; - m_Index = Other.m_Index; - m_ManagedDeleted = Other.m_ManagedDeleted; - m_Managed = Other.m_Managed; - m_LoadedKey = Other.m_LoadedKey; - m_ManagedKey = Other.m_ManagedKey; - - if (m_Managed) - InsertManaged(); -} - -template -CBTree::iterator::~iterator() -{ - RemoveManaged(m_Node); -} - - -template -void CBTree::iterator::setManaged() -{ - if (!m_Managed) - InsertManaged(); - - m_Managed = true; -} - -template -inline void CBTree::iterator::RemoveManaged(TNodeRef FromNode) -{ - if (m_Managed && m_Tree) - { - typename TManagedMap::iterator i = m_Tree->m_ManagedIterators.find(FromNode); - - while ((i != m_Tree->m_ManagedIterators.end()) && (i->second != this) && (i->first == FromNode)) - ++i; - - if ((i != m_Tree->m_ManagedIterators.end()) && (i->second == this)) - m_Tree->m_ManagedIterators.erase(i); - } -} -template -inline void CBTree::iterator::InsertManaged() -{ - if (m_Tree) - m_Tree->m_ManagedIterators.insert(std::make_pair(m_Node, this)); -} - -template -bool CBTree::iterator::wasDeleted() -{ - return m_ManagedDeleted; -} - -template -void CBTree::iterator::Backup() -{ - if ((!m_ManagedDeleted) && (*this)) - { - TNode * tmp; - if (!m_LoadedKey) - { - tmp = m_Tree->Read(m_Node); - m_ManagedKey = tmp->Key[m_Index]; - } - m_LoadedKey = true; - } - - m_ManagedDeleted = true; -} - -template -CBTree * CBTree::iterator::Tree() -{ - return m_Tree; -} - -template -const TKey& CBTree::iterator::operator *() -{ - if (!m_LoadedKey) - { - TNode * node; - node = m_Tree->Read(m_Node); - m_ManagedKey = node->Key[m_Index]; - m_LoadedKey = true; - } - return m_ManagedKey; -} - -template -const TKey* CBTree::iterator::operator ->() -{ - if (!m_LoadedKey) - { - TNode * node; - node = m_Tree->Read(m_Node); - m_ManagedKey = node->Key[m_Index]; - m_LoadedKey = true; - } - return &m_ManagedKey; -} - -template -inline CBTree::iterator::operator bool() const -{ - if (m_Tree && m_Node) - { - TNode * node; - node = m_Tree->Read(m_Node); - return (m_Index < (node->Info & cKeyCountMask)); - } else - return false; -} - -template -inline bool CBTree::iterator::operator !() const -{ - if (m_Tree && m_Node) - { - TNode * node; - node = m_Tree->Read(m_Node); - return (m_Index > (node->Info & cKeyCountMask)); - } else - return true; -} - -template -inline bool CBTree::iterator::operator ==(iterator & Other) -{ - //return (m_Tree == Other.m_Tree) && (m_Node == Other.m_Node) && (m_Index == Other.m_Index) && (!m_ManagedDeleted) && (!Other.m_ManagedDeleted); - return Key() == Other.Key(); -} - -template -inline bool CBTree::iterator::operator < (iterator & Other) -{ - return Key() < Other.Key(); -} -template -inline bool CBTree::iterator::operator > (iterator & Other) -{ - return Key() > Other.Key(); -} - - -template -typename CBTree::iterator& -CBTree::iterator::operator =(const iterator& Other) -{ - RemoveManaged(m_Node); - - m_Tree = Other.m_Tree; - m_Node = Other.m_Node; - m_Index = Other.m_Index; - m_ManagedDeleted = Other.m_ManagedDeleted; - m_Managed = Other.m_Managed; - m_LoadedKey = Other.m_LoadedKey; - m_ManagedKey = Other.m_ManagedKey; - - if (m_Managed) - InsertManaged(); - - return *this; -} - -template -typename CBTree::iterator& -CBTree::iterator::operator ++() //pre ++i -{ - TNodeRef oldnode = m_Node; - if (m_Managed && m_ManagedDeleted) - { - TKey oldkey = m_ManagedKey; - m_LoadedKey = false; - m_ManagedDeleted = false; - iterator other = m_Tree->LowerBound(m_ManagedKey); - m_Node = other.m_Node; - m_Index = other.m_Index; - while (((**this) == oldkey) && (*this)) - Inc(); - - } else - Inc(); - - if (m_Managed && (oldnode != m_Node)) - { - RemoveManaged(oldnode); - InsertManaged(); - } - return *this; -} - -template -typename CBTree::iterator& -CBTree::iterator::operator --() //pre --i -{ - TNodeRef oldnode = m_Node; - if (m_Managed && m_ManagedDeleted) - { - TKey oldkey = m_ManagedKey; - m_LoadedKey = false; - - m_ManagedDeleted = false; - iterator other = m_Tree->UpperBound(m_ManagedKey); - m_Node = other.m_Node; - m_Index = other.m_Index; - while (((**this) == oldkey) && (*this)) - Dec(); - } else - Dec(); - - if (m_Managed && (oldnode != m_Node)) - { - RemoveManaged(oldnode); - InsertManaged(); - } - return *this; -} - -template -typename CBTree::iterator -CBTree::iterator::operator ++(int) //post i++ -{ - iterator tmp(*this); - ++(*this); - return tmp; -} -template -typename CBTree::iterator -CBTree::iterator::operator --(int) //post i-- -{ - iterator tmp(*this); - --(*this); - return tmp; -} - -template -void CBTree::iterator::Inc() -{ - TNode * node; - TNodeRef nextnode; - node = m_Tree->Read(m_Node); - - m_LoadedKey = false; - - if ((node->Info & cIsLeafMask) && ((node->Info & cKeyCountMask) > m_Index + 1)) // leaf - { - m_Index++; - return; - } - - if ((node->Info & cIsLeafMask) == 0) // inner node. go down - { - m_Node = node->Child[m_Index + 1]; - node = m_Tree->Read(m_Node); - - m_Index = 0; - - while ((node->Info & cIsLeafMask) == 0) // go down to a leaf - { - m_Node = node->Child[0]; - node = m_Tree->Read(m_Node); - } - - return; - } - - while (m_Index >= (node->Info & cKeyCountMask) - 1) // go up - { - if (m_Node == m_Tree->m_Root) // the root is the top, we cannot go further - { - m_Index = 0xFFFF; - m_Node = 0; - return; - } - - nextnode = node->Parent; - node = m_Tree->Read(nextnode); - m_Index = 0; - - while ((m_Index <= (node->Info & cKeyCountMask)) && (node->Child[m_Index] != m_Node)) - m_Index++; - - m_Node = nextnode; - - if (m_Index < (node->Info & cKeyCountMask)) - return; - } - -} - -template -void CBTree::iterator::Dec() -{ - TNode * node; - TNodeRef nextnode; - node = m_Tree->Read(m_Node); - - m_LoadedKey = false; - - if ((node->Info & cIsLeafMask) && (m_Index > 0)) // leaf - { - m_Index--; - return; - } - - if ((node->Info & cIsLeafMask) == 0) // inner node. go down - { - m_Node = node->Child[m_Index]; - node = m_Tree->Read(m_Node); - m_Index = (node->Info & cKeyCountMask) - 1; - - while ((node->Info & cIsLeafMask) == 0) // go down to a leaf - { - m_Node = node->Child[node->Info & cKeyCountMask]; - node = m_Tree->Read(m_Node); - m_Index = (node->Info & cKeyCountMask) - 1; - } - - return; - } - - while (m_Index == 0) // go up - { - if (m_Node == m_Tree->m_Root) // the root is the top, we cannot go further - { - m_Index = 0xFFFF; - m_Node = 0; - return; - } - - nextnode = node->Parent; - node = m_Tree->Read(nextnode); - m_Index = 0; - - while ((m_Index <= (node->Info & cKeyCountMask)) && (node->Child[m_Index] != m_Node)) - m_Index++; - - m_Node = nextnode; - - if (m_Index > 0) - { - m_Index--; - return; - } - } -} diff --git a/plugins/Dbx_tree/BlockManager.cpp b/plugins/Dbx_tree/BlockManager.cpp deleted file mode 100644 index b52298602f..0000000000 --- a/plugins/Dbx_tree/BlockManager.cpp +++ /dev/null @@ -1,965 +0,0 @@ -/* - -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 "BlockManager.h" -#include "Logger.h" - -CBlockManager::CBlockManager( - CFileAccess & FileAccess, - CEncryptionManager & EncryptionManager - ) -: m_BlockSync(), - m_FileAccess(FileAccess), - m_EncryptionManager(EncryptionManager), - m_BlockTable(1024), - m_FreeBlocks() -{ - m_Optimize.Thread = NULL; - m_Optimize.Source = 0; - m_Optimize.Dest = 0; - - m_CacheInfo.Growth = 0; - m_CacheInfo.Size = 0; - m_CacheInfo.LastPurge = time(NULL); - - m_PendingHead = NULL; - m_PendingTail = NULL; - m_PendingLast = NULL; - m_LastFlush = time(NULL); - m_BytesPending = 20; - m_FirstFreeIndex = 0; - - m_SaveMode = true; - m_ReadOnly = m_FileAccess.ReadOnly(); - - memset(m_Cache, 0, sizeof(m_Cache)); -} - -CBlockManager::~CBlockManager() -{ - m_BlockSync.BeginWrite(); - if (m_Optimize.Thread) - { - m_Optimize.Thread->FreeOnTerminate(false); - m_Optimize.Thread->Terminate(); - - m_BlockSync.EndWrite(); - m_Optimize.Thread->WaitFor(); - - delete m_Optimize.Thread; - } else { - m_BlockSync.EndWrite(); - } - - _PendingFlush(true); - - for (uint32_t buddy = 0; buddy < cCacheBuddyCount; buddy++) - { - TCacheEntry * i = m_Cache[buddy]; - while (i) - { - free(i->Cache); - - TCacheEntry * tmp = i; - i = i->Next; - free(tmp); - } - } -} - -// Optimize File Size -void CBlockManager::ExecuteOptimize() -{ /* - TBlockHeadFree h = {0,0}; - uint8_t * buf = (uint8_t*)malloc(1 << 18); // 256kb - uint32_t bufuse = 0; - uint32_t bufsize = 1 << 18; - uint32_t lastflush = 0; - - { - int i = 0; - while (!m_Optimize.Thread->Terminated() && (i < 600)) - { - ++i; - Sleep(100); // wait for Miranda to start - } - } - - TransactionBeginWrite(); - - while (!m_Optimize.Thread->Terminated() && (m_Optimize.Source < m_FileAccess.Size()) && !m_ReadOnly) - { - m_FileAccess.Read(&h, m_Optimize.Source, sizeof(h)); - if (h.ID == cFreeBlockID) - { - _RemoveFreeBlock(m_Optimize.Source, h.Size); - - m_Optimize.Source += h.Size; - } else { - - if (bufsize < bufuse + h.Size) - { - buf = (uint8_t*)realloc(buf, bufuse + h.Size); - bufsize = bufuse + h.Size; - } - m_FileAccess.Read(buf + bufuse, m_Optimize.Source, h.Size); - - m_BlockTable[h.ID >> 2].Addr = (m_Optimize.Dest + bufuse) >> 2; - - m_Optimize.Source += h.Size; - bufuse += h.Size; - } - - if ((m_BlockSync.Waiting() > 0) - || (bufuse + 1024 >= bufsize) - || (m_Optimize.Source >= m_FileAccess.Size())) // buffer is nearly full or EOF - { - if (m_Optimize.Dest != m_Optimize.Source) // move blocks - { - TBlockHeadFree h = {cFreeBlockID, m_Optimize.Source - m_Optimize.Dest}; - TBlockTailFree t = {m_Optimize.Source - m_Optimize.Dest, cFreeBlockID}; - - m_FileAccess.Write(buf, m_Optimize.Dest, bufuse); - - m_FileAccess.Write(&h, m_Optimize.Dest + bufuse, sizeof(h)); - m_FileAccess.Invalidate(m_Optimize.Dest + bufuse + sizeof(h), m_Optimize.Source - m_Optimize.Dest - bufuse - sizeof(h) - sizeof(t)); - m_FileAccess.Write(&t, m_Optimize.Dest + bufuse - sizeof(t), sizeof(t)); - - if (m_SaveMode) - { - m_FileAccess.CloseTransaction(); - m_FileAccess.Flush(); - m_FileAccess.UseJournal(false); - - m_FileAccess.Write(buf, m_Optimize.Dest, bufuse); - - m_FileAccess.Write(&h, m_Optimize.Dest + bufuse, sizeof(h)); - m_FileAccess.Invalidate(m_Optimize.Dest + bufuse + sizeof(h), m_Optimize.Source - m_Optimize.Dest - bufuse - sizeof(h) - sizeof(t)); - m_FileAccess.Write(&t, m_Optimize.Dest + bufuse - sizeof(t), sizeof(t)); - - m_FileAccess.Flush(); - m_FileAccess.CleanJournal(); - m_FileAccess.UseJournal(true); - } - - m_Optimize.Dest += bufuse; - bufuse = 0; - } - - if (m_BlockSync.Waiting() > 0) - { - unsigned int w = m_BlockSync.Waiting(); - m_BlockSync.EndWrite(); - Sleep(w * 64 + 1); - m_BlockSync.BeginWrite(); - m_FileAccess.UseJournal(m_SaveMode); - } - } - } - - if (m_Optimize.Source >= m_FileAccess.Size()) - m_FileAccess.Size(m_Optimize.Dest); - - m_Optimize.Thread = NULL; - m_Optimize.Source = 0; - m_Optimize.Dest = 0; - if (m_SaveMode) - TransactionEndWrite(); - else - m_BlockSync.EndWrite(); - - free(buf); */ - - m_Optimize.Thread = NULL; -} - -inline void CBlockManager::_PendingAdd(uint32_t BlockID, uint32_t Addr, uint32_t Size, TCacheEntry * Cache) -{ - TPendingOperation * p = NULL; - if (BlockID == cFreeBlockID) - { - p = (TPendingOperation*)malloc(sizeof(TPendingOperation)); - - p->BlockID = cFreeBlockID; - p->Addr = Addr; - p->Size = Size; - p->CacheEntry = NULL; - p->EncryptionBuffer = NULL; - - m_BytesPending += 24 + sizeof(TBlockHeadFree) + sizeof(TBlockTailFree); - if (Addr & cPendingInvalidate) - m_BytesPending += 12; - - } else { - if (Cache->Pending) - { - p = Cache->Pending; - _PendingRemove(Cache->Pending, false); - } else { - p = (TPendingOperation*)malloc(sizeof(TPendingOperation)); - } - - p->BlockID = BlockID; - p->Addr = Addr; - p->Size = Size; - p->CacheEntry = Cache; - p->EncryptionBuffer = NULL; - - m_BytesPending += 12 + Size; - - Cache->Pending = p; - } - - p->Next = NULL; - p->Prev = m_PendingTail; - if (m_PendingTail) - m_PendingTail->Next = p; - - m_PendingTail = p; - if (!m_PendingHead) - m_PendingHead = p; -} - -inline void CBlockManager::_PendingRemove(TPendingOperation * Pending, bool Free) -{ - if (Pending->Prev) - Pending->Prev->Next = Pending->Next; - else - m_PendingHead = Pending->Next; - - if (Pending->Next) - Pending->Next->Prev = Pending->Prev; - else - m_PendingTail = Pending->Prev; - - if (Pending->EncryptionBuffer) - free(Pending->EncryptionBuffer); - - if (m_PendingLast == Pending) - m_PendingLast = Pending->Prev; - - Pending->CacheEntry->Pending = NULL; - if (Free) - free(Pending); -} - -inline void CBlockManager::_PendingFlush(bool FullFlush) -{ - TPendingOperation * i = NULL; - - if (m_ReadOnly) - return; - - if (FullFlush) - { - if (m_SaveMode) - { - _PendingFlush(false); // write to journal - m_FileAccess.Flush(); - m_FileAccess.UseJournal(false); - m_FileAccess.Size(m_FileAccess.Size()); // resize real file - } else { - m_FileAccess.UseJournal(false); - } - - i = m_PendingHead; - } else if (m_PendingLast) - { - i = m_PendingLast->Next; - m_FileAccess.UseJournal(m_SaveMode); - } else { - i = m_PendingHead; - m_FileAccess.UseJournal(m_SaveMode); - } - - while (i) - { - if (i->BlockID == cFreeBlockID) - { - uint32_t addr = i->Addr & ~cPendingInvalidate; - if (addr + i->Size <= m_FileAccess.Size()) - { - TBlockHeadFree h = {cFreeBlockID, i->Size}; - TBlockTailFree t = {i->Size, cFreeBlockID}; - - m_FileAccess.Write(&h, addr, sizeof(h)); - if (i->Addr & cPendingInvalidate) - m_FileAccess.Invalidate(addr + sizeof(h), i->Size - sizeof(h) - sizeof(t)); - m_FileAccess.Write(&t, addr + i->Size - sizeof(t), sizeof(t)); - } - - } else { - - if (i->BlockID && !i->EncryptionBuffer && m_EncryptionManager.IsEncrypted(i->BlockID)) - { - i->EncryptionBuffer = (TBlockHeadOcc*) malloc(i->Size); - memcpy(i->EncryptionBuffer, i->CacheEntry->Cache, i->Size); - m_EncryptionManager.Encrypt(i->EncryptionBuffer + 1, i->Size - sizeof(TBlockHeadOcc) - sizeof(TBlockTailOcc), i->BlockID, 0); - } - - if (i->EncryptionBuffer) - { - m_FileAccess.Write(i->EncryptionBuffer, i->Addr, i->Size); - } else { - m_FileAccess.Write(i->CacheEntry->Cache, i->Addr, i->Size); - } - } - - i = i->Next; - } // while - - if (FullFlush) - { - m_FileAccess.Flush(); - if (m_SaveMode) - m_FileAccess.CleanJournal(); - - m_BytesPending = 20; - m_LastFlush = time(NULL); - - i = m_PendingHead; - while (i) - { - if (i->EncryptionBuffer) - free(i->EncryptionBuffer); - - if (i->CacheEntry) - i->CacheEntry->Pending = NULL; - - TPendingOperation * tmp = i; - i = i->Next; - free(tmp); - } - m_PendingHead = NULL; - m_PendingTail = NULL; - m_PendingLast = NULL; - } else { - m_PendingLast = m_PendingTail; - m_FileAccess.CloseTransaction(); - } -} - -inline CBlockManager::TCacheEntry * CBlockManager::_CacheInsert(uint32_t Idx, TBlockHeadOcc * Cache, bool Virtual) -{ - TCacheEntry * res; - uint32_t myidx = ROR_32(Idx, cCacheBuddyBits); - - res = (TCacheEntry *)malloc(sizeof(TCacheEntry)); - res->Cache = Cache; - res->Pending = NULL; - res->Idx = myidx; - res->Forced = Virtual; - - TCacheEntry * volatile * last = &m_Cache[Idx % cCacheBuddyCount]; - TCacheEntry * i; - do { - i = *last; - - while (i && (i->Idx < myidx)) - { - last = &i->Next; - i = i->Next; - } - - if (i && (i->Idx == myidx)) - { - free(res); - free(Cache); - - i->LastUse = time(NULL) >> 2; - return i; - } - - res->Next = i; - - } while (i != CMPXCHG_Ptr(*last, res, i)); - - res->LastUse = time(NULL) >> 2; - - m_BlockTable[Idx].InCache = true; - if (!Virtual) - XADD_32(m_CacheInfo.Growth, res->Cache->Size); - - return res; -} - -inline CBlockManager::TCacheEntry * CBlockManager::_CacheFind(uint32_t Idx) -{ - TCacheEntry * i = m_Cache[Idx % cCacheBuddyCount]; - uint32_t myidx = ROR_32(Idx, cCacheBuddyBits); - while (i && (i->Idx < myidx)) - i = i->Next; - - if (i && (i->Idx == myidx)) - return i; - else - return NULL; -} - -inline void CBlockManager::_CacheErase(uint32_t Idx) -{ - TCacheEntry * i = m_Cache[Idx % cCacheBuddyCount]; - TCacheEntry * volatile * l = &m_Cache[Idx % cCacheBuddyCount]; - - uint32_t myidx = ROR_32(Idx, cCacheBuddyBits); - - while (i->Idx < myidx) - { - l = &i->Next; - i = i->Next; - } - *l = i->Next; - - if (i->Cache) - free(i->Cache); - free(i); -} - -inline void CBlockManager::_CachePurge() -{ - _PendingFlush(true); - - uint32_t ts = time(NULL); - if (m_CacheInfo.Size + m_CacheInfo.Growth > cCachePurgeSize) { - ts = ts - (ts - m_CacheInfo.LastPurge) * cCachePurgeSize / (m_CacheInfo.Size + 2 * m_CacheInfo.Growth); - } else if (m_CacheInfo.Growth > m_CacheInfo.Size) - { - ts = ts - (ts - m_CacheInfo.LastPurge) * m_CacheInfo.Size / m_CacheInfo.Growth; - } else if (m_CacheInfo.Size > m_CacheInfo.Growth) - { - ts = ts - (ts - m_CacheInfo.LastPurge) * m_CacheInfo.Growth / m_CacheInfo.Size; - } else { - ts = m_CacheInfo.LastPurge; - } - - m_CacheInfo.Size += m_CacheInfo.Growth; - m_CacheInfo.Growth = 0; - m_CacheInfo.LastPurge = time(NULL); - - for (uint32_t buddy = 0; buddy < cCacheBuddyCount; buddy++) - { - TCacheEntry * i = m_Cache[buddy]; - TCacheEntry * volatile * l = &m_Cache[buddy]; - - while (i) - { - if (!i->Forced && !i->KeepInCache && i->Idx && ((i->LastUse << 2) < ts)) - { - uint32_t idx = ROL_32(i->Idx, cCacheBuddyBits); - m_CacheInfo.Size -= i->Cache->Size; - m_BlockTable[idx].InCache = false; - free(i->Cache); - - *l = i->Next; - TCacheEntry * tmp = i; - i = i->Next; - free(tmp); - - } else { - l = &i->Next; - i = i->Next; - } - } - } -} - -inline uint32_t CBlockManager::_GetAvailableIndex() -{ - uint32_t id; - if (m_FirstFreeIndex) - { - id = m_FirstFreeIndex; - m_FirstFreeIndex = m_BlockTable[id].Addr; - TBlockTableEntry b = {false, false, 0}; - m_BlockTable[id] = b; - } else { - id = static_cast(m_BlockTable.size()); - if (id > (1 << 12)) - m_BlockTable.resize(id + (1 << 12)); - else - m_BlockTable.resize(id * 2); - - for (uint32_t i = static_cast(m_BlockTable.size() - 1); i > id; --i) - { - TBlockTableEntry b = {true, true, m_FirstFreeIndex}; - m_BlockTable[i] = b; - m_FirstFreeIndex = i; - } - } - return id; -} - -inline void CBlockManager::_InsertFreeBlock(uint32_t Addr, uint32_t Size, bool InvalidateData, bool Reuse) -{ - if (Addr + Size == m_FileAccess.Size()) - { - if (Reuse) // in FindFreePosition we would want to use that block - m_FileAccess.Size(Addr); - } else { - - if (Reuse) - m_FreeBlocks.insert(std::make_pair(Size, Addr)); - - if (!m_ReadOnly) - _PendingAdd(cFreeBlockID, InvalidateData ? Addr | cPendingInvalidate : Addr, Size, NULL); - - } -} - -inline void CBlockManager::_RemoveFreeBlock(uint32_t Addr, uint32_t Size) -{ - TFreeBlockMap::iterator i = m_FreeBlocks.find(Size); - while ((i != m_FreeBlocks.end()) && (i->first == Size)) - { - if (i->second == Addr) - { - m_FreeBlocks.erase(i); - i = m_FreeBlocks.end(); - } else { - ++i; - } - } -} - -inline uint32_t CBlockManager::_FindFreePosition(uint32_t Size) -{ - // try to find free block - TFreeBlockMap::iterator f; - TFreeBlockMap::iterator e = m_FreeBlocks.end(); - - if (m_FreeBlocks.size()) - { - f = m_FreeBlocks.find(Size); - if (f == e) - { - if (m_FreeBlocks.rbegin()->first > Size * 2) - { - f = m_FreeBlocks.end(); - --f; - } - } - } else { - f = e; - } - - uint32_t addr = 0; - - if (f == e) // no block found - expand file - { - addr = m_FileAccess.Size(); - m_FileAccess.Size(addr + Size); - - } else { - addr = f->second; - - if (f->first != Size) - { - _InsertFreeBlock(addr + Size, f->first - Size, false, true); - } - _InsertFreeBlock(addr, Size, false, false); - - m_FreeBlocks.erase(f); - } - - return addr; -} - -inline bool CBlockManager::_InitOperation(uint32_t BlockID, uint32_t & Addr, TCacheEntry * & Cache) -{ - if (!BlockID || (BlockID & 3) || ((BlockID >> 2) >= m_BlockTable.size())) - return false; - - uint32_t idx = BlockID >> 2; - TBlockTableEntry dat = m_BlockTable[idx]; - - if (dat.Deleted) // deleted or FreeIDList item - return false; - - Addr = dat.Addr << 2; - if (dat.InCache) - { - Cache = _CacheFind(idx); - } else if (Addr) - { - TBlockHeadOcc h; - - m_FileAccess.Read(&h, Addr, sizeof(h)); - - TBlockHeadOcc * block = (TBlockHeadOcc *) malloc(h.Size); - m_FileAccess.Read(block, Addr, h.Size); - - m_EncryptionManager.Decrypt(block + 1, h.Size - sizeof(TBlockHeadOcc) - sizeof(TBlockTailOcc), BlockID, 0); - - Cache = _CacheInsert(idx, block, false); - } else { - return false; - } - - return Cache != NULL; -} - -inline void CBlockManager::_UpdateBlock(uint32_t BlockID, TCacheEntry * CacheEntry, uint32_t Addr) -{ - CacheEntry->KeepInCache = m_ReadOnly; - - if (!CacheEntry->Forced) - { - if (!m_ReadOnly) - _PendingAdd(BlockID, Addr, CacheEntry->Cache->Size, CacheEntry); - } -} - - -uint32_t CBlockManager::ScanFile(uint32_t FirstBlockStart, uint32_t HeaderSignature, uint32_t FileSize) -{ - TBlockHeadOcc h, lasth = {0, 0, 0}; - uint32_t p; - uint32_t res = 0; - bool invalidateblock = false; - - p = FirstBlockStart; - m_FirstBlockStart = FirstBlockStart; - m_Optimize.Source = 0; - m_Optimize.Dest = 0; - - { // insert header cache element - void * header = malloc(FirstBlockStart); - m_FileAccess.Read(header, 0, FirstBlockStart); - _CacheInsert(0, (TBlockHeadOcc*)header, false); - } - - TransactionBeginWrite(); - - while (p < FileSize) - { - m_FileAccess.Read(&h, p, sizeof(h)); - if (CLogger::Instance().Level() >= CLogger::logERROR || !h.Size) - { - LOG(logCRITICAL, _T("Block-structure of file is corrupt!")); - return 0; - } - - if (h.ID == cFreeBlockID) - { - if (m_Optimize.Dest == 0) - m_Optimize.Dest = p; - - if (lasth.ID == cFreeBlockID) - { - lasth.Size += h.Size; - invalidateblock = true; - } else { - lasth = h; - } - - } else { - - if (lasth.ID == cFreeBlockID) - { - if (m_Optimize.Source == 0) - m_Optimize.Source = p; - - _InsertFreeBlock(p - lasth.Size, lasth.Size, invalidateblock, true); - } - lasth = h; - invalidateblock = false; - - while ((h.ID >> 2) >= m_BlockTable.size()) - m_BlockTable.resize(m_BlockTable.size() << 1); - - m_BlockTable[h.ID >> 2].Addr = p >> 2; - - if (h.Signature == HeaderSignature) - res = h.ID; - } - - p = p + h.Size; - } - - m_FirstFreeIndex = 0; - for (uint32_t i = static_cast(m_BlockTable.size() - 1); i > 0; --i) - { - if (m_BlockTable[i].Addr == 0) - { - TBlockTableEntry b = {true, true, m_FirstFreeIndex}; - m_BlockTable[i] = b; - m_FirstFreeIndex = i; - } - } - - TransactionEndWrite(); - - if (m_Optimize.Source && !m_FileAccess.ReadOnly()) - { - m_Optimize.Thread = new COptimizeThread(*this); - m_Optimize.Thread->Priority(CThread::tpLowest); - m_Optimize.Thread->FreeOnTerminate(true); - m_Optimize.Thread->Resume(); - } - - return res; -} - -void * CBlockManager::_CreateBlock(uint32_t & BlockID, const uint32_t Signature, uint32_t Size) -{ - uint32_t idx = _GetAvailableIndex(); - BlockID = idx << 2; - - Size = m_EncryptionManager.AlignSize(BlockID, (Size + 3) & 0xfffffffc); // align on cipher after we aligned on 4 bytes - - TBlockHeadOcc h = {BlockID, Size + sizeof(TBlockHeadOcc) + sizeof(TBlockTailOcc), Signature}; - TBlockTailOcc t = {BlockID}; - - TBlockHeadOcc * block = (TBlockHeadOcc*) malloc(Size + sizeof(h) + sizeof(t)); - *block = h; - memset(block + 1, 0, Size); - *(TBlockTailOcc*)(((uint8_t*)(block + 1)) + Size) = t; - - TCacheEntry * ce = _CacheInsert(idx, block, false); - - if (m_ReadOnly) - { - TBlockTableEntry b = {false, true, 0}; - m_BlockTable[idx] = b; - } else { - uint32_t addr = _FindFreePosition(Size + sizeof(h) + sizeof(t)); - TBlockTableEntry b = {false, true, addr >> 2 }; - m_BlockTable[idx] = b; - - _UpdateBlock(BlockID, ce, addr); - } - - return ce->Cache + 1; -} - -void * CBlockManager::_CreateBlockVirtual(uint32_t & BlockID, const uint32_t Signature, uint32_t Size) -{ - uint32_t idx = _GetAvailableIndex(); - BlockID = idx << 2; - - Size = m_EncryptionManager.AlignSize(BlockID, (Size + 3) & 0xfffffffc); // align on cipher after we aligned on 4 bytes - - TBlockHeadOcc h = {BlockID, Size + sizeof(TBlockHeadOcc) + sizeof(TBlockTailOcc), Signature}; - TBlockTailOcc t = {BlockID}; - - TBlockHeadOcc * block = (TBlockHeadOcc*) malloc(Size + sizeof(h) + sizeof(t)); - *block = h; - memset(block + 1, 0, Size); - *(TBlockTailOcc*)(((uint8_t*)(block + 1)) + Size) = t; - - return _CacheInsert(idx, block, true)->Cache + 1; -} - -bool CBlockManager::DeleteBlock(uint32_t BlockID) -{ - uint32_t idx = BlockID >> 2; - uint32_t addr; - uint32_t size; - TCacheEntry * ce; - if (!_InitOperation(BlockID, addr, ce)) - return false; - - if (!ce->Forced) - XADD_32(m_CacheInfo.Size, 0 - ce->Cache->Size); - - if (ce->Pending) - _PendingRemove(ce->Pending, true); - - size = ce->Cache->Size; - _CacheErase(idx); - - if (addr == 0) // Block in memory only - { - TBlockTableEntry b = {false, false, 0}; - m_BlockTable[idx] = b; - - } else if (m_ReadOnly) - { - m_BlockTable[idx].Deleted = true; - m_BlockTable[idx].InCache = false; - } else { - _InsertFreeBlock(addr, size, true, true); - - TBlockTableEntry b = {false, false, 0}; - m_BlockTable[idx] = b; - } - - return true; -} - -uint32_t CBlockManager::_ResizeBlock(uint32_t BlockID, void * & Buffer, uint32_t Size) -{ - uint32_t idx = BlockID >> 2; - uint32_t addr; - TCacheEntry * ce; - - if (Size == 0) - return 0; - - if (!_InitOperation(BlockID, addr, ce)) - return 0; - - Size = m_EncryptionManager.AlignSize(BlockID, (Size + 3) & 0xfffffffc); // align on cipher after we aligned on 4 bytes - - uint32_t os = ce->Cache->Size; - uint32_t ns = Size + sizeof(TBlockHeadOcc) + sizeof(TBlockTailOcc); - if (ns == ce->Cache->Size) - { - Buffer = ce->Cache + 1; - return Size; - } - - ce->Cache = (TBlockHeadOcc*) realloc(ce->Cache, ns); - ce->Cache->Size = ns; - TBlockTailOcc t = {BlockID}; - *(TBlockTailOcc*)(((uint8_t*)(ce->Cache + 1)) + Size) = t; - XADD_32(m_CacheInfo.Size, ns - os); - - Buffer = ce->Cache + 1; - ce->KeepInCache = m_ReadOnly; - - if (!m_ReadOnly && addr) - { - _InsertFreeBlock(addr, os, true, true); - addr = _FindFreePosition(ns); - m_BlockTable[idx].Addr = addr >> 2; - - _UpdateBlock(BlockID, ce, addr); // write down - } - - return Size; -} - -bool CBlockManager::IsForcedVirtual(uint32_t BlockID) -{ - TCacheEntry * ce = _CacheFind(BlockID >> 2); - return ce && ce->Forced; -} - -bool CBlockManager::WriteBlockToDisk(uint32_t BlockID) -{ - uint32_t addr; - TCacheEntry * ce; - - if (!_InitOperation(BlockID, addr, ce)) - return false; - - if (!ce->Forced) - return true; - - ce->Forced = false; - XADD_32(m_CacheInfo.Size, ce->Cache->Size); - - if (!m_ReadOnly) - { - addr = _FindFreePosition(ce->Cache->Size); - m_BlockTable[BlockID >> 2].Addr = addr >> 2; - _UpdateBlock(BlockID, ce, addr); - } - return true; -} - -bool CBlockManager::MakeBlockVirtual(uint32_t BlockID) -{ - uint32_t addr; - TCacheEntry * ce; - - if (!_InitOperation(BlockID, addr, ce)) - return false; - - if (ce->Forced) - return true; - - if (ce->Pending) // don't write down, we kill it anyway - _PendingRemove(ce->Pending, true); - - ce->Forced = true; - XADD_32(m_CacheInfo.Size, 0 - ce->Cache->Size); - - if (!m_ReadOnly) - { - _InsertFreeBlock(addr, ce->Cache->Size, true, true); - m_BlockTable[BlockID >> 2].Addr = 0; - } - return true; -} - -void * CBlockManager::_ReadBlock(uint32_t BlockID, uint32_t & Size, uint32_t & Signature) -{ - uint32_t addr; - TCacheEntry * ce; - - if ((BlockID == 0) && (Signature == -1)) - { - Size = m_FirstBlockStart; - return m_Cache[0]->Cache; - } - - if (!_InitOperation(BlockID, addr, ce)) - return NULL; - - if ((Signature != 0) && (Signature != ce->Cache->Signature)) - { - Signature = ce->Cache->Signature; - return NULL; - } - Signature = ce->Cache->Signature; - - if ((Size != 0) && (Size != ce->Cache->Size - sizeof(TBlockHeadOcc) - sizeof(TBlockTailOcc))) - { - Size = ce->Cache->Size - sizeof(TBlockHeadOcc) - sizeof(TBlockTailOcc); - return NULL; - } - Size = ce->Cache->Size - sizeof(TBlockHeadOcc) - sizeof(TBlockTailOcc); - - return ce->Cache + 1; -} - -bool CBlockManager::UpdateBlock(uint32_t BlockID, uint32_t Signature) -{ - uint32_t addr; - TCacheEntry * ce; - - if ((BlockID == 0) && (Signature == -1)) - { - if (!m_ReadOnly) - _PendingAdd(0, 0, m_FirstBlockStart, m_Cache[0]); - - return true; - } - - if (!_InitOperation(BlockID, addr, ce)) - return false; - - if (Signature) - ce->Cache->Signature = Signature; - - _UpdateBlock(BlockID, ce, addr); - - return true; -} - -// make file writeable: -// write all cached blocks to file and check for the old addresses -// remove virtual only from file -// update m_FreeBlocks along the way - diff --git a/plugins/Dbx_tree/BlockManager.h b/plugins/Dbx_tree/BlockManager.h deleted file mode 100644 index dcccd4f0b9..0000000000 --- a/plugins/Dbx_tree/BlockManager.h +++ /dev/null @@ -1,401 +0,0 @@ -/* - -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. - -*/ - -#pragma once - -#include -#include -#include - -#include "stdint.h" -#include "FileAccess.h" -#include "EncryptionManager.h" -#include "MREWSync.h" -#include "Thread.h" -#include "intrinsics.h" - -class CBlockManager -{ -protected: - static const uint32_t cFreeBlockID = 0xFFFFFFFF; - - static const uint32_t cJournalFlushBytes = (1 << 20) - 2048; // flush before reserved journal-space is exhausted - static const uint32_t cJournalFlushTimeout = 300; // journal flush every 5 minutes - - static const uint32_t cCacheBuddyBits = 10; - static const uint32_t cCacheBuddyCount = 1 << cCacheBuddyBits; // count of static allocated buddy nodes - static const uint32_t cCacheBuddyCheck = 0xffffffff << cCacheBuddyBits; - - static const uint32_t cCacheMinimumTimeout = 2; // purge less than every n seconds (high priority) - static const uint32_t cCacheMaximumTimeout = 600; // purge every 10 minutes (high priority) - static const uint32_t cCachePurgeSize = 1 << 21; // cache up to 2MB - static const uint32_t cCacheMinimumGrowthForPurge = 1 << 19; // cache only when 512kb were added - - #pragma pack(push, 1) // push current alignment to stack, set alignment to 1 byte boundary - - typedef struct TBlockHeadFree { - uint32_t ID; - uint32_t Size; - } TBlockHeadFree; - typedef struct TBlockHeadOcc { - uint32_t ID; - uint32_t Size; - uint32_t Signature; /// if occupied block - } TBlockHeadOcc; - - typedef struct TBlockTailOcc { - uint32_t ID; - } TBlockTailOcc; - - typedef struct TBlockTailFree { - uint32_t Size; /// if free block - uint32_t ID; - } TBlockTailFree; - - #pragma pack(pop) - - //////////////////////////////////////////////////////////////////////////////////////////////////// - /// Block table entry. - /// - /// Addr Deleted InCache Meaning - /// 0 0 0 successfully deleted block - /// 0 0 1 virtual only block (either forced virtual or created on a read-only file) - /// 0 1 0 invalid - /// 0 1 1 FreeID list (last entry) - /// set 0 0 Normal in-file block - /// set 0 1 in file and cache (normal cache which could differ on a read-only file or forced virtual out of a read-only file - check TCacheEntry) - /// set 1 0 deleted block or a read-only file - /// set 1 1 FreeID list entry - /// - /// Michael "Protogenes" Kunz, 07.09.2010. - //////////////////////////////////////////////////////////////////////////////////////////////////// - typedef struct TBlockTableEntry { - uint32_t Deleted : 1; ///< Flag is set if the block was deleted but can't be removed, because the file is read-only - uint32_t InCache : 1; ///< Flag is set if block is in the cache (either forced virtual or from the file) - uint32_t Addr : 30; ///< The Offset in the file div 4, so we can address files up to 4GB - } TBlockTableEntry; - std::vector m_BlockTable; - - struct TPendingOperation; - typedef struct TCacheEntry { - TCacheEntry * volatile Next; - TBlockHeadOcc * volatile Cache; - TPendingOperation * Pending; - - uint32_t Idx; - uint32_t Forced : 1; - uint32_t KeepInCache : 1; - uint32_t LastUse : 30; - } TCacheEntry; - - TCacheEntry * m_Cache[cCacheBuddyCount]; - - struct { - uint32_t volatile Size; - uint32_t volatile Growth; - uint32_t volatile LastPurge; - } m_CacheInfo; - - CFileAccess & m_FileAccess; - CEncryptionManager & m_EncryptionManager; - CMultiReadExclusiveWriteSynchronizer m_BlockSync; - - uint32_t m_FirstBlockStart; - bool m_SaveMode; - bool m_ReadOnly; - - typedef std::multimap TFreeBlockMap; - TFreeBlockMap m_FreeBlocks; - uint32_t m_FirstFreeIndex; - - static const uint32_t cPendingInvalidate = 0x00000001; - typedef struct TPendingOperation { - TPendingOperation * Next; ///< The next - TPendingOperation * Prev; ///< The previous - uint32_t BlockID; ///< Identifier for the block - uint32_t Addr; ///< The address in the file - uint32_t Size; ///< The size of the block - TCacheEntry * CacheEntry; ///< The cache entry - TBlockHeadOcc * EncryptionBuffer; ///< Buffer for encrypted block - } TPendingOperation; - - TPendingOperation * m_PendingHead; ///< The double linked list head - TPendingOperation * m_PendingTail; ///< The double linked list tail - TPendingOperation * m_PendingLast; ///< The last processed item - - uint32_t m_LastFlush; ///< The last flush timestamp - uint32_t m_BytesPending; ///< The bytes pending for write - - class COptimizeThread : public CThread - { - protected: - CBlockManager & m_Owner; - void Execute() { m_Owner.ExecuteOptimize(); }; - public: - COptimizeThread(CBlockManager & Owner) : CThread(true), m_Owner(Owner) {}; - ~COptimizeThread() {}; - }; - - struct { - uint32_t Source; - uint32_t Dest; - COptimizeThread * Thread; - } m_Optimize; - void ExecuteOptimize(); - - uint32_t _GetAvailableIndex(); - void _InsertFreeBlock(uint32_t Addr, uint32_t Size, bool InvalidateData, bool Reuse); - void _RemoveFreeBlock(uint32_t Addr, uint32_t Size); - uint32_t _FindFreePosition(uint32_t Size); - - bool _InitOperation(uint32_t BlockID, uint32_t & Addr, TCacheEntry * & Cache); - void _UpdateBlock(uint32_t BlockID, TCacheEntry * CacheEntry, uint32_t Addr); - - void * _ReadBlock(uint32_t BlockID, uint32_t & Size, uint32_t & Signature); - void * _CreateBlock(uint32_t & BlockID, const uint32_t Signature, uint32_t Size); - void * _CreateBlockVirtual(uint32_t & BlockID, const uint32_t Signature, uint32_t Size); - uint32_t _ResizeBlock(uint32_t BlockID, void * & Buffer, uint32_t Size); - - TCacheEntry * _CacheInsert(uint32_t Idx, TBlockHeadOcc * Cache, bool Virtual); - TCacheEntry * _CacheFind(uint32_t Idx); - void _CacheErase(uint32_t Idx); - - void _CachePurge(); - void _PendingAdd(uint32_t BlockID, uint32_t Addr, uint32_t Size, TCacheEntry * Cache); - void _PendingRemove(TPendingOperation * Pending, bool Free); - void _PendingFlush(bool FullFlush); - - - - void TransactionBeginRead() - { - m_BlockSync.BeginRead(); - }; - - void TransactionEndRead() - { - m_BlockSync.EndRead(); - }; - - void TransactionBeginWrite() - { - m_BlockSync.BeginWrite(); - m_FileAccess.UseJournal(m_SaveMode); - }; - - void TransactionEndWrite() - { - if (m_BlockSync.WriteRecursionCount() == 1) - { - m_FileAccess.CompleteTransaction(); - m_BytesPending += 12; - - if ((m_CacheInfo.LastPurge + cCacheMaximumTimeout < time(NULL)) - || ((m_CacheInfo.Size + m_CacheInfo.Growth > cCachePurgeSize) - && (m_CacheInfo.Growth > cCacheMinimumGrowthForPurge) - && (m_CacheInfo.LastPurge + cCacheMinimumTimeout < time(NULL)))) - { - _CachePurge(); - } else if ((m_BytesPending >= cJournalFlushBytes) || (time(NULL) > m_LastFlush + cJournalFlushTimeout)) - { - _PendingFlush(true); - } else { - _PendingFlush(false); - } - } - - m_BlockSync.EndWrite(); - }; -public: - CBlockManager(CFileAccess & FileAccess, CEncryptionManager & EncryptionManager); - ~CBlockManager(); - - - class ReadTransaction - { - private: - CBlockManager * m_Owner; - uint32_t volatile * m_RefCount; - bool m_Closed; - public: - ReadTransaction() - : m_Owner(NULL), - m_RefCount(NULL), - m_Closed(true) - { - - }; - ReadTransaction(CBlockManager & BlockManager) - : m_Owner(&BlockManager), - m_RefCount(new uint32_t(1)), - m_Closed(false) - { - m_Owner->TransactionBeginRead(); - }; - ReadTransaction(const ReadTransaction & Other) - : m_Owner(Other.m_Owner), - m_RefCount(Other.m_RefCount), - m_Closed(Other.m_Closed) - { - if (!m_Closed) - INC_32(*m_RefCount); - }; - ~ReadTransaction() - { - if (!m_Closed && (DEC_32(*m_RefCount) == 0)) - { - delete m_RefCount; - m_Owner->TransactionEndRead(); - } - }; - - ReadTransaction & operator =(const ReadTransaction & Other) - { - if (!m_Closed && (DEC_32(*m_RefCount) == 0)) - { - delete m_RefCount; - m_Owner->TransactionEndRead(); - } - - m_Owner = Other.m_Owner; - m_RefCount = Other.m_RefCount; - m_Closed = Other.m_Closed; - if (!m_Closed) - INC_32(*m_RefCount); - - return *this; - } - - void Close() - { - if (!m_Closed && (DEC_32(*m_RefCount) == 0)) - { - delete m_RefCount; - m_Owner->TransactionEndRead(); - } - m_Closed = true; - } - - }; - class WriteTransaction - { - private: - CBlockManager * m_Owner; - uint32_t volatile * m_RefCount; - bool m_Closed; - public: - WriteTransaction() - : m_Owner(NULL), - m_RefCount(NULL), - m_Closed(true) - { - - }; - WriteTransaction(CBlockManager & BlockManager) - : m_Owner(&BlockManager), - m_RefCount(new uint32_t(1)), - m_Closed(false) - { - m_Owner->TransactionBeginWrite(); - }; - WriteTransaction(const WriteTransaction & Other) - : m_Owner(Other.m_Owner), - m_RefCount(Other.m_RefCount), - m_Closed(Other.m_Closed) - { - if (!m_Closed) - INC_32(*m_RefCount); - }; - ~WriteTransaction() - { - if (!m_Closed && (DEC_32(*m_RefCount) == 0)) - { - delete m_RefCount; - m_Owner->TransactionEndWrite(); - } - }; - - WriteTransaction & operator =(const WriteTransaction & Other) - { - if (!m_Closed && (DEC_32(*m_RefCount) == 0)) - { - delete m_RefCount; - m_Owner->TransactionEndWrite(); - } - - m_Owner = Other.m_Owner; - m_RefCount = Other.m_RefCount; - m_Closed = Other.m_Closed; - if (!m_Closed) - INC_32(*m_RefCount); - - return *this; - } - - void Close() - { - if (!m_Closed && (DEC_32(*m_RefCount) == 0)) - { - delete m_RefCount; - m_Owner->TransactionEndWrite(); - } - m_Closed = true; - } - - }; - - uint32_t ScanFile(uint32_t FirstBlockStart, uint32_t HeaderSignature, uint32_t FileSize); - - template - BlockType * ReadBlock(uint32_t BlockID, uint32_t & Size, uint32_t & Signature) - { - return reinterpret_cast(_ReadBlock(BlockID, Size, Signature)); - }; - - template - BlockType * CreateBlock(uint32_t & BlockID, const uint32_t Signature, uint32_t Size = sizeof(BlockType)) - { - return reinterpret_cast(_CreateBlock(BlockID, Signature, Size)); - }; - - template - BlockType * CreateBlockVirtual(uint32_t & BlockID, const uint32_t Signature, uint32_t Size = sizeof(BlockType)) - { - return reinterpret_cast(_CreateBlockVirtual(BlockID, Signature, Size)); - }; - - template - uint32_t ResizeBlock(uint32_t BlockID, BlockType * & Buffer, uint32_t Size) - { - void * tmp = Buffer; - uint32_t res = _ResizeBlock(BlockID, tmp, Size); - Buffer = reinterpret_cast(tmp); - return res; - }; - - bool UpdateBlock(uint32_t BlockID, uint32_t Signature = 0); - bool DeleteBlock(uint32_t BlockID); - - bool IsForcedVirtual(uint32_t BlockID); - bool WriteBlockToDisk(uint32_t BlockID); - bool MakeBlockVirtual(uint32_t BlockID); -}; diff --git a/plugins/Dbx_tree/Compatibility.cpp b/plugins/Dbx_tree/Compatibility.cpp deleted file mode 100644 index 759e44012c..0000000000 --- a/plugins/Dbx_tree/Compatibility.cpp +++ /dev/null @@ -1,799 +0,0 @@ -/* - -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 "Compatibility.h" -#include "Logger.h" -#define DB_NOHELPERFUNCTIONS -#include "m_database.h" -#include "m_db_int.h" -#undef DB_NOHELPERFUNCTIONS -#ifndef _MSC_VER -#include "savestrings_gcc.h" -#endif - -HANDLE gEvents[6] = {0,0,0,0,0,0}; - -HANDLE hEventDeletedEvent, - hEventAddedEvent, - hEventFilterAddedEvent, - hSettingChangeEvent, - hContactDeletedEvent, - hContactAddedEvent; - -STDMETHODIMP_(HANDLE) CDataBase::AddContact(void) -{ - TDBTEntity entity = {0,0,0,0}; - entity.hParentEntity = DBEntityGetRoot(0, 0); - entity.hAccountEntity = entity.hParentEntity; - - TDBTEntityHandle res = gDataBase->getEntities().CreateEntity(entity); - if (res == DBT_INVALIDPARAM) - return (HANDLE)1; - - NotifyEventHooks(hContactAddedEvent, res, 0); - return (HANDLE)res; -} - -STDMETHODIMP_(LONG) CDataBase::DeleteContact(HANDLE hContact) -{ - NotifyEventHooks(hContactDeletedEvent, (WPARAM)hContact, 0); - - int res = DBEntityDelete((WPARAM)hContact, 0); - if (res == DBT_INVALIDPARAM) - return 1; - - return res; -} - -STDMETHODIMP_(BOOL) CDataBase::IsDbContact(HANDLE hContact) -{ - int flags = DBEntityGetFlags((WPARAM)hContact, 0); - return (flags != DBT_INVALIDPARAM) && - ((flags & DBT_NFM_SpecialEntity) == 0); -} - -STDMETHODIMP_(LONG) CDataBase::GetContactCount(void) -{ - TDBTEntityIterFilter f = {0,0,0,0}; - f.cbSize = sizeof(f); - f.fDontHasFlags = DBT_NF_IsGroup | DBT_NF_IsVirtual | DBT_NF_IsAccount | DBT_NF_IsRoot; - f.Options = DBT_NIFO_OSC_AC | DBT_NIFO_OC_AC; - - TDBTEntityIterationHandle hiter = DBEntityIterInit((WPARAM)&f, gDataBase->getEntities().getRootEntity()); - int c = 0; - if ((hiter != 0) && (hiter != DBT_INVALIDPARAM)) - { - TDBTEntityHandle con = DBEntityIterNext(hiter, 0); - - while ((con != DBT_INVALIDPARAM) && (con != 0)) - { - if ((con != 0) && (con != DBT_INVALIDPARAM)) - c++; - - con = DBEntityIterNext(hiter, 0); - } - DBEntityIterClose(hiter, 0); - } - return c; -} - -//!!!!!!!!!!!!!!!!!!!! szProto ignored -STDMETHODIMP_(HANDLE) CDataBase::FindFirstContact(const char* szProto) -{ - return (HANDLE)gDataBase->getEntities().compFirstContact(); -} - -//!!!!!!!!!!!!!!!!!!!! szProto ignored -STDMETHODIMP_(HANDLE) CDataBase::FindNextContact(HANDLE hContact, const char* szProto) -{ - return (HANDLE)gDataBase->getEntities().compNextContact((WPARAM)hContact); -} - -STDMETHODIMP_(BOOL) CDataBase::GetContactSetting(HANDLE hContact, DBCONTACTGETSETTING *dbcgs) -{ - dbcgs->pValue->type = 0; - - char namebuf[512]; - namebuf[0] = 0; - - if (!(dbcgs->szModule || dbcgs->szSetting)) - return -1; - - if (dbcgs->szModule) - strcpy_s(namebuf, dbcgs->szModule); - strcat_s(namebuf, "/"); - if (dbcgs->szSetting) - strcat_s(namebuf, dbcgs->szSetting); - - TDBTSettingDescriptor desc = {0,0,0,0,0,0,0,0}; - TDBTSetting set = {0,0,0,0}; - desc.cbSize = sizeof(desc); - desc.Entity = (WPARAM)hContact; - desc.pszSettingName = namebuf; - - set.cbSize = sizeof(set); - set.Descriptor = &desc; - - if (DBSettingRead(reinterpret_cast(&set), 0) == DBT_INVALIDPARAM) - return -1; - - switch (set.Type) - { - case DBT_ST_ANSI: - { - dbcgs->pValue->type = DBVT_ASCIIZ; - dbcgs->pValue->pszVal = set.Value.pAnsi; - dbcgs->pValue->cchVal = set.Value.Length - 1; - } break; - case DBT_ST_UTF8: - { - dbcgs->pValue->type = DBVT_WCHAR; - dbcgs->pValue->pwszVal = mir_utf8decodeW(set.Value.pUTF8); - if (dbcgs->pValue->pwszVal) - dbcgs->pValue->cchVal = static_cast(wcslen(dbcgs->pValue->pwszVal)); - else - dbcgs->pValue->cchVal = 0; - mir_free(set.Value.pUTF8); - } break; - case DBT_ST_WCHAR: - { - dbcgs->pValue->type = DBVT_WCHAR; - dbcgs->pValue->pwszVal = set.Value.pWide; - dbcgs->pValue->cchVal = set.Value.Length - 1; - } break; - case DBT_ST_BLOB: - { - dbcgs->pValue->type = DBVT_BLOB; - dbcgs->pValue->pbVal = set.Value.pBlob; - dbcgs->pValue->cpbVal = set.Value.Length; - } break; - case DBT_ST_BOOL: - { - dbcgs->pValue->type = DBVT_BYTE; - dbcgs->pValue->bVal = (uint8_t)set.Value.Bool; - } break; - case DBT_ST_BYTE: case DBT_ST_CHAR: - { - dbcgs->pValue->type = DBVT_BYTE; - dbcgs->pValue->bVal = set.Value.Byte; - } break; - case DBT_ST_SHORT: case DBT_ST_WORD: - { - dbcgs->pValue->type = DBVT_WORD; - dbcgs->pValue->wVal = set.Value.Word; - } break; - case DBT_ST_INT: case DBT_ST_DWORD: - { - dbcgs->pValue->type = DBVT_DWORD; - dbcgs->pValue->dVal = set.Value.DWord; - } break; - case DBT_ST_INT64: case DBT_ST_QWORD: - case DBT_ST_DOUBLE: case DBT_ST_FLOAT: - { - dbcgs->pValue->type = DBVT_BLOB; - dbcgs->pValue->cpbVal = sizeof(set.Value); - dbcgs->pValue->pbVal = reinterpret_cast(mir_alloc(sizeof(set.Value))); - memcpy(dbcgs->pValue->pbVal, &set.Value, sizeof(set.Value)); - } break; - - default: - return -1; - } - - return 0; -} - -STDMETHODIMP_(BOOL) CDataBase::GetContactSettingStr(HANDLE hContact, DBCONTACTGETSETTING *dbcgs) -{ - if ((dbcgs->pValue->type & DBVTF_VARIABLELENGTH) == 0) - { - FreeVariant(dbcgs->pValue); - dbcgs->pValue->type = 0; - } - - char namebuf[512]; - namebuf[0] = 0; - if (dbcgs->szModule) - strcpy_s(namebuf, dbcgs->szModule); - strcat_s(namebuf, "/"); - if (dbcgs->szSetting) - strcat_s(namebuf, dbcgs->szSetting); - - TDBTSettingDescriptor desc = {0,0,0,0,0,0,0,0}; - TDBTSetting set = {0,0,0,0}; - desc.cbSize = sizeof(desc); - desc.Entity = (WPARAM)hContact; - desc.pszSettingName = namebuf; - - set.cbSize = sizeof(set); - set.Descriptor = &desc; - - - switch (dbcgs->pValue->type) - { - case DBVT_ASCIIZ: set.Type = DBT_ST_ANSI; break; - case DBVT_BLOB: set.Type = DBT_ST_BLOB; break; - case DBVT_UTF8: set.Type = DBT_ST_UTF8; break; - case DBVT_WCHAR: set.Type = DBT_ST_WCHAR; break; - } - - if (DBSettingRead(reinterpret_cast(&set), 0) == DBT_INVALIDPARAM) - return -1; - - switch (set.Type) - { - case DBT_ST_ANSI: - { - dbcgs->pValue->type = DBVT_ASCIIZ; - dbcgs->pValue->pszVal = set.Value.pAnsi; - dbcgs->pValue->cchVal = set.Value.Length - 1; - } break; - case DBT_ST_UTF8: - { - dbcgs->pValue->type = DBVT_UTF8; - dbcgs->pValue->pszVal = set.Value.pUTF8; - dbcgs->pValue->cchVal = set.Value.Length - 1; - } break; - case DBT_ST_WCHAR: - { - if (dbcgs->pValue->type == DBVT_WCHAR) - { - dbcgs->pValue->pwszVal = set.Value.pWide; - dbcgs->pValue->cchVal = set.Value.Length - 1; - } else { - dbcgs->pValue->type = DBVT_UTF8; - dbcgs->pValue->pszVal = mir_utf8encodeW(set.Value.pWide); - dbcgs->pValue->cchVal = static_cast(strlen(dbcgs->pValue->pszVal)); - mir_free(set.Value.pWide); - } - } break; - case DBT_ST_BLOB: - { - dbcgs->pValue->type = DBVT_BLOB; - dbcgs->pValue->pbVal = set.Value.pBlob; - dbcgs->pValue->cpbVal = set.Value.Length; - } break; - case DBT_ST_BOOL: - { - dbcgs->pValue->type = DBVT_BYTE; - dbcgs->pValue->bVal = (uint8_t)set.Value.Bool; - } break; - case DBT_ST_BYTE: case DBT_ST_CHAR: - { - dbcgs->pValue->type = DBVT_BYTE; - dbcgs->pValue->bVal = set.Value.Byte; - } break; - case DBT_ST_SHORT: case DBT_ST_WORD: - { - dbcgs->pValue->type = DBVT_WORD; - dbcgs->pValue->wVal = set.Value.Word; - } break; - case DBT_ST_INT: case DBT_ST_DWORD: - { - dbcgs->pValue->type = DBVT_DWORD; - dbcgs->pValue->dVal = set.Value.DWord; - } break; - case DBT_ST_INT64: case DBT_ST_QWORD: - case DBT_ST_DOUBLE: case DBT_ST_FLOAT: - { - dbcgs->pValue->type = DBVT_BLOB; - dbcgs->pValue->cpbVal = sizeof(set.Value); - dbcgs->pValue->pbVal = reinterpret_cast(mir_alloc(sizeof(set.Value))); - memcpy(dbcgs->pValue->pbVal, &set.Value, sizeof(set.Value)); - } break; - default: - return -1; - } - - return 0; -} - -STDMETHODIMP_(BOOL) CDataBase::GetContactSettingStatic(HANDLE hContact, DBCONTACTGETSETTING *dbcgs) -{ - char namebuf[512]; - namebuf[0] = 0; - if (dbcgs->szModule) - strcpy_s(namebuf, dbcgs->szModule); - strcat_s(namebuf, "/"); - if (dbcgs->szSetting) - strcat_s(namebuf, dbcgs->szSetting); - - TDBTSettingDescriptor desc = {0,0,0,0,0,0,0,0}; - TDBTSetting set = {0,0,0,0}; - desc.cbSize = sizeof(desc); - desc.Entity = (WPARAM)hContact; - desc.pszSettingName = namebuf; - - set.cbSize = sizeof(set); - set.Descriptor = &desc; - - if (DBSettingRead(reinterpret_cast(&set), 0) == DBT_INVALIDPARAM) - return -1; - - if ((set.Type & DBT_STF_VariableLength) ^ (dbcgs->pValue->type & DBVTF_VARIABLELENGTH)) - { - if (set.Type & DBT_STF_VariableLength) - mir_free(set.Value.pBlob); - return -1; - } - - switch (set.Type) - { - case DBT_ST_ANSI: - { - if (dbcgs->pValue->cchVal < set.Value.Length) - { - memcpy(dbcgs->pValue->pszVal, set.Value.pAnsi, dbcgs->pValue->cchVal); - dbcgs->pValue->pszVal[dbcgs->pValue->cchVal - 1] = 0; - } else { - memcpy(dbcgs->pValue->pszVal, set.Value.pAnsi, set.Value.Length); - } - dbcgs->pValue->type = DBVT_ASCIIZ; - dbcgs->pValue->cchVal = set.Value.Length - 1; - - mir_free(set.Value.pAnsi); - } break; - case DBT_ST_UTF8: - { - set.Value.pUTF8 = mir_utf8decode(set.Value.pUTF8, NULL); - set.Value.Length = static_cast(strlen(set.Value.pUTF8)); - - if (dbcgs->pValue->cchVal < set.Value.Length) - { - memcpy(dbcgs->pValue->pszVal, set.Value.pUTF8, dbcgs->pValue->cchVal); - dbcgs->pValue->pszVal[dbcgs->pValue->cchVal - 1] = 0; - } else { - memcpy(dbcgs->pValue->pszVal, set.Value.pUTF8, set.Value.Length); - } - dbcgs->pValue->type = DBVT_ASCIIZ; - dbcgs->pValue->cchVal = set.Value.Length - 1; - - mir_free(set.Value.pUTF8); - } break; - case DBT_ST_WCHAR: - { - char * tmp = mir_u2a(set.Value.pWide); - WORD l = static_cast(strlen(tmp)); - mir_free(set.Value.pWide); - - if (dbcgs->pValue->cchVal < l + 1) - { - memcpy(dbcgs->pValue->pszVal, tmp, dbcgs->pValue->cchVal); - dbcgs->pValue->pszVal[l] = 0; - } else { - memcpy(dbcgs->pValue->pszVal, tmp, l + 1); - } - dbcgs->pValue->type = DBVT_ASCIIZ; - dbcgs->pValue->cchVal = l; - - mir_free(tmp); - } break; - case DBT_ST_BLOB: - { - if (dbcgs->pValue->cchVal < set.Value.Length) - { - memcpy(dbcgs->pValue->pbVal, set.Value.pBlob, dbcgs->pValue->cchVal); - } else { - memcpy(dbcgs->pValue->pbVal, set.Value.pBlob, set.Value.Length); - } - dbcgs->pValue->type = DBVT_BLOB; - dbcgs->pValue->cchVal = set.Value.Length; - - mir_free(set.Value.pBlob); - } break; - case DBT_ST_BOOL: - { - dbcgs->pValue->type = DBVT_BYTE; - dbcgs->pValue->bVal = set.Value.Bool ? TRUE : FALSE; - } break; - case DBT_ST_BYTE: case DBT_ST_CHAR: - { - dbcgs->pValue->type = DBVT_BYTE; - dbcgs->pValue->bVal = set.Value.Byte; - } break; - case DBT_ST_SHORT: case DBT_ST_WORD: - { - dbcgs->pValue->type = DBVT_WORD; - dbcgs->pValue->wVal = set.Value.Word; - } break; - case DBT_ST_INT: case DBT_ST_DWORD: - { - dbcgs->pValue->type = DBVT_DWORD; - dbcgs->pValue->dVal = set.Value.DWord; - } break; - default: - return -1; - } - - return 0; -} - -STDMETHODIMP_(BOOL) CDataBase::FreeVariant(DBVARIANT *dbv) -{ - if ((dbv->type == DBVT_BLOB) && (dbv->pbVal)) - { - mir_free(dbv->pbVal); - dbv->pbVal = 0; - } else if ((dbv->type & DBVTF_VARIABLELENGTH) && (dbv->pszVal)) - { - mir_free(dbv->pszVal); - dbv->pszVal = NULL; - } - dbv->type = 0; - return 0; -} - -STDMETHODIMP_(BOOL) CDataBase::WriteContactSetting(HANDLE hContact, DBCONTACTWRITESETTING *dbcws) -{ - char namebuf[512]; - namebuf[0] = 0; - if (dbcws->szModule) - strcpy_s(namebuf, dbcws->szModule); - strcat_s(namebuf, "/"); - if (dbcws->szSetting) - strcat_s(namebuf, dbcws->szSetting); - - TDBTSettingDescriptor desc = {0,0,0,0,0,0,0,0}; - TDBTSetting set = {0,0,0,0}; - desc.cbSize = sizeof(desc); - desc.Entity = (WPARAM)hContact; - desc.pszSettingName = namebuf; - - set.cbSize = sizeof(set); - set.Descriptor = &desc; - - switch (dbcws->value.type) - { - case DBVT_ASCIIZ: - { - set.Type = DBT_ST_ANSI; - set.Value.pAnsi = dbcws->value.pszVal; - } break; - case DBVT_UTF8: - { - wchar_t * tmp = mir_utf8decodeW(dbcws->value.pszVal); - if (tmp == 0) - { - if (IsDebuggerPresent()) - { - DebugBreak(); -#ifdef _DEBUG - } else { - LOG(logWARNING, _T("Trying to write malformed UTF8 setting \"%hs\" in module \"%hs\""), dbcws->szSetting, dbcws->szModule); - CLogger::Instance().ShowMessage(); -#endif - } - return -1; - } else { - mir_free(tmp); - } - - set.Type = DBT_ST_UTF8; - set.Value.pUTF8 = dbcws->value.pszVal; - } break; - case DBVT_WCHAR: - { - set.Type = DBT_ST_WCHAR; - set.Value.pWide = dbcws->value.pwszVal; - } break; - case DBVT_BLOB: - { - set.Type = DBT_ST_BLOB; - set.Value.pBlob = dbcws->value.pbVal; - set.Value.Length = dbcws->value.cpbVal; - } break; - case DBVT_BYTE: - { - set.Type = DBT_ST_BYTE; - set.Value.Byte = dbcws->value.bVal; - } break; - case DBVT_WORD: - { - set.Type = DBT_ST_WORD; - set.Value.Word = dbcws->value.wVal; - } break; - case DBVT_DWORD: - { - set.Type = DBT_ST_DWORD; - set.Value.DWord = dbcws->value.dVal; - } break; - default: - { - return -1; - } - } - - if (DBSettingWrite(reinterpret_cast(&set), 0) == DBT_INVALIDPARAM) - return -1; - - if (dbcws->value.type == DBVT_WCHAR) - { - dbcws->value.type = DBVT_UTF8; - wchar_t * tmp = dbcws->value.pwszVal; - dbcws->value.pszVal = mir_utf8encodeW(dbcws->value.pwszVal); - NotifyEventHooks(hSettingChangeEvent, (WPARAM)hContact, (LPARAM)dbcws); - mir_free(dbcws->value.pszVal); - dbcws->value.type = DBVT_WCHAR; - dbcws->value.pwszVal = tmp; - } else { - NotifyEventHooks(hSettingChangeEvent, (WPARAM)hContact, (LPARAM)dbcws); - } - - return 0; -} - -STDMETHODIMP_(BOOL) CDataBase::DeleteContactSetting(HANDLE hContact, DBCONTACTGETSETTING *dbcgs) -{ - char namebuf[512]; - namebuf[0] = 0; - if (dbcgs->szModule) - strcpy_s(namebuf, dbcgs->szModule); - strcat_s(namebuf, "/"); - if (dbcgs->szSetting) - strcat_s(namebuf, dbcgs->szSetting); - - TDBTSettingDescriptor desc = {0,0,0,0,0,0,0,0}; - desc.cbSize = sizeof(desc); - desc.Entity = (WPARAM)hContact; - desc.pszSettingName = namebuf; - - if (DBSettingDelete(reinterpret_cast(&desc), 0) == DBT_INVALIDPARAM) - return -1; - - { - DBCONTACTWRITESETTING tmp = {0,0,0,0}; - tmp.szModule = dbcgs->szModule; - tmp.szSetting = dbcgs->szSetting; - tmp.value.type = 0; - NotifyEventHooks(hSettingChangeEvent, (WPARAM)hContact, (LPARAM)&tmp); - } - - return 0; -} - -STDMETHODIMP_(BOOL) CDataBase::EnumContactSettings(HANDLE hContact, DBCONTACTENUMSETTINGS* pces) -{ - TDBTSettingDescriptor desc = {0,0,0,0,0,0,0,0}; - desc.cbSize = sizeof(desc); - desc.Entity = (WPARAM)hContact; - - char namebuf[512]; - namebuf[0] = 0; - if (pces->szModule) - strcpy_s(namebuf, pces->szModule); - strcat_s(namebuf, "/"); - - TDBTSettingIterFilter filter = {0,0,0,0,0,0,0,0}; - filter.cbSize = sizeof(filter); - filter.Descriptor = &desc; - filter.hEntity = (WPARAM)(WPARAM)hContact; - filter.NameStart = namebuf; - - TDBTSettingIterationHandle hiter = DBSettingIterInit(reinterpret_cast(&filter), 0); - if ((hiter == 0) || (hiter == DBT_INVALIDPARAM)) - return -1; - - int res = 0; - TDBTSettingHandle hset = DBSettingIterNext(hiter, 0); - while (hset != 0) - { - char * p = strchr(desc.pszSettingName, '/'); - if (p) { - ++p; - } else { - p = desc.pszSettingName; - } - - res = pces->pfnEnumProc(p, pces->lParam); - if (res == 0) - { - hset = DBSettingIterNext(hiter, 0); - } else { - hset = 0; - } - } - - DBSettingIterClose(hiter, 0); - - if (desc.pszSettingName) - mir_free(desc.pszSettingName); - - return res; -} - -STDMETHODIMP_(LONG) CDataBase::GetEventCount(HANDLE hContact) -{ - if (hContact == 0) - hContact = (HANDLE)gDataBase->getEntities().getRootEntity(); - - return DBEventGetCount((WPARAM)hContact, 0); -} - -STDMETHODIMP_(HANDLE) CDataBase::AddEvent(HANDLE hContact, DBEVENTINFO *dbei) -{ - if (dbei->cbSize < sizeof(DBEVENTINFO)) - return (HANDLE)-1; - - int tmp = NotifyEventHooks(hEventFilterAddedEvent, (WPARAM)hContact, (LPARAM)dbei); - if (tmp != 0) - return (HANDLE)tmp; - - if (hContact == 0) - hContact = (HANDLE)gDataBase->getEntities().getRootEntity(); - - - TDBTEvent ev = {0,0,0,0,0,0,0}; - ev.cbSize = sizeof(ev); - ev.ModuleName = dbei->szModule; - ev.Timestamp = dbei->timestamp; - ev.Flags = dbei->flags; - if (ev.Flags & DBEF_SENT) - ev.Flags = ev.Flags | DBEF_READ; - ev.EventType = dbei->eventType; - ev.cbBlob = dbei->cbBlob; - ev.pBlob = dbei->pBlob; - - int res = DBEventAdd((WPARAM)hContact, reinterpret_cast(&ev)); - if (res != DBT_INVALIDPARAM) - { - NotifyEventHooks(hEventAddedEvent, (WPARAM)hContact, res); - return (HANDLE)res; - } - return NULL; -} - -STDMETHODIMP_(BOOL) CDataBase::DeleteEvent(HANDLE hContact, HANDLE hDbEvent) -{ - int res = NotifyEventHooks(hEventDeletedEvent, (WPARAM)hContact, (WPARAM)hDbEvent); - - if (hContact == 0) - hContact = (HANDLE)gDataBase->getEntities().getRootEntity(); - - if (res == 0) - return DBEventDelete((WPARAM)hDbEvent, 0); - - return res; -} - -STDMETHODIMP_(LONG) CDataBase::GetBlobSize(HANDLE hDbEvent) -{ - int res = DBEventGetBlobSize((WPARAM)hDbEvent, 0); - if (res == DBT_INVALIDPARAM) - return -1; - - return res; -} - -STDMETHODIMP_(BOOL) CDataBase::GetEvent(HANDLE hDbEvent, DBEVENTINFO *dbei) -{ - if (dbei->cbSize < sizeof(DBEVENTINFO)) - return -1; - - TDBTEvent ev = {0,0,0,0,0,0,0}; - ev.cbSize = sizeof(ev); - ev.cbBlob = 0; - ev.pBlob = NULL; - - int res = DBEventGet((WPARAM)hDbEvent, reinterpret_cast(&ev)); - - dbei->szModule = ev.ModuleName; - dbei->timestamp = ev.Timestamp; - dbei->flags = ev.Flags; - if (dbei->flags & DBEF_SENT) - dbei->flags = dbei->flags & ~DBEF_READ; - dbei->eventType = ev.EventType; - - if (dbei->cbBlob && dbei->pBlob) - { - if (dbei->cbBlob >= ev.cbBlob) - memcpy(dbei->pBlob, ev.pBlob, ev.cbBlob); - else - memcpy(dbei->pBlob, ev.pBlob, dbei->cbBlob); - } - mir_free(ev.pBlob); - dbei->cbBlob = ev.cbBlob; - - if (res == DBT_INVALIDPARAM) - return 1; - - return res; -} - -STDMETHODIMP_(BOOL) CDataBase::MarkEventRead(HANDLE hContact, HANDLE hDbEvent) -{ - int res = DBEventMarkRead((WPARAM)hDbEvent, 0); - if ((res != DBT_INVALIDPARAM) && (res & DBEF_SENT)) - res = res & ~DBEF_READ; - return res; -} - -STDMETHODIMP_(HANDLE) CDataBase::GetEventContact(HANDLE hDbEvent) -{ - TDBTEntityHandle res = DBEventGetEntity((WPARAM)hDbEvent, 0); - if (res == gDataBase->getEntities().getRootEntity()) - res = 0; - - return (HANDLE)res; -} - -STDMETHODIMP_(HANDLE) CDataBase::FindFirstEvent(HANDLE hContact) -{ - if (hContact == 0) - hContact = (HANDLE)gDataBase->getEntities().getRootEntity(); - - return (HANDLE)gDataBase->getEvents().compFirstEvent((WPARAM)hContact); -} - -STDMETHODIMP_(HANDLE) CDataBase::FindFirstUnreadEvent(HANDLE hContact) -{ - if (hContact == 0) - hContact = (HANDLE)gDataBase->getEntities().getRootEntity(); - return (HANDLE)gDataBase->getEvents().compFirstUnreadEvent((WPARAM)hContact); -} - -STDMETHODIMP_(HANDLE) CDataBase::FindLastEvent(HANDLE hContact) -{ - if (hContact == 0) - hContact = (HANDLE)gDataBase->getEntities().getRootEntity(); - return (HANDLE)gDataBase->getEvents().compLastEvent((WPARAM)hContact); -} - -STDMETHODIMP_(HANDLE) CDataBase::FindNextEvent(HANDLE hDbEvent) -{ - return (HANDLE)gDataBase->getEvents().compNextEvent((WPARAM)hDbEvent); -} - -STDMETHODIMP_(HANDLE) CDataBase::FindPrevEvent(HANDLE hDbEvent) -{ - return (HANDLE)gDataBase->getEvents().compPrevEvent((WPARAM)hDbEvent); -} - -STDMETHODIMP_(BOOL) CDataBase::EnumModuleNames(DBMODULEENUMPROC pCallback, void *pParam) -{ - if (!pCallback) - return -1; - - return gDataBase->getSettings().CompEnumModules(pCallback, (WPARAM)pParam); -} - -STDMETHODIMP_(BOOL) CDataBase::SetSettingResident(BOOL bIsResident, const char *pszSettingName) -{ - return FALSE; -} - -STDMETHODIMP_(BOOL) CDataBase::EnumResidentSettings(DBMODULEENUMPROC pFunc, void *pParam) -{ - return FALSE; -} - -STDMETHODIMP_(void) CDataBase::SetCacheSafetyMode(BOOL) {} - -bool CompatibilityRegister() -{ - hEventDeletedEvent = CreateHookableEvent(ME_DB_EVENT_DELETED); - hEventAddedEvent = CreateHookableEvent(ME_DB_EVENT_ADDED); - hEventFilterAddedEvent = CreateHookableEvent(ME_DB_EVENT_FILTER_ADD); - hSettingChangeEvent = CreateHookableEvent(ME_DB_CONTACT_SETTINGCHANGED); - hContactDeletedEvent = CreateHookableEvent(ME_DB_CONTACT_DELETED); - hContactAddedEvent = CreateHookableEvent(ME_DB_CONTACT_ADDED); - return true; -} diff --git a/plugins/Dbx_tree/Compatibility.h b/plugins/Dbx_tree/Compatibility.h deleted file mode 100644 index a23fa9284b..0000000000 --- a/plugins/Dbx_tree/Compatibility.h +++ /dev/null @@ -1,30 +0,0 @@ -/* - -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. - -*/ - -#pragma once - -#include "Interface.h" -#include "DataBase.h" -#include "Services.h" - -bool CompatibilityRegister(); - diff --git a/plugins/Dbx_tree/DataBase.cpp b/plugins/Dbx_tree/DataBase.cpp deleted file mode 100644 index 50fe494b3c..0000000000 --- a/plugins/Dbx_tree/DataBase.cpp +++ /dev/null @@ -1,371 +0,0 @@ -/* - -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 "DataBase.h" -#include "newpluginapi.h" -#ifndef _MSC_VER -#include "savestrings_gcc.h" -#endif -#include "Logger.h" - -CDataBase *gDataBase = NULL; - -CDataBase::CDataBase(const TCHAR *FileName) -{ - InitDbInstance(this); - - size_t len = _tcslen(FileName); - m_FileName[0] = new TCHAR[len + 1]; - _tcsncpy_s(m_FileName[0], len + 1, FileName, len); - m_FileName[0][len] = 0; - - TCHAR * tmp = _tcsrchr(m_FileName[0], '.'); - if (tmp) - { - m_FileName[1] = new TCHAR[len + 1]; - _tcsncpy_s(m_FileName[1], len + 1, m_FileName[0], tmp - m_FileName[0]); - _tcscat_s(m_FileName[1], len + 1, _T(".pri")); - } else { - m_FileName[1] = new TCHAR[len + 5]; - _tcscpy_s(m_FileName[1], len + 5, m_FileName[0]); - _tcscat_s(m_FileName[1], len + 5, _T(".pri")); - } - - m_Opened = false; - - for (int i = 0; i < DBFileMax; ++i) - { - m_BlockManager[i] = NULL; - m_FileAccess[i] = NULL; - m_EncryptionManager[i] = NULL; - m_HeaderBlock[i] = 0; - } - - m_Entities = NULL; - m_Settings = NULL; - m_Events = NULL; - -} -CDataBase::~CDataBase() -{ - if (m_Events) delete m_Events; - if (m_Settings) delete m_Settings; - if (m_Entities) delete m_Entities; - - m_Entities = NULL; - m_Settings = NULL; - m_Events = NULL; - - for (int i = DBFileMax - 1; i >= 0; --i) - { - if (m_BlockManager[i]) delete m_BlockManager[i]; - if (m_FileAccess[i]) delete m_FileAccess[i]; - if (m_EncryptionManager[i]) delete m_EncryptionManager[i]; - - m_BlockManager[i] = NULL; - m_FileAccess[i] = NULL; - m_EncryptionManager[i] = NULL; - - delete [] (m_FileName[i]); - } - DestroyDbInstance(this); -} - -int CDataBase::CreateDB() -{ - /// TODO: create and show wizard - if (!CreateNewFile(DBFileSetting) || - !CreateNewFile(DBFilePrivate)) - return EMKPRF_CREATEFAILED; - - return 0; -} - - -int CDataBase::CheckFile(TDBFileType Index) -{ - TGenericFileHeader h; - memset(&h, 0, sizeof(h)); - DWORD r = 0; - HANDLE htmp = CreateFile(m_FileName[Index], GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_FLAG_RANDOM_ACCESS, NULL); - if (htmp != INVALID_HANDLE_VALUE) - { - SetFilePointer(htmp, 0, NULL, FILE_BEGIN); - if (ReadFile(htmp, &h, sizeof(h), &r, NULL)) - { - if (0 != memcmp(h.Gen.Signature, cFileSignature[Index], sizeof(cFileSignature[Index]))) - { - CloseHandle(htmp); - return EGROKPRF_UNKHEADER; - } - - if (cDBVersion < h.Gen.Version) - { - CloseHandle(htmp); - return EGROKPRF_VERNEWER; - } - - CloseHandle(htmp); - return EGROKPRF_NOERROR; - } - CloseHandle(htmp); - } - - return EGROKPRF_CANTREAD; -} - -int CDataBase::CheckDB() -{ - int res = CheckFile(DBFileSetting); - - if (res != EGROKPRF_NOERROR) - return res; - - if (PrivateFileExists()) - res = CheckFile(DBFilePrivate); - - return res; -} - -int CDataBase::LoadFile(TDBFileType Index) -{ - TGenericFileHeader h; - m_EncryptionManager[Index] = new CEncryptionManager; - - if (CMappedMemory::InitMMAP()) - m_FileAccess[Index] = new CMappedMemory(m_FileName[Index]); - else - m_FileAccess[Index] = new CDirectAccess(m_FileName[Index]); - - m_FileAccess[Index]->Read(&h, 0, sizeof(h)); - m_EncryptionManager[Index]->InitEncryption(h.Gen.FileEncryption); - - m_FileAccess[Index]->Size(h.Gen.FileSize); - m_FileAccess[Index]->sigFileSizeChanged().connect(this, &CDataBase::onFileSizeChanged); - - m_BlockManager[Index] = new CBlockManager(*m_FileAccess[Index], *m_EncryptionManager[Index]); - - CBlockManager::WriteTransaction trans(*m_BlockManager[Index]); // don't fire size event until header is loaded - - m_HeaderBlock[Index] = m_BlockManager[Index]->ScanFile(sizeof(h), cHeaderBlockSignature, h.Gen.FileSize); - - if (m_HeaderBlock[Index] == 0) - { - LOG(logCRITICAL, _T("Header Block not found! File damaged: \"%s\""), m_FileName[Index]); - return -1; - } - - uint32_t size = sizeof(h); - uint32_t sig = -1; - m_Header[Index] = m_BlockManager[Index]->ReadBlock(0, size, sig); - - sig = cHeaderBlockSignature; - TGenericFileHeader * buf = m_BlockManager[Index]->ReadBlock(m_HeaderBlock[Index], size, sig); - if (!buf) - { - LOG(logCRITICAL, _T("Header Block cannot be read! File damaged: \"%s\""), m_FileName[Index]); - return -1; - } - - buf->Gen.Obscure = 0; - - if (memcmp(m_Header[Index], buf, size)) - { - LOG(logCRITICAL, _T("Header Block in \"%s\" damaged!"), m_FileName[Index]); - return -1; - } - - return 0; -} - -int CDataBase::OpenDB() -{ - if (!PrivateFileExists()) - { - // TODO WIZARD - if (!CreateNewFile(DBFilePrivate)) - return -1; - } - - int res = LoadFile(DBFileSetting); - if ((res != 0) && (CLogger::logERROR <= CLogger::Instance().ShowMessage())) - { - return res; - } - - res = LoadFile(DBFilePrivate); - - if ((res != 0) && (CLogger::logERROR <= CLogger::Instance().ShowMessage())) - { - return res; - } - if (CLogger::logERROR <= CLogger::Instance().ShowMessage()) - return -1; - - m_Entities = new CEntities(*m_BlockManager[DBFilePrivate], - m_Header[DBFilePrivate]->Pri.RootEntity, - m_Header[DBFilePrivate]->Pri.Entities, - m_Header[DBFilePrivate]->Pri.Virtuals); - - m_Entities->sigRootChanged().connect(this, &CDataBase::onEntitiesRootChanged); - m_Entities->sigVirtualRootChanged().connect(this, &CDataBase::onVirtualsRootChanged); - - if (m_Entities->getRootEntity() != m_Header[DBFilePrivate]->Pri.RootEntity) - { - m_Header[DBFilePrivate]->Pri.RootEntity = m_Entities->getRootEntity(); - ReWriteHeader(DBFilePrivate); - } - - m_Settings = new CSettings(*m_BlockManager[DBFileSetting], - *m_BlockManager[DBFilePrivate], - m_Header[DBFileSetting]->Set.Settings, - *m_Entities); - - m_Settings->sigRootChanged().connect(this, &CDataBase::onSettingsRootChanged); - - m_Events = new CEvents(*m_BlockManager[DBFilePrivate], - *m_EncryptionManager[DBFilePrivate], - *m_Entities, - *m_Settings); - - return 0; -} - -bool CDataBase::PrivateFileExists() -{ - HANDLE htmp = CreateFile(m_FileName[DBFilePrivate], GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_FLAG_RANDOM_ACCESS, NULL); - if (htmp != INVALID_HANDLE_VALUE) - { - CloseHandle(htmp); - return true; - } - - return false; -} - - -bool CDataBase::CreateNewFile(TDBFileType File) -{ - CEncryptionManager enc; - CDirectAccess fa(m_FileName[File]); - fa.Size(sizeof(TGenericFileHeader)); - CBlockManager bm(fa, enc); - bm.ScanFile(sizeof(TGenericFileHeader), 0, sizeof(TGenericFileHeader)); - - CBlockManager::WriteTransaction trans(bm); - - uint32_t block; - TGenericFileHeader * buf = bm.CreateBlock(block, cHeaderBlockSignature); - uint32_t size = 0; - uint32_t sig = -1; - TGenericFileHeader * h = bm.ReadBlock(0, size, sig); - - memset(h, 0, sizeof(TGenericFileHeader)); - memcpy(&h->Gen.Signature, &cFileSignature[File], sizeof(h->Gen.Signature)); - h->Gen.Version = cDBVersion; - h->Gen.FileSize = fa.Size(); - - memcpy(buf, h, sizeof(TGenericFileHeader)); - bm.UpdateBlock(block, 0); - bm.UpdateBlock(0, -1); - - return true; -} - -inline void CDataBase::ReWriteHeader(TDBFileType Index) -{ - m_BlockManager[Index]->UpdateBlock(0, -1); - uint32_t size = 0, sig = 0; - TGenericFileHeader * h = m_BlockManager[Index]->ReadBlock(m_HeaderBlock[Index], size, sig); - - *h = *m_Header[Index]; - h->Gen.Obscure = GetTickCount(); - m_BlockManager[Index]->UpdateBlock(m_HeaderBlock[Index], 0); -} - - -void CDataBase::onSettingsRootChanged(CSettings* Settings, CSettingsTree::TNodeRef NewRoot) -{ - m_Header[DBFileSetting]->Set.Settings = NewRoot; - ReWriteHeader(DBFileSetting); -} -void CDataBase::onVirtualsRootChanged(void* Virtuals, CVirtuals::TNodeRef NewRoot) -{ - m_Header[DBFilePrivate]->Pri.Virtuals = NewRoot; - ReWriteHeader(DBFilePrivate); -} -void CDataBase::onEntitiesRootChanged(void* Entities, CEntities::TNodeRef NewRoot) -{ - m_Header[DBFilePrivate]->Pri.Entities = NewRoot; - ReWriteHeader(DBFilePrivate); -} -void CDataBase::onFileSizeChanged(CFileAccess * File, uint32_t Size) -{ - if (File == m_FileAccess[DBFileSetting]) - { - m_Header[DBFileSetting]->Gen.FileSize = Size; - ReWriteHeader(DBFileSetting); - } else { - m_Header[DBFilePrivate]->Gen.FileSize = Size; - ReWriteHeader(DBFilePrivate); - } -} - -int CDataBase::getProfileName(int BufferSize, char * Buffer) -{ - TCHAR * slash = _tcsrchr(m_FileName[DBFileSetting], '\\'); - if (slash) - slash++; - else - slash = m_FileName[DBFileSetting]; - - int l = static_cast(_tcslen(slash)); - if (BufferSize < l + 1) - return -1; - - char * tmp = mir_t2a(slash); - strcpy_s(Buffer, BufferSize, tmp); - mir_free(tmp); - - return 0; -} -int CDataBase::getProfilePath(int BufferSize, char * Buffer) -{ - TCHAR * slash = _tcsrchr(m_FileName[DBFileSetting], '\\'); - if (!slash) - return -1; - - int l = slash - m_FileName[DBFileSetting]; - - if (BufferSize < l + 1) - { - return -1; - } - - *slash = 0; - char * tmp = mir_t2a(m_FileName[DBFileSetting]); - strcpy_s(Buffer, BufferSize, tmp); - mir_free(tmp); - *slash = '\\'; - - return 0; -} diff --git a/plugins/Dbx_tree/DataBase.h b/plugins/Dbx_tree/DataBase.h deleted file mode 100644 index 124fee4f9d..0000000000 --- a/plugins/Dbx_tree/DataBase.h +++ /dev/null @@ -1,189 +0,0 @@ -/* - -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. - -*/ - -#pragma once - -#ifndef _MSC_VER -#include -#else -#include "stdint.h" -#endif -#include "MREWSync.h" - -#include "Events.h" -#include "Settings.h" -#include "Entities.h" - -#include "FileAccess.h" -#include "MappedMemory.h" -#include "DirectAccess.h" -#include "Blockmanager.h" - -#include "sigslot.h" - -#include "EncryptionManager.h" - -typedef enum TDBFileType { - DBFileSetting = 0, - DBFilePrivate = 1, - DBFileMax = 2 -} TDBFileType; - -static const uint8_t cFileSignature[DBFileMax][20] = {"Miranda IM Settings", "Miranda IM DataTree"}; -static const uint32_t cDBVersion = 0x00000001; - -static const uint32_t cHeaderBlockSignature = 0x7265491E; - -#pragma pack(push, 1) // push current alignment to stack, set alignment to 1 byte boundary - -typedef struct TSettingsHeader { - uint8_t Signature[20]; /// signature must be cSettingsHeader - uint32_t Version; /// internal DB version cDataBaseVersion - uint32_t Obscure; - TFileEncryption FileEncryption; /// Encryption Method - uint32_t FileStructureBlock; /// Offset of CBlockManager master block - uint32_t FileSize; /// Offset to the last used byte + 1 - uint32_t Settings; /// Offset to the SettingsBTree RootNode - uint8_t Reserved[256 - sizeof(TFileEncryption) - 20 - 5*sizeof(uint32_t)]; /// reserved storage -} TSettingsHeader; - -typedef struct TPrivateHeader { - uint8_t Signature[20]; /// signature must be CDataHeader - uint32_t Version; /// internal DB version cDataBaseVersion - uint32_t Obscure; - TFileEncryption FileEncryption; /// Encryption Method - uint32_t FileStructureBlock; /// Offset of CBlockManager master block - uint32_t FileSize; /// Offset to the last used byte + 1 - uint32_t RootEntity; /// Offset to the Root CList Entity - uint32_t Entities; /// Offset to the EntityBTree RootNode - uint32_t Virtuals; /// Offset to the VirtualsBTree RootNode - uint8_t Reserved[256 - sizeof(TFileEncryption) - 20 - 7*sizeof(uint32_t)]; /// reserved storage -} TPrivateHeader; - - -typedef union TGenericFileHeader { - struct { - uint8_t Signature[20]; /// signature must be cSettingsHeader - uint32_t Version; /// internal DB version cDataBaseVersion - uint32_t Obscure; - TFileEncryption FileEncryption; /// Encryption Method - uint32_t FileStructureBlock; /// Offset of CBlockManager master block - uint32_t FileSize; /// Offset to the last used byte + 1 - uint8_t Reserved[256 - sizeof(TFileEncryption) - 20 - 4*sizeof(uint32_t)]; /// reserved storage - } Gen; - TSettingsHeader Set; - TPrivateHeader Pri; -} TGenericFileHeader; - -#pragma pack(pop) - -class CDataBase : public sigslot::has_slots<>, public MIDatabase -{ -private: - TCHAR* m_FileName[DBFileMax]; - bool m_Opened; - - CBlockManager *m_BlockManager[DBFileMax]; - CFileAccess *m_FileAccess[DBFileMax]; - TGenericFileHeader * m_Header[DBFileMax]; - CEncryptionManager *m_EncryptionManager[DBFileMax]; - - uint32_t m_HeaderBlock[DBFileMax]; - - void onSettingsRootChanged(CSettings* Settings, CSettingsTree::TNodeRef NewRoot); - void onVirtualsRootChanged(void* Virtuals, CVirtuals::TNodeRef NewRoot); - void onEntitiesRootChanged(void* Entities, CEntities::TNodeRef NewRoot); - void onFileSizeChanged(CFileAccess * File, uint32_t Size); - - bool PrivateFileExists(); - bool CreateNewFile(TDBFileType File); - - int CheckFile(TDBFileType Index); - int LoadFile(TDBFileType Index); -protected: - CEntities *m_Entities; - CSettings *m_Settings; - CEvents *m_Events; - - void ReWriteHeader(TDBFileType Index); - -public: - CDataBase(const TCHAR* FileName); - virtual ~CDataBase(); - - int CreateDB(); - int CheckDB(); - int OpenDB(); - - CEntities & getEntities() - { - return *m_Entities; - } - CSettings & getSettings() - { - return *m_Settings; - } - CEvents & getEvents() - { - return *m_Events; - } - - int getProfileName(int BufferSize, char * Buffer); - int getProfilePath(int BufferSize, char * Buffer); - -protected: // to be compatible with the standard Miranda databases - STDMETHODIMP_(void) SetCacheSafetyMode(BOOL); - - STDMETHODIMP_(LONG) GetContactCount(void); - STDMETHODIMP_(HANDLE) FindFirstContact(const char* szProto = NULL); - STDMETHODIMP_(HANDLE) FindNextContact(HANDLE hContact, const char* szProto = NULL); - STDMETHODIMP_(LONG) DeleteContact(HANDLE hContact); - STDMETHODIMP_(HANDLE) AddContact(void); - STDMETHODIMP_(BOOL) IsDbContact(HANDLE hContact); - - STDMETHODIMP_(LONG) GetEventCount(HANDLE hContact); - STDMETHODIMP_(HANDLE) AddEvent(HANDLE hContact, DBEVENTINFO *dbe); - STDMETHODIMP_(BOOL) DeleteEvent(HANDLE hContact, HANDLE hDbEvent); - STDMETHODIMP_(LONG) GetBlobSize(HANDLE hDbEvent); - STDMETHODIMP_(BOOL) GetEvent(HANDLE hDbEvent, DBEVENTINFO *dbe); - STDMETHODIMP_(BOOL) MarkEventRead(HANDLE hContact, HANDLE hDbEvent); - STDMETHODIMP_(HANDLE) GetEventContact(HANDLE hDbEvent); - STDMETHODIMP_(HANDLE) FindFirstEvent(HANDLE hContact); - STDMETHODIMP_(HANDLE) FindFirstUnreadEvent(HANDLE hContact); - STDMETHODIMP_(HANDLE) FindLastEvent(HANDLE hContact); - STDMETHODIMP_(HANDLE) FindNextEvent(HANDLE hDbEvent); - STDMETHODIMP_(HANDLE) FindPrevEvent(HANDLE hDbEvent); - - STDMETHODIMP_(BOOL) EnumModuleNames(DBMODULEENUMPROC pFunc, void *pParam); - - STDMETHODIMP_(BOOL) GetContactSetting(HANDLE hContact, DBCONTACTGETSETTING *dbcgs); - STDMETHODIMP_(BOOL) GetContactSettingStr(HANDLE hContact, DBCONTACTGETSETTING *dbcgs); - STDMETHODIMP_(BOOL) GetContactSettingStatic(HANDLE hContact, DBCONTACTGETSETTING *dbcgs); - STDMETHODIMP_(BOOL) FreeVariant(DBVARIANT *dbv); - STDMETHODIMP_(BOOL) WriteContactSetting(HANDLE hContact, DBCONTACTWRITESETTING *dbcws); - STDMETHODIMP_(BOOL) DeleteContactSetting(HANDLE hContact, DBCONTACTGETSETTING *dbcgs); - STDMETHODIMP_(BOOL) EnumContactSettings(HANDLE hContact, DBCONTACTENUMSETTINGS* dbces); - STDMETHODIMP_(BOOL) SetSettingResident(BOOL bIsResident, const char *pszSettingName); - STDMETHODIMP_(BOOL) EnumResidentSettings(DBMODULEENUMPROC pFunc, void *pParam); -}; - -extern CDataBase *gDataBase; diff --git a/plugins/Dbx_tree/DatabaseLink.cpp b/plugins/Dbx_tree/DatabaseLink.cpp deleted file mode 100644 index cc944cc305..0000000000 --- a/plugins/Dbx_tree/DatabaseLink.cpp +++ /dev/null @@ -1,96 +0,0 @@ -/* - -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 "DatabaseLink.h" -#ifndef _MSC_VER -#include "savestrings_gcc.h" -#endif - - -/* - profile: pointer to a string which contains full path + name - Affect: The database plugin should create the profile, the filepath will not exist at - the time of this call, profile will be C:\..\.dat - Note: Do not prompt the user in anyway about this operation. - Note: Do not initialise internal data structures at this point! - Returns: 0 on success, non zero on failure - error contains extended error information, see EMKPRF_* -*/ - -static int makeDatabase(const TCHAR *profile) -{ - std::auto_ptr db( new CDataBase(profile)); - return db->CreateDB(); -} - -/* - profile: [in] a null terminated string to file path of selected profile - error: [in/out] pointer to an int to set with error if any - Affect: Ask the database plugin if it supports the given profile, if it does it will - return 0, if it doesnt return 1, with the error set in error -- EGROKPRF_* can be valid error - condition, most common error would be [EGROKPRF_UNKHEADER] - Note: Just because 1 is returned, doesnt mean the profile is not supported, the profile might be damaged - etc. - Returns: 0 on success, non zero on failure -*/ -static int grokHeader(const TCHAR *profile) -{ - std::auto_ptr db( new CDataBase(profile)); - return db->CheckDB(); -} - -/* -Affect: Tell the database to create all services/hooks that a 3.xx legecy database might support into link, - which is a PLUGINLINK structure -Returns: 0 on success, nonzero on failure -*/ - -static MIDatabase* LoadDatabase(const TCHAR *profile) -{ - gDataBase = new CDataBase(profile); - gDataBase->OpenDB(); - return gDataBase; -} - -/* -Affect: The database plugin should shutdown, unloading things from the core and freeing internal structures -Returns: 0 on success, nonzero on failure -Note: Unload() might be called even if Load(void) was never called, wasLoaded is set to 1 if Load(void) was ever called. -*/ - -static int UnloadDatabase(MIDatabase* db) -{ - if (gDataBase == db) - gDataBase = NULL; - delete (CDataBase*)db; - return 0; -} - -DATABASELINK gDBLink = { - sizeof(DATABASELINK), - gInternalName, - _T(gInternalNameLong), - makeDatabase, - grokHeader, - LoadDatabase, - UnloadDatabase, - NULL // does not support file checking -}; diff --git a/plugins/Dbx_tree/DatabaseLink.h b/plugins/Dbx_tree/DatabaseLink.h deleted file mode 100644 index c0c20b7fa0..0000000000 --- a/plugins/Dbx_tree/DatabaseLink.h +++ /dev/null @@ -1,28 +0,0 @@ -/* - -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. - -*/ - -#pragma once -#include -#include "Interface.h" -#include "Database.h" -#include "Services.h" -#include "Compatibility.h" \ No newline at end of file diff --git a/plugins/Dbx_tree/DirectAccess.cpp b/plugins/Dbx_tree/DirectAccess.cpp deleted file mode 100644 index 33785af7c4..0000000000 --- a/plugins/Dbx_tree/DirectAccess.cpp +++ /dev/null @@ -1,118 +0,0 @@ -/* - -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 "DirectAccess.h" -#include "Logger.h" - -CDirectAccess::CDirectAccess(const TCHAR* FileName) -: CFileAccess(FileName) -{ - m_File = CreateFile(FileName, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS, 0); - CHECKSYS(m_File != INVALID_HANDLE_VALUE, - logCRITICAL, _T("CreateFile failed")); - - m_MinAllocGranularity = 0x00001000; // 4kb to avoid heavy fragmentation - m_AllocGranularity = 0x00008000; // 32kb - m_MaxAllocGranularity = 0x00100000; // 1mb for fast increasing - - uint32_t size = GetFileSize(m_File, NULL); - size = (size + m_AllocGranularity - 1) & ~(m_AllocGranularity - 1); - - if (size == 0) - size = m_AllocGranularity; - - m_AllocSize = size; - - InitJournal(); -} - -CDirectAccess::~CDirectAccess() -{ - if (m_File) - { - if (INVALID_SET_FILE_POINTER != SetFilePointer(m_File, m_Size, NULL, FILE_BEGIN)) - SetEndOfFile(m_File); - - CloseHandle(m_File); - } -} - -uint32_t CDirectAccess::_Read(void* Buf, uint32_t Source, uint32_t Size) -{ - DWORD read = 0; - - CHECKSYS(INVALID_SET_FILE_POINTER != SetFilePointer(m_File, Source, NULL, FILE_BEGIN), - logERROR, _T("SetFilePointer failed")); - - CHECKSYS(ReadFile(m_File, Buf, Size, &read, NULL), - logERROR, _T("ReadFile failed")); - - return read; -} -uint32_t CDirectAccess::_Write(void* Buf, uint32_t Dest, uint32_t Size) -{ - DWORD written = 0; - - CHECKSYS(INVALID_SET_FILE_POINTER != SetFilePointer(m_File, Dest, NULL, FILE_BEGIN), - logERROR, _T("SetFilePointer failed")); - - CHECKSYS(WriteFile(m_File, Buf, Size, &written, NULL), - logERROR, _T("WriteFile failed")); - - return written; -} - -uint32_t CDirectAccess::_SetSize(uint32_t Size) -{ - CHECKSYS(INVALID_SET_FILE_POINTER != SetFilePointer(m_File, Size, NULL, FILE_BEGIN), - logERROR, _T("SetFilePointer failed")); - - CHECKSYS(SetEndOfFile(m_File), - logERROR, _T("SetEndOfFile failed")); - - return Size; -} - -void CDirectAccess::_Invalidate(uint32_t Dest, uint32_t Size) -{ - DWORD written; - uint8_t buf[4096]; - memset(buf, 0, sizeof(buf)); - - CHECKSYS(INVALID_SET_FILE_POINTER != SetFilePointer(m_File, Dest, NULL, FILE_BEGIN), - logERROR, _T("SetFilePointer failed")); - - while (Size > sizeof(buf)) - { - Size -= sizeof(buf); - CHECKSYS(WriteFile(m_File, buf, sizeof(buf), &written, NULL), - logERROR, _T("WriteFile failed")); - } - CHECKSYS(WriteFile(m_File, buf, Size, &written, NULL), - logERROR, _T("WriteFile failed")); -} - -void CDirectAccess::_Flush() -{ - CHECKSYS(FlushFileBuffers(m_File), - logERROR, _T("FlushFileBuffers failed")); -} diff --git a/plugins/Dbx_tree/DirectAccess.h b/plugins/Dbx_tree/DirectAccess.h deleted file mode 100644 index cc4241c235..0000000000 --- a/plugins/Dbx_tree/DirectAccess.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - -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. - -*/ - -#pragma once - -#include -#include "FileAccess.h" - -class CDirectAccess : public CFileAccess -{ -private: - - HANDLE m_File; -protected: - uint32_t _Read(void* Buf, uint32_t Source, uint32_t Size); - uint32_t _Write(void* Buf, uint32_t Dest, uint32_t Size); - void _Invalidate(uint32_t Dest, uint32_t Size); - uint32_t _SetSize(uint32_t Size); - void _Flush(); -public: - CDirectAccess(const TCHAR* FileName); - virtual ~CDirectAccess(); - -}; diff --git a/plugins/Dbx_tree/EncryptionManager.cpp b/plugins/Dbx_tree/EncryptionManager.cpp deleted file mode 100644 index 7afdcb248f..0000000000 --- a/plugins/Dbx_tree/EncryptionManager.cpp +++ /dev/null @@ -1,241 +0,0 @@ -/* - -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 "EncryptionManager.h" -#include - -uint32_t CEncryptionManager::CipherListRefCount = 0; -CEncryptionManager::TCipherList* CEncryptionManager::CipherList = NULL; - -static const uint32_t cFileBlockMask = 0xfffff000; - -void CEncryptionManager::LoadCipherList() -{ - if (CipherList) - return; - - CipherList = new TCipherList; - CipherListRefCount++; - - WIN32_FIND_DATA search; - TCHAR path[MAX_PATH * 8]; - GetModuleFileName(NULL, path, sizeof(path)); - TCHAR * file = _tcsrchr(path, '\\'); - if (!file) - file = path; - - _tcscpy_s(file, sizeof(path) / sizeof(path[0]) - (file - path), _T("\\plugins\\encryption\\*.dll")); - file += 20; - - HANDLE hfinder = FindFirstFile(path, &search); - if (hfinder != INVALID_HANDLE_VALUE) - { - TCipherItem item; - TCipherInfo* (__cdecl *CipherInfoProc)(void *); - do { - _tcscpy_s(file, sizeof(path) / sizeof(path[0]) - (file - path), search.cFileName); - HMODULE hmod = LoadLibrary(path); - if (hmod) - { - CipherInfoProc = (TCipherInfo*(__cdecl*)(void*)) GetProcAddress(hmod, "CipherInfo"); - if (CipherInfoProc) - { - TCipherInfo* info = CipherInfoProc(NULL); - if (info && (info->cbSize == sizeof(TCipherInfo)) && (CipherList->find(info->ID) == CipherList->end())) - { - item.ID = info->ID; - item.Name = _wcsdup(info->Name); - item.Description = _wcsdup(info->Description); - item.FilePath = _tcsdup(path); - item.FileName = item.FilePath + (file - path); - - CipherList->insert(std::make_pair(item.ID, item)); - } - } - - FreeLibrary(hmod); - - } - } while (FindNextFile(hfinder, &search)); - - FindClose(hfinder); - } -} - -CEncryptionManager::CEncryptionManager() -{ - m_Ciphers[CURRENT].Cipher = NULL; - m_Ciphers[OLD].Cipher = NULL; - m_Changing = false; - m_ChangingProcess = 0; - - LoadCipherList(); -} -CEncryptionManager::~CEncryptionManager() -{ - if (m_Ciphers[CURRENT].Cipher) - delete m_Ciphers[CURRENT].Cipher; - m_Ciphers[CURRENT].Cipher = NULL; - if (m_Ciphers[OLD].Cipher) - delete m_Ciphers[OLD].Cipher; - m_Ciphers[OLD].Cipher = NULL; - - CipherListRefCount--; - if (!CipherListRefCount) - { - TCipherList::iterator i = CipherList->begin(); - while (i != CipherList->end()) - { - free(i->second.Description); - free(i->second.Name); - free(i->second.FilePath); - // do not free Filename... it's a substring of FilePath - ++i; - } - - delete CipherList; - CipherList = NULL; - } -} - -bool CEncryptionManager::InitEncryption(TFileEncryption & Enc) -{ - if (Enc.ConversionProcess) - { - m_Changing = true; - m_ChangingProcess = Enc.ConversionProcess; - } - - for (int c = (int)CURRENT; c < (int)COUNT; c++) - { - TCipherList::iterator i = CipherList->find(Enc.CipherID); - if (i != CipherList->end()) - { - m_Ciphers[c].CipherDLL = LoadLibrary(i->second.FilePath); - if (m_Ciphers[c].CipherDLL) - { - TCipherInfo* (__cdecl *cipherinfoproc)(void *); - cipherinfoproc = (TCipherInfo*(__cdecl*)(void*)) GetProcAddress(m_Ciphers[c].CipherDLL, "CipherInfo"); - if (cipherinfoproc) - { - TCipherInfo* info = cipherinfoproc(NULL); - if (info && (info->cbSize == sizeof(TCipherInfo))) - m_Ciphers[c].Cipher = new CCipher(info->Create()); - - } - - if (!m_Ciphers[c].Cipher) - { - FreeLibrary(m_Ciphers[c].CipherDLL); - m_Ciphers[c].CipherDLL = NULL; - } - } - } - } - - return true; -} - -bool CEncryptionManager::AlignData(uint32_t ID, uint32_t & Start, uint32_t & End) -{ - if (m_Ciphers[CURRENT].Cipher && (!m_Changing || (ID < m_ChangingProcess))) - { - if (m_Ciphers[CURRENT].Cipher->IsStreamCipher()) - { - Start = 0; - End = End - End % m_Ciphers[CURRENT].Cipher->BlockSizeBytes() + m_Ciphers[CURRENT].Cipher->BlockSizeBytes(); - } else { - Start = Start - Start % m_Ciphers[CURRENT].Cipher->BlockSizeBytes(); - if (End % m_Ciphers[CURRENT].Cipher->BlockSizeBytes()) - End = End - End % m_Ciphers[CURRENT].Cipher->BlockSizeBytes() + m_Ciphers[CURRENT].Cipher->BlockSizeBytes(); - } - - return true; - } else if (m_Ciphers[OLD].Cipher && m_Changing && (ID >= m_ChangingProcess)) - { - if (m_Ciphers[OLD].Cipher->IsStreamCipher()) - { - Start = 0; - End = End - End % m_Ciphers[OLD].Cipher->BlockSizeBytes() + m_Ciphers[OLD].Cipher->BlockSizeBytes(); - } else { - Start = Start - Start % m_Ciphers[OLD].Cipher->BlockSizeBytes(); - if (End % m_Ciphers[OLD].Cipher->BlockSizeBytes()) - End = End - End % m_Ciphers[OLD].Cipher->BlockSizeBytes() + m_Ciphers[OLD].Cipher->BlockSizeBytes(); - } - - return true; - } - - return false; -} -uint32_t CEncryptionManager::AlignSize(uint32_t ID, uint32_t Size) -{ - if (m_Ciphers[CURRENT].Cipher && (!m_Changing || (ID < m_ChangingProcess))) - { - if (Size % m_Ciphers[CURRENT].Cipher->BlockSizeBytes()) - return Size - Size % m_Ciphers[CURRENT].Cipher->BlockSizeBytes() + m_Ciphers[CURRENT].Cipher->BlockSizeBytes(); - - } else if (m_Ciphers[OLD].Cipher && m_Changing && (ID >= m_ChangingProcess)) - { - if (Size % m_Ciphers[OLD].Cipher->BlockSizeBytes()) - return Size - Size % m_Ciphers[OLD].Cipher->BlockSizeBytes() + m_Ciphers[OLD].Cipher->BlockSizeBytes(); - - } - - return Size; -} - -bool CEncryptionManager::IsEncrypted(uint32_t ID) -{ - return (m_Ciphers[CURRENT].Cipher && (!m_Changing || (ID < m_ChangingProcess))) || - (m_Ciphers[OLD].Cipher && m_Changing && (ID >= m_ChangingProcess)); -} - -void CEncryptionManager::Encrypt(void* Data, uint32_t DataLength, uint32_t ID, uint32_t StartByte) -{ - if (m_Ciphers[CURRENT].Cipher && (!m_Changing || (ID < m_ChangingProcess))) - { - m_Ciphers[CURRENT].Cipher->Encrypt(Data, DataLength, ID, StartByte); - } else if (m_Ciphers[OLD].Cipher && m_Changing && (ID >= m_ChangingProcess)) - { - m_Ciphers[OLD].Cipher->Encrypt(Data, DataLength, ID, StartByte); - } -} -void CEncryptionManager::Decrypt(void* Data, uint32_t DataLength, uint32_t ID, uint32_t StartByte) -{ - if (m_Ciphers[CURRENT].Cipher && (!m_Changing || (ID < m_ChangingProcess))) - { - m_Ciphers[CURRENT].Cipher->Decrypt(Data, DataLength, ID, StartByte); - } else if (m_Ciphers[OLD].Cipher && m_Changing && (ID >= m_ChangingProcess)) - { - m_Ciphers[OLD].Cipher->Decrypt(Data, DataLength, ID, StartByte); - } -} - -bool CEncryptionManager::CanChangeCipher() -{ - return false; -} -bool CEncryptionManager::ChangeCipher(TEncryption & Encryption) -{ - return false; -} diff --git a/plugins/Dbx_tree/EncryptionManager.h b/plugins/Dbx_tree/EncryptionManager.h deleted file mode 100644 index 763df26595..0000000000 --- a/plugins/Dbx_tree/EncryptionManager.h +++ /dev/null @@ -1,107 +0,0 @@ -/* - -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. - -*/ - -#pragma once - -#ifndef _MSC_VER -#include -#else -#include "stdint.h" -#endif -#include "sigslot.h" - -#define __INTERFACE_ONLY__ -#include "encryption/Cipher.h" -#undef __INTERFACE_ONLY__ - -#include "SHA256.h" -#include "Interface.h" -//#include "Thread.h" -#include -#include - -static const uint32_t cEncryptionChangingFlag = 0x80000000; - -#pragma pack(push, 1) - -typedef struct TFileEncryption { - uint32_t CipherID; - uint32_t CipherOldID; - uint32_t ConversionProcess; - uint8_t SHA[32]; - uint8_t SHAOld[32]; - uint32_t Reserved[2]; -} TFileEncryption, *PFileEncryption; - -#pragma pack(pop) - -typedef struct TEncryption { - uint32_t CipherID; - wchar_t * Password; -} TEncryption, *PEncryption; - -class CEncryptionManager -{ -public: - CEncryptionManager(); - ~CEncryptionManager(); - - typedef struct { - TCHAR * FilePath; - TCHAR * FileName; - uint32_t ID; - wchar_t * Name; - wchar_t * Description; - } TCipherItem; - typedef std::map TCipherList; - - static TCipherList* CipherList; // = NULL; see cpp - static uint32_t CipherListRefCount; // = 0; see cpp - static void LoadCipherList(); - - bool InitEncryption(TFileEncryption & Enc); - - bool AlignData(uint32_t ID, uint32_t & Start, uint32_t & End); - uint32_t AlignSize(uint32_t ID, uint32_t Size); - bool IsEncrypted(uint32_t ID); - void Encrypt(void* Data, uint32_t DataLength, uint32_t ID, uint32_t StartByte); - void Decrypt(void* Data, uint32_t DataLength, uint32_t ID, uint32_t StartByte); - - bool CanChangeCipher(); - bool ChangeCipher(TEncryption & Encryption); -private: - bool m_Changing; - uint32_t m_ChangingProcess; - - typedef enum TUsedCiphers { - CURRENT = 0, - OLD = 1, - COUNT = 2 - } TUsedCiphers; - - struct - { - CCipher * Cipher; - HMODULE CipherDLL; - } m_Ciphers[COUNT]; - -}; diff --git a/plugins/Dbx_tree/Entities.cpp b/plugins/Dbx_tree/Entities.cpp deleted file mode 100644 index 73e9487ac6..0000000000 --- a/plugins/Dbx_tree/Entities.cpp +++ /dev/null @@ -1,1032 +0,0 @@ -/* - -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 "Entities.h" - -CVirtuals::CVirtuals(CBlockManager & BlockManager, TNodeRef RootNode) -: CFileBTree::CFileBTree(BlockManager, RootNode, cVirtualNodeSignature) -{ - -} - -CVirtuals::~CVirtuals() -{ - -} - -TDBTEntityHandle CVirtuals::_DeleteRealEntity(TDBTEntityHandle hRealEntity) -{ - TDBTEntityHandle result; - TVirtualKey key; - TEntity * entity; - bool copies = false; - uint32_t size = sizeof(TEntity); - uint32_t sig = cEntitySignature; - - key.RealEntity = hRealEntity; - key.Virtual = 0; - - iterator i = LowerBound(key); - result = i->Virtual; - i.setManaged(); - Delete(*i); - - while ((i) && (i->RealEntity == hRealEntity)) - { - key = *i; - Delete(key); - - key.RealEntity = result; - Insert(key); - - entity = m_BlockManager.ReadBlock(key.Virtual, size, sig); - if (entity) - { - entity->VParent = result; - m_BlockManager.UpdateBlock(key.Virtual); - - copies = true; - } // TODO log - } - - entity = m_BlockManager.ReadBlock(result, size, sig); - if (entity) - { - entity->Flags = entity->Flags & ~(DBT_NF_HasVirtuals | DBT_NF_IsVirtual); - if (copies) - entity->Flags |= DBT_NF_HasVirtuals; - - m_BlockManager.UpdateBlock(result); - } // TODO log - return result; -} - -bool CVirtuals::_InsertVirtual(TDBTEntityHandle hRealEntity, TDBTEntityHandle hVirtual) -{ - TVirtualKey key; - key.RealEntity = hRealEntity; - key.Virtual = hVirtual; - - Insert(key); - - return true; -} -void CVirtuals::_DeleteVirtual(TDBTEntityHandle hRealEntity, TDBTEntityHandle hVirtual) -{ - TVirtualKey key; - key.RealEntity = hRealEntity; - key.Virtual = hVirtual; - - Delete(key); -} -TDBTEntityHandle CVirtuals::getParent(TDBTEntityHandle hVirtual) -{ - TEntity * entity; - uint32_t size = sizeof(TEntity); - uint32_t sig = cEntitySignature; - - CBlockManager::ReadTransaction trans(m_BlockManager); - - entity = m_BlockManager.ReadBlock(hVirtual, size, sig); - if (!entity || ((entity->Flags & DBT_NF_IsVirtual) == 0)) - return DBT_INVALIDPARAM; - - return entity->VParent; -} -TDBTEntityHandle CVirtuals::getFirst(TDBTEntityHandle hRealEntity) -{ - TEntity * entity; - uint32_t size = sizeof(TEntity); - uint32_t sig = cEntitySignature; - - CBlockManager::ReadTransaction trans(m_BlockManager); - - entity = m_BlockManager.ReadBlock(hRealEntity, size, sig); - if (!entity || ((entity->Flags & DBT_NF_HasVirtuals) == 0)) - return DBT_INVALIDPARAM; - - TVirtualKey key; - key.RealEntity = hRealEntity; - key.Virtual = 0; - - iterator i = LowerBound(key); - - if (i && (i->RealEntity == hRealEntity)) - key.Virtual = i->Virtual; - else - key.Virtual = 0; - - return key.Virtual; -} -TDBTEntityHandle CVirtuals::getNext(TDBTEntityHandle hVirtual) -{ - TEntity * entity; - uint32_t size = sizeof(TEntity); - uint32_t sig = cEntitySignature; - - CBlockManager::ReadTransaction trans(m_BlockManager); - - entity = m_BlockManager.ReadBlock(hVirtual, size, sig); - if (!entity || ((entity->Flags & DBT_NF_IsVirtual) == 0)) - return DBT_INVALIDPARAM; - - TVirtualKey key; - key.RealEntity = entity->VParent; - key.Virtual = hVirtual + 1; - - iterator i = LowerBound(key); - - if ((i) && (i->RealEntity == entity->VParent)) - key.Virtual = i->Virtual; - else - key.Virtual = 0; - - return key.Virtual; -} - - - - -/////////////////////////////////////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////////////////// - -CEntities::CEntities(CBlockManager & BlockManager, TDBTEntityHandle RootEntity, TNodeRef EntityRoot, CVirtuals::TNodeRef VirtualRoot) -: CFileBTree::CFileBTree(BlockManager, EntityRoot, cEntityNodeSignature), - m_Virtuals(BlockManager, VirtualRoot), - - m_sigEntityDelete(), - m_sigInternalDeleteEvents(), - m_sigInternalDeleteSettings(), - m_sigInternalMergeSettings(), - m_sigInternalTransferEvents() -{ - if (RootEntity == 0) - m_RootEntity = _CreateRootEntity(); - else - m_RootEntity = RootEntity; - -} - -CEntities::~CEntities() -{ - -} - -TDBTEntityHandle CEntities::_CreateRootEntity() -{ - TEntity * entity; - TEntityKey key = {0,0,0}; - - CBlockManager::WriteTransaction trans(m_BlockManager); - - entity = m_BlockManager.CreateBlock(key.Entity, cEntitySignature); - entity->Flags = DBT_NF_IsGroup | DBT_NF_IsRoot; - m_BlockManager.UpdateBlock(key.Entity); - Insert(key); - return key.Entity; -} - -void CEntities::_InternalTransferContacts(TDBTEntityHandle OldAccount, TDBTEntityHandle NewAccount) -{ - uint32_t sig = cEntitySignature; - uint32_t size = sizeof(TEntity); - - TEntityKey key = {0,0,0}; - iterator i = LowerBound(key); - - while (i) - { - sig = cEntitySignature; - TEntity * entity = m_BlockManager.ReadBlock(i->Entity, size, sig); - if (entity && (entity->Account == OldAccount)) - { - entity->Account = NewAccount; - m_BlockManager.UpdateBlock(i->Entity); - } - - ++i; - } -} - -uint32_t CEntities::_getSettingsRoot(TDBTEntityHandle hEntity) -{ - /*CSettingsTree::TNodeRef*/ - uint32_t sig = cEntitySignature; - uint32_t size = sizeof(TEntity); - TEntity * entity = m_BlockManager.ReadBlock(hEntity, size, sig); - - if (!entity) - return DBT_INVALIDPARAM; - - return entity->Settings; -} -bool CEntities::_setSettingsRoot(TDBTEntityHandle hEntity, /*CSettingsTree::TNodeRef*/ uint32_t NewRoot) -{ - uint32_t sig = cEntitySignature; - uint32_t size = sizeof(TEntity); - TEntity * entity = m_BlockManager.ReadBlock(hEntity, size, sig); - - if (!entity) - return false; - - entity->Settings = NewRoot; - m_BlockManager.UpdateBlock(hEntity); - - return true; -} - -uint32_t CEntities::_getEventsRoot(TDBTEntityHandle hEntity) -{ - /*CEventsTree::TNodeRef*/ - uint32_t sig = cEntitySignature; - uint32_t size = sizeof(TEntity); - TEntity * entity = m_BlockManager.ReadBlock(hEntity, size, sig); - - if (!entity) - return DBT_INVALIDPARAM; - - return entity->Events; -} -bool CEntities::_setEventsRoot(TDBTEntityHandle hEntity, /*CEventsTree::TNodeRef*/ uint32_t NewRoot) -{ - uint32_t sig = cEntitySignature; - uint32_t size = sizeof(TEntity); - TEntity * entity = m_BlockManager.ReadBlock(hEntity, size, sig); - - if (!entity) - return false; - entity->Events = NewRoot; - m_BlockManager.UpdateBlock(hEntity); - - return true; -} - -uint32_t CEntities::_getEventCount(TDBTEntityHandle hEntity) -{ - uint32_t sig = cEntitySignature; - uint32_t size = sizeof(TEntity); - TEntity * entity = m_BlockManager.ReadBlock(hEntity, size, sig); - - if (!entity) - return DBT_INVALIDPARAM; - - return entity->EventCount; -} - -uint32_t CEntities::_adjustEventCount(TDBTEntityHandle hEntity, int32_t Adjust) -{ - uint32_t sig = cEntitySignature; - uint32_t size = sizeof(TEntity); - TEntity * entity = m_BlockManager.ReadBlock(hEntity, size, sig); - - if (!entity) - return DBT_INVALIDPARAM; - - if (((Adjust < 0) && ((uint32_t)(-Adjust) <= entity->EventCount)) || - ((Adjust > 0) && ((0xffffffff - entity->EventCount) > (uint32_t)Adjust))) - { - entity->EventCount += Adjust; - m_BlockManager.UpdateBlock(hEntity); - } - - return entity->EventCount; -} - -bool CEntities::_getFirstUnreadEvent(TDBTEntityHandle hEntity, uint32_t & hEvent, uint32_t & Timestamp) -{ - uint32_t sig = cEntitySignature; - uint32_t size = sizeof(TEntity); - TEntity * entity = m_BlockManager.ReadBlock(hEntity, size, sig); - - if (!entity) - return false; - - Timestamp = entity->FirstUnreadEventTimestamp; - hEvent = entity->FirstUnreadEventHandle; - return true; -} -bool CEntities::_setFirstUnreadEvent(TDBTEntityHandle hEntity, uint32_t hEvent, uint32_t Timestamp) -{ - uint32_t sig = cEntitySignature; - uint32_t size = sizeof(TEntity); - TEntity * entity = m_BlockManager.ReadBlock(hEntity, size, sig); - - if (!entity) - return false; - entity->FirstUnreadEventTimestamp = Timestamp; - entity->FirstUnreadEventHandle = hEvent; - m_BlockManager.UpdateBlock(hEntity); - - return true; -} - -TDBTEntityHandle CEntities::getParent(TDBTEntityHandle hEntity) -{ - uint32_t sig = cEntitySignature; - uint32_t size = sizeof(TEntity); - - CBlockManager::ReadTransaction trans(m_BlockManager); - - TEntity * entity = m_BlockManager.ReadBlock(hEntity, size, sig); - if (!entity) - return DBT_INVALIDPARAM; - - return entity->ParentEntity; -} -TDBTEntityHandle CEntities::setParent(TDBTEntityHandle hEntity, TDBTEntityHandle hParent) -{ - TEntity *entity, *newparent, *oldparent; - uint32_t size = sizeof(TEntity); - uint32_t sig = cEntitySignature; - - CBlockManager::WriteTransaction trans(m_BlockManager); - - entity = m_BlockManager.ReadBlock(hEntity, size, sig); - newparent = m_BlockManager.ReadBlock(hParent, size, sig); - if (!entity || !newparent) - return DBT_INVALIDPARAM; - - oldparent = m_BlockManager.ReadBlock(entity->ParentEntity, size, sig); - if (!oldparent) - return DBT_INVALIDPARAM; - - // update parents - if (--oldparent->ChildCount == 0) - oldparent->Flags &= ~DBT_NF_HasChildren; - - if (++newparent->ChildCount == 1) - newparent->Flags |= DBT_NF_HasChildren; - - - m_BlockManager.UpdateBlock(entity->ParentEntity); - m_BlockManager.UpdateBlock(hParent); - - // update rest - - TEntityKey key; - int dif = newparent->Level - entity->Level + 1; - - if (dif == 0) // no level difference, update only moved Entity - { - key.Entity = hEntity; - key.Level = entity->Level; - key.Parent = entity->ParentEntity; - Delete(key); - key.Parent = hParent; - Insert(key); - - entity->ParentEntity = hParent; - m_BlockManager.UpdateBlock(hEntity); - - } else { - TDBTEntityIterFilter filter = {0,0,0,0}; - filter.cbSize = sizeof(filter); - filter.Options = DBT_NIFO_OSC_AC | DBT_NIFO_OC_AC; - - TDBTEntityIterationHandle iter = IterationInit(filter, hEntity); - - key.Entity = IterationNext(iter); - - while ((key.Entity != 0) && (key.Entity != DBT_INVALIDPARAM)) - { - size = sizeof(TEntity); - sig = cEntitySignature; - TEntity * child = m_BlockManager.ReadBlock(key.Entity, size, sig); - - if (child) - { - key.Level = child->Level; - key.Parent = child->ParentEntity; - Delete(key); - - if (key.Entity == hEntity) - { - key.Parent = hParent; - entity->ParentEntity = hParent; - } - - child->Level += dif; - key.Level += dif; - m_BlockManager.UpdateBlock(key.Entity); - - Insert(key); - } // TODO log - key.Entity = IterationNext(iter); - } - - IterationClose(iter); - } - - /// TODO raise event - - return entity->ParentEntity; -} - -uint32_t CEntities::getChildCount(TDBTEntityHandle hEntity) -{ - uint32_t sig = cEntitySignature; - uint32_t size = sizeof(TEntity); - - CBlockManager::ReadTransaction trans(m_BlockManager); - - TEntity * entity = m_BlockManager.ReadBlock(hEntity, size, sig); - if (!entity) - return DBT_INVALIDPARAM; - - return entity->ChildCount; -} - -uint32_t CEntities::getFlags(TDBTEntityHandle hEntity) -{ - uint32_t sig = cEntitySignature; - uint32_t size = sizeof(TEntity); - - CBlockManager::ReadTransaction trans(m_BlockManager); - - TEntity * entity = m_BlockManager.ReadBlock(hEntity, size, sig); - if (!entity) - return DBT_INVALIDPARAM; - - return entity->Flags; -} - -uint32_t CEntities::getAccount(TDBTEntityHandle hEntity) -{ - uint32_t sig = cEntitySignature; - uint32_t size = sizeof(TEntity); - - CBlockManager::ReadTransaction trans(m_BlockManager); - - TEntity * entity = m_BlockManager.ReadBlock(hEntity, size, sig); - if (!entity) - return DBT_INVALIDPARAM; - - if (entity->Flags & DBT_NF_IsVirtual) - return getAccount(entity->VParent); - else if (entity->Flags & (DBT_NF_IsAccount | DBT_NF_IsGroup | DBT_NF_IsRoot)) - return 0; - - return entity->Flags; -} - -TDBTEntityHandle CEntities::CreateEntity(const TDBTEntity & Entity) -{ - uint32_t sig = cEntitySignature; - uint32_t size = sizeof(TEntity); - TDBTEntityHandle haccount = 0; - - CBlockManager::WriteTransaction trans(m_BlockManager); - - TEntity * parent = m_BlockManager.ReadBlock(Entity.hParentEntity, size, sig); - - if (!parent) - return DBT_INVALIDPARAM; - - // check account specification - if ((Entity.fFlags == 0) && (Entity.hAccountEntity != m_RootEntity)) // TODO disable root account thing, after conversion - { - TEntity * account = m_BlockManager.ReadBlock(Entity.hAccountEntity, size, sig); - if (!account || !(account->Flags & DBT_NF_IsAccount)) - return DBT_INVALIDPARAM; - - if (account->Flags & DBT_NF_IsVirtual) - { - haccount = VirtualGetParent(Entity.hAccountEntity); - } else { - haccount = Entity.hAccountEntity; - } - } - - TDBTEntityHandle hentity; - TEntity * entityblock = m_BlockManager.CreateBlock(hentity, cEntitySignature); - if (!entityblock) - return DBT_INVALIDPARAM; - - TEntityKey key; - - entityblock->Level = parent->Level + 1; - entityblock->ParentEntity = Entity.hParentEntity; - entityblock->Flags = Entity.fFlags; - entityblock->Account = haccount; - - m_BlockManager.UpdateBlock(hentity); - - key.Level = entityblock->Level; - key.Parent = entityblock->ParentEntity; - key.Entity = hentity; - - Insert(key); - - if (parent->ChildCount == 0) - parent->Flags = parent->Flags | DBT_NF_HasChildren; - - ++parent->ChildCount; - m_BlockManager.UpdateBlock(Entity.hParentEntity); - - return hentity; -} - -unsigned int CEntities::DeleteEntity(TDBTEntityHandle hEntity) -{ - uint32_t sig = cEntitySignature; - uint32_t size = sizeof(TEntity); - TDBTEntityHandle haccount = 0; - - CBlockManager::WriteTransaction trans(m_BlockManager); - - TEntity * entity = m_BlockManager.ReadBlock(hEntity, size, sig); - - if (!entity) - return DBT_INVALIDPARAM; - - TEntity * parent = m_BlockManager.ReadBlock(entity->ParentEntity, size, sig); - if (!parent) - return DBT_INVALIDPARAM; - - m_sigEntityDelete.emit(this, hEntity); - - if (entity->Flags & DBT_NF_HasVirtuals) - { - // move virtuals and make one of them real - TDBTEntityHandle newreal = m_Virtuals._DeleteRealEntity(hEntity); - - TEntity * realblock = m_BlockManager.ReadBlock(newreal, size, sig); - if (realblock) - { - realblock->EventCount = entity->EventCount; - realblock->Events = entity->Events; - - m_BlockManager.UpdateBlock(newreal); - - m_sigInternalTransferEvents.emit(this, hEntity, newreal); - m_sigInternalMergeSettings.emit(this, hEntity, newreal); - - if (entity->Flags & DBT_NF_IsAccount) - _InternalTransferContacts(hEntity, newreal); - } // TODO log - } else { - m_sigInternalDeleteEvents.emit(this, hEntity); - m_sigInternalDeleteSettings.emit(this, hEntity); - - if ((entity->Flags & DBT_NF_IsAccount) && !(entity->Flags & DBT_NF_IsVirtual)) - _InternalTransferContacts(hEntity, m_RootEntity); - - } - - TEntityKey key; - key.Level = entity->Level; - key.Parent = entity->ParentEntity; - key.Entity = hEntity; - Delete(key); - - if (entity->Flags & DBT_NF_HasChildren) // keep the children - { - parent->Flags |= DBT_NF_HasChildren; - parent->ChildCount += entity->ChildCount; - - TDBTEntityIterFilter filter = {0,0,0,0}; - filter.cbSize = sizeof(filter); - filter.Options = DBT_NIFO_OSC_AC | DBT_NIFO_OC_AC; - - TDBTEntityIterationHandle iter = IterationInit(filter, hEntity); - if (iter != DBT_INVALIDPARAM) - { - IterationNext(iter); - key.Entity = IterationNext(iter); - - while ((key.Entity != 0) && (key.Entity != DBT_INVALIDPARAM)) - { - size = sizeof(TEntity); - sig = cEntitySignature; - TEntity * child = m_BlockManager.ReadBlock(key.Entity, size, sig); - if (child) - { - key.Parent = child->ParentEntity; - key.Level = child->Level; - Delete(key); - - if (key.Parent == hEntity) - { - key.Parent = entity->ParentEntity; - child->ParentEntity = entity->ParentEntity; - } - - key.Level--; - m_BlockManager.UpdateBlock(key.Entity); - - Insert(key); - - } - key.Entity = IterationNext(iter); - } - - IterationClose(iter); - } - } - - if (--parent->ChildCount == 0) - parent->Flags = parent->Flags & (~DBT_NF_HasChildren); - - m_BlockManager.UpdateBlock(entity->ParentEntity); - - m_BlockManager.DeleteBlock(hEntity); // we needed this block, delete it now - - return 0; -} - - - -TDBTEntityIterationHandle CEntities::IterationInit(const TDBTEntityIterFilter & Filter, TDBTEntityHandle hParent) -{ - uint32_t sig = cEntitySignature; - uint32_t size = sizeof(TEntity); - TDBTEntityHandle haccount = 0; - - CBlockManager::ReadTransaction trans(m_BlockManager); - - TEntity * parent = m_BlockManager.ReadBlock(hParent, size, sig); - - if (!parent) - return DBT_INVALIDPARAM; - - PEntityIteration iter = new TEntityIteration; - iter->filter = Filter; - iter->q = new std::deque; - iter->parents = new std::deque; - iter->accounts = new std::deque; - #ifdef _MSC_VER - iter->returned = new stdext::hash_set; - #else - iter->returned = new __gnu_cxx::hash_set; - #endif - iter->returned->insert(hParent); - - TEntityIterationItem it; - it.Flags = parent->Flags; - it.Handle = hParent; - it.Level = parent->Level; - it.Options = Filter.Options & 0x000000ff; - it.LookupDepth = 0; - - iter->q->push_back(it); - - return (TDBTEntityIterationHandle)iter; -} -TDBTEntityHandle CEntities::IterationNext(TDBTEntityIterationHandle Iteration) -{ - uint32_t sig = cEntitySignature; - uint32_t size = sizeof(TEntity); - - CBlockManager::ReadTransaction trans(m_BlockManager); - - PEntityIteration iter = reinterpret_cast(Iteration); - TEntityIterationItem item; - TDBTEntityHandle result = 0; - - if (iter->q->empty()) - { - std::deque * tmp = iter->q; - iter->q = iter->parents; - iter->parents = tmp; - } - - if (iter->q->empty()) - { - std::deque * tmp = iter->q; - iter->q = iter->accounts; - iter->accounts = tmp; - } - - if (iter->q->empty() && - (iter->filter.Options & DBT_NIFO_GF_USEROOT) && - (iter->returned->find(m_RootEntity) == iter->returned->end())) - { - item.Handle = m_RootEntity; - item.Level = 0; - item.Options = 0; - item.Flags = 0; - item.LookupDepth = 255; - - iter->filter.Options = iter->filter.Options & ~DBT_NIFO_GF_USEROOT; - - iter->q->push_back(item); - } - - if (iter->q->empty()) - return 0; - - do { - item = iter->q->front(); - iter->q->pop_front(); - - std::deque tmp; - TEntityIterationItem newitem; - - // children - if ((item.Flags & DBT_NF_HasChildren) && - (item.Options & DBT_NIFO_OSC_AC)) - { - TEntityKey key; - key.Parent = item.Handle; - key.Level = item.Level + 1; - - newitem.Level = item.Level + 1; - newitem.LookupDepth = item.LookupDepth; - newitem.Options = (iter->filter.Options / DBT_NIFO_OC_AC * DBT_NIFO_OSC_AC) & (DBT_NIFO_OSC_AC | DBT_NIFO_OSC_AO | DBT_NIFO_OSC_AOC | DBT_NIFO_OSC_AOP); - - if (iter->filter.Options & DBT_NIFO_GF_DEPTHFIRST) - { - key.Entity = 0xffffffff; - - CEntities::iterator c = UpperBound(key); - while ((c) && (c->Parent == item.Handle)) - { - newitem.Handle = c->Entity; - - if (iter->returned->find(newitem.Handle) == iter->returned->end()) - { - TEntity * tmp = m_BlockManager.ReadBlock(newitem.Handle, size, sig); - if (tmp) - { - newitem.Flags = tmp->Flags; - if (((newitem.Flags & DBT_NF_IsGroup) == 0) || ((DBT_NF_IsGroup & iter->filter.fHasFlags) == 0)) // if we want only groups, we don't need to trace down Entities... - { - iter->q->push_front(newitem); - iter->returned->insert(newitem.Handle); - } - } - } - - --c; - } - } else { - key.Entity = 0; - - CEntities::iterator c = LowerBound(key); - while ((c) && (c->Parent == item.Handle)) - { - newitem.Handle = c->Entity; - - if (iter->returned->find(newitem.Handle) == iter->returned->end()) - { - TEntity * tmp = m_BlockManager.ReadBlock(newitem.Handle, size, sig); - if (tmp) - { - newitem.Flags = tmp->Flags; - if (((newitem.Flags & DBT_NF_IsGroup) == 0) || ((DBT_NF_IsGroup & iter->filter.fHasFlags) == 0)) // if we want only groups, we don't need to trace down Entities... - { - iter->q->push_back(newitem); - iter->returned->insert(newitem.Handle); - } - } - } - - ++c; - } - - } - } - - // parent... - if ((item.Options & DBT_NIFO_OSC_AP) && (item.Handle != m_RootEntity)) - { - newitem.Handle = getParent(item.Handle); - if ((iter->returned->find(newitem.Handle) == iter->returned->end()) && - (newitem.Handle != DBT_INVALIDPARAM)) - { - TEntity * tmp = m_BlockManager.ReadBlock(newitem.Handle, size, sig); - if (tmp) - { - newitem.Level = item.Level - 1; - newitem.LookupDepth = item.LookupDepth; - newitem.Options = (iter->filter.Options / DBT_NIFO_OP_AC * DBT_NIFO_OSC_AC) & (DBT_NIFO_OSC_AC | DBT_NIFO_OSC_AP | DBT_NIFO_OSC_AO | DBT_NIFO_OSC_AOC | DBT_NIFO_OSC_AOP); - newitem.Flags = tmp->Flags; - - if ((newitem.Flags & iter->filter.fDontHasFlags & DBT_NF_IsGroup) == 0) // if we don't want groups, stop it - { - iter->parents->push_back(newitem); - iter->returned->insert(newitem.Handle); - } - } - } - } - - // virtual lookup, original Entity is the next one - if ((item.Flags & DBT_NF_IsVirtual) && - (item.Options & DBT_NIFO_OSC_AO) && - (((iter->filter.Options >> 28) >= item.LookupDepth) || ((iter->filter.Options >> 28) == 0))) - { - newitem.Handle = VirtualGetParent(item.Handle); - - if ((iter->returned->find(newitem.Handle) == iter->returned->end()) && - (newitem.Handle != DBT_INVALIDPARAM)) - { - TEntity * tmp = m_BlockManager.ReadBlock(newitem.Handle, size, sig); - if (tmp) - { - newitem.Level = tmp->Level; - newitem.Options = 0; - newitem.Flags = tmp->Flags; - - if ((item.Options & DBT_NIFO_OSC_AOC) == DBT_NIFO_OSC_AOC) - newitem.Options |= DBT_NIFO_OSC_AC; - if ((item.Options & DBT_NIFO_OSC_AOP) == DBT_NIFO_OSC_AOP) - newitem.Options |= DBT_NIFO_OSC_AP; - - newitem.LookupDepth = item.LookupDepth + 1; - - iter->q->push_front(newitem); - iter->returned->insert(newitem.Handle); - } - } - } - - if (((iter->filter.fHasFlags & item.Flags) == iter->filter.fHasFlags) && - ((iter->filter.fDontHasFlags & item.Flags) == 0)) - { - result = item.Handle; - - // account lookup - if (((item.Flags & (DBT_NF_IsAccount | DBT_NF_IsGroup | DBT_NF_IsRoot)) == 0) && - ((item.Options & DBT_NIFO_OC_USEACCOUNT) == DBT_NIFO_OC_USEACCOUNT)) - { - TDBTEntityHandle acc = item.Handle; - if (item.Flags & DBT_NF_IsVirtual) - acc = VirtualGetParent(item.Handle); - - acc = getAccount(acc); - - std::deque::iterator acci = iter->accounts->begin(); - - while ((acci != iter->accounts->end()) && (acc != 0)) - { - if (acci->Handle == acc) - acc = 0; - acci++; - } - if (acc != 0) - { - TEntity * tmp = m_BlockManager.ReadBlock(acc, size, sig); - if (tmp) - { - newitem.Options = 0; - newitem.LookupDepth = 0; - newitem.Handle = acc; - newitem.Flags = tmp->Flags; - newitem.Level = tmp->Level; - iter->accounts->push_back(newitem); - } - } - } - } - - } while ((result == 0) && !iter->q->empty()); - - if (result == 0) - result = IterationNext(Iteration); - - return result; -} -unsigned int CEntities::IterationClose(TDBTEntityIterationHandle Iteration) -{ - PEntityIteration iter = reinterpret_cast(Iteration); - - delete iter->q; - delete iter->parents; - delete iter->accounts; - delete iter->returned; - delete iter; - - return 0; -} - - -TDBTEntityHandle CEntities::VirtualCreate(TDBTEntityHandle hRealEntity, TDBTEntityHandle hParent) -{ - uint32_t sig = cEntitySignature; - uint32_t size = sizeof(TEntity); - TDBTEntityHandle haccount = 0; - - CBlockManager::WriteTransaction trans(m_BlockManager); - - TEntity * realentity = m_BlockManager.ReadBlock(hRealEntity, size, sig); - - if (!realentity || (realentity->Flags & (DBT_NF_IsGroup | DBT_NF_IsRoot))) - return DBT_INVALIDPARAM; - - TDBTEntity entity = {0,0,0,0}; - entity.hParentEntity = hParent; - entity.fFlags = DBT_NF_IsVirtual | (realentity->Flags & DBT_NF_IsAccount); - entity.hAccountEntity = 0; - - TDBTEntityHandle result = CreateEntity(entity); - if (result == DBT_INVALIDPARAM) - return DBT_INVALIDPARAM; - - TEntity * entityblock = m_BlockManager.ReadBlock(result, size, sig); - if (!entityblock) - return DBT_INVALIDPARAM; - - if (realentity->Flags & DBT_NF_IsVirtual) - { - hRealEntity = realentity->VParent; - realentity = m_BlockManager.ReadBlock(hRealEntity, size, sig); - - if (!realentity) - return DBT_INVALIDPARAM; - } - - entityblock->VParent = hRealEntity; - m_BlockManager.UpdateBlock(result); - - if ((realentity->Flags & DBT_NF_HasVirtuals) == 0) - { - realentity->Flags |= DBT_NF_HasVirtuals; - m_BlockManager.UpdateBlock(hRealEntity); - } - - m_Virtuals._InsertVirtual(hRealEntity, result); - return result; -} - - -TDBTEntityHandle CEntities::compFirstContact() -{ - uint32_t sig = cEntitySignature; - uint32_t size = sizeof(TEntity); - - CBlockManager::ReadTransaction trans(m_BlockManager); - - TEntityKey key = {0,0,0}; - iterator i = LowerBound(key); - TDBTEntityHandle res = 0; - - while (i && (res == 0)) - { - TEntity * tmp = m_BlockManager.ReadBlock(i->Entity, size, sig); - if (tmp) - { - if ((tmp->Flags & DBT_NFM_SpecialEntity) == 0) - res = i->Entity; - } - if (res == 0) - ++i; - } - - return res; -} -TDBTEntityHandle CEntities::compNextContact(TDBTEntityHandle hEntity) -{ - uint32_t sig = cEntitySignature; - uint32_t size = sizeof(TEntity); - - CBlockManager::ReadTransaction trans(m_BlockManager); - - TEntityKey key; - key.Entity = hEntity; - TDBTEntityHandle res = 0; - - TEntity * entity = m_BlockManager.ReadBlock(hEntity, size, sig); - - if (entity) - { - key.Level = entity->Level; - key.Parent = entity->ParentEntity; - key.Entity++; - iterator i = LowerBound(key); - - while (i && (res == 0)) - { - entity = m_BlockManager.ReadBlock(i->Entity, size, sig); - if (entity) - { - if ((entity->Flags & DBT_NFM_SpecialEntity) == 0) - res = i->Entity; - } - if (res == 0) - ++i; - } - } - - return res; -} diff --git a/plugins/Dbx_tree/Entities.h b/plugins/Dbx_tree/Entities.h deleted file mode 100644 index 579383d15f..0000000000 --- a/plugins/Dbx_tree/Entities.h +++ /dev/null @@ -1,299 +0,0 @@ -/* - -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. - -*/ - -#pragma once - -#include "Interface.h" -#include "FileBTree.h" -#include "MREWSync.h" -#include -#ifdef _MSC_VER -#include -#else -#include -#endif - -#pragma pack(push, 1) // push current alignment to stack, set alignment to 1 byte boundary - - -/** - \brief Key Type of the VirtualsBTree - - This BTree don't hold data itself, it's just for organisation - The virtual Entities are sorted first based on their real Entity. - That is for enumeration of one Entity's virtual copies, which are all stored in one block in the BTree -**/ -typedef struct TVirtualKey { - TDBTEntityHandle RealEntity; /// hEntity of the duplicated RealEntity - TDBTEntityHandle Virtual; /// hEntity of the virtual duplicate - - bool operator < (const TVirtualKey & Other) const - { - if (RealEntity != Other.RealEntity) return RealEntity < Other.RealEntity; - if (Virtual != Other.Virtual) return Virtual < Other.Virtual; - return false; - } - //bool operator <= (const TVirtualKey & Other); - bool operator == (const TVirtualKey & Other) const - { - return (RealEntity == Other.RealEntity) && (Virtual == Other.Virtual); - } - //bool operator >= (const TVirtualKey & Other); - bool operator > (const TVirtualKey & Other) const - { - if (RealEntity != Other.RealEntity) return RealEntity > Other.RealEntity; - if (Virtual != Other.Virtual) return Virtual > Other.Virtual; - return false; - } -} TVirtualKey; - -/** - \brief Key Type of the EntityBTree - - The Entities are sorted first based on their level. (root is first node, followed by its children) - That is for enumeration of one Entity's children, which are all stored in one block in the BTree -**/ -typedef struct TEntityKey { - uint16_t Level; /// Level where Entity is located or parent-steps to root. Root.Level == 0, root children have level 1 etc. - TDBTEntityHandle Parent; /// hEntity of the Parent. Root.Parent == 0 - TDBTEntityHandle Entity; /// hEntity of the stored Entity itself - - bool operator < (const TEntityKey & Other) const - { - if (Level != Other.Level) return Level < Other.Level; - if (Parent != Other.Parent) return Parent < Other.Parent; - if (Entity != Other.Entity) return Entity < Other.Entity; - return false; - } - //bool operator <= (const TEntityKey & Other); - bool operator == (const TEntityKey & Other) const - { - return (Level == Other.Level) && (Parent == Other.Parent) && (Entity == Other.Entity); - } - //bool operator >= (const TEntityKey & Other); - bool operator > (const TEntityKey & Other) const - { - if (Level != Other.Level) return Level > Other.Level; - if (Parent != Other.Parent) return Parent > Other.Parent; - if (Entity != Other.Entity) return Entity > Other.Entity; - return false; - } -} TEntityKey; - -/** - \brief The data of an Entity -**/ -typedef struct TEntity { - uint16_t Level; /// Level where Entity is located or parent-steps to root. Root.Level == 0, root children have level 1 etc. !used in the BTreeKey! - uint16_t ChildCount; /// Count of the children !invalid for Virtual Entity! - TDBTEntityHandle ParentEntity; /// hEntity of the Parent. Root.Parent == 0 !used in the BTreeKey! - union { - TDBTEntityHandle VParent; /// if the Entity is Virtual this is the hEntity of the related Realnode - TDBTEntityHandle Account; /// if the Entity's account, only for real real normal Entities - }; - uint32_t Flags; /// flags, see cEF_* - /*CSettingsTree::TNodeRef*/ - uint32_t Settings; /// Offset to the SettingsBTree RootNode of this Entity, NULL if no settings are present - /*CEventsTree::TNodeRef*/ - uint32_t Events; /// Offset to the EventsBTree RootNode of this Entity, NULL if no events are present !invalid for Virtal Entity! - uint32_t EventCount; /// Count of the stored events !invalid for Virtual Entity! - uint32_t FirstUnreadEventTimestamp; /// timestamp of the first unread event - uint32_t FirstUnreadEventHandle;/// ID of the first unread event - uint8_t Reserved[4]; /// reserved storage -} TEntity; - -#pragma pack(pop) // pop the alignment from stack - - - - -/** - \brief Manages the Virtual Entities in the Database - - A virtual Entity is stored as normal Entity in the database-structure, but doesn't hold own settings/events. - Such an Entity has the virtual flag set and refers its original duplicate. - All copies are stored in this BTree sorted to the RealEntity. - If the RealEntity should be deleted take the first virtual duplicate and make it real. Also change the relation of other copies. -**/ -class CVirtuals : public CFileBTree -{ -private: - -protected: - -public: - CVirtuals(CBlockManager & BlockManager, TNodeRef Root); - virtual ~CVirtuals(); - - /** - \brief Changes reference for all copies to the first Virtual in list - - \return New Original (previously first Virtual) to associate data with - **/ - TDBTEntityHandle _DeleteRealEntity(TDBTEntityHandle hRealEntity); - - bool _InsertVirtual(TDBTEntityHandle hRealEntity, TDBTEntityHandle hVirtual); - void _DeleteVirtual(TDBTEntityHandle hRealEntity, TDBTEntityHandle hVirtual); - - // services: - TDBTEntityHandle getParent(TDBTEntityHandle hVirtual); - TDBTEntityHandle getFirst(TDBTEntityHandle hRealEntity); - TDBTEntityHandle getNext(TDBTEntityHandle hVirtual); -}; - - -static const uint32_t cEntitySignature = 0x9A6B3C0D; -static const uint16_t cEntityNodeSignature = 0x65A9; -static const uint16_t cVirtualNodeSignature = 0x874E; -/** - \brief Manages the Entities in the Database - - A hEntity is equivalent to the fileoffset of its related TEntity structure -**/ -class CEntities : public CFileBTree -{ - -public: - CEntities(CBlockManager & BlockManager, TDBTEntityHandle RootEntity, TNodeRef EntityRoot, CVirtuals::TNodeRef VirtualRoot); - virtual ~CEntities(); - - typedef sigslot::signal2 TOnEntityDelete; - typedef sigslot::signal2 TOnInternalDeleteSettings; - typedef sigslot::signal2 TOnInternalDeleteEvents; - - typedef sigslot::signal3 TOnInternalMergeSettings; - typedef sigslot::signal3 TOnInternalTransferEvents; - - CVirtuals::TOnRootChanged & sigVirtualRootChanged() - { - return m_Virtuals.sigRootChanged(); - }; - - TOnEntityDelete & sigEntityDelete() - { - return m_sigEntityDelete; - }; - TOnInternalDeleteEvents & _sigDeleteEvents() - { - return m_sigInternalDeleteEvents; - }; - TOnInternalDeleteSettings & _sigDeleteSettings() - { - return m_sigInternalDeleteSettings; - }; - TOnInternalMergeSettings & _sigMergeSettings() - { - return m_sigInternalMergeSettings; - }; - TOnInternalTransferEvents & _sigTransferEvents() - { - return m_sigInternalTransferEvents; - }; - - //internal helpers: - /*CSettingsTree::TNodeRef*/ - uint32_t _getSettingsRoot(TDBTEntityHandle hEntity); - bool _setSettingsRoot(TDBTEntityHandle hEntity, /*CSettingsTree::TNodeRef*/ uint32_t NewRoot); - uint32_t _getEventsRoot(TDBTEntityHandle hEntity); - bool _setEventsRoot(TDBTEntityHandle hEntity, /*CSettingsTree::TNodeRef*/ uint32_t NewRoot); - uint32_t _getEventCount(TDBTEntityHandle hEntity); - uint32_t _adjustEventCount(TDBTEntityHandle hEntity, int32_t Adjust); - bool _getFirstUnreadEvent(TDBTEntityHandle hEntity, uint32_t & hEvent, uint32_t & Timestamp); - bool _setFirstUnreadEvent(TDBTEntityHandle hEntity, uint32_t hEvent, uint32_t Timestamp); - - CVirtuals & _getVirtuals() - { - return m_Virtuals; - }; - - //compatibility: - TDBTEntityHandle compFirstContact(); - TDBTEntityHandle compNextContact(TDBTEntityHandle hEntity); - //Services: - TDBTEntityHandle CEntities::getRootEntity() - { - return m_RootEntity; - }; - - TDBTEntityHandle getParent(TDBTEntityHandle hEntity); - TDBTEntityHandle setParent(TDBTEntityHandle hEntity, TDBTEntityHandle hParent); - uint32_t getChildCount(TDBTEntityHandle hEntity); - uint32_t getFlags(TDBTEntityHandle hEntity); - uint32_t getAccount(TDBTEntityHandle hEntity); - - TDBTEntityHandle CreateEntity(const TDBTEntity & Entity); - unsigned int DeleteEntity(TDBTEntityHandle hEntity); - - TDBTEntityIterationHandle IterationInit(const TDBTEntityIterFilter & Filter, TDBTEntityHandle hParent); - TDBTEntityHandle IterationNext(TDBTEntityIterationHandle Iteration); - unsigned int IterationClose(TDBTEntityIterationHandle Iteration); - - TDBTEntityHandle VirtualCreate(TDBTEntityHandle hRealEntity, TDBTEntityHandle hParent); - TDBTEntityHandle VirtualGetParent(TDBTEntityHandle hVirtual) - { - return m_Virtuals.getParent(hVirtual); - }; - TDBTEntityHandle VirtualGetFirst(TDBTEntityHandle hRealEntity) - { - return m_Virtuals.getFirst(hRealEntity); - }; - TDBTEntityHandle VirtualGetNext(TDBTEntityHandle hVirtual) - { - return m_Virtuals.getNext(hVirtual); - }; -private: - -protected: - - typedef struct TEntityIterationItem { - uint8_t Options; - uint8_t LookupDepth; - uint16_t Level; - TDBTEntityHandle Handle; - uint32_t Flags; - } TEntityIterationItem; - - typedef struct TEntityIteration { - TDBTEntityIterFilter filter; - std::deque * q; - std::deque * parents; - std::deque * accounts; - #ifdef _MSC_VER - stdext::hash_set * returned; - #else - __gnu_cxx::hash_set * returned; - #endif - } TEntityIteration, *PEntityIteration; - - TDBTEntityHandle m_RootEntity; - CVirtuals m_Virtuals; - - TDBTEntityHandle _CreateRootEntity(); - void _InternalTransferContacts(TDBTEntityHandle OldAccount, TDBTEntityHandle NewAccount); - - TOnEntityDelete m_sigEntityDelete; - TOnInternalDeleteEvents m_sigInternalDeleteEvents; - TOnInternalDeleteSettings m_sigInternalDeleteSettings; - TOnInternalMergeSettings m_sigInternalMergeSettings; - TOnInternalTransferEvents m_sigInternalTransferEvents; - -}; diff --git a/plugins/Dbx_tree/Events.cpp b/plugins/Dbx_tree/Events.cpp deleted file mode 100644 index 732f6241c2..0000000000 --- a/plugins/Dbx_tree/Events.cpp +++ /dev/null @@ -1,986 +0,0 @@ -/* - -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 "Events.h" -#ifndef _MSC_VER -#include "savestrings_gcc.h" -#endif - - -CEventsTypeManager::CEventsTypeManager(CEntities & Entities, CSettings & Settings) -: m_Entities(Entities), - m_Settings(Settings), - m_Map() -{ - m_Settings._EnsureModuleExists("$EventTypes"); -} -CEventsTypeManager::~CEventsTypeManager() -{ - TTypeMap::iterator it = m_Map.begin(); - - while (it != m_Map.end()) - { - delete [] it->second->ModuleName; - delete it->second; - ++it; - } -} - -uint32_t CEventsTypeManager::MakeGlobalID(char* Module, uint32_t EventType) -{ - uint32_t l = static_cast(strlen(Module)); - void * buf = malloc(l + sizeof(uint32_t)); - memcpy(buf, Module, l); - memcpy(((char*)buf) + l, &EventType, sizeof(uint32_t)); - - uint32_t h = Hash(buf, l + sizeof(uint32_t)); - free(buf); - - char * m; - uint32_t t; - while (GetType(h, m, t) && ((t != EventType) || (strcmp(m, Module) != 0))) - { - ++h; - } - - return h; -} -bool CEventsTypeManager::GetType(uint32_t GlobalID, char * & Module, uint32_t & EventType) -{ - TTypeMap::iterator it = m_Map.find(GlobalID); - - if (it == m_Map.end()) - { - char n[256]; - - TDBTSettingDescriptor d = {0,0,0,0,0,0,0,0}; - d.cbSize = sizeof(d); - d.Entity = m_Entities.getRootEntity(); - d.pszSettingName = n; - - TDBTSetting sid = {0,0,0,0}; - TDBTSetting sname = {0,0,0,0}; - - sid.cbSize = sizeof(sid); - sid.Descriptor = &d; - sid.Type = DBT_ST_INT; - - sname.cbSize = sizeof(sname); - sname.Descriptor = &d; - sname.Type = DBT_ST_ANSI; - - sprintf_s(n, "$EventTypes/%08x/ModuleID", GlobalID); - TDBTSettingHandle h = m_Settings.ReadSetting(sid); - - if ((h != DBT_INVALIDPARAM) && (h != 0)) - { - sprintf_s(n, "$EventTypes/%08x/ModuleName", GlobalID); - d.Flags = 0; - h = m_Settings.ReadSetting(sname); - - if ((h != DBT_INVALIDPARAM) && (h != 0)) - { - PEventType t = new TEventType; - - t->EventType = sid.Value.Int; - - t->ModuleName = new char[sname.Value.Length]; - strcpy_s(t->ModuleName, sname.Value.Length, sname.Value.pAnsi); - - m_Map.insert(std::make_pair(GlobalID, t)); - - mir_free(sname.Value.pAnsi); - - Module = t->ModuleName; - EventType = t->EventType; - - return true; - } - } - } else { - Module = it->second->ModuleName; - EventType = it->second->EventType; - - return true; - } - - return false; -} - -uint32_t CEventsTypeManager::EnsureIDExists(char* Module, uint32_t EventType) -{ - uint32_t res = MakeGlobalID(Module, EventType); - char * m; - uint32_t t; - if (!GetType(res, m, t)) - { - char n[256]; - - TDBTSettingDescriptor d = {0,0,0,0,0,0,0,0}; - d.cbSize = sizeof(d); - d.pszSettingName = n; - d.Entity = m_Entities.getRootEntity(); - - TDBTSetting s = {0,0,0,0}; - s.cbSize = sizeof(s); - s.Descriptor = &d; - - sprintf_s(n, "$EventTypes/%08x/ModuleID", res); - s.Type = DBT_ST_INT; - s.Value.Int = EventType; - m_Settings.WriteSetting(s); - - sprintf_s(n, "$EventTypes/%08x/ModuleName", res); - d.Flags = 0; - s.Type = DBT_ST_ANSI; - s.Value.Length = static_cast(strlen(Module) + 1); - s.Value.pAnsi = Module; - m_Settings.WriteSetting(s); - - m_Settings._EnsureModuleExists(Module); - } - - return res; -} - - -CEvents::CEvents( - CBlockManager & BlockManager, - CEncryptionManager & EncryptionManager, - CEntities & Entities, - CSettings & Settings -) -: m_BlockManager(BlockManager), - m_EncryptionManager(EncryptionManager), - m_Entities(Entities), - m_Types(Entities, Settings), - m_EntityEventsMap() -{ - m_Entities._sigDeleteEvents().connect(this, &CEvents::onDeleteEvents); - m_Entities._sigTransferEvents().connect(this, &CEvents::onTransferEvents); -} - -CEvents::~CEvents() -{ - TEntityEventsMap::iterator i = m_EntityEventsMap.begin(); - while (i != m_EntityEventsMap.end()) - { - delete i->second->RealTree; - delete i->second->VirtualTree; - delete i->second; - ++i; - } -} - -void CEvents::onRootChanged(void* EventsTree, CEventsTree::TNodeRef NewRoot) -{ - m_Entities._setEventsRoot(reinterpret_cast(EventsTree)->Entity(), NewRoot); -} - -void CEvents::onDeleteEventCallback(void * Tree, const TEventKey & Key, uint32_t Param) -{ - m_BlockManager.DeleteBlock(Key.Event); -} - -void CEvents::onDeleteVirtualEventCallback(void * Tree, const TEventKey & Key, uint32_t Param) -{ - m_BlockManager.DeleteBlock(Key.Event); -} -void CEvents::onDeleteEvents(CEntities * Entities, TDBTEntityHandle hEntity) -{ - PEntityEventsRecord record = getEntityRecord(hEntity); - - if (record == NULL) - return; - - m_Entities._setEventsRoot(hEntity, 0); - - if (record->VirtualCount) - { - CVirtualEventsTree::TDeleteCallback callback; - callback.connect(this, &CEvents::onDeleteVirtualEventCallback); - - record->VirtualTree->DeleteTree(&callback, hEntity); - } - delete record->VirtualTree; - - CEventsTree::TDeleteCallback callback; - callback.connect(this, &CEvents::onDeleteEventCallback); - record->RealTree->DeleteTree(&callback, hEntity); - delete record->RealTree; - m_EntityEventsMap.erase(hEntity); -} -void CEvents::onTransferEvents(CEntities * Entities, TDBTEntityHandle Source, TDBTEntityHandle Dest) -{ - PEntityEventsRecord record = getEntityRecord(Source); - - if (record == NULL) - return; - - if (record->VirtualCount) - { - TEventKey key = {0,0}; - - CVirtualEventsTree::iterator i = record->VirtualTree->LowerBound(key); - - while (i) - { - uint32_t sig = cEventSignature; - uint32_t size = 0; - TEvent * tmp = m_BlockManager.ReadBlock(i->Event, size, sig); - if (tmp) - { - tmp->Entity = Dest; - m_BlockManager.UpdateBlock(i->Event); - } - ++i; - } - } - - { - TEventKey key = {0,0}; - - CEventsTree::iterator i = record->RealTree->LowerBound(key); - while (i) - { - uint32_t sig = cEventSignature; - uint32_t size = 0; - TEvent * tmp = m_BlockManager.ReadBlock(i->Event, size, sig); - if (tmp) - { - tmp->Entity = Dest; - m_BlockManager.UpdateBlock(i->Event); - } - ++i; - } - - m_Entities._setEventsRoot(Source, 0); - m_Entities._setEventsRoot(Dest, record->RealTree->getRoot()); - m_Entities._adjustEventCount(Dest, m_Entities._getEventCount(Source)); - m_Entities._getFirstUnreadEvent(Source, key.Event, key.TimeStamp); - m_Entities._setFirstUnreadEvent(Dest, key.Event, key.TimeStamp); - } - - record->VirtualTree->Entity(Dest); - record->RealTree->Entity(Dest); - m_EntityEventsMap.erase(Source); - m_EntityEventsMap.insert(std::make_pair(Dest, record)); -} - -CEvents::PEntityEventsRecord CEvents::getEntityRecord(TDBTEntityHandle hEntity) -{ - TEntityEventsMap::iterator i = m_EntityEventsMap.find(hEntity); - if (i != m_EntityEventsMap.end()) - return i->second; - - uint32_t root = m_Entities._getEventsRoot(hEntity); - if (root == DBT_INVALIDPARAM) - return NULL; - - PEntityEventsRecord res = new TEntityEventsRecord; - res->RealTree = new CEventsTree(m_BlockManager, root, hEntity); - res->RealTree->sigRootChanged().connect(this, &CEvents::onRootChanged); - res->VirtualTree = new CVirtualEventsTree(hEntity); - res->VirtualCount = 0; - res->FirstVirtualUnread.TimeStamp = 0; - res->FirstVirtualUnread.Event = 0; - m_EntityEventsMap.insert(std::make_pair(hEntity, res)); - - return res; -} - -inline uint32_t CEvents::adjustVirtualEventCount(PEntityEventsRecord Record, int32_t Adjust) -{ - if (((Adjust < 0) && ((uint32_t)(-Adjust) <= Record->VirtualCount)) || - ((Adjust > 0) && ((0xffffffff - Record->VirtualCount) > (uint32_t)Adjust))) - { - Record->VirtualCount += Adjust; - } - - return Record->VirtualCount; -} - -inline bool CEvents::MarkEventsTree(TEventBase::iterator Iterator, TDBTEventHandle FirstUnread) -{ - uint32_t sig, size; - bool b = true; - bool res = false; - while (Iterator && b) - { - sig = cEventSignature; - size = 0; - TEvent * event = m_BlockManager.ReadBlock(Iterator->Event, size, sig); - if (event) - { - if (Iterator->Event == FirstUnread) - res = true; - - if ((event->Flags & DBT_EF_READ) == 0) - { - event->Flags |= DBT_EF_READ; - m_BlockManager.UpdateBlock(Iterator->Event); - --Iterator; - } else { - b = false; - } - } else { - --Iterator; - } - } - return res; -} -inline void CEvents::FindNextUnreadEvent(TEventBase::iterator & Iterator) -{ - uint32_t sig, size; - while (Iterator) - { - sig = cEventSignature; - size = 0; - TEvent * event = m_BlockManager.ReadBlock(Iterator->Event, size, sig); - if (event) - { - if (event->Flags & DBT_EF_READ) - ++Iterator; - else - return; - } else { - ++Iterator; - } - } -} - -unsigned int CEvents::GetBlobSize(TDBTEventHandle hEvent) -{ - uint32_t sig = cEventSignature; - uint32_t size = 0; - - CBlockManager::ReadTransaction trans(m_BlockManager); - TEvent * event = m_BlockManager.ReadBlock(hEvent, size, sig); - if (!event) - return DBT_INVALIDPARAM; - - return event->DataLength; -} - -unsigned int CEvents::Get(TDBTEventHandle hEvent, TDBTEvent & Event) -{ - uint32_t sig = cEventSignature; - uint32_t size = 0; - - CBlockManager::ReadTransaction trans(m_BlockManager); - - TEvent * event = m_BlockManager.ReadBlock(hEvent, size, sig); - if (!event) - return DBT_INVALIDPARAM; - - uint8_t * blob = reinterpret_cast(event + 1); - - if (!m_Types.GetType(event->Type, Event.ModuleName, Event.EventType)) - { - Event.EventType = event->Type; - Event.ModuleName = "???"; - } - - Event.Flags = event->Flags; - if (m_BlockManager.IsForcedVirtual(hEvent)) - Event.Flags |= DBT_EF_VIRTUAL; - - Event.Timestamp = event->TimeStamp; - - if (Event.cbBlob < event->DataLength) - Event.pBlob = (uint8_t*) mir_realloc(Event.pBlob, event->DataLength); - - memcpy(Event.pBlob, blob, event->DataLength); - Event.cbBlob = event->DataLength; - - return 0; -} - -unsigned int CEvents::GetCount(TDBTEntityHandle hEntity) -{ - CBlockManager::ReadTransaction trans(m_BlockManager); - - uint32_t res = m_Entities._getEventCount(hEntity); - PEntityEventsRecord record = getEntityRecord(hEntity); - - if ((res == DBT_INVALIDPARAM) || !record) - return DBT_INVALIDPARAM; - - res = res + record->VirtualCount; // access to Virtual Count need sync, too - - return res; -} - -unsigned int CEvents::Delete(TDBTEventHandle hEvent) -{ - uint32_t sig = cEventSignature; - uint32_t size = 0; - TEventKey key = {0, hEvent}; - - CBlockManager::WriteTransaction trans(m_BlockManager); - - TEvent * event = m_BlockManager.ReadBlock(hEvent, size, sig); - if (!event) - return DBT_INVALIDPARAM; - - key.TimeStamp = event->TimeStamp; - - PEntityEventsRecord record = getEntityRecord(event->Entity); - if (!record) - return DBT_INVALIDPARAM; - - if (m_BlockManager.IsForcedVirtual(hEvent)) - { - if (record->VirtualTree->Delete(key)) - { - adjustVirtualEventCount(record, -1); - - if (record->FirstVirtualUnread.Event == hEvent) - { - CVirtualEventsTree::iterator vi = record->VirtualTree->LowerBound(key); - FindNextUnreadEvent(vi); - if (vi) - { - record->FirstVirtualUnread = *vi; - } else { - record->FirstVirtualUnread.TimeStamp = 0; - record->FirstVirtualUnread.Event = 0; - } - } - } - } else { // real event - if (record->RealTree->Delete(key)) - { - m_Entities._adjustEventCount(event->Entity, -1); - TEventKey unreadkey; - m_Entities._getFirstUnreadEvent(event->Entity, unreadkey.Event, unreadkey.TimeStamp); - if (unreadkey.Event == hEvent) - { - CEventsTree::iterator it = record->VirtualTree->LowerBound(key); - FindNextUnreadEvent(it); - if (it) - { - m_Entities._setFirstUnreadEvent(event->Entity, it->Event, it->TimeStamp); - } else { - m_Entities._setFirstUnreadEvent(event->Entity, 0, 0); - } - } - } - } - m_BlockManager.DeleteBlock(hEvent); - - return 0; -} - -TDBTEventHandle CEvents::Add(TDBTEntityHandle hEntity, TDBTEvent & Event) -{ - TDBTEventHandle res = 0; - TEvent * event; - - CBlockManager::WriteTransaction trans(m_BlockManager); - - uint32_t eflags = m_Entities.getFlags(hEntity); - PEntityEventsRecord record = getEntityRecord(hEntity); - - if ((eflags == DBT_INVALIDPARAM) || - ((eflags & (DBT_NF_IsGroup | DBT_NF_IsRoot)) == DBT_NF_IsGroup) || // forbid events in groups. but allow root to have system history - !record) - { - return DBT_INVALIDPARAM; - } - - if (eflags & DBT_NF_IsVirtual) - hEntity = m_Entities.VirtualGetParent(hEntity); - - uint8_t *blobdata = Event.pBlob; - bool bloballocated = false; - - if (Event.Flags & DBT_EF_VIRTUAL) - { - event = m_BlockManager.CreateBlockVirtual(res, cEventSignature, sizeof(TEvent) + Event.cbBlob); - } else { - event = m_BlockManager.CreateBlock(res, cEventSignature, sizeof(TEvent) + Event.cbBlob); - } - - if (!event) - return DBT_INVALIDPARAM; - - TEventKey key = {0,0}; - - event->TimeStamp = Event.Timestamp; - event->Flags = Event.Flags & ~DBT_EF_VIRTUAL; - event->Type = m_Types.EnsureIDExists(Event.ModuleName, Event.EventType); - event->DataLength = Event.cbBlob; - event->Entity = hEntity; - - key.TimeStamp = event->TimeStamp; - key.Event = res; - memcpy(event + 1, Event.pBlob, Event.cbBlob); - - m_BlockManager.UpdateBlock(res); - - if (Event.Flags & DBT_EF_VIRTUAL) - { - record->VirtualTree->Insert(key); - adjustVirtualEventCount(record, +1); - if (!(Event.Flags & DBT_EF_READ) && ((record->FirstVirtualUnread.Event == 0) || (key < record->FirstVirtualUnread))) - { - record->FirstVirtualUnread = key; - } - } else { - record->RealTree->Insert(key); - m_Entities._adjustEventCount(hEntity, +1); - - if (!(Event.Flags & DBT_EF_READ)) - { - TEventKey unreadkey; - if (m_Entities._getFirstUnreadEvent(hEntity, unreadkey.Event, unreadkey.TimeStamp) && - ((unreadkey.Event == 0) || (key < unreadkey))) - { - m_Entities._setFirstUnreadEvent(hEntity, key.Event, key.TimeStamp); - } - } - } - - return res; -} -unsigned int CEvents::MarkRead(TDBTEventHandle hEvent) -{ - uint32_t sig = cEventSignature; - uint32_t size = 0; - TEventKey key = {0, hEvent}; - - CBlockManager::WriteTransaction trans(m_BlockManager); - - TEvent * event = m_BlockManager.ReadBlock(hEvent, size, sig); - - if (!event) - return DBT_INVALIDPARAM; - - key.TimeStamp = event->TimeStamp; - - if (event->Flags & DBT_EF_READ) - return event->Flags; - - PEntityEventsRecord record = getEntityRecord(event->Entity); - if (!record) - return DBT_INVALIDPARAM; - - CEventsTree::iterator it = record->RealTree->UpperBound(key); - CVirtualEventsTree::iterator vi = record->VirtualTree->UpperBound(key); - - m_Entities._getFirstUnreadEvent(event->Entity, key.Event, key.TimeStamp); - if (MarkEventsTree(it, key.Event)) - { - FindNextUnreadEvent(++it); - if (it) - { - m_Entities._setFirstUnreadEvent(event->Entity, it->Event, it->TimeStamp); - } else { - m_Entities._setFirstUnreadEvent(event->Entity, 0, 0); - } - } - if (MarkEventsTree(vi, record->FirstVirtualUnread.Event)) - { - FindNextUnreadEvent(++vi); - if (vi) - { - record->FirstVirtualUnread = *it; - } else { - record->FirstVirtualUnread.TimeStamp = 0; - record->FirstVirtualUnread.Event = 0; - } - } - - return event->Flags | DBT_EF_READ; -} -unsigned int CEvents::WriteToDisk(TDBTEventHandle hEvent) -{ - uint32_t sig = cEventSignature; - uint32_t size = 0; - TEventKey key; - key.Event = hEvent; - - CBlockManager::WriteTransaction trans(m_BlockManager); - - if (!m_BlockManager.IsForcedVirtual(hEvent)) - return DBT_INVALIDPARAM; - - TEvent * event = m_BlockManager.ReadBlock(hEvent, size, sig); - if (!event || (size < sizeof(TEvent))) - return DBT_INVALIDPARAM; - - PEntityEventsRecord record = getEntityRecord(event->Entity); - if (!record) - return DBT_INVALIDPARAM; - - key.TimeStamp = event->TimeStamp; - key.Event = hEvent; - - if (record->VirtualTree->Delete(key)) - adjustVirtualEventCount(record, -1); - - if (record->RealTree->Insert(key)) - m_Entities._adjustEventCount(event->Entity, +1); - m_BlockManager.WriteBlockToDisk(hEvent); - - return 0; -} - -TDBTEntityHandle CEvents::getEntity(TDBTEventHandle hEvent) -{ - uint32_t sig = cEventSignature; - uint32_t size = 0; - - CBlockManager::ReadTransaction trans(m_BlockManager); - TEvent * event = m_BlockManager.ReadBlock(hEvent, size, sig); - if (!event) - return DBT_INVALIDPARAM; - - return event->Entity; -} - -TDBTEventIterationHandle CEvents::IterationInit(TDBTEventIterFilter & Filter) -{ - CBlockManager::ReadTransaction trans(m_BlockManager); - - PEntityEventsRecord record = getEntityRecord(Filter.hEntity); - - if (!record) - return DBT_INVALIDPARAM; - - std::queue q; - q.push(record->RealTree); - q.push(record->VirtualTree); - - TDBTEntityIterFilter f = {0,0,0,0}; - f.cbSize = sizeof(f); - f.Options = Filter.Options; - - TDBTEntityIterationHandle citer = m_Entities.IterationInit(f, Filter.hEntity); - if (citer != DBT_INVALIDPARAM) - { - m_Entities.IterationNext(citer); - TDBTEntityHandle c = m_Entities.IterationNext(citer); - while (c != 0) - { - record = getEntityRecord(c); - if (record) - { - q.push(record->RealTree); - q.push(record->VirtualTree); - } - - c = m_Entities.IterationNext(citer); - } - - m_Entities.IterationClose(citer); - } - - for (unsigned j = 0; j < Filter.ExtraCount; ++j) - { - record = getEntityRecord(Filter.ExtraEntities[j]); - if (record) - { - q.push(record->RealTree); - q.push(record->VirtualTree); - } - } - - PEventIteration iter = new TEventIteration; - iter->Filter = Filter; - iter->LastEvent = 0; - iter->Heap = NULL; - - TEventKey key; - key.TimeStamp = Filter.tSince; - key.Event = 0; - - while (!q.empty()) - { - TEventBase * b = q.front(); - q.pop(); - - TEventBase::iterator it = b->LowerBound(key); - if (it) - { - TEventBase::iterator * it2 = new TEventBase::iterator(it); - it2->setManaged(); - if (iter->Heap) - { - iter->Heap->Insert(*it2); - } else { - iter->Heap = new TEventsHeap(*it2, TEventsHeap::ITForward, true); - } - } - } - - if (iter->Heap == NULL) - { - delete iter; - iter = (PEventIteration)DBT_INVALIDPARAM; - } - - return reinterpret_cast(iter); -} - -TDBTEventHandle CEvents::IterationNext(TDBTEventIterationHandle Iteration) -{ - PEventIteration iter = reinterpret_cast(Iteration); - - CBlockManager::ReadTransaction trans(m_BlockManager); - - TDBTEventHandle res = 0; - TEventBase::iterator it = iter->Heap->Top(); - - while ((it) && (it.wasDeleted() || ((it->TimeStamp <= iter->Filter.tTill) && (it->Event == iter->LastEvent)))) - { - iter->Heap->Pop(); - it = iter->Heap->Top(); - } - - if ((it) && !it.wasDeleted() && (it->TimeStamp <= iter->Filter.tTill)) - { - res = it->Event; - iter->Heap->Pop(); - } - - if (res) - { - iter->LastEvent = res; - if (iter->Filter.Event) - { - iter->Filter.Event->EventType = 0; - Get(res, *iter->Filter.Event); - } - } - - return res; -} - -unsigned int CEvents::IterationClose(TDBTEventIterationHandle Iteration) -{ - PEventIteration iter = reinterpret_cast(Iteration); - - CBlockManager::ReadTransaction trans(m_BlockManager); - delete iter->Heap; - delete iter; - return 0; -} - - -TDBTEventHandle CEvents::compFirstEvent(TDBTEntityHandle hEntity) -{ - CBlockManager::ReadTransaction trans(m_BlockManager); - - TDBTEventHandle res = 0; - - PEntityEventsRecord record = getEntityRecord(hEntity); - if (!record) - return 0; - - TEventKey key = {0,0}; - CEventsTree::iterator i = record->RealTree->LowerBound(key); - CVirtualEventsTree::iterator vi = record->VirtualTree->LowerBound(key); - - if (i && vi) - { - if (*i < *vi) - { - res = i->Event; - } else { - res = vi->Event; - } - } else if (i) - { - res = i->Event; - } else if (vi) - { - res = vi->Event; - } - - return res; -} -TDBTEventHandle CEvents::compFirstUnreadEvent(TDBTEntityHandle hEntity) -{ - CBlockManager::ReadTransaction trans(m_BlockManager); - - TDBTEventHandle res = 0; - - PEntityEventsRecord record = getEntityRecord(hEntity); - if (!record) - return 0; - - TEventKey key; - m_Entities._getFirstUnreadEvent(hEntity, key.Event, key.TimeStamp); - if (key.Event) - { - if (record->FirstVirtualUnread.Event && (record->FirstVirtualUnread < key)) - { - res = record->FirstVirtualUnread.Event; - } else { - res = key.Event; - } - } else if (record->FirstVirtualUnread.Event) - { - res = record->FirstVirtualUnread.Event; - } - - return res; -} -TDBTEventHandle CEvents::compLastEvent(TDBTEntityHandle hEntity) -{ - CBlockManager::ReadTransaction trans(m_BlockManager); - TDBTEventHandle res = 0; - - PEntityEventsRecord record = getEntityRecord(hEntity); - if (!record) - return 0; - - TEventKey key = {0xffffffff, 0xffffffff}; - - CEventsTree::iterator i = record->RealTree->UpperBound(key); - CVirtualEventsTree::iterator vi = record->VirtualTree->UpperBound(key); - - if (i && vi) - { - if (*i > *vi) - { - res = i->Event; - } else { - res = vi->Event; - } - } else if (i) - { - res = i->Event; - } else if (vi) - { - res = vi->Event; - } - - return res; -} -TDBTEventHandle CEvents::compNextEvent(TDBTEventHandle hEvent) -{ - uint32_t sig = cEventSignature; - uint32_t size = 0; - - CBlockManager::ReadTransaction trans(m_BlockManager); - - TEvent * event = m_BlockManager.ReadBlock(hEvent, size, sig); - - if (!event) - return 0; - - TEventKey key = {event->TimeStamp, hEvent}; - - PEntityEventsRecord record = getEntityRecord(event->Entity); - - if (!record) - return 0; - - if (key.Event == 0xffffffff) - { - if (key.TimeStamp == 0xffffffff) - { - return 0; - } else { - ++key.TimeStamp; - } - } else { - ++key.Event; - } - - CEventsTree::iterator i = record->RealTree->LowerBound(key); - CVirtualEventsTree::iterator vi = record->VirtualTree->LowerBound(key); - - TDBTEventHandle res = 0; - if (i && vi) - { - if (*i < *vi) - { - res = i->Event; - } else { - res = vi->Event; - } - } else if (i) - { - res = i->Event; - } else if (vi) - { - res = vi->Event; - } - - return res; -} -TDBTEventHandle CEvents::compPrevEvent(TDBTEventHandle hEvent) -{ - uint32_t sig = cEventSignature; - uint32_t size = 0; - - CBlockManager::ReadTransaction trans(m_BlockManager); - - TEvent * event = m_BlockManager.ReadBlock(hEvent, size, sig); - - if (!event) - return 0; - - TEventKey key = {event->TimeStamp, hEvent}; - - PEntityEventsRecord record = getEntityRecord(event->Entity); - if (!record) - return 0; - - if (key.Event == 0) - { - if (key.TimeStamp == 0) - { - return 0; - } else { - --key.TimeStamp; - } - } else { - --key.Event; - } - - CEventsTree::iterator i = record->RealTree->UpperBound(key); - CVirtualEventsTree::iterator vi = record->VirtualTree->UpperBound(key); - - TDBTEventHandle res = 0; - if (i && vi) - { - if (*i > *vi) - { - res = i->Event; - } else { - res = vi->Event; - } - } else if (i) - { - res = i->Event; - } else if (vi) - { - res = vi->Event; - } - - return res; -} diff --git a/plugins/Dbx_tree/Events.h b/plugins/Dbx_tree/Events.h deleted file mode 100644 index 7a3d50ff19..0000000000 --- a/plugins/Dbx_tree/Events.h +++ /dev/null @@ -1,263 +0,0 @@ -/* - -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. - -*/ - -#pragma once - -#include "Interface.h" -#include "BTree.h" -#include "FileBTree.h" -#include "BlockManager.h" -#include "IterationHeap.h" -#include "Entities.h" -#include "Settings.h" -#include "Hash.h" -#include "EncryptionManager.h" -#include "sigslot.h" - -#ifdef _MSC_VER -#include -#include -#else -#include -#include -#endif -#include -#include -#include - -#pragma pack(push, 1) // push current alignment to stack, set alignment to 1 byte boundary - -/** - \brief Key Type of the EventsBTree - - The Key consists of a timestamp, seconds elapsed since 1.1.1970 - and an Index, which makes it possible to store multiple events with the same timestamp -**/ -typedef struct TEventKey { - uint32_t TimeStamp; /// timestamp at which the event occoured - TDBTEventHandle Event; - - bool operator < (const TEventKey & Other) const - { - if (TimeStamp != Other.TimeStamp) return TimeStamp < Other.TimeStamp; - if (Event != Other.Event) return Event < Other.Event; - return false; - } - //bool operator <= (const TEventKey & Other); - bool operator == (const TEventKey & Other) const - { - return (TimeStamp == Other.TimeStamp) && (Event == Other.Event); - } - - //bool operator >= (const TEventKey & Other); - bool operator > (const TEventKey & Other) const - { - if (TimeStamp != Other.TimeStamp) return TimeStamp > Other.TimeStamp; - if (Event != Other.Event) return Event > Other.Event; - return false; - } - -} TEventKey; - -/** - \brief The data of an Event - - A event's data is variable length. The data is a TDBTEvent-structure followed by varaible length data. - - fixed data - - blob data (mostly UTF8 message body) -**/ -typedef struct TEvent { - uint32_t Flags; /// Flags - uint32_t TimeStamp; /// Timestamp of the event (seconds elapsed since 1.1.1970) used as key element - uint32_t Type; /// Eventtype - TDBTEntityHandle Entity; /// hEntity which owns this event - uint32_t DataLength; /// Length of the stored data in bytes - - uint8_t Reserved[8]; /// reserved storage -} TEvent; - -#pragma pack(pop) - - -static const uint32_t cEventSignature = 0x365A7E92; -static const uint16_t cEventNodeSignature = 0x195C; - -/** - \brief Manages the Events Index in the Database -**/ -class CEventsTree : public CFileBTree -{ -private: - TDBTEntityHandle m_Entity; - -public: - CEventsTree(CBlockManager & BlockManager, TNodeRef RootNode, TDBTEntityHandle Entity) - : CFileBTree::CFileBTree(BlockManager, RootNode, cEventNodeSignature), - m_Entity(Entity) - { }; - ~CEventsTree() - { }; - - TDBTEntityHandle Entity() - { - return m_Entity; - }; - void Entity(TDBTEntityHandle NewEntity) - { - m_Entity = NewEntity; - }; -}; - -/** - \brief Manages the Virtual Events Index - Sorry for duplicating code... -**/ -class CVirtualEventsTree : public CBTree -{ -private: - TDBTEntityHandle m_Entity; - -public: - CVirtualEventsTree(TDBTEntityHandle Entity) - : CBTree::CBTree(0), - m_Entity(Entity) - { }; - - ~CVirtualEventsTree() - { }; - - TDBTEntityHandle Entity() - { - return m_Entity; - }; - void Entity(TDBTEntityHandle NewEntity) - { - m_Entity = NewEntity; - }; -}; - - -class CEventsTypeManager -{ -public: - CEventsTypeManager(CEntities & Entities, CSettings & Settings); - ~CEventsTypeManager(); - - uint32_t MakeGlobalID(char* Module, uint32_t EventType); - bool GetType(uint32_t GlobalID, char * & Module, uint32_t & EventType); - uint32_t EnsureIDExists(char* Module, uint32_t EventType); - -private: - typedef struct TEventType { - char * ModuleName; - uint32_t EventType; - } TEventType, *PEventType; - #ifdef _MSC_VER - typedef stdext::hash_map TTypeMap; - #else - typedef __gnu_cxx::hash_map TTypeMap; - #endif - - CEntities & m_Entities; - CSettings & m_Settings; - TTypeMap m_Map; - -}; - - -class CEvents : public sigslot::has_slots<> -{ -public: - - CEvents( - CBlockManager & BlockManager, - CEncryptionManager & EncryptionManager, - CEntities & Entities, - CSettings & Settings - ); - ~CEvents(); - - //compatibility - TDBTEventHandle compFirstEvent(TDBTEntityHandle hEntity); - TDBTEventHandle compFirstUnreadEvent(TDBTEntityHandle hEntity); - TDBTEventHandle compLastEvent(TDBTEntityHandle hEntity); - TDBTEventHandle compNextEvent(TDBTEventHandle hEvent); - TDBTEventHandle compPrevEvent(TDBTEventHandle hEvent); - - //services - unsigned int GetBlobSize(TDBTEventHandle hEvent); - unsigned int Get(TDBTEventHandle hEvent, TDBTEvent & Event); - unsigned int GetCount(TDBTEntityHandle hEntity); - unsigned int Delete(TDBTEventHandle hEvent); - TDBTEventHandle Add(TDBTEntityHandle hEntity, TDBTEvent & Event); - unsigned int MarkRead(TDBTEventHandle hEvent); - unsigned int WriteToDisk(TDBTEventHandle hEvent); - - TDBTEntityHandle getEntity(TDBTEventHandle hEvent); - - TDBTEventIterationHandle IterationInit(TDBTEventIterFilter & Filter); - TDBTEventHandle IterationNext(TDBTEventIterationHandle Iteration); - unsigned int IterationClose(TDBTEventIterationHandle Iteration); - - -private: - typedef CBTree TEventBase; - typedef struct - { - CEventsTree * RealTree; - CVirtualEventsTree * VirtualTree; - uint32_t VirtualCount; - TEventKey FirstVirtualUnread; - } TEntityEventsRecord, *PEntityEventsRecord; - #ifdef _MSC_VER - typedef stdext::hash_map TEntityEventsMap; - #else - typedef __gnu_cxx::hash_map TEntityEventsMap; - #endif - typedef CIterationHeap TEventsHeap; - - CBlockManager & m_BlockManager; - CEncryptionManager & m_EncryptionManager; - - CEntities & m_Entities; - CEventsTypeManager m_Types; - - TEntityEventsMap m_EntityEventsMap; - - typedef struct TEventIteration { - TDBTEventIterFilter Filter; - TEventsHeap * Heap; - TDBTEventHandle LastEvent; - } TEventIteration, *PEventIteration; - - void onRootChanged(void* EventsTree, CEventsTree::TNodeRef NewRoot); - - void onDeleteEventCallback(void * Tree, const TEventKey & Key, uint32_t Param); - void onDeleteVirtualEventCallback(void * Tree, const TEventKey & Key, uint32_t Param); - void onDeleteEvents(CEntities * Entities, TDBTEntityHandle hEntity); - void onTransferEvents(CEntities * Entities, TDBTEntityHandle Source, TDBTEntityHandle Dest); - - PEntityEventsRecord getEntityRecord(TDBTEntityHandle hEntity); - uint32_t adjustVirtualEventCount(PEntityEventsRecord Record, int32_t Adjust); - bool MarkEventsTree(TEventBase::iterator Iterator, TDBTEventHandle FirstUnread); - void FindNextUnreadEvent(TEventBase::iterator & Iterator); -}; diff --git a/plugins/Dbx_tree/FileAccess.cpp b/plugins/Dbx_tree/FileAccess.cpp deleted file mode 100644 index a0aa85aecb..0000000000 --- a/plugins/Dbx_tree/FileAccess.cpp +++ /dev/null @@ -1,299 +0,0 @@ -/* - -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 "FileAccess.h" -#include -#ifndef _MSC_VER -#include "savestrings_gcc.h" -#define _time32 time -#endif -#include "Logger.h" - -const uint8_t CFileAccess::cJournalSignature[20] = "Miranda IM Journal!"; - -CFileAccess::CFileAccess(const TCHAR* FileName) -{ - m_FileName = new TCHAR[_tcslen(FileName) + 1]; - m_Journal.FileName = new TCHAR[_tcslen(FileName) + 5]; - _tcscpy_s(m_FileName, _tcslen(FileName) + 1, FileName); - _tcscpy_s(m_Journal.FileName, _tcslen(FileName) + 5, FileName); - _tcscat_s(m_Journal.FileName, _tcslen(FileName) + 5, _T(".jrn")); - - m_ReadOnly = false; - m_LastSize = 0; - m_Size = 0; - m_Journal.Use = false; - m_Journal.hFile = 0; - m_Journal.BufUse = 0; - - m_LastAllocTime = _time32(NULL); -} - -CFileAccess::~CFileAccess() -{ - CloseHandle(m_Journal.hFile); - DeleteFile(m_Journal.FileName); - - delete [] m_FileName; - delete [] m_Journal.FileName; -} - -uint32_t CFileAccess::Size(uint32_t NewSize) -{ - m_Size = NewSize; - if (!m_Journal.Use) - { - NewSize = (NewSize + m_AllocGranularity - 1) & ~(m_AllocGranularity - 1); - - if (NewSize == 0) - NewSize = m_AllocGranularity; - - if (NewSize != m_AllocSize) - { - m_AllocSize = _SetSize(NewSize); - - // adapt Alloc Granularity - uint32_t t = _time32(NULL); - uint32_t d = t - m_LastAllocTime; - m_LastAllocTime = t; - - if (d < 30) // increase alloc stepping - { - if (m_AllocGranularity < m_MaxAllocGranularity) - m_AllocGranularity = m_AllocGranularity << 1; - } else if (d > 120) // decrease alloc stepping - { - if (m_AllocGranularity > m_MinAllocGranularity) - m_AllocGranularity = m_AllocGranularity >> 1; - } - } - } - return NewSize; -} - - -void CFileAccess::CleanJournal() -{ - SetFilePointer(m_Journal.hFile, 0, NULL, FILE_BEGIN); - SetEndOfFile(m_Journal.hFile); - - DWORD written; - WriteFile(m_Journal.hFile, cJournalSignature, sizeof(cJournalSignature), &written, NULL); -} - -void CFileAccess::ProcessJournal() -{ - uint32_t filesize = GetFileSize(m_Journal.hFile, NULL) - sizeof(cJournalSignature); - SetFilePointer(m_Journal.hFile, sizeof(cJournalSignature), NULL, FILE_BEGIN); - - uint8_t* buf = (uint8_t*)malloc(filesize); - TJournalEntry* e = (TJournalEntry*)buf; - DWORD read = 0; - if (!ReadFile(m_Journal.hFile, buf, filesize, &read, NULL) || (read != filesize)) - { - free(buf); - LOGSYS(logCRITICAL, _T("Couldn't flush the journal because ReadFile failed!")); - return; - } - - m_Journal.Use = false; - std::vector currentops; - - while (filesize >= sizeof(TJournalEntry)) - { - switch (e->Signature) - { - case 'fini': - { - Size(e->Size); - - std::vector::iterator i = currentops.begin(); - while (i != currentops.end()) - { - switch ((*i)->Signature) - { - case 'writ': - { - if ((*i)->Address + (*i)->Size <= m_AllocSize) - { - _Write(*i + 1, (*i)->Address, (*i)->Size); - } else if ((*i)->Address < m_AllocSize) - { - _Write(*i + 1, (*i)->Address, m_AllocSize - (*i)->Address); - } - } break; - case 'inva': - { - if ((*i)->Address + (*i)->Size <= m_AllocSize) - { - _Invalidate((*i)->Address, (*i)->Size); - } else if ((*i)->Address < m_AllocSize) - { - _Invalidate((*i)->Address, m_AllocSize - (*i)->Address); - } - } break; - } - ++i; - } - currentops.clear(); - - e++; - filesize = filesize - sizeof(TJournalEntry); - } break; - case 'writ': - { - if (filesize < sizeof(e) + e->Size) - { - filesize = 0; - } else { - currentops.push_back(e); - filesize = filesize - sizeof(TJournalEntry) - e->Size; - e = (TJournalEntry*)((uint8_t*)e + sizeof(TJournalEntry) + e->Size); - } - } break; - case 'inva': - { - if (filesize < sizeof(e)) - { - filesize = 0; - } else { - currentops.push_back(e); - e++; - filesize = filesize - sizeof(TJournalEntry); - } - } break; - default: - { - filesize = 0; - if (currentops.size()) - LOG(logWARNING, _T("Your database journal wasn't completely written to disk.")); - } break; - } - } - - _Flush(); - - CleanJournal(); - - free(buf); - m_Journal.Use = true; -} - -void CFileAccess::InitJournal() -{ - m_Journal.hFile = CreateFile(m_Journal.FileName, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, 0); - if (m_Journal.hFile == INVALID_HANDLE_VALUE) - { - LOGSYS(logCRITICAL, _T("CreateFile failed on Journal %s"), m_Journal.FileName); - return; - } - - uint8_t h[sizeof(cJournalSignature)]; - DWORD read; - if (ReadFile(m_Journal.hFile, &h, sizeof(h), &read, NULL) && (read == sizeof(h)) && (0 == memcmp(h, cJournalSignature, sizeof(h)))) - { - TCHAR * bckname = new TCHAR[_tcslen(m_FileName) + 12]; - _tcscpy_s(bckname, _tcslen(m_FileName) + 12, m_FileName); - _tcscat_s(bckname, _tcslen(m_FileName) + 12, _T(".autobackup")); - - TCHAR * bckjrnname = new TCHAR[_tcslen(m_Journal.FileName) + 12]; - _tcscpy_s(bckjrnname, _tcslen(m_Journal.FileName) + 12, m_Journal.FileName); - _tcscat_s(bckjrnname, _tcslen(m_Journal.FileName) + 12, _T(".autobackup")); - - char buf[4096]; - HANDLE hfilebackup = CreateFile(bckname, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, 0); - if (hfilebackup) - { - uint32_t i = 0; - while (i + sizeof(buf) <= m_AllocSize) - { - DWORD w; - _Read(buf, i, sizeof(buf)); - i += sizeof(buf); - WriteFile(hfilebackup, buf, sizeof(buf), &w, NULL); - } - if (i < m_AllocSize) - { - DWORD w; - _Read(buf, i, m_AllocSize - i); - WriteFile(hfilebackup, buf, m_AllocSize - i, &w, NULL); - } - - CloseHandle(hfilebackup); - } - - HANDLE hjrnfilebackup = CreateFile(bckjrnname, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, 0); - if (hjrnfilebackup) - { - uint32_t i = 0; - - uint32_t filesize = GetFileSize(m_Journal.hFile, NULL); - SetFilePointer(m_Journal.hFile, 0, NULL, FILE_BEGIN); - - while (i + sizeof(buf) <= filesize) - { - DWORD w, r; - ReadFile(m_Journal.hFile, buf, sizeof(buf), &r, NULL); - i += sizeof(buf); - WriteFile(hjrnfilebackup, buf, sizeof(buf), &w, NULL); - } - if (i < filesize) - { - DWORD w, r; - ReadFile(m_Journal.hFile, buf, filesize - i, &r, NULL); - WriteFile(hjrnfilebackup, buf, filesize - i, &w, NULL); - } - CloseHandle(hjrnfilebackup); - } - - TCHAR* path = bckname; - TCHAR* fn = _tcsrchr(m_Journal.FileName, _T('\\')); - TCHAR* bfn = _tcsrchr(bckname, _T('\\')); - TCHAR* jrn = _tcsrchr(bckjrnname, _T('\\')); - if (bfn) // truncate path var - *bfn = 0; - - if (hfilebackup || hjrnfilebackup) - { - LOG(logWARNING, - _T("Journal \"%s\" was found on start.\nBackup \"%s\"%s created and backup \"%s\"%s created.\nYou may delete these file(s) after successful start from \"%s\"."), - fn?fn+1:m_Journal.FileName, - bfn?bfn+1:bckname, (hfilebackup!=INVALID_HANDLE_VALUE)?_T(" was successfully"):_T(" could not be"), - jrn?jrn+1:bckjrnname, (hjrnfilebackup!=INVALID_HANDLE_VALUE)?_T(" was successfully"):_T(" could not be"), - path); - } else { - LOG(logWARNING, - _T("Journal \"%s\" was found on start.\nBackups \"%s\"and \"%s\" could not be created in \"%s\"."), - fn?fn+1:m_Journal.FileName, - bfn?bfn+1:bckname, - jrn?jrn+1:bckjrnname, - path); - } - - delete [] bckname; - delete [] bckjrnname; - - ProcessJournal(); - } - - CleanJournal(); -} diff --git a/plugins/Dbx_tree/FileAccess.h b/plugins/Dbx_tree/FileAccess.h deleted file mode 100644 index f49643e2a3..0000000000 --- a/plugins/Dbx_tree/FileAccess.h +++ /dev/null @@ -1,191 +0,0 @@ -/* - -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. - -*/ - -#pragma once - -#include -#include -#include "stdint.h" -#include "sigslot.h" - -class CFileAccess -{ -public: - static const uint8_t cJournalSignature[20]; - - CFileAccess(const TCHAR* FileName); - virtual ~CFileAccess(); - - - uint32_t Read(void* Buf, uint32_t Source, uint32_t Size) - { - return _Read(Buf, Source, Size); - }; - - bool Write(void* Buf, uint32_t Dest, uint32_t Size) - { - if (m_Journal.Use) - { - DWORD written; - - TJournalEntry * data = reinterpret_cast(m_Journal.Buffer + m_Journal.BufUse); - data->Signature = 'writ'; - data->Address = Dest; - data->Size = Size; - m_Journal.BufUse += 12; - if (Size + m_Journal.BufUse < sizeof(m_Journal.Buffer) - 12) // one journal header has always to fit in - { - memcpy(m_Journal.Buffer + m_Journal.BufUse, Buf, Size); - m_Journal.BufUse += Size; - } else { - WriteFile(m_Journal.hFile, m_Journal.Buffer, m_Journal.BufUse, &written, NULL); - WriteFile(m_Journal.hFile, Buf, Size, &written, NULL); - - m_Journal.BufUse = 0; - } - } else { - _Write(Buf, Dest, Size); - } - - return true; - }; - - void Invalidate(uint32_t Dest, uint32_t Size) - { - if (m_Journal.Use) - { - DWORD written; - - TJournalEntry * data = reinterpret_cast(m_Journal.Buffer + m_Journal.BufUse); - data->Signature = 'inva'; - data->Address = Dest; - data->Size = Size; - m_Journal.BufUse += 12; - if (m_Journal.BufUse > sizeof(m_Journal.Buffer) - 12) - { - WriteFile(m_Journal.hFile, m_Journal.Buffer, m_Journal.BufUse, &written, NULL); - m_Journal.BufUse = 0; - } - } else { - _Invalidate(Dest, Size); - } - }; - - void Flush() - { - if (m_Journal.Use) - { - if (m_Journal.BufUse) - { - DWORD written; - WriteFile(m_Journal.hFile, m_Journal.Buffer, m_Journal.BufUse, &written, NULL); - m_Journal.BufUse = 0; - } - FlushFileBuffers(m_Journal.hFile); - } else { - _Flush(); - } - }; - - void UseJournal(bool UseIt) - { - m_Journal.Use = UseIt; - }; - - void CompleteTransaction() - { - if (m_Size != m_LastSize) - { - m_sigFileSizeChanged.emit(this, m_Size); - m_LastSize = m_Size; - } - }; - void CloseTransaction() - { - if (m_Journal.Use) - { - DWORD written; - - TJournalEntry * data = reinterpret_cast(m_Journal.Buffer + m_Journal.BufUse); - data->Signature = 'fini'; - data->Address = 0; - data->Size = m_Size; - - WriteFile(m_Journal.hFile, m_Journal.Buffer, m_Journal.BufUse + 12, &written, NULL); - m_Journal.BufUse = 0; - } - }; - - void CleanJournal(); - - uint32_t Size(uint32_t NewSize); - uint32_t Size() - { return m_Size; }; - void ReadOnly(bool ReadOnly) - { m_ReadOnly = ReadOnly; }; - bool ReadOnly() - { return m_ReadOnly; }; - - typedef sigslot::signal2 TOnFileSizeChanged; - - TOnFileSizeChanged & sigFileSizeChanged() - { return m_sigFileSizeChanged; }; - -protected: - TCHAR* m_FileName; - struct { - bool Use; - TCHAR* FileName; - HANDLE hFile; - - uint8_t Buffer[4096]; - uint32_t BufUse; - } m_Journal; - - uint32_t m_Size; - uint32_t m_AllocSize; - uint32_t m_AllocGranularity; - uint32_t m_MinAllocGranularity; - uint32_t m_MaxAllocGranularity; - uint32_t m_LastAllocTime; - bool m_ReadOnly; - uint32_t m_LastSize; - - TOnFileSizeChanged m_sigFileSizeChanged; - virtual uint32_t _Read(void* Buf, uint32_t Source, uint32_t Size) = 0; - virtual uint32_t _Write(void* Buf, uint32_t Dest, uint32_t Size) = 0; - virtual void _Invalidate(uint32_t Dest, uint32_t Size) = 0; - virtual uint32_t _SetSize(uint32_t Size) = 0; - virtual void _Flush() = 0; - -#pragma pack (push, 1) - typedef struct TJournalEntry - { - uint32_t Signature; - uint32_t Address; - uint32_t Size; - } TJournalEntry; -#pragma pack (pop) - - void InitJournal(); - void ProcessJournal(); -}; diff --git a/plugins/Dbx_tree/FileBTree.h b/plugins/Dbx_tree/FileBTree.h deleted file mode 100644 index 3a9e58a43e..0000000000 --- a/plugins/Dbx_tree/FileBTree.h +++ /dev/null @@ -1,102 +0,0 @@ -/* - -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. - -*/ - -#pragma once -#include "BTree.h" -#include "BlockManager.h" -#include "Logger.h" - -template -class CFileBTree : public CBTree -{ -private: - -protected: - CBlockManager & m_BlockManager; - uint16_t cSignature; - - virtual void PrepareInsertOperation(); - virtual TNode * CreateNewNode(TNodeRef & NodeRef); - virtual void DeleteNode(TNodeRef Node); - virtual TNode * Read(TNodeRef Node); - virtual void Write(TNodeRef Node); -public: - CFileBTree(CBlockManager & BlockManager, typename CBTree::TNodeRef RootNode, uint16_t Signature); - virtual ~CFileBTree(); -}; - - - - -template -CFileBTree::CFileBTree(CBlockManager & BlockManager, typename CBTree::TNodeRef RootNode, uint16_t Signature) -: CBTree::CBTree(RootNode), - m_BlockManager(BlockManager) -{ - cSignature = Signature; - CBTree::m_DestroyTree = false; -} - -template -CFileBTree::~CFileBTree() -{ - CBTree::m_DestroyTree = false; -} - - -template -void CFileBTree::PrepareInsertOperation() -{ - -} - -template -typename CBTree::TNode * CFileBTree::CreateNewNode(typename CBTree::TNodeRef & NodeRef) -{ - return reinterpret_cast( m_BlockManager.CreateBlock(NodeRef, cSignature << 16, sizeof(typename CBTree::TNode) - 4) - 1); -} - -template -void CFileBTree::DeleteNode(typename CBTree::TNodeRef Node) -{ - m_BlockManager.DeleteBlock(Node); -} - -template -typename CBTree::TNode * CFileBTree::Read(typename CBTree::TNodeRef Node) -{ - uint32_t sig = 0; - uint32_t size = 0; - TNode * res = reinterpret_cast( m_BlockManager.ReadBlock(Node, size, sig) - 1); /// HACK using knowledge about the blockmanager here - - CHECK(res->Signature == cSignature, - logCRITICAL, _T("Signature check failed")); - - return res; -} - -template -void CFileBTree::Write(typename CBTree::TNodeRef Node) -{ - m_BlockManager.UpdateBlock(Node, 0); -} - diff --git a/plugins/Dbx_tree/Filestructure.txt b/plugins/Dbx_tree/Filestructure.txt deleted file mode 100644 index 6128b5f993..0000000000 Binary files a/plugins/Dbx_tree/Filestructure.txt and /dev/null differ diff --git a/plugins/Dbx_tree/Hash.cpp b/plugins/Dbx_tree/Hash.cpp deleted file mode 100644 index f0541c2da0..0000000000 --- a/plugins/Dbx_tree/Hash.cpp +++ /dev/null @@ -1,183 +0,0 @@ -/* - -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 "Hash.h" - - -/// lookup3, by Bob Jenkins, May 2006, Public Domain. -#define rot(x,k) (((x)<<(k)) | ((x)>>(32-(k)))) - -#define HASHmix(a,b,c) \ -{ \ - a -= c; a ^= rot(c, 4); c += b; \ - b -= a; b ^= rot(a, 6); a += c; \ - c -= b; c ^= rot(b, 8); b += a; \ - a -= c; a ^= rot(c,16); c += b; \ - b -= a; b ^= rot(a,19); a += c; \ - c -= b; c ^= rot(b, 4); b += a; \ -} -#define HASHfinal(a,b,c) \ -{ \ - c ^= b; c -= rot(b,14); \ - a ^= c; a -= rot(c,11); \ - b ^= a; b -= rot(a,25); \ - c ^= b; c -= rot(b,16); \ - a ^= c; a -= rot(c, 4); \ - b ^= a; b -= rot(a,14); \ - c ^= b; c -= rot(b,24); \ -} - - -uint32_t Hash(const void * Data, uint32_t Length) -{ - register uint32_t a,b,c; // internal state - union { const void *ptr; uint32_t i; } u; // needed for Mac Powerbook G4 - - // Set up the internal state - a = b = c = 0xdeadbeef + Length; // + initval = 0 - - u.ptr = Data; - if ((u.i & 0x3) == 0) - { - const uint32_t *k = (const uint32_t *)Data; // read 32-bit chunks - - // all but last block: aligned reads and affect 32 bits of (a,b,c) - while (Length > 12) - { - a += k[0]; - b += k[1]; - c += k[2]; - HASHmix(a,b,c); - Length -= 12; - k += 3; - } - - switch(Length) - { - case 12: c += k[2]; b += k[1]; a += k[0]; break; - case 11: c += k[2] & 0xffffff; b += k[1]; a += k[0]; break; - case 10: c += k[2] & 0xffff; b += k[1]; a += k[0]; break; - case 9 : c += k[2] & 0xff; b += k[1]; a += k[0]; break; - case 8 : b += k[1]; a += k[0]; break; - case 7 : b += k[1] & 0xffffff; a += k[0]; break; - case 6 : b += k[1] & 0xffff; a += k[0]; break; - case 5 : b += k[1] & 0xff; a += k[0]; break; - case 4 : a += k[0]; break; - case 3 : a += k[0] & 0xffffff; break; - case 2 : a += k[0] & 0xffff; break; - case 1 : a += k[0] & 0xff; break; - case 0 : return c; // zero length strings require no mixing - } - - } else if ((u.i & 0x1) == 0) { - const uint16_t *k = (const uint16_t *)Data; /* read 16-bit chunks */ - const uint8_t *k8; - - // all but last block: aligned reads and different mixing - while (Length > 12) - { - a += k[0] + (((uint32_t)k[1]) << 16); - b += k[2] + (((uint32_t)k[3]) << 16); - c += k[4] + (((uint32_t)k[5]) << 16); - HASHmix(a,b,c); - Length -= 12; - k += 6; - } - - // handle the last (probably partial) block - k8 = (const uint8_t *)k; - switch(Length) - { - case 12: c += k[4] + (((uint32_t)k[5]) << 16); - b += k[2] + (((uint32_t)k[3]) << 16); - a += k[0] + (((uint32_t)k[1]) << 16); - break; - case 11: c += ((uint32_t)k8[10]) << 16; // fall through - case 10: c += k[4]; - b += k[2] + (((uint32_t)k[3]) << 16); - a += k[0] + (((uint32_t)k[1]) << 16); - break; - case 9 : c += k8[8]; // fall through - case 8 : b += k[2] + (((uint32_t)k[3]) << 16); - a += k[0] + (((uint32_t)k[1]) << 16); - break; - case 7 : b += ((uint32_t)k8[6]) << 16; // fall through - case 6 : b += k[2]; - a += k[0] + (((uint32_t)k[1]) << 16); - break; - case 5 : b += k8[4]; // fall through - case 4 : a += k[0] + (((uint32_t)k[1]) << 16); - break; - case 3 : a += ((uint32_t)k8[2]) << 16; // fall through - case 2 : a += k[0]; - break; - case 1 : a += k8[0]; - break; - case 0 : return c; // zero length requires no mixing - } - - } else { // need to read the key one byte at a time - const uint8_t *k = (const uint8_t *)Data; - - // all but the last block: affect some 32 bits of (a,b,c) - while (Length > 12) - { - a += k[0]; - a += ((uint32_t)k[1] ) << 8; - a += ((uint32_t)k[2] ) << 16; - a += ((uint32_t)k[3] ) << 24; - b += k[4]; - b += ((uint32_t)k[5] ) << 8; - b += ((uint32_t)k[6] ) << 16; - b += ((uint32_t)k[7] ) << 24; - c += k[8]; - c += ((uint32_t)k[9] ) << 8; - c += ((uint32_t)k[10]) << 16; - c += ((uint32_t)k[11]) << 24; - HASHmix(a,b,c); - Length -= 12; - k += 12; - } - - // last block: affect all 32 bits of (c) - switch(Length) // all the case statements fall through - { - case 12: c += ((uint32_t)k[11]) << 24; - case 11: c += ((uint32_t)k[10]) << 16; - case 10: c += ((uint32_t)k[9] ) << 8; - case 9 : c += k[8]; - case 8 : b += ((uint32_t)k[7] ) << 24; - case 7 : b += ((uint32_t)k[6] ) << 16; - case 6 : b += ((uint32_t)k[5] ) << 8; - case 5 : b += k[4]; - case 4 : a += ((uint32_t)k[3] ) << 24; - case 3 : a += ((uint32_t)k[2] ) << 16; - case 2 : a += ((uint32_t)k[1] ) << 8; - case 1 : a += k[0]; - break; - case 0 : return c; - } - } - - HASHfinal(a,b,c); - return c; -} diff --git a/plugins/Dbx_tree/Hash.h b/plugins/Dbx_tree/Hash.h deleted file mode 100644 index 886e8b1485..0000000000 --- a/plugins/Dbx_tree/Hash.h +++ /dev/null @@ -1,29 +0,0 @@ -/* - -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. - -*/ - -#ifndef _MSC_VER -#include -#else -#include "stdint.h" -#endif - -uint32_t Hash(const void * Data, uint32_t Length); diff --git a/plugins/Dbx_tree/Interface.h b/plugins/Dbx_tree/Interface.h deleted file mode 100644 index bde0a74511..0000000000 --- a/plugins/Dbx_tree/Interface.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - -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. - -*/ - -#pragma once - -#ifndef INTERFACE_VERSION_ONLY - -#define MIRANDA_VER 0x0A00 -#include -#include "newpluginapi.h" -#include "m_system.h" -#include "m_system_cpp.h" -#include "m_database.h" -#include "m_db_int.h" -#include "m_utils.h" -#include "win2k.h" - -#include "m_langpack.h" - -#include "m_dbx_tree.h" - -extern HINSTANCE hInstance; - -extern DATABASELINK gDBLink; -#endif - - -#define gVersion 0x00000012 -#define gResVersion 0,0,0,18 -#define gResVersionString "0.0.0.18" -#define gInternalName "dbx_tree" -#define gInternalNameLong "Miranda dbx_tree database driver" -#define gDescription "Provides extended Miranda database support" -#define gAutor "Michael 'Protogenes' Kunz" -#define gAutorEmail "Michael.Kunz@s2005.TU-Chemnitz.de" -#define gCopyright "2007 - 2010 Michael 'Protogenes' Kunz" diff --git a/plugins/Dbx_tree/IterationHeap.h b/plugins/Dbx_tree/IterationHeap.h deleted file mode 100644 index db06f7e695..0000000000 --- a/plugins/Dbx_tree/IterationHeap.h +++ /dev/null @@ -1,196 +0,0 @@ -/* - -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. - -*/ - -#pragma once - -#include - -template -class CIterationHeap -{ -public: - enum TIterationType {ITForward, ITBackward}; - - CIterationHeap(TType & InitialItem, TIterationType ForBack, bool DeleteItems = true); - ~CIterationHeap(); - - bool Insert(TType & Item); - TType & Top(); - void Pop(); - -protected: - typedef struct THeapElement { - TType * Elem; - size_t Index; - } THeapElement, * PHeapElement; - - std::vector m_Heap; - TIterationType m_Type; - bool m_DeleteItems; - - bool A_b4_B(PHeapElement a, PHeapElement b); -private: - -}; - - -template -inline bool CIterationHeap::A_b4_B(PHeapElement a, PHeapElement b) -{ - if (m_Type == ITForward) - { - if ((**a->Elem) == (**b->Elem)) return a->Index < b->Index; - return (**a->Elem) < (**b->Elem); - } else { - if ((**a->Elem) == (**b->Elem)) return a->Index > b->Index; - return (**a->Elem) > (**b->Elem); - } -} - -template -CIterationHeap::CIterationHeap(TType & InitialItem, TIterationType MinMax, bool DeleteItems) -: m_Heap() -{ - m_Heap.resize(1); - m_Heap.reserve(1 << 1); - m_Type = MinMax; - - m_Heap[0] = new THeapElement; - m_Heap[0]->Elem = &InitialItem; - m_Heap[0]->Index = m_Heap.size(); - m_DeleteItems = DeleteItems; -} - -template -CIterationHeap::~CIterationHeap() -{ - unsigned int i = 0; - while ((i < m_Heap.size()) && (m_Heap[i])) - { - if (m_DeleteItems && m_Heap[i]->Elem) - delete m_Heap[i]->Elem; - - delete m_Heap[i]; - ++i; - } -} - -template -bool CIterationHeap::Insert(TType & Item) -{ - if (!Item) - return false; - - if (m_Heap.capacity() == m_Heap.size() + 1) - m_Heap.reserve(m_Heap.capacity() << 1); - - m_Heap.push_back(NULL); - - size_t way = m_Heap.capacity() >> 2; - size_t index = 0; - PHeapElement ins = new THeapElement; - ins->Elem = &Item; - ins->Index = m_Heap.size(); - - PHeapElement next; - - while ((way > 0) && (index + 1 < m_Heap.size())) - { - next = m_Heap[index]; - if ((!(*next->Elem)) || A_b4_B(ins, next)) - { - m_Heap[index] = ins; - ins = next; - } - - if (way & m_Heap.size()) //right - { - index = (index << 1) + 2; - } else { // left - index = (index << 1) + 1; - } - way = way >> 1; - } - - m_Heap[index] = ins; - - return true; -} - -template -TType & CIterationHeap::Top() -{ - return *m_Heap[0]->Elem; -} - -template -void CIterationHeap::Pop() -{ - if (m_Type == ITForward) - ++(*m_Heap[0]->Elem); - else - --(*m_Heap[0]->Elem); - - size_t index = 0; - PHeapElement ins = m_Heap[0]; - size_t big = 1; - - while ((big > 0) && (index < (m_Heap.size() >> 1))) - { - big = 0; - - if ((((index << 1) + 2) < m_Heap.size()) && (*m_Heap[(index << 1) + 2]->Elem)) - { - if (*ins->Elem) - { - if (A_b4_B(m_Heap[(index << 1) + 2], m_Heap[(index << 1) + 1])) - big = (index << 1) + 2; - else - big = (index << 1) + 1; - - } else { - m_Heap[index] = m_Heap[(index << 1) + 2]; - index = (index << 1) + 2; - m_Heap[index] = ins; - } - } else if ((((index << 1) + 1) < m_Heap.size()) && (*m_Heap[(index << 1) + 1]->Elem)) - { - if (*ins->Elem) - { - big = (index << 1) + 1; - } else { - m_Heap[index] = m_Heap[(index << 1) + 1]; - index = (index << 1) + 1; - m_Heap[index] = ins; - } - } - - if ((big > 0) && A_b4_B(m_Heap[big], ins)) - { - m_Heap[index] = m_Heap[big]; - index = big; - m_Heap[big] = ins; - } else { - big = 0; - } - } -} diff --git a/plugins/Dbx_tree/Logger.cpp b/plugins/Dbx_tree/Logger.cpp deleted file mode 100644 index 551824d905..0000000000 --- a/plugins/Dbx_tree/Logger.cpp +++ /dev/null @@ -1,124 +0,0 @@ -/* - -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 "Logger.h" -#include - -CLogger CLogger::_Instance; - -CLogger::CLogger() - : m_Length(0), - m_Level(logNOTICE) -{ - -} - -CLogger::~CLogger() -{ - for (std::vector::iterator it = m_Messages.begin(); it != m_Messages.end(); ++it) - delete [] *it; -} - -void CLogger::Append(const TCHAR * File, const TCHAR * Function, const int Line, DWORD SysState, TLevel Level, const TCHAR * Message, ...) -{ - if (m_Level < Level) - m_Level = Level; - - time_t rawtime = time(NULL); - tm timeinfo; - TCHAR timebuf[80]; - localtime_s(&timeinfo, &rawtime); - size_t len = _tcsftime(timebuf, sizeof(timebuf) / sizeof(*timebuf), _T("%c"), &timeinfo); - - TCHAR msgbuf[4096]; - va_list va; - va_start(va, Message); - len += _vstprintf_s(msgbuf, Message, va); - va_end(va); - - TCHAR * message; - if (SysState) - { - TCHAR syserror[2048]; - len += FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, SysState, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), syserror, 2048, NULL); - - len += /*_tcslen(File) + 10 +*/ _tcslen(Function) + 32 + 12 + 1; - - message = new TCHAR[len]; - m_Length += _stprintf_s(message, len, _T("[%s - %s]\n%s\n\nSystem Error Code: %d\n%s\n\n"), timebuf, /*File, Line, */ Function, msgbuf, SysState, syserror) + 1; - } else { - len += /*_tcslen(File) + 10 +*/ _tcslen(Function) + 12 + 1; - - message = new TCHAR[len]; - m_Length += _stprintf_s(message, len, _T("[%s - %s]\n%s\n\n"), timebuf, /*File, Line, */Function, msgbuf) + 1; - } - m_Messages.push_back(message); -} - -CLogger::TLevel CLogger::ShowMessage(TLevel CanAsyncTill) -{ - if (m_Messages.size() == 0) - return logNOTICE; - - TCHAR * msg = new TCHAR[m_Length]; - *msg = 0; - - for (std::vector::iterator it = m_Messages.begin(); it != m_Messages.end(); ++it) - { - _tcscat_s(msg, m_Length, *it); - delete [] *it; - } - m_Messages.clear(); - - if (m_Level <= CanAsyncTill) - { - MSGBOXPARAMS * p = new MSGBOXPARAMS; - p->cbSize = sizeof(*p); - p->hwndOwner = 0; - p->hInstance = NULL; - p->lpszText = msg; - p->lpszCaption = _T(gInternalNameLong); - p->dwStyle = MB_OK | (m_Level >= logERROR)?MB_ICONHAND:((m_Level == logWARNING)?MB_ICONWARNING:MB_ICONINFORMATION); - p->lpszIcon = NULL; - p->dwContextHelpId = 0; - p->lpfnMsgBoxCallback = NULL; - p->dwLanguageId = MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL); - - _beginthread(&CLogger::MessageBoxAsync, 0, p); - } else { - MessageBox(0, msg, _T(gInternalNameLong), MB_OK | (m_Level >= logERROR)?MB_ICONHAND:((m_Level == logWARNING)?MB_ICONWARNING:MB_ICONINFORMATION)); - delete [] msg; - } - - TLevel tmp = m_Level; - m_Level = logNOTICE; - return tmp; -} - -void CLogger::MessageBoxAsync(void * MsgBoxParams) -{ - MSGBOXPARAMS* p = reinterpret_cast(MsgBoxParams); - MessageBoxIndirect(p); - if (p->lpszText) - delete [] p->lpszText; - delete p; -} \ No newline at end of file diff --git a/plugins/Dbx_tree/Logger.h b/plugins/Dbx_tree/Logger.h deleted file mode 100644 index a97b928555..0000000000 --- a/plugins/Dbx_tree/Logger.h +++ /dev/null @@ -1,73 +0,0 @@ -/* - -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. - -*/ - -#pragma once - -#include -#include -#include "Interface.h" - -#define WIDEN2(x) L ## x -#define WIDEN(x) WIDEN2(x) -#define __WFILE__ WIDEN(__FILE__) -#define __WFUNCTION__ WIDEN(__FUNCTION__) - - -#define LOG(Level, Message, ...) CLogger::Instance().Append(__WFILE__, __WFUNCTION__, __LINE__, 0, CLogger:: ## Level, Message, __VA_ARGS__) -#define LOGSYS(Level, Message, ...) CLogger::Instance().Append(__WFILE__, __WFUNCTION__, __LINE__, GetLastError(), CLogger:: ## Level, Message, __VA_ARGS__) - - -#define CHECK(Assertion, Level, Message, ...) if (!(Assertion)) LOG(Level, Message, __VA_ARGS__) -#define CHECKSYS(Assertion, Level, Message, ...) if (!(Assertion)) LOGSYS(Level, Message, __VA_ARGS__) - -class CLogger -{ - public: - enum TLevel - { - logNOTICE, - logWARNING, - logERROR, - logCRITICAL - }; - - CLogger(); - ~CLogger(); - - void Append(const TCHAR * File, const TCHAR * Function, const int Line, DWORD SysState, TLevel Level, const TCHAR * Message, ...); - TLevel ShowMessage(TLevel CanAsyncTill = logERROR); - - static CLogger & Instance() - { return _Instance; }; - - TLevel Level() - { return m_Level; }; - protected: - std::vector m_Messages; - size_t m_Length; - TLevel m_Level; - - static void MessageBoxAsync(void * MsgBoxParams); - private: - static CLogger _Instance; - -}; diff --git a/plugins/Dbx_tree/MREWSync.cpp b/plugins/Dbx_tree/MREWSync.cpp deleted file mode 100644 index 6e08be6475..0000000000 --- a/plugins/Dbx_tree/MREWSync.cpp +++ /dev/null @@ -1,330 +0,0 @@ -/* - -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 "MREWSync.h" -#include -#include "intrinsics.h" - -#if defined(MREW_DO_DEBUG_LOGGING) && (defined(DEBUG) || defined(_DEBUG)) - #include -#endif - - -/////////////////////////////////////////////////////////////////////////////////////////////////// -// +------------+---------------+---------------+------------+---------------+ -// | ReaderBusy | ReaderWaiting | WriterWaiting | WriterBusy | UseOddReader? | -// +------------+---------------+---------------+------------+---------------+ -// 63..44 43..24 23..4 3 0 -/////////////////////////////////////////////////////////////////////////////////////////////////// -#define isWriterBusy(Sentinel) ((Sentinel) & 0x0000000000000008ui64) -#define isWriterWaiting(Sentinel) ((Sentinel) & 0x0000000000fffff0ui64) -#define isReaderWaiting(Sentinel) ((Sentinel) & 0x00000fffff000000ui64) -#define isReaderBusy(Sentinel) ((Sentinel) & 0xfffff00000000000ui64) - -#define countWriterWaiting(Sentinel) (((Sentinel) & 0x0000000000fffff0ui64) >> 4) -#define countReaderWaiting(Sentinel) (((Sentinel) & 0x00000fffff000000ui64) >> 24) -#define countReaderBusy(Sentinel) (((Sentinel) & 0xfffff00000000000ui64) >> 44) - -#define WriterBusy (1ui64 << 3) -#define WriterWaiting (1ui64 << 4) -#define ReaderWaiting (1ui64 << 24) -#define ReaderBusy (1ui64 << 44) - -#define isUseOddReader(Sentinel) ((Sentinel) & 1) -#define useOddReader (1ui64) - -CMultiReadExclusiveWriteSynchronizer::CMultiReadExclusiveWriteSynchronizer(void) -: tls(), - m_Sentinel(0) -{ - m_ReadSignal[0] = CreateEvent(NULL, TRUE, FALSE, NULL); - m_ReadSignal[1] = CreateEvent(NULL, TRUE, FALSE, NULL); - m_WriteSignal = CreateEvent(NULL, FALSE, FALSE, NULL); - m_WriterID = 0; - m_WriteRecursion = 0; - m_Revision = 0; -} - -CMultiReadExclusiveWriteSynchronizer::~CMultiReadExclusiveWriteSynchronizer(void) -{ - BeginWrite(); - CloseHandle(m_WriteSignal); - CloseHandle(m_ReadSignal[0]); - CloseHandle(m_ReadSignal[1]); -} - -void CMultiReadExclusiveWriteSynchronizer::BeginRead() -{ - unsigned long id = GetCurrentThreadId(); - unsigned & reccount(tls.Open(this, 0)); - - reccount++; - if ((m_WriterID != id) && (reccount == 1)) - { - int64_t old; - int64_t newvalue; - - do { - old = m_Sentinel; - if (isWriterBusy(old)) - newvalue = old + ReaderBusy; // writer has lock -> we are going to enter after he leaves -> we are busy but have to wait - else if (isWriterWaiting(old)) - newvalue = old + ReaderWaiting; // writer is waiting for lock -> don't set myself busy as he waits for all readers to leave lock - else - newvalue = old + ReaderBusy; // no writer in sight, just take lock - - } while (CMPXCHG_64(m_Sentinel, newvalue, old) != old); - - - if (isWriterBusy(old) || isWriterWaiting(old)) - { - if (isUseOddReader(old)) - WaitForSingleObject(m_ReadSignal[1], INFINITE); - else - WaitForSingleObject(m_ReadSignal[0], INFINITE); - } - } -} -void CMultiReadExclusiveWriteSynchronizer::EndRead() -{ - unsigned long id = GetCurrentThreadId(); - unsigned & reccount(tls.Open(this, 1)); - reccount--; - - if ((reccount == 0) && (m_WriterID != id)) - { - int64_t old; - int64_t newvalue; - - do { - old = m_Sentinel; - if ((countReaderBusy(old) == 1) && isWriterWaiting(old)) - { // give control to the writer... move waiting readers to busy (but blocked) - newvalue = old - WriterWaiting + WriterBusy - ReaderBusy + countReaderWaiting(old) * (ReaderBusy - ReaderWaiting); - } else { - newvalue = old - ReaderBusy; - } - } while (CMPXCHG_64(m_Sentinel, newvalue, old) != old); - - if ((countReaderBusy(old) == 1) && isWriterWaiting(old)) - { - SetEvent(m_WriteSignal); - } - } - - if (reccount == 0) - tls.Remove(this); -} -bool CMultiReadExclusiveWriteSynchronizer::BeginWrite() -{ - unsigned long id = GetCurrentThreadId(); - unsigned * reccount = tls.Find(this); - bool res = true; - - if (m_WriterID != id) - { - int64_t old; - int64_t newvalue; - unsigned int oldrevision = m_Revision; - - if (reccount) // upgrade our readlock - { - do { - old = m_Sentinel; - // isWriterBusy cannot happen because we have a readlock, so we ignore it - if (countReaderBusy(old) > 1) // there is another reader.. we have to wait for him. set arriving readers to waiting state - { - newvalue = old + WriterWaiting - ReaderBusy; - } else if (isWriterWaiting(old)) // there is another writer waiting, who arrived earlier. we will sign him in and wait. we are the last reader, so we have to update the sentinel - { - newvalue = old + WriterBusy - ReaderBusy + countReaderWaiting(old) * (ReaderBusy - ReaderWaiting); - } else { // nobody is busy, we want the lock - newvalue = old + WriterBusy - ReaderBusy; - } - } while (CMPXCHG_64(m_Sentinel, newvalue, old) != old); - - if (countReaderBusy(old) > 1) - { - WaitForSingleObject(m_WriteSignal, INFINITE); // someone woke me up... he had to take care of all state changes of the sentinel - } else if (isWriterWaiting(old)) // we will wait for the other writer, as we are the last reader, we have to wake him up - { - SetEvent(m_WriteSignal); - Sleep(0); // yield thread trying to keep FIFO order - WaitForSingleObject(m_WriteSignal, INFINITE); // someone woke me up... he had to take care of all state changes of the sentinel - } - } else { // gain write lock - do { - old = m_Sentinel; - if (isWriterBusy(old)) // there is a writer.. we have to wait for him - { - newvalue = old + WriterWaiting; - } else if (isReaderBusy(old)) // there is a reader.. we have to wait for him. set arriving readers to waiting state - { - newvalue = old + WriterWaiting; - } else if (isWriterWaiting(old)) // there is another writer waiting, who arrived earlier. we will wait - { - newvalue = old + WriterWaiting; - } else { // nobody is busy, we want the lock - newvalue = old + WriterBusy; - } - } while (CMPXCHG_64(m_Sentinel, newvalue, old) != old); - - if (isWriterBusy(old) || isReaderBusy(old) || isWriterWaiting(old)) - { - WaitForSingleObject(m_WriteSignal, INFINITE); // someone woke me up... he had to take care of all state changes of the sentinel - } - } - res = (oldrevision == (INC_32(m_Revision) - 1)); - - m_WriterID = id; - } - m_WriteRecursion++; - - return res; -} - -bool CMultiReadExclusiveWriteSynchronizer::EndWrite() -{ - unsigned long id = GetCurrentThreadId(); - unsigned * reccount = tls.Find(this); - - m_WriteRecursion--; - - if (m_WriteRecursion == 0) - { - int64_t old; - int64_t newvalue; - - m_WriterID = 0; - - if (isUseOddReader(m_Sentinel)) // reset upcoming signal - ResetEvent(m_ReadSignal[0]); - else - ResetEvent(m_ReadSignal[1]); - - if (reccount) // downgrade to reader lock - { - do { - old = m_Sentinel; - newvalue = (old ^ useOddReader) - WriterBusy + ReaderBusy; // single case... we are a waiting reader and we will keep control of the lock - } while (CMPXCHG_64(m_Sentinel, newvalue, old) != old); - - if (isUseOddReader(old)) // allow additional readers to pass - SetEvent(m_ReadSignal[1]); - else - SetEvent(m_ReadSignal[0]); - - } else { - - do { - old = m_Sentinel; - if (isReaderBusy(old)) // give control to waiting readers - { - newvalue = (old ^ useOddReader) - WriterBusy; - } else if (isWriterWaiting(old)) // no reader arrived while i was working... give control to next writer - { - newvalue = (old ^ useOddReader) - WriterWaiting; - } else { // nobody else is there... just close lock - newvalue = (old ^ useOddReader) - WriterBusy; - } - } while (CMPXCHG_64(m_Sentinel, newvalue, old) != old); - - if (isReaderBusy(old)) // release waiting readers - { - if (isUseOddReader(old)) - SetEvent(m_ReadSignal[1]); - else - SetEvent(m_ReadSignal[0]); - } else if (isWriterWaiting(old)) - { - SetEvent(m_WriteSignal); - } - } - return true; - } - - return false; -} - -bool CMultiReadExclusiveWriteSynchronizer::TryBeginWrite() -{ - unsigned long id = GetCurrentThreadId(); - unsigned * reccount = tls.Find(this); - - if (m_WriterID != id) - { - int64_t old; - int64_t newvalue; - unsigned int oldrevision = m_Revision; - - if (reccount) // upgrade our readlock - { - do { - old = m_Sentinel; - // isWriterBusy cannot happen because we have a readlock, so we ignore it - if (countReaderBusy(old) > 1) // there is another reader.. we have to wait for him. set arriving readers to waiting state - { - return false; - } else if (isWriterWaiting(old)) // there is another writer waiting, who arrived earlier. we will sign him in and wait. we are the last reader, so we have to update the sentinel - { - return false; - } else { // nobody is busy, we want the lock - newvalue = old + WriterBusy - ReaderBusy; - } - } while (CMPXCHG_64(m_Sentinel, newvalue, old) != old); - - } else { // gain write lock - do { - old = m_Sentinel; - if (isWriterBusy(old)) // there is a writer.. we have to wait for him - { - return false; - } else if (isReaderBusy(old)) // there is a reader.. we have to wait for him. set arriving readers to waiting state - { - return false; - } else if (isWriterWaiting(old)) // there is another writer waiting, who arrived earlier. we will wait - { - return false; - } else { // nobody is busy, we want the lock - newvalue = old + WriterBusy; - } - } while (CMPXCHG_64(m_Sentinel, newvalue, old) != old); - } - INC_32(m_Revision); - - m_WriterID = id; - } - m_WriteRecursion++; - - return true; -} - -unsigned int CMultiReadExclusiveWriteSynchronizer::Waiting() -{ - int64_t old = m_Sentinel; - if (isWriterBusy(old)) - { // cast is safe, we don't loose data because these fields are max 20 bits - return static_cast(countReaderBusy(old) + countReaderWaiting(old) + countWriterWaiting(old)); - } else { - return static_cast(countReaderWaiting(old) + countWriterWaiting(old)); - } -}; diff --git a/plugins/Dbx_tree/MREWSync.h b/plugins/Dbx_tree/MREWSync.h deleted file mode 100644 index 2ffcbc08d7..0000000000 --- a/plugins/Dbx_tree/MREWSync.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - -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. - -*/ - -#pragma once - -#include -#include "TLS.h" -#include "stdint.h" - -class CMultiReadExclusiveWriteSynchronizer -{ -private: - uint64_t volatile m_Sentinel; - HANDLE m_ReadSignal[2]; - HANDLE m_WriteSignal; - - volatile uint32_t m_Revision; - unsigned int m_WriterID; - unsigned int m_WriteRecursion; - - CThreadLocalStorage tls; - -public: - CMultiReadExclusiveWriteSynchronizer(); - virtual ~CMultiReadExclusiveWriteSynchronizer(); - - void BeginRead(); - void EndRead(); - bool BeginWrite(); - bool TryBeginWrite(); - bool EndWrite(); - - unsigned int Waiting(); - unsigned int WriteRecursionCount() {return m_WriteRecursion;}; - -}; diff --git a/plugins/Dbx_tree/MappedMemory.cpp b/plugins/Dbx_tree/MappedMemory.cpp deleted file mode 100644 index 09a1471a90..0000000000 --- a/plugins/Dbx_tree/MappedMemory.cpp +++ /dev/null @@ -1,167 +0,0 @@ -/* - -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 "MappedMemory.h" -#include "Logger.h" - -typedef BOOL (WINAPI *TUnmapViewOfFile)(LPCVOID); -typedef BOOL (WINAPI *TFlushViewOfFile)(LPCVOID, SIZE_T); -typedef HANDLE (WINAPI *TCreateFileMappingA)(HANDLE, LPSECURITY_ATTRIBUTES, DWORD, DWORD, DWORD, LPCSTR); -typedef LPVOID (WINAPI *TMapViewOfFile)(HANDLE, DWORD, DWORD, DWORD, SIZE_T); - -HMODULE myKernelLib = NULL; -TUnmapViewOfFile myUnmapViewOfFile = NULL; -TFlushViewOfFile myFlushViewOfFile = NULL; -TCreateFileMappingA myCreateFileMappingA = NULL; -TMapViewOfFile myMapViewOfFile = NULL; - -bool CMappedMemory::InitMMAP() -{ - if (!myKernelLib) - myKernelLib = GetModuleHandleA("kernel32.dll"); // is always loaded - - if (myKernelLib) - { - myUnmapViewOfFile = (TUnmapViewOfFile) GetProcAddress(myKernelLib, "UnmapViewOfFile"); - myFlushViewOfFile = (TFlushViewOfFile) GetProcAddress(myKernelLib, "FlushViewOfFile"); - myCreateFileMappingA = (TCreateFileMappingA) GetProcAddress(myKernelLib, "CreateFileMappingA"); - myMapViewOfFile = (TMapViewOfFile) GetProcAddress(myKernelLib, "MapViewOfFile"); - } - - return myUnmapViewOfFile && myFlushViewOfFile && myCreateFileMappingA && myMapViewOfFile; -} -CMappedMemory::CMappedMemory(const TCHAR* FileName) -: CFileAccess(FileName) -{ - SYSTEM_INFO sysinfo; - - m_AllocSize = 0; - m_DirectFile = 0; - m_FileMapping = 0; - m_Base = NULL; - - GetSystemInfo(&sysinfo); - m_AllocGranularity = sysinfo.dwAllocationGranularity; // usually 64kb - m_MinAllocGranularity = m_AllocGranularity; // must be at least one segment - m_MaxAllocGranularity = m_AllocGranularity << 4; // usually 1mb for fast increasing - - m_DirectFile = CreateFile(FileName, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS, 0); - if (m_DirectFile == INVALID_HANDLE_VALUE) - LOGSYS(logCRITICAL, _T("CreateFile failed")); - - uint32_t size = GetFileSize(m_DirectFile, NULL); - size = (size + m_AllocGranularity - 1) & ~(m_AllocGranularity - 1); - - if (size == 0) - size = m_AllocGranularity; - - _SetSize(size); - m_AllocSize = size; - - InitJournal(); -} - -CMappedMemory::~CMappedMemory() -{ - if (m_Base) - { - myFlushViewOfFile(m_Base, NULL); - myUnmapViewOfFile(m_Base); - } - if (m_FileMapping) - CloseHandle(m_FileMapping); - - if (m_DirectFile) - { - if (INVALID_SET_FILE_POINTER != SetFilePointer(m_DirectFile, m_Size, NULL, FILE_BEGIN)) - SetEndOfFile(m_DirectFile); - - FlushFileBuffers(m_DirectFile); - CloseHandle(m_DirectFile); - } -} - - -uint32_t CMappedMemory::_Read(void* Buf, uint32_t Source, uint32_t Size) -{ - memcpy(Buf, m_Base + Source, Size); - return Size; -} -uint32_t CMappedMemory::_Write(void* Buf, uint32_t Dest, uint32_t Size) -{ - memcpy(m_Base + Dest, Buf, Size); - return Size; -} - -uint32_t CMappedMemory::_SetSize(uint32_t Size) -{ - if (m_Base) - { - myFlushViewOfFile(m_Base, 0); - myUnmapViewOfFile(m_Base); - } - if (m_FileMapping) - CloseHandle(m_FileMapping); - - m_Base = NULL; - m_FileMapping = NULL; - - if (INVALID_SET_FILE_POINTER == SetFilePointer(m_DirectFile, Size, NULL, FILE_BEGIN)) - { - LOGSYS(logERROR, _T("SetFilePointer failed")); - return 0; - } - - if (!SetEndOfFile(m_DirectFile)) - { - LOGSYS(logERROR, _T("Cannot set end of file")); - return 0; - } - - m_FileMapping = myCreateFileMappingA(m_DirectFile, NULL, PAGE_READWRITE, 0, Size, NULL); - - if (!m_FileMapping) - { - LOGSYS(logERROR, _T("CreateFileMapping failed")); - return 0; - } - - m_Base = (uint8_t*) myMapViewOfFile(m_FileMapping, FILE_MAP_ALL_ACCESS, 0, 0, 0); - if (!m_Base) - { - LOGSYS(logERROR, _T("MapViewOfFile failed")); - return 0; - } - - return Size; -} - -void CMappedMemory::_Invalidate(uint32_t Dest, uint32_t Size) -{ - memset(m_Base + Dest, 0, Size); -} - -void CMappedMemory::_Flush() -{ - myFlushViewOfFile(m_Base, NULL); - FlushFileBuffers(m_DirectFile); -} diff --git a/plugins/Dbx_tree/MappedMemory.h b/plugins/Dbx_tree/MappedMemory.h deleted file mode 100644 index e66862836e..0000000000 --- a/plugins/Dbx_tree/MappedMemory.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - -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. - -*/ - -#pragma once - -#include -#include "FileAccess.h" - -class CMappedMemory : public CFileAccess -{ -private: - uint8_t* m_Base; - - HANDLE m_DirectFile; - HANDLE m_FileMapping; -protected: - - uint32_t _Read(void* Buf, uint32_t Source, uint32_t Size); - uint32_t _Write(void* Buf, uint32_t Dest, uint32_t Size); - void _Invalidate(uint32_t Dest, uint32_t Size); - uint32_t _SetSize(uint32_t Size); - void _Flush(); -public: - CMappedMemory(const TCHAR* FileName); - virtual ~CMappedMemory(); - - static bool InitMMAP(); -}; diff --git a/plugins/Dbx_tree/SHA256.cpp b/plugins/Dbx_tree/SHA256.cpp deleted file mode 100644 index 9ca7df329c..0000000000 --- a/plugins/Dbx_tree/SHA256.cpp +++ /dev/null @@ -1,301 +0,0 @@ -/* - -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 "SHA256.h" -#include -#include - -#if !defined(_MSC_VER) || !defined(_M_IX86) -#define NO_ASM -#endif -#define SHA_LOOPUNROLL - -#ifndef _MSC_VER - #define rotr(x,n) (((x)>>(n))|((x)<<(32-(n)))) -#else - #define rotr(x,n) _lrotr(x,n) -#endif - - -// table of round constants -// (first 32 bits of the fractional parts of the cube roots of the first 64 primes 2..311): -static const uint32_t cKey[64] = { - 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, - 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, - 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, - 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, - 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, - 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, - 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, - 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, - 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, - 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, - 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, - 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, - 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, - 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, - 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, - 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 -}; - -// initialisation vector -// (first 32 bits of the fractional parts of the square roots of the first 8 primes 2..19): -static const SHA256::THash cHashInit = { - 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19 -}; - - - -SHA256::SHA256() -{ - SHAInit(); -} -SHA256::~SHA256() -{ - -} -void SHA256::SHAInit() -{ - memcpy(m_Hash, cHashInit, sizeof(m_Hash)); - m_Length = 0; -} -void SHA256::SHAUpdate(void * Data, uint32_t Length) -{ - uint8_t * dat = (uint8_t *)Data; - uint32_t len = Length; - - if (m_Length & 63) - { - uint32_t p = (m_Length & 63); - uint32_t pl = 64 - p; - if (pl > len) - pl = len; - - memcpy(&(m_Block[p]), dat, pl); - len -= pl; - dat += pl; - - if (p + pl == 64) - SHABlock(); - } - - while (len >= 64) - { - memcpy(m_Block, dat, sizeof(m_Block)); - SHABlock(); - len -= 64; - dat += 64; - } - - if (len > 0) - { - memcpy(m_Block, dat, len); - } - - m_Length += Length; -} - -void SHA256::SHAFinal(SHA256::THash & Hash) -{ - uint8_t pad[128] = { - 0x80, 0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0 - }; - - uint32_t padlen = 0; - if ((m_Length & 63) < 55) // 64 - 9 -> short padding - { - padlen = 64 - (m_Length & 63); - } else { - padlen = 128 - (m_Length & 63); - } - - uint64_t l = m_Length << 3; - { - uint8_t * p = (uint8_t *) &l; -#ifdef NO_ASM - pad[padlen - 1] = (uint8_t)(p[0]); - pad[padlen - 2] = (uint8_t)(p[1]); - pad[padlen - 3] = (uint8_t)(p[2]); - pad[padlen - 4] = (uint8_t)(p[3]); - pad[padlen - 5] = (uint8_t)(p[4]); - pad[padlen - 6] = (uint8_t)(p[5]); - pad[padlen - 7] = (uint8_t)(p[6]); - pad[padlen - 8] = (uint8_t)(p[7]); -#else - uint8_t * p2 = (uint8_t *) &(pad[padlen - 8]); - __asm { - MOV ebx, p - MOV eax, [ebx] - BSWAP eax - MOV edx, [ebx + 4] - MOV ebx, p2 - BSWAP edx - MOV [ebx + 4], eax - MOV [ebx], edx - } -#endif - } - - SHAUpdate((uint32_t *)pad, padlen); - - { - uint8_t * h = (uint8_t *)Hash; - uint8_t * m = (uint8_t *)m_Hash; -#ifdef NO_ASM - for (int i = 0; i < 32; i += 4) - { - h[i] = m[i + 3]; - h[i + 1] = m[i + 2]; - h[i + 2] = m[i + 1]; - h[i + 3] = m[i]; - } -#else - __asm { - MOV esi, m - MOV edi, h - MOV ecx, 8 - loop_label: - LODSD - BSWAP eax - STOSD - dec ecx - jnz loop_label - } -#endif - } - - SHAInit(); -} - -#define SHA256_ROUND(a,b,c,d,e,f,g,h, i) { \ -t1 = (h) + (rotr((e), 6) ^ rotr((e), 11) ^ rotr((e), 25)) + \ - (((e) & (f)) ^ ((~(e)) & (g))) + cKey[i] + w[i]; \ -t2 = (rotr((a), 2) ^ rotr((a), 13) ^ rotr((a), 22)) + \ - (((a) & (b)) ^ ((a) & (c)) ^ ((b) & (c))); \ -d += t1; \ -h = t1 + t2; \ -} - -void SHA256::SHABlock() -{ - uint32_t w[64]; - - // make Big Endian - { - uint8_t * d = (uint8_t *)w; - uint8_t * s = (uint8_t *)m_Block; -#ifdef NO_ASM - for (int i = 0; i < 64; i += 4) - { - d[i] = s[i + 3]; - d[i + 1] = s[i + 2]; - d[i + 2] = s[i + 1]; - d[i + 3] = s[i]; - } -#else - __asm { - MOV esi, s - MOV edi, d - MOV ecx, 16 - loop_label: - LODSD - BSWAP eax - STOSD - dec ecx - jnz loop_label - } -#endif - } - - uint32_t t1, t2, a,b,c,d,e,f,g,h; - for (uint32_t i = 16; i < 64; ++i) - { - t1 = w[i-15]; - t2 = w[i-2]; - w[i] = w[i-16] + (rotr(t1, 7) ^ rotr(t1, 18) ^ (t1 >> 3)) + w[i-7] + (rotr(t2, 17) ^ rotr(t2, 19) ^ (t2 >> 10)); - } - - a = m_Hash[0]; - b = m_Hash[1]; - c = m_Hash[2]; - d = m_Hash[3]; - e = m_Hash[4]; - f = m_Hash[5]; - g = m_Hash[6]; - h = m_Hash[7]; - -#ifdef SHA_LOOPUNROLL - for (uint32_t i = 0; i < 64; ++i) - { - SHA256_ROUND(a,b,c,d,e,f,g,h,i); ++i; - SHA256_ROUND(h,a,b,c,d,e,f,g,i); ++i; - SHA256_ROUND(g,h,a,b,c,d,e,f,i); ++i; - SHA256_ROUND(f,g,h,a,b,c,d,e,i); ++i; - SHA256_ROUND(e,f,g,h,a,b,c,d,i); ++i; - SHA256_ROUND(d,e,f,g,h,a,b,c,i); ++i; - SHA256_ROUND(c,d,e,f,g,h,a,b,i); ++i; - SHA256_ROUND(b,c,d,e,f,g,h,a,i); - } -#else - for (uint32_t i = 0; i < 64; ++i) - { - t1 = h + (rotr(e, 6) ^ rotr(e, 11) ^ rotr(e, 25)) + //s1 - ((e & f) ^ ((~e) & g)) + cKey[i] + w[i]; //ch - - t2 = (rotr(a, 2) ^ rotr(a, 13) ^ rotr(a, 22)) + //s0 - ((a & b) ^ (a & c) ^ (b & c)); //maj - - h = g; - g = f; - f = e; - e = d + t1; - d = c; - c = b; - b = a; - a = t1 + t2; - } -#endif - - m_Hash[0] += a; - m_Hash[1] += b; - m_Hash[2] += c; - m_Hash[3] += d; - m_Hash[4] += e; - m_Hash[5] += f; - m_Hash[6] += g; - m_Hash[7] += h; -} diff --git a/plugins/Dbx_tree/SHA256.h b/plugins/Dbx_tree/SHA256.h deleted file mode 100644 index a9629e6a2a..0000000000 --- a/plugins/Dbx_tree/SHA256.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - -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. - -*/ - -#ifndef _MSC_VER -#include -#else -#include "stdint.h" -#endif - - -class SHA256 -{ -public: - typedef uint32_t THash[8]; - - SHA256(); - ~SHA256(); - - void SHAInit(); - void SHAUpdate(void * Data, uint32_t Length); - void SHAFinal(THash & Hash); -private: - THash m_Hash; - uint64_t m_Length; /// Datalength in byte - - uint8_t m_Block[64]; - - void SHABlock(); - void Swap64(void * Addr); -}; diff --git a/plugins/Dbx_tree/Services.cpp b/plugins/Dbx_tree/Services.cpp deleted file mode 100644 index d8b734795d..0000000000 --- a/plugins/Dbx_tree/Services.cpp +++ /dev/null @@ -1,402 +0,0 @@ -/* - -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 "Services.h" - -HANDLE gServices[40] = {0}; - -INT_PTR DBEntityGetRoot(WPARAM wParam, LPARAM lParam) -{ - return gDataBase->getEntities().getRootEntity(); -} -INT_PTR DBEntityChildCount(WPARAM hEntity, LPARAM lParam) -{ - if (hEntity == 0) - hEntity = gDataBase->getEntities().getRootEntity(); - - return gDataBase->getEntities().getChildCount(hEntity); -} -INT_PTR DBEntityGetParent(WPARAM hEntity, LPARAM lParam) -{ - if (hEntity == 0) - hEntity = gDataBase->getEntities().getRootEntity(); - - return gDataBase->getEntities().getParent(hEntity); -} -INT_PTR DBEntityMove(WPARAM hEntity, LPARAM hParent) -{ - if ((hEntity == 0) || (hEntity == gDataBase->getEntities().getRootEntity())) - return DBT_INVALIDPARAM; - - if (hParent == 0) - hParent = gDataBase->getEntities().getRootEntity(); - - return gDataBase->getEntities().setParent(hEntity, hParent); -} -INT_PTR DBEntityGetFlags(WPARAM hEntity, LPARAM lParam) -{ - if (hEntity == 0) - hEntity = gDataBase->getEntities().getRootEntity(); - - return gDataBase->getEntities().getFlags(hEntity); -} -INT_PTR DBEntityIterInit(WPARAM pFilter, LPARAM hParent) -{ - TDBTEntityIterFilter fil = {0,0,0,0}; - if (pFilter == NULL) - { - pFilter = reinterpret_cast(&fil); - fil.cbSize = sizeof(fil); - } - - if (reinterpret_cast(pFilter)->cbSize != sizeof(TDBTEntityIterFilter)) - return DBT_INVALIDPARAM; - - if (reinterpret_cast(pFilter)->fDontHasFlags & ((PDBTEntityIterFilter)pFilter)->fHasFlags) - return DBT_INVALIDPARAM; - - if (hParent == 0) - hParent = gDataBase->getEntities().getRootEntity(); - - return gDataBase->getEntities().IterationInit(*reinterpret_cast(pFilter), hParent); -} -INT_PTR DBEntityIterNext(WPARAM hIteration, LPARAM lParam) -{ - if ((hIteration == 0) || (hIteration == DBT_INVALIDPARAM)) - return hIteration; - - return gDataBase->getEntities().IterationNext(hIteration); -} -INT_PTR DBEntityIterClose(WPARAM hIteration, LPARAM lParam) -{ - if ((hIteration == 0) || (hIteration == DBT_INVALIDPARAM)) - return hIteration; - - return gDataBase->getEntities().IterationClose(hIteration); -} -INT_PTR DBEntityDelete(WPARAM hEntity, LPARAM lParam) -{ - if ((hEntity == 0) || (hEntity == gDataBase->getEntities().getRootEntity())) - return DBT_INVALIDPARAM; - - return gDataBase->getEntities().DeleteEntity(hEntity); -} -INT_PTR DBEntityCreate(WPARAM pEntity, LPARAM lParam) -{ - if (reinterpret_cast(pEntity)->bcSize != sizeof(TDBTEntity)) - return DBT_INVALIDPARAM; - - if (reinterpret_cast(pEntity)->hParentEntity == 0) - reinterpret_cast(pEntity)->hParentEntity = gDataBase->getEntities().getRootEntity(); - - reinterpret_cast(pEntity)->fFlags = reinterpret_cast(pEntity)->fFlags & ~(DBT_NF_IsRoot | DBT_NF_HasChildren | DBT_NF_IsVirtual | DBT_NF_HasVirtuals); // forbidden flags... - return gDataBase->getEntities().CreateEntity(*reinterpret_cast(pEntity)); -} - -INT_PTR DBEntityGetAccount(WPARAM hEntity, LPARAM lParam) -{ - return gDataBase->getEntities().getAccount(hEntity); -} - -INT_PTR DBVirtualEntityCreate(WPARAM hEntity, LPARAM hParent) -{ - if ((hEntity == 0) || (hEntity == gDataBase->getEntities().getRootEntity())) - return DBT_INVALIDPARAM; - - if (hParent == 0) - hParent = gDataBase->getEntities().getRootEntity(); - - return gDataBase->getEntities().VirtualCreate(hEntity, hParent); -} -INT_PTR DBVirtualEntityGetParent(WPARAM hVirtualEntity, LPARAM lParam) -{ - if ((hVirtualEntity == 0) || (hVirtualEntity == gDataBase->getEntities().getRootEntity())) - return DBT_INVALIDPARAM; - - return gDataBase->getEntities().VirtualGetParent(hVirtualEntity); -} -INT_PTR DBVirtualEntityGetFirst(WPARAM hEntity, LPARAM lParam) -{ - if ((hEntity == 0) || (hEntity == gDataBase->getEntities().getRootEntity())) - return DBT_INVALIDPARAM; - - return gDataBase->getEntities().VirtualGetFirst(hEntity); -} -INT_PTR DBVirtualEntityGetNext(WPARAM hVirtualEntity, LPARAM lParam) -{ - if ((hVirtualEntity == 0) || (hVirtualEntity == gDataBase->getEntities().getRootEntity())) - return DBT_INVALIDPARAM; - - return gDataBase->getEntities().VirtualGetNext(hVirtualEntity); -} - - -INT_PTR DBSettingFind(WPARAM pSettingDescriptor, LPARAM lParam) -{ - if (pSettingDescriptor == NULL) - return DBT_INVALIDPARAM; - - if (reinterpret_cast(pSettingDescriptor)->cbSize != sizeof(TDBTSettingDescriptor)) - return DBT_INVALIDPARAM; - - if (reinterpret_cast(pSettingDescriptor)->pszSettingName == NULL) - return DBT_INVALIDPARAM; - - return gDataBase->getSettings().FindSetting(*reinterpret_cast(pSettingDescriptor)); -} -INT_PTR DBSettingDelete(WPARAM pSettingDescriptor, LPARAM lParam) -{ - if (pSettingDescriptor == NULL) - return DBT_INVALIDPARAM; - - if (reinterpret_cast(pSettingDescriptor)->cbSize != sizeof(TDBTSettingDescriptor)) - return DBT_INVALIDPARAM; - - if (reinterpret_cast(pSettingDescriptor)->pszSettingName == NULL) - return DBT_INVALIDPARAM; - - return gDataBase->getSettings().DeleteSetting(*reinterpret_cast(pSettingDescriptor)); -} -INT_PTR DBSettingDeleteHandle(WPARAM hSetting, LPARAM lParam) -{ - if (hSetting == 0) - return DBT_INVALIDPARAM; - - return gDataBase->getSettings().DeleteSetting(hSetting); -} -INT_PTR DBSettingWrite(WPARAM pSetting, LPARAM lParam) -{ - if (pSetting == NULL) - return DBT_INVALIDPARAM; - - if (reinterpret_cast(pSetting)->cbSize != sizeof(TDBTSetting)) - return DBT_INVALIDPARAM; - - if (reinterpret_cast(pSetting)->Descriptor == NULL) - return DBT_INVALIDPARAM; - - if (reinterpret_cast(pSetting)->Descriptor->cbSize != sizeof(TDBTSettingDescriptor)) - return DBT_INVALIDPARAM; - - if (reinterpret_cast(pSetting)->Descriptor->pszSettingName == NULL) - return DBT_INVALIDPARAM; - - if ((reinterpret_cast(pSetting)->Type & DBT_STF_VariableLength) && (reinterpret_cast(pSetting)->Value.pBlob == NULL)) - return DBT_INVALIDPARAM; - - return gDataBase->getSettings().WriteSetting(*reinterpret_cast(pSetting)); -} -INT_PTR DBSettingWriteHandle(WPARAM pSetting, LPARAM hSetting) -{ - if (pSetting == NULL) - return DBT_INVALIDPARAM; - - if (reinterpret_cast(pSetting)->cbSize != sizeof(TDBTSetting)) - return DBT_INVALIDPARAM; - - return gDataBase->getSettings().WriteSetting(*reinterpret_cast(pSetting), hSetting); -} -INT_PTR DBSettingRead(WPARAM pSetting, LPARAM lParam) -{ - if (pSetting == NULL) - return DBT_INVALIDPARAM; - - if (reinterpret_cast(pSetting)->cbSize != sizeof(TDBTSetting)) - return DBT_INVALIDPARAM; - - if (reinterpret_cast(pSetting)->Descriptor == NULL) - return DBT_INVALIDPARAM; - - if (reinterpret_cast(pSetting)->Descriptor->cbSize != sizeof(TDBTSettingDescriptor)) - return DBT_INVALIDPARAM; - - if (reinterpret_cast(pSetting)->Descriptor->pszSettingName == NULL) - return DBT_INVALIDPARAM; - - return gDataBase->getSettings().ReadSetting(*reinterpret_cast(pSetting)); -} -INT_PTR DBSettingReadHandle(WPARAM pSetting, LPARAM hSetting) -{ - if ((pSetting == NULL) || (hSetting == 0)) - return DBT_INVALIDPARAM; - - if (reinterpret_cast(pSetting)->cbSize != sizeof(TDBTSetting)) - return DBT_INVALIDPARAM; - - if ((reinterpret_cast(pSetting)->Descriptor != NULL) && (reinterpret_cast(pSetting)->Descriptor->cbSize != sizeof(TDBTSettingDescriptor))) - return DBT_INVALIDPARAM; - - return gDataBase->getSettings().ReadSetting(*((PDBTSetting)pSetting), hSetting); -} -INT_PTR DBSettingIterInit(WPARAM pFilter, LPARAM lParam) -{ - if (pFilter == NULL) - return DBT_INVALIDPARAM; - - if (reinterpret_cast(pFilter)->cbSize != sizeof(TDBTSettingIterFilter)) - return DBT_INVALIDPARAM; - - if ((reinterpret_cast(pFilter)->Descriptor != NULL) && (reinterpret_cast(pFilter)->Descriptor->cbSize != sizeof(TDBTSettingDescriptor))) - return DBT_INVALIDPARAM; - - if ((reinterpret_cast(pFilter)->Setting != NULL) && (reinterpret_cast(pFilter)->Setting->cbSize != sizeof(TDBTSetting))) - return DBT_INVALIDPARAM; - - if ((reinterpret_cast(pFilter)->Setting != NULL) && (reinterpret_cast(pFilter)->Setting->Descriptor != NULL) && (reinterpret_cast(pFilter)->Setting->Descriptor->cbSize != sizeof(TDBTSettingIterFilter))) - return DBT_INVALIDPARAM; - - return gDataBase->getSettings().IterationInit(*reinterpret_cast(pFilter)); -} -INT_PTR DBSettingIterNext(WPARAM hIteration, LPARAM lParam) -{ - if ((hIteration == 0) || (hIteration == DBT_INVALIDPARAM)) - return hIteration; - - return gDataBase->getSettings().IterationNext(hIteration); -} -INT_PTR DBSettingIterClose(WPARAM hIteration, LPARAM lParam) -{ - if ((hIteration == 0) || (hIteration == DBT_INVALIDPARAM)) - return hIteration; - - return gDataBase->getSettings().IterationClose(hIteration); -} - -INT_PTR DBEventGetBlobSize(WPARAM hEvent, LPARAM lParam) -{ - return gDataBase->getEvents().GetBlobSize(hEvent); -} - -INT_PTR DBEventGet(WPARAM hEvent, LPARAM pEvent) -{ - if ((pEvent == NULL) || (reinterpret_cast(pEvent)->cbSize != sizeof(TDBTEvent))) - return DBT_INVALIDPARAM; - - return gDataBase->getEvents().Get(hEvent, *reinterpret_cast(pEvent)); -} - -INT_PTR DBEventGetCount(WPARAM hEntity, LPARAM lParam) -{ - return gDataBase->getEvents().GetCount(hEntity); -} - -INT_PTR DBEventDelete(WPARAM hEvent, LPARAM lParam) -{ - return gDataBase->getEvents().Delete(hEvent); -} - -INT_PTR DBEventAdd(WPARAM hEntity, LPARAM pEvent) -{ - if ((pEvent == NULL) || (reinterpret_cast(pEvent)->cbSize != sizeof(TDBTEvent)) || (reinterpret_cast(pEvent)->pBlob == NULL) || (reinterpret_cast(pEvent)->cbBlob == 0)) - return DBT_INVALIDPARAM; - - return gDataBase->getEvents().Add(hEntity, *((PDBTEvent)pEvent)); -} - -INT_PTR DBEventMarkRead(WPARAM hEvent, LPARAM lParam) -{ - return gDataBase->getEvents().MarkRead(hEvent); -} - -INT_PTR DBEventWriteToDisk(WPARAM hEvent, LPARAM lParam) -{ - return gDataBase->getEvents().WriteToDisk(hEvent); -} - -INT_PTR DBEventGetEntity(WPARAM hEvent, LPARAM lParam) -{ - return gDataBase->getEvents().getEntity(hEvent); -} - -INT_PTR DBEventIterInit(WPARAM pFilter, LPARAM lParam) -{ - if ((pFilter == NULL) || (reinterpret_cast(pFilter)->cbSize != sizeof(TDBTEventIterFilter))) - return DBT_INVALIDPARAM; - - if ((reinterpret_cast(pFilter)->Event != NULL) && (reinterpret_cast(pFilter)->Event->cbSize != sizeof(TDBTEvent))) - return DBT_INVALIDPARAM; - - return gDataBase->getEvents().IterationInit(*reinterpret_cast(pFilter)); -} - -INT_PTR DBEventIterNext(WPARAM hIteration, LPARAM lParam) -{ - if ((hIteration == 0) || (hIteration == DBT_INVALIDPARAM)) - return hIteration; - - return gDataBase->getEvents().IterationNext(hIteration); -} - -INT_PTR DBEventIterClose(WPARAM hIteration, LPARAM lParam) -{ - if ((hIteration == 0) || (hIteration == DBT_INVALIDPARAM)) - return hIteration; - - return gDataBase->getEvents().IterationClose(hIteration); -} - - -bool RegisterServices() -{ - gServices[ 0] = CreateServiceFunction(MS_DBT_ENTITY_GETROOT, DBEntityGetRoot); - gServices[ 1] = CreateServiceFunction(MS_DBT_ENTITY_CHILDCOUNT, DBEntityChildCount); - gServices[ 2] = CreateServiceFunction(MS_DBT_ENTITY_GETPARENT, DBEntityGetParent); - gServices[ 3] = CreateServiceFunction(MS_DBT_ENTITY_MOVE, DBEntityMove); - gServices[ 8] = CreateServiceFunction(MS_DBT_ENTITY_GETFLAGS, DBEntityGetFlags); - gServices[ 9] = CreateServiceFunction(MS_DBT_ENTITY_ITER_INIT, DBEntityIterInit); - gServices[10] = CreateServiceFunction(MS_DBT_ENTITY_ITER_NEXT, DBEntityIterNext); - gServices[11] = CreateServiceFunction(MS_DBT_ENTITY_ITER_CLOSE, DBEntityIterClose); - gServices[12] = CreateServiceFunction(MS_DBT_ENTITY_DELETE, DBEntityDelete); - gServices[13] = CreateServiceFunction(MS_DBT_ENTITY_CREATE, DBEntityCreate); - gServices[13] = CreateServiceFunction(MS_DBT_ENTITY_GETACCOUNT, DBEntityGetAccount); - - gServices[14] = CreateServiceFunction(MS_DBT_VIRTUALENTITY_CREATE, DBVirtualEntityCreate); - gServices[15] = CreateServiceFunction(MS_DBT_VIRTUALENTITY_GETPARENT, DBVirtualEntityGetParent); - gServices[16] = CreateServiceFunction(MS_DBT_VIRTUALENTITY_GETFIRST, DBVirtualEntityGetFirst); - gServices[17] = CreateServiceFunction(MS_DBT_VIRTUALENTITY_GETNEXT, DBVirtualEntityGetNext); - - gServices[18] = CreateServiceFunction(MS_DBT_SETTING_FIND, DBSettingFind); - gServices[19] = CreateServiceFunction(MS_DBT_SETTING_DELETE, DBSettingDelete); - gServices[20] = CreateServiceFunction(MS_DBT_SETTING_DELETEHANDLE, DBSettingDeleteHandle); - gServices[21] = CreateServiceFunction(MS_DBT_SETTING_WRITE, DBSettingWrite); - gServices[22] = CreateServiceFunction(MS_DBT_SETTING_WRITEHANDLE, DBSettingWriteHandle); - gServices[23] = CreateServiceFunction(MS_DBT_SETTING_READ, DBSettingRead); - gServices[24] = CreateServiceFunction(MS_DBT_SETTING_READHANDLE, DBSettingReadHandle); - gServices[25] = CreateServiceFunction(MS_DBT_SETTING_ITER_INIT, DBSettingIterInit); - gServices[26] = CreateServiceFunction(MS_DBT_SETTING_ITER_NEXT, DBSettingIterNext); - gServices[27] = CreateServiceFunction(MS_DBT_SETTING_ITER_CLOSE, DBSettingIterClose); - - gServices[28] = CreateServiceFunction(MS_DBT_EVENT_GETBLOBSIZE, DBEventGetBlobSize); - gServices[29] = CreateServiceFunction(MS_DBT_EVENT_GET, DBEventGet); - gServices[30] = CreateServiceFunction(MS_DBT_EVENT_GETCOUNT, DBEventGetCount); - gServices[31] = CreateServiceFunction(MS_DBT_EVENT_DELETE, DBEventDelete); - gServices[32] = CreateServiceFunction(MS_DBT_EVENT_ADD, DBEventAdd); - gServices[33] = CreateServiceFunction(MS_DBT_EVENT_MARKREAD, DBEventMarkRead); - gServices[34] = CreateServiceFunction(MS_DBT_EVENT_WRITETODISK, DBEventWriteToDisk); - gServices[35] = CreateServiceFunction(MS_DBT_EVENT_GETENTITY, DBEventGetEntity); - gServices[36] = CreateServiceFunction(MS_DBT_EVENT_ITER_INIT, DBEventIterInit); - gServices[37] = CreateServiceFunction(MS_DBT_EVENT_ITER_NEXT, DBEventIterNext); - gServices[38] = CreateServiceFunction(MS_DBT_EVENT_ITER_CLOSE, DBEventIterClose); - - - return true; -} diff --git a/plugins/Dbx_tree/Services.h b/plugins/Dbx_tree/Services.h deleted file mode 100644 index 0d75552fd4..0000000000 --- a/plugins/Dbx_tree/Services.h +++ /dev/null @@ -1,69 +0,0 @@ -/* - -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. - -*/ - -#pragma once - -#include "Interface.h" -#include "DataBase.h" - -bool RegisterServices(); - - -INT_PTR DBEntityGetRoot(WPARAM wParam, LPARAM lParam); -INT_PTR DBEntityChildCount(WPARAM hEntity, LPARAM lParam); -INT_PTR DBEntityGetParent(WPARAM hEntity, LPARAM lParam); -INT_PTR DBEntityMove(WPARAM hEntity, LPARAM hParent); -INT_PTR DBEntityGetFlags(WPARAM hEntity, LPARAM lParam); -INT_PTR DBEntityIterInit(WPARAM pFilter, LPARAM hParent); -INT_PTR DBEntityIterNext(WPARAM hIteration, LPARAM lParam); -INT_PTR DBEntityIterClose(WPARAM hIteration, LPARAM lParam); -INT_PTR DBEntityDelete(WPARAM hEntity, LPARAM lParam); -INT_PTR DBEntityCreate(WPARAM pEntity, LPARAM lParam); -INT_PTR DBEntityGetAccount(WPARAM hEntity, LPARAM lParam); - -INT_PTR DBVirtualEntityCreate(WPARAM hEntity, LPARAM hParent); -INT_PTR DBVirtualEntityGetParent(WPARAM hVirtualEntity, LPARAM lParam); -INT_PTR DBVirtualEntityGetFirst(WPARAM hEntity, LPARAM lParam); -INT_PTR DBVirtualEntityGetNext(WPARAM hVirtualEntity, LPARAM lParam); - -INT_PTR DBSettingFind(WPARAM pSettingDescriptor, LPARAM lParam); -INT_PTR DBSettingDelete(WPARAM pSettingDescriptor, LPARAM lParam); -INT_PTR DBSettingDeleteHandle(WPARAM hSetting, LPARAM lParam); -INT_PTR DBSettingWrite(WPARAM pSetting, LPARAM lParam); -INT_PTR DBSettingWriteHandle(WPARAM pSetting, LPARAM hSetting); -INT_PTR DBSettingRead(WPARAM pSetting, LPARAM lParam); -INT_PTR DBSettingReadHandle(WPARAM pSetting, LPARAM hSetting); -INT_PTR DBSettingIterInit(WPARAM pFilter, LPARAM lParam); -INT_PTR DBSettingIterNext(WPARAM hIteration, LPARAM lParam); -INT_PTR DBSettingIterClose(WPARAM hIteration, LPARAM lParam); - -INT_PTR DBEventGetBlobSize(WPARAM hEvent, LPARAM lParam); -INT_PTR DBEventGet(WPARAM hEvent, LPARAM pEvent); -INT_PTR DBEventGetCount(WPARAM hEntity, LPARAM lParam); -INT_PTR DBEventDelete(WPARAM hEvent, LPARAM lParam); -INT_PTR DBEventAdd(WPARAM hEntity, LPARAM pEvent); -INT_PTR DBEventMarkRead(WPARAM hEvent, LPARAM lParam); -INT_PTR DBEventWriteToDisk(WPARAM hEvent, LPARAM lParam); -INT_PTR DBEventGetEntity(WPARAM hEvent, LPARAM lParam); -INT_PTR DBEventIterInit(WPARAM pFilter, LPARAM lParam); -INT_PTR DBEventIterNext(WPARAM hIteration, LPARAM lParam); -INT_PTR DBEventIterClose(WPARAM hIteration, LPARAM lParam); diff --git a/plugins/Dbx_tree/Settings.cpp b/plugins/Dbx_tree/Settings.cpp deleted file mode 100644 index b4ba799c55..0000000000 --- a/plugins/Dbx_tree/Settings.cpp +++ /dev/null @@ -1,1479 +0,0 @@ -/* - -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 // 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(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(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(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(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(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( 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(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(hSetting, size, sig); - - if (!setting) - return DBT_INVALIDPARAM; - - CSettingsTree * tree = getSettingsTree(setting->Entity); - if (tree == NULL) - return DBT_INVALIDPARAM; - - char * str = reinterpret_cast(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(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(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(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(strlen(Setting.Descriptor->pszSettingName)) + 1 + blobsize; - - if (hSetting == 0) // create new setting - { - setting = file->CreateBlock(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(strlen(Setting.Descriptor->pszSettingName))), hSetting); - } - - } else { - uint32_t tmp = 0; - setting = file->ReadBlock(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(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(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(hSetting, size, sig); - - if (!setting) - return DBT_INVALIDPARAM; - - uint8_t* str = reinterpret_cast(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(strlen(Setting.Value.pUTF8) + 1); - } break; - case DBT_ST_WCHAR: - { - Setting.Value.pWide = mir_a2u((char*)str); - Setting.Value.Length = static_cast(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(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(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(strlen(Setting.Value.pAnsi) + 1); - } break; - case DBT_ST_UTF8: - { - Setting.Value.pUTF8 = mir_utf8encodeW((wchar_t*)str); - Setting.Value.Length = static_cast(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 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(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; - - return reinterpret_cast(iter); -} - - -typedef struct TSettingIterationHelper { - TDBTSettingHandle Handle; - CSettingsTree * Tree; - uint16_t NameLen; - char * Name; - } TSettingIterationHelper; - -TDBTSettingHandle CSettings::IterationNext(TDBTSettingIterationHandle Iteration) -{ - PSettingIteration iter = reinterpret_cast(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 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(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; -} diff --git a/plugins/Dbx_tree/Settings.h b/plugins/Dbx_tree/Settings.h deleted file mode 100644 index 28be10603e..0000000000 --- a/plugins/Dbx_tree/Settings.h +++ /dev/null @@ -1,235 +0,0 @@ -/* - -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. - -*/ - -#pragma once - -#include "Interface.h" -#include "FileBTree.h" -#include "MREWSync.h" -#include "sigslot.h" -#include "IterationHeap.h" -#include -#include "lockfree_hashmap.h" - -class CSettings; -class CSettingsTree; - -#include "Entities.h" - -#pragma pack(push, 1) // push current alignment to stack, set alignment to 1 byte boundary - -/** - \brief Key Type of the SettingsBTree - - The setting names (ASCII) are hashed, so that they can easily be accessed. -**/ - -typedef struct TSettingKey { - uint32_t Hash; /// 32 bit hash of the Setting name - TDBTSettingHandle Setting; - - bool operator < (const TSettingKey & Other) const - { - if (Hash != Other.Hash) return Hash < Other.Hash; - if (Setting != Other.Setting) return Setting < Other.Setting; - return false; - } - //bool operator <= (const TSettingKey & Other); - bool operator == (const TSettingKey & Other) const - { - return (Hash == Other.Hash) && (Setting == Other.Setting); - } - //bool operator >= (const TSettingKey & Other); - bool operator > (const TSettingKey & Other) const - { - if (Hash != Other.Hash) return Hash > Other.Hash; - if (Setting != Other.Setting) return Setting > Other.Setting; - return false; - } -} TSettingKey; - -static const uint32_t cSettingSignature = 0xF5B87A3D; -static const uint16_t cSettingNodeSignature = 0xBA12; - -/** - \brief The data of a setting - - A setting's data is variable length. The data is a TSetting-structure followed by variable length data. - - fixed data - - SettingName (ASCII) - - maybe blob data -**/ -typedef struct TSetting { - TDBTEntityHandle Entity; /// Settings' Entity - uint32_t Flags; /// flags - uint16_t Type; /// setting type - uint16_t NameLength; /// settingname length - union { - union { - bool Bool; - int8_t Char; uint8_t Byte; - int16_t Short; uint16_t Word; - uint32_t Int; uint32_t DWord; - int64_t Int64; uint64_t QWord; - float Float; - double Double; - } Value; /// if type is fixed length, the data is stored right here - - struct { - uint32_t BlobLength; /// if type is variable length this describes the length of the data in bytes - uint32_t AllocSize; /// this is the allocated space for the blob ALWAYS in byte! this prevents us to realloc it too often - }; - }; - uint8_t Reserved[8]; - // settingname with terminating NULL - // blob -} TSetting; - -#pragma pack(pop) - -/** - \brief Manages the Settings in the Database -**/ -class CSettingsTree : public CFileBTree -{ -protected: - TDBTEntityHandle m_Entity; - CSettings & m_Owner; -public: - CSettingsTree(CSettings & Owner, CBlockManager & BlockManager, TNodeRef RootNode, TDBTEntityHandle Entity) - : CFileBTree(BlockManager, RootNode, cSettingNodeSignature), - m_Owner(Owner), - m_Entity(Entity) - { - - }; - ~CSettingsTree() - { - - }; - - TDBTEntityHandle Entity() - { - return m_Entity; - }; - void Entity(TDBTEntityHandle NewEntity) - { - m_Entity = NewEntity; - }; - - TDBTSettingHandle _FindSetting(const uint32_t Hash, const char * Name, const uint32_t Length); - bool _DeleteSetting(const uint32_t Hash, const TDBTSettingHandle hSetting); - bool _AddSetting(const uint32_t Hash, const TDBTSettingHandle hSetting); -}; - - -/** - \brief Manages all Settings and provides access to them -**/ -class CSettings : public sigslot::has_slots<> -{ -public: - typedef sigslot::signal2 TOnRootChanged; - - static const uint32_t cSettingsFileFlag = 0x00000001; - - CSettings( - CBlockManager & BlockManagerSet, - CBlockManager & BlockManagerPri, - CSettingsTree::TNodeRef SettingsRoot, - CEntities & Entities - ); - virtual ~CSettings(); - - - TOnRootChanged & sigRootChanged() - { - return m_sigRootChanged; - }; - - bool _ReadSettingName(CBlockManager & BlockManager, TDBTSettingHandle Setting, uint16_t & NameLength, char *& NameBuf); - void _EnsureModuleExists(char * Module); - - // compatibility: - typedef int (*DBMODULEENUMPROC)(const char *szModuleName,DWORD ofsModuleName,LPARAM lParam); - - int CompEnumModules(DBMODULEENUMPROC CallBack, LPARAM lParam); - // services: - TDBTSettingHandle FindSetting(TDBTSettingDescriptor & Descriptor); - unsigned int DeleteSetting(TDBTSettingDescriptor & Descriptor); - unsigned int DeleteSetting(TDBTSettingHandle hSetting); - TDBTSettingHandle WriteSetting(TDBTSetting & Setting); - TDBTSettingHandle WriteSetting(TDBTSetting & Setting, TDBTSettingHandle hSetting); - unsigned int ReadSetting(TDBTSetting & Setting); - unsigned int ReadSetting(TDBTSetting & Setting, TDBTSettingHandle hSetting); - - - TDBTSettingIterationHandle IterationInit(TDBTSettingIterFilter & Filter); - TDBTSettingHandle IterationNext(TDBTSettingIterationHandle Iteration); - unsigned int IterationClose(TDBTSettingIterationHandle Iteration); - - -private: - - typedef lockfree::hash_map TSettingsTreeMap; - - typedef CIterationHeap TSettingsHeap; - - CBlockManager & m_BlockManagerSet; - CBlockManager & m_BlockManagerPri; - - CEntities & m_Entities; - - TSettingsTreeMap m_SettingsMap; - - typedef struct TSettingIterationResult { - TDBTSettingHandle Handle; - TDBTEntityHandle Entity; - char * Name; - uint16_t NameLen; - } TSettingIterationResult; - - typedef struct TSettingIteration { - TDBTSettingIterFilter Filter; - uint16_t FilterNameStartLength; - TSettingsHeap * Heap; - std::queue * Frame; - bool LockSetting; - bool LockPrivate; - } TSettingIteration, *PSettingIteration; - - TOnRootChanged m_sigRootChanged; - void onRootChanged(void* SettingsTree, CSettingsTree::TNodeRef NewRoot); - - void onDeleteSettingCallback(void * Tree, const TSettingKey & Key, uint32_t Param); - void onDeleteSettings(CEntities * Entities, TDBTEntityHandle hEntity); - void onMergeSettingCallback(void * Tree, const TSettingKey & Key, uint32_t Param); - void onMergeSettings(CEntities * Entities, TDBTEntityHandle Source, TDBTEntityHandle Dest); - - CSettingsTree * getSettingsTree(TDBTEntityHandle hEntity); - typedef lockfree::hash_multimap TModulesMap; - - TModulesMap m_Modules; - - void _LoadModules(); - -}; diff --git a/plugins/Dbx_tree/TLS.h b/plugins/Dbx_tree/TLS.h deleted file mode 100644 index d309090a34..0000000000 --- a/plugins/Dbx_tree/TLS.h +++ /dev/null @@ -1,161 +0,0 @@ -/* - -dbx_tree: tree database driver for Miranda IM - -Copyright 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. - -*/ - -#pragma once - -#include "lockfree_hashmap.h" - -template -class CThreadLocalStorage -{ - private: - typedef struct TListElem - { - TListElem * Next; - TAdministrator * Admin; - TData Data; - TListElem(TListElem * ANext, TAdministrator * AAdmin, const TData & AData) - : Next(ANext), Admin(AAdmin), Data(AData) - { }; - - } TListElem, *PListElem; - static __declspec(thread) PListElem m_Head; - - static inline uint32_t DummyHash(const void * Data, uint32_t Length) - { - return *reinterpret_cast(Data); - } - - lockfree::hash_map * m_LockfreeList; - typedef typename lockfree::hash_map::iterator TThreadStorage; - - public: - CThreadLocalStorage(); - ~CThreadLocalStorage(); - - TData & Open(TAdministrator * Admin, const TData & Default); - TData * Find(TAdministrator * Admin); - void Remove(TAdministrator * Admin); -}; - -const bool _CanUseTLS = ((LOBYTE(LOWORD(GetVersion()))) >= 6); - -template -typename CThreadLocalStorage::PListElem CThreadLocalStorage::m_Head = NULL; - - -template -CThreadLocalStorage::CThreadLocalStorage() -{ - m_LockfreeList = NULL; - if (!_CanUseTLS) - m_LockfreeList = new lockfree::hash_map(); -} -template -CThreadLocalStorage::~CThreadLocalStorage() -{ - if (m_LockfreeList) - delete m_LockfreeList; -} - - -template -typename TData & CThreadLocalStorage::Open(typename TAdministrator * Admin, const TData & Default) -{ - if (_CanUseTLS) - { - PListElem * last = &m_Head; - PListElem i = m_Head; - while (i && (i->Admin != Admin)) - { - last = &i->Next; - i = i->Next; - } - - if (i) - { - *last = i->Next; - i->Next = m_Head; - m_Head = i; - } else { - m_Head = new TListElem(m_Head, Admin, Default); - } - return m_Head->Data; - } else { - TThreadStorage & res = m_LockfreeList->insert(std::make_pair(GetCurrentThreadId(), Default)).first; - return res->second; - } -} - -template -typename TData * CThreadLocalStorage::Find(typename TAdministrator * Admin) -{ - if (_CanUseTLS) - { - PListElem * last = &m_Head; - PListElem i = m_Head; - while (i && (i->Admin != Admin)) - { - last = &i->Next; - i = i->Next; - } - - if (i) - { - *last = i->Next; - i->Next = m_Head; - m_Head = i; - } else { - return NULL; - } - return &m_Head->Data; - } else { - TThreadStorage & res = m_LockfreeList->find(GetCurrentThreadId()); - if (res != m_LockfreeList->end()) - return &res->second; - else - return NULL; - } -} - -template -void CThreadLocalStorage::Remove(typename TAdministrator * Admin) -{ - if (_CanUseTLS) - { - PListElem * last = &m_Head; - PListElem i = m_Head; - while (i && (i->Admin != Admin)) - { - last = &i->Next; - i = i->Next; - } - - if (i) - { - *last = i->Next; - delete i; - } - } else { - m_LockfreeList->erase(GetCurrentThreadId()); - } -} diff --git a/plugins/Dbx_tree/Thread.cpp b/plugins/Dbx_tree/Thread.cpp deleted file mode 100644 index bdb01f18aa..0000000000 --- a/plugins/Dbx_tree/Thread.cpp +++ /dev/null @@ -1,114 +0,0 @@ -/* - -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 "Thread.h" -#include "intrinsics.h" - -unsigned int __stdcall ThreadDistributor(void* Param) -{ - CThread * thread = static_cast(Param); - DWORD result = thread->Wrapper(); - _endthreadex(result); - return result; // to make the compiler happy -} - -CThread::CThread(bool CreateSuspended) -{ - m_Handle = NULL; - m_Terminated = 0; - m_FreeOnTerminate = false; - m_Finished = false; - m_Suspended = CreateSuspended; - m_ReturnValue = 0; - unsigned int flags = 0; - if (CreateSuspended) - flags = CREATE_SUSPENDED; - - m_Handle = reinterpret_cast (_beginthreadex(NULL, 0, &ThreadDistributor, this, flags, &m_ThreadID)); -} -CThread::~CThread() -{ - if (!m_Finished && !m_Suspended) - { - Terminate(); - WaitFor(); - } - if (m_Handle) - CloseHandle(m_Handle); -} -DWORD CThread::Wrapper() -{ - Execute(); - - bool dofree = FreeOnTerminate(); - DWORD result = ReturnValue(); - m_Finished = true; - - m_sigTerminate(this); - if (dofree) - delete this; - - return result; -} - -void CThread::Resume() -{ - if (ResumeThread(m_Handle) == 1) - XCHG_32(m_Suspended, 0); -} -void CThread::Suspend() -{ - SuspendThread(m_Handle); - XCHG_32(m_Suspended, 1); -} -void CThread::Terminate() -{ - XCHG_32(m_Terminated, 1); -} -DWORD CThread::WaitFor() -{ - HANDLE tmp = m_Handle; - DWORD result = WAIT_FAILED; - - if (WaitForSingleObject(m_Handle, INFINITE) != WAIT_FAILED) - GetExitCodeThread(tmp, &result); - - return result; -} - -void CThread::FreeOnTerminate(bool Terminate) -{ - XCHG_32(m_FreeOnTerminate, Terminate); -} -void CThread::ReturnValue(DWORD Value) -{ - XCHG_32(m_ReturnValue, Value); -} - -void CThread::Priority(TPriority NewPriority) -{ - SetThreadPriority(m_Handle, NewPriority); -} -CThread::TPriority CThread::Priority() -{ - return static_cast (GetThreadPriority(m_Handle) & 0xffff); -} diff --git a/plugins/Dbx_tree/Thread.h b/plugins/Dbx_tree/Thread.h deleted file mode 100644 index 09b0b6c016..0000000000 --- a/plugins/Dbx_tree/Thread.h +++ /dev/null @@ -1,77 +0,0 @@ -/* - -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. - -*/ - -#pragma once - -#include -#include -#include "sigslot.h" -#include "stdint.h" - -class CThread -{ -private: - uint32_t volatile m_Terminated; - uint32_t volatile m_FreeOnTerminate; - uint32_t volatile m_Finished; - uint32_t volatile m_Suspended; - uint32_t volatile m_ReturnValue; -protected: - HANDLE m_Handle; - unsigned int m_ThreadID; - - void ReturnValue(DWORD Value); - virtual void Execute() = 0; -public: - CThread(bool CreateSuspended); - virtual ~CThread(); - - DWORD Wrapper(); - - void Resume(); - void Suspend(); - void Terminate(); - DWORD WaitFor(); - - bool Suspended() {return m_Suspended != 0;}; - bool Terminated() {return m_Terminated != 0;}; - bool FreeOnTerminate() {return m_FreeOnTerminate != 0;}; - void FreeOnTerminate(bool Terminate); - DWORD ReturnValue() {return m_ReturnValue;}; - - typedef enum TPriority { - tpIdle = THREAD_PRIORITY_IDLE, - tpLowest = THREAD_PRIORITY_LOWEST, - tpLower = THREAD_PRIORITY_BELOW_NORMAL, - tpNormal = THREAD_PRIORITY_NORMAL, - tpHigher = THREAD_PRIORITY_ABOVE_NORMAL, - tpHighest = THREAD_PRIORITY_HIGHEST, - tpRealTime = THREAD_PRIORITY_TIME_CRITICAL - } TPriority; - - void Priority(TPriority NewPriority); - TPriority Priority(); - - typedef sigslot::signal1 TOnTerminate; - TOnTerminate m_sigTerminate; - TOnTerminate & sigTerminate() {return m_sigTerminate;}; -}; diff --git a/plugins/Dbx_tree/dbConfig.rc b/plugins/Dbx_tree/dbConfig.rc deleted file mode 100644 index 1dff63b228..0000000000 --- a/plugins/Dbx_tree/dbConfig.rc +++ /dev/null @@ -1,113 +0,0 @@ -// Microsoft Visual C++ generated resource script. -// -#include "dbConfig_rc.h" - -#define APSTUDIO_READONLY_SYMBOLS -///////////////////////////////////////////////////////////////////////////// -// -// Generated from the TEXTINCLUDE 2 resource. -// -#include "afxres.h" - -///////////////////////////////////////////////////////////////////////////// -#undef APSTUDIO_READONLY_SYMBOLS - -///////////////////////////////////////////////////////////////////////////// -// Neutral resources - -#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_NEU) -#ifdef _WIN32 -LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL -#pragma code_page(1252) -#endif //_WIN32 - -///////////////////////////////////////////////////////////////////////////// -// -// Dialog -// - -IDD_DIALOGBAR DIALOGEX 0, 0, 429, 290 -STYLE DS_LOCALEDIT | DS_SETFONT | DS_MODALFRAME | DS_SETFOREGROUND | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU -EXSTYLE WS_EX_APPWINDOW -CAPTION "dbxTree Profile Wizard" -FONT 8, "MS Shell Dlg", 400, 0, 0x0 -BEGIN - PUSHBUTTON "Cancel",IDC_BUTTON1,316,267,54,16 - PUSHBUTTON "Next >",IDC_BUTTON2,254,267,54,16 - PUSHBUTTON "< Prev",IDC_BUTTON3,192,267,54,16 - CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,6,258,416,1 - LISTBOX IDC_LIST1,6,6,116,252,LBS_SORT | LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP -END - - -///////////////////////////////////////////////////////////////////////////// -// -// DESIGNINFO -// - -#ifdef APSTUDIO_INVOKED -GUIDELINES DESIGNINFO -BEGIN - IDD_DIALOGBAR, DIALOG - BEGIN - LEFTMARGIN, 6 - RIGHTMARGIN, 422 - TOPMARGIN, 6 - BOTTOMMARGIN, 284 - END -END -#endif // APSTUDIO_INVOKED - -#endif // Neutral resources -///////////////////////////////////////////////////////////////////////////// - - -///////////////////////////////////////////////////////////////////////////// -// German (Germany) resources - -#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_DEU) -#ifdef _WIN32 -LANGUAGE LANG_GERMAN, SUBLANG_GERMAN -#pragma code_page(1252) -#endif //_WIN32 - -#ifdef APSTUDIO_INVOKED -///////////////////////////////////////////////////////////////////////////// -// -// TEXTINCLUDE -// - -1 TEXTINCLUDE -BEGIN - "dbConfig_rc.h\0" -END - -2 TEXTINCLUDE -BEGIN - "#include ""afxres.h""\r\n" - "\0" -END - -3 TEXTINCLUDE -BEGIN - "\r\n" - "\0" -END - -#endif // APSTUDIO_INVOKED - -#endif // German (Germany) resources -///////////////////////////////////////////////////////////////////////////// - - - -#ifndef APSTUDIO_INVOKED -///////////////////////////////////////////////////////////////////////////// -// -// Generated from the TEXTINCLUDE 3 resource. -// - - -///////////////////////////////////////////////////////////////////////////// -#endif // not APSTUDIO_INVOKED - diff --git a/plugins/Dbx_tree/dbConfig_rc.h b/plugins/Dbx_tree/dbConfig_rc.h deleted file mode 100644 index 099067d3ec..0000000000 --- a/plugins/Dbx_tree/dbConfig_rc.h +++ /dev/null @@ -1,20 +0,0 @@ -//{{NO_DEPENDENCIES}} -// Microsoft Visual C++ generated include file. -// Used by dbConfig.rc -// -#define IDD_DIALOGBAR 103 -#define IDC_BUTTON1 1001 -#define IDC_BUTTON2 1002 -#define IDC_BUTTON3 1003 -#define IDC_LIST1 1004 - -// Next default values for new objects -// -#ifdef APSTUDIO_INVOKED -#ifndef APSTUDIO_READONLY_SYMBOLS -#define _APS_NEXT_RESOURCE_VALUE 101 -#define _APS_NEXT_COMMAND_VALUE 40001 -#define _APS_NEXT_CONTROL_VALUE 1005 -#define _APS_NEXT_SYMED_VALUE 101 -#endif -#endif diff --git a/plugins/Dbx_tree/dbVersion.rc b/plugins/Dbx_tree/dbVersion.rc deleted file mode 100644 index 170da6f794..0000000000 --- a/plugins/Dbx_tree/dbVersion.rc +++ /dev/null @@ -1,105 +0,0 @@ -// Microsoft Visual C++ generated resource script. -// -#include "dbVersion_rc.h" -#define INTERFACE_VERSION_ONLY -#include "Interface.h" -#undef INTERFACE_VERSION_ONLY - -#define APSTUDIO_READONLY_SYMBOLS -///////////////////////////////////////////////////////////////////////////// -// -// Generated from the TEXTINCLUDE 2 resource. -// -#include "afxres.h" - -///////////////////////////////////////////////////////////////////////////// -#undef APSTUDIO_READONLY_SYMBOLS - -///////////////////////////////////////////////////////////////////////////// -// German (Germany) resources - -#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_DEU) -#ifdef _WIN32 -LANGUAGE LANG_GERMAN, SUBLANG_GERMAN -#pragma code_page(1252) -#endif //_WIN32 - -#ifdef APSTUDIO_INVOKED -///////////////////////////////////////////////////////////////////////////// -// -// TEXTINCLUDE -// - -1 TEXTINCLUDE -BEGIN - "dbVersion_rc.h\0" -END - -2 TEXTINCLUDE -BEGIN - "#include ""afxres.h""\r\n" - "\0" -END - -3 TEXTINCLUDE -BEGIN - "\r\n" - "\0" -END - -#endif // APSTUDIO_INVOKED - - -///////////////////////////////////////////////////////////////////////////// -// -// Version -// - -VS_VERSION_INFO VERSIONINFO - FILEVERSION gResVersion - PRODUCTVERSION gResVersion - FILEFLAGSMASK 0x17L -#ifdef _DEBUG - FILEFLAGS 0x3L -#else - FILEFLAGS 0x2L -#endif - FILEOS 0x4L - FILETYPE 0x2L - FILESUBTYPE 0x0L -BEGIN - BLOCK "StringFileInfo" - BEGIN - BLOCK "000004b0" - BEGIN - VALUE "CompanyName", gAutor - VALUE "FileDescription", gDescription - VALUE "FileVersion", gResVersionString - VALUE "InternalName", gInternalName - VALUE "LegalCopyright", gCopyright - VALUE "OriginalFilename", "dbx_tree.dll" - VALUE "ProductName", gInternalNameLong - VALUE "ProductVersion", gResVersionString - END - END - BLOCK "VarFileInfo" - BEGIN - VALUE "Translation", 0x0, 1200 - END -END - -#endif // German (Germany) resources -///////////////////////////////////////////////////////////////////////////// - - - -#ifndef APSTUDIO_INVOKED -///////////////////////////////////////////////////////////////////////////// -// -// Generated from the TEXTINCLUDE 3 resource. -// - - -///////////////////////////////////////////////////////////////////////////// -#endif // not APSTUDIO_INVOKED - diff --git a/plugins/Dbx_tree/dbVersion_rc.h b/plugins/Dbx_tree/dbVersion_rc.h deleted file mode 100644 index 24a3ae4cf4..0000000000 --- a/plugins/Dbx_tree/dbVersion_rc.h +++ /dev/null @@ -1,14 +0,0 @@ -//{{NO_DEPENDENCIES}} -// Microsoft Visual C++ generated include file. -// Used by dbVersion.rc - -// Next default values for new objects -// -#ifdef APSTUDIO_INVOKED -#ifndef APSTUDIO_READONLY_SYMBOLS -#define _APS_NEXT_RESOURCE_VALUE 101 -#define _APS_NEXT_COMMAND_VALUE 40001 -#define _APS_NEXT_CONTROL_VALUE 1001 -#define _APS_NEXT_SYMED_VALUE 101 -#endif -#endif diff --git a/plugins/Dbx_tree/dbx_tree-translation.txt b/plugins/Dbx_tree/dbx_tree-translation.txt deleted file mode 100644 index 1da8e58342..0000000000 --- a/plugins/Dbx_tree/dbx_tree-translation.txt +++ /dev/null @@ -1,8 +0,0 @@ -; Common strings that belong to many files -;[] - -; ../../plugins/Dbx_tree/dbConfig.rc -;[< Prev] -;[Cancel] -;[Next >] -;[dbxTree Profile Wizard] diff --git a/plugins/Dbx_tree/dbx_tree_10.vcxproj b/plugins/Dbx_tree/dbx_tree_10.vcxproj index 7265c5a2b2..c7c88820e3 100644 --- a/plugins/Dbx_tree/dbx_tree_10.vcxproj +++ b/plugins/Dbx_tree/dbx_tree_10.vcxproj @@ -176,69 +176,64 @@ - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + - - - - - \ No newline at end of file diff --git a/plugins/Dbx_tree/dbx_tree_10.vcxproj.filters b/plugins/Dbx_tree/dbx_tree_10.vcxproj.filters index 606b567ede..1c51fc77e6 100644 --- a/plugins/Dbx_tree/dbx_tree_10.vcxproj.filters +++ b/plugins/Dbx_tree/dbx_tree_10.vcxproj.filters @@ -37,164 +37,164 @@ - + Resource - + Resource - + Resource - + Resource - + Database\HeaderFiles - + Database\HeaderFiles - + Database\HeaderFiles - + Database\HeaderFiles - + Database\HeaderFiles - + Database\HeaderFiles - + Database\FileAccess\Encryption - + Database\FileAccess\Encryption - + Database\FileAccess\Encryption\SHA256 - + Database\FileAccess\HeaderFiles - + Database\FileAccess\HeaderFiles - + Database\FileAccess\HeaderFiles - + Database\FileAccess\HeaderFiles - + Interface\HeaderFiles - + Interface\HeaderFiles - + Interface\HeaderFiles - + Interface\HeaderFiles - + Utils\HeaderFiles - + Utils\HeaderFiles - + Utils\HeaderFiles - + Utils\HeaderFiles - + Utils\HeaderFiles - + Utils\HeaderFiles - + Utils\HeaderFiles - + Utils\HeaderFiles - + Utils\HeaderFiles - + Utils\HeaderFiles - + Utils\HeaderFiles - + Utils\HeaderFiles - + Utils\HeaderFiles - + Database - + Database - + Database - + Database - + Database\FileAccess - + Database\FileAccess - + Database\FileAccess - + Database\FileAccess - + Database\FileAccess\Encryption - + Database\FileAccess\Encryption\SHA256 - + Interface - + Interface - + Interface - + Interface - + Utils - + Utils - + Utils - + Utils diff --git a/plugins/Dbx_tree/docs/Filestructure.txt b/plugins/Dbx_tree/docs/Filestructure.txt new file mode 100644 index 0000000000..6128b5f993 Binary files /dev/null and b/plugins/Dbx_tree/docs/Filestructure.txt differ diff --git a/plugins/Dbx_tree/docs/dbx_tree-translation.txt b/plugins/Dbx_tree/docs/dbx_tree-translation.txt new file mode 100644 index 0000000000..1da8e58342 --- /dev/null +++ b/plugins/Dbx_tree/docs/dbx_tree-translation.txt @@ -0,0 +1,8 @@ +; Common strings that belong to many files +;[] + +; ../../plugins/Dbx_tree/dbConfig.rc +;[< Prev] +;[Cancel] +;[Next >] +;[dbxTree Profile Wizard] diff --git a/plugins/Dbx_tree/encryption/ARC4.cpp b/plugins/Dbx_tree/encryption/ARC4.cpp deleted file mode 100644 index 7f3780e6a2..0000000000 --- a/plugins/Dbx_tree/encryption/ARC4.cpp +++ /dev/null @@ -1,129 +0,0 @@ -/* - -dbx_tree: tree database driver for Miranda IM - -Copyright 2007-2008 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 "ARC4.h" -#include - -const wchar_t * ARC4::Name() -{ - return cName; -} -const wchar_t * ARC4::Description() -{ - return cDescription; -} -const uint32_t ARC4::BlockSizeBytes() -{ - return cBlockSizeBytes; -} -const bool ARC4::IsStreamCipher() -{ - return cIsStreamCipher; -} - -ARC4::ARC4() -{ - -} -ARC4::~ARC4() -{ - -} - -CCipher::TCipherInterface* ARC4::Create() -{ - return (new ARC4())->m_Interface; -} - -void ARC4::SetKey(void* Key, uint32_t KeyLength) -{ - uint8_t swapbyte; - uint8_t index1; - uint8_t index2; - unsigned int i; - - uint8_t * k = (uint8_t *) Key; - - for (i = 0; i < 256; ++i) - State[i] = i; - - x = 0; - y = 0; - index1 = 0; - index2 = 0; - for (i = 0; i < 256; ++i) - { - index2 = (k[index1] + State[i] + index2) & 0xff; - swapbyte = State[i]; - State[i] = State[index2]; - State[index2] = swapbyte; - index1 = (index1 + 1) % KeyLength; - } - - for (i = 0; i < 3742; ++i) - Stream(); - - Backx = x; - Backy = y; - memcpy(BackState, State, sizeof(State)); -} - -inline uint8_t ARC4::Stream() -{ - uint8_t swapbyte; - - x = (x + 1) & 0xff; - y = (State[x] + y) & 0xff; - - swapbyte = State[x]; - State[x] = State[y]; - State[y] = swapbyte; - - return State[ (State[x] + State[y]) & 0xff ]; -} - -void ARC4::Encrypt(void* Data, uint32_t Size, uint32_t Nonce, uint32_t StartByte) -{ - uint8_t * dat = (uint8_t *) Data; - x = Backx; - y = Backy; - memcpy(State, BackState, sizeof(State)); - - for (unsigned int i = (Nonce + (Nonce >> 8) + (Nonce >> 16) + (Nonce >> 24)) & 0x1ff; i > 0; --i) - Stream(); - - while (Size > 0) - { - (*dat) = (*dat) ^ Stream(); - --Size; - ++dat; - } -} -void ARC4::Decrypt(void* Data, uint32_t Size, uint32_t Nonce, uint32_t StartByte) -{ - Encrypt(Data, Size, Nonce, StartByte); -} - -extern "C" __declspec(dllexport) const TCipherInfo* CipherInfo(void * Reserved) -{ - return &ARC4::cCipherInfo; -} diff --git a/plugins/Dbx_tree/encryption/ARC4.h b/plugins/Dbx_tree/encryption/ARC4.h deleted file mode 100644 index 48fdc35312..0000000000 --- a/plugins/Dbx_tree/encryption/ARC4.h +++ /dev/null @@ -1,65 +0,0 @@ -/* - -dbx_tree: tree database driver for Miranda IM - -Copyright 2007-2008 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. - -*/ - -#pragma once - -#include "Cipher.h" - -class ARC4 : public CCipher -{ -private: - uint8_t x; - uint8_t y; - uint8_t State[256]; - - uint8_t Backx; - uint8_t Backy; - uint8_t BackState[256]; - - uint8_t Stream(); - - static const wchar_t* cName; - static const wchar_t* cDescription; - static const uint32_t cBlockSizeBytes = 1; - static const bool cIsStreamCipher = true; - -public: - const wchar_t * __cdecl Name(); - const wchar_t * __cdecl Description(); - const uint32_t __cdecl BlockSizeBytes(); - const bool __cdecl IsStreamCipher(); - - static const TCipherInfo cCipherInfo; - - ARC4(); - ~ARC4(); - static CCipher::TCipherInterface* __cdecl Create(); - - void __cdecl SetKey(void* Key, uint32_t KeyLength); - void __cdecl Encrypt(void* Data, uint32_t Size, uint32_t Nonce, uint32_t StartByte); - void __cdecl Decrypt(void* Data, uint32_t Size, uint32_t Nonce, uint32_t StartByte); - -}; - -const wchar_t* ARC4::cName = L"ARC4"; -const wchar_t* ARC4::cDescription = L"Streamcipher - 8bit step, fast, Ron Rivest 1987"; -const TCipherInfo ARC4::cCipherInfo = {sizeof(TCipherInfo), 'ARC4', cName, cDescription, &ARC4::Create}; diff --git a/plugins/Dbx_tree/encryption/ARC4.vcxproj b/plugins/Dbx_tree/encryption/ARC4.vcxproj deleted file mode 100644 index e8692710a2..0000000000 --- a/plugins/Dbx_tree/encryption/ARC4.vcxproj +++ /dev/null @@ -1,160 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - Dbx_tree_ARC4 - {F60935E3-8F27-46E2-8598-013E7D4C90E7} - - - - DynamicLibrary - Unicode - - - DynamicLibrary - Unicode - - - DynamicLibrary - Unicode - true - - - DynamicLibrary - Unicode - true - - - - - - - - - - <_ProjectFileVersion>10.0.20506.1 - $(SolutionDir)$(Configuration)\Plugins\Encryption\ - $(SolutionDir)$(Configuration)64\Plugins\Encryption\ - $(SolutionDir)$(Configuration)\Obj\$(ProjectName)\ - $(SolutionDir)$(Configuration)64\Obj\$(ProjectName)\ - $(SolutionDir)$(Configuration)\Plugins\Encryption\ - $(SolutionDir)$(Configuration)64\Plugins\Encryption\ - $(SolutionDir)$(Configuration)\Obj\$(ProjectName)\ - $(SolutionDir)$(Configuration)64\Obj\$(ProjectName)\ - true - - - - Disabled - WIN32;_DEBUG;_WINDOWS;_USRDLL;DBX_TREE_ENCRYPTION_EXPORTS;%(PreprocessorDefinitions) - true - EnableFastChecks - MultiThreadedDebugDLL - Level3 - EditAndContinue - true - true - Fast - - - true - Windows - $(IntDir)$(TargetName).lib - false - $(SolutionDir)\lib - - - - - Disabled - WIN64;_DEBUG;_WINDOWS;_USRDLL;DBX_TREE_ENCRYPTION_EXPORTS;%(PreprocessorDefinitions) - EnableFastChecks - MultiThreadedDebugDLL - Level3 - true - true - true - Fast - - - true - Windows - $(IntDir)$(TargetName).lib - false - $(SolutionDir)\lib - - - - - Full - AnySuitable - Size - WIN32;NDEBUG;_WINDOWS;_USRDLL;DBX_TREE_ENCRYPTION_EXPORTS;%(PreprocessorDefinitions) - true - Level3 - true - true - Fast - - - true - Windows - true - true - $(IntDir)$(TargetName).lib - false - $(SolutionDir)\lib - /PDBALTPATH:%_PDB% - - - - - Full - AnySuitable - Size - WIN64;NDEBUG;_WINDOWS;_USRDLL;DBX_TREE_ENCRYPTION_EXPORTS;%(PreprocessorDefinitions) - true - Level3 - true - true - Fast - - - true - Windows - true - true - $(IntDir)$(TargetName).lib - false - $(SolutionDir)\lib - /PDBALTPATH:%_PDB% - - - - - - - - - - - - - \ No newline at end of file diff --git a/plugins/Dbx_tree/encryption/ARC4.vcxproj.filters b/plugins/Dbx_tree/encryption/ARC4.vcxproj.filters deleted file mode 100644 index 513c5124c8..0000000000 --- a/plugins/Dbx_tree/encryption/ARC4.vcxproj.filters +++ /dev/null @@ -1,30 +0,0 @@ - - - - - {93995380-89BD-4b04-88EB-625FBE52EBFB} - h;hpp;hxx;hm;inl;inc;xsd - - - {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} - rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx - - - - - Header Files - - - Header Files - - - - - Source Files - - - \ No newline at end of file diff --git a/plugins/Dbx_tree/encryption/ARC4/ARC4.vcxproj b/plugins/Dbx_tree/encryption/ARC4/ARC4.vcxproj new file mode 100644 index 0000000000..3fcc596e3a --- /dev/null +++ b/plugins/Dbx_tree/encryption/ARC4/ARC4.vcxproj @@ -0,0 +1,168 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + Dbx_tree_ARC4 + {F60935E3-8F27-46E2-8598-013E7D4C90E7} + + + + DynamicLibrary + Unicode + + + DynamicLibrary + Unicode + + + DynamicLibrary + Unicode + true + + + DynamicLibrary + Unicode + true + + + + + + + + + + <_ProjectFileVersion>10.0.20506.1 + $(SolutionDir)$(Configuration)\Plugins\Encryption\ + $(SolutionDir)$(Configuration)64\Plugins\Encryption\ + $(SolutionDir)$(Configuration)\Obj\$(ProjectName)\ + $(SolutionDir)$(Configuration)64\Obj\$(ProjectName)\ + $(SolutionDir)$(Configuration)\Plugins\Encryption\ + $(SolutionDir)$(Configuration)64\Plugins\Encryption\ + $(SolutionDir)$(Configuration)\Obj\$(ProjectName)\ + $(SolutionDir)$(Configuration)64\Obj\$(ProjectName)\ + true + ARC4 + ARC4 + ARC4 + ARC4 + + + + Disabled + WIN32;_DEBUG;_WINDOWS;_USRDLL;DBX_TREE_ENCRYPTION_EXPORTS;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + Level3 + ..\Common + EditAndContinue + true + true + Fast + + + true + Windows + $(IntDir)$(TargetName).lib + false + $(SolutionDir)\lib + + + + + Disabled + WIN64;_DEBUG;_WINDOWS;_USRDLL;DBX_TREE_ENCRYPTION_EXPORTS;%(PreprocessorDefinitions) + EnableFastChecks + MultiThreadedDebugDLL + Level3 + ..\Common + true + true + true + Fast + + + true + Windows + $(IntDir)$(TargetName).lib + false + $(SolutionDir)\lib + + + + + Full + AnySuitable + Size + WIN32;NDEBUG;_WINDOWS;_USRDLL;DBX_TREE_ENCRYPTION_EXPORTS;%(PreprocessorDefinitions) + true + Level3 + ..\Common + true + true + Fast + + + true + Windows + true + true + $(IntDir)$(TargetName).lib + false + $(SolutionDir)\lib + /PDBALTPATH:%_PDB% + + + + + Full + AnySuitable + Size + WIN64;NDEBUG;_WINDOWS;_USRDLL;DBX_TREE_ENCRYPTION_EXPORTS;%(PreprocessorDefinitions) + true + Level3 + ..\Common + true + true + Fast + + + true + Windows + true + true + $(IntDir)$(TargetName).lib + false + $(SolutionDir)\lib + /PDBALTPATH:%_PDB% + + + + + + + + + + + + + \ No newline at end of file diff --git a/plugins/Dbx_tree/encryption/ARC4/ARC4.vcxproj.filters b/plugins/Dbx_tree/encryption/ARC4/ARC4.vcxproj.filters new file mode 100644 index 0000000000..125c2ecc43 --- /dev/null +++ b/plugins/Dbx_tree/encryption/ARC4/ARC4.vcxproj.filters @@ -0,0 +1,30 @@ + + + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + + + Header Files + + + Header Files + + + + + Source Files + + + \ No newline at end of file diff --git a/plugins/Dbx_tree/encryption/ARC4/src/ARC4.cpp b/plugins/Dbx_tree/encryption/ARC4/src/ARC4.cpp new file mode 100644 index 0000000000..7f3780e6a2 --- /dev/null +++ b/plugins/Dbx_tree/encryption/ARC4/src/ARC4.cpp @@ -0,0 +1,129 @@ +/* + +dbx_tree: tree database driver for Miranda IM + +Copyright 2007-2008 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 "ARC4.h" +#include + +const wchar_t * ARC4::Name() +{ + return cName; +} +const wchar_t * ARC4::Description() +{ + return cDescription; +} +const uint32_t ARC4::BlockSizeBytes() +{ + return cBlockSizeBytes; +} +const bool ARC4::IsStreamCipher() +{ + return cIsStreamCipher; +} + +ARC4::ARC4() +{ + +} +ARC4::~ARC4() +{ + +} + +CCipher::TCipherInterface* ARC4::Create() +{ + return (new ARC4())->m_Interface; +} + +void ARC4::SetKey(void* Key, uint32_t KeyLength) +{ + uint8_t swapbyte; + uint8_t index1; + uint8_t index2; + unsigned int i; + + uint8_t * k = (uint8_t *) Key; + + for (i = 0; i < 256; ++i) + State[i] = i; + + x = 0; + y = 0; + index1 = 0; + index2 = 0; + for (i = 0; i < 256; ++i) + { + index2 = (k[index1] + State[i] + index2) & 0xff; + swapbyte = State[i]; + State[i] = State[index2]; + State[index2] = swapbyte; + index1 = (index1 + 1) % KeyLength; + } + + for (i = 0; i < 3742; ++i) + Stream(); + + Backx = x; + Backy = y; + memcpy(BackState, State, sizeof(State)); +} + +inline uint8_t ARC4::Stream() +{ + uint8_t swapbyte; + + x = (x + 1) & 0xff; + y = (State[x] + y) & 0xff; + + swapbyte = State[x]; + State[x] = State[y]; + State[y] = swapbyte; + + return State[ (State[x] + State[y]) & 0xff ]; +} + +void ARC4::Encrypt(void* Data, uint32_t Size, uint32_t Nonce, uint32_t StartByte) +{ + uint8_t * dat = (uint8_t *) Data; + x = Backx; + y = Backy; + memcpy(State, BackState, sizeof(State)); + + for (unsigned int i = (Nonce + (Nonce >> 8) + (Nonce >> 16) + (Nonce >> 24)) & 0x1ff; i > 0; --i) + Stream(); + + while (Size > 0) + { + (*dat) = (*dat) ^ Stream(); + --Size; + ++dat; + } +} +void ARC4::Decrypt(void* Data, uint32_t Size, uint32_t Nonce, uint32_t StartByte) +{ + Encrypt(Data, Size, Nonce, StartByte); +} + +extern "C" __declspec(dllexport) const TCipherInfo* CipherInfo(void * Reserved) +{ + return &ARC4::cCipherInfo; +} diff --git a/plugins/Dbx_tree/encryption/ARC4/src/ARC4.h b/plugins/Dbx_tree/encryption/ARC4/src/ARC4.h new file mode 100644 index 0000000000..48fdc35312 --- /dev/null +++ b/plugins/Dbx_tree/encryption/ARC4/src/ARC4.h @@ -0,0 +1,65 @@ +/* + +dbx_tree: tree database driver for Miranda IM + +Copyright 2007-2008 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. + +*/ + +#pragma once + +#include "Cipher.h" + +class ARC4 : public CCipher +{ +private: + uint8_t x; + uint8_t y; + uint8_t State[256]; + + uint8_t Backx; + uint8_t Backy; + uint8_t BackState[256]; + + uint8_t Stream(); + + static const wchar_t* cName; + static const wchar_t* cDescription; + static const uint32_t cBlockSizeBytes = 1; + static const bool cIsStreamCipher = true; + +public: + const wchar_t * __cdecl Name(); + const wchar_t * __cdecl Description(); + const uint32_t __cdecl BlockSizeBytes(); + const bool __cdecl IsStreamCipher(); + + static const TCipherInfo cCipherInfo; + + ARC4(); + ~ARC4(); + static CCipher::TCipherInterface* __cdecl Create(); + + void __cdecl SetKey(void* Key, uint32_t KeyLength); + void __cdecl Encrypt(void* Data, uint32_t Size, uint32_t Nonce, uint32_t StartByte); + void __cdecl Decrypt(void* Data, uint32_t Size, uint32_t Nonce, uint32_t StartByte); + +}; + +const wchar_t* ARC4::cName = L"ARC4"; +const wchar_t* ARC4::cDescription = L"Streamcipher - 8bit step, fast, Ron Rivest 1987"; +const TCipherInfo ARC4::cCipherInfo = {sizeof(TCipherInfo), 'ARC4', cName, cDescription, &ARC4::Create}; diff --git a/plugins/Dbx_tree/encryption/CAST128.cpp b/plugins/Dbx_tree/encryption/CAST128.cpp deleted file mode 100644 index 2814a4142b..0000000000 --- a/plugins/Dbx_tree/encryption/CAST128.cpp +++ /dev/null @@ -1,260 +0,0 @@ -/* - -dbx_tree: tree database driver for Miranda IM - -Copyright 2007-2008 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 "CAST128.h" -#include "CAST128.inc" - -const wchar_t * CAST128::Name() -{ - return cName; -} -const wchar_t * CAST128::Description() -{ - return cDescription; -} -const uint32_t CAST128::BlockSizeBytes() -{ - return cBlockSizeBytes; -} -const bool CAST128::IsStreamCipher() -{ - return cIsStreamCipher; -} - -CAST128::CAST128() -{ - -} -CAST128::~CAST128() -{ - -} -CCipher::TCipherInterface* CAST128::Create() -{ - return (new CAST128())->m_Interface; -} - -void CAST128::SetKey(void* Key, uint32_t KeyLength) -{ - uint8_t k128[16] = "Mirandadbx_tree"; - int i = 0; - uint8_t* k = (uint8_t*) Key; - while (KeyLength > 0) - { - k128[i] = k128[i] ^ (*k); - i = (i + 1) % 16; - ++k; - --KeyLength; - } - CreateSubKeys(k128); -} -void CAST128::Encrypt(void* Data, uint32_t Size, uint32_t Nonce, uint32_t StartByte) -{ - for (uint32_t i = 0; i <= Size - BlockSizeBytes(); i += BlockSizeBytes()) - { - EncryptBlock((uint8_t*)Data + i); - StartByte += BlockSizeBytes(); - } -} -void CAST128::Decrypt(void* Data, uint32_t Size, uint32_t Nonce, uint32_t StartByte) -{ - for (uint32_t i = 0; i <= Size - BlockSizeBytes(); i += BlockSizeBytes()) - { - DecryptBlock((uint8_t*)Data + i); - StartByte += BlockSizeBytes(); - } -} - -void CAST128::CreateSubKeys(uint8_t* Key) -{ - union { - uint8_t z[16]; - uint32_t i[4]; - } t; - - uint32_t* k; - k = (uint32_t*) Key; - - t.i[0] = k[0] ^ S5[Key[0xD]] ^ S6[Key[0xF]] ^ S7[Key[0xC]] ^ S8[Key[0xE]] ^ S7[Key[0x8]]; - t.i[1] = k[2] ^ S5[t.z[0x0]] ^ S6[t.z[0x2]] ^ S7[t.z[0x1]] ^ S8[t.z[0x3]] ^ S8[Key[0xA]]; - t.i[2] = k[3] ^ S5[t.z[0x7]] ^ S6[t.z[0x6]] ^ S7[t.z[0x5]] ^ S8[t.z[0x4]] ^ S5[Key[0x9]]; - t.i[3] = k[1] ^ S5[t.z[0xA]] ^ S6[t.z[0x9]] ^ S7[t.z[0xB]] ^ S8[t.z[0x8]] ^ S6[Key[0xB]]; - - Km[0x0] = S5[t.z[0x8]] ^ S6[t.z[0x9]] ^ S7[t.z[0x7]] ^ S8[t.z[0x6]] ^ S5[t.z[0x2]]; - Km[0x1] = S5[t.z[0xA]] ^ S6[t.z[0xB]] ^ S7[t.z[0x5]] ^ S8[t.z[0x4]] ^ S6[t.z[0x6]]; - Km[0x2] = S5[t.z[0xC]] ^ S6[t.z[0xD]] ^ S7[t.z[0x3]] ^ S8[t.z[0x2]] ^ S7[t.z[0x9]]; - Km[0x3] = S5[t.z[0xE]] ^ S6[t.z[0xF]] ^ S7[t.z[0x1]] ^ S8[t.z[0x0]] ^ S8[t.z[0xC]]; - - k[0] = t.i[2] ^ S5[t.z[0x5]] ^ S6[t.z[0x7]] ^ S7[t.z[0x4]] ^ S8[t.z[0x6]] ^ S7[t.z[0x0]]; - k[1] = t.i[0] ^ S5[Key[0x0]] ^ S6[Key[0x2]] ^ S7[Key[0x1]] ^ S8[Key[0x3]] ^ S8[t.z[0x2]]; - k[2] = t.i[1] ^ S5[Key[0x7]] ^ S6[Key[0x6]] ^ S7[Key[0x5]] ^ S8[Key[0x4]] ^ S5[t.z[0x1]]; - k[3] = t.i[3] ^ S5[Key[0xA]] ^ S6[Key[0x9]] ^ S7[Key[0xB]] ^ S8[Key[0x8]] ^ S6[t.z[0x3]]; - - Km[0x4] = S5[Key[0x3]] ^ S6[Key[0x2]] ^ S7[Key[0xC]] ^ S8[Key[0xD]] ^ S5[Key[0x8]]; - Km[0x5] = S5[Key[0x1]] ^ S6[Key[0x0]] ^ S7[Key[0xE]] ^ S8[Key[0xF]] ^ S6[Key[0xD]]; - Km[0x6] = S5[Key[0x7]] ^ S6[Key[0x6]] ^ S7[Key[0x8]] ^ S8[Key[0x9]] ^ S7[Key[0x3]]; - Km[0x7] = S5[Key[0x5]] ^ S6[Key[0x4]] ^ S7[Key[0xA]] ^ S8[Key[0xB]] ^ S8[Key[0x7]]; - - t.i[0] = k[0] ^ S5[Key[0xD]] ^ S6[Key[0xF]] ^ S7[Key[0xC]] ^ S8[Key[0xE]] ^ S7[Key[0x8]]; - t.i[1] = k[2] ^ S5[t.z[0x0]] ^ S6[t.z[0x2]] ^ S7[t.z[0x1]] ^ S8[t.z[0x3]] ^ S8[Key[0xA]]; - t.i[2] = k[3] ^ S5[t.z[0x7]] ^ S6[t.z[0x6]] ^ S7[t.z[0x5]] ^ S8[t.z[0x4]] ^ S5[Key[0x9]]; - t.i[3] = k[1] ^ S5[t.z[0xA]] ^ S6[t.z[0x9]] ^ S7[t.z[0xB]] ^ S8[t.z[0x8]] ^ S6[Key[0xB]]; - - Km[0x8] = S5[t.z[0x3]] ^ S6[t.z[0x2]] ^ S7[t.z[0xC]] ^ S8[t.z[0xD]] ^ S5[t.z[0x9]]; - Km[0x9] = S5[t.z[0x1]] ^ S6[t.z[0x0]] ^ S7[t.z[0xE]] ^ S8[t.z[0xF]] ^ S6[t.z[0xC]]; - Km[0xa] = S5[t.z[0x7]] ^ S6[t.z[0x6]] ^ S7[t.z[0x8]] ^ S8[t.z[0x9]] ^ S7[t.z[0x2]]; - Km[0xb] = S5[t.z[0x5]] ^ S6[t.z[0x4]] ^ S7[t.z[0xA]] ^ S8[t.z[0xB]] ^ S8[t.z[0x6]]; - - k[0] = t.i[2] ^ S5[t.z[0x5]] ^ S6[t.z[0x7]] ^ S7[t.z[0x4]] ^ S8[t.z[0x6]] ^ S7[t.z[0x0]]; - k[1] = t.i[0] ^ S5[Key[0x0]] ^ S6[Key[0x2]] ^ S7[Key[0x1]] ^ S8[Key[0x3]] ^ S8[t.z[0x2]]; - k[2] = t.i[1] ^ S5[Key[0x7]] ^ S6[Key[0x6]] ^ S7[Key[0x5]] ^ S8[Key[0x4]] ^ S5[t.z[0x1]]; - k[3] = t.i[3] ^ S5[Key[0xA]] ^ S6[Key[0x9]] ^ S7[Key[0xB]] ^ S8[Key[0x8]] ^ S6[t.z[0x3]]; - - Km[0xc] = S5[Key[0x8]] ^ S6[Key[0x9]] ^ S7[Key[0x7]] ^ S8[Key[0x6]] ^ S5[Key[0x3]]; - Km[0xd] = S5[Key[0xA]] ^ S6[Key[0xB]] ^ S7[Key[0x5]] ^ S8[Key[0x4]] ^ S6[Key[0x7]]; - Km[0xe] = S5[Key[0xC]] ^ S6[Key[0xD]] ^ S7[Key[0x3]] ^ S8[Key[0x2]] ^ S7[Key[0x8]]; - Km[0xf] = S5[Key[0xE]] ^ S6[Key[0xF]] ^ S7[Key[0x1]] ^ S8[Key[0x0]] ^ S8[Key[0xD]]; - - - - t.i[0] = k[0] ^ S5[Key[0xD]] ^ S6[Key[0xF]] ^ S7[Key[0xC]] ^ S8[Key[0xE]] ^ S7[Key[0x8]]; - t.i[1] = k[2] ^ S5[t.z[0x0]] ^ S6[t.z[0x2]] ^ S7[t.z[0x1]] ^ S8[t.z[0x3]] ^ S8[Key[0xA]]; - t.i[2] = k[3] ^ S5[t.z[0x7]] ^ S6[t.z[0x6]] ^ S7[t.z[0x5]] ^ S8[t.z[0x4]] ^ S5[Key[0x9]]; - t.i[3] = k[1] ^ S5[t.z[0xA]] ^ S6[t.z[0x9]] ^ S7[t.z[0xB]] ^ S8[t.z[0x8]] ^ S6[Key[0xB]]; - - Kr[0x0] = S5[t.z[0x8]] ^ S6[t.z[0x9]] ^ S7[t.z[0x7]] ^ S8[t.z[0x6]] ^ S5[t.z[0x2]]; - Kr[0x1] = S5[t.z[0xA]] ^ S6[t.z[0xB]] ^ S7[t.z[0x5]] ^ S8[t.z[0x4]] ^ S6[t.z[0x6]]; - Kr[0x2] = S5[t.z[0xC]] ^ S6[t.z[0xD]] ^ S7[t.z[0x3]] ^ S8[t.z[0x2]] ^ S7[t.z[0x9]]; - Kr[0x3] = S5[t.z[0xE]] ^ S6[t.z[0xF]] ^ S7[t.z[0x1]] ^ S8[t.z[0x0]] ^ S8[t.z[0xC]]; - - k[0] = t.i[2] ^ S5[t.z[0x5]] ^ S6[t.z[0x7]] ^ S7[t.z[0x4]] ^ S8[t.z[0x6]] ^ S7[t.z[0x0]]; - k[1] = t.i[0] ^ S5[Key[0x0]] ^ S6[Key[0x2]] ^ S7[Key[0x1]] ^ S8[Key[0x3]] ^ S8[t.z[0x2]]; - k[2] = t.i[1] ^ S5[Key[0x7]] ^ S6[Key[0x6]] ^ S7[Key[0x5]] ^ S8[Key[0x4]] ^ S5[t.z[0x1]]; - k[3] = t.i[3] ^ S5[Key[0xA]] ^ S6[Key[0x9]] ^ S7[Key[0xB]] ^ S8[Key[0x8]] ^ S6[t.z[0x3]]; - - Kr[0x4] = S5[Key[0x3]] ^ S6[Key[0x2]] ^ S7[Key[0xC]] ^ S8[Key[0xD]] ^ S5[Key[0x8]]; - Kr[0x5] = S5[Key[0x1]] ^ S6[Key[0x0]] ^ S7[Key[0xE]] ^ S8[Key[0xF]] ^ S6[Key[0xD]]; - Kr[0x6] = S5[Key[0x7]] ^ S6[Key[0x6]] ^ S7[Key[0x8]] ^ S8[Key[0x9]] ^ S7[Key[0x3]]; - Kr[0x7] = S5[Key[0x5]] ^ S6[Key[0x4]] ^ S7[Key[0xA]] ^ S8[Key[0xB]] ^ S8[Key[0x7]]; - - t.i[0] = k[0] ^ S5[Key[0xD]] ^ S6[Key[0xF]] ^ S7[Key[0xC]] ^ S8[Key[0xE]] ^ S7[Key[0x8]]; - t.i[1] = k[2] ^ S5[t.z[0x0]] ^ S6[t.z[0x2]] ^ S7[t.z[0x1]] ^ S8[t.z[0x3]] ^ S8[Key[0xA]]; - t.i[2] = k[3] ^ S5[t.z[0x7]] ^ S6[t.z[0x6]] ^ S7[t.z[0x5]] ^ S8[t.z[0x4]] ^ S5[Key[0x9]]; - t.i[3] = k[1] ^ S5[t.z[0xA]] ^ S6[t.z[0x9]] ^ S7[t.z[0xB]] ^ S8[t.z[0x8]] ^ S6[Key[0xB]]; - - Kr[0x8] = S5[t.z[0x3]] ^ S6[t.z[0x2]] ^ S7[t.z[0xC]] ^ S8[t.z[0xD]] ^ S5[t.z[0x9]]; - Kr[0x9] = S5[t.z[0x1]] ^ S6[t.z[0x0]] ^ S7[t.z[0xE]] ^ S8[t.z[0xF]] ^ S6[t.z[0xC]]; - Kr[0xa] = S5[t.z[0x7]] ^ S6[t.z[0x6]] ^ S7[t.z[0x8]] ^ S8[t.z[0x9]] ^ S7[t.z[0x2]]; - Kr[0xb] = S5[t.z[0x5]] ^ S6[t.z[0x4]] ^ S7[t.z[0xA]] ^ S8[t.z[0xB]] ^ S8[t.z[0x6]]; - - k[0] = t.i[2] ^ S5[t.z[0x5]] ^ S6[t.z[0x7]] ^ S7[t.z[0x4]] ^ S8[t.z[0x6]] ^ S7[t.z[0x0]]; - k[1] = t.i[0] ^ S5[Key[0x0]] ^ S6[Key[0x2]] ^ S7[Key[0x1]] ^ S8[Key[0x3]] ^ S8[t.z[0x2]]; - k[2] = t.i[1] ^ S5[Key[0x7]] ^ S6[Key[0x6]] ^ S7[Key[0x5]] ^ S8[Key[0x4]] ^ S5[t.z[0x1]]; - k[3] = t.i[3] ^ S5[Key[0xA]] ^ S6[Key[0x9]] ^ S7[Key[0xB]] ^ S8[Key[0x8]] ^ S6[t.z[0x3]]; - - Kr[0xc] = S5[Key[0x8]] ^ S6[Key[0x9]] ^ S7[Key[0x7]] ^ S8[Key[0x6]] ^ S5[Key[0x3]]; - Kr[0xd] = S5[Key[0xA]] ^ S6[Key[0xB]] ^ S7[Key[0x5]] ^ S8[Key[0x4]] ^ S6[Key[0x7]]; - Kr[0xe] = S5[Key[0xC]] ^ S6[Key[0xD]] ^ S7[Key[0x3]] ^ S8[Key[0x2]] ^ S7[Key[0x8]]; - Kr[0xf] = S5[Key[0xE]] ^ S6[Key[0xF]] ^ S7[Key[0x1]] ^ S8[Key[0x0]] ^ S8[Key[0xD]]; - - - for (int i = 0; i < 16; i++) - Kr[i] = Kr[i] & 0x0000001F; -} - - -inline void CAST128::EncryptBlock(uint8_t *Block) -{ - uint32_t l, r, tmp; - union { - uint8_t byte[4]; - uint32_t block; - } t; - - l = ((uint32_t*)Block)[0]; - r = ((uint32_t*)Block)[1]; - - for (int i = 0; i < 16; i++) - { - if ((i % 3) == 0) - { - t.block = (t.block << Kr[i]) | (t.block >> (32 - Kr[i])); - t.block = ((S1[t.byte[0]] ^ S2[t.byte[1]]) - S3[t.byte[2]]) + S4[t.byte[3]]; - } else if ((i % 3) == 1) - { - t.block = (t.block << Kr[i]) | (t.block >> (32 - Kr[i])); - t.block = ((S1[t.byte[0]] - S2[t.byte[1]]) + S3[t.byte[2]]) ^ S4[t.byte[3]]; - } else { - t.block = (t.block << Kr[i]) | (t.block >> (32 - Kr[i])); - t.block = ((S1[t.byte[0]] + S2[t.byte[1]]) ^ S3[t.byte[2]]) - S4[t.byte[3]]; - } - - tmp = r; - r = l ^ t.block; - l = tmp; - } - - ((uint32_t*)Block)[0] = l; - ((uint32_t*)Block)[1] = r; -} - - - -inline void CAST128::DecryptBlock(uint8_t *Block) -{ - uint32_t l, r, tmp; - union { - uint8_t byte[4]; - uint32_t block; - } t; - - r = ((uint32_t*)Block)[0]; - l = ((uint32_t*)Block)[1]; - - for (int i = 15; i >= 0; i--) - { - if ((i % 3) == 0) - { - t.block = (t.block << Kr[i]) | (t.block >> (32 - Kr[i])); - t.block = ((S1[t.byte[0]] ^ S2[t.byte[1]]) - S3[t.byte[2]]) + S4[t.byte[3]]; - } else if ((i % 3) == 1) - { - t.block = (t.block << Kr[i]) | (t.block >> (32 - Kr[i])); - t.block = ((S1[t.byte[0]] - S2[t.byte[1]]) + S3[t.byte[2]]) ^ S4[t.byte[3]]; - } else { - t.block = (t.block << Kr[i]) | (t.block >> (32 - Kr[i])); - t.block = ((S1[t.byte[0]] + S2[t.byte[1]]) ^ S3[t.byte[2]]) - S4[t.byte[3]]; - } - - tmp = r; - r = l ^ t.block; - l = tmp; - } - - ((uint32_t*)Block)[0] = r; - ((uint32_t*)Block)[1] = l; -} - -extern "C" __declspec(dllexport) const TCipherInfo* CipherInfo(void * Reserved) -{ - return &CAST128::cCipherInfo; -} diff --git a/plugins/Dbx_tree/encryption/CAST128.h b/plugins/Dbx_tree/encryption/CAST128.h deleted file mode 100644 index 9477254986..0000000000 --- a/plugins/Dbx_tree/encryption/CAST128.h +++ /dev/null @@ -1,61 +0,0 @@ -/* - -dbx_tree: tree database driver for Miranda IM - -Copyright 2007-2008 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. - -*/ - -#pragma once - -#include "Cipher.h" - -class CAST128 : public CCipher -{ -private: - uint32_t Km[16], Kr[16]; - - void EncryptBlock(uint8_t *Block); - void DecryptBlock(uint8_t *Block); - void CreateSubKeys(uint8_t* Key); - - static const wchar_t* cName; - static const wchar_t* cDescription; - static const uint32_t cBlockSizeBytes = 8; - static const bool cIsStreamCipher = false; - -public: - const wchar_t * __cdecl Name(); - const wchar_t * __cdecl Description(); - const uint32_t __cdecl BlockSizeBytes(); - const bool __cdecl IsStreamCipher(); - - static const TCipherInfo cCipherInfo; - - CAST128(); - ~CAST128(); - static CCipher::TCipherInterface* __cdecl Create(); - - void __cdecl SetKey(void* Key, uint32_t KeyLength); - void __cdecl Encrypt(void* Data, uint32_t Size, uint32_t Nonce, uint32_t StartByte); - void __cdecl Decrypt(void* Data, uint32_t Size, uint32_t Nonce, uint32_t StartByte); - -}; - -const wchar_t* CAST128::cName = L"Cast128"; -const wchar_t* CAST128::cDescription = L"Blockcipher - 64bit block, fast and secure, Carlisle Adams and Stafford Tavares 1996"; -const TCipherInfo CAST128::cCipherInfo = {sizeof(TCipherInfo), 'Cast', cName, cDescription, &CAST128::Create}; diff --git a/plugins/Dbx_tree/encryption/CAST128.inc b/plugins/Dbx_tree/encryption/CAST128.inc deleted file mode 100644 index 8389acc92c..0000000000 --- a/plugins/Dbx_tree/encryption/CAST128.inc +++ /dev/null @@ -1,302 +0,0 @@ -/* - -dbx_tree: tree database driver for Miranda IM - -Copyright 2007-2008 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. - -*/ - - -static const uint32_t S1[256] = { -0x30fb40d4, 0x9fa0ff0b, 0x6beccd2f, 0x3f258c7a, 0x1e213f2f, 0x9c004dd3, 0x6003e540, 0xcf9fc949, -0xbfd4af27, 0x88bbbdb5, 0xe2034090, 0x98d09675, 0x6e63a0e0, 0x15c361d2, 0xc2e7661d, 0x22d4ff8e, -0x28683b6f, 0xc07fd059, 0xff2379c8, 0x775f50e2, 0x43c340d3, 0xdf2f8656, 0x887ca41a, 0xa2d2bd2d, -0xa1c9e0d6, 0x346c4819, 0x61b76d87, 0x22540f2f, 0x2abe32e1, 0xaa54166b, 0x22568e3a, 0xa2d341d0, -0x66db40c8, 0xa784392f, 0x004dff2f, 0x2db9d2de, 0x97943fac, 0x4a97c1d8, 0x527644b7, 0xb5f437a7, -0xb82cbaef, 0xd751d159, 0x6ff7f0ed, 0x5a097a1f, 0x827b68d0, 0x90ecf52e, 0x22b0c054, 0xbc8e5935, -0x4b6d2f7f, 0x50bb64a2, 0xd2664910, 0xbee5812d, 0xb7332290, 0xe93b159f, 0xb48ee411, 0x4bff345d, -0xfd45c240, 0xad31973f, 0xc4f6d02e, 0x55fc8165, 0xd5b1caad, 0xa1ac2dae, 0xa2d4b76d, 0xc19b0c50, -0x882240f2, 0x0c6e4f38, 0xa4e4bfd7, 0x4f5ba272, 0x564c1d2f, 0xc59c5319, 0xb949e354, 0xb04669fe, -0xb1b6ab8a, 0xc71358dd, 0x6385c545, 0x110f935d, 0x57538ad5, 0x6a390493, 0xe63d37e0, 0x2a54f6b3, -0x3a787d5f, 0x6276a0b5, 0x19a6fcdf, 0x7a42206a, 0x29f9d4d5, 0xf61b1891, 0xbb72275e, 0xaa508167, -0x38901091, 0xc6b505eb, 0x84c7cb8c, 0x2ad75a0f, 0x874a1427, 0xa2d1936b, 0x2ad286af, 0xaa56d291, -0xd7894360, 0x425c750d, 0x93b39e26, 0x187184c9, 0x6c00b32d, 0x73e2bb14, 0xa0bebc3c, 0x54623779, -0x64459eab, 0x3f328b82, 0x7718cf82, 0x59a2cea6, 0x04ee002e, 0x89fe78e6, 0x3fab0950, 0x325ff6c2, -0x81383f05, 0x6963c5c8, 0x76cb5ad6, 0xd49974c9, 0xca180dcf, 0x380782d5, 0xc7fa5cf6, 0x8ac31511, -0x35e79e13, 0x47da91d0, 0xf40f9086, 0xa7e2419e, 0x31366241, 0x051ef495, 0xaa573b04, 0x4a805d8d, -0x548300d0, 0x00322a3c, 0xbf64cddf, 0xba57a68e, 0x75c6372b, 0x50afd341, 0xa7c13275, 0x915a0bf5, -0x6b54bfab, 0x2b0b1426, 0xab4cc9d7, 0x449ccd82, 0xf7fbf265, 0xab85c5f3, 0x1b55db94, 0xaad4e324, -0xcfa4bd3f, 0x2deaa3e2, 0x9e204d02, 0xc8bd25ac, 0xeadf55b3, 0xd5bd9e98, 0xe31231b2, 0x2ad5ad6c, -0x954329de, 0xadbe4528, 0xd8710f69, 0xaa51c90f, 0xaa786bf6, 0x22513f1e, 0xaa51a79b, 0x2ad344cc, -0x7b5a41f0, 0xd37cfbad, 0x1b069505, 0x41ece491, 0xb4c332e6, 0x032268d4, 0xc9600acc, 0xce387e6d, -0xbf6bb16c, 0x6a70fb78, 0x0d03d9c9, 0xd4df39de, 0xe01063da, 0x4736f464, 0x5ad328d8, 0xb347cc96, -0x75bb0fc3, 0x98511bfb, 0x4ffbcc35, 0xb58bcf6a, 0xe11f0abc, 0xbfc5fe4a, 0xa70aec10, 0xac39570a, -0x3f04442f, 0x6188b153, 0xe0397a2e, 0x5727cb79, 0x9ceb418f, 0x1cacd68d, 0x2ad37c96, 0x0175cb9d, -0xc69dff09, 0xc75b65f0, 0xd9db40d8, 0xec0e7779, 0x4744ead4, 0xb11c3274, 0xdd24cb9e, 0x7e1c54bd, -0xf01144f9, 0xd2240eb1, 0x9675b3fd, 0xa3ac3755, 0xd47c27af, 0x51c85f4d, 0x56907596, 0xa5bb15e6, -0x580304f0, 0xca042cf1, 0x011a37ea, 0x8dbfaadb, 0x35ba3e4a, 0x3526ffa0, 0xc37b4d09, 0xbc306ed9, -0x98a52666, 0x5648f725, 0xff5e569d, 0x0ced63d0, 0x7c63b2cf, 0x700b45e1, 0xd5ea50f1, 0x85a92872, -0xaf1fbda7, 0xd4234870, 0xa7870bf3, 0x2d3b4d79, 0x42e04198, 0x0cd0ede7, 0x26470db8, 0xf881814c, -0x474d6ad7, 0x7c0c5e5c, 0xd1231959, 0x381b7298, 0xf5d2f4db, 0xab838653, 0x6e2f1e23, 0x83719c9e, -0xbd91e046, 0x9a56456e, 0xdc39200c, 0x20c8c571, 0x962bda1c, 0xe1e696ff, 0xb141ab08, 0x7cca89b9, -0x1a69e783, 0x02cc4843, 0xa2f7c579, 0x429ef47d, 0x427b169c, 0x5ac9f049, 0xdd8f0f00, 0x5c8165bf, -}; - -static const uint32_t S2[256] = { -0x1f201094, 0xef0ba75b, 0x69e3cf7e, 0x393f4380, 0xfe61cf7a, 0xeec5207a, 0x55889c94, 0x72fc0651, -0xada7ef79, 0x4e1d7235, 0xd55a63ce, 0xde0436ba, 0x99c430ef, 0x5f0c0794, 0x18dcdb7d, 0xa1d6eff3, -0xa0b52f7b, 0x59e83605, 0xee15b094, 0xe9ffd909, 0xdc440086, 0xef944459, 0xba83ccb3, 0xe0c3cdfb, -0xd1da4181, 0x3b092ab1, 0xf997f1c1, 0xa5e6cf7b, 0x01420ddb, 0xe4e7ef5b, 0x25a1ff41, 0xe180f806, -0x1fc41080, 0x179bee7a, 0xd37ac6a9, 0xfe5830a4, 0x98de8b7f, 0x77e83f4e, 0x79929269, 0x24fa9f7b, -0xe113c85b, 0xacc40083, 0xd7503525, 0xf7ea615f, 0x62143154, 0x0d554b63, 0x5d681121, 0xc866c359, -0x3d63cf73, 0xcee234c0, 0xd4d87e87, 0x5c672b21, 0x071f6181, 0x39f7627f, 0x361e3084, 0xe4eb573b, -0x602f64a4, 0xd63acd9c, 0x1bbc4635, 0x9e81032d, 0x2701f50c, 0x99847ab4, 0xa0e3df79, 0xba6cf38c, -0x10843094, 0x2537a95e, 0xf46f6ffe, 0xa1ff3b1f, 0x208cfb6a, 0x8f458c74, 0xd9e0a227, 0x4ec73a34, -0xfc884f69, 0x3e4de8df, 0xef0e0088, 0x3559648d, 0x8a45388c, 0x1d804366, 0x721d9bfd, 0xa58684bb, -0xe8256333, 0x844e8212, 0x128d8098, 0xfed33fb4, 0xce280ae1, 0x27e19ba5, 0xd5a6c252, 0xe49754bd, -0xc5d655dd, 0xeb667064, 0x77840b4d, 0xa1b6a801, 0x84db26a9, 0xe0b56714, 0x21f043b7, 0xe5d05860, -0x54f03084, 0x066ff472, 0xa31aa153, 0xdadc4755, 0xb5625dbf, 0x68561be6, 0x83ca6b94, 0x2d6ed23b, -0xeccf01db, 0xa6d3d0ba, 0xb6803d5c, 0xaf77a709, 0x33b4a34c, 0x397bc8d6, 0x5ee22b95, 0x5f0e5304, -0x81ed6f61, 0x20e74364, 0xb45e1378, 0xde18639b, 0x881ca122, 0xb96726d1, 0x8049a7e8, 0x22b7da7b, -0x5e552d25, 0x5272d237, 0x79d2951c, 0xc60d894c, 0x488cb402, 0x1ba4fe5b, 0xa4b09f6b, 0x1ca815cf, -0xa20c3005, 0x8871df63, 0xb9de2fcb, 0x0cc6c9e9, 0x0beeff53, 0xe3214517, 0xb4542835, 0x9f63293c, -0xee41e729, 0x6e1d2d7c, 0x50045286, 0x1e6685f3, 0xf33401c6, 0x30a22c95, 0x31a70850, 0x60930f13, -0x73f98417, 0xa1269859, 0xec645c44, 0x52c877a9, 0xcdff33a6, 0xa02b1741, 0x7cbad9a2, 0x2180036f, -0x50d99c08, 0xcb3f4861, 0xc26bd765, 0x64a3f6ab, 0x80342676, 0x25a75e7b, 0xe4e6d1fc, 0x20c710e6, -0xcdf0b680, 0x17844d3b, 0x31eef84d, 0x7e0824e4, 0x2ccb49eb, 0x846a3bae, 0x8ff77888, 0xee5d60f6, -0x7af75673, 0x2fdd5cdb, 0xa11631c1, 0x30f66f43, 0xb3faec54, 0x157fd7fa, 0xef8579cc, 0xd152de58, -0xdb2ffd5e, 0x8f32ce19, 0x306af97a, 0x02f03ef8, 0x99319ad5, 0xc242fa0f, 0xa7e3ebb0, 0xc68e4906, -0xb8da230c, 0x80823028, 0xdcdef3c8, 0xd35fb171, 0x088a1bc8, 0xbec0c560, 0x61a3c9e8, 0xbca8f54d, -0xc72feffa, 0x22822e99, 0x82c570b4, 0xd8d94e89, 0x8b1c34bc, 0x301e16e6, 0x273be979, 0xb0ffeaa6, -0x61d9b8c6, 0x00b24869, 0xb7ffce3f, 0x08dc283b, 0x43daf65a, 0xf7e19798, 0x7619b72f, 0x8f1c9ba4, -0xdc8637a0, 0x16a7d3b1, 0x9fc393b7, 0xa7136eeb, 0xc6bcc63e, 0x1a513742, 0xef6828bc, 0x520365d6, -0x2d6a77ab, 0x3527ed4b, 0x821fd216, 0x095c6e2e, 0xdb92f2fb, 0x5eea29cb, 0x145892f5, 0x91584f7f, -0x5483697b, 0x2667a8cc, 0x85196048, 0x8c4bacea, 0x833860d4, 0x0d23e0f9, 0x6c387e8a, 0x0ae6d249, -0xb284600c, 0xd835731d, 0xdcb1c647, 0xac4c56ea, 0x3ebd81b3, 0x230eabb0, 0x6438bc87, 0xf0b5b1fa, -0x8f5ea2b3, 0xfc184642, 0x0a036b7a, 0x4fb089bd, 0x649da589, 0xa345415e, 0x5c038323, 0x3e5d3bb9, -0x43d79572, 0x7e6dd07c, 0x06dfdf1e, 0x6c6cc4ef, 0x7160a539, 0x73bfbe70, 0x83877605, 0x4523ecf1, -}; - -static const uint32_t S3[256] = { -0x8defc240, 0x25fa5d9f, 0xeb903dbf, 0xe810c907, 0x47607fff, 0x369fe44b, 0x8c1fc644, 0xaececa90, -0xbeb1f9bf, 0xeefbcaea, 0xe8cf1950, 0x51df07ae, 0x920e8806, 0xf0ad0548, 0xe13c8d83, 0x927010d5, -0x11107d9f, 0x07647db9, 0xb2e3e4d4, 0x3d4f285e, 0xb9afa820, 0xfade82e0, 0xa067268b, 0x8272792e, -0x553fb2c0, 0x489ae22b, 0xd4ef9794, 0x125e3fbc, 0x21fffcee, 0x825b1bfd, 0x9255c5ed, 0x1257a240, -0x4e1a8302, 0xbae07fff, 0x528246e7, 0x8e57140e, 0x3373f7bf, 0x8c9f8188, 0xa6fc4ee8, 0xc982b5a5, -0xa8c01db7, 0x579fc264, 0x67094f31, 0xf2bd3f5f, 0x40fff7c1, 0x1fb78dfc, 0x8e6bd2c1, 0x437be59b, -0x99b03dbf, 0xb5dbc64b, 0x638dc0e6, 0x55819d99, 0xa197c81c, 0x4a012d6e, 0xc5884a28, 0xccc36f71, -0xb843c213, 0x6c0743f1, 0x8309893c, 0x0feddd5f, 0x2f7fe850, 0xd7c07f7e, 0x02507fbf, 0x5afb9a04, -0xa747d2d0, 0x1651192e, 0xaf70bf3e, 0x58c31380, 0x5f98302e, 0x727cc3c4, 0x0a0fb402, 0x0f7fef82, -0x8c96fdad, 0x5d2c2aae, 0x8ee99a49, 0x50da88b8, 0x8427f4a0, 0x1eac5790, 0x796fb449, 0x8252dc15, -0xefbd7d9b, 0xa672597d, 0xada840d8, 0x45f54504, 0xfa5d7403, 0xe83ec305, 0x4f91751a, 0x925669c2, -0x23efe941, 0xa903f12e, 0x60270df2, 0x0276e4b6, 0x94fd6574, 0x927985b2, 0x8276dbcb, 0x02778176, -0xf8af918d, 0x4e48f79e, 0x8f616ddf, 0xe29d840e, 0x842f7d83, 0x340ce5c8, 0x96bbb682, 0x93b4b148, -0xef303cab, 0x984faf28, 0x779faf9b, 0x92dc560d, 0x224d1e20, 0x8437aa88, 0x7d29dc96, 0x2756d3dc, -0x8b907cee, 0xb51fd240, 0xe7c07ce3, 0xe566b4a1, 0xc3e9615e, 0x3cf8209d, 0x6094d1e3, 0xcd9ca341, -0x5c76460e, 0x00ea983b, 0xd4d67881, 0xfd47572c, 0xf76cedd9, 0xbda8229c, 0x127dadaa, 0x438a074e, -0x1f97c090, 0x081bdb8a, 0x93a07ebe, 0xb938ca15, 0x97b03cff, 0x3dc2c0f8, 0x8d1ab2ec, 0x64380e51, -0x68cc7bfb, 0xd90f2788, 0x12490181, 0x5de5ffd4, 0xdd7ef86a, 0x76a2e214, 0xb9a40368, 0x925d958f, -0x4b39fffa, 0xba39aee9, 0xa4ffd30b, 0xfaf7933b, 0x6d498623, 0x193cbcfa, 0x27627545, 0x825cf47a, -0x61bd8ba0, 0xd11e42d1, 0xcead04f4, 0x127ea392, 0x10428db7, 0x8272a972, 0x9270c4a8, 0x127de50b, -0x285ba1c8, 0x3c62f44f, 0x35c0eaa5, 0xe805d231, 0x428929fb, 0xb4fcdf82, 0x4fb66a53, 0x0e7dc15b, -0x1f081fab, 0x108618ae, 0xfcfd086d, 0xf9ff2889, 0x694bcc11, 0x236a5cae, 0x12deca4d, 0x2c3f8cc5, -0xd2d02dfe, 0xf8ef5896, 0xe4cf52da, 0x95155b67, 0x494a488c, 0xb9b6a80c, 0x5c8f82bc, 0x89d36b45, -0x3a609437, 0xec00c9a9, 0x44715253, 0x0a874b49, 0xd773bc40, 0x7c34671c, 0x02717ef6, 0x4feb5536, -0xa2d02fff, 0xd2bf60c4, 0xd43f03c0, 0x50b4ef6d, 0x07478cd1, 0x006e1888, 0xa2e53f55, 0xb9e6d4bc, -0xa2048016, 0x97573833, 0xd7207d67, 0xde0f8f3d, 0x72f87b33, 0xabcc4f33, 0x7688c55d, 0x7b00a6b0, -0x947b0001, 0x570075d2, 0xf9bb88f8, 0x8942019e, 0x4264a5ff, 0x856302e0, 0x72dbd92b, 0xee971b69, -0x6ea22fde, 0x5f08ae2b, 0xaf7a616d, 0xe5c98767, 0xcf1febd2, 0x61efc8c2, 0xf1ac2571, 0xcc8239c2, -0x67214cb8, 0xb1e583d1, 0xb7dc3e62, 0x7f10bdce, 0xf90a5c38, 0x0ff0443d, 0x606e6dc6, 0x60543a49, -0x5727c148, 0x2be98a1d, 0x8ab41738, 0x20e1be24, 0xaf96da0f, 0x68458425, 0x99833be5, 0x600d457d, -0x282f9350, 0x8334b362, 0xd91d1120, 0x2b6d8da0, 0x642b1e31, 0x9c305a00, 0x52bce688, 0x1b03588a, -0xf7baefd5, 0x4142ed9c, 0xa4315c11, 0x83323ec5, 0xdfef4636, 0xa133c501, 0xe9d3531c, 0xee353783, -}; - -static const uint32_t S4[256] = { -0x9db30420, 0x1fb6e9de, 0xa7be7bef, 0xd273a298, 0x4a4f7bdb, 0x64ad8c57, 0x85510443, 0xfa020ed1, -0x7e287aff, 0xe60fb663, 0x095f35a1, 0x79ebf120, 0xfd059d43, 0x6497b7b1, 0xf3641f63, 0x241e4adf, -0x28147f5f, 0x4fa2b8cd, 0xc9430040, 0x0cc32220, 0xfdd30b30, 0xc0a5374f, 0x1d2d00d9, 0x24147b15, -0xee4d111a, 0x0fca5167, 0x71ff904c, 0x2d195ffe, 0x1a05645f, 0x0c13fefe, 0x081b08ca, 0x05170121, -0x80530100, 0xe83e5efe, 0xac9af4f8, 0x7fe72701, 0xd2b8ee5f, 0x06df4261, 0xbb9e9b8a, 0x7293ea25, -0xce84ffdf, 0xf5718801, 0x3dd64b04, 0xa26f263b, 0x7ed48400, 0x547eebe6, 0x446d4ca0, 0x6cf3d6f5, -0x2649abdf, 0xaea0c7f5, 0x36338cc1, 0x503f7e93, 0xd3772061, 0x11b638e1, 0x72500e03, 0xf80eb2bb, -0xabe0502e, 0xec8d77de, 0x57971e81, 0xe14f6746, 0xc9335400, 0x6920318f, 0x081dbb99, 0xffc304a5, -0x4d351805, 0x7f3d5ce3, 0xa6c866c6, 0x5d5bcca9, 0xdaec6fea, 0x9f926f91, 0x9f46222f, 0x3991467d, -0xa5bf6d8e, 0x1143c44f, 0x43958302, 0xd0214eeb, 0x022083b8, 0x3fb6180c, 0x18f8931e, 0x281658e6, -0x26486e3e, 0x8bd78a70, 0x7477e4c1, 0xb506e07c, 0xf32d0a25, 0x79098b02, 0xe4eabb81, 0x28123b23, -0x69dead38, 0x1574ca16, 0xdf871b62, 0x211c40b7, 0xa51a9ef9, 0x0014377b, 0x041e8ac8, 0x09114003, -0xbd59e4d2, 0xe3d156d5, 0x4fe876d5, 0x2f91a340, 0x557be8de, 0x00eae4a7, 0x0ce5c2ec, 0x4db4bba6, -0xe756bdff, 0xdd3369ac, 0xec17b035, 0x06572327, 0x99afc8b0, 0x56c8c391, 0x6b65811c, 0x5e146119, -0x6e85cb75, 0xbe07c002, 0xc2325577, 0x893ff4ec, 0x5bbfc92d, 0xd0ec3b25, 0xb7801ab7, 0x8d6d3b24, -0x20c763ef, 0xc366a5fc, 0x9c382880, 0x0ace3205, 0xaac9548a, 0xeca1d7c7, 0x041afa32, 0x1d16625a, -0x6701902c, 0x9b757a54, 0x31d477f7, 0x9126b031, 0x36cc6fdb, 0xc70b8b46, 0xd9e66a48, 0x56e55a79, -0x026a4ceb, 0x52437eff, 0x2f8f76b4, 0x0df980a5, 0x8674cde3, 0xedda04eb, 0x17a9be04, 0x2c18f4df, -0xb7747f9d, 0xab2af7b4, 0xefc34d20, 0x2e096b7c, 0x1741a254, 0xe5b6a035, 0x213d42f6, 0x2c1c7c26, -0x61c2f50f, 0x6552daf9, 0xd2c231f8, 0x25130f69, 0xd8167fa2, 0x0418f2c8, 0x001a96a6, 0x0d1526ab, -0x63315c21, 0x5e0a72ec, 0x49bafefd, 0x187908d9, 0x8d0dbd86, 0x311170a7, 0x3e9b640c, 0xcc3e10d7, -0xd5cad3b6, 0x0caec388, 0xf73001e1, 0x6c728aff, 0x71eae2a1, 0x1f9af36e, 0xcfcbd12f, 0xc1de8417, -0xac07be6b, 0xcb44a1d8, 0x8b9b0f56, 0x013988c3, 0xb1c52fca, 0xb4be31cd, 0xd8782806, 0x12a3a4e2, -0x6f7de532, 0x58fd7eb6, 0xd01ee900, 0x24adffc2, 0xf4990fc5, 0x9711aac5, 0x001d7b95, 0x82e5e7d2, -0x109873f6, 0x00613096, 0xc32d9521, 0xada121ff, 0x29908415, 0x7fbb977f, 0xaf9eb3db, 0x29c9ed2a, -0x5ce2a465, 0xa730f32c, 0xd0aa3fe8, 0x8a5cc091, 0xd49e2ce7, 0x0ce454a9, 0xd60acd86, 0x015f1919, -0x77079103, 0xdea03af6, 0x78a8565e, 0xdee356df, 0x21f05cbe, 0x8b75e387, 0xb3c50651, 0xb8a5c3ef, -0xd8eeb6d2, 0xe523be77, 0xc2154529, 0x2f69efdf, 0xafe67afb, 0xf470c4b2, 0xf3e0eb5b, 0xd6cc9876, -0x39e4460c, 0x1fda8538, 0x1987832f, 0xca007367, 0xa99144f8, 0x296b299e, 0x492fc295, 0x9266beab, -0xb5676e69, 0x9bd3ddda, 0xdf7e052f, 0xdb25701c, 0x1b5e51ee, 0xf65324e6, 0x6afce36c, 0x0316cc04, -0x8644213e, 0xb7dc59d0, 0x7965291f, 0xccd6fd43, 0x41823979, 0x932bcdf6, 0xb657c34d, 0x4edfd282, -0x7ae5290c, 0x3cb9536b, 0x851e20fe, 0x9833557e, 0x13ecf0b0, 0xd3ffb372, 0x3f85c5c1, 0x0aef7ed2, -}; - -static const uint32_t S5[256] = { -0x7ec90c04, 0x2c6e74b9, 0x9b0e66df, 0xa6337911, 0xb86a7fff, 0x1dd358f5, 0x44dd9d44, 0x1731167f, -0x08fbf1fa, 0xe7f511cc, 0xd2051b00, 0x735aba00, 0x2ab722d8, 0x386381cb, 0xacf6243a, 0x69befd7a, -0xe6a2e77f, 0xf0c720cd, 0xc4494816, 0xccf5c180, 0x38851640, 0x15b0a848, 0xe68b18cb, 0x4caadeff, -0x5f480a01, 0x0412b2aa, 0x259814fc, 0x41d0efe2, 0x4e40b48d, 0x248eb6fb, 0x8dba1cfe, 0x41a99b02, -0x1a550a04, 0xba8f65cb, 0x7251f4e7, 0x95a51725, 0xc106ecd7, 0x97a5980a, 0xc539b9aa, 0x4d79fe6a, -0xf2f3f763, 0x68af8040, 0xed0c9e56, 0x11b4958b, 0xe1eb5a88, 0x8709e6b0, 0xd7e07156, 0x4e29fea7, -0x6366e52d, 0x02d1c000, 0xc4ac8e05, 0x9377f571, 0x0c05372a, 0x578535f2, 0x2261be02, 0xd642a0c9, -0xdf13a280, 0x74b55bd2, 0x682199c0, 0xd421e5ec, 0x53fb3ce8, 0xc8adedb3, 0x28a87fc9, 0x3d959981, -0x5c1ff900, 0xfe38d399, 0x0c4eff0b, 0x062407ea, 0xaa2f4fb1, 0x4fb96976, 0x90c79505, 0xb0a8a774, -0xef55a1ff, 0xe59ca2c2, 0xa6b62d27, 0xe66a4263, 0xdf65001f, 0x0ec50966, 0xdfdd55bc, 0x29de0655, -0x911e739a, 0x17af8975, 0x32c7911c, 0x89f89468, 0x0d01e980, 0x524755f4, 0x03b63cc9, 0x0cc844b2, -0xbcf3f0aa, 0x87ac36e9, 0xe53a7426, 0x01b3d82b, 0x1a9e7449, 0x64ee2d7e, 0xcddbb1da, 0x01c94910, -0xb868bf80, 0x0d26f3fd, 0x9342ede7, 0x04a5c284, 0x636737b6, 0x50f5b616, 0xf24766e3, 0x8eca36c1, -0x136e05db, 0xfef18391, 0xfb887a37, 0xd6e7f7d4, 0xc7fb7dc9, 0x3063fcdf, 0xb6f589de, 0xec2941da, -0x26e46695, 0xb7566419, 0xf654efc5, 0xd08d58b7, 0x48925401, 0xc1bacb7f, 0xe5ff550f, 0xb6083049, -0x5bb5d0e8, 0x87d72e5a, 0xab6a6ee1, 0x223a66ce, 0xc62bf3cd, 0x9e0885f9, 0x68cb3e47, 0x086c010f, -0xa21de820, 0xd18b69de, 0xf3f65777, 0xfa02c3f6, 0x407edac3, 0xcbb3d550, 0x1793084d, 0xb0d70eba, -0x0ab378d5, 0xd951fb0c, 0xded7da56, 0x4124bbe4, 0x94ca0b56, 0x0f5755d1, 0xe0e1e56e, 0x6184b5be, -0x580a249f, 0x94f74bc0, 0xe327888e, 0x9f7b5561, 0xc3dc0280, 0x05687715, 0x646c6bd7, 0x44904db3, -0x66b4f0a3, 0xc0f1648a, 0x697ed5af, 0x49e92ff6, 0x309e374f, 0x2cb6356a, 0x85808573, 0x4991f840, -0x76f0ae02, 0x083be84d, 0x28421c9a, 0x44489406, 0x736e4cb8, 0xc1092910, 0x8bc95fc6, 0x7d869cf4, -0x134f616f, 0x2e77118d, 0xb31b2be1, 0xaa90b472, 0x3ca5d717, 0x7d161bba, 0x9cad9010, 0xaf462ba2, -0x9fe459d2, 0x45d34559, 0xd9f2da13, 0xdbc65487, 0xf3e4f94e, 0x176d486f, 0x097c13ea, 0x631da5c7, -0x445f7382, 0x175683f4, 0xcdc66a97, 0x70be0288, 0xb3cdcf72, 0x6e5dd2f3, 0x20936079, 0x459b80a5, -0xbe60e2db, 0xa9c23101, 0xeba5315c, 0x224e42f2, 0x1c5c1572, 0xf6721b2c, 0x1ad2fff3, 0x8c25404e, -0x324ed72f, 0x4067b7fd, 0x0523138e, 0x5ca3bc78, 0xdc0fd66e, 0x75922283, 0x784d6b17, 0x58ebb16e, -0x44094f85, 0x3f481d87, 0xfcfeae7b, 0x77b5ff76, 0x8c2302bf, 0xaaf47556, 0x5f46b02a, 0x2b092801, -0x3d38f5f7, 0x0ca81f36, 0x52af4a8a, 0x66d5e7c0, 0xdf3b0874, 0x95055110, 0x1b5ad7a8, 0xf61ed5ad, -0x6cf6e479, 0x20758184, 0xd0cefa65, 0x88f7be58, 0x4a046826, 0x0ff6f8f3, 0xa09c7f70, 0x5346aba0, -0x5ce96c28, 0xe176eda3, 0x6bac307f, 0x376829d2, 0x85360fa9, 0x17e3fe2a, 0x24b79767, 0xf5a96b20, -0xd6cd2595, 0x68ff1ebf, 0x7555442c, 0xf19f06be, 0xf9e0659a, 0xeeb9491d, 0x34010718, 0xbb30cab8, -0xe822fe15, 0x88570983, 0x750e6249, 0xda627e55, 0x5e76ffa8, 0xb1534546, 0x6d47de08, 0xefe9e7d4, -}; - -static const uint32_t S6[256] = { -0xf6fa8f9d, 0x2cac6ce1, 0x4ca34867, 0xe2337f7c, 0x95db08e7, 0x016843b4, 0xeced5cbc, 0x325553ac, -0xbf9f0960, 0xdfa1e2ed, 0x83f0579d, 0x63ed86b9, 0x1ab6a6b8, 0xde5ebe39, 0xf38ff732, 0x8989b138, -0x33f14961, 0xc01937bd, 0xf506c6da, 0xe4625e7e, 0xa308ea99, 0x4e23e33c, 0x79cbd7cc, 0x48a14367, -0xa3149619, 0xfec94bd5, 0xa114174a, 0xeaa01866, 0xa084db2d, 0x09a8486f, 0xa888614a, 0x2900af98, -0x01665991, 0xe1992863, 0xc8f30c60, 0x2e78ef3c, 0xd0d51932, 0xcf0fec14, 0xf7ca07d2, 0xd0a82072, -0xfd41197e, 0x9305a6b0, 0xe86be3da, 0x74bed3cd, 0x372da53c, 0x4c7f4448, 0xdab5d440, 0x6dba0ec3, -0x083919a7, 0x9fbaeed9, 0x49dbcfb0, 0x4e670c53, 0x5c3d9c01, 0x64bdb941, 0x2c0e636a, 0xba7dd9cd, -0xea6f7388, 0xe70bc762, 0x35f29adb, 0x5c4cdd8d, 0xf0d48d8c, 0xb88153e2, 0x08a19866, 0x1ae2eac8, -0x284caf89, 0xaa928223, 0x9334be53, 0x3b3a21bf, 0x16434be3, 0x9aea3906, 0xefe8c36e, 0xf890cdd9, -0x80226dae, 0xc340a4a3, 0xdf7e9c09, 0xa694a807, 0x5b7c5ecc, 0x221db3a6, 0x9a69a02f, 0x68818a54, -0xceb2296f, 0x53c0843a, 0xfe893655, 0x25bfe68a, 0xb4628abc, 0xcf222ebf, 0x25ac6f48, 0xa9a99387, -0x53bddb65, 0xe76ffbe7, 0xe967fd78, 0x0ba93563, 0x8e342bc1, 0xe8a11be9, 0x4980740d, 0xc8087dfc, -0x8de4bf99, 0xa11101a0, 0x7fd37975, 0xda5a26c0, 0xe81f994f, 0x9528cd89, 0xfd339fed, 0xb87834bf, -0x5f04456d, 0x22258698, 0xc9c4c83b, 0x2dc156be, 0x4f628daa, 0x57f55ec5, 0xe2220abe, 0xd2916ebf, -0x4ec75b95, 0x24f2c3c0, 0x42d15d99, 0xcd0d7fa0, 0x7b6e27ff, 0xa8dc8af0, 0x7345c106, 0xf41e232f, -0x35162386, 0xe6ea8926, 0x3333b094, 0x157ec6f2, 0x372b74af, 0x692573e4, 0xe9a9d848, 0xf3160289, -0x3a62ef1d, 0xa787e238, 0xf3a5f676, 0x74364853, 0x20951063, 0x4576698d, 0xb6fad407, 0x592af950, -0x36f73523, 0x4cfb6e87, 0x7da4cec0, 0x6c152daa, 0xcb0396a8, 0xc50dfe5d, 0xfcd707ab, 0x0921c42f, -0x89dff0bb, 0x5fe2be78, 0x448f4f33, 0x754613c9, 0x2b05d08d, 0x48b9d585, 0xdc049441, 0xc8098f9b, -0x7dede786, 0xc39a3373, 0x42410005, 0x6a091751, 0x0ef3c8a6, 0x890072d6, 0x28207682, 0xa9a9f7be, -0xbf32679d, 0xd45b5b75, 0xb353fd00, 0xcbb0e358, 0x830f220a, 0x1f8fb214, 0xd372cf08, 0xcc3c4a13, -0x8cf63166, 0x061c87be, 0x88c98f88, 0x6062e397, 0x47cf8e7a, 0xb6c85283, 0x3cc2acfb, 0x3fc06976, -0x4e8f0252, 0x64d8314d, 0xda3870e3, 0x1e665459, 0xc10908f0, 0x513021a5, 0x6c5b68b7, 0x822f8aa0, -0x3007cd3e, 0x74719eef, 0xdc872681, 0x073340d4, 0x7e432fd9, 0x0c5ec241, 0x8809286c, 0xf592d891, -0x08a930f6, 0x957ef305, 0xb7fbffbd, 0xc266e96f, 0x6fe4ac98, 0xb173ecc0, 0xbc60b42a, 0x953498da, -0xfba1ae12, 0x2d4bd736, 0x0f25faab, 0xa4f3fceb, 0xe2969123, 0x257f0c3d, 0x9348af49, 0x361400bc, -0xe8816f4a, 0x3814f200, 0xa3f94043, 0x9c7a54c2, 0xbc704f57, 0xda41e7f9, 0xc25ad33a, 0x54f4a084, -0xb17f5505, 0x59357cbe, 0xedbd15c8, 0x7f97c5ab, 0xba5ac7b5, 0xb6f6deaf, 0x3a479c3a, 0x5302da25, -0x653d7e6a, 0x54268d49, 0x51a477ea, 0x5017d55b, 0xd7d25d88, 0x44136c76, 0x0404a8c8, 0xb8e5a121, -0xb81a928a, 0x60ed5869, 0x97c55b96, 0xeaec991b, 0x29935913, 0x01fdb7f1, 0x088e8dfa, 0x9ab6f6f5, -0x3b4cbf9f, 0x4a5de3ab, 0xe6051d35, 0xa0e1d855, 0xd36b4cf1, 0xf544edeb, 0xb0e93524, 0xbebb8fbd, -0xa2d762cf, 0x49c92f54, 0x38b5f331, 0x7128a454, 0x48392905, 0xa65b1db8, 0x851c97bd, 0xd675cf2f, -}; - -static const uint32_t S7[256] = { -0x85e04019, 0x332bf567, 0x662dbfff, 0xcfc65693, 0x2a8d7f6f, 0xab9bc912, 0xde6008a1, 0x2028da1f, -0x0227bce7, 0x4d642916, 0x18fac300, 0x50f18b82, 0x2cb2cb11, 0xb232e75c, 0x4b3695f2, 0xb28707de, -0xa05fbcf6, 0xcd4181e9, 0xe150210c, 0xe24ef1bd, 0xb168c381, 0xfde4e789, 0x5c79b0d8, 0x1e8bfd43, -0x4d495001, 0x38be4341, 0x913cee1d, 0x92a79c3f, 0x089766be, 0xbaeeadf4, 0x1286becf, 0xb6eacb19, -0x2660c200, 0x7565bde4, 0x64241f7a, 0x8248dca9, 0xc3b3ad66, 0x28136086, 0x0bd8dfa8, 0x356d1cf2, -0x107789be, 0xb3b2e9ce, 0x0502aa8f, 0x0bc0351e, 0x166bf52a, 0xeb12ff82, 0xe3486911, 0xd34d7516, -0x4e7b3aff, 0x5f43671b, 0x9cf6e037, 0x4981ac83, 0x334266ce, 0x8c9341b7, 0xd0d854c0, 0xcb3a6c88, -0x47bc2829, 0x4725ba37, 0xa66ad22b, 0x7ad61f1e, 0x0c5cbafa, 0x4437f107, 0xb6e79962, 0x42d2d816, -0x0a961288, 0xe1a5c06e, 0x13749e67, 0x72fc081a, 0xb1d139f7, 0xf9583745, 0xcf19df58, 0xbec3f756, -0xc06eba30, 0x07211b24, 0x45c28829, 0xc95e317f, 0xbc8ec511, 0x38bc46e9, 0xc6e6fa14, 0xbae8584a, -0xad4ebc46, 0x468f508b, 0x7829435f, 0xf124183b, 0x821dba9f, 0xaff60ff4, 0xea2c4e6d, 0x16e39264, -0x92544a8b, 0x009b4fc3, 0xaba68ced, 0x9ac96f78, 0x06a5b79a, 0xb2856e6e, 0x1aec3ca9, 0xbe838688, -0x0e0804e9, 0x55f1be56, 0xe7e5363b, 0xb3a1f25d, 0xf7debb85, 0x61fe033c, 0x16746233, 0x3c034c28, -0xda6d0c74, 0x79aac56c, 0x3ce4e1ad, 0x51f0c802, 0x98f8f35a, 0x1626a49f, 0xeed82b29, 0x1d382fe3, -0x0c4fb99a, 0xbb325778, 0x3ec6d97b, 0x6e77a6a9, 0xcb658b5c, 0xd45230c7, 0x2bd1408b, 0x60c03eb7, -0xb9068d78, 0xa33754f4, 0xf430c87d, 0xc8a71302, 0xb96d8c32, 0xebd4e7be, 0xbe8b9d2d, 0x7979fb06, -0xe7225308, 0x8b75cf77, 0x11ef8da4, 0xe083c858, 0x8d6b786f, 0x5a6317a6, 0xfa5cf7a0, 0x5dda0033, -0xf28ebfb0, 0xf5b9c310, 0xa0eac280, 0x08b9767a, 0xa3d9d2b0, 0x79d34217, 0x021a718d, 0x9ac6336a, -0x2711fd60, 0x438050e3, 0x069908a8, 0x3d7fedc4, 0x826d2bef, 0x4eeb8476, 0x488dcf25, 0x36c9d566, -0x28e74e41, 0xc2610aca, 0x3d49a9cf, 0xbae3b9df, 0xb65f8de6, 0x92aeaf64, 0x3ac7d5e6, 0x9ea80509, -0xf22b017d, 0xa4173f70, 0xdd1e16c3, 0x15e0d7f9, 0x50b1b887, 0x2b9f4fd5, 0x625aba82, 0x6a017962, -0x2ec01b9c, 0x15488aa9, 0xd716e740, 0x40055a2c, 0x93d29a22, 0xe32dbf9a, 0x058745b9, 0x3453dc1e, -0xd699296e, 0x496cff6f, 0x1c9f4986, 0xdfe2ed07, 0xb87242d1, 0x19de7eae, 0x053e561a, 0x15ad6f8c, -0x66626c1c, 0x7154c24c, 0xea082b2a, 0x93eb2939, 0x17dcb0f0, 0x58d4f2ae, 0x9ea294fb, 0x52cf564c, -0x9883fe66, 0x2ec40581, 0x763953c3, 0x01d6692e, 0xd3a0c108, 0xa1e7160e, 0xe4f2dfa6, 0x693ed285, -0x74904698, 0x4c2b0edd, 0x4f757656, 0x5d393378, 0xa132234f, 0x3d321c5d, 0xc3f5e194, 0x4b269301, -0xc79f022f, 0x3c997e7e, 0x5e4f9504, 0x3ffafbbd, 0x76f7ad0e, 0x296693f4, 0x3d1fce6f, 0xc61e45be, -0xd3b5ab34, 0xf72bf9b7, 0x1b0434c0, 0x4e72b567, 0x5592a33d, 0xb5229301, 0xcfd2a87f, 0x60aeb767, -0x1814386b, 0x30bcc33d, 0x38a0c07d, 0xfd1606f2, 0xc363519b, 0x589dd390, 0x5479f8e6, 0x1cb8d647, -0x97fd61a9, 0xea7759f4, 0x2d57539d, 0x569a58cf, 0xe84e63ad, 0x462e1b78, 0x6580f87e, 0xf3817914, -0x91da55f4, 0x40a230f3, 0xd1988f35, 0xb6e318d2, 0x3ffa50bc, 0x3d40f021, 0xc3c0bdae, 0x4958c24c, -0x518f36b2, 0x84b1d370, 0x0fedce83, 0x878ddada, 0xf2a279c7, 0x94e01be8, 0x90716f4b, 0x954b8aa3, -}; - -static const uint32_t S8[256] = { -0xe216300d, 0xbbddfffc, 0xa7ebdabd, 0x35648095, 0x7789f8b7, 0xe6c1121b, 0x0e241600, 0x052ce8b5, -0x11a9cfb0, 0xe5952f11, 0xece7990a, 0x9386d174, 0x2a42931c, 0x76e38111, 0xb12def3a, 0x37ddddfc, -0xde9adeb1, 0x0a0cc32c, 0xbe197029, 0x84a00940, 0xbb243a0f, 0xb4d137cf, 0xb44e79f0, 0x049eedfd, -0x0b15a15d, 0x480d3168, 0x8bbbde5a, 0x669ded42, 0xc7ece831, 0x3f8f95e7, 0x72df191b, 0x7580330d, -0x94074251, 0x5c7dcdfa, 0xabbe6d63, 0xaa402164, 0xb301d40a, 0x02e7d1ca, 0x53571dae, 0x7a3182a2, -0x12a8ddec, 0xfdaa335d, 0x176f43e8, 0x71fb46d4, 0x38129022, 0xce949ad4, 0xb84769ad, 0x965bd862, -0x82f3d055, 0x66fb9767, 0x15b80b4e, 0x1d5b47a0, 0x4cfde06f, 0xc28ec4b8, 0x57e8726e, 0x647a78fc, -0x99865d44, 0x608bd593, 0x6c200e03, 0x39dc5ff6, 0x5d0b00a3, 0xae63aff2, 0x7e8bd632, 0x70108c0c, -0xbbd35049, 0x2998df04, 0x980cf42a, 0x9b6df491, 0x9e7edd53, 0x06918548, 0x58cb7e07, 0x3b74ef2e, -0x522fffb1, 0xd24708cc, 0x1c7e27cd, 0xa4eb215b, 0x3cf1d2e2, 0x19b47a38, 0x424f7618, 0x35856039, -0x9d17dee7, 0x27eb35e6, 0xc9aff67b, 0x36baf5b8, 0x09c467cd, 0xc18910b1, 0xe11dbf7b, 0x06cd1af8, -0x7170c608, 0x2d5e3354, 0xd4de495a, 0x64c6d006, 0xbcc0c62c, 0x3dd00db3, 0x708f8f34, 0x77d51b42, -0x264f620f, 0x24b8d2bf, 0x15c1b79e, 0x46a52564, 0xf8d7e54e, 0x3e378160, 0x7895cda5, 0x859c15a5, -0xe6459788, 0xc37bc75f, 0xdb07ba0c, 0x0676a3ab, 0x7f229b1e, 0x31842e7b, 0x24259fd7, 0xf8bef472, -0x835ffcb8, 0x6df4c1f2, 0x96f5b195, 0xfd0af0fc, 0xb0fe134c, 0xe2506d3d, 0x4f9b12ea, 0xf215f225, -0xa223736f, 0x9fb4c428, 0x25d04979, 0x34c713f8, 0xc4618187, 0xea7a6e98, 0x7cd16efc, 0x1436876c, -0xf1544107, 0xbedeee14, 0x56e9af27, 0xa04aa441, 0x3cf7c899, 0x92ecbae6, 0xdd67016d, 0x151682eb, -0xa842eedf, 0xfdba60b4, 0xf1907b75, 0x20e3030f, 0x24d8c29e, 0xe139673b, 0xefa63fb8, 0x71873054, -0xb6f2cf3b, 0x9f326442, 0xcb15a4cc, 0xb01a4504, 0xf1e47d8d, 0x844a1be5, 0xbae7dfdc, 0x42cbda70, -0xcd7dae0a, 0x57e85b7a, 0xd53f5af6, 0x20cf4d8c, 0xcea4d428, 0x79d130a4, 0x3486ebfb, 0x33d3cddc, -0x77853b53, 0x37effcb5, 0xc5068778, 0xe580b3e6, 0x4e68b8f4, 0xc5c8b37e, 0x0d809ea2, 0x398feb7c, -0x132a4f94, 0x43b7950e, 0x2fee7d1c, 0x223613bd, 0xdd06caa2, 0x37df932b, 0xc4248289, 0xacf3ebc3, -0x5715f6b7, 0xef3478dd, 0xf267616f, 0xc148cbe4, 0x9052815e, 0x5e410fab, 0xb48a2465, 0x2eda7fa4, -0xe87b40e4, 0xe98ea084, 0x5889e9e1, 0xefd390fc, 0xdd07d35b, 0xdb485694, 0x38d7e5b2, 0x57720101, -0x730edebc, 0x5b643113, 0x94917e4f, 0x503c2fba, 0x646f1282, 0x7523d24a, 0xe0779695, 0xf9c17a8f, -0x7a5b2121, 0xd187b896, 0x29263a4d, 0xba510cdf, 0x81f47c9f, 0xad1163ed, 0xea7b5965, 0x1a00726e, -0x11403092, 0x00da6d77, 0x4a0cdd61, 0xad1f4603, 0x605bdfb0, 0x9eedc364, 0x22ebe6a8, 0xcee7d28a, -0xa0e736a0, 0x5564a6b9, 0x10853209, 0xc7eb8f37, 0x2de705ca, 0x8951570f, 0xdf09822b, 0xbd691a6c, -0xaa12e4f2, 0x87451c0f, 0xe0f6a27a, 0x3ada4819, 0x4cf1764f, 0x0d771c2b, 0x67cdb156, 0x350d8384, -0x5938fa0f, 0x42399ef3, 0x36997b07, 0x0e84093d, 0x4aa93e61, 0x8360d87b, 0x1fa98b0c, 0x1149382c, -0xe97625a5, 0x0614d1b7, 0x0e25244b, 0x0c768347, 0x589e8d82, 0x0d2059d1, 0xa466bb1e, 0xf8da0a82, -0x04f19130, 0xba6e4ec0, 0x99265164, 0x1ee7230d, 0x50b2ad80, 0xeaee6801, 0x8db2a283, 0xea8bf59e, -}; diff --git a/plugins/Dbx_tree/encryption/CAST128/Cast128.vcxproj b/plugins/Dbx_tree/encryption/CAST128/Cast128.vcxproj new file mode 100644 index 0000000000..76acf68f31 --- /dev/null +++ b/plugins/Dbx_tree/encryption/CAST128/Cast128.vcxproj @@ -0,0 +1,171 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + Dbx_tree_Cast128 + {7E88D7F5-8B0A-4B79-84CD-D7982D4E0D4D} + + + + DynamicLibrary + Unicode + + + DynamicLibrary + Unicode + + + DynamicLibrary + Unicode + true + + + DynamicLibrary + Unicode + true + + + + + + + + + + <_ProjectFileVersion>10.0.20506.1 + $(SolutionDir)$(Configuration)\Plugins\Encryption\ + $(SolutionDir)$(Configuration)64\Plugins\Encryption\ + $(SolutionDir)$(Configuration)\Obj\$(ProjectName)\ + $(SolutionDir)$(Configuration)64\Obj\$(ProjectName)\ + $(SolutionDir)$(Configuration)\Plugins\Encryption\ + $(SolutionDir)$(Configuration)64\Plugins\Encryption\ + $(SolutionDir)$(Configuration)\Obj\$(ProjectName)\ + $(SolutionDir)$(Configuration)64\Obj\$(ProjectName)\ + true + Cast128 + Cast128 + Cast128 + Cast128 + + + + Disabled + WIN32;_DEBUG;_WINDOWS;_USRDLL;CAST128_EXPORTS;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + Level3 + ..\Common + EditAndContinue + true + true + Fast + + + true + Windows + $(IntDir)$(TargetName).lib + false + $(SolutionDir)\lib + + + + + Disabled + WIN64;_DEBUG;_WINDOWS;_USRDLL;CAST128_EXPORTS;%(PreprocessorDefinitions) + EnableFastChecks + MultiThreadedDebugDLL + Level3 + ..\Common + true + true + true + Fast + + + true + Windows + $(IntDir)$(TargetName).lib + false + $(SolutionDir)\lib + + + + + Full + AnySuitable + Size + WIN32;NDEBUG;_WINDOWS;_USRDLL;CAST128_EXPORTS;%(PreprocessorDefinitions) + true + Level3 + ..\Common + true + true + Fast + + + true + Windows + true + true + $(IntDir)$(TargetName).lib + false + $(SolutionDir)\lib + /PDBALTPATH:%_PDB% + + + + + Full + AnySuitable + Size + WIN64;NDEBUG;_WINDOWS;_USRDLL;CAST128_EXPORTS;%(PreprocessorDefinitions) + true + Level3 + ..\Common + true + true + Fast + + + true + Windows + true + true + $(IntDir)$(TargetName).lib + false + $(SolutionDir)\lib + /PDBALTPATH:%_PDB% + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/plugins/Dbx_tree/encryption/CAST128/Cast128.vcxproj.filters b/plugins/Dbx_tree/encryption/CAST128/Cast128.vcxproj.filters new file mode 100644 index 0000000000..f23057e4ba --- /dev/null +++ b/plugins/Dbx_tree/encryption/CAST128/Cast128.vcxproj.filters @@ -0,0 +1,35 @@ + + + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + + + Source Files + + + + + Header Files + + + Header Files + + + + + Header Files + + + \ No newline at end of file diff --git a/plugins/Dbx_tree/encryption/CAST128/src/CAST128.cpp b/plugins/Dbx_tree/encryption/CAST128/src/CAST128.cpp new file mode 100644 index 0000000000..2814a4142b --- /dev/null +++ b/plugins/Dbx_tree/encryption/CAST128/src/CAST128.cpp @@ -0,0 +1,260 @@ +/* + +dbx_tree: tree database driver for Miranda IM + +Copyright 2007-2008 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 "CAST128.h" +#include "CAST128.inc" + +const wchar_t * CAST128::Name() +{ + return cName; +} +const wchar_t * CAST128::Description() +{ + return cDescription; +} +const uint32_t CAST128::BlockSizeBytes() +{ + return cBlockSizeBytes; +} +const bool CAST128::IsStreamCipher() +{ + return cIsStreamCipher; +} + +CAST128::CAST128() +{ + +} +CAST128::~CAST128() +{ + +} +CCipher::TCipherInterface* CAST128::Create() +{ + return (new CAST128())->m_Interface; +} + +void CAST128::SetKey(void* Key, uint32_t KeyLength) +{ + uint8_t k128[16] = "Mirandadbx_tree"; + int i = 0; + uint8_t* k = (uint8_t*) Key; + while (KeyLength > 0) + { + k128[i] = k128[i] ^ (*k); + i = (i + 1) % 16; + ++k; + --KeyLength; + } + CreateSubKeys(k128); +} +void CAST128::Encrypt(void* Data, uint32_t Size, uint32_t Nonce, uint32_t StartByte) +{ + for (uint32_t i = 0; i <= Size - BlockSizeBytes(); i += BlockSizeBytes()) + { + EncryptBlock((uint8_t*)Data + i); + StartByte += BlockSizeBytes(); + } +} +void CAST128::Decrypt(void* Data, uint32_t Size, uint32_t Nonce, uint32_t StartByte) +{ + for (uint32_t i = 0; i <= Size - BlockSizeBytes(); i += BlockSizeBytes()) + { + DecryptBlock((uint8_t*)Data + i); + StartByte += BlockSizeBytes(); + } +} + +void CAST128::CreateSubKeys(uint8_t* Key) +{ + union { + uint8_t z[16]; + uint32_t i[4]; + } t; + + uint32_t* k; + k = (uint32_t*) Key; + + t.i[0] = k[0] ^ S5[Key[0xD]] ^ S6[Key[0xF]] ^ S7[Key[0xC]] ^ S8[Key[0xE]] ^ S7[Key[0x8]]; + t.i[1] = k[2] ^ S5[t.z[0x0]] ^ S6[t.z[0x2]] ^ S7[t.z[0x1]] ^ S8[t.z[0x3]] ^ S8[Key[0xA]]; + t.i[2] = k[3] ^ S5[t.z[0x7]] ^ S6[t.z[0x6]] ^ S7[t.z[0x5]] ^ S8[t.z[0x4]] ^ S5[Key[0x9]]; + t.i[3] = k[1] ^ S5[t.z[0xA]] ^ S6[t.z[0x9]] ^ S7[t.z[0xB]] ^ S8[t.z[0x8]] ^ S6[Key[0xB]]; + + Km[0x0] = S5[t.z[0x8]] ^ S6[t.z[0x9]] ^ S7[t.z[0x7]] ^ S8[t.z[0x6]] ^ S5[t.z[0x2]]; + Km[0x1] = S5[t.z[0xA]] ^ S6[t.z[0xB]] ^ S7[t.z[0x5]] ^ S8[t.z[0x4]] ^ S6[t.z[0x6]]; + Km[0x2] = S5[t.z[0xC]] ^ S6[t.z[0xD]] ^ S7[t.z[0x3]] ^ S8[t.z[0x2]] ^ S7[t.z[0x9]]; + Km[0x3] = S5[t.z[0xE]] ^ S6[t.z[0xF]] ^ S7[t.z[0x1]] ^ S8[t.z[0x0]] ^ S8[t.z[0xC]]; + + k[0] = t.i[2] ^ S5[t.z[0x5]] ^ S6[t.z[0x7]] ^ S7[t.z[0x4]] ^ S8[t.z[0x6]] ^ S7[t.z[0x0]]; + k[1] = t.i[0] ^ S5[Key[0x0]] ^ S6[Key[0x2]] ^ S7[Key[0x1]] ^ S8[Key[0x3]] ^ S8[t.z[0x2]]; + k[2] = t.i[1] ^ S5[Key[0x7]] ^ S6[Key[0x6]] ^ S7[Key[0x5]] ^ S8[Key[0x4]] ^ S5[t.z[0x1]]; + k[3] = t.i[3] ^ S5[Key[0xA]] ^ S6[Key[0x9]] ^ S7[Key[0xB]] ^ S8[Key[0x8]] ^ S6[t.z[0x3]]; + + Km[0x4] = S5[Key[0x3]] ^ S6[Key[0x2]] ^ S7[Key[0xC]] ^ S8[Key[0xD]] ^ S5[Key[0x8]]; + Km[0x5] = S5[Key[0x1]] ^ S6[Key[0x0]] ^ S7[Key[0xE]] ^ S8[Key[0xF]] ^ S6[Key[0xD]]; + Km[0x6] = S5[Key[0x7]] ^ S6[Key[0x6]] ^ S7[Key[0x8]] ^ S8[Key[0x9]] ^ S7[Key[0x3]]; + Km[0x7] = S5[Key[0x5]] ^ S6[Key[0x4]] ^ S7[Key[0xA]] ^ S8[Key[0xB]] ^ S8[Key[0x7]]; + + t.i[0] = k[0] ^ S5[Key[0xD]] ^ S6[Key[0xF]] ^ S7[Key[0xC]] ^ S8[Key[0xE]] ^ S7[Key[0x8]]; + t.i[1] = k[2] ^ S5[t.z[0x0]] ^ S6[t.z[0x2]] ^ S7[t.z[0x1]] ^ S8[t.z[0x3]] ^ S8[Key[0xA]]; + t.i[2] = k[3] ^ S5[t.z[0x7]] ^ S6[t.z[0x6]] ^ S7[t.z[0x5]] ^ S8[t.z[0x4]] ^ S5[Key[0x9]]; + t.i[3] = k[1] ^ S5[t.z[0xA]] ^ S6[t.z[0x9]] ^ S7[t.z[0xB]] ^ S8[t.z[0x8]] ^ S6[Key[0xB]]; + + Km[0x8] = S5[t.z[0x3]] ^ S6[t.z[0x2]] ^ S7[t.z[0xC]] ^ S8[t.z[0xD]] ^ S5[t.z[0x9]]; + Km[0x9] = S5[t.z[0x1]] ^ S6[t.z[0x0]] ^ S7[t.z[0xE]] ^ S8[t.z[0xF]] ^ S6[t.z[0xC]]; + Km[0xa] = S5[t.z[0x7]] ^ S6[t.z[0x6]] ^ S7[t.z[0x8]] ^ S8[t.z[0x9]] ^ S7[t.z[0x2]]; + Km[0xb] = S5[t.z[0x5]] ^ S6[t.z[0x4]] ^ S7[t.z[0xA]] ^ S8[t.z[0xB]] ^ S8[t.z[0x6]]; + + k[0] = t.i[2] ^ S5[t.z[0x5]] ^ S6[t.z[0x7]] ^ S7[t.z[0x4]] ^ S8[t.z[0x6]] ^ S7[t.z[0x0]]; + k[1] = t.i[0] ^ S5[Key[0x0]] ^ S6[Key[0x2]] ^ S7[Key[0x1]] ^ S8[Key[0x3]] ^ S8[t.z[0x2]]; + k[2] = t.i[1] ^ S5[Key[0x7]] ^ S6[Key[0x6]] ^ S7[Key[0x5]] ^ S8[Key[0x4]] ^ S5[t.z[0x1]]; + k[3] = t.i[3] ^ S5[Key[0xA]] ^ S6[Key[0x9]] ^ S7[Key[0xB]] ^ S8[Key[0x8]] ^ S6[t.z[0x3]]; + + Km[0xc] = S5[Key[0x8]] ^ S6[Key[0x9]] ^ S7[Key[0x7]] ^ S8[Key[0x6]] ^ S5[Key[0x3]]; + Km[0xd] = S5[Key[0xA]] ^ S6[Key[0xB]] ^ S7[Key[0x5]] ^ S8[Key[0x4]] ^ S6[Key[0x7]]; + Km[0xe] = S5[Key[0xC]] ^ S6[Key[0xD]] ^ S7[Key[0x3]] ^ S8[Key[0x2]] ^ S7[Key[0x8]]; + Km[0xf] = S5[Key[0xE]] ^ S6[Key[0xF]] ^ S7[Key[0x1]] ^ S8[Key[0x0]] ^ S8[Key[0xD]]; + + + + t.i[0] = k[0] ^ S5[Key[0xD]] ^ S6[Key[0xF]] ^ S7[Key[0xC]] ^ S8[Key[0xE]] ^ S7[Key[0x8]]; + t.i[1] = k[2] ^ S5[t.z[0x0]] ^ S6[t.z[0x2]] ^ S7[t.z[0x1]] ^ S8[t.z[0x3]] ^ S8[Key[0xA]]; + t.i[2] = k[3] ^ S5[t.z[0x7]] ^ S6[t.z[0x6]] ^ S7[t.z[0x5]] ^ S8[t.z[0x4]] ^ S5[Key[0x9]]; + t.i[3] = k[1] ^ S5[t.z[0xA]] ^ S6[t.z[0x9]] ^ S7[t.z[0xB]] ^ S8[t.z[0x8]] ^ S6[Key[0xB]]; + + Kr[0x0] = S5[t.z[0x8]] ^ S6[t.z[0x9]] ^ S7[t.z[0x7]] ^ S8[t.z[0x6]] ^ S5[t.z[0x2]]; + Kr[0x1] = S5[t.z[0xA]] ^ S6[t.z[0xB]] ^ S7[t.z[0x5]] ^ S8[t.z[0x4]] ^ S6[t.z[0x6]]; + Kr[0x2] = S5[t.z[0xC]] ^ S6[t.z[0xD]] ^ S7[t.z[0x3]] ^ S8[t.z[0x2]] ^ S7[t.z[0x9]]; + Kr[0x3] = S5[t.z[0xE]] ^ S6[t.z[0xF]] ^ S7[t.z[0x1]] ^ S8[t.z[0x0]] ^ S8[t.z[0xC]]; + + k[0] = t.i[2] ^ S5[t.z[0x5]] ^ S6[t.z[0x7]] ^ S7[t.z[0x4]] ^ S8[t.z[0x6]] ^ S7[t.z[0x0]]; + k[1] = t.i[0] ^ S5[Key[0x0]] ^ S6[Key[0x2]] ^ S7[Key[0x1]] ^ S8[Key[0x3]] ^ S8[t.z[0x2]]; + k[2] = t.i[1] ^ S5[Key[0x7]] ^ S6[Key[0x6]] ^ S7[Key[0x5]] ^ S8[Key[0x4]] ^ S5[t.z[0x1]]; + k[3] = t.i[3] ^ S5[Key[0xA]] ^ S6[Key[0x9]] ^ S7[Key[0xB]] ^ S8[Key[0x8]] ^ S6[t.z[0x3]]; + + Kr[0x4] = S5[Key[0x3]] ^ S6[Key[0x2]] ^ S7[Key[0xC]] ^ S8[Key[0xD]] ^ S5[Key[0x8]]; + Kr[0x5] = S5[Key[0x1]] ^ S6[Key[0x0]] ^ S7[Key[0xE]] ^ S8[Key[0xF]] ^ S6[Key[0xD]]; + Kr[0x6] = S5[Key[0x7]] ^ S6[Key[0x6]] ^ S7[Key[0x8]] ^ S8[Key[0x9]] ^ S7[Key[0x3]]; + Kr[0x7] = S5[Key[0x5]] ^ S6[Key[0x4]] ^ S7[Key[0xA]] ^ S8[Key[0xB]] ^ S8[Key[0x7]]; + + t.i[0] = k[0] ^ S5[Key[0xD]] ^ S6[Key[0xF]] ^ S7[Key[0xC]] ^ S8[Key[0xE]] ^ S7[Key[0x8]]; + t.i[1] = k[2] ^ S5[t.z[0x0]] ^ S6[t.z[0x2]] ^ S7[t.z[0x1]] ^ S8[t.z[0x3]] ^ S8[Key[0xA]]; + t.i[2] = k[3] ^ S5[t.z[0x7]] ^ S6[t.z[0x6]] ^ S7[t.z[0x5]] ^ S8[t.z[0x4]] ^ S5[Key[0x9]]; + t.i[3] = k[1] ^ S5[t.z[0xA]] ^ S6[t.z[0x9]] ^ S7[t.z[0xB]] ^ S8[t.z[0x8]] ^ S6[Key[0xB]]; + + Kr[0x8] = S5[t.z[0x3]] ^ S6[t.z[0x2]] ^ S7[t.z[0xC]] ^ S8[t.z[0xD]] ^ S5[t.z[0x9]]; + Kr[0x9] = S5[t.z[0x1]] ^ S6[t.z[0x0]] ^ S7[t.z[0xE]] ^ S8[t.z[0xF]] ^ S6[t.z[0xC]]; + Kr[0xa] = S5[t.z[0x7]] ^ S6[t.z[0x6]] ^ S7[t.z[0x8]] ^ S8[t.z[0x9]] ^ S7[t.z[0x2]]; + Kr[0xb] = S5[t.z[0x5]] ^ S6[t.z[0x4]] ^ S7[t.z[0xA]] ^ S8[t.z[0xB]] ^ S8[t.z[0x6]]; + + k[0] = t.i[2] ^ S5[t.z[0x5]] ^ S6[t.z[0x7]] ^ S7[t.z[0x4]] ^ S8[t.z[0x6]] ^ S7[t.z[0x0]]; + k[1] = t.i[0] ^ S5[Key[0x0]] ^ S6[Key[0x2]] ^ S7[Key[0x1]] ^ S8[Key[0x3]] ^ S8[t.z[0x2]]; + k[2] = t.i[1] ^ S5[Key[0x7]] ^ S6[Key[0x6]] ^ S7[Key[0x5]] ^ S8[Key[0x4]] ^ S5[t.z[0x1]]; + k[3] = t.i[3] ^ S5[Key[0xA]] ^ S6[Key[0x9]] ^ S7[Key[0xB]] ^ S8[Key[0x8]] ^ S6[t.z[0x3]]; + + Kr[0xc] = S5[Key[0x8]] ^ S6[Key[0x9]] ^ S7[Key[0x7]] ^ S8[Key[0x6]] ^ S5[Key[0x3]]; + Kr[0xd] = S5[Key[0xA]] ^ S6[Key[0xB]] ^ S7[Key[0x5]] ^ S8[Key[0x4]] ^ S6[Key[0x7]]; + Kr[0xe] = S5[Key[0xC]] ^ S6[Key[0xD]] ^ S7[Key[0x3]] ^ S8[Key[0x2]] ^ S7[Key[0x8]]; + Kr[0xf] = S5[Key[0xE]] ^ S6[Key[0xF]] ^ S7[Key[0x1]] ^ S8[Key[0x0]] ^ S8[Key[0xD]]; + + + for (int i = 0; i < 16; i++) + Kr[i] = Kr[i] & 0x0000001F; +} + + +inline void CAST128::EncryptBlock(uint8_t *Block) +{ + uint32_t l, r, tmp; + union { + uint8_t byte[4]; + uint32_t block; + } t; + + l = ((uint32_t*)Block)[0]; + r = ((uint32_t*)Block)[1]; + + for (int i = 0; i < 16; i++) + { + if ((i % 3) == 0) + { + t.block = (t.block << Kr[i]) | (t.block >> (32 - Kr[i])); + t.block = ((S1[t.byte[0]] ^ S2[t.byte[1]]) - S3[t.byte[2]]) + S4[t.byte[3]]; + } else if ((i % 3) == 1) + { + t.block = (t.block << Kr[i]) | (t.block >> (32 - Kr[i])); + t.block = ((S1[t.byte[0]] - S2[t.byte[1]]) + S3[t.byte[2]]) ^ S4[t.byte[3]]; + } else { + t.block = (t.block << Kr[i]) | (t.block >> (32 - Kr[i])); + t.block = ((S1[t.byte[0]] + S2[t.byte[1]]) ^ S3[t.byte[2]]) - S4[t.byte[3]]; + } + + tmp = r; + r = l ^ t.block; + l = tmp; + } + + ((uint32_t*)Block)[0] = l; + ((uint32_t*)Block)[1] = r; +} + + + +inline void CAST128::DecryptBlock(uint8_t *Block) +{ + uint32_t l, r, tmp; + union { + uint8_t byte[4]; + uint32_t block; + } t; + + r = ((uint32_t*)Block)[0]; + l = ((uint32_t*)Block)[1]; + + for (int i = 15; i >= 0; i--) + { + if ((i % 3) == 0) + { + t.block = (t.block << Kr[i]) | (t.block >> (32 - Kr[i])); + t.block = ((S1[t.byte[0]] ^ S2[t.byte[1]]) - S3[t.byte[2]]) + S4[t.byte[3]]; + } else if ((i % 3) == 1) + { + t.block = (t.block << Kr[i]) | (t.block >> (32 - Kr[i])); + t.block = ((S1[t.byte[0]] - S2[t.byte[1]]) + S3[t.byte[2]]) ^ S4[t.byte[3]]; + } else { + t.block = (t.block << Kr[i]) | (t.block >> (32 - Kr[i])); + t.block = ((S1[t.byte[0]] + S2[t.byte[1]]) ^ S3[t.byte[2]]) - S4[t.byte[3]]; + } + + tmp = r; + r = l ^ t.block; + l = tmp; + } + + ((uint32_t*)Block)[0] = r; + ((uint32_t*)Block)[1] = l; +} + +extern "C" __declspec(dllexport) const TCipherInfo* CipherInfo(void * Reserved) +{ + return &CAST128::cCipherInfo; +} diff --git a/plugins/Dbx_tree/encryption/CAST128/src/CAST128.h b/plugins/Dbx_tree/encryption/CAST128/src/CAST128.h new file mode 100644 index 0000000000..9477254986 --- /dev/null +++ b/plugins/Dbx_tree/encryption/CAST128/src/CAST128.h @@ -0,0 +1,61 @@ +/* + +dbx_tree: tree database driver for Miranda IM + +Copyright 2007-2008 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. + +*/ + +#pragma once + +#include "Cipher.h" + +class CAST128 : public CCipher +{ +private: + uint32_t Km[16], Kr[16]; + + void EncryptBlock(uint8_t *Block); + void DecryptBlock(uint8_t *Block); + void CreateSubKeys(uint8_t* Key); + + static const wchar_t* cName; + static const wchar_t* cDescription; + static const uint32_t cBlockSizeBytes = 8; + static const bool cIsStreamCipher = false; + +public: + const wchar_t * __cdecl Name(); + const wchar_t * __cdecl Description(); + const uint32_t __cdecl BlockSizeBytes(); + const bool __cdecl IsStreamCipher(); + + static const TCipherInfo cCipherInfo; + + CAST128(); + ~CAST128(); + static CCipher::TCipherInterface* __cdecl Create(); + + void __cdecl SetKey(void* Key, uint32_t KeyLength); + void __cdecl Encrypt(void* Data, uint32_t Size, uint32_t Nonce, uint32_t StartByte); + void __cdecl Decrypt(void* Data, uint32_t Size, uint32_t Nonce, uint32_t StartByte); + +}; + +const wchar_t* CAST128::cName = L"Cast128"; +const wchar_t* CAST128::cDescription = L"Blockcipher - 64bit block, fast and secure, Carlisle Adams and Stafford Tavares 1996"; +const TCipherInfo CAST128::cCipherInfo = {sizeof(TCipherInfo), 'Cast', cName, cDescription, &CAST128::Create}; diff --git a/plugins/Dbx_tree/encryption/CAST128/src/CAST128.inc b/plugins/Dbx_tree/encryption/CAST128/src/CAST128.inc new file mode 100644 index 0000000000..8389acc92c --- /dev/null +++ b/plugins/Dbx_tree/encryption/CAST128/src/CAST128.inc @@ -0,0 +1,302 @@ +/* + +dbx_tree: tree database driver for Miranda IM + +Copyright 2007-2008 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. + +*/ + + +static const uint32_t S1[256] = { +0x30fb40d4, 0x9fa0ff0b, 0x6beccd2f, 0x3f258c7a, 0x1e213f2f, 0x9c004dd3, 0x6003e540, 0xcf9fc949, +0xbfd4af27, 0x88bbbdb5, 0xe2034090, 0x98d09675, 0x6e63a0e0, 0x15c361d2, 0xc2e7661d, 0x22d4ff8e, +0x28683b6f, 0xc07fd059, 0xff2379c8, 0x775f50e2, 0x43c340d3, 0xdf2f8656, 0x887ca41a, 0xa2d2bd2d, +0xa1c9e0d6, 0x346c4819, 0x61b76d87, 0x22540f2f, 0x2abe32e1, 0xaa54166b, 0x22568e3a, 0xa2d341d0, +0x66db40c8, 0xa784392f, 0x004dff2f, 0x2db9d2de, 0x97943fac, 0x4a97c1d8, 0x527644b7, 0xb5f437a7, +0xb82cbaef, 0xd751d159, 0x6ff7f0ed, 0x5a097a1f, 0x827b68d0, 0x90ecf52e, 0x22b0c054, 0xbc8e5935, +0x4b6d2f7f, 0x50bb64a2, 0xd2664910, 0xbee5812d, 0xb7332290, 0xe93b159f, 0xb48ee411, 0x4bff345d, +0xfd45c240, 0xad31973f, 0xc4f6d02e, 0x55fc8165, 0xd5b1caad, 0xa1ac2dae, 0xa2d4b76d, 0xc19b0c50, +0x882240f2, 0x0c6e4f38, 0xa4e4bfd7, 0x4f5ba272, 0x564c1d2f, 0xc59c5319, 0xb949e354, 0xb04669fe, +0xb1b6ab8a, 0xc71358dd, 0x6385c545, 0x110f935d, 0x57538ad5, 0x6a390493, 0xe63d37e0, 0x2a54f6b3, +0x3a787d5f, 0x6276a0b5, 0x19a6fcdf, 0x7a42206a, 0x29f9d4d5, 0xf61b1891, 0xbb72275e, 0xaa508167, +0x38901091, 0xc6b505eb, 0x84c7cb8c, 0x2ad75a0f, 0x874a1427, 0xa2d1936b, 0x2ad286af, 0xaa56d291, +0xd7894360, 0x425c750d, 0x93b39e26, 0x187184c9, 0x6c00b32d, 0x73e2bb14, 0xa0bebc3c, 0x54623779, +0x64459eab, 0x3f328b82, 0x7718cf82, 0x59a2cea6, 0x04ee002e, 0x89fe78e6, 0x3fab0950, 0x325ff6c2, +0x81383f05, 0x6963c5c8, 0x76cb5ad6, 0xd49974c9, 0xca180dcf, 0x380782d5, 0xc7fa5cf6, 0x8ac31511, +0x35e79e13, 0x47da91d0, 0xf40f9086, 0xa7e2419e, 0x31366241, 0x051ef495, 0xaa573b04, 0x4a805d8d, +0x548300d0, 0x00322a3c, 0xbf64cddf, 0xba57a68e, 0x75c6372b, 0x50afd341, 0xa7c13275, 0x915a0bf5, +0x6b54bfab, 0x2b0b1426, 0xab4cc9d7, 0x449ccd82, 0xf7fbf265, 0xab85c5f3, 0x1b55db94, 0xaad4e324, +0xcfa4bd3f, 0x2deaa3e2, 0x9e204d02, 0xc8bd25ac, 0xeadf55b3, 0xd5bd9e98, 0xe31231b2, 0x2ad5ad6c, +0x954329de, 0xadbe4528, 0xd8710f69, 0xaa51c90f, 0xaa786bf6, 0x22513f1e, 0xaa51a79b, 0x2ad344cc, +0x7b5a41f0, 0xd37cfbad, 0x1b069505, 0x41ece491, 0xb4c332e6, 0x032268d4, 0xc9600acc, 0xce387e6d, +0xbf6bb16c, 0x6a70fb78, 0x0d03d9c9, 0xd4df39de, 0xe01063da, 0x4736f464, 0x5ad328d8, 0xb347cc96, +0x75bb0fc3, 0x98511bfb, 0x4ffbcc35, 0xb58bcf6a, 0xe11f0abc, 0xbfc5fe4a, 0xa70aec10, 0xac39570a, +0x3f04442f, 0x6188b153, 0xe0397a2e, 0x5727cb79, 0x9ceb418f, 0x1cacd68d, 0x2ad37c96, 0x0175cb9d, +0xc69dff09, 0xc75b65f0, 0xd9db40d8, 0xec0e7779, 0x4744ead4, 0xb11c3274, 0xdd24cb9e, 0x7e1c54bd, +0xf01144f9, 0xd2240eb1, 0x9675b3fd, 0xa3ac3755, 0xd47c27af, 0x51c85f4d, 0x56907596, 0xa5bb15e6, +0x580304f0, 0xca042cf1, 0x011a37ea, 0x8dbfaadb, 0x35ba3e4a, 0x3526ffa0, 0xc37b4d09, 0xbc306ed9, +0x98a52666, 0x5648f725, 0xff5e569d, 0x0ced63d0, 0x7c63b2cf, 0x700b45e1, 0xd5ea50f1, 0x85a92872, +0xaf1fbda7, 0xd4234870, 0xa7870bf3, 0x2d3b4d79, 0x42e04198, 0x0cd0ede7, 0x26470db8, 0xf881814c, +0x474d6ad7, 0x7c0c5e5c, 0xd1231959, 0x381b7298, 0xf5d2f4db, 0xab838653, 0x6e2f1e23, 0x83719c9e, +0xbd91e046, 0x9a56456e, 0xdc39200c, 0x20c8c571, 0x962bda1c, 0xe1e696ff, 0xb141ab08, 0x7cca89b9, +0x1a69e783, 0x02cc4843, 0xa2f7c579, 0x429ef47d, 0x427b169c, 0x5ac9f049, 0xdd8f0f00, 0x5c8165bf, +}; + +static const uint32_t S2[256] = { +0x1f201094, 0xef0ba75b, 0x69e3cf7e, 0x393f4380, 0xfe61cf7a, 0xeec5207a, 0x55889c94, 0x72fc0651, +0xada7ef79, 0x4e1d7235, 0xd55a63ce, 0xde0436ba, 0x99c430ef, 0x5f0c0794, 0x18dcdb7d, 0xa1d6eff3, +0xa0b52f7b, 0x59e83605, 0xee15b094, 0xe9ffd909, 0xdc440086, 0xef944459, 0xba83ccb3, 0xe0c3cdfb, +0xd1da4181, 0x3b092ab1, 0xf997f1c1, 0xa5e6cf7b, 0x01420ddb, 0xe4e7ef5b, 0x25a1ff41, 0xe180f806, +0x1fc41080, 0x179bee7a, 0xd37ac6a9, 0xfe5830a4, 0x98de8b7f, 0x77e83f4e, 0x79929269, 0x24fa9f7b, +0xe113c85b, 0xacc40083, 0xd7503525, 0xf7ea615f, 0x62143154, 0x0d554b63, 0x5d681121, 0xc866c359, +0x3d63cf73, 0xcee234c0, 0xd4d87e87, 0x5c672b21, 0x071f6181, 0x39f7627f, 0x361e3084, 0xe4eb573b, +0x602f64a4, 0xd63acd9c, 0x1bbc4635, 0x9e81032d, 0x2701f50c, 0x99847ab4, 0xa0e3df79, 0xba6cf38c, +0x10843094, 0x2537a95e, 0xf46f6ffe, 0xa1ff3b1f, 0x208cfb6a, 0x8f458c74, 0xd9e0a227, 0x4ec73a34, +0xfc884f69, 0x3e4de8df, 0xef0e0088, 0x3559648d, 0x8a45388c, 0x1d804366, 0x721d9bfd, 0xa58684bb, +0xe8256333, 0x844e8212, 0x128d8098, 0xfed33fb4, 0xce280ae1, 0x27e19ba5, 0xd5a6c252, 0xe49754bd, +0xc5d655dd, 0xeb667064, 0x77840b4d, 0xa1b6a801, 0x84db26a9, 0xe0b56714, 0x21f043b7, 0xe5d05860, +0x54f03084, 0x066ff472, 0xa31aa153, 0xdadc4755, 0xb5625dbf, 0x68561be6, 0x83ca6b94, 0x2d6ed23b, +0xeccf01db, 0xa6d3d0ba, 0xb6803d5c, 0xaf77a709, 0x33b4a34c, 0x397bc8d6, 0x5ee22b95, 0x5f0e5304, +0x81ed6f61, 0x20e74364, 0xb45e1378, 0xde18639b, 0x881ca122, 0xb96726d1, 0x8049a7e8, 0x22b7da7b, +0x5e552d25, 0x5272d237, 0x79d2951c, 0xc60d894c, 0x488cb402, 0x1ba4fe5b, 0xa4b09f6b, 0x1ca815cf, +0xa20c3005, 0x8871df63, 0xb9de2fcb, 0x0cc6c9e9, 0x0beeff53, 0xe3214517, 0xb4542835, 0x9f63293c, +0xee41e729, 0x6e1d2d7c, 0x50045286, 0x1e6685f3, 0xf33401c6, 0x30a22c95, 0x31a70850, 0x60930f13, +0x73f98417, 0xa1269859, 0xec645c44, 0x52c877a9, 0xcdff33a6, 0xa02b1741, 0x7cbad9a2, 0x2180036f, +0x50d99c08, 0xcb3f4861, 0xc26bd765, 0x64a3f6ab, 0x80342676, 0x25a75e7b, 0xe4e6d1fc, 0x20c710e6, +0xcdf0b680, 0x17844d3b, 0x31eef84d, 0x7e0824e4, 0x2ccb49eb, 0x846a3bae, 0x8ff77888, 0xee5d60f6, +0x7af75673, 0x2fdd5cdb, 0xa11631c1, 0x30f66f43, 0xb3faec54, 0x157fd7fa, 0xef8579cc, 0xd152de58, +0xdb2ffd5e, 0x8f32ce19, 0x306af97a, 0x02f03ef8, 0x99319ad5, 0xc242fa0f, 0xa7e3ebb0, 0xc68e4906, +0xb8da230c, 0x80823028, 0xdcdef3c8, 0xd35fb171, 0x088a1bc8, 0xbec0c560, 0x61a3c9e8, 0xbca8f54d, +0xc72feffa, 0x22822e99, 0x82c570b4, 0xd8d94e89, 0x8b1c34bc, 0x301e16e6, 0x273be979, 0xb0ffeaa6, +0x61d9b8c6, 0x00b24869, 0xb7ffce3f, 0x08dc283b, 0x43daf65a, 0xf7e19798, 0x7619b72f, 0x8f1c9ba4, +0xdc8637a0, 0x16a7d3b1, 0x9fc393b7, 0xa7136eeb, 0xc6bcc63e, 0x1a513742, 0xef6828bc, 0x520365d6, +0x2d6a77ab, 0x3527ed4b, 0x821fd216, 0x095c6e2e, 0xdb92f2fb, 0x5eea29cb, 0x145892f5, 0x91584f7f, +0x5483697b, 0x2667a8cc, 0x85196048, 0x8c4bacea, 0x833860d4, 0x0d23e0f9, 0x6c387e8a, 0x0ae6d249, +0xb284600c, 0xd835731d, 0xdcb1c647, 0xac4c56ea, 0x3ebd81b3, 0x230eabb0, 0x6438bc87, 0xf0b5b1fa, +0x8f5ea2b3, 0xfc184642, 0x0a036b7a, 0x4fb089bd, 0x649da589, 0xa345415e, 0x5c038323, 0x3e5d3bb9, +0x43d79572, 0x7e6dd07c, 0x06dfdf1e, 0x6c6cc4ef, 0x7160a539, 0x73bfbe70, 0x83877605, 0x4523ecf1, +}; + +static const uint32_t S3[256] = { +0x8defc240, 0x25fa5d9f, 0xeb903dbf, 0xe810c907, 0x47607fff, 0x369fe44b, 0x8c1fc644, 0xaececa90, +0xbeb1f9bf, 0xeefbcaea, 0xe8cf1950, 0x51df07ae, 0x920e8806, 0xf0ad0548, 0xe13c8d83, 0x927010d5, +0x11107d9f, 0x07647db9, 0xb2e3e4d4, 0x3d4f285e, 0xb9afa820, 0xfade82e0, 0xa067268b, 0x8272792e, +0x553fb2c0, 0x489ae22b, 0xd4ef9794, 0x125e3fbc, 0x21fffcee, 0x825b1bfd, 0x9255c5ed, 0x1257a240, +0x4e1a8302, 0xbae07fff, 0x528246e7, 0x8e57140e, 0x3373f7bf, 0x8c9f8188, 0xa6fc4ee8, 0xc982b5a5, +0xa8c01db7, 0x579fc264, 0x67094f31, 0xf2bd3f5f, 0x40fff7c1, 0x1fb78dfc, 0x8e6bd2c1, 0x437be59b, +0x99b03dbf, 0xb5dbc64b, 0x638dc0e6, 0x55819d99, 0xa197c81c, 0x4a012d6e, 0xc5884a28, 0xccc36f71, +0xb843c213, 0x6c0743f1, 0x8309893c, 0x0feddd5f, 0x2f7fe850, 0xd7c07f7e, 0x02507fbf, 0x5afb9a04, +0xa747d2d0, 0x1651192e, 0xaf70bf3e, 0x58c31380, 0x5f98302e, 0x727cc3c4, 0x0a0fb402, 0x0f7fef82, +0x8c96fdad, 0x5d2c2aae, 0x8ee99a49, 0x50da88b8, 0x8427f4a0, 0x1eac5790, 0x796fb449, 0x8252dc15, +0xefbd7d9b, 0xa672597d, 0xada840d8, 0x45f54504, 0xfa5d7403, 0xe83ec305, 0x4f91751a, 0x925669c2, +0x23efe941, 0xa903f12e, 0x60270df2, 0x0276e4b6, 0x94fd6574, 0x927985b2, 0x8276dbcb, 0x02778176, +0xf8af918d, 0x4e48f79e, 0x8f616ddf, 0xe29d840e, 0x842f7d83, 0x340ce5c8, 0x96bbb682, 0x93b4b148, +0xef303cab, 0x984faf28, 0x779faf9b, 0x92dc560d, 0x224d1e20, 0x8437aa88, 0x7d29dc96, 0x2756d3dc, +0x8b907cee, 0xb51fd240, 0xe7c07ce3, 0xe566b4a1, 0xc3e9615e, 0x3cf8209d, 0x6094d1e3, 0xcd9ca341, +0x5c76460e, 0x00ea983b, 0xd4d67881, 0xfd47572c, 0xf76cedd9, 0xbda8229c, 0x127dadaa, 0x438a074e, +0x1f97c090, 0x081bdb8a, 0x93a07ebe, 0xb938ca15, 0x97b03cff, 0x3dc2c0f8, 0x8d1ab2ec, 0x64380e51, +0x68cc7bfb, 0xd90f2788, 0x12490181, 0x5de5ffd4, 0xdd7ef86a, 0x76a2e214, 0xb9a40368, 0x925d958f, +0x4b39fffa, 0xba39aee9, 0xa4ffd30b, 0xfaf7933b, 0x6d498623, 0x193cbcfa, 0x27627545, 0x825cf47a, +0x61bd8ba0, 0xd11e42d1, 0xcead04f4, 0x127ea392, 0x10428db7, 0x8272a972, 0x9270c4a8, 0x127de50b, +0x285ba1c8, 0x3c62f44f, 0x35c0eaa5, 0xe805d231, 0x428929fb, 0xb4fcdf82, 0x4fb66a53, 0x0e7dc15b, +0x1f081fab, 0x108618ae, 0xfcfd086d, 0xf9ff2889, 0x694bcc11, 0x236a5cae, 0x12deca4d, 0x2c3f8cc5, +0xd2d02dfe, 0xf8ef5896, 0xe4cf52da, 0x95155b67, 0x494a488c, 0xb9b6a80c, 0x5c8f82bc, 0x89d36b45, +0x3a609437, 0xec00c9a9, 0x44715253, 0x0a874b49, 0xd773bc40, 0x7c34671c, 0x02717ef6, 0x4feb5536, +0xa2d02fff, 0xd2bf60c4, 0xd43f03c0, 0x50b4ef6d, 0x07478cd1, 0x006e1888, 0xa2e53f55, 0xb9e6d4bc, +0xa2048016, 0x97573833, 0xd7207d67, 0xde0f8f3d, 0x72f87b33, 0xabcc4f33, 0x7688c55d, 0x7b00a6b0, +0x947b0001, 0x570075d2, 0xf9bb88f8, 0x8942019e, 0x4264a5ff, 0x856302e0, 0x72dbd92b, 0xee971b69, +0x6ea22fde, 0x5f08ae2b, 0xaf7a616d, 0xe5c98767, 0xcf1febd2, 0x61efc8c2, 0xf1ac2571, 0xcc8239c2, +0x67214cb8, 0xb1e583d1, 0xb7dc3e62, 0x7f10bdce, 0xf90a5c38, 0x0ff0443d, 0x606e6dc6, 0x60543a49, +0x5727c148, 0x2be98a1d, 0x8ab41738, 0x20e1be24, 0xaf96da0f, 0x68458425, 0x99833be5, 0x600d457d, +0x282f9350, 0x8334b362, 0xd91d1120, 0x2b6d8da0, 0x642b1e31, 0x9c305a00, 0x52bce688, 0x1b03588a, +0xf7baefd5, 0x4142ed9c, 0xa4315c11, 0x83323ec5, 0xdfef4636, 0xa133c501, 0xe9d3531c, 0xee353783, +}; + +static const uint32_t S4[256] = { +0x9db30420, 0x1fb6e9de, 0xa7be7bef, 0xd273a298, 0x4a4f7bdb, 0x64ad8c57, 0x85510443, 0xfa020ed1, +0x7e287aff, 0xe60fb663, 0x095f35a1, 0x79ebf120, 0xfd059d43, 0x6497b7b1, 0xf3641f63, 0x241e4adf, +0x28147f5f, 0x4fa2b8cd, 0xc9430040, 0x0cc32220, 0xfdd30b30, 0xc0a5374f, 0x1d2d00d9, 0x24147b15, +0xee4d111a, 0x0fca5167, 0x71ff904c, 0x2d195ffe, 0x1a05645f, 0x0c13fefe, 0x081b08ca, 0x05170121, +0x80530100, 0xe83e5efe, 0xac9af4f8, 0x7fe72701, 0xd2b8ee5f, 0x06df4261, 0xbb9e9b8a, 0x7293ea25, +0xce84ffdf, 0xf5718801, 0x3dd64b04, 0xa26f263b, 0x7ed48400, 0x547eebe6, 0x446d4ca0, 0x6cf3d6f5, +0x2649abdf, 0xaea0c7f5, 0x36338cc1, 0x503f7e93, 0xd3772061, 0x11b638e1, 0x72500e03, 0xf80eb2bb, +0xabe0502e, 0xec8d77de, 0x57971e81, 0xe14f6746, 0xc9335400, 0x6920318f, 0x081dbb99, 0xffc304a5, +0x4d351805, 0x7f3d5ce3, 0xa6c866c6, 0x5d5bcca9, 0xdaec6fea, 0x9f926f91, 0x9f46222f, 0x3991467d, +0xa5bf6d8e, 0x1143c44f, 0x43958302, 0xd0214eeb, 0x022083b8, 0x3fb6180c, 0x18f8931e, 0x281658e6, +0x26486e3e, 0x8bd78a70, 0x7477e4c1, 0xb506e07c, 0xf32d0a25, 0x79098b02, 0xe4eabb81, 0x28123b23, +0x69dead38, 0x1574ca16, 0xdf871b62, 0x211c40b7, 0xa51a9ef9, 0x0014377b, 0x041e8ac8, 0x09114003, +0xbd59e4d2, 0xe3d156d5, 0x4fe876d5, 0x2f91a340, 0x557be8de, 0x00eae4a7, 0x0ce5c2ec, 0x4db4bba6, +0xe756bdff, 0xdd3369ac, 0xec17b035, 0x06572327, 0x99afc8b0, 0x56c8c391, 0x6b65811c, 0x5e146119, +0x6e85cb75, 0xbe07c002, 0xc2325577, 0x893ff4ec, 0x5bbfc92d, 0xd0ec3b25, 0xb7801ab7, 0x8d6d3b24, +0x20c763ef, 0xc366a5fc, 0x9c382880, 0x0ace3205, 0xaac9548a, 0xeca1d7c7, 0x041afa32, 0x1d16625a, +0x6701902c, 0x9b757a54, 0x31d477f7, 0x9126b031, 0x36cc6fdb, 0xc70b8b46, 0xd9e66a48, 0x56e55a79, +0x026a4ceb, 0x52437eff, 0x2f8f76b4, 0x0df980a5, 0x8674cde3, 0xedda04eb, 0x17a9be04, 0x2c18f4df, +0xb7747f9d, 0xab2af7b4, 0xefc34d20, 0x2e096b7c, 0x1741a254, 0xe5b6a035, 0x213d42f6, 0x2c1c7c26, +0x61c2f50f, 0x6552daf9, 0xd2c231f8, 0x25130f69, 0xd8167fa2, 0x0418f2c8, 0x001a96a6, 0x0d1526ab, +0x63315c21, 0x5e0a72ec, 0x49bafefd, 0x187908d9, 0x8d0dbd86, 0x311170a7, 0x3e9b640c, 0xcc3e10d7, +0xd5cad3b6, 0x0caec388, 0xf73001e1, 0x6c728aff, 0x71eae2a1, 0x1f9af36e, 0xcfcbd12f, 0xc1de8417, +0xac07be6b, 0xcb44a1d8, 0x8b9b0f56, 0x013988c3, 0xb1c52fca, 0xb4be31cd, 0xd8782806, 0x12a3a4e2, +0x6f7de532, 0x58fd7eb6, 0xd01ee900, 0x24adffc2, 0xf4990fc5, 0x9711aac5, 0x001d7b95, 0x82e5e7d2, +0x109873f6, 0x00613096, 0xc32d9521, 0xada121ff, 0x29908415, 0x7fbb977f, 0xaf9eb3db, 0x29c9ed2a, +0x5ce2a465, 0xa730f32c, 0xd0aa3fe8, 0x8a5cc091, 0xd49e2ce7, 0x0ce454a9, 0xd60acd86, 0x015f1919, +0x77079103, 0xdea03af6, 0x78a8565e, 0xdee356df, 0x21f05cbe, 0x8b75e387, 0xb3c50651, 0xb8a5c3ef, +0xd8eeb6d2, 0xe523be77, 0xc2154529, 0x2f69efdf, 0xafe67afb, 0xf470c4b2, 0xf3e0eb5b, 0xd6cc9876, +0x39e4460c, 0x1fda8538, 0x1987832f, 0xca007367, 0xa99144f8, 0x296b299e, 0x492fc295, 0x9266beab, +0xb5676e69, 0x9bd3ddda, 0xdf7e052f, 0xdb25701c, 0x1b5e51ee, 0xf65324e6, 0x6afce36c, 0x0316cc04, +0x8644213e, 0xb7dc59d0, 0x7965291f, 0xccd6fd43, 0x41823979, 0x932bcdf6, 0xb657c34d, 0x4edfd282, +0x7ae5290c, 0x3cb9536b, 0x851e20fe, 0x9833557e, 0x13ecf0b0, 0xd3ffb372, 0x3f85c5c1, 0x0aef7ed2, +}; + +static const uint32_t S5[256] = { +0x7ec90c04, 0x2c6e74b9, 0x9b0e66df, 0xa6337911, 0xb86a7fff, 0x1dd358f5, 0x44dd9d44, 0x1731167f, +0x08fbf1fa, 0xe7f511cc, 0xd2051b00, 0x735aba00, 0x2ab722d8, 0x386381cb, 0xacf6243a, 0x69befd7a, +0xe6a2e77f, 0xf0c720cd, 0xc4494816, 0xccf5c180, 0x38851640, 0x15b0a848, 0xe68b18cb, 0x4caadeff, +0x5f480a01, 0x0412b2aa, 0x259814fc, 0x41d0efe2, 0x4e40b48d, 0x248eb6fb, 0x8dba1cfe, 0x41a99b02, +0x1a550a04, 0xba8f65cb, 0x7251f4e7, 0x95a51725, 0xc106ecd7, 0x97a5980a, 0xc539b9aa, 0x4d79fe6a, +0xf2f3f763, 0x68af8040, 0xed0c9e56, 0x11b4958b, 0xe1eb5a88, 0x8709e6b0, 0xd7e07156, 0x4e29fea7, +0x6366e52d, 0x02d1c000, 0xc4ac8e05, 0x9377f571, 0x0c05372a, 0x578535f2, 0x2261be02, 0xd642a0c9, +0xdf13a280, 0x74b55bd2, 0x682199c0, 0xd421e5ec, 0x53fb3ce8, 0xc8adedb3, 0x28a87fc9, 0x3d959981, +0x5c1ff900, 0xfe38d399, 0x0c4eff0b, 0x062407ea, 0xaa2f4fb1, 0x4fb96976, 0x90c79505, 0xb0a8a774, +0xef55a1ff, 0xe59ca2c2, 0xa6b62d27, 0xe66a4263, 0xdf65001f, 0x0ec50966, 0xdfdd55bc, 0x29de0655, +0x911e739a, 0x17af8975, 0x32c7911c, 0x89f89468, 0x0d01e980, 0x524755f4, 0x03b63cc9, 0x0cc844b2, +0xbcf3f0aa, 0x87ac36e9, 0xe53a7426, 0x01b3d82b, 0x1a9e7449, 0x64ee2d7e, 0xcddbb1da, 0x01c94910, +0xb868bf80, 0x0d26f3fd, 0x9342ede7, 0x04a5c284, 0x636737b6, 0x50f5b616, 0xf24766e3, 0x8eca36c1, +0x136e05db, 0xfef18391, 0xfb887a37, 0xd6e7f7d4, 0xc7fb7dc9, 0x3063fcdf, 0xb6f589de, 0xec2941da, +0x26e46695, 0xb7566419, 0xf654efc5, 0xd08d58b7, 0x48925401, 0xc1bacb7f, 0xe5ff550f, 0xb6083049, +0x5bb5d0e8, 0x87d72e5a, 0xab6a6ee1, 0x223a66ce, 0xc62bf3cd, 0x9e0885f9, 0x68cb3e47, 0x086c010f, +0xa21de820, 0xd18b69de, 0xf3f65777, 0xfa02c3f6, 0x407edac3, 0xcbb3d550, 0x1793084d, 0xb0d70eba, +0x0ab378d5, 0xd951fb0c, 0xded7da56, 0x4124bbe4, 0x94ca0b56, 0x0f5755d1, 0xe0e1e56e, 0x6184b5be, +0x580a249f, 0x94f74bc0, 0xe327888e, 0x9f7b5561, 0xc3dc0280, 0x05687715, 0x646c6bd7, 0x44904db3, +0x66b4f0a3, 0xc0f1648a, 0x697ed5af, 0x49e92ff6, 0x309e374f, 0x2cb6356a, 0x85808573, 0x4991f840, +0x76f0ae02, 0x083be84d, 0x28421c9a, 0x44489406, 0x736e4cb8, 0xc1092910, 0x8bc95fc6, 0x7d869cf4, +0x134f616f, 0x2e77118d, 0xb31b2be1, 0xaa90b472, 0x3ca5d717, 0x7d161bba, 0x9cad9010, 0xaf462ba2, +0x9fe459d2, 0x45d34559, 0xd9f2da13, 0xdbc65487, 0xf3e4f94e, 0x176d486f, 0x097c13ea, 0x631da5c7, +0x445f7382, 0x175683f4, 0xcdc66a97, 0x70be0288, 0xb3cdcf72, 0x6e5dd2f3, 0x20936079, 0x459b80a5, +0xbe60e2db, 0xa9c23101, 0xeba5315c, 0x224e42f2, 0x1c5c1572, 0xf6721b2c, 0x1ad2fff3, 0x8c25404e, +0x324ed72f, 0x4067b7fd, 0x0523138e, 0x5ca3bc78, 0xdc0fd66e, 0x75922283, 0x784d6b17, 0x58ebb16e, +0x44094f85, 0x3f481d87, 0xfcfeae7b, 0x77b5ff76, 0x8c2302bf, 0xaaf47556, 0x5f46b02a, 0x2b092801, +0x3d38f5f7, 0x0ca81f36, 0x52af4a8a, 0x66d5e7c0, 0xdf3b0874, 0x95055110, 0x1b5ad7a8, 0xf61ed5ad, +0x6cf6e479, 0x20758184, 0xd0cefa65, 0x88f7be58, 0x4a046826, 0x0ff6f8f3, 0xa09c7f70, 0x5346aba0, +0x5ce96c28, 0xe176eda3, 0x6bac307f, 0x376829d2, 0x85360fa9, 0x17e3fe2a, 0x24b79767, 0xf5a96b20, +0xd6cd2595, 0x68ff1ebf, 0x7555442c, 0xf19f06be, 0xf9e0659a, 0xeeb9491d, 0x34010718, 0xbb30cab8, +0xe822fe15, 0x88570983, 0x750e6249, 0xda627e55, 0x5e76ffa8, 0xb1534546, 0x6d47de08, 0xefe9e7d4, +}; + +static const uint32_t S6[256] = { +0xf6fa8f9d, 0x2cac6ce1, 0x4ca34867, 0xe2337f7c, 0x95db08e7, 0x016843b4, 0xeced5cbc, 0x325553ac, +0xbf9f0960, 0xdfa1e2ed, 0x83f0579d, 0x63ed86b9, 0x1ab6a6b8, 0xde5ebe39, 0xf38ff732, 0x8989b138, +0x33f14961, 0xc01937bd, 0xf506c6da, 0xe4625e7e, 0xa308ea99, 0x4e23e33c, 0x79cbd7cc, 0x48a14367, +0xa3149619, 0xfec94bd5, 0xa114174a, 0xeaa01866, 0xa084db2d, 0x09a8486f, 0xa888614a, 0x2900af98, +0x01665991, 0xe1992863, 0xc8f30c60, 0x2e78ef3c, 0xd0d51932, 0xcf0fec14, 0xf7ca07d2, 0xd0a82072, +0xfd41197e, 0x9305a6b0, 0xe86be3da, 0x74bed3cd, 0x372da53c, 0x4c7f4448, 0xdab5d440, 0x6dba0ec3, +0x083919a7, 0x9fbaeed9, 0x49dbcfb0, 0x4e670c53, 0x5c3d9c01, 0x64bdb941, 0x2c0e636a, 0xba7dd9cd, +0xea6f7388, 0xe70bc762, 0x35f29adb, 0x5c4cdd8d, 0xf0d48d8c, 0xb88153e2, 0x08a19866, 0x1ae2eac8, +0x284caf89, 0xaa928223, 0x9334be53, 0x3b3a21bf, 0x16434be3, 0x9aea3906, 0xefe8c36e, 0xf890cdd9, +0x80226dae, 0xc340a4a3, 0xdf7e9c09, 0xa694a807, 0x5b7c5ecc, 0x221db3a6, 0x9a69a02f, 0x68818a54, +0xceb2296f, 0x53c0843a, 0xfe893655, 0x25bfe68a, 0xb4628abc, 0xcf222ebf, 0x25ac6f48, 0xa9a99387, +0x53bddb65, 0xe76ffbe7, 0xe967fd78, 0x0ba93563, 0x8e342bc1, 0xe8a11be9, 0x4980740d, 0xc8087dfc, +0x8de4bf99, 0xa11101a0, 0x7fd37975, 0xda5a26c0, 0xe81f994f, 0x9528cd89, 0xfd339fed, 0xb87834bf, +0x5f04456d, 0x22258698, 0xc9c4c83b, 0x2dc156be, 0x4f628daa, 0x57f55ec5, 0xe2220abe, 0xd2916ebf, +0x4ec75b95, 0x24f2c3c0, 0x42d15d99, 0xcd0d7fa0, 0x7b6e27ff, 0xa8dc8af0, 0x7345c106, 0xf41e232f, +0x35162386, 0xe6ea8926, 0x3333b094, 0x157ec6f2, 0x372b74af, 0x692573e4, 0xe9a9d848, 0xf3160289, +0x3a62ef1d, 0xa787e238, 0xf3a5f676, 0x74364853, 0x20951063, 0x4576698d, 0xb6fad407, 0x592af950, +0x36f73523, 0x4cfb6e87, 0x7da4cec0, 0x6c152daa, 0xcb0396a8, 0xc50dfe5d, 0xfcd707ab, 0x0921c42f, +0x89dff0bb, 0x5fe2be78, 0x448f4f33, 0x754613c9, 0x2b05d08d, 0x48b9d585, 0xdc049441, 0xc8098f9b, +0x7dede786, 0xc39a3373, 0x42410005, 0x6a091751, 0x0ef3c8a6, 0x890072d6, 0x28207682, 0xa9a9f7be, +0xbf32679d, 0xd45b5b75, 0xb353fd00, 0xcbb0e358, 0x830f220a, 0x1f8fb214, 0xd372cf08, 0xcc3c4a13, +0x8cf63166, 0x061c87be, 0x88c98f88, 0x6062e397, 0x47cf8e7a, 0xb6c85283, 0x3cc2acfb, 0x3fc06976, +0x4e8f0252, 0x64d8314d, 0xda3870e3, 0x1e665459, 0xc10908f0, 0x513021a5, 0x6c5b68b7, 0x822f8aa0, +0x3007cd3e, 0x74719eef, 0xdc872681, 0x073340d4, 0x7e432fd9, 0x0c5ec241, 0x8809286c, 0xf592d891, +0x08a930f6, 0x957ef305, 0xb7fbffbd, 0xc266e96f, 0x6fe4ac98, 0xb173ecc0, 0xbc60b42a, 0x953498da, +0xfba1ae12, 0x2d4bd736, 0x0f25faab, 0xa4f3fceb, 0xe2969123, 0x257f0c3d, 0x9348af49, 0x361400bc, +0xe8816f4a, 0x3814f200, 0xa3f94043, 0x9c7a54c2, 0xbc704f57, 0xda41e7f9, 0xc25ad33a, 0x54f4a084, +0xb17f5505, 0x59357cbe, 0xedbd15c8, 0x7f97c5ab, 0xba5ac7b5, 0xb6f6deaf, 0x3a479c3a, 0x5302da25, +0x653d7e6a, 0x54268d49, 0x51a477ea, 0x5017d55b, 0xd7d25d88, 0x44136c76, 0x0404a8c8, 0xb8e5a121, +0xb81a928a, 0x60ed5869, 0x97c55b96, 0xeaec991b, 0x29935913, 0x01fdb7f1, 0x088e8dfa, 0x9ab6f6f5, +0x3b4cbf9f, 0x4a5de3ab, 0xe6051d35, 0xa0e1d855, 0xd36b4cf1, 0xf544edeb, 0xb0e93524, 0xbebb8fbd, +0xa2d762cf, 0x49c92f54, 0x38b5f331, 0x7128a454, 0x48392905, 0xa65b1db8, 0x851c97bd, 0xd675cf2f, +}; + +static const uint32_t S7[256] = { +0x85e04019, 0x332bf567, 0x662dbfff, 0xcfc65693, 0x2a8d7f6f, 0xab9bc912, 0xde6008a1, 0x2028da1f, +0x0227bce7, 0x4d642916, 0x18fac300, 0x50f18b82, 0x2cb2cb11, 0xb232e75c, 0x4b3695f2, 0xb28707de, +0xa05fbcf6, 0xcd4181e9, 0xe150210c, 0xe24ef1bd, 0xb168c381, 0xfde4e789, 0x5c79b0d8, 0x1e8bfd43, +0x4d495001, 0x38be4341, 0x913cee1d, 0x92a79c3f, 0x089766be, 0xbaeeadf4, 0x1286becf, 0xb6eacb19, +0x2660c200, 0x7565bde4, 0x64241f7a, 0x8248dca9, 0xc3b3ad66, 0x28136086, 0x0bd8dfa8, 0x356d1cf2, +0x107789be, 0xb3b2e9ce, 0x0502aa8f, 0x0bc0351e, 0x166bf52a, 0xeb12ff82, 0xe3486911, 0xd34d7516, +0x4e7b3aff, 0x5f43671b, 0x9cf6e037, 0x4981ac83, 0x334266ce, 0x8c9341b7, 0xd0d854c0, 0xcb3a6c88, +0x47bc2829, 0x4725ba37, 0xa66ad22b, 0x7ad61f1e, 0x0c5cbafa, 0x4437f107, 0xb6e79962, 0x42d2d816, +0x0a961288, 0xe1a5c06e, 0x13749e67, 0x72fc081a, 0xb1d139f7, 0xf9583745, 0xcf19df58, 0xbec3f756, +0xc06eba30, 0x07211b24, 0x45c28829, 0xc95e317f, 0xbc8ec511, 0x38bc46e9, 0xc6e6fa14, 0xbae8584a, +0xad4ebc46, 0x468f508b, 0x7829435f, 0xf124183b, 0x821dba9f, 0xaff60ff4, 0xea2c4e6d, 0x16e39264, +0x92544a8b, 0x009b4fc3, 0xaba68ced, 0x9ac96f78, 0x06a5b79a, 0xb2856e6e, 0x1aec3ca9, 0xbe838688, +0x0e0804e9, 0x55f1be56, 0xe7e5363b, 0xb3a1f25d, 0xf7debb85, 0x61fe033c, 0x16746233, 0x3c034c28, +0xda6d0c74, 0x79aac56c, 0x3ce4e1ad, 0x51f0c802, 0x98f8f35a, 0x1626a49f, 0xeed82b29, 0x1d382fe3, +0x0c4fb99a, 0xbb325778, 0x3ec6d97b, 0x6e77a6a9, 0xcb658b5c, 0xd45230c7, 0x2bd1408b, 0x60c03eb7, +0xb9068d78, 0xa33754f4, 0xf430c87d, 0xc8a71302, 0xb96d8c32, 0xebd4e7be, 0xbe8b9d2d, 0x7979fb06, +0xe7225308, 0x8b75cf77, 0x11ef8da4, 0xe083c858, 0x8d6b786f, 0x5a6317a6, 0xfa5cf7a0, 0x5dda0033, +0xf28ebfb0, 0xf5b9c310, 0xa0eac280, 0x08b9767a, 0xa3d9d2b0, 0x79d34217, 0x021a718d, 0x9ac6336a, +0x2711fd60, 0x438050e3, 0x069908a8, 0x3d7fedc4, 0x826d2bef, 0x4eeb8476, 0x488dcf25, 0x36c9d566, +0x28e74e41, 0xc2610aca, 0x3d49a9cf, 0xbae3b9df, 0xb65f8de6, 0x92aeaf64, 0x3ac7d5e6, 0x9ea80509, +0xf22b017d, 0xa4173f70, 0xdd1e16c3, 0x15e0d7f9, 0x50b1b887, 0x2b9f4fd5, 0x625aba82, 0x6a017962, +0x2ec01b9c, 0x15488aa9, 0xd716e740, 0x40055a2c, 0x93d29a22, 0xe32dbf9a, 0x058745b9, 0x3453dc1e, +0xd699296e, 0x496cff6f, 0x1c9f4986, 0xdfe2ed07, 0xb87242d1, 0x19de7eae, 0x053e561a, 0x15ad6f8c, +0x66626c1c, 0x7154c24c, 0xea082b2a, 0x93eb2939, 0x17dcb0f0, 0x58d4f2ae, 0x9ea294fb, 0x52cf564c, +0x9883fe66, 0x2ec40581, 0x763953c3, 0x01d6692e, 0xd3a0c108, 0xa1e7160e, 0xe4f2dfa6, 0x693ed285, +0x74904698, 0x4c2b0edd, 0x4f757656, 0x5d393378, 0xa132234f, 0x3d321c5d, 0xc3f5e194, 0x4b269301, +0xc79f022f, 0x3c997e7e, 0x5e4f9504, 0x3ffafbbd, 0x76f7ad0e, 0x296693f4, 0x3d1fce6f, 0xc61e45be, +0xd3b5ab34, 0xf72bf9b7, 0x1b0434c0, 0x4e72b567, 0x5592a33d, 0xb5229301, 0xcfd2a87f, 0x60aeb767, +0x1814386b, 0x30bcc33d, 0x38a0c07d, 0xfd1606f2, 0xc363519b, 0x589dd390, 0x5479f8e6, 0x1cb8d647, +0x97fd61a9, 0xea7759f4, 0x2d57539d, 0x569a58cf, 0xe84e63ad, 0x462e1b78, 0x6580f87e, 0xf3817914, +0x91da55f4, 0x40a230f3, 0xd1988f35, 0xb6e318d2, 0x3ffa50bc, 0x3d40f021, 0xc3c0bdae, 0x4958c24c, +0x518f36b2, 0x84b1d370, 0x0fedce83, 0x878ddada, 0xf2a279c7, 0x94e01be8, 0x90716f4b, 0x954b8aa3, +}; + +static const uint32_t S8[256] = { +0xe216300d, 0xbbddfffc, 0xa7ebdabd, 0x35648095, 0x7789f8b7, 0xe6c1121b, 0x0e241600, 0x052ce8b5, +0x11a9cfb0, 0xe5952f11, 0xece7990a, 0x9386d174, 0x2a42931c, 0x76e38111, 0xb12def3a, 0x37ddddfc, +0xde9adeb1, 0x0a0cc32c, 0xbe197029, 0x84a00940, 0xbb243a0f, 0xb4d137cf, 0xb44e79f0, 0x049eedfd, +0x0b15a15d, 0x480d3168, 0x8bbbde5a, 0x669ded42, 0xc7ece831, 0x3f8f95e7, 0x72df191b, 0x7580330d, +0x94074251, 0x5c7dcdfa, 0xabbe6d63, 0xaa402164, 0xb301d40a, 0x02e7d1ca, 0x53571dae, 0x7a3182a2, +0x12a8ddec, 0xfdaa335d, 0x176f43e8, 0x71fb46d4, 0x38129022, 0xce949ad4, 0xb84769ad, 0x965bd862, +0x82f3d055, 0x66fb9767, 0x15b80b4e, 0x1d5b47a0, 0x4cfde06f, 0xc28ec4b8, 0x57e8726e, 0x647a78fc, +0x99865d44, 0x608bd593, 0x6c200e03, 0x39dc5ff6, 0x5d0b00a3, 0xae63aff2, 0x7e8bd632, 0x70108c0c, +0xbbd35049, 0x2998df04, 0x980cf42a, 0x9b6df491, 0x9e7edd53, 0x06918548, 0x58cb7e07, 0x3b74ef2e, +0x522fffb1, 0xd24708cc, 0x1c7e27cd, 0xa4eb215b, 0x3cf1d2e2, 0x19b47a38, 0x424f7618, 0x35856039, +0x9d17dee7, 0x27eb35e6, 0xc9aff67b, 0x36baf5b8, 0x09c467cd, 0xc18910b1, 0xe11dbf7b, 0x06cd1af8, +0x7170c608, 0x2d5e3354, 0xd4de495a, 0x64c6d006, 0xbcc0c62c, 0x3dd00db3, 0x708f8f34, 0x77d51b42, +0x264f620f, 0x24b8d2bf, 0x15c1b79e, 0x46a52564, 0xf8d7e54e, 0x3e378160, 0x7895cda5, 0x859c15a5, +0xe6459788, 0xc37bc75f, 0xdb07ba0c, 0x0676a3ab, 0x7f229b1e, 0x31842e7b, 0x24259fd7, 0xf8bef472, +0x835ffcb8, 0x6df4c1f2, 0x96f5b195, 0xfd0af0fc, 0xb0fe134c, 0xe2506d3d, 0x4f9b12ea, 0xf215f225, +0xa223736f, 0x9fb4c428, 0x25d04979, 0x34c713f8, 0xc4618187, 0xea7a6e98, 0x7cd16efc, 0x1436876c, +0xf1544107, 0xbedeee14, 0x56e9af27, 0xa04aa441, 0x3cf7c899, 0x92ecbae6, 0xdd67016d, 0x151682eb, +0xa842eedf, 0xfdba60b4, 0xf1907b75, 0x20e3030f, 0x24d8c29e, 0xe139673b, 0xefa63fb8, 0x71873054, +0xb6f2cf3b, 0x9f326442, 0xcb15a4cc, 0xb01a4504, 0xf1e47d8d, 0x844a1be5, 0xbae7dfdc, 0x42cbda70, +0xcd7dae0a, 0x57e85b7a, 0xd53f5af6, 0x20cf4d8c, 0xcea4d428, 0x79d130a4, 0x3486ebfb, 0x33d3cddc, +0x77853b53, 0x37effcb5, 0xc5068778, 0xe580b3e6, 0x4e68b8f4, 0xc5c8b37e, 0x0d809ea2, 0x398feb7c, +0x132a4f94, 0x43b7950e, 0x2fee7d1c, 0x223613bd, 0xdd06caa2, 0x37df932b, 0xc4248289, 0xacf3ebc3, +0x5715f6b7, 0xef3478dd, 0xf267616f, 0xc148cbe4, 0x9052815e, 0x5e410fab, 0xb48a2465, 0x2eda7fa4, +0xe87b40e4, 0xe98ea084, 0x5889e9e1, 0xefd390fc, 0xdd07d35b, 0xdb485694, 0x38d7e5b2, 0x57720101, +0x730edebc, 0x5b643113, 0x94917e4f, 0x503c2fba, 0x646f1282, 0x7523d24a, 0xe0779695, 0xf9c17a8f, +0x7a5b2121, 0xd187b896, 0x29263a4d, 0xba510cdf, 0x81f47c9f, 0xad1163ed, 0xea7b5965, 0x1a00726e, +0x11403092, 0x00da6d77, 0x4a0cdd61, 0xad1f4603, 0x605bdfb0, 0x9eedc364, 0x22ebe6a8, 0xcee7d28a, +0xa0e736a0, 0x5564a6b9, 0x10853209, 0xc7eb8f37, 0x2de705ca, 0x8951570f, 0xdf09822b, 0xbd691a6c, +0xaa12e4f2, 0x87451c0f, 0xe0f6a27a, 0x3ada4819, 0x4cf1764f, 0x0d771c2b, 0x67cdb156, 0x350d8384, +0x5938fa0f, 0x42399ef3, 0x36997b07, 0x0e84093d, 0x4aa93e61, 0x8360d87b, 0x1fa98b0c, 0x1149382c, +0xe97625a5, 0x0614d1b7, 0x0e25244b, 0x0c768347, 0x589e8d82, 0x0d2059d1, 0xa466bb1e, 0xf8da0a82, +0x04f19130, 0xba6e4ec0, 0x99265164, 0x1ee7230d, 0x50b2ad80, 0xeaee6801, 0x8db2a283, 0xea8bf59e, +}; diff --git a/plugins/Dbx_tree/encryption/Cast128.vcxproj b/plugins/Dbx_tree/encryption/Cast128.vcxproj deleted file mode 100644 index e9fbe2cd25..0000000000 --- a/plugins/Dbx_tree/encryption/Cast128.vcxproj +++ /dev/null @@ -1,163 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - Dbx_tree_Cast128 - {7E88D7F5-8B0A-4B79-84CD-D7982D4E0D4D} - - - - DynamicLibrary - Unicode - - - DynamicLibrary - Unicode - - - DynamicLibrary - Unicode - true - - - DynamicLibrary - Unicode - true - - - - - - - - - - <_ProjectFileVersion>10.0.20506.1 - $(SolutionDir)$(Configuration)\Plugins\Encryption\ - $(SolutionDir)$(Configuration)64\Plugins\Encryption\ - $(SolutionDir)$(Configuration)\Obj\$(ProjectName)\ - $(SolutionDir)$(Configuration)64\Obj\$(ProjectName)\ - $(SolutionDir)$(Configuration)\Plugins\Encryption\ - $(SolutionDir)$(Configuration)64\Plugins\Encryption\ - $(SolutionDir)$(Configuration)\Obj\$(ProjectName)\ - $(SolutionDir)$(Configuration)64\Obj\$(ProjectName)\ - true - - - - Disabled - WIN32;_DEBUG;_WINDOWS;_USRDLL;CAST128_EXPORTS;%(PreprocessorDefinitions) - true - EnableFastChecks - MultiThreadedDebugDLL - Level3 - EditAndContinue - true - true - Fast - - - true - Windows - $(IntDir)$(TargetName).lib - false - $(SolutionDir)\lib - - - - - Disabled - WIN64;_DEBUG;_WINDOWS;_USRDLL;CAST128_EXPORTS;%(PreprocessorDefinitions) - EnableFastChecks - MultiThreadedDebugDLL - Level3 - true - true - true - Fast - - - true - Windows - $(IntDir)$(TargetName).lib - false - $(SolutionDir)\lib - - - - - Full - AnySuitable - Size - WIN32;NDEBUG;_WINDOWS;_USRDLL;CAST128_EXPORTS;%(PreprocessorDefinitions) - true - Level3 - true - true - Fast - - - true - Windows - true - true - $(IntDir)$(TargetName).lib - false - $(SolutionDir)\lib - /PDBALTPATH:%_PDB% - - - - - Full - AnySuitable - Size - WIN64;NDEBUG;_WINDOWS;_USRDLL;CAST128_EXPORTS;%(PreprocessorDefinitions) - true - Level3 - true - true - Fast - - - true - Windows - true - true - $(IntDir)$(TargetName).lib - false - $(SolutionDir)\lib - /PDBALTPATH:%_PDB% - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/plugins/Dbx_tree/encryption/Cast128.vcxproj.filters b/plugins/Dbx_tree/encryption/Cast128.vcxproj.filters deleted file mode 100644 index 5c3548e7f6..0000000000 --- a/plugins/Dbx_tree/encryption/Cast128.vcxproj.filters +++ /dev/null @@ -1,35 +0,0 @@ - - - - - {93995380-89BD-4b04-88EB-625FBE52EBFB} - h;hpp;hxx;hm;inl;inc;xsd - - - {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} - rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx - - - - - Source Files - - - - - Header Files - - - Header Files - - - - - Header Files - - - \ No newline at end of file diff --git a/plugins/Dbx_tree/encryption/Cipher.h b/plugins/Dbx_tree/encryption/Cipher.h deleted file mode 100644 index 76d07e61a0..0000000000 --- a/plugins/Dbx_tree/encryption/Cipher.h +++ /dev/null @@ -1,180 +0,0 @@ -/* - -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. - -*/ - -#pragma once - -#ifdef _MSC_VER -#include "../stdint.h" -#else -#include -#endif - -#include - -#pragma pack(push, 1) - -#ifdef __INTERFACE_ONLY__ -#define __INTERFACE_VIRTUAL__ -#else -#define __INTERFACE_VIRTUAL__ virtual -#endif - -class CCipher -{ -public: - typedef struct TCipherInterface - { - CCipher * self; - uint32_t Size; - void (__cdecl CCipher::*Destroy)(); - - const wchar_t* (__cdecl CCipher::*Name)(); - const wchar_t* (__cdecl CCipher::*Description)(); - const uint32_t (__cdecl CCipher::*BlockSizeBytes)(); - const bool (__cdecl CCipher::*IsStreamCipher)(); - - void (__cdecl CCipher::*SetKey)(void* Key, uint32_t KeyLength); - void (__cdecl CCipher::*Encrypt)(void* Data, uint32_t Size, uint32_t Nonce, uint32_t StartByte); - void (__cdecl CCipher::*Decrypt)(void* Data, uint32_t Size, uint32_t Nonce, uint32_t StartByte); - - } TCipherInterface; - TCipherInterface * m_Interface; - -#ifndef __INTERFACE_ONLY__ - virtual void __cdecl Destroy() - { - delete this; - } - - CCipher() - { - m_Interface = new TCipherInterface; - m_Interface->Size = sizeof(TCipherInterface); - m_Interface->self = this; - m_Interface->Destroy = &CCipher::Destroy; - m_Interface->Name = &CCipher::Name; - m_Interface->Description = &CCipher::Description; - m_Interface->BlockSizeBytes = &CCipher::BlockSizeBytes; - m_Interface->IsStreamCipher = &CCipher::IsStreamCipher; - m_Interface->SetKey = &CCipher::SetKey; - m_Interface->Encrypt = &CCipher::Encrypt; - m_Interface->Decrypt = &CCipher::Decrypt; - }; -#endif - -#ifdef __INTERFACE_ONLY__ - CCipher(TCipherInterface * Interface) - { - m_Interface = Interface; - }; -#endif - - __INTERFACE_VIRTUAL__ ~CCipher() -#ifdef __INTERFACE_ONLY__ - { - (m_Interface->self->*(m_Interface->Destroy))(); - } -#else - { } -#endif - ; - - __INTERFACE_VIRTUAL__ const wchar_t* __cdecl Name() -#ifdef __INTERFACE_ONLY__ - { - return (m_Interface->self->*(m_Interface->Name))(); - } -#else - = 0 -#endif - ; - - __INTERFACE_VIRTUAL__ const wchar_t* __cdecl Description() -#ifdef __INTERFACE_ONLY__ - { - return (m_Interface->self->*(m_Interface->Description))(); - } -#else - = 0 -#endif - ; - - __INTERFACE_VIRTUAL__ const uint32_t __cdecl BlockSizeBytes() -#ifdef __INTERFACE_ONLY__ - { - return (m_Interface->self->*(m_Interface->BlockSizeBytes))(); - } -#else - = 0 -#endif - ; - - __INTERFACE_VIRTUAL__ const bool __cdecl IsStreamCipher() -#ifdef __INTERFACE_ONLY__ - { - return (m_Interface->self->*(m_Interface->IsStreamCipher))(); - } -#else - = 0 -#endif - ; - - __INTERFACE_VIRTUAL__ void __cdecl SetKey(void* Key, uint32_t KeyLength) -#ifdef __INTERFACE_ONLY__ - { - return (m_Interface->self->*(m_Interface->SetKey))(Key, KeyLength); - } -#else - = 0 -#endif - ; - __INTERFACE_VIRTUAL__ void __cdecl Encrypt(void* Data, uint32_t Size, uint32_t Nonce, uint32_t StartByte) -#ifdef __INTERFACE_ONLY__ - { - return (m_Interface->self->*(m_Interface->Encrypt))(Data, Size, Nonce, StartByte); - } -#else - = 0 -#endif - ; - __INTERFACE_VIRTUAL__ void __cdecl Decrypt(void* Data, uint32_t Size, uint32_t Nonce, uint32_t StartByte) -#ifdef __INTERFACE_ONLY__ - { - return (m_Interface->self->*(m_Interface->Decrypt))(Data, Size, Nonce, StartByte); - } -#else - = 0 -#endif - ; - -}; - -typedef struct TCipherInfo -{ - uint32_t cbSize; - const uint32_t ID; - const wchar_t* Name; - const wchar_t* Description; - CCipher::TCipherInterface * (__cdecl *Create)(); -} TCipherInfo; - -#pragma pack(pop) diff --git a/plugins/Dbx_tree/encryption/Common/Cipher.h b/plugins/Dbx_tree/encryption/Common/Cipher.h new file mode 100644 index 0000000000..abdcbf06be --- /dev/null +++ b/plugins/Dbx_tree/encryption/Common/Cipher.h @@ -0,0 +1,180 @@ +/* + +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. + +*/ + +#pragma once + +#ifdef _MSC_VER +#include "../../src/stdint.h" +#else +#include +#endif + +#include + +#pragma pack(push, 1) + +#ifdef __INTERFACE_ONLY__ +#define __INTERFACE_VIRTUAL__ +#else +#define __INTERFACE_VIRTUAL__ virtual +#endif + +class CCipher +{ +public: + typedef struct TCipherInterface + { + CCipher * self; + uint32_t Size; + void (__cdecl CCipher::*Destroy)(); + + const wchar_t* (__cdecl CCipher::*Name)(); + const wchar_t* (__cdecl CCipher::*Description)(); + const uint32_t (__cdecl CCipher::*BlockSizeBytes)(); + const bool (__cdecl CCipher::*IsStreamCipher)(); + + void (__cdecl CCipher::*SetKey)(void* Key, uint32_t KeyLength); + void (__cdecl CCipher::*Encrypt)(void* Data, uint32_t Size, uint32_t Nonce, uint32_t StartByte); + void (__cdecl CCipher::*Decrypt)(void* Data, uint32_t Size, uint32_t Nonce, uint32_t StartByte); + + } TCipherInterface; + TCipherInterface * m_Interface; + +#ifndef __INTERFACE_ONLY__ + virtual void __cdecl Destroy() + { + delete this; + } + + CCipher() + { + m_Interface = new TCipherInterface; + m_Interface->Size = sizeof(TCipherInterface); + m_Interface->self = this; + m_Interface->Destroy = &CCipher::Destroy; + m_Interface->Name = &CCipher::Name; + m_Interface->Description = &CCipher::Description; + m_Interface->BlockSizeBytes = &CCipher::BlockSizeBytes; + m_Interface->IsStreamCipher = &CCipher::IsStreamCipher; + m_Interface->SetKey = &CCipher::SetKey; + m_Interface->Encrypt = &CCipher::Encrypt; + m_Interface->Decrypt = &CCipher::Decrypt; + }; +#endif + +#ifdef __INTERFACE_ONLY__ + CCipher(TCipherInterface * Interface) + { + m_Interface = Interface; + }; +#endif + + __INTERFACE_VIRTUAL__ ~CCipher() +#ifdef __INTERFACE_ONLY__ + { + (m_Interface->self->*(m_Interface->Destroy))(); + } +#else + { } +#endif + ; + + __INTERFACE_VIRTUAL__ const wchar_t* __cdecl Name() +#ifdef __INTERFACE_ONLY__ + { + return (m_Interface->self->*(m_Interface->Name))(); + } +#else + = 0 +#endif + ; + + __INTERFACE_VIRTUAL__ const wchar_t* __cdecl Description() +#ifdef __INTERFACE_ONLY__ + { + return (m_Interface->self->*(m_Interface->Description))(); + } +#else + = 0 +#endif + ; + + __INTERFACE_VIRTUAL__ const uint32_t __cdecl BlockSizeBytes() +#ifdef __INTERFACE_ONLY__ + { + return (m_Interface->self->*(m_Interface->BlockSizeBytes))(); + } +#else + = 0 +#endif + ; + + __INTERFACE_VIRTUAL__ const bool __cdecl IsStreamCipher() +#ifdef __INTERFACE_ONLY__ + { + return (m_Interface->self->*(m_Interface->IsStreamCipher))(); + } +#else + = 0 +#endif + ; + + __INTERFACE_VIRTUAL__ void __cdecl SetKey(void* Key, uint32_t KeyLength) +#ifdef __INTERFACE_ONLY__ + { + return (m_Interface->self->*(m_Interface->SetKey))(Key, KeyLength); + } +#else + = 0 +#endif + ; + __INTERFACE_VIRTUAL__ void __cdecl Encrypt(void* Data, uint32_t Size, uint32_t Nonce, uint32_t StartByte) +#ifdef __INTERFACE_ONLY__ + { + return (m_Interface->self->*(m_Interface->Encrypt))(Data, Size, Nonce, StartByte); + } +#else + = 0 +#endif + ; + __INTERFACE_VIRTUAL__ void __cdecl Decrypt(void* Data, uint32_t Size, uint32_t Nonce, uint32_t StartByte) +#ifdef __INTERFACE_ONLY__ + { + return (m_Interface->self->*(m_Interface->Decrypt))(Data, Size, Nonce, StartByte); + } +#else + = 0 +#endif + ; + +}; + +typedef struct TCipherInfo +{ + uint32_t cbSize; + const uint32_t ID; + const wchar_t* Name; + const wchar_t* Description; + CCipher::TCipherInterface * (__cdecl *Create)(); +} TCipherInfo; + +#pragma pack(pop) diff --git a/plugins/Dbx_tree/encryption/HC256.cpp b/plugins/Dbx_tree/encryption/HC256.cpp deleted file mode 100644 index 056b4e4dae..0000000000 --- a/plugins/Dbx_tree/encryption/HC256.cpp +++ /dev/null @@ -1,243 +0,0 @@ -/* - -dbx_tree: tree database driver for Miranda IM - -Copyright 2007-2008 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 "HC256.h" -#include -#include - -#ifndef _MSC_VER - #define rotr(x,n) (((x)>>(n))|((x)<<(32-(n)))) -#else - #define rotr(x,n) _lrotr(x,n) -#endif - -#define h1(x,y) { \ - uint8_t a,b,c,d; \ - a = (uint8_t) (x); \ - b = (uint8_t) ((x) >> 8); \ - c = (uint8_t) ((x) >> 16); \ - d = (uint8_t) ((x) >> 24); \ - (y) = Q[a]+Q[256+b]+Q[512+c]+Q[768+d]; \ -} -#define h2(x,y) { \ - uint8_t a,b,c,d; \ - a = (uint8_t) (x); \ - b = (uint8_t) ((x) >> 8); \ - c = (uint8_t) ((x) >> 16); \ - d = (uint8_t) ((x) >> 24); \ - (y) = P[a]+P[256+b]+P[512+c]+P[768+d]; \ -} -#define step_A(u,v,a,b,c,d,m){ \ - uint32_t tem0,tem1,tem2,tem3; \ - tem0 = rotr((v),23); \ - tem1 = rotr((c),10); \ - tem2 = ((v) ^ (c)) & 0x3ff; \ - (u) += (b)+(tem0^tem1)+Q[tem2]; \ - (a) = (u); \ - h1((d),tem3); \ - (m) ^= tem3 ^ (u) ; \ -} -#define step_B(u,v,a,b,c,d,m){ \ - uint32_t tem0,tem1,tem2,tem3; \ - tem0 = rotr((v),23); \ - tem1 = rotr((c),10); \ - tem2 = ((v) ^ (c)) & 0x3ff; \ - (u) += (b)+(tem0^tem1)+P[tem2]; \ - (a) = (u); \ - h2((d),tem3); \ - (m) ^= tem3 ^ (u) ; \ -} - - -#define f1(x) (rotr((x),7) ^ rotr((x),18) ^ ((x) >> 3)) -#define f2(x) (rotr((x),17) ^ rotr((x),19) ^ ((x) >> 10)) -#define f(a,b,c,d) (f2((a)) + (b) + f1((c)) + (d)) -#define feedback_1(u,v,b,c) { \ - uint32_t tem0,tem1,tem2; \ - tem0 = rotr((v),23); \ - tem1 = rotr((c),10); \ - tem2 = ((v) ^ (c)) & 0x3ff; \ - (u) += (b)+(tem0^tem1)+Q[tem2]; \ -} -#define feedback_2(u,v,b,c) { \ - uint32_t tem0,tem1,tem2; \ - tem0 = rotr((v),23); \ - tem1 = rotr((c),10); \ - tem2 = ((v) ^ (c)) & 0x3ff; \ - (u) += (b)+(tem0^tem1)+P[tem2]; \ -} - -const wchar_t * HC256::Name() -{ - return cName; -} -const wchar_t * HC256::Description() -{ - return cDescription; -} -const uint32_t HC256::BlockSizeBytes() -{ - return cBlockSizeBytes; -} -const bool HC256::IsStreamCipher() -{ - return cIsStreamCipher; -} - -HC256::HC256() -{ - -} -HC256::~HC256() -{ - -} -CCipher::TCipherInterface* HC256::Create() -{ - return (new HC256())->m_Interface; -} - -void HC256::SetKey(void* Key, uint32_t KeyLength) -{ - uint8_t k[32] = {0}; - - for (uint32_t i = 0; i < KeyLength; ++i) - { - k[i & 0x1f] ^= ((uint8_t *)Key)[i]; - } - CreateTables(k); -} -void HC256::Encrypt(void* Data, uint32_t Size, uint32_t Nonce, uint32_t StartByte) -{ - memcpy(X, BackX, sizeof(X)); - memcpy(Y, BackY, sizeof(Y)); - memcpy(P, BackP, sizeof(P)); - memcpy(Q, BackQ, sizeof(Q)); - - counter2048 = (Nonce + (Nonce >> 11) + (Nonce >> 22)) & 0x7ff; - - for (uint32_t i = 0; i <= Size - BlockSizeBytes(); i += BlockSizeBytes()) - { - EncryptBlock((uint32_t*)((uint8_t*)Data + i)); - StartByte += BlockSizeBytes(); - } -} -void HC256::Decrypt(void* Data, uint32_t Size, uint32_t Nonce, uint32_t StartByte) -{ - Encrypt(Data, Size, Nonce, StartByte); -} - -inline void HC256::EncryptBlock(uint32_t *Data) -{ - uint32_t cc,dd; - cc = counter2048 & 0x3ff; - dd = (cc + 16) & 0x3ff; - if (counter2048 < 1024) - { - counter2048 = (counter2048 + 16) & 0x7ff; - step_A(P[cc+0], P[cc+1], X[0], X[6], X[13],X[4], Data[0]); - step_A(P[cc+1], P[cc+2], X[1], X[7], X[14],X[5], Data[1]); - step_A(P[cc+2], P[cc+3], X[2], X[8], X[15],X[6], Data[2]); - step_A(P[cc+3], P[cc+4], X[3], X[9], X[0], X[7], Data[3]); - step_A(P[cc+4], P[cc+5], X[4], X[10],X[1], X[8], Data[4]); - step_A(P[cc+5], P[cc+6], X[5], X[11],X[2], X[9], Data[5]); - step_A(P[cc+6], P[cc+7], X[6], X[12],X[3], X[10],Data[6]); - step_A(P[cc+7], P[cc+8], X[7], X[13],X[4], X[11],Data[7]); - step_A(P[cc+8], P[cc+9], X[8], X[14],X[5], X[12],Data[8]); - step_A(P[cc+9], P[cc+10],X[9], X[15],X[6], X[13],Data[9]); - step_A(P[cc+10],P[cc+11],X[10],X[0], X[7], X[14],Data[10]); - step_A(P[cc+11],P[cc+12],X[11],X[1], X[8], X[15],Data[11]); - step_A(P[cc+12],P[cc+13],X[12],X[2], X[9], X[0], Data[12]); - step_A(P[cc+13],P[cc+14],X[13],X[3], X[10],X[1], Data[13]); - step_A(P[cc+14],P[cc+15],X[14],X[4], X[11],X[2], Data[14]); - step_A(P[cc+15],P[dd+0], X[15],X[5], X[12],X[3], Data[15]); - - } else { - - counter2048 = (counter2048 + 16) & 0x7ff; - step_B(Q[cc+0], Q[cc+1], Y[0], Y[6], Y[13],Y[4], Data[0]); - step_B(Q[cc+1], Q[cc+2], Y[1], Y[7], Y[14],Y[5], Data[1]); - step_B(Q[cc+2], Q[cc+3], Y[2], Y[8], Y[15],Y[6], Data[2]); - step_B(Q[cc+3], Q[cc+4], Y[3], Y[9], Y[0], Y[7], Data[3]); - step_B(Q[cc+4], Q[cc+5], Y[4], Y[10],Y[1], Y[8], Data[4]); - step_B(Q[cc+5], Q[cc+6], Y[5], Y[11],Y[2], Y[9], Data[5]); - step_B(Q[cc+6], Q[cc+7], Y[6], Y[12],Y[3], Y[10],Data[6]); - step_B(Q[cc+7], Q[cc+8], Y[7], Y[13],Y[4], Y[11],Data[7]); - step_B(Q[cc+8], Q[cc+9], Y[8], Y[14],Y[5], Y[12],Data[8]); - step_B(Q[cc+9], Q[cc+10],Y[9], Y[15],Y[6], Y[13],Data[9]); - step_B(Q[cc+10],Q[cc+11],Y[10],Y[0], Y[7], Y[14],Data[10]); - step_B(Q[cc+11],Q[cc+12],Y[11],Y[1], Y[8], Y[15],Data[11]); - step_B(Q[cc+12],Q[cc+13],Y[12],Y[2], Y[9], Y[0], Data[12]); - step_B(Q[cc+13],Q[cc+14],Y[13],Y[3], Y[10],Y[1], Data[13]); - step_B(Q[cc+14],Q[cc+15],Y[14],Y[4], Y[11],Y[2], Data[14]); - step_B(Q[cc+15],Q[dd+0], Y[15],Y[5], Y[12],Y[3], Data[15]); - } -} -inline void HC256::CreateTables(uint8_t* Key) -{ - uint32_t i, j; - uint8_t iv[32] = "Miranda NG dbx_tree Protogenes!"; - //expand the key and iv into P and Q - for (i = 0; i < 8; i++) - P[i] = Key[i]; - for (i = 8; i < 16; i++) - P[i] = iv[i - 8]; - for (i = 16; i < 528; i++) - P[i] = f(P[i - 2], P[i - 7], P[i - 15], P[i - 16]) + i; - for (i = 0; i < 16; i++) - P[i] = P[i + 512]; - for (i = 16; i < 1024; i++) - P[i] = f(P[i - 2], P[i - 7], P[i - 15], P[i - 16]) + 512 + i; - for (i = 0; i < 16; i++) - Q[i] = P[1024 - 16 + i]; - for (i = 16; i < 32; i++) - Q[i] = f(Q[i - 2], Q[i - 7], Q[i - 15], Q[i - 16]) + 1520 + i; - for (i = 0; i < 16; i++) - Q[i] = Q[i + 16]; - for (i = 16; i < 1024;i++) - Q[i] = f(Q[i - 2], Q[i - 7], Q[i - 15], Q[i - 16]) + 1536 + i; - //run the cipher 4096 steps without generating output - for (i = 0; i < 2; i++) - { - for (j = 0; j < 10; j++) - feedback_1(P[j], P[j + 1], P[(j - 10) & 0x3ff], P[(j - 3) & 0x3ff]); - for (j = 10; j < 1023; j++) - feedback_1(P[j], P[j + 1], P[j - 10], P[j - 3]); - feedback_1(P[1023], P[0], P[1013], P[1020]); - for (j = 0; j < 10; j++) - feedback_2(Q[j], Q[j+1], Q[(j-10) & 0x3ff], Q[(j - 3) & 0x3ff]); - for (j = 10; j < 1023; j++) - feedback_2(Q[j], Q[j + 1], Q[j - 10], Q[j - 3]); - feedback_2(Q[1023], Q[0], Q[1013], Q[1020]); - } - //initialize counter2048, and tables X and Y - counter2048 = 0; - for (i = 0; i < 16; i++) - X[i] = P[1008 + i]; - for (i = 0; i < 16; i++) - Y[i] = Q[1008 + i]; -} - -extern "C" __declspec(dllexport) const TCipherInfo* CipherInfo(void * Reserved) -{ - return &HC256::cCipherInfo; -} diff --git a/plugins/Dbx_tree/encryption/HC256.h b/plugins/Dbx_tree/encryption/HC256.h deleted file mode 100644 index d4acb3195f..0000000000 --- a/plugins/Dbx_tree/encryption/HC256.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - -dbx_tree: tree database driver for Miranda IM - -Copyright 2007-2008 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. - -*/ - -#pragma once - -#include "Cipher.h" - -class HC256 : public CCipher -{ -private: - uint32_t counter2048; - uint32_t P[1024], Q[1024]; - uint32_t X[16], Y[16]; - - uint32_t BackP[1024], BackQ[1024]; - uint32_t BackX[16], BackY[16]; - - void EncryptBlock(uint32_t *Data); - void CreateTables(uint8_t* Key); - - static const wchar_t* cName; - static const wchar_t* cDescription; - static const uint32_t cBlockSizeBytes = 64; - static const bool cIsStreamCipher = true; - -public: - - const wchar_t * __cdecl Name(); - const wchar_t * __cdecl Description(); - const uint32_t __cdecl BlockSizeBytes(); - const bool __cdecl IsStreamCipher(); - - static const TCipherInfo cCipherInfo; - - HC256(); - ~HC256(); - static CCipher::TCipherInterface* __cdecl Create(); - - void __cdecl SetKey(void* Key, uint32_t KeyLength); - void __cdecl Encrypt(void* Data, uint32_t Size, uint32_t Nonce, uint32_t StartByte); - void __cdecl Decrypt(void* Data, uint32_t Size, uint32_t Nonce, uint32_t StartByte); - -}; - -const wchar_t* HC256::cName = L"HC-256"; -const wchar_t* HC256::cDescription = L"Streamcipher - 512bit step, very fast, Hongjun Wu 2005"; -const TCipherInfo HC256::cCipherInfo = {sizeof(TCipherInfo), 'HC25', cName, cDescription, &HC256::Create}; diff --git a/plugins/Dbx_tree/encryption/HC256.vcxproj b/plugins/Dbx_tree/encryption/HC256.vcxproj deleted file mode 100644 index f006b55725..0000000000 --- a/plugins/Dbx_tree/encryption/HC256.vcxproj +++ /dev/null @@ -1,160 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - Dbx_tree_HC256 - {541BE2B3-4320-47B8-AB64-C7F7ED0EFABA} - - - - DynamicLibrary - Unicode - - - DynamicLibrary - Unicode - - - DynamicLibrary - Unicode - true - - - DynamicLibrary - Unicode - true - - - - - - - - - - <_ProjectFileVersion>10.0.20506.1 - $(SolutionDir)$(Configuration)\Plugins\Encryption\ - $(SolutionDir)$(Configuration)64\Plugins\Encryption\ - $(SolutionDir)$(Configuration)\Obj\$(ProjectName)\ - $(SolutionDir)$(Configuration)64\Obj\$(ProjectName)\ - $(SolutionDir)$(Configuration)\Plugins\Encryption\ - $(SolutionDir)$(Configuration)64\Plugins\Encryption\ - $(SolutionDir)$(Configuration)\Obj\$(ProjectName)\ - $(SolutionDir)$(Configuration)64\Obj\$(ProjectName)\ - true - - - - Disabled - WIN32;_DEBUG;_WINDOWS;_USRDLL;HC256_EXPORTS;%(PreprocessorDefinitions) - true - EnableFastChecks - MultiThreadedDebugDLL - Level3 - EditAndContinue - true - true - Fast - - - true - Windows - $(IntDir)$(TargetName).lib - false - $(SolutionDir)\lib - - - - - Disabled - WIN64;_DEBUG;_WINDOWS;_USRDLL;HC256_EXPORTS;%(PreprocessorDefinitions) - EnableFastChecks - MultiThreadedDebugDLL - Level3 - true - true - true - Fast - - - true - Windows - $(IntDir)$(TargetName).lib - false - $(SolutionDir)\lib - - - - - Full - AnySuitable - Size - WIN32;NDEBUG;_WINDOWS;_USRDLL;HC256_EXPORTS;%(PreprocessorDefinitions) - true - Level3 - true - true - Fast - - - true - Windows - true - true - $(IntDir)$(TargetName).lib - false - $(SolutionDir)\lib - /PDBALTPATH:%_PDB% - - - - - Full - AnySuitable - Size - WIN64;NDEBUG;_WINDOWS;_USRDLL;HC256_EXPORTS;%(PreprocessorDefinitions) - true - Level3 - true - true - Fast - - - true - Windows - true - true - $(IntDir)$(TargetName).lib - false - $(SolutionDir)\lib - /PDBALTPATH:%_PDB% - - - - - - - - - - - - - \ No newline at end of file diff --git a/plugins/Dbx_tree/encryption/HC256.vcxproj.filters b/plugins/Dbx_tree/encryption/HC256.vcxproj.filters deleted file mode 100644 index 5d1e3ec0dd..0000000000 --- a/plugins/Dbx_tree/encryption/HC256.vcxproj.filters +++ /dev/null @@ -1,30 +0,0 @@ - - - - - {93995380-89BD-4b04-88EB-625FBE52EBFB} - h;hpp;hxx;hm;inl;inc;xsd - - - {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} - rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx - - - - - Header Files - - - Header Files - - - - - Source Files - - - \ No newline at end of file diff --git a/plugins/Dbx_tree/encryption/HC256/HC256.vcxproj b/plugins/Dbx_tree/encryption/HC256/HC256.vcxproj new file mode 100644 index 0000000000..2369cea095 --- /dev/null +++ b/plugins/Dbx_tree/encryption/HC256/HC256.vcxproj @@ -0,0 +1,168 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + Dbx_tree_HC256 + {541BE2B3-4320-47B8-AB64-C7F7ED0EFABA} + + + + DynamicLibrary + Unicode + + + DynamicLibrary + Unicode + + + DynamicLibrary + Unicode + true + + + DynamicLibrary + Unicode + true + + + + + + + + + + <_ProjectFileVersion>10.0.20506.1 + $(SolutionDir)$(Configuration)\Plugins\Encryption\ + $(SolutionDir)$(Configuration)64\Plugins\Encryption\ + $(SolutionDir)$(Configuration)\Obj\$(ProjectName)\ + $(SolutionDir)$(Configuration)64\Obj\$(ProjectName)\ + $(SolutionDir)$(Configuration)\Plugins\Encryption\ + $(SolutionDir)$(Configuration)64\Plugins\Encryption\ + $(SolutionDir)$(Configuration)\Obj\$(ProjectName)\ + $(SolutionDir)$(Configuration)64\Obj\$(ProjectName)\ + true + HC256 + HC256 + HC256 + HC256 + + + + Disabled + WIN32;_DEBUG;_WINDOWS;_USRDLL;HC256_EXPORTS;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + Level3 + ..\Common + EditAndContinue + true + true + Fast + + + true + Windows + $(IntDir)$(TargetName).lib + false + $(SolutionDir)\lib + + + + + Disabled + WIN64;_DEBUG;_WINDOWS;_USRDLL;HC256_EXPORTS;%(PreprocessorDefinitions) + EnableFastChecks + MultiThreadedDebugDLL + Level3 + ..\Common + true + true + true + Fast + + + true + Windows + $(IntDir)$(TargetName).lib + false + $(SolutionDir)\lib + + + + + Full + AnySuitable + Size + WIN32;NDEBUG;_WINDOWS;_USRDLL;HC256_EXPORTS;%(PreprocessorDefinitions) + true + Level3 + ..\Common + true + true + Fast + + + true + Windows + true + true + $(IntDir)$(TargetName).lib + false + $(SolutionDir)\lib + /PDBALTPATH:%_PDB% + + + + + Full + AnySuitable + Size + WIN64;NDEBUG;_WINDOWS;_USRDLL;HC256_EXPORTS;%(PreprocessorDefinitions) + true + Level3 + ..\Common + true + true + Fast + + + true + Windows + true + true + $(IntDir)$(TargetName).lib + false + $(SolutionDir)\lib + /PDBALTPATH:%_PDB% + + + + + + + + + + + + + \ No newline at end of file diff --git a/plugins/Dbx_tree/encryption/HC256/HC256.vcxproj.filters b/plugins/Dbx_tree/encryption/HC256/HC256.vcxproj.filters new file mode 100644 index 0000000000..abb4df92d0 --- /dev/null +++ b/plugins/Dbx_tree/encryption/HC256/HC256.vcxproj.filters @@ -0,0 +1,30 @@ + + + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + + + Header Files + + + Header Files + + + + + Source Files + + + \ No newline at end of file diff --git a/plugins/Dbx_tree/encryption/HC256/src/HC256.cpp b/plugins/Dbx_tree/encryption/HC256/src/HC256.cpp new file mode 100644 index 0000000000..056b4e4dae --- /dev/null +++ b/plugins/Dbx_tree/encryption/HC256/src/HC256.cpp @@ -0,0 +1,243 @@ +/* + +dbx_tree: tree database driver for Miranda IM + +Copyright 2007-2008 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 "HC256.h" +#include +#include + +#ifndef _MSC_VER + #define rotr(x,n) (((x)>>(n))|((x)<<(32-(n)))) +#else + #define rotr(x,n) _lrotr(x,n) +#endif + +#define h1(x,y) { \ + uint8_t a,b,c,d; \ + a = (uint8_t) (x); \ + b = (uint8_t) ((x) >> 8); \ + c = (uint8_t) ((x) >> 16); \ + d = (uint8_t) ((x) >> 24); \ + (y) = Q[a]+Q[256+b]+Q[512+c]+Q[768+d]; \ +} +#define h2(x,y) { \ + uint8_t a,b,c,d; \ + a = (uint8_t) (x); \ + b = (uint8_t) ((x) >> 8); \ + c = (uint8_t) ((x) >> 16); \ + d = (uint8_t) ((x) >> 24); \ + (y) = P[a]+P[256+b]+P[512+c]+P[768+d]; \ +} +#define step_A(u,v,a,b,c,d,m){ \ + uint32_t tem0,tem1,tem2,tem3; \ + tem0 = rotr((v),23); \ + tem1 = rotr((c),10); \ + tem2 = ((v) ^ (c)) & 0x3ff; \ + (u) += (b)+(tem0^tem1)+Q[tem2]; \ + (a) = (u); \ + h1((d),tem3); \ + (m) ^= tem3 ^ (u) ; \ +} +#define step_B(u,v,a,b,c,d,m){ \ + uint32_t tem0,tem1,tem2,tem3; \ + tem0 = rotr((v),23); \ + tem1 = rotr((c),10); \ + tem2 = ((v) ^ (c)) & 0x3ff; \ + (u) += (b)+(tem0^tem1)+P[tem2]; \ + (a) = (u); \ + h2((d),tem3); \ + (m) ^= tem3 ^ (u) ; \ +} + + +#define f1(x) (rotr((x),7) ^ rotr((x),18) ^ ((x) >> 3)) +#define f2(x) (rotr((x),17) ^ rotr((x),19) ^ ((x) >> 10)) +#define f(a,b,c,d) (f2((a)) + (b) + f1((c)) + (d)) +#define feedback_1(u,v,b,c) { \ + uint32_t tem0,tem1,tem2; \ + tem0 = rotr((v),23); \ + tem1 = rotr((c),10); \ + tem2 = ((v) ^ (c)) & 0x3ff; \ + (u) += (b)+(tem0^tem1)+Q[tem2]; \ +} +#define feedback_2(u,v,b,c) { \ + uint32_t tem0,tem1,tem2; \ + tem0 = rotr((v),23); \ + tem1 = rotr((c),10); \ + tem2 = ((v) ^ (c)) & 0x3ff; \ + (u) += (b)+(tem0^tem1)+P[tem2]; \ +} + +const wchar_t * HC256::Name() +{ + return cName; +} +const wchar_t * HC256::Description() +{ + return cDescription; +} +const uint32_t HC256::BlockSizeBytes() +{ + return cBlockSizeBytes; +} +const bool HC256::IsStreamCipher() +{ + return cIsStreamCipher; +} + +HC256::HC256() +{ + +} +HC256::~HC256() +{ + +} +CCipher::TCipherInterface* HC256::Create() +{ + return (new HC256())->m_Interface; +} + +void HC256::SetKey(void* Key, uint32_t KeyLength) +{ + uint8_t k[32] = {0}; + + for (uint32_t i = 0; i < KeyLength; ++i) + { + k[i & 0x1f] ^= ((uint8_t *)Key)[i]; + } + CreateTables(k); +} +void HC256::Encrypt(void* Data, uint32_t Size, uint32_t Nonce, uint32_t StartByte) +{ + memcpy(X, BackX, sizeof(X)); + memcpy(Y, BackY, sizeof(Y)); + memcpy(P, BackP, sizeof(P)); + memcpy(Q, BackQ, sizeof(Q)); + + counter2048 = (Nonce + (Nonce >> 11) + (Nonce >> 22)) & 0x7ff; + + for (uint32_t i = 0; i <= Size - BlockSizeBytes(); i += BlockSizeBytes()) + { + EncryptBlock((uint32_t*)((uint8_t*)Data + i)); + StartByte += BlockSizeBytes(); + } +} +void HC256::Decrypt(void* Data, uint32_t Size, uint32_t Nonce, uint32_t StartByte) +{ + Encrypt(Data, Size, Nonce, StartByte); +} + +inline void HC256::EncryptBlock(uint32_t *Data) +{ + uint32_t cc,dd; + cc = counter2048 & 0x3ff; + dd = (cc + 16) & 0x3ff; + if (counter2048 < 1024) + { + counter2048 = (counter2048 + 16) & 0x7ff; + step_A(P[cc+0], P[cc+1], X[0], X[6], X[13],X[4], Data[0]); + step_A(P[cc+1], P[cc+2], X[1], X[7], X[14],X[5], Data[1]); + step_A(P[cc+2], P[cc+3], X[2], X[8], X[15],X[6], Data[2]); + step_A(P[cc+3], P[cc+4], X[3], X[9], X[0], X[7], Data[3]); + step_A(P[cc+4], P[cc+5], X[4], X[10],X[1], X[8], Data[4]); + step_A(P[cc+5], P[cc+6], X[5], X[11],X[2], X[9], Data[5]); + step_A(P[cc+6], P[cc+7], X[6], X[12],X[3], X[10],Data[6]); + step_A(P[cc+7], P[cc+8], X[7], X[13],X[4], X[11],Data[7]); + step_A(P[cc+8], P[cc+9], X[8], X[14],X[5], X[12],Data[8]); + step_A(P[cc+9], P[cc+10],X[9], X[15],X[6], X[13],Data[9]); + step_A(P[cc+10],P[cc+11],X[10],X[0], X[7], X[14],Data[10]); + step_A(P[cc+11],P[cc+12],X[11],X[1], X[8], X[15],Data[11]); + step_A(P[cc+12],P[cc+13],X[12],X[2], X[9], X[0], Data[12]); + step_A(P[cc+13],P[cc+14],X[13],X[3], X[10],X[1], Data[13]); + step_A(P[cc+14],P[cc+15],X[14],X[4], X[11],X[2], Data[14]); + step_A(P[cc+15],P[dd+0], X[15],X[5], X[12],X[3], Data[15]); + + } else { + + counter2048 = (counter2048 + 16) & 0x7ff; + step_B(Q[cc+0], Q[cc+1], Y[0], Y[6], Y[13],Y[4], Data[0]); + step_B(Q[cc+1], Q[cc+2], Y[1], Y[7], Y[14],Y[5], Data[1]); + step_B(Q[cc+2], Q[cc+3], Y[2], Y[8], Y[15],Y[6], Data[2]); + step_B(Q[cc+3], Q[cc+4], Y[3], Y[9], Y[0], Y[7], Data[3]); + step_B(Q[cc+4], Q[cc+5], Y[4], Y[10],Y[1], Y[8], Data[4]); + step_B(Q[cc+5], Q[cc+6], Y[5], Y[11],Y[2], Y[9], Data[5]); + step_B(Q[cc+6], Q[cc+7], Y[6], Y[12],Y[3], Y[10],Data[6]); + step_B(Q[cc+7], Q[cc+8], Y[7], Y[13],Y[4], Y[11],Data[7]); + step_B(Q[cc+8], Q[cc+9], Y[8], Y[14],Y[5], Y[12],Data[8]); + step_B(Q[cc+9], Q[cc+10],Y[9], Y[15],Y[6], Y[13],Data[9]); + step_B(Q[cc+10],Q[cc+11],Y[10],Y[0], Y[7], Y[14],Data[10]); + step_B(Q[cc+11],Q[cc+12],Y[11],Y[1], Y[8], Y[15],Data[11]); + step_B(Q[cc+12],Q[cc+13],Y[12],Y[2], Y[9], Y[0], Data[12]); + step_B(Q[cc+13],Q[cc+14],Y[13],Y[3], Y[10],Y[1], Data[13]); + step_B(Q[cc+14],Q[cc+15],Y[14],Y[4], Y[11],Y[2], Data[14]); + step_B(Q[cc+15],Q[dd+0], Y[15],Y[5], Y[12],Y[3], Data[15]); + } +} +inline void HC256::CreateTables(uint8_t* Key) +{ + uint32_t i, j; + uint8_t iv[32] = "Miranda NG dbx_tree Protogenes!"; + //expand the key and iv into P and Q + for (i = 0; i < 8; i++) + P[i] = Key[i]; + for (i = 8; i < 16; i++) + P[i] = iv[i - 8]; + for (i = 16; i < 528; i++) + P[i] = f(P[i - 2], P[i - 7], P[i - 15], P[i - 16]) + i; + for (i = 0; i < 16; i++) + P[i] = P[i + 512]; + for (i = 16; i < 1024; i++) + P[i] = f(P[i - 2], P[i - 7], P[i - 15], P[i - 16]) + 512 + i; + for (i = 0; i < 16; i++) + Q[i] = P[1024 - 16 + i]; + for (i = 16; i < 32; i++) + Q[i] = f(Q[i - 2], Q[i - 7], Q[i - 15], Q[i - 16]) + 1520 + i; + for (i = 0; i < 16; i++) + Q[i] = Q[i + 16]; + for (i = 16; i < 1024;i++) + Q[i] = f(Q[i - 2], Q[i - 7], Q[i - 15], Q[i - 16]) + 1536 + i; + //run the cipher 4096 steps without generating output + for (i = 0; i < 2; i++) + { + for (j = 0; j < 10; j++) + feedback_1(P[j], P[j + 1], P[(j - 10) & 0x3ff], P[(j - 3) & 0x3ff]); + for (j = 10; j < 1023; j++) + feedback_1(P[j], P[j + 1], P[j - 10], P[j - 3]); + feedback_1(P[1023], P[0], P[1013], P[1020]); + for (j = 0; j < 10; j++) + feedback_2(Q[j], Q[j+1], Q[(j-10) & 0x3ff], Q[(j - 3) & 0x3ff]); + for (j = 10; j < 1023; j++) + feedback_2(Q[j], Q[j + 1], Q[j - 10], Q[j - 3]); + feedback_2(Q[1023], Q[0], Q[1013], Q[1020]); + } + //initialize counter2048, and tables X and Y + counter2048 = 0; + for (i = 0; i < 16; i++) + X[i] = P[1008 + i]; + for (i = 0; i < 16; i++) + Y[i] = Q[1008 + i]; +} + +extern "C" __declspec(dllexport) const TCipherInfo* CipherInfo(void * Reserved) +{ + return &HC256::cCipherInfo; +} diff --git a/plugins/Dbx_tree/encryption/HC256/src/HC256.h b/plugins/Dbx_tree/encryption/HC256/src/HC256.h new file mode 100644 index 0000000000..d4acb3195f --- /dev/null +++ b/plugins/Dbx_tree/encryption/HC256/src/HC256.h @@ -0,0 +1,66 @@ +/* + +dbx_tree: tree database driver for Miranda IM + +Copyright 2007-2008 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. + +*/ + +#pragma once + +#include "Cipher.h" + +class HC256 : public CCipher +{ +private: + uint32_t counter2048; + uint32_t P[1024], Q[1024]; + uint32_t X[16], Y[16]; + + uint32_t BackP[1024], BackQ[1024]; + uint32_t BackX[16], BackY[16]; + + void EncryptBlock(uint32_t *Data); + void CreateTables(uint8_t* Key); + + static const wchar_t* cName; + static const wchar_t* cDescription; + static const uint32_t cBlockSizeBytes = 64; + static const bool cIsStreamCipher = true; + +public: + + const wchar_t * __cdecl Name(); + const wchar_t * __cdecl Description(); + const uint32_t __cdecl BlockSizeBytes(); + const bool __cdecl IsStreamCipher(); + + static const TCipherInfo cCipherInfo; + + HC256(); + ~HC256(); + static CCipher::TCipherInterface* __cdecl Create(); + + void __cdecl SetKey(void* Key, uint32_t KeyLength); + void __cdecl Encrypt(void* Data, uint32_t Size, uint32_t Nonce, uint32_t StartByte); + void __cdecl Decrypt(void* Data, uint32_t Size, uint32_t Nonce, uint32_t StartByte); + +}; + +const wchar_t* HC256::cName = L"HC-256"; +const wchar_t* HC256::cDescription = L"Streamcipher - 512bit step, very fast, Hongjun Wu 2005"; +const TCipherInfo HC256::cCipherInfo = {sizeof(TCipherInfo), 'HC25', cName, cDescription, &HC256::Create}; diff --git a/plugins/Dbx_tree/init.cpp b/plugins/Dbx_tree/init.cpp deleted file mode 100644 index 3e1f4cc6a6..0000000000 --- a/plugins/Dbx_tree/init.cpp +++ /dev/null @@ -1,73 +0,0 @@ -/* - -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 "Interface.h" -#include "DatabaseLink.h" - -HINSTANCE hInstance = NULL; -int hLangpack; - -static const DWORD gMinMirVer = 0x00080000; -// {28F45248-8C9C-4bee-9307-7BCF3E12BF99} -static const MUUID gGUID = -{ 0x28f45248, 0x8c9c, 0x4bee, { 0x93, 0x07, 0x7b, 0xcf, 0x3e, 0x12, 0xbf, 0x99 } }; - -static PLUGININFOEX gPluginInfoEx = { - sizeof(PLUGININFOEX), - gInternalNameLong, - gVersion, - gDescription, - gAutor, - gAutorEmail, - gCopyright, - "http://miranda-ng.org/", - UNICODE_AWARE, - gGUID -}; - -extern "C" __declspec(dllexport) PLUGININFOEX * MirandaPluginInfoEx(DWORD MirandaVersion) -{ - return &gPluginInfoEx; -} - -extern "C" __declspec(dllexport) const MUUID MirandaInterfaces[] = {MIID_DATABASE, MIID_LAST}; - -extern "C" __declspec(dllexport) int Load(void) -{ - mir_getLP(&gPluginInfoEx); - - RegisterDatabasePlugin(&gDBLink); - RegisterServices(); - CompatibilityRegister(); - return 0; -} - -extern "C" __declspec(dllexport) int Unload(void) -{ - return 0; -} - -BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD dwReason, LPVOID reserved) -{ - hInstance = hInstDLL; - return TRUE; -} diff --git a/plugins/Dbx_tree/intrinsics.h b/plugins/Dbx_tree/intrinsics.h deleted file mode 100644 index 7cb8af18f3..0000000000 --- a/plugins/Dbx_tree/intrinsics.h +++ /dev/null @@ -1,407 +0,0 @@ -#pragma once - -#ifdef _MSC_VER - -#include -#include "stdint.h" - -#ifdef _M_X64 - -inline uint32_t XCHG_32(uint32_t volatile & Dest, uint32_t Exchange) -{ - return (uint32_t)_InterlockedExchange((long volatile*)&(Dest), (long)(Exchange)); -} -inline int32_t XCHG_32(int32_t volatile & Dest, int32_t Exchange) -{ - return (int32_t)_InterlockedExchange((long volatile*)&(Dest), (long)(Exchange)); -} - -inline uint64_t XCHG_64(uint64_t volatile & Dest, uint64_t Exchange) -{ - return (uint64_t)_InterlockedExchange64((__int64 volatile*)&Dest, (__int64)Exchange); -} -inline int64_t XCHG_64(int64_t volatile & Dest, int64_t Exchange) -{ - return (int64_t)_InterlockedExchange64((__int64 volatile*)&Dest, (__int64)Exchange); -} - -template -inline T * XCHG_Ptr(T * volatile & Dest, T * Exchange) -{ - return (T*)_InterlockedExchangePointer((void*volatile*)&Dest, (void*)Exchange); -} - - -inline uint32_t CMPXCHG_32(uint32_t volatile & Dest, uint32_t Exchange, uint32_t Comperand) -{ - return (uint64_t)_InterlockedCompareExchange((long volatile*)&(Dest), (long)(Exchange), (long)Comperand); -} -inline int32_t CMPXCHG_32(int32_t volatile & Dest, int32_t Exchange, int32_t Comperand) -{ - return (int32_t)_InterlockedCompareExchange((long volatile*)&(Dest), (long)(Exchange), (long)Comperand); -} - -inline uint64_t CMPXCHG_64(uint64_t volatile & Dest, uint64_t Exchange, uint64_t Comperand) -{ - return (uint64_t)_InterlockedCompareExchange64((__int64 volatile*)&Dest, (__int64)Exchange, (__int64)Comperand); -} -inline int64_t CMPXCHG_64(int64_t volatile & Dest, int64_t Exchange, int64_t Comperand) -{ - return (int64_t)_InterlockedCompareExchange64((__int64 volatile*)&Dest, (__int64)Exchange, (__int64)Comperand); -} - -template -inline T * CMPXCHG_Ptr(T * volatile & Dest, T * Exchange, T * Comperand) -{ - return (T*)_InterlockedCompareExchangePointer((void*volatile*)&Dest, (void*)Exchange, (void*)Comperand); -} - -inline uint32_t XADD_32(uint32_t volatile & Dest, int32_t Addend) -{ - return (uint32_t)_InterlockedExchangeAdd((long volatile*)&Dest, (long)Addend); -} -inline int32_t XADD_32(int32_t volatile & Dest, int32_t Addend) -{ - return (int32_t)_InterlockedExchangeAdd((long volatile*)&Dest, (long)Addend); -} - -inline uint64_t XADD_64(uint64_t volatile & Dest, int64_t Addend) -{ - return (uint64_t)_InterlockedExchangeAdd64((__int64 volatile*)&Dest, (__int64)Addend); -} -inline int64_t XADD_64(int64_t volatile & Dest, int64_t Addend) -{ - return (int64_t)_InterlockedExchangeAdd64((__int64 volatile*)&Dest, (__int64)Addend); -} - -inline uint32_t DEC_32(uint32_t volatile & Dest) -{ - return (uint32_t)_InterlockedDecrement((long volatile*)&Dest); -} -inline int32_t DEC_32(int32_t volatile & Dest) -{ - return (int32_t)_InterlockedDecrement((long volatile*)&Dest); -} - -inline uint64_t DEC_64(uint64_t volatile & Dest) -{ - return (uint64_t)_InterlockedDecrement64((__int64 volatile*)&Dest); -} -inline int64_t DEC_64(int64_t volatile & Dest) -{ - return (int64_t)_InterlockedDecrement64((__int64 volatile*)&Dest); -} - -inline uint32_t INC_32(uint32_t volatile & Dest) -{ - return (uint32_t)_InterlockedIncrement((long volatile*)&Dest); -} -inline int32_t INC_32(int32_t volatile & Dest) -{ - return (int32_t)_InterlockedIncrement((long volatile*)&Dest); -} - -inline uint64_t INC_64(uint64_t volatile & Dest) -{ - return (uint64_t)_InterlockedIncrement64((__int64 volatile*)&Dest); -} -inline int64_t INC_64(int64_t volatile & Dest) -{ - return (int64_t)_InterlockedIncrement64((__int64 volatile*)&Dest); -} - -inline bool BTS_32(uint32_t volatile & Dest, uint8_t Offset) -{ - return !!_interlockedbittestandset((long volatile*)&Dest, Offset); -} -inline bool BTS_32(int32_t volatile & Dest, uint8_t Offset) -{ - return !!_interlockedbittestandset((long volatile*)&Dest, Offset); -} -inline bool BTS_64(uint64_t volatile & Dest, uint8_t Offset) -{ - return !!_interlockedbittestandset64((__int64 volatile*)&Dest, Offset); -} -inline bool BTS_64(int64_t volatile & Dest, uint8_t Offset) -{ - return !!_interlockedbittestandset64((__int64 volatile*)&Dest, Offset); -} - - -inline bool BTR_32(uint32_t volatile & Dest, uint8_t Offset) -{ - return !!_interlockedbittestandreset((long volatile*)&Dest, Offset); -} -inline bool BTR_32(int32_t volatile & Dest, uint8_t Offset) -{ - return !!_interlockedbittestandreset((long volatile*)&Dest, Offset); -} -inline bool BTR_64(uint64_t volatile & Dest, uint8_t Offset) -{ - return !!_interlockedbittestandreset64((__int64 volatile*)&Dest, Offset); -} -inline bool BTR_64(int64_t volatile & Dest, uint8_t Offset) -{ - return !!_interlockedbittestandreset64((__int64 volatile*)&Dest, Offset); -} - - -inline uint32_t OR_32(uint32_t volatile & Value, uint32_t Operator) -{ - return (uint32_t)_InterlockedOr((long volatile*)&Value, (long)Operator); -} - -inline int32_t OR_32(int32_t volatile & Value, int32_t Operator) -{ - return (int32_t)_InterlockedOr((long volatile*)&Value, (long)Operator); -} - -inline uint64_t OR_64(uint64_t volatile & Value, uint64_t Operator) -{ - return (uint64_t)_InterlockedOr64((__int64 volatile*)&Value, (__int64)Operator); -} - -inline int64_t OR_64(int64_t volatile & Value, int64_t Operator) -{ - return (int64_t)_InterlockedOr64((__int64 volatile*)&Value, (__int64)Operator); -} - -inline uint32_t AND_32(uint32_t volatile & Value, uint32_t Operator) -{ - return (uint32_t)_InterlockedAnd((long volatile*)&Value, (long)Operator); -} - -inline int32_t AND_32(int32_t volatile & Value, int32_t Operator) -{ - return (int32_t)_InterlockedAnd((long volatile*)&Value, (long)Operator); -} - -inline uint64_t AND_64(uint64_t volatile & Value, uint64_t Operator) -{ - return (uint64_t)_InterlockedAnd64((__int64 volatile*)&Value, (__int64)Operator); -} - -inline int64_t AND_64(int64_t volatile & Value, int64_t Operator) -{ - return (int64_t)_InterlockedAnd64((__int64 volatile*)&Value, (__int64)Operator); -} - - -inline uint32_t XOR_32(uint32_t volatile & Value, uint32_t Operator) -{ - return (uint32_t)_InterlockedXor((long volatile*)&Value, (long)Operator); -} - -inline int32_t XOR_32(int32_t volatile & Value, int32_t Operator) -{ - return (int32_t)_InterlockedXor((long volatile*)&Value, (long)Operator); -} -inline uint64_t XOR_64(uint64_t volatile & Value, uint64_t Operator) -{ - return (uint64_t)_InterlockedXor64((__int64 volatile*)&Value, (__int64)Operator); -} - -inline int64_t XOR_64(int64_t volatile & Value, int64_t Operator) -{ - return (int64_t)_InterlockedXor64((__int64 volatile*)&Value, (__int64)Operator); -} - - -inline uint32_t BSWAP_32(uint32_t Value) -{ - return _byteswap_ulong(Value); -} - -inline uint32_t ROL_32(uint32_t Value, uint8_t Shift) -{ - return _rotl(Value, Shift); -} - -inline uint32_t ROR_32(uint32_t Value, uint8_t Shift) -{ - return _rotr(Value, Shift); -} - -#elif defined(_M_IX86) - -inline uint32_t XCHG_32(uint32_t volatile & Dest, uint32_t Exchange) -{ - return (uint32_t)_InterlockedExchange((long volatile*)&(Dest), (long)(Exchange)); -} -inline int32_t XCHG_32(int32_t volatile & Dest, int32_t Exchange) -{ - return (int32_t)_InterlockedExchange((long volatile*)&(Dest), (long)(Exchange)); -} -/* -inline uint64_t XCHG_64(uint64_t volatile & Dest, uint64_t Exchange) -{ - return (uint64_t)_InterlockedExchange64((__int64 volatile*)&Dest, (__int64)Exchange); -} -inline int64_t XCHG_64(int64_t volatile & Dest, int64_t Exchange) -{ - return (int64_t)_InterlockedExchange64((__int64 volatile*)&Dest, (__int64)Exchange); -} -*/ -template -inline T * XCHG_Ptr(T * volatile & Dest, T * Exchange) -{ - return (T*)_InterlockedExchange((long volatile*)&Dest, (long)Exchange); -} - - -inline uint32_t CMPXCHG_32(uint32_t volatile & Dest, uint32_t Exchange, uint32_t Comperand) -{ - return (uint64_t)_InterlockedCompareExchange((long volatile*)&(Dest), (long)(Exchange), (long)Comperand); -} -inline int32_t CMPXCHG_32(int32_t volatile & Dest, int32_t Exchange, int32_t Comperand) -{ - return (int32_t)_InterlockedCompareExchange((long volatile*)&(Dest), (long)(Exchange), (long)Comperand); -} - -inline uint64_t CMPXCHG_64(uint64_t volatile & Dest, uint64_t Exchange, uint64_t Comperand) -{ - return (uint64_t)_InterlockedCompareExchange64((__int64 volatile*)&Dest, (__int64)Exchange, (__int64)Comperand); -} -inline int64_t CMPXCHG_64(int64_t volatile & Dest, int64_t Exchange, int64_t Comperand) -{ - return (int64_t)_InterlockedCompareExchange64((__int64 volatile*)&Dest, (__int64)Exchange, (__int64)Comperand); -} - -template -inline T * CMPXCHG_Ptr(T * volatile & Dest, T * Exchange, T * Comperand) -{ - return (T*)_InterlockedCompareExchange((long volatile *)&Dest, (long)Exchange, (long)Comperand); -} - -inline uint32_t XADD_32(uint32_t volatile & Dest, int32_t Addend) -{ - return (uint32_t)_InterlockedExchangeAdd((long volatile*)&Dest, (long)Addend); -} -inline int32_t XADD_32(int32_t volatile & Dest, int32_t Addend) -{ - return (int32_t)_InterlockedExchangeAdd((long volatile*)&Dest, (long)Addend); -} - -inline uint32_t DEC_32(uint32_t volatile & Dest) -{ - return (uint32_t)_InterlockedDecrement((long volatile*)&Dest); -} -inline int32_t DEC_32(int32_t volatile & Dest) -{ - return (int32_t)_InterlockedDecrement((long volatile*)&Dest); -} - -inline uint32_t INC_32(uint32_t volatile & Dest) -{ - return (uint32_t)_InterlockedIncrement((long volatile*)&Dest); -} -inline int32_t INC_32(int32_t volatile & Dest) -{ - return (int32_t)_InterlockedIncrement((long volatile*)&Dest); -} - -inline bool BTS_32(uint32_t volatile & Dest, uint8_t Offset) -{ - return !!_interlockedbittestandset((long volatile*)&Dest, Offset); -} -inline bool BTS_32(int32_t volatile & Dest, uint8_t Offset) -{ - return !!_interlockedbittestandset((long volatile*)&Dest, Offset); -} -inline bool BTS_64(uint64_t volatile & Dest, uint8_t Offset) -{ - if (Offset > 31) - return !!_interlockedbittestandset((long volatile*)&Dest, Offset); - else - return !!_interlockedbittestandset(((long volatile*)&Dest) + 1, Offset - 32); -} -inline bool BTS_64(int64_t volatile & Dest, uint8_t Offset) -{ - if (Offset > 31) - return !!_interlockedbittestandset((long volatile*)&Dest, Offset); - else - return !!_interlockedbittestandset(((long volatile*)&Dest) + 1, Offset - 32); -} - - -inline bool BTR_32(uint32_t volatile & Dest, uint8_t Offset) -{ - return !!_interlockedbittestandreset((long volatile*)&Dest, Offset); -} -inline bool BTR_32(int32_t volatile & Dest, uint8_t Offset) -{ - return !!_interlockedbittestandreset((long volatile*)&Dest, Offset); -} -inline bool BTR_64(uint64_t volatile & Dest, uint8_t Offset) -{ - if (Offset > 31) - return !!_interlockedbittestandreset((long volatile*)&Dest, Offset); - else - return !!_interlockedbittestandreset(((long volatile*)&Dest) + 1, Offset - 32); -} -inline bool BTR_64(int64_t volatile & Dest, uint8_t Offset) -{ - if (Offset > 31) - return !!_interlockedbittestandreset((long volatile*)&Dest, Offset); - else - return !!_interlockedbittestandreset(((long volatile*)&Dest) + 1, Offset - 32); -} - -inline uint32_t OR_32(uint32_t volatile & Value, uint32_t Operator) -{ - return (uint32_t)_InterlockedOr((long volatile*)&Value, (long)Operator); -} - -inline int32_t OR_32(int32_t volatile & Value, int32_t Operator) -{ - return (int32_t)_InterlockedOr((long volatile*)&Value, (long)Operator); -} - -inline uint32_t AND_32(uint32_t volatile & Value, uint32_t Operator) -{ - return (uint32_t)_InterlockedAnd((long volatile*)&Value, (long)Operator); -} - -inline int32_t AND_32(int32_t volatile & Value, int32_t Operator) -{ - return (int32_t)_InterlockedAnd((long volatile*)&Value, (long)Operator); -} - -inline uint32_t XOR_32(uint32_t volatile & Value, uint32_t Operator) -{ - return (uint32_t)_InterlockedXor((long volatile*)&Value, (long)Operator); -} - -inline int32_t XOR_32(int32_t volatile & Value, int32_t Operator) -{ - return (int32_t)_InterlockedXor((long volatile*)&Value, (long)Operator); -} - - -inline uint32_t BSWAP_32(uint32_t Value) -{ - return _byteswap_ulong(Value); -} - -inline uint32_t ROL_32(uint32_t Value, uint8_t Shift) -{ - return _rotl(Value, Shift); -} -inline uint32_t ROR_32(uint32_t Value, uint8_t Shift) -{ - return _rotr(Value, Shift); -} - - - -#else - -#error unsupported architecture - -#endif - -#else - -#error unsupported compiler - -#endif diff --git a/plugins/Dbx_tree/inttypes.h b/plugins/Dbx_tree/inttypes.h deleted file mode 100644 index 25542771f5..0000000000 --- a/plugins/Dbx_tree/inttypes.h +++ /dev/null @@ -1,305 +0,0 @@ -// ISO C9x compliant inttypes.h for Microsoft Visual Studio -// Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124 -// -// Copyright (c) 2006 Alexander Chemeris -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, -// this list of conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// -// 3. The name of the author may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED -// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO -// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; -// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR -// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF -// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -/////////////////////////////////////////////////////////////////////////////// - -#ifndef _MSC_VER // [ -#error "Use this header only with Microsoft Visual C++ compilers!" -#endif // _MSC_VER ] - -#ifndef _MSC_INTTYPES_H_ // [ -#define _MSC_INTTYPES_H_ - -#if _MSC_VER > 1000 -#pragma once -#endif - -#include "stdint.h" - -// 7.8 Format conversion of integer types - -typedef struct { - intmax_t quot; - intmax_t rem; -} imaxdiv_t; - -// 7.8.1 Macros for format specifiers - -#if !defined(__cplusplus) || defined(__STDC_FORMAT_MACROS) // [ See footnote 185 at page 198 - -// The fprintf macros for signed integers are: -#define PRId8 "d" -#define PRIi8 "i" -#define PRIdLEAST8 "d" -#define PRIiLEAST8 "i" -#define PRIdFAST8 "d" -#define PRIiFAST8 "i" - -#define PRId16 "hd" -#define PRIi16 "hi" -#define PRIdLEAST16 "hd" -#define PRIiLEAST16 "hi" -#define PRIdFAST16 "hd" -#define PRIiFAST16 "hi" - -#define PRId32 "I32d" -#define PRIi32 "I32i" -#define PRIdLEAST32 "I32d" -#define PRIiLEAST32 "I32i" -#define PRIdFAST32 "I32d" -#define PRIiFAST32 "I32i" - -#define PRId64 "I64d" -#define PRIi64 "I64i" -#define PRIdLEAST64 "I64d" -#define PRIiLEAST64 "I64i" -#define PRIdFAST64 "I64d" -#define PRIiFAST64 "I64i" - -#define PRIdMAX "I64d" -#define PRIiMAX "I64i" - -#define PRIdPTR "Id" -#define PRIiPTR "Ii" - -// The fprintf macros for unsigned integers are: -#define PRIo8 "o" -#define PRIu8 "u" -#define PRIx8 "x" -#define PRIX8 "X" -#define PRIoLEAST8 "o" -#define PRIuLEAST8 "u" -#define PRIxLEAST8 "x" -#define PRIXLEAST8 "X" -#define PRIoFAST8 "o" -#define PRIuFAST8 "u" -#define PRIxFAST8 "x" -#define PRIXFAST8 "X" - -#define PRIo16 "ho" -#define PRIu16 "hu" -#define PRIx16 "hx" -#define PRIX16 "hX" -#define PRIoLEAST16 "ho" -#define PRIuLEAST16 "hu" -#define PRIxLEAST16 "hx" -#define PRIXLEAST16 "hX" -#define PRIoFAST16 "ho" -#define PRIuFAST16 "hu" -#define PRIxFAST16 "hx" -#define PRIXFAST16 "hX" - -#define PRIo32 "I32o" -#define PRIu32 "I32u" -#define PRIx32 "I32x" -#define PRIX32 "I32X" -#define PRIoLEAST32 "I32o" -#define PRIuLEAST32 "I32u" -#define PRIxLEAST32 "I32x" -#define PRIXLEAST32 "I32X" -#define PRIoFAST32 "I32o" -#define PRIuFAST32 "I32u" -#define PRIxFAST32 "I32x" -#define PRIXFAST32 "I32X" - -#define PRIo64 "I64o" -#define PRIu64 "I64u" -#define PRIx64 "I64x" -#define PRIX64 "I64X" -#define PRIoLEAST64 "I64o" -#define PRIuLEAST64 "I64u" -#define PRIxLEAST64 "I64x" -#define PRIXLEAST64 "I64X" -#define PRIoFAST64 "I64o" -#define PRIuFAST64 "I64u" -#define PRIxFAST64 "I64x" -#define PRIXFAST64 "I64X" - -#define PRIoMAX "I64o" -#define PRIuMAX "I64u" -#define PRIxMAX "I64x" -#define PRIXMAX "I64X" - -#define PRIoPTR "Io" -#define PRIuPTR "Iu" -#define PRIxPTR "Ix" -#define PRIXPTR "IX" - -// The fscanf macros for signed integers are: -#define SCNd8 "d" -#define SCNi8 "i" -#define SCNdLEAST8 "d" -#define SCNiLEAST8 "i" -#define SCNdFAST8 "d" -#define SCNiFAST8 "i" - -#define SCNd16 "hd" -#define SCNi16 "hi" -#define SCNdLEAST16 "hd" -#define SCNiLEAST16 "hi" -#define SCNdFAST16 "hd" -#define SCNiFAST16 "hi" - -#define SCNd32 "ld" -#define SCNi32 "li" -#define SCNdLEAST32 "ld" -#define SCNiLEAST32 "li" -#define SCNdFAST32 "ld" -#define SCNiFAST32 "li" - -#define SCNd64 "I64d" -#define SCNi64 "I64i" -#define SCNdLEAST64 "I64d" -#define SCNiLEAST64 "I64i" -#define SCNdFAST64 "I64d" -#define SCNiFAST64 "I64i" - -#define SCNdMAX "I64d" -#define SCNiMAX "I64i" - -#ifdef _WIN64 // [ -# define SCNdPTR "I64d" -# define SCNiPTR "I64i" -#else // _WIN64 ][ -# define SCNdPTR "ld" -# define SCNiPTR "li" -#endif // _WIN64 ] - -// The fscanf macros for unsigned integers are: -#define SCNo8 "o" -#define SCNu8 "u" -#define SCNx8 "x" -#define SCNX8 "X" -#define SCNoLEAST8 "o" -#define SCNuLEAST8 "u" -#define SCNxLEAST8 "x" -#define SCNXLEAST8 "X" -#define SCNoFAST8 "o" -#define SCNuFAST8 "u" -#define SCNxFAST8 "x" -#define SCNXFAST8 "X" - -#define SCNo16 "ho" -#define SCNu16 "hu" -#define SCNx16 "hx" -#define SCNX16 "hX" -#define SCNoLEAST16 "ho" -#define SCNuLEAST16 "hu" -#define SCNxLEAST16 "hx" -#define SCNXLEAST16 "hX" -#define SCNoFAST16 "ho" -#define SCNuFAST16 "hu" -#define SCNxFAST16 "hx" -#define SCNXFAST16 "hX" - -#define SCNo32 "lo" -#define SCNu32 "lu" -#define SCNx32 "lx" -#define SCNX32 "lX" -#define SCNoLEAST32 "lo" -#define SCNuLEAST32 "lu" -#define SCNxLEAST32 "lx" -#define SCNXLEAST32 "lX" -#define SCNoFAST32 "lo" -#define SCNuFAST32 "lu" -#define SCNxFAST32 "lx" -#define SCNXFAST32 "lX" - -#define SCNo64 "I64o" -#define SCNu64 "I64u" -#define SCNx64 "I64x" -#define SCNX64 "I64X" -#define SCNoLEAST64 "I64o" -#define SCNuLEAST64 "I64u" -#define SCNxLEAST64 "I64x" -#define SCNXLEAST64 "I64X" -#define SCNoFAST64 "I64o" -#define SCNuFAST64 "I64u" -#define SCNxFAST64 "I64x" -#define SCNXFAST64 "I64X" - -#define SCNoMAX "I64o" -#define SCNuMAX "I64u" -#define SCNxMAX "I64x" -#define SCNXMAX "I64X" - -#ifdef _WIN64 // [ -# define SCNoPTR "I64o" -# define SCNuPTR "I64u" -# define SCNxPTR "I64x" -# define SCNXPTR "I64X" -#else // _WIN64 ][ -# define SCNoPTR "lo" -# define SCNuPTR "lu" -# define SCNxPTR "lx" -# define SCNXPTR "lX" -#endif // _WIN64 ] - -#endif // __STDC_FORMAT_MACROS ] - -// 7.8.2 Functions for greatest-width integer types - -// 7.8.2.1 The imaxabs function -#define imaxabs _abs64 - -// 7.8.2.2 The imaxdiv function - -// This is modified version of div() function from Microsoft's div.c found -// in %MSVC.NET%\crt\src\div.c -#ifdef STATIC_IMAXDIV // [ -static -#else // STATIC_IMAXDIV ][ -_inline -#endif // STATIC_IMAXDIV ] -imaxdiv_t __cdecl imaxdiv(intmax_t numer, intmax_t denom) -{ - imaxdiv_t result; - - result.quot = numer / denom; - result.rem = numer % denom; - - if (numer < 0 && result.rem > 0) { - // did division wrong; must fix up - ++result.quot; - result.rem -= denom; - } - - return result; -} - -// 7.8.2.3 The strtoimax and strtoumax functions -#define strtoimax _strtoi64 -#define strtoumax _strtoui64 - -// 7.8.2.4 The wcstoimax and wcstoumax functions -#define wcstoimax _wcstoi64 -#define wcstoumax _wcstoui64 - - -#endif // _MSC_INTTYPES_H_ ] diff --git a/plugins/Dbx_tree/lockfree_hashmap.h b/plugins/Dbx_tree/lockfree_hashmap.h deleted file mode 100644 index 7ec2df3ce4..0000000000 --- a/plugins/Dbx_tree/lockfree_hashmap.h +++ /dev/null @@ -1,749 +0,0 @@ -#pragma once - -/* - -lockfree hash-multi_map based on Ori Shalev and Nir Shavit - -implementation -Copyright 2009-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. - -*/ - -#pragma once - -#include -#include "Hash.h" -#include "intrinsics.h" - -#define NodePointer(listitem) ((PListItem)(((uintptr_t)(listitem)) & ~1)) -#define NodeMark(listitem) ((bool) (((uintptr_t)(listitem)) & 1)) - -#define HashTablePtr(hashtable) ((PHashTable)(((uintptr_t)(hashtable)) & ~31)) -#define HashTableSize(hashtable) ((uint32_t)(((uintptr_t)(hashtable)) & 31)) -#define HashTable(tableptr, tablesize) ((void*)(((uintptr_t)(tableptr)) | ((tablesize) & 31))) - -#define GCSelection(Sentinel) ((Sentinel) >> 63) -#define GCRefCount0(Sentinel) ((Sentinel) & 0x7fffffff) -#define GCRefCount1(Sentinel) (((Sentinel) >> 32) & 0x7fffffff) -#define GCMakeSentinel(Sel, RefCount0, RefCount1) ((((uint64_t)(Sel) & 1) << 63) | (((uint64_t)(RefCount1)) << 32) | ((uint64_t)(RefCount0))) - -#define GCRef0 (1) -#define GCRef1 (0x0000000100000000) - -namespace lockfree -{ - template - class hash_map - { - public: - typedef std::pair value_type; - - private: - typedef struct TListItem - { - TListItem * volatile Next; - TListItem * volatile NextPurge; - volatile uint32_t Hash; - value_type Value; - } TListItem, *PListItem; - - typedef struct THashTable - { - volatile PListItem Table[256]; - } THashTable, *PHashTable; - - typedef struct { - volatile uint64_t Sentinel; - volatile PListItem Purge0; - volatile PListItem Purge1; - } THashTableReferences; - - THashTableReferences m_GarbageCollector; - - volatile uint32_t m_Count; - void * volatile m_HashTableData; - - PListItem listInsert(PListItem BucketNode, PListItem Node); - PListItem listDelete(PListItem BucketNode, uint32_t Hash, const TKey & Key); - - PListItem listDelete(PListItem BucketNode, PListItem Node); - - bool listFind(const PListItem BucketNode, const uint32_t Hash, const TKey & Key, const PListItem Node, volatile PListItem * & Prev, PListItem & Curr, PListItem & Next); - - uint32_t getMask(uint32_t Size) - { - const uint32_t mask[32] = { - 0x80000000, 0xc0000000, 0xe0000000, 0xf0000000, - 0xf8000000, 0xfc000000, 0xfe000000, 0xff000000, - 0xff800000, 0xffc00000, 0xffe00000, 0xfff00000, - 0xfff80000, 0xfffc0000, 0xfffe0000, 0xffff0000, - 0xffff8000, 0xffffc000, 0xffffe000, 0xfffff000, - 0xfffff800, 0xfffffc00, 0xfffffe00, 0xffffff00, - 0xffffff80, 0xffffffc0, 0xffffffe0, 0xfffffff0, - 0xfffffff8, 0xfffffffc, 0xfffffffe, 0xffffffff - }; - return mask[Size - 1]; - }; - - PHashTable makeNewTable() - { - void * block = malloc(sizeof(THashTable) + 32 + sizeof(void*)); - PHashTable result = reinterpret_cast((reinterpret_cast(block) + 31 + sizeof(void*)) & (~(uintptr_t)31)); - *(reinterpret_cast(result)-1) = block; - memset(reinterpret_cast(result), 0, sizeof(THashTable)); - return reinterpret_cast(result); - }; - - void destroyTable(PHashTable Table) - { - free(*(reinterpret_cast(Table) - 1)); - }; - - PListItem makeDummyNode(uint32_t Hash) - { - PListItem result = new TListItem; - result->Hash = Hash; - result->Next = NULL; - result->NextPurge = NULL; - return result; - }; - - bool DisposeNode(volatile PListItem * Prev, PListItem Curr, PListItem Next); - - PListItem initializeBucket(uint32_t Bucket, uint32_t Mask); - - PListItem getBucket(uint32_t Bucket); - - void setBucket(uint32_t Bucket, PListItem Dummy); - - void DeleteTable(void * Table, uint32_t Size) - { - if (Size > 8) - { - for (uint32_t i = 0; i < 256; ++i) - { - if (HashTablePtr(Table)->Table[i]) - DeleteTable(HashTablePtr(Table)->Table[i], Size - 8); - } - } - - destroyTable(HashTablePtr(Table)); - }; - - - int addRef(int GC = -1); - void delRef(int GC); - - public: - - - class iterator - { - protected: - friend class hash_map; - PListItem m_Item; - typename hash_map * m_Owner; - int m_GC; - - iterator(hash_map * Owner, PListItem Item, int GC) - : m_Owner(Owner) - { - m_GC = GC; - m_Item = Item; - - while (m_Item && (!(m_Item->Hash & 1) || NodeMark(m_Item->Next))) - m_Item = NodePointer(m_Item->Next); - - if (!m_Item && (m_GC != -1)) - { - m_Owner->delRef(m_GC); - m_GC = -1; - } - - }; - public: - iterator(const iterator & Other) - : m_Owner(Other.m_Owner), - m_Item(Other.m_Item) - { - m_GC = -1; - if (Other.m_GC != -1) - m_GC = m_Owner->addRef(Other.m_GC); - }; - ~iterator() - { - if (m_GC != -1) - m_Owner->delRef(m_GC); - }; - - operator bool() const - { - return m_Item != NULL; - }; - bool operator !() const - { - return m_Item == NULL; - }; - - value_type * operator ->() - { - return &m_Item->Value; - }; - value_type & operator *() - { - return m_Item->Value; - }; - - bool operator ==(iterator& Other) - { - return m_Item->Value.first == Other.m_Item->Value.first; - }; - bool operator < (iterator & Other) - { - return m_Item->Value.first < Other.m_Item->Value.first; - }; - bool operator > (iterator & Other) - { - return m_Item->Value.first > Other.m_Item->Value.first; - }; - - iterator& operator =(const iterator& Other) - { - m_Owner = Other.m_Owner; - m_Item = Other.m_Item; - - if (Other.m_GC != m_GC) - { - if (m_GC != -1) - m_Owner->delRef(m_GC); - - m_GC = Other.m_GC; - - if (Other.m_GC != -1) - m_GC = m_Owner->addRef(Other.m_GC); - - } - - return *this; - }; - - iterator& operator ++() //pre ++i - { - if (!m_Item) - return *this; - - int gc = m_GC; - m_GC = m_Owner->addRef(); - do - { - m_Item = NodePointer(m_Item->Next); - } while (m_Item && (!(m_Item->Hash & 1) || NodeMark(m_Item->Next))); - - m_Owner->delRef(gc); - if (!m_Item) - { - m_Owner->delRef(m_GC); - m_GC = -1; - } - return *this; - }; - iterator operator ++(int) //post i++ - { - iterator bak(*this); - ++(*this); - return bak; - }; - }; - - iterator begin() - { - return iterator(this, getBucket(0), addRef()); - }; - - iterator end() - { - return iterator(this, NULL, -1); - }; - - hash_map(); - ~hash_map(); - - std::pair insert(const value_type & Val); - - iterator find(const TKey & Key); - - iterator erase(const iterator & Where); - - size_t erase(const TKey & Key); - - }; - - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - - template - int hash_map::addRef(int GC = -1) - { - uint64_t old; - uint64_t newvalue; - int res; - do { - old = m_GarbageCollector.Sentinel; - if (GC == 0) // this is safe because refcount will never fall to zero because of the original reference - { - newvalue = old + GCRef0; - res = 0; - } else if (GC == 1) - { - newvalue = old + GCRef1; - res = 1; - } else { - if (GCSelection(old)) - { - newvalue = old + GCRef1; - res = 1; - } else { - newvalue = old + GCRef0; - res = 0; - } - } - } - while (CMPXCHG_64(m_GarbageCollector.Sentinel, newvalue, old) != old); - - return res; - }; - - template - void hash_map::delRef(int GC) - { - uint64_t old; - uint64_t newvalue; - PListItem purge = NULL; - do { - old = m_GarbageCollector.Sentinel; - if (GC) - { - newvalue = old - GCRef1; - - if (!GCSelection(old) && (GCRefCount1(old) == 1)) // the other gc is activated and we are the last one - { - if (!purge) // check if we had to loop... - purge = m_GarbageCollector.Purge1; - - m_GarbageCollector.Purge1 = NULL; - } - - } else { - newvalue = old - GCRef0; - - if (GCSelection(old) && (GCRefCount0(old) == 1)) // the other gc is activated and we are the last one - { - if (!purge) // check if we had to loop... - purge = m_GarbageCollector.Purge0; - - m_GarbageCollector.Purge0 = NULL; - } - - } - } while (CMPXCHG_64(m_GarbageCollector.Sentinel, newvalue, old) != old); - - purge = NodePointer(purge); - while (purge) - { - PListItem tmp = purge; - purge = purge->NextPurge; - delete tmp; - }; - }; - - - - template - bool hash_map::DisposeNode(volatile PListItem * Prev, PListItem Curr, PListItem Next) - { - if (NodePointer(Curr) == CMPXCHG_Ptr(*Prev, NodePointer(Next), NodePointer(Curr))) - { - uint64_t old = m_GarbageCollector.Sentinel; - PListItem del = NodePointer(Curr); - - if (GCSelection(old)) - { - del->NextPurge = (PListItem)XCHG_Ptr(m_GarbageCollector.Purge1, del); - - if (!GCRefCount0(old)) - BTR_64(m_GarbageCollector.Sentinel, 63); // switch - - } else { - - del->NextPurge = (PListItem)XCHG_Ptr(m_GarbageCollector.Purge0, del); - - if (!GCRefCount1(old)) - BTS_64(m_GarbageCollector.Sentinel, 63); // switch - - } - return true; - } - - return false; - }; - - - template - typename hash_map::PListItem hash_map::listInsert(PListItem BucketNode, PListItem Node) - { - PListItem volatile * prev; - PListItem curr, next; - do - { - if (listFind(BucketNode, Node->Hash, Node->Value.first, NULL, prev, curr, next)) - return NodePointer(curr); - - Node->Next = NodePointer(curr); - - } while (NodePointer(curr) != CMPXCHG_Ptr(*prev, Node, NodePointer(curr))); - return Node; - }; - - - template - typename hash_map::PListItem hash_map::listDelete(PListItem BucketNode, uint32_t Hash, const TKey & Key) - { - PListItem volatile * prev; - PListItem curr, next; - - if (!listFind(BucketNode, Hash, Key, NULL, prev, curr, next)) - return NodePointer(curr); - - do - { - if (!listFind(BucketNode, Hash, Key, NULL, prev, curr, next)) - return NodePointer(curr); - - } while (NodePointer(next) != CMPXCHG_Ptr(curr->Next, (PListItem)((uintptr_t)next | 1), NodePointer(next))); - - if (!DisposeNode(prev, curr, next)) - listFind(BucketNode, Hash, Key, NULL, prev, curr, next); // cleanup - - return NodePointer(curr); - }; - - template - typename hash_map::PListItem hash_map::listDelete(PListItem BucketNode, PListItem Node) - { - PListItem volatile * prev; - PListItem curr, next; - if (!listFind(BucketNode, Node->Hash, Node->Value.first, Node, prev, curr, next)) - return NodePointer(curr); - - do - { - if (!listFind(BucketNode, Node->Hash, Node->Value.first, Node, prev, curr, next)) - return NodePointer(curr); - - } while (NodePointer(next) != CMPXCHG_Ptr(curr->Next, (PListItem)((uintptr_t)next | 1), NodePointer(next))); - - if (!DisposeNode(prev, curr, next)) - listFind(BucketNode, Node->Hash, Node->Value.first, Node, prev, curr, next); // cleanup - - return NodePointer(curr); - }; - - template - bool hash_map::listFind(const PListItem BucketNode, const uint32_t Hash, const TKey & Key, const PListItem Node, volatile PListItem * & Prev, PListItem & Curr, PListItem & Next) - { -tryagain: - Prev = &(BucketNode->Next); - Curr = *Prev; - do - { - if (NodePointer(Curr) == NULL) - return false; - - Next = NodePointer(Curr)->Next; - uint32_t h = NodePointer(Curr)->Hash; - - if (*Prev != NodePointer(Curr)) - goto tryagain; // don't judge me for that - //return listFind(BucketNode, Hash, Key, Node, Prev, Curr, Next); // it's the same but stack overflow can happen - - if (!NodeMark(Next)) - { - if (Node) - { - if ((h > Hash) || (Node == NodePointer(Curr))) - return NodePointer(Curr) == Node; - } - else if ((h > Hash) || ((h == Hash) && !(NodePointer(Curr)->Value.first < Key))) - { - return (h == Hash) && (NodePointer(Curr)->Value.first == Key); - } - - Prev = &(NodePointer(Curr)->Next); - } else { - if (!DisposeNode(Prev, Curr, Next)) - goto tryagain; // don't judge me for that - //return listFind(BucketNode, Hash, Key, Node, Prev, Curr, Next); // it's the same but stack overflow can happen - } - Curr = Next; - } while (true); - - }; - - - template - typename hash_map::PListItem hash_map::initializeBucket(uint32_t Bucket, uint32_t Mask) - { - uint32_t parent = Bucket & (Mask << 1); - PListItem parentnode = getBucket(parent); - if (parentnode == NULL) - parentnode = initializeBucket(parent, Mask << 1); - - PListItem dummy = makeDummyNode(Bucket); - PListItem bucketnode = listInsert(parentnode, dummy); - if (bucketnode != dummy) - { - delete dummy; - dummy = bucketnode; - } - setBucket(Bucket, dummy); - - return dummy; - } - - template - typename hash_map::PListItem hash_map::getBucket(uint32_t Bucket) - { - void * table; - uint32_t mask; - - table = (void*)m_HashTableData; - mask = getMask(HashTableSize(table)); - - uint32_t levelshift = (32 - HashTableSize(table)) & ~7; - - while (levelshift < 24) - { - table = HashTablePtr(table)->Table[((Bucket & mask) >> levelshift) & 0xff]; - levelshift = levelshift + 8; - if (!HashTablePtr(table)) - return NULL; - } - return HashTablePtr(table)->Table[(Bucket & mask) >> 24]; - }; - - template - void hash_map::setBucket(uint32_t Bucket, PListItem Dummy) - { - void * table; - void *volatile * last; - uint32_t mask; - - table = m_HashTableData; - mask = getMask(HashTableSize(table)); - - uint32_t levelshift = (32 - HashTableSize(table)) & ~7; - - while (levelshift < 24) - { - last = (void*volatile*)&HashTablePtr(table)->Table[((Bucket & mask) >> levelshift) & 0xff]; - table = *last; - levelshift = levelshift + 8; - if (!table) - { - PHashTable newtable = makeNewTable(); - table = CMPXCHG_Ptr(*last, newtable, NULL); - if (table) - { - destroyTable(newtable); - } else { - table = newtable; - } - } - } - HashTablePtr(table)->Table[(Bucket & mask) >> 24] = Dummy; - }; - - template - hash_map::hash_map() - { - m_Count = 0; - - m_GarbageCollector.Sentinel = GCMakeSentinel(0,0,0); - m_GarbageCollector.Purge0 = NULL; - m_GarbageCollector.Purge1 = NULL; - - m_HashTableData = HashTable(makeNewTable(), 1); - setBucket(0x00000000, makeDummyNode(0x00000000)); - setBucket(0x80000000, makeDummyNode(0x80000000)); - HashTablePtr(m_HashTableData)->Table[0]->Next = getBucket(0x80000000); - }; - - template - hash_map::~hash_map() - { - PListItem h = getBucket(0); - DeleteTable(HashTablePtr(m_HashTableData), HashTableSize(m_HashTableData)); - - while (h) - { - PListItem tmp = h; - h = NodePointer(h->Next); - delete tmp; - }; - - h = m_GarbageCollector.Purge0; - while (h) - { - PListItem tmp = h; - h = h->NextPurge; - delete tmp; - }; - - h = m_GarbageCollector.Purge1; - while (h) - { - PListItem tmp = h; - h = h->NextPurge; - delete tmp; - }; - - }; - - template - typename std::pair::iterator, bool> hash_map::insert(const value_type & Val) - { - int gc = addRef(); - PListItem node = new TListItem; - node->Value = Val; - node->Hash = FHash(&node->Value.first, sizeof(TKey)) | 1; - node->NextPurge = NULL; - node->Next = NULL; - - void * tmp; - void * newdata; - tmp = (void*)m_HashTableData; - - uint32_t mask = getMask(HashTableSize(tmp)); - - uint32_t bucket = node->Hash & mask; - PListItem bucketnode = getBucket(bucket); - - if (bucketnode == NULL) - bucketnode = initializeBucket(bucket, mask); - PListItem retnode = listInsert(bucketnode, node); - if (retnode != node) - { - delete node; - return std::make_pair(iterator(this, retnode, gc), false); - } - - if ((INC_32(m_Count) > ((uint32_t)1 << (HashTableSize(tmp) + 3))) && (HashTableSize(tmp) < 31) && (HashTableSize(tmp) == HashTableSize(m_HashTableData))) - { - newdata = HashTable(HashTablePtr(tmp), HashTableSize(tmp) + 1); - - if ((HashTableSize(tmp) & 0x7) == 0) - { - newdata = HashTable(makeNewTable(), HashTableSize(tmp) + 1); - HashTablePtr(newdata)->Table[0] = (TListItem*)HashTablePtr(tmp); - - if (tmp != CMPXCHG_Ptr(m_HashTableData, newdata, tmp)) - destroyTable(HashTablePtr(newdata)); // someone else expanded the table. - } else { - CMPXCHG_Ptr(m_HashTableData, newdata, tmp); - } - - } - - return std::make_pair(iterator(this, node, gc), true); - }; - - template - typename hash_map::iterator hash_map::find(const TKey & Key) - { - int gc = addRef(); - uint32_t hash = FHash(&Key, sizeof(TKey)) | 1; - uint32_t mask = getMask(HashTableSize(m_HashTableData)); - uint32_t bucket = hash & mask; - PListItem bucketnode = getBucket(bucket); - if (bucketnode == NULL) - bucketnode = initializeBucket(bucket, mask); - - PListItem volatile * prev; - PListItem curr, next; - if (listFind(bucketnode, hash, Key, NULL, prev, curr, next)) - return iterator(this, NodePointer(curr), gc); - - return iterator(this, NULL, gc); - }; - - template - typename hash_map::iterator hash_map::erase(const iterator & Where) - { - int gc = addRef(); - uint32_t hash = Where.m_Item->Hash; - uint32_t mask = getMask(HashTableSize(m_HashTableData)); - uint32_t bucket = hash & mask; - PListItem bucketnode = getBucket(bucket); - - if (bucketnode == NULL) - bucketnode = initializeBucket(bucket, mask); - - PListItem res = listDelete(bucketnode, Where.m_Item); - if (Where.m_Item == res) - { - DEC_32(m_Count); - return iterator(this, NodePointer(res->Next), gc); - } - return iterator(this, res, gc); - }; - - template - size_t hash_map::erase(const TKey & Key) - { - int gc = addRef(); - uint32_t hash = FHash(&Key, sizeof(TKey)) | 1; - uint32_t mask = getMask(HashTableSize(m_HashTableData)); - uint32_t bucket = hash & mask; - PListItem bucketnode = getBucket(bucket); - - if (bucketnode == NULL) - bucketnode = initializeBucket(bucket, mask); - - PListItem result = listDelete(bucketnode, hash, Key); - if (result && (result->Value.first == Key)) - { - DEC_32(m_Count); - delRef(gc); - return 1; - } - - delRef(gc); - return 0; - }; -} - -#undef NodePointer -#undef NodeMark - -#undef HashTablePtr -#undef HashTableSize -#undef HashTable - -#undef GCSelection -#undef GCRefCount0 -#undef GCRefCount1 -#undef GCMakeSentinel - diff --git a/plugins/Dbx_tree/lockfree_hashmultimap.h b/plugins/Dbx_tree/lockfree_hashmultimap.h deleted file mode 100644 index 79981e5447..0000000000 --- a/plugins/Dbx_tree/lockfree_hashmultimap.h +++ /dev/null @@ -1,750 +0,0 @@ -#pragma once - -/* - -lockfree hash-multi_map based on Ori Shalev and Nir Shavit - -implementation -Copyright 2009-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. - -*/ - -#pragma once - -#include -#include "Hash.h" -#include "intrinsics.h" - -#define NodePointer(listitem) ((PListItem)(((uintptr_t)(listitem)) & ~1)) -#define NodeMark(listitem) ((bool) (((uintptr_t)(listitem)) & 1)) - -#define HashTablePtr(hashtable) ((PHashTable)(((uintptr_t)(hashtable)) & ~31)) -#define HashTableSize(hashtable) ((uint32_t)(((uintptr_t)(hashtable)) & 31)) -#define HashTable(tableptr, tablesize) ((void*)(((uintptr_t)(tableptr)) | ((tablesize) & 31))) - -#define GCSelection(Sentinel) ((Sentinel) >> 63) -#define GCRefCount0(Sentinel) ((Sentinel) & 0x7fffffff) -#define GCRefCount1(Sentinel) (((Sentinel) >> 32) & 0x7fffffff) -#define GCMakeSentinel(Sel, RefCount0, RefCount1) ((((uint64_t)(Sel) & 1) << 63) | (((uint64_t)(RefCount1)) << 32) | ((uint64_t)(RefCount0))) - -#define GCRef0 (1) -#define GCRef1 (0x0000000100000000) - -namespace lockfree -{ - template - class hash_multimap - { - public: - typedef std::pair value_type; - - private: - typedef struct TListItem - { - TListItem * volatile Next; - TListItem * volatile NextPurge; - volatile uint32_t Hash; - value_type Value; - } TListItem, *PListItem; - - typedef struct THashTable - { - volatile PListItem Table[256]; - } THashTable, *PHashTable; - - typedef struct { - volatile uint64_t Sentinel; - volatile PListItem Purge0; - volatile PListItem Purge1; - } THashTableReferences; - - THashTableReferences m_GarbageCollector; - - volatile uint32_t m_Count; - void * volatile m_HashTableData; - - PListItem listInsert(PListItem BucketNode, PListItem Node); - PListItem listDelete(PListItem BucketNode, uint32_t Hash, const TKey & Key); - - PListItem listDelete(PListItem BucketNode, PListItem Node); - - bool listFind(const PListItem BucketNode, const uint32_t Hash, const TKey & Key, const PListItem Node, volatile PListItem * & Prev, PListItem & Curr, PListItem & Next); - - uint32_t getMask(uint32_t Size) - { - const uint32_t mask[32] = { - 0x80000000, 0xc0000000, 0xe0000000, 0xf0000000, - 0xf8000000, 0xfc000000, 0xfe000000, 0xff000000, - 0xff800000, 0xffc00000, 0xffe00000, 0xfff00000, - 0xfff80000, 0xfffc0000, 0xfffe0000, 0xffff0000, - 0xffff8000, 0xffffc000, 0xffffe000, 0xfffff000, - 0xfffff800, 0xfffffc00, 0xfffffe00, 0xffffff00, - 0xffffff80, 0xffffffc0, 0xffffffe0, 0xfffffff0, - 0xfffffff8, 0xfffffffc, 0xfffffffe, 0xffffffff - }; - return mask[Size - 1]; - }; - - PHashTable makeNewTable() - { - void * block = malloc(sizeof(THashTable) + 32 + sizeof(void*)); - PHashTable result = reinterpret_cast((reinterpret_cast(block) + 31 + sizeof(void*)) & (~(uintptr_t)31)); - *(reinterpret_cast(result)-1) = block; - memset(reinterpret_cast(result), 0, sizeof(THashTable)); - return reinterpret_cast(result); - }; - - void destroyTable(PHashTable Table) - { - free(*(reinterpret_cast(Table) - 1)); - }; - - PListItem makeDummyNode(uint32_t Hash) - { - PListItem result = new TListItem; - result->Hash = Hash; - result->Next = NULL; - result->NextPurge = NULL; - return result; - }; - - bool DisposeNode(volatile PListItem * Prev, PListItem Curr, PListItem Next); - - PListItem initializeBucket(uint32_t Bucket, uint32_t Mask); - - PListItem getBucket(uint32_t Bucket); - - void setBucket(uint32_t Bucket, PListItem Dummy); - - void DeleteTable(void * Table, uint32_t Size) - { - if (Size > 8) - { - for (uint32_t i = 0; i < 256; ++i) - { - if (HashTablePtr(Table)->Table[i]) - DeleteTable(HashTablePtr(Table)->Table[i], Size - 8); - } - } - - destroyTable(HashTablePtr(Table)); - }; - - - int addRef(int GC = -1); - void delRef(int GC); - - public: - - - class iterator - { - protected: - friend class hash_multimap; - PListItem m_Item; - typename hash_multimap * m_Owner; - int m_GC; - - iterator(hash_multimap * Owner, PListItem Item, int GC) - : m_Owner(Owner) - { - m_GC = GC; - m_Item = Item; - - while (m_Item && (!(m_Item->Hash & 1) || NodeMark(m_Item->Next))) - m_Item = NodePointer(m_Item->Next); - - if (!m_Item && (m_GC != -1)) - { - m_Owner->delRef(m_GC); - m_GC = -1; - } - - }; - public: - iterator(const iterator & Other) - : m_Owner(Other.m_Owner), - m_Item(Other.m_Item) - { - m_GC = -1; - if (Other.m_GC != -1) - m_GC = m_Owner->addRef(Other.m_GC); - }; - ~iterator() - { - if (m_GC != -1) - m_Owner->delRef(m_GC); - }; - - operator bool() const - { - return m_Item != NULL; - }; - bool operator !() const - { - return m_Item == NULL; - }; - - value_type * operator ->() - { - return &m_Item->Value; - }; - value_type & operator *() - { - return m_Item->Value; - }; - - bool operator ==(iterator& Other) - { - return m_Item->Value.first == Other.m_Item->Value.first; - }; - bool operator < (iterator & Other) - { - return m_Item->Value.first < Other.m_Item->Value.first; - }; - bool operator > (iterator & Other) - { - return m_Item->Value.first > Other.m_Item->Value.first; - }; - - iterator& operator =(const iterator& Other) - { - m_Owner = Other.m_Owner; - m_Item = Other.m_Item; - - if (Other.m_GC != m_GC) - { - if (m_GC != -1) - m_Owner->delRef(m_GC); - - m_GC = Other.m_GC; - - if (Other.m_GC != -1) - m_GC = m_Owner->addRef(Other.m_GC); - - } - - return *this; - }; - - iterator& operator ++() //pre ++i - { - if (!m_Item) - return *this; - - int gc = m_GC; - m_GC = m_Owner->addRef(); - do - { - m_Item = NodePointer(m_Item->Next); - } while (m_Item && (!(m_Item->Hash & 1) || NodeMark(m_Item->Next))); - - m_Owner->delRef(gc); - if (!m_Item) - { - m_Owner->delRef(m_GC); - m_GC = -1; - } - return *this; - }; - iterator operator ++(int) //post i++ - { - iterator bak(*this); - ++(*this); - return bak; - }; - }; - - iterator begin() - { - return iterator(this, getBucket(0), addRef()); - }; - - iterator end() - { - return iterator(this, NULL, -1); - }; - - hash_multimap(); - ~hash_multimap(); - - std::pair insert(const value_type & Val); - - iterator find(const TKey & Key); - - iterator erase(const iterator & Where); - - size_t erase(const TKey & Key); - - }; - - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - - template - int hash_multimap::addRef(int GC = -1) - { - uint64_t old; - uint64_t newvalue; - int res; - do { - old = m_GarbageCollector.Sentinel; - if (GC == 0) // this is safe because refcount will never fall to zero because of the original reference - { - newvalue = old + GCRef0; - res = 0; - } else if (GC == 1) - { - newvalue = old + GCRef1; - res = 1; - } else { - if (GCSelection(old)) - { - newvalue = old + GCRef1; - res = 1; - } else { - newvalue = old + GCRef0; - res = 0; - } - } - } - while (CMPXCHG_64(m_GarbageCollector.Sentinel, newvalue, old) != old); - - return res; - }; - - template - void hash_multimap::delRef(int GC) - { - uint64_t old; - uint64_t newvalue; - PListItem purge = NULL; - do { - old = m_GarbageCollector.Sentinel; - if (GC) - { - newvalue = old - GCRef1; - - if (!GCSelection(old) && (GCRefCount1(old) == 1)) // the other gc is activated and we are the last one - { - if (!purge) // check if we had to loop... - purge = m_GarbageCollector.Purge1; - - m_GarbageCollector.Purge1 = NULL; - } - - } else { - newvalue = old - GCRef0; - - if (GCSelection(old) && (GCRefCount0(old) == 1)) // the other gc is activated and we are the last one - { - if (!purge) // check if we had to loop... - purge = m_GarbageCollector.Purge0; - - m_GarbageCollector.Purge0 = NULL; - } - - } - } while (CMPXCHG_64(m_GarbageCollector.Sentinel, newvalue, old) != old); - - purge = NodePointer(purge); - while (purge) - { - PListItem tmp = purge; - purge = purge->NextPurge; - delete tmp; - }; - }; - - - - template - bool hash_multimap::DisposeNode(volatile PListItem * Prev, PListItem Curr, PListItem Next) - { - if (NodePointer(Curr) == CMPXCHG_Ptr(*Prev, NodePointer(Next), NodePointer(Curr))) - { - uint64_t old = m_GarbageCollector.Sentinel; - PListItem del = NodePointer(Curr); - - if (GCSelection(old)) - { - del->NextPurge = (PListItem)XCHG_Ptr(m_GarbageCollector.Purge1, del); - - if (!GCRefCount0(old)) - BTR_64(m_GarbageCollector.Sentinel, 63); // switch - - } else { - - del->NextPurge = (PListItem)XCHG_Ptr(m_GarbageCollector.Purge0, del); - - if (!GCRefCount1(old)) - BTS_64(m_GarbageCollector.Sentinel, 63); // switch - - } - return true; - } - - return false; - }; - - - template - typename hash_multimap::PListItem hash_multimap::listInsert(PListItem BucketNode, PListItem Node) - { - PListItem volatile * prev; - PListItem curr, next; - do - { - listFind(BucketNode, Node->Hash, Node->Value.first, NULL, prev, curr, next); - - Node->Next = NodePointer(curr); - - } while (NodePointer(curr) != CMPXCHG_Ptr(*prev, Node, NodePointer(curr))); - return Node; - }; - - - template - typename hash_multimap::PListItem hash_multimap::listDelete(PListItem BucketNode, uint32_t Hash, const TKey & Key) - { - PListItem volatile * prev; - PListItem curr, next; - - if (!listFind(BucketNode, Hash, Key, NULL, prev, curr, next)) - return NodePointer(curr); - - do - { - if (!listFind(BucketNode, Hash, Key, NULL, prev, curr, next)) - return NodePointer(curr); - - } while (NodePointer(next) != CMPXCHG_Ptr(curr->Next, (PListItem)((uintptr_t)next | 1), NodePointer(next))); - - if (!DisposeNode(prev, curr, next)) - listFind(BucketNode, Hash, Key, NULL, prev, curr, next); // cleanup - - return NodePointer(curr); - }; - - template - typename hash_multimap::PListItem hash_multimap::listDelete(PListItem BucketNode, PListItem Node) - { - PListItem volatile * prev; - PListItem curr, next; - if (!listFind(BucketNode, Node->Hash, Node->Value.first, Node, prev, curr, next)) - return NodePointer(curr); - - do - { - if (!listFind(BucketNode, Node->Hash, Node->Value.first, Node, prev, curr, next)) - return NodePointer(curr); - - } while (NodePointer(next) != CMPXCHG_Ptr(curr->Next, (PListItem)((uintptr_t)next | 1), NodePointer(next))); - - if (!DisposeNode(prev, curr, next)) - listFind(BucketNode, Node->Hash, Node->Value.first, Node, prev, curr, next); // cleanup - - return NodePointer(curr); - }; - - template - bool hash_multimap::listFind(const PListItem BucketNode, const uint32_t Hash, const TKey & Key, const PListItem Node, volatile PListItem * & Prev, PListItem & Curr, PListItem & Next) - { -tryagain: - Prev = &(BucketNode->Next); - Curr = *Prev; - do - { - if (NodePointer(Curr) == NULL) - return false; - - Next = NodePointer(Curr)->Next; - uint32_t h = NodePointer(Curr)->Hash; - - if (*Prev != NodePointer(Curr)) - goto tryagain; // don't judge me for that - //return listFind(BucketNode, Hash, Key, Node, Prev, Curr, Next); // it's the same but stack overflow can happen - - if (!NodeMark(Next)) - { - if (Node) - { - if ((h > Hash) || (Node == NodePointer(Curr))) - return NodePointer(Curr) == Node; - } - else if ((h > Hash) || ((h == Hash) && !(NodePointer(Curr)->Value.first < Key))) - { - return (h == Hash) && (NodePointer(Curr)->Value.first == Key); - } - - Prev = &(NodePointer(Curr)->Next); - } else { - if (!DisposeNode(Prev, Curr, Next)) - goto tryagain; // don't judge me for that - //return listFind(BucketNode, Hash, Key, Node, Prev, Curr, Next); // it's the same but stack overflow can happen - } - Curr = Next; - } while (true); - - }; - - - template - typename hash_multimap::PListItem hash_multimap::initializeBucket(uint32_t Bucket, uint32_t Mask) - { - uint32_t parent = Bucket & (Mask << 1); - PListItem parentnode = getBucket(parent); - if (parentnode == NULL) - parentnode = initializeBucket(parent, Mask << 1); - - PListItem dummy = makeDummyNode(Bucket); - PListItem bucketnode = listInsert(parentnode, dummy); - if (bucketnode != dummy) - { - delete dummy; - dummy = bucketnode; - } - setBucket(Bucket, dummy); - - return dummy; - } - - template - typename hash_multimap::PListItem hash_multimap::getBucket(uint32_t Bucket) - { - void * table; - uint32_t mask; - - table = (void*)m_HashTableData; - mask = getMask(HashTableSize(table)); - - uint32_t levelshift = (32 - HashTableSize(table)) & ~7; - - while (levelshift < 24) - { - table = HashTablePtr(table)->Table[((Bucket & mask) >> levelshift) & 0xff]; - levelshift = levelshift + 8; - if (!HashTablePtr(table)) - return NULL; - } - return HashTablePtr(table)->Table[(Bucket & mask) >> 24]; - }; - - template - void hash_multimap::setBucket(uint32_t Bucket, PListItem Dummy) - { - void * table; - void *volatile * last; - uint32_t mask; - - table = m_HashTableData; - mask = getMask(HashTableSize(table)); - - uint32_t levelshift = (32 - HashTableSize(table)) & ~7; - - while (levelshift < 24) - { - last = (void*volatile*)&HashTablePtr(table)->Table[((Bucket & mask) >> levelshift) & 0xff]; - table = *last; - levelshift = levelshift + 8; - if (!table) - { - PHashTable newtable = makeNewTable(); - table = CMPXCHG_Ptr(*last, newtable, NULL); - if (table) - { - destroyTable(newtable); - } else { - table = newtable; - } - } - } - HashTablePtr(table)->Table[(Bucket & mask) >> 24] = Dummy; - }; - - template - hash_multimap::hash_multimap() - { - m_Count = 0; - - m_GarbageCollector.Sentinel = GCMakeSentinel(0,0,0); - m_GarbageCollector.Purge0 = NULL; - m_GarbageCollector.Purge1 = NULL; - - m_HashTableData = HashTable(makeNewTable(), 1); - setBucket(0x00000000, makeDummyNode(0x00000000)); - setBucket(0x80000000, makeDummyNode(0x80000000)); - HashTablePtr(m_HashTableData)->Table[0]->Next = getBucket(0x80000000); - }; - - template - hash_multimap::~hash_multimap() - { - PListItem h = getBucket(0); - DeleteTable(HashTablePtr(m_HashTableData), HashTableSize(m_HashTableData)); - - while (h) - { - PListItem tmp = h; - h = NodePointer(h->Next); - delete tmp; - }; - - h = m_GarbageCollector.Purge0; - while (h) - { - PListItem tmp = h; - h = h->NextPurge; - delete tmp; - }; - - h = m_GarbageCollector.Purge1; - while (h) - { - PListItem tmp = h; - h = h->NextPurge; - delete tmp; - }; - - }; - - template - typename std::pair::iterator, bool> hash_multimap::insert(const value_type & Val) - { - int gc = addRef(); - PListItem node = new TListItem; - node->Value = Val; - node->Hash = FHash(&node->Value.first, sizeof(TKey)) | 1; - node->NextPurge = NULL; - node->Next = NULL; - - void * tmp; - void * newdata; - tmp = (void*)m_HashTableData; - - uint32_t mask = getMask(HashTableSize(tmp)); - - uint32_t bucket = node->Hash & mask; - PListItem bucketnode = getBucket(bucket); - - if (bucketnode == NULL) - bucketnode = initializeBucket(bucket, mask); - PListItem retnode = listInsert(bucketnode, node); - if (retnode != node) - { - delete node; - return std::make_pair(iterator(this, retnode, gc), false); - } - - if ((INC_32(m_Count) > ((uint32_t)1 << (HashTableSize(tmp) + 3))) && (HashTableSize(tmp) < 31) && (HashTableSize(tmp) == HashTableSize(m_HashTableData))) - { - newdata = HashTable(HashTablePtr(tmp), HashTableSize(tmp) + 1); - - if ((HashTableSize(tmp) & 0x7) == 0) - { - newdata = HashTable(makeNewTable(), HashTableSize(tmp) + 1); - HashTablePtr(newdata)->Table[0] = (TListItem*)HashTablePtr(tmp); - - if (tmp != CMPXCHG_Ptr(m_HashTableData, newdata, tmp)) - destroyTable(HashTablePtr(newdata)); // someone else expanded the table. - } else { - CMPXCHG_Ptr(m_HashTableData, newdata, tmp); - } - - } - - return std::make_pair(iterator(this, node, gc), true); - }; - - template - typename hash_multimap::iterator hash_multimap::find(const TKey & Key) - { - int gc = addRef(); - uint32_t hash = FHash(&Key, sizeof(TKey)) | 1; - uint32_t mask = getMask(HashTableSize(m_HashTableData)); - uint32_t bucket = hash & mask; - PListItem bucketnode = getBucket(bucket); - if (bucketnode == NULL) - bucketnode = initializeBucket(bucket, mask); - - PListItem volatile * prev; - PListItem curr, next; - if (listFind(bucketnode, hash, Key, NULL, prev, curr, next)) - return iterator(this, NodePointer(curr), gc); - - return iterator(this, NULL, gc); - }; - - template - typename hash_multimap::iterator hash_multimap::erase(const iterator & Where) - { - int gc = addRef(); - uint32_t hash = Where.m_Item->Hash; - uint32_t mask = getMask(HashTableSize(m_HashTableData)); - uint32_t bucket = hash & mask; - PListItem bucketnode = getBucket(bucket); - - if (bucketnode == NULL) - bucketnode = initializeBucket(bucket, mask); - - PListItem res = listDelete(bucketnode, Where.m_Item); - if (Where.m_Item == res) - { - DEC_32(m_Count); - return iterator(this, NodePointer(res->Next), gc); - } - return iterator(this, res, gc); - }; - - template - size_t hash_multimap::erase(const TKey & Key) - { - int gc = addRef(); - int count = 0; - uint32_t hash = FHash(&Key, sizeof(TKey)) | 1; - uint32_t mask = getMask(HashTableSize(m_HashTableData)); - uint32_t bucket = hash & mask; - PListItem bucketnode = getBucket(bucket); - - if (bucketnode == NULL) - bucketnode = initializeBucket(bucket, mask); - - PListItem volatile * prev; - PListItem curr, next; - while (listFind(bucketnode, hash, Key, NULL, prev, curr, next)) - { - if (curr == listDelete(bucketnode, curr)) - count++; - } - - XADD_32(m_Count, -count); - delRef(gc); - return count; - }; -} - -#undef NodePointer -#undef NodeMark - -#undef HashTablePtr -#undef HashTableSize -#undef HashTable - -#undef GCSelection -#undef GCRefCount0 -#undef GCRefCount1 -#undef GCMakeSentinel - diff --git a/plugins/Dbx_tree/res/dbConfig.rc b/plugins/Dbx_tree/res/dbConfig.rc new file mode 100644 index 0000000000..0e5745acc9 --- /dev/null +++ b/plugins/Dbx_tree/res/dbConfig.rc @@ -0,0 +1,113 @@ +// Microsoft Visual C++ generated resource script. +// +#include "..\src\dbConfig_rc.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "afxres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// Neutral resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_NEU) +#ifdef _WIN32 +LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL +#pragma code_page(1252) +#endif //_WIN32 + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_DIALOGBAR DIALOGEX 0, 0, 429, 290 +STYLE DS_LOCALEDIT | DS_SETFONT | DS_MODALFRAME | DS_SETFOREGROUND | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU +EXSTYLE WS_EX_APPWINDOW +CAPTION "dbxTree Profile Wizard" +FONT 8, "MS Shell Dlg", 400, 0, 0x0 +BEGIN + PUSHBUTTON "Cancel",IDC_BUTTON1,316,267,54,16 + PUSHBUTTON "Next >",IDC_BUTTON2,254,267,54,16 + PUSHBUTTON "< Prev",IDC_BUTTON3,192,267,54,16 + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,6,258,416,1 + LISTBOX IDC_LIST1,6,6,116,252,LBS_SORT | LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP +END + + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO +BEGIN + IDD_DIALOGBAR, DIALOG + BEGIN + LEFTMARGIN, 6 + RIGHTMARGIN, 422 + TOPMARGIN, 6 + BOTTOMMARGIN, 284 + END +END +#endif // APSTUDIO_INVOKED + +#endif // Neutral resources +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// +// German (Germany) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_DEU) +#ifdef _WIN32 +LANGUAGE LANG_GERMAN, SUBLANG_GERMAN +#pragma code_page(1252) +#endif //_WIN32 + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "..\\src\\dbConfig_rc.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#include ""afxres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + +#endif // German (Germany) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/plugins/Dbx_tree/res/dbVersion.rc b/plugins/Dbx_tree/res/dbVersion.rc new file mode 100644 index 0000000000..5717940ed4 --- /dev/null +++ b/plugins/Dbx_tree/res/dbVersion.rc @@ -0,0 +1,105 @@ +// Microsoft Visual C++ generated resource script. +// +#include "..\src\dbVersion_rc.h" +#define INTERFACE_VERSION_ONLY +#include "..\src\Interface.h" +#undef INTERFACE_VERSION_ONLY + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "afxres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// German (Germany) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_DEU) +#ifdef _WIN32 +LANGUAGE LANG_GERMAN, SUBLANG_GERMAN +#pragma code_page(1252) +#endif //_WIN32 + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "..\\src\\dbVersion_rc.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#include ""afxres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION gResVersion + PRODUCTVERSION gResVersion + FILEFLAGSMASK 0x17L +#ifdef _DEBUG + FILEFLAGS 0x3L +#else + FILEFLAGS 0x2L +#endif + FILEOS 0x4L + FILETYPE 0x2L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "000004b0" + BEGIN + VALUE "CompanyName", gAutor + VALUE "FileDescription", gDescription + VALUE "FileVersion", gResVersionString + VALUE "InternalName", gInternalName + VALUE "LegalCopyright", gCopyright + VALUE "OriginalFilename", "dbx_tree.dll" + VALUE "ProductName", gInternalNameLong + VALUE "ProductVersion", gResVersionString + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x0, 1200 + END +END + +#endif // German (Germany) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/plugins/Dbx_tree/savestrings_gcc.h b/plugins/Dbx_tree/savestrings_gcc.h deleted file mode 100644 index 9da680874d..0000000000 --- a/plugins/Dbx_tree/savestrings_gcc.h +++ /dev/null @@ -1,127 +0,0 @@ -/* - -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. - -*/ - -#pragma once - -inline int strcpy_s( - char *strDestination, - size_t numberOfElements, - const char *strSource -) -{ - if (!strDestination) return EINVAL; - if (!strSource) {strDestination[0] = 0; return EINVAL;} - size_t l = strlen(strSource); - if (numberOfElements < l + 1) {strDestination[0] = 0; return ERANGE;} - memcpy(strDestination, strSource, l + 1); - return 0; -} - -template -inline int strcpy_s( - char (&strDestination)[size], - const char *strSource -) -{ - if (!strDestination) return EINVAL; - if (!strSource) {strDestination[0] = 0; return EINVAL;} - size_t l = strlen(strSource); - if (size < l + 1) {strDestination[0] = 0; return ERANGE;} - - memcpy(strDestination, strSource, l + 1); - return 0; -} - - -inline int strcat_s( - char *strDestination, - size_t numberOfElements, - const char *strSource -) -{ - if (!strDestination) return EINVAL; - if (!strSource) {strDestination[0] = 0; return EINVAL;} - size_t l = strlen(strSource); - size_t m = strlen(strDestination); - if (numberOfElements < l + m + 1) {strDestination[0] = 0; return ERANGE;} - - memcpy(&strDestination[m], strSource, l + 1); - return 0; -} - -template -inline int strcat_s( - char (&strDestination)[size], - const char *strSource -) -{ - if (!strDestination) return EINVAL; - if (!strSource) {strDestination[0] = 0; return EINVAL;} - size_t l = strlen(strSource); - size_t m = strlen(strDestination); - if (size < l + m + 1) {strDestination[0] = 0; return ERANGE;} - - memcpy(&strDestination[m], strSource, l + 1); - return 0; -} - -inline int strncpy_s( - char *strDest, - size_t numberOfElements, - const char *strSource, - size_t count -) -{ - if (count > numberOfElements) - return strcpy_s(strDest, numberOfElements, strSource); - else - return strcpy_s(strDest, count + 1, strSource); -} - - -template -inline int sprintf_s( - char (&buffer)[size], - const char *format, - ... -) -{ - va_list va; - va_start(va, format); - vsnprintf(buffer, size, format, va); - va_end(va); -} - -template -inline int swprintf_s( - wchar_t (&buffer)[size], - const wchar_t *format, - ... -) -{ - va_list va; - va_start(va, format); - vsnwprintf(buffer, size, format, va); - va_end(va); -} - -#define vsprintf_s vsnprintf diff --git a/plugins/Dbx_tree/sigslot.h b/plugins/Dbx_tree/sigslot.h deleted file mode 100644 index 1e67a152bf..0000000000 --- a/plugins/Dbx_tree/sigslot.h +++ /dev/null @@ -1,2639 +0,0 @@ -// sigslot.h: Signal/Slot classes -// -// Written by Sarah Thompson (sarah@telergy.com) 2002. -// -// License: Public domain. You are free to use this code however you like, with the proviso that -// the author takes on no responsibility or liability for any use. -// -// QUICK DOCUMENTATION -// -// (see also the full documentation at http://sigslot.sourceforge.net/) -// -// #define switches -// SIGSLOT_PURE_ISO - Define this to force ISO C++ compliance. This also disables -// all of the thread safety support on platforms where it is -// available. -// -// SIGSLOT_USE_POSIX_THREADS - Force use of Posix threads when using a C++ compiler other than -// gcc on a platform that supports Posix threads. (When using gcc, -// this is the default - use SIGSLOT_PURE_ISO to disable this if -// necessary) -// -// SIGSLOT_DEFAULT_MT_POLICY - Where thread support is enabled, this defaults to multi_threaded_global. -// Otherwise, the default is single_threaded. #define this yourself to -// override the default. In pure ISO mode, anything other than -// single_threaded will cause a compiler error. -// -// PLATFORM NOTES -// -// Win32 - On Win32, the WIN32 symbol must be #defined. Most mainstream -// compilers do this by default, but you may need to define it -// yourself if your build environment is less standard. This causes -// the Win32 thread support to be compiled in and used automatically. -// -// Unix/Linux/BSD, etc. - If you're using gcc, it is assumed that you have Posix threads -// available, so they are used automatically. You can override this -// (as under Windows) with the SIGSLOT_PURE_ISO switch. If you're using -// something other than gcc but still want to use Posix threads, you -// need to #define SIGSLOT_USE_POSIX_THREADS. -// -// ISO C++ - If none of the supported platforms are detected, or if -// SIGSLOT_PURE_ISO is defined, all multithreading support is turned off, -// along with any code that might cause a pure ISO C++ environment to -// complain. Before you ask, gcc -ansi -pedantic won't compile this -// library, but gcc -ansi is fine. Pedantic mode seems to throw a lot of -// errors that aren't really there. If you feel like investigating this, -// please contact the author. -// -// -// THREADING MODES -// -// single_threaded - Your program is assumed to be single threaded from the point of view -// of signal/slot usage (i.e. all objects using signals and slots are -// created and destroyed from a single thread). Behaviour if objects are -// destroyed concurrently is undefined (i.e. you'll get the occasional -// segmentation fault/memory exception). -// -// multi_threaded_global - Your program is assumed to be multi threaded. Objects using signals and -// slots can be safely created and destroyed from any thread, even when -// connections exist. In multi_threaded_global mode, this is achieved by a -// single global mutex (actually a critical section on Windows because they -// are faster). This option uses less OS resources, but results in more -// opportunities for contention, possibly resulting in more context switches -// than are strictly necessary. -// -// multi_threaded_local - Behaviour in this mode is essentially the same as multi_threaded_global, -// except that each signal, and each object that inherits has_slots, all -// have their own mutex/critical section. In practice, this means that -// mutex collisions (and hence context switches) only happen if they are -// absolutely essential. However, on some platforms, creating a lot of -// mutexes can slow down the whole OS, so use this option with care. -// -// USING THE LIBRARY -// -// See the full documentation at http://sigslot.sourceforge.net/ -// -// - -#ifndef SIGSLOT_H__ -#define SIGSLOT_H__ - -#include -#include - -#if defined(SIGSLOT_PURE_ISO) || (!defined(WIN32) && !defined(__GNUG__) && !defined(SIGSLOT_USE_POSIX_THREADS)) -# define _SIGSLOT_SINGLE_THREADED -#elif defined(WIN32) -# define _SIGSLOT_HAS_WIN32_THREADS -# include -#elif defined(__GNUG__) || defined(SIGSLOT_USE_POSIX_THREADS) -# define _SIGSLOT_HAS_POSIX_THREADS -# include -#else -# define _SIGSLOT_SINGLE_THREADED -#endif - -#define SIGSLOT_DEFAULT_MT_POLICY multi_threaded_global - -#ifndef SIGSLOT_DEFAULT_MT_POLICY -# ifdef _SIGSLOT_SINGLE_THREADED -# define SIGSLOT_DEFAULT_MT_POLICY single_threaded -# else -# define SIGSLOT_DEFAULT_MT_POLICY multi_threaded_local -# endif -#endif - - -namespace sigslot { - - class single_threaded - { - public: - single_threaded() - { - ; - } - - ~single_threaded() - { - ; - } - - void lock() - { - ; - } - - void unlock() - { - ; - } - }; - -#ifdef _SIGSLOT_HAS_WIN32_THREADS - // The multi threading policies only get compiled in if they are enabled. - class multi_threaded_global - { - public: - multi_threaded_global() - { - static bool isinitialised = false; - - if (!isinitialised) - { - InitializeCriticalSection(get_critsec()); - isinitialised = true; - } - } - - multi_threaded_global(const multi_threaded_global&) - { - ; - } - - ~multi_threaded_global() - { - ; - } - - void lock() - { - EnterCriticalSection(get_critsec()); - } - - void unlock() - { - LeaveCriticalSection(get_critsec()); - } - - private: - CRITICAL_SECTION* get_critsec() - { - static CRITICAL_SECTION g_critsec; - return &g_critsec; - } - }; - - class multi_threaded_local - { - public: - multi_threaded_local() - { - InitializeCriticalSection(&m_critsec); - } - - multi_threaded_local(const multi_threaded_local&) - { - InitializeCriticalSection(&m_critsec); - } - - ~multi_threaded_local() - { - DeleteCriticalSection(&m_critsec); - } - - void lock() - { - EnterCriticalSection(&m_critsec); - } - - void unlock() - { - LeaveCriticalSection(&m_critsec); - } - - private: - CRITICAL_SECTION m_critsec; - }; -#endif // _SIGSLOT_HAS_WIN32_THREADS - -#ifdef _SIGSLOT_HAS_POSIX_THREADS - // The multi threading policies only get compiled in if they are enabled. - class multi_threaded_global - { - public: - multi_threaded_global() - { - pthread_mutex_init(get_mutex(), NULL); - } - - multi_threaded_global(const multi_threaded_global&) - { - ; - } - - ~multi_threaded_global() - { - ; - } - - void lock() - { - pthread_mutex_lock(get_mutex()); - } - - void unlock() - { - pthread_mutex_unlock(get_mutex()); - } - - private: - pthread_mutex_t* get_mutex() - { - static pthread_mutex_t g_mutex; - return &g_mutex; - } - }; - - class multi_threaded_local - { - public: - multi_threaded_local() - { - pthread_mutex_init(&m_mutex, NULL); - } - - multi_threaded_local(const multi_threaded_local&) - { - pthread_mutex_init(&m_mutex, NULL); - } - - ~multi_threaded_local() - { - pthread_mutex_destroy(&m_mutex); - } - - void lock() - { - pthread_mutex_lock(&m_mutex); - } - - void unlock() - { - pthread_mutex_unlock(&m_mutex); - } - - private: - pthread_mutex_t m_mutex; - }; -#endif // _SIGSLOT_HAS_POSIX_THREADS - - template - class lock_block - { - public: - mt_policy *m_mutex; - - lock_block(mt_policy *mtx) - : m_mutex(mtx) - { - m_mutex->lock(); - } - - ~lock_block() - { - m_mutex->unlock(); - } - }; - - template - class has_slots; - - template - class _connection_base0 - { - public: - virtual ~_connection_base0() { ; } - virtual has_slots* getdest() const = 0; - virtual void emit() = 0; - virtual _connection_base0* clone() = 0; - virtual _connection_base0* duplicate(has_slots* pnewdest) = 0; - }; - - template - class _connection_base1 - { - public: - virtual ~_connection_base1() { ; } - virtual has_slots* getdest() const = 0; - virtual void emit(arg1_type) = 0; - virtual _connection_base1* clone() = 0; - virtual _connection_base1* duplicate(has_slots* pnewdest) = 0; - }; - - template - class _connection_base2 - { - public: - virtual ~_connection_base2() { ; } - virtual has_slots* getdest() const = 0; - virtual void emit(arg1_type, arg2_type) = 0; - virtual _connection_base2* clone() = 0; - virtual _connection_base2* duplicate(has_slots* pnewdest) = 0; - }; - - template - class _connection_base3 - { - public: - virtual ~_connection_base3() { ; } - virtual has_slots* getdest() const = 0; - virtual void emit(arg1_type, arg2_type, arg3_type) = 0; - virtual _connection_base3* clone() = 0; - virtual _connection_base3* duplicate(has_slots* pnewdest) = 0; - }; - - template - class _connection_base4 - { - public: - virtual ~_connection_base4() { ; } - virtual has_slots* getdest() const = 0; - virtual void emit(arg1_type, arg2_type, arg3_type, arg4_type) = 0; - virtual _connection_base4* clone() = 0; - virtual _connection_base4* duplicate(has_slots* pnewdest) = 0; - }; - - template - class _connection_base5 - { - public: - virtual ~_connection_base5() { ; } - virtual has_slots* getdest() const = 0; - virtual void emit(arg1_type, arg2_type, arg3_type, arg4_type, - arg5_type) = 0; - virtual _connection_base5* clone() = 0; - virtual _connection_base5* duplicate(has_slots* pnewdest) = 0; - }; - - template - class _connection_base6 - { - public: - virtual ~_connection_base6() { ; } - virtual has_slots* getdest() const = 0; - virtual void emit(arg1_type, arg2_type, arg3_type, arg4_type, arg5_type, - arg6_type) = 0; - virtual _connection_base6* clone() = 0; - virtual _connection_base6* duplicate(has_slots* pnewdest) = 0; - }; - - template - class _connection_base7 - { - public: - virtual ~_connection_base7() { ; } - virtual has_slots* getdest() const = 0; - virtual void emit(arg1_type, arg2_type, arg3_type, arg4_type, arg5_type, - arg6_type, arg7_type) = 0; - virtual _connection_base7* clone() = 0; - virtual _connection_base7* duplicate(has_slots* pnewdest) = 0; - }; - - template - class _connection_base8 - { - public: - virtual ~_connection_base8() { ; } - virtual has_slots* getdest() const = 0; - virtual void emit(arg1_type, arg2_type, arg3_type, arg4_type, arg5_type, - arg6_type, arg7_type, arg8_type) = 0; - virtual _connection_base8* clone() = 0; - virtual _connection_base8* duplicate(has_slots* pnewdest) = 0; - }; - - template - class _signal_base : public mt_policy - { - public: - virtual void slot_disconnect(has_slots* pslot) = 0; - virtual void slot_duplicate(const has_slots* poldslot, has_slots* pnewslot) = 0; - }; - - template - class has_slots : public mt_policy - { - private: - typedef typename std::set<_signal_base *> sender_set; - typedef typename sender_set::const_iterator const_iterator; - - public: - has_slots() - { - ; - } - - has_slots(const has_slots& hs) - : mt_policy(hs) - { - lock_block lock(this); - const_iterator it = hs.m_senders.begin(); - const_iterator itEnd = hs.m_senders.end(); - - while(it != itEnd) - { - (*it)->slot_duplicate(&hs, this); - m_senders.insert(*it); - ++it; - } - } - - void signal_connect(_signal_base* sender) - { - lock_block lock(this); - m_senders.insert(sender); - } - - void signal_disconnect(_signal_base* sender) - { - lock_block lock(this); - m_senders.erase(sender); - } - - virtual ~has_slots() - { - disconnect_all(); - } - - void disconnect_all() - { - lock_block lock(this); - const_iterator it = m_senders.begin(); - const_iterator itEnd = m_senders.end(); - - while(it != itEnd) - { - (*it)->slot_disconnect(this); - ++it; - } - - m_senders.erase(m_senders.begin(), m_senders.end()); - } - - private: - sender_set m_senders; - }; - - template - class _signal_base0 : public _signal_base - { - public: - typedef typename std::list<_connection_base0 *> connections_list; - typedef typename connections_list::const_iterator const_iterator; - typedef typename connections_list::iterator iterator; - - _signal_base0() - { - ; - } - - _signal_base0(const _signal_base0& s) - : _signal_base(s) - { - lock_block lock(this); - const_iterator it = s.m_connected_slots.begin(); - const_iterator itEnd = s.m_connected_slots.end(); - - while(it != itEnd) - { - (*it)->getdest()->signal_connect(this); - m_connected_slots.push_back((*it)->clone()); - - ++it; - } - } - - ~_signal_base0() - { - disconnect_all(); - } - - void disconnect_all() - { - lock_block lock(this); - const_iterator it = m_connected_slots.begin(); - const_iterator itEnd = m_connected_slots.end(); - - while(it != itEnd) - { - (*it)->getdest()->signal_disconnect(this); - delete *it; - - ++it; - } - - m_connected_slots.erase(m_connected_slots.begin(), m_connected_slots.end()); - } - - void disconnect(has_slots* pclass) - { - lock_block lock(this); - iterator it = m_connected_slots.begin(); - iterator itEnd = m_connected_slots.end(); - - while(it != itEnd) - { - if ((*it)->getdest() == pclass) - { - delete *it; - m_connected_slots.erase(it); - pclass->signal_disconnect(this); - return; - } - - ++it; - } - } - - void slot_disconnect(has_slots* pslot) - { - lock_block lock(this); - iterator it = m_connected_slots.begin(); - iterator itEnd = m_connected_slots.end(); - - while(it != itEnd) - { - iterator itNext = it; - ++itNext; - - if ((*it)->getdest() == pslot) - { - delete *it; - m_connected_slots.erase(it); - // delete *it; - } - - it = itNext; - } - } - - void slot_duplicate(const has_slots* oldtarget, has_slots* newtarget) - { - lock_block lock(this); - iterator it = m_connected_slots.begin(); - iterator itEnd = m_connected_slots.end(); - - while(it != itEnd) - { - if ((*it)->getdest() == oldtarget) - { - m_connected_slots.push_back((*it)->duplicate(newtarget)); - } - - ++it; - } - } - - protected: - connections_list m_connected_slots; - }; - - template - class _signal_base1 : public _signal_base - { - public: - typedef typename std::list<_connection_base1 *> connections_list; - typedef typename connections_list::const_iterator const_iterator; - typedef typename connections_list::iterator iterator; - - _signal_base1() - { - ; - } - - _signal_base1(const _signal_base1& s) - : _signal_base(s) - { - lock_block lock(this); - const_iterator it = s.m_connected_slots.begin(); - const_iterator itEnd = s.m_connected_slots.end(); - - while(it != itEnd) - { - (*it)->getdest()->signal_connect(this); - m_connected_slots.push_back((*it)->clone()); - - ++it; - } - } - - void slot_duplicate(const has_slots* oldtarget, has_slots* newtarget) - { - lock_block lock(this); - iterator it = m_connected_slots.begin(); - iterator itEnd = m_connected_slots.end(); - - while(it != itEnd) - { - if ((*it)->getdest() == oldtarget) - { - m_connected_slots.push_back((*it)->duplicate(newtarget)); - } - - ++it; - } - } - - ~_signal_base1() - { - disconnect_all(); - } - - void disconnect_all() - { - lock_block lock(this); - const_iterator it = m_connected_slots.begin(); - const_iterator itEnd = m_connected_slots.end(); - - while(it != itEnd) - { - (*it)->getdest()->signal_disconnect(this); - delete *it; - - ++it; - } - - m_connected_slots.erase(m_connected_slots.begin(), m_connected_slots.end()); - } - - void disconnect(has_slots* pclass) - { - lock_block lock(this); - iterator it = m_connected_slots.begin(); - iterator itEnd = m_connected_slots.end(); - - while(it != itEnd) - { - if ((*it)->getdest() == pclass) - { - delete *it; - m_connected_slots.erase(it); - pclass->signal_disconnect(this); - return; - } - - ++it; - } - } - - void slot_disconnect(has_slots* pslot) - { - lock_block lock(this); - iterator it = m_connected_slots.begin(); - iterator itEnd = m_connected_slots.end(); - - while(it != itEnd) - { - iterator itNext = it; - ++itNext; - - if ((*it)->getdest() == pslot) - { - delete *it; - m_connected_slots.erase(it); - // delete *it; - } - - it = itNext; - } - } - - - protected: - connections_list m_connected_slots; - }; - - template - class _signal_base2 : public _signal_base - { - public: - typedef typename std::list<_connection_base2 *> - connections_list; - typedef typename connections_list::const_iterator const_iterator; - typedef typename connections_list::iterator iterator; - - _signal_base2() - { - ; - } - - _signal_base2(const _signal_base2& s) - : _signal_base(s) - { - lock_block lock(this); - const_iterator it = s.m_connected_slots.begin(); - const_iterator itEnd = s.m_connected_slots.end(); - - while(it != itEnd) - { - (*it)->getdest()->signal_connect(this); - m_connected_slots.push_back((*it)->clone()); - - ++it; - } - } - - void slot_duplicate(const has_slots* oldtarget, has_slots* newtarget) - { - lock_block lock(this); - iterator it = m_connected_slots.begin(); - iterator itEnd = m_connected_slots.end(); - - while(it != itEnd) - { - if ((*it)->getdest() == oldtarget) - { - m_connected_slots.push_back((*it)->duplicate(newtarget)); - } - - ++it; - } - } - - ~_signal_base2() - { - disconnect_all(); - } - - void disconnect_all() - { - lock_block lock(this); - const_iterator it = m_connected_slots.begin(); - const_iterator itEnd = m_connected_slots.end(); - - while(it != itEnd) - { - (*it)->getdest()->signal_disconnect(this); - delete *it; - - ++it; - } - - m_connected_slots.erase(m_connected_slots.begin(), m_connected_slots.end()); - } - - void disconnect(has_slots* pclass) - { - lock_block lock(this); - iterator it = m_connected_slots.begin(); - iterator itEnd = m_connected_slots.end(); - - while(it != itEnd) - { - if ((*it)->getdest() == pclass) - { - delete *it; - m_connected_slots.erase(it); - pclass->signal_disconnect(this); - return; - } - - ++it; - } - } - - void slot_disconnect(has_slots* pslot) - { - lock_block lock(this); - iterator it = m_connected_slots.begin(); - iterator itEnd = m_connected_slots.end(); - - while(it != itEnd) - { - iterator itNext = it; - ++itNext; - - if ((*it)->getdest() == pslot) - { - delete *it; - m_connected_slots.erase(it); - // delete *it; - } - - it = itNext; - } - } - - protected: - connections_list m_connected_slots; - }; - - template - class _signal_base3 : public _signal_base - { - public: - typedef std::list<_connection_base3 *> - connections_list; - - typedef typename connections_list::const_iterator const_iterator; - typedef typename connections_list::iterator iterator; - _signal_base3() - { - ; - } - - _signal_base3(const _signal_base3& s) - : _signal_base(s) - { - lock_block lock(this); - const_iterator it = s.m_connected_slots.begin(); - const_iterator itEnd = s.m_connected_slots.end(); - - while(it != itEnd) - { - (*it)->getdest()->signal_connect(this); - m_connected_slots.push_back((*it)->clone()); - - ++it; - } - } - - void slot_duplicate(const has_slots* oldtarget, has_slots* newtarget) - { - lock_block lock(this); - iterator it = m_connected_slots.begin(); - iterator itEnd = m_connected_slots.end(); - - while(it != itEnd) - { - if ((*it)->getdest() == oldtarget) - { - m_connected_slots.push_back((*it)->duplicate(newtarget)); - } - - ++it; - } - } - - ~_signal_base3() - { - disconnect_all(); - } - - void disconnect_all() - { - lock_block lock(this); - const_iterator it = m_connected_slots.begin(); - const_iterator itEnd = m_connected_slots.end(); - - while(it != itEnd) - { - (*it)->getdest()->signal_disconnect(this); - delete *it; - - ++it; - } - - m_connected_slots.erase(m_connected_slots.begin(), m_connected_slots.end()); - } - - void disconnect(has_slots* pclass) - { - lock_block lock(this); - iterator it = m_connected_slots.begin(); - iterator itEnd = m_connected_slots.end(); - - while(it != itEnd) - { - if ((*it)->getdest() == pclass) - { - delete *it; - m_connected_slots.erase(it); - pclass->signal_disconnect(this); - return; - } - - ++it; - } - } - - void slot_disconnect(has_slots* pslot) - { - lock_block lock(this); - iterator it = m_connected_slots.begin(); - iterator itEnd = m_connected_slots.end(); - - while(it != itEnd) - { - iterator itNext = it; - ++itNext; - - if ((*it)->getdest() == pslot) - { - delete *it; - m_connected_slots.erase(it); - // delete *it; - } - - it = itNext; - } - } - - protected: - connections_list m_connected_slots; - }; - - template - class _signal_base4 : public _signal_base - { - public: - typedef std::list<_connection_base4 *> connections_list; - typedef typename connections_list::const_iterator const_iterator; - typedef typename connections_list::iterator iterator; - - _signal_base4() - { - ; - } - - _signal_base4(const _signal_base4& s) - : _signal_base(s) - { - lock_block lock(this); - const_iterator it = s.m_connected_slots.begin(); - const_iterator itEnd = s.m_connected_slots.end(); - - while(it != itEnd) - { - (*it)->getdest()->signal_connect(this); - m_connected_slots.push_back((*it)->clone()); - - ++it; - } - } - - void slot_duplicate(const has_slots* oldtarget, has_slots* newtarget) - { - lock_block lock(this); - iterator it = m_connected_slots.begin(); - iterator itEnd = m_connected_slots.end(); - - while(it != itEnd) - { - if ((*it)->getdest() == oldtarget) - { - m_connected_slots.push_back((*it)->duplicate(newtarget)); - } - - ++it; - } - } - - ~_signal_base4() - { - disconnect_all(); - } - - void disconnect_all() - { - lock_block lock(this); - const_iterator it = m_connected_slots.begin(); - const_iterator itEnd = m_connected_slots.end(); - - while(it != itEnd) - { - (*it)->getdest()->signal_disconnect(this); - delete *it; - - ++it; - } - - m_connected_slots.erase(m_connected_slots.begin(), m_connected_slots.end()); - } - - void disconnect(has_slots* pclass) - { - lock_block lock(this); - iterator it = m_connected_slots.begin(); - iterator itEnd = m_connected_slots.end(); - - while(it != itEnd) - { - if ((*it)->getdest() == pclass) - { - delete *it; - this->m_connected_slots.erase(it); - pclass->signal_disconnect(this); - return; - } - - ++it; - } - } - - void slot_disconnect(has_slots* pslot) - { - lock_block lock(this); - iterator it = m_connected_slots.begin(); - iterator itEnd = m_connected_slots.end(); - - while(it != itEnd) - { - iterator itNext = it; - ++itNext; - - if ((*it)->getdest() == pslot) - { - delete *it; - m_connected_slots.erase(it); - // delete *it; - } - - it = itNext; - } - } - - protected: - connections_list m_connected_slots; - }; - - template - class _signal_base5 : public _signal_base - { - public: - typedef std::list<_connection_base5 *> connections_list; - typedef typename connections_list::const_iterator const_iterator; - typedef typename connections_list::iterator iterator; - - _signal_base5() - { - ; - } - - _signal_base5(const _signal_base5& s) - : _signal_base(s) - { - lock_block lock(this); - const_iterator it = s.m_connected_slots.begin(); - const_iterator itEnd = s.m_connected_slots.end(); - - while(it != itEnd) - { - (*it)->getdest()->signal_connect(this); - m_connected_slots.push_back((*it)->clone()); - - ++it; - } - } - - void slot_duplicate(const has_slots* oldtarget, has_slots* newtarget) - { - lock_block lock(this); - iterator it = m_connected_slots.begin(); - iterator itEnd = m_connected_slots.end(); - - while(it != itEnd) - { - if ((*it)->getdest() == oldtarget) - { - m_connected_slots.push_back((*it)->duplicate(newtarget)); - } - - ++it; - } - } - - ~_signal_base5() - { - disconnect_all(); - } - - void disconnect_all() - { - lock_block lock(this); - const_iterator it = m_connected_slots.begin(); - const_iterator itEnd = m_connected_slots.end(); - - while(it != itEnd) - { - (*it)->getdest()->signal_disconnect(this); - delete *it; - - ++it; - } - - m_connected_slots.erase(m_connected_slots.begin(), m_connected_slots.end()); - } - - void disconnect(has_slots* pclass) - { - lock_block lock(this); - iterator it = m_connected_slots.begin(); - iterator itEnd = m_connected_slots.end(); - - while(it != itEnd) - { - if ((*it)->getdest() == pclass) - { - delete *it; - m_connected_slots.erase(it); - pclass->signal_disconnect(this); - return; - } - - ++it; - } - } - - void slot_disconnect(has_slots* pslot) - { - lock_block lock(this); - iterator it = m_connected_slots.begin(); - iterator itEnd = m_connected_slots.end(); - - while(it != itEnd) - { - iterator itNext = it; - ++itNext; - - if ((*it)->getdest() == pslot) - { - delete *it; - m_connected_slots.erase(it); - // delete *it; - } - - it = itNext; - } - } - - protected: - connections_list m_connected_slots; - }; - - template - class _signal_base6 : public _signal_base - { - public: - typedef std::list<_connection_base6 *> connections_list; - typedef typename connections_list::const_iterator const_iterator; - typedef typename connections_list::iterator iterator; - - _signal_base6() - { - ; - } - - _signal_base6(const _signal_base6& s) - : _signal_base(s) - { - lock_block lock(this); - const_iterator it = s.m_connected_slots.begin(); - const_iterator itEnd = s.m_connected_slots.end(); - - while(it != itEnd) - { - (*it)->getdest()->signal_connect(this); - m_connected_slots.push_back((*it)->clone()); - - ++it; - } - } - - void slot_duplicate(const has_slots* oldtarget, has_slots* newtarget) - { - lock_block lock(this); - iterator it = m_connected_slots.begin(); - iterator itEnd = m_connected_slots.end(); - - while(it != itEnd) - { - if ((*it)->getdest() == oldtarget) - { - m_connected_slots.push_back((*it)->duplicate(newtarget)); - } - - ++it; - } - } - - ~_signal_base6() - { - disconnect_all(); - } - - void disconnect_all() - { - lock_block lock(this); - const_iterator it = m_connected_slots.begin(); - const_iterator itEnd = m_connected_slots.end(); - - while(it != itEnd) - { - (*it)->getdest()->signal_disconnect(this); - delete *it; - - ++it; - } - - m_connected_slots.erase(m_connected_slots.begin(), m_connected_slots.end()); - } - - void disconnect(has_slots* pclass) - { - lock_block lock(this); - iterator it = m_connected_slots.begin(); - iterator itEnd = m_connected_slots.end(); - - while(it != itEnd) - { - if ((*it)->getdest() == pclass) - { - delete *it; - m_connected_slots.erase(it); - pclass->signal_disconnect(this); - return; - } - - ++it; - } - } - - void slot_disconnect(has_slots* pslot) - { - lock_block lock(this); - iterator it = m_connected_slots.begin(); - iterator itEnd = m_connected_slots.end(); - - while(it != itEnd) - { - iterator itNext = it; - ++itNext; - - if ((*it)->getdest() == pslot) - { - delete *it; - m_connected_slots.erase(it); - // delete *it; - } - - it = itNext; - } - } - - protected: - connections_list m_connected_slots; - }; - - template - class _signal_base7 : public _signal_base - { - public: - typedef std::list<_connection_base7 *> connections_list; - typedef typename connections_list::const_iterator const_iterator; - typedef typename connections_list::iterator iterator; - - _signal_base7() - { - ; - } - - _signal_base7(const _signal_base7& s) - : _signal_base(s) - { - lock_block lock(this); - const_iterator it = s.m_connected_slots.begin(); - const_iterator itEnd = s.m_connected_slots.end(); - - while(it != itEnd) - { - (*it)->getdest()->signal_connect(this); - m_connected_slots.push_back((*it)->clone()); - - ++it; - } - } - - void slot_duplicate(const has_slots* oldtarget, has_slots* newtarget) - { - lock_block lock(this); - iterator it = m_connected_slots.begin(); - iterator itEnd = m_connected_slots.end(); - - while(it != itEnd) - { - if ((*it)->getdest() == oldtarget) - { - m_connected_slots.push_back((*it)->duplicate(newtarget)); - } - - ++it; - } - } - - ~_signal_base7() - { - disconnect_all(); - } - - void disconnect_all() - { - lock_block lock(this); - const_iterator it = m_connected_slots.begin(); - const_iterator itEnd = m_connected_slots.end(); - - while(it != itEnd) - { - (*it)->getdest()->signal_disconnect(this); - delete *it; - - ++it; - } - - m_connected_slots.erase(m_connected_slots.begin(), m_connected_slots.end()); - } - - void disconnect(has_slots* pclass) - { - lock_block lock(this); - iterator it = m_connected_slots.begin(); - iterator itEnd = m_connected_slots.end(); - - while(it != itEnd) - { - if ((*it)->getdest() == pclass) - { - delete *it; - m_connected_slots.erase(it); - pclass->signal_disconnect(this); - return; - } - - ++it; - } - } - - void slot_disconnect(has_slots* pslot) - { - lock_block lock(this); - iterator it = m_connected_slots.begin(); - iterator itEnd = m_connected_slots.end(); - - while(it != itEnd) - { - iterator itNext = it; - ++itNext; - - if ((*it)->getdest() == pslot) - { - delete *it; - m_connected_slots.erase(it); - // delete *it; - } - - it = itNext; - } - } - - protected: - connections_list m_connected_slots; - }; - - template - class _signal_base8 : public _signal_base - { - public: - typedef std::list<_connection_base8 *> - connections_list; - typedef typename connections_list::const_iterator const_iterator; - typedef typename connections_list::iterator iterator; - - _signal_base8() - { - ; - } - - _signal_base8(const _signal_base8& s) - : _signal_base(s) - { - lock_block lock(this); - const_iterator it = s.m_connected_slots.begin(); - const_iterator itEnd = s.m_connected_slots.end(); - - while(it != itEnd) - { - (*it)->getdest()->signal_connect(this); - m_connected_slots.push_back((*it)->clone()); - - ++it; - } - } - - void slot_duplicate(const has_slots* oldtarget, has_slots* newtarget) - { - lock_block lock(this); - iterator it = m_connected_slots.begin(); - iterator itEnd = m_connected_slots.end(); - - while(it != itEnd) - { - if ((*it)->getdest() == oldtarget) - { - m_connected_slots.push_back((*it)->duplicate(newtarget)); - } - - ++it; - } - } - - ~_signal_base8() - { - disconnect_all(); - } - - void disconnect_all() - { - lock_block lock(this); - const_iterator it = m_connected_slots.begin(); - const_iterator itEnd = m_connected_slots.end(); - - while(it != itEnd) - { - (*it)->getdest()->signal_disconnect(this); - delete *it; - - ++it; - } - - m_connected_slots.erase(m_connected_slots.begin(), m_connected_slots.end()); - } - - void disconnect(has_slots* pclass) - { - lock_block lock(this); - iterator it = m_connected_slots.begin(); - iterator itEnd = m_connected_slots.end(); - - while(it != itEnd) - { - if ((*it)->getdest() == pclass) - { - delete *it; - m_connected_slots.erase(it); - pclass->signal_disconnect(this); - return; - } - - ++it; - } - } - - void slot_disconnect(has_slots* pslot) - { - lock_block lock(this); - iterator it = m_connected_slots.begin(); - iterator itEnd = m_connected_slots.end(); - - while(it != itEnd) - { - iterator itNext = it; - ++itNext; - - if ((*it)->getdest() == pslot) - { - delete *it; - m_connected_slots.erase(it); - // delete *it; - } - - it = itNext; - } - } - - protected: - connections_list m_connected_slots; - }; - - - template - class _connection0 : public _connection_base0 - { - public: - _connection0() - { - this->pobject = NULL; - this->pmemfun = NULL; - } - - _connection0(dest_type* pobject, void (dest_type::*pmemfun)()) - { - m_pobject = pobject; - m_pmemfun = pmemfun; - } - - virtual ~_connection0() - { - ; - } - - virtual _connection_base0* clone() - { - return new _connection0(*this); - } - - virtual _connection_base0* duplicate(has_slots* pnewdest) - { - return new _connection0((dest_type *)pnewdest, m_pmemfun); - } - - virtual void emit() - { - (m_pobject->*m_pmemfun)(); - } - - virtual has_slots* getdest() const - { - return m_pobject; - } - - private: - dest_type* m_pobject; - void (dest_type::* m_pmemfun)(); - }; - - template - class _connection1 : public _connection_base1 - { - public: - _connection1() - { - this->pobject = NULL; - this->pmemfun = NULL; - } - - _connection1(dest_type* pobject, void (dest_type::*pmemfun)(arg1_type)) - { - m_pobject = pobject; - m_pmemfun = pmemfun; - } - - virtual ~_connection1() - { - ; - } - - virtual _connection_base1* clone() - { - return new _connection1(*this); - } - - virtual _connection_base1* duplicate(has_slots* pnewdest) - { - return new _connection1((dest_type *)pnewdest, m_pmemfun); - } - - virtual void emit(arg1_type a1) - { - (m_pobject->*m_pmemfun)(a1); - } - - virtual has_slots* getdest() const - { - return m_pobject; - } - - private: - dest_type* m_pobject; - void (dest_type::* m_pmemfun)(arg1_type); - }; - - template - class _connection2 : public _connection_base2 - { - public: - _connection2() - { - this->pobject = NULL; - this->pmemfun = NULL; - } - - _connection2(dest_type* pobject, void (dest_type::*pmemfun)(arg1_type, - arg2_type)) - { - m_pobject = pobject; - m_pmemfun = pmemfun; - } - - virtual ~_connection2() - { - ; - } - - - virtual _connection_base2* clone() - { - return new _connection2(*this); - } - - virtual _connection_base2* duplicate(has_slots* pnewdest) - { - return new _connection2((dest_type *)pnewdest, m_pmemfun); - } - - virtual void emit(arg1_type a1, arg2_type a2) - { - (m_pobject->*m_pmemfun)(a1, a2); - } - - virtual has_slots* getdest() const - { - return m_pobject; - } - - private: - dest_type* m_pobject; - void (dest_type::* m_pmemfun)(arg1_type, arg2_type); - }; - - template - class _connection3 : public _connection_base3 - { - public: - _connection3() - { - this->pobject = NULL; - this->pmemfun = NULL; - } - - _connection3(dest_type* pobject, void (dest_type::*pmemfun)(arg1_type, - arg2_type, arg3_type)) - { - m_pobject = pobject; - m_pmemfun = pmemfun; - } - - virtual ~_connection3() - { - ; - } - - - virtual _connection_base3* clone() - { - return new _connection3(*this); - } - - virtual _connection_base3* duplicate(has_slots* pnewdest) - { - return new _connection3((dest_type *)pnewdest, m_pmemfun); - } - - virtual void emit(arg1_type a1, arg2_type a2, arg3_type a3) - { - (m_pobject->*m_pmemfun)(a1, a2, a3); - } - - virtual has_slots* getdest() const - { - return m_pobject; - } - - private: - dest_type* m_pobject; - void (dest_type::* m_pmemfun)(arg1_type, arg2_type, arg3_type); - }; - - template - class _connection4 : public _connection_base4 - { - public: - _connection4() - { - this->pobject = NULL; - this->pmemfun = NULL; - } - - _connection4(dest_type* pobject, void (dest_type::*pmemfun)(arg1_type, - arg2_type, arg3_type, arg4_type)) - { - m_pobject = pobject; - m_pmemfun = pmemfun; - } - - virtual ~_connection4() - { - ; - } - - virtual _connection_base4* clone() - { - return new _connection4(*this); - } - - virtual _connection_base4* duplicate(has_slots* pnewdest) - { - return new _connection4((dest_type *)pnewdest, m_pmemfun); - } - - virtual void emit(arg1_type a1, arg2_type a2, arg3_type a3, - arg4_type a4) - { - (m_pobject->*m_pmemfun)(a1, a2, a3, a4); - } - - virtual has_slots* getdest() const - { - return m_pobject; - } - - private: - dest_type* m_pobject; - void (dest_type::* m_pmemfun)(arg1_type, arg2_type, arg3_type, - arg4_type); - }; - - template - class _connection5 : public _connection_base5 - { - public: - _connection5() - { - this->pobject = NULL; - this->pmemfun = NULL; - } - - _connection5(dest_type* pobject, void (dest_type::*pmemfun)(arg1_type, - arg2_type, arg3_type, arg4_type, arg5_type)) - { - m_pobject = pobject; - m_pmemfun = pmemfun; - } - - virtual ~_connection5() - { - ; - } - - virtual _connection_base5* clone() - { - return new _connection5(*this); - } - - virtual _connection_base5* duplicate(has_slots* pnewdest) - { - return new _connection5((dest_type *)pnewdest, m_pmemfun); - } - - virtual void emit(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4, - arg5_type a5) - { - (m_pobject->*m_pmemfun)(a1, a2, a3, a4, a5); - } - - virtual has_slots* getdest() const - { - return m_pobject; - } - - private: - dest_type* m_pobject; - void (dest_type::* m_pmemfun)(arg1_type, arg2_type, arg3_type, arg4_type, - arg5_type); - }; - - template - class _connection6 : public _connection_base6 - { - public: - _connection6() - { - this->pobject = NULL; - this->pmemfun = NULL; - } - - _connection6(dest_type* pobject, void (dest_type::*pmemfun)(arg1_type, - arg2_type, arg3_type, arg4_type, arg5_type, arg6_type)) - { - m_pobject = pobject; - m_pmemfun = pmemfun; - } - - virtual ~_connection6() - { - ; - } - - virtual _connection_base6* clone() - { - return new _connection6(*this); - } - - virtual _connection_base6* duplicate(has_slots* pnewdest) - { - return new _connection6((dest_type *)pnewdest, m_pmemfun); - } - - virtual void emit(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4, - arg5_type a5, arg6_type a6) - { - (m_pobject->*m_pmemfun)(a1, a2, a3, a4, a5, a6); - } - - virtual has_slots* getdest() const - { - return m_pobject; - } - - private: - dest_type* m_pobject; - void (dest_type::* m_pmemfun)(arg1_type, arg2_type, arg3_type, arg4_type, - arg5_type, arg6_type); - }; - - template - class _connection7 : public _connection_base7 - { - public: - _connection7() - { - this->pobject = NULL; - this->pmemfun = NULL; - } - - _connection7(dest_type* pobject, void (dest_type::*pmemfun)(arg1_type, - arg2_type, arg3_type, arg4_type, arg5_type, arg6_type, arg7_type)) - { - m_pobject = pobject; - m_pmemfun = pmemfun; - } - - virtual ~_connection7() - { - ; - } - - virtual _connection_base7* clone() - { - return new _connection7(*this); - } - - virtual _connection_base7* duplicate(has_slots* pnewdest) - { - return new _connection7((dest_type *)pnewdest, m_pmemfun); - } - - virtual void emit(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4, - arg5_type a5, arg6_type a6, arg7_type a7) - { - (m_pobject->*m_pmemfun)(a1, a2, a3, a4, a5, a6, a7); - } - - virtual has_slots* getdest() const - { - return m_pobject; - } - - private: - dest_type* m_pobject; - void (dest_type::* m_pmemfun)(arg1_type, arg2_type, arg3_type, arg4_type, - arg5_type, arg6_type, arg7_type); - }; - - template - class _connection8 : public _connection_base8 - { - public: - _connection8() - { - this->pobject = NULL; - this->pmemfun = NULL; - } - - _connection8(dest_type* pobject, void (dest_type::*pmemfun)(arg1_type, - arg2_type, arg3_type, arg4_type, arg5_type, arg6_type, - arg7_type, arg8_type)) - { - m_pobject = pobject; - m_pmemfun = pmemfun; - } - - virtual ~_connection8() - { - ; - } - - virtual _connection_base8* clone() - { - return new _connection8(*this); - } - - virtual _connection_base8* duplicate(has_slots* pnewdest) - { - return new _connection8((dest_type *)pnewdest, m_pmemfun); - } - - virtual void emit(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4, - arg5_type a5, arg6_type a6, arg7_type a7, arg8_type a8) - { - (m_pobject->*m_pmemfun)(a1, a2, a3, a4, a5, a6, a7, a8); - } - - virtual has_slots* getdest() const - { - return m_pobject; - } - - private: - dest_type* m_pobject; - void (dest_type::* m_pmemfun)(arg1_type, arg2_type, arg3_type, arg4_type, - arg5_type, arg6_type, arg7_type, arg8_type); - }; - - template - class signal0 : public _signal_base0 - { - public: - typedef typename _signal_base0::connections_list::const_iterator const_iterator; - signal0() - { - ; - } - - signal0(const signal0& s) - : _signal_base0(s) - { - ; - } - - virtual ~signal0() - { - ; - } - - template - void connect(desttype* pclass, void (desttype::*pmemfun)()) - { - lock_block lock(this); - _connection0* conn = - new _connection0(pclass, pmemfun); - this->m_connected_slots.push_back(conn); - pclass->signal_connect(this); - } - - void emit() - { - lock_block lock(this); - const_iterator itNext, it = this->m_connected_slots.begin(); - const_iterator itEnd = this->m_connected_slots.end(); - - while(it != itEnd) - { - itNext = it; - ++itNext; - - (*it)->emit(); - - it = itNext; - } - } - - void operator()() - { - lock_block lock(this); - const_iterator itNext, it = this->m_connected_slots.begin(); - const_iterator itEnd = this->m_connected_slots.end(); - - while(it != itEnd) - { - itNext = it; - ++itNext; - - (*it)->emit(); - - it = itNext; - } - } - }; - - template - class signal1 : public _signal_base1 - { - public: - typedef typename _signal_base1::connections_list::const_iterator const_iterator; - signal1() - { - ; - } - - signal1(const signal1& s) - : _signal_base1(s) - { - ; - } - - virtual ~signal1() - { - ; - } - - template - void connect(desttype* pclass, void (desttype::*pmemfun)(arg1_type)) - { - lock_block lock(this); - _connection1* conn = - new _connection1(pclass, pmemfun); - this->m_connected_slots.push_back(conn); - pclass->signal_connect(this); - } - - void emit(arg1_type a1) - { - lock_block lock(this); - const_iterator itNext, it = this->m_connected_slots.begin(); - const_iterator itEnd = this->m_connected_slots.end(); - - while(it != itEnd) - { - itNext = it; - ++itNext; - - (*it)->emit(a1); - - it = itNext; - } - } - - void operator()(arg1_type a1) - { - lock_block lock(this); - const_iterator itNext, it = this->m_connected_slots.begin(); - const_iterator itEnd = this->m_connected_slots.end(); - - while(it != itEnd) - { - itNext = it; - ++itNext; - - (*it)->emit(a1); - - it = itNext; - } - } - }; - - template - class signal2 : public _signal_base2 - { - public: - typedef typename _signal_base2::connections_list::const_iterator const_iterator; - signal2() - { - ; - } - - signal2(const signal2& s) - : _signal_base2(s) - { - ; - } - - virtual ~signal2() - { - ; - } - - template - void connect(desttype* pclass, void (desttype::*pmemfun)(arg1_type, - arg2_type)) - { - lock_block lock(this); - _connection2* conn = new - _connection2(pclass, pmemfun); - this->m_connected_slots.push_back(conn); - pclass->signal_connect(this); - } - - void emit(arg1_type a1, arg2_type a2) - { - lock_block lock(this); - const_iterator itNext, it = this->m_connected_slots.begin(); - const_iterator itEnd = this->m_connected_slots.end(); - - while(it != itEnd) - { - itNext = it; - ++itNext; - - (*it)->emit(a1, a2); - - it = itNext; - } - } - - void operator()(arg1_type a1, arg2_type a2) - { - lock_block lock(this); - const_iterator itNext, it = this->m_connected_slots.begin(); - const_iterator itEnd = this->m_connected_slots.end(); - - while(it != itEnd) - { - itNext = it; - ++itNext; - - (*it)->emit(a1, a2); - - it = itNext; - } - } - }; - - template - class signal3 : public _signal_base3 - { - public: - typedef typename _signal_base3::connections_list::const_iterator const_iterator; - signal3() - { - ; - } - - signal3(const signal3& s) - : _signal_base3(s) - { - ; - } - - virtual ~signal3() - { - ; - } - - template - void connect(desttype* pclass, void (desttype::*pmemfun)(arg1_type, - arg2_type, arg3_type)) - { - lock_block lock(this); - _connection3* conn = - new _connection3(pclass, - pmemfun); - this->m_connected_slots.push_back(conn); - pclass->signal_connect(this); - } - - void emit(arg1_type a1, arg2_type a2, arg3_type a3) - { - lock_block lock(this); - const_iterator itNext, it = this->m_connected_slots.begin(); - const_iterator itEnd = this->m_connected_slots.end(); - - while(it != itEnd) - { - itNext = it; - ++itNext; - - (*it)->emit(a1, a2, a3); - - it = itNext; - } - } - - void operator()(arg1_type a1, arg2_type a2, arg3_type a3) - { - lock_block lock(this); - const_iterator itNext, it = this->m_connected_slots.begin(); - const_iterator itEnd = this->m_connected_slots.end(); - - while(it != itEnd) - { - itNext = it; - ++itNext; - - (*it)->emit(a1, a2, a3); - - it = itNext; - } - } - }; - - template - class signal4 : public _signal_base4 - { - public: - typedef typename _signal_base4::connections_list::const_iterator const_iterator; - signal4() - { - ; - } - - signal4(const signal4& s) - : _signal_base4(s) - { - ; - } - - virtual ~signal4() - { - ; - } - - template - void connect(desttype* pclass, void (desttype::*pmemfun)(arg1_type, - arg2_type, arg3_type, arg4_type)) - { - lock_block lock(this); - _connection4* - conn = new _connection4(pclass, pmemfun); - this->m_connected_slots.push_back(conn); - pclass->signal_connect(this); - } - - void emit(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4) - { - lock_block lock(this); - const_iterator itNext, it = this->m_connected_slots.begin(); - const_iterator itEnd = this->m_connected_slots.end(); - - while(it != itEnd) - { - itNext = it; - ++itNext; - - (*it)->emit(a1, a2, a3, a4); - - it = itNext; - } - } - - void operator()(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4) - { - lock_block lock(this); - const_iterator itNext, it = this->m_connected_slots.begin(); - const_iterator itEnd = this->m_connected_slots.end(); - - while(it != itEnd) - { - itNext = it; - ++itNext; - - (*it)->emit(a1, a2, a3, a4); - - it = itNext; - } - } - }; - - template - class signal5 : public _signal_base5 - { - public: - typedef typename _signal_base5::connections_list::const_iterator const_iterator; - signal5() - { - ; - } - - signal5(const signal5& s) - : _signal_base5(s) - { - ; - } - - virtual ~signal5() - { - ; - } - - template - void connect(desttype* pclass, void (desttype::*pmemfun)(arg1_type, - arg2_type, arg3_type, arg4_type, arg5_type)) - { - lock_block lock(this); - _connection5* conn = new _connection5(pclass, pmemfun); - this->m_connected_slots.push_back(conn); - pclass->signal_connect(this); - } - - void emit(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4, - arg5_type a5) - { - lock_block lock(this); - const_iterator itNext, it = this->m_connected_slots.begin(); - const_iterator itEnd = this->m_connected_slots.end(); - - while(it != itEnd) - { - itNext = it; - ++itNext; - - (*it)->emit(a1, a2, a3, a4, a5); - - it = itNext; - } - } - - void operator()(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4, - arg5_type a5) - { - lock_block lock(this); - const_iterator itNext, it = this->m_connected_slots.begin(); - const_iterator itEnd = this->m_connected_slots.end(); - - while(it != itEnd) - { - itNext = it; - ++itNext; - - (*it)->emit(a1, a2, a3, a4, a5); - - it = itNext; - } - } - }; - - - template - class signal6 : public _signal_base6 - { - public: - typedef typename _signal_base6::connections_list::const_iterator const_iterator; - signal6() - { - ; - } - - signal6(const signal6& s) - : _signal_base6(s) - { - ; - } - - virtual ~signal6() - { - ; - } - - template - void connect(desttype* pclass, void (desttype::*pmemfun)(arg1_type, - arg2_type, arg3_type, arg4_type, arg5_type, arg6_type)) - { - lock_block lock(this); - _connection6* conn = - new _connection6(pclass, pmemfun); - this->m_connected_slots.push_back(conn); - pclass->signal_connect(this); - } - - void emit(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4, - arg5_type a5, arg6_type a6) - { - lock_block lock(this); - const_iterator itNext, it = this->m_connected_slots.begin(); - const_iterator itEnd = this->m_connected_slots.end(); - - while(it != itEnd) - { - itNext = it; - ++itNext; - - (*it)->emit(a1, a2, a3, a4, a5, a6); - - it = itNext; - } - } - - void operator()(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4, - arg5_type a5, arg6_type a6) - { - lock_block lock(this); - const_iterator itNext, it = this->m_connected_slots.begin(); - const_iterator itEnd = this->m_connected_slots.end(); - - while(it != itEnd) - { - itNext = it; - ++itNext; - - (*it)->emit(a1, a2, a3, a4, a5, a6); - - it = itNext; - } - } - }; - - template - class signal7 : public _signal_base7 - { - public: - typedef typename _signal_base7::connections_list::const_iterator const_iterator; - signal7() - { - ; - } - - signal7(const signal7& s) - : _signal_base7(s) - { - ; - } - - virtual ~signal7() - { - ; - } - - template - void connect(desttype* pclass, void (desttype::*pmemfun)(arg1_type, - arg2_type, arg3_type, arg4_type, arg5_type, arg6_type, - arg7_type)) - { - lock_block lock(this); - _connection7* conn = - new _connection7(pclass, pmemfun); - this->m_connected_slots.push_back(conn); - pclass->signal_connect(this); - } - - void emit(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4, - arg5_type a5, arg6_type a6, arg7_type a7) - { - lock_block lock(this); - const_iterator itNext, it = this->m_connected_slots.begin(); - const_iterator itEnd = this->m_connected_slots.end(); - - while(it != itEnd) - { - itNext = it; - ++itNext; - - (*it)->emit(a1, a2, a3, a4, a5, a6, a7); - - it = itNext; - } - } - - void operator()(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4, - arg5_type a5, arg6_type a6, arg7_type a7) - { - lock_block lock(this); - const_iterator itNext, it = this->m_connected_slots.begin(); - const_iterator itEnd = this->m_connected_slots.end(); - - while(it != itEnd) - { - itNext = it; - ++itNext; - - (*it)->emit(a1, a2, a3, a4, a5, a6, a7); - - it = itNext; - } - } - }; - - template - class signal8 : public _signal_base8 - { - public: - typedef typename _signal_base8::connections_list::const_iterator const_iterator; - signal8() - { - ; - } - - signal8(const signal8& s) - : _signal_base8(s) - { - ; - } - - virtual ~signal8() - { - ; - } - - template - void connect(desttype* pclass, void (desttype::*pmemfun)(arg1_type, - arg2_type, arg3_type, arg4_type, arg5_type, arg6_type, - arg7_type, arg8_type)) - { - lock_block lock(this); - _connection8* conn = - new _connection8(pclass, pmemfun); - this->m_connected_slots.push_back(conn); - pclass->signal_connect(this); - } - - void emit(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4, - arg5_type a5, arg6_type a6, arg7_type a7, arg8_type a8) - { - lock_block lock(this); - const_iterator itNext, it = this->m_connected_slots.begin(); - const_iterator itEnd = this->m_connected_slots.end(); - - while(it != itEnd) - { - itNext = it; - ++itNext; - - (*it)->emit(a1, a2, a3, a4, a5, a6, a7, a8); - - it = itNext; - } - } - - void operator()(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4, - arg5_type a5, arg6_type a6, arg7_type a7, arg8_type a8) - { - lock_block lock(this); - const_iterator itNext, it = this->m_connected_slots.begin(); - const_iterator itEnd = this->m_connected_slots.end(); - - while(it != itEnd) - { - itNext = it; - ++itNext; - - (*it)->emit(a1, a2, a3, a4, a5, a6, a7, a8); - - it = itNext; - } - } - }; - -} // namespace sigslot - -#endif // SIGSLOT_H__ - diff --git a/plugins/Dbx_tree/src/BTree.h b/plugins/Dbx_tree/src/BTree.h new file mode 100644 index 0000000000..20c2abfd71 --- /dev/null +++ b/plugins/Dbx_tree/src/BTree.h @@ -0,0 +1,1358 @@ +/* + +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. + +*/ + +#pragma once + +#include +#include "lockfree_hashmultimap.h" +#include "sigslot.h" +#ifdef _MSC_VER +#include "stdint.h" +#else +#include +#endif + +#include "Logger.h" + +#ifndef _MSC_VER +#ifdef offsetof +#undef offsetof +#endif +#define offsetof(TYPE, MEMBER) \ + ( (reinterpret_cast \ + (&reinterpret_cast \ + (static_cast (0)->MEMBER)))) +#endif + +template +class CBTree +{ +public: + typedef uint32_t TNodeRef; /// 32bit indices (not storing pointers) + typedef sigslot::signal2< void *, TNodeRef > TOnRootChanged; + + #pragma pack(push, 1) // push current alignment to stack, set alignment to 1 byte boundary + + typedef struct TNode { + uint16_t Info; /// Node information (IsLeaf and stored KeyCount) + uint16_t Signature; /// signature + TNodeRef Parent; /// Handle to the parent node + TKey Key[SizeParam * 2 - 1]; /// array with Keys + TNodeRef Child[SizeParam * 2]; /// array with child node handles + } TNode; + + #pragma pack(pop) + + class iterator + { + public: + iterator(); + iterator(CBTree* Tree, TNodeRef Node, uint16_t Index); + iterator(const iterator& Other); + ~iterator(); + + CBTree * Tree(); + + /** + \brief Keeps track of changes in the tree and refresh the iterator + **/ + void setManaged(); + bool wasDeleted(); + + operator bool() const; + bool operator !() const; + + const TKey & operator *(); + const TKey * operator->(); + + + bool operator == (iterator & Other); + bool operator < (iterator & Other); + bool operator > (iterator & Other); + + iterator& operator =(const iterator& Other); + + iterator& operator ++(); //pre ++i + iterator& operator --(); //pre --i + iterator operator ++(int); //post i++ + iterator operator --(int); //post i-- + + + protected: + friend class CBTree; + + TNodeRef m_Node; + uint16_t m_Index; + CBTree* m_Tree; + + bool m_Managed; + bool m_LoadedKey; + TKey m_ManagedKey; + bool m_ManagedDeleted; + + void Backup(); + void Dec(); + void Inc(); + void RemoveManaged(TNodeRef FromNode); + void InsertManaged(); + }; + + + CBTree(TNodeRef RootNode = 0); + virtual ~CBTree(); + + iterator Insert(const TKey & Key); + iterator Find(const TKey & Key); + iterator LowerBound(const TKey & Key); + iterator UpperBound(const TKey & Key); + bool Delete(const TKey & Key); + + typedef sigslot::signal3 TDeleteCallback; + void DeleteTree(TDeleteCallback * CallBack, uint32_t Param); + + TNodeRef getRoot(); + void setRoot(TNodeRef NewRoot); + + TOnRootChanged & sigRootChanged() {return m_sigRootChanged;}; + + +protected: + static const uint16_t cIsLeafMask = 0x8000; + static const uint16_t cKeyCountMask = 0x7FFF; + static const uint16_t cFullNode = SizeParam * 2 - 1; + static const uint16_t cEmptyNode = SizeParam - 1; + + typedef lockfree::hash_multimap TManagedMap; + + TNodeRef m_Root; + TOnRootChanged m_sigRootChanged; + TManagedMap m_ManagedIterators; + + bool m_DestroyTree; + + uint32_t m_AllocCount; + uint32_t m_Count; + uint32_t m_FreeIndex; + TNode * m_Alloc; + + virtual void PrepareInsertOperation(); + virtual TNode * CreateNewNode(TNodeRef & NodeRef); + virtual void DeleteNode(TNodeRef Node); + virtual TNode * Read(TNodeRef Node); + virtual void Write(TNodeRef Node); + + void DestroyTree(); + + +private: + friend class iterator; + + bool InNodeFind(const TNode * Node, const TKey & Key, uint16_t & GreaterEqual); + void SplitNode(TNodeRef Node, TNode * NodeData, TNodeRef & Left, TNodeRef & Right, TKey & UpKey, TNodeRef ParentNode, uint16_t ParentIndex); + TNodeRef MergeNodes(TNodeRef Left, TNode * LeftData, TNodeRef Right, TNode * RightData, const TKey & DownKey, TNodeRef ParentNode, uint16_t ParentIndex); + void KeyInsert(TNodeRef Node, TNode * NodeData, uint16_t Where); + void KeyDelete(TNodeRef Node, TNode * NodeData, uint16_t Where); + void KeyMove(TNodeRef Source, uint16_t SourceIndex, const TNode * SourceData, TNodeRef Dest, uint16_t DestIndex, TNode * DestData); +}; + + + + + + +template +CBTree::CBTree(TNodeRef RootNode = NULL) +: m_sigRootChanged(), + m_ManagedIterators() +{ + m_Root = RootNode; + m_DestroyTree = true; + + m_AllocCount = 0; + m_Count = 0; + m_FreeIndex = 0; + m_Alloc = NULL; +} + +template +CBTree::~CBTree() +{ + typename TManagedMap::iterator i = m_ManagedIterators.begin(); + while (i != m_ManagedIterators.end()) + { + i->second->m_Tree = NULL; + i++; + } + + if (m_DestroyTree) + DestroyTree(); +} + +template +inline bool CBTree::InNodeFind(const TNode * Node, const TKey & Key, uint16_t & GreaterEqual) +{ + uint16_t l = 0; + uint16_t r = (Node->Info & cKeyCountMask); + bool res = false; + GreaterEqual = 0; + while ((l < r) && !res) + { + GreaterEqual = (l + r) >> 1; + if (Node->Key[GreaterEqual] < Key) + { + GreaterEqual++; + l = GreaterEqual; + } else if (Node->Key[GreaterEqual] == Key) + { + //r = -1; + res = true; + } else { + r = GreaterEqual; + } + } + + return res; +} + + +template +inline void CBTree::SplitNode(TNodeRef Node, TNode * NodeData, TNodeRef & Left, TNodeRef & Right, TKey & UpKey, TNodeRef ParentNode, uint16_t ParentIndex) +{ + const uint16_t upindex = SizeParam - 1; + TNode *ldata, *rdata; + Left = Node; + ldata = NodeData; + rdata = CreateNewNode(Right); + + typename TManagedMap::iterator it = m_ManagedIterators.find(Node); + while ((it != m_ManagedIterators.end()) && (it->first == Node)) + { + if (it->second->m_Index == upindex) + { + it->second->m_Index = ParentIndex; + it->second->m_Node = ParentNode; + m_ManagedIterators.insert(std::make_pair(ParentNode, it->second)); + it = m_ManagedIterators.erase(it); + } else if (it->second->m_Index > upindex) + { + it->second->m_Index = it->second->m_Index - upindex - 1; + it->second->m_Node = Right; + m_ManagedIterators.insert(std::make_pair(Right, it->second)); + it = m_ManagedIterators.erase(it); + } else { + ++it; + } + } + + UpKey = NodeData->Key[upindex]; + + memcpy(&(rdata->Key[0]), &(NodeData->Key[upindex+1]), sizeof(TKey) * (cFullNode - upindex)); + if ((NodeData->Info & cIsLeafMask) == 0) + { + memcpy(&(rdata->Child[0]), &(NodeData->Child[upindex+1]), sizeof(TNodeRef) * (cFullNode - upindex + 1)); + + for (int i = 0; i <= upindex; i++) + { + TNode * tmp = Read(rdata->Child[i]); + tmp->Parent = Right; + Write(rdata->Child[i]); + } + } + + rdata->Info = (NodeData->Info & cIsLeafMask) | upindex; + NodeData->Info = rdata->Info; + rdata->Parent = NodeData->Parent; + + Write(Left); + Write(Right); +} + +template +inline typename CBTree::TNodeRef CBTree::MergeNodes(TNodeRef Left, TNode * LeftData, TNodeRef Right, TNode * RightData, const TKey & DownKey, TNodeRef ParentNode, uint16_t ParentIndex) +{ + uint16_t downindex = LeftData->Info & cKeyCountMask; + LeftData->Key[downindex] = DownKey; + + typename TManagedMap::iterator it = m_ManagedIterators.find(Right); + while ((it != m_ManagedIterators.end()) && (it->first == Right)) + { + it->second->m_Index = it->second->m_Index + downindex + 1; + it->second->m_Node = Left; + m_ManagedIterators.insert(std::make_pair(Left, it->second)); + it = m_ManagedIterators.erase(it); + } + + it = m_ManagedIterators.find(ParentNode); + while ((it != m_ManagedIterators.end()) && (it->first == ParentNode)) + { + if (it->second->m_Index == ParentIndex) + { + it->second->m_Index = downindex; + it->second->m_Node = Left; + m_ManagedIterators.insert(std::make_pair(Left, it->second)); + it = m_ManagedIterators.erase(it); + } else { + ++it; + } + } + + memcpy(&(LeftData->Key[downindex+1]), &(RightData->Key[0]), sizeof(TKey) * (RightData->Info & cKeyCountMask)); + if ((LeftData->Info & cIsLeafMask) == 0) + { + memcpy(&(LeftData->Child[downindex+1]), &(RightData->Child[0]), sizeof(TNodeRef) * ((RightData->Info & cKeyCountMask) + 1)); + + for (int i = 0; i <= (RightData->Info & cKeyCountMask); i++) + { + TNode * tmp = Read(RightData->Child[i]); + tmp->Parent = Left; + Write(RightData->Child[i]); + } + } + + LeftData->Info = ((LeftData->Info & cIsLeafMask) | (downindex + 1 + (RightData->Info & cKeyCountMask))); + + Write(Left); + DeleteNode(Right); + + return Left; +} + + +template +inline void CBTree::KeyInsert(TNodeRef Node, TNode * NodeData, uint16_t Where) +{ + memcpy(&(NodeData->Key[Where+1]), &(NodeData->Key[Where]), sizeof(TKey) * ((NodeData->Info & cKeyCountMask) - Where)); + + if ((NodeData->Info & cIsLeafMask) == 0) + memcpy(&(NodeData->Child[Where+1]), &(NodeData->Child[Where]), sizeof(TNodeRef) * ((NodeData->Info & cKeyCountMask) - Where + 1)); + + NodeData->Info++; + + typename TManagedMap::iterator it = m_ManagedIterators.find(Node); + while ((it != m_ManagedIterators.end()) && (it->first == Node)) + { + if (it->second->m_Index >= Where) + it->second->m_Index++; + + ++it; + } +} + +template +inline void CBTree::KeyDelete(TNodeRef Node, TNode * NodeData, uint16_t Where) +{ + NodeData->Info--; + + typename TManagedMap::iterator it = m_ManagedIterators.find(Node); + while ((it != m_ManagedIterators.end()) && (it->first == Node)) + { + if (it->second->m_Index == Where) + { + it->second->Backup(); + } else if (it->second->m_Index > Where) + { + it->second->m_Index--; + } + + ++it; + } + + memcpy(&(NodeData->Key[Where]), &(NodeData->Key[Where+1]), sizeof(TKey) * ((NodeData->Info & cKeyCountMask) - Where)); + + if ((NodeData->Info & cIsLeafMask) == 0) + memcpy(&(NodeData->Child[Where]), &(NodeData->Child[Where+1]), sizeof(TNodeRef) * ((NodeData->Info & cKeyCountMask) - Where + 1)); +} + + +template +inline void CBTree::KeyMove(TNodeRef Source, uint16_t SourceIndex, const TNode * SourceData, TNodeRef Dest, uint16_t DestIndex, TNode * DestData) +{ + DestData->Key[DestIndex] = SourceData->Key[SourceIndex]; + + typename TManagedMap::iterator it = m_ManagedIterators.find(Source); + while ((it != m_ManagedIterators.end()) && (it->first == Source)) + { + if (it->second->m_Index == SourceIndex) + { + it->second->m_Index = DestIndex; + it->second->m_Node = Dest; + m_ManagedIterators.insert(std::make_pair(Dest, it->second)); + it = m_ManagedIterators.erase(it); + } else { + ++it; + } + } +} + +template +typename CBTree::iterator +CBTree::Insert(const TKey & Key) +{ + TNode *node, *node2; + TNodeRef actnode; + TNodeRef nextnode; + bool exists; + uint16_t ge; + + PrepareInsertOperation(); + + if (!m_Root) + { + node = CreateNewNode(m_Root); + node->Info = cIsLeafMask; + Write(m_Root); + m_sigRootChanged.emit(this, m_Root); + } + + actnode = m_Root; + node = Read(actnode); + if ((node->Info & cKeyCountMask) == cFullNode) // root split + { + // be a little tricky and let the main code handle the actual splitting. + // just assign a new root with keycount to zero and one child = old root + // the InNode test will fail with GreaterEqual = 0 + node2 = CreateNewNode(nextnode); + node2->Info = 0; + node2->Child[0] = actnode; + Write(nextnode); + + node->Parent = nextnode; + Write(actnode); + + node = node2; + actnode = nextnode; + + m_Root = nextnode; + m_sigRootChanged.emit(this, m_Root); + } + + while (actnode) + { + exists = InNodeFind(node, Key, ge); + if (exists) // already exists + { + return iterator(this, actnode, ge); + } else { + if (node->Info & cIsLeafMask) // direct insert to leaf node + { + KeyInsert(actnode, node, ge); + + node->Key[ge] = Key; + + Write(actnode); + + return iterator(this, actnode, ge); + + } else { // middle node + nextnode = node->Child[ge]; + node2 = Read(nextnode); + + if ((node2->Info & cKeyCountMask) == cFullNode) // split the childnode + { + KeyInsert(actnode, node, ge); + SplitNode(nextnode, node2, node->Child[ge], node->Child[ge+1], node->Key[ge], actnode, ge); + + Write(actnode); + if (node->Key[ge] == Key) + { + return iterator(this, actnode, ge); + } else { + if (node->Key[ge] < Key) + { + nextnode = node->Child[ge+1]; + } else { + nextnode = node->Child[ge]; + } + } + + } + actnode = nextnode; + node = Read(actnode); + + } // if (node.Info & cIsLeafMask) + } // if (exists) + } // while (actnode) + + // something went wrong + return iterator(this, 0, 0xFFFF); +} + + +template +typename CBTree::iterator +CBTree::Find(const TKey & Key) +{ + TNode * node; + TNodeRef actnode = m_Root; + uint16_t ge; + + if (!m_Root) return iterator(this, 0, 0xFFFF); + + node = Read(actnode); + + while (actnode) + { + if (InNodeFind(node, Key, ge)) + { + return iterator(this, actnode, ge); + } + + if (!(node->Info & cIsLeafMask)) + { + actnode = node->Child[ge]; + node = Read(actnode); + } else { + actnode = 0; + } + } + + return iterator(this, 0, 0xFFFF); +} + +template +typename CBTree::iterator +CBTree::LowerBound(const TKey & Key) +{ + TNode * node; + TNodeRef actnode = m_Root; + uint16_t ge; + + if (!m_Root) return iterator(this, 0, 0xFFFF); + + node = Read(actnode); + + while (actnode) + { + if (InNodeFind(node, Key, ge)) + { + return iterator(this, actnode, ge); + } + + if (node->Info & cIsLeafMask) + { + if (ge >= (node->Info & cKeyCountMask)) + { + iterator i(this, actnode, ge - 1); + ++i; + return i; + } else { + return iterator(this, actnode, ge); + } + } else { + actnode = node->Child[ge]; + node = Read(actnode); + } + } + + return iterator(this, 0, 0xFFFF); +} + +template +typename CBTree::iterator +CBTree::UpperBound(const TKey & Key) +{ + TNode * node; + TNodeRef actnode = m_Root; + uint16_t ge; + if (!m_Root) return iterator(this, 0, 0xFFFF); + + node = Read(actnode); + + while (actnode) + { + if (InNodeFind(node, Key, ge)) + { + return iterator(this, actnode, ge); + } + + if (node->Info & cIsLeafMask) + { + if (ge == 0) + { + iterator i(this, actnode, 0); + --i; + return i; + } else { + return iterator(this, actnode, ge - 1); + } + } else { + actnode = node->Child[ge]; + node = Read(actnode); + } + } + + return iterator(this, 0, 0xFFFF); +} + +template +bool CBTree::Delete(const TKey& Key) +{ + if (!m_Root) return false; + + TNode *node, *node2, *lnode, *rnode; + + TNodeRef actnode = m_Root; + TNodeRef nextnode, l, r; + bool exists, skipread; + uint16_t ge; + + bool foundininnernode = false; + bool wantleftmost = false; + TNodeRef innernode = 0; + TNode * innernodedata = NULL; + uint16_t innerindex = 0xFFFF; + + node = Read(actnode); + + while (actnode) + { + skipread = false; + + if (foundininnernode) + { + exists = false; + if (wantleftmost) + ge = 0; + else + ge = node->Info & cKeyCountMask; + + } else { + exists = InNodeFind(node, Key, ge); + } + + if (exists) + { + if (node->Info & cIsLeafMask) // delete in leaf + { + KeyDelete(actnode, node, ge); + Write(actnode); + + return true; + + } else { // delete in inner node + l = node->Child[ge]; + r = node->Child[ge+1]; + lnode = Read(l); + rnode = Read(r); + + + if (((rnode->Info & cKeyCountMask) == cEmptyNode) && ((lnode->Info & cKeyCountMask) == cEmptyNode)) + { // merge childnodes and keep going + nextnode = MergeNodes(l, lnode, r, rnode, node->Key[ge], actnode, ge); + + KeyDelete(actnode, node, ge); + node->Child[ge] = nextnode; + + if ((actnode == m_Root) && ((node->Info & cKeyCountMask) == 0)) + { // root node is empty. delete it + DeleteNode(actnode); + m_Root = nextnode; + m_sigRootChanged.emit(this, m_Root); + } else { + Write(actnode); + } + + } else { // need a key-data-pair from a leaf to replace deleted pair -> save position + foundininnernode = true; + innernode = actnode; + innerindex = ge; + innernodedata = node; + + if ((lnode->Info & cKeyCountMask) == cEmptyNode) + { + wantleftmost = true; + nextnode = r; + } else { + wantleftmost = false; + nextnode = l; + } + } + } + + } else if (node->Info & cIsLeafMask) { // we are at the bottom. finish it + if (foundininnernode) + { + if (wantleftmost) + { + KeyMove(actnode, 0, node, innernode, innerindex, innernodedata); + Write(innernode); + + KeyDelete(actnode, node, 0); + Write(actnode); + + } else { + KeyMove(actnode, (node->Info & cKeyCountMask) - 1, node, innernode, innerindex, innernodedata); + Write(innernode); + + //KeyDelete(actnode, node, node.Info & cKeyCountMask); + node->Info--; + Write(actnode); + } + } + return foundininnernode; + + } else { // inner node. go on and check if moving or merging is neccessary + nextnode = node->Child[ge]; + node2 = Read(nextnode); + + if ((node2->Info & cKeyCountMask) == cEmptyNode) // move or merge + { + // set l and r for easier access + if (ge > 0) + { + l = node->Child[ge - 1]; + lnode = Read(l); + } else + l = 0; + + if (ge < (node->Info & cKeyCountMask)) + { + r = node->Child[ge + 1]; + rnode = Read(r); + } else + r = 0; + + if ((r != 0) && ((rnode->Info & cKeyCountMask) > cEmptyNode)) // move a Key-Data-pair from the right + { + // move key-data-pair down from current to the next node + KeyMove(actnode, ge, node, nextnode, node2->Info & cKeyCountMask, node2); + + // move the child from right to next node + node2->Child[(node2->Info & cKeyCountMask) + 1] = rnode->Child[0]; + + // move key-data-pair up from right to current node + KeyMove(r, 0, rnode, actnode, ge, node); + Write(actnode); + + // decrement right node key count and remove the first key-data-pair + KeyDelete(r, rnode, 0); + + // increment KeyCount of the next node + node2->Info++; + + if ((node2->Info & cIsLeafMask) == 0) // update the parent property of moved child + { + TNode * tmp = Read(node2->Child[node2->Info & cKeyCountMask]); + tmp->Parent = nextnode; + Write(node2->Child[node2->Info & cKeyCountMask]); + } + + + Write(r); + Write(nextnode); + node = node2; + skipread = true; + + } else if ((l != 0) && ((lnode->Info & cKeyCountMask) > cEmptyNode)) // move a Key-Data-pair from the left + { + // increment next node key count and make new first key-data-pair + KeyInsert(nextnode, node2, 0); + + // move key-data-pair down from current to the next node + KeyMove(actnode, ge - 1, node, nextnode, 0, node2); + + // move the child from left to next node + node2->Child[0] = lnode->Child[lnode->Info & cKeyCountMask]; + + // move key-data-pair up from left to current node + KeyMove(l, (lnode->Info & cKeyCountMask) - 1, lnode, actnode, ge - 1, node); + Write(actnode); + + // decrement left node key count + lnode->Info--; + Write(l); + + if ((node2->Info & cIsLeafMask) == 0) // update the parent property of moved child + { + TNode * tmp = Read(node2->Child[0]); + tmp->Parent = nextnode; + Write(node2->Child[0]); + } + + Write(nextnode); + node = node2; + skipread = true; + + } else { + if (l != 0) // merge with the left node + { + nextnode = MergeNodes(l, lnode, nextnode, node2, node->Key[ge - 1], actnode, ge - 1); + KeyDelete(actnode, node, ge - 1); + node->Child[ge - 1] = nextnode; + + } else { // merge with the right node + nextnode = MergeNodes(nextnode, node2, r, rnode, node->Key[ge], actnode, ge); + KeyDelete(actnode, node, ge); + node->Child[ge] = nextnode; + } + + if ((actnode == m_Root) && ((node->Info & cKeyCountMask) == 0)) + { + DeleteNode(actnode); + m_Root = nextnode; + m_sigRootChanged(this, nextnode); + } else { + Write(actnode); + } + } + } + } // if (exists) else if (node.Info & cIsLeafMask) + + actnode = nextnode; + if (!skipread) + node = Read(actnode); + + } // while(actnode) + + return false; +} + +template +typename CBTree::TNodeRef CBTree::getRoot() +{ + return m_Root; +} + +template +void CBTree::setRoot(TNodeRef NewRoot) +{ + m_Root = NewRoot; + return; +} + +template +void CBTree::PrepareInsertOperation() +{ + if (m_Count + 64 > m_AllocCount) + { + m_AllocCount += 64; + m_Alloc = (TNode *)realloc(m_Alloc, sizeof(TNode) * m_AllocCount); + + for (TNodeRef i = m_AllocCount - 64; i < m_AllocCount; ++i) + m_Alloc[i].Parent = i + 1; + + m_Alloc[m_AllocCount - 1].Parent = 0; + + if (m_FreeIndex) + { + TNodeRef i = m_FreeIndex; + while (m_Alloc[i].Parent) + i = m_Alloc[i].Parent; + + m_Alloc[i].Parent = m_AllocCount - 64; + + } else { + m_FreeIndex = m_AllocCount - 63; + } + + } +} + +template +typename CBTree::TNode * CBTree::CreateNewNode(TNodeRef & NodeRef) +{ + NodeRef = m_FreeIndex; + m_FreeIndex = m_Alloc[m_FreeIndex].Parent; + m_Count++; + memset(m_Alloc + NodeRef, 0, sizeof(TNode)); + return m_Alloc + NodeRef; +} + +template +void CBTree::DeleteNode(TNodeRef Node) +{ + CHECK((Node > 0) && (Node < m_AllocCount), logERROR, _T("Invalid Node")); + m_Alloc[Node].Parent = m_FreeIndex; + m_FreeIndex = Node; + m_Count--; +} + +template +typename CBTree::TNode * CBTree::Read(TNodeRef Node) +{ + CHECK((Node > 0) && (Node < m_AllocCount), logERROR, _T("Invalid Node")); + return m_Alloc + Node; +} + +template +void CBTree::Write(TNodeRef Node) +{ + return; +} + +template +void CBTree::DestroyTree() +{ + std::stack s; + TNodeRef node; + TNode* nodedata; + uint16_t i; + + if (m_Root) + s.push(m_Root); + while (!s.empty()) + { + node = s.top(); + nodedata = Read(node); + s.pop(); + + if ((nodedata->Info & cIsLeafMask) == 0) + { + for (i = 0; i <= (nodedata->Info & cKeyCountMask); i++) + s.push(nodedata->Child[i]); + } + + DeleteNode(node); + } + + if (m_Alloc) + free(m_Alloc); + m_Alloc = NULL; + m_AllocCount = 0; + m_Count = 0; + m_FreeIndex = 0; +} + + +template +void CBTree::DeleteTree(TDeleteCallback * CallBack, uint32_t Param) +{ + std::stack s; + TNodeRef actnode; + TNode * node; + uint16_t i; + + typename TManagedMap::iterator it = m_ManagedIterators.begin(); + while (it != m_ManagedIterators.end()) + { + it->second->m_Node = 0; + it->second->m_Index = 0xffff; + ++it; + } + + if (m_Root) + s.push(m_Root); + + m_Root = 0; + m_sigRootChanged.emit(this, m_Root); + + while (!s.empty()) + { + actnode = s.top(); + s.pop(); + + node = Read(actnode); + + if ((node->Info & cIsLeafMask) == 0) + { + for (i = 0; i <= (node->Info & cKeyCountMask); i++) + s.push(node->Child[i]); + + } + if (CallBack) + { + for (i = 0; i < (node->Info & cKeyCountMask); i++) + CallBack->emit(this, node->Key[i], Param); + } + + DeleteNode(actnode); + } +} + + + + + + + +template +CBTree::iterator::iterator() +{ + m_Tree = NULL; + m_Node = 0; + m_Index = 0xFFFF; + m_Managed = false; + m_ManagedDeleted = false; + m_LoadedKey = false; +} +template +CBTree::iterator::iterator(CBTree* Tree, TNodeRef Node, uint16_t Index) +{ + m_Tree = Tree; + m_Node = Node; + m_Index = Index; + m_Managed = false; + m_ManagedDeleted = false; + m_LoadedKey = false; +} +template +CBTree::iterator::iterator(const iterator& Other) +{ + m_Tree = Other.m_Tree; + m_Node = Other.m_Node; + m_Index = Other.m_Index; + m_ManagedDeleted = Other.m_ManagedDeleted; + m_Managed = Other.m_Managed; + m_LoadedKey = Other.m_LoadedKey; + m_ManagedKey = Other.m_ManagedKey; + + if (m_Managed) + InsertManaged(); +} + +template +CBTree::iterator::~iterator() +{ + RemoveManaged(m_Node); +} + + +template +void CBTree::iterator::setManaged() +{ + if (!m_Managed) + InsertManaged(); + + m_Managed = true; +} + +template +inline void CBTree::iterator::RemoveManaged(TNodeRef FromNode) +{ + if (m_Managed && m_Tree) + { + typename TManagedMap::iterator i = m_Tree->m_ManagedIterators.find(FromNode); + + while ((i != m_Tree->m_ManagedIterators.end()) && (i->second != this) && (i->first == FromNode)) + ++i; + + if ((i != m_Tree->m_ManagedIterators.end()) && (i->second == this)) + m_Tree->m_ManagedIterators.erase(i); + } +} +template +inline void CBTree::iterator::InsertManaged() +{ + if (m_Tree) + m_Tree->m_ManagedIterators.insert(std::make_pair(m_Node, this)); +} + +template +bool CBTree::iterator::wasDeleted() +{ + return m_ManagedDeleted; +} + +template +void CBTree::iterator::Backup() +{ + if ((!m_ManagedDeleted) && (*this)) + { + TNode * tmp; + if (!m_LoadedKey) + { + tmp = m_Tree->Read(m_Node); + m_ManagedKey = tmp->Key[m_Index]; + } + m_LoadedKey = true; + } + + m_ManagedDeleted = true; +} + +template +CBTree * CBTree::iterator::Tree() +{ + return m_Tree; +} + +template +const TKey& CBTree::iterator::operator *() +{ + if (!m_LoadedKey) + { + TNode * node; + node = m_Tree->Read(m_Node); + m_ManagedKey = node->Key[m_Index]; + m_LoadedKey = true; + } + return m_ManagedKey; +} + +template +const TKey* CBTree::iterator::operator ->() +{ + if (!m_LoadedKey) + { + TNode * node; + node = m_Tree->Read(m_Node); + m_ManagedKey = node->Key[m_Index]; + m_LoadedKey = true; + } + return &m_ManagedKey; +} + +template +inline CBTree::iterator::operator bool() const +{ + if (m_Tree && m_Node) + { + TNode * node; + node = m_Tree->Read(m_Node); + return (m_Index < (node->Info & cKeyCountMask)); + } else + return false; +} + +template +inline bool CBTree::iterator::operator !() const +{ + if (m_Tree && m_Node) + { + TNode * node; + node = m_Tree->Read(m_Node); + return (m_Index > (node->Info & cKeyCountMask)); + } else + return true; +} + +template +inline bool CBTree::iterator::operator ==(iterator & Other) +{ + //return (m_Tree == Other.m_Tree) && (m_Node == Other.m_Node) && (m_Index == Other.m_Index) && (!m_ManagedDeleted) && (!Other.m_ManagedDeleted); + return Key() == Other.Key(); +} + +template +inline bool CBTree::iterator::operator < (iterator & Other) +{ + return Key() < Other.Key(); +} +template +inline bool CBTree::iterator::operator > (iterator & Other) +{ + return Key() > Other.Key(); +} + + +template +typename CBTree::iterator& +CBTree::iterator::operator =(const iterator& Other) +{ + RemoveManaged(m_Node); + + m_Tree = Other.m_Tree; + m_Node = Other.m_Node; + m_Index = Other.m_Index; + m_ManagedDeleted = Other.m_ManagedDeleted; + m_Managed = Other.m_Managed; + m_LoadedKey = Other.m_LoadedKey; + m_ManagedKey = Other.m_ManagedKey; + + if (m_Managed) + InsertManaged(); + + return *this; +} + +template +typename CBTree::iterator& +CBTree::iterator::operator ++() //pre ++i +{ + TNodeRef oldnode = m_Node; + if (m_Managed && m_ManagedDeleted) + { + TKey oldkey = m_ManagedKey; + m_LoadedKey = false; + m_ManagedDeleted = false; + iterator other = m_Tree->LowerBound(m_ManagedKey); + m_Node = other.m_Node; + m_Index = other.m_Index; + while (((**this) == oldkey) && (*this)) + Inc(); + + } else + Inc(); + + if (m_Managed && (oldnode != m_Node)) + { + RemoveManaged(oldnode); + InsertManaged(); + } + return *this; +} + +template +typename CBTree::iterator& +CBTree::iterator::operator --() //pre --i +{ + TNodeRef oldnode = m_Node; + if (m_Managed && m_ManagedDeleted) + { + TKey oldkey = m_ManagedKey; + m_LoadedKey = false; + + m_ManagedDeleted = false; + iterator other = m_Tree->UpperBound(m_ManagedKey); + m_Node = other.m_Node; + m_Index = other.m_Index; + while (((**this) == oldkey) && (*this)) + Dec(); + } else + Dec(); + + if (m_Managed && (oldnode != m_Node)) + { + RemoveManaged(oldnode); + InsertManaged(); + } + return *this; +} + +template +typename CBTree::iterator +CBTree::iterator::operator ++(int) //post i++ +{ + iterator tmp(*this); + ++(*this); + return tmp; +} +template +typename CBTree::iterator +CBTree::iterator::operator --(int) //post i-- +{ + iterator tmp(*this); + --(*this); + return tmp; +} + +template +void CBTree::iterator::Inc() +{ + TNode * node; + TNodeRef nextnode; + node = m_Tree->Read(m_Node); + + m_LoadedKey = false; + + if ((node->Info & cIsLeafMask) && ((node->Info & cKeyCountMask) > m_Index + 1)) // leaf + { + m_Index++; + return; + } + + if ((node->Info & cIsLeafMask) == 0) // inner node. go down + { + m_Node = node->Child[m_Index + 1]; + node = m_Tree->Read(m_Node); + + m_Index = 0; + + while ((node->Info & cIsLeafMask) == 0) // go down to a leaf + { + m_Node = node->Child[0]; + node = m_Tree->Read(m_Node); + } + + return; + } + + while (m_Index >= (node->Info & cKeyCountMask) - 1) // go up + { + if (m_Node == m_Tree->m_Root) // the root is the top, we cannot go further + { + m_Index = 0xFFFF; + m_Node = 0; + return; + } + + nextnode = node->Parent; + node = m_Tree->Read(nextnode); + m_Index = 0; + + while ((m_Index <= (node->Info & cKeyCountMask)) && (node->Child[m_Index] != m_Node)) + m_Index++; + + m_Node = nextnode; + + if (m_Index < (node->Info & cKeyCountMask)) + return; + } + +} + +template +void CBTree::iterator::Dec() +{ + TNode * node; + TNodeRef nextnode; + node = m_Tree->Read(m_Node); + + m_LoadedKey = false; + + if ((node->Info & cIsLeafMask) && (m_Index > 0)) // leaf + { + m_Index--; + return; + } + + if ((node->Info & cIsLeafMask) == 0) // inner node. go down + { + m_Node = node->Child[m_Index]; + node = m_Tree->Read(m_Node); + m_Index = (node->Info & cKeyCountMask) - 1; + + while ((node->Info & cIsLeafMask) == 0) // go down to a leaf + { + m_Node = node->Child[node->Info & cKeyCountMask]; + node = m_Tree->Read(m_Node); + m_Index = (node->Info & cKeyCountMask) - 1; + } + + return; + } + + while (m_Index == 0) // go up + { + if (m_Node == m_Tree->m_Root) // the root is the top, we cannot go further + { + m_Index = 0xFFFF; + m_Node = 0; + return; + } + + nextnode = node->Parent; + node = m_Tree->Read(nextnode); + m_Index = 0; + + while ((m_Index <= (node->Info & cKeyCountMask)) && (node->Child[m_Index] != m_Node)) + m_Index++; + + m_Node = nextnode; + + if (m_Index > 0) + { + m_Index--; + return; + } + } +} diff --git a/plugins/Dbx_tree/src/BlockManager.cpp b/plugins/Dbx_tree/src/BlockManager.cpp new file mode 100644 index 0000000000..b52298602f --- /dev/null +++ b/plugins/Dbx_tree/src/BlockManager.cpp @@ -0,0 +1,965 @@ +/* + +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 "BlockManager.h" +#include "Logger.h" + +CBlockManager::CBlockManager( + CFileAccess & FileAccess, + CEncryptionManager & EncryptionManager + ) +: m_BlockSync(), + m_FileAccess(FileAccess), + m_EncryptionManager(EncryptionManager), + m_BlockTable(1024), + m_FreeBlocks() +{ + m_Optimize.Thread = NULL; + m_Optimize.Source = 0; + m_Optimize.Dest = 0; + + m_CacheInfo.Growth = 0; + m_CacheInfo.Size = 0; + m_CacheInfo.LastPurge = time(NULL); + + m_PendingHead = NULL; + m_PendingTail = NULL; + m_PendingLast = NULL; + m_LastFlush = time(NULL); + m_BytesPending = 20; + m_FirstFreeIndex = 0; + + m_SaveMode = true; + m_ReadOnly = m_FileAccess.ReadOnly(); + + memset(m_Cache, 0, sizeof(m_Cache)); +} + +CBlockManager::~CBlockManager() +{ + m_BlockSync.BeginWrite(); + if (m_Optimize.Thread) + { + m_Optimize.Thread->FreeOnTerminate(false); + m_Optimize.Thread->Terminate(); + + m_BlockSync.EndWrite(); + m_Optimize.Thread->WaitFor(); + + delete m_Optimize.Thread; + } else { + m_BlockSync.EndWrite(); + } + + _PendingFlush(true); + + for (uint32_t buddy = 0; buddy < cCacheBuddyCount; buddy++) + { + TCacheEntry * i = m_Cache[buddy]; + while (i) + { + free(i->Cache); + + TCacheEntry * tmp = i; + i = i->Next; + free(tmp); + } + } +} + +// Optimize File Size +void CBlockManager::ExecuteOptimize() +{ /* + TBlockHeadFree h = {0,0}; + uint8_t * buf = (uint8_t*)malloc(1 << 18); // 256kb + uint32_t bufuse = 0; + uint32_t bufsize = 1 << 18; + uint32_t lastflush = 0; + + { + int i = 0; + while (!m_Optimize.Thread->Terminated() && (i < 600)) + { + ++i; + Sleep(100); // wait for Miranda to start + } + } + + TransactionBeginWrite(); + + while (!m_Optimize.Thread->Terminated() && (m_Optimize.Source < m_FileAccess.Size()) && !m_ReadOnly) + { + m_FileAccess.Read(&h, m_Optimize.Source, sizeof(h)); + if (h.ID == cFreeBlockID) + { + _RemoveFreeBlock(m_Optimize.Source, h.Size); + + m_Optimize.Source += h.Size; + } else { + + if (bufsize < bufuse + h.Size) + { + buf = (uint8_t*)realloc(buf, bufuse + h.Size); + bufsize = bufuse + h.Size; + } + m_FileAccess.Read(buf + bufuse, m_Optimize.Source, h.Size); + + m_BlockTable[h.ID >> 2].Addr = (m_Optimize.Dest + bufuse) >> 2; + + m_Optimize.Source += h.Size; + bufuse += h.Size; + } + + if ((m_BlockSync.Waiting() > 0) + || (bufuse + 1024 >= bufsize) + || (m_Optimize.Source >= m_FileAccess.Size())) // buffer is nearly full or EOF + { + if (m_Optimize.Dest != m_Optimize.Source) // move blocks + { + TBlockHeadFree h = {cFreeBlockID, m_Optimize.Source - m_Optimize.Dest}; + TBlockTailFree t = {m_Optimize.Source - m_Optimize.Dest, cFreeBlockID}; + + m_FileAccess.Write(buf, m_Optimize.Dest, bufuse); + + m_FileAccess.Write(&h, m_Optimize.Dest + bufuse, sizeof(h)); + m_FileAccess.Invalidate(m_Optimize.Dest + bufuse + sizeof(h), m_Optimize.Source - m_Optimize.Dest - bufuse - sizeof(h) - sizeof(t)); + m_FileAccess.Write(&t, m_Optimize.Dest + bufuse - sizeof(t), sizeof(t)); + + if (m_SaveMode) + { + m_FileAccess.CloseTransaction(); + m_FileAccess.Flush(); + m_FileAccess.UseJournal(false); + + m_FileAccess.Write(buf, m_Optimize.Dest, bufuse); + + m_FileAccess.Write(&h, m_Optimize.Dest + bufuse, sizeof(h)); + m_FileAccess.Invalidate(m_Optimize.Dest + bufuse + sizeof(h), m_Optimize.Source - m_Optimize.Dest - bufuse - sizeof(h) - sizeof(t)); + m_FileAccess.Write(&t, m_Optimize.Dest + bufuse - sizeof(t), sizeof(t)); + + m_FileAccess.Flush(); + m_FileAccess.CleanJournal(); + m_FileAccess.UseJournal(true); + } + + m_Optimize.Dest += bufuse; + bufuse = 0; + } + + if (m_BlockSync.Waiting() > 0) + { + unsigned int w = m_BlockSync.Waiting(); + m_BlockSync.EndWrite(); + Sleep(w * 64 + 1); + m_BlockSync.BeginWrite(); + m_FileAccess.UseJournal(m_SaveMode); + } + } + } + + if (m_Optimize.Source >= m_FileAccess.Size()) + m_FileAccess.Size(m_Optimize.Dest); + + m_Optimize.Thread = NULL; + m_Optimize.Source = 0; + m_Optimize.Dest = 0; + if (m_SaveMode) + TransactionEndWrite(); + else + m_BlockSync.EndWrite(); + + free(buf); */ + + m_Optimize.Thread = NULL; +} + +inline void CBlockManager::_PendingAdd(uint32_t BlockID, uint32_t Addr, uint32_t Size, TCacheEntry * Cache) +{ + TPendingOperation * p = NULL; + if (BlockID == cFreeBlockID) + { + p = (TPendingOperation*)malloc(sizeof(TPendingOperation)); + + p->BlockID = cFreeBlockID; + p->Addr = Addr; + p->Size = Size; + p->CacheEntry = NULL; + p->EncryptionBuffer = NULL; + + m_BytesPending += 24 + sizeof(TBlockHeadFree) + sizeof(TBlockTailFree); + if (Addr & cPendingInvalidate) + m_BytesPending += 12; + + } else { + if (Cache->Pending) + { + p = Cache->Pending; + _PendingRemove(Cache->Pending, false); + } else { + p = (TPendingOperation*)malloc(sizeof(TPendingOperation)); + } + + p->BlockID = BlockID; + p->Addr = Addr; + p->Size = Size; + p->CacheEntry = Cache; + p->EncryptionBuffer = NULL; + + m_BytesPending += 12 + Size; + + Cache->Pending = p; + } + + p->Next = NULL; + p->Prev = m_PendingTail; + if (m_PendingTail) + m_PendingTail->Next = p; + + m_PendingTail = p; + if (!m_PendingHead) + m_PendingHead = p; +} + +inline void CBlockManager::_PendingRemove(TPendingOperation * Pending, bool Free) +{ + if (Pending->Prev) + Pending->Prev->Next = Pending->Next; + else + m_PendingHead = Pending->Next; + + if (Pending->Next) + Pending->Next->Prev = Pending->Prev; + else + m_PendingTail = Pending->Prev; + + if (Pending->EncryptionBuffer) + free(Pending->EncryptionBuffer); + + if (m_PendingLast == Pending) + m_PendingLast = Pending->Prev; + + Pending->CacheEntry->Pending = NULL; + if (Free) + free(Pending); +} + +inline void CBlockManager::_PendingFlush(bool FullFlush) +{ + TPendingOperation * i = NULL; + + if (m_ReadOnly) + return; + + if (FullFlush) + { + if (m_SaveMode) + { + _PendingFlush(false); // write to journal + m_FileAccess.Flush(); + m_FileAccess.UseJournal(false); + m_FileAccess.Size(m_FileAccess.Size()); // resize real file + } else { + m_FileAccess.UseJournal(false); + } + + i = m_PendingHead; + } else if (m_PendingLast) + { + i = m_PendingLast->Next; + m_FileAccess.UseJournal(m_SaveMode); + } else { + i = m_PendingHead; + m_FileAccess.UseJournal(m_SaveMode); + } + + while (i) + { + if (i->BlockID == cFreeBlockID) + { + uint32_t addr = i->Addr & ~cPendingInvalidate; + if (addr + i->Size <= m_FileAccess.Size()) + { + TBlockHeadFree h = {cFreeBlockID, i->Size}; + TBlockTailFree t = {i->Size, cFreeBlockID}; + + m_FileAccess.Write(&h, addr, sizeof(h)); + if (i->Addr & cPendingInvalidate) + m_FileAccess.Invalidate(addr + sizeof(h), i->Size - sizeof(h) - sizeof(t)); + m_FileAccess.Write(&t, addr + i->Size - sizeof(t), sizeof(t)); + } + + } else { + + if (i->BlockID && !i->EncryptionBuffer && m_EncryptionManager.IsEncrypted(i->BlockID)) + { + i->EncryptionBuffer = (TBlockHeadOcc*) malloc(i->Size); + memcpy(i->EncryptionBuffer, i->CacheEntry->Cache, i->Size); + m_EncryptionManager.Encrypt(i->EncryptionBuffer + 1, i->Size - sizeof(TBlockHeadOcc) - sizeof(TBlockTailOcc), i->BlockID, 0); + } + + if (i->EncryptionBuffer) + { + m_FileAccess.Write(i->EncryptionBuffer, i->Addr, i->Size); + } else { + m_FileAccess.Write(i->CacheEntry->Cache, i->Addr, i->Size); + } + } + + i = i->Next; + } // while + + if (FullFlush) + { + m_FileAccess.Flush(); + if (m_SaveMode) + m_FileAccess.CleanJournal(); + + m_BytesPending = 20; + m_LastFlush = time(NULL); + + i = m_PendingHead; + while (i) + { + if (i->EncryptionBuffer) + free(i->EncryptionBuffer); + + if (i->CacheEntry) + i->CacheEntry->Pending = NULL; + + TPendingOperation * tmp = i; + i = i->Next; + free(tmp); + } + m_PendingHead = NULL; + m_PendingTail = NULL; + m_PendingLast = NULL; + } else { + m_PendingLast = m_PendingTail; + m_FileAccess.CloseTransaction(); + } +} + +inline CBlockManager::TCacheEntry * CBlockManager::_CacheInsert(uint32_t Idx, TBlockHeadOcc * Cache, bool Virtual) +{ + TCacheEntry * res; + uint32_t myidx = ROR_32(Idx, cCacheBuddyBits); + + res = (TCacheEntry *)malloc(sizeof(TCacheEntry)); + res->Cache = Cache; + res->Pending = NULL; + res->Idx = myidx; + res->Forced = Virtual; + + TCacheEntry * volatile * last = &m_Cache[Idx % cCacheBuddyCount]; + TCacheEntry * i; + do { + i = *last; + + while (i && (i->Idx < myidx)) + { + last = &i->Next; + i = i->Next; + } + + if (i && (i->Idx == myidx)) + { + free(res); + free(Cache); + + i->LastUse = time(NULL) >> 2; + return i; + } + + res->Next = i; + + } while (i != CMPXCHG_Ptr(*last, res, i)); + + res->LastUse = time(NULL) >> 2; + + m_BlockTable[Idx].InCache = true; + if (!Virtual) + XADD_32(m_CacheInfo.Growth, res->Cache->Size); + + return res; +} + +inline CBlockManager::TCacheEntry * CBlockManager::_CacheFind(uint32_t Idx) +{ + TCacheEntry * i = m_Cache[Idx % cCacheBuddyCount]; + uint32_t myidx = ROR_32(Idx, cCacheBuddyBits); + while (i && (i->Idx < myidx)) + i = i->Next; + + if (i && (i->Idx == myidx)) + return i; + else + return NULL; +} + +inline void CBlockManager::_CacheErase(uint32_t Idx) +{ + TCacheEntry * i = m_Cache[Idx % cCacheBuddyCount]; + TCacheEntry * volatile * l = &m_Cache[Idx % cCacheBuddyCount]; + + uint32_t myidx = ROR_32(Idx, cCacheBuddyBits); + + while (i->Idx < myidx) + { + l = &i->Next; + i = i->Next; + } + *l = i->Next; + + if (i->Cache) + free(i->Cache); + free(i); +} + +inline void CBlockManager::_CachePurge() +{ + _PendingFlush(true); + + uint32_t ts = time(NULL); + if (m_CacheInfo.Size + m_CacheInfo.Growth > cCachePurgeSize) { + ts = ts - (ts - m_CacheInfo.LastPurge) * cCachePurgeSize / (m_CacheInfo.Size + 2 * m_CacheInfo.Growth); + } else if (m_CacheInfo.Growth > m_CacheInfo.Size) + { + ts = ts - (ts - m_CacheInfo.LastPurge) * m_CacheInfo.Size / m_CacheInfo.Growth; + } else if (m_CacheInfo.Size > m_CacheInfo.Growth) + { + ts = ts - (ts - m_CacheInfo.LastPurge) * m_CacheInfo.Growth / m_CacheInfo.Size; + } else { + ts = m_CacheInfo.LastPurge; + } + + m_CacheInfo.Size += m_CacheInfo.Growth; + m_CacheInfo.Growth = 0; + m_CacheInfo.LastPurge = time(NULL); + + for (uint32_t buddy = 0; buddy < cCacheBuddyCount; buddy++) + { + TCacheEntry * i = m_Cache[buddy]; + TCacheEntry * volatile * l = &m_Cache[buddy]; + + while (i) + { + if (!i->Forced && !i->KeepInCache && i->Idx && ((i->LastUse << 2) < ts)) + { + uint32_t idx = ROL_32(i->Idx, cCacheBuddyBits); + m_CacheInfo.Size -= i->Cache->Size; + m_BlockTable[idx].InCache = false; + free(i->Cache); + + *l = i->Next; + TCacheEntry * tmp = i; + i = i->Next; + free(tmp); + + } else { + l = &i->Next; + i = i->Next; + } + } + } +} + +inline uint32_t CBlockManager::_GetAvailableIndex() +{ + uint32_t id; + if (m_FirstFreeIndex) + { + id = m_FirstFreeIndex; + m_FirstFreeIndex = m_BlockTable[id].Addr; + TBlockTableEntry b = {false, false, 0}; + m_BlockTable[id] = b; + } else { + id = static_cast(m_BlockTable.size()); + if (id > (1 << 12)) + m_BlockTable.resize(id + (1 << 12)); + else + m_BlockTable.resize(id * 2); + + for (uint32_t i = static_cast(m_BlockTable.size() - 1); i > id; --i) + { + TBlockTableEntry b = {true, true, m_FirstFreeIndex}; + m_BlockTable[i] = b; + m_FirstFreeIndex = i; + } + } + return id; +} + +inline void CBlockManager::_InsertFreeBlock(uint32_t Addr, uint32_t Size, bool InvalidateData, bool Reuse) +{ + if (Addr + Size == m_FileAccess.Size()) + { + if (Reuse) // in FindFreePosition we would want to use that block + m_FileAccess.Size(Addr); + } else { + + if (Reuse) + m_FreeBlocks.insert(std::make_pair(Size, Addr)); + + if (!m_ReadOnly) + _PendingAdd(cFreeBlockID, InvalidateData ? Addr | cPendingInvalidate : Addr, Size, NULL); + + } +} + +inline void CBlockManager::_RemoveFreeBlock(uint32_t Addr, uint32_t Size) +{ + TFreeBlockMap::iterator i = m_FreeBlocks.find(Size); + while ((i != m_FreeBlocks.end()) && (i->first == Size)) + { + if (i->second == Addr) + { + m_FreeBlocks.erase(i); + i = m_FreeBlocks.end(); + } else { + ++i; + } + } +} + +inline uint32_t CBlockManager::_FindFreePosition(uint32_t Size) +{ + // try to find free block + TFreeBlockMap::iterator f; + TFreeBlockMap::iterator e = m_FreeBlocks.end(); + + if (m_FreeBlocks.size()) + { + f = m_FreeBlocks.find(Size); + if (f == e) + { + if (m_FreeBlocks.rbegin()->first > Size * 2) + { + f = m_FreeBlocks.end(); + --f; + } + } + } else { + f = e; + } + + uint32_t addr = 0; + + if (f == e) // no block found - expand file + { + addr = m_FileAccess.Size(); + m_FileAccess.Size(addr + Size); + + } else { + addr = f->second; + + if (f->first != Size) + { + _InsertFreeBlock(addr + Size, f->first - Size, false, true); + } + _InsertFreeBlock(addr, Size, false, false); + + m_FreeBlocks.erase(f); + } + + return addr; +} + +inline bool CBlockManager::_InitOperation(uint32_t BlockID, uint32_t & Addr, TCacheEntry * & Cache) +{ + if (!BlockID || (BlockID & 3) || ((BlockID >> 2) >= m_BlockTable.size())) + return false; + + uint32_t idx = BlockID >> 2; + TBlockTableEntry dat = m_BlockTable[idx]; + + if (dat.Deleted) // deleted or FreeIDList item + return false; + + Addr = dat.Addr << 2; + if (dat.InCache) + { + Cache = _CacheFind(idx); + } else if (Addr) + { + TBlockHeadOcc h; + + m_FileAccess.Read(&h, Addr, sizeof(h)); + + TBlockHeadOcc * block = (TBlockHeadOcc *) malloc(h.Size); + m_FileAccess.Read(block, Addr, h.Size); + + m_EncryptionManager.Decrypt(block + 1, h.Size - sizeof(TBlockHeadOcc) - sizeof(TBlockTailOcc), BlockID, 0); + + Cache = _CacheInsert(idx, block, false); + } else { + return false; + } + + return Cache != NULL; +} + +inline void CBlockManager::_UpdateBlock(uint32_t BlockID, TCacheEntry * CacheEntry, uint32_t Addr) +{ + CacheEntry->KeepInCache = m_ReadOnly; + + if (!CacheEntry->Forced) + { + if (!m_ReadOnly) + _PendingAdd(BlockID, Addr, CacheEntry->Cache->Size, CacheEntry); + } +} + + +uint32_t CBlockManager::ScanFile(uint32_t FirstBlockStart, uint32_t HeaderSignature, uint32_t FileSize) +{ + TBlockHeadOcc h, lasth = {0, 0, 0}; + uint32_t p; + uint32_t res = 0; + bool invalidateblock = false; + + p = FirstBlockStart; + m_FirstBlockStart = FirstBlockStart; + m_Optimize.Source = 0; + m_Optimize.Dest = 0; + + { // insert header cache element + void * header = malloc(FirstBlockStart); + m_FileAccess.Read(header, 0, FirstBlockStart); + _CacheInsert(0, (TBlockHeadOcc*)header, false); + } + + TransactionBeginWrite(); + + while (p < FileSize) + { + m_FileAccess.Read(&h, p, sizeof(h)); + if (CLogger::Instance().Level() >= CLogger::logERROR || !h.Size) + { + LOG(logCRITICAL, _T("Block-structure of file is corrupt!")); + return 0; + } + + if (h.ID == cFreeBlockID) + { + if (m_Optimize.Dest == 0) + m_Optimize.Dest = p; + + if (lasth.ID == cFreeBlockID) + { + lasth.Size += h.Size; + invalidateblock = true; + } else { + lasth = h; + } + + } else { + + if (lasth.ID == cFreeBlockID) + { + if (m_Optimize.Source == 0) + m_Optimize.Source = p; + + _InsertFreeBlock(p - lasth.Size, lasth.Size, invalidateblock, true); + } + lasth = h; + invalidateblock = false; + + while ((h.ID >> 2) >= m_BlockTable.size()) + m_BlockTable.resize(m_BlockTable.size() << 1); + + m_BlockTable[h.ID >> 2].Addr = p >> 2; + + if (h.Signature == HeaderSignature) + res = h.ID; + } + + p = p + h.Size; + } + + m_FirstFreeIndex = 0; + for (uint32_t i = static_cast(m_BlockTable.size() - 1); i > 0; --i) + { + if (m_BlockTable[i].Addr == 0) + { + TBlockTableEntry b = {true, true, m_FirstFreeIndex}; + m_BlockTable[i] = b; + m_FirstFreeIndex = i; + } + } + + TransactionEndWrite(); + + if (m_Optimize.Source && !m_FileAccess.ReadOnly()) + { + m_Optimize.Thread = new COptimizeThread(*this); + m_Optimize.Thread->Priority(CThread::tpLowest); + m_Optimize.Thread->FreeOnTerminate(true); + m_Optimize.Thread->Resume(); + } + + return res; +} + +void * CBlockManager::_CreateBlock(uint32_t & BlockID, const uint32_t Signature, uint32_t Size) +{ + uint32_t idx = _GetAvailableIndex(); + BlockID = idx << 2; + + Size = m_EncryptionManager.AlignSize(BlockID, (Size + 3) & 0xfffffffc); // align on cipher after we aligned on 4 bytes + + TBlockHeadOcc h = {BlockID, Size + sizeof(TBlockHeadOcc) + sizeof(TBlockTailOcc), Signature}; + TBlockTailOcc t = {BlockID}; + + TBlockHeadOcc * block = (TBlockHeadOcc*) malloc(Size + sizeof(h) + sizeof(t)); + *block = h; + memset(block + 1, 0, Size); + *(TBlockTailOcc*)(((uint8_t*)(block + 1)) + Size) = t; + + TCacheEntry * ce = _CacheInsert(idx, block, false); + + if (m_ReadOnly) + { + TBlockTableEntry b = {false, true, 0}; + m_BlockTable[idx] = b; + } else { + uint32_t addr = _FindFreePosition(Size + sizeof(h) + sizeof(t)); + TBlockTableEntry b = {false, true, addr >> 2 }; + m_BlockTable[idx] = b; + + _UpdateBlock(BlockID, ce, addr); + } + + return ce->Cache + 1; +} + +void * CBlockManager::_CreateBlockVirtual(uint32_t & BlockID, const uint32_t Signature, uint32_t Size) +{ + uint32_t idx = _GetAvailableIndex(); + BlockID = idx << 2; + + Size = m_EncryptionManager.AlignSize(BlockID, (Size + 3) & 0xfffffffc); // align on cipher after we aligned on 4 bytes + + TBlockHeadOcc h = {BlockID, Size + sizeof(TBlockHeadOcc) + sizeof(TBlockTailOcc), Signature}; + TBlockTailOcc t = {BlockID}; + + TBlockHeadOcc * block = (TBlockHeadOcc*) malloc(Size + sizeof(h) + sizeof(t)); + *block = h; + memset(block + 1, 0, Size); + *(TBlockTailOcc*)(((uint8_t*)(block + 1)) + Size) = t; + + return _CacheInsert(idx, block, true)->Cache + 1; +} + +bool CBlockManager::DeleteBlock(uint32_t BlockID) +{ + uint32_t idx = BlockID >> 2; + uint32_t addr; + uint32_t size; + TCacheEntry * ce; + if (!_InitOperation(BlockID, addr, ce)) + return false; + + if (!ce->Forced) + XADD_32(m_CacheInfo.Size, 0 - ce->Cache->Size); + + if (ce->Pending) + _PendingRemove(ce->Pending, true); + + size = ce->Cache->Size; + _CacheErase(idx); + + if (addr == 0) // Block in memory only + { + TBlockTableEntry b = {false, false, 0}; + m_BlockTable[idx] = b; + + } else if (m_ReadOnly) + { + m_BlockTable[idx].Deleted = true; + m_BlockTable[idx].InCache = false; + } else { + _InsertFreeBlock(addr, size, true, true); + + TBlockTableEntry b = {false, false, 0}; + m_BlockTable[idx] = b; + } + + return true; +} + +uint32_t CBlockManager::_ResizeBlock(uint32_t BlockID, void * & Buffer, uint32_t Size) +{ + uint32_t idx = BlockID >> 2; + uint32_t addr; + TCacheEntry * ce; + + if (Size == 0) + return 0; + + if (!_InitOperation(BlockID, addr, ce)) + return 0; + + Size = m_EncryptionManager.AlignSize(BlockID, (Size + 3) & 0xfffffffc); // align on cipher after we aligned on 4 bytes + + uint32_t os = ce->Cache->Size; + uint32_t ns = Size + sizeof(TBlockHeadOcc) + sizeof(TBlockTailOcc); + if (ns == ce->Cache->Size) + { + Buffer = ce->Cache + 1; + return Size; + } + + ce->Cache = (TBlockHeadOcc*) realloc(ce->Cache, ns); + ce->Cache->Size = ns; + TBlockTailOcc t = {BlockID}; + *(TBlockTailOcc*)(((uint8_t*)(ce->Cache + 1)) + Size) = t; + XADD_32(m_CacheInfo.Size, ns - os); + + Buffer = ce->Cache + 1; + ce->KeepInCache = m_ReadOnly; + + if (!m_ReadOnly && addr) + { + _InsertFreeBlock(addr, os, true, true); + addr = _FindFreePosition(ns); + m_BlockTable[idx].Addr = addr >> 2; + + _UpdateBlock(BlockID, ce, addr); // write down + } + + return Size; +} + +bool CBlockManager::IsForcedVirtual(uint32_t BlockID) +{ + TCacheEntry * ce = _CacheFind(BlockID >> 2); + return ce && ce->Forced; +} + +bool CBlockManager::WriteBlockToDisk(uint32_t BlockID) +{ + uint32_t addr; + TCacheEntry * ce; + + if (!_InitOperation(BlockID, addr, ce)) + return false; + + if (!ce->Forced) + return true; + + ce->Forced = false; + XADD_32(m_CacheInfo.Size, ce->Cache->Size); + + if (!m_ReadOnly) + { + addr = _FindFreePosition(ce->Cache->Size); + m_BlockTable[BlockID >> 2].Addr = addr >> 2; + _UpdateBlock(BlockID, ce, addr); + } + return true; +} + +bool CBlockManager::MakeBlockVirtual(uint32_t BlockID) +{ + uint32_t addr; + TCacheEntry * ce; + + if (!_InitOperation(BlockID, addr, ce)) + return false; + + if (ce->Forced) + return true; + + if (ce->Pending) // don't write down, we kill it anyway + _PendingRemove(ce->Pending, true); + + ce->Forced = true; + XADD_32(m_CacheInfo.Size, 0 - ce->Cache->Size); + + if (!m_ReadOnly) + { + _InsertFreeBlock(addr, ce->Cache->Size, true, true); + m_BlockTable[BlockID >> 2].Addr = 0; + } + return true; +} + +void * CBlockManager::_ReadBlock(uint32_t BlockID, uint32_t & Size, uint32_t & Signature) +{ + uint32_t addr; + TCacheEntry * ce; + + if ((BlockID == 0) && (Signature == -1)) + { + Size = m_FirstBlockStart; + return m_Cache[0]->Cache; + } + + if (!_InitOperation(BlockID, addr, ce)) + return NULL; + + if ((Signature != 0) && (Signature != ce->Cache->Signature)) + { + Signature = ce->Cache->Signature; + return NULL; + } + Signature = ce->Cache->Signature; + + if ((Size != 0) && (Size != ce->Cache->Size - sizeof(TBlockHeadOcc) - sizeof(TBlockTailOcc))) + { + Size = ce->Cache->Size - sizeof(TBlockHeadOcc) - sizeof(TBlockTailOcc); + return NULL; + } + Size = ce->Cache->Size - sizeof(TBlockHeadOcc) - sizeof(TBlockTailOcc); + + return ce->Cache + 1; +} + +bool CBlockManager::UpdateBlock(uint32_t BlockID, uint32_t Signature) +{ + uint32_t addr; + TCacheEntry * ce; + + if ((BlockID == 0) && (Signature == -1)) + { + if (!m_ReadOnly) + _PendingAdd(0, 0, m_FirstBlockStart, m_Cache[0]); + + return true; + } + + if (!_InitOperation(BlockID, addr, ce)) + return false; + + if (Signature) + ce->Cache->Signature = Signature; + + _UpdateBlock(BlockID, ce, addr); + + return true; +} + +// make file writeable: +// write all cached blocks to file and check for the old addresses +// remove virtual only from file +// update m_FreeBlocks along the way + diff --git a/plugins/Dbx_tree/src/BlockManager.h b/plugins/Dbx_tree/src/BlockManager.h new file mode 100644 index 0000000000..dcccd4f0b9 --- /dev/null +++ b/plugins/Dbx_tree/src/BlockManager.h @@ -0,0 +1,401 @@ +/* + +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. + +*/ + +#pragma once + +#include +#include +#include + +#include "stdint.h" +#include "FileAccess.h" +#include "EncryptionManager.h" +#include "MREWSync.h" +#include "Thread.h" +#include "intrinsics.h" + +class CBlockManager +{ +protected: + static const uint32_t cFreeBlockID = 0xFFFFFFFF; + + static const uint32_t cJournalFlushBytes = (1 << 20) - 2048; // flush before reserved journal-space is exhausted + static const uint32_t cJournalFlushTimeout = 300; // journal flush every 5 minutes + + static const uint32_t cCacheBuddyBits = 10; + static const uint32_t cCacheBuddyCount = 1 << cCacheBuddyBits; // count of static allocated buddy nodes + static const uint32_t cCacheBuddyCheck = 0xffffffff << cCacheBuddyBits; + + static const uint32_t cCacheMinimumTimeout = 2; // purge less than every n seconds (high priority) + static const uint32_t cCacheMaximumTimeout = 600; // purge every 10 minutes (high priority) + static const uint32_t cCachePurgeSize = 1 << 21; // cache up to 2MB + static const uint32_t cCacheMinimumGrowthForPurge = 1 << 19; // cache only when 512kb were added + + #pragma pack(push, 1) // push current alignment to stack, set alignment to 1 byte boundary + + typedef struct TBlockHeadFree { + uint32_t ID; + uint32_t Size; + } TBlockHeadFree; + typedef struct TBlockHeadOcc { + uint32_t ID; + uint32_t Size; + uint32_t Signature; /// if occupied block + } TBlockHeadOcc; + + typedef struct TBlockTailOcc { + uint32_t ID; + } TBlockTailOcc; + + typedef struct TBlockTailFree { + uint32_t Size; /// if free block + uint32_t ID; + } TBlockTailFree; + + #pragma pack(pop) + + //////////////////////////////////////////////////////////////////////////////////////////////////// + /// Block table entry. + /// + /// Addr Deleted InCache Meaning + /// 0 0 0 successfully deleted block + /// 0 0 1 virtual only block (either forced virtual or created on a read-only file) + /// 0 1 0 invalid + /// 0 1 1 FreeID list (last entry) + /// set 0 0 Normal in-file block + /// set 0 1 in file and cache (normal cache which could differ on a read-only file or forced virtual out of a read-only file - check TCacheEntry) + /// set 1 0 deleted block or a read-only file + /// set 1 1 FreeID list entry + /// + /// Michael "Protogenes" Kunz, 07.09.2010. + //////////////////////////////////////////////////////////////////////////////////////////////////// + typedef struct TBlockTableEntry { + uint32_t Deleted : 1; ///< Flag is set if the block was deleted but can't be removed, because the file is read-only + uint32_t InCache : 1; ///< Flag is set if block is in the cache (either forced virtual or from the file) + uint32_t Addr : 30; ///< The Offset in the file div 4, so we can address files up to 4GB + } TBlockTableEntry; + std::vector m_BlockTable; + + struct TPendingOperation; + typedef struct TCacheEntry { + TCacheEntry * volatile Next; + TBlockHeadOcc * volatile Cache; + TPendingOperation * Pending; + + uint32_t Idx; + uint32_t Forced : 1; + uint32_t KeepInCache : 1; + uint32_t LastUse : 30; + } TCacheEntry; + + TCacheEntry * m_Cache[cCacheBuddyCount]; + + struct { + uint32_t volatile Size; + uint32_t volatile Growth; + uint32_t volatile LastPurge; + } m_CacheInfo; + + CFileAccess & m_FileAccess; + CEncryptionManager & m_EncryptionManager; + CMultiReadExclusiveWriteSynchronizer m_BlockSync; + + uint32_t m_FirstBlockStart; + bool m_SaveMode; + bool m_ReadOnly; + + typedef std::multimap TFreeBlockMap; + TFreeBlockMap m_FreeBlocks; + uint32_t m_FirstFreeIndex; + + static const uint32_t cPendingInvalidate = 0x00000001; + typedef struct TPendingOperation { + TPendingOperation * Next; ///< The next + TPendingOperation * Prev; ///< The previous + uint32_t BlockID; ///< Identifier for the block + uint32_t Addr; ///< The address in the file + uint32_t Size; ///< The size of the block + TCacheEntry * CacheEntry; ///< The cache entry + TBlockHeadOcc * EncryptionBuffer; ///< Buffer for encrypted block + } TPendingOperation; + + TPendingOperation * m_PendingHead; ///< The double linked list head + TPendingOperation * m_PendingTail; ///< The double linked list tail + TPendingOperation * m_PendingLast; ///< The last processed item + + uint32_t m_LastFlush; ///< The last flush timestamp + uint32_t m_BytesPending; ///< The bytes pending for write + + class COptimizeThread : public CThread + { + protected: + CBlockManager & m_Owner; + void Execute() { m_Owner.ExecuteOptimize(); }; + public: + COptimizeThread(CBlockManager & Owner) : CThread(true), m_Owner(Owner) {}; + ~COptimizeThread() {}; + }; + + struct { + uint32_t Source; + uint32_t Dest; + COptimizeThread * Thread; + } m_Optimize; + void ExecuteOptimize(); + + uint32_t _GetAvailableIndex(); + void _InsertFreeBlock(uint32_t Addr, uint32_t Size, bool InvalidateData, bool Reuse); + void _RemoveFreeBlock(uint32_t Addr, uint32_t Size); + uint32_t _FindFreePosition(uint32_t Size); + + bool _InitOperation(uint32_t BlockID, uint32_t & Addr, TCacheEntry * & Cache); + void _UpdateBlock(uint32_t BlockID, TCacheEntry * CacheEntry, uint32_t Addr); + + void * _ReadBlock(uint32_t BlockID, uint32_t & Size, uint32_t & Signature); + void * _CreateBlock(uint32_t & BlockID, const uint32_t Signature, uint32_t Size); + void * _CreateBlockVirtual(uint32_t & BlockID, const uint32_t Signature, uint32_t Size); + uint32_t _ResizeBlock(uint32_t BlockID, void * & Buffer, uint32_t Size); + + TCacheEntry * _CacheInsert(uint32_t Idx, TBlockHeadOcc * Cache, bool Virtual); + TCacheEntry * _CacheFind(uint32_t Idx); + void _CacheErase(uint32_t Idx); + + void _CachePurge(); + void _PendingAdd(uint32_t BlockID, uint32_t Addr, uint32_t Size, TCacheEntry * Cache); + void _PendingRemove(TPendingOperation * Pending, bool Free); + void _PendingFlush(bool FullFlush); + + + + void TransactionBeginRead() + { + m_BlockSync.BeginRead(); + }; + + void TransactionEndRead() + { + m_BlockSync.EndRead(); + }; + + void TransactionBeginWrite() + { + m_BlockSync.BeginWrite(); + m_FileAccess.UseJournal(m_SaveMode); + }; + + void TransactionEndWrite() + { + if (m_BlockSync.WriteRecursionCount() == 1) + { + m_FileAccess.CompleteTransaction(); + m_BytesPending += 12; + + if ((m_CacheInfo.LastPurge + cCacheMaximumTimeout < time(NULL)) + || ((m_CacheInfo.Size + m_CacheInfo.Growth > cCachePurgeSize) + && (m_CacheInfo.Growth > cCacheMinimumGrowthForPurge) + && (m_CacheInfo.LastPurge + cCacheMinimumTimeout < time(NULL)))) + { + _CachePurge(); + } else if ((m_BytesPending >= cJournalFlushBytes) || (time(NULL) > m_LastFlush + cJournalFlushTimeout)) + { + _PendingFlush(true); + } else { + _PendingFlush(false); + } + } + + m_BlockSync.EndWrite(); + }; +public: + CBlockManager(CFileAccess & FileAccess, CEncryptionManager & EncryptionManager); + ~CBlockManager(); + + + class ReadTransaction + { + private: + CBlockManager * m_Owner; + uint32_t volatile * m_RefCount; + bool m_Closed; + public: + ReadTransaction() + : m_Owner(NULL), + m_RefCount(NULL), + m_Closed(true) + { + + }; + ReadTransaction(CBlockManager & BlockManager) + : m_Owner(&BlockManager), + m_RefCount(new uint32_t(1)), + m_Closed(false) + { + m_Owner->TransactionBeginRead(); + }; + ReadTransaction(const ReadTransaction & Other) + : m_Owner(Other.m_Owner), + m_RefCount(Other.m_RefCount), + m_Closed(Other.m_Closed) + { + if (!m_Closed) + INC_32(*m_RefCount); + }; + ~ReadTransaction() + { + if (!m_Closed && (DEC_32(*m_RefCount) == 0)) + { + delete m_RefCount; + m_Owner->TransactionEndRead(); + } + }; + + ReadTransaction & operator =(const ReadTransaction & Other) + { + if (!m_Closed && (DEC_32(*m_RefCount) == 0)) + { + delete m_RefCount; + m_Owner->TransactionEndRead(); + } + + m_Owner = Other.m_Owner; + m_RefCount = Other.m_RefCount; + m_Closed = Other.m_Closed; + if (!m_Closed) + INC_32(*m_RefCount); + + return *this; + } + + void Close() + { + if (!m_Closed && (DEC_32(*m_RefCount) == 0)) + { + delete m_RefCount; + m_Owner->TransactionEndRead(); + } + m_Closed = true; + } + + }; + class WriteTransaction + { + private: + CBlockManager * m_Owner; + uint32_t volatile * m_RefCount; + bool m_Closed; + public: + WriteTransaction() + : m_Owner(NULL), + m_RefCount(NULL), + m_Closed(true) + { + + }; + WriteTransaction(CBlockManager & BlockManager) + : m_Owner(&BlockManager), + m_RefCount(new uint32_t(1)), + m_Closed(false) + { + m_Owner->TransactionBeginWrite(); + }; + WriteTransaction(const WriteTransaction & Other) + : m_Owner(Other.m_Owner), + m_RefCount(Other.m_RefCount), + m_Closed(Other.m_Closed) + { + if (!m_Closed) + INC_32(*m_RefCount); + }; + ~WriteTransaction() + { + if (!m_Closed && (DEC_32(*m_RefCount) == 0)) + { + delete m_RefCount; + m_Owner->TransactionEndWrite(); + } + }; + + WriteTransaction & operator =(const WriteTransaction & Other) + { + if (!m_Closed && (DEC_32(*m_RefCount) == 0)) + { + delete m_RefCount; + m_Owner->TransactionEndWrite(); + } + + m_Owner = Other.m_Owner; + m_RefCount = Other.m_RefCount; + m_Closed = Other.m_Closed; + if (!m_Closed) + INC_32(*m_RefCount); + + return *this; + } + + void Close() + { + if (!m_Closed && (DEC_32(*m_RefCount) == 0)) + { + delete m_RefCount; + m_Owner->TransactionEndWrite(); + } + m_Closed = true; + } + + }; + + uint32_t ScanFile(uint32_t FirstBlockStart, uint32_t HeaderSignature, uint32_t FileSize); + + template + BlockType * ReadBlock(uint32_t BlockID, uint32_t & Size, uint32_t & Signature) + { + return reinterpret_cast(_ReadBlock(BlockID, Size, Signature)); + }; + + template + BlockType * CreateBlock(uint32_t & BlockID, const uint32_t Signature, uint32_t Size = sizeof(BlockType)) + { + return reinterpret_cast(_CreateBlock(BlockID, Signature, Size)); + }; + + template + BlockType * CreateBlockVirtual(uint32_t & BlockID, const uint32_t Signature, uint32_t Size = sizeof(BlockType)) + { + return reinterpret_cast(_CreateBlockVirtual(BlockID, Signature, Size)); + }; + + template + uint32_t ResizeBlock(uint32_t BlockID, BlockType * & Buffer, uint32_t Size) + { + void * tmp = Buffer; + uint32_t res = _ResizeBlock(BlockID, tmp, Size); + Buffer = reinterpret_cast(tmp); + return res; + }; + + bool UpdateBlock(uint32_t BlockID, uint32_t Signature = 0); + bool DeleteBlock(uint32_t BlockID); + + bool IsForcedVirtual(uint32_t BlockID); + bool WriteBlockToDisk(uint32_t BlockID); + bool MakeBlockVirtual(uint32_t BlockID); +}; diff --git a/plugins/Dbx_tree/src/Compatibility.cpp b/plugins/Dbx_tree/src/Compatibility.cpp new file mode 100644 index 0000000000..759e44012c --- /dev/null +++ b/plugins/Dbx_tree/src/Compatibility.cpp @@ -0,0 +1,799 @@ +/* + +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 "Compatibility.h" +#include "Logger.h" +#define DB_NOHELPERFUNCTIONS +#include "m_database.h" +#include "m_db_int.h" +#undef DB_NOHELPERFUNCTIONS +#ifndef _MSC_VER +#include "savestrings_gcc.h" +#endif + +HANDLE gEvents[6] = {0,0,0,0,0,0}; + +HANDLE hEventDeletedEvent, + hEventAddedEvent, + hEventFilterAddedEvent, + hSettingChangeEvent, + hContactDeletedEvent, + hContactAddedEvent; + +STDMETHODIMP_(HANDLE) CDataBase::AddContact(void) +{ + TDBTEntity entity = {0,0,0,0}; + entity.hParentEntity = DBEntityGetRoot(0, 0); + entity.hAccountEntity = entity.hParentEntity; + + TDBTEntityHandle res = gDataBase->getEntities().CreateEntity(entity); + if (res == DBT_INVALIDPARAM) + return (HANDLE)1; + + NotifyEventHooks(hContactAddedEvent, res, 0); + return (HANDLE)res; +} + +STDMETHODIMP_(LONG) CDataBase::DeleteContact(HANDLE hContact) +{ + NotifyEventHooks(hContactDeletedEvent, (WPARAM)hContact, 0); + + int res = DBEntityDelete((WPARAM)hContact, 0); + if (res == DBT_INVALIDPARAM) + return 1; + + return res; +} + +STDMETHODIMP_(BOOL) CDataBase::IsDbContact(HANDLE hContact) +{ + int flags = DBEntityGetFlags((WPARAM)hContact, 0); + return (flags != DBT_INVALIDPARAM) && + ((flags & DBT_NFM_SpecialEntity) == 0); +} + +STDMETHODIMP_(LONG) CDataBase::GetContactCount(void) +{ + TDBTEntityIterFilter f = {0,0,0,0}; + f.cbSize = sizeof(f); + f.fDontHasFlags = DBT_NF_IsGroup | DBT_NF_IsVirtual | DBT_NF_IsAccount | DBT_NF_IsRoot; + f.Options = DBT_NIFO_OSC_AC | DBT_NIFO_OC_AC; + + TDBTEntityIterationHandle hiter = DBEntityIterInit((WPARAM)&f, gDataBase->getEntities().getRootEntity()); + int c = 0; + if ((hiter != 0) && (hiter != DBT_INVALIDPARAM)) + { + TDBTEntityHandle con = DBEntityIterNext(hiter, 0); + + while ((con != DBT_INVALIDPARAM) && (con != 0)) + { + if ((con != 0) && (con != DBT_INVALIDPARAM)) + c++; + + con = DBEntityIterNext(hiter, 0); + } + DBEntityIterClose(hiter, 0); + } + return c; +} + +//!!!!!!!!!!!!!!!!!!!! szProto ignored +STDMETHODIMP_(HANDLE) CDataBase::FindFirstContact(const char* szProto) +{ + return (HANDLE)gDataBase->getEntities().compFirstContact(); +} + +//!!!!!!!!!!!!!!!!!!!! szProto ignored +STDMETHODIMP_(HANDLE) CDataBase::FindNextContact(HANDLE hContact, const char* szProto) +{ + return (HANDLE)gDataBase->getEntities().compNextContact((WPARAM)hContact); +} + +STDMETHODIMP_(BOOL) CDataBase::GetContactSetting(HANDLE hContact, DBCONTACTGETSETTING *dbcgs) +{ + dbcgs->pValue->type = 0; + + char namebuf[512]; + namebuf[0] = 0; + + if (!(dbcgs->szModule || dbcgs->szSetting)) + return -1; + + if (dbcgs->szModule) + strcpy_s(namebuf, dbcgs->szModule); + strcat_s(namebuf, "/"); + if (dbcgs->szSetting) + strcat_s(namebuf, dbcgs->szSetting); + + TDBTSettingDescriptor desc = {0,0,0,0,0,0,0,0}; + TDBTSetting set = {0,0,0,0}; + desc.cbSize = sizeof(desc); + desc.Entity = (WPARAM)hContact; + desc.pszSettingName = namebuf; + + set.cbSize = sizeof(set); + set.Descriptor = &desc; + + if (DBSettingRead(reinterpret_cast(&set), 0) == DBT_INVALIDPARAM) + return -1; + + switch (set.Type) + { + case DBT_ST_ANSI: + { + dbcgs->pValue->type = DBVT_ASCIIZ; + dbcgs->pValue->pszVal = set.Value.pAnsi; + dbcgs->pValue->cchVal = set.Value.Length - 1; + } break; + case DBT_ST_UTF8: + { + dbcgs->pValue->type = DBVT_WCHAR; + dbcgs->pValue->pwszVal = mir_utf8decodeW(set.Value.pUTF8); + if (dbcgs->pValue->pwszVal) + dbcgs->pValue->cchVal = static_cast(wcslen(dbcgs->pValue->pwszVal)); + else + dbcgs->pValue->cchVal = 0; + mir_free(set.Value.pUTF8); + } break; + case DBT_ST_WCHAR: + { + dbcgs->pValue->type = DBVT_WCHAR; + dbcgs->pValue->pwszVal = set.Value.pWide; + dbcgs->pValue->cchVal = set.Value.Length - 1; + } break; + case DBT_ST_BLOB: + { + dbcgs->pValue->type = DBVT_BLOB; + dbcgs->pValue->pbVal = set.Value.pBlob; + dbcgs->pValue->cpbVal = set.Value.Length; + } break; + case DBT_ST_BOOL: + { + dbcgs->pValue->type = DBVT_BYTE; + dbcgs->pValue->bVal = (uint8_t)set.Value.Bool; + } break; + case DBT_ST_BYTE: case DBT_ST_CHAR: + { + dbcgs->pValue->type = DBVT_BYTE; + dbcgs->pValue->bVal = set.Value.Byte; + } break; + case DBT_ST_SHORT: case DBT_ST_WORD: + { + dbcgs->pValue->type = DBVT_WORD; + dbcgs->pValue->wVal = set.Value.Word; + } break; + case DBT_ST_INT: case DBT_ST_DWORD: + { + dbcgs->pValue->type = DBVT_DWORD; + dbcgs->pValue->dVal = set.Value.DWord; + } break; + case DBT_ST_INT64: case DBT_ST_QWORD: + case DBT_ST_DOUBLE: case DBT_ST_FLOAT: + { + dbcgs->pValue->type = DBVT_BLOB; + dbcgs->pValue->cpbVal = sizeof(set.Value); + dbcgs->pValue->pbVal = reinterpret_cast(mir_alloc(sizeof(set.Value))); + memcpy(dbcgs->pValue->pbVal, &set.Value, sizeof(set.Value)); + } break; + + default: + return -1; + } + + return 0; +} + +STDMETHODIMP_(BOOL) CDataBase::GetContactSettingStr(HANDLE hContact, DBCONTACTGETSETTING *dbcgs) +{ + if ((dbcgs->pValue->type & DBVTF_VARIABLELENGTH) == 0) + { + FreeVariant(dbcgs->pValue); + dbcgs->pValue->type = 0; + } + + char namebuf[512]; + namebuf[0] = 0; + if (dbcgs->szModule) + strcpy_s(namebuf, dbcgs->szModule); + strcat_s(namebuf, "/"); + if (dbcgs->szSetting) + strcat_s(namebuf, dbcgs->szSetting); + + TDBTSettingDescriptor desc = {0,0,0,0,0,0,0,0}; + TDBTSetting set = {0,0,0,0}; + desc.cbSize = sizeof(desc); + desc.Entity = (WPARAM)hContact; + desc.pszSettingName = namebuf; + + set.cbSize = sizeof(set); + set.Descriptor = &desc; + + + switch (dbcgs->pValue->type) + { + case DBVT_ASCIIZ: set.Type = DBT_ST_ANSI; break; + case DBVT_BLOB: set.Type = DBT_ST_BLOB; break; + case DBVT_UTF8: set.Type = DBT_ST_UTF8; break; + case DBVT_WCHAR: set.Type = DBT_ST_WCHAR; break; + } + + if (DBSettingRead(reinterpret_cast(&set), 0) == DBT_INVALIDPARAM) + return -1; + + switch (set.Type) + { + case DBT_ST_ANSI: + { + dbcgs->pValue->type = DBVT_ASCIIZ; + dbcgs->pValue->pszVal = set.Value.pAnsi; + dbcgs->pValue->cchVal = set.Value.Length - 1; + } break; + case DBT_ST_UTF8: + { + dbcgs->pValue->type = DBVT_UTF8; + dbcgs->pValue->pszVal = set.Value.pUTF8; + dbcgs->pValue->cchVal = set.Value.Length - 1; + } break; + case DBT_ST_WCHAR: + { + if (dbcgs->pValue->type == DBVT_WCHAR) + { + dbcgs->pValue->pwszVal = set.Value.pWide; + dbcgs->pValue->cchVal = set.Value.Length - 1; + } else { + dbcgs->pValue->type = DBVT_UTF8; + dbcgs->pValue->pszVal = mir_utf8encodeW(set.Value.pWide); + dbcgs->pValue->cchVal = static_cast(strlen(dbcgs->pValue->pszVal)); + mir_free(set.Value.pWide); + } + } break; + case DBT_ST_BLOB: + { + dbcgs->pValue->type = DBVT_BLOB; + dbcgs->pValue->pbVal = set.Value.pBlob; + dbcgs->pValue->cpbVal = set.Value.Length; + } break; + case DBT_ST_BOOL: + { + dbcgs->pValue->type = DBVT_BYTE; + dbcgs->pValue->bVal = (uint8_t)set.Value.Bool; + } break; + case DBT_ST_BYTE: case DBT_ST_CHAR: + { + dbcgs->pValue->type = DBVT_BYTE; + dbcgs->pValue->bVal = set.Value.Byte; + } break; + case DBT_ST_SHORT: case DBT_ST_WORD: + { + dbcgs->pValue->type = DBVT_WORD; + dbcgs->pValue->wVal = set.Value.Word; + } break; + case DBT_ST_INT: case DBT_ST_DWORD: + { + dbcgs->pValue->type = DBVT_DWORD; + dbcgs->pValue->dVal = set.Value.DWord; + } break; + case DBT_ST_INT64: case DBT_ST_QWORD: + case DBT_ST_DOUBLE: case DBT_ST_FLOAT: + { + dbcgs->pValue->type = DBVT_BLOB; + dbcgs->pValue->cpbVal = sizeof(set.Value); + dbcgs->pValue->pbVal = reinterpret_cast(mir_alloc(sizeof(set.Value))); + memcpy(dbcgs->pValue->pbVal, &set.Value, sizeof(set.Value)); + } break; + default: + return -1; + } + + return 0; +} + +STDMETHODIMP_(BOOL) CDataBase::GetContactSettingStatic(HANDLE hContact, DBCONTACTGETSETTING *dbcgs) +{ + char namebuf[512]; + namebuf[0] = 0; + if (dbcgs->szModule) + strcpy_s(namebuf, dbcgs->szModule); + strcat_s(namebuf, "/"); + if (dbcgs->szSetting) + strcat_s(namebuf, dbcgs->szSetting); + + TDBTSettingDescriptor desc = {0,0,0,0,0,0,0,0}; + TDBTSetting set = {0,0,0,0}; + desc.cbSize = sizeof(desc); + desc.Entity = (WPARAM)hContact; + desc.pszSettingName = namebuf; + + set.cbSize = sizeof(set); + set.Descriptor = &desc; + + if (DBSettingRead(reinterpret_cast(&set), 0) == DBT_INVALIDPARAM) + return -1; + + if ((set.Type & DBT_STF_VariableLength) ^ (dbcgs->pValue->type & DBVTF_VARIABLELENGTH)) + { + if (set.Type & DBT_STF_VariableLength) + mir_free(set.Value.pBlob); + return -1; + } + + switch (set.Type) + { + case DBT_ST_ANSI: + { + if (dbcgs->pValue->cchVal < set.Value.Length) + { + memcpy(dbcgs->pValue->pszVal, set.Value.pAnsi, dbcgs->pValue->cchVal); + dbcgs->pValue->pszVal[dbcgs->pValue->cchVal - 1] = 0; + } else { + memcpy(dbcgs->pValue->pszVal, set.Value.pAnsi, set.Value.Length); + } + dbcgs->pValue->type = DBVT_ASCIIZ; + dbcgs->pValue->cchVal = set.Value.Length - 1; + + mir_free(set.Value.pAnsi); + } break; + case DBT_ST_UTF8: + { + set.Value.pUTF8 = mir_utf8decode(set.Value.pUTF8, NULL); + set.Value.Length = static_cast(strlen(set.Value.pUTF8)); + + if (dbcgs->pValue->cchVal < set.Value.Length) + { + memcpy(dbcgs->pValue->pszVal, set.Value.pUTF8, dbcgs->pValue->cchVal); + dbcgs->pValue->pszVal[dbcgs->pValue->cchVal - 1] = 0; + } else { + memcpy(dbcgs->pValue->pszVal, set.Value.pUTF8, set.Value.Length); + } + dbcgs->pValue->type = DBVT_ASCIIZ; + dbcgs->pValue->cchVal = set.Value.Length - 1; + + mir_free(set.Value.pUTF8); + } break; + case DBT_ST_WCHAR: + { + char * tmp = mir_u2a(set.Value.pWide); + WORD l = static_cast(strlen(tmp)); + mir_free(set.Value.pWide); + + if (dbcgs->pValue->cchVal < l + 1) + { + memcpy(dbcgs->pValue->pszVal, tmp, dbcgs->pValue->cchVal); + dbcgs->pValue->pszVal[l] = 0; + } else { + memcpy(dbcgs->pValue->pszVal, tmp, l + 1); + } + dbcgs->pValue->type = DBVT_ASCIIZ; + dbcgs->pValue->cchVal = l; + + mir_free(tmp); + } break; + case DBT_ST_BLOB: + { + if (dbcgs->pValue->cchVal < set.Value.Length) + { + memcpy(dbcgs->pValue->pbVal, set.Value.pBlob, dbcgs->pValue->cchVal); + } else { + memcpy(dbcgs->pValue->pbVal, set.Value.pBlob, set.Value.Length); + } + dbcgs->pValue->type = DBVT_BLOB; + dbcgs->pValue->cchVal = set.Value.Length; + + mir_free(set.Value.pBlob); + } break; + case DBT_ST_BOOL: + { + dbcgs->pValue->type = DBVT_BYTE; + dbcgs->pValue->bVal = set.Value.Bool ? TRUE : FALSE; + } break; + case DBT_ST_BYTE: case DBT_ST_CHAR: + { + dbcgs->pValue->type = DBVT_BYTE; + dbcgs->pValue->bVal = set.Value.Byte; + } break; + case DBT_ST_SHORT: case DBT_ST_WORD: + { + dbcgs->pValue->type = DBVT_WORD; + dbcgs->pValue->wVal = set.Value.Word; + } break; + case DBT_ST_INT: case DBT_ST_DWORD: + { + dbcgs->pValue->type = DBVT_DWORD; + dbcgs->pValue->dVal = set.Value.DWord; + } break; + default: + return -1; + } + + return 0; +} + +STDMETHODIMP_(BOOL) CDataBase::FreeVariant(DBVARIANT *dbv) +{ + if ((dbv->type == DBVT_BLOB) && (dbv->pbVal)) + { + mir_free(dbv->pbVal); + dbv->pbVal = 0; + } else if ((dbv->type & DBVTF_VARIABLELENGTH) && (dbv->pszVal)) + { + mir_free(dbv->pszVal); + dbv->pszVal = NULL; + } + dbv->type = 0; + return 0; +} + +STDMETHODIMP_(BOOL) CDataBase::WriteContactSetting(HANDLE hContact, DBCONTACTWRITESETTING *dbcws) +{ + char namebuf[512]; + namebuf[0] = 0; + if (dbcws->szModule) + strcpy_s(namebuf, dbcws->szModule); + strcat_s(namebuf, "/"); + if (dbcws->szSetting) + strcat_s(namebuf, dbcws->szSetting); + + TDBTSettingDescriptor desc = {0,0,0,0,0,0,0,0}; + TDBTSetting set = {0,0,0,0}; + desc.cbSize = sizeof(desc); + desc.Entity = (WPARAM)hContact; + desc.pszSettingName = namebuf; + + set.cbSize = sizeof(set); + set.Descriptor = &desc; + + switch (dbcws->value.type) + { + case DBVT_ASCIIZ: + { + set.Type = DBT_ST_ANSI; + set.Value.pAnsi = dbcws->value.pszVal; + } break; + case DBVT_UTF8: + { + wchar_t * tmp = mir_utf8decodeW(dbcws->value.pszVal); + if (tmp == 0) + { + if (IsDebuggerPresent()) + { + DebugBreak(); +#ifdef _DEBUG + } else { + LOG(logWARNING, _T("Trying to write malformed UTF8 setting \"%hs\" in module \"%hs\""), dbcws->szSetting, dbcws->szModule); + CLogger::Instance().ShowMessage(); +#endif + } + return -1; + } else { + mir_free(tmp); + } + + set.Type = DBT_ST_UTF8; + set.Value.pUTF8 = dbcws->value.pszVal; + } break; + case DBVT_WCHAR: + { + set.Type = DBT_ST_WCHAR; + set.Value.pWide = dbcws->value.pwszVal; + } break; + case DBVT_BLOB: + { + set.Type = DBT_ST_BLOB; + set.Value.pBlob = dbcws->value.pbVal; + set.Value.Length = dbcws->value.cpbVal; + } break; + case DBVT_BYTE: + { + set.Type = DBT_ST_BYTE; + set.Value.Byte = dbcws->value.bVal; + } break; + case DBVT_WORD: + { + set.Type = DBT_ST_WORD; + set.Value.Word = dbcws->value.wVal; + } break; + case DBVT_DWORD: + { + set.Type = DBT_ST_DWORD; + set.Value.DWord = dbcws->value.dVal; + } break; + default: + { + return -1; + } + } + + if (DBSettingWrite(reinterpret_cast(&set), 0) == DBT_INVALIDPARAM) + return -1; + + if (dbcws->value.type == DBVT_WCHAR) + { + dbcws->value.type = DBVT_UTF8; + wchar_t * tmp = dbcws->value.pwszVal; + dbcws->value.pszVal = mir_utf8encodeW(dbcws->value.pwszVal); + NotifyEventHooks(hSettingChangeEvent, (WPARAM)hContact, (LPARAM)dbcws); + mir_free(dbcws->value.pszVal); + dbcws->value.type = DBVT_WCHAR; + dbcws->value.pwszVal = tmp; + } else { + NotifyEventHooks(hSettingChangeEvent, (WPARAM)hContact, (LPARAM)dbcws); + } + + return 0; +} + +STDMETHODIMP_(BOOL) CDataBase::DeleteContactSetting(HANDLE hContact, DBCONTACTGETSETTING *dbcgs) +{ + char namebuf[512]; + namebuf[0] = 0; + if (dbcgs->szModule) + strcpy_s(namebuf, dbcgs->szModule); + strcat_s(namebuf, "/"); + if (dbcgs->szSetting) + strcat_s(namebuf, dbcgs->szSetting); + + TDBTSettingDescriptor desc = {0,0,0,0,0,0,0,0}; + desc.cbSize = sizeof(desc); + desc.Entity = (WPARAM)hContact; + desc.pszSettingName = namebuf; + + if (DBSettingDelete(reinterpret_cast(&desc), 0) == DBT_INVALIDPARAM) + return -1; + + { + DBCONTACTWRITESETTING tmp = {0,0,0,0}; + tmp.szModule = dbcgs->szModule; + tmp.szSetting = dbcgs->szSetting; + tmp.value.type = 0; + NotifyEventHooks(hSettingChangeEvent, (WPARAM)hContact, (LPARAM)&tmp); + } + + return 0; +} + +STDMETHODIMP_(BOOL) CDataBase::EnumContactSettings(HANDLE hContact, DBCONTACTENUMSETTINGS* pces) +{ + TDBTSettingDescriptor desc = {0,0,0,0,0,0,0,0}; + desc.cbSize = sizeof(desc); + desc.Entity = (WPARAM)hContact; + + char namebuf[512]; + namebuf[0] = 0; + if (pces->szModule) + strcpy_s(namebuf, pces->szModule); + strcat_s(namebuf, "/"); + + TDBTSettingIterFilter filter = {0,0,0,0,0,0,0,0}; + filter.cbSize = sizeof(filter); + filter.Descriptor = &desc; + filter.hEntity = (WPARAM)(WPARAM)hContact; + filter.NameStart = namebuf; + + TDBTSettingIterationHandle hiter = DBSettingIterInit(reinterpret_cast(&filter), 0); + if ((hiter == 0) || (hiter == DBT_INVALIDPARAM)) + return -1; + + int res = 0; + TDBTSettingHandle hset = DBSettingIterNext(hiter, 0); + while (hset != 0) + { + char * p = strchr(desc.pszSettingName, '/'); + if (p) { + ++p; + } else { + p = desc.pszSettingName; + } + + res = pces->pfnEnumProc(p, pces->lParam); + if (res == 0) + { + hset = DBSettingIterNext(hiter, 0); + } else { + hset = 0; + } + } + + DBSettingIterClose(hiter, 0); + + if (desc.pszSettingName) + mir_free(desc.pszSettingName); + + return res; +} + +STDMETHODIMP_(LONG) CDataBase::GetEventCount(HANDLE hContact) +{ + if (hContact == 0) + hContact = (HANDLE)gDataBase->getEntities().getRootEntity(); + + return DBEventGetCount((WPARAM)hContact, 0); +} + +STDMETHODIMP_(HANDLE) CDataBase::AddEvent(HANDLE hContact, DBEVENTINFO *dbei) +{ + if (dbei->cbSize < sizeof(DBEVENTINFO)) + return (HANDLE)-1; + + int tmp = NotifyEventHooks(hEventFilterAddedEvent, (WPARAM)hContact, (LPARAM)dbei); + if (tmp != 0) + return (HANDLE)tmp; + + if (hContact == 0) + hContact = (HANDLE)gDataBase->getEntities().getRootEntity(); + + + TDBTEvent ev = {0,0,0,0,0,0,0}; + ev.cbSize = sizeof(ev); + ev.ModuleName = dbei->szModule; + ev.Timestamp = dbei->timestamp; + ev.Flags = dbei->flags; + if (ev.Flags & DBEF_SENT) + ev.Flags = ev.Flags | DBEF_READ; + ev.EventType = dbei->eventType; + ev.cbBlob = dbei->cbBlob; + ev.pBlob = dbei->pBlob; + + int res = DBEventAdd((WPARAM)hContact, reinterpret_cast(&ev)); + if (res != DBT_INVALIDPARAM) + { + NotifyEventHooks(hEventAddedEvent, (WPARAM)hContact, res); + return (HANDLE)res; + } + return NULL; +} + +STDMETHODIMP_(BOOL) CDataBase::DeleteEvent(HANDLE hContact, HANDLE hDbEvent) +{ + int res = NotifyEventHooks(hEventDeletedEvent, (WPARAM)hContact, (WPARAM)hDbEvent); + + if (hContact == 0) + hContact = (HANDLE)gDataBase->getEntities().getRootEntity(); + + if (res == 0) + return DBEventDelete((WPARAM)hDbEvent, 0); + + return res; +} + +STDMETHODIMP_(LONG) CDataBase::GetBlobSize(HANDLE hDbEvent) +{ + int res = DBEventGetBlobSize((WPARAM)hDbEvent, 0); + if (res == DBT_INVALIDPARAM) + return -1; + + return res; +} + +STDMETHODIMP_(BOOL) CDataBase::GetEvent(HANDLE hDbEvent, DBEVENTINFO *dbei) +{ + if (dbei->cbSize < sizeof(DBEVENTINFO)) + return -1; + + TDBTEvent ev = {0,0,0,0,0,0,0}; + ev.cbSize = sizeof(ev); + ev.cbBlob = 0; + ev.pBlob = NULL; + + int res = DBEventGet((WPARAM)hDbEvent, reinterpret_cast(&ev)); + + dbei->szModule = ev.ModuleName; + dbei->timestamp = ev.Timestamp; + dbei->flags = ev.Flags; + if (dbei->flags & DBEF_SENT) + dbei->flags = dbei->flags & ~DBEF_READ; + dbei->eventType = ev.EventType; + + if (dbei->cbBlob && dbei->pBlob) + { + if (dbei->cbBlob >= ev.cbBlob) + memcpy(dbei->pBlob, ev.pBlob, ev.cbBlob); + else + memcpy(dbei->pBlob, ev.pBlob, dbei->cbBlob); + } + mir_free(ev.pBlob); + dbei->cbBlob = ev.cbBlob; + + if (res == DBT_INVALIDPARAM) + return 1; + + return res; +} + +STDMETHODIMP_(BOOL) CDataBase::MarkEventRead(HANDLE hContact, HANDLE hDbEvent) +{ + int res = DBEventMarkRead((WPARAM)hDbEvent, 0); + if ((res != DBT_INVALIDPARAM) && (res & DBEF_SENT)) + res = res & ~DBEF_READ; + return res; +} + +STDMETHODIMP_(HANDLE) CDataBase::GetEventContact(HANDLE hDbEvent) +{ + TDBTEntityHandle res = DBEventGetEntity((WPARAM)hDbEvent, 0); + if (res == gDataBase->getEntities().getRootEntity()) + res = 0; + + return (HANDLE)res; +} + +STDMETHODIMP_(HANDLE) CDataBase::FindFirstEvent(HANDLE hContact) +{ + if (hContact == 0) + hContact = (HANDLE)gDataBase->getEntities().getRootEntity(); + + return (HANDLE)gDataBase->getEvents().compFirstEvent((WPARAM)hContact); +} + +STDMETHODIMP_(HANDLE) CDataBase::FindFirstUnreadEvent(HANDLE hContact) +{ + if (hContact == 0) + hContact = (HANDLE)gDataBase->getEntities().getRootEntity(); + return (HANDLE)gDataBase->getEvents().compFirstUnreadEvent((WPARAM)hContact); +} + +STDMETHODIMP_(HANDLE) CDataBase::FindLastEvent(HANDLE hContact) +{ + if (hContact == 0) + hContact = (HANDLE)gDataBase->getEntities().getRootEntity(); + return (HANDLE)gDataBase->getEvents().compLastEvent((WPARAM)hContact); +} + +STDMETHODIMP_(HANDLE) CDataBase::FindNextEvent(HANDLE hDbEvent) +{ + return (HANDLE)gDataBase->getEvents().compNextEvent((WPARAM)hDbEvent); +} + +STDMETHODIMP_(HANDLE) CDataBase::FindPrevEvent(HANDLE hDbEvent) +{ + return (HANDLE)gDataBase->getEvents().compPrevEvent((WPARAM)hDbEvent); +} + +STDMETHODIMP_(BOOL) CDataBase::EnumModuleNames(DBMODULEENUMPROC pCallback, void *pParam) +{ + if (!pCallback) + return -1; + + return gDataBase->getSettings().CompEnumModules(pCallback, (WPARAM)pParam); +} + +STDMETHODIMP_(BOOL) CDataBase::SetSettingResident(BOOL bIsResident, const char *pszSettingName) +{ + return FALSE; +} + +STDMETHODIMP_(BOOL) CDataBase::EnumResidentSettings(DBMODULEENUMPROC pFunc, void *pParam) +{ + return FALSE; +} + +STDMETHODIMP_(void) CDataBase::SetCacheSafetyMode(BOOL) {} + +bool CompatibilityRegister() +{ + hEventDeletedEvent = CreateHookableEvent(ME_DB_EVENT_DELETED); + hEventAddedEvent = CreateHookableEvent(ME_DB_EVENT_ADDED); + hEventFilterAddedEvent = CreateHookableEvent(ME_DB_EVENT_FILTER_ADD); + hSettingChangeEvent = CreateHookableEvent(ME_DB_CONTACT_SETTINGCHANGED); + hContactDeletedEvent = CreateHookableEvent(ME_DB_CONTACT_DELETED); + hContactAddedEvent = CreateHookableEvent(ME_DB_CONTACT_ADDED); + return true; +} diff --git a/plugins/Dbx_tree/src/Compatibility.h b/plugins/Dbx_tree/src/Compatibility.h new file mode 100644 index 0000000000..a23fa9284b --- /dev/null +++ b/plugins/Dbx_tree/src/Compatibility.h @@ -0,0 +1,30 @@ +/* + +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. + +*/ + +#pragma once + +#include "Interface.h" +#include "DataBase.h" +#include "Services.h" + +bool CompatibilityRegister(); + diff --git a/plugins/Dbx_tree/src/DataBase.cpp b/plugins/Dbx_tree/src/DataBase.cpp new file mode 100644 index 0000000000..50fe494b3c --- /dev/null +++ b/plugins/Dbx_tree/src/DataBase.cpp @@ -0,0 +1,371 @@ +/* + +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 "DataBase.h" +#include "newpluginapi.h" +#ifndef _MSC_VER +#include "savestrings_gcc.h" +#endif +#include "Logger.h" + +CDataBase *gDataBase = NULL; + +CDataBase::CDataBase(const TCHAR *FileName) +{ + InitDbInstance(this); + + size_t len = _tcslen(FileName); + m_FileName[0] = new TCHAR[len + 1]; + _tcsncpy_s(m_FileName[0], len + 1, FileName, len); + m_FileName[0][len] = 0; + + TCHAR * tmp = _tcsrchr(m_FileName[0], '.'); + if (tmp) + { + m_FileName[1] = new TCHAR[len + 1]; + _tcsncpy_s(m_FileName[1], len + 1, m_FileName[0], tmp - m_FileName[0]); + _tcscat_s(m_FileName[1], len + 1, _T(".pri")); + } else { + m_FileName[1] = new TCHAR[len + 5]; + _tcscpy_s(m_FileName[1], len + 5, m_FileName[0]); + _tcscat_s(m_FileName[1], len + 5, _T(".pri")); + } + + m_Opened = false; + + for (int i = 0; i < DBFileMax; ++i) + { + m_BlockManager[i] = NULL; + m_FileAccess[i] = NULL; + m_EncryptionManager[i] = NULL; + m_HeaderBlock[i] = 0; + } + + m_Entities = NULL; + m_Settings = NULL; + m_Events = NULL; + +} +CDataBase::~CDataBase() +{ + if (m_Events) delete m_Events; + if (m_Settings) delete m_Settings; + if (m_Entities) delete m_Entities; + + m_Entities = NULL; + m_Settings = NULL; + m_Events = NULL; + + for (int i = DBFileMax - 1; i >= 0; --i) + { + if (m_BlockManager[i]) delete m_BlockManager[i]; + if (m_FileAccess[i]) delete m_FileAccess[i]; + if (m_EncryptionManager[i]) delete m_EncryptionManager[i]; + + m_BlockManager[i] = NULL; + m_FileAccess[i] = NULL; + m_EncryptionManager[i] = NULL; + + delete [] (m_FileName[i]); + } + DestroyDbInstance(this); +} + +int CDataBase::CreateDB() +{ + /// TODO: create and show wizard + if (!CreateNewFile(DBFileSetting) || + !CreateNewFile(DBFilePrivate)) + return EMKPRF_CREATEFAILED; + + return 0; +} + + +int CDataBase::CheckFile(TDBFileType Index) +{ + TGenericFileHeader h; + memset(&h, 0, sizeof(h)); + DWORD r = 0; + HANDLE htmp = CreateFile(m_FileName[Index], GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_FLAG_RANDOM_ACCESS, NULL); + if (htmp != INVALID_HANDLE_VALUE) + { + SetFilePointer(htmp, 0, NULL, FILE_BEGIN); + if (ReadFile(htmp, &h, sizeof(h), &r, NULL)) + { + if (0 != memcmp(h.Gen.Signature, cFileSignature[Index], sizeof(cFileSignature[Index]))) + { + CloseHandle(htmp); + return EGROKPRF_UNKHEADER; + } + + if (cDBVersion < h.Gen.Version) + { + CloseHandle(htmp); + return EGROKPRF_VERNEWER; + } + + CloseHandle(htmp); + return EGROKPRF_NOERROR; + } + CloseHandle(htmp); + } + + return EGROKPRF_CANTREAD; +} + +int CDataBase::CheckDB() +{ + int res = CheckFile(DBFileSetting); + + if (res != EGROKPRF_NOERROR) + return res; + + if (PrivateFileExists()) + res = CheckFile(DBFilePrivate); + + return res; +} + +int CDataBase::LoadFile(TDBFileType Index) +{ + TGenericFileHeader h; + m_EncryptionManager[Index] = new CEncryptionManager; + + if (CMappedMemory::InitMMAP()) + m_FileAccess[Index] = new CMappedMemory(m_FileName[Index]); + else + m_FileAccess[Index] = new CDirectAccess(m_FileName[Index]); + + m_FileAccess[Index]->Read(&h, 0, sizeof(h)); + m_EncryptionManager[Index]->InitEncryption(h.Gen.FileEncryption); + + m_FileAccess[Index]->Size(h.Gen.FileSize); + m_FileAccess[Index]->sigFileSizeChanged().connect(this, &CDataBase::onFileSizeChanged); + + m_BlockManager[Index] = new CBlockManager(*m_FileAccess[Index], *m_EncryptionManager[Index]); + + CBlockManager::WriteTransaction trans(*m_BlockManager[Index]); // don't fire size event until header is loaded + + m_HeaderBlock[Index] = m_BlockManager[Index]->ScanFile(sizeof(h), cHeaderBlockSignature, h.Gen.FileSize); + + if (m_HeaderBlock[Index] == 0) + { + LOG(logCRITICAL, _T("Header Block not found! File damaged: \"%s\""), m_FileName[Index]); + return -1; + } + + uint32_t size = sizeof(h); + uint32_t sig = -1; + m_Header[Index] = m_BlockManager[Index]->ReadBlock(0, size, sig); + + sig = cHeaderBlockSignature; + TGenericFileHeader * buf = m_BlockManager[Index]->ReadBlock(m_HeaderBlock[Index], size, sig); + if (!buf) + { + LOG(logCRITICAL, _T("Header Block cannot be read! File damaged: \"%s\""), m_FileName[Index]); + return -1; + } + + buf->Gen.Obscure = 0; + + if (memcmp(m_Header[Index], buf, size)) + { + LOG(logCRITICAL, _T("Header Block in \"%s\" damaged!"), m_FileName[Index]); + return -1; + } + + return 0; +} + +int CDataBase::OpenDB() +{ + if (!PrivateFileExists()) + { + // TODO WIZARD + if (!CreateNewFile(DBFilePrivate)) + return -1; + } + + int res = LoadFile(DBFileSetting); + if ((res != 0) && (CLogger::logERROR <= CLogger::Instance().ShowMessage())) + { + return res; + } + + res = LoadFile(DBFilePrivate); + + if ((res != 0) && (CLogger::logERROR <= CLogger::Instance().ShowMessage())) + { + return res; + } + if (CLogger::logERROR <= CLogger::Instance().ShowMessage()) + return -1; + + m_Entities = new CEntities(*m_BlockManager[DBFilePrivate], + m_Header[DBFilePrivate]->Pri.RootEntity, + m_Header[DBFilePrivate]->Pri.Entities, + m_Header[DBFilePrivate]->Pri.Virtuals); + + m_Entities->sigRootChanged().connect(this, &CDataBase::onEntitiesRootChanged); + m_Entities->sigVirtualRootChanged().connect(this, &CDataBase::onVirtualsRootChanged); + + if (m_Entities->getRootEntity() != m_Header[DBFilePrivate]->Pri.RootEntity) + { + m_Header[DBFilePrivate]->Pri.RootEntity = m_Entities->getRootEntity(); + ReWriteHeader(DBFilePrivate); + } + + m_Settings = new CSettings(*m_BlockManager[DBFileSetting], + *m_BlockManager[DBFilePrivate], + m_Header[DBFileSetting]->Set.Settings, + *m_Entities); + + m_Settings->sigRootChanged().connect(this, &CDataBase::onSettingsRootChanged); + + m_Events = new CEvents(*m_BlockManager[DBFilePrivate], + *m_EncryptionManager[DBFilePrivate], + *m_Entities, + *m_Settings); + + return 0; +} + +bool CDataBase::PrivateFileExists() +{ + HANDLE htmp = CreateFile(m_FileName[DBFilePrivate], GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_FLAG_RANDOM_ACCESS, NULL); + if (htmp != INVALID_HANDLE_VALUE) + { + CloseHandle(htmp); + return true; + } + + return false; +} + + +bool CDataBase::CreateNewFile(TDBFileType File) +{ + CEncryptionManager enc; + CDirectAccess fa(m_FileName[File]); + fa.Size(sizeof(TGenericFileHeader)); + CBlockManager bm(fa, enc); + bm.ScanFile(sizeof(TGenericFileHeader), 0, sizeof(TGenericFileHeader)); + + CBlockManager::WriteTransaction trans(bm); + + uint32_t block; + TGenericFileHeader * buf = bm.CreateBlock(block, cHeaderBlockSignature); + uint32_t size = 0; + uint32_t sig = -1; + TGenericFileHeader * h = bm.ReadBlock(0, size, sig); + + memset(h, 0, sizeof(TGenericFileHeader)); + memcpy(&h->Gen.Signature, &cFileSignature[File], sizeof(h->Gen.Signature)); + h->Gen.Version = cDBVersion; + h->Gen.FileSize = fa.Size(); + + memcpy(buf, h, sizeof(TGenericFileHeader)); + bm.UpdateBlock(block, 0); + bm.UpdateBlock(0, -1); + + return true; +} + +inline void CDataBase::ReWriteHeader(TDBFileType Index) +{ + m_BlockManager[Index]->UpdateBlock(0, -1); + uint32_t size = 0, sig = 0; + TGenericFileHeader * h = m_BlockManager[Index]->ReadBlock(m_HeaderBlock[Index], size, sig); + + *h = *m_Header[Index]; + h->Gen.Obscure = GetTickCount(); + m_BlockManager[Index]->UpdateBlock(m_HeaderBlock[Index], 0); +} + + +void CDataBase::onSettingsRootChanged(CSettings* Settings, CSettingsTree::TNodeRef NewRoot) +{ + m_Header[DBFileSetting]->Set.Settings = NewRoot; + ReWriteHeader(DBFileSetting); +} +void CDataBase::onVirtualsRootChanged(void* Virtuals, CVirtuals::TNodeRef NewRoot) +{ + m_Header[DBFilePrivate]->Pri.Virtuals = NewRoot; + ReWriteHeader(DBFilePrivate); +} +void CDataBase::onEntitiesRootChanged(void* Entities, CEntities::TNodeRef NewRoot) +{ + m_Header[DBFilePrivate]->Pri.Entities = NewRoot; + ReWriteHeader(DBFilePrivate); +} +void CDataBase::onFileSizeChanged(CFileAccess * File, uint32_t Size) +{ + if (File == m_FileAccess[DBFileSetting]) + { + m_Header[DBFileSetting]->Gen.FileSize = Size; + ReWriteHeader(DBFileSetting); + } else { + m_Header[DBFilePrivate]->Gen.FileSize = Size; + ReWriteHeader(DBFilePrivate); + } +} + +int CDataBase::getProfileName(int BufferSize, char * Buffer) +{ + TCHAR * slash = _tcsrchr(m_FileName[DBFileSetting], '\\'); + if (slash) + slash++; + else + slash = m_FileName[DBFileSetting]; + + int l = static_cast(_tcslen(slash)); + if (BufferSize < l + 1) + return -1; + + char * tmp = mir_t2a(slash); + strcpy_s(Buffer, BufferSize, tmp); + mir_free(tmp); + + return 0; +} +int CDataBase::getProfilePath(int BufferSize, char * Buffer) +{ + TCHAR * slash = _tcsrchr(m_FileName[DBFileSetting], '\\'); + if (!slash) + return -1; + + int l = slash - m_FileName[DBFileSetting]; + + if (BufferSize < l + 1) + { + return -1; + } + + *slash = 0; + char * tmp = mir_t2a(m_FileName[DBFileSetting]); + strcpy_s(Buffer, BufferSize, tmp); + mir_free(tmp); + *slash = '\\'; + + return 0; +} diff --git a/plugins/Dbx_tree/src/DataBase.h b/plugins/Dbx_tree/src/DataBase.h new file mode 100644 index 0000000000..124fee4f9d --- /dev/null +++ b/plugins/Dbx_tree/src/DataBase.h @@ -0,0 +1,189 @@ +/* + +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. + +*/ + +#pragma once + +#ifndef _MSC_VER +#include +#else +#include "stdint.h" +#endif +#include "MREWSync.h" + +#include "Events.h" +#include "Settings.h" +#include "Entities.h" + +#include "FileAccess.h" +#include "MappedMemory.h" +#include "DirectAccess.h" +#include "Blockmanager.h" + +#include "sigslot.h" + +#include "EncryptionManager.h" + +typedef enum TDBFileType { + DBFileSetting = 0, + DBFilePrivate = 1, + DBFileMax = 2 +} TDBFileType; + +static const uint8_t cFileSignature[DBFileMax][20] = {"Miranda IM Settings", "Miranda IM DataTree"}; +static const uint32_t cDBVersion = 0x00000001; + +static const uint32_t cHeaderBlockSignature = 0x7265491E; + +#pragma pack(push, 1) // push current alignment to stack, set alignment to 1 byte boundary + +typedef struct TSettingsHeader { + uint8_t Signature[20]; /// signature must be cSettingsHeader + uint32_t Version; /// internal DB version cDataBaseVersion + uint32_t Obscure; + TFileEncryption FileEncryption; /// Encryption Method + uint32_t FileStructureBlock; /// Offset of CBlockManager master block + uint32_t FileSize; /// Offset to the last used byte + 1 + uint32_t Settings; /// Offset to the SettingsBTree RootNode + uint8_t Reserved[256 - sizeof(TFileEncryption) - 20 - 5*sizeof(uint32_t)]; /// reserved storage +} TSettingsHeader; + +typedef struct TPrivateHeader { + uint8_t Signature[20]; /// signature must be CDataHeader + uint32_t Version; /// internal DB version cDataBaseVersion + uint32_t Obscure; + TFileEncryption FileEncryption; /// Encryption Method + uint32_t FileStructureBlock; /// Offset of CBlockManager master block + uint32_t FileSize; /// Offset to the last used byte + 1 + uint32_t RootEntity; /// Offset to the Root CList Entity + uint32_t Entities; /// Offset to the EntityBTree RootNode + uint32_t Virtuals; /// Offset to the VirtualsBTree RootNode + uint8_t Reserved[256 - sizeof(TFileEncryption) - 20 - 7*sizeof(uint32_t)]; /// reserved storage +} TPrivateHeader; + + +typedef union TGenericFileHeader { + struct { + uint8_t Signature[20]; /// signature must be cSettingsHeader + uint32_t Version; /// internal DB version cDataBaseVersion + uint32_t Obscure; + TFileEncryption FileEncryption; /// Encryption Method + uint32_t FileStructureBlock; /// Offset of CBlockManager master block + uint32_t FileSize; /// Offset to the last used byte + 1 + uint8_t Reserved[256 - sizeof(TFileEncryption) - 20 - 4*sizeof(uint32_t)]; /// reserved storage + } Gen; + TSettingsHeader Set; + TPrivateHeader Pri; +} TGenericFileHeader; + +#pragma pack(pop) + +class CDataBase : public sigslot::has_slots<>, public MIDatabase +{ +private: + TCHAR* m_FileName[DBFileMax]; + bool m_Opened; + + CBlockManager *m_BlockManager[DBFileMax]; + CFileAccess *m_FileAccess[DBFileMax]; + TGenericFileHeader * m_Header[DBFileMax]; + CEncryptionManager *m_EncryptionManager[DBFileMax]; + + uint32_t m_HeaderBlock[DBFileMax]; + + void onSettingsRootChanged(CSettings* Settings, CSettingsTree::TNodeRef NewRoot); + void onVirtualsRootChanged(void* Virtuals, CVirtuals::TNodeRef NewRoot); + void onEntitiesRootChanged(void* Entities, CEntities::TNodeRef NewRoot); + void onFileSizeChanged(CFileAccess * File, uint32_t Size); + + bool PrivateFileExists(); + bool CreateNewFile(TDBFileType File); + + int CheckFile(TDBFileType Index); + int LoadFile(TDBFileType Index); +protected: + CEntities *m_Entities; + CSettings *m_Settings; + CEvents *m_Events; + + void ReWriteHeader(TDBFileType Index); + +public: + CDataBase(const TCHAR* FileName); + virtual ~CDataBase(); + + int CreateDB(); + int CheckDB(); + int OpenDB(); + + CEntities & getEntities() + { + return *m_Entities; + } + CSettings & getSettings() + { + return *m_Settings; + } + CEvents & getEvents() + { + return *m_Events; + } + + int getProfileName(int BufferSize, char * Buffer); + int getProfilePath(int BufferSize, char * Buffer); + +protected: // to be compatible with the standard Miranda databases + STDMETHODIMP_(void) SetCacheSafetyMode(BOOL); + + STDMETHODIMP_(LONG) GetContactCount(void); + STDMETHODIMP_(HANDLE) FindFirstContact(const char* szProto = NULL); + STDMETHODIMP_(HANDLE) FindNextContact(HANDLE hContact, const char* szProto = NULL); + STDMETHODIMP_(LONG) DeleteContact(HANDLE hContact); + STDMETHODIMP_(HANDLE) AddContact(void); + STDMETHODIMP_(BOOL) IsDbContact(HANDLE hContact); + + STDMETHODIMP_(LONG) GetEventCount(HANDLE hContact); + STDMETHODIMP_(HANDLE) AddEvent(HANDLE hContact, DBEVENTINFO *dbe); + STDMETHODIMP_(BOOL) DeleteEvent(HANDLE hContact, HANDLE hDbEvent); + STDMETHODIMP_(LONG) GetBlobSize(HANDLE hDbEvent); + STDMETHODIMP_(BOOL) GetEvent(HANDLE hDbEvent, DBEVENTINFO *dbe); + STDMETHODIMP_(BOOL) MarkEventRead(HANDLE hContact, HANDLE hDbEvent); + STDMETHODIMP_(HANDLE) GetEventContact(HANDLE hDbEvent); + STDMETHODIMP_(HANDLE) FindFirstEvent(HANDLE hContact); + STDMETHODIMP_(HANDLE) FindFirstUnreadEvent(HANDLE hContact); + STDMETHODIMP_(HANDLE) FindLastEvent(HANDLE hContact); + STDMETHODIMP_(HANDLE) FindNextEvent(HANDLE hDbEvent); + STDMETHODIMP_(HANDLE) FindPrevEvent(HANDLE hDbEvent); + + STDMETHODIMP_(BOOL) EnumModuleNames(DBMODULEENUMPROC pFunc, void *pParam); + + STDMETHODIMP_(BOOL) GetContactSetting(HANDLE hContact, DBCONTACTGETSETTING *dbcgs); + STDMETHODIMP_(BOOL) GetContactSettingStr(HANDLE hContact, DBCONTACTGETSETTING *dbcgs); + STDMETHODIMP_(BOOL) GetContactSettingStatic(HANDLE hContact, DBCONTACTGETSETTING *dbcgs); + STDMETHODIMP_(BOOL) FreeVariant(DBVARIANT *dbv); + STDMETHODIMP_(BOOL) WriteContactSetting(HANDLE hContact, DBCONTACTWRITESETTING *dbcws); + STDMETHODIMP_(BOOL) DeleteContactSetting(HANDLE hContact, DBCONTACTGETSETTING *dbcgs); + STDMETHODIMP_(BOOL) EnumContactSettings(HANDLE hContact, DBCONTACTENUMSETTINGS* dbces); + STDMETHODIMP_(BOOL) SetSettingResident(BOOL bIsResident, const char *pszSettingName); + STDMETHODIMP_(BOOL) EnumResidentSettings(DBMODULEENUMPROC pFunc, void *pParam); +}; + +extern CDataBase *gDataBase; diff --git a/plugins/Dbx_tree/src/DatabaseLink.cpp b/plugins/Dbx_tree/src/DatabaseLink.cpp new file mode 100644 index 0000000000..cc944cc305 --- /dev/null +++ b/plugins/Dbx_tree/src/DatabaseLink.cpp @@ -0,0 +1,96 @@ +/* + +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 "DatabaseLink.h" +#ifndef _MSC_VER +#include "savestrings_gcc.h" +#endif + + +/* + profile: pointer to a string which contains full path + name + Affect: The database plugin should create the profile, the filepath will not exist at + the time of this call, profile will be C:\..\.dat + Note: Do not prompt the user in anyway about this operation. + Note: Do not initialise internal data structures at this point! + Returns: 0 on success, non zero on failure - error contains extended error information, see EMKPRF_* +*/ + +static int makeDatabase(const TCHAR *profile) +{ + std::auto_ptr db( new CDataBase(profile)); + return db->CreateDB(); +} + +/* + profile: [in] a null terminated string to file path of selected profile + error: [in/out] pointer to an int to set with error if any + Affect: Ask the database plugin if it supports the given profile, if it does it will + return 0, if it doesnt return 1, with the error set in error -- EGROKPRF_* can be valid error + condition, most common error would be [EGROKPRF_UNKHEADER] + Note: Just because 1 is returned, doesnt mean the profile is not supported, the profile might be damaged + etc. + Returns: 0 on success, non zero on failure +*/ +static int grokHeader(const TCHAR *profile) +{ + std::auto_ptr db( new CDataBase(profile)); + return db->CheckDB(); +} + +/* +Affect: Tell the database to create all services/hooks that a 3.xx legecy database might support into link, + which is a PLUGINLINK structure +Returns: 0 on success, nonzero on failure +*/ + +static MIDatabase* LoadDatabase(const TCHAR *profile) +{ + gDataBase = new CDataBase(profile); + gDataBase->OpenDB(); + return gDataBase; +} + +/* +Affect: The database plugin should shutdown, unloading things from the core and freeing internal structures +Returns: 0 on success, nonzero on failure +Note: Unload() might be called even if Load(void) was never called, wasLoaded is set to 1 if Load(void) was ever called. +*/ + +static int UnloadDatabase(MIDatabase* db) +{ + if (gDataBase == db) + gDataBase = NULL; + delete (CDataBase*)db; + return 0; +} + +DATABASELINK gDBLink = { + sizeof(DATABASELINK), + gInternalName, + _T(gInternalNameLong), + makeDatabase, + grokHeader, + LoadDatabase, + UnloadDatabase, + NULL // does not support file checking +}; diff --git a/plugins/Dbx_tree/src/DatabaseLink.h b/plugins/Dbx_tree/src/DatabaseLink.h new file mode 100644 index 0000000000..c0c20b7fa0 --- /dev/null +++ b/plugins/Dbx_tree/src/DatabaseLink.h @@ -0,0 +1,28 @@ +/* + +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. + +*/ + +#pragma once +#include +#include "Interface.h" +#include "Database.h" +#include "Services.h" +#include "Compatibility.h" \ No newline at end of file diff --git a/plugins/Dbx_tree/src/DirectAccess.cpp b/plugins/Dbx_tree/src/DirectAccess.cpp new file mode 100644 index 0000000000..33785af7c4 --- /dev/null +++ b/plugins/Dbx_tree/src/DirectAccess.cpp @@ -0,0 +1,118 @@ +/* + +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 "DirectAccess.h" +#include "Logger.h" + +CDirectAccess::CDirectAccess(const TCHAR* FileName) +: CFileAccess(FileName) +{ + m_File = CreateFile(FileName, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS, 0); + CHECKSYS(m_File != INVALID_HANDLE_VALUE, + logCRITICAL, _T("CreateFile failed")); + + m_MinAllocGranularity = 0x00001000; // 4kb to avoid heavy fragmentation + m_AllocGranularity = 0x00008000; // 32kb + m_MaxAllocGranularity = 0x00100000; // 1mb for fast increasing + + uint32_t size = GetFileSize(m_File, NULL); + size = (size + m_AllocGranularity - 1) & ~(m_AllocGranularity - 1); + + if (size == 0) + size = m_AllocGranularity; + + m_AllocSize = size; + + InitJournal(); +} + +CDirectAccess::~CDirectAccess() +{ + if (m_File) + { + if (INVALID_SET_FILE_POINTER != SetFilePointer(m_File, m_Size, NULL, FILE_BEGIN)) + SetEndOfFile(m_File); + + CloseHandle(m_File); + } +} + +uint32_t CDirectAccess::_Read(void* Buf, uint32_t Source, uint32_t Size) +{ + DWORD read = 0; + + CHECKSYS(INVALID_SET_FILE_POINTER != SetFilePointer(m_File, Source, NULL, FILE_BEGIN), + logERROR, _T("SetFilePointer failed")); + + CHECKSYS(ReadFile(m_File, Buf, Size, &read, NULL), + logERROR, _T("ReadFile failed")); + + return read; +} +uint32_t CDirectAccess::_Write(void* Buf, uint32_t Dest, uint32_t Size) +{ + DWORD written = 0; + + CHECKSYS(INVALID_SET_FILE_POINTER != SetFilePointer(m_File, Dest, NULL, FILE_BEGIN), + logERROR, _T("SetFilePointer failed")); + + CHECKSYS(WriteFile(m_File, Buf, Size, &written, NULL), + logERROR, _T("WriteFile failed")); + + return written; +} + +uint32_t CDirectAccess::_SetSize(uint32_t Size) +{ + CHECKSYS(INVALID_SET_FILE_POINTER != SetFilePointer(m_File, Size, NULL, FILE_BEGIN), + logERROR, _T("SetFilePointer failed")); + + CHECKSYS(SetEndOfFile(m_File), + logERROR, _T("SetEndOfFile failed")); + + return Size; +} + +void CDirectAccess::_Invalidate(uint32_t Dest, uint32_t Size) +{ + DWORD written; + uint8_t buf[4096]; + memset(buf, 0, sizeof(buf)); + + CHECKSYS(INVALID_SET_FILE_POINTER != SetFilePointer(m_File, Dest, NULL, FILE_BEGIN), + logERROR, _T("SetFilePointer failed")); + + while (Size > sizeof(buf)) + { + Size -= sizeof(buf); + CHECKSYS(WriteFile(m_File, buf, sizeof(buf), &written, NULL), + logERROR, _T("WriteFile failed")); + } + CHECKSYS(WriteFile(m_File, buf, Size, &written, NULL), + logERROR, _T("WriteFile failed")); +} + +void CDirectAccess::_Flush() +{ + CHECKSYS(FlushFileBuffers(m_File), + logERROR, _T("FlushFileBuffers failed")); +} diff --git a/plugins/Dbx_tree/src/DirectAccess.h b/plugins/Dbx_tree/src/DirectAccess.h new file mode 100644 index 0000000000..cc4241c235 --- /dev/null +++ b/plugins/Dbx_tree/src/DirectAccess.h @@ -0,0 +1,43 @@ +/* + +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. + +*/ + +#pragma once + +#include +#include "FileAccess.h" + +class CDirectAccess : public CFileAccess +{ +private: + + HANDLE m_File; +protected: + uint32_t _Read(void* Buf, uint32_t Source, uint32_t Size); + uint32_t _Write(void* Buf, uint32_t Dest, uint32_t Size); + void _Invalidate(uint32_t Dest, uint32_t Size); + uint32_t _SetSize(uint32_t Size); + void _Flush(); +public: + CDirectAccess(const TCHAR* FileName); + virtual ~CDirectAccess(); + +}; diff --git a/plugins/Dbx_tree/src/EncryptionManager.cpp b/plugins/Dbx_tree/src/EncryptionManager.cpp new file mode 100644 index 0000000000..7afdcb248f --- /dev/null +++ b/plugins/Dbx_tree/src/EncryptionManager.cpp @@ -0,0 +1,241 @@ +/* + +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 "EncryptionManager.h" +#include + +uint32_t CEncryptionManager::CipherListRefCount = 0; +CEncryptionManager::TCipherList* CEncryptionManager::CipherList = NULL; + +static const uint32_t cFileBlockMask = 0xfffff000; + +void CEncryptionManager::LoadCipherList() +{ + if (CipherList) + return; + + CipherList = new TCipherList; + CipherListRefCount++; + + WIN32_FIND_DATA search; + TCHAR path[MAX_PATH * 8]; + GetModuleFileName(NULL, path, sizeof(path)); + TCHAR * file = _tcsrchr(path, '\\'); + if (!file) + file = path; + + _tcscpy_s(file, sizeof(path) / sizeof(path[0]) - (file - path), _T("\\plugins\\encryption\\*.dll")); + file += 20; + + HANDLE hfinder = FindFirstFile(path, &search); + if (hfinder != INVALID_HANDLE_VALUE) + { + TCipherItem item; + TCipherInfo* (__cdecl *CipherInfoProc)(void *); + do { + _tcscpy_s(file, sizeof(path) / sizeof(path[0]) - (file - path), search.cFileName); + HMODULE hmod = LoadLibrary(path); + if (hmod) + { + CipherInfoProc = (TCipherInfo*(__cdecl*)(void*)) GetProcAddress(hmod, "CipherInfo"); + if (CipherInfoProc) + { + TCipherInfo* info = CipherInfoProc(NULL); + if (info && (info->cbSize == sizeof(TCipherInfo)) && (CipherList->find(info->ID) == CipherList->end())) + { + item.ID = info->ID; + item.Name = _wcsdup(info->Name); + item.Description = _wcsdup(info->Description); + item.FilePath = _tcsdup(path); + item.FileName = item.FilePath + (file - path); + + CipherList->insert(std::make_pair(item.ID, item)); + } + } + + FreeLibrary(hmod); + + } + } while (FindNextFile(hfinder, &search)); + + FindClose(hfinder); + } +} + +CEncryptionManager::CEncryptionManager() +{ + m_Ciphers[CURRENT].Cipher = NULL; + m_Ciphers[OLD].Cipher = NULL; + m_Changing = false; + m_ChangingProcess = 0; + + LoadCipherList(); +} +CEncryptionManager::~CEncryptionManager() +{ + if (m_Ciphers[CURRENT].Cipher) + delete m_Ciphers[CURRENT].Cipher; + m_Ciphers[CURRENT].Cipher = NULL; + if (m_Ciphers[OLD].Cipher) + delete m_Ciphers[OLD].Cipher; + m_Ciphers[OLD].Cipher = NULL; + + CipherListRefCount--; + if (!CipherListRefCount) + { + TCipherList::iterator i = CipherList->begin(); + while (i != CipherList->end()) + { + free(i->second.Description); + free(i->second.Name); + free(i->second.FilePath); + // do not free Filename... it's a substring of FilePath + ++i; + } + + delete CipherList; + CipherList = NULL; + } +} + +bool CEncryptionManager::InitEncryption(TFileEncryption & Enc) +{ + if (Enc.ConversionProcess) + { + m_Changing = true; + m_ChangingProcess = Enc.ConversionProcess; + } + + for (int c = (int)CURRENT; c < (int)COUNT; c++) + { + TCipherList::iterator i = CipherList->find(Enc.CipherID); + if (i != CipherList->end()) + { + m_Ciphers[c].CipherDLL = LoadLibrary(i->second.FilePath); + if (m_Ciphers[c].CipherDLL) + { + TCipherInfo* (__cdecl *cipherinfoproc)(void *); + cipherinfoproc = (TCipherInfo*(__cdecl*)(void*)) GetProcAddress(m_Ciphers[c].CipherDLL, "CipherInfo"); + if (cipherinfoproc) + { + TCipherInfo* info = cipherinfoproc(NULL); + if (info && (info->cbSize == sizeof(TCipherInfo))) + m_Ciphers[c].Cipher = new CCipher(info->Create()); + + } + + if (!m_Ciphers[c].Cipher) + { + FreeLibrary(m_Ciphers[c].CipherDLL); + m_Ciphers[c].CipherDLL = NULL; + } + } + } + } + + return true; +} + +bool CEncryptionManager::AlignData(uint32_t ID, uint32_t & Start, uint32_t & End) +{ + if (m_Ciphers[CURRENT].Cipher && (!m_Changing || (ID < m_ChangingProcess))) + { + if (m_Ciphers[CURRENT].Cipher->IsStreamCipher()) + { + Start = 0; + End = End - End % m_Ciphers[CURRENT].Cipher->BlockSizeBytes() + m_Ciphers[CURRENT].Cipher->BlockSizeBytes(); + } else { + Start = Start - Start % m_Ciphers[CURRENT].Cipher->BlockSizeBytes(); + if (End % m_Ciphers[CURRENT].Cipher->BlockSizeBytes()) + End = End - End % m_Ciphers[CURRENT].Cipher->BlockSizeBytes() + m_Ciphers[CURRENT].Cipher->BlockSizeBytes(); + } + + return true; + } else if (m_Ciphers[OLD].Cipher && m_Changing && (ID >= m_ChangingProcess)) + { + if (m_Ciphers[OLD].Cipher->IsStreamCipher()) + { + Start = 0; + End = End - End % m_Ciphers[OLD].Cipher->BlockSizeBytes() + m_Ciphers[OLD].Cipher->BlockSizeBytes(); + } else { + Start = Start - Start % m_Ciphers[OLD].Cipher->BlockSizeBytes(); + if (End % m_Ciphers[OLD].Cipher->BlockSizeBytes()) + End = End - End % m_Ciphers[OLD].Cipher->BlockSizeBytes() + m_Ciphers[OLD].Cipher->BlockSizeBytes(); + } + + return true; + } + + return false; +} +uint32_t CEncryptionManager::AlignSize(uint32_t ID, uint32_t Size) +{ + if (m_Ciphers[CURRENT].Cipher && (!m_Changing || (ID < m_ChangingProcess))) + { + if (Size % m_Ciphers[CURRENT].Cipher->BlockSizeBytes()) + return Size - Size % m_Ciphers[CURRENT].Cipher->BlockSizeBytes() + m_Ciphers[CURRENT].Cipher->BlockSizeBytes(); + + } else if (m_Ciphers[OLD].Cipher && m_Changing && (ID >= m_ChangingProcess)) + { + if (Size % m_Ciphers[OLD].Cipher->BlockSizeBytes()) + return Size - Size % m_Ciphers[OLD].Cipher->BlockSizeBytes() + m_Ciphers[OLD].Cipher->BlockSizeBytes(); + + } + + return Size; +} + +bool CEncryptionManager::IsEncrypted(uint32_t ID) +{ + return (m_Ciphers[CURRENT].Cipher && (!m_Changing || (ID < m_ChangingProcess))) || + (m_Ciphers[OLD].Cipher && m_Changing && (ID >= m_ChangingProcess)); +} + +void CEncryptionManager::Encrypt(void* Data, uint32_t DataLength, uint32_t ID, uint32_t StartByte) +{ + if (m_Ciphers[CURRENT].Cipher && (!m_Changing || (ID < m_ChangingProcess))) + { + m_Ciphers[CURRENT].Cipher->Encrypt(Data, DataLength, ID, StartByte); + } else if (m_Ciphers[OLD].Cipher && m_Changing && (ID >= m_ChangingProcess)) + { + m_Ciphers[OLD].Cipher->Encrypt(Data, DataLength, ID, StartByte); + } +} +void CEncryptionManager::Decrypt(void* Data, uint32_t DataLength, uint32_t ID, uint32_t StartByte) +{ + if (m_Ciphers[CURRENT].Cipher && (!m_Changing || (ID < m_ChangingProcess))) + { + m_Ciphers[CURRENT].Cipher->Decrypt(Data, DataLength, ID, StartByte); + } else if (m_Ciphers[OLD].Cipher && m_Changing && (ID >= m_ChangingProcess)) + { + m_Ciphers[OLD].Cipher->Decrypt(Data, DataLength, ID, StartByte); + } +} + +bool CEncryptionManager::CanChangeCipher() +{ + return false; +} +bool CEncryptionManager::ChangeCipher(TEncryption & Encryption) +{ + return false; +} diff --git a/plugins/Dbx_tree/src/EncryptionManager.h b/plugins/Dbx_tree/src/EncryptionManager.h new file mode 100644 index 0000000000..768ea19efa --- /dev/null +++ b/plugins/Dbx_tree/src/EncryptionManager.h @@ -0,0 +1,107 @@ +/* + +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. + +*/ + +#pragma once + +#ifndef _MSC_VER +#include +#else +#include "stdint.h" +#endif +#include "sigslot.h" + +#define __INTERFACE_ONLY__ +#include "../encryption/Common/Cipher.h" +#undef __INTERFACE_ONLY__ + +#include "SHA256.h" +#include "Interface.h" +//#include "Thread.h" +#include +#include + +static const uint32_t cEncryptionChangingFlag = 0x80000000; + +#pragma pack(push, 1) + +typedef struct TFileEncryption { + uint32_t CipherID; + uint32_t CipherOldID; + uint32_t ConversionProcess; + uint8_t SHA[32]; + uint8_t SHAOld[32]; + uint32_t Reserved[2]; +} TFileEncryption, *PFileEncryption; + +#pragma pack(pop) + +typedef struct TEncryption { + uint32_t CipherID; + wchar_t * Password; +} TEncryption, *PEncryption; + +class CEncryptionManager +{ +public: + CEncryptionManager(); + ~CEncryptionManager(); + + typedef struct { + TCHAR * FilePath; + TCHAR * FileName; + uint32_t ID; + wchar_t * Name; + wchar_t * Description; + } TCipherItem; + typedef std::map TCipherList; + + static TCipherList* CipherList; // = NULL; see cpp + static uint32_t CipherListRefCount; // = 0; see cpp + static void LoadCipherList(); + + bool InitEncryption(TFileEncryption & Enc); + + bool AlignData(uint32_t ID, uint32_t & Start, uint32_t & End); + uint32_t AlignSize(uint32_t ID, uint32_t Size); + bool IsEncrypted(uint32_t ID); + void Encrypt(void* Data, uint32_t DataLength, uint32_t ID, uint32_t StartByte); + void Decrypt(void* Data, uint32_t DataLength, uint32_t ID, uint32_t StartByte); + + bool CanChangeCipher(); + bool ChangeCipher(TEncryption & Encryption); +private: + bool m_Changing; + uint32_t m_ChangingProcess; + + typedef enum TUsedCiphers { + CURRENT = 0, + OLD = 1, + COUNT = 2 + } TUsedCiphers; + + struct + { + CCipher * Cipher; + HMODULE CipherDLL; + } m_Ciphers[COUNT]; + +}; diff --git a/plugins/Dbx_tree/src/Entities.cpp b/plugins/Dbx_tree/src/Entities.cpp new file mode 100644 index 0000000000..73e9487ac6 --- /dev/null +++ b/plugins/Dbx_tree/src/Entities.cpp @@ -0,0 +1,1032 @@ +/* + +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 "Entities.h" + +CVirtuals::CVirtuals(CBlockManager & BlockManager, TNodeRef RootNode) +: CFileBTree::CFileBTree(BlockManager, RootNode, cVirtualNodeSignature) +{ + +} + +CVirtuals::~CVirtuals() +{ + +} + +TDBTEntityHandle CVirtuals::_DeleteRealEntity(TDBTEntityHandle hRealEntity) +{ + TDBTEntityHandle result; + TVirtualKey key; + TEntity * entity; + bool copies = false; + uint32_t size = sizeof(TEntity); + uint32_t sig = cEntitySignature; + + key.RealEntity = hRealEntity; + key.Virtual = 0; + + iterator i = LowerBound(key); + result = i->Virtual; + i.setManaged(); + Delete(*i); + + while ((i) && (i->RealEntity == hRealEntity)) + { + key = *i; + Delete(key); + + key.RealEntity = result; + Insert(key); + + entity = m_BlockManager.ReadBlock(key.Virtual, size, sig); + if (entity) + { + entity->VParent = result; + m_BlockManager.UpdateBlock(key.Virtual); + + copies = true; + } // TODO log + } + + entity = m_BlockManager.ReadBlock(result, size, sig); + if (entity) + { + entity->Flags = entity->Flags & ~(DBT_NF_HasVirtuals | DBT_NF_IsVirtual); + if (copies) + entity->Flags |= DBT_NF_HasVirtuals; + + m_BlockManager.UpdateBlock(result); + } // TODO log + return result; +} + +bool CVirtuals::_InsertVirtual(TDBTEntityHandle hRealEntity, TDBTEntityHandle hVirtual) +{ + TVirtualKey key; + key.RealEntity = hRealEntity; + key.Virtual = hVirtual; + + Insert(key); + + return true; +} +void CVirtuals::_DeleteVirtual(TDBTEntityHandle hRealEntity, TDBTEntityHandle hVirtual) +{ + TVirtualKey key; + key.RealEntity = hRealEntity; + key.Virtual = hVirtual; + + Delete(key); +} +TDBTEntityHandle CVirtuals::getParent(TDBTEntityHandle hVirtual) +{ + TEntity * entity; + uint32_t size = sizeof(TEntity); + uint32_t sig = cEntitySignature; + + CBlockManager::ReadTransaction trans(m_BlockManager); + + entity = m_BlockManager.ReadBlock(hVirtual, size, sig); + if (!entity || ((entity->Flags & DBT_NF_IsVirtual) == 0)) + return DBT_INVALIDPARAM; + + return entity->VParent; +} +TDBTEntityHandle CVirtuals::getFirst(TDBTEntityHandle hRealEntity) +{ + TEntity * entity; + uint32_t size = sizeof(TEntity); + uint32_t sig = cEntitySignature; + + CBlockManager::ReadTransaction trans(m_BlockManager); + + entity = m_BlockManager.ReadBlock(hRealEntity, size, sig); + if (!entity || ((entity->Flags & DBT_NF_HasVirtuals) == 0)) + return DBT_INVALIDPARAM; + + TVirtualKey key; + key.RealEntity = hRealEntity; + key.Virtual = 0; + + iterator i = LowerBound(key); + + if (i && (i->RealEntity == hRealEntity)) + key.Virtual = i->Virtual; + else + key.Virtual = 0; + + return key.Virtual; +} +TDBTEntityHandle CVirtuals::getNext(TDBTEntityHandle hVirtual) +{ + TEntity * entity; + uint32_t size = sizeof(TEntity); + uint32_t sig = cEntitySignature; + + CBlockManager::ReadTransaction trans(m_BlockManager); + + entity = m_BlockManager.ReadBlock(hVirtual, size, sig); + if (!entity || ((entity->Flags & DBT_NF_IsVirtual) == 0)) + return DBT_INVALIDPARAM; + + TVirtualKey key; + key.RealEntity = entity->VParent; + key.Virtual = hVirtual + 1; + + iterator i = LowerBound(key); + + if ((i) && (i->RealEntity == entity->VParent)) + key.Virtual = i->Virtual; + else + key.Virtual = 0; + + return key.Virtual; +} + + + + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// + +CEntities::CEntities(CBlockManager & BlockManager, TDBTEntityHandle RootEntity, TNodeRef EntityRoot, CVirtuals::TNodeRef VirtualRoot) +: CFileBTree::CFileBTree(BlockManager, EntityRoot, cEntityNodeSignature), + m_Virtuals(BlockManager, VirtualRoot), + + m_sigEntityDelete(), + m_sigInternalDeleteEvents(), + m_sigInternalDeleteSettings(), + m_sigInternalMergeSettings(), + m_sigInternalTransferEvents() +{ + if (RootEntity == 0) + m_RootEntity = _CreateRootEntity(); + else + m_RootEntity = RootEntity; + +} + +CEntities::~CEntities() +{ + +} + +TDBTEntityHandle CEntities::_CreateRootEntity() +{ + TEntity * entity; + TEntityKey key = {0,0,0}; + + CBlockManager::WriteTransaction trans(m_BlockManager); + + entity = m_BlockManager.CreateBlock(key.Entity, cEntitySignature); + entity->Flags = DBT_NF_IsGroup | DBT_NF_IsRoot; + m_BlockManager.UpdateBlock(key.Entity); + Insert(key); + return key.Entity; +} + +void CEntities::_InternalTransferContacts(TDBTEntityHandle OldAccount, TDBTEntityHandle NewAccount) +{ + uint32_t sig = cEntitySignature; + uint32_t size = sizeof(TEntity); + + TEntityKey key = {0,0,0}; + iterator i = LowerBound(key); + + while (i) + { + sig = cEntitySignature; + TEntity * entity = m_BlockManager.ReadBlock(i->Entity, size, sig); + if (entity && (entity->Account == OldAccount)) + { + entity->Account = NewAccount; + m_BlockManager.UpdateBlock(i->Entity); + } + + ++i; + } +} + +uint32_t CEntities::_getSettingsRoot(TDBTEntityHandle hEntity) +{ + /*CSettingsTree::TNodeRef*/ + uint32_t sig = cEntitySignature; + uint32_t size = sizeof(TEntity); + TEntity * entity = m_BlockManager.ReadBlock(hEntity, size, sig); + + if (!entity) + return DBT_INVALIDPARAM; + + return entity->Settings; +} +bool CEntities::_setSettingsRoot(TDBTEntityHandle hEntity, /*CSettingsTree::TNodeRef*/ uint32_t NewRoot) +{ + uint32_t sig = cEntitySignature; + uint32_t size = sizeof(TEntity); + TEntity * entity = m_BlockManager.ReadBlock(hEntity, size, sig); + + if (!entity) + return false; + + entity->Settings = NewRoot; + m_BlockManager.UpdateBlock(hEntity); + + return true; +} + +uint32_t CEntities::_getEventsRoot(TDBTEntityHandle hEntity) +{ + /*CEventsTree::TNodeRef*/ + uint32_t sig = cEntitySignature; + uint32_t size = sizeof(TEntity); + TEntity * entity = m_BlockManager.ReadBlock(hEntity, size, sig); + + if (!entity) + return DBT_INVALIDPARAM; + + return entity->Events; +} +bool CEntities::_setEventsRoot(TDBTEntityHandle hEntity, /*CEventsTree::TNodeRef*/ uint32_t NewRoot) +{ + uint32_t sig = cEntitySignature; + uint32_t size = sizeof(TEntity); + TEntity * entity = m_BlockManager.ReadBlock(hEntity, size, sig); + + if (!entity) + return false; + entity->Events = NewRoot; + m_BlockManager.UpdateBlock(hEntity); + + return true; +} + +uint32_t CEntities::_getEventCount(TDBTEntityHandle hEntity) +{ + uint32_t sig = cEntitySignature; + uint32_t size = sizeof(TEntity); + TEntity * entity = m_BlockManager.ReadBlock(hEntity, size, sig); + + if (!entity) + return DBT_INVALIDPARAM; + + return entity->EventCount; +} + +uint32_t CEntities::_adjustEventCount(TDBTEntityHandle hEntity, int32_t Adjust) +{ + uint32_t sig = cEntitySignature; + uint32_t size = sizeof(TEntity); + TEntity * entity = m_BlockManager.ReadBlock(hEntity, size, sig); + + if (!entity) + return DBT_INVALIDPARAM; + + if (((Adjust < 0) && ((uint32_t)(-Adjust) <= entity->EventCount)) || + ((Adjust > 0) && ((0xffffffff - entity->EventCount) > (uint32_t)Adjust))) + { + entity->EventCount += Adjust; + m_BlockManager.UpdateBlock(hEntity); + } + + return entity->EventCount; +} + +bool CEntities::_getFirstUnreadEvent(TDBTEntityHandle hEntity, uint32_t & hEvent, uint32_t & Timestamp) +{ + uint32_t sig = cEntitySignature; + uint32_t size = sizeof(TEntity); + TEntity * entity = m_BlockManager.ReadBlock(hEntity, size, sig); + + if (!entity) + return false; + + Timestamp = entity->FirstUnreadEventTimestamp; + hEvent = entity->FirstUnreadEventHandle; + return true; +} +bool CEntities::_setFirstUnreadEvent(TDBTEntityHandle hEntity, uint32_t hEvent, uint32_t Timestamp) +{ + uint32_t sig = cEntitySignature; + uint32_t size = sizeof(TEntity); + TEntity * entity = m_BlockManager.ReadBlock(hEntity, size, sig); + + if (!entity) + return false; + entity->FirstUnreadEventTimestamp = Timestamp; + entity->FirstUnreadEventHandle = hEvent; + m_BlockManager.UpdateBlock(hEntity); + + return true; +} + +TDBTEntityHandle CEntities::getParent(TDBTEntityHandle hEntity) +{ + uint32_t sig = cEntitySignature; + uint32_t size = sizeof(TEntity); + + CBlockManager::ReadTransaction trans(m_BlockManager); + + TEntity * entity = m_BlockManager.ReadBlock(hEntity, size, sig); + if (!entity) + return DBT_INVALIDPARAM; + + return entity->ParentEntity; +} +TDBTEntityHandle CEntities::setParent(TDBTEntityHandle hEntity, TDBTEntityHandle hParent) +{ + TEntity *entity, *newparent, *oldparent; + uint32_t size = sizeof(TEntity); + uint32_t sig = cEntitySignature; + + CBlockManager::WriteTransaction trans(m_BlockManager); + + entity = m_BlockManager.ReadBlock(hEntity, size, sig); + newparent = m_BlockManager.ReadBlock(hParent, size, sig); + if (!entity || !newparent) + return DBT_INVALIDPARAM; + + oldparent = m_BlockManager.ReadBlock(entity->ParentEntity, size, sig); + if (!oldparent) + return DBT_INVALIDPARAM; + + // update parents + if (--oldparent->ChildCount == 0) + oldparent->Flags &= ~DBT_NF_HasChildren; + + if (++newparent->ChildCount == 1) + newparent->Flags |= DBT_NF_HasChildren; + + + m_BlockManager.UpdateBlock(entity->ParentEntity); + m_BlockManager.UpdateBlock(hParent); + + // update rest + + TEntityKey key; + int dif = newparent->Level - entity->Level + 1; + + if (dif == 0) // no level difference, update only moved Entity + { + key.Entity = hEntity; + key.Level = entity->Level; + key.Parent = entity->ParentEntity; + Delete(key); + key.Parent = hParent; + Insert(key); + + entity->ParentEntity = hParent; + m_BlockManager.UpdateBlock(hEntity); + + } else { + TDBTEntityIterFilter filter = {0,0,0,0}; + filter.cbSize = sizeof(filter); + filter.Options = DBT_NIFO_OSC_AC | DBT_NIFO_OC_AC; + + TDBTEntityIterationHandle iter = IterationInit(filter, hEntity); + + key.Entity = IterationNext(iter); + + while ((key.Entity != 0) && (key.Entity != DBT_INVALIDPARAM)) + { + size = sizeof(TEntity); + sig = cEntitySignature; + TEntity * child = m_BlockManager.ReadBlock(key.Entity, size, sig); + + if (child) + { + key.Level = child->Level; + key.Parent = child->ParentEntity; + Delete(key); + + if (key.Entity == hEntity) + { + key.Parent = hParent; + entity->ParentEntity = hParent; + } + + child->Level += dif; + key.Level += dif; + m_BlockManager.UpdateBlock(key.Entity); + + Insert(key); + } // TODO log + key.Entity = IterationNext(iter); + } + + IterationClose(iter); + } + + /// TODO raise event + + return entity->ParentEntity; +} + +uint32_t CEntities::getChildCount(TDBTEntityHandle hEntity) +{ + uint32_t sig = cEntitySignature; + uint32_t size = sizeof(TEntity); + + CBlockManager::ReadTransaction trans(m_BlockManager); + + TEntity * entity = m_BlockManager.ReadBlock(hEntity, size, sig); + if (!entity) + return DBT_INVALIDPARAM; + + return entity->ChildCount; +} + +uint32_t CEntities::getFlags(TDBTEntityHandle hEntity) +{ + uint32_t sig = cEntitySignature; + uint32_t size = sizeof(TEntity); + + CBlockManager::ReadTransaction trans(m_BlockManager); + + TEntity * entity = m_BlockManager.ReadBlock(hEntity, size, sig); + if (!entity) + return DBT_INVALIDPARAM; + + return entity->Flags; +} + +uint32_t CEntities::getAccount(TDBTEntityHandle hEntity) +{ + uint32_t sig = cEntitySignature; + uint32_t size = sizeof(TEntity); + + CBlockManager::ReadTransaction trans(m_BlockManager); + + TEntity * entity = m_BlockManager.ReadBlock(hEntity, size, sig); + if (!entity) + return DBT_INVALIDPARAM; + + if (entity->Flags & DBT_NF_IsVirtual) + return getAccount(entity->VParent); + else if (entity->Flags & (DBT_NF_IsAccount | DBT_NF_IsGroup | DBT_NF_IsRoot)) + return 0; + + return entity->Flags; +} + +TDBTEntityHandle CEntities::CreateEntity(const TDBTEntity & Entity) +{ + uint32_t sig = cEntitySignature; + uint32_t size = sizeof(TEntity); + TDBTEntityHandle haccount = 0; + + CBlockManager::WriteTransaction trans(m_BlockManager); + + TEntity * parent = m_BlockManager.ReadBlock(Entity.hParentEntity, size, sig); + + if (!parent) + return DBT_INVALIDPARAM; + + // check account specification + if ((Entity.fFlags == 0) && (Entity.hAccountEntity != m_RootEntity)) // TODO disable root account thing, after conversion + { + TEntity * account = m_BlockManager.ReadBlock(Entity.hAccountEntity, size, sig); + if (!account || !(account->Flags & DBT_NF_IsAccount)) + return DBT_INVALIDPARAM; + + if (account->Flags & DBT_NF_IsVirtual) + { + haccount = VirtualGetParent(Entity.hAccountEntity); + } else { + haccount = Entity.hAccountEntity; + } + } + + TDBTEntityHandle hentity; + TEntity * entityblock = m_BlockManager.CreateBlock(hentity, cEntitySignature); + if (!entityblock) + return DBT_INVALIDPARAM; + + TEntityKey key; + + entityblock->Level = parent->Level + 1; + entityblock->ParentEntity = Entity.hParentEntity; + entityblock->Flags = Entity.fFlags; + entityblock->Account = haccount; + + m_BlockManager.UpdateBlock(hentity); + + key.Level = entityblock->Level; + key.Parent = entityblock->ParentEntity; + key.Entity = hentity; + + Insert(key); + + if (parent->ChildCount == 0) + parent->Flags = parent->Flags | DBT_NF_HasChildren; + + ++parent->ChildCount; + m_BlockManager.UpdateBlock(Entity.hParentEntity); + + return hentity; +} + +unsigned int CEntities::DeleteEntity(TDBTEntityHandle hEntity) +{ + uint32_t sig = cEntitySignature; + uint32_t size = sizeof(TEntity); + TDBTEntityHandle haccount = 0; + + CBlockManager::WriteTransaction trans(m_BlockManager); + + TEntity * entity = m_BlockManager.ReadBlock(hEntity, size, sig); + + if (!entity) + return DBT_INVALIDPARAM; + + TEntity * parent = m_BlockManager.ReadBlock(entity->ParentEntity, size, sig); + if (!parent) + return DBT_INVALIDPARAM; + + m_sigEntityDelete.emit(this, hEntity); + + if (entity->Flags & DBT_NF_HasVirtuals) + { + // move virtuals and make one of them real + TDBTEntityHandle newreal = m_Virtuals._DeleteRealEntity(hEntity); + + TEntity * realblock = m_BlockManager.ReadBlock(newreal, size, sig); + if (realblock) + { + realblock->EventCount = entity->EventCount; + realblock->Events = entity->Events; + + m_BlockManager.UpdateBlock(newreal); + + m_sigInternalTransferEvents.emit(this, hEntity, newreal); + m_sigInternalMergeSettings.emit(this, hEntity, newreal); + + if (entity->Flags & DBT_NF_IsAccount) + _InternalTransferContacts(hEntity, newreal); + } // TODO log + } else { + m_sigInternalDeleteEvents.emit(this, hEntity); + m_sigInternalDeleteSettings.emit(this, hEntity); + + if ((entity->Flags & DBT_NF_IsAccount) && !(entity->Flags & DBT_NF_IsVirtual)) + _InternalTransferContacts(hEntity, m_RootEntity); + + } + + TEntityKey key; + key.Level = entity->Level; + key.Parent = entity->ParentEntity; + key.Entity = hEntity; + Delete(key); + + if (entity->Flags & DBT_NF_HasChildren) // keep the children + { + parent->Flags |= DBT_NF_HasChildren; + parent->ChildCount += entity->ChildCount; + + TDBTEntityIterFilter filter = {0,0,0,0}; + filter.cbSize = sizeof(filter); + filter.Options = DBT_NIFO_OSC_AC | DBT_NIFO_OC_AC; + + TDBTEntityIterationHandle iter = IterationInit(filter, hEntity); + if (iter != DBT_INVALIDPARAM) + { + IterationNext(iter); + key.Entity = IterationNext(iter); + + while ((key.Entity != 0) && (key.Entity != DBT_INVALIDPARAM)) + { + size = sizeof(TEntity); + sig = cEntitySignature; + TEntity * child = m_BlockManager.ReadBlock(key.Entity, size, sig); + if (child) + { + key.Parent = child->ParentEntity; + key.Level = child->Level; + Delete(key); + + if (key.Parent == hEntity) + { + key.Parent = entity->ParentEntity; + child->ParentEntity = entity->ParentEntity; + } + + key.Level--; + m_BlockManager.UpdateBlock(key.Entity); + + Insert(key); + + } + key.Entity = IterationNext(iter); + } + + IterationClose(iter); + } + } + + if (--parent->ChildCount == 0) + parent->Flags = parent->Flags & (~DBT_NF_HasChildren); + + m_BlockManager.UpdateBlock(entity->ParentEntity); + + m_BlockManager.DeleteBlock(hEntity); // we needed this block, delete it now + + return 0; +} + + + +TDBTEntityIterationHandle CEntities::IterationInit(const TDBTEntityIterFilter & Filter, TDBTEntityHandle hParent) +{ + uint32_t sig = cEntitySignature; + uint32_t size = sizeof(TEntity); + TDBTEntityHandle haccount = 0; + + CBlockManager::ReadTransaction trans(m_BlockManager); + + TEntity * parent = m_BlockManager.ReadBlock(hParent, size, sig); + + if (!parent) + return DBT_INVALIDPARAM; + + PEntityIteration iter = new TEntityIteration; + iter->filter = Filter; + iter->q = new std::deque; + iter->parents = new std::deque; + iter->accounts = new std::deque; + #ifdef _MSC_VER + iter->returned = new stdext::hash_set; + #else + iter->returned = new __gnu_cxx::hash_set; + #endif + iter->returned->insert(hParent); + + TEntityIterationItem it; + it.Flags = parent->Flags; + it.Handle = hParent; + it.Level = parent->Level; + it.Options = Filter.Options & 0x000000ff; + it.LookupDepth = 0; + + iter->q->push_back(it); + + return (TDBTEntityIterationHandle)iter; +} +TDBTEntityHandle CEntities::IterationNext(TDBTEntityIterationHandle Iteration) +{ + uint32_t sig = cEntitySignature; + uint32_t size = sizeof(TEntity); + + CBlockManager::ReadTransaction trans(m_BlockManager); + + PEntityIteration iter = reinterpret_cast(Iteration); + TEntityIterationItem item; + TDBTEntityHandle result = 0; + + if (iter->q->empty()) + { + std::deque * tmp = iter->q; + iter->q = iter->parents; + iter->parents = tmp; + } + + if (iter->q->empty()) + { + std::deque * tmp = iter->q; + iter->q = iter->accounts; + iter->accounts = tmp; + } + + if (iter->q->empty() && + (iter->filter.Options & DBT_NIFO_GF_USEROOT) && + (iter->returned->find(m_RootEntity) == iter->returned->end())) + { + item.Handle = m_RootEntity; + item.Level = 0; + item.Options = 0; + item.Flags = 0; + item.LookupDepth = 255; + + iter->filter.Options = iter->filter.Options & ~DBT_NIFO_GF_USEROOT; + + iter->q->push_back(item); + } + + if (iter->q->empty()) + return 0; + + do { + item = iter->q->front(); + iter->q->pop_front(); + + std::deque tmp; + TEntityIterationItem newitem; + + // children + if ((item.Flags & DBT_NF_HasChildren) && + (item.Options & DBT_NIFO_OSC_AC)) + { + TEntityKey key; + key.Parent = item.Handle; + key.Level = item.Level + 1; + + newitem.Level = item.Level + 1; + newitem.LookupDepth = item.LookupDepth; + newitem.Options = (iter->filter.Options / DBT_NIFO_OC_AC * DBT_NIFO_OSC_AC) & (DBT_NIFO_OSC_AC | DBT_NIFO_OSC_AO | DBT_NIFO_OSC_AOC | DBT_NIFO_OSC_AOP); + + if (iter->filter.Options & DBT_NIFO_GF_DEPTHFIRST) + { + key.Entity = 0xffffffff; + + CEntities::iterator c = UpperBound(key); + while ((c) && (c->Parent == item.Handle)) + { + newitem.Handle = c->Entity; + + if (iter->returned->find(newitem.Handle) == iter->returned->end()) + { + TEntity * tmp = m_BlockManager.ReadBlock(newitem.Handle, size, sig); + if (tmp) + { + newitem.Flags = tmp->Flags; + if (((newitem.Flags & DBT_NF_IsGroup) == 0) || ((DBT_NF_IsGroup & iter->filter.fHasFlags) == 0)) // if we want only groups, we don't need to trace down Entities... + { + iter->q->push_front(newitem); + iter->returned->insert(newitem.Handle); + } + } + } + + --c; + } + } else { + key.Entity = 0; + + CEntities::iterator c = LowerBound(key); + while ((c) && (c->Parent == item.Handle)) + { + newitem.Handle = c->Entity; + + if (iter->returned->find(newitem.Handle) == iter->returned->end()) + { + TEntity * tmp = m_BlockManager.ReadBlock(newitem.Handle, size, sig); + if (tmp) + { + newitem.Flags = tmp->Flags; + if (((newitem.Flags & DBT_NF_IsGroup) == 0) || ((DBT_NF_IsGroup & iter->filter.fHasFlags) == 0)) // if we want only groups, we don't need to trace down Entities... + { + iter->q->push_back(newitem); + iter->returned->insert(newitem.Handle); + } + } + } + + ++c; + } + + } + } + + // parent... + if ((item.Options & DBT_NIFO_OSC_AP) && (item.Handle != m_RootEntity)) + { + newitem.Handle = getParent(item.Handle); + if ((iter->returned->find(newitem.Handle) == iter->returned->end()) && + (newitem.Handle != DBT_INVALIDPARAM)) + { + TEntity * tmp = m_BlockManager.ReadBlock(newitem.Handle, size, sig); + if (tmp) + { + newitem.Level = item.Level - 1; + newitem.LookupDepth = item.LookupDepth; + newitem.Options = (iter->filter.Options / DBT_NIFO_OP_AC * DBT_NIFO_OSC_AC) & (DBT_NIFO_OSC_AC | DBT_NIFO_OSC_AP | DBT_NIFO_OSC_AO | DBT_NIFO_OSC_AOC | DBT_NIFO_OSC_AOP); + newitem.Flags = tmp->Flags; + + if ((newitem.Flags & iter->filter.fDontHasFlags & DBT_NF_IsGroup) == 0) // if we don't want groups, stop it + { + iter->parents->push_back(newitem); + iter->returned->insert(newitem.Handle); + } + } + } + } + + // virtual lookup, original Entity is the next one + if ((item.Flags & DBT_NF_IsVirtual) && + (item.Options & DBT_NIFO_OSC_AO) && + (((iter->filter.Options >> 28) >= item.LookupDepth) || ((iter->filter.Options >> 28) == 0))) + { + newitem.Handle = VirtualGetParent(item.Handle); + + if ((iter->returned->find(newitem.Handle) == iter->returned->end()) && + (newitem.Handle != DBT_INVALIDPARAM)) + { + TEntity * tmp = m_BlockManager.ReadBlock(newitem.Handle, size, sig); + if (tmp) + { + newitem.Level = tmp->Level; + newitem.Options = 0; + newitem.Flags = tmp->Flags; + + if ((item.Options & DBT_NIFO_OSC_AOC) == DBT_NIFO_OSC_AOC) + newitem.Options |= DBT_NIFO_OSC_AC; + if ((item.Options & DBT_NIFO_OSC_AOP) == DBT_NIFO_OSC_AOP) + newitem.Options |= DBT_NIFO_OSC_AP; + + newitem.LookupDepth = item.LookupDepth + 1; + + iter->q->push_front(newitem); + iter->returned->insert(newitem.Handle); + } + } + } + + if (((iter->filter.fHasFlags & item.Flags) == iter->filter.fHasFlags) && + ((iter->filter.fDontHasFlags & item.Flags) == 0)) + { + result = item.Handle; + + // account lookup + if (((item.Flags & (DBT_NF_IsAccount | DBT_NF_IsGroup | DBT_NF_IsRoot)) == 0) && + ((item.Options & DBT_NIFO_OC_USEACCOUNT) == DBT_NIFO_OC_USEACCOUNT)) + { + TDBTEntityHandle acc = item.Handle; + if (item.Flags & DBT_NF_IsVirtual) + acc = VirtualGetParent(item.Handle); + + acc = getAccount(acc); + + std::deque::iterator acci = iter->accounts->begin(); + + while ((acci != iter->accounts->end()) && (acc != 0)) + { + if (acci->Handle == acc) + acc = 0; + acci++; + } + if (acc != 0) + { + TEntity * tmp = m_BlockManager.ReadBlock(acc, size, sig); + if (tmp) + { + newitem.Options = 0; + newitem.LookupDepth = 0; + newitem.Handle = acc; + newitem.Flags = tmp->Flags; + newitem.Level = tmp->Level; + iter->accounts->push_back(newitem); + } + } + } + } + + } while ((result == 0) && !iter->q->empty()); + + if (result == 0) + result = IterationNext(Iteration); + + return result; +} +unsigned int CEntities::IterationClose(TDBTEntityIterationHandle Iteration) +{ + PEntityIteration iter = reinterpret_cast(Iteration); + + delete iter->q; + delete iter->parents; + delete iter->accounts; + delete iter->returned; + delete iter; + + return 0; +} + + +TDBTEntityHandle CEntities::VirtualCreate(TDBTEntityHandle hRealEntity, TDBTEntityHandle hParent) +{ + uint32_t sig = cEntitySignature; + uint32_t size = sizeof(TEntity); + TDBTEntityHandle haccount = 0; + + CBlockManager::WriteTransaction trans(m_BlockManager); + + TEntity * realentity = m_BlockManager.ReadBlock(hRealEntity, size, sig); + + if (!realentity || (realentity->Flags & (DBT_NF_IsGroup | DBT_NF_IsRoot))) + return DBT_INVALIDPARAM; + + TDBTEntity entity = {0,0,0,0}; + entity.hParentEntity = hParent; + entity.fFlags = DBT_NF_IsVirtual | (realentity->Flags & DBT_NF_IsAccount); + entity.hAccountEntity = 0; + + TDBTEntityHandle result = CreateEntity(entity); + if (result == DBT_INVALIDPARAM) + return DBT_INVALIDPARAM; + + TEntity * entityblock = m_BlockManager.ReadBlock(result, size, sig); + if (!entityblock) + return DBT_INVALIDPARAM; + + if (realentity->Flags & DBT_NF_IsVirtual) + { + hRealEntity = realentity->VParent; + realentity = m_BlockManager.ReadBlock(hRealEntity, size, sig); + + if (!realentity) + return DBT_INVALIDPARAM; + } + + entityblock->VParent = hRealEntity; + m_BlockManager.UpdateBlock(result); + + if ((realentity->Flags & DBT_NF_HasVirtuals) == 0) + { + realentity->Flags |= DBT_NF_HasVirtuals; + m_BlockManager.UpdateBlock(hRealEntity); + } + + m_Virtuals._InsertVirtual(hRealEntity, result); + return result; +} + + +TDBTEntityHandle CEntities::compFirstContact() +{ + uint32_t sig = cEntitySignature; + uint32_t size = sizeof(TEntity); + + CBlockManager::ReadTransaction trans(m_BlockManager); + + TEntityKey key = {0,0,0}; + iterator i = LowerBound(key); + TDBTEntityHandle res = 0; + + while (i && (res == 0)) + { + TEntity * tmp = m_BlockManager.ReadBlock(i->Entity, size, sig); + if (tmp) + { + if ((tmp->Flags & DBT_NFM_SpecialEntity) == 0) + res = i->Entity; + } + if (res == 0) + ++i; + } + + return res; +} +TDBTEntityHandle CEntities::compNextContact(TDBTEntityHandle hEntity) +{ + uint32_t sig = cEntitySignature; + uint32_t size = sizeof(TEntity); + + CBlockManager::ReadTransaction trans(m_BlockManager); + + TEntityKey key; + key.Entity = hEntity; + TDBTEntityHandle res = 0; + + TEntity * entity = m_BlockManager.ReadBlock(hEntity, size, sig); + + if (entity) + { + key.Level = entity->Level; + key.Parent = entity->ParentEntity; + key.Entity++; + iterator i = LowerBound(key); + + while (i && (res == 0)) + { + entity = m_BlockManager.ReadBlock(i->Entity, size, sig); + if (entity) + { + if ((entity->Flags & DBT_NFM_SpecialEntity) == 0) + res = i->Entity; + } + if (res == 0) + ++i; + } + } + + return res; +} diff --git a/plugins/Dbx_tree/src/Entities.h b/plugins/Dbx_tree/src/Entities.h new file mode 100644 index 0000000000..579383d15f --- /dev/null +++ b/plugins/Dbx_tree/src/Entities.h @@ -0,0 +1,299 @@ +/* + +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. + +*/ + +#pragma once + +#include "Interface.h" +#include "FileBTree.h" +#include "MREWSync.h" +#include +#ifdef _MSC_VER +#include +#else +#include +#endif + +#pragma pack(push, 1) // push current alignment to stack, set alignment to 1 byte boundary + + +/** + \brief Key Type of the VirtualsBTree + + This BTree don't hold data itself, it's just for organisation + The virtual Entities are sorted first based on their real Entity. + That is for enumeration of one Entity's virtual copies, which are all stored in one block in the BTree +**/ +typedef struct TVirtualKey { + TDBTEntityHandle RealEntity; /// hEntity of the duplicated RealEntity + TDBTEntityHandle Virtual; /// hEntity of the virtual duplicate + + bool operator < (const TVirtualKey & Other) const + { + if (RealEntity != Other.RealEntity) return RealEntity < Other.RealEntity; + if (Virtual != Other.Virtual) return Virtual < Other.Virtual; + return false; + } + //bool operator <= (const TVirtualKey & Other); + bool operator == (const TVirtualKey & Other) const + { + return (RealEntity == Other.RealEntity) && (Virtual == Other.Virtual); + } + //bool operator >= (const TVirtualKey & Other); + bool operator > (const TVirtualKey & Other) const + { + if (RealEntity != Other.RealEntity) return RealEntity > Other.RealEntity; + if (Virtual != Other.Virtual) return Virtual > Other.Virtual; + return false; + } +} TVirtualKey; + +/** + \brief Key Type of the EntityBTree + + The Entities are sorted first based on their level. (root is first node, followed by its children) + That is for enumeration of one Entity's children, which are all stored in one block in the BTree +**/ +typedef struct TEntityKey { + uint16_t Level; /// Level where Entity is located or parent-steps to root. Root.Level == 0, root children have level 1 etc. + TDBTEntityHandle Parent; /// hEntity of the Parent. Root.Parent == 0 + TDBTEntityHandle Entity; /// hEntity of the stored Entity itself + + bool operator < (const TEntityKey & Other) const + { + if (Level != Other.Level) return Level < Other.Level; + if (Parent != Other.Parent) return Parent < Other.Parent; + if (Entity != Other.Entity) return Entity < Other.Entity; + return false; + } + //bool operator <= (const TEntityKey & Other); + bool operator == (const TEntityKey & Other) const + { + return (Level == Other.Level) && (Parent == Other.Parent) && (Entity == Other.Entity); + } + //bool operator >= (const TEntityKey & Other); + bool operator > (const TEntityKey & Other) const + { + if (Level != Other.Level) return Level > Other.Level; + if (Parent != Other.Parent) return Parent > Other.Parent; + if (Entity != Other.Entity) return Entity > Other.Entity; + return false; + } +} TEntityKey; + +/** + \brief The data of an Entity +**/ +typedef struct TEntity { + uint16_t Level; /// Level where Entity is located or parent-steps to root. Root.Level == 0, root children have level 1 etc. !used in the BTreeKey! + uint16_t ChildCount; /// Count of the children !invalid for Virtual Entity! + TDBTEntityHandle ParentEntity; /// hEntity of the Parent. Root.Parent == 0 !used in the BTreeKey! + union { + TDBTEntityHandle VParent; /// if the Entity is Virtual this is the hEntity of the related Realnode + TDBTEntityHandle Account; /// if the Entity's account, only for real real normal Entities + }; + uint32_t Flags; /// flags, see cEF_* + /*CSettingsTree::TNodeRef*/ + uint32_t Settings; /// Offset to the SettingsBTree RootNode of this Entity, NULL if no settings are present + /*CEventsTree::TNodeRef*/ + uint32_t Events; /// Offset to the EventsBTree RootNode of this Entity, NULL if no events are present !invalid for Virtal Entity! + uint32_t EventCount; /// Count of the stored events !invalid for Virtual Entity! + uint32_t FirstUnreadEventTimestamp; /// timestamp of the first unread event + uint32_t FirstUnreadEventHandle;/// ID of the first unread event + uint8_t Reserved[4]; /// reserved storage +} TEntity; + +#pragma pack(pop) // pop the alignment from stack + + + + +/** + \brief Manages the Virtual Entities in the Database + + A virtual Entity is stored as normal Entity in the database-structure, but doesn't hold own settings/events. + Such an Entity has the virtual flag set and refers its original duplicate. + All copies are stored in this BTree sorted to the RealEntity. + If the RealEntity should be deleted take the first virtual duplicate and make it real. Also change the relation of other copies. +**/ +class CVirtuals : public CFileBTree +{ +private: + +protected: + +public: + CVirtuals(CBlockManager & BlockManager, TNodeRef Root); + virtual ~CVirtuals(); + + /** + \brief Changes reference for all copies to the first Virtual in list + + \return New Original (previously first Virtual) to associate data with + **/ + TDBTEntityHandle _DeleteRealEntity(TDBTEntityHandle hRealEntity); + + bool _InsertVirtual(TDBTEntityHandle hRealEntity, TDBTEntityHandle hVirtual); + void _DeleteVirtual(TDBTEntityHandle hRealEntity, TDBTEntityHandle hVirtual); + + // services: + TDBTEntityHandle getParent(TDBTEntityHandle hVirtual); + TDBTEntityHandle getFirst(TDBTEntityHandle hRealEntity); + TDBTEntityHandle getNext(TDBTEntityHandle hVirtual); +}; + + +static const uint32_t cEntitySignature = 0x9A6B3C0D; +static const uint16_t cEntityNodeSignature = 0x65A9; +static const uint16_t cVirtualNodeSignature = 0x874E; +/** + \brief Manages the Entities in the Database + + A hEntity is equivalent to the fileoffset of its related TEntity structure +**/ +class CEntities : public CFileBTree +{ + +public: + CEntities(CBlockManager & BlockManager, TDBTEntityHandle RootEntity, TNodeRef EntityRoot, CVirtuals::TNodeRef VirtualRoot); + virtual ~CEntities(); + + typedef sigslot::signal2 TOnEntityDelete; + typedef sigslot::signal2 TOnInternalDeleteSettings; + typedef sigslot::signal2 TOnInternalDeleteEvents; + + typedef sigslot::signal3 TOnInternalMergeSettings; + typedef sigslot::signal3 TOnInternalTransferEvents; + + CVirtuals::TOnRootChanged & sigVirtualRootChanged() + { + return m_Virtuals.sigRootChanged(); + }; + + TOnEntityDelete & sigEntityDelete() + { + return m_sigEntityDelete; + }; + TOnInternalDeleteEvents & _sigDeleteEvents() + { + return m_sigInternalDeleteEvents; + }; + TOnInternalDeleteSettings & _sigDeleteSettings() + { + return m_sigInternalDeleteSettings; + }; + TOnInternalMergeSettings & _sigMergeSettings() + { + return m_sigInternalMergeSettings; + }; + TOnInternalTransferEvents & _sigTransferEvents() + { + return m_sigInternalTransferEvents; + }; + + //internal helpers: + /*CSettingsTree::TNodeRef*/ + uint32_t _getSettingsRoot(TDBTEntityHandle hEntity); + bool _setSettingsRoot(TDBTEntityHandle hEntity, /*CSettingsTree::TNodeRef*/ uint32_t NewRoot); + uint32_t _getEventsRoot(TDBTEntityHandle hEntity); + bool _setEventsRoot(TDBTEntityHandle hEntity, /*CSettingsTree::TNodeRef*/ uint32_t NewRoot); + uint32_t _getEventCount(TDBTEntityHandle hEntity); + uint32_t _adjustEventCount(TDBTEntityHandle hEntity, int32_t Adjust); + bool _getFirstUnreadEvent(TDBTEntityHandle hEntity, uint32_t & hEvent, uint32_t & Timestamp); + bool _setFirstUnreadEvent(TDBTEntityHandle hEntity, uint32_t hEvent, uint32_t Timestamp); + + CVirtuals & _getVirtuals() + { + return m_Virtuals; + }; + + //compatibility: + TDBTEntityHandle compFirstContact(); + TDBTEntityHandle compNextContact(TDBTEntityHandle hEntity); + //Services: + TDBTEntityHandle CEntities::getRootEntity() + { + return m_RootEntity; + }; + + TDBTEntityHandle getParent(TDBTEntityHandle hEntity); + TDBTEntityHandle setParent(TDBTEntityHandle hEntity, TDBTEntityHandle hParent); + uint32_t getChildCount(TDBTEntityHandle hEntity); + uint32_t getFlags(TDBTEntityHandle hEntity); + uint32_t getAccount(TDBTEntityHandle hEntity); + + TDBTEntityHandle CreateEntity(const TDBTEntity & Entity); + unsigned int DeleteEntity(TDBTEntityHandle hEntity); + + TDBTEntityIterationHandle IterationInit(const TDBTEntityIterFilter & Filter, TDBTEntityHandle hParent); + TDBTEntityHandle IterationNext(TDBTEntityIterationHandle Iteration); + unsigned int IterationClose(TDBTEntityIterationHandle Iteration); + + TDBTEntityHandle VirtualCreate(TDBTEntityHandle hRealEntity, TDBTEntityHandle hParent); + TDBTEntityHandle VirtualGetParent(TDBTEntityHandle hVirtual) + { + return m_Virtuals.getParent(hVirtual); + }; + TDBTEntityHandle VirtualGetFirst(TDBTEntityHandle hRealEntity) + { + return m_Virtuals.getFirst(hRealEntity); + }; + TDBTEntityHandle VirtualGetNext(TDBTEntityHandle hVirtual) + { + return m_Virtuals.getNext(hVirtual); + }; +private: + +protected: + + typedef struct TEntityIterationItem { + uint8_t Options; + uint8_t LookupDepth; + uint16_t Level; + TDBTEntityHandle Handle; + uint32_t Flags; + } TEntityIterationItem; + + typedef struct TEntityIteration { + TDBTEntityIterFilter filter; + std::deque * q; + std::deque * parents; + std::deque * accounts; + #ifdef _MSC_VER + stdext::hash_set * returned; + #else + __gnu_cxx::hash_set * returned; + #endif + } TEntityIteration, *PEntityIteration; + + TDBTEntityHandle m_RootEntity; + CVirtuals m_Virtuals; + + TDBTEntityHandle _CreateRootEntity(); + void _InternalTransferContacts(TDBTEntityHandle OldAccount, TDBTEntityHandle NewAccount); + + TOnEntityDelete m_sigEntityDelete; + TOnInternalDeleteEvents m_sigInternalDeleteEvents; + TOnInternalDeleteSettings m_sigInternalDeleteSettings; + TOnInternalMergeSettings m_sigInternalMergeSettings; + TOnInternalTransferEvents m_sigInternalTransferEvents; + +}; diff --git a/plugins/Dbx_tree/src/Events.cpp b/plugins/Dbx_tree/src/Events.cpp new file mode 100644 index 0000000000..732f6241c2 --- /dev/null +++ b/plugins/Dbx_tree/src/Events.cpp @@ -0,0 +1,986 @@ +/* + +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 "Events.h" +#ifndef _MSC_VER +#include "savestrings_gcc.h" +#endif + + +CEventsTypeManager::CEventsTypeManager(CEntities & Entities, CSettings & Settings) +: m_Entities(Entities), + m_Settings(Settings), + m_Map() +{ + m_Settings._EnsureModuleExists("$EventTypes"); +} +CEventsTypeManager::~CEventsTypeManager() +{ + TTypeMap::iterator it = m_Map.begin(); + + while (it != m_Map.end()) + { + delete [] it->second->ModuleName; + delete it->second; + ++it; + } +} + +uint32_t CEventsTypeManager::MakeGlobalID(char* Module, uint32_t EventType) +{ + uint32_t l = static_cast(strlen(Module)); + void * buf = malloc(l + sizeof(uint32_t)); + memcpy(buf, Module, l); + memcpy(((char*)buf) + l, &EventType, sizeof(uint32_t)); + + uint32_t h = Hash(buf, l + sizeof(uint32_t)); + free(buf); + + char * m; + uint32_t t; + while (GetType(h, m, t) && ((t != EventType) || (strcmp(m, Module) != 0))) + { + ++h; + } + + return h; +} +bool CEventsTypeManager::GetType(uint32_t GlobalID, char * & Module, uint32_t & EventType) +{ + TTypeMap::iterator it = m_Map.find(GlobalID); + + if (it == m_Map.end()) + { + char n[256]; + + TDBTSettingDescriptor d = {0,0,0,0,0,0,0,0}; + d.cbSize = sizeof(d); + d.Entity = m_Entities.getRootEntity(); + d.pszSettingName = n; + + TDBTSetting sid = {0,0,0,0}; + TDBTSetting sname = {0,0,0,0}; + + sid.cbSize = sizeof(sid); + sid.Descriptor = &d; + sid.Type = DBT_ST_INT; + + sname.cbSize = sizeof(sname); + sname.Descriptor = &d; + sname.Type = DBT_ST_ANSI; + + sprintf_s(n, "$EventTypes/%08x/ModuleID", GlobalID); + TDBTSettingHandle h = m_Settings.ReadSetting(sid); + + if ((h != DBT_INVALIDPARAM) && (h != 0)) + { + sprintf_s(n, "$EventTypes/%08x/ModuleName", GlobalID); + d.Flags = 0; + h = m_Settings.ReadSetting(sname); + + if ((h != DBT_INVALIDPARAM) && (h != 0)) + { + PEventType t = new TEventType; + + t->EventType = sid.Value.Int; + + t->ModuleName = new char[sname.Value.Length]; + strcpy_s(t->ModuleName, sname.Value.Length, sname.Value.pAnsi); + + m_Map.insert(std::make_pair(GlobalID, t)); + + mir_free(sname.Value.pAnsi); + + Module = t->ModuleName; + EventType = t->EventType; + + return true; + } + } + } else { + Module = it->second->ModuleName; + EventType = it->second->EventType; + + return true; + } + + return false; +} + +uint32_t CEventsTypeManager::EnsureIDExists(char* Module, uint32_t EventType) +{ + uint32_t res = MakeGlobalID(Module, EventType); + char * m; + uint32_t t; + if (!GetType(res, m, t)) + { + char n[256]; + + TDBTSettingDescriptor d = {0,0,0,0,0,0,0,0}; + d.cbSize = sizeof(d); + d.pszSettingName = n; + d.Entity = m_Entities.getRootEntity(); + + TDBTSetting s = {0,0,0,0}; + s.cbSize = sizeof(s); + s.Descriptor = &d; + + sprintf_s(n, "$EventTypes/%08x/ModuleID", res); + s.Type = DBT_ST_INT; + s.Value.Int = EventType; + m_Settings.WriteSetting(s); + + sprintf_s(n, "$EventTypes/%08x/ModuleName", res); + d.Flags = 0; + s.Type = DBT_ST_ANSI; + s.Value.Length = static_cast(strlen(Module) + 1); + s.Value.pAnsi = Module; + m_Settings.WriteSetting(s); + + m_Settings._EnsureModuleExists(Module); + } + + return res; +} + + +CEvents::CEvents( + CBlockManager & BlockManager, + CEncryptionManager & EncryptionManager, + CEntities & Entities, + CSettings & Settings +) +: m_BlockManager(BlockManager), + m_EncryptionManager(EncryptionManager), + m_Entities(Entities), + m_Types(Entities, Settings), + m_EntityEventsMap() +{ + m_Entities._sigDeleteEvents().connect(this, &CEvents::onDeleteEvents); + m_Entities._sigTransferEvents().connect(this, &CEvents::onTransferEvents); +} + +CEvents::~CEvents() +{ + TEntityEventsMap::iterator i = m_EntityEventsMap.begin(); + while (i != m_EntityEventsMap.end()) + { + delete i->second->RealTree; + delete i->second->VirtualTree; + delete i->second; + ++i; + } +} + +void CEvents::onRootChanged(void* EventsTree, CEventsTree::TNodeRef NewRoot) +{ + m_Entities._setEventsRoot(reinterpret_cast(EventsTree)->Entity(), NewRoot); +} + +void CEvents::onDeleteEventCallback(void * Tree, const TEventKey & Key, uint32_t Param) +{ + m_BlockManager.DeleteBlock(Key.Event); +} + +void CEvents::onDeleteVirtualEventCallback(void * Tree, const TEventKey & Key, uint32_t Param) +{ + m_BlockManager.DeleteBlock(Key.Event); +} +void CEvents::onDeleteEvents(CEntities * Entities, TDBTEntityHandle hEntity) +{ + PEntityEventsRecord record = getEntityRecord(hEntity); + + if (record == NULL) + return; + + m_Entities._setEventsRoot(hEntity, 0); + + if (record->VirtualCount) + { + CVirtualEventsTree::TDeleteCallback callback; + callback.connect(this, &CEvents::onDeleteVirtualEventCallback); + + record->VirtualTree->DeleteTree(&callback, hEntity); + } + delete record->VirtualTree; + + CEventsTree::TDeleteCallback callback; + callback.connect(this, &CEvents::onDeleteEventCallback); + record->RealTree->DeleteTree(&callback, hEntity); + delete record->RealTree; + m_EntityEventsMap.erase(hEntity); +} +void CEvents::onTransferEvents(CEntities * Entities, TDBTEntityHandle Source, TDBTEntityHandle Dest) +{ + PEntityEventsRecord record = getEntityRecord(Source); + + if (record == NULL) + return; + + if (record->VirtualCount) + { + TEventKey key = {0,0}; + + CVirtualEventsTree::iterator i = record->VirtualTree->LowerBound(key); + + while (i) + { + uint32_t sig = cEventSignature; + uint32_t size = 0; + TEvent * tmp = m_BlockManager.ReadBlock(i->Event, size, sig); + if (tmp) + { + tmp->Entity = Dest; + m_BlockManager.UpdateBlock(i->Event); + } + ++i; + } + } + + { + TEventKey key = {0,0}; + + CEventsTree::iterator i = record->RealTree->LowerBound(key); + while (i) + { + uint32_t sig = cEventSignature; + uint32_t size = 0; + TEvent * tmp = m_BlockManager.ReadBlock(i->Event, size, sig); + if (tmp) + { + tmp->Entity = Dest; + m_BlockManager.UpdateBlock(i->Event); + } + ++i; + } + + m_Entities._setEventsRoot(Source, 0); + m_Entities._setEventsRoot(Dest, record->RealTree->getRoot()); + m_Entities._adjustEventCount(Dest, m_Entities._getEventCount(Source)); + m_Entities._getFirstUnreadEvent(Source, key.Event, key.TimeStamp); + m_Entities._setFirstUnreadEvent(Dest, key.Event, key.TimeStamp); + } + + record->VirtualTree->Entity(Dest); + record->RealTree->Entity(Dest); + m_EntityEventsMap.erase(Source); + m_EntityEventsMap.insert(std::make_pair(Dest, record)); +} + +CEvents::PEntityEventsRecord CEvents::getEntityRecord(TDBTEntityHandle hEntity) +{ + TEntityEventsMap::iterator i = m_EntityEventsMap.find(hEntity); + if (i != m_EntityEventsMap.end()) + return i->second; + + uint32_t root = m_Entities._getEventsRoot(hEntity); + if (root == DBT_INVALIDPARAM) + return NULL; + + PEntityEventsRecord res = new TEntityEventsRecord; + res->RealTree = new CEventsTree(m_BlockManager, root, hEntity); + res->RealTree->sigRootChanged().connect(this, &CEvents::onRootChanged); + res->VirtualTree = new CVirtualEventsTree(hEntity); + res->VirtualCount = 0; + res->FirstVirtualUnread.TimeStamp = 0; + res->FirstVirtualUnread.Event = 0; + m_EntityEventsMap.insert(std::make_pair(hEntity, res)); + + return res; +} + +inline uint32_t CEvents::adjustVirtualEventCount(PEntityEventsRecord Record, int32_t Adjust) +{ + if (((Adjust < 0) && ((uint32_t)(-Adjust) <= Record->VirtualCount)) || + ((Adjust > 0) && ((0xffffffff - Record->VirtualCount) > (uint32_t)Adjust))) + { + Record->VirtualCount += Adjust; + } + + return Record->VirtualCount; +} + +inline bool CEvents::MarkEventsTree(TEventBase::iterator Iterator, TDBTEventHandle FirstUnread) +{ + uint32_t sig, size; + bool b = true; + bool res = false; + while (Iterator && b) + { + sig = cEventSignature; + size = 0; + TEvent * event = m_BlockManager.ReadBlock(Iterator->Event, size, sig); + if (event) + { + if (Iterator->Event == FirstUnread) + res = true; + + if ((event->Flags & DBT_EF_READ) == 0) + { + event->Flags |= DBT_EF_READ; + m_BlockManager.UpdateBlock(Iterator->Event); + --Iterator; + } else { + b = false; + } + } else { + --Iterator; + } + } + return res; +} +inline void CEvents::FindNextUnreadEvent(TEventBase::iterator & Iterator) +{ + uint32_t sig, size; + while (Iterator) + { + sig = cEventSignature; + size = 0; + TEvent * event = m_BlockManager.ReadBlock(Iterator->Event, size, sig); + if (event) + { + if (event->Flags & DBT_EF_READ) + ++Iterator; + else + return; + } else { + ++Iterator; + } + } +} + +unsigned int CEvents::GetBlobSize(TDBTEventHandle hEvent) +{ + uint32_t sig = cEventSignature; + uint32_t size = 0; + + CBlockManager::ReadTransaction trans(m_BlockManager); + TEvent * event = m_BlockManager.ReadBlock(hEvent, size, sig); + if (!event) + return DBT_INVALIDPARAM; + + return event->DataLength; +} + +unsigned int CEvents::Get(TDBTEventHandle hEvent, TDBTEvent & Event) +{ + uint32_t sig = cEventSignature; + uint32_t size = 0; + + CBlockManager::ReadTransaction trans(m_BlockManager); + + TEvent * event = m_BlockManager.ReadBlock(hEvent, size, sig); + if (!event) + return DBT_INVALIDPARAM; + + uint8_t * blob = reinterpret_cast(event + 1); + + if (!m_Types.GetType(event->Type, Event.ModuleName, Event.EventType)) + { + Event.EventType = event->Type; + Event.ModuleName = "???"; + } + + Event.Flags = event->Flags; + if (m_BlockManager.IsForcedVirtual(hEvent)) + Event.Flags |= DBT_EF_VIRTUAL; + + Event.Timestamp = event->TimeStamp; + + if (Event.cbBlob < event->DataLength) + Event.pBlob = (uint8_t*) mir_realloc(Event.pBlob, event->DataLength); + + memcpy(Event.pBlob, blob, event->DataLength); + Event.cbBlob = event->DataLength; + + return 0; +} + +unsigned int CEvents::GetCount(TDBTEntityHandle hEntity) +{ + CBlockManager::ReadTransaction trans(m_BlockManager); + + uint32_t res = m_Entities._getEventCount(hEntity); + PEntityEventsRecord record = getEntityRecord(hEntity); + + if ((res == DBT_INVALIDPARAM) || !record) + return DBT_INVALIDPARAM; + + res = res + record->VirtualCount; // access to Virtual Count need sync, too + + return res; +} + +unsigned int CEvents::Delete(TDBTEventHandle hEvent) +{ + uint32_t sig = cEventSignature; + uint32_t size = 0; + TEventKey key = {0, hEvent}; + + CBlockManager::WriteTransaction trans(m_BlockManager); + + TEvent * event = m_BlockManager.ReadBlock(hEvent, size, sig); + if (!event) + return DBT_INVALIDPARAM; + + key.TimeStamp = event->TimeStamp; + + PEntityEventsRecord record = getEntityRecord(event->Entity); + if (!record) + return DBT_INVALIDPARAM; + + if (m_BlockManager.IsForcedVirtual(hEvent)) + { + if (record->VirtualTree->Delete(key)) + { + adjustVirtualEventCount(record, -1); + + if (record->FirstVirtualUnread.Event == hEvent) + { + CVirtualEventsTree::iterator vi = record->VirtualTree->LowerBound(key); + FindNextUnreadEvent(vi); + if (vi) + { + record->FirstVirtualUnread = *vi; + } else { + record->FirstVirtualUnread.TimeStamp = 0; + record->FirstVirtualUnread.Event = 0; + } + } + } + } else { // real event + if (record->RealTree->Delete(key)) + { + m_Entities._adjustEventCount(event->Entity, -1); + TEventKey unreadkey; + m_Entities._getFirstUnreadEvent(event->Entity, unreadkey.Event, unreadkey.TimeStamp); + if (unreadkey.Event == hEvent) + { + CEventsTree::iterator it = record->VirtualTree->LowerBound(key); + FindNextUnreadEvent(it); + if (it) + { + m_Entities._setFirstUnreadEvent(event->Entity, it->Event, it->TimeStamp); + } else { + m_Entities._setFirstUnreadEvent(event->Entity, 0, 0); + } + } + } + } + m_BlockManager.DeleteBlock(hEvent); + + return 0; +} + +TDBTEventHandle CEvents::Add(TDBTEntityHandle hEntity, TDBTEvent & Event) +{ + TDBTEventHandle res = 0; + TEvent * event; + + CBlockManager::WriteTransaction trans(m_BlockManager); + + uint32_t eflags = m_Entities.getFlags(hEntity); + PEntityEventsRecord record = getEntityRecord(hEntity); + + if ((eflags == DBT_INVALIDPARAM) || + ((eflags & (DBT_NF_IsGroup | DBT_NF_IsRoot)) == DBT_NF_IsGroup) || // forbid events in groups. but allow root to have system history + !record) + { + return DBT_INVALIDPARAM; + } + + if (eflags & DBT_NF_IsVirtual) + hEntity = m_Entities.VirtualGetParent(hEntity); + + uint8_t *blobdata = Event.pBlob; + bool bloballocated = false; + + if (Event.Flags & DBT_EF_VIRTUAL) + { + event = m_BlockManager.CreateBlockVirtual(res, cEventSignature, sizeof(TEvent) + Event.cbBlob); + } else { + event = m_BlockManager.CreateBlock(res, cEventSignature, sizeof(TEvent) + Event.cbBlob); + } + + if (!event) + return DBT_INVALIDPARAM; + + TEventKey key = {0,0}; + + event->TimeStamp = Event.Timestamp; + event->Flags = Event.Flags & ~DBT_EF_VIRTUAL; + event->Type = m_Types.EnsureIDExists(Event.ModuleName, Event.EventType); + event->DataLength = Event.cbBlob; + event->Entity = hEntity; + + key.TimeStamp = event->TimeStamp; + key.Event = res; + memcpy(event + 1, Event.pBlob, Event.cbBlob); + + m_BlockManager.UpdateBlock(res); + + if (Event.Flags & DBT_EF_VIRTUAL) + { + record->VirtualTree->Insert(key); + adjustVirtualEventCount(record, +1); + if (!(Event.Flags & DBT_EF_READ) && ((record->FirstVirtualUnread.Event == 0) || (key < record->FirstVirtualUnread))) + { + record->FirstVirtualUnread = key; + } + } else { + record->RealTree->Insert(key); + m_Entities._adjustEventCount(hEntity, +1); + + if (!(Event.Flags & DBT_EF_READ)) + { + TEventKey unreadkey; + if (m_Entities._getFirstUnreadEvent(hEntity, unreadkey.Event, unreadkey.TimeStamp) && + ((unreadkey.Event == 0) || (key < unreadkey))) + { + m_Entities._setFirstUnreadEvent(hEntity, key.Event, key.TimeStamp); + } + } + } + + return res; +} +unsigned int CEvents::MarkRead(TDBTEventHandle hEvent) +{ + uint32_t sig = cEventSignature; + uint32_t size = 0; + TEventKey key = {0, hEvent}; + + CBlockManager::WriteTransaction trans(m_BlockManager); + + TEvent * event = m_BlockManager.ReadBlock(hEvent, size, sig); + + if (!event) + return DBT_INVALIDPARAM; + + key.TimeStamp = event->TimeStamp; + + if (event->Flags & DBT_EF_READ) + return event->Flags; + + PEntityEventsRecord record = getEntityRecord(event->Entity); + if (!record) + return DBT_INVALIDPARAM; + + CEventsTree::iterator it = record->RealTree->UpperBound(key); + CVirtualEventsTree::iterator vi = record->VirtualTree->UpperBound(key); + + m_Entities._getFirstUnreadEvent(event->Entity, key.Event, key.TimeStamp); + if (MarkEventsTree(it, key.Event)) + { + FindNextUnreadEvent(++it); + if (it) + { + m_Entities._setFirstUnreadEvent(event->Entity, it->Event, it->TimeStamp); + } else { + m_Entities._setFirstUnreadEvent(event->Entity, 0, 0); + } + } + if (MarkEventsTree(vi, record->FirstVirtualUnread.Event)) + { + FindNextUnreadEvent(++vi); + if (vi) + { + record->FirstVirtualUnread = *it; + } else { + record->FirstVirtualUnread.TimeStamp = 0; + record->FirstVirtualUnread.Event = 0; + } + } + + return event->Flags | DBT_EF_READ; +} +unsigned int CEvents::WriteToDisk(TDBTEventHandle hEvent) +{ + uint32_t sig = cEventSignature; + uint32_t size = 0; + TEventKey key; + key.Event = hEvent; + + CBlockManager::WriteTransaction trans(m_BlockManager); + + if (!m_BlockManager.IsForcedVirtual(hEvent)) + return DBT_INVALIDPARAM; + + TEvent * event = m_BlockManager.ReadBlock(hEvent, size, sig); + if (!event || (size < sizeof(TEvent))) + return DBT_INVALIDPARAM; + + PEntityEventsRecord record = getEntityRecord(event->Entity); + if (!record) + return DBT_INVALIDPARAM; + + key.TimeStamp = event->TimeStamp; + key.Event = hEvent; + + if (record->VirtualTree->Delete(key)) + adjustVirtualEventCount(record, -1); + + if (record->RealTree->Insert(key)) + m_Entities._adjustEventCount(event->Entity, +1); + m_BlockManager.WriteBlockToDisk(hEvent); + + return 0; +} + +TDBTEntityHandle CEvents::getEntity(TDBTEventHandle hEvent) +{ + uint32_t sig = cEventSignature; + uint32_t size = 0; + + CBlockManager::ReadTransaction trans(m_BlockManager); + TEvent * event = m_BlockManager.ReadBlock(hEvent, size, sig); + if (!event) + return DBT_INVALIDPARAM; + + return event->Entity; +} + +TDBTEventIterationHandle CEvents::IterationInit(TDBTEventIterFilter & Filter) +{ + CBlockManager::ReadTransaction trans(m_BlockManager); + + PEntityEventsRecord record = getEntityRecord(Filter.hEntity); + + if (!record) + return DBT_INVALIDPARAM; + + std::queue q; + q.push(record->RealTree); + q.push(record->VirtualTree); + + TDBTEntityIterFilter f = {0,0,0,0}; + f.cbSize = sizeof(f); + f.Options = Filter.Options; + + TDBTEntityIterationHandle citer = m_Entities.IterationInit(f, Filter.hEntity); + if (citer != DBT_INVALIDPARAM) + { + m_Entities.IterationNext(citer); + TDBTEntityHandle c = m_Entities.IterationNext(citer); + while (c != 0) + { + record = getEntityRecord(c); + if (record) + { + q.push(record->RealTree); + q.push(record->VirtualTree); + } + + c = m_Entities.IterationNext(citer); + } + + m_Entities.IterationClose(citer); + } + + for (unsigned j = 0; j < Filter.ExtraCount; ++j) + { + record = getEntityRecord(Filter.ExtraEntities[j]); + if (record) + { + q.push(record->RealTree); + q.push(record->VirtualTree); + } + } + + PEventIteration iter = new TEventIteration; + iter->Filter = Filter; + iter->LastEvent = 0; + iter->Heap = NULL; + + TEventKey key; + key.TimeStamp = Filter.tSince; + key.Event = 0; + + while (!q.empty()) + { + TEventBase * b = q.front(); + q.pop(); + + TEventBase::iterator it = b->LowerBound(key); + if (it) + { + TEventBase::iterator * it2 = new TEventBase::iterator(it); + it2->setManaged(); + if (iter->Heap) + { + iter->Heap->Insert(*it2); + } else { + iter->Heap = new TEventsHeap(*it2, TEventsHeap::ITForward, true); + } + } + } + + if (iter->Heap == NULL) + { + delete iter; + iter = (PEventIteration)DBT_INVALIDPARAM; + } + + return reinterpret_cast(iter); +} + +TDBTEventHandle CEvents::IterationNext(TDBTEventIterationHandle Iteration) +{ + PEventIteration iter = reinterpret_cast(Iteration); + + CBlockManager::ReadTransaction trans(m_BlockManager); + + TDBTEventHandle res = 0; + TEventBase::iterator it = iter->Heap->Top(); + + while ((it) && (it.wasDeleted() || ((it->TimeStamp <= iter->Filter.tTill) && (it->Event == iter->LastEvent)))) + { + iter->Heap->Pop(); + it = iter->Heap->Top(); + } + + if ((it) && !it.wasDeleted() && (it->TimeStamp <= iter->Filter.tTill)) + { + res = it->Event; + iter->Heap->Pop(); + } + + if (res) + { + iter->LastEvent = res; + if (iter->Filter.Event) + { + iter->Filter.Event->EventType = 0; + Get(res, *iter->Filter.Event); + } + } + + return res; +} + +unsigned int CEvents::IterationClose(TDBTEventIterationHandle Iteration) +{ + PEventIteration iter = reinterpret_cast(Iteration); + + CBlockManager::ReadTransaction trans(m_BlockManager); + delete iter->Heap; + delete iter; + return 0; +} + + +TDBTEventHandle CEvents::compFirstEvent(TDBTEntityHandle hEntity) +{ + CBlockManager::ReadTransaction trans(m_BlockManager); + + TDBTEventHandle res = 0; + + PEntityEventsRecord record = getEntityRecord(hEntity); + if (!record) + return 0; + + TEventKey key = {0,0}; + CEventsTree::iterator i = record->RealTree->LowerBound(key); + CVirtualEventsTree::iterator vi = record->VirtualTree->LowerBound(key); + + if (i && vi) + { + if (*i < *vi) + { + res = i->Event; + } else { + res = vi->Event; + } + } else if (i) + { + res = i->Event; + } else if (vi) + { + res = vi->Event; + } + + return res; +} +TDBTEventHandle CEvents::compFirstUnreadEvent(TDBTEntityHandle hEntity) +{ + CBlockManager::ReadTransaction trans(m_BlockManager); + + TDBTEventHandle res = 0; + + PEntityEventsRecord record = getEntityRecord(hEntity); + if (!record) + return 0; + + TEventKey key; + m_Entities._getFirstUnreadEvent(hEntity, key.Event, key.TimeStamp); + if (key.Event) + { + if (record->FirstVirtualUnread.Event && (record->FirstVirtualUnread < key)) + { + res = record->FirstVirtualUnread.Event; + } else { + res = key.Event; + } + } else if (record->FirstVirtualUnread.Event) + { + res = record->FirstVirtualUnread.Event; + } + + return res; +} +TDBTEventHandle CEvents::compLastEvent(TDBTEntityHandle hEntity) +{ + CBlockManager::ReadTransaction trans(m_BlockManager); + TDBTEventHandle res = 0; + + PEntityEventsRecord record = getEntityRecord(hEntity); + if (!record) + return 0; + + TEventKey key = {0xffffffff, 0xffffffff}; + + CEventsTree::iterator i = record->RealTree->UpperBound(key); + CVirtualEventsTree::iterator vi = record->VirtualTree->UpperBound(key); + + if (i && vi) + { + if (*i > *vi) + { + res = i->Event; + } else { + res = vi->Event; + } + } else if (i) + { + res = i->Event; + } else if (vi) + { + res = vi->Event; + } + + return res; +} +TDBTEventHandle CEvents::compNextEvent(TDBTEventHandle hEvent) +{ + uint32_t sig = cEventSignature; + uint32_t size = 0; + + CBlockManager::ReadTransaction trans(m_BlockManager); + + TEvent * event = m_BlockManager.ReadBlock(hEvent, size, sig); + + if (!event) + return 0; + + TEventKey key = {event->TimeStamp, hEvent}; + + PEntityEventsRecord record = getEntityRecord(event->Entity); + + if (!record) + return 0; + + if (key.Event == 0xffffffff) + { + if (key.TimeStamp == 0xffffffff) + { + return 0; + } else { + ++key.TimeStamp; + } + } else { + ++key.Event; + } + + CEventsTree::iterator i = record->RealTree->LowerBound(key); + CVirtualEventsTree::iterator vi = record->VirtualTree->LowerBound(key); + + TDBTEventHandle res = 0; + if (i && vi) + { + if (*i < *vi) + { + res = i->Event; + } else { + res = vi->Event; + } + } else if (i) + { + res = i->Event; + } else if (vi) + { + res = vi->Event; + } + + return res; +} +TDBTEventHandle CEvents::compPrevEvent(TDBTEventHandle hEvent) +{ + uint32_t sig = cEventSignature; + uint32_t size = 0; + + CBlockManager::ReadTransaction trans(m_BlockManager); + + TEvent * event = m_BlockManager.ReadBlock(hEvent, size, sig); + + if (!event) + return 0; + + TEventKey key = {event->TimeStamp, hEvent}; + + PEntityEventsRecord record = getEntityRecord(event->Entity); + if (!record) + return 0; + + if (key.Event == 0) + { + if (key.TimeStamp == 0) + { + return 0; + } else { + --key.TimeStamp; + } + } else { + --key.Event; + } + + CEventsTree::iterator i = record->RealTree->UpperBound(key); + CVirtualEventsTree::iterator vi = record->VirtualTree->UpperBound(key); + + TDBTEventHandle res = 0; + if (i && vi) + { + if (*i > *vi) + { + res = i->Event; + } else { + res = vi->Event; + } + } else if (i) + { + res = i->Event; + } else if (vi) + { + res = vi->Event; + } + + return res; +} diff --git a/plugins/Dbx_tree/src/Events.h b/plugins/Dbx_tree/src/Events.h new file mode 100644 index 0000000000..7a3d50ff19 --- /dev/null +++ b/plugins/Dbx_tree/src/Events.h @@ -0,0 +1,263 @@ +/* + +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. + +*/ + +#pragma once + +#include "Interface.h" +#include "BTree.h" +#include "FileBTree.h" +#include "BlockManager.h" +#include "IterationHeap.h" +#include "Entities.h" +#include "Settings.h" +#include "Hash.h" +#include "EncryptionManager.h" +#include "sigslot.h" + +#ifdef _MSC_VER +#include +#include +#else +#include +#include +#endif +#include +#include +#include + +#pragma pack(push, 1) // push current alignment to stack, set alignment to 1 byte boundary + +/** + \brief Key Type of the EventsBTree + + The Key consists of a timestamp, seconds elapsed since 1.1.1970 + and an Index, which makes it possible to store multiple events with the same timestamp +**/ +typedef struct TEventKey { + uint32_t TimeStamp; /// timestamp at which the event occoured + TDBTEventHandle Event; + + bool operator < (const TEventKey & Other) const + { + if (TimeStamp != Other.TimeStamp) return TimeStamp < Other.TimeStamp; + if (Event != Other.Event) return Event < Other.Event; + return false; + } + //bool operator <= (const TEventKey & Other); + bool operator == (const TEventKey & Other) const + { + return (TimeStamp == Other.TimeStamp) && (Event == Other.Event); + } + + //bool operator >= (const TEventKey & Other); + bool operator > (const TEventKey & Other) const + { + if (TimeStamp != Other.TimeStamp) return TimeStamp > Other.TimeStamp; + if (Event != Other.Event) return Event > Other.Event; + return false; + } + +} TEventKey; + +/** + \brief The data of an Event + + A event's data is variable length. The data is a TDBTEvent-structure followed by varaible length data. + - fixed data + - blob data (mostly UTF8 message body) +**/ +typedef struct TEvent { + uint32_t Flags; /// Flags + uint32_t TimeStamp; /// Timestamp of the event (seconds elapsed since 1.1.1970) used as key element + uint32_t Type; /// Eventtype + TDBTEntityHandle Entity; /// hEntity which owns this event + uint32_t DataLength; /// Length of the stored data in bytes + + uint8_t Reserved[8]; /// reserved storage +} TEvent; + +#pragma pack(pop) + + +static const uint32_t cEventSignature = 0x365A7E92; +static const uint16_t cEventNodeSignature = 0x195C; + +/** + \brief Manages the Events Index in the Database +**/ +class CEventsTree : public CFileBTree +{ +private: + TDBTEntityHandle m_Entity; + +public: + CEventsTree(CBlockManager & BlockManager, TNodeRef RootNode, TDBTEntityHandle Entity) + : CFileBTree::CFileBTree(BlockManager, RootNode, cEventNodeSignature), + m_Entity(Entity) + { }; + ~CEventsTree() + { }; + + TDBTEntityHandle Entity() + { + return m_Entity; + }; + void Entity(TDBTEntityHandle NewEntity) + { + m_Entity = NewEntity; + }; +}; + +/** + \brief Manages the Virtual Events Index + Sorry for duplicating code... +**/ +class CVirtualEventsTree : public CBTree +{ +private: + TDBTEntityHandle m_Entity; + +public: + CVirtualEventsTree(TDBTEntityHandle Entity) + : CBTree::CBTree(0), + m_Entity(Entity) + { }; + + ~CVirtualEventsTree() + { }; + + TDBTEntityHandle Entity() + { + return m_Entity; + }; + void Entity(TDBTEntityHandle NewEntity) + { + m_Entity = NewEntity; + }; +}; + + +class CEventsTypeManager +{ +public: + CEventsTypeManager(CEntities & Entities, CSettings & Settings); + ~CEventsTypeManager(); + + uint32_t MakeGlobalID(char* Module, uint32_t EventType); + bool GetType(uint32_t GlobalID, char * & Module, uint32_t & EventType); + uint32_t EnsureIDExists(char* Module, uint32_t EventType); + +private: + typedef struct TEventType { + char * ModuleName; + uint32_t EventType; + } TEventType, *PEventType; + #ifdef _MSC_VER + typedef stdext::hash_map TTypeMap; + #else + typedef __gnu_cxx::hash_map TTypeMap; + #endif + + CEntities & m_Entities; + CSettings & m_Settings; + TTypeMap m_Map; + +}; + + +class CEvents : public sigslot::has_slots<> +{ +public: + + CEvents( + CBlockManager & BlockManager, + CEncryptionManager & EncryptionManager, + CEntities & Entities, + CSettings & Settings + ); + ~CEvents(); + + //compatibility + TDBTEventHandle compFirstEvent(TDBTEntityHandle hEntity); + TDBTEventHandle compFirstUnreadEvent(TDBTEntityHandle hEntity); + TDBTEventHandle compLastEvent(TDBTEntityHandle hEntity); + TDBTEventHandle compNextEvent(TDBTEventHandle hEvent); + TDBTEventHandle compPrevEvent(TDBTEventHandle hEvent); + + //services + unsigned int GetBlobSize(TDBTEventHandle hEvent); + unsigned int Get(TDBTEventHandle hEvent, TDBTEvent & Event); + unsigned int GetCount(TDBTEntityHandle hEntity); + unsigned int Delete(TDBTEventHandle hEvent); + TDBTEventHandle Add(TDBTEntityHandle hEntity, TDBTEvent & Event); + unsigned int MarkRead(TDBTEventHandle hEvent); + unsigned int WriteToDisk(TDBTEventHandle hEvent); + + TDBTEntityHandle getEntity(TDBTEventHandle hEvent); + + TDBTEventIterationHandle IterationInit(TDBTEventIterFilter & Filter); + TDBTEventHandle IterationNext(TDBTEventIterationHandle Iteration); + unsigned int IterationClose(TDBTEventIterationHandle Iteration); + + +private: + typedef CBTree TEventBase; + typedef struct + { + CEventsTree * RealTree; + CVirtualEventsTree * VirtualTree; + uint32_t VirtualCount; + TEventKey FirstVirtualUnread; + } TEntityEventsRecord, *PEntityEventsRecord; + #ifdef _MSC_VER + typedef stdext::hash_map TEntityEventsMap; + #else + typedef __gnu_cxx::hash_map TEntityEventsMap; + #endif + typedef CIterationHeap TEventsHeap; + + CBlockManager & m_BlockManager; + CEncryptionManager & m_EncryptionManager; + + CEntities & m_Entities; + CEventsTypeManager m_Types; + + TEntityEventsMap m_EntityEventsMap; + + typedef struct TEventIteration { + TDBTEventIterFilter Filter; + TEventsHeap * Heap; + TDBTEventHandle LastEvent; + } TEventIteration, *PEventIteration; + + void onRootChanged(void* EventsTree, CEventsTree::TNodeRef NewRoot); + + void onDeleteEventCallback(void * Tree, const TEventKey & Key, uint32_t Param); + void onDeleteVirtualEventCallback(void * Tree, const TEventKey & Key, uint32_t Param); + void onDeleteEvents(CEntities * Entities, TDBTEntityHandle hEntity); + void onTransferEvents(CEntities * Entities, TDBTEntityHandle Source, TDBTEntityHandle Dest); + + PEntityEventsRecord getEntityRecord(TDBTEntityHandle hEntity); + uint32_t adjustVirtualEventCount(PEntityEventsRecord Record, int32_t Adjust); + bool MarkEventsTree(TEventBase::iterator Iterator, TDBTEventHandle FirstUnread); + void FindNextUnreadEvent(TEventBase::iterator & Iterator); +}; diff --git a/plugins/Dbx_tree/src/FileAccess.cpp b/plugins/Dbx_tree/src/FileAccess.cpp new file mode 100644 index 0000000000..a0aa85aecb --- /dev/null +++ b/plugins/Dbx_tree/src/FileAccess.cpp @@ -0,0 +1,299 @@ +/* + +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 "FileAccess.h" +#include +#ifndef _MSC_VER +#include "savestrings_gcc.h" +#define _time32 time +#endif +#include "Logger.h" + +const uint8_t CFileAccess::cJournalSignature[20] = "Miranda IM Journal!"; + +CFileAccess::CFileAccess(const TCHAR* FileName) +{ + m_FileName = new TCHAR[_tcslen(FileName) + 1]; + m_Journal.FileName = new TCHAR[_tcslen(FileName) + 5]; + _tcscpy_s(m_FileName, _tcslen(FileName) + 1, FileName); + _tcscpy_s(m_Journal.FileName, _tcslen(FileName) + 5, FileName); + _tcscat_s(m_Journal.FileName, _tcslen(FileName) + 5, _T(".jrn")); + + m_ReadOnly = false; + m_LastSize = 0; + m_Size = 0; + m_Journal.Use = false; + m_Journal.hFile = 0; + m_Journal.BufUse = 0; + + m_LastAllocTime = _time32(NULL); +} + +CFileAccess::~CFileAccess() +{ + CloseHandle(m_Journal.hFile); + DeleteFile(m_Journal.FileName); + + delete [] m_FileName; + delete [] m_Journal.FileName; +} + +uint32_t CFileAccess::Size(uint32_t NewSize) +{ + m_Size = NewSize; + if (!m_Journal.Use) + { + NewSize = (NewSize + m_AllocGranularity - 1) & ~(m_AllocGranularity - 1); + + if (NewSize == 0) + NewSize = m_AllocGranularity; + + if (NewSize != m_AllocSize) + { + m_AllocSize = _SetSize(NewSize); + + // adapt Alloc Granularity + uint32_t t = _time32(NULL); + uint32_t d = t - m_LastAllocTime; + m_LastAllocTime = t; + + if (d < 30) // increase alloc stepping + { + if (m_AllocGranularity < m_MaxAllocGranularity) + m_AllocGranularity = m_AllocGranularity << 1; + } else if (d > 120) // decrease alloc stepping + { + if (m_AllocGranularity > m_MinAllocGranularity) + m_AllocGranularity = m_AllocGranularity >> 1; + } + } + } + return NewSize; +} + + +void CFileAccess::CleanJournal() +{ + SetFilePointer(m_Journal.hFile, 0, NULL, FILE_BEGIN); + SetEndOfFile(m_Journal.hFile); + + DWORD written; + WriteFile(m_Journal.hFile, cJournalSignature, sizeof(cJournalSignature), &written, NULL); +} + +void CFileAccess::ProcessJournal() +{ + uint32_t filesize = GetFileSize(m_Journal.hFile, NULL) - sizeof(cJournalSignature); + SetFilePointer(m_Journal.hFile, sizeof(cJournalSignature), NULL, FILE_BEGIN); + + uint8_t* buf = (uint8_t*)malloc(filesize); + TJournalEntry* e = (TJournalEntry*)buf; + DWORD read = 0; + if (!ReadFile(m_Journal.hFile, buf, filesize, &read, NULL) || (read != filesize)) + { + free(buf); + LOGSYS(logCRITICAL, _T("Couldn't flush the journal because ReadFile failed!")); + return; + } + + m_Journal.Use = false; + std::vector currentops; + + while (filesize >= sizeof(TJournalEntry)) + { + switch (e->Signature) + { + case 'fini': + { + Size(e->Size); + + std::vector::iterator i = currentops.begin(); + while (i != currentops.end()) + { + switch ((*i)->Signature) + { + case 'writ': + { + if ((*i)->Address + (*i)->Size <= m_AllocSize) + { + _Write(*i + 1, (*i)->Address, (*i)->Size); + } else if ((*i)->Address < m_AllocSize) + { + _Write(*i + 1, (*i)->Address, m_AllocSize - (*i)->Address); + } + } break; + case 'inva': + { + if ((*i)->Address + (*i)->Size <= m_AllocSize) + { + _Invalidate((*i)->Address, (*i)->Size); + } else if ((*i)->Address < m_AllocSize) + { + _Invalidate((*i)->Address, m_AllocSize - (*i)->Address); + } + } break; + } + ++i; + } + currentops.clear(); + + e++; + filesize = filesize - sizeof(TJournalEntry); + } break; + case 'writ': + { + if (filesize < sizeof(e) + e->Size) + { + filesize = 0; + } else { + currentops.push_back(e); + filesize = filesize - sizeof(TJournalEntry) - e->Size; + e = (TJournalEntry*)((uint8_t*)e + sizeof(TJournalEntry) + e->Size); + } + } break; + case 'inva': + { + if (filesize < sizeof(e)) + { + filesize = 0; + } else { + currentops.push_back(e); + e++; + filesize = filesize - sizeof(TJournalEntry); + } + } break; + default: + { + filesize = 0; + if (currentops.size()) + LOG(logWARNING, _T("Your database journal wasn't completely written to disk.")); + } break; + } + } + + _Flush(); + + CleanJournal(); + + free(buf); + m_Journal.Use = true; +} + +void CFileAccess::InitJournal() +{ + m_Journal.hFile = CreateFile(m_Journal.FileName, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, 0); + if (m_Journal.hFile == INVALID_HANDLE_VALUE) + { + LOGSYS(logCRITICAL, _T("CreateFile failed on Journal %s"), m_Journal.FileName); + return; + } + + uint8_t h[sizeof(cJournalSignature)]; + DWORD read; + if (ReadFile(m_Journal.hFile, &h, sizeof(h), &read, NULL) && (read == sizeof(h)) && (0 == memcmp(h, cJournalSignature, sizeof(h)))) + { + TCHAR * bckname = new TCHAR[_tcslen(m_FileName) + 12]; + _tcscpy_s(bckname, _tcslen(m_FileName) + 12, m_FileName); + _tcscat_s(bckname, _tcslen(m_FileName) + 12, _T(".autobackup")); + + TCHAR * bckjrnname = new TCHAR[_tcslen(m_Journal.FileName) + 12]; + _tcscpy_s(bckjrnname, _tcslen(m_Journal.FileName) + 12, m_Journal.FileName); + _tcscat_s(bckjrnname, _tcslen(m_Journal.FileName) + 12, _T(".autobackup")); + + char buf[4096]; + HANDLE hfilebackup = CreateFile(bckname, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, 0); + if (hfilebackup) + { + uint32_t i = 0; + while (i + sizeof(buf) <= m_AllocSize) + { + DWORD w; + _Read(buf, i, sizeof(buf)); + i += sizeof(buf); + WriteFile(hfilebackup, buf, sizeof(buf), &w, NULL); + } + if (i < m_AllocSize) + { + DWORD w; + _Read(buf, i, m_AllocSize - i); + WriteFile(hfilebackup, buf, m_AllocSize - i, &w, NULL); + } + + CloseHandle(hfilebackup); + } + + HANDLE hjrnfilebackup = CreateFile(bckjrnname, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, 0); + if (hjrnfilebackup) + { + uint32_t i = 0; + + uint32_t filesize = GetFileSize(m_Journal.hFile, NULL); + SetFilePointer(m_Journal.hFile, 0, NULL, FILE_BEGIN); + + while (i + sizeof(buf) <= filesize) + { + DWORD w, r; + ReadFile(m_Journal.hFile, buf, sizeof(buf), &r, NULL); + i += sizeof(buf); + WriteFile(hjrnfilebackup, buf, sizeof(buf), &w, NULL); + } + if (i < filesize) + { + DWORD w, r; + ReadFile(m_Journal.hFile, buf, filesize - i, &r, NULL); + WriteFile(hjrnfilebackup, buf, filesize - i, &w, NULL); + } + CloseHandle(hjrnfilebackup); + } + + TCHAR* path = bckname; + TCHAR* fn = _tcsrchr(m_Journal.FileName, _T('\\')); + TCHAR* bfn = _tcsrchr(bckname, _T('\\')); + TCHAR* jrn = _tcsrchr(bckjrnname, _T('\\')); + if (bfn) // truncate path var + *bfn = 0; + + if (hfilebackup || hjrnfilebackup) + { + LOG(logWARNING, + _T("Journal \"%s\" was found on start.\nBackup \"%s\"%s created and backup \"%s\"%s created.\nYou may delete these file(s) after successful start from \"%s\"."), + fn?fn+1:m_Journal.FileName, + bfn?bfn+1:bckname, (hfilebackup!=INVALID_HANDLE_VALUE)?_T(" was successfully"):_T(" could not be"), + jrn?jrn+1:bckjrnname, (hjrnfilebackup!=INVALID_HANDLE_VALUE)?_T(" was successfully"):_T(" could not be"), + path); + } else { + LOG(logWARNING, + _T("Journal \"%s\" was found on start.\nBackups \"%s\"and \"%s\" could not be created in \"%s\"."), + fn?fn+1:m_Journal.FileName, + bfn?bfn+1:bckname, + jrn?jrn+1:bckjrnname, + path); + } + + delete [] bckname; + delete [] bckjrnname; + + ProcessJournal(); + } + + CleanJournal(); +} diff --git a/plugins/Dbx_tree/src/FileAccess.h b/plugins/Dbx_tree/src/FileAccess.h new file mode 100644 index 0000000000..f49643e2a3 --- /dev/null +++ b/plugins/Dbx_tree/src/FileAccess.h @@ -0,0 +1,191 @@ +/* + +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. + +*/ + +#pragma once + +#include +#include +#include "stdint.h" +#include "sigslot.h" + +class CFileAccess +{ +public: + static const uint8_t cJournalSignature[20]; + + CFileAccess(const TCHAR* FileName); + virtual ~CFileAccess(); + + + uint32_t Read(void* Buf, uint32_t Source, uint32_t Size) + { + return _Read(Buf, Source, Size); + }; + + bool Write(void* Buf, uint32_t Dest, uint32_t Size) + { + if (m_Journal.Use) + { + DWORD written; + + TJournalEntry * data = reinterpret_cast(m_Journal.Buffer + m_Journal.BufUse); + data->Signature = 'writ'; + data->Address = Dest; + data->Size = Size; + m_Journal.BufUse += 12; + if (Size + m_Journal.BufUse < sizeof(m_Journal.Buffer) - 12) // one journal header has always to fit in + { + memcpy(m_Journal.Buffer + m_Journal.BufUse, Buf, Size); + m_Journal.BufUse += Size; + } else { + WriteFile(m_Journal.hFile, m_Journal.Buffer, m_Journal.BufUse, &written, NULL); + WriteFile(m_Journal.hFile, Buf, Size, &written, NULL); + + m_Journal.BufUse = 0; + } + } else { + _Write(Buf, Dest, Size); + } + + return true; + }; + + void Invalidate(uint32_t Dest, uint32_t Size) + { + if (m_Journal.Use) + { + DWORD written; + + TJournalEntry * data = reinterpret_cast(m_Journal.Buffer + m_Journal.BufUse); + data->Signature = 'inva'; + data->Address = Dest; + data->Size = Size; + m_Journal.BufUse += 12; + if (m_Journal.BufUse > sizeof(m_Journal.Buffer) - 12) + { + WriteFile(m_Journal.hFile, m_Journal.Buffer, m_Journal.BufUse, &written, NULL); + m_Journal.BufUse = 0; + } + } else { + _Invalidate(Dest, Size); + } + }; + + void Flush() + { + if (m_Journal.Use) + { + if (m_Journal.BufUse) + { + DWORD written; + WriteFile(m_Journal.hFile, m_Journal.Buffer, m_Journal.BufUse, &written, NULL); + m_Journal.BufUse = 0; + } + FlushFileBuffers(m_Journal.hFile); + } else { + _Flush(); + } + }; + + void UseJournal(bool UseIt) + { + m_Journal.Use = UseIt; + }; + + void CompleteTransaction() + { + if (m_Size != m_LastSize) + { + m_sigFileSizeChanged.emit(this, m_Size); + m_LastSize = m_Size; + } + }; + void CloseTransaction() + { + if (m_Journal.Use) + { + DWORD written; + + TJournalEntry * data = reinterpret_cast(m_Journal.Buffer + m_Journal.BufUse); + data->Signature = 'fini'; + data->Address = 0; + data->Size = m_Size; + + WriteFile(m_Journal.hFile, m_Journal.Buffer, m_Journal.BufUse + 12, &written, NULL); + m_Journal.BufUse = 0; + } + }; + + void CleanJournal(); + + uint32_t Size(uint32_t NewSize); + uint32_t Size() + { return m_Size; }; + void ReadOnly(bool ReadOnly) + { m_ReadOnly = ReadOnly; }; + bool ReadOnly() + { return m_ReadOnly; }; + + typedef sigslot::signal2 TOnFileSizeChanged; + + TOnFileSizeChanged & sigFileSizeChanged() + { return m_sigFileSizeChanged; }; + +protected: + TCHAR* m_FileName; + struct { + bool Use; + TCHAR* FileName; + HANDLE hFile; + + uint8_t Buffer[4096]; + uint32_t BufUse; + } m_Journal; + + uint32_t m_Size; + uint32_t m_AllocSize; + uint32_t m_AllocGranularity; + uint32_t m_MinAllocGranularity; + uint32_t m_MaxAllocGranularity; + uint32_t m_LastAllocTime; + bool m_ReadOnly; + uint32_t m_LastSize; + + TOnFileSizeChanged m_sigFileSizeChanged; + virtual uint32_t _Read(void* Buf, uint32_t Source, uint32_t Size) = 0; + virtual uint32_t _Write(void* Buf, uint32_t Dest, uint32_t Size) = 0; + virtual void _Invalidate(uint32_t Dest, uint32_t Size) = 0; + virtual uint32_t _SetSize(uint32_t Size) = 0; + virtual void _Flush() = 0; + +#pragma pack (push, 1) + typedef struct TJournalEntry + { + uint32_t Signature; + uint32_t Address; + uint32_t Size; + } TJournalEntry; +#pragma pack (pop) + + void InitJournal(); + void ProcessJournal(); +}; diff --git a/plugins/Dbx_tree/src/FileBTree.h b/plugins/Dbx_tree/src/FileBTree.h new file mode 100644 index 0000000000..3a9e58a43e --- /dev/null +++ b/plugins/Dbx_tree/src/FileBTree.h @@ -0,0 +1,102 @@ +/* + +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. + +*/ + +#pragma once +#include "BTree.h" +#include "BlockManager.h" +#include "Logger.h" + +template +class CFileBTree : public CBTree +{ +private: + +protected: + CBlockManager & m_BlockManager; + uint16_t cSignature; + + virtual void PrepareInsertOperation(); + virtual TNode * CreateNewNode(TNodeRef & NodeRef); + virtual void DeleteNode(TNodeRef Node); + virtual TNode * Read(TNodeRef Node); + virtual void Write(TNodeRef Node); +public: + CFileBTree(CBlockManager & BlockManager, typename CBTree::TNodeRef RootNode, uint16_t Signature); + virtual ~CFileBTree(); +}; + + + + +template +CFileBTree::CFileBTree(CBlockManager & BlockManager, typename CBTree::TNodeRef RootNode, uint16_t Signature) +: CBTree::CBTree(RootNode), + m_BlockManager(BlockManager) +{ + cSignature = Signature; + CBTree::m_DestroyTree = false; +} + +template +CFileBTree::~CFileBTree() +{ + CBTree::m_DestroyTree = false; +} + + +template +void CFileBTree::PrepareInsertOperation() +{ + +} + +template +typename CBTree::TNode * CFileBTree::CreateNewNode(typename CBTree::TNodeRef & NodeRef) +{ + return reinterpret_cast( m_BlockManager.CreateBlock(NodeRef, cSignature << 16, sizeof(typename CBTree::TNode) - 4) - 1); +} + +template +void CFileBTree::DeleteNode(typename CBTree::TNodeRef Node) +{ + m_BlockManager.DeleteBlock(Node); +} + +template +typename CBTree::TNode * CFileBTree::Read(typename CBTree::TNodeRef Node) +{ + uint32_t sig = 0; + uint32_t size = 0; + TNode * res = reinterpret_cast( m_BlockManager.ReadBlock(Node, size, sig) - 1); /// HACK using knowledge about the blockmanager here + + CHECK(res->Signature == cSignature, + logCRITICAL, _T("Signature check failed")); + + return res; +} + +template +void CFileBTree::Write(typename CBTree::TNodeRef Node) +{ + m_BlockManager.UpdateBlock(Node, 0); +} + diff --git a/plugins/Dbx_tree/src/Hash.cpp b/plugins/Dbx_tree/src/Hash.cpp new file mode 100644 index 0000000000..f0541c2da0 --- /dev/null +++ b/plugins/Dbx_tree/src/Hash.cpp @@ -0,0 +1,183 @@ +/* + +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 "Hash.h" + + +/// lookup3, by Bob Jenkins, May 2006, Public Domain. +#define rot(x,k) (((x)<<(k)) | ((x)>>(32-(k)))) + +#define HASHmix(a,b,c) \ +{ \ + a -= c; a ^= rot(c, 4); c += b; \ + b -= a; b ^= rot(a, 6); a += c; \ + c -= b; c ^= rot(b, 8); b += a; \ + a -= c; a ^= rot(c,16); c += b; \ + b -= a; b ^= rot(a,19); a += c; \ + c -= b; c ^= rot(b, 4); b += a; \ +} +#define HASHfinal(a,b,c) \ +{ \ + c ^= b; c -= rot(b,14); \ + a ^= c; a -= rot(c,11); \ + b ^= a; b -= rot(a,25); \ + c ^= b; c -= rot(b,16); \ + a ^= c; a -= rot(c, 4); \ + b ^= a; b -= rot(a,14); \ + c ^= b; c -= rot(b,24); \ +} + + +uint32_t Hash(const void * Data, uint32_t Length) +{ + register uint32_t a,b,c; // internal state + union { const void *ptr; uint32_t i; } u; // needed for Mac Powerbook G4 + + // Set up the internal state + a = b = c = 0xdeadbeef + Length; // + initval = 0 + + u.ptr = Data; + if ((u.i & 0x3) == 0) + { + const uint32_t *k = (const uint32_t *)Data; // read 32-bit chunks + + // all but last block: aligned reads and affect 32 bits of (a,b,c) + while (Length > 12) + { + a += k[0]; + b += k[1]; + c += k[2]; + HASHmix(a,b,c); + Length -= 12; + k += 3; + } + + switch(Length) + { + case 12: c += k[2]; b += k[1]; a += k[0]; break; + case 11: c += k[2] & 0xffffff; b += k[1]; a += k[0]; break; + case 10: c += k[2] & 0xffff; b += k[1]; a += k[0]; break; + case 9 : c += k[2] & 0xff; b += k[1]; a += k[0]; break; + case 8 : b += k[1]; a += k[0]; break; + case 7 : b += k[1] & 0xffffff; a += k[0]; break; + case 6 : b += k[1] & 0xffff; a += k[0]; break; + case 5 : b += k[1] & 0xff; a += k[0]; break; + case 4 : a += k[0]; break; + case 3 : a += k[0] & 0xffffff; break; + case 2 : a += k[0] & 0xffff; break; + case 1 : a += k[0] & 0xff; break; + case 0 : return c; // zero length strings require no mixing + } + + } else if ((u.i & 0x1) == 0) { + const uint16_t *k = (const uint16_t *)Data; /* read 16-bit chunks */ + const uint8_t *k8; + + // all but last block: aligned reads and different mixing + while (Length > 12) + { + a += k[0] + (((uint32_t)k[1]) << 16); + b += k[2] + (((uint32_t)k[3]) << 16); + c += k[4] + (((uint32_t)k[5]) << 16); + HASHmix(a,b,c); + Length -= 12; + k += 6; + } + + // handle the last (probably partial) block + k8 = (const uint8_t *)k; + switch(Length) + { + case 12: c += k[4] + (((uint32_t)k[5]) << 16); + b += k[2] + (((uint32_t)k[3]) << 16); + a += k[0] + (((uint32_t)k[1]) << 16); + break; + case 11: c += ((uint32_t)k8[10]) << 16; // fall through + case 10: c += k[4]; + b += k[2] + (((uint32_t)k[3]) << 16); + a += k[0] + (((uint32_t)k[1]) << 16); + break; + case 9 : c += k8[8]; // fall through + case 8 : b += k[2] + (((uint32_t)k[3]) << 16); + a += k[0] + (((uint32_t)k[1]) << 16); + break; + case 7 : b += ((uint32_t)k8[6]) << 16; // fall through + case 6 : b += k[2]; + a += k[0] + (((uint32_t)k[1]) << 16); + break; + case 5 : b += k8[4]; // fall through + case 4 : a += k[0] + (((uint32_t)k[1]) << 16); + break; + case 3 : a += ((uint32_t)k8[2]) << 16; // fall through + case 2 : a += k[0]; + break; + case 1 : a += k8[0]; + break; + case 0 : return c; // zero length requires no mixing + } + + } else { // need to read the key one byte at a time + const uint8_t *k = (const uint8_t *)Data; + + // all but the last block: affect some 32 bits of (a,b,c) + while (Length > 12) + { + a += k[0]; + a += ((uint32_t)k[1] ) << 8; + a += ((uint32_t)k[2] ) << 16; + a += ((uint32_t)k[3] ) << 24; + b += k[4]; + b += ((uint32_t)k[5] ) << 8; + b += ((uint32_t)k[6] ) << 16; + b += ((uint32_t)k[7] ) << 24; + c += k[8]; + c += ((uint32_t)k[9] ) << 8; + c += ((uint32_t)k[10]) << 16; + c += ((uint32_t)k[11]) << 24; + HASHmix(a,b,c); + Length -= 12; + k += 12; + } + + // last block: affect all 32 bits of (c) + switch(Length) // all the case statements fall through + { + case 12: c += ((uint32_t)k[11]) << 24; + case 11: c += ((uint32_t)k[10]) << 16; + case 10: c += ((uint32_t)k[9] ) << 8; + case 9 : c += k[8]; + case 8 : b += ((uint32_t)k[7] ) << 24; + case 7 : b += ((uint32_t)k[6] ) << 16; + case 6 : b += ((uint32_t)k[5] ) << 8; + case 5 : b += k[4]; + case 4 : a += ((uint32_t)k[3] ) << 24; + case 3 : a += ((uint32_t)k[2] ) << 16; + case 2 : a += ((uint32_t)k[1] ) << 8; + case 1 : a += k[0]; + break; + case 0 : return c; + } + } + + HASHfinal(a,b,c); + return c; +} diff --git a/plugins/Dbx_tree/src/Hash.h b/plugins/Dbx_tree/src/Hash.h new file mode 100644 index 0000000000..886e8b1485 --- /dev/null +++ b/plugins/Dbx_tree/src/Hash.h @@ -0,0 +1,29 @@ +/* + +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. + +*/ + +#ifndef _MSC_VER +#include +#else +#include "stdint.h" +#endif + +uint32_t Hash(const void * Data, uint32_t Length); diff --git a/plugins/Dbx_tree/src/Interface.h b/plugins/Dbx_tree/src/Interface.h new file mode 100644 index 0000000000..bde0a74511 --- /dev/null +++ b/plugins/Dbx_tree/src/Interface.h @@ -0,0 +1,55 @@ +/* + +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. + +*/ + +#pragma once + +#ifndef INTERFACE_VERSION_ONLY + +#define MIRANDA_VER 0x0A00 +#include +#include "newpluginapi.h" +#include "m_system.h" +#include "m_system_cpp.h" +#include "m_database.h" +#include "m_db_int.h" +#include "m_utils.h" +#include "win2k.h" + +#include "m_langpack.h" + +#include "m_dbx_tree.h" + +extern HINSTANCE hInstance; + +extern DATABASELINK gDBLink; +#endif + + +#define gVersion 0x00000012 +#define gResVersion 0,0,0,18 +#define gResVersionString "0.0.0.18" +#define gInternalName "dbx_tree" +#define gInternalNameLong "Miranda dbx_tree database driver" +#define gDescription "Provides extended Miranda database support" +#define gAutor "Michael 'Protogenes' Kunz" +#define gAutorEmail "Michael.Kunz@s2005.TU-Chemnitz.de" +#define gCopyright "2007 - 2010 Michael 'Protogenes' Kunz" diff --git a/plugins/Dbx_tree/src/IterationHeap.h b/plugins/Dbx_tree/src/IterationHeap.h new file mode 100644 index 0000000000..db06f7e695 --- /dev/null +++ b/plugins/Dbx_tree/src/IterationHeap.h @@ -0,0 +1,196 @@ +/* + +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. + +*/ + +#pragma once + +#include + +template +class CIterationHeap +{ +public: + enum TIterationType {ITForward, ITBackward}; + + CIterationHeap(TType & InitialItem, TIterationType ForBack, bool DeleteItems = true); + ~CIterationHeap(); + + bool Insert(TType & Item); + TType & Top(); + void Pop(); + +protected: + typedef struct THeapElement { + TType * Elem; + size_t Index; + } THeapElement, * PHeapElement; + + std::vector m_Heap; + TIterationType m_Type; + bool m_DeleteItems; + + bool A_b4_B(PHeapElement a, PHeapElement b); +private: + +}; + + +template +inline bool CIterationHeap::A_b4_B(PHeapElement a, PHeapElement b) +{ + if (m_Type == ITForward) + { + if ((**a->Elem) == (**b->Elem)) return a->Index < b->Index; + return (**a->Elem) < (**b->Elem); + } else { + if ((**a->Elem) == (**b->Elem)) return a->Index > b->Index; + return (**a->Elem) > (**b->Elem); + } +} + +template +CIterationHeap::CIterationHeap(TType & InitialItem, TIterationType MinMax, bool DeleteItems) +: m_Heap() +{ + m_Heap.resize(1); + m_Heap.reserve(1 << 1); + m_Type = MinMax; + + m_Heap[0] = new THeapElement; + m_Heap[0]->Elem = &InitialItem; + m_Heap[0]->Index = m_Heap.size(); + m_DeleteItems = DeleteItems; +} + +template +CIterationHeap::~CIterationHeap() +{ + unsigned int i = 0; + while ((i < m_Heap.size()) && (m_Heap[i])) + { + if (m_DeleteItems && m_Heap[i]->Elem) + delete m_Heap[i]->Elem; + + delete m_Heap[i]; + ++i; + } +} + +template +bool CIterationHeap::Insert(TType & Item) +{ + if (!Item) + return false; + + if (m_Heap.capacity() == m_Heap.size() + 1) + m_Heap.reserve(m_Heap.capacity() << 1); + + m_Heap.push_back(NULL); + + size_t way = m_Heap.capacity() >> 2; + size_t index = 0; + PHeapElement ins = new THeapElement; + ins->Elem = &Item; + ins->Index = m_Heap.size(); + + PHeapElement next; + + while ((way > 0) && (index + 1 < m_Heap.size())) + { + next = m_Heap[index]; + if ((!(*next->Elem)) || A_b4_B(ins, next)) + { + m_Heap[index] = ins; + ins = next; + } + + if (way & m_Heap.size()) //right + { + index = (index << 1) + 2; + } else { // left + index = (index << 1) + 1; + } + way = way >> 1; + } + + m_Heap[index] = ins; + + return true; +} + +template +TType & CIterationHeap::Top() +{ + return *m_Heap[0]->Elem; +} + +template +void CIterationHeap::Pop() +{ + if (m_Type == ITForward) + ++(*m_Heap[0]->Elem); + else + --(*m_Heap[0]->Elem); + + size_t index = 0; + PHeapElement ins = m_Heap[0]; + size_t big = 1; + + while ((big > 0) && (index < (m_Heap.size() >> 1))) + { + big = 0; + + if ((((index << 1) + 2) < m_Heap.size()) && (*m_Heap[(index << 1) + 2]->Elem)) + { + if (*ins->Elem) + { + if (A_b4_B(m_Heap[(index << 1) + 2], m_Heap[(index << 1) + 1])) + big = (index << 1) + 2; + else + big = (index << 1) + 1; + + } else { + m_Heap[index] = m_Heap[(index << 1) + 2]; + index = (index << 1) + 2; + m_Heap[index] = ins; + } + } else if ((((index << 1) + 1) < m_Heap.size()) && (*m_Heap[(index << 1) + 1]->Elem)) + { + if (*ins->Elem) + { + big = (index << 1) + 1; + } else { + m_Heap[index] = m_Heap[(index << 1) + 1]; + index = (index << 1) + 1; + m_Heap[index] = ins; + } + } + + if ((big > 0) && A_b4_B(m_Heap[big], ins)) + { + m_Heap[index] = m_Heap[big]; + index = big; + m_Heap[big] = ins; + } else { + big = 0; + } + } +} diff --git a/plugins/Dbx_tree/src/Logger.cpp b/plugins/Dbx_tree/src/Logger.cpp new file mode 100644 index 0000000000..551824d905 --- /dev/null +++ b/plugins/Dbx_tree/src/Logger.cpp @@ -0,0 +1,124 @@ +/* + +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 "Logger.h" +#include + +CLogger CLogger::_Instance; + +CLogger::CLogger() + : m_Length(0), + m_Level(logNOTICE) +{ + +} + +CLogger::~CLogger() +{ + for (std::vector::iterator it = m_Messages.begin(); it != m_Messages.end(); ++it) + delete [] *it; +} + +void CLogger::Append(const TCHAR * File, const TCHAR * Function, const int Line, DWORD SysState, TLevel Level, const TCHAR * Message, ...) +{ + if (m_Level < Level) + m_Level = Level; + + time_t rawtime = time(NULL); + tm timeinfo; + TCHAR timebuf[80]; + localtime_s(&timeinfo, &rawtime); + size_t len = _tcsftime(timebuf, sizeof(timebuf) / sizeof(*timebuf), _T("%c"), &timeinfo); + + TCHAR msgbuf[4096]; + va_list va; + va_start(va, Message); + len += _vstprintf_s(msgbuf, Message, va); + va_end(va); + + TCHAR * message; + if (SysState) + { + TCHAR syserror[2048]; + len += FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, SysState, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), syserror, 2048, NULL); + + len += /*_tcslen(File) + 10 +*/ _tcslen(Function) + 32 + 12 + 1; + + message = new TCHAR[len]; + m_Length += _stprintf_s(message, len, _T("[%s - %s]\n%s\n\nSystem Error Code: %d\n%s\n\n"), timebuf, /*File, Line, */ Function, msgbuf, SysState, syserror) + 1; + } else { + len += /*_tcslen(File) + 10 +*/ _tcslen(Function) + 12 + 1; + + message = new TCHAR[len]; + m_Length += _stprintf_s(message, len, _T("[%s - %s]\n%s\n\n"), timebuf, /*File, Line, */Function, msgbuf) + 1; + } + m_Messages.push_back(message); +} + +CLogger::TLevel CLogger::ShowMessage(TLevel CanAsyncTill) +{ + if (m_Messages.size() == 0) + return logNOTICE; + + TCHAR * msg = new TCHAR[m_Length]; + *msg = 0; + + for (std::vector::iterator it = m_Messages.begin(); it != m_Messages.end(); ++it) + { + _tcscat_s(msg, m_Length, *it); + delete [] *it; + } + m_Messages.clear(); + + if (m_Level <= CanAsyncTill) + { + MSGBOXPARAMS * p = new MSGBOXPARAMS; + p->cbSize = sizeof(*p); + p->hwndOwner = 0; + p->hInstance = NULL; + p->lpszText = msg; + p->lpszCaption = _T(gInternalNameLong); + p->dwStyle = MB_OK | (m_Level >= logERROR)?MB_ICONHAND:((m_Level == logWARNING)?MB_ICONWARNING:MB_ICONINFORMATION); + p->lpszIcon = NULL; + p->dwContextHelpId = 0; + p->lpfnMsgBoxCallback = NULL; + p->dwLanguageId = MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL); + + _beginthread(&CLogger::MessageBoxAsync, 0, p); + } else { + MessageBox(0, msg, _T(gInternalNameLong), MB_OK | (m_Level >= logERROR)?MB_ICONHAND:((m_Level == logWARNING)?MB_ICONWARNING:MB_ICONINFORMATION)); + delete [] msg; + } + + TLevel tmp = m_Level; + m_Level = logNOTICE; + return tmp; +} + +void CLogger::MessageBoxAsync(void * MsgBoxParams) +{ + MSGBOXPARAMS* p = reinterpret_cast(MsgBoxParams); + MessageBoxIndirect(p); + if (p->lpszText) + delete [] p->lpszText; + delete p; +} \ No newline at end of file diff --git a/plugins/Dbx_tree/src/Logger.h b/plugins/Dbx_tree/src/Logger.h new file mode 100644 index 0000000000..a97b928555 --- /dev/null +++ b/plugins/Dbx_tree/src/Logger.h @@ -0,0 +1,73 @@ +/* + +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. + +*/ + +#pragma once + +#include +#include +#include "Interface.h" + +#define WIDEN2(x) L ## x +#define WIDEN(x) WIDEN2(x) +#define __WFILE__ WIDEN(__FILE__) +#define __WFUNCTION__ WIDEN(__FUNCTION__) + + +#define LOG(Level, Message, ...) CLogger::Instance().Append(__WFILE__, __WFUNCTION__, __LINE__, 0, CLogger:: ## Level, Message, __VA_ARGS__) +#define LOGSYS(Level, Message, ...) CLogger::Instance().Append(__WFILE__, __WFUNCTION__, __LINE__, GetLastError(), CLogger:: ## Level, Message, __VA_ARGS__) + + +#define CHECK(Assertion, Level, Message, ...) if (!(Assertion)) LOG(Level, Message, __VA_ARGS__) +#define CHECKSYS(Assertion, Level, Message, ...) if (!(Assertion)) LOGSYS(Level, Message, __VA_ARGS__) + +class CLogger +{ + public: + enum TLevel + { + logNOTICE, + logWARNING, + logERROR, + logCRITICAL + }; + + CLogger(); + ~CLogger(); + + void Append(const TCHAR * File, const TCHAR * Function, const int Line, DWORD SysState, TLevel Level, const TCHAR * Message, ...); + TLevel ShowMessage(TLevel CanAsyncTill = logERROR); + + static CLogger & Instance() + { return _Instance; }; + + TLevel Level() + { return m_Level; }; + protected: + std::vector m_Messages; + size_t m_Length; + TLevel m_Level; + + static void MessageBoxAsync(void * MsgBoxParams); + private: + static CLogger _Instance; + +}; diff --git a/plugins/Dbx_tree/src/MREWSync.cpp b/plugins/Dbx_tree/src/MREWSync.cpp new file mode 100644 index 0000000000..6e08be6475 --- /dev/null +++ b/plugins/Dbx_tree/src/MREWSync.cpp @@ -0,0 +1,330 @@ +/* + +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 "MREWSync.h" +#include +#include "intrinsics.h" + +#if defined(MREW_DO_DEBUG_LOGGING) && (defined(DEBUG) || defined(_DEBUG)) + #include +#endif + + +/////////////////////////////////////////////////////////////////////////////////////////////////// +// +------------+---------------+---------------+------------+---------------+ +// | ReaderBusy | ReaderWaiting | WriterWaiting | WriterBusy | UseOddReader? | +// +------------+---------------+---------------+------------+---------------+ +// 63..44 43..24 23..4 3 0 +/////////////////////////////////////////////////////////////////////////////////////////////////// +#define isWriterBusy(Sentinel) ((Sentinel) & 0x0000000000000008ui64) +#define isWriterWaiting(Sentinel) ((Sentinel) & 0x0000000000fffff0ui64) +#define isReaderWaiting(Sentinel) ((Sentinel) & 0x00000fffff000000ui64) +#define isReaderBusy(Sentinel) ((Sentinel) & 0xfffff00000000000ui64) + +#define countWriterWaiting(Sentinel) (((Sentinel) & 0x0000000000fffff0ui64) >> 4) +#define countReaderWaiting(Sentinel) (((Sentinel) & 0x00000fffff000000ui64) >> 24) +#define countReaderBusy(Sentinel) (((Sentinel) & 0xfffff00000000000ui64) >> 44) + +#define WriterBusy (1ui64 << 3) +#define WriterWaiting (1ui64 << 4) +#define ReaderWaiting (1ui64 << 24) +#define ReaderBusy (1ui64 << 44) + +#define isUseOddReader(Sentinel) ((Sentinel) & 1) +#define useOddReader (1ui64) + +CMultiReadExclusiveWriteSynchronizer::CMultiReadExclusiveWriteSynchronizer(void) +: tls(), + m_Sentinel(0) +{ + m_ReadSignal[0] = CreateEvent(NULL, TRUE, FALSE, NULL); + m_ReadSignal[1] = CreateEvent(NULL, TRUE, FALSE, NULL); + m_WriteSignal = CreateEvent(NULL, FALSE, FALSE, NULL); + m_WriterID = 0; + m_WriteRecursion = 0; + m_Revision = 0; +} + +CMultiReadExclusiveWriteSynchronizer::~CMultiReadExclusiveWriteSynchronizer(void) +{ + BeginWrite(); + CloseHandle(m_WriteSignal); + CloseHandle(m_ReadSignal[0]); + CloseHandle(m_ReadSignal[1]); +} + +void CMultiReadExclusiveWriteSynchronizer::BeginRead() +{ + unsigned long id = GetCurrentThreadId(); + unsigned & reccount(tls.Open(this, 0)); + + reccount++; + if ((m_WriterID != id) && (reccount == 1)) + { + int64_t old; + int64_t newvalue; + + do { + old = m_Sentinel; + if (isWriterBusy(old)) + newvalue = old + ReaderBusy; // writer has lock -> we are going to enter after he leaves -> we are busy but have to wait + else if (isWriterWaiting(old)) + newvalue = old + ReaderWaiting; // writer is waiting for lock -> don't set myself busy as he waits for all readers to leave lock + else + newvalue = old + ReaderBusy; // no writer in sight, just take lock + + } while (CMPXCHG_64(m_Sentinel, newvalue, old) != old); + + + if (isWriterBusy(old) || isWriterWaiting(old)) + { + if (isUseOddReader(old)) + WaitForSingleObject(m_ReadSignal[1], INFINITE); + else + WaitForSingleObject(m_ReadSignal[0], INFINITE); + } + } +} +void CMultiReadExclusiveWriteSynchronizer::EndRead() +{ + unsigned long id = GetCurrentThreadId(); + unsigned & reccount(tls.Open(this, 1)); + reccount--; + + if ((reccount == 0) && (m_WriterID != id)) + { + int64_t old; + int64_t newvalue; + + do { + old = m_Sentinel; + if ((countReaderBusy(old) == 1) && isWriterWaiting(old)) + { // give control to the writer... move waiting readers to busy (but blocked) + newvalue = old - WriterWaiting + WriterBusy - ReaderBusy + countReaderWaiting(old) * (ReaderBusy - ReaderWaiting); + } else { + newvalue = old - ReaderBusy; + } + } while (CMPXCHG_64(m_Sentinel, newvalue, old) != old); + + if ((countReaderBusy(old) == 1) && isWriterWaiting(old)) + { + SetEvent(m_WriteSignal); + } + } + + if (reccount == 0) + tls.Remove(this); +} +bool CMultiReadExclusiveWriteSynchronizer::BeginWrite() +{ + unsigned long id = GetCurrentThreadId(); + unsigned * reccount = tls.Find(this); + bool res = true; + + if (m_WriterID != id) + { + int64_t old; + int64_t newvalue; + unsigned int oldrevision = m_Revision; + + if (reccount) // upgrade our readlock + { + do { + old = m_Sentinel; + // isWriterBusy cannot happen because we have a readlock, so we ignore it + if (countReaderBusy(old) > 1) // there is another reader.. we have to wait for him. set arriving readers to waiting state + { + newvalue = old + WriterWaiting - ReaderBusy; + } else if (isWriterWaiting(old)) // there is another writer waiting, who arrived earlier. we will sign him in and wait. we are the last reader, so we have to update the sentinel + { + newvalue = old + WriterBusy - ReaderBusy + countReaderWaiting(old) * (ReaderBusy - ReaderWaiting); + } else { // nobody is busy, we want the lock + newvalue = old + WriterBusy - ReaderBusy; + } + } while (CMPXCHG_64(m_Sentinel, newvalue, old) != old); + + if (countReaderBusy(old) > 1) + { + WaitForSingleObject(m_WriteSignal, INFINITE); // someone woke me up... he had to take care of all state changes of the sentinel + } else if (isWriterWaiting(old)) // we will wait for the other writer, as we are the last reader, we have to wake him up + { + SetEvent(m_WriteSignal); + Sleep(0); // yield thread trying to keep FIFO order + WaitForSingleObject(m_WriteSignal, INFINITE); // someone woke me up... he had to take care of all state changes of the sentinel + } + } else { // gain write lock + do { + old = m_Sentinel; + if (isWriterBusy(old)) // there is a writer.. we have to wait for him + { + newvalue = old + WriterWaiting; + } else if (isReaderBusy(old)) // there is a reader.. we have to wait for him. set arriving readers to waiting state + { + newvalue = old + WriterWaiting; + } else if (isWriterWaiting(old)) // there is another writer waiting, who arrived earlier. we will wait + { + newvalue = old + WriterWaiting; + } else { // nobody is busy, we want the lock + newvalue = old + WriterBusy; + } + } while (CMPXCHG_64(m_Sentinel, newvalue, old) != old); + + if (isWriterBusy(old) || isReaderBusy(old) || isWriterWaiting(old)) + { + WaitForSingleObject(m_WriteSignal, INFINITE); // someone woke me up... he had to take care of all state changes of the sentinel + } + } + res = (oldrevision == (INC_32(m_Revision) - 1)); + + m_WriterID = id; + } + m_WriteRecursion++; + + return res; +} + +bool CMultiReadExclusiveWriteSynchronizer::EndWrite() +{ + unsigned long id = GetCurrentThreadId(); + unsigned * reccount = tls.Find(this); + + m_WriteRecursion--; + + if (m_WriteRecursion == 0) + { + int64_t old; + int64_t newvalue; + + m_WriterID = 0; + + if (isUseOddReader(m_Sentinel)) // reset upcoming signal + ResetEvent(m_ReadSignal[0]); + else + ResetEvent(m_ReadSignal[1]); + + if (reccount) // downgrade to reader lock + { + do { + old = m_Sentinel; + newvalue = (old ^ useOddReader) - WriterBusy + ReaderBusy; // single case... we are a waiting reader and we will keep control of the lock + } while (CMPXCHG_64(m_Sentinel, newvalue, old) != old); + + if (isUseOddReader(old)) // allow additional readers to pass + SetEvent(m_ReadSignal[1]); + else + SetEvent(m_ReadSignal[0]); + + } else { + + do { + old = m_Sentinel; + if (isReaderBusy(old)) // give control to waiting readers + { + newvalue = (old ^ useOddReader) - WriterBusy; + } else if (isWriterWaiting(old)) // no reader arrived while i was working... give control to next writer + { + newvalue = (old ^ useOddReader) - WriterWaiting; + } else { // nobody else is there... just close lock + newvalue = (old ^ useOddReader) - WriterBusy; + } + } while (CMPXCHG_64(m_Sentinel, newvalue, old) != old); + + if (isReaderBusy(old)) // release waiting readers + { + if (isUseOddReader(old)) + SetEvent(m_ReadSignal[1]); + else + SetEvent(m_ReadSignal[0]); + } else if (isWriterWaiting(old)) + { + SetEvent(m_WriteSignal); + } + } + return true; + } + + return false; +} + +bool CMultiReadExclusiveWriteSynchronizer::TryBeginWrite() +{ + unsigned long id = GetCurrentThreadId(); + unsigned * reccount = tls.Find(this); + + if (m_WriterID != id) + { + int64_t old; + int64_t newvalue; + unsigned int oldrevision = m_Revision; + + if (reccount) // upgrade our readlock + { + do { + old = m_Sentinel; + // isWriterBusy cannot happen because we have a readlock, so we ignore it + if (countReaderBusy(old) > 1) // there is another reader.. we have to wait for him. set arriving readers to waiting state + { + return false; + } else if (isWriterWaiting(old)) // there is another writer waiting, who arrived earlier. we will sign him in and wait. we are the last reader, so we have to update the sentinel + { + return false; + } else { // nobody is busy, we want the lock + newvalue = old + WriterBusy - ReaderBusy; + } + } while (CMPXCHG_64(m_Sentinel, newvalue, old) != old); + + } else { // gain write lock + do { + old = m_Sentinel; + if (isWriterBusy(old)) // there is a writer.. we have to wait for him + { + return false; + } else if (isReaderBusy(old)) // there is a reader.. we have to wait for him. set arriving readers to waiting state + { + return false; + } else if (isWriterWaiting(old)) // there is another writer waiting, who arrived earlier. we will wait + { + return false; + } else { // nobody is busy, we want the lock + newvalue = old + WriterBusy; + } + } while (CMPXCHG_64(m_Sentinel, newvalue, old) != old); + } + INC_32(m_Revision); + + m_WriterID = id; + } + m_WriteRecursion++; + + return true; +} + +unsigned int CMultiReadExclusiveWriteSynchronizer::Waiting() +{ + int64_t old = m_Sentinel; + if (isWriterBusy(old)) + { // cast is safe, we don't loose data because these fields are max 20 bits + return static_cast(countReaderBusy(old) + countReaderWaiting(old) + countWriterWaiting(old)); + } else { + return static_cast(countReaderWaiting(old) + countWriterWaiting(old)); + } +}; diff --git a/plugins/Dbx_tree/src/MREWSync.h b/plugins/Dbx_tree/src/MREWSync.h new file mode 100644 index 0000000000..2ffcbc08d7 --- /dev/null +++ b/plugins/Dbx_tree/src/MREWSync.h @@ -0,0 +1,55 @@ +/* + +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. + +*/ + +#pragma once + +#include +#include "TLS.h" +#include "stdint.h" + +class CMultiReadExclusiveWriteSynchronizer +{ +private: + uint64_t volatile m_Sentinel; + HANDLE m_ReadSignal[2]; + HANDLE m_WriteSignal; + + volatile uint32_t m_Revision; + unsigned int m_WriterID; + unsigned int m_WriteRecursion; + + CThreadLocalStorage tls; + +public: + CMultiReadExclusiveWriteSynchronizer(); + virtual ~CMultiReadExclusiveWriteSynchronizer(); + + void BeginRead(); + void EndRead(); + bool BeginWrite(); + bool TryBeginWrite(); + bool EndWrite(); + + unsigned int Waiting(); + unsigned int WriteRecursionCount() {return m_WriteRecursion;}; + +}; diff --git a/plugins/Dbx_tree/src/MappedMemory.cpp b/plugins/Dbx_tree/src/MappedMemory.cpp new file mode 100644 index 0000000000..09a1471a90 --- /dev/null +++ b/plugins/Dbx_tree/src/MappedMemory.cpp @@ -0,0 +1,167 @@ +/* + +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 "MappedMemory.h" +#include "Logger.h" + +typedef BOOL (WINAPI *TUnmapViewOfFile)(LPCVOID); +typedef BOOL (WINAPI *TFlushViewOfFile)(LPCVOID, SIZE_T); +typedef HANDLE (WINAPI *TCreateFileMappingA)(HANDLE, LPSECURITY_ATTRIBUTES, DWORD, DWORD, DWORD, LPCSTR); +typedef LPVOID (WINAPI *TMapViewOfFile)(HANDLE, DWORD, DWORD, DWORD, SIZE_T); + +HMODULE myKernelLib = NULL; +TUnmapViewOfFile myUnmapViewOfFile = NULL; +TFlushViewOfFile myFlushViewOfFile = NULL; +TCreateFileMappingA myCreateFileMappingA = NULL; +TMapViewOfFile myMapViewOfFile = NULL; + +bool CMappedMemory::InitMMAP() +{ + if (!myKernelLib) + myKernelLib = GetModuleHandleA("kernel32.dll"); // is always loaded + + if (myKernelLib) + { + myUnmapViewOfFile = (TUnmapViewOfFile) GetProcAddress(myKernelLib, "UnmapViewOfFile"); + myFlushViewOfFile = (TFlushViewOfFile) GetProcAddress(myKernelLib, "FlushViewOfFile"); + myCreateFileMappingA = (TCreateFileMappingA) GetProcAddress(myKernelLib, "CreateFileMappingA"); + myMapViewOfFile = (TMapViewOfFile) GetProcAddress(myKernelLib, "MapViewOfFile"); + } + + return myUnmapViewOfFile && myFlushViewOfFile && myCreateFileMappingA && myMapViewOfFile; +} +CMappedMemory::CMappedMemory(const TCHAR* FileName) +: CFileAccess(FileName) +{ + SYSTEM_INFO sysinfo; + + m_AllocSize = 0; + m_DirectFile = 0; + m_FileMapping = 0; + m_Base = NULL; + + GetSystemInfo(&sysinfo); + m_AllocGranularity = sysinfo.dwAllocationGranularity; // usually 64kb + m_MinAllocGranularity = m_AllocGranularity; // must be at least one segment + m_MaxAllocGranularity = m_AllocGranularity << 4; // usually 1mb for fast increasing + + m_DirectFile = CreateFile(FileName, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS, 0); + if (m_DirectFile == INVALID_HANDLE_VALUE) + LOGSYS(logCRITICAL, _T("CreateFile failed")); + + uint32_t size = GetFileSize(m_DirectFile, NULL); + size = (size + m_AllocGranularity - 1) & ~(m_AllocGranularity - 1); + + if (size == 0) + size = m_AllocGranularity; + + _SetSize(size); + m_AllocSize = size; + + InitJournal(); +} + +CMappedMemory::~CMappedMemory() +{ + if (m_Base) + { + myFlushViewOfFile(m_Base, NULL); + myUnmapViewOfFile(m_Base); + } + if (m_FileMapping) + CloseHandle(m_FileMapping); + + if (m_DirectFile) + { + if (INVALID_SET_FILE_POINTER != SetFilePointer(m_DirectFile, m_Size, NULL, FILE_BEGIN)) + SetEndOfFile(m_DirectFile); + + FlushFileBuffers(m_DirectFile); + CloseHandle(m_DirectFile); + } +} + + +uint32_t CMappedMemory::_Read(void* Buf, uint32_t Source, uint32_t Size) +{ + memcpy(Buf, m_Base + Source, Size); + return Size; +} +uint32_t CMappedMemory::_Write(void* Buf, uint32_t Dest, uint32_t Size) +{ + memcpy(m_Base + Dest, Buf, Size); + return Size; +} + +uint32_t CMappedMemory::_SetSize(uint32_t Size) +{ + if (m_Base) + { + myFlushViewOfFile(m_Base, 0); + myUnmapViewOfFile(m_Base); + } + if (m_FileMapping) + CloseHandle(m_FileMapping); + + m_Base = NULL; + m_FileMapping = NULL; + + if (INVALID_SET_FILE_POINTER == SetFilePointer(m_DirectFile, Size, NULL, FILE_BEGIN)) + { + LOGSYS(logERROR, _T("SetFilePointer failed")); + return 0; + } + + if (!SetEndOfFile(m_DirectFile)) + { + LOGSYS(logERROR, _T("Cannot set end of file")); + return 0; + } + + m_FileMapping = myCreateFileMappingA(m_DirectFile, NULL, PAGE_READWRITE, 0, Size, NULL); + + if (!m_FileMapping) + { + LOGSYS(logERROR, _T("CreateFileMapping failed")); + return 0; + } + + m_Base = (uint8_t*) myMapViewOfFile(m_FileMapping, FILE_MAP_ALL_ACCESS, 0, 0, 0); + if (!m_Base) + { + LOGSYS(logERROR, _T("MapViewOfFile failed")); + return 0; + } + + return Size; +} + +void CMappedMemory::_Invalidate(uint32_t Dest, uint32_t Size) +{ + memset(m_Base + Dest, 0, Size); +} + +void CMappedMemory::_Flush() +{ + myFlushViewOfFile(m_Base, NULL); + FlushFileBuffers(m_DirectFile); +} diff --git a/plugins/Dbx_tree/src/MappedMemory.h b/plugins/Dbx_tree/src/MappedMemory.h new file mode 100644 index 0000000000..e66862836e --- /dev/null +++ b/plugins/Dbx_tree/src/MappedMemory.h @@ -0,0 +1,47 @@ +/* + +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. + +*/ + +#pragma once + +#include +#include "FileAccess.h" + +class CMappedMemory : public CFileAccess +{ +private: + uint8_t* m_Base; + + HANDLE m_DirectFile; + HANDLE m_FileMapping; +protected: + + uint32_t _Read(void* Buf, uint32_t Source, uint32_t Size); + uint32_t _Write(void* Buf, uint32_t Dest, uint32_t Size); + void _Invalidate(uint32_t Dest, uint32_t Size); + uint32_t _SetSize(uint32_t Size); + void _Flush(); +public: + CMappedMemory(const TCHAR* FileName); + virtual ~CMappedMemory(); + + static bool InitMMAP(); +}; diff --git a/plugins/Dbx_tree/src/SHA256.cpp b/plugins/Dbx_tree/src/SHA256.cpp new file mode 100644 index 0000000000..9ca7df329c --- /dev/null +++ b/plugins/Dbx_tree/src/SHA256.cpp @@ -0,0 +1,301 @@ +/* + +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 "SHA256.h" +#include +#include + +#if !defined(_MSC_VER) || !defined(_M_IX86) +#define NO_ASM +#endif +#define SHA_LOOPUNROLL + +#ifndef _MSC_VER + #define rotr(x,n) (((x)>>(n))|((x)<<(32-(n)))) +#else + #define rotr(x,n) _lrotr(x,n) +#endif + + +// table of round constants +// (first 32 bits of the fractional parts of the cube roots of the first 64 primes 2..311): +static const uint32_t cKey[64] = { + 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, + 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, + 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, + 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, + 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, + 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, + 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, + 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, + 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, + 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, + 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, + 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, + 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, + 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, + 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, + 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 +}; + +// initialisation vector +// (first 32 bits of the fractional parts of the square roots of the first 8 primes 2..19): +static const SHA256::THash cHashInit = { + 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19 +}; + + + +SHA256::SHA256() +{ + SHAInit(); +} +SHA256::~SHA256() +{ + +} +void SHA256::SHAInit() +{ + memcpy(m_Hash, cHashInit, sizeof(m_Hash)); + m_Length = 0; +} +void SHA256::SHAUpdate(void * Data, uint32_t Length) +{ + uint8_t * dat = (uint8_t *)Data; + uint32_t len = Length; + + if (m_Length & 63) + { + uint32_t p = (m_Length & 63); + uint32_t pl = 64 - p; + if (pl > len) + pl = len; + + memcpy(&(m_Block[p]), dat, pl); + len -= pl; + dat += pl; + + if (p + pl == 64) + SHABlock(); + } + + while (len >= 64) + { + memcpy(m_Block, dat, sizeof(m_Block)); + SHABlock(); + len -= 64; + dat += 64; + } + + if (len > 0) + { + memcpy(m_Block, dat, len); + } + + m_Length += Length; +} + +void SHA256::SHAFinal(SHA256::THash & Hash) +{ + uint8_t pad[128] = { + 0x80, 0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0 + }; + + uint32_t padlen = 0; + if ((m_Length & 63) < 55) // 64 - 9 -> short padding + { + padlen = 64 - (m_Length & 63); + } else { + padlen = 128 - (m_Length & 63); + } + + uint64_t l = m_Length << 3; + { + uint8_t * p = (uint8_t *) &l; +#ifdef NO_ASM + pad[padlen - 1] = (uint8_t)(p[0]); + pad[padlen - 2] = (uint8_t)(p[1]); + pad[padlen - 3] = (uint8_t)(p[2]); + pad[padlen - 4] = (uint8_t)(p[3]); + pad[padlen - 5] = (uint8_t)(p[4]); + pad[padlen - 6] = (uint8_t)(p[5]); + pad[padlen - 7] = (uint8_t)(p[6]); + pad[padlen - 8] = (uint8_t)(p[7]); +#else + uint8_t * p2 = (uint8_t *) &(pad[padlen - 8]); + __asm { + MOV ebx, p + MOV eax, [ebx] + BSWAP eax + MOV edx, [ebx + 4] + MOV ebx, p2 + BSWAP edx + MOV [ebx + 4], eax + MOV [ebx], edx + } +#endif + } + + SHAUpdate((uint32_t *)pad, padlen); + + { + uint8_t * h = (uint8_t *)Hash; + uint8_t * m = (uint8_t *)m_Hash; +#ifdef NO_ASM + for (int i = 0; i < 32; i += 4) + { + h[i] = m[i + 3]; + h[i + 1] = m[i + 2]; + h[i + 2] = m[i + 1]; + h[i + 3] = m[i]; + } +#else + __asm { + MOV esi, m + MOV edi, h + MOV ecx, 8 + loop_label: + LODSD + BSWAP eax + STOSD + dec ecx + jnz loop_label + } +#endif + } + + SHAInit(); +} + +#define SHA256_ROUND(a,b,c,d,e,f,g,h, i) { \ +t1 = (h) + (rotr((e), 6) ^ rotr((e), 11) ^ rotr((e), 25)) + \ + (((e) & (f)) ^ ((~(e)) & (g))) + cKey[i] + w[i]; \ +t2 = (rotr((a), 2) ^ rotr((a), 13) ^ rotr((a), 22)) + \ + (((a) & (b)) ^ ((a) & (c)) ^ ((b) & (c))); \ +d += t1; \ +h = t1 + t2; \ +} + +void SHA256::SHABlock() +{ + uint32_t w[64]; + + // make Big Endian + { + uint8_t * d = (uint8_t *)w; + uint8_t * s = (uint8_t *)m_Block; +#ifdef NO_ASM + for (int i = 0; i < 64; i += 4) + { + d[i] = s[i + 3]; + d[i + 1] = s[i + 2]; + d[i + 2] = s[i + 1]; + d[i + 3] = s[i]; + } +#else + __asm { + MOV esi, s + MOV edi, d + MOV ecx, 16 + loop_label: + LODSD + BSWAP eax + STOSD + dec ecx + jnz loop_label + } +#endif + } + + uint32_t t1, t2, a,b,c,d,e,f,g,h; + for (uint32_t i = 16; i < 64; ++i) + { + t1 = w[i-15]; + t2 = w[i-2]; + w[i] = w[i-16] + (rotr(t1, 7) ^ rotr(t1, 18) ^ (t1 >> 3)) + w[i-7] + (rotr(t2, 17) ^ rotr(t2, 19) ^ (t2 >> 10)); + } + + a = m_Hash[0]; + b = m_Hash[1]; + c = m_Hash[2]; + d = m_Hash[3]; + e = m_Hash[4]; + f = m_Hash[5]; + g = m_Hash[6]; + h = m_Hash[7]; + +#ifdef SHA_LOOPUNROLL + for (uint32_t i = 0; i < 64; ++i) + { + SHA256_ROUND(a,b,c,d,e,f,g,h,i); ++i; + SHA256_ROUND(h,a,b,c,d,e,f,g,i); ++i; + SHA256_ROUND(g,h,a,b,c,d,e,f,i); ++i; + SHA256_ROUND(f,g,h,a,b,c,d,e,i); ++i; + SHA256_ROUND(e,f,g,h,a,b,c,d,i); ++i; + SHA256_ROUND(d,e,f,g,h,a,b,c,i); ++i; + SHA256_ROUND(c,d,e,f,g,h,a,b,i); ++i; + SHA256_ROUND(b,c,d,e,f,g,h,a,i); + } +#else + for (uint32_t i = 0; i < 64; ++i) + { + t1 = h + (rotr(e, 6) ^ rotr(e, 11) ^ rotr(e, 25)) + //s1 + ((e & f) ^ ((~e) & g)) + cKey[i] + w[i]; //ch + + t2 = (rotr(a, 2) ^ rotr(a, 13) ^ rotr(a, 22)) + //s0 + ((a & b) ^ (a & c) ^ (b & c)); //maj + + h = g; + g = f; + f = e; + e = d + t1; + d = c; + c = b; + b = a; + a = t1 + t2; + } +#endif + + m_Hash[0] += a; + m_Hash[1] += b; + m_Hash[2] += c; + m_Hash[3] += d; + m_Hash[4] += e; + m_Hash[5] += f; + m_Hash[6] += g; + m_Hash[7] += h; +} diff --git a/plugins/Dbx_tree/src/SHA256.h b/plugins/Dbx_tree/src/SHA256.h new file mode 100644 index 0000000000..a9629e6a2a --- /dev/null +++ b/plugins/Dbx_tree/src/SHA256.h @@ -0,0 +1,49 @@ +/* + +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. + +*/ + +#ifndef _MSC_VER +#include +#else +#include "stdint.h" +#endif + + +class SHA256 +{ +public: + typedef uint32_t THash[8]; + + SHA256(); + ~SHA256(); + + void SHAInit(); + void SHAUpdate(void * Data, uint32_t Length); + void SHAFinal(THash & Hash); +private: + THash m_Hash; + uint64_t m_Length; /// Datalength in byte + + uint8_t m_Block[64]; + + void SHABlock(); + void Swap64(void * Addr); +}; diff --git a/plugins/Dbx_tree/src/Services.cpp b/plugins/Dbx_tree/src/Services.cpp new file mode 100644 index 0000000000..d8b734795d --- /dev/null +++ b/plugins/Dbx_tree/src/Services.cpp @@ -0,0 +1,402 @@ +/* + +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 "Services.h" + +HANDLE gServices[40] = {0}; + +INT_PTR DBEntityGetRoot(WPARAM wParam, LPARAM lParam) +{ + return gDataBase->getEntities().getRootEntity(); +} +INT_PTR DBEntityChildCount(WPARAM hEntity, LPARAM lParam) +{ + if (hEntity == 0) + hEntity = gDataBase->getEntities().getRootEntity(); + + return gDataBase->getEntities().getChildCount(hEntity); +} +INT_PTR DBEntityGetParent(WPARAM hEntity, LPARAM lParam) +{ + if (hEntity == 0) + hEntity = gDataBase->getEntities().getRootEntity(); + + return gDataBase->getEntities().getParent(hEntity); +} +INT_PTR DBEntityMove(WPARAM hEntity, LPARAM hParent) +{ + if ((hEntity == 0) || (hEntity == gDataBase->getEntities().getRootEntity())) + return DBT_INVALIDPARAM; + + if (hParent == 0) + hParent = gDataBase->getEntities().getRootEntity(); + + return gDataBase->getEntities().setParent(hEntity, hParent); +} +INT_PTR DBEntityGetFlags(WPARAM hEntity, LPARAM lParam) +{ + if (hEntity == 0) + hEntity = gDataBase->getEntities().getRootEntity(); + + return gDataBase->getEntities().getFlags(hEntity); +} +INT_PTR DBEntityIterInit(WPARAM pFilter, LPARAM hParent) +{ + TDBTEntityIterFilter fil = {0,0,0,0}; + if (pFilter == NULL) + { + pFilter = reinterpret_cast(&fil); + fil.cbSize = sizeof(fil); + } + + if (reinterpret_cast(pFilter)->cbSize != sizeof(TDBTEntityIterFilter)) + return DBT_INVALIDPARAM; + + if (reinterpret_cast(pFilter)->fDontHasFlags & ((PDBTEntityIterFilter)pFilter)->fHasFlags) + return DBT_INVALIDPARAM; + + if (hParent == 0) + hParent = gDataBase->getEntities().getRootEntity(); + + return gDataBase->getEntities().IterationInit(*reinterpret_cast(pFilter), hParent); +} +INT_PTR DBEntityIterNext(WPARAM hIteration, LPARAM lParam) +{ + if ((hIteration == 0) || (hIteration == DBT_INVALIDPARAM)) + return hIteration; + + return gDataBase->getEntities().IterationNext(hIteration); +} +INT_PTR DBEntityIterClose(WPARAM hIteration, LPARAM lParam) +{ + if ((hIteration == 0) || (hIteration == DBT_INVALIDPARAM)) + return hIteration; + + return gDataBase->getEntities().IterationClose(hIteration); +} +INT_PTR DBEntityDelete(WPARAM hEntity, LPARAM lParam) +{ + if ((hEntity == 0) || (hEntity == gDataBase->getEntities().getRootEntity())) + return DBT_INVALIDPARAM; + + return gDataBase->getEntities().DeleteEntity(hEntity); +} +INT_PTR DBEntityCreate(WPARAM pEntity, LPARAM lParam) +{ + if (reinterpret_cast(pEntity)->bcSize != sizeof(TDBTEntity)) + return DBT_INVALIDPARAM; + + if (reinterpret_cast(pEntity)->hParentEntity == 0) + reinterpret_cast(pEntity)->hParentEntity = gDataBase->getEntities().getRootEntity(); + + reinterpret_cast(pEntity)->fFlags = reinterpret_cast(pEntity)->fFlags & ~(DBT_NF_IsRoot | DBT_NF_HasChildren | DBT_NF_IsVirtual | DBT_NF_HasVirtuals); // forbidden flags... + return gDataBase->getEntities().CreateEntity(*reinterpret_cast(pEntity)); +} + +INT_PTR DBEntityGetAccount(WPARAM hEntity, LPARAM lParam) +{ + return gDataBase->getEntities().getAccount(hEntity); +} + +INT_PTR DBVirtualEntityCreate(WPARAM hEntity, LPARAM hParent) +{ + if ((hEntity == 0) || (hEntity == gDataBase->getEntities().getRootEntity())) + return DBT_INVALIDPARAM; + + if (hParent == 0) + hParent = gDataBase->getEntities().getRootEntity(); + + return gDataBase->getEntities().VirtualCreate(hEntity, hParent); +} +INT_PTR DBVirtualEntityGetParent(WPARAM hVirtualEntity, LPARAM lParam) +{ + if ((hVirtualEntity == 0) || (hVirtualEntity == gDataBase->getEntities().getRootEntity())) + return DBT_INVALIDPARAM; + + return gDataBase->getEntities().VirtualGetParent(hVirtualEntity); +} +INT_PTR DBVirtualEntityGetFirst(WPARAM hEntity, LPARAM lParam) +{ + if ((hEntity == 0) || (hEntity == gDataBase->getEntities().getRootEntity())) + return DBT_INVALIDPARAM; + + return gDataBase->getEntities().VirtualGetFirst(hEntity); +} +INT_PTR DBVirtualEntityGetNext(WPARAM hVirtualEntity, LPARAM lParam) +{ + if ((hVirtualEntity == 0) || (hVirtualEntity == gDataBase->getEntities().getRootEntity())) + return DBT_INVALIDPARAM; + + return gDataBase->getEntities().VirtualGetNext(hVirtualEntity); +} + + +INT_PTR DBSettingFind(WPARAM pSettingDescriptor, LPARAM lParam) +{ + if (pSettingDescriptor == NULL) + return DBT_INVALIDPARAM; + + if (reinterpret_cast(pSettingDescriptor)->cbSize != sizeof(TDBTSettingDescriptor)) + return DBT_INVALIDPARAM; + + if (reinterpret_cast(pSettingDescriptor)->pszSettingName == NULL) + return DBT_INVALIDPARAM; + + return gDataBase->getSettings().FindSetting(*reinterpret_cast(pSettingDescriptor)); +} +INT_PTR DBSettingDelete(WPARAM pSettingDescriptor, LPARAM lParam) +{ + if (pSettingDescriptor == NULL) + return DBT_INVALIDPARAM; + + if (reinterpret_cast(pSettingDescriptor)->cbSize != sizeof(TDBTSettingDescriptor)) + return DBT_INVALIDPARAM; + + if (reinterpret_cast(pSettingDescriptor)->pszSettingName == NULL) + return DBT_INVALIDPARAM; + + return gDataBase->getSettings().DeleteSetting(*reinterpret_cast(pSettingDescriptor)); +} +INT_PTR DBSettingDeleteHandle(WPARAM hSetting, LPARAM lParam) +{ + if (hSetting == 0) + return DBT_INVALIDPARAM; + + return gDataBase->getSettings().DeleteSetting(hSetting); +} +INT_PTR DBSettingWrite(WPARAM pSetting, LPARAM lParam) +{ + if (pSetting == NULL) + return DBT_INVALIDPARAM; + + if (reinterpret_cast(pSetting)->cbSize != sizeof(TDBTSetting)) + return DBT_INVALIDPARAM; + + if (reinterpret_cast(pSetting)->Descriptor == NULL) + return DBT_INVALIDPARAM; + + if (reinterpret_cast(pSetting)->Descriptor->cbSize != sizeof(TDBTSettingDescriptor)) + return DBT_INVALIDPARAM; + + if (reinterpret_cast(pSetting)->Descriptor->pszSettingName == NULL) + return DBT_INVALIDPARAM; + + if ((reinterpret_cast(pSetting)->Type & DBT_STF_VariableLength) && (reinterpret_cast(pSetting)->Value.pBlob == NULL)) + return DBT_INVALIDPARAM; + + return gDataBase->getSettings().WriteSetting(*reinterpret_cast(pSetting)); +} +INT_PTR DBSettingWriteHandle(WPARAM pSetting, LPARAM hSetting) +{ + if (pSetting == NULL) + return DBT_INVALIDPARAM; + + if (reinterpret_cast(pSetting)->cbSize != sizeof(TDBTSetting)) + return DBT_INVALIDPARAM; + + return gDataBase->getSettings().WriteSetting(*reinterpret_cast(pSetting), hSetting); +} +INT_PTR DBSettingRead(WPARAM pSetting, LPARAM lParam) +{ + if (pSetting == NULL) + return DBT_INVALIDPARAM; + + if (reinterpret_cast(pSetting)->cbSize != sizeof(TDBTSetting)) + return DBT_INVALIDPARAM; + + if (reinterpret_cast(pSetting)->Descriptor == NULL) + return DBT_INVALIDPARAM; + + if (reinterpret_cast(pSetting)->Descriptor->cbSize != sizeof(TDBTSettingDescriptor)) + return DBT_INVALIDPARAM; + + if (reinterpret_cast(pSetting)->Descriptor->pszSettingName == NULL) + return DBT_INVALIDPARAM; + + return gDataBase->getSettings().ReadSetting(*reinterpret_cast(pSetting)); +} +INT_PTR DBSettingReadHandle(WPARAM pSetting, LPARAM hSetting) +{ + if ((pSetting == NULL) || (hSetting == 0)) + return DBT_INVALIDPARAM; + + if (reinterpret_cast(pSetting)->cbSize != sizeof(TDBTSetting)) + return DBT_INVALIDPARAM; + + if ((reinterpret_cast(pSetting)->Descriptor != NULL) && (reinterpret_cast(pSetting)->Descriptor->cbSize != sizeof(TDBTSettingDescriptor))) + return DBT_INVALIDPARAM; + + return gDataBase->getSettings().ReadSetting(*((PDBTSetting)pSetting), hSetting); +} +INT_PTR DBSettingIterInit(WPARAM pFilter, LPARAM lParam) +{ + if (pFilter == NULL) + return DBT_INVALIDPARAM; + + if (reinterpret_cast(pFilter)->cbSize != sizeof(TDBTSettingIterFilter)) + return DBT_INVALIDPARAM; + + if ((reinterpret_cast(pFilter)->Descriptor != NULL) && (reinterpret_cast(pFilter)->Descriptor->cbSize != sizeof(TDBTSettingDescriptor))) + return DBT_INVALIDPARAM; + + if ((reinterpret_cast(pFilter)->Setting != NULL) && (reinterpret_cast(pFilter)->Setting->cbSize != sizeof(TDBTSetting))) + return DBT_INVALIDPARAM; + + if ((reinterpret_cast(pFilter)->Setting != NULL) && (reinterpret_cast(pFilter)->Setting->Descriptor != NULL) && (reinterpret_cast(pFilter)->Setting->Descriptor->cbSize != sizeof(TDBTSettingIterFilter))) + return DBT_INVALIDPARAM; + + return gDataBase->getSettings().IterationInit(*reinterpret_cast(pFilter)); +} +INT_PTR DBSettingIterNext(WPARAM hIteration, LPARAM lParam) +{ + if ((hIteration == 0) || (hIteration == DBT_INVALIDPARAM)) + return hIteration; + + return gDataBase->getSettings().IterationNext(hIteration); +} +INT_PTR DBSettingIterClose(WPARAM hIteration, LPARAM lParam) +{ + if ((hIteration == 0) || (hIteration == DBT_INVALIDPARAM)) + return hIteration; + + return gDataBase->getSettings().IterationClose(hIteration); +} + +INT_PTR DBEventGetBlobSize(WPARAM hEvent, LPARAM lParam) +{ + return gDataBase->getEvents().GetBlobSize(hEvent); +} + +INT_PTR DBEventGet(WPARAM hEvent, LPARAM pEvent) +{ + if ((pEvent == NULL) || (reinterpret_cast(pEvent)->cbSize != sizeof(TDBTEvent))) + return DBT_INVALIDPARAM; + + return gDataBase->getEvents().Get(hEvent, *reinterpret_cast(pEvent)); +} + +INT_PTR DBEventGetCount(WPARAM hEntity, LPARAM lParam) +{ + return gDataBase->getEvents().GetCount(hEntity); +} + +INT_PTR DBEventDelete(WPARAM hEvent, LPARAM lParam) +{ + return gDataBase->getEvents().Delete(hEvent); +} + +INT_PTR DBEventAdd(WPARAM hEntity, LPARAM pEvent) +{ + if ((pEvent == NULL) || (reinterpret_cast(pEvent)->cbSize != sizeof(TDBTEvent)) || (reinterpret_cast(pEvent)->pBlob == NULL) || (reinterpret_cast(pEvent)->cbBlob == 0)) + return DBT_INVALIDPARAM; + + return gDataBase->getEvents().Add(hEntity, *((PDBTEvent)pEvent)); +} + +INT_PTR DBEventMarkRead(WPARAM hEvent, LPARAM lParam) +{ + return gDataBase->getEvents().MarkRead(hEvent); +} + +INT_PTR DBEventWriteToDisk(WPARAM hEvent, LPARAM lParam) +{ + return gDataBase->getEvents().WriteToDisk(hEvent); +} + +INT_PTR DBEventGetEntity(WPARAM hEvent, LPARAM lParam) +{ + return gDataBase->getEvents().getEntity(hEvent); +} + +INT_PTR DBEventIterInit(WPARAM pFilter, LPARAM lParam) +{ + if ((pFilter == NULL) || (reinterpret_cast(pFilter)->cbSize != sizeof(TDBTEventIterFilter))) + return DBT_INVALIDPARAM; + + if ((reinterpret_cast(pFilter)->Event != NULL) && (reinterpret_cast(pFilter)->Event->cbSize != sizeof(TDBTEvent))) + return DBT_INVALIDPARAM; + + return gDataBase->getEvents().IterationInit(*reinterpret_cast(pFilter)); +} + +INT_PTR DBEventIterNext(WPARAM hIteration, LPARAM lParam) +{ + if ((hIteration == 0) || (hIteration == DBT_INVALIDPARAM)) + return hIteration; + + return gDataBase->getEvents().IterationNext(hIteration); +} + +INT_PTR DBEventIterClose(WPARAM hIteration, LPARAM lParam) +{ + if ((hIteration == 0) || (hIteration == DBT_INVALIDPARAM)) + return hIteration; + + return gDataBase->getEvents().IterationClose(hIteration); +} + + +bool RegisterServices() +{ + gServices[ 0] = CreateServiceFunction(MS_DBT_ENTITY_GETROOT, DBEntityGetRoot); + gServices[ 1] = CreateServiceFunction(MS_DBT_ENTITY_CHILDCOUNT, DBEntityChildCount); + gServices[ 2] = CreateServiceFunction(MS_DBT_ENTITY_GETPARENT, DBEntityGetParent); + gServices[ 3] = CreateServiceFunction(MS_DBT_ENTITY_MOVE, DBEntityMove); + gServices[ 8] = CreateServiceFunction(MS_DBT_ENTITY_GETFLAGS, DBEntityGetFlags); + gServices[ 9] = CreateServiceFunction(MS_DBT_ENTITY_ITER_INIT, DBEntityIterInit); + gServices[10] = CreateServiceFunction(MS_DBT_ENTITY_ITER_NEXT, DBEntityIterNext); + gServices[11] = CreateServiceFunction(MS_DBT_ENTITY_ITER_CLOSE, DBEntityIterClose); + gServices[12] = CreateServiceFunction(MS_DBT_ENTITY_DELETE, DBEntityDelete); + gServices[13] = CreateServiceFunction(MS_DBT_ENTITY_CREATE, DBEntityCreate); + gServices[13] = CreateServiceFunction(MS_DBT_ENTITY_GETACCOUNT, DBEntityGetAccount); + + gServices[14] = CreateServiceFunction(MS_DBT_VIRTUALENTITY_CREATE, DBVirtualEntityCreate); + gServices[15] = CreateServiceFunction(MS_DBT_VIRTUALENTITY_GETPARENT, DBVirtualEntityGetParent); + gServices[16] = CreateServiceFunction(MS_DBT_VIRTUALENTITY_GETFIRST, DBVirtualEntityGetFirst); + gServices[17] = CreateServiceFunction(MS_DBT_VIRTUALENTITY_GETNEXT, DBVirtualEntityGetNext); + + gServices[18] = CreateServiceFunction(MS_DBT_SETTING_FIND, DBSettingFind); + gServices[19] = CreateServiceFunction(MS_DBT_SETTING_DELETE, DBSettingDelete); + gServices[20] = CreateServiceFunction(MS_DBT_SETTING_DELETEHANDLE, DBSettingDeleteHandle); + gServices[21] = CreateServiceFunction(MS_DBT_SETTING_WRITE, DBSettingWrite); + gServices[22] = CreateServiceFunction(MS_DBT_SETTING_WRITEHANDLE, DBSettingWriteHandle); + gServices[23] = CreateServiceFunction(MS_DBT_SETTING_READ, DBSettingRead); + gServices[24] = CreateServiceFunction(MS_DBT_SETTING_READHANDLE, DBSettingReadHandle); + gServices[25] = CreateServiceFunction(MS_DBT_SETTING_ITER_INIT, DBSettingIterInit); + gServices[26] = CreateServiceFunction(MS_DBT_SETTING_ITER_NEXT, DBSettingIterNext); + gServices[27] = CreateServiceFunction(MS_DBT_SETTING_ITER_CLOSE, DBSettingIterClose); + + gServices[28] = CreateServiceFunction(MS_DBT_EVENT_GETBLOBSIZE, DBEventGetBlobSize); + gServices[29] = CreateServiceFunction(MS_DBT_EVENT_GET, DBEventGet); + gServices[30] = CreateServiceFunction(MS_DBT_EVENT_GETCOUNT, DBEventGetCount); + gServices[31] = CreateServiceFunction(MS_DBT_EVENT_DELETE, DBEventDelete); + gServices[32] = CreateServiceFunction(MS_DBT_EVENT_ADD, DBEventAdd); + gServices[33] = CreateServiceFunction(MS_DBT_EVENT_MARKREAD, DBEventMarkRead); + gServices[34] = CreateServiceFunction(MS_DBT_EVENT_WRITETODISK, DBEventWriteToDisk); + gServices[35] = CreateServiceFunction(MS_DBT_EVENT_GETENTITY, DBEventGetEntity); + gServices[36] = CreateServiceFunction(MS_DBT_EVENT_ITER_INIT, DBEventIterInit); + gServices[37] = CreateServiceFunction(MS_DBT_EVENT_ITER_NEXT, DBEventIterNext); + gServices[38] = CreateServiceFunction(MS_DBT_EVENT_ITER_CLOSE, DBEventIterClose); + + + return true; +} diff --git a/plugins/Dbx_tree/src/Services.h b/plugins/Dbx_tree/src/Services.h new file mode 100644 index 0000000000..0d75552fd4 --- /dev/null +++ b/plugins/Dbx_tree/src/Services.h @@ -0,0 +1,69 @@ +/* + +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. + +*/ + +#pragma once + +#include "Interface.h" +#include "DataBase.h" + +bool RegisterServices(); + + +INT_PTR DBEntityGetRoot(WPARAM wParam, LPARAM lParam); +INT_PTR DBEntityChildCount(WPARAM hEntity, LPARAM lParam); +INT_PTR DBEntityGetParent(WPARAM hEntity, LPARAM lParam); +INT_PTR DBEntityMove(WPARAM hEntity, LPARAM hParent); +INT_PTR DBEntityGetFlags(WPARAM hEntity, LPARAM lParam); +INT_PTR DBEntityIterInit(WPARAM pFilter, LPARAM hParent); +INT_PTR DBEntityIterNext(WPARAM hIteration, LPARAM lParam); +INT_PTR DBEntityIterClose(WPARAM hIteration, LPARAM lParam); +INT_PTR DBEntityDelete(WPARAM hEntity, LPARAM lParam); +INT_PTR DBEntityCreate(WPARAM pEntity, LPARAM lParam); +INT_PTR DBEntityGetAccount(WPARAM hEntity, LPARAM lParam); + +INT_PTR DBVirtualEntityCreate(WPARAM hEntity, LPARAM hParent); +INT_PTR DBVirtualEntityGetParent(WPARAM hVirtualEntity, LPARAM lParam); +INT_PTR DBVirtualEntityGetFirst(WPARAM hEntity, LPARAM lParam); +INT_PTR DBVirtualEntityGetNext(WPARAM hVirtualEntity, LPARAM lParam); + +INT_PTR DBSettingFind(WPARAM pSettingDescriptor, LPARAM lParam); +INT_PTR DBSettingDelete(WPARAM pSettingDescriptor, LPARAM lParam); +INT_PTR DBSettingDeleteHandle(WPARAM hSetting, LPARAM lParam); +INT_PTR DBSettingWrite(WPARAM pSetting, LPARAM lParam); +INT_PTR DBSettingWriteHandle(WPARAM pSetting, LPARAM hSetting); +INT_PTR DBSettingRead(WPARAM pSetting, LPARAM lParam); +INT_PTR DBSettingReadHandle(WPARAM pSetting, LPARAM hSetting); +INT_PTR DBSettingIterInit(WPARAM pFilter, LPARAM lParam); +INT_PTR DBSettingIterNext(WPARAM hIteration, LPARAM lParam); +INT_PTR DBSettingIterClose(WPARAM hIteration, LPARAM lParam); + +INT_PTR DBEventGetBlobSize(WPARAM hEvent, LPARAM lParam); +INT_PTR DBEventGet(WPARAM hEvent, LPARAM pEvent); +INT_PTR DBEventGetCount(WPARAM hEntity, LPARAM lParam); +INT_PTR DBEventDelete(WPARAM hEvent, LPARAM lParam); +INT_PTR DBEventAdd(WPARAM hEntity, LPARAM pEvent); +INT_PTR DBEventMarkRead(WPARAM hEvent, LPARAM lParam); +INT_PTR DBEventWriteToDisk(WPARAM hEvent, LPARAM lParam); +INT_PTR DBEventGetEntity(WPARAM hEvent, LPARAM lParam); +INT_PTR DBEventIterInit(WPARAM pFilter, LPARAM lParam); +INT_PTR DBEventIterNext(WPARAM hIteration, LPARAM lParam); +INT_PTR DBEventIterClose(WPARAM hIteration, LPARAM lParam); 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 // 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(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(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(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(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(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( 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(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(hSetting, size, sig); + + if (!setting) + return DBT_INVALIDPARAM; + + CSettingsTree * tree = getSettingsTree(setting->Entity); + if (tree == NULL) + return DBT_INVALIDPARAM; + + char * str = reinterpret_cast(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(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(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(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(strlen(Setting.Descriptor->pszSettingName)) + 1 + blobsize; + + if (hSetting == 0) // create new setting + { + setting = file->CreateBlock(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(strlen(Setting.Descriptor->pszSettingName))), hSetting); + } + + } else { + uint32_t tmp = 0; + setting = file->ReadBlock(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(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(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(hSetting, size, sig); + + if (!setting) + return DBT_INVALIDPARAM; + + uint8_t* str = reinterpret_cast(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(strlen(Setting.Value.pUTF8) + 1); + } break; + case DBT_ST_WCHAR: + { + Setting.Value.pWide = mir_a2u((char*)str); + Setting.Value.Length = static_cast(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(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(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(strlen(Setting.Value.pAnsi) + 1); + } break; + case DBT_ST_UTF8: + { + Setting.Value.pUTF8 = mir_utf8encodeW((wchar_t*)str); + Setting.Value.Length = static_cast(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 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(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; + + return reinterpret_cast(iter); +} + + +typedef struct TSettingIterationHelper { + TDBTSettingHandle Handle; + CSettingsTree * Tree; + uint16_t NameLen; + char * Name; + } TSettingIterationHelper; + +TDBTSettingHandle CSettings::IterationNext(TDBTSettingIterationHandle Iteration) +{ + PSettingIteration iter = reinterpret_cast(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 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(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; +} diff --git a/plugins/Dbx_tree/src/Settings.h b/plugins/Dbx_tree/src/Settings.h new file mode 100644 index 0000000000..28be10603e --- /dev/null +++ b/plugins/Dbx_tree/src/Settings.h @@ -0,0 +1,235 @@ +/* + +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. + +*/ + +#pragma once + +#include "Interface.h" +#include "FileBTree.h" +#include "MREWSync.h" +#include "sigslot.h" +#include "IterationHeap.h" +#include +#include "lockfree_hashmap.h" + +class CSettings; +class CSettingsTree; + +#include "Entities.h" + +#pragma pack(push, 1) // push current alignment to stack, set alignment to 1 byte boundary + +/** + \brief Key Type of the SettingsBTree + + The setting names (ASCII) are hashed, so that they can easily be accessed. +**/ + +typedef struct TSettingKey { + uint32_t Hash; /// 32 bit hash of the Setting name + TDBTSettingHandle Setting; + + bool operator < (const TSettingKey & Other) const + { + if (Hash != Other.Hash) return Hash < Other.Hash; + if (Setting != Other.Setting) return Setting < Other.Setting; + return false; + } + //bool operator <= (const TSettingKey & Other); + bool operator == (const TSettingKey & Other) const + { + return (Hash == Other.Hash) && (Setting == Other.Setting); + } + //bool operator >= (const TSettingKey & Other); + bool operator > (const TSettingKey & Other) const + { + if (Hash != Other.Hash) return Hash > Other.Hash; + if (Setting != Other.Setting) return Setting > Other.Setting; + return false; + } +} TSettingKey; + +static const uint32_t cSettingSignature = 0xF5B87A3D; +static const uint16_t cSettingNodeSignature = 0xBA12; + +/** + \brief The data of a setting + + A setting's data is variable length. The data is a TSetting-structure followed by variable length data. + - fixed data + - SettingName (ASCII) + - maybe blob data +**/ +typedef struct TSetting { + TDBTEntityHandle Entity; /// Settings' Entity + uint32_t Flags; /// flags + uint16_t Type; /// setting type + uint16_t NameLength; /// settingname length + union { + union { + bool Bool; + int8_t Char; uint8_t Byte; + int16_t Short; uint16_t Word; + uint32_t Int; uint32_t DWord; + int64_t Int64; uint64_t QWord; + float Float; + double Double; + } Value; /// if type is fixed length, the data is stored right here + + struct { + uint32_t BlobLength; /// if type is variable length this describes the length of the data in bytes + uint32_t AllocSize; /// this is the allocated space for the blob ALWAYS in byte! this prevents us to realloc it too often + }; + }; + uint8_t Reserved[8]; + // settingname with terminating NULL + // blob +} TSetting; + +#pragma pack(pop) + +/** + \brief Manages the Settings in the Database +**/ +class CSettingsTree : public CFileBTree +{ +protected: + TDBTEntityHandle m_Entity; + CSettings & m_Owner; +public: + CSettingsTree(CSettings & Owner, CBlockManager & BlockManager, TNodeRef RootNode, TDBTEntityHandle Entity) + : CFileBTree(BlockManager, RootNode, cSettingNodeSignature), + m_Owner(Owner), + m_Entity(Entity) + { + + }; + ~CSettingsTree() + { + + }; + + TDBTEntityHandle Entity() + { + return m_Entity; + }; + void Entity(TDBTEntityHandle NewEntity) + { + m_Entity = NewEntity; + }; + + TDBTSettingHandle _FindSetting(const uint32_t Hash, const char * Name, const uint32_t Length); + bool _DeleteSetting(const uint32_t Hash, const TDBTSettingHandle hSetting); + bool _AddSetting(const uint32_t Hash, const TDBTSettingHandle hSetting); +}; + + +/** + \brief Manages all Settings and provides access to them +**/ +class CSettings : public sigslot::has_slots<> +{ +public: + typedef sigslot::signal2 TOnRootChanged; + + static const uint32_t cSettingsFileFlag = 0x00000001; + + CSettings( + CBlockManager & BlockManagerSet, + CBlockManager & BlockManagerPri, + CSettingsTree::TNodeRef SettingsRoot, + CEntities & Entities + ); + virtual ~CSettings(); + + + TOnRootChanged & sigRootChanged() + { + return m_sigRootChanged; + }; + + bool _ReadSettingName(CBlockManager & BlockManager, TDBTSettingHandle Setting, uint16_t & NameLength, char *& NameBuf); + void _EnsureModuleExists(char * Module); + + // compatibility: + typedef int (*DBMODULEENUMPROC)(const char *szModuleName,DWORD ofsModuleName,LPARAM lParam); + + int CompEnumModules(DBMODULEENUMPROC CallBack, LPARAM lParam); + // services: + TDBTSettingHandle FindSetting(TDBTSettingDescriptor & Descriptor); + unsigned int DeleteSetting(TDBTSettingDescriptor & Descriptor); + unsigned int DeleteSetting(TDBTSettingHandle hSetting); + TDBTSettingHandle WriteSetting(TDBTSetting & Setting); + TDBTSettingHandle WriteSetting(TDBTSetting & Setting, TDBTSettingHandle hSetting); + unsigned int ReadSetting(TDBTSetting & Setting); + unsigned int ReadSetting(TDBTSetting & Setting, TDBTSettingHandle hSetting); + + + TDBTSettingIterationHandle IterationInit(TDBTSettingIterFilter & Filter); + TDBTSettingHandle IterationNext(TDBTSettingIterationHandle Iteration); + unsigned int IterationClose(TDBTSettingIterationHandle Iteration); + + +private: + + typedef lockfree::hash_map TSettingsTreeMap; + + typedef CIterationHeap TSettingsHeap; + + CBlockManager & m_BlockManagerSet; + CBlockManager & m_BlockManagerPri; + + CEntities & m_Entities; + + TSettingsTreeMap m_SettingsMap; + + typedef struct TSettingIterationResult { + TDBTSettingHandle Handle; + TDBTEntityHandle Entity; + char * Name; + uint16_t NameLen; + } TSettingIterationResult; + + typedef struct TSettingIteration { + TDBTSettingIterFilter Filter; + uint16_t FilterNameStartLength; + TSettingsHeap * Heap; + std::queue * Frame; + bool LockSetting; + bool LockPrivate; + } TSettingIteration, *PSettingIteration; + + TOnRootChanged m_sigRootChanged; + void onRootChanged(void* SettingsTree, CSettingsTree::TNodeRef NewRoot); + + void onDeleteSettingCallback(void * Tree, const TSettingKey & Key, uint32_t Param); + void onDeleteSettings(CEntities * Entities, TDBTEntityHandle hEntity); + void onMergeSettingCallback(void * Tree, const TSettingKey & Key, uint32_t Param); + void onMergeSettings(CEntities * Entities, TDBTEntityHandle Source, TDBTEntityHandle Dest); + + CSettingsTree * getSettingsTree(TDBTEntityHandle hEntity); + typedef lockfree::hash_multimap TModulesMap; + + TModulesMap m_Modules; + + void _LoadModules(); + +}; diff --git a/plugins/Dbx_tree/src/TLS.h b/plugins/Dbx_tree/src/TLS.h new file mode 100644 index 0000000000..d309090a34 --- /dev/null +++ b/plugins/Dbx_tree/src/TLS.h @@ -0,0 +1,161 @@ +/* + +dbx_tree: tree database driver for Miranda IM + +Copyright 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. + +*/ + +#pragma once + +#include "lockfree_hashmap.h" + +template +class CThreadLocalStorage +{ + private: + typedef struct TListElem + { + TListElem * Next; + TAdministrator * Admin; + TData Data; + TListElem(TListElem * ANext, TAdministrator * AAdmin, const TData & AData) + : Next(ANext), Admin(AAdmin), Data(AData) + { }; + + } TListElem, *PListElem; + static __declspec(thread) PListElem m_Head; + + static inline uint32_t DummyHash(const void * Data, uint32_t Length) + { + return *reinterpret_cast(Data); + } + + lockfree::hash_map * m_LockfreeList; + typedef typename lockfree::hash_map::iterator TThreadStorage; + + public: + CThreadLocalStorage(); + ~CThreadLocalStorage(); + + TData & Open(TAdministrator * Admin, const TData & Default); + TData * Find(TAdministrator * Admin); + void Remove(TAdministrator * Admin); +}; + +const bool _CanUseTLS = ((LOBYTE(LOWORD(GetVersion()))) >= 6); + +template +typename CThreadLocalStorage::PListElem CThreadLocalStorage::m_Head = NULL; + + +template +CThreadLocalStorage::CThreadLocalStorage() +{ + m_LockfreeList = NULL; + if (!_CanUseTLS) + m_LockfreeList = new lockfree::hash_map(); +} +template +CThreadLocalStorage::~CThreadLocalStorage() +{ + if (m_LockfreeList) + delete m_LockfreeList; +} + + +template +typename TData & CThreadLocalStorage::Open(typename TAdministrator * Admin, const TData & Default) +{ + if (_CanUseTLS) + { + PListElem * last = &m_Head; + PListElem i = m_Head; + while (i && (i->Admin != Admin)) + { + last = &i->Next; + i = i->Next; + } + + if (i) + { + *last = i->Next; + i->Next = m_Head; + m_Head = i; + } else { + m_Head = new TListElem(m_Head, Admin, Default); + } + return m_Head->Data; + } else { + TThreadStorage & res = m_LockfreeList->insert(std::make_pair(GetCurrentThreadId(), Default)).first; + return res->second; + } +} + +template +typename TData * CThreadLocalStorage::Find(typename TAdministrator * Admin) +{ + if (_CanUseTLS) + { + PListElem * last = &m_Head; + PListElem i = m_Head; + while (i && (i->Admin != Admin)) + { + last = &i->Next; + i = i->Next; + } + + if (i) + { + *last = i->Next; + i->Next = m_Head; + m_Head = i; + } else { + return NULL; + } + return &m_Head->Data; + } else { + TThreadStorage & res = m_LockfreeList->find(GetCurrentThreadId()); + if (res != m_LockfreeList->end()) + return &res->second; + else + return NULL; + } +} + +template +void CThreadLocalStorage::Remove(typename TAdministrator * Admin) +{ + if (_CanUseTLS) + { + PListElem * last = &m_Head; + PListElem i = m_Head; + while (i && (i->Admin != Admin)) + { + last = &i->Next; + i = i->Next; + } + + if (i) + { + *last = i->Next; + delete i; + } + } else { + m_LockfreeList->erase(GetCurrentThreadId()); + } +} diff --git a/plugins/Dbx_tree/src/Thread.cpp b/plugins/Dbx_tree/src/Thread.cpp new file mode 100644 index 0000000000..bdb01f18aa --- /dev/null +++ b/plugins/Dbx_tree/src/Thread.cpp @@ -0,0 +1,114 @@ +/* + +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 "Thread.h" +#include "intrinsics.h" + +unsigned int __stdcall ThreadDistributor(void* Param) +{ + CThread * thread = static_cast(Param); + DWORD result = thread->Wrapper(); + _endthreadex(result); + return result; // to make the compiler happy +} + +CThread::CThread(bool CreateSuspended) +{ + m_Handle = NULL; + m_Terminated = 0; + m_FreeOnTerminate = false; + m_Finished = false; + m_Suspended = CreateSuspended; + m_ReturnValue = 0; + unsigned int flags = 0; + if (CreateSuspended) + flags = CREATE_SUSPENDED; + + m_Handle = reinterpret_cast (_beginthreadex(NULL, 0, &ThreadDistributor, this, flags, &m_ThreadID)); +} +CThread::~CThread() +{ + if (!m_Finished && !m_Suspended) + { + Terminate(); + WaitFor(); + } + if (m_Handle) + CloseHandle(m_Handle); +} +DWORD CThread::Wrapper() +{ + Execute(); + + bool dofree = FreeOnTerminate(); + DWORD result = ReturnValue(); + m_Finished = true; + + m_sigTerminate(this); + if (dofree) + delete this; + + return result; +} + +void CThread::Resume() +{ + if (ResumeThread(m_Handle) == 1) + XCHG_32(m_Suspended, 0); +} +void CThread::Suspend() +{ + SuspendThread(m_Handle); + XCHG_32(m_Suspended, 1); +} +void CThread::Terminate() +{ + XCHG_32(m_Terminated, 1); +} +DWORD CThread::WaitFor() +{ + HANDLE tmp = m_Handle; + DWORD result = WAIT_FAILED; + + if (WaitForSingleObject(m_Handle, INFINITE) != WAIT_FAILED) + GetExitCodeThread(tmp, &result); + + return result; +} + +void CThread::FreeOnTerminate(bool Terminate) +{ + XCHG_32(m_FreeOnTerminate, Terminate); +} +void CThread::ReturnValue(DWORD Value) +{ + XCHG_32(m_ReturnValue, Value); +} + +void CThread::Priority(TPriority NewPriority) +{ + SetThreadPriority(m_Handle, NewPriority); +} +CThread::TPriority CThread::Priority() +{ + return static_cast (GetThreadPriority(m_Handle) & 0xffff); +} diff --git a/plugins/Dbx_tree/src/Thread.h b/plugins/Dbx_tree/src/Thread.h new file mode 100644 index 0000000000..09b0b6c016 --- /dev/null +++ b/plugins/Dbx_tree/src/Thread.h @@ -0,0 +1,77 @@ +/* + +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. + +*/ + +#pragma once + +#include +#include +#include "sigslot.h" +#include "stdint.h" + +class CThread +{ +private: + uint32_t volatile m_Terminated; + uint32_t volatile m_FreeOnTerminate; + uint32_t volatile m_Finished; + uint32_t volatile m_Suspended; + uint32_t volatile m_ReturnValue; +protected: + HANDLE m_Handle; + unsigned int m_ThreadID; + + void ReturnValue(DWORD Value); + virtual void Execute() = 0; +public: + CThread(bool CreateSuspended); + virtual ~CThread(); + + DWORD Wrapper(); + + void Resume(); + void Suspend(); + void Terminate(); + DWORD WaitFor(); + + bool Suspended() {return m_Suspended != 0;}; + bool Terminated() {return m_Terminated != 0;}; + bool FreeOnTerminate() {return m_FreeOnTerminate != 0;}; + void FreeOnTerminate(bool Terminate); + DWORD ReturnValue() {return m_ReturnValue;}; + + typedef enum TPriority { + tpIdle = THREAD_PRIORITY_IDLE, + tpLowest = THREAD_PRIORITY_LOWEST, + tpLower = THREAD_PRIORITY_BELOW_NORMAL, + tpNormal = THREAD_PRIORITY_NORMAL, + tpHigher = THREAD_PRIORITY_ABOVE_NORMAL, + tpHighest = THREAD_PRIORITY_HIGHEST, + tpRealTime = THREAD_PRIORITY_TIME_CRITICAL + } TPriority; + + void Priority(TPriority NewPriority); + TPriority Priority(); + + typedef sigslot::signal1 TOnTerminate; + TOnTerminate m_sigTerminate; + TOnTerminate & sigTerminate() {return m_sigTerminate;}; +}; diff --git a/plugins/Dbx_tree/src/dbConfig_rc.h b/plugins/Dbx_tree/src/dbConfig_rc.h new file mode 100644 index 0000000000..099067d3ec --- /dev/null +++ b/plugins/Dbx_tree/src/dbConfig_rc.h @@ -0,0 +1,20 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by dbConfig.rc +// +#define IDD_DIALOGBAR 103 +#define IDC_BUTTON1 1001 +#define IDC_BUTTON2 1002 +#define IDC_BUTTON3 1003 +#define IDC_LIST1 1004 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 101 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1005 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/plugins/Dbx_tree/src/dbVersion_rc.h b/plugins/Dbx_tree/src/dbVersion_rc.h new file mode 100644 index 0000000000..24a3ae4cf4 --- /dev/null +++ b/plugins/Dbx_tree/src/dbVersion_rc.h @@ -0,0 +1,14 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by dbVersion.rc + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 101 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1001 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/plugins/Dbx_tree/src/init.cpp b/plugins/Dbx_tree/src/init.cpp new file mode 100644 index 0000000000..3e1f4cc6a6 --- /dev/null +++ b/plugins/Dbx_tree/src/init.cpp @@ -0,0 +1,73 @@ +/* + +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 "Interface.h" +#include "DatabaseLink.h" + +HINSTANCE hInstance = NULL; +int hLangpack; + +static const DWORD gMinMirVer = 0x00080000; +// {28F45248-8C9C-4bee-9307-7BCF3E12BF99} +static const MUUID gGUID = +{ 0x28f45248, 0x8c9c, 0x4bee, { 0x93, 0x07, 0x7b, 0xcf, 0x3e, 0x12, 0xbf, 0x99 } }; + +static PLUGININFOEX gPluginInfoEx = { + sizeof(PLUGININFOEX), + gInternalNameLong, + gVersion, + gDescription, + gAutor, + gAutorEmail, + gCopyright, + "http://miranda-ng.org/", + UNICODE_AWARE, + gGUID +}; + +extern "C" __declspec(dllexport) PLUGININFOEX * MirandaPluginInfoEx(DWORD MirandaVersion) +{ + return &gPluginInfoEx; +} + +extern "C" __declspec(dllexport) const MUUID MirandaInterfaces[] = {MIID_DATABASE, MIID_LAST}; + +extern "C" __declspec(dllexport) int Load(void) +{ + mir_getLP(&gPluginInfoEx); + + RegisterDatabasePlugin(&gDBLink); + RegisterServices(); + CompatibilityRegister(); + return 0; +} + +extern "C" __declspec(dllexport) int Unload(void) +{ + return 0; +} + +BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD dwReason, LPVOID reserved) +{ + hInstance = hInstDLL; + return TRUE; +} diff --git a/plugins/Dbx_tree/src/intrinsics.h b/plugins/Dbx_tree/src/intrinsics.h new file mode 100644 index 0000000000..7cb8af18f3 --- /dev/null +++ b/plugins/Dbx_tree/src/intrinsics.h @@ -0,0 +1,407 @@ +#pragma once + +#ifdef _MSC_VER + +#include +#include "stdint.h" + +#ifdef _M_X64 + +inline uint32_t XCHG_32(uint32_t volatile & Dest, uint32_t Exchange) +{ + return (uint32_t)_InterlockedExchange((long volatile*)&(Dest), (long)(Exchange)); +} +inline int32_t XCHG_32(int32_t volatile & Dest, int32_t Exchange) +{ + return (int32_t)_InterlockedExchange((long volatile*)&(Dest), (long)(Exchange)); +} + +inline uint64_t XCHG_64(uint64_t volatile & Dest, uint64_t Exchange) +{ + return (uint64_t)_InterlockedExchange64((__int64 volatile*)&Dest, (__int64)Exchange); +} +inline int64_t XCHG_64(int64_t volatile & Dest, int64_t Exchange) +{ + return (int64_t)_InterlockedExchange64((__int64 volatile*)&Dest, (__int64)Exchange); +} + +template +inline T * XCHG_Ptr(T * volatile & Dest, T * Exchange) +{ + return (T*)_InterlockedExchangePointer((void*volatile*)&Dest, (void*)Exchange); +} + + +inline uint32_t CMPXCHG_32(uint32_t volatile & Dest, uint32_t Exchange, uint32_t Comperand) +{ + return (uint64_t)_InterlockedCompareExchange((long volatile*)&(Dest), (long)(Exchange), (long)Comperand); +} +inline int32_t CMPXCHG_32(int32_t volatile & Dest, int32_t Exchange, int32_t Comperand) +{ + return (int32_t)_InterlockedCompareExchange((long volatile*)&(Dest), (long)(Exchange), (long)Comperand); +} + +inline uint64_t CMPXCHG_64(uint64_t volatile & Dest, uint64_t Exchange, uint64_t Comperand) +{ + return (uint64_t)_InterlockedCompareExchange64((__int64 volatile*)&Dest, (__int64)Exchange, (__int64)Comperand); +} +inline int64_t CMPXCHG_64(int64_t volatile & Dest, int64_t Exchange, int64_t Comperand) +{ + return (int64_t)_InterlockedCompareExchange64((__int64 volatile*)&Dest, (__int64)Exchange, (__int64)Comperand); +} + +template +inline T * CMPXCHG_Ptr(T * volatile & Dest, T * Exchange, T * Comperand) +{ + return (T*)_InterlockedCompareExchangePointer((void*volatile*)&Dest, (void*)Exchange, (void*)Comperand); +} + +inline uint32_t XADD_32(uint32_t volatile & Dest, int32_t Addend) +{ + return (uint32_t)_InterlockedExchangeAdd((long volatile*)&Dest, (long)Addend); +} +inline int32_t XADD_32(int32_t volatile & Dest, int32_t Addend) +{ + return (int32_t)_InterlockedExchangeAdd((long volatile*)&Dest, (long)Addend); +} + +inline uint64_t XADD_64(uint64_t volatile & Dest, int64_t Addend) +{ + return (uint64_t)_InterlockedExchangeAdd64((__int64 volatile*)&Dest, (__int64)Addend); +} +inline int64_t XADD_64(int64_t volatile & Dest, int64_t Addend) +{ + return (int64_t)_InterlockedExchangeAdd64((__int64 volatile*)&Dest, (__int64)Addend); +} + +inline uint32_t DEC_32(uint32_t volatile & Dest) +{ + return (uint32_t)_InterlockedDecrement((long volatile*)&Dest); +} +inline int32_t DEC_32(int32_t volatile & Dest) +{ + return (int32_t)_InterlockedDecrement((long volatile*)&Dest); +} + +inline uint64_t DEC_64(uint64_t volatile & Dest) +{ + return (uint64_t)_InterlockedDecrement64((__int64 volatile*)&Dest); +} +inline int64_t DEC_64(int64_t volatile & Dest) +{ + return (int64_t)_InterlockedDecrement64((__int64 volatile*)&Dest); +} + +inline uint32_t INC_32(uint32_t volatile & Dest) +{ + return (uint32_t)_InterlockedIncrement((long volatile*)&Dest); +} +inline int32_t INC_32(int32_t volatile & Dest) +{ + return (int32_t)_InterlockedIncrement((long volatile*)&Dest); +} + +inline uint64_t INC_64(uint64_t volatile & Dest) +{ + return (uint64_t)_InterlockedIncrement64((__int64 volatile*)&Dest); +} +inline int64_t INC_64(int64_t volatile & Dest) +{ + return (int64_t)_InterlockedIncrement64((__int64 volatile*)&Dest); +} + +inline bool BTS_32(uint32_t volatile & Dest, uint8_t Offset) +{ + return !!_interlockedbittestandset((long volatile*)&Dest, Offset); +} +inline bool BTS_32(int32_t volatile & Dest, uint8_t Offset) +{ + return !!_interlockedbittestandset((long volatile*)&Dest, Offset); +} +inline bool BTS_64(uint64_t volatile & Dest, uint8_t Offset) +{ + return !!_interlockedbittestandset64((__int64 volatile*)&Dest, Offset); +} +inline bool BTS_64(int64_t volatile & Dest, uint8_t Offset) +{ + return !!_interlockedbittestandset64((__int64 volatile*)&Dest, Offset); +} + + +inline bool BTR_32(uint32_t volatile & Dest, uint8_t Offset) +{ + return !!_interlockedbittestandreset((long volatile*)&Dest, Offset); +} +inline bool BTR_32(int32_t volatile & Dest, uint8_t Offset) +{ + return !!_interlockedbittestandreset((long volatile*)&Dest, Offset); +} +inline bool BTR_64(uint64_t volatile & Dest, uint8_t Offset) +{ + return !!_interlockedbittestandreset64((__int64 volatile*)&Dest, Offset); +} +inline bool BTR_64(int64_t volatile & Dest, uint8_t Offset) +{ + return !!_interlockedbittestandreset64((__int64 volatile*)&Dest, Offset); +} + + +inline uint32_t OR_32(uint32_t volatile & Value, uint32_t Operator) +{ + return (uint32_t)_InterlockedOr((long volatile*)&Value, (long)Operator); +} + +inline int32_t OR_32(int32_t volatile & Value, int32_t Operator) +{ + return (int32_t)_InterlockedOr((long volatile*)&Value, (long)Operator); +} + +inline uint64_t OR_64(uint64_t volatile & Value, uint64_t Operator) +{ + return (uint64_t)_InterlockedOr64((__int64 volatile*)&Value, (__int64)Operator); +} + +inline int64_t OR_64(int64_t volatile & Value, int64_t Operator) +{ + return (int64_t)_InterlockedOr64((__int64 volatile*)&Value, (__int64)Operator); +} + +inline uint32_t AND_32(uint32_t volatile & Value, uint32_t Operator) +{ + return (uint32_t)_InterlockedAnd((long volatile*)&Value, (long)Operator); +} + +inline int32_t AND_32(int32_t volatile & Value, int32_t Operator) +{ + return (int32_t)_InterlockedAnd((long volatile*)&Value, (long)Operator); +} + +inline uint64_t AND_64(uint64_t volatile & Value, uint64_t Operator) +{ + return (uint64_t)_InterlockedAnd64((__int64 volatile*)&Value, (__int64)Operator); +} + +inline int64_t AND_64(int64_t volatile & Value, int64_t Operator) +{ + return (int64_t)_InterlockedAnd64((__int64 volatile*)&Value, (__int64)Operator); +} + + +inline uint32_t XOR_32(uint32_t volatile & Value, uint32_t Operator) +{ + return (uint32_t)_InterlockedXor((long volatile*)&Value, (long)Operator); +} + +inline int32_t XOR_32(int32_t volatile & Value, int32_t Operator) +{ + return (int32_t)_InterlockedXor((long volatile*)&Value, (long)Operator); +} +inline uint64_t XOR_64(uint64_t volatile & Value, uint64_t Operator) +{ + return (uint64_t)_InterlockedXor64((__int64 volatile*)&Value, (__int64)Operator); +} + +inline int64_t XOR_64(int64_t volatile & Value, int64_t Operator) +{ + return (int64_t)_InterlockedXor64((__int64 volatile*)&Value, (__int64)Operator); +} + + +inline uint32_t BSWAP_32(uint32_t Value) +{ + return _byteswap_ulong(Value); +} + +inline uint32_t ROL_32(uint32_t Value, uint8_t Shift) +{ + return _rotl(Value, Shift); +} + +inline uint32_t ROR_32(uint32_t Value, uint8_t Shift) +{ + return _rotr(Value, Shift); +} + +#elif defined(_M_IX86) + +inline uint32_t XCHG_32(uint32_t volatile & Dest, uint32_t Exchange) +{ + return (uint32_t)_InterlockedExchange((long volatile*)&(Dest), (long)(Exchange)); +} +inline int32_t XCHG_32(int32_t volatile & Dest, int32_t Exchange) +{ + return (int32_t)_InterlockedExchange((long volatile*)&(Dest), (long)(Exchange)); +} +/* +inline uint64_t XCHG_64(uint64_t volatile & Dest, uint64_t Exchange) +{ + return (uint64_t)_InterlockedExchange64((__int64 volatile*)&Dest, (__int64)Exchange); +} +inline int64_t XCHG_64(int64_t volatile & Dest, int64_t Exchange) +{ + return (int64_t)_InterlockedExchange64((__int64 volatile*)&Dest, (__int64)Exchange); +} +*/ +template +inline T * XCHG_Ptr(T * volatile & Dest, T * Exchange) +{ + return (T*)_InterlockedExchange((long volatile*)&Dest, (long)Exchange); +} + + +inline uint32_t CMPXCHG_32(uint32_t volatile & Dest, uint32_t Exchange, uint32_t Comperand) +{ + return (uint64_t)_InterlockedCompareExchange((long volatile*)&(Dest), (long)(Exchange), (long)Comperand); +} +inline int32_t CMPXCHG_32(int32_t volatile & Dest, int32_t Exchange, int32_t Comperand) +{ + return (int32_t)_InterlockedCompareExchange((long volatile*)&(Dest), (long)(Exchange), (long)Comperand); +} + +inline uint64_t CMPXCHG_64(uint64_t volatile & Dest, uint64_t Exchange, uint64_t Comperand) +{ + return (uint64_t)_InterlockedCompareExchange64((__int64 volatile*)&Dest, (__int64)Exchange, (__int64)Comperand); +} +inline int64_t CMPXCHG_64(int64_t volatile & Dest, int64_t Exchange, int64_t Comperand) +{ + return (int64_t)_InterlockedCompareExchange64((__int64 volatile*)&Dest, (__int64)Exchange, (__int64)Comperand); +} + +template +inline T * CMPXCHG_Ptr(T * volatile & Dest, T * Exchange, T * Comperand) +{ + return (T*)_InterlockedCompareExchange((long volatile *)&Dest, (long)Exchange, (long)Comperand); +} + +inline uint32_t XADD_32(uint32_t volatile & Dest, int32_t Addend) +{ + return (uint32_t)_InterlockedExchangeAdd((long volatile*)&Dest, (long)Addend); +} +inline int32_t XADD_32(int32_t volatile & Dest, int32_t Addend) +{ + return (int32_t)_InterlockedExchangeAdd((long volatile*)&Dest, (long)Addend); +} + +inline uint32_t DEC_32(uint32_t volatile & Dest) +{ + return (uint32_t)_InterlockedDecrement((long volatile*)&Dest); +} +inline int32_t DEC_32(int32_t volatile & Dest) +{ + return (int32_t)_InterlockedDecrement((long volatile*)&Dest); +} + +inline uint32_t INC_32(uint32_t volatile & Dest) +{ + return (uint32_t)_InterlockedIncrement((long volatile*)&Dest); +} +inline int32_t INC_32(int32_t volatile & Dest) +{ + return (int32_t)_InterlockedIncrement((long volatile*)&Dest); +} + +inline bool BTS_32(uint32_t volatile & Dest, uint8_t Offset) +{ + return !!_interlockedbittestandset((long volatile*)&Dest, Offset); +} +inline bool BTS_32(int32_t volatile & Dest, uint8_t Offset) +{ + return !!_interlockedbittestandset((long volatile*)&Dest, Offset); +} +inline bool BTS_64(uint64_t volatile & Dest, uint8_t Offset) +{ + if (Offset > 31) + return !!_interlockedbittestandset((long volatile*)&Dest, Offset); + else + return !!_interlockedbittestandset(((long volatile*)&Dest) + 1, Offset - 32); +} +inline bool BTS_64(int64_t volatile & Dest, uint8_t Offset) +{ + if (Offset > 31) + return !!_interlockedbittestandset((long volatile*)&Dest, Offset); + else + return !!_interlockedbittestandset(((long volatile*)&Dest) + 1, Offset - 32); +} + + +inline bool BTR_32(uint32_t volatile & Dest, uint8_t Offset) +{ + return !!_interlockedbittestandreset((long volatile*)&Dest, Offset); +} +inline bool BTR_32(int32_t volatile & Dest, uint8_t Offset) +{ + return !!_interlockedbittestandreset((long volatile*)&Dest, Offset); +} +inline bool BTR_64(uint64_t volatile & Dest, uint8_t Offset) +{ + if (Offset > 31) + return !!_interlockedbittestandreset((long volatile*)&Dest, Offset); + else + return !!_interlockedbittestandreset(((long volatile*)&Dest) + 1, Offset - 32); +} +inline bool BTR_64(int64_t volatile & Dest, uint8_t Offset) +{ + if (Offset > 31) + return !!_interlockedbittestandreset((long volatile*)&Dest, Offset); + else + return !!_interlockedbittestandreset(((long volatile*)&Dest) + 1, Offset - 32); +} + +inline uint32_t OR_32(uint32_t volatile & Value, uint32_t Operator) +{ + return (uint32_t)_InterlockedOr((long volatile*)&Value, (long)Operator); +} + +inline int32_t OR_32(int32_t volatile & Value, int32_t Operator) +{ + return (int32_t)_InterlockedOr((long volatile*)&Value, (long)Operator); +} + +inline uint32_t AND_32(uint32_t volatile & Value, uint32_t Operator) +{ + return (uint32_t)_InterlockedAnd((long volatile*)&Value, (long)Operator); +} + +inline int32_t AND_32(int32_t volatile & Value, int32_t Operator) +{ + return (int32_t)_InterlockedAnd((long volatile*)&Value, (long)Operator); +} + +inline uint32_t XOR_32(uint32_t volatile & Value, uint32_t Operator) +{ + return (uint32_t)_InterlockedXor((long volatile*)&Value, (long)Operator); +} + +inline int32_t XOR_32(int32_t volatile & Value, int32_t Operator) +{ + return (int32_t)_InterlockedXor((long volatile*)&Value, (long)Operator); +} + + +inline uint32_t BSWAP_32(uint32_t Value) +{ + return _byteswap_ulong(Value); +} + +inline uint32_t ROL_32(uint32_t Value, uint8_t Shift) +{ + return _rotl(Value, Shift); +} +inline uint32_t ROR_32(uint32_t Value, uint8_t Shift) +{ + return _rotr(Value, Shift); +} + + + +#else + +#error unsupported architecture + +#endif + +#else + +#error unsupported compiler + +#endif diff --git a/plugins/Dbx_tree/src/inttypes.h b/plugins/Dbx_tree/src/inttypes.h new file mode 100644 index 0000000000..25542771f5 --- /dev/null +++ b/plugins/Dbx_tree/src/inttypes.h @@ -0,0 +1,305 @@ +// ISO C9x compliant inttypes.h for Microsoft Visual Studio +// Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124 +// +// Copyright (c) 2006 Alexander Chemeris +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// 3. The name of the author may be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED +// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO +// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef _MSC_VER // [ +#error "Use this header only with Microsoft Visual C++ compilers!" +#endif // _MSC_VER ] + +#ifndef _MSC_INTTYPES_H_ // [ +#define _MSC_INTTYPES_H_ + +#if _MSC_VER > 1000 +#pragma once +#endif + +#include "stdint.h" + +// 7.8 Format conversion of integer types + +typedef struct { + intmax_t quot; + intmax_t rem; +} imaxdiv_t; + +// 7.8.1 Macros for format specifiers + +#if !defined(__cplusplus) || defined(__STDC_FORMAT_MACROS) // [ See footnote 185 at page 198 + +// The fprintf macros for signed integers are: +#define PRId8 "d" +#define PRIi8 "i" +#define PRIdLEAST8 "d" +#define PRIiLEAST8 "i" +#define PRIdFAST8 "d" +#define PRIiFAST8 "i" + +#define PRId16 "hd" +#define PRIi16 "hi" +#define PRIdLEAST16 "hd" +#define PRIiLEAST16 "hi" +#define PRIdFAST16 "hd" +#define PRIiFAST16 "hi" + +#define PRId32 "I32d" +#define PRIi32 "I32i" +#define PRIdLEAST32 "I32d" +#define PRIiLEAST32 "I32i" +#define PRIdFAST32 "I32d" +#define PRIiFAST32 "I32i" + +#define PRId64 "I64d" +#define PRIi64 "I64i" +#define PRIdLEAST64 "I64d" +#define PRIiLEAST64 "I64i" +#define PRIdFAST64 "I64d" +#define PRIiFAST64 "I64i" + +#define PRIdMAX "I64d" +#define PRIiMAX "I64i" + +#define PRIdPTR "Id" +#define PRIiPTR "Ii" + +// The fprintf macros for unsigned integers are: +#define PRIo8 "o" +#define PRIu8 "u" +#define PRIx8 "x" +#define PRIX8 "X" +#define PRIoLEAST8 "o" +#define PRIuLEAST8 "u" +#define PRIxLEAST8 "x" +#define PRIXLEAST8 "X" +#define PRIoFAST8 "o" +#define PRIuFAST8 "u" +#define PRIxFAST8 "x" +#define PRIXFAST8 "X" + +#define PRIo16 "ho" +#define PRIu16 "hu" +#define PRIx16 "hx" +#define PRIX16 "hX" +#define PRIoLEAST16 "ho" +#define PRIuLEAST16 "hu" +#define PRIxLEAST16 "hx" +#define PRIXLEAST16 "hX" +#define PRIoFAST16 "ho" +#define PRIuFAST16 "hu" +#define PRIxFAST16 "hx" +#define PRIXFAST16 "hX" + +#define PRIo32 "I32o" +#define PRIu32 "I32u" +#define PRIx32 "I32x" +#define PRIX32 "I32X" +#define PRIoLEAST32 "I32o" +#define PRIuLEAST32 "I32u" +#define PRIxLEAST32 "I32x" +#define PRIXLEAST32 "I32X" +#define PRIoFAST32 "I32o" +#define PRIuFAST32 "I32u" +#define PRIxFAST32 "I32x" +#define PRIXFAST32 "I32X" + +#define PRIo64 "I64o" +#define PRIu64 "I64u" +#define PRIx64 "I64x" +#define PRIX64 "I64X" +#define PRIoLEAST64 "I64o" +#define PRIuLEAST64 "I64u" +#define PRIxLEAST64 "I64x" +#define PRIXLEAST64 "I64X" +#define PRIoFAST64 "I64o" +#define PRIuFAST64 "I64u" +#define PRIxFAST64 "I64x" +#define PRIXFAST64 "I64X" + +#define PRIoMAX "I64o" +#define PRIuMAX "I64u" +#define PRIxMAX "I64x" +#define PRIXMAX "I64X" + +#define PRIoPTR "Io" +#define PRIuPTR "Iu" +#define PRIxPTR "Ix" +#define PRIXPTR "IX" + +// The fscanf macros for signed integers are: +#define SCNd8 "d" +#define SCNi8 "i" +#define SCNdLEAST8 "d" +#define SCNiLEAST8 "i" +#define SCNdFAST8 "d" +#define SCNiFAST8 "i" + +#define SCNd16 "hd" +#define SCNi16 "hi" +#define SCNdLEAST16 "hd" +#define SCNiLEAST16 "hi" +#define SCNdFAST16 "hd" +#define SCNiFAST16 "hi" + +#define SCNd32 "ld" +#define SCNi32 "li" +#define SCNdLEAST32 "ld" +#define SCNiLEAST32 "li" +#define SCNdFAST32 "ld" +#define SCNiFAST32 "li" + +#define SCNd64 "I64d" +#define SCNi64 "I64i" +#define SCNdLEAST64 "I64d" +#define SCNiLEAST64 "I64i" +#define SCNdFAST64 "I64d" +#define SCNiFAST64 "I64i" + +#define SCNdMAX "I64d" +#define SCNiMAX "I64i" + +#ifdef _WIN64 // [ +# define SCNdPTR "I64d" +# define SCNiPTR "I64i" +#else // _WIN64 ][ +# define SCNdPTR "ld" +# define SCNiPTR "li" +#endif // _WIN64 ] + +// The fscanf macros for unsigned integers are: +#define SCNo8 "o" +#define SCNu8 "u" +#define SCNx8 "x" +#define SCNX8 "X" +#define SCNoLEAST8 "o" +#define SCNuLEAST8 "u" +#define SCNxLEAST8 "x" +#define SCNXLEAST8 "X" +#define SCNoFAST8 "o" +#define SCNuFAST8 "u" +#define SCNxFAST8 "x" +#define SCNXFAST8 "X" + +#define SCNo16 "ho" +#define SCNu16 "hu" +#define SCNx16 "hx" +#define SCNX16 "hX" +#define SCNoLEAST16 "ho" +#define SCNuLEAST16 "hu" +#define SCNxLEAST16 "hx" +#define SCNXLEAST16 "hX" +#define SCNoFAST16 "ho" +#define SCNuFAST16 "hu" +#define SCNxFAST16 "hx" +#define SCNXFAST16 "hX" + +#define SCNo32 "lo" +#define SCNu32 "lu" +#define SCNx32 "lx" +#define SCNX32 "lX" +#define SCNoLEAST32 "lo" +#define SCNuLEAST32 "lu" +#define SCNxLEAST32 "lx" +#define SCNXLEAST32 "lX" +#define SCNoFAST32 "lo" +#define SCNuFAST32 "lu" +#define SCNxFAST32 "lx" +#define SCNXFAST32 "lX" + +#define SCNo64 "I64o" +#define SCNu64 "I64u" +#define SCNx64 "I64x" +#define SCNX64 "I64X" +#define SCNoLEAST64 "I64o" +#define SCNuLEAST64 "I64u" +#define SCNxLEAST64 "I64x" +#define SCNXLEAST64 "I64X" +#define SCNoFAST64 "I64o" +#define SCNuFAST64 "I64u" +#define SCNxFAST64 "I64x" +#define SCNXFAST64 "I64X" + +#define SCNoMAX "I64o" +#define SCNuMAX "I64u" +#define SCNxMAX "I64x" +#define SCNXMAX "I64X" + +#ifdef _WIN64 // [ +# define SCNoPTR "I64o" +# define SCNuPTR "I64u" +# define SCNxPTR "I64x" +# define SCNXPTR "I64X" +#else // _WIN64 ][ +# define SCNoPTR "lo" +# define SCNuPTR "lu" +# define SCNxPTR "lx" +# define SCNXPTR "lX" +#endif // _WIN64 ] + +#endif // __STDC_FORMAT_MACROS ] + +// 7.8.2 Functions for greatest-width integer types + +// 7.8.2.1 The imaxabs function +#define imaxabs _abs64 + +// 7.8.2.2 The imaxdiv function + +// This is modified version of div() function from Microsoft's div.c found +// in %MSVC.NET%\crt\src\div.c +#ifdef STATIC_IMAXDIV // [ +static +#else // STATIC_IMAXDIV ][ +_inline +#endif // STATIC_IMAXDIV ] +imaxdiv_t __cdecl imaxdiv(intmax_t numer, intmax_t denom) +{ + imaxdiv_t result; + + result.quot = numer / denom; + result.rem = numer % denom; + + if (numer < 0 && result.rem > 0) { + // did division wrong; must fix up + ++result.quot; + result.rem -= denom; + } + + return result; +} + +// 7.8.2.3 The strtoimax and strtoumax functions +#define strtoimax _strtoi64 +#define strtoumax _strtoui64 + +// 7.8.2.4 The wcstoimax and wcstoumax functions +#define wcstoimax _wcstoi64 +#define wcstoumax _wcstoui64 + + +#endif // _MSC_INTTYPES_H_ ] diff --git a/plugins/Dbx_tree/src/lockfree_hashmap.h b/plugins/Dbx_tree/src/lockfree_hashmap.h new file mode 100644 index 0000000000..7ec2df3ce4 --- /dev/null +++ b/plugins/Dbx_tree/src/lockfree_hashmap.h @@ -0,0 +1,749 @@ +#pragma once + +/* + +lockfree hash-multi_map based on Ori Shalev and Nir Shavit + +implementation +Copyright 2009-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. + +*/ + +#pragma once + +#include +#include "Hash.h" +#include "intrinsics.h" + +#define NodePointer(listitem) ((PListItem)(((uintptr_t)(listitem)) & ~1)) +#define NodeMark(listitem) ((bool) (((uintptr_t)(listitem)) & 1)) + +#define HashTablePtr(hashtable) ((PHashTable)(((uintptr_t)(hashtable)) & ~31)) +#define HashTableSize(hashtable) ((uint32_t)(((uintptr_t)(hashtable)) & 31)) +#define HashTable(tableptr, tablesize) ((void*)(((uintptr_t)(tableptr)) | ((tablesize) & 31))) + +#define GCSelection(Sentinel) ((Sentinel) >> 63) +#define GCRefCount0(Sentinel) ((Sentinel) & 0x7fffffff) +#define GCRefCount1(Sentinel) (((Sentinel) >> 32) & 0x7fffffff) +#define GCMakeSentinel(Sel, RefCount0, RefCount1) ((((uint64_t)(Sel) & 1) << 63) | (((uint64_t)(RefCount1)) << 32) | ((uint64_t)(RefCount0))) + +#define GCRef0 (1) +#define GCRef1 (0x0000000100000000) + +namespace lockfree +{ + template + class hash_map + { + public: + typedef std::pair value_type; + + private: + typedef struct TListItem + { + TListItem * volatile Next; + TListItem * volatile NextPurge; + volatile uint32_t Hash; + value_type Value; + } TListItem, *PListItem; + + typedef struct THashTable + { + volatile PListItem Table[256]; + } THashTable, *PHashTable; + + typedef struct { + volatile uint64_t Sentinel; + volatile PListItem Purge0; + volatile PListItem Purge1; + } THashTableReferences; + + THashTableReferences m_GarbageCollector; + + volatile uint32_t m_Count; + void * volatile m_HashTableData; + + PListItem listInsert(PListItem BucketNode, PListItem Node); + PListItem listDelete(PListItem BucketNode, uint32_t Hash, const TKey & Key); + + PListItem listDelete(PListItem BucketNode, PListItem Node); + + bool listFind(const PListItem BucketNode, const uint32_t Hash, const TKey & Key, const PListItem Node, volatile PListItem * & Prev, PListItem & Curr, PListItem & Next); + + uint32_t getMask(uint32_t Size) + { + const uint32_t mask[32] = { + 0x80000000, 0xc0000000, 0xe0000000, 0xf0000000, + 0xf8000000, 0xfc000000, 0xfe000000, 0xff000000, + 0xff800000, 0xffc00000, 0xffe00000, 0xfff00000, + 0xfff80000, 0xfffc0000, 0xfffe0000, 0xffff0000, + 0xffff8000, 0xffffc000, 0xffffe000, 0xfffff000, + 0xfffff800, 0xfffffc00, 0xfffffe00, 0xffffff00, + 0xffffff80, 0xffffffc0, 0xffffffe0, 0xfffffff0, + 0xfffffff8, 0xfffffffc, 0xfffffffe, 0xffffffff + }; + return mask[Size - 1]; + }; + + PHashTable makeNewTable() + { + void * block = malloc(sizeof(THashTable) + 32 + sizeof(void*)); + PHashTable result = reinterpret_cast((reinterpret_cast(block) + 31 + sizeof(void*)) & (~(uintptr_t)31)); + *(reinterpret_cast(result)-1) = block; + memset(reinterpret_cast(result), 0, sizeof(THashTable)); + return reinterpret_cast(result); + }; + + void destroyTable(PHashTable Table) + { + free(*(reinterpret_cast(Table) - 1)); + }; + + PListItem makeDummyNode(uint32_t Hash) + { + PListItem result = new TListItem; + result->Hash = Hash; + result->Next = NULL; + result->NextPurge = NULL; + return result; + }; + + bool DisposeNode(volatile PListItem * Prev, PListItem Curr, PListItem Next); + + PListItem initializeBucket(uint32_t Bucket, uint32_t Mask); + + PListItem getBucket(uint32_t Bucket); + + void setBucket(uint32_t Bucket, PListItem Dummy); + + void DeleteTable(void * Table, uint32_t Size) + { + if (Size > 8) + { + for (uint32_t i = 0; i < 256; ++i) + { + if (HashTablePtr(Table)->Table[i]) + DeleteTable(HashTablePtr(Table)->Table[i], Size - 8); + } + } + + destroyTable(HashTablePtr(Table)); + }; + + + int addRef(int GC = -1); + void delRef(int GC); + + public: + + + class iterator + { + protected: + friend class hash_map; + PListItem m_Item; + typename hash_map * m_Owner; + int m_GC; + + iterator(hash_map * Owner, PListItem Item, int GC) + : m_Owner(Owner) + { + m_GC = GC; + m_Item = Item; + + while (m_Item && (!(m_Item->Hash & 1) || NodeMark(m_Item->Next))) + m_Item = NodePointer(m_Item->Next); + + if (!m_Item && (m_GC != -1)) + { + m_Owner->delRef(m_GC); + m_GC = -1; + } + + }; + public: + iterator(const iterator & Other) + : m_Owner(Other.m_Owner), + m_Item(Other.m_Item) + { + m_GC = -1; + if (Other.m_GC != -1) + m_GC = m_Owner->addRef(Other.m_GC); + }; + ~iterator() + { + if (m_GC != -1) + m_Owner->delRef(m_GC); + }; + + operator bool() const + { + return m_Item != NULL; + }; + bool operator !() const + { + return m_Item == NULL; + }; + + value_type * operator ->() + { + return &m_Item->Value; + }; + value_type & operator *() + { + return m_Item->Value; + }; + + bool operator ==(iterator& Other) + { + return m_Item->Value.first == Other.m_Item->Value.first; + }; + bool operator < (iterator & Other) + { + return m_Item->Value.first < Other.m_Item->Value.first; + }; + bool operator > (iterator & Other) + { + return m_Item->Value.first > Other.m_Item->Value.first; + }; + + iterator& operator =(const iterator& Other) + { + m_Owner = Other.m_Owner; + m_Item = Other.m_Item; + + if (Other.m_GC != m_GC) + { + if (m_GC != -1) + m_Owner->delRef(m_GC); + + m_GC = Other.m_GC; + + if (Other.m_GC != -1) + m_GC = m_Owner->addRef(Other.m_GC); + + } + + return *this; + }; + + iterator& operator ++() //pre ++i + { + if (!m_Item) + return *this; + + int gc = m_GC; + m_GC = m_Owner->addRef(); + do + { + m_Item = NodePointer(m_Item->Next); + } while (m_Item && (!(m_Item->Hash & 1) || NodeMark(m_Item->Next))); + + m_Owner->delRef(gc); + if (!m_Item) + { + m_Owner->delRef(m_GC); + m_GC = -1; + } + return *this; + }; + iterator operator ++(int) //post i++ + { + iterator bak(*this); + ++(*this); + return bak; + }; + }; + + iterator begin() + { + return iterator(this, getBucket(0), addRef()); + }; + + iterator end() + { + return iterator(this, NULL, -1); + }; + + hash_map(); + ~hash_map(); + + std::pair insert(const value_type & Val); + + iterator find(const TKey & Key); + + iterator erase(const iterator & Where); + + size_t erase(const TKey & Key); + + }; + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + template + int hash_map::addRef(int GC = -1) + { + uint64_t old; + uint64_t newvalue; + int res; + do { + old = m_GarbageCollector.Sentinel; + if (GC == 0) // this is safe because refcount will never fall to zero because of the original reference + { + newvalue = old + GCRef0; + res = 0; + } else if (GC == 1) + { + newvalue = old + GCRef1; + res = 1; + } else { + if (GCSelection(old)) + { + newvalue = old + GCRef1; + res = 1; + } else { + newvalue = old + GCRef0; + res = 0; + } + } + } + while (CMPXCHG_64(m_GarbageCollector.Sentinel, newvalue, old) != old); + + return res; + }; + + template + void hash_map::delRef(int GC) + { + uint64_t old; + uint64_t newvalue; + PListItem purge = NULL; + do { + old = m_GarbageCollector.Sentinel; + if (GC) + { + newvalue = old - GCRef1; + + if (!GCSelection(old) && (GCRefCount1(old) == 1)) // the other gc is activated and we are the last one + { + if (!purge) // check if we had to loop... + purge = m_GarbageCollector.Purge1; + + m_GarbageCollector.Purge1 = NULL; + } + + } else { + newvalue = old - GCRef0; + + if (GCSelection(old) && (GCRefCount0(old) == 1)) // the other gc is activated and we are the last one + { + if (!purge) // check if we had to loop... + purge = m_GarbageCollector.Purge0; + + m_GarbageCollector.Purge0 = NULL; + } + + } + } while (CMPXCHG_64(m_GarbageCollector.Sentinel, newvalue, old) != old); + + purge = NodePointer(purge); + while (purge) + { + PListItem tmp = purge; + purge = purge->NextPurge; + delete tmp; + }; + }; + + + + template + bool hash_map::DisposeNode(volatile PListItem * Prev, PListItem Curr, PListItem Next) + { + if (NodePointer(Curr) == CMPXCHG_Ptr(*Prev, NodePointer(Next), NodePointer(Curr))) + { + uint64_t old = m_GarbageCollector.Sentinel; + PListItem del = NodePointer(Curr); + + if (GCSelection(old)) + { + del->NextPurge = (PListItem)XCHG_Ptr(m_GarbageCollector.Purge1, del); + + if (!GCRefCount0(old)) + BTR_64(m_GarbageCollector.Sentinel, 63); // switch + + } else { + + del->NextPurge = (PListItem)XCHG_Ptr(m_GarbageCollector.Purge0, del); + + if (!GCRefCount1(old)) + BTS_64(m_GarbageCollector.Sentinel, 63); // switch + + } + return true; + } + + return false; + }; + + + template + typename hash_map::PListItem hash_map::listInsert(PListItem BucketNode, PListItem Node) + { + PListItem volatile * prev; + PListItem curr, next; + do + { + if (listFind(BucketNode, Node->Hash, Node->Value.first, NULL, prev, curr, next)) + return NodePointer(curr); + + Node->Next = NodePointer(curr); + + } while (NodePointer(curr) != CMPXCHG_Ptr(*prev, Node, NodePointer(curr))); + return Node; + }; + + + template + typename hash_map::PListItem hash_map::listDelete(PListItem BucketNode, uint32_t Hash, const TKey & Key) + { + PListItem volatile * prev; + PListItem curr, next; + + if (!listFind(BucketNode, Hash, Key, NULL, prev, curr, next)) + return NodePointer(curr); + + do + { + if (!listFind(BucketNode, Hash, Key, NULL, prev, curr, next)) + return NodePointer(curr); + + } while (NodePointer(next) != CMPXCHG_Ptr(curr->Next, (PListItem)((uintptr_t)next | 1), NodePointer(next))); + + if (!DisposeNode(prev, curr, next)) + listFind(BucketNode, Hash, Key, NULL, prev, curr, next); // cleanup + + return NodePointer(curr); + }; + + template + typename hash_map::PListItem hash_map::listDelete(PListItem BucketNode, PListItem Node) + { + PListItem volatile * prev; + PListItem curr, next; + if (!listFind(BucketNode, Node->Hash, Node->Value.first, Node, prev, curr, next)) + return NodePointer(curr); + + do + { + if (!listFind(BucketNode, Node->Hash, Node->Value.first, Node, prev, curr, next)) + return NodePointer(curr); + + } while (NodePointer(next) != CMPXCHG_Ptr(curr->Next, (PListItem)((uintptr_t)next | 1), NodePointer(next))); + + if (!DisposeNode(prev, curr, next)) + listFind(BucketNode, Node->Hash, Node->Value.first, Node, prev, curr, next); // cleanup + + return NodePointer(curr); + }; + + template + bool hash_map::listFind(const PListItem BucketNode, const uint32_t Hash, const TKey & Key, const PListItem Node, volatile PListItem * & Prev, PListItem & Curr, PListItem & Next) + { +tryagain: + Prev = &(BucketNode->Next); + Curr = *Prev; + do + { + if (NodePointer(Curr) == NULL) + return false; + + Next = NodePointer(Curr)->Next; + uint32_t h = NodePointer(Curr)->Hash; + + if (*Prev != NodePointer(Curr)) + goto tryagain; // don't judge me for that + //return listFind(BucketNode, Hash, Key, Node, Prev, Curr, Next); // it's the same but stack overflow can happen + + if (!NodeMark(Next)) + { + if (Node) + { + if ((h > Hash) || (Node == NodePointer(Curr))) + return NodePointer(Curr) == Node; + } + else if ((h > Hash) || ((h == Hash) && !(NodePointer(Curr)->Value.first < Key))) + { + return (h == Hash) && (NodePointer(Curr)->Value.first == Key); + } + + Prev = &(NodePointer(Curr)->Next); + } else { + if (!DisposeNode(Prev, Curr, Next)) + goto tryagain; // don't judge me for that + //return listFind(BucketNode, Hash, Key, Node, Prev, Curr, Next); // it's the same but stack overflow can happen + } + Curr = Next; + } while (true); + + }; + + + template + typename hash_map::PListItem hash_map::initializeBucket(uint32_t Bucket, uint32_t Mask) + { + uint32_t parent = Bucket & (Mask << 1); + PListItem parentnode = getBucket(parent); + if (parentnode == NULL) + parentnode = initializeBucket(parent, Mask << 1); + + PListItem dummy = makeDummyNode(Bucket); + PListItem bucketnode = listInsert(parentnode, dummy); + if (bucketnode != dummy) + { + delete dummy; + dummy = bucketnode; + } + setBucket(Bucket, dummy); + + return dummy; + } + + template + typename hash_map::PListItem hash_map::getBucket(uint32_t Bucket) + { + void * table; + uint32_t mask; + + table = (void*)m_HashTableData; + mask = getMask(HashTableSize(table)); + + uint32_t levelshift = (32 - HashTableSize(table)) & ~7; + + while (levelshift < 24) + { + table = HashTablePtr(table)->Table[((Bucket & mask) >> levelshift) & 0xff]; + levelshift = levelshift + 8; + if (!HashTablePtr(table)) + return NULL; + } + return HashTablePtr(table)->Table[(Bucket & mask) >> 24]; + }; + + template + void hash_map::setBucket(uint32_t Bucket, PListItem Dummy) + { + void * table; + void *volatile * last; + uint32_t mask; + + table = m_HashTableData; + mask = getMask(HashTableSize(table)); + + uint32_t levelshift = (32 - HashTableSize(table)) & ~7; + + while (levelshift < 24) + { + last = (void*volatile*)&HashTablePtr(table)->Table[((Bucket & mask) >> levelshift) & 0xff]; + table = *last; + levelshift = levelshift + 8; + if (!table) + { + PHashTable newtable = makeNewTable(); + table = CMPXCHG_Ptr(*last, newtable, NULL); + if (table) + { + destroyTable(newtable); + } else { + table = newtable; + } + } + } + HashTablePtr(table)->Table[(Bucket & mask) >> 24] = Dummy; + }; + + template + hash_map::hash_map() + { + m_Count = 0; + + m_GarbageCollector.Sentinel = GCMakeSentinel(0,0,0); + m_GarbageCollector.Purge0 = NULL; + m_GarbageCollector.Purge1 = NULL; + + m_HashTableData = HashTable(makeNewTable(), 1); + setBucket(0x00000000, makeDummyNode(0x00000000)); + setBucket(0x80000000, makeDummyNode(0x80000000)); + HashTablePtr(m_HashTableData)->Table[0]->Next = getBucket(0x80000000); + }; + + template + hash_map::~hash_map() + { + PListItem h = getBucket(0); + DeleteTable(HashTablePtr(m_HashTableData), HashTableSize(m_HashTableData)); + + while (h) + { + PListItem tmp = h; + h = NodePointer(h->Next); + delete tmp; + }; + + h = m_GarbageCollector.Purge0; + while (h) + { + PListItem tmp = h; + h = h->NextPurge; + delete tmp; + }; + + h = m_GarbageCollector.Purge1; + while (h) + { + PListItem tmp = h; + h = h->NextPurge; + delete tmp; + }; + + }; + + template + typename std::pair::iterator, bool> hash_map::insert(const value_type & Val) + { + int gc = addRef(); + PListItem node = new TListItem; + node->Value = Val; + node->Hash = FHash(&node->Value.first, sizeof(TKey)) | 1; + node->NextPurge = NULL; + node->Next = NULL; + + void * tmp; + void * newdata; + tmp = (void*)m_HashTableData; + + uint32_t mask = getMask(HashTableSize(tmp)); + + uint32_t bucket = node->Hash & mask; + PListItem bucketnode = getBucket(bucket); + + if (bucketnode == NULL) + bucketnode = initializeBucket(bucket, mask); + PListItem retnode = listInsert(bucketnode, node); + if (retnode != node) + { + delete node; + return std::make_pair(iterator(this, retnode, gc), false); + } + + if ((INC_32(m_Count) > ((uint32_t)1 << (HashTableSize(tmp) + 3))) && (HashTableSize(tmp) < 31) && (HashTableSize(tmp) == HashTableSize(m_HashTableData))) + { + newdata = HashTable(HashTablePtr(tmp), HashTableSize(tmp) + 1); + + if ((HashTableSize(tmp) & 0x7) == 0) + { + newdata = HashTable(makeNewTable(), HashTableSize(tmp) + 1); + HashTablePtr(newdata)->Table[0] = (TListItem*)HashTablePtr(tmp); + + if (tmp != CMPXCHG_Ptr(m_HashTableData, newdata, tmp)) + destroyTable(HashTablePtr(newdata)); // someone else expanded the table. + } else { + CMPXCHG_Ptr(m_HashTableData, newdata, tmp); + } + + } + + return std::make_pair(iterator(this, node, gc), true); + }; + + template + typename hash_map::iterator hash_map::find(const TKey & Key) + { + int gc = addRef(); + uint32_t hash = FHash(&Key, sizeof(TKey)) | 1; + uint32_t mask = getMask(HashTableSize(m_HashTableData)); + uint32_t bucket = hash & mask; + PListItem bucketnode = getBucket(bucket); + if (bucketnode == NULL) + bucketnode = initializeBucket(bucket, mask); + + PListItem volatile * prev; + PListItem curr, next; + if (listFind(bucketnode, hash, Key, NULL, prev, curr, next)) + return iterator(this, NodePointer(curr), gc); + + return iterator(this, NULL, gc); + }; + + template + typename hash_map::iterator hash_map::erase(const iterator & Where) + { + int gc = addRef(); + uint32_t hash = Where.m_Item->Hash; + uint32_t mask = getMask(HashTableSize(m_HashTableData)); + uint32_t bucket = hash & mask; + PListItem bucketnode = getBucket(bucket); + + if (bucketnode == NULL) + bucketnode = initializeBucket(bucket, mask); + + PListItem res = listDelete(bucketnode, Where.m_Item); + if (Where.m_Item == res) + { + DEC_32(m_Count); + return iterator(this, NodePointer(res->Next), gc); + } + return iterator(this, res, gc); + }; + + template + size_t hash_map::erase(const TKey & Key) + { + int gc = addRef(); + uint32_t hash = FHash(&Key, sizeof(TKey)) | 1; + uint32_t mask = getMask(HashTableSize(m_HashTableData)); + uint32_t bucket = hash & mask; + PListItem bucketnode = getBucket(bucket); + + if (bucketnode == NULL) + bucketnode = initializeBucket(bucket, mask); + + PListItem result = listDelete(bucketnode, hash, Key); + if (result && (result->Value.first == Key)) + { + DEC_32(m_Count); + delRef(gc); + return 1; + } + + delRef(gc); + return 0; + }; +} + +#undef NodePointer +#undef NodeMark + +#undef HashTablePtr +#undef HashTableSize +#undef HashTable + +#undef GCSelection +#undef GCRefCount0 +#undef GCRefCount1 +#undef GCMakeSentinel + diff --git a/plugins/Dbx_tree/src/lockfree_hashmultimap.h b/plugins/Dbx_tree/src/lockfree_hashmultimap.h new file mode 100644 index 0000000000..79981e5447 --- /dev/null +++ b/plugins/Dbx_tree/src/lockfree_hashmultimap.h @@ -0,0 +1,750 @@ +#pragma once + +/* + +lockfree hash-multi_map based on Ori Shalev and Nir Shavit + +implementation +Copyright 2009-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. + +*/ + +#pragma once + +#include +#include "Hash.h" +#include "intrinsics.h" + +#define NodePointer(listitem) ((PListItem)(((uintptr_t)(listitem)) & ~1)) +#define NodeMark(listitem) ((bool) (((uintptr_t)(listitem)) & 1)) + +#define HashTablePtr(hashtable) ((PHashTable)(((uintptr_t)(hashtable)) & ~31)) +#define HashTableSize(hashtable) ((uint32_t)(((uintptr_t)(hashtable)) & 31)) +#define HashTable(tableptr, tablesize) ((void*)(((uintptr_t)(tableptr)) | ((tablesize) & 31))) + +#define GCSelection(Sentinel) ((Sentinel) >> 63) +#define GCRefCount0(Sentinel) ((Sentinel) & 0x7fffffff) +#define GCRefCount1(Sentinel) (((Sentinel) >> 32) & 0x7fffffff) +#define GCMakeSentinel(Sel, RefCount0, RefCount1) ((((uint64_t)(Sel) & 1) << 63) | (((uint64_t)(RefCount1)) << 32) | ((uint64_t)(RefCount0))) + +#define GCRef0 (1) +#define GCRef1 (0x0000000100000000) + +namespace lockfree +{ + template + class hash_multimap + { + public: + typedef std::pair value_type; + + private: + typedef struct TListItem + { + TListItem * volatile Next; + TListItem * volatile NextPurge; + volatile uint32_t Hash; + value_type Value; + } TListItem, *PListItem; + + typedef struct THashTable + { + volatile PListItem Table[256]; + } THashTable, *PHashTable; + + typedef struct { + volatile uint64_t Sentinel; + volatile PListItem Purge0; + volatile PListItem Purge1; + } THashTableReferences; + + THashTableReferences m_GarbageCollector; + + volatile uint32_t m_Count; + void * volatile m_HashTableData; + + PListItem listInsert(PListItem BucketNode, PListItem Node); + PListItem listDelete(PListItem BucketNode, uint32_t Hash, const TKey & Key); + + PListItem listDelete(PListItem BucketNode, PListItem Node); + + bool listFind(const PListItem BucketNode, const uint32_t Hash, const TKey & Key, const PListItem Node, volatile PListItem * & Prev, PListItem & Curr, PListItem & Next); + + uint32_t getMask(uint32_t Size) + { + const uint32_t mask[32] = { + 0x80000000, 0xc0000000, 0xe0000000, 0xf0000000, + 0xf8000000, 0xfc000000, 0xfe000000, 0xff000000, + 0xff800000, 0xffc00000, 0xffe00000, 0xfff00000, + 0xfff80000, 0xfffc0000, 0xfffe0000, 0xffff0000, + 0xffff8000, 0xffffc000, 0xffffe000, 0xfffff000, + 0xfffff800, 0xfffffc00, 0xfffffe00, 0xffffff00, + 0xffffff80, 0xffffffc0, 0xffffffe0, 0xfffffff0, + 0xfffffff8, 0xfffffffc, 0xfffffffe, 0xffffffff + }; + return mask[Size - 1]; + }; + + PHashTable makeNewTable() + { + void * block = malloc(sizeof(THashTable) + 32 + sizeof(void*)); + PHashTable result = reinterpret_cast((reinterpret_cast(block) + 31 + sizeof(void*)) & (~(uintptr_t)31)); + *(reinterpret_cast(result)-1) = block; + memset(reinterpret_cast(result), 0, sizeof(THashTable)); + return reinterpret_cast(result); + }; + + void destroyTable(PHashTable Table) + { + free(*(reinterpret_cast(Table) - 1)); + }; + + PListItem makeDummyNode(uint32_t Hash) + { + PListItem result = new TListItem; + result->Hash = Hash; + result->Next = NULL; + result->NextPurge = NULL; + return result; + }; + + bool DisposeNode(volatile PListItem * Prev, PListItem Curr, PListItem Next); + + PListItem initializeBucket(uint32_t Bucket, uint32_t Mask); + + PListItem getBucket(uint32_t Bucket); + + void setBucket(uint32_t Bucket, PListItem Dummy); + + void DeleteTable(void * Table, uint32_t Size) + { + if (Size > 8) + { + for (uint32_t i = 0; i < 256; ++i) + { + if (HashTablePtr(Table)->Table[i]) + DeleteTable(HashTablePtr(Table)->Table[i], Size - 8); + } + } + + destroyTable(HashTablePtr(Table)); + }; + + + int addRef(int GC = -1); + void delRef(int GC); + + public: + + + class iterator + { + protected: + friend class hash_multimap; + PListItem m_Item; + typename hash_multimap * m_Owner; + int m_GC; + + iterator(hash_multimap * Owner, PListItem Item, int GC) + : m_Owner(Owner) + { + m_GC = GC; + m_Item = Item; + + while (m_Item && (!(m_Item->Hash & 1) || NodeMark(m_Item->Next))) + m_Item = NodePointer(m_Item->Next); + + if (!m_Item && (m_GC != -1)) + { + m_Owner->delRef(m_GC); + m_GC = -1; + } + + }; + public: + iterator(const iterator & Other) + : m_Owner(Other.m_Owner), + m_Item(Other.m_Item) + { + m_GC = -1; + if (Other.m_GC != -1) + m_GC = m_Owner->addRef(Other.m_GC); + }; + ~iterator() + { + if (m_GC != -1) + m_Owner->delRef(m_GC); + }; + + operator bool() const + { + return m_Item != NULL; + }; + bool operator !() const + { + return m_Item == NULL; + }; + + value_type * operator ->() + { + return &m_Item->Value; + }; + value_type & operator *() + { + return m_Item->Value; + }; + + bool operator ==(iterator& Other) + { + return m_Item->Value.first == Other.m_Item->Value.first; + }; + bool operator < (iterator & Other) + { + return m_Item->Value.first < Other.m_Item->Value.first; + }; + bool operator > (iterator & Other) + { + return m_Item->Value.first > Other.m_Item->Value.first; + }; + + iterator& operator =(const iterator& Other) + { + m_Owner = Other.m_Owner; + m_Item = Other.m_Item; + + if (Other.m_GC != m_GC) + { + if (m_GC != -1) + m_Owner->delRef(m_GC); + + m_GC = Other.m_GC; + + if (Other.m_GC != -1) + m_GC = m_Owner->addRef(Other.m_GC); + + } + + return *this; + }; + + iterator& operator ++() //pre ++i + { + if (!m_Item) + return *this; + + int gc = m_GC; + m_GC = m_Owner->addRef(); + do + { + m_Item = NodePointer(m_Item->Next); + } while (m_Item && (!(m_Item->Hash & 1) || NodeMark(m_Item->Next))); + + m_Owner->delRef(gc); + if (!m_Item) + { + m_Owner->delRef(m_GC); + m_GC = -1; + } + return *this; + }; + iterator operator ++(int) //post i++ + { + iterator bak(*this); + ++(*this); + return bak; + }; + }; + + iterator begin() + { + return iterator(this, getBucket(0), addRef()); + }; + + iterator end() + { + return iterator(this, NULL, -1); + }; + + hash_multimap(); + ~hash_multimap(); + + std::pair insert(const value_type & Val); + + iterator find(const TKey & Key); + + iterator erase(const iterator & Where); + + size_t erase(const TKey & Key); + + }; + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + template + int hash_multimap::addRef(int GC = -1) + { + uint64_t old; + uint64_t newvalue; + int res; + do { + old = m_GarbageCollector.Sentinel; + if (GC == 0) // this is safe because refcount will never fall to zero because of the original reference + { + newvalue = old + GCRef0; + res = 0; + } else if (GC == 1) + { + newvalue = old + GCRef1; + res = 1; + } else { + if (GCSelection(old)) + { + newvalue = old + GCRef1; + res = 1; + } else { + newvalue = old + GCRef0; + res = 0; + } + } + } + while (CMPXCHG_64(m_GarbageCollector.Sentinel, newvalue, old) != old); + + return res; + }; + + template + void hash_multimap::delRef(int GC) + { + uint64_t old; + uint64_t newvalue; + PListItem purge = NULL; + do { + old = m_GarbageCollector.Sentinel; + if (GC) + { + newvalue = old - GCRef1; + + if (!GCSelection(old) && (GCRefCount1(old) == 1)) // the other gc is activated and we are the last one + { + if (!purge) // check if we had to loop... + purge = m_GarbageCollector.Purge1; + + m_GarbageCollector.Purge1 = NULL; + } + + } else { + newvalue = old - GCRef0; + + if (GCSelection(old) && (GCRefCount0(old) == 1)) // the other gc is activated and we are the last one + { + if (!purge) // check if we had to loop... + purge = m_GarbageCollector.Purge0; + + m_GarbageCollector.Purge0 = NULL; + } + + } + } while (CMPXCHG_64(m_GarbageCollector.Sentinel, newvalue, old) != old); + + purge = NodePointer(purge); + while (purge) + { + PListItem tmp = purge; + purge = purge->NextPurge; + delete tmp; + }; + }; + + + + template + bool hash_multimap::DisposeNode(volatile PListItem * Prev, PListItem Curr, PListItem Next) + { + if (NodePointer(Curr) == CMPXCHG_Ptr(*Prev, NodePointer(Next), NodePointer(Curr))) + { + uint64_t old = m_GarbageCollector.Sentinel; + PListItem del = NodePointer(Curr); + + if (GCSelection(old)) + { + del->NextPurge = (PListItem)XCHG_Ptr(m_GarbageCollector.Purge1, del); + + if (!GCRefCount0(old)) + BTR_64(m_GarbageCollector.Sentinel, 63); // switch + + } else { + + del->NextPurge = (PListItem)XCHG_Ptr(m_GarbageCollector.Purge0, del); + + if (!GCRefCount1(old)) + BTS_64(m_GarbageCollector.Sentinel, 63); // switch + + } + return true; + } + + return false; + }; + + + template + typename hash_multimap::PListItem hash_multimap::listInsert(PListItem BucketNode, PListItem Node) + { + PListItem volatile * prev; + PListItem curr, next; + do + { + listFind(BucketNode, Node->Hash, Node->Value.first, NULL, prev, curr, next); + + Node->Next = NodePointer(curr); + + } while (NodePointer(curr) != CMPXCHG_Ptr(*prev, Node, NodePointer(curr))); + return Node; + }; + + + template + typename hash_multimap::PListItem hash_multimap::listDelete(PListItem BucketNode, uint32_t Hash, const TKey & Key) + { + PListItem volatile * prev; + PListItem curr, next; + + if (!listFind(BucketNode, Hash, Key, NULL, prev, curr, next)) + return NodePointer(curr); + + do + { + if (!listFind(BucketNode, Hash, Key, NULL, prev, curr, next)) + return NodePointer(curr); + + } while (NodePointer(next) != CMPXCHG_Ptr(curr->Next, (PListItem)((uintptr_t)next | 1), NodePointer(next))); + + if (!DisposeNode(prev, curr, next)) + listFind(BucketNode, Hash, Key, NULL, prev, curr, next); // cleanup + + return NodePointer(curr); + }; + + template + typename hash_multimap::PListItem hash_multimap::listDelete(PListItem BucketNode, PListItem Node) + { + PListItem volatile * prev; + PListItem curr, next; + if (!listFind(BucketNode, Node->Hash, Node->Value.first, Node, prev, curr, next)) + return NodePointer(curr); + + do + { + if (!listFind(BucketNode, Node->Hash, Node->Value.first, Node, prev, curr, next)) + return NodePointer(curr); + + } while (NodePointer(next) != CMPXCHG_Ptr(curr->Next, (PListItem)((uintptr_t)next | 1), NodePointer(next))); + + if (!DisposeNode(prev, curr, next)) + listFind(BucketNode, Node->Hash, Node->Value.first, Node, prev, curr, next); // cleanup + + return NodePointer(curr); + }; + + template + bool hash_multimap::listFind(const PListItem BucketNode, const uint32_t Hash, const TKey & Key, const PListItem Node, volatile PListItem * & Prev, PListItem & Curr, PListItem & Next) + { +tryagain: + Prev = &(BucketNode->Next); + Curr = *Prev; + do + { + if (NodePointer(Curr) == NULL) + return false; + + Next = NodePointer(Curr)->Next; + uint32_t h = NodePointer(Curr)->Hash; + + if (*Prev != NodePointer(Curr)) + goto tryagain; // don't judge me for that + //return listFind(BucketNode, Hash, Key, Node, Prev, Curr, Next); // it's the same but stack overflow can happen + + if (!NodeMark(Next)) + { + if (Node) + { + if ((h > Hash) || (Node == NodePointer(Curr))) + return NodePointer(Curr) == Node; + } + else if ((h > Hash) || ((h == Hash) && !(NodePointer(Curr)->Value.first < Key))) + { + return (h == Hash) && (NodePointer(Curr)->Value.first == Key); + } + + Prev = &(NodePointer(Curr)->Next); + } else { + if (!DisposeNode(Prev, Curr, Next)) + goto tryagain; // don't judge me for that + //return listFind(BucketNode, Hash, Key, Node, Prev, Curr, Next); // it's the same but stack overflow can happen + } + Curr = Next; + } while (true); + + }; + + + template + typename hash_multimap::PListItem hash_multimap::initializeBucket(uint32_t Bucket, uint32_t Mask) + { + uint32_t parent = Bucket & (Mask << 1); + PListItem parentnode = getBucket(parent); + if (parentnode == NULL) + parentnode = initializeBucket(parent, Mask << 1); + + PListItem dummy = makeDummyNode(Bucket); + PListItem bucketnode = listInsert(parentnode, dummy); + if (bucketnode != dummy) + { + delete dummy; + dummy = bucketnode; + } + setBucket(Bucket, dummy); + + return dummy; + } + + template + typename hash_multimap::PListItem hash_multimap::getBucket(uint32_t Bucket) + { + void * table; + uint32_t mask; + + table = (void*)m_HashTableData; + mask = getMask(HashTableSize(table)); + + uint32_t levelshift = (32 - HashTableSize(table)) & ~7; + + while (levelshift < 24) + { + table = HashTablePtr(table)->Table[((Bucket & mask) >> levelshift) & 0xff]; + levelshift = levelshift + 8; + if (!HashTablePtr(table)) + return NULL; + } + return HashTablePtr(table)->Table[(Bucket & mask) >> 24]; + }; + + template + void hash_multimap::setBucket(uint32_t Bucket, PListItem Dummy) + { + void * table; + void *volatile * last; + uint32_t mask; + + table = m_HashTableData; + mask = getMask(HashTableSize(table)); + + uint32_t levelshift = (32 - HashTableSize(table)) & ~7; + + while (levelshift < 24) + { + last = (void*volatile*)&HashTablePtr(table)->Table[((Bucket & mask) >> levelshift) & 0xff]; + table = *last; + levelshift = levelshift + 8; + if (!table) + { + PHashTable newtable = makeNewTable(); + table = CMPXCHG_Ptr(*last, newtable, NULL); + if (table) + { + destroyTable(newtable); + } else { + table = newtable; + } + } + } + HashTablePtr(table)->Table[(Bucket & mask) >> 24] = Dummy; + }; + + template + hash_multimap::hash_multimap() + { + m_Count = 0; + + m_GarbageCollector.Sentinel = GCMakeSentinel(0,0,0); + m_GarbageCollector.Purge0 = NULL; + m_GarbageCollector.Purge1 = NULL; + + m_HashTableData = HashTable(makeNewTable(), 1); + setBucket(0x00000000, makeDummyNode(0x00000000)); + setBucket(0x80000000, makeDummyNode(0x80000000)); + HashTablePtr(m_HashTableData)->Table[0]->Next = getBucket(0x80000000); + }; + + template + hash_multimap::~hash_multimap() + { + PListItem h = getBucket(0); + DeleteTable(HashTablePtr(m_HashTableData), HashTableSize(m_HashTableData)); + + while (h) + { + PListItem tmp = h; + h = NodePointer(h->Next); + delete tmp; + }; + + h = m_GarbageCollector.Purge0; + while (h) + { + PListItem tmp = h; + h = h->NextPurge; + delete tmp; + }; + + h = m_GarbageCollector.Purge1; + while (h) + { + PListItem tmp = h; + h = h->NextPurge; + delete tmp; + }; + + }; + + template + typename std::pair::iterator, bool> hash_multimap::insert(const value_type & Val) + { + int gc = addRef(); + PListItem node = new TListItem; + node->Value = Val; + node->Hash = FHash(&node->Value.first, sizeof(TKey)) | 1; + node->NextPurge = NULL; + node->Next = NULL; + + void * tmp; + void * newdata; + tmp = (void*)m_HashTableData; + + uint32_t mask = getMask(HashTableSize(tmp)); + + uint32_t bucket = node->Hash & mask; + PListItem bucketnode = getBucket(bucket); + + if (bucketnode == NULL) + bucketnode = initializeBucket(bucket, mask); + PListItem retnode = listInsert(bucketnode, node); + if (retnode != node) + { + delete node; + return std::make_pair(iterator(this, retnode, gc), false); + } + + if ((INC_32(m_Count) > ((uint32_t)1 << (HashTableSize(tmp) + 3))) && (HashTableSize(tmp) < 31) && (HashTableSize(tmp) == HashTableSize(m_HashTableData))) + { + newdata = HashTable(HashTablePtr(tmp), HashTableSize(tmp) + 1); + + if ((HashTableSize(tmp) & 0x7) == 0) + { + newdata = HashTable(makeNewTable(), HashTableSize(tmp) + 1); + HashTablePtr(newdata)->Table[0] = (TListItem*)HashTablePtr(tmp); + + if (tmp != CMPXCHG_Ptr(m_HashTableData, newdata, tmp)) + destroyTable(HashTablePtr(newdata)); // someone else expanded the table. + } else { + CMPXCHG_Ptr(m_HashTableData, newdata, tmp); + } + + } + + return std::make_pair(iterator(this, node, gc), true); + }; + + template + typename hash_multimap::iterator hash_multimap::find(const TKey & Key) + { + int gc = addRef(); + uint32_t hash = FHash(&Key, sizeof(TKey)) | 1; + uint32_t mask = getMask(HashTableSize(m_HashTableData)); + uint32_t bucket = hash & mask; + PListItem bucketnode = getBucket(bucket); + if (bucketnode == NULL) + bucketnode = initializeBucket(bucket, mask); + + PListItem volatile * prev; + PListItem curr, next; + if (listFind(bucketnode, hash, Key, NULL, prev, curr, next)) + return iterator(this, NodePointer(curr), gc); + + return iterator(this, NULL, gc); + }; + + template + typename hash_multimap::iterator hash_multimap::erase(const iterator & Where) + { + int gc = addRef(); + uint32_t hash = Where.m_Item->Hash; + uint32_t mask = getMask(HashTableSize(m_HashTableData)); + uint32_t bucket = hash & mask; + PListItem bucketnode = getBucket(bucket); + + if (bucketnode == NULL) + bucketnode = initializeBucket(bucket, mask); + + PListItem res = listDelete(bucketnode, Where.m_Item); + if (Where.m_Item == res) + { + DEC_32(m_Count); + return iterator(this, NodePointer(res->Next), gc); + } + return iterator(this, res, gc); + }; + + template + size_t hash_multimap::erase(const TKey & Key) + { + int gc = addRef(); + int count = 0; + uint32_t hash = FHash(&Key, sizeof(TKey)) | 1; + uint32_t mask = getMask(HashTableSize(m_HashTableData)); + uint32_t bucket = hash & mask; + PListItem bucketnode = getBucket(bucket); + + if (bucketnode == NULL) + bucketnode = initializeBucket(bucket, mask); + + PListItem volatile * prev; + PListItem curr, next; + while (listFind(bucketnode, hash, Key, NULL, prev, curr, next)) + { + if (curr == listDelete(bucketnode, curr)) + count++; + } + + XADD_32(m_Count, -count); + delRef(gc); + return count; + }; +} + +#undef NodePointer +#undef NodeMark + +#undef HashTablePtr +#undef HashTableSize +#undef HashTable + +#undef GCSelection +#undef GCRefCount0 +#undef GCRefCount1 +#undef GCMakeSentinel + diff --git a/plugins/Dbx_tree/src/savestrings_gcc.h b/plugins/Dbx_tree/src/savestrings_gcc.h new file mode 100644 index 0000000000..9da680874d --- /dev/null +++ b/plugins/Dbx_tree/src/savestrings_gcc.h @@ -0,0 +1,127 @@ +/* + +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. + +*/ + +#pragma once + +inline int strcpy_s( + char *strDestination, + size_t numberOfElements, + const char *strSource +) +{ + if (!strDestination) return EINVAL; + if (!strSource) {strDestination[0] = 0; return EINVAL;} + size_t l = strlen(strSource); + if (numberOfElements < l + 1) {strDestination[0] = 0; return ERANGE;} + memcpy(strDestination, strSource, l + 1); + return 0; +} + +template +inline int strcpy_s( + char (&strDestination)[size], + const char *strSource +) +{ + if (!strDestination) return EINVAL; + if (!strSource) {strDestination[0] = 0; return EINVAL;} + size_t l = strlen(strSource); + if (size < l + 1) {strDestination[0] = 0; return ERANGE;} + + memcpy(strDestination, strSource, l + 1); + return 0; +} + + +inline int strcat_s( + char *strDestination, + size_t numberOfElements, + const char *strSource +) +{ + if (!strDestination) return EINVAL; + if (!strSource) {strDestination[0] = 0; return EINVAL;} + size_t l = strlen(strSource); + size_t m = strlen(strDestination); + if (numberOfElements < l + m + 1) {strDestination[0] = 0; return ERANGE;} + + memcpy(&strDestination[m], strSource, l + 1); + return 0; +} + +template +inline int strcat_s( + char (&strDestination)[size], + const char *strSource +) +{ + if (!strDestination) return EINVAL; + if (!strSource) {strDestination[0] = 0; return EINVAL;} + size_t l = strlen(strSource); + size_t m = strlen(strDestination); + if (size < l + m + 1) {strDestination[0] = 0; return ERANGE;} + + memcpy(&strDestination[m], strSource, l + 1); + return 0; +} + +inline int strncpy_s( + char *strDest, + size_t numberOfElements, + const char *strSource, + size_t count +) +{ + if (count > numberOfElements) + return strcpy_s(strDest, numberOfElements, strSource); + else + return strcpy_s(strDest, count + 1, strSource); +} + + +template +inline int sprintf_s( + char (&buffer)[size], + const char *format, + ... +) +{ + va_list va; + va_start(va, format); + vsnprintf(buffer, size, format, va); + va_end(va); +} + +template +inline int swprintf_s( + wchar_t (&buffer)[size], + const wchar_t *format, + ... +) +{ + va_list va; + va_start(va, format); + vsnwprintf(buffer, size, format, va); + va_end(va); +} + +#define vsprintf_s vsnprintf diff --git a/plugins/Dbx_tree/src/sigslot.h b/plugins/Dbx_tree/src/sigslot.h new file mode 100644 index 0000000000..1e67a152bf --- /dev/null +++ b/plugins/Dbx_tree/src/sigslot.h @@ -0,0 +1,2639 @@ +// sigslot.h: Signal/Slot classes +// +// Written by Sarah Thompson (sarah@telergy.com) 2002. +// +// License: Public domain. You are free to use this code however you like, with the proviso that +// the author takes on no responsibility or liability for any use. +// +// QUICK DOCUMENTATION +// +// (see also the full documentation at http://sigslot.sourceforge.net/) +// +// #define switches +// SIGSLOT_PURE_ISO - Define this to force ISO C++ compliance. This also disables +// all of the thread safety support on platforms where it is +// available. +// +// SIGSLOT_USE_POSIX_THREADS - Force use of Posix threads when using a C++ compiler other than +// gcc on a platform that supports Posix threads. (When using gcc, +// this is the default - use SIGSLOT_PURE_ISO to disable this if +// necessary) +// +// SIGSLOT_DEFAULT_MT_POLICY - Where thread support is enabled, this defaults to multi_threaded_global. +// Otherwise, the default is single_threaded. #define this yourself to +// override the default. In pure ISO mode, anything other than +// single_threaded will cause a compiler error. +// +// PLATFORM NOTES +// +// Win32 - On Win32, the WIN32 symbol must be #defined. Most mainstream +// compilers do this by default, but you may need to define it +// yourself if your build environment is less standard. This causes +// the Win32 thread support to be compiled in and used automatically. +// +// Unix/Linux/BSD, etc. - If you're using gcc, it is assumed that you have Posix threads +// available, so they are used automatically. You can override this +// (as under Windows) with the SIGSLOT_PURE_ISO switch. If you're using +// something other than gcc but still want to use Posix threads, you +// need to #define SIGSLOT_USE_POSIX_THREADS. +// +// ISO C++ - If none of the supported platforms are detected, or if +// SIGSLOT_PURE_ISO is defined, all multithreading support is turned off, +// along with any code that might cause a pure ISO C++ environment to +// complain. Before you ask, gcc -ansi -pedantic won't compile this +// library, but gcc -ansi is fine. Pedantic mode seems to throw a lot of +// errors that aren't really there. If you feel like investigating this, +// please contact the author. +// +// +// THREADING MODES +// +// single_threaded - Your program is assumed to be single threaded from the point of view +// of signal/slot usage (i.e. all objects using signals and slots are +// created and destroyed from a single thread). Behaviour if objects are +// destroyed concurrently is undefined (i.e. you'll get the occasional +// segmentation fault/memory exception). +// +// multi_threaded_global - Your program is assumed to be multi threaded. Objects using signals and +// slots can be safely created and destroyed from any thread, even when +// connections exist. In multi_threaded_global mode, this is achieved by a +// single global mutex (actually a critical section on Windows because they +// are faster). This option uses less OS resources, but results in more +// opportunities for contention, possibly resulting in more context switches +// than are strictly necessary. +// +// multi_threaded_local - Behaviour in this mode is essentially the same as multi_threaded_global, +// except that each signal, and each object that inherits has_slots, all +// have their own mutex/critical section. In practice, this means that +// mutex collisions (and hence context switches) only happen if they are +// absolutely essential. However, on some platforms, creating a lot of +// mutexes can slow down the whole OS, so use this option with care. +// +// USING THE LIBRARY +// +// See the full documentation at http://sigslot.sourceforge.net/ +// +// + +#ifndef SIGSLOT_H__ +#define SIGSLOT_H__ + +#include +#include + +#if defined(SIGSLOT_PURE_ISO) || (!defined(WIN32) && !defined(__GNUG__) && !defined(SIGSLOT_USE_POSIX_THREADS)) +# define _SIGSLOT_SINGLE_THREADED +#elif defined(WIN32) +# define _SIGSLOT_HAS_WIN32_THREADS +# include +#elif defined(__GNUG__) || defined(SIGSLOT_USE_POSIX_THREADS) +# define _SIGSLOT_HAS_POSIX_THREADS +# include +#else +# define _SIGSLOT_SINGLE_THREADED +#endif + +#define SIGSLOT_DEFAULT_MT_POLICY multi_threaded_global + +#ifndef SIGSLOT_DEFAULT_MT_POLICY +# ifdef _SIGSLOT_SINGLE_THREADED +# define SIGSLOT_DEFAULT_MT_POLICY single_threaded +# else +# define SIGSLOT_DEFAULT_MT_POLICY multi_threaded_local +# endif +#endif + + +namespace sigslot { + + class single_threaded + { + public: + single_threaded() + { + ; + } + + ~single_threaded() + { + ; + } + + void lock() + { + ; + } + + void unlock() + { + ; + } + }; + +#ifdef _SIGSLOT_HAS_WIN32_THREADS + // The multi threading policies only get compiled in if they are enabled. + class multi_threaded_global + { + public: + multi_threaded_global() + { + static bool isinitialised = false; + + if (!isinitialised) + { + InitializeCriticalSection(get_critsec()); + isinitialised = true; + } + } + + multi_threaded_global(const multi_threaded_global&) + { + ; + } + + ~multi_threaded_global() + { + ; + } + + void lock() + { + EnterCriticalSection(get_critsec()); + } + + void unlock() + { + LeaveCriticalSection(get_critsec()); + } + + private: + CRITICAL_SECTION* get_critsec() + { + static CRITICAL_SECTION g_critsec; + return &g_critsec; + } + }; + + class multi_threaded_local + { + public: + multi_threaded_local() + { + InitializeCriticalSection(&m_critsec); + } + + multi_threaded_local(const multi_threaded_local&) + { + InitializeCriticalSection(&m_critsec); + } + + ~multi_threaded_local() + { + DeleteCriticalSection(&m_critsec); + } + + void lock() + { + EnterCriticalSection(&m_critsec); + } + + void unlock() + { + LeaveCriticalSection(&m_critsec); + } + + private: + CRITICAL_SECTION m_critsec; + }; +#endif // _SIGSLOT_HAS_WIN32_THREADS + +#ifdef _SIGSLOT_HAS_POSIX_THREADS + // The multi threading policies only get compiled in if they are enabled. + class multi_threaded_global + { + public: + multi_threaded_global() + { + pthread_mutex_init(get_mutex(), NULL); + } + + multi_threaded_global(const multi_threaded_global&) + { + ; + } + + ~multi_threaded_global() + { + ; + } + + void lock() + { + pthread_mutex_lock(get_mutex()); + } + + void unlock() + { + pthread_mutex_unlock(get_mutex()); + } + + private: + pthread_mutex_t* get_mutex() + { + static pthread_mutex_t g_mutex; + return &g_mutex; + } + }; + + class multi_threaded_local + { + public: + multi_threaded_local() + { + pthread_mutex_init(&m_mutex, NULL); + } + + multi_threaded_local(const multi_threaded_local&) + { + pthread_mutex_init(&m_mutex, NULL); + } + + ~multi_threaded_local() + { + pthread_mutex_destroy(&m_mutex); + } + + void lock() + { + pthread_mutex_lock(&m_mutex); + } + + void unlock() + { + pthread_mutex_unlock(&m_mutex); + } + + private: + pthread_mutex_t m_mutex; + }; +#endif // _SIGSLOT_HAS_POSIX_THREADS + + template + class lock_block + { + public: + mt_policy *m_mutex; + + lock_block(mt_policy *mtx) + : m_mutex(mtx) + { + m_mutex->lock(); + } + + ~lock_block() + { + m_mutex->unlock(); + } + }; + + template + class has_slots; + + template + class _connection_base0 + { + public: + virtual ~_connection_base0() { ; } + virtual has_slots* getdest() const = 0; + virtual void emit() = 0; + virtual _connection_base0* clone() = 0; + virtual _connection_base0* duplicate(has_slots* pnewdest) = 0; + }; + + template + class _connection_base1 + { + public: + virtual ~_connection_base1() { ; } + virtual has_slots* getdest() const = 0; + virtual void emit(arg1_type) = 0; + virtual _connection_base1* clone() = 0; + virtual _connection_base1* duplicate(has_slots* pnewdest) = 0; + }; + + template + class _connection_base2 + { + public: + virtual ~_connection_base2() { ; } + virtual has_slots* getdest() const = 0; + virtual void emit(arg1_type, arg2_type) = 0; + virtual _connection_base2* clone() = 0; + virtual _connection_base2* duplicate(has_slots* pnewdest) = 0; + }; + + template + class _connection_base3 + { + public: + virtual ~_connection_base3() { ; } + virtual has_slots* getdest() const = 0; + virtual void emit(arg1_type, arg2_type, arg3_type) = 0; + virtual _connection_base3* clone() = 0; + virtual _connection_base3* duplicate(has_slots* pnewdest) = 0; + }; + + template + class _connection_base4 + { + public: + virtual ~_connection_base4() { ; } + virtual has_slots* getdest() const = 0; + virtual void emit(arg1_type, arg2_type, arg3_type, arg4_type) = 0; + virtual _connection_base4* clone() = 0; + virtual _connection_base4* duplicate(has_slots* pnewdest) = 0; + }; + + template + class _connection_base5 + { + public: + virtual ~_connection_base5() { ; } + virtual has_slots* getdest() const = 0; + virtual void emit(arg1_type, arg2_type, arg3_type, arg4_type, + arg5_type) = 0; + virtual _connection_base5* clone() = 0; + virtual _connection_base5* duplicate(has_slots* pnewdest) = 0; + }; + + template + class _connection_base6 + { + public: + virtual ~_connection_base6() { ; } + virtual has_slots* getdest() const = 0; + virtual void emit(arg1_type, arg2_type, arg3_type, arg4_type, arg5_type, + arg6_type) = 0; + virtual _connection_base6* clone() = 0; + virtual _connection_base6* duplicate(has_slots* pnewdest) = 0; + }; + + template + class _connection_base7 + { + public: + virtual ~_connection_base7() { ; } + virtual has_slots* getdest() const = 0; + virtual void emit(arg1_type, arg2_type, arg3_type, arg4_type, arg5_type, + arg6_type, arg7_type) = 0; + virtual _connection_base7* clone() = 0; + virtual _connection_base7* duplicate(has_slots* pnewdest) = 0; + }; + + template + class _connection_base8 + { + public: + virtual ~_connection_base8() { ; } + virtual has_slots* getdest() const = 0; + virtual void emit(arg1_type, arg2_type, arg3_type, arg4_type, arg5_type, + arg6_type, arg7_type, arg8_type) = 0; + virtual _connection_base8* clone() = 0; + virtual _connection_base8* duplicate(has_slots* pnewdest) = 0; + }; + + template + class _signal_base : public mt_policy + { + public: + virtual void slot_disconnect(has_slots* pslot) = 0; + virtual void slot_duplicate(const has_slots* poldslot, has_slots* pnewslot) = 0; + }; + + template + class has_slots : public mt_policy + { + private: + typedef typename std::set<_signal_base *> sender_set; + typedef typename sender_set::const_iterator const_iterator; + + public: + has_slots() + { + ; + } + + has_slots(const has_slots& hs) + : mt_policy(hs) + { + lock_block lock(this); + const_iterator it = hs.m_senders.begin(); + const_iterator itEnd = hs.m_senders.end(); + + while(it != itEnd) + { + (*it)->slot_duplicate(&hs, this); + m_senders.insert(*it); + ++it; + } + } + + void signal_connect(_signal_base* sender) + { + lock_block lock(this); + m_senders.insert(sender); + } + + void signal_disconnect(_signal_base* sender) + { + lock_block lock(this); + m_senders.erase(sender); + } + + virtual ~has_slots() + { + disconnect_all(); + } + + void disconnect_all() + { + lock_block lock(this); + const_iterator it = m_senders.begin(); + const_iterator itEnd = m_senders.end(); + + while(it != itEnd) + { + (*it)->slot_disconnect(this); + ++it; + } + + m_senders.erase(m_senders.begin(), m_senders.end()); + } + + private: + sender_set m_senders; + }; + + template + class _signal_base0 : public _signal_base + { + public: + typedef typename std::list<_connection_base0 *> connections_list; + typedef typename connections_list::const_iterator const_iterator; + typedef typename connections_list::iterator iterator; + + _signal_base0() + { + ; + } + + _signal_base0(const _signal_base0& s) + : _signal_base(s) + { + lock_block lock(this); + const_iterator it = s.m_connected_slots.begin(); + const_iterator itEnd = s.m_connected_slots.end(); + + while(it != itEnd) + { + (*it)->getdest()->signal_connect(this); + m_connected_slots.push_back((*it)->clone()); + + ++it; + } + } + + ~_signal_base0() + { + disconnect_all(); + } + + void disconnect_all() + { + lock_block lock(this); + const_iterator it = m_connected_slots.begin(); + const_iterator itEnd = m_connected_slots.end(); + + while(it != itEnd) + { + (*it)->getdest()->signal_disconnect(this); + delete *it; + + ++it; + } + + m_connected_slots.erase(m_connected_slots.begin(), m_connected_slots.end()); + } + + void disconnect(has_slots* pclass) + { + lock_block lock(this); + iterator it = m_connected_slots.begin(); + iterator itEnd = m_connected_slots.end(); + + while(it != itEnd) + { + if ((*it)->getdest() == pclass) + { + delete *it; + m_connected_slots.erase(it); + pclass->signal_disconnect(this); + return; + } + + ++it; + } + } + + void slot_disconnect(has_slots* pslot) + { + lock_block lock(this); + iterator it = m_connected_slots.begin(); + iterator itEnd = m_connected_slots.end(); + + while(it != itEnd) + { + iterator itNext = it; + ++itNext; + + if ((*it)->getdest() == pslot) + { + delete *it; + m_connected_slots.erase(it); + // delete *it; + } + + it = itNext; + } + } + + void slot_duplicate(const has_slots* oldtarget, has_slots* newtarget) + { + lock_block lock(this); + iterator it = m_connected_slots.begin(); + iterator itEnd = m_connected_slots.end(); + + while(it != itEnd) + { + if ((*it)->getdest() == oldtarget) + { + m_connected_slots.push_back((*it)->duplicate(newtarget)); + } + + ++it; + } + } + + protected: + connections_list m_connected_slots; + }; + + template + class _signal_base1 : public _signal_base + { + public: + typedef typename std::list<_connection_base1 *> connections_list; + typedef typename connections_list::const_iterator const_iterator; + typedef typename connections_list::iterator iterator; + + _signal_base1() + { + ; + } + + _signal_base1(const _signal_base1& s) + : _signal_base(s) + { + lock_block lock(this); + const_iterator it = s.m_connected_slots.begin(); + const_iterator itEnd = s.m_connected_slots.end(); + + while(it != itEnd) + { + (*it)->getdest()->signal_connect(this); + m_connected_slots.push_back((*it)->clone()); + + ++it; + } + } + + void slot_duplicate(const has_slots* oldtarget, has_slots* newtarget) + { + lock_block lock(this); + iterator it = m_connected_slots.begin(); + iterator itEnd = m_connected_slots.end(); + + while(it != itEnd) + { + if ((*it)->getdest() == oldtarget) + { + m_connected_slots.push_back((*it)->duplicate(newtarget)); + } + + ++it; + } + } + + ~_signal_base1() + { + disconnect_all(); + } + + void disconnect_all() + { + lock_block lock(this); + const_iterator it = m_connected_slots.begin(); + const_iterator itEnd = m_connected_slots.end(); + + while(it != itEnd) + { + (*it)->getdest()->signal_disconnect(this); + delete *it; + + ++it; + } + + m_connected_slots.erase(m_connected_slots.begin(), m_connected_slots.end()); + } + + void disconnect(has_slots* pclass) + { + lock_block lock(this); + iterator it = m_connected_slots.begin(); + iterator itEnd = m_connected_slots.end(); + + while(it != itEnd) + { + if ((*it)->getdest() == pclass) + { + delete *it; + m_connected_slots.erase(it); + pclass->signal_disconnect(this); + return; + } + + ++it; + } + } + + void slot_disconnect(has_slots* pslot) + { + lock_block lock(this); + iterator it = m_connected_slots.begin(); + iterator itEnd = m_connected_slots.end(); + + while(it != itEnd) + { + iterator itNext = it; + ++itNext; + + if ((*it)->getdest() == pslot) + { + delete *it; + m_connected_slots.erase(it); + // delete *it; + } + + it = itNext; + } + } + + + protected: + connections_list m_connected_slots; + }; + + template + class _signal_base2 : public _signal_base + { + public: + typedef typename std::list<_connection_base2 *> + connections_list; + typedef typename connections_list::const_iterator const_iterator; + typedef typename connections_list::iterator iterator; + + _signal_base2() + { + ; + } + + _signal_base2(const _signal_base2& s) + : _signal_base(s) + { + lock_block lock(this); + const_iterator it = s.m_connected_slots.begin(); + const_iterator itEnd = s.m_connected_slots.end(); + + while(it != itEnd) + { + (*it)->getdest()->signal_connect(this); + m_connected_slots.push_back((*it)->clone()); + + ++it; + } + } + + void slot_duplicate(const has_slots* oldtarget, has_slots* newtarget) + { + lock_block lock(this); + iterator it = m_connected_slots.begin(); + iterator itEnd = m_connected_slots.end(); + + while(it != itEnd) + { + if ((*it)->getdest() == oldtarget) + { + m_connected_slots.push_back((*it)->duplicate(newtarget)); + } + + ++it; + } + } + + ~_signal_base2() + { + disconnect_all(); + } + + void disconnect_all() + { + lock_block lock(this); + const_iterator it = m_connected_slots.begin(); + const_iterator itEnd = m_connected_slots.end(); + + while(it != itEnd) + { + (*it)->getdest()->signal_disconnect(this); + delete *it; + + ++it; + } + + m_connected_slots.erase(m_connected_slots.begin(), m_connected_slots.end()); + } + + void disconnect(has_slots* pclass) + { + lock_block lock(this); + iterator it = m_connected_slots.begin(); + iterator itEnd = m_connected_slots.end(); + + while(it != itEnd) + { + if ((*it)->getdest() == pclass) + { + delete *it; + m_connected_slots.erase(it); + pclass->signal_disconnect(this); + return; + } + + ++it; + } + } + + void slot_disconnect(has_slots* pslot) + { + lock_block lock(this); + iterator it = m_connected_slots.begin(); + iterator itEnd = m_connected_slots.end(); + + while(it != itEnd) + { + iterator itNext = it; + ++itNext; + + if ((*it)->getdest() == pslot) + { + delete *it; + m_connected_slots.erase(it); + // delete *it; + } + + it = itNext; + } + } + + protected: + connections_list m_connected_slots; + }; + + template + class _signal_base3 : public _signal_base + { + public: + typedef std::list<_connection_base3 *> + connections_list; + + typedef typename connections_list::const_iterator const_iterator; + typedef typename connections_list::iterator iterator; + _signal_base3() + { + ; + } + + _signal_base3(const _signal_base3& s) + : _signal_base(s) + { + lock_block lock(this); + const_iterator it = s.m_connected_slots.begin(); + const_iterator itEnd = s.m_connected_slots.end(); + + while(it != itEnd) + { + (*it)->getdest()->signal_connect(this); + m_connected_slots.push_back((*it)->clone()); + + ++it; + } + } + + void slot_duplicate(const has_slots* oldtarget, has_slots* newtarget) + { + lock_block lock(this); + iterator it = m_connected_slots.begin(); + iterator itEnd = m_connected_slots.end(); + + while(it != itEnd) + { + if ((*it)->getdest() == oldtarget) + { + m_connected_slots.push_back((*it)->duplicate(newtarget)); + } + + ++it; + } + } + + ~_signal_base3() + { + disconnect_all(); + } + + void disconnect_all() + { + lock_block lock(this); + const_iterator it = m_connected_slots.begin(); + const_iterator itEnd = m_connected_slots.end(); + + while(it != itEnd) + { + (*it)->getdest()->signal_disconnect(this); + delete *it; + + ++it; + } + + m_connected_slots.erase(m_connected_slots.begin(), m_connected_slots.end()); + } + + void disconnect(has_slots* pclass) + { + lock_block lock(this); + iterator it = m_connected_slots.begin(); + iterator itEnd = m_connected_slots.end(); + + while(it != itEnd) + { + if ((*it)->getdest() == pclass) + { + delete *it; + m_connected_slots.erase(it); + pclass->signal_disconnect(this); + return; + } + + ++it; + } + } + + void slot_disconnect(has_slots* pslot) + { + lock_block lock(this); + iterator it = m_connected_slots.begin(); + iterator itEnd = m_connected_slots.end(); + + while(it != itEnd) + { + iterator itNext = it; + ++itNext; + + if ((*it)->getdest() == pslot) + { + delete *it; + m_connected_slots.erase(it); + // delete *it; + } + + it = itNext; + } + } + + protected: + connections_list m_connected_slots; + }; + + template + class _signal_base4 : public _signal_base + { + public: + typedef std::list<_connection_base4 *> connections_list; + typedef typename connections_list::const_iterator const_iterator; + typedef typename connections_list::iterator iterator; + + _signal_base4() + { + ; + } + + _signal_base4(const _signal_base4& s) + : _signal_base(s) + { + lock_block lock(this); + const_iterator it = s.m_connected_slots.begin(); + const_iterator itEnd = s.m_connected_slots.end(); + + while(it != itEnd) + { + (*it)->getdest()->signal_connect(this); + m_connected_slots.push_back((*it)->clone()); + + ++it; + } + } + + void slot_duplicate(const has_slots* oldtarget, has_slots* newtarget) + { + lock_block lock(this); + iterator it = m_connected_slots.begin(); + iterator itEnd = m_connected_slots.end(); + + while(it != itEnd) + { + if ((*it)->getdest() == oldtarget) + { + m_connected_slots.push_back((*it)->duplicate(newtarget)); + } + + ++it; + } + } + + ~_signal_base4() + { + disconnect_all(); + } + + void disconnect_all() + { + lock_block lock(this); + const_iterator it = m_connected_slots.begin(); + const_iterator itEnd = m_connected_slots.end(); + + while(it != itEnd) + { + (*it)->getdest()->signal_disconnect(this); + delete *it; + + ++it; + } + + m_connected_slots.erase(m_connected_slots.begin(), m_connected_slots.end()); + } + + void disconnect(has_slots* pclass) + { + lock_block lock(this); + iterator it = m_connected_slots.begin(); + iterator itEnd = m_connected_slots.end(); + + while(it != itEnd) + { + if ((*it)->getdest() == pclass) + { + delete *it; + this->m_connected_slots.erase(it); + pclass->signal_disconnect(this); + return; + } + + ++it; + } + } + + void slot_disconnect(has_slots* pslot) + { + lock_block lock(this); + iterator it = m_connected_slots.begin(); + iterator itEnd = m_connected_slots.end(); + + while(it != itEnd) + { + iterator itNext = it; + ++itNext; + + if ((*it)->getdest() == pslot) + { + delete *it; + m_connected_slots.erase(it); + // delete *it; + } + + it = itNext; + } + } + + protected: + connections_list m_connected_slots; + }; + + template + class _signal_base5 : public _signal_base + { + public: + typedef std::list<_connection_base5 *> connections_list; + typedef typename connections_list::const_iterator const_iterator; + typedef typename connections_list::iterator iterator; + + _signal_base5() + { + ; + } + + _signal_base5(const _signal_base5& s) + : _signal_base(s) + { + lock_block lock(this); + const_iterator it = s.m_connected_slots.begin(); + const_iterator itEnd = s.m_connected_slots.end(); + + while(it != itEnd) + { + (*it)->getdest()->signal_connect(this); + m_connected_slots.push_back((*it)->clone()); + + ++it; + } + } + + void slot_duplicate(const has_slots* oldtarget, has_slots* newtarget) + { + lock_block lock(this); + iterator it = m_connected_slots.begin(); + iterator itEnd = m_connected_slots.end(); + + while(it != itEnd) + { + if ((*it)->getdest() == oldtarget) + { + m_connected_slots.push_back((*it)->duplicate(newtarget)); + } + + ++it; + } + } + + ~_signal_base5() + { + disconnect_all(); + } + + void disconnect_all() + { + lock_block lock(this); + const_iterator it = m_connected_slots.begin(); + const_iterator itEnd = m_connected_slots.end(); + + while(it != itEnd) + { + (*it)->getdest()->signal_disconnect(this); + delete *it; + + ++it; + } + + m_connected_slots.erase(m_connected_slots.begin(), m_connected_slots.end()); + } + + void disconnect(has_slots* pclass) + { + lock_block lock(this); + iterator it = m_connected_slots.begin(); + iterator itEnd = m_connected_slots.end(); + + while(it != itEnd) + { + if ((*it)->getdest() == pclass) + { + delete *it; + m_connected_slots.erase(it); + pclass->signal_disconnect(this); + return; + } + + ++it; + } + } + + void slot_disconnect(has_slots* pslot) + { + lock_block lock(this); + iterator it = m_connected_slots.begin(); + iterator itEnd = m_connected_slots.end(); + + while(it != itEnd) + { + iterator itNext = it; + ++itNext; + + if ((*it)->getdest() == pslot) + { + delete *it; + m_connected_slots.erase(it); + // delete *it; + } + + it = itNext; + } + } + + protected: + connections_list m_connected_slots; + }; + + template + class _signal_base6 : public _signal_base + { + public: + typedef std::list<_connection_base6 *> connections_list; + typedef typename connections_list::const_iterator const_iterator; + typedef typename connections_list::iterator iterator; + + _signal_base6() + { + ; + } + + _signal_base6(const _signal_base6& s) + : _signal_base(s) + { + lock_block lock(this); + const_iterator it = s.m_connected_slots.begin(); + const_iterator itEnd = s.m_connected_slots.end(); + + while(it != itEnd) + { + (*it)->getdest()->signal_connect(this); + m_connected_slots.push_back((*it)->clone()); + + ++it; + } + } + + void slot_duplicate(const has_slots* oldtarget, has_slots* newtarget) + { + lock_block lock(this); + iterator it = m_connected_slots.begin(); + iterator itEnd = m_connected_slots.end(); + + while(it != itEnd) + { + if ((*it)->getdest() == oldtarget) + { + m_connected_slots.push_back((*it)->duplicate(newtarget)); + } + + ++it; + } + } + + ~_signal_base6() + { + disconnect_all(); + } + + void disconnect_all() + { + lock_block lock(this); + const_iterator it = m_connected_slots.begin(); + const_iterator itEnd = m_connected_slots.end(); + + while(it != itEnd) + { + (*it)->getdest()->signal_disconnect(this); + delete *it; + + ++it; + } + + m_connected_slots.erase(m_connected_slots.begin(), m_connected_slots.end()); + } + + void disconnect(has_slots* pclass) + { + lock_block lock(this); + iterator it = m_connected_slots.begin(); + iterator itEnd = m_connected_slots.end(); + + while(it != itEnd) + { + if ((*it)->getdest() == pclass) + { + delete *it; + m_connected_slots.erase(it); + pclass->signal_disconnect(this); + return; + } + + ++it; + } + } + + void slot_disconnect(has_slots* pslot) + { + lock_block lock(this); + iterator it = m_connected_slots.begin(); + iterator itEnd = m_connected_slots.end(); + + while(it != itEnd) + { + iterator itNext = it; + ++itNext; + + if ((*it)->getdest() == pslot) + { + delete *it; + m_connected_slots.erase(it); + // delete *it; + } + + it = itNext; + } + } + + protected: + connections_list m_connected_slots; + }; + + template + class _signal_base7 : public _signal_base + { + public: + typedef std::list<_connection_base7 *> connections_list; + typedef typename connections_list::const_iterator const_iterator; + typedef typename connections_list::iterator iterator; + + _signal_base7() + { + ; + } + + _signal_base7(const _signal_base7& s) + : _signal_base(s) + { + lock_block lock(this); + const_iterator it = s.m_connected_slots.begin(); + const_iterator itEnd = s.m_connected_slots.end(); + + while(it != itEnd) + { + (*it)->getdest()->signal_connect(this); + m_connected_slots.push_back((*it)->clone()); + + ++it; + } + } + + void slot_duplicate(const has_slots* oldtarget, has_slots* newtarget) + { + lock_block lock(this); + iterator it = m_connected_slots.begin(); + iterator itEnd = m_connected_slots.end(); + + while(it != itEnd) + { + if ((*it)->getdest() == oldtarget) + { + m_connected_slots.push_back((*it)->duplicate(newtarget)); + } + + ++it; + } + } + + ~_signal_base7() + { + disconnect_all(); + } + + void disconnect_all() + { + lock_block lock(this); + const_iterator it = m_connected_slots.begin(); + const_iterator itEnd = m_connected_slots.end(); + + while(it != itEnd) + { + (*it)->getdest()->signal_disconnect(this); + delete *it; + + ++it; + } + + m_connected_slots.erase(m_connected_slots.begin(), m_connected_slots.end()); + } + + void disconnect(has_slots* pclass) + { + lock_block lock(this); + iterator it = m_connected_slots.begin(); + iterator itEnd = m_connected_slots.end(); + + while(it != itEnd) + { + if ((*it)->getdest() == pclass) + { + delete *it; + m_connected_slots.erase(it); + pclass->signal_disconnect(this); + return; + } + + ++it; + } + } + + void slot_disconnect(has_slots* pslot) + { + lock_block lock(this); + iterator it = m_connected_slots.begin(); + iterator itEnd = m_connected_slots.end(); + + while(it != itEnd) + { + iterator itNext = it; + ++itNext; + + if ((*it)->getdest() == pslot) + { + delete *it; + m_connected_slots.erase(it); + // delete *it; + } + + it = itNext; + } + } + + protected: + connections_list m_connected_slots; + }; + + template + class _signal_base8 : public _signal_base + { + public: + typedef std::list<_connection_base8 *> + connections_list; + typedef typename connections_list::const_iterator const_iterator; + typedef typename connections_list::iterator iterator; + + _signal_base8() + { + ; + } + + _signal_base8(const _signal_base8& s) + : _signal_base(s) + { + lock_block lock(this); + const_iterator it = s.m_connected_slots.begin(); + const_iterator itEnd = s.m_connected_slots.end(); + + while(it != itEnd) + { + (*it)->getdest()->signal_connect(this); + m_connected_slots.push_back((*it)->clone()); + + ++it; + } + } + + void slot_duplicate(const has_slots* oldtarget, has_slots* newtarget) + { + lock_block lock(this); + iterator it = m_connected_slots.begin(); + iterator itEnd = m_connected_slots.end(); + + while(it != itEnd) + { + if ((*it)->getdest() == oldtarget) + { + m_connected_slots.push_back((*it)->duplicate(newtarget)); + } + + ++it; + } + } + + ~_signal_base8() + { + disconnect_all(); + } + + void disconnect_all() + { + lock_block lock(this); + const_iterator it = m_connected_slots.begin(); + const_iterator itEnd = m_connected_slots.end(); + + while(it != itEnd) + { + (*it)->getdest()->signal_disconnect(this); + delete *it; + + ++it; + } + + m_connected_slots.erase(m_connected_slots.begin(), m_connected_slots.end()); + } + + void disconnect(has_slots* pclass) + { + lock_block lock(this); + iterator it = m_connected_slots.begin(); + iterator itEnd = m_connected_slots.end(); + + while(it != itEnd) + { + if ((*it)->getdest() == pclass) + { + delete *it; + m_connected_slots.erase(it); + pclass->signal_disconnect(this); + return; + } + + ++it; + } + } + + void slot_disconnect(has_slots* pslot) + { + lock_block lock(this); + iterator it = m_connected_slots.begin(); + iterator itEnd = m_connected_slots.end(); + + while(it != itEnd) + { + iterator itNext = it; + ++itNext; + + if ((*it)->getdest() == pslot) + { + delete *it; + m_connected_slots.erase(it); + // delete *it; + } + + it = itNext; + } + } + + protected: + connections_list m_connected_slots; + }; + + + template + class _connection0 : public _connection_base0 + { + public: + _connection0() + { + this->pobject = NULL; + this->pmemfun = NULL; + } + + _connection0(dest_type* pobject, void (dest_type::*pmemfun)()) + { + m_pobject = pobject; + m_pmemfun = pmemfun; + } + + virtual ~_connection0() + { + ; + } + + virtual _connection_base0* clone() + { + return new _connection0(*this); + } + + virtual _connection_base0* duplicate(has_slots* pnewdest) + { + return new _connection0((dest_type *)pnewdest, m_pmemfun); + } + + virtual void emit() + { + (m_pobject->*m_pmemfun)(); + } + + virtual has_slots* getdest() const + { + return m_pobject; + } + + private: + dest_type* m_pobject; + void (dest_type::* m_pmemfun)(); + }; + + template + class _connection1 : public _connection_base1 + { + public: + _connection1() + { + this->pobject = NULL; + this->pmemfun = NULL; + } + + _connection1(dest_type* pobject, void (dest_type::*pmemfun)(arg1_type)) + { + m_pobject = pobject; + m_pmemfun = pmemfun; + } + + virtual ~_connection1() + { + ; + } + + virtual _connection_base1* clone() + { + return new _connection1(*this); + } + + virtual _connection_base1* duplicate(has_slots* pnewdest) + { + return new _connection1((dest_type *)pnewdest, m_pmemfun); + } + + virtual void emit(arg1_type a1) + { + (m_pobject->*m_pmemfun)(a1); + } + + virtual has_slots* getdest() const + { + return m_pobject; + } + + private: + dest_type* m_pobject; + void (dest_type::* m_pmemfun)(arg1_type); + }; + + template + class _connection2 : public _connection_base2 + { + public: + _connection2() + { + this->pobject = NULL; + this->pmemfun = NULL; + } + + _connection2(dest_type* pobject, void (dest_type::*pmemfun)(arg1_type, + arg2_type)) + { + m_pobject = pobject; + m_pmemfun = pmemfun; + } + + virtual ~_connection2() + { + ; + } + + + virtual _connection_base2* clone() + { + return new _connection2(*this); + } + + virtual _connection_base2* duplicate(has_slots* pnewdest) + { + return new _connection2((dest_type *)pnewdest, m_pmemfun); + } + + virtual void emit(arg1_type a1, arg2_type a2) + { + (m_pobject->*m_pmemfun)(a1, a2); + } + + virtual has_slots* getdest() const + { + return m_pobject; + } + + private: + dest_type* m_pobject; + void (dest_type::* m_pmemfun)(arg1_type, arg2_type); + }; + + template + class _connection3 : public _connection_base3 + { + public: + _connection3() + { + this->pobject = NULL; + this->pmemfun = NULL; + } + + _connection3(dest_type* pobject, void (dest_type::*pmemfun)(arg1_type, + arg2_type, arg3_type)) + { + m_pobject = pobject; + m_pmemfun = pmemfun; + } + + virtual ~_connection3() + { + ; + } + + + virtual _connection_base3* clone() + { + return new _connection3(*this); + } + + virtual _connection_base3* duplicate(has_slots* pnewdest) + { + return new _connection3((dest_type *)pnewdest, m_pmemfun); + } + + virtual void emit(arg1_type a1, arg2_type a2, arg3_type a3) + { + (m_pobject->*m_pmemfun)(a1, a2, a3); + } + + virtual has_slots* getdest() const + { + return m_pobject; + } + + private: + dest_type* m_pobject; + void (dest_type::* m_pmemfun)(arg1_type, arg2_type, arg3_type); + }; + + template + class _connection4 : public _connection_base4 + { + public: + _connection4() + { + this->pobject = NULL; + this->pmemfun = NULL; + } + + _connection4(dest_type* pobject, void (dest_type::*pmemfun)(arg1_type, + arg2_type, arg3_type, arg4_type)) + { + m_pobject = pobject; + m_pmemfun = pmemfun; + } + + virtual ~_connection4() + { + ; + } + + virtual _connection_base4* clone() + { + return new _connection4(*this); + } + + virtual _connection_base4* duplicate(has_slots* pnewdest) + { + return new _connection4((dest_type *)pnewdest, m_pmemfun); + } + + virtual void emit(arg1_type a1, arg2_type a2, arg3_type a3, + arg4_type a4) + { + (m_pobject->*m_pmemfun)(a1, a2, a3, a4); + } + + virtual has_slots* getdest() const + { + return m_pobject; + } + + private: + dest_type* m_pobject; + void (dest_type::* m_pmemfun)(arg1_type, arg2_type, arg3_type, + arg4_type); + }; + + template + class _connection5 : public _connection_base5 + { + public: + _connection5() + { + this->pobject = NULL; + this->pmemfun = NULL; + } + + _connection5(dest_type* pobject, void (dest_type::*pmemfun)(arg1_type, + arg2_type, arg3_type, arg4_type, arg5_type)) + { + m_pobject = pobject; + m_pmemfun = pmemfun; + } + + virtual ~_connection5() + { + ; + } + + virtual _connection_base5* clone() + { + return new _connection5(*this); + } + + virtual _connection_base5* duplicate(has_slots* pnewdest) + { + return new _connection5((dest_type *)pnewdest, m_pmemfun); + } + + virtual void emit(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4, + arg5_type a5) + { + (m_pobject->*m_pmemfun)(a1, a2, a3, a4, a5); + } + + virtual has_slots* getdest() const + { + return m_pobject; + } + + private: + dest_type* m_pobject; + void (dest_type::* m_pmemfun)(arg1_type, arg2_type, arg3_type, arg4_type, + arg5_type); + }; + + template + class _connection6 : public _connection_base6 + { + public: + _connection6() + { + this->pobject = NULL; + this->pmemfun = NULL; + } + + _connection6(dest_type* pobject, void (dest_type::*pmemfun)(arg1_type, + arg2_type, arg3_type, arg4_type, arg5_type, arg6_type)) + { + m_pobject = pobject; + m_pmemfun = pmemfun; + } + + virtual ~_connection6() + { + ; + } + + virtual _connection_base6* clone() + { + return new _connection6(*this); + } + + virtual _connection_base6* duplicate(has_slots* pnewdest) + { + return new _connection6((dest_type *)pnewdest, m_pmemfun); + } + + virtual void emit(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4, + arg5_type a5, arg6_type a6) + { + (m_pobject->*m_pmemfun)(a1, a2, a3, a4, a5, a6); + } + + virtual has_slots* getdest() const + { + return m_pobject; + } + + private: + dest_type* m_pobject; + void (dest_type::* m_pmemfun)(arg1_type, arg2_type, arg3_type, arg4_type, + arg5_type, arg6_type); + }; + + template + class _connection7 : public _connection_base7 + { + public: + _connection7() + { + this->pobject = NULL; + this->pmemfun = NULL; + } + + _connection7(dest_type* pobject, void (dest_type::*pmemfun)(arg1_type, + arg2_type, arg3_type, arg4_type, arg5_type, arg6_type, arg7_type)) + { + m_pobject = pobject; + m_pmemfun = pmemfun; + } + + virtual ~_connection7() + { + ; + } + + virtual _connection_base7* clone() + { + return new _connection7(*this); + } + + virtual _connection_base7* duplicate(has_slots* pnewdest) + { + return new _connection7((dest_type *)pnewdest, m_pmemfun); + } + + virtual void emit(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4, + arg5_type a5, arg6_type a6, arg7_type a7) + { + (m_pobject->*m_pmemfun)(a1, a2, a3, a4, a5, a6, a7); + } + + virtual has_slots* getdest() const + { + return m_pobject; + } + + private: + dest_type* m_pobject; + void (dest_type::* m_pmemfun)(arg1_type, arg2_type, arg3_type, arg4_type, + arg5_type, arg6_type, arg7_type); + }; + + template + class _connection8 : public _connection_base8 + { + public: + _connection8() + { + this->pobject = NULL; + this->pmemfun = NULL; + } + + _connection8(dest_type* pobject, void (dest_type::*pmemfun)(arg1_type, + arg2_type, arg3_type, arg4_type, arg5_type, arg6_type, + arg7_type, arg8_type)) + { + m_pobject = pobject; + m_pmemfun = pmemfun; + } + + virtual ~_connection8() + { + ; + } + + virtual _connection_base8* clone() + { + return new _connection8(*this); + } + + virtual _connection_base8* duplicate(has_slots* pnewdest) + { + return new _connection8((dest_type *)pnewdest, m_pmemfun); + } + + virtual void emit(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4, + arg5_type a5, arg6_type a6, arg7_type a7, arg8_type a8) + { + (m_pobject->*m_pmemfun)(a1, a2, a3, a4, a5, a6, a7, a8); + } + + virtual has_slots* getdest() const + { + return m_pobject; + } + + private: + dest_type* m_pobject; + void (dest_type::* m_pmemfun)(arg1_type, arg2_type, arg3_type, arg4_type, + arg5_type, arg6_type, arg7_type, arg8_type); + }; + + template + class signal0 : public _signal_base0 + { + public: + typedef typename _signal_base0::connections_list::const_iterator const_iterator; + signal0() + { + ; + } + + signal0(const signal0& s) + : _signal_base0(s) + { + ; + } + + virtual ~signal0() + { + ; + } + + template + void connect(desttype* pclass, void (desttype::*pmemfun)()) + { + lock_block lock(this); + _connection0* conn = + new _connection0(pclass, pmemfun); + this->m_connected_slots.push_back(conn); + pclass->signal_connect(this); + } + + void emit() + { + lock_block lock(this); + const_iterator itNext, it = this->m_connected_slots.begin(); + const_iterator itEnd = this->m_connected_slots.end(); + + while(it != itEnd) + { + itNext = it; + ++itNext; + + (*it)->emit(); + + it = itNext; + } + } + + void operator()() + { + lock_block lock(this); + const_iterator itNext, it = this->m_connected_slots.begin(); + const_iterator itEnd = this->m_connected_slots.end(); + + while(it != itEnd) + { + itNext = it; + ++itNext; + + (*it)->emit(); + + it = itNext; + } + } + }; + + template + class signal1 : public _signal_base1 + { + public: + typedef typename _signal_base1::connections_list::const_iterator const_iterator; + signal1() + { + ; + } + + signal1(const signal1& s) + : _signal_base1(s) + { + ; + } + + virtual ~signal1() + { + ; + } + + template + void connect(desttype* pclass, void (desttype::*pmemfun)(arg1_type)) + { + lock_block lock(this); + _connection1* conn = + new _connection1(pclass, pmemfun); + this->m_connected_slots.push_back(conn); + pclass->signal_connect(this); + } + + void emit(arg1_type a1) + { + lock_block lock(this); + const_iterator itNext, it = this->m_connected_slots.begin(); + const_iterator itEnd = this->m_connected_slots.end(); + + while(it != itEnd) + { + itNext = it; + ++itNext; + + (*it)->emit(a1); + + it = itNext; + } + } + + void operator()(arg1_type a1) + { + lock_block lock(this); + const_iterator itNext, it = this->m_connected_slots.begin(); + const_iterator itEnd = this->m_connected_slots.end(); + + while(it != itEnd) + { + itNext = it; + ++itNext; + + (*it)->emit(a1); + + it = itNext; + } + } + }; + + template + class signal2 : public _signal_base2 + { + public: + typedef typename _signal_base2::connections_list::const_iterator const_iterator; + signal2() + { + ; + } + + signal2(const signal2& s) + : _signal_base2(s) + { + ; + } + + virtual ~signal2() + { + ; + } + + template + void connect(desttype* pclass, void (desttype::*pmemfun)(arg1_type, + arg2_type)) + { + lock_block lock(this); + _connection2* conn = new + _connection2(pclass, pmemfun); + this->m_connected_slots.push_back(conn); + pclass->signal_connect(this); + } + + void emit(arg1_type a1, arg2_type a2) + { + lock_block lock(this); + const_iterator itNext, it = this->m_connected_slots.begin(); + const_iterator itEnd = this->m_connected_slots.end(); + + while(it != itEnd) + { + itNext = it; + ++itNext; + + (*it)->emit(a1, a2); + + it = itNext; + } + } + + void operator()(arg1_type a1, arg2_type a2) + { + lock_block lock(this); + const_iterator itNext, it = this->m_connected_slots.begin(); + const_iterator itEnd = this->m_connected_slots.end(); + + while(it != itEnd) + { + itNext = it; + ++itNext; + + (*it)->emit(a1, a2); + + it = itNext; + } + } + }; + + template + class signal3 : public _signal_base3 + { + public: + typedef typename _signal_base3::connections_list::const_iterator const_iterator; + signal3() + { + ; + } + + signal3(const signal3& s) + : _signal_base3(s) + { + ; + } + + virtual ~signal3() + { + ; + } + + template + void connect(desttype* pclass, void (desttype::*pmemfun)(arg1_type, + arg2_type, arg3_type)) + { + lock_block lock(this); + _connection3* conn = + new _connection3(pclass, + pmemfun); + this->m_connected_slots.push_back(conn); + pclass->signal_connect(this); + } + + void emit(arg1_type a1, arg2_type a2, arg3_type a3) + { + lock_block lock(this); + const_iterator itNext, it = this->m_connected_slots.begin(); + const_iterator itEnd = this->m_connected_slots.end(); + + while(it != itEnd) + { + itNext = it; + ++itNext; + + (*it)->emit(a1, a2, a3); + + it = itNext; + } + } + + void operator()(arg1_type a1, arg2_type a2, arg3_type a3) + { + lock_block lock(this); + const_iterator itNext, it = this->m_connected_slots.begin(); + const_iterator itEnd = this->m_connected_slots.end(); + + while(it != itEnd) + { + itNext = it; + ++itNext; + + (*it)->emit(a1, a2, a3); + + it = itNext; + } + } + }; + + template + class signal4 : public _signal_base4 + { + public: + typedef typename _signal_base4::connections_list::const_iterator const_iterator; + signal4() + { + ; + } + + signal4(const signal4& s) + : _signal_base4(s) + { + ; + } + + virtual ~signal4() + { + ; + } + + template + void connect(desttype* pclass, void (desttype::*pmemfun)(arg1_type, + arg2_type, arg3_type, arg4_type)) + { + lock_block lock(this); + _connection4* + conn = new _connection4(pclass, pmemfun); + this->m_connected_slots.push_back(conn); + pclass->signal_connect(this); + } + + void emit(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4) + { + lock_block lock(this); + const_iterator itNext, it = this->m_connected_slots.begin(); + const_iterator itEnd = this->m_connected_slots.end(); + + while(it != itEnd) + { + itNext = it; + ++itNext; + + (*it)->emit(a1, a2, a3, a4); + + it = itNext; + } + } + + void operator()(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4) + { + lock_block lock(this); + const_iterator itNext, it = this->m_connected_slots.begin(); + const_iterator itEnd = this->m_connected_slots.end(); + + while(it != itEnd) + { + itNext = it; + ++itNext; + + (*it)->emit(a1, a2, a3, a4); + + it = itNext; + } + } + }; + + template + class signal5 : public _signal_base5 + { + public: + typedef typename _signal_base5::connections_list::const_iterator const_iterator; + signal5() + { + ; + } + + signal5(const signal5& s) + : _signal_base5(s) + { + ; + } + + virtual ~signal5() + { + ; + } + + template + void connect(desttype* pclass, void (desttype::*pmemfun)(arg1_type, + arg2_type, arg3_type, arg4_type, arg5_type)) + { + lock_block lock(this); + _connection5* conn = new _connection5(pclass, pmemfun); + this->m_connected_slots.push_back(conn); + pclass->signal_connect(this); + } + + void emit(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4, + arg5_type a5) + { + lock_block lock(this); + const_iterator itNext, it = this->m_connected_slots.begin(); + const_iterator itEnd = this->m_connected_slots.end(); + + while(it != itEnd) + { + itNext = it; + ++itNext; + + (*it)->emit(a1, a2, a3, a4, a5); + + it = itNext; + } + } + + void operator()(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4, + arg5_type a5) + { + lock_block lock(this); + const_iterator itNext, it = this->m_connected_slots.begin(); + const_iterator itEnd = this->m_connected_slots.end(); + + while(it != itEnd) + { + itNext = it; + ++itNext; + + (*it)->emit(a1, a2, a3, a4, a5); + + it = itNext; + } + } + }; + + + template + class signal6 : public _signal_base6 + { + public: + typedef typename _signal_base6::connections_list::const_iterator const_iterator; + signal6() + { + ; + } + + signal6(const signal6& s) + : _signal_base6(s) + { + ; + } + + virtual ~signal6() + { + ; + } + + template + void connect(desttype* pclass, void (desttype::*pmemfun)(arg1_type, + arg2_type, arg3_type, arg4_type, arg5_type, arg6_type)) + { + lock_block lock(this); + _connection6* conn = + new _connection6(pclass, pmemfun); + this->m_connected_slots.push_back(conn); + pclass->signal_connect(this); + } + + void emit(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4, + arg5_type a5, arg6_type a6) + { + lock_block lock(this); + const_iterator itNext, it = this->m_connected_slots.begin(); + const_iterator itEnd = this->m_connected_slots.end(); + + while(it != itEnd) + { + itNext = it; + ++itNext; + + (*it)->emit(a1, a2, a3, a4, a5, a6); + + it = itNext; + } + } + + void operator()(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4, + arg5_type a5, arg6_type a6) + { + lock_block lock(this); + const_iterator itNext, it = this->m_connected_slots.begin(); + const_iterator itEnd = this->m_connected_slots.end(); + + while(it != itEnd) + { + itNext = it; + ++itNext; + + (*it)->emit(a1, a2, a3, a4, a5, a6); + + it = itNext; + } + } + }; + + template + class signal7 : public _signal_base7 + { + public: + typedef typename _signal_base7::connections_list::const_iterator const_iterator; + signal7() + { + ; + } + + signal7(const signal7& s) + : _signal_base7(s) + { + ; + } + + virtual ~signal7() + { + ; + } + + template + void connect(desttype* pclass, void (desttype::*pmemfun)(arg1_type, + arg2_type, arg3_type, arg4_type, arg5_type, arg6_type, + arg7_type)) + { + lock_block lock(this); + _connection7* conn = + new _connection7(pclass, pmemfun); + this->m_connected_slots.push_back(conn); + pclass->signal_connect(this); + } + + void emit(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4, + arg5_type a5, arg6_type a6, arg7_type a7) + { + lock_block lock(this); + const_iterator itNext, it = this->m_connected_slots.begin(); + const_iterator itEnd = this->m_connected_slots.end(); + + while(it != itEnd) + { + itNext = it; + ++itNext; + + (*it)->emit(a1, a2, a3, a4, a5, a6, a7); + + it = itNext; + } + } + + void operator()(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4, + arg5_type a5, arg6_type a6, arg7_type a7) + { + lock_block lock(this); + const_iterator itNext, it = this->m_connected_slots.begin(); + const_iterator itEnd = this->m_connected_slots.end(); + + while(it != itEnd) + { + itNext = it; + ++itNext; + + (*it)->emit(a1, a2, a3, a4, a5, a6, a7); + + it = itNext; + } + } + }; + + template + class signal8 : public _signal_base8 + { + public: + typedef typename _signal_base8::connections_list::const_iterator const_iterator; + signal8() + { + ; + } + + signal8(const signal8& s) + : _signal_base8(s) + { + ; + } + + virtual ~signal8() + { + ; + } + + template + void connect(desttype* pclass, void (desttype::*pmemfun)(arg1_type, + arg2_type, arg3_type, arg4_type, arg5_type, arg6_type, + arg7_type, arg8_type)) + { + lock_block lock(this); + _connection8* conn = + new _connection8(pclass, pmemfun); + this->m_connected_slots.push_back(conn); + pclass->signal_connect(this); + } + + void emit(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4, + arg5_type a5, arg6_type a6, arg7_type a7, arg8_type a8) + { + lock_block lock(this); + const_iterator itNext, it = this->m_connected_slots.begin(); + const_iterator itEnd = this->m_connected_slots.end(); + + while(it != itEnd) + { + itNext = it; + ++itNext; + + (*it)->emit(a1, a2, a3, a4, a5, a6, a7, a8); + + it = itNext; + } + } + + void operator()(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4, + arg5_type a5, arg6_type a6, arg7_type a7, arg8_type a8) + { + lock_block lock(this); + const_iterator itNext, it = this->m_connected_slots.begin(); + const_iterator itEnd = this->m_connected_slots.end(); + + while(it != itEnd) + { + itNext = it; + ++itNext; + + (*it)->emit(a1, a2, a3, a4, a5, a6, a7, a8); + + it = itNext; + } + } + }; + +} // namespace sigslot + +#endif // SIGSLOT_H__ + diff --git a/plugins/Dbx_tree/src/stdint.h b/plugins/Dbx_tree/src/stdint.h new file mode 100644 index 0000000000..59d067302f --- /dev/null +++ b/plugins/Dbx_tree/src/stdint.h @@ -0,0 +1,247 @@ +// ISO C9x compliant stdint.h for Microsoft Visual Studio +// Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124 +// +// Copyright (c) 2006-2008 Alexander Chemeris +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// 3. The name of the author may be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED +// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO +// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef _MSC_VER // [ +#error "Use this header only with Microsoft Visual C++ compilers!" +#endif // _MSC_VER ] + +#ifndef _MSC_STDINT_H_ // [ +#define _MSC_STDINT_H_ + +#if _MSC_VER > 1000 +#pragma once +#endif + +#include + +// For Visual Studio 6 in C++ mode and for many Visual Studio versions when +// compiling for ARM we should wrap include with 'extern "C++" {}' +// or compiler give many errors like this: +// error C2733: second C linkage of overloaded function 'wmemchr' not allowed +#ifdef __cplusplus +extern "C" { +#endif +# include +#ifdef __cplusplus +} +#endif + +// Define _W64 macros to mark types changing their size, like intptr_t. +#ifndef _W64 +# if !defined(__midl) && (defined(_X86_) || defined(_M_IX86)) && _MSC_VER >= 1300 +# define _W64 __w64 +# else +# define _W64 +# endif +#endif + + +// 7.18.1 Integer types + +// 7.18.1.1 Exact-width integer types + +// Visual Studio 6 and Embedded Visual C++ 4 doesn't +// realize that, e.g. char has the same size as __int8 +// so we give up on __intX for them. +#if (_MSC_VER < 1300) + typedef signed char int8_t; + typedef signed short int16_t; + typedef signed int int32_t; + typedef unsigned char uint8_t; + typedef unsigned short uint16_t; + typedef unsigned int uint32_t; +#else + typedef signed __int8 int8_t; + typedef signed __int16 int16_t; + typedef signed __int32 int32_t; + typedef unsigned __int8 uint8_t; + typedef unsigned __int16 uint16_t; + typedef unsigned __int32 uint32_t; +#endif +typedef signed __int64 int64_t; +typedef unsigned __int64 uint64_t; + + +// 7.18.1.2 Minimum-width integer types +typedef int8_t int_least8_t; +typedef int16_t int_least16_t; +typedef int32_t int_least32_t; +typedef int64_t int_least64_t; +typedef uint8_t uint_least8_t; +typedef uint16_t uint_least16_t; +typedef uint32_t uint_least32_t; +typedef uint64_t uint_least64_t; + +// 7.18.1.3 Fastest minimum-width integer types +typedef int8_t int_fast8_t; +typedef int16_t int_fast16_t; +typedef int32_t int_fast32_t; +typedef int64_t int_fast64_t; +typedef uint8_t uint_fast8_t; +typedef uint16_t uint_fast16_t; +typedef uint32_t uint_fast32_t; +typedef uint64_t uint_fast64_t; + +// 7.18.1.4 Integer types capable of holding object pointers +#ifdef _WIN64 // [ + typedef signed __int64 intptr_t; + typedef unsigned __int64 uintptr_t; +#else // _WIN64 ][ + typedef _W64 signed int intptr_t; + typedef _W64 unsigned int uintptr_t; +#endif // _WIN64 ] + +// 7.18.1.5 Greatest-width integer types +typedef int64_t intmax_t; +typedef uint64_t uintmax_t; + + +// 7.18.2 Limits of specified-width integer types + +#if !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS) // [ See footnote 220 at page 257 and footnote 221 at page 259 + +// 7.18.2.1 Limits of exact-width integer types +#define INT8_MIN ((int8_t)_I8_MIN) +#define INT8_MAX _I8_MAX +#define INT16_MIN ((int16_t)_I16_MIN) +#define INT16_MAX _I16_MAX +#define INT32_MIN ((int32_t)_I32_MIN) +#define INT32_MAX _I32_MAX +#define INT64_MIN ((int64_t)_I64_MIN) +#define INT64_MAX _I64_MAX +#define UINT8_MAX _UI8_MAX +#define UINT16_MAX _UI16_MAX +#define UINT32_MAX _UI32_MAX +#define UINT64_MAX _UI64_MAX + +// 7.18.2.2 Limits of minimum-width integer types +#define INT_LEAST8_MIN INT8_MIN +#define INT_LEAST8_MAX INT8_MAX +#define INT_LEAST16_MIN INT16_MIN +#define INT_LEAST16_MAX INT16_MAX +#define INT_LEAST32_MIN INT32_MIN +#define INT_LEAST32_MAX INT32_MAX +#define INT_LEAST64_MIN INT64_MIN +#define INT_LEAST64_MAX INT64_MAX +#define UINT_LEAST8_MAX UINT8_MAX +#define UINT_LEAST16_MAX UINT16_MAX +#define UINT_LEAST32_MAX UINT32_MAX +#define UINT_LEAST64_MAX UINT64_MAX + +// 7.18.2.3 Limits of fastest minimum-width integer types +#define INT_FAST8_MIN INT8_MIN +#define INT_FAST8_MAX INT8_MAX +#define INT_FAST16_MIN INT16_MIN +#define INT_FAST16_MAX INT16_MAX +#define INT_FAST32_MIN INT32_MIN +#define INT_FAST32_MAX INT32_MAX +#define INT_FAST64_MIN INT64_MIN +#define INT_FAST64_MAX INT64_MAX +#define UINT_FAST8_MAX UINT8_MAX +#define UINT_FAST16_MAX UINT16_MAX +#define UINT_FAST32_MAX UINT32_MAX +#define UINT_FAST64_MAX UINT64_MAX + +// 7.18.2.4 Limits of integer types capable of holding object pointers +#ifdef _WIN64 // [ +# define INTPTR_MIN INT64_MIN +# define INTPTR_MAX INT64_MAX +# define UINTPTR_MAX UINT64_MAX +#else // _WIN64 ][ +# define INTPTR_MIN INT32_MIN +# define INTPTR_MAX INT32_MAX +# define UINTPTR_MAX UINT32_MAX +#endif // _WIN64 ] + +// 7.18.2.5 Limits of greatest-width integer types +#define INTMAX_MIN INT64_MIN +#define INTMAX_MAX INT64_MAX +#define UINTMAX_MAX UINT64_MAX + +// 7.18.3 Limits of other integer types + +#ifdef _WIN64 // [ +# define PTRDIFF_MIN _I64_MIN +# define PTRDIFF_MAX _I64_MAX +#else // _WIN64 ][ +# define PTRDIFF_MIN _I32_MIN +# define PTRDIFF_MAX _I32_MAX +#endif // _WIN64 ] + +#define SIG_ATOMIC_MIN INT_MIN +#define SIG_ATOMIC_MAX INT_MAX + +#ifndef SIZE_MAX // [ +# ifdef _WIN64 // [ +# define SIZE_MAX _UI64_MAX +# else // _WIN64 ][ +# define SIZE_MAX _UI32_MAX +# endif // _WIN64 ] +#endif // SIZE_MAX ] + +// WCHAR_MIN and WCHAR_MAX are also defined in +#ifndef WCHAR_MIN // [ +# define WCHAR_MIN 0 +#endif // WCHAR_MIN ] +#ifndef WCHAR_MAX // [ +# define WCHAR_MAX _UI16_MAX +#endif // WCHAR_MAX ] + +#define WINT_MIN 0 +#define WINT_MAX _UI16_MAX + +#endif // __STDC_LIMIT_MACROS ] + + +// 7.18.4 Limits of other integer types + +#if !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) // [ See footnote 224 at page 260 + +// 7.18.4.1 Macros for minimum-width integer constants + +#define INT8_C(val) val##i8 +#define INT16_C(val) val##i16 +#define INT32_C(val) val##i32 +#define INT64_C(val) val##i64 + +#define UINT8_C(val) val##ui8 +#define UINT16_C(val) val##ui16 +#define UINT32_C(val) val##ui32 +#define UINT64_C(val) val##ui64 + +// 7.18.4.2 Macros for greatest-width integer constants +#define INTMAX_C INT64_C +#define UINTMAX_C UINT64_C + +#endif // __STDC_CONSTANT_MACROS ] + + +#endif // _MSC_STDINT_H_ ] diff --git a/plugins/Dbx_tree/stdint.h b/plugins/Dbx_tree/stdint.h deleted file mode 100644 index 59d067302f..0000000000 --- a/plugins/Dbx_tree/stdint.h +++ /dev/null @@ -1,247 +0,0 @@ -// ISO C9x compliant stdint.h for Microsoft Visual Studio -// Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124 -// -// Copyright (c) 2006-2008 Alexander Chemeris -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, -// this list of conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// -// 3. The name of the author may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED -// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO -// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; -// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR -// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF -// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -/////////////////////////////////////////////////////////////////////////////// - -#ifndef _MSC_VER // [ -#error "Use this header only with Microsoft Visual C++ compilers!" -#endif // _MSC_VER ] - -#ifndef _MSC_STDINT_H_ // [ -#define _MSC_STDINT_H_ - -#if _MSC_VER > 1000 -#pragma once -#endif - -#include - -// For Visual Studio 6 in C++ mode and for many Visual Studio versions when -// compiling for ARM we should wrap include with 'extern "C++" {}' -// or compiler give many errors like this: -// error C2733: second C linkage of overloaded function 'wmemchr' not allowed -#ifdef __cplusplus -extern "C" { -#endif -# include -#ifdef __cplusplus -} -#endif - -// Define _W64 macros to mark types changing their size, like intptr_t. -#ifndef _W64 -# if !defined(__midl) && (defined(_X86_) || defined(_M_IX86)) && _MSC_VER >= 1300 -# define _W64 __w64 -# else -# define _W64 -# endif -#endif - - -// 7.18.1 Integer types - -// 7.18.1.1 Exact-width integer types - -// Visual Studio 6 and Embedded Visual C++ 4 doesn't -// realize that, e.g. char has the same size as __int8 -// so we give up on __intX for them. -#if (_MSC_VER < 1300) - typedef signed char int8_t; - typedef signed short int16_t; - typedef signed int int32_t; - typedef unsigned char uint8_t; - typedef unsigned short uint16_t; - typedef unsigned int uint32_t; -#else - typedef signed __int8 int8_t; - typedef signed __int16 int16_t; - typedef signed __int32 int32_t; - typedef unsigned __int8 uint8_t; - typedef unsigned __int16 uint16_t; - typedef unsigned __int32 uint32_t; -#endif -typedef signed __int64 int64_t; -typedef unsigned __int64 uint64_t; - - -// 7.18.1.2 Minimum-width integer types -typedef int8_t int_least8_t; -typedef int16_t int_least16_t; -typedef int32_t int_least32_t; -typedef int64_t int_least64_t; -typedef uint8_t uint_least8_t; -typedef uint16_t uint_least16_t; -typedef uint32_t uint_least32_t; -typedef uint64_t uint_least64_t; - -// 7.18.1.3 Fastest minimum-width integer types -typedef int8_t int_fast8_t; -typedef int16_t int_fast16_t; -typedef int32_t int_fast32_t; -typedef int64_t int_fast64_t; -typedef uint8_t uint_fast8_t; -typedef uint16_t uint_fast16_t; -typedef uint32_t uint_fast32_t; -typedef uint64_t uint_fast64_t; - -// 7.18.1.4 Integer types capable of holding object pointers -#ifdef _WIN64 // [ - typedef signed __int64 intptr_t; - typedef unsigned __int64 uintptr_t; -#else // _WIN64 ][ - typedef _W64 signed int intptr_t; - typedef _W64 unsigned int uintptr_t; -#endif // _WIN64 ] - -// 7.18.1.5 Greatest-width integer types -typedef int64_t intmax_t; -typedef uint64_t uintmax_t; - - -// 7.18.2 Limits of specified-width integer types - -#if !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS) // [ See footnote 220 at page 257 and footnote 221 at page 259 - -// 7.18.2.1 Limits of exact-width integer types -#define INT8_MIN ((int8_t)_I8_MIN) -#define INT8_MAX _I8_MAX -#define INT16_MIN ((int16_t)_I16_MIN) -#define INT16_MAX _I16_MAX -#define INT32_MIN ((int32_t)_I32_MIN) -#define INT32_MAX _I32_MAX -#define INT64_MIN ((int64_t)_I64_MIN) -#define INT64_MAX _I64_MAX -#define UINT8_MAX _UI8_MAX -#define UINT16_MAX _UI16_MAX -#define UINT32_MAX _UI32_MAX -#define UINT64_MAX _UI64_MAX - -// 7.18.2.2 Limits of minimum-width integer types -#define INT_LEAST8_MIN INT8_MIN -#define INT_LEAST8_MAX INT8_MAX -#define INT_LEAST16_MIN INT16_MIN -#define INT_LEAST16_MAX INT16_MAX -#define INT_LEAST32_MIN INT32_MIN -#define INT_LEAST32_MAX INT32_MAX -#define INT_LEAST64_MIN INT64_MIN -#define INT_LEAST64_MAX INT64_MAX -#define UINT_LEAST8_MAX UINT8_MAX -#define UINT_LEAST16_MAX UINT16_MAX -#define UINT_LEAST32_MAX UINT32_MAX -#define UINT_LEAST64_MAX UINT64_MAX - -// 7.18.2.3 Limits of fastest minimum-width integer types -#define INT_FAST8_MIN INT8_MIN -#define INT_FAST8_MAX INT8_MAX -#define INT_FAST16_MIN INT16_MIN -#define INT_FAST16_MAX INT16_MAX -#define INT_FAST32_MIN INT32_MIN -#define INT_FAST32_MAX INT32_MAX -#define INT_FAST64_MIN INT64_MIN -#define INT_FAST64_MAX INT64_MAX -#define UINT_FAST8_MAX UINT8_MAX -#define UINT_FAST16_MAX UINT16_MAX -#define UINT_FAST32_MAX UINT32_MAX -#define UINT_FAST64_MAX UINT64_MAX - -// 7.18.2.4 Limits of integer types capable of holding object pointers -#ifdef _WIN64 // [ -# define INTPTR_MIN INT64_MIN -# define INTPTR_MAX INT64_MAX -# define UINTPTR_MAX UINT64_MAX -#else // _WIN64 ][ -# define INTPTR_MIN INT32_MIN -# define INTPTR_MAX INT32_MAX -# define UINTPTR_MAX UINT32_MAX -#endif // _WIN64 ] - -// 7.18.2.5 Limits of greatest-width integer types -#define INTMAX_MIN INT64_MIN -#define INTMAX_MAX INT64_MAX -#define UINTMAX_MAX UINT64_MAX - -// 7.18.3 Limits of other integer types - -#ifdef _WIN64 // [ -# define PTRDIFF_MIN _I64_MIN -# define PTRDIFF_MAX _I64_MAX -#else // _WIN64 ][ -# define PTRDIFF_MIN _I32_MIN -# define PTRDIFF_MAX _I32_MAX -#endif // _WIN64 ] - -#define SIG_ATOMIC_MIN INT_MIN -#define SIG_ATOMIC_MAX INT_MAX - -#ifndef SIZE_MAX // [ -# ifdef _WIN64 // [ -# define SIZE_MAX _UI64_MAX -# else // _WIN64 ][ -# define SIZE_MAX _UI32_MAX -# endif // _WIN64 ] -#endif // SIZE_MAX ] - -// WCHAR_MIN and WCHAR_MAX are also defined in -#ifndef WCHAR_MIN // [ -# define WCHAR_MIN 0 -#endif // WCHAR_MIN ] -#ifndef WCHAR_MAX // [ -# define WCHAR_MAX _UI16_MAX -#endif // WCHAR_MAX ] - -#define WINT_MIN 0 -#define WINT_MAX _UI16_MAX - -#endif // __STDC_LIMIT_MACROS ] - - -// 7.18.4 Limits of other integer types - -#if !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) // [ See footnote 224 at page 260 - -// 7.18.4.1 Macros for minimum-width integer constants - -#define INT8_C(val) val##i8 -#define INT16_C(val) val##i16 -#define INT32_C(val) val##i32 -#define INT64_C(val) val##i64 - -#define UINT8_C(val) val##ui8 -#define UINT16_C(val) val##ui16 -#define UINT32_C(val) val##ui32 -#define UINT64_C(val) val##ui64 - -// 7.18.4.2 Macros for greatest-width integer constants -#define INTMAX_C INT64_C -#define UINTMAX_C UINT64_C - -#endif // __STDC_CONSTANT_MACROS ] - - -#endif // _MSC_STDINT_H_ ] -- cgit v1.2.3