largeobject.hxx
/*-------------------------------------------------------------------------
*
* FILE
* pqxx/largeobject.hxx
*
* DESCRIPTION
* libpqxx's Large Objects interface
* Allows access to large objects directly, or through I/O streams
* DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/largeobject instead.
*
* Copyright (c) 2003-2012, Jeroen T. Vermeulen <jtv@xs4all.nl>
*
* See COPYING for copyright license. If you did not receive a file called
* COPYING with this source code, please notify the distributor of this mistake,
* or contact the author.
*
*-------------------------------------------------------------------------
*/
#ifndef PQXX_H_LARGEOBJECT
#define PQXX_H_LARGEOBJECT
#include "pqxx/compiler-public.hxx"
#include "pqxx/compiler-internal-pre.hxx"
#ifdef PQXX_HAVE_STREAMBUF
#include <streambuf>
#else
#include <streambuf.h>
#endif
#include "pqxx/dbtransaction"
namespace pqxx
{
class largeobjectaccess;
class PQXX_LIBEXPORT largeobject
{
public:
typedef long size_type;
largeobject() throw (); //[t48]
explicit largeobject(dbtransaction &T); //[t48]
explicit largeobject(oid O) throw () : m_ID(O) {} //[t48]
largeobject(dbtransaction &T, const PGSTD::string &File); //[t53]
largeobject(const largeobjectaccess &O) throw (); //[t50]
oid id() const throw () { return m_ID; } //[t48]
bool operator==(const largeobject &other) const //[t51]
{ return m_ID == other.m_ID; }
bool operator!=(const largeobject &other) const //[t51]
{ return m_ID != other.m_ID; }
bool operator<=(const largeobject &other) const //[t51]
{ return m_ID <= other.m_ID; }
bool operator>=(const largeobject &other) const //[t51]
{ return m_ID >= other.m_ID; }
bool operator<(const largeobject &other) const //[t51]
{ return m_ID < other.m_ID; }
bool operator>(const largeobject &other) const //[t51]
{ return m_ID > other.m_ID; }
void to_file(dbtransaction &T, const PGSTD::string &File) const; //[t52]
void remove(dbtransaction &T) const; //[t48]
protected:
static internal::pq::PGconn * PQXX_PURE RawConnection(const dbtransaction &T);
PGSTD::string Reason(int err) const;
private:
oid m_ID;
};
// TODO: New hierarchy with separate read / write / mixed-mode access
class PQXX_LIBEXPORT largeobjectaccess : private largeobject
{
public:
using largeobject::size_type;
typedef long off_type;
typedef size_type pos_type;
typedef PGSTD::ios::openmode openmode;
typedef PGSTD::ios::seekdir seekdir;
explicit largeobjectaccess(dbtransaction &T,
openmode mode =
PGSTD::ios::in |
PGSTD::ios::out); //[t51]
largeobjectaccess(dbtransaction &T,
oid O,
openmode mode =
PGSTD::ios::in |
PGSTD::ios::out); //[t52]
largeobjectaccess(dbtransaction &T,
largeobject O,
openmode mode = PGSTD::ios::in | PGSTD::ios::out); //[t50]
largeobjectaccess(dbtransaction &T,
const PGSTD::string &File,
openmode mode =
PGSTD::ios::in | PGSTD::ios::out); //[t55]
~largeobjectaccess() throw () { close(); }
using largeobject::id;
void to_file(const PGSTD::string &File) const //[t54]
{ largeobject::to_file(m_Trans, File); }
#ifdef PQXX_BROKEN_USING_DECL
void to_file(dbtransaction &T, const PGSTD::string &F) const
{ largeobject::to_file(T, F); }
#else
using largeobject::to_file;
#endif
void write(const char Buf[], size_type Len); //[t51]
void write(const PGSTD::string &Buf) //[t50]
{ write(Buf.c_str(), static_cast<size_type>(Buf.size())); }
size_type read(char Buf[], size_type Len); //[t50]
size_type seek(size_type dest, seekdir dir); //[t51]
size_type tell() const; //[t50]
pos_type cseek(off_type dest, seekdir dir) throw (); //[t50]
off_type cwrite(const char Buf[], size_type Len) throw (); //[t50]
off_type cread(char Buf[], size_type Len) throw (); //[t50]
pos_type ctell() const throw (); //[t50]
void process_notice(const PGSTD::string &) throw (); //[t50]
using largeobject::remove;
using largeobject::operator==;
using largeobject::operator!=;
using largeobject::operator<;
using largeobject::operator<=;
using largeobject::operator>;
using largeobject::operator>=;
private:
PGSTD::string PQXX_PRIVATE Reason(int err) const;
internal::pq::PGconn *RawConnection() const
{ return largeobject::RawConnection(m_Trans); }
void open(openmode mode);
void close() throw ();
dbtransaction &m_Trans;
int m_fd;
// Not allowed:
largeobjectaccess();
largeobjectaccess(const largeobjectaccess &);
largeobjectaccess operator=(const largeobjectaccess &);
};
template<typename CHAR=char, typename TRAITS=PGSTD::char_traits<CHAR> >
class largeobject_streambuf :
#ifdef PQXX_HAVE_STREAMBUF
public PGSTD::basic_streambuf<CHAR, TRAITS>
#else
public PGSTD::streambuf
#endif
{
typedef long size_type;
public:
typedef CHAR char_type;
typedef TRAITS traits_type;
typedef typename traits_type::int_type int_type;
#ifdef PQXX_HAVE_STREAMBUF
typedef typename traits_type::pos_type pos_type;
typedef typename traits_type::off_type off_type;
#else
typedef streamoff off_type;
typedef streampos pos_type;
#endif
typedef largeobjectaccess::openmode openmode;
typedef largeobjectaccess::seekdir seekdir;
largeobject_streambuf(dbtransaction &T,
largeobject O,
openmode mode = PGSTD::ios::in | PGSTD::ios::out,
size_type BufSize=512) : //[t48]
m_BufSize(BufSize),
m_Obj(T, O, mode),
m_G(0),
m_P(0)
{ initialize(mode); }
largeobject_streambuf(dbtransaction &T,
oid O,
openmode mode = PGSTD::ios::in | PGSTD::ios::out,
size_type BufSize=512) : //[t48]
m_BufSize(BufSize),
m_Obj(T, O, mode),
m_G(0),
m_P(0)
{ initialize(mode); }
virtual ~largeobject_streambuf() throw () { delete [] m_P; delete [] m_G; }
void process_notice(const PGSTD::string &s) { m_Obj.process_notice(s); }
#ifdef PQXX_HAVE_STREAMBUF
protected:
#endif
virtual int sync()
{
// setg() sets eback, gptr, egptr
this->setg(this->eback(), this->eback(), this->egptr());
return overflow(EoF());
}
protected:
virtual pos_type seekoff(off_type offset,
seekdir dir,
openmode)
{
return AdjustEOF(m_Obj.cseek(largeobjectaccess::off_type(offset), dir));
}
virtual pos_type seekpos(pos_type pos, openmode)
{
const largeobjectaccess::pos_type newpos = m_Obj.cseek(
largeobjectaccess::off_type(pos),
PGSTD::ios::beg);
return AdjustEOF(newpos);
}
virtual int_type overflow(int_type ch = EoF())
{
char *const pp = this->pptr();
if (!pp) return EoF();
char *const pb = this->pbase();
int_type res = 0;
if (pp > pb) res = int_type(AdjustEOF(m_Obj.cwrite(pb, pp-pb)));
this->setp(m_P, m_P + m_BufSize);
// Write that one more character, if it's there.
if (ch != EoF())
{
*this->pptr() = char(ch);
this->pbump(1);
}
return res;
}
virtual int_type underflow()
{
if (!this->gptr()) return EoF();
char *const eb = this->eback();
const int_type res(static_cast<int_type>(
AdjustEOF(m_Obj.cread(this->eback(), m_BufSize))));
this->setg(eb, eb, eb + ((res==EoF()) ? 0 : res));
return (!res || (res == EoF())) ? EoF() : *eb;
}
private:
static int_type EoF() { return traits_type::eof(); }
template<typename INTYPE>
static PGSTD::streampos AdjustEOF(INTYPE pos)
{ return (pos==-1) ? PGSTD::streampos(EoF()) : PGSTD::streampos(pos); }
void initialize(openmode mode)
{
if (mode & PGSTD::ios::in)
{
m_G = new char_type[unsigned(m_BufSize)];
this->setg(m_G, m_G, m_G);
}
if (mode & PGSTD::ios::out)
{
m_P = new char_type[unsigned(m_BufSize)];
this->setp(m_P, m_P + m_BufSize);
}
}
const size_type m_BufSize;
largeobjectaccess m_Obj;
// Get & put buffers
char_type *m_G, *m_P;
};
template<typename CHAR=char, typename TRAITS=PGSTD::char_traits<CHAR> >
class basic_ilostream :
#ifdef PQXX_HAVE_STREAMBUF
public PGSTD::basic_istream<CHAR, TRAITS>
#else
public PGSTD::istream
#endif
{
#ifdef PQXX_HAVE_STREAMBUF
typedef PGSTD::basic_istream<CHAR, TRAITS> super;
#else
typedef PGSTD::istream super;
#endif
public:
typedef CHAR char_type;
typedef TRAITS traits_type;
typedef typename traits_type::int_type int_type;
typedef typename traits_type::pos_type pos_type;
typedef typename traits_type::off_type off_type;
basic_ilostream(dbtransaction &T,
largeobject O,
largeobject::size_type BufSize=512) : //[t57]
super(0),
m_Buf(T, O, PGSTD::ios::in, BufSize)
{ super::init(&m_Buf); }
basic_ilostream(dbtransaction &T,
oid O,
largeobject::size_type BufSize=512) : //[t48]
super(0),
m_Buf(T, O, PGSTD::ios::in, BufSize)
{ super::init(&m_Buf); }
private:
largeobject_streambuf<CHAR,TRAITS> m_Buf;
};
typedef basic_ilostream<char> ilostream;
template<typename CHAR=char, typename TRAITS=PGSTD::char_traits<CHAR> >
class basic_olostream :
#ifdef PQXX_HAVE_STREAMBUF
public PGSTD::basic_ostream<CHAR, TRAITS>
#else
public PGSTD::ostream
#endif
{
#ifdef PQXX_HAVE_STREAMBUF
typedef PGSTD::basic_ostream<CHAR, TRAITS> super;
#else
typedef PGSTD::ostream super;
#endif
public:
typedef CHAR char_type;
typedef TRAITS traits_type;
typedef typename traits_type::int_type int_type;
typedef typename traits_type::pos_type pos_type;
typedef typename traits_type::off_type off_type;
basic_olostream(dbtransaction &T,
largeobject O,
largeobject::size_type BufSize=512) : //[t48]
super(0),
m_Buf(T, O, PGSTD::ios::out, BufSize)
{ super::init(&m_Buf); }
basic_olostream(dbtransaction &T,
oid O,
largeobject::size_type BufSize=512) : //[t57]
super(0),
m_Buf(T, O, PGSTD::ios::out, BufSize)
{ super::init(&m_Buf); }
~basic_olostream()
{
try
{
#ifdef PQXX_HAVE_STREAMBUF
m_Buf.pubsync(); m_Buf.pubsync();
#else
m_Buf.sync(); m_Buf.sync();
#endif
}
catch (const PGSTD::exception &e)
{
m_Buf.process_notice(e.what());
}
}
private:
largeobject_streambuf<CHAR,TRAITS> m_Buf;
};
typedef basic_olostream<char> olostream;
template<typename CHAR=char, typename TRAITS=PGSTD::char_traits<CHAR> >
class basic_lostream :
#ifdef PQXX_HAVE_STREAMBUF
public PGSTD::basic_iostream<CHAR, TRAITS>
#else
public PGSTD::iostream
#endif
{
#ifdef PQXX_HAVE_STREAMBUF
typedef PGSTD::basic_iostream<CHAR, TRAITS> super;
#else
typedef PGSTD::iostream super;
#endif
public:
typedef CHAR char_type;
typedef TRAITS traits_type;
typedef typename traits_type::int_type int_type;
typedef typename traits_type::pos_type pos_type;
typedef typename traits_type::off_type off_type;
basic_lostream(dbtransaction &T,
largeobject O,
largeobject::size_type BufSize=512) : //[t59]
super(0),
m_Buf(T, O, PGSTD::ios::in | PGSTD::ios::out, BufSize)
{ super::init(&m_Buf); }
basic_lostream(dbtransaction &T,
oid O,
largeobject::size_type BufSize=512) : //[t59]
super(0),
m_Buf(T, O, PGSTD::ios::in | PGSTD::ios::out, BufSize)
{ super::init(&m_Buf); }
~basic_lostream()
{
try
{
#ifdef PQXX_HAVE_STREAMBUF
m_Buf.pubsync(); m_Buf.pubsync();
#else
m_Buf.sync(); m_Buf.sync();
#endif
}
catch (const PGSTD::exception &e)
{
m_Buf.process_notice(e.what());
}
}
private:
largeobject_streambuf<CHAR,TRAITS> m_Buf;
};
typedef basic_lostream<char> lostream;
} // namespace pqxx
#include "pqxx/compiler-internal-post.hxx"
#endif
pqxx::largeobjectaccess::pos_type
size_type pos_type
Definition: largeobject.hxx:154
pqxx::basic_olostream::traits_type
TRAITS traits_type
Definition: largeobject.hxx:593
pqxx::dbtransaction
Definition: dbtransaction.hxx:73
pqxx::basic_ilostream::traits_type
TRAITS traits_type
Definition: largeobject.hxx:531
pqxx::basic_olostream::basic_olostream
basic_olostream(dbtransaction &T, oid O, largeobject::size_type BufSize=512)
Create a basic_olostream.
Definition: largeobject.hxx:617
pqxx::basic_olostream
Output stream that writes data back to a large object.
Definition: largeobject.hxx:579
pqxx::largeobject_streambuf::openmode
largeobjectaccess::openmode openmode
Definition: largeobject.hxx:391
pqxx::largeobjectaccess
Accessor for large object&#39;s contents.
Definition: largeobject.hxx:149
pqxx::basic_lostream::basic_lostream
basic_lostream(dbtransaction &T, oid O, largeobject::size_type BufSize=512)
Create a basic_lostream.
Definition: largeobject.hxx:696
pqxx::largeobject::id
oid id() const
Object identifier.
Definition: largeobject.hxx:86
pqxx::largeobject_streambuf::largeobject_streambuf
largeobject_streambuf(dbtransaction &T, oid O, openmode mode=std::ios::in|std::ios::out, size_type BufSize=512)
Definition: largeobject.hxx:404
pqxx::largeobject_streambuf::int_type
traits_type::int_type int_type
Definition: largeobject.hxx:383
pqxx::largeobjectaccess::to_file
void to_file(const std::string &File) const
Export large object&#39;s contents to a local file.
Definition: largeobject.hxx:226
pqxx::largeobject::operator>
bool operator>(const largeobject &other) const
Compare object identities.
Definition: largeobject.hxx:118
pqxx::largeobject_streambuf::off_type
streamoff off_type
Definition: largeobject.hxx:388
pqxx::largeobject_streambuf::~largeobject_streambuf
virtual ~largeobject_streambuf()
Definition: largeobject.hxx:414
pqxx::basic_lostream::basic_lostream
basic_lostream(dbtransaction &T, largeobject O, largeobject::size_type BufSize=512)
Create a basic_lostream.
Definition: largeobject.hxx:683
pqxx::basic_ilostream::off_type
traits_type::off_type off_type
Definition: largeobject.hxx:534
pqxx::basic_lostream::~basic_lostream
~basic_lostream()
Definition: largeobject.hxx:703
pqxx::largeobject::operator!=
bool operator!=(const largeobject &other) const
Compare object identities.
Definition: largeobject.hxx:102
pqxx::largeobject_streambuf::seekoff
virtual pos_type seekoff(off_type offset, seekdir dir, openmode)
Definition: largeobject.hxx:431
pqxx::basic_olostream::~basic_olostream
~basic_olostream()
Definition: largeobject.hxx:624
pqxx::ilostream
basic_ilostream< char > ilostream
Definition: largeobject.hxx:566
pqxx::basic_olostream::char_type
CHAR char_type
Definition: largeobject.hxx:592
pqxx::lostream
basic_lostream< char > lostream
Definition: largeobject.hxx:723
pqxx::basic_ilostream::basic_ilostream
basic_ilostream(dbtransaction &T, oid O, largeobject::size_type BufSize=512)
Create a basic_ilostream.
Definition: largeobject.hxx:555
pqxx::largeobject::operator>=
bool operator>=(const largeobject &other) const
Compare object identities.
Definition: largeobject.hxx:110
pqxx::largeobjectaccess::openmode
std::ios::openmode openmode
Open mode: in, out (can be combined with the "or" operator)
Definition: largeobject.hxx:161
pqxx::basic_olostream::pos_type
traits_type::pos_type pos_type
Definition: largeobject.hxx:595
pqxx::largeobject::operator<
bool operator<(const largeobject &other) const
Compare object identities.
Definition: largeobject.hxx:114
pqxx::basic_lostream::pos_type
traits_type::pos_type pos_type
Definition: largeobject.hxx:674
pqxx::largeobject_streambuf::process_notice
void process_notice(const std::string &s)
For use by large object stream classes.
Definition: largeobject.hxx:418
pqxx::basic_lostream::off_type
traits_type::off_type off_type
Definition: largeobject.hxx:675
pqxx::basic_ilostream::pos_type
traits_type::pos_type pos_type
Definition: largeobject.hxx:533
pqxx::basic_olostream::off_type
traits_type::off_type off_type
Definition: largeobject.hxx:596
pqxx::largeobject_streambuf::largeobject_streambuf
largeobject_streambuf(dbtransaction &T, largeobject O, openmode mode=std::ios::in|std::ios::out, size_type BufSize=512)
Definition: largeobject.hxx:394
pqxx::largeobject::to_file
void to_file(dbtransaction &T, const std::string &File) const
Export large object&#39;s contents to a local file.
Definition: largeobject.cxx:114
pqxx::basic_ilostream::basic_ilostream
basic_ilostream(dbtransaction &T, largeobject O, largeobject::size_type BufSize=512)
Create a basic_ilostream.
Definition: largeobject.hxx:542
pqxx::olostream
basic_olostream< char > olostream
Definition: largeobject.hxx:644
pqxx::largeobject::operator<=
bool operator<=(const largeobject &other) const
Compare object identities.
Definition: largeobject.hxx:106
pqxx::largeobject_streambuf::overflow
virtual int_type overflow(int_type ch=EoF())
Definition: largeobject.hxx:446
pqxx::largeobjectaccess::~largeobjectaccess
~largeobjectaccess()
Definition: largeobject.hxx:214
pqxx::basic_ilostream
Input stream that gets its data from a large object.
Definition: largeobject.hxx:516
pqxx::largeobjectaccess::off_type
long off_type
Definition: largeobject.hxx:153
pqxx::largeobject
Identity of a large object.
Definition: largeobject.hxx:47
pqxx::largeobject_streambuf::seekpos
virtual pos_type seekpos(pos_type pos, openmode)
Definition: largeobject.hxx:438
pqxx::largeobjectaccess::write
void write(const std::string &Buf)
Write string to large object.
Definition: largeobject.hxx:256
pqxx::largeobject_streambuf::pos_type
streampos pos_type
Definition: largeobject.hxx:389
pqxx::basic_ilostream::char_type
CHAR char_type
Definition: largeobject.hxx:530
pqxx::largeobject_streambuf::seekdir
largeobjectaccess::seekdir seekdir
Definition: largeobject.hxx:392
pqxx::basic_olostream::basic_olostream
basic_olostream(dbtransaction &T, largeobject O, largeobject::size_type BufSize=512)
Create a basic_olostream.
Definition: largeobject.hxx:604
pqxx::largeobject_streambuf::sync
virtual int sync()
Definition: largeobject.hxx:423
pqxx::basic_lostream::traits_type
TRAITS traits_type
Definition: largeobject.hxx:672
pqxx::basic_lostream
Stream that reads and writes a large object.
Definition: largeobject.hxx:657
pqxx::largeobject_streambuf::underflow
virtual int_type underflow()
Definition: largeobject.hxx:465
pqxx::largeobjectaccess::seekdir
std::ios::seekdir seekdir
Seek direction: beg, cur, end.
Definition: largeobject.hxx:168
pqxx::largeobject_streambuf::char_type
CHAR char_type
Definition: largeobject.hxx:381
pqxx
The home of all libpqxx classes, functions, templates, etc.
Definition: basic_connection.hxx:35
pqxx::largeobject::operator==
bool operator==(const largeobject &other) const
Compare object identities.
Definition: largeobject.hxx:98
pqxx::basic_lostream::char_type
CHAR char_type
Definition: largeobject.hxx:671
pqxx::basic_olostream::int_type
traits_type::int_type int_type
Definition: largeobject.hxx:594
pqxx::basic_ilostream::int_type
traits_type::int_type int_type
Definition: largeobject.hxx:532
pqxx::largeobject::remove
void remove(dbtransaction &T) const
Delete large object from database.
Definition: largeobject.cxx:128
pqxx::basic_lostream::int_type
traits_type::int_type int_type
Definition: largeobject.hxx:673
pqxx::largeobject::size_type
long size_type
Definition: largeobject.hxx:50
pqxx::largeobject::RawConnection
static internal::pq::PGconn *PQXX_PURE RawConnection(const dbtransaction &T)
Definition: largeobject.cxx:140
pqxx::largeobject_streambuf::traits_type
TRAITS traits_type
Definition: largeobject.hxx:382
pqxx::largeobject_streambuf
Streambuf to use large objects in standard I/O streams.
Definition: largeobject.hxx:372