/*======================================================================
 FILE: vcardderivedvalue.c
 CREATOR: Ken Murchison 24 Aug 2022 <murch@fastmailteam.com>

 SPDX-FileCopyrightText: 2022, Fastmail Pty. Ltd. (https://fastmail.com)
 SPDX-License-Identifier: LGPL-2.1-only OR MPL-2.0
 ======================================================================*/

/**
 * @file vcardderivedvalue.c
 * @brief vCard values.
 */

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include "vcardderivedvalue.h"
#include "vcardvalue.h"
#include "vcardvalueimpl.h"
#include "icalerror_p.h"
#include "icalmemory.h"

#include <errno.h>
#include <stdlib.h>
#include <string.h>

struct vcardvalue_impl *vcardvalue_new_impl(vcardvalue_kind kind);

/* This map associates each of the value types with its string
   representation */
struct vcardvalue_kind_map
{
    vcardvalue_kind kind;
    char name[20];
};

static const struct vcardvalue_kind_map value_map[21]={
    {VCARD_BOOLEAN_VALUE,"BOOLEAN"},
    {VCARD_DATE_VALUE,"DATE"},
    {VCARD_DATEANDORTIME_VALUE,"DATE-AND-OR-TIME"},
    {VCARD_DATETIME_VALUE,"DATE-TIME"},
    {VCARD_FLOAT_VALUE,"FLOAT"},
    {VCARD_GEO_VALUE,"GEO"},
    {VCARD_GRAMGENDER_VALUE,"GRAMGENDER"},
    {VCARD_INTEGER_VALUE,"INTEGER"},
    {VCARD_KIND_VALUE,"KIND"},
    {VCARD_LANGUAGETAG_VALUE,"LANGUAGE-TAG"},
    {VCARD_STRUCTURED_VALUE,"STRUCTURED"},
    {VCARD_TEXT_VALUE,"TEXT"},
    {VCARD_TEXTLIST_VALUE,"TEXTLIST"},
    {VCARD_TIME_VALUE,"TIME"},
    {VCARD_TIMESTAMP_VALUE,"TIMESTAMP"},
    {VCARD_TZ_VALUE,"TZ"},
    {VCARD_URI_VALUE,"URI"},
    {VCARD_UTCOFFSET_VALUE,"UTC-OFFSET"},
    {VCARD_VERSION_VALUE,"VERSION"},
    {VCARD_X_VALUE,"X"},
    {VCARD_NO_VALUE,""}
};
vcardvalue *vcardvalue_new_boolean(int v)
{
    struct vcardvalue_impl *impl;

    impl = vcardvalue_new_impl(VCARD_BOOLEAN_VALUE);
    vcardvalue_set_boolean((vcardvalue *)impl, v);
    return (vcardvalue*)impl;
}

void vcardvalue_set_boolean(vcardvalue *value, int v)
{
    struct vcardvalue_impl *impl;
    icalerror_check_arg_rv((value != 0), "value");

    icalerror_check_value_type(value, VCARD_BOOLEAN_VALUE);
    impl = (struct vcardvalue_impl *)value;

    impl->data.v_int = v;
    vcardvalue_reset_kind(impl);
}

int vcardvalue_get_boolean(const vcardvalue *value)
{
    icalerror_check_arg((value != 0), "value");
    if (!value) {
        return 0;
    }
    icalerror_check_value_type(value, VCARD_BOOLEAN_VALUE);
    return (((struct vcardvalue_impl *)value)->data.v_int);
}

vcardvalue *vcardvalue_new_date(vcardtimetype v)
{
    struct vcardvalue_impl *impl;

    impl = vcardvalue_new_impl(VCARD_DATE_VALUE);
    vcardvalue_set_date((vcardvalue *)impl, v);
    return (vcardvalue*)impl;
}

void vcardvalue_set_date(vcardvalue *value, vcardtimetype v)
{
    struct vcardvalue_impl *impl;
    icalerror_check_arg_rv((value != 0), "value");

    icalerror_check_value_type(value, VCARD_DATE_VALUE);
    impl = (struct vcardvalue_impl *)value;

    impl->data.v_time = v;
    vcardvalue_reset_kind(impl);
}

vcardtimetype vcardvalue_get_date(const vcardvalue *value)
{
    icalerror_check_arg((value != 0), "value");
    if (!value) {
        return vcardtime_null_datetime();
    }
    icalerror_check_value_type(value, VCARD_DATE_VALUE);
    return (((struct vcardvalue_impl *)value)->data.v_time);
}

