ObjectivelyMVC
Object oriented MVC framework for SDL3 and GNU C
Loading...
Searching...
No Matches
SelectorSequence.c
Go to the documentation of this file.
1/*
2 * ObjectivelyMVC: Object oriented MVC framework for SDL3 and 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 <Objectively/Array.h>
29
30#include "SelectorSequence.h"
31#include "View.h"
32
33#define _Class _SelectorSequence
34
35#pragma mark - Object
36
40static void dealloc(Object *self) {
41
42 SelectorSequence *this = (SelectorSequence *) self;
43
44 free(this->sequence);
45 release(this->simpleSelectors);
46
47 super(Object, self, dealloc);
48}
49
53static String *description(const Object *self) {
54
55 const SelectorSequence *this = (SelectorSequence *) self;
56
57 return str(this->sequence);
58}
59
60#pragma mark - SelectorSequence
61
66static SelectorSequence *initWithSequence(SelectorSequence *self, const char *sequence) {
67
68 self = (SelectorSequence *) super(Object, self, init);
69 if (self) {
70
71 self->sequence = strtrim(sequence);
72 assert(self->sequence);
73
74 assert(strlen(self->sequence));
75
76 self->simpleSelectors = $$(SimpleSelector, parse, self->sequence);
77 assert(self->simpleSelectors->count);
78 }
79
80 return self;
81}
82
87static bool matchesView(const SelectorSequence *self, const View *view) {
88
89 for (size_t i = 0; i < self->simpleSelectors->count; i++) {
90 const SimpleSelector *simpleSelector = $(self->simpleSelectors, objectAtIndex, i);
91 if ($(view, matchesSelector, simpleSelector) == false) {
92 return false;
93 }
94 }
95
96 return true;
97}
98
103
105
106 while (isspace(*c)) {
107 combinator = SequenceCombinatorDescendent;
108 c++;
109 }
110
111 switch (*c) {
112 case '>':
114 case '~':
116 case '+':
118 case '\0':
120 default:
121 break;
122 }
123
124 return combinator;
125}
126
131static Array *parse(const char *rule) {
132
133 assert(rule);
134
135 Array *selectorSequences = $$(Array, arrayWithCapacity, 8);
136 assert(selectorSequences);
137
139
140 const char *c = rule;
141 while (*c) {
142 const size_t size = strcspn(c, " \n\t>+~");
143 if (size) {
144 char *sequence = calloc(1, size + 1);
145 assert(sequence);
146
147 strncpy(sequence, c, size);
148
149 SelectorSequence *selectorSequence = $(alloc(SelectorSequence), initWithSequence, sequence);
150 assert(selectorSequence);
151
152 selectorSequence->right = sequenceCombinator(c + size);
153 assert(selectorSequence->right);
154
155 selectorSequence->left = left;
156 left = selectorSequence->right;
157
158 $(selectorSequences, addObject, selectorSequence);
159
160 release(selectorSequence);
161 free(sequence);
162 }
163
164 c += size;
165 c += strspn(c, " \n\t>+~");
166 }
167
168 return (Array *) selectorSequences;
169}
170
171#pragma mark - Class lifecycle
172
176static void initialize(Class *clazz) {
177
178 ((ObjectInterface *) clazz->interface)->dealloc = dealloc;
179 ((ObjectInterface *) clazz->interface)->description = description;
180
181 ((SelectorSequenceInterface *) clazz->interface)->initWithSequence = initWithSequence;
182 ((SelectorSequenceInterface *) clazz->interface)->matchesView = matchesView;
183 ((SelectorSequenceInterface *) clazz->interface)->parse = parse;
184}
185
190Class *_SelectorSequence(void) {
191 static Class *clazz;
192 static Once once;
193
194 do_once(&once, {
195 clazz = _initialize(&(const ClassDef) {
196 .name = "SelectorSequence",
197 .superclass = _Object(),
198 .instanceSize = sizeof(SelectorSequence),
199 .interfaceOffset = offsetof(SelectorSequence, interface),
200 .interfaceSize = sizeof(SelectorSequenceInterface),
202 });
203 });
204
205 return clazz;
206}
207
208#undef _Class
static View * init(View *self)
Definition Box.c:67
static bool matchesSelector(const View *self, const SimpleSelector *simpleSelector)
static SDL_Size size(const Image *self)
Definition Image.c:181
static bool matchesView(const SelectorSequence *self, const View *view)
static Array * parse(const char *rule)
static String * description(const Object *self)
static SequenceCombinator sequenceCombinator(const char *c)
Class * _SelectorSequence(void)
static void dealloc(Object *self)
static void initialize(Class *clazz)
static SelectorSequence * initWithSequence(SelectorSequence *self, const char *sequence)
The SeletorSequence type.
SequenceCombinator
Combinators are operators for chaining SelectorSequences.
@ SequenceCombinatorTerminal
@ SequenceCombinatorAdjacent
@ SequenceCombinatorNone
@ SequenceCombinatorChild
@ SequenceCombinatorDescendent
@ SequenceCombinatorSibling
Views are the fundamental building blocks of ObjectivelyMVC user interfaces.
SelectorSequences are comprised of one or more SimpleSelectors.
SequenceCombinator right
SequenceCombinator left
The combinators.
char * sequence
The sequence, as provided by the user.
bool matchesView(const SelectorSequence *self, const View *view)
Array * simpleSelectors
The SimpleSelectors comprising this SelectorSequence.
The SimpleSelector type.
Views are the fundamental building blocks of ObjectivelyMVC user interfaces.
Definition View.h:134