Skip to content

Commit

Permalink
Fixed|libdeng2: Files can only be immutable input streams
Browse files Browse the repository at this point in the history
The assumption with modifiable input streams is that the read bytes
are gone after having been read. This assumption is not compatible
with how byte array files work: the read bytes persist. Therefore,
byte array files can only be used as immutable streams.

However, Reader will automatically check if the stream can be casted
to a byte array, as byte arrays provide random access and are
therefore more useful for reading.
  • Loading branch information
skyjake committed Nov 28, 2012
1 parent ae61c08 commit 4e63713
Show file tree
Hide file tree
Showing 5 changed files with 42 additions and 11 deletions.
6 changes: 4 additions & 2 deletions doomsday/libdeng2/include/de/data/reader.h
Expand Up @@ -66,15 +66,17 @@ class DENG2_PUBLIC Reader
IByteArray::Offset offset = 0);

/**
* Constructs a new reader that reads from a stream.
* Constructs a new reader that reads from a mutable stream. The bytes are
* expected to be removed from the stream once read.
*
* @param stream Stream where input is read.
* @param byteOrder Byte order to use.
*/
Reader(IIStream &stream, ByteOrder const &byteOrder = littleEndianByteOrder);

/**
* Constructs a new reader that reads from a const stream.
* Constructs a new reader that reads from an immutable stream. The bytes
* remain in the stream.
*
* @param stream Const stream where input is read.
* @param byteOrder Byte order to use.
Expand Down
6 changes: 3 additions & 3 deletions doomsday/libdeng2/include/de/filesys/bytearrayfile.h
Expand Up @@ -33,9 +33,9 @@ namespace de
*
* When used as an I/O stream: reading from the stream outputs the entire
* contents of the file, and writing to the stream appends new content to
* the end of the file. There is no difference whether the file is const or
* not, the stream is considered immutable in both cases (i.e., when, say,
* a native file is read, the bytes aren't removed from the file).
* the end of the file. Byte array files must be used is immutable mode;
* the bytes are not removed from the stream by readers (i.e., when, say, a
* native file is read, the bytes aren't removed from the file).
*
* @ingroup fs
*/
Expand Down
2 changes: 2 additions & 0 deletions doomsday/libdeng2/src/core/config.cpp
Expand Up @@ -67,6 +67,8 @@ void Config::read()
// If we already have a saved copy of the config, read it.
File &file = App::rootFolder().locate<File>(_writtenConfigPath);
Reader(file) >> names();

LOG_DEBUG("Serialized Config:\n") << names();

// If the saved config is from a different version, rerun the script.
Value const &oldVersion = names()["__version__"].value();
Expand Down
31 changes: 29 additions & 2 deletions doomsday/libdeng2/src/data/reader.cpp
Expand Up @@ -56,12 +56,39 @@ struct Reader::Instance
Instance(ByteOrder const &order, IIStream *str)
: convert(order), source(0), offset(0), markOffset(0),
stream(str), constStream(0), numReceivedBytes(0), marking(false)
{}
{
upgradeToByteArray();
}

Instance(ByteOrder const &order, IIStream const *str)
: convert(order), source(0), offset(0), markOffset(0),
stream(0), constStream(str), numReceivedBytes(0), marking(false)
{}
{
upgradeToByteArray();
}

/**
* Byte arrays provide more freedom with reading. If the streaming object
* happens to support the byte array interface, Reader will use it instead.
*/
void upgradeToByteArray()
{
if(stream)
{
if((source = dynamic_cast<IByteArray const *>(stream)) != 0)
{
stream = 0;
}
}

if(constStream)
{
if((source = dynamic_cast<IByteArray const *>(constStream)) != 0)
{
constStream = 0;
}
}
}

/**
* Reads bytes from the stream and adds them to the incoming buffer.
Expand Down
8 changes: 4 additions & 4 deletions doomsday/libdeng2/src/filesys/bytearrayfile.cpp
Expand Up @@ -29,11 +29,11 @@ IOStream &ByteArrayFile::operator << (IByteArray const &bytes)
return *this;
}

IIStream &ByteArrayFile::operator >> (IByteArray &bytes)
IIStream &ByteArrayFile::operator >> (IByteArray &)
{
// Behave as a const stream.
*const_cast<ByteArrayFile const *>(this) >> bytes;
return *this;
// Bytes cannot be read from a byte array file in such a way that they would
// be gone from the array.
throw InputError("ByteArrayFile::operator >>", "ByteArrayFile is an immutable stream");
}

IIStream const &ByteArrayFile::operator >> (IByteArray &bytes) const
Expand Down

0 comments on commit 4e63713

Please sign in to comment.