From: James Turner Date: Sun, 6 Oct 2013 16:43:36 +0000 (+0200) Subject: Avoid a data copy decoding base64 data. X-Git-Url: https://git.mxchange.org/?a=commitdiff_plain;h=23140e3bf71ddde1d207ccb201b2d133a140fb5e;p=simgear.git Avoid a data copy decoding base64 data. Use an out parameter to avoid a buffer alloc/copy/free cycle when returning base64-decoded data. --- diff --git a/simgear/io/SVNReportParser.cxx b/simgear/io/SVNReportParser.cxx index 758dd00d..96b357f5 100644 --- a/simgear/io/SVNReportParser.cxx +++ b/simgear/io/SVNReportParser.cxx @@ -165,7 +165,7 @@ namespace { _ptr = p; } - bool apply(std::vector& output, std::istream& source) + bool apply(std::vector& output, std::istream& source) { unsigned char* pEnd = _ptr + instructionLength; unsigned char* newData = pEnd; @@ -330,11 +330,12 @@ public: } bool decodeTextDelta(const SGPath& outputPath) - { - string decoded = strutils::decodeBase64(txDeltaData); + { + std::vector output, decoded; + strutils::decodeBase64(txDeltaData, decoded); size_t bytesToDecode = decoded.size(); - std::vector output; - unsigned char* p = (unsigned char*) decoded.data(); + + unsigned char* p = decoded.data(); if (memcmp(p, "SVN\0", DELTA_HEADER_SIZE) != 0) { return false; // bad header } @@ -346,9 +347,9 @@ public: while (bytesToDecode > 0) { if (!SVNDeltaWindow::isWindowComplete(p, bytesToDecode)) { - SG_LOG(SG_IO, SG_WARN, "SVN txdelta broken window"); - return false; - } + SG_LOG(SG_IO, SG_WARN, "SVN txdelta broken window"); + return false; + } SVNDeltaWindow window(p); assert(bytesToDecode >= window.size()); @@ -362,7 +363,7 @@ public: std::ofstream f; f.open(outputPath.c_str(), std::ios::out | std::ios::trunc | std::ios::binary); - f.write(output.data(), output.size()); + f.write((char*) output.data(), output.size()); // compute MD5 while we have the file in memory memset(&md5Context, 0, sizeof(SG_MD5_CTX)); diff --git a/simgear/misc/strutils.cxx b/simgear/misc/strutils.cxx index 34d93074..10a4c679 100644 --- a/simgear/misc/strutils.cxx +++ b/simgear/misc/strutils.cxx @@ -370,14 +370,13 @@ static bool is_whitespace(unsigned char c) { return ((c == ' ') || (c == '\r') || (c == '\n')); } -std::string decodeBase64(const std::string& encoded_string) +void decodeBase64(const std::string& encoded_string, std::vector& ret) { int in_len = encoded_string.size(); int i = 0; int j = 0; int in_ = 0; unsigned char char_array_4[4], char_array_3[3]; - std::string ret; while (in_len-- && ( encoded_string[in_] != '=')) { if (is_whitespace( encoded_string[in_])) { @@ -399,7 +398,7 @@ std::string decodeBase64(const std::string& encoded_string) char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3]; for (i = 0; (i < 3); i++) - ret += char_array_3[i]; + ret.push_back(char_array_3[i]); i = 0; } } @@ -415,10 +414,8 @@ std::string decodeBase64(const std::string& encoded_string) char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2); char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3]; - for (j = 0; (j < i - 1); j++) ret += char_array_3[j]; + for (j = 0; (j < i - 1); j++) ret.push_back(char_array_3[j]); } - - return ret; } const char hexChar[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; diff --git a/simgear/misc/strutils.hxx b/simgear/misc/strutils.hxx index 977aa894..7fce94a5 100644 --- a/simgear/misc/strutils.hxx +++ b/simgear/misc/strutils.hxx @@ -160,7 +160,7 @@ namespace simgear { * NULs). Throws an exception if input data is not base64, or is * malformed */ - std::string decodeBase64(const std::string& a); + void decodeBase64(const std::string& a, std::vector& output); /** * convert bytes to hexadecimal equivalent