1 /*
2 * libjingle
3 * Copyright 2004--2005, Google Inc.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright notice,
11 * this list of conditions and the following disclaimer in the documentation
12 * and/or other materials provided with the distribution.
13 * 3. The name of the author may not be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
19 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28 #ifndef TALK_BASE_BYTEORDER_H__
29 #define TALK_BASE_BYTEORDER_H__
30
31 #ifdef POSIX
32 #include <arpa/inet.h>
33 #endif
34
35 #ifdef WIN32
36 #include <winsock2.h>
37 #endif
38
39 #include "talk/base/basictypes.h"
40
41 namespace talk_base {
42
43 // Reading and writing of little and big-endian numbers from memory
44 // TODO: Add HostEndian #defines (HE)
45 // TODO: Consider NetworkEndian as synonym for BigEndian, for clarity in use.
46 // TODO: Consider creating optimized versions, such as direct read/writes of
47 // integers in host-endian format, when the platform supports it.
48
Set8(void * memory,size_t offset,uint8 v)49 inline void Set8(void* memory, size_t offset, uint8 v) {
50 static_cast<uint8*>(memory)[offset] = v;
51 }
Get8(const void * memory,size_t offset)52 inline uint8 Get8(const void* memory, size_t offset) {
53 return static_cast<const uint8*>(memory)[offset];
54 }
55
SetBE16(void * memory,uint16 v)56 inline void SetBE16(void* memory, uint16 v) {
57 Set8(memory, 0, static_cast<uint8>(v >> 8));
58 Set8(memory, 1, static_cast<uint8>(v >> 0));
59 }
SetBE32(void * memory,uint32 v)60 inline void SetBE32(void* memory, uint32 v) {
61 Set8(memory, 0, static_cast<uint8>(v >> 24));
62 Set8(memory, 1, static_cast<uint8>(v >> 16));
63 Set8(memory, 2, static_cast<uint8>(v >> 8));
64 Set8(memory, 3, static_cast<uint8>(v >> 0));
65 }
SetBE64(void * memory,uint64 v)66 inline void SetBE64(void* memory, uint64 v) {
67 Set8(memory, 0, static_cast<uint8>(v >> 56));
68 Set8(memory, 1, static_cast<uint8>(v >> 48));
69 Set8(memory, 2, static_cast<uint8>(v >> 40));
70 Set8(memory, 3, static_cast<uint8>(v >> 32));
71 Set8(memory, 4, static_cast<uint8>(v >> 24));
72 Set8(memory, 5, static_cast<uint8>(v >> 16));
73 Set8(memory, 6, static_cast<uint8>(v >> 8));
74 Set8(memory, 7, static_cast<uint8>(v >> 0));
75 }
GetBE16(const void * memory)76 inline uint16 GetBE16(const void* memory) {
77 return (static_cast<uint16>(Get8(memory, 0)) << 8)
78 | (static_cast<uint16>(Get8(memory, 1)) << 0);
79 }
GetBE32(const void * memory)80 inline uint32 GetBE32(const void* memory) {
81 return (static_cast<uint32>(Get8(memory, 0)) << 24)
82 | (static_cast<uint32>(Get8(memory, 1)) << 16)
83 | (static_cast<uint32>(Get8(memory, 2)) << 8)
84 | (static_cast<uint32>(Get8(memory, 3)) << 0);
85 }
GetBE64(const void * memory)86 inline uint64 GetBE64(const void* memory) {
87 return (static_cast<uint64>(Get8(memory, 0)) << 56)
88 | (static_cast<uint64>(Get8(memory, 1)) << 48)
89 | (static_cast<uint64>(Get8(memory, 2)) << 40)
90 | (static_cast<uint64>(Get8(memory, 3)) << 32)
91 | (static_cast<uint64>(Get8(memory, 4)) << 24)
92 | (static_cast<uint64>(Get8(memory, 5)) << 16)
93 | (static_cast<uint64>(Get8(memory, 6)) << 8)
94 | (static_cast<uint64>(Get8(memory, 7)) << 0);
95 }
96
SetLE16(void * memory,uint16 v)97 inline void SetLE16(void* memory, uint16 v) {
98 Set8(memory, 1, static_cast<uint8>(v >> 8));
99 Set8(memory, 0, static_cast<uint8>(v >> 0));
100 }
SetLE32(void * memory,uint32 v)101 inline void SetLE32(void* memory, uint32 v) {
102 Set8(memory, 3, static_cast<uint8>(v >> 24));
103 Set8(memory, 2, static_cast<uint8>(v >> 16));
104 Set8(memory, 1, static_cast<uint8>(v >> 8));
105 Set8(memory, 0, static_cast<uint8>(v >> 0));
106 }
SetLE64(void * memory,uint64 v)107 inline void SetLE64(void* memory, uint64 v) {
108 Set8(memory, 7, static_cast<uint8>(v >> 56));
109 Set8(memory, 6, static_cast<uint8>(v >> 48));
110 Set8(memory, 5, static_cast<uint8>(v >> 40));
111 Set8(memory, 4, static_cast<uint8>(v >> 32));
112 Set8(memory, 3, static_cast<uint8>(v >> 24));
113 Set8(memory, 2, static_cast<uint8>(v >> 16));
114 Set8(memory, 1, static_cast<uint8>(v >> 8));
115 Set8(memory, 0, static_cast<uint8>(v >> 0));
116 }
GetLE16(const void * memory)117 inline uint16 GetLE16(const void* memory) {
118 return (static_cast<uint16>(Get8(memory, 1)) << 8)
119 | (static_cast<uint16>(Get8(memory, 0)) << 0);
120 }
GetLE32(const void * memory)121 inline uint32 GetLE32(const void* memory) {
122 return (static_cast<uint32>(Get8(memory, 3)) << 24)
123 | (static_cast<uint32>(Get8(memory, 2)) << 16)
124 | (static_cast<uint32>(Get8(memory, 1)) << 8)
125 | (static_cast<uint32>(Get8(memory, 0)) << 0);
126 }
GetLE64(const void * memory)127 inline uint64 GetLE64(const void* memory) {
128 return (static_cast<uint64>(Get8(memory, 7)) << 56)
129 | (static_cast<uint64>(Get8(memory, 6)) << 48)
130 | (static_cast<uint64>(Get8(memory, 5)) << 40)
131 | (static_cast<uint64>(Get8(memory, 4)) << 32)
132 | (static_cast<uint64>(Get8(memory, 3)) << 24)
133 | (static_cast<uint64>(Get8(memory, 2)) << 16)
134 | (static_cast<uint64>(Get8(memory, 1)) << 8)
135 | (static_cast<uint64>(Get8(memory, 0)) << 0);
136 }
137
138 // Check if the current host is big endian.
IsHostBigEndian()139 inline bool IsHostBigEndian() {
140 static const int number = 1;
141 return (0 == *reinterpret_cast<const char*>(&number));
142 }
143
HostToNetwork16(uint16 n)144 inline uint16 HostToNetwork16(uint16 n) {
145 return htons(n);
146 }
147
HostToNetwork32(uint32 n)148 inline uint32 HostToNetwork32(uint32 n) {
149 return htonl(n);
150 }
151
HostToNetwork64(uint64 n)152 inline uint64 HostToNetwork64(uint64 n) {
153 // If the host is little endian, GetBE64 converts n to big network endian.
154 return IsHostBigEndian() ? n : GetBE64(&n);
155 }
156
NetworkToHost16(uint16 n)157 inline uint16 NetworkToHost16(uint16 n) {
158 return ntohs(n);
159 }
160
NetworkToHost32(uint32 n)161 inline uint32 NetworkToHost32(uint32 n) {
162 return ntohl(n);
163 }
164
NetworkToHost64(uint64 n)165 inline uint64 NetworkToHost64(uint64 n) {
166 // If the host is little endian, GetBE64 converts n to little endian.
167 return IsHostBigEndian() ? n : GetBE64(&n);
168 }
169
170 } // namespace talk_base
171
172 #endif // TALK_BASE_BYTEORDER_H__
173