📄 bdb_map.hpp
字号:
/* * =========================================================================== * PRODUCTION $Log: bdb_map.hpp,v $ * PRODUCTION Revision 1000.2 2004/04/29 15:32:57 gouriano * PRODUCTION PRODUCTION: UPGRADED [CATCHUP_003] Dev-tree R1.11 * PRODUCTION * =========================================================================== */#ifndef BDB_MAP__HPP#define BDB_MAP__HPP/* $Id: bdb_map.hpp,v 1000.2 2004/04/29 15:32:57 gouriano Exp $ * =========================================================================== * * PUBLIC DOMAIN NOTICE * National Center for Biotechnology Information * * This software/database is a "United States Government Work" under the * terms of the United States Copyright Act. It was written as part of * the author's official duties as a United States Government employee and * thus cannot be copyrighted. This software/database is freely available * to the public for use. The National Library of Medicine and the U.S. * Government have not placed any restriction on its use or reproduction. * * Although all reasonable efforts have been taken to ensure the accuracy * and reliability of the software and data, the NLM and the U.S. * Government do not and cannot warrant the performance or results that * may be obtained by using this software or data. The NLM and the U.S. * Government disclaim all warranties, express or implied, including * warranties of performance, merchantability or fitness for any particular * purpose. * * Please cite the author in any work or product based on this material. * * =========================================================================== * * Author: Anatoliy Kuznetsov * * File Description: Templates implementing Berkeley DB based maps with syntax * close to standard associative containers */#include <bdb/bdb_cursor.hpp>BEGIN_NCBI_SCOPE/** @addtogroup BDB_Map * * @{ *//// Internal template used for compiler based type mapping /// (C++ templates specialization emplyed here)///template<class T> struct CBDB_TypeMapper{ typedef T TFieldType;};template<> struct CBDB_TypeMapper<int>{ typedef CBDB_FieldInt4 TFieldType;};template<> struct CBDB_TypeMapper<string>{ typedef CBDB_FieldLString TFieldType;};/// db_map_base /// template<class K, class T> class db_map_base{public: typedef typename CBDB_TypeMapper<K>::TFieldType db_first_type; typedef typename CBDB_TypeMapper<T>::TFieldType db_second_type; typedef std::pair<K, T> value_type; struct File : public CBDB_File { db_first_type key; db_second_type value; File(CBDB_File::EDuplicateKeys dup_keys) : CBDB_File(dup_keys) { BindKey("Key", &key); BindData("Value", &value, 1024); } }; typedef typename db_map_base<K, T>::File map_file_type;protected: // Base class for all db_map iterators // Class opens its own copy of BerkeleyDB file and cursor on it. class iterator_base { protected: enum EIteratorStatus { eUnknown, eEnd, eBeforeBegin, eInFile }; iterator_base(map_file_type* db_file) : m_ParentFile(db_file), m_CursorFile(0), m_Cur(0), m_OpenMode(CBDB_RawFile::eReadOnly), m_IStatus(eUnknown) { } ~iterator_base() { delete m_Cur; delete m_CursorFile; } iterator_base(const iterator_base& it) { init_from(it); } iterator_base& operator=(const iterator_base& it) { return init_from(it); } iterator_base& init_from(const iterator_base& it) { m_ParentFile = it.m_ParentFile; m_CursorFile = 0; m_Cur = 0; m_OpenMode = it.m_OpenMode; m_SearchFlag = it.m_SearchFlag; m_pair.first = it.m_pair.first; m_pair.second = it.m_pair.second; m_IStatus = it.m_IStatus; return *this; } void open_cursor(CBDB_RawFile::EOpenMode open_mode, CBDB_FileCursor::ECondition cursor_condition) const { delete m_Cur; m_Cur = 0; bool attached = m_CursorFile->IsAttached(); if (!attached) { m_CursorFile->Attach(*m_ParentFile); } m_Cur = new CBDB_FileCursor(*m_CursorFile); m_Cur->SetCondition(cursor_condition); } void open_cursor(CBDB_RawFile::EOpenMode open_mode, CBDB_FileCursor::ECondition cursor_condition, const K& key) const { open_cursor(open_mode, cursor_condition); m_Cur->From << key; } // db_map iterators are quite heavy (opens BDB cursors and stuff) and // to simplify the iteratros coping and assignments we use lazy initilization // It means actual db operation is postponed until the first iterator access. void check_open_cursor() const { if (m_CursorFile == 0) { _ASSERT(m_ParentFile); m_CursorFile = new map_file_type(m_ParentFile->GetDupKeysMode()); _ASSERT(m_Cur == 0); if (m_SearchFlag) { open_cursor(m_OpenMode, CBDB_FileCursor::eGE, m_pair.first); } else { if (m_IStatus == eEnd) { open_cursor(m_OpenMode, CBDB_FileCursor::eLast); m_Cur->ReverseFetchDirection(); } else { open_cursor(m_OpenMode, CBDB_FileCursor::eFirst); } } if (m_Cur->Fetch() == eBDB_Ok) { m_SearchFlag = true; m_pair.first = m_CursorFile->key; m_pair.second= m_CursorFile->value; if (m_IStatus == eEnd) { } else { m_IStatus = eInFile; } } else { // No data... // go to the end open_cursor(m_OpenMode, CBDB_FileCursor::eLast); m_IStatus = eEnd; } } } void go_end() { if (m_IStatus == eEnd) return; // if it's "end()" iterartor, no need to open any files here if (m_CursorFile == 0) { m_IStatus = eEnd; return; } open_cursor(m_OpenMode, CBDB_FileCursor::eLast); m_Cur->ReverseFetchDirection(); if (m_Cur->Fetch() == eBDB_Ok) { m_pair.first = (K)m_CursorFile->key; m_pair.second= (T)m_CursorFile->value; } m_IStatus = eEnd; } void fetch_next() { _ASSERT(m_IStatus != eEnd); check_open_cursor(); if (m_Cur->Fetch() == eBDB_Ok) { m_pair.first = m_CursorFile->key; m_pair.second= m_CursorFile->value; m_IStatus = eInFile; } else { m_IStatus = eEnd; } } void fetch_prev() { _ASSERT(m_IStatus != eBeforeBegin); check_open_cursor(); if (m_Cur->Fetch(CBDB_FileCursor::eBackward) == eBDB_Ok) { m_pair.first = m_CursorFile->key; m_pair.second= m_CursorFile->value; m_IStatus = eInFile; } else { m_IStatus = eBeforeBegin; } } bool is_equal(const iterator_base& it) const { if (m_ParentFile != it.m_ParentFile) return false; if (m_IStatus == eUnknown) { check_open_cursor(); } if (m_IStatus == it.m_IStatus) { if (m_IStatus == eEnd && it.m_IStatus == eEnd) return true; if (m_IStatus == eBeforeBegin && it.m_IStatus == eBeforeBegin) return true; return (m_pair.first == it.m_pair.first); } return false; } public: // Return TRUE while iterator is in the correct range bool valid() const { check_open_cursor(); if (m_IStatus == eEnd) return false; if (m_IStatus == eBeforeBegin) return false; return true; } protected: mutable map_file_type* m_ParentFile; mutable map_file_type* m_CursorFile; mutable CBDB_FileCursor* m_Cur; // Cursor open mode CBDB_RawFile::EOpenMode m_OpenMode; // TRUE if iterator searches for the specific key mutable bool m_SearchFlag; // Current key-value pair mutable value_type m_pair; // Iterator "navigation" status mutable EIteratorStatus m_IStatus; };public: class const_iterator : public iterator_base { public: const_iterator(map_file_type* db_file) : iterator_base(db_file) { this->m_SearchFlag = false; } const_iterator(map_file_type* db_file, const K& key) : iterator_base(db_file) { this->m_SearchFlag = true; this->m_pair.first = key; } const_iterator& go_end() { iterator_base::go_end(); return *this; } const_iterator() : iterator_base(0) {} const_iterator(const const_iterator& it) : iterator_base(it) {} const_iterator& operator=(const const_iterator& it) { init_from(it);return *this; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -