見出し画像

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用に実装するのも難しくないでしょう。

注意: コードの利用においてチブル・システムズは一切の責任を負いません。自己責任でご利用をお願いいたします。

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