1 #include <iterator>
2 #include <vector>
3 #include <utility>
4 #include <algorithm>
5
6 #include "ADM_default.h"
7 #include "gui_action.hxx"
8
9 using std::vector;
10 using std::pair;
11 using std::make_pair;
12 using std::back_inserter;
13 using std::transform;
14 using std::sort;
15 using std::equal_range;
16
17 struct ActionNameNum
18 {
19 const Action num;
20 const char * const name;
21 };
22
23 // The getActionName() function assumes that the following array is sorted by
24 // action number, and further that it can be indexed by action number based on
25 // the action number of the first entry.
26
27 const ActionNameNum action_names [] =
28 {
29 #define ACT(_name) { ACT_ ## _name, # _name },
30 #include "gui_action.names"
31 #undef ACT
32 // { ACT_INVALID, 0 }
33 };
34
35 const int ACTION_NAME_COUNT = sizeof (action_names) / sizeof (action_names[0]);
36
37 // One might think to use a map here, instead of a vector (and in fact I did),
38 // but Scott Meyers in _Effective STL_ advises (in item 23) that it is more
39 // efficient to use a sorted vector when we are doing a bunch of insertions
40 // followed by mostly (in our case exclusively) lookups.
41
42 typedef pair <const char *, Action> ActionNamePair;
43 typedef vector <ActionNamePair> ActionNameVec;
44 typedef ActionNameVec::iterator ActionNameIter;
45
46 class ActionNameCompare
47 {
48 public:
operator ()(const ActionNamePair & lhs,const ActionNamePair & rhs) const49 bool operator () (const ActionNamePair & lhs, // for sorting
50 const ActionNamePair & rhs) const
51 {
52 return doLess (lhs.first, rhs.first);
53 }
54
operator ()(const ActionNamePair & lhs,const ActionNamePair::first_type & rhs) const55 bool operator () (const ActionNamePair & lhs, // for lookups 1
56 const ActionNamePair::first_type & rhs) const
57 {
58 return doLess (lhs.first, rhs);
59 }
60
operator ()(const ActionNamePair::first_type & lhs,const ActionNamePair & rhs) const61 bool operator () (const ActionNamePair::first_type & lhs, // for lookups 2
62 const ActionNamePair & rhs) const
63 {
64 return doLess (lhs, rhs.first);
65 }
66
67 private:
68
doLess(const ActionNamePair::first_type & lhs,const ActionNamePair::first_type & rhs) const69 bool doLess (const ActionNamePair::first_type & lhs,
70 const ActionNamePair::first_type & rhs) const
71 {
72 return (strcasecmp (lhs, rhs) < 0);
73 }
74 };
75
76 class MakeActionNamePair
77 {
78 public:
operator ()(const ActionNameNum & ann)79 ActionNamePair operator () (const ActionNameNum & ann)
80 {
81 return make_pair (ann.name, ann.num);
82 }
83 };
84
85 static ActionNameVec action_name_vec;
86
initActionNameVec(void)87 void initActionNameVec (void)
88 {
89 action_name_vec.reserve (ACTION_NAME_COUNT);
90 transform (action_names, action_names + ACTION_NAME_COUNT,
91 back_inserter (action_name_vec), MakeActionNamePair());
92 sort (action_name_vec.begin(), action_name_vec.end(),
93 ActionNameCompare());
94 }
95
lookupActionByName(const char * name)96 Action lookupActionByName (const char * name)
97 {
98 if (action_name_vec.empty())
99 initActionNameVec();
100
101 pair <ActionNameIter, ActionNameIter> range
102 = equal_range (action_name_vec.begin(),
103 action_name_vec.end(), name,
104 ActionNameCompare());
105 if (range.first == range.second)
106 return ACT_INVALID;
107 else
108 return range.first->second;
109 }
110
getActionName(Action act)111 const char * getActionName (Action act)
112 {
113 if(act==ACT_DUMMY) return "ACT_DUMMY";
114 if(act>=ACT_SCRIPT_ENGINE_SHELL_FIRST) return "ACT_SCRIPT_ENGINE_SHELL";
115 if(act>=ACT_SCRIPT_ENGINE_FIRST) return "ACT_SCRIPT_ENGINE";
116
117 uint32_t index = act - action_names [0].num;
118 return (action_names [index].name);
119 }
120
dumpActionNames(const char * filename)121 void dumpActionNames (const char * filename)
122 {
123 if (action_name_vec.empty())
124 initActionNameVec();
125
126 printf ("# Action names (which can be used in %s, "
127 "though some should not be):\n", filename);
128 ActionNameIter it = action_name_vec.begin();
129 while (it != action_name_vec.end())
130 {
131 printf ("# %s\n", it->first);
132 ++it;
133 }
134 }
135