Merge pull request #688 from martin-osborne/issue_297

Issue #297 - Added implementation of seekoff to BasicMemoryStreamBuf
This commit is contained in:
Aleksandar Fabijanic 2015-01-25 20:56:20 -06:00
commit f440c4b101
3 changed files with 409 additions and 0 deletions

View File

@ -74,6 +74,66 @@ public:
return char_traits::eof();
}
virtual pos_type seekoff(off_type off, std::ios_base::seekdir way, std::ios_base::openmode which = std::ios_base::in | std::ios_base::out)
{
const pos_type fail = off_type(-1);
off_type newoff = off_type(-1);
if ((which & std::ios_base::in) != 0)
{
if (this->gptr() == 0)
return fail;
switch (way)
{
case std::ios_base::beg:
newoff = 0;
break;
case std::ios_base::cur:
// cur is not valid if both in and out are specified (Condition 3)
if ((which & std::ios_base::out) != 0)
return fail;
newoff = this->gptr() - this->eback();
break;
case std::ios_base::end:
newoff = this->egptr() - this->eback();
break;
}
if ((newoff + off) < 0 || (this->egptr() - this->eback()) < (newoff + off))
return fail;
this->setg(this->eback(), this->eback() + newoff + off, this->egptr());
}
if ((which & std::ios_base::out) != 0)
{
if (this->pptr() == 0)
return fail;
switch (way)
{
case std::ios_base::beg:
newoff = 0;
break;
case std::ios_base::cur:
// cur is not valid if both in and out are specified (Condition 3)
if ((which & std::ios_base::in) != 0)
return fail;
newoff = this->pptr() - this->pbase();
break;
case std::ios_base::end:
newoff = this->epptr() - this->pbase();
break;
}
if (newoff + off < 0 || (this->epptr() - this->pbase()) < newoff + off)
return fail;
this->pbump((int)(newoff + off - (this->pptr() - this->pbase())));
}
return newoff;
}
virtual int sync()
{
return 0;

View File

@ -13,8 +13,10 @@
#include "MemoryStreamTest.h"
#include "CppUnit/TestCaller.h"
#include "CppUnit/TestSuite.h"
#include "Poco/Buffer.h"
#include "Poco/MemoryStream.h"
#include <sstream>
using Poco::MemoryInputStream;
using Poco::MemoryOutputStream;
@ -86,6 +88,343 @@ void MemoryStreamTest::testOutput()
assert (ostr2.fail());
}
void MemoryStreamTest::testTell()
{
Poco::Buffer<char> buffer(1024);
Poco::MemoryOutputStream ostr(buffer.begin(), buffer.size());
ostr << 'H' << 'e' << 'l' << 'l' << 'o' << '\0';
std::streamoff np = ostr.tellp();
assert (np == 6);
Poco::MemoryInputStream istr(buffer.begin(), buffer.size());
char c;
istr >> c;
assert (c == 'H');
istr >> c;
assert (c == 'e');
istr >> c;
assert (c == 'l');
std::streamoff ng = istr.tellg();
assert (ng == 3);
}
void MemoryStreamTest::testInputSeek()
{
Poco::Buffer<char> buffer(9);
Poco::MemoryOutputStream ostr(buffer.begin(), buffer.size());
ostr << '1' << '2' << '3' << '4' << '5' << '6' << '7' << '8' << '9';
Poco::MemoryInputStream istr(buffer.begin(), buffer.size());
char c;
istr >> c;
assert (c == '1');
istr.seekg(3, std::ios_base::beg); // 3 from beginning
istr >> c; // now that makes 4
assert (istr.tellg() == 4);
assert (c == '4');
istr.seekg(2, std::ios_base::cur); // now that makes 6
istr >> c; // now that makes 7
assert (istr.tellg() == 7);
assert (c == '7');
istr.seekg(-7, std::ios_base::end); // so that puts us at 9-7=2
istr >> c; // now 3
assert (istr.tellg() == 3);
assert (c == '3');
istr.seekg(9, std::ios_base::beg);
assert (istr.good());
assert (istr.tellg() == 9);
{
Poco::MemoryInputStream istr2(buffer.begin(), buffer.size());
istr2.seekg(10, std::ios_base::beg);
assert (istr2.fail());
}
istr.seekg(-9, std::ios_base::end);
assert (istr.good());
assert (istr.tellg() == 0);
{
Poco::MemoryInputStream istr2(buffer.begin(), buffer.size());
istr2.seekg(-10, std::ios_base::end);
assert (istr2.fail());
}
istr.seekg(0, std::ios_base::beg);
assert (istr.good());
assert (istr.tellg() == 0);
{
Poco::MemoryInputStream istr2(buffer.begin(), buffer.size());
istr2.seekg(-1, std::ios_base::beg);
assert (istr2.fail());
}
istr.seekg(0, std::ios_base::end);
assert (istr.good());
assert (istr.tellg() == 9);
{
Poco::MemoryInputStream istr2(buffer.begin(), buffer.size());
istr2.seekg(1, std::ios_base::end);
assert (istr2.fail());
}
istr.seekg(3, std::ios_base::beg);
assert (istr.good());
assert (istr.tellg() == 3);
istr.seekg(6, std::ios_base::cur);
assert (istr.good());
assert (istr.tellg() == 9);
{
Poco::MemoryInputStream istr2(buffer.begin(), buffer.size());
istr2.seekg(4, std::ios_base::beg);
istr2.seekg(6, std::ios_base::cur);
assert (istr2.fail());
}
istr.seekg(-4, std::ios_base::end);
assert (istr.good());
assert (istr.tellg() == 5);
istr.seekg(4, std::ios_base::cur);
assert (istr.good());
assert (istr.tellg() == 9);
{
Poco::MemoryInputStream istr2(buffer.begin(), buffer.size());
istr2.seekg(-4, std::ios_base::end);
istr2.seekg(5, std::ios_base::cur);
assert (istr2.fail());
}
istr.seekg(4, std::ios_base::beg);
assert (istr.good());
assert (istr.tellg() == 4);
istr.seekg(-4, std::ios_base::cur);
assert (istr.good());
assert (istr.tellg() == 0);
{
Poco::MemoryInputStream istr2(buffer.begin(), buffer.size());
istr2.seekg(4, std::ios_base::beg);
istr2.seekg(-5, std::ios_base::cur);
assert (istr2.fail());
}
}
void MemoryStreamTest::testInputSeekVsStringStream()
{
Poco::Buffer<char> buffer(9);
Poco::MemoryOutputStream ostr(buffer.begin(), buffer.size());
ostr << '1' << '2' << '3' << '4' << '5' << '6' << '7' << '8' << '9';
std::stringstream sss;
sss << '1' << '2' << '3' << '4' << '5' << '6' << '7' << '8' << '9';
Poco::MemoryInputStream mis(buffer.begin(), buffer.size());
char x, y;
sss >> x;
mis >> y;
assert (x == y);
sss.seekg(3, std::ios_base::beg);
mis.seekg(3, std::ios_base::beg);
sss >> x;
mis >> y;
assert (x == y);
assert (sss.tellg() == mis.tellg());
sss.seekg(2, std::ios_base::cur);
mis.seekg(2, std::ios_base::cur);
sss >> x;
mis >> y;
assert (x == y);
assert (sss.tellg() == mis.tellg());
sss.seekg(-7, std::ios_base::end);
mis.seekg(-7, std::ios_base::end);
sss >> x;
mis >> y;
assert (x == y);
assert (sss.tellg() == mis.tellg());
}
void MemoryStreamTest::testOutputSeek()
{
Poco::Buffer<char> buffer(9);
Poco::MemoryOutputStream ostr(buffer.begin(), buffer.size());
ostr << '1' << '2' << '3' << '4' << '5' << '6' << '7' << '8' << '9';
ostr.seekp(4, std::ios_base::beg); // 4 from beginning
ostr << 'a'; // and that makes 5 (zero index 4)
assert (ostr.tellp() == 5);
assert (buffer[4] == 'a');
ostr.seekp(2, std::ios_base::cur); // and this makes 7
ostr << 'b'; // and this makes 8 (zero index 7)
assert (ostr.tellp() == 8);
assert (buffer[7] == 'b');
ostr.seekp(-3, std::ios_base::end); // 9-3=6 from the beginning
ostr << 'c'; // and this makes 7 (zero index 6)
assert (ostr.tellp() == 7);
assert (buffer[6] == 'c');
ostr.seekp(9, std::ios_base::beg);
assert (ostr.good());
assert (ostr.tellp() == 9);
{
Poco::MemoryOutputStream ostr2(buffer.begin(), buffer.size());
ostr2.seekp(10, std::ios_base::beg);
assert (ostr2.fail());
}
ostr.seekp(-9, std::ios_base::end);
assert (ostr.good());
assert (ostr.tellp() == 0);
{
Poco::MemoryOutputStream ostr2(buffer.begin(), buffer.size());
ostr2.seekp(-10, std::ios_base::end);
assert (ostr2.fail());
}
ostr.seekp(0, std::ios_base::beg);
assert (ostr.good());
assert (ostr.tellp() == 0);
{
Poco::MemoryOutputStream ostr2(buffer.begin(), buffer.size());
ostr2.seekp(-1, std::ios_base::beg);
assert (ostr2.fail());
}
ostr.seekp(0, std::ios_base::end);
assert (ostr.good());
assert (ostr.tellp() == 9);
{
Poco::MemoryOutputStream ostr2(buffer.begin(), buffer.size());
ostr2.seekp(1, std::ios_base::end);
assert (ostr2.fail());
}
ostr.seekp(3, std::ios_base::beg);
assert (ostr.good());
assert (ostr.tellp() == 3);
ostr.seekp(6, std::ios_base::cur);
assert (ostr.good());
assert (ostr.tellp() == 9);
{
Poco::MemoryOutputStream ostr2(buffer.begin(), buffer.size());
ostr2.seekp(4, std::ios_base::beg);
ostr2.seekp(6, std::ios_base::cur);
assert (ostr2.fail());
}
ostr.seekp(-4, std::ios_base::end);
assert (ostr.good());
assert (ostr.tellp() == 5);
ostr.seekp(4, std::ios_base::cur);
assert (ostr.good());
assert (ostr.tellp() == 9);
{
Poco::MemoryOutputStream ostr2(buffer.begin(), buffer.size());
ostr2.seekp(-4, std::ios_base::end);
ostr2.seekp(5, std::ios_base::cur);
assert (ostr2.fail());
}
ostr.seekp(4, std::ios_base::beg);
assert (ostr.good());
assert (ostr.tellp() == 4);
ostr.seekp(-4, std::ios_base::cur);
assert (ostr.good());
assert (ostr.tellp() == 0);
{
Poco::MemoryOutputStream ostr2(buffer.begin(), buffer.size());
ostr2.seekp(4, std::ios_base::beg);
ostr2.seekp(-5, std::ios_base::cur);
assert (ostr2.fail());
}
}
void MemoryStreamTest::testOutputSeekVsStringStream()
{
Poco::Buffer<char> buffer(9);
Poco::MemoryOutputStream mos(buffer.begin(), buffer.size());
mos << '1' << '2' << '3' << '4' << '5' << '6' << '7' << '8' << '9';
std::ostringstream oss;
oss << '1' << '2' << '3' << '4' << '5' << '6' << '7' << '8' << '9';
mos.seekp(4, std::ios_base::beg);
oss.seekp(4, std::ios_base::beg);
mos << 'a';
oss << 'a';
assert (oss.str()[4] == 'a');
assert (buffer[4] == oss.str()[4]);
assert (oss.tellp() == mos.tellp());
mos.seekp(2, std::ios_base::cur);
oss.seekp(2, std::ios_base::cur);
mos << 'b';
oss << 'b';
assert (oss.str()[7] == 'b');
assert (buffer[7] == oss.str()[7]);
assert (oss.tellp() == mos.tellp());
mos.seekp(-3, std::ios_base::end);
oss.seekp(-3, std::ios_base::end);
mos << 'c';
oss << 'c';
assert (oss.str()[6] == 'c');
assert (buffer[6] == oss.str()[6]);
assert (oss.tellp() == mos.tellp());
mos.seekp(-2, std::ios_base::cur);
oss.seekp(-2, std::ios_base::cur);
mos << 'd';
oss << 'd';
assert (oss.str()[5] == 'd');
assert (buffer[5] == oss.str()[5]);
assert (oss.tellp() == mos.tellp());
}
void MemoryStreamTest::setUp()
{
@ -103,6 +442,11 @@ CppUnit::Test* MemoryStreamTest::suite()
CppUnit_addTest(pSuite, MemoryStreamTest, testInput);
CppUnit_addTest(pSuite, MemoryStreamTest, testOutput);
CppUnit_addTest(pSuite, MemoryStreamTest, testTell);
CppUnit_addTest(pSuite, MemoryStreamTest, testInputSeek);
CppUnit_addTest(pSuite, MemoryStreamTest, testInputSeekVsStringStream);
CppUnit_addTest(pSuite, MemoryStreamTest, testOutputSeek);
CppUnit_addTest(pSuite, MemoryStreamTest, testOutputSeekVsStringStream);
return pSuite;
}

View File

@ -28,6 +28,11 @@ public:
void testInput();
void testOutput();
void testTell();
void testInputSeek();
void testInputSeekVsStringStream();
void testOutputSeek();
void testOutputSeekVsStringStream();
void setUp();
void tearDown();