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