見出し画像

Notes C API探訪: TFMTとNFMTのラップ

今回は、日時や数値を文字列化したり、文字列から日時や数値にしたりする関数で使用する、フォーマット設定構造体をラップします。先日の以下の記事で紹介しているINTLFORMAT構造体も、先の関数で使用しますが、INTLFORMATはざっくり国別の設定で、日時と数値の設定が同居しています。TFMTとNFMTは、日時用、数値用とはっきり分かれています。

TFMT

まず、日時用フォーマット設定構造体のTFMTを見ていきます。これは以前、以下の記事で紹介しています。

これをクラスでラップしてみたいと思います。

// nxpp/include/nxpp/nxpp_timedate.hpp

#ifndef NXPP_TIMEDATE_HPP
#define NXPP_TIMEDATE_HPP

#include <utility>

#ifdef NT
#pragma pack(push, 1)
#endif

#include <global.h>
#include <misc.h>

#ifdef NT
#pragma pack(pop)
#endif

namespace nxpp {

/**
* @brief 日時フォーマットクラス
*/
class TimeFormat
{
 TFMT value_;

public:
 /**
  * @brief デフォルトコンストラクタ
  */
 TimeFormat() : value_({TDFMT_FULL,TTFMT_FULL,TZFMT_NEVER,TSFMT_DATETIME}) {}

 /**
  * @brief コンストラクタ
  * @param date 日付フォーマット値(TDFMT_xxx)
  * @param time 時刻フォーマット値(TTFMT_xxx)
  * @param zone タイムゾーンフォーマット値(TZFMT_xxx)
  * @param structure 構成フォーマット値(TSFMT_xxx)
  */
 TimeFormat(BYTE date, BYTE time, BYTE zone, BYTE structure)
   : value_({date, time, zone, structure})
 {}

 /**
  * @return TFMTへのポインタ
  */
 TFMT *data() { return &value_; }

 /**
  * @return 日付フォーマット
  */
 BYTE date() const { return value_.Date; }

 /**
  * @return 時刻フォーマット
  */
 BYTE time() const { return value_.Time; }

 /**
  * @return タイムゾーンフォーマット
  */
 BYTE zone() const { return value_.Zone; }

 /**
  * @return 構成フォーマット
  */
 BYTE structure() const { return value_.Structure; }

 /**
  * @param v 設定する日付フォーマット値
  */
 void setDate(BYTE v) { value_.Date = v; }

 /**
  * @param v 設定する時刻フォーマット値
  */
 void setTime(BYTE v) { value_.Time = v; }

 /**
  * @param v 設定するタイムゾーンフォーマット値
  */
 void setZone(BYTE v) { value_.Zone = v; }

 /**
  * @param v 設定する構成フォーマット値
  */
 void setStructure(BYTE v) { value_.Structure = v; }
};

} // namespace nxpp

#endif // NXPP_TIMEDATE_HPP

TFMTは、各メンバー変数が単純な数値設定なので、それぞれの値を取り出したり、設定したりするだけで実装できます。日時→文字列、文字列→日時、それぞれの変換関数で利用できるように、構造体のポインタに直接アクセスできるようになっています。

NFMT

NFMT構造体は、数値→文字列、文字列→数値、それぞれの変換関数で利用するフォーマットを規定した構造体です。

// #include <misc.h>

/*	Number Format */

#define	NFMT_GENERAL		0		/* Number Formats */
#define	NFMT_FIXED			1
#define	NFMT_SCIENTIFIC		2
#define	NFMT_CURRENCY		3
#define	NFMT_BYTES			4 		/* LI 3926.07  Number Format */

#define	NATTR_PUNCTUATED	0x0001	/* Number Attributes */
#define	NATTR_PARENS		0x0002
#define	NATTR_PERCENT		0x0004
#define NATTR_VARYING		0x0008
#define NATTR_BYTES			0x0010 /* LI 3926.07, new number format type in Hannover, added for backward compatibility */

typedef struct {
	BYTE Digits;					/* Number of decimal digits */
	BYTE Format;					/* Display Format */
	BYTE Attributes;				/* Display Attributes */
	BYTE Unused;
} NFMT;

Digitsは、小数点以下の桁数です。
Formatは、NFMT_xxxで規定されているフォーマットタイプです。
Attributesは、NATTR_xxxでフラグ化されているビットスイッチ型属性値です。
Unusedは、使用されないので0を指定します。

