/*====================================================================== FILE: icalvalue.c CREATOR: eric 02 May 1999 (C) COPYRIGHT 1999, Eric Busboom This library 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: https://www.gnu.org/licenses/lgpl-2.1.html Or: The Mozilla Public License Version 2.0. You may obtain a copy of the License at https://www.mozilla.org/MPL/ Contributions from: Graham Davison (g.m.davison@computer.org) ======================================================================*/ #ifdef HAVE_CONFIG_H #include #endif #include "icalderivedvalue.h" #include "icalvalue.h" #include "icalvalueimpl.h" #include "icalerror.h" #include "icalmemory.h" #include "icaltimezone.h" #include #include #include struct icalvalue_impl *icalvalue_new_impl(icalvalue_kind kind); /* This map associates each of the value types with its string representation */ struct icalvalue_kind_map { icalvalue_kind kind; char name[20]; }; int icalvalue_kind_is_valid(const icalvalue_kind kind) { int i = 0; int num_values = (int)(sizeof(value_map) / sizeof(value_map[0])); if (kind == ICAL_ANY_VALUE) { return 0; } num_values--; do { if (value_map[i].kind == kind) { return 1; } } while (i++ < num_values); return 0; } const char *icalvalue_kind_to_string(const icalvalue_kind kind) { int i, num_values; num_values = (int)(sizeof(value_map) / sizeof(value_map[0])); for (i = 0; i < num_values; i++) { if (value_map[i].kind == kind) { return value_map[i].name; } } return 0; } icalvalue_kind icalvalue_string_to_kind(const char *str) { int i, num_values; if (str == 0) { return ICAL_NO_VALUE; } num_values = (int)(sizeof(value_map) / sizeof(value_map[0])); for (i = 0; i < num_values; i++) { if (strcasecmp(value_map[i].name, str) == 0) { return value_map[i].kind; } } return ICAL_NO_VALUE; } icalvalue *icalvalue_new_x(const char *v) { struct icalvalue_impl *impl; icalerror_check_arg_rz((v != 0), "v"); impl = icalvalue_new_impl(ICAL_X_VALUE); icalvalue_set_x((icalvalue *) impl, v); return (icalvalue *) impl; } void icalvalue_set_x(icalvalue *impl, const char *v) { icalerror_check_arg_rv((impl != 0), "value"); icalerror_check_arg_rv((v != 0), "v"); if (impl->x_value != 0) { free((void *)impl->x_value); } impl->x_value = icalmemory_strdup(v); if (impl->x_value == 0) { errno = ENOMEM; } } const char *icalvalue_get_x(const icalvalue *value) { icalerror_check_arg_rz((value != 0), "value"); icalerror_check_value_type(value, ICAL_X_VALUE); return value->x_value; } /* Recur is a special case, so it is not auto generated. */ icalvalue *icalvalue_new_recur(struct icalrecurrencetype v) { struct icalvalue_impl *impl = icalvalue_new_impl(ICAL_RECUR_VALUE); icalvalue_set_recur((icalvalue *) impl, v); return (icalvalue *) impl; } void icalvalue_set_recur(icalvalue *impl, struct icalrecurrencetype v) { icalerror_check_arg_rv((impl != 0), "value"); /* don't allow both count and until */ icalerror_check_arg_rv(v.count == 0 || icaltime_is_null_time(v.until), "recurrencetype"); icalerror_check_value_type(value, ICAL_RECUR_VALUE); if (impl->data.v_recur != 0) { free(impl->data.v_recur->rscale); free(impl->data.v_recur); impl->data.v_recur = 0; } impl->data.v_recur = malloc(sizeof(struct icalrecurrencetype)); if (impl->data.v_recur == 0) { icalerror_set_errno(ICAL_NEWFAILED_ERROR); return; } else { memcpy(impl->data.v_recur, &v, sizeof(struct icalrecurrencetype)); if (v.rscale) impl->data.v_recur->rscale = icalmemory_strdup(v.rscale); } } struct icalrecurrencetype icalvalue_get_recur(const icalvalue *value) { struct icalrecurrencetype rt; icalrecurrencetype_clear(&rt); icalerror_check_arg_rx((value != 0), "value", rt); icalerror_check_arg_rx((value->data.v_recur != 0), "value", rt); icalerror_check_value_type(value, ICAL_RECUR_VALUE); return *(value->data.v_recur); } icalvalue *icalvalue_new_trigger(struct icaltriggertype v) { struct icalvalue_impl *impl = icalvalue_new_impl(ICAL_TRIGGER_VALUE); icalvalue_set_trigger((icalvalue *) impl, v); return (icalvalue *) impl; } void icalvalue_set_trigger(icalvalue *value, struct icaltriggertype v) { icalerror_check_arg_rv((value != 0), "value"); if (!icaltime_is_null_time(v.time)) { value->kind = ICAL_DATETIME_VALUE; icalvalue_set_datetime(value, v.time); } else { value->kind = ICAL_DURATION_VALUE; icalvalue_set_duration(value, v.duration); } } struct icaltriggertype icalvalue_get_trigger(const icalvalue *impl) { struct icaltriggertype tr; tr.duration = icaldurationtype_from_int(0); tr.time = icaltime_null_time(); icalerror_check_arg_rx((impl != 0), "value", tr); if (impl->kind == ICAL_DATETIME_VALUE) { tr.duration = icaldurationtype_from_int(0); tr.time = impl->data.v_time; } else if (impl->kind == ICAL_DURATION_VALUE) { tr.time = icaltime_null_time(); tr.duration = impl->data.v_duration; } else { tr.duration = icaldurationtype_from_int(0); tr.time = icaltime_null_time(); icalerror_set_errno(ICAL_BADARG_ERROR); } return tr; } icalvalue *icalvalue_new_date(struct icaltimetype v) { struct icalvalue_impl *impl = icalvalue_new_impl(ICAL_DATE_VALUE); icalvalue_set_date((icalvalue *) impl, v); return (icalvalue *) impl; } void icalvalue_set_date(icalvalue *value, struct icaltimetype v) { icalerror_check_arg_rv((icaltime_is_date(v)), "v"); icalvalue_set_datetimedate(value, v); } struct icaltimetype icalvalue_get_date(const icalvalue *value) { struct icaltimetype dt; dt = icaltime_null_date(); icalerror_check_arg_rx((value != 0), "value", dt); icalerror_check_arg_rx((value->kind == ICAL_DATE_VALUE), "value->kind", dt); return ((struct icalvalue_impl *)value)->data.v_time; } icalvalue *icalvalue_new_datetime(struct icaltimetype v) { struct icalvalue_impl *impl = icalvalue_new_impl(ICAL_DATETIME_VALUE); icalvalue_set_datetime((icalvalue *) impl, v); return (icalvalue *) impl; } void icalvalue_set_datetime(icalvalue *value, struct icaltimetype v) { icalerror_check_arg_rv((!icaltime_is_date(v)), "v"); icalvalue_set_datetimedate(value, v); } struct icaltimetype icalvalue_get_datetime(const icalvalue *value) { /* For backwards compatibility, fetch both DATE and DATE-TIME */ return icalvalue_get_datetimedate(value); } icalvalue *icalvalue_new_datetimedate(struct icaltimetype v) { struct icalvalue_impl *impl = icalvalue_new_impl(ICAL_DATETIME_VALUE); icalvalue_set_datetimedate((icalvalue *) impl, v); return (icalvalue *) impl; } void icalvalue_set_datetimedate(icalvalue *value, struct icaltimetype v) { struct icalvalue_impl *impl; if (!icaltime_is_valid_time(v)) { icalerror_set_errno(ICAL_BADARG_ERROR); return; } icalerror_check_arg_rv((value != 0), "value"); icalerror_check_arg_rv(((value->kind == ICAL_DATETIME_VALUE) || (value->kind == ICAL_DATE_VALUE)), "value->kind"); impl = (struct icalvalue_impl *)value; impl->data.v_time = v; /* preserve only built-in UTC time zone, otherwise unset any set on the 'v' */ if (impl->data.v_time.zone != NULL && impl->data.v_time.zone != icaltimezone_get_utc_timezone()) { impl->data.v_time.zone = NULL; } icalvalue_reset_kind(impl); } struct icaltimetype icalvalue_get_datetimedate(const icalvalue *value) { struct icaltimetype dt; dt = icaltime_null_time(); icalerror_check_arg_rx((value != 0), "value", dt); icalerror_check_arg_rx(((value->kind == ICAL_DATETIME_VALUE) || (value->kind == ICAL_DATE_VALUE)), "value->kind", dt); return ((struct icalvalue_impl *)value)->data.v_time; } /* DATE-TIME-PERIOD is a special case, and is not auto generated */ icalvalue *icalvalue_new_datetimeperiod(struct icaldatetimeperiodtype v) { struct icalvalue_impl *impl = icalvalue_new_impl(ICAL_DATETIMEPERIOD_VALUE); icalvalue_set_datetimeperiod(impl, v); return (icalvalue *) impl; } void icalvalue_set_datetimeperiod(icalvalue *impl, struct icaldatetimeperiodtype v) { icalerror_check_arg_rv((impl != 0), "value"); icalerror_check_value_type(value, ICAL_DATETIMEPERIOD_VALUE); if (!icaltime_is_null_time(v.time)) { impl->kind = ICAL_DATETIME_VALUE; icalvalue_set_datetimedate(impl, v.time); } else if (!icalperiodtype_is_null_period(v.period)) { if (!icalperiodtype_is_valid_period(v.period)) { icalerror_set_errno(ICAL_BADARG_ERROR); return; } impl->kind = ICAL_PERIOD_VALUE; icalvalue_set_period(impl, v.period); } else { icalerror_set_errno(ICAL_BADARG_ERROR); } } struct icaldatetimeperiodtype icalvalue_get_datetimeperiod(const icalvalue *impl) { struct icaldatetimeperiodtype dtp; dtp.period = icalperiodtype_null_period(); dtp.time = icaltime_null_time(); icalerror_check_arg_rx((impl != 0), "value", dtp); icalerror_check_value_type(value, ICAL_DATETIMEPERIOD_VALUE); if (impl->kind == ICAL_DATETIME_VALUE || impl->kind == ICAL_DATE_VALUE) { dtp.period = icalperiodtype_null_period(); dtp.time = impl->data.v_time; } else if (impl->kind == ICAL_PERIOD_VALUE) { dtp.period = impl->data.v_period; dtp.time = icaltime_null_time(); } else { dtp.period = icalperiodtype_null_period(); dtp.time = icaltime_null_time(); icalerror_set_errno(ICAL_BADARG_ERROR); } return dtp; } icalvalue *icalvalue_new_class(enum icalproperty_class v) { struct icalvalue_impl *impl = icalvalue_new_impl(ICAL_CLASS_VALUE); icalvalue_set_class((icalvalue *) impl, v); return (icalvalue *) impl; } void icalvalue_set_class(icalvalue *value, enum icalproperty_class v) { struct icalvalue_impl *impl; icalerror_check_arg_rv((value != 0), "value"); icalerror_check_value_type(value, ICAL_CLASS_VALUE); impl = (struct icalvalue_impl *)value; impl->data.v_enum = v; icalvalue_reset_kind(impl); } enum icalproperty_class icalvalue_get_class(const icalvalue *value) { icalproperty_class pr; pr = ICAL_CLASS_NONE; icalerror_check_arg_rx((value != NULL), "value", pr); icalerror_check_arg((value != 0), "value"); icalerror_check_value_type(value, ICAL_CLASS_VALUE); return ((struct icalvalue_impl *)value)->data.v_enum; } icalvalue *icalvalue_new_geo(struct icalgeotype v) { struct icalvalue_impl *impl = icalvalue_new_impl(ICAL_GEO_VALUE); icalvalue_set_geo((icalvalue *) impl, v); return (icalvalue *) impl; } void icalvalue_set_geo(icalvalue *value, struct icalgeotype v) { struct icalvalue_impl *impl; icalerror_check_arg_rv((value != 0), "value"); icalerror_check_value_type(value, ICAL_GEO_VALUE); impl = (struct icalvalue_impl *)value; impl->data.v_geo = v; icalvalue_reset_kind(impl); } struct icalgeotype icalvalue_get_geo(const icalvalue *value) { struct icalgeotype gt; gt.lat = 255.0; gt.lon = 255.0; icalerror_check_arg_rx((value != 0), "value", gt); icalerror_check_value_type(value, ICAL_GEO_VALUE); return ((struct icalvalue_impl *)value)->data.v_geo; } icalvalue *icalvalue_new_attach(icalattach *attach) { struct icalvalue_impl *impl; icalerror_check_arg_rz((attach != NULL), "attach"); impl = icalvalue_new_impl(ICAL_ATTACH_VALUE); if (!impl) { errno = ENOMEM; return NULL; } icalvalue_set_attach((icalvalue *) impl, attach); return (icalvalue *) impl; } void icalvalue_set_attach(icalvalue *value, icalattach *attach) { struct icalvalue_impl *impl; icalerror_check_arg_rv((value != NULL), "value"); icalerror_check_value_type(value, ICAL_ATTACH_VALUE); icalerror_check_arg_rv((attach != NULL), "attach"); impl = (struct icalvalue_impl *)value; icalattach_ref(attach); if (impl->data.v_attach) icalattach_unref(impl->data.v_attach); impl->data.v_attach = attach; } icalattach *icalvalue_get_attach(const icalvalue *value) { icalerror_check_arg_rz((value != NULL), "value"); icalerror_check_value_type(value, ICAL_ATTACH_VALUE); return value->data.v_attach; } icalvalue *icalvalue_new_binary(const char * v) { struct icalvalue_impl *impl; icalerror_check_arg_rz((v != NULL), "v"); impl = icalvalue_new_impl(ICAL_BINARY_VALUE); if (!impl) { errno = ENOMEM; return NULL; } icalvalue_set_binary((icalvalue *) impl, v); return (icalvalue*)impl; } static void free_icalvalue_attach_data(char *data, void *user_data) { _unused(user_data); free(data); } void icalvalue_set_binary(icalvalue *value, const char * v) { struct icalvalue_impl *impl; icalerror_check_arg_rv((value != NULL), "value"); icalerror_check_value_type(value, ICAL_BINARY_VALUE); icalerror_check_arg_rv((v != NULL), "v"); impl = (struct icalvalue_impl *)value; if (impl->data.v_attach) icalattach_unref(impl->data.v_attach); impl->data.v_attach = icalattach_new_from_data(strdup(v), free_icalvalue_attach_data, 0); } const char *icalvalue_get_binary(const icalvalue *value) { icalerror_check_arg_rz((value != 0), "value"); icalerror_check_value_type(value, ICAL_BINARY_VALUE); return (const char *) icalattach_get_data(value->data.v_attach); } /* The remaining interfaces are 'new', 'set' and 'get' for each of the value types */ /* Everything below this line is machine generated. Do not edit. */