// // Programmer: Craig Stuart Sapp // Creation Date: Mon Feb 16 12:26:32 PST 2015 Adapted from binasc program. // Last Modified: Sat Apr 21 10:52:19 PDT 2018 Removed using namespace std; // Filename: midifile/src-library/Binasc.cpp // Syntax: C++11 // vim: ts=3 noexpandtab // // description: Interface to convert bytes between binary and ASCII forms. // #include "Binasc.h" #include #include namespace smf { ////////////////////////////// // // Binasc::Binasc -- Constructor: set the default option values. // Binasc::Binasc(void) { m_bytesQ = 1; // for printing HEX bytes when converting to ASCII m_commentsQ = 0; // for printing text comments when converting to ASCII m_midiQ = 0; // for printing ASCII as parsed MIDI file. m_maxLineLength = 75; m_maxLineBytes = 25; } ////////////////////////////// // // Binasc::~Binasc -- Destructor. // Binasc::~Binasc() { // do nothing } ////////////////////////////// // // Binasc::setLineLength -- Set the maximum length of a line when converting // binary content into ASCII bytes. If the input size is less than one, // set to the default value of 75 characters per line. // int Binasc::setLineLength(int length) { if (length < 1) { m_maxLineLength = 75; } else { m_maxLineLength = length; } return m_maxLineLength; } ////////////////////////////// // // Binasc::getLineLength -- Set the maximum length of a line when converting // binary content into ASCII bytes. // int Binasc::getLineLength(void) { return m_maxLineLength; } ////////////////////////////// // // Binasc::setLineBytes -- Set the maximum number of hex bytes in ASCII output. // If the input size is less than one, set to the default value of 25 // hex bytes per line. // int Binasc::setLineBytes(int length) { if (length < 1) { m_maxLineBytes = 25; } else { m_maxLineBytes = length; } return m_maxLineBytes; } ////////////////////////////// // // Binasc::getLineBytes -- Get the maximum number of hex bytes in ASCII output. // int Binasc::getLineBytes(void) { return m_maxLineLength; } ////////////////////////////// // // Binasc::setComments -- Display or not display printable characters // as comments when converting binary files to ASCII byte codes. // void Binasc::setComments(int state) { m_commentsQ = state ? 1 : 0; } void Binasc::setCommentsOn(void) { setComments(true); } void Binasc::setCommentsOff(void) { setComments(false); } ////////////////////////////// // // Binasc::getComments -- Get the comment display style for // showing comments in ASCII output; // int Binasc::getComments(void) { return m_commentsQ; } ////////////////////////////// // // Binasc::setBytes -- Display or not display hex codes (only // print ASCII printable characters). // void Binasc::setBytes(int state) { m_bytesQ = state ? 1 : 0; } void Binasc::setBytesOn(void) { setBytes(true); } void Binasc::setBytesOff(void) { setBytes(false); } ////////////////////////////// // // Binasc::getBytes -- Get hex byte display status. // int Binasc::getBytes(void) { return m_bytesQ; } ////////////////////////////// // // Binasc::setMidi -- Display or not display parsed MIDI data. // void Binasc::setMidi(int state) { m_midiQ = state ? 1 : 0; } void Binasc::setMidiOn(void) { setMidi(true); } void Binasc::setMidiOff(void) { setMidi(false); } ////////////////////////////// // // Binasc::getMidi -- Get the MIDI file printing style option state. // int Binasc::getMidi(void) { return m_midiQ; } ////////////////////////////// // // Binasc::writeToBinary -- Convert an ASCII representation of bytes into // the binary file that it describes. Returns 0 if there was a problem // otherwise returns 1. // int Binasc::writeToBinary(const std::string& outfile, const std::string& infile) { std::ifstream input; input.open(infile.c_str()); if (!input.is_open()) { std::cerr << "Cannot open " << infile << " for reading in binasc." << std::endl; return 0; } std::ofstream output; output.open(outfile.c_str()); if (!output.is_open()) { std::cerr << "Cannot open " << outfile << " for reading in binasc." << std::endl; return 0; } int status = writeToBinary(output, input); input.close(); output.close(); return status; } int Binasc::writeToBinary(const std::string& outfile, std::istream& input) { std::ofstream output; output.open(outfile.c_str()); if (!output.is_open()) { std::cerr << "Cannot open " << outfile << " for reading in binasc." << std::endl; return 0; } int status = writeToBinary(output, input); output.close(); return status; } int Binasc::writeToBinary(std::ostream& out, const std::string& infile) { std::ifstream input; input.open(infile.c_str()); if (!input.is_open()) { std::cerr << "Cannot open " << infile << " for reading in binasc." << std::endl; return 0; } int status = writeToBinary(out, input); input.close(); return status; } int Binasc::writeToBinary(std::ostream& out, std::istream& input) { char inputLine[1024] = {0}; // current line being processed int lineNum = 0; // current line number input.getline(inputLine, 1024, '\n'); lineNum++; while (!input.eof()) { int status = processLine(out, inputLine, lineNum); if (!status) { return 0; } input.getline(inputLine, 1024, '\n'); lineNum++; } return 1; } ////////////////////////////// // // Binasc::readFromBinary -- convert an ASCII representation of bytes into // the binary file that it describes. // int Binasc::readFromBinary(const std::string& outfile, const std::string& infile) { std::ifstream input; input.open(infile.c_str()); if (!input.is_open()) { std::cerr << "Cannot open " << infile << " for reading in binasc." << std::endl; return 0; } std::ofstream output; output.open(outfile.c_str()); if (!output.is_open()) { std::cerr << "Cannot open " << outfile << " for reading in binasc." << std::endl; return 0; } int status = readFromBinary(output, input); input.close(); output.close(); return status; } int Binasc::readFromBinary(const std::string& outfile, std::istream& input) { std::ofstream output; output.open(outfile.c_str()); if (!output.is_open()) { std::cerr << "Cannot open " << outfile << " for reading in binasc." << std::endl; return 0; } int status = readFromBinary(output, input); output.close(); return status; } int Binasc::readFromBinary(std::ostream& out, const std::string& infile) { std::ifstream input; input.open(infile.c_str()); if (!input.is_open()) { std::cerr << "Cannot open " << infile << " for reading in binasc." << std::endl; return 0; } int status = readFromBinary(out, input); input.close(); return status; } int Binasc::readFromBinary(std::ostream& out, std::istream& input) { int status; if (m_midiQ) { status = outputStyleMidi(out, input); } else if (!m_bytesQ) { status = outputStyleAscii(out, input); } else if (m_bytesQ && m_commentsQ) { status = outputStyleBoth(out, input); } else { status = outputStyleBinary(out, input); } return status; } /////////////////////////////////////////////////////////////////////////// // // protected functions -- // ////////////////////////////// // // Binasc::outputStyleAscii -- read an input file and output bytes in ascii // form, not displaying any blank lines. Output words are not // broken unless they are longer than 75 characters. // int Binasc::outputStyleAscii(std::ostream& out, std::istream& input) { uchar outputWord[256] = {0}; // storage for current word int index = 0; // current length of word int lineCount = 0; // current length of line int type = 0; // 0=space, 1=printable uchar ch; // current input byte ch = input.get(); while (!input.eof()) { int lastType = type; type = (isprint(ch) && !isspace(ch)) ? 1 : 0; if ((type == 1) && (lastType == 0)) { // start of a new word. check where to put old word if (index + lineCount >= m_maxLineLength) { // put on next line outputWord[index] = '\0'; out << '\n' << outputWord; lineCount = index; index = 0; } else { // put on current line outputWord[index] = '\0'; if (lineCount != 0) { out << ' '; lineCount++; } out << outputWord; lineCount += index; index = 0; } } if (type == 1) { outputWord[index++] = ch; } ch = input.get(); } if (index != 0) { out << std::endl; } return 1; } ////////////////////////////// // // Binasc::outputStyleBinary -- read an input binary file and output bytes // in ascii form, hexadecimal numbers only. // int Binasc::outputStyleBinary(std::ostream& out, std::istream& input) { int currentByte = 0; // current byte output in line uchar ch; // current input byte ch = input.get(); if (input.eof()) { std::cerr << "End of the file right away!" << std::endl; return 0; } while (!input.eof()) { if (ch < 0x10) { out << '0'; } out << std::hex << (int)ch << ' '; currentByte++; if (currentByte >= m_maxLineBytes) { out << '\n'; currentByte = 0; } ch = input.get(); } if (currentByte != 0) { out << std::endl; } return 1; } ////////////////////////////// // // Binasc::outputStyleBoth -- read an input file and output bytes in ASCII // form with both hexadecimal numbers and ascii representation // int Binasc::outputStyleBoth(std::ostream& out, std::istream& input) { uchar asciiLine[256] = {0}; // storage for output line int currentByte = 0; // current byte output in line int index = 0; // current character in asciiLine uchar ch; // current input byte ch = input.get(); while (!input.eof()) { if (index == 0) { asciiLine[index++] = ';'; out << ' '; } if (ch < 0x10) { out << '0'; } out << std::hex << (int)ch << ' '; currentByte++; asciiLine[index++] = ' '; if (isprint(ch)) { asciiLine[index++] = ch; } else { asciiLine[index++] = ' '; } asciiLine[index++] = ' '; if (currentByte >= m_maxLineBytes) { out << '\n'; asciiLine[index] = '\0'; out << asciiLine << "\n\n"; currentByte = 0; index = 0; } ch = input.get(); } if (currentByte != 0) { out << '\n'; asciiLine[index] = '\0'; out << asciiLine << '\n' << std::endl; } return 1; } /////////////////////////////// // // processLine -- read a line of input and output any specified bytes // int Binasc::processLine(std::ostream& out, const std::string& input, int lineCount) { int status = 1; int i = 0; int length = (int)input.size(); std::string word; while (i 2)) { status = processBinaryWord(out, word, lineCount); } else { status = processHexWord(out, word, lineCount); } } if (status == 0) { return 0; } } return 1; } ////////////////////////////// // // Binasc::getWord -- extract a sub string, stopping at any of the given // terminator characters. // int Binasc::getWord(std::string& word, const std::string& input, const std::string& terminators, int index) { word.resize(0); int i = index; int escape = 0; int ecount = 0; if (terminators.find('"') != std::string::npos) { escape = 1; } while (i < (int)input.size()) { if (escape && input[i] == '\"') { ecount++; i++; if (ecount >= 2) { break; } } if (escape && (i<(int)input.size()-1) && (input[i] == '\\') && (input[i+1] == '"')) { word.push_back(input[i+1]); i += 2; } else if (terminators.find(input[i]) == std::string::npos) { word.push_back(input[i]); i++; } else { i++; return i; } } return i; } /////////////////////////////// // // Binasc::getVLV -- read a Variable-Length Value from the file // int Binasc::getVLV(std::istream& infile, int& trackbytes) { int output = 0; uchar ch; infile.read((char*)&ch, 1); trackbytes++; output = (output << 7) | (0x7f & ch); while (ch >= 0x80) { infile.read((char*)&ch, 1); trackbytes++; output = (output << 7) | (0x7f & ch); } return output; } ////////////////////////////// // // Binasc::readMidiEvent -- Read a delta time and then a MIDI message // (or meta message). Returns 1 if not end-of-track meta message; // 0 otherwise. // int Binasc::readMidiEvent(std::ostream& out, std::istream& infile, int& trackbytes, int& command) { // Read and print Variable Length Value for delta ticks int vlv = getVLV(infile, trackbytes); std::stringstream output; output << "v" << std::dec << vlv << "\t"; std::string comment; int status = 1; uchar ch; char byte1, byte2; infile.read((char*)&ch, 1); trackbytes++; if (ch < 0x80) { // running status: command byte is previous one in data stream output << " "; } else { // midi command byte output << std::hex << (int)ch; command = ch; infile.read((char*)&ch, 1); trackbytes++; } byte1 = ch; switch (command & 0xf0) { case 0x80: // note-off: 2 bytes output << " '" << std::dec << (int)byte1; infile.read((char*)&ch, 1); trackbytes++; byte2 = ch; output << " '" << std::dec << (int)byte2; if (m_commentsQ) { comment += "note-off " + keyToPitchName(byte1); } break; case 0x90: // note-on: 2 bytes output << " '" << std::dec << (int)byte1; infile.read((char*)&ch, 1); trackbytes++; byte2 = ch; output << " '" << std::dec << (int)byte2; if (m_commentsQ) { if (byte2 == 0) { comment += "note-off " + keyToPitchName(byte1); } else { comment += "note-on " + keyToPitchName(byte1); } } break; case 0xA0: // aftertouch: 2 bytes output << " '" << std::dec << (int)byte1; infile.read((char*)&ch, 1); trackbytes++; byte2 = ch; output << " '" << std::dec << (int)byte2; if (m_commentsQ) { comment += "after-touch"; } break; case 0xB0: // continuous controller: 2 bytes output << " '" << std::dec << (int)byte1; infile.read((char*)&ch, 1); trackbytes++; byte2 = ch; output << " '" << std::dec << (int)byte2; if (m_commentsQ) { comment += "controller"; } break; case 0xE0: // pitch-bend: 2 bytes output << " '" << std::dec << (int)byte1; infile.read((char*)&ch, 1); trackbytes++; byte2 = ch; output << " '" << std::dec << (int)byte2; if (m_commentsQ) { comment += "pitch-bend"; } break; case 0xC0: // patch change: 1 bytes output << " '" << std::dec << (int)byte1; if (m_commentsQ) { output << "\t"; comment += "patch-change"; } break; case 0xD0: // channel pressure: 1 bytes output << " '" << std::dec << (int)byte1; if (m_commentsQ) { comment += "channel pressure"; } break; case 0xF0: // various system bytes: variable bytes switch (command) { case 0xf0: break; case 0xf7: // Read the first byte which is either 0xf0 or 0xf7. // Then a VLV byte count for the number of bytes // that remain in the message will follow. // Then read that number of bytes. { infile.putback(byte1); trackbytes--; int length = getVLV(infile, trackbytes); output << " v" << std::dec << length; for (int i=0; i 0) { tempout << "\t\t\t; unknown header bytes"; tempout << std::endl; } for (i=0; i 127 || tempLong < -128) { std::cerr << "Error on line " << lineNum << " at token: " << word << std::endl; std::cerr << "Decimal number out of range from -128 to 127" << std::endl; return 0; } char charOutput = (char)tempLong; out << charOutput; return 1; } else { ulong tempLong = (ulong)atoi(&word[quoteIndex + 1]); uchar ucharOutput = (uchar)tempLong; if (tempLong > 255) { // || (tempLong < 0)) { std::cerr << "Error on line " << lineNum << " at token: " << word << std::endl; std::cerr << "Decimal number out of range from 0 to 255" << std::endl; return 0; } out << ucharOutput; return 1; } } // left with an integer number with a specified number of bytes switch (byteCount) { case 1: if (signIndex != -1) { long tempLong = atoi(&word[quoteIndex + 1]); char charOutput = (char)tempLong; out << charOutput; return 1; } else { ulong tempLong = (ulong)atoi(&word[quoteIndex + 1]); uchar ucharOutput = (uchar)tempLong; out << ucharOutput; return 1; } break; case 2: if (signIndex != -1) { long tempLong = atoi(&word[quoteIndex + 1]); short shortOutput = (short)tempLong; if (endianIndex == -1) { writeBigEndianShort(out, shortOutput); } else { writeLittleEndianShort(out, shortOutput); } return 1; } else { ulong tempLong = (ulong)atoi(&word[quoteIndex + 1]); ushort ushortOutput = (ushort)tempLong; if (endianIndex == -1) { writeBigEndianUShort(out, ushortOutput); } else { writeLittleEndianUShort(out, ushortOutput); } return 1; } break; case 3: { if (signIndex != -1) { std::cerr << "Error on line " << lineNum << " at token: " << word << std::endl; std::cerr << "negative decimal numbers cannot be stored in 3 bytes" << std::endl; return 0; } ulong tempLong = (ulong)atoi(&word[quoteIndex + 1]); uchar byte1 = (uchar)((tempLong & 0x00ff0000) >> 16); uchar byte2 = (uchar)((tempLong & 0x0000ff00) >> 8); uchar byte3 = (uchar)((tempLong & 0x000000ff)); if (endianIndex == -1) { out << byte1; out << byte2; out << byte3; } else { out << byte3; out << byte2; out << byte1; } return 1; } break; case 4: if (signIndex != -1) { long tempLong = atoi(&word[quoteIndex + 1]); if (endianIndex == -1) { writeBigEndianLong(out, tempLong); } else { writeLittleEndianLong(out, tempLong); } return 1; } else { ulong tempuLong = (ulong)atoi(&word[quoteIndex + 1]); if (endianIndex == -1) { writeBigEndianULong(out, tempuLong); } else { writeLittleEndianULong(out, tempuLong); } return 1; } break; default: std::cerr << "Error on line " << lineNum << " at token: " << word << std::endl; std::cerr << "invalid byte count specification for decimal number" << std::endl; return 0; } return 1; } ////////////////////////////// // // Binasc::processHexWord -- interprets a hexadecimal word and converts into // its binary byte form. // int Binasc::processHexWord(std::ostream& out, const std::string& word, int lineNum) { int length = (int)word.size(); uchar outputByte; if (length > 2) { std::cerr << "Error on line " << lineNum << " at token: " << word << std::endl; std::cerr << "Size of hexadecimal number is too large. Max is ff." << std::endl; return 0; } if (!isxdigit(word[0]) || (length == 2 && !isxdigit(word[1]))) { std::cerr << "Error on line " << lineNum << " at token: " << word << std::endl; std::cerr << "Invalid character in hexadecimal number." << std::endl; return 0; } outputByte = (uchar)strtol(word.c_str(), (char**)NULL, 16); out << outputByte; return 1; } ////////////////////////////// // // Binasc::processStringWord -- interprets a binary word into // its constituent byte // int Binasc::processStringWord(std::ostream& out, const std::string& word, int /* lineNum */) { out << word; return 1; } ////////////////////////////// // // Binasc::processAsciiWord -- interprets a binary word into // its constituent byte // int Binasc::processAsciiWord(std::ostream& out, const std::string& word, int lineNum) { int length = (int)word.size(); uchar outputByte; if (word[0] != '+') { std::cerr << "Error on line " << lineNum << " at token: " << word << std::endl; std::cerr << "character byte must start with \'+\' sign: " << std::endl; return 0; } if (length > 2) { std::cerr << "Error on line " << lineNum << " at token: " << word << std::endl; std::cerr << "character byte word is too long -- specify only one character" << std::endl; return 0; } if (length == 2) { outputByte = (uchar)word[1]; } else { outputByte = ' '; } out << outputByte; return 1; } ////////////////////////////// // // Binasc::processBinaryWord -- interprets a binary word into // its constituent byte // int Binasc::processBinaryWord(std::ostream& out, const std::string& word, int lineNum) { int length = (int)word.size(); // length of ascii binary number int commaIndex = -1; // index location of comma in number int leftDigits = -1; // number of digits to left of comma int rightDigits = -1; // number of digits to right of comma int i = 0; // make sure that all characters are valid for (i=0; i 8) { std::cerr << "Error on line " << lineNum << " at token: " << word << std::endl; std::cerr << "too many digits in binary number" << std::endl; return 0; } // if there is a comma, then there cannot be more than 4 digits on a side if (leftDigits > 4) { std::cerr << "Error on line " << lineNum << " at token: " << word << std::endl; std::cerr << "too many digits to left of comma" << std::endl; return 0; } if (rightDigits > 4) { std::cerr << "Error on line " << lineNum << " at token: " << word << std::endl; std::cerr << "too many digits to right of comma" << std::endl; return 0; } // OK, we have a valid binary number, so calculate the byte uchar output = 0; // if no comma in binary number if (commaIndex == -1) { for (i=0; i> 28) & 0x7f; byte[1] = (value >> 21) & 0x7f; byte[2] = (value >> 14) & 0x7f; byte[3] = (value >> 7) & 0x7f; byte[4] = (value >> 0) & 0x7f; int i; int flag = 0; for (i=0; i<4; i++) { if (byte[i] != 0) { flag = 1; } if (flag) { byte[i] |= 0x80; } } for (i=0; i<5; i++) { if (byte[i] >= 0x80 || i == 4) { out << byte[i]; } } return 1; } //////////////////////////// // // Binasc::processMidiTempoWord -- convert a floating point tempo into // a three-byte number of microseconds per beat per minute value. // int Binasc::processMidiTempoWord(std::ostream& out, const std::string& word, int lineNum) { if (word.size() < 2) { std::cerr << "Error on line: " << lineNum << ": 't' needs to be followed immediately by " << "a floating-point number" << std::endl; return 0; } if (!(isdigit(word[1]) || word[1] == '.' || word[1] == '-' || word[1] == '+')) { std::cerr << "Error on line: " << lineNum << ": 't' needs to be followed immediately by " << "a floating-point number" << std::endl; return 0; } double value = strtod(&word[1], NULL); if (value < 0.0) { value = -value; } int intval = int(60.0 * 1000000.0 / value + 0.5); uchar byte0 = intval & 0xff; uchar byte1 = (intval >> 8) & 0xff; uchar byte2 = (intval >> 16) & 0xff; out << byte2 << byte1 << byte0; return 1; } //////////////////////////// // // Binasc::processMidiPitchBendWord -- convert a floating point number in // the range from +1.0 to -1.0 into a 14-point integer with -1.0 mapping // to 0 and +1.0 mapping to 2^15-1. This integer will be packed into // two bytes, with the LSB coming first and containing the bottom // 7-bits of the 14-bit value, then the MSB coming second and containing // the top 7-bits of the 14-bit value. int Binasc::processMidiPitchBendWord(std::ostream& out, const std::string& word, int lineNum) { if (word.size() < 2) { std::cerr << "Error on line: " << lineNum << ": 'p' needs to be followed immediately by " << "a floating-point number" << std::endl; return 0; } if (!(isdigit(word[1]) || word[1] == '.' || word[1] == '-' || word[1] == '+')) { std::cerr << "Error on line: " << lineNum << ": 'p' needs to be followed immediately by " << "a floating-point number" << std::endl; return 0; } double value = strtod(&word[1], NULL); if (value > 1.0) { value = 1.0; } if (value < -1.0) { value = -1.0; } int intval = (int)(((1 << 13)-0.5) * (value + 1.0) + 0.5); uchar LSB = intval & 0x7f; uchar MSB = (intval >> 7) & 0x7f; out << LSB << MSB; return 1; } /////////////////////////////////////////////////////////////////////////// // // Ordered byte writing functions -- // ////////////////////////////// // // Binasc::writeLittleEndianUShort -- // std::ostream& Binasc::writeLittleEndianUShort(std::ostream& out, ushort value) { union { char bytes[2]; ushort us; } data; data.us = value; out << data.bytes[0]; out << data.bytes[1]; return out; } ////////////////////////////// // // Binasc::writeBigEndianUShort -- // std::ostream& Binasc::writeBigEndianUShort(std::ostream& out, ushort value) { union { char bytes[2]; ushort us; } data; data.us = value; out << data.bytes[1]; out << data.bytes[0]; return out; } ////////////////////////////// // // Binasc::writeLittleEndianShort -- // std::ostream& Binasc::writeLittleEndianShort(std::ostream& out, short value) { union { char bytes[2]; short s; } data; data.s = value; out << data.bytes[0]; out << data.bytes[1]; return out; } ////////////////////////////// // // writeBigEndianShort -- // std::ostream& Binasc::writeBigEndianShort(std::ostream& out, short value) { union { char bytes[2]; short s; } data; data.s = value; out << data.bytes[1]; out << data.bytes[0]; return out; } ////////////////////////////// // // Binasc::writeLittleEndianULong -- // std::ostream& Binasc::writeLittleEndianULong(std::ostream& out, ulong value) { union { char bytes[4]; ulong ul; } data; data.ul = value; out << data.bytes[0]; out << data.bytes[1]; out << data.bytes[2]; out << data.bytes[3]; return out; } ////////////////////////////// // // Binasc::writeBigEndianULong -- // std::ostream& Binasc::writeBigEndianULong(std::ostream& out, ulong value) { union { char bytes[4]; long ul; } data; data.ul = value; out << data.bytes[3]; out << data.bytes[2]; out << data.bytes[1]; out << data.bytes[0]; return out; } ////////////////////////////// // // Binasc::writeLittleEndianLong -- // std::ostream& Binasc::writeLittleEndianLong(std::ostream& out, long value) { union { char bytes[4]; long l; } data; data.l = value; out << data.bytes[0]; out << data.bytes[1]; out << data.bytes[2]; out << data.bytes[3]; return out; } ////////////////////////////// // // Binasc::writeBigEndianLong -- // std::ostream& Binasc::writeBigEndianLong(std::ostream& out, long value) { union { char bytes[4]; long l; } data; data.l = value; out << data.bytes[3]; out << data.bytes[2]; out << data.bytes[1]; out << data.bytes[0]; return out; } ////////////////////////////// // // Binasc::writeBigEndianFloat -- // std::ostream& Binasc::writeBigEndianFloat(std::ostream& out, float value) { union { char bytes[4]; float f; } data; data.f = value; out << data.bytes[3]; out << data.bytes[2]; out << data.bytes[1]; out << data.bytes[0]; return out; } ////////////////////////////// // // Binasc::writeLittleEndianFloat -- // std::ostream& Binasc::writeLittleEndianFloat(std::ostream& out, float value) { union { char bytes[4]; float f; } data; data.f = value; out << data.bytes[0]; out << data.bytes[1]; out << data.bytes[2]; out << data.bytes[3]; return out; } ////////////////////////////// // // Binasc::writeBigEndianDouble -- // std::ostream& Binasc::writeBigEndianDouble(std::ostream& out, double value) { union { char bytes[8]; double d; } data; data.d = value; out << data.bytes[7]; out << data.bytes[6]; out << data.bytes[5]; out << data.bytes[4]; out << data.bytes[3]; out << data.bytes[2]; out << data.bytes[1]; out << data.bytes[0]; return out; } ////////////////////////////// // // Binasc::writeLittleEndianDouble -- // std::ostream& Binasc::writeLittleEndianDouble(std::ostream& out, double value) { union { char bytes[8]; double d; } data; data.d = value; out << data.bytes[0]; out << data.bytes[1]; out << data.bytes[2]; out << data.bytes[3]; out << data.bytes[4]; out << data.bytes[5]; out << data.bytes[6]; out << data.bytes[7]; return out; } } // end namespace smf