├── .gitignore ├── .travis.yml ├── LICENSE ├── README.md ├── include └── can_encode_decode_inl.h ├── run_tests.sh └── test └── test_encode_decode.cpp /.gitignore: -------------------------------------------------------------------------------- 1 | encode_decode_test 2 | *.swp 3 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | dist: trusty 2 | language: generic 3 | script: 4 | - source run_tests.sh 5 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Rein Appeldoorn 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # libcan-encode-decode 2 | 3 | [![Build Status](https://travis-ci.org/reinzor/libcan-encode-decode.svg?branch=master)](https://travis-ci.org/reinzor/libcan-encode-decode) 4 | 5 | C++ functions for encoding and decoding CAN frames ( uint8_t[8] ) 6 | 7 | ## Usage 8 | 9 | Copy the include/can_encode_decode.inl into your c++ project and use the inline functions. 10 | 11 | uint8_t src_array[8]; 12 | 13 | encode(src_array, 3.0, 56, 3, false, false, 1.000000, 0); 14 | decode(src_array, 56, 3, false, false, 1.000000, 0); // 3.0 15 | 16 | encode(src_array, 35, 2, 6, true, false, 1.0, 0); 17 | decode(src_array, 2, 6, true, false, 1.000000, 0) // 35.000000 18 | 19 | encode(src_array, 1.0, 0, 2, true, false, 1.0, 0); 20 | decode(src_array, 0, 2, true, false, 1.000000, 0); // 1.000000 21 | 22 | ## Run tests 23 | 24 | `./run_tests.sh` 25 | -------------------------------------------------------------------------------- /include/can_encode_decode_inl.h: -------------------------------------------------------------------------------- 1 | #ifndef CAN_ENCODE_DECODE_INL_H_ 2 | #define CAN_ENCODE_DECODE_INL_H_ 3 | 4 | #include //uint typedefinitions, non-rtw! 5 | #include 6 | #include 7 | 8 | #define MASK64(nbits) ((0xffffffffffffffff) >> (64 - nbits)) 9 | 10 | 11 | inline float toPhysicalValue(uint64_t target, float factor, float offset, bool is_signed) 12 | { 13 | if (is_signed) 14 | return ((int64_t)target) * factor + offset; 15 | else 16 | return target * factor + offset; 17 | } 18 | 19 | inline uint64_t fromPhysicalValue(float physical_value, float factor, float offset) 20 | { 21 | return (int64_t)((physical_value - offset) / factor); 22 | } 23 | 24 | inline void clearBits(uint8_t* target_byte, uint8_t* bits_to_clear, const uint8_t startbit, const uint8_t length) 25 | { 26 | for (uint8_t i = startbit; i < length + startbit; ++i) 27 | { 28 | *target_byte &= ~(1UL << i); 29 | *bits_to_clear -= 1; 30 | } 31 | } 32 | 33 | inline void storeSignal(uint8_t* frame, uint64_t value, const uint8_t startbit, const uint8_t length, 34 | bool is_big_endian, bool is_signed) 35 | { 36 | uint8_t start_byte = startbit / 8; 37 | uint8_t startbit_in_byte = startbit % 8; 38 | uint8_t end_byte = 0; 39 | int8_t count = 0; 40 | uint8_t current_target_length = (8 - startbit_in_byte); 41 | uint8_t bits_to_clear = length; 42 | 43 | // Mask the value 44 | value &= MASK64(length); 45 | 46 | // Write bits of startbyte 47 | clearBits(&frame[start_byte], &bits_to_clear, startbit_in_byte, current_target_length > length ? length : current_target_length); 48 | frame[start_byte] |= value << startbit_in_byte; 49 | 50 | // Write residual bytes 51 | if (is_big_endian) // Motorola (big endian) 52 | { 53 | end_byte = (start_byte * 8 + 8 - startbit_in_byte - length) / 8; 54 | 55 | for (count = start_byte - 1; count >= end_byte; count--) 56 | { 57 | clearBits(&frame[count], &bits_to_clear, 0, bits_to_clear >= 8 ? 8 : bits_to_clear); 58 | frame[count] |= value >> current_target_length; 59 | current_target_length += 8; 60 | } 61 | } 62 | else // Intel (little endian) 63 | { 64 | end_byte = (startbit + length - 1) / 8; 65 | 66 | for (count = start_byte + 1; count <= end_byte; count++) 67 | { 68 | clearBits(&frame[count], &bits_to_clear, 0, bits_to_clear >= 8 ? 8 : bits_to_clear); 69 | frame[count] |= value >> current_target_length; 70 | current_target_length += 8; 71 | } 72 | } 73 | } 74 | 75 | inline uint64_t extractSignal(const uint8_t* frame, const uint8_t startbit, const uint8_t length, bool is_big_endian, 76 | bool is_signed) 77 | { 78 | uint8_t start_byte = startbit / 8; 79 | uint8_t startbit_in_byte = startbit % 8; 80 | uint8_t current_target_length = (8 - startbit_in_byte); 81 | uint8_t end_byte = 0; 82 | int8_t count = 0; 83 | 84 | // Write first bits to target 85 | uint64_t target = frame[start_byte] >> startbit_in_byte; 86 | 87 | // Write residual bytes 88 | if (is_big_endian) // Motorola (big endian) 89 | { 90 | end_byte = (start_byte * 8 + 8 - startbit_in_byte - length) / 8; 91 | 92 | for (count = start_byte - 1; count >= end_byte; count--) 93 | { 94 | target |= frame[count] << current_target_length; 95 | current_target_length += 8; 96 | } 97 | } 98 | else // Intel (little endian) 99 | { 100 | end_byte = (startbit + length - 1) / 8; 101 | 102 | for (count = start_byte + 1; count <= end_byte; count++) 103 | { 104 | target |= frame[count] << current_target_length; 105 | current_target_length += 8; 106 | } 107 | } 108 | 109 | // Mask value 110 | target &= MASK64(length); 111 | 112 | // perform sign extension 113 | if (is_signed) 114 | { 115 | int64_t msb_sign_mask = 1 << (length - 1); 116 | target = ((int64_t)target ^ msb_sign_mask) - msb_sign_mask; 117 | } 118 | 119 | return target; 120 | } 121 | 122 | // For Vector CAN DB files https://vector.com/vi_candb_en.html 123 | 124 | inline float decode(const uint8_t* frame, const uint16_t startbit, const uint16_t length, bool is_big_endian, 125 | bool is_signed, float factor, float offset) 126 | { 127 | return toPhysicalValue(extractSignal(frame, startbit, length, is_big_endian, is_signed), factor, offset, is_signed); 128 | } 129 | 130 | inline void encode(uint8_t* frame, const float value, const uint16_t startbit, const uint16_t length, 131 | bool is_big_endian, bool is_signed, float factor, float offset) 132 | { 133 | storeSignal(frame, fromPhysicalValue(value, factor, offset), startbit, length, is_big_endian, is_signed); 134 | } 135 | 136 | // Texas instruments IQ notation https://en.wikipedia.org/wiki/Q_(number_format) 137 | 138 | inline double extractIQ(const uint8_t* frame, uint8_t start, uint8_t length, uint8_t float_length, bool is_big_endian, 139 | bool is_signed) 140 | { 141 | return (int64_t) extractSignal(frame, start, length, is_big_endian, is_signed) / pow(2, float_length); 142 | } 143 | 144 | inline void storeIQ(uint8_t* frame, double value, uint8_t start, uint8_t length, uint8_t float_length, 145 | bool is_big_endian, bool is_signed) 146 | { 147 | storeSignal(frame, value * pow(2, float_length), start, length, is_big_endian, is_signed); 148 | } 149 | 150 | #endif 151 | -------------------------------------------------------------------------------- /run_tests.sh: -------------------------------------------------------------------------------- 1 | g++ test/test_encode_decode.cpp -o encode_decode_test 2 | ./encode_decode_test 3 | -------------------------------------------------------------------------------- /test/test_encode_decode.cpp: -------------------------------------------------------------------------------- 1 | #include "../include/can_encode_decode_inl.h" 2 | 3 | #include 4 | #include 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | std::stack tictoc_stack; 12 | unsigned int num_tests = 0; 13 | 14 | void tic() 15 | { 16 | tictoc_stack.push(clock()); 17 | } 18 | 19 | void toc() 20 | { 21 | std::cout << "All " << num_tests << " tests passed within " 22 | << ((double)(clock() - tictoc_stack.top())) / CLOCKS_PER_SEC << " seconds!" << std::endl; 23 | tictoc_stack.pop(); 24 | } 25 | 26 | inline void TEST(float k, float v, float eps = 0.01) 27 | { 28 | num_tests++; 29 | bool near = (k >= v - eps && k <= v + eps); 30 | if (!near) 31 | { 32 | std::cerr << "Expected " << v << " but got " << k << std::endl; 33 | exit(1); 34 | } 35 | } 36 | 37 | inline void PRINT(uint64_t value, int64_t signed_value) 38 | { 39 | std::cout << "Values signed vs unsigned:" << std::endl; 40 | std::cout << std::bitset<64>(value) << ": " << value << std::endl; 41 | std::cout << std::bitset<64>(signed_value) << ": " << signed_value << " (signed)" << std::endl; 42 | } 43 | 44 | inline void PRINT(uint8_t* array) 45 | { 46 | std::cout << ">> Array:" << std::endl; 47 | for (unsigned int i = 0; i < 8; ++i) 48 | std::cout << "\t" << std::bitset<8>(array[i]) << std::endl; 49 | } 50 | 51 | inline void TEST_STORE_EXTRACT(int64_t value, unsigned int startbit, unsigned int length, bool is_big_endian, 52 | bool is_signed) 53 | { 54 | // std::cout << "--\n TEST_STORE_EXTRACT(" << value << ", " << startbit << ", " << length << ", " << is_big_endian << 55 | // ", " << is_signed << ")" << std::endl; 56 | uint8_t src_array[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; 57 | 58 | storeSignal(src_array, value, startbit, length, is_big_endian, is_signed); 59 | TEST((int32_t)extractSignal(src_array, startbit, length, is_big_endian, is_signed), value); 60 | } 61 | 62 | inline void TEST_ENCODE_DECODE(float value, unsigned int startbit, unsigned int length, bool is_big_endian, 63 | bool is_signed, float factor, float offset) 64 | { 65 | // std::cout << "--\n TEST_ENCODE_DECODE(" << value << ", " << startbit << ", " << length << ", " << is_big_endian << 66 | // ", " << is_signed << ", " << factor << ", " << offset << ")" << std::endl; 67 | uint8_t src_array[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; 68 | 69 | // Only negative allowed when signed 70 | assert(is_signed || (int64_t)fromPhysicalValue(value, factor, offset) >= 0); 71 | 72 | encode(src_array, value, startbit, length, is_big_endian, is_signed, factor, offset); 73 | 74 | TEST(decode(src_array, startbit, length, is_big_endian, is_signed, factor, offset), value); 75 | } 76 | 77 | inline void TEST_IQ_STORE_EXTRACT(float value, unsigned int startbit, unsigned int length, unsigned int float_length, 78 | bool is_big_endian, bool is_signed) 79 | { 80 | uint8_t src_array[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; 81 | storeIQ(src_array, value, startbit, length, float_length, is_big_endian, is_signed); 82 | TEST(extractIQ(src_array, startbit, length, float_length, is_big_endian, is_signed), value); 83 | } 84 | 85 | int main() 86 | { 87 | tic(); 88 | 89 | // Decode test 1 (big endian unsigned) 90 | { 91 | uint64_t src = 0x182000110008d; 92 | uint8_t src_array[8] = { 141, 0, 16, 1, 0, 130, 1, 0 }; 93 | 94 | TEST(extractSignal(src_array, 0, 2, true, false), 1); 95 | TEST(decode(src_array, 0, 2, true, false, 1.000000, 0), 1.000000); 96 | 97 | TEST(extractSignal(src_array, 2, 6, true, false), 35); 98 | TEST(decode(src_array, 2, 6, true, false, 1.000000, 0), 35.000000); 99 | 100 | TEST(extractSignal(src_array, 21, 11, true, false), 0); 101 | TEST(decode(src_array, 21, 11, true, false, 0.100000, 0), 0.000000); 102 | 103 | TEST(extractSignal(src_array, 25, 12, true, false), 2048); 104 | TEST(decode(src_array, 25, 12, true, false, 0.062500, -128), 0.000000); 105 | 106 | TEST(extractSignal(src_array, 32, 9, true, false), 256); 107 | TEST(decode(src_array, 32, 9, true, false, 0.062500, -16), 0.000000); 108 | 109 | TEST(extractSignal(src_array, 48, 3, true, false), 1); 110 | TEST(decode(src_array, 48, 3, true, false, 1.000000, 0), 1.000000); 111 | 112 | TEST(extractSignal(src_array, 51, 3, true, false), 0); 113 | TEST(decode(src_array, 51, 3, true, false, 1.000000, 0), 0.000000); 114 | 115 | TEST(extractSignal(src_array, 54, 10, true, false), 520); 116 | TEST(decode(src_array, 54, 10, true, false, 0.100000, -52), 0.000000); 117 | 118 | TEST(extractSignal(src_array, 56, 3, true, false), 0); 119 | TEST(decode(src_array, 56, 3, true, false, 1.000000, 0), 0.000000); 120 | 121 | TEST(extractSignal(src_array, 59, 3, true, false), 0); 122 | TEST(decode(src_array, 59, 3, true, false, 1.000000, 0), 0.000000); 123 | 124 | TEST(extractSignal(src_array, 62, 2, true, false), 0); 125 | TEST(decode(src_array, 62, 2, true, false, 1.000000, 0), 0.000000); 126 | } 127 | 128 | // Decode test 2 (little endian, signed and unsigned) 129 | { 130 | // src, startbit, bitlength, is_big_endian, is_signed, factor, offset, name, value 131 | uint8_t src_array[8] = { 12, 0, 5, 112, 3, 205, 31, 131 }; 132 | 133 | TEST(extractSignal(src_array, 60, 2, false, false), 0); 134 | TEST(decode(src_array, 60, 2, false, true, 1.000000, 0), 0.000000); 135 | 136 | TEST(extractSignal(src_array, 55, 1, false, false), 0); 137 | TEST(decode(src_array, 55, 1, false, false, 1.000000, 0), 0.000000); 138 | 139 | TEST(extractSignal(src_array, 20, 4, false, false), 0); 140 | TEST(decode(src_array, 20, 4, false, false, 1.000000, 0), 0.000000); 141 | 142 | TEST(extractSignal(src_array, 62, 2, false, false), 2); 143 | TEST(decode(src_array, 62, 2, false, false, 1.000000, 0), 2.000000); 144 | 145 | TEST(extractSignal(src_array, 34, 3, false, false), 0); 146 | TEST(decode(src_array, 34, 3, false, false, 1.000000, 0), 0.000000); 147 | 148 | TEST(extractSignal(src_array, 37, 3, false, false), 0); 149 | TEST(decode(src_array, 37, 3, false, false, 1.000000, 0), 0.000000); 150 | 151 | TEST(extractSignal(src_array, 59, 1, false, true), 0); 152 | TEST(decode(src_array, 59, 1, false, true, 1.000000, 0), 0.000000); 153 | 154 | TEST(extractSignal(src_array, 56, 3, false, false), 3); 155 | TEST(decode(src_array, 56, 3, false, false, 1.000000, 0), 3.000000); 156 | 157 | TEST(extractSignal(src_array, 52, 3, false, false), 1); 158 | TEST(decode(src_array, 52, 3, false, false, 1.000000, 0), 1.000000); 159 | 160 | TEST(extractSignal(src_array, 8, 12, false, false), 1280); 161 | TEST(decode(src_array, 8, 12, false, false, 0.062500, 0), 80.000000); 162 | 163 | TEST(decode(src_array, 40, 12, false, true, 0.062500, 0), -3.187500); 164 | 165 | TEST(extractSignal(src_array, 24, 10, false, true), (uint64_t)-144); 166 | TEST(decode(src_array, 24, 10, false, true, 0.062500, 0), -9.000000); 167 | 168 | TEST(extractSignal(src_array, 0, 8, false, false), 12); 169 | TEST(decode(src_array, 0, 8, false, false, 1.000000, 0), 12.000000); 170 | } 171 | 172 | // Store extract 173 | { 174 | TEST_STORE_EXTRACT(512, 8, 12, false, true); 175 | 176 | // Limits 177 | TEST_STORE_EXTRACT(512, 0, 32, false, false); 178 | TEST_STORE_EXTRACT(512, 56, 32, true, false); 179 | TEST_STORE_EXTRACT(512, 32, 32, false, false); 180 | TEST_STORE_EXTRACT(512, 32, 32, true, false); 181 | 182 | // Limits 183 | TEST_STORE_EXTRACT(-512, 0, 32, false, true); 184 | TEST_STORE_EXTRACT(-512, 56, 32, true, true); 185 | TEST_STORE_EXTRACT(-512, 32, 32, false, true); 186 | TEST_STORE_EXTRACT(-512, 32, 32, true, true); 187 | 188 | // Some other 189 | TEST_STORE_EXTRACT(26, 4, 8, false, false); 190 | TEST_STORE_EXTRACT(26, 62, 8, true, false); 191 | TEST_STORE_EXTRACT(-12, 4, 8, false, true); 192 | TEST_STORE_EXTRACT(-13, 62, 8, true, true); 193 | TEST_STORE_EXTRACT(-190, 62, 24, true, true); 194 | } 195 | 196 | // Encoding decoding 197 | { 198 | TEST_ENCODE_DECODE(-1.0, 0, 7, false, true, 1.0, 0.0); 199 | TEST_ENCODE_DECODE(-100.0, 0, 7, false, true, 100, 0.0); 200 | TEST_ENCODE_DECODE(3.0, 56, 3, false, false, 1.000000, 0.0); 201 | TEST_ENCODE_DECODE(35, 2, 6, true, false, 1.0, 0); 202 | TEST_ENCODE_DECODE(1.0, 0, 2, true, false, 1.0, 0); 203 | 204 | TEST_ENCODE_DECODE(1.0, 62, 24, true, true, 0.1, 20); 205 | } 206 | 207 | // IQ notations store extract (little endian only) 208 | { 209 | TEST_IQ_STORE_EXTRACT(-1.0, 0, 7, 3, false, true); 210 | TEST_IQ_STORE_EXTRACT(-8.25, 0, 16, 8, false, true); 211 | TEST_IQ_STORE_EXTRACT(3.0, 56, 3, 0, false, false); 212 | TEST_IQ_STORE_EXTRACT(8.32, 2, 16, 8, false, false); 213 | TEST_IQ_STORE_EXTRACT(1.0, 0, 2, 0, false, false); 214 | TEST_IQ_STORE_EXTRACT(1.6, 0, 24, 8, false, true); 215 | } 216 | 217 | // Encoding with non-zero source array 218 | { 219 | uint8_t src_array[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; 220 | int number = 11465; 221 | encode(src_array, number, 16, 16, false, false, 0.5, 0); 222 | TEST(number, decode(src_array, 16, 16, false, false, 0.5, 0)); 223 | 224 | number = 3; 225 | encode(src_array, number, 15, 3, false, false, 0.5, 0); 226 | TEST(number, decode(src_array, 15, 3, false, false, 0.5, 0)); 227 | 228 | number = 11768; 229 | encode(src_array, number, 16, 16, false, false, 0.5, 0); 230 | TEST(number, decode(src_array, 16, 16, false, false, 0.5, 0)); 231 | 232 | // Clearing after within byte 233 | number = 15; 234 | encode(src_array, number, 0, 4, false, false, 1.0, 0); 235 | TEST(number, decode(src_array, 0, 4, false, false, 1.0, 0)); 236 | 237 | int second_number = 0; 238 | encode(src_array, second_number, 4, 4, false, false, 1.0, 0); 239 | TEST(second_number, decode(src_array, 4, 4, false, false, 1.0, 0)); 240 | TEST(number, decode(src_array, 0, 4, false, false, 1.0, 0)); 241 | 242 | // Clearing before within byte 243 | encode(src_array, number, 4, 4, false, false, 1.0, 0); 244 | TEST(number, decode(src_array, 4, 4, false, false, 1.0, 0)); 245 | 246 | encode(src_array, second_number, 0, 4, false, false, 1.0, 0); 247 | TEST(second_number, decode(src_array, 0, 4, false, false, 1.0, 0)); 248 | TEST(number, decode(src_array, 4, 4, false, false, 1.0, 0)); 249 | } 250 | 251 | { 252 | uint8_t src_array[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; 253 | 254 | // Clearing after over bytes 255 | int number = 4095; 256 | int second_number = 0; 257 | 258 | encode(src_array, number, 0, 12, false, false, 1.0, 0); 259 | TEST(number, decode(src_array, 0, 12, false, false, 1.0, 0)); 260 | 261 | encode(src_array, second_number, 12, 4, false, false, 1.0, 0); 262 | TEST(second_number, decode(src_array, 12, 4, false, false, 1.0, 0)); 263 | TEST(number, decode(src_array, 0, 12, false, false, 1.0, 0)); 264 | } 265 | 266 | { 267 | uint8_t src_array[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; 268 | 269 | // Clearing after over byte 270 | int number = 15; 271 | int second_number = 0; 272 | encode(src_array, number, 12, 4, false, false, 1.0, 0); 273 | TEST(number, decode(src_array, 12, 4, false, false, 1.0, 0)); 274 | 275 | encode(src_array, second_number, 0, 12, false, false, 1.0, 0); 276 | TEST(second_number, decode(src_array, 0, 12, false, false, 1.0, 0)); 277 | TEST(number, decode(src_array, 12, 4, false, false, 1.0, 0)); 278 | } 279 | 280 | { 281 | uint8_t src_array[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; 282 | 283 | // Clearing over bytes 284 | int number = 255; 285 | int second_number = 15; 286 | 287 | encode(src_array, number, 4, 8, false, false, 1.0, 0); 288 | encode(src_array, second_number, 0, 4, false, false, 1.0, 0); 289 | encode(src_array, second_number, 12, 4, false, false, 1.0, 0); 290 | TEST(number, decode(src_array, 4, 8, false, false, 1.0, 0)); 291 | } 292 | 293 | { 294 | uint8_t src_array[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; 295 | 296 | // Clearing over bytes 297 | int number = 255; 298 | int second_number = 15; 299 | 300 | encode(src_array, second_number, 0, 4, false, false, 1.0, 0); 301 | encode(src_array, second_number, 12, 4, false, false, 1.0, 0); 302 | 303 | encode(src_array, number, 4, 8, false, false, 1.0, 0); 304 | TEST(second_number, decode(src_array, 0, 4, false, false, 1.0, 0)); 305 | TEST(second_number, decode(src_array, 12, 4, false, false, 1.0, 0)); 306 | } 307 | 308 | toc(); 309 | } 310 | --------------------------------------------------------------------------------