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

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(int)           { return  "%i"; }
00042 template<> inline const char *FmtString(long)          { return "%li"; }
00043 template<> inline const char *FmtString(unsigned)      { return  "%u"; }
00044 template<> inline const char *FmtString(unsigned long) { return "%lu"; }
00045 template<> inline const char *FmtString(float)         { return  "%f"; }
00046 template<> inline const char *FmtString(double)        { return "%lf"; }
00047 template<> inline const char *FmtString(long double)   { return "%Lf"; }
00048 template<> inline const char *FmtString(char)          { return  "%c"; }
00049 template<> inline const char *FmtString(unsigned char) { return  "%c"; }
00050 
00051 
00053 template<typename T> inline PGSTD::string ToString(const T &Obj)
00054 {
00055   // TODO: Find a decent way to determine max string length at compile time!
00056   char Buf[500];
00057   sprintf(Buf, FmtString(Obj), Obj);
00058   return PGSTD::string(Buf);
00059 }
00060 
00061 template<> inline PGSTD::string ToString(const PGSTD::string &Obj) {return Obj;}
00062 template<> inline PGSTD::string ToString(const char *const &Obj) { return Obj; }
00063 template<> inline PGSTD::string ToString(char *const &Obj) { return Obj; }
00064 
00065 template<> inline PGSTD::string ToString(const bool &Obj) 
00066 { 
00067   return ToString(unsigned(Obj));
00068 }
00069 
00070 template<> inline PGSTD::string ToString(const short &Obj)
00071 {
00072   return ToString(int(Obj));
00073 }
00074 
00075 template<> inline PGSTD::string ToString(const unsigned short &Obj)
00076 {
00077   return ToString(unsigned(Obj));
00078 }
00079 
00080 
00081 template<typename T> inline void FromString(const char Str[], T &Obj)
00082 {
00083   if (!Str) throw PGSTD::runtime_error("Attempt to convert NULL string to " +
00084                                      PGSTD::string(typeid(T).name()));
00085 
00086   if (sscanf(Str, FmtString(Obj), &Obj) != 1)
00087     throw PGSTD::runtime_error("Cannot convert value '" + 
00088                              PGSTD::string(Str) + 
00089                              "' to " + typeid(T).name());
00090 }
00091 
00092 
00093 template<> inline void FromString(const char Str[], PGSTD::string &Obj)
00094 {
00095   if (!Str) 
00096     throw PGSTD::runtime_error("Attempt to convert NULL C string to C++ "
00097                                "string");
00098   Obj = Str;
00099 }
00100 
00101 
00102 template<> inline void FromString(const char Str[], const char *&Obj)
00103 {
00104   if (!Str)
00105     throw PGSTD::runtime_error("Attempt to read NULL string");
00106   Obj = Str;
00107 }
00108 
00109 template<> inline void FromString(const char Str[], bool &Obj)
00110 {
00111   if (!Str)
00112     throw PGSTD::runtime_error("Attempt to read NULL string");
00113 
00114   switch (Str[0])
00115   {
00116   case 0:
00117   case 'f':
00118     Obj = false;
00119     break;
00120   case '0':
00121     {
00122       int I;
00123       FromString(Str, I);
00124       Obj = (I != 0);
00125     }
00126     break;
00127   default:
00128     Obj = true;
00129   }
00130 }
00131 
00132 
00135 template<typename T> PGSTD::string Quote(const T &Obj, bool EmptyIsNull=false);
00136 
00137 
00139 template<> inline PGSTD::string Quote(const PGSTD::string &Obj, 
00140                                       bool EmptyIsNull)
00141 {
00142   if (EmptyIsNull && Obj.empty()) return "null";
00143 
00144   PGSTD::string Result;
00145   Result.reserve(Obj.size() + 2);
00146   Result += "'";
00147 
00148 #ifdef HAVE_PQESCAPESTRING
00149 
00150   char *const Buf = new char[2*Obj.size() + 1];
00151   try
00152   {
00153     PQescapeString(Buf, Obj.c_str(), Obj.size());
00154     Result += Buf;
00155   }
00156   catch (const PGSTD::exception &)
00157   {
00158     delete [] Buf;
00159     throw;
00160   }
00161   delete [] Buf;
00162 
00163 #else
00164 
00165   for (PGSTD::string::size_type i=0; i < Obj.size(); ++i)
00166   {
00167     if (isgraph(Obj[i]))
00168     {
00169       switch (Obj[i])
00170       {
00171       case '\'':
00172       case '\\':
00173         Result += '\\';
00174       }
00175       Result += Obj[i];
00176     }
00177     else
00178     {
00179         char s[10];
00180         sprintf(s, 
00181                 "\\%03o", 
00182                 static_cast<unsigned int>(static_cast<unsigned char>(Obj[i])));
00183         Result.append(s, 4);
00184     }
00185   }
00186 
00187 #endif
00188 
00189   return Result + '\'';
00190 }
00191 
00192 
00195 template<> inline PGSTD::string Quote(const char *const & Obj, 
00196                                       bool EmptyIsNull)
00197 {
00198   if (!Obj) return "null";
00199   return Quote(PGSTD::string(Obj), EmptyIsNull);
00200 }
00201 
00202 
00206 template<typename T> inline PGSTD::string Quote(const T &Obj, bool EmptyIsNull)
00207 {
00208   return Quote(ToString(Obj), EmptyIsNull);
00209 }
00210 
00211 
00212 
00214 template<typename T> PGSTD::string Classname(const T *);
00215 
00216 
00222 template<typename GUEST>
00223 class Unique
00224 {
00225 public:
00226   Unique() : m_Guest(0) {}
00227 
00228   const GUEST *get() const throw () { return m_Guest; }
00229 
00230   void Register(const GUEST *G)
00231   {
00232     if (!G) throw PGSTD::logic_error("Internal libpqxx error: NULL " + 
00233                                      Classname(G));
00234     
00235     if (m_Guest)
00236     {
00237       if (G == m_Guest)
00238         throw PGSTD::logic_error(Classname(G) +
00239                                  " '" +
00240                                  G->Name() +
00241                                  "' started more than once without closing");
00242 
00243       throw PGSTD::logic_error("Started " + 
00244                                Classname(G) +
00245                                " '" + 
00246                                G->Name() + 
00247                                "' while '" +
00248                                m_Guest->Name() +
00249                                "' was still active");
00250     }
00251     
00252     m_Guest = G;
00253   }
00254 
00255   void Unregister(const GUEST *G)
00256   {
00257     if (G != m_Guest)
00258     {
00259       if (!G) 
00260         throw PGSTD::logic_error("Closing NULL " + Classname(G));
00261       else if (!m_Guest)
00262         throw PGSTD::logic_error("Closing " + 
00263                                  Classname(G) +
00264                                  " '" +
00265                                  G->Name() +
00266                                  "' which wasn't open");
00267       else
00268         throw PGSTD::logic_error("Closing wrong " + 
00269                                  Classname(G) +
00270                                  "; expected '" +
00271                                  m_Guest->Name() +
00272                                  "' but got '" +
00273                                  G->Name() +
00274                                  "'");
00275     }
00276 
00277     m_Guest = 0;
00278   }
00279 
00280 private:
00281   const GUEST *m_Guest;
00282 
00283   // Not allowed:
00284   Unique(const Unique &);
00285   Unique &operator=(const Unique &);
00286 };
00287 
00288 }
00289 
00290 #endif
00291 

Generated on Sat Mar 15 20:47:39 2003 for libpqxx by doxygen1.3-rc3