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  * See COPYING for copyright license.  If you did not receive a file called
00012  * COPYING with this source code, please notify the distributor of this mistake,
00013  * or contact the author.
00014  *
00015  *-------------------------------------------------------------------------
00016  */
00017 #ifndef PQXX_UTIL_H
00018 #define PQXX_UTIL_H
00019 
00020 #include "pqxx/compiler.h"
00021 
00022 #include <cstdio>
00023 #include <stdexcept>
00024 #include <string>
00025 #include <typeinfo>
00026 
00027 extern "C"
00028 {
00029 #include "libpq-fe.h"
00030 }
00031 
00032 
00033 namespace pqxx
00034 {
00035 typedef long result_size_type;
00036 typedef int tuple_size_type;
00037 
00039 typedef Oid oid;
00040 
00042 const oid oid_none = InvalidOid;
00043 
00044 
00047 template<typename T> inline const char *FmtString(T);
00048 
00049 // Not implemented to prevent accidents with irregular meaning of argument:
00050 // template<> inline const char *FmtString(const char *&) { return "%s"; }
00051 
00052 template<> inline const char *FmtString(short)         { return "%hd"; }
00053 template<> inline const char *FmtString(unsigned short){ return "%hu"; }
00054 template<> inline const char *FmtString(int)           { return  "%i"; }
00055 template<> inline const char *FmtString(long)          { return "%li"; }
00056 template<> inline const char *FmtString(unsigned)      { return  "%u"; }
00057 template<> inline const char *FmtString(unsigned long) { return "%lu"; }
00058 template<> inline const char *FmtString(float)         { return  "%f"; }
00059 template<> inline const char *FmtString(double)        { return "%lf"; }
00060 template<> inline const char *FmtString(long double)   { return "%Lf"; }
00061 template<> inline const char *FmtString(char)          { return  "%c"; }
00062 template<> inline const char *FmtString(unsigned char) { return  "%c"; }
00063 
00064 
00066 
00073 template<typename T> inline PGSTD::string ToString(const T &Obj)
00074 {
00075   // TODO: Find a decent way to determine max string length at compile time!
00076   char Buf[500];
00077   sprintf(Buf, FmtString(Obj), Obj);
00078   return PGSTD::string(Buf);
00079 }
00080 
00081 // TODO: Implement date conversions
00082 
00083 template<> inline PGSTD::string ToString(const PGSTD::string &Obj) {return Obj;}
00084 template<> inline PGSTD::string ToString(const char *const &Obj) { return Obj; }
00085 template<> inline PGSTD::string ToString(char *const &Obj) { return Obj; }
00086 
00087 template<> inline PGSTD::string ToString(const bool &Obj) 
00088 { 
00089   return ToString(unsigned(Obj));
00090 }
00091 
00092 template<> inline PGSTD::string ToString(const short &Obj)
00093 {
00094   return ToString(int(Obj));
00095 }
00096 
00097 template<> inline PGSTD::string ToString(const unsigned short &Obj)
00098 {
00099   return ToString(unsigned(Obj));
00100 }
00101 
00102 
00104 
00111 template<typename T> inline void FromString(const char Str[], T &Obj)
00112 {
00113   if (!Str) throw PGSTD::runtime_error("Attempt to convert NULL string to " +
00114                                      PGSTD::string(typeid(T).name()));
00115 
00116   if (sscanf(Str, FmtString(Obj), &Obj) != 1)
00117     throw PGSTD::runtime_error("Cannot convert value '" + 
00118                              PGSTD::string(Str) + 
00119                              "' to " + typeid(T).name());
00120 }
00121 
00122 
00123 template<> inline void FromString(const char Str[], PGSTD::string &Obj)
00124 {
00125   if (!Str) 
00126     throw PGSTD::runtime_error("Attempt to convert NULL C string to C++ "
00127                                "string");
00128   Obj = Str;
00129 }
00130 
00131 
00132 template<> inline void FromString(const char Str[], const char *&Obj)
00133 {
00134   if (!Str)
00135     throw PGSTD::runtime_error("Attempt to read NULL string");
00136   Obj = Str;
00137 }
00138 
00139 template<> inline void FromString(const char Str[], bool &Obj)
00140 {
00141   if (!Str)
00142     throw PGSTD::runtime_error("Attempt to read NULL string");
00143 
00144   switch (Str[0])
00145   {
00146   case 0:
00147   case 'f':
00148     Obj = false;
00149     break;
00150   case '0':
00151     {
00152       int I;
00153       FromString(Str, I);
00154       Obj = (I != 0);
00155     }
00156     break;
00157   default:
00158     Obj = true;
00159   }
00160 }
00161 
00162 
00164 
00167 template<typename T> inline PGSTD::string Quote(const T &Obj, bool EmptyIsNull);
00168 
00170 template<> inline PGSTD::string Quote(const PGSTD::string &Obj, 
00171                                       bool EmptyIsNull)
00172 {
00173   if (EmptyIsNull && Obj.empty()) return "null";
00174 
00175   PGSTD::string Result;
00176   Result.reserve(Obj.size() + 2);
00177   Result += "'";
00178 
00179 #ifdef HAVE_PQESCAPESTRING
00180 
00181   char *const Buf = new char[2*Obj.size() + 1];
00182   try
00183   {
00184     PQescapeString(Buf, Obj.c_str(), Obj.size());
00185     Result += Buf;
00186   }
00187   catch (const PGSTD::exception &)
00188   {
00189     delete [] Buf;
00190     throw;
00191   }
00192   delete [] Buf;
00193 
00194 #else
00195 
00196   for (PGSTD::string::size_type i=0; i < Obj.size(); ++i)
00197   {
00198     if (isgraph(Obj[i]))
00199     {
00200       switch (Obj[i])
00201       {
00202       case '\'':
00203       case '\\':
00204         Result += '\\';
00205       }
00206       Result += Obj[i];
00207     }
00208     else
00209     {
00210         char s[10];
00211         sprintf(s, 
00212                 "\\%03o", 
00213                 static_cast<unsigned int>(static_cast<unsigned char>(Obj[i])));
00214         Result.append(s, 4);
00215     }
00216   }
00217 
00218 #endif
00219 
00220   return Result + '\'';
00221 }
00222 
00223 
00226 template<> inline PGSTD::string Quote(const char *const & Obj, 
00227                                       bool EmptyIsNull)
00228 {
00229   if (!Obj) return "null";
00230   return Quote(PGSTD::string(Obj), EmptyIsNull);
00231 }
00232 
00233 
00235 
00240 template<int LEN> inline PGSTD::string Quote(const char (&Obj)[LEN],
00241                                              bool EmptyIsNull)          //[t18]
00242 {
00243   return Quote(PGSTD::string(Obj), EmptyIsNull);
00244 }
00245 
00246 
00250 template<typename T> inline PGSTD::string Quote(const T &Obj, bool EmptyIsNull)
00251 {
00252   return Quote(ToString(Obj), EmptyIsNull);
00253 }
00254 
00255 
00257 
00259 template<typename T> inline PGSTD::string Quote(T Obj)
00260 {
00261   return Quote(Obj, false);
00262 }
00263 
00264 
00265 
00267 template<typename T> PGSTD::string Classname(const T *);
00268 
00269 
00271 
00276 template<typename T> class PQXX_LIBEXPORT PQAlloc
00277 {
00278   T *m_Obj;
00279 public:
00280   PQAlloc() : m_Obj(0) {}
00281 
00283   explicit PQAlloc(T *obj) : m_Obj(obj) {}
00284 
00285   ~PQAlloc() { close(); }
00286 
00288 
00290   PQAlloc &operator=(T *obj) throw ()
00291   { 
00292     if (obj != m_Obj)
00293     {
00294       close();
00295       m_Obj = obj;
00296     }
00297     return *this;
00298   }
00299 
00301   operator bool() const throw () { return m_Obj != 0; }
00302 
00304   bool operator!() const throw () { return !m_Obj; }
00305 
00307 
00309   T *operator->() const throw (PGSTD::logic_error)
00310   {
00311     if (!m_Obj) throw PGSTD::logic_error("Null pointer dereferenced");
00312     return m_Obj;
00313   }
00314 
00316 
00318   T &operator*() const throw (PGSTD::logic_error) { return *operator->(); }
00319 
00321 
00323   T *c_ptr() const throw () { return m_Obj; }
00324 
00326   void close() throw () { if (m_Obj) freemem(); m_Obj = 0; }
00327 
00328 private:
00329   void freemem() throw ()
00330   {
00331 #ifdef HAVE_PQFREEMEM
00332     PQfreemem(reinterpret_cast<unsigned char *>(m_Obj));
00333 #else
00334     free(m_Obj);
00335 #endif
00336   }
00337 
00338   PQAlloc(const PQAlloc &);             // Not allowed
00339   PQAlloc &operator=(const PQAlloc &);  // Not allowed
00340 };
00341 
00342 
00343 
00349 template<typename GUEST>
00350 class PQXX_LIBEXPORT unique
00351 {
00352 public:
00353   unique() : m_Guest(0) {}
00354 
00355   GUEST *get() const throw () { return m_Guest; }
00356 
00357   void Register(GUEST *G)
00358   {
00359     if (!G) throw PGSTD::logic_error("Internal libpqxx error: NULL " + 
00360                                      Classname(G));
00361     
00362     if (m_Guest)
00363     {
00364       if (G == m_Guest)
00365         throw PGSTD::logic_error(Classname(G) +
00366                                  " '" +
00367                                  G->Name() +
00368                                  "' started more than once without closing");
00369 
00370       throw PGSTD::logic_error("Started " + 
00371                                Classname(G) +
00372                                " '" + 
00373                                G->Name() + 
00374                                "' while '" +
00375                                m_Guest->Name() +
00376                                "' was still active");
00377     }
00378     
00379     m_Guest = G;
00380   }
00381 
00382   void Unregister(GUEST *G)
00383   {
00384     if (G != m_Guest)
00385     {
00386       if (!G) 
00387         throw PGSTD::logic_error("Closing NULL " + Classname(G));
00388       else if (!m_Guest)
00389         throw PGSTD::logic_error("Closing " + 
00390                                  Classname(G) +
00391                                  " '" +
00392                                  G->Name() +
00393                                  "' which wasn't open");
00394       else
00395         throw PGSTD::logic_error("Closing wrong " + 
00396                                  Classname(G) +
00397                                  "; expected '" +
00398                                  m_Guest->Name() +
00399                                  "' but got '" +
00400                                  G->Name() +
00401                                  "'");
00402     }
00403 
00404     m_Guest = 0;
00405   }
00406 
00407 private:
00408   GUEST *m_Guest;
00409 
00410   // Not allowed:
00411   unique(const unique &);
00412   unique &operator=(const unique &);
00413 };
00414 
00415 }
00416 
00417 #endif
00418 

Generated on Sat Jun 7 00:49:34 2003 for libpqxx by doxygen1.3-rc3