vcardvalue *vcardvalue_new_dateandortime(vcardtimetype v)
{
    struct vcardvalue_impl *impl;

    impl = vcardvalue_new_impl(VCARD_DATEANDORTIME_VALUE);
    vcardvalue_set_dateandortime((vcardvalue *)impl, v);
    return (vcardvalue*)impl;
}

void vcardvalue_set_dateandortime(vcardvalue *value, vcardtimetype v)
{
    struct vcardvalue_impl *impl;
    icalerror_check_arg_rv((value != 0), "value");

    icalerror_check_value_type(value, VCARD_DATEANDORTIME_VALUE);
    impl = (struct vcardvalue_impl *)value;

    impl->data.v_time = v;
    vcardvalue_reset_kind(impl);
}

vcardtimetype vcardvalue_get_dateandortime(const vcardvalue *value)
{
    icalerror_check_arg((value != 0), "value");
    if (!value) {
        return vcardtime_null_datetime();
    }
    icalerror_check_value_type(value, VCARD_DATEANDORTIME_VALUE);
    return (((struct vcardvalue_impl *)value)->data.v_time);
}

vcardvalue *vcardvalue_new_datetime(vcardtimetype v)
{
    struct vcardvalue_impl *impl;

    impl = vcardvalue_new_impl(VCARD_DATETIME_VALUE);
    vcardvalue_set_datetime((vcardvalue *)impl, v);
    return (vcardvalue*)impl;
}

void vcardvalue_set_datetime(vcardvalue *value, vcardtimetype v)
{
    struct vcardvalue_impl *impl;
    icalerror_check_arg_rv((value != 0), "value");

    icalerror_check_value_type(value, VCARD_DATETIME_VALUE);
    impl = (struct vcardvalue_impl *)value;

    impl->data.v_time = v;
    vcardvalue_reset_kind(impl);
}

vcardtimetype vcardvalue_get_datetime(const vcardvalue *value)
{
    icalerror_check_arg((value != 0), "value");
    if (!value) {
        return vcardtime_null_datetime();
    }
    icalerror_check_value_type(value, VCARD_DATETIME_VALUE);
    return (((struct vcardvalue_impl *)value)->data.v_time);
}

vcardvalue *vcardvalue_new_float(float v)
{
    struct vcardvalue_impl *impl;

    impl = vcardvalue_new_impl(VCARD_FLOAT_VALUE);
    vcardvalue_set_float((vcardvalue *)impl, v);
    return (vcardvalue*)impl;
}

void vcardvalue_set_float(vcardvalue *value, float v)
{
    struct vcardvalue_impl *impl;
    icalerror_check_arg_rv((value != 0), "value");

    icalerror_check_value_type(value, VCARD_FLOAT_VALUE);
    impl = (struct vcardvalue_impl *)value;

    impl->data.v_float = v;
    vcardvalue_reset_kind(impl);
}

float vcardvalue_get_float(const vcardvalue *value)
{
    icalerror_check_arg((value != 0), "value");
    if (!value) {
        return 0.0;
     }
    icalerror_check_value_type(value, VCARD_FLOAT_VALUE);
    return (((struct vcardvalue_impl *)value)->data.v_float);
}

vcardvalue *vcardvalue_new_gramgender(enum vcardproperty_gramgender v)
{
    struct vcardvalue_impl *impl;

    impl = vcardvalue_new_impl(VCARD_GRAMGENDER_VALUE);
    vcardvalue_set_gramgender((vcardvalue *)impl, v);
    return (vcardvalue*)impl;
}

void vcardvalue_set_gramgender(vcardvalue *value, enum vcardproperty_gramgender v)
{
    struct vcardvalue_impl *impl;
    icalerror_check_arg_rv((value != 0), "value");

    icalerror_check_value_type(value, VCARD_GRAMGENDER_VALUE);
    impl = (struct vcardvalue_impl *)value;

    impl->data.v_enum = (int)v;
    vcardvalue_reset_kind(impl);
}

enum vcardproperty_gramgender vcardvalue_get_gramgender(const vcardvalue *value)
{
    icalerror_check_arg((value != 0), "value");
    if (!value) {
        return VCARD_GRAMGENDER_NONE;
    }
    icalerror_check_value_type(value, VCARD_GRAMGENDER_VALUE);
    return (enum vcardproperty_gramgender)(((struct vcardvalue_impl *)value)->data.v_enum);
}

