byte_io.h 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402
  1. /*
  2. * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
  3. *
  4. * Use of this source code is governed by a BSD-style license
  5. * that can be found in the LICENSE file in the root of the source
  6. * tree. An additional intellectual property rights grant can be found
  7. * in the file PATENTS. All contributing project authors may
  8. * be found in the AUTHORS file in the root of the source tree.
  9. */
  10. #ifndef MODULES_RTP_RTCP_SOURCE_BYTE_IO_H_
  11. #define MODULES_RTP_RTCP_SOURCE_BYTE_IO_H_
  12. // This file contains classes for reading and writing integer types from/to
  13. // byte array representations. Signed/unsigned, partial (whole byte) sizes,
  14. // and big/little endian byte order is all supported.
  15. //
  16. // Usage examples:
  17. //
  18. // uint8_t* buffer = ...;
  19. //
  20. // // Read an unsigned 4 byte integer in big endian format
  21. // uint32_t val = ByteReader<uint32_t>::ReadBigEndian(buffer);
  22. //
  23. // // Read a signed 24-bit (3 byte) integer in little endian format
  24. // int32_t val = ByteReader<int32_t, 3>::ReadLittle(buffer);
  25. //
  26. // // Write an unsigned 8 byte integer in little endian format
  27. // ByteWriter<uint64_t>::WriteLittleEndian(buffer, val);
  28. //
  29. // Write an unsigned 40-bit (5 byte) integer in big endian format
  30. // ByteWriter<uint64_t, 5>::WriteBigEndian(buffer, val);
  31. //
  32. // These classes are implemented as recursive templetizations, inteded to make
  33. // it easy for the compiler to completely inline the reading/writing.
  34. #include <stdint.h>
  35. #include <limits>
  36. namespace webrtc {
  37. // According to ISO C standard ISO/IEC 9899, section 6.2.6.2 (2), the three
  38. // representations of signed integers allowed are two's complement, one's
  39. // complement and sign/magnitude. We can detect which is used by looking at
  40. // the two last bits of -1, which will be 11 in two's complement, 10 in one's
  41. // complement and 01 in sign/magnitude.
  42. // TODO(sprang): In the unlikely event that we actually need to support a
  43. // platform that doesn't use two's complement, implement conversion to/from
  44. // wire format.
  45. // Assume the if any one signed integer type is two's complement, then all
  46. // other will be too.
  47. static_assert(
  48. (-1 & 0x03) == 0x03,
  49. "Only two's complement representation of signed integers supported.");
  50. // Plain const char* won't work for static_assert, use #define instead.
  51. #define kSizeErrorMsg "Byte size must be less than or equal to data type size."
  52. // Utility class for getting the unsigned equivalent of a signed type.
  53. template <typename T>
  54. struct UnsignedOf;
  55. // Class for reading integers from a sequence of bytes.
  56. // T = type of integer, B = bytes to read, is_signed = true if signed integer.
  57. // If is_signed is true and B < sizeof(T), sign extension might be needed.
  58. template <typename T,
  59. unsigned int B = sizeof(T),
  60. bool is_signed = std::numeric_limits<T>::is_signed>
  61. class ByteReader;
  62. // Specialization of ByteReader for unsigned types.
  63. template <typename T, unsigned int B>
  64. class ByteReader<T, B, false> {
  65. public:
  66. static T ReadBigEndian(const uint8_t* data) {
  67. static_assert(B <= sizeof(T), kSizeErrorMsg);
  68. return InternalReadBigEndian(data);
  69. }
  70. static T ReadLittleEndian(const uint8_t* data) {
  71. static_assert(B <= sizeof(T), kSizeErrorMsg);
  72. return InternalReadLittleEndian(data);
  73. }
  74. private:
  75. static T InternalReadBigEndian(const uint8_t* data) {
  76. T val(0);
  77. for (unsigned int i = 0; i < B; ++i)
  78. val |= static_cast<T>(data[i]) << ((B - 1 - i) * 8);
  79. return val;
  80. }
  81. static T InternalReadLittleEndian(const uint8_t* data) {
  82. T val(0);
  83. for (unsigned int i = 0; i < B; ++i)
  84. val |= static_cast<T>(data[i]) << (i * 8);
  85. return val;
  86. }
  87. };
  88. // Specialization of ByteReader for signed types.
  89. template <typename T, unsigned int B>
  90. class ByteReader<T, B, true> {
  91. public:
  92. typedef typename UnsignedOf<T>::Type U;
  93. static T ReadBigEndian(const uint8_t* data) {
  94. U unsigned_val = ByteReader<T, B, false>::ReadBigEndian(data);
  95. if (B < sizeof(T))
  96. unsigned_val = SignExtend(unsigned_val);
  97. return ReinterpretAsSigned(unsigned_val);
  98. }
  99. static T ReadLittleEndian(const uint8_t* data) {
  100. U unsigned_val = ByteReader<T, B, false>::ReadLittleEndian(data);
  101. if (B < sizeof(T))
  102. unsigned_val = SignExtend(unsigned_val);
  103. return ReinterpretAsSigned(unsigned_val);
  104. }
  105. private:
  106. // As a hack to avoid implementation-specific or undefined behavior when
  107. // bit-shifting or casting signed integers, read as a signed equivalent
  108. // instead and convert to signed. This is safe since we have asserted that
  109. // two's complement for is used.
  110. static T ReinterpretAsSigned(U unsigned_val) {
  111. // An unsigned value with only the highest order bit set (ex 0x80).
  112. const U kUnsignedHighestBitMask = static_cast<U>(1)
  113. << ((sizeof(U) * 8) - 1);
  114. // A signed value with only the highest bit set. Since this is two's
  115. // complement form, we can use the min value from std::numeric_limits.
  116. const T kSignedHighestBitMask = std::numeric_limits<T>::min();
  117. T val;
  118. if ((unsigned_val & kUnsignedHighestBitMask) != 0) {
  119. // Casting is only safe when unsigned value can be represented in the
  120. // signed target type, so mask out highest bit and mask it back manually.
  121. val = static_cast<T>(unsigned_val & ~kUnsignedHighestBitMask);
  122. val |= kSignedHighestBitMask;
  123. } else {
  124. val = static_cast<T>(unsigned_val);
  125. }
  126. return val;
  127. }
  128. // If number of bytes is less than native data type (eg 24 bit, in int32_t),
  129. // and the most significant bit of the actual data is set, we must sign
  130. // extend the remaining byte(s) with ones so that the correct negative
  131. // number is retained.
  132. // Ex: 0x810A0B -> 0xFF810A0B, but 0x710A0B -> 0x00710A0B
  133. static U SignExtend(const U val) {
  134. const uint8_t kMsb = static_cast<uint8_t>(val >> ((B - 1) * 8));
  135. if ((kMsb & 0x80) != 0) {
  136. // Create a mask where all bits used by the B bytes are set to one,
  137. // for instance 0x00FFFFFF for B = 3. Bit-wise invert that mask (to
  138. // (0xFF000000 in the example above) and add it to the input value.
  139. // The "B % sizeof(T)" is a workaround to undefined values warnings for
  140. // B == sizeof(T), in which case this code won't be called anyway.
  141. const U kUsedBitsMask = (1 << ((B % sizeof(T)) * 8)) - 1;
  142. return ~kUsedBitsMask | val;
  143. }
  144. return val;
  145. }
  146. };
  147. // Class for writing integers to a sequence of bytes
  148. // T = type of integer, B = bytes to write
  149. template <typename T,
  150. unsigned int B = sizeof(T),
  151. bool is_signed = std::numeric_limits<T>::is_signed>
  152. class ByteWriter;
  153. // Specialization of ByteWriter for unsigned types.
  154. template <typename T, unsigned int B>
  155. class ByteWriter<T, B, false> {
  156. public:
  157. static void WriteBigEndian(uint8_t* data, T val) {
  158. static_assert(B <= sizeof(T), kSizeErrorMsg);
  159. for (unsigned int i = 0; i < B; ++i) {
  160. data[i] = val >> ((B - 1 - i) * 8);
  161. }
  162. }
  163. static void WriteLittleEndian(uint8_t* data, T val) {
  164. static_assert(B <= sizeof(T), kSizeErrorMsg);
  165. for (unsigned int i = 0; i < B; ++i) {
  166. data[i] = val >> (i * 8);
  167. }
  168. }
  169. };
  170. // Specialization of ByteWriter for signed types.
  171. template <typename T, unsigned int B>
  172. class ByteWriter<T, B, true> {
  173. public:
  174. typedef typename UnsignedOf<T>::Type U;
  175. static void WriteBigEndian(uint8_t* data, T val) {
  176. ByteWriter<U, B, false>::WriteBigEndian(data, ReinterpretAsUnsigned(val));
  177. }
  178. static void WriteLittleEndian(uint8_t* data, T val) {
  179. ByteWriter<U, B, false>::WriteLittleEndian(data,
  180. ReinterpretAsUnsigned(val));
  181. }
  182. private:
  183. static U ReinterpretAsUnsigned(T val) {
  184. // According to ISO C standard ISO/IEC 9899, section 6.3.1.3 (1, 2) a
  185. // conversion from signed to unsigned keeps the value if the new type can
  186. // represent it, and otherwise adds one more than the max value of T until
  187. // the value is in range. For two's complement, this fortunately means
  188. // that the bit-wise value will be intact. Thus, since we have asserted that
  189. // two's complement form is actually used, a simple cast is sufficient.
  190. return static_cast<U>(val);
  191. }
  192. };
  193. // ----- Below follows specializations of UnsignedOf utility class -----
  194. template <>
  195. struct UnsignedOf<int8_t> {
  196. typedef uint8_t Type;
  197. };
  198. template <>
  199. struct UnsignedOf<int16_t> {
  200. typedef uint16_t Type;
  201. };
  202. template <>
  203. struct UnsignedOf<int32_t> {
  204. typedef uint32_t Type;
  205. };
  206. template <>
  207. struct UnsignedOf<int64_t> {
  208. typedef uint64_t Type;
  209. };
  210. // ----- Below follows specializations for unsigned, B in { 1, 2, 4, 8 } -----
  211. // TODO(sprang): Check if these actually help or if generic cases will be
  212. // unrolled to and optimized to similar performance.
  213. // Specializations for single bytes
  214. template <typename T>
  215. class ByteReader<T, 1, false> {
  216. public:
  217. static T ReadBigEndian(const uint8_t* data) {
  218. static_assert(sizeof(T) == 1, kSizeErrorMsg);
  219. return data[0];
  220. }
  221. static T ReadLittleEndian(const uint8_t* data) {
  222. static_assert(sizeof(T) == 1, kSizeErrorMsg);
  223. return data[0];
  224. }
  225. };
  226. template <typename T>
  227. class ByteWriter<T, 1, false> {
  228. public:
  229. static void WriteBigEndian(uint8_t* data, T val) {
  230. static_assert(sizeof(T) == 1, kSizeErrorMsg);
  231. data[0] = val;
  232. }
  233. static void WriteLittleEndian(uint8_t* data, T val) {
  234. static_assert(sizeof(T) == 1, kSizeErrorMsg);
  235. data[0] = val;
  236. }
  237. };
  238. // Specializations for two byte words
  239. template <typename T>
  240. class ByteReader<T, 2, false> {
  241. public:
  242. static T ReadBigEndian(const uint8_t* data) {
  243. static_assert(sizeof(T) >= 2, kSizeErrorMsg);
  244. return (data[0] << 8) | data[1];
  245. }
  246. static T ReadLittleEndian(const uint8_t* data) {
  247. static_assert(sizeof(T) >= 2, kSizeErrorMsg);
  248. return data[0] | (data[1] << 8);
  249. }
  250. };
  251. template <typename T>
  252. class ByteWriter<T, 2, false> {
  253. public:
  254. static void WriteBigEndian(uint8_t* data, T val) {
  255. static_assert(sizeof(T) >= 2, kSizeErrorMsg);
  256. data[0] = val >> 8;
  257. data[1] = val;
  258. }
  259. static void WriteLittleEndian(uint8_t* data, T val) {
  260. static_assert(sizeof(T) >= 2, kSizeErrorMsg);
  261. data[0] = val;
  262. data[1] = val >> 8;
  263. }
  264. };
  265. // Specializations for four byte words.
  266. template <typename T>
  267. class ByteReader<T, 4, false> {
  268. public:
  269. static T ReadBigEndian(const uint8_t* data) {
  270. static_assert(sizeof(T) >= 4, kSizeErrorMsg);
  271. return (Get(data, 0) << 24) | (Get(data, 1) << 16) | (Get(data, 2) << 8) |
  272. Get(data, 3);
  273. }
  274. static T ReadLittleEndian(const uint8_t* data) {
  275. static_assert(sizeof(T) >= 4, kSizeErrorMsg);
  276. return Get(data, 0) | (Get(data, 1) << 8) | (Get(data, 2) << 16) |
  277. (Get(data, 3) << 24);
  278. }
  279. private:
  280. inline static T Get(const uint8_t* data, unsigned int index) {
  281. return static_cast<T>(data[index]);
  282. }
  283. };
  284. // Specializations for four byte words.
  285. template <typename T>
  286. class ByteWriter<T, 4, false> {
  287. public:
  288. static void WriteBigEndian(uint8_t* data, T val) {
  289. static_assert(sizeof(T) >= 4, kSizeErrorMsg);
  290. data[0] = val >> 24;
  291. data[1] = val >> 16;
  292. data[2] = val >> 8;
  293. data[3] = val;
  294. }
  295. static void WriteLittleEndian(uint8_t* data, T val) {
  296. static_assert(sizeof(T) >= 4, kSizeErrorMsg);
  297. data[0] = val;
  298. data[1] = val >> 8;
  299. data[2] = val >> 16;
  300. data[3] = val >> 24;
  301. }
  302. };
  303. // Specializations for eight byte words.
  304. template <typename T>
  305. class ByteReader<T, 8, false> {
  306. public:
  307. static T ReadBigEndian(const uint8_t* data) {
  308. static_assert(sizeof(T) >= 8, kSizeErrorMsg);
  309. return (Get(data, 0) << 56) | (Get(data, 1) << 48) | (Get(data, 2) << 40) |
  310. (Get(data, 3) << 32) | (Get(data, 4) << 24) | (Get(data, 5) << 16) |
  311. (Get(data, 6) << 8) | Get(data, 7);
  312. }
  313. static T ReadLittleEndian(const uint8_t* data) {
  314. static_assert(sizeof(T) >= 8, kSizeErrorMsg);
  315. return Get(data, 0) | (Get(data, 1) << 8) | (Get(data, 2) << 16) |
  316. (Get(data, 3) << 24) | (Get(data, 4) << 32) | (Get(data, 5) << 40) |
  317. (Get(data, 6) << 48) | (Get(data, 7) << 56);
  318. }
  319. private:
  320. inline static T Get(const uint8_t* data, unsigned int index) {
  321. return static_cast<T>(data[index]);
  322. }
  323. };
  324. template <typename T>
  325. class ByteWriter<T, 8, false> {
  326. public:
  327. static void WriteBigEndian(uint8_t* data, T val) {
  328. static_assert(sizeof(T) >= 8, kSizeErrorMsg);
  329. data[0] = val >> 56;
  330. data[1] = val >> 48;
  331. data[2] = val >> 40;
  332. data[3] = val >> 32;
  333. data[4] = val >> 24;
  334. data[5] = val >> 16;
  335. data[6] = val >> 8;
  336. data[7] = val;
  337. }
  338. static void WriteLittleEndian(uint8_t* data, T val) {
  339. static_assert(sizeof(T) >= 8, kSizeErrorMsg);
  340. data[0] = val;
  341. data[1] = val >> 8;
  342. data[2] = val >> 16;
  343. data[3] = val >> 24;
  344. data[4] = val >> 32;
  345. data[5] = val >> 40;
  346. data[6] = val >> 48;
  347. data[7] = val >> 56;
  348. }
  349. };
  350. } // namespace webrtc
  351. #endif // MODULES_RTP_RTCP_SOURCE_BYTE_IO_H_