2616 lines
68 KiB
C
2616 lines
68 KiB
C
//
|
|
// --------------------------------------------------------------------------
|
|
// Gurux Ltd
|
|
//
|
|
//
|
|
//
|
|
// Filename: $HeadURL$
|
|
//
|
|
// Version: $Revision$,
|
|
// $Date$
|
|
// $Author$
|
|
//
|
|
// Copyright (c) Gurux Ltd
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
//
|
|
// DESCRIPTION
|
|
//
|
|
// This file is a part of Gurux Device Framework.
|
|
//
|
|
// Gurux Device Framework is Open Source software; you can redistribute it
|
|
// and/or modify it under the terms of the GNU General Public License
|
|
// as published by the Free Software Foundation; version 2 of the License.
|
|
// Gurux Device Framework is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
// See the GNU General Public License for more details.
|
|
//
|
|
// This code is licensed under the GNU General Public License v2.
|
|
// Full text may be retrieved at http://www.gnu.org/licenses/gpl-2.0.txt
|
|
//---------------------------------------------------------------------------
|
|
|
|
#if defined(_WIN32) || defined(_WIN64) || defined(__linux__)
|
|
#include <assert.h>
|
|
#endif
|
|
|
|
#include "gxmem.h"
|
|
#ifndef DLMS_IGNORE_STRING_CONVERTER
|
|
#include <stdio.h> //printf needs this or error is generated.
|
|
#if _MSC_VER > 1400
|
|
#include <crtdbg.h>
|
|
#endif
|
|
#endif //DLMS_IGNORE_STRING_CONVERTER
|
|
|
|
#include <string.h> /* memset */
|
|
|
|
#include "variant.h"
|
|
#include "errorcodes.h"
|
|
#include "helpers.h"
|
|
|
|
int var_setEnum(dlmsVARIANT* data, unsigned char value)
|
|
{
|
|
var_clear(data);
|
|
data->vt = DLMS_DATA_TYPE_ENUM;
|
|
data->bVal = value;
|
|
return DLMS_ERROR_CODE_OK;
|
|
}
|
|
|
|
int var_setUInt8(dlmsVARIANT* data, unsigned char value)
|
|
{
|
|
var_clear(data);
|
|
data->vt = DLMS_DATA_TYPE_UINT8;
|
|
data->bVal = value;
|
|
return DLMS_ERROR_CODE_OK;
|
|
}
|
|
|
|
int var_setUInt16(dlmsVARIANT* data, uint16_t value)
|
|
{
|
|
var_clear(data);
|
|
data->vt = DLMS_DATA_TYPE_UINT16;
|
|
data->uiVal = value;
|
|
return DLMS_ERROR_CODE_OK;
|
|
}
|
|
|
|
int var_setUInt32(dlmsVARIANT* data, uint32_t value)
|
|
{
|
|
var_clear(data);
|
|
data->vt = DLMS_DATA_TYPE_UINT32;
|
|
data->ulVal = value;
|
|
return DLMS_ERROR_CODE_OK;
|
|
}
|
|
|
|
int var_setUInt64(dlmsVARIANT* data, uint64_t value)
|
|
{
|
|
var_clear(data);
|
|
data->vt = DLMS_DATA_TYPE_UINT64;
|
|
data->ullVal = value;
|
|
return DLMS_ERROR_CODE_OK;
|
|
}
|
|
|
|
int var_setInt8(dlmsVARIANT* data, char value)
|
|
{
|
|
var_clear(data);
|
|
data->vt = DLMS_DATA_TYPE_INT8;
|
|
data->cVal = value;
|
|
return DLMS_ERROR_CODE_OK;
|
|
}
|
|
|
|
int var_setInt16(dlmsVARIANT* data, short value)
|
|
{
|
|
var_clear(data);
|
|
data->vt = DLMS_DATA_TYPE_INT16;
|
|
data->iVal = value;
|
|
return DLMS_ERROR_CODE_OK;
|
|
}
|
|
|
|
int var_setInt32(dlmsVARIANT* data, int32_t value)
|
|
{
|
|
var_clear(data);
|
|
data->vt = DLMS_DATA_TYPE_INT32;
|
|
data->lVal = value;
|
|
return DLMS_ERROR_CODE_OK;
|
|
}
|
|
|
|
int var_setInt64(dlmsVARIANT* data, int64_t value)
|
|
{
|
|
var_clear(data);
|
|
data->vt = DLMS_DATA_TYPE_INT64;
|
|
data->llVal = value;
|
|
return DLMS_ERROR_CODE_OK;
|
|
}
|
|
|
|
#ifndef DLMS_IGNORE_FLOAT64
|
|
int var_setDouble(dlmsVARIANT* data, double value)
|
|
{
|
|
var_clear(data);
|
|
data->vt = DLMS_DATA_TYPE_FLOAT64;
|
|
data->dblVal = value;
|
|
return DLMS_ERROR_CODE_OK;
|
|
}
|
|
#endif //DLMS_IGNORE_FLOAT64
|
|
|
|
int var_getUInt8(dlmsVARIANT* data, unsigned char* value)
|
|
{
|
|
if (data->vt == DLMS_DATA_TYPE_NONE)
|
|
{
|
|
*value = 0;
|
|
}
|
|
else
|
|
{
|
|
*value = data->bVal;
|
|
}
|
|
return DLMS_ERROR_CODE_OK;
|
|
}
|
|
|
|
int var_getUInt16(dlmsVARIANT* data, uint16_t* value)
|
|
{
|
|
if (data->vt == DLMS_DATA_TYPE_NONE)
|
|
{
|
|
*value = 0;
|
|
}
|
|
else
|
|
{
|
|
*value = data->uiVal;
|
|
}
|
|
return DLMS_ERROR_CODE_OK;
|
|
}
|
|
|
|
int var_getUInt32(dlmsVARIANT* data, uint32_t* value)
|
|
{
|
|
if (data->vt == DLMS_DATA_TYPE_NONE)
|
|
{
|
|
*value = 0;
|
|
}
|
|
else
|
|
{
|
|
*value = data->lVal;
|
|
}
|
|
return DLMS_ERROR_CODE_OK;
|
|
}
|
|
|
|
int var_getUInt64(dlmsVARIANT* data, uint64_t* value)
|
|
{
|
|
if (data->vt == DLMS_DATA_TYPE_NONE)
|
|
{
|
|
*value = 0;
|
|
}
|
|
else
|
|
{
|
|
*value = data->ullVal;
|
|
}
|
|
return DLMS_ERROR_CODE_OK;
|
|
}
|
|
|
|
int var_getInt8(dlmsVARIANT* data, char* value)
|
|
{
|
|
if (data->vt == DLMS_DATA_TYPE_NONE)
|
|
{
|
|
*value = 0;
|
|
}
|
|
else
|
|
{
|
|
*value = data->cVal;
|
|
}
|
|
return DLMS_ERROR_CODE_OK;
|
|
}
|
|
|
|
int var_getInt16(dlmsVARIANT* data, short* value)
|
|
{
|
|
if (data->vt == DLMS_DATA_TYPE_NONE)
|
|
{
|
|
*value = 0;
|
|
}
|
|
else
|
|
{
|
|
*value = data->iVal;
|
|
}
|
|
return DLMS_ERROR_CODE_OK;
|
|
}
|
|
|
|
int var_getInt32(dlmsVARIANT* data, int32_t* value)
|
|
{
|
|
var_clear(data);
|
|
if (data->vt == DLMS_DATA_TYPE_NONE)
|
|
{
|
|
*value = 0;
|
|
}
|
|
else
|
|
{
|
|
*value = data->lVal;
|
|
}
|
|
return DLMS_ERROR_CODE_OK;
|
|
}
|
|
|
|
int var_getInt64(dlmsVARIANT* data, int64_t* value)
|
|
{
|
|
if (data->vt == DLMS_DATA_TYPE_NONE)
|
|
{
|
|
*value = 0;
|
|
}
|
|
else
|
|
{
|
|
*value = data->llVal;
|
|
}
|
|
return DLMS_ERROR_CODE_OK;
|
|
}
|
|
|
|
int var_addBytes(dlmsVARIANT* data, const unsigned char* value, uint16_t count)
|
|
{
|
|
if (data->vt != DLMS_DATA_TYPE_OCTET_STRING)
|
|
{
|
|
#ifdef DLMS_IGNORE_MALLOC
|
|
return DLMS_ERROR_CODE_INVALID_PARAMETER;
|
|
#else
|
|
var_clear(data);
|
|
data->byteArr = (gxByteBuffer*)gxmalloc(sizeof(gxByteBuffer));
|
|
BYTE_BUFFER_INIT(data->byteArr);
|
|
data->vt = DLMS_DATA_TYPE_OCTET_STRING;
|
|
#endif //DLMS_IGNORE_MALLOC
|
|
}
|
|
#ifndef DLMS_IGNORE_MALLOC
|
|
else
|
|
{
|
|
bb_clear(data->byteArr);
|
|
}
|
|
#endif //DLMS_IGNORE_MALLOC
|
|
return bb_set(data->byteArr, value, count);
|
|
}
|
|
|
|
#ifndef DLMS_IGNORE_MALLOC
|
|
int var_setString(dlmsVARIANT* data, const char* value, uint16_t count)
|
|
{
|
|
var_clear(data);
|
|
if (data->vt != DLMS_DATA_TYPE_STRING)
|
|
{
|
|
var_clear(data);
|
|
data->strVal = (gxByteBuffer*)gxmalloc(sizeof(gxByteBuffer));
|
|
BYTE_BUFFER_INIT(data->strVal);
|
|
data->vt = DLMS_DATA_TYPE_STRING;
|
|
}
|
|
bb_set(data->strVal, (const unsigned char*)value, count);
|
|
return DLMS_ERROR_CODE_OK;
|
|
}
|
|
#endif //DLMS_IGNORE_MALLOC
|
|
|
|
int var_addOctetString(
|
|
dlmsVARIANT* data,
|
|
gxByteBuffer* ba)
|
|
{
|
|
var_clear(data);
|
|
return var_addBytes(data, ba->data + ba->position, (uint16_t)(ba->size - ba->position));
|
|
}
|
|
|
|
int var_addByteArray(
|
|
dlmsVARIANT* data,
|
|
gxByteBuffer* ba,
|
|
uint16_t index,
|
|
uint16_t count)
|
|
{
|
|
return var_addBytes(data, ba->data + index, count);
|
|
}
|
|
|
|
//Initialize variant.
|
|
int var_init(dlmsVARIANT* data)
|
|
{
|
|
data->vt = DLMS_DATA_TYPE_NONE;
|
|
data->byteArr = NULL;
|
|
return DLMS_ERROR_CODE_OK;
|
|
}
|
|
|
|
#ifndef DLMS_IGNORE_MALLOC
|
|
void var_attachArray(dlmsVARIANT* data,
|
|
const variantArray* arr,
|
|
const uint16_t count)
|
|
{
|
|
data->Arr = (variantArray*)gxmalloc(sizeof(variantArray));
|
|
data->vt = DLMS_DATA_TYPE_ARRAY;
|
|
data->Arr->capacity = 0x8000 + count;
|
|
data->Arr->size = count;
|
|
data->Arr->data = (void**)arr->data;
|
|
}
|
|
#endif //DLMS_IGNORE_MALLOC
|
|
|
|
#ifndef DLMS_IGNORE_MALLOC
|
|
void var_attachStructure(dlmsVARIANT* data,
|
|
const dlmsVARIANT** arr,
|
|
const uint16_t count)
|
|
{
|
|
data->Arr = (variantArray*)gxmalloc(sizeof(variantArray));
|
|
data->vt = DLMS_DATA_TYPE_STRUCTURE;
|
|
data->Arr->capacity = 0x8000 + count;
|
|
data->Arr->size = count;
|
|
data->Arr->data = (void**)arr;
|
|
}
|
|
#endif //DLMS_IGNORE_MALLOC
|
|
|
|
//Clear variant.
|
|
int var_clear(dlmsVARIANT* data)
|
|
{
|
|
#ifdef DLMS_IGNORE_MALLOC
|
|
//Referenced values are not cleared. User must do it.
|
|
if ((data->vt & DLMS_DATA_TYPE_BYREF) == 0)
|
|
{
|
|
data->llVal = 0;
|
|
data->vt = DLMS_DATA_TYPE_NONE;
|
|
}
|
|
data->size = 0;
|
|
#else
|
|
//Referenced values are not cleared. User must do it.
|
|
if ((data->vt & DLMS_DATA_TYPE_BYREF) != 0)
|
|
{
|
|
return 0;
|
|
}
|
|
switch (data->vt)
|
|
{
|
|
case DLMS_DATA_TYPE_OCTET_STRING:
|
|
if (data->byteArr != NULL)
|
|
{
|
|
bb_clear(data->byteArr);
|
|
if (!bb_isAttached(data->byteArr))
|
|
{
|
|
gxfree(data->byteArr);
|
|
data->byteArr = NULL;
|
|
}
|
|
}
|
|
break;
|
|
case DLMS_DATA_TYPE_STRING_UTF8:
|
|
if (data->strUtfVal != NULL)
|
|
{
|
|
bb_clear(data->strUtfVal);
|
|
if (!bb_isAttached(data->strUtfVal))
|
|
{
|
|
gxfree(data->strUtfVal);
|
|
data->strUtfVal = NULL;
|
|
}
|
|
}
|
|
break;
|
|
case DLMS_DATA_TYPE_STRING:
|
|
if (data->strVal != NULL)
|
|
{
|
|
bb_clear(data->strVal);
|
|
gxfree(data->strVal);
|
|
}
|
|
break;
|
|
case DLMS_DATA_TYPE_ARRAY:
|
|
case DLMS_DATA_TYPE_STRUCTURE:
|
|
case DLMS_DATA_TYPE_COMPACT_ARRAY:
|
|
if (data->Arr != NULL)
|
|
{
|
|
va_clear(data->Arr);
|
|
gxfree(data->Arr);
|
|
data->Arr = NULL;
|
|
}
|
|
break;
|
|
case DLMS_DATA_TYPE_BIT_STRING:
|
|
if (data->bitArr != NULL)
|
|
{
|
|
ba_clear(data->bitArr);
|
|
gxfree(data->bitArr);
|
|
}
|
|
break;
|
|
case DLMS_DATA_TYPE_DATETIME:
|
|
case DLMS_DATA_TYPE_DATE:
|
|
case DLMS_DATA_TYPE_TIME:
|
|
if (data->dateTime != NULL)
|
|
{
|
|
gxfree(data->dateTime);
|
|
data->dateTime = NULL;
|
|
}
|
|
break;
|
|
default:
|
|
data->llVal = 0;
|
|
break;
|
|
}
|
|
data->vt = DLMS_DATA_TYPE_NONE;
|
|
#endif //DLMS_IGNORE_MALLOC
|
|
return DLMS_ERROR_CODE_OK;
|
|
}
|
|
|
|
int var_getDateTime2(
|
|
gxtime* dateTime,
|
|
gxByteBuffer* ba)
|
|
{
|
|
uint16_t year = 0xFFFF;
|
|
unsigned char month = 0xFF, day = 0xFF, hour = 0xFF, minute = 0xFF, second = 0xFF, dayOfWeek = 0xFF;
|
|
#ifdef DLMS_USE_EPOCH_TIME
|
|
time_fromUnixTime2(dateTime->value, &year, &month,
|
|
&day, &hour, &minute, &second, &dayOfWeek);
|
|
//Add year.
|
|
if ((dateTime->skip & DATETIME_SKIPS_YEAR) != 0)
|
|
{
|
|
year = 0xFFFF;
|
|
}
|
|
if ((dateTime->skip & (DATETIME_SKIPS_YEAR | DATETIME_SKIPS_MONTH | DATETIME_SKIPS_DAY)) != 0)
|
|
{
|
|
dayOfWeek = 0xFF;
|
|
}
|
|
#else
|
|
if (dateTime->value.tm_isdst && (dateTime->status & DLMS_CLOCK_STATUS_DAYLIGHT_SAVE_ACTIVE) == 0)
|
|
{
|
|
time_addMinutes(dateTime, -60);
|
|
}
|
|
//Add year.
|
|
if (dateTime->value.tm_year != -1 && (dateTime->skip & DATETIME_SKIPS_YEAR) == 0)
|
|
{
|
|
year = (uint16_t)(1900 + dateTime->value.tm_year);
|
|
}
|
|
if (dateTime->value.tm_mon != -1 && (dateTime->skip & DATETIME_SKIPS_MONTH) == 0)
|
|
{
|
|
if (dateTime->extraInfo == DLMS_DATE_TIME_EXTRA_INFO_DST_BEGIN)
|
|
{
|
|
month = 0xFE;
|
|
}
|
|
else if (dateTime->extraInfo == DLMS_DATE_TIME_EXTRA_INFO_DST_END)
|
|
{
|
|
month = 0xFD;
|
|
}
|
|
else
|
|
{
|
|
month = (unsigned char)dateTime->value.tm_mon + 1;
|
|
}
|
|
}
|
|
if (dateTime->value.tm_mday != -1 && (dateTime->skip & DATETIME_SKIPS_DAY) == 0)
|
|
{
|
|
if (dateTime->extraInfo == DLMS_DATE_TIME_EXTRA_INFO_LAST_DAY)
|
|
{
|
|
day = 0xFE;
|
|
}
|
|
else if (dateTime->extraInfo == DLMS_DATE_TIME_EXTRA_INFO_LAST_DAY2)
|
|
{
|
|
day = 0xFD;
|
|
}
|
|
else
|
|
{
|
|
day = (unsigned char)dateTime->value.tm_mday;
|
|
}
|
|
}
|
|
//Add week day
|
|
if ((dateTime->value.tm_wday != -1 && dateTime->skip & DATETIME_SKIPS_DAYOFWEEK) == 0)
|
|
{
|
|
dayOfWeek = (unsigned char)dateTime->value.tm_wday;
|
|
}
|
|
//Add Hours
|
|
if (dateTime->value.tm_hour != -1 && (dateTime->skip & DATETIME_SKIPS_HOUR) == 0)
|
|
{
|
|
hour = (unsigned char)dateTime->value.tm_hour;
|
|
}
|
|
//Add Minutes
|
|
if (dateTime->value.tm_min != -1 && (dateTime->skip & DATETIME_SKIPS_MINUTE) == 0)
|
|
{
|
|
minute = (unsigned char)dateTime->value.tm_min;
|
|
}
|
|
//Add seconds.
|
|
if (dateTime->value.tm_sec != -1 && (dateTime->skip & DATETIME_SKIPS_SECOND) == 0)
|
|
{
|
|
second = (unsigned char)dateTime->value.tm_sec;
|
|
}
|
|
#endif // DLMS_USE_EPOCH_TIME
|
|
//Add year.
|
|
bb_setUInt16(ba, year);
|
|
//Add month
|
|
if ((dateTime->extraInfo & DLMS_DATE_TIME_EXTRA_INFO_DST_BEGIN) != 0)
|
|
{
|
|
bb_setUInt8(ba, 0xFE);
|
|
}
|
|
else if ((dateTime->extraInfo & DLMS_DATE_TIME_EXTRA_INFO_DST_END) != 0)
|
|
{
|
|
bb_setUInt8(ba, 0xFD);
|
|
}
|
|
else if ((dateTime->skip & DATETIME_SKIPS_MONTH) == 0)
|
|
{
|
|
bb_setUInt8(ba, month);
|
|
}
|
|
else
|
|
{
|
|
bb_setUInt8(ba, 0xFF);
|
|
}
|
|
//Add day
|
|
if ((dateTime->extraInfo & DLMS_DATE_TIME_EXTRA_INFO_LAST_DAY) != 0)
|
|
{
|
|
bb_setUInt8(ba, 0xFE);
|
|
}
|
|
else if ((dateTime->extraInfo & DLMS_DATE_TIME_EXTRA_INFO_LAST_DAY2) != 0)
|
|
{
|
|
bb_setUInt8(ba, 0xFD);
|
|
}
|
|
else if ((dateTime->skip & DATETIME_SKIPS_DAY) == 0)
|
|
{
|
|
bb_setUInt8(ba, day);
|
|
}
|
|
else
|
|
{
|
|
bb_setUInt8(ba, 0xFF);
|
|
}
|
|
//Add week day
|
|
if ((dateTime->skip & DATETIME_SKIPS_DAYOFWEEK) == 0)
|
|
{
|
|
//If Sunday.
|
|
if (dayOfWeek == 0)
|
|
{
|
|
dayOfWeek = 7;
|
|
}
|
|
bb_setUInt8(ba, dayOfWeek);
|
|
}
|
|
else
|
|
{
|
|
bb_setUInt8(ba, 0xFF);
|
|
}
|
|
|
|
//Add Hours
|
|
if ((dateTime->skip & DATETIME_SKIPS_HOUR) == 0)
|
|
{
|
|
bb_setUInt8(ba, hour);
|
|
}
|
|
else
|
|
{
|
|
bb_setUInt8(ba, 0xFF);
|
|
}
|
|
//Add Minutes
|
|
if ((dateTime->skip & DATETIME_SKIPS_MINUTE) == 0)
|
|
{
|
|
bb_setUInt8(ba, minute);
|
|
}
|
|
else
|
|
{
|
|
bb_setUInt8(ba, 0xFF);
|
|
}
|
|
//Add seconds.
|
|
if ((dateTime->skip & DATETIME_SKIPS_SECOND) == 0)
|
|
{
|
|
bb_setUInt8(ba, second);
|
|
}
|
|
else
|
|
{
|
|
bb_setUInt8(ba, 0xFF);
|
|
}
|
|
//Add ms.
|
|
#ifdef DLMS_ITALIAN_STANDARD
|
|
//Italian standard uses 0 for ms.
|
|
bb_setUInt8(ba, 0x00);
|
|
#else
|
|
if ((dateTime->skip & DATETIME_SKIPS_MS) == 0)
|
|
{
|
|
bb_setUInt8(ba, 0x00);
|
|
}
|
|
else
|
|
{
|
|
bb_setUInt8(ba, 0xFF);
|
|
}
|
|
#endif //DLMS_ITALIAN_STANDARD
|
|
//Add Deviation
|
|
if (year == 0xFFFF || (dateTime->skip & DATETIME_SKIPS_DEVITATION) != 0)
|
|
{
|
|
bb_setInt16(ba, 0x8000);//(not specified)
|
|
}
|
|
else
|
|
{
|
|
bb_setInt16(ba, dateTime->deviation);
|
|
}
|
|
//Add clock status
|
|
if ((dateTime->skip & DATETIME_SKIPS_STATUS) != 0)
|
|
{
|
|
bb_setUInt8(ba, 0xFF);
|
|
}
|
|
else
|
|
{
|
|
bb_setUInt8(ba, dateTime->status);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int var_getDate(
|
|
gxtime* dateTime,
|
|
gxByteBuffer* ba)
|
|
{
|
|
uint16_t year = 0xFFFF;
|
|
unsigned char month = 0xFF, day = 0xFF, dayOfWeek = 0xFF;
|
|
#ifdef DLMS_USE_EPOCH_TIME
|
|
time_fromUnixTime2(dateTime->value, &year, &month,
|
|
&day, NULL, NULL, NULL, &dayOfWeek);
|
|
//Add year.
|
|
if ((dateTime->skip & DATETIME_SKIPS_YEAR) != 0)
|
|
{
|
|
year = 0xFFFF;
|
|
}
|
|
#else
|
|
//Add year.
|
|
if (dateTime->value.tm_year != -1 && (dateTime->skip & DATETIME_SKIPS_YEAR) == 0)
|
|
{
|
|
year = (uint16_t)(1900 + dateTime->value.tm_year);
|
|
}
|
|
if (dateTime->value.tm_mon != -1 && (dateTime->skip & DATETIME_SKIPS_MONTH) == 0)
|
|
{
|
|
month = (unsigned char)dateTime->value.tm_mon + 1;
|
|
}
|
|
if (dateTime->value.tm_mday != -1 && (dateTime->skip & DATETIME_SKIPS_DAY) == 0)
|
|
{
|
|
day = (unsigned char)dateTime->value.tm_mday;
|
|
}
|
|
//Add week day
|
|
if ((dateTime->value.tm_wday != -1 && dateTime->skip & DATETIME_SKIPS_DAYOFWEEK) == 0)
|
|
{
|
|
dayOfWeek = (unsigned char)dateTime->value.tm_wday;
|
|
}
|
|
#endif // DLMS_USE_EPOCH_TIME
|
|
//Add year.
|
|
bb_setUInt16(ba, year);
|
|
//Add month
|
|
if ((dateTime->skip & DATETIME_SKIPS_MONTH) == 0)
|
|
{
|
|
if ((dateTime->extraInfo & DLMS_DATE_TIME_EXTRA_INFO_DST_BEGIN) != 0)
|
|
{
|
|
month = 0xFE;
|
|
}
|
|
else if ((dateTime->extraInfo & DLMS_DATE_TIME_EXTRA_INFO_DST_END) != 0)
|
|
{
|
|
month = 0xFD;
|
|
}
|
|
bb_setUInt8(ba, month);
|
|
}
|
|
else
|
|
{
|
|
bb_setUInt8(ba, 0xFF);
|
|
}
|
|
//Add day
|
|
if ((dateTime->skip & DATETIME_SKIPS_DAY) == 0)
|
|
{
|
|
if ((dateTime->extraInfo & DLMS_DATE_TIME_EXTRA_INFO_LAST_DAY) != 0)
|
|
{
|
|
day = 0xFE;
|
|
}
|
|
else if ((dateTime->extraInfo & DLMS_DATE_TIME_EXTRA_INFO_LAST_DAY2) != 0)
|
|
{
|
|
day = 0xFD;
|
|
}
|
|
bb_setUInt8(ba, day);
|
|
}
|
|
else
|
|
{
|
|
bb_setUInt8(ba, 0xFF);
|
|
}
|
|
//Add week day
|
|
if ((dateTime->skip & DATETIME_SKIPS_DAYOFWEEK) == 0)
|
|
{
|
|
//If Sunday.
|
|
if (dayOfWeek == 0)
|
|
{
|
|
dayOfWeek = 7;
|
|
}
|
|
bb_setUInt8(ba, dayOfWeek);
|
|
}
|
|
else
|
|
{
|
|
bb_setUInt8(ba, 0xFF);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int var_getTime(
|
|
gxtime* dateTime,
|
|
gxByteBuffer* ba)
|
|
{
|
|
unsigned char hour = 0xFF, minute = 0xFF, second = 0xFF;
|
|
#ifdef DLMS_USE_EPOCH_TIME
|
|
int ret = time_fromUnixTime2(dateTime->value, NULL, NULL,
|
|
NULL, &hour, &minute, &second, NULL);
|
|
if (ret != 0)
|
|
{
|
|
return ret;
|
|
}
|
|
#else
|
|
//Add Hours
|
|
if (dateTime->value.tm_hour != -1 && (dateTime->skip & DATETIME_SKIPS_HOUR) == 0)
|
|
{
|
|
hour = (unsigned char)dateTime->value.tm_hour;
|
|
}
|
|
//Add Minutes
|
|
if (dateTime->value.tm_min != -1 && (dateTime->skip & DATETIME_SKIPS_MINUTE) == 0)
|
|
{
|
|
minute = (unsigned char)dateTime->value.tm_min;
|
|
}
|
|
//Add seconds.
|
|
if (dateTime->value.tm_sec != -1 && (dateTime->skip & DATETIME_SKIPS_SECOND) == 0)
|
|
{
|
|
second = (unsigned char)dateTime->value.tm_sec;
|
|
}
|
|
#endif // DLMS_USE_EPOCH_TIME
|
|
//Add Hours
|
|
if ((dateTime->skip & DATETIME_SKIPS_HOUR) == 0)
|
|
{
|
|
bb_setUInt8(ba, hour);
|
|
}
|
|
else
|
|
{
|
|
bb_setUInt8(ba, 0xFF);
|
|
}
|
|
//Add Minutes
|
|
if ((dateTime->skip & DATETIME_SKIPS_MINUTE) == 0)
|
|
{
|
|
bb_setUInt8(ba, minute);
|
|
}
|
|
else
|
|
{
|
|
bb_setUInt8(ba, 0xFF);
|
|
}
|
|
//Add seconds.
|
|
if ((dateTime->skip & DATETIME_SKIPS_SECOND) == 0)
|
|
{
|
|
bb_setUInt8(ba, second);
|
|
}
|
|
else
|
|
{
|
|
bb_setUInt8(ba, 0xFF);
|
|
}
|
|
//Add ms.
|
|
#ifdef DLMS_ITALIAN_STANDARD
|
|
//Italian standard uses 0 for ms.
|
|
bb_setUInt8(ba, 0x00);
|
|
#else
|
|
if ((dateTime->skip & DATETIME_SKIPS_MS) == 0)
|
|
{
|
|
bb_setUInt8(ba, 0x00);
|
|
}
|
|
else
|
|
{
|
|
bb_setUInt8(ba, 0xFF);
|
|
}
|
|
#endif //DLMS_ITALIAN_STANDARD
|
|
return 0;
|
|
}
|
|
|
|
//Get bytes from variant value.
|
|
int var_getBytes(
|
|
dlmsVARIANT* data,
|
|
gxByteBuffer* ba)
|
|
{
|
|
return var_getBytes2(data, data->vt, ba);
|
|
}
|
|
|
|
#ifndef DLMS_IGNORE_MALLOC
|
|
/**
|
|
* Convert octetstring to DLMS bytes.
|
|
*
|
|
* buff
|
|
* Byte buffer where data is write.
|
|
* value
|
|
* Added value.
|
|
*/
|
|
int var_setOctetString(gxByteBuffer* buff, dlmsVARIANT* value)
|
|
{
|
|
if (value->vt == DLMS_DATA_TYPE_STRING)
|
|
{
|
|
gxByteBuffer bb;
|
|
BYTE_BUFFER_INIT(&bb);
|
|
bb_addHexString(&bb, (char*)value->strVal->data);
|
|
hlp_setObjectCount(bb.size, buff);
|
|
bb_set2(buff, &bb, 0, bb.size);
|
|
}
|
|
else if (value->vt == DLMS_DATA_TYPE_OCTET_STRING)
|
|
{
|
|
if (value->byteArr == NULL)
|
|
{
|
|
hlp_setObjectCount(0, buff);
|
|
}
|
|
else
|
|
{
|
|
hlp_setObjectCount(value->byteArr->size, buff);
|
|
bb_set(buff, value->byteArr->data, value->byteArr->size);
|
|
}
|
|
}
|
|
else if (value->vt == DLMS_DATA_TYPE_NONE)
|
|
{
|
|
hlp_setObjectCount(0, buff);
|
|
}
|
|
else
|
|
{
|
|
// Invalid data type.
|
|
return DLMS_ERROR_CODE_INVALID_PARAMETER;
|
|
}
|
|
return 0;
|
|
}
|
|
#endif //DLMS_IGNORE_MALLOC
|
|
|
|
|
|
//Get bytes from variant value.
|
|
int var_getBytes2(
|
|
dlmsVARIANT* data,
|
|
DLMS_DATA_TYPE type,
|
|
gxByteBuffer* ba)
|
|
{
|
|
return var_getBytes3(data, type, ba, 1);
|
|
}
|
|
|
|
//Returns bytes as Big Endian byteorder.
|
|
int var_getBytes3(
|
|
dlmsVARIANT* data,
|
|
DLMS_DATA_TYPE type,
|
|
gxByteBuffer* ba,
|
|
unsigned char addType)
|
|
{
|
|
int ret = 0, pos;
|
|
if ((type & DLMS_DATA_TYPE_BYREF) != 0)
|
|
{
|
|
return var_getBytes3(data, type & ~DLMS_DATA_TYPE_BYREF, ba, addType);
|
|
}
|
|
if (type == DLMS_DATA_TYPE_STRUCTURE ||
|
|
type == DLMS_DATA_TYPE_ARRAY)
|
|
{
|
|
dlmsVARIANT* tmp;
|
|
if ((ret = bb_setUInt8(ba, type)) == 0 &&
|
|
(ret = hlp_setObjectCount(data->Arr != NULL ? data->Arr->size : 0, ba)) == 0)
|
|
{
|
|
if (data->Arr != NULL)
|
|
{
|
|
for (pos = 0; pos != data->Arr->size; ++pos)
|
|
{
|
|
if ((ret = va_getByIndex(data->Arr, pos, &tmp)) != DLMS_ERROR_CODE_OK ||
|
|
(ret = var_getBytes(tmp, ba)) != DLMS_ERROR_CODE_OK)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
if (addType)
|
|
{
|
|
if ((ret = bb_setUInt8(ba, type)) != 0)
|
|
{
|
|
return ret;
|
|
}
|
|
}
|
|
switch (type)
|
|
{
|
|
case DLMS_DATA_TYPE_NONE:
|
|
break;
|
|
case DLMS_DATA_TYPE_UINT8:
|
|
case DLMS_DATA_TYPE_ENUM:
|
|
ret = bb_setUInt8(ba, (data->vt & DLMS_DATA_TYPE_BYREF) != 0 ? *data->pbVal : data->bVal);
|
|
break;
|
|
case DLMS_DATA_TYPE_BOOLEAN:
|
|
if ((data->vt & DLMS_DATA_TYPE_BYREF) != 0)
|
|
{
|
|
ret = bb_setUInt8(ba, *data->pbVal == 0 ? 0 : 1);
|
|
}
|
|
else
|
|
{
|
|
ret = bb_setUInt8(ba, data->bVal == 0 ? 0 : 1);
|
|
}
|
|
break;
|
|
case DLMS_DATA_TYPE_UINT16:
|
|
ret = bb_setUInt16(ba, (data->vt & DLMS_DATA_TYPE_BYREF) != 0 ? *data->puiVal : data->uiVal);
|
|
break;
|
|
case DLMS_DATA_TYPE_UINT32:
|
|
ret = bb_setUInt32(ba, (data->vt & DLMS_DATA_TYPE_BYREF) != 0 ? *data->pulVal : data->ulVal);
|
|
break;
|
|
case DLMS_DATA_TYPE_UINT64:
|
|
ret = bb_setUInt64(ba, (data->vt & DLMS_DATA_TYPE_BYREF) != 0 ? *data->pullVal : data->ullVal);
|
|
break;
|
|
case DLMS_DATA_TYPE_INT8:
|
|
ret = bb_setInt8(ba, (data->vt & DLMS_DATA_TYPE_BYREF) != 0 ? *data->pcVal : data->cVal);
|
|
break;
|
|
case DLMS_DATA_TYPE_INT16:
|
|
ret = bb_setInt16(ba, (data->vt & DLMS_DATA_TYPE_BYREF) != 0 ? *data->puiVal : data->uiVal);
|
|
break;
|
|
case DLMS_DATA_TYPE_INT32:
|
|
ret = bb_setUInt32(ba, (data->vt & DLMS_DATA_TYPE_BYREF) != 0 ? *data->plVal : data->lVal);
|
|
break;
|
|
case DLMS_DATA_TYPE_INT64:
|
|
ret = bb_setInt64(ba, (data->vt & DLMS_DATA_TYPE_BYREF) != 0 ? *data->pllVal : data->llVal);
|
|
break;
|
|
case DLMS_DATA_TYPE_FLOAT32:
|
|
#ifndef DLMS_IGNORE_FLOAT32
|
|
ret = bb_setFloat(ba, (data->vt & DLMS_DATA_TYPE_BYREF) != 0 ? *data->pfltVal : data->fltVal);
|
|
#else
|
|
ret = DLMS_ERROR_CODE_INVALID_PARAMETER;
|
|
#endif //DLMS_IGNORE_FLOAT32
|
|
break;
|
|
case DLMS_DATA_TYPE_FLOAT64:
|
|
#ifndef DLMS_IGNORE_FLOAT64
|
|
ret = bb_setDouble(ba, (data->vt & DLMS_DATA_TYPE_BYREF) != 0 ? *data->pdblVal : data->dblVal);
|
|
#else
|
|
ret = DLMS_ERROR_CODE_INVALID_PARAMETER;
|
|
#endif //DLMS_IGNORE_FLOAT64
|
|
break;
|
|
case DLMS_DATA_TYPE_STRING:
|
|
#ifndef DLMS_IGNORE_MALLOC
|
|
if (data->strVal == NULL)
|
|
{
|
|
ret = hlp_setObjectCount(0, ba);
|
|
}
|
|
else
|
|
{
|
|
if ((ret = hlp_setObjectCount(data->strVal->size, ba)) == 0)
|
|
{
|
|
ret = bb_set(ba, data->strVal->data, data->strVal->size);
|
|
}
|
|
}
|
|
#else
|
|
if (data->vt == (DLMS_DATA_TYPE_BYREF | DLMS_DATA_TYPE_STRING))
|
|
{
|
|
if ((ret = hlp_setObjectCount(data->size, ba)) != 0 ||
|
|
(ret = bb_set(ba, data->pbVal, data->size)) != 0)
|
|
{
|
|
//Error code is returned at the end of the function.
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ret = DLMS_ERROR_CODE_INVALID_PARAMETER;
|
|
}
|
|
#endif //DLMS_IGNORE_MALLOC
|
|
break;
|
|
case DLMS_DATA_TYPE_OCTET_STRING:
|
|
#ifndef DLMS_IGNORE_MALLOC
|
|
if (data->vt == DLMS_DATA_TYPE_DATETIME)
|
|
{
|
|
if ((ret = bb_setUInt8(ba, 12)) == 0)
|
|
{
|
|
ret = var_getDateTime2(data->dateTime, ba);
|
|
}
|
|
}
|
|
else if (data->vt == DLMS_DATA_TYPE_DATE)
|
|
{
|
|
if ((ret = bb_setUInt8(ba, 5)) == 0)
|
|
{
|
|
ret = var_getDate(data->dateTime, ba);
|
|
}
|
|
}
|
|
else if (data->vt == DLMS_DATA_TYPE_TIME)
|
|
{
|
|
if ((ret = bb_setUInt8(ba, 4)) == 0)
|
|
{
|
|
ret = var_getTime(data->dateTime, ba);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ret = var_setOctetString(ba, data);
|
|
}
|
|
#else
|
|
if (data->vt == (DLMS_DATA_TYPE_BYREF | DLMS_DATA_TYPE_DATETIME))
|
|
{
|
|
if ((ret = bb_setUInt8(ba, 12)) == 0)
|
|
{
|
|
ret = var_getDateTime2(data->pVal, ba);
|
|
}
|
|
}
|
|
else if (data->vt == (DLMS_DATA_TYPE_BYREF | DLMS_DATA_TYPE_DATE))
|
|
{
|
|
if ((ret = bb_setUInt8(ba, 5)) == 0)
|
|
{
|
|
ret = var_getDate(data->pVal, ba);
|
|
}
|
|
}
|
|
else if (data->vt == (DLMS_DATA_TYPE_BYREF | DLMS_DATA_TYPE_TIME))
|
|
{
|
|
if ((ret = bb_setUInt8(ba, 4)) == 0)
|
|
{
|
|
ret = var_getTime(data->pVal, ba);
|
|
}
|
|
}
|
|
else if (data->vt == (DLMS_DATA_TYPE_BYREF | DLMS_DATA_TYPE_OCTET_STRING))
|
|
{
|
|
if ((ret = hlp_setObjectCount(data->size, ba)) != 0 ||
|
|
(ret = bb_set(ba, data->pbVal, data->size)) != 0)
|
|
{
|
|
//Error code is returned at the end of the function.
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ((ret = hlp_setObjectCount(data->byteArr->size, ba)) != 0 ||
|
|
(ret = bb_set(ba, data->byteArr->data, data->byteArr->size)) != 0)
|
|
{
|
|
//Error code is returned at the end of the function.
|
|
}
|
|
}
|
|
#endif //DLMS_IGNORE_MALLOC
|
|
break;
|
|
case DLMS_DATA_TYPE_DATETIME:
|
|
{
|
|
#ifdef DLMS_IGNORE_MALLOC
|
|
ret = var_getDateTime2(data->pVal, ba);
|
|
#else
|
|
ret = var_getDateTime2(data->dateTime, ba);
|
|
#endif //DLMS_IGNORE_MALLOC
|
|
break;
|
|
}
|
|
case DLMS_DATA_TYPE_DATE:
|
|
{
|
|
#ifdef DLMS_IGNORE_MALLOC
|
|
ret = var_getDate(data->pVal, ba);
|
|
#else
|
|
ret = var_getDate(data->dateTime, ba);
|
|
#endif //DLMS_IGNORE_MALLOC
|
|
|
|
break;
|
|
}
|
|
case DLMS_DATA_TYPE_TIME:
|
|
{
|
|
#ifdef DLMS_IGNORE_MALLOC
|
|
ret = var_getTime(data->pVal, ba);
|
|
#else
|
|
ret = var_getTime(data->dateTime, ba);
|
|
#endif //DLMS_IGNORE_MALLOC
|
|
|
|
break;
|
|
}
|
|
case DLMS_DATA_TYPE_BIT_STRING:
|
|
{
|
|
#ifdef DLMS_IGNORE_MALLOC
|
|
if ((ret = hlp_setObjectCount(data->size, ba)) == 0)
|
|
{
|
|
ret = bb_set(ba, data->pVal, ba_getByteCount(data->size));
|
|
}
|
|
#else
|
|
if ((ret = hlp_setObjectCount(data->bitArr->size, ba)) == 0)
|
|
{
|
|
ret = bb_set(ba, data->bitArr->data, ba_getByteCount(data->bitArr->size));
|
|
}
|
|
#endif //DLMS_IGNORE_MALLOC
|
|
break;
|
|
}
|
|
default:
|
|
#if defined(_WIN32) || defined(_WIN64) || defined(__linux__)
|
|
assert(0);
|
|
#endif
|
|
ret = DLMS_ERROR_CODE_INVALID_PARAMETER;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
//Get size in bytes.
|
|
int var_getSize(DLMS_DATA_TYPE vt)
|
|
{
|
|
int nSize = -1;
|
|
switch (vt)
|
|
{
|
|
case DLMS_DATA_TYPE_NONE:
|
|
nSize = 0;
|
|
break;
|
|
case DLMS_DATA_TYPE_BOOLEAN:
|
|
case DLMS_DATA_TYPE_INT8:
|
|
case DLMS_DATA_TYPE_UINT8:
|
|
case DLMS_DATA_TYPE_ENUM:
|
|
nSize = 1;
|
|
break;
|
|
case DLMS_DATA_TYPE_INT16:
|
|
case DLMS_DATA_TYPE_UINT16:
|
|
nSize = 2;
|
|
break;
|
|
case DLMS_DATA_TYPE_INT32:
|
|
case DLMS_DATA_TYPE_UINT32:
|
|
case DLMS_DATA_TYPE_FLOAT32:
|
|
nSize = 4;
|
|
break;
|
|
case DLMS_DATA_TYPE_INT64:
|
|
case DLMS_DATA_TYPE_UINT64:
|
|
case DLMS_DATA_TYPE_FLOAT64:
|
|
nSize = 8;
|
|
break;
|
|
case DLMS_DATA_TYPE_BIT_STRING:
|
|
case DLMS_DATA_TYPE_OCTET_STRING:
|
|
case DLMS_DATA_TYPE_STRING:
|
|
case DLMS_DATA_TYPE_STRING_UTF8:
|
|
nSize = -1;
|
|
break;
|
|
case DLMS_DATA_TYPE_BINARY_CODED_DESIMAL:
|
|
break;
|
|
case DLMS_DATA_TYPE_DATETIME:
|
|
nSize = 12;
|
|
break;
|
|
//case DLMS_DATA_TYPE_DATE:
|
|
//case DLMS_DATA_TYPE_TIME:
|
|
//case DLMS_DATA_TYPE_ARRAY:
|
|
//case DLMS_DATA_TYPE_STRUCTURE:
|
|
//case DLMS_DATA_TYPE_COMPACT_ARRAY:
|
|
default:
|
|
break;
|
|
}
|
|
return nSize;
|
|
}
|
|
|
|
//Convert variant value to integer.
|
|
int var_toInteger(dlmsVARIANT* data)
|
|
{
|
|
int ret;
|
|
if ((data->vt & DLMS_DATA_TYPE_BYREF) != 0)
|
|
{
|
|
dlmsVARIANT tmp;
|
|
if ((ret = var_copy(&tmp, data)) == 0)
|
|
{
|
|
ret = var_toInteger(&tmp);
|
|
}
|
|
else
|
|
{
|
|
#if defined(_WIN32) || defined(_WIN64) || defined(__linux__)
|
|
assert(0);
|
|
#endif
|
|
ret = -1;
|
|
}
|
|
return ret;
|
|
}
|
|
switch (data->vt)
|
|
{
|
|
case DLMS_DATA_TYPE_NONE:
|
|
ret = 0;
|
|
break;
|
|
case DLMS_DATA_TYPE_BOOLEAN:
|
|
ret = data->boolVal ? 1 : 0;
|
|
break;
|
|
case DLMS_DATA_TYPE_INT32:
|
|
ret = data->lVal;
|
|
break;
|
|
case DLMS_DATA_TYPE_UINT32:
|
|
ret = data->ulVal;
|
|
break;
|
|
case DLMS_DATA_TYPE_BINARY_CODED_DESIMAL:
|
|
#if defined(_WIN32) || defined(_WIN64) || defined(__linux__)
|
|
assert(0);
|
|
#endif
|
|
ret = 0;
|
|
break;
|
|
case DLMS_DATA_TYPE_STRING_UTF8:
|
|
#if defined(_WIN32) || defined(_WIN64) || defined(__linux__)
|
|
assert(0);
|
|
#endif
|
|
ret = 0;
|
|
break;
|
|
case DLMS_DATA_TYPE_INT8:
|
|
ret = data->cVal;
|
|
break;
|
|
case DLMS_DATA_TYPE_INT16:
|
|
ret = data->iVal;
|
|
break;
|
|
case DLMS_DATA_TYPE_UINT8:
|
|
ret = data->bVal;
|
|
break;
|
|
case DLMS_DATA_TYPE_UINT16:
|
|
ret = data->uiVal;
|
|
break;
|
|
case DLMS_DATA_TYPE_INT64:
|
|
ret = (int)data->llVal;
|
|
break;
|
|
case DLMS_DATA_TYPE_UINT64:
|
|
ret = (int)data->ullVal;
|
|
break;
|
|
case DLMS_DATA_TYPE_ENUM:
|
|
ret = data->bVal;
|
|
break;
|
|
#ifndef DLMS_IGNORE_FLOAT32
|
|
case DLMS_DATA_TYPE_FLOAT32:
|
|
ret = (int)data->fltVal;
|
|
break;
|
|
#endif //DLMS_IGNORE_FLOAT32
|
|
#ifndef DLMS_IGNORE_FLOAT64
|
|
case DLMS_DATA_TYPE_FLOAT64:
|
|
ret = (int)data->dblVal;
|
|
break;
|
|
#endif //DLMS_IGNORE_FLOAT64
|
|
#ifndef DLMS_IGNORE_MALLOC
|
|
case DLMS_DATA_TYPE_STRING:
|
|
ret = hlp_stringToInt((const char*)data->strVal);
|
|
break;
|
|
case DLMS_DATA_TYPE_BIT_STRING:
|
|
{
|
|
uint32_t value;
|
|
ba_toInteger(data->bitArr, &value);
|
|
ret = (int)value;
|
|
}
|
|
break;
|
|
#endif //DLMS_IGNORE_MALLOC
|
|
default:
|
|
#if defined(_WIN32) || defined(_WIN64) || defined(__linux__)
|
|
assert(0);
|
|
#endif
|
|
ret = 0;
|
|
break;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
char va_isAttached(variantArray* arr)
|
|
{
|
|
return (arr->capacity & 0x8000) == 0x8000;
|
|
}
|
|
|
|
uint16_t va_size(variantArray* arr)
|
|
{
|
|
return arr == NULL ? 0 : arr->size;
|
|
}
|
|
|
|
uint16_t va_getCapacity(variantArray* arr)
|
|
{
|
|
return arr->capacity & 0x7FFF;
|
|
}
|
|
|
|
//Initialize variantArray.
|
|
void va_init(variantArray* arr)
|
|
{
|
|
arr->capacity = 0;
|
|
arr->data = NULL;
|
|
arr->size = 0;
|
|
}
|
|
|
|
//Allocate new size for the array in bytes.
|
|
int va_capacity(variantArray* arr, uint16_t capacity)
|
|
{
|
|
#ifndef DLMS_IGNORE_MALLOC
|
|
if (!va_isAttached(arr))
|
|
{
|
|
if (capacity == 0)
|
|
{
|
|
if (arr->capacity != 0)
|
|
{
|
|
gxfree(arr->data);
|
|
arr->size = 0;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (arr->capacity == 0)
|
|
{
|
|
arr->data = (void**)gxmalloc(capacity * sizeof(dlmsVARIANT*));
|
|
if (arr->data == NULL)
|
|
{
|
|
return DLMS_ERROR_CODE_OUTOFMEMORY;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
#ifdef gxrealloc
|
|
//If compiler supports realloc.
|
|
void** tmp = (void**)gxrealloc(arr->data, capacity * sizeof(dlmsVARIANT*));
|
|
if (tmp == NULL)
|
|
{
|
|
return DLMS_ERROR_CODE_OUTOFMEMORY;
|
|
}
|
|
arr->data = tmp;
|
|
#else
|
|
//If compiler doesn't support realloc.
|
|
void** old = arr->data;
|
|
arr->data = (void**)gxmalloc(capacity * sizeof(dlmsVARIANT*));
|
|
//If not enought memory available.
|
|
if (arr->data == NULL)
|
|
{
|
|
arr->data = old;
|
|
return DLMS_ERROR_CODE_OUTOFMEMORY;
|
|
}
|
|
memcpy(arr->data, old, sizeof(dlmsVARIANT*) * arr->size);
|
|
gxfree(old);
|
|
#endif // gxrealloc
|
|
}
|
|
}
|
|
arr->capacity = capacity;
|
|
}
|
|
#endif //DLMS_IGNORE_MALLOC
|
|
if (va_getCapacity(arr) < capacity)
|
|
{
|
|
return DLMS_ERROR_CODE_OUTOFMEMORY;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
//Push new data to the variantArray.
|
|
int va_push(variantArray* arr, dlmsVARIANT* item)
|
|
{
|
|
dlmsVARIANT** p;
|
|
#ifndef DLMS_IGNORE_MALLOC
|
|
if (!va_isAttached(arr))
|
|
{
|
|
if (arr->size >= arr->capacity)
|
|
{
|
|
arr->capacity += VARIANT_ARRAY_CAPACITY;
|
|
if (arr->size == 0)
|
|
{
|
|
arr->data = (void**)gxmalloc(arr->capacity * sizeof(dlmsVARIANT*));
|
|
}
|
|
else
|
|
{
|
|
#ifdef gxrealloc
|
|
//If compiler supports realloc.
|
|
void** tmp = (void**)gxrealloc(arr->data, arr->capacity * sizeof(dlmsVARIANT*));
|
|
if (tmp == NULL)
|
|
{
|
|
return DLMS_ERROR_CODE_OUTOFMEMORY;
|
|
}
|
|
arr->data = tmp;
|
|
#else
|
|
//If compiler doesn't support realloc.
|
|
void** old = arr->data;
|
|
arr->data = (void**)gxmalloc(arr->capacity * sizeof(dlmsVARIANT*));
|
|
//If not enought memory available.
|
|
if (arr->data == NULL)
|
|
{
|
|
arr->data = old;
|
|
return DLMS_ERROR_CODE_OUTOFMEMORY;
|
|
}
|
|
memcpy(arr->data, old, sizeof(dlmsVARIANT*) * arr->size);
|
|
gxfree(old);
|
|
#endif // gxrealloc
|
|
}
|
|
}
|
|
}
|
|
#endif //DLMS_IGNORE_MALLOC
|
|
if (va_getCapacity(arr) <= arr->size)
|
|
{
|
|
return DLMS_ERROR_CODE_OUTOFMEMORY;
|
|
}
|
|
p = (dlmsVARIANT**)arr->data;
|
|
p[arr->size] = item;
|
|
++arr->size;
|
|
return 0;
|
|
}
|
|
|
|
void va_clear(
|
|
variantArray* arr)
|
|
{
|
|
#ifndef DLMS_IGNORE_MALLOC
|
|
int pos;
|
|
unsigned char attached = va_isAttached(arr);
|
|
if (arr->data != NULL && !attached)
|
|
{
|
|
for (pos = 0; pos != arr->size; ++pos)
|
|
{
|
|
var_clear((dlmsVARIANT*)arr->data[pos]);
|
|
gxfree(arr->data[pos]);
|
|
}
|
|
gxfree(arr->data);
|
|
arr->data = NULL;
|
|
}
|
|
if (!attached)
|
|
{
|
|
arr->capacity = 0;
|
|
}
|
|
#endif //DLMS_IGNORE_MALLOC
|
|
arr->size = 0;
|
|
}
|
|
|
|
#ifdef DLMS_IGNORE_MALLOC
|
|
void va_attach(
|
|
variantArray* trg,
|
|
dlmsVARIANT* src,
|
|
uint16_t size,
|
|
uint16_t capacity)
|
|
{
|
|
trg->data = src;
|
|
trg->capacity = (uint16_t)(0x8000 | capacity);
|
|
trg->size = size;
|
|
}
|
|
#endif //DLMS_IGNORE_MALLOC
|
|
|
|
void va_attach2(
|
|
variantArray* trg,
|
|
variantArray* src)
|
|
{
|
|
trg->capacity = src->capacity;
|
|
trg->data = src->data;
|
|
trg->size = src->size;
|
|
src->data = NULL;
|
|
src->size = src->capacity = 0;
|
|
}
|
|
|
|
//Get item from variant array by index.
|
|
int va_getByIndex(variantArray* arr, int index, dlmsVARIANT_PTR* item)
|
|
{
|
|
if (index >= arr->size)
|
|
{
|
|
return DLMS_ERROR_CODE_OUTOFMEMORY;
|
|
}
|
|
|
|
#ifdef DLMS_IGNORE_MALLOC
|
|
dlmsVARIANT_PTR p = (dlmsVARIANT_PTR)arr->data;
|
|
*item = &p[index];
|
|
return DLMS_ERROR_CODE_OK;
|
|
#else
|
|
dlmsVARIANT** p = (dlmsVARIANT**)arr->data;
|
|
*item = p[index];
|
|
return DLMS_ERROR_CODE_OK;
|
|
#endif //DLMS_IGNORE_MALLOC
|
|
}
|
|
|
|
#ifndef DLMS_IGNORE_MALLOC
|
|
int va_copyArray(
|
|
variantArray* target,
|
|
variantArray* source)
|
|
{
|
|
int ret = DLMS_ERROR_CODE_OK;
|
|
dlmsVARIANT* tmp, * tmp2;
|
|
int pos;
|
|
va_clear(target);
|
|
for (pos = 0; pos != source->size; ++pos)
|
|
{
|
|
ret = va_getByIndex(source, pos, &tmp);
|
|
if (ret != DLMS_ERROR_CODE_OK)
|
|
{
|
|
return ret;
|
|
}
|
|
tmp2 = (dlmsVARIANT*)gxmalloc(sizeof(dlmsVARIANT));
|
|
var_init(tmp2);
|
|
ret = var_copy(tmp2, tmp);
|
|
if (ret != DLMS_ERROR_CODE_OK)
|
|
{
|
|
return ret;
|
|
}
|
|
va_push(target, tmp2);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int va_addValue(
|
|
variantArray* target,
|
|
dlmsVARIANT* value,
|
|
uint16_t count)
|
|
{
|
|
int pos, ret = DLMS_ERROR_CODE_OK;
|
|
dlmsVARIANT* tmp;
|
|
for (pos = 0; pos != count; ++pos)
|
|
{
|
|
tmp = (dlmsVARIANT*)gxmalloc(sizeof(dlmsVARIANT));
|
|
if (tmp == NULL)
|
|
{
|
|
ret = DLMS_ERROR_CODE_OUTOFMEMORY;
|
|
break;
|
|
}
|
|
if ((ret = var_init(tmp)) != 0 ||
|
|
(ret = var_copy(tmp, value)) != 0 ||
|
|
(ret = va_push(target, tmp)) != 0)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
#endif //DLMS_IGNORE_MALLOC
|
|
|
|
#ifndef DLMS_IGNORE_MALLOC
|
|
//Note! var_toString do not clear existing bytearray.
|
|
int var_toString(dlmsVARIANT* item, gxByteBuffer* value)
|
|
{
|
|
int ret = DLMS_ERROR_CODE_OK;
|
|
uint16_t pos;
|
|
if (item->vt == DLMS_DATA_TYPE_ARRAY || item->vt == DLMS_DATA_TYPE_STRUCTURE)
|
|
{
|
|
dlmsVARIANT* it;
|
|
bb_setInt8(value, item->vt == DLMS_DATA_TYPE_ARRAY ? '{' : '[');
|
|
for (pos = 0; pos != item->Arr->size; ++pos)
|
|
{
|
|
if (pos != 0)
|
|
{
|
|
bb_setInt8(value, ',');
|
|
bb_setInt8(value, ' ');
|
|
}
|
|
if ((ret = va_getByIndex(item->Arr, pos, &it)) != 0 ||
|
|
(ret = var_toString(it, value)) != 0)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
bb_setInt8(value, item->vt == DLMS_DATA_TYPE_ARRAY ? '}' : ']');
|
|
}
|
|
else
|
|
{
|
|
dlmsVARIANT tmp;
|
|
var_init(&tmp);
|
|
ret = var_copy(&tmp, item);
|
|
if (ret == 0)
|
|
{
|
|
ret = var_changeType(&tmp, DLMS_DATA_TYPE_STRING);
|
|
if (ret == 0 && tmp.strVal != NULL)
|
|
{
|
|
bb_set(value, tmp.strVal->data, tmp.strVal->size);
|
|
}
|
|
}
|
|
var_clear(&tmp);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
|
|
//Note! va_toString do not clear existing bytearray.
|
|
int va_toString(
|
|
variantArray* items,
|
|
gxByteBuffer* ba)
|
|
{
|
|
dlmsVARIANT* it;
|
|
int pos, ret = DLMS_ERROR_CODE_OK;
|
|
for (pos = 0; pos != items->size; ++pos)
|
|
{
|
|
if ((ret = va_getByIndex(items, pos, &it)) != 0)
|
|
{
|
|
return ret;
|
|
}
|
|
if (pos != 0)
|
|
{
|
|
bb_addString(ba, ", ");
|
|
}
|
|
if ((ret = var_toString(it, ba)) != 0)
|
|
{
|
|
return ret;
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
static int convert(dlmsVARIANT* item, DLMS_DATA_TYPE type)
|
|
{
|
|
int ret, fromSize, toSize;
|
|
uint16_t pos;
|
|
char buff[250];
|
|
dlmsVARIANT tmp, tmp3;
|
|
dlmsVARIANT* it;
|
|
if (item->vt == type)
|
|
{
|
|
return DLMS_ERROR_CODE_OK;
|
|
}
|
|
var_init(&tmp);
|
|
var_init(&tmp3);
|
|
ret = var_copy(&tmp, item);
|
|
if (ret != DLMS_ERROR_CODE_OK)
|
|
{
|
|
return ret;
|
|
}
|
|
var_clear(item);
|
|
if (type == DLMS_DATA_TYPE_STRING)
|
|
{
|
|
item->strVal = (gxByteBuffer*)gxmalloc(sizeof(gxByteBuffer));
|
|
BYTE_BUFFER_INIT(item->strVal);
|
|
switch (tmp.vt)
|
|
{
|
|
case DLMS_DATA_TYPE_ARRAY:
|
|
case DLMS_DATA_TYPE_STRUCTURE:
|
|
{
|
|
bb_setUInt8(item->strVal, '{');
|
|
for (pos = 0; pos != tmp.Arr->size; ++pos)
|
|
{
|
|
ret = va_getByIndex(tmp.Arr, pos, &it);
|
|
if (ret != DLMS_ERROR_CODE_OK)
|
|
{
|
|
return ret;
|
|
}
|
|
if (pos != 0)
|
|
{
|
|
bb_setUInt8(item->strVal, ',');
|
|
bb_setUInt8(item->strVal, ' ');
|
|
}
|
|
ret = var_copy(&tmp3, it);
|
|
if (ret != DLMS_ERROR_CODE_OK)
|
|
{
|
|
return ret;
|
|
}
|
|
ret = var_toString(&tmp3, item->strVal);
|
|
var_clear(&tmp3);
|
|
if (ret != DLMS_ERROR_CODE_OK)
|
|
{
|
|
var_clear(&tmp);
|
|
return ret;
|
|
}
|
|
}
|
|
bb_setUInt8(item->strVal, '}');
|
|
bb_setUInt8(item->strVal, '\0');
|
|
--item->strVal->size;
|
|
item->vt = type;
|
|
var_clear(&tmp);
|
|
return DLMS_ERROR_CODE_OK;
|
|
}
|
|
case DLMS_DATA_TYPE_BOOLEAN:
|
|
{
|
|
if (tmp.boolVal == 0)
|
|
{
|
|
bb_addString(item->strVal, "False");
|
|
}
|
|
else
|
|
{
|
|
bb_addString(item->strVal, "True");
|
|
}
|
|
item->vt = type;
|
|
var_clear(&tmp);
|
|
return DLMS_ERROR_CODE_OK;
|
|
}
|
|
case DLMS_DATA_TYPE_INT32:
|
|
{
|
|
hlp_intToString(buff, 250, tmp.lVal, 1, 0);
|
|
bb_addString(item->strVal, buff);
|
|
item->vt = type;
|
|
var_clear(&tmp);
|
|
return DLMS_ERROR_CODE_OK;
|
|
}
|
|
case DLMS_DATA_TYPE_UINT32:
|
|
{
|
|
hlp_uint64ToString(buff, 250, tmp.ulVal, 0);
|
|
if ((ret = bb_addString(item->strVal, buff)) == 0)
|
|
{
|
|
item->vt = type;
|
|
}
|
|
var_clear(&tmp);
|
|
return ret;
|
|
}
|
|
case DLMS_DATA_TYPE_INT8:
|
|
{
|
|
hlp_intToString(buff, 250, tmp.cVal, 1, 0);
|
|
bb_addString(item->strVal, buff);
|
|
item->vt = type;
|
|
var_clear(&tmp);
|
|
return DLMS_ERROR_CODE_OK;
|
|
}
|
|
case DLMS_DATA_TYPE_INT16:
|
|
{
|
|
hlp_intToString(buff, 250, tmp.iVal, 1, 0);
|
|
bb_addString(item->strVal, buff);
|
|
item->vt = type;
|
|
var_clear(&tmp);
|
|
return DLMS_ERROR_CODE_OK;
|
|
}
|
|
case DLMS_DATA_TYPE_UINT8:
|
|
{
|
|
hlp_intToString(buff, 250, tmp.bVal, 0, 0);
|
|
bb_addString(item->strVal, buff);
|
|
item->vt = type;
|
|
var_clear(&tmp);
|
|
return DLMS_ERROR_CODE_OK;
|
|
}
|
|
case DLMS_DATA_TYPE_UINT16:
|
|
{
|
|
hlp_intToString(buff, 250, tmp.uiVal, 0, 0);
|
|
bb_addString(item->strVal, buff);
|
|
item->vt = type;
|
|
var_clear(&tmp);
|
|
return DLMS_ERROR_CODE_OK;
|
|
}
|
|
case DLMS_DATA_TYPE_INT64:
|
|
{
|
|
hlp_int64ToString(buff, 250, tmp.llVal, 1);
|
|
bb_addString(item->strVal, buff);
|
|
item->vt = type;
|
|
var_clear(&tmp);
|
|
return DLMS_ERROR_CODE_OK;
|
|
}
|
|
case DLMS_DATA_TYPE_UINT64:
|
|
{
|
|
hlp_uint64ToString(buff, 250, tmp.ullVal, 0);
|
|
bb_addString(item->strVal, buff);
|
|
item->vt = type;
|
|
var_clear(&tmp);
|
|
return DLMS_ERROR_CODE_OK;
|
|
}
|
|
case DLMS_DATA_TYPE_ENUM:
|
|
{
|
|
hlp_intToString(buff, 250, tmp.bVal, 0, 0);
|
|
bb_addString(item->strVal, buff);
|
|
item->vt = type;
|
|
var_clear(&tmp);
|
|
return DLMS_ERROR_CODE_OK;
|
|
}
|
|
#if !defined(DLMS_IGNORE_STRING_CONVERTER) && !defined(DLMS_IGNORE_FLOAT32)
|
|
case DLMS_DATA_TYPE_FLOAT32:
|
|
{
|
|
#if _MSC_VER > 1000
|
|
sprintf_s(buff, 250, "%f", tmp.fltVal);
|
|
#else
|
|
sprintf(buff, "%f", tmp.fltVal);
|
|
#endif
|
|
bb_addString(item->strVal, buff);
|
|
item->vt = type;
|
|
var_clear(&tmp);
|
|
return DLMS_ERROR_CODE_OK;
|
|
}
|
|
#endif //!defined(DLMS_IGNORE_STRING_CONVERTER) && !defined(DLMS_IGNORE_FLOAT32)
|
|
#if !defined(DLMS_IGNORE_STRING_CONVERTER) && !defined(DLMS_IGNORE_FLOAT64)
|
|
case DLMS_DATA_TYPE_FLOAT64:
|
|
{
|
|
#if _MSC_VER > 1000
|
|
sprintf_s(buff, 250, "%lf", tmp.dblVal);
|
|
#else
|
|
sprintf(buff, "%lf", tmp.dblVal);
|
|
#endif
|
|
bb_addString(item->strVal, buff);
|
|
item->vt = type;
|
|
var_clear(&tmp);
|
|
return DLMS_ERROR_CODE_OK;
|
|
}
|
|
#endif //!defined(DLMS_IGNORE_STRING_CONVERTER) && !defined(DLMS_IGNORE_FLOAT64)
|
|
case DLMS_DATA_TYPE_BIT_STRING:
|
|
{
|
|
char* str = ba_toString(tmp.bitArr);
|
|
bb_attachString(item->strVal, str);
|
|
item->vt = type;
|
|
var_clear(&tmp);
|
|
return DLMS_ERROR_CODE_OK;
|
|
}
|
|
#ifndef DLMS_IGNORE_STRING_CONVERTER
|
|
case DLMS_DATA_TYPE_DATETIME:
|
|
case DLMS_DATA_TYPE_DATE:
|
|
case DLMS_DATA_TYPE_TIME:
|
|
{
|
|
time_toString(tmp.dateTime, item->strVal);
|
|
item->vt = type;
|
|
var_clear(&tmp);
|
|
return DLMS_ERROR_CODE_OK;
|
|
}
|
|
#endif //DLMS_IGNORE_STRING_CONVERTER
|
|
case DLMS_DATA_TYPE_OCTET_STRING:
|
|
{
|
|
#ifndef DLMS_IGNORE_STRING_CONVERTER
|
|
if (tmp.byteArr != NULL)
|
|
{
|
|
char* str = bb_toHexString(tmp.byteArr);
|
|
bb_addString(item->strVal, str);
|
|
gxfree(str);
|
|
}
|
|
item->vt = type;
|
|
var_clear(&tmp);
|
|
return DLMS_ERROR_CODE_OK;
|
|
#else
|
|
return DLMS_ERROR_CODE_INVALID_PARAMETER;
|
|
#endif //DLMS_IGNORE_STRING_CONVERTER
|
|
}
|
|
case DLMS_DATA_TYPE_NONE:
|
|
{
|
|
item->vt = type;
|
|
var_clear(&tmp);
|
|
return DLMS_ERROR_CODE_OK;
|
|
}
|
|
default:
|
|
return DLMS_ERROR_CODE_NOT_IMPLEMENTED;
|
|
}
|
|
}
|
|
else if (item->vt == DLMS_DATA_TYPE_STRING)
|
|
{
|
|
if (type == DLMS_DATA_TYPE_BOOLEAN)
|
|
{
|
|
item->boolVal = strcmp((char*)tmp.strVal->data, "False") == 0 ? 0 : 1;
|
|
item->vt = type;
|
|
var_clear(&tmp);
|
|
return DLMS_ERROR_CODE_OK;
|
|
}
|
|
else if (type == DLMS_DATA_TYPE_INT32)
|
|
{
|
|
item->lVal = hlp_stringToInt((char*)tmp.strVal->data);
|
|
item->vt = type;
|
|
var_clear(&tmp);
|
|
return DLMS_ERROR_CODE_OK;
|
|
}
|
|
else if (type == DLMS_DATA_TYPE_UINT32)
|
|
{
|
|
item->ulVal = hlp_stringToInt((char*)tmp.strVal->data) & 0xFFFFFFFF;
|
|
item->vt = type;
|
|
var_clear(&tmp);
|
|
return DLMS_ERROR_CODE_OK;
|
|
}
|
|
else if (type == DLMS_DATA_TYPE_INT8)
|
|
{
|
|
item->cVal = (char)hlp_stringToInt((char*)tmp.strVal->data);
|
|
item->vt = type;
|
|
var_clear(&tmp);
|
|
return DLMS_ERROR_CODE_OK;
|
|
}
|
|
else if (type == DLMS_DATA_TYPE_INT16)
|
|
{
|
|
item->iVal = (short)hlp_stringToInt((char*)tmp.strVal->data);
|
|
item->vt = type;
|
|
var_clear(&tmp);
|
|
return DLMS_ERROR_CODE_OK;
|
|
}
|
|
else if (type == DLMS_DATA_TYPE_UINT8)
|
|
{
|
|
item->bVal = (unsigned char)hlp_stringToInt((char*)tmp.strVal->data);
|
|
item->vt = type;
|
|
var_clear(&tmp);
|
|
return DLMS_ERROR_CODE_OK;
|
|
}
|
|
else if (type == DLMS_DATA_TYPE_UINT16)
|
|
{
|
|
item->uiVal = (uint16_t)hlp_stringToInt((char*)tmp.strVal->data);
|
|
item->vt = type;
|
|
var_clear(&tmp);
|
|
return DLMS_ERROR_CODE_OK;
|
|
}
|
|
else if (type == DLMS_DATA_TYPE_INT64)
|
|
{
|
|
item->llVal = hlp_stringToInt64((char*)tmp.strVal->data);
|
|
item->vt = type;
|
|
var_clear(&tmp);
|
|
return DLMS_ERROR_CODE_OK;
|
|
}
|
|
else if (type == DLMS_DATA_TYPE_UINT64)
|
|
{
|
|
item->ullVal = (uint64_t)hlp_stringToInt64((char*)tmp.strVal->data);
|
|
item->vt = type;
|
|
var_clear(&tmp);
|
|
return DLMS_ERROR_CODE_OK;
|
|
}
|
|
else if (type == DLMS_DATA_TYPE_ENUM)
|
|
{
|
|
item->bVal = (unsigned char)hlp_stringToInt((char*)tmp.strVal->data);
|
|
item->vt = type;
|
|
var_clear(&tmp);
|
|
return DLMS_ERROR_CODE_OK;
|
|
}
|
|
#if !defined(DLMS_IGNORE_FLOAT32) && !defined(DLMS_IGNORE_STRING_CONVERTER)
|
|
else if (type == DLMS_DATA_TYPE_FLOAT32)
|
|
{
|
|
#if _MSC_VER > 1000
|
|
sscanf_s((char*)tmp.strVal->data, "%f", &item->fltVal);
|
|
#else
|
|
sscanf((char*)tmp.strVal->data, "%f", &item->fltVal);
|
|
#endif
|
|
item->vt = type;
|
|
var_clear(&tmp);
|
|
return DLMS_ERROR_CODE_OK;
|
|
}
|
|
#endif //DLMS_IGNORE_FLOAT32
|
|
#if !defined(DLMS_IGNORE_FLOAT64) && !defined(DLMS_IGNORE_STRING_CONVERTER)
|
|
else if (type == DLMS_DATA_TYPE_FLOAT64)
|
|
{
|
|
#if _MSC_VER > 1000
|
|
sscanf_s((char*)tmp.strVal->data, "%lf", &item->dblVal);
|
|
#else
|
|
sscanf((char*)tmp.strVal->data, "%lf", &item->dblVal);
|
|
#endif
|
|
item->vt = type;
|
|
var_clear(&tmp);
|
|
return DLMS_ERROR_CODE_OK;
|
|
}
|
|
#endif //DLMS_IGNORE_FLOAT64
|
|
else if (type == DLMS_DATA_TYPE_OCTET_STRING)
|
|
{
|
|
char* pBuff = (char*)tmp.strVal->data;
|
|
item->byteArr = (gxByteBuffer*)gxmalloc(sizeof(gxByteBuffer));
|
|
BYTE_BUFFER_INIT(item->byteArr);
|
|
bb_addHexString(item->byteArr, pBuff);
|
|
item->vt = type;
|
|
var_clear(&tmp);
|
|
bb_trim(item->byteArr);
|
|
return DLMS_ERROR_CODE_OK;
|
|
}
|
|
return DLMS_ERROR_CODE_NOT_IMPLEMENTED;
|
|
}
|
|
fromSize = var_getSize(tmp.vt);
|
|
toSize = var_getSize(item->vt);
|
|
//If we try to change bigger valut to smaller check that value is not too big.
|
|
//Example Int16 to Int8.
|
|
if (fromSize > toSize)
|
|
{
|
|
unsigned char* pValue = &tmp.bVal;
|
|
for (pos = (unsigned char)toSize; pos != (unsigned char)fromSize; ++pos)
|
|
{
|
|
if (pValue[pos] != 0)
|
|
{
|
|
return DLMS_ERROR_CODE_INVALID_PARAMETER;
|
|
}
|
|
}
|
|
}
|
|
if (fromSize > toSize)
|
|
{
|
|
memcpy(&item->bVal, &tmp.bVal, toSize);
|
|
}
|
|
else
|
|
{
|
|
memset(&item->bVal, 0, toSize);
|
|
memcpy(&item->bVal, &tmp.bVal, fromSize);
|
|
}
|
|
item->vt = type;
|
|
var_clear(&tmp);
|
|
return DLMS_ERROR_CODE_OK;
|
|
}
|
|
|
|
int var_changeType(dlmsVARIANT* value, DLMS_DATA_TYPE newType)
|
|
{
|
|
if (newType == value->vt)
|
|
{
|
|
return DLMS_ERROR_CODE_OK;
|
|
}
|
|
if (newType == DLMS_DATA_TYPE_NONE)
|
|
{
|
|
return var_clear(value);
|
|
}
|
|
if (value->vt == DLMS_DATA_TYPE_ARRAY && newType == DLMS_DATA_TYPE_OCTET_STRING)
|
|
{
|
|
return DLMS_ERROR_CODE_OK;
|
|
}
|
|
if (value->vt == DLMS_DATA_TYPE_STRING)
|
|
{
|
|
return convert(value, newType);
|
|
}
|
|
switch (newType)
|
|
{
|
|
case DLMS_DATA_TYPE_STRING:
|
|
case DLMS_DATA_TYPE_BOOLEAN:
|
|
case DLMS_DATA_TYPE_INT32:
|
|
case DLMS_DATA_TYPE_UINT32:
|
|
case DLMS_DATA_TYPE_INT8:
|
|
case DLMS_DATA_TYPE_INT16:
|
|
case DLMS_DATA_TYPE_UINT8:
|
|
case DLMS_DATA_TYPE_UINT16:
|
|
case DLMS_DATA_TYPE_INT64:
|
|
case DLMS_DATA_TYPE_UINT64:
|
|
case DLMS_DATA_TYPE_ENUM:
|
|
#ifndef DLMS_IGNORE_FLOAT32
|
|
case DLMS_DATA_TYPE_FLOAT32:
|
|
#endif //DLMS_IGNORE_FLOAT32
|
|
#ifndef DLMS_IGNORE_FLOAT64
|
|
case DLMS_DATA_TYPE_FLOAT64:
|
|
#endif //DLMS_IGNORE_FLOAT64
|
|
return convert(value, newType);
|
|
default:
|
|
//Handled later.
|
|
break;
|
|
}
|
|
switch (value->vt)
|
|
{
|
|
case DLMS_DATA_TYPE_BOOLEAN:
|
|
return DLMS_ERROR_CODE_INVALID_PARAMETER;
|
|
case DLMS_DATA_TYPE_BIT_STRING:
|
|
{
|
|
return DLMS_ERROR_CODE_INVALID_PARAMETER;
|
|
}
|
|
case DLMS_DATA_TYPE_INT32:
|
|
switch (newType)
|
|
{
|
|
case DLMS_DATA_TYPE_BINARY_CODED_DESIMAL:
|
|
return DLMS_ERROR_CODE_NOT_IMPLEMENTED;
|
|
default:
|
|
return DLMS_ERROR_CODE_INVALID_PARAMETER;
|
|
}
|
|
case DLMS_DATA_TYPE_UINT32:
|
|
switch (newType)
|
|
{
|
|
case DLMS_DATA_TYPE_BINARY_CODED_DESIMAL:
|
|
return DLMS_ERROR_CODE_NOT_IMPLEMENTED;
|
|
default:
|
|
return DLMS_ERROR_CODE_INVALID_PARAMETER;
|
|
}
|
|
case DLMS_DATA_TYPE_OCTET_STRING:
|
|
switch (newType)
|
|
{
|
|
case DLMS_DATA_TYPE_DATETIME:
|
|
return DLMS_ERROR_CODE_NOT_IMPLEMENTED;
|
|
case DLMS_DATA_TYPE_DATE:
|
|
return DLMS_ERROR_CODE_NOT_IMPLEMENTED;
|
|
case DLMS_DATA_TYPE_TIME:
|
|
return DLMS_ERROR_CODE_NOT_IMPLEMENTED;
|
|
default:
|
|
return DLMS_ERROR_CODE_INVALID_PARAMETER;
|
|
}
|
|
case DLMS_DATA_TYPE_BINARY_CODED_DESIMAL:
|
|
switch (newType)
|
|
{
|
|
case DLMS_DATA_TYPE_INT32:
|
|
break;
|
|
case DLMS_DATA_TYPE_UINT32:
|
|
break;
|
|
case DLMS_DATA_TYPE_STRING:
|
|
break;
|
|
case DLMS_DATA_TYPE_INT8:
|
|
break;
|
|
case DLMS_DATA_TYPE_INT16:
|
|
break;
|
|
case DLMS_DATA_TYPE_UINT8:
|
|
break;
|
|
case DLMS_DATA_TYPE_UINT16:
|
|
break;
|
|
case DLMS_DATA_TYPE_INT64:
|
|
break;
|
|
case DLMS_DATA_TYPE_UINT64:
|
|
break;
|
|
case DLMS_DATA_TYPE_ENUM:
|
|
break;
|
|
case DLMS_DATA_TYPE_FLOAT32:
|
|
break;
|
|
case DLMS_DATA_TYPE_FLOAT64:
|
|
break;
|
|
default:
|
|
return DLMS_ERROR_CODE_INVALID_PARAMETER;
|
|
}
|
|
break;
|
|
case DLMS_DATA_TYPE_INT8:
|
|
switch (newType)
|
|
{
|
|
case DLMS_DATA_TYPE_BINARY_CODED_DESIMAL:
|
|
return DLMS_ERROR_CODE_NOT_IMPLEMENTED;
|
|
default:
|
|
return DLMS_ERROR_CODE_INVALID_PARAMETER;
|
|
}
|
|
case DLMS_DATA_TYPE_INT16:
|
|
switch (newType)
|
|
{
|
|
case DLMS_DATA_TYPE_BINARY_CODED_DESIMAL:
|
|
return DLMS_ERROR_CODE_NOT_IMPLEMENTED;
|
|
default:
|
|
return DLMS_ERROR_CODE_INVALID_PARAMETER;
|
|
}
|
|
case DLMS_DATA_TYPE_UINT8:
|
|
switch (newType)
|
|
{
|
|
case DLMS_DATA_TYPE_BINARY_CODED_DESIMAL:
|
|
return DLMS_ERROR_CODE_NOT_IMPLEMENTED;
|
|
default:
|
|
return DLMS_ERROR_CODE_INVALID_PARAMETER;
|
|
}
|
|
case DLMS_DATA_TYPE_UINT16:
|
|
switch (newType)
|
|
{
|
|
case DLMS_DATA_TYPE_BINARY_CODED_DESIMAL:
|
|
return DLMS_ERROR_CODE_NOT_IMPLEMENTED;
|
|
default:
|
|
return DLMS_ERROR_CODE_INVALID_PARAMETER;
|
|
}
|
|
case DLMS_DATA_TYPE_INT64:
|
|
switch (newType)
|
|
{
|
|
case DLMS_DATA_TYPE_BINARY_CODED_DESIMAL:
|
|
return DLMS_ERROR_CODE_NOT_IMPLEMENTED;
|
|
default:
|
|
return DLMS_ERROR_CODE_INVALID_PARAMETER;
|
|
}
|
|
case DLMS_DATA_TYPE_UINT64:
|
|
switch (newType)
|
|
{
|
|
case DLMS_DATA_TYPE_BINARY_CODED_DESIMAL:
|
|
return DLMS_ERROR_CODE_NOT_IMPLEMENTED;
|
|
default:
|
|
return DLMS_ERROR_CODE_INVALID_PARAMETER;
|
|
}
|
|
case DLMS_DATA_TYPE_ENUM:
|
|
switch (newType)
|
|
{
|
|
case DLMS_DATA_TYPE_BINARY_CODED_DESIMAL:
|
|
return DLMS_ERROR_CODE_NOT_IMPLEMENTED;
|
|
default:
|
|
return DLMS_ERROR_CODE_INVALID_PARAMETER;
|
|
}
|
|
case DLMS_DATA_TYPE_FLOAT32:
|
|
switch (newType)
|
|
{
|
|
case DLMS_DATA_TYPE_BINARY_CODED_DESIMAL:
|
|
return DLMS_ERROR_CODE_NOT_IMPLEMENTED;
|
|
default:
|
|
return DLMS_ERROR_CODE_INVALID_PARAMETER;
|
|
}
|
|
case DLMS_DATA_TYPE_FLOAT64:
|
|
switch (newType)
|
|
{
|
|
case DLMS_DATA_TYPE_BINARY_CODED_DESIMAL:
|
|
return DLMS_ERROR_CODE_NOT_IMPLEMENTED;
|
|
default:
|
|
return DLMS_ERROR_CODE_INVALID_PARAMETER;
|
|
}
|
|
case DLMS_DATA_TYPE_DATETIME:
|
|
switch (newType)
|
|
{
|
|
case DLMS_DATA_TYPE_OCTET_STRING:
|
|
break;
|
|
case DLMS_DATA_TYPE_STRING:
|
|
break;
|
|
case DLMS_DATA_TYPE_DATE:
|
|
break;
|
|
case DLMS_DATA_TYPE_TIME:
|
|
break;
|
|
default:
|
|
return DLMS_ERROR_CODE_INVALID_PARAMETER;
|
|
}
|
|
break;
|
|
case DLMS_DATA_TYPE_DATE:
|
|
switch (newType)
|
|
{
|
|
case DLMS_DATA_TYPE_OCTET_STRING:
|
|
break;
|
|
case DLMS_DATA_TYPE_STRING:
|
|
break;
|
|
case DLMS_DATA_TYPE_DATETIME:
|
|
break;
|
|
case DLMS_DATA_TYPE_DATE:
|
|
break;
|
|
case DLMS_DATA_TYPE_TIME:
|
|
break;
|
|
default:
|
|
return DLMS_ERROR_CODE_INVALID_PARAMETER;
|
|
}
|
|
break;
|
|
case DLMS_DATA_TYPE_TIME:
|
|
switch (newType)
|
|
{
|
|
case DLMS_DATA_TYPE_OCTET_STRING:
|
|
break;
|
|
case DLMS_DATA_TYPE_STRING:
|
|
break;
|
|
case DLMS_DATA_TYPE_DATETIME:
|
|
break;
|
|
case DLMS_DATA_TYPE_DATE:
|
|
break;
|
|
case DLMS_DATA_TYPE_TIME:
|
|
break;
|
|
default:
|
|
return DLMS_ERROR_CODE_INVALID_PARAMETER;
|
|
}
|
|
break;
|
|
case DLMS_DATA_TYPE_ARRAY:
|
|
case DLMS_DATA_TYPE_STRUCTURE:
|
|
case DLMS_DATA_TYPE_COMPACT_ARRAY:
|
|
default:
|
|
return DLMS_ERROR_CODE_INVALID_PARAMETER;
|
|
}
|
|
return DLMS_ERROR_CODE_OK;
|
|
}
|
|
#endif //DLMS_IGNORE_MALLOC
|
|
|
|
//copy variant.
|
|
int var_copy(dlmsVARIANT* target, dlmsVARIANT* source)
|
|
{
|
|
#ifndef DLMS_IGNORE_MALLOC
|
|
dlmsVARIANT* it;
|
|
dlmsVARIANT* item;
|
|
#endif //DLMS_IGNORE_MALLOC
|
|
int ret = DLMS_ERROR_CODE_OK;
|
|
if ((source->vt & DLMS_DATA_TYPE_BYREF) != 0)
|
|
{
|
|
if (source->vt == (DLMS_DATA_TYPE_BYREF | DLMS_DATA_TYPE_ARRAY) ||
|
|
source->vt == (DLMS_DATA_TYPE_BYREF | DLMS_DATA_TYPE_STRUCTURE))
|
|
{
|
|
target->vt = source->vt & ~DLMS_DATA_TYPE_BYREF;
|
|
target->pVal = source->pVal;
|
|
return 0;
|
|
}
|
|
if (source->vt == (DLMS_DATA_TYPE_BYREF | DLMS_DATA_TYPE_OCTET_STRING) ||
|
|
source->vt == (DLMS_DATA_TYPE_BYREF | DLMS_DATA_TYPE_STRING) ||
|
|
source->vt == (DLMS_DATA_TYPE_BYREF | DLMS_DATA_TYPE_BIT_STRING) ||
|
|
source->vt == (DLMS_DATA_TYPE_BYREF | DLMS_DATA_TYPE_DATETIME) ||
|
|
source->vt == (DLMS_DATA_TYPE_BYREF | DLMS_DATA_TYPE_DATE) ||
|
|
source->vt == (DLMS_DATA_TYPE_BYREF | DLMS_DATA_TYPE_TIME))
|
|
{
|
|
return var_getBytes2(source, source->vt, target->byteArr);
|
|
}
|
|
target->vt = source->vt & ~DLMS_DATA_TYPE_BYREF;
|
|
target->ullVal = *source->pullVal;
|
|
return 0;
|
|
}
|
|
if ((target->vt & DLMS_DATA_TYPE_BYREF) != 0)
|
|
{
|
|
uint16_t count;
|
|
if (source->vt == DLMS_DATA_TYPE_OCTET_STRING || source->vt == DLMS_DATA_TYPE_STRING)
|
|
{
|
|
if ((ret = hlp_getObjectCount2(source->byteArr, &count)) != 0)
|
|
{
|
|
return ret;
|
|
}
|
|
#ifdef DLMS_IGNORE_MALLOC
|
|
if (count > target->capacity)
|
|
{
|
|
return DLMS_ERROR_CODE_INVALID_PARAMETER;
|
|
}
|
|
target->size = count;
|
|
#endif //DLMS_IGNORE_MALLOC
|
|
memcpy(target->pVal, source->byteArr + source->byteArr->position, count);
|
|
}
|
|
else
|
|
{
|
|
count = (uint16_t)hlp_getDataTypeSize(source->vt);
|
|
if (count != hlp_getDataTypeSize(target->vt ^ DLMS_DATA_TYPE_BYREF))
|
|
{
|
|
return DLMS_ERROR_CODE_INVALID_PARAMETER;
|
|
}
|
|
memcpy(target->pVal, &source->bVal, count);
|
|
}
|
|
return 0;
|
|
}
|
|
#ifndef DLMS_IGNORE_MALLOC
|
|
unsigned char attaced = 0;
|
|
if ((target->vt == DLMS_DATA_TYPE_ARRAY || target->vt == DLMS_DATA_TYPE_STRUCTURE) && va_isAttached(target->Arr))
|
|
{
|
|
attaced = 1;
|
|
}
|
|
else
|
|
#endif //DLMS_IGNORE_MALLOC
|
|
{
|
|
ret = var_clear(target);
|
|
if (ret != DLMS_ERROR_CODE_OK)
|
|
{
|
|
return ret;
|
|
}
|
|
target->vt = source->vt;
|
|
}
|
|
if (source->vt == DLMS_DATA_TYPE_STRING)
|
|
{
|
|
#ifndef DLMS_IGNORE_MALLOC
|
|
if (source->strVal != NULL)
|
|
{
|
|
target->strVal = (gxByteBuffer*)gxmalloc(sizeof(gxByteBuffer));
|
|
BYTE_BUFFER_INIT(target->strVal);
|
|
bb_set(target->strVal, source->strVal->data, source->strVal->size);
|
|
}
|
|
#else
|
|
return DLMS_ERROR_CODE_INVALID_PARAMETER;
|
|
#endif //DLMS_IGNORE_MALLOC
|
|
}
|
|
else if (source->vt == DLMS_DATA_TYPE_OCTET_STRING)
|
|
{
|
|
#ifndef DLMS_IGNORE_MALLOC
|
|
if (source->byteArr != 0)
|
|
{
|
|
target->byteArr = (gxByteBuffer*)gxmalloc(sizeof(gxByteBuffer));
|
|
BYTE_BUFFER_INIT(target->byteArr);
|
|
bb_set(target->byteArr, source->byteArr->data, source->byteArr->size);
|
|
}
|
|
#else
|
|
return DLMS_ERROR_CODE_INVALID_PARAMETER;
|
|
#endif //DLMS_IGNORE_MALLOC
|
|
}
|
|
else if (source->vt == DLMS_DATA_TYPE_ARRAY ||
|
|
source->vt == DLMS_DATA_TYPE_STRUCTURE)
|
|
{
|
|
#ifndef DLMS_IGNORE_MALLOC
|
|
int pos;
|
|
if (source->Arr != NULL && source->Arr->size != 0)
|
|
{
|
|
if (target->Arr == NULL)
|
|
{
|
|
target->Arr = (variantArray*)gxmalloc(sizeof(variantArray));
|
|
va_init(target->Arr);
|
|
}
|
|
va_capacity(target->Arr, source->Arr->size);
|
|
for (pos = 0; pos != source->Arr->size; ++pos)
|
|
{
|
|
if ((ret = va_getByIndex(source->Arr, pos, &it)) != DLMS_ERROR_CODE_OK)
|
|
{
|
|
return ret;
|
|
}
|
|
if (attaced)
|
|
{
|
|
if ((ret = va_getByIndex(target->Arr, pos, &item)) != DLMS_ERROR_CODE_OK ||
|
|
(ret = var_copy(item, it)) != DLMS_ERROR_CODE_OK)
|
|
{
|
|
return ret;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
item = (dlmsVARIANT*)gxmalloc(sizeof(dlmsVARIANT));
|
|
ret = var_init(item);
|
|
if (ret != DLMS_ERROR_CODE_OK)
|
|
{
|
|
return ret;
|
|
}
|
|
ret = var_copy(item, it);
|
|
if (ret != DLMS_ERROR_CODE_OK)
|
|
{
|
|
return ret;
|
|
}
|
|
va_push(target->Arr, item);
|
|
}
|
|
}
|
|
}
|
|
#else
|
|
return DLMS_ERROR_CODE_INVALID_PARAMETER;
|
|
#endif //DLMS_IGNORE_MALLOC
|
|
}
|
|
#ifndef DLMS_IGNORE_MALLOC
|
|
else if (source->vt == DLMS_DATA_TYPE_DATETIME)
|
|
{
|
|
ret = var_setDateTime(target, source->dateTime);
|
|
}
|
|
else if (source->vt == DLMS_DATA_TYPE_DATE)
|
|
{
|
|
ret = var_setDate(target, source->dateTime);
|
|
}
|
|
else if (source->vt == DLMS_DATA_TYPE_TIME)
|
|
{
|
|
ret = var_setTime(target, source->dateTime);
|
|
}
|
|
#endif //DLMS_IGNORE_MALLOC
|
|
else if (source->vt == DLMS_DATA_TYPE_BIT_STRING)
|
|
{
|
|
#ifndef DLMS_IGNORE_MALLOC
|
|
target->bitArr = (bitArray*)gxmalloc(sizeof(bitArray));
|
|
ba_init(target->bitArr);
|
|
ret = ba_copy(target->bitArr, source->bitArr->data, (uint16_t)source->bitArr->size);
|
|
#else
|
|
return DLMS_ERROR_CODE_INVALID_PARAMETER;
|
|
#endif //DLMS_IGNORE_MALLOC
|
|
}
|
|
else
|
|
{
|
|
ret = var_getSize(source->vt);
|
|
if (ret > 0)
|
|
{
|
|
memcpy(&target->pVal, &source->pVal, ret);
|
|
}
|
|
ret = 0;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
#ifndef DLMS_IGNORE_MALLOC
|
|
int var_setDateTime(dlmsVARIANT* target, gxtime* value)
|
|
{
|
|
int ret;
|
|
if ((ret = var_clear(target)) == DLMS_ERROR_CODE_OK)
|
|
{
|
|
target->dateTime = (gxtime*)gxmalloc(sizeof(gxtime));
|
|
time_copy(target->dateTime, value);
|
|
target->vt = DLMS_DATA_TYPE_DATETIME;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int var_setDate(dlmsVARIANT* target, gxtime* value)
|
|
{
|
|
int ret;
|
|
if ((ret = var_clear(target)) == DLMS_ERROR_CODE_OK)
|
|
{
|
|
target->dateTime = (gxtime*)gxmalloc(sizeof(gxtime));
|
|
time_copy(target->dateTime, value);
|
|
target->vt = DLMS_DATA_TYPE_DATE;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int var_setTime(dlmsVARIANT* target, gxtime* value)
|
|
{
|
|
int ret;
|
|
if ((ret = var_clear(target)) == DLMS_ERROR_CODE_OK)
|
|
{
|
|
target->dateTime = (gxtime*)gxmalloc(sizeof(gxtime));
|
|
time_copy(target->dateTime, value);
|
|
target->vt = DLMS_DATA_TYPE_TIME;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int var_setDateTimeAsOctetString(
|
|
dlmsVARIANT* target,
|
|
gxtime* value)
|
|
{
|
|
int ret;
|
|
if ((ret = var_clear(target)) == DLMS_ERROR_CODE_OK)
|
|
{
|
|
target->byteArr = (gxByteBuffer*)gxmalloc(sizeof(gxByteBuffer));
|
|
BYTE_BUFFER_INIT(target->byteArr);
|
|
bb_capacity(target->byteArr, 12);
|
|
if ((ret = var_getDateTime2(value, target->byteArr)) == 0)
|
|
{
|
|
target->vt = DLMS_DATA_TYPE_OCTET_STRING;
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int var_setDateAsOctetString(
|
|
dlmsVARIANT* target,
|
|
gxtime* value)
|
|
{
|
|
int ret;
|
|
if ((ret = var_clear(target)) == DLMS_ERROR_CODE_OK)
|
|
{
|
|
target->byteArr = (gxByteBuffer*)gxmalloc(sizeof(gxByteBuffer));
|
|
BYTE_BUFFER_INIT(target->byteArr);
|
|
bb_capacity(target->byteArr, 5);
|
|
if ((ret = var_getDate(value, target->byteArr)) == 0)
|
|
{
|
|
target->vt = DLMS_DATA_TYPE_OCTET_STRING;
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int var_setTimeAsOctetString(
|
|
dlmsVARIANT* target,
|
|
gxtime* value)
|
|
{
|
|
int ret;
|
|
if ((ret = var_clear(target)) == DLMS_ERROR_CODE_OK)
|
|
{
|
|
target->byteArr = (gxByteBuffer*)gxmalloc(sizeof(gxByteBuffer));
|
|
BYTE_BUFFER_INIT(target->byteArr);
|
|
bb_capacity(target->byteArr, 4);
|
|
if ((ret = var_getTime(value, target->byteArr)) == 0)
|
|
{
|
|
target->vt = DLMS_DATA_TYPE_OCTET_STRING;
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
#endif //DLMS_IGNORE_MALLOC
|
|
int var_setBoolean(dlmsVARIANT* target, char value)
|
|
{
|
|
int ret;
|
|
if ((ret = var_clear(target)) == DLMS_ERROR_CODE_OK)
|
|
{
|
|
target->boolVal = value;
|
|
target->vt = DLMS_DATA_TYPE_BOOLEAN;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
#ifdef DLMS_IGNORE_MALLOC
|
|
//Attach value by ref.
|
|
int var_byRef(dlmsVARIANT* target, DLMS_DATA_TYPE type, void* value)
|
|
{
|
|
int ret;
|
|
ret = var_clear(target);
|
|
if (ret != DLMS_ERROR_CODE_OK)
|
|
{
|
|
return ret;
|
|
}
|
|
target->pVal = value;
|
|
target->vt = type | DLMS_DATA_TYPE_BYREF;
|
|
return ret;
|
|
}
|
|
#endif //DLMS_IGNORE_MALLOC
|
|
|
|
#ifndef DLMS_IGNORE_MALLOC
|
|
void var_attach(
|
|
dlmsVARIANT* target,
|
|
gxByteBuffer* source)
|
|
{
|
|
target->byteArr = (gxByteBuffer*)gxmalloc(sizeof(gxByteBuffer));
|
|
target->byteArr->data = source->data;
|
|
target->byteArr->capacity = source->capacity;
|
|
target->byteArr->size = source->size;
|
|
target->byteArr->position = source->position;
|
|
source->data = 0;
|
|
source->size = source->position = source->capacity = 0;
|
|
target->vt = DLMS_DATA_TYPE_OCTET_STRING;
|
|
}
|
|
#endif //DLMS_IGNORE_MALLOC
|
|
|
|
int var_getDateTime(dlmsVARIANT* target, gxtime* value)
|
|
{
|
|
if (target->vt == DLMS_DATA_TYPE_NONE)
|
|
{
|
|
time_clear(value);
|
|
}
|
|
#ifndef DLMS_IGNORE_MALLOC
|
|
else if (target->vt == DLMS_DATA_TYPE_DATETIME ||
|
|
target->vt == DLMS_DATA_TYPE_DATE ||
|
|
target->vt == DLMS_DATA_TYPE_TIME)
|
|
{
|
|
value->extraInfo = target->dateTime->extraInfo;
|
|
value->skip = target->dateTime->skip;
|
|
value->status = target->dateTime->status;
|
|
value->value = target->dateTime->value;
|
|
}
|
|
#endif //DLMS_IGNORE_MALLOC
|
|
else
|
|
{
|
|
return DLMS_ERROR_CODE_INVALID_PARAMETER;
|
|
}
|
|
return DLMS_ERROR_CODE_OK;
|
|
}
|
|
|
|
double var_toDouble(dlmsVARIANT* target)
|
|
{
|
|
switch (target->vt)
|
|
{
|
|
case DLMS_DATA_TYPE_NONE:
|
|
{
|
|
return 0;
|
|
}
|
|
case DLMS_DATA_TYPE_BOOLEAN:
|
|
{
|
|
return target->boolVal ? 1 : 0;
|
|
}
|
|
case DLMS_DATA_TYPE_INT32:
|
|
{
|
|
return target->lVal;
|
|
}
|
|
case DLMS_DATA_TYPE_UINT32:
|
|
{
|
|
return target->ulVal;
|
|
}
|
|
case DLMS_DATA_TYPE_STRING_UTF8:
|
|
{
|
|
#if defined(_WIN32) || defined(_WIN64) || defined(__linux__)
|
|
assert(0);
|
|
#endif
|
|
return 0;
|
|
}
|
|
case DLMS_DATA_TYPE_STRING:
|
|
{
|
|
#if defined(_WIN32) || defined(_WIN64) || defined(__linux__)
|
|
assert(0);
|
|
#endif
|
|
return 0;
|
|
}
|
|
case DLMS_DATA_TYPE_INT8:
|
|
{
|
|
return target->cVal;
|
|
}
|
|
case DLMS_DATA_TYPE_INT16:
|
|
{
|
|
return target->iVal;
|
|
}
|
|
case DLMS_DATA_TYPE_UINT8:
|
|
{
|
|
return target->bVal;
|
|
}
|
|
case DLMS_DATA_TYPE_UINT16:
|
|
{
|
|
return target->uiVal;
|
|
}
|
|
case DLMS_DATA_TYPE_INT64:
|
|
{
|
|
return (double)target->llVal;
|
|
}
|
|
case DLMS_DATA_TYPE_UINT64:
|
|
{
|
|
return (double)target->ullVal;
|
|
}
|
|
case DLMS_DATA_TYPE_ENUM:
|
|
{
|
|
return target->bVal;
|
|
}
|
|
#ifndef DLMS_IGNORE_FLOAT32
|
|
case DLMS_DATA_TYPE_FLOAT32:
|
|
{
|
|
return target->fltVal;
|
|
}
|
|
#endif //DLMS_IGNORE_FLOAT32
|
|
#ifndef DLMS_IGNORE_FLOAT64
|
|
case DLMS_DATA_TYPE_FLOAT64:
|
|
{
|
|
return target->dblVal;
|
|
}
|
|
#endif //DLMS_IGNORE_FLOAT64
|
|
default:
|
|
break;
|
|
}
|
|
#if defined(_WIN32) || defined(_WIN64) || defined(__linux__)
|
|
assert(0);
|
|
#endif
|
|
return 0;
|
|
}
|
|
|
|
#if !defined(DLMS_IGNORE_STRING_CONVERTER) && !defined(DLMS_IGNORE_MALLOC)
|
|
//Print content of the variant to cout.
|
|
int var_print(const char* format, dlmsVARIANT* target)
|
|
{
|
|
int ret = DLMS_ERROR_CODE_OK;
|
|
dlmsVARIANT tmp;
|
|
var_init(&tmp);
|
|
ret = var_copy(&tmp, target);
|
|
if (ret == 0)
|
|
{
|
|
ret = var_changeType(&tmp, DLMS_DATA_TYPE_STRING);
|
|
if (ret == 0 && tmp.strVal != NULL)
|
|
{
|
|
if (format == NULL)
|
|
{
|
|
format = "%s\r\n";
|
|
}
|
|
printf(format, tmp.strVal->data);
|
|
}
|
|
}
|
|
var_clear(&tmp);
|
|
return ret;
|
|
}
|
|
|
|
int va_print(
|
|
variantArray* items)
|
|
{
|
|
dlmsVARIANT* it;
|
|
int pos, ret = DLMS_ERROR_CODE_OK;
|
|
const char* format = "%s,\r\n";
|
|
for (pos = 0; pos != items->size; ++pos)
|
|
{
|
|
if ((ret = va_getByIndex(items, pos, &it)) != 0)
|
|
{
|
|
return ret;
|
|
}
|
|
|
|
if (pos + 1 == items->size)
|
|
{
|
|
format = NULL;
|
|
}
|
|
if ((ret = var_print(format, it)) != 0)
|
|
{
|
|
return ret;
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
#endif //!defined(DLMS_IGNORE_STRING_CONVERTER) && defined(DLMS_IGNORE_MALLOC)
|