![見出し画像](https://assets.st-note.com/production/uploads/images/60409661/rectangle_large_type_2_207fcd525e5be9f2a559f00422f1eb5c.png?width=1200)
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ラップ関数を使った、日時、数値と文字列との交互変換する仕組みを作っていきます。