From 8291b5884c1c4c5278473886cdf1bb0f022aac99 Mon Sep 17 00:00:00 2001 From: Caolán McNamara Date: Fri, 29 Jul 2011 00:02:42 +0100 Subject: make stream operators leave variables in original state on failure this aligns them with the behaviour of std::stream, and makes things like sal_uInt32 n(0); rSt >> n; if (n) { ... } safe if there was a short read of e.g. 3 bytes instead of the required 4 --- tools/inc/tools/stream.hxx | 18 +++--- tools/qa/cppunit/test_streamstate.cxx | 5 +- tools/source/stream/stream.cxx | 113 +++++++++++++++++++++++----------- 3 files changed, 91 insertions(+), 45 deletions(-) (limited to 'tools') diff --git a/tools/inc/tools/stream.hxx b/tools/inc/tools/stream.hxx index 707b830d78c9..82ff78ce554f 100644 --- a/tools/inc/tools/stream.hxx +++ b/tools/inc/tools/stream.hxx @@ -526,18 +526,22 @@ public: friend SvStream& operator<<( SvStream& rStr, SvStrPtr f ); // fuer Manips - //end of input seen + //end of input seen during previous i/o operation bool eof() const { return bIsEof; } // stream is broken bool bad() const { return GetError() != 0; } - //next operation might succeed. If the state is good() the previous i/o - //operation succeeded. If the state is good(), the next input operation - //might succeed; otherwise, it will fail. Applying an input operation to a - //stream that is not in the good() state is a null operation as far as the - //variable being read into is concerned. If we try to read into a variable - //v and the operation fails, the value of v should be unchanged, + //If the state is good() the previous i/o operation succeeded. + // + //If the state is good(), the next input operation might succeed; + //otherwise, it will fail. + // + //Applying an input operation to a stream that is not in the good() state + //is a null operation as far as the variable being read into is concerned. + // + //If we try to read into a variable v and the operation fails, the value of + //v should be unchanged, bool good() const { return !(eof() || bad()); } }; diff --git a/tools/qa/cppunit/test_streamstate.cxx b/tools/qa/cppunit/test_streamstate.cxx index c2a4be0c5e00..182ad6c45561 100644 --- a/tools/qa/cppunit/test_streamstate.cxx +++ b/tools/qa/cppunit/test_streamstate.cxx @@ -94,6 +94,9 @@ namespace //yet, the read didn't succeed CPPUNIT_ASSERT(!aMemStream.good()); + //set things up so that there is only one byte available on an attempt + //to read a two-byte sal_uInt16. The byte should be consumed, but the + //operation should fail, and tools_b should remain unchanged, sal_uInt16 tools_b = 0x1122; aMemStream.SeekRel(-1); CPPUNIT_ASSERT(!aMemStream.eof()); @@ -101,7 +104,7 @@ namespace aMemStream >> tools_b; CPPUNIT_ASSERT(!aMemStream.good()); CPPUNIT_ASSERT(aMemStream.eof()); -// CPPUNIT_ASSERT(tools_b == 0x1122); //nasty, real nasty + CPPUNIT_ASSERT(tools_b == 0x1122); iss.clear(); iss.seekg(0); diff --git a/tools/source/stream/stream.cxx b/tools/source/stream/stream.cxx index 2917776e6212..84ae7bfb72ee 100644 --- a/tools/source/stream/stream.cxx +++ b/tools/source/stream/stream.cxx @@ -1158,58 +1158,89 @@ sal_Size SvStream::SeekRel( sal_sSize nPos ) |* *************************************************************************/ -SvStream& SvStream::operator >> ( sal_uInt16& r ) +SvStream& SvStream::operator>>(sal_uInt16& r) { - READNUMBER_WITHOUT_SWAP(sal_uInt16,r) - if( bSwap ) - SwapUShort(r); + sal_uInt16 n; + READNUMBER_WITHOUT_SWAP(sal_uInt16, n) + if (good()) + { + if (bSwap) + SwapUShort(n); + r = n; + } return *this; } -SvStream& SvStream::operator>> ( sal_uInt32& r ) +SvStream& SvStream::operator>>(sal_uInt32& r) { - READNUMBER_WITHOUT_SWAP(sal_uInt32,r) - if( bSwap ) - SwapULong(r); + sal_uInt32 n; + READNUMBER_WITHOUT_SWAP(sal_uInt32, n) + if (good()) + { + if (bSwap) + SwapULong(n); + r = n; + } return *this; } -SvStream& SvStream::operator>> ( sal_uInt64& r ) +SvStream& SvStream::operator>>(sal_uInt64& r) { - READNUMBER_WITHOUT_SWAP(sal_uInt64,r) - if( bSwap ) - SwapUInt64(r); + sal_uInt64 n; + READNUMBER_WITHOUT_SWAP(sal_uInt64, n) + if (good()) + { + if (bSwap) + SwapUInt64(n); + r = n; + } return *this; } -SvStream& SvStream::operator >> ( long& r ) +SvStream& SvStream::operator >>(long& r) //puke!, kill this { #if(SAL_TYPES_SIZEOFLONG != 4) - int tmp = r; - *this >> tmp; - r = tmp; + int n; + *this >> n; + if (good()) + r = n; #else - READNUMBER_WITHOUT_SWAP(long,r) - if( bSwap ) - SwapLong(r); + long n; + READNUMBER_WITHOUT_SWAP(long, n) + if (good()) + { + if (bSwap) + SwapLong(n); + r = n; + } #endif return *this; } -SvStream& SvStream::operator >> ( short& r ) +SvStream& SvStream::operator>>(short& r) { - READNUMBER_WITHOUT_SWAP(short,r) - if( bSwap ) - SwapShort(r); + short n; + READNUMBER_WITHOUT_SWAP(short, n) + if (good()) + { + if(bSwap) + SwapShort(n); + r = n; + } return *this; } -SvStream& SvStream::operator >> ( int& r ) +SvStream& SvStream::operator>>(int& r) { - READNUMBER_WITHOUT_SWAP(int,r) - if( bSwap ) - SwapLongInt(r); + int n; + READNUMBER_WITHOUT_SWAP(int, n) + if (good()) + { + if (bSwap) + SwapLongInt(n); + r = n; + } return *this; } @@ -1260,25 +1291,33 @@ SvStream& SvStream::operator>>( unsigned char& r ) return *this; } -SvStream& SvStream::operator>>( float& r ) +SvStream& SvStream::operator>>(float& r) { - // Read( (char*)&r, sizeof(float) ); - READNUMBER_WITHOUT_SWAP(float,r) + float n; + READNUMBER_WITHOUT_SWAP(float, n) + if (good()) + { #if defined UNX - if( bSwap ) - SwapFloat(r); + if (bSwap) + SwapFloat(n); #endif + r = n; + } return *this; } -SvStream& SvStream::operator>>( double& r ) +SvStream& SvStream::operator>>(double& r) { - // Read( (char*)&r, sizeof(double) ); - READNUMBER_WITHOUT_SWAP(double,r) + double n; + READNUMBER_WITHOUT_SWAP(double, n) + if (good()) + { #if defined UNX - if( bSwap ) - SwapDouble(r); + if (bSwap) + SwapDouble(n); + r = n; #endif + } return *this; } -- cgit