1499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org/* 2499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved. 3499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org * 4499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org * Use of this source code is governed by a BSD-style license 5499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org * that can be found in the LICENSE file in the root of the source 6499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org * tree. An additional intellectual property rights grant can be found 7499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org * in the file PATENTS. All contributing project authors may 8499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org * be found in the AUTHORS file in the root of the source tree. 9499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org */ 10499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org 11499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org#ifndef WEBRTC_MODULES_RTP_RTCP_SOURCE_BYTE_IO_H_ 12499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org#define WEBRTC_MODULES_RTP_RTCP_SOURCE_BYTE_IO_H_ 13499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org 14499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org 15499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org// This file contains classes for reading and writing integer types from/to 16499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org// byte array representations. Signed/unsigned, partial (whole byte) sizes, 17499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org// and big/little endian byte order is all supported. 18499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org// 19499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org// Usage examples: 20499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org// 21499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org// uint8_t* buffer = ...; 22499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org// 23499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org// // Read an unsigned 4 byte integer in big endian format 24499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org// uint32_t val = ByteReader<uint32_t>::ReadBigEndian(buffer); 25499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org// 26499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org// // Read a signed 24-bit (3 byte) integer in little endian format 27499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org// int32_t val = ByteReader<int32_t, 3>::ReadLittle(buffer); 28499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org// 29499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org// // Write an unsigned 8 byte integer in little endian format 30499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org// ByteWriter<uint64_t>::WriteLittleEndian(buffer, val); 31499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org// 32499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org// Write an unsigned 40-bit (5 byte) integer in big endian format 33499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org// ByteWriter<uint64_t, 5>::WriteBigEndian(buffer, val); 34499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org// 35499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org// These classes are implemented as recursive templetizations, inteded to make 36499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org// it easy for the compiler to completely inline the reading/writing. 37499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org 38499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org 39499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org#include <limits> 40499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org 41499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org#include "webrtc/typedefs.h" 42499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org 43499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.orgnamespace webrtc { 44499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org 45be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprang// According to ISO C standard ISO/IEC 9899, section 6.2.6.2 (2), the three 46be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprang// representations of signed integers allowed are two's complement, one's 47be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprang// complement and sign/magnitude. We can detect which is used by looking at 48be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprang// the two last bits of -1, which will be 11 in two's complement, 10 in one's 49be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprang// complement and 01 in sign/magnitude. 50be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprang// TODO(sprang): In the unlikely event that we actually need to support a 51be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprang// platform that doesn't use two's complement, implement conversion to/from 52be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprang// wire format. 53be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprang 546a6f0893dd1e653410ba4b22e7f33947d15aeb65danilchap// Assume the if any one signed integer type is two's complement, then all 556a6f0893dd1e653410ba4b22e7f33947d15aeb65danilchap// other will be too. 566a6f0893dd1e653410ba4b22e7f33947d15aeb65danilchapstatic_assert( 576a6f0893dd1e653410ba4b22e7f33947d15aeb65danilchap (-1 & 0x03) == 0x03, 586a6f0893dd1e653410ba4b22e7f33947d15aeb65danilchap "Only two's complement representation of signed integers supported."); 596a6f0893dd1e653410ba4b22e7f33947d15aeb65danilchap 60be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprang// Plain const char* won't work for static_assert, use #define instead. 61be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprang#define kSizeErrorMsg "Byte size must be less than or equal to data type size." 62be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprang 63be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprang// Utility class for getting the unsigned equivalent of a signed type. 64be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprangtemplate <typename T> 65be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprangstruct UnsignedOf; 66be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprang 67499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org// Class for reading integers from a sequence of bytes. 68be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprang// T = type of integer, B = bytes to read, is_signed = true if signed integer. 69be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprang// If is_signed is true and B < sizeof(T), sign extension might be needed. 70be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprangtemplate <typename T, 71be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprang unsigned int B = sizeof(T), 72be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprang bool is_signed = std::numeric_limits<T>::is_signed> 73be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprangclass ByteReader; 74be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprang 75be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprang// Specialization of ByteReader for unsigned types. 76be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprangtemplate <typename T, unsigned int B> 77be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprangclass ByteReader<T, B, false> { 78499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org public: 792a6558c2a51a0aa610e85455ea7a35cfaf39bec8sprang@webrtc.org static T ReadBigEndian(const uint8_t* data) { 80be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprang static_assert(B <= sizeof(T), kSizeErrorMsg); 81499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org return InternalReadBigEndian(data); 82499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org } 83499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org 842a6558c2a51a0aa610e85455ea7a35cfaf39bec8sprang@webrtc.org static T ReadLittleEndian(const uint8_t* data) { 85be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprang static_assert(B <= sizeof(T), kSizeErrorMsg); 86499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org return InternalReadLittleEndian(data); 87499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org } 88499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org 89499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org private: 902a6558c2a51a0aa610e85455ea7a35cfaf39bec8sprang@webrtc.org static T InternalReadBigEndian(const uint8_t* data) { 91499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org T val(0); 92be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprang for (unsigned int i = 0; i < B; ++i) 93499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org val |= static_cast<T>(data[i]) << ((B - 1 - i) * 8); 94499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org return val; 95499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org } 96499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org 972a6558c2a51a0aa610e85455ea7a35cfaf39bec8sprang@webrtc.org static T InternalReadLittleEndian(const uint8_t* data) { 98499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org T val(0); 99be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprang for (unsigned int i = 0; i < B; ++i) 100499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org val |= static_cast<T>(data[i]) << (i * 8); 101be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprang return val; 102be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprang } 103be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprang}; 104be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprang 105be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprang// Specialization of ByteReader for signed types. 106be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprangtemplate <typename T, unsigned int B> 107be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprangclass ByteReader<T, B, true> { 108be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprang public: 109be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprang typedef typename UnsignedOf<T>::Type U; 110be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprang 111be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprang static T ReadBigEndian(const uint8_t* data) { 112be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprang U unsigned_val = ByteReader<T, B, false>::ReadBigEndian(data); 113be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprang if (B < sizeof(T)) 114be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprang unsigned_val = SignExtend(unsigned_val); 115be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprang return ReinterpretAsSigned(unsigned_val); 116be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprang } 117be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprang 118be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprang static T ReadLittleEndian(const uint8_t* data) { 119be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprang U unsigned_val = ByteReader<T, B, false>::ReadLittleEndian(data); 120be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprang if (B < sizeof(T)) 121be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprang unsigned_val = SignExtend(unsigned_val); 122be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprang return ReinterpretAsSigned(unsigned_val); 123be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprang } 124be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprang 125be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprang private: 126be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprang // As a hack to avoid implementation-specific or undefined behavior when 127be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprang // bit-shifting or casting signed integers, read as a signed equivalent 128be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprang // instead and convert to signed. This is safe since we have asserted that 129be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprang // two's complement for is used. 130be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprang static T ReinterpretAsSigned(U unsigned_val) { 131be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprang // An unsigned value with only the highest order bit set (ex 0x80). 132be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprang const U kUnsignedHighestBitMask = 133be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprang static_cast<U>(1) << ((sizeof(U) * 8) - 1); 134be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprang // A signed value with only the highest bit set. Since this is two's 135be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprang // complement form, we can use the min value from std::numeric_limits. 136be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprang const T kSignedHighestBitMask = std::numeric_limits<T>::min(); 137be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprang 138be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprang T val; 139be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprang if ((unsigned_val & kUnsignedHighestBitMask) != 0) { 140be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprang // Casting is only safe when unsigned value can be represented in the 141be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprang // signed target type, so mask out highest bit and mask it back manually. 142be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprang val = static_cast<T>(unsigned_val & ~kUnsignedHighestBitMask); 143be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprang val |= kSignedHighestBitMask; 144be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprang } else { 145be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprang val = static_cast<T>(unsigned_val); 146499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org } 147499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org return val; 148499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org } 149499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org 150499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org // If number of bytes is less than native data type (eg 24 bit, in int32_t), 151499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org // and the most significant bit of the actual data is set, we must sign 152499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org // extend the remaining byte(s) with ones so that the correct negative 153499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org // number is retained. 154499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org // Ex: 0x810A0B -> 0xFF810A0B, but 0x710A0B -> 0x00710A0B 155be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprang static U SignExtend(const U val) { 156be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprang const uint8_t kMsb = static_cast<uint8_t>(val >> ((B - 1) * 8)); 157be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprang if ((kMsb & 0x80) != 0) { 158be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprang // Create a mask where all bits used by the B bytes are set to one, 159be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprang // for instance 0x00FFFFFF for B = 3. Bit-wise invert that mask (to 160be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprang // (0xFF000000 in the example above) and add it to the input value. 161be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprang // The "B % sizeof(T)" is a workaround to undefined values warnings for 162be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprang // B == sizeof(T), in which case this code won't be called anyway. 163be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprang const U kUsedBitsMask = (1 << ((B % sizeof(T)) * 8)) - 1; 164be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprang return ~kUsedBitsMask | val; 165499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org } 166499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org return val; 167499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org } 168499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org}; 169499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org 170499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org// Class for writing integers to a sequence of bytes 171499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org// T = type of integer, B = bytes to write 172be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprangtemplate <typename T, 173be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprang unsigned int B = sizeof(T), 174be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprang bool is_signed = std::numeric_limits<T>::is_signed> 175be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprangclass ByteWriter; 176be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprang 177be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprang// Specialization of ByteWriter for unsigned types. 178be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprangtemplate <typename T, unsigned int B> 179be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprangclass ByteWriter<T, B, false> { 180499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org public: 181499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org static void WriteBigEndian(uint8_t* data, T val) { 182be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprang static_assert(B <= sizeof(T), kSizeErrorMsg); 183499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org for (unsigned int i = 0; i < B; ++i) { 184499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org data[i] = val >> ((B - 1 - i) * 8); 185499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org } 186499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org } 187499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org 188499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org static void WriteLittleEndian(uint8_t* data, T val) { 189be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprang static_assert(B <= sizeof(T), kSizeErrorMsg); 190499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org for (unsigned int i = 0; i < B; ++i) { 191499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org data[i] = val >> (i * 8); 192499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org } 193499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org } 194499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org}; 195499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org 196be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprang// Specialization of ByteWriter for signed types. 197be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprangtemplate <typename T, unsigned int B> 198be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprangclass ByteWriter<T, B, true> { 199be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprang public: 200be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprang typedef typename UnsignedOf<T>::Type U; 201be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprang 202be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprang static void WriteBigEndian(uint8_t* data, T val) { 203be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprang ByteWriter<U, B, false>::WriteBigEndian(data, ReinterpretAsUnsigned(val)); 204be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprang } 205be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprang 206be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprang static void WriteLittleEndian(uint8_t* data, T val) { 207be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprang ByteWriter<U, B, false>::WriteLittleEndian(data, 208be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprang ReinterpretAsUnsigned(val)); 209be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprang } 210be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprang 211be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprang private: 212be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprang static U ReinterpretAsUnsigned(T val) { 213be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprang // According to ISO C standard ISO/IEC 9899, section 6.3.1.3 (1, 2) a 214be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprang // conversion from signed to unsigned keeps the value if the new type can 215be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprang // represent it, and otherwise adds one more than the max value of T until 216be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprang // the value is in range. For two's complement, this fortunately means 217be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprang // that the bit-wise value will be intact. Thus, since we have asserted that 218be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprang // two's complement form is actually used, a simple cast is sufficient. 219be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprang return static_cast<U>(val); 220be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprang } 221be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprang}; 222be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprang 223be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprang// ----- Below follows specializations of UnsignedOf utility class ----- 224be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprang 225be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprangtemplate <> 226be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprangstruct UnsignedOf<int8_t> { 227be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprang typedef uint8_t Type; 228be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprang}; 229be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprangtemplate <> 230be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprangstruct UnsignedOf<int16_t> { 231be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprang typedef uint16_t Type; 232be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprang}; 233be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprangtemplate <> 234be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprangstruct UnsignedOf<int32_t> { 235be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprang typedef uint32_t Type; 236be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprang}; 237be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprangtemplate <> 238be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprangstruct UnsignedOf<int64_t> { 239be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprang typedef uint64_t Type; 240be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprang}; 241be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprang 242be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprang// ----- Below follows specializations for unsigned, B in { 1, 2, 4, 8 } ----- 243be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprang 244be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprang// TODO(sprang): Check if these actually help or if generic cases will be 245be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprang// unrolled to and optimized to similar performance. 246499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org 247be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprang// Specializations for single bytes 248be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprangtemplate <typename T> 249be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprangclass ByteReader<T, 1, false> { 250be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprang public: 251be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprang static T ReadBigEndian(const uint8_t* data) { 252be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprang static_assert(sizeof(T) == 1, kSizeErrorMsg); 253be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprang return data[0]; 254be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprang } 255499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org 256be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprang static T ReadLittleEndian(const uint8_t* data) { 257be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprang static_assert(sizeof(T) == 1, kSizeErrorMsg); 258be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprang return data[0]; 259be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprang } 260be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprang}; 261be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprang 262be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprangtemplate <typename T> 263be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprangclass ByteWriter<T, 1, false> { 264be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprang public: 265be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprang static void WriteBigEndian(uint8_t* data, T val) { 266be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprang static_assert(sizeof(T) == 1, kSizeErrorMsg); 267be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprang data[0] = val; 268be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprang } 269be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprang 270be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprang static void WriteLittleEndian(uint8_t* data, T val) { 271be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprang static_assert(sizeof(T) == 1, kSizeErrorMsg); 272be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprang data[0] = val; 273be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprang } 274be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprang}; 275499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org 276499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org// Specializations for two byte words 277be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprangtemplate <typename T> 278be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprangclass ByteReader<T, 2, false> { 279499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org public: 2802a6558c2a51a0aa610e85455ea7a35cfaf39bec8sprang@webrtc.org static T ReadBigEndian(const uint8_t* data) { 281be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprang static_assert(sizeof(T) >= 2, kSizeErrorMsg); 282499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org return (data[0] << 8) | data[1]; 283499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org } 284499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org 2852a6558c2a51a0aa610e85455ea7a35cfaf39bec8sprang@webrtc.org static T ReadLittleEndian(const uint8_t* data) { 286be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprang static_assert(sizeof(T) >= 2, kSizeErrorMsg); 287499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org return data[0] | (data[1] << 8); 288499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org } 289499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org}; 290499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org 291be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprangtemplate <typename T> 292be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprangclass ByteWriter<T, 2, false> { 293499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org public: 294499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org static void WriteBigEndian(uint8_t* data, T val) { 295be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprang static_assert(sizeof(T) >= 2, kSizeErrorMsg); 296499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org data[0] = val >> 8; 297499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org data[1] = val; 298499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org } 299499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org 300499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org static void WriteLittleEndian(uint8_t* data, T val) { 301be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprang static_assert(sizeof(T) >= 2, kSizeErrorMsg); 302499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org data[0] = val; 303499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org data[1] = val >> 8; 304499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org } 305499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org}; 306499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org 307499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org// Specializations for four byte words. 308be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprangtemplate <typename T> 309be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprangclass ByteReader<T, 4, false> { 310499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org public: 3112a6558c2a51a0aa610e85455ea7a35cfaf39bec8sprang@webrtc.org static T ReadBigEndian(const uint8_t* data) { 312be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprang static_assert(sizeof(T) >= 4, kSizeErrorMsg); 313499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org return (data[0] << 24) | (data[1] << 16) | (data[2] << 8) | data[3]; 314499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org } 315499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org 3162a6558c2a51a0aa610e85455ea7a35cfaf39bec8sprang@webrtc.org static T ReadLittleEndian(const uint8_t* data) { 317be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprang static_assert(sizeof(T) >= 4, kSizeErrorMsg); 318499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org return data[0] | (data[1] << 8) | (data[2] << 16) | (data[3] << 24); 319499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org } 320499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org}; 321499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org 322499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org// Specializations for four byte words. 323be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprangtemplate <typename T> 324be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprangclass ByteWriter<T, 4, false> { 325499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org public: 326499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org static void WriteBigEndian(uint8_t* data, T val) { 327be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprang static_assert(sizeof(T) >= 4, kSizeErrorMsg); 328499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org data[0] = val >> 24; 329499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org data[1] = val >> 16; 330499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org data[2] = val >> 8; 331499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org data[3] = val; 332499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org } 333499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org 334499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org static void WriteLittleEndian(uint8_t* data, T val) { 335be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprang static_assert(sizeof(T) >= 4, kSizeErrorMsg); 336499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org data[0] = val; 337499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org data[1] = val >> 8; 338499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org data[2] = val >> 16; 339499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org data[3] = val >> 24; 340499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org } 341499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org}; 342499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org 343499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org// Specializations for eight byte words. 344be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprangtemplate <typename T> 345be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprangclass ByteReader<T, 8, false> { 346499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org public: 3472a6558c2a51a0aa610e85455ea7a35cfaf39bec8sprang@webrtc.org static T ReadBigEndian(const uint8_t* data) { 348be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprang static_assert(sizeof(T) >= 8, kSizeErrorMsg); 349499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org return 350499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org (Get(data, 0) << 56) | (Get(data, 1) << 48) | 351499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org (Get(data, 2) << 40) | (Get(data, 3) << 32) | 352499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org (Get(data, 4) << 24) | (Get(data, 5) << 16) | 353499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org (Get(data, 6) << 8) | Get(data, 7); 354499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org } 355499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org 3562a6558c2a51a0aa610e85455ea7a35cfaf39bec8sprang@webrtc.org static T ReadLittleEndian(const uint8_t* data) { 357be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprang static_assert(sizeof(T) >= 8, kSizeErrorMsg); 358499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org return 359499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org Get(data, 0) | (Get(data, 1) << 8) | 360499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org (Get(data, 2) << 16) | (Get(data, 3) << 24) | 361499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org (Get(data, 4) << 32) | (Get(data, 5) << 40) | 362499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org (Get(data, 6) << 48) | (Get(data, 7) << 56); 363499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org } 364499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org 365499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org private: 3662a6558c2a51a0aa610e85455ea7a35cfaf39bec8sprang@webrtc.org inline static T Get(const uint8_t* data, unsigned int index) { 367499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org return static_cast<T>(data[index]); 368499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org } 369499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org}; 370499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org 371be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprangtemplate <typename T> 372be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprangclass ByteWriter<T, 8, false> { 373499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org public: 374499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org static void WriteBigEndian(uint8_t* data, T val) { 375be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprang static_assert(sizeof(T) >= 8, kSizeErrorMsg); 376499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org data[0] = val >> 56; 377499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org data[1] = val >> 48; 378499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org data[2] = val >> 40; 379499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org data[3] = val >> 32; 380499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org data[4] = val >> 24; 381499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org data[5] = val >> 16; 382499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org data[6] = val >> 8; 383499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org data[7] = val; 384499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org } 385499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org 386499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org static void WriteLittleEndian(uint8_t* data, T val) { 387be9b7b6881e5b0e0b54e7d2fb79c5af5f68c015bsprang static_assert(sizeof(T) >= 8, kSizeErrorMsg); 388499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org data[0] = val; 389499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org data[1] = val >> 8; 390499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org data[2] = val >> 16; 391499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org data[3] = val >> 24; 392499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org data[4] = val >> 32; 393499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org data[5] = val >> 40; 394499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org data[6] = val >> 48; 395499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org data[7] = val >> 56; 396499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org } 397499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org}; 398499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org 399499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org} // namespace webrtc 400499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org 401499631c1e4ad2672a333898e652d905c372793a1sprang@webrtc.org#endif // WEBRTC_MODULES_RTP_RTCP_SOURCE_BYTE_IO_H_ 402