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-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   PGSTD::string Reason(int err) const;
00140 
00141 private:
00142   oid m_ID;
00143 };
00144 
00145 
00146 // TODO: New hierarchy with separate read / write / mixed-mode access
00147 
00149 class PQXX_LIBEXPORT largeobjectaccess : private largeobject
00150 {
00151 public:
00152   using largeobject::size_type;
00153   typedef long off_type;
00154   typedef size_type pos_type;
00155 
00157 
00161   typedef PGSTD::ios::openmode openmode;
00162 
00164 
00168   typedef PGSTD::ios::seekdir seekdir;
00169 
00171 
00175   explicit largeobjectaccess(dbtransaction &T,
00176                              openmode mode =
00177                                 PGSTD::ios::in |
00178                                 PGSTD::ios::out);                       //[t51]
00179 
00181 
00187   largeobjectaccess(dbtransaction &T,
00188                     oid O,
00189                     openmode mode =
00190                         PGSTD::ios::in |
00191                         PGSTD::ios::out);                               //[t52]
00192 
00194 
00199   largeobjectaccess(dbtransaction &T,
00200                     largeobject O,
00201                     openmode mode = PGSTD::ios::in | PGSTD::ios::out);  //[t50]
00202 
00204 
00209   largeobjectaccess(dbtransaction &T,
00210                     const PGSTD::string &File,
00211                     openmode mode =
00212                         PGSTD::ios::in | PGSTD::ios::out);              //[t55]
00213 
00214   ~largeobjectaccess() throw () { close(); }
00215 
00217 
00220   using largeobject::id;
00221 
00223 
00226   void to_file(const PGSTD::string &File) const                         //[t54]
00227         { largeobject::to_file(m_Trans, File); }
00228 
00229 #ifdef PQXX_BROKEN_USING_DECL
00231 
00235   void to_file(dbtransaction &T, const PGSTD::string &F) const
00236         { largeobject::to_file(T, F); }
00237 #else
00238   using largeobject::to_file;
00239 #endif
00240 
00245 
00246 
00250   void write(const char Buf[], size_type Len);                          //[t51]
00251 
00253 
00256   void write(const PGSTD::string &Buf)                                  //[t50]
00257         { write(Buf.c_str(), static_cast<size_type>(Buf.size())); }
00258 
00260 
00266   size_type read(char Buf[], size_type Len);                            //[t50]
00267 
00269 
00272   size_type seek(size_type dest, seekdir dir);                          //[t51]
00273 
00275 
00278   size_type tell() const;                                               //[t50]
00280 
00290 
00291 
00299   pos_type cseek(off_type dest, seekdir dir) throw ();                  //[t50]
00300 
00302 
00308   off_type cwrite(const char Buf[], size_type Len) throw ();            //[t50]
00309 
00311 
00317   off_type cread(char Buf[], size_type Len) throw ();                   //[t50]
00318 
00320 
00324   pos_type ctell() const throw ();                                      //[t50]
00326 
00331 
00332   void process_notice(const PGSTD::string &) throw ();                  //[t50]
00334 
00335   using largeobject::remove;
00336 
00337   using largeobject::operator==;
00338   using largeobject::operator!=;
00339   using largeobject::operator<;
00340   using largeobject::operator<=;
00341   using largeobject::operator>;
00342   using largeobject::operator>=;
00343 
00344 private:
00345   PGSTD::string PQXX_PRIVATE Reason(int err) const;
00346   internal::pq::PGconn *RawConnection() const
00347         { return largeobject::RawConnection(m_Trans); }
00348 
00349   void open(openmode mode);
00350   void close() throw ();
00351 
00352   dbtransaction &m_Trans;
00353   int m_fd;
00354 
00355   // Not allowed:
00356   largeobjectaccess();
00357   largeobjectaccess(const largeobjectaccess &);
00358   largeobjectaccess operator=(const largeobjectaccess &);
00359 };
00360 
00361 
00363 
00371 template<typename CHAR=char, typename TRAITS=PGSTD::char_traits<CHAR> >
00372   class largeobject_streambuf :
00373 #ifdef PQXX_HAVE_STREAMBUF
00374     public PGSTD::basic_streambuf<CHAR, TRAITS>
00375 #else
00376     public PGSTD::streambuf
00377 #endif
00378 {
00379   typedef long size_type;
00380 public:
00381   typedef CHAR   char_type;
00382   typedef TRAITS traits_type;
00383   typedef typename traits_type::int_type int_type;
00384 #ifdef PQXX_HAVE_STREAMBUF
00385   typedef typename traits_type::pos_type pos_type;
00386   typedef typename traits_type::off_type off_type;
00387 #else
00388   typedef streamoff off_type;
00389   typedef streampos pos_type;
00390 #endif
00391   typedef largeobjectaccess::openmode openmode;
00392   typedef largeobjectaccess::seekdir seekdir;
00393 
00394   largeobject_streambuf(dbtransaction &T,
00395                         largeobject O,
00396                         openmode mode = PGSTD::ios::in | PGSTD::ios::out,
00397                         size_type BufSize=512) :                        //[t48]
00398     m_BufSize(BufSize),
00399     m_Obj(T, O),
00400     m_G(0),
00401     m_P(0)
00402         { initialize(mode); }
00403 
00404   largeobject_streambuf(dbtransaction &T,
00405                         oid O,
00406                         openmode mode = PGSTD::ios::in | PGSTD::ios::out,
00407                         size_type BufSize=512) :                        //[t48]
00408     m_BufSize(BufSize),
00409     m_Obj(T, O),
00410     m_G(0),
00411     m_P(0)
00412         { initialize(mode); }
00413 
00414   virtual ~largeobject_streambuf() throw () { delete [] m_P; delete [] m_G; }
00415 
00416 
00418   void process_notice(const PGSTD::string &s) { m_Obj.process_notice(s); }
00419 
00420 #ifdef PQXX_HAVE_STREAMBUF
00421 protected:
00422 #endif
00423   virtual int sync()
00424   {
00425     // setg() sets eback, gptr, egptr
00426     setg(this->eback(), this->eback(), this->egptr());
00427     return overflow(EoF());
00428   }
00429 
00430 protected:
00431   virtual pos_type seekoff(off_type offset,
00432                            seekdir dir,
00433                            openmode)
00434   {
00435     return AdjustEOF(m_Obj.cseek(largeobjectaccess::off_type(offset), dir));
00436   }
00437 
00438   virtual pos_type seekpos(pos_type pos, openmode)
00439   {
00440     const largeobjectaccess::pos_type newpos = m_Obj.cseek(
00441         largeobjectaccess::off_type(pos),
00442         PGSTD::ios::beg);
00443     return AdjustEOF(newpos);
00444   }
00445 
00446   virtual int_type overflow(int_type ch = EoF())
00447   {
00448     char *const pp = this->pptr();
00449     if (!pp) return EoF();
00450     char *const pb = this->pbase();
00451     int_type res = 0;
00452 
00453     if (pp > pb) res = int_type(AdjustEOF(m_Obj.cwrite(pb, pp-pb)));
00454     setp(m_P, m_P + m_BufSize);
00455 
00456     // Write that one more character, if it's there.
00457     if (ch != EoF())
00458     {
00459       *this->pptr() = char(ch);
00460       this->pbump(1);
00461     }
00462     return res;
00463   }
00464 
00465   virtual int_type underflow()
00466   {
00467     if (!this->gptr()) return EoF();
00468     char *const eb = this->eback();
00469     const int_type res(static_cast<int_type>(AdjustEOF(m_Obj.cread(this->eback(), m_BufSize))));
00470     setg(eb, eb, eb + ((res==EoF()) ? 0 : res));
00471     return (!res || (res == EoF())) ? EoF() : *eb;
00472   }
00473 
00474 private:
00476   static int_type EoF() { return traits_type::eof(); }
00477 
00479   template<typename INTYPE>
00480   static PGSTD::streampos AdjustEOF(INTYPE pos)
00481         { return (pos==-1) ? PGSTD::streampos(EoF()) : PGSTD::streampos(pos); }
00482 
00483   void initialize(openmode mode)
00484   {
00485     if (mode & PGSTD::ios::in)
00486     {
00487       m_G = new char_type[m_BufSize];
00488       setg(m_G, m_G, m_G);
00489     }
00490     if (mode & PGSTD::ios::out)
00491     {
00492       m_P = new char_type[m_BufSize];
00493       setp(m_P, m_P + m_BufSize);
00494     }
00495   }
00496 
00497   const size_type m_BufSize;
00498   largeobjectaccess m_Obj;
00499 
00500   // Get & put buffers
00501   char_type *m_G, *m_P;
00502 };
00503 
00504 
00506 
00514 template<typename CHAR=char, typename TRAITS=PGSTD::char_traits<CHAR> >
00515   class basic_ilostream :
00516 #ifdef PQXX_HAVE_STREAMBUF
00517     public PGSTD::basic_istream<CHAR, TRAITS>
00518 #else
00519     public PGSTD::istream
00520 #endif
00521 {
00522 #ifdef PQXX_HAVE_STREAMBUF
00523   typedef PGSTD::basic_istream<CHAR, TRAITS> super;
00524 #else
00525   typedef PGSTD::istream super;
00526 #endif
00527 
00528 public:
00529   typedef CHAR char_type;
00530   typedef TRAITS traits_type;
00531   typedef typename traits_type::int_type int_type;
00532   typedef typename traits_type::pos_type pos_type;
00533   typedef typename traits_type::off_type off_type;
00534 
00536 
00541   basic_ilostream(dbtransaction &T,
00542                   largeobject O,
00543                   largeobject::size_type BufSize=512) :                 //[t57]
00544     super(0),
00545     m_Buf(T, O, PGSTD::ios::in, BufSize)
00546         { super::init(&m_Buf); }
00547 
00549 
00554   basic_ilostream(dbtransaction &T,
00555                   oid O,
00556                   largeobject::size_type BufSize=512) :                 //[t48]
00557     super(0),
00558     m_Buf(T, O, PGSTD::ios::in, BufSize)
00559         { super::init(&m_Buf); }
00560 
00561 private:
00562   largeobject_streambuf<CHAR,TRAITS> m_Buf;
00563 };
00564 
00565 typedef basic_ilostream<char> ilostream;
00566 
00567 
00569 
00577 template<typename CHAR=char, typename TRAITS=PGSTD::char_traits<CHAR> >
00578   class basic_olostream :
00579 #ifdef PQXX_HAVE_STREAMBUF
00580     public PGSTD::basic_ostream<CHAR, TRAITS>
00581 #else
00582     public PGSTD::ostream
00583 #endif
00584 {
00585 #ifdef PQXX_HAVE_STREAMBUF
00586   typedef PGSTD::basic_ostream<CHAR, TRAITS> super;
00587 #else
00588   typedef PGSTD::ostream super;
00589 #endif
00590 public:
00591   typedef CHAR char_type;
00592   typedef TRAITS traits_type;
00593   typedef typename traits_type::int_type int_type;
00594   typedef typename traits_type::pos_type pos_type;
00595   typedef typename traits_type::off_type off_type;
00596 
00598 
00603   basic_olostream(dbtransaction &T,
00604                   largeobject O,
00605                   largeobject::size_type BufSize=512) :                 //[t48]
00606     super(0),
00607     m_Buf(T, O, PGSTD::ios::out, BufSize)
00608         { super::init(&m_Buf); }
00609 
00611 
00616   basic_olostream(dbtransaction &T,
00617                   oid O,
00618                   largeobject::size_type BufSize=512) :                 //[t57]
00619     super(0),
00620     m_Buf(T, O, PGSTD::ios::out, BufSize)
00621         { super::init(&m_Buf); }
00622 
00623   ~basic_olostream()
00624   {
00625     try
00626     {
00627 #ifdef PQXX_HAVE_STREAMBUF
00628       m_Buf.pubsync(); m_Buf.pubsync();
00629 #else
00630       m_Buf.sync(); m_Buf.sync();
00631 #endif
00632     }
00633     catch (const PGSTD::exception &e)
00634     {
00635       m_Buf.process_notice(e.what());
00636     }
00637   }
00638 
00639 private:
00640   largeobject_streambuf<CHAR,TRAITS> m_Buf;
00641 };
00642 
00643 typedef basic_olostream<char> olostream;
00644 
00645 
00647 
00655 template<typename CHAR=char, typename TRAITS=PGSTD::char_traits<CHAR> >
00656   class basic_lostream :
00657 #ifdef PQXX_HAVE_STREAMBUF
00658     public PGSTD::basic_iostream<CHAR, TRAITS>
00659 #else
00660     public PGSTD::iostream
00661 #endif
00662 {
00663 #ifdef PQXX_HAVE_STREAMBUF
00664   typedef PGSTD::basic_iostream<CHAR, TRAITS> super;
00665 #else
00666   typedef PGSTD::iostream super;
00667 #endif
00668 
00669 public:
00670   typedef CHAR char_type;
00671   typedef TRAITS traits_type;
00672   typedef typename traits_type::int_type int_type;
00673   typedef typename traits_type::pos_type pos_type;
00674   typedef typename traits_type::off_type off_type;
00675 
00677 
00682   basic_lostream(dbtransaction &T,
00683                  largeobject O,
00684                  largeobject::size_type BufSize=512) :                  //[t59]
00685     super(0),
00686     m_Buf(T, O, PGSTD::ios::in | PGSTD::ios::out, BufSize)
00687         { super::init(&m_Buf); }
00688 
00690 
00695   basic_lostream(dbtransaction &T,
00696                  oid O,
00697                  largeobject::size_type BufSize=512) :                  //[t59]
00698     super(0),
00699     m_Buf(T, O, PGSTD::ios::in | PGSTD::ios::out, BufSize)
00700         { super::init(&m_Buf); }
00701 
00702   ~basic_lostream()
00703   {
00704     try
00705     {
00706 #ifdef PQXX_HAVE_STREAMBUF
00707       m_Buf.pubsync(); m_Buf.pubsync();
00708 #else
00709       m_Buf.sync(); m_Buf.sync();
00710 #endif
00711     }
00712     catch (const PGSTD::exception &e)
00713     {
00714       m_Buf.process_notice(e.what());
00715     }
00716   }
00717 
00718 private:
00719   largeobject_streambuf<CHAR,TRAITS> m_Buf;
00720 };
00721 
00722 typedef basic_lostream<char> lostream;
00723 
00724 } // namespace pqxx
00725 
00726 #include "pqxx/compiler-internal-post.hxx"
00727 
00728 #endif
00729 

Generated on Mon Feb 15 18:22:41 2010 for libpqxx by  doxygen 1.5.5