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, 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();                                                        //[t48]
00050 
00052 
00054   explicit largeobject(dbtransaction &T);                               //[t48]
00055 
00057 
00061   explicit largeobject(oid O) : m_ID(O) {}                              //[t48]
00062 
00064 
00068   largeobject(dbtransaction &T, const PGSTD::string &File);             //[t53]
00069 
00071 
00075   largeobject(const largeobjectaccess &O);                              //[t50]
00076 
00078 
00082   oid id() const throw () { return m_ID; }                              //[t48]
00083 
00085   bool operator==(const largeobject &other) const                       //[t51]
00086           { return m_ID == other.m_ID; }
00088   bool operator!=(const largeobject &other) const                       //[t51]
00089           { return m_ID != other.m_ID; }
00091   bool operator<=(const largeobject &other) const                       //[t51]
00092           { return m_ID <= other.m_ID; }
00094   bool operator>=(const largeobject &other) const                       //[t51]
00095           { return m_ID >= other.m_ID; }
00097   bool operator<(const largeobject &other) const                        //[t51]
00098           { return m_ID < other.m_ID; }
00100   bool operator>(const largeobject &other) const                        //[t51]
00101           { return m_ID > other.m_ID; }
00102 
00104 
00108   void to_file(dbtransaction &T, const PGSTD::string &File) const;      //[t52]
00109 
00111 
00115   void remove(dbtransaction &T) const;                                  //[t48]
00116 
00117 protected:
00118   static PGconn *RawConnection(const dbtransaction &T)
00119   {
00120     return T.conn().RawConnection();
00121   }
00122 
00123   PGSTD::string Reason() const;
00124 
00125 private:
00126   oid m_ID;
00127 };
00128 
00129 
00130 // TODO: New hierarchy with separate read / write / mixed-mode access
00131 
00133 class PQXX_LIBEXPORT largeobjectaccess : private largeobject
00134 {
00135 public:
00136   using largeobject::size_type;
00137   typedef long off_type;
00138   typedef size_type pos_type;
00139 
00141 
00145   typedef PGSTD::ios::openmode openmode;
00146 
00148 
00152   typedef PGSTD::ios::seekdir seekdir;
00153 
00155 
00159   explicit largeobjectaccess(dbtransaction &T, 
00160                              openmode mode = 
00161                                 PGSTD::ios::in | 
00162                                 PGSTD::ios::out);                       //[t51]
00163 
00165 
00171   largeobjectaccess(dbtransaction &T, 
00172                     oid O,
00173                     openmode mode = 
00174                         PGSTD::ios::in | 
00175                         PGSTD::ios::out);                               //[t52]
00176 
00178 
00183   largeobjectaccess(dbtransaction &T, 
00184                     largeobject O,
00185                     openmode mode = PGSTD::ios::in | PGSTD::ios::out);  //[t50]
00186 
00188 
00193   largeobjectaccess(dbtransaction &T, 
00194                     const PGSTD::string &File,
00195                     openmode mode = 
00196                         PGSTD::ios::in | PGSTD::ios::out);              //[t55]
00197 
00198   ~largeobjectaccess() { close(); }
00199 
00201 
00204   using largeobject::id;
00205 
00207 
00210   void to_file(const PGSTD::string &File) const                         //[t54]
00211   { 
00212     largeobject::to_file(m_Trans, File); 
00213   }
00214 
00215 #ifdef PQXX_BROKEN_USING_DECL
00216 
00217 
00221   void to_file(dbtransaction &T, const PGSTD::string &F) const
00222         { largeobject::to_file(T, F); }
00223 #else
00224   using largeobject::to_file;
00225 #endif
00226 
00227 
00229 
00233   void write(const char Buf[], size_type Len);                          //[t51]
00234 
00236 
00239   void write(const PGSTD::string &Buf)                                  //[t50]
00240         { write(Buf.c_str(), Buf.size()); }
00241 
00243 
00249   size_type read(char Buf[], size_type Len);                            //[t50]
00250 
00252 
00255   size_type seek(size_type dest, seekdir dir);                          //[t51]
00256 
00258 
00266   pos_type cseek(off_type dest, seekdir dir) throw ();                  //[t50]
00267     
00269 
00275   off_type cwrite(const char Buf[], size_type Len) throw ();            //[t50]
00276 
00278 
00284   off_type cread(char Buf[], size_type Len) throw ();                   //[t50]
00285 
00286   using largeobject::remove;
00287 
00288   using largeobject::operator==;
00289   using largeobject::operator!=;
00290   using largeobject::operator<;
00291   using largeobject::operator<=;
00292   using largeobject::operator>;
00293   using largeobject::operator>=;
00294 
00295 private:
00296   PGSTD::string Reason() const;
00297   PGconn *RawConnection() { return largeobject::RawConnection(m_Trans); }
00298 
00299   void open(openmode mode);
00300   void close();
00301 
00302   dbtransaction &m_Trans;
00303   int m_fd;
00304 
00305   // Not allowed:
00306   largeobjectaccess();
00307   largeobjectaccess(const largeobjectaccess &);
00308   largeobjectaccess operator=(const largeobjectaccess &);
00309 };
00310 
00311 
00313 
00321 template<typename CHAR=char, typename TRAITS=PGSTD::char_traits<CHAR> >
00322   class largeobject_streambuf :
00323 #ifdef PQXX_HAVE_STREAMBUF
00324     public PGSTD::basic_streambuf<CHAR, TRAITS>
00325 #else
00326     public PGSTD::streambuf
00327 #endif
00328 {
00329   typedef long size_type;
00330 public:
00331   typedef CHAR   char_type;
00332   typedef TRAITS traits_type;
00333   typedef typename traits_type::int_type int_type;
00334 #ifdef PQXX_HAVE_STREAMBUF
00335   typedef typename traits_type::pos_type pos_type;
00336   typedef typename traits_type::off_type off_type;
00337 #else
00338   typedef streamoff off_type;
00339   typedef streampos pos_type;
00340 #endif
00341   typedef largeobjectaccess::openmode openmode;
00342   typedef largeobjectaccess::seekdir seekdir;
00343 
00344   largeobject_streambuf(dbtransaction &T,
00345                         largeobject O,
00346                         openmode mode = in | out,
00347                         size_type BufSize=512) :                        //[t48]
00348     m_BufSize(BufSize),
00349     m_Obj(T, O),
00350     m_G(0),
00351     m_P(0)
00352   {
00353     initialize(mode);
00354   }
00355 
00356   largeobject_streambuf(dbtransaction &T,
00357                         oid O,
00358                         openmode mode = in | out,
00359                         size_type BufSize=512) :                        //[t48]
00360     m_BufSize(BufSize),
00361     m_Obj(T, O),
00362     m_G(0),
00363     m_P(0)
00364   {
00365     initialize(mode);
00366   }
00367 
00368   virtual ~largeobject_streambuf()
00369   {
00370     delete [] m_P;
00371     delete [] m_G;
00372   }
00373 
00374 
00375 #ifdef PQXX_HAVE_STREAMBUF
00376 protected:
00377 #endif
00378   virtual int sync()
00379   {
00380     // setg() sets eback, gptr, egptr
00381     setg(eback(), eback(), egptr());
00382     return overflow(EoF());
00383   }
00384 
00385 protected:
00386   virtual pos_type seekoff(off_type offset, 
00387                            seekdir dir,
00388                            openmode mode = in|out)
00389   {
00390     if (!mode) {}       // Quench "unused parameter" warning
00391     return AdjustEOF(m_Obj.cseek(offset, dir));
00392   }
00393 
00394   virtual pos_type seekpos(pos_type pos, 
00395                            openmode mode = in|out)
00396   {
00397     if (!mode) {}       // Quench "unused parameter" warning
00398     return AdjustEOF(m_Obj.cseek(pos, PGSTD::ios::beg));
00399   }
00400 
00401   virtual int_type overflow(int_type ch = EoF())
00402   {
00403     char *const pp = pptr();
00404     if (!pp) return EoF();
00405     char *const pb = pbase();
00406     int_type res = 0;
00407 
00408     if (pp > pb) res = AdjustEOF(m_Obj.cwrite(pb, pp-pb));
00409     setp(m_P, m_P + m_BufSize);
00410 
00411     // Write that one more character, if it's there.
00412     if (ch != EoF())
00413     {
00414       *pptr() = char(ch);
00415       pbump(1);
00416     }
00417     return res;
00418   }
00419 
00420   virtual int_type underflow()
00421   {
00422     if (!gptr()) return EoF();
00423     char *const eb = eback();
00424     const int res = AdjustEOF(m_Obj.cread(eback(), m_BufSize));
00425     setg(eb, eb, eb + ((res==EoF()) ? 0 : res));
00426     return (!res || (res == EoF())) ? EoF() : *eb;
00427   }
00428 
00429 private:
00431   static int_type EoF() { return traits_type::eof(); }
00432 
00434   static PGSTD::streampos AdjustEOF(int pos)
00435   {
00436     return (pos == -1) ? EoF() : pos;
00437   }
00438 
00439   void initialize(openmode mode)
00440   {
00441     if (mode & PGSTD::ios::in) 
00442     {
00443       m_G = new char_type[m_BufSize];
00444       setg(m_G, m_G, m_G);
00445     }
00446     if (mode & PGSTD::ios::out)
00447     {
00448       m_P = new char_type[m_BufSize];
00449       setp(m_P, m_P + m_BufSize);
00450     }
00451   }
00452 
00453   const size_type m_BufSize;
00454   largeobjectaccess m_Obj;
00455 
00456   // Get & put buffers
00457   char_type *m_G, *m_P;
00458 };
00459 
00460 
00462 
00470 template<typename CHAR=char, typename TRAITS=PGSTD::char_traits<CHAR> > 
00471   class basic_ilostream :
00472 #ifdef PQXX_HAVE_STREAMBUF
00473     public PGSTD::basic_istream<CHAR, TRAITS>
00474 #else
00475     public PGSTD::istream
00476 #endif
00477 {
00478 #ifdef PQXX_HAVE_STREAMBUF
00479   typedef PGSTD::basic_istream<CHAR, TRAITS> super;
00480 #else
00481   typedef PGSTD::istream super;
00482 #endif
00483 
00484 public:
00485   typedef CHAR char_type;
00486   typedef TRAITS traits_type;
00487   typedef typename traits_type::int_type int_type;
00488   typedef typename traits_type::pos_type pos_type;
00489   typedef typename traits_type::off_type off_type;
00490 
00492 
00496   basic_ilostream(dbtransaction &T, 
00497                   largeobject O, 
00498                   largeobject::size_type BufSize=512) :                 //[t57]
00499     super(&m_Buf),
00500     m_Buf(T, O, in, BufSize) 
00501   { 
00502   }
00503 
00505 
00509   basic_ilostream(dbtransaction &T, 
00510                   oid O, 
00511                   largeobject::size_type BufSize=512) :                 //[t48]
00512     super(&m_Buf),
00513     m_Buf(T, O, in, BufSize) 
00514   { 
00515   }
00516 
00517 private:
00518   largeobject_streambuf<CHAR,TRAITS> m_Buf;
00519 };
00520 
00521 typedef basic_ilostream<char> ilostream;
00522 
00523 
00525 
00533 template<typename CHAR=char, typename TRAITS=PGSTD::char_traits<CHAR> > 
00534   class basic_olostream : 
00535 #ifdef PQXX_HAVE_STREAMBUF
00536     public PGSTD::basic_ostream<CHAR, TRAITS>
00537 #else
00538     public PGSTD::ostream
00539 #endif
00540 {
00541 #ifdef PQXX_HAVE_STREAMBUF
00542   typedef PGSTD::basic_ostream<CHAR, TRAITS> super;
00543 #else
00544   typedef PGSTD::ostream super;
00545 #endif
00546 public:
00547   typedef CHAR char_type;
00548   typedef TRAITS traits_type;
00549   typedef typename traits_type::int_type int_type;
00550   typedef typename traits_type::pos_type pos_type;
00551   typedef typename traits_type::off_type off_type;
00552 
00554 
00558   basic_olostream(dbtransaction &T, 
00559                   largeobject O,
00560                   largeobject::size_type BufSize=512) :                 //[t48]
00561     super(&m_Buf),
00562     m_Buf(T, O, out, BufSize) 
00563   { 
00564   }
00565 
00567 
00571   basic_olostream(dbtransaction &T, 
00572                   oid O,
00573                   largeobject::size_type BufSize=512) :                 //[t57]
00574     super(&m_Buf),
00575     m_Buf(T, O, out, BufSize) 
00576   { 
00577   }
00578 
00579   ~basic_olostream() 
00580   { 
00581 #ifdef PQXX_HAVE_STREAMBUF
00582     m_Buf.pubsync(); m_Buf.pubsync(); 
00583 #else
00584     m_Buf.sync(); m_Buf.sync();
00585 #endif
00586   }
00587 
00588 private:
00589   largeobject_streambuf<CHAR,TRAITS> m_Buf;
00590 };
00591 
00592 typedef basic_olostream<char> olostream;
00593 
00594 
00596 
00604 template<typename CHAR=char, typename TRAITS=PGSTD::char_traits<CHAR> > 
00605   class basic_lostream :
00606 #ifdef PQXX_HAVE_STREAMBUF
00607     public PGSTD::basic_iostream<CHAR, TRAITS>
00608 #else
00609     public PGSTD::iostream
00610 #endif
00611 {
00612 #ifdef PQXX_HAVE_STREAMBUF
00613   typedef PGSTD::basic_iostream<CHAR, TRAITS> super;
00614 #else
00615   typedef PGSTD::iostream super;
00616 #endif
00617 
00618 public:
00619   typedef CHAR char_type;
00620   typedef TRAITS traits_type;
00621   typedef typename traits_type::int_type int_type;
00622   typedef typename traits_type::pos_type pos_type;
00623   typedef typename traits_type::off_type off_type;
00624 
00626 
00630   basic_lostream(dbtransaction &T, 
00631                  largeobject O,
00632                  largeobject::size_type BufSize=512) :                  //[t59]
00633     super(&m_Buf),
00634     m_Buf(T, O, in | out, BufSize) 
00635   { 
00636   }
00637 
00639 
00643   basic_lostream(dbtransaction &T, 
00644                  oid O,
00645                  largeobject::size_type BufSize=512) :                  //[t59]
00646     super(&m_Buf),
00647     m_Buf(T, O, in | out, BufSize) 
00648   { 
00649   }
00650 
00651   ~basic_lostream() 
00652   { 
00653 #ifdef PQXX_HAVE_STREAMBUF
00654     m_Buf.pubsync(); m_Buf.pubsync(); 
00655 #else
00656     m_Buf.sync(); m_Buf.sync();
00657 #endif
00658   }
00659 
00660 private:
00661   largeobject_streambuf<CHAR,TRAITS> m_Buf;
00662 };
00663 
00664 typedef basic_lostream<char> lostream;
00665 
00666 }
00667 
00668 

Generated on Sat Nov 15 01:48:58 2003 for libpqxx by doxygen 1.3.4