(file) Return to helpers.c CVS log (file) (dir) Up to [OMI] / omi / base

File: [OMI] / omi / base / helpers.c (download)
Revision: 1.1.1.1 (vendor branch), Wed May 30 21:47:49 2012 UTC (12 years ago) by mike
Branch: TOG
CVS Tags: OMI_1_0_2_Branch, OMI_1_0_2, OMI_1_0_1_PRE, OMI_1_0_1, OMI_1_0_0
Changes since 1.1: +0 -0 lines
Initial Import

/*
**==============================================================================
**
** Open Management Infrastructure (OMI)
**
** Copyright (c) Microsoft Corporation
** 
** Licensed under the Apache License, Version 2.0 (the "License"); you may not 
** use this file except in compliance with the License. You may obtain a copy 
** of the License at 
**
**     http://www.apache.org/licenses/LICENSE-2.0 
**
** THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
** KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED 
** WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, 
** MERCHANTABLITY OR NON-INFRINGEMENT. 
**
** See the Apache 2 License for the specific language governing permissions 
** and limitations under the License.
**
**==============================================================================
*/

#include <ctype.h>
#include "helpers.h"
#include "types.h"
#include "strings.h"
#include "alloc.h"
#include "io.h"

#define T MI_T

static const MI_Char* _ParseNumber(const MI_Char* p, unsigned long* n)
{
    MI_Char* end;

    *n = Ztoul(p, &end, 10);

    if (end == p)
        return NULL;

    return end;
}

static const MI_Char* _ParseDecimalPart(
    const MI_Char* p, 
    unsigned long* n)
{
    MI_Char* end;
    int i;
    MI_Char buf[7];
    unsigned long x;

    x = Ztoul(p, &end, 10);

    if (end == p)
    {
        /* Zero decimal part */
        *n = 0;
        return p;
    }

    for (i = 0; i < 6 && p != end; i++, p++)
        buf[i] = *p;

    for (; i < 6; i++)
        buf[i] = '0';

    buf[6] = '\0';

    *n = Ztoul(buf, NULL, 10);

    return end;
}

static int _ParseWSManDuration(const MI_Char* str, MI_Datetime* x)
{
    const MI_Char* p = str;
    int foundT = 0;
    unsigned long years = 0;
    unsigned long months = 0;
    unsigned long days = 0;
    unsigned long hours = 0;
    unsigned long minutes = 0;
    unsigned long seconds = 0;
    unsigned long microseconds = 0;

    /* xs:duration: PnYnMnDTnHnMnS */
    if (*p != 'P')
        return -1;

    /* [xs:duration]
     *
     * Format: "PnYnMnDTnHnMnS", where
     *     P - period (required)
     *     nY - number of years
     *     nM - number of month
     *     nD - number of days
     *     T - start of time section (required for the following)
     *     nH - number of hours
     *     nM - number of minutes
     *     nS - number of seconds
     *
     * Examples:
     *     -P10D (rejected)
     *     -P1347M (rejected)
     *     P5Y
     *     P5Y2M10D
     *     P5Y2M10DT15H
     *     PT15H
     *     P1347Y
     *     P1347M 
     *     P1Y2MT2H 
     *     P0Y1347M 
     *     P0Y1347M0D 
     *     P1Y2M3DT10H30M
     *
     * Illegal:
     *     P-1347M (rejected)
     *     P1Y2MT (tolerated)
     */

    p++;

    while (*p)
    {
        unsigned long n = 0;

        if (*p == 'T')
        {
            foundT = 1;
            p++;
        }
        else if (foundT)
        {
            p = _ParseNumber(p, &n);

            if (!p)
                break;

            switch (*p)
            {
                case 'H':
                    hours = n;
                    break;
                case 'M':
                    minutes = n;
                    break;
                case 'S':
                    seconds = n;
                    break;
                case '.':
                {
                    p++;
                    p = _ParseDecimalPart(p, &microseconds);

                    if (*p != 'S')
                        return -1;

                    seconds = n;
                    break;
                }
                default:
                    return -1;
            }

            p++;
        }
        else
        {
            p = _ParseNumber(p, &n);

            if (!p)
                break;

            switch (*p)
            {
                case 'Y':
                    years = n;
                    break;
                case 'M':
                    months = n;
                    break;
                case 'D':
                    days = n;
                    break;
                default:
                    return -1;
            }

            p++;
        }
    }

    /* ATTN: check for overflow */

    /* Normalize seconds (possibly increasing minutes) */
    minutes += seconds / 60;
    seconds = seconds % 60;

    /* Normalize minutes (possibly increasing hours) */
    hours += minutes / 60;
    minutes = minutes % 60;

    /* Normalize hours (possibly increasing days) */
    days += hours / 24;
    hours = hours % 24;

    /* Approximate days from years-months-days */
    days += years * 365;
    days += years / 4;
    days += months * 30;
    days += months / 2;

    /* Set CIM datetime fields */
    x->isTimestamp = MI_FALSE;
    x->u.interval.days = (unsigned int)days;
    x->u.interval.hours = (unsigned int)hours;
    x->u.interval.minutes = (unsigned int)minutes;
    x->u.interval.seconds = (unsigned int)seconds;
    x->u.interval.microseconds = microseconds;

    return (p && *p == '\0') ? 0 : -1;
}

