Main Page | 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 
00085 
00086   bool operator==(const largeobject &other) const                       //[t51]
00087           { return m_ID == other.m_ID; }
00089 
00090   bool operator!=(const largeobject &other) const                       //[t51]
00091           { return m_ID != other.m_ID; }
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; }
00108 
00110 
00114   void to_file(dbtransaction &T, const PGSTD::string &File) const;      //[t52]
00115 
00117 
00121   void remove(dbtransaction &T) const;                                  //[t48]
00122 
00123 protected:
00124   static internal::pq::PGconn *RawConnection(const dbtransaction &T)
00125   {
00126     return T.conn().RawConnection();
00127   }
00128 
00129   PGSTD::string Reason(int err) const;
00130 
00131 private:
00132   oid m_ID;
00133 };
00134 
00135 
00136 // TODO: New hierarchy with separate read / write / mixed-mode access
00137 
00139 class PQXX_LIBEXPORT largeobjectaccess : private largeobject
00140 {
00141 public:
00142   using largeobject::size_type;
00143   typedef long off_type;
00144   typedef size_type pos_type;
00145 
00147 
00151   typedef PGSTD::ios::openmode openmode;
00152 
00154 
00158   typedef PGSTD::ios::seekdir seekdir;
00159 
00161 
00165   explicit largeobjectaccess(dbtransaction &T,
00166                              openmode mode =
00167                                 PGSTD::ios::in |
00168                                 PGSTD::ios::out);                       //[t51]
00169 
00171 
00177   largeobjectaccess(dbtransaction &T,
00178                     oid O,
00179                     openmode mode =
00180                         PGSTD::ios::in |
00181                         PGSTD::ios::out);                               //[t52]
00182 
00184 
00189   largeobjectaccess(dbtransaction &T,
00190                     largeobject O,
00191                     openmode mode = PGSTD::ios::in | PGSTD::ios::out);  //[t50]
00192 
00194 
00199   largeobjectaccess(dbtransaction &T,
00200                     const PGSTD::string &File,
00201                     openmode mode =
00202                         PGSTD::ios::in | PGSTD::ios::out);              //[t55]
00203 
00204   ~largeobjectaccess() throw () { close(); }
00205 
00207 
00210   using largeobject::id;
00211 
00213 
00216   void to_file(const PGSTD::string &File) const                         //[t54]
00217         { largeobject::to_file(m_Trans, File); }
00218 
00219 #ifdef PQXX_BROKEN_USING_DECL
00220 
00221 
00225   void to_file(dbtransaction &T, const PGSTD::string &F) const
00226         { largeobject::to_file(T, F); }
00227 #else
00228   using largeobject::to_file;
00229 #endif
00230 
00231 
00233 
00237   void write(const char Buf[], size_type Len);                          //[t51]
00238 
00240 
00243   void write(const PGSTD::string &Buf)                                  //[t50]
00244         { write(Buf.c_str(), Buf.size()); }
00245 
00247 
00253   size_type read(char Buf[], size_type Len);                            //[t50]
00254 
00256 
00259   size_type seek(size_type dest, seekdir dir);                          //[t51]
00260 
00262 
00270   pos_type cseek(off_type dest, seekdir dir) throw ();                  //[t50]
00271 
00273 
00279   off_type cwrite(const char Buf[], size_type Len) throw ();            //[t50]
00280 
00282 
00288   off_type cread(char Buf[], size_type Len) throw ();                   //[t50]
00289 
00290 
00292   void process_notice(const PGSTD::string &) throw ();                  //[t50]
00293 
00294   using largeobject::remove;
00295 
00296   using largeobject::operator==;
00297   using largeobject::operator!=;
00298   using largeobject::operator<;
00299   using largeobject::operator<=;
00300   using largeobject::operator>;
00301   using largeobject::operator>=;
00302 
00303 private:
00304   PGSTD::string PQXX_PRIVATE Reason(int err) const;
00305   internal::pq::PGconn *RawConnection()
00306         { return largeobject::RawConnection(m_Trans); }
00307 
00308   void open(openmode mode);
00309   void close() throw ();
00310 
00311   dbtransaction &m_Trans;
00312   int m_fd;
00313 
00314   // Not allowed:
00315   largeobjectaccess();
00316   largeobjectaccess(const largeobjectaccess &);
00317   largeobjectaccess operator=(const largeobjectaccess &);
00318 };
00319 
00320 
00322 
00330 template<typename CHAR=char, typename TRAITS=PGSTD::char_traits<CHAR> >
00331   class largeobject_streambuf :
00332 #ifdef PQXX_HAVE_STREAMBUF
00333     public PGSTD::basic_streambuf<CHAR, TRAITS>
00334 #else
00335     public PGSTD::streambuf
00336 #endif
00337 {
00338   typedef long size_type;
00339 public:
00340   typedef CHAR   char_type;
00341   typedef TRAITS traits_type;
00342   typedef typename traits_type::int_type int_type;
00343 #ifdef PQXX_HAVE_STREAMBUF
00344   typedef typename traits_type::pos_type pos_type;
00345   typedef typename traits_type::off_type off_type;
00346 #else
00347   typedef streamoff off_type;
00348   typedef streampos pos_type;
00349 #endif
00350   typedef largeobjectaccess::openmode openmode;
00351   typedef largeobjectaccess::seekdir seekdir;
00352 
00353   largeobject_streambuf(dbtransaction &T,
00354                         largeobject O,
00355                         openmode mode = PGSTD::ios::in | PGSTD::ios::out,
00356                         size_type BufSize=512) :                        //[t48]
00357     m_BufSize(BufSize),
00358     m_Obj(T, O),
00359     m_G(0),
00360     m_P(0)
00361         { initialize(mode); }
00362 
00363   largeobject_streambuf(dbtransaction &T,
00364                         oid O,
00365                         openmode mode = PGSTD::ios::in | PGSTD::ios::out,
00366                         size_type BufSize=512) :                        //[t48]
00367     m_BufSize(BufSize),
00368     m_Obj(T, O),
00369     m_G(0),
00370     m_P(0)
00371         { initialize(mode); }
00372 
00373   virtual ~largeobject_streambuf() throw () { delete [] m_P; delete [] m_G; }
00374 
00375 
00377   void process_notice(const PGSTD::string &s) { m_Obj.process_notice(s); }
00378 
00379 #ifdef PQXX_HAVE_STREAMBUF
00380 protected:
00381 #endif
00382   virtual int sync()
00383   {
00384     // setg() sets eback, gptr, egptr
00385     setg(this->eback(), this->eback(), this->egptr());
00386     return overflow(EoF());
00387   }
00388 
00389 protected:
00390   virtual pos_type seekoff(off_type offset,
00391                            seekdir dir,
00392                            openmode)
00393         { return AdjustEOF(m_Obj.cseek(offset, dir)); }
00394 
00395   virtual pos_type seekpos(pos_type pos, openmode)
00396         { return AdjustEOF(m_Obj.cseek(pos, PGSTD::ios::beg)); }
00397 
00398   virtual int_type overflow(int_type ch = EoF())
00399   {
00400     char *const pp = this->pptr();
00401     if (!pp) return EoF();
00402     char *const pb = this->pbase();
00403     int_type res = 0;
00404 
00405     if (pp > pb) res = AdjustEOF(m_Obj.cwrite(pb, pp-pb));
00406     setp(m_P, m_P + m_BufSize);
00407 
00408     // Write that one more character, if it's there.
00409     if (ch != EoF())
00410     {
00411       *this->pptr() = char(ch);
00412       this->pbump(1);
00413     }
00414     return res;
00415   }
00416 
00417   virtual int_type underflow()
00418   {
00419     if (!this->gptr()) return EoF();
00420     char *const eb = this->eback();
00421     const int res = AdjustEOF(m_Obj.cread(this->eback(), m_BufSize));
00422     setg(eb, eb, eb + ((res==EoF()) ? 0 : res));
00423     return (!res || (res == EoF())) ? EoF() : *eb;
00424   }
00425 
00426 private:
00428   static int_type EoF() { return traits_type::eof(); }
00429 
00431   static PGSTD::streampos AdjustEOF(int pos) { return (pos==-1) ? EoF() : pos; }
00432 
00433   void initialize(openmode mode)
00434   {
00435     if (mode & PGSTD::ios::in)
00436     {
00437       m_G = new char_type[m_BufSize];
00438       setg(m_G, m_G, m_G);
00439     }
00440     if (mode & PGSTD::ios::out)
00441     {
00442       m_P = new char_type[m_BufSize];
00443       setp(m_P, m_P + m_BufSize);
00444     }
00445   }
00446 
00447   const size_type m_BufSize;
00448   largeobjectaccess m_Obj;
00449 
00450   // Get & put buffers
00451   char_type *m_G, *m_P;
00452 };
00453 
00454 
00456 
00464 template<typename CHAR=char, typename TRAITS=PGSTD::char_traits<CHAR> >
00465   class basic_ilostream :
00466 #ifdef PQXX_HAVE_STREAMBUF
00467     public PGSTD::basic_istream<CHAR, TRAITS>
00468 #else
00469     public PGSTD::istream
00470 #endif
00471 {
00472 #ifdef PQXX_HAVE_STREAMBUF
00473   typedef PGSTD::basic_istream<CHAR, TRAITS> super;
00474 #else
00475   typedef PGSTD::istream super;
00476 #endif
00477 
00478 public:
00479   typedef CHAR char_type;
00480   typedef TRAITS traits_type;
00481   typedef typename traits_type::int_type int_type;
00482   typedef typename traits_type::pos_type pos_type;
00483   typedef typename traits_type::off_type off_type;
00484 
00486 
00491   basic_ilostream(dbtransaction &T,
00492                   largeobject O,
00493                   largeobject::size_type BufSize=512) :                 //[t57]
00494     super(0),
00495     m_Buf(T, O, PGSTD::ios::in, BufSize)
00496         { super::init(&m_Buf); }
00497 
00499 
00504   basic_ilostream(dbtransaction &T,
00505                   oid O,
00506                   largeobject::size_type BufSize=512) :                 //[t48]
00507     super(0),
00508     m_Buf(T, O, PGSTD::ios::in, BufSize)
00509         { super::init(&m_Buf); }
00510 
00511 private:
00512   largeobject_streambuf<CHAR,TRAITS> m_Buf;
00513 };
00514 
00515 typedef basic_ilostream<char> ilostream;
00516 
00517 
00519 
00527 template<typename CHAR=char, typename TRAITS=PGSTD::char_traits<CHAR> >
00528   class basic_olostream :
00529 #ifdef PQXX_HAVE_STREAMBUF
00530     public PGSTD::basic_ostream<CHAR, TRAITS>
00531 #else
00532     public PGSTD::ostream
00533 #endif
00534 {
00535 #ifdef PQXX_HAVE_STREAMBUF
00536   typedef PGSTD::basic_ostream<CHAR, TRAITS> super;
00537 #else
00538   typedef PGSTD::ostream super;
00539 #endif
00540 public:
00541   typedef CHAR char_type;
00542   typedef TRAITS traits_type;
00543   typedef typename traits_type::int_type int_type;
00544   typedef typename traits_type::pos_type pos_type;
00545   typedef typename traits_type::off_type off_type;
00546 
00548 
00553   basic_olostream(dbtransaction &T,
00554                   largeobject O,
00555                   largeobject::size_type BufSize=512) :                 //[t48]
00556     super(0),
00557     m_Buf(T, O, PGSTD::ios::out, BufSize)
00558         { super::init(&m_Buf); }
00559 
00561 
00566   basic_olostream(dbtransaction &T,
00567                   oid O,
00568                   largeobject::size_type BufSize=512) :                 //[t57]
00569     super(0),
00570     m_Buf(T, O, PGSTD::ios::out, BufSize)
00571         { super::init(&m_Buf); }
00572 
00573   ~basic_olostream()
00574   {
00575     try
00576     {
00577 #ifdef PQXX_HAVE_STREAMBUF
00578       m_Buf.pubsync(); m_Buf.pubsync();
00579 #else
00580       m_Buf.sync(); m_Buf.sync();
00581 #endif
00582     }
00583     catch (const PGSTD::exception &e)
00584     {
00585       m_Buf.process_notice(e.what());
00586     }
00587   }
00588 
00589 private:
00590   largeobject_streambuf<CHAR,TRAITS> m_Buf;
00591 };
00592 
00593 typedef basic_olostream<char> olostream;
00594 
00595 
00597 
00605 template<typename CHAR=char, typename TRAITS=PGSTD::char_traits<CHAR> >
00606   class basic_lostream :
00607 #ifdef PQXX_HAVE_STREAMBUF
00608     public PGSTD::basic_iostream<CHAR, TRAITS>
00609 #else
00610     public PGSTD::iostream
00611 #endif
00612 {
00613 #ifdef PQXX_HAVE_STREAMBUF
00614   typedef PGSTD::basic_iostream<CHAR, TRAITS> super;
00615 #else
00616   typedef PGSTD::iostream super;
00617 #endif
00618 
00619 public:
00620   typedef CHAR char_type;
00621   typedef TRAITS traits_type;
00622   typedef typename traits_type::int_type int_type;
00623   typedef typename traits_type::pos_type pos_type;
00624   typedef typename traits_type::off_type off_type;
00625 
00627 
00632   basic_lostream(dbtransaction &T,
00633                  largeobject O,
00634                  largeobject::size_type BufSize=512) :                  //[t59]
00635     super(0),
00636     m_Buf(T, O, PGSTD::ios::in | PGSTD::ios::out, BufSize)
00637         { super::init(&m_Buf); }
00638 
00640 
00645   basic_lostream(dbtransaction &T,
00646                  oid O,
00647                  largeobject::size_type BufSize=512) :                  //[t59]
00648     super(0),
00649     m_Buf(T, O, PGSTD::ios::in | PGSTD::ios::out, BufSize)
00650         { super::init(&m_Buf); }
00651 
00652   ~basic_lostream()
00653   {
00654     try
00655     {
00656 #ifdef PQXX_HAVE_STREAMBUF
00657       m_Buf.pubsync(); m_Buf.pubsync();
00658 #else
00659       m_Buf.sync(); m_Buf.sync();
00660 #endif
00661     }
00662     catch (const PGSTD::exception &e)
00663     {
00664       m_Buf.process_notice(e.what());
00665     }
00666   }
00667 
00668 private:
00669   largeobject_streambuf<CHAR,TRAITS> m_Buf;
00670 };
00671 
00672 typedef basic_lostream<char> lostream;
00673 
00674 }
00675 
00676 

Generated on Fri Jul 1 14:36:19 2005 for libpqxx by  doxygen 1.4.2