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 <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 LargeObject();
00041
00043
00045 explicit LargeObject(TransactionItf &T);
00046
00048
00052 explicit LargeObject(Oid O) : m_ID(O) {}
00053
00055
00059 LargeObject(TransactionItf &T, const PGSTD::string &File);
00060
00062
00066 LargeObject(const LargeObjectAccess &O);
00067
00069
00072 Oid id() const throw () { return m_ID; }
00073
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; }
00090 bool operator>(const LargeObject &other) const
00091 { return m_ID > other.m_ID; }
00092
00094
00098 void to_file(TransactionItf &T, const char File[]) const;
00099
00101
00105 void to_file(TransactionItf &T, const PGSTD::string &File) const
00106 {
00107 to_file(T, File.c_str());
00108 }
00109
00111
00115 void remove(TransactionItf &T) const;
00116
00117 protected:
00118 static PGconn *RawConnection(const TransactionItf &T)
00119 {
00120 return T.Conn().RawConnection();
00121 }
00122
00123 private:
00124 Oid m_ID;
00125 };
00126
00127
00128
00130
00131 {
00132 public:
00134
00138 explicit LargeObjectAccess(TransactionItf &T,
00139 PGSTD::ios_base::openmode mode =
00140 PGSTD::ios_base::in |
00141 PGSTD::ios_base::out);
00142
00144
00150 explicit LargeObjectAccess(TransactionItf &T,
00151 Oid O,
00152 PGSTD::ios_base::openmode mode =
00153 PGSTD::ios_base::in |
00154 PGSTD::ios_base::out);
00155
00157
00162 explicit LargeObjectAccess(TransactionItf &T,
00163 LargeObject O,
00164 PGSTD::ios_base::openmode mode =
00165 PGSTD::ios_base::in |
00166 PGSTD::ios_base::out);
00167
00169
00174 LargeObjectAccess(TransactionItf &T,
00175 const PGSTD::string &File,
00176 PGSTD::ios_base::openmode mode =
00177 PGSTD::ios_base::in | PGSTD::ios_base::out);
00178
00179 ~LargeObjectAccess() { close(); }
00180
00182
00185 using LargeObject::id;
00186
00188
00191 void to_file(const char File[]) const
00192 {
00193 LargeObject::to_file(m_Trans, File);
00194 }
00195
00197
00200 void to_file(const PGSTD::string &File) const
00201 {
00202 LargeObject::to_file(m_Trans, File);
00203 }
00204
00205
00207
00208 * @param dest offset to go to
00209 * @param dir origin to which dest is relative: ios_base::beg (from beginning
00210 * of the object), ios_base::cur (from current access position), or
00211 * ios_base;:end (from end of object)
00212 */
00213 long cseek(long dest, PGSTD::ios_base::seekdir dir) throw ();
00214
00215
00217
00218 * @param Buf bytes to write
00219 * @param Len number of bytes to write
00220 */
00221 long cwrite(const char Buf[], size_t Len) throw ();
00222
00223
00225
00226 * @param Buf area where bytes should be stored
00227 * @param Len number of bytes to read
00228 */
00229 long cread(char Buf[], size_t Len) throw ();
00230
00231
00232
00233
00234 private:
00235 PGconn *RawConnection() { return LargeObject::RawConnection(m_Trans); }
00236
00237 void open(PGSTD::ios_base::openmode mode);
00238 void close();
00239
00240 TransactionItf &m_Trans;
00241 int m_fd;
00242
00243
00244 LargeObjectAccess();
00245 LargeObjectAccess(const LargeObjectAccess &);
00246 LargeObjectAccess operator=(const LargeObjectAccess &);
00247 };
00248
00249
00250
00251
00253
00254 *
00255 * The standard streambuf classes provide uniform access to data storage such
00256 * as files or string buffers, so they can be accessed using standard input or
00257 * output streams. This streambuf implementation provides similar access to
00258 * large objects, so they can be read and written using the same stream classes.
00259 */
00260 template<typename CHAR=char, typename TRAITS=PGSTD::char_traits<CHAR> >
00261 class largeobject_streambuf : public PGSTD::basic_streambuf<CHAR, TRAITS>
00262 {
00263 public:
00264 typedef CHAR char_type;
00265 typedef TRAITS traits_type;
00266 typedef typename traits_type::int_type int_type;
00267 typedef typename traits_type::pos_type pos_type;
00268 typedef typename traits_type::off_type off_type;
00269
00270 largeobject_streambuf(TransactionItf &T,
00271 LargeObject O,
00272 PGSTD::ios_base::openmode mode =
00273 PGSTD::ios::in | PGSTD::ios::out) :
00274 m_BufSize(512),
00275 m_Obj(T, O),
00276 m_G(0),
00277 m_P(0)
00278 {
00279 initialize(mode);
00280 }
00281
00282 largeobject_streambuf(TransactionItf &T,
00283 Oid O,
00284 PGSTD::ios_base::openmode mode =
00285 PGSTD::ios::in | PGSTD::ios::out) :
00286 m_BufSize(512),
00287 m_Obj(T, O),
00288 m_G(0),
00289 m_P(0)
00290 {
00291 initialize(mode);
00292 }
00293
00294 virtual ~largeobject_streambuf()
00295 {
00296 delete [] m_P;
00297 delete [] m_G;
00298 }
00299
00300
00301 protected:
00302 virtual int sync()
00303 {
00304
00305 setg(eback(), eback(), egptr());
00306 return overflow(EoF());
00307 }
00308
00309 virtual pos_type seekoff(off_type offset,
00310 PGSTD::ios_base::seekdir dir,
00311 PGSTD::ios_base::openmode mode =
00312 PGSTD::ios_base::in|PGSTD::ios_base::out)
00313 {
00314 if (!mode) {}
00315 return AdjustEOF(m_Obj.cseek(offset, dir));
00316 }
00317
00318 virtual pos_type seekpos(pos_type pos,
00319 PGSTD::ios_base::openmode mode =
00320 PGSTD::ios_base::in|PGSTD::ios_base::out)
00321 {
00322 if (!mode) {}
00323 return AdjustEOF(m_Obj.cseek(pos, PGSTD::ios_base::beg));
00324 }
00325
00326 virtual int_type overflow(int_type ch = EoF())
00327 {
00328 char *const pp = pptr();
00329 if (!pp) return EoF();
00330 char *const pb = pbase();
00331 int_type result = 0;
00332
00333 if (pp > pb) result = AdjustEOF(m_Obj.cwrite(pb, pp-pb));
00334 setp(m_P, m_P + m_BufSize);
00335
00336
00337 if (ch != EoF())
00338 {
00339 *pptr() = char(ch);
00340 pbump(1);
00341 }
00342 return result;
00343 }
00344
00345 virtual int_type underflow()
00346 {
00347 if (!gptr()) return EoF();
00348 char *const eb = eback();
00349 const int result = AdjustEOF(m_Obj.cread(eback(), m_BufSize));
00350 setg(eb, eb, eb + ((result==EoF()) ? 0 : result));
00351 return (!result || (result == EoF())) ? EoF() : *eb;
00352 }
00353
00354 private:
00356 static int_type EoF() { return traits_type::eof(); }
00357
00359 static PGSTD::streampos AdjustEOF(int pos)
00360 {
00361 return (pos == -1) ? EoF() : pos;
00362 }
00363
00364 void initialize(PGSTD::ios_base::openmode mode)
00365 {
00366 if (mode & PGSTD::ios_base::in)
00367 {
00368 m_G = new char_type[m_BufSize];
00369 setg(m_G, m_G, m_G);
00370 }
00371 if (mode & PGSTD::ios_base::out)
00372 {
00373 m_P = new char_type[m_BufSize];
00374 setp(m_P, m_P + m_BufSize);
00375 }
00376 }
00377
00378 const size_t m_BufSize;
00379 LargeObjectAccess m_Obj;
00380
00381
00382 char_type *m_G, *m_P;
00383 };
00384
00385
00386 template<typename CHAR=char, typename TRAITS=PGSTD::char_traits<CHAR> >
00387 class basic_ilostream : public PGSTD::basic_istream<CHAR, TRAITS>
00388 {
00389 public:
00390 typedef CHAR char_type;
00391 typedef TRAITS traits_type;
00392 typedef typename traits_type::int_type int_type;
00393 typedef typename traits_type::pos_type pos_type;
00394 typedef typename traits_type::off_type off_type;
00395
00396 basic_ilostream(TransactionItf &T, LargeObject O) :
00397 PGSTD::basic_istream<CHAR,TRAITS>(&m_Buf),
00398 m_Buf(T, O, PGSTD::ios_base::in)
00399 {
00400 }
00401
00402 basic_ilostream(TransactionItf &T, Oid O) :
00403 PGSTD::basic_istream<CHAR,TRAITS>(&m_Buf),
00404 m_Buf(T, O, PGSTD::ios_base::in)
00405 {
00406 }
00407
00408 private:
00409 largeobject_streambuf<CHAR,TRAITS> m_Buf;
00410 };
00411
00412 typedef basic_ilostream<char> ilostream;
00413
00414 template<typename CHAR=char, typename TRAITS=PGSTD::char_traits<CHAR> >
00415 class basic_olostream : public PGSTD::basic_ostream<CHAR, TRAITS>
00416 {
00417 public:
00418 typedef CHAR char_type;
00419 typedef TRAITS traits_type;
00420 typedef typename traits_type::int_type int_type;
00421 typedef typename traits_type::pos_type pos_type;
00422 typedef typename traits_type::off_type off_type;
00423
00424 basic_olostream(TransactionItf &T, LargeObject O) :
00425 PGSTD::basic_ostream<CHAR,TRAITS>(&m_Buf),
00426 m_Buf(T, O, PGSTD::ios_base::out)
00427 {
00428 }
00429
00430 basic_olostream(TransactionItf &T, Oid O) :
00431 PGSTD::basic_ostream<CHAR,TRAITS>(&m_Buf),
00432 m_Buf(T, O, PGSTD::ios_base::out)
00433 {
00434 }
00435
00436 ~basic_olostream() { m_Buf.pubsync(); m_Buf.pubsync(); }
00437
00438 private:
00439 largeobject_streambuf<CHAR,TRAITS> m_Buf;
00440 };
00441
00442 typedef basic_olostream<char> olostream;
00443
00444
00445 template<typename CHAR=char, typename TRAITS=PGSTD::char_traits<CHAR> >
00446 class basic_lostream : public PGSTD::basic_iostream<CHAR, TRAITS>
00447 {
00448 public:
00449 typedef CHAR char_type;
00450 typedef TRAITS traits_type;
00451 typedef typename traits_type::int_type int_type;
00452 typedef typename traits_type::pos_type pos_type;
00453 typedef typename traits_type::off_type off_type;
00454
00455 basic_lostream(TransactionItf &T, LargeObject O) :
00456 PGSTD::basic_iostream<CHAR,TRAITS>(&m_Buf),
00457 m_Buf(T, O)
00458 {
00459 }
00460
00461 basic_lostream(TransactionItf &T, Oid O) :
00462 PGSTD::basic_iostream<CHAR,TRAITS>(&m_Buf),
00463 m_Buf(T, O)
00464 {
00465 }
00466
00467 ~basic_lostream() { m_Buf.pubsync(); m_Buf.pubsync(); }
00468
00469 private:
00470 largeobject_streambuf<CHAR,TRAITS> m_Buf;
00471 };
00472
00473 typedef basic_lostream<char> lostream;
00474
00475 }
00476
00477 #endif
00478