Skip to content

Commit

Permalink
Add copyStreamRange to StreamCopier (#4474)
Browse files Browse the repository at this point in the history
* feat(Foundation): StreamCopier copyStreamRange #4413

* chore(ci): disable instalation of unused databases in odbc job

---------

Co-authored-by: Pavle <[email protected]>
Co-authored-by: Alex Fabijanic <[email protected]>
  • Loading branch information
3 people authored Feb 28, 2024
1 parent 6b3aab0 commit 8119259
Show file tree
Hide file tree
Showing 5 changed files with 343 additions and 115 deletions.
44 changes: 22 additions & 22 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -660,27 +660,27 @@ jobs:
linux-gcc-make-odbc:
runs-on: ubuntu-22.04
services:
mysql:
image: mysql:8.1.0
env:
MYSQL_ALLOW_EMPTY_PASSWORD: yes
MYSQL_USER: pocotest
MYSQL_PASSWORD: pocotest
MYSQL_DATABASE: pocotest
ports:
- 3306:3306
postgres:
image: postgres:16.0
env:
POSTGRES_PASSWORD: postgres
ports:
- 5432:5432
oracle:
image: container-registry.oracle.com/database/express:21.3.0-xe
env:
ORACLE_PWD: poco
ports:
- 1521:1521
#mysql:
# image: mysql:8.1.0
# env:
# MYSQL_ALLOW_EMPTY_PASSWORD: yes
# MYSQL_USER: pocotest
# MYSQL_PASSWORD: pocotest
# MYSQL_DATABASE: pocotest
# ports:
# - 3306:3306
#postgres:
# image: postgres:16.0
# env:
# POSTGRES_PASSWORD: postgres
# ports:
# - 5432:5432
#oracle:
# image: container-registry.oracle.com/database/express:21.3.0-xe
# env:
# ORACLE_PWD: poco
# ports:
# - 1521:1521
sqlserver:
image: mcr.microsoft.com/mssql/server:2022-latest
env:
Expand All @@ -691,7 +691,7 @@ jobs:
- 1433:1433
steps:
- uses: actions/checkout@v3
- run: sudo apt -y update && sudo apt -y install libssl-dev unixodbc-dev libmysqlclient-dev mysql-client alien libaio1 gnupg2 curl #odbc-postgresql
- run: sudo apt -y update && sudo apt -y install libssl-dev unixodbc-dev alien libaio1 gnupg2 curl # libmysqlclient-dev mysql-client odbc-postgresql
- run: ./configure --everything --no-samples --omit=ActiveRecord,ApacheConnector,CppParser,Crypto,Data/MySQL,Data/PostgreSQL,Data/SQLite,Encodings,JSON,JWT,MongoDB,Net,NetSSL_OpenSSL,NetSSL_Win,PDF,PageCompiler,PocoDoc,ProGen,Prometheus,Redis,SevenZip,Util,XML,Zip && make all -s -j4 && sudo make install
# - name: Setup MySQL ODBC connector
# run: |
Expand Down
144 changes: 144 additions & 0 deletions Foundation/include/Poco/StreamCopier.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@


#include "Poco/Foundation.h"
#include "Poco/Buffer.h"
#include <istream>
#include <ostream>
#include <cstddef>
Expand Down Expand Up @@ -47,6 +48,21 @@ class Foundation_API StreamCopier
/// integer is used to count the number of bytes copied.
#endif

static std::streamsize copyStreamRange(std::istream& istr, std::ostream& ostr, std::streampos rangeStart, std::streamsize rangeLength, std::size_t bufferSize = 8192);
/// Writes range of bytes readable from istr to ostr, using an internal buffer.
///
/// Returns the number of bytes copied.

#if defined(POCO_HAVE_INT64)
static Poco::UInt64 copyStreamRange64(std::istream& istr, std::ostream& ostr, std::streampos rangeStart, std::streamsize rangeLength, std::size_t bufferSize = 8192);
/// Writes range of bytes readable from istr to ostr, using an internal buffer.
///
/// Returns the number of bytes copied as a 64-bit unsigned integer.
///
/// Note: the only difference to copyStreamRange() is that a 64-bit unsigned
/// integer is used to count the number of bytes copied.
#endif

static std::streamsize copyStreamUnbuffered(std::istream& istr, std::ostream& ostr);
/// Writes all bytes readable from istr to ostr.
///
Expand All @@ -62,6 +78,21 @@ class Foundation_API StreamCopier
/// integer is used to count the number of bytes copied.
#endif

static std::streamsize copyStreamRangeUnbuffered(std::istream& istr, std::ostream& ostr, std::streampos rangeStart, std::streamsize rangeLength);
/// Writes range of bytes readable from istr to ostr.
///
/// Returns the number of bytes copied.

#if defined(POCO_HAVE_INT64)
static Poco::UInt64 copyStreamRangeUnbuffered64(std::istream& istr, std::ostream& ostr, std::streampos rangeStart, std::streamsize rangeLength);
/// Writes range of bytes readable from istr to ostr.
///
/// Returns the number of bytes copied as a 64-bit unsigned integer.
///
/// Note: the only difference to copyStreamRangeUnbuffered() is that a 64-bit unsigned
/// integer is used to count the number of bytes copied.
#endif

static std::streamsize copyToString(std::istream& istr, std::string& str, std::size_t bufferSize = 8192);
/// Appends all bytes readable from istr to the given string, using an internal buffer.
///
Expand All @@ -76,6 +107,119 @@ class Foundation_API StreamCopier
/// Note: the only difference to copyToString() is that a 64-bit unsigned
/// integer is used to count the number of bytes copied.
#endif

private:
template <typename T>
static T copyStreamImpl(std::istream& istr, std::ostream& ostr, std::size_t bufferSize)
{
poco_assert (bufferSize > 0);

Buffer<char> buffer(bufferSize);
T len = 0;
istr.read(buffer.begin(), bufferSize);
std::streamsize n = istr.gcount();
while (n > 0)
{
len += n;
ostr.write(buffer.begin(), n);
if (istr && ostr)
{
istr.read(buffer.begin(), bufferSize);
n = istr.gcount();
}
else n = 0;
}
return len;
}

template <typename T>
static T copyStreamRangeImpl(std::istream& istr, std::ostream& ostr, std::streampos rangeStart, std::streamsize rangeLength, std::size_t bufferSize)
{
poco_assert (bufferSize > 0);

if (bufferSize > rangeLength)
bufferSize = rangeLength;

Buffer<char> buffer(bufferSize);
T len = 0;
if (istr)
{
istr.seekg(rangeStart);
istr.read(buffer.begin(), bufferSize);
std::streamsize n = istr.gcount();
while (n > 0)
{
len += n;
ostr.write(buffer.begin(), n);
if ((len < rangeLength) && istr && ostr)
{
if (bufferSize > (rangeLength - len))
bufferSize = rangeLength - len;
istr.read(buffer.begin(), bufferSize);
n = istr.gcount();
}
else n = 0;
}
}
return len;
}

template <typename T>
static T copyToStringImpl(std::istream& istr, std::string& str, std::size_t bufferSize)
{
poco_assert (bufferSize > 0);

Buffer<char> buffer(bufferSize);
T len = 0;
istr.read(buffer.begin(), bufferSize);
std::streamsize n = istr.gcount();
while (n > 0)
{
len += n;
str.append(buffer.begin(), static_cast<std::string::size_type>(n));
if (istr)
{
istr.read(buffer.begin(), bufferSize);
n = istr.gcount();
}
else n = 0;
}
return len;
}

template <typename T>
static T copyStreamUnbufferedImpl(std::istream& istr, std::ostream& ostr)
{
char c = 0;
T len = 0;
istr.get(c);
while (istr && ostr)
{
++len;
ostr.put(c);
istr.get(c);
}
return len;
}

template <typename T>
static T copyStreamRangeUnbufferedImpl(std::istream& istr, std::ostream& ostr, std::streampos rangeStart, std::streamsize rangeLength)
{
T len = 0;
char c = 0;
if (istr)
{
istr.seekg(rangeStart);
istr.get(c);
while (istr && ostr && (len < rangeLength))
{
ostr.put(c);
++len;
istr.get(c);
}
}
return len;
}
};


