Easy3D 2.5.3
tokenizer.h
1//----------------------------------------------------------------------------------
2// File: NV/NvTokenizer.h
3// SDK Version: v3.00
4// Email: gameworks@nvidia.com
5// Site: http://developer.nvidia.com/
6//
7// Copyright (c) 2014-2015, NVIDIA CORPORATION. All rights reserved.
8//
9// Redistribution and use in source and binary forms, with or without
10// modification, are permitted provided that the following conditions
11// are met:
12// * Redistributions of source code must retain the above copyright
13// notice, this list of conditions and the following disclaimer.
14// * Redistributions in binary form must reproduce the above copyright
15// notice, this list of conditions and the following disclaimer in the
16// documentation and/or other materials provided with the distribution.
17// * Neither the name of NVIDIA CORPORATION nor the names of its
18// contributors may be used to endorse or promote products derived
19// from this software without specific prior written permission.
20//
21// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
22// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
24// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
25// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
26// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
27// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
28// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
29// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32//
33//----------------------------------------------------------------------------------
34
35#ifndef NV_TOKENIZER_H
36#define NV_TOKENIZER_H
37
38#include <string>
39#include <cstdlib>
40
41#define NV_MAX_TOKEN_LEN 1024
42#define NV_MAX_DELIM_COUNT 16
43
44namespace easy3d {
45
46
52 {
53 protected:
54 const char* mSrcBuf; /*< This holds a pointer to an immutable char buffer. */
55 char mTokBuf[NV_MAX_TOKEN_LEN]; /*< This is a temporary buffer for collecting next token. */
56 uint32_t mTokLen; /*< This is the character length of current token, not including null termination. */
57 char mTermChar; /*< This is the character that caused us to stop parsing the current token. */
58 char mDelims[NV_MAX_DELIM_COUNT];
59 uint32_t mNumDelims;
60 private:
61 bool mConsumeWS;
62
63 public:
64 explicit Tokenizer(const char* src, const char* delims = nullptr)
65 : mSrcBuf(src)
66 , mTokLen(0)
67 , mTermChar(0)
68 , mNumDelims(0)
69 , mConsumeWS(true)
70 {
71 if (nullptr == delims)
72 { // built in delim set.
73 mNumDelims = 3;
74 mDelims[0] = '=';
75 mDelims[1] = ',';
76 mDelims[2] = ':';
77 }
78 else
79 { // note that we DO support empty string, in which case
80 // we have no delims other than whitespace...
81 int i = 0;
82 mNumDelims = 0;
83 while (mNumDelims < NV_MAX_DELIM_COUNT && delims[i])
84 {
85 const char c = delims[i++];
86 // else skip built-in handled chars
87 if (c == ' ' || c == '\t' || // Whitespace
88 c == '"' || c == '\'' || // Quote
89 c == '\n' || c == '\r') // EOL
90 continue;
91 mDelims[mNumDelims++] = c;
92 }
93 }
94 }
95
96 void setConsumeWS(bool ws) { mConsumeWS = ws; }
97
98 inline bool isWhitespace(const char c)
99 {
100 return (' ' == c || '\t' == c);
101 }
102
103 inline bool isQuote(const char c)
104 {
105 return ('"' == c || '\'' == c);
106 }
107
108 inline bool isEOL(const char c)
109 {
110 return ('\n' == c || '\r' == c);
111 }
112
113 inline bool isTerm(const char c)
114 {
115 return (isWhitespace(c) || isEOL(c));
116 }
117
118 inline bool isDelim(const char c)
119 { // TBD any other delims we want to call out.
120 for (uint32_t i = 0; i < mNumDelims; i++)
121 if (c == mDelims[i]) return true;
122 return false;
123 }
124
125
126 public:
127 inline bool atEOF() {
128 // EOF is if we've reached a null character. :)
129 return (0 == *mSrcBuf);
130 }
131
132 char consumeWhitespace()
133 {
134 //VERBOSE_TOKEN_DEBUG("consuming whitespace");
135 mTermChar = 0;
136 while (!atEOF() && isWhitespace(*mSrcBuf))
137 mTermChar = *mSrcBuf++;
138 return mTermChar;
139 }
140
141 char consumeOneDelim()
142 {
143 //VERBOSE_TOKEN_DEBUG("consuming delimiter");
144 consumeWhitespace();
145 mTermChar = 0;
146 // eat ONE delimiter...
147 if (!atEOF() && isDelim(*mSrcBuf)) {
148 mTermChar = *mSrcBuf++;
149 }
150 if (isEOL(*mSrcBuf))
151 mTermChar = *mSrcBuf; // so that we return the EOL but DON'T CONSUME IT.
152 return mTermChar;
153 }
154
155 void consumeToEOL()
156 {
157 while (!atEOF() && !isEOL(*mSrcBuf)) // eat up to the EOL
158 mSrcBuf++;
159 while (!atEOF() && isEOL(*mSrcBuf)) // if not null, then eat EOL chars until gone, in case of /r/n type stuff...
160 mSrcBuf++;
161 }
162
163 bool readToken()
164 {
165 char startedWithQuote = 0; // we'll store the character if we get a quote
166 mTermChar = 0;
167 mTokLen = 0;
168 mTokBuf[0] = 0; // initialize
169 if (atEOF())
170 return false; // exit early...
171
172 if (mConsumeWS)
173 consumeWhitespace();
174 if (!atEOF() && isQuote(*mSrcBuf)) {
175 startedWithQuote = *mSrcBuf; // save WHAT quote character so we match it.
176 mSrcBuf++;
177 }
178
179 while (!atEOF()) { // termchar is already null so fine to exit loop.
180 // look for hard terminations (EOL)
181 if (isEOL(*mSrcBuf)) {
182 mTermChar = *mSrcBuf;
183 break;
184 }
185 // look to handle quoted strings, which CAN have delimiters validly in their contents.
186 if (startedWithQuote) {
187 if (startedWithQuote == *mSrcBuf) {
188 // consume and break.
189 mSrcBuf++;
190 mTermChar = startedWithQuote;
191 break;
192 }
193 }
194 else if (isDelim(*mSrcBuf) || isWhitespace(*mSrcBuf)) {
195 // just break, leave delim.
196 mTermChar = *mSrcBuf;
197 break;
198 }
199
200 mTokBuf[mTokLen] = *mSrcBuf; // copy char
201 mTokLen++; // inc length
202 mSrcBuf++; // inc buffer
203 }
204
205 // null-term buffer, do NOT inc length.
206 mTokBuf[mTokLen] = 0;
207
208 return (mTokLen > 0 || startedWithQuote); // false if empty string UNLESS quoted empty string...
209 }
210
211 bool requireToken(const char *find)
212 {
213 if (find == nullptr || find[0] == 0)
214 return false; // bad input.
215 if (!readToken())
216 return false;
217 // let's eliminate str functions...
218 const size_t findlen = strlen(find);
219 if (findlen != mTokLen)
220 return false; // early out.
221 if (0 != memcmp(mTokBuf, find, findlen))
222 return false;
223 // accepted.
224 return true;
225 }
226
227 bool requireTokenDelim(const char *find)
228 {
229 if (!requireToken(find))
230 return false;
231 if (!consumeOneDelim())
232 return false;
233 // accepted.
234 return true;
235 }
236
238 char getTermChar() const {
239 return mTermChar;
240 }
241
243 bool getLastToken(std::string& returnTok)
244 {
245 // we just return what's already in the buffer.
246 // handy for failure or unexpected cases.
247 returnTok.assign(mTokBuf);
248 return true;
249 }
250
252 const char* getLastTokenPtr()
253 {
254 return mTokBuf;
255 }
256
258 uint32_t getLastTokenLen() const
259 {
260 return mTokLen;
261 }
262
263
265 bool getTokenString(std::string& returnTok)
266 {
267 if (!readToken()) {
268 returnTok.clear();
269 return false;
270 }
271 returnTok.assign(mTokBuf);
272 return true;
273 }
274
276 bool getTokenString(char out[], const uint32_t outmax)
277 {
278 if (!readToken()) {
279 out[0] = 0;
280 return false;
281 }
282
283 // note mTokLen include the NULL terminator.
284 if (mTokLen > outmax)
285 {
286 // just have to truncate.
287 memcpy(out, mTokBuf, outmax - 1);
288 out[outmax - 1] = 0; // null terminate...
289 }
290 else
291 memcpy(out, mTokBuf, mTokLen + 1); // copy null!
292 return true;
293 }
294
296 bool getTokenFloat(float &out)
297 {
298 if (!readToken()) {
299 out = 0;
300 return false;
301 }
302 out = (float)strtod(mTokBuf, nullptr);
303 return true;
304 }
305
307 uint32_t getTokenFloatArray(float out[], uint32_t size)
308 {
309 uint32_t i = 0;
310 char firstdelim = 0, delim = 0;
311 while (i < size) {
312 if (firstdelim) {
313 // we had a delim initially, so we require (but can have repeated).
314 delim = consumeOneDelim();
315 if (delim == firstdelim)
316 continue;
317 }
318 if (!readToken())
319 break; // so we return what we've got.
320 out[i++] = (float)strtod(mTokBuf, nullptr);
321
322 // OPTIONALLY consume a delimiter between each number.
323 delim = consumeOneDelim();
324 if (delim && isEOL(delim)) // we didn't consume EOL, we are AT it though.
325 break;
326 if (i == 1) firstdelim = delim; // stash away.
327 }
328 return i; // return number of elements read.
329 }
330
332 uint32_t getTokenIntArray(int32_t out[], uint32_t size)
333 {
334 uint32_t i = 0;
335 char firstdelim = 0, delim = 0;
336 while (i < size) {
337 if (firstdelim) {
338 // we had a delim initially, so we require (but can have repeated).
339 delim = consumeOneDelim();
340 if (delim == firstdelim)
341 continue;
342 }
343 if (!readToken())
344 break; // so we return what we've got.
345 out[i++] = (int32_t)strtol(mTokBuf, nullptr, 0);
346
347 // OPTIONALLY consume a delimiter between each number.
348 delim = consumeOneDelim();
349 if (delim && isEOL(delim)) // we didn't consume EOL, we are AT it though.
350 break;
351 if (i == 1) firstdelim = delim; // stash away.
352 }
353 return i; // return number of elements read.
354 }
355
357 bool getTokenInt(int32_t &out)
358 {
359 if (!readToken()) {
360 out = 0;
361 return false;
362 }
363 out = (int32_t)strtol(mTokBuf, nullptr, 0);
364 return true;
365 }
366
368 bool getTokenUint(uint32_t &out)
369 {
370 if (!readToken()) {
371 out = 0;
372 return false;
373 }
374 out = (uint32_t)strtoul(mTokBuf, nullptr, 0);
375 return true;
376 }
377
379 bool getTokenBool(bool &out)
380 {
381 if (!readToken()) {
382 out = false;
383 return false;
384 }
385 if (mTokLen == 1 &&
386 (mTokBuf[0] == '0' || mTokBuf[0] == '1')) {
387 out = (mTokBuf[0] == '1');
388 return true;
389 }
390 else if ((0 == strcmp(mTokBuf, "true")) ||
391 (0 == strcmp(mTokBuf, "TRUE")) ||
392 (0 == strcmp(mTokBuf, "yes")) ||
393 (0 == strcmp(mTokBuf, "YES"))) {
394 out = true;
395 return true;
396 }
397 else if ((0 == strcmp(mTokBuf, "false")) ||
398 (0 == strcmp(mTokBuf, "FALSE")) ||
399 (0 == strcmp(mTokBuf, "no")) ||
400 (0 == strcmp(mTokBuf, "NO"))) {
401 out = false;
402 return true;
403 }
404 // ... otherwise, no boolean value detected.
405 return false;
406 }
407 };
408
409}
410
411#endif
A class for tokenizing input character streams.
Definition: tokenizer.h:52
bool getTokenString(std::string &returnTok)
get next token as a std::string
Definition: tokenizer.h:265
bool getTokenString(char out[], const uint32_t outmax)
get next token as a char array with maximum size.
Definition: tokenizer.h:276
uint32_t getTokenIntArray(int32_t out[], uint32_t size)
get next tokens as array of integer numbers
Definition: tokenizer.h:332
bool getLastToken(std::string &returnTok)
get last read token as a std::string
Definition: tokenizer.h:243
bool getTokenFloat(float &out)
get next token as a floating-point number
Definition: tokenizer.h:296
uint32_t getTokenFloatArray(float out[], uint32_t size)
get next tokens as array of floating point numbers
Definition: tokenizer.h:307
bool getTokenUint(uint32_t &out)
get next token as an unsigned integer
Definition: tokenizer.h:368
bool getTokenInt(int32_t &out)
get next token as an integer
Definition: tokenizer.h:357
const char * getLastTokenPtr()
accessor to get last read token const char *
Definition: tokenizer.h:252
char getTermChar() const
accessor to get character that caused 'stop' of last token read
Definition: tokenizer.h:238
uint32_t getLastTokenLen() const
accessor to get last read token length
Definition: tokenizer.h:258
bool getTokenBool(bool &out)
get next token as some form of boolean value/string
Definition: tokenizer.h:379
Definition: collider.cpp:182