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