/ source / blood / src / nnextstr.cpp
nnextstr.cpp
  1  //-------------------------------------------------------------------------
  2  /*
  3  Copyright (C) 2010-2019 EDuke32 developers and contributors
  4  Copyright (C) 2019 Nuke.YKT
  5  Copyright (C) NoOne
  6  
  7  *****************************************************************
  8  NoOne: A very basic string parser. Update or replace eventually.
  9  *****************************************************************
 10  
 11  This file is part of NBlood.
 12  
 13  NBlood is free software; you can redistribute it and/or
 14  modify it under the terms of the GNU General Public License version 2
 15  as published by the Free Software Foundation.
 16  
 17  This program is distributed in the hope that it will be useful,
 18  but WITHOUT ANY WARRANTY; without even the implied warranty of
 19  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 20  
 21  See the GNU General Public License for more details.
 22  
 23  You should have received a copy of the GNU General Public License
 24  along with this program; if not, write to the Free Software
 25  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 26  */
 27  //-------------------------------------------------------------------------
 28  #ifdef NOONE_EXTENSIONS
 29  #include "common_game.h"
 30  #include "nnextstr.h"
 31  #include "nnexts.h"
 32  
 33  struct NAMED_TYPE
 34  {
 35      unsigned int id;
 36      const char* text;
 37  };
 38  
 39  static const NAMED_TYPE gBoolNames[] =
 40  {
 41      { false, "0" },
 42      { true, "1" },
 43      { false, "No" },
 44      { true, "Yes" },
 45      { false, "False" },
 46      { true, "True" },
 47  };
 48  
 49  const char* enumStrGetChar(int nOffs, char* out, const char* str, char expcr)
 50  {
 51      int j = ClipLow(nOffs, 0);
 52      int i = 0;
 53  
 54      out[0] = '\0';
 55      
 56      if (j > 0)
 57      {
 58          // search for start
 59          while (str[i] && j > 0)
 60          {
 61              if (str[i++] == expcr)
 62                  j--;
 63          }
 64      }
 65  
 66      while (str[i] && str[i] != expcr)
 67          out[j++] = str[i++];
 68      
 69      
 70      out[j] = '\0';
 71      
 72      return (out[0]) ? out : NULL;
 73  }
 74  
 75  int enumStr(int nOffs, const char* str, char* key, char* val)
 76  {
 77      if (!str)
 78          return 0;
 79      
 80      const char* pStr;
 81      char buffer1[256], buffer2[256], string[256];
 82      int t;
 83  
 84      if (isarray(str))
 85      {
 86          t = Bstrlen(str);
 87          Bstrcpy(string, str);
 88          string[t] = '\0';
 89  
 90          pStr = &string[(string[0] == '(')];
 91          if (string[t - 1] == ')')
 92              string[t - 1] = '\0';
 93  
 94          removeSpaces(string);
 95  
 96          if (enumStrGetChar(nOffs, buffer1, pStr, ','))
 97          {
 98              if (key)
 99              {
100                  if (enumStrGetChar(0, buffer2, buffer1, '='))
101                      Bsprintf(key, "%s", buffer2);
102                  else
103                      key[0] = '\0';
104              }
105  
106              if (val)
107              {
108                  if (enumStrGetChar(1, buffer2, buffer1, '='))
109                  {
110                      Bsprintf(val, "%s", buffer2);
111                      t = ClipLow(Bstrlen(val), 1);
112                      if (val[0] == '(' && val[t - 1] != ')')
113                      {
114                          char tval[256];
115  
116                          nOffs++;
117                          while ( 1 )
118                          {
119                              if ((nOffs = enumStr(nOffs, str, tval)) != 0)
120                              {
121                                  t = Bstrlen(tval); Bstrcat(val, ","); Bstrcat(val, tval);
122                                  if (tval[t - 1] != ')')
123                                      continue;
124                              }
125                              else
126                              {
127                                  ThrowError("End of array is not found in \"%s\"", str);
128                              }
129  
130                              return nOffs;
131                          }
132                      }
133  
134                  }
135                  else
136                      val[0] = '\0';
137              }
138  
139              return ++nOffs;
140          }
141      }
142  
143      return 0;
144  }
145  
146  int enumStr(int nOffs, const char* str, char* val)
147  {
148      if (!str)
149          return 0;
150      
151      const char* pStr;
152      char string[256];
153      int t;
154  
155      t = Bstrlen(str);
156      Bstrcpy(string, str);
157      string[t] = '\0';
158  
159      pStr = &string[(string[0] == '(')];
160      if (string[t - 1] == ')')
161          string[t - 1] = '\0';
162  
163      removeSpaces(string);
164      if (enumStrGetChar(nOffs, val, pStr, ','))
165          return ++nOffs;
166  
167      return 0;
168  }
169  
170  void removeSpaces(char* str)
171  {
172      if (str)
173      {
174          int t = Bstrlen(str);
175          for (int i = t - 1; i >= 0; i--)
176          {
177              if (!isspace(str[i]))
178                  continue;
179  
180              for (int j = i; j < t; j++) { str[j] = str[j + 1]; }
181          }
182      }
183  }
184  
185  int btoi(const char* str)
186  {
187      if (str)
188      {
189          int i;
190          const NAMED_TYPE* pEntry = gBoolNames;
191          for (i = 0; i < LENGTH(gBoolNames); i++)
192          {
193              if (Bstrcasecmp(str, pEntry->text) == 0)
194                  return (bool)pEntry->id;
195  
196              pEntry++;
197          }
198      }
199  
200      return -1;
201  }
202  char isbool(const char* str) { return (str && btoi(str) != -1); }
203  char isarray(const char* str, int* nLen)
204  {
205      if (nLen)
206          *nLen = 0;
207  
208      if (str)
209      {
210          int l = Bstrlen(str);
211          if (l && str[0] == '(' && str[l - 1] == ')')
212          {
213              if (nLen)
214              {
215                  *nLen = *nLen + 1;
216                  const char* pStr = str;
217                  while ((pStr = Bstrchr(pStr, ',')) != NULL)
218                      pStr++, * nLen = *nLen + 1;
219              }
220  
221              return true;
222          }
223      }
224  
225      return false;
226  }
227  
228  char isperc(const char* str)
229  {
230      if (str)
231      {
232          int l = Bstrlen(str);
233          if (--l > 0 && str[l] == '%')
234          {
235              while (--l > 0)
236              {
237                  if (!isdigit(str[l]))
238                      return false;
239              }
240  
241              if (isdigit(str[l]) || str[l] == '-' || str[l] == '+')
242                  return true;
243          }
244      }
245  
246      return false;
247  }
248  
249  char isfix(const char* str, char flags)
250  {
251      if (str)
252      {
253          int l = Bstrlen(str);
254          if (l > 0)
255          {
256              if (!isdigit(str[0]))
257              {
258                  switch (str[0])
259                  {
260                      case '-':
261                          if (!(flags & 0x01)) return false;
262                          break;
263                      case '+':
264                          if (!(flags & 0x02)) return false;
265                          break;
266                      default:
267                          return false;
268  
269                  }
270              }
271  
272              while (--l > 0)
273              {
274                  if (!isdigit(str[l]))
275                      return false;
276              }
277  
278              return true;
279          }
280      }
281  
282      return false;
283  
284  }
285  
286  
287  char isufix(const char* str)
288  {
289      return isfix(str, 0);
290  }
291  #endif