Vcsn  2.4
Be Rational
stream.cc
Go to the documentation of this file.
1 #include <vcsn/misc/stream.hh>
2 
3 #include <cassert>
4 #include <cstring> // strerror
5 #include <istream>
6 #include <fstream>
7 
8 #include <vcsn/misc/raise.hh>
9 
10 namespace vcsn
11 {
12 
13  std::ostream cnull{nullptr};
14  std::wostream wcnull{nullptr};
15 
16  std::string
17  bracketed(std::istream& i, const char lbracket, const char rbracket)
18  {
19  assert(i.peek() == lbracket);
20  i.ignore();
21  size_t level = 1;
22  std::ostringstream o;
23  int c;
24  while ((c = i.get()) != -1)
25  {
26  if (c == lbracket)
27  ++level;
28  else if (c == rbracket
29  && !--level)
30  return o.str();
31  o << char(c);
32  }
33  raise("missing ", str_escape(rbracket), " after ",
34  str_escape(lbracket), o.str());
35  }
36 
37  char get_char(std::istream& i)
38  {
39  int res = i.get();
40  if (res == '\\')
41  switch (int c = i.get())
42  {
43  // Usual escapes.
44 #define CASE(Key, Value) \
45  case Key: res = Value; i.ignore(); break
46  CASE('a', '\a');
47  CASE('b', '\b');
48  CASE('f', '\f');
49  CASE('n', '\n');
50  CASE('r', '\r');
51  CASE('t', '\t');
52  CASE('v', '\v');
53 #undef CASE
54 
55  // Hexadecimal escapes.
56  case 'x':
57  {
58  // Handle hexadecimal escape.
59  int c1 = i.get();
60  require(c1 != EOF,
61  "get_char: unexpected end-of-file"
62  " after: \\x");
63  require(isxdigit(c1),
64  "get_char: invalid escape: \\x", char(c1));
65  int c2 = i.get();
66  require(c2 != EOF,
67  "get_char: unexpected end-of-file"
68  " after: \\x", char(c1));
69  require(isxdigit(c2),
70  "get_char: invalid escape: \\x",
71  char(c1), char(c2));
72  res = std::stoi(std::string{char(c1), char(c2)}, nullptr, 16);
73  }
74  break;
75 
76  // Other escapes, e.g., \\, \", \', etc. \(, \) and \-
77  // are used in setalpha::make, e.g., char_letters(\(\-\)).
78  default:
79  require(!std::isalnum(c),
80  "get_char: invalid escape: \\", char(c), " in \\",
81  char(c), i);
82  res = c;
83  break;
84  }
85  require(res != EOF,
86  "get_char: unexpected end-of-file");
87  return res;
88  }
89 
90  char eat(std::istream& is, char c)
91  {
92  if (is.peek() == c)
93  {
94  is.ignore();
95  return c;
96  }
97  else
98  fail_reading(is, "expected ", str_escape(c), ", got");
99  }
100 
101  const std::string& eat(std::istream& is, const std::string& expect)
102  {
103  std::string s;
104  char c;
105  size_t cnt = expect.size();
106  while (cnt && is >> c)
107  {
108  s.append(1, c);
109  --cnt;
110  }
111  VCSN_REQUIRE(s == expect,
112  "unexpected: ", str_escape(s),
113  ": expected ", str_escape(expect));
114  return expect;
115  }
116 
117  // http://stackoverflow.com/questions/2602013.
118  std::string
119  get_file_contents(const std::string& file)
120  {
121  std::ifstream in(file.c_str(), std::ios::in | std::ios::binary);
122  VCSN_REQUIRE(in.good(), "cannot read file: ", file, ": ", strerror(errno));
123 
124  std::string res;
125  in.seekg(0, std::ios::end);
126  res.resize(in.tellg());
127  in.seekg(0, std::ios::beg);
128  in.read(&res[0], res.size());
129  in.close();
130  return res;
131  }
132 
133  std::shared_ptr<std::istream>
134  open_input_file(const std::string& file)
135  {
136  std::shared_ptr<std::istream> res;
137  if (file.empty() || file == "-")
138  res.reset(&std::cin, [](...){});
139  else
140  {
141  res.reset(new std::ifstream(file.c_str()));
142  VCSN_REQUIRE(res->good(),
143  "cannot open ", file, " for reading: ", strerror(errno));
144  }
145  return res;
146  }
147 
148  std::shared_ptr<std::ostream>
149  open_output_file(const std::string& file)
150  {
151  std::shared_ptr<std::ostream> res;
152  if (file.empty() || file == "-")
153  res.reset(&std::cout, [](...){});
154  else
155  {
156  res.reset(new std::ofstream(file.c_str()));
157  VCSN_REQUIRE(res->good(),
158  "cannot open ", file, " for writing: ", strerror(errno));
159  }
160  return res;
161  }
162 
163  void skip_space(std::istream& is)
164  {
165  while (isspace(is.peek()))
166  is.ignore();
167  }
168 }
char eat(std::istream &is, char c)
Check lookahead character and advance.
Definition: stream.cc:90
return res
Definition: multiply.hh:398
std::string bracketed(std::istream &i, char lbracket, char rbracket)
Extract the string which is here between lbracket and rbracket.
Definition: stream.cc:17
std::string get_file_contents(const std::string &file)
Return the contents of file.
Definition: stream.cc:119
std::ostream cnull
An narrow-char stream that discards the output.
Definition: stream.cc:13
void require(Bool b, Args &&...args)
If b is not verified, raise an error with args as message.
Definition: raise.hh:91
std::shared_ptr< std::istream > open_input_file(const std::string &file)
Open file for reading and return its autoclosing stream.
Definition: stream.cc:134
Definition: a-star.hh:8
auto in(const Aut &aut, state_t_of< Aut > s)
Indexes of visible transitions arriving to state s.
Definition: automaton.hh:134
#define VCSN_REQUIRE(Cond,...)
A macro similar to require.
Definition: raise.hh:111
void skip_space(std::istream &is)
Ignore spaces.
Definition: stream.cc:163
char get_char(std::istream &i)
Read a single char, with possible -escape support.
Definition: stream.cc:37
std::ostream & str_escape(std::ostream &os, const std::string &str, const char *special=nullptr)
Output a string, escaping special characters.
Definition: escape.cc:51
#define CASE(Key, Value)
std::wostream wcnull
An wide-char stream that discards the output.
Definition: stream.cc:14
ATTRIBUTE_NORETURN void fail_reading(std::istream &is, Args &&...args)
Throw an exception after failing to read from is.
Definition: stream.hh:68
std::shared_ptr< std::ostream > open_output_file(const std::string &file)
Open file for writing and return its autoclosing stream.
Definition: stream.cc:149