vcardvalue *vcardvalue_new_integer(int v)
{
    struct vcardvalue_impl *impl;

    impl = vcardvalue_new_impl(VCARD_INTEGER_VALUE);
    vcardvalue_set_integer((vcardvalue *)impl, v);
    return (vcardvalue*)impl;
}

void vcardvalue_set_integer(vcardvalue *value, int v)
{
    struct vcardvalue_impl *impl;
    icalerror_check_arg_rv((value != 0), "value");

    icalerror_check_value_type(value, VCARD_INTEGER_VALUE);
    impl = (struct vcardvalue_impl *)value;

    impl->data.v_int = v;
    vcardvalue_reset_kind(impl);
}

int vcardvalue_get_integer(const vcardvalue *value)
{
    icalerror_check_arg((value != 0), "value");
    if (!value) {
        return 0;
    }
    icalerror_check_value_type(value, VCARD_INTEGER_VALUE);
    return (((struct vcardvalue_impl *)value)->data.v_int);
}

vcardvalue *vcardvalue_new_kind(enum vcardproperty_kindenum v)
{
    struct vcardvalue_impl *impl;

    impl = vcardvalue_new_impl(VCARD_KIND_VALUE);
    vcardvalue_set_kind((vcardvalue *)impl, v);
    return (vcardvalue*)impl;
}

void vcardvalue_set_kind(vcardvalue *value, enum vcardproperty_kindenum v)
{
    struct vcardvalue_impl *impl;
    icalerror_check_arg_rv((value != 0), "value");

    icalerror_check_value_type(value, VCARD_KIND_VALUE);
    impl = (struct vcardvalue_impl *)value;

    impl->data.v_enum = (int)v;
    vcardvalue_reset_kind(impl);
}

enum vcardproperty_kindenum vcardvalue_get_kind(const vcardvalue *value)
{
    icalerror_check_arg((value != 0), "value");
    if (!value) {
        return VCARD_KIND_NONE;
    }
    icalerror_check_value_type(value, VCARD_KIND_VALUE);
    return (enum vcardproperty_kindenum)(((struct vcardvalue_impl *)value)->data.v_enum);
}

vcardvalue *vcardvalue_new_languagetag(const char * v)
{
    struct vcardvalue_impl *impl;
    icalerror_check_arg_rz((v != 0), "v");

    impl = vcardvalue_new_impl(VCARD_LANGUAGETAG_VALUE);
    vcardvalue_set_languagetag((vcardvalue *)impl, v);
    return (vcardvalue*)impl;
}

void vcardvalue_set_languagetag(vcardvalue *value, const char * v)
{
    struct vcardvalue_impl *impl;
    icalerror_check_arg_rv((value != 0), "value");
    icalerror_check_arg_rv((v != 0), "v");

    icalerror_check_value_type(value, VCARD_LANGUAGETAG_VALUE);
    impl = (struct vcardvalue_impl *)value;
    if (impl->data.v_string != 0) {
        icalmemory_free_buffer((void *)impl->data.v_string);
    }

    impl->data.v_string = icalmemory_strdup(v);

    if (impl->data.v_string == 0) {
        errno = ENOMEM;
    }

    vcardvalue_reset_kind(impl);
}

const char * vcardvalue_get_languagetag(const vcardvalue *value)
{
    icalerror_check_arg_rz((value != 0), "value");
    icalerror_check_value_type(value, VCARD_LANGUAGETAG_VALUE);
    return (((struct vcardvalue_impl *)value)->data.v_string);
}

vcardvalue *vcardvalue_new_text(const char * v)
{
    struct vcardvalue_impl *impl;
    icalerror_check_arg_rz((v != 0), "v");

    impl = vcardvalue_new_impl(VCARD_TEXT_VALUE);
    vcardvalue_set_text((vcardvalue *)impl, v);
    return (vcardvalue*)impl;
}

void vcardvalue_set_text(vcardvalue *value, const char * v)
{
    struct vcardvalue_impl *impl;
    icalerror_check_arg_rv((value != 0), "value");
    icalerror_check_arg_rv((v != 0), "v");

    icalerror_check_value_type(value, VCARD_TEXT_VALUE);
    impl = (struct vcardvalue_impl *)value;
    if (impl->data.v_string != 0) {
        icalmemory_free_buffer((void *)impl->data.v_string);
    }

    impl->data.v_string = icalmemory_strdup(v);

    if (impl->data.v_string == 0) {
        errno = ENOMEM;
    }

    vcardvalue_reset_kind(impl);
}

