1 /////////////////////////////////////////////////////////////////////////////// 2 // 3 // Copyright (C) 2010-2011 Artyom Beilis (Tonkikh) <artyomtnk@yahoo.com> 4 // 5 // Distributed under: 6 // 7 // the Boost Software License, Version 1.0. 8 // (See accompanying file LICENSE_1_0.txt or copy at 9 // http://www.boost.org/LICENSE_1_0.txt) 10 // 11 // or (at your opinion) under: 12 // 13 // The MIT License 14 // (See accompanying file MIT.txt or a copy at 15 // http://www.opensource.org/licenses/mit-license.php) 16 // 17 /////////////////////////////////////////////////////////////////////////////// 18 #define CPPDB_SOURCE 19 #include <cppdb/utils.h> 20 #include <cppdb/errors.h> 21 #include <time.h> 22 #include <stdio.h> 23 #include <string.h> 24 #include <sstream> 25 #include <locale> 26 27 namespace cppdb { format_time(std::tm const & v)28 std::string format_time(std::tm const &v) 29 { 30 char buf[64]= {0}; 31 strftime(buf,sizeof(buf),"%Y-%m-%d %H:%M:%S",&v); 32 return std::string(buf); 33 } 34 parse_time(std::string const & v)35 std::tm parse_time(std::string const &v) 36 { 37 if(strlen(v.c_str())!=v.size()) 38 throw bad_value_cast(); 39 return parse_time(v.c_str()); 40 } parse_time(char const * v)41 std::tm parse_time(char const *v) 42 { 43 std::tm t=std::tm(); 44 int n; 45 double sec = 0; 46 n = sscanf(v,"%d-%d-%d %d:%d:%lf", 47 &t.tm_year,&t.tm_mon,&t.tm_mday, 48 &t.tm_hour,&t.tm_min,&sec); 49 if(n!=3 && n!=6) 50 { 51 throw bad_value_cast(); 52 } 53 t.tm_year-=1900; 54 t.tm_mon-=1; 55 t.tm_isdst = -1; 56 t.tm_sec=static_cast<int>(sec); 57 if(mktime(&t)==-1) 58 throw bad_value_cast(); 59 return t; 60 } 61 62 namespace { is_blank_char(char c)63 bool is_blank_char(char c) 64 { 65 return c==' ' || c=='\t' || c=='\r' || c=='\n' || c=='\f'; 66 } trim(std::string const & s)67 std::string trim(std::string const &s) 68 { 69 if(s.empty()) 70 return s; 71 size_t start=0,end=s.size()-1; 72 while(start < s.size() && is_blank_char(s[start])) { 73 start++; 74 } 75 while(end > start && is_blank_char(s[end])) { 76 end--; 77 } 78 return s.substr(start,end-start+1); 79 } 80 } 81 parse_connection_string(std::string const & connection_string,std::string & driver,std::map<std::string,std::string> & params)82 void parse_connection_string( std::string const &connection_string, 83 std::string &driver, 84 std::map<std::string,std::string> ¶ms) 85 { 86 params.clear(); 87 size_t p = connection_string.find(':'); 88 if( p == std::string::npos ) 89 throw cppdb_error("cppdb::Invalid connection string - no driver given"); 90 driver = connection_string.substr(0,p); 91 p++; 92 while(p<connection_string.size()) { 93 size_t n=connection_string.find('=',p); 94 if(n==std::string::npos) 95 throw cppdb_error("Invalid connection string - invalid property"); 96 std::string key = trim(connection_string.substr(p,n-p)); 97 p=n+1; 98 std::string value; 99 while(p<connection_string.size() && is_blank_char(connection_string[p])) 100 { 101 ++p; 102 } 103 if(p>=connection_string.size()) { 104 /// Nothing - empty property 105 } 106 else if(connection_string[p]=='\'') { 107 p++; 108 while(true) { 109 if(p>=connection_string.size()) { 110 throw cppdb_error("Invalid connection string unterminated string"); 111 } 112 if(connection_string[p]=='\'') { 113 if(p+1 < connection_string.size() && connection_string[p+1]=='\'') { 114 value+='\''; 115 p+=2; 116 } 117 else { 118 p++; 119 break; 120 } 121 } 122 else { 123 value+=connection_string[p]; 124 p++; 125 } 126 } 127 } 128 else { 129 size_t n=connection_string.find(';',p); 130 if(n==std::string::npos) { 131 value=trim(connection_string.substr(p)); 132 p=connection_string.size(); 133 } 134 else { 135 value=trim(connection_string.substr(p,n-p)); 136 p=n; 137 } 138 } 139 if(params.find(key)!=params.end()) { 140 throw cppdb_error("cppdb::invalid connection string duplicate key"); 141 } 142 params[key]=value; 143 while(p<connection_string.size()) { 144 char c=connection_string[p]; 145 if(is_blank_char(c)) 146 ++p; 147 else if(c==';') { 148 ++p; 149 break; 150 } 151 } 152 } 153 } // get(std::string const & prop,std::string const & default_value) const154 std::string connection_info::get(std::string const &prop,std::string const &default_value) const 155 { 156 properties_type::const_iterator p=properties.find(prop); 157 if(p==properties.end()) 158 return default_value; 159 else 160 return p->second; 161 } 162 has(std::string const & prop) const163 bool connection_info::has(std::string const &prop) const 164 { 165 return properties.find(prop) != properties.end(); 166 } 167 get(std::string const & prop,int default_value) const168 int connection_info::get(std::string const &prop,int default_value) const 169 { 170 properties_type::const_iterator p=properties.find(prop); 171 if(p==properties.end()) 172 return default_value; 173 std::istringstream ss; 174 ss.imbue(std::locale::classic()); 175 ss.str(p->second); 176 int val; 177 ss >> val; 178 if(!ss || !ss.eof()) { 179 throw cppdb_error("cppdb::connection_info property " + prop + " expected to be integer value"); 180 } 181 return val; 182 } 183 184 } 185