# largeobject.hxx

Go to the documentation of this file.

    00001 /*-------------------------------------------------------------------------
    00002  *
    00003  *   FILE
    00004  *      pqxx/largeobject.hxx
    00005  *
    00006  *   DESCRIPTION
    00007  *      libpqxx's Large Objects interface
    00008  *   Allows access to large objects directly, or through I/O streams
    00009  *   DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/largeobject instead.
    00010  *
    00011  * Copyright (c) 2003-2006, Jeroen T. Vermeulen <jtv@xs4all.nl>
    00012  *
    00013  * See COPYING for copyright license.  If you did not receive a file called
    00014  * COPYING with this source code, please notify the distributor of this mistake,
    00015  * or contact the author.
    00016  *
    00017  *-------------------------------------------------------------------------
    00018  */
    00019 #include "pqxx/compiler-public.hxx"
    00020 #include "pqxx/compiler-internal-pre.hxx"
    00021
    00022 #ifdef PQXX_HAVE_STREAMBUF
    00023 #include <streambuf>
    00024 #else
    00025 #include <streambuf.h>
    00026 #endif
    00027
    00028 #include "pqxx/dbtransaction"
    00029
    00030
    00031 namespace pqxx
    00032 {
    00033
    00034 class largeobjectaccess;
    00035
    00037
    00044 class PQXX_LIBEXPORT largeobject
    00045 {
    00046 public:
    00047   typedef long size_type;
    00048
    00050   largeobject() throw ();                                               //[t48]
    00051
    00053
    00055   explicit largeobject(dbtransaction &T);                               //[t48]
    00056
    00058
    00062   explicit largeobject(oid O) throw () : m_ID(O) {}                     //[t48]
    00063
    00065
    00069   largeobject(dbtransaction &T, const PGSTD::string &File);             //[t53]
    00070
    00072
    00076   largeobject(const largeobjectaccess &O) throw ();                     //[t50]
    00077
    00079
    00083   oid id() const throw () { return m_ID; }                              //[t48]
    00084
    00093
    00094
    00095   bool operator==(const largeobject &other) const                       //[t51]
    00096           { return m_ID == other.m_ID; }
    00098
    00099   bool operator!=(const largeobject &other) const                       //[t51]
    00100           { return m_ID != other.m_ID; }
    00102
    00103   bool operator<=(const largeobject &other) const                       //[t51]
    00104           { return m_ID <= other.m_ID; }
    00106
    00107   bool operator>=(const largeobject &other) const                       //[t51]
    00108           { return m_ID >= other.m_ID; }
    00110
    00111   bool operator<(const largeobject &other) const                        //[t51]
    00112           { return m_ID < other.m_ID; }
    00114
    00115   bool operator>(const largeobject &other) const                        //[t51]
    00116           { return m_ID > other.m_ID; }
    00118
    00120
    00124   void to_file(dbtransaction &T, const PGSTD::string &File) const;      //[t52]
    00125
    00127
    00131   void remove(dbtransaction &T) const;                                  //[t48]
    00132
    00133 protected:
    00134   static internal::pq::PGconn *RawConnection(const dbtransaction &T)
    00135   {
    00136     return T.conn().RawConnection();
    00137   }
    00138
    00139   PGSTD::string Reason(int err) const;
    00140
    00141 private:
    00142   oid m_ID;
    00143 };
    00144
    00145
    00146 // TODO: New hierarchy with separate read / write / mixed-mode access
    00147
    00149 class PQXX_LIBEXPORT largeobjectaccess : private largeobject
    00150 {
    00151 public:
    00152   using largeobject::size_type;
    00153   typedef long off_type;
    00154   typedef size_type pos_type;
    00155
    00157
    00161   typedef PGSTD::ios::openmode openmode;
    00162
    00164
    00168   typedef PGSTD::ios::seekdir seekdir;
    00169
    00171
    00175   explicit largeobjectaccess(dbtransaction &T,
    00176                              openmode mode =
    00177                                 PGSTD::ios::in |
    00178                                 PGSTD::ios::out);                       //[t51]
    00179
    00181
    00187   largeobjectaccess(dbtransaction &T,
    00188                     oid O,
    00189                     openmode mode =
    00190                         PGSTD::ios::in |
    00191                         PGSTD::ios::out);                               //[t52]
    00192
    00194
    00199   largeobjectaccess(dbtransaction &T,
    00200                     largeobject O,
    00201                     openmode mode = PGSTD::ios::in | PGSTD::ios::out);  //[t50]
    00202
    00204
    00209   largeobjectaccess(dbtransaction &T,
    00210                     const PGSTD::string &File,
    00211                     openmode mode =
    00212                         PGSTD::ios::in | PGSTD::ios::out);              //[t55]
    00213
    00214   ~largeobjectaccess() throw () { close(); }
    00215
    00217
    00220   using largeobject::id;
    00221
    00223
    00226   void to_file(const PGSTD::string &File) const                         //[t54]
    00227         { largeobject::to_file(m_Trans, File); }
    00228
    00229 #ifdef PQXX_BROKEN_USING_DECL
    00231
    00235   void to_file(dbtransaction &T, const PGSTD::string &F) const
    00236         { largeobject::to_file(T, F); }
    00237 #else
    00238   using largeobject::to_file;
    00239 #endif
    00240
    00245
    00246
    00250   void write(const char Buf[], size_type Len);                          //[t51]
    00251
    00253
    00256   void write(const PGSTD::string &Buf)                                  //[t50]
    00257         { write(Buf.c_str(), static_cast<size_type>(Buf.size())); }
    00258
    00260
    00266   size_type read(char Buf[], size_type Len);                            //[t50]
    00267
    00269
    00272   size_type seek(size_type dest, seekdir dir);                          //[t51]
    00273
    00275
    00278   size_type tell() const;                                               //[t50]
    00280
    00290
    00291
    00299   pos_type cseek(off_type dest, seekdir dir) throw ();                  //[t50]
    00300
    00302
    00308   off_type cwrite(const char Buf[], size_type Len) throw ();            //[t50]
    00309
    00311
    00317   off_type cread(char Buf[], size_type Len) throw ();                   //[t50]
    00318
    00320
    00324   pos_type ctell() const throw ();                                      //[t50]
    00326
    00331
    00332   void process_notice(const PGSTD::string &) throw ();                  //[t50]
    00334
    00335   using largeobject::remove;
    00336
    00337   using largeobject::operator==;
    00338   using largeobject::operator!=;
    00339   using largeobject::operator<;
    00340   using largeobject::operator<=;
    00341   using largeobject::operator>;
    00342   using largeobject::operator>=;
    00343
    00344 private:
    00345   PGSTD::string PQXX_PRIVATE Reason(int err) const;
    00346   internal::pq::PGconn *RawConnection() const
    00347         { return largeobject::RawConnection(m_Trans); }
    00348
    00349   void open(openmode mode);
    00350   void close() throw ();
    00351
    00352   dbtransaction &m_Trans;
    00353   int m_fd;
    00354
    00355   // Not allowed:
    00356   largeobjectaccess();
    00357   largeobjectaccess(const largeobjectaccess &);
    00358   largeobjectaccess operator=(const largeobjectaccess &);
    00359 };
    00360
    00361
    00363
    00371 template<typename CHAR=char, typename TRAITS=PGSTD::char_traits<CHAR> >
    00372   class largeobject_streambuf :
    00373 #ifdef PQXX_HAVE_STREAMBUF
    00374     public PGSTD::basic_streambuf<CHAR, TRAITS>
    00375 #else
    00376     public PGSTD::streambuf
    00377 #endif
    00378 {
    00379   typedef long size_type;
    00380 public:
    00381   typedef CHAR   char_type;
    00382   typedef TRAITS traits_type;
    00383   typedef typename traits_type::int_type int_type;
    00384 #ifdef PQXX_HAVE_STREAMBUF
    00385   typedef typename traits_type::pos_type pos_type;
    00386   typedef typename traits_type::off_type off_type;
    00387 #else
    00388   typedef streamoff off_type;
    00389   typedef streampos pos_type;
    00390 #endif
    00391   typedef largeobjectaccess::openmode openmode;
    00392   typedef largeobjectaccess::seekdir seekdir;
    00393
    00394   largeobject_streambuf(dbtransaction &T,
    00395                         largeobject O,
    00396                         openmode mode = PGSTD::ios::in | PGSTD::ios::out,
    00397                         size_type BufSize=512) :                        //[t48]
    00398     m_BufSize(BufSize),
    00399     m_Obj(T, O),
    00400     m_G(0),
    00401     m_P(0)
    00402         { initialize(mode); }
    00403
    00404   largeobject_streambuf(dbtransaction &T,
    00405                         oid O,
    00406                         openmode mode = PGSTD::ios::in | PGSTD::ios::out,
    00407                         size_type BufSize=512) :                        //[t48]
    00408     m_BufSize(BufSize),
    00409     m_Obj(T, O),
    00410     m_G(0),
    00411     m_P(0)
    00412         { initialize(mode); }
    00413
    00414   virtual ~largeobject_streambuf() throw () { delete [] m_P; delete [] m_G; }
    00415
    00416
    00418   void process_notice(const PGSTD::string &s) { m_Obj.process_notice(s); }
    00419
    00420 #ifdef PQXX_HAVE_STREAMBUF
    00421 protected:
    00422 #endif
    00423   virtual int sync()
    00424   {
    00425     // setg() sets eback, gptr, egptr
    00426     setg(this->eback(), this->eback(), this->egptr());
    00427     return overflow(EoF());
    00428   }
    00429
    00430 protected:
    00431   virtual pos_type seekoff(off_type offset,
    00432                            seekdir dir,
    00433                            openmode)
    00434         { return AdjustEOF(m_Obj.cseek(offset, dir)); }
    00435
    00436   virtual pos_type seekpos(pos_type pos, openmode)
    00437         { return AdjustEOF(m_Obj.cseek(pos, PGSTD::ios::beg)); }
    00438
    00439   virtual int_type overflow(int_type ch = EoF())
    00440   {
    00441     char *const pp = this->pptr();
    00442     if (!pp) return EoF();
    00443     char *const pb = this->pbase();
    00444     int_type res = 0;
    00445
    00446     if (pp > pb) res = AdjustEOF(m_Obj.cwrite(pb, pp-pb));
    00447     setp(m_P, m_P + m_BufSize);
    00448
    00449     // Write that one more character, if it's there.
    00450     if (ch != EoF())
    00451     {
    00452       *this->pptr() = char(ch);
    00453       this->pbump(1);
    00454     }
    00455     return res;
    00456   }
    00457
    00458   virtual int_type underflow()
    00459   {
    00460     if (!this->gptr()) return EoF();
    00461     char *const eb = this->eback();
    00462     const int res = AdjustEOF(m_Obj.cread(this->eback(), m_BufSize));
    00463     setg(eb, eb, eb + ((res==EoF()) ? 0 : res));
    00464     return (!res || (res == EoF())) ? EoF() : *eb;
    00465   }
    00466
    00467 private:
    00469   static int_type EoF() { return traits_type::eof(); }
    00470
    00472   static PGSTD::streampos AdjustEOF(int pos) { return (pos==-1) ? EoF() : pos; }
    00473
    00474   void initialize(openmode mode)
    00475   {
    00476     if (mode & PGSTD::ios::in)
    00477     {
    00478       m_G = new char_type[m_BufSize];
    00479       setg(m_G, m_G, m_G);
    00480     }
    00481     if (mode & PGSTD::ios::out)
    00482     {
    00483       m_P = new char_type[m_BufSize];
    00484       setp(m_P, m_P + m_BufSize);
    00485     }
    00486   }
    00487
    00488   const size_type m_BufSize;
    00489   largeobjectaccess m_Obj;
    00490
    00491   // Get & put buffers
    00492   char_type *m_G, *m_P;
    00493 };
    00494
    00495
    00497
    00505 template<typename CHAR=char, typename TRAITS=PGSTD::char_traits<CHAR> >
    00506   class basic_ilostream :
    00507 #ifdef PQXX_HAVE_STREAMBUF
    00508     public PGSTD::basic_istream<CHAR, TRAITS>
    00509 #else
    00510     public PGSTD::istream
    00511 #endif
    00512 {
    00513 #ifdef PQXX_HAVE_STREAMBUF
    00514   typedef PGSTD::basic_istream<CHAR, TRAITS> super;
    00515 #else
    00516   typedef PGSTD::istream super;
    00517 #endif
    00518
    00519 public:
    00520   typedef CHAR char_type;
    00521   typedef TRAITS traits_type;
    00522   typedef typename traits_type::int_type int_type;
    00523   typedef typename traits_type::pos_type pos_type;
    00524   typedef typename traits_type::off_type off_type;
    00525
    00527
    00532   basic_ilostream(dbtransaction &T,
    00533                   largeobject O,
    00534                   largeobject::size_type BufSize=512) :                 //[t57]
    00535     super(0),
    00536     m_Buf(T, O, PGSTD::ios::in, BufSize)
    00537         { super::init(&m_Buf); }
    00538
    00540
    00545   basic_ilostream(dbtransaction &T,
    00546                   oid O,
    00547                   largeobject::size_type BufSize=512) :                 //[t48]
    00548     super(0),
    00549     m_Buf(T, O, PGSTD::ios::in, BufSize)
    00550         { super::init(&m_Buf); }
    00551
    00552 private:
    00553   largeobject_streambuf<CHAR,TRAITS> m_Buf;
    00554 };
    00555
    00556 typedef basic_ilostream<char> ilostream;
    00557
    00558
    00560
    00568 template<typename CHAR=char, typename TRAITS=PGSTD::char_traits<CHAR> >
    00569   class basic_olostream :
    00570 #ifdef PQXX_HAVE_STREAMBUF
    00571     public PGSTD::basic_ostream<CHAR, TRAITS>
    00572 #else
    00573     public PGSTD::ostream
    00574 #endif
    00575 {
    00576 #ifdef PQXX_HAVE_STREAMBUF
    00577   typedef PGSTD::basic_ostream<CHAR, TRAITS> super;
    00578 #else
    00579   typedef PGSTD::ostream super;
    00580 #endif
    00581 public:
    00582   typedef CHAR char_type;
    00583   typedef TRAITS traits_type;
    00584   typedef typename traits_type::int_type int_type;
    00585   typedef typename traits_type::pos_type pos_type;
    00586   typedef typename traits_type::off_type off_type;
    00587
    00589
    00594   basic_olostream(dbtransaction &T,
    00595                   largeobject O,
    00596                   largeobject::size_type BufSize=512) :                 //[t48]
    00597     super(0),
    00598     m_Buf(T, O, PGSTD::ios::out, BufSize)
    00599         { super::init(&m_Buf); }
    00600
    00602
    00607   basic_olostream(dbtransaction &T,
    00608                   oid O,
    00609                   largeobject::size_type BufSize=512) :                 //[t57]
    00610     super(0),
    00611     m_Buf(T, O, PGSTD::ios::out, BufSize)
    00612         { super::init(&m_Buf); }
    00613
    00614   ~basic_olostream()
    00615   {
    00616     try
    00617     {
    00618 #ifdef PQXX_HAVE_STREAMBUF
    00619       m_Buf.pubsync(); m_Buf.pubsync();
    00620 #else
    00621       m_Buf.sync(); m_Buf.sync();
    00622 #endif
    00623     }
    00624     catch (const PGSTD::exception &e)
    00625     {
    00626       m_Buf.process_notice(e.what());
    00627     }
    00628   }
    00629
    00630 private:
    00631   largeobject_streambuf<CHAR,TRAITS> m_Buf;
    00632 };
    00633
    00634 typedef basic_olostream<char> olostream;
    00635
    00636
    00638
    00646 template<typename CHAR=char, typename TRAITS=PGSTD::char_traits<CHAR> >
    00647   class basic_lostream :
    00648 #ifdef PQXX_HAVE_STREAMBUF
    00649     public PGSTD::basic_iostream<CHAR, TRAITS>
    00650 #else
    00651     public PGSTD::iostream
    00652 #endif
    00653 {
    00654 #ifdef PQXX_HAVE_STREAMBUF
    00655   typedef PGSTD::basic_iostream<CHAR, TRAITS> super;
    00656 #else
    00657   typedef PGSTD::iostream super;
    00658 #endif
    00659
    00660 public:
    00661   typedef CHAR char_type;
    00662   typedef TRAITS traits_type;
    00663   typedef typename traits_type::int_type int_type;
    00664   typedef typename traits_type::pos_type pos_type;
    00665   typedef typename traits_type::off_type off_type;
    00666
    00668
    00673   basic_lostream(dbtransaction &T,
    00674                  largeobject O,
    00675                  largeobject::size_type BufSize=512) :                  //[t59]
    00676     super(0),
    00677     m_Buf(T, O, PGSTD::ios::in | PGSTD::ios::out, BufSize)
    00678         { super::init(&m_Buf); }
    00679
    00681
    00686   basic_lostream(dbtransaction &T,
    00687                  oid O,
    00688                  largeobject::size_type BufSize=512) :                  //[t59]
    00689     super(0),
    00690     m_Buf(T, O, PGSTD::ios::in | PGSTD::ios::out, BufSize)
    00691         { super::init(&m_Buf); }
    00692
    00693   ~basic_lostream()
    00694   {
    00695     try
    00696     {
    00697 #ifdef PQXX_HAVE_STREAMBUF
    00698       m_Buf.pubsync(); m_Buf.pubsync();
    00699 #else
    00700       m_Buf.sync(); m_Buf.sync();
    00701 #endif
    00702     }
    00703     catch (const PGSTD::exception &e)
    00704     {
    00705       m_Buf.process_notice(e.what());
    00706     }
    00707   }
    00708
    00709 private:
    00710   largeobject_streambuf<CHAR,TRAITS> m_Buf;
    00711 };
    00712
    00713 typedef basic_lostream<char> lostream;
    00714
    00715 } // namespace pqxx
    00716
    00717 #include "pqxx/compiler-internal-post.hxx"