Choreonoid  1.8
SimpleScanner.h
Go to the documentation of this file.
1 #ifndef CNOID_UTIL_SIMPLE_SCANNER_H
2 #define CNOID_UTIL_SIMPLE_SCANNER_H
3 
4 #include "UTF8.h"
5 #include <cnoid/stdx/filesystem>
6 #include <fast_float/fast_float.h>
7 #include <fmt/format.h>
8 #include <fstream>
9 #include <stdexcept>
10 #include <cstdlib>
11 
12 namespace cnoid {
13 
15 {
16 public:
17  typedef std::ifstream::pos_type pos_type;
18 
19  std::ifstream ifs;
20  char* buf;
21  size_t bufsize;
22  const char* pos;
23  const char* dummy; // This makes the parse 10% faster in some architectures
24  const char* bufEndPos;
25  size_t lineNumber;
26  std::string filename;
27  std::string tmpString;
28 
29  static constexpr size_t buf1size = 256;
30  char buf1[buf1size];
31  std::vector<char> buf2;
32 
34  {
35  clear(false);
36  }
37 
38  void clear(bool doRelease = true)
39  {
40  buf = buf1;
41  bufsize = buf1size;
42  bufEndPos = buf + bufsize;
43  buf[0] = '\0';
44  pos = buf;
45  lineNumber = 0;
46 
47  if(doRelease){
48  buf2.clear();
49  buf2.shrink_to_fit();
50  }
51  }
52 
53  bool open(const std::string& filename)
54  {
55  clear();
56 
57  // The binary mode is faster on Windows
58  ifs.open(fromUTF8(filename), std::ios::in | std::ios::binary);
59  if(ifs.is_open()){
60  this->filename = filename;
61  return true;
62  }
63  return false;
64  }
65 
66  void close()
67  {
68  if(ifs.is_open()){
69  ifs.close();
70  }
71  }
72 
73  bool getLine()
74  {
75  pos = buf;
76  bool result = false;
77 
78 #ifndef _WIN32
79  if(ifs.getline(buf, bufsize)){
80  result = true;
81  }
82 #else
83  // The following code is faster on Windows
84  if(ifs.get(buf, bufsize, '\n')){
85  ifs.ignore();
86  result = true;
87  } else if(!ifs.eof() && ifs.fail()){
88  ifs.clear();
89  if(ifs.peek() == '\n'){
90  ifs.ignore();
91  result = true;
92  }
93  }
94 #endif
95  if(result){
96  ++lineNumber;
97  return true;
98  }
99 
100  if(!ifs.eof()){
101  int gcount = ifs.gcount();
102  if(gcount <= 0){
103  throwEx("I/O error");
104  } else {
105  bufsize = bufsize * 2;
106  buf2.resize(bufsize);
107  buf = &buf2[0];
108  bufEndPos = buf + bufsize;
109  ifs.clear();
110  ifs.seekg(-gcount, std::ios::cur);
111  return getLine();
112  }
113  }
114  buf[0] = '\0';
115  return !ifs.eof();
116  }
117 
118  const std::string& currentLine()
119  {
120  char* end = buf;
121  while(true){
122  if(*end == '\n' || *end == '\0'){
123  break;
124  }
125  ++end;
126  }
127  tmpString.assign(buf, end - buf);
128  return tmpString;
129  }
130 
131  void moveForward()
132  {
133  ++pos;
134  }
135 
136  void skipSpaces()
137  {
138  while(*pos == ' '){
139  ++pos;
140  }
141  }
142 
144  {
145  while(*pos == ' ' || *pos == '\t'){
146  ++pos;
147  }
148  }
149 
150  int peekChar()
151  {
152  return *pos;
153  }
154 
155  int readChar()
156  {
157  int c = *pos;
158  if(c != '\0'){
159  ++pos;
160  }
161  return c;
162  }
163 
165  {
166  if(*pos == chara){
167  ++pos;
168  return true;
169  }
170  return false;
171  }
172 
173  bool checkChar(int chara)
174  {
175  skipSpaces();
176  return checkCharAtCurrentPosition(chara);
177  }
178 
179  bool checkLF()
180  {
181  skipSpaces();
182  if(*pos == '\0'){
183  return true;
184  } else if(*pos == '\r'){
185  ++pos;
186  return true;
187  }
188  return false;
189  }
190 
191  void checkLFEx()
192  {
193  if(!checkLF()){
194  throwEx("Invalid value");
195  }
196  }
197 
198  bool checkEOF()
199  {
200  if(checkLF()){
201  return ifs.eof();
202  }
203  return false;
204  }
205 
207  {
208  const char* pos0 = pos;
209  while(*str != '\0'){
210  if(*str++ != *pos++){
211  pos = pos0;
212  return false;
213  }
214  }
215  return true;
216  }
217 
218  bool checkString(const char* str)
219  {
220  skipSpaces();
222  }
223 
224  void checkStringEx(const char* str)
225  {
226  const char* org = str;
227  if(!checkString(str)){
228  throwEx(fmt::format("\"{}\" is expected", org));
229  }
230  }
231 
232  bool seekToString(pos_type initialSeekPos, const char* str, size_t maxLength, pos_type& out_seekPos)
233  {
234  ifs.seekg(initialSeekPos);
235  getLine();
236 
237  pos_type currentLinePos = initialSeekPos;
238  pos_type nextLinePos = ifs.tellg();
239  const char* str0 = str;
240  char* found = nullptr;
241  while(true){
242  while(*pos != '\0'){
243  ++pos;
244  }
245  if(!getLine()){
246  break;
247  }
248  currentLinePos = nextLinePos;
249  nextLinePos = ifs.tellg();
250  if(currentLinePos - initialSeekPos > maxLength){
251  break;
252  }
253  skipSpaces();
254 
255  if(*pos == *str){
256  ++pos;
257  ++str;
258  while(true){
259  if(*str == '\0'){
260  out_seekPos = currentLinePos;
261  ifs.seekg(out_seekPos);
262  clear();
263  return true; // found
264  }
265  if(*pos++ != *str++){
266  str = str0;
267  break;
268  }
269  }
270  }
271  }
272  out_seekPos = initialSeekPos;
273  return false;
274  }
275 
276  bool readStringAtCurrentPosition(std::string& out_string)
277  {
278  const char* pos0 = pos;
279  // Todo: use isspace, iscontl, etc.
280  while((*pos != ' ') && (*pos != '\t') && (*pos != '\r') && (*pos != '\0')){
281  ++pos;
282  }
283  out_string.assign(pos0, pos - pos0);
284  return !out_string.empty();
285  }
286 
287  bool readString(std::string& out_string)
288  {
289  skipSpaces();
290  return readStringAtCurrentPosition(out_string);
291  }
292 
293  bool readStringToEOL(std::string& out_string)
294  {
295  skipSpaces();
296  const char* pos0 = pos;
297  while((*pos != '\r') && (*pos != '\n') && (*pos != '\0')){
298  ++pos;
299  }
300  out_string.assign(pos0, pos - pos0);
301  return !out_string.empty();
302  }
303 
304  float readFloatEx()
305  {
306  float value;
307  auto result = fast_float::from_chars(pos, bufEndPos, value);
308  if(result.ec == std::errc()){
309  pos = result.ptr;
310  } else {
311  throwEx("Invalid value");
312  }
313  return value;
314  }
315 
316  bool readInt(int& out_value)
317  {
318  char* tail;
319  out_value = std::strtol(pos, &tail, 0);
320  if(tail != pos){
321  pos = tail;
322  return true;
323  }
324  return false;
325  }
326 
327  int readIntEx()
328  {
329  char* tail;
330  int value = std::strtol(pos, &tail, 0);
331  if(tail != pos){
332  pos = tail;
333  } else {
334  throwEx("Invald value");
335  }
336  return value;
337  }
338 
339  void throwEx(const std::string& error)
340  {
341  stdx::filesystem::path path(fromUTF8(filename));
342  throw std::runtime_error(
343  fmt::format("{0} at line {1} of \"{2}\".",
344  error, lineNumber, toUTF8(path.filename().string())));
345  }
346 };
347 
348 }
349 
350 #endif
cnoid::fromUTF8
const std::string & fromUTF8(const std::string &text)
Definition: UTF8.h:20
cnoid::SimpleScanner::seekToString
bool seekToString(pos_type initialSeekPos, const char *str, size_t maxLength, pos_type &out_seekPos)
Definition: SimpleScanner.h:232
cnoid::SimpleScanner::filename
std::string filename
Definition: SimpleScanner.h:26
cnoid::SimpleScanner::buf2
std::vector< char > buf2
Definition: SimpleScanner.h:31
cnoid::SimpleScanner::getLine
bool getLine()
Definition: SimpleScanner.h:73
cnoid::SimpleScanner::readIntEx
int readIntEx()
Definition: SimpleScanner.h:327
cnoid::str
std::string str(const Vector3 &v)
Definition: EigenUtil.cpp:206
cnoid::SimpleScanner::buf1size
static constexpr size_t buf1size
Definition: SimpleScanner.h:29
cnoid::SimpleScanner::open
bool open(const std::string &filename)
Definition: SimpleScanner.h:53
cnoid::SimpleScanner::pos
const char * pos
Definition: SimpleScanner.h:22
cnoid::SimpleScanner::peekChar
int peekChar()
Definition: SimpleScanner.h:150
cnoid::SimpleScanner::readString
bool readString(std::string &out_string)
Definition: SimpleScanner.h:287
cnoid::SimpleScanner::checkEOF
bool checkEOF()
Definition: SimpleScanner.h:198
cnoid::SimpleScanner::skipSpaces
void skipSpaces()
Definition: SimpleScanner.h:136
cnoid::SimpleScanner::checkLF
bool checkLF()
Definition: SimpleScanner.h:179
cnoid::SimpleScanner::readChar
int readChar()
Definition: SimpleScanner.h:155
UTF8.h
cnoid::SimpleScanner::tmpString
std::string tmpString
Definition: SimpleScanner.h:27
cnoid::SimpleScanner::buf
char * buf
Definition: SimpleScanner.h:20
cnoid::SimpleScanner::readInt
bool readInt(int &out_value)
Definition: SimpleScanner.h:316
cnoid::SimpleScanner::readStringToEOL
bool readStringToEOL(std::string &out_string)
Definition: SimpleScanner.h:293
cnoid::SimpleScanner::checkCharAtCurrentPosition
bool checkCharAtCurrentPosition(int chara)
Definition: SimpleScanner.h:164
cnoid::SimpleScanner::ifs
std::ifstream ifs
Definition: SimpleScanner.h:19
cnoid::SimpleScanner::readStringAtCurrentPosition
bool readStringAtCurrentPosition(std::string &out_string)
Definition: SimpleScanner.h:276
cnoid::SimpleScanner::checkStringEx
void checkStringEx(const char *str)
Definition: SimpleScanner.h:224
cnoid
Definition: AbstractSceneLoader.h:11
cnoid::SimpleScanner::SimpleScanner
SimpleScanner()
Definition: SimpleScanner.h:33
cnoid::SimpleScanner::buf1
char buf1[buf1size]
Definition: SimpleScanner.h:30
cnoid::SimpleScanner::dummy
const char * dummy
Definition: SimpleScanner.h:23
cnoid::SimpleScanner::bufEndPos
const char * bufEndPos
Definition: SimpleScanner.h:24
cnoid::SimpleScanner::readFloatEx
float readFloatEx()
Definition: SimpleScanner.h:304
cnoid::SimpleScanner
Definition: SimpleScanner.h:14
cnoid::SimpleScanner::bufsize
size_t bufsize
Definition: SimpleScanner.h:21
cnoid::SimpleScanner::lineNumber
size_t lineNumber
Definition: SimpleScanner.h:25
cnoid::SimpleScanner::clear
void clear(bool doRelease=true)
Definition: SimpleScanner.h:38
cnoid::SimpleScanner::moveForward
void moveForward()
Definition: SimpleScanner.h:131
cnoid::SimpleScanner::skipSpacesAndTabs
void skipSpacesAndTabs()
Definition: SimpleScanner.h:143
cnoid::SimpleScanner::checkLFEx
void checkLFEx()
Definition: SimpleScanner.h:191
cnoid::SimpleScanner::close
void close()
Definition: SimpleScanner.h:66
cnoid::toUTF8
const std::string & toUTF8(const std::string &text)
Definition: UTF8.h:19
cnoid::SimpleScanner::throwEx
void throwEx(const std::string &error)
Definition: SimpleScanner.h:339
cnoid::SimpleScanner::checkString
bool checkString(const char *str)
Definition: SimpleScanner.h:218
cnoid::SimpleScanner::checkChar
bool checkChar(int chara)
Definition: SimpleScanner.h:173
cnoid::SimpleScanner::checkStringAtCurrentPosition
bool checkStringAtCurrentPosition(const char *str)
Definition: SimpleScanner.h:206
cnoid::SimpleScanner::currentLine
const std::string & currentLine()
Definition: SimpleScanner.h:118
cnoid::SimpleScanner::pos_type
std::ifstream::pos_type pos_type
Definition: SimpleScanner.h:17