00001
00002
00003 #import <HexFiend/HFTypes.h>
00004 #import <libkern/OSAtomic.h>
00005
00006 #define HFZeroRange (HFRange){0, 0}
00007
00011 static inline HFRange HFRangeMake(unsigned long long loc, unsigned long long len) {
00012 return (HFRange){loc, len};
00013 }
00014
00018 static inline BOOL HFLocationInRange(unsigned long long location, HFRange range) {
00019 return location >= range.location && location - range.location < range.length;
00020 }
00021
00025 static inline NSString* HFRangeToString(HFRange range) {
00026 return [NSString stringWithFormat:@"{%llu, %llu}", range.location, range.length];
00027 }
00028
00032 static inline NSString* HFFPRangeToString(HFFPRange range) {
00033 return [NSString stringWithFormat:@"{%Lf, %Lf}", range.location, range.length];
00034 }
00035
00039 static inline BOOL HFRangeEqualsRange(HFRange a, HFRange b) {
00040 return a.location == b.location && a.length == b.length;
00041 }
00042
00046 static inline BOOL HFSumDoesNotOverflow(unsigned long long a, unsigned long long b) {
00047 return a + b >= a;
00048 }
00049
00053 static inline BOOL HFProductDoesNotOverflow(unsigned long long a, unsigned long long b) {
00054 if (b == 0) return YES;
00055 unsigned long long result = a * b;
00056 return result / b == a;
00057 }
00058
00062 static inline NSUInteger HFProductInt(NSUInteger a, NSUInteger b) {
00063 NSUInteger result = a * b;
00064 assert(a == 0 || result / a == b);
00065 return result;
00066 }
00067
00071 static inline NSUInteger HFSumInt(NSUInteger a, NSUInteger b) {
00072 assert(a + b >= a);
00073 return a + b;
00074 }
00075
00079 static inline NSUInteger HFSumIntSaturate(NSUInteger a, NSUInteger b) {
00080 NSUInteger result = a + b;
00081 return (result < a) ? NSUIntegerMax : result;
00082 }
00083
00087 static inline unsigned long long HFSumULLSaturate(unsigned long long a, unsigned long long b) {
00088 unsigned long long result = a + b;
00089 return (result < a) ? ULLONG_MAX : result;
00090 }
00091
00095 static inline unsigned long long HFProductULL(unsigned long long a, unsigned long long b) {
00096 unsigned long long result = a * b;
00097 assert(HFProductDoesNotOverflow(a, b));
00098 return result;
00099 }
00100
00104 static inline unsigned long long HFSum(unsigned long long a, unsigned long long b) {
00105 assert(HFSumDoesNotOverflow(a, b));
00106 return a + b;
00107 }
00108
00112 static inline unsigned long long HFSubtract(unsigned long long a, unsigned long long b) {
00113 assert(a >= b);
00114 return a - b;
00115 }
00116
00120 static inline unsigned long long HFRoundUpToMultiple(unsigned long long a, unsigned long long b) {
00121
00122 unsigned long long remainder = a % b;
00123 if (remainder == 0) return a;
00124 else return HFSum(a, b - remainder);
00125 }
00126
00130 static inline NSUInteger HFRoundUpToMultipleInt(NSUInteger a, NSUInteger b) {
00131
00132 NSUInteger remainder = a % b;
00133 if (remainder == 0) return a;
00134 else return (NSUInteger)HFSum(a, b - remainder);
00135 }
00136
00140 static inline NSUInteger HFLeastCommonMultiple(NSUInteger a, NSUInteger b) {
00141 assert(a > 0);
00142 assert(b > 0);
00143
00144
00145 NSUInteger t, u = a, v = b;
00146 while (v > 0) {
00147 t = v;
00148 v = u % v;
00149 u = t;
00150 }
00151
00152
00153 return HFProductInt(a/u, b);
00154 }
00155
00156
00160 static inline unsigned long long HFRoundUpToNextMultipleSaturate(unsigned long long a, unsigned long long b) {
00161 assert(b > 0);
00162 unsigned long long result = a + (b - a % b);
00163 if (result < a) result = ULLONG_MAX;
00164 return result;
00165 }
00166
00168 static inline unsigned long long HFMaxRange(HFRange a) {
00169 assert(HFSumDoesNotOverflow(a.location, a.length));
00170 return a.location + a.length;
00171 }
00172
00174 static inline BOOL HFRangeIsSubrangeOfRange(HFRange needle, HFRange haystack) {
00175
00176 if (needle.location < haystack.location || needle.length > haystack.length) return NO;
00177
00178
00179 return haystack.length - needle.length >= needle.location - haystack.location;
00180 }
00181
00183 static inline void HFRangeSplitAboutSubrange(HFRange range, HFRange subrange, HFRange *outPrefix, HFRange *outSuffix) {
00184
00185 assert(HFRangeIsSubrangeOfRange(subrange, range));
00186 outPrefix->location = range.location;
00187 outPrefix->length = HFSubtract(subrange.location, range.location);
00188 outSuffix->location = HFMaxRange(subrange);
00189 outSuffix->length = HFMaxRange(range) - outSuffix->location;
00190 }
00191
00193 static inline BOOL HFIntersectsRange(HFRange a, HFRange b) {
00194
00195 if (a.length == 0 || b.length == 0) return NO;
00196
00197
00198
00199 BOOL clause1 = (a.location >= b.location && a.location - b.location >= b.length);
00200 BOOL clause2 = (b.location >= a.location && b.location - a.location >= a.length);
00201 return ! (clause1 || clause2);
00202 }
00203
00205 static inline HFRange HFUnionRange(HFRange a, HFRange b) {
00206 assert(HFIntersectsRange(a, b) || HFMaxRange(a) == b.location || HFMaxRange(b) == a.location);
00207 HFRange result;
00208 result.location = MIN(a.location, b.location);
00209 assert(HFSumDoesNotOverflow(a.location, a.length));
00210 assert(HFSumDoesNotOverflow(b.location, b.length));
00211 result.length = MAX(a.location + a.length, b.location + b.length) - result.location;
00212 return result;
00213 }
00214
00215
00217 static inline BOOL HFSumIsLargerThanSum(unsigned long long a, unsigned long long b, unsigned long long c, unsigned long long d) {
00218 #if 1
00219
00220 unsigned int rem1 = (unsigned)(a%2 + b%2);
00221 unsigned int rem2 = (unsigned)(c%2 + d%2);
00222 unsigned long long sum1 = a/2 + b/2 + rem1/2;
00223 unsigned long long sum2 = c/2 + d/2 + rem2/2;
00224 if (sum1 > sum2) return YES;
00225 else if (sum1 < sum2) return NO;
00226 else {
00227
00228 if (rem1%2 > rem2%2) return YES;
00229 else return NO;
00230 }
00231 #else
00232
00233 unsigned long long xor1 = a^b;
00234 unsigned long long xor2 = c^d;
00235 unsigned long long avg1 = (a&b)+(xor1/2);
00236 unsigned long long avg2 = (c&d)+(xor2/2);
00237 unsigned s1l = avg1 > avg2;
00238 unsigned eq = (avg1 == avg2);
00239 return s1l | ((xor1 & ~xor2) & eq);
00240 #endif
00241 }
00242
00244 static inline unsigned long long HFAbsoluteDifference(unsigned long long a, unsigned long long b) {
00245 if (a > b) return a - b;
00246 else return b - a;
00247 }
00248
00250 static inline BOOL HFRangeExtendsPastRange(HFRange a, HFRange b) {
00251 return HFSumIsLargerThanSum(a.location, a.length, b.location, b.length);
00252 }
00253
00255 static inline HFRange HFIntersectionRange(HFRange range1, HFRange range2) {
00256 unsigned long long minend = HFRangeExtendsPastRange(range2, range1) ? range1.location + range1.length : range2.location + range2.length;
00257 if (range2.location <= range1.location && range1.location - range2.location < range2.length) {
00258 return HFRangeMake(range1.location, minend - range1.location);
00259 }
00260 else if (range1.location <= range2.location && range2.location - range1.location < range1.length) {
00261 return HFRangeMake(range2.location, minend - range2.location);
00262 }
00263 return HFRangeMake(0, 0);
00264 }
00265
00267 static inline CGFloat HFCeil(CGFloat a) {
00268 if (sizeof(a) == sizeof(float)) return (CGFloat)ceilf((float)a);
00269 else return (CGFloat)ceil((double)a);
00270 }
00271
00273 static inline CGFloat HFFloor(CGFloat a) {
00274 if (sizeof(a) == sizeof(float)) return (CGFloat)floorf((float)a);
00275 else return (CGFloat)floor((double)a);
00276 }
00277
00279 static inline CGFloat HFRound(CGFloat a) {
00280 if (sizeof(a) == sizeof(float)) return (CGFloat)roundf((float)a);
00281 else return (CGFloat)round((double)a);
00282 }
00283
00285 static inline CGFloat HFMin(CGFloat a, CGFloat b) {
00286 if (sizeof(a) == sizeof(float)) return (CGFloat)fminf((float)a, (float)b);
00287 else return (CGFloat)fmin((double)a, (double)b);
00288 }
00289
00291 static inline CGFloat HFMax(CGFloat a, CGFloat b) {
00292 if (sizeof(a) == sizeof(float)) return (CGFloat)fmaxf((float)a, (float)b);
00293 else return (CGFloat)fmax((double)a, (double)b);
00294 }
00295
00297 static inline BOOL HFFPRangeEqualsRange(HFFPRange a, HFFPRange b) {
00298 return a.location == b.location && a.length == b.length;
00299 }
00300
00302 static inline CGFloat HFCopysign(CGFloat a, CGFloat b) {
00303 #if __LP64__
00304 return copysign(a, b);
00305 #else
00306 return copysignf(a, b);
00307 #endif
00308 }
00309
00311 static inline NSUInteger HFAtomicIncrement(NSUInteger *ptr, BOOL barrier) {
00312 #if __LP64__
00313 return (barrier ? OSAtomicIncrement64Barrier : OSAtomicIncrement64)((volatile int64_t *)ptr);
00314 #else
00315 return (barrier ? OSAtomicIncrement32Barrier : OSAtomicIncrement32)((volatile int32_t *)ptr);
00316 #endif
00317 }
00318
00320 static inline NSUInteger HFAtomicDecrement(NSUInteger *ptr, BOOL barrier) {
00321 #if __LP64__
00322 return (barrier ? OSAtomicDecrement64Barrier : OSAtomicDecrement64)((volatile int64_t *)ptr);
00323 #else
00324 return (barrier ? OSAtomicDecrement32Barrier : OSAtomicDecrement32)((volatile int32_t *)ptr);
00325 #endif
00326 }
00327
00329 static inline unsigned long long HFFPToUL(long double val) {
00330 assert(val >= 0);
00331 assert(val <= ULLONG_MAX);
00332 unsigned long long result = (unsigned long long)val;
00333 assert((long double)result == val);
00334 return result;
00335 }
00336
00338 static inline long double HFULToFP(unsigned long long val) {
00339 long double result = (long double)val;
00340 assert(HFFPToUL(result) == val);
00341 return result;
00342 }
00343
00345 static inline NSString *HFDescribeAffineTransform(CGAffineTransform t) {
00346 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];
00347 }
00348
00350 static inline NSUInteger HFCountDigitsBase10(unsigned long long val) {
00351 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};
00352 NSUInteger low = 0, high = sizeof kValues / sizeof *kValues;
00353 while (high > low) {
00354 NSUInteger mid = (low + high)/2;
00355 if (val > kValues[mid]) {
00356 low = mid + 1;
00357 }
00358 else {
00359 high = mid;
00360 }
00361 }
00362 return MAX(1, low);
00363 }
00364
00366 static inline NSUInteger HFCountDigitsBase16(unsigned long long val) {
00367
00368 if (val == 0) return 1;
00369
00370
00371 NSUInteger leadingZeros = (NSUInteger)__builtin_clzll(val);
00372 NSUInteger logBase2 = (CHAR_BIT * sizeof val) - leadingZeros - 1;
00373 return 1 + logBase2/4;
00374 }
00375
00377 BOOL HFStringEncodingIsSupersetOfASCII(NSStringEncoding encoding);
00378
00380 uint8_t HFStringEncodingCharacterLength(NSStringEncoding encoding);
00381
00383 static inline unsigned long ll2l(unsigned long long val) { assert(val <= ULONG_MAX); return (unsigned long)val; }
00384
00386 static inline CGFloat ld2f(long double val) {
00387 #if ! NDEBUG
00388 if (isfinite(val)) {
00389 assert(val <= CGFLOAT_MAX);
00390 assert(val >= -CGFLOAT_MAX);
00391 if ((val > 0 && val < CGFLOAT_MIN) || (val < 0 && val > -CGFLOAT_MIN)) {
00392 NSLog(@"Warning - conversion of long double %Lf to CGFloat will result in the non-normal CGFloat %f", val, (CGFloat)val);
00393 }
00394 }
00395 #endif
00396 return (CGFloat)val;
00397 }
00398
00400 static inline unsigned long long HFDivideULLRoundingUp(unsigned long long a, unsigned long long b) {
00401 if (a == 0) return 0;
00402 else return ((a - 1) / b) + 1;
00403 }
00404
00406 static inline NSUInteger HFDivideULRoundingUp(NSUInteger a, NSUInteger b) {
00407 if (a == 0) return 0;
00408 else return ((a - 1) / b) + 1;
00409 }
00410
00412 void HFDrawShadow(CGContextRef context, NSRect rect, CGFloat size, NSRectEdge rectEdge, BOOL active, NSRect clip);
00413
00415 void HFRegisterViewForWindowAppearanceChanges(NSView *view, SEL notificationSEL, BOOL appToo);
00416
00418 void HFUnregisterViewForWindowAppearanceChanges(NSView *view, BOOL appToo);
00419
00421 NSString *HFDescribeByteCount(unsigned long long count);
00422
00426 @interface HFRangeWrapper : NSObject {
00427 @public
00428 HFRange range;
00429 }
00430
00432 - (HFRange)HFRange;
00433
00435 + (HFRangeWrapper *)withRange:(HFRange)range;
00436
00438 + (NSArray *)withRanges:(const HFRange *)ranges count:(NSUInteger)count;
00439
00441 + (void)getRanges:(HFRange *)ranges fromArray:(NSArray *)array;
00442
00444 + (NSArray *)organizeAndMergeRanges:(NSArray *)inputRanges;
00445
00446 @end
00447
00448 #ifndef NDEBUG
00449 void HFStartTiming(const char *name);
00450 void HFStopTiming(void);
00451 #endif