/* * ber_decoder.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 . * * See COPYING file for the complete license text. */ #include "libiec61850_platform_includes.h" #include "ber_decode.h" int BerDecoder_decodeLength(uint8_t* buffer, int* length, int bufPos, int maxBufPos) { if (bufPos >= maxBufPos) return -1; uint8_t len1 = buffer[bufPos++]; if (len1 & 0x80) { int lenLength = len1 & 0x7f; if (lenLength == 0) { /* indefinite length form */ *length = -1; } else { *length = 0; int i; for (i = 0; i < lenLength; i++) { if (bufPos >= maxBufPos) return -1; *length <<= 8; *length += buffer[bufPos++]; } } } else { *length = len1; } if (*length < 0) return -1; if (bufPos + (*length) > maxBufPos) return -1; return bufPos; } char* BerDecoder_decodeString(uint8_t* buffer, int strlen, int bufPos, int maxBufPos) { char* string = (char*) GLOBAL_MALLOC(strlen + 1); memcpy(string, buffer + bufPos, strlen); string[strlen] = 0; return string; } uint32_t BerDecoder_decodeUint32(uint8_t* buffer, int intLen, int bufPos) { uint32_t value = 0; int i; for (i = 0; i < intLen; i++) { value <<= 8; value += buffer[bufPos + i]; } return value; } #if 0 int32_t BerDecoder_decodeInt32(uint8_t* buffer, int intlen, int bufPos) { int32_t value = 0; bool isNegative = ((buffer[bufPos] & 0x80) == 0x80); int i = 0; if (isNegative) { for (i = 0; i < 4; i++) { value <<= 8; if (i < (4 - intlen)) value += 0xff; else value += buffer[bufPos + i - (4 - intlen)]; } } else { for (i = 0; i < intlen; i++) { value <<= 8; value += buffer[bufPos + i]; } } return value; } #endif #if 1 int32_t BerDecoder_decodeInt32(uint8_t* buffer, int intlen, int bufPos) { int32_t value; int i; bool isNegative = ((buffer[bufPos] & 0x80) == 0x80); if (isNegative) value = -1; else value = 0; for (i = 0; i < intlen; i++) { value <<= 8; value += buffer[bufPos + i]; } return value; } #endif float BerDecoder_decodeFloat(uint8_t* buffer, int bufPos) { float value; uint8_t* valueBuf = (uint8_t*) &value; int i; bufPos += 1; /* skip exponentWidth field */ #if (ORDER_LITTLE_ENDIAN == 1) for (i = 3; i >= 0; i--) { valueBuf[i] = buffer[bufPos++]; } #else for (i = 0; i < 4; i++) { valueBuf[i] = buffer[bufPos++]; } #endif return value; } double BerDecoder_decodeDouble(uint8_t* buffer, int bufPos) { double value; uint8_t* valueBuf = (uint8_t*) &value; int i; bufPos += 1; /* skip exponentWidth field */ #if (ORDER_LITTLE_ENDIAN == 1) for (i = 7; i >= 0; i--) { valueBuf[i] = buffer[bufPos++]; } #else for (i = 0; i < 8; i++) { valueBuf[i] = buffer[bufPos++]; } #endif return value; } bool BerDecoder_decodeBoolean(uint8_t* buffer, int bufPos) { if (buffer[bufPos] != 0) return true; else return false; }