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"

Generated on Thu Feb 1 17:12:08 2007 for libpqxx by  doxygen 1.5.1