Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | 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-2004, 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 #include <new>
00022 
00023 #ifdef PQXX_HAVE_STREAMBUF
00024 #include <streambuf>
00025 #else
00026 #include <streambuf.h>
00027 #endif
00028 
00029 #include "pqxx/dbtransaction"
00030 
00031 
00032 namespace pqxx
00033 {
00034 
00035 class largeobjectaccess;
00036 
00038 
00045 class PQXX_LIBEXPORT largeobject
00046 {
00047 public:
00048   typedef long size_type;
00049 
00051   largeobject() throw ();                                               //[t48]
00052 
00054 
00056   explicit largeobject(dbtransaction &T);                               //[t48]
00057 
00059 
00063   explicit largeobject(oid O) throw () : m_ID(O) {}                     //[t48]
00064 
00066 
00070   largeobject(dbtransaction &T, const PGSTD::string &File);             //[t53]
00071 
00073 
00077   largeobject(const largeobjectaccess &O) throw ();                     //[t50]
00078 
00080 
00084   oid id() const throw () { return m_ID; }                              //[t48]
00085 
00087   bool operator==(const largeobject &other) const                       //[t51]
00088           { return m_ID == other.m_ID; }
00090   bool operator!=(const largeobject &other) const                       //[t51]
00091           { return m_ID != other.m_ID; }
00093   bool operator<=(const largeobject &other) const                       //[t51]
00094           { return m_ID <= other.m_ID; }
00096   bool operator>=(const largeobject &other) const                       //[t51]
00097           { return m_ID >= other.m_ID; }
00099   bool operator<(const largeobject &other) const                        //[t51]
00100           { return m_ID < other.m_ID; }
00102   bool operator>(const largeobject &other) const                        //[t51]
00103           { return m_ID > other.m_ID; }
00104 
00106 
00110   void to_file(dbtransaction &T, const PGSTD::string &File) const;      //[t52]
00111 
00113 
00117   void remove(dbtransaction &T) const;                                  //[t48]
00118 
00119 protected:
00120   static PGconn *RawConnection(const dbtransaction &T)
00121   {
00122     return T.conn().RawConnection();
00123   }
00124 
00125   PGSTD::string Reason() const;
00126 
00127 private:
00128   oid m_ID;
00129 };
00130 
00131 
00132 // TODO: New hierarchy with separate read / write / mixed-mode access
00133 
00135 class PQXX_LIBEXPORT largeobjectaccess : private largeobject
00136 {
00137 public:
00138   using largeobject::size_type;
00139   typedef long off_type;
00140   typedef size_type pos_type;
00141 
00143 
00147   typedef PGSTD::ios::openmode openmode;
00148 
00150 
00154   typedef PGSTD::ios::seekdir seekdir;
00155 
00157 
00161   explicit largeobjectaccess(dbtransaction &T, 
00162                              openmode mode = 
00163                                 PGSTD::ios::in | 
00164                                 PGSTD::ios::out);                       //[t51]
00165 
00167 
00173   largeobjectaccess(dbtransaction &T, 
00174                     oid O,
00175                     openmode mode = 
00176                         PGSTD::ios::in | 
00177                         PGSTD::ios::out);                               //[t52]
00178 
00180 
00185   largeobjectaccess(dbtransaction &T, 
00186                     largeobject O,
00187                     openmode mode = PGSTD::ios::in | PGSTD::ios::out);  //[t50]
00188 
00190 
00195   largeobjectaccess(dbtransaction &T, 
00196                     const PGSTD::string &File,
00197                     openmode mode = 
00198                         PGSTD::ios::in | PGSTD::ios::out);              //[t55]
00199 
00200   ~largeobjectaccess() throw () { close(); }
00201 
00203 
00206   using largeobject::id;
00207 
00209 
00212   void to_file(const PGSTD::string &File) const                         //[t54]
00213   { 
00214     largeobject::to_file(m_Trans, File); 
00215   }
00216 
00217 #ifdef PQXX_BROKEN_USING_DECL
00218 
00219 
00223   void to_file(dbtransaction &T, const PGSTD::string &F) const
00224         { largeobject::to_file(T, F); }
00225 #else
00226   using largeobject::to_file;
00227 #endif
00228 
00229 
00231 
00235   void write(const char Buf[], size_type Len);                          //[t51]
00236 
00238 
00241   void write(const PGSTD::string &Buf)                                  //[t50]
00242         { write(Buf.c_str(), Buf.size()); }
00243 
00245 
00251   size_type read(char Buf[], size_type Len);                            //[t50]
00252 
00254 
00257   size_type seek(size_type dest, seekdir dir);                          //[t51]
00258 
00260 
00268   pos_type cseek(off_type dest, seekdir dir) throw ();                  //[t50]
00269     
00271 
00277   off_type cwrite(const char Buf[], size_type Len) throw ();            //[t50]
00278 
00280 
00286   off_type cread(char Buf[], size_type Len) throw ();                   //[t50]
00287 
00288 
00290   void process_notice(const PGSTD::string &) throw ();                  //[t50]
00291 
00292   using largeobject::remove;
00293 
00294   using largeobject::operator==;
00295   using largeobject::operator!=;
00296   using largeobject::operator<;
00297   using largeobject::operator<=;
00298   using largeobject::operator>;
00299   using largeobject::operator>=;
00300 
00301 private:
00302   PGSTD::string Reason() const;
00303   PGconn *RawConnection() { return largeobject::RawConnection(m_Trans); }
00304 
00305   void open(openmode mode);
00306   void close() throw ();
00307 
00308   dbtransaction &m_Trans;
00309   int m_fd;
00310 
00311   // Not allowed:
00312   largeobjectaccess();
00313   largeobjectaccess(const largeobjectaccess &);
00314   largeobjectaccess operator=(const largeobjectaccess &);
00315 };
00316 
00317 
00319 
00327 template<typename CHAR=char, typename TRAITS=PGSTD::char_traits<CHAR> >
00328   class largeobject_streambuf :
00329 #ifdef PQXX_HAVE_STREAMBUF
00330     public PGSTD::basic_streambuf<CHAR, TRAITS>
00331 #else
00332     public PGSTD::streambuf
00333 #endif
00334 {
00335   typedef long size_type;
00336 public:
00337   typedef CHAR   char_type;
00338   typedef TRAITS traits_type;
00339   typedef typename traits_type::int_type int_type;
00340 #ifdef PQXX_HAVE_STREAMBUF
00341   typedef typename traits_type::pos_type pos_type;
00342   typedef typename traits_type::off_type off_type;
00343 #else
00344   typedef streamoff off_type;
00345   typedef streampos pos_type;
00346 #endif
00347   typedef largeobjectaccess::openmode openmode;
00348   typedef largeobjectaccess::seekdir seekdir;
00349 
00350   largeobject_streambuf(dbtransaction &T,
00351                         largeobject O,
00352                         openmode mode = PGSTD::ios::in | PGSTD::ios::out,
00353                         size_type BufSize=512) :                        //[t48]
00354     m_BufSize(BufSize),
00355     m_Obj(T, O),
00356     m_G(0),
00357     m_P(0)
00358   {
00359     initialize(mode);
00360   }
00361 
00362   largeobject_streambuf(dbtransaction &T,
00363                         oid O,
00364                         openmode mode = PGSTD::ios::in | PGSTD::ios::out,
00365                         size_type BufSize=512) :                        //[t48]
00366     m_BufSize(BufSize),
00367     m_Obj(T, O),
00368     m_G(0),
00369     m_P(0)
00370   {
00371     initialize(mode);
00372   }
00373 
00374   virtual ~largeobject_streambuf() throw ()
00375   {
00376     delete [] m_P;
00377     delete [] m_G;
00378   }
00379 
00380 
00382   void process_notice(const PGSTD::string &s) { m_Obj.process_notice(s); }
00383 
00384 #ifdef PQXX_HAVE_STREAMBUF
00385 protected:
00386 #endif
00387   virtual int sync()
00388   {
00389     // setg() sets eback, gptr, egptr
00390     setg(this->eback(), this->eback(), this->egptr());
00391     return overflow(EoF());
00392   }
00393 
00394 protected:
00395   virtual pos_type seekoff(off_type offset, 
00396                            seekdir dir,
00397                            openmode mode)
00398   {
00399     if (mode != SEEK_CUR)
00400       throw PGSTD::logic_error("Offset "+to_string(int(mode))+" in seekoff()");
00401     return AdjustEOF(m_Obj.cseek(offset, dir));
00402   }
00403 
00404   virtual pos_type seekpos(pos_type pos, openmode mode)
00405   {
00406     if (mode != SEEK_SET)
00407       throw PGSTD::logic_error("Offset "+to_string(int(mode))+" in seekpos()");
00408     return AdjustEOF(m_Obj.cseek(pos, PGSTD::ios::beg));
00409   }
00410 
00411   virtual int_type overflow(int_type ch = EoF())
00412   {
00413     char *const pp = this->pptr();
00414     if (!pp) return EoF();
00415     char *const pb = this->pbase();
00416     int_type res = 0;
00417 
00418     if (pp > pb) res = AdjustEOF(m_Obj.cwrite(pb, pp-pb));
00419     setp(m_P, m_P + m_BufSize);
00420 
00421     // Write that one more character, if it's there.
00422     if (ch != EoF())
00423     {
00424       *this->pptr() = char(ch);
00425       this->pbump(1);
00426     }
00427     return res;
00428   }
00429 
00430   virtual int_type underflow()
00431   {
00432     if (!this->gptr()) return EoF();
00433     char *const eb = this->eback();
00434     const int res = AdjustEOF(m_Obj.cread(this->eback(), m_BufSize));
00435     setg(eb, eb, eb + ((res==EoF()) ? 0 : res));
00436     return (!res || (res == EoF())) ? EoF() : *eb;
00437   }
00438 
00439 private:
00441   static int_type EoF() { return traits_type::eof(); }
00442 
00444   static PGSTD::streampos AdjustEOF(int pos)
00445   {
00446     return (pos == -1) ? EoF() : pos;
00447   }
00448 
00449   void initialize(openmode mode)
00450   {
00451     if (mode & PGSTD::ios::in) 
00452     {
00453       m_G = new char_type[m_BufSize];
00454       setg(m_G, m_G, m_G);
00455     }
00456     if (mode & PGSTD::ios::out)
00457     {
00458       m_P = new char_type[m_BufSize];
00459       setp(m_P, m_P + m_BufSize);
00460     }
00461   }
00462 
00463   const size_type m_BufSize;
00464   largeobjectaccess m_Obj;
00465 
00466   // Get & put buffers
00467   char_type *m_G, *m_P;
00468 };
00469 
00470 
00472 
00480 template<typename CHAR=char, typename TRAITS=PGSTD::char_traits<CHAR> > 
00481   class basic_ilostream :
00482 #ifdef PQXX_HAVE_STREAMBUF
00483     public PGSTD::basic_istream<CHAR, TRAITS>
00484 #else
00485     public PGSTD::istream
00486 #endif
00487 {
00488 #ifdef PQXX_HAVE_STREAMBUF
00489   typedef PGSTD::basic_istream<CHAR, TRAITS> super;
00490 #else
00491   typedef PGSTD::istream super;
00492 #endif
00493 
00494 public:
00495   typedef CHAR char_type;
00496   typedef TRAITS traits_type;
00497   typedef typename traits_type::int_type int_type;
00498   typedef typename traits_type::pos_type pos_type;
00499   typedef typename traits_type::off_type off_type;
00500 
00502 
00506   basic_ilostream(dbtransaction &T, 
00507                   largeobject O, 
00508                   largeobject::size_type BufSize=512) :                 //[t57]
00509     super(&m_Buf),
00510     m_Buf(T, O, PGSTD::ios::in, BufSize) 
00511   { 
00512   }
00513 
00515 
00519   basic_ilostream(dbtransaction &T, 
00520                   oid O, 
00521                   largeobject::size_type BufSize=512) :                 //[t48]
00522     super(&m_Buf),
00523     m_Buf(T, O, PGSTD::ios::in, BufSize) 
00524   { 
00525   }
00526 
00527 private:
00528   largeobject_streambuf<CHAR,TRAITS> m_Buf;
00529 };
00530 
00531 typedef basic_ilostream<char> ilostream;
00532 
00533 
00535 
00543 template<typename CHAR=char, typename TRAITS=PGSTD::char_traits<CHAR> > 
00544   class basic_olostream : 
00545 #ifdef PQXX_HAVE_STREAMBUF
00546     public PGSTD::basic_ostream<CHAR, TRAITS>
00547 #else
00548     public PGSTD::ostream
00549 #endif
00550 {
00551 #ifdef PQXX_HAVE_STREAMBUF
00552   typedef PGSTD::basic_ostream<CHAR, TRAITS> super;
00553 #else
00554   typedef PGSTD::ostream super;
00555 #endif
00556 public:
00557   typedef CHAR char_type;
00558   typedef TRAITS traits_type;
00559   typedef typename traits_type::int_type int_type;
00560   typedef typename traits_type::pos_type pos_type;
00561   typedef typename traits_type::off_type off_type;
00562 
00564 
00568   basic_olostream(dbtransaction &T, 
00569                   largeobject O,
00570                   largeobject::size_type BufSize=512) :                 //[t48]
00571     super(&m_Buf),
00572     m_Buf(T, O, PGSTD::ios::out, BufSize) 
00573   { 
00574   }
00575 
00577 
00581   basic_olostream(dbtransaction &T, 
00582                   oid O,
00583                   largeobject::size_type BufSize=512) :                 //[t57]
00584     super(&m_Buf),
00585     m_Buf(T, O, PGSTD::ios::out, BufSize) 
00586   { 
00587   }
00588 
00589   ~basic_olostream() 
00590   { 
00591     try
00592     {
00593 #ifdef PQXX_HAVE_STREAMBUF
00594       m_Buf.pubsync(); m_Buf.pubsync(); 
00595 #else
00596       m_Buf.sync(); m_Buf.sync();
00597 #endif
00598     }
00599     catch (const PGSTD::exception &e)
00600     {
00601       m_Buf.process_notice(e.what());
00602     }
00603   }
00604 
00605 private:
00606   largeobject_streambuf<CHAR,TRAITS> m_Buf;
00607 };
00608 
00609 typedef basic_olostream<char> olostream;
00610 
00611 
00613 
00621 template<typename CHAR=char, typename TRAITS=PGSTD::char_traits<CHAR> > 
00622   class basic_lostream :
00623 #ifdef PQXX_HAVE_STREAMBUF
00624     public PGSTD::basic_iostream<CHAR, TRAITS>
00625 #else
00626     public PGSTD::iostream
00627 #endif
00628 {
00629 #ifdef PQXX_HAVE_STREAMBUF
00630   typedef PGSTD::basic_iostream<CHAR, TRAITS> super;
00631 #else
00632   typedef PGSTD::iostream super;
00633 #endif
00634 
00635 public:
00636   typedef CHAR char_type;
00637   typedef TRAITS traits_type;
00638   typedef typename traits_type::int_type int_type;
00639   typedef typename traits_type::pos_type pos_type;
00640   typedef typename traits_type::off_type off_type;
00641 
00643 
00647   basic_lostream(dbtransaction &T, 
00648                  largeobject O,
00649                  largeobject::size_type BufSize=512) :                  //[t59]
00650     super(&m_Buf),
00651     m_Buf(T, O, PGSTD::ios::in | PGSTD::ios::out, BufSize) 
00652   { 
00653   }
00654 
00656 
00660   basic_lostream(dbtransaction &T, 
00661                  oid O,
00662                  largeobject::size_type BufSize=512) :                  //[t59]
00663     super(&m_Buf),
00664     m_Buf(T, O, PGSTD::ios::in | PGSTD::ios::out, BufSize) 
00665   { 
00666   }
00667 
00668   ~basic_lostream() 
00669   {
00670     try
00671     {
00672 #ifdef PQXX_HAVE_STREAMBUF
00673       m_Buf.pubsync(); m_Buf.pubsync(); 
00674 #else
00675       m_Buf.sync(); m_Buf.sync();
00676 #endif
00677     }
00678     catch (const PGSTD::exception &e)
00679     {
00680       m_Buf.process_notice(e.what());
00681     }
00682   }
00683 
00684 private:
00685   largeobject_streambuf<CHAR,TRAITS> m_Buf;
00686 };
00687 
00688 typedef basic_lostream<char> lostream;
00689 
00690 }
00691 
00692 

Generated on Mon May 10 13:19:09 2004 for libpqxx by doxygen 1.3.6-20040222