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 unsigned long long HFProductULL(unsigned long long a, unsigned long long b) {
00080 unsigned long long result = a * b;
00081 assert(HFProductDoesNotOverflow(a, b));
00082 return result;
00083 }
00084
00088 static inline unsigned long long HFSum(unsigned long long a, unsigned long long b) {
00089 assert(HFSumDoesNotOverflow(a, b));
00090 return a + b;
00091 }
00092
00096 static inline unsigned long long HFSubtract(unsigned long long a, unsigned long long b) {
00097 assert(a >= b);
00098 return a - b;
00099 }
00100
00104 static inline unsigned long long HFRoundUpToNextMultiple(unsigned long long a, unsigned long long b) {
00105 assert(b > 0);
00106 return HFSum(a, b - a % b);
00107 }
00108
00110 static inline unsigned long long HFMaxRange(HFRange a) {
00111 assert(HFSumDoesNotOverflow(a.location, a.length));
00112 return a.location + a.length;
00113 }
00114
00116 static inline BOOL HFRangeIsSubrangeOfRange(HFRange needle, HFRange haystack) {
00117
00118 if (needle.location < haystack.location || needle.length > haystack.length) return NO;
00119
00120
00121 if (HFRangeEqualsRange(needle, haystack)) return YES;
00122
00123
00124
00125 if (needle.location - haystack.location > haystack.length) return NO;
00126
00127
00128 if (needle.location - haystack.location > haystack.length - needle.length) return NO;
00129
00130 return YES;
00131 }
00132
00134 static inline BOOL HFIntersectsRange(HFRange a, HFRange b) {
00135
00136 if (a.length == 0 || b.length == 0) return NO;
00137
00138
00139
00140 BOOL clause1 = (a.location >= b.location && a.location - b.location >= b.length);
00141 BOOL clause2 = (b.location >= a.location && b.location - a.location >= a.length);
00142 return ! (clause1 || clause2);
00143 }
00144
00146 static inline HFRange HFUnionRange(HFRange a, HFRange b) {
00147 assert(HFIntersectsRange(a, b) || HFMaxRange(a) == b.location || HFMaxRange(b) == a.location);
00148 HFRange result;
00149 result.location = MIN(a.location, b.location);
00150 assert(HFSumDoesNotOverflow(a.location, a.length));
00151 assert(HFSumDoesNotOverflow(b.location, b.length));
00152 result.length = MAX(a.location + a.length, b.location + b.length) - result.location;
00153 return result;
00154 }
00155
00156
00158 static inline BOOL HFSumIsLargerThanSum(unsigned long long a, unsigned long long b, unsigned long long c, unsigned long long d) {
00159
00160 unsigned long long sum1 = a/2 + b/2;
00161 unsigned long long sum2 = c/2 + d/2;
00162 if (sum1 > sum2) return YES;
00163 else if (sum1 < sum2) return NO;
00164 else {
00165
00166 unsigned int sum3 = (unsigned int)(a%2) + (unsigned int)(b%2);
00167 unsigned int sum4 = (unsigned int)(c%2) + (unsigned int)(d%2);
00168 if (sum3 > sum4) return YES;
00169 else return NO;
00170 }
00171 }
00172
00174 static inline unsigned long long HFAbsoluteDifference(unsigned long long a, unsigned long long b) {
00175 if (a > b) return a - b;
00176 else return b - a;
00177 }
00178
00180 static inline BOOL HFRangeExtendsPastRange(HFRange a, HFRange b) {
00181 return HFSumIsLargerThanSum(a.location, a.length, b.location, b.length);
00182 }
00183
00185 static inline HFRange HFIntersectionRange(HFRange range1, HFRange range2) {
00186 unsigned long long minend = HFRangeExtendsPastRange(range2, range1) ? range1.location + range1.length : range2.location + range2.length;
00187 if (range2.location <= range1.location && range1.location - range2.location < range2.length) {
00188 return HFRangeMake(range1.location, minend - range1.location);
00189 }
00190 else if (range1.location <= range2.location && range2.location - range1.location < range1.length) {
00191 return HFRangeMake(range2.location, minend - range2.location);
00192 }
00193 return HFRangeMake(0, 0);
00194 }
00195
00197 static inline CGFloat HFCeil(CGFloat a) {
00198 if (sizeof(a) == sizeof(float)) return (CGFloat)ceilf((float)a);
00199 else return (CGFloat)ceil((double)a);
00200 }
00201
00203 static inline CGFloat HFFloor(CGFloat a) {
00204 if (sizeof(a) == sizeof(float)) return (CGFloat)floorf((float)a);
00205 else return (CGFloat)floor((double)a);
00206 }
00207
00209 static inline CGFloat HFRound(CGFloat a) {
00210 if (sizeof(a) == sizeof(float)) return (CGFloat)roundf((float)a);
00211 else return (CGFloat)round((double)a);
00212 }
00213
00215 static inline CGFloat HFMin(CGFloat a, CGFloat b) {
00216 if (sizeof(a) == sizeof(float)) return (CGFloat)fminf((float)a, (float)b);
00217 else return (CGFloat)fmin((double)a, (double)b);
00218 }
00219
00221 static inline CGFloat HFMax(CGFloat a, CGFloat b) {
00222 if (sizeof(a) == sizeof(float)) return (CGFloat)fmaxf((float)a, (float)b);
00223 else return (CGFloat)fmax((double)a, (double)b);
00224 }
00225
00227 static inline BOOL HFFPRangeEqualsRange(HFFPRange a, HFFPRange b) {
00228 return a.location == b.location && a.length == b.length;
00229 }
00230
00232 static inline CGFloat HFCopysign(CGFloat a, CGFloat b) {
00233 #if __LP64__
00234 return copysign(a, b);
00235 #else
00236 return copysignf(a, b);
00237 #endif
00238 }
00239
00241 static inline NSUInteger HFAtomicIncrement(NSUInteger *ptr, BOOL barrier) {
00242 #if __LP64__
00243 return (barrier ? OSAtomicIncrement64Barrier : OSAtomicIncrement64)((volatile int64_t *)ptr);
00244 #else
00245 return (barrier ? OSAtomicIncrement32Barrier : OSAtomicIncrement32)((volatile int32_t *)ptr);
00246 #endif
00247 }
00248
00250 static inline NSUInteger HFAtomicDecrement(NSUInteger *ptr, BOOL barrier) {
00251 #if __LP64__
00252 return (barrier ? OSAtomicDecrement64Barrier : OSAtomicDecrement64)((volatile int64_t *)ptr);
00253 #else
00254 return (barrier ? OSAtomicDecrement32Barrier : OSAtomicDecrement32)((volatile int32_t *)ptr);
00255 #endif
00256 }
00257
00259 static inline unsigned long long HFFPToUL(long double val) {
00260 assert(val >= 0);
00261 assert(val <= ULLONG_MAX);
00262 unsigned long long result = (unsigned long long)val;
00263 assert((long double)result == val);
00264 return result;
00265 }
00266
00268 static inline long double HFULToFP(unsigned long long val) {
00269 long double result = (long double)val;
00270 assert(HFFPToUL(result) == val);
00271 return result;
00272 }
00273
00275 static inline NSString *HFDescribeAffineTransform(CGAffineTransform t) {
00276 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];
00277 }
00278
00280 static inline NSUInteger HFCountDigitsBase10(unsigned long long val) {
00281 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};
00282 NSUInteger low = 0, high = sizeof kValues / sizeof *kValues;
00283 while (high > low) {
00284 NSUInteger mid = (low + high)/2;
00285 if (val > kValues[mid]) {
00286 low = mid + 1;
00287 }
00288 else {
00289 high = mid;
00290 }
00291 }
00292 return MAX(1, low);
00293 }
00294
00296 static inline NSUInteger HFCountDigitsBase16(unsigned long long val) {
00297
00298 if (val == 0) return 1;
00299
00300
00301 NSUInteger leadingZeros = (NSUInteger)__builtin_clzll(val);
00302 NSUInteger logBase2 = (CHAR_BIT * sizeof val) - leadingZeros - 1;
00303 return 1 + logBase2/4;
00304 }
00305
00307 BOOL HFStringEncodingIsSupersetOfASCII(NSStringEncoding encoding);
00308
00310 static inline unsigned long ll2l(unsigned long long val) { assert(val <= NSUIntegerMax); return (unsigned long)val; }
00311
00313 static inline CGFloat ld2f(long double val) {
00314 #if ! NDEBUG
00315 if (isfinite(val)) {
00316 assert(val <= CGFLOAT_MAX);
00317 assert(val >= -CGFLOAT_MAX);
00318 if ((val > 0 && val < CGFLOAT_MIN) || (val < 0 && val > -CGFLOAT_MIN)) {
00319 NSLog(@"Warning - conversion of long double %Lf to CGFloat will result in the non-normal CGFloat %f", val, (CGFloat)val);
00320 }
00321 }
00322 #endif
00323 return (CGFloat)val;
00324 }
00325
00327 static inline unsigned long long HFDivideULLRoundingUp(unsigned long long a, unsigned long long b) {
00328 if (a == 0) return 0;
00329 else return ((a - 1) / b) + 1;
00330 }
00331
00333 static inline NSUInteger HFDivideULRoundingUp(NSUInteger a, NSUInteger b) {
00334 if (a == 0) return 0;
00335 else return ((a - 1) / b) + 1;
00336 }
00337
00341 @interface HFRangeWrapper : NSObject {
00342 @public
00343 HFRange range;
00344 }
00345
00347 - (HFRange)HFRange;
00348
00350 + (HFRangeWrapper *)withRange:(HFRange)range;
00351
00353 + (NSArray *)withRanges:(const HFRange *)ranges count:(NSUInteger)count;
00354
00356 + (void)getRanges:(HFRange *)ranges fromArray:(NSArray *)array;
00357
00359 + (NSArray *)organizeAndMergeRanges:(NSArray *)inputRanges;
00360
00361 @end
00362
00363 #ifndef NDEBUG
00364 void HFStartTiming(const char *name);
00365 void HFStopTiming(void);
00366 #endif