UFO: Alien Invasion
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
binaryexpressionparser.cpp
Go to the documentation of this file.
1 
5 /*
6 Copyright (C) 2002-2020 UFO: Alien Invasion.
7 
8 This program is free software; you can redistribute it and/or
9 modify it under the terms of the GNU General Public License
10 as published by the Free Software Foundation; either version 2
11 of the License, or (at your option) any later version.
12 
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
16 
17 See the GNU General Public License for more details.
18 
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 
23 */
24 
25 #include "binaryexpressionparser.h"
26 #include "common.h"
27 
28 typedef enum
29 {
32 
37 private:
41  bool result;
42  const void* userdata;
43 
44  inline void SkipWhiteSpaces (const char** s) const
45  {
46  while (**s == ' ' || **s == '\t')
47  (*s)++;
48  }
49 
53  inline void NextChar (const char** s) const
54  {
55  (*s)++;
56  /* skip white-spaces too */
57  SkipWhiteSpaces(s);
58  }
59 
60  const char* GetSwitchName (const char** s)
61  {
62  int pos = 0;
63 
64  /* skip non printable chars and special chars that are used to define the binary expression */
65  while (**s > ' ' && **s != '^' && **s != '|' && **s != '&' && **s != '!' && **s != '(' && **s != ')') {
66  varName[pos++] = **s;
67  (*s)++;
68  }
69  varName[pos] = '\0';
70 
71  return varName;
72  }
73 
79  bool CheckOR (const char** s)
80  {
81  bool result = false;
82  enum {
83  BEP_NONE, BEP_OR, BEP_EXCLUSIVE_OR
84  };
85  int goOn = BEP_NONE;
86 
87  SkipWhiteSpaces(s);
88  do {
89  if (goOn == BEP_EXCLUSIVE_OR)
90  result ^= CheckAND(s);
91  else
92  result |= CheckAND(s);
93 
94  if (**s == '|') {
95  goOn = BEP_OR;
96  NextChar(s);
97  } else if (**s == '^') {
98  goOn = BEP_EXCLUSIVE_OR;
99  NextChar(s);
100  } else {
101  goOn = BEP_NONE;
102  }
103  } while (goOn != BEP_NONE && !binaryExpressionParserError);
104 
105  return result;
106  }
107 
108  bool CheckAND (const char** s)
109  {
110  bool result = true;
111  bool negate = false;
112  bool goOn = false;
113 
114  do {
115  /* parse all negate chars and swap the flag accordingly */
116  while (**s == '!') {
117  negate ^= true;
118  NextChar(s);
119  }
120  /* handling braces */
121  if (**s == '(') {
122  NextChar(s);
123  /* and the result of the inner clause by calling the entry
124  * point again (and apply the negate flag) */
125  result &= CheckOR(s) ^ negate;
126  if (**s != ')')
127  binaryExpressionParserError = BEPERR_BRACE;
128  NextChar(s);
129  } else {
130  /* get the variable state by calling the evaluate callback */
131  const int value = varFunc(GetSwitchName(s), userdata);
132  if (value == -1)
133  binaryExpressionParserError = BEPERR_NOTFOUND;
134  else
135  result &= value ^ negate;
136  SkipWhiteSpaces(s);
137  }
138 
139  /* check whether there is another and clause */
140  if (**s == '&') {
141  goOn = true;
142  NextChar(s);
143  } else {
144  goOn = false;
145  }
146  negate = false;
147  } while (goOn && !binaryExpressionParserError);
148 
149  return result;
150  }
151 
152 public:
153  BinaryExpressionParser (const char* expr, BEPEvaluteCallback_t varFuncParam, const void* userdataPtr) :
154  binaryExpressionParserError(BEPERR_NONE), varFunc(varFuncParam), userdata(userdataPtr)
155  {
156  varName[0] = 0;
157  const char* str = expr;
158  result = CheckOR(&str);
159  /* check for no end error */
160  if (Q_strvalid(str) && !binaryExpressionParserError)
161  binaryExpressionParserError = BEPERR_NOEND;
162  }
163 
164  inline bool getResult() const
165  {
166  return result;
167  }
168 
170  {
172  }
173 };
174 
175 bool BEP_Evaluate (const char* expr, BEPEvaluteCallback_t varFuncParam, const void* userdata)
176 {
177  if (!Q_strvalid(expr))
178  return true;
179 
180  BinaryExpressionParser bep(expr, varFuncParam, userdata);
181  const bool result = bep.getResult();
182  const binaryExpressionParserError_t error = bep.getError();
183 
184  switch (error) {
185  case BEPERR_NONE:
186  /* do nothing */
187  return result;
188  case BEPERR_BRACE:
189  Com_Printf("')' expected in binary expression (%s).\n", expr);
190  return true;
191  case BEPERR_NOEND:
192  Com_Printf("Unexpected end of condition in binary expression (%s).\n", expr);
193  return result;
194  case BEPERR_NOTFOUND:
195  Com_Printf("Variable not found in binary expression (%s).\n", expr);
196  return false;
197  }
198  Com_Error(ERR_FATAL, "Unknown CheckBEP error in binary expression (%s)", expr);
199 }
void NextChar(const char **s) const
Advance to the next char that is no whitespace.
const char * GetSwitchName(const char **s)
BinaryExpressionParser(const char *expr, BEPEvaluteCallback_t varFuncParam, const void *userdataPtr)
Evaluates stuff like this expression.
void Com_Printf(const char *const fmt,...)
Definition: common.cpp:386
binaryExpressionParserError_t
#define ERR_FATAL
Definition: common.h:210
#define Q_strvalid(string)
Definition: shared.h:141
bool BEP_Evaluate(const char *expr, BEPEvaluteCallback_t varFuncParam, const void *userdata)
void Com_Error(int code, const char *fmt,...)
Definition: common.cpp:417
BEPEvaluteCallback_t varFunc
#define MAX_VAR
Definition: shared.h:36
bool CheckOR(const char **s)
Evaluates or and xor in the given string. This is the entry point, it delegates to the and checks tha...
int(* BEPEvaluteCallback_t)(const char *var, const void *userdata)
definitions common between client and server, but not game lib
binaryExpressionParserError_t getError() const
binaryExpressionParserError_t binaryExpressionParserError
void SkipWhiteSpaces(const char **s) const