Main Page | Namespace List | Class Hierarchy | Alphabetical List | Compound List | File List | Namespace Members | Compound Members | File Members

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-2003, 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/libcompiler.h"
00019 
00020 #include <cstdio>
00021 #include <cctype>
00022 #include <stdexcept>
00023 #include <string>
00024 #include <typeinfo>
00025 
00026 extern "C"
00027 {
00028 #include "libpq-fe.h"
00029 }
00030 
00031 
00032 namespace pqxx
00033 {
00034 typedef long result_size_type;
00035 typedef int tuple_size_type;
00036 
00038 typedef Oid oid;
00039 
00041 const oid oid_none = InvalidOid;
00042 
00043 
00046 template<typename T> inline const char *FmtString(T);
00047 
00048 // Not implemented to prevent accidents with irregular meaning of argument:
00049 // template<> inline const char *FmtString(const char *&) { return "%s"; }
00050 
00051 template<> inline const char *FmtString(short)         { return "%hd"; }
00052 template<> inline const char *FmtString(unsigned short){ return "%hu"; }
00053 template<> inline const char *FmtString(int)           { return  "%i"; }
00054 template<> inline const char *FmtString(long)          { return "%li"; }
00055 template<> inline const char *FmtString(unsigned)      { return  "%u"; }
00056 template<> inline const char *FmtString(unsigned long) { return "%lu"; }
00057 template<> inline const char *FmtString(float)         { return  "%f"; }
00058 template<> inline const char *FmtString(double)        { return "%lf"; }
00059 template<> inline const char *FmtString(long double)   { return "%Lf"; }
00060 template<> inline const char *FmtString(char)          { return  "%c"; }
00061 template<> inline const char *FmtString(unsigned char) { return  "%c"; }
00062 
00063 
00065 
00072 template<typename T> inline PGSTD::string ToString(const T &Obj)
00073 {
00074   // TODO: Find a decent way to determine max string length at compile time!
00075   char Buf[500];
00076   sprintf(Buf, FmtString(Obj), Obj);
00077   return PGSTD::string(Buf);
00078 }
00079 
00080 // TODO: Implement date conversions
00081 
00082 template<> inline PGSTD::string ToString(const PGSTD::string &Obj) {return Obj;}
00083 template<> inline PGSTD::string ToString(const char *const &Obj) { return Obj; }
00084 template<> inline PGSTD::string ToString(char *const &Obj) { return Obj; }
00085 
00086 template<> inline PGSTD::string ToString(const bool &Obj) 
00087 { 
00088   return ToString(unsigned(Obj));
00089 }
00090 
00091 template<> inline PGSTD::string ToString(const short &Obj)
00092 {
00093   return ToString(int(Obj));
00094 }
00095 
00096 template<> inline PGSTD::string ToString(const unsigned short &Obj)
00097 {
00098   return ToString(unsigned(Obj));
00099 }
00100 
00101 
00103 
00110 template<typename T> inline void FromString(const char Str[], T &Obj)
00111 {
00112   if (!Str) throw PGSTD::runtime_error("Attempt to convert NULL string to " +
00113                                      PGSTD::string(typeid(T).name()));
00114 
00115   if (sscanf(Str, FmtString(Obj), &Obj) != 1)
00116     throw PGSTD::runtime_error("Cannot convert value '" + 
00117                              PGSTD::string(Str) + 
00118                              "' to " + typeid(T).name());
00119 }
00120 
00121 
00122 template<> inline void FromString(const char Str[], PGSTD::string &Obj)
00123 {
00124   if (!Str) 
00125     throw PGSTD::runtime_error("Attempt to convert NULL C string to C++ "
00126                                "string");
00127   Obj = Str;
00128 }
00129 
00130 
00131 template<> inline void FromString(const char Str[], const char *&Obj)
00132 {
00133   if (!Str)
00134     throw PGSTD::runtime_error("Attempt to read NULL string");
00135   Obj = Str;
00136 }
00137 
00138 template<> inline void FromString(const char Str[], bool &Obj)
00139 {
00140   if (!Str)
00141     throw PGSTD::runtime_error("Attempt to read NULL string");
00142 
00143   switch (Str[0])
00144   {
00145   case 0:
00146   case 'f':
00147     Obj = false;
00148     break;
00149   case '0':
00150     {
00151       int I;
00152       FromString(Str, I);
00153       Obj = (I != 0);
00154     }
00155     break;
00156   default:
00157     Obj = true;
00158   }
00159 }
00160 
00161 
00163 
00166 template<typename T> inline PGSTD::string Quote(const T &Obj, bool EmptyIsNull);
00167 
00169 template<> inline PGSTD::string Quote(const PGSTD::string &Obj, 
00170                                       bool EmptyIsNull)
00171 {
00172   if (EmptyIsNull && Obj.empty()) return "null";
00173 
00174   PGSTD::string Result;
00175   Result.reserve(Obj.size() + 2);
00176   Result += "'";
00177 
00178 #ifdef PQXX_HAVE_PQESCAPESTRING
00179 
00180   char *const Buf = new char[2*Obj.size() + 1];
00181   try
00182   {
00183     PQescapeString(Buf, Obj.c_str(), Obj.size());
00184     Result += Buf;
00185   }
00186   catch (const PGSTD::exception &)
00187   {
00188     delete [] Buf;
00189     throw;
00190   }
00191   delete [] Buf;
00192 
00193 #else
00194 
00195   for (PGSTD::string::size_type i=0; i < Obj.size(); ++i)
00196   {
00197     if (isgraph(Obj[i]))
00198     {
00199       switch (Obj[i])
00200       {
00201       case '\'':
00202       case '\\':
00203         Result += '\\';
00204       }
00205       Result += Obj[i];
00206     }
00207     else
00208     {
00209         char s[10];
00210         sprintf(s, 
00211                 "\\%03o", 
00212                 static_cast<unsigned int>(static_cast<unsigned char>(Obj[i])));
00213         Result.append(s, 4);
00214     }
00215   }
00216 
00217 #endif
00218 
00219   return Result + '\'';
00220 }
00221 
00222 
00225 template<> inline PGSTD::string Quote(const char *const & Obj, 
00226                                       bool EmptyIsNull)
00227 {
00228   if (!Obj) return "null";
00229   return Quote(PGSTD::string(Obj), EmptyIsNull);
00230 }
00231 
00232 
00234 
00239 template<int LEN> inline PGSTD::string Quote(const char (&Obj)[LEN],
00240                                              bool EmptyIsNull)          //[t18]
00241 {
00242   return Quote(PGSTD::string(Obj), EmptyIsNull);
00243 }
00244 
00245 
00249 template<typename T> inline PGSTD::string Quote(const T &Obj, bool EmptyIsNull)
00250 {
00251   return Quote(ToString(Obj), EmptyIsNull);
00252 }
00253 
00254 
00256 
00258 template<typename T> inline PGSTD::string Quote(T Obj)
00259 {
00260   return Quote(Obj, false);
00261 }
00262 
00263 
00265 template<typename T> PGSTD::string Classname(const T *);
00266 
00267 
00269 
00275 template<typename T> class PQAlloc
00276 {
00277   T *m_Obj;
00278 public:
00279   PQAlloc() : m_Obj(0) {}
00280 
00282   explicit PQAlloc(T *obj) : m_Obj(obj) {}
00283 
00284   ~PQAlloc() { close(); }
00285 
00287 
00289   PQAlloc &operator=(T *obj) throw ()
00290   { 
00291     if (obj != m_Obj)
00292     {
00293       close();
00294       m_Obj = obj;
00295     }
00296     return *this;
00297   }
00298 
00300   operator bool() const throw () { return m_Obj != 0; }
00301 
00303   bool operator!() const throw () { return !m_Obj; }
00304 
00306 
00308   T *operator->() const throw (PGSTD::logic_error)
00309   {
00310     if (!m_Obj) throw PGSTD::logic_error("Null pointer dereferenced");
00311     return m_Obj;
00312   }
00313 
00315 
00317   T &operator*() const throw (PGSTD::logic_error) { return *operator->(); }
00318 
00320 
00322   T *c_ptr() const throw () { return m_Obj; }
00323 
00325   void close() throw () { if (m_Obj) freemem(); m_Obj = 0; }
00326 
00327 private:
00328   void freemem() throw ()
00329   {
00330 #if defined(PQXX_HAVE_PQFREEMEM)
00331     PQfreemem(reinterpret_cast<unsigned char *>(m_Obj));
00332 #else
00333     free(m_Obj);
00334 #endif
00335   }
00336 
00337   PQAlloc(const PQAlloc &);             // Not allowed
00338   PQAlloc &operator=(const PQAlloc &);  // Not allowed
00339 };
00340 
00341 
00343 template<> inline void PQAlloc<PGnotify>::freemem() throw ()
00344 {
00345 #if defined(PQXX_HAVE_PQFREEMEM)
00346     PQfreemem(reinterpret_cast<unsigned char *>(m_Obj));
00347 #elif defined(PQXX_HAVE_PQFREENOTIFY)
00348     PQfreeNotify(m_Obj);
00349 #else
00350     free(m_Obj);
00351 #endif
00352 }
00353 
00354 
00355 
00357 
00364 template<typename GUEST>
00365 class unique
00366 {
00367 public:
00368   unique() : m_Guest(0) {}
00369 
00370   GUEST *get() const throw () { return m_Guest; }
00371 
00372   void Register(GUEST *G)
00373   {
00374     if (!G) throw PGSTD::logic_error("Internal libpqxx error: NULL " + 
00375                                      Classname(G));
00376     
00377     if (m_Guest)
00378     {
00379       if (G == m_Guest)
00380         throw PGSTD::logic_error(Classname(G) +
00381                                  " '" +
00382                                  G->name() +
00383                                  "' started more than once without closing");
00384 
00385       throw PGSTD::logic_error("Started " + 
00386                                Classname(G) +
00387                                " '" + 
00388                                G->name() + 
00389                                "' while '" +
00390                                m_Guest->name() +
00391                                "' was still active");
00392     }
00393     
00394     m_Guest = G;
00395   }
00396 
00397   void Unregister(GUEST *G)
00398   {
00399     if (G != m_Guest)
00400     {
00401       if (!G) 
00402         throw PGSTD::logic_error("Closing NULL " + Classname(G));
00403       else if (!m_Guest)
00404         throw PGSTD::logic_error("Closing " + 
00405                                  Classname(G) +
00406                                  " '" +
00407                                  G->name() +
00408                                  "' which wasn't open");
00409       else
00410         throw PGSTD::logic_error("Closing wrong " + 
00411                                  Classname(G) +
00412                                  "; expected '" +
00413                                  m_Guest->name() +
00414                                  "' but got '" +
00415                                  G->name() +
00416                                  "'");
00417     }
00418 
00419     m_Guest = 0;
00420   }
00421 
00422 private:
00423   GUEST *m_Guest;
00424 
00425   // Not allowed:
00426   unique(const unique &);
00427   unique &operator=(const unique &);
00428 };
00429 
00430 }
00431 
00432 

Generated on Mon Sep 22 20:47:53 2003 for libpqxx by doxygen 1.3.2