ObjectivelyMVC
Object oriented MVC framework for SDL3 and GNU C
Loading...
Searching...
No Matches
Selector.c File Reference
#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include <Objectively/Hash.h>
#include <Objectively/Array.h>
#include <Objectively/Set.h>
#include "Log.h"
#include "Selector.h"
#include "View.h"

Go to the source code of this file.

Data Structures

struct  Match
 A context for View matching. More...
 
struct  Selection
 A context for View selection. More...
 

Macros

#define _Class   _Selector
 

Functions

static Set * __select (View *view, Selection *selection)
 Recursively selects Views by iterating the SelectorSequences in the given Selection.
 
static void __selectEnumerator (View *view, ident data)
 ViewEnumerator adapter for __select, so it may be passed to the View::enumerate* family of methods, which require the exact ViewEnumerator signature.
 
static bool _matchesView (const View *view, Match *match)
 Recursive View match predicate, invoked directly by matchesView and indirectly, via _matchesViewEnumerator, by the View::enumerate* methods.
 
static void _matchesViewEnumerator (View *view, ident data)
 ViewEnumerator adapter for _matchesView, so it may be passed to the View::enumerate* family of methods, which require the exact ViewEnumerator signature.
 
static Set * _select (const Selector *self, View *view)
 
static void _selectFirst (Selection *selection, View *view)
 Recursively selects the first View by iterating the SelectorSequences in the given Selection.
 
static void _selectFirstEnumerator (View *view, ident data)
 ViewEnumerator adapter for _selectFirst, so it may be passed to the View::enumerate* family of methods, which require the exact ViewEnumerator signature. Note that _selectFirst's parameter order (Selection *, View *) is reversed from ViewEnumerator's (View *, ident); this adapter restores the correct order rather than relying on an incompatible raw cast.
 
Class * _Selector (void)
 
static Order compareTo (const Selector *self, const Selector *other)
 
static void dealloc (Object *self)
 
static String * description (const Object *self)
 
static void enumerateSelection (const Selector *self, View *view, ViewEnumerator enumerator, ident data)
 
static int hash (const Object *self)
 
static void initialize (Class *clazz)
 
static SelectorinitWithRule (Selector *self, const char *rule)
 
static bool isEqual (const Object *self, const Object *other)
 
static bool matchesView (const Selector *self, const View *view)
 
static Array * parse (const char *rules)
 
static ViewselectFirst (const Selector *self, View *view)
 
static int specificity (const Selector *selector)
 

Macro Definition Documentation

◆ _Class

#define _Class   _Selector

Definition at line 36 of file Selector.c.

Function Documentation

◆ __select()

static Set * __select ( View view,
Selection selection 
)
static

Recursively selects Views by iterating the SelectorSequences in the given Selection.

Definition at line 343 of file Selector.c.

343 {
344
345 const SelectorSequence *sequence = $(selection->sequences, objectAtIndex, selection->sequence);
346
347 if ($(sequence, matchesView, view)) {
348
349 switch (sequence->right) {
351 break;
352
354 selection->sequence++;
355 $(view, enumerateDescendants, __selectEnumerator, selection);
356 break;
357
359 selection->sequence++;
360 $(view, enumerateSubviews, __selectEnumerator, selection);
361 break;
362
364 selection->sequence++;
365 $(view, enumerateSiblings, __selectEnumerator, selection);
366 break;
367
369 selection->sequence++;
370 $(view, enumerateAdjacent, __selectEnumerator, selection);
371 break;
372
374 $(selection->selection, addObject, view);
375 break;
376 }
377 }
378
379 $(view, enumerateSubviews, __selectEnumerator, selection);
380
381 return (Set *) selection->selection;
382}
static void __selectEnumerator(View *view, ident data)
ViewEnumerator adapter for __select, so it may be passed to the View::enumerate* family of methods,...
Definition Selector.c:387
static bool matchesView(const Selector *self, const View *view)
Definition Selector.c:277
@ SequenceCombinatorTerminal
@ SequenceCombinatorAdjacent
@ SequenceCombinatorNone
@ SequenceCombinatorChild
@ SequenceCombinatorDescendent
@ SequenceCombinatorSibling
static void enumerateSubviews(const View *self, ViewEnumerator enumerator, ident data)
Definition View.c:846
static void enumerateAdjacent(const View *self, ViewEnumerator enumerator, ident data)
Definition View.c:762
static void enumerateSiblings(const View *self, ViewEnumerator enumerator, ident data)
Definition View.c:826
static void enumerateDescendants(const View *self, ViewEnumerator enumerator, ident data)
Definition View.c:808
const Array * sequences
Definition Selector.c:327
size_t sequence
Definition Selector.c:328
Set * selection
Definition Selector.c:329
SelectorSequences are comprised of one or more SimpleSelectors.
SequenceCombinator right

