Objectively
Ultra-lightweight object oriented framework for GNU C.
Loading...
Searching...
No Matches
URL.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
27#include "String.h"
28#include "Regexp.h"
29#include "URL.h"
30
31#define _Class _URL
32
33#pragma mark - Object
34
38static Object *copy(const Object *self) {
39
40 const URL *this = (URL *) self;
41
42 return (Object *) $(alloc(URL), initWithString, this->urlString);
43}
44
48static void dealloc(Object *self) {
49
50 URL *this = (URL *) self;
51
52 release(this->fragment);
53 release(this->host);
54 release(this->path);
55 release(this->query);
56 release(this->scheme);
57 release(this->urlString);
58
59 super(Object, self, dealloc);
60}
61
65static String *description(const Object *self) {
66
67 const URL *this = (URL *) self;
68
69 return $((Object *) this->urlString, description);
70}
71
75static int hash(const Object *self) {
76
77 const URL *this = (URL *) self;
78
79 return $((Object *) this->urlString, hash);
80}
81
85static bool isEqual(const Object *self, const Object *other) {
86
87 if (super(Object, self, isEqual, other)) {
88 return true;
89 }
90
91 if (other && self->clazz == other->clazz) {
92
93 const URL *this = (URL *) self;
94 const URL *that = (URL *) other;
95
96 return $((Object *) this->urlString, isEqual, (Object *) that->urlString);
97 }
98
99 return false;
100}
101
102#pragma mark - URL
103
108static URL *baseURL(const URL *self) {
109
110 String *string = $(alloc(String), init);
111
112 $(string, appendString, self->scheme);
113 $(string, appendFormat, "://");
114
115 if (self->host) {
116 $(string, appendString, self->host);
117 }
118
119 if (self->port) {
120 $(string, appendFormat, ":%u", self->port);
121 }
122
123 URL *baseURL = $(alloc(URL), initWithString, (String *) string);
124
125 release(string);
126
127 return baseURL;
128}
129
130static Regexp *_re;
131
136static URL *initWithCharacters(URL *self, const char *chars) {
137
138 assert(chars);
139
140 self = (URL *) super(Object, self, init);
141 if (self) {
142
143 Range *ranges;
144 if ($(_re, matchesCharacters, chars, 0, &ranges)) {
145
146 self->urlString = $(alloc(String), initWithCharacters, chars);
147
148 Range *scheme = &ranges[1];
149 Range *host = &ranges[2];
150 Range *port = &ranges[3];
151 Range *path = &ranges[4];
152 Range *query = &ranges[5];
153 Range *fragment = &ranges[6];
154
155 self->scheme = $(self->urlString, substring, *scheme);
156
157 if (host->location > -1) {
158 self->host = $(self->urlString, substring, *host);
159
160 if (port->location > -1) {
161 const char *s = self->urlString->chars + port->location + 1;
162 self->port = strtoul(s, NULL, 10);
163 }
164 }
165
166 if (path->location > -1) {
167 self->path = $(self->urlString, substring, *path);
168 }
169
170 if (query->location > -1) {
171
172 query->location++;
173 query->length--;
174
175 self->query = $(self->urlString, substring, *query);
176 }
177
178 if (fragment->location > -1) {
179
180 fragment->location++;
181 fragment->length--;
182
183 self->fragment = $(self->urlString, substring, *fragment);
184 }
185
186 free(ranges);
187 } else {
188 self = release(self);
189 }
190 }
191
192 return self;
193}
194
199static URL *initWithString(URL *self, const String *string) {
200
201 assert(string);
202
203 return $(self, initWithCharacters, string->chars);
204}
205
210static Array *pathComponents(const URL *self) {
211
212 return $(self->path, componentsSeparatedByCharacters, "/");
213}
214
215#pragma mark - Class lifecycle
216
220static void destroy(Class *clazz) {
221
222 release(_re);
223}
224
228static void initialize(Class *clazz) {
229
230 ((ObjectInterface *) clazz->interface)->copy = copy;
231 ((ObjectInterface *) clazz->interface)->dealloc = dealloc;
232 ((ObjectInterface *) clazz->interface)->description = description;
233 ((ObjectInterface *) clazz->interface)->hash = hash;
234 ((ObjectInterface *) clazz->interface)->isEqual = isEqual;
235
236 ((URLInterface *) clazz->interface)->baseURL = baseURL;
237 ((URLInterface *) clazz->interface)->initWithCharacters = initWithCharacters;
238 ((URLInterface *) clazz->interface)->initWithString = initWithString;
239 ((URLInterface *) clazz->interface)->pathComponents = pathComponents;
240
241 _re = re("([a-z]+)://([^:/\?]+)?(:[0-9]+)?(/[^\?#]+)?([^#]+)?(#.*)?", 0);
242}
243
248Class *_URL(void) {
249 static Class *clazz;
250 static Once once;
251
252 do_once(&once, {
253 clazz = _initialize(&(const ClassDef) {
254 .name = "URL",
255 .superclass = _Object(),
256 .instanceSize = sizeof(URL),
257 .interfaceOffset = offsetof(URL, interface),
258 .interfaceSize = sizeof(URLInterface),
260 .destroy = destroy,
261 });
262 });
263
264 return clazz;
265}
266
267#undef _Class
static Array * init(Array *self)
Definition Array.c:420
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
#define alloc(type)
Allocate and initialize and instance of type.
Definition Class.h:176
#define super(type, obj, method,...)
Class * _Object(void)
Definition Object.c:136
static bool matchesCharacters(const Regexp *self, const char *chars, int options, Range **ranges)
Definition Regexp.c:134
Regexp * re(const char *pattern, int options)
Definition Regexp.c:219
Extended POSIX regular expressions.
static String * string(void)
Definition String.c:905
static String * substring(const String *self, const Range range)
Definition String.c:401
static void appendFormat(String *self, const char *fmt,...)
Definition String.c:541
static Array * componentsSeparatedByCharacters(const String *self, const char *chars)
Definition String.c:182
static void appendString(String *self, const String *string)
Definition String.c:555
UTF-8 strings.
static void destroy(Class *clazz)
Definition URL.c:220
static Array * pathComponents(const URL *self)
Definition URL.c:210
static bool isEqual(const Object *self, const Object *other)
Definition URL.c:85
static URL * initWithString(URL *self, const String *string)
Definition URL.c:199
static String * description(const Object *self)
Definition URL.c:65
static URL * baseURL(const URL *self)
Definition URL.c:108
static void dealloc(Object *self)
Definition URL.c:48
static Regexp * _re
Definition URL.c:130
static Object * copy(const Object *self)
Definition URL.c:38
static void initialize(Class *clazz)
Definition URL.c:228
Class * _URL(void)
Definition URL.c:248
static URL * initWithCharacters(URL *self, const char *chars)
Definition URL.c:136
static int hash(const Object *self)
Definition URL.c:75
Uniform Resource Locators (RFC 3986).
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
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
Object is the root Class of The Objectively Class hierarchy.
Definition Object.h:46
Class * clazz
Every instance of Object begins with a pointer to its Class.
Definition Object.h:55
int hash(const Object *self)
Definition Array.c:129
void dealloc(Object *self)
Frees all resources held by this Object.
Definition Array.c:99
A location and length into contiguous collections.
Definition Types.h:54
ssize_t location
The location.
Definition Types.h:59
size_t length
The length.
Definition Types.h:64
Extended POSIX regular expressions.
Definition Regexp.h:43
UTF-8 strings.
Definition String.h:69
char * chars
The backing null-terminated UTF-8 encoded character array.
Definition String.h:85
Uniform Resource Locators (RFC 3986).
Definition URL.h:44
String * path
The path.
Definition URL.h:70
unsigned short port
The port.
Definition URL.h:75
Array * pathComponents(const URL *self)
Definition URL.c:210
String * urlString
The URL String.
Definition URL.h:90
String * scheme
The scheme, or protocol.
Definition URL.h:85
URL * initWithString(URL *self, const String *string)
Initializes this URL with the specified String.
Definition URL.c:199
String * host
The host.
Definition URL.h:65
String * fragment
The fragment.
Definition URL.h:60
String * query
The query.
Definition URL.h:80
URL * initWithCharacters(URL *self, const char *chars)
Initializes this URL with the specified characters.
Definition URL.c:136