Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

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-2005, 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/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 ();                                               //[t48]
00050 
00052 
00054   explicit largeobject(dbtransaction &T);                               //[t48]
00055 
00057 
00061   explicit largeobject(oid O) throw () : m_ID(O) {}                     //[t48]
00062 
00064 
00068   largeobject(dbtransaction &T, const PGSTD::string &File);             //[t53]
00069 
00071 
00075   largeobject(const largeobjectaccess &O) throw ();                     //[t50]
00076 
00078 
00082   oid id() const throw () { return m_ID; }                              //[t48]
00083 
00092 
00093 
00094   bool operator==(const largeobject &other) const                       //[t51]
00095           { return m_ID == other.m_ID; }
00097 
00098   bool operator!=(const largeobject &other) const                       //[t51]
00099           { return m_ID != other.m_ID; }
00101 
00102   bool operator<=(const largeobject &other) const                       //[t51]
00103           { return m_ID <= other.m_ID; }
00105 
00106   bool operator>=(const largeobject &other) const                       //[t51]
00107           { return m_ID >= other.m_ID; }
00109 
00110   bool operator<(const largeobject &other) const                        //[t51]
00111           { return m_ID < other.m_ID; }
00113 
00114   bool operator>(const largeobject &other) const                        //[t51]
00115           { return m_ID > other.m_ID; }
00117 
00119 
00123   void to_file(dbtransaction &T, const PGSTD::string &File) const;      //[t52]
00124 
00126 
00130   void remove(dbtransaction &T) const;                                  //[t48]
00131 
00132 protected:
00133   static internal::pq::PGconn *RawConnection(const dbtransaction &T)
00134   {
00135     return T.conn().RawConnection();
00136   }
00137 
00138   PGSTD::string Reason(int err) const;
00139 
00140 private:
00141   oid m_ID;
00142 };
00143 
00144 
00145 // TODO: New hierarchy with separate read / write / mixed-mode access
00146 
00148 class PQXX_LIBEXPORT largeobjectaccess : private largeobject
00149 {
00150 public:
00151   using largeobject::size_type;
00152   typedef long off_type;
00153   typedef size_type pos_type;
00154 
00156 
00160   typedef PGSTD::ios::openmode openmode;
00161 
00163 
00167   typedef PGSTD::ios::seekdir seekdir;
00168 
00170 
00174   explicit largeobjectaccess(dbtransaction &T,
00175                              openmode mode =
00176                                 PGSTD::ios::in |
00177                                 PGSTD::ios::out);                       //[t51]
00178 
00180 
00186   largeobjectaccess(dbtransaction &T,
00187                     oid O,
00188                     openmode mode =
00189                         PGSTD::ios::in |
00190                         PGSTD::ios::out);                               //[t52]
00191 
00193 
00198   largeobjectaccess(dbtransaction &T,
00199                     largeobject O,
00200                     openmode mode = PGSTD::ios::in | PGSTD::ios::out);  //[t50]
00201 
00203 
00208   largeobjectaccess(dbtransaction &T,
00209                     const PGSTD::string &File,
00210                     openmode mode =
00211                         PGSTD::ios::in | PGSTD::ios::out);              //[t55]
00212 
00213   ~largeobjectaccess() throw () { close(); }
00214 
00216 
00219   using largeobject::id;
00220 
00222 
00225   void to_file(const PGSTD::string &File) const                         //[t54]
00226         { largeobject::to_file(m_Trans, File); }
00227 
00228 #ifdef PQXX_BROKEN_USING_DECL
00229 
00230 
00234   void to_file(dbtransaction &T, const PGSTD::string &F) const
00235         { largeobject::to_file(T, F); }
00236 #else
00237   using largeobject::to_file;
00238 #endif
00239 
00244 
00245 
00249   void write(const char Buf[], size_type Len);                          //[t51]
00250 
00252 
00255   void write(const PGSTD::string &Buf)                                  //[t50]
00256         { write(Buf.c_str(), Buf.size()); }
00257 
00259 
00265   size_type read(char Buf[], size_type Len);                            //[t50]
00266 
00268 
00271   size_type seek(size_type dest, seekdir dir);                          //[t51]
00272         
00274 
00277   size_type tell() const;                                               //[t50]
00279 
00289 
00290 
00298   pos_type cseek(off_type dest, seekdir dir) throw ();                  //[t50]
00299 
00301 
00307   off_type cwrite(const char Buf[], size_type Len) throw ();            //[t50]
00308 
00310 
00316   off_type cread(char Buf[], size_type Len) throw ();                   //[t50]
00317   
00319 
00323   pos_type ctell() const throw ();                                      //[t50]
00325 
00330 
00331   void process_notice(const PGSTD::string &) throw ();                  //[t50]
00333 
00334   using largeobject::remove;
00335 
00336   using largeobject::operator==;
00337   using largeobject::operator!=;
00338   using largeobject::operator<;
00339   using largeobject::operator<=;
00340   using largeobject::operator>;
00341   using largeobject::operator>=;
00342 
00343 private:
00344   PGSTD::string PQXX_PRIVATE Reason(int err) const;
00345   internal::pq::PGconn *RawConnection() const
00346         { return largeobject::RawConnection(m_Trans); }
00347 
00348   void open(openmode mode);
00349   void close() throw ();
00350 
00351   dbtransaction &m_Trans;
00352   int m_fd;
00353 
00354   // Not allowed:
00355   largeobjectaccess();
00356   largeobjectaccess(const largeobjectaccess &);
00357   largeobjectaccess operator=(const largeobjectaccess &);
00358 };
00359 
00360 
00362 
00370 template<typename CHAR=char, typename TRAITS=PGSTD::char_traits<CHAR> >
00371   class largeobject_streambuf :
00372 #ifdef PQXX_HAVE_STREAMBUF
00373     public PGSTD::basic_streambuf<CHAR, TRAITS>
00374 #else
00375     public PGSTD::streambuf
00376 #endif
00377 {
00378   typedef long size_type;
00379 public:
00380   typedef CHAR   char_type;
00381   typedef TRAITS traits_type;
00382   typedef typename traits_type::int_type int_type;
00383 #ifdef PQXX_HAVE_STREAMBUF
00384   typedef typename traits_type::pos_type pos_type;
00385   typedef typename traits_type::off_type off_type;
00386 #else
00387   typedef streamoff off_type;
00388   typedef streampos pos_type;
00389 #endif
00390   typedef largeobjectaccess::openmode openmode;
00391   typedef largeobjectaccess::seekdir seekdir;
00392 
00393   largeobject_streambuf(dbtransaction &T,
00394                         largeobject O,
00395                         openmode mode = PGSTD::ios::in | PGSTD::ios::out,
00396                         size_type BufSize=512) :                        //[t48]
00397     m_BufSize(BufSize),
00398     m_Obj(T, O),
00399     m_G(0),
00400     m_P(0)
00401         { initialize(mode); }
00402 
00403   largeobject_streambuf(dbtransaction &T,
00404                         oid O,
00405                         openmode mode = PGSTD::ios::in | PGSTD::ios::out,
00406                         size_type BufSize=512) :                        //[t48]
00407     m_BufSize(BufSize),
00408     m_Obj(T, O),
00409     m_G(0),
00410     m_P(0)
00411         { initialize(mode); }
00412 
00413   virtual ~largeobject_streambuf() throw () { delete [] m_P; delete [] m_G; }
00414 
00415 
00417   void process_notice(const PGSTD::string &s) { m_Obj.process_notice(s); }
00418 
00419 #ifdef PQXX_HAVE_STREAMBUF
00420 protected:
00421 #endif
00422   virtual int sync()
00423   {
00424     // setg() sets eback, gptr, egptr
00425     setg(this->eback(), this->eback(), this->egptr());
00426     return overflow(EoF());
00427   }
00428 
00429 protected:
00430   virtual pos_type seekoff(off_type offset,
00431                            seekdir dir,
00432                            openmode)
00433         { return AdjustEOF(m_Obj.cseek(offset, dir)); }
00434 
00435   virtual pos_type seekpos(pos_type pos, openmode)
00436         { return AdjustEOF(m_Obj.cseek(pos, PGSTD::ios::beg)); }
00437 
00438   virtual int_type overflow(int_type ch = EoF())
00439   {
00440     char *const pp = this->pptr();
00441     if (!pp) return EoF();
00442     char *const pb = this->pbase();
00443     int_type res = 0;
00444 
00445     if (pp > pb) res = AdjustEOF(m_Obj.cwrite(pb, pp-pb));
00446     setp(m_P, m_P + m_BufSize);
00447 
00448     // Write that one more character, if it's there.
00449     if (ch != EoF())
00450     {
00451       *this->pptr() = char(ch);
00452       this->pbump(1);
00453     }
00454     return res;
00455   }
00456 
00457   virtual int_type underflow()
00458   {
00459     if (!this->gptr()) return EoF();
00460     char *const eb = this->eback();
00461     const int res = AdjustEOF(m_Obj.cread(this->eback(), m_BufSize));
00462     setg(eb, eb, eb + ((res==EoF()) ? 0 : res));
00463     return (!res || (res == EoF())) ? EoF() : *eb;
00464   }
00465 
00466 private:
00468   static int_type EoF() { return traits_type::eof(); }
00469 
00471   static PGSTD::streampos AdjustEOF(int pos) { return (pos==-1) ? EoF() : pos; }
00472 
00473   void initialize(openmode mode)
00474   {
00475     if (mode & PGSTD::ios::in)
00476     {
00477       m_G = new char_type[m_BufSize];
00478       setg(m_G, m_G, m_G);
00479     }
00480     if (mode & PGSTD::ios::out)
00481     {
00482       m_P = new char_type[m_BufSize];
00483       setp(m_P, m_P + m_BufSize);
00484     }
00485   }
00486 
00487   const size_type m_BufSize;
00488   largeobjectaccess m_Obj;
00489 
00490   // Get & put buffers
00491   char_type *m_G, *m_P;
00492 };
00493 
00494 
00496 
00504 template<typename CHAR=char, typename TRAITS=PGSTD::char_traits<CHAR> >
00505   class basic_ilostream :
00506 #ifdef PQXX_HAVE_STREAMBUF
00507     public PGSTD::basic_istream<CHAR, TRAITS>
00508 #else
00509     public PGSTD::istream
00510 #endif
00511 {
00512 #ifdef PQXX_HAVE_STREAMBUF
00513   typedef PGSTD::basic_istream<CHAR, TRAITS> super;
00514 #else
00515   typedef PGSTD::istream super;
00516 #endif
00517 
00518 public:
00519   typedef CHAR char_type;
00520   typedef TRAITS traits_type;
00521   typedef typename traits_type::int_type int_type;
00522   typedef typename traits_type::pos_type pos_type;
00523   typedef typename traits_type::off_type off_type;
00524 
00526 
00531   basic_ilostream(dbtransaction &T,
00532                   largeobject O,
00533                   largeobject::size_type BufSize=512) :                 //[t57]
00534     super(0),
00535     m_Buf(T, O, PGSTD::ios::in, BufSize)
00536         { super::init(&m_Buf); }
00537 
00539 
00544   basic_ilostream(dbtransaction &T,
00545                   oid O,
00546                   largeobject::size_type BufSize=512) :                 //[t48]
00547     super(0),
00548     m_Buf(T, O, PGSTD::ios::in, BufSize)
00549         { super::init(&m_Buf); }
00550 
00551 private:
00552   largeobject_streambuf<CHAR,TRAITS> m_Buf;
00553 };
00554 
00555 typedef basic_ilostream<char> ilostream;
00556 
00557 
00559 
00567 template<typename CHAR=char, typename TRAITS=PGSTD::char_traits<CHAR> >
00568   class basic_olostream :
00569 #ifdef PQXX_HAVE_STREAMBUF
00570     public PGSTD::basic_ostream<CHAR, TRAITS>
00571 #else
00572     public PGSTD::ostream
00573 #endif
00574 {
00575 #ifdef PQXX_HAVE_STREAMBUF
00576   typedef PGSTD::basic_ostream<CHAR, TRAITS> super;
00577 #else
00578   typedef PGSTD::ostream super;
00579 #endif
00580 public:
00581   typedef CHAR char_type;
00582   typedef TRAITS traits_type;
00583   typedef typename traits_type::int_type int_type;
00584   typedef typename traits_type::pos_type pos_type;
00585   typedef typename traits_type::off_type off_type;
00586 
00588 
00593   basic_olostream(dbtransaction &T,
00594                   largeobject O,
00595                   largeobject::size_type BufSize=512) :                 //[t48]
00596     super(0),
00597     m_Buf(T, O, PGSTD::ios::out, BufSize)
00598         { super::init(&m_Buf); }
00599 
00601 
00606   basic_olostream(dbtransaction &T,
00607                   oid O,
00608                   largeobject::size_type BufSize=512) :                 //[t57]
00609     super(0),
00610     m_Buf(T, O, PGSTD::ios::out, BufSize)
00611         { super::init(&m_Buf); }
00612 
00613   ~basic_olostream()
00614   {
00615     try
00616     {
00617 #ifdef PQXX_HAVE_STREAMBUF
00618       m_Buf.pubsync(); m_Buf.pubsync();
00619 #else
00620       m_Buf.sync(); m_Buf.sync();
00621 #endif
00622     }
00623     catch (const PGSTD::exception &e)
00624     {
00625       m_Buf.process_notice(e.what());
00626     }
00627   }
00628 
00629 private:
00630   largeobject_streambuf<CHAR,TRAITS> m_Buf;
00631 };
00632 
00633 typedef basic_olostream<char> olostream;
00634 
00635 
00637 
00645 template<typename CHAR=char, typename TRAITS=PGSTD::char_traits<CHAR> >
00646   class basic_lostream :
00647 #ifdef PQXX_HAVE_STREAMBUF
00648     public PGSTD::basic_iostream<CHAR, TRAITS>
00649 #else
00650     public PGSTD::iostream
00651 #endif
00652 {
00653 #ifdef PQXX_HAVE_STREAMBUF
00654   typedef PGSTD::basic_iostream<CHAR, TRAITS> super;
00655 #else
00656   typedef PGSTD::iostream super;
00657 #endif
00658 
00659 public:
00660   typedef CHAR char_type;
00661   typedef TRAITS traits_type;
00662   typedef typename traits_type::int_type int_type;
00663   typedef typename traits_type::pos_type pos_type;
00664   typedef typename traits_type::off_type off_type;
00665 
00667 
00672   basic_lostream(dbtransaction &T,
00673                  largeobject O,
00674                  largeobject::size_type BufSize=512) :                  //[t59]
00675     super(0),
00676     m_Buf(T, O, PGSTD::ios::in | PGSTD::ios::out, BufSize)
00677         { super::init(&m_Buf); }
00678 
00680 
00685   basic_lostream(dbtransaction &T,
00686                  oid O,
00687                  largeobject::size_type BufSize=512) :                  //[t59]
00688     super(0),
00689     m_Buf(T, O, PGSTD::ios::in | PGSTD::ios::out, BufSize)
00690         { super::init(&m_Buf); }
00691 
00692   ~basic_lostream()
00693   {
00694     try
00695     {
00696 #ifdef PQXX_HAVE_STREAMBUF
00697       m_Buf.pubsync(); m_Buf.pubsync();
00698 #else
00699       m_Buf.sync(); m_Buf.sync();
00700 #endif
00701     }
00702     catch (const PGSTD::exception &e)
00703     {
00704       m_Buf.process_notice(e.what());
00705     }
00706   }
00707 
00708 private:
00709   largeobject_streambuf<CHAR,TRAITS> m_Buf;
00710 };
00711 
00712 typedef basic_lostream<char> lostream;
00713 
00714 }

Generated on Mon Oct 3 20:28:59 2005 for libpqxx by  doxygen 1.4.2