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 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 PGconn *RawConnection() { return largeobject::RawConnection(m_Trans); }
00304
00305 void open(openmode mode);
00306 void close() throw ();
00307
00308 dbtransaction &m_Trans;
00309 int m_fd;
00310
00311
00312 largeobjectaccess();
00313 largeobjectaccess(const largeobjectaccess &);
00314 largeobjectaccess operator=(const largeobjectaccess &);
00315 };
00316
00317
00319
00327 template<typename CHAR=char, typename TRAITS=PGSTD::char_traits<CHAR> >
00328 class largeobject_streambuf :
00329 #ifdef PQXX_HAVE_STREAMBUF
00330 public PGSTD::basic_streambuf<CHAR, TRAITS>
00331 #else
00332 public PGSTD::streambuf
00333 #endif
00334 {
00335 typedef long size_type;
00336 public:
00337 typedef CHAR char_type;
00338 typedef TRAITS traits_type;
00339 typedef typename traits_type::int_type int_type;
00340 #ifdef PQXX_HAVE_STREAMBUF
00341 typedef typename traits_type::pos_type pos_type;
00342 typedef typename traits_type::off_type off_type;
00343 #else
00344 typedef streamoff off_type;
00345 typedef streampos pos_type;
00346 #endif
00347 typedef largeobjectaccess::openmode openmode;
00348 typedef largeobjectaccess::seekdir seekdir;
00349
00350 largeobject_streambuf(dbtransaction &T,
00351 largeobject O,
00352 openmode mode = PGSTD::ios::in | PGSTD::ios::out,
00353 size_type BufSize=512) :
00354 m_BufSize(BufSize),
00355 m_Obj(T, O),
00356 m_G(0),
00357 m_P(0)
00358 {
00359 initialize(mode);
00360 }
00361
00362 largeobject_streambuf(dbtransaction &T,
00363 oid O,
00364 openmode mode = PGSTD::ios::in | PGSTD::ios::out,
00365 size_type BufSize=512) :
00366 m_BufSize(BufSize),
00367 m_Obj(T, O),
00368 m_G(0),
00369 m_P(0)
00370 {
00371 initialize(mode);
00372 }
00373
00374 virtual ~largeobject_streambuf() throw ()
00375 {
00376 delete [] m_P;
00377 delete [] m_G;
00378 }
00379
00380
00382 void process_notice(const PGSTD::string &s) { m_Obj.process_notice(s); }
00383
00384 #ifdef PQXX_HAVE_STREAMBUF
00385 protected:
00386 #endif
00387 virtual int sync()
00388 {
00389
00390 setg(eback(), eback(), egptr());
00391 return overflow(EoF());
00392 }
00393
00394 protected:
00395 virtual pos_type seekoff(off_type offset,
00396 seekdir dir,
00397 openmode mode)
00398 {
00399 if (mode != SEEK_CUR)
00400 throw PGSTD::logic_error("Offset "+to_string(int(mode))+" in seekoff()");
00401 return AdjustEOF(m_Obj.cseek(offset, dir));
00402 }
00403
00404 virtual pos_type seekpos(pos_type pos, openmode mode)
00405 {
00406 if (mode != SEEK_SET)
00407 throw PGSTD::logic_error("Offset "+to_string(int(mode))+" in seekpos()");
00408 return AdjustEOF(m_Obj.cseek(pos, PGSTD::ios::beg));
00409 }
00410
00411 virtual int_type overflow(int_type ch = EoF())
00412 {
00413 char *const pp = pptr();
00414 if (!pp) return EoF();
00415 char *const pb = pbase();
00416 int_type res = 0;
00417
00418 if (pp > pb) res = AdjustEOF(m_Obj.cwrite(pb, pp-pb));
00419 setp(m_P, m_P + m_BufSize);
00420
00421
00422 if (ch != EoF())
00423 {
00424 *pptr() = char(ch);
00425 pbump(1);
00426 }
00427 return res;
00428 }
00429
00430 virtual int_type underflow()
00431 {
00432 if (!gptr()) return EoF();
00433 char *const eb = eback();
00434 const int res = AdjustEOF(m_Obj.cread(eback(), m_BufSize));
00435 setg(eb, eb, eb + ((res==EoF()) ? 0 : res));
00436 return (!res || (res == EoF())) ? EoF() : *eb;
00437 }
00438
00439 private:
00441 static int_type EoF() { return traits_type::eof(); }
00442
00444 static PGSTD::streampos AdjustEOF(int pos)
00445 {
00446 return (pos == -1) ? EoF() : pos;
00447 }
00448
00449 void initialize(openmode mode)
00450 {
00451 if (mode & PGSTD::ios::in)
00452 {
00453 m_G = new char_type[m_BufSize];
00454 setg(m_G, m_G, m_G);
00455 }
00456 if (mode & PGSTD::ios::out)
00457 {
00458 m_P = new char_type[m_BufSize];
00459 setp(m_P, m_P + m_BufSize);
00460 }
00461 }
00462
00463 const size_type m_BufSize;
00464 largeobjectaccess m_Obj;
00465
00466
00467 char_type *m_G, *m_P;
00468 };
00469
00470
00472
00480 template<typename CHAR=char, typename TRAITS=PGSTD::char_traits<CHAR> >
00481 class basic_ilostream :
00482 #ifdef PQXX_HAVE_STREAMBUF
00483 public PGSTD::basic_istream<CHAR, TRAITS>
00484 #else
00485 public PGSTD::istream
00486 #endif
00487 {
00488 #ifdef PQXX_HAVE_STREAMBUF
00489 typedef PGSTD::basic_istream<CHAR, TRAITS> super;
00490 #else
00491 typedef PGSTD::istream super;
00492 #endif
00493
00494 public:
00495 typedef CHAR char_type;
00496 typedef TRAITS traits_type;
00497 typedef typename traits_type::int_type int_type;
00498 typedef typename traits_type::pos_type pos_type;
00499 typedef typename traits_type::off_type off_type;
00500
00502
00506 basic_ilostream(dbtransaction &T,
00507 largeobject O,
00508 largeobject::size_type BufSize=512) :
00509 super(&m_Buf),
00510 m_Buf(T, O, PGSTD::ios::in, BufSize)
00511 {
00512 }
00513
00515
00519 basic_ilostream(dbtransaction &T,
00520 oid O,
00521 largeobject::size_type BufSize=512) :
00522 super(&m_Buf),
00523 m_Buf(T, O, PGSTD::ios::in, BufSize)
00524 {
00525 }
00526
00527 private:
00528 largeobject_streambuf<CHAR,TRAITS> m_Buf;
00529 };
00530
00531 typedef basic_ilostream<char> ilostream;
00532
00533
00535
00543 template<typename CHAR=char, typename TRAITS=PGSTD::char_traits<CHAR> >
00544 class basic_olostream :
00545 #ifdef PQXX_HAVE_STREAMBUF
00546 public PGSTD::basic_ostream<CHAR, TRAITS>
00547 #else
00548 public PGSTD::ostream
00549 #endif
00550 {
00551 #ifdef PQXX_HAVE_STREAMBUF
00552 typedef PGSTD::basic_ostream<CHAR, TRAITS> super;
00553 #else
00554 typedef PGSTD::ostream super;
00555 #endif
00556 public:
00557 typedef CHAR char_type;
00558 typedef TRAITS traits_type;
00559 typedef typename traits_type::int_type int_type;
00560 typedef typename traits_type::pos_type pos_type;
00561 typedef typename traits_type::off_type off_type;
00562
00564
00568 basic_olostream(dbtransaction &T,
00569 largeobject O,
00570 largeobject::size_type BufSize=512) :
00571 super(&m_Buf),
00572 m_Buf(T, O, PGSTD::ios::out, BufSize)
00573 {
00574 }
00575
00577
00581 basic_olostream(dbtransaction &T,
00582 oid O,
00583 largeobject::size_type BufSize=512) :
00584 super(&m_Buf),
00585 m_Buf(T, O, PGSTD::ios::out, BufSize)
00586 {
00587 }
00588
00589 ~basic_olostream()
00590 {
00591 try
00592 {
00593 #ifdef PQXX_HAVE_STREAMBUF
00594 m_Buf.pubsync(); m_Buf.pubsync();
00595 #else
00596 m_Buf.sync(); m_Buf.sync();
00597 #endif
00598 }
00599 catch (const PGSTD::exception &e)
00600 {
00601 m_Buf.process_notice(e.what());
00602 }
00603 }
00604
00605 private:
00606 largeobject_streambuf<CHAR,TRAITS> m_Buf;
00607 };
00608
00609 typedef basic_olostream<char> olostream;
00610
00611
00613
00621 template<typename CHAR=char, typename TRAITS=PGSTD::char_traits<CHAR> >
00622 class basic_lostream :
00623 #ifdef PQXX_HAVE_STREAMBUF
00624 public PGSTD::basic_iostream<CHAR, TRAITS>
00625 #else
00626 public PGSTD::iostream
00627 #endif
00628 {
00629 #ifdef PQXX_HAVE_STREAMBUF
00630 typedef PGSTD::basic_iostream<CHAR, TRAITS> super;
00631 #else
00632 typedef PGSTD::iostream super;
00633 #endif
00634
00635 public:
00636 typedef CHAR char_type;
00637 typedef TRAITS traits_type;
00638 typedef typename traits_type::int_type int_type;
00639 typedef typename traits_type::pos_type pos_type;
00640 typedef typename traits_type::off_type off_type;
00641
00643
00647 basic_lostream(dbtransaction &T,
00648 largeobject O,
00649 largeobject::size_type BufSize=512) :
00650 super(&m_Buf),
00651 m_Buf(T, O, PGSTD::ios::in | PGSTD::ios::out, BufSize)
00652 {
00653 }
00654
00656
00660 basic_lostream(dbtransaction &T,
00661 oid O,
00662 largeobject::size_type BufSize=512) :
00663 super(&m_Buf),
00664 m_Buf(T, O, PGSTD::ios::in | PGSTD::ios::out, BufSize)
00665 {
00666 }
00667
00668 ~basic_lostream()
00669 {
00670 try
00671 {
00672 #ifdef PQXX_HAVE_STREAMBUF
00673 m_Buf.pubsync(); m_Buf.pubsync();
00674 #else
00675 m_Buf.sync(); m_Buf.sync();
00676 #endif
00677 }
00678 catch (const PGSTD::exception &e)
00679 {
00680 m_Buf.process_notice(e.what());
00681 }
00682 }
00683
00684 private:
00685 largeobject_streambuf<CHAR,TRAITS> m_Buf;
00686 };
00687
00688 typedef basic_lostream<char> lostream;
00689
00690 }
00691
00692