1 | // Scintilla source code edit control |
2 | /** @file OptionSet.h |
3 | ** Manage descriptive information about an options struct for a lexer. |
4 | ** Hold the names, positions, and descriptions of boolean, integer and string options and |
5 | ** allow setting options and retrieving metadata about the options. |
6 | **/ |
7 | // Copyright 2010 by Neil Hodgson <neilh@scintilla.org> |
8 | // The License.txt file describes the conditions under which this software may be distributed. |
9 | |
10 | #ifndef OPTIONSET_H |
11 | #define OPTIONSET_H |
12 | |
13 | namespace Lexilla { |
14 | |
15 | template <typename T> |
16 | class OptionSet { |
17 | typedef T Target; |
18 | typedef bool T::*plcob; |
19 | typedef int T::*plcoi; |
20 | typedef std::string T::*plcos; |
21 | struct Option { |
22 | int opType; |
23 | union { |
24 | plcob pb; |
25 | plcoi pi; |
26 | plcos ps; |
27 | }; |
28 | std::string value; |
29 | std::string description; |
30 | Option() : |
31 | opType(SC_TYPE_BOOLEAN), pb(0), description("" ) { |
32 | } |
33 | Option(plcob pb_, std::string description_="" ) : |
34 | opType(SC_TYPE_BOOLEAN), pb(pb_), description(description_) { |
35 | } |
36 | Option(plcoi pi_, std::string description_) : |
37 | opType(SC_TYPE_INTEGER), pi(pi_), description(description_) { |
38 | } |
39 | Option(plcos ps_, std::string description_) : |
40 | opType(SC_TYPE_STRING), ps(ps_), description(description_) { |
41 | } |
42 | bool Set(T *base, const char *val) { |
43 | value = val; |
44 | switch (opType) { |
45 | case SC_TYPE_BOOLEAN: { |
46 | bool option = atoi(val) != 0; |
47 | if ((*base).*pb != option) { |
48 | (*base).*pb = option; |
49 | return true; |
50 | } |
51 | break; |
52 | } |
53 | case SC_TYPE_INTEGER: { |
54 | int option = atoi(val); |
55 | if ((*base).*pi != option) { |
56 | (*base).*pi = option; |
57 | return true; |
58 | } |
59 | break; |
60 | } |
61 | case SC_TYPE_STRING: { |
62 | if ((*base).*ps != val) { |
63 | (*base).*ps = val; |
64 | return true; |
65 | } |
66 | break; |
67 | } |
68 | } |
69 | return false; |
70 | } |
71 | const char *Get() const noexcept { |
72 | return value.c_str(); |
73 | } |
74 | }; |
75 | typedef std::map<std::string, Option, std::less<>> OptionMap; |
76 | OptionMap nameToDef; |
77 | std::string names; |
78 | std::string wordLists; |
79 | |
80 | void AppendName(const char *name) { |
81 | if (!names.empty()) |
82 | names += "\n" ; |
83 | names += name; |
84 | } |
85 | public: |
86 | void DefineProperty(const char *name, plcob pb, std::string description="" ) { |
87 | nameToDef[name] = Option(pb, description); |
88 | AppendName(name); |
89 | } |
90 | void DefineProperty(const char *name, plcoi pi, std::string description="" ) { |
91 | nameToDef[name] = Option(pi, description); |
92 | AppendName(name); |
93 | } |
94 | void DefineProperty(const char *name, plcos ps, std::string description="" ) { |
95 | nameToDef[name] = Option(ps, description); |
96 | AppendName(name); |
97 | } |
98 | const char *PropertyNames() const noexcept { |
99 | return names.c_str(); |
100 | } |
101 | int PropertyType(const char *name) { |
102 | typename OptionMap::iterator it = nameToDef.find(name); |
103 | if (it != nameToDef.end()) { |
104 | return it->second.opType; |
105 | } |
106 | return SC_TYPE_BOOLEAN; |
107 | } |
108 | const char *DescribeProperty(const char *name) { |
109 | typename OptionMap::iterator it = nameToDef.find(name); |
110 | if (it != nameToDef.end()) { |
111 | return it->second.description.c_str(); |
112 | } |
113 | return "" ; |
114 | } |
115 | |
116 | bool PropertySet(T *base, const char *name, const char *val) { |
117 | typename OptionMap::iterator it = nameToDef.find(name); |
118 | if (it != nameToDef.end()) { |
119 | return it->second.Set(base, val); |
120 | } |
121 | return false; |
122 | } |
123 | |
124 | const char *PropertyGet(const char *name) { |
125 | typename OptionMap::iterator it = nameToDef.find(name); |
126 | if (it != nameToDef.end()) { |
127 | return it->second.Get(); |
128 | } |
129 | return nullptr; |
130 | } |
131 | |
132 | void DefineWordListSets(const char * const wordListDescriptions[]) { |
133 | if (wordListDescriptions) { |
134 | for (size_t wl = 0; wordListDescriptions[wl]; wl++) { |
135 | if (!wordLists.empty()) |
136 | wordLists += "\n" ; |
137 | wordLists += wordListDescriptions[wl]; |
138 | } |
139 | } |
140 | } |
141 | |
142 | const char *DescribeWordListSets() const noexcept { |
143 | return wordLists.c_str(); |
144 | } |
145 | }; |
146 | |
147 | } |
148 | |
149 | #endif |
150 | |