static const MI_Char* _ParseWSManUTC(const MI_Char* str, MI_Datetime* x)
{
    const MI_Char* p = str;
    unsigned long utcHours = 0;
    unsigned long utcMinutes = 0;
    long utcSign = 0; /* '1' is positive, '-1' is negative */

    if (*p == 'Z')
    {
        p++;
        return p;
    }
    else if (*p == '+' || *p == '-')
    {
        /* Parse UTC "HH:SS" */
        const MI_Char* end;

        utcSign = (*p == '-') ? -1 : 1;

        p++;
        end = _ParseNumber(p, &utcHours);

        if (!end || (end - p) != 2)
            return NULL;

        p = end;

        if (*p != ':')
            return NULL;

        p++;
        end = _ParseNumber(p, &utcMinutes);

        if (!end || (end - p) != 2)
            return NULL;

        p = end;
    }
    else
    {
        return NULL;
    }

    /* Set CIM datetime fields */
    x->u.timestamp.utc = utcSign * ((utcHours * 60) + utcMinutes);

    return p;
}

static const MI_Char* _ParseWSManDate(const MI_Char* str, MI_Datetime* x)
{
    const MI_Char* p = str;
    unsigned long year = 0;
    unsigned long month = 0;
    unsigned long day = 0;

    /* Parse YYYY */
    {
        const MI_Char* end = _ParseNumber(p, &year);

        if (!end || (end - p) != 4)
            return NULL;

        p = end;
    }

    /* Expect '-' */
    if (*p++ != '-')
        return NULL;

    /* Parse MM */
    {
        const MI_Char* end = _ParseNumber(p, &month);

        if (!end || (end - p) != 2)
            return NULL;

        p = end;
    }

    /* Expect '-' */
    if (*p++ != '-')
        return NULL;

    /* Parse DD */
    {
        const MI_Char* end = _ParseNumber(p, &day);

        if (!end || (end - p) != 2)
            return NULL;

        p = end;
    }

    /* Set CIM datetime fields */
    memset(x, 0, sizeof(MI_Datetime));
    x->isTimestamp = MI_TRUE;
    x->u.timestamp.year = (unsigned int)year;
    x->u.timestamp.month = (unsigned int)month;
    x->u.timestamp.day = (unsigned int)day;

    /* Parse UTC part */
    if (*p == 'Z' || *p == '+' || *p == '-')
    {
        p = _ParseWSManUTC(p, x);

        if (!p)
            return NULL;
    }

    return p;
}

