1 /* -*- C++ -*- |
|
2 * src/lemon/bits/item_reader.h - Part of LEMON, a generic C++ optimization library |
|
3 * |
|
4 * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport |
|
5 * (Egervary Research Group on Combinatorial Optimization, EGRES). |
|
6 * |
|
7 * Permission to use, modify and distribute this software is granted |
|
8 * provided that this copyright notice appears in all copies. For |
|
9 * precise terms see the accompanying LICENSE file. |
|
10 * |
|
11 * This software is provided "AS IS" with no warranty of any kind, |
|
12 * express or implied, and with no claim as to its suitability for any |
|
13 * purpose. |
|
14 * |
|
15 */ |
|
16 |
|
17 /// @defgroup item_io Item Readers and Writers |
|
18 /// @ingroup io_group |
|
19 /// \brief Item Readers and Writers |
|
20 /// |
|
21 /// The Input-Output classes can handle more data type by example |
|
22 /// as map or attribute value. Each of these should be written and |
|
23 /// read some way. The module make possible to do this. |
|
24 |
|
25 /// \ingroup item_io |
|
26 /// \file |
|
27 /// \brief Item reader bits for lemon input. |
|
28 |
|
29 #ifndef LEMON_BITS_ITEM_READER_H |
|
30 #define LEMON_BITS_ITEM_READER_H |
|
31 |
|
32 #include <iostream> |
|
33 #include <string> |
|
34 |
|
35 #include <vector> |
|
36 #include <deque> |
|
37 #include <list> |
|
38 #include <set> |
|
39 |
|
40 namespace lemon { |
|
41 |
|
42 template <typename Value> |
|
43 class DefaultReader; |
|
44 |
|
45 /// \ingroup item_io |
|
46 /// |
|
47 /// \brief Reader class for quoted strings. |
|
48 /// |
|
49 /// Reader class for quoted strings. It can process the escape |
|
50 /// sequences in the string. |
|
51 /// |
|
52 /// \author Balazs Dezso |
|
53 class QuotedStringReader { |
|
54 public: |
|
55 /// \brief The value type of reader. |
|
56 /// |
|
57 /// The value type of reader. |
|
58 typedef std::string Value; |
|
59 |
|
60 /// \brief Constructor for the reader. |
|
61 /// |
|
62 /// Constructor for the reader. If the given parameter is true |
|
63 /// the reader processes the escape sequences. |
|
64 QuotedStringReader(bool _escaped = true) |
|
65 : escaped(_escaped) {} |
|
66 |
|
67 /// \brief Reads a quoted string from the given stream. |
|
68 /// |
|
69 /// Reads a quoted string from the given stream. |
|
70 void read(std::istream& is, std::string& value) const { |
|
71 char c; |
|
72 value.clear(); |
|
73 is >> std::ws; |
|
74 if (!is.get(c) || c != '\"') |
|
75 throw DataFormatError("Quoted string format error"); |
|
76 while (is.get(c) && c != '\"') { |
|
77 if (escaped && c == '\\') { |
|
78 value += readEscape(is); |
|
79 } else { |
|
80 value += c; |
|
81 } |
|
82 } |
|
83 if (!is) throw DataFormatError("Quoted string format error"); |
|
84 } |
|
85 |
|
86 private: |
|
87 |
|
88 static char readEscape(std::istream& is) { |
|
89 char c; |
|
90 switch (is.get(c), c) { |
|
91 case '\\': |
|
92 return '\\'; |
|
93 case '\"': |
|
94 return '\"'; |
|
95 case '\'': |
|
96 return '\''; |
|
97 case '\?': |
|
98 return '\?'; |
|
99 case 'a': |
|
100 return '\a'; |
|
101 case 'b': |
|
102 return '\b'; |
|
103 case 'f': |
|
104 return '\f'; |
|
105 case 'n': |
|
106 return '\n'; |
|
107 case 'r': |
|
108 return '\r'; |
|
109 case 't': |
|
110 return '\t'; |
|
111 case 'v': |
|
112 return '\v'; |
|
113 case 'x': |
|
114 { |
|
115 int code; |
|
116 if (!is.get(c) || !isHex(c)) |
|
117 throw DataFormatError("Escape format error"); |
|
118 else if (code = valueHex(c), !is.get(c) || !isHex(c)) is.putback(c); |
|
119 else code = code * 16 + valueHex(c); |
|
120 return code; |
|
121 } |
|
122 default: |
|
123 { |
|
124 int code; |
|
125 if (!isOct(c)) |
|
126 throw DataFormatError("Escape format error"); |
|
127 else if (code = valueOct(c), !is.get(c) || !isOct(c)) |
|
128 is.putback(c); |
|
129 else if (code = code * 8 + valueOct(c), !is.get(c) || !isOct(c)) |
|
130 is.putback(c); |
|
131 else code = code * 8 + valueOct(c); |
|
132 return code; |
|
133 } |
|
134 } |
|
135 } |
|
136 |
|
137 static bool isOct(char c) { |
|
138 return '0' <= c && c <='7'; |
|
139 } |
|
140 |
|
141 static int valueOct(char c) { |
|
142 return c - '0'; |
|
143 } |
|
144 |
|
145 static bool isHex(char c) { |
|
146 return ('0' <= c && c <= '9') || |
|
147 ('a' <= c && c <= 'z') || |
|
148 ('A' <= c && c <= 'Z'); |
|
149 } |
|
150 |
|
151 static int valueHex(char c) { |
|
152 if ('0' <= c && c <= '9') return c - '0'; |
|
153 if ('a' <= c && c <= 'z') return c - 'a' + 10; |
|
154 return c - 'A' + 10; |
|
155 } |
|
156 |
|
157 bool escaped; |
|
158 }; |
|
159 |
|
160 /// \ingroup item_io |
|
161 /// \brief Reader for standard containers. |
|
162 /// |
|
163 /// Reader for back insertable standard containers. The representation |
|
164 /// of the container is the values enumerated between an open and a |
|
165 /// close parse. |
|
166 /// |
|
167 /// \author Balazs Dezso |
|
168 template < |
|
169 typename _Container, |
|
170 typename _ItemReader = DefaultReader<typename _Container::value_type> |
|
171 > |
|
172 class PushBackReader { |
|
173 public: |
|
174 typedef _Container Value; |
|
175 typedef _ItemReader ItemReader; |
|
176 |
|
177 private: |
|
178 |
|
179 ItemReader item_reader; |
|
180 |
|
181 public: |
|
182 |
|
183 /// \brief Reads the values into the container from the given stream. |
|
184 /// |
|
185 /// Reads the values into the container from the given stream. |
|
186 void read(std::istream& is, Value& value) const { |
|
187 char c; |
|
188 if (!(is >> c) || c != '(') |
|
189 throw DataFormatError("PushBackReader format error"); |
|
190 while (is >> c && c != ')') { |
|
191 is.putback(c); |
|
192 typename ItemReader::Value item; |
|
193 item_reader.read(is, item); |
|
194 value.push_back(item); |
|
195 } |
|
196 if (!is) throw DataFormatError("PushBackReader format error"); |
|
197 is.putback(c); |
|
198 } |
|
199 |
|
200 }; |
|
201 |
|
202 /// \ingroup item_io |
|
203 /// |
|
204 /// \brief Reader for standard containers. |
|
205 /// |
|
206 /// Reader for insertable standard containers. The representation |
|
207 /// of the container is the values enumerated between an open and a |
|
208 /// close parse. |
|
209 /// |
|
210 /// \author Balazs Dezso |
|
211 template < |
|
212 typename _Container, |
|
213 typename _ItemReader = DefaultReader<typename _Container::value_type> |
|
214 > |
|
215 class InsertReader { |
|
216 public: |
|
217 typedef _Container Value; |
|
218 typedef _ItemReader ItemReader; |
|
219 |
|
220 private: |
|
221 |
|
222 ItemReader item_reader; |
|
223 |
|
224 public: |
|
225 |
|
226 /// \brief Reads the values into the container from the given stream. |
|
227 /// |
|
228 /// Reads the values into the container from the given stream. |
|
229 void read(std::istream& is, Value& value) const { |
|
230 char c; |
|
231 if (!(is >> c) || c != '(') |
|
232 throw DataFormatError("InsertReader format error"); |
|
233 while (is >> c && c != ')') { |
|
234 is.putback(c); |
|
235 typename ItemReader::Value item; |
|
236 item_reader.read(is, item); |
|
237 value.insert(item); |
|
238 } |
|
239 if (!is) throw DataFormatError("PushBackReader format error"); |
|
240 is.putback(c); |
|
241 } |
|
242 |
|
243 }; |
|
244 |
|
245 /// \ingroup item_io |
|
246 /// \brief Reader for parsed string. |
|
247 /// |
|
248 /// Reader for parsed strings. You can give the open and close |
|
249 /// parse characters. |
|
250 /// |
|
251 /// \author Balazs Dezso |
|
252 class ParsedStringReader { |
|
253 public: |
|
254 typedef std::string Value; |
|
255 |
|
256 /// \brief Constructor. |
|
257 /// |
|
258 /// Constructor for ParsedStringReader. You can give as parameter |
|
259 /// the open and close parse characters. |
|
260 ParsedStringReader(char _open = '(', char _close = ')') |
|
261 : open(_open), close(_close) {} |
|
262 |
|
263 |
|
264 /// \brief Reads the parsed string from the given stream. |
|
265 /// |
|
266 /// Reads the parsed string from the given stream. |
|
267 void read(std::istream& is, Value& value) const { |
|
268 char c; |
|
269 if (!(is >> c) || c != open) { |
|
270 throw DataFormatError("ParsedStringReader format error"); |
|
271 } |
|
272 value += c; |
|
273 int counter = 1; |
|
274 while (counter > 0 && is >> c) { |
|
275 if (c == close) { |
|
276 --counter; |
|
277 } else if (c == open) { |
|
278 ++counter; |
|
279 } |
|
280 value += c; |
|
281 } |
|
282 if (!is) { |
|
283 throw DataFormatError("ParsedStrinReader format error"); |
|
284 } |
|
285 } |
|
286 |
|
287 private: |
|
288 char open, close; |
|
289 |
|
290 }; |
|
291 |
|
292 /// \ingroup item_io |
|
293 /// \brief Reader for read the whole line. |
|
294 /// |
|
295 /// Reader for read the whole line. |
|
296 /// |
|
297 /// \author Balazs Dezso |
|
298 class LineReader { |
|
299 public: |
|
300 typedef std::string Value; |
|
301 |
|
302 /// \brief Constructor. |
|
303 /// |
|
304 /// Constructor for the LineReader. If the given parameter is |
|
305 /// true then the spaces before the first not space character are |
|
306 /// skipped. |
|
307 LineReader(bool _skipSpaces = true) : skipSpaces(_skipSpaces) {} |
|
308 |
|
309 /// \brief Reads the line from the given stream. |
|
310 /// |
|
311 /// Reads the line from the given stream. |
|
312 void read(std::istream& is, Value& value) { |
|
313 if (skipSpaces) is >> std::ws; |
|
314 if (!getline(is, value)) { |
|
315 throw DataFormatError("LineReader forma error"); |
|
316 } |
|
317 } |
|
318 private: |
|
319 bool skipSpaces; |
|
320 }; |
|
321 |
|
322 /// \ingroup item_io |
|
323 /// |
|
324 /// \brief The default item reader template class. |
|
325 /// |
|
326 /// The default item reader template class. If some section reader |
|
327 /// needs to read a value from a stream it will give the default way for it. |
|
328 /// |
|
329 /// \author Balazs Dezso |
|
330 template <typename _Value> |
|
331 class DefaultReader { |
|
332 public: |
|
333 /// The value type. |
|
334 typedef _Value Value; |
|
335 /// \brief Reads a value from the given stream. |
|
336 /// |
|
337 /// Reads a value from the given stream. |
|
338 void read(std::istream& is, Value& value) const { |
|
339 if (!(is >> value)) |
|
340 throw DataFormatError("DefaultReader format error"); |
|
341 } |
|
342 }; |
|
343 |
|
344 template <> |
|
345 class DefaultReader<std::string> { |
|
346 public: |
|
347 typedef std::string Value; |
|
348 |
|
349 void read(std::istream& is, Value& value) const { |
|
350 char c; |
|
351 if (!(is >> std::ws >> c)) return; |
|
352 is.putback(c); |
|
353 switch (c) { |
|
354 case '\"': |
|
355 QuotedStringReader().read(is, value); |
|
356 break; |
|
357 case '(': |
|
358 ParsedStringReader().read(is, value); |
|
359 break; |
|
360 default: |
|
361 is >> value; |
|
362 break; |
|
363 } |
|
364 } |
|
365 |
|
366 }; |
|
367 |
|
368 template <typename Item> |
|
369 class DefaultReader<std::vector<Item> > |
|
370 : public PushBackReader<std::vector<Item> > {}; |
|
371 |
|
372 template <typename Item> |
|
373 class DefaultReader<std::deque<Item> > |
|
374 : public PushBackReader<std::deque<Item> > {}; |
|
375 |
|
376 template <typename Item> |
|
377 class DefaultReader<std::list<Item> > |
|
378 : public PushBackReader<std::list<Item> > {}; |
|
379 |
|
380 template <typename Item> |
|
381 class DefaultReader<std::set<Item> > |
|
382 : public InsertReader<std::set<Item> > {}; |
|
383 |
|
384 template <typename Item> |
|
385 class DefaultReader<std::multiset<Item> > |
|
386 : public InsertReader<std::multiset<Item> > {}; |
|
387 |
|
388 /// \ingroup item_io |
|
389 /// |
|
390 /// \brief The default item reader for skipping a value in the stream. |
|
391 /// |
|
392 /// The default item reader for skipping a value in the stream. |
|
393 /// |
|
394 /// \author Balazs Dezso |
|
395 class DefaultSkipper : public DefaultReader<std::string> {}; |
|
396 |
|
397 /// \ingroup item_io |
|
398 /// \brief Standard ReaderTraits for the GraphReader class. |
|
399 /// |
|
400 /// Standard ReaderTraits for the GraphReader class. |
|
401 /// It defines standard reading method for all type of value. |
|
402 /// \author Balazs Dezso |
|
403 struct DefaultReaderTraits { |
|
404 |
|
405 template <typename _Value> |
|
406 struct Reader : DefaultReader<_Value> {}; |
|
407 |
|
408 typedef DefaultSkipper Skipper; |
|
409 |
|
410 }; |
|
411 |
|
412 } |
|
413 |
|
414 #endif |
|