/* ....[@@@..[@@@..............[@.................. MUD++ is a written from ....[@..[@..[@..[@..[@..[@@@@@....[@......[@.... scratch multi-user swords and ....[@..[@..[@..[@..[@..[@..[@..[@@@@@..[@@@@@.. sorcery game written in C++. ....[@......[@..[@..[@..[@..[@....[@......[@.... This server is an ongoing ....[@......[@..[@@@@@..[@@@@@.................. development project. All ................................................ contributions are welcome. ....Copyright(C).1995.Melvin.Smith.............. Enjoy. ------------------------------------------------------------------------------ Melvin Smith (aka Fusion) msmith@hom.net MUD++ development mailing list mudpp@van.ml.org ------------------------------------------------------------------------------ properties.cpp */ #include "config.h" #include "properties.h" #include "erratum.h" #include "bit.h" HashTable<Property> properties; bool properties_initialized = false; const bitType prop_types[] = { {0, 0}, {"bool", PROP_BOOL}, {"int", PROP_INT}, {"string", PROP_STRING}, {"(unknown)", PROP_UNKNOWN}, {0, 0} }; Property & Property::operator= (const Property & p) { if ( (type == PROP_STRING) && ( value.s) ) delete value.s; runtime = p.getRuntime(); type = p.getType(); nfun = p.getFun(); value = p.getValue(); if ( (type == PROP_STRING) && ( value.s ) ) value.s = new String(*(value.s)); return *this; } int Property::readFrom( StaticInput & si ) { char buf[BUF]; assert( type == PROP_UNKNOWN); si.getword(buf); if( *buf == 'T' ) runtime = true; else if ( *buf == 'R' ) runtime = false; else if ( *buf == '#' ) return 1; else { si.errorf( "Property:readFrom - unknown runtime flag '%c'", *buf); return -1; } si.getword(buf); type = (property_type) lookupBit( prop_types, buf ); if ( type == PROP_UNKNOWN ) { si.errorf( "Property:readFrom - unknown type %s", buf); return -1; } si.getword(buf); setName( String(buf) ); switch (type ) { case PROP_BOOL: si.getword(buf); if ( !strcmp(buf, "true") ) value.b = true; else value.b = false; break; case PROP_INT: value.i = si.getnum(); break; case PROP_STRING: si.getstring(buf); value.s = new String(buf); break; default: Error::dump("Property::readFrom - unknown type despite of check"); } return 0; } const char * Property::asText() const { switch(type) { case PROP_BOOL: return ( value.b ? "true" : "false" ); case PROP_INT: return itoa(value.i); case PROP_STRING: return value.s->chars(); default: return "(unknown)"; } } const char * Property::getTypeName() const { return lookupBitName( prop_types, type); } int Property::writeTo(Output & out ) const { out << (runtime ? "T " : "R ") << getTypeName() << ' ' << getName() << ' ' << asText(); if ( type == PROP_STRING ) out << '~'; return 0; } const char * Property::parseValue( const char * arg ) { prop_val nval; prop_val old; const char * txt; switch ( type ) { case PROP_BOOL: if ( !strcmp(arg, "true") ) nval.b = true; else if ( !strcmp(arg ,"false") ) nval.b = false; else return "This is boolean property - specify 'true' or 'false'"; if ( value.b == nval.b ) return "Same value was already set"; break; case PROP_INT: nval.i = atoi(arg); if ( value.i == nval.i ) return "Same value was already set"; break; case PROP_STRING: if ( nfun ) { old = value; value.s = new String( arg ); if ( (txt = (*nfun) (this)) ) { delete value.s; value = old; return txt; } if ( old.s ) delete old.s; return 0; } else { if ( value.s ) delete value.s; value.s = new String ( arg ); return 0; } default: Error::dump("Property:parseValue - unknown type"); } if ( !nfun ) { value = nval; return 0; } else { old = value; value = nval; if ( (txt = (*nfun) (this)) ) { value = old; return txt; } return 0; } } void lookup_property( Property ** holder, const char * name, property_type type, const char * defl, notifyFun fun, bool runtime ) { Property * prop; const char * init_err; prop = properties.lookup( name ); if ( prop ) { assert( prop->getType() == type ); if ( !prop->getFun() && fun ) { prop->setFun( fun ); init_err = (*fun) (prop); if ( init_err ) { Cout.sendf( "Property %s set to illegal value before initialization.\n\r" "Changing to default.\n\r", prop->getName().chars() ); init_err = prop->parseValue(defl); if ( init_err ) Error::dumpf("Default value %s for property %s is unacceptable", defl, name); } } else { assert( prop->getFun() == fun ); } } else { prop = new Property(); prop->setName(String(name)); prop->setType(type); prop->setFun(fun); prop->setRuntime(runtime); init_err = prop->parseValue(defl); if ( init_err ) Error::dumpf("Default value %s for property %s is unacceptable", defl, name); properties.add( prop->getName(), prop); } *holder = prop; } void initProperties() { Property * prop; int answer; assert( !properties_initialized ); InputFile inf(DEFAULT_PROPERTIES_FILE); if ( !inf ) { Cout << "no properties file." << endl; return; } while ( true ) { prop = new Property(); if ( (answer = prop->readFrom(inf)) ) { delete prop; if ( answer == 1 ) Cout << "sucessfull" << endl; else Cout << "with error" << endl; return; } properties.add( prop->getName(), prop ); } } void loadProperties( StaticInput & si, String & log ) { Property * prop; Property * oldprop; int state; int iprop =-1; const char * txt; while ( true ) { iprop++; prop = new Property(); state = prop->readFrom(si); if ( state == 1 ) { log << "Completed sucessfully\n\r"; delete prop; return; } else if (state == -1 ) { log << "Error ocurred during load of " << iprop << " property.\n\r"; delete prop; return; } oldprop = properties.lookup(prop->getName()); if (oldprop) { prop->setFun(oldprop->getFun()); if ( prop->getFun() ) { txt = prop->notify(); if ( txt ) { log << txt << endl; delete prop; continue; } } *oldprop = *prop; delete prop; continue; } properties.add(prop->getName(),prop); } } void saveProperties( Output & outp ) { Property * prop; for_each( properties, prop ) { prop->writeTo(outp); outp << endl; } outp << '#' << endl; } const char * nf_gtz( const Property * prop ) { assert(prop->getType() == PROP_INT ); if ( prop->getInt() <= 0 ) return "Value has to be greater than zero"; return 0; } const char * nf_gez( const Property * prop ) { assert(prop->getType() == PROP_INT ); if ( prop->getInt() < 0 ) return "Value has to be greater or equal to zero"; return 0; }