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-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 internal::pq::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   internal::pq::PGconn *RawConnection()
00304         { return largeobject::RawConnection(m_Trans); }
00305 
00306   void open(openmode mode);
00307   void close() throw ();
00308 
00309   dbtransaction &m_Trans;
00310   int m_fd;
00311 
00312   // Not allowed:
00313   largeobjectaccess();
00314   largeobjectaccess(const largeobjectaccess &);
00315   largeobjectaccess operator=(const largeobjectaccess &);
00316 };
00317 
00318 
00320 
00328 template<typename CHAR=char, typename TRAITS=PGSTD::char_traits<CHAR> >
00329   class largeobject_streambuf :
00330 #ifdef PQXX_HAVE_STREAMBUF
00331     public PGSTD::basic_streambuf<CHAR, TRAITS>
00332 #else
00333     public PGSTD::streambuf
00334 #endif
00335 {
00336   typedef long size_type;
00337 public:
00338   typedef CHAR   char_type;
00339   typedef TRAITS traits_type;
00340   typedef typename traits_type::int_type int_type;
00341 #ifdef PQXX_HAVE_STREAMBUF
00342   typedef typename traits_type::pos_type pos_type;
00343   typedef typename traits_type::off_type off_type;
00344 #else
00345   typedef streamoff off_type;
00346   typedef streampos pos_type;
00347 #endif
00348   typedef largeobjectaccess::openmode openmode;
00349   typedef largeobjectaccess::seekdir seekdir;
00350 
00351   largeobject_streambuf(dbtransaction &T,
00352                         largeobject O,
00353                         openmode mode = PGSTD::ios::in | PGSTD::ios::out,
00354                         size_type BufSize=512) :                        //[t48]
00355     m_BufSize(BufSize),
00356     m_Obj(T, O),
00357     m_G(0),
00358     m_P(0)
00359   {
00360     initialize(mode);
00361   }
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   {
00372     initialize(mode);
00373   }
00374 
00375   virtual ~largeobject_streambuf() throw ()
00376   {
00377     delete [] m_P;
00378     delete [] m_G;
00379   }
00380 
00381 
00383   void process_notice(const PGSTD::string &s) { m_Obj.process_notice(s); }
00384 
00385 #ifdef PQXX_HAVE_STREAMBUF
00386 protected:
00387 #endif
00388   virtual int sync()
00389   {
00390     // setg() sets eback, gptr, egptr
00391     setg(this->eback(), this->eback(), this->egptr());
00392     return overflow(EoF());
00393   }
00394 
00395 protected:
00396   virtual pos_type seekoff(off_type offset, 
00397                            seekdir dir,
00398                            openmode mode)
00399   {
00400     if (mode != SEEK_CUR)
00401       throw PGSTD::logic_error("Offset "+to_string(int(mode))+" in seekoff()");
00402     return AdjustEOF(m_Obj.cseek(offset, dir));
00403   }
00404 
00405   virtual pos_type seekpos(pos_type pos, openmode mode)
00406   {
00407     if (mode != SEEK_SET)
00408       throw PGSTD::logic_error("Offset "+to_string(int(mode))+" in seekpos()");
00409     return AdjustEOF(m_Obj.cseek(pos, PGSTD::ios::beg));
00410   }
00411 
00412   virtual int_type overflow(int_type ch = EoF())
00413   {
00414     char *const pp = this->pptr();
00415     if (!pp) return EoF();
00416     char *const pb = this->pbase();
00417     int_type res = 0;
00418 
00419     if (pp > pb) res = AdjustEOF(m_Obj.cwrite(pb, pp-pb));
00420     setp(m_P, m_P + m_BufSize);
00421 
00422     // Write that one more character, if it's there.
00423     if (ch != EoF())
00424     {
00425       *this->pptr() = char(ch);
00426       this->pbump(1);
00427     }
00428     return res;
00429   }
00430 
00431   virtual int_type underflow()
00432   {
00433     if (!this->gptr()) return EoF();
00434     char *const eb = this->eback();
00435     const int res = AdjustEOF(m_Obj.cread(this->eback(), m_BufSize));
00436     setg(eb, eb, eb + ((res==EoF()) ? 0 : res));
00437     return (!res || (res == EoF())) ? EoF() : *eb;
00438   }
00439 
00440 private:
00442   static int_type EoF() { return traits_type::eof(); }
00443 
00445   static PGSTD::streampos AdjustEOF(int pos)
00446   {
00447     return (pos == -1) ? EoF() : pos;
00448   }
00449 
00450   void initialize(openmode mode)
00451   {
00452     if (mode & PGSTD::ios::in) 
00453     {
00454       m_G = new char_type[m_BufSize];
00455       setg(m_G, m_G, m_G);
00456     }
00457     if (mode & PGSTD::ios::out)
00458     {
00459       m_P = new char_type[m_BufSize];
00460       setp(m_P, m_P + m_BufSize);
00461     }
00462   }
00463 
00464   const size_type m_BufSize;
00465   largeobjectaccess m_Obj;
00466 
00467   // Get & put buffers
00468   char_type *m_G, *m_P;
00469 };
00470 
00471 
00473 
00481 template<typename CHAR=char, typename TRAITS=PGSTD::char_traits<CHAR> > 
00482   class basic_ilostream :
00483 #ifdef PQXX_HAVE_STREAMBUF
00484     public PGSTD::basic_istream<CHAR, TRAITS>
00485 #else
00486     public PGSTD::istream
00487 #endif
00488 {
00489 #ifdef PQXX_HAVE_STREAMBUF
00490   typedef PGSTD::basic_istream<CHAR, TRAITS> super;
00491 #else
00492   typedef PGSTD::istream super;
00493 #endif
00494 
00495 public:
00496   typedef CHAR char_type;
00497   typedef TRAITS traits_type;
00498   typedef typename traits_type::int_type int_type;
00499   typedef typename traits_type::pos_type pos_type;
00500   typedef typename traits_type::off_type off_type;
00501 
00503 
00507   basic_ilostream(dbtransaction &T, 
00508                   largeobject O, 
00509                   largeobject::size_type BufSize=512) :                 //[t57]
00510     super(&m_Buf),
00511     m_Buf(T, O, PGSTD::ios::in, BufSize) 
00512   { 
00513   }
00514 
00516 
00520   basic_ilostream(dbtransaction &T, 
00521                   oid O, 
00522                   largeobject::size_type BufSize=512) :                 //[t48]
00523     super(&m_Buf),
00524     m_Buf(T, O, PGSTD::ios::in, BufSize) 
00525   { 
00526   }
00527 
00528 private:
00529   largeobject_streambuf<CHAR,TRAITS> m_Buf;
00530 };
00531 
00532 typedef basic_ilostream<char> ilostream;
00533 
00534 
00536 
00544 template<typename CHAR=char, typename TRAITS=PGSTD::char_traits<CHAR> > 
00545   class basic_olostream : 
00546 #ifdef PQXX_HAVE_STREAMBUF
00547     public PGSTD::basic_ostream<CHAR, TRAITS>
00548 #else
00549     public PGSTD::ostream
00550 #endif
00551 {
00552 #ifdef PQXX_HAVE_STREAMBUF
00553   typedef PGSTD::basic_ostream<CHAR, TRAITS> super;
00554 #else
00555   typedef PGSTD::ostream super;
00556 #endif
00557 public:
00558   typedef CHAR char_type;
00559   typedef TRAITS traits_type;
00560   typedef typename traits_type::int_type int_type;
00561   typedef typename traits_type::pos_type pos_type;
00562   typedef typename traits_type::off_type off_type;
00563 
00565 
00569   basic_olostream(dbtransaction &T, 
00570                   largeobject O,
00571                   largeobject::size_type BufSize=512) :                 //[t48]
00572     super(&m_Buf),
00573     m_Buf(T, O, PGSTD::ios::out, BufSize) 
00574   { 
00575   }
00576 
00578 
00582   basic_olostream(dbtransaction &T, 
00583                   oid O,
00584                   largeobject::size_type BufSize=512) :                 //[t57]
00585     super(&m_Buf),
00586     m_Buf(T, O, PGSTD::ios::out, BufSize) 
00587   { 
00588   }
00589 
00590   ~basic_olostream() 
00591   { 
00592     try
00593     {
00594 #ifdef PQXX_HAVE_STREAMBUF
00595       m_Buf.pubsync(); m_Buf.pubsync(); 
00596 #else
00597       m_Buf.sync(); m_Buf.sync();
00598 #endif
00599     }
00600     catch (const PGSTD::exception &e)
00601     {
00602       m_Buf.process_notice(e.what());
00603     }
00604   }
00605 
00606 private:
00607   largeobject_streambuf<CHAR,TRAITS> m_Buf;
00608 };
00609 
00610 typedef basic_olostream<char> olostream;
00611 
00612 
00614 
00622 template<typename CHAR=char, typename TRAITS=PGSTD::char_traits<CHAR> > 
00623   class basic_lostream :
00624 #ifdef PQXX_HAVE_STREAMBUF
00625     public PGSTD::basic_iostream<CHAR, TRAITS>
00626 #else
00627     public PGSTD::iostream
00628 #endif
00629 {
00630 #ifdef PQXX_HAVE_STREAMBUF
00631   typedef PGSTD::basic_iostream<CHAR, TRAITS> super;
00632 #else
00633   typedef PGSTD::iostream super;
00634 #endif
00635 
00636 public:
00637   typedef CHAR char_type;
00638   typedef TRAITS traits_type;
00639   typedef typename traits_type::int_type int_type;
00640   typedef typename traits_type::pos_type pos_type;
00641   typedef typename traits_type::off_type off_type;
00642 
00644 
00648   basic_lostream(dbtransaction &T, 
00649                  largeobject O,
00650                  largeobject::size_type BufSize=512) :                  //[t59]
00651     super(&m_Buf),
00652     m_Buf(T, O, PGSTD::ios::in | PGSTD::ios::out, BufSize) 
00653   { 
00654   }
00655 
00657 
00661   basic_lostream(dbtransaction &T, 
00662                  oid O,
00663                  largeobject::size_type BufSize=512) :                  //[t59]
00664     super(&m_Buf),
00665     m_Buf(T, O, PGSTD::ios::in | PGSTD::ios::out, BufSize) 
00666   { 
00667   }
00668 
00669   ~basic_lostream() 
00670   {
00671     try
00672     {
00673 #ifdef PQXX_HAVE_STREAMBUF
00674       m_Buf.pubsync(); m_Buf.pubsync(); 
00675 #else
00676       m_Buf.sync(); m_Buf.sync();
00677 #endif
00678     }
00679     catch (const PGSTD::exception &e)
00680     {
00681       m_Buf.process_notice(e.what());
00682     }
00683   }
00684 
00685 private:
00686   largeobject_streambuf<CHAR,TRAITS> m_Buf;
00687 };
00688 
00689 typedef basic_lostream<char> lostream;
00690 
00691 }
00692 
00693 

Generated on Mon Nov 1 19:13:35 2004 for libpqxx by  doxygen 1.3.9.1