29 #ifdef MSQ_USE_OLD_C_HEADERS
42 FileTokenizer::FileTokenizer( FILE* file_ptr )
43 : filePtr( file_ptr ),
50 FileTokenizer::~FileTokenizer()
53 bool FileTokenizer::eof()
const
54 {
return nextToken == bufferEnd && feof(filePtr); }
56 const char* FileTokenizer::get_string(
MsqError& err )
68 if (nextToken == bufferEnd)
70 size_t count =
fread( buffer, 1,
sizeof(buffer) - 1, filePtr );
74 MSQ_SETERR(err)(
"File truncated.\n", MsqError::PARSE_ERROR );
81 bufferEnd = buffer + count;
85 if (!isspace(*nextToken))
90 if (*nextToken ==
'\n')
98 char* result = nextToken;
99 while (nextToken != bufferEnd && !isspace(*nextToken))
106 if (nextToken == bufferEnd)
109 size_t remaining = bufferEnd - result;
110 memmove( buffer, result, remaining );
112 nextToken = result + remaining;
115 size_t count =
fread( nextToken, 1,
sizeof(buffer) - remaining - 1, filePtr );
116 if (!count && !feof(filePtr))
118 MSQ_SETERR(err)(
"I/O error.\n", MsqError::IO_ERROR );
121 bufferEnd = nextToken + count;
125 while (nextToken != bufferEnd && !isspace(*nextToken))
128 if (nextToken == bufferEnd)
136 lastChar = *nextToken;
144 bool FileTokenizer::get_double_internal(
double& result,
MsqError& err )
147 const char *token_end, *token = get_string( err );
154 if (token[0] && token[1] && token[0] ==
'0' && toupper(token[1]) ==
'X')
157 "Syntax error at line %d: expected number, got \"%s\"",
158 line_number(), token );
164 result = strtod( token, (
char**)&token_end );
172 "Syntax error at line %d: expected number, got \"%s\"",
173 line_number(), token );
180 bool FileTokenizer::get_float_internal(
float& result,
MsqError& err )
183 get_double_internal( d, err );
188 if (d != (
double)result)
190 MSQ_SETERR(err)( MsqError::PARSE_ERROR,
"Numberic overflow at line %d.", line_number() );
197 bool FileTokenizer::get_long_int_internal(
long& result,
MsqError& err )
200 const char *token_end, *token = get_string( err );
205 result = strtol( token, (
char**)&token_end, 0 );
213 "Syntax error at line %d: expected integer, got \"%s\"",
214 line_number(), token );
221 bool FileTokenizer::get_byte_internal(
unsigned char& result,
MsqError& err )
224 get_long_int_internal( i, err );
228 result = (
unsigned char)i;
229 if (i != (
long)result)
231 MSQ_SETERR(err)( MsqError::PARSE_ERROR,
"Numberic overflow at line %d.", line_number() );
238 bool FileTokenizer::get_short_int_internal(
short& result,
MsqError& err )
241 get_long_int_internal( i, err );
246 if (i != (
long)result)
248 MSQ_SETERR(err)( MsqError::PARSE_ERROR,
"Numberic overflow at line %d.", line_number() );
255 bool FileTokenizer::get_integer_internal(
int& result,
MsqError& err )
258 get_long_int_internal( i, err );
263 if (i != (
long)result)
265 MSQ_SETERR(err)( MsqError::PARSE_ERROR,
"Numberic overflow at line %d.", line_number() );
272 bool FileTokenizer::get_boolean_internal(
bool& result,
MsqError& err )
275 const char *token = get_string( err );
279 if (token[1] || (token[0] !=
'0' && token[0] !=
'1'))
282 "Syntax error at line %d: expected 0 or 1, got \"%s\"",
283 line_number(), token );
287 result = token[0] ==
'1';
291 bool FileTokenizer::get_floats(
size_t count,
float* array,
MsqError& err )
293 for (
size_t i = 0;
i < count; ++
i)
295 if (!get_float_internal( *array, err ))
302 bool FileTokenizer::get_doubles(
size_t count,
double* array,
MsqError& err )
304 for (
size_t i = 0;
i < count; ++
i)
306 get_double_internal( *array, err );
314 bool FileTokenizer::get_bytes(
size_t count,
unsigned char* array,
MsqError& err )
316 for (
size_t i = 0;
i < count; ++
i)
318 get_byte_internal( *array, err );
326 bool FileTokenizer::get_short_ints(
size_t count,
short* array,
MsqError& err )
328 for (
size_t i = 0;
i < count; ++
i)
330 get_short_int_internal( *array, err );
339 bool FileTokenizer::get_integers(
size_t count,
int* array,
MsqError& err )
341 for (
size_t i = 0;
i < count; ++
i)
343 get_integer_internal( *array, err );
351 bool FileTokenizer::get_long_ints(
size_t count,
long* array,
MsqError& err )
353 for (
size_t i = 0;
i < count; ++
i)
355 get_long_int_internal( *array, err );
363 bool FileTokenizer::get_booleans(
size_t count,
bool* array,
MsqError& err )
365 for (
size_t i = 0;
i < count; ++
i)
367 get_boolean_internal( *array, err );
375 void FileTokenizer::unget_token()
377 if (nextToken - buffer < 2)
381 *nextToken = lastChar;
383 while (nextToken > buffer && *nextToken)
392 bool FileTokenizer::match_token(
const char* str,
MsqError& err )
395 const char *token = get_string( err );
400 if (0 == strcmp( token, str ))
405 "Syntax error at line %d: expected \"%s\", got \"%s\"",
406 line_number(), str, token );
411 int FileTokenizer::match_token(
const char*
const* list,
MsqError& err )
414 const char *token = get_string( err );
419 const char*
const* ptr;
420 for (ptr = list; *ptr; ++ptr)
421 if (0 == strcmp( token, *ptr ))
422 return ptr - list + 1;
425 msq_std::string message(
"Parsing error at line " );
427 sprintf( lineno,
"%d", line_number() );
429 message +=
": expected one of {";
430 for (ptr = list; *ptr; ++ptr)
435 message +=
" } got \"";
438 MSQ_SETERR(err)( message, MsqError::PARSE_ERROR );
444 if (lastChar ==
'\n')
456 if (nextToken == bufferEnd)
458 size_t count =
fread( buffer, 1,
sizeof(buffer), filePtr );
462 MSQ_SETERR(err)(
"File truncated.", MsqError::PARSE_ERROR );
469 bufferEnd = buffer + count;
473 if (!isspace(*nextToken))
475 MSQ_SETERR(err)( MsqError::PARSE_ERROR,
"Expected newline at line %d.", line_number() );
481 if (*nextToken ==
'\n')
int fread(T *const ptr, const unsigned int nmemb, std::FILE *stream)
Read file data, and check for possible errors.
Used to hold the error state and return it to the application.
int fclose(std::FILE *file)
Close a file, and check for possible errors.
#define MSQ_CHKERR(err)
Mesquite's Error Checking macro.
#define MSQ_SETERR(err)
Macro to set error - use err.clear() to clear.