const char * vcardvalue_get_text(const vcardvalue *value)
{
    icalerror_check_arg_rz((value != 0), "value");
    icalerror_check_value_type(value, VCARD_TEXT_VALUE);
    return (((struct vcardvalue_impl *)value)->data.v_string);
}

vcardvalue *vcardvalue_new_textlist(vcardstrarray * v)
{
    struct vcardvalue_impl *impl;
    icalerror_check_arg_rz((v != 0), "v");

    impl = vcardvalue_new_impl(VCARD_TEXTLIST_VALUE);
    vcardvalue_set_textlist((vcardvalue *)impl, v);
    return (vcardvalue*)impl;
}

void vcardvalue_set_textlist(vcardvalue *value, vcardstrarray * v)
{
    struct vcardvalue_impl *impl;
    icalerror_check_arg_rv((value != 0), "value");
    icalerror_check_arg_rv((v != 0), "v");

    icalerror_check_value_type(value, VCARD_TEXTLIST_VALUE);
    impl = (struct vcardvalue_impl *)value;
    vcardstrarray_free(impl->data.v_textlist);

    impl->data.v_textlist = v;
    vcardvalue_reset_kind(impl);
}

vcardstrarray * vcardvalue_get_textlist(const vcardvalue *value)
{
    icalerror_check_arg_rz((value != 0), "value");
    icalerror_check_value_type(value, VCARD_TEXTLIST_VALUE);
    return (((struct vcardvalue_impl *)value)->data.v_textlist);
}

vcardvalue *vcardvalue_new_time(vcardtimetype v)
{
    struct vcardvalue_impl *impl;

    impl = vcardvalue_new_impl(VCARD_TIME_VALUE);
    vcardvalue_set_time((vcardvalue *)impl, v);
    return (vcardvalue*)impl;
}

void vcardvalue_set_time(vcardvalue *value, vcardtimetype v)
{
    struct vcardvalue_impl *impl;
    icalerror_check_arg_rv((value != 0), "value");

    icalerror_check_value_type(value, VCARD_TIME_VALUE);
    impl = (struct vcardvalue_impl *)value;

    impl->data.v_time = v;
    vcardvalue_reset_kind(impl);
}

vcardtimetype vcardvalue_get_time(const vcardvalue *value)
{
    icalerror_check_arg((value != 0), "value");
    if (!value) {
        return vcardtime_null_datetime();
    }
    icalerror_check_value_type(value, VCARD_TIME_VALUE);
    return (((struct vcardvalue_impl *)value)->data.v_time);
}

vcardvalue *vcardvalue_new_timestamp(vcardtimetype v)
{
    struct vcardvalue_impl *impl;

    impl = vcardvalue_new_impl(VCARD_TIMESTAMP_VALUE);
    vcardvalue_set_timestamp((vcardvalue *)impl, v);
    return (vcardvalue*)impl;
}

void vcardvalue_set_timestamp(vcardvalue *value, vcardtimetype v)
{
    struct vcardvalue_impl *impl;
    icalerror_check_arg_rv((value != 0), "value");

    icalerror_check_value_type(value, VCARD_TIMESTAMP_VALUE);
    impl = (struct vcardvalue_impl *)value;

    impl->data.v_time = v;
    vcardvalue_reset_kind(impl);
}

vcardtimetype vcardvalue_get_timestamp(const vcardvalue *value)
{
    icalerror_check_arg((value != 0), "value");
    if (!value) {
        return vcardtime_null_datetime();
    }
    icalerror_check_value_type(value, VCARD_TIMESTAMP_VALUE);
    return (((struct vcardvalue_impl *)value)->data.v_time);
}

vcardvalue *vcardvalue_new_uri(const char * v)
{
    struct vcardvalue_impl *impl;
    icalerror_check_arg_rz((v != 0), "v");

    impl = vcardvalue_new_impl(VCARD_URI_VALUE);
    vcardvalue_set_uri((vcardvalue *)impl, v);
    return (vcardvalue*)impl;
}

void vcardvalue_set_uri(vcardvalue *value, const char * v)
{
    struct vcardvalue_impl *impl;
    icalerror_check_arg_rv((value != 0), "value");
    icalerror_check_arg_rv((v != 0), "v");

    icalerror_check_value_type(value, VCARD_URI_VALUE);
    impl = (struct vcardvalue_impl *)value;
    if (impl->data.v_string != 0) {
        icalmemory_free_buffer((void *)impl->data.v_string);
    }

    impl->data.v_string = icalmemory_strdup(v);

    if (impl->data.v_string == 0) {
        errno = ENOMEM;
    }

    vcardvalue_reset_kind(impl);
}

