summaryrefslogblamecommitdiffstatshomepage
path: root/src/lib/util/options.h
blob: edf7f8600c8f023b71e939968e68a0e9c78ee59b (plain) (tree)
1
2
3
4
5
6
7
8
9
10

                                





                                                                            

                                                                            

                               
 
                     
                        


 


                                                                            
 
               
                                                                                

    






                                                        
  
 
                    




                                                                                 
 
                                                 
 
 


                                                                            
 

                                                                                     
 

                                                                                 
                                                                                 
                                                                             

  
 

                                                              
 






                                                          
                                                
 
                                           
                                                                                                                     



                                                      
                                                                                                                                                            
                                                                         



                                                                               
                                                                         
                                                          

                                                                            
                                                                                   
                                                                                             
                                                           
                                                             



                                                                   
                                                              
                                                            
                                                         
                                                              


                                 
                                                                                    
                                                                                     


                                                                                                            




                                                                                         
                                                                           








                                                                                                                        
 



                                                         
 
                  
                                                            
                                                                
                                                 
 
                          


                                                                   
 
                        
                                                                                                                                                      
                                                                                                                                                                           

                                                                                         
                                                                        


                                           
                                                                                                         
                                                                                                                    
                                                                                                                   

                    
                                                                                                          

                 

                                                                         


                                                    
                                                          
                                               


                                                                                    
                                            

                  


                                                                                                     
                                                                       
                                            
 
               
                                                                                                                      

                                                                 
          








                                                                                                               
                                                                                        
                                                                                                                                                    
                                                                                                     
 




                                               
                                                                                                                    

                         
                                                                                  
                                                                                                    
                                                                        
                                                                                            
  
 

 
                                 
// license:BSD-3-Clause
// copyright-holders:Aaron Giles
/***************************************************************************

    options.h

    Core options code code

***************************************************************************/

#ifndef MAME_LIB_UTIL_OPTIONS_H
#define MAME_LIB_UTIL_OPTIONS_H

#include "corefile.h"
#include <unordered_map>



//**************************************************************************
//  CONSTANTS
//**************************************************************************

// option types
const uint32_t OPTION_TYPE_MASK       = 0x0007;       // up to 8 different types
enum
{
	OPTION_INVALID,         // invalid
	OPTION_HEADER,          // a header item
	OPTION_COMMAND,         // a command
	OPTION_BOOLEAN,         // boolean option
	OPTION_INTEGER,         // integer option
	OPTION_FLOAT,           // floating-point option
	OPTION_STRING           // string option
};

// option priorities
const int OPTION_PRIORITY_DEFAULT   = 0;            // defaults are at 0 priority
const int OPTION_PRIORITY_LOW       = 50;           // low priority
const int OPTION_PRIORITY_NORMAL    = 100;          // normal priority
const int OPTION_PRIORITY_HIGH      = 150;          // high priority
const int OPTION_PRIORITY_MAXIMUM   = 255;          // maximum priority

const uint32_t OPTION_FLAG_INTERNAL = 0x40000000;


//**************************************************************************
//  TYPE DEFINITIONS
//**************************************************************************

// static structure describing a single option with its description and default value
struct options_entry
{
	const char *        name;               // name on the command line
	const char *        defvalue;           // default value of this argument
	uint32_t              flags;              // flags to describe the option
	const char *        description;        // description for -showusage
};


// structure holding information about a collection of options
class core_options
{
	static const int MAX_UNADORNED_OPTIONS = 16;

public:
	// information about a single entry in the options
	class entry
	{
		friend class core_options;
		friend class simple_list<entry>;

		// construction/destruction
		entry(const char *name, const char *description, uint32_t flags = 0, const char *defvalue = nullptr);

	public:
		// getters
		entry *next() const { return m_next; }
		const char *name(int index = 0) const { return (index < ARRAY_LENGTH(m_name) && !m_name[index].empty()) ? m_name[index].c_str() : nullptr; }
		const char *description() const { return m_description; }
		const char *value() const { return m_data.c_str(); }
		const char *default_value() const { return m_defdata.c_str(); }
		const char *minimum() const { return m_minimum.c_str(); }
		const char *maximum() const { return m_maximum.c_str(); }
		int type() const { return (m_flags & OPTION_TYPE_MASK); }
		uint32_t flags() const { return m_flags; }
		bool is_header() const { return type() == OPTION_HEADER; }
		bool is_command() const { return type() == OPTION_COMMAND; }
		bool is_internal() const { return m_flags & OPTION_FLAG_INTERNAL; }
		bool has_range() const { return (!m_minimum.empty() && !m_maximum.empty()); }
		int priority() const { return m_priority; }
		bool is_changed() const { return m_changed; }

