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
|
/* CFDateInterval.c
Copyright (c) 2017-2019, Apple Inc. and the Swift project authors
Portions Copyright (c) 2017-2019, Apple Inc. and the Swift project authors
Licensed under Apache License v2.0 with Runtime Library Exception
See http://swift.org/LICENSE.txt for license information
See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
*/
#include "CFRuntime.h"
#include "CFString.h"
#include "CFInternal.h"
#include "CFDateInterval.h"
/* Runtime setup */
static CFTypeID __kCFDateIntervalTypeID = _kCFRuntimeNotATypeID;
struct __CFDateInterval {
CFRuntimeBase _base;
CFDateRef _start;
CFTimeInterval _duration;
};
static Boolean __CFDateIntervalEqual(CFTypeRef cf1, CFTypeRef cf2) {
if (cf1 == cf2) return true;
CFDateIntervalRef di1 = (CFDateIntervalRef)cf1;
CFDateIntervalRef di2 = (CFDateIntervalRef)cf2;
return di1->_duration == di2->_duration && CFEqual(di1->_start, di2->_start);
}
static CFHashCode __CFDateIntervalHash(CFTypeRef cf) {
CFDateIntervalRef di = (CFDateIntervalRef)cf;
CFAbsoluteTime start = CFDateGetAbsoluteTime(di->_start);
CFAbsoluteTime end = start + di->_duration;
CFAbsoluteTime buf[] = {start, end};
return CFHashBytes((uint8_t *)buf, (sizeof(buf) / sizeof(buf[0])) * sizeof(CFAbsoluteTime));
}
static void __CFDateIntervalDeallocate(CFTypeRef cf) {
CFDateIntervalRef di = (CFDateIntervalRef)cf;
CFRelease(di->_start);
}
static CFStringRef __CFDateIntervalCopyDescription(CFTypeRef cf) {
CFDateIntervalRef di = (CFDateIntervalRef)cf;
return CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("<CFDateInterval %p [%p]> %@ %f"), di, CFGetAllocator(di), di->_start, di->_duration);
}
static const CFRuntimeClass __CFDateIntervalClass = {
0,
"CFDateInterval",
NULL, // init
NULL, // copy
__CFDateIntervalDeallocate,
__CFDateIntervalEqual,
__CFDateIntervalHash,
NULL, //
__CFDateIntervalCopyDescription
};
CF_PRIVATE CFTypeID CFDateIntervalGetTypeID(void) {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
__kCFDateIntervalTypeID = _CFRuntimeRegisterClass(&__CFDateIntervalClass);
});
return __kCFDateIntervalTypeID;
}
CF_EXPORT CFDateIntervalRef CFDateIntervalCreate(CFAllocatorRef _Nullable allocator, CFDateRef startDate, CFTimeInterval duration) {
if (!allocator) allocator = CFAllocatorGetDefault();
struct __CFDateInterval *di = NULL;
uint32_t size = sizeof(struct __CFDateInterval) - sizeof(CFRuntimeBase);
di = (struct __CFDateInterval *)_CFRuntimeCreateInstance(allocator, CFDateIntervalGetTypeID(), size, NULL);
if (NULL == di) HALT;
di->_start = CFRetain(startDate);
di->_duration = duration;
return di;
}
CF_EXPORT CFDateIntervalRef CFDateIntervalCreateWithEndDate(CFAllocatorRef _Nullable allocator, CFDateRef startDate, CFDateRef endDate) {
return CFDateIntervalCreate(allocator, startDate, CFDateGetAbsoluteTime(endDate) - CFDateGetAbsoluteTime(startDate));
}
CF_EXPORT CFTimeInterval CFDateIntervalGetDuration(CFDateIntervalRef interval) {
return interval->_duration;
}
CF_EXPORT CFDateRef CFDateIntervalCopyStartDate(CFDateIntervalRef interval) {
return CFRetain(interval->_start);
}
CF_EXPORT CFDateRef CFDateIntervalCopyEndDate(CFDateIntervalRef interval) {
return CFDateCreate(kCFAllocatorSystemDefault, CFDateGetAbsoluteTime(interval->_start) + interval->_duration);
}
CF_EXPORT CFComparisonResult CFDateIntervalCompare(CFDateIntervalRef interval1, CFDateIntervalRef interval2) {
CFComparisonResult result = CFDateCompare(interval1->_start, interval2->_start, NULL);
if (result == kCFCompareEqualTo) {
if (interval1->_duration < interval2->_duration) return kCFCompareLessThan;
if (interval1->_duration > interval2->_duration) return kCFCompareGreaterThan;
return kCFCompareEqualTo;
}
return result;
}
CF_EXPORT Boolean CFDateIntervalIntersectsDateInterval(CFDateIntervalRef interval, CFDateIntervalRef intervalToIntersect) {
CFDateRef otherEndDate = CFDateIntervalCopyEndDate(intervalToIntersect);
CFDateRef selfEndDate = CFDateIntervalCopyEndDate(interval);
Boolean result =
CFDateIntervalContainsDate(interval, intervalToIntersect->_start) ||
CFDateIntervalContainsDate(interval, otherEndDate) ||
CFDateIntervalContainsDate(intervalToIntersect, interval->_start) ||
CFDateIntervalContainsDate(intervalToIntersect, selfEndDate);
CFRelease(otherEndDate);
CFRelease(selfEndDate);
return result;
}
CF_EXPORT CFDateIntervalRef _Nullable CFDateIntervalCreateIntersectionWithDateInterval(CFAllocatorRef allocator, CFDateIntervalRef interval, CFDateIntervalRef intervalToIntersect) {
if (CFEqual(interval, intervalToIntersect)) {
return (CFDateIntervalRef)CFRetain(interval);
}
if (!CFDateIntervalIntersectsDateInterval(interval, intervalToIntersect)) {
return NULL;
}
CFAbsoluteTime selfStart = CFDateGetAbsoluteTime(interval->_start);
CFAbsoluteTime selfEnd = selfStart + interval->_duration;
CFAbsoluteTime otherStart = CFDateGetAbsoluteTime(intervalToIntersect->_start);
CFAbsoluteTime otherEnd = otherStart + intervalToIntersect->_duration;
CFDateRef resultStartDate = NULL;
CFAbsoluteTime resultEndTime = 0;
if (otherStart >= selfStart) {
resultStartDate = intervalToIntersect->_start;
} else {
// interval starts after intervalToIntersect
resultStartDate = interval->_start;
}
if (otherEnd >= selfEnd) {
resultEndTime = selfEnd;
} else {
// intervalToIntersect ends before interval
resultEndTime = otherEnd;
}
CFTimeInterval resultDuration = resultEndTime - CFDateGetAbsoluteTime(resultStartDate);
return CFDateIntervalCreate(allocator, resultStartDate, resultDuration);
}
CF_EXPORT Boolean CFDateIntervalContainsDate(CFDateIntervalRef interval, CFDateRef date) {
CFAbsoluteTime time = CFDateGetAbsoluteTime(date);
CFAbsoluteTime start = CFDateGetAbsoluteTime(interval->_start);
CFAbsoluteTime end = start + interval->_duration;
return ((time >= start) && (time <= end));
}
|