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