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 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
00284 Unique(const Unique &);
00285 Unique &operator=(const Unique &);
00286 };
00287
00288 }
00289
00290 #endif
00291