Objectively
Ultra-lightweight object oriented framework for GNU C.
Loading...
Searching...
No Matches
Regexp.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
28#include "Hash.h"
29#include "Regexp.h"
30
31#define _Class _Regexp
32
33#pragma mark - Object
34
38static Object *copy(const Object *self) {
39
40 const Regexp *this = (Regexp *) self;
41
42 return (Object *) re(this->pattern, this->options);
43}
44
48static void dealloc(Object *self) {
49
50 Regexp *this = (Regexp *) self;
51
52 regfree(this->regex);
53 free(this->regex);
54
55 super(Object, self, dealloc);
56}
57
61static String *description(const Object *self) {
62
63 const Regexp *this = (Regexp *) self;
64
65 return $$(String, stringWithCharacters, this->pattern);
66}
67
71static int hash(const Object *self) {
72
73 Regexp *this = (Regexp *) self;
74
75 int hash = HASH_SEED;
77
78 const Range range = { 0, strlen(this->pattern) };
79 hash = HashForBytes(hash, (uint8_t *) this->pattern, range);
80
81 return hash;
82}
83
87static bool isEqual(const Object *self, const Object *other) {
88
89 if (super(Object, self, isEqual, other)) {
90 return true;
91 }
92
93 if (other && $(other, isKindOfClass, _Regexp())) {
94
95 const Regexp *this = (Regexp *) self;
96 const Regexp *that = (Regexp *) other;
97
98 if (this->options == that->options) {
99 return strcmp(this->pattern, that->pattern) == 0;
100 }
101 }
102
103 return false;
104}
105
106#pragma mark - Regexp
107
112static Regexp *initWithPattern(Regexp *self, const char *pattern, int options) {
113
114 self = (Regexp *) super(Object, self, init);
115 if (self) {
116 self->regex = calloc(1, sizeof(regex_t));
117 assert(self->regex);
118
119 const int err = regcomp(self->regex, pattern, REG_EXTENDED | options);
120 assert(err == 0);
121
122 self->pattern = pattern;
123 self->options = options;
124 self->numberOfSubExpressions = ((regex_t *) self->regex)->re_nsub;
125 }
126
127 return self;
128}
129
134static bool matchesCharacters(const Regexp *self, const char *chars, int options, Range **ranges) {
135
136 if (ranges) {
137 const size_t numberOfMatches = self->numberOfSubExpressions + 1;
138 regmatch_t matches[numberOfMatches];
139
140 const int err = regexec(self->regex, chars, numberOfMatches, matches, options);
141 assert(err == 0 || err == REG_NOMATCH);
142
143 *ranges = calloc(numberOfMatches, sizeof(Range));
144 assert(*ranges);
145
146 Range *range = *ranges;
147 const regmatch_t *match = matches;
148 for (size_t i = 0; i < numberOfMatches; i++, range++, match++) {
149 range->location = match->rm_so;
150 if (range->location > -1) {
151 range->length = match->rm_eo - match->rm_so;
152 } else {
153 range->length = 0;
154 }
155 }
156
157 return err == 0;
158 }
159
160 const int err = regexec(self->regex, chars, 0, NULL, options);
161 assert(err == 0 || err == REG_NOMATCH);
162
163 return err == 0;
164}
165
170static bool matchesString(const Regexp *self, const String *string, int options, Range **ranges) {
171
172 assert(string);
173
174 return $(self, matchesCharacters, string->chars, options, ranges);
175}
176
177#pragma mark - Class lifecycle
178
182static void initialize(Class *clazz) {
183
184 ((ObjectInterface *) clazz->interface)->copy = copy;
185 ((ObjectInterface *) clazz->interface)->dealloc = dealloc;
186 ((ObjectInterface *) clazz->interface)->description = description;
187 ((ObjectInterface *) clazz->interface)->hash = hash;
188 ((ObjectInterface *) clazz->interface)->isEqual = isEqual;
189
190 ((RegexpInterface *) clazz->interface)->initWithPattern = initWithPattern;
191 ((RegexpInterface *) clazz->interface)->matchesCharacters = matchesCharacters;
192 ((RegexpInterface *) clazz->interface)->matchesString = matchesString;
193}
194
200 static Class *clazz;
201 static Once once;
202
203 do_once(&once, {
204 clazz = _initialize(&(const ClassDef) {
205 .name = "Regexp",
206 .superclass = _Object(),
207 .instanceSize = sizeof(Regexp),
208 .interfaceOffset = offsetof(Regexp, interface),
209 .interfaceSize = sizeof(RegexpInterface),
211 });
212 });
213
214 return clazz;
215}
216
217#undef _Class
218
219Regexp *re(const char *pattern, int options) {
220 return $(alloc(Regexp), initWithPattern, pattern, options);
221}
static Array * init(Array *self)
Definition Array.c:420
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,...)
int HashForInteger(int hash, const long integer)
Accumulates the hash value of integer into hash.
Definition Hash.c:66
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
static bool isKindOfClass(const Object *self, const Class *clazz)
Definition Object.c:101
Class * _Object(void)
Definition Object.c:136
static int options(RESTClient *self, const char *url, Data **data)
Definition RESTClient.c:217
static Regexp * initWithPattern(Regexp *self, const char *pattern, int options)
Definition Regexp.c:112
static bool isEqual(const Object *self, const Object *other)
Definition Regexp.c:87
static bool matchesCharacters(const Regexp *self, const char *chars, int options, Range **ranges)
Definition Regexp.c:134
static bool matchesString(const Regexp *self, const String *string, int options, Range **ranges)
Definition Regexp.c:170
static String * description(const Object *self)
Definition Regexp.c:61
static void dealloc(Object *self)
Definition Regexp.c:48
Class * _Regexp(void)
Definition Regexp.c:199
static Object * copy(const Object *self)
Definition Regexp.c:38
static void initialize(Class *clazz)
Definition Regexp.c:182
Regexp * re(const char *pattern, int options)
Definition Regexp.c:219
static int hash(const Object *self)
Definition Regexp.c:71
Extended POSIX regular expressions.
static String * string(void)
Definition String.c:905
static String * stringWithCharacters(const char *chars)
Definition String.c:349
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
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
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
ident regex
The backing regular expression.
Definition Regexp.h:74
bool matchesCharacters(const Regexp *self, const char *chars, int options, Range **matches)
Matches this regular expression against the given characters.
Definition Regexp.c:134
const char * pattern
The pattern.
Definition Regexp.h:59
int options
A bitwise-or of REG_ICASE, REG_NEWLINE.
Definition Regexp.h:64
size_t numberOfSubExpressions
The number of parenthesized sub-expressions.
Definition Regexp.h:69
UTF-8 strings.
Definition String.h:69
char * chars
The backing null-terminated UTF-8 encoded character array.
Definition String.h:85