summaryrefslogtreecommitdiffstatshomepage
path: root/src/osd/interface/inputseq.h
blob: 62704462d47bfb852c2cfbe37ae8f67e6cddd562 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
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
// license:BSD-3-Clause
// copyright-holders:Aaron Giles
/***************************************************************************

    inputseq.h

    A combination of hosts inputs that can be assigned to a control.

***************************************************************************/
#ifndef MAME_OSD_INTERFACE_INPUTSEQ_H
#define MAME_OSD_INTERFACE_INPUTSEQ_H

#pragma once

#include "inputcode.h"

#include <algorithm>
#include <array>
#include <cassert>
#include <utility>


namespace osd {

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

// a combination of input_codes, supporting AND/OR and inversion

class input_seq
{
public:
	// construction/destruction
	input_seq() noexcept : input_seq(std::make_index_sequence<std::tuple_size<decltype(m_code)>::value>())
	{
	}
	template <typename... T>
	input_seq(input_code code_0, T... code_n) noexcept :
		input_seq(std::make_index_sequence<std::tuple_size<decltype(m_code)>::value - sizeof...(T) - 1>(), code_0, code_n...)
	{
	}
	constexpr input_seq(const input_seq &rhs) noexcept = default;

	// operators
	bool operator==(const input_seq &rhs) const noexcept { return m_code == rhs.m_code; }
	bool operator!=(const input_seq &rhs) const noexcept { return m_code != rhs.m_code; }
	constexpr input_code operator[](int index) const noexcept { return (index >= 0 && index < m_code.size()) ? m_code[index] : end_code; }
	input_seq &operator+=(input_code code) noexcept;
	input_seq &operator|=(input_code code) noexcept;

	// getters
	constexpr bool empty() const noexcept { return m_code[0] == end_code; }
	constexpr int max_size() const noexcept { return std::tuple_size<decltype(m_code)>::value; }
	int length() const noexcept;
	bool is_valid() const noexcept;
	constexpr bool is_default() const noexcept { return m_code[0] == default_code; }

	// setters
	template <typename... T> void set(input_code code_0, T... code_n) noexcept
	{
		static_assert(sizeof...(T) < std::tuple_size<decltype(m_code)>::value, "too many codes for input_seq");
		set<0>(code_0, code_n...);
	}
	void reset() noexcept { set(end_code); }
	void set_default() noexcept { set(default_code); }
	void backspace() noexcept;
	void replace(input_code oldcode, input_code newcode) noexcept;

	// constant codes used in sequences
	static constexpr input_code end_code { DEVICE_CLASS_INTERNAL, 0, ITEM_CLASS_INVALID, ITEM_MODIFIER_NONE, ITEM_ID_SEQ_END };
	static constexpr input_code default_code { DEVICE_CLASS_INTERNAL, 0, ITEM_CLASS_INVALID, ITEM_MODIFIER_NONE, ITEM_ID_SEQ_DEFAULT };
	static constexpr input_code not_code { DEVICE_CLASS_INTERNAL, 0, ITEM_CLASS_INVALID, ITEM_MODIFIER_NONE, ITEM_ID_SEQ_NOT };
	static constexpr input_code or_code { DEVICE_CLASS_INTERNAL, 0, ITEM_CLASS_INVALID, ITEM_MODIFIER_NONE, ITEM_ID_SEQ_OR };

	// constant sequences
	static const input_seq empty_seq;

private:
	static constexpr input_code get_end_code(size_t) noexcept { return end_code; }

	template <size_t... N, typename... T>
	input_seq(std::integer_sequence<size_t, N...>, T... code) noexcept : m_code({ code..., get_end_code(N)... })
	{
	}
	template <size_t... N>
	input_seq(std::integer_sequence<size_t, N...>) noexcept : m_code({ get_end_code(N)... })
	{
	}

	template <unsigned N> void set() noexcept
	{
		std::fill(std::next(m_code.begin(), N), m_code.end(), end_code);
	}
	template <unsigned N, typename... T> void set(input_code code_0, T... code_n) noexcept
	{
		m_code[N] = code_0;
		set<N + 1>(code_n...);
	}

	// internal state
	std::array<input_code, 16> m_code;
};

}  // namespace osd

#endif // MAME_OSD_INTERFACE_INPUTSEQ_H