461 lines
10 KiB
C
461 lines
10 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"
|
|
#if _MSC_VER > 1400
|
|
#include <crtdbg.h>
|
|
#endif
|
|
#include <string.h>
|
|
#include "errorcodes.h"
|
|
#include "gxarray.h"
|
|
#include "bytebuffer.h"
|
|
#include "gxkey.h"
|
|
|
|
//Initialize gxArray.
|
|
void arr_init(gxArray* arr)
|
|
{
|
|
arr->capacity = 0;
|
|
arr->data = NULL;
|
|
arr->size = 0;
|
|
#ifndef DLMS_IGNORE_MALLOC
|
|
arr->position = 0;
|
|
#endif //DLMS_IGNORE_MALLOC
|
|
}
|
|
|
|
char arr_isAttached(gxArray* arr)
|
|
{
|
|
return (arr->capacity & 0x8000) == 0x8000;
|
|
}
|
|
|
|
uint16_t arr_getCapacity(gxArray* arr)
|
|
{
|
|
return arr->capacity & 0x7FFF;
|
|
}
|
|
|
|
void arr_attach(
|
|
gxArray* arr,
|
|
void* value,
|
|
uint16_t count,
|
|
uint16_t capacity)
|
|
{
|
|
arr->data = value;
|
|
arr->capacity = (uint16_t)(0x8000 | capacity);
|
|
arr->size = count;
|
|
#ifndef DLMS_IGNORE_MALLOC
|
|
arr->position = 0;
|
|
#endif //DLMS_IGNORE_MALLOC
|
|
}
|
|
|
|
|
|
//Allocate new size for the array in bytes.
|
|
int arr_capacity(gxArray* arr, int capacity)
|
|
{
|
|
#ifndef DLMS_IGNORE_MALLOC
|
|
if (!arr_isAttached(arr))
|
|
{
|
|
if (capacity == 0)
|
|
{
|
|
if (arr->data != NULL)
|
|
{
|
|
gxfree(arr->data);
|
|
arr->data = NULL;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (arr->data == NULL)
|
|
{
|
|
arr->data = (void**)gxmalloc(capacity * sizeof(void*));
|
|
if (arr->data == NULL)
|
|
{
|
|
return DLMS_ERROR_CODE_OUTOFMEMORY;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
#ifdef gxrealloc
|
|
void* tmp = (void**)gxrealloc(arr->data, capacity * sizeof(void*));
|
|
//If not enought memory available.
|
|
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(void*));
|
|
//If not enought memory available.
|
|
if (arr->data == NULL)
|
|
{
|
|
arr->data = old;
|
|
return DLMS_ERROR_CODE_OUTOFMEMORY;
|
|
}
|
|
memcpy(arr->data, old, sizeof(void*) * arr->size);
|
|
gxfree(old);
|
|
#endif // gxrealloc
|
|
}
|
|
}
|
|
arr->capacity = (uint16_t)capacity;
|
|
}
|
|
#endif //DLMS_IGNORE_MALLOC
|
|
if (arr_getCapacity(arr) < capacity)
|
|
{
|
|
return DLMS_ERROR_CODE_OUTOFMEMORY;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
#ifndef DLMS_IGNORE_MALLOC
|
|
int arr_push(gxArray* arr, void* item)
|
|
{
|
|
if (arr->size >= arr->capacity)
|
|
{
|
|
int ret = arr_capacity(arr, arr->capacity + GXARRAY_CAPACITY);
|
|
if (ret != 0)
|
|
{
|
|
return ret;
|
|
}
|
|
}
|
|
arr->data[arr->size] = item;
|
|
++arr->size;
|
|
return 0;
|
|
}
|
|
#endif //DLMS_IGNORE_MALLOC
|
|
|
|
void arr_clear(
|
|
gxArray* arr)
|
|
{
|
|
#ifndef DLMS_IGNORE_MALLOC
|
|
int pos;
|
|
if (arr->size != 0)
|
|
{
|
|
for (pos = 0; pos != arr->size; ++pos)
|
|
{
|
|
gxfree(arr->data[pos]);
|
|
}
|
|
}
|
|
if (!arr_isAttached(arr) && arr->capacity != 0)
|
|
{
|
|
gxfree(arr->data);
|
|
arr->data = NULL;
|
|
arr->capacity = 0;
|
|
}
|
|
if (!arr_isAttached(arr))
|
|
{
|
|
arr->size = 0;
|
|
}
|
|
#else
|
|
arr->size = 0;
|
|
#endif //DLMS_IGNORE_MALLOC
|
|
|
|
#ifndef DLMS_IGNORE_MALLOC
|
|
arr->position = 0;
|
|
#endif //DLMS_IGNORE_MALLOC
|
|
}
|
|
|
|
void arr_empty(
|
|
gxArray* arr)
|
|
{
|
|
#ifndef DLMS_IGNORE_MALLOC
|
|
if (arr->size != 0)
|
|
{
|
|
gxfree(arr->data);
|
|
arr->data = NULL;
|
|
}
|
|
arr->capacity = 0;
|
|
if (!arr_isAttached(arr))
|
|
{
|
|
arr->size = 0;
|
|
}
|
|
#else
|
|
arr->size = 0;
|
|
#endif //DLMS_IGNORE_MALLOC
|
|
#ifndef DLMS_IGNORE_MALLOC
|
|
arr->position = 0;
|
|
#endif //DLMS_IGNORE_MALLOC
|
|
}
|
|
|
|
#ifndef DLMS_IGNORE_MALLOC
|
|
int arr_get(gxArray* arr, void** value)
|
|
{
|
|
if (arr->position >= arr->size)
|
|
{
|
|
return DLMS_ERROR_CODE_OUTOFMEMORY;
|
|
}
|
|
*value = arr->data[arr->position];
|
|
++arr->position;
|
|
return 0;
|
|
}
|
|
#endif //DLMS_IGNORE_MALLOC
|
|
|
|
|
|
|
|
#ifndef DLMS_IGNORE_MALLOC
|
|
int arr_getByIndex(gxArray* arr, uint16_t index, void** value)
|
|
{
|
|
if (arr == NULL || value == NULL)
|
|
{
|
|
return DLMS_ERROR_CODE_INVALID_PARAMETER;
|
|
}
|
|
if (index >= arr->size)
|
|
{
|
|
return DLMS_ERROR_CODE_OUTOFMEMORY;
|
|
}
|
|
*value = arr->data[index];
|
|
return 0;
|
|
}
|
|
|
|
int arr_getByIndex3(gxArray* arr, uint16_t index, void** value, unsigned char checkSize)
|
|
{
|
|
if (arr == NULL || value == NULL)
|
|
{
|
|
return DLMS_ERROR_CODE_INVALID_PARAMETER;
|
|
}
|
|
if (index >= arr->size)
|
|
{
|
|
if (checkSize || index >= arr->capacity)
|
|
{
|
|
return DLMS_ERROR_CODE_OUTOFMEMORY;
|
|
}
|
|
}
|
|
*value = arr->data[index];
|
|
return 0;
|
|
}
|
|
#else
|
|
int arr_getByIndex(gxArray* arr, uint16_t index, void** value, uint16_t itemSize)
|
|
{
|
|
if (arr == NULL || value == NULL)
|
|
{
|
|
return DLMS_ERROR_CODE_INVALID_PARAMETER;
|
|
}
|
|
if (index >= arr->size)
|
|
{
|
|
return DLMS_ERROR_CODE_OUTOFMEMORY;
|
|
}
|
|
*value = (void*)((unsigned char*)arr->data + (index * itemSize));
|
|
return 0;
|
|
}
|
|
int arr_getByIndex3(gxArray* arr, uint16_t index, void** value, uint16_t itemSize, unsigned char checkSize)
|
|
{
|
|
if (arr == NULL || value == NULL)
|
|
{
|
|
return DLMS_ERROR_CODE_INVALID_PARAMETER;
|
|
}
|
|
if (index >= arr->size)
|
|
{
|
|
if (checkSize || index >= arr->capacity)
|
|
{
|
|
return DLMS_ERROR_CODE_OUTOFMEMORY;
|
|
}
|
|
}
|
|
*value = (void*)((unsigned char*)arr->data + (index * itemSize));
|
|
return 0;
|
|
}
|
|
#endif //DLMS_IGNORE_MALLOC
|
|
|
|
|
|
int arr_getByIndex2(gxArray* arr, uint16_t index, void** value, uint16_t itemSize)
|
|
{
|
|
#ifndef DLMS_IGNORE_MALLOC
|
|
return arr_getByIndex(arr, index, value);
|
|
#else
|
|
return arr_getByIndex(arr, index, value, itemSize);
|
|
#endif //DLMS_IGNORE_MALLOC
|
|
}
|
|
|
|
int arr_getByIndex4(gxArray* arr, uint16_t index, void** value, uint16_t itemSize, unsigned char checkSize)
|
|
{
|
|
#ifndef DLMS_IGNORE_MALLOC
|
|
return arr_getByIndex3(arr, index, value, checkSize);
|
|
#else
|
|
return arr_getByIndex3(arr, index, value, itemSize, checkSize);
|
|
#endif //DLMS_IGNORE_MALLOC
|
|
}
|
|
|
|
int arr_getByIndexRef(gxArray* arr, uint16_t index, void** value)
|
|
{
|
|
if (arr == NULL || value == NULL)
|
|
{
|
|
return DLMS_ERROR_CODE_INVALID_PARAMETER;
|
|
}
|
|
if (index >= arr->size)
|
|
{
|
|
return DLMS_ERROR_CODE_OUTOFMEMORY;
|
|
}
|
|
*value = (void*)((gxArray**)arr->data)[index];
|
|
return 0;
|
|
}
|
|
|
|
int arr_setByIndexRef(gxArray* arr, void* value)
|
|
{
|
|
if (!(arr->size < arr_getCapacity(arr)))
|
|
{
|
|
return DLMS_ERROR_CODE_OUTOFMEMORY;
|
|
}
|
|
((gxArray**)arr->data)[arr->size] = value;
|
|
++arr->size;
|
|
return 0;
|
|
}
|
|
|
|
|
|
void arr_clearKeyValuePair(gxArray* arr)
|
|
{
|
|
#ifndef DLMS_IGNORE_MALLOC
|
|
gxKey* k;
|
|
int pos;
|
|
if (arr->capacity != 0)
|
|
{
|
|
for (pos = 0; pos != arr->size; ++pos)
|
|
{
|
|
k = (gxKey*)arr->data[pos];
|
|
gxfree(k->key);
|
|
gxfree(k->value);
|
|
gxfree(k);
|
|
}
|
|
gxfree(arr->data);
|
|
arr->data = NULL;
|
|
arr->capacity = 0;
|
|
arr->size = 0;
|
|
arr->position = 0;
|
|
}
|
|
#else
|
|
arr_clear(arr);
|
|
#endif //DLMS_IGNORE_MALLOC
|
|
}
|
|
|
|
void arr_clearStrings(gxArray* arr)
|
|
{
|
|
#ifndef DLMS_IGNORE_MALLOC
|
|
gxByteBuffer* it;
|
|
int pos;
|
|
if (arr->capacity != 0)
|
|
{
|
|
for (pos = 0; pos != arr->size; ++pos)
|
|
{
|
|
it = (gxByteBuffer*)arr->data[pos];
|
|
gxfree(it->data);
|
|
gxfree(it);
|
|
}
|
|
gxfree(arr->data);
|
|
arr->data = NULL;
|
|
arr->capacity = 0;
|
|
arr->size = 0;
|
|
arr->position = 0;
|
|
}
|
|
#else
|
|
arr_clear(arr);
|
|
#endif //DLMS_IGNORE_MALLOC
|
|
}
|
|
|
|
#ifndef DLMS_IGNORE_MALLOC
|
|
int arr_removeByIndex(gxArray* arr, uint16_t index, void** value)
|
|
{
|
|
int pos;
|
|
if (index >= arr->size)
|
|
{
|
|
return DLMS_ERROR_CODE_OUTOFMEMORY;
|
|
}
|
|
if (value != NULL)
|
|
{
|
|
*value = arr->data[index];
|
|
}
|
|
for (pos = index; pos != arr->size; ++pos)
|
|
{
|
|
arr->data[pos] = arr->data[pos + 1];
|
|
}
|
|
--arr->size;
|
|
return 0;
|
|
}
|
|
#else
|
|
int arr_removeByIndex(
|
|
gxArray* arr,
|
|
uint16_t index,
|
|
uint16_t itemSize)
|
|
{
|
|
int ret;
|
|
uint16_t pos;
|
|
void* prev = NULL;
|
|
void* item = NULL;
|
|
if ((ret = arr_getByIndex(arr, index, &prev, itemSize)) == 0)
|
|
{
|
|
for (pos = index + 1; pos < arr->size; ++pos)
|
|
{
|
|
if ((ret = arr_getByIndex(arr, pos, &item, itemSize)) == 0)
|
|
{
|
|
memcpy(prev, item, itemSize);
|
|
prev = item;
|
|
}
|
|
}
|
|
--arr->size;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
#endif //DLMS_IGNORE_MALLOC
|
|
|
|
#ifndef DLMS_IGNORE_MALLOC
|
|
int arr_swap(gxArray* arr, uint16_t index1, uint16_t index2)
|
|
{
|
|
void* tmp;
|
|
if (!(index1 < arr->size || index2 < arr->size))
|
|
{
|
|
return DLMS_ERROR_CODE_OUTOFMEMORY;
|
|
}
|
|
tmp = arr->data[index1];
|
|
arr->data[index1] = arr->data[index2];
|
|
arr->data[index2] = tmp;
|
|
return 0;
|
|
}
|
|
#else
|
|
int arr_swap(
|
|
gxArray* arr,
|
|
uint16_t index1,
|
|
uint16_t index2,
|
|
uint16_t itemSize,
|
|
void* tmp)
|
|
{
|
|
int ret;
|
|
void* prev = NULL;
|
|
void* item = NULL;
|
|
if ((ret = arr_getByIndex(arr, index1, &prev, itemSize)) == 0 &&
|
|
(ret = arr_getByIndex(arr, index2, &item, itemSize)) == 0)
|
|
{
|
|
memcpy(tmp, prev, itemSize);
|
|
memcpy(prev, item, itemSize);
|
|
memcpy(item, tmp, itemSize);
|
|
}
|
|
return 0;
|
|
}
|
|
#endif //DLMS_IGNORE_MALLOC
|