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
00042 explicit LargeObject(TransactionItf &T);
00043
00045
00049 explicit LargeObject(Oid O) : m_ID(O) {}
00050
00052
00056 LargeObject(TransactionItf &T, const PGSTD::string &File);
00057
00059
00063 LargeObject(const LargeObjectAccess &O);
00064
00066
00069 Oid id() const throw () { return m_ID; }
00070
00072 bool operator==(const LargeObject &other) const
00073 { return m_ID == other.m_ID; }
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; }
00089
00091
00095 void to_file(TransactionItf &T, const char File[]) const;
00096
00098
00102 void to_file(TransactionItf &T, const PGSTD::string &File) const
00103 {
00104 to_file(T, File.c_str());
00105 }
00106
00107
00108
00110
00111 * @param T the transaction in which the object is to be deleted
00112 */
00113 int cunlink(TransactionItf &T) const throw ();
00114
00115 protected:
00116 static PGconn *RawConnection(const TransactionItf &T)
00117 {
00118 return T.Conn().RawConnection();
00119 }
00120
00121 private:
00122 Oid m_ID;
00123 };
00124
00125
00126
00128
00129 {
00130 public:
00132
00136 explicit LargeObjectAccess(TransactionItf &T,
00137 PGSTD::ios_base::openmode mode =
00138 PGSTD::ios_base::in |
00139 PGSTD::ios_base::out);
00140
00142
00148 explicit LargeObjectAccess(TransactionItf &T,
00149 Oid O,
00150 PGSTD::ios_base::openmode mode =
00151 PGSTD::ios_base::in |
00152 PGSTD::ios_base::out);
00153
00155
00160 explicit LargeObjectAccess(TransactionItf &T,
00161 LargeObject O,
00162 PGSTD::ios_base::openmode mode =
00163 PGSTD::ios_base::in |
00164 PGSTD::ios_base::out);
00165
00167
00172 LargeObjectAccess(TransactionItf &T,
00173 const PGSTD::string &File,
00174 PGSTD::ios_base::openmode mode =
00175 PGSTD::ios_base::in | PGSTD::ios_base::out);
00176
00177 ~LargeObjectAccess() { close(); }
00178
00180
00183 using LargeObject::id;
00184
00186
00189 void to_file(const char File[]) const
00190 {
00191 LargeObject::to_file(m_Trans, File);
00192 }
00193
00195
00198 void to_file(const PGSTD::string &File) const
00199 {
00200 LargeObject::to_file(m_Trans, File);
00201 }
00202
00203
00205
00206 * @param dest offset to go to
00207 * @param dir origin to which dest is relative: ios_base::beg (from beginning
00208 * of the object), ios_base::cur (from current access position), or
00209 * ios_base;:end (from end of object)
00210 */
00211 long cseek(long dest, PGSTD::ios_base::seekdir dir) throw ();
00212
00213
00215
00216 * @param Buf bytes to write
00217 * @param Len number of bytes to write
00218 */
00219 long cwrite(const char Buf[], size_t Len) throw ();
00220
00221
00223
00224 * @param Buf area where bytes should be stored
00225 * @param Len number of bytes to read
00226 */
00227 long cread(char Buf[], size_t Len) throw ();
00228
00229
00230
00231
00232 private:
00233 PGconn *RawConnection() { return LargeObject::RawConnection(m_Trans); }
00234
00235 void open(PGSTD::ios_base::openmode mode);
00236 void close();
00237
00238 TransactionItf &m_Trans;
00239 int m_fd;
00240
00241
00242 LargeObjectAccess();
00243 LargeObjectAccess(const LargeObjectAccess &);
00244 LargeObjectAccess operator=(const LargeObjectAccess &);
00245 };
00246
00247
00248
00250
00251 *
00252 * The standard streambuf classes provide uniform access to data storage such
00253 * as files or string buffers, so they can be accessed using standard input or
00254 * output streams. This streambuf implementation provides similar access to
00255 * large objects, so they can be read and written using the same stream classes.
00256 */
00257 template<typename CHAR=char, typename TRAITS=PGSTD::char_traits<CHAR> >
00258 class largeobject_streambuf : public PGSTD::basic_streambuf<CHAR, TRAITS>
00259 {
00260 public:
00261 typedef CHAR char_type;
00262 typedef TRAITS traits_type;
00263 typedef typename traits_type::int_type int_type;
00264 typedef typename traits_type::pos_type pos_type;
00265 typedef typename traits_type::off_type off_type;
00266
00267 largeobject_streambuf(TransactionItf &T,
00268 LargeObject O,
00269 PGSTD::ios_base::openmode mode =
00270 PGSTD::ios::in | PGSTD::ios::out) :
00271 m_BufSize(512),
00272 m_Obj(T, O),
00273 m_G(0),
00274 m_P(0)
00275 {
00276 initialize(mode);
00277 }
00278
00279 largeobject_streambuf(TransactionItf &T,
00280 Oid O,
00281 PGSTD::ios_base::openmode mode =
00282 PGSTD::ios::in | PGSTD::ios::out) :
00283 m_BufSize(512),
00284 m_Obj(T, O),
00285 m_G(0),
00286 m_P(0)
00287 {
00288 initialize(mode);
00289 }
00290
00291 virtual ~largeobject_streambuf()
00292 {
00293 delete [] m_P;
00294 delete [] m_G;
00295 }
00296
00297
00298 protected:
00299 virtual int sync()
00300 {
00301
00302 setg(eback(), eback(), egptr());
00303 return overflow(EoF());
00304 }
00305
00306 virtual pos_type seekoff(off_type offset,
00307 PGSTD::ios_base::seekdir dir,
00308 PGSTD::ios_base::openmode mode =
00309 PGSTD::ios_base::in|PGSTD::ios_base::out)
00310 {
00311 if (!mode) {}
00312 return AdjustEOF(m_Obj.cseek(offset, dir));
00313 }
00314
00315 virtual pos_type seekpos(pos_type pos,
00316 PGSTD::ios_base::openmode mode =
00317 PGSTD::ios_base::in|PGSTD::ios_base::out)
00318 {
00319 if (!mode) {}
00320 return AdjustEOF(m_Obj.cseek(pos, PGSTD::ios_base::beg));
00321 }
00322
00323 virtual int_type overflow(int_type ch = EoF())
00324 {
00325 char *const pp = pptr();
00326 if (!pp) return EoF();
00327 char *const pb = pbase();
00328 int_type result = 0;
00329
00330 if (pp > pb) result = AdjustEOF(m_Obj.cwrite(pb, pp-pb));
00331 setp(m_P, m_P + m_BufSize);
00332
00333
00334 if (ch != EoF())
00335 {
00336 *pptr() = char(ch);
00337 pbump(1);
00338 }
00339 return result;
00340 }
00341
00342 virtual int_type underflow()
00343 {
00344 if (!gptr()) return EoF();
00345 char *const eb = eback();
00346 const int result = AdjustEOF(m_Obj.cread(eback(), m_BufSize));
00347 setg(eb, eb, eb + ((result==EoF()) ? 0 : result));
00348 return (!result || (result == EoF())) ? EoF() : *eb;
00349 }
00350
00351 private:
00353 static int_type EoF() { return traits_type::eof(); }
00354
00356 static PGSTD::streampos AdjustEOF(int pos)
00357 {
00358 return (pos == -1) ? EoF() : pos;
00359 }
00360
00361 void initialize(PGSTD::ios_base::openmode mode)
00362 {
00363 if (mode & PGSTD::ios::in)
00364 {
00365 m_G = new char_type[m_BufSize];
00366 setg(m_G, m_G, m_G);
00367 }
00368 if (mode & PGSTD::ios::out)
00369 {
00370 m_P = new char_type[m_BufSize];
00371 setp(m_P, m_P + m_BufSize);
00372 }
00373 }
00374
00375 const size_t m_BufSize;
00376 LargeObjectAccess m_Obj;
00377
00378
00379 char_type *m_G, *m_P;
00380 };
00381
00382 }
00383
00384 #endif
00385