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);            //[]
00062 
00064 
00068   LargeObject(const LargeObjectAccess &O);                              //[]
00069 
00071 
00074   Oid id() const throw () { return m_ID; }                              //[t48]
00075 
00077   bool operator==(const LargeObject &other) const                       //[]
00078           { return m_ID == other.m_ID; }
00080   bool operator!=(const LargeObject &other) const                       //[]
00081           { return m_ID != other.m_ID; }
00083   bool operator<=(const LargeObject &other) const                       //[]
00084           { return m_ID <= other.m_ID; }
00086   bool operator>=(const LargeObject &other) const                       //[]
00087           { return m_ID >= other.m_ID; }
00089   bool operator<(const LargeObject &other) const                        //[]
00090           { return m_ID < other.m_ID; }
00092   bool operator>(const LargeObject &other) const                        //[]
00093           { return m_ID > other.m_ID; }
00094 
00096 
00100   void to_file(TransactionItf &T, const char File[]) const;             //[]
00101 
00103 
00107   void to_file(TransactionItf &T, const PGSTD::string &File) const      //[]
00108   { 
00109     to_file(T, File.c_str()); 
00110   }
00111 
00113 
00117   void remove(TransactionItf &T) const;                                 //[t48]
00118 
00119 protected:
00120   static PGconn *RawConnection(const TransactionItf &T)
00121   {
00122     return T.Conn().RawConnection();
00123   }
00124 
00125 private:
00126   Oid m_ID;
00127 };
00128 
00129 
00131 class LargeObjectAccess : private LargeObject
00132 {
00133 public:
00134   using LargeObject::size_type;
00135 
00137 
00141   explicit LargeObjectAccess(TransactionItf &T, 
00142                              PGSTD::ios_base::openmode mode = 
00143                                 PGSTD::ios_base::in | 
00144                                 PGSTD::ios_base::out);                  //[]
00145 
00147 
00153   explicit LargeObjectAccess(TransactionItf &T, 
00154                              Oid O,
00155                              PGSTD::ios_base::openmode mode = 
00156                                 PGSTD::ios_base::in | 
00157                                 PGSTD::ios_base::out);                  //[]
00158 
00160 
00165   explicit LargeObjectAccess(TransactionItf &T, 
00166                              LargeObject O,
00167                              PGSTD::ios_base::openmode mode = 
00168                                 PGSTD::ios_base::in | 
00169                                 PGSTD::ios_base::out);                  //[]
00170 
00172 
00177   LargeObjectAccess(TransactionItf &T, 
00178                     const PGSTD::string &File,
00179                     PGSTD::ios_base::openmode mode = 
00180                         PGSTD::ios_base::in | PGSTD::ios_base::out);    //[]
00181 
00182   ~LargeObjectAccess() { close(); }
00183 
00185 
00188   using LargeObject::id;
00189 
00191 
00194   void to_file(const char File[]) const 
00195   { 
00196     LargeObject::to_file(m_Trans, File); 
00197   }
00198 
00200 
00203   void to_file(const PGSTD::string &File) const 
00204   { 
00205     LargeObject::to_file(m_Trans, File); 
00206   }
00207 
00209 
00213   void write(const char Buf[], size_type Len);
00214 
00216 
00219   void write(const PGSTD::string &Buf) 
00220         { write(Buf.c_str(), Buf.size()); }
00221 
00223 
00229   size_type read(char Buf[], size_type Len);
00230 
00231   // TODO: Document return value
00233   /** Does not throw exception in case of error; inspect return value instead.
00234    * @param dest offset to go to
00235    * @param dir origin to which dest is relative: ios_base::beg (from beginning 
00236    *        of the object), ios_base::cur (from current access position), or
00237    *        ios_base;:end (from end of object)
00238    */
00239   long cseek(long dest, PGSTD::ios_base::seekdir dir) throw ();
00240     
00242 
00247   long cwrite(const char Buf[], size_type Len) throw ();
00248 
00250 
00255   long cread(char Buf[], size_type Len) throw ();
00256 
00257   using LargeObject::operator==;
00258   using LargeObject::operator!=;
00259   using LargeObject::operator<;
00260   using LargeObject::operator<=;
00261   using LargeObject::operator>;
00262   using LargeObject::operator>=;
00263 
00264 private:
00265   PGconn *RawConnection() { return LargeObject::RawConnection(m_Trans); }
00266 
00267   void open(PGSTD::ios_base::openmode mode);
00268   void close();
00269 
00270   TransactionItf &m_Trans;
00271   int m_fd;
00272 
00273   // Not allowed:
00274   LargeObjectAccess();
00275   LargeObjectAccess(const LargeObjectAccess &);
00276   LargeObjectAccess operator=(const LargeObjectAccess &);
00277 };
00278 
00279 
00281 
00288 template<typename CHAR=char, typename TRAITS=PGSTD::char_traits<CHAR> >
00289 class largeobject_streambuf : public PGSTD::basic_streambuf<CHAR, TRAITS>
00290 {
00291   typedef long size_type;
00292 public:
00293   typedef CHAR   char_type;
00294   typedef TRAITS traits_type;
00295   typedef typename traits_type::int_type int_type;
00296   typedef typename traits_type::pos_type pos_type;
00297   typedef typename traits_type::off_type off_type;
00298 
00299   largeobject_streambuf(TransactionItf &T,
00300                         LargeObject O,
00301                         PGSTD::ios_base::openmode mode = 
00302                                 PGSTD::ios::in | PGSTD::ios::out,
00303                         size_type BufSize=512) :                        //[t48]
00304     m_BufSize(BufSize),
00305     m_Obj(T, O),
00306     m_G(0),
00307     m_P(0)
00308   {
00309     initialize(mode);
00310   }
00311 
00312   largeobject_streambuf(TransactionItf &T,
00313                         Oid O,
00314                         PGSTD::ios_base::openmode mode = 
00315                                 PGSTD::ios::in | PGSTD::ios::out,
00316                         size_type BufSize=512) :                        //[t48]
00317     m_BufSize(BufSize),
00318     m_Obj(T, O),
00319     m_G(0),
00320     m_P(0)
00321   {
00322     initialize(mode);
00323   }
00324 
00325   virtual ~largeobject_streambuf()
00326   {
00327     delete [] m_P;
00328     delete [] m_G;
00329   }
00330 
00331 
00332 protected:
00333   virtual int sync()
00334   {
00335     // setg() sets eback, gptr, egptr
00336     setg(eback(), eback(), egptr());
00337     return overflow(EoF());
00338   }
00339 
00340   virtual pos_type seekoff(off_type offset, 
00341                            PGSTD::ios_base::seekdir dir,
00342                            PGSTD::ios_base::openmode mode =
00343                                 PGSTD::ios_base::in|PGSTD::ios_base::out)
00344   {
00345     if (!mode) {}       // Quench "unused parameter" warning
00346     return AdjustEOF(m_Obj.cseek(offset, dir));
00347   }
00348 
00349   virtual pos_type seekpos(pos_type pos, 
00350                            PGSTD::ios_base::openmode mode =
00351                                 PGSTD::ios_base::in|PGSTD::ios_base::out)
00352   {
00353     if (!mode) {}       // Quench "unused parameter" warning
00354     return AdjustEOF(m_Obj.cseek(pos, PGSTD::ios_base::beg));
00355   }
00356 
00357   virtual int_type overflow(int_type ch = EoF())
00358   {
00359     char *const pp = pptr();
00360     if (!pp) return EoF();
00361     char *const pb = pbase();
00362     int_type result = 0;
00363 
00364     if (pp > pb) result = AdjustEOF(m_Obj.cwrite(pb, pp-pb));
00365     setp(m_P, m_P + m_BufSize);
00366 
00367     // Write that one more character, if it's there.
00368     if (ch != EoF())
00369     {
00370       *pptr() = char(ch);
00371       pbump(1);
00372     }
00373     return result;
00374   }
00375 
00376   virtual int_type underflow()
00377   {
00378     if (!gptr()) return EoF();
00379     char *const eb = eback();
00380     const int result = AdjustEOF(m_Obj.cread(eback(), m_BufSize));
00381     setg(eb, eb, eb + ((result==EoF()) ? 0 : result));
00382     return (!result || (result == EoF())) ? EoF() : *eb;
00383   }
00384 
00385 private:
00387   static int_type EoF() { return traits_type::eof(); }
00388 
00390   static PGSTD::streampos AdjustEOF(int pos)
00391   {
00392     return (pos == -1) ? EoF() : pos;
00393   }
00394 
00395   void initialize(PGSTD::ios_base::openmode mode)
00396   {
00397     if (mode & PGSTD::ios_base::in) 
00398     {
00399       m_G = new char_type[m_BufSize];
00400       setg(m_G, m_G, m_G);
00401     }
00402     if (mode & PGSTD::ios_base::out)
00403     {
00404       m_P = new char_type[m_BufSize];
00405       setp(m_P, m_P + m_BufSize);
00406     }
00407   }
00408 
00409   const size_type m_BufSize;
00410   LargeObjectAccess m_Obj;
00411 
00412   // Get & put buffers
00413   char_type *m_G, *m_P;
00414 };
00415 
00416 
00418 
00425 template<typename CHAR=char, typename TRAITS=PGSTD::char_traits<CHAR> > 
00426 class basic_ilostream : public PGSTD::basic_istream<CHAR, TRAITS>
00427 {
00428 public:
00429   typedef CHAR char_type;
00430   typedef TRAITS traits_type;
00431   typedef typename traits_type::int_type int_type;
00432   typedef typename traits_type::pos_type pos_type;
00433   typedef typename traits_type::off_type off_type;
00434 
00436 
00440   basic_ilostream(TransactionItf &T, 
00441                   LargeObject O, 
00442                   LargeObject::size_type BufSize=512) :
00443     PGSTD::basic_istream<CHAR,TRAITS>(&m_Buf),
00444     m_Buf(T, O, in, BufSize) 
00445   { 
00446   }
00447 
00449 
00453   basic_ilostream(TransactionItf &T, 
00454                   Oid O, 
00455                   LargeObject::size_type BufSize=512) :
00456     PGSTD::basic_istream<CHAR,TRAITS>(&m_Buf),
00457     m_Buf(T, O, in, BufSize) 
00458   { 
00459   }
00460 
00461 private:
00462   largeobject_streambuf<CHAR,TRAITS> m_Buf;
00463 };
00464 
00465 typedef basic_ilostream<char> ilostream;
00466 
00467 
00469 
00476 template<typename CHAR=char, typename TRAITS=PGSTD::char_traits<CHAR> > 
00477 class basic_olostream : public PGSTD::basic_ostream<CHAR, TRAITS>
00478 {
00479 public:
00480   typedef CHAR char_type;
00481   typedef TRAITS traits_type;
00482   typedef typename traits_type::int_type int_type;
00483   typedef typename traits_type::pos_type pos_type;
00484   typedef typename traits_type::off_type off_type;
00485 
00487 
00491   basic_olostream(TransactionItf &T, 
00492                   LargeObject O,
00493                   LargeObject::size_type BufSize=512) :
00494     PGSTD::basic_ostream<CHAR,TRAITS>(&m_Buf),
00495     m_Buf(T, O, out, BufSize) 
00496   { 
00497   }
00498 
00500 
00504   basic_olostream(TransactionItf &T, Oid O) :
00505     PGSTD::basic_ostream<CHAR,TRAITS>(&m_Buf),
00506     m_Buf(T, O, out, BufSize) 
00507   { 
00508   }
00509 
00510   ~basic_olostream() { m_Buf.pubsync(); m_Buf.pubsync(); }
00511 
00512 private:
00513   largeobject_streambuf<CHAR,TRAITS> m_Buf;
00514 };
00515 
00516 typedef basic_olostream<char> olostream;
00517 
00518 
00520 
00527 template<typename CHAR=char, typename TRAITS=PGSTD::char_traits<CHAR> > 
00528 class basic_lostream : public PGSTD::basic_iostream<CHAR, TRAITS>
00529 {
00530 public:
00531   typedef CHAR char_type;
00532   typedef TRAITS traits_type;
00533   typedef typename traits_type::int_type int_type;
00534   typedef typename traits_type::pos_type pos_type;
00535   typedef typename traits_type::off_type off_type;
00536 
00538 
00542   basic_lostream(TransactionItf &T, LargeObject O) :
00543     PGSTD::basic_iostream<CHAR,TRAITS>(&m_Buf),
00544     m_Buf(T, O, in | out, BufSize) 
00545   { 
00546   }
00547 
00549 
00553   basic_lostream(TransactionItf &T, Oid O) :
00554     PGSTD::basic_iostream<CHAR,TRAITS>(&m_Buf),
00555     m_Buf(T, O, in | out, BufSize) 
00556   { 
00557   }
00558 
00559   ~basic_lostream() { m_Buf.pubsync(); m_Buf.pubsync(); }
00560 
00561 private:
00562   largeobject_streambuf<CHAR,TRAITS> m_Buf;
00563 };
00564 
00565 typedef basic_lostream<char> lostream;
00566 
00567 }
00568 
00569 #endif
00570 

Generated on Mon Mar 17 22:59:04 2003 for libpqxx by doxygen1.3-rc3