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 #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();                                                        //[t48]
00052 
00054 
00056   explicit largeobject(dbtransaction &T);                               //[t48]
00057 
00059 
00063   explicit largeobject(oid O) : m_ID(O) {}                              //[t48]
00064 
00066 
00070   largeobject(dbtransaction &T, const PGSTD::string &File);             //[t53]
00071 
00073 
00077   largeobject(const largeobjectaccess &O);                              //[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() { 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   using largeobject::remove;
00289 
00290   using largeobject::operator==;
00291   using largeobject::operator!=;
00292   using largeobject::operator<;
00293   using largeobject::operator<=;
00294   using largeobject::operator>;
00295   using largeobject::operator>=;
00296 
00297 private:
00298   PGSTD::string Reason() const;
00299   PGconn *RawConnection() { return largeobject::RawConnection(m_Trans); }
00300 
00301   void open(openmode mode);
00302   void close();
00303 
00304   dbtransaction &m_Trans;
00305   int m_fd;
00306 
00307   // Not allowed:
00308   largeobjectaccess();
00309   largeobjectaccess(const largeobjectaccess &);
00310   largeobjectaccess operator=(const largeobjectaccess &);
00311 };
00312 
00313 
00315 
00323 template<typename CHAR=char, typename TRAITS=PGSTD::char_traits<CHAR> >
00324   class largeobject_streambuf :
00325 #ifdef PQXX_HAVE_STREAMBUF
00326     public PGSTD::basic_streambuf<CHAR, TRAITS>
00327 #else
00328     public PGSTD::streambuf
00329 #endif
00330 {
00331   typedef long size_type;
00332 public:
00333   typedef CHAR   char_type;
00334   typedef TRAITS traits_type;
00335   typedef typename traits_type::int_type int_type;
00336 #ifdef PQXX_HAVE_STREAMBUF
00337   typedef typename traits_type::pos_type pos_type;
00338   typedef typename traits_type::off_type off_type;
00339 #else
00340   typedef streamoff off_type;
00341   typedef streampos pos_type;
00342 #endif
00343   typedef largeobjectaccess::openmode openmode;
00344   typedef largeobjectaccess::seekdir seekdir;
00345 
00346   largeobject_streambuf(dbtransaction &T,
00347                         largeobject O,
00348                         openmode mode = in | out,
00349                         size_type BufSize=512) :                        //[t48]
00350     m_BufSize(BufSize),
00351     m_Obj(T, O),
00352     m_G(0),
00353     m_P(0)
00354   {
00355     initialize(mode);
00356   }
00357 
00358   largeobject_streambuf(dbtransaction &T,
00359                         oid O,
00360                         openmode mode = in | out,
00361                         size_type BufSize=512) :                        //[t48]
00362     m_BufSize(BufSize),
00363     m_Obj(T, O),
00364     m_G(0),
00365     m_P(0)
00366   {
00367     initialize(mode);
00368   }
00369 
00370   virtual ~largeobject_streambuf()
00371   {
00372     delete [] m_P;
00373     delete [] m_G;
00374   }
00375 
00376 
00377 #ifdef PQXX_HAVE_STREAMBUF
00378 protected:
00379 #endif
00380   virtual int sync()
00381   {
00382     // setg() sets eback, gptr, egptr
00383     setg(eback(), eback(), egptr());
00384     return overflow(EoF());
00385   }
00386 
00387 protected:
00388   virtual pos_type seekoff(off_type offset, 
00389                            seekdir dir,
00390                            openmode mode = in|out)
00391   {
00392     if (!mode) {}       // Quench "unused parameter" warning
00393     return AdjustEOF(m_Obj.cseek(offset, dir));
00394   }
00395 
00396   virtual pos_type seekpos(pos_type pos, 
00397                            openmode mode = in|out)
00398   {
00399     if (!mode) {}       // Quench "unused parameter" warning
00400     return AdjustEOF(m_Obj.cseek(pos, PGSTD::ios::beg));
00401   }
00402 
00403   virtual int_type overflow(int_type ch = EoF())
00404   {
00405     char *const pp = pptr();
00406     if (!pp) return EoF();
00407     char *const pb = pbase();
00408     int_type res = 0;
00409 
00410     if (pp > pb) res = AdjustEOF(m_Obj.cwrite(pb, pp-pb));
00411     setp(m_P, m_P + m_BufSize);
00412 
00413     // Write that one more character, if it's there.
00414     if (ch != EoF())
00415     {
00416       *pptr() = char(ch);
00417       pbump(1);
00418     }
00419     return res;
00420   }
00421 
00422   virtual int_type underflow()
00423   {
00424     if (!gptr()) return EoF();
00425     char *const eb = eback();
00426     const int res = AdjustEOF(m_Obj.cread(eback(), m_BufSize));
00427     setg(eb, eb, eb + ((res==EoF()) ? 0 : res));
00428     return (!res || (res == EoF())) ? EoF() : *eb;
00429   }
00430 
00431 private:
00433   static int_type EoF() { return traits_type::eof(); }
00434 
00436   static PGSTD::streampos AdjustEOF(int pos)
00437   {
00438     return (pos == -1) ? EoF() : pos;
00439   }
00440 
00441   void initialize(openmode mode)
00442   {
00443     if (mode & PGSTD::ios::in) 
00444     {
00445       m_G = new char_type[m_BufSize];
00446       setg(m_G, m_G, m_G);
00447     }
00448     if (mode & PGSTD::ios::out)
00449     {
00450       m_P = new char_type[m_BufSize];
00451       setp(m_P, m_P + m_BufSize);
00452     }
00453   }
00454 
00455   const size_type m_BufSize;
00456   largeobjectaccess m_Obj;
00457 
00458   // Get & put buffers
00459   char_type *m_G, *m_P;
00460 };
00461 
00462 
00464 
00472 template<typename CHAR=char, typename TRAITS=PGSTD::char_traits<CHAR> > 
00473   class basic_ilostream :
00474 #ifdef PQXX_HAVE_STREAMBUF
00475     public PGSTD::basic_istream<CHAR, TRAITS>
00476 #else
00477     public PGSTD::istream
00478 #endif
00479 {
00480 #ifdef PQXX_HAVE_STREAMBUF
00481   typedef PGSTD::basic_istream<CHAR, TRAITS> super;
00482 #else
00483   typedef PGSTD::istream super;
00484 #endif
00485 
00486 public:
00487   typedef CHAR char_type;
00488   typedef TRAITS traits_type;
00489   typedef typename traits_type::int_type int_type;
00490   typedef typename traits_type::pos_type pos_type;
00491   typedef typename traits_type::off_type off_type;
00492 
00494 
00498   basic_ilostream(dbtransaction &T, 
00499                   largeobject O, 
00500                   largeobject::size_type BufSize=512) :                 //[t57]
00501     super(&m_Buf),
00502     m_Buf(T, O, in, BufSize) 
00503   { 
00504   }
00505 
00507 
00511   basic_ilostream(dbtransaction &T, 
00512                   oid O, 
00513                   largeobject::size_type BufSize=512) :                 //[t48]
00514     super(&m_Buf),
00515     m_Buf(T, O, in, BufSize) 
00516   { 
00517   }
00518 
00519 private:
00520   largeobject_streambuf<CHAR,TRAITS> m_Buf;
00521 };
00522 
00523 typedef basic_ilostream<char> ilostream;
00524 
00525 
00527 
00535 template<typename CHAR=char, typename TRAITS=PGSTD::char_traits<CHAR> > 
00536   class basic_olostream : 
00537 #ifdef PQXX_HAVE_STREAMBUF
00538     public PGSTD::basic_ostream<CHAR, TRAITS>
00539 #else
00540     public PGSTD::ostream
00541 #endif
00542 {
00543 #ifdef PQXX_HAVE_STREAMBUF
00544   typedef PGSTD::basic_ostream<CHAR, TRAITS> super;
00545 #else
00546   typedef PGSTD::ostream super;
00547 #endif
00548 public:
00549   typedef CHAR char_type;
00550   typedef TRAITS traits_type;
00551   typedef typename traits_type::int_type int_type;
00552   typedef typename traits_type::pos_type pos_type;
00553   typedef typename traits_type::off_type off_type;
00554 
00556 
00560   basic_olostream(dbtransaction &T, 
00561                   largeobject O,
00562                   largeobject::size_type BufSize=512) :                 //[t48]
00563     super(&m_Buf),
00564     m_Buf(T, O, out, BufSize) 
00565   { 
00566   }
00567 
00569 
00573   basic_olostream(dbtransaction &T, 
00574                   oid O,
00575                   largeobject::size_type BufSize=512) :                 //[t57]
00576     super(&m_Buf),
00577     m_Buf(T, O, out, BufSize) 
00578   { 
00579   }
00580 
00581   ~basic_olostream() 
00582   { 
00583 #ifdef PQXX_HAVE_STREAMBUF
00584     m_Buf.pubsync(); m_Buf.pubsync(); 
00585 #else
00586     m_Buf.sync(); m_Buf.sync();
00587 #endif
00588   }
00589 
00590 private:
00591   largeobject_streambuf<CHAR,TRAITS> m_Buf;
00592 };
00593 
00594 typedef basic_olostream<char> olostream;
00595 
00596 
00598 
00606 template<typename CHAR=char, typename TRAITS=PGSTD::char_traits<CHAR> > 
00607   class basic_lostream :
00608 #ifdef PQXX_HAVE_STREAMBUF
00609     public PGSTD::basic_iostream<CHAR, TRAITS>
00610 #else
00611     public PGSTD::iostream
00612 #endif
00613 {
00614 #ifdef PQXX_HAVE_STREAMBUF
00615   typedef PGSTD::basic_iostream<CHAR, TRAITS> super;
00616 #else
00617   typedef PGSTD::iostream super;
00618 #endif
00619 
00620 public:
00621   typedef CHAR char_type;
00622   typedef TRAITS traits_type;
00623   typedef typename traits_type::int_type int_type;
00624   typedef typename traits_type::pos_type pos_type;
00625   typedef typename traits_type::off_type off_type;
00626 
00628 
00632   basic_lostream(dbtransaction &T, 
00633                  largeobject O,
00634                  largeobject::size_type BufSize=512) :                  //[t59]
00635     super(&m_Buf),
00636     m_Buf(T, O, in | out, BufSize) 
00637   { 
00638   }
00639 
00641 
00645   basic_lostream(dbtransaction &T, 
00646                  oid O,
00647                  largeobject::size_type BufSize=512) :                  //[t59]
00648     super(&m_Buf),
00649     m_Buf(T, O, in | out, BufSize) 
00650   { 
00651   }
00652 
00653   ~basic_lostream() 
00654   { 
00655 #ifdef PQXX_HAVE_STREAMBUF
00656     m_Buf.pubsync(); m_Buf.pubsync(); 
00657 #else
00658     m_Buf.sync(); m_Buf.sync();
00659 #endif
00660   }
00661 
00662 private:
00663   largeobject_streambuf<CHAR,TRAITS> m_Buf;
00664 };
00665 
00666 typedef basic_lostream<char> lostream;
00667 
00668 }
00669 
00670 

Generated on Thu Dec 25 07:22:37 2003 for libpqxx by doxygen 1.3.4