# 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-2009, 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 <sstream>
    00026 #include <stdexcept>
    00027 #include <string>
    00028 #include <typeinfo>
    00029 #include <vector>
    00030
    00068
    00069 namespace pqxx {}
    00070
    00072
    00077 namespace PGSTD {}
    00078
    00079 #include <pqxx/libpq-forward.hxx>
    00080
    00081
    00082 namespace pqxx
    00083 {
    00085 const oid oid_none = 0;
    00086
    00098
    00100
    00103 template<typename T> struct string_traits;
    00104
    00105 namespace internal
    00106 {
    00108 void PQXX_LIBEXPORT throw_null_conversion(const PGSTD::string &type);
    00109 } // namespace pqxx::internal
    00110
    00111 #define PQXX_DECLARE_STRING_TRAITS_SPECIALIZATION(T)                    \
    00112 template<> struct PQXX_LIBEXPORT string_traits<T>                       \
    00113 {                                                                       \
    00114   typedef T subject_type;                                               \
    00115   static const char *name() { return #T; }                              \
    00116   static bool has_null() { return false; }                              \
    00117   static bool is_null(T) { return false; }                              \
    00118   static T null()                                                       \
    00119     { internal::throw_null_conversion(name()); return subject_type(); } \
    00120   static void from_string(const char Str[], T &Obj);                    \
    00121   static PGSTD::string to_string(T Obj);                                \
    00122 };
    00123
    00124 PQXX_DECLARE_STRING_TRAITS_SPECIALIZATION(bool)
    00125
    00126 PQXX_DECLARE_STRING_TRAITS_SPECIALIZATION(short)
    00127 PQXX_DECLARE_STRING_TRAITS_SPECIALIZATION(unsigned short)
    00128 PQXX_DECLARE_STRING_TRAITS_SPECIALIZATION(int)
    00129 PQXX_DECLARE_STRING_TRAITS_SPECIALIZATION(unsigned int)
    00130 PQXX_DECLARE_STRING_TRAITS_SPECIALIZATION(long)
    00131 PQXX_DECLARE_STRING_TRAITS_SPECIALIZATION(unsigned long)
    00132 #ifdef PQXX_HAVE_LONG_LONG
    00133 PQXX_DECLARE_STRING_TRAITS_SPECIALIZATION(long long)
    00134 PQXX_DECLARE_STRING_TRAITS_SPECIALIZATION(unsigned long long)
    00135 #endif
    00136
    00137 PQXX_DECLARE_STRING_TRAITS_SPECIALIZATION(float)
    00138 PQXX_DECLARE_STRING_TRAITS_SPECIALIZATION(double)
    00139 #ifdef PQXX_HAVE_LONG_DOUBLE
    00140 PQXX_DECLARE_STRING_TRAITS_SPECIALIZATION(long double)
    00141 #endif
    00142
    00143 #undef PQXX_DECLARE_STRING_TRAITS_SPECIALIZATION
    00144
    00146 template<> struct PQXX_LIBEXPORT string_traits<const char *>
    00147 {
    00148   static const char *name() { return "const char *"; }
    00149   static bool has_null() { return true; }
    00150   static bool is_null(const char *t) { return !t; }
    00151   static const char *null() { return NULL; }
    00152   static void from_string(const char Str[], const char *&Obj) { Obj = Str; }
    00153   static PGSTD::string to_string(const char *Obj) { return Obj; }
    00154 };
    00155
    00157 template<size_t N> struct PQXX_LIBEXPORT string_traits<char[N]>
    00158 {
    00159   static const char *name() { return "char[]"; }
    00160   static bool has_null() { return true; }
    00161   static bool is_null(const char t[]) { return !t; }
    00162   static const char *null() { return NULL; }
    00163   static void from_string(const char Str[], const char *&Obj) { Obj = Str; }
    00164   static PGSTD::string to_string(const char Obj[]) { return Obj; }
    00165 };
    00166
    00167 template<> struct PQXX_LIBEXPORT string_traits<PGSTD::string>
    00168 {
    00169   static const char *name() { return "string"; }
    00170   static bool has_null() { return false; }
    00171   static bool is_null(const PGSTD::string &) { return false; }
    00172   static PGSTD::string null()
    00173         { internal::throw_null_conversion(name()); return PGSTD::string(); }
    00174   static void from_string(const char Str[], PGSTD::string &Obj) { Obj=Str; }
    00175   static PGSTD::string to_string(const PGSTD::string &Obj) { return Obj; }
    00176 };
    00177
    00178 template<> struct PQXX_LIBEXPORT string_traits<PGSTD::stringstream>
    00179 {
    00180   static const char *name() { return "stringstream"; }
    00181   static bool has_null() { return false; }
    00182   static bool is_null(const PGSTD::stringstream &) { return false; }
    00183   static PGSTD::stringstream null()
    00184   {
    00185     internal::throw_null_conversion(name());
    00186     // No, dear compiler, we don't need a return here.
    00187     throw 0;
    00188   }
    00189   static void from_string(const char Str[], PGSTD::stringstream &Obj)
    00190                                                     { Obj.clear(); Obj << Str; }
    00191   static PGSTD::string to_string(const PGSTD::stringstream &Obj)
    00192                                                            { return Obj.str(); }
    00193 };
    00194
    00195
    00196 // TODO: Implement date conversions
    00197
    00199
    00211 template<typename T>
    00212   inline void from_string(const char Str[], T &Obj)
    00213 {
    00214   if (!Str)
    00215     throw PGSTD::runtime_error("Attempt to read NULL string");
    00216   string_traits<T>::from_string(Str, Obj);
    00217 }
    00218
    00219
    00221
    00227 template<typename T> void from_string(const char Str[], T &Obj, size_t)
    00228 {
    00229   return from_string(Str, Obj);
    00230 }
    00231
    00232 template<>
    00233   inline void from_string<PGSTD::string>(const char Str[],
    00234         PGSTD::string &Obj,
    00235         size_t len)                                                     //[t0]
    00236 {
    00237   if (!Str)
    00238     throw PGSTD::runtime_error("Attempt to read NULL string");
    00239   Obj.assign(Str, len);
    00240 }
    00241
    00242 template<typename T>
    00243   inline void from_string(const PGSTD::string &Str, T &Obj)             //[t45]
    00244         { from_string(Str.c_str(), Obj); }
    00245
    00246 template<typename T>
    00247   inline void from_string(const PGSTD::stringstream &Str, T &Obj)       //[t0]
    00248         { from_string(Str.str(), Obj); }
    00249
    00250 template<> inline void
    00251 from_string(const PGSTD::string &Str, PGSTD::string &Obj)               //[t46]
    00252         { Obj = Str; }
    00253
    00254
    00255 namespace internal
    00256 {
    00258 inline int digit_to_number(char c) throw () { return c-'0'; }
    00259 inline char number_to_digit(int i) throw () { return static_cast<char>(i+'0'); }
    00260 }
    00261
    00262
    00264
    00268 template<typename T> inline PGSTD::string to_string(const T &Obj)
    00269         { return string_traits<T>::to_string(Obj); }
    00270
    00271
    00272 inline PGSTD::string to_string(const char Obj[])                        //[t14]
    00273         { return Obj; }
    00274
    00275
    00277
    00279
    00301 template<typename T=PGSTD::string, typename CONT=PGSTD::vector<T> >
    00302 class items : public CONT
    00303 {
    00304 public:
    00306   items() : CONT() {}                                                   //[t80]
    00308   explicit items(const T &t) : CONT() { push_back(t); }                 //[t0]
    00309   items(const T &t1, const T &t2) : CONT()                              //[t80]
    00310         { push_back(t1); push_back(t2); }
    00311   items(const T &t1, const T &t2, const T &t3) : CONT()                 //[t0]
    00312         { push_back(t1); push_back(t2); push_back(t3); }
    00313   items(const T &t1, const T &t2, const T &t3, const T &t4) : CONT()    //[t0]
    00314         { push_back(t1); push_back(t2); push_back(t3); push_back(t4); }
    00315   items(const T&t1,const T&t2,const T&t3,const T&t4,const T&t5):CONT()  //[t0]
    00316         {push_back(t1);push_back(t2);push_back(t3);push_back(t4);push_back(t5);}
    00318   items(const CONT &c) : CONT(c) {}                                     //[t0]
    00319
    00321   items &operator()(const T &t)                                         //[t80]
    00322   {
    00323     push_back(t);
    00324     return *this;
    00325   }
    00326 };
    00327
    00328
    00329 namespace internal
    00330 {
    00331 // TODO: Does standard library provide a ready-made version of this?
    00333 template<typename ITER> struct dereference
    00334 {
    00335   typename ITER::value_type operator()(ITER i) const { return *i; }
    00336 };
    00337 template<typename T> struct deref_ptr { T operator()(T *i) const {return *i;} };
    00338 } // namespace internal
    00339
    00340
    00342
    00348 template<typename ITER, typename ACCESS> inline
    00349 PGSTD::string separated_list(const PGSTD::string &sep,                  //[t0]
    00350     ITER begin,
    00351     ITER end,
    00352     ACCESS access)
    00353 {
    00354   PGSTD::string result;
    00355   if (begin != end)
    00356   {
    00357     result = to_string(access(begin));
    00358     for (++begin; begin != end; ++begin)
    00359     {
    00360       result += sep;
    00361       result += to_string(access(begin));
    00362     }
    00363   }
    00364   return result;
    00365 }
    00366
    00371
    00373 template<typename ITER> inline PGSTD::string
    00374 separated_list(const PGSTD::string &sep, ITER begin, ITER end)          //[t8]
    00375         { return separated_list(sep,begin,end,internal::dereference<ITER>()); }
    00376
    00377
    00379 template<typename OBJ> inline PGSTD::string
    00380 separated_list(const PGSTD::string &sep, OBJ *begin, OBJ *end)          //[t9]
    00381         { return separated_list(sep,begin,end,internal::deref_ptr<OBJ>()); }
    00382
    00383
    00385 template<typename CONTAINER> inline PGSTD::string
    00386 separated_list(const PGSTD::string &sep, const CONTAINER &c)            //[t10]
    00387         { return separated_list(sep, c.begin(), c.end()); }
    00389
    00391
    00400 namespace internal
    00401 {
    00402 typedef unsigned long result_size_type;
    00403 typedef long result_difference_type;
    00404 } // namespace internal
    00405
    00406
    00407 namespace internal
    00408 {
    00409 void PQXX_LIBEXPORT freepqmem(void *);
    00410
    00411
    00413 class PQXX_LIBEXPORT refcount
    00414 {
    00415   refcount *volatile m_l, *volatile m_r;
    00416
    00417 public:
    00418   refcount();
    00419   ~refcount();
    00420
    00422   void makeref(refcount &) throw ();
    00423
    00425   bool loseref() throw ();
    00426
    00427 private:
    00429   refcount(const refcount &);
    00431   refcount &operator=(const refcount &);
    00432 };
    00433
    00434
    00436
    00450 template<typename T> class PQAlloc
    00451 {
    00452   T *m_Obj;
    00453   mutable refcount m_rc;
    00454 public:
    00455   typedef T content_type;
    00456
    00457   PQAlloc() throw () : m_Obj(0), m_rc() {}
    00458   PQAlloc(const PQAlloc &rhs) throw () : m_Obj(0), m_rc() { makeref(rhs); }
    00459   ~PQAlloc() throw () { loseref(); }
    00460
    00461   PQAlloc &operator=(const PQAlloc &rhs) throw () {redoref(rhs); return *this;}
    00462
    00464
    00466   explicit PQAlloc(T *obj) throw () : m_Obj(obj), m_rc() {}
    00467
    00468   void swap(PQAlloc &rhs) throw ()
    00469   {
    00470     PQAlloc tmp(*this);
    00471     *this = rhs;
    00472     rhs = tmp;
    00473   }
    00474
    00475   PQAlloc &operator=(T *obj) throw () { redoref(obj); return *this; }
    00476
    00478   operator bool() const throw () { return m_Obj != 0; }
    00479
    00481   bool operator!() const throw () { return !m_Obj; }
    00482
    00484
    00486   T *operator->() const throw (PGSTD::logic_error)
    00487   {
    00488     if (!m_Obj) throw PGSTD::logic_error("Null pointer dereferenced");
    00489     return m_Obj;
    00490   }
    00491
    00493
    00495   T &operator*() const throw (PGSTD::logic_error) { return *operator->(); }
    00496
    00498
    00500   T *c_ptr() const throw () { return m_Obj; }
    00501
    00502   void clear() throw () { loseref(); }
    00503
    00504 private:
    00505   void makeref(T *p) throw () { m_Obj = p; }
    00506
    00507   void makeref(const PQAlloc &rhs) throw ()
    00508   {
    00509     m_Obj = rhs.m_Obj;
    00510     m_rc.makeref(rhs.m_rc);
    00511   }
    00512
    00514   void loseref() throw ()
    00515   {
    00516     if (m_rc.loseref() && m_Obj) freemem();
    00517     m_Obj = 0;
    00518   }
    00519
    00520   void redoref(const PQAlloc &rhs) throw ()
    00521         { if (rhs.m_Obj != m_Obj) { loseref(); makeref(rhs); } }
    00522   void redoref(T *obj) throw ()
    00523         { if (obj != m_Obj) { loseref(); makeref(obj); } }
    00524
    00525   void freemem() throw () { freepqmem(m_Obj); }
    00526 };
    00527
    00528
    00529 void PQXX_LIBEXPORT freemem_notif(pq::PGnotify *) throw ();
    00530 template<> inline void PQAlloc<pq::PGnotify>::freemem() throw ()
    00531         { freemem_notif(m_Obj); }
    00532
    00533
    00534
    00535 template<typename T> class scoped_array
    00536 {
    00537   T *m_ptr;
    00538 public:
    00539   typedef size_t size_type;
    00540   typedef long difference_type;
    00541
    00542   scoped_array() : m_ptr(0) {}
    00543   explicit scoped_array(size_type n) : m_ptr(new T[n]) {}
    00544   explicit scoped_array(T *t) : m_ptr(t) {}
    00545   ~scoped_array() { delete [] m_ptr; }
    00546
    00547   T *c_ptr() const throw () { return m_ptr; }
    00548   T &operator*() const throw () { return *m_ptr; }
    00549   template<typename INDEX> T &operator[](INDEX i) const throw ()
    00550         { return m_ptr[i]; }
    00551
    00552   scoped_array &operator=(T *t) throw ()
    00553   {
    00554     if (t != m_ptr)
    00555     {
    00556       delete [] m_ptr;
    00557       m_ptr = t;
    00558     }
    00559     return *this;
    00560   }
    00561
    00562 private:
    00564   scoped_array(const scoped_array &);
    00565   scoped_array &operator=(const scoped_array &);
    00566 };
    00567
    00568
    00569 class PQXX_LIBEXPORT namedclass
    00570 {
    00571 public:
    00572   namedclass(const PGSTD::string &Classname, const PGSTD::string &Name="") :
    00573     m_Classname(Classname),
    00574     m_Name(Name)
    00575   {
    00576   }
    00577
    00578   const PGSTD::string &name() const throw () { return m_Name; }         //[t1]
    00579   const PGSTD::string &classname() const throw () {return m_Classname;} //[t73]
    00580   PGSTD::string description() const;
    00581
    00582 private:
    00583   PGSTD::string m_Classname, m_Name;
    00584 };
    00585
    00586
    00587 void CheckUniqueRegistration(const namedclass *New, const namedclass *Old);
    00588 void CheckUniqueUnregistration(const namedclass *New, const namedclass *Old);
    00589
    00590
    00592
    00595 template<typename GUEST>
    00596 class unique
    00597 {
    00598 public:
    00599   unique() : m_Guest(0) {}
    00600
    00601   GUEST *get() const throw () { return m_Guest; }
    00602
    00603   void Register(GUEST *G)
    00604   {
    00605     CheckUniqueRegistration(G, m_Guest);
    00606     m_Guest = G;
    00607   }
    00608
    00609   void Unregister(GUEST *G)
    00610   {
    00611     CheckUniqueUnregistration(G, m_Guest);
    00612     m_Guest = 0;
    00613   }
    00614
    00615 private:
    00616   GUEST *m_Guest;
    00617
    00619   unique(const unique &);
    00621   unique &operator=(const unique &);
    00622 };
    00623
    00625
    00628 void PQXX_LIBEXPORT sleep_seconds(int);
    00629
    00631 typedef const char *cstring;
    00632
    00634
    00643 cstring PQXX_LIBEXPORT strerror_wrapper(int err, char buf[], PGSTD::size_t len)
    00644   throw ();
    00645
    00646
    00648 extern const char sql_begin_work[], sql_commit_work[], sql_rollback_work[];
    00649
    00650 } // namespace internal
    00651 } // namespace pqxx
    00652
    00653 #endif
    00654