/* [<][>][^][v][top][bottom][index][help] */
DEFINITIONS
This source file includes following definitions.
- Scm_ReadBinaryUint8
- Scm_ReadBinarySint8
- Scm_WriteBinaryUint8
- Scm_WriteBinarySint8
- getbytes
- Scm_ReadBinaryUint16
- Scm_ReadBinarySint16
- Scm_ReadBinaryUint32
- Scm_ReadBinarySint32
- Scm_ReadBinaryUint64
- Scm_ReadBinarySint64
- Scm_ReadBinaryFloat
- Scm_ReadBinaryDouble
- Scm_WriteBinaryUint16
- Scm_WriteBinarySint16
- Scm_WriteBinaryUint32
- Scm_WriteBinarySint32
- Scm_WriteBinaryUint64
- Scm_WriteBinarySint64
- Scm_WriteBinaryFloat
- Scm_WriteBinaryDouble
- Scm_Init_binary
1 /*
2 * binaryio.c - Binary I/O routines
3 *
4 * Copyright (c) 2004 Shiro Kawai, All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 *
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 *
17 * 3. Neither the name of the authors nor the names of its contributors
18 * may be used to endorse or promote products derived from this
19 * software without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
27 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
28 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
29 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
30 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
31 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 *
33 * $Id: binary.c,v 1.4 2005/07/22 09:26:54 shirok Exp $
34 */
35
36 #include <gauche.h>
37 #include <gauche/extend.h>
38 #include "binary.h"
39
40 #define IPORT(var, x) \
41 do { \
42 if (SCM_FALSEP(x)) { \
43 (var) = SCM_CURIN; \
44 } else if (SCM_IPORTP(x)) { \
45 (var) = SCM_PORT(x); \
46 } else { \
47 Scm_Error("input port or #f is expected, but got: %S", x); \
48 (var) = NULL; \
49 } \
50 } while (0)
51
52 #define OPORT(var, x) \
53 do { \
54 if (SCM_FALSEP(x)) { \
55 (var) = SCM_CUROUT; \
56 } else if (SCM_OPORTP(x)) { \
57 (var) = SCM_PORT(x); \
58 } else { \
59 Scm_Error("output port or #f is expected, but got: %S", x); \
60 (var) = NULL; \
61 } \
62 } while (0)
63
64 /*
65 * uint8 and sint8 is easy; just do it here.
66 */
67 ScmObj Scm_ReadBinaryUint8(ScmObj sport, Endian endian)
68 {
69 ScmPort *iport;
70 int b;
71 IPORT(iport, sport);
72 if ((b = Scm_Getb(iport)) == EOF) return SCM_EOF;
73 else return SCM_MAKE_INT(b);
74 }
75
76 ScmObj Scm_ReadBinarySint8(ScmObj sport, Endian endian)
77 {
78 ScmPort *iport;
79 int b;
80 IPORT(iport, sport);
81 if ((b = Scm_Getb(iport)) == EOF) return SCM_EOF;
82 if (b >= 128) b -= 256;
83 return SCM_MAKE_INT(b);
84 }
85
86 void Scm_WriteBinaryUint8(ScmObj sval, ScmObj sport, Endian endian)
87 {
88 ScmPort *oport;
89 int val;
90 OPORT(oport, sport);
91 if (!SCM_INTP(sval)
92 || ((val = SCM_INT_VALUE(sval)) < 0)
93 || (val >= 256)) {
94 Scm_Error("argument out of range (uint8): %S", sval);
95 }
96 Scm_Putb(val, oport);
97 }
98
99 void Scm_WriteBinarySint8(ScmObj sval, ScmObj sport, Endian endian)
100 {
101 ScmPort *oport;
102 int val;
103 OPORT(oport, sport);
104 if (!SCM_INTP(sval)
105 || ((val = SCM_INT_VALUE(sval)) < -128)
106 || (val >= 128)) {
107 Scm_Error("argument out of range (sint8): %S", sval);
108 }
109 Scm_Putb(val, oport);
110 }
111
112 /*
113 * Readers
114 */
115
116 /* generic routine to handle byte-stream */
117 static inline int getbytes(char *buf, int len, ScmObj sport)
118 {
119 ScmPort *iport;
120 int nread = 0, r;
121 IPORT(iport, sport);
122 while (nread < len) {
123 r = Scm_Getz(buf, len-nread, iport);
124 if (r <= 0) return EOF;
125 nread += r;
126 buf += r;
127 }
128 return nread;
129 }
130
131 #define CSWAP(buf, tmp, n, m) (tmp=buf[n], buf[n]=buf[m], buf[m]=tmp)
132
133 #define SWAP2() \
134 do { char z; if (SWAP_REQUIRED(endian)) CSWAP(v.buf, z, 0, 1); } while (0)
135
136 #define SWAP4() \
137 do { char z; \
138 if (SWAP_REQUIRED(endian)) { \
139 CSWAP(v.buf, z, 0, 3); \
140 CSWAP(v.buf, z, 1, 2); \
141 } \
142 } while (0)
143
144 #define SWAP8() \
145 do { char z; \
146 if (SWAP_REQUIRED(endian)) { \
147 CSWAP(v.buf, z, 0, 7); \
148 CSWAP(v.buf, z, 1, 6); \
149 CSWAP(v.buf, z, 2, 5); \
150 CSWAP(v.buf, z, 3, 4); \
151 } \
152 } while (0)
153
154 /* ARM uses mixed endian for double. [01234567] -> [32107654].
155 For the time being, we won't support I/O for native ARM format.
156 Bytes are swaped either for pure big-endian or pure little-endian. */
157 #ifdef DOUBLE_ARMENDIAN
158 #define SWAPD() \
159 do { char z; \
160 if (endian == SCM_BE) { \
161 CSWAP(v.buf, z, 0, 3); \
162 CSWAP(v.buf, z, 1, 2); \
163 CSWAP(v.buf, z, 4, 7); \
164 CSWAP(v.buf, z, 5, 6); \
165 } else { \
166 CSWAP(v.buf, z, 0, 4); \
167 CSWAP(v.buf, z, 1, 5); \
168 CSWAP(v.buf, z, 2, 6); \
169 CSWAP(v.buf, z, 3, 7); \
170 } \
171 } while (0)
172 #else /*!DOUBLE_ARMENDIAN*/
173 #define SWAPD() \
174 do { char z; \
175 if (SWAP_REQUIRED(endian)) { \
176 CSWAP(v.buf, z, 0, 7); \
177 CSWAP(v.buf, z, 1, 6); \
178 CSWAP(v.buf, z, 2, 5); \
179 CSWAP(v.buf, z, 3, 4); \
180 } \
181 } while (0)
182 #endif /*!DOUBLE_ARMENDIAN*/
183
184
185
186 ScmObj Scm_ReadBinaryUint16(ScmObj sport, Endian endian)
187 {
188 union { char buf[2]; unsigned short val; } v;
189 if (getbytes(v.buf, 2, sport) == EOF) return SCM_EOF;
190 SWAP2();
191 return SCM_MAKE_INT(v.val);
192 }
193
194 ScmObj Scm_ReadBinarySint16(ScmObj sport, Endian endian)
195 {
196 union { char buf[2]; short val; } v;
197 if (getbytes(v.buf, 2, sport) == EOF) return SCM_EOF;
198 SWAP2();
199 return SCM_MAKE_INT(v.val);
200 }
201
202 ScmObj Scm_ReadBinaryUint32(ScmObj sport, Endian endian)
203 {
204 union { char buf[4]; ScmUInt32 val; } v;
205 if (getbytes(v.buf, 4, sport) == EOF) return SCM_EOF;
206 SWAP4();
207 return Scm_MakeIntegerFromUI(v.val);
208 }
209
210 ScmObj Scm_ReadBinarySint32(ScmObj sport, Endian endian)
211 {
212 union { char buf[4]; ScmInt32 val; } v;
213 if (getbytes(v.buf, 4, sport) == EOF) return SCM_EOF;
214 SWAP4();
215 return Scm_MakeInteger(v.val);
216 }
217
218 ScmObj Scm_ReadBinaryUint64(ScmObj sport, Endian endian)
219 {
220 union { char buf[8]; ScmUInt64 val; } v;
221 if (getbytes(v.buf, 8, sport) == EOF) return SCM_EOF;
222 SWAP8();
223 return Scm_MakeIntegerU64(v.val);
224 }
225
226 ScmObj Scm_ReadBinarySint64(ScmObj sport, Endian endian)
227 {
228 union { char buf[8]; ScmInt64 val; } v;
229 if (getbytes(v.buf, 8, sport) == EOF) return SCM_EOF;
230 SWAP8();
231 return Scm_MakeInteger64(v.val);
232 }
233
234 ScmObj Scm_ReadBinaryFloat(ScmObj sport, Endian endian)
235 {
236 union { char buf[4]; float val; } v;
237 if (getbytes(v.buf, 4, sport) == EOF) return SCM_EOF;
238 SWAP4();
239 return Scm_MakeFlonum((double)v.val);
240 }
241
242 ScmObj Scm_ReadBinaryDouble(ScmObj sport, Endian endian)
243 {
244 union { char buf[8]; double val;} v;
245 if (getbytes(v.buf, 8, sport) == EOF) return SCM_EOF;
246 SWAPD();
247 return Scm_MakeFlonum(v.val);
248 }
249
250 /*
251 * Writers
252 */
253
254 void Scm_WriteBinaryUint16(ScmObj sval, ScmObj sport, Endian endian)
255 {
256 union { char buf[2]; u_short val; } v;
257 long vv;
258 ScmPort *oport;
259 OPORT(oport, sport);
260 if (!SCM_INTP(sval)
261 || ((vv = SCM_INT_VALUE(sval)) < 0)
262 || (vv >= 65536)) {
263 Scm_Error("argument out of range (uint16): %S", sval);
264 }
265 v.val = vv;
266 SWAP2();
267 Scm_Putz(v.buf, 2, oport);
268 }
269
270 void Scm_WriteBinarySint16(ScmObj sval, ScmObj sport, Endian endian)
271 {
272 union { char buf[2]; short val; } v;
273 long vv;
274 ScmPort *oport;
275 OPORT(oport, sport);
276 if (!SCM_INTP(sval)
277 || ((vv = SCM_INT_VALUE(sval)) < -32768)
278 || (vv >= 32768)) {
279 Scm_Error("argument out of range (sint16): %S", sval);
280 }
281 v.val = vv;
282 SWAP2();
283 Scm_Putz(v.buf, 2, oport);
284 }
285
286 void Scm_WriteBinaryUint32(ScmObj sval, ScmObj sport, Endian endian)
287 {
288 union { char buf[4]; ScmUInt32 val; } v;
289 ScmPort *oport;
290 OPORT(oport, sport);
291 v.val = Scm_GetIntegerU32Clamp(sval, FALSE, FALSE);
292 SWAP4();
293 Scm_Putz(v.buf, 4, oport);
294 }
295
296 void Scm_WriteBinarySint32(ScmObj sval, ScmObj sport, Endian endian)
297 {
298 union { char buf[4]; ScmInt32 val; } v;
299 ScmPort *oport;
300 OPORT(oport, sport);
301 v.val = Scm_GetInteger32Clamp(sval, FALSE, FALSE);
302 SWAP4();
303 Scm_Putz(v.buf, 4, oport);
304 }
305
306 void Scm_WriteBinaryUint64(ScmObj sval, ScmObj sport, Endian endian)
307 {
308 union { char buf[8]; ScmUInt64 val; } v;
309 ScmPort *oport;
310 OPORT(oport, sport);
311 v.val = Scm_GetIntegerU64Clamp(sval, FALSE, FALSE);
312 SWAP8();
313 Scm_Putz(v.buf, 8, oport);
314 }
315
316 void Scm_WriteBinarySint64(ScmObj sval, ScmObj sport, Endian endian)
317 {
318 union { char buf[8]; ScmInt64 val; } v;
319 ScmPort *oport;
320 OPORT(oport, sport);
321 v.val = Scm_GetInteger64Clamp(sval, FALSE, FALSE);
322 SWAP8();
323 Scm_Putz(v.buf, 8, oport);
324 }
325
326 void Scm_WriteBinaryFloat(ScmObj sval, ScmObj sport, Endian endian)
327 {
328 union { char buf[4]; float val; } v;
329 ScmPort *oport;
330 OPORT(oport, sport);
331 v.val = (float)Scm_GetDouble(sval);
332 SWAP4();
333 Scm_Putz(v.buf, 4, oport);
334 }
335
336 void Scm_WriteBinaryDouble(ScmObj sval, ScmObj sport, Endian endian)
337 {
338 union { char buf[8]; double val; } v;
339 ScmPort *oport;
340 OPORT(oport, sport);
341 v.val = Scm_GetDouble(sval);
342 SWAPD();
343 Scm_Putz(v.buf, 8, oport);
344 }
345
346
347 /*
348 * Init
349 */
350
351
352 extern void Scm_Init_binarylib(ScmModule *mod);
353
354 void Scm_Init_binary(void)
355 {
356 ScmModule *mod_io = SCM_FIND_MODULE("binary.io", SCM_FIND_MODULE_CREATE);
357 SCM_INIT_EXTENSION(binary);
358 Scm_Init_binarylib(mod_io);
359 }