A toolkit for working with phylogenetic data.
v0.18.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
scanner.hpp
Go to the documentation of this file.
1 #ifndef GENESIS_UTILS_IO_SCANNER_H_
2 #define GENESIS_UTILS_IO_SCANNER_H_
3 
4 /*
5  Genesis - A toolkit for working with phylogenetic data.
6  Copyright (C) 2014-2017 Lucas Czech
7 
8  This program is free software: you can redistribute it and/or modify
9  it under the terms of the GNU General Public License as published by
10  the Free Software Foundation, either version 3 of the License, or
11  (at your option) any later version.
12 
13  This program is distributed in the hope that it will be useful,
14  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  GNU General Public License for more details.
17 
18  You should have received a copy of the GNU General Public License
19  along with this program. If not, see <http://www.gnu.org/licenses/>.
20 
21  Contact:
22  Lucas Czech <lucas.czech@h-its.org>
23  Exelixis Lab, Heidelberg Institute for Theoretical Studies
24  Schloss-Wolfsbrunnenweg 35, D-69118 Heidelberg, Germany
25 */
26 
34 #include <assert.h>
35 #include <cctype>
36 #include <functional>
37 #include <stdexcept>
38 
39 namespace genesis {
40 namespace utils {
41 
42 // =================================================================================================
43 // Helper Classes and Enums
44 // =================================================================================================
45 
60 enum class SkipWhitespace : unsigned char
61 {
65  kNone = 0,
66 
70  kLeading = 1,
71 
75  kTrailing = 2,
76 
80  kSurrounding = 3
81 };
82 
95 inline bool operator & ( SkipWhitespace lhs, SkipWhitespace rhs )
96 {
97  using T = std::underlying_type< SkipWhitespace >::type;
98  return static_cast< T >( lhs ) & static_cast< T >( rhs );
99 }
100 
101 // =================================================================================================
102 // Scanners
103 // =================================================================================================
104 
105 // -------------------------------------------------------------------------
106 // end of line
107 // -------------------------------------------------------------------------
108 
115 template< typename InputStream >
117  InputStream& source
118 ) {
119  while( source && *source != '\n' ) {
120  ++source;
121  }
122 }
123 
131 template< typename InputStream >
132 inline std::string read_to_end_of_line(
133  InputStream& source
134 ) {
135  std::string target;
136  while( source && *source != '\n' ) {
137  target += *source;
138  ++source;
139  }
140  return target;
141 }
142 
143 // -------------------------------------------------------------------------
144 // skip while
145 // -------------------------------------------------------------------------
146 
150 template< typename InputStream >
151 inline void skip_while(
152  InputStream& source,
153  char criterion
154 ) {
155  while( source && *source == criterion ) {
156  ++source;
157  }
158 }
159 
164 template< typename InputStream >
165 inline void skip_while(
166  InputStream& source,
167  std::function<bool (char)> criterion
168 ) {
169  while( source && criterion( *source )) {
170  ++source;
171  }
172 }
173 
174 // -------------------------------------------------------------------------
175 // skip until
176 // -------------------------------------------------------------------------
177 
181 template< typename InputStream >
182 inline void skip_until(
183  InputStream& source,
184  char criterion
185 ) {
186  while( source && *source != criterion ) {
187  ++source;
188  }
189 }
190 
195 template< typename InputStream >
196 inline void skip_until(
197  InputStream& source,
198  std::function<bool (char)> criterion
199 ) {
200  while( source && ! criterion( *source )) {
201  ++source;
202  }
203 }
204 
205 // -------------------------------------------------------------------------
206 // read while
207 // -------------------------------------------------------------------------
208 
213 template< typename InputStream >
214 inline std::string read_while(
215  InputStream& source,
216  char criterion
217 ) {
218  std::string target;
219  while( source && *source == criterion ) {
220  target += *source;
221  ++source;
222  }
223  return target;
224 }
225 
230 template< typename InputStream >
231 inline std::string read_while(
232  InputStream& source,
233  std::function<bool (char)> criterion
234 ) {
235  std::string target;
236  while( source && criterion( *source )) {
237  target += *source;
238  ++source;
239  }
240  return target;
241 }
242 
243 // -------------------------------------------------------------------------
244 // read until
245 // -------------------------------------------------------------------------
246 
251 template< typename InputStream >
252 inline std::string read_until(
253  InputStream& source,
254  char criterion
255 ) {
256  std::string target;
257  while( source && *source != criterion ) {
258  target += *source;
259  ++source;
260  }
261  return target;
262 }
263 
268 template< typename InputStream >
269 inline std::string read_until(
270  InputStream& source,
271  std::function<bool (char)> criterion
272 ) {
273  std::string target;
274  while( source && ! criterion( *source )) {
275  target += *source;
276  ++source;
277  }
278  return target;
279 }
280 
281 // -------------------------------------------------------------------------
282 // read char
283 // -------------------------------------------------------------------------
284 
296 template< typename InputStream >
297 inline char read_char_or_throw(
298  InputStream& source,
299  char criterion,
301 ) {
302  // Skip leading whitespace
303  if( skip_ws & SkipWhitespace::kLeading ) {
304  skip_while( source, isspace );
305  }
306 
307  // Check char and move to next.
308  if( !source || *source != criterion ) {
309  throw std::runtime_error(
310  std::string("Expecting '") + criterion + "' at " + source.at() + "."
311  );
312  }
313  assert( source && *source == criterion );
314  ++source;
315 
316  // Skip trailing whitespace
317  if( skip_ws & SkipWhitespace::kTrailing ) {
318  skip_while( source, isspace );
319  }
320 
321  return criterion;
322 }
323 
335 template< typename InputStream >
336 inline char read_char_or_throw(
337  InputStream& source,
338  std::function<bool (char)> criterion,
340 ) {
341  // Skip leading whitespace
342  if( skip_ws & SkipWhitespace::kLeading ) {
343  skip_while( source, isspace );
344  }
345 
346  // Check char and move to next.
347  if( !source || ! criterion( *source )) {
348  throw std::runtime_error(
349  "Unexpected char at " + source.at() + "."
350  );
351  }
352  assert( source );
353  auto chr = *source;
354  ++source;
355 
356  // Skip trailing whitespace
357  if( skip_ws & SkipWhitespace::kTrailing ) {
358  skip_while( source, isspace );
359  }
360 
361  return chr;
362 }
363 
364 // -------------------------------------------------------------------------
365 // expect char
366 // -------------------------------------------------------------------------
367 
379 template< typename InputStream >
381  InputStream& source,
382  char criterion,
384 ) {
385  // Skip leading whitespace
386  if( skip_ws & SkipWhitespace::kLeading ) {
387  skip_while( source, isspace );
388  }
389 
390  // Check char.
391  if( !source || *source != criterion ) {
392  throw std::runtime_error(
393  std::string("Expecting '") + criterion + "' at " + source.at() + "."
394  );
395  }
396 
397  // Skip trailing whitespace
398  if( skip_ws & SkipWhitespace::kTrailing ) {
399  skip_while( source, isspace );
400  }
401 }
402 
414 template< typename InputStream >
416  InputStream& source,
417  std::function<bool (char)> criterion,
419 ) {
420  // Skip leading whitespace
421  if( skip_ws & SkipWhitespace::kLeading ) {
422  skip_while( source, isspace );
423  }
424 
425  // Check char.
426  if( !source || ! criterion( *source )) {
427  throw std::runtime_error(
428  "Unexpected char at " + source.at() + "."
429  );
430  }
431 
432  // Skip trailing whitespace
433  if( skip_ws & SkipWhitespace::kTrailing ) {
434  skip_while( source, isspace );
435  }
436 }
437 
438 } // namespace utils
439 } // namespace genesis
440 
441 #endif // include guard
Skip no whitespace. Thus, immediately treat the current input char.
void skip_while(InputStream &source, char criterion)
Lexing function that advances the stream while its current char equals the provided one...
Definition: scanner.hpp:151
Skip all whitespace in the input stream, then treat the next non-white char.
bool operator&(SkipWhitespace lhs, SkipWhitespace rhs)
And-operator to check whether a SkipWhitespace is set.
Definition: scanner.hpp:95
std::string at() const
Return a textual representation of the current input position in the form "line:column".
std::string read_to_end_of_line(InputStream &source)
Lexing function that reads until the end of the line (i.e., to the new line char), and returns the read chars (excluding the new line char).
Definition: scanner.hpp:132
SkipWhitespace
Option to determine how to treat surrounding whitespace when scanning an input stream.
Definition: scanner.hpp:60
void skip_to_end_of_line(InputStream &source)
Lexing function that advances the stream to the end of the line, i.e., to the new line char...
Definition: scanner.hpp:116
std::string read_while(InputStream &source, char criterion)
Lexing function that reads from the stream while its current char equals the provided one...
Definition: scanner.hpp:214
Treat the current char in the input stream, then skip the following whitespace.
Skip whitespace, treat the first non-white char, then skip all following whitespace.
void affirm_char_or_throw(InputStream &source, char criterion, SkipWhitespace skip_ws=SkipWhitespace::kNone)
Lexing function that checks whether the current char from the stream equals the provided one...
Definition: scanner.hpp:380
char read_char_or_throw(InputStream &source, char criterion, SkipWhitespace skip_ws=SkipWhitespace::kNone)
Lexing function that reads a single char from the stream and checks whether it equals the provided on...
Definition: scanner.hpp:297
std::string read_until(InputStream &source, char criterion)
Lexing function that reads from the stream until its current char equals the provided one...
Definition: scanner.hpp:252
void skip_until(InputStream &source, char criterion)
Lexing function that advances the stream until its current char equals the provided one...
Definition: scanner.hpp:182
Stream interface for reading data from an InputSource, that keeps track of line and column counters...