libpqxx: util.hxx Source File

libpqxx 4.0.1

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

util.hxx
1 /*-------------------------------------------------------------------------
2 *
3 * FILE
4 * pqxx/util.hxx
5 *
6 * DESCRIPTION
7 * Various utility definitions for libpqxx
8 * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/util instead.
9 *
10 * Copyright (c) 2001-2012, Jeroen T. Vermeulen <jtv@xs4all.nl>
11 *
12 * See COPYING for copyright license. If you did not receive a file called
13 * COPYING with this source code, please notify the distributor of this mistake,
14 * or contact the author.
15 *
16 *-------------------------------------------------------------------------
17 */
18 #ifndef PQXX_H_UTIL
19 #define PQXX_H_UTIL
20
21 #include "pqxx/compiler-public.hxx"
22
23 #include <cstdio>
24 #include <cctype>
25 #include <stdexcept>
26 #include <string>
27 #include <typeinfo>
28 #include <vector>
29
30 #ifdef PQXX_TR1_HEADERS
31 #include <tr1/memory>
32 #else
33 #include <memory>
34 #endif
35
36 #include "pqxx/strconv"
37
38
261
262 namespace pqxx {}
263
265
270 namespace PGSTD {}
271
272 #include <pqxx/internal/libpq-forward.hxx>
273
274
275 namespace pqxx
276 {
278
280 struct PQXX_LIBEXPORT thread_safety_model
281 {
283
290 bool have_safe_strerror;
291
293
300 bool safe_libpq;
301
303
306 bool safe_query_cancel;
307
309
314 bool safe_result_copy;
315
317
323 bool safe_kerberos;
324
326 PGSTD::string description;
327 };
328
330 thread_safety_model PQXX_LIBEXPORT describe_thread_safety() throw ();
331
333 const oid oid_none = 0;
334
336
358 template<typename T=PGSTD::string, typename CONT=PGSTD::vector<T> >
359 class items : public CONT
360 {
361 public:
363 items() : CONT() {} //[t0]
365 explicit items(const T &t) : CONT() { this->push_back(t); } //[t0]
366 items(const T &t1, const T &t2) : CONT() //[t0]
367 { this->push_back(t1); this->push_back(t2); }
368 items(const T &t1, const T &t2, const T &t3) : CONT() //[t0]
369 { this->push_back(t1); this->push_back(t2); this->push_back(t3); }
370 items(const T &t1, const T &t2, const T &t3, const T &t4) : CONT() //[t0]
371 {
372 this->push_back(t1);
373 this->push_back(t2);
374 this->push_back(t3);
375 this->push_back(t4);
376 }
377 items(const T&t1,const T&t2,const T&t3,const T&t4,const T&t5):CONT() //[t0]
378 {
379 this->push_back(t1);
380 this->push_back(t2);
381 this->push_back(t3);
382 this->push_back(t4);
383 this->push_back(t5);
384 }
386 items(const CONT &c) : CONT(c) {} //[t0]
387
389 items &operator()(const T &t) //[t0]
390 {
391 this->push_back(t);
392 return *this;
393 }
394 };
395
396
397 namespace internal
398 {
399 // TODO: Does standard library provide a ready-made version of this?
401 template<typename ITER> struct dereference
402 {
403 typename ITER::value_type operator()(ITER i) const { return *i; }
404 };
405 template<typename T> struct deref_ptr { T operator()(T *i) const {return *i;} };
406 } // namespace internal
407
408
410
416 template<typename ITER, typename ACCESS> inline
417 PGSTD::string separated_list(const PGSTD::string &sep, //[t0]
418 ITER begin,
419 ITER end,
420 ACCESS access)
421 {
422 PGSTD::string result;
423 if (begin != end)
424 {
425 result = to_string(access(begin));
426 for (++begin; begin != end; ++begin)
427 {
428 result += sep;
429 result += to_string(access(begin));
430 }
431 }
432 return result;
433 }
434
439
441 template<typename ITER> inline PGSTD::string
442 separated_list(const PGSTD::string &sep, ITER begin, ITER end) //[t0]
443 { return separated_list(sep,begin,end,internal::dereference<ITER>()); }
444
445
447 template<typename OBJ> inline PGSTD::string
448 separated_list(const PGSTD::string &sep, OBJ *begin, OBJ *end) //[t0]
449 { return separated_list(sep,begin,end,internal::deref_ptr<OBJ>()); }
450
451
453 template<typename CONTAINER> inline PGSTD::string
454 separated_list(const PGSTD::string &sep, const CONTAINER &c) //[t10]
455 { return separated_list(sep, c.begin(), c.end()); }
457
459
468 namespace internal
469 {
470 typedef unsigned long result_size_type;
471 typedef long result_difference_type;
472 } // namespace internal
473
474
475 namespace internal
476 {
477 void PQXX_LIBEXPORT freepqmem(const void *) throw ();
478 template<typename P> inline void freepqmem_templated(P *p) throw ()
479 {
480 freepqmem(p);
481 }
482
483 void PQXX_LIBEXPORT freemallocmem(const void *) throw ();
484 template<typename P> inline void freemallocmem_templated(P *p) throw ()
485 {
486 freemallocmem(p);
487 }
488
489
490 #ifdef PQXX_HAVE_SHARED_PTR
491
493 template<typename T, void (*DELETER)(T *) = freepqmem_templated<T> >
494 class PQAlloc
495 {
496 public:
497 typedef T content_type;
498 PQAlloc() throw () : m_ptr() {}
499 PQAlloc(const PQAlloc &rhs) throw () : m_ptr(rhs.m_ptr) {}
500 explicit PQAlloc(T *t) : m_ptr(t, DELETER) {}
501
502 T *get() const throw () { return m_ptr.get(); }
503 PQAlloc &operator=(const PQAlloc &rhs) throw ()
504 {
505 m_ptr = rhs.m_ptr;
506 return *this;
507 }
508
509 T *operator->() const throw () { return m_ptr.get(); }
510 T &operator*() const throw () { return *m_ptr; }
511 void reset() throw () { m_ptr.reset(); }
512 void swap(PQAlloc &other) throw () { m_ptr.swap(other.m_ptr); }
513
514 private:
515 PQXXTR1::shared_ptr<T> m_ptr;
516 };
517
518 #else // !PQXX_HAVE_SHARED_PTR
519
522 class PQXX_LIBEXPORT refcount
523 {
524 refcount *volatile m_l, *volatile m_r;
525
526 public:
527 refcount();
528 ~refcount();
529
531 void makeref(refcount &) throw ();
532
534 bool loseref() throw ();
535
536 private:
538 refcount(const refcount &);
540 refcount &operator=(const refcount &);
541 };
542
543
545
558 template<typename T, void (*DELETER)(T *) = freepqmem_templated<T> >
559 class PQAlloc
560 {
561 T *m_Obj;
562 mutable refcount m_rc;
563 public:
564 typedef T content_type;
565
566 PQAlloc() throw () : m_Obj(0), m_rc() {}
567 PQAlloc(const PQAlloc &rhs) throw () : m_Obj(0), m_rc() { makeref(rhs); }
568 ~PQAlloc() throw () { loseref(); }
569
570 PQAlloc &operator=(const PQAlloc &rhs) throw () {redoref(rhs); return *this;}
571
573
575 explicit PQAlloc(T *obj) throw () : m_Obj(obj), m_rc() {}
576
577 void swap(PQAlloc &rhs) throw ()
578 {
579 PQAlloc tmp(*this);
580 *this = rhs;
581 rhs = tmp;
582 }
583
584 //PQAlloc &operator=(T *obj) throw () { redoref(obj); return *this; }
585
587 operator bool() const throw () { return m_Obj != 0; }
588
590 bool operator!() const throw () { return !m_Obj; }
591
593
595 T *operator->() const throw (PGSTD::logic_error)
596 {
597 if (!m_Obj) throw PGSTD::logic_error("Null pointer dereferenced");
598 return m_Obj;
599 }
600
602
604 T &operator*() const throw (PGSTD::logic_error) { return *operator->(); }
605
607
609 T *get() const throw () { return m_Obj; }
610
611 void reset() throw () { loseref(); }
612
613 private:
614 void makeref(T *p) throw () { m_Obj = p; }
615
616 void makeref(const PQAlloc &rhs) throw ()
617 {
618 m_Obj = rhs.m_Obj;
619 m_rc.makeref(rhs.m_rc);
620 }
621
623 void loseref() throw ()
624 {
625 if (m_rc.loseref() && m_Obj) DELETER(m_Obj);
626 m_Obj = 0;
627 }
628
629 void redoref(const PQAlloc &rhs) throw ()
630 { if (rhs.m_Obj != m_Obj) { loseref(); makeref(rhs); } }
631 void redoref(T *obj) throw ()
632 { if (obj != m_Obj) { loseref(); makeref(obj); } }
633 };
634
635 #endif // PQXX_HAVE_SHARED_PTR
636
637
638 template<typename T> class scoped_array
639 {
640 T *m_ptr;
641 public:
642 typedef size_t size_type;
643 typedef long difference_type;
644
645 scoped_array() : m_ptr(0) {}
646 explicit scoped_array(size_type n) : m_ptr(new T[n]) {}
647 explicit scoped_array(T *t) : m_ptr(t) {}
648 ~scoped_array() { delete [] m_ptr; }
649
650 T *get() const throw () { return m_ptr; }
651 T &operator*() const throw () { return *m_ptr; }
652 template<typename INDEX> T &operator[](INDEX i) const throw ()
653 { return m_ptr[i]; }
654
655 scoped_array &operator=(T *t) throw ()
656 {
657 if (t != m_ptr)
658 {
659 delete [] m_ptr;
660 m_ptr = t;
661 }
662 return *this;
663 }
664
665 private:
667 scoped_array(const scoped_array &);
668 scoped_array &operator=(const scoped_array &);
669 };
670
671
672 class PQXX_LIBEXPORT namedclass
673 {
674 public:
675 namedclass(const PGSTD::string &Classname, const PGSTD::string &Name="") :
676 m_Classname(Classname),
677 m_Name(Name)
678 {
679 }
680
681 const PGSTD::string &name() const throw () { return m_Name; } //[t1]
682 const PGSTD::string &classname() const throw () {return m_Classname;} //[t73]
683 PGSTD::string description() const;
684
685 private:
686 PGSTD::string m_Classname, m_Name;
687 };
688
689
690 void CheckUniqueRegistration(const namedclass *New, const namedclass *Old);
691 void CheckUniqueUnregistration(const namedclass *New, const namedclass *Old);
692
693
695
698 template<typename GUEST>
699 class unique
700 {
701 public:
702 unique() : m_Guest(0) {}
703
704 GUEST *get() const throw () { return m_Guest; }
705
706 void Register(GUEST *G)
707 {
708 CheckUniqueRegistration(G, m_Guest);
709 m_Guest = G;
710 }
711
712 void Unregister(GUEST *G)
713 {
714 CheckUniqueUnregistration(G, m_Guest);
715 m_Guest = 0;
716 }
717
718 private:
719 GUEST *m_Guest;
720
722 unique(const unique &);
724 unique &operator=(const unique &);
725 };
726
728
731 void PQXX_LIBEXPORT sleep_seconds(int);
732
734 typedef const char *cstring;
735
737
746 cstring PQXX_LIBEXPORT strerror_wrapper(int err, char buf[], PGSTD::size_t len)
747 throw ();
748
749
751 extern const char sql_begin_work[], sql_commit_work[], sql_rollback_work[];
752
753
755 template<typename T> inline PGSTD::ptrdiff_t distance(T first, T last)
756 {
757 #ifdef PQXX_HAVE_DISTANCE
758 return PGSTD::distance(first, last);
759 #else
760 // Naive implementation. All we really need for now.
761 PGSTD::ptrdiff_t d;
762 for (d=0; first != last; ++d) ++first;
763 return d;
764 #endif
765 }
766
767 } // namespace internal
768 } // namespace pqxx
769
770 #endif
771