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 <memory>
00026 #include <stdexcept>
00027 #include <string>
00028 #include <typeinfo>
00029 #include <vector>
00030
00031 #include "pqxx/strconv"
00032
00033
00256
00257 namespace pqxx {}
00258
00259 #include <pqxx/internal/libpq-forward.hxx>
00260
00261
00262 namespace pqxx
00263 {
00265
00267 struct PQXX_LIBEXPORT thread_safety_model
00268 {
00270
00277 bool have_safe_strerror;
00278
00280
00287 bool safe_libpq;
00288
00290
00293 bool safe_query_cancel;
00294
00296
00301 bool safe_result_copy;
00302
00304
00310 bool safe_kerberos;
00311
00313 std::string description;
00314 };
00315
00317 PQXX_LIBEXPORT thread_safety_model describe_thread_safety() PQXX_NOEXCEPT;
00318
00320 const oid oid_none = 0;
00321
00323
00345 template<typename T=std::string, typename CONT=std::vector<T> >
00346 class items : public CONT
00347 {
00348 public:
00350 items() : CONT() {}
00352 explicit items(const T &t) : CONT() { this->push_back(t); }
00353 items(const T &t1, const T &t2) : CONT()
00354 { this->push_back(t1); this->push_back(t2); }
00355 items(const T &t1, const T &t2, const T &t3) : CONT()
00356 { this->push_back(t1); this->push_back(t2); this->push_back(t3); }
00357 items(const T &t1, const T &t2, const T &t3, const T &t4) : CONT()
00358 {
00359 this->push_back(t1);
00360 this->push_back(t2);
00361 this->push_back(t3);
00362 this->push_back(t4);
00363 }
00364 items(const T&t1,const T&t2,const T&t3,const T&t4,const T&t5):CONT()
00365 {
00366 this->push_back(t1);
00367 this->push_back(t2);
00368 this->push_back(t3);
00369 this->push_back(t4);
00370 this->push_back(t5);
00371 }
00373 items(const CONT &c) : CONT(c) {}
00374
00376 items &operator()(const T &t)
00377 {
00378 this->push_back(t);
00379 return *this;
00380 }
00381 };
00382
00383
00384 namespace internal
00385 {
00386
00388 template<typename ITER> struct dereference
00389 {
00390 typename ITER::value_type operator()(ITER i) const { return *i; }
00391 };
00392 template<typename T> struct deref_ptr { T operator()(T *i) const {return *i;} };
00393 }
00394
00395
00397
00403 template<typename ITER, typename ACCESS> inline
00404 std::string separated_list(const std::string &sep,
00405 ITER begin,
00406 ITER end,
00407 ACCESS access)
00408 {
00409 std::string result;
00410 if (begin != end)
00411 {
00412 result = to_string(access(begin));
00413 for (++begin; begin != end; ++begin)
00414 {
00415 result += sep;
00416 result += to_string(access(begin));
00417 }
00418 }
00419 return result;
00420 }
00421
00426
00428 template<typename ITER> inline std::string
00429 separated_list(const std::string &sep, ITER begin, ITER end)
00430 { return separated_list(sep,begin,end,internal::dereference<ITER>()); }
00431
00432
00434 template<typename OBJ> inline std::string
00435 separated_list(const std::string &sep, OBJ *begin, OBJ *end)
00436 { return separated_list(sep,begin,end,internal::deref_ptr<OBJ>()); }
00437
00438
00440 template<typename CONTAINER> inline std::string
00441 separated_list(const std::string &sep, const CONTAINER &c)
00442 { return separated_list(sep, c.begin(), c.end()); }
00444
00446
00455 namespace internal
00456 {
00457 typedef unsigned long result_size_type;
00458 typedef long result_difference_type;
00459 }
00460
00461
00462 namespace internal
00463 {
00464 PQXX_LIBEXPORT void freepqmem(const void *) PQXX_NOEXCEPT;
00465 template<typename P> inline void freepqmem_templated(P *p) PQXX_NOEXCEPT
00466 {
00467 freepqmem(p);
00468 }
00469
00470 PQXX_LIBEXPORT void freemallocmem(const void *) PQXX_NOEXCEPT;
00471 template<typename P> inline void freemallocmem_templated(P *p) PQXX_NOEXCEPT
00472 {
00473 freemallocmem(p);
00474 }
00475
00476
00477 #ifdef PQXX_HAVE_SHARED_PTR
00478
00480 template<typename T, void (*DELETER)(T *) = freepqmem_templated<T> >
00481 class PQAlloc
00482 {
00483 public:
00484 typedef T content_type;
00485 PQAlloc() PQXX_NOEXCEPT : m_ptr() {}
00486 PQAlloc(const PQAlloc &rhs) PQXX_NOEXCEPT : m_ptr(rhs.m_ptr) {}
00487 explicit PQAlloc(T *t) : m_ptr(t, DELETER) {}
00488
00489 T *get() const PQXX_NOEXCEPT { return m_ptr.get(); }
00490 PQAlloc &operator=(const PQAlloc &rhs) PQXX_NOEXCEPT
00491 {
00492 m_ptr = rhs.m_ptr;
00493 return *this;
00494 }
00495
00496 #if __cplusplus >= 201103L
00497 PQAlloc(PQAlloc &&) =default;
00498 PQAlloc &operator=(PQAlloc &&) =default;
00499 #endif
00500
00501 T *operator->() const PQXX_NOEXCEPT { return m_ptr.get(); }
00502 T &operator*() const PQXX_NOEXCEPT { return *m_ptr; }
00503 void reset() PQXX_NOEXCEPT { m_ptr.reset(); }
00504 void swap(PQAlloc &other) PQXX_NOEXCEPT { m_ptr.swap(other.m_ptr); }
00505
00506 private:
00507 std::shared_ptr<T> m_ptr;
00508 };
00509
00510 #else // !PQXX_HAVE_SHARED_PTR
00511
00514 class PQXX_LIBEXPORT refcount
00515 {
00516 refcount *volatile m_l, *volatile m_r;
00517
00518 public:
00519 refcount();
00520 ~refcount();
00521
00523 void makeref(refcount &) PQXX_NOEXCEPT;
00524
00526 bool loseref() PQXX_NOEXCEPT;
00527
00528 private:
00530 refcount(const refcount &);
00532 refcount &operator=(const refcount &);
00533 };
00534
00535
00537
00550 template<typename T, void (*DELETER)(T *) = freepqmem_templated<T> >
00551 class PQAlloc
00552 {
00553 T *m_Obj;
00554 mutable refcount m_rc;
00555 public:
00556 typedef T content_type;
00557
00558 PQAlloc() PQXX_NOEXCEPT : m_Obj(0), m_rc() {}
00559 PQAlloc(const PQAlloc &rhs) PQXX_NOEXCEPT : m_Obj(0), m_rc() { makeref(rhs); }
00560 ~PQAlloc() PQXX_NOEXCEPT { loseref(); }
00561
00562 PQAlloc &operator=(const PQAlloc &rhs) PQXX_NOEXCEPT
00563 {redoref(rhs); return *this;}
00564
00566
00568 explicit PQAlloc(T *obj) PQXX_NOEXCEPT : m_Obj(obj), m_rc() {}
00569
00570 void swap(PQAlloc &rhs) PQXX_NOEXCEPT
00571 {
00572 PQAlloc tmp(*this);
00573 *this = rhs;
00574 rhs = tmp;
00575 }
00576
00578 operator bool() const PQXX_NOEXCEPT { return m_Obj != 0; }
00579
00581 bool operator!() const PQXX_NOEXCEPT { return !m_Obj; }
00582
00584
00586 T *operator->() const
00587 {
00588 if (!m_Obj) throw std::logic_error("Null pointer dereferenced");
00589 return m_Obj;
00590 }
00591
00593
00595 T &operator*() const { return *operator->(); }
00596
00598
00600 T *get() const PQXX_NOEXCEPT { return m_Obj; }
00601
00602 void reset() PQXX_NOEXCEPT { loseref(); }
00603
00604 private:
00605 void makeref(T *p) PQXX_NOEXCEPT { m_Obj = p; }
00606
00607 void makeref(const PQAlloc &rhs) PQXX_NOEXCEPT
00608 {
00609 m_Obj = rhs.m_Obj;
00610 m_rc.makeref(rhs.m_rc);
00611 }
00612
00614 void loseref() PQXX_NOEXCEPT
00615 {
00616 if (m_rc.loseref() && m_Obj) DELETER(m_Obj);
00617 m_Obj = 0;
00618 }
00619
00620 void redoref(const PQAlloc &rhs) PQXX_NOEXCEPT
00621 { if (rhs.m_Obj != m_Obj) { loseref(); makeref(rhs); } }
00622 void redoref(T *obj) PQXX_NOEXCEPT
00623 { if (obj != m_Obj) { loseref(); makeref(obj); } }
00624 };
00625
00626 #endif // PQXX_HAVE_SHARED_PTR
00627
00628
00629 class PQXX_LIBEXPORT namedclass
00630 {
00631 public:
00632 namedclass(const std::string &Classname, const std::string &Name="") :
00633 m_Classname(Classname),
00634 m_Name(Name)
00635 {
00636 }
00637
00638 const std::string &name() const PQXX_NOEXCEPT { return m_Name; }
00639 const std::string &classname() const PQXX_NOEXCEPT
00640 {return m_Classname;}
00641 std::string description() const;
00642
00643 private:
00644 std::string m_Classname, m_Name;
00645 };
00646
00647
00648 void CheckUniqueRegistration(const namedclass *New, const namedclass *Old);
00649 void CheckUniqueUnregistration(const namedclass *New, const namedclass *Old);
00650
00651
00653
00656 template<typename GUEST>
00657 class unique
00658 {
00659 public:
00660 unique() : m_Guest(0) {}
00661
00662 GUEST *get() const PQXX_NOEXCEPT { return m_Guest; }
00663
00664 void Register(GUEST *G)
00665 {
00666 CheckUniqueRegistration(G, m_Guest);
00667 m_Guest = G;
00668 }
00669
00670 void Unregister(GUEST *G)
00671 {
00672 CheckUniqueUnregistration(G, m_Guest);
00673 m_Guest = 0;
00674 }
00675
00676 private:
00677 GUEST *m_Guest;
00678
00680 unique(const unique &);
00682 unique &operator=(const unique &);
00683 };
00684
00686
00689 PQXX_LIBEXPORT void sleep_seconds(int);
00690
00692 typedef const char *cstring;
00693
00695
00704 PQXX_LIBEXPORT cstring strerror_wrapper(int err, char buf[], std::size_t len)
00705 PQXX_NOEXCEPT;
00706
00707
00709 extern const char sql_begin_work[], sql_commit_work[], sql_rollback_work[];
00710
00711
00713 template<typename T> inline std::ptrdiff_t distance(T first, T last)
00714 {
00715 #ifdef PQXX_HAVE_DISTANCE
00716 return std::distance(first, last);
00717 #else
00718
00719 std::ptrdiff_t d;
00720 for (d=0; first != last; ++d) ++first;
00721 return d;
00722 #endif
00723 }
00724
00725 }
00726 }
00727
00728 #endif
00729