# 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-2006, 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 #include "pqxx/compiler-public.hxx"
    00019
    00020 #include <cstdio>
    00021 #include <cctype>
    00022 #include <sstream>
    00023 #include <stdexcept>
    00024 #include <string>
    00025 #include <typeinfo>
    00026 #include <vector>
    00027
    00065
    00066 namespace pqxx {}
    00067
    00069
    00074 namespace PGSTD {}
    00075
    00076 #include <pqxx/libpq-forward.hxx>
    00077
    00078
    00079 namespace pqxx
    00080 {
    00082 const oid oid_none = 0;
    00083
    00106
    00108
    00121 template<typename T> void error_unsupported_type_in_string_conversion(T);
    00122
    00123
    00125
    00131 template<typename T> PGSTD::string error_ambiguous_string_conversion(T);
    00132
    00133
    00134
    00135 // TODO: Implement date conversions
    00136
    00138
    00150 template<typename T> void from_string(const char Str[], T &Obj);
    00151
    00153
    00159 template<typename T> void from_string(const char Str[], T &Obj, size_t)
    00160 {
    00161   return from_string(Str, Obj);
    00162 }
    00163
    00164 template<> void PQXX_LIBEXPORT from_string(const char Str[],
    00165         PGSTD::string &,
    00166         size_t);                                                        //[t0]
    00167
    00168 template<> void PQXX_LIBEXPORT from_string(const char Str[], long &);   //[t45]
    00169 template<>
    00170   void PQXX_LIBEXPORT from_string(const char Str[], unsigned long &);   //[t45]
    00171 template<> void PQXX_LIBEXPORT from_string(const char Str[], int &);    //[t45]
    00172 template<>
    00173   void PQXX_LIBEXPORT from_string(const char Str[], unsigned int &);    //[t45]
    00174 template<> void PQXX_LIBEXPORT from_string(const char Str[], short &);  //[t45]
    00175 template<>
    00176   void PQXX_LIBEXPORT from_string(const char Str[], unsigned short &);  //[t45]
    00177 template<> void PQXX_LIBEXPORT from_string(const char Str[], float &);  //[t46]
    00178 template<> void PQXX_LIBEXPORT from_string(const char Str[], double &); //[t46]
    00179 template<> void PQXX_LIBEXPORT from_string(const char Str[], bool &);   //[t76]
    00180
    00181 #if defined(PQXX_HAVE_LONG_LONG) && defined(PQXX_ALLOW_LONG_LONG)
    00182 template<> void PQXX_LIBEXPORT
    00183   from_string(const char Str[], long long &);                           //[t0]
    00184 template<> void PQXX_LIBEXPORT
    00185   from_string(const char Str[], unsigned long long &);                  //[t0]
    00186 #endif
    00187
    00188 #if defined(PQXX_HAVE_LONG_DOUBLE)
    00189 template<>
    00190   void PQXX_LIBEXPORT from_string(const char Str[], long double &);     //[t46]
    00191 #endif
    00192
    00193
    00194 template<> inline void from_string(const char Str[],PGSTD::string &Obj) //[t46]
    00195         { Obj = Str; }
    00196
    00197 template<>
    00198   inline void from_string(const char Str[], PGSTD::stringstream &Obj)   //[t0]
    00199         { Obj.clear(); Obj << Str; }
    00200
    00201 template<typename T>
    00202   inline void from_string(const PGSTD::string &Str, T &Obj)             //[t45]
    00203         { from_string(Str.c_str(), Obj); }
    00204
    00205 template<typename T>
    00206   inline void from_string(const PGSTD::stringstream &Str, T &Obj)       //[t0]
    00207         { from_string(Str.str(), Obj); }
    00208
    00209 template<> inline void
    00210 from_string(const PGSTD::string &Str, PGSTD::string &Obj)               //[t46]
    00211         { Obj = Str; }
    00212
    00213 template<> inline void
    00214 from_string(const char [], char &Obj)
    00215         { error_ambiguous_string_conversion(Obj); }
    00216 template<> inline void
    00217 from_string(const char [], signed char &Obj)
    00218         { error_ambiguous_string_conversion(Obj); }
    00219 template<> inline void
    00220 from_string(const char [], unsigned char &Obj)
    00221         { error_ambiguous_string_conversion(Obj); }
    00222
    00223 template<> inline void
    00224 from_string(const PGSTD::string &, char &Obj)
    00225         { error_ambiguous_string_conversion(Obj); }
    00226 template<> inline void
    00227 from_string(const PGSTD::string &, signed char &Obj)
    00228         { error_ambiguous_string_conversion(Obj); }
    00229 template<> inline void
    00230 from_string(const PGSTD::string &, unsigned char &Obj)
    00231         { error_ambiguous_string_conversion(Obj); }
    00232
    00233
    00234 namespace internal
    00235 {
    00237 inline int digit_to_number(char c) throw () { return c-'0'; }
    00238 inline char number_to_digit(int i) throw () { return static_cast<char>(i)+'0'; }
    00239 }
    00240
    00241
    00243
    00247 template<typename T> PGSTD::string to_string(const T &);
    00248
    00249 template<> PGSTD::string PQXX_LIBEXPORT to_string(const short &);       //[t76]
    00250 template<>
    00251   PGSTD::string PQXX_LIBEXPORT to_string(const unsigned short &);       //[t76]
    00252 template<> PGSTD::string PQXX_LIBEXPORT to_string(const int &);         //[t10]
    00253 template<>
    00254   PGSTD::string PQXX_LIBEXPORT to_string(const unsigned int &);         //[t13]
    00255 template<> PGSTD::string PQXX_LIBEXPORT to_string(const long &);        //[t18]
    00256 template<>
    00257   PGSTD::string PQXX_LIBEXPORT to_string(const unsigned long &);        //[t20]
    00258 template<> PGSTD::string PQXX_LIBEXPORT to_string(const float &);       //[t74]
    00259 template<> PGSTD::string PQXX_LIBEXPORT to_string(const double &);      //[t74]
    00260 template<> PGSTD::string PQXX_LIBEXPORT to_string(const bool &);        //[t76]
    00261
    00262 /* Even if the compiler supports "long long" and friends, the user may not want
    00263  * them used because they may break compilation of client programs with
    00264  * different compiler options.
    00265  * When "long long" becomes a standard feature (both de jure and de facto),
    00266  * we'll make long long support the default and provide a different option to
    00267  * suppress these declarations.
    00268  */
    00269 #if defined(PQXX_HAVE_LONG_LONG) && defined(PQXX_ALLOW_LONG_LONG)
    00271 template<> PGSTD::string PQXX_LIBEXPORT
    00272   to_string(const long long &);                                         //[t0]
    00274 template<> PGSTD::string PQXX_LIBEXPORT
    00275   to_string(const unsigned long long &);                                //[t0]
    00276 #endif
    00277
    00278 #if defined(PQXX_HAVE_LONG_DOUBLE)
    00279 template<> PGSTD::string PQXX_LIBEXPORT to_string(const long double &); //[t74]
    00280 #endif
    00281
    00282 inline PGSTD::string to_string(const char Obj[])                        //[t14]
    00283         { return PGSTD::string(Obj); }
    00284
    00285 inline PGSTD::string to_string(const PGSTD::stringstream &Obj)          //[t0]
    00286         { return Obj.str(); }
    00287
    00288 inline PGSTD::string to_string(const PGSTD::string &Obj) {return Obj;}  //[t21]
    00289
    00290 template<> PGSTD::string PQXX_LIBEXPORT to_string(const char &);        //[t21]
    00291
    00292
    00293 template<> inline PGSTD::string to_string(const signed char &Obj)
    00294         { return error_ambiguous_string_conversion(Obj); }
    00295 template<> inline PGSTD::string to_string(const unsigned char &Obj)
    00296         { return error_ambiguous_string_conversion(Obj); }
    00298
    00300
    00322 template<typename T=PGSTD::string, typename CONT=PGSTD::vector<T> >
    00323 class items : public CONT
    00324 {
    00325 public:
    00327   items() : CONT() {}                                                   //[t80]
    00329   explicit items(const T &t) : CONT() { push_back(t); }                 //[t0]
    00330   items(const T &t1, const T &t2) : CONT()                              //[t80]
    00331         { push_back(t1); push_back(t2); }
    00332   items(const T &t1, const T &t2, const T &t3) : CONT()                 //[t0]
    00333         { push_back(t1); push_back(t2); push_back(t3); }
    00334   items(const T &t1, const T &t2, const T &t3, const T &t4) : CONT()    //[t0]
    00335         { push_back(t1); push_back(t2); push_back(t3); push_back(t4); }
    00336   items(const T&t1,const T&t2,const T&t3,const T&t4,const T&t5):CONT()  //[t0]
    00337         {push_back(t1);push_back(t2);push_back(t3);push_back(t4);push_back(t5);}
    00339   items(const CONT &c) : CONT(c) {}                                     //[t0]
    00340
    00342   items &operator()(const T &t)                                         //[t80]
    00343   {
    00344     push_back(t);
    00345     return *this;
    00346   }
    00347 };
    00348
    00349
    00350 namespace internal
    00351 {
    00352 // TODO: Does standard library provide a ready-made version of this?
    00354 template<typename ITER> struct dereference
    00355 {
    00356   typename ITER::value_type operator()(ITER i) const { return *i; }
    00357 };
    00358 template<typename T> struct deref_ptr { T operator()(T *i) const {return *i;} };
    00359 }
    00360
    00361
    00363
    00369 template<typename ITER, typename ACCESS> inline
    00370 PGSTD::string separated_list(const PGSTD::string &sep,                  //[t0]
    00371     ITER begin,
    00372     ITER end,
    00373     ACCESS access)
    00374 {
    00375   PGSTD::string result;
    00376   if (begin != end)
    00377   {
    00378     result = to_string(access(begin));
    00379     for (++begin; begin != end; ++begin)
    00380     {
    00381       result += sep;
    00382       result += to_string(access(begin));
    00383     }
    00384   }
    00385   return result;
    00386 }
    00387
    00392
    00394 template<typename ITER> inline PGSTD::string
    00395 separated_list(const PGSTD::string &sep, ITER begin, ITER end)          //[t8]
    00396         { return separated_list(sep,begin,end,internal::dereference<ITER>()); }
    00397
    00398
    00400 template<typename OBJ> inline PGSTD::string
    00401 separated_list(const PGSTD::string &sep, OBJ *begin, OBJ *end)          //[t9]
    00402         { return separated_list(sep,begin,end,internal::deref_ptr<OBJ>()); }
    00403
    00404
    00406 template<typename CONTAINER> inline PGSTD::string
    00407 separated_list(const PGSTD::string &sep, const CONTAINER &c)            //[t10]
    00408         { return separated_list(sep, c.begin(), c.end()); }
    00410
    00412
    00421 namespace internal
    00422 {
    00423 typedef unsigned long result_size_type;
    00424 typedef long result_difference_type;
    00425 } // namespace internal
    00426
    00427
    00428 namespace internal
    00429 {
    00431
    00433 PGSTD::string escape_string(const char str[], size_t maxlen) PQXX_DEPRECATED;
    00434 } // namespace internal
    00435
    00436
    00437
    00504
    00505
    00516 PGSTD::string PQXX_LIBEXPORT sqlesc(const char str[]) PQXX_DEPRECATED;
    00517
    00519
    00531 PGSTD::string PQXX_LIBEXPORT sqlesc(const char str[], size_t maxlen)
    00532         PQXX_DEPRECATED;
    00533
    00535
    00541 PGSTD::string PQXX_LIBEXPORT sqlesc(const PGSTD::string &) PQXX_DEPRECATED;
    00542
    00544
    00545
    00546 namespace internal
    00547 {
    00548 void PQXX_LIBEXPORT freepqmem(void *);
    00549
    00550
    00552 class PQXX_LIBEXPORT refcount
    00553 {
    00554   refcount *volatile m_l, *volatile m_r;
    00555
    00556 public:
    00557   refcount();
    00558   ~refcount();
    00559
    00561   void makeref(refcount &) throw ();
    00562
    00564   bool loseref() throw ();
    00565
    00566 private:
    00568   refcount(const refcount &);
    00570   refcount &operator=(const refcount &);
    00571 };
    00572
    00573
    00575
    00589 template<typename T> class PQAlloc
    00590 {
    00591   T *m_Obj;
    00592   mutable refcount m_rc;
    00593 public:
    00594   typedef T content_type;
    00595
    00596   PQAlloc() throw () : m_Obj(0), m_rc() {}
    00597   PQAlloc(const PQAlloc &rhs) throw () : m_Obj(0), m_rc() { makeref(rhs); }
    00598   ~PQAlloc() throw () { loseref(); }
    00599
    00600   PQAlloc &operator=(const PQAlloc &rhs) throw () {redoref(rhs); return *this;}
    00601
    00603
    00605   explicit PQAlloc(T *obj) throw () : m_Obj(obj), m_rc() {}
    00606
    00607   void swap(PQAlloc &rhs) throw ()
    00608   {
    00609     PQAlloc tmp(*this);
    00610     *this = rhs;
    00611     rhs = tmp;
    00612   }
    00613
    00614   PQAlloc &operator=(T *obj) throw () { redoref(obj); return *this; }
    00615
    00617   operator bool() const throw () { return m_Obj != 0; }
    00618
    00620   bool operator!() const throw () { return !m_Obj; }
    00621
    00623
    00625   T *operator->() const throw (PGSTD::logic_error)
    00626   {
    00627     if (!m_Obj) throw PGSTD::logic_error("Null pointer dereferenced");
    00628     return m_Obj;
    00629   }
    00630
    00632
    00634   T &operator*() const throw (PGSTD::logic_error) { return *operator->(); }
    00635
    00637
    00639   T *c_ptr() const throw () { return m_Obj; }
    00640
    00641   void clear() throw () { loseref(); }
    00642
    00643 private:
    00644   void makeref(T *p) throw () { m_Obj = p; }
    00645
    00646   void makeref(const PQAlloc &rhs) throw ()
    00647   {
    00648     m_Obj = rhs.m_Obj;
    00649     m_rc.makeref(rhs.m_rc);
    00650   }
    00651
    00653   void loseref() throw ()
    00654   {
    00655     if (m_rc.loseref() && m_Obj) freemem();
    00656     m_Obj = 0;
    00657   }
    00658
    00659   void redoref(const PQAlloc &rhs) throw ()
    00660         { if (rhs.m_Obj != m_Obj) { loseref(); makeref(rhs); } }
    00661   void redoref(T *obj) throw ()
    00662         { if (obj != m_Obj) { loseref(); makeref(obj); } }
    00663
    00664   void freemem() throw () { freepqmem(m_Obj); }
    00665 };
    00666
    00667
    00668 void PQXX_LIBEXPORT freemem_notif(pq::PGnotify *) throw ();
    00669 template<> inline void PQAlloc<pq::PGnotify>::freemem() throw ()
    00670         { freemem_notif(m_Obj); }
    00671
    00672
    00673
    00674 template<typename T> class scoped_array
    00675 {
    00676   T *m_ptr;
    00677 public:
    00678   typedef size_t size_type;
    00679   typedef long difference_type;
    00680
    00681   scoped_array() : m_ptr(0) {}
    00682   explicit scoped_array(size_type n) : m_ptr(new T[n]) {}
    00683   explicit scoped_array(T *t) : m_ptr(t) {}
    00684   ~scoped_array() { delete [] m_ptr; }
    00685
    00686   T *c_ptr() const throw () { return m_ptr; }
    00687   T &operator*() const throw () { return *m_ptr; }
    00688   T &operator[](difference_type i) const throw () { return m_ptr[i]; }
    00689
    00690   scoped_array &operator=(T *t) throw ()
    00691   {
    00692     if (t != m_ptr)
    00693     {
    00694       delete [] m_ptr;
    00695       m_ptr = t;
    00696     }
    00697     return *this;
    00698   }
    00699
    00700 private:
    00702   scoped_array(const scoped_array &);
    00703   scoped_array &operator=(const scoped_array &);
    00704 };
    00705
    00706
    00707 class PQXX_LIBEXPORT namedclass
    00708 {
    00709 public:
    00710   namedclass(const PGSTD::string &Classname, const PGSTD::string &Name="") :
    00711     m_Classname(Classname),
    00712     m_Name(Name)
    00713   {
    00714   }
    00715
    00716   const PGSTD::string &name() const throw () { return m_Name; }         //[t1]
    00717   const PGSTD::string &classname() const throw () {return m_Classname;} //[t73]
    00718   PGSTD::string description() const;
    00719
    00720 private:
    00721   PGSTD::string m_Classname, m_Name;
    00722 };
    00723
    00724
    00725 void CheckUniqueRegistration(const namedclass *New, const namedclass *Old);
    00726 void CheckUniqueUnregistration(const namedclass *New, const namedclass *Old);
    00727
    00728
    00730
    00733 template<typename GUEST>
    00734 class unique
    00735 {
    00736 public:
    00737   unique() : m_Guest(0) {}
    00738
    00739   GUEST *get() const throw () { return m_Guest; }
    00740
    00741   void Register(GUEST *G)
    00742   {
    00743     CheckUniqueRegistration(G, m_Guest);
    00744     m_Guest = G;
    00745   }
    00746
    00747   void Unregister(GUEST *G)
    00748   {
    00749     CheckUniqueUnregistration(G, m_Guest);
    00750     m_Guest = 0;
    00751   }
    00752
    00753 private:
    00754   GUEST *m_Guest;
    00755
    00757   unique(const unique &);
    00759   unique &operator=(const unique &);
    00760 };
    00761
    00763
    00766 void PQXX_LIBEXPORT sleep_seconds(int);
    00767
    00769 typedef const char *cstring;
    00770
    00772
    00781 cstring PQXX_LIBEXPORT strerror_wrapper(int err, char buf[], PGSTD::size_t len)
    00782   throw ();
    00783
    00784
    00786 extern const char sql_begin_work[], sql_commit_work[], sql_rollback_work[];
    00787
    00788 } // namespace internal
    00789 } // namespace pqxx
    00790