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