From 9054a51dd3de26be9dd551dd1cdba34c25ec2b23 Mon Sep 17 00:00:00 2001 From: Florent Rougon Date: Fri, 19 Jan 2018 02:33:48 +0100 Subject: [PATCH] fgrcc: use octal escape sequences instead of hexadecimal ones Octal escape sequences can be as short as 2 bytes (\0, ..., \7), therefore they allow one to generate shorter files than hex escapes, for the same resource contents. The line lengths won't be as even, but this is purely cosmetic, virtually no one will ever read the resource data string literals, so this is quite a negligible drawback compared to the advantage of using less space in the Git repository every time resource files are committed. --- src/EmbeddedResources/fgrcc.cxx | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/src/EmbeddedResources/fgrcc.cxx b/src/EmbeddedResources/fgrcc.cxx index cfd5c0f53..70b6d0163 100644 --- a/src/EmbeddedResources/fgrcc.cxx +++ b/src/EmbeddedResources/fgrcc.cxx @@ -452,26 +452,24 @@ CPPEncoder::CPPEncoder(std::istream& inputStream) [[ noreturn ]] void CPPEncoder::handleWriteError(int errorNumber) { throw sg_exception( - "error while writing hex-encoded resource data: " + + "error while writing octal-encoded resource data: " + simgear::strutils::error_string(errorNumber)); } -// Extract bytes from a stream, write them in lines of hex-encoded C++ +// Extract bytes from a stream, write them in lines of octal-encoded C++ // character escapes. Return the number of bytes from the input stream that // have been encoded. std::size_t CPPEncoder::write(std::ostream& oStream) { char buf[4096]; std::streamsize nbBytesRead; - // Write at most 19 encoded bytes per line (19*4 + 1 = 77) - constexpr std::streamsize nbEncBytesPerLine = 19; - std::streamsize availablePlaces = 0; // what remains to fill for current line + // Lines will be at most 80 characters wide because of the '";' following + // the string literal contents. + const std::size_t maxColumns = 78; + std::size_t availableColumns = 0; // what remains to fill for current line int savedErrno; std::size_t payloadSize = 0; - oStream.flags(std::ios::right | std::ios::hex | std::ios::uppercase); - oStream.fill('0'); - do { // std::ifstream::read() sets *both* the eofbit and failbit flags if EOF // was reached before it could read the number of characters requested. @@ -482,19 +480,22 @@ std::size_t CPPEncoder::write(std::ostream& oStream) // Process what has been read (*even* if _inputStream.fail() is true) for (std::streamsize remaining = nbBytesRead; remaining > 0; remaining--) { - if (availablePlaces == 0) { + std::ostringstream oss; + oss << "\\" << std::oct << static_cast(*charPtr++); + string theCharLiteral = oss.str(); + + if (availableColumns < theCharLiteral.size()) { if (!(oStream << "\\\n")) { handleWriteError(errno); } - availablePlaces = nbEncBytesPerLine; + availableColumns = maxColumns; } - if (!(oStream << "\\x" << - std::setw(2) << static_cast(*charPtr++))) { + if (!(oStream << theCharLiteral)) { handleWriteError(errno); } - availablePlaces--; + availableColumns -= theCharLiteral.size(); } // of for loop over the 'nbBytesRead' bytes payloadSize += nbBytesRead;