summaryrefslogtreecommitdiffabout
path: root/libical/src/libicalss/icalgauge.c
Unidiff
Diffstat (limited to 'libical/src/libicalss/icalgauge.c') (more/less context) (ignore whitespace changes)
-rw-r--r--libical/src/libicalss/icalgauge.c447
1 files changed, 447 insertions, 0 deletions
diff --git a/libical/src/libicalss/icalgauge.c b/libical/src/libicalss/icalgauge.c
new file mode 100644
index 0000000..b958ecf
--- a/dev/null
+++ b/libical/src/libicalss/icalgauge.c
@@ -0,0 +1,447 @@
1/* -*- Mode: C -*- */
2/*======================================================================
3 FILE: icalgauge.c
4 CREATOR: eric 23 December 1999
5
6
7 $Id$
8 $Locker$
9
10 (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org
11
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of either:
14
15 The LGPL as published by the Free Software Foundation, version
16 2.1, available at: http://www.fsf.org/copyleft/lesser.html
17
18 Or:
19
20 The Mozilla Public License Version 1.0. You may obtain a copy of
21 the License at http://www.mozilla.org/MPL/
22
23 The Original Code is eric. The Initial Developer of the Original
24 Code is Eric Busboom
25
26
27======================================================================*/
28
29#include "ical.h"
30#include "icalgauge.h"
31#include "icalgaugeimpl.h"
32#include <stdlib.h>
33
34extern char* input_buffer;
35extern char* input_buffer_p;
36int ssparse(void);
37
38struct icalgauge_impl *icalss_yy_gauge;
39
40icalgauge* icalgauge_new_from_sql(char* sql)
41{
42 struct icalgauge_impl *impl;
43
44 int r;
45
46 if ( ( impl = (struct icalgauge_impl*)
47 malloc(sizeof(struct icalgauge_impl))) == 0) {
48 icalerror_set_errno(ICAL_NEWFAILED_ERROR);
49 return 0;
50 }
51
52 impl->select = pvl_newlist();
53 impl->from = pvl_newlist();
54 impl->where = pvl_newlist();
55
56 icalss_yy_gauge = impl;
57
58 input_buffer_p = input_buffer = sql;
59 r = ssparse();
60
61 return impl;
62}
63
64
65void icalgauge_free(icalgauge* gauge)
66{
67 struct icalgauge_impl *impl = (struct icalgauge_impl*)gauge;
68 struct icalgauge_where *w;
69
70 assert(impl->select != 0);
71 assert(impl->where != 0);
72 assert(impl->from != 0);
73
74 if(impl->select){
75 while( (w=pvl_pop(impl->select)) != 0){
76 if(w->value != 0){
77 free(w->value);
78 }
79 free(w);
80 }
81 pvl_free(impl->select);
82 }
83
84 if(impl->where){
85 while( (w=pvl_pop(impl->where)) != 0){
86
87 if(w->value != 0){
88 free(w->value);
89 }
90 free(w);
91 }
92 pvl_free(impl->where);
93 }
94
95 if(impl->from){
96 pvl_free(impl->from);
97 }
98
99}
100
101/* Convert a VQUERY component into a gauge */
102icalcomponent* icalgauge_make_gauge(icalcomponent* query);
103
104/* icaldirset_test compares a component against a gauge, and returns
105 true if the component passes the test
106
107 The gauge is a VCALENDAR component that specifies how to test the
108 target components. The guage holds a collection of VEVENT, VTODO or
109 VJOURNAL sub-components. Each of the sub-components has a
110 collection of properties that are compared to corresponding
111 properties in the target component, according to the
112 X-LIC-COMPARETYPE parameters to the gauge's properties.
113
114 When a gauge has several sub-components, the results of testing the
115 target against each of them is ORed together - the target
116 component will pass if it matches any of the sub-components in the
117 gauge. However, the results of matching the properties in a
118 sub-component are ANDed -- the target must match every property in
119 a gauge sub-component to match the sub-component.
120
121 Here is an example:
122
123 BEGIN:XROOT
124 DTSTART;X-LIC-COMPARETYPE=LESS:19981025T020000
125 ORGANIZER;X-LIC-COMPARETYPE=EQUAL:mrbig@host.com
126 END:XROOT
127 BEGIN:XROOT
128 LOCATION;X-LIC-COMPARETYPE=EQUAL:McNary's Pub
129 END:XROOT
130
131 This gauge has two sub-components; one which will match a VEVENT
132 based on start time, and organizer, and another that matches based
133 on LOCATION. A target component will pass the test if it matched
134 either of the sub-components.
135
136 */
137
138
139int icalgauge_compare_recurse(icalcomponent* comp, icalcomponent* gauge)
140{
141 int pass = 1,localpass = 0;
142 icalproperty *p;
143 icalcomponent *child,*subgauge;
144 icalcomponent_kind gaugekind, compkind;
145
146 icalerror_check_arg_rz( (comp!=0), "comp");
147 icalerror_check_arg_rz( (gauge!=0), "gauge");
148
149 gaugekind = icalcomponent_isa(gauge);
150 compkind = icalcomponent_isa(comp);
151
152 if( ! (gaugekind == compkind || gaugekind == ICAL_ANY_COMPONENT) ){
153 return 0;
154 }
155
156 /* Test properties. For each property in the gauge, search through
157 the component for a similar property. If one is found, compare
158 the two properties value with the comparison specified in the
159 gauge with the X-LIC-COMPARETYPE parameter */
160
161 for(p = icalcomponent_get_first_property(gauge,ICAL_ANY_PROPERTY);
162 p != 0;
163 p = icalcomponent_get_next_property(gauge,ICAL_ANY_PROPERTY)){
164
165 icalproperty* targetprop;
166 icalparameter* compareparam;
167 icalparameter_xliccomparetype compare;
168 int rel; /* The relationship between the gauge and target values.*/
169
170 /* Extract the comparison type from the gauge. If there is no
171 comparison type, assume that it is "EQUAL" */
172
173 compareparam = icalproperty_get_first_parameter(
174 p,
175 ICAL_XLICCOMPARETYPE_PARAMETER);
176
177 if (compareparam!=0){
178 compare = icalparameter_get_xliccomparetype(compareparam);
179 } else {
180 compare = ICAL_XLICCOMPARETYPE_EQUAL;
181 }
182
183 /* Find a property in the component that has the same type
184 as the gauge property. HACK -- multiples of a single
185 property type in the gauge will match only the first
186 instance in the component */
187
188 targetprop = icalcomponent_get_first_property(comp,
189 icalproperty_isa(p));
190
191 if(targetprop != 0){
192
193 /* Compare the values of the gauge property and the target
194 property */
195
196 rel = icalvalue_compare(icalproperty_get_value(p),
197 icalproperty_get_value(targetprop));
198
199 /* Now see if the comparison is equavalent to the comparison
200 specified in the gauge */
201
202 if (rel == compare){
203 localpass++;
204 } else if (compare == ICAL_XLICCOMPARETYPE_LESSEQUAL &&
205 ( rel == ICAL_XLICCOMPARETYPE_LESS ||
206 rel == ICAL_XLICCOMPARETYPE_EQUAL)) {
207 localpass++;
208 } else if (compare == ICAL_XLICCOMPARETYPE_GREATEREQUAL &&
209 ( rel == ICAL_XLICCOMPARETYPE_GREATER ||
210 rel == ICAL_XLICCOMPARETYPE_EQUAL)) {
211 localpass++;
212 } else if (compare == ICAL_XLICCOMPARETYPE_NOTEQUAL &&
213 ( rel == ICAL_XLICCOMPARETYPE_GREATER ||
214 rel == ICAL_XLICCOMPARETYPE_LESS)) {
215 localpass++;
216 } else {
217 localpass = 0;
218 }
219
220 pass = pass && (localpass>0);
221 }
222 }
223
224 /* Test subcomponents. Look for a child component that has a
225 counterpart in the gauge. If one is found, recursively call
226 icaldirset_test */
227
228 for(subgauge = icalcomponent_get_first_component(gauge,ICAL_ANY_COMPONENT);
229 subgauge != 0;
230 subgauge = icalcomponent_get_next_component(gauge,ICAL_ANY_COMPONENT)){
231
232 gaugekind = icalcomponent_isa(subgauge);
233
234 if (gaugekind == ICAL_ANY_COMPONENT){
235 child = icalcomponent_get_first_component(comp,ICAL_ANY_COMPONENT);
236 } else {
237 child = icalcomponent_get_first_component(comp,gaugekind);
238 }
239
240 if(child !=0){
241 localpass = icalgauge_compare_recurse(child,subgauge);
242 pass = pass && localpass;
243 } else {
244 pass = 0;
245 }
246 }
247
248 return pass;
249}
250
251
252int icalgauge_compare(icalgauge* gauge,icalcomponent* comp)
253{
254
255 struct icalgauge_impl *impl = (struct icalgauge_impl*)gauge;
256 icalcomponent *inner;
257 int local_pass = 0;
258 int last_clause = 1, this_clause = 1;
259 pvl_elem e;
260
261 icalerror_check_arg_rz( (comp!=0), "comp");
262 icalerror_check_arg_rz( (gauge!=0), "gauge");
263
264 inner = icalcomponent_get_first_real_component(comp);
265
266 if(inner == 0){
267 icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR);
268 return 0;
269 }
270
271
272 /* Check that this component is one of the FROM types */
273 local_pass = 0;
274 for(e = pvl_head(impl->from);e!=0;e=pvl_next(e)){
275 icalcomponent_kind k = (icalcomponent_kind)pvl_data(e);
276
277 if(k == icalcomponent_isa(inner)){
278 local_pass=1;
279 }
280 }
281
282 if(local_pass == 0){
283 return 0;
284 }
285
286
287 /* Check each where clause against the component */
288 for(e = pvl_head(impl->where);e!=0;e=pvl_next(e)){
289 struct icalgauge_where *w = pvl_data(e);
290 icalcomponent *sub_comp;
291 icalvalue *v;
292 icalproperty *prop;
293 icalvalue_kind vk;
294
295 if(w->prop == ICAL_NO_PROPERTY || w->value == 0){
296 icalerror_set_errno(ICAL_INTERNAL_ERROR);
297 return 0;
298 }
299
300 /* First, create a value from the gauge */
301 vk = icalenum_property_kind_to_value_kind(w->prop);
302
303 if(vk == ICAL_NO_VALUE){
304 icalerror_set_errno(ICAL_INTERNAL_ERROR);
305 return 0;
306 }
307
308 v = icalvalue_new_from_string(vk,w->value);
309
310 if (v == 0){
311 /* Keep error set by icalvalue_from-string*/
312 return 0;
313 }
314
315 /* Now find the corresponding property in the component,
316 descending into a sub-component if necessary */
317
318 if(w->comp == ICAL_NO_COMPONENT){
319 sub_comp = inner;
320 } else {
321 sub_comp = icalcomponent_get_first_component(inner,w->comp);
322 if(sub_comp == 0){
323 return 0;
324 }
325 }
326
327 this_clause = 0;
328 local_pass = 0;
329 for(prop = icalcomponent_get_first_property(sub_comp,w->prop);
330 prop != 0;
331 prop = icalcomponent_get_next_property(sub_comp,w->prop)){
332 icalvalue* prop_value;
333 icalgaugecompare relation;
334
335 prop_value = icalproperty_get_value(prop);
336
337 relation = (icalgaugecompare)icalvalue_compare(prop_value,v);
338
339 if (relation == w->compare){
340 local_pass++;
341 } else if (w->compare == ICALGAUGECOMPARE_LESSEQUAL &&
342 ( relation == ICALGAUGECOMPARE_LESS ||
343 relation == ICALGAUGECOMPARE_EQUAL)) {
344 local_pass++;
345 } else if (w->compare == ICALGAUGECOMPARE_GREATEREQUAL &&
346 ( relation == ICALGAUGECOMPARE_GREATER ||
347 relation == ICALGAUGECOMPARE_EQUAL)) {
348 local_pass++;
349 } else if (w->compare == ICALGAUGECOMPARE_NOTEQUAL &&
350 ( relation == ICALGAUGECOMPARE_GREATER ||
351 relation == ICALGAUGECOMPARE_LESS)) {
352 local_pass++;
353 } else {
354 local_pass = 0;
355 }
356 }
357
358 this_clause = local_pass > 0 ? 1 : 0;
359
360 /* Now look at the logic operator for this clause to see how
361 the value should be merge with the previous clause */
362
363 if(w->logic == ICALGAUGELOGIC_AND){
364 last_clause = this_clause && last_clause;
365 } else if(w->logic == ICALGAUGELOGIC_AND) {
366 last_clause = this_clause || last_clause;
367 } else {
368 last_clause = this_clause;
369 }
370 }
371
372 return last_clause;
373
374}
375
376
377void icalgauge_dump(icalcomponent* gauge)
378{
379
380 pvl_elem *p;
381 struct icalgauge_impl *impl = (struct icalgauge_impl*)gauge;
382
383
384 printf("--- Select ---\n");
385 for(p = pvl_head(impl->select);p!=0;p=pvl_next(p)){
386 struct icalgauge_where *w = pvl_data(p);
387
388 if(w->comp != ICAL_NO_COMPONENT){
389 printf("%s ",icalenum_component_kind_to_string(w->comp));
390 }
391
392 if(w->prop != ICAL_NO_PROPERTY){
393 printf("%s ",icalenum_property_kind_to_string(w->prop));
394 }
395
396 if (w->compare != ICALGAUGECOMPARE_NONE){
397 printf("%d ",w->compare);
398 }
399
400
401 if (w->value!=0){
402 printf("%s",w->value);
403 }
404
405
406 printf("\n");
407 }
408
409 printf("--- From ---\n");
410 for(p = pvl_head(impl->from);p!=0;p=pvl_next(p)){
411 icalcomponent_kind k = (icalcomponent_kind)pvl_data(p);
412
413 printf("%s\n",icalenum_component_kind_to_string(k));
414 }
415
416 printf("--- Where ---\n");
417 for(p = pvl_head(impl->where);p!=0;p=pvl_next(p)){
418 struct icalgauge_where *w = pvl_data(p);
419
420 if(w->logic != ICALGAUGELOGIC_NONE){
421 printf("%d ",w->logic);
422 }
423
424 if(w->comp != ICAL_NO_COMPONENT){
425 printf("%s ",icalenum_component_kind_to_string(w->comp));
426 }
427
428 if(w->prop != ICAL_NO_PROPERTY){
429 printf("%s ",icalenum_property_kind_to_string(w->prop));
430 }
431
432 if (w->compare != ICALGAUGECOMPARE_NONE){
433 printf("%d ",w->compare);
434 }
435
436
437 if (w->value!=0){
438 printf("%s",w->value);
439 }
440
441
442 printf("\n");
443 }
444
445
446}
447