static const MI_Char* _ParseWSManTime(const MI_Char* str, MI_Datetime* x)
{
    const MI_Char* p = str;
    unsigned long hour = 0;
    unsigned long minute = 0;
    unsigned long second = 0;
    unsigned long microseconds = 0;

    /* Parse "HH" */
    {
        const MI_Char* end = _ParseNumber(p, &hour);

        if (!end || (end - p) != 2)
            return NULL;

        p = end;
    }

    /* Expect ':' */
    if (*p++ != ':')
        return NULL;

    /* Parse "MM" */
    {
        const MI_Char* end = _ParseNumber(p, &minute);

        if (!end || (end - p) != 2)
            return NULL;

        p = end;
    }

    /* Expect ":" */
    if (*p++ != ':')
        return NULL;

    /* Parse "SS" */
    {
        const MI_Char* end = _ParseNumber(p, &second);

        if (!end || (end - p) != 2)
            return NULL;

        p = end;
    }

    /* Parse decimal part */
    if (*p == '.')
    {
        p++;
        p = _ParseDecimalPart(p, &microseconds);

        if (!p)
            return NULL;
    }

    /* Set CIM datetime fields */
    x->isTimestamp = MI_TRUE;
    x->u.timestamp.hour = (unsigned int)hour;
    x->u.timestamp.minute = (unsigned int)minute;
    x->u.timestamp.second = (unsigned int)second;
    x->u.timestamp.microseconds = (unsigned int)microseconds;

    /* Parse UTC part */
    if (*p == 'Z' || *p == '+' || *p == '-')
    {
        p = _ParseWSManUTC(p, x);

        if (!p)
            return NULL;
    }

    return p;
}

int ParseWSManDatetime(const MI_Char* str, MI_Datetime* x)
{
    const MI_Char* p = str;

    /* Clear datetime */
    memset(x, 0, sizeof(MI_Datetime));

    /* negative xs:duration */
    if (*p == '-')
    {
        /* Negative intervals not supported by CIM */
        return -1;
    }

    /* xs:duration: "PnYnMnDTnHnMnS" */
    if (*p == 'P')
    {
        return _ParseWSManDuration(str, x);
    }

    /* xs:date: "YYYY-MM-DD" plus UTC */
    if (isdigit(p[0]) && isdigit(p[1]) && isdigit(p[2]) && isdigit(p[3]))
    {
        p = _ParseWSManDate(str, x);

        if (!p)
            return -1;

        if (*p == '\0')
            return 0;

        /* xs:time "HH:MM:SS" plus UTC */
        if (*p == 'T')
        {
            p++;
            p = _ParseWSManTime(p, x);

            if (!p)
                return -1;

            if (*p == '\0')
                return 0;
        }
    }

    /* xs:time: "HH:MM:SS" plus UTC */
    if (isdigit(p[0]) && isdigit(p[1]) && p[2] == ':')
    {
        p = _ParseWSManTime(str, x);

        if (!p)
            return -1;

        if (*p == '\0')
            return 0;
    }

    /* Failed */
    return -1;
}

