Notes C API探訪: 計算ハンドルのラップ
前回の記事で、@式をコンパイルする関数NSFFormulaCompileをラップしてみました。コンパイルが済むと、@式はバイナリーデータの状態になり、その領域はハンドルFORMULAHANDLEとして管理されます。
@式ハンドルの状態でも利用できる場面はありますが、これを実行して結果を得たい場合、@式ハンドルから「計算ハンドル」を生み出す必要があります。その辺りは「式ハンドルの使用方法(その1)」の記事で紹介しています。
今回は、この計算ハンドルの取得から破棄までの作業をラップしたクラスを作ってみます。
// nxpp/include/nxpp_compute.hpp
#ifndef NXPP_COMPUTE_HPP
#define NXPP_COMPUTE_HPP
#include "./nxpp_status.hpp"
#include "./lmbcs/nxpp_lmbcs.hpp"
#include "./nxpp_variant.hpp"
#include "./nxpp_utils.hpp"
#include <memory>
#ifdef NT
#pragma pack(push, 1)
#endif
#include <global.h>
#include <nsfsearc.h>
#include <osmem.h>
#ifdef NT
#pragma pack(pop)
#endif
namespace nxpp {
class Compute;
using ComputePtr = std::shared_ptr<Compute>;
/**
* @brief 計算クラス
*/
class Compute
{
HCOMPUTE handle_; ///< 計算ハンドル
public:
/**
* @brief 評価結果クラス
*/
class Evaluated
{
Variant value_; ///< 評価結果
BOOL noteMatchedFormula_; ///< 文書が式にマッチしたか
BOOL noteShouldBeDeleted_; ///< 式が文書の削除を示しているか
BOOL noteModified_; ///< 文書が式により変更されたか
public:
/**
* @brief デフォルトコンストラクタ
*/
Evaluated()
: value_()
, noteMatchedFormula_(FALSE)
, noteShouldBeDeleted_(FALSE)
, noteModified_(FALSE)
{}
/**
* @brief コンストラクタ
* @param value 評価結果
* @param noteMatchedFormula 文書が式にマッチしたか
* @param noteShouldBeDeleted 式が文書の削除を示しているか
* @param noteModified 文書が式により変更されたか
*/
Evaluated(
Variant &&value,
BOOL noteMatchedFormula,
BOOL noteShouldBeDeleted,
BOOL noteModified
)
: value_(std::move(value))
, noteMatchedFormula_(noteMatchedFormula)
, noteShouldBeDeleted_(noteShouldBeDeleted)
, noteModified_(noteModified)
{}
Variant value() const { return value_; }
BOOL noteMatchedFormula() const { return noteMatchedFormula_; }
BOOL noteShouldBeDeleted() const { return noteShouldBeDeleted_; }
BOOL noteModified() const { return noteModified_; }
};
/**
* @brief デフォルトコンストラクタ
*/
Compute() : handle_(nullptr) {}
/**
* @brief コンストラクタ
* @param handle @式ハンドル
*/
Compute(HCOMPUTE handle) : handle_(handle) {}
/**
* @brief デストラクタ
*/
virtual ~Compute() {
stop();
}
/**
* @return ハンドルを返す
*/
HCOMPUTE handle() const { return handle_; }
/**
* @brief ハンドルを閉じる
*/
void stop() {
if (handle_ != nullptr) {
NSFComputeStop(handle_);
handle_ = nullptr;
}
}
/**
* @brief 計算を評価する
* @param hNote 計算の評価対象となる文書ハンドル、式を単独で評価する場合は0
* @return 評価結果インスタンス
*/
Evaluated evaluate(
NOTEHANDLE hNote = NULLHANDLE
) noexcept(false) {
return evaluate(handle_, hNote);
}
/**
* @brief 計算を評価する
* @param hCompute 計算ハンドル
* @param hNote 計算の評価対象となる文書ハンドル、式を単独で評価する場合は0
* @return 評価結果インスタンス
*/
static Evaluated evaluate(
HCOMPUTE hCompute,
NOTEHANDLE hNote = NULLHANDLE
) noexcept(false) {
DHANDLE handle = NULLHANDLE;
WORD len = 0;
BOOL noteMatchedFormula = FALSE,
noteShouldBeDeleted = FALSE,
noteModified = FALSE;
Status status = NSFComputeEvaluate(
hCompute,
hNote,
&handle,
&len,
¬eMatchedFormula,
¬eShouldBeDeleted,
¬eModified
);
if (!status) { throw status; }
ObjectLocker<char> locker(handle);
if (!locker) return Evaluated();
Variant value(
dataTypePrefix(&locker, TRUE),
skipPrefixPtr<char>(&locker, TRUE),
len);
return Evaluated(
std::move(value),
noteMatchedFormula,
noteShouldBeDeleted,
noteModified
);
}
/**
* @brief 式から計算ハンドルを取得する
* @param pFormula ロック済み式ハンドルのポインタ
* @return Computeインスタンスの共有ポインタ
*/
static ComputePtr start(void *pFormula) noexcept(false) {
HCOMPUTE handle = nullptr;
Status status = NSFComputeStart(0, pFormula, &handle);
if (!status) { throw status; }
return std::make_shared<Compute>(handle);
}
};
} // namespace nxpp
#endif // NXPP_COMPUTE_HPP
これを利用するには、例えば次のようにします。
auto fPtr = nxpp::Formula::compile("@Today");
nxpp::ObjectLocker locker<char>(fPtr->handle());
auto cPtr = nxpp::Compute::start(&locker);
auto evaluated = cPtr->evaluate();
auto value = evaluated.value();
auto result = value.toString();
ui->textBrowser->append(fromLmbcsQ(result.value());
まとめ
今年2021年の6月28日から、まずは紹介していかなければならない、Notes C APIの基本のキと、それをC++で使いやすくする方法、そしてQt5を利用したGUIアプリでの活用方法などを中心に、120を超える記事を毎日投稿してきました。ここまで読んでいただいて本当に感謝です。しかしながら、ここへ来て仕込みの量と精度が非常に高くなって、クオリティの低下が懸念される段階になってきました。今日はハロウィン、10月31日と区切りもいいので、来月からは週単位をメドに記事を投稿していきたいと思っています。これからもどうぞよろしくお願いいたします。