boost iostreams question(s)

This topic is 3675 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

Recommended Posts

Ok, I am trying to write a wrapper for PhysFS so that I can use it with C++ streams. To simplify this, I decided to try boost iostreams. At the moment I have the following device:
struct input_seekable_device_tag :
boost::iostreams::device_tag,
boost::iostreams::input_seekable
{};

{
public:
typedef char        char_type;
typedef input_seekable_device_tag  category;

{

cout << "Opening file " << fname << endl;

if(!handle)
throw std::runtime_error(physfs::getLastError());
}

{
// Read up to n characters from the input
// sequence into the buffer s, returning
// the number of characters read, or -1
// to indicate end-of-sequence.

{
throw std::runtime_error(physfs::getLastError());
}
{
if(PHYSFS_eof(handle))
return -1;
}

}

std::streampos seek(boost::iostreams::stream_offset off, std::ios_base::seekdir way)
{
// returning the new position, where the offset is
// calculated from:
//  - the start of the sequence if way == ios_base::beg
//  - the current position if way == ios_base::cur
//  - the end of the sequence if way == ios_base::end

PHYSFS_uint64 seekAmt;
PHYSFS_sint64 currentPos;

cout << "Seeking... offset=" << off << endl;

if(way == ios_base::beg)
{
cout << "From beginning..." << endl;
seekAmt = (off > 0) ? static_cast<PHYSFS_uint64>(off) : 0;
}
else if(way == ios_base::cur)
{
cout << "From current..." << endl;
currentPos = PHYSFS_tell(handle);
if(currentPos < 0)
throw std::runtime_error(physfs::getLastError());

currentPos += static_cast<PHYSFS_sint64>(off);

seekAmt = (currentPos > 0) ? static_cast<PHYSFS_uint64>(currentPos) : 0;
}
else if(way == ios_base::end)
{
cout << "From end..." << endl;
currentPos = PHYSFS_fileLength(handle);
if(currentPos < 0) // file length could not be determined... what to do...
throw std::runtime_error("Could not determine file size, possibly streamed");

currentPos += static_cast<PHYSFS_sint64>(off);

seekAmt = (currentPos > 0) ? static_cast<PHYSFS_uint64>(currentPos) : 0;
}
else
throw std::runtime_error("Invalid seek direction");

if(!PHYSFS_seek(handle, static_cast<PHYSFS_uint64>(seekAmt)))
throw std::runtime_error(physfs::getLastError());

currentPos = PHYSFS_tell(handle);
if(currentPos < 0)
throw std::runtime_error(physfs::getLastError());

cout << "New position: " << currentPos << endl;

return std::streampos(static_cast<PHYSFS_uint32>(currentPos));
}

private:
PHYSFS_File* handle;
};


This seems to work fine for the most part... except for the seeking... No matter if I create my final stream this way:
boost::iostreams::stream<PhysfsReadDevice> ifile("somefile.txt");


or this way
boost::iostreams::stream_buffer<PhysfsReadDevice> ifilebuf("somefile.txt");
std::istream ifile(&ifilebuf);


Doing ifile.seekg(123); does not actually call my seek function! Am I doing something wrong? This otoh hand works: ifile.seekg(1234, ios_base::cur); (which, according to the PhysFS api description should report an error, as it seeks beyond the end of the file, but it doesn't. But here the iostreams part seems to work at least...) EDIT: and readsome always returns 0... [Edited by - l0calh05t on January 28, 2008 4:21:12 PM]

Share on other sites
bump...

Well, after some testing I noticed that seekg *does* call my seek function after all, but only if the state flags are good. If the state flags are eof|fail, my seek function is not called, *but* the flags are reset...

Is this behavior normal??

Oh.. and readsome still doesn't work...

EDIT:

well, both behaviors seem to be normal...
seekg behaves the same with a standard filebuf (first call if any flags are set only resets flags)
readsome behaves the same with a standard filebuf (always returns 0)

still doesn't make much sense imo, but at least it doesn't seem to be my fault...

[Edited by - l0calh05t on January 29, 2008 7:34:12 AM]

• 10
• 10
• 11
• 10
• 12