vmime/src/utility/stream.cpp

513 lines
9.0 KiB
C++
Raw Normal View History

2004-10-05 10:28:21 +00:00
//
2005-03-18 21:33:11 +00:00
// VMime library (http://www.vmime.org)
2006-02-05 10:22:59 +00:00
// Copyright (C) 2002-2006 Vincent Richard <vincent@vincent-richard.net>
2004-10-05 10:28:21 +00:00
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
// published by the Free Software Foundation; either version 2 of
// the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// General Public License for more details.
//
2005-09-17 10:10:29 +00:00
// You should have received a copy of the GNU General Public License along along
// with this program; if not, write to the Free Software Foundation, Inc., Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA..
2004-10-05 10:28:21 +00:00
//
#include "vmime/utility/stream.hpp"
#include "vmime/utility/stringProxy.hpp"
2004-10-05 10:28:21 +00:00
#include <algorithm> // for std::copy
#include <iterator> // for std::back_inserter
#if VMIME_HAVE_MESSAGING_FEATURES
#include "vmime/net/socket.hpp"
#endif
2004-10-05 10:28:21 +00:00
namespace vmime {
namespace utility {
2006-11-18 09:27:30 +00:00
// stream
const stream::size_type stream::getBlockSize() const
{
return 32768; // 32 KB
}
2004-10-05 10:28:21 +00:00
// Helpers
outputStream& operator<<(outputStream& os, const stream::value_type c)
{
os.write(&c, 1);
return (os);
}
outputStream& operator<<(outputStream& os, const string& str)
{
os.write(str.data(), str.length());
return (os);
}
const stream::size_type bufferedStreamCopy(inputStream& is, outputStream& os)
{
return bufferedStreamCopy(is, os, 0, NULL);
}
const stream::size_type bufferedStreamCopy(inputStream& is, outputStream& os,
const stream::size_type length, progressListener* progress)
2004-10-05 10:28:21 +00:00
{
2006-11-18 09:27:30 +00:00
const stream::size_type blockSize =
std::min(is.getBlockSize(), os.getBlockSize());
std::vector <stream::value_type> vbuffer(blockSize);
stream::value_type* buffer = &vbuffer.front();
2004-10-05 10:28:21 +00:00
stream::size_type total = 0;
if (progress != NULL)
progress->start(length);
2004-10-05 10:28:21 +00:00
while (!is.eof())
{
const stream::size_type read = is.read(buffer, sizeof(buffer));
if (read != 0)
{
os.write(buffer, read);
total += read;
if (progress != NULL)
progress->progress(total, std::max(total, length));
2004-10-05 10:28:21 +00:00
}
}
if (progress != NULL)
progress->stop(total);
2004-10-05 10:28:21 +00:00
return (total);
}
// outputStreamAdapter
outputStreamAdapter::outputStreamAdapter(std::ostream& os)
: m_stream(os)
{
}
void outputStreamAdapter::write
(const value_type* const data, const size_type count)
{
m_stream.write(data, count);
}
void outputStreamAdapter::flush()
{
m_stream.flush();
}
2004-10-05 10:28:21 +00:00
// outputStreamStringAdapter
outputStreamStringAdapter::outputStreamStringAdapter(string& buffer)
: m_buffer(buffer)
{
}
void outputStreamStringAdapter::write(const value_type* const data, const size_type count)
{
m_buffer.append(data, count);
2004-10-05 10:28:21 +00:00
}
void outputStreamStringAdapter::flush()
{
// Do nothing
}
2004-10-05 10:28:21 +00:00
2005-10-03 21:29:04 +00:00
// outputStreamByteArrayAdapter
outputStreamByteArrayAdapter::outputStreamByteArrayAdapter(byteArray& array)
: m_array(array)
{
}
void outputStreamByteArrayAdapter::write(const value_type* const data, const size_type count)
{
m_array.insert(m_array.end(), data, data + count);
}
void outputStreamByteArrayAdapter::flush()
{
// Do nothing
}
2005-10-03 21:29:04 +00:00
2004-10-05 10:28:21 +00:00
// inputStreamAdapter
inputStreamAdapter::inputStreamAdapter(std::istream& is)
: m_stream(is)
{
}
const bool inputStreamAdapter::eof() const
{
return (m_stream.eof());
}
void inputStreamAdapter::reset()
{
m_stream.seekg(0, std::ios::beg);
m_stream.clear();
}
const stream::size_type inputStreamAdapter::read
(value_type* const data, const size_type count)
{
m_stream.read(data, count);
return (m_stream.gcount());
}
2004-12-16 09:49:55 +00:00
const stream::size_type inputStreamAdapter::skip(const size_type count)
{
m_stream.ignore(count);
return (m_stream.gcount());
}
2004-10-05 10:28:21 +00:00
// inputStreamStringAdapter
inputStreamStringAdapter::inputStreamStringAdapter(const string& buffer)
: m_buffer(buffer), m_begin(0), m_end(buffer.length()), m_pos(0)
{
}
inputStreamStringAdapter::inputStreamStringAdapter(const string& buffer,
const string::size_type begin, const string::size_type end)
: m_buffer(buffer), m_begin(begin), m_end(end), m_pos(begin)
{
}
const bool inputStreamStringAdapter::eof() const
{
return (m_pos >= m_end);
}
void inputStreamStringAdapter::reset()
{
m_pos = m_begin;
}
const stream::size_type inputStreamStringAdapter::read
(value_type* const data, const size_type count)
{
if (m_pos + count >= m_end)
{
const size_type remaining = m_end - m_pos;
std::copy(m_buffer.begin() + m_pos, m_buffer.end(), data);
m_pos = m_end;
return (remaining);
}
else
{
std::copy(m_buffer.begin() + m_pos, m_buffer.begin() + m_pos + count, data);
m_pos += count;
return (count);
}
}
2004-12-16 09:49:55 +00:00
const stream::size_type inputStreamStringAdapter::skip(const size_type count)
{
if (m_pos + count >= m_end)
{
const size_type remaining = m_end - m_pos;
m_pos = m_end;
return (remaining);
}
else
{
m_pos += count;
return (count);
}
}
2004-10-05 10:28:21 +00:00
// inputStreamStringProxyAdapter
inputStreamStringProxyAdapter::inputStreamStringProxyAdapter(const stringProxy& buffer)
: m_buffer(buffer), m_pos(0)
{
}
const bool inputStreamStringProxyAdapter::eof() const
{
return (m_pos >= m_buffer.length());
}
void inputStreamStringProxyAdapter::reset()
{
m_pos = 0;
}
const stream::size_type inputStreamStringProxyAdapter::read
(value_type* const data, const size_type count)
{
const size_type remaining = m_buffer.length() - m_pos;
if (count > remaining)
{
std::copy(m_buffer.it_begin() + m_pos, m_buffer.it_end(), data);
m_pos = m_buffer.length();
return (remaining);
}
else
{
std::copy(m_buffer.it_begin() + m_pos, m_buffer.it_begin() + m_pos + count, data);
m_pos += count;
return (count);
}
}
2004-12-16 09:49:55 +00:00
const stream::size_type inputStreamStringProxyAdapter::skip(const size_type count)
{
const size_type remaining = m_buffer.length() - m_pos;
if (count > remaining)
{
m_pos = m_buffer.length();
return (remaining);
}
else
{
m_pos += count;
return (count);
}
}
2004-10-05 10:28:21 +00:00
// inputStreamPointerAdapter
inputStreamPointerAdapter::inputStreamPointerAdapter(std::istream* is, const bool own)
: m_stream(is), m_own(own)
{
}
2005-07-12 22:28:02 +00:00
inputStreamPointerAdapter::inputStreamPointerAdapter(const inputStreamPointerAdapter&)
: inputStream(), m_stream(NULL), m_own(false)
{
// Not copiable
}
2004-10-05 10:28:21 +00:00
inputStreamPointerAdapter::~inputStreamPointerAdapter()
{
if (m_own)
delete (m_stream);
}
const bool inputStreamPointerAdapter::eof() const
{
return (m_stream->eof());
}
void inputStreamPointerAdapter::reset()
{
m_stream->seekg(0, std::ios::beg);
m_stream->clear();
}
const stream::size_type inputStreamPointerAdapter::read
(value_type* const data, const size_type count)
{
m_stream->read(data, count);
return (m_stream->gcount());
}
2004-12-16 09:49:55 +00:00
const stream::size_type inputStreamPointerAdapter::skip(const size_type count)
{
m_stream->ignore(count);
return (m_stream->gcount());
}
2005-09-17 09:08:45 +00:00
// inputStreamByteBufferAdapter
2006-04-18 19:04:30 +00:00
inputStreamByteBufferAdapter::inputStreamByteBufferAdapter(const byte_t* buffer, const size_type length)
2005-09-17 09:08:45 +00:00
: m_buffer(buffer), m_length(length), m_pos(0)
{
}
const bool inputStreamByteBufferAdapter::eof() const
{
return m_pos >= m_length;
}
void inputStreamByteBufferAdapter::reset()
{
m_pos = 0;
}
const stream::size_type inputStreamByteBufferAdapter::read
(value_type* const data, const size_type count)
{
const size_type remaining = m_length - m_pos;
if (remaining < count)
{
std::copy(m_buffer + m_pos, m_buffer + m_pos + remaining, data);
m_pos += remaining;
return remaining;
}
else
{
std::copy(m_buffer + m_pos, m_buffer + m_pos + count, data);
m_pos += count;
return count;
}
}
const stream::size_type inputStreamByteBufferAdapter::skip(const size_type count)
{
const size_type remaining = m_length - m_pos;
if (remaining < count)
{
m_pos += remaining;
return remaining;
}
else
{
m_pos += count;
return count;
}
}
#ifdef VMIME_HAVE_MESSAGING_FEATURES
// outputStreamSocketAdapter
outputStreamSocketAdapter::outputStreamSocketAdapter(net::socket& sok)
: m_socket(sok)
{
}
void outputStreamSocketAdapter::write
(const value_type* const data, const size_type count)
{
m_socket.sendRaw(data, count);
}
void outputStreamSocketAdapter::flush()
{
// Do nothing
}
2006-11-18 09:27:30 +00:00
const stream::size_type outputStreamSocketAdapter::getBlockSize() const
{
return 16384; // 16 KB
}
// inputStreamSocketAdapter
inputStreamSocketAdapter::inputStreamSocketAdapter(net::socket& sok)
: m_socket(sok)
{
}
const bool inputStreamSocketAdapter::eof() const
{
// Can't know...
return false;
}
void inputStreamSocketAdapter::reset()
{
// Not supported
}
const stream::size_type inputStreamSocketAdapter::read
(value_type* const data, const size_type count)
{
return m_socket.receiveRaw(data, count);
}
const stream::size_type inputStreamSocketAdapter::skip
(const size_type /* count */)
{
// Not supported
return 0;
}
2006-11-18 09:27:30 +00:00
const stream::size_type inputStreamSocketAdapter::getBlockSize() const
{
return 16384; // 16 KB
}
#endif // VMIME_HAVE_MESSAGING_FEATURES
2004-10-05 10:28:21 +00:00
} // utility
} // vmime