SameBoy | Accurate GB/GBC emulator |
| download: https://git.y1.nz/archives/sameboy.tar.gz | |
| README | Files | Log | Refs | LICENSE |
HexFiend/HFFunctions.h
1 /* Functions and convenience methods for working with HFTypes */
2
3 #import <HexFiend/HFTypes.h>
4 #import <libkern/OSAtomic.h>
5
6 #define HFDEFAULT_FONT (@"Monaco")
7 #define HFDEFAULT_FONTSIZE ((CGFloat)11.)
8
9 #define HFZeroRange (HFRange){0, 0}
10
11 /*!
12 Makes an HFRange. An HFRange is like an NSRange except it uses unsigned long longs.
13 */
14 static inline HFRange HFRangeMake(unsigned long long loc, unsigned long long len) {
15 return (HFRange){loc, len};
16 }
17
18 /*!
19 Returns true if a given location is within a given HFRange. If the location is at the end of the range (range.location + range.length) this returns NO.
20 */
21 static inline BOOL HFLocationInRange(unsigned long long location, HFRange range) {
22 return location >= range.location && location - range.location < range.length;
23 }
24
25 /*!
26 Like NSRangeToString but for HFRanges
27 */
28 static inline NSString* HFRangeToString(HFRange range) {
29 return [NSString stringWithFormat:@"{%llu, %llu}", range.location, range.length];
30 }
31
32 /*!
33 Converts a given HFFPRange to a string.
34 */
35 static inline NSString* HFFPRangeToString(HFFPRange range) {
36 return [NSString stringWithFormat:@"{%Lf, %Lf}", range.location, range.length];
37 }
38
39 /*!
40 Returns true if two HFRanges are equal.
41 */
42 static inline BOOL HFRangeEqualsRange(HFRange a, HFRange b) {
43 return a.location == b.location && a.length == b.length;
44 }
45
46 /*!
47 Returns true if a + b does not overflow an unsigned long long.
48 */
49 static inline BOOL HFSumDoesNotOverflow(unsigned long long a, unsigned long long b) {
50 return a + b >= a;
51 }
52
53 /*!
54 Returns true if a * b does not overflow an unsigned long long.
55 */
56 static inline BOOL HFProductDoesNotOverflow(unsigned long long a, unsigned long long b) {
57 if (b == 0) return YES;
58 unsigned long long result = a * b;
59 return result / b == a;
60 }
61
62 /*!
63 Returns a * b as an NSUInteger. This asserts on overflow, unless NDEBUG is defined.
64 */
65 static inline NSUInteger HFProductInt(NSUInteger a, NSUInteger b) {
66 NSUInteger result = a * b;
67 assert(a == 0 || result / a == b); //detect overflow
68 return result;
69 }
70
71 /*!
72 Returns a + b as an NSUInteger. This asserts on overflow unless NDEBUG is defined.
73 */
74 static inline NSUInteger HFSumInt(NSUInteger a, NSUInteger b) {
75 assert(a + b >= a);
76 return a + b;
77 }
78
79 /*!
80 Returns a + b as an NSUInteger, saturating at NSUIntegerMax
81 */
82 static inline NSUInteger HFSumIntSaturate(NSUInteger a, NSUInteger b) {
83 NSUInteger result = a + b;
84 return (result < a) ? NSUIntegerMax : result;
85 }
86
87 /*!
88 Returns a + b as an unsigned long long, saturating at ULLONG_MAX
89 */
90 static inline unsigned long long HFSumULLSaturate(unsigned long long a, unsigned long long b) {
91 unsigned long long result = a + b;
92 return (result < a) ? ULLONG_MAX : result;
93 }
94
95 /*!
96 Returns a * b as an unsigned long long. This asserts on overflow, unless NDEBUG is defined.
97 */
98 static inline unsigned long long HFProductULL(unsigned long long a, unsigned long long b) {
99 unsigned long long result = a * b;
100 assert(HFProductDoesNotOverflow(a, b)); //detect overflow
101 return result;
102 }
103
104 /*!
105 Returns a + b as an unsigned long long. This asserts on overflow, unless NDEBUG is defined.
106 */
107 static inline unsigned long long HFSum(unsigned long long a, unsigned long long b) {
108 assert(HFSumDoesNotOverflow(a, b));
109 return a + b;
110 }
111
112 /*!
113 Returns a + b as an unsigned long long. This asserts on overflow, unless NDEBUG is defined.
114 */
115 static inline unsigned long long HFMaxULL(unsigned long long a, unsigned long long b) {
116 return a < b ? b : a;
117 }
118
119 /*!
120 Returns a - b as an unsigned long long. This asserts on underflow (if b > a), unless NDEBUG is defined.
121 */
122 static inline unsigned long long HFSubtract(unsigned long long a, unsigned long long b) {
123 assert(a >= b);
124 return a - b;
125 }
126
127 /*!
128 Returns the smallest multiple of B that is equal to or larger than A, and asserts on overflow.
129 */
130 static inline unsigned long long HFRoundUpToMultiple(unsigned long long a, unsigned long long b) {
131 // The usual approach of ((a + (b - 1)) / b) * b doesn't handle overflow correctly
132 unsigned long long remainder = a % b;
133 if (remainder == 0) return a;
134 else return HFSum(a, b - remainder);
135 }
136
137 /*!
138 Returns the smallest multiple of B that is equal to or larger than A, and asserts on overflow.
139 */
140 static inline NSUInteger HFRoundUpToMultipleInt(NSUInteger a, NSUInteger b) {
141 // The usual approach of ((a + (b - 1)) / b) * b doesn't handle overflow correctly
142 NSUInteger remainder = a % b;
143 if (remainder == 0) return a;
144 else return (NSUInteger)HFSum(a, b - remainder);
145 }
146
147 /*!
148 Returns the least common multiple of A and B, and asserts on overflow or if A or B is zero.
149 */
150 static inline NSUInteger HFLeastCommonMultiple(NSUInteger a, NSUInteger b) {
151 assert(a > 0);
152 assert(b > 0);
153
154 /* Compute GCD. It ends up in U. */
155 NSUInteger t, u = a, v = b;
156 while (v > 0) {
157 t = v;
158 v = u % v;
159 u = t;
160 }
161
162 /* Return the product divided by the GCD, in an overflow safe manner */
163 return HFProductInt(a/u, b);
164 }
165
166
167 /*!
168 Returns the smallest multiple of B strictly larger than A, or ULLONG_MAX if it would overflow
169 */
170 static inline unsigned long long HFRoundUpToNextMultipleSaturate(unsigned long long a, unsigned long long b) {
171 assert(b > 0);
172 unsigned long long result = a + (b - a % b);
173 if (result < a) result = ULLONG_MAX; //the saturation...on overflow go to the max
174 return result;
175 }
176
177 /*! Like NSMaxRange, but for an HFRange. */
178 static inline unsigned long long HFMaxRange(HFRange a) {
179 assert(HFSumDoesNotOverflow(a.location, a.length));
180 return a.location + a.length;
181 }
182
183 /*! Returns YES if needle is fully contained within haystack. Equal ranges are always considered to be subranges of each other (even if they are empty). Furthermore, a zero length needle at the end of haystack is considered a subrange - for example, {6, 0} is a subrange of {3, 3}. */
184 static inline BOOL HFRangeIsSubrangeOfRange(HFRange needle, HFRange haystack) {
185 // If needle starts before haystack, or if needle is longer than haystack, it is not a subrange of haystack
186 if (needle.location < haystack.location || needle.length > haystack.length) return NO;
187
188 // Their difference in lengths determines the maximum difference in their start locations. We know that these expressions cannot overflow because of the above checks.
189 return haystack.length - needle.length >= needle.location - haystack.location;
190 }
191
192 /*! Splits a range about a subrange, returning by reference the prefix and suffix (which may have length zero). */
193 static inline void HFRangeSplitAboutSubrange(HFRange range, HFRange subrange, HFRange *outPrefix, HFRange *outSuffix) {
194 // Requires it to be a subrange
195 assert(HFRangeIsSubrangeOfRange(subrange, range));
196 outPrefix->location = range.location;
197 outPrefix->length = HFSubtract(subrange.location, range.location);
198 outSuffix->location = HFMaxRange(subrange);
199 outSuffix->length = HFMaxRange(range) - outSuffix->location;
200 }
201
202 /*! Returns YES if the given ranges intersect. Two ranges are considered to intersect if they share at least one index in common. Thus, zero-length ranges do not intersect anything. */
203 static inline BOOL HFIntersectsRange(HFRange a, HFRange b) {
204 // Ranges are said to intersect if they share at least one value. Therefore, zero length ranges never intersect anything.
205 if (a.length == 0 || b.length == 0) return NO;
206
207 // rearrange (a.location < b.location + b.length && b.location < a.location + a.length) to not overflow
208 // = ! (a.location >= b.location + b.length || b.location >= a.location + a.length)
209 BOOL clause1 = (a.location >= b.location && a.location - b.location >= b.length);
210 BOOL clause2 = (b.location >= a.location && b.location - a.location >= a.length);
211 return ! (clause1 || clause2);
212 }
213
214 /*! Returns YES if the given ranges intersect. Two ranges are considered to intersect if any fraction overlaps; zero-length ranges do not intersect anything. */
215 static inline BOOL HFFPIntersectsRange(HFFPRange a, HFFPRange b) {
216 // Ranges are said to intersect if they share at least one value. Therefore, zero length ranges never intersect anything.
217 if (a.length == 0 || b.length == 0) return NO;
218
219 if (a.location <= b.location && a.location + a.length >= b.location) return YES;
220 if (b.location <= a.location && b.location + b.length >= a.location) return YES;
221 return NO;
222 }
223
224 /*! Returns a range containing the union of the given ranges. These ranges must either intersect or be adjacent: there cannot be any "holes" between them. */
225 static inline HFRange HFUnionRange(HFRange a, HFRange b) {
226 assert(HFIntersectsRange(a, b) || HFMaxRange(a) == b.location || HFMaxRange(b) == a.location);
227 HFRange result;
228 result.location = MIN(a.location, b.location);
229 assert(HFSumDoesNotOverflow(a.location, a.length));
230 assert(HFSumDoesNotOverflow(b.location, b.length));
231 result.length = MAX(a.location + a.length, b.location + b.length) - result.location;
232 return result;
233 }
234
235
236 /*! Returns whether a+b > c+d, as if there were no overflow (so ULLONG_MAX + 1 > 10 + 20) */
237 static inline BOOL HFSumIsLargerThanSum(unsigned long long a, unsigned long long b, unsigned long long c, unsigned long long d) {
238 #if 1
239 // Theory: compare a/2 + b/2 to c/2 + d/2, and if they're equal, compare a%2 + b%2 to c%2 + d%2. We may get into trouble if a and b are both even and c and d are both odd: e.g. a = 2, b = 2, c = 1, d = 3. We would compare 1 + 1 vs 0 + 1, and therefore that 2 + 2 > 1 + 3. To address this, if both remainders are 1, we add this to the sum. We know this cannot overflow because ULLONG_MAX is odd, so (ULLONG_MAX/2) + (ULLONG_MAX/2) + 1 does not overflow.
240 unsigned int rem1 = (unsigned)(a%2 + b%2);
241 unsigned int rem2 = (unsigned)(c%2 + d%2);
242 unsigned long long sum1 = a/2 + b/2 + rem1/2;
243 unsigned long long sum2 = c/2 + d/2 + rem2/2;
244 if (sum1 > sum2) return YES;
245 else if (sum1 < sum2) return NO;
246 else {
247 // sum1 == sum2, so compare the remainders. But we have already added in the remainder / 2, so compare the remainders mod 2.
248 if (rem1%2 > rem2%2) return YES;
249 else return NO;
250 }
251 #else
252 /* Faster version, but not thoroughly tested yet. */
253 unsigned long long xor1 = a^b;
254 unsigned long long xor2 = c^d;
255 unsigned long long avg1 = (a&b)+(xor1/2);
256 unsigned long long avg2 = (c&d)+(xor2/2);
257 unsigned s1l = avg1 > avg2;
258 unsigned eq = (avg1 == avg2);
259 return s1l | ((xor1 & ~xor2) & eq);
260 #endif
261 }
262
263 /*! Returns the absolute value of a - b. */
264 static inline unsigned long long HFAbsoluteDifference(unsigned long long a, unsigned long long b) {
265 if (a > b) return a - b;
266 else return b - a;
267 }
268
269 /*! Returns true if the end of A is larger than the end of B. */
270 static inline BOOL HFRangeExtendsPastRange(HFRange a, HFRange b) {
271 return HFSumIsLargerThanSum(a.location, a.length, b.location, b.length);
272 }
273
274 /*! Returns a range containing all indexes in common betwen the two ranges. If there are no indexes in common, returns {0, 0}. */
275 static inline HFRange HFIntersectionRange(HFRange range1, HFRange range2) {
276 unsigned long long minend = HFRangeExtendsPastRange(range2, range1) ? range1.location + range1.length : range2.location + range2.length;
277 if (range2.location <= range1.location && range1.location - range2.location < range2.length) {
278 return HFRangeMake(range1.location, minend - range1.location);
279 }
280 else if (range1.location <= range2.location && range2.location - range1.location < range1.length) {
281 return HFRangeMake(range2.location, minend - range2.location);
282 }
283 return HFRangeMake(0, 0);
284 }
285
286 /*! ceil() for a CGFloat, for compatibility with OSes that do not have the CG versions. */
287 static inline CGFloat HFCeil(CGFloat a) {
288 if (sizeof(a) == sizeof(float)) return (CGFloat)ceilf((float)a);
289 else return (CGFloat)ceil((double)a);
290 }
291
292 /*! floor() for a CGFloat, for compatibility with OSes that do not have the CG versions. */
293 static inline CGFloat HFFloor(CGFloat a) {
294 if (sizeof(a) == sizeof(float)) return (CGFloat)floorf((float)a);
295 else return (CGFloat)floor((double)a);
296 }
297
298 /*! round() for a CGFloat, for compatibility with OSes that do not have the CG versions. */
299 static inline CGFloat HFRound(CGFloat a) {
300 if (sizeof(a) == sizeof(float)) return (CGFloat)roundf((float)a);
301 else return (CGFloat)round((double)a);
302 }
303
304 /*! fmin() for a CGFloat, for compatibility with OSes that do not have the CG versions. */
305 static inline CGFloat HFMin(CGFloat a, CGFloat b) {
306 if (sizeof(a) == sizeof(float)) return (CGFloat)fminf((float)a, (float)b);
307 else return (CGFloat)fmin((double)a, (double)b);
308 }
309
310 /*! fmax() for a CGFloat, for compatibility with OSes that do not have the CG versions. */
311 static inline CGFloat HFMax(CGFloat a, CGFloat b) {
312 if (sizeof(a) == sizeof(float)) return (CGFloat)fmaxf((float)a, (float)b);
313 else return (CGFloat)fmax((double)a, (double)b);
314 }
315
316 /*! Returns true if the given HFFPRanges are equal. */
317 static inline BOOL HFFPRangeEqualsRange(HFFPRange a, HFFPRange b) {
318 return a.location == b.location && a.length == b.length;
319 }
320
321 /*! copysign() for a CGFloat */
322 static inline CGFloat HFCopysign(CGFloat a, CGFloat b) {
323 #if CGFLOAT_IS_DOUBLE
324 return copysign(a, b);
325 #else
326 return copysignf(a, b);
327 #endif
328 }
329
330 /*! Atomically increments an NSUInteger, returning the new value. Optionally invokes a memory barrier. */
331 static inline NSUInteger HFAtomicIncrement(volatile NSUInteger *ptr, BOOL barrier) {
332 return _Generic(ptr,
333 volatile unsigned *: (barrier ? OSAtomicIncrement32Barrier : OSAtomicIncrement32)((volatile int32_t *)ptr),
334 #if ULONG_MAX == UINT32_MAX
335 volatile unsigned long *: (barrier ? OSAtomicIncrement32Barrier : OSAtomicIncrement32)((volatile int32_t *)ptr),
336 #else
337 volatile unsigned long *: (barrier ? OSAtomicIncrement64Barrier : OSAtomicIncrement64)((volatile int64_t *)ptr),
338 #endif
339 volatile unsigned long long *: (barrier ? OSAtomicIncrement64Barrier : OSAtomicIncrement64)((volatile int64_t *)ptr));
340 }
341
342 /*! Atomically decrements an NSUInteger, returning the new value. Optionally invokes a memory barrier. */
343 static inline NSUInteger HFAtomicDecrement(volatile NSUInteger *ptr, BOOL barrier) {
344 return _Generic(ptr,
345 volatile unsigned *: (barrier ? OSAtomicDecrement32Barrier : OSAtomicDecrement32)((volatile int32_t *)ptr),
346 #if ULONG_MAX == UINT32_MAX
347 volatile unsigned long *: (barrier ? OSAtomicDecrement32Barrier : OSAtomicDecrement32)((volatile int32_t *)ptr),
348 #else
349 volatile unsigned long *: (barrier ? OSAtomicDecrement64Barrier : OSAtomicDecrement64)((volatile int64_t *)ptr),
350 #endif
351 volatile unsigned long long *: (barrier ? OSAtomicDecrement64Barrier : OSAtomicDecrement64)((volatile int64_t *)ptr));
352 }
353
354 /*! Converts a long double to unsigned long long. Assumes that val is already an integer - use floorl or ceill */
355 static inline unsigned long long HFFPToUL(long double val) {
356 assert(val >= 0);
357 assert(val <= ULLONG_MAX);
358 unsigned long long result = (unsigned long long)val;
359 assert((long double)result == val);
360 return result;
361 }
362
363 /*! Converts an unsigned long long to a long double. */
364 static inline long double HFULToFP(unsigned long long val) {
365 long double result = (long double)val;
366 assert(HFFPToUL(result) == val);
367 return result;
368 }
369
370 /*! Convenience to return information about a CGAffineTransform for logging. */
371 static inline NSString *HFDescribeAffineTransform(CGAffineTransform t) {
372 return [NSString stringWithFormat:@"%f %f 0\n%f %f 0\n%f %f 1", t.a, t.b, t.c, t.d, t.tx, t.ty];
373 }
374
375 /*! Returns 1 + floor(log base 10 of val). If val is 0, returns 1. */
376 static inline NSUInteger HFCountDigitsBase10(unsigned long long val) {
377 const unsigned long long kValues[] = {0ULL, 9ULL, 99ULL, 999ULL, 9999ULL, 99999ULL, 999999ULL, 9999999ULL, 99999999ULL, 999999999ULL, 9999999999ULL, 99999999999ULL, 999999999999ULL, 9999999999999ULL, 99999999999999ULL, 999999999999999ULL, 9999999999999999ULL, 99999999999999999ULL, 999999999999999999ULL, 9999999999999999999ULL};
378 NSUInteger low = 0, high = sizeof kValues / sizeof *kValues;
379 while (high > low) {
380 NSUInteger mid = (low + high)/2; //low + high cannot overflow
381 if (val > kValues[mid]) {
382 low = mid + 1;
383 }
384 else {
385 high = mid;
386 }
387 }
388 return MAX(1u, low);
389 }
390
391 /*! Returns 1 + floor(log base 16 of val). If val is 0, returns 1. This works by computing the log base 2 based on the number of leading zeros, and then dividing by 4. */
392 static inline NSUInteger HFCountDigitsBase16(unsigned long long val) {
393 /* __builtin_clzll doesn't like being passed 0 */
394 if (val == 0) return 1;
395
396 /* Compute the log base 2 */
397 NSUInteger leadingZeros = (NSUInteger)__builtin_clzll(val);
398 NSUInteger logBase2 = (CHAR_BIT * sizeof val) - leadingZeros - 1;
399 return 1 + logBase2/4;
400 }
401
402 /*! Returns YES if the given string encoding is a superset of ASCII. */
403 BOOL HFStringEncodingIsSupersetOfASCII(NSStringEncoding encoding);
404
405 /*! Returns the "granularity" of an encoding, in bytes. ASCII is 1, UTF-16 is 2, etc. Variable width encodings return the smallest (e.g. Shift-JIS returns 1). */
406 uint8_t HFStringEncodingCharacterLength(NSStringEncoding encoding);
407
408 /*! Converts an unsigned long long to NSUInteger. The unsigned long long should be no more than ULONG_MAX. */
409 static inline NSUInteger ll2l(unsigned long long val) { assert(val <= ULONG_MAX); return (unsigned long)val; }
410
411 /*! Converts an unsigned long long to uintptr_t. The unsigned long long should be no more than UINTPTR_MAX. */
412 static inline uintptr_t ll2p(unsigned long long val) { assert(val <= UINTPTR_MAX); return (uintptr_t)val; }
413
414 /*! Returns an unsigned long long, which must be no more than ULLONG_MAX, as an unsigned long. */
415 static inline CGFloat ld2f(long double val) {
416 #if ! NDEBUG
417 if (isfinite(val)) {
418 assert(val <= CGFLOAT_MAX);
419 assert(val >= -CGFLOAT_MAX);
420 if ((val > 0 && val < CGFLOAT_MIN) || (val < 0 && val > -CGFLOAT_MIN)) {
421 NSLog(@"Warning - conversion of long double %Lf to CGFloat will result in the non-normal CGFloat %f", val, (CGFloat)val);
422 }
423 }
424 #endif
425 return (CGFloat)val;
426 }
427
428 /*! Returns the quotient of a divided by b, rounding up, for unsigned long longs. Will not overflow. */
429 static inline unsigned long long HFDivideULLRoundingUp(unsigned long long a, unsigned long long b) {
430 if (a == 0) return 0;
431 else return ((a - 1) / b) + 1;
432 }
433
434 /*! Returns the quotient of a divided by b, rounding up, for NSUIntegers. Will not overflow. */
435 static inline NSUInteger HFDivideULRoundingUp(NSUInteger a, NSUInteger b) {
436 if (a == 0) return 0;
437 else return ((a - 1) / b) + 1;
438 }
439
440 /*! Draws a shadow. */
441 void HFDrawShadow(CGContextRef context, NSRect rect, CGFloat size, NSRectEdge rectEdge, BOOL active, NSRect clip);
442
443 /*! Registers a view to have the given notificationSEL invoked (taking the NSNotification object) when the window becomes or loses key. If appToo is YES, this also registers with NSApplication for Activate and Deactivate methods. */
444 void HFRegisterViewForWindowAppearanceChanges(NSView *view, SEL notificationSEL, BOOL appToo);
445
446 /*! Unregisters a view to have the given notificationSEL invoked when the window becomes or loses key. If appToo is YES, this also unregisters with NSApplication. */
447 void HFUnregisterViewForWindowAppearanceChanges(NSView *view, BOOL appToo);
448
449 /*! Returns a description of the given byte count (e.g. "24 kilobytes") */
450 NSString *HFDescribeByteCount(unsigned long long count);
451
452 /*! @brief An object wrapper for the HFRange type.
453
454 A simple class responsible for holding an immutable HFRange as an object. Methods that logically work on multiple HFRanges usually take or return arrays of HFRangeWrappers. */
455 @interface HFRangeWrapper : NSObject <NSCopying> {
456 @public
457 HFRange range;
458 }
459
460 /*! Returns the HFRange for this HFRangeWrapper. */
461 - (HFRange)HFRange;
462
463 /*! Creates an autoreleased HFRangeWrapper for this HFRange. */
464 + (HFRangeWrapper *)withRange:(HFRange)range;
465
466 /*! Creates an NSArray of HFRangeWrappers for this HFRange. */
467 + (NSArray *)withRanges:(const HFRange *)ranges count:(NSUInteger)count;
468
469 /*! Given an NSArray of HFRangeWrappers, get all of the HFRanges into a C array. */
470 + (void)getRanges:(HFRange *)ranges fromArray:(NSArray *)array;
471
472 /*! Given an array of HFRangeWrappers, returns a "cleaned up" array of equivalent ranges. This new array represents the same indexes, but overlapping ranges will have been merged, and the ranges will be sorted in ascending order. */
473 + (NSArray *)organizeAndMergeRanges:(NSArray *)inputRanges;
474
475 @end
476
477 /*! @brief A set of HFRanges. HFRangeSet takes the interpetation that all zero-length ranges are identical.
478
479 Essentially, a mutable array of ranges that is maintained to be sorted and minimized (i.e. merged with overlapping neighbors).
480
481 TODO: The HexFiend codebase currently uses arrays of HFRangeWrappers that have been run through organizeAndMergeRanges:, and not HFRangeSet. The advantage of HFRangeSet is that the sorting & merging is implied by the type, instead of just tacitly assumed. This should lead to less confusion and fewer extra applications of organizeAndMergeRanges.
482
483 TODO: HFRangeSet needs to be tested! I guarantee it has bugs! (Which doesn't matter right now because it's all dead code...)
484 */
485 @interface HFRangeSet : NSObject <NSCopying, NSSecureCoding, NSFastEnumeration> {
486 @private
487 CFMutableArrayRef array;
488 }
489
490 /*! Create a range set with just one range. */
491 + (HFRangeSet *)withRange:(HFRange)range;
492
493 /*! Create a range set with a C array of ranges. No prior sorting is necessary. */
494 + (HFRangeSet *)withRanges:(const HFRange *)ranges count:(NSUInteger)count;
495
496 /*! Create a range set with an array of HFRangeWrappers. No prior sorting is necessary. */
497 + (HFRangeSet *)withRangeWrappers:(NSArray *)ranges;
498
499 /*! Create a range set as a copy of another. */
500 + (HFRangeSet *)withRangeSet:(HFRangeSet *)rangeSet;
501
502 /*! Equivalent to HFRangeSet *x = [HFRangeSet withRange:range]; [x removeRange:rangeSet]; */
503 + (HFRangeSet *)complementOfRangeSet:(HFRangeSet *)rangeSet inRange:(HFRange)range;
504
505 - (void)addRange:(HFRange)range; /*!< Union with range */
506 - (void)removeRange:(HFRange)range; /*!< Subtract range */
507 - (void)clipToRange:(HFRange)range; /*!< Intersect with range */
508 - (void)toggleRange:(HFRange)range; /*!< Symmetric difference with range */
509
510 - (void)addRangeSet:(HFRangeSet *)rangeSet; /*!< Union with range set */
511 - (void)removeRangeSet:(HFRangeSet *)rangeSet; /*!< Subtract range set */
512 - (void)clipToRangeSet:(HFRangeSet *)rangeSet; /*!< Intersect with range set */
513 - (void)toggleRangeSet:(HFRangeSet *)rangeSet; /*!< Symmetric difference with range set */
514
515
516 - (BOOL)isEqualToRangeSet:(HFRangeSet *)rangeSet; /*!< Test if two range sets are equivalent. */
517 - (BOOL)isEmpty; /*!< Test if range set is empty. */
518
519 - (BOOL)containsAllRange:(HFRange)range; /*!< Check if the range set covers all of a range. Always true if 'range' is zero length. */
520 - (BOOL)overlapsAnyRange:(HFRange)range; /*!< Check if the range set covers any of a range. Never true if 'range' is zero length. */
521 - (BOOL)containsAllRangeSet:(HFRangeSet *)rangeSet; /*!< Check if this range is a superset of another. */
522 - (BOOL)overlapsAnyRangeSet:(HFRangeSet *)rangeSet; /*!< Check if this range has a nonempty intersection with another. */
523
524 - (HFRange)spanningRange; /*!< Return a single range that covers the entire range set */
525
526 - (void)assertIntegrity;
527
528 @end
529
530 #ifndef NDEBUG
531 void HFStartTiming(const char *name);
532 void HFStopTiming(void);
533 #endif
This webpage is intended to be an accessible preview of this repository. To get a fuller picture, clone it and use the git CLI.