void FormatWSManDatetime(const MI_Datetime* x, MI_Char buffer[64])
{
    int n = 64;

    *buffer = '\0';

    if (x->isTimestamp)
    {
        /* Example output: "2010-12-31T12:30:03.123456+06:00" */
        int haveDate;
        int haveTime;
        MI_Char tmpbuf[64];

        haveDate = x->u.timestamp.year || x->u.timestamp.month ||
            x->u.timestamp.day;

        haveTime = x->u.timestamp.hour || x->u.timestamp.minute ||
            x->u.timestamp.second || x->u.timestamp.microseconds;

        if (haveDate)
        {
            Szprintf(tmpbuf, MI_COUNT(tmpbuf), T("%04u-%02u-%02u"),
                x->u.timestamp.year,
                x->u.timestamp.month,
                x->u.timestamp.day);
            Zlcat(buffer, tmpbuf, n);
        }

        if (haveTime || !haveDate)
        {
            if (haveDate)
                Zlcat(buffer, T("T"), n);

            Szprintf(tmpbuf, MI_COUNT(tmpbuf), T("%02u:%02u:%02u"),
                x->u.timestamp.hour,
                x->u.timestamp.minute,
                x->u.timestamp.second);
            Zlcat(buffer, tmpbuf, n);

            if (x->u.timestamp.microseconds)
            {
                Szprintf(tmpbuf, MI_COUNT(tmpbuf), T(".%06u"), 
                    x->u.timestamp.microseconds);
                Zlcat(buffer, tmpbuf, n);
            }

        }

        if (x->u.timestamp.utc > 0)
        {
            Szprintf(tmpbuf, MI_COUNT(tmpbuf), T("+%02u:%02u"), 
                x->u.timestamp.utc / 60, x->u.timestamp.utc % 60);
            Zlcat(buffer, tmpbuf, n);
        }
        else if (x->u.timestamp.utc < 0)
        {
            Szprintf(tmpbuf, MI_COUNT(tmpbuf), T("-%02u:%02u"), 
                -x->u.timestamp.utc / 60, -x->u.timestamp.utc % 60);
            Zlcat(buffer, tmpbuf, n);
        }
    }
    else
    {
        MI_Char tmpbuf[64];

        /* Example: "P1Y1M22DT10H11M12S" */

        Zlcat(buffer, T("P"), n);

        if (x->u.interval.days)
        {
            Szprintf(tmpbuf, MI_COUNT(tmpbuf), T("%uD"), x->u.interval.days);
            Zlcat(buffer, tmpbuf, n);
        }

        if (x->u.interval.hours || x->u.interval.minutes || 
            x->u.interval.seconds || x->u.interval.microseconds)
        {
            Zlcat(buffer, T("T"), n);
        }

        if (x->u.interval.hours)
        {
            Szprintf(tmpbuf, MI_COUNT(tmpbuf), T("%uH"), x->u.interval.hours);
            Zlcat(buffer, tmpbuf, n);
        }

        if (x->u.interval.minutes)
        {
            Szprintf(tmpbuf, MI_COUNT(tmpbuf), T("%uM"), x->u.interval.minutes);
            Zlcat(buffer, tmpbuf, n);
        }

        if (x->u.interval.seconds && x->u.interval.microseconds)
        {
            Szprintf(tmpbuf, MI_COUNT(tmpbuf), T("%u.%06uS"),
                x->u.interval.seconds, x->u.interval.microseconds);
            Zlcat(buffer, tmpbuf, n);
        }
        else if (x->u.interval.seconds && !x->u.interval.microseconds)
        {
            Szprintf(tmpbuf, MI_COUNT(tmpbuf), T("%uS"), x->u.interval.seconds);
            Zlcat(buffer, tmpbuf, n);
        }
        else if (!x->u.interval.seconds && x->u.interval.microseconds)
        {
            Szprintf(tmpbuf, MI_COUNT(tmpbuf), T("0.%06uS"),
                x->u.interval.microseconds);
            Zlcat(buffer, tmpbuf, n);
        }
    }
}

static int _StrToU32(const MI_Char* s, size_t offset, size_t size, MI_Uint32* x)
{
    MI_Char buf[64];
    MI_Char* end;

    if (size >= MI_COUNT(buf))
        return -1;

    memcpy(buf, &s[offset], size * sizeof(MI_Char));
    buf[size] = '\0';

    *x = (MI_Uint32)Ztoul(buf, &end, 10);

    if (*end != '\0')
        return -1;

    /* Success */
    return 0;
}

int StrToChar16(const MI_Char* str, MI_Char16* x)
{
    MI_Char* end;
    *x = (MI_Char16)Ztoul(str, &end, 0);

    if (*end != '\0')
        return -1;

    return 0;
}

