summaryrefslogtreecommitdiffstatshomepage
path: root/src/emu/ui/filemngr.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/emu/ui/filemngr.cpp')
0 files changed, 0 insertions, 0 deletions
#n52'>52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274
// license:BSD-3-Clause
// copyright-holders:Nathan Woods
/****************************************************************************

    opresolv.h

    Extensible ranged option resolution handling

    An extensible mechanism for handling options is a major need in MESS and
    Imgtool.  Unfortunately, since we are using straight C for everything, it
    can be hard and awkward to create non-arcane mechanisms for representing
    these options.

    In this system, we have the following concepts:
    1.  An "option specification"; a string that represents what options are
        available, their defaults, and their allowed ranges.  Here is an
        example:

        Examples:
            "H[1]-2;T[35]/40/80;S[18]"
                Allow 1-2 heads; 35, 40 or 80 tracks, and 18 sectors,
                defaulting to 1 heads and 35 tracks.

            "N'Simon''s desk'"
                Simon's desk (strings are not subject to range checking)

    2.  An "option guide"; a struct that provides information about what the
        various members of the option specification mean (i.e. - H=heads)

    3.  An "option resolution"; an object that represents a set of interpreted
        options.  At this stage, the option bid has been processed and it is
        guaranteed that all options reside in their expected ranges.

    An option_resolution object is created based on an option guide and an
    option specification.  It is then possible to specify individual parameters
    to the option_resolution object.  Argument checks occur at this time.  When
    one is all done, you can then query the object for any given value.

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

#ifndef __OPRESOLV_H__
#define __OPRESOLV_H__

#include <stdlib.h>
#include <vector>
#include <string>


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

#define OPTION_GUIDE_START(option_guide_)														\
	namespace option_guide_impl_##option_guide_													\
	{																							\
		static const util::option_guide &get();													\
	};																							\
	const util::option_guide &option_guide_ = option_guide_impl_##option_guide_::get();			\
	namespace option_guide_impl_##option_guide_													\
	{																							\
		static const auto actual = util::make_option_guide(0
#define OPTION_GUIDE_END																		\
		);																						\
		static const util::option_guide &get() { return actual; }								\
	};	
#define OPTION_GUIDE_EXTERN(option_guide_)														\
	extern const util::option_guide &option_guide_
#define OPTION_INT(option_char, identifier, display_name)										\
	,util::option_guide::entry(util::option_guide::entry::option_type::INT, (option_char), (identifier), (display_name))
#define OPTION_STRING(option_char, identifier, display_name)                					\
	,util::option_guide::entry(util::option_guide::entry::option_type::STRING, (option_char), (identifier), (display_name))
#define OPTION_ENUM_START(option_char, identifier, display_name)            					\
	,util::option_guide::entry(util::option_guide::entry::option_type::ENUM_BEGIN, (option_char), (identifier), (display_name))
#define OPTION_ENUM(value, identifier, display_name)                        					\
	,util::option_guide::entry(util::option_guide::entry::option_type::ENUM_VALUE, (value), (identifier), (display_name))
#define OPTION_ENUM_END

namespace util {

// ======================> option_guide

class option_guide
{
public:
	class entry
	{
	public:
		enum class option_type
		{
			INVALID,
			INT,
			STRING,
			ENUM_BEGIN,
			ENUM_VALUE
		};

		constexpr entry()
			: m_type(option_type::INVALID), m_parameter(0), m_identifier(nullptr), m_display_name(nullptr)
		{
		}

		constexpr entry(option_type type, int parameter = 0, const char *identifier = nullptr, const char *display_name = nullptr)
			: m_type(type), m_parameter(parameter), m_identifier(identifier), m_display_name(display_name)
		{
		}

		// accessors
		const option_type type() const { return m_type; }
		int parameter() const { return m_parameter; }
		const char *identifier() const { return m_identifier; }
		const char *display_name() const { return m_display_name; }
	
	private:
		option_type	m_type;
		int			m_parameter;
		const char *m_identifier;
		const char *m_display_name;
	};

	// methods
	const entry *begin() const { return m_begin; }
	const entry *end() const { return m_end; }

protected:
	option_guide(const entry *begin, const entry *end)
		: m_begin(begin), m_end(end)
	{
	}


private:
	const entry *m_begin;
	const entry *m_end;
};

// ======================> option_guide_impl

template <std::size_t Count>
class option_guide_impl : protected std::array<option_guide::entry, Count>, public option_guide
{
public:
	template<typename... T>
	option_guide_impl(T &&... elems)
		: std::array<option_guide::entry, Count>({ std::forward<T>(elems)... })
		, option_guide(Count > 0 ? &(*this)[0] : nullptr, Count > 0 ? &(*this)[0] + Count : nullptr)
	{
	}
};

template <typename... T>
option_guide_impl<sizeof...(T)> make_option_guide(int dummy, T &&... elems)
{
	return option_guide_impl<sizeof...(T)>(std::forward<T>(elems)...);
}


// ======================> option_resolution

class option_resolution
{
public:
	// TODO - audit unused parameters
	enum class error
	{
		SUCCESS,
		OUTOFMEMORY,
		PARAMOUTOFRANGE,
		PARAMNOTSPECIFIED,
		PARAMNOTFOUND,
		PARAMALREADYSPECIFIED,
		BADPARAM,
		SYNTAX,
		INTERNAL
	};

	template<typename T>
	struct range
	{
		range() { min = -1; max = -1; }
		T min, max;
	};

	// class to represent specific entry
	class entry
	{
		friend class option_resolution;

	public:
		typedef std::vector<range<int> > rangelist;

		// ctor
		entry(const option_guide::entry &guide_entry);

		// returns true if this entry is subject to range constraints
		bool is_ranged() const { return !m_ranges.empty(); }

		// accessors
		bool is_pertinent() const { return m_is_pertinent; }
		const std::string &value() const;
		int value_int() const;
		const std::string &default_value() const { return m_default_value; }
		const rangelist &ranges() const { return m_ranges; }
		const option_guide::entry *enum_value_begin() const { return m_enum_value_begin; }
		const option_guide::entry *enum_value_end() const { return m_enum_value_end; }

		// accessors for guide data
		option_guide::entry::option_type option_type() const { return m_guide_entry.type(); }
		const char *display_name() const { return m_guide_entry.display_name(); }
		const char *identifier() const { return m_guide_entry.identifier(); }
		int parameter() const { return m_guide_entry.parameter(); }


		// mutators
		bool set_value(const std::string &value);
		bool set_value(int value) { return set_value(numeric_value(value)); }

		// higher level operations
		bool can_bump_lower() const;
		bool can_bump_higher() const;
		bool bump_lower();
		bool bump_higher();

	private:
		// references to the option guide
		const option_guide::entry &				m_guide_entry;
		const option_guide::entry *				m_enum_value_begin;
		const option_guide::entry *				m_enum_value_end;

		// runtime state
		bool									m_is_pertinent;
		std::string								m_value;
		std::string								m_default_value;
		rangelist								m_ranges;

		// methods
		void parse_specification(const char *specification);
		void set_enum_value_range(const option_guide::entry *begin, const option_guide::entry *end);
		static std::string numeric_value(int value);
		rangelist::const_iterator find_in_ranges(int value) const;
	};

	// ctor/dtor
	option_resolution(const option_guide &guide);
	~option_resolution();

	// sets a specification
	void set_specification(const std::string &specification);

	// entry lookup - note that we're not exposing m_entries directly because we don't really
	// have a way of making the list be immutable but the members be mutable at the same time
	std::vector<entry>::iterator entries_begin() { return m_entries.begin(); }
	std::vector<entry>::iterator entries_end() { return m_entries.end(); }
	entry *find(int parameter);
	entry *find(const std::string &identifier);
	int lookup_int(int parameter);
	const std::string &lookup_string(int parameter);

	// misc
	static const char *error_string(error err);
	static error get_default(const char *specification, int option_char, int *val);

private:
	std::vector<entry> m_entries;

	error set_parameter(std::vector<entry>::iterator iter, const std::string &value);

	static const char *lookup_in_specification(const char *specification, const option_guide::entry &option);
	const entry *lookup_entry(int option_char) const;
};


} // namespace util

#endif /* __OPRESOLV_H__ */