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