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:
00040   LargeObject();                                                        //[t48]
00041 
00043 
00045   explicit LargeObject(TransactionItf &T);                              //[t48]
00046 
00048 
00052   explicit LargeObject(Oid O) : m_ID(O) {}                              //[t48]
00053 
00055 
00059   LargeObject(TransactionItf &T, const PGSTD::string &File);            //[]
00060 
00062 
00066   LargeObject(const LargeObjectAccess &O);                              //[]
00067 
00069 
00072   Oid id() const throw () { return m_ID; }                              //[t48]
00073 
00075   bool operator==(const LargeObject &other) const                       //[]
00076         { return m_ID == other.m_ID; }
00078   bool operator!=(const LargeObject &other) const                       //[]
00079         { return m_ID != other.m_ID; }
00081   bool operator<=(const LargeObject &other) const                       //[]
00082         { return m_ID <= other.m_ID; }
00084   bool operator>=(const LargeObject &other) const                       //[]
00085         { return m_ID >= other.m_ID; }
00087   bool operator<(const LargeObject &other) const                        //[]
00088         { return m_ID < other.m_ID; }
00090   bool operator>(const LargeObject &other) const                        //[]
00091         { return m_ID > other.m_ID; }
00092 
00094 
00098   void to_file(TransactionItf &T, const char File[]) const;             //[]
00099 
00101 
00105   void to_file(TransactionItf &T, const PGSTD::string &File) const      //[]
00106   { 
00107     to_file(T, File.c_str()); 
00108   }
00109 
00111 
00115   void remove(TransactionItf &T) const;                                 //[t48]
00116 
00117 protected:
00118   static PGconn *RawConnection(const TransactionItf &T)
00119   {
00120     return T.Conn().RawConnection();
00121   }
00122 
00123 private:
00124   Oid m_ID;
00125 };
00126 
00127 
00128 // TODO: Consider iLargeObjectAccess, oLargeObjectAccess!?
00130 class LargeObjectAccess : private LargeObject
00131 {
00132 public:
00134 
00138   explicit LargeObjectAccess(TransactionItf &T, 
00139                              PGSTD::ios_base::openmode mode = 
00140                                 PGSTD::ios_base::in | 
00141                                 PGSTD::ios_base::out);                  //[]
00142 
00144 
00150   explicit LargeObjectAccess(TransactionItf &T, 
00151                              Oid O,
00152                              PGSTD::ios_base::openmode mode = 
00153                                 PGSTD::ios_base::in | 
00154                                 PGSTD::ios_base::out);                  //[]
00155 
00157 
00162   explicit LargeObjectAccess(TransactionItf &T, 
00163                              LargeObject O,
00164                              PGSTD::ios_base::openmode mode = 
00165                                 PGSTD::ios_base::in | 
00166                                 PGSTD::ios_base::out);                  //[]
00167 
00169 
00174   LargeObjectAccess(TransactionItf &T, 
00175                     const PGSTD::string &File,
00176                     PGSTD::ios_base::openmode mode = 
00177                         PGSTD::ios_base::in | PGSTD::ios_base::out);    //[]
00178 
00179   ~LargeObjectAccess() { close(); }
00180 
00182 
00185   using LargeObject::id;
00186 
00188 
00191   void to_file(const char File[]) const 
00192   { 
00193     LargeObject::to_file(m_Trans, File); 
00194   }
00195 
00197 
00200   void to_file(const PGSTD::string &File) const 
00201   { 
00202     LargeObject::to_file(m_Trans, File); 
00203   }
00204 
00205   // TODO: Document return value
00207   /** Does not throw exception in case of error; inspect return value instead.
00208    * @param dest offset to go to
00209    * @param dir origin to which dest is relative: ios_base::beg (from beginning 
00210    *        of the object), ios_base::cur (from current access position), or
00211    *        ios_base;:end (from end of object)
00212    */
00213   long cseek(long dest, PGSTD::ios_base::seekdir dir) throw ();
00214   
00215   // TODO: Document return value
00217   /** Does not throw exception in case of error; inspect return value instead.
00218    * @param Buf bytes to write
00219    * @param Len number of bytes to write
00220    */
00221   long cwrite(const char Buf[], size_t Len) throw ();
00222 
00223   // TODO: Document return value
00225   /** Does not throw exception in case of error; inspect return value instead.
00226    * @param Buf area where bytes should be stored
00227    * @param Len number of bytes to read
00228    */
00229   long cread(char Buf[], size_t Len) throw ();
00230 
00231   // TODO: Comparison operators
00232   // TODO: C++-style access functions
00233 
00234 private:
00235   PGconn *RawConnection() { return LargeObject::RawConnection(m_Trans); }
00236 
00237   void open(PGSTD::ios_base::openmode mode);
00238   void close();
00239 
00240   TransactionItf &m_Trans;
00241   int m_fd;
00242 
00243   // Not allowed:
00244   LargeObjectAccess();
00245   LargeObjectAccess(const LargeObjectAccess &);
00246   LargeObjectAccess operator=(const LargeObjectAccess &);
00247 };
00248 
00249 
00250 // TODO: Create i, o stream classes
00251 // TODO: Allow the creator to select a buffer size
00253 /** @warning Still experimental.  May change profoundly.
00254  *
00255  * The standard streambuf classes provide uniform access to data storage such
00256  * as files or string buffers, so they can be accessed using standard input or
00257  * output streams.  This streambuf implementation provides similar access to
00258  * large objects, so they can be read and written using the same stream classes.
00259  */
00260 template<typename CHAR=char, typename TRAITS=PGSTD::char_traits<CHAR> >
00261 class largeobject_streambuf : public PGSTD::basic_streambuf<CHAR, TRAITS>
00262 {
00263 public:
00264   typedef CHAR   char_type;
00265   typedef TRAITS traits_type;
00266   typedef typename traits_type::int_type int_type;
00267   typedef typename traits_type::pos_type pos_type;
00268   typedef typename traits_type::off_type off_type;
00269 
00270   largeobject_streambuf(TransactionItf &T,
00271                         LargeObject O,
00272                         PGSTD::ios_base::openmode mode = 
00273                                 PGSTD::ios::in | PGSTD::ios::out) :     //[t48]
00274     m_BufSize(512),
00275     m_Obj(T, O),
00276     m_G(0),
00277     m_P(0)
00278   {
00279     initialize(mode);
00280   }
00281 
00282   largeobject_streambuf(TransactionItf &T,
00283                         Oid O,
00284                         PGSTD::ios_base::openmode mode = 
00285                                 PGSTD::ios::in | PGSTD::ios::out) :     //[t48]
00286     m_BufSize(512),
00287     m_Obj(T, O),
00288     m_G(0),
00289     m_P(0)
00290   {
00291     initialize(mode);
00292   }
00293 
00294   virtual ~largeobject_streambuf()
00295   {
00296     delete [] m_P;
00297     delete [] m_G;
00298   }
00299 
00300 
00301 protected:
00302   virtual int sync()
00303   {
00304     // setg() sets eback, gptr, egptr
00305     setg(eback(), eback(), egptr());
00306     return overflow(EoF());
00307   }
00308 
00309   virtual pos_type seekoff(off_type offset, 
00310                            PGSTD::ios_base::seekdir dir,
00311                            PGSTD::ios_base::openmode mode =
00312                                 PGSTD::ios_base::in|PGSTD::ios_base::out)
00313   {
00314     if (!mode) {}       // Quench "unused parameter" warning
00315     return AdjustEOF(m_Obj.cseek(offset, dir));
00316   }
00317 
00318   virtual pos_type seekpos(pos_type pos, 
00319                            PGSTD::ios_base::openmode mode =
00320                                 PGSTD::ios_base::in|PGSTD::ios_base::out)
00321   {
00322     if (!mode) {}       // Quench "unused parameter" warning
00323     return AdjustEOF(m_Obj.cseek(pos, PGSTD::ios_base::beg));
00324   }
00325 
00326   virtual int_type overflow(int_type ch = EoF())
00327   {
00328     char *const pp = pptr();
00329     if (!pp) return EoF();
00330     char *const pb = pbase();
00331     int_type result = 0;
00332 
00333     if (pp > pb) result = AdjustEOF(m_Obj.cwrite(pb, pp-pb));
00334     setp(m_P, m_P + m_BufSize);
00335 
00336     // Write that one more character, if it's there.
00337     if (ch != EoF())
00338     {
00339       *pptr() = char(ch);
00340       pbump(1);
00341     }
00342     return result;
00343   }
00344 
00345   virtual int_type underflow()
00346   {
00347     if (!gptr()) return EoF();
00348     char *const eb = eback();
00349     const int result = AdjustEOF(m_Obj.cread(eback(), m_BufSize));
00350     setg(eb, eb, eb + ((result==EoF()) ? 0 : result));
00351     return (!result || (result == EoF())) ? EoF() : *eb;
00352   }
00353 
00354 private:
00356   static int_type EoF() { return traits_type::eof(); }
00357 
00359   static PGSTD::streampos AdjustEOF(int pos)
00360   {
00361     return (pos == -1) ? EoF() : pos;
00362   }
00363 
00364   void initialize(PGSTD::ios_base::openmode mode)
00365   {
00366     if (mode & PGSTD::ios_base::in) 
00367     {
00368       m_G = new char_type[m_BufSize];
00369       setg(m_G, m_G, m_G);
00370     }
00371     if (mode & PGSTD::ios_base::out)
00372     {
00373       m_P = new char_type[m_BufSize];
00374       setp(m_P, m_P + m_BufSize);
00375     }
00376   }
00377 
00378   const size_t m_BufSize;
00379   LargeObjectAccess m_Obj;
00380 
00381   // Get & put buffers
00382   char_type *m_G, *m_P;
00383 };
00384 
00385 
00386 template<typename CHAR=char, typename TRAITS=PGSTD::char_traits<CHAR> > 
00387 class basic_ilostream : public PGSTD::basic_istream<CHAR, TRAITS>
00388 {
00389 public:
00390   typedef CHAR char_type;
00391   typedef TRAITS traits_type;
00392   typedef typename traits_type::int_type int_type;
00393   typedef typename traits_type::pos_type pos_type;
00394   typedef typename traits_type::off_type off_type;
00395 
00396   basic_ilostream(TransactionItf &T, LargeObject O) :
00397     PGSTD::basic_istream<CHAR,TRAITS>(&m_Buf),
00398     m_Buf(T, O, PGSTD::ios_base::in) 
00399   { 
00400   }
00401 
00402   basic_ilostream(TransactionItf &T, Oid O) :
00403     PGSTD::basic_istream<CHAR,TRAITS>(&m_Buf),
00404     m_Buf(T, O, PGSTD::ios_base::in) 
00405   { 
00406   }
00407 
00408 private:
00409   largeobject_streambuf<CHAR,TRAITS> m_Buf;
00410 };
00411 
00412 typedef basic_ilostream<char> ilostream;
00413 
00414 template<typename CHAR=char, typename TRAITS=PGSTD::char_traits<CHAR> > 
00415 class basic_olostream : public PGSTD::basic_ostream<CHAR, TRAITS>
00416 {
00417 public:
00418   typedef CHAR char_type;
00419   typedef TRAITS traits_type;
00420   typedef typename traits_type::int_type int_type;
00421   typedef typename traits_type::pos_type pos_type;
00422   typedef typename traits_type::off_type off_type;
00423 
00424   basic_olostream(TransactionItf &T, LargeObject O) :
00425     PGSTD::basic_ostream<CHAR,TRAITS>(&m_Buf),
00426     m_Buf(T, O, PGSTD::ios_base::out) 
00427   { 
00428   }
00429 
00430   basic_olostream(TransactionItf &T, Oid O) :
00431     PGSTD::basic_ostream<CHAR,TRAITS>(&m_Buf),
00432     m_Buf(T, O, PGSTD::ios_base::out) 
00433   { 
00434   }
00435 
00436   ~basic_olostream() { m_Buf.pubsync(); m_Buf.pubsync(); }
00437 
00438 private:
00439   largeobject_streambuf<CHAR,TRAITS> m_Buf;
00440 };
00441 
00442 typedef basic_olostream<char> olostream;
00443 
00444 
00445 template<typename CHAR=char, typename TRAITS=PGSTD::char_traits<CHAR> > 
00446 class basic_lostream : public PGSTD::basic_iostream<CHAR, TRAITS>
00447 {
00448 public:
00449   typedef CHAR char_type;
00450   typedef TRAITS traits_type;
00451   typedef typename traits_type::int_type int_type;
00452   typedef typename traits_type::pos_type pos_type;
00453   typedef typename traits_type::off_type off_type;
00454 
00455   basic_lostream(TransactionItf &T, LargeObject O) :
00456     PGSTD::basic_iostream<CHAR,TRAITS>(&m_Buf),
00457     m_Buf(T, O) 
00458   { 
00459   }
00460 
00461   basic_lostream(TransactionItf &T, Oid O) :
00462     PGSTD::basic_iostream<CHAR,TRAITS>(&m_Buf),
00463     m_Buf(T, O) 
00464   { 
00465   }
00466 
00467   ~basic_lostream() { m_Buf.pubsync(); m_Buf.pubsync(); }
00468 
00469 private:
00470   largeobject_streambuf<CHAR,TRAITS> m_Buf;
00471 };
00472 
00473 typedef basic_lostream<char> lostream;
00474 
00475 }
00476 
00477 #endif
00478 

Generated on Sat Mar 15 20:47:39 2003 for libpqxx by doxygen1.3-rc3