伝説のツール「NotesPeek」をQtでリメイクする(その4・IDテーブル)
IDテーブル
IDテーブルは、Notesにおける文書のためのコンテナの役割を持っています。Notes/Domino APIプログラミング―C++とSTLによる実践的プログラミングでも書かれていますが、
文書IDテーブルとは、文書ID(NOTEID)を昇順で保持するコンテナで、std::set
とほぼ同じ機能を提供します。
と、あります。もともとAPIはC用に作られているので、C++のコンテナをそのまま使うわけにはいきません。CのみであればこのIDテーブルを使えばいいわけです。またC++であればstd::set
まず、IDテーブルクラスの実装を紹介する前に、ここで扱うIDテーブル関連のAPIを紹介します。
IDテーブルは、IDCreateTable関数によって生成し、IDDestroyTable関数によって破棄します(例外もあります)。生成されたIDテーブルはDHANDLEにて管理します。
#include <idtable.h> STATUS LNPUBLIC IDCreateTable (DWORD Alignment, DHANDLE far *rethTable); STATUS LNPUBLIC IDDestroyTable(DHANDLE hTable);
ここで、Alignmentはsizeof(NOTEID)を渡すことになります。
IDテーブルにIDを追加するには、IDInsert関数を使います。
#include <idtable.h> STATUS LNPUBLIC IDInsert (DHANDLE hTable, DWORD id, BOOL far *retfInserted);
戻り値はいつものステータス値ですが、IDが挿入できたかどうかは3番目の引数、retfInsertedを見ます。これは、IDがすでにIDテーブル内に存在していればfalseを返します。必要なければnullptrを与えておきます。
テーブル内のIDは通常IDDeleteかIDDeleteAllを使って削除しますが、その実装は後日とします。また、Noteクラスとの連携に唯一getNoteメソッドを実装していますが、これも後日説明します。
それでは、僕流のIDTableクラスと、IDTable::iteratorクラスです。
// ntlx/idtable.h #ifndef NTLX_IDTABLE_H #define NTLX_IDTABLE_H #include "ntlx_global.h" #include "ntlx/status.h" #if defined(NT) #pragma pack(push, 1) #endif #include <nsfdata.h> #if defined(NT) #pragma pack(pop) #endif namespace ntlx { class Database; class Note; /** * @brief IDテーブルクラス */ class NTLXSHARED_EXPORT IDTable : public IStatus { public: /** * @brief イテレータインナークラス */ class NTLXSHARED_EXPORT iterator { public: /** * @brief デフォルトコンストラクタ */ iterator(); /** * @brief NOTEIDを返す演算子 * @return NOTEID */ NOTEID operator*(); /** * @brief 前置きインクリメント演算子 * @return 自身への参照 */ iterator& operator++(); /** * @brief 後置きインクリメント演算子 * @return インクリメントする前のイテレータ */ iterator operator++(int); /** * @brief NOTEIDに対応したNoteオブジェクトを取得する * @param db 取得元になるデータベースオブジェクト * @return Noteオブジェクト */ Note getNote(Database& db) const; protected: /** * @brief コンストラクタ * @param pIdTable IDTableオブジェクトへのポインタ * @param noteId NOTEID * @param isLast 最後を示しているか */ iterator(IDTable* pIdTable, NOTEID noteId, bool isLast = false); IDTable* idTable_; NOTEID id_; bool isLast_; /** * @brief 等値演算子 * @param lhs 左辺値 * @param rhs 右辺値 * @return ブール値 */ friend NTLXSHARED_EXPORT bool operator==( const iterator& lhs , const iterator& rhs ); /** * @brief 不等値演算子 * @param lhs 左辺値 * @param rhs 右辺値 * @return ブール値 */ friend NTLXSHARED_EXPORT bool operator!=( const iterator& lhs , const iterator& rhs ); friend class IDTable; }; /** * @brief コンストラクタ */ IDTable(); /** * @brief デストラクタ */ virtual ~IDTable(); /** * @brief 最初のイテレータを返す * @return 最初のイテレータ */ iterator begin(); /** * @brief 最後のイテレータを返す * @return 最後のイテレータ */ iterator end(); /** * @brief NOTEIDを挿入する * @param id NOTEID * @return 重複していなければ真 */ bool insert(NOTEID id); private: DHANDLE handle_; friend class iterator; }; } // namespace ntlx #endif // IDTABLE_H
// idtable.cpp #include "ntlx/idtable.h" #include "ntlx/note.h" #if defined(NT) #pragma pack(push, 1) #endif #include <idtable.h> #if defined(NT) #pragma pack(pop) #endif namespace ntlx { IDTable::iterator::iterator() : idTable_(nullptr) , id_(0) , isLast_(false) { } NOTEID IDTable::iterator::operator *() { return id_; } IDTable::iterator& IDTable::iterator::operator++() { isLast_ = !IDScan(idTable_->handle_, id_ == 0, &id_); return *this; } IDTable::iterator IDTable::iterator::operator++(int) { iterator it = *this; operator++(); return it; } Note IDTable::iterator::getNote(Database &db) const { return Note(db, id_); } IDTable::iterator::iterator(IDTable *pIdTable, NOTEID noteId, bool isLast) : idTable_(pIdTable) , id_(noteId) , isLast_(isLast) { } bool operator==(const IDTable::iterator& lhs, const IDTable::iterator& rhs) { if (lhs.isLast_ && rhs.isLast_) return true; else return lhs.id_ == rhs.id_; } bool operator!=(const IDTable::iterator& lhs, const IDTable::iterator& rhs) { return !operator==(lhs, rhs); } IDTable::IDTable() : IStatus() , handle_(NULLHANDLE) { lastStatus_ = IDCreateTable(sizeof(NOTEID), &handle_); } IDTable::~IDTable() { if (handle_) IDDestroyTable(handle_); } IDTable::iterator IDTable::begin() { if (handle_ == NULLHANDLE) return end(); return ++iterator(this, 0); } IDTable::iterator IDTable::end() { return iterator(this, 0, true); } bool IDTable::insert(NOTEID id) { Q_ASSERT(handle_); BOOL b = false; lastStatus_ = IDInsert(handle_, id, &b); return b; } } // namespace ntlx