NFMT_BYTES、NATTR_BYTESは数値をバイト表記するためのものらしいのですが、コメントを読むと、「Hannover(Lotus Notes 8の開発コード名)の後方互換性のために追加された新しい値」とあります。ただ、少なくともNotesクライアント9のデザイナーでは、これに相当するフィールド設定はないようです。

では、これをクラスラップしてみます。

// nxpp/include/nxpp/nxpp_number.hpp

#ifndef NXPP_NUMBER_HPP
#define NXPP_NUMBER_HPP

#ifdef NT
#pragma pack(push, 1)
#endif

#include <global.h>
#include <misc.h>

#ifdef NT
#pragma pack(pop)
#endif

namespace nxpp {

/**
* @brief 数値フォーマットクラス
*/
class NumberFormat
{
 NFMT value_;

public:
 /**
  * @brief デフォルトコンストラクタ
  */
 NumberFormat() : value_({2,NFMT_GENERAL,0,0}) {}

 /**
  * @brief コンストラクタ
  * @param digits 小数点以下の桁数
  * @param format フォーマット値(NFMT_xxx)
  * @param attributes フォーマット属性(NATTR_xxx)
  */
 NumberFormat(BYTE digits, BYTE format, BYTE attributes)
   : value_({digits, format, attributes, 0})
 {}

 /**
  * @return NFMTへのポインタ
  */
 NFMT *data() { return &value_; }

 /**
  * @return 小数点以下の桁数
  */
 BYTE digits() const { return value_.Digits; }

 /**
  * @param v 設定する小数点以下の桁数
  */
 void setDigits(BYTE v) { value_.Digits = v; }

 /**
  * @return フォーマット値(NFMT_xxx)
  */
 BYTE format() const { return value_.Format; }

 /**
  * @param v 設定するフォーマット値(NFMT_xxx)
  */
 void setFormat(BYTE v) { value_.Format = v; }

 /**
  * @brief 属性値から該当属性の真偽を調べる
  * @param A 属性
  * @return 属性が真ならtrue
  */
 bool isAttribute(WORD A) const {
   return value_.Attributes & A;
 }

 /**
  * @brief 属性値の真偽を設定する
  * @param A 属性
  * @param a 真にするならtrue
  */
 void setAttribute(WORD A, bool a) {
   if (a) { value_.Attributes |= A; }
   else { value_.Attributes &= (~A); }
 }

 /**
  * @return 3桁ごとに分離記号を付けるか
  */
 bool isPunctuated() const { return isAttribute(NATTR_PUNCTUATED); }

 /**
  * @return 負のときに括弧を付けるか
  */
 bool isParen() const { return isAttribute(NATTR_PARENS); }

 /**
  * @return パーセント表示をするか
  */
 bool isPercent() const { return isAttribute(NATTR_PERCENT); }

 /**
  * @return 小数点位置を可変にするか
  */
 bool isVarying() const { return isAttribute(NATTR_VARYING); }

 /**
  * @return バイト表示するか
  */
 bool isBytes() const { return isAttribute(NATTR_BYTES); }

 /**
  * @param a 3桁ごとに分離記号を付けるかを設定
  */
 void setPunctuated(bool a) { setAttribute(NATTR_PUNCTUATED, a); }

 /**
  * @param a 負のときに括弧を付けるかを設定
  */
 void setParen(bool a) { setAttribute(NATTR_PARENS, a); }

 /**
  * @param a パーセント表示をするかを設定
  */
 void setPercent(bool a) { setAttribute(NATTR_PERCENT, a); }

 /**
  * @param a 小数点位置を可変にするかを設定
  */
 void setVarying(bool a) { setAttribute(NATTR_VARYING, a); }

 /**
  * @param a バイト表示するかを設定
  */
 void setBytes(bool a) { setAttribute(NATTR_BYTES, a); }
};

} // namespace nxpp

#endif // NXPP_NUMBER_HPP

DigitsとFormatは、通常のゲッター/セッターを用意します。
Attributesは、テンプレート的なメンバ関数を用意して、各属性名が追加ゲッター/セッター関数はそのテンプレート的関数を呼ぶようにしています。

次回は、これらとINTLFORMATラップ関数を使った、日時、数値と文字列との交互変換する仕組みを作っていきます。

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