| /* |
| * Copyright (C) 2015-2016 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #pragma once |
| |
| #include "block_device.h" /* for data_block_t */ |
| |
| /** |
| * struct block_range - Struct describing a range of blocks |
| * @start: First block in range. |
| * @end: Last block in range plus one. |
| */ |
| struct block_range { |
| data_block_t start; |
| data_block_t end; |
| }; |
| #define BLOCK_RANGE_INITIAL_VALUE(block_range) \ |
| { 0, 0 } |
| |
| /** |
| * block_range_empty - Check if block range is empty |
| * @range: Block range to check. |
| * |
| * Return: %true if @range is empty, %false otherwise. |
| */ |
| static inline bool block_range_empty(const struct block_range range) { |
| assert(range.end >= range.start); |
| |
| return range.start == range.end; |
| } |
| |
| /* |
| * block_in_range - Check if block is in range |
| * @range: Block range to check. |
| * @block: Block to check. |
| * |
| * Return: %true if @block is in @range, %false otherwise. |
| */ |
| static inline bool block_in_range(const struct block_range range, |
| data_block_t block) { |
| assert(range.end >= range.start); |
| |
| return (block >= range.start && block < range.end); |
| } |
| |
| /** |
| * block_in_range - Check if two block ranges have any overlap |
| * @a: Block range to check. |
| * @b: Block range to check. |
| * |
| * Return: %true if @a and @b share any blocks, %false otherwise. |
| */ |
| static inline bool block_range_overlap(const struct block_range a, |
| const struct block_range b) { |
| return block_in_range(a, b.start) || block_in_range(b, a.start); |
| } |
| |
| /** |
| * block_range_before - Check if a block range start before another block range |
| * @a: Block range to check. |
| * @b: Block range to check. |
| * |
| * Return: %true if @a starts at a lower block number than @b where the start |
| * block number of an empty block range is considered infinite, %false |
| * otherwise. |
| */ |
| static inline bool block_range_before(const struct block_range a, |
| const struct block_range b) { |
| return !block_range_empty(a) && (block_range_empty(b) || a.start < b.start); |
| } |
| |
| /** |
| * block_range_is_sub_range - Check if a block range is a subset of another |
| * range |
| * @range: Block range to check. |
| * @sub_range: Block range to check. |
| * |
| * Return: %true if every block in @sub_range is also in @range, %false |
| * otherwise. @sub_range is not allowed to be be empty. |
| */ |
| static inline bool block_range_is_sub_range( |
| const struct block_range range, |
| const struct block_range sub_range) { |
| assert(!block_range_empty(sub_range)); |
| return block_in_range(range, sub_range.start) && |
| block_in_range(range, sub_range.end - 1); |
| } |
| |
| /** |
| * block_range_eq - Check if two block ranges are identical |
| * @a: Block range to check. |
| * @b: Block range to check. |
| * |
| * Return: %true if @a and @b are identical, %false otherwise. |
| */ |
| static inline bool block_range_eq(const struct block_range a, |
| const struct block_range b) { |
| assert(a.end >= a.start); |
| assert(b.end >= b.start); |
| |
| return a.start == b.start && a.end == b.end; |
| } |
| |
| /** |
| * block_range_init_single - Initialize a block range containing a single block |
| * @range: Block range object to initialize. |
| * @block: Block that should be in @range. |
| */ |
| static inline void block_range_init_single(struct block_range* range, |
| data_block_t block) { |
| range->start = block; |
| range->end = block + 1; |
| } |
| |
| /** |
| * block_range_clear - Remove all blocks from a block range |
| * @range: Block range object to clear. |
| */ |
| static inline void block_range_clear(struct block_range* range) { |
| range->start = 0; |
| range->end = 0; |
| } |