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 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 // 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 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 // Not allowed: 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) : //[t48] 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) : //[t48] 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 // setg() sets eback, gptr, egptr 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 // Write that one more character, if it's there. 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 // Get & put buffers 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) : //[t57] 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) : //[t48] 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) : //[t48] 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) : //[t57] 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) : //[t59] 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) : //[t59] 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

Generated on Thu Aug 12 23:56:27 2004 for libpqxx by doxygen 1.3.8