見出し画像

Notes C API探訪: NSFFormulaCompileをラップ

以前の記事で、何回かに分けて@式の扱い方について紹介しました。

NSFFormulaCompile(関数)
式ハンドルの使用方法(その1)
式ハンドルの使用方法(その2)
@式のデコンパイル

今回は、このうちのNSFFormulaCompile関数を使ったラップクラスを作ってみます。

#ifndef NXPP_FORMULA_HPP
#define NXPP_FORMULA_HPP

#include "./nxpp_status.hpp"
#include "./lmbcs/nxpp_lmbcs.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 Formula;
using FormulaPtr = std::shared_ptr<Formula>;

/**
* @brief @式クラス
*/
class Formula
{
 FORMULAHANDLE handle_; ///< ハンドル

public:

 /**
  * @brief コンパイルエラークラス
  */
 class CompileError
     : public Status
 {
   WORD line_; ///< 行番号
   WORD col_; ///< 列番号
   WORD offset_; ///< エラー位置までのオフセット
   WORD length_; ///< エラー範囲の文字数

 public:
   /**
    * @brief デフォルトコンストラクタ
    */
   CompileError()
     : Status()
     , line_(0)
     , col_(0)
     , offset_(0)
     , length_(0)
   {}

   /**
    * @brief コンストラクタ
    * @param status ステータス値
    * @param line 行番号
    * @param col 列番号
    * @param offset エラー位置までのオフセット
    * @param length エラー範囲の文字数
    */
   CompileError(STATUS status, WORD line, WORD col, WORD offset, WORD length)
     : Status(status)
     , line_(line)
     , col_(col)
     , offset_(offset)
     , length_(length)
   {}

   WORD line() const { return line_; }

   WORD col() const { return col_; }

   WORD offset() const { return offset_; }

   WORD length() const { return length_; }
 };

 /**
  * @brief デフォルトコンストラクタ
  */
 Formula() : handle_(NULLHANDLE) {}

 /**
  * @brief コンストラクタ
  * @param handle @式ハンドル
  */
 Formula(FORMULAHANDLE handle) : handle_(handle) {}

 /**
  * @brief デストラクタ
  */
 virtual ~Formula() {
   close();
 }

 /**
  * @return ハンドルを返す
  */
 FORMULAHANDLE handle() const { return handle_; }

 /**
  * @brief ハンドルを閉じる
  */
 void close() {
   if (handle_ != NULLHANDLE) {
     OSMemFree(handle_);
     handle_ = NULLHANDLE;
   }
 }

 /**
  * @brief @式をコンパイルする
  * @param statement 文字列の@式
  * @param column ビューの列の内部名、ビュー以外に使用する場合はヌル文字列
  * @return Formulaクラスの共有ポインタ
  */
 static FormulaPtr compile(
     const Lmbcs &statement,
     const Lmbcs &column = ""
     ) noexcept(false) {
   FORMULAHANDLE handle = NULLHANDLE;
   STATUS compileStatus = NOERROR;
   WORD formulaLen = 0, line = 0, col = 0, offset = 0, length = 0;
   Status status = NSFFormulaCompile(
         column.empty() ? nullptr : const_cast<char*>(column.c_str()),
         static_cast<WORD>(column.size()),
         const_cast<char*>(statement.c_str()),
         static_cast<WORD>(statement.size()),
         &handle,
         &formulaLen,
         &compileStatus,
         &line,
         &col,
         &offset,
         &length
         );
   if (!status) { throw status; }
   CompileError compileError { compileStatus, line, col, offset, length };
   if (!compileError) { throw compileError; }
   return std::make_shared<Formula>(handle);
 }
};

} // namespace nxpp

#endif // NXPP_FORMULA_HPP

例えばこんな風に使います。

auto fPtr = nxpp::Formula::compile("@All;");

まとめ

@式のハンドルだけを受け取るAPI関数であればこれだけで十分です。式を文書上などで評価しなければいけない場合は、ここからさらに計算ハンドルを得る必要があります。

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