Easy3D 2.6.1
Loading...
Searching...
No Matches
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
53 {
54 public:
60 explicit Tokenizer(const char* src, const char* delims = nullptr)
61 : mSrcBuf(src)
62 , mTokLen(0)
63 , mTermChar(0)
64 , mNumDelims(0)
65 , mConsumeWS(true)
66 {
67 if (nullptr == delims)
68 { // built in delim set.
69 mNumDelims = 3;
70 mDelims[0] = '=';
71 mDelims[1] = ',';
72 mDelims[2] = ':';
73 }
74 else
75 { // note that we DO support empty string, in which case
76 // we have no delims other than whitespace...
77 int i = 0;
78 mNumDelims = 0;
79 while (mNumDelims < NV_MAX_DELIM_COUNT && delims[i])
80 {
81 const char c = delims[i++];
82 // else skip built-in handled chars
83 if (c == ' ' || c == '\t' || // Whitespace
84 c == '"' || c == '\'' || // Quote
85 c == '\n' || c == '\r') // EOL
86 continue;
87 mDelims[mNumDelims++] = c;
88 }
89 }
90 }
91
96 void setConsumeWS(bool ws) { mConsumeWS = ws; }
97
103 bool isWhitespace(const char c) {
104 return (' ' == c || '\t' == c);
105 }
106
111 bool isQuote(const char c) {
112 return ('"' == c || '\'' == c);
113 }
114
119 bool isEOL(const char c) {
120 return ('\n' == c || '\r' == c);
121 }
122
127 bool isTerm(const char c) {
128 return (isWhitespace(c) || isEOL(c));
129 }
130
135 bool isDelim(const char c) { // TBD any other delims we want to call out.
136 for (uint32_t i = 0; i < mNumDelims; i++)
137 if (c == mDelims[i]) return true;
138 return false;
139 }
140
141
142 public:
147 bool atEOF() {
148 // EOF is if we've reached a null character. :)
149 return (0 == *mSrcBuf);
150 }
151
156 {
157 //VERBOSE_TOKEN_DEBUG("consuming whitespace");
158 mTermChar = 0;
159 while (!atEOF() && isWhitespace(*mSrcBuf))
160 mTermChar = *mSrcBuf++;
161 return mTermChar;
162 }
163
168 {
169 //VERBOSE_TOKEN_DEBUG("consuming delimiter");
171 mTermChar = 0;
172 // eat ONE delimiter...
173 if (!atEOF() && isDelim(*mSrcBuf)) {
174 mTermChar = *mSrcBuf++;
175 }
176 if (isEOL(*mSrcBuf))
177 mTermChar = *mSrcBuf; // so that we return the EOL but DON'T CONSUME IT.
178 return mTermChar;
179 }
180
184 {
185 while (!atEOF() && !isEOL(*mSrcBuf)) // eat up to the EOL
186 mSrcBuf++;
187 while (!atEOF() && isEOL(*mSrcBuf)) // if not null, then eat EOL chars until gone, in case of /r/n type stuff...
188 mSrcBuf++;
189 }
190
195 {
196 char startedWithQuote = 0; // we'll store the character if we get a quote
197 mTermChar = 0;
198 mTokLen = 0;
199 mTokBuf[0] = 0; // initialize
200 if (atEOF())
201 return false; // exit early...
202
203 if (mConsumeWS)
205 if (!atEOF() && isQuote(*mSrcBuf)) {
206 startedWithQuote = *mSrcBuf; // save WHAT quote character so we match it.
207 mSrcBuf++;
208 }
209
210 while (!atEOF()) { // termchar is already null so fine to exit loop.
211 // look for hard terminations (EOL)
212 if (isEOL(*mSrcBuf)) {
213 mTermChar = *mSrcBuf;
214 break;
215 }
216 // look to handle quoted strings, which CAN have delimiters validly in their contents.
217 if (startedWithQuote) {
218 if (startedWithQuote == *mSrcBuf) {
219 // consume and break.
220 mSrcBuf++;
221 mTermChar = startedWithQuote;
222 break;
223 }
224 }
225 else if (isDelim(*mSrcBuf) || isWhitespace(*mSrcBuf)) {
226 // just break, leave delim.
227 mTermChar = *mSrcBuf;
228 break;
229 }
230
231 mTokBuf[mTokLen] = *mSrcBuf; // copy char
232 mTokLen++; // inc length
233 mSrcBuf++; // inc buffer
234 }
235
236 // null-term buffer, do NOT inc length.
237 mTokBuf[mTokLen] = 0;
238
239 return (mTokLen > 0 || startedWithQuote); // false if empty string UNLESS quoted empty string...
240 }
241
246 bool requireToken(const char *find)
247 {
248 if (find == nullptr || find[0] == 0)
249 return false; // bad input.
250 if (!readToken())
251 return false;
252 // let's eliminate str functions...
253 const size_t findlen = strlen(find);
254 if (findlen != mTokLen)
255 return false; // early out.
256 if (0 != memcmp(mTokBuf, find, findlen))
257 return false;
258 // accepted.
259 return true;
260 }
261
266 bool requireTokenDelim(const char *find)
267 {
268 if (!requireToken(find))
269 return false;
270 if (!consumeOneDelim())
271 return false;
272 // accepted.
273 return true;
274 }
275
280 char getTermChar() const {
281 return mTermChar;
282 }
283
289 bool getLastToken(std::string& returnTok)
290 {
291 // we just return what's already in the buffer.
292 // handy for failure or unexpected cases.
293 returnTok.assign(mTokBuf);
294 return true;
295 }
296
301 const char* getLastTokenPtr() {
302 return mTokBuf;
303 }
304
309 uint32_t getLastTokenLen() const {
310 return mTokLen;
311 }
312
318 bool getTokenString(std::string& returnTok)
319 {
320 if (!readToken()) {
321 returnTok.clear();
322 return false;
323 }
324 returnTok.assign(mTokBuf);
325 return true;
326 }
327
334 bool getTokenString(char out[], const uint32_t outmax)
335 {
336 if (!readToken()) {
337 out[0] = 0;
338 return false;
339 }
340
341 // note mTokLen include the NULL terminator.
342 if (mTokLen > outmax)
343 {
344 // just have to truncate.
345 memcpy(out, mTokBuf, outmax - 1);
346 out[outmax - 1] = 0; // null terminate...
347 }
348 else
349 memcpy(out, mTokBuf, mTokLen + 1); // copy null!
350 return true;
351 }
352
358 bool getTokenFloat(float &out)
359 {
360 if (!readToken()) {
361 out = 0;
362 return false;
363 }
364 out = (float)strtod(mTokBuf, nullptr);
365 return true;
366 }
367
374 uint32_t getTokenFloatArray(float out[], uint32_t size)
375 {
376 uint32_t i = 0;
377 char firstdelim = 0, delim = 0;
378 while (i < size) {
379 if (firstdelim) {
380 // we had a delim initially, so we require (but can have repeated).
381 delim = consumeOneDelim();
382 if (delim == firstdelim)
383 continue;
384 }
385 if (!readToken())
386 break; // so we return what we've got.
387 out[i++] = (float)strtod(mTokBuf, nullptr);
388
389 // OPTIONALLY consume a delimiter between each number.
390 delim = consumeOneDelim();
391 if (delim && isEOL(delim)) // we didn't consume EOL, we are AT it though.
392 break;
393 if (i == 1) firstdelim = delim; // stash away.
394 }
395 return i; // return number of elements read.
396 }
397
404 uint32_t getTokenIntArray(int32_t out[], uint32_t size)
405 {
406 uint32_t i = 0;
407 char firstdelim = 0, delim = 0;
408 while (i < size) {
409 if (firstdelim) {
410 // we had a delim initially, so we require (but can have repeated).
411 delim = consumeOneDelim();
412 if (delim == firstdelim)
413 continue;
414 }
415 if (!readToken())
416 break; // so we return what we've got.
417 out[i++] = (int32_t)strtol(mTokBuf, nullptr, 0);
418
419 // OPTIONALLY consume a delimiter between each number.
420 delim = consumeOneDelim();
421 if (delim && isEOL(delim)) // we didn't consume EOL, we are AT it though.
422 break;
423 if (i == 1) firstdelim = delim; // stash away.
424 }
425 return i; // return number of elements read.
426 }
427
433 bool getTokenInt(int32_t &out)
434 {
435 if (!readToken()) {
436 out = 0;
437 return false;
438 }
439 out = (int32_t)strtol(mTokBuf, nullptr, 0);
440 return true;
441 }
442
448 bool getTokenUint(uint32_t &out)
449 {
450 if (!readToken()) {
451 out = 0;
452 return false;
453 }
454 out = (uint32_t)strtoul(mTokBuf, nullptr, 0);
455 return true;
456 }
457
463 bool getTokenBool(bool &out)
464 {
465 if (!readToken()) {
466 out = false;
467 return false;
468 }
469 if (mTokLen == 1 &&
470 (mTokBuf[0] == '0' || mTokBuf[0] == '1')) {
471 out = (mTokBuf[0] == '1');
472 return true;
473 }
474 else if ((0 == strcmp(mTokBuf, "true")) ||
475 (0 == strcmp(mTokBuf, "TRUE")) ||
476 (0 == strcmp(mTokBuf, "yes")) ||
477 (0 == strcmp(mTokBuf, "YES"))) {
478 out = true;
479 return true;
480 }
481 else if ((0 == strcmp(mTokBuf, "false")) ||
482 (0 == strcmp(mTokBuf, "FALSE")) ||
483 (0 == strcmp(mTokBuf, "no")) ||
484 (0 == strcmp(mTokBuf, "NO"))) {
485 out = false;
486 return true;
487 }
488 // ... otherwise, no boolean value detected.
489 return false;
490 }
491
492 protected:
493 const char* mSrcBuf; /*< This holds a pointer to an immutable char buffer. */
494 char mTokBuf[NV_MAX_TOKEN_LEN]; /*< This is a temporary buffer for collecting next token. */
495 uint32_t mTokLen; /*< This is the character length of current token, not including null termination. */
496 char mTermChar; /*< This is the character that caused us to stop parsing the current token. */
497 char mDelims[NV_MAX_DELIM_COUNT];
498 uint32_t mNumDelims;
499 private:
500 bool mConsumeWS;
501 };
502
503}
504
505#endif
bool getTokenString(std::string &returnTok)
Gets the next token as a std::string.
Definition tokenizer.h:318
bool getTokenString(char out[], const uint32_t outmax)
Gets the next token as a char array with a maximum size.
Definition tokenizer.h:334
uint32_t getTokenIntArray(int32_t out[], uint32_t size)
Gets the next tokens as an array of integer numbers.
Definition tokenizer.h:404
bool getLastToken(std::string &returnTok)
Gets the last read token as a std::string.
Definition tokenizer.h:289
bool atEOF()
Checks if the tokenizer has reached the end of the source string.
Definition tokenizer.h:147
bool isWhitespace(const char c)
Checks if the given character is a whitespace character.
Definition tokenizer.h:103
char consumeOneDelim()
Consumes one delimiter character from the source string.
Definition tokenizer.h:167
bool getTokenFloat(float &out)
Gets the next token as a floating-point number.
Definition tokenizer.h:358
uint32_t getTokenFloatArray(float out[], uint32_t size)
Gets the next tokens as an array of floating-point numbers.
Definition tokenizer.h:374
bool requireToken(const char *find)
Checks if the next token matches the given string.
Definition tokenizer.h:246
bool getTokenUint(uint32_t &out)
Gets the next token as an unsigned integer.
Definition tokenizer.h:448
void setConsumeWS(bool ws)
Sets whether to consume whitespace characters.
Definition tokenizer.h:96
char consumeWhitespace()
Consumes whitespace characters from the source string.
Definition tokenizer.h:155
Tokenizer(const char *src, const char *delims=nullptr)
Constructor that initializes the tokenizer with a source string and optional delimiters.
Definition tokenizer.h:60
bool getTokenInt(int32_t &out)
Gets the next token as an integer.
Definition tokenizer.h:433
bool isDelim(const char c)
Checks if the given character is a delimiter.
Definition tokenizer.h:135
const char * getLastTokenPtr()
Gets the last read token as a const char*.
Definition tokenizer.h:301
bool isTerm(const char c)
Checks if the given character is a termination character.
Definition tokenizer.h:127
char getTermChar() const
Gets the character that caused the stop of the last token read.
Definition tokenizer.h:280
uint32_t getLastTokenLen() const
Gets the length of the last read token.
Definition tokenizer.h:309
bool getTokenBool(bool &out)
Gets the next token as a boolean value.
Definition tokenizer.h:463
bool isEOL(const char c)
Checks if the given character is an end-of-line character.
Definition tokenizer.h:119
void consumeToEOL()
Consumes characters up to the end of the line.
Definition tokenizer.h:183
bool requireTokenDelim(const char *find)
Checks if the next token matches the given string and consumes a delimiter.
Definition tokenizer.h:266
bool readToken()
Reads the next token from the source string.
Definition tokenizer.h:194
bool isQuote(const char c)
Checks if the given character is a quote character.
Definition tokenizer.h:111
Definition collider.cpp:182