Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages  

util.h

Go to the documentation of this file.
00001 /*-------------------------------------------------------------------------
00002  *
00003  *   FILE
00004  *      pqxx/util.h
00005  *
00006  *   DESCRIPTION
00007  *      Various utility definitions for libpqxx
00008  *
00009  * Copyright (c) 2001-2003, Jeroen T. Vermeulen <jtv@xs4all.nl>
00010  *
00011  *-------------------------------------------------------------------------
00012  */
00013 #ifndef PQXX_UTIL_H
00014 #define PQXX_UTIL_H
00015 
00016 #include "pqxx/compiler.h"
00017 
00018 #include <cstdio>
00019 #include <stdexcept>
00020 #include <string>
00021 #include <typeinfo>
00022 
00023 extern "C"
00024 {
00025 #include "libpq-fe.h"
00026 }
00027 
00028 
00029 namespace pqxx
00030 {
00031 typedef long Result_size_type;
00032 typedef int Tuple_size_type;
00033 
00036 template<typename T> inline const char *FmtString(T);
00037 
00038 // Not implemented to prevent accidents with irregular meaning of argument:
00039 // template<> inline const char *FmtString(const char *&) { return "%s"; }
00040 
00041 template<> inline const char *FmtString(short)         { return "%hd"; }
00042 template<> inline const char *FmtString(unsigned short){ return "%hu"; }
00043 template<> inline const char *FmtString(int)           { return  "%i"; }
00044 template<> inline const char *FmtString(long)          { return "%li"; }
00045 template<> inline const char *FmtString(unsigned)      { return  "%u"; }
00046 template<> inline const char *FmtString(unsigned long) { return "%lu"; }
00047 template<> inline const char *FmtString(float)         { return  "%f"; }
00048 template<> inline const char *FmtString(double)        { return "%lf"; }
00049 template<> inline const char *FmtString(long double)   { return "%Lf"; }
00050 template<> inline const char *FmtString(char)          { return  "%c"; }
00051 template<> inline const char *FmtString(unsigned char) { return  "%c"; }
00052 
00053 
00055 
00062 template<typename T> inline PGSTD::string ToString(const T &Obj)
00063 {
00064   // TODO: Find a decent way to determine max string length at compile time!
00065   char Buf[500];
00066   sprintf(Buf, FmtString(Obj), Obj);
00067   return PGSTD::string(Buf);
00068 }
00069 
00070 template<> inline PGSTD::string ToString(const PGSTD::string &Obj) {return Obj;}
00071 template<> inline PGSTD::string ToString(const char *const &Obj) { return Obj; }
00072 template<> inline PGSTD::string ToString(char *const &Obj) { return Obj; }
00073 
00074 template<> inline PGSTD::string ToString(const bool &Obj) 
00075 { 
00076   return ToString(unsigned(Obj));
00077 }
00078 
00079 template<> inline PGSTD::string ToString(const short &Obj)
00080 {
00081   return ToString(int(Obj));
00082 }
00083 
00084 template<> inline PGSTD::string ToString(const unsigned short &Obj)
00085 {
00086   return ToString(unsigned(Obj));
00087 }
00088 
00089 
00091 
00098 template<typename T> inline void FromString(const char Str[], T &Obj)
00099 {
00100   if (!Str) throw PGSTD::runtime_error("Attempt to convert NULL string to " +
00101                                      PGSTD::string(typeid(T).name()));
00102 
00103   if (sscanf(Str, FmtString(Obj), &Obj) != 1)
00104     throw PGSTD::runtime_error("Cannot convert value '" + 
00105                              PGSTD::string(Str) + 
00106                              "' to " + typeid(T).name());
00107 }
00108 
00109 
00110 template<> inline void FromString(const char Str[], PGSTD::string &Obj)
00111 {
00112   if (!Str) 
00113     throw PGSTD::runtime_error("Attempt to convert NULL C string to C++ "
00114                                "string");
00115   Obj = Str;
00116 }
00117 
00118 
00119 template<> inline void FromString(const char Str[], const char *&Obj)
00120 {
00121   if (!Str)
00122     throw PGSTD::runtime_error("Attempt to read NULL string");
00123   Obj = Str;
00124 }
00125 
00126 template<> inline void FromString(const char Str[], bool &Obj)
00127 {
00128   if (!Str)
00129     throw PGSTD::runtime_error("Attempt to read NULL string");
00130 
00131   switch (Str[0])
00132   {
00133   case 0:
00134   case 'f':
00135     Obj = false;
00136     break;
00137   case '0':
00138     {
00139       int I;
00140       FromString(Str, I);
00141       Obj = (I != 0);
00142     }
00143     break;
00144   default:
00145     Obj = true;
00146   }
00147 }
00148 
00149 
00151 
00154 template<typename T> inline PGSTD::string Quote(const T &Obj, bool EmptyIsNull);
00155 
00157 template<> inline PGSTD::string Quote(const PGSTD::string &Obj, 
00158                                       bool EmptyIsNull)
00159 {
00160   if (EmptyIsNull && Obj.empty()) return "null";
00161 
00162   PGSTD::string Result;
00163   Result.reserve(Obj.size() + 2);
00164   Result += "'";
00165 
00166 #ifdef HAVE_PQESCAPESTRING
00167 
00168   char *const Buf = new char[2*Obj.size() + 1];
00169   try
00170   {
00171     PQescapeString(Buf, Obj.c_str(), Obj.size());
00172     Result += Buf;
00173   }
00174   catch (const PGSTD::exception &)
00175   {
00176     delete [] Buf;
00177     throw;
00178   }
00179   delete [] Buf;
00180 
00181 #else
00182 
00183   for (PGSTD::string::size_type i=0; i < Obj.size(); ++i)
00184   {
00185     if (isgraph(Obj[i]))
00186     {
00187       switch (Obj[i])
00188       {
00189       case '\'':
00190       case '\\':
00191         Result += '\\';
00192       }
00193       Result += Obj[i];
00194     }
00195     else
00196     {
00197         char s[10];
00198         sprintf(s, 
00199                 "\\%03o", 
00200                 static_cast<unsigned int>(static_cast<unsigned char>(Obj[i])));
00201         Result.append(s, 4);
00202     }
00203   }
00204 
00205 #endif
00206 
00207   return Result + '\'';
00208 }
00209 
00210 
00213 template<> inline PGSTD::string Quote(const char *const & Obj, 
00214                                       bool EmptyIsNull)
00215 {
00216   if (!Obj) return "null";
00217   return Quote(PGSTD::string(Obj), EmptyIsNull);
00218 }
00219 
00220 
00222 
00227 template<int LEN> inline PGSTD::string Quote(const char (&Obj)[LEN],
00228                                              bool EmptyIsNull)          //[t18]
00229 {
00230   return Quote(PGSTD::string(Obj), EmptyIsNull);
00231 }
00232 
00233 
00237 template<typename T> inline PGSTD::string Quote(const T &Obj, bool EmptyIsNull)
00238 {
00239   return Quote(ToString(Obj), EmptyIsNull);
00240 }
00241 
00242 
00244 
00246 template<typename T> inline PGSTD::string Quote(T Obj)
00247 {
00248   return Quote(Obj, false);
00249 }
00250 
00251 
00252 
00254 template<typename T> PGSTD::string Classname(const T *);
00255 
00256 
00258 
00263 template<typename T> class PQXX_LIBEXPORT PQAlloc
00264 {
00265   T *m_Obj;
00266 public:
00267   PQAlloc() : m_Obj(0) {}
00268 
00270   explicit PQAlloc(T *obj) : m_Obj(obj) {}
00271 
00272   ~PQAlloc() { close(); }
00273 
00275 
00277   PQAlloc &operator=(T *obj) throw ()
00278   { 
00279     if (obj != m_Obj)
00280     {
00281       close();
00282       m_Obj = obj;
00283     }
00284     return *this;
00285   }
00286 
00288   operator bool() const throw () { return m_Obj != 0; }
00289 
00291   bool operator!() const throw () { return !m_Obj; }
00292 
00294 
00296   T *operator->() const throw (PGSTD::logic_error)
00297   {
00298     if (!m_Obj) throw PGSTD::logic_error("Null pointer dereferenced");
00299     return m_Obj;
00300   }
00301 
00303 
00305   T &operator*() const throw (PGSTD::logic_error) { return *operator->(); }
00306 
00308 
00310   T *c_ptr() const throw () { return m_Obj; }
00311 
00313   void close() throw () { if (m_Obj) freemem(); m_Obj = 0; }
00314 
00315 private:
00316   void freemem() throw ()
00317   {
00318 #ifdef HAVE_PQFREEMEM
00319     PQfreemem(reinterpret_cast<unsigned char *>(m_Obj));
00320 #else
00321     free(m_Obj);
00322 #endif
00323   }
00324 
00325   PQAlloc(const PQAlloc &);             // Not allowed
00326   PQAlloc &operator=(const PQAlloc &);  // Not allowed
00327 };
00328 
00329 
00330 
00336 template<typename GUEST>
00337 class PQXX_LIBEXPORT Unique
00338 {
00339 public:
00340   Unique() : m_Guest(0) {}
00341 
00342   GUEST *get() const throw () { return m_Guest; }
00343 
00344   void Register(GUEST *G)
00345   {
00346     if (!G) throw PGSTD::logic_error("Internal libpqxx error: NULL " + 
00347                                      Classname(G));
00348     
00349     if (m_Guest)
00350     {
00351       if (G == m_Guest)
00352         throw PGSTD::logic_error(Classname(G) +
00353                                  " '" +
00354                                  G->Name() +
00355                                  "' started more than once without closing");
00356 
00357       throw PGSTD::logic_error("Started " + 
00358                                Classname(G) +
00359                                " '" + 
00360                                G->Name() + 
00361                                "' while '" +
00362                                m_Guest->Name() +
00363                                "' was still active");
00364     }
00365     
00366     m_Guest = G;
00367   }
00368 
00369   void Unregister(GUEST *G)
00370   {
00371     if (G != m_Guest)
00372     {
00373       if (!G) 
00374         throw PGSTD::logic_error("Closing NULL " + Classname(G));
00375       else if (!m_Guest)
00376         throw PGSTD::logic_error("Closing " + 
00377                                  Classname(G) +
00378                                  " '" +
00379                                  G->Name() +
00380                                  "' which wasn't open");
00381       else
00382         throw PGSTD::logic_error("Closing wrong " + 
00383                                  Classname(G) +
00384                                  "; expected '" +
00385                                  m_Guest->Name() +
00386                                  "' but got '" +
00387                                  G->Name() +
00388                                  "'");
00389     }
00390 
00391     m_Guest = 0;
00392   }
00393 
00394 private:
00395   GUEST *m_Guest;
00396 
00397   // Not allowed:
00398   Unique(const Unique &);
00399   Unique &operator=(const Unique &);
00400 };
00401 
00402 }
00403 
00404 #endif
00405 

Generated on Sat May 24 02:03:12 2003 for libpqxx by doxygen1.3-rc3