libpqxx  4.0.1
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 
291 
293 
301 
303 
307 
309 
315 
317 
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;
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 &);
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