00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 #pragma once
00022 
00030 #include <cstring>
00031 #include <string>
00032 #include <vector>
00033 
00034 #include "Assert.h"
00035 #include "CommandBinding.h"
00036 
00043 template<typename T>
00044 class CommandTable
00045 {
00046         typedef CommandBinding<T> Binding; 
00047         typedef CommandObject<T> Object; 
00049 public:
00051         CommandTable(const Binding* bindings, const unsigned int n);
00052         
00054         virtual ~CommandTable();
00055 
00056         
00058         const Binding* getBinding(const std::string& action);
00059         
00061         const Object* getObject(const std::string& action);
00062 
00063 
00065         const std::vector<std::string>& getCommandsVector() const;
00066 
00067 private:
00068         const Binding* m_bindings; 
00069         const unsigned int m_n; 
00070         std::vector<std::string> m_words; 
00071 };
00072 
00073 template<typename T>
00074 CommandTable<T>::CommandTable(const Binding* bindings, const unsigned int n):
00075         m_bindings(bindings),
00076         m_n(n),
00077         m_words(n)
00078 {
00079         
00080         for(unsigned int i = 1; i < m_n; ++i)
00081                 Assert(std::strcmp(m_bindings[i - 1].m_alias, m_bindings[i].m_alias) < 0);
00082         
00083         for(unsigned int i = 0; i < m_n; ++i)
00084                 m_words[i] = m_bindings[i].m_alias;
00085 }
00086 
00087 template<typename T>
00088 CommandTable<T>::~CommandTable()
00089 {
00090 }
00091 
00092 static bool
00093 string_lt_partial(const char* a, const char* b)
00094 {
00095         while(*a && *b && *a == *b) {
00096                 ++a;
00097                 ++b;
00098         }
00099 
00100         if(*a < *b && *b)
00101                 return true;
00102                 
00103         return false;
00104 }
00105 
00106 static bool
00107 string_eq_partial(const char* a, const char* b)
00108 {
00109         while(*a && *b && *a == *b) {
00110                 ++a;
00111                 ++b;
00112         }
00113 
00114         if(*a == *b || !*b)
00115                 return true;
00116                 
00117         return false;
00118 }
00119 
00120 template<typename T>
00121 const CommandBinding<T>*
00122 CommandTable<T>::getBinding(const std::string& action)
00123 {
00124         const char* word = action.c_str();
00125         unsigned int left = 0;
00126         unsigned int right = m_n;
00127 
00128         while(left < right) {
00129                 unsigned int modus = left + (right - left) / 2;
00130                 if(string_lt_partial(m_bindings[modus].m_alias, word))
00131                         left = modus + 1;
00132                 else
00133                         right = modus;
00134         }
00135 
00136         if(left < m_n)
00137         {
00138                 CommandBinding<T> command = m_bindings[left];
00139                 if(command.fullName())
00140                 {
00141                         if(!strncmp(command.m_alias, word, action.size()))
00142                                 return &m_bindings[left];
00143                 }
00144                 else
00145                 {
00146                         if(string_eq_partial(command.m_alias, word))
00147                                 return &m_bindings[left];
00148                 }
00149         }
00150 
00151         return NULL;
00152 }
00153 
00154 template<typename T>
00155 const CommandObject<T>*
00156 CommandTable<T>::getObject(const std::string& action)
00157 {
00158         const CommandBinding<T>* b = getBinding(action);
00159         if(!b)
00160                 return NULL;
00161 
00162         return &b->getCommand();
00163 }
00164 
00165 template<typename T>
00166 const std::vector<std::string>&
00167 CommandTable<T>::getCommandsVector() const
00168 {
00169         return m_words;
00170 }