00001 #include <set>
00002 #include "types.h"
00003
00004
00005 #include <stdio.h>
00006
00007 namespace storage
00008 {
00009
00010 const TYPES TypeTraits<bool>::id = T_BOOL;
00011 #ifndef _MSC_VER
00012 const TYPES TypeTraits<wchar_t>::id = T_WCHART;
00013 #endif
00014 const TYPES TypeTraits<char>::id = T_CHAR;
00015 const TYPES TypeTraits<signed char>::id = T_SIGNED_CHAR;
00016 const TYPES TypeTraits<unsigned char>::id = T_UNSIGNED_CHAR;
00017 const TYPES TypeTraits<short>::id = T_SHORT;
00018 const TYPES TypeTraits<unsigned short>::id = T_UNSIGNED_SHORT;
00019 const TYPES TypeTraits<int>::id = T_INT;
00020 const TYPES TypeTraits<unsigned int>::id = T_UNSIGNED_INT;
00021 const TYPES TypeTraits<long>::id = T_LONG;
00022 const TYPES TypeTraits<unsigned long>::id = T_UNSIGNED_LONG;
00023 const TYPES TypeTraits<long long>::id = T_LONG_LONG;
00024 const TYPES TypeTraits<unsigned long long>::id = T_UNSIGNED_LONG_LONG;
00025 const TYPES TypeTraits<float>::id = T_FLOAT;
00026 const TYPES TypeTraits<double>::id = T_DOUBLE;
00027 const TYPES TypeTraits<long double>::id = T_LONG_DOUBLE;
00028 const TYPES TypeTraits<std::string>::id = T_STRING;
00029 const TYPES TypeTraits<QString>::id = T_STRING;
00030
00031 const QString TypeTraits<bool>::name = "bool";
00032 #ifndef _MSC_VER
00033 const QString TypeTraits<wchar_t>::name = "wchar_t";
00034 #endif
00035 const QString TypeTraits<char>::name = "char";
00036 const QString TypeTraits<signed char>::name = "signed_char";
00037 const QString TypeTraits<unsigned char>::name = "unsigned_char";
00038 const QString TypeTraits<short>::name = "short";
00039 const QString TypeTraits<unsigned short>::name = "unsigned_short";
00040 const QString TypeTraits<int>::name = "int";
00041 const QString TypeTraits<unsigned int>::name = "unsigned_int";
00042 const QString TypeTraits<long>::name = "long";
00043 const QString TypeTraits<unsigned long>::name = "unsigned_long";
00044 const QString TypeTraits<long long>::name = "long_long";
00045 const QString TypeTraits<unsigned long long>::name = "long_long";
00046 const QString TypeTraits<float>::name = "float";
00047 const QString TypeTraits<double>::name = "double";
00048 const QString TypeTraits<long double>::name = "long_double";
00049 const QString TypeTraits<std::string>::name = "string";
00050 const QString TypeTraits<QString>::name = "string";
00051
00052 const NUMBER_CLASS TypeTraits<bool>::type = NOT_A_NUMBER;
00053 #ifndef _MSC_VER
00054 const NUMBER_CLASS TypeTraits<wchar_t>::type = CHAR;
00055 #endif
00056 const NUMBER_CLASS TypeTraits<char>::type = CHAR;
00057 const NUMBER_CLASS TypeTraits<signed char>::type = SIGNED_INTEGER;
00058 const NUMBER_CLASS TypeTraits<unsigned char>::type = UNSIGNED_INTEGER;
00059 const NUMBER_CLASS TypeTraits<short>::type = SIGNED_INTEGER;
00060 const NUMBER_CLASS TypeTraits<unsigned short>::type = UNSIGNED_INTEGER;
00061 const NUMBER_CLASS TypeTraits<int>::type = SIGNED_INTEGER;
00062 const NUMBER_CLASS TypeTraits<unsigned int>::type = UNSIGNED_INTEGER;
00063 const NUMBER_CLASS TypeTraits<long>::type = SIGNED_INTEGER;
00064 const NUMBER_CLASS TypeTraits<unsigned long>::type = UNSIGNED_INTEGER;
00065 const NUMBER_CLASS TypeTraits<long long>::type = SIGNED_INTEGER;
00066 const NUMBER_CLASS TypeTraits<unsigned long long>::type = UNSIGNED_INTEGER;
00067 const NUMBER_CLASS TypeTraits<float>::type = FLOATING_POINT;
00068 const NUMBER_CLASS TypeTraits<double>::type = FLOATING_POINT;
00069 const NUMBER_CLASS TypeTraits<long double>::type = FLOATING_POINT;
00070 const NUMBER_CLASS TypeTraits<QString>::type = NOT_A_NUMBER;
00071 const NUMBER_CLASS TypeTraits<std::string>::type = NOT_A_NUMBER;
00072
00073
00074
00075 #define SBO sizeof(bool)
00076 #define SWC sizeof(wchar_t)
00077 #define SCH sizeof(char)
00078 #define SSC sizeof(signed char)
00079 #define SUC sizeof(unsigned char)
00080 #define SSH sizeof(short)
00081 #define SUS sizeof(unsigned short)
00082 #define SIN sizeof(int)
00083 #define SUI sizeof(unsigned int)
00084 #define SLO sizeof(long)
00085 #define SUL sizeof(unsigned long)
00086 #define SLL sizeof(long long)
00087 #define ULL sizeof(unsigned long long)
00088 #define SFL sizeof(float)
00089 #define SDB sizeof(double)
00090 #define SLD sizeof(long double)
00091
00092 static bool conversion_matrix[NB_STORAGE_TYPES][NB_STORAGE_TYPES] = {
00093
00094 { true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true },
00095 { false, true, false, false, false, SWC<=SSH, SWC<=SUS, SWC<=SIN, SWC<=SUI, SWC<=SLO, SWC<=SUL, SWC<=SLL, SWC<=ULL, false, false, false, true },
00096 { false, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true },
00097 { false, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true },
00098 { false, true, true, false, true, true, true, true, true, true, true, true, true, true, true, true, true },
00099 { false, SSH<=SWC, false, false, false, true, true, true, true, true, true, true, true, SSH<SFL, SSH<SDB, SSH<SLD, true },
00100 { false, SUS<=SWC, false, false, false, false, true, SUS<SIN, true, SUS<SLO, true, SUS<SLL, true, SUS<SFL, SUS<SDB, SUS<SLD, true },
00101 { false, SIN<=SWC, false, false, false, false, false, true, true, true, true, true, true, SIN<SFL, SIN<SDB, SIN<SLD, true },
00102 { false, SUI<=SWC, false, false, false, false, false, false, true, SUS<SLO, true, SUS<SLL, true, SUI<SFL, SUI<SDB, SUI<SLD, true },
00103 { false, SLO<=SWC, false, false, false, false, false, false, false, true, true, true, true, SLO<SFL, SLO<SDB, SLO<SLD, true },
00104 { false, SUL<=SWC, false, false, false, false, false, false, false, false, true, SUL<SLL, true, SUL<SFL, SUL<SDB, SUL<SLD, true },
00105 { false, SLL<=SWC, false, false, false, false, false, false, false, false, false, true, true, SLL<SFL, SLL<SDB, SLL<SLD, true },
00106 { false, ULL<=SWC, false, false, false, false, false, false, false, false, false, false, true, ULL<SFL, ULL<SDB, ULL<SLD, true },
00107 { false, false, false, false, false, false, false, false, false, false, false, false, false, true, true, true, true },
00108 { false, false, false, false, false, false, false, false, false, false, false, false, false, false, true, true, true },
00109 { false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, true, true },
00110 { true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true }
00111 };
00112
00113 bool isStrictConversion(TYPES from, TYPES to)
00114 {
00115 return conversion_matrix[from][to];
00116 }
00117
00118 static QString* make_types()
00119 {
00120 static QString result[NB_STORAGE_TYPES];
00121 #define CREATE_TYPE_ENTRY(id, type) result[id] = TypeTraits<type>::name;
00122 FOR_ALL_TYPEIDS(CREATE_TYPE_ENTRY)
00123 #undef CREATE_TYPE_ENTRY
00124 return result;
00125 };
00126
00127
00128 static QString const* const type_names = make_types();
00129
00130 TYPES typename_to_id(const QString& name)
00131 {
00132 for(int i = T_BOOL ; i <= T_STRING ; ++i)
00133 {
00134 if(type_names[i] == name)
00135 return (TYPES)i;
00136 }
00137 return T_INVALID;
00138 }
00139
00140 const QString& typeid_to_name(TYPES id)
00141 {
00142 if(id == T_INVALID)
00143 return TypeTraits<void>::name;
00144 return type_names[id];
00145 }
00146
00147 static std::set<QString> set_true_values()
00148 {
00149 std::set<QString> s;
00150 s.insert("true");
00151 s.insert("1");
00152 s.insert("yes");
00153 s.insert("y");
00154 s.insert("t");
00155 return s;
00156 }
00157
00158 static std::set<QString> set_false_values()
00159 {
00160 std::set<QString> s;
00161 s.insert("false");
00162 s.insert("0");
00163 s.insert("no");
00164 s.insert("n");
00165 s.insert("f");
00166 return s;
00167 }
00168
00169 static std::set<QString> true_values = set_true_values();
00170 static std::set<QString> false_values = set_false_values();
00171
00172 bool ConvertType<bool,QString>::operator()(const bool& c, QString &str) const
00173 {
00174 if(c)
00175 str = "True";
00176 else
00177 str = "False";
00178 return true;
00179 }
00180
00181 #ifndef _MSC_VER
00182 bool ConvertType<wchar_t,QString>::operator()(const wchar_t& c, QString &str) const
00183 {
00184 str = QString::fromWCharArray(&c, 1);
00185 return true;
00186 }
00187 #endif
00188
00189 bool ConvertType<char,QString>::operator()(const char& c, QString &str) const
00190 {
00191 str = QString(1, c);
00192 return true;
00193 }
00194
00195 bool ConvertType<signed char,QString>::operator()(const signed char& c, QString &str) const
00196 {
00197 str = QString(1, c);
00198 return true;
00199 }
00200
00201 bool ConvertType<unsigned char,QString>::operator()(const unsigned char& c, QString &str) const
00202 {
00203 str = QString(1, c);
00204 return true;
00205 }
00206
00207 bool ConvertType<short,QString>::operator()(const short& c, QString &str) const
00208 {
00209 str = QString::number(c);
00210 return true;
00211 }
00212
00213 bool ConvertType<unsigned short,QString>::operator()(const unsigned short& c, QString &str) const
00214 {
00215 str = QString::number(c);
00216 return true;
00217 }
00218
00219 bool ConvertType<int,QString>::operator()(const int& c, QString &str) const
00220 {
00221 str = QString::number(c);
00222 return true;
00223 }
00224
00225 bool ConvertType<unsigned int,QString>::operator()(const unsigned int& c, QString &str) const
00226 {
00227 str = QString::number(c);
00228 return true;
00229 }
00230
00231 bool ConvertType<long,QString>::operator()(const long& c, QString &str) const
00232 {
00233 str = QString::number(c);
00234 return true;
00235 }
00236
00237 bool ConvertType<unsigned long,QString>::operator()(const unsigned long& c, QString &str) const
00238 {
00239 str = QString::number(c);
00240 return true;
00241 }
00242
00243 bool ConvertType<long long,QString>::operator()(const long long& c, QString &str) const
00244 {
00245 str = QString::number(c);
00246 return true;
00247 }
00248
00249 bool ConvertType<unsigned long long,QString>::operator()(const unsigned long long& c, QString &str) const
00250 {
00251 str = QString::number(c);
00252 return true;
00253 }
00254 bool ConvertType<float,QString>::operator()(const float& c, QString &str) const
00255 {
00256 str = QString::number(c, 'g', 20).trimmed();
00257 return true;
00258 }
00259
00260 bool ConvertType<double,QString>::operator()(const double& c, QString &str) const
00261 {
00262 str = QString::number(c, 'g', 20).trimmed();
00263 return true;
00264 }
00265
00266 bool ConvertType<long double,QString>::operator()(const long double& c, QString &str) const
00267 {
00268 static char buf[100];
00269 ::snprintf(buf, 100, "%-20.20Lg", c);
00270 str = QString::fromAscii(buf).trimmed();
00271 return true;
00272 }
00273
00274 bool ConvertType<std::string,QString>::operator()(const std::string& c, QString &str) const
00275 {
00276 str = QString::fromStdString(c);
00277 return true;
00278 }
00279
00280 bool ConvertType<QString,bool>::operator()(const QString& str, bool& c) const
00281 {
00282 QString lstr = str.toLower();
00283 if(true_values.find(lstr) != true_values.end())
00284 {
00285 c = true;
00286 return true;
00287 }
00288 else if(false_values.find(lstr) != false_values.end())
00289 {
00290 c = false;
00291 return true;
00292 }
00293 return false;
00294 }
00295
00296 #ifndef _MSC_VER
00297 bool ConvertType<QString,wchar_t>::operator()(const QString& str, wchar_t& c) const
00298 {
00299 if(str.isEmpty())
00300 return false;
00301 c = str.toStdWString()[0];
00302 return true;
00303 }
00304 #endif
00305
00306 bool ConvertType<QString,char>::operator()(const QString& str, char& c) const
00307 {
00308 if(str.isEmpty())
00309 return false;
00310 c = str.toStdString()[0];
00311 return true;
00312 }
00313
00314 bool ConvertType<QString,signed char>::operator()(const QString& str, signed char& c) const
00315 {
00316 if(str.isEmpty())
00317 return false;
00318 c = str.toStdString()[0];
00319 return true;
00320 }
00321
00322 bool ConvertType<QString,unsigned char>::operator()(const QString& str, unsigned char& c) const
00323 {
00324 if(str.isEmpty())
00325 return false;
00326 c = str.toStdString()[0];
00327 return true;
00328 }
00329
00330 bool ConvertType<QString,short>::operator()(const QString& str, short& c) const
00331 {
00332 bool ok;
00333 c = str.toShort(&ok);
00334 return ok;
00335 }
00336
00337 bool ConvertType<QString,unsigned short>::operator()(const QString& str, unsigned short& c) const
00338 {
00339 bool ok;
00340 c = str.toUShort(&ok);
00341 return ok;
00342 }
00343
00344 bool ConvertType<QString,int>::operator()(const QString& str, int& c) const
00345 {
00346 bool ok;
00347 c = str.toInt(&ok);
00348 return ok;
00349 }
00350
00351 bool ConvertType<QString,unsigned int>::operator()(const QString& str, unsigned int& c) const
00352 {
00353 bool ok;
00354 c = str.toUInt(&ok);
00355 return ok;
00356 }
00357
00358 bool ConvertType<QString,long>::operator()(const QString& str, long& c) const
00359 {
00360 bool ok;
00361 c = str.toLong(&ok);
00362 return ok;
00363 }
00364
00365 bool ConvertType<QString,unsigned long>::operator()(const QString& str, unsigned long& c) const
00366 {
00367 bool ok;
00368 c = str.toULong(&ok);
00369 return ok;
00370 }
00371
00372 bool ConvertType<QString,long long>::operator()(const QString& str, long long& c) const
00373 {
00374 bool ok;
00375 c = str.toLongLong(&ok);
00376 return ok;
00377 }
00378
00379 bool ConvertType<QString,unsigned long long>::operator()(const QString& str, unsigned long long& c) const
00380 {
00381 bool ok;
00382 c = str.toULongLong(&ok);
00383 return ok;
00384 }
00385
00386 bool ConvertType<QString,float>::operator()(const QString& str, float& c) const
00387 {
00388 bool ok;
00389 c = str.toFloat(&ok);
00390 return ok;
00391 }
00392
00393 bool ConvertType<QString,double>::operator()(const QString& str, double& c) const
00394 {
00395 bool ok;
00396 c = str.toDouble(&ok);
00397 return ok;
00398 }
00399
00400 bool ConvertType<QString,long double>::operator()(const QString& str, long double& c) const
00401 {
00402 QByteArray content = str.toAscii();
00403 const char* data = content.data();
00404 int nb_success = ::sscanf(data, "%Lg", &c);
00405 return nb_success == 1;
00406 }
00407
00408 bool ConvertType<QString,std::string>::operator()(const QString& str, std::string& c) const
00409 {
00410 c = str.toStdString();
00411 return true;
00412 }
00413
00414 #define CONVERT_TO_STDSTRING(type) \
00415 bool ConvertType<type,std::string>::operator()(const type& c, std::string& str) const \
00416 { \
00417 QString sstr; \
00418 bool result = convert_type(c, sstr); \
00419 if(result) \
00420 { \
00421 str = sstr.toStdString(); \
00422 return true; \
00423 } \
00424 return false; \
00425 }
00426 #define CONVERT_FROM_STDSTRING(type) \
00427 bool ConvertType<std::string,type>::operator()(const std::string& str, type& c) const \
00428 { \
00429 QString sstr = QString::fromStdString(str); \
00430 return convert_type(sstr, c); \
00431 }
00432
00433 FOR_ALL_TYPES_NOSTRING(CONVERT_TO_STDSTRING);
00434 FOR_ALL_TYPES_NOSTRING(CONVERT_FROM_STDSTRING);
00435
00436 #undef CONVERT_TO_STDSTRING
00437 #undef CONVERT_FROM_STDSTRING
00438
00439 static TYPES type_by_capacity[4][6] =
00440 { { T_INVALID, T_INVALID, T_INVALID, T_INVALID, T_INVALID, T_INVALID },
00441 { T_INVALID, T_INVALID, T_INVALID, T_INVALID, T_INVALID, T_INVALID },
00442 { T_INVALID, T_INVALID, T_INVALID, T_INVALID, T_INVALID, T_INVALID },
00443 { T_INVALID, T_INVALID, T_INVALID, T_INVALID, T_INVALID, T_INVALID }
00444 };
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454 static bool find_integer_types()
00455 {
00456 #define FIT_TYPE(cat, typ, enu) \
00457 if(sizeof(typ) == 1) type_by_capacity[cat][0] = enu;\
00458 else if(sizeof(typ) == 2) type_by_capacity[cat][1] = enu;\
00459 else if(sizeof(typ) == 4) type_by_capacity[cat][2] = enu;\
00460 else if(sizeof(typ) == 8) type_by_capacity[cat][3] = enu;\
00461 else if(sizeof(typ) == 12) type_by_capacity[cat][4] = enu;\
00462 else if(sizeof(typ) == 16) type_by_capacity[cat][5] = enu
00463 FIT_TYPE(FLOATING_POINT, long double, T_LONG_DOUBLE);
00464 FIT_TYPE(FLOATING_POINT, double, T_DOUBLE);
00465 FIT_TYPE(FLOATING_POINT, float, T_FLOAT);
00466 FIT_TYPE(UNSIGNED_INTEGER, unsigned long long, T_UNSIGNED_LONG_LONG);
00467 FIT_TYPE(UNSIGNED_INTEGER, unsigned long, T_UNSIGNED_LONG);
00468 FIT_TYPE(UNSIGNED_INTEGER, unsigned int, T_UNSIGNED_INT);
00469 FIT_TYPE(UNSIGNED_INTEGER, unsigned short, T_UNSIGNED_SHORT);
00470 FIT_TYPE(UNSIGNED_INTEGER, unsigned char, T_UNSIGNED_CHAR);
00471 FIT_TYPE(SIGNED_INTEGER, long long, T_LONG_LONG);
00472 FIT_TYPE(SIGNED_INTEGER, long, T_LONG);
00473 FIT_TYPE(SIGNED_INTEGER, int, T_INT);
00474 FIT_TYPE(SIGNED_INTEGER, short, T_SHORT);
00475 FIT_TYPE(SIGNED_INTEGER, signed char, T_SIGNED_CHAR);
00476 FIT_TYPE(CHAR, wchar_t, T_WCHART);
00477 FIT_TYPE(CHAR, char, T_CHAR);
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488 return true;
00489 }
00490
00491 static bool check_types = find_integer_types();
00492
00493 TYPES find_type(NUMBER_CLASS klass, size_t bytes)
00494 {
00495 int nb_cap;
00496 if(klass == NOT_A_NUMBER)
00497 return T_INVALID;
00498 if(bytes == 1)
00499 nb_cap = 0;
00500 else if(bytes == 2)
00501 nb_cap = 1;
00502 else if(bytes == 4)
00503 nb_cap = 2;
00504 else if(bytes == 8)
00505 nb_cap = 3;
00506 else if(bytes == 12)
00507 nb_cap = 4;
00508 else if(bytes == 16)
00509 nb_cap = 5;
00510 else
00511 return T_INVALID;
00512 return type_by_capacity[klass][nb_cap];
00513 }
00514
00515 }