I have a problem, mostly because I can't really understand how to handle the situation.
I have a char*
buffer of X
size, it's the content of an encrypted file who's got decrypted and will be then parsed by the ifstream
handler class that i can't edit.
So my idea was to create an fstream
object in which, with rdbuf()
assign the buffer with sputn
.
fstream _handle2;
_handle2.rdbuf()->sputn(_buffer, _size);
_handle2.flush();
But of course, it's not working and buffer does not get written into the fstream
object, do you have any idea of how to make it so?
I tried different methods but I clearly can't figure out what to do.
I'm trying to create a buffer type that can be parsed similarly to a ifstream.
You might try something like this (adopted from the link I provided in the comment already):
std::ifstream ifs("test.txt", std::ifstream::binary);
if (ifs)
{
ifs.seekg (0, ifs.end);
int length = ifs.tellg();
ifs.seekg (0, ifs.beg);
std::string buffer;
buffer.resize(length);
ifs.read(const_cast<char*>(buffer.data()), length);
if (ifs)
{
// de-crypt the buffer here!
// something like:
// buffer[i] = decryptChar(buffer[i]);
std::istringstream iss(buffer);
// now you can use iss just the same way as ifs,
// if the file was not encrypted...
}
else
{
std::cout << "error: only " << ifs.gcount() << " bytes could be read";
}
ifs.close();
}
Edit in response to your comment:
std::istringstream
is used to convert text into binary data, e. g. int n; iss >> n;
would convert the string "20102012", represented by ascii sequence 0x32, 0x30, 0x31, 0x30, 0x32, 0x30, 0x31, 0x32 into the corresponding four-byte integer value of 0x0132bb7c). But if data is already binary, std::istringstream
is not suitable. Then you might rather try to write your own stream class similar to this example:
class DecryptionStream
{
std::unique_ptr<char> mBuffer;
char* mEnd;
char* mPos;
unsigned int flags;
unsigned int const eofbit = 1 << 0;
unsigned int const failbit = 1 << 1;
// other flag bits as needed
public:
// fail/eof bits as needed
DecryptionStream(char const* fileName) : mPos(nullptr)
{
std::ifstream ifs(fileName, std::ifstream::binary);
if (ifs)
{
ifs.seekg (0, ifs.end);
int length = ifs.tellg();
ifs.seekg (0, ifs.beg);
mBuffer.reset(new char[length]);
ifs.read(mBuffer.get(), length);
if (ifs)
{
// de-crypt the buffer here!
// something like:
// buffer[i] = decryptChar(buffer[i]);
mPos = mBuffer.get();
mEnd = mBuffer.get() + length;
}
else
{
flags |= failbit;
}
ifs.close();
}
}
template<typename T>
DecryptionStream& operator >>(T& t)
{
// fail, if any fail bit set already
size_t avail = mPos - mEnd;
if (avail < sizeof(t))
{
flags |= eofbit | failbit;
}
else
{
if(avail == sizeof(t))
{
flags |= eofbit;
}
memcpy(&t, mPos, sizeof(t));
mPos += sizeof(t);
}
return *this;
}
operator bool()
{
return flags == 0;
}
};
You could even use this class with complex data types - then make sure, though, that you control byte alignment of these appropriately, otherwise you might fail badly!