libpqxx: largeobject.hxx Source File

libpqxx 4.0.1

- Main Page
- Related Pages
- Modules
- Namespaces
- Classes

largeobject.hxx
1 /*-------------------------------------------------------------------------
2 *
3 * FILE
4 * pqxx/largeobject.hxx
5 *
6 * DESCRIPTION
7 * libpqxx's Large Objects interface
8 * Allows access to large objects directly, or through I/O streams
9 * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/largeobject instead.
10 *
11 * Copyright (c) 2003-2012, Jeroen T. Vermeulen <jtv@xs4all.nl>
12 *
13 * See COPYING for copyright license. If you did not receive a file called
14 * COPYING with this source code, please notify the distributor of this mistake,
15 * or contact the author.
16 *
17 *-------------------------------------------------------------------------
18 */
19 #ifndef PQXX_H_LARGEOBJECT
20 #define PQXX_H_LARGEOBJECT
21
22 #include "pqxx/compiler-public.hxx"
23 #include "pqxx/compiler-internal-pre.hxx"
24
25 #ifdef PQXX_HAVE_STREAMBUF
26 #include <streambuf>
27 #else
28 #include <streambuf.h>
29 #endif
30
31 #include "pqxx/dbtransaction"
32
33
34 namespace pqxx
35 {
36
37 class largeobjectaccess;
38
40
47 class PQXX_LIBEXPORT largeobject
48 {
49 public:
50 typedef long size_type;
51
53 largeobject() throw (); //[t48]
54
56
58 explicit largeobject(dbtransaction &T); //[t48]
59
61
65 explicit largeobject(oid O) throw () : m_ID(O) {} //[t48]
66
68
72 largeobject(dbtransaction &T, const PGSTD::string &File); //[t53]
73
75
79 largeobject(const largeobjectaccess &O) throw (); //[t50]
80
82
86 oid id() const throw () { return m_ID; } //[t48]
87
96
97
98 bool operator==(const largeobject &other) const //[t51]
99 { return m_ID == other.m_ID; }
101
102 bool operator!=(const largeobject &other) const //[t51]
103 { return m_ID != other.m_ID; }
105
106 bool operator<=(const largeobject &other) const //[t51]
107 { return m_ID <= other.m_ID; }
109
110 bool operator>=(const largeobject &other) const //[t51]
111 { return m_ID >= other.m_ID; }
113
114 bool operator<(const largeobject &other) const //[t51]
115 { return m_ID < other.m_ID; }
117
118 bool operator>(const largeobject &other) const //[t51]
119 { return m_ID > other.m_ID; }
121
123
127 void to_file(dbtransaction &T, const PGSTD::string &File) const; //[t52]
128
130
134 void remove(dbtransaction &T) const; //[t48]
135
136 protected:
137 static internal::pq::PGconn * PQXX_PURE RawConnection(const dbtransaction &T);
138
139 PGSTD::string Reason(int err) const;
140
141 private:
142 oid m_ID;
143 };
144
145
146 // TODO: New hierarchy with separate read / write / mixed-mode access
147
149 class PQXX_LIBEXPORT largeobjectaccess : private largeobject
150 {
151 public:
152 using largeobject::size_type;
153 typedef long off_type;
154 typedef size_type pos_type;
155
157
161 typedef PGSTD::ios::openmode openmode;
162
164
168 typedef PGSTD::ios::seekdir seekdir;
169
171
175 explicit largeobjectaccess(dbtransaction &T,
176 openmode mode =
177 PGSTD::ios::in |
178 PGSTD::ios::out); //[t51]
179
181
187 largeobjectaccess(dbtransaction &T,
188 oid O,
189 openmode mode =
190 PGSTD::ios::in |
191 PGSTD::ios::out); //[t52]
192
194
199 largeobjectaccess(dbtransaction &T,
200 largeobject O,
201 openmode mode = PGSTD::ios::in | PGSTD::ios::out); //[t50]
202
204
209 largeobjectaccess(dbtransaction &T,
210 const PGSTD::string &File,
211 openmode mode =
212 PGSTD::ios::in | PGSTD::ios::out); //[t55]
213
214 ~largeobjectaccess() throw () { close(); }
215
217
220 using largeobject::id;
221
223
226 void to_file(const PGSTD::string &File) const //[t54]
227 { largeobject::to_file(m_Trans, File); }
228
229 #ifdef PQXX_BROKEN_USING_DECL
230
231
235 void to_file(dbtransaction &T, const PGSTD::string &F) const
236 { largeobject::to_file(T, F); }
237 #else
238 using largeobject::to_file;
239 #endif
240
245
246
250 void write(const char Buf[], size_type Len); //[t51]
251
253
256 void write(const PGSTD::string &Buf) //[t50]
257 { write(Buf.c_str(), static_cast<size_type>(Buf.size())); }
258
260
266 size_type read(char Buf[], size_type Len); //[t50]
267
269
272 size_type seek(size_type dest, seekdir dir); //[t51]
273
275
278 size_type tell() const; //[t50]
280
290
291
299 pos_type cseek(off_type dest, seekdir dir) throw (); //[t50]
300
302
308 off_type cwrite(const char Buf[], size_type Len) throw (); //[t50]
309
311
317 off_type cread(char Buf[], size_type Len) throw (); //[t50]
318
320
324 pos_type ctell() const throw (); //[t50]
326
331
332 void process_notice(const PGSTD::string &) throw (); //[t50]
334
335 using largeobject::remove;
336
337 using largeobject::operator==;
338 using largeobject::operator!=;
339 using largeobject::operator<;
340 using largeobject::operator<=;
341 using largeobject::operator>;
342 using largeobject::operator>=;
343
344 private:
345 PGSTD::string PQXX_PRIVATE Reason(int err) const;
346 internal::pq::PGconn *RawConnection() const
347 { return largeobject::RawConnection(m_Trans); }
348
349 void open(openmode mode);
350 void close() throw ();
351
352 dbtransaction &m_Trans;
353 int m_fd;
354
355 // Not allowed:
356 largeobjectaccess();
357 largeobjectaccess(const largeobjectaccess &);
358 largeobjectaccess operator=(const largeobjectaccess &);
359 };
360
361
363
371 template<typename CHAR=char, typename TRAITS=PGSTD::char_traits<CHAR> >
372 class largeobject_streambuf :
373 #ifdef PQXX_HAVE_STREAMBUF
374 public PGSTD::basic_streambuf<CHAR, TRAITS>
375 #else
376 public PGSTD::streambuf
377 #endif
378 {
379 typedef long size_type;
380 public:
381 typedef CHAR char_type;
382 typedef TRAITS traits_type;
383 typedef typename traits_type::int_type int_type;
384 #ifdef PQXX_HAVE_STREAMBUF
385 typedef typename traits_type::pos_type pos_type;
386 typedef typename traits_type::off_type off_type;
387 #else
388 typedef streamoff off_type;
389 typedef streampos pos_type;
390 #endif
391 typedef largeobjectaccess::openmode openmode;
392 typedef largeobjectaccess::seekdir seekdir;
393
394 largeobject_streambuf(dbtransaction &T,
395 largeobject O,
396 openmode mode = PGSTD::ios::in | PGSTD::ios::out,
397 size_type BufSize=512) : //[t48]
398 m_BufSize(BufSize),
399 m_Obj(T, O, mode),
400 m_G(0),
401 m_P(0)
402 { initialize(mode); }
403
404 largeobject_streambuf(dbtransaction &T,
405 oid O,
406 openmode mode = PGSTD::ios::in | PGSTD::ios::out,
407 size_type BufSize=512) : //[t48]
408 m_BufSize(BufSize),
409 m_Obj(T, O, mode),
410 m_G(0),
411 m_P(0)
412 { initialize(mode); }
413
414 virtual ~largeobject_streambuf() throw () { delete [] m_P; delete [] m_G; }
415
416
418 void process_notice(const PGSTD::string &s) { m_Obj.process_notice(s); }
419
420 #ifdef PQXX_HAVE_STREAMBUF
421 protected:
422 #endif
423 virtual int sync()
424 {
425 // setg() sets eback, gptr, egptr
426 this->setg(this->eback(), this->eback(), this->egptr());
427 return overflow(EoF());
428 }
429
430 protected:
431 virtual pos_type seekoff(off_type offset,
432 seekdir dir,
433 openmode)
434 {
435 return AdjustEOF(m_Obj.cseek(largeobjectaccess::off_type(offset), dir));
436 }
437
438 virtual pos_type seekpos(pos_type pos, openmode)
439 {
440 const largeobjectaccess::pos_type newpos = m_Obj.cseek(
441 largeobjectaccess::off_type(pos),
442 PGSTD::ios::beg);
443 return AdjustEOF(newpos);
444 }
445
446 virtual int_type overflow(int_type ch = EoF())
447 {
448 char *const pp = this->pptr();
449 if (!pp) return EoF();
450 char *const pb = this->pbase();
451 int_type res = 0;
452
453 if (pp > pb) res = int_type(AdjustEOF(m_Obj.cwrite(pb, pp-pb)));
454 this->setp(m_P, m_P + m_BufSize);
455
456 // Write that one more character, if it's there.
457 if (ch != EoF())
458 {
459 *this->pptr() = char(ch);
460 this->pbump(1);
461 }
462 return res;
463 }
464
465 virtual int_type underflow()
466 {
467 if (!this->gptr()) return EoF();
468 char *const eb = this->eback();
469 const int_type res(static_cast<int_type>(
470 AdjustEOF(m_Obj.cread(this->eback(), m_BufSize))));
471 this->setg(eb, eb, eb + ((res==EoF()) ? 0 : res));
472 return (!res || (res == EoF())) ? EoF() : *eb;
473 }
474
475 private:
477 static int_type EoF() { return traits_type::eof(); }
478
480 template<typename INTYPE>
481 static PGSTD::streampos AdjustEOF(INTYPE pos)
482 { return (pos==-1) ? PGSTD::streampos(EoF()) : PGSTD::streampos(pos); }
483
484 void initialize(openmode mode)
485 {
486 if (mode & PGSTD::ios::in)
487 {
488 m_G = new char_type[unsigned(m_BufSize)];
489 this->setg(m_G, m_G, m_G);
490 }
491 if (mode & PGSTD::ios::out)
492 {
493 m_P = new char_type[unsigned(m_BufSize)];
494 this->setp(m_P, m_P + m_BufSize);
495 }
496 }
497
498 const size_type m_BufSize;
499 largeobjectaccess m_Obj;
500
501 // Get & put buffers
502 char_type *m_G, *m_P;
503 };
504
505
507
515 template<typename CHAR=char, typename TRAITS=PGSTD::char_traits<CHAR> >
516 class basic_ilostream :
517 #ifdef PQXX_HAVE_STREAMBUF
518 public PGSTD::basic_istream<CHAR, TRAITS>
519 #else
520 public PGSTD::istream
521 #endif
522 {
523 #ifdef PQXX_HAVE_STREAMBUF
524 typedef PGSTD::basic_istream<CHAR, TRAITS> super;
525 #else
526 typedef PGSTD::istream super;
527 #endif
528
529 public:
530 typedef CHAR char_type;
531 typedef TRAITS traits_type;
532 typedef typename traits_type::int_type int_type;
533 typedef typename traits_type::pos_type pos_type;
534 typedef typename traits_type::off_type off_type;
535
537
542 basic_ilostream(dbtransaction &T,
543 largeobject O,
544 largeobject::size_type BufSize=512) : //[t57]
545 super(0),
546 m_Buf(T, O, PGSTD::ios::in, BufSize)
547 { super::init(&m_Buf); }
548
550
555 basic_ilostream(dbtransaction &T,
556 oid O,
557 largeobject::size_type BufSize=512) : //[t48]
558 super(0),
559 m_Buf(T, O, PGSTD::ios::in, BufSize)
560 { super::init(&m_Buf); }
561
562 private:
563 largeobject_streambuf<CHAR,TRAITS> m_Buf;
564 };
565
566 typedef basic_ilostream<char> ilostream;
567
568
570
578 template<typename CHAR=char, typename TRAITS=PGSTD::char_traits<CHAR> >
579 class basic_olostream :
580 #ifdef PQXX_HAVE_STREAMBUF
581 public PGSTD::basic_ostream<CHAR, TRAITS>
582 #else
583 public PGSTD::ostream
584 #endif
585 {
586 #ifdef PQXX_HAVE_STREAMBUF
587 typedef PGSTD::basic_ostream<CHAR, TRAITS> super;
588 #else
589 typedef PGSTD::ostream super;
590 #endif
591 public:
592 typedef CHAR char_type;
593 typedef TRAITS traits_type;
594 typedef typename traits_type::int_type int_type;
595 typedef typename traits_type::pos_type pos_type;
596 typedef typename traits_type::off_type off_type;
597
599
604 basic_olostream(dbtransaction &T,
605 largeobject O,
606 largeobject::size_type BufSize=512) : //[t48]
607 super(0),
608 m_Buf(T, O, PGSTD::ios::out, BufSize)
609 { super::init(&m_Buf); }
610
612
617 basic_olostream(dbtransaction &T,
618 oid O,
619 largeobject::size_type BufSize=512) : //[t57]
620 super(0),
621 m_Buf(T, O, PGSTD::ios::out, BufSize)
622 { super::init(&m_Buf); }
623
624 ~basic_olostream()
625 {
626 try
627 {
628 #ifdef PQXX_HAVE_STREAMBUF
629 m_Buf.pubsync(); m_Buf.pubsync();
630 #else
631 m_Buf.sync(); m_Buf.sync();
632 #endif
633 }
634 catch (const PGSTD::exception &e)
635 {
636 m_Buf.process_notice(e.what());
637 }
638 }
639
640 private:
641 largeobject_streambuf<CHAR,TRAITS> m_Buf;
642 };
643
644 typedef basic_olostream<char> olostream;
645
646
648
656 template<typename CHAR=char, typename TRAITS=PGSTD::char_traits<CHAR> >
657 class basic_lostream :
658 #ifdef PQXX_HAVE_STREAMBUF
659 public PGSTD::basic_iostream<CHAR, TRAITS>
660 #else
661 public PGSTD::iostream
662 #endif
663 {
664 #ifdef PQXX_HAVE_STREAMBUF
665 typedef PGSTD::basic_iostream<CHAR, TRAITS> super;
666 #else
667 typedef PGSTD::iostream super;
668 #endif
669
670 public:
671 typedef CHAR char_type;
672 typedef TRAITS traits_type;
673 typedef typename traits_type::int_type int_type;
674 typedef typename traits_type::pos_type pos_type;
675 typedef typename traits_type::off_type off_type;
676
678
683 basic_lostream(dbtransaction &T,
684 largeobject O,
685 largeobject::size_type BufSize=512) : //[t59]
686 super(0),
687 m_Buf(T, O, PGSTD::ios::in | PGSTD::ios::out, BufSize)
688 { super::init(&m_Buf); }
689
691
696 basic_lostream(dbtransaction &T,
697 oid O,
698 largeobject::size_type BufSize=512) : //[t59]
699 super(0),
700 m_Buf(T, O, PGSTD::ios::in | PGSTD::ios::out, BufSize)
701 { super::init(&m_Buf); }
702
703 ~basic_lostream()
704 {
705 try
706 {
707 #ifdef PQXX_HAVE_STREAMBUF
708 m_Buf.pubsync(); m_Buf.pubsync();
709 #else
710 m_Buf.sync(); m_Buf.sync();
711 #endif
712 }
713 catch (const PGSTD::exception &e)
714 {
715 m_Buf.process_notice(e.what());
716 }
717 }
718
719 private:
720 largeobject_streambuf<CHAR,TRAITS> m_Buf;
721 };
722
723 typedef basic_lostream<char> lostream;
724
725 } // namespace pqxx
726
727 #include "pqxx/compiler-internal-post.hxx"
728
729 #endif
730