#include "../shared/SimpleLogFile.h" #include "SerializeValuesByName.h" ///////////////////////////////////////////////////////////////////// // SerializeRecords ///////////////////////////////////////////////////////////////////// void SerializeRecords::addRecord(std::string &destination, RecordBuilder &source) { // Interesting. RecordBuilder::exportAsString() isn't const. It would // take some changes to make it const. Easier just to accept it than to // fix it. std::string asString = source.exportAsString(); size_t size = asString.size(); assert(size <= 0xffffff); // Three bytes destination.append((char *)(&size), 3); destination += asString; } void SerializeRecords::loadNames(RecordBuilder &header, ValuesByName const &source) { for (auto it = source.begin(); it != source.end(); it++) if (!_names.count(it->first)) { const int fieldId = _names.size(); _names[it->first] = fieldId; header.append(fieldId, it->first); } } void SerializeRecords::go(RecordBuilder &record, ValuesByName const &source) const { for (auto it = source.begin(); it != source.end(); it++) { std::string const &name = it->first; const int fieldId = getProperty(_names, name, -1); assert(fieldId != -1); it->second.appendTo(record, fieldId); } } ///////////////////////////////////////////////////////////////////// // DeserializeRecords ///////////////////////////////////////////////////////////////////// std::vector< Record::Ref > DeserializeRecords::getRecords(std::string const &source) { std::vector< Record::Ref > result; int offset = 0; while (true) { int remaining = ((int)source.length()) - offset; if (remaining == 0) return result; if (remaining < 3) { reportError("getRecords() invalid record header"); return std::vector< Record::Ref >(); } int recordSize = 0; char *p = (char *)&recordSize; *p++ = source[offset++]; *p++ = source[offset++]; *p++ = source[offset++]; remaining -= 3; if (recordSize > remaining) { reportError("getRecords() incomplete record"); return std::vector< Record::Ref >(); } Record::Ref record = Record::create(source.substr(offset, recordSize)); if (!record) { reportError("getRecords() invalid record"); return std::vector< Record::Ref >(); } result.push_back(record); offset += recordSize; } } void DeserializeRecords::reportError(std::string const &type) { static const bool immediate = false; if (immediate) { // Useful in testing. You can see exactly which test case failed. Also, // our tests usually abort before the 5 minute timer would print the // first ThreadMonitor data. TclList msg; msg<first <second.shortDebug(); result< const &rows) { for (auto it = rows.begin(); it != rows.end(); it++) addTo< const &rows) { TclList result; debugDump(result, rows); return result; }