Implement direct file i/o to- and from blocks.

This commit is contained in:
Leonetienne
2022-05-26 04:22:42 +02:00
parent 101a1e0fd6
commit 81a9570673
7 changed files with 205 additions and 56 deletions

View File

@@ -1,5 +1,6 @@
#include "GCrypt/Util.h"
#include "GCrypt/GHash.h"
#include <vector>
namespace Leonetienne::GCrypt {
@@ -50,13 +51,22 @@ namespace Leonetienne::GCrypt {
return Flexblock(ss.str());
}
std::string BitblockToBytes(const Block& bits) {
std::string BitblockToBytes(const Block& block) {
std::stringstream ss;
const std::string bitstring = bits.ToString();
std::uint8_t* curByte = (std::uint8_t*)(void*)block.Data();
for (std::size_t j = 0; j < Block::BLOCK_SIZE; j++) {
ss << *curByte++;
}
for (std::size_t i = 0; i < Block::BLOCK_SIZE_BITS; i += 8) {
ss << (char)std::bitset<8>(bitstring.substr(i, 8)).to_ulong();
return ss.str();
}
std::string BitblocksToBytes(const std::vector<Block>& blocks) {
std::stringstream ss;
for (const Block& block : blocks) {
ss << BitblockToBytes(block);
}
return ss.str();
@@ -72,6 +82,16 @@ namespace Leonetienne::GCrypt {
return text;
}
std::string BitblocksToString(const std::vector<Block>& blocks) {
// Decode to bytes
std::string text = BitblocksToBytes(blocks);
// Dümp excess nullbytes
text.resize(strlen(text.data()));
return text;
}
std::string BitsToBytes(const Flexblock& bits) {
std::stringstream ss;
@@ -211,5 +231,113 @@ namespace Leonetienne::GCrypt {
return;
}
std::vector<Block> ReadFileToBlocks(const std::string& filepath) {
// Read file
// "ate" specifies that the read-pointer is already at the end of the file
// this allows to estimate the file size
std::ifstream ifs(filepath, std::ios::binary | std::ios::ate);
if (!ifs.good()) {
throw std::runtime_error("Unable to open ifilestream!");
}
// Create our vector of blocks, and resorve a good guess
// of memory
std::vector<Block> blocks;
blocks.reserve((ifs.tellg() / Block::BLOCK_SIZE) + 1);
// Move read head to the file beginning
ifs.seekg(std::ios_base::beg);
// Whilst not reached eof, read into blocks
while (!ifs.eof()) {
// Create a new block, and zero it
Block block;
block.Reset();
// Read data into the block
ifs.read((char*)(void*)block.Data(), Block::BLOCK_SIZE);
const std::size_t n_bytes_read = ifs.gcount();
if (n_bytes_read > 0) {
// Append the block to our vector
blocks.emplace_back(block);
}
}
// Close the filehandle
ifs.close();
return blocks;
}
void WriteBlocksToFile(
const std::string& filepath,
const std::vector<Block>& blocks
){
// Create outfile file handle
std::ofstream ofs(filepath, std::ios::binary);
if (!ofs.good()) {
throw std::runtime_error("Unable to open ofilestream!");
}
// Write all the blocks
for (const Block& block : blocks) {
ofs.write((char*)(void*)block.Data(), Block::BLOCK_SIZE);
}
// Close the filehandle
ofs.close();
return;
}
std::vector<Block> StringToBitblocks(const std::string& s) {
// Create our block vector, and reserve exactly
// how many blocks are required to store this string
const std::size_t num_blocks = (s.length() / Block::BLOCK_SIZE) + 1;
std::vector<Block> blocks;
blocks.reserve(num_blocks);
for (std::size_t i = 0; i < num_blocks; i++) {
// Create new block, and zero it
Block block;
block.Reset();
std::size_t bytes_copied = 0;
// Iterate over all bytes in the block
std::uint8_t* curByte = (std::uint8_t*)(void*)block.Data();
for (std::size_t j = 0; j < Block::BLOCK_SIZE; j++) {
curByte++;
// Carry our character over
const std::size_t strIdx = i*Block::BLOCK_SIZE + j;
// The string still has chars to give
if (strIdx < s.length()) {
*curByte = s[j];
bytes_copied++;
}
// We've reached the end of the string
else {
// Save our block, if it contains any bytes
if (bytes_copied) {
blocks.emplace_back(block);
}
// Return our blocks
return blocks;
}
}
}
return blocks;
}
}