Notes C API探訪: 数値をテキストにコンバートする
前回までの「Qt5再入門」15回シリーズでお届けしたコンバートシミュレーターダイアログで、Qt5のウィジェット開発機能を使ったGUIを構築してきました。このダイアログはあくまでUI、入出力の手段であって、本命は今回以降の「数値、日時とテキストとの相互コンバート」になります。今回は数値からテキストへのコンバートについて扱います。
前回の記事で紹介したソースコードに、以下の記述がありました。
// convertsimulatordialog.cppから抜粋
void ConvertSimulatorDialog::convertNumberToText() {
nxpp::NumberToTextConverter converter;
setIntlFormat(&converter);
setNumberFormat(&converter);
try {
bool ok = false;
double num = ui->numberToTextSrcLineEdit->text().toDouble(&ok);
if (!ok) {
consoleLog(tr("Unable to convert numbers to text.")); // throwもあり
return;
}
nxpp::Lmbcs text = converter(&num);
ui->numberToTextDestLineEdit->setText(fromLmbcsQ(text));
}
// Notesステータスがスローされたらそのエラーメッセージに変換して表示
catch (nxpp::Status &status) {
consoleLog(nxpp::qt::fromStatus(status.error()));
}
// それ以外の例外ならそのメッセージを表示
catch (std::exception &ex) {
std::string what(ex.what());
consoleLog(QString::fromStdString(what));
}
}
この中に、nxpp::NumberToTextConverter という、私が定義したクラスがあります。これは数値からテキストに変換するクラスで、 operator () を備えているので、「関数オブジェクト」として使用することができます。
まずは定義を見ていきます。
// nxpp/include/nxpp/nxpp_number.hpp
// ...
namespace nxpp {
// ...
class NumberToTextConverter
: public NumberConverter
{
public:
NumberToTextConverter() : NumberConverter() {}
NumberToTextConverter(
intl::SettingsPtr iPtr,
NumberFormatPtr nPtr
)
: NumberConverter(iPtr, nPtr)
{}
Lmbcs operator () (NUMBER *pNum) const {
char buffer[MAXALPHANUMBER] = "";
WORD len = 0;
Status status = ConvertFLOATToText(
!intlSettingsPtr_ ? nullptr : intlSettingsPtr_->data(),
!formatPtr_ ? nullptr : formatPtr_->data(),
pNum,
buffer,
MAXALPHANUMBER,
&len
);
if (!status) { throw status; }
return Lmbcs(buffer, len);
}
};
// ...
} // namespace nxpp
// ...
関数オブジェクトの「関数機能」実装がメインで、NUMBERポインタを受け取り、ConvertFLOATToText関数を呼び出して、数値をテキストに変換し、LMBCS文字列として返しています。
ConvertFLOATToText関数は、INTLFORMATとNFMTを受け入れることができるので、このオブジェクト関数のオブジェクト内に、設定があればそれらを使用し、なければヌルポインタでConvertFLOATToText関数を呼び出すようになっています。
さて、この関数オブジェクトクラスの継承元 NumberConverter はどうなっているのか見てみます。
// nxpp/include/nxpp/nxpp_number.hpp
// ...
namespace nxpp {
// ...
using NumberFormatPtr = std::shared_ptr<NumberFormat>;
class NumberConverter
: public intl::ConverterBase<NumberFormat>
{
public:
NumberConverter() : intl::ConverterBase<NumberFormat>() {}
NumberConverter(
intl::SettingsPtr iPtr,
NumberFormatPtr nPtr
)
: intl::ConverterBase<NumberFormat>(iPtr, nPtr)
{}
};
// ...
} // namespace nxpp
// ...
コード中の NumberFormat は、以前紹介したNFMT構造体のラップクラスです。
このクラスは、さらに intl::ConverterBase テンプレートクラスを継承元にしていますので、これも定義を見てみます。
// nxpp/include/nxpp/nxpp_intl.hpp
// ...
namespace nxpp::intl {
// ...
using SettingsPtr = std::shared_ptr<Settings>;
template <class T>
class ConverterBase
{
protected:
SettingsPtr intlSettingsPtr_;
std::shared_ptr<T> formatPtr_;
public:
ConverterBase() : intlSettingsPtr_() , formatPtr_() {}
ConverterBase(
intl::SettingsPtr iPtr,
std::shared_ptr<T> tPtr
)
: intlSettingsPtr_(iPtr)
, formatPtr_(tPtr)
{}
void setIntlSettings(SettingsPtr sPtr) {
intlSettingsPtr_ = sPtr;
}
void setFormat(std::shared_ptr<T> ptr) {
formatPtr_ = ptr;
}
};
// ...
} // namespace nxpp::intl
// ...
メンバ変数として、INTLFORMATをラップしたクラスのスマートポインタと、NFMTまたはTFMTをラップしたクラスのスマートポインタを有します。これらは、デフォルトではヌルポインタとなっています。API関数 Convert***ToText、またはConvertTextTo***では、ヌルポインタは「設定なし」と見立てて処理できるので、その仕様に合わせています。
フォーマットを調整して適用したい場合、それぞれのスマートポインタを受け入れられるようにもなっています。
まとめ
今回は、ご紹介予定の関数オブジェクトクラスのうちから1つだけ紹介しました。
1. 数値 → テキスト (今回紹介済み)
2. テキスト → 数値
3. 日時 → テキスト
4. テキスト → 日時
残りの3つも、原則今回のクラスの設計と同じようなスタイルを踏襲しています。予定としては、次回に2番を、以降に3と4をご紹介する予定です。
実は、3と4は日時が絡みますが、Qtの日時ウィジェットからNotes C APIのTIMEDATE構造体に変換したり、その逆の変換もしなくてはいけません。API自体は「Notes C API探訪: TIME(データ型)」の回でご紹介しているので、そのラップコードも一緒にご紹介していきたいと思います。