Objectively 1.0.0
Ultra-lightweight object oriented framework for GNU C.
All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
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 String *description(const Object *self) {
49
50 const Regexp *this = (Regexp *) self;
51
52 return $$(String, stringWithCharacters, this->pattern);
53}
54
58static void dealloc(Object *self) {
59
60 Regexp *this = (Regexp *) self;
61
62 regfree(this->regex);
63 free(this->regex);
64
65 super(Object, self, dealloc);
66}
67
71static int hash(const Object *self) {
72
73 Regexp *this = (Regexp *) self;
74
75 int hash = HASH_SEED;
76 hash = HashForInteger(hash, this->options);
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}
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,...)
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
static void initialize(Class *clazz)
Definition: Regexp.c:182
Extended POSIX regular expressions.
Immutable 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
Condition * init(Condition *self)
Initializes this Condition.
Definition: Condition.c:67
MutableString * string(void)
Returns a new MutableString.
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
String * description(const Object *self)
Definition: Array.c:66
_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
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
const char * pattern
The pattern.
Definition: Regexp.h:59
_Bool matchesCharacters(const Regexp *self, const char *chars, int options, Range **matches)
Matches this regular expression against the given characters.
Definition: Regexp.c:134
Regexp * initWithPattern(Regexp *self, const char *pattern, int options)
Initializes this regular expression.
Definition: Regexp.c:112
_Bool matchesString(const Regexp *self, const String *string, int options, Range **matches)
Matches this regular expression against the given String.
Definition: Regexp.c:170
OBJECTIVELY_EXPORT Regexp * re(const char *pattern, int options)
A convenience function for instantiating Regexps.
Definition: Regexp.c:219
Class * _Regexp(void)
The Regexp archetype.
Definition: Regexp.c:199
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
Immutable UTF-8 strings.
Definition: String.h:69
char * chars
The backing null-terminated UTF-8 encoded character array.
Definition: String.h:85
String * stringWithCharacters(const char *chars)
Returns a new String by copying chars.
Definition: String.c:487