00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
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 }
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
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
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)
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)
00244 { from_string(Str.c_str(), Obj); }
00245
00246 template<typename T>
00247 inline void from_string(const PGSTD::stringstream &Str, T &Obj)
00248 { from_string(Str.str(), Obj); }
00249
00250 template<> inline void
00251 from_string(const PGSTD::string &Str, PGSTD::string &Obj)
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[])
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() {}
00308 explicit items(const T &t) : CONT() { push_back(t); }
00309 items(const T &t1, const T &t2) : CONT()
00310 { push_back(t1); push_back(t2); }
00311 items(const T &t1, const T &t2, const T &t3) : CONT()
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()
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()
00316 {push_back(t1);push_back(t2);push_back(t3);push_back(t4);push_back(t5);}
00318 items(const CONT &c) : CONT(c) {}
00319
00321 items &operator()(const T &t)
00322 {
00323 push_back(t);
00324 return *this;
00325 }
00326 };
00327
00328
00329 namespace internal
00330 {
00331
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 }
00339
00340
00342
00348 template<typename ITER, typename ACCESS> inline
00349 PGSTD::string separated_list(const PGSTD::string &sep,
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)
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)
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)
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 }
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; }
00579 const PGSTD::string &classname() const throw () {return m_Classname;}
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 }
00651 }
00652
00653 #endif
00654