Only allow this language: ((n|s)!(w|e)!(u|d)!;)+ for directions.
[UnsignedByte.git] / src / Core / Command / CommandTable.h
blob61e9d70c6e8a1320e14f4a5107c8031480fd6e30
1 /***************************************************************************
2 * Copyright (C) 2008 by Vegard Nossum *
3 * vegard.nossum@gmail.com *
4 * *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 3 of the License, or *
8 * (at your option) any later version. *
9 * *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
14 * *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program; if not, write to the *
17 * Free Software Foundation, Inc., *
18 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
19 ***************************************************************************/
21 #pragma once
23 /**
24 * @file CommandTable.h
25 * This file contains the CommandTable template.
27 * @see CommandTable
28 */
30 #include <cstring>
31 #include <string>
32 #include <vector>
34 #include "Assert.h"
35 #include "CommandBinding.h"
37 /**
38 * This class performs lookup of input to commands.
40 * The lookup performs a binary search on the bindings table.
41 * It also checks for partial matches.
42 */
43 template<typename T>
44 class CommandTable
46 typedef CommandBinding<T> Binding; /**< The type of a binding to a specific clsas. */
47 typedef CommandObject<T> Object; /**< The type of a CommandObject of a specific class. */
49 public:
50 /** Constructs a CommandTable using the specified bindings table that is of the specified size.*/
51 CommandTable(const Binding* bindings, const unsigned int n);
53 /** Destructor, a noop. */
54 virtual ~CommandTable();
57 /** Performs a lookup on the specified word and returns the associated binding. */
58 const Binding* getBinding(const std::string& action);
60 /** Performs a lookup on the specified word and returns the associated object. */
61 const Object* getObject(const std::string& action);
64 /** Returns a list of known commands. */
65 const std::vector<std::string>& getCommandsVector() const;
67 private:
68 const Binding* m_bindings; /**< The bindings we search on. */
69 const unsigned int m_n; /**< The size of the bindings. */
70 std::vector<std::string> m_words; /**< The list of known commands. */
73 template<typename T>
74 CommandTable<T>::CommandTable(const Binding* bindings, const unsigned int n):
75 m_bindings(bindings),
76 m_n(n),
77 m_words(n)
79 /* Make sure the table is sorted. If it isn't, binary search won't work. */
80 for(unsigned int i = 1; i < m_n; ++i)
81 Assert(std::strcmp(m_bindings[i - 1].m_alias, m_bindings[i].m_alias) < 0);
83 for(unsigned int i = 0; i < m_n; ++i)
84 m_words[i] = m_bindings[i].m_alias;
87 template<typename T>
88 CommandTable<T>::~CommandTable()
92 static bool
93 string_lt_partial(const char* a, const char* b)
95 while(*a && *b && *a == *b) {
96 ++a;
97 ++b;
100 if(*a < *b && *b)
101 return true;
103 return false;
106 static bool
107 string_eq_partial(const char* a, const char* b)
109 while(*a && *b && *a == *b) {
110 ++a;
111 ++b;
114 if(*a == *b || !*b)
115 return true;
117 return false;
120 template<typename T>
121 const CommandBinding<T>*
122 CommandTable<T>::getBinding(const std::string& action)
124 const char* word = action.c_str();
125 unsigned int left = 0;
126 unsigned int right = m_n;
128 while(left < right) {
129 unsigned int modus = left + (right - left) / 2;
130 if(string_lt_partial(m_bindings[modus].m_alias, word))
131 left = modus + 1;
132 else
133 right = modus;
136 if(left < m_n)
138 CommandBinding<T> command = m_bindings[left];
139 if(command.fullName())
141 if(!strncmp(command.m_alias, word, action.size()))
142 return &m_bindings[left];
144 else
146 if(string_eq_partial(command.m_alias, word))
147 return &m_bindings[left];
151 return NULL;
154 template<typename T>
155 const CommandObject<T>*
156 CommandTable<T>::getObject(const std::string& action)
158 const CommandBinding<T>* b = getBinding(action);
159 if(!b)
160 return NULL;
162 return &b->getCommand();
165 template<typename T>
166 const std::vector<std::string>&
167 CommandTable<T>::getCommandsVector() const
169 return m_words;