1 /**
2 * MOAB, a Mesh-Oriented datABase, is a software component for creating,
3 * storing and accessing finite element mesh data.
4 *
5 * Copyright 2004 Sandia Corporation. Under the terms of Contract
6 * DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government
7 * retains certain rights in this software.
8 *
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
13 *
14 */
15
16 #ifndef FILE_TOKENIZER_HPP
17 #define FILE_TOKENIZER_HPP
18
19 #include "moab/Types.hpp"
20 #include <cstdio>
21 #include <sys/types.h>
22
23 namespace moab
24 {
25
26 class ReadUtilIface;
27
28 /**
29 * \brief Parse a file as space-separated tokens
30 * \author Jason Kraftcheck
31 * \date 30 Sept 2004
32 *
33 * Read a file, separating it into space-separated tokens.
34 * This is provided in place of using the standard C or C++
35 * file parsing routines because it counts lines, which is
36 * useful for error reporting. Also provides some useful
37 * utility methods for parsing VTK files (which is the
38 * intended use of this implementation.)
39 *
40 * Uses raw reads/writes, implementing internal buffering.
41 * Token size may not exceed buffer size.
42 */
43
44 class FileTokenizer
45 {
46 public:
47 /** \brief constructor
48 *
49 * \param file_ptr The file to read from.
50 * \param read_util_ptr Pointer to ReadUtilIface to use for
51 * reporting errors.
52 */
53 FileTokenizer( std::FILE* file_ptr, ReadUtilIface* read_util_ptr );
54
55 /** \brief destructor : closes file.
56 *
57 * The destructor closes the passed file handle. This
58 * is done as a convenience feature. If the caller
59 * creates an instance of this object on the stack, the
60 * file will automatically be closed when the caller
61 * returns.
62 */
63 ~FileTokenizer();
64
65 /** \brief get next token
66 *
67 * Get the next whitespace-delimited token from the file.
68 * NOTE: The returned string is only valid until the next
69 * call to any of the functions in this class that
70 * read from the file.
71 *
72 * \return A pointer to the buffer space containing the string,
73 * or NULL if an error occurred.
74 */
75 const char* get_string();
76
77 /** \brief check for newline
78 *
79 * Consume whitespace up to and including the next newline.
80 * If a non-space character is found before a newline,
81 * the function will stop, set the error message, and
82 * return false.
83 *
84 * \return True if a newline was found before any non-space
85 * character. False otherwise.
86 */
87 bool get_newline( bool report_error = true );
88
89 /** \brief Parse a sequence of double values.
90 *
91 * Read the specified number of space-delimited doubles.
92 *
93 * \param count The number of values to read.
94 * \param array The memory at which to store the values.
95 * \return true if successful, false otherwise.
96 */
97 bool get_doubles( size_t count, double* array );
98
99 /** \brief Parse a sequence of float values.
100 *
101 * Read the specified number of space-delimited doubles.
102 *
103 * \param count The number of values to read.
104 * \param array The memory at which to store the values.
105 * \return true if successful, false otherwise.
106 */
107 bool get_floats( size_t count, float* array );
108
109 /** \brief Parse a sequence of integer values.
110 *
111 * Read the specified number of space-delimited ints.
112 *
113 * \param count The number of values to read.
114 * \param array The memory at which to store the values.
115 * \return true if successful, false otherwise.
116 */
117 bool get_integers( size_t count, int* array );
118
119 /** \brief Parse a sequence of integer values.
120 *
121 * Read the specified number of space-delimited ints.
122 *
123 * \param count The number of values to read.
124 * \param array The memory at which to store the values.
125 * \return true if successful, false otherwise.
126 */
127 bool get_long_ints( size_t count, long* array );
128
129 /** \brief Parse a sequence of integer values.
130 *
131 * Read the specified number of space-delimited ints.
132 *
133 * \param count The number of values to read.
134 * \param array The memory at which to store the values.
135 * \return true if successful, false otherwise.
136 */
137 bool get_short_ints( size_t count, short* array );
138
139 /** \brief Parse a sequence of integer values.
140 *
141 * Read the specified number of space-delimited ints.
142 *
143 * \param count The number of values to read.
144 * \param array The memory at which to store the values.
145 * \return true if successful, false otherwise.
146 */
147 bool get_bytes( size_t count, unsigned char* array );
148
149 /** \brief Read binary data (interleaved with ASCII)
150 *
151 * Read a block of binary data.
152 *\param bytes Number of bytes to read
153 *\param mem Memory address at which to store data.
154 */
155 bool get_binary( size_t bytes, void* mem );
156
157 /** \brief Parse a sequence of bit or boolean values.
158 *
159 * Read the specified number of space-delimited values.
160 *
161 * \param count The number of values to read.
162 * \param array The memory at which to store the values.
163 * \return true if successful, false otherwise.
164 */
165 bool get_booleans( size_t count, bool* array );
166
167 /**
168 * Check for end-of-file condition.
169 */
170 bool eof() const;
171
172 /**
173 * Get the line number the last token was read from.
174 */
175 int line_number() const
176 {
177 return lineNumber;
178 }
179
180 /**
181 * Put current token back in buffer. Can only unget one token.
182 */
183 void unget_token();
184
185 /**
186 * Match current token to passed string. If token
187 * doesn't match, set error message.
188 */
189 bool match_token( const char* string, bool print_error = true );
190
191 /**
192 * Match the current token to one of an array of strings.
193 * Sets the error message if the current token doesn't
194 * match any of the input strings.
195 *
196 * \param string_list A NULL-terminated array of strings.
197 * \return One greater than the index of the matched
198 * string, or zero if no match.
199 */
200 int match_token( const char* const* string_list, bool print_error = true );
201
202 private:
203 /** Internal implementation of \ref get_doubles */
204 bool get_double_internal( double& result );
205 /** Internal implementation of \ref get_long_ints */
206 bool get_long_int_internal( long& result );
207 /** Internal implementation of \ref get_Booleans */
208 bool get_boolean_internal( bool& result );
209
210 /** Internal implementation of \ref get_floats */
211 bool get_float_internal( float& result );
212 /** Internal implementation of \ref get_integers */
213 bool get_integer_internal( int& result );
214 /** Internal implementation of \ref get_short_ints */
215 bool get_short_int_internal( short& result );
216 /** Internal implementation of \ref get_bytes */
217 bool get_byte_internal( unsigned char& result );
218
219 /** Pointer to standard C FILE struct */
220 std::FILE* filePtr;
221
222 /** Input buffer */
223 char buffer[512];
224
225 /** One past the end of the last token returned */
226 char* nextToken;
227 /** One past the last used byte of the buffer */
228 char* bufferEnd;
229
230 /** Line number of last returned token */
231 int lineNumber;
232
233 /** The whitespace character marking the end of the
234 * last returned token. Saved here because if it
235 * is a newline, the line count will need to be
236 * incremented when the next token is returned.
237 */
238 char lastChar;
239 };
240
241 } // namespace moab
242
243 #endif