2 * lemon/bits/item_reader.h - Part of LEMON, a generic C++ optimization library
4 * Copyright (C) 2006 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
5 * (Egervary Research Groin on Combinatorial Optimization, EGRES).
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.
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
17 /// @defgroin item_io Item Readers and Writers
19 /// \brief Item Readers and Writers
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.
27 /// \brief Item reader bits for lemon input.
29 #ifndef LEMON_BITS_ITEM_READER_H
30 #define LEMON_BITS_ITEM_READER_H
42 template <typename Value>
47 /// \brief Reader class for quoted strings.
49 /// Reader class for quoted strings. It can process the escape
50 /// sequences in the string.
52 /// \author Balazs Dezso
53 class QuotedStringReader {
55 /// \brief The value type of reader.
57 /// The value type of reader.
58 typedef std::string Value;
60 /// \brief Constructor for the reader.
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) {}
67 /// \brief Reads a quoted string from the given stream.
69 /// Reads a quoted string from the given stream.
70 void read(std::istream& is, std::string& value) const {
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);
83 if (!is) throw DataFormatError("Quoted string format error");
88 static char readEscape(std::istream& is) {
90 switch (is.get(c), c) {
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);
126 throw DataFormatError("Escape format error");
127 else if (code = valueOct(c), !is.get(c) || !isOct(c))
129 else if (code = code * 8 + valueOct(c), !is.get(c) || !isOct(c))
131 else code = code * 8 + valueOct(c);
137 static bool isOct(char c) {
138 return '0' <= c && c <='7';
141 static int valueOct(char c) {
145 static bool isHex(char c) {
146 return ('0' <= c && c <= '9') ||
147 ('a' <= c && c <= 'z') ||
148 ('A' <= c && c <= 'Z');
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;
161 /// \brief Reader for standard containers.
163 /// Reader for back insertable standard containers. The representation
164 /// of the container is the values enumerated between an open and a
167 /// \author Balazs Dezso
170 typename _ItemReader = DefaultReader<typename _Container::value_type>
172 class PushBackReader {
174 typedef _Container Value;
175 typedef _ItemReader ItemReader;
179 ItemReader item_reader;
183 /// \brief Constructor for InsertReader
185 /// Constructor for InsertReader
186 PushBackReader(const ItemReader& _item_reader = ItemReader())
187 : item_reader(_item_reader) {}
189 /// \brief Reads the values into the container from the given stream.
191 /// Reads the values into the container from the given stream.
192 void read(std::istream& is, Value& value) const {
194 if (!(is >> c) || c != '(')
195 throw DataFormatError("PushBackReader format error");
196 while (is >> c && c != ')') {
198 typename ItemReader::Value item;
199 item_reader.read(is, item);
200 value.push_back(item);
202 if (!is) throw DataFormatError("PushBackReader format error");
209 /// \brief Reader for standard containers.
211 /// Reader for insertable standard containers. The representation
212 /// of the container is the values enumerated between an open and a
215 /// \author Balazs Dezso
218 typename _ItemReader = DefaultReader<typename _Container::value_type>
222 typedef _Container Value;
223 typedef _ItemReader ItemReader;
227 ItemReader item_reader;
231 /// \brief Constructor for InsertReader
233 /// Constructor for InsertReader
234 InsertReader(const ItemReader& _item_reader = ItemReader())
235 : item_reader(_item_reader) {}
237 /// \brief Reads the values into the container from the given stream.
239 /// Reads the values into the container from the given stream.
240 void read(std::istream& is, Value& value) const {
242 if (!(is >> c) || c != '(')
243 throw DataFormatError("InsertReader format error");
244 while (is >> c && c != ')') {
246 typename ItemReader::Value item;
247 item_reader.read(is, item);
250 if (!is) throw DataFormatError("PushBackReader format error");
256 /// \brief Reader for parsed string.
258 /// Reader for parsed strings. You can define the open and close
259 /// parse characters. It reads from the input a character sequence
260 /// which is right parsed.
262 /// \author Balazs Dezso
263 class ParsedStringReader {
265 typedef std::string Value;
267 /// \brief Constructor.
269 /// Constructor for ParsedStringReader. You can give as parameter
270 /// the open and close parse characters.
271 ParsedStringReader(char _open = '(', char _close = ')')
272 : open(_open), close(_close) {}
275 /// \brief Reads the parsed string from the given stream.
277 /// Reads the parsed string from the given stream.
278 void read(std::istream& is, Value& value) const {
280 if (!(is >> c) || c != open) {
281 throw DataFormatError("ParsedStringReader format error");
285 while (counter > 0 && is >> c) {
288 } else if (c == open) {
294 throw DataFormatError("ParsedStrinReader format error");
304 /// \brief Reader for read the whole line.
306 /// Reader for read the whole line.
308 /// \author Balazs Dezso
311 typedef std::string Value;
313 /// \brief Constructor.
315 /// Constructor for the LineReader. If the given parameter is
316 /// true then the spaces before the first not space character are
318 LineReader(bool _skipSpaces = true) : skipSpaces(_skipSpaces) {}
320 /// \brief Reads the line from the given stream.
322 /// Reads the line from the given stream.
323 void read(std::istream& is, Value& value) const {
324 if (skipSpaces) is >> std::ws;
325 if (!getline(is, value)) {
326 throw DataFormatError("LineReader format error");
334 /// \brief Reader for std::pair.
336 /// Reader for std::pair.
338 /// \author Balazs Dezso
339 template <typename _Pair,
340 typename _FirstReader =
341 DefaultReader<typename _Pair::first_type>,
342 typename _SecondReader =
343 DefaultReader<typename _Pair::second_type> >
348 typedef _FirstReader FirstReader;
349 typedef _SecondReader SecondReader;
353 FirstReader first_reader;
354 SecondReader second_reader;
358 /// \brief Constructor.
360 /// Constructor for the PairReader.
361 PairReader(const FirstReader& _first_reader = FirstReader(),
362 const SecondReader& _second_reader = SecondReader())
363 : first_reader(_first_reader), second_reader(_second_reader) {}
365 /// \brief Reads the pair from the given stream.
367 /// Reads the pair from the given stream.
368 void read(std::istream& is, Value& value) const {
370 if (!(is >> c) || c != '(') {
371 throw DataFormatError("PairReader format error");
373 first_reader.read(is, value.first);
374 if (!(is >> c) || c != '=') {
375 throw DataFormatError("PairReader format error");
377 if (!(is >> c) || c != '>') {
378 throw DataFormatError("PairReader format error");
380 second_reader.read(is, value.second);
381 if (!(is >> c) || c != ')') {
382 throw DataFormatError("PairReader format error");
389 /// \brief The default item reader template class.
391 /// The default item reader template class. If some section reader
392 /// needs to read a value from a stream it will give the default way for it.
394 /// \author Balazs Dezso
395 template <typename _Value>
396 class DefaultReader {
399 typedef _Value Value;
400 /// \brief Reads a value from the given stream.
402 /// Reads a value from the given stream.
403 void read(std::istream& is, Value& value) const {
405 throw DataFormatError("DefaultReader format error");
410 class DefaultReader<std::string> {
412 typedef std::string Value;
414 void read(std::istream& is, Value& value) const {
416 if (!(is >> std::ws >> c)) return;
420 QuotedStringReader().read(is, value);
423 ParsedStringReader().read(is, value);
426 ParsedStringReader('[', ']').read(is, value);
429 ParsedStringReader('/', '/').read(is, value);
433 throw DataFormatError("DefaultReader format error");
440 template <typename Item>
441 class DefaultReader<std::vector<Item> >
442 : public PushBackReader<std::vector<Item> > {};
444 template <typename Item>
445 class DefaultReader<std::deque<Item> >
446 : public PushBackReader<std::deque<Item> > {};
448 template <typename Item>
449 class DefaultReader<std::list<Item> >
450 : public PushBackReader<std::list<Item> > {};
452 template <typename Item>
453 class DefaultReader<std::set<Item> >
454 : public InsertReader<std::set<Item> > {};
456 template <typename Key, typename Value>
457 class DefaultReader<std::map<Key, Value> >
458 : public InsertReader<std::map<Key, Value>,
459 DefaultReader<std::pair<Key, Value> > > {};
461 template <typename Item>
462 class DefaultReader<std::multiset<Item> >
463 : public InsertReader<std::multiset<Item> > {};
465 template <typename Key, typename Value>
466 class DefaultReader<std::multimap<Key, Value> >
467 : public InsertReader<std::multimap<Key, Value>,
468 DefaultReader<std::pair<Key, Value> > > {};
470 template <typename First, typename Second>
471 class DefaultReader<std::pair<First, Second> >
472 : public PairReader<std::pair<First, Second> > {};
476 /// \brief The default item reader for skipping a value in the stream.
478 /// The default item reader for skipping a value in the stream.
480 /// \author Balazs Dezso
481 class DefaultSkipper : public DefaultReader<std::string> {};
484 /// \brief Standard ReaderTraits for the GraphReader class.
486 /// Standard ReaderTraits for the GraphReader class.
487 /// It defines standard reading method for all type of value.
488 /// \author Balazs Dezso
489 struct DefaultReaderTraits {
491 template <typename _Value>
492 struct Reader : DefaultReader<_Value> {};
494 typedef DefaultSkipper Skipper;