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
13namespace Lexilla {
14
15template <typename T>
16class 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 }
85public:
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