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