00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #ifndef PQXX_H_LARGEOBJECT
00020 #define PQXX_H_LARGEOBJECT
00021
00022 #include "pqxx/compiler-public.hxx"
00023 #include "pqxx/compiler-internal-pre.hxx"
00024
00025 #include <streambuf>
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() PQXX_NOEXCEPT;
00050
00052
00054 explicit largeobject(dbtransaction &T);
00055
00057
00061 explicit largeobject(oid O) PQXX_NOEXCEPT : m_ID(O) {}
00062
00064
00068 largeobject(dbtransaction &T, const std::string &File);
00069
00071
00075 largeobject(const largeobjectaccess &O) PQXX_NOEXCEPT;
00076
00078
00082 oid id() const PQXX_NOEXCEPT { return m_ID; }
00083
00092
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; }
00109
00110 bool operator<(const largeobject &other) const
00111 { return m_ID < other.m_ID; }
00113
00114 bool operator>(const largeobject &other) const
00115 { return m_ID > other.m_ID; }
00117
00119
00123 void to_file(dbtransaction &T, const std::string &File) const;
00124
00126
00130 void remove(dbtransaction &T) const;
00131
00132 protected:
00133 PQXX_PURE static internal::pq::PGconn *RawConnection(const dbtransaction &T);
00134
00135 std::string Reason(int err) const;
00136
00137 private:
00138 oid m_ID;
00139 };
00140
00141
00142
00143
00145 class PQXX_LIBEXPORT largeobjectaccess : private largeobject
00146 {
00147 public:
00148 using largeobject::size_type;
00149 typedef long off_type;
00150 typedef size_type pos_type;
00151
00153
00157 typedef std::ios::openmode openmode;
00158
00160
00164 typedef std::ios::seekdir seekdir;
00165
00167
00171 explicit largeobjectaccess(dbtransaction &T,
00172 openmode mode=std::ios::in|std::ios::out);
00173
00175
00181 largeobjectaccess(dbtransaction &T,
00182 oid O,
00183 openmode mode=std::ios::in|std::ios::out);
00184
00186
00191 largeobjectaccess(dbtransaction &T,
00192 largeobject O,
00193 openmode mode=std::ios::in|std::ios::out);
00194
00196
00201 largeobjectaccess(dbtransaction &T,
00202 const std::string &File,
00203 openmode mode=std::ios::in|std::ios::out);
00204
00205 ~largeobjectaccess() PQXX_NOEXCEPT { close(); }
00206
00208
00211 using largeobject::id;
00212
00214
00217 void to_file(const std::string &File) const
00218 { largeobject::to_file(m_Trans, File); }
00219
00220 using largeobject::to_file;
00221
00226
00227
00231 void write(const char Buf[], size_type Len);
00232
00234
00237 void write(const std::string &Buf)
00238 { write(Buf.c_str(), static_cast<size_type>(Buf.size())); }
00239
00241
00247 size_type read(char Buf[], size_type Len);
00248
00250
00253 size_type seek(size_type dest, seekdir dir);
00254
00256
00259 size_type tell() const;
00261
00271
00272
00280 pos_type cseek(off_type dest, seekdir dir) PQXX_NOEXCEPT;
00281
00283
00289 off_type cwrite(const char Buf[], size_type Len) PQXX_NOEXCEPT;
00290
00292
00298 off_type cread(char Buf[], size_type Len) PQXX_NOEXCEPT;
00299
00301
00305 pos_type ctell() const PQXX_NOEXCEPT;
00307
00312
00313 void process_notice(const std::string &) PQXX_NOEXCEPT;
00315
00316 using largeobject::remove;
00317
00318 using largeobject::operator==;
00319 using largeobject::operator!=;
00320 using largeobject::operator<;
00321 using largeobject::operator<=;
00322 using largeobject::operator>;
00323 using largeobject::operator>=;
00324
00325 private:
00326 PQXX_PRIVATE std::string Reason(int err) const;
00327 internal::pq::PGconn *RawConnection() const
00328 { return largeobject::RawConnection(m_Trans); }
00329
00330 void open(openmode mode);
00331 void close() PQXX_NOEXCEPT;
00332
00333 dbtransaction &m_Trans;
00334 int m_fd;
00335
00336
00337 largeobjectaccess() PQXX_DELETED_OP;
00338 largeobjectaccess(const largeobjectaccess &) PQXX_DELETED_OP;
00339 largeobjectaccess operator=(const largeobjectaccess &) PQXX_DELETED_OP;
00340 };
00341
00342
00344
00352 template<typename CHAR=char, typename TRAITS=std::char_traits<CHAR> >
00353 class largeobject_streambuf :
00354 public std::basic_streambuf<CHAR, TRAITS>
00355 {
00356 typedef long size_type;
00357 public:
00358 typedef CHAR char_type;
00359 typedef TRAITS traits_type;
00360 typedef typename traits_type::int_type int_type;
00361 typedef typename traits_type::pos_type pos_type;
00362 typedef typename traits_type::off_type off_type;
00363 typedef largeobjectaccess::openmode openmode;
00364 typedef largeobjectaccess::seekdir seekdir;
00365
00366 largeobject_streambuf(dbtransaction &T,
00367 largeobject O,
00368 openmode mode=std::ios::in|std::ios::out,
00369 size_type BufSize=512) :
00370 m_BufSize(BufSize),
00371 m_Obj(T, O, mode),
00372 m_G(0),
00373 m_P(0)
00374 { initialize(mode); }
00375
00376 largeobject_streambuf(dbtransaction &T,
00377 oid O,
00378 openmode mode=std::ios::in|std::ios::out,
00379 size_type BufSize=512) :
00380 m_BufSize(BufSize),
00381 m_Obj(T, O, mode),
00382 m_G(0),
00383 m_P(0)
00384 { initialize(mode); }
00385
00386 virtual ~largeobject_streambuf() PQXX_NOEXCEPT
00387 { delete [] m_P; delete [] m_G; }
00388
00389
00391 void process_notice(const std::string &s) { m_Obj.process_notice(s); }
00392
00393 protected:
00394 virtual int sync() PQXX_OVERRIDE
00395 {
00396
00397 this->setg(this->eback(), this->eback(), this->egptr());
00398 return overflow(EoF());
00399 }
00400
00401 protected:
00402 virtual pos_type seekoff(off_type offset,
00403 seekdir dir,
00404 openmode) PQXX_OVERRIDE
00405 {
00406 return AdjustEOF(m_Obj.cseek(largeobjectaccess::off_type(offset), dir));
00407 }
00408
00409 virtual pos_type seekpos(pos_type pos, openmode) PQXX_OVERRIDE
00410 {
00411 const largeobjectaccess::pos_type newpos = m_Obj.cseek(
00412 largeobjectaccess::off_type(pos),
00413 std::ios::beg);
00414 return AdjustEOF(newpos);
00415 }
00416
00417 virtual int_type overflow(int_type ch = EoF()) PQXX_OVERRIDE
00418 {
00419 char *const pp = this->pptr();
00420 if (!pp) return EoF();
00421 char *const pb = this->pbase();
00422 int_type res = 0;
00423
00424 if (pp > pb) res = int_type(AdjustEOF(m_Obj.cwrite(pb, pp-pb)));
00425 this->setp(m_P, m_P + m_BufSize);
00426
00427
00428 if (ch != EoF())
00429 {
00430 *this->pptr() = char(ch);
00431 this->pbump(1);
00432 }
00433 return res;
00434 }
00435
00436 virtual int_type underflow() PQXX_OVERRIDE
00437 {
00438 if (!this->gptr()) return EoF();
00439 char *const eb = this->eback();
00440 const int_type res(static_cast<int_type>(
00441 AdjustEOF(m_Obj.cread(this->eback(), m_BufSize))));
00442 this->setg(eb, eb, eb + ((res==EoF()) ? 0 : res));
00443 return (!res || (res == EoF())) ? EoF() : *eb;
00444 }
00445
00446 private:
00448 static int_type EoF() { return traits_type::eof(); }
00449
00451 template<typename INTYPE>
00452 static std::streampos AdjustEOF(INTYPE pos)
00453 { return (pos==-1) ? std::streampos(EoF()) : std::streampos(pos); }
00454
00455 void initialize(openmode mode)
00456 {
00457 if (mode & std::ios::in)
00458 {
00459 m_G = new char_type[unsigned(m_BufSize)];
00460 this->setg(m_G, m_G, m_G);
00461 }
00462 if (mode & std::ios::out)
00463 {
00464 m_P = new char_type[unsigned(m_BufSize)];
00465 this->setp(m_P, m_P + m_BufSize);
00466 }
00467 }
00468
00469 const size_type m_BufSize;
00470 largeobjectaccess m_Obj;
00471
00472
00473 char_type *m_G, *m_P;
00474 };
00475
00476
00478
00486 template<typename CHAR=char, typename TRAITS=std::char_traits<CHAR> >
00487 class basic_ilostream :
00488 public std::basic_istream<CHAR, TRAITS>
00489 {
00490 typedef std::basic_istream<CHAR, TRAITS> super;
00491
00492 public:
00493 typedef CHAR char_type;
00494 typedef TRAITS traits_type;
00495 typedef typename traits_type::int_type int_type;
00496 typedef typename traits_type::pos_type pos_type;
00497 typedef typename traits_type::off_type off_type;
00498
00500
00505 basic_ilostream(dbtransaction &T,
00506 largeobject O,
00507 largeobject::size_type BufSize=512) :
00508 super(0),
00509 m_Buf(T, O, std::ios::in, BufSize)
00510 { super::init(&m_Buf); }
00511
00513
00518 basic_ilostream(dbtransaction &T,
00519 oid O,
00520 largeobject::size_type BufSize=512) :
00521 super(0),
00522 m_Buf(T, O, std::ios::in, BufSize)
00523 { super::init(&m_Buf); }
00524
00525 private:
00526 largeobject_streambuf<CHAR,TRAITS> m_Buf;
00527 };
00528
00529 typedef basic_ilostream<char> ilostream;
00530
00531
00533
00541 template<typename CHAR=char, typename TRAITS=std::char_traits<CHAR> >
00542 class basic_olostream :
00543 public std::basic_ostream<CHAR, TRAITS>
00544 {
00545 typedef std::basic_ostream<CHAR, TRAITS> super;
00546 public:
00547 typedef CHAR char_type;
00548 typedef TRAITS traits_type;
00549 typedef typename traits_type::int_type int_type;
00550 typedef typename traits_type::pos_type pos_type;
00551 typedef typename traits_type::off_type off_type;
00552
00554
00559 basic_olostream(dbtransaction &T,
00560 largeobject O,
00561 largeobject::size_type BufSize=512) :
00562 super(0),
00563 m_Buf(T, O, std::ios::out, BufSize)
00564 { super::init(&m_Buf); }
00565
00567
00572 basic_olostream(dbtransaction &T,
00573 oid O,
00574 largeobject::size_type BufSize=512) :
00575 super(0),
00576 m_Buf(T, O, std::ios::out, BufSize)
00577 { super::init(&m_Buf); }
00578
00579 ~basic_olostream()
00580 {
00581 try
00582 {
00583 m_Buf.pubsync(); m_Buf.pubsync();
00584 }
00585 catch (const std::exception &e)
00586 {
00587 m_Buf.process_notice(e.what());
00588 }
00589 }
00590
00591 private:
00592 largeobject_streambuf<CHAR,TRAITS> m_Buf;
00593 };
00594
00595 typedef basic_olostream<char> olostream;
00596
00597
00599
00607 template<typename CHAR=char, typename TRAITS=std::char_traits<CHAR> >
00608 class basic_lostream :
00609 public std::basic_iostream<CHAR, TRAITS>
00610 {
00611 typedef std::basic_iostream<CHAR, TRAITS> super;
00612
00613 public:
00614 typedef CHAR char_type;
00615 typedef TRAITS traits_type;
00616 typedef typename traits_type::int_type int_type;
00617 typedef typename traits_type::pos_type pos_type;
00618 typedef typename traits_type::off_type off_type;
00619
00621
00626 basic_lostream(dbtransaction &T,
00627 largeobject O,
00628 largeobject::size_type BufSize=512) :
00629 super(0),
00630 m_Buf(T, O, std::ios::in | std::ios::out, BufSize)
00631 { super::init(&m_Buf); }
00632
00634
00639 basic_lostream(dbtransaction &T,
00640 oid O,
00641 largeobject::size_type BufSize=512) :
00642 super(0),
00643 m_Buf(T, O, std::ios::in | std::ios::out, BufSize)
00644 { super::init(&m_Buf); }
00645
00646 ~basic_lostream()
00647 {
00648 try
00649 {
00650 m_Buf.pubsync(); m_Buf.pubsync();
00651 }
00652 catch (const std::exception &e)
00653 {
00654 m_Buf.process_notice(e.what());
00655 }
00656 }
00657
00658 private:
00659 largeobject_streambuf<CHAR,TRAITS> m_Buf;
00660 };
00661
00662 typedef basic_lostream<char> lostream;
00663
00664 }
00665
00666 #include "pqxx/compiler-internal-post.hxx"
00667
00668 #endif
00669