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

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 
00042   explicit LargeObject(TransactionItf &T);                              //[t48]
00043 
00045 
00049   explicit LargeObject(Oid O) : m_ID(O) {}                              //[]
00050 
00052 
00056   LargeObject(TransactionItf &T, const PGSTD::string &File);            //[]
00057 
00059 
00063   LargeObject(const LargeObjectAccess &O);                              //[]
00064 
00066 
00069   Oid id() const throw () { return m_ID; }                              //[t48]
00070 
00072   bool operator==(const LargeObject &other) const                       //[]
00073         { return m_ID == other.m_ID; }
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; }
00089 
00091 
00095   void to_file(TransactionItf &T, const char File[]) const;             //[]
00096 
00098 
00102   void to_file(TransactionItf &T, const PGSTD::string &File) const      //[]
00103   { 
00104     to_file(T, File.c_str()); 
00105   }
00106 
00107   // TODO: Document return value
00108   // TODO: Write C++-style wrapper (which throws on error)
00110   /** Does not throw exception in case of error; inspect return value instead.
00111    * @param T the transaction in which the object is to be deleted
00112    */
00113   int cunlink(TransactionItf &T) const throw ();                        //[]
00114 
00115 protected:
00116   static PGconn *RawConnection(const TransactionItf &T)
00117   {
00118     return T.Conn().RawConnection();
00119   }
00120 
00121 private:
00122   Oid m_ID;
00123 };
00124 
00125 
00126 // TODO: Consider iLargeObjectAccess, oLargeObjectAccess!?
00128 class LargeObjectAccess : private LargeObject
00129 {
00130 public:
00132 
00136   explicit LargeObjectAccess(TransactionItf &T, 
00137                              PGSTD::ios_base::openmode mode = 
00138                                 PGSTD::ios_base::in | 
00139                                 PGSTD::ios_base::out);                  //[]
00140 
00142 
00148   explicit LargeObjectAccess(TransactionItf &T, 
00149                              Oid O,
00150                              PGSTD::ios_base::openmode mode = 
00151                                 PGSTD::ios_base::in | 
00152                                 PGSTD::ios_base::out);                  //[]
00153 
00155 
00160   explicit LargeObjectAccess(TransactionItf &T, 
00161                              LargeObject O,
00162                              PGSTD::ios_base::openmode mode = 
00163                                 PGSTD::ios_base::in | 
00164                                 PGSTD::ios_base::out);                  //[]
00165 
00167 
00172   LargeObjectAccess(TransactionItf &T, 
00173                     const PGSTD::string &File,
00174                     PGSTD::ios_base::openmode mode = 
00175                         PGSTD::ios_base::in | PGSTD::ios_base::out);    //[]
00176 
00177   ~LargeObjectAccess() { close(); }
00178 
00180 
00183   using LargeObject::id;
00184 
00186 
00189   void to_file(const char File[]) const 
00190   { 
00191     LargeObject::to_file(m_Trans, File); 
00192   }
00193 
00195 
00198   void to_file(const PGSTD::string &File) const 
00199   { 
00200     LargeObject::to_file(m_Trans, File); 
00201   }
00202 
00203   // TODO: Document return value
00205   /** Does not throw exception in case of error; inspect return value instead.
00206    * @param dest offset to go to
00207    * @param dir origin to which dest is relative: ios_base::beg (from beginning 
00208    *        of the object), ios_base::cur (from current access position), or
00209    *        ios_base;:end (from end of object)
00210    */
00211   long cseek(long dest, PGSTD::ios_base::seekdir dir) throw ();
00212   
00213   // TODO: Document return value
00215   /** Does not throw exception in case of error; inspect return value instead.
00216    * @param Buf bytes to write
00217    * @param Len number of bytes to write
00218    */
00219   long cwrite(const char Buf[], size_t Len) throw ();
00220 
00221   // TODO: Document return value
00223   /** Does not throw exception in case of error; inspect return value instead.
00224    * @param Buf area where bytes should be stored
00225    * @param Len number of bytes to read
00226    */
00227   long cread(char Buf[], size_t Len) throw ();
00228 
00229   // TODO: Comparison operators
00230   // TODO: C++-style access functions
00231 
00232 private:
00233   PGconn *RawConnection() { return LargeObject::RawConnection(m_Trans); }
00234 
00235   void open(PGSTD::ios_base::openmode mode);
00236   void close();
00237 
00238   TransactionItf &m_Trans;
00239   int m_fd;
00240 
00241   // Not allowed:
00242   LargeObjectAccess();
00243   LargeObjectAccess(const LargeObjectAccess &);
00244   LargeObjectAccess operator=(const LargeObjectAccess &);
00245 };
00246 
00247 
00248 // TODO: Create i, o wrappers (easier construction, no template brackets)
00250 /** @warning Still experimental.  May change profoundly.
00251  *
00252  * The standard streambuf classes provide uniform access to data storage such
00253  * as files or string buffers, so they can be accessed using standard input or
00254  * output streams.  This streambuf implementation provides similar access to
00255  * large objects, so they can be read and written using the same stream classes.
00256  */
00257 template<typename CHAR=char, typename TRAITS=PGSTD::char_traits<CHAR> >
00258 class largeobject_streambuf : public PGSTD::basic_streambuf<CHAR, TRAITS>
00259 {
00260 public:
00261   typedef CHAR   char_type;
00262   typedef TRAITS traits_type;
00263   typedef typename traits_type::int_type int_type;
00264   typedef typename traits_type::pos_type pos_type;
00265   typedef typename traits_type::off_type off_type;
00266 
00267   largeobject_streambuf(TransactionItf &T,
00268                         LargeObject O,
00269                         PGSTD::ios_base::openmode mode = 
00270                                 PGSTD::ios::in | PGSTD::ios::out) :     //[t48]
00271     m_BufSize(512),
00272     m_Obj(T, O),
00273     m_G(0),
00274     m_P(0)
00275   {
00276     initialize(mode);
00277   }
00278 
00279   largeobject_streambuf(TransactionItf &T,
00280                         Oid O,
00281                         PGSTD::ios_base::openmode mode = 
00282                                 PGSTD::ios::in | PGSTD::ios::out) :     //[t48]
00283     m_BufSize(512),
00284     m_Obj(T, O),
00285     m_G(0),
00286     m_P(0)
00287   {
00288     initialize(mode);
00289   }
00290 
00291   virtual ~largeobject_streambuf()
00292   {
00293     delete [] m_P;
00294     delete [] m_G;
00295   }
00296 
00297 
00298 protected:
00299   virtual int sync()
00300   {
00301     // setg() sets eback, gptr, egptr
00302     setg(eback(), eback(), egptr());
00303     return overflow(EoF());
00304   }
00305 
00306   virtual pos_type seekoff(off_type offset, 
00307                            PGSTD::ios_base::seekdir dir,
00308                            PGSTD::ios_base::openmode mode =
00309                                 PGSTD::ios_base::in|PGSTD::ios_base::out)
00310   {
00311     if (!mode) {}       // Quench "unused parameter" warning
00312     return AdjustEOF(m_Obj.cseek(offset, dir));
00313   }
00314 
00315   virtual pos_type seekpos(pos_type pos, 
00316                            PGSTD::ios_base::openmode mode =
00317                                 PGSTD::ios_base::in|PGSTD::ios_base::out)
00318   {
00319     if (!mode) {}       // Quench "unused parameter" warning
00320     return AdjustEOF(m_Obj.cseek(pos, PGSTD::ios_base::beg));
00321   }
00322 
00323   virtual int_type overflow(int_type ch = EoF())
00324   {
00325     char *const pp = pptr();
00326     if (!pp) return EoF();
00327     char *const pb = pbase();
00328     int_type result = 0;
00329 
00330     if (pp > pb) result = AdjustEOF(m_Obj.cwrite(pb, pp-pb));
00331     setp(m_P, m_P + m_BufSize);
00332 
00333     // Write that one more character, if it's there.
00334     if (ch != EoF())
00335     {
00336       *pptr() = char(ch);
00337       pbump(1);
00338     }
00339     return result;
00340   }
00341 
00342   virtual int_type underflow()
00343   {
00344     if (!gptr()) return EoF();
00345     char *const eb = eback();
00346     const int result = AdjustEOF(m_Obj.cread(eback(), m_BufSize));
00347     setg(eb, eb, eb + ((result==EoF()) ? 0 : result));
00348     return (!result || (result == EoF())) ? EoF() : *eb;
00349   }
00350 
00351 private:
00353   static int_type EoF() { return traits_type::eof(); }
00354 
00356   static PGSTD::streampos AdjustEOF(int pos)
00357   {
00358     return (pos == -1) ? EoF() : pos;
00359   }
00360 
00361   void initialize(PGSTD::ios_base::openmode mode)
00362   {
00363     if (mode & PGSTD::ios::in) 
00364     {
00365       m_G = new char_type[m_BufSize];
00366       setg(m_G, m_G, m_G);
00367     }
00368     if (mode & PGSTD::ios::out)
00369     {
00370       m_P = new char_type[m_BufSize];
00371       setp(m_P, m_P + m_BufSize);
00372     }
00373   }
00374 
00375   const size_t m_BufSize;
00376   LargeObjectAccess m_Obj;
00377 
00378   // Get & put buffers
00379   char_type *m_G, *m_P;
00380 };
00381 
00382 }
00383 
00384 #endif
00385 

Generated on Thu Mar 6 23:30:04 2003 for libpqxx by doxygen1.3-rc3