esphome_elektromer_han/components/xt211/bytebuffer.c

1310 lines
30 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
//---------------------------------------------------------------------------
#include "gxmem.h"
#ifndef DLMS_IGNORE_STRING_CONVERTER
#include <stdio.h> //printf needs this or error is generated.
#endif //DLMS_IGNORE_STRING_CONVERTER
#if defined(_WIN32) || defined(_WIN64) || defined(__linux__)
#include <assert.h>
#if _MSC_VER > 1400
#include <crtdbg.h>
#endif
#endif
#include <string.h>
#include "errorcodes.h"
#include "bytebuffer.h"
#include "helpers.h"
char bb_isAttached(gxByteBuffer* arr)
{
if (arr == NULL)
{
return 0;
}
#if defined(GX_DLMS_BYTE_BUFFER_SIZE_32) || (!defined(GX_DLMS_MICROCONTROLLER) && (defined(_WIN32) || defined(_WIN64) || defined(__linux__)))
//If byte buffer is attached.
return (arr->capacity & 0x80000000) == 0x80000000;
#else
return (arr->capacity & 0x8000) == 0x8000;
#endif
}
#if defined(GX_DLMS_BYTE_BUFFER_SIZE_32) || (!defined(GX_DLMS_MICROCONTROLLER) && (defined(_WIN32) || defined(_WIN64) || defined(__linux__)))
uint32_t bb_available(gxByteBuffer* arr)
#else
uint16_t bb_available(gxByteBuffer* arr)
#endif
{
if (arr == NULL)
{
return 0;
}
return arr->size - arr->position;
}
#if defined(GX_DLMS_BYTE_BUFFER_SIZE_32) || (!defined(GX_DLMS_MICROCONTROLLER) && (defined(_WIN32) || defined(_WIN64) || defined(__linux__)))
uint32_t bb_getCapacity(gxByteBuffer* arr)
#else
uint16_t bb_getCapacity(gxByteBuffer* arr)
#endif
{
#if defined(GX_DLMS_BYTE_BUFFER_SIZE_32) || (!defined(GX_DLMS_MICROCONTROLLER)&& (defined(_WIN32) || defined(_WIN64) || defined(__linux__)))
//If byte buffer is attached.
return arr->capacity & 0x7FFFFFFF;
#else
return arr->capacity & 0x7FFF;
#endif
}
#if defined(GX_DLMS_BYTE_BUFFER_SIZE_32) || (!defined(GX_DLMS_MICROCONTROLLER) && (defined(_WIN32) || defined(_WIN64) || defined(__linux__)))
uint32_t bb_size(gxByteBuffer* arr)
#else
uint16_t bb_size(gxByteBuffer* arr)
#endif
{
return arr != NULL ? arr->size : 0;
}
int BYTE_BUFFER_INIT(
gxByteBuffer* arr)
{
arr->capacity = 0;
arr->data = NULL;
arr->position = 0;
arr->size = 0;
return 0;
}
#if defined(GX_DLMS_BYTE_BUFFER_SIZE_32) || (!defined(GX_DLMS_MICROCONTROLLER) && (defined(_WIN32) || defined(_WIN64) || defined(__linux__)))
int bb_capacity(
gxByteBuffer* arr,
uint32_t capacity)
#else
int bb_capacity(
gxByteBuffer* arr,
uint16_t capacity)
#endif
{
#ifndef DLMS_IGNORE_MALLOC
//Capacity can't change if it's attached.
if (!bb_isAttached(arr))
{
if (capacity == 0)
{
if (arr->data != NULL)
{
gxfree(arr->data);
arr->data = NULL;
arr->size = 0;
}
}
else
{
if (arr->capacity == 0)
{
arr->data = (unsigned char*)gxmalloc(capacity);
if (arr->data == NULL)
{
return DLMS_ERROR_CODE_OUTOFMEMORY;
}
}
else
{
#ifdef gxrealloc
//If compiler supports realloc.
unsigned char* tmp = (unsigned char*)gxrealloc(arr->data, capacity);
//If not enought memory available.
if (tmp == NULL)
{
return DLMS_ERROR_CODE_OUTOFMEMORY;
}
arr->data = tmp;
#else
//If compiler doesn't support realloc.
unsigned char* old = arr->data;
arr->data = (unsigned char*)gxmalloc(capacity);
//If not enought memory available.
if (arr->data == NULL)
{
arr->data = old;
return DLMS_ERROR_CODE_OUTOFMEMORY;
}
memcpy(arr->data, old, arr->size);
gxfree(old);
#endif // gxrealloc
}
if (arr->size > capacity)
{
arr->size = capacity;
}
}
arr->capacity = capacity;
}
#endif //DLMS_IGNORE_MALLOC
if (bb_getCapacity(arr) < capacity)
{
return DLMS_ERROR_CODE_OUTOFMEMORY;
}
return DLMS_ERROR_CODE_OK;
}
#if defined(GX_DLMS_BYTE_BUFFER_SIZE_32) || (!defined(GX_DLMS_MICROCONTROLLER) && (defined(_WIN32) || defined(_WIN64) || defined(__linux__)))
int bb_zero(
gxByteBuffer* arr,
uint32_t index,
uint32_t count)
#else
int bb_zero(
gxByteBuffer* arr,
uint16_t index,
uint16_t count)
#endif
{
int ret;
if (index + count > arr->capacity)
{
if ((ret = bb_capacity(arr, (index + count))) != 0)
{
return ret;
}
}
if (arr->size < index + count)
{
arr->size = index + count;
}
memset(arr->data + index, 0, count);
return 0;
}
int bb_setUInt8(
gxByteBuffer* arr,
unsigned char item)
{
int ret = bb_setUInt8ByIndex(arr, bb_size(arr), item);
if (ret == 0)
{
++arr->size;
}
return ret;
}
#if defined(GX_DLMS_BYTE_BUFFER_SIZE_32) || (!defined(GX_DLMS_MICROCONTROLLER) && (defined(_WIN32) || defined(_WIN64) || defined(__linux__)))
int bb_insertUInt8(
gxByteBuffer* arr,
uint32_t index,
unsigned char item)
#else
int bb_insertUInt8(
gxByteBuffer* arr,
uint16_t index,
unsigned char item)
#endif
{
int ret;
if ((ret = bb_move(arr, index, index + 1, arr->size)) == 0)
{
if (index == 0 && arr->size == 0)
{
//If buffer is empty and there is no data to move.
++arr->size;
}
ret = bb_setUInt8ByIndex(arr, index, item);
}
return ret;
}
#if defined(GX_DLMS_BYTE_BUFFER_SIZE_32) || (!defined(GX_DLMS_MICROCONTROLLER) && (defined(_WIN32) || defined(_WIN64) || defined(__linux__)))
int bb_allocate(
gxByteBuffer* arr,
uint32_t index,
uint32_t dataSize)
#else
int bb_allocate(
gxByteBuffer* arr,
uint16_t index,
uint16_t dataSize)
#endif
{
#ifndef DLMS_IGNORE_MALLOC
if (!bb_isAttached(arr) && (arr->capacity == 0 || index + dataSize > arr->capacity))
{
unsigned char empty = arr->capacity == 0;
//If data is append fist time.
if (dataSize > VECTOR_CAPACITY || arr->capacity == 0)
{
arr->capacity += dataSize;
}
else
{
arr->capacity += VECTOR_CAPACITY;
}
if (empty)
{
arr->data = (unsigned char*)gxmalloc(arr->capacity);
if (arr->data == NULL)
{
return DLMS_ERROR_CODE_OUTOFMEMORY;
}
}
else
{
#ifdef gxrealloc
//If compiler supports realloc.
unsigned char* tmp = (unsigned char*)gxrealloc(arr->data, arr->capacity);
if (tmp == NULL)
{
return DLMS_ERROR_CODE_OUTOFMEMORY;
}
arr->data = tmp;
#else
//If compiler doesn't supports realloc.
unsigned char* old = arr->data;
arr->data = (unsigned char*)gxmalloc(arr->capacity);
//If not enought memory available.
if (arr->data == NULL)
{
arr->data = old;
return DLMS_ERROR_CODE_OUTOFMEMORY;
}
memcpy(arr->data, old, arr->size);
gxfree(old);
#endif //gxrealloc
}
}
#endif //DLMS_IGNORE_MALLOC
if (bb_getCapacity(arr) < index + dataSize)
{
return DLMS_ERROR_CODE_OUTOFMEMORY;
}
return 0;
}
#if defined(GX_DLMS_BYTE_BUFFER_SIZE_32) || (!defined(GX_DLMS_MICROCONTROLLER) && (defined(_WIN32) || defined(_WIN64) || defined(__linux__)))
int bb_setUInt8ByIndex(
gxByteBuffer* arr,
uint32_t index,
unsigned char item)
#else
int bb_setUInt8ByIndex(
gxByteBuffer* arr,
uint16_t index,
unsigned char item)
#endif
{
if (arr == NULL)
{
return DLMS_ERROR_CODE_INVALID_PARAMETER;
}
int ret = bb_allocate(arr, index, 1);
if (ret == 0)
{
arr->data[index] = item;
}
return ret;
}
int bb_setUInt16(
gxByteBuffer* arr,
uint16_t item)
{
int ret = bb_setUInt16ByIndex(arr, arr->size, item);
if (ret == 0)
{
arr->size += 2;
}
return ret;
}
#if defined(GX_DLMS_BYTE_BUFFER_SIZE_32) || (!defined(GX_DLMS_MICROCONTROLLER) && (defined(_WIN32) || defined(_WIN64) || defined(__linux__)))
int bb_setUInt16ByIndex(
gxByteBuffer* arr,
uint32_t index,
uint16_t item)
#else
int bb_setUInt16ByIndex(
gxByteBuffer* arr,
uint16_t index,
uint16_t item)
#endif
{
int ret = 0;
if (index + 2 > arr->size)
{
bb_allocate(arr, arr->size, 2);
}
if (ret == 0)
{
arr->data[index] = (item >> 8) & 0xFF;
arr->data[index + 1] = item & 0xFF;
}
return ret;
}
int bb_setUInt32(
gxByteBuffer* arr,
uint32_t item)
{
int ret = bb_setUInt32ByIndex(arr, arr->size, item);
if (ret == 0)
{
arr->size += 4;
}
return ret;
}
#if defined(GX_DLMS_BYTE_BUFFER_SIZE_32) || (!defined(GX_DLMS_MICROCONTROLLER) && (defined(_WIN32) || defined(_WIN64) || defined(__linux__)))
int bb_setUInt32ByIndex(
gxByteBuffer* arr,
uint32_t index,
uint32_t item)
#else
int bb_setUInt32ByIndex(
gxByteBuffer* arr,
uint16_t index,
uint32_t item)
#endif //defined(GX_DLMS_BYTE_BUFFER_SIZE_32) || (!defined(GX_DLMS_MICROCONTROLLER) && (defined(_WIN32) || defined(_WIN64) || defined(__linux__)))
{
int ret = bb_allocate(arr, index, 4);
if (ret == 0)
{
PUT32(arr->data + index, item);
}
return ret;
}
int bb_setUInt64(
gxByteBuffer* arr,
uint64_t item)
{
int ret = bb_allocate(arr, arr->size, 8);
if (ret == 0)
{
((unsigned char*)arr->data)[arr->size + 7] = item & 0xFF;
item >>= 8;
((unsigned char*)arr->data)[arr->size + 6] = item & 0xFF;
item >>= 8;
((unsigned char*)arr->data)[arr->size + 5] = item & 0xFF;
item >>= 8;
((unsigned char*)arr->data)[arr->size + 4] = item & 0xFF;
item >>= 8;
((unsigned char*)arr->data)[arr->size + 3] = item & 0xFF;
item >>= 8;
((unsigned char*)arr->data)[arr->size + 2] = item & 0xFF;
item >>= 8;
((unsigned char*)arr->data)[arr->size + 1] = item & 0xFF;
item >>= 8;
((unsigned char*)arr->data)[arr->size] = item & 0xFF;
arr->size += 8;
}
return ret;
}
#ifndef DLMS_IGNORE_FLOAT32
int bb_setFloat(
gxByteBuffer* arr,
float value)
{
typedef union
{
float value;
char b[sizeof(float)];
} HELPER;
HELPER tmp;
tmp.value = value;
int ret = bb_allocate(arr, arr->size, 4);
if (ret == 0)
{
arr->data[arr->size] = tmp.b[3];
arr->data[arr->size + 1] = tmp.b[2];
arr->data[arr->size + 2] = tmp.b[1];
arr->data[arr->size + 3] = tmp.b[0];
arr->size += 4;
}
return ret;
}
#endif //DLMS_IGNORE_FLOAT32
#ifndef DLMS_IGNORE_FLOAT64
int bb_setDouble(
gxByteBuffer* arr,
double value)
{
typedef union
{
double value;
char b[sizeof(double)];
} HELPER;
HELPER tmp;
tmp.value = value;
int ret = bb_allocate(arr, arr->size, 8);
if (ret == 0)
{
arr->data[arr->size] = tmp.b[7];
arr->data[arr->size + 1] = tmp.b[6];
arr->data[arr->size + 2] = tmp.b[5];
arr->data[arr->size + 3] = tmp.b[4];
arr->data[arr->size + 4] = tmp.b[3];
arr->data[arr->size + 5] = tmp.b[2];
arr->data[arr->size + 6] = tmp.b[1];
arr->data[arr->size + 7] = tmp.b[0];
arr->size += 8;
}
return ret;
}
#endif //DLMS_IGNORE_FLOAT64
int bb_setInt8(
gxByteBuffer* arr,
char item)
{
return bb_setUInt8(arr, (unsigned char)item);
}
int bb_setInt16(
gxByteBuffer* arr,
short item)
{
return bb_setUInt16(arr, (uint16_t)item);
}
int bb_setInt32(
gxByteBuffer* arr,
int32_t item)
{
return bb_setUInt32(arr, (uint32_t)item);
}
int bb_setInt64(
gxByteBuffer* arr,
int64_t item)
{
return bb_setUInt64(arr, (uint64_t)item);
}
#if defined(GX_DLMS_BYTE_BUFFER_SIZE_32) || (!defined(GX_DLMS_MICROCONTROLLER) && (defined(_WIN32) || defined(_WIN64) || defined(__linux__)))
int bb_set(
gxByteBuffer* arr,
const unsigned char* pSource,
uint32_t count)
#else
int bb_set(
gxByteBuffer* arr,
const unsigned char* pSource,
uint16_t count)
#endif
{
if (count != 0)
{
int ret = bb_allocate(arr, arr->size, count);
if (ret == 0)
{
if (arr->size + count > arr->capacity)
{
return DLMS_ERROR_CODE_OUTOFMEMORY;
}
memcpy(arr->data + arr->size, pSource, count);
arr->size += count;
}
return ret;
}
else
{
return 0;
}
}
#if defined(GX_DLMS_BYTE_BUFFER_SIZE_32) || (!defined(GX_DLMS_MICROCONTROLLER) && (defined(_WIN32) || defined(_WIN64) || defined(__linux__)))
int bb_set2(
gxByteBuffer* arr,
gxByteBuffer* data,
uint32_t index,
uint32_t count)
#else
int bb_set2(
gxByteBuffer* arr,
gxByteBuffer* data,
uint16_t index,
uint16_t count)
#endif
{
if (data != NULL && count != 0)
{
#if defined(GX_DLMS_BYTE_BUFFER_SIZE_32) || (!defined(GX_DLMS_MICROCONTROLLER) && (defined(_WIN32) || defined(_WIN64) || defined(__linux__)))
if (count == (uint32_t)-1)
#else
if (count == (uint16_t)-1)
#endif
{
count = data->size - index;
}
int ret = bb_set(arr, data->data + index, count);
if (ret == 0)
{
data->position += count;
}
return ret;
}
return 0;
}
int bb_addString(
gxByteBuffer* arr,
const char* value)
{
if (value != NULL)
{
int len = (int)strlen(value);
if (len > 0)
{
int ret = bb_set(arr, (const unsigned char*)value, (uint16_t)(len + 1));
if (ret == 0)
{
//Add end of string, but that is not added to the length.
arr->data[arr->size - 1] = '\0';
--arr->size;
}
return ret;
}
}
return 0;
}
#if defined(GX_DLMS_BYTE_BUFFER_SIZE_32) || (!defined(GX_DLMS_MICROCONTROLLER) && (defined(_WIN32) || defined(_WIN64) || defined(__linux__)))
int bb_attach(
gxByteBuffer* arr,
unsigned char* value,
uint32_t count,
uint32_t capacity)
#else
int bb_attach(
gxByteBuffer* arr,
unsigned char* value,
uint16_t count,
uint16_t capacity)
#endif
{
//If capacity is 1 value is cast t
if (value == NULL || capacity < count)
{
return DLMS_ERROR_CODE_OUTOFMEMORY;
}
arr->data = value;
#if defined(GX_DLMS_BYTE_BUFFER_SIZE_32) || (!defined(GX_DLMS_MICROCONTROLLER) && (defined(_WIN32) || defined(_WIN64) || defined(__linux__)))
if (capacity >= 0x80000000)
{
return DLMS_ERROR_CODE_OUTOFMEMORY;
}
arr->capacity = (0x80000000 | capacity);
#else
if (capacity >= 0x8000)
{
return DLMS_ERROR_CODE_OUTOFMEMORY;
}
arr->capacity = (uint16_t)(0x8000 | capacity);
#endif
arr->size = count;
arr->position = 0;
return 0;
}
#if defined(GX_DLMS_BYTE_BUFFER_SIZE_32) || (!defined(GX_DLMS_MICROCONTROLLER) && (defined(_WIN32) || defined(_WIN64) || defined(__linux__)))
int bb_attachString2(
gxByteBuffer* arr,
char* value,
uint32_t count,
uint32_t capacity)
#else
int bb_attachString2(
gxByteBuffer* arr,
char* value,
uint16_t count,
uint16_t capacity)
#endif
{
return bb_attach(arr, (unsigned char*)value, count, capacity);
}
#ifndef DLMS_IGNORE_MALLOC
int bb_attachString(
gxByteBuffer* arr,
char* value)
{
int len = (int)strlen(value);
int ret = bb_set(arr, (const unsigned char*)value, (uint16_t)len);
gxfree(value);
return ret;
}
#endif //DLMS_IGNORE_MALLOC
int bb_clear(
gxByteBuffer* arr)
{
#ifndef DLMS_IGNORE_MALLOC
//If byte buffer is attached.
if (!bb_isAttached(arr))
{
if (arr->data != NULL)
{
gxfree(arr->data);
arr->data = NULL;
}
arr->capacity = 0;
}
#endif //DLMS_IGNORE_MALLOC
arr->size = 0;
arr->position = 0;
return 0;
}
int bb_empty(
gxByteBuffer* arr)
{
arr->size = 0;
arr->position = 0;
return 0;
}
int bb_getUInt8(
gxByteBuffer* arr,
unsigned char* value)
{
if (arr->position >= arr->size)
{
return DLMS_ERROR_CODE_OUTOFMEMORY;
}
*value = ((unsigned char*)arr->data)[arr->position];
++arr->position;
return 0;
}
int bb_getInt8(
gxByteBuffer* arr,
signed char* value)
{
if (arr->position >= arr->size)
{
return DLMS_ERROR_CODE_OUTOFMEMORY;
}
*value = (signed char)((unsigned char*)arr->data)[arr->position];
++arr->position;
return 0;
}
int bb_getUInt8ByIndex(
gxByteBuffer* arr,
uint32_t index,
unsigned char* value)
{
if (index >= arr->size)
{
return DLMS_ERROR_CODE_OUTOFMEMORY;
}
*value = ((unsigned char*)arr->data)[index];
return 0;
}
int bb_getUInt16(
gxByteBuffer* arr,
uint16_t* value)
{
if (arr->position + 2 > arr->size)
{
return DLMS_ERROR_CODE_OUTOFMEMORY;
}
*value = (uint16_t)(((unsigned char*)arr->data)[arr->position] << 8 |
((unsigned char*)arr->data)[arr->position + 1]);
arr->position += 2;
return 0;
}
int bb_getUInt32(
gxByteBuffer* arr,
uint32_t* value)
{
if (arr->position + 4 > arr->size)
{
return DLMS_ERROR_CODE_OUTOFMEMORY;
}
*value = GETU32(arr->data + arr->position);
arr->position += 4;
return 0;
}
int bb_getInt16(
gxByteBuffer* arr,
short* value)
{
if (arr->position + 2 > arr->size)
{
return DLMS_ERROR_CODE_OUTOFMEMORY;
}
*value = (short)(((unsigned char*)arr->data)[arr->position] << 8 |
((unsigned char*)arr->data)[arr->position + 1]);
arr->position += 2;
return 0;
}
int bb_getUInt24(
gxByteBuffer* arr,
uint32_t* value)
{
int ret = bb_getUInt24ByIndex(arr, arr->position, value);
arr->position += 3;
return ret;
}
int bb_getInt32(
gxByteBuffer* arr,
int32_t* value)
{
int ret = bb_getUInt32ByIndex(arr, arr->position, (uint32_t*)value);
arr->position += 4;
return ret;
}
int bb_getUInt24ByIndex(
gxByteBuffer* arr,
uint32_t index,
uint32_t* value)
{
if (index + 3 > bb_size(arr))
{
return DLMS_ERROR_CODE_OUTOFMEMORY;
}
*value = ((uint32_t)(arr->data)[index] << 16) |
((uint32_t)(arr->data)[index + 1] << 8) |
((uint32_t)(arr->data)[index + 2]);
return 0;
}
int bb_getUInt32ByIndex(
gxByteBuffer* arr,
uint32_t index,
uint32_t* value)
{
if (index + 4 > arr->size)
{
return DLMS_ERROR_CODE_OUTOFMEMORY;
}
*value = GETU32(arr->data + index);
return 0;
}
int bb_getInt64(
gxByteBuffer* arr,
int64_t* value)
{
int ret = bb_getUInt64ByIndex(arr, arr->position, (uint64_t*)value);
if (ret == 0)
{
arr->position += 8;
}
return ret;
}
int bb_getUInt64(
gxByteBuffer* arr,
uint64_t* value)
{
int ret = bb_getUInt64ByIndex(arr, arr->position, value);
if (ret == 0)
{
arr->position += 8;
}
return ret;
}
int bb_getUInt64ByIndex(
gxByteBuffer* arr,
uint32_t index,
uint64_t* value)
{
if (index + 8 > arr->size)
{
return DLMS_ERROR_CODE_OUTOFMEMORY;
}
*value = GETU32(arr->data + index);
//Some 32 bit microcontrollers can't handle *value <<= 32;
//For this reason value is sifted on two parts.
*value <<= 16;
*value <<= 16;
*value |= GETU32(arr->data + index + 4);
return 0;
}
int bb_getUInt128ByIndex(
gxByteBuffer* arr,
uint32_t index,
unsigned char* value)
{
int ret = bb_getUInt32ByIndex(arr, index, (uint32_t*)value);
if (ret == 0)
{
ret = bb_getUInt32ByIndex(arr, index + 4, (uint32_t*)value + 1);
if (ret == 0)
{
ret = bb_getUInt32ByIndex(arr, index + 8, (uint32_t*)value + 2);
if (ret == 0)
{
ret = bb_getUInt32ByIndex(arr, index + 12, (uint32_t*)value + 3);
}
}
}
return ret;
}
#ifndef DLMS_IGNORE_FLOAT32
int bb_getFloat(
gxByteBuffer* arr,
float* value)
{
typedef union
{
float value;
char b[sizeof(float)];
} HELPER;
HELPER tmp;
if (arr->position + 4 > arr->size)
{
return DLMS_ERROR_CODE_OUTOFMEMORY;
}
tmp.b[3] = arr->data[arr->position];
tmp.b[2] = arr->data[arr->position + 1];
tmp.b[1] = arr->data[arr->position + 2];
tmp.b[0] = arr->data[arr->position + 3];
*value = tmp.value;
arr->position += 4;
return 0;
}
#endif //DLMS_IGNORE_FLOAT32
#ifndef DLMS_IGNORE_FLOAT64
int bb_getDouble(
gxByteBuffer* arr,
double* value)
{
typedef union
{
double value;
char b[sizeof(double)];
} HELPER;
HELPER tmp;
if (arr->position + 8 > arr->size)
{
return DLMS_ERROR_CODE_OUTOFMEMORY;
}
tmp.b[7] = arr->data[arr->position];
tmp.b[6] = arr->data[arr->position + 1];
tmp.b[5] = arr->data[arr->position + 2];
tmp.b[4] = arr->data[arr->position + 3];
tmp.b[3] = arr->data[arr->position + 4];
tmp.b[2] = arr->data[arr->position + 5];
tmp.b[1] = arr->data[arr->position + 6];
tmp.b[0] = arr->data[arr->position + 7];
*value = tmp.value;
arr->position += 8;
return 0;
}
#endif //DLMS_IGNORE_FLOAT64
int bb_getUInt16ByIndex(
gxByteBuffer* arr,
uint32_t index,
uint16_t* value)
{
if (index + 2 > arr->size)
{
return DLMS_ERROR_CODE_OUTOFMEMORY;
}
*value = (uint16_t)(((unsigned char*)arr->data)[index] << 8 |
((unsigned char*)arr->data)[index + 1]);
return 0;
}
#ifndef DLMS_IGNORE_MALLOC
int bb_addHexString(
gxByteBuffer* arr,
const char* str)
{
uint16_t count;
int ret;
unsigned char* buffer = NULL;
ret = hlp_hexToBytes(str, &buffer, &count);
if (ret != 0)
{
return ret;
}
if (buffer != NULL)
{
bb_set(arr, buffer, count);
gxfree(buffer);
}
return 0;
}
#endif //DLMS_IGNORE_MALLOC
int bb_addHexString2(
gxByteBuffer* arr,
const char* str)
{
if (str == NULL)
{
return 0;
}
int len = (int)strlen(str);
if (len == 0)
{
return 0;
}
int ret = 0;
int lastValue = -1;
for (int pos = 0; pos != len; ++pos)
{
if (*str >= '0' && *str < 'g')
{
if (lastValue == -1)
{
lastValue = hlp_getValue(*str);
}
else if (lastValue != -1)
{
if ((ret = bb_setUInt8(arr, (unsigned char)(lastValue << 4 | hlp_getValue(*str)))) != 0)
{
break;
}
lastValue = -1;
}
}
else if (lastValue != -1)
{
ret = bb_setUInt8(arr, hlp_getValue(*str));
lastValue = -1;
}
++str;
}
return ret;
}
int bb_addLogicalName(
gxByteBuffer* arr,
const unsigned char* str)
{
int ret;
char buffer[25];
if ((ret = hlp_bytesToHex2(str, 6, buffer, sizeof(buffer))) == 0)
{
ret = bb_addString(arr, buffer);
}
return ret;
}
int bb_toHexString2(
gxByteBuffer* arr,
char* buffer,
uint16_t size)
{
return hlp_bytesToHex2(arr->data, (uint16_t)arr->size, buffer, size);
}
#if !(defined(DLMS_IGNORE_STRING_CONVERTER) || defined(DLMS_IGNORE_MALLOC))
char* bb_toString(
gxByteBuffer* arr)
{
char* buff = (char*)gxmalloc(arr->size + 1);
if (buff != NULL)
{
memcpy(buff, arr->data, arr->size);
*(buff + arr->size) = 0;
}
return buff;
}
char* bb_toHexString(
gxByteBuffer* arr)
{
char* buff = hlp_bytesToHex(arr->data, arr->size);
return buff;
}
int bb_addDoubleAsString(
gxByteBuffer* bb,
double value)
{
char buff[20];
//Show as integer value if there is no fractal part.
if (value - (int32_t)value == 0)
{
return bb_addIntAsString(bb, (int)value);
}
else
{
#if _MSC_VER > 1000
sprintf_s(buff, 20, "%lf", value);
#else
sprintf(buff, "%lf", value);
#endif
return bb_addString(bb, buff);
}
}
#endif //!(defined(DLMS_IGNORE_STRING_CONVERTER) || defined(DLMS_IGNORE_MALLOC))
int bb_addIntAsString(gxByteBuffer* bb, int value)
{
return bb_addIntAsString2(bb, value, 0);
}
int bb_addIntAsString2(gxByteBuffer* bb, int value, unsigned char digits)
{
int ret;
char str[20];
hlp_intToString(str, 20, value, 1, digits);
if ((ret = bb_addString(bb, str)) != 0)
{
}
return ret;
}
#if defined(GX_DLMS_BYTE_BUFFER_SIZE_32) || (!defined(GX_DLMS_MICROCONTROLLER) && (defined(_WIN32) || defined(_WIN64) || defined(__linux__)))
int bb_subArray(
gxByteBuffer* bb,
uint32_t index,
uint32_t count,
gxByteBuffer* target)
#else
int bb_subArray(
gxByteBuffer* bb,
uint16_t index,
uint16_t count,
gxByteBuffer* target)
#endif
{
bb_clear(target);
bb_set2(target, bb, index, count);
return 0;
}
#if defined(GX_DLMS_BYTE_BUFFER_SIZE_32) || (!defined(GX_DLMS_MICROCONTROLLER) && (defined(_WIN32) || defined(_WIN64) || defined(__linux__)))
int bb_insert(const unsigned char* src,
uint32_t count,
gxByteBuffer* target,
uint32_t index)
#else
int bb_insert(const unsigned char* src,
uint16_t count,
gxByteBuffer* target,
uint16_t index)
#endif
{
int ret;
if (target->size == 0)
{
ret = bb_set(target, src, count);
}
else
{
if ((ret = bb_capacity(target, target->size + count)) == 0 &&
(ret = bb_move(target, index, index + count, target->size - index)) == 0)
{
//Do not use memcpy here!
memmove(target->data + index, src + index, count);
}
}
return ret;
}
#if defined(GX_DLMS_BYTE_BUFFER_SIZE_32) || (!defined(GX_DLMS_MICROCONTROLLER) && (defined(_WIN32) || defined(_WIN64) || defined(__linux__)))
int bb_move(
gxByteBuffer* bb,
uint32_t srcPos,
uint32_t destPos,
uint32_t count)
#else
int bb_move(
gxByteBuffer* bb,
uint16_t srcPos,
uint16_t destPos,
uint16_t count)
#endif
{
//If items are removed.
if (srcPos > destPos)
{
if (bb->size < destPos + count)
{
return DLMS_ERROR_CODE_INVALID_PARAMETER;
}
}
else
{
//Append data.
if (bb_getCapacity(bb) < count + destPos)
{
int ret;
if (bb_isAttached(bb))
{
return DLMS_ERROR_CODE_INVALID_PARAMETER;
}
if ((ret = bb_capacity(bb, count + destPos)) != 0)
{
return ret;
}
}
}
if (count != 0)
{
//Do not use memcpy here!
memmove(bb->data + destPos, bb->data + srcPos, count);
bb->size = (destPos + count);
if (bb->position > bb->size)
{
bb->position = bb->size;
}
}
return DLMS_ERROR_CODE_OK;
}
int bb_trim(
gxByteBuffer* bb)
{
int ret;
if (bb->size == bb->position)
{
bb->size = 0;
}
else
{
if ((ret = bb_move(bb, bb->position, 0, bb->size - bb->position)) != 0)
{
return ret;
}
}
bb->position = 0;
return DLMS_ERROR_CODE_OK;
}
#if defined(GX_DLMS_BYTE_BUFFER_SIZE_32) || (!defined(GX_DLMS_MICROCONTROLLER) && (defined(_WIN32) || defined(_WIN64) || defined(__linux__)))
unsigned char bb_compare(
gxByteBuffer* bb,
unsigned char* buff,
uint32_t length)
#else
unsigned char bb_compare(
gxByteBuffer* bb,
unsigned char* buff,
uint16_t length)
#endif
{
unsigned char equal;
if (bb_available(bb) != length)
{
return 0;
}
equal = memcmp(bb->data + bb->position, buff, length) == 0;
if (equal)
{
bb->position += length;
}
return equal;
}
#if defined(GX_DLMS_BYTE_BUFFER_SIZE_32) || (!defined(GX_DLMS_MICROCONTROLLER) && (defined(_WIN32) || defined(_WIN64) || defined(__linux__)))
int bb_get(
gxByteBuffer* bb,
unsigned char* value,
uint32_t count)
#else
int bb_get(
gxByteBuffer* bb,
unsigned char* value,
uint16_t count)
#endif
{
if (bb == NULL || value == NULL || bb->size - bb->position < count)
{
return DLMS_ERROR_CODE_OUTOFMEMORY;
}
memcpy(value, bb->data + bb->position, count);
bb->position += count;
return 0;
}
uint32_t bb_indexOf(
gxByteBuffer* bb,
char ch)
{
uint32_t pos;
if (bb == NULL)
{
return (uint32_t)-1;
}
for (pos = bb->position; pos < bb->size; ++pos)
{
if (bb->data[pos] == ch)
{
return pos;
}
}
return (uint32_t)-1;
}
#ifndef GX_DLMS_MICROCONTROLLER
#if defined(_WIN32) || defined(_WIN64) || defined(__linux__)
int bb_print(gxByteBuffer* bb)
{
const char hexArray[] = { '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F' };
uint32_t pos;
char hexChars[4];
hexChars[2] = ' ';
hexChars[3] = '\0';
for (pos = 0; pos != bb->size; ++pos)
{
hexChars[0] = hexArray[bb->data[pos] >> 4];
hexChars[1] = hexArray[bb->data[pos] & 0x0F];
printf("%s", hexChars);
}
return 0;
}
#endif //defined(_WIN32) || defined(_WIN64) || defined(__linux__)
#endif //GX_DLMS_MICROCONTROLLER