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-2015, 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 #include <streambuf>
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() PQXX_NOEXCEPT;                                          //[t48]
00050 
00052 
00054   explicit largeobject(dbtransaction &T);                               //[t48]
00055 
00057 
00061   explicit largeobject(oid O) PQXX_NOEXCEPT : m_ID(O) {}                //[t48]
00062 
00064 
00068   largeobject(dbtransaction &T, const std::string &File);               //[t53]
00069 
00071 
00075   largeobject(const largeobjectaccess &O) PQXX_NOEXCEPT;                //[t50]
00076 
00078 
00082   oid id() const PQXX_NOEXCEPT { return m_ID; }                         //[t48]
00083 
00092 
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; }
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 
00119 
00123   void to_file(dbtransaction &T, const std::string &File) const;        //[t52]
00124 
00126 
00130   void remove(dbtransaction &T) const;                                  //[t48]
00131 
00132 protected:
00133   PQXX_PURE static internal::pq::PGconn *RawConnection(const dbtransaction &T);
00134 
00135   std::string Reason(int err) const;
00136 
00137 private:
00138   oid m_ID;
00139 };
00140 
00141 
00142 // TODO: New hierarchy with separate read / write / mixed-mode access
00143 
00145 class PQXX_LIBEXPORT largeobjectaccess : private largeobject
00146 {
00147 public:
00148   using largeobject::size_type;
00149   typedef long off_type;
00150   typedef size_type pos_type;
00151 
00153 
00157   typedef std::ios::openmode openmode;
00158 
00160 
00164   typedef std::ios::seekdir seekdir;
00165 
00167 
00171   explicit largeobjectaccess(dbtransaction &T,
00172                              openmode mode=std::ios::in|std::ios::out); //[t51]
00173 
00175 
00181   largeobjectaccess(dbtransaction &T,
00182                     oid O,
00183                     openmode mode=std::ios::in|std::ios::out);          //[t52]
00184 
00186 
00191   largeobjectaccess(dbtransaction &T,
00192                     largeobject O,
00193                     openmode mode=std::ios::in|std::ios::out);          //[t50]
00194 
00196 
00201   largeobjectaccess(dbtransaction &T,
00202                     const std::string &File,
00203                     openmode mode=std::ios::in|std::ios::out);          //[t55]
00204 
00205   ~largeobjectaccess() PQXX_NOEXCEPT { close(); }
00206 
00208 
00211   using largeobject::id;
00212 
00214 
00217   void to_file(const std::string &File) const                           //[t54]
00218         { largeobject::to_file(m_Trans, File); }
00219 
00220   using largeobject::to_file;
00221 
00226 
00227 
00231   void write(const char Buf[], size_type Len);                          //[t51]
00232 
00234 
00237   void write(const std::string &Buf)                                    //[t50]
00238         { write(Buf.c_str(), static_cast<size_type>(Buf.size())); }
00239 
00241 
00247   size_type read(char Buf[], size_type Len);                            //[t50]
00248 
00250 
00253   size_type seek(size_type dest, seekdir dir);                          //[t51]
00254 
00256 
00259   size_type tell() const;                                               //[t50]
00261 
00271 
00272 
00280   pos_type cseek(off_type dest, seekdir dir) PQXX_NOEXCEPT;             //[t50]
00281 
00283 
00289   off_type cwrite(const char Buf[], size_type Len) PQXX_NOEXCEPT;       //[t50]
00290 
00292 
00298   off_type cread(char Buf[], size_type Len) PQXX_NOEXCEPT;              //[t50]
00299 
00301 
00305   pos_type ctell() const PQXX_NOEXCEPT;                                 //[t50]
00307 
00312 
00313   void process_notice(const std::string &) PQXX_NOEXCEPT;               //[t50]
00315 
00316   using largeobject::remove;
00317 
00318   using largeobject::operator==;
00319   using largeobject::operator!=;
00320   using largeobject::operator<;
00321   using largeobject::operator<=;
00322   using largeobject::operator>;
00323   using largeobject::operator>=;
00324 
00325 private:
00326   PQXX_PRIVATE std::string Reason(int err) const;
00327   internal::pq::PGconn *RawConnection() const
00328         { return largeobject::RawConnection(m_Trans); }
00329 
00330   void open(openmode mode);
00331   void close() PQXX_NOEXCEPT;
00332 
00333   dbtransaction &m_Trans;
00334   int m_fd;
00335 
00336   // Not allowed:
00337   largeobjectaccess() PQXX_DELETED_OP;
00338   largeobjectaccess(const largeobjectaccess &) PQXX_DELETED_OP;
00339   largeobjectaccess operator=(const largeobjectaccess &) PQXX_DELETED_OP;
00340 };
00341 
00342 
00344 
00352 template<typename CHAR=char, typename TRAITS=std::char_traits<CHAR> >
00353   class largeobject_streambuf :
00354     public std::basic_streambuf<CHAR, TRAITS>
00355 {
00356   typedef long size_type;
00357 public:
00358   typedef CHAR   char_type;
00359   typedef TRAITS traits_type;
00360   typedef typename traits_type::int_type int_type;
00361   typedef typename traits_type::pos_type pos_type;
00362   typedef typename traits_type::off_type off_type;
00363   typedef largeobjectaccess::openmode openmode;
00364   typedef largeobjectaccess::seekdir seekdir;
00365 
00366   largeobject_streambuf(dbtransaction &T,
00367                         largeobject O,
00368                         openmode mode=std::ios::in|std::ios::out,
00369                         size_type BufSize=512) :                        //[t48]
00370     m_BufSize(BufSize),
00371     m_Obj(T, O, mode),
00372     m_G(0),
00373     m_P(0)
00374         { initialize(mode); }
00375 
00376   largeobject_streambuf(dbtransaction &T,
00377                         oid O,
00378                         openmode mode=std::ios::in|std::ios::out,
00379                         size_type BufSize=512) :                        //[t48]
00380     m_BufSize(BufSize),
00381     m_Obj(T, O, mode),
00382     m_G(0),
00383     m_P(0)
00384         { initialize(mode); }
00385 
00386   virtual ~largeobject_streambuf() PQXX_NOEXCEPT
00387         { delete [] m_P; delete [] m_G; }
00388 
00389 
00391   void process_notice(const std::string &s) { m_Obj.process_notice(s); }
00392 
00393 protected:
00394   virtual int sync() PQXX_OVERRIDE
00395   {
00396     // setg() sets eback, gptr, egptr
00397     this->setg(this->eback(), this->eback(), this->egptr());
00398     return overflow(EoF());
00399   }
00400 
00401 protected:
00402   virtual pos_type seekoff(off_type offset,
00403                            seekdir dir,
00404                            openmode) PQXX_OVERRIDE
00405   {
00406     return AdjustEOF(m_Obj.cseek(largeobjectaccess::off_type(offset), dir));
00407   }
00408 
00409   virtual pos_type seekpos(pos_type pos, openmode) PQXX_OVERRIDE
00410   {
00411     const largeobjectaccess::pos_type newpos = m_Obj.cseek(
00412         largeobjectaccess::off_type(pos),
00413         std::ios::beg);
00414     return AdjustEOF(newpos);
00415   }
00416 
00417   virtual int_type overflow(int_type ch = EoF()) PQXX_OVERRIDE
00418   {
00419     char *const pp = this->pptr();
00420     if (!pp) return EoF();
00421     char *const pb = this->pbase();
00422     int_type res = 0;
00423 
00424     if (pp > pb) res = int_type(AdjustEOF(m_Obj.cwrite(pb, pp-pb)));
00425     this->setp(m_P, m_P + m_BufSize);
00426 
00427     // Write that one more character, if it's there.
00428     if (ch != EoF())
00429     {
00430       *this->pptr() = char(ch);
00431       this->pbump(1);
00432     }
00433     return res;
00434   }
00435 
00436   virtual int_type underflow() PQXX_OVERRIDE
00437   {
00438     if (!this->gptr()) return EoF();
00439     char *const eb = this->eback();
00440     const int_type res(static_cast<int_type>(
00441         AdjustEOF(m_Obj.cread(this->eback(), m_BufSize))));
00442     this->setg(eb, eb, eb + ((res==EoF()) ? 0 : res));
00443     return (!res || (res == EoF())) ? EoF() : *eb;
00444   }
00445 
00446 private:
00448   static int_type EoF() { return traits_type::eof(); }
00449 
00451   template<typename INTYPE>
00452   static std::streampos AdjustEOF(INTYPE pos)
00453         { return (pos==-1) ? std::streampos(EoF()) : std::streampos(pos); }
00454 
00455   void initialize(openmode mode)
00456   {
00457     if (mode & std::ios::in)
00458     {
00459       m_G = new char_type[unsigned(m_BufSize)];
00460       this->setg(m_G, m_G, m_G);
00461     }
00462     if (mode & std::ios::out)
00463     {
00464       m_P = new char_type[unsigned(m_BufSize)];
00465       this->setp(m_P, m_P + m_BufSize);
00466     }
00467   }
00468 
00469   const size_type m_BufSize;
00470   largeobjectaccess m_Obj;
00471 
00472   // Get & put buffers
00473   char_type *m_G, *m_P;
00474 };
00475 
00476 
00478 
00486 template<typename CHAR=char, typename TRAITS=std::char_traits<CHAR> >
00487   class basic_ilostream :
00488     public std::basic_istream<CHAR, TRAITS>
00489 {
00490   typedef std::basic_istream<CHAR, TRAITS> super;
00491 
00492 public:
00493   typedef CHAR char_type;
00494   typedef TRAITS traits_type;
00495   typedef typename traits_type::int_type int_type;
00496   typedef typename traits_type::pos_type pos_type;
00497   typedef typename traits_type::off_type off_type;
00498 
00500 
00505   basic_ilostream(dbtransaction &T,
00506                   largeobject O,
00507                   largeobject::size_type BufSize=512) :                 //[t57]
00508     super(0),
00509     m_Buf(T, O, std::ios::in, BufSize)
00510         { super::init(&m_Buf); }
00511 
00513 
00518   basic_ilostream(dbtransaction &T,
00519                   oid O,
00520                   largeobject::size_type BufSize=512) :                 //[t48]
00521     super(0),
00522     m_Buf(T, O, std::ios::in, BufSize)
00523         { super::init(&m_Buf); }
00524 
00525 private:
00526   largeobject_streambuf<CHAR,TRAITS> m_Buf;
00527 };
00528 
00529 typedef basic_ilostream<char> ilostream;
00530 
00531 
00533 
00541 template<typename CHAR=char, typename TRAITS=std::char_traits<CHAR> >
00542   class basic_olostream :
00543     public std::basic_ostream<CHAR, TRAITS>
00544 {
00545   typedef std::basic_ostream<CHAR, TRAITS> super;
00546 public:
00547   typedef CHAR char_type;
00548   typedef TRAITS traits_type;
00549   typedef typename traits_type::int_type int_type;
00550   typedef typename traits_type::pos_type pos_type;
00551   typedef typename traits_type::off_type off_type;
00552 
00554 
00559   basic_olostream(dbtransaction &T,
00560                   largeobject O,
00561                   largeobject::size_type BufSize=512) :                 //[t48]
00562     super(0),
00563     m_Buf(T, O, std::ios::out, BufSize)
00564         { super::init(&m_Buf); }
00565 
00567 
00572   basic_olostream(dbtransaction &T,
00573                   oid O,
00574                   largeobject::size_type BufSize=512) :                 //[t57]
00575     super(0),
00576     m_Buf(T, O, std::ios::out, BufSize)
00577         { super::init(&m_Buf); }
00578 
00579   ~basic_olostream()
00580   {
00581     try
00582     {
00583       m_Buf.pubsync(); m_Buf.pubsync();
00584     }
00585     catch (const std::exception &e)
00586     {
00587       m_Buf.process_notice(e.what());
00588     }
00589   }
00590 
00591 private:
00592   largeobject_streambuf<CHAR,TRAITS> m_Buf;
00593 };
00594 
00595 typedef basic_olostream<char> olostream;
00596 
00597 
00599 
00607 template<typename CHAR=char, typename TRAITS=std::char_traits<CHAR> >
00608   class basic_lostream :
00609     public std::basic_iostream<CHAR, TRAITS>
00610 {
00611   typedef std::basic_iostream<CHAR, TRAITS> super;
00612 
00613 public:
00614   typedef CHAR char_type;
00615   typedef TRAITS traits_type;
00616   typedef typename traits_type::int_type int_type;
00617   typedef typename traits_type::pos_type pos_type;
00618   typedef typename traits_type::off_type off_type;
00619 
00621 
00626   basic_lostream(dbtransaction &T,
00627                  largeobject O,
00628                  largeobject::size_type BufSize=512) :                  //[t59]
00629     super(0),
00630     m_Buf(T, O, std::ios::in | std::ios::out, BufSize)
00631         { super::init(&m_Buf); }
00632 
00634 
00639   basic_lostream(dbtransaction &T,
00640                  oid O,
00641                  largeobject::size_type BufSize=512) :                  //[t59]
00642     super(0),
00643     m_Buf(T, O, std::ios::in | std::ios::out, BufSize)
00644         { super::init(&m_Buf); }
00645 
00646   ~basic_lostream()
00647   {
00648     try
00649     {
00650       m_Buf.pubsync(); m_Buf.pubsync();
00651     }
00652     catch (const std::exception &e)
00653     {
00654       m_Buf.process_notice(e.what());
00655     }
00656   }
00657 
00658 private:
00659   largeobject_streambuf<CHAR,TRAITS> m_Buf;
00660 };
00661 
00662 typedef basic_lostream<char> lostream;
00663 
00664 } // namespace pqxx
00665 
00666 #include "pqxx/compiler-internal-post.hxx"
00667 
00668 #endif
00669 

Generated on 17 Mar 2017 for libpqxx by  doxygen 1.6.1