|
4 | 4 | #if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS |
5 | 5 |
|
6 | 6 | #include "util.h" |
| 7 | +#include <string.h> // memcpy() |
7 | 8 |
|
8 | 9 | namespace node { |
9 | 10 |
|
@@ -200,47 +201,69 @@ TypeName* Unwrap(v8::Local<v8::Object> object) { |
200 | 201 | return static_cast<TypeName*>(pointer); |
201 | 202 | } |
202 | 203 |
|
203 | | -void SwapBytes16(char* dst, const char* src, size_t size) { |
204 | | - for (size_t i = 0; i < size; i += 2) { |
205 | | - char a = src[i + 0]; |
206 | | - char b = src[i + 1]; |
207 | | - dst[i + 0] = b; |
208 | | - dst[i + 1] = a; |
| 204 | +template <typename T, typename U> |
| 205 | +bool IsAlignedTo(const U* p) { |
| 206 | + return reinterpret_cast<uintptr_t>(p) % sizeof(T) == 0; |
| 207 | +} |
| 208 | + |
| 209 | +uint16_t ByteSwap(uint16_t v) { |
| 210 | + uint16_t a = (v >> 0) & 255; |
| 211 | + uint16_t b = (v >> 8) & 255; |
| 212 | + return (a << 8) | b; |
| 213 | +} |
| 214 | + |
| 215 | +uint32_t ByteSwap(uint32_t v) { |
| 216 | + uint32_t a = (v >> 0) & 255; |
| 217 | + uint32_t b = (v >> 8) & 255; |
| 218 | + uint32_t c = (v >> 16) & 255; |
| 219 | + uint32_t d = (v >> 24) & 255; |
| 220 | + return (a << 24) | (b << 16) | (c << 8) | d; |
| 221 | +} |
| 222 | + |
| 223 | +uint64_t ByteSwap(uint64_t v) { |
| 224 | + uint64_t a = (v >> 0) & 255; |
| 225 | + uint64_t b = (v >> 8) & 255; |
| 226 | + uint64_t c = (v >> 16) & 255; |
| 227 | + uint64_t d = (v >> 24) & 255; |
| 228 | + uint64_t e = (v >> 32) & 255; |
| 229 | + uint64_t f = (v >> 40) & 255; |
| 230 | + uint64_t g = (v >> 48) & 255; |
| 231 | + uint64_t h = (v >> 56) & 255; |
| 232 | + return (a << 56) | (b << 48) | (c << 40) | (d << 32) | |
| 233 | + (e << 24) | (f << 16) | (g << 8) | h; |
| 234 | +} |
| 235 | + |
| 236 | +template <typename T> |
| 237 | +inline void DoSwapBytes(char* dst, const char* src, size_t size) { |
| 238 | + for (size_t i = 0; i < size; i += sizeof(T)) { |
| 239 | + T v; |
| 240 | + memcpy(&v, &src[i], sizeof(v)); |
| 241 | + v = ByteSwap(v); |
| 242 | + memcpy(&dst[i], &v, sizeof(v)); |
209 | 243 | } |
210 | 244 | } |
211 | 245 |
|
212 | | -void SwapBytes32(char* dst, const char* src, size_t size) { |
213 | | - for (size_t i = 0; i < size; i += 4) { |
214 | | - char a = src[i + 0]; |
215 | | - char b = src[i + 1]; |
216 | | - char c = src[i + 2]; |
217 | | - char d = src[i + 3]; |
218 | | - dst[i + 0] = d; |
219 | | - dst[i + 1] = c; |
220 | | - dst[i + 2] = b; |
221 | | - dst[i + 3] = a; |
| 246 | +template <typename T> |
| 247 | +void SwapBytes(char* dst, const char* src, size_t size) { |
| 248 | + if (src == dst && IsAlignedTo<T>(dst)) { |
| 249 | + // Hit the compiler over the head with the fact that the source |
| 250 | + // and the destination are the same and is properly aligned. |
| 251 | + DoSwapBytes<T>(dst, dst, size); |
| 252 | + } else { |
| 253 | + DoSwapBytes<T>(dst, src, size); |
222 | 254 | } |
223 | 255 | } |
224 | 256 |
|
| 257 | +void SwapBytes16(char* dst, const char* src, size_t size) { |
| 258 | + return SwapBytes<uint16_t>(dst, src, size); |
| 259 | +} |
| 260 | + |
| 261 | +void SwapBytes32(char* dst, const char* src, size_t size) { |
| 262 | + return SwapBytes<uint32_t>(dst, src, size); |
| 263 | +} |
| 264 | + |
225 | 265 | void SwapBytes64(char* dst, const char* src, size_t size) { |
226 | | - for (size_t i = 0; i < size; i += 8) { |
227 | | - char a = src[i + 0]; |
228 | | - char b = src[i + 1]; |
229 | | - char c = src[i + 2]; |
230 | | - char d = src[i + 3]; |
231 | | - char e = src[i + 4]; |
232 | | - char f = src[i + 5]; |
233 | | - char g = src[i + 6]; |
234 | | - char h = src[i + 7]; |
235 | | - dst[i + 0] = h; |
236 | | - dst[i + 1] = g; |
237 | | - dst[i + 2] = f; |
238 | | - dst[i + 3] = e; |
239 | | - dst[i + 4] = d; |
240 | | - dst[i + 5] = c; |
241 | | - dst[i + 6] = b; |
242 | | - dst[i + 7] = a; |
243 | | - } |
| 266 | + return SwapBytes<uint64_t>(dst, src, size); |
244 | 267 | } |
245 | 268 |
|
246 | 269 | char ToLower(char c) { |
|
0 commit comments