/* * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source * tree. An additional intellectual property rights grant can be found * in the file PATENTS. All contributing project authors may * be found in the AUTHORS file in the root of the source tree. */ #ifndef MODULES_RTP_RTCP_SOURCE_BYTE_IO_H_ #define MODULES_RTP_RTCP_SOURCE_BYTE_IO_H_ // This file contains classes for reading and writing integer types from/to // byte array representations. Signed/unsigned, partial (whole byte) sizes, // and big/little endian byte order is all supported. // // Usage examples: // // uint8_t* buffer = ...; // // // Read an unsigned 4 byte integer in big endian format // uint32_t val = ByteReader<uint32_t>::ReadBigEndian(buffer); // // // Read a signed 24-bit (3 byte) integer in little endian format // int32_t val = ByteReader<int32_t, 3>::ReadLittle(buffer); // // // Write an unsigned 8 byte integer in little endian format // ByteWriter<uint64_t>::WriteLittleEndian(buffer, val); // // Write an unsigned 40-bit (5 byte) integer in big endian format // ByteWriter<uint64_t, 5>::WriteBigEndian(buffer, val); // // These classes are implemented as recursive templetizations, intended to make // it easy for the compiler to completely inline the reading/writing. #include <stdint.h> #include <limits> namespace webrtc { // According to ISO C standard ISO/IEC 9899, section 6.2.6.2 (2), the three // representations of signed integers allowed are two's complement, one's // complement and sign/magnitude. We can detect which is used by looking at // the two last bits of -1, which will be 11 in two's complement, 10 in one's // complement and 01 in sign/magnitude. // TODO(sprang): In the unlikely event that we actually need to support a // platform that doesn't use two's complement, implement conversion to/from // wire format. // Assume the if any one signed integer type is two's complement, then all // other will be too. static_assert …; // Plain const char* won't work for static_assert, use #define instead. #define kSizeErrorMsg … // Utility class for getting the unsigned equivalent of a signed type. template <typename T> struct UnsignedOf; // Class for reading integers from a sequence of bytes. // T = type of integer, B = bytes to read, is_signed = true if signed integer. // If is_signed is true and B < sizeof(T), sign extension might be needed. template <typename T, unsigned int B = sizeof(T), bool is_signed = std::numeric_limits<T>::is_signed> class ByteReader; // Specialization of ByteReader for unsigned types. ByteReader<T, B, false>; // Specialization of ByteReader for signed types. ByteReader<T, B, true>; // Class for writing integers to a sequence of bytes // T = type of integer, B = bytes to write template <typename T, unsigned int B = sizeof(T), bool is_signed = std::numeric_limits<T>::is_signed> class ByteWriter; // Specialization of ByteWriter for unsigned types. ByteWriter<T, B, false>; // Specialization of ByteWriter for signed types. ByteWriter<T, B, true>; // ----- Below follows specializations of UnsignedOf utility class ----- template <> struct UnsignedOf<int8_t> { … }; template <> struct UnsignedOf<int16_t> { … }; template <> struct UnsignedOf<int32_t> { … }; template <> struct UnsignedOf<int64_t> { … }; // ----- Below follows specializations for unsigned, B in { 1, 2, 4, 8 } ----- // TODO(sprang): Check if these actually help or if generic cases will be // unrolled to and optimized to similar performance. // Specializations for single bytes ByteReader<T, 1, false>; ByteWriter<T, 1, false>; // Specializations for two byte words ByteReader<T, 2, false>; ByteWriter<T, 2, false>; // Specializations for four byte words. ByteReader<T, 4, false>; // Specializations for four byte words. ByteWriter<T, 4, false>; // Specializations for eight byte words. ByteReader<T, 8, false>; ByteWriter<T, 8, false>; } // namespace webrtc #endif // MODULES_RTP_RTCP_SOURCE_BYTE_IO_H_