◆ __selectEnumerator()

static void __selectEnumerator ( View view,
ident  data 
)
static

ViewEnumerator adapter for __select, so it may be passed to the View::enumerate* family of methods, which require the exact ViewEnumerator signature.

See also
__selectEnumerator(View *, ident)

Definition at line 387 of file Selector.c.

387 {
388 __select(view, (Selection *) data);
389}
static Set * __select(View *view, Selection *selection)
Recursively selects Views by iterating the SelectorSequences in the given Selection.
Definition Selector.c:343
A context for View selection.
Definition Selector.c:326

◆ _matchesView()

static bool _matchesView ( const View view,
Match match 
)
static

Recursive View match predicate, invoked directly by matchesView and indirectly, via _matchesViewEnumerator, by the View::enumerate* methods.

Definition at line 227 of file Selector.c.

227 {
228
229 const SelectorSequence *sequence = $(match->sequences, objectAtIndex, match->sequence);
230
231 if ($(sequence, matchesView, view)) {
232
233 switch (sequence->left) {
235 match->match = true;
236 break;
237
239 match->sequence--;
241 break;
242
244 match->sequence--;
246 break;
247
249 match->sequence--;
251 break;
252
254 match->sequence--;
256 break;
257
259 break;
260 }
261 }
262
263 return match->match;
264}
static void _matchesViewEnumerator(View *view, ident data)
ViewEnumerator adapter for _matchesView, so it may be passed to the View::enumerate* family of method...
Definition Selector.c:269
static void enumerateAncestors(const View *self, ViewEnumerator enumerator, ident data)
Definition View.c:782
static void enumerateSuperview(const View *self, ViewEnumerator enumerator, ident data)
Definition View.c:860
bool match
Definition Selector.c:213
const Array * sequences
Definition Selector.c:211
size_t sequence
Definition Selector.c:212
SequenceCombinator left
The combinators.

◆ _matchesViewEnumerator()

static void _matchesViewEnumerator ( View view,
ident  data 
)
static

ViewEnumerator adapter for _matchesView, so it may be passed to the View::enumerate* family of methods, which require the exact ViewEnumerator signature.

See also
_matchesViewEnumerator(View *, ident)

Definition at line 269 of file Selector.c.

269 {
270 _matchesView(view, (Match *) data);
271}
static bool _matchesView(const View *view, Match *match)
Recursive View match predicate, invoked directly by matchesView and indirectly, via _matchesViewEnume...
Definition Selector.c:227
A context for View matching.
Definition Selector.c:210

◆ _select()

static Set * _select ( const Selector self,
View view 
)
static

Definition at line 395 of file Selector.c.

395 {
396
397 assert(view);
398
399 return __select(view, &(Selection) {
400 .sequences = self->sequences,
401 .selection = $$(Set, set),
402 });
403}
Array * sequences
The sequences.
Definition Selector.h:65

◆ _selectFirst()

static void _selectFirst ( Selection selection,
View view 
)
static

Recursively selects the first View by iterating the SelectorSequences in the given Selection.

Definition at line 417 of file Selector.c.

417 {
418
419 const SelectorSequence *sequence = $(selection->sequences, objectAtIndex, selection->sequence);
420
421 if ($(sequence, matchesView, view)) {
422
423 switch (sequence->right) {
425 break;
426
428 selection->sequence++;
429 $(view, enumerateDescendants, __selectEnumerator, selection);
430 break;
431
433 selection->sequence++;
434 $(view, enumerateSubviews, __selectEnumerator, selection);
435 break;
436
438 selection->sequence++;
439 $(view, enumerateSiblings, __selectEnumerator, selection);
440 break;
441
443 selection->sequence++;
444 $(view, enumerateAdjacent, __selectEnumerator, selection);
445 break;
446
448 selection->first = view;
449 return;
450 }
451 }
452
453 $(view, enumerateSubviews, _selectFirstEnumerator, selection);
454}
static void _selectFirstEnumerator(View *view, ident data)
ViewEnumerator adapter for _selectFirst, so it may be passed to the View::enumerate* family of method...
Definition Selector.c:459
View * first
Definition Selector.c:330

◆ _selectFirstEnumerator()

static void _selectFirstEnumerator ( View view,
ident  data 
)
static

ViewEnumerator adapter for _selectFirst, so it may be passed to the View::enumerate* family of methods, which require the exact ViewEnumerator signature. Note that _selectFirst's parameter order (Selection *, View *) is reversed from ViewEnumerator's (View *, ident); this adapter restores the correct order rather than relying on an incompatible raw cast.

