![見出し画像](https://assets.st-note.com/production/uploads/images/56927389/rectangle_large_type_2_2d85c2df50e6cd4ffe1e866bdf746d19.png?width=800)
Notes C API探訪: RANGE(データ型)その3
LIST型には、エントリー数は変えられないが、エントリー数の範囲内でテキストを設定できるListAddText関数がありました。それのRANGE型版を作ってみます。
RangeAddItem
RangeAddItemテンプレート関数は、RANGE型の指定したアイテムエントリー位置に指定したデータを設定します。
/**
* @brief 指定した位置のアイテムエントリーを設定する。
* @tparam Traits 特性構造体
* @param pRange ロック済みメモリポインタへのポインタ
* @param fPrefixDataType データタイププレフィックスの有無
* @param EntrNumber アイテムのエントリー位置
* @param pData 設定するアイテムデータ
*/
template <typename Traits>
void RangeAddItem(
void *pRange,
BOOL fPrefixDataType,
WORD EntryNumber,
const typename Traits::item *pData
) {
char *pos = static_cast<char*>(pRange)
+ sizeof(WORD) * (fPrefixDataType ? 1 : 0)
+ sizeof(RANGE)
+ sizeof(Traits::item) * EntryNumber;
*reinterpret_cast<typename Traits::item*>(pos) = *pData;
}
・Traitsは、前回の記事で紹介した特性構造体、NumberRangeTraitsかTimeDateRangeTraitsかを指定します。
・pRangeは、RANGEデータのロック済みメモリポインタを指定します。
・fPrefixDataTypeは、データタイププレフィックスを持つかどうか指定します。
・EntryNumberは、設定したいアイテムリスト(ペアでない方のリスト)のインデックス番号を指定します。
・pDataは、設定したいアイテムデータを指定します。
RangeAddPair
RangeAddPairテンプレート関数は、RANGE型の指定したペアエントリー位置に指定したデータを設定します。
/**
* @brief 指定した位置のペアエントリーを設定する。
* @tparam Traits 特性構造体
* @param pRange ロック済みメモリポインタへのポインタ
* @param fPrefixDataType データタイププレフィックスの有無
* @param EntrNumber ペアのエントリー位置
* @param pData 設定するペアデータ
*/
template <typename Traits>
void RangeAddPair(
void *pRange,
BOOL fPrefixDataType,
WORD EntryNumber,
const typename Traits::pair *data
) {
char *pos = static_cast<char*>(pRange)
+ sizeof(WORD) * (fPrefixDataType ? 1 : 0);
RANGE *_pRange = reinterpret_cast<RANGE*>(pos);
pos += sizeof(RANGE)
+ sizeof(Traits::item) * _pRange->ListEntries
+ sizeof(Traits::pair) * EntryNumber;
*reinterpret_cast<typename Traits::pair*>(pos) = *data;
}
・Traitsは、前回の記事で紹介した特性構造体、NumberRangeTraitsかTimeDateRangeTraitsかを指定します。
・pRangeは、RANGEデータのロック済みメモリポインタを指定します。
・fPrefixDataTypeは、データタイププレフィックスを持つかどうか指定します。
・EntryNumberは、設定したいペアリストのインデックス番号を指定します。
・pDataは、設定したいペアデータを指定します。
コーディング例
// 設定する日時データを用意
1 TIMEDATE time0, time1;
2 OSCurrentTIMEDATE(&time0);
3 TimeDateAdjust(&time0, 0, 0, 0, -10, 0, 0);
4 OSCurrentTIMEDATE(&time1);
5 TimeDateAdjust(&time1, 0, 0, 0, 10, 0, 0);
// RANGE型の0番、1番に用意したデータを設定
6 RangeAddItem<TimeDateRangeTraits>(pRange, fPrefixDataType, 0, &time0);
7 RangeAddItem<TimeDateRangeTraits>(pRange, fPrefixDataType, 1, &time1);
// 設定する日時ペアデータを用意
8 TIMEDATE_PAIR pair;
9 OSCurrentTIMEDATE(&pair.Lower);
10 TimeDateAdjust(&pair.Lower, 0, -10, 0, 0, 0, 0);
11 OSCurrentTIMEDATE(&pair.Upper);
12 TimeDateAdjust(&pair.Upper, 0, 10, 0, 0, 0, 0);
// RANGE型の0番に用意したペアデータを設定
13 RangeAddPair<TimeDateRangeTraits>(pRange, fPrefixDataType, 0, &pair);
(1〜5行目) TIMEDATE型を2つ用意し、それぞれ10日前、10日後の時間に調整します。
(6~7行目) RANGE型のアイテムリストに、前述のTIMEDATE型データを追加(設定)します。
(8〜12行目) TIMEDATE_PAIR型を用意し、下位を10分前、上位を10分後の時間に調整します。
(13行目) Range型のペアリストに、10分前〜10分後のペアデータを追加します。
まとめ
ListAddText関数は、リスト内の設定順を0から指定していかないと、各エントリーの内容が崩れる現象がありましたが、各エントリーが固定長のRANGEではそんな現象は起きないので、比較的楽なコーディングと言えると思います。
また、現状NUMBER型とTIMEDATE型は同じ8バイトなので、わざわざテンプレートを使わなくても、共通化した実装はできるので、テンプレート機能のないC用に実装するのも難しくないでしょう。
注意: コードの利用においてチブル・システムズは一切の責任を負いません。自己責任でご利用をお願いいたします。
この記事が気に入ったらサポートをしてみませんか?