1 /*
2  * Copyright (C) 2015-2016 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #pragma once
18 
19 #include "block_device.h" /* for data_block_t */
20 
21 /**
22  * struct block_range - Struct describing a range of blocks
23  * @start:      First block in range.
24  * @end:        Last block in range plus one.
25  */
26 struct block_range {
27     data_block_t start;
28     data_block_t end;
29 };
30 #define BLOCK_RANGE_INITIAL_VALUE(block_range) \
31     { 0, 0 }
32 
33 /**
34  * block_range_empty - Check if block range is empty
35  * @range:      Block range to check.
36  *
37  * Return: %true if @range is empty, %false otherwise.
38  */
block_range_empty(const struct block_range range)39 static inline bool block_range_empty(const struct block_range range) {
40     assert(range.end >= range.start);
41 
42     return range.start == range.end;
43 }
44 
45 /*
46  * block_in_range - Check if block is in range
47  * @range:      Block range to check.
48  * @block:      Block to check.
49  *
50  * Return: %true if @block is in @range, %false otherwise.
51  */
block_in_range(const struct block_range range,data_block_t block)52 static inline bool block_in_range(const struct block_range range,
53                                   data_block_t block) {
54     assert(range.end >= range.start);
55 
56     return (block >= range.start && block < range.end);
57 }
58 
59 /**
60  * block_in_range - Check if two block ranges have any overlap
61  * @a:          Block range to check.
62  * @b:          Block range to check.
63  *
64  * Return: %true if @a and @b share any blocks, %false otherwise.
65  */
block_range_overlap(const struct block_range a,const struct block_range b)66 static inline bool block_range_overlap(const struct block_range a,
67                                        const struct block_range b) {
68     return block_in_range(a, b.start) || block_in_range(b, a.start);
69 }
70 
71 /**
72  * block_range_before - Check if a block range start before another block range
73  * @a:          Block range to check.
74  * @b:          Block range to check.
75  *
76  * Return: %true if @a starts at a lower block number than @b where the start
77  * block number of an empty block range is considered infinite, %false
78  * otherwise.
79  */
block_range_before(const struct block_range a,const struct block_range b)80 static inline bool block_range_before(const struct block_range a,
81                                       const struct block_range b) {
82     return !block_range_empty(a) && (block_range_empty(b) || a.start < b.start);
83 }
84 
85 /**
86  * block_range_is_sub_range - Check if a block range is a subset of another
87  * range
88  * @range:      Block range to check.
89  * @sub_range:  Block range to check.
90  *
91  * Return: %true if every block in @sub_range is also in @range, %false
92  * otherwise. @sub_range is not allowed to be be empty.
93  */
block_range_is_sub_range(const struct block_range range,const struct block_range sub_range)94 static inline bool block_range_is_sub_range(
95         const struct block_range range,
96         const struct block_range sub_range) {
97     assert(!block_range_empty(sub_range));
98     return block_in_range(range, sub_range.start) &&
99            block_in_range(range, sub_range.end - 1);
100 }
101 
102 /**
103  * block_range_eq - Check if two block ranges are identical
104  * @a:          Block range to check.
105  * @b:          Block range to check.
106  *
107  * Return: %true if @a and @b are identical, %false otherwise.
108  */
block_range_eq(const struct block_range a,const struct block_range b)109 static inline bool block_range_eq(const struct block_range a,
110                                   const struct block_range b) {
111     assert(a.end >= a.start);
112     assert(b.end >= b.start);
113 
114     return a.start == b.start && a.end == b.end;
115 }
116 
117 /**
118  * block_range_init_single - Initialize a block range containing a single block
119  * @range:      Block range object to initialize.
120  * @block:      Block that should be in @range.
121  */
block_range_init_single(struct block_range * range,data_block_t block)122 static inline void block_range_init_single(struct block_range* range,
123                                            data_block_t block) {
124     range->start = block;
125     range->end = block + 1;
126 }
127 
128 /**
129  * block_range_clear - Remove all blocks from a block range
130  * @range:      Block range object to clear.
131  */
block_range_clear(struct block_range * range)132 static inline void block_range_clear(struct block_range* range) {
133     range->start = 0;
134     range->end = 0;
135 }
136