Skip to content

Commit

Permalink
Optimize DDoc memory handling
Browse files Browse the repository at this point in the history
IB-6868

Signed-off-by: Raul Metsma <raul@metsma.ee>
  • Loading branch information
metsma committed Jun 24, 2022
1 parent d9fd053 commit 26d4484
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 26 deletions.
85 changes: 62 additions & 23 deletions src/SiVaContainer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -55,33 +55,72 @@ using namespace xercesc;
using json = nlohmann::json;

static std::string base64_decode(const XMLCh *in) {
static const std::string b = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
static const std::vector<int> T = [] {
std::vector<int> T(256, -1);
for (size_t i = 0; i < b.size(); ++i)
T[b[i]] = i;
return T;
}();
static constexpr std::array<std::uint8_t, 128> T{
0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64,
0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64,
0x64, 0x64, 0x64, 0x64, 0x64, 0x3E, 0x64, 0x64, 0x64, 0x3F, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C,
0x3D, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A,
0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x64, 0x64, 0x64, 0x64,
0x64, 0x64, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A,
0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32, 0x33, 0x64, 0x64, 0x64, 0x64, 0x64
};

std::string out;
int val = 0;
int valb = -8;
int value = 0;
int bits = -8;
for(; in; ++in)
{
const char c(*in);
if(c == '\r' || c == '\n' || c == ' ')
continue;
if(T[c] == -1)
uint8_t check = T[c];
if(check == 0x64)
break;
val = (val << 6) + T[c];
if((valb += 6) < 0)
value = (value << 6) + check;
if((bits += 6) < 0)
continue;
out.push_back(char((val >> valb) & 0xFF));
valb -= 8;
out.push_back(char((value >> bits) & 0xFF));
bits -= 8;
}
return out;
}

// move string to this class to avoid copy (C++20 replace std::stringview)
struct imemstream: istream
{
struct membuf final: streambuf
{
membuf(char *p, size_t size)
{
setg(p, p, p + size);
}

pos_type seekpos(pos_type sp, ios_base::openmode which) final
{
return seekoff(sp - pos_type(off_type(0)), ios_base::beg, which);
}

pos_type seekoff(off_type off, ios_base::seekdir dir, ios_base::openmode /* which */) final
{
switch(dir)
{
case ios_base::cur: gbump(int(off)); break;
case ios_base::end: setg(eback(), egptr() + off, egptr()); break;
case ios_base::beg: setg(eback(), eback() + off, egptr()); break;
}
return gptr() - eback();
}
};

explicit imemstream(string &&_data)
: istream(&buf)
, data(std::move(_data))
, buf(data.data(), data.size())
{}

string data;
membuf buf;
};


class SiVaContainer::Private
Expand Down Expand Up @@ -141,10 +180,10 @@ void SignatureSiVa::validate(const string &policy) const


SiVaContainer::SiVaContainer(const string &path, const string &ext, bool useHashCode)
: d(new Private)
: d(make_unique<Private>())
{
DEBUG("SiVaContainer::SiVaContainer(%s, %s, %d)", path.c_str(), ext.c_str(), useHashCode);
unique_ptr<istream> ifs(new ifstream(File::encodeName(d->path = path).c_str(), ifstream::binary));
unique_ptr<istream> ifs = make_unique<ifstream>(File::encodeName(d->path = path).c_str(), ifstream::binary);
istream *is = ifs.get();
if(ext == "DDOC")
{
Expand Down Expand Up @@ -175,6 +214,7 @@ SiVaContainer::SiVaContainer(const string &path, const string &ext, bool useHash
b64.append((char*)out, size);
delete out;
}
ifs.release();

string url = CONF(verifyServiceUri);
string req = json({
Expand Down Expand Up @@ -281,7 +321,6 @@ SiVaContainer::~SiVaContainer()
delete s;
for(const DataFile *f: d->dataFiles)
delete f;
delete d;
}

void SiVaContainer::addDataFile(const string & /*path*/, const string & /*mediaType*/)
Expand Down Expand Up @@ -353,8 +392,10 @@ stringstream* SiVaContainer::parseDDoc(istream &is, bool useHashCode)

if(const XMLCh *b64 = item->getTextContent())
{
d->dataFiles.push_back(new DataFilePrivate(unique_ptr<istream>(new stringstream(base64_decode(b64))),
transcode(item->getAttribute(cpXMLCh(u"Filename"))), transcode(item->getAttribute(cpXMLCh(u"MimeType"))), transcode(item->getAttribute(cpXMLCh(u"Id")))));
d->dataFiles.push_back(new DataFilePrivate(make_unique<imemstream>(base64_decode(b64)),
transcode(item->getAttribute(cpXMLCh(u"Filename"))),
transcode(item->getAttribute(cpXMLCh(u"MimeType"))),
transcode(item->getAttribute(cpXMLCh(u"Id")))));
}

if(!useHashCode)
Expand All @@ -377,7 +418,7 @@ stringstream* SiVaContainer::parseDDoc(istream &is, bool useHashCode)
DOMImplementation *pImplement = DOMImplementationRegistry::getDOMImplementation(cpXMLCh(u"LS"));
unique_ptr<DOMLSOutput> pDomLsOutput(pImplement->createLSOutput());
unique_ptr<DOMLSSerializer> pSerializer(pImplement->createLSSerializer());
unique_ptr<stringstream> result(new stringstream);
unique_ptr<stringstream> result = make_unique<stringstream>();
xsd::cxx::xml::dom::ostream_format_target out(*result);
pDomLsOutput->setByteStream(&out);
pSerializer->setNewLine(cpXMLCh(u"\n"));
Expand Down Expand Up @@ -439,11 +480,9 @@ void SiVaContainer::save(const string &path)
string to = path.empty() ? d->path : path;
if(d->data)
{
ofstream ofs(File::encodeName(to).c_str(), ofstream::binary);
d->data->clear();
d->data->seekg(0);
ofs << d->data->rdbuf();
ofs.close();
ofstream(File::encodeName(to).c_str(), ofstream::binary) << d->data->rdbuf();
}
else
d->dataFiles[0]->saveAs(to);
Expand Down
2 changes: 1 addition & 1 deletion src/SiVaContainer.h
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ class SiVaContainer final: public Container
std::stringstream* parseDDoc(std::istream &is, bool useHashCode);

class Private;
Private *d;
std::unique_ptr<Private> d;
};

}
5 changes: 3 additions & 2 deletions src/xml/SecureDOMParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -113,9 +113,10 @@ void SecureDOMParser::calcDigestOnNode(Digest *calc,
THROW("Unsupported canonicalization method '%s'", algorithmType.c_str());
}

unsigned char buffer[1024];
constexpr int bufferSize = 10*1024;
unsigned char buffer[bufferSize];
XMLSize_t bytes = 0;
while((bytes = c14n.outputBuffer(buffer, 1024)) > 0)
while((bytes = c14n.outputBuffer(buffer, bufferSize)) > 0)
calc->update(buffer, bytes);
}

Expand Down

0 comments on commit 26d4484

Please sign in to comment.