00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #ifndef BK_LIB_STRING_CONVERT_H_INCLUDED
00019 #define BK_LIB_STRING_CONVERT_H_INCLUDED
00020 #include <cstring>
00021 #include <string>
00022 #include <vector>
00023 #include <utility>
00024 #include <stdexcept>
00025 #include <typeinfo>
00026 #include <istream>
00027 #if !defined(_MSC_VER)
00028 #include <strings.h>
00029 #else
00030 inline int strcasecmp(const char* lhs, const char* rhs) { return _stricmp(lhs, rhs); }
00031 inline int strncasecmp(const char* lhs, const char* rhs, size_t n) { return _strnicmp(lhs, rhs, n); }
00032 #endif
00033 namespace bk_lib { namespace detail {
00034
00035
00036
00037 template<class T, class Traits = std::char_traits<T> >
00038 class input_from_string : public std::basic_streambuf<T, Traits> {
00039 typedef std::basic_streambuf<T, Traits> base_type;
00040 typedef typename Traits::char_type* pointer_type;
00041 typedef const typename Traits::char_type* const_pointer_type;
00042 typedef typename base_type::pos_type pos_type;
00043 typedef typename base_type::off_type off_type;
00044 public:
00045 explicit input_from_string(const_pointer_type p, size_t size)
00046 : buffer_(const_cast<pointer_type>(p))
00047 , size_(size) {
00048 base_type::setp(0, 0);
00049 base_type::setg(buffer_, buffer_, buffer_+size_);
00050 }
00051 pos_type seekoff(off_type offset, std::ios_base::seekdir dir, std::ios_base::openmode which) {
00052 if(which & std::ios_base::out) {
00053
00054 return base_type::seekoff(offset, dir, which);
00055 }
00056 if(dir == std::ios_base::cur) {
00057 offset += static_cast<off_type>(base_type::gptr() - base_type::eback());
00058 }
00059 else if(dir == std::ios_base::end) {
00060 offset = static_cast<off_type>(size_) - offset;
00061 }
00062 return seekpos(offset, which);
00063 }
00064 pos_type seekpos(pos_type offset, std::ios_base::openmode which) {
00065 if((which & std::ios_base::out) == 0 && offset >= pos_type(0) && ((size_t)offset) <= size_) {
00066 base_type::setg(buffer_, buffer_+(size_t)offset, buffer_+size_);
00067 return offset;
00068 }
00069 return base_type::seekpos(offset, which);
00070 }
00071 private:
00072 input_from_string(const input_from_string&);
00073 input_from_string& operator=(const input_from_string&);
00074 protected:
00075 pointer_type buffer_;
00076 size_t size_;
00077 };
00078
00079 template<class T, class Traits = std::char_traits<T> >
00080 class input_stream : public std::basic_istream<T, Traits> {
00081 public:
00082 input_stream(const std::string& str)
00083 : std::basic_istream<T, Traits>(0)
00084 , buffer_(str.data(), str.size()) {
00085 std::basic_istream<T, Traits>::rdbuf(&buffer_);
00086 }
00087 input_stream(const char* x, size_t size)
00088 : std::basic_istream<T, Traits>(0)
00089 , buffer_(x, size) {
00090 std::basic_istream<T, Traits>::rdbuf(&buffer_);
00091 }
00092 private:
00093 input_from_string<T, Traits> buffer_;
00094 };
00095 struct no_stream_support { template <class T> no_stream_support(const T&) {} };
00096 no_stream_support& operator >> (std::istream&, const no_stream_support&);
00097 }
00099
00101 template <class T>
00102 int xconvert(const char* x, T& out, const char** errPos = 0, double = 0);
00103 int xconvert(const char* x, bool& out, const char** errPos = 0, int = 0);
00104 int xconvert(const char* x, char& out, const char** errPos = 0, int = 0);
00105 int xconvert(const char* x, unsigned& out, const char** errPos = 0, int = 0);
00106 int xconvert(const char* x, int& out, const char** errPos = 0, int = 0);
00107 int xconvert(const char* x, long& out, const char** errPos = 0, int = 0);
00108 int xconvert(const char* x, unsigned long& out, const char** errPos = 0, int = 0);
00109 int xconvert(const char* x, double& out, const char** errPos = 0, int = 0);
00110 int xconvert(const char* x, const char*& out, const char** errPos = 0, int = 0);
00111 int xconvert(const char* x, std::string& out, const char** errPos = 0, int sep = 0);
00113
00115 const int def_sep = int(',');
00116
00117 template <class T, class U>
00118 int xconvert(const char* x, std::pair<T, U>& out, const char** errPos = 0, int sep = def_sep) {
00119 if (!x) { return 0; }
00120 if (sep == 0) { sep = def_sep; }
00121 std::pair<T, U> temp(out);
00122 const char* n = x;
00123 int ps = 0;
00124 if (*n == '(') { ++ps; ++n; }
00125 int tokT = xconvert(n, temp.first, &n, sep);
00126 int tokU = tokT && *n == (char)sep ? xconvert(n+1, temp.second, &n, sep) : 0;
00127 int sum = 0;
00128 if (!ps || *n == ')') {
00129 n += ps;
00130 if (tokU) { out.second= temp.second; ++sum; }
00131 if (tokU || !*n) { out.first = temp.first; ++sum; }
00132 }
00133 if (!sum) { n = x; }
00134 if (errPos) *errPos = n;
00135 return sum;
00136 }
00137
00138
00139 template <class T>
00140 int xconvert(const char* x, std::vector<T>& out, const char** errPos = 0, int sep = def_sep) {
00141 if (sep == 0) { sep = def_sep; }
00142 if (!x) { return 0; }
00143 const char* n = x;
00144 int sum = 0;
00145 int ps = 0;
00146 if (*n == '[') { ++ps; ++n; }
00147 for (;;) {
00148 T temp;
00149 int tok = xconvert(n, temp, &n, sep);
00150 if (!tok) break;
00151 ++sum;
00152 out.push_back(temp);
00153 if (!*n || *n != (char)sep) break;
00154 n = n+1;
00155 }
00156 if (!ps || *n == ']') { n += ps; }
00157 else { while (sum) { out.pop_back(); --sum; } n = x; }
00158 if (errPos) *errPos = n;
00159 return sum;
00160 }
00161
00162
00163 template <class T>
00164 int xconvert(const char* x, T* out, const char** errPos, int maxTok) {
00165 const char* n = x;
00166 int sumTok = 0;
00167 while (maxTok) {
00168 T temp;
00169 int tok = xconvert(x, temp, &n, def_sep);
00170 if (!tok) break;
00171 ++sumTok; --maxTok;
00172 *out++ = temp;
00173 if (!*n || *n != (char)def_sep) break;
00174 x = n+1;
00175 }
00176 if (errPos) *errPos = n;
00177 return sumTok;
00178 }
00180
00182 template <class T>
00183 int xconvert(const char* x, T& out, const char** errPos, double) {
00184 std::size_t xLen = std::strlen(x);
00185 const char* err = x;
00186 detail::input_stream<char> str(x, xLen);
00187 if (str >> out) {
00188 if (str.eof()){ err += xLen; }
00189 else { err += static_cast<std::size_t>(str.tellg()); }
00190 }
00191 if (errPos) { *errPos = err; }
00192 return int(err != x);
00193 }
00195
00197 class bad_string_cast : public std::bad_cast {
00198 public:
00199 ~bad_string_cast() throw();
00200 virtual const char* what() const throw();
00201 };
00202 template <class T>
00203 bool string_cast(const char* arg, T& to) {
00204 const char* end;
00205 return xconvert(arg, to, &end, 0) != 0 && !*end;
00206 }
00207 template <class T>
00208 T string_cast(const char* s) {
00209 T to;
00210 if (string_cast<T>(s, to)) { return to; }
00211 throw bad_string_cast();
00212 }
00213 template <class T>
00214 T string_cast(const std::string& s) { return string_cast<T>(s.c_str()); }
00215 template <class T>
00216 bool string_cast(const std::string& from, T& to) { return string_cast<T>(from.c_str(), to); }
00217 }
00218
00219 #endif
00220