00001
00002
00003
00004
00005
00006
00007
00008
00009
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
00039
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
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)
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 &);
00311 PQAlloc &operator=(const PQAlloc &);
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
00383 Unique(const Unique &);
00384 Unique &operator=(const Unique &);
00385 };
00386
00387 }
00388
00389 #endif
00390