/* * Copyright (C) 2007-2018 Siemens AG * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published * by the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ /******************************************************************* * * @author Daniel.Peintner.EXT@siemens.com * @version 2017-03-02 * @contact Richard.Kuntschke@siemens.com * *

Code generated by EXIdizer

*

Schema: V2G_CI_MsgDef.xsd

* * ********************************************************************/ #include "DecoderChannel.h" #include "EXIConfig.h" #include "EXIOptions.h" #include "BitInputStream.h" #include "EXITypes.h" #include "MethodsBag.h" /*#include "v2gEXICoder.h"*/ #include "ErrorCodes.h" #if MEMORY_ALLOCATION == DYNAMIC_ALLOCATION #include "DynamicMemory.h" #endif /* DYNAMIC_ALLOCATION */ #ifndef DECODER_CHANNEL_C #define DECODER_CHANNEL_C /* unsigned long == 64 bits, 10 * 7bits = 70 bits */ #define MAX_OCTETS_FOR_UNSIGNED_INTEGER_64 10 /* unsigned int == 32 bits, 5 * 7bits = 35 bits */ #define MAX_OCTETS_FOR_UNSIGNED_INTEGER_32 5 /* buffer for reading (arbitrary) large integer values */ static uint8_t maskedOctets[MAX_OCTETS_FOR_UNSIGNED_INTEGER_64]; static int _decodeUnsignedInteger(bitstream_t* stream, exi_integer_t* iv, int negative) { int errn = 0; int i = 0; uint8_t b; int k; do { /* Read the next octet */ errn = decode(stream, &b); if (errn == 0) { if(i < MAX_OCTETS_FOR_UNSIGNED_INTEGER_64) { /* the 7 least significant bits hold the actual value */ maskedOctets[i++] = (b & 127); } else { errn = EXI_UNSUPPORTED_INTEGER_VALUE; } } } while( errn == 0 && b >= 128 ); /* no more octets ? */ if ( errn == 0 ) { /* For negative values, the Unsigned Integer holds the * magnitude of the value minus 1 */ switch(i) { case 1: /* 7 bits */ if (negative) { iv->val.int8 = (int8_t)(-( b + 1)); iv->type = EXI_INTEGER_8; } else { iv->val.uint8 = b; iv->type = EXI_UNSIGNED_INTEGER_8; } break; case 2: /* 14 bits */ iv->val.uint16 = 0; for (k = i-1; k >= 0 ; k--) { iv->val.uint16 = (uint16_t)((iv->val.uint16 << 7) | maskedOctets[k]); } if (negative) { iv->val.int16 = (int16_t)( -( iv->val.uint16 + 1 )); iv->type = EXI_INTEGER_16; } else { iv->type = EXI_UNSIGNED_INTEGER_16; } break; case 3: /* 21 bits */ case 4: /* 28 bits */ iv->val.uint32 = 0; for (k = i-1; k >= 0 ; k--) { iv->val.uint32 = (iv->val.uint32 << 7) | maskedOctets[k]; } if (negative) { iv->val.int32 = (-(int32_t)(iv->val.uint32 + 1)); if (iv->val.int32 <= INT16_MAX && iv->val.int32 >= INT16_MIN ) { iv->type = EXI_INTEGER_16; } else { iv->type = EXI_INTEGER_32; } } else { if (iv->val.uint32 <= UINT16_MAX) { iv->type = EXI_UNSIGNED_INTEGER_16; } else { iv->type = EXI_UNSIGNED_INTEGER_32; } } break; case 5: /* 35 bits */ case 6: /* 42 bits */ case 7: /* 49 bits */ case 8: /* 56 bits */ case 9: /* 63 bits */ case 10: /* 70 bits */ iv->val.uint64 = 0; for (k = i-1; k >= 0 ; k--) { iv->val.uint64 = (iv->val.uint64 << 7) | maskedOctets[k]; } if (negative) { if (i > 9) { /* too large */ return EXI_UNSUPPORTED_INTEGER_VALUE; } iv->val.int64 = (-(int64_t)(iv->val.uint64 + 1)); if (iv->val.int64 <= INT32_MAX && iv->val.int64 >= INT32_MIN ) { iv->type = EXI_INTEGER_32; } else { iv->type = EXI_INTEGER_64; } } else { if (iv->val.uint64 <= UINT32_MAX) { iv->type = EXI_UNSIGNED_INTEGER_32; /* iv->val.uint32 = iv->val.uint64;*/ } else { iv->type = EXI_UNSIGNED_INTEGER_64; } } break; default: errn = EXI_UNSUPPORTED_INTEGER_VALUE; break; } } return errn; } int decodeUnsignedInteger(bitstream_t* stream, exi_integer_t* iv) { return _decodeUnsignedInteger(stream, iv, 0); } int decodeUnsignedInteger16(bitstream_t* stream, uint16_t* uint16) { unsigned int mShift = 0; int errn = 0; uint8_t b = 0; *uint16 = 0; do { /* 1. Read the next octet */ errn = decode(stream, &b); /* 2. Multiply the value of the unsigned number represented by the 7 * least significant * bits of the octet by the current multiplier and add the result to * the current value */ *uint16 = (uint16_t)(*uint16 + ((b & 127) << mShift)); /* 3. Multiply the multiplier by 128 */ mShift += 7; /* 4. If the most significant bit of the octet was 1, go back to step 1 */ } while (errn == 0 && (b >> 7) == 1); return errn; } int decodeUnsignedInteger32(bitstream_t* stream, uint32_t* uint32) { /* 0XXXXXXX ... 1XXXXXXX 1XXXXXXX */ unsigned int mShift = 0; int errn = 0; uint8_t b = 0; *uint32 = 0; do { /* 1. Read the next octet */ errn = decode(stream, &b); /* 2. Multiply the value of the unsigned number represented by the 7 * least significant * bits of the octet by the current multiplier and add the result to * the current value */ *uint32 += (uint32_t)((b & 127) << mShift); /* 3. Multiply the multiplier by 128 */ mShift += 7; /* 4. If the most significant bit of the octet was 1, go back to step 1 */ } while (errn == 0 && (b >> 7) == 1); return errn; } int decodeUnsignedIntegerSizeT(bitstream_t* stream, size_t* sizeT) { int errn = 0; /* TODO is there a better way to detect the actual size of size_t */ if(SIZE_MAX == UINT16_MAX) { /* 16bit */ uint16_t uint16; errn = decodeUnsignedInteger16(stream, &uint16); if(errn == 0) { *sizeT = (size_t)uint16; } } else if(SIZE_MAX == UINT32_MAX) { /* 32bit */ uint32_t uint32; errn = decodeUnsignedInteger32(stream, &uint32); if(errn == 0) { *sizeT = (size_t)uint32; } } else { /* 64bit */ uint64_t uint64; errn = decodeUnsignedInteger64(stream, &uint64); if(errn == 0) { *sizeT = (size_t)uint64; } } return errn; } /** * Decode an arbitrary precision non negative integer using a sequence of * octets. The most significant bit of the last octet is set to zero to * indicate sequence termination. Only seven bits per octet are used to * store the integer's value. */ int decodeUnsignedInteger64(bitstream_t* stream, uint64_t* uint64) { unsigned int mShift = 0; int errn = 0; uint8_t b; *uint64 = 0L; do { errn = decode(stream, &b); *uint64 += ((uint64_t) (b & 127)) << mShift; mShift += 7; } while (errn == 0 && (b >> 7) == 1); return errn; } void _reverseArray(uint8_t *array, int number) { int x, t; number--; for(x = 0; x < number; x ++, number --) { t = array[x]; array[x] = array[number]; array[number] = t; } } /** * Decode an arbitrary precision non negative integer using a sequence of * octets. The most significant bit of the last octet is set to zero to * indicate sequence termination. Only seven bits per octet are used to * store the integer's value. */ int decodeUnsignedIntegerBig(bitstream_t* stream, size_t size, uint8_t* data, size_t* len) { int errn = 0; uint8_t b = 0; unsigned int mShift1 = 0; unsigned int mShift2 = 0; unsigned int mShift3 = 0; unsigned int mShift4 = 0; unsigned int nBytesRead = 0; unsigned int nBitsAvailable = 0; uint64_t uint64_1 = 0; uint64_t uint64_2 = 0; uint64_t uint64_3 = 0; uint64_t uint64_4 = 0; *len = 0; do { errn = decode(stream, &b); nBytesRead++; nBitsAvailable += 7; if(nBytesRead <= 8) { uint64_1 += ((uint64_t) (b & 127)) << mShift1; mShift1 += 7; } else if(nBytesRead <= 16) { uint64_2 += ((uint64_t) (b & 127)) << mShift2; mShift2 += 7; } else if(nBytesRead <= 24) { uint64_3 += ((uint64_t) (b & 127)) << mShift3; mShift3 += 7; } else if(nBytesRead <= 32) { uint64_4 += ((uint64_t) (b & 127)) << mShift4; mShift4 += 7; } else { return -1; // too large } } while (errn == 0 && (b >> 7) == 1); // shift actual data into array if(uint64_4 != 0) { // 7 octets for uint64_1 data[(*len)++] = (uint8_t)(uint64_1 & 0xFF); // 1 uint64_1 >>= 8; data[(*len)++] = (uint8_t)(uint64_1 & 0xFF); // 2 uint64_1 >>= 8; data[(*len)++] = (uint8_t)(uint64_1 & 0xFF); // 3 uint64_1 >>= 8; data[(*len)++] = (uint8_t)(uint64_1 & 0xFF); // 4 uint64_1 >>= 8; data[(*len)++] = (uint8_t)(uint64_1 & 0xFF); // 5 uint64_1 >>= 8; data[(*len)++] = (uint8_t)(uint64_1 & 0xFF); // 6 uint64_1 >>= 8; data[(*len)++] = (uint8_t)(uint64_1 & 0xFF); // 7 // 7 octets for uint64_2 data[(*len)++] = (uint8_t)(uint64_2 & 0xFF); // 1 uint64_2 >>= 8; data[(*len)++] = (uint8_t)(uint64_2 & 0xFF); // 2 uint64_2 >>= 8; data[(*len)++] = (uint8_t)(uint64_2 & 0xFF); // 3 uint64_2 >>= 8; data[(*len)++] = (uint8_t)(uint64_2 & 0xFF); // 4 uint64_2 >>= 8; data[(*len)++] = (uint8_t)(uint64_2 & 0xFF); // 5 uint64_2 >>= 8; data[(*len)++] = (uint8_t)(uint64_2 & 0xFF); // 6 uint64_2 >>= 8; data[(*len)++] = (uint8_t)(uint64_2 & 0xFF); // 7 // 7 octets for uint64_3 data[(*len)++] = (uint8_t)(uint64_3 & 0xFF); // 1 uint64_3 >>= 8; data[(*len)++] = (uint8_t)(uint64_3 & 0xFF); // 2 uint64_3 >>= 8; data[(*len)++] = (uint8_t)(uint64_3 & 0xFF); // 3 uint64_3 >>= 8; data[(*len)++] = (uint8_t)(uint64_3 & 0xFF); // 4 uint64_3 >>= 8; data[(*len)++] = (uint8_t)(uint64_3 & 0xFF); // 5 uint64_3 >>= 8; data[(*len)++] = (uint8_t)(uint64_3 & 0xFF); // 6 uint64_3 >>= 8; data[(*len)++] = (uint8_t)(uint64_3 & 0xFF); // 7 // remaining octets of uint64_4 while (uint64_4 != 0 && errn == 0) { data[(*len)++] = uint64_4 & 0xFF; uint64_4 >>= 8; } } else if(uint64_3 != 0) { // 7 octets for uint64_1 data[(*len)++] = (uint8_t)(uint64_1 & 0xFF); // 1 uint64_1 >>= 8; data[(*len)++] = (uint8_t)(uint64_1 & 0xFF); // 2 uint64_1 >>= 8; data[(*len)++] = (uint8_t)(uint64_1 & 0xFF); // 3 uint64_1 >>= 8; data[(*len)++] = (uint8_t)(uint64_1 & 0xFF); // 4 uint64_1 >>= 8; data[(*len)++] = (uint8_t)(uint64_1 & 0xFF); // 5 uint64_1 >>= 8; data[(*len)++] = (uint8_t)(uint64_1 & 0xFF); // 6 uint64_1 >>= 8; data[(*len)++] = (uint8_t)(uint64_1 & 0xFF); // 7 // 7 octets for uint64_2 data[(*len)++] = (uint8_t)(uint64_2 & 0xFF); // 1 uint64_2 >>= 8; data[(*len)++] = (uint8_t)(uint64_2 & 0xFF); // 2 uint64_2 >>= 8; data[(*len)++] = (uint8_t)(uint64_2 & 0xFF); // 3 uint64_2 >>= 8; data[(*len)++] = (uint8_t)(uint64_2 & 0xFF); // 4 uint64_2 >>= 8; data[(*len)++] = (uint8_t)(uint64_2 & 0xFF); // 5 uint64_2 >>= 8; data[(*len)++] = (uint8_t)(uint64_2 & 0xFF); // 6 uint64_2 >>= 8; data[(*len)++] = (uint8_t)(uint64_2 & 0xFF); // 7 // remaining octets of uint64_3 while (uint64_3 != 0 && errn == 0) { data[(*len)++] = uint64_3 & 0xFF; uint64_3 >>= 8; } } else if(uint64_2 != 0) { // 7 octets for uint64_1 data[(*len)++] = (uint8_t)(uint64_1 & 0xFF); // 1 uint64_1 >>= 8; data[(*len)++] = (uint8_t)(uint64_1 & 0xFF); // 2 uint64_1 >>= 8; data[(*len)++] = (uint8_t)(uint64_1 & 0xFF); // 3 uint64_1 >>= 8; data[(*len)++] = (uint8_t)(uint64_1 & 0xFF); // 4 uint64_1 >>= 8; data[(*len)++] = (uint8_t)(uint64_1 & 0xFF); // 5 uint64_1 >>= 8; data[(*len)++] = (uint8_t)(uint64_1 & 0xFF); // 6 uint64_1 >>= 8; data[(*len)++] = (uint8_t)(uint64_1 & 0xFF); // 7 // remaining octets of uint64_2 while (uint64_2 != 0 && errn == 0) { data[(*len)++] = uint64_2 & 0xFF; uint64_2 >>= 8; } } else if(uint64_1 != 0) { while (uint64_1 != 0 && errn == 0) { data[(*len)++] = uint64_1 & 0xFF; uint64_1 >>= 8; } } _reverseArray(data, *len); return errn; } int decodeInteger(bitstream_t* stream, exi_integer_t* iv) { int b; int errn = decodeBoolean(stream, &b); if (errn == 0) { errn = _decodeUnsignedInteger(stream, iv, b); } return errn; } /** * Decode an arbitrary precision integer using a sign bit followed by a * sequence of octets. The most significant bit of the last octet is set to * zero to indicate sequence termination. Only seven bits per octet are used * to store the integer's value. */ int decodeInteger16(bitstream_t* stream, int16_t* int16) { int b; uint16_t uint16; int errn = decodeBoolean(stream, &b); if (errn == 0) { if (b) { /* For negative values, the Unsigned Integer holds the * magnitude of the value minus 1 */ errn = decodeUnsignedInteger16(stream, &uint16); *int16 = (int16_t)(-(uint16 + 1)); } else { /* positive */ errn = decodeUnsignedInteger16(stream, &uint16); *int16 = (int16_t)(uint16); } } return errn; } /** * Decode an arbitrary precision integer using a sign bit followed by a * sequence of octets. The most significant bit of the last octet is set to * zero to indicate sequence termination. Only seven bits per octet are used * to store the integer's value. */ int decodeInteger32(bitstream_t* stream, int32_t* int32) { int b; uint32_t uint32; int errn = decodeBoolean(stream, &b); if (errn == 0) { if (b) { /* For negative values, the Unsigned Integer holds the * magnitude of the value minus 1 */ errn = decodeUnsignedInteger32(stream, &uint32); *int32 = (-(int32_t)(uint32 + 1)); } else { /* positive */ errn = decodeUnsignedInteger32(stream, &uint32); *int32 = (int32_t)(uint32); } } return errn; } /** * Decode an arbitrary precision integer using a sign bit followed by a * sequence of octets. The most significant bit of the last octet is set to * zero to indicate sequence termination. Only seven bits per octet are used * to store the integer's value. */ int decodeInteger64(bitstream_t* stream, int64_t* int64) { int b; uint64_t uint64; int errn = decodeBoolean(stream, &b); if (errn == 0) { if (b) { /* For negative values, the Unsigned Integer holds the * magnitude of the value minus 1 */ errn = decodeUnsignedInteger64(stream, &uint64); *int64 = (-(int64_t)(uint64 + 1)); } else { /* positive */ errn = decodeUnsignedInteger64(stream, &uint64); *int64 = (int64_t)(uint64); } } return errn; } /** * Decode an arbitrary precision integer using a sign bit followed by a * sequence of octets. The most significant bit of the last octet is set to * zero to indicate sequence termination. Only seven bits per octet are used * to store the integer's value. */ int decodeIntegerBig(bitstream_t* stream, int* negative, size_t size, uint8_t* data, size_t* len) { int errn = decodeBoolean(stream, negative); if (errn == 0) { if (*negative) { /* For negative values, the Unsigned Integer holds the * magnitude of the value minus 1 */ } else { /* positive */ } errn = decodeUnsignedIntegerBig(stream, size, data, len); } return errn; } /** * Decode a Float datatype as two consecutive Integers. * The first Integer represents the mantissa of the floating point * number and the second Integer represents the base-10 exponent * of the floating point number. */ int decodeFloat(bitstream_t* stream, exi_float_me_t* f) { int errn = decodeInteger64(stream, &f->mantissa); if (errn == 0) { errn = decodeInteger16(stream, &f->exponent); } return errn; } /** * Decode a decimal represented as a Boolean sign followed by two Unsigned * Integers. A sign value of zero (0) is used to represent positive Decimal * values and a sign value of one (1) is used to represent negative Decimal * values The first Integer represents the integral portion of the Decimal * value. The second positive integer represents the fractional portion of * the decimal with the digits in reverse order to preserve leading zeros. */ int decodeDecimal(bitstream_t* stream, exi_decimal_t* d) { int errn = decodeBoolean(stream, &d->negative); if (errn == 0) { errn = decodeUnsignedInteger(stream, &d->integral); if (errn == 0) { errn = decodeUnsignedInteger(stream, &d->reverseFraction); } } return errn; } /** * Decode a sequence of characters for a given length. */ int decodeStringOnly(bitstream_t* stream, size_t len, exi_string_t* s) { int errn = 0; unsigned int extraChar = 0; #if STRING_REPRESENTATION == STRING_REPRESENTATION_ASCII extraChar = 1; /* null terminator */ #endif /* STRING_REPRESENTATION_ASCII */ if ( (len + extraChar) > s->size) { #if MEMORY_ALLOCATION == STATIC_ALLOCATION errn = EXI_ERROR_OUT_OF_STRING_BUFFER; #endif /* STATIC_ALLOCATION */ #if MEMORY_ALLOCATION == DYNAMIC_ALLOCATION if(s->size > 0) { errn = exiFreeDynamicStringMemory(s); if(errn) { return errn; } } errn = exiAllocateDynamicStringMemory(s, (len + extraChar)); /*s->len*/ #endif /* DYNAMIC_ALLOCATION */ } if(errn == 0) { errn = decodeCharacters(stream, len, s->characters, s->size); s->len = len; } return errn; } /** * Decode a length prefixed sequence of characters. */ int decodeString(bitstream_t* stream, exi_string_t* s) { int errn = decodeUnsignedIntegerSizeT(stream, &s->len); if (errn == 0) { errn = decodeStringOnly(stream, s->len, s); } return errn; } /** * Decode a sequence of characters according to a given length. * Each character is represented by its UCS [ISO/IEC 10646] * code point encoded as an Unsigned Integer */ int decodeCharacters(bitstream_t* stream, size_t len, exi_string_character_t* chars, size_t charsSize) { unsigned int i; int errn = 0; unsigned int extraChar = 0; #if STRING_REPRESENTATION == STRING_REPRESENTATION_ASCII extraChar = 1; /* null terminator */ #endif /* STRING_REPRESENTATION_ASCII */ if ( (len + extraChar) > charsSize) { errn = EXI_ERROR_OUT_OF_STRING_BUFFER; return errn; } #if STRING_REPRESENTATION == STRING_REPRESENTATION_ASCII uint8_t b; for (i = 0; i < len && errn == 0; i++) { errn = decode(stream, &b); if(b < 128) { chars[i] = (exi_string_character_t)b; } else { errn = EXI_ERROR_STRINGVALUES_CHARACTER; } } /* null terminator \0 */ chars[i] = '\0'; #endif /* STRING_REPRESENTATION_ASCII */ #if STRING_REPRESENTATION == STRING_REPRESENTATION_UCS for (i = 0; i < len && errn == 0; i++) { errn = decodeUnsignedInteger32(stream, &chars[i]); } #endif /* STRING_REPRESENTATION_UCS */ return errn; } int decodeRCSCharacters(bitstream_t* stream, size_t len, exi_string_character_t* chars, size_t charsSize, size_t rcsCodeLength, size_t rcsSize, const exi_string_character_t rcsSet[]) { unsigned int i; int errn = 0; uint32_t uint32; unsigned int extraChar = 0; #if STRING_REPRESENTATION == STRING_REPRESENTATION_ASCII uint8_t b; extraChar = 1; /* null terminator */ #endif /* STRING_REPRESENTATION_ASCII */ if ( (len + extraChar) > charsSize) { errn = EXI_ERROR_OUT_OF_STRING_BUFFER; return errn; } for (i = 0; i < len && errn == 0; i++) { errn = decodeNBitUnsignedInteger(stream, rcsCodeLength, &uint32); if(errn == 0) { if ( uint32 == rcsSize ) { /* RCS deviation */ #if STRING_REPRESENTATION == STRING_REPRESENTATION_ASCII errn = decode(stream, &b); if(b < 128) { chars[i] = (exi_string_character_t)b; } else { errn = EXI_ERROR_STRINGVALUES_CHARACTER; } #endif /* STRING_REPRESENTATION_ASCII */ #if STRING_REPRESENTATION == STRING_REPRESENTATION_UCS errn = decodeUnsignedInteger32(stream, &chars[i]); #endif /* STRING_REPRESENTATION_UCS */ } else { /* RCS match */ #if STRING_REPRESENTATION == STRING_REPRESENTATION_ASCII chars[i] = rcsSet[uint32]; #endif /* STRING_REPRESENTATION_ASCII */ #if STRING_REPRESENTATION == STRING_REPRESENTATION_UCS chars[i] = rcsSet[uint32]; #endif /* STRING_REPRESENTATION_UCS */ } } } return errn; } /** * Decode a binary value as a length-prefixed sequence of octets. */ int decodeBinary(bitstream_t* stream, exi_bytes_t* bytes) { int errn = decodeUnsignedIntegerSizeT(stream, &bytes->len); if (errn == 0) { if (bytes->len > bytes->size) { #if MEMORY_ALLOCATION == STATIC_ALLOCATION errn = EXI_ERROR_OUT_OF_BYTE_BUFFER; #endif /* STATIC_ALLOCATION */ #if MEMORY_ALLOCATION == DYNAMIC_ALLOCATION errn = exiFreeDynamicBinaryMemory(bytes); if(errn == 0) { errn = exiAllocateDynamicBinaryMemory(bytes, bytes->len); } #endif /* DYNAMIC_ALLOCATION */ } errn = decodeBytes(stream, bytes->len, bytes->data); } return errn; } int decodeBytes(bitstream_t* stream, size_t len, uint8_t* data) { unsigned int i; int errn = 0; uint8_t b = 0; for (i = 0; i < len && errn == 0; i++) { errn = decode(stream, &b); data[i] = (uint8_t)b; } return errn; } /** * Decode Date-Time as sequence of values representing the individual * components of the Date-Time. */ int decodeDateTime(bitstream_t* stream, exi_datetime_type_t type, exi_datetime_t* datetime) { int errn = 0; datetime->type = type; datetime->year = 0; datetime->monthDay = 0; datetime->time = 0; datetime->presenceFractionalSecs = 0; datetime->fractionalSecs = 0; datetime->presenceTimezone = 0; datetime->timezone = 0; switch (type) { case EXI_DATETIME_GYEAR: /* Year, [Time-Zone] */ errn = decodeInteger32(stream, &datetime->year); if (errn == 0) { datetime->year += DATETIME_YEAR_OFFSET; } break; case EXI_DATETIME_GYEARMONTH: /* Year, MonthDay, [TimeZone] */ case EXI_DATETIME_DATE: errn = decodeInteger32(stream, &datetime->year); if (errn == 0) { datetime->year += DATETIME_YEAR_OFFSET; errn = decodeNBitUnsignedInteger(stream, DATETIME_NUMBER_BITS_MONTHDAY, &datetime->monthDay); } break; case EXI_DATETIME_DATETIME: /* Year, MonthDay, Time, [FractionalSecs], [TimeZone] */ /* e.g. "0001-01-01T00:00:00.111+00:33" */ errn = decodeInteger32(stream, &datetime->year); if (errn == 0) { datetime->year += DATETIME_YEAR_OFFSET; errn = decodeNBitUnsignedInteger(stream, DATETIME_NUMBER_BITS_MONTHDAY, &datetime->monthDay); if (errn != 0) { break; } } /* no break */ case EXI_DATETIME_TIME: /* Time, [FractionalSecs], [TimeZone] */ /* e.g. "12:34:56.135" */ errn = decodeNBitUnsignedInteger(stream, DATETIME_NUMBER_BITS_TIME, &datetime->time); if (errn == 0) { errn = decodeBoolean(stream, &datetime->presenceFractionalSecs); if (errn == 0) { if (datetime->presenceFractionalSecs) { errn = decodeUnsignedInteger32(stream, &datetime->fractionalSecs); } } } break; case EXI_DATETIME_GMONTH: /* MonthDay, [TimeZone] */ /* e.g. "--12" */ case EXI_DATETIME_GMONTHDAY: /* MonthDay, [TimeZone] */ /* e.g. "--01-28" */ case EXI_DATETIME_GDAY: /* MonthDay, [TimeZone] */ /* "---16" */ errn = decodeNBitUnsignedInteger(stream, DATETIME_NUMBER_BITS_MONTHDAY, &datetime->monthDay ); break; default: errn = EXI_UNSUPPORTED_DATETIME_TYPE; break; } if(errn == 0) { errn = decodeBoolean(stream, &datetime->presenceTimezone ); if (errn == 0 && datetime->presenceTimezone) { errn = decodeNBitUnsignedInteger(stream, DATETIME_NUMBER_BITS_TIMEZONE, &datetime->timezone); datetime->timezone -= DATETIME_TIMEZONE_OFFSET_IN_MINUTES; } } return errn; } int decode(bitstream_t* stream, uint8_t* b) { #if EXI_OPTION_ALIGNMENT == BIT_PACKED uint32_t bb; int errn = readBits(stream, 8, &bb); if (errn == 0) { if (bb > 256) { errn = EXI_ERROR_UNEXPECTED_BYTE_VALUE; } else { *b = (uint8_t)bb; } } return errn; #endif /* EXI_OPTION_ALIGNMENT == BIT_PACKED */ #if EXI_OPTION_ALIGNMENT == BYTE_ALIGNMENT int errn = 0; #if EXI_STREAM == BYTE_ARRAY if ( (*stream->pos) < stream->size ) { *b = stream->data[(*stream->pos)++]; } else { errn = EXI_ERROR_INPUT_STREAM_EOF; } #endif /* EXI_STREAM == BYTE_ARRAY */ #if EXI_STREAM == FILE_STREAM *b = (uint8_t)(getc(stream->file)); /* EOF cannot be used, 0xFF valid value */ if ( feof(stream->file) || ferror(stream->file) ) { errn = EXI_ERROR_INPUT_STREAM_EOF; } #endif /* EXI_STREAM == FILE_STREAM */ return errn; #endif /* EXI_OPTION_ALIGNMENT == BYTE_ALIGNMENT */ } int decodeBoolean(bitstream_t* stream, int* b) { #if EXI_OPTION_ALIGNMENT == BIT_PACKED uint32_t ub; int errn = readBits(stream, 1, &ub); *b = (ub == 0) ? 0 : 1; return errn; #endif /* EXI_OPTION_ALIGNMENT == BIT_PACKED */ #if EXI_OPTION_ALIGNMENT == BYTE_ALIGNMENT uint8_t bb; int errn = decode(stream, &bb); *b = (bb == 0) ? 0 : 1; return errn; #endif /* EXI_OPTION_ALIGNMENT == BYTE_ALIGNMENT */ } /** * Decodes and returns an n-bit unsigned integer using the minimum number of * bytes required for n bits. */ int decodeNBitUnsignedInteger(bitstream_t* stream, size_t nbits, uint32_t* uint32) { #if EXI_OPTION_ALIGNMENT == BIT_PACKED int errn = 0; if (nbits == 0) { *uint32 = 0; } else { errn= readBits(stream, nbits, uint32); } return errn; #endif /* EXI_OPTION_ALIGNMENT == BIT_PACKED */ #if EXI_OPTION_ALIGNMENT == BYTE_ALIGNMENT size_t bitsRead = 0; uint8_t b; int errn = 0; *uint32 = 0; while (errn == 0 && bitsRead < nbits) { errn = decode(stream, &b); *uint32 = *uint32 + (uint32_t)(b << bitsRead); bitsRead = (bitsRead + 8); } return errn; #endif /* EXI_OPTION_ALIGNMENT == BYTE_ALIGNMENT */ } #endif