3 * This file is a part of LEMON, a generic C++ optimization library
5 * Copyright (C) 2003-2006
6 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
7 * (Egervary Research Group on Combinatorial Optimization, EGRES).
9 * Permission to use, modify and distribute this software is granted
10 * provided that this copyright notice appears in all copies. For
11 * precise terms see the accompanying LICENSE file.
13 * This software is provided "AS IS" with no warranty of any kind,
14 * express or implied, and with no claim as to its suitability for any
21 /// \brief Item reader bits for lemon input.
23 #ifndef LEMON_BITS_ITEM_READER_H
24 #define LEMON_BITS_ITEM_READER_H
36 template <typename Value>
41 /// \brief Reader class for quoted strings.
43 /// Reader class for quoted strings. It can process the escape
44 /// sequences in the string.
46 /// \author Balazs Dezso
47 class QuotedStringReader {
49 /// \brief The value type of reader.
51 /// The value type of reader.
52 typedef std::string Value;
54 /// \brief Constructor for the reader.
56 /// Constructor for the reader. If the given parameter is true
57 /// the reader processes the escape sequences.
58 QuotedStringReader(bool _escaped = true)
59 : escaped(_escaped) {}
61 /// \brief Reads a quoted string from the given stream.
63 /// Reads a quoted string from the given stream.
64 void read(std::istream& is, std::string& value) const {
68 if (!is.get(c) || c != '\"')
69 throw DataFormatError("Quoted string format error");
70 while (is.get(c) && c != '\"') {
71 if (escaped && c == '\\') {
72 value += readEscape(is);
77 if (!is) throw DataFormatError("Quoted string format error");
82 static char readEscape(std::istream& is) {
84 switch (is.get(c), c) {
110 if (!is.get(c) || !isHex(c))
111 throw DataFormatError("Escape format error");
112 else if (code = valueHex(c), !is.get(c) || !isHex(c)) is.putback(c);
113 else code = code * 16 + valueHex(c);
120 throw DataFormatError("Escape format error");
121 else if (code = valueOct(c), !is.get(c) || !isOct(c))
123 else if (code = code * 8 + valueOct(c), !is.get(c) || !isOct(c))
125 else code = code * 8 + valueOct(c);
131 static bool isOct(char c) {
132 return '0' <= c && c <='7';
135 static int valueOct(char c) {
139 static bool isHex(char c) {
140 return ('0' <= c && c <= '9') ||
141 ('a' <= c && c <= 'z') ||
142 ('A' <= c && c <= 'Z');
145 static int valueHex(char c) {
146 if ('0' <= c && c <= '9') return c - '0';
147 if ('a' <= c && c <= 'z') return c - 'a' + 10;
155 /// \brief Reader for standard containers.
157 /// Reader for back insertable standard containers. The representation
158 /// of the container is the values enumerated between an open and a
161 /// \author Balazs Dezso
164 typename _ItemReader = DefaultReader<typename _Container::value_type>
166 class PushBackReader {
168 typedef _Container Value;
169 typedef _ItemReader ItemReader;
173 ItemReader item_reader;
177 /// \brief Constructor for InsertReader
179 /// Constructor for InsertReader
180 PushBackReader(const ItemReader& _item_reader = ItemReader())
181 : item_reader(_item_reader) {}
183 /// \brief Reads the values into the container from the given stream.
185 /// Reads the values into the container from the given stream.
186 void read(std::istream& is, Value& value) const {
188 if (!(is >> c) || c != '(')
189 throw DataFormatError("PushBackReader format error");
190 while (is >> c && c != ')') {
192 typename ItemReader::Value item;
193 item_reader.read(is, item);
194 value.push_back(item);
196 if (!is) throw DataFormatError("PushBackReader format error");
203 /// \brief Reader for standard containers.
205 /// Reader for insertable standard containers. The representation
206 /// of the container is the values enumerated between an open and a
209 /// \author Balazs Dezso
212 typename _ItemReader = DefaultReader<typename _Container::value_type>
216 typedef _Container Value;
217 typedef _ItemReader ItemReader;
221 ItemReader item_reader;
225 /// \brief Constructor for InsertReader
227 /// Constructor for InsertReader
228 InsertReader(const ItemReader& _item_reader = ItemReader())
229 : item_reader(_item_reader) {}
231 /// \brief Reads the values into the container from the given stream.
233 /// Reads the values into the container from the given stream.
234 void read(std::istream& is, Value& value) const {
236 if (!(is >> c) || c != '(')
237 throw DataFormatError("InsertReader format error");
238 while (is >> c && c != ')') {
240 typename ItemReader::Value item;
241 item_reader.read(is, item);
244 if (!is) throw DataFormatError("PushBackReader format error");
250 /// \brief Reader for parsed string.
252 /// Reader for parsed strings. You can define the open and close
253 /// parse characters. It reads from the input a character sequence
254 /// which is right parsed.
256 /// \author Balazs Dezso
257 class ParsedStringReader {
259 typedef std::string Value;
261 /// \brief Constructor.
263 /// Constructor for ParsedStringReader. You can give as parameter
264 /// the open and close parse characters.
265 ParsedStringReader(char _open = '(', char _close = ')')
266 : open(_open), close(_close) {}
269 /// \brief Reads the parsed string from the given stream.
271 /// Reads the parsed string from the given stream.
272 void read(std::istream& is, Value& value) const {
274 if (!(is >> c) || c != open) {
275 throw DataFormatError("ParsedStringReader format error");
279 while (counter > 0 && is >> c) {
282 } else if (c == open) {
288 throw DataFormatError("ParsedStrinReader format error");
298 /// \brief Reader for read the whole line.
300 /// Reader for read the whole line.
302 /// \author Balazs Dezso
305 typedef std::string Value;
307 /// \brief Constructor.
309 /// Constructor for the LineReader. If the given parameter is
310 /// true then the spaces before the first not space character are
312 LineReader(bool _skipSpaces = true) : skipSpaces(_skipSpaces) {}
314 /// \brief Reads the line from the given stream.
316 /// Reads the line from the given stream.
317 void read(std::istream& is, Value& value) const {
318 if (skipSpaces) is >> std::ws;
319 if (!getline(is, value)) {
320 throw DataFormatError("LineReader format error");
328 /// \brief Reader for std::pair.
330 /// Reader for std::pair.
332 /// \author Balazs Dezso
333 template <typename _Pair,
334 typename _FirstReader =
335 DefaultReader<typename _Pair::first_type>,
336 typename _SecondReader =
337 DefaultReader<typename _Pair::second_type> >
342 typedef _FirstReader FirstReader;
343 typedef _SecondReader SecondReader;
347 FirstReader first_reader;
348 SecondReader second_reader;
352 /// \brief Constructor.
354 /// Constructor for the PairReader.
355 PairReader(const FirstReader& _first_reader = FirstReader(),
356 const SecondReader& _second_reader = SecondReader())
357 : first_reader(_first_reader), second_reader(_second_reader) {}
359 /// \brief Reads the pair from the given stream.
361 /// Reads the pair from the given stream.
362 void read(std::istream& is, Value& value) const {
364 if (!(is >> c) || c != '(') {
365 throw DataFormatError("PairReader format error");
367 first_reader.read(is, value.first);
368 if (!(is >> c) || c != '=') {
369 throw DataFormatError("PairReader format error");
371 if (!(is >> c) || c != '>') {
372 throw DataFormatError("PairReader format error");
374 second_reader.read(is, value.second);
375 if (!(is >> c) || c != ')') {
376 throw DataFormatError("PairReader format error");
383 /// \brief The default item reader template class.
385 /// The default item reader template class. If some section reader
386 /// needs to read a value from a stream it will give the default way for it.
388 /// \author Balazs Dezso
389 template <typename _Value>
390 class DefaultReader {
393 typedef _Value Value;
394 /// \brief Reads a value from the given stream.
396 /// Reads a value from the given stream.
397 void read(std::istream& is, Value& value) const {
399 throw DataFormatError("DefaultReader format error");
404 class DefaultReader<std::string> {
406 typedef std::string Value;
408 void read(std::istream& is, Value& value) const {
410 if (!(is >> std::ws >> c)) return;
414 QuotedStringReader().read(is, value);
417 ParsedStringReader().read(is, value);
420 ParsedStringReader('[', ']').read(is, value);
423 ParsedStringReader('/', '/').read(is, value);
427 throw DataFormatError("DefaultReader format error");
434 template <typename Item>
435 class DefaultReader<std::vector<Item> >
436 : public PushBackReader<std::vector<Item> > {};
438 template <typename Item>
439 class DefaultReader<std::deque<Item> >
440 : public PushBackReader<std::deque<Item> > {};
442 template <typename Item>
443 class DefaultReader<std::list<Item> >
444 : public PushBackReader<std::list<Item> > {};
446 template <typename Item>
447 class DefaultReader<std::set<Item> >
448 : public InsertReader<std::set<Item> > {};
450 template <typename Key, typename Value>
451 class DefaultReader<std::map<Key, Value> >
452 : public InsertReader<std::map<Key, Value>,
453 DefaultReader<std::pair<Key, Value> > > {};
455 template <typename Item>
456 class DefaultReader<std::multiset<Item> >
457 : public InsertReader<std::multiset<Item> > {};
459 template <typename Key, typename Value>
460 class DefaultReader<std::multimap<Key, Value> >
461 : public InsertReader<std::multimap<Key, Value>,
462 DefaultReader<std::pair<Key, Value> > > {};
464 template <typename First, typename Second>
465 class DefaultReader<std::pair<First, Second> >
466 : public PairReader<std::pair<First, Second> > {};
470 /// \brief The default item reader for skipping a value in the stream.
472 /// The default item reader for skipping a value in the stream.
474 /// \author Balazs Dezso
475 class DefaultSkipper : public DefaultReader<std::string> {};
478 /// \brief Standard ReaderTraits for the GraphReader class.
480 /// Standard ReaderTraits for the GraphReader class.
481 /// It defines standard reading method for all type of value.
482 /// \author Balazs Dezso
483 struct DefaultReaderTraits {
485 template <typename _Value>
486 struct Reader : DefaultReader<_Value> {};
488 typedef DefaultSkipper Skipper;