const char * vcardvalue_get_uri(const vcardvalue *value)
{
    icalerror_check_arg_rz((value != 0), "value");
    icalerror_check_value_type(value, VCARD_URI_VALUE);
    return (((struct vcardvalue_impl *)value)->data.v_string);
}

vcardvalue *vcardvalue_new_utcoffset(int v)
{
    struct vcardvalue_impl *impl;

    impl = vcardvalue_new_impl(VCARD_UTCOFFSET_VALUE);
    vcardvalue_set_utcoffset((vcardvalue *)impl, v);
    return (vcardvalue*)impl;
}

void vcardvalue_set_utcoffset(vcardvalue *value, int v)
{
    struct vcardvalue_impl *impl;
    icalerror_check_arg_rv((value != 0), "value");

    icalerror_check_value_type(value, VCARD_UTCOFFSET_VALUE);
    impl = (struct vcardvalue_impl *)value;

    impl->data.v_int = v;
    vcardvalue_reset_kind(impl);
}

int vcardvalue_get_utcoffset(const vcardvalue *value)
{
    icalerror_check_arg((value != 0), "value");
    if (!value) {
        return 0;
    }
    icalerror_check_value_type(value, VCARD_UTCOFFSET_VALUE);
    return (((struct vcardvalue_impl *)value)->data.v_int);
}

vcardvalue *vcardvalue_new_version(enum vcardproperty_version v)
{
    struct vcardvalue_impl *impl;

    impl = vcardvalue_new_impl(VCARD_VERSION_VALUE);
    vcardvalue_set_version((vcardvalue *)impl, v);
    return (vcardvalue*)impl;
}

void vcardvalue_set_version(vcardvalue *value, enum vcardproperty_version v)
{
    struct vcardvalue_impl *impl;
    icalerror_check_arg_rv((value != 0), "value");

    icalerror_check_value_type(value, VCARD_VERSION_VALUE);
    impl = (struct vcardvalue_impl *)value;

    impl->data.v_enum = (int)v;
    vcardvalue_reset_kind(impl);
}

enum vcardproperty_version vcardvalue_get_version(const vcardvalue *value)
{
    icalerror_check_arg((value != 0), "value");
    if (!value) {
        return VCARD_VERSION_NONE;
    }
    icalerror_check_value_type(value, VCARD_VERSION_VALUE);
    return (enum vcardproperty_version)(((struct vcardvalue_impl *)value)->data.v_enum);
}

vcardvalue *vcardvalue_new_structured(vcardstructuredtype *v)
{
    struct vcardvalue_impl *impl;
    icalerror_check_arg_rz((v != 0), "v");

    impl = vcardvalue_new_impl(VCARD_STRUCTURED_VALUE);
    vcardvalue_set_structured((vcardvalue *)impl, v);
    return (vcardvalue*)impl;
}

void vcardvalue_set_structured(vcardvalue *value, vcardstructuredtype *v)
{
    struct vcardvalue_impl *impl;

    icalerror_check_arg_rv((value != 0), "value");
    icalerror_check_arg_rv((v != 0), "v");

    icalerror_check_value_type(value, VCARD_STRUCTURED_VALUE);
    impl = (struct vcardvalue_impl *)value;

    vcardstructured_ref(v);
    impl->data.v_structured = v;

    vcardvalue_reset_kind(impl);
}

vcardstructuredtype *vcardvalue_get_structured(const vcardvalue *value)
{
    icalerror_check_arg((value != 0), "value");
    icalerror_check_value_type(value, VCARD_STRUCTURED_VALUE);
    return ((struct vcardvalue_impl *)value)->data.v_structured;
}

vcardvalue *vcardvalue_new_geo(struct vcardgeotype v)
{
    struct vcardvalue_impl *impl = vcardvalue_new_impl(VCARD_GEO_VALUE);

    vcardvalue_set_geo((vcardvalue *) impl, v);

    return (vcardvalue *) impl;
}