See also
_selectFirstEnumerator(View *, ident)

Definition at line 459 of file Selector.c.

459 {
460 _selectFirst((Selection *) data, view);
461}
static void _selectFirst(Selection *selection, View *view)
Recursively selects the first View by iterating the SelectorSequences in the given Selection.
Definition Selector.c:417

◆ _Selector()

Class * _Selector ( void  )

Definition at line 504 of file Selector.c.

504 {
505 static Class *clazz;
506 static Once once;
507
508 do_once(&once, {
509 clazz = _initialize(&(const ClassDef) {
510 .name = "Selector",
511 .superclass = _Object(),
512 .instanceSize = sizeof(Selector),
513 .interfaceOffset = offsetof(Selector, interface),
514 .interfaceSize = sizeof(SelectorInterface),
516 });
517 });
518
519 return clazz;
520}
static void initialize(Class *clazz)
Definition Selector.c:484
Selectors are comprised of one or more SelectorSequences.
Definition Selector.h:49

◆ compareTo()

static Order compareTo ( const Selector self,
const Selector other 
)
static

Definition at line 151 of file Selector.c.

151 {
152
153 assert(other);
154
155 if (self->specificity < other->specificity) {
156 return OrderAscending;
157 } else if (self->specificity > other->specificity) {
158 return OrderDescending;
159 }
160
161 return OrderSame;
162}
int specificity
The specificity.
Definition Selector.h:76

◆ dealloc()

static void dealloc ( Object *  self)
static
See also
Object::dealloc(Object *)

Definition at line 43 of file Selector.c.

43 {
44
45 Selector *this = (Selector *) self;
46
47 release(this->sequences);
48 free(this->rule);
49
50 super(Object, self, dealloc);
51}
static void dealloc(Object *self)
Definition Selector.c:43

◆ description()

static String * description ( const Object *  self)
static
See also
Object::description(const Object *)

Definition at line 56 of file Selector.c.

56 {
57
58 const Selector *this = (Selector *) self;
59
60 return str(this->rule);
61}

◆ enumerateSelection()

static void enumerateSelection ( const Selector self,
View view,
ViewEnumerator  enumerator,
ident  data 
)
static

Definition at line 168 of file Selector.c.

168 {
169
170 assert(enumerator);
171
172 Set *selection = $(self, select, view);
173 assert(selection);
174
175 Array *array = $(selection, allObjects);
176 assert(array);
177
178 for (size_t i = 0; i < array->count; i++) {
179 enumerator($(array, objectAtIndex, i), data);
180 }
181
182 release(array);
183 release(selection);
184}

◆ hash()

static int hash ( const Object *  self)
static
See also
Object::hash(const Object *)

Definition at line 66 of file Selector.c.

66 {
67
68 Selector *this = (Selector *) self;
69
70 return HashForCString(HASH_SEED, this->rule);
71}

◆ initialize()

static void initialize ( Class *  clazz)
static
See also
Class::initialize(Class *)

Definition at line 484 of file Selector.c.

484 {
485
486 ((ObjectInterface *) clazz->interface)->dealloc = dealloc;
487 ((ObjectInterface *) clazz->interface)->description = description;
488 ((ObjectInterface *) clazz->interface)->hash = hash;
489 ((ObjectInterface *) clazz->interface)->isEqual = isEqual;
490
491 ((SelectorInterface *) clazz->interface)->enumerateSelection = enumerateSelection;
492 ((SelectorInterface *) clazz->interface)->compareTo = compareTo;
493 ((SelectorInterface *) clazz->interface)->initWithRule = initWithRule;
494 ((SelectorInterface *) clazz->interface)->matchesView = matchesView;
495 ((SelectorInterface *) clazz->interface)->parse = parse;
496 ((SelectorInterface *) clazz->interface)->select = _select;
497 ((SelectorInterface *) clazz->interface)->selectFirst = selectFirst;
498}
static void enumerateSelection(const Selector *self, View *view, ViewEnumerator enumerator, ident data)
Definition Selector.c:168
static bool isEqual(const Object *self, const Object *other)
Definition Selector.c:76
static Selector * initWithRule(Selector *self, const char *rule)
Definition Selector.c:190
static Set * _select(const Selector *self, View *view)
Definition Selector.c:395
static Order compareTo(const Selector *self, const Selector *other)
Definition Selector.c:151
static Array * parse(const char *rules)
Definition Selector.c:291
static String * description(const Object *self)
Definition Selector.c:56
static View * selectFirst(const Selector *self, View *view)
Definition Selector.c:467
static int hash(const Object *self)
Definition Selector.c:66
bool matchesView(const Selector *self, View *view)

◆ initWithRule()

