author | zautrix <zautrix> | 2004-06-26 19:01:18 (UTC) |
---|---|---|
committer | zautrix <zautrix> | 2004-06-26 19:01:18 (UTC) |
commit | b9aad1f15dc600e4dbe4c62d3fcced6363188ba3 (patch) (side-by-side diff) | |
tree | 2c3d4004fb21c72cba65793859f9bcd8ffd3a49c /libical/src/libicalss/icalgauge.c | |
download | kdepimpi-b9aad1f15dc600e4dbe4c62d3fcced6363188ba3.zip kdepimpi-b9aad1f15dc600e4dbe4c62d3fcced6363188ba3.tar.gz kdepimpi-b9aad1f15dc600e4dbe4c62d3fcced6363188ba3.tar.bz2 |
Initial revision
Diffstat (limited to 'libical/src/libicalss/icalgauge.c') (more/less context) (ignore whitespace changes)
-rw-r--r-- | libical/src/libicalss/icalgauge.c | 447 |
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 @@ +/* -*- Mode: C -*- */ +/*====================================================================== + FILE: icalgauge.c + CREATOR: eric 23 December 1999 + + + $Id$ + $Locker$ + + (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org + + This program is free software; you can redistribute it and/or modify + it under the terms of either: + + The LGPL as published by the Free Software Foundation, version + 2.1, available at: http://www.fsf.org/copyleft/lesser.html + + Or: + + The Mozilla Public License Version 1.0. You may obtain a copy of + the License at http://www.mozilla.org/MPL/ + + The Original Code is eric. The Initial Developer of the Original + Code is Eric Busboom + + +======================================================================*/ + +#include "ical.h" +#include "icalgauge.h" +#include "icalgaugeimpl.h" +#include <stdlib.h> + +extern char* input_buffer; +extern char* input_buffer_p; +int ssparse(void); + +struct icalgauge_impl *icalss_yy_gauge; + +icalgauge* icalgauge_new_from_sql(char* sql) +{ + struct icalgauge_impl *impl; + + int r; + + if ( ( impl = (struct icalgauge_impl*) + malloc(sizeof(struct icalgauge_impl))) == 0) { + icalerror_set_errno(ICAL_NEWFAILED_ERROR); + return 0; + } + + impl->select = pvl_newlist(); + impl->from = pvl_newlist(); + impl->where = pvl_newlist(); + + icalss_yy_gauge = impl; + + input_buffer_p = input_buffer = sql; + r = ssparse(); + + return impl; +} + + +void icalgauge_free(icalgauge* gauge) +{ + struct icalgauge_impl *impl = (struct icalgauge_impl*)gauge; + struct icalgauge_where *w; + + assert(impl->select != 0); + assert(impl->where != 0); + assert(impl->from != 0); + + if(impl->select){ + while( (w=pvl_pop(impl->select)) != 0){ + if(w->value != 0){ + free(w->value); + } + free(w); + } + pvl_free(impl->select); + } + + if(impl->where){ + while( (w=pvl_pop(impl->where)) != 0){ + + if(w->value != 0){ + free(w->value); + } + free(w); + } + pvl_free(impl->where); + } + + if(impl->from){ + pvl_free(impl->from); + } + +} + +/* Convert a VQUERY component into a gauge */ +icalcomponent* icalgauge_make_gauge(icalcomponent* query); + +/* icaldirset_test compares a component against a gauge, and returns + true if the component passes the test + + The gauge is a VCALENDAR component that specifies how to test the + target components. The guage holds a collection of VEVENT, VTODO or + VJOURNAL sub-components. Each of the sub-components has a + collection of properties that are compared to corresponding + properties in the target component, according to the + X-LIC-COMPARETYPE parameters to the gauge's properties. + + When a gauge has several sub-components, the results of testing the + target against each of them is ORed together - the target + component will pass if it matches any of the sub-components in the + gauge. However, the results of matching the properties in a + sub-component are ANDed -- the target must match every property in + a gauge sub-component to match the sub-component. + + Here is an example: + + BEGIN:XROOT + DTSTART;X-LIC-COMPARETYPE=LESS:19981025T020000 + ORGANIZER;X-LIC-COMPARETYPE=EQUAL:mrbig@host.com + END:XROOT + BEGIN:XROOT + LOCATION;X-LIC-COMPARETYPE=EQUAL:McNary's Pub + END:XROOT + + This gauge has two sub-components; one which will match a VEVENT + based on start time, and organizer, and another that matches based + on LOCATION. A target component will pass the test if it matched + either of the sub-components. + + */ + + +int icalgauge_compare_recurse(icalcomponent* comp, icalcomponent* gauge) +{ + int pass = 1,localpass = 0; + icalproperty *p; + icalcomponent *child,*subgauge; + icalcomponent_kind gaugekind, compkind; + + icalerror_check_arg_rz( (comp!=0), "comp"); + icalerror_check_arg_rz( (gauge!=0), "gauge"); + + gaugekind = icalcomponent_isa(gauge); + compkind = icalcomponent_isa(comp); + + if( ! (gaugekind == compkind || gaugekind == ICAL_ANY_COMPONENT) ){ + return 0; + } + + /* Test properties. For each property in the gauge, search through + the component for a similar property. If one is found, compare + the two properties value with the comparison specified in the + gauge with the X-LIC-COMPARETYPE parameter */ + + for(p = icalcomponent_get_first_property(gauge,ICAL_ANY_PROPERTY); + p != 0; + p = icalcomponent_get_next_property(gauge,ICAL_ANY_PROPERTY)){ + + icalproperty* targetprop; + icalparameter* compareparam; + icalparameter_xliccomparetype compare; + int rel; /* The relationship between the gauge and target values.*/ + + /* Extract the comparison type from the gauge. If there is no + comparison type, assume that it is "EQUAL" */ + + compareparam = icalproperty_get_first_parameter( + p, + ICAL_XLICCOMPARETYPE_PARAMETER); + + if (compareparam!=0){ + compare = icalparameter_get_xliccomparetype(compareparam); + } else { + compare = ICAL_XLICCOMPARETYPE_EQUAL; + } + + /* Find a property in the component that has the same type + as the gauge property. HACK -- multiples of a single + property type in the gauge will match only the first + instance in the component */ + + targetprop = icalcomponent_get_first_property(comp, + icalproperty_isa(p)); + + if(targetprop != 0){ + + /* Compare the values of the gauge property and the target + property */ + + rel = icalvalue_compare(icalproperty_get_value(p), + icalproperty_get_value(targetprop)); + + /* Now see if the comparison is equavalent to the comparison + specified in the gauge */ + + if (rel == compare){ + localpass++; + } else if (compare == ICAL_XLICCOMPARETYPE_LESSEQUAL && + ( rel == ICAL_XLICCOMPARETYPE_LESS || + rel == ICAL_XLICCOMPARETYPE_EQUAL)) { + localpass++; + } else if (compare == ICAL_XLICCOMPARETYPE_GREATEREQUAL && + ( rel == ICAL_XLICCOMPARETYPE_GREATER || + rel == ICAL_XLICCOMPARETYPE_EQUAL)) { + localpass++; + } else if (compare == ICAL_XLICCOMPARETYPE_NOTEQUAL && + ( rel == ICAL_XLICCOMPARETYPE_GREATER || + rel == ICAL_XLICCOMPARETYPE_LESS)) { + localpass++; + } else { + localpass = 0; + } + + pass = pass && (localpass>0); + } + } + + /* Test subcomponents. Look for a child component that has a + counterpart in the gauge. If one is found, recursively call + icaldirset_test */ + + for(subgauge = icalcomponent_get_first_component(gauge,ICAL_ANY_COMPONENT); + subgauge != 0; + subgauge = icalcomponent_get_next_component(gauge,ICAL_ANY_COMPONENT)){ + + gaugekind = icalcomponent_isa(subgauge); + + if (gaugekind == ICAL_ANY_COMPONENT){ + child = icalcomponent_get_first_component(comp,ICAL_ANY_COMPONENT); + } else { + child = icalcomponent_get_first_component(comp,gaugekind); + } + + if(child !=0){ + localpass = icalgauge_compare_recurse(child,subgauge); + pass = pass && localpass; + } else { + pass = 0; + } + } + + return pass; +} + + +int icalgauge_compare(icalgauge* gauge,icalcomponent* comp) +{ + + struct icalgauge_impl *impl = (struct icalgauge_impl*)gauge; + icalcomponent *inner; + int local_pass = 0; + int last_clause = 1, this_clause = 1; + pvl_elem e; + + icalerror_check_arg_rz( (comp!=0), "comp"); + icalerror_check_arg_rz( (gauge!=0), "gauge"); + + inner = icalcomponent_get_first_real_component(comp); + + if(inner == 0){ + icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR); + return 0; + } + + + /* Check that this component is one of the FROM types */ + local_pass = 0; + for(e = pvl_head(impl->from);e!=0;e=pvl_next(e)){ + icalcomponent_kind k = (icalcomponent_kind)pvl_data(e); + + if(k == icalcomponent_isa(inner)){ + local_pass=1; + } + } + + if(local_pass == 0){ + return 0; + } + + + /* Check each where clause against the component */ + for(e = pvl_head(impl->where);e!=0;e=pvl_next(e)){ + struct icalgauge_where *w = pvl_data(e); + icalcomponent *sub_comp; + icalvalue *v; + icalproperty *prop; + icalvalue_kind vk; + + if(w->prop == ICAL_NO_PROPERTY || w->value == 0){ + icalerror_set_errno(ICAL_INTERNAL_ERROR); + return 0; + } + + /* First, create a value from the gauge */ + vk = icalenum_property_kind_to_value_kind(w->prop); + + if(vk == ICAL_NO_VALUE){ + icalerror_set_errno(ICAL_INTERNAL_ERROR); + return 0; + } + + v = icalvalue_new_from_string(vk,w->value); + + if (v == 0){ + /* Keep error set by icalvalue_from-string*/ + return 0; + } + + /* Now find the corresponding property in the component, + descending into a sub-component if necessary */ + + if(w->comp == ICAL_NO_COMPONENT){ + sub_comp = inner; + } else { + sub_comp = icalcomponent_get_first_component(inner,w->comp); + if(sub_comp == 0){ + return 0; + } + } + + this_clause = 0; + local_pass = 0; + for(prop = icalcomponent_get_first_property(sub_comp,w->prop); + prop != 0; + prop = icalcomponent_get_next_property(sub_comp,w->prop)){ + icalvalue* prop_value; + icalgaugecompare relation; + + prop_value = icalproperty_get_value(prop); + + relation = (icalgaugecompare)icalvalue_compare(prop_value,v); + + if (relation == w->compare){ + local_pass++; + } else if (w->compare == ICALGAUGECOMPARE_LESSEQUAL && + ( relation == ICALGAUGECOMPARE_LESS || + relation == ICALGAUGECOMPARE_EQUAL)) { + local_pass++; + } else if (w->compare == ICALGAUGECOMPARE_GREATEREQUAL && + ( relation == ICALGAUGECOMPARE_GREATER || + relation == ICALGAUGECOMPARE_EQUAL)) { + local_pass++; + } else if (w->compare == ICALGAUGECOMPARE_NOTEQUAL && + ( relation == ICALGAUGECOMPARE_GREATER || + relation == ICALGAUGECOMPARE_LESS)) { + local_pass++; + } else { + local_pass = 0; + } + } + + this_clause = local_pass > 0 ? 1 : 0; + + /* Now look at the logic operator for this clause to see how + the value should be merge with the previous clause */ + + if(w->logic == ICALGAUGELOGIC_AND){ + last_clause = this_clause && last_clause; + } else if(w->logic == ICALGAUGELOGIC_AND) { + last_clause = this_clause || last_clause; + } else { + last_clause = this_clause; + } + } + + return last_clause; + +} + + +void icalgauge_dump(icalcomponent* gauge) +{ + + pvl_elem *p; + struct icalgauge_impl *impl = (struct icalgauge_impl*)gauge; + + + printf("--- Select ---\n"); + for(p = pvl_head(impl->select);p!=0;p=pvl_next(p)){ + struct icalgauge_where *w = pvl_data(p); + + if(w->comp != ICAL_NO_COMPONENT){ + printf("%s ",icalenum_component_kind_to_string(w->comp)); + } + + if(w->prop != ICAL_NO_PROPERTY){ + printf("%s ",icalenum_property_kind_to_string(w->prop)); + } + + if (w->compare != ICALGAUGECOMPARE_NONE){ + printf("%d ",w->compare); + } + + + if (w->value!=0){ + printf("%s",w->value); + } + + + printf("\n"); + } + + printf("--- From ---\n"); + for(p = pvl_head(impl->from);p!=0;p=pvl_next(p)){ + icalcomponent_kind k = (icalcomponent_kind)pvl_data(p); + + printf("%s\n",icalenum_component_kind_to_string(k)); + } + + printf("--- Where ---\n"); + for(p = pvl_head(impl->where);p!=0;p=pvl_next(p)){ + struct icalgauge_where *w = pvl_data(p); + + if(w->logic != ICALGAUGELOGIC_NONE){ + printf("%d ",w->logic); + } + + if(w->comp != ICAL_NO_COMPONENT){ + printf("%s ",icalenum_component_kind_to_string(w->comp)); + } + + if(w->prop != ICAL_NO_PROPERTY){ + printf("%s ",icalenum_property_kind_to_string(w->prop)); + } + + if (w->compare != ICALGAUGECOMPARE_NONE){ + printf("%d ",w->compare); + } + + + if (w->value!=0){ + printf("%s",w->value); + } + + + printf("\n"); + } + + +} + |