int StrToDatetime(const MI_Char* s, MI_Datetime* x)
{
    if (Zlen(s) != 25)
        return -1;

    memset(x, 0, sizeof(MI_Datetime));

    if (s[21] == '+' || s[21] == '-')
    {
        MI_Uint32 utc;

        /* It must be a timestamp (YYYYMMDDHHMMSS.MMMMMMSUTC) */
        if (_StrToU32(s, 0, 4, &x->u.timestamp.year) != 0 ||
            _StrToU32(s, 4, 2, &x->u.timestamp.month) != 0 ||
            _StrToU32(s, 6, 2, &x->u.timestamp.day) != 0 ||
            _StrToU32(s, 8, 2, &x->u.timestamp.hour) != 0 ||
            _StrToU32(s, 10, 2, &x->u.timestamp.minute) != 0 ||
            _StrToU32(s, 12, 2, &x->u.timestamp.second) != 0 ||
            s[14] != '.' ||
            _StrToU32(s, 15, 6, &x->u.timestamp.microseconds) != 0 ||
            _StrToU32(s, 22, 3, &utc) != 0)
        {
            return -1;
        }

        if (s[21] == '+')
             x->u.timestamp.utc = (MI_Sint32)utc;
        else
             x->u.timestamp.utc = -(MI_Sint32)utc;

        x->isTimestamp = 1;
    }
    else if (s[21] == ':')
    {
        /* It must be an interval (DDDDDDDDHHMMSS.MMMMMM:000) */
        if (_StrToU32(s, 0, 8, &x->u.interval.days) != 0 ||
            _StrToU32(s, 8, 2, &x->u.interval.hours) != 0 ||
            _StrToU32(s, 10, 2, &x->u.interval.minutes) != 0 ||
            _StrToU32(s, 12, 2, &x->u.interval.seconds) != 0 ||
            s[14] != '.' ||
            _StrToU32(s, 15, 6, &x->u.interval.microseconds) != 0 ||
            s[22] != '0' || s[23] != '0' || s[24] != '0')
        {
            return -1;
        }

        x->isTimestamp = 0;
    }
    else
        return -1;

    return 0;
}

static int _ParseDatetime(const MI_Char* str, MI_Datetime* x)
{
    if (StrToDatetime(str, x) == 0)
        return 0;

    if (ParseWSManDatetime(str, x) == 0)
        return 0;

    return -1;
}

int StrToBoolean(const MI_Char* str, MI_Boolean* x)
{
    if (Zcasecmp(str, T("true")) == 0)
        *x = MI_TRUE;
    else if (Zcasecmp(str, T("false")) == 0)
        *x = MI_FALSE;
    else
        return -1;

    return 0;
}

int StrToUint8(const MI_Char* str, MI_Uint8* x)
{
    MI_Char* end;
    *x = (MI_Uint8)Ztoul(str, &end, 0);

    if (*end != '\0')
        return -1;

    return 0;
}

int StrToSint8(const MI_Char* str, MI_Sint8* x)
{
    MI_Char* end;
    *x = (MI_Sint8)Ztol(str, &end, 0);

    if (*end != '\0')
        return -1;

    return 0;
}

int StrToUint16(const MI_Char* str, MI_Uint16* x)
{
    MI_Char* end;
    *x = (MI_Uint16)Ztoul(str, &end, 0);

    if (*end != '\0')
        return -1;

    return 0;
}

int StrToSint16(const MI_Char* str, MI_Sint16* x)
{
    MI_Char* end;
    *x = (MI_Sint16)Ztol(str, &end, 0);

    if (*end != '\0')
        return -1;

    return 0;
}

int StrToUint32(const MI_Char* str, MI_Uint32* x)
{
    MI_Char* end;
    *x = (MI_Uint32)Ztoul(str, &end, 0);

    if (*end != '\0')
        return -1;

    return 0;
}

int StrToSint32(const MI_Char* str, MI_Sint32* x)
{
    MI_Char* end;
    *x = (MI_Sint32)Ztol(str, &end, 0);

    if (*end != '\0')
        return -1;

    return 0;
}

