00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
#include "pqxx/libcompiler.h"
00020
00021
#include <new>
00022
00023
#ifdef PQXX_HAVE_STREAMBUF
00024
#include <streambuf>
00025
#else
00026
#include <streambuf.h>
00027
#endif
00028
00029
#include "pqxx/dbtransaction"
00030
00031
00032
namespace pqxx
00033 {
00034
00035
class largeobjectaccess;
00036
00038
00045 class PQXX_LIBEXPORT largeobject
00046 {
00047
public:
00048 typedef long size_type;
00049
00051 largeobject() throw ();
00052
00054
00056 explicit largeobject(
dbtransaction &T);
00057
00059
00063 explicit largeobject(
oid O) throw () : m_ID(O) {}
00064
00066
00070 largeobject(
dbtransaction &T,
const PGSTD::string &File);
00071
00073
00077 largeobject(
const largeobjectaccess &O)
throw ();
00078
00080
00084 oid id() const throw () {
return m_ID; }
00085
00087 bool operator==(
const largeobject &other)
const
00088 {
return m_ID == other.m_ID; }
00090 bool operator!=(
const largeobject &other)
const
00091 {
return m_ID != other.m_ID; }
00093 bool operator<=(
const largeobject &other)
const
00094 {
return m_ID <= other.m_ID; }
00096 bool operator>=(
const largeobject &other)
const
00097 {
return m_ID >= other.m_ID; }
00099 bool operator<(
const largeobject &other)
const
00100 {
return m_ID < other.m_ID; }
00102 bool operator>(
const largeobject &other)
const
00103 {
return m_ID > other.m_ID; }
00104
00106
00110
void to_file(
dbtransaction &T,
const PGSTD::string &File)
const;
00111
00113
00117
void remove(
dbtransaction &T)
const;
00118
00119
protected:
00120 static internal::pq::PGconn *RawConnection(
const dbtransaction &T)
00121 {
00122
return T.
conn().
RawConnection();
00123 }
00124
00125 PGSTD::string Reason() const;
00126
00127 private:
00128
oid m_ID;
00129 };
00130
00131
00132
00133
00135 class PQXX_LIBEXPORT
largeobjectaccess : private largeobject
00136 {
00137
public:
00138
using largeobject::size_type;
00139 typedef long off_type;
00140 typedef size_type pos_type;
00141
00143
00147 typedef PGSTD::ios::openmode
openmode;
00148
00150
00154 typedef PGSTD::ios::seekdir
seekdir;
00155
00157
00161
explicit largeobjectaccess(
dbtransaction &T,
00162 openmode mode =
00163 PGSTD::ios::in |
00164 PGSTD::ios::out);
00165
00167
00173
largeobjectaccess(
dbtransaction &T,
00174
oid O,
00175 openmode mode =
00176 PGSTD::ios::in |
00177 PGSTD::ios::out);
00178
00180
00185
largeobjectaccess(
dbtransaction &T,
00186 largeobject O,
00187 openmode mode = PGSTD::ios::in | PGSTD::ios::out);
00188
00190
00195
largeobjectaccess(
dbtransaction &T,
00196
const PGSTD::string &File,
00197 openmode mode =
00198 PGSTD::ios::in | PGSTD::ios::out);
00199
00200 ~
largeobjectaccess() throw () { close(); }
00201
00203
00206
using largeobject::id;
00207
00209
00212 void to_file(
const PGSTD::string &File)
const
00213 {
00214 largeobject::to_file(m_Trans, File);
00215 }
00216
00217
#ifdef PQXX_BROKEN_USING_DECL
00218
00219
00223
void to_file(
dbtransaction &T,
const PGSTD::string &F)
const
00224
{ largeobject::to_file(T, F); }
00225
#else
00226
using largeobject::to_file;
00227
#endif
00228
00229
00231
00235
void write(
const char Buf[], size_type Len);
00236
00238
00241 void write(
const PGSTD::string &Buf)
00242 { write(Buf.c_str(), Buf.size()); }
00243
00245
00251 size_type read(
char Buf[], size_type Len);
00252
00254
00257 size_type seek(size_type dest, seekdir dir);
00258
00260
00268 pos_type cseek(off_type dest, seekdir dir)
throw ();
00269
00271
00277 off_type cwrite(
const char Buf[], size_type Len)
throw ();
00278
00280
00286 off_type cread(
char Buf[], size_type Len)
throw ();
00287
00288
00290
void process_notice(
const PGSTD::string &) throw ();
00291
00292 using largeobject::remove;
00293
00294 using largeobject::operator==;
00295 using largeobject::operator!=;
00296 using largeobject::operator<;
00297 using largeobject::operator<=;
00298 using largeobject::operator>;
00299 using largeobject::operator>=;
00300
00301 private:
00302 PGSTD::string Reason() const;
00303 internal::pq::PGconn *RawConnection()
00304 {
return largeobject::RawConnection(m_Trans); }
00305
00306
void open(openmode mode);
00307
void close() throw ();
00308
00309 dbtransaction &m_Trans;
00310
int m_fd;
00311
00312
00313 largeobjectaccess();
00314 largeobjectaccess(const largeobjectaccess &);
00315 largeobjectaccess operator=(const largeobjectaccess &);
00316 };
00317
00318
00320
00328 template<typename CHAR=
char, typename TRAITS=PGSTD::char_traits<CHAR> >
00329 class
largeobject_streambuf :
00330 #ifdef PQXX_HAVE_STREAMBUF
00331 public PGSTD::basic_streambuf<CHAR, TRAITS>
00332 #else
00333 public PGSTD::streambuf
00334 #endif
00335 {
00336
typedef long size_type;
00337
public:
00338 typedef CHAR
char_type;
00339 typedef TRAITS
traits_type;
00340 typedef typename traits_type::int_type
int_type;
00341
#ifdef PQXX_HAVE_STREAMBUF
00342
typedef typename traits_type::pos_type pos_type;
00343
typedef typename traits_type::off_type off_type;
00344
#else
00345 typedef streamoff off_type;
00346 typedef streampos pos_type;
00347
#endif
00348 typedef largeobjectaccess::openmode openmode;
00349 typedef largeobjectaccess::seekdir seekdir;
00350
00351 largeobject_streambuf(
dbtransaction &T,
00352 largeobject O,
00353 openmode mode = PGSTD::ios::in | PGSTD::ios::out,
00354 size_type BufSize=512) :
00355 m_BufSize(BufSize),
00356 m_Obj(T, O),
00357 m_G(0),
00358 m_P(0)
00359 {
00360 initialize(mode);
00361 }
00362
00363 largeobject_streambuf(
dbtransaction &T,
00364
oid O,
00365 openmode mode = PGSTD::ios::in | PGSTD::ios::out,
00366 size_type BufSize=512) :
00367 m_BufSize(BufSize),
00368 m_Obj(T, O),
00369 m_G(0),
00370 m_P(0)
00371 {
00372 initialize(mode);
00373 }
00374
00375 virtual ~
largeobject_streambuf() throw ()
00376 {
00377
delete [] m_P;
00378
delete [] m_G;
00379 }
00380
00381
00383 void process_notice(
const PGSTD::string &s) { m_Obj.process_notice(s); }
00384
00385
#ifdef PQXX_HAVE_STREAMBUF
00386
protected:
00387
#endif
00388 virtual int sync()
00389 {
00390
00391 setg(this->eback(), this->eback(), this->egptr());
00392
return overflow(EoF());
00393 }
00394
00395
protected:
00396 virtual pos_type seekoff(off_type offset,
00397 seekdir dir,
00398 openmode mode)
00399 {
00400
if (mode != SEEK_CUR)
00401
throw PGSTD::logic_error(
"Offset "+
to_string(
int(mode))+
" in seekoff()");
00402
return AdjustEOF(m_Obj.cseek(offset, dir));
00403 }
00404
00405 virtual pos_type seekpos(pos_type pos, openmode mode)
00406 {
00407
if (mode != SEEK_SET)
00408
throw PGSTD::logic_error(
"Offset "+
to_string(
int(mode))+
" in seekpos()");
00409
return AdjustEOF(m_Obj.cseek(pos, PGSTD::ios::beg));
00410 }
00411
00412 virtual int_type overflow(int_type ch = EoF())
00413 {
00414
char *
const pp = this->pptr();
00415
if (!pp)
return EoF();
00416
char *
const pb = this->pbase();
00417 int_type res = 0;
00418
00419
if (pp > pb) res = AdjustEOF(m_Obj.cwrite(pb, pp-pb));
00420 setp(m_P, m_P + m_BufSize);
00421
00422
00423
if (ch != EoF())
00424 {
00425 *this->pptr() = char(ch);
00426 this->pbump(1);
00427 }
00428
return res;
00429 }
00430
00431 virtual int_type underflow()
00432 {
00433
if (!this->gptr())
return EoF();
00434
char *
const eb = this->eback();
00435
const int res = AdjustEOF(m_Obj.cread(this->eback(), m_BufSize));
00436 setg(eb, eb, eb + ((res==EoF()) ? 0 : res));
00437
return (!res || (res == EoF())) ? EoF() : *eb;
00438 }
00439
00440
private:
00442
static int_type EoF() {
return traits_type::eof(); }
00443
00445
static PGSTD::streampos AdjustEOF(
int pos)
00446 {
00447
return (pos == -1) ? EoF() : pos;
00448 }
00449
00450
void initialize(openmode mode)
00451 {
00452
if (mode & PGSTD::ios::in)
00453 {
00454 m_G =
new char_type[m_BufSize];
00455 setg(m_G, m_G, m_G);
00456 }
00457
if (mode & PGSTD::ios::out)
00458 {
00459 m_P =
new char_type[m_BufSize];
00460 setp(m_P, m_P + m_BufSize);
00461 }
00462 }
00463
00464
const size_type m_BufSize;
00465 largeobjectaccess m_Obj;
00466
00467
00468 char_type *m_G, *m_P;
00469 };
00470
00471
00473
00481
template<
typename CHAR=
char,
typename TRAITS=PGSTD::
char_traits<CHAR> >
00482 class basic_ilostream :
00483 #ifdef
PQXX_HAVE_STREAMBUF
00484
public PGSTD::basic_istream<CHAR, TRAITS>
00485 #else
00486
public PGSTD::istream
00487 #endif
00488 {
00489
#ifdef PQXX_HAVE_STREAMBUF
00490
typedef PGSTD::basic_istream<CHAR, TRAITS> super;
00491
#else
00492
typedef PGSTD::istream super;
00493
#endif
00494
00495
public:
00496 typedef CHAR char_type;
00497 typedef TRAITS traits_type;
00498 typedef typename traits_type::int_type int_type;
00499 typedef typename traits_type::pos_type pos_type;
00500 typedef typename traits_type::off_type off_type;
00501
00503
00507 basic_ilostream(
dbtransaction &T,
00508 largeobject O,
00509
largeobject::size_type BufSize=512) :
00510 super(&m_Buf),
00511 m_Buf(T, O,
PGSTD::ios::in, BufSize)
00512 {
00513 }
00514
00516
00520 basic_ilostream(
dbtransaction &T,
00521
oid O,
00522
largeobject::size_type BufSize=512) :
00523 super(&m_Buf),
00524 m_Buf(T, O,
PGSTD::ios::in, BufSize)
00525 {
00526 }
00527
00528
private:
00529
largeobject_streambuf<CHAR,TRAITS> m_Buf;
00530 };
00531
00532 typedef basic_ilostream<char> ilostream;
00533
00534
00536
00544
template<
typename CHAR=
char,
typename TRAITS=PGSTD::
char_traits<CHAR> >
00545 class basic_olostream :
00546 #ifdef
PQXX_HAVE_STREAMBUF
00547
public PGSTD::basic_ostream<CHAR, TRAITS>
00548 #else
00549
public PGSTD::ostream
00550 #endif
00551 {
00552
#ifdef PQXX_HAVE_STREAMBUF
00553
typedef PGSTD::basic_ostream<CHAR, TRAITS> super;
00554
#else
00555
typedef PGSTD::ostream super;
00556
#endif
00557
public:
00558 typedef CHAR char_type;
00559 typedef TRAITS traits_type;
00560 typedef typename traits_type::int_type int_type;
00561 typedef typename traits_type::pos_type pos_type;
00562 typedef typename traits_type::off_type off_type;
00563
00565
00569 basic_olostream(
dbtransaction &T,
00570 largeobject O,
00571
largeobject::size_type BufSize=512) :
00572 super(&m_Buf),
00573 m_Buf(T, O,
PGSTD::ios::out, BufSize)
00574 {
00575 }
00576
00578
00582 basic_olostream(
dbtransaction &T,
00583
oid O,
00584
largeobject::size_type BufSize=512) :
00585 super(&m_Buf),
00586 m_Buf(T, O,
PGSTD::ios::out, BufSize)
00587 {
00588 }
00589
00590 ~
basic_olostream()
00591 {
00592
try
00593 {
00594
#ifdef PQXX_HAVE_STREAMBUF
00595
m_Buf.pubsync(); m_Buf.pubsync();
00596
#else
00597
m_Buf.sync(); m_Buf.sync();
00598
#endif
00599
}
00600
catch (
const PGSTD::exception &e)
00601 {
00602 m_Buf.process_notice(e.what());
00603 }
00604 }
00605
00606
private:
00607
largeobject_streambuf<CHAR,TRAITS> m_Buf;
00608 };
00609
00610 typedef basic_olostream<char> olostream;
00611
00612
00614
00622
template<
typename CHAR=
char,
typename TRAITS=PGSTD::
char_traits<CHAR> >
00623 class basic_lostream :
00624 #ifdef
PQXX_HAVE_STREAMBUF
00625
public PGSTD::basic_iostream<CHAR, TRAITS>
00626 #else
00627
public PGSTD::iostream
00628 #endif
00629 {
00630
#ifdef PQXX_HAVE_STREAMBUF
00631
typedef PGSTD::basic_iostream<CHAR, TRAITS> super;
00632
#else
00633
typedef PGSTD::iostream super;
00634
#endif
00635
00636
public:
00637 typedef CHAR char_type;
00638 typedef TRAITS traits_type;
00639 typedef typename traits_type::int_type int_type;
00640 typedef typename traits_type::pos_type pos_type;
00641 typedef typename traits_type::off_type off_type;
00642
00644
00648 basic_lostream(
dbtransaction &T,
00649 largeobject O,
00650
largeobject::size_type BufSize=512) :
00651 super(&m_Buf),
00652 m_Buf(T, O,
PGSTD::ios::in |
PGSTD::ios::out, BufSize)
00653 {
00654 }
00655
00657
00661 basic_lostream(
dbtransaction &T,
00662
oid O,
00663
largeobject::size_type BufSize=512) :
00664 super(&m_Buf),
00665 m_Buf(T, O,
PGSTD::ios::in |
PGSTD::ios::out, BufSize)
00666 {
00667 }
00668
00669 ~
basic_lostream()
00670 {
00671
try
00672 {
00673
#ifdef PQXX_HAVE_STREAMBUF
00674
m_Buf.pubsync(); m_Buf.pubsync();
00675
#else
00676
m_Buf.sync(); m_Buf.sync();
00677
#endif
00678
}
00679
catch (
const PGSTD::exception &e)
00680 {
00681 m_Buf.process_notice(e.what());
00682 }
00683 }
00684
00685
private:
00686
largeobject_streambuf<CHAR,TRAITS> m_Buf;
00687 };
00688
00689 typedef basic_lostream<char> lostream;
00690
00691 }
00692
00693