/* orxonox - the future of 3D-vertical-scrollers Copyright (C) 2004 orx This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. ### File Specific: main-programmer: Benjamin Grauer co-programmer: ... */ //#define DEBUG_SPECIAL_MODULE DEBUG_MODULE_ #include "multi_type.h" #include #ifdef DEBUG #include "debug.h" #endif /** * @brief creates a multiType without any stored value at all. */ MultiType::MultiType(MT_Type type) { this->type = type; switch (this->type) { default: this->value.Float = 0.0f; break; case MT_BOOL: this->value.Bool = false; break; case MT_INT: this->value.Int = 0; break; case MT_FLOAT: this->value.Float = 0.0f; break; case MT_CHAR: this->value.Char = '\0'; break; case MT_STRING: this->storedString = ""; break; } } /** * @brief creates a multiType out of a boolean * @param value the Value of this MulitType */ MultiType::MultiType(bool value) { this->setBool(value); } /** * @brief creates a multiType out of an integer * @param value the Value of this MulitType */ MultiType::MultiType(int value) { this->setInt(value); } /** * @brief creates a multiType out of a float (double) * @param value the Value of this MulitType */ MultiType::MultiType(double value) { this->setFloat(value); } /** * @brief creates a multiType out of a char * @param value the Value of this MulitType */ MultiType::MultiType(char value) { this->setChar(value); } /** * @brief creates a multiType out of a String * @param value the Value of this MulitType */ MultiType::MultiType(const std::string& value) { this->setString(value); } /** * @brief constructs a new MultiType from another one (copy) */ MultiType::MultiType(const MultiType& multiType) { *this = multiType; } /** * @brief standard deconstructor */ MultiType::~MultiType () { } /** * @brief copy operator * @param mt: the entity to copy * @returns A Copy of itself. (strings inside are copied as well) */ MultiType& MultiType::operator= (const MultiType& mt) { this->type = mt.type; this->value = mt.value; this->storedString = mt.storedString; return *this; } /** * @brief checks if the two Multitypes match * @param mt MultiType to check against this one * @returns true on match. false otherwise * * Two MultiType match if and only if * 1. the internal Type is the same * 2. the stored values match */ bool MultiType::operator==(const MultiType& mt) const { if (this->type != mt.type) return false; switch (this->type) { case MT_NULL: return true; case MT_BOOL: return (this->value.Bool == mt.value.Bool); case MT_INT: return (this->value.Int == mt.value.Int); case MT_CHAR: return (this->value.Char == mt.value.Char); case MT_FLOAT: return (this->value.Float == mt.value.Float); case MT_STRING: return (this->storedString == mt.storedString); default: return false; } } /** * @brief sets the type of this MultiType and resets to the default value * @param type the new Type */ void MultiType::setType(MT_Type type) { if (this->type == type) return; switch (type) { case MT_BOOL: this->setBool(this->getBool()); break; case MT_INT: this->setInt(this->getInt()); break; case MT_FLOAT: this->setFloat(this->getFloat()); break; case MT_CHAR: this->setChar(this->getChar()); break; case MT_STRING: this->setString(this->getString()); break; default: this->type = type; } } /** * @brief sets the Value of mt without changing the type of this MultiType * @param mt: the MultiType to get the value from * * This is a pure Value copy. The current type will be preserved. */ void MultiType::setValueOf(const MultiType& mt) { MT_Type prevType = this->type; *this = mt; this->setType(prevType); } /** * @brief sets a new Value to the MultiType * @param value the new Value as a bool */ void MultiType::setBool(bool value) { this->type = MT_BOOL; this->value.Bool = value; } /** * @brief sets a new Value to the MultiType * @param value the new Value as an int */ void MultiType::setInt(int value) { this->type = MT_INT; this->value.Int = value; } /** * @brief sets a new Value to the MultiType * @param value the new Value as a float */ void MultiType::setFloat(float value) { this->type = MT_FLOAT; this->value.Float = value; } /** * @brief sets a new Value to the MultiType * @param value the new Value as a char */ void MultiType::setChar(char value) { this->type = MT_CHAR; this->value.Char = value; } /** * @brief sets a new Value to the MultiType * @param value the new Value as a String */ void MultiType::setString(const std::string& value) { this->type = MT_STRING; this->storedString = value; } /** * @brief stores any value to the string. * @note this Value can be grabbed by using the getStoredString function. */ void MultiType::storeString() { if (!(this->type & MT_STRING)) this->storedString = this->getString(); } /************************** *** RETRIEVAL FUNCTIONS *** **************************/ /** * @returns the Value of this MultiType as a int */ bool MultiType::getBool() const { // default case: if (this->type & MT_BOOL) return this->value.Bool; // Special Cases: else if (this->type & MT_INT) return (this->value.Int == 0)? false : true; else if (this->type & MT_FLOAT) return (this->value.Float == 0.0f)? false : true; else if (this->type & MT_CHAR) return (this->value.Char == '\0')? false : true; else if (this->type & MT_STRING) return (this->storedString == "true" || this->storedString == "TRUE" || this->storedString != "0"); // TODO make this better... return false; } /** * @returns the Value of this MultiType as a int */ int MultiType::getInt() const { // default case: if (this->type & MT_INT) return this->value.Int; if (this->type & MT_BOOL) return (this->value.Bool)? 1 : 0; else if (this->type & MT_FLOAT) return (int) this->value.Float; else if (this->type & MT_CHAR) return (int) this->value.Char; else if (this->type & MT_STRING) { std::stringstream ssStream(this->storedString); int iReturn; ssStream >> iReturn; return iReturn; } return 0; } /** * @returns the Value of this MultiType as a float */ float MultiType::getFloat() const { // default case: if (this->type & MT_FLOAT) return this->value.Float; if (this->type & MT_BOOL) return (this->value.Bool == true)? 1.0f : 0.0f; else if (this->type & MT_INT) return (float) this->value.Int; else if (this->type & MT_CHAR) return (float) this->value.Char; else if (this->type & MT_STRING) { char* endPtr = NULL; double result = strtod(this->storedString.c_str(), &endPtr); if ( endPtr >= this->storedString.c_str() && endPtr < this->storedString.c_str() + this->storedString.size()) return 0.0f; else return result; } return 0.0f; } /** * @returns the Value of this MultiType as a char */ char MultiType::getChar() const { // default case: if (this->type & MT_INT) return this->value.Int; if (this->type & MT_BOOL) return (this->value.Bool)? 'y' : 'n'; else if (this->type & MT_INT) return (int) this->value.Int; else if (this->type & MT_FLOAT) return (char) this->value.Float; else if (this->type & MT_STRING) return this->storedString[0]; return '\0'; } /** * @returns the Value of this MultiType as a String */ std::string MultiType::getString() const { // default case: if (this->type & MT_STRING) return this->storedString; else { if (this->type & MT_BOOL) return (this->value.Bool)? "true" : "false"; else if (this->type & MT_INT) { char tmpString[32]; sprintf(tmpString, "%d", this->value.Int); return tmpString; } else if (this->type & MT_FLOAT) { char tmpString[64]; sprintf(tmpString, "%f", this->value.Float); return tmpString; } else if (this->type & MT_CHAR) { char tmpString[2]; tmpString[0] = this->value.Char; tmpString[1] = '\0'; return tmpString; } } return ""; } /** * @brief returns a Constant string (actually this is slower than getString() * @returns a constant string of the stored version's one. * @note this could lead to a inconsistency of data AND IS HIGHLY NON_THREAD_SAFE! * PLEASE THINK ABOUT USING THE getStoredString function in conjunction with storeString(). */ const std::string& MultiType::getConstString() const { MultiType::constString = this->getString(); return MultiType::constString; } /** * @brief returns the currently stored string. * @returns the Stored string. * @note Storing a string works as follows: \\ * MultiType a(3); // Creates a MultiType of Type int with value 3 \\ * a.storeString(); // Stores the String in the internal structure. \\ * std::string name = a.getStoredString(); * * This would be the same as * name = a.getString(); * but with much more const'ness. */ const std::string& MultiType::getStoredString() const { MultiType::constString = this->getString(); return MultiType::constString; } /** * @returns a formated c-string of the held value */ const char* MultiType::getCString() { if (this->type & MT_STRING) return this->storedString.c_str(); else { this->storedString = this->getString(); return this->storedString.c_str(); } } /** * @brief prints out some nice debug output */ void MultiType::debug() const { #ifdef DEBUG PRINT(0) #else printf #endif ("MultiType of Type '%s' :: Values: BOOL: '%d', INT: '%d', FLOAT: '%f', CHAR: '%c', STRING '%s'\n", MultiType::MultiTypeToString(this->type).c_str(), this->getBool(), this->getInt(), this->getFloat(), this->getChar(), this->getString().c_str() ); } /** * @brief Resets the MultiType to default values. */ void MultiType::reset() { switch ( this->type ) { case MT_BOOL: this->setBool(false); break; case MT_INT: this->setInt(0); break; case MT_FLOAT: this->setFloat(0.0f); break; case MT_CHAR: this->setChar('\0'); break; case MT_STRING: this->setString(""); break; default: #ifdef DEBUG PRINTF(2)("Unknown Type not reseting\n"); #endif break; } } /** * @brief converts a MT_Type into a String * @param type: the MT_Type * @returns: the Type as a constant String (do not delete) */ const std::string& MultiType::MultiTypeToString(MT_Type type) { switch ( type ) { case MT_BOOL: return MultiType::typeNames[1]; case MT_INT: return MultiType::typeNames[2]; case MT_FLOAT: return MultiType::typeNames[3]; case MT_CHAR: return MultiType::typeNames[4]; case MT_STRING: return MultiType::typeNames[5]; default: return MultiType::typeNames[0]; } } /** * @brief converts a String into a MT_Type * @param type: the Type as a String * @returns: the Type as MT_Type */ MT_Type MultiType::StringToMultiType(const std::string& type) { if (type == MultiType::typeNames[1]) return MT_BOOL; if (type == MultiType::typeNames[2]) return MT_INT; if (type == MultiType::typeNames[3]) return MT_FLOAT; if (type == MultiType::typeNames[4]) return MT_CHAR; if (type == MultiType::typeNames[5]) return MT_STRING; return MT_NULL; } std::string MultiType::constString = ""; const std::string MultiType::typeNames[] = { "NONE", //0 "bool", //1 "int", //2 "float", //3 "char", //4 "string" //5 };