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