void vcardvalue_set_geo(vcardvalue *value, struct vcardgeotype v)
{
    struct vcardvalue_impl *impl;

    icalerror_check_arg_rv((value != 0), "value");

    impl = (struct vcardvalue_impl *)value;

    if (v.uri) {
        if (impl->kind == VCARD_GEO_VALUE) {
            impl->data.v_geo.coords.lat[0] = '\0';
            impl->data.v_geo.coords.lon[0] = '\0';
        }
        impl->kind = VCARD_URI_VALUE;
        vcardvalue_set_uri(value, v.uri);
    } else {
        if (impl->kind == VCARD_URI_VALUE) {
            if (impl->data.v_string != 0) {
                icalmemory_free_buffer((void *)impl->data.v_string);
                impl->data.v_string = 0;
            }
        }
        impl->data.v_geo = v;
        impl->data.v_geo.uri = NULL;
        impl->kind = VCARD_GEO_VALUE;
        vcardvalue_reset_kind(impl);
    }
}

struct vcardgeotype vcardvalue_get_geo(const vcardvalue *impl)
{
    struct vcardgeotype geo = { 0 };

    icalerror_check_arg_rx((impl != 0), "value", geo);

    if (impl->kind == VCARD_URI_VALUE) {
        geo.uri = impl->data.v_string;
    } else if (impl->kind == VCARD_GEO_VALUE) {
        geo = impl->data.v_geo;
        geo.uri = NULL;
    } else {
        icalerror_set_errno(ICAL_BADARG_ERROR);
    }

    return geo;
}

vcardvalue *vcardvalue_new_tz(struct vcardtztype v)
{
    struct vcardvalue_impl *impl = vcardvalue_new_impl(VCARD_TZ_VALUE);

    vcardvalue_set_tz((vcardvalue *) impl, v);

    return (vcardvalue *) impl;
}

void vcardvalue_set_tz(vcardvalue *value, struct vcardtztype v)
{
    icalerror_check_arg_rv((value != 0), "value");

    if (v.tzid) {
        value->kind = VCARD_TEXT_VALUE;
        vcardvalue_set_text(value, v.tzid);
    } else if (v.uri) {
        value->kind = VCARD_URI_VALUE;
        vcardvalue_set_uri(value, v.uri);
    } else {
        value->kind = VCARD_UTCOFFSET_VALUE;
        vcardvalue_set_utcoffset(value, v.utcoffset);
    }
}

struct vcardtztype vcardvalue_get_tz(const vcardvalue *impl)
{
    struct vcardtztype tz = { 0 };

    icalerror_check_arg_rx((impl != 0), "value", tz);

    if (impl->kind == VCARD_TEXT_VALUE) {
        tz.tzid = impl->data.v_string;
    } else if (impl->kind == VCARD_URI_VALUE) {
        tz.uri = impl->data.v_string;
    } else if (impl->kind == VCARD_UTCOFFSET_VALUE) {
        tz.utcoffset = impl->data.v_int;
    } else {
        icalerror_set_errno(ICAL_BADARG_ERROR);
    }

    return tz;
}

bool vcardvalue_kind_is_valid(const vcardvalue_kind kind)
{
    int i = 0;
    int num_values = (int)(sizeof(value_map) / sizeof(value_map[0]));

    if (kind == VCARD_ANY_VALUE) {
        return false;
    }

    num_values--;
    do {
        if (value_map[i].kind == kind) {
            return true;
        }
    } while (i++ < num_values);

    return false;
}

const char *vcardvalue_kind_to_string(const vcardvalue_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;
}

vcardvalue_kind vcardvalue_string_to_kind(const char *str)
{
    int i, num_values;

    if (str == 0) {
        return VCARD_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 VCARD_NO_VALUE;
}

vcardvalue *vcardvalue_new_x(const char *v)
{
    struct vcardvalue_impl *impl;

    icalerror_check_arg_rz((v != 0), "v");

    impl = vcardvalue_new_impl(VCARD_X_VALUE);

    vcardvalue_set_x((vcardvalue *) impl, v);
    return (vcardvalue *) impl;
}

void vcardvalue_set_x(vcardvalue *impl, const char *v)
{
    icalerror_check_arg_rv((impl != 0), "value");
    icalerror_check_arg_rv((v != 0), "v");

    if (impl->x_value != 0) {
        icalmemory_free_buffer((void *)impl->x_value);
    }

    impl->x_value = icalmemory_strdup(v);

    if (impl->x_value == 0) {
        errno = ENOMEM;
    }
}

const char *vcardvalue_get_x(const vcardvalue *value)
{
    icalerror_check_arg_rz((value != 0), "value");
    icalerror_check_value_type(value, VCARD_X_VALUE);
    return value->x_value;
}

/* The remaining interfaces are 'new', 'set' and 'get' for each of the value
   types */

/* Everything below this line is machine generated. Do not edit. */
