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 template<typename T> inline PGSTD::string ToString(const T &Obj)
00056 {
00057   // TODO: Find a decent way to determine max string length at compile time!
00058   char Buf[500];
00059   sprintf(Buf, FmtString(Obj), Obj);
00060   return PGSTD::string(Buf);
00061 }
00062 
00063 template<> inline PGSTD::string ToString(const PGSTD::string &Obj) {return Obj;}
00064 template<> inline PGSTD::string ToString(const char *const &Obj) { return Obj; }
00065 template<> inline PGSTD::string ToString(char *const &Obj) { return Obj; }
00066 
00067 template<> inline PGSTD::string ToString(const bool &Obj) 
00068 { 
00069   return ToString(unsigned(Obj));
00070 }
00071 
00072 template<> inline PGSTD::string ToString(const short &Obj)
00073 {
00074   return ToString(int(Obj));
00075 }
00076 
00077 template<> inline PGSTD::string ToString(const unsigned short &Obj)
00078 {
00079   return ToString(unsigned(Obj));
00080 }
00081 
00082 
00083 template<typename T> inline void FromString(const char Str[], T &Obj)
00084 {
00085   if (!Str) throw PGSTD::runtime_error("Attempt to convert NULL string to " +
00086                                      PGSTD::string(typeid(T).name()));
00087 
00088   if (sscanf(Str, FmtString(Obj), &Obj) != 1)
00089     throw PGSTD::runtime_error("Cannot convert value '" + 
00090                              PGSTD::string(Str) + 
00091                              "' to " + typeid(T).name());
00092 }
00093 
00094 
00095 template<> inline void FromString(const char Str[], PGSTD::string &Obj)
00096 {
00097   if (!Str) 
00098     throw PGSTD::runtime_error("Attempt to convert NULL C string to C++ "
00099                                "string");
00100   Obj = Str;
00101 }
00102 
00103 
00104 template<> inline void FromString(const char Str[], const char *&Obj)
00105 {
00106   if (!Str)
00107     throw PGSTD::runtime_error("Attempt to read NULL string");
00108   Obj = Str;
00109 }
00110 
00111 template<> inline void FromString(const char Str[], bool &Obj)
00112 {
00113   if (!Str)
00114     throw PGSTD::runtime_error("Attempt to read NULL string");
00115 
00116   switch (Str[0])
00117   {
00118   case 0:
00119   case 'f':
00120     Obj = false;
00121     break;
00122   case '0':
00123     {
00124       int I;
00125       FromString(Str, I);
00126       Obj = (I != 0);
00127     }
00128     break;
00129   default:
00130     Obj = true;
00131   }
00132 }
00133 
00134 
00136 
00139 template<typename T> inline PGSTD::string Quote(const T &Obj, bool EmptyIsNull);
00140 
00142 template<> inline PGSTD::string Quote(const PGSTD::string &Obj, 
00143                                       bool EmptyIsNull)
00144 {
00145   if (EmptyIsNull && Obj.empty()) return "null";
00146 
00147   PGSTD::string Result;
00148   Result.reserve(Obj.size() + 2);
00149   Result += "'";
00150 
00151 #ifdef HAVE_PQESCAPESTRING
00152 
00153   char *const Buf = new char[2*Obj.size() + 1];
00154   try
00155   {
00156     PQescapeString(Buf, Obj.c_str(), Obj.size());
00157     Result += Buf;
00158   }
00159   catch (const PGSTD::exception &)
00160   {
00161     delete [] Buf;
00162     throw;
00163   }
00164   delete [] Buf;
00165 
00166 #else
00167 
00168   for (PGSTD::string::size_type i=0; i < Obj.size(); ++i)
00169   {
00170     if (isgraph(Obj[i]))
00171     {
00172       switch (Obj[i])
00173       {
00174       case '\'':
00175       case '\\':
00176         Result += '\\';
00177       }
00178       Result += Obj[i];
00179     }
00180     else
00181     {
00182         char s[10];
00183         sprintf(s, 
00184                 "\\%03o", 
00185                 static_cast<unsigned int>(static_cast<unsigned char>(Obj[i])));
00186         Result.append(s, 4);
00187     }
00188   }
00189 
00190 #endif
00191 
00192   return Result + '\'';
00193 }
00194 
00195 
00198 template<> inline PGSTD::string Quote(const char *const & Obj, 
00199                                       bool EmptyIsNull)
00200 {
00201   if (!Obj) return "null";
00202   return Quote(PGSTD::string(Obj), EmptyIsNull);
00203 }
00204 
00205 
00207 
00212 template<int LEN> inline PGSTD::string Quote(const char (&Obj)[LEN],
00213                                              bool EmptyIsNull)          //[t18]
00214 {
00215   return Quote(PGSTD::string(Obj), EmptyIsNull);
00216 }
00217 
00218 
00222 template<typename T> inline PGSTD::string Quote(const T &Obj, bool EmptyIsNull)
00223 {
00224   return Quote(ToString(Obj), EmptyIsNull);
00225 }
00226 
00227 
00229 
00231 template<typename T> inline PGSTD::string Quote(T Obj)
00232 {
00233   return Quote(Obj, false);
00234 }
00235 
00236 
00237 
00239 template<typename T> PGSTD::string Classname(const T *);
00240 
00241 
00243 
00248 template<typename T> class PQAlloc
00249 {
00250   T *m_Obj;
00251 public:
00252   PQAlloc() : m_Obj(0) {}
00253 
00255   explicit PQAlloc(T *obj) : m_Obj(obj) {}
00256 
00257   ~PQAlloc() { close(); }
00258 
00260 
00262   PQAlloc &operator=(T *obj) throw ()
00263   { 
00264     if (obj != m_Obj)
00265     {
00266       close();
00267       m_Obj = obj;
00268     }
00269     return *this;
00270   }
00271 
00273   operator bool() const throw () { return m_Obj != 0; }
00274 
00276   bool operator!() const throw () { return !m_Obj; }
00277 
00279 
00281   T *operator->() const throw (PGSTD::logic_error)
00282   {
00283     if (!m_Obj) throw PGSTD::logic_error("Null pointer dereferenced");
00284     return m_Obj;
00285   }
00286 
00288 
00290   T &operator*() const throw (PGSTD::logic_error) { return *operator->(); }
00291 
00293 
00295   T *c_ptr() const throw () { return m_Obj; }
00296 
00298   void close() throw () { if (m_Obj) freemem(); m_Obj = 0; }
00299 
00300 private:
00301   void freemem() throw ()
00302   {
00303 #ifdef HAVE_PQFREEMEM
00304     PQfreemem(m_Obj);
00305 #else
00306     free(m_Obj);
00307 #endif
00308   }
00309 
00310   PQAlloc(const PQAlloc &);             // Not allowed
00311   PQAlloc &operator=(const PQAlloc &);  // Not allowed
00312 };
00313 
00314 
00315 
00321 template<typename GUEST>
00322 class Unique
00323 {
00324 public:
00325   Unique() : m_Guest(0) {}
00326 
00327   GUEST *get() const throw () { return m_Guest; }
00328 
00329   void Register(GUEST *G)
00330   {
00331     if (!G) throw PGSTD::logic_error("Internal libpqxx error: NULL " + 
00332                                      Classname(G));
00333     
00334     if (m_Guest)
00335     {
00336       if (G == m_Guest)
00337         throw PGSTD::logic_error(Classname(G) +
00338                                  " '" +
00339                                  G->Name() +
00340                                  "' started more than once without closing");
00341 
00342       throw PGSTD::logic_error("Started " + 
00343                                Classname(G) +
00344                                " '" + 
00345                                G->Name() + 
00346                                "' while '" +
00347                                m_Guest->Name() +
00348                                "' was still active");
00349     }
00350     
00351     m_Guest = G;
00352   }
00353 
00354   void Unregister(GUEST *G)
00355   {
00356     if (G != m_Guest)
00357     {
00358       if (!G) 
00359         throw PGSTD::logic_error("Closing NULL " + Classname(G));
00360       else if (!m_Guest)
00361         throw PGSTD::logic_error("Closing " + 
00362                                  Classname(G) +
00363                                  " '" +
00364                                  G->Name() +
00365                                  "' which wasn't open");
00366       else
00367         throw PGSTD::logic_error("Closing wrong " + 
00368                                  Classname(G) +
00369                                  "; expected '" +
00370                                  m_Guest->Name() +
00371                                  "' but got '" +
00372                                  G->Name() +
00373                                  "'");
00374     }
00375 
00376     m_Guest = 0;
00377   }
00378 
00379 private:
00380   GUEST *m_Guest;
00381 
00382   // Not allowed:
00383   Unique(const Unique &);
00384   Unique &operator=(const Unique &);
00385 };
00386 
00387 }
00388 
00389 #endif
00390 

Generated on Sat May 10 18:53:39 2003 for libpqxx by doxygen1.3-rc3