2 * lemon/bits/item_reader.h - Part of LEMON, a generic C++ optimization library
4 * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
5 * (Egervary Research Group 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 /// @defgroup 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 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");
204 /// \brief Reader for standard containers.
206 /// Reader for insertable standard containers. The representation
207 /// of the container is the values enumerated between an open and a
210 /// \author Balazs Dezso
213 typename _ItemReader = DefaultReader<typename _Container::value_type>
217 typedef _Container Value;
218 typedef _ItemReader ItemReader;
222 ItemReader item_reader;
226 /// \brief Reads the values into the container from the given stream.
228 /// Reads the values into the container from the given stream.
229 void read(std::istream& is, Value& value) const {
231 if (!(is >> c) || c != '(')
232 throw DataFormatError("InsertReader format error");
233 while (is >> c && c != ')') {
235 typename ItemReader::Value item;
236 item_reader.read(is, item);
239 if (!is) throw DataFormatError("PushBackReader format error");
246 /// \brief Reader for parsed string.
248 /// Reader for parsed strings. You can give the open and close
249 /// parse characters.
251 /// \author Balazs Dezso
252 class ParsedStringReader {
254 typedef std::string Value;
256 /// \brief Constructor.
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) {}
264 /// \brief Reads the parsed string from the given stream.
266 /// Reads the parsed string from the given stream.
267 void read(std::istream& is, Value& value) const {
269 if (!(is >> c) || c != open) {
270 throw DataFormatError("ParsedStringReader format error");
274 while (counter > 0 && is >> c) {
277 } else if (c == open) {
283 throw DataFormatError("ParsedStrinReader format error");
293 /// \brief Reader for read the whole line.
295 /// Reader for read the whole line.
297 /// \author Balazs Dezso
300 typedef std::string Value;
302 /// \brief Constructor.
304 /// Constructor for the LineReader. If the given parameter is
305 /// true then the spaces before the first not space character are
307 LineReader(bool _skipSpaces = true) : skipSpaces(_skipSpaces) {}
309 /// \brief Reads the line from the given stream.
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");
324 /// \brief The default item reader template class.
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.
329 /// \author Balazs Dezso
330 template <typename _Value>
331 class DefaultReader {
334 typedef _Value Value;
335 /// \brief Reads a value from the given stream.
337 /// Reads a value from the given stream.
338 void read(std::istream& is, Value& value) const {
340 throw DataFormatError("DefaultReader format error");
345 class DefaultReader<std::string> {
347 typedef std::string Value;
349 void read(std::istream& is, Value& value) const {
351 if (!(is >> std::ws >> c)) return;
355 QuotedStringReader().read(is, value);
358 ParsedStringReader().read(is, value);
368 template <typename Item>
369 class DefaultReader<std::vector<Item> >
370 : public PushBackReader<std::vector<Item> > {};
372 template <typename Item>
373 class DefaultReader<std::deque<Item> >
374 : public PushBackReader<std::deque<Item> > {};
376 template <typename Item>
377 class DefaultReader<std::list<Item> >
378 : public PushBackReader<std::list<Item> > {};
380 template <typename Item>
381 class DefaultReader<std::set<Item> >
382 : public InsertReader<std::set<Item> > {};
384 template <typename Item>
385 class DefaultReader<std::multiset<Item> >
386 : public InsertReader<std::multiset<Item> > {};
390 /// \brief The default item reader for skipping a value in the stream.
392 /// The default item reader for skipping a value in the stream.
394 /// \author Balazs Dezso
395 class DefaultSkipper : public DefaultReader<std::string> {};
398 /// \brief Standard ReaderTraits for the GraphReader class.
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 {
405 template <typename _Value>
406 struct Reader : DefaultReader<_Value> {};
408 typedef DefaultSkipper Skipper;