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