forked from swiftlang/swift-corelibs-foundation
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathCFDateInterval.c
163 lines (134 loc) · 6.19 KB
/
CFDateInterval.c
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-2018, Apple Inc. and the Swift project authors
Portions Copyright (c) 2017-2018, 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 <CoreFoundation/CFRuntime.h>
#include <CoreFoundation/CFString.h>
#include "CFInternal.h"
#include <CoreFoundation/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));
}