Objectively 1.0.0
Ultra-lightweight object oriented framework for GNU C.
Data.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#include <stdio.h>
26#include <stdlib.h>
27#include <string.h>
28
29#include "Data.h"
30#include "Hash.h"
31#include "MutableData.h"
32
33#define _Class _Data
34
35#define DATA_BLOCK_SIZE 4096
36
37#pragma mark - Object
38
42static Object *copy(const Object *self) {
43
44 Data *this = (Data *) self;
45
46 return (Object *) $(alloc(Data), initWithBytes, this->bytes, this->length);
47}
48
52static void dealloc(Object *self) {
53
54 Data *this = (Data *) self;
55
56 if (this->destroy) {
57 if (this->bytes) {
58 this->destroy(this->bytes);
59 }
60 }
61
62 super(Object, self, dealloc);
63}
64
68static int hash(const Object *self) {
69
70 Data *this = (Data *) self;
71
72 int hash = HASH_SEED;
73 hash = HashForInteger(hash, this->length);
74
75 const Range range = { 0, this->length };
76 hash = HashForBytes(hash, this->bytes, range);
77
78 return hash;
79}
80
84static _Bool isEqual(const Object *self, const Object *other) {
85
86 if (super(Object, self, isEqual, other)) {
87 return true;
88 }
89
90 if (other && $(other, isKindOfClass, _Data())) {
91
92 const Data *this = (Data *) self;
93 const Data *that = (Data *) other;
94
95 if (this->length == that->length) {
96 return memcmp(this->bytes, that->bytes, this->length) == 0;
97 }
98 }
99
100 return false;
101}
102
103#pragma mark - Data
104
109static Data *dataWithBytes(const uint8_t *bytes, size_t length) {
110
111 return $(alloc(Data), initWithBytes, bytes, length);
112}
113
118static Data *dataWithConstMemory(const ident mem, size_t length) {
119
120 return $(alloc(Data), initWithConstMemory, mem, length);
121}
122
127static Data *dataWithContentsOfFile(const char *path) {
128
129 return $(alloc(Data), initWithContentsOfFile, path);
130}
131
136static Data *dataWithMemory(ident mem, size_t length) {
137
138 return $(alloc(Data), initWithMemory, mem, length);
139}
140
145static Data *initWithBytes(Data *self, const uint8_t *bytes, size_t length) {
146
147 ident mem = malloc(length);
148 assert(mem);
149
150 memcpy(mem, bytes, length);
151
152 return $(self, initWithMemory, mem, length);
153}
154
159static Data *initWithConstMemory(Data *self, const ident mem, size_t length) {
160
161 self = (Data *) super(Object, self, init);
162 if (self) {
163 self->bytes = mem;
164 self->length = length;
165 }
166
167 return self;
168}
169
174static Data *initWithContentsOfFile(Data *self, const char *path) {
175
176 assert(path);
177
178 FILE *file = fopen(path, "rb");
179 if (file) {
180 ident mem = NULL;
181
182 int err = fseek(file, 0, SEEK_END);
183 assert(err == 0);
184
185 const size_t length = ftell(file);
186 if (length) {
187
188 mem = malloc(length);
189 assert(mem);
190
191 err = fseek(file, 0, SEEK_SET);
192 assert(err == 0);
193
194 const size_t read = fread(mem, length, 1, file);
195 assert(read == 1);
196 }
197
198 fclose(file);
199 return $(self, initWithMemory, mem, length);
200 }
201
202 return release(self);
203}
204
209static Data *initWithMemory(Data *self, ident mem, size_t length) {
210
211 self = $(self, initWithConstMemory, mem, length);
212 if (self) {
213 self->destroy = free;
214 }
215
216 return self;
217}
218
223static MutableData *mutableCopy(const Data *self) {
224
225 return $(alloc(MutableData), initWithData, self);
226}
227
232static _Bool writeToFile(const Data *self, const char *path) {
233
234 assert(path);
235
236 FILE *file = fopen(path, "w");
237 if (file) {
238
239 size_t count = 1;
240
241 if (self->length) {
242 count = fwrite(self->bytes, self->length, 1, file);
243 }
244
245 fclose(file);
246
247 if (count == 1) {
248 return true;
249 }
250 }
251
252 return false;
253}
254
255#pragma mark - Class lifecycle
256
260static void initialize(Class *clazz) {
261
262 ((ObjectInterface *) clazz->interface)->copy = copy;
263 ((ObjectInterface *) clazz->interface)->dealloc = dealloc;
264 ((ObjectInterface *) clazz->interface)->hash = hash;
265 ((ObjectInterface *) clazz->interface)->isEqual = isEqual;
266
267 ((DataInterface *) clazz->interface)->dataWithBytes = dataWithBytes;
268 ((DataInterface *) clazz->interface)->dataWithConstMemory = dataWithConstMemory;
269 ((DataInterface *) clazz->interface)->dataWithContentsOfFile = dataWithContentsOfFile;
270 ((DataInterface *) clazz->interface)->dataWithMemory = dataWithMemory;
271 ((DataInterface *) clazz->interface)->initWithBytes = initWithBytes;
272 ((DataInterface *) clazz->interface)->initWithConstMemory = initWithConstMemory;
273 ((DataInterface *) clazz->interface)->initWithContentsOfFile = initWithContentsOfFile;
274 ((DataInterface *) clazz->interface)->initWithMemory = initWithMemory;
275 ((DataInterface *) clazz->interface)->mutableCopy = mutableCopy;
276 ((DataInterface *) clazz->interface)->writeToFile = writeToFile;
277}
278
283Class *_Data(void) {
284 static Class *clazz;
285 static Once once;
286
287 do_once(&once, {
288 clazz = _initialize(&(const ClassDef) {
289 .name = "Data",
290 .superclass = _Object(),
291 .instanceSize = sizeof(Data),
292 .interfaceOffset = offsetof(Data, interface),
293 .interfaceSize = sizeof(DataInterface),
295 });
296 });
297
298 return clazz;
299}
300
301#undef _Class
static void destroy(Class *clazz)
Definition: Boole.c:115
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: Data.c:260
Immutable data buffers.
int HashForInteger(int hash, const long integer)
Accumulates the hash value of integer into hash.
Definition: Hash.c:62
int HashForBytes(int hash, const uint8_t *bytes, const Range range)
Accumulates the hash value of bytes into hash.
Definition: Hash.c:28
Utilities for calculating hash values.
#define HASH_SEED
The hash seed value.
Definition: Hash.h:37
Mutable data buffers.
Immutable UTF-8 strings.
void * ident
The identity type, similar to Objective-C id.
Definition: Types.h:49
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
MutableArray * mutableCopy(const Array *self)
Definition: Array.c:381
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
Immutable data buffers.
Definition: Data.h:50
Class * _Data(void)
The Data archetype.
Definition: Data.c:283
Data * initWithContentsOfFile(Data *self, const char *path)
Initializes this Data with the contents of the file at path.
Definition: Data.c:174
Data * dataWithBytes(const uint8_t *bytes, size_t length)
Returns a new Data by copying length of bytes.
Definition: Data.c:109
Data * initWithMemory(Data *self, ident mem, size_t length)
Initializes this Data, taking ownership of the specified memory.
Definition: Data.c:209
DataDestructor destroy
An optional destructor that, if set, is called on dealloc.
Definition: Data.h:71
Data * dataWithMemory(ident mem, size_t length)
Returns a new Data, taking ownership of the specified memory.
Definition: Data.c:136
Data * dataWithContentsOfFile(const char *path)
Returns a new Data with the contents of the file at path.
Definition: Data.c:127
size_t length
The length of bytes.
Definition: Data.h:76
uint8_t * bytes
The bytes.
Definition: Data.h:66
MutableData * mutableCopy(const Data *self)
Definition: Data.c:223
Data * initWithConstMemory(Data *self, const ident mem, size_t length)
Initializes this Data with the given const memory.
Definition: Data.c:159
_Bool writeToFile(const Data *self, const char *path)
Writes this Data to path.
Definition: Data.c:232
Data * initWithBytes(Data *self, const uint8_t *bytes, size_t length)
Initializes this Data by copying length of bytes.
Definition: Data.c:145
Data * dataWithConstMemory(const ident mem, size_t length)
Returns a new Data, backed by the given const memory.
Definition: Data.c:118
Mutable data buffers.
Definition: MutableData.h:40
MutableData * initWithData(MutableData *self, const Data *data)
Initializes this Data with the contents of data.
Definition: MutableData.c:124
Object is the root Class of The Objectively Class hierarchy.
Definition: Object.h:46
Class * _Object(void)
The Object archetype.
Definition: Object.c:136
Object * copy(const Object *self)
Creates a shallow copy of this Object.
Definition: Array.c:40
_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
void dealloc(Object *self)
Frees all resources held by this Object.
Definition: Array.c:50
A location and length into contiguous collections.
Definition: Types.h:54
int read(StringReader *self)
Reads a single Unicode code point from this StringReader.