1 ////////////////////////////////////////////////////////////////////////////////
2 // Scorched3D (c) 2000-2009
4 // This file is part of Scorched3D.
6 // Scorched3D is free software; you can redistribute it and/or modify
7 // it under the terms of the GNU General Public License as published by
8 // the Free Software Foundation; either version 2 of the License, or
9 // (at your option) any later version.
11 // Scorched3D is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
16 // You should have received a copy of the GNU General Public License
17 // along with Scorched3D; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 ////////////////////////////////////////////////////////////////////////////////
21 #include <console/ConsoleRules.h>
22 #include <console/Console.h>
23 #include <common/Defines.h>
25 ConsoleRules::ConsoleRules()
30 ConsoleRules::~ConsoleRules()
35 void ConsoleRules::addRule(ConsoleRule
*rule
)
39 std::string addName
= rule
->getName();
40 _strlwr((char *) addName
.c_str());
41 rules_
.insert(std::pair
<std::string
, ConsoleRule
*>(addName
, rule
));
44 void ConsoleRules::removeRule(ConsoleRule
*rule
)
46 std::multimap
<std::string
, ConsoleRule
*>::iterator itor
;
47 for (itor
= rules_
.begin();
51 ConsoleRule
*r
= itor
->second
;
60 std::string
ConsoleRules::matchRule(const char *line
,
61 std::vector
<ConsoleRule
*> &matches
)
63 std::vector
<ConsoleRuleValue
> values
;
64 parseLine(line
, values
);
68 std::multimap
<std::string
, ConsoleRule
*>::iterator itor
;
69 for (itor
= rules_
.begin();
73 ConsoleRule
*rule
= itor
->second
;
74 matches
.push_back((*itor
).second
);
80 std::multimap
<std::string
, ConsoleRule
*>::iterator itor
;
81 for (itor
= rules_
.begin();
85 ConsoleRule
*rule
= itor
->second
;
86 ConsoleRuleValue
&nameValue
= values
[0];
88 if (values
.size() == 1)
90 unsigned int nameLen
= strlen(rule
->getName());
91 if (nameLen
>= nameValue
.valueString
.length() &&
92 _strnicmp(line
, rule
->getName(), nameValue
.valueString
.length()) == 0)
94 matches
.push_back((*itor
).second
);
99 if (0 == stricmp(rule
->getName(), nameValue
.valueString
.c_str()))
101 if (rule
->matchesPartialParams(values
))
103 matches
.push_back((*itor
).second
);
109 if (matches
.empty()) return "";
110 if (matches
.size() == 1) return matches
[0]->toString(values
);
112 ConsoleRuleValue
&firstValue
= values
[0];
113 for (int i
=(int) firstValue
.valueString
.length();; i
++)
115 ConsoleRule
*firstRule
= matches
[0];
116 for (int j
=0; j
<(int)matches
.size(); j
++)
118 ConsoleRule
*secondRule
= matches
[j
];
119 std::string firstString
= firstRule
->toString(values
);
120 std::string secondString
= secondRule
->toString(values
);
122 if ((int) strlen(secondString
.c_str()) < i
||
123 0 != _strnicmp(secondString
.c_str(), firstString
.c_str(), i
))
126 buffer
.append(secondString
.c_str(), i
- 1);
136 void ConsoleRules::addLine(Console
*console
, const char *line
)
138 std::vector
<ConsoleRuleValue
> values
;
139 if (!parseLine(line
, values
))
141 console
->addLine(false, S3D::formatStringBuffer(
142 "Non terminated quote in : %s",
147 if (values
.empty()) return; // Should never happen!
149 std::vector
<ConsoleRule
*> closeMatches
;
150 ConsoleRule
*exactMatch
= matchRule(values
, closeMatches
);
153 exactMatch
->runRule(console
, line
, values
);
157 std::string valuesString
= ConsoleRule::valuesToString(values
);
158 console
->addLine(false, "Unrecognised function :");
159 console
->addLine(false, S3D::formatStringBuffer(
161 valuesString
.c_str()));
162 if (!closeMatches
.empty())
164 console
->addLine(false, "Possible matches are :");
165 std::vector
<ConsoleRule
*>::iterator itor
;
166 for (itor
= closeMatches
.begin();
167 itor
!= closeMatches
.end();
170 std::string text
= (*itor
)->toString();
171 console
->addLine(false, S3D::formatStringBuffer(
172 " %s", text
.c_str()));
178 ConsoleRule
*ConsoleRules::matchRule(
179 std::vector
<ConsoleRuleValue
> &values
,
180 std::vector
<ConsoleRule
*> &closeMatches
)
182 std::multimap
<int, ConsoleRule
*> matchedRules
;
184 ConsoleRuleValue firstValue
= values
.front();
185 _strlwr((char *)firstValue
.valueString
.c_str());
186 std::pair
<RulesMap::iterator
, RulesMap::iterator
> itp
=
187 rules_
.equal_range(firstValue
.valueString
);
188 for (RulesMap::iterator itor
= itp
.first
; itor
!= itp
.second
; ++itor
)
190 ConsoleRule
*rule
= itor
->second
;
192 std::pair
<int, ConsoleRule
*>(
193 (int) rule
->getParams().size(), rule
));
196 if (matchedRules
.empty()) return 0;
198 std::vector
<ConsoleRule
*>::iterator ruleItor
;
199 std::vector
<ConsoleRule
*> sameNumberArgs
;
200 getMatchedRules(sameNumberArgs
, matchedRules
, (int) values
.size() - 1);
201 if (!sameNumberArgs
.empty())
203 for (ruleItor
= sameNumberArgs
.begin();
204 ruleItor
!= sameNumberArgs
.end();
207 ConsoleRule
*rule
= *ruleItor
;
208 closeMatches
.push_back(rule
);
209 if (rule
->matchesExactParams(values
))
211 closeMatches
.clear();
220 void ConsoleRules::getMatchedRules(
221 std::vector
<ConsoleRule
*> &result
,
222 std::multimap
<int, ConsoleRule
*> &matchedRules
,
227 std::multimap
<int, ConsoleRule
*>::iterator
,
228 std::multimap
<int, ConsoleRule
*>::iterator
> itp
=
229 matchedRules
.equal_range(argCount
);
230 for (std::multimap
<int, ConsoleRule
*>::iterator itor
= itp
.first
;
234 ConsoleRule
*rule
= itor
->second
;
235 result
.push_back(rule
);
239 bool ConsoleRules::parseLine(const char *line
,
240 std::vector
<ConsoleRuleValue
> &split
)
243 bool inQuote
= false;
244 std::string currentEntry
;
245 for (int i
=0; i
<(int) strlen(line
)+1; i
++)
247 const char c
= line
[i
];
251 if (inQuote
) return false;
252 parseAddLine(pos
, currentEntry
.c_str(), split
);
253 currentEntry
= ""; pos
= -1;
258 ((split
.size() == 1 && currentEntry
.empty()) ||
259 (split
.size() == 0 && !currentEntry
.empty())))
261 parseAddLine(pos
, currentEntry
.c_str(), split
);
262 currentEntry
= ""; pos
= -1;
264 else if ((c
== ' ') && !inQuote
)
266 parseAddLine(pos
, currentEntry
.c_str(), split
);
267 currentEntry
= ""; pos
= -1;
275 if (pos
== -1) pos
= i
;
283 void ConsoleRules::parseAddLine(int position
, const char *line
,
284 std::vector
<ConsoleRuleValue
> &split
)
286 int n
= (int) strlen(line
);
289 ConsoleRuleValue newSplit
;
290 newSplit
.valueString
= line
;
291 newSplit
.position
= position
;
293 if (strcmp(line
, "on") == 0)
295 newSplit
.type
= ConsoleRuleTypeBoolean
;
296 newSplit
.valueBool
= true;
298 else if (strcmp(line
, "off") == 0)
300 newSplit
.type
= ConsoleRuleTypeBoolean
;
301 newSplit
.valueBool
= false;
305 bool numbersOnly
= true;
306 for (int i
=0; i
<n
; i
++)
308 if ((line
[i
] < '0') || (line
[i
] > '9'))
320 newSplit
.type
= ConsoleRuleTypeNumber
;
321 newSplit
.valueNumber
= (float) atof(line
);
325 newSplit
.type
= ConsoleRuleTypeString
;
329 split
.push_back(newSplit
);
332 void ConsoleRules::dump(std::vector
<std::string
> &resultList
)
334 std::multimap
<std::string
, ConsoleRule
*>::iterator itor
;
335 for (itor
= rules_
.begin();
336 itor
!= rules_
.end();
339 ConsoleRule
*rule
= itor
->second
;
340 resultList
.push_back(rule
->toString());