C++DB is the database layer that was designed to work with C++CMS. This customized version is used within Ye Ol' Pi Shack.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

185 lines
4.6 KiB

  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. namespace cppdb {
  27. std::string format_time(std::tm const &v)
  28. {
  29. char buf[64]= {0};
  30. strftime(buf,sizeof(buf),"%Y-%m-%d %H:%M:%S",&v);
  31. return std::string(buf);
  32. }
  33. std::tm parse_time(std::string const &v)
  34. {
  35. if(strlen(v.c_str())!=v.size())
  36. throw bad_value_cast();
  37. return parse_time(v.c_str());
  38. }
  39. std::tm parse_time(char const *v)
  40. {
  41. std::tm t=std::tm();
  42. int n;
  43. double sec = 0;
  44. n = sscanf(v,"%d-%d-%d %d:%d:%lf",
  45. &t.tm_year,&t.tm_mon,&t.tm_mday,
  46. &t.tm_hour,&t.tm_min,&sec);
  47. if(n!=3 && n!=6)
  48. {
  49. throw bad_value_cast();
  50. }
  51. t.tm_year-=1900;
  52. t.tm_mon-=1;
  53. t.tm_isdst = -1;
  54. t.tm_sec=static_cast<int>(sec);
  55. if(mktime(&t)==-1)
  56. throw bad_value_cast();
  57. return t;
  58. }
  59. namespace {
  60. bool is_blank_char(char c)
  61. {
  62. return c==' ' || c=='\t' || c=='\r' || c=='\n' || c=='\f';
  63. }
  64. std::string trim(std::string const &s)
  65. {
  66. if(s.empty())
  67. return s;
  68. size_t start=0,end=s.size()-1;
  69. while(start < s.size() && is_blank_char(s[start])) {
  70. start++;
  71. }
  72. while(end > start && is_blank_char(s[end])) {
  73. end--;
  74. }
  75. return s.substr(start,end-start+1);
  76. }
  77. }
  78. void parse_connection_string( std::string const &connection_string,
  79. std::string &driver,
  80. std::map<std::string,std::string> &params)
  81. {
  82. params.clear();
  83. size_t p = connection_string.find(':');
  84. if( p == std::string::npos )
  85. throw cppdb_error("cppdb::Invalid connection string - no driver given");
  86. driver = connection_string.substr(0,p);
  87. p++;
  88. while(p<connection_string.size()) {
  89. size_t n=connection_string.find('=',p);
  90. if(n==std::string::npos)
  91. throw cppdb_error("Invalid connection string - invalid property");
  92. std::string key = trim(connection_string.substr(p,n-p));
  93. p=n+1;
  94. std::string value;
  95. while(p<connection_string.size() && is_blank_char(connection_string[p]))
  96. {
  97. ++p;
  98. }
  99. if(p>=connection_string.size()) {
  100. /// Nothing - empty property
  101. }
  102. else if(connection_string[p]=='\'') {
  103. p++;
  104. while(true) {
  105. if(p>=connection_string.size()) {
  106. throw cppdb_error("Invalid connection string unterminated string");
  107. }
  108. if(connection_string[p]=='\'') {
  109. if(p+1 < connection_string.size() && connection_string[p+1]=='\'') {
  110. value+='\'';
  111. p+=2;
  112. }
  113. else {
  114. p++;
  115. break;
  116. }
  117. }
  118. else {
  119. value+=connection_string[p];
  120. p++;
  121. }
  122. }
  123. }
  124. else {
  125. size_t n=connection_string.find(';',p);
  126. if(n==std::string::npos) {
  127. value=trim(connection_string.substr(p));
  128. p=connection_string.size();
  129. }
  130. else {
  131. value=trim(connection_string.substr(p,n-p));
  132. p=n;
  133. }
  134. }
  135. if(params.find(key)!=params.end()) {
  136. throw cppdb_error("cppdb::invalid connection string duplicate key");
  137. }
  138. params[key]=value;
  139. while(p<connection_string.size()) {
  140. char c=connection_string[p];
  141. if(is_blank_char(c))
  142. ++p;
  143. else if(c==';') {
  144. ++p;
  145. break;
  146. }
  147. }
  148. }
  149. } //
  150. std::string connection_info::get(std::string const &prop,std::string const &default_value) const
  151. {
  152. properties_type::const_iterator p=properties.find(prop);
  153. if(p==properties.end())
  154. return default_value;
  155. else
  156. return p->second;
  157. }
  158. bool connection_info::has(std::string const &prop) const
  159. {
  160. return properties.find(prop) != properties.end();
  161. }
  162. int connection_info::get(std::string const &prop,int default_value) const
  163. {
  164. properties_type::const_iterator p=properties.find(prop);
  165. if(p==properties.end())
  166. return default_value;
  167. std::istringstream ss;
  168. ss.imbue(std::locale::classic());
  169. ss.str(p->second);
  170. int val;
  171. ss >> val;
  172. if(!ss || !ss.eof()) {
  173. throw cppdb_error("cppdb::connection_info property " + prop + " expected to be integer value");
  174. }
  175. return val;
  176. }
  177. }