Expand Down
126 changes: 33 additions & 93 deletions Foundation/src/StreamCopier.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,136 +13,76 @@


#include "Poco/StreamCopier.h"
#include "Poco/Buffer.h"


namespace Poco {


std::streamsize StreamCopier::copyStream(std::istream& istr, std::ostream& ostr, std::size_t bufferSize)
{
poco_assert (bufferSize > 0);

Buffer<char> buffer(bufferSize);
std::streamsize len = 0;
istr.read(buffer.begin(), bufferSize);
std::streamsize n = istr.gcount();
while (n > 0)
{
len += n;
ostr.write(buffer.begin(), n);
if (istr && ostr)
{
istr.read(buffer.begin(), bufferSize);
n = istr.gcount();
}
else n = 0;
}
return len;
return copyStreamImpl<std::streamsize>(istr, ostr, bufferSize);
}


#if defined(POCO_HAVE_INT64)
Poco::UInt64 StreamCopier::copyStream64(std::istream& istr, std::ostream& ostr, std::size_t bufferSize)
{
poco_assert (bufferSize > 0);

Buffer<char> buffer(bufferSize);
Poco::UInt64 len = 0;
istr.read(buffer.begin(), bufferSize);
std::streamsize n = istr.gcount();
while (n > 0)
{
len += n;
ostr.write(buffer.begin(), n);
if (istr && ostr)
{
istr.read(buffer.begin(), bufferSize);
n = istr.gcount();
}
else n = 0;
}
return len;
return copyStreamImpl<Poco::UInt64>(istr, ostr, bufferSize);
}
#endif


std::streamsize StreamCopier::copyStreamRange(std::istream& istr, std::ostream& ostr, std::streampos rangeStart, std::streamsize rangeLength, std::size_t bufferSize)
{
return copyStreamRangeImpl<std::streamsize>(istr, ostr, rangeStart, rangeLength, bufferSize);
}


#if defined(POCO_HAVE_INT64)
Poco::UInt64 StreamCopier::copyStreamRange64(std::istream& istr, std::ostream& ostr, std::streampos rangeStart, std::streamsize rangeLength, std::size_t bufferSize)
{
return copyStreamRangeImpl<Poco::UInt64>(istr, ostr, rangeStart, rangeLength, bufferSize);
}
#endif


std::streamsize StreamCopier::copyToString(std::istream& istr, std::string& str, std::size_t bufferSize)
{
poco_assert (bufferSize > 0);

Buffer<char> buffer(bufferSize);
std::streamsize len = 0;
istr.read(buffer.begin(), bufferSize);
std::streamsize n = istr.gcount();
while (n > 0)
{
len += n;
str.append(buffer.begin(), static_cast<std::string::size_type>(n));
if (istr)
{
istr.read(buffer.begin(), bufferSize);
n = istr.gcount();
}
else n = 0;
}
return len;
return copyToStringImpl<std::streamsize>(istr, str, bufferSize);
}


#if defined(POCO_HAVE_INT64)
Poco::UInt64 StreamCopier::copyToString64(std::istream& istr, std::string& str, std::size_t bufferSize)
{
poco_assert (bufferSize > 0);

Buffer<char> buffer(bufferSize);
Poco::UInt64 len = 0;
istr.read(buffer.begin(), bufferSize);
std::streamsize n = istr.gcount();
while (n > 0)
{
len += n;
str.append(buffer.begin(), static_cast<std::string::size_type>(n));
if (istr)
{
istr.read(buffer.begin(), bufferSize);
n = istr.gcount();
}
else n = 0;
}
return len;
return copyToStringImpl<Poco::UInt64>(istr, str, bufferSize);
}
#endif


std::streamsize StreamCopier::copyStreamUnbuffered(std::istream& istr, std::ostream& ostr)
{
char c = 0;
std::streamsize len = 0;
istr.get(c);
while (istr && ostr)
{
++len;
ostr.put(c);
istr.get(c);
}
return len;
return copyStreamUnbufferedImpl<std::streamsize>(istr, ostr);
}


#if defined(POCO_HAVE_INT64)
Poco::UInt64 StreamCopier::copyStreamUnbuffered64(std::istream& istr, std::ostream& ostr)
{
char c = 0;
Poco::UInt64 len = 0;
istr.get(c);
while (istr && ostr)
{
++len;
ostr.put(c);
istr.get(c);
}
return len;
return copyStreamUnbufferedImpl<Poco::UInt64>(istr, ostr);
}
#endif

std::streamsize StreamCopier::copyStreamRangeUnbuffered(std::istream& istr, std::ostream& ostr, std::streampos rangeStart, std::streamsize rangeLength)
{
return copyStreamRangeUnbufferedImpl<std::streamsize>(istr, ostr, rangeStart, rangeLength);
}


#if defined(POCO_HAVE_INT64)
Poco::UInt64 StreamCopier::copyStreamRangeUnbuffered64(std::istream& istr, std::ostream& ostr, std::streampos rangeStart, std::streamsize rangeLength)
{
return copyStreamRangeUnbufferedImpl<Poco::UInt64>(istr, ostr, rangeStart, rangeLength);
}
#endif

Expand Down
Loading

0 comments on commit 8119259

Please sign in to comment.