int StrToUint64(const MI_Char* str, MI_Uint64* x)
{
    MI_Char* end;
    *x = (MI_Uint64)Ztoull(str, &end, 0);

    if (*end != '\0')
        return -1;

    return 0;
}

int StrToSint64(const MI_Char* str, MI_Sint64* x)
{
    MI_Char* end;
    *x = (MI_Sint64)Ztoll(str, &end, 0);

    if (*end != '\0')
        return -1;

    return 0;
}

int StrToReal32(const MI_Char* str, MI_Real32* x)
{
    MI_Char* end;
    *x = (MI_Real32)Ztod(str, &end);

    if (*end != '\0')
        return -1;

    return 0;
}

int StrToReal64(const MI_Char* str, MI_Real64* x)
{
    MI_Char* end;
    *x = (MI_Real64)Ztod(str, &end);

    if (*end != '\0')
        return -1;

    return 0;
}

MI_Result MI_CALL Instance_SetElementFromString(
    MI_Instance* self, 
    const MI_Char* name, 
    const MI_Char* str)
{
    /* ATTN: check for integer value truncation (see use of Ztol) */
    /* ATTN: implement array types! */
    /* ATTN: implement instance and reference types! */
    MI_Type type;
    MI_Value value;

    /* Check arguments */
    if (!self || !name || !str)
        MI_RETURN(MI_RESULT_INVALID_PARAMETER);

    /* Obtain type of named property */
    {
        MI_Result r = MI_Instance_GetElement(self, name, NULL, &type, 
            NULL, NULL);

        if (r != MI_RESULT_OK)
            return r;
    }

    /* If type is array and value is string,
        try to create a single item array from this string
    */
    if (0 != (MI_ARRAY_BIT & type))
        return Instance_SetElementFromStringA(
            self, name, &str, 1);


    /* Convert string to value */
    switch (type)
    {
        case MI_BOOLEAN:
        {
            if (StrToBoolean(str, &value.boolean) != 0)
                MI_RETURN(MI_RESULT_FAILED);
            break;
        }
        case MI_UINT8:
        {
            if (StrToUint8(str, &value.uint8) != 0)
                MI_RETURN(MI_RESULT_FAILED);
            break;
        }
        case MI_SINT8:
        {
            if (StrToSint8(str, &value.sint8) != 0)
                MI_RETURN(MI_RESULT_FAILED);
            break;
        }
        case MI_UINT16:
        {
            if (StrToUint16(str, &value.uint16) != 0)
                MI_RETURN(MI_RESULT_FAILED);
            break;
        }
        case MI_SINT16:
        {
            if (StrToSint16(str, &value.sint16) != 0)
                MI_RETURN(MI_RESULT_FAILED);
            break;
        }
        case MI_UINT32:
        {
            if (StrToUint32(str, &value.uint32) != 0)
                MI_RETURN(MI_RESULT_FAILED);
            break;
        }
        case MI_SINT32:
        {
            if (StrToSint32(str, &value.sint32) != 0)
                MI_RETURN(MI_RESULT_FAILED);
            break;
        }
        case MI_UINT64:
        {
            if (StrToUint64(str, &value.uint64) != 0)
                MI_RETURN(MI_RESULT_FAILED);
            break;
        }
        case MI_SINT64:
        {
            if (StrToSint64(str, &value.sint64) != 0)
                MI_RETURN(MI_RESULT_FAILED);
            break;
        }
        case MI_REAL32:
        {
            if (StrToReal32(str, &value.real32) != 0)
                MI_RETURN(MI_RESULT_FAILED);
            break;
        }
        case MI_REAL64:
        {
            if (StrToReal64(str, &value.real64) != 0)
                MI_RETURN(MI_RESULT_FAILED);
            break;
        }
        case MI_CHAR16:
        {
            if (StrToUint16(str, &value.char16) != 0)
                MI_RETURN(MI_RESULT_FAILED);
            break;
        }
        case MI_DATETIME:
        {
            if (_ParseDatetime(str, &value.datetime) != 0)
                MI_RETURN(MI_RESULT_FAILED);
            break;
        }
        case MI_STRING:
        {
            value.string = (MI_Char*)str;
            break;
        }
        default:
        {
            MI_RETURN(MI_RESULT_FAILED);
        }
    }

    MI_RETURN(MI_Instance_SetElement(self, name, &value, type, 0));
}

