]>
Commit | Line | Data |
---|---|---|
5c19dc3a A |
1 | // |
2 | // SOSGenCount.c | |
3 | // sec | |
4 | // | |
5 | // Created by Richard Murphy on 1/29/15. | |
6 | // | |
7 | // | |
8 | ||
9 | #include "SOSGenCount.h" | |
10 | #include <utilities/SecCFWrappers.h> | |
11 | #include <CoreFoundation/CFLocale.h> | |
12 | ||
13 | static CFAbsoluteTime SOSGenerationCountGetDateBits(int64_t genValue) { | |
14 | return (uint32_t) ((((uint64_t) genValue) >> 32) << 1); | |
15 | } | |
16 | ||
17 | void SOSGenerationCountWithDescription(SOSGenCountRef gen, void (^operation)(CFStringRef description)) { | |
18 | CFStringRef description = SOSGenerationCountCopyDescription(gen); | |
19 | ||
20 | operation(description); | |
21 | ||
22 | CFReleaseSafe(description); | |
23 | } | |
24 | ||
25 | CFStringRef SOSGenerationCountCopyDescription(SOSGenCountRef gen) { | |
26 | int64_t value = SOSGetGenerationSint(gen); | |
27 | ||
28 | CFMutableStringRef gcDecsription = CFStringCreateMutableCopy(kCFAllocatorDefault, 0, CFSTR("[")); | |
29 | ||
30 | withStringOfAbsoluteTime(SOSGenerationCountGetDateBits(value), ^(CFStringRef decription) { | |
31 | CFStringAppend(gcDecsription, decription); | |
32 | }); | |
33 | ||
34 | CFStringAppendFormat(gcDecsription, NULL, CFSTR(" %u]"), (uint32_t)(value & 0xFFFFFFFF)); | |
35 | ||
36 | return gcDecsription; | |
37 | } | |
38 | ||
39 | int64_t SOSGetGenerationSint(SOSGenCountRef gen) { | |
40 | int64_t value; | |
41 | if(!gen) return 0; | |
42 | CFNumberGetValue(gen, kCFNumberSInt64Type, &value); | |
43 | return value; | |
44 | } | |
45 | ||
46 | static int64_t sosGenerationSetHighBits(int64_t value, int32_t high_31) | |
47 | { | |
48 | value &= 0xFFFFFFFF; // Keep the low 32 bits. | |
49 | value |= ((int64_t) high_31) << 32; | |
50 | ||
51 | return value; | |
52 | } | |
53 | ||
54 | static SOSGenCountRef sosGenerationCreateOrIncrement(SOSGenCountRef gen) { | |
55 | int64_t value = 0; | |
56 | ||
57 | if(gen) { | |
58 | value = SOSGetGenerationSint(gen); | |
59 | } | |
60 | ||
61 | if((value >> 32) == 0) { | |
62 | uint32_t seconds = CFAbsoluteTimeGetCurrent(); // seconds | |
63 | value = sosGenerationSetHighBits(value, (seconds >> 1)); | |
64 | } | |
65 | ||
66 | value++; | |
67 | return CFNumberCreate(NULL, kCFNumberSInt64Type, &value); | |
68 | } | |
69 | ||
70 | SOSGenCountRef SOSGenerationCreate() { | |
71 | return sosGenerationCreateOrIncrement(NULL); | |
72 | } | |
73 | ||
e0e0d90e A |
74 | |
75 | // We need this for a circle gencount test | |
76 | SOSGenCountRef SOSGenerationCreateWithValue(int64_t value) { | |
77 | return CFNumberCreate(NULL, kCFNumberSInt64Type, &value); | |
78 | } | |
79 | ||
5c19dc3a A |
80 | SOSGenCountRef SOSGenerationIncrementAndCreate(SOSGenCountRef gen) { |
81 | return sosGenerationCreateOrIncrement(gen); | |
82 | } | |
83 | ||
84 | SOSGenCountRef SOSGenerationCopy(SOSGenCountRef gen) { | |
85 | if(!gen) return NULL; | |
86 | int64_t value = SOSGetGenerationSint(gen); | |
87 | return CFNumberCreate(NULL, kCFNumberSInt64Type, &value); | |
88 | } | |
89 | ||
fa7225c8 A |
90 | // Is current older than proposed? |
91 | bool SOSGenerationIsOlder(SOSGenCountRef older, SOSGenCountRef newer) { | |
92 | switch(CFNumberCompare(older, newer, NULL)) { | |
93 | case kCFCompareLessThan: return true; | |
94 | case kCFCompareEqualTo: return false; | |
95 | case kCFCompareGreaterThan: return false; | |
96 | } | |
97 | return false; | |
5c19dc3a | 98 | } |
e0e0d90e | 99 | |
fa7225c8 A |
100 | // Is current older than proposed? |
101 | static bool SOSGenerationIsOlderOrEqual(SOSGenCountRef older, SOSGenCountRef newer) { | |
102 | switch(CFNumberCompare(older, newer, NULL)) { | |
103 | case kCFCompareLessThan: return true; | |
104 | case kCFCompareEqualTo: return true; | |
105 | case kCFCompareGreaterThan: return false; | |
106 | } | |
107 | return false; | |
108 | } | |
109 | ||
110 | ||
e0e0d90e A |
111 | SOSGenCountRef SOSGenerationCreateWithBaseline(SOSGenCountRef reference) { |
112 | SOSGenCountRef retval = SOSGenerationCreate(); | |
fa7225c8 | 113 | if(SOSGenerationIsOlderOrEqual(retval, reference)) { |
e0e0d90e A |
114 | CFReleaseNull(retval); |
115 | retval = SOSGenerationIncrementAndCreate(reference); | |
116 | } | |
117 | return retval; | |
118 | } |