00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include <program_opts/string_convert.h>
00019 #include <cstdlib>
00020 #include <climits>
00021 #include <cerrno>
00022 #if defined(_MSC_VER)
00023 #define snprintf _snprintf_s
00024 #endif
00025 namespace bk_lib {
00026
00027 static int detectBase(const char* x) {
00028 if (x[0] == '0') {
00029 if (x[1] == 'x' || x[1] == 'X') return 16;
00030 if (x[1] >= '0' && x[1] <= '7') return 8;
00031 }
00032 return 10;
00033 }
00034
00035 static bool empty(const char* x, const char** errPos) {
00036 if (x && *x) return false;
00037 if (errPos) { *errPos = x; }
00038 return true;
00039 }
00040
00041 static int parsed(int tok, const char* end, const char** errPos) {
00042 if (errPos) *errPos = end;
00043 return tok;
00044 }
00045
00046 int xconvert(const char* x, bool& out, const char** errPos, int) {
00047 if (empty(x, errPos)) { return 0; }
00048 else if (*x == '1') { out = true; x += 1; }
00049 else if (*x == '0') { out = false; x += 1; }
00050 else if (std::strncmp(x, "no", 2) == 0) { out = false; x += 2; }
00051 else if (std::strncmp(x, "on", 2) == 0) { out = true; x += 2; }
00052 else if (std::strncmp(x, "yes", 3) == 0) { out = true; x += 3; }
00053 else if (std::strncmp(x, "off", 3) == 0) { out = false; x += 3; }
00054 else if (std::strncmp(x, "true", 4) == 0) { out = true; x += 4; }
00055 else if (std::strncmp(x, "false", 5) == 0){ out = false; x += 5; }
00056 return parsed(1, x, errPos);
00057 }
00058 int xconvert(const char* x, char& out, const char** errPos, int) {
00059 if (empty(x, errPos)) { return 0; }
00060 if ((out = *x++) == '\\') {
00061 switch(*x) {
00062 case 't': out = '\t'; ++x; break;
00063 case 'n': out = '\n'; ++x; break;
00064 case 'v': out = '\v'; ++x; break;
00065 default: break;
00066 }
00067 }
00068 return parsed(1, x, errPos);
00069 }
00070
00071 int xconvert(const char* x, long& out, const char** errPos, int) {
00072 if (empty(x, errPos)) { return 0; }
00073 char* err;
00074 out = std::strtol(x, &err, detectBase(x));
00075 if ((out == LONG_MAX || out == LONG_MIN) && errno == ERANGE) { err = (char*)x; }
00076 return parsed(err != x, err, errPos);
00077 }
00078
00079 int xconvert(const char* x, unsigned long& out, const char** errPos, int) {
00080 if (empty(x, errPos)) { return 0; }
00081 char* err;
00082 if (std::strncmp(x, "umax", 4) == 0) {
00083 out = static_cast<unsigned long>(-1);
00084 err = (char*)x+4;
00085 }
00086 else if (std::strncmp(x, "-1", 2) == 0) {
00087 out = static_cast<unsigned long>(-1);
00088 err = (char*)x+2;
00089 }
00090 else if (*x != '-') {
00091 out = std::strtoul(x, &err, detectBase(x));
00092 if (out == ULONG_MAX && errno == ERANGE) { err = (char*)x; }
00093 }
00094 else { err = (char*)x; }
00095 return parsed(err != x, err, errPos);
00096 }
00097
00098 int xconvert(const char* x, double& out, const char** errPos, int) {
00099 if (empty(x, errPos)) { return 0; }
00100 char* err;
00101 out = std::strtod(x, &err);
00102 return parsed(err != x, err, errPos);
00103 }
00104
00105
00106 int xconvert(const char* x, unsigned& out, const char** errPos, int) {
00107 unsigned long temp;
00108 int tok = xconvert(x, temp, errPos, 0);
00109 if (tok == 0 || (temp > UINT_MAX && temp != static_cast<unsigned long>(-1))) {
00110 return parsed(0, x, errPos);
00111 }
00112 out = (unsigned)temp;
00113 return tok;
00114 }
00115 int xconvert(const char* x, int& out, const char** errPos, int) {
00116 long temp;
00117 int tok = xconvert(x, temp, errPos, 0);
00118 if (tok == 0 || temp < (long)INT_MIN || temp > (long)INT_MAX) {
00119 return parsed(0, x, errPos);
00120 }
00121 out = (int)temp;
00122 return tok;
00123 }
00124
00125 int xconvert(const char* x, const char*& out, const char** errPos, int) {
00126 out = x;
00127 if (errPos) { *errPos = x + std::strlen(x); }
00128 return 1;
00129 }
00130 int xconvert(const char* x, std::string& out, const char** errPos, int sep) {
00131 const char* end;
00132 if (sep == 0 || (end = std::strchr(x, char(sep))) == 0) {
00133 out = x;
00134 }
00135 else {
00136 out.assign(x, end - x);
00137 }
00138 if (errPos) { *errPos = x + out.length(); }
00139 return 1;
00140 }
00141
00142 bad_string_cast::~bad_string_cast() throw() {}
00143 const char* bad_string_cast::what() const throw() { return "bad_string_cast"; }
00144
00145 }