Add wxInputStream::ReadAll() and wxOutputStream::WriteAll().

Unlike Read() and Write(), these functions always transfer exactly the
specified number of bytes or fail.

See #12056.

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@74034 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Vadim Zeitlin
2013-05-20 13:15:16 +00:00
parent 54582f9ac6
commit cc437b9654
4 changed files with 107 additions and 0 deletions

View File

@@ -576,6 +576,7 @@ All:
- Add wxDIR_NO_FOLLOW flag for wxDir traversal (David Hart).
- Allow testing for symlink/FIFO/socket existence in wxFileName (David Hart).
- Many important bug fixes in wxFileSystemWatcher (David Hart).
- Add wxInputStream::ReadAll() and wxOutputStream::WriteAll() (Catalin Raceanu).
- Add new wxFSW_EVENT_ATTRIB and wxFSW_EVENT_UNMOUNT flags (David Hart).
- Add separate read/written bytes counters and per-direction NOWAIT and WAITALL
flags to wxSocket (Rob Bresalier).

View File

@@ -128,6 +128,11 @@ public:
// it means that EOF has been reached.
virtual wxInputStream& Read(void *buffer, size_t size);
// Read exactly the given number of bytes, unlike Read(), which may read
// less than the requested amount of data without returning an error, this
// method either reads all the data or returns false.
bool ReadAll(void *buffer, size_t size);
// copy the entire contents of this stream into streamOut, stopping only
// when EOF is reached or an error occurs
wxInputStream& Read(wxOutputStream& streamOut);
@@ -233,6 +238,12 @@ public:
void PutC(char c);
virtual wxOutputStream& Write(const void *buffer, size_t size);
// This is ReadAll() equivalent for Write(): it either writes exactly the
// given number of bytes or returns false, unlike Write() which can write
// less data than requested but still return without error.
bool WriteAll(const void *buffer, size_t size);
wxOutputStream& Write(wxInputStream& stream_in);
virtual wxFileOffset SeekO(wxFileOffset pos, wxSeekMode mode = wxFromStart);

View File

@@ -537,6 +537,20 @@ public:
*/
wxOutputStream& Write(wxInputStream& stream_in);
/**
Writes exactly the specified number of bytes from the buffer.
Returns @true if exactly @a size bytes were written. Otherwise, returns
@false and LastWrite() should be used to retrieve the exact amount of
the data written if necessary.
This method uses repeated calls to Write() (which may return writing
only part of the data) if necessary.
@since 2.9.5
*/
bool WriteAll(const void* buffer, size_t size);
protected:
/**
Internal function. It is called when the stream wants to write data of the
@@ -629,6 +643,23 @@ public:
*/
wxInputStream& Read(wxOutputStream& stream_out);
/**
Reads exactly the specified number of bytes into the buffer.
Returns @true only if the entire amount of data was read, otherwise
@false is returned and the number of bytes really read can be retrieved
using LastRead(), as with Read().
This method uses repeated calls to Read() (which may return after
reading less than the requested number of bytes) if necessary.
@warning
The buffer absolutely needs to have at least the specified size.
@since 2.9.5
*/
bool ReadAll(void* buffer, size_t size);
/**
Changes the stream current position.

View File

@@ -913,6 +913,42 @@ wxInputStream& wxInputStream::Read(wxOutputStream& stream_out)
return *this;
}
bool wxInputStream::ReadAll(void *buffer_, size_t size)
{
char* buffer = static_cast<char*>(buffer_);
m_lastcount = 0;
for ( ;; )
{
const size_t lastCount = Read(buffer, size).LastRead();
// There is no point in continuing looping if we can't read anything at
// all.
if ( !lastCount )
break;
m_lastcount += lastCount;
// ... Or if an error occurred on the stream.
if ( !IsOk() )
break;
// Return successfully if we read exactly the requested number of
// bytes (normally the ">" case should never occur and so we could use
// "==" test, but be safe and avoid overflowing size even in case of
// bugs in LastRead()).
if ( lastCount >= size )
return true;
// Advance the buffer before trying to read the rest of data.
size -= lastCount;
buffer += lastCount;
}
return false;
}
wxFileOffset wxInputStream::SeekI(wxFileOffset pos, wxSeekMode mode)
{
// RR: This code is duplicated in wxBufferedInputStream. This is
@@ -1030,6 +1066,34 @@ wxOutputStream& wxOutputStream::Write(wxInputStream& stream_in)
return *this;
}
bool wxOutputStream::WriteAll(const void *buffer_, size_t size)
{
// This exactly mirrors ReadAll(), see there for more comments.
const char* buffer = static_cast<const char*>(buffer_);
m_lastcount = 0;
for ( ;; )
{
const size_t lastCount = Write(buffer, size).LastWrite();
if ( !lastCount )
break;
m_lastcount += lastCount;
if ( !IsOk() )
break;
if ( lastCount >= size )
return true;
size -= lastCount;
buffer += lastCount;
}
return false;
}
wxFileOffset wxOutputStream::TellO() const
{
return OnSysTell();