見出し画像

Notes C API探訪: テキスト用LIST型のラップクラス(その3)

まずは、前回記事でご紹介したコードの改善から。
nxpp::TextListクラス内に定義したLockerクラスは、OSLockObject、OSUnlockObject関数を使った他のDominoオブジェクト(DHANDLEハンドルで管理されるデータという意味)でも使用できるので、ロックした後のポインタの型をテンプレート化すれば、共通して利用できるようにしました。

// nxpp/include/nxpp_utils.hpp内に定義

namespace nxpp {

/**
* @brief ハンドルをロックしてポインタを取得するクラス
* スコープをはずれると自動的にハンドルをアンロックする
*/
template <class T>
class ObjectLocker {
 DHANDLE handle_;
 T *ptr_;

public:
 /**
  * @brief コンストラクタ
  * @param parent テキストリストへのポインタ
  */
 ObjectLocker(DHANDLE handle) : handle_(handle), ptr_(nullptr) {
   ptr_ = handle != NULLHANDLE
       ? reinterpret_cast<T*>(OSLockObject(handle))
       : nullptr;
 }

 /**
  * @brief デストラクタ
  */
 virtual ~ObjectLocker() {
   if (ptr_ != nullptr) {
     OSUnlockObject(handle_);
   }
 }

 /**
  * @brief 正常にロックされてTポインタが有効か
  */
 operator bool() const { return ptr_ != nullptr;}

 /**
  * @brief ロックされたTポインタを得る
  * @return Tポインタ
  */
 T *operator &() const { return ptr_; }
};

} // namespace nxpp

こうすると、例えば同じく前回の記事で紹介したnxpp::TextList::sizeメソッドは次のようになります。

  /**
  * @return 現在の要素数
  */
 WORD size() const {
   ObjectLocker<LIST> locker(handle_);
   return !locker ? 0 : size(&locker, fPrefix_);
 }

テキストリストへの挿入、追加

さて、改めて今回は、前回の続きでnxpp::TextListクラスに文字列テキストを挿入するメソッドを作ります。メモリの増減を司るハンドルを扱えるインスタンスメソッドと違い、LIST構造体のポインタを使って操作するクラスメソッドでは、テキストリストの格納領域を増減することができないため、挿入や削除のメソッドはインスタンス向けで作成します。

// class nxpp::TextList内
public:
  /**
  * @brief 要素を指定した位置への挿入
  * @param index 挿入位置
  * @param item 挿入するテキスト
  * @return 例外以外の失敗はfalseを返す
  */
 bool insert(WORD index, const Lmbcs &item) {
   if (handle_ == NULLHANDLE) {
     if (!allocate()) return false;
   }
   if (index > size()) { return false; }
   auto curSize = byteSize();
   Status status = ListAddEntry(
         handle_,
         fPrefix_,
         &curSize,
         index,
         item.c_str(),
         static_cast<WORD>(item.length())
         );
   if (!status) { throw status; }
   return true;
 }

 /**
  * @brief 末尾への要素追加
  * @param item 追加するテキスト
  */
 bool push_back(const Lmbcs &item) {
   return insert(size(), item);
 }

insertメソッドは、テキストをテキストリストの任意の位置に挿入します。引数にはindex(挿入位置)とitem(挿入テキスト)を取ります。
デフォルトコンストラクタでインスタンスを作成した時はまだ領域を確保していない(ハンドルがない)ので、allocateメソッドを使ってハンドルを取得します。
index(挿入位置)は0〜要素数-1と、末尾に追加するため要素数まで指定できます。WORD型がunsignedなのでマイナスはない前提です。
テキストを挿入するAPIはListAddEntryを使用します(紹介記事)。ListAddEntryはSTATUS型を返すので、NOERROR以外を返したらステータス値をスローします。成功すればtrueを返します。

続くpush_backは、単に末尾にテキストを追加したい時のショートカットメソッドです。

まとめ

次回は、テキストリストから要素を取り除くメソッドをご紹介する予定です。

この記事が気に入ったらサポートをしてみませんか?