1 /* Copyright (c) 2003-2004, Roger Dingledine
2 * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
3 * Copyright (c) 2007-2021, The Tor Project, Inc. */
4 /* See LICENSE for licensing information */
5
6 #ifndef TOR_BYTES_H
7 #define TOR_BYTES_H
8
9 /**
10 * \file bytes.h
11 *
12 * \brief Inline functions for reading and writing multibyte values from
13 * the middle of strings, and for manipulating byte order.
14 **/
15
16 #include <string.h>
17 #include "lib/cc/torint.h"
18
19 /**
20 * Read an 8-bit from <b>cp</b>.
21 */
22 static inline uint8_t
get_uint8(const void * cp)23 get_uint8(const void *cp)
24 {
25 return *(const uint8_t*)(cp);
26 }
27 /**
28 * Store an 8-bit value from <b>v</b> to <b>cp</b>.
29 */
30 static inline void
set_uint8(void * cp,uint8_t v)31 set_uint8(void *cp, uint8_t v)
32 {
33 *(uint8_t*)cp = v;
34 }
35
36 /**
37 * Read a 16-bit value beginning at <b>cp</b>. Equivalent to
38 * *(uint16_t*)(cp), but will not cause segfaults on platforms that forbid
39 * unaligned memory access.
40 */
41 static inline uint16_t
get_uint16(const void * cp)42 get_uint16(const void *cp)
43 {
44 uint16_t v;
45 memcpy(&v,cp,2);
46 return v;
47 }
48 /**
49 * Read a 32-bit value beginning at <b>cp</b>. Equivalent to
50 * *(uint32_t*)(cp), but will not cause segfaults on platforms that forbid
51 * unaligned memory access.
52 */
53 static inline uint32_t
get_uint32(const void * cp)54 get_uint32(const void *cp)
55 {
56 uint32_t v;
57 memcpy(&v,cp,4);
58 return v;
59 }
60 /**
61 * Read a 64-bit value beginning at <b>cp</b>. Equivalent to
62 * *(uint64_t*)(cp), but will not cause segfaults on platforms that forbid
63 * unaligned memory access.
64 */
65 static inline uint64_t
get_uint64(const void * cp)66 get_uint64(const void *cp)
67 {
68 uint64_t v;
69 memcpy(&v,cp,8);
70 return v;
71 }
72
73 /**
74 * Set a 16-bit value beginning at <b>cp</b> to <b>v</b>. Equivalent to
75 * *(uint16_t*)(cp) = v, but will not cause segfaults on platforms that forbid
76 * unaligned memory access. */
77 static inline void
set_uint16(void * cp,uint16_t v)78 set_uint16(void *cp, uint16_t v)
79 {
80 memcpy(cp,&v,2);
81 }
82 /**
83 * Set a 32-bit value beginning at <b>cp</b> to <b>v</b>. Equivalent to
84 * *(uint32_t*)(cp) = v, but will not cause segfaults on platforms that forbid
85 * unaligned memory access. */
86 static inline void
set_uint32(void * cp,uint32_t v)87 set_uint32(void *cp, uint32_t v)
88 {
89 memcpy(cp,&v,4);
90 }
91 /**
92 * Set a 64-bit value beginning at <b>cp</b> to <b>v</b>. Equivalent to
93 * *(uint64_t*)(cp) = v, but will not cause segfaults on platforms that forbid
94 * unaligned memory access. */
95 static inline void
set_uint64(void * cp,uint64_t v)96 set_uint64(void *cp, uint64_t v)
97 {
98 memcpy(cp,&v,8);
99 }
100
101 #if defined(WORDS_BIGENDIAN)
102 static inline uint16_t
tor_htons(uint32_t a)103 tor_htons(uint32_t a)
104 {
105 return a;
106 }
107
108 static inline uint16_t
tor_ntohs(uint64_t a)109 tor_ntohs(uint64_t a)
110 {
111 return a;
112 }
113
114 static inline uint32_t
tor_htonl(uint32_t a)115 tor_htonl(uint32_t a)
116 {
117 return a;
118 }
119
120 static inline uint32_t
tor_ntohl(uint64_t a)121 tor_ntohl(uint64_t a)
122 {
123 return a;
124 }
125
126 static inline uint64_t
tor_htonll(uint64_t a)127 tor_htonll(uint64_t a)
128 {
129 return a;
130 }
131
132 static inline uint64_t
tor_ntohll(uint64_t a)133 tor_ntohll(uint64_t a)
134 {
135 return a;
136 }
137 #else /* !defined(WORDS_BIGENDIAN) */
138 /**
139 * Convert a 16-bit value from host order to network order (big-endian).
140 **/
141 static inline uint16_t
tor_htons(uint16_t a)142 tor_htons(uint16_t a)
143 {
144 /* Our compilers will indeed recognize this as bswap. */
145 return
146 ((a & 0x00ff) << 8) |
147 ((a & 0xff00) >> 8);
148 }
149
150 /**
151 * Convert a 16-bit value from network order (big-endian) to host order.
152 **/
153 static inline uint16_t
tor_ntohs(uint16_t a)154 tor_ntohs(uint16_t a)
155 {
156 return tor_htons(a);
157 }
158
159 /**
160 * Convert a 32-bit value from host order to network order (big-endian).
161 **/
162 static inline uint32_t
tor_htonl(uint32_t a)163 tor_htonl(uint32_t a)
164 {
165 /* Our compilers will indeed recognize this as bswap. */
166 return
167 ((a & 0x000000ff) <<24) |
168 ((a & 0x0000ff00) << 8) |
169 ((a & 0x00ff0000) >> 8) |
170 ((a & 0xff000000) >>24);
171 }
172
173 /**
174 * Convert a 32-bit value from network order (big-endian) to host order.
175 **/
176 static inline uint32_t
tor_ntohl(uint32_t a)177 tor_ntohl(uint32_t a)
178 {
179 return tor_htonl(a);
180 }
181
182 /** Return a uint64_t value from <b>a</b> in network byte order. */
183 static inline uint64_t
tor_htonll(uint64_t a)184 tor_htonll(uint64_t a)
185 {
186 /* Little endian. The worst... */
187 return tor_htonl((uint32_t)(a>>32)) |
188 (((uint64_t)tor_htonl((uint32_t)a))<<32);
189 }
190
191 /** Return a uint64_t value from <b>a</b> in host byte order. */
192 static inline uint64_t
tor_ntohll(uint64_t a)193 tor_ntohll(uint64_t a)
194 {
195 return tor_htonll(a);
196 }
197 #endif /* defined(WORDS_BIGENDIAN) */
198
199 #endif /* !defined(TOR_BYTES_H) */
200