Objectively 1.0.0
Ultra-lightweight object oriented framework for GNU C.
Date.c
Go to the documentation of this file.
1/*
2 * Objectively: Ultra-lightweight object oriented framework for GNU C.
3 * Copyright (C) 2014 Jay Dolan <jay@jaydolan.com>
4 *
5 * This software is provided 'as-is', without any express or implied
6 * warranty. In no event will the authors be held liable for any damages
7 * arising from the use of this software.
8 *
9 * Permission is granted to anyone to use this software for any purpose,
10 * including commercial applications, and to alter it and redistribute it
11 * freely, subject to the following restrictions:
12 *
13 * 1. The origin of this software must not be misrepresented; you must not
14 * claim that you wrote the original software. If you use this software
15 * in a product, an acknowledgment in the product documentation would be
16 * appreciated but is not required.
17 *
18 * 2. Altered source versions must be plainly marked as such, and must not be
19 * misrepresented as being the original software.
20 *
21 * 3. This notice may not be removed or altered from any source distribution.
22 */
23
24#include <assert.h>
25
26#include "Date.h"
27#include "Hash.h"
28
29#define _Class _Date
30
31#pragma mark - Object
32
36static int hash(const Object *self) {
37
38 Date *this = (Date *) self;
39
40 int hash = HASH_SEED;
41
42 hash = HashForInteger(hash, this->time.tv_sec);
43 hash = HashForInteger(hash, this->time.tv_usec);
44
45 return hash;
46}
47
51static _Bool isEqual(const Object *self, const Object *other) {
52
53 if (super(Object, self, isEqual, other)) {
54 return true;
55 }
56
57 if (other && $(other, isKindOfClass, _Date())) {
58
59 const Date *this = (Date *) self;
60 const Date *that = (Date *) other;
61
62 return $(this, compareTo, that) == OrderSame;
63 }
64
65 return false;
66}
67
68#pragma mark - Date
69
74static Order compareTo(const Date *self, const Date *other) {
75
76 if (other) {
77 const long seconds = self->time.tv_sec - other->time.tv_sec;
78 if (seconds == 0) {
79
80 const long microseconds = self->time.tv_usec - other->time.tv_usec;
81 if (microseconds == 0) {
82 return OrderSame;
83 }
84
85 return microseconds < 0 ? OrderAscending : OrderDescending;
86 }
87
88 return seconds < 0 ? OrderAscending : OrderDescending;
89 }
90
91 return OrderAscending;
92}
93
98static Date *date(void) {
99
100 return $$(Date, dateWithTimeSinceNow, NULL);
101}
102
107static Date *dateWithTimeSinceNow(const Time *interval) {
108
109 Date *date = $(alloc(Date), init);
110 if (date) {
111 if (interval) {
112 date->time.tv_sec += interval->tv_sec;
113 date->time.tv_usec += interval->tv_usec;
114 if (date->time.tv_usec >= MSEC_PER_SEC) {
115 date->time.tv_sec++;
116 date->time.tv_usec -= MSEC_PER_SEC;
117 } else if (date->time.tv_usec < 0) {
118 date->time.tv_sec--;
119 date->time.tv_usec += MSEC_PER_SEC;
120 }
121 }
122 }
123
124 return date;
125}
126
131static Date *init(Date *self) {
132 return $(self, initWithTime, NULL);
133}
134
139static Date *initWithTime(Date *self, const Time *time) {
140
141 self = (Date *) super(Object, self, init);
142 if (self) {
143 if (time) {
144 self->time = *time;
145 } else {
146 gettimeofday(&self->time, NULL);
147 }
148 }
149
150 return self;
151}
152
157static Time timeSinceDate(const Date *self, const Date *date) {
158
159 assert(date);
160
161 return $(self, timeSinceTime, &date->time);
162}
163
168static Time timeSinceNow(const Date *self) {
169
170 Date *date = $$(Date, date);
171
172 Time time = $(self, timeSinceDate, date);
173
174 release(date);
175
176 return time;
177}
178
183static Time timeSinceTime(const Date *self, const Time *time) {
184
185 Time delta = {
186 .tv_sec = self->time.tv_sec - time->tv_sec,
187 .tv_usec = self->time.tv_usec - time->tv_usec
188 };
189
190 if (delta.tv_usec < 0) {
191 delta.tv_sec--;
192 delta.tv_usec += MSEC_PER_SEC;
193 }
194
195 return delta;
196}
197
198#pragma mark - Class lifecycle
199
203static void initialize(Class *clazz) {
204
205 ((ObjectInterface *) clazz->interface)->hash = hash;
206 ((ObjectInterface *) clazz->interface)->isEqual = isEqual;
207
208 ((DateInterface *) clazz->interface)->compareTo = compareTo;
209 ((DateInterface *) clazz->interface)->date = date;
210 ((DateInterface *) clazz->interface)->dateWithTimeSinceNow = dateWithTimeSinceNow;
211 ((DateInterface *) clazz->interface)->init = init;
212 ((DateInterface *) clazz->interface)->initWithTime = initWithTime;
213 ((DateInterface *) clazz->interface)->timeSinceDate = timeSinceDate;
214 ((DateInterface *) clazz->interface)->timeSinceNow = timeSinceNow;
215 ((DateInterface *) clazz->interface)->timeSinceTime = timeSinceTime;
216}
217
222Class *_Date(void) {
223 static Class *clazz;
224 static Once once;
225
226 do_once(&once, {
227 clazz = _initialize(&(const ClassDef) {
228 .name = "Date",
229 .superclass = _Object(),
230 .instanceSize = sizeof(Date),
231 .interfaceOffset = offsetof(Date, interface),
232 .interfaceSize = sizeof(DateInterface),
234 });
235 });
236
237 return clazz;
238}
239
240#undef _Class
241
ident release(ident obj)
Atomically decrement the given Object's reference count. If the resulting reference count is 0,...
Definition: Class.c:196
Class * _initialize(const ClassDef *def)
Initializes the given Class.
Definition: Class.c:91
#define alloc(type)
Allocate and initialize and instance of type.
Definition: Class.h:159
#define super(type, obj, method,...)
static void initialize(Class *clazz)
Definition: Date.c:203
Microsecond-precision immutable dates.
#define MSEC_PER_SEC
Microseconds per second.
Definition: Date.h:50
struct timeval Time
Time (seconds and microseconds).
Definition: Date.h:60
int HashForInteger(int hash, const long integer)
Accumulates the hash value of integer into hash.
Definition: Hash.c:62
Utilities for calculating hash values.
#define HASH_SEED
The hash seed value.
Definition: Hash.h:37
Order
Comparison constants.
Definition: Types.h:70
@ OrderSame
Definition: Types.h:72
@ OrderDescending
Definition: Types.h:73
@ OrderAscending
Definition: Types.h:71
long Once
The Once type.
Definition: Once.h:37
#define do_once(once, block)
Executes the given block at most one time.
Definition: Once.h:43
ClassDefs are passed to _initialize via an archetype to initialize a Class.
Definition: Class.h:41
The runtime representation of a Class.
Definition: Class.h:95
ident interface
The interface of the Class.
Definition: Class.h:105
Condition * init(Condition *self)
Initializes this Condition.
Definition: Condition.c:67
Microsecond-precision immutable dates.
Definition: Date.h:70
Date * dateWithTimeSinceNow(const Time interval)
Returns a new Date with the given Time since now.
Time timeSinceTime(const Date *self, const Time *time)
Definition: Date.c:183
Time timeSinceNow(const Date *self)
Definition: Date.c:168
Date * init(Date *self)
Definition: Date.c:131
Order compareTo(const Date *self, const Date *other)
Compares this Date to another.
Definition: Date.c:74
Time timeSinceDate(const Date *self, const Date *date)
Definition: Date.c:157
Date * initWithTime(Date *self, const Time *time)
Definition: Date.c:139
Class * _Date(void)
The Date archetype.
Definition: Date.c:222
Time time
The time.
Definition: Date.h:86
Date * date(void)
Returns a new Date with the current Time.
Definition: Date.c:98
Object is the root Class of The Objectively Class hierarchy.
Definition: Object.h:46
Class * _Object(void)
The Object archetype.
Definition: Object.c:136
_Bool isKindOfClass(const Object *self, const Class *clazz)
Tests for Class hierarchy membership.
Definition: Object.c:101
_Bool isEqual(const Object *self, const Object *other)
Tests equality of the other Object.
Definition: Array.c:96
int hash(const Object *self)
Definition: Array.c:80