		// setters
		void set_value(const char *newvalue, int priority);
		void set_default_value(const char *defvalue);
		void set_description(const char *description);
		void set_flag(uint32_t mask, uint32_t flag);
		void mark_changed() { m_changed = true; }
		void revert(int priority_hi, int priority_lo);

	private:
		// internal state
		entry *                 m_next;             // link to the next data
		uint32_t                  m_flags;            // flags from the entry
		bool                    m_error_reported;   // have we reported an error on this option yet?
		int                     m_priority;         // priority of the data set
		const char *            m_description;      // description for this item
		std::string             m_name[4];          // up to 4 names for the item
		std::string             m_data;             // data for this item
		std::string             m_defdata;          // default data for this item
		std::string             m_minimum;          // minimum value
		std::string             m_maximum;          // maximum value
		bool                    m_changed;          // changed flag
	};

	// construction/destruction
	core_options();
	core_options(const options_entry *entrylist);
	core_options(const options_entry *entrylist1, const options_entry *entrylist2);
	core_options(const options_entry *entrylist1, const options_entry *entrylist2, const options_entry *entrylist3);
	core_options(const core_options &src);
	virtual ~core_options();

	// operators
	core_options &operator=(const core_options &rhs);
	bool operator==(const core_options &rhs);
	bool operator!=(const core_options &rhs);

	// getters
	entry *first() const { return m_entrylist.first(); }
	const std::string &command() const { return m_command; }
	entry *get_entry(const char *name) const;

	// range iterators
	using auto_iterator = simple_list<entry>::auto_iterator;
	auto_iterator begin() const { return m_entrylist.begin(); }
	auto_iterator end() const { return m_entrylist.end(); }

	// configuration
	void add_entry(const char *name, const char *description, uint32_t flags = 0, const char *defvalue = nullptr, bool override_existing = false);
	void add_entry(const options_entry &data, bool override_existing = false) { add_entry(data.name, data.description, data.flags, data.defvalue, override_existing); }
	void add_entries(const options_entry *entrylist, bool override_existing = false);
	void set_default_value(const char *name, const char *defvalue);
	void set_description(const char *name, const char *description);
	void remove_entry(entry &delentry);

	// parsing/input
	bool parse_command_line(std::vector<std::string> &args, int priority, std::string &error_string);
	bool parse_ini_file(util::core_file &inifile, int priority, int ignore_priority, std::string &error_string);
	bool pluck_from_command_line(std::vector<std::string> &args, const std::string &name, std::string &result);

	// reverting
	void revert(int priority_hi = OPTION_PRIORITY_MAXIMUM, int priority_lo = OPTION_PRIORITY_DEFAULT);

	// output
	std::string output_ini(const core_options *diff = nullptr) const;
	std::string output_help() const;

	// reading
	const char *value(const char *option) const;
	const char *description(const char *option) const;
	int priority(const char *option) const;
	bool bool_value(const char *name) const { return (atoi(value(name)) != 0); }
	int int_value(const char *name) const { return atoi(value(name)); }
	float float_value(const char *name) const { return atof(value(name)); }
	bool exists(const char *name) const;

	// setting
	bool set_value(const char *name, const char *value, int priority, std::string &error_string);
	bool set_value(const char *name, int value, int priority, std::string &error_string);
	bool set_value(const char *name, float value, int priority, std::string &error_string);
	void set_flag(const char *name, uint32_t mask, uint32_t flags);
	void mark_changed(const char *name);

	// misc
	static const char *unadorned(int x = 0) { return s_option_unadorned[std::min(x, MAX_UNADORNED_OPTIONS - 1)]; }
	int options_count() const { return m_entrylist.count(); }

protected:
	// This is a hook to allow option value retrieval to be overridden for various reasons; this is a crude
	// extensibility mechanism that should really be replaced by something better
	enum class override_get_value_result
	{
		NONE,
		OVERRIDE,
		SKIP
	};

	virtual void value_changed(const std::string &name, const std::string &value) {}
	virtual override_get_value_result override_get_value(const char *name, std::string &value) const { return override_get_value_result::NONE; }
	virtual bool override_set_value(const char *name, const std::string &value) { return false; }

private:
	// internal helpers
	void reset();
	void append_entry(entry &newentry);
	void copyfrom(const core_options &src);
	bool validate_and_set_data(entry &curentry, std::string &&newdata, int priority, std::string &error_string);

	// internal state
	simple_list<entry>      m_entrylist;            // head of list of entries
	std::unordered_map<std::string,entry *>       m_entrymap;             // map for fast lookup
	std::string             m_command;              // command found
	static const char *const s_option_unadorned[];  // array of unadorned option "names"
};



#endif // MAME_LIB_UTIL_OPTIONS_H