1 /******************************************************************************* 2 3 Copyright: 4 Copyright (c) 2004 Kris Bell. 5 Some parts copyright (c) 2009-2016 dunnhumby Germany GmbH. 6 All rights reserved. 7 8 License: 9 Tango Dual License: 3-Clause BSD License / Academic Free License v3.0. 10 See LICENSE_TANGO.txt for details. 11 12 Version: 13 Initial release: October 2004 14 Feb 20th 2005 - Asm version removed by Aleksey Bobnev 15 16 Authors: Kris, Aleksey Bobnev 17 18 *******************************************************************************/ 19 20 module ocean.core.ByteSwap; 21 22 import ocean.core.BitManip; 23 import ocean.core.Verify; 24 25 /******************************************************************************* 26 27 Reverse byte order for specific datum sizes. Note that the 28 byte-swap approach avoids alignment issues, so is probably 29 faster overall than a traditional 'shift' implementation. 30 --- 31 ubyte[] x = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08]; 32 33 auto a = x.dup; 34 ByteSwap.swap16(a); 35 assert(a == [cast(ubyte) 0x02, 0x01, 0x04, 0x03, 0x06, 0x05, 0x08, 0x07]); 36 37 auto b = x.dup; 38 ByteSwap.swap32(b); 39 assert(b == [cast(ubyte) 0x04, 0x03, 0x02, 0x01, 0x08, 0x07, 0x06, 0x05]); 40 41 auto c = x.dup; 42 ByteSwap.swap64(c); 43 assert(c == [cast(ubyte) 0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01]); 44 --- 45 46 *******************************************************************************/ 47 48 struct ByteSwap 49 { 50 /*********************************************************************** 51 52 Reverses two-byte sequences. Parameter dst imples the 53 number of bytes, which should be a multiple of 2 54 55 ***********************************************************************/ 56 57 final static void swap16 (void[] dst) 58 { 59 swap16 (dst.ptr, dst.length); 60 } 61 62 /*********************************************************************** 63 64 Reverses four-byte sequences. Parameter dst implies the 65 number of bytes, which should be a multiple of 4 66 67 ***********************************************************************/ 68 69 final static void swap32 (void[] dst) 70 { 71 swap32 (dst.ptr, dst.length); 72 } 73 74 /*********************************************************************** 75 76 Reverse eight-byte sequences. Parameter dst implies the 77 number of bytes, which should be a multiple of 8 78 79 ***********************************************************************/ 80 81 final static void swap64 (void[] dst) 82 { 83 swap64 (dst.ptr, dst.length); 84 } 85 86 /*********************************************************************** 87 88 Reverse ten-byte sequences. Parameter dst implies the 89 number of bytes, which should be a multiple of 10 90 91 ***********************************************************************/ 92 93 final static void swap80 (void[] dst) 94 { 95 swap80 (dst.ptr, dst.length); 96 } 97 98 /*********************************************************************** 99 100 Reverses two-byte sequences. Parameter bytes specifies the 101 number of bytes, which should be a multiple of 2 102 103 ***********************************************************************/ 104 105 final static void swap16 (void *dst, size_t bytes) 106 { 107 verify((bytes & 0x01) is 0); 108 109 auto p = cast(ubyte*) dst; 110 while (bytes) 111 { 112 ubyte b = p[0]; 113 p[0] = p[1]; 114 p[1] = b; 115 116 p += short.sizeof; 117 bytes -= short.sizeof; 118 } 119 } 120 121 /*********************************************************************** 122 123 Reverses four-byte sequences. Parameter bytes specifies the 124 number of bytes, which should be a multiple of 4 125 126 ***********************************************************************/ 127 128 final static void swap32 (void *dst, size_t bytes) 129 { 130 verify((bytes & 0x03) is 0); 131 132 auto p = cast(uint*) dst; 133 while (bytes) 134 { 135 *p = bswap(*p); 136 ++p; 137 bytes -= int.sizeof; 138 } 139 } 140 141 /*********************************************************************** 142 143 Reverse eight-byte sequences. Parameter bytes specifies the 144 number of bytes, which should be a multiple of 8 145 146 ***********************************************************************/ 147 148 final static void swap64 (void *dst, size_t bytes) 149 { 150 verify((bytes & 0x07) is 0); 151 152 auto p = cast(uint*) dst; 153 while (bytes) 154 { 155 uint i = p[0]; 156 p[0] = bswap(p[1]); 157 p[1] = bswap(i); 158 159 p += (long.sizeof / int.sizeof); 160 bytes -= long.sizeof; 161 } 162 } 163 164 /*********************************************************************** 165 166 Reverse ten-byte sequences. Parameter bytes specifies the 167 number of bytes, which should be a multiple of 10 168 169 ***********************************************************************/ 170 171 final static void swap80 (void *dst, size_t bytes) 172 { 173 verify((bytes % 10) is 0); 174 175 auto p = cast(ubyte*) dst; 176 while (bytes) 177 { 178 ubyte b = p[0]; 179 p[0] = p[9]; 180 p[9] = b; 181 182 b = p[1]; 183 p[1] = p[8]; 184 p[8] = b; 185 186 b = p[2]; 187 p[2] = p[7]; 188 p[7] = b; 189 190 b = p[3]; 191 p[3] = p[6]; 192 p[6] = b; 193 194 b = p[4]; 195 p[4] = p[5]; 196 p[5] = b; 197 198 p += 10; 199 bytes -= 10; 200 } 201 } 202 }