Libical API Documentation 4.0 UNRELEASED Go to the stable 3.0 documentation
Loading...
Searching...
No Matches
icalgauge.c
Go to the documentation of this file.
1/*======================================================================
2 FILE: icalgauge.c
3 CREATOR: eric 23 December 1999
4
5 SPDX-FileCopyrightText: 2000, Eric Busboom <eric@civicknowledge.com>
6 SPDX-License-Identifier: LGPL-2.1-only OR MPL-2.0
7
8 The Original Code is eric. The Initial Developer of the Original
9 Code is Eric Busboom
10======================================================================*/
11
16
17#ifdef HAVE_CONFIG_H
18#include <config.h>
19#endif
20
21#include "icalgauge.h"
22#include "icalgaugeimpl.h"
23#include "icalerror_p.h"
24#include "icalpvl_p.h"
25#include "icalvalue.h"
26
27#include <stddef.h> /* for ptrdiff_t */
28#include <stdlib.h>
29
31extern int ssparse(void);
32extern char *input_buffer;
33extern char *input_buffer_p;
34
35struct icalgauge_impl *icalss_yy_gauge;
37
38icalgauge *icalgauge_new_from_sql(const char *sql, int expand)
39{
40 struct icalgauge_impl *impl;
41 int r;
42
43 if ((impl = (struct icalgauge_impl *)malloc(sizeof(struct icalgauge_impl))) == 0) {
45 return 0;
46 }
47
48 impl->select = icalpvl_newlist();
49 impl->from = icalpvl_newlist();
50 impl->where = icalpvl_newlist();
51 impl->expand = expand;
52
53 icalss_yy_gauge = impl;
54 input_buffer = input_buffer_p = (char *)sql;
55
56 r = ssparse();
57
58 if (r == 0) {
59 return impl;
60 } else {
61 icalgauge_free(impl);
62 return NULL;
63 }
64}
65
66int icalgauge_get_expand(const icalgauge *gauge)
67{
68 icalerror_check_arg_rz((gauge != 0), "gauge");
69 return gauge->expand;
70}
71
72void icalgauge_free(icalgauge *gauge)
73{
74 struct icalgauge_where *w;
75
76 assert(gauge->select != 0);
77 assert(gauge->where != 0);
78 assert(gauge->from != 0);
79
80 if (gauge->select) {
81 while ((w = icalpvl_pop(gauge->select)) != 0) {
82 if (w->value != 0) {
83 free(w->value);
84 }
85 free(w);
86 }
87 icalpvl_free(gauge->select);
88 gauge->select = 0;
89 }
90
91 if (gauge->where) {
92 while ((w = icalpvl_pop(gauge->where)) != 0) {
93 if (w->value != 0) {
94 free(w->value);
95 }
96 free(w);
97 }
98 icalpvl_free(gauge->where);
99 gauge->where = 0;
100 }
101
102 if (gauge->from) {
103 icalpvl_free(gauge->from);
104 gauge->from = 0;
105 }
106
107 free(gauge);
108}
109
111/*non-static,recursive*/
112int icalgauge_compare_recurse(icalcomponent *comp, icalcomponent *gauge)
113{
114 int pass = 1, localpass = 0;
115 icalproperty *p;
116 icalcomponent *child, *subgauge;
117 icalcomponent_kind gaugekind, compkind;
118
119 icalerror_check_arg_rz((comp != 0), "comp");
120 icalerror_check_arg_rz((gauge != 0), "gauge");
121
122 gaugekind = icalcomponent_isa(gauge);
123 compkind = icalcomponent_isa(comp);
124
125 if (!(gaugekind == compkind || gaugekind == ICAL_ANY_COMPONENT)) {
126 return 0;
127 }
128
129 /* Test properties. For each property in the gauge, search through
130 the component for a similar property. If one is found, compare
131 the two properties value with the comparison specified in the
132 gauge with the X-LIC-COMPARETYPE parameter */
133
134 for (p = icalcomponent_get_first_property(gauge, ICAL_ANY_PROPERTY);
135 p != 0;
136 p = icalcomponent_get_next_property(gauge, ICAL_ANY_PROPERTY)) {
137 icalproperty *targetprop;
138 icalparameter *compareparam;
139 icalparameter_xliccomparetype compare;
140
141 /* Extract the comparison type from the gauge. If there is no
142 comparison type, assume that it is "EQUAL" */
143
144 compareparam = icalproperty_get_first_parameter(p, ICAL_XLICCOMPARETYPE_PARAMETER);
145
146 if (compareparam != 0) {
147 compare = icalparameter_get_xliccomparetype(compareparam);
148 } else {
149 compare = ICAL_XLICCOMPARETYPE_EQUAL;
150 }
151
152 /* Find a property in the component that has the same type
153 as the gauge property. HACK -- multiples of a single
154 property type in the gauge will match only the first
155 instance in the component */
156
158
159 if (targetprop != 0) {
160 /* Compare the values of the gauge property and the target
161 property */
162
163 /* The relationship between the gauge and target values */
164 icalparameter_xliccomparetype rel = icalvalue_compare(icalproperty_get_value(p), icalproperty_get_value(targetprop));
165
166 /* Now see if the comparison is equivalent to the comparison
167 specified in the gauge */
168
169 if (rel == ICAL_XLICCOMPARETYPE_NONE || compare == ICAL_XLICCOMPARETYPE_NONE) {
170 localpass = 0;
171 } else if (rel == compare) {
172 localpass++;
173 } else if (compare == ICAL_XLICCOMPARETYPE_LESSEQUAL &&
174 (rel == ICAL_XLICCOMPARETYPE_LESS || rel == ICAL_XLICCOMPARETYPE_EQUAL)) {
175 localpass++;
176 } else if (compare == ICAL_XLICCOMPARETYPE_GREATEREQUAL &&
177 (rel == ICAL_XLICCOMPARETYPE_GREATER || rel == ICAL_XLICCOMPARETYPE_EQUAL)) {
178 localpass++;
179 } else if (compare == ICAL_XLICCOMPARETYPE_NOTEQUAL &&
180 (rel == ICAL_XLICCOMPARETYPE_GREATER || rel == ICAL_XLICCOMPARETYPE_LESS)) {
181 localpass++;
182 } else {
183 localpass = 0;
184 }
185
186 pass = pass && (localpass > 0);
187 }
188 }
189
190 /* Test subcomponents. Look for a child component that has a
191 counterpart in the gauge. */
192
194 subgauge != 0;
196 gaugekind = icalcomponent_isa(subgauge);
197
198 if (gaugekind == ICAL_ANY_COMPONENT) {
200 } else {
201 child = icalcomponent_get_first_component(comp, gaugekind);
202 }
203
204 if (child != 0) {
205 localpass = icalgauge_compare_recurse(child, subgauge);
206 pass = pass && localpass;
207 } else {
208 pass = 0;
209 }
210 }
211
212 return pass;
213}
215
216bool icalgauge_compare(icalgauge *gauge, icalcomponent *comp)
217{
218 icalcomponent *inner;
219 int local_pass = 0;
220 bool last_clause = true;
221 icalpvl_elem e;
222 int compare_recur = 0;
223
224 icalerror_check_arg_rz((comp != 0), "comp");
225 icalerror_check_arg_rz((gauge != 0), "gauge");
226
228
229 if (inner == 0) {
230 /* Wally Yau: our component is not always wrapped with
231 * a <VCALENDAR>. It's not an error.
232 * icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR);
233 * return false; */
235 if (kind == ICAL_VEVENT_COMPONENT ||
236 kind == ICAL_VTODO_COMPONENT ||
237 kind == ICAL_VJOURNAL_COMPONENT ||
239 inner = comp;
240 } else {
242 return false;
243 }
244 }
245
246 /* Check that this component is one of the FROM types */
247 local_pass = 0;
248 for (e = icalpvl_head(gauge->from); e != 0; e = icalpvl_next(e)) {
249 icalcomponent_kind k = (icalcomponent_kind)(ptrdiff_t)icalpvl_data(e);
250
251 if (k == icalcomponent_isa(inner)) {
252 local_pass = 1;
253 }
254 }
255
256 if (local_pass == 0) {
257 return false;
258 }
259
260 /**** Check each where clause against the component ****/
261 for (e = icalpvl_head(gauge->where); e != 0; e = icalpvl_next(e)) {
262 struct icalgauge_where *w = icalpvl_data(e);
263 icalcomponent *sub_comp;
264 icalvalue *v;
265 icalproperty *prop;
266 icalvalue_kind vk;
267
268 if (!w || w->prop == ICAL_NO_PROPERTY || w->value == 0) {
270 return false;
271 }
272
273 /* First, create a value from the gauge */
275
276 if (vk == ICAL_NO_VALUE) {
278 return false;
279 }
280
281 if (w->compare == ICALGAUGECOMPARE_ISNULL || w->compare == ICALGAUGECOMPARE_ISNOTNULL) {
282 v = icalvalue_new(vk);
283 } else {
284 v = icalvalue_new_from_string(vk, w->value);
285 }
286
287 if (v == 0) {
288 /* Keep error set by icalvalue_from-string */
289 return false;
290 }
291
292 /* Now find the corresponding property in the component,
293 descending into a sub-component if necessary */
294
295 if (w->comp == ICAL_NO_COMPONENT) {
296 sub_comp = inner;
297 } else {
298 sub_comp = icalcomponent_get_first_component(inner, w->comp);
299 if (sub_comp == 0) {
301 return false;
302 }
303 }
304
305 /* check if it is a recurring */
306 const icalproperty *rrule = icalcomponent_get_first_property(sub_comp, ICAL_RRULE_PROPERTY);
307
308 if (gauge->expand && rrule) {
309 if (w->prop == ICAL_DTSTART_PROPERTY ||
310 w->prop == ICAL_DTEND_PROPERTY || w->prop == ICAL_DUE_PROPERTY) {
312 compare_recur = 1;
313 }
314 }
315
316 local_pass = (w->compare == ICALGAUGECOMPARE_ISNULL) ? 1 : 0;
317
318 for (prop = icalcomponent_get_first_property(sub_comp, w->prop);
319 prop != 0;
320 prop = icalcomponent_get_next_property(sub_comp, w->prop)) {
321 icalvalue *prop_value;
322 icalgaugecompare relation;
323
324 if (w->compare == ICALGAUGECOMPARE_ISNULL) {
325 local_pass = 0;
326 break;
327 }
328
329 if (w->compare == ICALGAUGECOMPARE_ISNOTNULL) {
330 local_pass = 1;
331 break;
332 }
333
334 if (compare_recur) {
335 icalproperty *p =
336 icalcomponent_get_first_property(sub_comp, ICAL_RECURRENCEID_PROPERTY);
337 prop_value = icalproperty_get_value(p);
338 } else { /* prop value from this component */
339 prop_value = icalproperty_get_value(prop);
340 }
341
342 relation = (icalgaugecompare)icalvalue_compare(prop_value, v);
343
344 if (relation == w->compare) {
345 local_pass++;
346 } else if (w->compare == ICALGAUGECOMPARE_LESSEQUAL &&
347 (relation == ICALGAUGECOMPARE_LESS || relation == ICALGAUGECOMPARE_EQUAL)) {
348 local_pass++;
349 } else if (w->compare == ICALGAUGECOMPARE_GREATEREQUAL &&
350 (relation == ICALGAUGECOMPARE_GREATER ||
351 relation == ICALGAUGECOMPARE_EQUAL)) {
352 local_pass++;
353 } else if (w->compare == ICALGAUGECOMPARE_NOTEQUAL &&
354 (relation == ICALGAUGECOMPARE_GREATER ||
355 relation == ICALGAUGECOMPARE_LESS)) {
356 local_pass++;
357 } else {
358 local_pass = 0;
359 }
360 }
361
362 bool this_clause = (local_pass > 0);
363
364 /* Now look at the logic operator for this clause to see how
365 the value should be merge with the previous clause */
366
367 if (w->logic == ICALGAUGELOGIC_AND) {
368 last_clause = this_clause && last_clause;
369 } else if (w->logic == ICALGAUGELOGIC_OR) {
370 last_clause = this_clause || last_clause;
371 } else {
372 last_clause = this_clause;
373 }
374
376
377 } /**** check next one in where clause ****/
378
379 return last_clause;
380}
381
382void icalgauge_dump(icalgauge *gauge)
383{
384 icalpvl_elem p;
385
386 printf("--- Select ---\n");
387 for (p = icalpvl_head(gauge->select); p != 0; p = icalpvl_next(p)) {
388 struct icalgauge_where *w = icalpvl_data(p);
389
390 if (!w) {
391 continue;
392 }
393
394 if (w->comp != ICAL_NO_COMPONENT) {
395 printf("%s ", icalcomponent_kind_to_string(w->comp));
396 }
397
398 if (w->prop != ICAL_NO_PROPERTY) {
399 printf("%s ", icalproperty_kind_to_string(w->prop));
400 }
401
402 if (w->compare != ICALGAUGECOMPARE_NONE) {
403 printf("%d ", w->compare);
404 }
405
406 if (w->value != 0) {
407 printf("%s", w->value);
408 }
409
410 printf("\n");
411 }
412
413 printf("--- From ---\n");
414 for (p = icalpvl_head(gauge->from); p != 0; p = icalpvl_next(p)) {
415 icalcomponent_kind k = (icalcomponent_kind)(ptrdiff_t)icalpvl_data(p);
416
417 printf("%s\n", icalcomponent_kind_to_string(k));
418 }
419
420 printf("--- Where ---\n");
421 for (p = icalpvl_head(gauge->where); p != 0; p = icalpvl_next(p)) {
422 struct icalgauge_where *w = icalpvl_data(p);
423
424 if (!w) {
425 continue;
426 }
427
428 if (w->logic != ICALGAUGELOGIC_NONE) {
429 printf("%d ", w->logic);
430 }
431
432 if (w->comp != ICAL_NO_COMPONENT) {
433 printf("%s ", icalcomponent_kind_to_string(w->comp));
434 }
435
436 if (w->prop != ICAL_NO_PROPERTY) {
437 printf("%s ", icalproperty_kind_to_string(w->prop));
438 }
439
440 if (w->compare != ICALGAUGECOMPARE_NONE) {
441 printf("%d ", w->compare);
442 }
443
444 if (w->value != 0) {
445 printf("%s", w->value);
446 }
447
448 printf("\n");
449 }
450}
icalproperty * icalcomponent_get_first_property(icalcomponent *c, icalproperty_kind kind)
icalcomponent * icalcomponent_get_next_component(icalcomponent *c, icalcomponent_kind kind)
icalcomponent * icalcomponent_get_first_component(icalcomponent *c, icalcomponent_kind kind)
const char * icalcomponent_kind_to_string(icalcomponent_kind kind)
icalcomponent * icalcomponent_get_first_real_component(const icalcomponent *c)
icalcomponent_kind icalcomponent_isa(const icalcomponent *component)
icalproperty * icalcomponent_get_next_property(icalcomponent *c, icalproperty_kind kind)
icalcomponent_kind
Definition icalenums.h:29
@ ICAL_NO_COMPONENT
Definition icalenums.h:30
@ ICAL_VTODO_COMPONENT
Definition icalenums.h:35
@ ICAL_VEVENT_COMPONENT
Definition icalenums.h:34
@ ICAL_VAGENDA_COMPONENT
Definition icalenums.h:38
@ ICAL_ANY_COMPONENT
Definition icalenums.h:31
@ ICAL_VJOURNAL_COMPONENT
Definition icalenums.h:36
@ ICAL_VQUERY_COMPONENT
Definition icalenums.h:50
void icalerror_set_errno(icalerrorenum x)
Sets the icalerrno to a given error.
Definition icalerror.c:90
@ ICAL_NEWFAILED_ERROR
Definition icalerror.h:50
@ ICAL_INTERNAL_ERROR
Definition icalerror.h:62
@ ICAL_MALFORMEDDATA_ERROR
Definition icalerror.h:56
bool icalgauge_compare(icalgauge *gauge, icalcomponent *comp)
Definition icalgauge.c:216
void icalgauge_free(icalgauge *gauge)
Definition icalgauge.c:72
void icalgauge_dump(icalgauge *gauge)
Definition icalgauge.c:382
int icalgauge_get_expand(const icalgauge *gauge)
Definition icalgauge.c:66
icalgauge * icalgauge_new_from_sql(const char *sql, int expand)
Definition icalgauge.c:38
Routines implementing a filter for ical components.
icalvalue * icalproperty_get_value(const icalproperty *prop)
icalproperty_kind icalproperty_isa(const icalproperty *p)
icalparameter * icalproperty_get_first_parameter(icalproperty *p, icalparameter_kind kind)
icalvalue_kind icalproperty_kind_to_value_kind(icalproperty_kind kind)
const char * icalproperty_kind_to_string(icalproperty_kind kind)
icalvalue * icalvalue_new_from_string(icalvalue_kind kind, const char *str)
Definition icalvalue.c:788
icalparameter_xliccomparetype icalvalue_compare(const icalvalue *a, const icalvalue *b)
Definition icalvalue.c:1353
icalvalue * icalvalue_new(icalvalue_kind kind)
Definition icalvalue.c:60
void icalvalue_free(icalvalue *v)
Definition icalvalue.c:793
Defines the data structure representing iCalendar parameter values.