00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 #ifndef PQXX_LARGEOBJECT_H
00015 #define PQXX_LARGEOBJECT_H
00016
00017 #include <pqxx/config.h>
00018
00019 #ifdef HAVE_STREAMBUF
00020 #include <streambuf>
00021 #else
00022 #include <streambuf.h>
00023 #endif
00024
00025 #include <pqxx/transaction_base.h>
00026
00027
00028 namespace pqxx
00029 {
00030
00031 class LargeObjectAccess;
00032
00033
00035
00042 class LargeObject
00043 {
00044 public:
00045 typedef long size_type;
00046
00048 LargeObject();
00049
00051
00053 explicit LargeObject(Transaction_base &T);
00054
00056
00060 explicit LargeObject(Oid O) : m_ID(O) {}
00061
00063
00067 LargeObject(Transaction_base &T, const PGSTD::string &File);
00068
00070
00074 LargeObject(const LargeObjectAccess &O);
00075
00077
00080 Oid id() const throw () { return m_ID; }
00081
00083 bool operator==(const LargeObject &other) const
00084 { return m_ID == other.m_ID; }
00086 bool operator!=(const LargeObject &other) const
00087 { return m_ID != other.m_ID; }
00089 bool operator<=(const LargeObject &other) const
00090 { return m_ID <= other.m_ID; }
00092 bool operator>=(const LargeObject &other) const
00093 { return m_ID >= other.m_ID; }
00095 bool operator<(const LargeObject &other) const
00096 { return m_ID < other.m_ID; }
00098 bool operator>(const LargeObject &other) const
00099 { return m_ID > other.m_ID; }
00100
00102
00106 void to_file(Transaction_base &T, const PGSTD::string &File) const;
00107
00109
00113 void remove(Transaction_base &T) const;
00114
00115 protected:
00116 static PGconn *RawConnection(const Transaction_base &T)
00117 {
00118 return T.Conn().RawConnection();
00119 }
00120
00121 PGSTD::string Reason() const;
00122
00123 private:
00124 Oid m_ID;
00125 };
00126
00127
00129 class LargeObjectAccess : private LargeObject
00130 {
00131 public:
00132 using LargeObject::size_type;
00133
00135
00139 typedef PGSTD::ios::openmode openmode;
00140
00142
00146 typedef PGSTD::ios::seekdir seekdir;
00147
00149
00153 explicit LargeObjectAccess(Transaction_base &T,
00154 openmode mode =
00155 PGSTD::ios::in |
00156 PGSTD::ios::out);
00157
00159
00165 LargeObjectAccess(Transaction_base &T,
00166 Oid O,
00167 openmode mode =
00168 PGSTD::ios::in |
00169 PGSTD::ios::out);
00170
00172
00177 LargeObjectAccess(Transaction_base &T,
00178 LargeObject O,
00179 openmode mode = PGSTD::ios::in | PGSTD::ios::out);
00180
00182
00187 LargeObjectAccess(Transaction_base &T,
00188 const PGSTD::string &File,
00189 openmode mode =
00190 PGSTD::ios::in | PGSTD::ios::out);
00191
00192 ~LargeObjectAccess() { close(); }
00193
00195
00198 using LargeObject::id;
00199
00201
00204 void to_file(const PGSTD::string &File) const
00205 {
00206 LargeObject::to_file(m_Trans, File);
00207 }
00208
00210
00214 void write(const char Buf[], size_type Len);
00215
00217
00220 void write(const PGSTD::string &Buf)
00221 { write(Buf.c_str(), Buf.size()); }
00222
00224
00230 size_type read(char Buf[], size_type Len);
00231
00233
00236 size_type seek(size_type dest, seekdir dir);
00237
00239
00247 long cseek(long dest, seekdir dir) throw ();
00248
00250
00256 long cwrite(const char Buf[], size_type Len) throw ();
00257
00259
00265 long cread(char Buf[], size_type Len) throw ();
00266
00267 using LargeObject::operator==;
00268 using LargeObject::operator!=;
00269 using LargeObject::operator<;
00270 using LargeObject::operator<=;
00271 using LargeObject::operator>;
00272 using LargeObject::operator>=;
00273
00274 private:
00275 PGSTD::string Reason() const;
00276 PGconn *RawConnection() { return LargeObject::RawConnection(m_Trans); }
00277
00278 void open(openmode mode);
00279 void close();
00280
00281 Transaction_base &m_Trans;
00282 int m_fd;
00283
00284
00285 LargeObjectAccess();
00286 LargeObjectAccess(const LargeObjectAccess &);
00287 LargeObjectAccess operator=(const LargeObjectAccess &);
00288 };
00289
00290
00292
00297 template<typename CHAR=char, typename TRAITS=PGSTD::char_traits<CHAR> >
00298 class largeobject_streambuf :
00299 #ifdef HAVE_STREAMBUF
00300 public PGSTD::basic_streambuf<CHAR, TRAITS>
00301 #else
00302 public PGSTD::streambuf
00303 #endif
00304 {
00305 typedef long size_type;
00306 public:
00307 typedef CHAR char_type;
00308 typedef TRAITS traits_type;
00309 typedef typename traits_type::int_type int_type;
00310 typedef typename traits_type::pos_type pos_type;
00311 typedef typename traits_type::off_type off_type;
00312 typedef LargeObjectAccess::openmode openmode;
00313 typedef LargeObjectAccess::seekdir seekdir;
00314
00315 largeobject_streambuf(Transaction_base &T,
00316 LargeObject O,
00317 openmode mode = in | out,
00318 size_type BufSize=512) :
00319 m_BufSize(BufSize),
00320 m_Obj(T, O),
00321 m_G(0),
00322 m_P(0)
00323 {
00324 initialize(mode);
00325 }
00326
00327 largeobject_streambuf(Transaction_base &T,
00328 Oid O,
00329 openmode mode = in | out,
00330 size_type BufSize=512) :
00331 m_BufSize(BufSize),
00332 m_Obj(T, O),
00333 m_G(0),
00334 m_P(0)
00335 {
00336 initialize(mode);
00337 }
00338
00339 virtual ~largeobject_streambuf()
00340 {
00341 delete [] m_P;
00342 delete [] m_G;
00343 }
00344
00345
00346 #ifdef HAVE_STREAMBUF
00347 protected:
00348 #endif
00349 virtual int sync()
00350 {
00351
00352 setg(eback(), eback(), egptr());
00353 return overflow(EoF());
00354 }
00355
00356 protected:
00357 virtual pos_type seekoff(off_type offset,
00358 seekdir dir,
00359 openmode mode = in|out)
00360 {
00361 if (!mode) {}
00362 return AdjustEOF(m_Obj.cseek(offset, dir));
00363 }
00364
00365 virtual pos_type seekpos(pos_type pos,
00366 openmode mode = in|out)
00367 {
00368 if (!mode) {}
00369 return AdjustEOF(m_Obj.cseek(pos, PGSTD::ios::beg));
00370 }
00371
00372 virtual int_type overflow(int_type ch = EoF())
00373 {
00374 char *const pp = pptr();
00375 if (!pp) return EoF();
00376 char *const pb = pbase();
00377 int_type result = 0;
00378
00379 if (pp > pb) result = AdjustEOF(m_Obj.cwrite(pb, pp-pb));
00380 setp(m_P, m_P + m_BufSize);
00381
00382
00383 if (ch != EoF())
00384 {
00385 *pptr() = char(ch);
00386 pbump(1);
00387 }
00388 return result;
00389 }
00390
00391 virtual int_type underflow()
00392 {
00393 if (!gptr()) return EoF();
00394 char *const eb = eback();
00395 const int result = AdjustEOF(m_Obj.cread(eback(), m_BufSize));
00396 setg(eb, eb, eb + ((result==EoF()) ? 0 : result));
00397 return (!result || (result == EoF())) ? EoF() : *eb;
00398 }
00399
00400 private:
00402 static int_type EoF() { return traits_type::eof(); }
00403
00405 static PGSTD::streampos AdjustEOF(int pos)
00406 {
00407 return (pos == -1) ? EoF() : pos;
00408 }
00409
00410 void initialize(openmode mode)
00411 {
00412 if (mode & PGSTD::ios::in)
00413 {
00414 m_G = new char_type[m_BufSize];
00415 setg(m_G, m_G, m_G);
00416 }
00417 if (mode & PGSTD::ios::out)
00418 {
00419 m_P = new char_type[m_BufSize];
00420 setp(m_P, m_P + m_BufSize);
00421 }
00422 }
00423
00424 const size_type m_BufSize;
00425 LargeObjectAccess m_Obj;
00426
00427
00428 char_type *m_G, *m_P;
00429 };
00430
00431
00433
00440 template<typename CHAR=char, typename TRAITS=PGSTD::char_traits<CHAR> >
00441 class basic_ilostream :
00442 #ifdef HAVE_STREAMBUF
00443 public PGSTD::basic_istream<CHAR, TRAITS>
00444 #else
00445 public PGSTD::istream
00446 #endif
00447 {
00448 #ifdef HAVE_STREAMBUF
00449 typedef PGSTD::basic_istream<CHAR, TRAITS> super;
00450 #else
00451 typedef PGSTD::istream super;
00452 #endif
00453
00454 public:
00455 typedef CHAR char_type;
00456 typedef TRAITS traits_type;
00457 typedef typename traits_type::int_type int_type;
00458 typedef typename traits_type::pos_type pos_type;
00459 typedef typename traits_type::off_type off_type;
00460
00462
00466 basic_ilostream(Transaction_base &T,
00467 LargeObject O,
00468 LargeObject::size_type BufSize=512) :
00469 super(m_Buf),
00470 m_Buf(T, O, in, BufSize)
00471 {
00472 }
00473
00475
00479 basic_ilostream(Transaction_base &T,
00480 Oid O,
00481 LargeObject::size_type BufSize=512) :
00482 super(&m_Buf),
00483 m_Buf(T, O, in, BufSize)
00484 {
00485 }
00486
00487 private:
00488 largeobject_streambuf<CHAR,TRAITS> m_Buf;
00489 };
00490
00491 typedef basic_ilostream<char> ilostream;
00492
00493
00495
00502 template<typename CHAR=char, typename TRAITS=PGSTD::char_traits<CHAR> >
00503 class basic_olostream :
00504 #ifdef HAVE_STREAMBUF
00505 public PGSTD::basic_ostream<CHAR, TRAITS>
00506 #else
00507 public PGSTD::ostream
00508 #endif
00509 {
00510 #ifdef HAVE_STREAMBUF
00511 typedef PGSTD::basic_ostream<CHAR, TRAITS> super;
00512 #else
00513 typedef PGSTD::ostream super;
00514 #endif
00515 public:
00516 typedef CHAR char_type;
00517 typedef TRAITS traits_type;
00518 typedef typename traits_type::int_type int_type;
00519 typedef typename traits_type::pos_type pos_type;
00520 typedef typename traits_type::off_type off_type;
00521
00523
00527 basic_olostream(Transaction_base &T,
00528 LargeObject O,
00529 LargeObject::size_type BufSize=512) :
00530 super(&m_Buf),
00531 m_Buf(T, O, out, BufSize)
00532 {
00533 }
00534
00536
00540 basic_olostream(Transaction_base &T,
00541 Oid O,
00542 LargeObject::size_type BufSize=512) :
00543 super(&m_Buf),
00544 m_Buf(T, O, out, BufSize)
00545 {
00546 }
00547
00548 ~basic_olostream()
00549 {
00550 #ifdef HAVE_STREAMBUF
00551 m_Buf.pubsync(); m_Buf.pubsync();
00552 #else
00553 m_Buf.sync(); m_Buf.sync();
00554 #endif
00555 }
00556
00557 private:
00558 largeobject_streambuf<CHAR,TRAITS> m_Buf;
00559 };
00560
00561 typedef basic_olostream<char> olostream;
00562
00563
00565
00572 template<typename CHAR=char, typename TRAITS=PGSTD::char_traits<CHAR> >
00573 class basic_lostream :
00574 #ifdef HAVE_STREAMBUF
00575 public PGSTD::basic_iostream<CHAR, TRAITS>
00576 #else
00577 public PGSTD::iostream
00578 #endif
00579 {
00580 #ifdef HAVE_STREAMBUF
00581 typedef PGSTD::basic_iostream<CHAR, TRAITS> super;
00582 #else
00583 typedef PGSTD::iostream super;
00584 #endif
00585
00586 public:
00587 typedef CHAR char_type;
00588 typedef TRAITS traits_type;
00589 typedef typename traits_type::int_type int_type;
00590 typedef typename traits_type::pos_type pos_type;
00591 typedef typename traits_type::off_type off_type;
00592
00594
00598 basic_lostream(Transaction_base &T,
00599 LargeObject O,
00600 LargeObject::size_type BufSize=512) :
00601 super(&m_Buf),
00602 m_Buf(T, O, in | out, BufSize)
00603 {
00604 }
00605
00607
00611 basic_lostream(Transaction_base &T,
00612 Oid O,
00613 LargeObject::size_type BufSize=512) :
00614 super(&m_Buf),
00615 m_Buf(T, O, in | out, BufSize)
00616 {
00617 }
00618
00619 ~basic_lostream()
00620 {
00621 #ifdef HAVE_STREAMBUF
00622 m_Buf.pubsync(); m_Buf.pubsync();
00623 #else
00624 m_Buf.sync(); m_Buf.sync();
00625 #endif
00626 }
00627
00628 private:
00629 largeobject_streambuf<CHAR,TRAITS> m_Buf;
00630 };
00631
00632 typedef basic_lostream<char> lostream;
00633
00634 }
00635
00636 #endif
00637