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 #ifdef PQXX_HAVE_STREAMBUF
00022 #include <streambuf>
00023 #else
00024 #include <streambuf.h>
00025 #endif
00026
00027 #include "pqxx/dbtransaction"
00028
00029
00030 namespace pqxx
00031 {
00032
00033 class largeobjectaccess;
00034
00036
00043 class PQXX_LIBEXPORT largeobject
00044 {
00045 public:
00046 typedef long size_type;
00047
00049 largeobject() throw ();
00050
00052
00054 explicit largeobject(dbtransaction &T);
00055
00057
00061 explicit largeobject(oid O) throw () : m_ID(O) {}
00062
00064
00068 largeobject(dbtransaction &T, const PGSTD::string &File);
00069
00071
00075 largeobject(const largeobjectaccess &O) throw ();
00076
00078
00082 oid id() const throw () { return m_ID; }
00083
00085
00086 bool operator==(const largeobject &other) const
00087 { return m_ID == other.m_ID; }
00089
00090 bool operator!=(const largeobject &other) const
00091 { return m_ID != other.m_ID; }
00093
00094 bool operator<=(const largeobject &other) const
00095 { return m_ID <= other.m_ID; }
00097
00098 bool operator>=(const largeobject &other) const
00099 { return m_ID >= other.m_ID; }
00101
00102 bool operator<(const largeobject &other) const
00103 { return m_ID < other.m_ID; }
00105
00106 bool operator>(const largeobject &other) const
00107 { return m_ID > other.m_ID; }
00108
00110
00114 void to_file(dbtransaction &T, const PGSTD::string &File) const;
00115
00117
00121 void remove(dbtransaction &T) const;
00122
00123 protected:
00124 static internal::pq::PGconn *RawConnection(const dbtransaction &T)
00125 {
00126 return T.conn().RawConnection();
00127 }
00128
00129 PGSTD::string Reason() const;
00130
00131 private:
00132 oid m_ID;
00133 };
00134
00135
00136
00137
00139 class PQXX_LIBEXPORT largeobjectaccess : private largeobject
00140 {
00141 public:
00142 using largeobject::size_type;
00143 typedef long off_type;
00144 typedef size_type pos_type;
00145
00147
00151 typedef PGSTD::ios::openmode openmode;
00152
00154
00158 typedef PGSTD::ios::seekdir seekdir;
00159
00161
00165 explicit largeobjectaccess(dbtransaction &T,
00166 openmode mode =
00167 PGSTD::ios::in |
00168 PGSTD::ios::out);
00169
00171
00177 largeobjectaccess(dbtransaction &T,
00178 oid O,
00179 openmode mode =
00180 PGSTD::ios::in |
00181 PGSTD::ios::out);
00182
00184
00189 largeobjectaccess(dbtransaction &T,
00190 largeobject O,
00191 openmode mode = PGSTD::ios::in | PGSTD::ios::out);
00192
00194
00199 largeobjectaccess(dbtransaction &T,
00200 const PGSTD::string &File,
00201 openmode mode =
00202 PGSTD::ios::in | PGSTD::ios::out);
00203
00204 ~largeobjectaccess() throw () { close(); }
00205
00207
00210 using largeobject::id;
00211
00213
00216 void to_file(const PGSTD::string &File) const
00217 { largeobject::to_file(m_Trans, File); }
00218
00219 #ifdef PQXX_BROKEN_USING_DECL
00220
00221
00225 void to_file(dbtransaction &T, const PGSTD::string &F) const
00226 { largeobject::to_file(T, F); }
00227 #else
00228 using largeobject::to_file;
00229 #endif
00230
00231
00233
00237 void write(const char Buf[], size_type Len);
00238
00240
00243 void write(const PGSTD::string &Buf)
00244 { write(Buf.c_str(), Buf.size()); }
00245
00247
00253 size_type read(char Buf[], size_type Len);
00254
00256
00259 size_type seek(size_type dest, seekdir dir);
00260
00262
00270 pos_type cseek(off_type dest, seekdir dir) throw ();
00271
00273
00279 off_type cwrite(const char Buf[], size_type Len) throw ();
00280
00282
00288 off_type cread(char Buf[], size_type Len) throw ();
00289
00290
00292 void process_notice(const PGSTD::string &) throw ();
00293
00294 using largeobject::remove;
00295
00296 using largeobject::operator==;
00297 using largeobject::operator!=;
00298 using largeobject::operator<;
00299 using largeobject::operator<=;
00300 using largeobject::operator>;
00301 using largeobject::operator>=;
00302
00303 private:
00304 PGSTD::string Reason() const;
00305 internal::pq::PGconn *RawConnection()
00306 { return largeobject::RawConnection(m_Trans); }
00307
00308 void open(openmode mode);
00309 void close() throw ();
00310
00311 dbtransaction &m_Trans;
00312 int m_fd;
00313
00314
00315 largeobjectaccess();
00316 largeobjectaccess(const largeobjectaccess &);
00317 largeobjectaccess operator=(const largeobjectaccess &);
00318 };
00319
00320
00322
00330 template<typename CHAR=char, typename TRAITS=PGSTD::char_traits<CHAR> >
00331 class largeobject_streambuf :
00332 #ifdef PQXX_HAVE_STREAMBUF
00333 public PGSTD::basic_streambuf<CHAR, TRAITS>
00334 #else
00335 public PGSTD::streambuf
00336 #endif
00337 {
00338 typedef long size_type;
00339 public:
00340 typedef CHAR char_type;
00341 typedef TRAITS traits_type;
00342 typedef typename traits_type::int_type int_type;
00343 #ifdef PQXX_HAVE_STREAMBUF
00344 typedef typename traits_type::pos_type pos_type;
00345 typedef typename traits_type::off_type off_type;
00346 #else
00347 typedef streamoff off_type;
00348 typedef streampos pos_type;
00349 #endif
00350 typedef largeobjectaccess::openmode openmode;
00351 typedef largeobjectaccess::seekdir seekdir;
00352
00353 largeobject_streambuf(dbtransaction &T,
00354 largeobject O,
00355 openmode mode = PGSTD::ios::in | PGSTD::ios::out,
00356 size_type BufSize=512) :
00357 m_BufSize(BufSize),
00358 m_Obj(T, O),
00359 m_G(0),
00360 m_P(0)
00361 { initialize(mode); }
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 { initialize(mode); }
00372
00373 virtual ~largeobject_streambuf() throw () { delete [] m_P; delete [] m_G; }
00374
00375
00377 void process_notice(const PGSTD::string &s) { m_Obj.process_notice(s); }
00378
00379 #ifdef PQXX_HAVE_STREAMBUF
00380 protected:
00381 #endif
00382 virtual int sync()
00383 {
00384
00385 setg(this->eback(), this->eback(), this->egptr());
00386 return overflow(EoF());
00387 }
00388
00389 protected:
00390 virtual pos_type seekoff(off_type offset,
00391 seekdir dir,
00392 openmode mode)
00393 {
00394 if (mode != SEEK_CUR)
00395 throw PGSTD::logic_error("Offset "+to_string(int(mode))+" in seekoff()");
00396 return AdjustEOF(m_Obj.cseek(offset, dir));
00397 }
00398
00399 virtual pos_type seekpos(pos_type pos, openmode mode)
00400 {
00401 if (mode != SEEK_SET)
00402 throw PGSTD::logic_error("Offset "+to_string(int(mode))+" in seekpos()");
00403 return AdjustEOF(m_Obj.cseek(pos, PGSTD::ios::beg));
00404 }
00405
00406 virtual int_type overflow(int_type ch = EoF())
00407 {
00408 char *const pp = this->pptr();
00409 if (!pp) return EoF();
00410 char *const pb = this->pbase();
00411 int_type res = 0;
00412
00413 if (pp > pb) res = AdjustEOF(m_Obj.cwrite(pb, pp-pb));
00414 setp(m_P, m_P + m_BufSize);
00415
00416
00417 if (ch != EoF())
00418 {
00419 *this->pptr() = char(ch);
00420 this->pbump(1);
00421 }
00422 return res;
00423 }
00424
00425 virtual int_type underflow()
00426 {
00427 if (!this->gptr()) return EoF();
00428 char *const eb = this->eback();
00429 const int res = AdjustEOF(m_Obj.cread(this->eback(), m_BufSize));
00430 setg(eb, eb, eb + ((res==EoF()) ? 0 : res));
00431 return (!res || (res == EoF())) ? EoF() : *eb;
00432 }
00433
00434 private:
00436 static int_type EoF() { return traits_type::eof(); }
00437
00439 static PGSTD::streampos AdjustEOF(int pos)
00440 {
00441 return (pos == -1) ? EoF() : pos;
00442 }
00443
00444 void initialize(openmode mode)
00445 {
00446 if (mode & PGSTD::ios::in)
00447 {
00448 m_G = new char_type[m_BufSize];
00449 setg(m_G, m_G, m_G);
00450 }
00451 if (mode & PGSTD::ios::out)
00452 {
00453 m_P = new char_type[m_BufSize];
00454 setp(m_P, m_P + m_BufSize);
00455 }
00456 }
00457
00458 const size_type m_BufSize;
00459 largeobjectaccess m_Obj;
00460
00461
00462 char_type *m_G, *m_P;
00463 };
00464
00465
00467
00475 template<typename CHAR=char, typename TRAITS=PGSTD::char_traits<CHAR> >
00476 class basic_ilostream :
00477 #ifdef PQXX_HAVE_STREAMBUF
00478 public PGSTD::basic_istream<CHAR, TRAITS>
00479 #else
00480 public PGSTD::istream
00481 #endif
00482 {
00483 #ifdef PQXX_HAVE_STREAMBUF
00484 typedef PGSTD::basic_istream<CHAR, TRAITS> super;
00485 #else
00486 typedef PGSTD::istream super;
00487 #endif
00488
00489 public:
00490 typedef CHAR char_type;
00491 typedef TRAITS traits_type;
00492 typedef typename traits_type::int_type int_type;
00493 typedef typename traits_type::pos_type pos_type;
00494 typedef typename traits_type::off_type off_type;
00495
00497
00502 basic_ilostream(dbtransaction &T,
00503 largeobject O,
00504 largeobject::size_type BufSize=512) :
00505 super(&m_Buf),
00506 m_Buf(T, O, PGSTD::ios::in, BufSize)
00507 { }
00508
00510
00515 basic_ilostream(dbtransaction &T,
00516 oid O,
00517 largeobject::size_type BufSize=512) :
00518 super(&m_Buf),
00519 m_Buf(T, O, PGSTD::ios::in, BufSize)
00520 { }
00521
00522 private:
00523 largeobject_streambuf<CHAR,TRAITS> m_Buf;
00524 };
00525
00526 typedef basic_ilostream<char> ilostream;
00527
00528
00530
00538 template<typename CHAR=char, typename TRAITS=PGSTD::char_traits<CHAR> >
00539 class basic_olostream :
00540 #ifdef PQXX_HAVE_STREAMBUF
00541 public PGSTD::basic_ostream<CHAR, TRAITS>
00542 #else
00543 public PGSTD::ostream
00544 #endif
00545 {
00546 #ifdef PQXX_HAVE_STREAMBUF
00547 typedef PGSTD::basic_ostream<CHAR, TRAITS> super;
00548 #else
00549 typedef PGSTD::ostream super;
00550 #endif
00551 public:
00552 typedef CHAR char_type;
00553 typedef TRAITS traits_type;
00554 typedef typename traits_type::int_type int_type;
00555 typedef typename traits_type::pos_type pos_type;
00556 typedef typename traits_type::off_type off_type;
00557
00559
00564 basic_olostream(dbtransaction &T,
00565 largeobject O,
00566 largeobject::size_type BufSize=512) :
00567 super(&m_Buf),
00568 m_Buf(T, O, PGSTD::ios::out, BufSize)
00569 { }
00570
00572
00577 basic_olostream(dbtransaction &T,
00578 oid O,
00579 largeobject::size_type BufSize=512) :
00580 super(&m_Buf),
00581 m_Buf(T, O, PGSTD::ios::out, BufSize)
00582 { }
00583
00584 ~basic_olostream()
00585 {
00586 try
00587 {
00588 #ifdef PQXX_HAVE_STREAMBUF
00589 m_Buf.pubsync(); m_Buf.pubsync();
00590 #else
00591 m_Buf.sync(); m_Buf.sync();
00592 #endif
00593 }
00594 catch (const PGSTD::exception &e)
00595 {
00596 m_Buf.process_notice(e.what());
00597 }
00598 }
00599
00600 private:
00601 largeobject_streambuf<CHAR,TRAITS> m_Buf;
00602 };
00603
00604 typedef basic_olostream<char> olostream;
00605
00606
00608
00616 template<typename CHAR=char, typename TRAITS=PGSTD::char_traits<CHAR> >
00617 class basic_lostream :
00618 #ifdef PQXX_HAVE_STREAMBUF
00619 public PGSTD::basic_iostream<CHAR, TRAITS>
00620 #else
00621 public PGSTD::iostream
00622 #endif
00623 {
00624 #ifdef PQXX_HAVE_STREAMBUF
00625 typedef PGSTD::basic_iostream<CHAR, TRAITS> super;
00626 #else
00627 typedef PGSTD::iostream super;
00628 #endif
00629
00630 public:
00631 typedef CHAR char_type;
00632 typedef TRAITS traits_type;
00633 typedef typename traits_type::int_type int_type;
00634 typedef typename traits_type::pos_type pos_type;
00635 typedef typename traits_type::off_type off_type;
00636
00638
00643 basic_lostream(dbtransaction &T,
00644 largeobject O,
00645 largeobject::size_type BufSize=512) :
00646 super(&m_Buf),
00647 m_Buf(T, O, PGSTD::ios::in | PGSTD::ios::out, BufSize)
00648 { }
00649
00651
00656 basic_lostream(dbtransaction &T,
00657 oid O,
00658 largeobject::size_type BufSize=512) :
00659 super(&m_Buf),
00660 m_Buf(T, O, PGSTD::ios::in | PGSTD::ios::out, BufSize)
00661 { }
00662
00663 ~basic_lostream()
00664 {
00665 try
00666 {
00667 #ifdef PQXX_HAVE_STREAMBUF
00668 m_Buf.pubsync(); m_Buf.pubsync();
00669 #else
00670 m_Buf.sync(); m_Buf.sync();
00671 #endif
00672 }
00673 catch (const PGSTD::exception &e)
00674 {
00675 m_Buf.process_notice(e.what());
00676 }
00677 }
00678
00679 private:
00680 largeobject_streambuf<CHAR,TRAITS> m_Buf;
00681 };
00682
00683 typedef basic_lostream<char> lostream;
00684
00685 }
00686
00687