00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
#include "pqxx/libcompiler.h"
00020 
00021 
#include <new>
00022 
00023 
#ifdef PQXX_HAVE_STREAMBUF
00024 
#include <streambuf>
00025 
#else
00026 
#include <streambuf.h>
00027 
#endif
00028 
00029 
#include "pqxx/dbtransaction"
00030 
00031 
00032 
namespace pqxx
00033 {
00034 
00035 
class largeobjectaccess;
00036 
00038 
00045 class PQXX_LIBEXPORT largeobject
00046 {
00047 
public:
00048   typedef long size_type;
00049 
00051   largeobject() throw ();                                               
00052 
00054 
00056   explicit largeobject(
dbtransaction &T);                               
00057 
00059 
00063   explicit largeobject(
oid O) throw () : m_ID(O) {}                     
00064 
00066 
00070   largeobject(
dbtransaction &T, 
const PGSTD::string &File);             
00071 
00073 
00077   largeobject(
const largeobjectaccess &O) 
throw ();                     
00078 
00080 
00084   oid id() const throw () { 
return m_ID; }                              
00085 
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; }
00093   bool operator<=(
const largeobject &other) 
const                       
00094           { 
return m_ID <= other.m_ID; }
00096   bool operator>=(
const largeobject &other) 
const                       
00097           { 
return m_ID >= other.m_ID; }
00099   bool operator<(
const largeobject &other) 
const                        
00100           { 
return m_ID < other.m_ID; }
00102   bool operator>(
const largeobject &other) 
const                        
00103           { 
return m_ID > other.m_ID; }
00104 
00106 
00110   
void to_file(
dbtransaction &T, 
const PGSTD::string &File) 
const;      
00111 
00113 
00117   
void remove(
dbtransaction &T) 
const;                                  
00118 
00119 
protected:
00120   static internal::pq::PGconn *RawConnection(
const dbtransaction &T)
00121   {
00122     
return T.
conn().
RawConnection();
00123   }
00124 
00125   PGSTD::string Reason() const;
00126 
00127 private:
00128   
oid m_ID;
00129 };
00130 
00131 
00132 
00133 
00135 class PQXX_LIBEXPORT 
largeobjectaccess : private largeobject
00136 {
00137 
public:
00138   
using largeobject::size_type;
00139   typedef long off_type;
00140   typedef size_type pos_type;
00141 
00143 
00147   typedef PGSTD::ios::openmode 
openmode;
00148 
00150 
00154   typedef PGSTD::ios::seekdir 
seekdir;
00155 
00157 
00161   
explicit largeobjectaccess(
dbtransaction &T, 
00162                              openmode mode = 
00163                                 PGSTD::ios::in | 
00164                                 PGSTD::ios::out);                       
00165 
00167 
00173   
largeobjectaccess(
dbtransaction &T, 
00174                     
oid O,
00175                     openmode mode = 
00176                         PGSTD::ios::in | 
00177                         PGSTD::ios::out);                               
00178 
00180 
00185   
largeobjectaccess(
dbtransaction &T, 
00186                     largeobject O,
00187                     openmode mode = PGSTD::ios::in | PGSTD::ios::out);  
00188 
00190 
00195   
largeobjectaccess(
dbtransaction &T, 
00196                     
const PGSTD::string &File,
00197                     openmode mode = 
00198                         PGSTD::ios::in | PGSTD::ios::out);              
00199 
00200   ~
largeobjectaccess() throw () { close(); }
00201 
00203 
00206   
using largeobject::id;
00207 
00209 
00212   void to_file(
const PGSTD::string &File) 
const                         
00213   { 
00214     largeobject::to_file(m_Trans, File); 
00215   }
00216 
00217 
#ifdef PQXX_BROKEN_USING_DECL
00218 
00219 
00223   
void to_file(
dbtransaction &T, 
const PGSTD::string &F)
 const
00224 
        { largeobject::to_file(T, F); }
00225 
#else
00226 
  using largeobject::to_file;
00227 
#endif
00228 
00229 
00231 
00235   
void write(
const char Buf[], size_type Len);                          
00236 
00238 
00241   void write(
const PGSTD::string &Buf)                                  
00242         { write(Buf.c_str(), Buf.size()); }
00243 
00245 
00251   size_type read(
char Buf[], size_type Len);                            
00252 
00254 
00257   size_type seek(size_type dest, seekdir dir);                          
00258 
00260 
00268   pos_type cseek(off_type dest, seekdir dir) 
throw ();                  
00269     
00271 
00277   off_type cwrite(
const char Buf[], size_type Len) 
throw ();            
00278 
00280 
00286   off_type cread(
char Buf[], size_type Len) 
throw ();                   
00287 
00288 
00290   
void process_notice(
const PGSTD::string &) throw ();                  
00291 
00292   using largeobject::remove;
00293 
00294   using largeobject::operator==;
00295   using largeobject::operator!=;
00296   using largeobject::operator<;
00297   using largeobject::operator<=;
00298   using largeobject::operator>;
00299   using largeobject::operator>=;
00300 
00301 private:
00302   PGSTD::string Reason() const;
00303   internal::pq::PGconn *RawConnection()
00304         { 
return largeobject::RawConnection(m_Trans); }
00305 
00306   
void open(openmode mode);
00307   
void close() throw ();
00308 
00309   dbtransaction &m_Trans;
00310   
int m_fd;
00311 
00312   
00313   largeobjectaccess();
00314   largeobjectaccess(const largeobjectaccess &);
00315   largeobjectaccess operator=(const largeobjectaccess &);
00316 };
00317 
00318 
00320 
00328 template<typename CHAR=
char, typename TRAITS=PGSTD::char_traits<CHAR> >
00329   class 
largeobject_streambuf :
00330 #ifdef PQXX_HAVE_STREAMBUF
00331     public PGSTD::basic_streambuf<CHAR, TRAITS>
00332 #else
00333     public PGSTD::streambuf
00334 #endif
00335 {
00336   
typedef long size_type;
00337 
public:
00338   typedef CHAR   
char_type;
00339   typedef TRAITS 
traits_type;
00340   typedef typename traits_type::int_type 
int_type;
00341 
#ifdef PQXX_HAVE_STREAMBUF
00342 
  typedef typename traits_type::pos_type pos_type;
00343   
typedef typename traits_type::off_type off_type;
00344 
#else
00345   typedef streamoff off_type;
00346   typedef streampos pos_type;
00347 
#endif
00348   typedef largeobjectaccess::openmode openmode;
00349   typedef largeobjectaccess::seekdir seekdir;
00350 
00351   largeobject_streambuf(
dbtransaction &T,
00352                         largeobject O,
00353                         openmode mode = PGSTD::ios::in | PGSTD::ios::out,
00354                         size_type BufSize=512) :                        
00355     m_BufSize(BufSize),
00356     m_Obj(T, O),
00357     m_G(0),
00358     m_P(0)
00359   {
00360     initialize(mode);
00361   }
00362 
00363   largeobject_streambuf(
dbtransaction &T,
00364                         
oid O,
00365                         openmode mode = PGSTD::ios::in | PGSTD::ios::out,
00366                         size_type BufSize=512) :                        
00367     m_BufSize(BufSize),
00368     m_Obj(T, O),
00369     m_G(0),
00370     m_P(0)
00371   {
00372     initialize(mode);
00373   }
00374 
00375   virtual ~
largeobject_streambuf() throw ()
00376   {
00377     
delete [] m_P;
00378     
delete [] m_G;
00379   }
00380 
00381 
00383   void process_notice(
const PGSTD::string &s) { m_Obj.process_notice(s); }
00384 
00385 
#ifdef PQXX_HAVE_STREAMBUF
00386 
protected:
00387 
#endif
00388   virtual int sync()
00389   {
00390     
00391     setg(this->eback(), this->eback(), this->egptr());
00392     
return overflow(EoF());
00393   }
00394 
00395 
protected:
00396   virtual pos_type seekoff(off_type offset, 
00397                            seekdir dir,
00398                            openmode mode)
00399   {
00400     
if (mode != SEEK_CUR)
00401       
throw PGSTD::logic_error(
"Offset "+
to_string(
int(mode))+
" in seekoff()");
00402     
return AdjustEOF(m_Obj.cseek(offset, dir));
00403   }
00404 
00405   virtual pos_type seekpos(pos_type pos, openmode mode)
00406   {
00407     
if (mode != SEEK_SET)
00408       
throw PGSTD::logic_error(
"Offset "+
to_string(
int(mode))+
" in seekpos()");
00409     
return AdjustEOF(m_Obj.cseek(pos, PGSTD::ios::beg));
00410   }
00411 
00412   virtual int_type overflow(int_type ch = EoF())
00413   {
00414     
char *
const pp = this->pptr();
00415     
if (!pp) 
return EoF();
00416     
char *
const pb = this->pbase();
00417     int_type res = 0;
00418 
00419     
if (pp > pb) res = AdjustEOF(m_Obj.cwrite(pb, pp-pb));
00420     setp(m_P, m_P + m_BufSize);
00421 
00422     
00423     
if (ch != EoF())
00424     {
00425       *this->pptr() = char(ch);
00426       this->pbump(1);
00427     }
00428     
return res;
00429   }
00430 
00431   virtual int_type underflow()
00432   {
00433     
if (!this->gptr()) 
return EoF();
00434     
char *
const eb = this->eback();
00435     
const int res = AdjustEOF(m_Obj.cread(this->eback(), m_BufSize));
00436     setg(eb, eb, eb + ((res==EoF()) ? 0 : res));
00437     
return (!res || (res == EoF())) ? EoF() : *eb;
00438   }
00439 
00440 
private:
00442   
static int_type EoF() { 
return traits_type::eof(); }
00443 
00445   
static PGSTD::streampos AdjustEOF(
int pos)
00446   {
00447     
return (pos == -1) ? EoF() : pos;
00448   }
00449 
00450   
void initialize(openmode mode)
00451   {
00452     
if (mode & PGSTD::ios::in) 
00453     {
00454       m_G = 
new char_type[m_BufSize];
00455       setg(m_G, m_G, m_G);
00456     }
00457     
if (mode & PGSTD::ios::out)
00458     {
00459       m_P = 
new char_type[m_BufSize];
00460       setp(m_P, m_P + m_BufSize);
00461     }
00462   }
00463 
00464   
const size_type m_BufSize;
00465   largeobjectaccess m_Obj;
00466 
00467   
00468   char_type *m_G, *m_P;
00469 };
00470 
00471 
00473 
00481 
template<
typename CHAR=
char, 
typename TRAITS=PGSTD::
char_traits<CHAR> > 
00482   class basic_ilostream :
00483 #ifdef 
PQXX_HAVE_STREAMBUF
00484     
public PGSTD::basic_istream<CHAR, TRAITS>
00485 #else
00486     
public PGSTD::istream
00487 #endif
00488 {
00489 
#ifdef PQXX_HAVE_STREAMBUF
00490 
  typedef PGSTD::basic_istream<CHAR, TRAITS> super;
00491 
#else
00492 
  typedef PGSTD::istream super;
00493 
#endif
00494 
00495 
public:
00496   typedef CHAR char_type;
00497   typedef TRAITS traits_type;
00498   typedef typename traits_type::int_type int_type;
00499   typedef typename traits_type::pos_type pos_type;
00500   typedef typename traits_type::off_type off_type;
00501 
00503 
00507   basic_ilostream(
dbtransaction &T, 
00508                   largeobject O, 
00509                   
largeobject::size_type BufSize=512) :                 
00510     super(&m_Buf),
00511     m_Buf(T, O, 
PGSTD::ios::in, BufSize) 
00512   { 
00513   }
00514 
00516 
00520   basic_ilostream(
dbtransaction &T, 
00521                   
oid O, 
00522                   
largeobject::size_type BufSize=512) :                 
00523     super(&m_Buf),
00524     m_Buf(T, O, 
PGSTD::ios::in, BufSize) 
00525   { 
00526   }
00527 
00528 
private:
00529   
largeobject_streambuf<CHAR,TRAITS> m_Buf;
00530 };
00531 
00532 typedef basic_ilostream<char> ilostream;
00533 
00534 
00536 
00544 
template<
typename CHAR=
char, 
typename TRAITS=PGSTD::
char_traits<CHAR> > 
00545   class basic_olostream : 
00546 #ifdef 
PQXX_HAVE_STREAMBUF
00547     
public PGSTD::basic_ostream<CHAR, TRAITS>
00548 #else
00549     
public PGSTD::ostream
00550 #endif
00551 {
00552 
#ifdef PQXX_HAVE_STREAMBUF
00553 
  typedef PGSTD::basic_ostream<CHAR, TRAITS> super;
00554 
#else
00555 
  typedef PGSTD::ostream super;
00556 
#endif
00557 
public:
00558   typedef CHAR char_type;
00559   typedef TRAITS traits_type;
00560   typedef typename traits_type::int_type int_type;
00561   typedef typename traits_type::pos_type pos_type;
00562   typedef typename traits_type::off_type off_type;
00563 
00565 
00569   basic_olostream(
dbtransaction &T, 
00570                   largeobject O,
00571                   
largeobject::size_type BufSize=512) :                 
00572     super(&m_Buf),
00573     m_Buf(T, O, 
PGSTD::ios::out, BufSize) 
00574   { 
00575   }
00576 
00578 
00582   basic_olostream(
dbtransaction &T, 
00583                   
oid O,
00584                   
largeobject::size_type BufSize=512) :                 
00585     super(&m_Buf),
00586     m_Buf(T, O, 
PGSTD::ios::out, BufSize) 
00587   { 
00588   }
00589 
00590   ~
basic_olostream() 
00591   { 
00592     
try
00593     {
00594 
#ifdef PQXX_HAVE_STREAMBUF
00595 
      m_Buf.pubsync(); m_Buf.pubsync(); 
00596 
#else
00597 
      m_Buf.sync(); m_Buf.sync();
00598 
#endif
00599 
    }
00600     
catch (
const PGSTD::exception &e)
00601     {
00602       m_Buf.process_notice(e.what());
00603     }
00604   }
00605 
00606 
private:
00607   
largeobject_streambuf<CHAR,TRAITS> m_Buf;
00608 };
00609 
00610 typedef basic_olostream<char> olostream;
00611 
00612 
00614 
00622 
template<
typename CHAR=
char, 
typename TRAITS=PGSTD::
char_traits<CHAR> > 
00623   class basic_lostream :
00624 #ifdef 
PQXX_HAVE_STREAMBUF
00625     
public PGSTD::basic_iostream<CHAR, TRAITS>
00626 #else
00627     
public PGSTD::iostream
00628 #endif
00629 {
00630 
#ifdef PQXX_HAVE_STREAMBUF
00631 
  typedef PGSTD::basic_iostream<CHAR, TRAITS> super;
00632 
#else
00633 
  typedef PGSTD::iostream super;
00634 
#endif
00635 
00636 
public:
00637   typedef CHAR char_type;
00638   typedef TRAITS traits_type;
00639   typedef typename traits_type::int_type int_type;
00640   typedef typename traits_type::pos_type pos_type;
00641   typedef typename traits_type::off_type off_type;
00642 
00644 
00648   basic_lostream(
dbtransaction &T, 
00649                  largeobject O,
00650                  
largeobject::size_type BufSize=512) :                  
00651     super(&m_Buf),
00652     m_Buf(T, O, 
PGSTD::ios::in | 
PGSTD::ios::out, BufSize) 
00653   { 
00654   }
00655 
00657 
00661   basic_lostream(
dbtransaction &T, 
00662                  
oid O,
00663                  
largeobject::size_type BufSize=512) :                  
00664     super(&m_Buf),
00665     m_Buf(T, O, 
PGSTD::ios::in | 
PGSTD::ios::out, BufSize) 
00666   { 
00667   }
00668 
00669   ~
basic_lostream() 
00670   {
00671     
try
00672     {
00673 
#ifdef PQXX_HAVE_STREAMBUF
00674 
      m_Buf.pubsync(); m_Buf.pubsync(); 
00675 
#else
00676 
      m_Buf.sync(); m_Buf.sync();
00677 
#endif
00678 
    }
00679     
catch (
const PGSTD::exception &e)
00680     {
00681       m_Buf.process_notice(e.what());
00682     }
00683   }
00684 
00685 
private:
00686   
largeobject_streambuf<CHAR,TRAITS> m_Buf;
00687 };
00688 
00689 typedef basic_lostream<char> lostream;
00690 
00691 }
00692 
00693