From 77ea0fb08e9ff9da56b2037b3cb3cc36cad40f82 Mon Sep 17 00:00:00 2001 From: Bob Polis Date: Wed, 19 Feb 2020 17:25:18 +0100 Subject: [PATCH] implemented and fixed byte order stuff --- byte_order_stuff.cpp | 280 +++++++++++++++++++++++++++++++++++-------- libscio.hpp | 73 +++++++---- 2 files changed, 276 insertions(+), 77 deletions(-) diff --git a/byte_order_stuff.cpp b/byte_order_stuff.cpp index 1d24cc5..31d96a5 100644 --- a/byte_order_stuff.cpp +++ b/byte_order_stuff.cpp @@ -7,84 +7,258 @@ // #include "libscio.hpp" +#include +#include +#include -sc::io::byte_order_changer(const sc::io::data_streamer* ds, sc::io::byte_order order) : _data_streamer {ds}, _saved_byte_order {order} { +using namespace sc::io; + +// data_streamer --------------------------------------------------------------- + +byte_order data_streamer::cur_byte_order() { + uint8_t ch[2] = {0x12, 0x34}; + uint16_t* p = reinterpret_cast(ch); + return *p == 0x1234 ? byte_order::big_endian : byte_order::little_endian; +} + +std::string data_streamer::get4chars(std::istream& file) const { + char buf[4]; + file.read(buf, 4); + return std::string(buf, 4); +} + +uint32_t data_streamer::getui24(std::istream& file) const { + char buf[4] = {0}; + file.read(&buf[1], 3); + if (cur_byte_order() != _target_byte_order) { + char tmp = buf[1]; + buf[1] = buf[3]; + buf[3] = tmp; + } + return *reinterpret_cast(buf); +} + +int32_t data_streamer::getsi24(std::istream& file) const { + return static_cast(getui24(file)); +} + +double data_streamer::getf80(std::istream& file) const { + float_80 val; + file.read(reinterpret_cast(val._val), sizeof(val._val)); + if (_target_byte_order != byte_order::big_endian) { + byte_swap(val._val, sizeof(val._val)); + } + return val; +} + +void data_streamer::put4chars(const std::string& s, std::ostream& file) const { + if (s.size() < 4) { + throw std::runtime_error("data_streamer::put4chars: string too short"); + } + file.write(s.c_str(), 4); +} + +void data_streamer::putui24(uint32_t val, std::ostream& file) const { + char* buf = reinterpret_cast(&val); + if (cur_byte_order() != _target_byte_order) { + char tmp = buf[1]; + buf[1] = buf[3]; + buf[3] = tmp; + } + file.write(&buf[1], 3); +} + +void data_streamer::putsi24(int32_t val, std::ostream& file) const { + putui24(static_cast(val), file); +} + +// byte_order_changer ---------------------------------------------------------- + +byte_order_changer::byte_order_changer(data_streamer* ds, byte_order order) : _data_streamer {ds} { if (ds == nullptr) { std::cerr << "byte_order_changer: no data streamer given\n"; return; } _saved_byte_order = _data_streamer->target_byte_order(); - _date_streamer->target_byte_order(order); + _data_streamer->target_byte_order(order); } -sc::io::~byte_order_changer() { +byte_order_changer::~byte_order_changer() { if (_data_streamer) { _data_streamer->target_byte_order(_saved_byte_order); } } -sc::io::byte_order_changer(sc::io::byte_order_changer&& other) { +byte_order_changer::byte_order_changer(byte_order_changer&& other) { _data_streamer = other._data_streamer; _saved_byte_order = other._saved_byte_order; other._data_streamer = nullptr; } -sc::io::byte_order_changer operator=(sc::io::byte_order_changer&& other) { - if (*other != this) { +byte_order_changer& byte_order_changer::operator=(byte_order_changer&& other) { + if (&other != this) { _data_streamer = other._data_streamer; _saved_byte_order = other._saved_byte_order; other._data_streamer = nullptr; - return *this; } + return *this; } -sc::io::byte_order sc::io::data_streamer::cur_byte_order() { - uint8_t ch[2] = {0x12, 0x34}; - uint16_t* p = reinterpret_cast(ch); - return *p == 0x1234 ? sc::io::byte_order::big_endian : sc::io::byte_order::little_endian; +// float_80 -------------------------------------------------------------------- + +/*- + * Copyright (c) 2005, 2006 by Marco Trillo + * + * Permission is hereby granted, free of charge, to any + * person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the + * Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the + * Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice + * shall be included in all copies or substantial portions of + * the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY + * KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR + * PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS + * OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +/* + * Infinite & NAN values for non-IEEE systems + */ +#ifndef HUGE_VAL +#ifdef HUGE +#define INFINITE_VALUE HUGE +#define NAN_VALUE HUGE +#endif +#else +#define INFINITE_VALUE HUGE_VAL +#define NAN_VALUE HUGE_VAL +#endif + + +/* + * IEEE 754 Extended Precision + * + * Implementation here is the 80-bit extended precision + * format of Motorola 68881, Motorola 68882 and Motorola + * 68040 FPUs, as well as Intel 80x87 FPUs. + * + * See: + * http://www.freescale.com/files/32bit/doc/fact_sheet/BR509.pdf + */ +/* + * Exponent range: [-16383,16383] + * Precision for mantissa: 64 bits with no hidden bit + * Bias: 16383 + */ + +float_80::float_80() : float_80(0) {} + +float_80::float_80(double in) { + int sgn, exp, shift; + double fraction, t; + unsigned int lexp, hexp; + unsigned long low, high; + + if (in == 0.0) { + memset(_val, 0, 10); + return; + } + if (in < 0.0) { + in = fabs(in); + sgn = 1; + } else + sgn = 0; + + fraction = frexp(in, &exp); + + if (exp == 0 || exp > 16384) { + if (exp > 16384) /* infinite value */ + low = high = 0; + else { + low = 0x80000000; + high = 0; + } + exp = 32767; + goto done; + } + fraction = ldexp(fraction, 32); + t = floor(fraction); + low = (unsigned long) t; + fraction -= t; + t = floor(ldexp(fraction, 32)); + high = (unsigned long) t; + + /* Convert exponents < -16382 to -16382 (then they will be + * stored as -16383) */ + if (exp < -16382) { + shift = 0 - exp - 16382; + high >>= shift; + high |= (low << (32 - shift)); + low >>= shift; + exp = -16382; + } + exp += 16383 - 1; /* bias */ + +done: + lexp = ((unsigned int) exp) >> 8; + hexp = ((unsigned int) exp) & 0xFF; + + /* big endian */ + _val[0] = ((unsigned char) sgn) << 7; + _val[0] |= (unsigned char) lexp; + _val[1] = (unsigned char) hexp; + _val[2] = (unsigned char) (low >> 24); + _val[3] = (unsigned char) ((low >> 16) & 0xFF); + _val[4] = (unsigned char) ((low >> 8) & 0xFF); + _val[5] = (unsigned char) (low & 0xFF); + _val[6] = (unsigned char) (high >> 24); + _val[7] = (unsigned char) ((high >> 16) & 0xFF); + _val[8] = (unsigned char) ((high >> 8) & 0xFF); + _val[9] = (unsigned char) (high & 0xFF); } -std::string sc::io::data_streamer::get4chars(std::istream& file) const { +float_80::operator double() const { + int sgn, exp; + unsigned long low, high; + double out; + /* Extract the components from the big endian buffer */ + sgn = (int) (_val[0] >> 7); + exp = ((int) (_val[0] & 0x7F) << 8) | ((int) _val[1]); + low = (((unsigned long) _val[2]) << 24) + | (((unsigned long) _val[3]) << 16) + | (((unsigned long) _val[4]) << 8) | (unsigned long) _val[5]; + high = (((unsigned long) _val[6]) << 24) + | (((unsigned long) _val[7]) << 16) + | (((unsigned long) _val[8]) << 8) | (unsigned long) _val[9]; + + if (exp == 0 && low == 0 && high == 0) + return (sgn ? -0.0 : 0.0); + + switch (exp) { + case 32767: + if (low == 0 && high == 0) + return (sgn ? -INFINITE_VALUE : INFINITE_VALUE); + else + return (sgn ? -NAN_VALUE : NAN_VALUE); + default: + exp -= 16383; /* unbias exponent */ + + } + + out = ldexp((double) low, -31 + exp); + out += ldexp((double) high, -63 + exp); + + return (sgn ? -out : out); } - -uint8_t sc::io::data_streamer::getui8(std::istream& file) const { - -} - -int8_t sc::io::data_streamer::getsi8(std::istream& file) const { - -} - -uin16_t sc::io::data_streamer::getui16(std::istream& file) const { - -} - -int16_t sc::io::data_streamer::getsi16(std::istream& file) const {} -uint32_t sc::io::data_streamer::getui24(std::istream& file) const {} -int32_t sc::io::data_streamer::getsi24(std::istream& file) const {} -uint32_t sc::io::data_streamer::getui32(std::istream& file) const {} -int32_t sc::io::data_streamer::getsi32(std::istream& file) const {} -uint64_t sc::io::data_streamer::getui64(std::istream& file) const {} -int64_t sc::io::data_streamer::getsi64(std::istream& file) const {} - -float sc::io::data_streamer::getf32(std::istream& file) const {} -double sc::io::data_streamer::getf64(std::istream& file) const {} -double sc::io::data_streamer::getf80(std::istream& file) const {} - -void sc::io::data_streamer::put4chars(const std::string& s, ostream& file) const {} - -void sc::io::data_streamer::putui8(uint8_t val, std::ostream& file) const {} -void sc::io::data_streamer::putsi8(int8_t val, std::ostream& file) const {} -void sc::io::data_streamer::putui16(uint16_t val, std::ostream& file) const {} -void sc::io::data_streamer::putsi16(int16_t val, std::ostream& file) const {} -void sc::io::data_streamer::putui24(uint32_t val, std::ostream& file) const {} -void sc::io::data_streamer::putsi24(int32_t val, std::ostream& file) const {} -void sc::io::data_streamer::putui32(uint32_t val, std::ostream& file) const {} -void sc::io::data_streamer::putsi32(int32_t val, std::ostream& file) const {} -void sc::io::data_streamer::putui64(uint64_t val, std::ostream& file) const {} -void sc::io::data_streamer::putsi64(int64_t val, std::ostream& file) const {} - -void sc::io::data_streamer::putf32(float val, std::ostream& file) const {} -void sc::io::data_streamer::putf64(double val, std::ostream& file) const {} -void sc::io::data_streamer::putf80(double val, std::ostream& file) const {} diff --git a/libscio.hpp b/libscio.hpp index 59b52d1..ff1abbb 100644 --- a/libscio.hpp +++ b/libscio.hpp @@ -13,6 +13,7 @@ #include #include #include +#include namespace sc { @@ -22,7 +23,7 @@ namespace sc { public: fdoutbuf(int fd): _fd(fd) {} - private: + protected: int _fd; int_type overflow(int_type c) override; @@ -33,7 +34,7 @@ namespace sc { public: fdostream(int fd) : std::ostream(&_buf), _buf(fd) {} - private: + protected: fdoutbuf _buf; }; @@ -73,6 +74,14 @@ namespace sc { }; + struct float_80 { + unsigned char _val[10]; // big endian + + float_80(); + float_80(double val); + operator double() const; + }; + enum class byte_order { undefined, little_endian, @@ -88,6 +97,22 @@ namespace sc { std::swap(p[i], p[n - 1 - i]); } } + template + inline T get(std::istream& file) const { + char buf[sizeof(T)]; + file.read(buf, sizeof(T)); + if (cur_byte_order() != _target_byte_order) { + byte_swap(buf, sizeof(T)); + } + return *reinterpret_cast(buf); + } + template + inline void put(T val, std::ostream& file) const { + if (cur_byte_order() != _target_byte_order) { + byte_swap(&val, sizeof(T)); + } + file.write(reinterpret_cast(&val), sizeof(T)); + } data_streamer() = default; @@ -96,36 +121,36 @@ namespace sc { std::string get4chars(std::istream& file) const; - uint8_t getui8(std::istream& file) const; - int8_t getsi8(std::istream& file) const; - uin16_t getui16(std::istream& file) const; - int16_t getsi16(std::istream& file) const; + uint8_t getui8(std::istream& file) const { return static_cast(file.get()); } + int8_t getsi8(std::istream& file) const { return file.get(); } + uint16_t getui16(std::istream& file) const { return get(file); } + int16_t getsi16(std::istream& file) const { return get(file); } uint32_t getui24(std::istream& file) const; int32_t getsi24(std::istream& file) const; - uint32_t getui32(std::istream& file) const; - int32_t getsi32(std::istream& file) const; - uint64_t getui64(std::istream& file) const; - int64_t getsi64(std::istream& file) const; + uint32_t getui32(std::istream& file) const { return get(file); } + int32_t getsi32(std::istream& file) const { return get(file); } + uint64_t getui64(std::istream& file) const { return get(file); } + int64_t getsi64(std::istream& file) const { return get(file); } - float getf32(std::istream& file) const; - double getf64(std::istream& file) const; + float getf32(std::istream& file) const { return get(file); } + double getf64(std::istream& file) const { return get(file); } double getf80(std::istream& file) const; - void put4chars(const std::string& s, ostream& file) const; + void put4chars(const std::string& s, std::ostream& file) const; - void putui8(uint8_t val, std::ostream& file) const; - void putsi8(int8_t val, std::ostream& file) const; - void putui16(uint16_t val, std::ostream& file) const; - void putsi16(int16_t val, std::ostream& file) const; + void putui8(uint8_t val, std::ostream& file) const { file.put(val); } + void putsi8(int8_t val, std::ostream& file) const { file.put(val); } + void putui16(uint16_t val, std::ostream& file) const { put(val, file); } + void putsi16(int16_t val, std::ostream& file) const { put(val, file); } void putui24(uint32_t val, std::ostream& file) const; void putsi24(int32_t val, std::ostream& file) const; - void putui32(uint32_t val, std::ostream& file) const; - void putsi32(int32_t val, std::ostream& file) const; - void putui64(uint64_t val, std::ostream& file) const; - void putsi64(int64_t val, std::ostream& file) const; + void putui32(uint32_t val, std::ostream& file) const { put(val, file); } + void putsi32(int32_t val, std::ostream& file) const { put(val, file); } + void putui64(uint64_t val, std::ostream& file) const { put(val, file); } + void putsi64(int64_t val, std::ostream& file) const { put(val, file); } - void putf32(float val, std::ostream& file) const; - void putf64(double val, std::ostream& file) const; + void putf32(float val, std::ostream& file) const { put(val, file); } + void putf64(double val, std::ostream& file) const { put(val, file); } void putf80(double val, std::ostream& file) const; private: @@ -134,7 +159,7 @@ namespace sc { class byte_order_changer { public: - byte_order_changer(const data_streamer* ds, byte_order order); + byte_order_changer(data_streamer* ds, byte_order order); ~byte_order_changer(); byte_order_changer(byte_order_changer&& other);