atari_py/ale_interface/src/emucore/PropsSet.cxx (185 lines of code) (raw):

//============================================================================ // // SSSS tt lll lll // SS SS tt ll ll // SS tttttt eeee ll ll aaaa // SSSS tt ee ee ll ll aa // SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator" // SS SS tt ee ll ll aa aa // SSSS ttt eeeee llll llll aaaaa // // Copyright (c) 1995-2007 by Bradford W. Mott and the Stella team // // See the file "license" for information on usage and redistribution of // this file, and for a DISCLAIMER OF ALL WARRANTIES. // // $Id: PropsSet.cxx,v 1.34 2007/07/31 15:46:20 stephena Exp $ //============================================================================ #include <sstream> #include <string.h> #include "OSystem.hxx" #include "DefProps.hxx" #include "Props.hxx" #include "PropsSet.hxx" #include "bspf.hxx" using namespace std; // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - PropertiesSet::PropertiesSet(OSystem* osystem) : myOSystem(osystem), myRoot(NULL), mySize(0) { const string& props = myOSystem->propertiesFile(); load(props, true); // do save these properties if(myOSystem->settings().getBool("showinfo")) cerr << "User game properties: \'" << props << "\'\n"; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - PropertiesSet::~PropertiesSet() { deleteNode(myRoot); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void PropertiesSet::getMD5(const string& md5, Properties& properties, bool useDefaults) const { properties.setDefaults(); bool found = false; // First check our dynamic BST for the object if(!useDefaults && myRoot != 0) { TreeNode* current = myRoot; while(current) { const string& currentMd5 = current->props->get(Cartridge_MD5); if(currentMd5 == md5) { // We only report a node as found if it's been marked as valid. // Invalid nodes are those that should be removed, and are // essentially treated as if they're not present. found = current->valid; break; } else if(md5 < currentMd5) current = current->left; else current = current->right; } if(found) properties = *(current->props); } // Otherwise, search the internal database using binary search if(!found) { int low = 0, high = DEF_PROPS_SIZE - 1; while(low <= high) { int i = (low + high) / 2; int cmp = strncmp(md5.c_str(), DefProps[i][Cartridge_MD5], 32); if(cmp == 0) // found it { for(int p = 0; p < LastPropType; ++p) if(DefProps[i][p][0] != 0) properties.set((PropertyType)p, DefProps[i][p]); found = true; break; } else if(cmp < 0) high = i - 1; // look at lower range else low = i + 1; // look at upper range } } } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void PropertiesSet::insert(const Properties& properties, bool save) { insertNode(myRoot, properties, save); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void PropertiesSet::removeMD5(const string& md5) { // We only remove from the dynamic BST if(myRoot != 0) { TreeNode* current = myRoot; while(current) { const string& currentMd5 = current->props->get(Cartridge_MD5); if(currentMd5 == md5) { current->valid = false; // Essentially, this node doesn't exist break; } else if(md5 < currentMd5) current = current->left; else current = current->right; } } } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void PropertiesSet::insertNode(TreeNode* &t, const Properties& properties, bool save) { if(t) { string md5 = properties.get(Cartridge_MD5); string currentMd5 = t->props->get(Cartridge_MD5); if(md5 < currentMd5) insertNode(t->left, properties, save); else if(md5 > currentMd5) insertNode(t->right, properties, save); else { delete t->props; t->props = new Properties(properties); t->save = save; t->valid = true; } } else { t = new TreeNode; t->props = new Properties(properties); t->left = 0; t->right = 0; t->save = save; t->valid = true; ++mySize; } } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void PropertiesSet::deleteNode(TreeNode *node) { if(node) { deleteNode(node->left); deleteNode(node->right); delete node->props; delete node; } } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void PropertiesSet::load(const string& filename, bool save) { ifstream in(filename.c_str(), ios::in); // Loop reading properties for(;;) { // Make sure the stream is still good or we're done if(!in) break; // Get the property list associated with this profile Properties prop; prop.load(in); // If the stream is still good then insert the properties if(in) insert(prop, save); } if(in) in.close(); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - bool PropertiesSet::save(const string& filename) const { ofstream out(filename.c_str(), ios::out); if(!out) return false; saveNode(out, myRoot); out.close(); return true; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void PropertiesSet::print() const { cerr << size() << endl; printNode(myRoot); // FIXME - print out internal properties as well } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void PropertiesSet::saveNode(ostream& out, TreeNode *node) const { if(node) { if(node->valid && node->save) node->props->save(out); saveNode(out, node->left); saveNode(out, node->right); } } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void PropertiesSet::printNode(TreeNode *node) const { if(node) { if(node->valid && node->save) node->props->print(); printNode(node->left); printNode(node->right); } } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - uInt32 PropertiesSet::size() const { return mySize; }