util.hxx

Go to the documentation of this file.
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-2008, 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 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 

Generated on Sun Nov 2 08:25:40 2008 for libpqxx by  doxygen 1.5.5