libpqxx 4.0
util.hxx
00001 /*-------------------------------------------------------------------------
00002  *
00003  *   FILE
00004  *      pqxx/util.hxx
00005  *
00006  *   DESCRIPTION
00007  *      Various utility definitions for libpqxx
00008  *      DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/util instead.
00009  *
00010  * Copyright (c) 2001-2011, Jeroen T. Vermeulen <jtv@xs4all.nl>
00011  *
00012  * See COPYING for copyright license.  If you did not receive a file called
00013  * COPYING with this source code, please notify the distributor of this mistake,
00014  * or contact the author.
00015  *
00016  *-------------------------------------------------------------------------
00017  */
00018 #ifndef PQXX_H_UTIL
00019 #define PQXX_H_UTIL
00020 
00021 #include "pqxx/compiler-public.hxx"
00022 
00023 #include <cstdio>
00024 #include <cctype>
00025 #include <stdexcept>
00026 #include <string>
00027 #include <typeinfo>
00028 #include <vector>
00029 
00030 #ifdef PQXX_TR1_HEADERS
00031 #include <tr1/memory>
00032 #else
00033 #include <memory>
00034 #endif
00035 
00036 #include "pqxx/strconv"
00037 
00038 
00261 
00262 namespace pqxx {}
00263 
00265 
00270 namespace PGSTD {}
00271 
00272 #include <pqxx/internal/libpq-forward.hxx>
00273 
00274 
00275 namespace pqxx
00276 {
00278 
00280 struct PQXX_LIBEXPORT thread_safety_model
00281 {
00283 
00290   bool have_safe_strerror;
00291 
00293 
00300   bool safe_libpq;
00301 
00303 
00306   bool safe_query_cancel;
00307 
00309 
00314   bool safe_result_copy;
00315 
00317 
00323   bool safe_kerberos;
00324 
00326   PGSTD::string description;
00327 };
00328 
00330 thread_safety_model PQXX_LIBEXPORT describe_thread_safety() throw ();
00331 
00333 const oid oid_none = 0;
00334 
00336 
00358 template<typename T=PGSTD::string, typename CONT=PGSTD::vector<T> >
00359 class items : public CONT
00360 {
00361 public:
00363   items() : CONT() {}                                                   //[t0]
00365   explicit items(const T &t) : CONT() { this->push_back(t); }           //[t0]
00366   items(const T &t1, const T &t2) : CONT()                              //[t0]
00367         { this->push_back(t1); this->push_back(t2); }
00368   items(const T &t1, const T &t2, const T &t3) : CONT()                 //[t0]
00369         { this->push_back(t1); this->push_back(t2); this->push_back(t3); }
00370   items(const T &t1, const T &t2, const T &t3, const T &t4) : CONT()    //[t0]
00371   {
00372     this->push_back(t1);
00373     this->push_back(t2);
00374     this->push_back(t3);
00375     this->push_back(t4);
00376   }
00377   items(const T&t1,const T&t2,const T&t3,const T&t4,const T&t5):CONT()  //[t0]
00378   {
00379     this->push_back(t1);
00380     this->push_back(t2);
00381     this->push_back(t3);
00382     this->push_back(t4);
00383     this->push_back(t5);
00384   }
00386   items(const CONT &c) : CONT(c) {}                                     //[t0]
00387 
00389   items &operator()(const T &t)                                         //[t0]
00390   {
00391     this->push_back(t);
00392     return *this;
00393   }
00394 };
00395 
00396 
00397 namespace internal
00398 {
00399 // TODO: Does standard library provide a ready-made version of this?
00401 template<typename ITER> struct dereference
00402 {
00403   typename ITER::value_type operator()(ITER i) const { return *i; }
00404 };
00405 template<typename T> struct deref_ptr { T operator()(T *i) const {return *i;} };
00406 } // namespace internal
00407 
00408 
00410 
00416 template<typename ITER, typename ACCESS> inline
00417 PGSTD::string separated_list(const PGSTD::string &sep,                  //[t0]
00418     ITER begin,
00419     ITER end,
00420     ACCESS access)
00421 {
00422   PGSTD::string result;
00423   if (begin != end)
00424   {
00425     result = to_string(access(begin));
00426     for (++begin; begin != end; ++begin)
00427     {
00428       result += sep;
00429       result += to_string(access(begin));
00430     }
00431   }
00432   return result;
00433 }
00434 
00439 
00441 template<typename ITER> inline PGSTD::string
00442 separated_list(const PGSTD::string &sep, ITER begin, ITER end)          //[t0]
00443         { return separated_list(sep,begin,end,internal::dereference<ITER>()); }
00444 
00445 
00447 template<typename OBJ> inline PGSTD::string
00448 separated_list(const PGSTD::string &sep, OBJ *begin, OBJ *end)          //[t0]
00449         { return separated_list(sep,begin,end,internal::deref_ptr<OBJ>()); }
00450 
00451 
00453 template<typename CONTAINER> inline PGSTD::string
00454 separated_list(const PGSTD::string &sep, const CONTAINER &c)            //[t10]
00455         { return separated_list(sep, c.begin(), c.end()); }
00457 
00459 
00468 namespace internal
00469 {
00470 typedef unsigned long result_size_type;
00471 typedef long result_difference_type;
00472 } // namespace internal
00473 
00474 
00475 namespace internal
00476 {
00477 void PQXX_LIBEXPORT freepqmem(const void *) throw ();
00478 template<typename P> inline void freepqmem_templated(P *p) throw ()
00479 {
00480   freepqmem(p);
00481 }
00482 
00483 void PQXX_LIBEXPORT freemallocmem(const void *) throw ();
00484 template<typename P> inline void freemallocmem_templated(P *p) throw ()
00485 {
00486   freemallocmem(p);
00487 }
00488 
00489 
00490 #ifdef PQXX_HAVE_SHARED_PTR
00491 
00493 template<typename T, void (*DELETER)(T *) = freepqmem_templated<T> >
00494   class PQAlloc
00495 {
00496 public:
00497   typedef T content_type;
00498   PQAlloc() throw () : m_ptr() {}
00499   PQAlloc(const PQAlloc &rhs) throw () : m_ptr(rhs.m_ptr) {}
00500   explicit PQAlloc(T *t) : m_ptr(t, DELETER) {}
00501 
00502   T *get() const throw () { return m_ptr.get(); }
00503   PQAlloc &operator=(const PQAlloc &rhs) throw ()
00504   {
00505     m_ptr = rhs.m_ptr;
00506     return *this;
00507   }
00508 
00509   T *operator->() const throw () { return m_ptr.get(); }
00510   T &operator*() const throw () { return *m_ptr; }
00511   void reset() throw () { m_ptr.reset(); }
00512   void swap(PQAlloc &other) throw () { m_ptr.swap(other.m_ptr); }
00513 
00514 private:
00515   PQXXTR1::shared_ptr<T> m_ptr;
00516 };
00517 
00518 #else // !PQXX_HAVE_SHARED_PTR
00519 
00522 class PQXX_LIBEXPORT refcount
00523 {
00524   refcount *volatile m_l, *volatile m_r;
00525 
00526 public:
00527   refcount();
00528   ~refcount();
00529 
00531   void makeref(refcount &) throw ();
00532 
00534   bool loseref() throw ();
00535 
00536 private:
00538   refcount(const refcount &);
00540   refcount &operator=(const refcount &);
00541 };
00542 
00543 
00545 
00558 template<typename T, void (*DELETER)(T *) = freepqmem_templated<T> >
00559 class PQAlloc
00560 {
00561   T *m_Obj;
00562   mutable refcount m_rc;
00563 public:
00564   typedef T content_type;
00565 
00566   PQAlloc() throw () : m_Obj(0), m_rc() {}
00567   PQAlloc(const PQAlloc &rhs) throw () : m_Obj(0), m_rc() { makeref(rhs); }
00568   ~PQAlloc() throw () { loseref(); }
00569 
00570   PQAlloc &operator=(const PQAlloc &rhs) throw () {redoref(rhs); return *this;}
00571 
00573 
00575   explicit PQAlloc(T *obj) throw () : m_Obj(obj), m_rc() {}
00576 
00577   void swap(PQAlloc &rhs) throw ()
00578   {
00579     PQAlloc tmp(*this);
00580     *this = rhs;
00581     rhs = tmp;
00582   }
00583 
00584   //PQAlloc &operator=(T *obj) throw () { redoref(obj); return *this; }
00585 
00587   operator bool() const throw () { return m_Obj != 0; }
00588 
00590   bool operator!() const throw () { return !m_Obj; }
00591 
00593 
00595   T *operator->() const throw (PGSTD::logic_error)
00596   {
00597     if (!m_Obj) throw PGSTD::logic_error("Null pointer dereferenced");
00598     return m_Obj;
00599   }
00600 
00602 
00604   T &operator*() const throw (PGSTD::logic_error) { return *operator->(); }
00605 
00607 
00609   T *get() const throw () { return m_Obj; }
00610 
00611   void reset() throw () { loseref(); }
00612 
00613 private:
00614   void makeref(T *p) throw () { m_Obj = p; }
00615 
00616   void makeref(const PQAlloc &rhs) throw ()
00617   {
00618     m_Obj = rhs.m_Obj;
00619     m_rc.makeref(rhs.m_rc);
00620   }
00621 
00623   void loseref() throw ()
00624   {
00625     if (m_rc.loseref() && m_Obj) DELETER(m_Obj);
00626     m_Obj = 0;
00627   }
00628 
00629   void redoref(const PQAlloc &rhs) throw ()
00630         { if (rhs.m_Obj != m_Obj) { loseref(); makeref(rhs); } }
00631   void redoref(T *obj) throw ()
00632         { if (obj != m_Obj) { loseref(); makeref(obj); } }
00633 };
00634 
00635 #endif // PQXX_HAVE_SHARED_PTR
00636 
00637 
00638 template<typename T> class scoped_array
00639 {
00640   T *m_ptr;
00641 public:
00642   typedef size_t size_type;
00643   typedef long difference_type;
00644 
00645   scoped_array() : m_ptr(0) {}
00646   explicit scoped_array(size_type n) : m_ptr(new T[n]) {}
00647   explicit scoped_array(T *t) : m_ptr(t) {}
00648   ~scoped_array() { delete [] m_ptr; }
00649 
00650   T *get() const throw () { return m_ptr; }
00651   T &operator*() const throw () { return *m_ptr; }
00652   template<typename INDEX> T &operator[](INDEX i) const throw ()
00653         { return m_ptr[i]; }
00654 
00655   scoped_array &operator=(T *t) throw ()
00656   {
00657     if (t != m_ptr)
00658     {
00659       delete [] m_ptr;
00660       m_ptr = t;
00661     }
00662     return *this;
00663   }
00664 
00665 private:
00667   scoped_array(const scoped_array &);
00668   scoped_array &operator=(const scoped_array &);
00669 };
00670 
00671 
00672 class PQXX_LIBEXPORT namedclass
00673 {
00674 public:
00675   namedclass(const PGSTD::string &Classname, const PGSTD::string &Name="") :
00676     m_Classname(Classname),
00677     m_Name(Name)
00678   {
00679   }
00680 
00681   const PGSTD::string &name() const throw () { return m_Name; }         //[t1]
00682   const PGSTD::string &classname() const throw () {return m_Classname;} //[t73]
00683   PGSTD::string description() const;
00684 
00685 private:
00686   PGSTD::string m_Classname, m_Name;
00687 };
00688 
00689 
00690 void CheckUniqueRegistration(const namedclass *New, const namedclass *Old);
00691 void CheckUniqueUnregistration(const namedclass *New, const namedclass *Old);
00692 
00693 
00695 
00698 template<typename GUEST>
00699 class unique
00700 {
00701 public:
00702   unique() : m_Guest(0) {}
00703 
00704   GUEST *get() const throw () { return m_Guest; }
00705 
00706   void Register(GUEST *G)
00707   {
00708     CheckUniqueRegistration(G, m_Guest);
00709     m_Guest = G;
00710   }
00711 
00712   void Unregister(GUEST *G)
00713   {
00714     CheckUniqueUnregistration(G, m_Guest);
00715     m_Guest = 0;
00716   }
00717 
00718 private:
00719   GUEST *m_Guest;
00720 
00722   unique(const unique &);
00724   unique &operator=(const unique &);
00725 };
00726 
00728 
00731 void PQXX_LIBEXPORT sleep_seconds(int);
00732 
00734 typedef const char *cstring;
00735 
00737 
00746 cstring PQXX_LIBEXPORT strerror_wrapper(int err, char buf[], PGSTD::size_t len)
00747   throw ();
00748 
00749 
00751 extern const char sql_begin_work[], sql_commit_work[], sql_rollback_work[];
00752 
00753 
00755 template<typename T> inline PGSTD::ptrdiff_t distance(T first, T last)
00756 {
00757 #ifdef PQXX_HAVE_DISTANCE
00758   return PGSTD::distance(first, last);
00759 #else
00760   // Naive implementation.  All we really need for now.
00761   PGSTD::ptrdiff_t d;
00762   for (d=0; first != last; ++d) ++first;
00763   return d;
00764 #endif
00765 }
00766 
00767 } // namespace internal
00768 } // namespace pqxx
00769 
00770 #endif
00771