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
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
|
// license:BSD-3-Clause
// copyright-holders:Wilbert Pol
/*********************************************************************
softlist.h
Software list file format.
*********************************************************************/
#ifndef __SOFTLIST_H_
#define __SOFTLIST_H_
#include <list>
#include "romentry.h"
#include "corefile.h"
//**************************************************************************
// CONSTANTS
//**************************************************************************
#define SOFTWARE_SUPPORTED_YES 0
#define SOFTWARE_SUPPORTED_PARTIAL 1
#define SOFTWARE_SUPPORTED_NO 2
//**************************************************************************
// TYPE DEFINITIONS
//**************************************************************************
struct XML_ParserStruct;
class software_info;
// ======================> feature_list_item
// an item in a list of name/value pairs
class feature_list_item
{
public:
// construction/destruction
feature_list_item(std::string &&name, std::string &&value);
feature_list_item(const std::string &name, const std::string &value);
feature_list_item(feature_list_item const &) = delete;
feature_list_item(feature_list_item &&) = delete;
feature_list_item& operator=(feature_list_item const &) = delete;
feature_list_item& operator=(feature_list_item &&) = delete;
// getters
feature_list_item *next() const { return m_next; }
const std::string &name() const { return m_name; }
const std::string &value() const { return m_value; }
private:
// internal state
feature_list_item * m_next;
std::string m_name;
std::string m_value;
};
// ======================> software_part
// a single part of a software item
class software_part
{
friend class softlist_parser;
public:
// construction/destruction
software_part(software_info &info, std::string &&name, std::string &&interface);
software_part(software_part const &) = delete;
software_part(software_part &&) = delete;
software_part& operator=(software_part const &) = delete;
software_part& operator=(software_part &&) = delete;
// getters
software_part *next() const { return m_next; }
software_info &info() const { return m_info; }
const std::string &name() const { return m_name; }
const std::string &interface() const { return m_interface; }
const std::list<feature_list_item> &featurelist() const { return m_featurelist; }
const std::vector<rom_entry> &romdata() const { return m_romdata; }
// helpers
bool matches_interface(const char *interface) const;
const char *feature(const std::string &feature_name) const;
private:
// internal state
software_part * m_next;
software_info & m_info;
std::string m_name;
std::string m_interface;
std::list<feature_list_item> m_featurelist;
std::vector<rom_entry> m_romdata;
};
// ======================> software_info
// a single software item
class software_info
{
friend class softlist_parser;
public:
// construction/destruction
software_info(std::string &&name, std::string &&parent, const std::string &supported);
software_info(software_info const &) = delete;
software_info(software_info &&) = delete;
software_info& operator=(software_info const &) = delete;
software_info& operator=(software_info &&) = delete;
// getters
const std::string &shortname() const { return m_shortname; }
const std::string &longname() const { return m_longname; }
const std::string &parentname() const { return m_parentname; }
const std::string &year() const { return m_year; }
const std::string &publisher() const { return m_publisher; }
const std::list<feature_list_item> &other_info() const { return m_other_info; }
const std::list<feature_list_item> &shared_info() const { return m_shared_info; }
UINT32 supported() const { return m_supported; }
const std::list<software_part> &parts() const { return m_partdata; }
// additional operations
const software_part *find_part(const std::string &partname, const char *interface = nullptr) const;
bool has_multiple_parts(const char *interface) const;
private:
// internal state
UINT32 m_supported;
std::string m_shortname;
std::string m_longname;
std::string m_parentname;
std::string m_year; // Copyright year on title screen, actual release dates can be tracked in external resources
std::string m_publisher;
std::list<feature_list_item> m_other_info; // Here we store info like developer, serial #, etc. which belong to the software entry as a whole
std::list<feature_list_item> m_shared_info; // Here we store info like TV standard compatibility, or add-on requirements, etc. which get inherited
// by each part of this software entry (after loading these are stored in partdata->featurelist)
std::list<software_part> m_partdata;
};
// ======================> softlist_parser
class softlist_parser
{
public:
// construction (== execution)
softlist_parser(util::core_file &file, const std::string &filename, std::string &description, std::list<software_info> &infolist, std::ostringstream &errors);
private:
enum parse_position
{
POS_ROOT,
POS_MAIN,
POS_SOFT,
POS_PART,
POS_DATA
};
// internal parsing helpers
const char *infoname() const { return (m_current_info != nullptr) ? m_current_info->shortname().c_str() : "???"; }
int line() const;
int column() const;
const char *parser_error() const;
// internal error helpers
template <typename Format, typename... Params> void parse_error(Format &&fmt, Params &&... args);
void unknown_tag(const char *tagname) { parse_error("Unknown tag: %s", tagname); }
void unknown_attribute(const char *attrname) { parse_error("Unknown attribute: %s", attrname); }
// internal helpers
template <typename T> std::vector<std::string> parse_attributes(const char **attributes, const T &attrlist);
bool parse_name_and_value(const char **attributes, std::string &name, std::string &value);
void add_rom_entry(std::string &&name, std::string &&hashdata, UINT32 offset, UINT32 length, UINT32 flags);
// expat callbacks
static void start_handler(void *data, const char *tagname, const char **attributes);
static void data_handler(void *data, const char *s, int len);
static void end_handler(void *data, const char *name);
// internal parsing
void parse_root_start(const char *tagname, const char **attributes);
void parse_main_start(const char *tagname, const char **attributes);
void parse_soft_start(const char *tagname, const char **attributes);
void parse_part_start(const char *tagname, const char **attributes);
void parse_data_start(const char *tagname, const char **attributes);
void parse_soft_end(const char *name);
// internal parsing state
util::core_file & m_file;
std::string m_filename;
std::list<software_info> & m_infolist;
std::ostringstream & m_errors;
struct XML_ParserStruct * m_parser;
bool m_done;
std::string & m_description;
bool m_data_accum_expected;
std::string m_data_accum;
software_info * m_current_info;
software_part * m_current_part;
parse_position m_pos;
};
#endif // __SOFTLIST_H_
|