3 /*======================================================================
5 CREATOR: eric 28 April 1999
10 (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of either:
15 The LGPL as published by the Free Software Foundation, version
16 2.1, available at: http://www.fsf.org/copyleft/lesser.html
20 The Mozilla Public License Version 1.0. You may obtain a copy of
21 the License at http://www.mozilla.org/MPL/
23 The original code is icalproperty.c
25 ======================================================================*/
26 /*#line 27 "icalproperty.c.in"*/
32 #include "icalproperty.h"
33 #include "icalparameter.h"
34 #include "icalcomponent.h"
36 #include "icalenums.h"
37 #include "icalerror.h"
38 #include "icalmemory.h"
39 #include "icalparser.h"
41 #include <string.h> /* For icalmemory_strdup, rindex */
45 #include <stdio.h> /* for printf */
46 #include <stdarg.h> /* for va_list, va_start, etc. */
48 #define TMP_BUF_SIZE 1024
50 /* Private routines for icalproperty */
51 void icalvalue_set_parent(icalvalue* value,
52 icalproperty* property);
53 icalproperty* icalvalue_get_parent(icalvalue* value);
55 void icalparameter_set_parent(icalparameter* param,
56 icalproperty* property);
57 icalproperty* icalparameter_get_parent(icalparameter* value);
60 void icalproperty_set_x_name(icalproperty* prop, char* name);
62 struct icalproperty_impl
65 icalproperty_kind kind;
68 pvl_elem parameter_iterator;
70 icalcomponent *parent;
73 void icalproperty_add_parameters(struct icalproperty_impl *prop,va_list args)
78 struct icalproperty_impl *impl = (struct icalproperty_impl*)prop;
80 while((vp = va_arg(args, void*)) != 0) {
82 if (icalvalue_isa_value(vp) != 0 ){
83 } else if (icalparameter_isa_parameter(vp) != 0 ){
85 icalproperty_add_parameter((icalproperty*)impl,
97 struct icalproperty_impl*
98 icalproperty_new_impl (icalproperty_kind kind)
100 struct icalproperty_impl* prop;
102 if ( ( prop = (struct icalproperty_impl*)
103 malloc(sizeof(struct icalproperty_impl))) == 0) {
104 icalerror_set_errno(ICAL_NEWFAILED_ERROR);
108 strcpy(prop->id,"prop");
111 prop->parameters = pvl_newlist();
112 prop->parameter_iterator = 0;
122 icalproperty_new (icalproperty_kind kind)
124 if(kind == ICAL_NO_PROPERTY){
128 return (icalproperty*)icalproperty_new_impl(kind);
133 icalproperty_new_clone(icalproperty* prop)
135 struct icalproperty_impl *old = (struct icalproperty_impl*)prop;
136 struct icalproperty_impl *new = icalproperty_new_impl(old->kind);
139 icalerror_check_arg_rz((prop!=0),"Prop");
140 icalerror_check_arg_rz((old!=0),"old");
141 icalerror_check_arg_rz((new!=0),"new");
143 if (old->value !=0) {
144 new->value = icalvalue_new_clone(old->value);
147 if (old->x_name != 0) {
149 new->x_name = icalmemory_strdup(old->x_name);
151 if (new->x_name == 0) {
152 icalproperty_free(new);
153 icalerror_set_errno(ICAL_NEWFAILED_ERROR);
158 for(p=pvl_head(old->parameters);p != 0; p = pvl_next(p)){
159 icalparameter *param = icalparameter_new_clone(pvl_data(p));
162 icalproperty_free(new);
163 icalerror_set_errno(ICAL_NEWFAILED_ERROR);
167 pvl_push(new->parameters,param);
175 icalproperty* icalproperty_new_from_string(char* str)
178 size_t buf_size = 1024;
179 char* buf = icalmemory_new_buffer(buf_size);
185 icalerror_check_arg_rz( (str!=0),"str");
187 /* Is this a HACK or a crafty reuse of code? */
189 icalmemory_append_string(&buf, &buf_ptr, &buf_size, "BEGIN:VCALENDAR\n");
190 icalmemory_append_string(&buf, &buf_ptr, &buf_size, str);
191 icalmemory_append_string(&buf, &buf_ptr, &buf_size, "\n");
192 icalmemory_append_string(&buf, &buf_ptr, &buf_size, "END:VCALENDAR\n");
194 comp = icalparser_parse_string(buf);
197 icalerror_set_errno(ICAL_PARSE_ERROR);
201 errors = icalcomponent_count_errors(comp);
203 prop = icalcomponent_get_first_property(comp,ICAL_ANY_PROPERTY);
205 icalcomponent_remove_property(comp,prop);
207 icalcomponent_free(comp);
211 icalproperty_free(prop);
220 icalproperty_free (icalproperty* prop)
222 struct icalproperty_impl *p;
224 icalparameter* param;
226 icalerror_check_arg_rv((prop!=0),"prop");
228 p = (struct icalproperty_impl*)prop;
230 #ifdef ICAL_FREE_ON_LIST_IS_ERROR
231 icalerror_assert( (p->parent ==0),"Tried to free a property that is still attached to a component. ");
240 icalvalue_set_parent(p->value,0);
241 icalvalue_free(p->value);
244 while( (param = pvl_pop(p->parameters)) != 0){
245 icalparameter_free(param);
248 pvl_free(p->parameters);
250 if (p->x_name != 0) {
254 p->kind = ICAL_NO_PROPERTY;
256 p->parameter_iterator = 0;
267 icalproperty_as_ical_string (icalproperty* prop)
269 icalparameter *param;
271 /* Create new buffer that we can append names, parameters and a
272 value to, and reallocate as needed. Later, this buffer will be
273 copied to a icalmemory_tmp_buffer, which is managed internally
274 by libical, so it can be given to the caller without fear of
275 the caller forgetting to free it */
277 const char* property_name = 0;
278 size_t buf_size = 1024;
279 char* buf = icalmemory_new_buffer(buf_size);
284 char newline[] = "\n";
286 struct icalproperty_impl *impl = (struct icalproperty_impl*)prop;
288 icalerror_check_arg_rz( (prop!=0),"prop");
291 /* Append property name */
293 if (impl->kind == ICAL_X_PROPERTY && impl->x_name != 0){
294 property_name = impl->x_name;
296 property_name = icalproperty_kind_to_string(impl->kind);
299 if (property_name == 0 ) {
300 icalerror_warn("Got a property of an unknown kind.");
301 icalmemory_free_buffer(buf);
307 icalmemory_append_string(&buf, &buf_ptr, &buf_size, property_name);
308 icalmemory_append_string(&buf, &buf_ptr, &buf_size, newline);
312 /* Determine what VALUE parameter to include. The VALUE parameters
313 are ignored in the normal parameter printing ( the block after
314 this one, so we need to do it here */
316 const char* kind_string = 0;
318 icalparameter *orig_val_param
319 = icalproperty_get_first_parameter(prop,ICAL_VALUE_PARAMETER);
321 icalvalue *value = icalproperty_get_value(impl);
323 icalvalue_kind orig_kind = ICAL_NO_VALUE;
325 icalvalue_kind this_kind = ICAL_NO_VALUE;
327 icalvalue_kind default_kind
328 = icalproperty_kind_to_value_kind(impl->kind);
331 orig_kind = (icalvalue_kind)icalparameter_get_value(orig_val_param);
335 this_kind = icalvalue_isa(value);
339 if(this_kind == default_kind &&
340 orig_kind != ICAL_NO_VALUE){
341 /* The kind is the default, so it does not need to be
342 included, but do it anyway, since it was explicit in
343 the property. But, use the default, not the one
344 specified in the property */
346 kind_string = icalvalue_kind_to_string(default_kind);
348 } else if (this_kind != default_kind && this_kind != ICAL_NO_VALUE){
349 /* Not the default, so it must be specified */
350 kind_string = icalvalue_kind_to_string(this_kind);
352 /* Don'tinclude the VALUE parameter at all */
356 icalmemory_append_string(&buf, &buf_ptr, &buf_size, " ;");
357 icalmemory_append_string(&buf, &buf_ptr, &buf_size, "VALUE=");
358 icalmemory_append_string(&buf, &buf_ptr, &buf_size, kind_string);
359 icalmemory_append_string(&buf, &buf_ptr, &buf_size, newline);
365 /* Append parameters */
366 for(param = icalproperty_get_first_parameter(prop,ICAL_ANY_PARAMETER);
368 param = icalproperty_get_next_parameter(prop,ICAL_ANY_PARAMETER)) {
370 char* kind_string = icalparameter_as_ical_string(param);
371 icalparameter_kind kind = icalparameter_isa(param);
373 if(kind==ICAL_VALUE_PARAMETER){
377 if (kind_string == 0 ) {
378 char temp[TMP_BUF_SIZE];
379 snprintf(temp, TMP_BUF_SIZE,"Got a parameter of unknown kind in %s property",property_name);
380 icalerror_warn(temp);
384 icalmemory_append_string(&buf, &buf_ptr, &buf_size, " ;");
385 icalmemory_append_string(&buf, &buf_ptr, &buf_size, kind_string);
386 icalmemory_append_string(&buf, &buf_ptr, &buf_size, newline);
392 icalmemory_append_string(&buf, &buf_ptr, &buf_size, " :");
394 value = icalproperty_get_value(prop);
397 const char *str = icalvalue_as_ical_string(value);
398 icalerror_assert((str !=0),"Could not get string representation of a value");
399 icalmemory_append_string(&buf, &buf_ptr, &buf_size, str);
401 icalmemory_append_string(&buf, &buf_ptr, &buf_size,"ERROR: No Value");
405 icalmemory_append_string(&buf, &buf_ptr, &buf_size, newline);
407 /* Now, copy the buffer to a tmp_buffer, which is safe to give to
408 the caller without worring about de-allocating it. */
411 out_buf = icalmemory_tmp_buffer(strlen(buf)+1);
412 strcpy(out_buf, buf);
414 icalmemory_free_buffer(buf);
422 icalproperty_isa (icalproperty* property)
424 struct icalproperty_impl *p = (struct icalproperty_impl*)property;
430 return ICAL_NO_PROPERTY;
434 icalproperty_isa_property (void* property)
436 struct icalproperty_impl *impl = (struct icalproperty_impl*)property;
438 icalerror_check_arg_rz( (property!=0), "property");
440 if (strcmp(impl->id,"prop") == 0) {
449 icalproperty_add_parameter (icalproperty* prop,icalparameter* parameter)
451 struct icalproperty_impl *p = (struct icalproperty_impl*)prop;
453 icalerror_check_arg_rv( (prop!=0),"prop");
454 icalerror_check_arg_rv( (parameter!=0),"parameter");
456 pvl_push(p->parameters, parameter);
461 icalproperty_set_parameter (icalproperty* prop,icalparameter* parameter)
463 icalparameter_kind kind;
465 icalerror_check_arg_rv( (prop!=0),"prop");
466 icalerror_check_arg_rv( (parameter!=0),"parameter");
468 kind = icalparameter_isa(parameter);
470 icalproperty_remove_parameter(prop,kind);
472 icalproperty_add_parameter(prop,parameter);
475 void icalproperty_set_parameter_from_string(icalproperty* prop,
476 const char* name, const char* value)
479 icalparameter_kind kind;
480 icalparameter *param;
482 icalerror_check_arg_rv( (prop!=0),"prop");
483 icalerror_check_arg_rv( (name!=0),"name");
484 icalerror_check_arg_rv( (value!=0),"value");
486 kind = icalparameter_string_to_kind(name);
488 if(kind == ICAL_NO_PARAMETER){
489 icalerror_set_errno(ICAL_BADARG_ERROR);
493 param = icalparameter_new_from_value_string(kind,value);
496 icalerror_set_errno(ICAL_BADARG_ERROR);
500 icalproperty_set_parameter(prop,param);
504 const char* icalproperty_get_parameter_as_string(icalproperty* prop,
507 icalparameter_kind kind;
508 icalparameter *param;
512 icalerror_check_arg_rz( (prop!=0),"prop");
513 icalerror_check_arg_rz( (name!=0),"name");
515 kind = icalparameter_string_to_kind(name);
517 if(kind == ICAL_NO_PROPERTY){
518 /* icalenum_string_to_parameter_kind will set icalerrno */
522 param = icalproperty_get_first_parameter(prop,kind);
528 str = icalparameter_as_ical_string(param);
530 pv = strchr(str,'=');
533 icalerror_set_errno(ICAL_INTERNAL_ERROR);
542 icalproperty_remove_parameter (icalproperty* prop, icalparameter_kind kind)
545 struct icalproperty_impl *impl = (struct icalproperty_impl*)prop;
547 icalerror_check_arg_rv((prop!=0),"prop");
549 for(p=pvl_head(impl->parameters);p != 0; p = pvl_next(p)){
550 icalparameter* param = (icalparameter *)pvl_data (p);
551 if (icalparameter_isa(param) == kind) {
552 pvl_remove (impl->parameters, p);
553 icalparameter_free (param);
561 icalproperty_count_parameters (icalproperty* prop)
563 struct icalproperty_impl *p = (struct icalproperty_impl*)prop;
566 return pvl_count(p->parameters);
569 icalerror_set_errno(ICAL_USAGE_ERROR);
575 icalproperty_get_first_parameter (icalproperty* prop, icalparameter_kind kind)
577 struct icalproperty_impl *p = (struct icalproperty_impl*)prop;
579 icalerror_check_arg_rz( (prop!=0),"prop");
581 p->parameter_iterator = pvl_head(p->parameters);
583 if (p->parameter_iterator == 0) {
587 for( p->parameter_iterator = pvl_head(p->parameters);
588 p->parameter_iterator !=0;
589 p->parameter_iterator = pvl_next(p->parameter_iterator)){
591 icalparameter *param = (icalparameter*)pvl_data(p->parameter_iterator);
593 if(icalparameter_isa(param) == kind || kind == ICAL_ANY_PARAMETER){
603 icalproperty_get_next_parameter (icalproperty* prop, icalparameter_kind kind)
605 struct icalproperty_impl *p = (struct icalproperty_impl*)prop;
607 icalerror_check_arg_rz( (prop!=0),"prop");
609 if (p->parameter_iterator == 0) {
613 for( p->parameter_iterator = pvl_next(p->parameter_iterator);
614 p->parameter_iterator !=0;
615 p->parameter_iterator = pvl_next(p->parameter_iterator)){
617 icalparameter *param = (icalparameter*)pvl_data(p->parameter_iterator);
619 if(icalparameter_isa(param) == kind || kind == ICAL_ANY_PARAMETER){
629 icalproperty_set_value (icalproperty* prop, icalvalue* value)
631 struct icalproperty_impl *p = (struct icalproperty_impl*)prop;
633 icalerror_check_arg_rv((prop !=0),"prop");
634 icalerror_check_arg_rv((value !=0),"value");
637 icalvalue_set_parent(p->value,0);
638 icalvalue_free(p->value);
644 icalvalue_set_parent(value,prop);
648 void icalproperty_set_value_from_string(icalproperty* prop,const char* str,
651 icalvalue *oval,*nval;
652 icalvalue_kind kind = ICAL_NO_VALUE;
654 icalerror_check_arg_rv( (prop!=0),"prop");
655 icalerror_check_arg_rv( (str!=0),"str");
656 icalerror_check_arg_rv( (type!=0),"type");
658 if(strcmp(type,"NO")==0){
659 /* Get the type from the value the property already has, if it exists */
660 oval = icalproperty_get_value(prop);
662 /* Use the existing value kind */
663 kind = icalvalue_isa(oval);
665 /* Use the default kind for the property */
666 kind = icalproperty_kind_to_value_kind(icalproperty_isa(prop));
669 /* Use the given kind string */
670 kind = icalvalue_string_to_kind(type);
673 if(kind == ICAL_NO_VALUE){
674 icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR);
678 nval = icalvalue_new_from_string(kind, str);
681 /* icalvalue_new_from_string sets errno */
682 assert(icalerrno != ICAL_NO_ERROR);
686 icalproperty_set_value(prop,nval);
692 icalproperty_get_value (icalproperty* prop)
694 struct icalproperty_impl *p = (struct icalproperty_impl*)prop;
696 icalerror_check_arg_rz( (prop!=0),"prop");
701 const char* icalproperty_get_value_as_string(icalproperty* prop)
705 struct icalproperty_impl *impl = (struct icalproperty_impl*)prop;
707 icalerror_check_arg_rz( (prop!=0),"prop");
711 return icalvalue_as_ical_string(value);
715 void icalproperty_set_x_name(icalproperty* prop, char* name)
717 struct icalproperty_impl *impl = (struct icalproperty_impl*)prop;
719 icalerror_check_arg_rv( (name!=0),"name");
720 icalerror_check_arg_rv( (prop!=0),"prop");
722 if (impl->x_name != 0) {
726 impl->x_name = icalmemory_strdup(name);
728 if(impl->x_name == 0){
729 icalerror_set_errno(ICAL_NEWFAILED_ERROR);
734 char* icalproperty_get_x_name(icalproperty* prop){
736 struct icalproperty_impl *impl = (struct icalproperty_impl*)prop;
738 icalerror_check_arg_rz( (prop!=0),"prop");
744 /* From Jonathan Yue <jonathan.yue@cp.net> */
745 char* icalproperty_get_name (icalproperty* prop)
748 const char* property_name = 0;
749 size_t buf_size = 256;
750 char* buf = icalmemory_new_buffer(buf_size);
753 struct icalproperty_impl *impl = (struct icalproperty_impl*)prop;
755 icalerror_check_arg_rz( (prop!=0),"prop");
757 if (impl->kind == ICAL_X_PROPERTY && impl->x_name != 0){
758 property_name = impl->x_name;
760 property_name = icalproperty_kind_to_string(impl->kind);
763 if (property_name == 0 ) {
764 icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR);
768 /* _append_string will automatically grow the buffer if
769 property_name is longer than the initial buffer size */
770 icalmemory_append_string(&buf, &buf_ptr, &buf_size, property_name);
773 /* Add the buffer to the temporary buffer ring -- the caller will
774 not have to free the memory. */
775 icalmemory_add_tmp_buffer(buf);
783 void icalproperty_set_parent(icalproperty* property,
784 icalcomponent* component)
786 struct icalproperty_impl *impl = (struct icalproperty_impl*)property;
788 icalerror_check_arg_rv( (property!=0),"property");
790 impl->parent = component;
793 icalcomponent* icalproperty_get_parent(icalproperty* property)
795 struct icalproperty_impl *impl = (struct icalproperty_impl*)property;
797 icalerror_check_arg_rz( (property!=0),"property");
808 /* Everything below this line is machine generated. Do not edit. */