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.c172
1 files changed, 127 insertions, 45 deletions
diff --git a/libical/src/libicalss/icalgauge.c b/libical/src/libicalss/icalgauge.c
index b958ecf..f4854c7 100644
--- a/libical/src/libicalss/icalgauge.c
+++ b/libical/src/libicalss/icalgauge.c
@@ -28,87 +28,111 @@
28 28
29#include "ical.h" 29#include "ical.h"
30#include "icalgauge.h" 30#include "icalgauge.h"
31#include "icalgaugeimpl.h" 31#include "icalgaugeimpl.h"
32#include <stdlib.h> 32#include <stdlib.h>
33 33
34extern char* input_buffer; 34#include "icalssyacc.h"
35extern char* input_buffer_p;
36int ssparse(void);
37 35
38struct icalgauge_impl *icalss_yy_gauge; 36typedef void* yyscan_t;
39 37
40icalgauge* icalgauge_new_from_sql(char* sql) 38int ssparse(yyscan_t );
39
40
41icalgauge* icalgauge_new_from_sql(char* sql, int expand)
41{ 42{
42 struct icalgauge_impl *impl; 43 struct icalgauge_impl *impl;
44 yyscan_t yy_globals = NULL;
43 45
44 int r; 46 int r;
45 47
46 if ( ( impl = (struct icalgauge_impl*) 48 if ( ( impl = (struct icalgauge_impl*)
47 malloc(sizeof(struct icalgauge_impl))) == 0) { 49 malloc(sizeof(struct icalgauge_impl))) == 0) {
48 icalerror_set_errno(ICAL_NEWFAILED_ERROR); 50 icalerror_set_errno(ICAL_NEWFAILED_ERROR);
49 return 0; 51 return 0;
50 } 52 }
51 53
52 impl->select = pvl_newlist(); 54 impl->select = pvl_newlist();
53 impl->from = pvl_newlist(); 55 impl->from = pvl_newlist();
54 impl->where = pvl_newlist(); 56 impl->where = pvl_newlist();
57 impl->expand = expand;
58
59 sslex_init(&yy_globals);
60
61 ssset_extra(impl, yy_globals);
55 62
56 icalss_yy_gauge = impl; 63 ss_scan_string(sql, yy_globals);
57 64
58 input_buffer_p = input_buffer = sql; 65 r = ssparse(yy_globals);
59 r = ssparse(); 66 sslex_destroy(yy_globals);
60 67
61 return impl; 68 if (r == 0) {
69 return impl;
70 }
71 else {
72 icalgauge_free(impl);
73 return NULL;
74 }
62} 75}
63 76
77int icalgauge_get_expand(icalgauge* gauge)
78{
79return (gauge->expand);
80
81}
64 82
65void icalgauge_free(icalgauge* gauge) 83void icalgauge_free(icalgauge* gauge)
66{ 84{
67 struct icalgauge_impl *impl = (struct icalgauge_impl*)gauge;
68 struct icalgauge_where *w; 85 struct icalgauge_where *w;
69 86
70 assert(impl->select != 0); 87 assert(gauge->select != 0);
71 assert(impl->where != 0); 88 assert(gauge->where != 0);
72 assert(impl->from != 0); 89 assert(gauge->from != 0);
73 90
74 if(impl->select){ 91 if(gauge->select){
75 while( (w=pvl_pop(impl->select)) != 0){ 92 while( (w=pvl_pop(gauge->select)) != 0){
76 if(w->value != 0){ 93 if(w->value != 0){
77 free(w->value); 94 free(w->value);
78 } 95 }
79 free(w); 96 free(w);
80 } 97 }
81 pvl_free(impl->select); 98 pvl_free(gauge->select);
99 gauge->select = 0;
82 } 100 }
83 101
84 if(impl->where){ 102 if(gauge->where){
85 while( (w=pvl_pop(impl->where)) != 0){ 103 while( (w=pvl_pop(gauge->where)) != 0){
86 104
87 if(w->value != 0){ 105 if(w->value != 0){
88 free(w->value); 106 free(w->value);
89 } 107 }
90 free(w); 108 free(w);
91 } 109 }
92 pvl_free(impl->where); 110 pvl_free(gauge->where);
111 gauge->where = 0;
93 } 112 }
94 113
95 if(impl->from){ 114 if(gauge->from){
96 pvl_free(impl->from); 115 pvl_free(gauge->from);
116 gauge->from = 0;
97 } 117 }
118
119 free(gauge);
98 120
99} 121}
100 122
101/* Convert a VQUERY component into a gauge */ 123
124/** Convert a VQUERY component into a gauge */
102icalcomponent* icalgauge_make_gauge(icalcomponent* query); 125icalcomponent* icalgauge_make_gauge(icalcomponent* query);
103 126
104/* icaldirset_test compares a component against a gauge, and returns 127/**
128 icaldirset_test compares a component against a gauge, and returns
105 true if the component passes the test 129 true if the component passes the test
106 130
107 The gauge is a VCALENDAR component that specifies how to test the 131 The gauge is a VCALENDAR component that specifies how to test the
108 target components. The guage holds a collection of VEVENT, VTODO or 132 target components. The gauge holds a collection of VEVENT, VTODO or
109 VJOURNAL sub-components. Each of the sub-components has a 133 VJOURNAL sub-components. Each of the sub-components has a
110 collection of properties that are compared to corresponding 134 collection of properties that are compared to corresponding
111 properties in the target component, according to the 135 properties in the target component, according to the
112 X-LIC-COMPARETYPE parameters to the gauge's properties. 136 X-LIC-COMPARETYPE parameters to the gauge's properties.
113 137
114 When a gauge has several sub-components, the results of testing the 138 When a gauge has several sub-components, the results of testing the
@@ -249,46 +273,65 @@ int icalgauge_compare_recurse(icalcomponent* comp, icalcomponent* gauge)
249} 273}
250 274
251 275
252int icalgauge_compare(icalgauge* gauge,icalcomponent* comp) 276int icalgauge_compare(icalgauge* gauge,icalcomponent* comp)
253{ 277{
254 278
255 struct icalgauge_impl *impl = (struct icalgauge_impl*)gauge;
256 icalcomponent *inner; 279 icalcomponent *inner;
257 int local_pass = 0; 280 int local_pass = 0;
258 int last_clause = 1, this_clause = 1; 281 int last_clause = 1, this_clause = 1;
259 pvl_elem e; 282 pvl_elem e;
283 icalcomponent_kind kind;
284 icalproperty *rrule;
285 int compare_recur = 0;
286
260 287
261 icalerror_check_arg_rz( (comp!=0), "comp"); 288 icalerror_check_arg_rz( (comp!=0), "comp");
262 icalerror_check_arg_rz( (gauge!=0), "gauge"); 289 icalerror_check_arg_rz( (gauge!=0), "gauge");
263 290
291 if (gauge == 0 || comp == 0) return 0;
292
264 inner = icalcomponent_get_first_real_component(comp); 293 inner = icalcomponent_get_first_real_component(comp);
265 294
266 if(inner == 0){ 295 if(inner == 0){
267 icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR); 296 /* Wally Yau: our component is not always wrapped with
268 return 0; 297 * a <VCALENDAR>. It's not an error.
298 * icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR);
299 * return 0; */
300 kind = icalcomponent_isa(comp);
301 if(kind == ICAL_VEVENT_COMPONENT ||
302 kind == ICAL_VTODO_COMPONENT ||
303 kind == ICAL_VJOURNAL_COMPONENT ||
304 kind == ICAL_VQUERY_COMPONENT ||
305 kind == ICAL_VAGENDA_COMPONENT){
306 inner = comp;
307 }
308 else {
309 icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR);
310 return 0;
311 }
312 inner = comp;
269 } 313 }
270 314
271
272 /* Check that this component is one of the FROM types */ 315 /* Check that this component is one of the FROM types */
273 local_pass = 0; 316 local_pass = 0;
274 for(e = pvl_head(impl->from);e!=0;e=pvl_next(e)){ 317 for(e = pvl_head(gauge->from);e!=0;e=pvl_next(e)){
275 icalcomponent_kind k = (icalcomponent_kind)pvl_data(e); 318 icalcomponent_kind k = (icalcomponent_kind)pvl_data(e);
276 319
277 if(k == icalcomponent_isa(inner)){ 320 if(k == icalcomponent_isa(inner)){
278 local_pass=1; 321 local_pass=1;
279 } 322 }
280 } 323 }
281 324
282 if(local_pass == 0){ 325 if(local_pass == 0){
283 return 0; 326 return 0;
284 } 327 }
285 328
286 329
287 /* Check each where clause against the component */ 330 /**** Check each where clause against the component ****/
288 for(e = pvl_head(impl->where);e!=0;e=pvl_next(e)){ 331 for(e = pvl_head(gauge->where);e!=0;e=pvl_next(e)){
289 struct icalgauge_where *w = pvl_data(e); 332 struct icalgauge_where *w = pvl_data(e);
290 icalcomponent *sub_comp; 333 icalcomponent *sub_comp;
291 icalvalue *v; 334 icalvalue *v;
292 icalproperty *prop; 335 icalproperty *prop;
293 icalvalue_kind vk; 336 icalvalue_kind vk;
294 337
@@ -298,17 +341,20 @@ int icalgauge_compare(icalgauge* gauge,icalcomponent* comp)
298 } 341 }
299 342
300 /* First, create a value from the gauge */ 343 /* First, create a value from the gauge */
301 vk = icalenum_property_kind_to_value_kind(w->prop); 344 vk = icalenum_property_kind_to_value_kind(w->prop);
302 345
303 if(vk == ICAL_NO_VALUE){ 346 if(vk == ICAL_NO_VALUE){
304 icalerror_set_errno(ICAL_INTERNAL_ERROR); 347 icalerror_set_errno(ICAL_INTERNAL_ERROR);
305 return 0; 348 return 0;
306 } 349 }
307 350
308 v = icalvalue_new_from_string(vk,w->value); 351 if (w->compare == ICALGAUGECOMPARE_ISNULL || w->compare == ICALGAUGECOMPARE_ISNOTNULL)
352 v = icalvalue_new(vk);
353 else
354 v = icalvalue_new_from_string(vk,w->value);
309 355
310 if (v == 0){ 356 if (v == 0){
311 /* Keep error set by icalvalue_from-string*/ 357 /* Keep error set by icalvalue_from-string*/
312 return 0; 358 return 0;
313 } 359 }
314 360
@@ -321,20 +367,52 @@ int icalgauge_compare(icalgauge* gauge,icalcomponent* comp)
321 sub_comp = icalcomponent_get_first_component(inner,w->comp); 367 sub_comp = icalcomponent_get_first_component(inner,w->comp);
322 if(sub_comp == 0){ 368 if(sub_comp == 0){
323 return 0; 369 return 0;
324 } 370 }
325 } 371 }
326 372
373 /* check if it is a recurring */
374 rrule = icalcomponent_get_first_property(sub_comp,ICAL_RRULE_PROPERTY);
375
376 if (gauge->expand
377 && rrule) {
378
379 if (w->prop == ICAL_DTSTART_PROPERTY ||
380 w->prop == ICAL_DTEND_PROPERTY ||
381 w->prop == ICAL_DUE_PROPERTY){
382 /** needs to use recurrence-id to do comparison */
383 compare_recur = 1;
384 }
385
386 }
387
388
327 this_clause = 0; 389 this_clause = 0;
328 local_pass = 0; 390 local_pass = (w->compare == ICALGAUGECOMPARE_ISNULL) ? 1 : 0;
391
329 for(prop = icalcomponent_get_first_property(sub_comp,w->prop); 392 for(prop = icalcomponent_get_first_property(sub_comp,w->prop);
330 prop != 0; 393 prop != 0;
331 prop = icalcomponent_get_next_property(sub_comp,w->prop)){ 394 prop = icalcomponent_get_next_property(sub_comp,w->prop)){
332 icalvalue* prop_value; 395 icalvalue* prop_value;
333 icalgaugecompare relation; 396 icalgaugecompare relation;
334 397
398 if (w->compare == ICALGAUGECOMPARE_ISNULL) {
399 local_pass = 0;
400 break;
401 }
402
403 if (w->compare == ICALGAUGECOMPARE_ISNOTNULL) {
404 local_pass = 1;
405 break;
406 }
407
408 if (compare_recur) {
409 icalproperty *p = icalcomponent_get_first_property(sub_comp, ICAL_RECURRENCEID_PROPERTY);
410 prop_value = icalproperty_get_value(p);
411 }
412 else /* prop value from this component */
335 prop_value = icalproperty_get_value(prop); 413 prop_value = icalproperty_get_value(prop);
336 414
337 relation = (icalgaugecompare)icalvalue_compare(prop_value,v); 415 relation = (icalgaugecompare)icalvalue_compare(prop_value,v);
338 416
339 if (relation == w->compare){ 417 if (relation == w->compare){
340 local_pass++; 418 local_pass++;
@@ -352,40 +430,46 @@ int icalgauge_compare(icalgauge* gauge,icalcomponent* comp)
352 local_pass++; 430 local_pass++;
353 } else { 431 } else {
354 local_pass = 0; 432 local_pass = 0;
355 } 433 }
356 } 434 }
357 435
436
358 this_clause = local_pass > 0 ? 1 : 0; 437 this_clause = local_pass > 0 ? 1 : 0;
359 438
439
360 /* Now look at the logic operator for this clause to see how 440 /* Now look at the logic operator for this clause to see how
361 the value should be merge with the previous clause */ 441 the value should be merge with the previous clause */
362 442
363 if(w->logic == ICALGAUGELOGIC_AND){ 443 if(w->logic == ICALGAUGELOGIC_AND){
364 last_clause = this_clause && last_clause; 444 last_clause = this_clause && last_clause;
365 } else if(w->logic == ICALGAUGELOGIC_AND) { 445 } else if(w->logic == ICALGAUGELOGIC_OR) {
366 last_clause = this_clause || last_clause; 446 last_clause = this_clause || last_clause;
367 } else { 447 } else {
368 last_clause = this_clause; 448 last_clause = this_clause;
369 } 449 }
370 } 450
451 icalvalue_free(v);
452
453 }/**** check next one in where clause ****/
371 454
372 return last_clause; 455 return last_clause;
373 456
374} 457}
375 458
459/** @brief Debug
460 * Print gauge information to stdout.
461 */
376 462
377void icalgauge_dump(icalcomponent* gauge) 463void icalgauge_dump(icalgauge* gauge)
378{ 464{
379 465
380 pvl_elem *p; 466 pvl_elem p;
381 struct icalgauge_impl *impl = (struct icalgauge_impl*)gauge;
382
383 467
384 printf("--- Select ---\n"); 468 printf("--- Select ---\n");
385 for(p = pvl_head(impl->select);p!=0;p=pvl_next(p)){ 469 for(p = pvl_head(gauge->select);p!=0;p=pvl_next(p)){
386 struct icalgauge_where *w = pvl_data(p); 470 struct icalgauge_where *w = pvl_data(p);
387 471
388 if(w->comp != ICAL_NO_COMPONENT){ 472 if(w->comp != ICAL_NO_COMPONENT){
389 printf("%s ",icalenum_component_kind_to_string(w->comp)); 473 printf("%s ",icalenum_component_kind_to_string(w->comp));
390 } 474 }
391 475
@@ -404,20 +488,20 @@ void icalgauge_dump(icalcomponent* gauge)
404 488
405 489
406 printf("\n"); 490 printf("\n");
407 } 491 }
408 492
409 printf("--- From ---\n"); 493 printf("--- From ---\n");
410 for(p = pvl_head(impl->from);p!=0;p=pvl_next(p)){ 494 for(p = pvl_head(gauge->from);p!=0;p=pvl_next(p)){
411 icalcomponent_kind k = (icalcomponent_kind)pvl_data(p); 495 icalcomponent_kind k = (icalcomponent_kind)pvl_data(p);
412 496
413 printf("%s\n",icalenum_component_kind_to_string(k)); 497 printf("%s\n",icalenum_component_kind_to_string(k));
414 } 498 }
415 499
416 printf("--- Where ---\n"); 500 printf("--- Where ---\n");
417 for(p = pvl_head(impl->where);p!=0;p=pvl_next(p)){ 501 for(p = pvl_head(gauge->where);p!=0;p=pvl_next(p)){
418 struct icalgauge_where *w = pvl_data(p); 502 struct icalgauge_where *w = pvl_data(p);
419 503
420 if(w->logic != ICALGAUGELOGIC_NONE){ 504 if(w->logic != ICALGAUGELOGIC_NONE){
421 printf("%d ",w->logic); 505 printf("%d ",w->logic);
422 } 506 }
423 507
@@ -438,10 +522,8 @@ void icalgauge_dump(icalcomponent* gauge)
438 printf("%s",w->value); 522 printf("%s",w->value);
439 } 523 }
440 524
441 525
442 printf("\n"); 526 printf("\n");
443 } 527 }
444
445
446} 528}
447 529