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

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 
00045 
00058 template<typename T> void error_unsupported_type_in_string_conversion(T);
00059 
00060 
00062 
00068 template<typename T> inline const char *FmtString(T t)
00069 {
00070   error_unsupported_type_in_string_conversion(t);
00071   return 0;
00072 }
00073 
00074 // Not implemented to prevent accidents with irregular meaning of argument:
00075 // template<> inline const char *FmtString(const char *&) { return "%s"; }
00076 
00077 template<> inline const char *FmtString(short)         { return "%hd"; }
00078 template<> inline const char *FmtString(unsigned short){ return "%hu"; }
00079 template<> inline const char *FmtString(int)           { return  "%i"; }
00080 template<> inline const char *FmtString(long)          { return "%li"; }
00081 template<> inline const char *FmtString(unsigned)      { return  "%u"; }
00082 template<> inline const char *FmtString(unsigned long) { return "%lu"; }
00083 template<> inline const char *FmtString(float)         { return  "%f"; }
00084 template<> inline const char *FmtString(double)        { return "%lf"; }
00085 template<> inline const char *FmtString(long double)   { return "%Lf"; }
00086 template<> inline const char *FmtString(char)          { return  "%c"; }
00087 template<> inline const char *FmtString(unsigned char) { return  "%c"; }
00088 
00089 
00091 
00098 template<typename T> inline PGSTD::string ToString(const T &Obj)
00099 {
00100   // TODO: Find a decent way to determine max string length at compile time!
00101   char Buf[500];
00102   sprintf(Buf, FmtString(Obj), Obj);
00103   return PGSTD::string(Buf);
00104 }
00105 
00106 // TODO: Implement date conversions
00107 
00108 template<> inline PGSTD::string ToString(const PGSTD::string &Obj) {return Obj;}
00109 template<> inline PGSTD::string ToString(const char *const &Obj) { return Obj; }
00110 template<> inline PGSTD::string ToString(char *const &Obj) { return Obj; }
00111 
00112 template<> inline PGSTD::string ToString(const unsigned char *const &Obj)
00113 {
00114   return reinterpret_cast<const char *>(Obj);
00115 }
00116 
00117 template<> inline PGSTD::string ToString(const bool &Obj) 
00118 { 
00119   return ToString(unsigned(Obj));
00120 }
00121 
00122 template<> inline PGSTD::string ToString(const short &Obj)
00123 {
00124   return ToString(int(Obj));
00125 }
00126 
00127 template<> inline PGSTD::string ToString(const unsigned short &Obj)
00128 {
00129   return ToString(unsigned(Obj));
00130 }
00131 
00132 
00134 
00141 template<typename T> inline void FromString(const char Str[], T &Obj)
00142 {
00143   if (!Str) throw PGSTD::runtime_error("Attempt to convert NULL string to " +
00144                                      PGSTD::string(typeid(T).name()));
00145 
00146   if (sscanf(Str, FmtString(Obj), &Obj) != 1)
00147     throw PGSTD::runtime_error("Cannot convert value '" + 
00148                              PGSTD::string(Str) + 
00149                              "' to " + typeid(T).name());
00150 }
00151 
00152 
00153 template<> inline void FromString(const char Str[], PGSTD::string &Obj)
00154 {
00155   if (!Str) 
00156     throw PGSTD::runtime_error("Attempt to convert NULL C string to C++ "
00157                                "string");
00158   Obj = Str;
00159 }
00160 
00161 
00162 template<> inline void FromString(const char Str[], const char *&Obj)
00163 {
00164   if (!Str)
00165     throw PGSTD::runtime_error("Attempt to read NULL string");
00166   Obj = Str;
00167 }
00168 
00169 template<> inline void FromString(const char Str[], const unsigned char *&Obj)
00170 {
00171   const char *C;
00172   FromString(Str, C);
00173   Obj = reinterpret_cast<const unsigned char *>(C);
00174 }
00175 
00176 template<> inline void FromString(const char Str[], bool &Obj)
00177 {
00178   if (!Str)
00179     throw PGSTD::runtime_error("Attempt to read NULL string");
00180 
00181   switch (Str[0])
00182   {
00183   case 0:
00184   case 'f':
00185     Obj = false;
00186     break;
00187   case '0':
00188     {
00189       int I;
00190       FromString(Str, I);
00191       Obj = (I != 0);
00192     }
00193     break;
00194   default:
00195     Obj = true;
00196   }
00197 }
00198 
00199 
00201 
00204 template<typename T> inline PGSTD::string Quote(const T &Obj, bool EmptyIsNull);
00205 
00207 template<> inline PGSTD::string Quote(const PGSTD::string &Obj, 
00208                                       bool EmptyIsNull)
00209 {
00210   if (EmptyIsNull && Obj.empty()) return "null";
00211 
00212   PGSTD::string Result;
00213   Result.reserve(Obj.size() + 2);
00214   Result += "'";
00215 
00216 #ifdef PQXX_HAVE_PQESCAPESTRING
00217 
00218   char *const Buf = new char[2*Obj.size() + 1];
00219   try
00220   {
00221     PQescapeString(Buf, Obj.c_str(), Obj.size());
00222     Result += Buf;
00223   }
00224   catch (const PGSTD::exception &)
00225   {
00226     delete [] Buf;
00227     throw;
00228   }
00229   delete [] Buf;
00230 
00231 #else
00232 
00233   for (PGSTD::string::size_type i=0; i < Obj.size(); ++i)
00234   {
00235     if (isgraph(Obj[i]))
00236     {
00237       switch (Obj[i])
00238       {
00239       case '\'':
00240       case '\\':
00241         Result += '\\';
00242       }
00243       Result += Obj[i];
00244     }
00245     else
00246     {
00247         char s[10];
00248         sprintf(s, 
00249                 "\\%03o", 
00250                 static_cast<unsigned int>(static_cast<unsigned char>(Obj[i])));
00251         Result.append(s, 4);
00252     }
00253   }
00254 
00255 #endif
00256 
00257   return Result + '\'';
00258 }
00259 
00260 
00263 template<> inline PGSTD::string Quote(const char *const & Obj, 
00264                                       bool EmptyIsNull)
00265 {
00266   if (!Obj) return "null";
00267   return Quote(PGSTD::string(Obj), EmptyIsNull);
00268 }
00269 
00270 
00272 
00277 template<int LEN> inline PGSTD::string Quote(const char (&Obj)[LEN],
00278                                              bool EmptyIsNull)          //[t18]
00279 {
00280   return Quote(PGSTD::string(Obj), EmptyIsNull);
00281 }
00282 
00283 
00287 template<typename T> inline PGSTD::string Quote(const T &Obj, bool EmptyIsNull)
00288 {
00289   return Quote(ToString(Obj), EmptyIsNull);
00290 }
00291 
00292 
00294 
00296 template<typename T> inline PGSTD::string Quote(T Obj)
00297 {
00298   return Quote(Obj, false);
00299 }
00300 
00301 
00303 template<typename T> PGSTD::string Classname(const T *);
00304 
00305 
00307 
00313 template<typename T> class PQAlloc
00314 {
00315   T *m_Obj;
00316 public:
00317   PQAlloc() : m_Obj(0) {}
00318 
00320   explicit PQAlloc(T *obj) : m_Obj(obj) {}
00321 
00322   ~PQAlloc() { close(); }
00323 
00325 
00327   PQAlloc &operator=(T *obj) throw ()
00328   { 
00329     if (obj != m_Obj)
00330     {
00331       close();
00332       m_Obj = obj;
00333     }
00334     return *this;
00335   }
00336 
00338   operator bool() const throw () { return m_Obj != 0; }
00339 
00341   bool operator!() const throw () { return !m_Obj; }
00342 
00344 
00346   T *operator->() const throw (PGSTD::logic_error)
00347   {
00348     if (!m_Obj) throw PGSTD::logic_error("Null pointer dereferenced");
00349     return m_Obj;
00350   }
00351 
00353 
00355   T &operator*() const throw (PGSTD::logic_error) { return *operator->(); }
00356 
00358 
00360   T *c_ptr() const throw () { return m_Obj; }
00361 
00363   void close() throw () { if (m_Obj) freemem(); m_Obj = 0; }
00364 
00365 private:
00366   void freemem() throw ()
00367   {
00368 #if defined(PQXX_HAVE_PQFREEMEM)
00369     PQfreemem(reinterpret_cast<unsigned char *>(m_Obj));
00370 #else
00371     free(m_Obj);
00372 #endif
00373   }
00374 
00375   PQAlloc(const PQAlloc &);             // Not allowed
00376   PQAlloc &operator=(const PQAlloc &);  // Not allowed
00377 };
00378 
00379 
00381 template<> inline void PQAlloc<PGnotify>::freemem() throw ()
00382 {
00383 #if defined(PQXX_HAVE_PQFREEMEM)
00384     PQfreemem(reinterpret_cast<unsigned char *>(m_Obj));
00385 #elif defined(PQXX_HAVE_PQFREENOTIFY)
00386     PQfreeNotify(m_Obj);
00387 #else
00388     free(m_Obj);
00389 #endif
00390 }
00391 
00392 
00393 
00395 
00402 template<typename GUEST>
00403 class unique
00404 {
00405 public:
00406   unique() : m_Guest(0) {}
00407 
00408   GUEST *get() const throw () { return m_Guest; }
00409 
00410   void Register(GUEST *G)
00411   {
00412     if (!G) throw PGSTD::logic_error("Internal libpqxx error: NULL " + 
00413                                      Classname(G));
00414     
00415     if (m_Guest)
00416     {
00417       if (G == m_Guest)
00418         throw PGSTD::logic_error(Classname(G) +
00419                                  " '" +
00420                                  G->name() +
00421                                  "' started more than once without closing");
00422 
00423       throw PGSTD::logic_error("Started " + 
00424                                Classname(G) +
00425                                " '" + 
00426                                G->name() + 
00427                                "' while '" +
00428                                m_Guest->name() +
00429                                "' was still active");
00430     }
00431     
00432     m_Guest = G;
00433   }
00434 
00435   void Unregister(GUEST *G)
00436   {
00437     if (G != m_Guest)
00438     {
00439       if (!G) 
00440         throw PGSTD::logic_error("Closing NULL " + Classname(G));
00441       else if (!m_Guest)
00442         throw PGSTD::logic_error("Closing " + 
00443                                  Classname(G) +
00444                                  " '" +
00445                                  G->name() +
00446                                  "' which wasn't open");
00447       else
00448         throw PGSTD::logic_error("Closing wrong " + 
00449                                  Classname(G) +
00450                                  "; expected '" +
00451                                  m_Guest->name() +
00452                                  "' but got '" +
00453                                  G->name() +
00454                                  "'");
00455     }
00456 
00457     m_Guest = 0;
00458   }
00459 
00460 private:
00461   GUEST *m_Guest;
00462 
00463   // Not allowed:
00464   unique(const unique &);
00465   unique &operator=(const unique &);
00466 };
00467 
00468 }
00469 
00470 

Generated on Fri Oct 31 16:15:35 2003 for libpqxx by doxygen 1.3.4