/*====================================================================== FILE: icalderivedproperty.c CREATOR: eric 09 May 1999 SPDX-FileCopyrightText: 1999, Eric Busboom SPDX-License-Identifier: LGPL-2.1-only OR MPL-2.0 ======================================================================*/ #ifdef HAVE_CONFIG_H #include #endif #include "icalderivedproperty.h" #include "icalproperty.h" #include "icalproperty_p.h" #include "icalcomponent.h" #include "icalerror.h" #include "icalmemory.h" #include /* This map associates the property kinds with: - the string representation of the property name; - the VALUE kind that libical uses internally; - the RFC 5545 VALUE kind that the property uses as a default (or NONE); - an array of RFC 5545 VALUE kinds that are legal for the property; - a bitmask of flags that further describe the property */ struct icalproperty_map { icalproperty_kind kind; const char *name; icalvalue_kind libical_value; icalvalue_kind default_value; /* The size of this array needs to be 1 greater than the maximum number of component values in any multi-typed value (e.g. DATE-TIME-PERIOD). This size SHOULD be calculated by the generating perl script(s). */ icalvalue_kind valid_values[4]; unsigned int flags; }; #define ICAL_PROPERTY_IS_STRUCTURED (1U<<0) #define ICAL_PROPERTY_IS_MULTIVALUED (1U<<1) /* This map associates the property enumerations with the king of property that they are used in and the string representation of the enumeration */ struct icalproperty_enum_map { icalproperty_kind prop; int prop_enum; const char *str; }; int icalproperty_kind_is_valid(const icalproperty_kind kind) { int i = 0; int num_props = (int)(sizeof(property_map) / sizeof(property_map[0])); if (kind == ICAL_ANY_PROPERTY) { return 0; } num_props--; do { if (property_map[i].kind == kind) { return 1; } } while (i++ < num_props); return 0; } const char *icalproperty_kind_to_string(icalproperty_kind kind) { int i, num_props; num_props = (int)(sizeof(property_map) / sizeof(property_map[0])); for (i = 0; i< num_props; i++) { if (property_map[i].kind == kind) { return property_map[i].name; } } return 0; } icalproperty_kind icalproperty_string_to_kind(const char *string) { int i, num_props; if (string == 0) { return ICAL_NO_PROPERTY; } num_props = (int)(sizeof(property_map) / sizeof(property_map[0])); for (i = 0; i < num_props; i++) { if (property_map[i].name && (strcasecmp(property_map[i].name, string) == 0)) { return property_map[i].kind; } } if (strncmp(string, "X-", 2) == 0) { return ICAL_X_PROPERTY; } return ICAL_NO_PROPERTY; } icalproperty_kind icalproperty_value_kind_to_kind(icalvalue_kind kind) { int i, num_props; num_props = (int)(sizeof(property_map) / sizeof(property_map[0])); for (i = 0; i < num_props; i++) { if (property_map[i].libical_value == kind) { return property_map[i].kind; } } return ICAL_NO_PROPERTY; } icalvalue_kind icalproperty_kind_to_value_kind(icalproperty_kind kind) { int i, num_props; num_props = (int)(sizeof(property_map) / sizeof(property_map[0])); for (i = 0; i < num_props; i++) { const struct icalproperty_map *map = &property_map[i]; if (map->kind == kind) { /* Return default value type if possible, otherwise return first legal value type */ return (map->default_value != ICAL_NO_VALUE) ? map->default_value : map->valid_values[0]; } } return ICAL_NO_VALUE; } int icalproperty_value_kind_is_valid(icalproperty_kind pkind, icalvalue_kind vkind) { int i, j; int num_props; if (vkind == ICAL_NO_VALUE) return 0; if (pkind == ICAL_X_PROPERTY) return 1; num_props = (int)(sizeof(property_map) / sizeof(property_map[0])); for (i = 0; i < num_props; i++) { const struct icalproperty_map *map = &property_map[i]; if (map->kind == pkind) { const icalvalue_kind *valid = map->valid_values; for (j = 0; valid[j] != ICAL_NO_VALUE; j++) { if (valid[j] == vkind) { return 1; } } break; } } return 0; } int icalproperty_value_kind_is_multivalued(icalproperty_kind pkind, icalvalue_kind *vkind) { int i, num_props; num_props = (int)(sizeof(property_map) / sizeof(property_map[0])); for (i = 0; i < num_props; i++) { const struct icalproperty_map *map = &property_map[i]; if (map->kind == pkind) { if ((map->flags & ICAL_PROPERTY_IS_STRUCTURED) && *vkind == map->default_value) { /* Normalize structured property VALUE type for proper parsing */ *vkind = map->libical_value; } if ((map->flags & ICAL_PROPERTY_IS_MULTIVALUED)) { /* Property is defined as multi-valued. Make sure the VALUE type is also defined as multi-valued. */ switch (*vkind) { case ICAL_DATE_VALUE: case ICAL_DATETIME_VALUE: case ICAL_DATETIMEDATE_VALUE: case ICAL_DATETIMEPERIOD_VALUE: case ICAL_DURATION_VALUE: case ICAL_FLOAT_VALUE: case ICAL_INTEGER_VALUE: case ICAL_PERIOD_VALUE: case ICAL_TEXT_VALUE: //case ICAL_TIME_VALUE: case ICAL_X_VALUE: return 1; break; default: break; } } break; } } return 0; } int icalproperty_value_kind_is_default(icalproperty_kind pkind, icalvalue_kind vkind) { int i, num_props; num_props = (int)(sizeof(property_map) / sizeof(property_map[0])); for (i = 0; i < num_props; i++) { const struct icalproperty_map *map = &property_map[i]; if (map->kind == pkind) { return ((vkind == map->default_value) || ((map->flags & ICAL_PROPERTY_IS_STRUCTURED) && (vkind == map->libical_value))); } } return 0; } const char *icalproperty_enum_to_string(int e) { icalerror_check_arg_rz(e >= ICALPROPERTY_FIRST_ENUM, "e"); icalerror_check_arg_rz(e <= ICALPROPERTY_LAST_ENUM, "e"); return enum_map[e - ICALPROPERTY_FIRST_ENUM].str; } char *icalproperty_enum_to_string_r(int e) { return icalmemory_strdup(icalproperty_enum_to_string(e)); } int icalproperty_kind_and_string_to_enum(const int kind, const char *str) { icalproperty_kind pkind; int i; icalerror_check_arg_rz(str != 0, "str"); if ((pkind = icalproperty_value_kind_to_kind(kind)) == ICAL_NO_PROPERTY) return 0; while (*str == ' ') { str++; } for (i = ICALPROPERTY_FIRST_ENUM; i != ICALPROPERTY_LAST_ENUM; i++) { if (enum_map[i - ICALPROPERTY_FIRST_ENUM].prop == pkind) break; } if (i == ICALPROPERTY_LAST_ENUM) return 0; for (; i != ICALPROPERTY_LAST_ENUM; i++) { if (enum_map[i - ICALPROPERTY_FIRST_ENUM].prop == pkind && strcasecmp(enum_map[i - ICALPROPERTY_FIRST_ENUM].str, str) == 0) { return enum_map[i - ICALPROPERTY_FIRST_ENUM].prop_enum; } } return 0; } int icalproperty_enum_belongs_to_property(icalproperty_kind kind, int e) { int i; for (i = ICALPROPERTY_FIRST_ENUM; i != ICALPROPERTY_LAST_ENUM; i++) { if (enum_map[i - ICALPROPERTY_FIRST_ENUM].prop_enum == e && enum_map[i - ICALPROPERTY_FIRST_ENUM].prop == kind) { return 1; } } return 0; } const char *icalproperty_method_to_string(icalproperty_method method) { icalerror_check_arg_rz(method >= ICAL_METHOD_X, "method"); icalerror_check_arg_rz(method <= ICAL_METHOD_NONE, "method"); return enum_map[method - ICALPROPERTY_FIRST_ENUM].str; } icalproperty_method icalproperty_string_to_method(const char *str) { int i; icalerror_check_arg_rx(str != 0, "str", ICAL_METHOD_NONE); while (*str == ' ') { str++; } for (i = ICAL_METHOD_X - ICALPROPERTY_FIRST_ENUM; i != ICAL_METHOD_NONE - ICALPROPERTY_FIRST_ENUM; i++) { if (strcasecmp(enum_map[i].str, str) == 0) { return (icalproperty_method) enum_map[i].prop_enum; } } return ICAL_METHOD_NONE; } const char *icalenum_status_to_string(icalproperty_status status) { icalerror_check_arg_rz(status >= ICAL_STATUS_X, "status"); icalerror_check_arg_rz(status <= ICAL_STATUS_NONE, "status"); return enum_map[status - ICALPROPERTY_FIRST_ENUM].str; } icalproperty_status icalenum_string_to_status(const char *str) { int i; icalerror_check_arg_rx(str != 0, "str", ICAL_STATUS_NONE); while (*str == ' ') { str++; } for (i = ICAL_STATUS_X - ICALPROPERTY_FIRST_ENUM; i != ICAL_STATUS_NONE - ICALPROPERTY_FIRST_ENUM; i++) { if (strcasecmp(enum_map[i].str, str) == 0) { return (icalproperty_status) enum_map[i].prop_enum; } } return ICAL_STATUS_NONE; }