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 #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() 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 Reason() 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 mode)
00393   {
00394     if (mode != SEEK_CUR)
00395       throw PGSTD::logic_error("Offset "+to_string(int(mode))+" in seekoff()");
00396     return AdjustEOF(m_Obj.cseek(offset, dir));
00397   }
00398 
00399   virtual pos_type seekpos(pos_type pos, openmode mode)
00400   {
00401     if (mode != SEEK_SET)
00402       throw PGSTD::logic_error("Offset "+to_string(int(mode))+" in seekpos()");
00403     return AdjustEOF(m_Obj.cseek(pos, PGSTD::ios::beg));
00404   }
00405 
00406   virtual int_type overflow(int_type ch = EoF())
00407   {
00408     char *const pp = this->pptr();
00409     if (!pp) return EoF();
00410     char *const pb = this->pbase();
00411     int_type res = 0;
00412 
00413     if (pp > pb) res = AdjustEOF(m_Obj.cwrite(pb, pp-pb));
00414     setp(m_P, m_P + m_BufSize);
00415 
00416     // Write that one more character, if it's there.
00417     if (ch != EoF())
00418     {
00419       *this->pptr() = char(ch);
00420       this->pbump(1);
00421     }
00422     return res;
00423   }
00424 
00425   virtual int_type underflow()
00426   {
00427     if (!this->gptr()) return EoF();
00428     char *const eb = this->eback();
00429     const int res = AdjustEOF(m_Obj.cread(this->eback(), m_BufSize));
00430     setg(eb, eb, eb + ((res==EoF()) ? 0 : res));
00431     return (!res || (res == EoF())) ? EoF() : *eb;
00432   }
00433 
00434 private:
00436   static int_type EoF() { return traits_type::eof(); }
00437 
00439   static PGSTD::streampos AdjustEOF(int pos)
00440   {
00441     return (pos == -1) ? EoF() : pos;
00442   }
00443 
00444   void initialize(openmode mode)
00445   {
00446     if (mode & PGSTD::ios::in) 
00447     {
00448       m_G = new char_type[m_BufSize];
00449       setg(m_G, m_G, m_G);
00450     }
00451     if (mode & PGSTD::ios::out)
00452     {
00453       m_P = new char_type[m_BufSize];
00454       setp(m_P, m_P + m_BufSize);
00455     }
00456   }
00457 
00458   const size_type m_BufSize;
00459   largeobjectaccess m_Obj;
00460 
00461   // Get & put buffers
00462   char_type *m_G, *m_P;
00463 };
00464 
00465 
00467 
00475 template<typename CHAR=char, typename TRAITS=PGSTD::char_traits<CHAR> > 
00476   class basic_ilostream :
00477 #ifdef PQXX_HAVE_STREAMBUF
00478     public PGSTD::basic_istream<CHAR, TRAITS>
00479 #else
00480     public PGSTD::istream
00481 #endif
00482 {
00483 #ifdef PQXX_HAVE_STREAMBUF
00484   typedef PGSTD::basic_istream<CHAR, TRAITS> super;
00485 #else
00486   typedef PGSTD::istream super;
00487 #endif
00488 
00489 public:
00490   typedef CHAR char_type;
00491   typedef TRAITS traits_type;
00492   typedef typename traits_type::int_type int_type;
00493   typedef typename traits_type::pos_type pos_type;
00494   typedef typename traits_type::off_type off_type;
00495 
00497 
00502   basic_ilostream(dbtransaction &T, 
00503                   largeobject O, 
00504                   largeobject::size_type BufSize=512) :                 //[t57]
00505     super(&m_Buf),
00506     m_Buf(T, O, PGSTD::ios::in, BufSize) 
00507         { }
00508 
00510 
00515   basic_ilostream(dbtransaction &T, 
00516                   oid O, 
00517                   largeobject::size_type BufSize=512) :                 //[t48]
00518     super(&m_Buf),
00519     m_Buf(T, O, PGSTD::ios::in, BufSize) 
00520         { }
00521 
00522 private:
00523   largeobject_streambuf<CHAR,TRAITS> m_Buf;
00524 };
00525 
00526 typedef basic_ilostream<char> ilostream;
00527 
00528 
00530 
00538 template<typename CHAR=char, typename TRAITS=PGSTD::char_traits<CHAR> > 
00539   class basic_olostream : 
00540 #ifdef PQXX_HAVE_STREAMBUF
00541     public PGSTD::basic_ostream<CHAR, TRAITS>
00542 #else
00543     public PGSTD::ostream
00544 #endif
00545 {
00546 #ifdef PQXX_HAVE_STREAMBUF
00547   typedef PGSTD::basic_ostream<CHAR, TRAITS> super;
00548 #else
00549   typedef PGSTD::ostream super;
00550 #endif
00551 public:
00552   typedef CHAR char_type;
00553   typedef TRAITS traits_type;
00554   typedef typename traits_type::int_type int_type;
00555   typedef typename traits_type::pos_type pos_type;
00556   typedef typename traits_type::off_type off_type;
00557 
00559 
00564   basic_olostream(dbtransaction &T, 
00565                   largeobject O,
00566                   largeobject::size_type BufSize=512) :                 //[t48]
00567     super(&m_Buf),
00568     m_Buf(T, O, PGSTD::ios::out, BufSize) 
00569         { }
00570 
00572 
00577   basic_olostream(dbtransaction &T, 
00578                   oid O,
00579                   largeobject::size_type BufSize=512) :                 //[t57]
00580     super(&m_Buf),
00581     m_Buf(T, O, PGSTD::ios::out, BufSize) 
00582         { }
00583 
00584   ~basic_olostream() 
00585   { 
00586     try
00587     {
00588 #ifdef PQXX_HAVE_STREAMBUF
00589       m_Buf.pubsync(); m_Buf.pubsync(); 
00590 #else
00591       m_Buf.sync(); m_Buf.sync();
00592 #endif
00593     }
00594     catch (const PGSTD::exception &e)
00595     {
00596       m_Buf.process_notice(e.what());
00597     }
00598   }
00599 
00600 private:
00601   largeobject_streambuf<CHAR,TRAITS> m_Buf;
00602 };
00603 
00604 typedef basic_olostream<char> olostream;
00605 
00606 
00608 
00616 template<typename CHAR=char, typename TRAITS=PGSTD::char_traits<CHAR> > 
00617   class basic_lostream :
00618 #ifdef PQXX_HAVE_STREAMBUF
00619     public PGSTD::basic_iostream<CHAR, TRAITS>
00620 #else
00621     public PGSTD::iostream
00622 #endif
00623 {
00624 #ifdef PQXX_HAVE_STREAMBUF
00625   typedef PGSTD::basic_iostream<CHAR, TRAITS> super;
00626 #else
00627   typedef PGSTD::iostream super;
00628 #endif
00629 
00630 public:
00631   typedef CHAR char_type;
00632   typedef TRAITS traits_type;
00633   typedef typename traits_type::int_type int_type;
00634   typedef typename traits_type::pos_type pos_type;
00635   typedef typename traits_type::off_type off_type;
00636 
00638 
00643   basic_lostream(dbtransaction &T, 
00644                  largeobject O,
00645                  largeobject::size_type BufSize=512) :                  //[t59]
00646     super(&m_Buf),
00647     m_Buf(T, O, PGSTD::ios::in | PGSTD::ios::out, BufSize) 
00648         { }
00649 
00651 
00656   basic_lostream(dbtransaction &T, 
00657                  oid O,
00658                  largeobject::size_type BufSize=512) :                  //[t59]
00659     super(&m_Buf),
00660     m_Buf(T, O, PGSTD::ios::in | PGSTD::ios::out, BufSize) 
00661         { }
00662 
00663   ~basic_lostream() 
00664   {
00665     try
00666     {
00667 #ifdef PQXX_HAVE_STREAMBUF
00668       m_Buf.pubsync(); m_Buf.pubsync(); 
00669 #else
00670       m_Buf.sync(); m_Buf.sync();
00671 #endif
00672     }
00673     catch (const PGSTD::exception &e)
00674     {
00675       m_Buf.process_notice(e.what());
00676     }
00677   }
00678 
00679 private:
00680   largeobject_streambuf<CHAR,TRAITS> m_Buf;
00681 };
00682 
00683 typedef basic_lostream<char> lostream;
00684 
00685 }
00686 
00687 

Generated on Mon Nov 15 11:27:59 2004 for libpqxx by  doxygen 1.3.9.1