libpqxx 4.0
|
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-2011, 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 <stdexcept> 00026 #include <string> 00027 #include <typeinfo> 00028 #include <vector> 00029 00030 #ifdef PQXX_TR1_HEADERS 00031 #include <tr1/memory> 00032 #else 00033 #include <memory> 00034 #endif 00035 00036 #include "pqxx/strconv" 00037 00038 00261 00262 namespace pqxx {} 00263 00265 00270 namespace PGSTD {} 00271 00272 #include <pqxx/internal/libpq-forward.hxx> 00273 00274 00275 namespace pqxx 00276 { 00278 00280 struct PQXX_LIBEXPORT thread_safety_model 00281 { 00283 00290 bool have_safe_strerror; 00291 00293 00300 bool safe_libpq; 00301 00303 00306 bool safe_query_cancel; 00307 00309 00314 bool safe_result_copy; 00315 00317 00323 bool safe_kerberos; 00324 00326 PGSTD::string description; 00327 }; 00328 00330 thread_safety_model PQXX_LIBEXPORT describe_thread_safety() throw (); 00331 00333 const oid oid_none = 0; 00334 00336 00358 template<typename T=PGSTD::string, typename CONT=PGSTD::vector<T> > 00359 class items : public CONT 00360 { 00361 public: 00363 items() : CONT() {} //[t0] 00365 explicit items(const T &t) : CONT() { this->push_back(t); } //[t0] 00366 items(const T &t1, const T &t2) : CONT() //[t0] 00367 { this->push_back(t1); this->push_back(t2); } 00368 items(const T &t1, const T &t2, const T &t3) : CONT() //[t0] 00369 { this->push_back(t1); this->push_back(t2); this->push_back(t3); } 00370 items(const T &t1, const T &t2, const T &t3, const T &t4) : CONT() //[t0] 00371 { 00372 this->push_back(t1); 00373 this->push_back(t2); 00374 this->push_back(t3); 00375 this->push_back(t4); 00376 } 00377 items(const T&t1,const T&t2,const T&t3,const T&t4,const T&t5):CONT() //[t0] 00378 { 00379 this->push_back(t1); 00380 this->push_back(t2); 00381 this->push_back(t3); 00382 this->push_back(t4); 00383 this->push_back(t5); 00384 } 00386 items(const CONT &c) : CONT(c) {} //[t0] 00387 00389 items &operator()(const T &t) //[t0] 00390 { 00391 this->push_back(t); 00392 return *this; 00393 } 00394 }; 00395 00396 00397 namespace internal 00398 { 00399 // TODO: Does standard library provide a ready-made version of this? 00401 template<typename ITER> struct dereference 00402 { 00403 typename ITER::value_type operator()(ITER i) const { return *i; } 00404 }; 00405 template<typename T> struct deref_ptr { T operator()(T *i) const {return *i;} }; 00406 } // namespace internal 00407 00408 00410 00416 template<typename ITER, typename ACCESS> inline 00417 PGSTD::string separated_list(const PGSTD::string &sep, //[t0] 00418 ITER begin, 00419 ITER end, 00420 ACCESS access) 00421 { 00422 PGSTD::string result; 00423 if (begin != end) 00424 { 00425 result = to_string(access(begin)); 00426 for (++begin; begin != end; ++begin) 00427 { 00428 result += sep; 00429 result += to_string(access(begin)); 00430 } 00431 } 00432 return result; 00433 } 00434 00439 00441 template<typename ITER> inline PGSTD::string 00442 separated_list(const PGSTD::string &sep, ITER begin, ITER end) //[t0] 00443 { return separated_list(sep,begin,end,internal::dereference<ITER>()); } 00444 00445 00447 template<typename OBJ> inline PGSTD::string 00448 separated_list(const PGSTD::string &sep, OBJ *begin, OBJ *end) //[t0] 00449 { return separated_list(sep,begin,end,internal::deref_ptr<OBJ>()); } 00450 00451 00453 template<typename CONTAINER> inline PGSTD::string 00454 separated_list(const PGSTD::string &sep, const CONTAINER &c) //[t10] 00455 { return separated_list(sep, c.begin(), c.end()); } 00457 00459 00468 namespace internal 00469 { 00470 typedef unsigned long result_size_type; 00471 typedef long result_difference_type; 00472 } // namespace internal 00473 00474 00475 namespace internal 00476 { 00477 void PQXX_LIBEXPORT freepqmem(const void *) throw (); 00478 template<typename P> inline void freepqmem_templated(P *p) throw () 00479 { 00480 freepqmem(p); 00481 } 00482 00483 void PQXX_LIBEXPORT freemallocmem(const void *) throw (); 00484 template<typename P> inline void freemallocmem_templated(P *p) throw () 00485 { 00486 freemallocmem(p); 00487 } 00488 00489 00490 #ifdef PQXX_HAVE_SHARED_PTR 00491 00493 template<typename T, void (*DELETER)(T *) = freepqmem_templated<T> > 00494 class PQAlloc 00495 { 00496 public: 00497 typedef T content_type; 00498 PQAlloc() throw () : m_ptr() {} 00499 PQAlloc(const PQAlloc &rhs) throw () : m_ptr(rhs.m_ptr) {} 00500 explicit PQAlloc(T *t) : m_ptr(t, DELETER) {} 00501 00502 T *get() const throw () { return m_ptr.get(); } 00503 PQAlloc &operator=(const PQAlloc &rhs) throw () 00504 { 00505 m_ptr = rhs.m_ptr; 00506 return *this; 00507 } 00508 00509 T *operator->() const throw () { return m_ptr.get(); } 00510 T &operator*() const throw () { return *m_ptr; } 00511 void reset() throw () { m_ptr.reset(); } 00512 void swap(PQAlloc &other) throw () { m_ptr.swap(other.m_ptr); } 00513 00514 private: 00515 PQXXTR1::shared_ptr<T> m_ptr; 00516 }; 00517 00518 #else // !PQXX_HAVE_SHARED_PTR 00519 00522 class PQXX_LIBEXPORT refcount 00523 { 00524 refcount *volatile m_l, *volatile m_r; 00525 00526 public: 00527 refcount(); 00528 ~refcount(); 00529 00531 void makeref(refcount &) throw (); 00532 00534 bool loseref() throw (); 00535 00536 private: 00538 refcount(const refcount &); 00540 refcount &operator=(const refcount &); 00541 }; 00542 00543 00545 00558 template<typename T, void (*DELETER)(T *) = freepqmem_templated<T> > 00559 class PQAlloc 00560 { 00561 T *m_Obj; 00562 mutable refcount m_rc; 00563 public: 00564 typedef T content_type; 00565 00566 PQAlloc() throw () : m_Obj(0), m_rc() {} 00567 PQAlloc(const PQAlloc &rhs) throw () : m_Obj(0), m_rc() { makeref(rhs); } 00568 ~PQAlloc() throw () { loseref(); } 00569 00570 PQAlloc &operator=(const PQAlloc &rhs) throw () {redoref(rhs); return *this;} 00571 00573 00575 explicit PQAlloc(T *obj) throw () : m_Obj(obj), m_rc() {} 00576 00577 void swap(PQAlloc &rhs) throw () 00578 { 00579 PQAlloc tmp(*this); 00580 *this = rhs; 00581 rhs = tmp; 00582 } 00583 00584 //PQAlloc &operator=(T *obj) throw () { redoref(obj); return *this; } 00585 00587 operator bool() const throw () { return m_Obj != 0; } 00588 00590 bool operator!() const throw () { return !m_Obj; } 00591 00593 00595 T *operator->() const throw (PGSTD::logic_error) 00596 { 00597 if (!m_Obj) throw PGSTD::logic_error("Null pointer dereferenced"); 00598 return m_Obj; 00599 } 00600 00602 00604 T &operator*() const throw (PGSTD::logic_error) { return *operator->(); } 00605 00607 00609 T *get() const throw () { return m_Obj; } 00610 00611 void reset() throw () { loseref(); } 00612 00613 private: 00614 void makeref(T *p) throw () { m_Obj = p; } 00615 00616 void makeref(const PQAlloc &rhs) throw () 00617 { 00618 m_Obj = rhs.m_Obj; 00619 m_rc.makeref(rhs.m_rc); 00620 } 00621 00623 void loseref() throw () 00624 { 00625 if (m_rc.loseref() && m_Obj) DELETER(m_Obj); 00626 m_Obj = 0; 00627 } 00628 00629 void redoref(const PQAlloc &rhs) throw () 00630 { if (rhs.m_Obj != m_Obj) { loseref(); makeref(rhs); } } 00631 void redoref(T *obj) throw () 00632 { if (obj != m_Obj) { loseref(); makeref(obj); } } 00633 }; 00634 00635 #endif // PQXX_HAVE_SHARED_PTR 00636 00637 00638 template<typename T> class scoped_array 00639 { 00640 T *m_ptr; 00641 public: 00642 typedef size_t size_type; 00643 typedef long difference_type; 00644 00645 scoped_array() : m_ptr(0) {} 00646 explicit scoped_array(size_type n) : m_ptr(new T[n]) {} 00647 explicit scoped_array(T *t) : m_ptr(t) {} 00648 ~scoped_array() { delete [] m_ptr; } 00649 00650 T *get() const throw () { return m_ptr; } 00651 T &operator*() const throw () { return *m_ptr; } 00652 template<typename INDEX> T &operator[](INDEX i) const throw () 00653 { return m_ptr[i]; } 00654 00655 scoped_array &operator=(T *t) throw () 00656 { 00657 if (t != m_ptr) 00658 { 00659 delete [] m_ptr; 00660 m_ptr = t; 00661 } 00662 return *this; 00663 } 00664 00665 private: 00667 scoped_array(const scoped_array &); 00668 scoped_array &operator=(const scoped_array &); 00669 }; 00670 00671 00672 class PQXX_LIBEXPORT namedclass 00673 { 00674 public: 00675 namedclass(const PGSTD::string &Classname, const PGSTD::string &Name="") : 00676 m_Classname(Classname), 00677 m_Name(Name) 00678 { 00679 } 00680 00681 const PGSTD::string &name() const throw () { return m_Name; } //[t1] 00682 const PGSTD::string &classname() const throw () {return m_Classname;} //[t73] 00683 PGSTD::string description() const; 00684 00685 private: 00686 PGSTD::string m_Classname, m_Name; 00687 }; 00688 00689 00690 void CheckUniqueRegistration(const namedclass *New, const namedclass *Old); 00691 void CheckUniqueUnregistration(const namedclass *New, const namedclass *Old); 00692 00693 00695 00698 template<typename GUEST> 00699 class unique 00700 { 00701 public: 00702 unique() : m_Guest(0) {} 00703 00704 GUEST *get() const throw () { return m_Guest; } 00705 00706 void Register(GUEST *G) 00707 { 00708 CheckUniqueRegistration(G, m_Guest); 00709 m_Guest = G; 00710 } 00711 00712 void Unregister(GUEST *G) 00713 { 00714 CheckUniqueUnregistration(G, m_Guest); 00715 m_Guest = 0; 00716 } 00717 00718 private: 00719 GUEST *m_Guest; 00720 00722 unique(const unique &); 00724 unique &operator=(const unique &); 00725 }; 00726 00728 00731 void PQXX_LIBEXPORT sleep_seconds(int); 00732 00734 typedef const char *cstring; 00735 00737 00746 cstring PQXX_LIBEXPORT strerror_wrapper(int err, char buf[], PGSTD::size_t len) 00747 throw (); 00748 00749 00751 extern const char sql_begin_work[], sql_commit_work[], sql_rollback_work[]; 00752 00753 00755 template<typename T> inline PGSTD::ptrdiff_t distance(T first, T last) 00756 { 00757 #ifdef PQXX_HAVE_DISTANCE 00758 return PGSTD::distance(first, last); 00759 #else 00760 // Naive implementation. All we really need for now. 00761 PGSTD::ptrdiff_t d; 00762 for (d=0; first != last; ++d) ++first; 00763 return d; 00764 #endif 00765 } 00766 00767 } // namespace internal 00768 } // namespace pqxx 00769 00770 #endif 00771