You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
libiec61850/src/mms/asn1/ber_integer.c

239 lines
5.3 KiB
C

/*
* ber_integer.c
*
* Copyright 2013 Michael Zillgith
*
* This file is part of libIEC61850.
*
* libIEC61850 is free 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, either version 3 of the License, or
* (at your option) any later version.
*
* libIEC61850 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.
*
* You should have received a copy of the GNU General Public License
* along with libIEC61850. If not, see <http://www.gnu.org/licenses/>.
*
* See COPYING file for the complete license text.
*/
#include "libiec61850_platform_includes.h"
#include "ber_integer.h"
#include "ber_encoder.h"
static int
setIntegerValue(Asn1PrimitiveValue* self, uint8_t* valueBuffer, int bufferSize)
{
#if (ORDER_LITTLE_ENDIAN == 1)
BerEncoder_revertByteOrder(valueBuffer, bufferSize);
#endif
int size = BerEncoder_compressInteger(valueBuffer, bufferSize);
if (size <= self->maxSize) {
self->size = size;
memcpy(self->octets, valueBuffer, size);
return 1;
}
else
return 0;
}
Asn1PrimitiveValue*
BerInteger_createInt32()
{
return Asn1PrimitiveValue_create(5);
}
Asn1PrimitiveValue*
BerInteger_createFromBuffer(uint8_t* buf, int size)
{
int maxSize;
if (size > 8)
maxSize = size;
else
maxSize = 8;
Asn1PrimitiveValue* self = Asn1PrimitiveValue_create(maxSize);
memcpy(self->octets, buf, size);
self->size = size;
return self;
}
int
BerInteger_setFromBerInteger(Asn1PrimitiveValue* self, Asn1PrimitiveValue* value)
{
if (self->maxSize >= value->size) {
self->size = value->size;
memcpy(self->octets, value->octets, value->size);
return 1;
}
else
return 0;
}
int
BerInteger_setInt32(Asn1PrimitiveValue* self, int32_t value)
{
int32_t valueCopy = value;
uint8_t* valueBuffer = (uint8_t*) &valueCopy;
return setIntegerValue(self, valueBuffer, sizeof(value));
}
Asn1PrimitiveValue*
BerInteger_createFromInt32(int32_t value)
{
Asn1PrimitiveValue* asn1Value = BerInteger_createInt32();
BerInteger_setInt32(asn1Value, value);
return asn1Value;
}
int
BerInteger_setUint16(Asn1PrimitiveValue* self, uint16_t value)
{
uint16_t valueCopy = value;
uint8_t* valueBuffer = (uint8_t*) &valueCopy;
return setIntegerValue(self, valueBuffer, sizeof(value));
}
int
BerInteger_setUint8(Asn1PrimitiveValue* self, uint8_t value)
{
uint8_t valueCopy = value;
uint8_t* valueBuffer = (uint8_t*) &valueCopy;
return setIntegerValue(self, valueBuffer, sizeof(value));
}
int
BerInteger_setUint32(Asn1PrimitiveValue* self, uint32_t value)
{
uint32_t valueCopy = value;
uint8_t* valueBuffer = (uint8_t*) &valueCopy;
uint8_t byteBuffer[5];
int i;
#if (ORDER_LITTLE_ENDIAN == 1)
byteBuffer[4] = 0;
for (i = 0; i < 4; i++)
byteBuffer[i] = valueBuffer[i];
#else
bytebuffer[0] = 0;
for (i = 0; i < 4; i++)
byteBuffer[i + 1] = valueBuffer[i];
#endif /* (ORDER_LITTLE_ENDIAN == 1) */
return setIntegerValue(self, byteBuffer, 5);
}
Asn1PrimitiveValue*
BerInteger_createFromUint32(uint32_t value)
{
Asn1PrimitiveValue* asn1Value = BerInteger_createInt32();
BerInteger_setUint32(asn1Value, value);
return asn1Value;
}
Asn1PrimitiveValue*
BerInteger_createInt64()
{
return Asn1PrimitiveValue_create(9);
}
int
BerInteger_setInt64(Asn1PrimitiveValue* self, int64_t value)
{
int64_t valueCopy = value;
uint8_t* valueBuffer = (uint8_t*) &valueCopy;
return setIntegerValue(self, valueBuffer, sizeof(value));
}
Asn1PrimitiveValue*
BerInteger_createFromInt64(int64_t value)
{
Asn1PrimitiveValue* asn1Value = BerInteger_createInt64();
BerInteger_setInt64(asn1Value, value);
return asn1Value;
}
int /* 1 - if conversion is possible, 0 - out of range */
BerInteger_toInt32(Asn1PrimitiveValue* self, int32_t* nativeValue)
{
if (self->size < 5) {
uint8_t* buf = self->octets;
int i;
if (buf[0] & 0x80) /* sign extension */
*nativeValue = 0xffffffff;
else
*nativeValue = 0;
for (i = 0; i < self->size; i++)
*nativeValue = (*nativeValue << 8) | buf[i];
return 1;
}
else
return 0;
}
int /* 1 - if conversion is possible, 0 - out of range */
BerInteger_toUint32(Asn1PrimitiveValue* self, uint32_t* nativeValue)
{
if (self->size < 6) {
uint8_t* buf = self->octets;
int i;
*nativeValue = 0;
for (i = 0; i < self->size; i++)
*nativeValue = (*nativeValue << 8) | buf[i];
return 1;
}
else
return 0;
}
int /* 1 - if conversion is possible, 0 - out of range */
BerInteger_toInt64(Asn1PrimitiveValue* self, int64_t* nativeValue)
{
if (self->size < 9) {
uint8_t* buf = self->octets;
int i;
if (buf[0] & 0x80) /* sign extension */
*nativeValue = 0xffffffffffffffff;
else
*nativeValue = 0;
for (i = 0; i < self->size; i++)
*nativeValue = (*nativeValue << 8) | buf[i];
return 1;
}
else
return 0;
}