largeobject.hxx

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-2009, 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 #ifndef PQXX_H_LARGEOBJECT
00020 #define PQXX_H_LARGEOBJECT
00021 
00022 #include "pqxx/compiler-public.hxx"
00023 #include "pqxx/compiler-internal-pre.hxx"
00024 
00025 #ifdef PQXX_HAVE_STREAMBUF
00026 #include <streambuf>
00027 #else
00028 #include <streambuf.h>
00029 #endif
00030 
00031 #include "pqxx/dbtransaction"
00032 
00033 
00034 namespace pqxx
00035 {
00036 
00037 class largeobjectaccess;
00038 
00040 
00047 class PQXX_LIBEXPORT largeobject
00048 {
00049 public:
00050   typedef long size_type;
00051 
00053   largeobject() throw ();                                               //[t48]
00054 
00056 
00058   explicit largeobject(dbtransaction &T);                               //[t48]
00059 
00061 
00065   explicit largeobject(oid O) throw () : m_ID(O) {}                     //[t48]
00066 
00068 
00072   largeobject(dbtransaction &T, const PGSTD::string &File);             //[t53]
00073 
00075 
00079   largeobject(const largeobjectaccess &O) throw ();                     //[t50]
00080 
00082 
00086   oid id() const throw () { return m_ID; }                              //[t48]
00087 
00096 
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; }
00109 
00110   bool operator>=(const largeobject &other) const                       //[t51]
00111           { return m_ID >= other.m_ID; }
00113 
00114   bool operator<(const largeobject &other) const                        //[t51]
00115           { return m_ID < other.m_ID; }
00117 
00118   bool operator>(const largeobject &other) const                        //[t51]
00119           { return m_ID > other.m_ID; }
00121 
00123 
00127   void to_file(dbtransaction &T, const PGSTD::string &File) const;      //[t52]
00128 
00130 
00134   void remove(dbtransaction &T) const;                                  //[t48]
00135 
00136 protected:
00137   static internal::pq::PGconn *RawConnection(const dbtransaction &T)
00138   {
00139     return T.conn().RawConnection();
00140   }
00141 
00142   PGSTD::string Reason(int err) const;
00143 
00144 private:
00145   oid m_ID;
00146 };
00147 
00148 
00149 // TODO: New hierarchy with separate read / write / mixed-mode access
00150 
00152 class PQXX_LIBEXPORT largeobjectaccess : private largeobject
00153 {
00154 public:
00155   using largeobject::size_type;
00156   typedef long off_type;
00157   typedef size_type pos_type;
00158 
00160 
00164   typedef PGSTD::ios::openmode openmode;
00165 
00167 
00171   typedef PGSTD::ios::seekdir seekdir;
00172 
00174 
00178   explicit largeobjectaccess(dbtransaction &T,
00179                              openmode mode =
00180                                 PGSTD::ios::in |
00181                                 PGSTD::ios::out);                       //[t51]
00182 
00184 
00190   largeobjectaccess(dbtransaction &T,
00191                     oid O,
00192                     openmode mode =
00193                         PGSTD::ios::in |
00194                         PGSTD::ios::out);                               //[t52]
00195 
00197 
00202   largeobjectaccess(dbtransaction &T,
00203                     largeobject O,
00204                     openmode mode = PGSTD::ios::in | PGSTD::ios::out);  //[t50]
00205 
00207 
00212   largeobjectaccess(dbtransaction &T,
00213                     const PGSTD::string &File,
00214                     openmode mode =
00215                         PGSTD::ios::in | PGSTD::ios::out);              //[t55]
00216 
00217   ~largeobjectaccess() throw () { close(); }
00218 
00220 
00223   using largeobject::id;
00224 
00226 
00229   void to_file(const PGSTD::string &File) const                         //[t54]
00230         { largeobject::to_file(m_Trans, File); }
00231 
00232 #ifdef PQXX_BROKEN_USING_DECL
00234 
00238   void to_file(dbtransaction &T, const PGSTD::string &F) const
00239         { largeobject::to_file(T, F); }
00240 #else
00241   using largeobject::to_file;
00242 #endif
00243 
00248 
00249 
00253   void write(const char Buf[], size_type Len);                          //[t51]
00254 
00256 
00259   void write(const PGSTD::string &Buf)                                  //[t50]
00260         { write(Buf.c_str(), static_cast<size_type>(Buf.size())); }
00261 
00263 
00269   size_type read(char Buf[], size_type Len);                            //[t50]
00270 
00272 
00275   size_type seek(size_type dest, seekdir dir);                          //[t51]
00276 
00278 
00281   size_type tell() const;                                               //[t50]
00283 
00293 
00294 
00302   pos_type cseek(off_type dest, seekdir dir) throw ();                  //[t50]
00303 
00305 
00311   off_type cwrite(const char Buf[], size_type Len) throw ();            //[t50]
00312 
00314 
00320   off_type cread(char Buf[], size_type Len) throw ();                   //[t50]
00321 
00323 
00327   pos_type ctell() const throw ();                                      //[t50]
00329 
00334 
00335   void process_notice(const PGSTD::string &) throw ();                  //[t50]
00337 
00338   using largeobject::remove;
00339 
00340   using largeobject::operator==;
00341   using largeobject::operator!=;
00342   using largeobject::operator<;
00343   using largeobject::operator<=;
00344   using largeobject::operator>;
00345   using largeobject::operator>=;
00346 
00347 private:
00348   PGSTD::string PQXX_PRIVATE Reason(int err) const;
00349   internal::pq::PGconn *RawConnection() const
00350         { return largeobject::RawConnection(m_Trans); }
00351 
00352   void open(openmode mode);
00353   void close() throw ();
00354 
00355   dbtransaction &m_Trans;
00356   int m_fd;
00357 
00358   // Not allowed:
00359   largeobjectaccess();
00360   largeobjectaccess(const largeobjectaccess &);
00361   largeobjectaccess operator=(const largeobjectaccess &);
00362 };
00363 
00364 
00366 
00374 template<typename CHAR=char, typename TRAITS=PGSTD::char_traits<CHAR> >
00375   class largeobject_streambuf :
00376 #ifdef PQXX_HAVE_STREAMBUF
00377     public PGSTD::basic_streambuf<CHAR, TRAITS>
00378 #else
00379     public PGSTD::streambuf
00380 #endif
00381 {
00382   typedef long size_type;
00383 public:
00384   typedef CHAR   char_type;
00385   typedef TRAITS traits_type;
00386   typedef typename traits_type::int_type int_type;
00387 #ifdef PQXX_HAVE_STREAMBUF
00388   typedef typename traits_type::pos_type pos_type;
00389   typedef typename traits_type::off_type off_type;
00390 #else
00391   typedef streamoff off_type;
00392   typedef streampos pos_type;
00393 #endif
00394   typedef largeobjectaccess::openmode openmode;
00395   typedef largeobjectaccess::seekdir seekdir;
00396 
00397   largeobject_streambuf(dbtransaction &T,
00398                         largeobject O,
00399                         openmode mode = PGSTD::ios::in | PGSTD::ios::out,
00400                         size_type BufSize=512) :                        //[t48]
00401     m_BufSize(BufSize),
00402     m_Obj(T, O),
00403     m_G(0),
00404     m_P(0)
00405         { initialize(mode); }
00406 
00407   largeobject_streambuf(dbtransaction &T,
00408                         oid O,
00409                         openmode mode = PGSTD::ios::in | PGSTD::ios::out,
00410                         size_type BufSize=512) :                        //[t48]
00411     m_BufSize(BufSize),
00412     m_Obj(T, O),
00413     m_G(0),
00414     m_P(0)
00415         { initialize(mode); }
00416 
00417   virtual ~largeobject_streambuf() throw () { delete [] m_P; delete [] m_G; }
00418 
00419 
00421   void process_notice(const PGSTD::string &s) { m_Obj.process_notice(s); }
00422 
00423 #ifdef PQXX_HAVE_STREAMBUF
00424 protected:
00425 #endif
00426   virtual int sync()
00427   {
00428     // setg() sets eback, gptr, egptr
00429     setg(this->eback(), this->eback(), this->egptr());
00430     return overflow(EoF());
00431   }
00432 
00433 protected:
00434   virtual pos_type seekoff(off_type offset,
00435                            seekdir dir,
00436                            openmode)
00437   {
00438     return AdjustEOF(m_Obj.cseek(largeobjectaccess::off_type(offset), dir));
00439   }
00440 
00441   virtual pos_type seekpos(pos_type pos, openmode)
00442   {
00443     const largeobjectaccess::pos_type newpos = m_Obj.cseek(
00444         largeobjectaccess::off_type(pos),
00445         PGSTD::ios::beg);
00446     return AdjustEOF(newpos);
00447   }
00448 
00449   virtual int_type overflow(int_type ch = EoF())
00450   {
00451     char *const pp = this->pptr();
00452     if (!pp) return EoF();
00453     char *const pb = this->pbase();
00454     int_type res = 0;
00455 
00456     if (pp > pb) res = int_type(AdjustEOF(m_Obj.cwrite(pb, pp-pb)));
00457     setp(m_P, m_P + m_BufSize);
00458 
00459     // Write that one more character, if it's there.
00460     if (ch != EoF())
00461     {
00462       *this->pptr() = char(ch);
00463       this->pbump(1);
00464     }
00465     return res;
00466   }
00467 
00468   virtual int_type underflow()
00469   {
00470     if (!this->gptr()) return EoF();
00471     char *const eb = this->eback();
00472     const int_type res(static_cast<int_type>(AdjustEOF(m_Obj.cread(this->eback(), m_BufSize))));
00473     setg(eb, eb, eb + ((res==EoF()) ? 0 : res));
00474     return (!res || (res == EoF())) ? EoF() : *eb;
00475   }
00476 
00477 private:
00479   static int_type EoF() { return traits_type::eof(); }
00480 
00482   template<typename INTYPE>
00483   static PGSTD::streampos AdjustEOF(INTYPE pos)
00484         { return (pos==-1) ? PGSTD::streampos(EoF()) : PGSTD::streampos(pos); }
00485 
00486   void initialize(openmode mode)
00487   {
00488     if (mode & PGSTD::ios::in)
00489     {
00490       m_G = new char_type[m_BufSize];
00491       setg(m_G, m_G, m_G);
00492     }
00493     if (mode & PGSTD::ios::out)
00494     {
00495       m_P = new char_type[m_BufSize];
00496       setp(m_P, m_P + m_BufSize);
00497     }
00498   }
00499 
00500   const size_type m_BufSize;
00501   largeobjectaccess m_Obj;
00502 
00503   // Get & put buffers
00504   char_type *m_G, *m_P;
00505 };
00506 
00507 
00509 
00517 template<typename CHAR=char, typename TRAITS=PGSTD::char_traits<CHAR> >
00518   class basic_ilostream :
00519 #ifdef PQXX_HAVE_STREAMBUF
00520     public PGSTD::basic_istream<CHAR, TRAITS>
00521 #else
00522     public PGSTD::istream
00523 #endif
00524 {
00525 #ifdef PQXX_HAVE_STREAMBUF
00526   typedef PGSTD::basic_istream<CHAR, TRAITS> super;
00527 #else
00528   typedef PGSTD::istream super;
00529 #endif
00530 
00531 public:
00532   typedef CHAR char_type;
00533   typedef TRAITS traits_type;
00534   typedef typename traits_type::int_type int_type;
00535   typedef typename traits_type::pos_type pos_type;
00536   typedef typename traits_type::off_type off_type;
00537 
00539 
00544   basic_ilostream(dbtransaction &T,
00545                   largeobject O,
00546                   largeobject::size_type BufSize=512) :                 //[t57]
00547     super(0),
00548     m_Buf(T, O, PGSTD::ios::in, BufSize)
00549         { super::init(&m_Buf); }
00550 
00552 
00557   basic_ilostream(dbtransaction &T,
00558                   oid O,
00559                   largeobject::size_type BufSize=512) :                 //[t48]
00560     super(0),
00561     m_Buf(T, O, PGSTD::ios::in, BufSize)
00562         { super::init(&m_Buf); }
00563 
00564 private:
00565   largeobject_streambuf<CHAR,TRAITS> m_Buf;
00566 };
00567 
00568 typedef basic_ilostream<char> ilostream;
00569 
00570 
00572 
00580 template<typename CHAR=char, typename TRAITS=PGSTD::char_traits<CHAR> >
00581   class basic_olostream :
00582 #ifdef PQXX_HAVE_STREAMBUF
00583     public PGSTD::basic_ostream<CHAR, TRAITS>
00584 #else
00585     public PGSTD::ostream
00586 #endif
00587 {
00588 #ifdef PQXX_HAVE_STREAMBUF
00589   typedef PGSTD::basic_ostream<CHAR, TRAITS> super;
00590 #else
00591   typedef PGSTD::ostream super;
00592 #endif
00593 public:
00594   typedef CHAR char_type;
00595   typedef TRAITS traits_type;
00596   typedef typename traits_type::int_type int_type;
00597   typedef typename traits_type::pos_type pos_type;
00598   typedef typename traits_type::off_type off_type;
00599 
00601 
00606   basic_olostream(dbtransaction &T,
00607                   largeobject O,
00608                   largeobject::size_type BufSize=512) :                 //[t48]
00609     super(0),
00610     m_Buf(T, O, PGSTD::ios::out, BufSize)
00611         { super::init(&m_Buf); }
00612 
00614 
00619   basic_olostream(dbtransaction &T,
00620                   oid O,
00621                   largeobject::size_type BufSize=512) :                 //[t57]
00622     super(0),
00623     m_Buf(T, O, PGSTD::ios::out, BufSize)
00624         { super::init(&m_Buf); }
00625 
00626   ~basic_olostream()
00627   {
00628     try
00629     {
00630 #ifdef PQXX_HAVE_STREAMBUF
00631       m_Buf.pubsync(); m_Buf.pubsync();
00632 #else
00633       m_Buf.sync(); m_Buf.sync();
00634 #endif
00635     }
00636     catch (const PGSTD::exception &e)
00637     {
00638       m_Buf.process_notice(e.what());
00639     }
00640   }
00641 
00642 private:
00643   largeobject_streambuf<CHAR,TRAITS> m_Buf;
00644 };
00645 
00646 typedef basic_olostream<char> olostream;
00647 
00648 
00650 
00658 template<typename CHAR=char, typename TRAITS=PGSTD::char_traits<CHAR> >
00659   class basic_lostream :
00660 #ifdef PQXX_HAVE_STREAMBUF
00661     public PGSTD::basic_iostream<CHAR, TRAITS>
00662 #else
00663     public PGSTD::iostream
00664 #endif
00665 {
00666 #ifdef PQXX_HAVE_STREAMBUF
00667   typedef PGSTD::basic_iostream<CHAR, TRAITS> super;
00668 #else
00669   typedef PGSTD::iostream super;
00670 #endif
00671 
00672 public:
00673   typedef CHAR char_type;
00674   typedef TRAITS traits_type;
00675   typedef typename traits_type::int_type int_type;
00676   typedef typename traits_type::pos_type pos_type;
00677   typedef typename traits_type::off_type off_type;
00678 
00680 
00685   basic_lostream(dbtransaction &T,
00686                  largeobject O,
00687                  largeobject::size_type BufSize=512) :                  //[t59]
00688     super(0),
00689     m_Buf(T, O, PGSTD::ios::in | PGSTD::ios::out, BufSize)
00690         { super::init(&m_Buf); }
00691 
00693 
00698   basic_lostream(dbtransaction &T,
00699                  oid O,
00700                  largeobject::size_type BufSize=512) :                  //[t59]
00701     super(0),
00702     m_Buf(T, O, PGSTD::ios::in | PGSTD::ios::out, BufSize)
00703         { super::init(&m_Buf); }
00704 
00705   ~basic_lostream()
00706   {
00707     try
00708     {
00709 #ifdef PQXX_HAVE_STREAMBUF
00710       m_Buf.pubsync(); m_Buf.pubsync();
00711 #else
00712       m_Buf.sync(); m_Buf.sync();
00713 #endif
00714     }
00715     catch (const PGSTD::exception &e)
00716     {
00717       m_Buf.process_notice(e.what());
00718     }
00719   }
00720 
00721 private:
00722   largeobject_streambuf<CHAR,TRAITS> m_Buf;
00723 };
00724 
00725 typedef basic_lostream<char> lostream;
00726 
00727 } // namespace pqxx
00728 
00729 #include "pqxx/compiler-internal-post.hxx"
00730 
00731 #endif
00732 

Generated on Sat Aug 15 00:16:49 2009 for libpqxx by  doxygen 1.5.8