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
00062 template<typename T> inline PGSTD::string ToString(const T &Obj)
00063 {
00064
00065 char Buf[500];
00066 sprintf(Buf, FmtString(Obj), Obj);
00067 return PGSTD::string(Buf);
00068 }
00069
00070 template<> inline PGSTD::string ToString(const PGSTD::string &Obj) {return Obj;}
00071 template<> inline PGSTD::string ToString(const char *const &Obj) { return Obj; }
00072 template<> inline PGSTD::string ToString(char *const &Obj) { return Obj; }
00073
00074 template<> inline PGSTD::string ToString(const bool &Obj)
00075 {
00076 return ToString(unsigned(Obj));
00077 }
00078
00079 template<> inline PGSTD::string ToString(const short &Obj)
00080 {
00081 return ToString(int(Obj));
00082 }
00083
00084 template<> inline PGSTD::string ToString(const unsigned short &Obj)
00085 {
00086 return ToString(unsigned(Obj));
00087 }
00088
00089
00091
00098 template<typename T> inline void FromString(const char Str[], T &Obj)
00099 {
00100 if (!Str) throw PGSTD::runtime_error("Attempt to convert NULL string to " +
00101 PGSTD::string(typeid(T).name()));
00102
00103 if (sscanf(Str, FmtString(Obj), &Obj) != 1)
00104 throw PGSTD::runtime_error("Cannot convert value '" +
00105 PGSTD::string(Str) +
00106 "' to " + typeid(T).name());
00107 }
00108
00109
00110 template<> inline void FromString(const char Str[], PGSTD::string &Obj)
00111 {
00112 if (!Str)
00113 throw PGSTD::runtime_error("Attempt to convert NULL C string to C++ "
00114 "string");
00115 Obj = Str;
00116 }
00117
00118
00119 template<> inline void FromString(const char Str[], const char *&Obj)
00120 {
00121 if (!Str)
00122 throw PGSTD::runtime_error("Attempt to read NULL string");
00123 Obj = Str;
00124 }
00125
00126 template<> inline void FromString(const char Str[], bool &Obj)
00127 {
00128 if (!Str)
00129 throw PGSTD::runtime_error("Attempt to read NULL string");
00130
00131 switch (Str[0])
00132 {
00133 case 0:
00134 case 'f':
00135 Obj = false;
00136 break;
00137 case '0':
00138 {
00139 int I;
00140 FromString(Str, I);
00141 Obj = (I != 0);
00142 }
00143 break;
00144 default:
00145 Obj = true;
00146 }
00147 }
00148
00149
00151
00154 template<typename T> inline PGSTD::string Quote(const T &Obj, bool EmptyIsNull);
00155
00157 template<> inline PGSTD::string Quote(const PGSTD::string &Obj,
00158 bool EmptyIsNull)
00159 {
00160 if (EmptyIsNull && Obj.empty()) return "null";
00161
00162 PGSTD::string Result;
00163 Result.reserve(Obj.size() + 2);
00164 Result += "'";
00165
00166 #ifdef HAVE_PQESCAPESTRING
00167
00168 char *const Buf = new char[2*Obj.size() + 1];
00169 try
00170 {
00171 PQescapeString(Buf, Obj.c_str(), Obj.size());
00172 Result += Buf;
00173 }
00174 catch (const PGSTD::exception &)
00175 {
00176 delete [] Buf;
00177 throw;
00178 }
00179 delete [] Buf;
00180
00181 #else
00182
00183 for (PGSTD::string::size_type i=0; i < Obj.size(); ++i)
00184 {
00185 if (isgraph(Obj[i]))
00186 {
00187 switch (Obj[i])
00188 {
00189 case '\'':
00190 case '\\':
00191 Result += '\\';
00192 }
00193 Result += Obj[i];
00194 }
00195 else
00196 {
00197 char s[10];
00198 sprintf(s,
00199 "\\%03o",
00200 static_cast<unsigned int>(static_cast<unsigned char>(Obj[i])));
00201 Result.append(s, 4);
00202 }
00203 }
00204
00205 #endif
00206
00207 return Result + '\'';
00208 }
00209
00210
00213 template<> inline PGSTD::string Quote(const char *const & Obj,
00214 bool EmptyIsNull)
00215 {
00216 if (!Obj) return "null";
00217 return Quote(PGSTD::string(Obj), EmptyIsNull);
00218 }
00219
00220
00222
00227 template<int LEN> inline PGSTD::string Quote(const char (&Obj)[LEN],
00228 bool EmptyIsNull)
00229 {
00230 return Quote(PGSTD::string(Obj), EmptyIsNull);
00231 }
00232
00233
00237 template<typename T> inline PGSTD::string Quote(const T &Obj, bool EmptyIsNull)
00238 {
00239 return Quote(ToString(Obj), EmptyIsNull);
00240 }
00241
00242
00244
00246 template<typename T> inline PGSTD::string Quote(T Obj)
00247 {
00248 return Quote(Obj, false);
00249 }
00250
00251
00252
00254 template<typename T> PGSTD::string Classname(const T *);
00255
00256
00258
00263 template<typename T> class PQXX_LIBEXPORT PQAlloc
00264 {
00265 T *m_Obj;
00266 public:
00267 PQAlloc() : m_Obj(0) {}
00268
00270 explicit PQAlloc(T *obj) : m_Obj(obj) {}
00271
00272 ~PQAlloc() { close(); }
00273
00275
00277 PQAlloc &operator=(T *obj) throw ()
00278 {
00279 if (obj != m_Obj)
00280 {
00281 close();
00282 m_Obj = obj;
00283 }
00284 return *this;
00285 }
00286
00288 operator bool() const throw () { return m_Obj != 0; }
00289
00291 bool operator!() const throw () { return !m_Obj; }
00292
00294
00296 T *operator->() const throw (PGSTD::logic_error)
00297 {
00298 if (!m_Obj) throw PGSTD::logic_error("Null pointer dereferenced");
00299 return m_Obj;
00300 }
00301
00303
00305 T &operator*() const throw (PGSTD::logic_error) { return *operator->(); }
00306
00308
00310 T *c_ptr() const throw () { return m_Obj; }
00311
00313 void close() throw () { if (m_Obj) freemem(); m_Obj = 0; }
00314
00315 private:
00316 void freemem() throw ()
00317 {
00318 #ifdef HAVE_PQFREEMEM
00319 PQfreemem(reinterpret_cast<unsigned char *>(m_Obj));
00320 #else
00321 free(m_Obj);
00322 #endif
00323 }
00324
00325 PQAlloc(const PQAlloc &);
00326 PQAlloc &operator=(const PQAlloc &);
00327 };
00328
00329
00330
00336 template<typename GUEST>
00337 class PQXX_LIBEXPORT Unique
00338 {
00339 public:
00340 Unique() : m_Guest(0) {}
00341
00342 GUEST *get() const throw () { return m_Guest; }
00343
00344 void Register(GUEST *G)
00345 {
00346 if (!G) throw PGSTD::logic_error("Internal libpqxx error: NULL " +
00347 Classname(G));
00348
00349 if (m_Guest)
00350 {
00351 if (G == m_Guest)
00352 throw PGSTD::logic_error(Classname(G) +
00353 " '" +
00354 G->Name() +
00355 "' started more than once without closing");
00356
00357 throw PGSTD::logic_error("Started " +
00358 Classname(G) +
00359 " '" +
00360 G->Name() +
00361 "' while '" +
00362 m_Guest->Name() +
00363 "' was still active");
00364 }
00365
00366 m_Guest = G;
00367 }
00368
00369 void Unregister(GUEST *G)
00370 {
00371 if (G != m_Guest)
00372 {
00373 if (!G)
00374 throw PGSTD::logic_error("Closing NULL " + Classname(G));
00375 else if (!m_Guest)
00376 throw PGSTD::logic_error("Closing " +
00377 Classname(G) +
00378 " '" +
00379 G->Name() +
00380 "' which wasn't open");
00381 else
00382 throw PGSTD::logic_error("Closing wrong " +
00383 Classname(G) +
00384 "; expected '" +
00385 m_Guest->Name() +
00386 "' but got '" +
00387 G->Name() +
00388 "'");
00389 }
00390
00391 m_Guest = 0;
00392 }
00393
00394 private:
00395 GUEST *m_Guest;
00396
00397
00398 Unique(const Unique &);
00399 Unique &operator=(const Unique &);
00400 };
00401
00402 }
00403
00404 #endif
00405