Merge pull request #110 from tesselode/fixes
[wdl/wdl-ol.git] / WDL / lineparse.h
blobb0c3cd2c4e3acb3d1d0ac69ee1631c8103b9f130
1 /*
2 WDL - lineparse.h
3 Copyright (C) 2005-2014 Cockos Incorporated
4 Copyright (C) 1999-2004 Nullsoft, Inc.
6 This software is provided 'as-is', without any express or implied
7 warranty. In no event will the authors be held liable for any damages
8 arising from the use of this software.
10 Permission is granted to anyone to use this software for any purpose,
11 including commercial applications, and to alter it and redistribute it
12 freely, subject to the following restrictions:
14 1. The origin of this software must not be misrepresented; you must not
15 claim that you wrote the original software. If you use this software
16 in a product, an acknowledgment in the product documentation would be
17 appreciated but is not required.
18 2. Altered source versions must be plainly marked as such, and must not be
19 misrepresented as being the original software.
20 3. This notice may not be removed or altered from any source distribution.
26 This file provides a simple line parsing class. This class was derived from that of NSIS,
27 http://nsis.sf.net, but it is no longer compatible (escaped-encodings and multiline C-style comments
28 are ignored).
30 In particular, it allows for multiple space delimited tokens
31 on a line, with a choice of three quotes (`bla`, 'bla', or "bla") to contain any
32 items that may have spaces.
36 #ifndef WDL_LINEPARSE_H_
37 #define WDL_LINEPARSE_H_
39 #include "heapbuf.h"
41 #ifndef WDL_LINEPARSER_HAS_LINEPARSERINT
42 #define WDL_LINEPARSER_HAS_LINEPARSERINT
43 #endif
45 #ifndef WDL_LINEPARSE_IMPL_ONLY
46 class LineParserInt // version which does not have any temporary space for buffers (requires use of parseDestroyBuffer)
48 public:
49 int getnumtokens() const { return m_nt-m_eat; }
51 #ifdef WDL_LINEPARSE_INTF_ONLY
52 // parse functions return <0 on error (-1=mem, -2=unterminated quotes), ignore_commentchars = true means don't treat #; as comments
53 int parseDestroyBuffer(char *line, bool ignore_commentchars = true, bool backtickquote = true, bool allowunterminatedquotes = false);
55 double gettoken_float(int token, int *success=NULL) const;
56 int gettoken_int(int token, int *success=NULL) const;
57 unsigned int gettoken_uint(int token, int *success=NULL) const;
58 const char *gettoken_str(int token) const;
59 char gettoken_quotingchar(int token) const;
60 int gettoken_enum(int token, const char *strlist) const; // null seperated list
61 #endif
63 void eattoken() { if (m_eat<m_nt) m_eat++; }
66 LineParserInt()
68 m_nt=m_eat=0;
69 m_tokens=m_toklist_small;
70 m_tokenbasebuffer=NULL;
73 ~LineParserInt()
77 #endif // !WDL_LINEPARSE_IMPL_ONLY
81 #ifndef WDL_LINEPARSE_INTF_ONLY
82 #ifdef WDL_LINEPARSE_IMPL_ONLY
83 #define WDL_LINEPARSE_PREFIX LineParserInt::
84 #define WDL_LINEPARSE_DEFPARM(x)
85 #else
86 #define WDL_LINEPARSE_PREFIX
87 #define WDL_LINEPARSE_DEFPARM(x) =(x)
88 #endif
90 int WDL_LINEPARSE_PREFIX parseDestroyBuffer(char *line, bool ignore_commentchars WDL_LINEPARSE_DEFPARM(true), bool backtickquote WDL_LINEPARSE_DEFPARM(true), bool allowunterminatedquotes WDL_LINEPARSE_DEFPARM(false))
92 m_nt=0;
93 m_eat=0;
94 if (!line) return -1;
96 m_tokens=m_toklist_small;
97 m_tokenbasebuffer = line;
98 char thischar;
99 while ((thischar=*line) == ' ' || thischar == '\t') line++;
100 if (!thischar) return 0;
102 for (;;)
104 static const char tab[4]={0, '"', '\'', '`'};
105 int lstate=0; // 1=", 2=`, 3='
107 switch (*line)
109 case ';':
110 case '#':
111 if (!ignore_commentchars) return 0; // we're done!
112 break;
113 case '"': line++; lstate=1; break;
114 case '\'': line++; lstate=2; break;
115 case '`': if (backtickquote) { line++; lstate=3; } break;
118 const char *basep = line;
120 if (!lstate) while ((thischar=*line) && thischar != ' ' && thischar != '\t') line++;
121 else while ((thischar=*line) && thischar != tab[lstate]) line++;
123 const char oldterm = *line;
124 *line=0; // null terminate this token
126 if (m_nt >= (int) (sizeof(m_toklist_small)/sizeof(m_toklist_small[0])))
128 m_tokens = m_toklist_big.ResizeOK(m_nt+1,false);
129 if (!m_tokens)
131 m_nt=0;
132 return -1;
134 if (m_nt == (int) (sizeof(m_toklist_small)/sizeof(m_toklist_small[0])))
135 memcpy(m_tokens,m_toklist_small,m_nt*sizeof(const char *));
137 m_tokens[m_nt++] = basep;
139 if (!oldterm)
141 if (lstate && !allowunterminatedquotes)
143 m_nt = 0;
144 return -2;
146 return 0;
149 line++;
150 while ((thischar=*line) == ' ' || thischar == '\t') line++;
151 if (!thischar) return 0;
156 double WDL_LINEPARSE_PREFIX gettoken_float(int token, int *success WDL_LINEPARSE_DEFPARM(NULL)) const
158 token+=m_eat;
159 if ((unsigned int)token >= m_nt)
161 if (success) *success=0;
162 return 0.0;
164 const char *t=m_tokens[token];
165 if (success)
166 *success=*t?1:0;
168 // todo: detect d or f prefix for double/float base64 encodings
169 char buf[512];
170 int ot = 0;
171 while (*t&&ot<(int)sizeof(buf)-1)
173 char c=*t++;
174 if (c == ',') c = '.';
175 else if (success && (c < '0' || c > '9') && c != '.') *success=0;
176 buf[ot++]=c;
178 buf[ot] = 0;
179 return atof(buf);
182 int WDL_LINEPARSE_PREFIX gettoken_int(int token, int *success WDL_LINEPARSE_DEFPARM(NULL)) const
184 token+=m_eat;
185 const char *tok;
186 if ((unsigned int)token >= m_nt || !((tok=m_tokens[token])[0]))
188 if (success) *success=0;
189 return 0;
191 char *tmp;
192 int l;
193 if (tok[0] == '-') l=(int)strtol(tok,&tmp,0);
194 else l=(int)strtoul(tok,&tmp,0);
195 if (success) *success=! (int)(*tmp);
196 return l;
199 unsigned int WDL_LINEPARSE_PREFIX gettoken_uint(int token, int *success WDL_LINEPARSE_DEFPARM(NULL)) const
201 token+=m_eat;
202 const char *tok;
203 if ((unsigned int)token >= m_nt || !((tok=m_tokens[token])[0]))
205 if (success) *success=0;
206 return 0;
208 char *tmp;
209 const char* p=tok;
210 if (p[0] == '-') ++p;
211 unsigned int val=(int)strtoul(p, &tmp, 0);
212 if (success) *success=! (int)(*tmp);
213 return val;
216 const char * WDL_LINEPARSE_PREFIX gettoken_str(int token) const
218 token+=m_eat;
219 if ((unsigned int)token >= m_nt) return "";
220 return m_tokens[token];
223 char WDL_LINEPARSE_PREFIX gettoken_quotingchar(int token) const
225 token+=m_eat;
226 if ((unsigned int)token >= m_nt) return 0;
228 const char *tok = m_tokens[token];
229 if (tok != m_tokenbasebuffer) switch (tok[-1])
231 case '"': return '"';
232 case '`': return '`';
233 case '\'': return '\'';
235 return 0;
238 int WDL_LINEPARSE_PREFIX gettoken_enum(int token, const char *strlist) const // null seperated list
240 token+=m_eat;
241 if ((unsigned int)token >= m_nt) return -1;
243 int x=0;
244 const char *tt=m_tokens[token];
245 if (*tt) while (*strlist)
247 #ifdef _WIN32
248 if (!stricmp(tt,strlist)) return x;
249 #else
250 if (!strcasecmp(tt,strlist)) return x;
251 #endif
252 while (*strlist) strlist++;
253 strlist++;
254 x++;
256 return -1;
259 #ifndef WDL_LINEPARSE_IMPL_ONLY
260 private:
261 #endif
264 #undef WDL_LINEPARSE_PREFIX
265 #undef WDL_LINEPARSE_DEFPARM
266 #endif // ! WDL_LINEPARSE_INTF_ONLY
268 #ifndef WDL_LINEPARSE_IMPL_ONLY
269 protected:
271 WDL_TypedBuf<const char *> m_toklist_big;
273 unsigned int m_nt, m_eat;
275 const char *m_tokenbasebuffer; // points to (mangled) caller's buffer
276 const char **m_tokens; // points to m_toklist_small or m_toklist_big
278 const char *m_toklist_small[64];
280 #endif//!WDL_LINEPARSE_IMPL_ONLY
287 // derived
289 #ifndef WDL_LINEPARSE_IMPL_ONLY
290 class LineParser : public LineParserInt
292 public:
293 int parse(const char *line) { return parse_ex(line,false); } // <0 on error, old style (;# starting tokens means comment to EOL)
295 #ifdef WDL_LINEPARSE_INTF_ONLY
296 // parse functions return <0 on error (-1=mem, -2=unterminated quotes), ignore_commentchars = true means don't treat #; as comments
297 int parse_ex(const char *line, bool ignore_commentchars = true, bool backtickquote = true, bool allowunterminatedquotes = false);
298 void set_one_token(const char *ptr);
299 char *__get_tmpbuf(const char *line);
300 #endif
303 LineParser(bool ignoredLegacyValue=false) { }
305 #endif // !WDL_LINEPARSE_IMPL_ONLY
309 #ifndef WDL_LINEPARSE_INTF_ONLY
310 #ifdef WDL_LINEPARSE_IMPL_ONLY
311 #define WDL_LINEPARSE_PREFIX LineParser::
312 #define WDL_LINEPARSE_DEFPARM(x)
313 #else
314 #define WDL_LINEPARSE_PREFIX
315 #define WDL_LINEPARSE_DEFPARM(x) =(x)
316 #endif
318 int WDL_LINEPARSE_PREFIX parse_ex(const char *line, bool ignore_commentchars WDL_LINEPARSE_DEFPARM(true), bool backtickquote WDL_LINEPARSE_DEFPARM(true), bool allowunterminatedquotes WDL_LINEPARSE_DEFPARM(false))
320 return parseDestroyBuffer(__get_tmpbuf(line), ignore_commentchars, backtickquote, allowunterminatedquotes);
323 void WDL_LINEPARSE_PREFIX set_one_token(const char *line)
325 m_tokens=m_toklist_small;
326 m_tokens[0] = m_tokenbasebuffer = __get_tmpbuf(line);
327 m_eat=0;
328 m_nt=m_tokenbasebuffer?1:0;
331 char * WDL_LINEPARSE_PREFIX __get_tmpbuf(const char *line)
333 int linelen = (int)strlen(line);
335 char *usebuf=m_tmpbuf;
336 if (linelen >= (int)sizeof(m_tmpbuf))
338 usebuf = (char *)m_tmpbuf_big.ResizeOK(linelen+1,false);
339 if (!usebuf)
341 m_nt=0;
342 return NULL;
345 memcpy(usebuf,line,linelen+1);
346 return usebuf;
349 #undef WDL_LINEPARSE_PREFIX
350 #undef WDL_LINEPARSE_DEFPARM
351 #endif // ! WDL_LINEPARSE_INTF_ONLY
353 #ifndef WDL_LINEPARSE_IMPL_ONLY
354 private:
356 WDL_HeapBuf m_tmpbuf_big;
357 char m_tmpbuf[2048];
359 #endif//!WDL_LINEPARSE_IMPL_ONLY
367 #endif//WDL_LINEPARSE_H_