1
0
Fork 0

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.
This commit is contained in:
Florent Rougon 2018-01-19 02:33:48 +01:00
parent f1906f3b8a
commit 9054a51dd3

View file

@ -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<unsigned int>(*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<const unsigned int>(*charPtr++))) {
if (!(oStream << theCharLiteral)) {
handleWriteError(errno);
}
availablePlaces--;
availableColumns -= theCharLiteral.size();
} // of for loop over the 'nbBytesRead' bytes
payloadSize += nbBytesRead;