-
Notifications
You must be signed in to change notification settings - Fork 6
/
AQBitfield.h
326 lines (273 loc) · 10.8 KB
/
AQBitfield.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
//
// AQBitfield.h
// AQAppStateMachine
//
// Created by Jim Dovey on 11-06-14.
// Copyright 2011 Jim Dovey. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//
// Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
//
// Neither the name of the project's author nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
#import <Foundation/Foundation.h>
/// A register-width type representing a single bit. Its value should always be `0` or `1`.
typedef CFBit AQBit;
/**
A class representing a bitfield of indeterminate size.
*/
@interface AQBitfield : NSObject <NSCopying, NSMutableCopying, NSCoding>
{
@protected
NSMutableIndexSet * _storage;
}
/// @name Initialization
/**
Initialize an empty bitfield.
This is the designated initializer for the AQBitfield class.
@return A new bitfield instance, with all bits set to zero.
*/
- (id) init;
/**
Initialize a bitfield using a 32-bit scalar value.
@param bits A 32-bit quantity whose bits will be used as initial content for the bitfield.
@return A new bitfield initialized with a copy of the bits within _bits_.
*/
- (id) initWith32BitField: (UInt32) bits;
/**
Initialize a bitfield using a 64-bit scalar value.
@param bits A 64-bit quantity whose bits will be used as initial content for the bitfield.
@return A new bitfield initialized with a copy of the bits within _bits_.
*/
- (id) initWith64BitField: (UInt64) bits;
/// @name Comparisons
/// Returns a hash code for the object's current state.
- (NSUInteger) hash;
/**
Check for equality with another object.
@param object The object to compare.
@return `YES` if the objects are equal, `NO` otherwise.
*/
- (BOOL) isEqual: (id) object;
/**
Compare the receiver against another bitfield.
@param other The bitfield against which to compare the receiver.
@return An `NSComparisonResult` indicating the fields' relative ordering.
*/
- (NSComparisonResult) compare: (AQBitfield *) other;
/// @name Counting
/**
The number of significant bits within the bitfield.
*NB:* This returns the number of bits in the range which covers all `1` bits in the bitfield.
i.e. it will return `((index of highest 1-bit) + 1)`.
*/
@property (nonatomic, readonly) NSUInteger count;
/**
Count the number of bits with a particular value within a range.
@param bit The bit value to count.
@param range The range of bits to check.
@return The number of bits set to the value of _bit_ within _range_.
*/
- (NSUInteger) countOfBit: (AQBit) bit inRange: (NSRange) range;
/**
Determine whether a given bit value exists within a range.
@param bit The bit value for which to search.
@param range The range of bits to check.
@return `YES` if the given bit value exists within the range, `NO` otherwise.
*/
- (BOOL) containsBit: (AQBit) bit inRange: (NSRange) range;
/// @name Bit Accessors
/**
Inspect the value of a specified bit.
@param index The index of the bit to check.
@result The value of the specified bit.
*/
- (AQBit) bitAtIndex: (NSUInteger) index;
/**
Obtain a (zero-based) bitfield containing a copy of all bits from a given range.
@param range The range of the receiver from which to create the new bitfield.
@result A new bitfield containing the bits from the specified range.
@exception NSRangeException Thrown if the range is beyond that allowable (`0..NSNotFound`)
*/
- (AQBitfield *) bitfieldFromRange: (NSRange) range;
/// @name Significant Bits
/**
Find the index of the least-significant bit containing a specified value.
@param bit The bit value for which to search.
@return The index of the least-significant bit with the given value.
*/
- (NSUInteger) firstIndexOfBit: (AQBit) bit;
/**
Find the index of the most-significant bit containing a specified value.
@param bit The bit value for which to search.
@return The index of the most-significant bit with the given value.
*/
- (NSUInteger) lastIndexOfBit: (AQBit) bit;
/**
Obtain a 32-bit scalar value representing a range of bits within the field.
@param range The range from which to copy the bits.
@exception NSRangeException Thrown if the _range_ parameter specifies a length greater than 4.
@return A 32-bit value representing the bits in the given _range_.
*/
- (UInt32) scalarBitsFromRange: (NSRange) range;
/**
Obtain a 64-bit scalar value representing a range of bits within the field.
@param range The range from which to copy the bits.
@exception NSRangeException Thrown if the _range_ parameter specifies a length greater than 8.
@return A 64-bit value representing the bits in the given _range_.
*/
- (UInt64) scalarBitsFrom64BitRange: (NSRange) range;
/// @name Toggling Bits
/**
Toggle the value of a particular bit.
@param index The index of the bit whose value to toggle.
*/
- (void) flipBitAtIndex: (NSUInteger) index;
/**
Toggle all bits in a given range.
@param range The range of bits to toggle.
*/
- (void) flipBitsInRange: (NSRange) range;
/// @name Setting Bits
/**
Set the value of a specific bit.
@param bit The value to set.
@param index The index of the bit to set.
*/
- (void) setBit: (AQBit) bit atIndex: (NSUInteger) index;
/**
Set the value of all bits in a range.
@param range The range of bits to modify.
@param bit The value to set.
*/
- (void) setBitsInRange: (NSRange) range usingBit: (AQBit) bit;
/**
Set the bits in the least-significant four words to those in a 32-bit quantity.
@param value The value whose bits to copy.
*/
- (void) setBitsFrom32BitValue: (UInt32) value;
/**
Set the bits in the least-significant eight words to those in a 64-bit quantity.
@param value The value whose bits to copy.
*/
- (void) setBitsFrom64BitValue: (UInt64) value;
/**
Set the bits in the given range to those in a 32-bit quantity.
@param value The value whose bits to copy.
@param range The range of bits to modify.
@exception NSInvalidArgumentException Thrown if the supplied range is greater than 32 bits in length.
*/
- (void) setBitsInRange: (NSRange) range from32BitValue: (UInt32) value;
/**
Set the bits in the given range to those in a 64-bit quantity.
@param value The value whose bits to copy.
@param range The range of bits to modify.
@exception NSInvalidArgumentException Thrown if the supplied range is greater than 64 bits in length.
*/
- (void) setBitsInRange: (NSRange) range from64BitValue: (UInt64) value;
/**
Copy all 1 bits from another bitfield.
@param bitfield The bitfield with which to merge the receiver.
*/
- (void) unionWithBitfield: (AQBitfield *) bitfield;
/**
Fills the entire bitfield (from `0` to `NSNotFound-1`) with a given value.
@param bit The value to use.
*/
- (void) setAllBits: (AQBit) bit;
/// @name Matching bit values
/**
Look for a match within the bitfield to an integer-sized value.
@param range The range of bits to compare. Must be `<= sizeof(NSUInteger)`. Compares least-significant bits of _bits_.
@param bits The value to compare against.
@return `YES` if a match is found, `NO` otherwise.
*/
- (BOOL) bitsInRange: (NSRange) range matchBits: (NSUInteger) bits;
/**
Look for a match within a sub-range of the bitfield.
@param range The range of bits to compare.
@param bitfield A zero-based bitfield corresponding to the bits within _range_ to compare.
@return `YES` if a match is found, `NO` otherwise.
*/
- (BOOL) bitsInRange: (NSRange) range equalToBitfield: (AQBitfield *) bitfield;
/**
Look for a match within the bitfield to an integer-sized value according to a mask.
@param range The range of bits to compare. Must be `<= sizeof(NSUInteger)`. Compares least-significant bits of _bits_.
@param mask A mask to determine which bits in the bitfield's sub-range to actually compare.
@param bits The value to compare against.
@return `YES` if a match is found, `NO` otherwise.
*/
- (BOOL) bitsInRange: (NSRange) range maskedWith: (NSUInteger) mask matchBits: (NSUInteger) bits;
/**
Look for a match within a sub-range of the bitfield according to a mask.
@param range The range of bits to compare.
@param mask A mask to determine which bits in the bitfield's sub-range to actually compare.
@param bitfield A zero-based bitfield corresponding to the bits within \a range to compare.
@return `YES` if a match is found, `NO` otherwise.
*/
- (BOOL) bitsInRange: (NSRange) range maskedWith: (AQBitfield *) mask equalToBitfield: (AQBitfield *) bitfield;
/// Bitwise Operations
/**
Shift all bits in the field to the left.
@param bits The number of places to shift.
*/
- (void) shiftBitsLeftBy: (NSUInteger) bits;
/**
Shift all bits in the field to the right.
@param bits The number of places to shift.
*/
- (void) shiftBitsRightBy: (NSUInteger) bits;
/**
Mask a bitfield using a bitwise AND operation.
@param mask The mask to apply to the bitfield's current state.
*/
- (void) maskWithBits: (AQBitfield *) mask;
/**
Obtain a copy of the receiver, masked with the given bits.
@param mask The mask to apply to the bitfield's current state.
*/
- (AQBitfield *) bitfieldUsingMask: (AQBitfield *) mask;
/**
Obtain a bitfield matching the receiver with all bits shifted to the left.
@param bits The number of places to shift.
@return A new bitfield instance.
*/
- (AQBitfield *) bitfieldFromLeftShiftingBy: (NSUInteger) bits;
/**
Obtain a bitfield matching the receiver with all bits shifted to the roght.
@param bits The number of places to shift.
@return A new bitfield instance.
*/
- (AQBitfield *) bitfieldFromRightShiftingBy: (NSUInteger) bits;
@end
/**
Convenience methods to build AQBitfields directly from NSIndexSets.
*/
@interface NSIndexSet (AQBitfieldCreation)
/**
Create an AQBitfield using the contents of the receiver.
*/
- (AQBitfield *) bitfieldRepresentation;
@end