Notes C API探訪: RANGE(データ型)その8
LIST型には、保持しているエントリーすべてを削除できるListRemoveAllEntries関数というのがありました。今回はそれのRANGE型版を作ってみます。
RangeRemoveAllItems
RangeRemoveAllItemsテンプレート関数は、RANGE型のアイテムリス領域にあるすべてのアイテムデータを削除します。確保しているメモリ領域は、アイテムリストデータすべての領域削除を要求しますが、必ずしもそのサイズになるとは限りません。
template <typename Traits>
STATUS RangeRemoveAllItems(
DHANDLE hRange,
BOOL fPrefixDataType
) {
// メモリハンドルをロックしてポインタを取得
void *p0 = reinterpret_cast<char*>(OSLockObject(hRange));
WORD realsize = RangeGetSize<Traits>(p0, fPrefixDataType);
// RANGE型データポインタを取得
DWORD offset = sizeof(WORD) * (fPrefixDataType ? 1 : 0);
RANGE *pRange = reinterpret_cast<RANGE*>(
reinterpret_cast<char*>(p0) + offset
);
// 元々削除できるエントリーがなければ返す。
if (pRange->ListEntries == 0) {
OSUnlockObject(hRange);
return NOERROR;
}
// ペアデータがなければ移動データがないので最低限のサイズにして返す。
if (pRange->RangeEntries == 0) {
pRange->ListEntries = 0;
OSUnlockObject(hRange);
return OSMemRealloc(hRange, offset + sizeof(RANGE));
}
// 減らすサイズを求める。
size_t delta = sizeof(Traits::item) * pRange->ListEntries;
// 削除位置の先端から終端まで求める
char *pos = reinterpret_cast<char*>(p0) + offset + sizeof(RANGE);
char *pos2 = pos + delta;
// カウントを0にし、ペアデータをまるごと移動する。
pRange->ListEntries = 0;
memmove(pos, pos2, sizeof(Traits::pair) * pRange->RangeEntries);
// メモリハンドルをアンロックする
OSUnlockObject(hRange);
// メモリをアイテムサイズ分減らす
return OSMemRealloc(hRange, realsize - delta);
}
・Traitsは、以前の記事で紹介した特性構造体、NumberRangeTraitsかTimeDateRangeTraitsかを指定します。
・hRangeは、RANGE型メモリハンドルを指定します。
・fPrefixDataTypeは、データタイププレフィックスを持つかどうか指定します。
RangeRemoveAllPairs
RangeRemoveAllPairsテンプレート関数は、RANGE型の領域からペアデータをすべて削除します。確保しているメモリ領域はすべてのペアデータ分の縮小を要求しますが、必ずしもそのサイズになるとは限りません。
template <typename Traits>
STATUS RangeRemoveAllPairs(
DHANDLE hRange,
BOOL fPrefixDataType
) {
// メモリハンドルをロックしてポインタを取得
void *p0 = reinterpret_cast<char*>(OSLockObject(hRange));
WORD realsize = RangeGetSize<Traits>(p0, fPrefixDataType);
// RANGE型データポインタを取得
DWORD offset = sizeof(WORD) * (fPrefixDataType ? 1 : 0);
RANGE *pRange = reinterpret_cast<RANGE*>(
reinterpret_cast<char*>(p0) + offset
);
// 元々削除できるエントリーがなければ返す。
if (pRange->RangeEntries == 0) {
OSUnlockObject(hRange);
return NOERROR;
}
// 削除後の新しいサイズを求める(ペアリストは末端なので移動する必要なし)
DWORD newSize = realsize - sizeof(Traits::pair) * pRange->RangeEntries;
pRange->RangeEntries = 0;
// メモリハンドルをアンロックする
OSUnlockObject(hRange);
// メモリをペアサイズ分減らす
return OSMemRealloc(hRange, newSize);
}
・Traitsは、以前の記事で紹介した特性構造体、NumberRangeTraitsかTimeDateRangeTraitsかを指定します。
・hRangeは、RANGE型メモリハンドルを指定します。
・fPrefixDataTypeは、データタイププレフィックスを持つかどうか指定します。
RangeRemoveAll
RangeRemoveAllインライン関数は、RANGE型のデータ領域をすべて削除します。残るのは、(あれば)プレフィックスとRANGE型のデータのみになります。RANGE::ListEntries、RANGE::RangeEntriesともに0に設定されます。なお、確保しているメモリ領域のデータ部すべての縮小を要求しますが、必ずしもそのサイズになるとは限りません。
inline STATUS RangeRemoveAll(
DHANDLE hRange,
BOOL fPrefixDataType
) {
// メモリハンドルをロックしてポインタを取得
char *p0 = reinterpret_cast<char*>(OSLockObject(hRange));
// RANGE型データポインタを取得
DWORD offset = sizeof(WORD) * (fPrefixDataType ? 1 : 0);
RANGE *pRange = reinterpret_cast<RANGE*>(p0 + offset);
// カウンターを0にする。
pRange->ListEntries = 0;
pRange->RangeEntries = 0;
// メモリハンドルをアンロックする
OSUnlockObject(hRange);
// メモリを最小限にする。
return OSMemRealloc(hRange, offset + sizeof(RANGE));
}
・hRangeは、RANGE型メモリハンドルを指定します。
・fPrefixDataTypeは、データタイププレフィックスを持つかどうか指定します。
コーディング例
STATUS status = RangeRemoveAllItems<TimeDateRangeTraits>(hRange, TRUE);
status = RangeRemoveAllPairs<TimeDateRangeTraits>(hRange, TRUE);
status = RangeRemoveAll(hRange, TRUE);
まとめ
RANGE型のデータ構造は、LIST型に比べて、アイテム1つ1つのデータ長が固定なので、メモリ移動などに必要な計算は非常に簡単です。すべてのアイテムを消去するRangeRemoveAllを使ってニュートラルにしてしまえば、TIMEDATE型用からNUMBER型用に変更することもできます。
注意: コードの利用においてチブル・システムズは一切の責任を負いません。自己責任でご利用をお願いいたします。