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

largeobject.hxx

Go to the documentation of this file.
00001 /*------------------------------------------------------------------------- 00002 * 00003 * FILE 00004 * pqxx/largeobject.hxx 00005 * 00006 * DESCRIPTION 00007 * libpqxx's Large Objects interface 00008 * Allows access to large objects directly, or through I/O streams 00009 * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/largeobject instead. 00010 * 00011 * Copyright (c) 2003-2004, Jeroen T. Vermeulen <jtv@xs4all.nl> 00012 * 00013 * See COPYING for copyright license. If you did not receive a file called 00014 * COPYING with this source code, please notify the distributor of this mistake, 00015 * or contact the author. 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 (); //[t48] 00052 00054 00056 explicit largeobject(dbtransaction &T); //[t48] 00057 00059 00063 explicit largeobject(oid O) throw () : m_ID(O) {} //[t48] 00064 00066 00070 largeobject(dbtransaction &T, const PGSTD::string &File); //[t53] 00071 00073 00077 largeobject(const largeobjectaccess &O) throw (); //[t50] 00078 00080 00084 oid id() const throw () { return m_ID; } //[t48] 00085 00087 bool operator==(const largeobject &other) const //[t51] 00088 { return m_ID == other.m_ID; } 00090 bool operator!=(const largeobject &other) const //[t51] 00091 { return m_ID != other.m_ID; } 00093 bool operator<=(const largeobject &other) const //[t51] 00094 { return m_ID <= other.m_ID; } 00096 bool operator>=(const largeobject &other) const //[t51] 00097 { return m_ID >= other.m_ID; } 00099 bool operator<(const largeobject &other) const //[t51] 00100 { return m_ID < other.m_ID; } 00102 bool operator>(const largeobject &other) const //[t51] 00103 { return m_ID > other.m_ID; } 00104 00106 00110 void to_file(dbtransaction &T, const PGSTD::string &File) const; //[t52] 00111 00113 00117 void remove(dbtransaction &T) const; //[t48] 00118 00119 protected: 00120 static 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 // TODO: New hierarchy with separate read / write / mixed-mode access 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); //[t51] 00165 00167 00173 largeobjectaccess(dbtransaction &T, 00174 oid O, 00175 openmode mode = 00176 PGSTD::ios::in | 00177 PGSTD::ios::out); //[t52] 00178 00180 00185 largeobjectaccess(dbtransaction &T, 00186 largeobject O, 00187 openmode mode = PGSTD::ios::in | PGSTD::ios::out); //[t50] 00188 00190 00195 largeobjectaccess(dbtransaction &T, 00196 const PGSTD::string &File, 00197 openmode mode = 00198 PGSTD::ios::in | PGSTD::ios::out); //[t55] 00199 00200 ~largeobjectaccess() throw () { close(); } 00201 00203 00206 using largeobject::id; 00207 00209 00212 void to_file(const PGSTD::string &File) const //[t54] 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); //[t51] 00236 00238 00241 void write(const PGSTD::string &Buf) //[t50] 00242 { write(Buf.c_str(), Buf.size()); } 00243 00245 00251 size_type read(char Buf[], size_type Len); //[t50] 00252 00254 00257 size_type seek(size_type dest, seekdir dir); //[t51] 00258 00260 00268 pos_type cseek(off_type dest, seekdir dir) throw (); //[t50] 00269 00271 00277 off_type cwrite(const char Buf[], size_type Len) throw (); //[t50] 00278 00280 00286 off_type cread(char Buf[], size_type Len) throw (); //[t50] 00287 00288 00290 void process_notice(const PGSTD::string &) throw (); //[t50] 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 PGconn *RawConnection() { return largeobject::RawConnection(m_Trans); } 00304 00305 void open(openmode mode); 00306 void close() throw (); 00307 00308 dbtransaction &m_Trans; 00309 int m_fd; 00310 00311 // Not allowed: 00312 largeobjectaccess(); 00313 largeobjectaccess(const largeobjectaccess &); 00314 largeobjectaccess operator=(const largeobjectaccess &); 00315 }; 00316 00317 00319 00327 template<typename CHAR=char, typename TRAITS=PGSTD::char_traits<CHAR> > 00328 class largeobject_streambuf : 00329 #ifdef PQXX_HAVE_STREAMBUF 00330 public PGSTD::basic_streambuf<CHAR, TRAITS> 00331 #else 00332 public PGSTD::streambuf 00333 #endif 00334 { 00335 typedef long size_type; 00336 public: 00337 typedef CHAR char_type; 00338 typedef TRAITS traits_type; 00339 typedef typename traits_type::int_type int_type; 00340 #ifdef PQXX_HAVE_STREAMBUF 00341 typedef typename traits_type::pos_type pos_type; 00342 typedef typename traits_type::off_type off_type; 00343 #else 00344 typedef streamoff off_type; 00345 typedef streampos pos_type; 00346 #endif 00347 typedef largeobjectaccess::openmode openmode; 00348 typedef largeobjectaccess::seekdir seekdir; 00349 00350 largeobject_streambuf(dbtransaction &T, 00351 largeobject O, 00352 openmode mode = PGSTD::ios::in | PGSTD::ios::out, 00353 size_type BufSize=512) : //[t48] 00354 m_BufSize(BufSize), 00355 m_Obj(T, O), 00356 m_G(0), 00357 m_P(0) 00358 { 00359 initialize(mode); 00360 } 00361 00362 largeobject_streambuf(dbtransaction &T, 00363 oid O, 00364 openmode mode = PGSTD::ios::in | PGSTD::ios::out, 00365 size_type BufSize=512) : //[t48] 00366 m_BufSize(BufSize), 00367 m_Obj(T, O), 00368 m_G(0), 00369 m_P(0) 00370 { 00371 initialize(mode); 00372 } 00373 00374 virtual ~largeobject_streambuf() throw () 00375 { 00376 delete [] m_P; 00377 delete [] m_G; 00378 } 00379 00380 00382 void process_notice(const PGSTD::string &s) { m_Obj.process_notice(s); } 00383 00384 #ifdef PQXX_HAVE_STREAMBUF 00385 protected: 00386 #endif 00387 virtual int sync() 00388 { 00389 // setg() sets eback, gptr, egptr 00390 setg(this->eback(), this->eback(), this->egptr()); 00391 return overflow(EoF()); 00392 } 00393 00394 protected: 00395 virtual pos_type seekoff(off_type offset, 00396 seekdir dir, 00397 openmode mode) 00398 { 00399 if (mode != SEEK_CUR) 00400 throw PGSTD::logic_error("Offset "+to_string(int(mode))+" in seekoff()"); 00401 return AdjustEOF(m_Obj.cseek(offset, dir)); 00402 } 00403 00404 virtual pos_type seekpos(pos_type pos, openmode mode) 00405 { 00406 if (mode != SEEK_SET) 00407 throw PGSTD::logic_error("Offset "+to_string(int(mode))+" in seekpos()"); 00408 return AdjustEOF(m_Obj.cseek(pos, PGSTD::ios::beg)); 00409 } 00410 00411 virtual int_type overflow(int_type ch = EoF()) 00412 { 00413 char *const pp = this->pptr(); 00414 if (!pp) return EoF(); 00415 char *const pb = this->pbase(); 00416 int_type res = 0; 00417 00418 if (pp > pb) res = AdjustEOF(m_Obj.cwrite(pb, pp-pb)); 00419 setp(m_P, m_P + m_BufSize); 00420 00421 // Write that one more character, if it's there. 00422 if (ch != EoF()) 00423 { 00424 *this->pptr() = char(ch); 00425 this->pbump(1); 00426 } 00427 return res; 00428 } 00429 00430 virtual int_type underflow() 00431 { 00432 if (!this->gptr()) return EoF(); 00433 char *const eb = this->eback(); 00434 const int res = AdjustEOF(m_Obj.cread(this->eback(), m_BufSize)); 00435 setg(eb, eb, eb + ((res==EoF()) ? 0 : res)); 00436 return (!res || (res == EoF())) ? EoF() : *eb; 00437 } 00438 00439 private: 00441 static int_type EoF() { return traits_type::eof(); } 00442 00444 static PGSTD::streampos AdjustEOF(int pos) 00445 { 00446 return (pos == -1) ? EoF() : pos; 00447 } 00448 00449 void initialize(openmode mode) 00450 { 00451 if (mode & PGSTD::ios::in) 00452 { 00453 m_G = new char_type[m_BufSize]; 00454 setg(m_G, m_G, m_G); 00455 } 00456 if (mode & PGSTD::ios::out) 00457 { 00458 m_P = new char_type[m_BufSize]; 00459 setp(m_P, m_P + m_BufSize); 00460 } 00461 } 00462 00463 const size_type m_BufSize; 00464 largeobjectaccess m_Obj; 00465 00466 // Get & put buffers 00467 char_type *m_G, *m_P; 00468 }; 00469 00470 00472 00480 template<typename CHAR=char, typename TRAITS=PGSTD::char_traits<CHAR> > 00481 class basic_ilostream : 00482 #ifdef PQXX_HAVE_STREAMBUF 00483 public PGSTD::basic_istream<CHAR, TRAITS> 00484 #else 00485 public PGSTD::istream 00486 #endif 00487 { 00488 #ifdef PQXX_HAVE_STREAMBUF 00489 typedef PGSTD::basic_istream<CHAR, TRAITS> super; 00490 #else 00491 typedef PGSTD::istream super; 00492 #endif 00493 00494 public: 00495 typedef CHAR char_type; 00496 typedef TRAITS traits_type; 00497 typedef typename traits_type::int_type int_type; 00498 typedef typename traits_type::pos_type pos_type; 00499 typedef typename traits_type::off_type off_type; 00500 00502 00506 basic_ilostream(dbtransaction &T, 00507 largeobject O, 00508 largeobject::size_type BufSize=512) : //[t57] 00509 super(&m_Buf), 00510 m_Buf(T, O, PGSTD::ios::in, BufSize) 00511 { 00512 } 00513 00515 00519 basic_ilostream(dbtransaction &T, 00520 oid O, 00521 largeobject::size_type BufSize=512) : //[t48] 00522 super(&m_Buf), 00523 m_Buf(T, O, PGSTD::ios::in, BufSize) 00524 { 00525 } 00526 00527 private: 00528 largeobject_streambuf<CHAR,TRAITS> m_Buf; 00529 }; 00530 00531 typedef basic_ilostream<char> ilostream; 00532 00533 00535 00543 template<typename CHAR=char, typename TRAITS=PGSTD::char_traits<CHAR> > 00544 class basic_olostream : 00545 #ifdef PQXX_HAVE_STREAMBUF 00546 public PGSTD::basic_ostream<CHAR, TRAITS> 00547 #else 00548 public PGSTD::ostream 00549 #endif 00550 { 00551 #ifdef PQXX_HAVE_STREAMBUF 00552 typedef PGSTD::basic_ostream<CHAR, TRAITS> super; 00553 #else 00554 typedef PGSTD::ostream super; 00555 #endif 00556 public: 00557 typedef CHAR char_type; 00558 typedef TRAITS traits_type; 00559 typedef typename traits_type::int_type int_type; 00560 typedef typename traits_type::pos_type pos_type; 00561 typedef typename traits_type::off_type off_type; 00562 00564 00568 basic_olostream(dbtransaction &T, 00569 largeobject O, 00570 largeobject::size_type BufSize=512) : //[t48] 00571 super(&m_Buf), 00572 m_Buf(T, O, PGSTD::ios::out, BufSize) 00573 { 00574 } 00575 00577 00581 basic_olostream(dbtransaction &T, 00582 oid O, 00583 largeobject::size_type BufSize=512) : //[t57] 00584 super(&m_Buf), 00585 m_Buf(T, O, PGSTD::ios::out, BufSize) 00586 { 00587 } 00588 00589 ~basic_olostream() 00590 { 00591 try 00592 { 00593 #ifdef PQXX_HAVE_STREAMBUF 00594 m_Buf.pubsync(); m_Buf.pubsync(); 00595 #else 00596 m_Buf.sync(); m_Buf.sync(); 00597 #endif 00598 } 00599 catch (const PGSTD::exception &e) 00600 { 00601 m_Buf.process_notice(e.what()); 00602 } 00603 } 00604 00605 private: 00606 largeobject_streambuf<CHAR,TRAITS> m_Buf; 00607 }; 00608 00609 typedef basic_olostream<char> olostream; 00610 00611 00613 00621 template<typename CHAR=char, typename TRAITS=PGSTD::char_traits<CHAR> > 00622 class basic_lostream : 00623 #ifdef PQXX_HAVE_STREAMBUF 00624 public PGSTD::basic_iostream<CHAR, TRAITS> 00625 #else 00626 public PGSTD::iostream 00627 #endif 00628 { 00629 #ifdef PQXX_HAVE_STREAMBUF 00630 typedef PGSTD::basic_iostream<CHAR, TRAITS> super; 00631 #else 00632 typedef PGSTD::iostream super; 00633 #endif 00634 00635 public: 00636 typedef CHAR char_type; 00637 typedef TRAITS traits_type; 00638 typedef typename traits_type::int_type int_type; 00639 typedef typename traits_type::pos_type pos_type; 00640 typedef typename traits_type::off_type off_type; 00641 00643 00647 basic_lostream(dbtransaction &T, 00648 largeobject O, 00649 largeobject::size_type BufSize=512) : //[t59] 00650 super(&m_Buf), 00651 m_Buf(T, O, PGSTD::ios::in | PGSTD::ios::out, BufSize) 00652 { 00653 } 00654 00656 00660 basic_lostream(dbtransaction &T, 00661 oid O, 00662 largeobject::size_type BufSize=512) : //[t59] 00663 super(&m_Buf), 00664 m_Buf(T, O, PGSTD::ios::in | PGSTD::ios::out, BufSize) 00665 { 00666 } 00667 00668 ~basic_lostream() 00669 { 00670 try 00671 { 00672 #ifdef PQXX_HAVE_STREAMBUF 00673 m_Buf.pubsync(); m_Buf.pubsync(); 00674 #else 00675 m_Buf.sync(); m_Buf.sync(); 00676 #endif 00677 } 00678 catch (const PGSTD::exception &e) 00679 { 00680 m_Buf.process_notice(e.what()); 00681 } 00682 } 00683 00684 private: 00685 largeobject_streambuf<CHAR,TRAITS> m_Buf; 00686 }; 00687 00688 typedef basic_lostream<char> lostream; 00689 00690 } 00691 00692

Generated on Fri Jul 2 21:47:27 2004 for libpqxx by doxygen 1.3.7