Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members  

largeobject.h

Go to the documentation of this file.
00001 /*-------------------------------------------------------------------------
00002  *
00003  *   FILE
00004  *      pqxx/largeobject.h
00005  *
00006  *   DESCRIPTION
00007  *      libpqxx's Large Objects interface
00008  *   Allows access to large objects directly, or through I/O streams
00009  *
00010  * Copyright (c) 2003, Jeroen T. Vermeulen <jtv@xs4all.nl>
00011  *
00012  *-------------------------------------------------------------------------
00013  */
00014 #ifndef PQXX_LARGEOBJECT_H
00015 #define PQXX_LARGEOBJECT_H
00016 
00017 #include <streambuf>
00018 
00019 #include <pqxx/transactionitf.h>
00020 
00021 
00022 namespace pqxx
00023 {
00024 
00025 class LargeObjectAccess;
00026 
00027 
00029 
00036 class LargeObject
00037 {
00038 public:
00039   typedef long size_type;
00040 
00042   LargeObject();                                                        //[t48]
00043 
00045 
00047   explicit LargeObject(TransactionItf &T);                              //[t48]
00048 
00050 
00054   explicit LargeObject(Oid O) : m_ID(O) {}                              //[t48]
00055 
00057 
00061   LargeObject(TransactionItf &T, const PGSTD::string &File);            //[t53]
00062 
00064 
00068   LargeObject(const LargeObjectAccess &O);                              //[t50]
00069 
00071 
00074   Oid id() const throw () { return m_ID; }                              //[t48]
00075 
00077   bool operator==(const LargeObject &other) const                       //[t51]
00078           { return m_ID == other.m_ID; }
00080   bool operator!=(const LargeObject &other) const                       //[t51]
00081           { return m_ID != other.m_ID; }
00083   bool operator<=(const LargeObject &other) const                       //[t51]
00084           { return m_ID <= other.m_ID; }
00086   bool operator>=(const LargeObject &other) const                       //[t51]
00087           { return m_ID >= other.m_ID; }
00089   bool operator<(const LargeObject &other) const                        //[t51]
00090           { return m_ID < other.m_ID; }
00092   bool operator>(const LargeObject &other) const                        //[t51]
00093           { return m_ID > other.m_ID; }
00094 
00096 
00100   void to_file(TransactionItf &T, const PGSTD::string &File) const;     //[t52]
00101 
00103 
00107   void remove(TransactionItf &T) const;                                 //[t48]
00108 
00109 protected:
00110   static PGconn *RawConnection(const TransactionItf &T)
00111   {
00112     return T.Conn().RawConnection();
00113   }
00114 
00115   PGSTD::string Reason() const;
00116 
00117 private:
00118   Oid m_ID;
00119 };
00120 
00121 
00123 class LargeObjectAccess : private LargeObject
00124 {
00125 public:
00126   using LargeObject::size_type;
00127 
00129 
00133   explicit LargeObjectAccess(TransactionItf &T, 
00134                              PGSTD::ios_base::openmode mode = 
00135                                 PGSTD::ios_base::in | 
00136                                 PGSTD::ios_base::out);                  //[t51]
00137 
00139 
00145   LargeObjectAccess(TransactionItf &T, 
00146                     Oid O,
00147                     PGSTD::ios_base::openmode mode = 
00148                         PGSTD::ios_base::in | 
00149                         PGSTD::ios_base::out);                          //[t52]
00150 
00152 
00157   LargeObjectAccess(TransactionItf &T, 
00158                     LargeObject O,
00159                     PGSTD::ios_base::openmode mode = 
00160                                 PGSTD::ios_base::in | 
00161                                 PGSTD::ios_base::out);                  //[t50]
00162 
00164 
00169   LargeObjectAccess(TransactionItf &T, 
00170                     const PGSTD::string &File,
00171                     PGSTD::ios_base::openmode mode = 
00172                         PGSTD::ios_base::in | PGSTD::ios_base::out);    //[t55]
00173 
00174   ~LargeObjectAccess() { close(); }
00175 
00177 
00180   using LargeObject::id;
00181 
00183 
00186   void to_file(const PGSTD::string &File) const                         //[t54]
00187   { 
00188     LargeObject::to_file(m_Trans, File); 
00189   }
00190 
00192 
00196   void write(const char Buf[], size_type Len);                          //[t51]
00197 
00199 
00202   void write(const PGSTD::string &Buf)                                  //[t50]
00203         { write(Buf.c_str(), Buf.size()); }
00204 
00206 
00212   size_type read(char Buf[], size_type Len);                            //[t50]
00213 
00215 
00218   size_type seek(size_type dest, PGSTD::ios_base::seekdir dir);         //[t51]
00219 
00221 
00229   long cseek(long dest, PGSTD::ios_base::seekdir dir) throw ();         //[t50]
00230     
00232 
00238   long cwrite(const char Buf[], size_type Len) throw ();                //[t50]
00239 
00241 
00247   long cread(char Buf[], size_type Len) throw ();                       //[t50]
00248 
00249   using LargeObject::operator==;
00250   using LargeObject::operator!=;
00251   using LargeObject::operator<;
00252   using LargeObject::operator<=;
00253   using LargeObject::operator>;
00254   using LargeObject::operator>=;
00255 
00256 private:
00257   PGSTD::string Reason() const;
00258   PGconn *RawConnection() { return LargeObject::RawConnection(m_Trans); }
00259 
00260   void open(PGSTD::ios_base::openmode mode);
00261   void close();
00262 
00263   TransactionItf &m_Trans;
00264   int m_fd;
00265 
00266   // Not allowed:
00267   LargeObjectAccess();
00268   LargeObjectAccess(const LargeObjectAccess &);
00269   LargeObjectAccess operator=(const LargeObjectAccess &);
00270 };
00271 
00272 
00274 
00279 template<typename CHAR=char, typename TRAITS=PGSTD::char_traits<CHAR> >
00280 class largeobject_streambuf : public PGSTD::basic_streambuf<CHAR, TRAITS>
00281 {
00282   typedef long size_type;
00283 public:
00284   typedef CHAR   char_type;
00285   typedef TRAITS traits_type;
00286   typedef typename traits_type::int_type int_type;
00287   typedef typename traits_type::pos_type pos_type;
00288   typedef typename traits_type::off_type off_type;
00289 
00290   largeobject_streambuf(TransactionItf &T,
00291                         LargeObject O,
00292                         PGSTD::ios_base::openmode mode = 
00293                                 PGSTD::ios::in | PGSTD::ios::out,
00294                         size_type BufSize=512) :                        //[t48]
00295     m_BufSize(BufSize),
00296     m_Obj(T, O),
00297     m_G(0),
00298     m_P(0)
00299   {
00300     initialize(mode);
00301   }
00302 
00303   largeobject_streambuf(TransactionItf &T,
00304                         Oid O,
00305                         PGSTD::ios_base::openmode mode = 
00306                                 PGSTD::ios::in | PGSTD::ios::out,
00307                         size_type BufSize=512) :                        //[t48]
00308     m_BufSize(BufSize),
00309     m_Obj(T, O),
00310     m_G(0),
00311     m_P(0)
00312   {
00313     initialize(mode);
00314   }
00315 
00316   virtual ~largeobject_streambuf()
00317   {
00318     delete [] m_P;
00319     delete [] m_G;
00320   }
00321 
00322 
00323 protected:
00324   virtual int sync()
00325   {
00326     // setg() sets eback, gptr, egptr
00327     setg(eback(), eback(), egptr());
00328     return overflow(EoF());
00329   }
00330 
00331   virtual pos_type seekoff(off_type offset, 
00332                            PGSTD::ios_base::seekdir dir,
00333                            PGSTD::ios_base::openmode mode =
00334                                 PGSTD::ios_base::in|PGSTD::ios_base::out)
00335   {
00336     if (!mode) {}       // Quench "unused parameter" warning
00337     return AdjustEOF(m_Obj.cseek(offset, dir));
00338   }
00339 
00340   virtual pos_type seekpos(pos_type pos, 
00341                            PGSTD::ios_base::openmode mode =
00342                                 PGSTD::ios_base::in|PGSTD::ios_base::out)
00343   {
00344     if (!mode) {}       // Quench "unused parameter" warning
00345     return AdjustEOF(m_Obj.cseek(pos, PGSTD::ios_base::beg));
00346   }
00347 
00348   virtual int_type overflow(int_type ch = EoF())
00349   {
00350     char *const pp = pptr();
00351     if (!pp) return EoF();
00352     char *const pb = pbase();
00353     int_type result = 0;
00354 
00355     if (pp > pb) result = AdjustEOF(m_Obj.cwrite(pb, pp-pb));
00356     setp(m_P, m_P + m_BufSize);
00357 
00358     // Write that one more character, if it's there.
00359     if (ch != EoF())
00360     {
00361       *pptr() = char(ch);
00362       pbump(1);
00363     }
00364     return result;
00365   }
00366 
00367   virtual int_type underflow()
00368   {
00369     if (!gptr()) return EoF();
00370     char *const eb = eback();
00371     const int result = AdjustEOF(m_Obj.cread(eback(), m_BufSize));
00372     setg(eb, eb, eb + ((result==EoF()) ? 0 : result));
00373     return (!result || (result == EoF())) ? EoF() : *eb;
00374   }
00375 
00376 private:
00378   static int_type EoF() { return traits_type::eof(); }
00379 
00381   static PGSTD::streampos AdjustEOF(int pos)
00382   {
00383     return (pos == -1) ? EoF() : pos;
00384   }
00385 
00386   void initialize(PGSTD::ios_base::openmode mode)
00387   {
00388     if (mode & PGSTD::ios_base::in) 
00389     {
00390       m_G = new char_type[m_BufSize];
00391       setg(m_G, m_G, m_G);
00392     }
00393     if (mode & PGSTD::ios_base::out)
00394     {
00395       m_P = new char_type[m_BufSize];
00396       setp(m_P, m_P + m_BufSize);
00397     }
00398   }
00399 
00400   const size_type m_BufSize;
00401   LargeObjectAccess m_Obj;
00402 
00403   // Get & put buffers
00404   char_type *m_G, *m_P;
00405 };
00406 
00407 
00409 
00416 template<typename CHAR=char, typename TRAITS=PGSTD::char_traits<CHAR> > 
00417 class basic_ilostream : public PGSTD::basic_istream<CHAR, TRAITS>
00418 {
00419 public:
00420   typedef CHAR char_type;
00421   typedef TRAITS traits_type;
00422   typedef typename traits_type::int_type int_type;
00423   typedef typename traits_type::pos_type pos_type;
00424   typedef typename traits_type::off_type off_type;
00425 
00427 
00431   basic_ilostream(TransactionItf &T, 
00432                   LargeObject O, 
00433                   LargeObject::size_type BufSize=512) :                 //[]
00434     PGSTD::basic_istream<CHAR,TRAITS>(&m_Buf),
00435     m_Buf(T, O, in, BufSize) 
00436   { 
00437   }
00438 
00440 
00444   basic_ilostream(TransactionItf &T, 
00445                   Oid O, 
00446                   LargeObject::size_type BufSize=512) :                 //[t48]
00447     PGSTD::basic_istream<CHAR,TRAITS>(&m_Buf),
00448     m_Buf(T, O, in, BufSize) 
00449   { 
00450   }
00451 
00452 private:
00453   largeobject_streambuf<CHAR,TRAITS> m_Buf;
00454 };
00455 
00456 typedef basic_ilostream<char> ilostream;
00457 
00458 
00460 
00467 template<typename CHAR=char, typename TRAITS=PGSTD::char_traits<CHAR> > 
00468 class basic_olostream : public PGSTD::basic_ostream<CHAR, TRAITS>
00469 {
00470 public:
00471   typedef CHAR char_type;
00472   typedef TRAITS traits_type;
00473   typedef typename traits_type::int_type int_type;
00474   typedef typename traits_type::pos_type pos_type;
00475   typedef typename traits_type::off_type off_type;
00476 
00478 
00482   basic_olostream(TransactionItf &T, 
00483                   LargeObject O,
00484                   LargeObject::size_type BufSize=512) :                 //[t48]
00485     PGSTD::basic_ostream<CHAR,TRAITS>(&m_Buf),
00486     m_Buf(T, O, out, BufSize) 
00487   { 
00488   }
00489 
00491 
00495   basic_olostream(TransactionItf &T, 
00496                   Oid O,
00497                   LargeObject::size_type BufSize=512) :                 //[]
00498     PGSTD::basic_ostream<CHAR,TRAITS>(&m_Buf),
00499     m_Buf(T, O, out, BufSize) 
00500   { 
00501   }
00502 
00503   ~basic_olostream() { m_Buf.pubsync(); m_Buf.pubsync(); }
00504 
00505 private:
00506   largeobject_streambuf<CHAR,TRAITS> m_Buf;
00507 };
00508 
00509 typedef basic_olostream<char> olostream;
00510 
00511 
00513 
00520 template<typename CHAR=char, typename TRAITS=PGSTD::char_traits<CHAR> > 
00521 class basic_lostream : public PGSTD::basic_iostream<CHAR, TRAITS>
00522 {
00523 public:
00524   typedef CHAR char_type;
00525   typedef TRAITS traits_type;
00526   typedef typename traits_type::int_type int_type;
00527   typedef typename traits_type::pos_type pos_type;
00528   typedef typename traits_type::off_type off_type;
00529 
00531 
00535   basic_lostream(TransactionItf &T, 
00536                  LargeObject O,
00537                  LargeObject::size_type BufSize=512) :                  //[]
00538     PGSTD::basic_iostream<CHAR,TRAITS>(&m_Buf),
00539     m_Buf(T, O, in | out, BufSize) 
00540   { 
00541   }
00542 
00544 
00548   basic_lostream(TransactionItf &T, 
00549                  Oid O,
00550                  LargeObject::size_type BufSize=512) :                  //[]
00551     PGSTD::basic_iostream<CHAR,TRAITS>(&m_Buf),
00552     m_Buf(T, O, in | out, BufSize) 
00553   { 
00554   }
00555 
00556   ~basic_lostream() { m_Buf.pubsync(); m_Buf.pubsync(); }
00557 
00558 private:
00559   largeobject_streambuf<CHAR,TRAITS> m_Buf;
00560 };
00561 
00562 typedef basic_lostream<char> lostream;
00563 
00564 }
00565 
00566 #endif
00567 

Generated on Sun May 4 06:03:41 2003 for libpqxx by doxygen1.3-rc3