static Selector * initWithRule ( Selector self,
const char *  rule 
)
static

Definition at line 190 of file Selector.c.

190 {
191
192 self = (Selector *) super(Object, self, init);
193 if (self) {
194
195 self->rule = strtrim(rule);
196 assert(self->rule);
197
198 self->sequences = $$(SelectorSequence, parse, self->rule);
199 assert(self->sequences->count);
200
201 self->specificity = specificity(self);
202 }
203
204 return self;
205}
static View * init(View *self)
Definition Box.c:67
static int specificity(const Selector *selector)
Definition Selector.c:98
char * rule
The rule, as provided by the user.
Definition Selector.h:70

◆ isEqual()

static bool isEqual ( const Object *  self,
const Object *  other 
)
static
See also
Object::isEqual(const Object *, const Object *)

Definition at line 76 of file Selector.c.

76 {
77
78 if (super(Object, self, isEqual, other)) {
79 return true;
80 }
81
82 if (other && $(other, isKindOfClass, _Selector())) {
83
84 const Selector *this = (Selector *) self;
85 const Selector *that = (Selector *) other;
86
87 return strcmp(this->rule, that->rule) == 0;
88 }
89
90 return false;
91}
Class * _Selector(void)
Definition Selector.c:504

◆ matchesView()

static bool matchesView ( const Selector self,
const View view 
)
static

Definition at line 277 of file Selector.c.

277 {
278
279 assert(view);
280
281 return _matchesView(view, &(Match) {
282 .sequences = self->sequences,
283 .sequence = self->sequences->count - 1
284 });
285}

◆ parse()

static Array * parse ( const char *  rules)
static

Definition at line 291 of file Selector.c.

291 {
292
293 Array *selectors = $$(Array, arrayWithCapacity, 4);
294 assert(selectors);
295
296 if (rules) {
297
298 const char *c = rules;
299 while (*c) {
300 const size_t size = strcspn(c, ",");
301 if (size) {
302 char *rule = calloc(1, size + 1);
303 assert(rule);
304
305 strncpy(rule, c, size);
306
307 Selector *selector = $(alloc(Selector), initWithRule, rule);
308 assert(selector);
309
310 $(selectors, addObject, selector);
311
312 release(selector);
313 free(rule);
314 }
315 c += size;
316 c += strspn(c, ", \t\n");
317 }
318 }
319
320 return (Array *) selectors;
321}
static SDL_Size size(const Image *self)
Definition Image.c:181

◆ selectFirst()

static View * selectFirst ( const Selector self,
View view 
)
static

Definition at line 467 of file Selector.c.

467 {
468
469 assert(view);
470
471 Selection selection = {
472 .sequences = self->sequences,
473 };
474
475 _selectFirst(&selection, view);
476 return selection.first;
477}

◆ specificity()

static int specificity ( const Selector selector)
static
Returns
The specificity of the given Selector.

Definition at line 98 of file Selector.c.

98 {
99
100 int specificity = 0;
101
102 for (size_t i = 0; i < selector->sequences->count; i++) {
103 SelectorSequence *sequence = $(selector->sequences, objectAtIndex, i);
104
105 for (size_t j = 0; j < sequence->simpleSelectors->count; j++) {
106 SimpleSelector *simpleSelector = $(sequence->simpleSelectors, objectAtIndex, j);
107
108 switch (simpleSelector->type) {
110 specificity += 100;
111 break;
114 specificity += 10;
115 break;
117 specificity += 1;
118 Class *clazz = classForName(simpleSelector->pattern);
119 if (clazz) {
120 while (clazz) {
121 if (clazz == _View()) {
122 break;
123 }
124 specificity += 1;
125 clazz = clazz->def.superclass;
126 }
127 if (clazz != _View()) {
128 MVC_LogError("Class `%s` in Selector `%s` does not extend View\n",
129 simpleSelector->pattern, selector->rule);
130 }
131 } else {
132 MVC_LogWarn("Class `%s` in Selector `%s` not found\n",
133 simpleSelector->pattern, selector->rule);
134 }
135
136 break;
137 }
138 default:
139 break;
140 }
141 }
142 }
143
144 return specificity;
145}
#define MVC_LogWarn(fmt,...)
Definition Log.h:54
#define MVC_LogError(fmt,...)
Definition Log.h:57
@ SimpleSelectorTypePseudo
@ SimpleSelectorTypeId
@ SimpleSelectorTypeClass
@ SimpleSelectorTypeType
Class * _View(void)
Definition View.c:2067
Array * simpleSelectors
The SimpleSelectors comprising this SelectorSequence.
The SimpleSelector type.
SimpleSelectorType type
The SimpleSelectorType.
char * pattern
The pattern, as provided by the user.