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
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_
41 #ifndef WDL_LINEPARSER_HAS_LINEPARSERINT
42 #define WDL_LINEPARSER_HAS_LINEPARSERINT
45 #ifndef WDL_LINEPARSE_IMPL_ONLY
46 class LineParserInt
// version which does not have any temporary space for buffers (requires use of parseDestroyBuffer)
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
63 void eattoken() { if (m_eat
<m_nt
) m_eat
++; }
69 m_tokens
=m_toklist_small
;
70 m_tokenbasebuffer
=NULL
;
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)
86 #define WDL_LINEPARSE_PREFIX
87 #define WDL_LINEPARSE_DEFPARM(x) =(x)
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))
96 m_tokens
=m_toklist_small
;
97 m_tokenbasebuffer
= line
;
99 while ((thischar
=*line
) == ' ' || thischar
== '\t') line
++;
100 if (!thischar
) return 0;
104 static const char tab
[4]={0, '"', '\'', '`'};
105 int lstate
=0; // 1=", 2=`, 3='
111 if (!ignore_commentchars
) return 0; // we're done!
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);
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
;
141 if (lstate
&& !allowunterminatedquotes
)
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
159 if ((unsigned int)token
>= m_nt
)
161 if (success
) *success
=0;
164 const char *t
=m_tokens
[token
];
168 // todo: detect d or f prefix for double/float base64 encodings
171 while (*t
&&ot
<(int)sizeof(buf
)-1)
174 if (c
== ',') c
= '.';
175 else if (success
&& (c
< '0' || c
> '9') && c
!= '.') *success
=0;
182 int WDL_LINEPARSE_PREFIX
gettoken_int(int token
, int *success
WDL_LINEPARSE_DEFPARM(NULL
)) const
186 if ((unsigned int)token
>= m_nt
|| !((tok
=m_tokens
[token
])[0]))
188 if (success
) *success
=0;
193 if (tok
[0] == '-') l
=(int)strtol(tok
,&tmp
,0);
194 else l
=(int)strtoul(tok
,&tmp
,0);
195 if (success
) *success
=! (int)(*tmp
);
199 unsigned int WDL_LINEPARSE_PREFIX
gettoken_uint(int token
, int *success
WDL_LINEPARSE_DEFPARM(NULL
)) const
203 if ((unsigned int)token
>= m_nt
|| !((tok
=m_tokens
[token
])[0]))
205 if (success
) *success
=0;
210 if (p
[0] == '-') ++p
;
211 unsigned int val
=(int)strtoul(p
, &tmp
, 0);
212 if (success
) *success
=! (int)(*tmp
);
216 const char * WDL_LINEPARSE_PREFIX
gettoken_str(int token
) const
219 if ((unsigned int)token
>= m_nt
) return "";
220 return m_tokens
[token
];
223 char WDL_LINEPARSE_PREFIX
gettoken_quotingchar(int token
) const
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 '\'';
238 int WDL_LINEPARSE_PREFIX
gettoken_enum(int token
, const char *strlist
) const // null seperated list
241 if ((unsigned int)token
>= m_nt
) return -1;
244 const char *tt
=m_tokens
[token
];
245 if (*tt
) while (*strlist
)
248 if (!stricmp(tt
,strlist
)) return x
;
250 if (!strcasecmp(tt
,strlist
)) return x
;
252 while (*strlist
) strlist
++;
259 #ifndef WDL_LINEPARSE_IMPL_ONLY
264 #undef WDL_LINEPARSE_PREFIX
265 #undef WDL_LINEPARSE_DEFPARM
266 #endif // ! WDL_LINEPARSE_INTF_ONLY
268 #ifndef WDL_LINEPARSE_IMPL_ONLY
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
289 #ifndef WDL_LINEPARSE_IMPL_ONLY
290 class LineParser
: public LineParserInt
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
);
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)
314 #define WDL_LINEPARSE_PREFIX
315 #define WDL_LINEPARSE_DEFPARM(x) =(x)
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
);
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);
345 memcpy(usebuf
,line
,linelen
+1);
349 #undef WDL_LINEPARSE_PREFIX
350 #undef WDL_LINEPARSE_DEFPARM
351 #endif // ! WDL_LINEPARSE_INTF_ONLY
353 #ifndef WDL_LINEPARSE_IMPL_ONLY
356 WDL_HeapBuf m_tmpbuf_big
;
359 #endif//!WDL_LINEPARSE_IMPL_ONLY
367 #endif//WDL_LINEPARSE_H_