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(int err) 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 PQXX_PRIVATE Reason(int err) 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)
00393 { return AdjustEOF(m_Obj.cseek(offset, dir)); }
00394
00395 virtual pos_type seekpos(pos_type pos, openmode)
00396 { return AdjustEOF(m_Obj.cseek(pos, PGSTD::ios::beg)); }
00397
00398 virtual int_type overflow(int_type ch = EoF())
00399 {
00400 char *const pp = this->pptr();
00401 if (!pp) return EoF();
00402 char *const pb = this->pbase();
00403 int_type res = 0;
00404
00405 if (pp > pb) res = AdjustEOF(m_Obj.cwrite(pb, pp-pb));
00406 setp(m_P, m_P + m_BufSize);
00407
00408
00409 if (ch != EoF())
00410 {
00411 *this->pptr() = char(ch);
00412 this->pbump(1);
00413 }
00414 return res;
00415 }
00416
00417 virtual int_type underflow()
00418 {
00419 if (!this->gptr()) return EoF();
00420 char *const eb = this->eback();
00421 const int res = AdjustEOF(m_Obj.cread(this->eback(), m_BufSize));
00422 setg(eb, eb, eb + ((res==EoF()) ? 0 : res));
00423 return (!res || (res == EoF())) ? EoF() : *eb;
00424 }
00425
00426 private:
00428 static int_type EoF() { return traits_type::eof(); }
00429
00431 static PGSTD::streampos AdjustEOF(int pos) { return (pos==-1) ? EoF() : pos; }
00432
00433 void initialize(openmode mode)
00434 {
00435 if (mode & PGSTD::ios::in)
00436 {
00437 m_G = new char_type[m_BufSize];
00438 setg(m_G, m_G, m_G);
00439 }
00440 if (mode & PGSTD::ios::out)
00441 {
00442 m_P = new char_type[m_BufSize];
00443 setp(m_P, m_P + m_BufSize);
00444 }
00445 }
00446
00447 const size_type m_BufSize;
00448 largeobjectaccess m_Obj;
00449
00450
00451 char_type *m_G, *m_P;
00452 };
00453
00454
00456
00464 template<typename CHAR=char, typename TRAITS=PGSTD::char_traits<CHAR> >
00465 class basic_ilostream :
00466 #ifdef PQXX_HAVE_STREAMBUF
00467 public PGSTD::basic_istream<CHAR, TRAITS>
00468 #else
00469 public PGSTD::istream
00470 #endif
00471 {
00472 #ifdef PQXX_HAVE_STREAMBUF
00473 typedef PGSTD::basic_istream<CHAR, TRAITS> super;
00474 #else
00475 typedef PGSTD::istream super;
00476 #endif
00477
00478 public:
00479 typedef CHAR char_type;
00480 typedef TRAITS traits_type;
00481 typedef typename traits_type::int_type int_type;
00482 typedef typename traits_type::pos_type pos_type;
00483 typedef typename traits_type::off_type off_type;
00484
00486
00491 basic_ilostream(dbtransaction &T,
00492 largeobject O,
00493 largeobject::size_type BufSize=512) :
00494 super(0),
00495 m_Buf(T, O, PGSTD::ios::in, BufSize)
00496 { super::init(&m_Buf); }
00497
00499
00504 basic_ilostream(dbtransaction &T,
00505 oid O,
00506 largeobject::size_type BufSize=512) :
00507 super(0),
00508 m_Buf(T, O, PGSTD::ios::in, BufSize)
00509 { super::init(&m_Buf); }
00510
00511 private:
00512 largeobject_streambuf<CHAR,TRAITS> m_Buf;
00513 };
00514
00515 typedef basic_ilostream<char> ilostream;
00516
00517
00519
00527 template<typename CHAR=char, typename TRAITS=PGSTD::char_traits<CHAR> >
00528 class basic_olostream :
00529 #ifdef PQXX_HAVE_STREAMBUF
00530 public PGSTD::basic_ostream<CHAR, TRAITS>
00531 #else
00532 public PGSTD::ostream
00533 #endif
00534 {
00535 #ifdef PQXX_HAVE_STREAMBUF
00536 typedef PGSTD::basic_ostream<CHAR, TRAITS> super;
00537 #else
00538 typedef PGSTD::ostream super;
00539 #endif
00540 public:
00541 typedef CHAR char_type;
00542 typedef TRAITS traits_type;
00543 typedef typename traits_type::int_type int_type;
00544 typedef typename traits_type::pos_type pos_type;
00545 typedef typename traits_type::off_type off_type;
00546
00548
00553 basic_olostream(dbtransaction &T,
00554 largeobject O,
00555 largeobject::size_type BufSize=512) :
00556 super(0),
00557 m_Buf(T, O, PGSTD::ios::out, BufSize)
00558 { super::init(&m_Buf); }
00559
00561
00566 basic_olostream(dbtransaction &T,
00567 oid O,
00568 largeobject::size_type BufSize=512) :
00569 super(0),
00570 m_Buf(T, O, PGSTD::ios::out, BufSize)
00571 { super::init(&m_Buf); }
00572
00573 ~basic_olostream()
00574 {
00575 try
00576 {
00577 #ifdef PQXX_HAVE_STREAMBUF
00578 m_Buf.pubsync(); m_Buf.pubsync();
00579 #else
00580 m_Buf.sync(); m_Buf.sync();
00581 #endif
00582 }
00583 catch (const PGSTD::exception &e)
00584 {
00585 m_Buf.process_notice(e.what());
00586 }
00587 }
00588
00589 private:
00590 largeobject_streambuf<CHAR,TRAITS> m_Buf;
00591 };
00592
00593 typedef basic_olostream<char> olostream;
00594
00595
00597
00605 template<typename CHAR=char, typename TRAITS=PGSTD::char_traits<CHAR> >
00606 class basic_lostream :
00607 #ifdef PQXX_HAVE_STREAMBUF
00608 public PGSTD::basic_iostream<CHAR, TRAITS>
00609 #else
00610 public PGSTD::iostream
00611 #endif
00612 {
00613 #ifdef PQXX_HAVE_STREAMBUF
00614 typedef PGSTD::basic_iostream<CHAR, TRAITS> super;
00615 #else
00616 typedef PGSTD::iostream super;
00617 #endif
00618
00619 public:
00620 typedef CHAR char_type;
00621 typedef TRAITS traits_type;
00622 typedef typename traits_type::int_type int_type;
00623 typedef typename traits_type::pos_type pos_type;
00624 typedef typename traits_type::off_type off_type;
00625
00627
00632 basic_lostream(dbtransaction &T,
00633 largeobject O,
00634 largeobject::size_type BufSize=512) :
00635 super(0),
00636 m_Buf(T, O, PGSTD::ios::in | PGSTD::ios::out, BufSize)
00637 { super::init(&m_Buf); }
00638
00640
00645 basic_lostream(dbtransaction &T,
00646 oid O,
00647 largeobject::size_type BufSize=512) :
00648 super(0),
00649 m_Buf(T, O, PGSTD::ios::in | PGSTD::ios::out, BufSize)
00650 { super::init(&m_Buf); }
00651
00652 ~basic_lostream()
00653 {
00654 try
00655 {
00656 #ifdef PQXX_HAVE_STREAMBUF
00657 m_Buf.pubsync(); m_Buf.pubsync();
00658 #else
00659 m_Buf.sync(); m_Buf.sync();
00660 #endif
00661 }
00662 catch (const PGSTD::exception &e)
00663 {
00664 m_Buf.process_notice(e.what());
00665 }
00666 }
00667
00668 private:
00669 largeobject_streambuf<CHAR,TRAITS> m_Buf;
00670 };
00671
00672 typedef basic_lostream<char> lostream;
00673
00674 }
00675
00676