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 }