#include "cfg-value.h" #define _CRT_SECURE_NO_DEPRECATE #include <stdio.h> #include <string.h> #include <stdlib.h> #include <math.h> #include <limits.h> #include <errno.h> #include "scm-mem.h" #include "io-guts.h" // -------------------------------------------------------------------------------------------- // // * Implementation * // -------------------------------------------------------------------------------------------- // // CPP namespace scm { // = x^p int ipow(const int x, const int p) { if (p == 0) return 1; if (p == 1) return x; int tmp = ipow(x, p / 2); if (p % 2 == 0) return tmp*tmp; else return x*tmp*tmp; } } // -------------------------------------------------------------------------------------------- // bool scm::is_integer(const char* token, int* value) { const int mode = 10; char* pend; if (strlen(token) == 0) return false; errno = 0; long lvalue = strtol(token, &pend, mode); if ((errno == ERANGE && (lvalue == LONG_MAX || lvalue == LONG_MIN)) || (errno != 0 && lvalue == 0)) { return false; } // checking integer bounds // if ((lvalue >= INT_MAX) || (lvalue <= INT_MIN)) return false; if (*pend != '\0') return false; *value = (int)lvalue; return true; } bool scm::is_integer(const char* token) { int value; return is_integer(token, &value); } bool scm::is_double(const char* token, double* value) { char* pend; if (strlen(token) == 0) return false; errno = 0; *value = strtod(token, &pend); if ((errno == ERANGE && (*value == HUGE_VAL || *value == -HUGE_VAL)) || (errno != 0 && *value == (double)0)) { return false; } if (*pend != '\0') return false; return true; } bool scm::is_double(const char* token) { double value; return is_double(token, &value); } bool scm::is_valid_c_name(const char* token) { int token_length = (int)strlen(token); if (token_length == 0) return false; if ((!isalpha(token[0])) && (token[0] != '_')) return false; for (int i = 1; i < token_length; i++) { if ((!isalnum(token[i])) && (token[i] != '_')) return false; } return true; } bool scm::is_valid_string(const char* token) { int token_length = (int)strlen(token); if (token_length <= 1) return false; if ((token[0] != '"') || (token[token_length - 1] != '"')) return false; return true; } bool scm::is_boolean(const char* token, bool* value) { if (!strcmp(token, "true")) { *value = true; return true; } if (!strcmp(token, "false")) { *value = false; return true; } return false; } bool scm::is_boolean(const char* token) { bool value; return is_boolean(token, &value); } void scm::strcpyrm(char* a, const char* b, const char sym) { int i = 0; for (int k = 0; k < (int)strlen(b); k++) { if (b[k] == sym) continue; a[i] = b[k]; i++; } a[i] = '\0'; } // -------------------------------------------------------------------------------------------- // // -------------------------------------------------------------------------------------------- // // * Implementation * // * scm::cfgValue * // -------------------------------------------------------------------------------------------- // // -------------------------------------------------------------------------------------------- // scm::cfgValue::cfgValue() : type(IS_UNDEF), eint(0), edouble((double)0), estring(NULL), ebool(false) { } scm::cfgValue::cfgValue(const int x) : type(IS_INT), eint(x), edouble((double)0), estring(NULL), ebool(false) { } scm::cfgValue::cfgValue(const float x) : type(IS_DOUBLE), eint(0), edouble((double)x), estring(NULL), ebool(false) { } scm::cfgValue::cfgValue(const double x) : type(IS_DOUBLE), eint(0), edouble(x), estring(NULL), ebool(false) { } scm::cfgValue::cfgValue(const long double x) : type(IS_DOUBLE), eint(0), edouble((double)x), estring(NULL), ebool(false) { } scm::cfgValue::cfgValue(const char* c_str) : type(IS_STRING), eint(0), edouble((double)0), estring(NULL), ebool(false) { estring = new char[strlen(c_str) + 1]; strcpy(estring, c_str); } scm::cfgValue::cfgValue(const bool x) : type(IS_BOOLEAN), eint(0), edouble((double)0), estring(NULL), ebool(x) { } scm::cfgValue::~cfgValue() { clear(); } scm::cfgValue::cfgValue(const cfgValue& x) { type = x.type; if (type == IS_INT) eint = x.eint; else if (type == IS_DOUBLE) edouble = x.edouble; else if (type == IS_BOOLEAN) ebool = x.ebool; else if (type == IS_STRING) { estring = new char[strlen(x.estring) + 1]; strcpy(estring, x.estring); } } // -------------------------------------------------------------------------------------------- // // * swap & assignment * // // -------------------------------------------------------------------------------------------- // const scm::cfgValue& scm::cfgValue::operator=(cfgValue x) { swap(x); return (*this); } void scm::cfgValue::swap( cfgValue& x) { scm::swap(type, x.type); scm::swap(eint, x.eint); scm::swap(edouble, x.edouble); scm::swap(estring, x.estring); scm::swap(ebool, x.ebool); } // -------------------------------------------------------------------------------------------- // // * make implicit value * // // -------------------------------------------------------------------------------------------- // scm::cfgValue scm::cfgValue::make_implicit(const char* value_in_string) { cfgValue x; if (is_integer(value_in_string, &x.eint)) x.type = IS_INT; else if (is_double(value_in_string, &x.edouble)) x.type = IS_DOUBLE; else if (is_boolean(value_in_string, &x.ebool)) x.type = IS_BOOLEAN; else if (is_valid_string(value_in_string)) { x.type = IS_STRING; x.estring = new char[strlen(value_in_string) + 1]; strcpyrm(x.estring, value_in_string, '"'); } return x; } // -------------------------------------------------------------------------------------------- // // * clear * // // -------------------------------------------------------------------------------------------- // void scm::cfgValue::clear() { if (type == IS_STRING) { delete[] estring; estring = NULL; } type = IS_UNDEF; } // -------------------------------------------------------------------------------------------- // // * get and check calls * // // -------------------------------------------------------------------------------------------- // bool scm::cfgValue::get(int* x) const { if (type == IS_INT) { (*x) = eint; return true; } return false; } bool scm::cfgValue::get(float* x) const { if (type == IS_DOUBLE) { (*x) = (float)edouble; return true; } if (type == IS_INT) { (*x) = (float)eint; return true; } return false; } bool scm::cfgValue::get(double* x) const { if (type == IS_DOUBLE) { (*x) = edouble; return true; } if (type == IS_INT) { (*x) = (double)eint; return true; } return false; } bool scm::cfgValue::get(long double* x) const { if (type == IS_DOUBLE) { (*x) = (long double)edouble; return true; } if (type == IS_INT) { (*x) = (long double)eint; return true; } return false; } bool scm::cfgValue::get(char** c_str) const { if (type == IS_STRING) { (*c_str) = new char[strlen(estring) + 1]; strcpy(*c_str, estring); return true; } return false; } bool scm::cfgValue::get(std::string& x) const { if (type == IS_STRING) { x = std::string(estring); return true; } return false; } bool scm::cfgValue::get(bool* x) const { if (type == IS_BOOLEAN) { (*x) = ebool; return true; } return false; } scm::cfgValue::VAR_TYPE scm::cfgValue::get_type() const { return type; } bool scm::cfgValue::is_defined() const { return (type != IS_UNDEF); } // -------------------------------------------------------------------------------------------- // // * print * // // -------------------------------------------------------------------------------------------- // void scm::cfgValue::print() const { print(stdout); } void scm::cfgValue::print(FILE *ptr) const { if (type == IS_INT) fprintf(ptr, "%i", eint); else if (type == IS_DOUBLE) fprintf(ptr, "%f", edouble); else if (type == IS_BOOLEAN) fprintf(ptr, "%s", ebool ? "true" : "false"); else if (type == IS_STRING) fprintf(ptr, "%s", estring); else fprintf(ptr, "(UNDEFINED)"); } void scm::cfgValue::print_typed() const { if (type == IS_INT) printf("(INT) %i", eint); else if (type == IS_DOUBLE) printf("(DOUBLE) %f", edouble); else if (type == IS_BOOLEAN) printf("(BOOLEAN) %s", ebool ? "true" : "false"); else if (type == IS_STRING) printf("(STRING) %s", estring); else printf("(UNDEFINED)"); } // -------------------------------------------------------------------------------------------- // // * operators * // // -------------------------------------------------------------------------------------------- // scm::cfgValue& scm::cfgValue::operator+=(const cfgValue& x) { // (int) += (int) // (int) += (double) + conversion to (double) // (double) += (double) // (double) += (int) // (string) += (string) if ((type == IS_INT) && (x.type == IS_INT)) eint += x.eint; else if ((type == IS_INT) && (x.type == IS_DOUBLE)) { edouble = (double)eint + x.edouble; type = IS_DOUBLE; } else if ((type == IS_DOUBLE) && (x.type == IS_DOUBLE)) edouble += x.edouble; else if ((type == IS_DOUBLE) && (x.type == IS_INT)) edouble += (double)x.eint; else if ((type == IS_STRING) && (x.type == IS_STRING)) { const size_t length = strlen(estring) + strlen(x.estring) + 1; char *buf = new char[length]; strcpy(buf, estring); strcat(buf, x.estring); delete[] estring; estring = buf; } else { clear(); // type:= IS_UNDEF } return (*this); } scm::cfgValue& scm::cfgValue::operator-=(const cfgValue& x) { // (int) -= (int) // (int) -= (double) + conversion to (double) // (double) -= (double) // (double) -= (int) if ((type == IS_INT) && (x.type == IS_INT)) eint -= x.eint; else if ((type == IS_INT) && (x.type == IS_DOUBLE)) { edouble = (double)eint - x.edouble; type = IS_DOUBLE; } else if ((type == IS_DOUBLE) && (x.type == IS_DOUBLE)) edouble -= x.edouble; else if ((type == IS_DOUBLE) && (x.type == IS_INT)) edouble -= (double)x.eint; else { clear(); // type:= IS_UNDEF } return (*this); } scm::cfgValue& scm::cfgValue::operator*=(const cfgValue& x) { // (int) *= (int) // (int) *= (double) + conversion to (double) // (double) *= (double) // (double) *= (int) if ((type == IS_INT) && (x.type == IS_INT)) eint *= x.eint; else if ((type == IS_INT) && (x.type == IS_DOUBLE)) { edouble = (double)eint * x.edouble; type = IS_DOUBLE; } else if ((type == IS_DOUBLE) && (x.type == IS_DOUBLE)) edouble *= x.edouble; else if ((type == IS_DOUBLE) && (x.type == IS_INT)) edouble *= (double)x.eint; else { clear(); // type:= IS_UNDEF } return (*this); } scm::cfgValue& scm::cfgValue::operator/=(const cfgValue& x) { // (int) /= (int) // (int) /= (double) + conversion to (double) // (double) /= (double) // (double) /= (int) if ((type == IS_INT) && (x.type == IS_INT)) eint /= x.eint; else if ((type == IS_INT) && (x.type == IS_DOUBLE)) { edouble = (double)eint / x.edouble; type = IS_DOUBLE; } else if ((type == IS_DOUBLE) && (x.type == IS_DOUBLE)) edouble /= x.edouble; else if ((type == IS_DOUBLE) && (x.type == IS_INT)) edouble /= (double)x.eint; else { clear(); // type:= IS_UNDEF } return (*this); } scm::cfgValue& scm::cfgValue::operator%=(const cfgValue& x) { // int %= (int) if ((type == IS_INT) && (x.type == IS_INT)) eint %= x.eint; else { clear(); // type:= IS_UNDEF } return (*this); } scm::cfgValue& scm::cfgValue::operator^=(const cfgValue& x) { // (int) ^= (int) // (int) ^= (double) + conversion to (double) // (double) ^= (double) // (double) ^= (int) if ((type == IS_INT) && (x.type == IS_INT)) eint = ipow(eint, x.eint); else if ((type == IS_INT) && (x.type == IS_DOUBLE)) { edouble = pow((double)eint, x.edouble); type = IS_DOUBLE; } else if ((type == IS_DOUBLE) && (x.type == IS_DOUBLE)) edouble = pow(edouble, x.edouble); else if ((type == IS_DOUBLE) && (x.type == IS_INT)) edouble = pow(edouble, x.eint); else { clear(); // type:= IS_UNDEF } return (*this); } // *: check if we should really use const on return (all operators) -> const scm::cfgValue scm::cfgValue::operator+(const cfgValue& x) const { return cfgValue(*this) += x; } const scm::cfgValue scm::cfgValue::operator-(const cfgValue& x) const { return cfgValue(*this) -= x; } const scm::cfgValue scm::cfgValue::operator*(const cfgValue& x) const { return cfgValue(*this) *= x; } const scm::cfgValue scm::cfgValue::operator/(const cfgValue& x) const { return cfgValue(*this) /= x; } const scm::cfgValue scm::cfgValue::operator%(const cfgValue& x) const { return cfgValue(*this) %= x; } const scm::cfgValue scm::cfgValue::operator^(const cfgValue& x) const { return cfgValue(*this) ^= x; } const scm::cfgValue scm::cfgValue::operator==(const cfgValue& x) const { cfgValue res; if (type == IS_INT) { if (x.type == IS_INT) { res.type = IS_BOOLEAN; res.ebool = (eint == x.eint); } else if (x.type == IS_DOUBLE) { res.type = IS_BOOLEAN; res.ebool = (eint == x.edouble); } else if (x.type == IS_BOOLEAN) { res.type = IS_BOOLEAN; res.ebool = (eint == (int)x.ebool); } } else if (type == IS_DOUBLE) { if (x.type == IS_INT) { res.type = IS_BOOLEAN; res.ebool = (edouble == x.eint); } else if (x.type == IS_DOUBLE) { res.type = IS_BOOLEAN; res.ebool = (edouble == x.edouble); } else if (x.type == IS_BOOLEAN) { res.type = IS_BOOLEAN; res.ebool = (edouble == (int)x.ebool); } } else if (type == IS_BOOLEAN) { if (x.type == IS_INT) { res.type = IS_BOOLEAN; res.ebool = ((int)ebool == x.eint); } else if (x.type == IS_DOUBLE) { res.type = IS_BOOLEAN; res.ebool = ((int)ebool == x.edouble); } else if (x.type == IS_BOOLEAN) { res.type = IS_BOOLEAN; res.ebool = (ebool == x.ebool); } } else if (type == IS_STRING) { if (x.type == IS_STRING) { res.type = IS_BOOLEAN; res.ebool = (!strcmp(estring, x.estring)); } } return res; } const scm::cfgValue scm::cfgValue::operator!=(const cfgValue& x) const { cfgValue res = ((*this) == x); if (res.type == IS_BOOLEAN) res.ebool = (!res.ebool); return res; } const scm::cfgValue scm::cfgValue::operator<(const cfgValue& x) const { cfgValue res; if (type == IS_INT) { if (x.type == IS_INT) { res.type = IS_BOOLEAN; res.ebool = (eint < x.eint); } else if (x.type == IS_DOUBLE) { res.type = IS_BOOLEAN; res.ebool = (eint < x.edouble); } else if (x.type == IS_BOOLEAN) { res.type = IS_BOOLEAN; res.ebool = (eint < (int)x.ebool); } } else if (type == IS_DOUBLE) { if (x.type == IS_INT) { res.type = IS_BOOLEAN; res.ebool = (edouble < x.eint); } else if (x.type == IS_DOUBLE) { res.type = IS_BOOLEAN; res.ebool = (edouble < x.edouble); } else if (x.type == IS_BOOLEAN) { res.type = IS_BOOLEAN; res.ebool = (edouble < (int)x.ebool); } } else if (type == IS_BOOLEAN) { if (x.type == IS_INT) { res.type = IS_BOOLEAN; res.ebool = ((int)ebool < x.eint); } else if (x.type == IS_DOUBLE) { res.type = IS_BOOLEAN; res.ebool = ((int)ebool < x.edouble); } else if (x.type == IS_BOOLEAN) { res.type = IS_BOOLEAN; res.ebool = (ebool < x.ebool); } } return res; } const scm::cfgValue scm::cfgValue::operator>(const cfgValue& x) const { cfgValue res; if (type == IS_INT) { if (x.type == IS_INT) { res.type = IS_BOOLEAN; res.ebool = (eint > x.eint); } else if (x.type == IS_DOUBLE) { res.type = IS_BOOLEAN; res.ebool = (eint > x.edouble); } else if (x.type == IS_BOOLEAN) { res.type = IS_BOOLEAN; res.ebool = (eint > (int)x.ebool); } } else if (type == IS_DOUBLE) { if (x.type == IS_INT) { res.type = IS_BOOLEAN; res.ebool = (edouble > x.eint); } else if (x.type == IS_DOUBLE) { res.type = IS_BOOLEAN; res.ebool = (edouble > x.edouble); } else if (x.type == IS_BOOLEAN) { res.type = IS_BOOLEAN; res.ebool = (edouble > (int)x.ebool); } } else if (type == IS_BOOLEAN) { if (x.type == IS_INT) { res.type = IS_BOOLEAN; res.ebool = ((int)ebool > x.eint); } else if (x.type == IS_DOUBLE) { res.type = IS_BOOLEAN; res.ebool = ((int)ebool > x.edouble); } else if (x.type == IS_BOOLEAN) { res.type = IS_BOOLEAN; res.ebool = (ebool > x.ebool); } } return res; } const scm::cfgValue scm::cfgValue::operator<=(const cfgValue& x) const { cfgValue res = ((*this) > x); if (res.type == IS_BOOLEAN) res.ebool = (!res.ebool); return res; } const scm::cfgValue scm::cfgValue::operator>=(const cfgValue& x) const { cfgValue res = ((*this) < x); if (res.type == IS_BOOLEAN) res.ebool = (!res.ebool); return res; } const scm::cfgValue scm::cfgValue::operator-() const { // -(int) // -(double) cfgValue x; // default: type:= IS_UNDEF if (type == IS_INT) { x = (*this); x.eint = -x.eint; } else if (type == IS_DOUBLE) { x = (*this); x.edouble = -x.edouble; } return x; } const scm::cfgValue scm::cfgValue::operator+() const { // +(int) // +(double) cfgValue x; // default: type:= IS_UNDEF if (type == IS_INT) x = (*this); else if (type == IS_DOUBLE) x = (*this); return x; } const scm::cfgValue scm::cfgValue::logical_and(const cfgValue& x) const { cfgValue res; if ((type == IS_BOOLEAN) && (x.type == IS_BOOLEAN)) { res.type = IS_BOOLEAN; res.ebool = (ebool && x.ebool); } return res; } const scm::cfgValue scm::cfgValue::logical_or(const cfgValue& x) const { cfgValue res; if ((type == IS_BOOLEAN) && (x.type == IS_BOOLEAN)) { res.type = IS_BOOLEAN; res.ebool = (ebool || x.ebool); } return res; } // <- // // -------------------------------------------------------------------------------------------- // // * functions * // // -------------------------------------------------------------------------------------------- // const scm::cfgValue scm::cfgValue::cfg_sin(const cfgValue& x) { // sin(int) // sin(double) cfgValue y; // default: type:=IS_UNDEF if (x.type == IS_DOUBLE) { y.edouble = sin(x.edouble); y.type = IS_DOUBLE; } else if (x.type == IS_INT) { y.edouble = sin((double)x.eint); y.type = IS_DOUBLE; } return y; } const scm::cfgValue scm::cfgValue::cfg_cos(const cfgValue& x) { // cos(int) // cos(double) cfgValue y; // default: type:=IS_UNDEF if (x.type == IS_DOUBLE) { y.edouble = cos(x.edouble); y.type = IS_DOUBLE; } else if (x.type == IS_INT) { y.edouble = cos((double)x.eint); y.type = IS_DOUBLE; } return y; } const scm::cfgValue scm::cfgValue::cfg_tan(const cfgValue& x) { // tan(int) // tan(double) cfgValue y; // default: type:=IS_UNDEF if (x.type == IS_DOUBLE) { y.edouble = tan(x.edouble); y.type = IS_DOUBLE; } else if (x.type == IS_INT) { y.edouble = tan((double)x.eint); y.type = IS_DOUBLE; } return y; } const scm::cfgValue scm::cfgValue::cfg_log(const cfgValue& x) { // log(int) // log(double) cfgValue y; // default: type:=IS_UNDEF if (x.type == IS_DOUBLE) { y.edouble = log(x.edouble); y.type = IS_DOUBLE; } else if (x.type == IS_INT) { y.edouble = log((double)x.eint); y.type = IS_DOUBLE; } return y; } const scm::cfgValue scm::cfgValue::cfg_sqrt(const cfgValue& x) { // sqrt(int) // sqrt(double) cfgValue y; // default: type:=IS_UNDEF if (x.type == IS_DOUBLE) { y.edouble = sqrt(x.edouble); y.type = IS_DOUBLE; } else if (x.type == IS_INT) { y.edouble = sqrt((double)x.eint); y.type = IS_DOUBLE; } return y; } const scm::cfgValue scm::cfgValue::cfg_abs(const cfgValue& x) { // sqrt(int) // sqrt(double) cfgValue y; // default: type:=IS_UNDEF if (x.type == IS_DOUBLE) { y.edouble = (x.edouble < (double)0) ? -x.edouble : x.edouble; y.type = IS_DOUBLE; } else if (x.type == IS_INT) { y.eint = (x.eint < 0) ? -x.eint : x.eint; y.type = IS_INT; } return y; } const scm::cfgValue scm::cfgValue::cfg_to_string(const cfgValue& x) { // string(int) // string(double) // string(string) // string(boolean) cfgValue y; // default: type:=IS_UNDEF if (x.type == IS_INT) { y.type = IS_STRING; std::string val_string = convert_to_string(x.eint); y.estring = new char[strlen(val_string.c_str()) + 1]; strcpy(y.estring, val_string.c_str()); } else if (x.type == IS_DOUBLE) { y.type = IS_STRING; std::string val_string = convert_to_string(x.edouble); y.estring = new char[strlen(val_string.c_str()) + 1]; strcpy(y.estring, val_string.c_str()); } else if (x.type == IS_BOOLEAN) { y.type = IS_STRING; std::string val_string; val_string = (x.ebool) ? "true" : "false"; y.estring = new char[strlen(val_string.c_str()) + 1]; strcpy(y.estring, val_string.c_str()); } else if (x.type == IS_STRING) y = x; return y; } const scm::cfgValue scm::cfgValue::cfg_min(const cfgValue& a, const cfgValue& b) { // min(int, int) // min(double, double) // min(int, double) // min(double, int) cfgValue _min; // default: type:=IS_UNDEF if ((a.type == IS_DOUBLE) && (b.type == IS_DOUBLE)) _min = (a.edouble < b.edouble) ? a : b; else if ((a.type == IS_DOUBLE) && (b.type == IS_INT)) { _min.edouble = (a.edouble < (double)b.eint) ? a.edouble : (double)b.eint; _min.type = IS_DOUBLE; } else if ((a.type == IS_INT) && (b.type == IS_DOUBLE)) { _min.edouble = ((double)a.eint < b.edouble) ? (double)a.eint : b.edouble; _min.type = IS_DOUBLE; } else if ((a.type == IS_INT) && (b.type == IS_INT)) _min = (a.eint < b.eint) ? a : b; return _min; } const scm::cfgValue scm::cfgValue::cfg_max(const cfgValue& a, const cfgValue& b) { // max(int, int) // max(double, double) // max(int, double) // max(double, int) cfgValue _max; // default: type:=IS_UNDEF if ((a.type == IS_DOUBLE) && (b.type == IS_DOUBLE)) _max = (a.edouble > b.edouble) ? a : b; else if ((a.type == IS_DOUBLE) && (b.type == IS_INT)) { _max.edouble = (a.edouble > (double)b.eint) ? a.edouble : (double)b.eint; _max.type = IS_DOUBLE; } else if ((a.type == IS_INT) && (b.type == IS_DOUBLE)) { _max.edouble = ((double)a.eint > b.edouble) ? (double)a.eint : b.edouble; _max.type = IS_DOUBLE; } else if ((a.type == IS_INT) && (b.type == IS_INT)) _max = (a.eint > b.eint) ? a : b; return _max; } // -------------------------------------------------------------------------------------------- //