calc/src/code/binsaver.cpp

143 lines
3.8 KiB
C++

#include "../include/binsaver.hpp"
CBinsaver::CBinsaver(std::map<std::string, CRational> &variablesMap) : CSaver(variablesMap) {}
CBinsaver::~CBinsaver() {}
bool CBinsaver::save(const std::string& fileName) {
ssize_t variableCount = m_variables.size();
// ssize_t fileHash = 0;
// uint64_t hashWord;
std::ofstream ofs(fileName);
if (!ofs || !ofs.good())
return false;
std::stringstream ss;
// write variable count
ss << std::to_string(variableCount) + "\n";
// write variables
for (auto& i : m_variables) {
ss << i.first + " " + i.second.toString() + "\n";
}
// calculate file hash
// std::stringstream hashSS(ss.str());
// while (hashSS.read(reinterpret_cast<char*>(&hashWord), sizeof(hashWord))) {
// fileHash ^= hashWord;
// }
// ss << "hash " + std::to_string(fileHash);
ofs << ss.rdbuf();
ofs.close();
return true;
}
bool CBinsaver::load( const std::string &fileName ) {
ssize_t variableCount;
std::ifstream ifs(fileName);
if (!ifs || !ifs.good()) {
m_log = "file reading error";
return false;
}
std::string buffer;
std::getline( ifs, buffer );
// check if variable count is valid
if (buffer.size() < 1 || buffer.size() > 10 || !(std::all_of(buffer.begin(), buffer.end(),
[](unsigned char ch) { return std::isdigit(ch); }) )) {
ifs.close();
m_log = "invalid argument count";
return false;
}
variableCount = std::stoll(buffer);
if (variableCount < 0) {
ifs.close();
m_log = "invalid argument count";
return false;
}
for (;variableCount && std::getline(ifs, buffer); --variableCount) {
std::istringstream iss(buffer);
std::string varName;
std::string numStr;
std::string denStr;
std::string slash;
bool numSign = 0;
bool denSign = 0;
if (!(iss >> varName >> numStr >> slash >> denStr) || slash != "/") {
ifs.close();
m_log = "wrong format";
return false;
}
if (numStr.at(0) == '-') {
numSign = 1;
numStr = numStr.substr(1);
}
if (denStr.at(0) == '-') {
denSign = 1;
denStr = denStr.substr(1);
}
if (!(std::all_of(numStr.begin(), numStr.end(), [](unsigned char ch) { return std::isdigit(ch); }) )
|| !(std::all_of(denStr.begin(), denStr.end(), [](unsigned char ch) { return std::isdigit(ch); }) )) {
ifs.close();
m_log = "invalid number";
return false;
}
for ( auto &c : numStr)
c -= 48;
for ( auto &c : denStr)
c -= 48;
CBigInt *num = new CBigInt(0);
uint64_t insertPosition = 0;
while (!std::all_of(numStr.begin(), numStr.end(), [](char c) { return c == 0; })) {
num->setBit(insertPosition++, CParser::stringDivideDecimal(numStr));
}
CBigInt *den = new CBigInt(0);
insertPosition = 0;
while (!std::all_of(denStr.begin(), denStr.end(), [](char c) { return c == 0; })) {
den->setBit(insertPosition++, CParser::stringDivideDecimal(denStr));
}
num->m_negative = numSign;
den->m_negative = denSign;
if (!m_variables.emplace(varName, CRational(num, den)).second) {
// delete num;
// delete den;
// ifs.close();
// m_log = "varable already exists";
// return false;
}
}
ifs.close();
return true;
}
/*
#binsaveformat
##header
[64bit varible count]
##one variable
[64bit identifier len] [identif]
[64bit datalen] [data]
##padding zeros to 8byte multiply
[0x0000]
[64bit hash]
##hash
xor all 64bit chunks
*/