MI_Result MI_CALL Instance_SetElementFromStringA(
    MI_Instance* self_, 
    const MI_Char* name, 
    const MI_Char** data,
    MI_Uint32 size)
{
    Instance* self = (Instance*)self_;
    MI_Type type = MI_BOOLEAN;
    MI_Value v;
    MI_Uint32 i;
    MI_Result result = MI_RESULT_OK;
    MI_Uint32 flags = 0;

    /* Clear value first */
    memset(&v, 0, sizeof(v));

    /* Check arguments */
    if (!self || !name || !data)
    {
        /* return instead of goto failed: 'v' is not initialized yet */
        return MI_RESULT_INVALID_PARAMETER;
    }

    /* Obtain type of named property */
    if (MI_Instance_GetElement(self_, name, NULL, &type, NULL, NULL))
    {
        /* return instead of goto failed: 'v' is not initialized yet */
        return MI_RESULT_FAILED;
    }

    /* Allocate array (allocate extra element for possible empty array) */
    if (type == MI_STRINGA)
    {
        v.array.data = (MI_Char**)data;
        v.array.size = size;
    }
    else
    {
        MI_Uint32 esize = (MI_Uint32)Type_SizeOf(Type_ScalarOf(type));
        v.array.data = BAlloc(self->batch, (size + 1) * esize, CALLSITE);

        if (!v.array.data)
        {
            result = MI_RESULT_FAILED;
            goto done;
        }

        v.array.size = size;
        flags |= MI_FLAG_ADOPT;
    }

    /* Convert string to v */
    switch (type)
    {
        case MI_BOOLEANA:
        {
            for (i = 0; i < size; i++)
            {
                if (StrToBoolean(data[i], &v.booleana.data[i]) != 0)
                {
                    result = MI_RESULT_FAILED;
                    goto done;
                }
            }
            break;
        }
        case MI_UINT8A:
        {
            for (i = 0; i < size; i++)
            {
                if (StrToUint8(data[i], &v.uint8a.data[i]) != 0)
                {
                    result = MI_RESULT_FAILED;
                    goto done;
                }
            }
            break;
        }
        case MI_SINT8A:
        {
            for (i = 0; i < size; i++)
            {
                if (StrToSint8(data[i], &v.sint8a.data[i]) != 0)
                {
                    result = MI_RESULT_FAILED;
                    goto done;
                }
            }
            break;
        }
        case MI_UINT16A:
        {
            for (i = 0; i < size; i++)
            {
                if (StrToUint16(data[i], &v.uint16a.data[i]) != 0)
                {
                    result = MI_RESULT_FAILED;
                    goto done;
                }
            }
            break;
        }
        case MI_SINT16A:
        {
            for (i = 0; i < size; i++)
            {
                if (StrToSint16(data[i], &v.sint16a.data[i]) != 0)
                {
                    result = MI_RESULT_FAILED;
                    goto done;
                }
            }
            break;
        }
        case MI_UINT32A:
        {
            for (i = 0; i < size; i++)
            {
                if (StrToUint32(data[i], &v.uint32a.data[i]) != 0)
                {
                    result = MI_RESULT_FAILED;
                    goto done;
                }
            }
            break;
        }
        case MI_SINT32A:
        {
            for (i = 0; i < size; i++)
            {
                if (StrToSint32(data[i], &v.sint32a.data[i]) != 0)
                {
                    result = MI_RESULT_FAILED;
                    goto done;
                }
            }
            break;
        }
        case MI_UINT64A:
        {
            for (i = 0; i < size; i++)
            {
                if (StrToUint64(data[i], &v.uint64a.data[i]) != 0)
                {
                    result = MI_RESULT_FAILED;
                    goto done;
                }
            }
            break;
        }
        case MI_SINT64A:
        {
            for (i = 0; i < size; i++)
            {
                if (StrToSint64(data[i], &v.sint64a.data[i]) != 0)
                {
                    result = MI_RESULT_FAILED;
                    goto done;
                }
            }
            break;
        }
        case MI_REAL32A:
        {
            for (i = 0; i < size; i++)
            {
                if (StrToReal32(data[i], &v.real32a.data[i]) != 0)
                {
                    result = MI_RESULT_FAILED;
                    goto done;
                }
            }
            break;
        }
        case MI_REAL64A:
        {
            for (i = 0; i < size; i++)
            {
                if (StrToReal64(data[i], &v.real64a.data[i]) != 0)
                {
                    result = MI_RESULT_FAILED;
                    goto done;
                }
            }
            break;
        }
        case MI_CHAR16A:
        {
            for (i = 0; i < size; i++)
            {
                if (StrToChar16(data[i], &v.char16a.data[i]) != 0)
                {
                    result = MI_RESULT_FAILED;
                    goto done;
                }
            }
            break;
        }
        case MI_DATETIMEA:
        {
            for (i = 0; i < size; i++)
            {
                if (_ParseDatetime(data[i], &v.datetimea.data[i]) != 0)
                {
                    result = MI_RESULT_FAILED;
                    goto done;
                }
            }
            break;
        }
        case MI_STRINGA:
        {
            // Handled above.
            break;
        }
        default:
        {
            result = MI_RESULT_FAILED;
            goto done;
        }
    }

    if (MI_Instance_SetElement(self_, name, &v, type, flags))
    {
        result = MI_RESULT_FAILED;
        goto done;
    }

done:

    if (result && v.array.data && type != MI_STRINGA)
        BFree(self->batch, v.array.data, CALLSITE);

    return result;
}

