root/ext/binary/binary.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. Scm_ReadBinaryUint8
  2. Scm_ReadBinarySint8
  3. Scm_WriteBinaryUint8
  4. Scm_WriteBinarySint8
  5. getbytes
  6. Scm_ReadBinaryUint16
  7. Scm_ReadBinarySint16
  8. Scm_ReadBinaryUint32
  9. Scm_ReadBinarySint32
  10. Scm_ReadBinaryUint64
  11. Scm_ReadBinarySint64
  12. Scm_ReadBinaryFloat
  13. Scm_ReadBinaryDouble
  14. Scm_WriteBinaryUint16
  15. Scm_WriteBinarySint16
  16. Scm_WriteBinaryUint32
  17. Scm_WriteBinarySint32
  18. Scm_WriteBinaryUint64
  19. Scm_WriteBinarySint64
  20. Scm_WriteBinaryFloat
  21. Scm_WriteBinaryDouble
  22. 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 }

/* [<][>][^][v][top][bottom][index][help] */