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++ string");
00095 Obj = Str;
00096 }
00097
00098
00099 template<> inline void FromString(const char Str[], const char *&Obj)
00100 {
00101 if (!Str)
00102 throw PGSTD::runtime_error("Attempt to read NULL string");
00103 Obj = Str;
00104 }
00105
00106 template<> inline void FromString(const char Str[], bool &Obj)
00107 {
00108 if (!Str)
00109 throw PGSTD::runtime_error("Attempt to read NULL string");
00110
00111 switch (Str[0])
00112 {
00113 case 0:
00114 case 'f':
00115 Obj = false;
00116 break;
00117 case '0':
00118 {
00119 int I;
00120 FromString(Str, I);
00121 Obj = (I != 0);
00122 }
00123 break;
00124 default:
00125 Obj = true;
00126 }
00127 }
00128
00129
00132 template<typename T> PGSTD::string Quote(const T &Obj, bool EmptyIsNull=false);
00133
00134
00136 template<> inline PGSTD::string Quote(const PGSTD::string &Obj,
00137 bool EmptyIsNull)
00138 {
00139 if (EmptyIsNull && Obj.empty())
00140 return "null";
00141
00142 PGSTD::string Result = "'" + Obj;
00143 const char Special[] = "'\\";
00144 for (PGSTD::string::size_type i = Result.find_last_of(Special);
00145 i > 0;
00146 i = Result.find_last_of(Special, i))
00147 Result.insert(i, 1, Result[i]);
00148
00149 return Result + "'";
00150 }
00151
00152
00155 template<> inline PGSTD::string Quote(const char *const & Obj,
00156 bool EmptyIsNull)
00157 {
00158 if (!Obj) return "null";
00159 return Quote(PGSTD::string(Obj), EmptyIsNull);
00160 }
00161
00162
00166 template<typename T> inline PGSTD::string Quote(const T &Obj, bool EmptyIsNull)
00167 {
00168 return Quote(ToString(Obj), EmptyIsNull);
00169 }
00170
00171
00172
00174 template<typename T> PGSTD::string Classname(const T *);
00175
00176
00182 template<typename GUEST>
00183 class Unique
00184 {
00185 public:
00186 Unique() : m_Guest(0) {}
00187
00188 const GUEST *get() const throw () { return m_Guest; }
00189
00190 void Register(const GUEST *G)
00191 {
00192 if (!G) throw PGSTD::logic_error("Internal libpqxx error: NULL " +
00193 Classname(G));
00194
00195 if (m_Guest)
00196 {
00197 if (G == m_Guest)
00198 throw PGSTD::logic_error(Classname(G) +
00199 " '" +
00200 G->Name() +
00201 "' started more than once without closing");
00202
00203 throw PGSTD::logic_error("Started " +
00204 Classname(G) +
00205 " '" +
00206 G->Name() +
00207 "' while '" +
00208 m_Guest->Name() +
00209 "' was still active");
00210 }
00211
00212 m_Guest = G;
00213 }
00214
00215 void Unregister(const GUEST *G)
00216 {
00217 if (G != m_Guest)
00218 {
00219 if (!G)
00220 throw PGSTD::logic_error("Closing NULL " + Classname(G));
00221 else if (!m_Guest)
00222 throw PGSTD::logic_error("Closing " +
00223 Classname(G) +
00224 " '" +
00225 G->Name() +
00226 "' which wasn't open");
00227 else
00228 throw PGSTD::logic_error("Closing wrong " +
00229 Classname(G) +
00230 "; expected '" +
00231 m_Guest->Name() +
00232 "' but got '" +
00233 G->Name() +
00234 "'");
00235 }
00236
00237 m_Guest = 0;
00238 }
00239
00240 private:
00241 const GUEST *m_Guest;
00242
00243
00244 Unique(const Unique &);
00245 Unique &operator=(const Unique &);
00246 };
00247
00248
00249 const Result_size_type Result_size_type_min =
00250 PGSTD::numeric_limits<Result_size_type>::min();
00251 const Result_size_type Result_size_type_max =
00252 PGSTD::numeric_limits<Result_size_type>::max();
00253
00254 }
00255
00256 #endif
00257