Objectively
Ultra-lightweight object oriented framework for GNU C.
Loading...
Searching...
No Matches
Resource.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 <stdlib.h>
26#include <string.h>
27#include <sys/stat.h>
28
29#include "Array.h"
30#include "Resource.h"
31#include "String.h"
32#include "Pointer.h"
33
34#define _Class _Resource
35
38
39#pragma mark - Object
40
44static void dealloc(Object *self) {
45
46 Resource *this = (Resource *) self;
47
48 release(this->data);
49
50 free(this->name);
51
52 super(Object, self, dealloc);
53}
54
55#pragma mark - Resource
56
61static void addResourcePath(const char *path) {
62
63 assert(path);
64 String *string = str(path);
65
66 $(_resourcePaths, addObject, string);
67 release(string);
68}
69
75
76 assert(provider);
77 Pointer *pointer = $(alloc(Pointer), initWithPointer, provider, NULL);
78
79 $(_resourceProviders, addObject, pointer);
80 release(pointer);
81}
82
87static Resource *initWithBytes(Resource *self, const uint8_t *bytes, size_t length, const char *name) {
88
89 Data *data = $$(Data, dataWithBytes, bytes, length);
90 self = $(self, initWithData, data, name);
91
93 return self;
94}
95
100static Resource *initWithData(Resource *self, Data *data, const char *name) {
101
102 self = (Resource *) super(Object, self, init);
103 if (self) {
104 assert(data);
105 self->data = retain(data);
106
107 assert(name);
108 self->name = strdup(name);
109 }
110
111 return self;
112}
113
118static Resource *initWithName(Resource *self, const char *name) {
119
120 Data *data = NULL;
121
122 const Array *resourceProviders = (Array *) _resourceProviders;
123 for (size_t i = 0; i < resourceProviders->count && data == NULL; i++) {
124
125 const Pointer *pointer = $(resourceProviders, objectAtIndex, i);
126 data = ((ResourceProvider) (pointer->pointer))(name);
127 }
128
129 const Array *resourcePaths = (Array *) _resourcePaths;
130 for (size_t i = 0; i < resourcePaths->count && data == NULL; i++) {
131
132 const String *resourcePath = $(resourcePaths, objectAtIndex, i);
133 String *path = str("%s%s%s", resourcePath->chars, PATH_SEPAR, name);
134
135 struct stat s;
136 if (stat(path->chars, &s) == 0 && S_ISREG(s.st_mode)) {
138 }
139
140 release(path);
141 }
142
143 if (data) {
144 self = $(self, initWithData, data, name);
145 } else {
146 self = release(self);
147 }
148
149 release(data);
150
151 return self;
152}
153
158static void removeResourcePath(const char *path) {
159
160 String *string = $$(String, stringWithCharacters, path);
161
162 $(_resourcePaths, removeObject, string);
163
164 release(string);
165}
166
172
173 Pointer *pointer = $(alloc(Pointer), initWithPointer, provider, NULL);
174
175 $(_resourceProviders, removeObject, pointer);
176
177 release(pointer);
178}
179
184static Resource *resourceWithName(const char *name) {
185 return $(alloc(Resource), initWithName, name);
186}
187
188#pragma mark - Class lifecycle
189
193static void destroy(Class *clazz) {
196}
197
201static void initialize(Class *clazz) {
202
203 ((ObjectInterface *) clazz->interface)->dealloc = dealloc;
204
205 ((ResourceInterface *) clazz->interface)->addResourcePath = addResourcePath;
206 ((ResourceInterface *) clazz->interface)->addResourceProvider = addResourceProvider;
207 ((ResourceInterface *) clazz->interface)->initWithBytes = initWithBytes;
208 ((ResourceInterface *) clazz->interface)->initWithData = initWithData;
209 ((ResourceInterface *) clazz->interface)->initWithName = initWithName;
210 ((ResourceInterface *) clazz->interface)->removeResourcePath = removeResourcePath;
211 ((ResourceInterface *) clazz->interface)->removeResourceProvider = removeResourceProvider;
212 ((ResourceInterface *) clazz->interface)->resourceWithName = resourceWithName;
213
215 assert(_resourcePaths);
216
217 const char *env = getenv("OBJECTIVELY_RESOURCE_PATH");
218 if (env) {
219
220 String *string = $$(String, stringWithCharacters, env);
222
223 for (size_t i = 0; i < paths->count; i++) {
224 addResourcePath(((String *) $(paths, objectAtIndex, i))->chars);
225 }
226
227 release(paths);
228 release(string);
229 }
230
231 addResourcePath(".");
232
234 assert(_resourceProviders);
235}
236
242 static Class *clazz;
243 static Once once;
244
245 do_once(&once, {
246 clazz = _initialize(&(const ClassDef) {
247 .name = "Resource",
248 .superclass = _Object(),
249 .instanceSize = sizeof(Resource),
250 .interfaceOffset = offsetof(Resource, interface),
251 .interfaceSize = sizeof(ResourceInterface),
253 .destroy = destroy,
254 });
255 });
256
257 return clazz;
258}
259
260#undef _Class
261
static ident objectAtIndex(const Array *self, size_t index)
Definition Array.c:578
static void removeObject(Array *self, const ident obj)
Definition Array.c:642
static void addObject(Array *self, const ident obj)
Definition Array.c:181
static Array * init(Array *self)
Definition Array.c:420
Arrays.
ident release(ident obj)
Atomically decrement the given Object's reference count. If the resulting reference count is 0,...
Definition Class.c:195
Class * _initialize(const ClassDef *def)
Initializes the given Class.
Definition Class.c:86
ident retain(ident obj)
Atomically increment the given Object's reference count.
Definition Class.c:210
#define alloc(type)
Allocate and initialize and instance of type.
Definition Class.h:176
#define super(type, obj, method,...)
static Data * data(void)
Definition Data.c:286
static Data * dataWithContentsOfFile(const char *path)
Definition Data.c:133
static Data * dataWithBytes(const uint8_t *bytes, size_t length)
Definition Data.c:115
Class * _Object(void)
Definition Object.c:136
static Pointer * initWithPointer(Pointer *self, ident pointer, Consumer destroy)
Definition Pointer.c:107
Pointers provide Object encapsulation for raw C pointers.
static void removeResourcePath(const char *path)
Definition Resource.c:158
static void destroy(Class *clazz)
Definition Resource.c:193
static Array * _resourcePaths
Definition Resource.c:36
static void removeResourceProvider(ResourceProvider provider)
Definition Resource.c:171
static void addResourceProvider(ResourceProvider provider)
Definition Resource.c:74
static Resource * initWithName(Resource *self, const char *name)
Definition Resource.c:118
static void dealloc(Object *self)
Definition Resource.c:44
static Array * _resourceProviders
Definition Resource.c:37
static void initialize(Class *clazz)
Definition Resource.c:201
Class * _Resource(void)
Definition Resource.c:241
static Resource * resourceWithName(const char *name)
Definition Resource.c:184
static Resource * initWithBytes(Resource *self, const uint8_t *bytes, size_t length, const char *name)
Definition Resource.c:87
static void addResourcePath(const char *path)
Definition Resource.c:61
static Resource * initWithData(Resource *self, Data *data, const char *name)
Definition Resource.c:100
Resources provide an abstraction for file and stream resources.
Data *(* ResourceProvider)(const char *name)
Applications may specify a provider function for loading via file system abstractions.
Definition Resource.h:47
#define PATH_DELIM
Definition Resource.h:32
#define PATH_SEPAR
Definition Resource.h:33
String * str(const char *fmt,...)
Definition String.c:1084
static String * stringWithCharacters(const char *chars)
Definition String.c:349
static Array * componentsSeparatedByCharacters(const String *self, const char *chars)
Definition String.c:182
UTF-8 strings.
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
Arrays.
Definition Array.h:56
size_t count
The count of elements.
Definition Array.h:72
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
Data buffers.
Definition Data.h:50
Object is the root Class of The Objectively Class hierarchy.
Definition Object.h:46
Pointers provide Object encapsulation for raw C pointers.
Definition Pointer.h:40
ident pointer
The backing pointer.
Definition Pointer.h:61
Resources provide an abstraction for file and stream resources.
Definition Resource.h:53
Resource * initWithData(Resource *self, Data *data)
void removeResourcePath(const char *path)
Removes the specified Resource path.
Definition Resource.c:158
Data * data
The resource data.
Definition Resource.h:69
Resource * initWithName(Resource *self, const char *name)
Initializes this Resource with the specified name.
Definition Resource.c:118
char * name
The resource name.
Definition Resource.h:74
UTF-8 strings.
Definition String.h:69
char * chars
The backing null-terminated UTF-8 encoded character array.
Definition String.h:85