22#include "icalvalueimpl.h"
23#include "icalerror_p.h"
34#define TMP_BUF_SIZE 1024
38 struct icalvalue_impl *v;
49 v->id = ICAL_STRUCTURE_TYPE_VALUE;
55 memset(&(v->data), 0,
sizeof(v->data));
68 struct icalvalue_impl *clone;
70 clone = icalvalue_new_impl(old->kind);
76 clone->kind = old->kind;
77 clone->size = old->size;
79 switch (clone->kind) {
86 clone->data.v_attach = old->data.v_attach;
87 if (clone->data.v_attach) {
101 if (old->data.v_string != 0) {
104 if (clone->data.v_string == 0) {
113 clone->data = old->data;
117 if (old->x_value != 0) {
120 if (clone->x_value == 0) {
130 if (old->data.v_recur != 0) {
132 if (clone->data.v_recur == 0) {
141 if (old->x_value != 0) {
144 if (clone->x_value == 0) {
155 clone->data = old->data;
156 if (old->data.v_requeststatus.debug != 0) {
157 clone->data.v_requeststatus.debug =
icalmemory_strdup(old->data.v_requeststatus.debug);
158 if (clone->data.v_requeststatus.debug == 0) {
171 clone->data = old->data;
178static char *icalmemory_strdup_and_dequote(
const char *
str)
195 for (p =
str; !wroteNull && *p != 0; p++) {
259static char *icalmemory_strdup_and_quote(
const icalvalue *value,
const char *unquoted_str)
267 buf_sz = strlen(unquoted_str) + 1;
276 for (p = unquoted_str; *p != 0 && cnt < max_value_chars; p++, cnt++) {
351 struct icalvalue_impl *value;
354 value = icalvalue_new_impl(
kind);
355 value->data.v_enum = e;
358 value = icalvalue_new_impl(
kind);
359 value->data.v_enum = x_type;
372static bool simple_str_to_doublestr(
const char *from,
char *result,
int result_len,
char **to)
374 const char *start = NULL;
375 char *end = NULL, *cur = (
char *)from;
377 struct lconv *loc_data = localeconv();
382 if (!from || !result) {
387 while (*cur && isspace((
int)*cur)) {
396 while (*cur && (isdigit((
int)*cur) || *cur ==
'.' || *cur ==
'+' || *cur ==
'-')) {
400 len = (int)(ptrdiff_t)(end - start);
401 if (len + 1 >= result_len) {
403 len = result_len - 1;
410 for (i = 0; i < len; ++i) {
411 if (start[i] ==
'.' &&
412 loc_data && loc_data->decimal_point && loc_data->decimal_point[0] && loc_data->decimal_point[0] !=
'.') {
414 result[i] = loc_data->decimal_point[0];
416 result[i] = start[i];
424 if (sscanf(result,
"%lf", &dtest) != 1) {
430static void free_icalvalue_attach_data(
char *data,
void *user_data)
437 const char *
str, icalproperty **error)
442 struct icalvalue_impl *value = 0;
444 icalerror_check_arg_rz(
str != 0,
"str");
464#if defined(__GNUC__) && !defined(__clang__)
465#pragma GCC diagnostic push
466#pragma GCC diagnostic ignored "-Wanalyzer-malloc-leak"
469 char *dupStr = strdup(
str);
482#if defined(__GNUC__) && !defined(__clang__)
483#pragma GCC diagnostic pop
487 if (!strcmp(
str,
"TRUE")) {
489 }
else if (!strcmp(
str,
"FALSE")) {
493 snprintf(temp,
sizeof(temp),
494 "Could not parse %s as a %s property",
500 "icalvalue_new_from_string cannot parse value string (%s) for \'%s\'",
502 icalerror_warn(temp);
561 const long tmpl = strtol(
str, &t_end, 10);
562 if (
str != t_end && errno != ERANGE) {
569 const float tmpf = strtof(
str, &t_end);
577 long utcoffset, hours, minutes, seconds;
581 long t = strtol(
str, 0, 10);
584 if (strlen(
str) < 7) {
588 minutes = (t - hours * 10000) / 100;
589 seconds = (t - hours * 10000 - minutes * 100);
590 utcoffset = hours * 3600 + minutes * 60 + seconds;
591 if (utcoffset < INT_MIN) {
593 }
else if (utcoffset > INT_MAX) {
604 char *dequoted_str = icalmemory_strdup_and_dequote(
str);
634 goto geo_parsing_error;
637 while (cur && isspace((
int)*cur)) {
642 if (!cur || *cur !=
';') {
643 goto geo_parsing_error;
649 while (cur && isspace((
int)*cur)) {
654 goto geo_parsing_error;
661 snprintf(temp,
sizeof(temp),
662 "Could not parse %s as a %s property",
668 "icalvalue_new_from_string cannot parse value string (%s) for \'%s\'",
670 icalerror_warn(temp);
691 value = icalvalue_new_impl(
kind);
692 value->data.v_time = tt;
758 char *dequoted_str = icalmemory_strdup_and_dequote(
str);
770 char *dequoted_str = icalmemory_strdup_and_dequote(
str);
785 "icalvalue_new_from_string got an unknown value type (%s) for \'%s\'",
787 icalerror_warn(temp);
792#if defined(__GNUC__) && !defined(__clang__)
793#pragma GCC diagnostic push
794#pragma GCC diagnostic ignored "-Wanalyzer-malloc-leak"
796 if (error != 0 && *error == 0 && value == 0) {
803#if defined(__GNUC__) && !defined(__clang__)
804#pragma GCC diagnostic pop
811 return icalvalue_new_from_string_with_error(
kind,
str, (icalproperty **)0);
816 icalerror_check_arg_rv((v != 0),
"value");
818 if (v->parent != 0) {
822 if (v->x_value != 0) {
829 if (v->data.v_attach) {
831 v->data.v_attach = NULL;
856 if (v->data.v_string != 0) {
858 v->data.v_string = 0;
863 if (v->data.v_recur != 0) {
865 v->data.v_recur = NULL;
871 if (v->data.v_requeststatus.debug != 0) {
873 v->data.v_requeststatus.debug = 0;
886 memset(&(v->data), 0,
sizeof(v->data));
887 v->id = ICAL_STRUCTURE_TYPE_VALUE_EMPTY;
900static char *icalvalue_binary_as_ical_string_r(
const icalvalue *value)
904 icalerror_check_arg_rz((value != 0),
"value");
907 snprintf(
str, 60,
"icalvalue_binary_as_ical_string is not implemented yet");
912static char *icalvalue_boolean_as_ical_string_r(
const icalvalue *value)
917 icalerror_check_arg_rz((value != 0),
"value");
922 strncpy(
str, data ?
"TRUE" :
"FALSE", 6);
928#define MAX_INT_DIGITS 12
931static char *icalvalue_int_as_ical_string_r(
const icalvalue *value)
936 icalerror_check_arg_rz((value != 0),
"value");
946static char *icalvalue_utcoffset_as_ical_string_r(
const icalvalue *value)
952 icalerror_check_arg_rz((value != 0),
"value");
957 if (abs(data) == data) {
964 m = (data - (h * 3600)) / 60;
965 s = (data - (h * 3600) - (m * 60));
971 snprintf(
str, 9,
"%c%02d%02d%02d", sign, h, m, s);
973 snprintf(
str, 9,
"%c%02d%02d", sign, h, m);
979static char *icalvalue_string_as_ical_string_r(
const icalvalue *value)
984 icalerror_check_arg_rz((value != 0),
"value");
985 data = value->data.v_string;
987 const size_t str_len = strlen(data) + 1;
990 strncpy(
str, data, str_len);
991 str[str_len - 1] =
'\0';
996static char *icalvalue_recur_as_ical_string_r(
const icalvalue *value)
1003static char *icalvalue_text_as_ical_string_r(
const icalvalue *value)
1005 return icalmemory_strdup_and_quote(value, value->data.v_string);
1008static char *icalvalue_attach_as_ical_string_r(
const icalvalue *value)
1013 icalerror_check_arg_rz((value != 0),
"value");
1021 const size_t len_url = strlen(url) + 1;
1023 strncpy(
str, url, len_url);
1024 str[len_url - 1] =
'\0';
1027 const char *data = 0;
1030 const size_t len_data = strlen(data) + 1;
1032 strncpy(
str, data, len_data);
1033 str[len_data - 1] =
'\0';
1038static char *icalvalue_duration_as_ical_string_r(
const icalvalue *value)
1042 icalerror_check_arg_rz((value != 0),
"value");
1048static void print_time_to_string(
char *
str,
const struct icaltimetype *data)
1052#if defined(__GNUC__) && !defined(__clang__)
1053#pragma GCC diagnostic push
1054#pragma GCC diagnostic ignored "-Wstringop-truncation"
1061 snprintf(temp,
sizeof(temp),
"%02d%02d%02dZ", data->
hour, data->
minute, data->
second);
1062 strncat(
str, temp, 7);
1064 snprintf(temp,
sizeof(temp),
"%02d%02d%02d", data->
hour, data->
minute, data->
second);
1065 strncat(
str, temp, 6);
1068#if defined(__GNUC__) && !defined(__clang__)
1069#pragma GCC diagnostic pop
1076#if defined(__GNUC__) && !defined(__clang__)
1077#pragma GCC diagnostic push
1078#pragma GCC diagnostic ignored "-Wstringop-truncation"
1085 snprintf(temp,
sizeof(temp),
"%04d%02d%02d", data->
year, data->
month, data->
day);
1086 strncat(
str, temp, 8);
1088#if defined(__GNUC__) && !defined(__clang__)
1089#pragma GCC diagnostic pop
1094static char *icalvalue_date_as_ical_string_r(
const icalvalue *value)
1099 icalerror_check_arg_rz((value != 0),
"value");
1105 print_date_to_string(
str, &data);
1111void print_datetime_to_string(
char *
str,
const struct icaltimetype *data)
1113#if defined(__GNUC__) && !defined(__clang__)
1114#pragma GCC diagnostic push
1115#pragma GCC diagnostic ignored "-Wstringop-truncation"
1117 char temp[20] = {0};
1121 print_date_to_string(
str, data);
1123 strncat(
str,
"T", 19);
1125 print_time_to_string(temp, data);
1126 strncat(
str, temp, 19);
1129#if defined(__GNUC__) && !defined(__clang__)
1130#pragma GCC diagnostic pop
1135static char *icalvalue_datetime_as_ical_string_r(
const icalvalue *value)
1141 icalerror_check_arg_rz((value != 0),
"value");
1153 print_datetime_to_string(
str, &data);
1158static char *icalvalue_float_as_ical_string_r(
const icalvalue *value)
1164 icalerror_check_arg_rz((value != 0),
"value");
1171 (void)setlocale(LC_NUMERIC,
"C");
1175 snprintf(
str, 40,
"%f", data);
1178 (void)setlocale(LC_NUMERIC, old_locale);
1184static char *icalvalue_geo_as_ical_string_r(
const icalvalue *value)
1189 icalerror_check_arg_rz((value != 0),
"value");
1193 snprintf(
str, 80,
"%s;%s", data.lat, data.lon);
1198static char *icalvalue_datetimeperiod_as_ical_string_r(
const icalvalue *value)
1202 icalerror_check_arg_rz((value != 0),
"value");
1211static char *icalvalue_period_as_ical_string_r(
const icalvalue *value)
1215 icalerror_check_arg_rz((value != 0),
"value");
1221static char *icalvalue_trigger_as_ical_string_r(
const icalvalue *value)
1225 icalerror_check_arg_rz((value != 0),
"value");
1250 switch (value->kind) {
1252 return icalvalue_attach_as_ical_string_r(value);
1255 return icalvalue_binary_as_ical_string_r(value);
1258 return icalvalue_boolean_as_ical_string_r(value);
1261 return icalvalue_int_as_ical_string_r(value);
1264 return icalvalue_utcoffset_as_ical_string_r(value);
1268 return icalvalue_text_as_ical_string_r(value);
1271 return icalvalue_string_as_ical_string_r(value);
1278 return icalvalue_string_as_ical_string_r(value);
1281 return icalvalue_date_as_ical_string_r(value);
1283 return icalvalue_datetime_as_ical_string_r(value);
1285 return icalvalue_duration_as_ical_string_r(value);
1288 return icalvalue_period_as_ical_string_r(value);
1290 return icalvalue_datetimeperiod_as_ical_string_r(value);
1293 return icalvalue_float_as_ical_string_r(value);
1296 return icalvalue_geo_as_ical_string_r(value);
1299 return icalvalue_recur_as_ical_string_r(value);
1302 return icalvalue_trigger_as_ical_string_r(value);
1321 if (value->x_value != 0) {
1328 if (value->x_value != 0) {
1329 return icalmemory_strdup_and_quote(value, value->x_value);
1356 const struct icalvalue_impl *impl = (
struct icalvalue_impl *)value;
1358 icalerror_check_arg_rz((value != 0),
"value");
1360 return (impl->id == ICAL_STRUCTURE_TYPE_VALUE);
1363static bool icalvalue_is_time(
const icalvalue *a)
1395 if (a->data.v_attach == b->data.v_attach) {
1403 if (a->data.v_attach == b->data.v_attach) {
1419 if (a->data.v_float > b->data.v_float) {
1421 }
else if (a->data.v_float < b->data.v_float) {
1430 if (a->data.v_int > b->data.v_int) {
1432 }
else if (a->data.v_int < b->data.v_int) {
1441 dur_b = b->data.v_duration;
1442 int a_days = (int)(7 * dur_a.
weeks + dur_a.
days) * (dur_a.
is_neg == 1 ? -1 : 1),
1443 b_days = (
int)(7 * dur_b.weeks + dur_b.days) * (dur_a.
is_neg == 1 ? -1 : 1);
1445 (dur_a.
is_neg == 1 ? -1 : 1),
1446 b_secs = (
int)(dur_b.seconds + 60 * (dur_b.minutes + 60 * dur_b.hours)) *
1447 (dur_b.is_neg == 1 ? -1 : 1);
1449 if (a_secs == b_secs) {
1450 if (a_days > b_days) {
1452 }
else if (a_days < b_days) {
1457 }
else if (a_days == b_days) {
1458 if (a_secs > b_secs) {
1481 char *temp1, *temp2;
1487 r = strcmp(temp1, temp2);
1543 icalerror_warn(
"Comparison not implemented for value type");
1564 icalerror_check_arg_rv((value != 0),
"value");
1566 value->parent = property;
1571 return value->parent;
1579 if ((szText == 0) || (szEncText == 0)) {
1589 ptr = icalvalue_text_as_ical_string_r(value);
1594 if ((
int)strlen(ptr) >= maxBufferLen) {
1600 strcpy(szEncText, ptr);
1614 if ((szText == 0) || (szDecText == 0) || (maxBufferLen <= 0)) {
1618 buf_sz = strlen(szText) + 1;
1625 for (p = szText; *p != 0; p++) {
1633 if (str_p -
str > maxBufferLen) {
1640 if ((
int)strlen(
str) >= maxBufferLen) {
1645 strcpy(szDecText,
str);
icalattach * icalattach_new_from_data(const char *data, icalattach_free_fn_t free_fn, void *free_fn_data)
Creates new icalattach object from data.
void icalattach_unref(icalattach *attach)
Decrements reference count of the icalattach.
void icalattach_ref(icalattach *attach)
Increments reference count of the icalattach.
unsigned char * icalattach_get_data(icalattach *attach)
Returns the data of the icalattach object.
const char * icalattach_get_url(icalattach *attach)
Returns the URL of the icalattach object.
icalattach * icalattach_new_from_url(const char *url)
Creates new icalattach object from a URL.
bool icalattach_get_is_url(const icalattach *attach)
Determines if attach is an URL.
struct icalattach_impl icalattach
An iCal attach object representing a link to a document object.
struct icalparameter_impl icalparameter
icalparameter_xliccomparetype
@ ICAL_XLICCOMPARETYPE_NOTEQUAL
@ ICAL_XLICCOMPARETYPE_LESS
@ ICAL_XLICCOMPARETYPE_GREATER
@ ICAL_XLICCOMPARETYPE_EQUAL
@ ICAL_XLICCOMPARETYPE_NONE
@ ICAL_XLICERRORTYPE_VALUEPARSEERROR
icalparameter * icalparameter_new_xlicerrortype(icalparameter_xlicerrortype v)
icalproperty * icalproperty_vanew_xlicerror(const char *v,...)
@ ICAL_LOCATIONTYPE_PROPERTY
@ ICAL_CATEGORIES_PROPERTY
@ ICAL_POLLPROPERTIES_PROPERTY
@ ICAL_RESOURCES_PROPERTY
icalvalue * icalvalue_new_query(const char *v)
struct icaltimetype icalvalue_get_datetime(const icalvalue *value)
enum icalproperty_status icalvalue_get_status(const icalvalue *value)
icalvalue * icalvalue_new_trigger(struct icaltriggertype v)
struct icaltriggertype icalvalue_get_trigger(const icalvalue *value)
float icalvalue_get_float(const icalvalue *value)
icalvalue * icalvalue_new_geo(struct icalgeotype v)
icalvalue * icalvalue_new_uid(const char *v)
icalvalue * icalvalue_new_x(const char *v)
icalvalue * icalvalue_new_integer(int v)
icalvalue * icalvalue_new_utcoffset(int v)
void icalvalue_set_x(icalvalue *value, const char *v)
struct icaltimetype icalvalue_get_date(const icalvalue *value)
icalvalue * icalvalue_new_uri(const char *v)
icalvalue * icalvalue_new_xmlreference(const char *v)
int icalvalue_get_integer(const icalvalue *value)
enum icalproperty_action icalvalue_get_action(const icalvalue *value)
icalvalue * icalvalue_new_requeststatus(struct icalreqstattype v)
enum icalproperty_transp icalvalue_get_transp(const icalvalue *value)
icalvalue * icalvalue_new_period(struct icalperiodtype v)
int icalvalue_get_utcoffset(const icalvalue *value)
icalattach * icalvalue_get_attach(const icalvalue *value)
icalvalue * icalvalue_new_color(const char *v)
icalvalue * icalvalue_new_boolean(int v)
icalvalue * icalvalue_new_duration(struct icaldurationtype v)
icalvalue * icalvalue_new_attach(icalattach *attach)
@ ICAL_RESOURCETYPE_VALUE
@ ICAL_XMLREFERENCE_VALUE
@ ICAL_DATETIMEPERIOD_VALUE
@ ICAL_POLLCOMPLETION_VALUE
@ ICAL_REQUESTSTATUS_VALUE
@ ICAL_PARTICIPANTTYPE_VALUE
icalvalue * icalvalue_new_float(float v)
struct icaldatetimeperiodtype icalvalue_get_datetimeperiod(const icalvalue *value)
icalvalue * icalvalue_new_string(const char *v)
enum icalproperty_method icalvalue_get_method(const icalvalue *value)
struct icaldurationtype icalvalue_get_duration(const icalvalue *value)
icalvalue * icalvalue_new_recur(struct icalrecurrencetype *recur)
icalvalue * icalvalue_new_caladdress(const char *v)
icalvalue * icalvalue_new_datetime(struct icaltimetype v)
struct icalperiodtype icalvalue_get_period(const icalvalue *value)
struct icalgeotype icalvalue_get_geo(const icalvalue *value)
icalvalue * icalvalue_new_text(const char *v)
int icalvalue_get_boolean(const icalvalue *value)
struct icalvalue_impl icalvalue
bool icaldurationtype_is_bad_duration(struct icaldurationtype d)
Checks if a duration is a bad duration.
char * icaldurationtype_as_ical_string_r(struct icaldurationtype d)
struct icaldurationtype icaldurationtype_from_string(const char *str)
Creates a new icaldurationtype from a duration given as a string.
enum icalrequeststatus kind
void icalerror_set_errno(icalerrorenum x)
Sets the icalerrno to a given error.
size_t icallimit_get(icallimits_kind kind)
Defines the interface for getting/setting internal library limits.
void icalmemory_free_buffer(void *buf)
Releases a buffer.
char * icalmemory_strdup(const char *s)
Creates a duplicate of a string.
void icalmemory_append_string(char **buf, char **pos, size_t *buf_size, const char *string)
Appends a string to a buffer.
void * icalmemory_new_buffer(size_t size)
Creates new buffer with the specified size.
void icalmemory_append_char(char **buf, char **pos, size_t *buf_size, char ch)
Appends a character to a buffer.
void icalmemory_add_tmp_buffer(void *buf)
Adds an externally allocated buffer to the ring.
Common memory management routines.
char * icalperiodtype_as_ical_string_r(struct icalperiodtype p)
Converts an icalperiodtype into an iCal-formatted string.
bool icalperiodtype_is_null_period(struct icalperiodtype p)
struct icalperiodtype icalperiodtype_from_string(const char *str)
Constructs a new icalperiodtype from str.
icalproperty_kind icalproperty_isa(const icalproperty *p)
bool icalproperty_get_allow_empty_properties(void)
char * icalproperty_enum_to_string_r(int e)
bool icalproperty_enum_belongs_to_property(icalproperty_kind kind, int e)
icalproperty_kind icalproperty_value_kind_to_kind(icalvalue_kind kind)
int icalproperty_kind_and_string_to_enum(const int kind, const char *str)
struct icalrecurrencetype * icalrecurrencetype_new_from_string(const char *str)
struct icalrecurrencetype * icalrecurrencetype_clone(struct icalrecurrencetype *recur)
void icalrecurrencetype_unref(struct icalrecurrencetype *recur)
char * icalrecurrencetype_as_string_r(struct icalrecurrencetype *recur)
bool icaltime_is_date(const struct icaltimetype t)
struct icaltimetype icaltime_from_string(const char *str)
bool icaltime_is_utc(const struct icaltimetype t)
bool icaltime_is_null_time(const struct icaltimetype t)
char * icaltime_as_ical_string_r(const struct icaltimetype tt)
Defines the data structure for representing date-times.
struct icaltriggertype icaltriggertype_from_string(const char *str)
bool icaltriggertype_is_bad_trigger(struct icaltriggertype tr)
struct icalreqstattype icalreqstattype_from_string(const char *str)
char * icalreqstattype_as_string_r(struct icalreqstattype stat)
icalproperty * icalvalue_get_parent(const icalvalue *value)
icalvalue_kind icalvalue_isa(const icalvalue *value)
bool icalvalue_is_valid(const icalvalue *value)
bool icalvalue_isa_value(void *value)
icalvalue * icalvalue_clone(const icalvalue *old)
icalvalue * icalvalue_new_from_string(icalvalue_kind kind, const char *str)
void icalvalue_set_parent(icalvalue *value, icalproperty *property)
icalparameter_xliccomparetype icalvalue_compare(const icalvalue *a, const icalvalue *b)
icalvalue * icalvalue_new(icalvalue_kind kind)
bool icalvalue_decode_ical_string(const char *szText, char *szDecText, int maxBufferLen)
void icalvalue_reset_kind(icalvalue *value)
void icalvalue_free(icalvalue *v)
char * icalvalue_as_ical_string_r(const icalvalue *value)
bool icalvalue_encode_ical_string(const char *szText, char *szEncText, int maxBufferLen)
const char * icalvalue_as_ical_string(const icalvalue *value)
Defines the data structure representing iCalendar parameter values.
bool icalvalue_kind_is_valid(const icalvalue_kind kind)
const char * icalvalue_kind_to_string(const icalvalue_kind kind)
struct icalperiodtype period