MI_Result MI_CALL Instance_GetValue(
    MI_Instance* self, 
    const MI_Char* name, 
    void* value,
    MI_Type type)
{
    MI_Result r;
    MI_Value v;
    MI_Type t;
    MI_Uint32 f;

    r = MI_Instance_GetElement(self, name, &v, &t, &f, NULL);

    if (r != MI_RESULT_OK)
        MI_RETURN(r);

    if (t != type)
        MI_RETURN(MI_RESULT_TYPE_MISMATCH);

    if (f & MI_FLAG_NULL)
        MI_RETURN(MI_RESULT_NOT_FOUND);

    if (!value)
        MI_RETURN(MI_RESULT_INVALID_PARAMETER);

    memcpy(value, &v, Type_SizeOf(type));

    MI_RETURN(MI_RESULT_OK);
}

void DatetimeToStr(const MI_Datetime* x, MI_Char buf[26])
{
    if (x->isTimestamp)
    {
        const MI_Char FMT[] =  MI_T("%04d%02d%02d%02d%02d%02d.%06d%c%03d");
        MI_Sint32 utc = x->u.timestamp.utc;
        Szprintf(buf, 26, FMT,
            x->u.timestamp.year,
            x->u.timestamp.month,
            x->u.timestamp.day,
            x->u.timestamp.hour,
            x->u.timestamp.minute,
            x->u.timestamp.second,
            x->u.timestamp.microseconds,
            utc < 0 ? '-' : '+',
            utc < 0 ? -utc : utc);
    }
    else
    {
        const MI_Char FMT[] = MI_T("%08u%02u%02u%02u.%06u:000");
        Szprintf(buf, 26, FMT,
            x->u.interval.days,
            x->u.interval.hours,
            x->u.interval.minutes,
            x->u.interval.seconds,
            x->u.interval.microseconds);
    }
}

ViewCVS 0.9.2