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-2008, 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         { return AdjustEOF(m_Obj.cseek(offset, dir)); }
00438 
00439   virtual pos_type seekpos(pos_type pos, openmode)
00440         { return AdjustEOF(m_Obj.cseek(pos, PGSTD::ios::beg)); }
00441 
00442   virtual int_type overflow(int_type ch = EoF())
00443   {
00444     char *const pp = this->pptr();
00445     if (!pp) return EoF();
00446     char *const pb = this->pbase();
00447     int_type res = 0;
00448 
00449     if (pp > pb) res = int_type(AdjustEOF(m_Obj.cwrite(pb, pp-pb)));
00450     setp(m_P, m_P + m_BufSize);
00451 
00452     // Write that one more character, if it's there.
00453     if (ch != EoF())
00454     {
00455       *this->pptr() = char(ch);
00456       this->pbump(1);
00457     }
00458     return res;
00459   }
00460 
00461   virtual int_type underflow()
00462   {
00463     if (!this->gptr()) return EoF();
00464     char *const eb = this->eback();
00465     const int_type res(static_cast<int_type>(AdjustEOF(m_Obj.cread(this->eback(), m_BufSize))));
00466     setg(eb, eb, eb + ((res==EoF()) ? 0 : res));
00467     return (!res || (res == EoF())) ? EoF() : *eb;
00468   }
00469 
00470 private:
00472   static int_type EoF() { return traits_type::eof(); }
00473 
00475   template<typename INTYPE>
00476   static PGSTD::streampos AdjustEOF(INTYPE pos)
00477         { return (pos==-1) ? PGSTD::streampos(EoF()) : PGSTD::streampos(pos); }
00478 
00479   void initialize(openmode mode)
00480   {
00481     if (mode & PGSTD::ios::in)
00482     {
00483       m_G = new char_type[m_BufSize];
00484       setg(m_G, m_G, m_G);
00485     }
00486     if (mode & PGSTD::ios::out)
00487     {
00488       m_P = new char_type[m_BufSize];
00489       setp(m_P, m_P + m_BufSize);
00490     }
00491   }
00492 
00493   const size_type m_BufSize;
00494   largeobjectaccess m_Obj;
00495 
00496   // Get & put buffers
00497   char_type *m_G, *m_P;
00498 };
00499 
00500 
00502 
00510 template<typename CHAR=char, typename TRAITS=PGSTD::char_traits<CHAR> >
00511   class basic_ilostream :
00512 #ifdef PQXX_HAVE_STREAMBUF
00513     public PGSTD::basic_istream<CHAR, TRAITS>
00514 #else
00515     public PGSTD::istream
00516 #endif
00517 {
00518 #ifdef PQXX_HAVE_STREAMBUF
00519   typedef PGSTD::basic_istream<CHAR, TRAITS> super;
00520 #else
00521   typedef PGSTD::istream super;
00522 #endif
00523 
00524 public:
00525   typedef CHAR char_type;
00526   typedef TRAITS traits_type;
00527   typedef typename traits_type::int_type int_type;
00528   typedef typename traits_type::pos_type pos_type;
00529   typedef typename traits_type::off_type off_type;
00530 
00532 
00537   basic_ilostream(dbtransaction &T,
00538                   largeobject O,
00539                   largeobject::size_type BufSize=512) :                 //[t57]
00540     super(0),
00541     m_Buf(T, O, PGSTD::ios::in, BufSize)
00542         { super::init(&m_Buf); }
00543 
00545 
00550   basic_ilostream(dbtransaction &T,
00551                   oid O,
00552                   largeobject::size_type BufSize=512) :                 //[t48]
00553     super(0),
00554     m_Buf(T, O, PGSTD::ios::in, BufSize)
00555         { super::init(&m_Buf); }
00556 
00557 private:
00558   largeobject_streambuf<CHAR,TRAITS> m_Buf;
00559 };
00560 
00561 typedef basic_ilostream<char> ilostream;
00562 
00563 
00565 
00573 template<typename CHAR=char, typename TRAITS=PGSTD::char_traits<CHAR> >
00574   class basic_olostream :
00575 #ifdef PQXX_HAVE_STREAMBUF
00576     public PGSTD::basic_ostream<CHAR, TRAITS>
00577 #else
00578     public PGSTD::ostream
00579 #endif
00580 {
00581 #ifdef PQXX_HAVE_STREAMBUF
00582   typedef PGSTD::basic_ostream<CHAR, TRAITS> super;
00583 #else
00584   typedef PGSTD::ostream super;
00585 #endif
00586 public:
00587   typedef CHAR char_type;
00588   typedef TRAITS traits_type;
00589   typedef typename traits_type::int_type int_type;
00590   typedef typename traits_type::pos_type pos_type;
00591   typedef typename traits_type::off_type off_type;
00592 
00594 
00599   basic_olostream(dbtransaction &T,
00600                   largeobject O,
00601                   largeobject::size_type BufSize=512) :                 //[t48]
00602     super(0),
00603     m_Buf(T, O, PGSTD::ios::out, BufSize)
00604         { super::init(&m_Buf); }
00605 
00607 
00612   basic_olostream(dbtransaction &T,
00613                   oid O,
00614                   largeobject::size_type BufSize=512) :                 //[t57]
00615     super(0),
00616     m_Buf(T, O, PGSTD::ios::out, BufSize)
00617         { super::init(&m_Buf); }
00618 
00619   ~basic_olostream()
00620   {
00621     try
00622     {
00623 #ifdef PQXX_HAVE_STREAMBUF
00624       m_Buf.pubsync(); m_Buf.pubsync();
00625 #else
00626       m_Buf.sync(); m_Buf.sync();
00627 #endif
00628     }
00629     catch (const PGSTD::exception &e)
00630     {
00631       m_Buf.process_notice(e.what());
00632     }
00633   }
00634 
00635 private:
00636   largeobject_streambuf<CHAR,TRAITS> m_Buf;
00637 };
00638 
00639 typedef basic_olostream<char> olostream;
00640 
00641 
00643 
00651 template<typename CHAR=char, typename TRAITS=PGSTD::char_traits<CHAR> >
00652   class basic_lostream :
00653 #ifdef PQXX_HAVE_STREAMBUF
00654     public PGSTD::basic_iostream<CHAR, TRAITS>
00655 #else
00656     public PGSTD::iostream
00657 #endif
00658 {
00659 #ifdef PQXX_HAVE_STREAMBUF
00660   typedef PGSTD::basic_iostream<CHAR, TRAITS> super;
00661 #else
00662   typedef PGSTD::iostream super;
00663 #endif
00664 
00665 public:
00666   typedef CHAR char_type;
00667   typedef TRAITS traits_type;
00668   typedef typename traits_type::int_type int_type;
00669   typedef typename traits_type::pos_type pos_type;
00670   typedef typename traits_type::off_type off_type;
00671 
00673 
00678   basic_lostream(dbtransaction &T,
00679                  largeobject O,
00680                  largeobject::size_type BufSize=512) :                  //[t59]
00681     super(0),
00682     m_Buf(T, O, PGSTD::ios::in | PGSTD::ios::out, BufSize)
00683         { super::init(&m_Buf); }
00684 
00686 
00691   basic_lostream(dbtransaction &T,
00692                  oid O,
00693                  largeobject::size_type BufSize=512) :                  //[t59]
00694     super(0),
00695     m_Buf(T, O, PGSTD::ios::in | PGSTD::ios::out, BufSize)
00696         { super::init(&m_Buf); }
00697 
00698   ~basic_lostream()
00699   {
00700     try
00701     {
00702 #ifdef PQXX_HAVE_STREAMBUF
00703       m_Buf.pubsync(); m_Buf.pubsync();
00704 #else
00705       m_Buf.sync(); m_Buf.sync();
00706 #endif
00707     }
00708     catch (const PGSTD::exception &e)
00709     {
00710       m_Buf.process_notice(e.what());
00711     }
00712   }
00713 
00714 private:
00715   largeobject_streambuf<CHAR,TRAITS> m_Buf;
00716 };
00717 
00718 typedef basic_lostream<char> lostream;
00719 
00720 } // namespace pqxx
00721 
00722 #include "pqxx/compiler-internal-post.hxx"
00723 
00724 #endif
00725 

Generated on Sun Nov 2 08:25:40 2008 for libpqxx by  doxygen 1.5.5