00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include <cstring>
00021 #include <stdexcept>
00022
00023 #include "binio.h"
00024
00025 #if BINIO_WITH_MATH
00026
00027 #include <cmath>
00028
00029 #ifdef __QNXNTO__
00030 #define pow std::powf
00031 #endif // __QNXNTO__
00032
00033
00034 #ifndef HUGE_VAL
00035 # define HUGE_VAL HUGE
00036 #endif
00037
00038 #endif
00039
00040
00041
00042 #if BINIO_ENABLE_STRING
00043
00044 #define STRINGBUFSIZE 256
00045 #endif
00046
00047
00048
00049 const binio::Flags binio::system_flags = binio::detect_system_flags();
00050
00051 binio::Flags binio::detect_system_flags()
00052 {
00053 Flags f = 0;
00054
00055
00056 union {
00057 int word;
00058 Byte byte;
00059 } endian_test;
00060
00061 endian_test.word = 1;
00062 if(endian_test.byte != 1) f |= BigEndian;
00063
00064
00065 float fl = 6.5;
00066 Byte *dat = (Byte *)&fl;
00067
00068 if(sizeof(float) == 4 && sizeof(double) == 8)
00069 {
00070 if(f & BigEndian)
00071 {
00072 if(dat[0] == 0x40 && dat[1] == 0xD0 && !dat[2] && !dat[3])
00073 f |= FloatIEEE;
00074 }
00075 else
00076 {
00077 if(dat[3] == 0x40 && dat[2] == 0xD0 && !dat[1] && !dat[0])
00078 f |= FloatIEEE;
00079 }
00080 }
00081
00082 return f;
00083 }
00084
00085 binio::binio()
00086 : my_flags(system_flags), err(NoError)
00087 {
00088 }
00089
00090 binio::~binio()
00091 {
00092 }
00093
00094 void binio::setFlag(Flag f, bool set)
00095 {
00096 if(set)
00097 my_flags |= f;
00098 else
00099 my_flags &= !f;
00100 }
00101
00102 bool binio::getFlag(Flag f)
00103 {
00104 return (my_flags & f ? true : false);
00105 }
00106
00107 binio::Error binio::error()
00108 {
00109 Error e = err;
00110
00111 err = NoError;
00112 return e;
00113 }
00114
00115 bool binio::eof()
00116 {
00117 return (err & Eof ? true : false);
00118 }
00119
00120
00121
00122 binistream::binistream()
00123 {
00124 }
00125
00126 binistream::~binistream()
00127 {
00128 }
00129
00130 binistream::Int binistream::readInt(unsigned int size)
00131 {
00132 unsigned int i;
00133 Int val = 0, in;
00134
00135
00136 if(size > sizeof(Int)) {
00137 err |= Unsupported;
00138 throw runtime_error ("The size of the integer to be read exceeds our system's biggest type");
00139 return 0;
00140 }
00141
00142 for(i = 0; i < size; i++) {
00143 in = getByte();
00144 if(getFlag(BigEndian))
00145 val <<= 8;
00146 else
00147 in <<= i * 8;
00148 val |= in;
00149 }
00150
00151 return val;
00152 }
00153
00154 binistream::Float binistream::readFloat(FType ft)
00155 {
00156 if(getFlag(FloatIEEE))
00157 {
00158
00159
00160 unsigned int i=0;
00161 unsigned int size=0;
00162 Byte in[8];
00163 bool swap;
00164
00165
00166 switch(ft) {
00167 case Single: size = 4; break;
00168 case Double: size = 8; break;
00169 }
00170
00171
00172 if(system_flags & FloatIEEE)
00173 swap = getFlag(BigEndian) ^ (system_flags & BigEndian);
00174 else
00175 swap = !getFlag(BigEndian);
00176
00177 if (!swap && ((size == sizeof (float)) || (size == sizeof (double))))
00178 {
00179 if (size == 4)
00180 {
00181 float f;
00182 getRaw ((char *)&f, size);
00183 return (Float)f;
00184 }
00185 else
00186 {
00187 double d;
00188 getRaw ((char *)&d, size);
00189 return (Float)d;
00190 }
00191 }
00192 else
00193 {
00194
00195 for(i = 0; i < size; i++)
00196 if(swap)
00197 in[size - i - 1] = getByte();
00198 else
00199 in[i] = getByte();
00200
00201 if(system_flags & FloatIEEE) {
00202
00203 switch(ft) {
00204 case Single: return *(float *)in;
00205 case Double: return *(double *)in;
00206 }
00207 } else {
00208 switch(ft) {
00209 case Single: return ieee_single2float(in);
00210 case Double: return ieee_double2float(in);
00211 }
00212 }
00213 }
00214 }
00215
00216
00217 err |= Unsupported; return 0.0;
00218 }
00219
00220 binistream::Float binistream::ieee_single2float(Byte *data)
00221 {
00222 signed int sign = data[0] >> 7 ? -1 : 1;
00223 unsigned int exp = ((data[0] << 1) & 0xff) | ((data[1] >> 7) & 1),
00224 fracthi7 = data[1] & 0x7f;
00225 Float fract = fracthi7 * 65536.0 + data[2] * 256.0 + data[3];
00226
00227
00228 if(!exp && !fracthi7 && !data[2] && !data[3]) return sign * 0.0;
00229
00230
00231 if(exp == 255)
00232 {
00233 if(!fracthi7 && !data[2] && !data[3])
00234 {
00235 #ifdef HUGE_VAL
00236 if(sign == -1) return -HUGE_VAL; else return HUGE_VAL;
00237 #else
00238 err |= Unsupported;
00239 if(sign == -1) return -1.0; else return 1.0;
00240 #endif
00241 }
00242 else
00243 {
00244 #ifdef NAN
00245 return NAN;
00246 #else
00247 err |= Unsupported; return 0.0;
00248 #endif
00249 }
00250 }
00251
00252 if(!exp)
00253 return sign * pow(2, -126.) * fract * pow(2, -23.);
00254 else
00255 return sign * pow(2, exp - 127.) * (fract * pow(2, -23.) + 1);
00256
00257 err |= Fatal; return 0.0;
00258 }
00259
00260 binistream::Float binistream::ieee_double2float(Byte *data)
00261 {
00262 signed int sign = data[0] >> 7 ? -1 : 1;
00263 unsigned int exp = ((unsigned int)(data[0] & 0x7f) << 4) | (data[1] >> 4),
00264 fracthi4 = data[1] & 0xf;
00265 Float fract = fracthi4 * pow(2, 48.) + data[2] * pow(2, 40.) + data[3] *
00266 pow(2, 32.) + data[4] * pow(2, 24.) + data[5] * pow(2, 16.) + data[6] *
00267 pow(2, 8.) + data[7];
00268
00269
00270 if(!exp && !fracthi4 && !data[2] && !data[3] && !data[4] && !data[5] &&
00271 !data[6] && !data[7]) return sign * 0.0;
00272
00273
00274 if(exp == 2047)
00275 {
00276 if(!fracthi4 && !data[2] && !data[3] && !data[4] && !data[5] && !data[6] &&
00277 !data[7])
00278 {
00279 #ifdef HUGE_VAL
00280 if(sign == -1) return -HUGE_VAL; else return HUGE_VAL;
00281 #else
00282 err |= Unsupported;
00283 if(sign == -1) return -1.0; else return 1.0;
00284 #endif
00285 }
00286 else
00287 {
00288 #ifdef NAN
00289 return NAN;
00290 #else
00291 err |= Unsupported; return 0.0;
00292 #endif
00293 }
00294 }
00295
00296 if(!exp)
00297 return sign * pow(2, -1022.) * fract * pow(2, -52.);
00298 else
00299 return sign * pow(2, exp - 1023.) * (fract * pow(2, -52.) + 1);
00300
00301 err |= Fatal; return 0.0;
00302 }
00303
00304 #if !BINIO_WITH_MATH
00305 binio::Float binio::pow(Float base, signed int exp)
00306
00307
00308
00309
00310 {
00311 int i;
00312 Float val = base;
00313
00314 if(!exp) return 1.0;
00315
00316 for(i = 1; i < (exp < 0 ? -exp : exp); i++)
00317 val *= base;
00318
00319 if(exp < 0) val = 1.0 / val;
00320
00321 return val;
00322 }
00323 #endif
00324
00325 unsigned long binistream::readString(char *str, unsigned long maxlen)
00326 {
00327 unsigned long i;
00328
00329 for(i = 0; i < maxlen; i++) {
00330 str[i] = (char)getByte();
00331 if(err) { str[i] = '\0'; return i; }
00332 }
00333
00334 return maxlen;
00335 }
00336
00337 unsigned long binistream::readString(char *str, unsigned long maxlen,
00338 const char delim)
00339 {
00340 unsigned long i;
00341
00342 for(i = 0; i < maxlen; i++) {
00343 str[i] = (char)getByte();
00344 if(str[i] == delim || err) { str[i] = '\0'; return i; }
00345 }
00346
00347 str[maxlen] = '\0';
00348 return maxlen;
00349 }
00350
00351 #if BINIO_ENABLE_STRING
00352 std::string binistream::readString(const char delim)
00353 {
00354 char buf[STRINGBUFSIZE + 1];
00355 std::string tempstr;
00356 unsigned long read;
00357
00358 do {
00359 read = readString(buf, STRINGBUFSIZE, delim);
00360 tempstr.append(buf, read);
00361 } while(read == STRINGBUFSIZE);
00362
00363 return tempstr;
00364 }
00365 #endif
00366
00367 binistream::Int binistream::peekInt(unsigned int size)
00368 {
00369 Int val = readInt(size);
00370 if(!err) seek(-(long)size, Add);
00371 return val;
00372 }
00373
00374 binistream::Float binistream::peekFloat(FType ft)
00375 {
00376 Float val = readFloat(ft);
00377
00378 if(!err)
00379 switch(ft) {
00380 case Single: seek(-4, Add); break;
00381 case Double: seek(-8, Add); break;
00382 }
00383
00384 return val;
00385 }
00386
00387 bool binistream::ateof()
00388 {
00389 Error olderr = err;
00390 bool eof_then;
00391
00392 peekInt(1);
00393 eof_then = eof();
00394 err = olderr;
00395 return eof_then;
00396 }
00397
00398 void binistream::ignore(unsigned long amount)
00399 {
00400 unsigned long i;
00401
00402 for(i = 0; i < amount; i++)
00403 getByte();
00404 }
00405
00406
00407
00408 binostream::binostream()
00409 {
00410 }
00411
00412 binostream::~binostream()
00413 {
00414 }
00415
00416 void binostream::writeInt(Int val, unsigned int size)
00417 {
00418 unsigned int i;
00419
00420
00421 if(size > sizeof(Int)) {
00422 err |= Unsupported;
00423 throw runtime_error ("The size of the integer to be stored exceeds our system's biggest type");
00424 return;
00425 }
00426
00427 for(i = 0; i < size; i++) {
00428 if(getFlag(BigEndian))
00429 putByte((unsigned char)(val >> ((size - i - 1) * 8)) & 0xff);
00430 else {
00431 putByte((unsigned char)val & 0xff);
00432 val >>= 8;
00433 }
00434 }
00435 }
00436
00437 void binostream::writeFloat(Float f, FType ft)
00438 {
00439 if(getFlag(FloatIEEE)) {
00440
00441 unsigned int i=0;
00442 unsigned int size=0;
00443 Byte *out=NULL;
00444 bool swap;
00445
00446 if(system_flags & FloatIEEE) {
00447
00448 float outf = (float)f;
00449 double outd = (double)f;
00450
00451
00452 swap = getFlag(BigEndian) ^ (system_flags & BigEndian);
00453
00454 switch(ft) {
00455 case Single: size = 4; break;
00456 case Double: size = 8; break;
00457 }
00458
00459 if (!swap && ((size == sizeof (float)) || (size == sizeof (double))))
00460 {
00461 if (size == 4)
00462 { putRaw ((char *)&outf, size); return; }
00463 else
00464 { putRaw ((char *)&outd, size); return; }
00465 }
00466 else
00467 {
00468
00469 switch(ft) {
00470 case Single: out = (Byte *)&outf; break;
00471 case Double: out = (Byte *)&outd; break;
00472 }
00473 }
00474 } else {
00475 #if BINIO_WITH_MATH
00476
00477 Byte buf[8];
00478
00479
00480
00481 swap = !getFlag(BigEndian);
00482
00483
00484 switch(ft) {
00485 case Single: size = 4; float2ieee_single(f, buf); break;
00486 case Double: size = 8; float2ieee_double(f, buf); break;
00487 }
00488
00489 out = buf;
00490 #else
00491
00492 err |= Unsupported; return;
00493 #endif
00494 }
00495
00496
00497 if(swap) out += size - 1;
00498 for(i = 0; i < size; i++) {
00499 putByte(*out);
00500 if(swap) out--; else out++;
00501 }
00502
00503 return;
00504 }
00505
00506
00507 err |= Unsupported;
00508 }
00509
00510 #ifdef BINIO_WITH_MATH
00511
00512
00513
00514
00515
00516
00517
00518
00519
00520
00521
00522
00523
00524
00525
00526
00527
00528
00529
00530
00531
00532
00533
00534
00535
00536
00537
00538
00539
00540 #ifdef applec
00541 # define FloatToUnsigned(f) ((unsigned long)(f))
00542 #else
00543 # define FloatToUnsigned(f) ((unsigned long)(((long)((f) - 2147483648.0)) + 2147483647L + 1))
00544 #endif
00545
00546 #define SEXP_MAX 255
00547 #define SEXP_OFFSET 127
00548 #define SEXP_SIZE 8
00549 #define SEXP_POSITION (32-SEXP_SIZE-1)
00550
00551 void binostream::float2ieee_single(Float num, Byte *bytes)
00552 {
00553 long sign;
00554 register long bits;
00555
00556 if (num < 0) {
00557 sign = 0x80000000;
00558 num *= -1;
00559 } else {
00560 sign = 0;
00561 }
00562
00563 if (num == 0) {
00564 bits = 0;
00565 } else {
00566 Float fMant;
00567 int expon;
00568
00569 fMant = frexp(num, &expon);
00570
00571 if ((expon > (SEXP_MAX-SEXP_OFFSET+1)) || !(fMant < 1)) {
00572
00573 bits = sign | 0x7F800000;
00574 }
00575
00576 else {
00577 long mantissa;
00578
00579 if (expon < -(SEXP_OFFSET-2)) {
00580 int shift = (SEXP_POSITION+1) + (SEXP_OFFSET-2) + expon;
00581 if (shift < 0) {
00582 bits = sign;
00583 }
00584 else {
00585 mantissa = (long)(fMant * (double)(1L << shift));
00586 bits = sign | mantissa;
00587 }
00588 }
00589
00590 else {
00591 mantissa = (long)floor(fMant * (1L << (SEXP_POSITION+1)));
00592 mantissa -= (1L << SEXP_POSITION);
00593 bits = sign | ((long)((expon + SEXP_OFFSET - 1)) << SEXP_POSITION) | mantissa;
00594 }
00595 }
00596 }
00597
00598 bytes[0] = (unsigned char)(bits >> 24);
00599 bytes[1] = (unsigned char)(bits >> 16);
00600 bytes[2] = (unsigned char)(bits >> 8);
00601 bytes[3] = (unsigned char)bits;
00602 }
00603
00604 #define DEXP_MAX 2047
00605 #define DEXP_OFFSET 1023
00606 #define DEXP_SIZE 11
00607 #define DEXP_POSITION (32-DEXP_SIZE-1)
00608
00609 void binostream::float2ieee_double(Float num, Byte *bytes)
00610 {
00611 long sign;
00612 long first, second;
00613
00614 if (num < 0) {
00615 sign = 0x80000000;
00616 num *= -1;
00617 } else {
00618 sign = 0;
00619 }
00620
00621 if (num == 0) {
00622 first = 0;
00623 second = 0;
00624 } else {
00625 Float fMant, fsMant;
00626 int expon;
00627
00628 fMant = frexp(num, &expon);
00629
00630 if ((expon > (DEXP_MAX-DEXP_OFFSET+1)) || !(fMant < 1)) {
00631
00632 first = sign | 0x7FF00000;
00633 second = 0;
00634 }
00635
00636 else {
00637 long mantissa;
00638
00639 if (expon < -(DEXP_OFFSET-2)) {
00640 int shift = (DEXP_POSITION+1) + (DEXP_OFFSET-2) + expon;
00641 if (shift < 0) {
00642 first = sign;
00643 shift += 32;
00644 if (shift < 0) {
00645 second = 0;
00646 }
00647 else {
00648 second = FloatToUnsigned(floor(ldexp(fMant, shift)));
00649 }
00650 }
00651 else {
00652 fsMant = ldexp(fMant, shift);
00653 mantissa = (long)floor(fsMant);
00654 first = sign | mantissa;
00655 second = FloatToUnsigned(floor(ldexp(fsMant - (double)mantissa, 32)));
00656 }
00657 }
00658
00659 else {
00660 fsMant = ldexp(fMant, DEXP_POSITION+1);
00661 mantissa = (long)floor(fsMant);
00662 mantissa -= (1L << DEXP_POSITION);
00663 fsMant -= (1L << DEXP_POSITION);
00664 first = sign | ((long)((expon + DEXP_OFFSET - 1)) << DEXP_POSITION) | mantissa;
00665 second = FloatToUnsigned(floor(ldexp(fsMant - (double)mantissa, 32)));
00666 }
00667 }
00668 }
00669
00670 bytes[0] = (unsigned char)(first >> 24);
00671 bytes[1] = (unsigned char)(first >> 16);
00672 bytes[2] = (unsigned char)(first >> 8);
00673 bytes[3] = (unsigned char)first;
00674 bytes[4] = (unsigned char)(second >> 24);
00675 bytes[5] = (unsigned char)(second >> 16);
00676 bytes[6] = (unsigned char)(second >> 8);
00677 bytes[7] = (unsigned char)second;
00678 }
00679
00680 #endif // BINIO_WITH_MATH
00681
00682 unsigned long binostream::writeString(const char *str, unsigned long amount)
00683 {
00684 unsigned int i;
00685
00686 if(!amount) amount = strlen(str);
00687
00688 for(i = 0; i < amount; i++) {
00689 putByte(str[i]);
00690 if(err) return i;
00691 }
00692
00693 return amount;
00694 }
00695
00696 #if BINIO_ENABLE_STRING
00697 unsigned long binostream::writeString(const std::string &str)
00698 {
00699 return writeString(str.c_str());
00700 }
00701 #endif