0
2
0
| ... | ... |
@@ -102,282 +102,282 @@ |
| 102 | 102 |
|
| 103 | 103 |
template <typename _Graph, bool _dir, typename _Map, |
| 104 | 104 |
typename _Converter = DefaultConverter<typename _Map::Value> > |
| 105 | 105 |
class GraphArcMapStorage : public MapStorageBase<typename _Graph::Edge> {
|
| 106 | 106 |
public: |
| 107 | 107 |
typedef _Map Map; |
| 108 | 108 |
typedef _Converter Converter; |
| 109 | 109 |
typedef _Graph Graph; |
| 110 | 110 |
typedef typename Graph::Edge Item; |
| 111 | 111 |
static const bool dir = _dir; |
| 112 | 112 |
|
| 113 | 113 |
private: |
| 114 | 114 |
const Graph& _graph; |
| 115 | 115 |
Map& _map; |
| 116 | 116 |
Converter _converter; |
| 117 | 117 |
|
| 118 | 118 |
public: |
| 119 | 119 |
GraphArcMapStorage(const Graph& graph, Map& map, |
| 120 | 120 |
const Converter& converter = Converter()) |
| 121 | 121 |
: _graph(graph), _map(map), _converter(converter) {}
|
| 122 | 122 |
virtual ~GraphArcMapStorage() {}
|
| 123 | 123 |
|
| 124 | 124 |
virtual void set(const Item& item ,const std::string& value) {
|
| 125 | 125 |
_map.set(_graph.direct(item, dir), _converter(value)); |
| 126 | 126 |
} |
| 127 | 127 |
}; |
| 128 | 128 |
|
| 129 | 129 |
class ValueStorageBase {
|
| 130 | 130 |
public: |
| 131 | 131 |
ValueStorageBase() {}
|
| 132 | 132 |
virtual ~ValueStorageBase() {}
|
| 133 | 133 |
|
| 134 | 134 |
virtual void set(const std::string&) = 0; |
| 135 | 135 |
}; |
| 136 | 136 |
|
| 137 | 137 |
template <typename _Value, typename _Converter = DefaultConverter<_Value> > |
| 138 | 138 |
class ValueStorage : public ValueStorageBase {
|
| 139 | 139 |
public: |
| 140 | 140 |
typedef _Value Value; |
| 141 | 141 |
typedef _Converter Converter; |
| 142 | 142 |
|
| 143 | 143 |
private: |
| 144 | 144 |
Value& _value; |
| 145 | 145 |
Converter _converter; |
| 146 | 146 |
|
| 147 | 147 |
public: |
| 148 | 148 |
ValueStorage(Value& value, const Converter& converter = Converter()) |
| 149 | 149 |
: _value(value), _converter(converter) {}
|
| 150 | 150 |
|
| 151 | 151 |
virtual void set(const std::string& value) {
|
| 152 | 152 |
_value = _converter(value); |
| 153 | 153 |
} |
| 154 | 154 |
}; |
| 155 | 155 |
|
| 156 | 156 |
template <typename Value> |
| 157 | 157 |
struct MapLookUpConverter {
|
| 158 | 158 |
const std::map<std::string, Value>& _map; |
| 159 | 159 |
|
| 160 | 160 |
MapLookUpConverter(const std::map<std::string, Value>& map) |
| 161 | 161 |
: _map(map) {}
|
| 162 | 162 |
|
| 163 | 163 |
Value operator()(const std::string& str) {
|
| 164 | 164 |
typename std::map<std::string, Value>::const_iterator it = |
| 165 | 165 |
_map.find(str); |
| 166 | 166 |
if (it == _map.end()) {
|
| 167 | 167 |
std::ostringstream msg; |
| 168 | 168 |
msg << "Item not found: " << str; |
| 169 | 169 |
throw DataFormatError(msg.str().c_str()); |
| 170 | 170 |
} |
| 171 | 171 |
return it->second; |
| 172 | 172 |
} |
| 173 | 173 |
}; |
| 174 | 174 |
|
| 175 | 175 |
template <typename Graph> |
| 176 | 176 |
struct GraphArcLookUpConverter {
|
| 177 | 177 |
const Graph& _graph; |
| 178 | 178 |
const std::map<std::string, typename Graph::Edge>& _map; |
| 179 | 179 |
|
| 180 | 180 |
GraphArcLookUpConverter(const Graph& graph, |
| 181 | 181 |
const std::map<std::string, |
| 182 | 182 |
typename Graph::Edge>& map) |
| 183 | 183 |
: _graph(graph), _map(map) {}
|
| 184 | 184 |
|
| 185 | 185 |
typename Graph::Arc operator()(const std::string& str) {
|
| 186 | 186 |
if (str.empty() || (str[0] != '+' && str[0] != '-')) {
|
| 187 | 187 |
throw DataFormatError("Item must start with '+' or '-'");
|
| 188 | 188 |
} |
| 189 | 189 |
typename std::map<std::string, typename Graph::Edge> |
| 190 | 190 |
::const_iterator it = _map.find(str.substr(1)); |
| 191 | 191 |
if (it == _map.end()) {
|
| 192 | 192 |
throw DataFormatError("Item not found");
|
| 193 | 193 |
} |
| 194 | 194 |
return _graph.direct(it->second, str[0] == '+'); |
| 195 | 195 |
} |
| 196 | 196 |
}; |
| 197 | 197 |
|
| 198 |
bool isWhiteSpace(char c) {
|
|
| 198 |
inline bool isWhiteSpace(char c) {
|
|
| 199 | 199 |
return c == ' ' || c == '\t' || c == '\v' || |
| 200 | 200 |
c == '\n' || c == '\r' || c == '\f'; |
| 201 | 201 |
} |
| 202 | 202 |
|
| 203 |
bool isOct(char c) {
|
|
| 203 |
inline bool isOct(char c) {
|
|
| 204 | 204 |
return '0' <= c && c <='7'; |
| 205 | 205 |
} |
| 206 | 206 |
|
| 207 |
int valueOct(char c) {
|
|
| 207 |
inline int valueOct(char c) {
|
|
| 208 | 208 |
LEMON_ASSERT(isOct(c), "The character is not octal."); |
| 209 | 209 |
return c - '0'; |
| 210 | 210 |
} |
| 211 | 211 |
|
| 212 |
bool isHex(char c) {
|
|
| 212 |
inline bool isHex(char c) {
|
|
| 213 | 213 |
return ('0' <= c && c <= '9') ||
|
| 214 | 214 |
('a' <= c && c <= 'z') ||
|
| 215 | 215 |
('A' <= c && c <= 'Z');
|
| 216 | 216 |
} |
| 217 | 217 |
|
| 218 |
int valueHex(char c) {
|
|
| 218 |
inline int valueHex(char c) {
|
|
| 219 | 219 |
LEMON_ASSERT(isHex(c), "The character is not hexadecimal."); |
| 220 | 220 |
if ('0' <= c && c <= '9') return c - '0';
|
| 221 | 221 |
if ('a' <= c && c <= 'z') return c - 'a' + 10;
|
| 222 | 222 |
return c - 'A' + 10; |
| 223 | 223 |
} |
| 224 | 224 |
|
| 225 |
bool isIdentifierFirstChar(char c) {
|
|
| 225 |
inline bool isIdentifierFirstChar(char c) {
|
|
| 226 | 226 |
return ('a' <= c && c <= 'z') ||
|
| 227 | 227 |
('A' <= c && c <= 'Z') || c == '_';
|
| 228 | 228 |
} |
| 229 | 229 |
|
| 230 |
bool isIdentifierChar(char c) {
|
|
| 230 |
inline bool isIdentifierChar(char c) {
|
|
| 231 | 231 |
return isIdentifierFirstChar(c) || |
| 232 | 232 |
('0' <= c && c <= '9');
|
| 233 | 233 |
} |
| 234 | 234 |
|
| 235 |
char readEscape(std::istream& is) {
|
|
| 235 |
inline char readEscape(std::istream& is) {
|
|
| 236 | 236 |
char c; |
| 237 | 237 |
if (!is.get(c)) |
| 238 | 238 |
throw DataFormatError("Escape format error");
|
| 239 | 239 |
|
| 240 | 240 |
switch (c) {
|
| 241 | 241 |
case '\\': |
| 242 | 242 |
return '\\'; |
| 243 | 243 |
case '\"': |
| 244 | 244 |
return '\"'; |
| 245 | 245 |
case '\'': |
| 246 | 246 |
return '\''; |
| 247 | 247 |
case '\?': |
| 248 | 248 |
return '\?'; |
| 249 | 249 |
case 'a': |
| 250 | 250 |
return '\a'; |
| 251 | 251 |
case 'b': |
| 252 | 252 |
return '\b'; |
| 253 | 253 |
case 'f': |
| 254 | 254 |
return '\f'; |
| 255 | 255 |
case 'n': |
| 256 | 256 |
return '\n'; |
| 257 | 257 |
case 'r': |
| 258 | 258 |
return '\r'; |
| 259 | 259 |
case 't': |
| 260 | 260 |
return '\t'; |
| 261 | 261 |
case 'v': |
| 262 | 262 |
return '\v'; |
| 263 | 263 |
case 'x': |
| 264 | 264 |
{
|
| 265 | 265 |
int code; |
| 266 | 266 |
if (!is.get(c) || !isHex(c)) |
| 267 | 267 |
throw DataFormatError("Escape format error");
|
| 268 | 268 |
else if (code = valueHex(c), !is.get(c) || !isHex(c)) is.putback(c); |
| 269 | 269 |
else code = code * 16 + valueHex(c); |
| 270 | 270 |
return code; |
| 271 | 271 |
} |
| 272 | 272 |
default: |
| 273 | 273 |
{
|
| 274 | 274 |
int code; |
| 275 | 275 |
if (!isOct(c)) |
| 276 | 276 |
throw DataFormatError("Escape format error");
|
| 277 | 277 |
else if (code = valueOct(c), !is.get(c) || !isOct(c)) |
| 278 | 278 |
is.putback(c); |
| 279 | 279 |
else if (code = code * 8 + valueOct(c), !is.get(c) || !isOct(c)) |
| 280 | 280 |
is.putback(c); |
| 281 | 281 |
else code = code * 8 + valueOct(c); |
| 282 | 282 |
return code; |
| 283 | 283 |
} |
| 284 | 284 |
} |
| 285 | 285 |
} |
| 286 | 286 |
|
| 287 |
std::istream& readToken(std::istream& is, std::string& str) {
|
|
| 287 |
inline std::istream& readToken(std::istream& is, std::string& str) {
|
|
| 288 | 288 |
std::ostringstream os; |
| 289 | 289 |
|
| 290 | 290 |
char c; |
| 291 | 291 |
is >> std::ws; |
| 292 | 292 |
|
| 293 | 293 |
if (!is.get(c)) |
| 294 | 294 |
return is; |
| 295 | 295 |
|
| 296 | 296 |
if (c == '\"') {
|
| 297 | 297 |
while (is.get(c) && c != '\"') {
|
| 298 | 298 |
if (c == '\\') |
| 299 | 299 |
c = readEscape(is); |
| 300 | 300 |
os << c; |
| 301 | 301 |
} |
| 302 | 302 |
if (!is) |
| 303 | 303 |
throw DataFormatError("Quoted format error");
|
| 304 | 304 |
} else {
|
| 305 | 305 |
is.putback(c); |
| 306 | 306 |
while (is.get(c) && !isWhiteSpace(c)) {
|
| 307 | 307 |
if (c == '\\') |
| 308 | 308 |
c = readEscape(is); |
| 309 | 309 |
os << c; |
| 310 | 310 |
} |
| 311 | 311 |
if (!is) {
|
| 312 | 312 |
is.clear(); |
| 313 | 313 |
} else {
|
| 314 | 314 |
is.putback(c); |
| 315 | 315 |
} |
| 316 | 316 |
} |
| 317 | 317 |
str = os.str(); |
| 318 | 318 |
return is; |
| 319 | 319 |
} |
| 320 | 320 |
|
| 321 | 321 |
class Section {
|
| 322 | 322 |
public: |
| 323 | 323 |
virtual ~Section() {}
|
| 324 | 324 |
virtual void process(std::istream& is, int& line_num) = 0; |
| 325 | 325 |
}; |
| 326 | 326 |
|
| 327 | 327 |
template <typename Functor> |
| 328 | 328 |
class LineSection : public Section {
|
| 329 | 329 |
private: |
| 330 | 330 |
|
| 331 | 331 |
Functor _functor; |
| 332 | 332 |
|
| 333 | 333 |
public: |
| 334 | 334 |
|
| 335 | 335 |
LineSection(const Functor& functor) : _functor(functor) {}
|
| 336 | 336 |
virtual ~LineSection() {}
|
| 337 | 337 |
|
| 338 | 338 |
virtual void process(std::istream& is, int& line_num) {
|
| 339 | 339 |
char c; |
| 340 | 340 |
std::string line; |
| 341 | 341 |
while (is.get(c) && c != '@') {
|
| 342 | 342 |
if (c == '\n') {
|
| 343 | 343 |
++line_num; |
| 344 | 344 |
} else if (c == '#') {
|
| 345 | 345 |
getline(is, line); |
| 346 | 346 |
++line_num; |
| 347 | 347 |
} else if (!isWhiteSpace(c)) {
|
| 348 | 348 |
is.putback(c); |
| 349 | 349 |
getline(is, line); |
| 350 | 350 |
_functor(line); |
| 351 | 351 |
++line_num; |
| 352 | 352 |
} |
| 353 | 353 |
} |
| 354 | 354 |
if (is) is.putback(c); |
| 355 | 355 |
else if (is.eof()) is.clear(); |
| 356 | 356 |
} |
| 357 | 357 |
}; |
| 358 | 358 |
|
| 359 | 359 |
template <typename Functor> |
| 360 | 360 |
class StreamSection : public Section {
|
| 361 | 361 |
private: |
| 362 | 362 |
|
| 363 | 363 |
Functor _functor; |
| 364 | 364 |
|
| 365 | 365 |
public: |
| 366 | 366 |
|
| 367 | 367 |
StreamSection(const Functor& functor) : _functor(functor) {}
|
| 368 | 368 |
virtual ~StreamSection() {}
|
| 369 | 369 |
|
| 370 | 370 |
virtual void process(std::istream& is, int& line_num) {
|
| 371 | 371 |
_functor(is, line_num); |
| 372 | 372 |
char c; |
| 373 | 373 |
std::string line; |
| 374 | 374 |
while (is.get(c) && c != '@') {
|
| 375 | 375 |
if (c == '\n') {
|
| 376 | 376 |
++line_num; |
| 377 | 377 |
} else if (!isWhiteSpace(c)) {
|
| 378 | 378 |
getline(is, line); |
| 379 | 379 |
++line_num; |
| 380 | 380 |
} |
| 381 | 381 |
} |
| 382 | 382 |
if (is) is.putback(c); |
| 383 | 383 |
else if (is.eof()) is.clear(); |
| ... | ... |
@@ -132,256 +132,256 @@ |
| 132 | 132 |
}; |
| 133 | 133 |
|
| 134 | 134 |
template <typename _Graph, bool _dir, typename _Map, |
| 135 | 135 |
typename _Converter = DefaultConverter<typename _Map::Value> > |
| 136 | 136 |
class GraphArcMapStorage : public MapStorageBase<typename _Graph::Edge> {
|
| 137 | 137 |
public: |
| 138 | 138 |
typedef _Map Map; |
| 139 | 139 |
typedef _Converter Converter; |
| 140 | 140 |
typedef _Graph Graph; |
| 141 | 141 |
typedef typename Graph::Edge Item; |
| 142 | 142 |
static const bool dir = _dir; |
| 143 | 143 |
|
| 144 | 144 |
private: |
| 145 | 145 |
const Graph& _graph; |
| 146 | 146 |
const Map& _map; |
| 147 | 147 |
Converter _converter; |
| 148 | 148 |
|
| 149 | 149 |
public: |
| 150 | 150 |
GraphArcMapStorage(const Graph& graph, const Map& map, |
| 151 | 151 |
const Converter& converter = Converter()) |
| 152 | 152 |
: _graph(graph), _map(map), _converter(converter) {}
|
| 153 | 153 |
virtual ~GraphArcMapStorage() {}
|
| 154 | 154 |
|
| 155 | 155 |
virtual std::string get(const Item& item) {
|
| 156 | 156 |
return _converter(_map[_graph.direct(item, dir)]); |
| 157 | 157 |
} |
| 158 | 158 |
virtual void sort(std::vector<Item>& items) {
|
| 159 | 159 |
GraphArcMapLess<Graph, dir, Map> less(_graph, _map); |
| 160 | 160 |
std::sort(items.begin(), items.end(), less); |
| 161 | 161 |
} |
| 162 | 162 |
}; |
| 163 | 163 |
|
| 164 | 164 |
class ValueStorageBase {
|
| 165 | 165 |
public: |
| 166 | 166 |
ValueStorageBase() {}
|
| 167 | 167 |
virtual ~ValueStorageBase() {}
|
| 168 | 168 |
|
| 169 | 169 |
virtual std::string get() = 0; |
| 170 | 170 |
}; |
| 171 | 171 |
|
| 172 | 172 |
template <typename _Value, typename _Converter = DefaultConverter<_Value> > |
| 173 | 173 |
class ValueStorage : public ValueStorageBase {
|
| 174 | 174 |
public: |
| 175 | 175 |
typedef _Value Value; |
| 176 | 176 |
typedef _Converter Converter; |
| 177 | 177 |
|
| 178 | 178 |
private: |
| 179 | 179 |
const Value& _value; |
| 180 | 180 |
Converter _converter; |
| 181 | 181 |
|
| 182 | 182 |
public: |
| 183 | 183 |
ValueStorage(const Value& value, const Converter& converter = Converter()) |
| 184 | 184 |
: _value(value), _converter(converter) {}
|
| 185 | 185 |
|
| 186 | 186 |
virtual std::string get() {
|
| 187 | 187 |
return _converter(_value); |
| 188 | 188 |
} |
| 189 | 189 |
}; |
| 190 | 190 |
|
| 191 | 191 |
template <typename Value> |
| 192 | 192 |
struct MapLookUpConverter {
|
| 193 | 193 |
const std::map<Value, std::string>& _map; |
| 194 | 194 |
|
| 195 | 195 |
MapLookUpConverter(const std::map<Value, std::string>& map) |
| 196 | 196 |
: _map(map) {}
|
| 197 | 197 |
|
| 198 | 198 |
std::string operator()(const Value& str) {
|
| 199 | 199 |
typename std::map<Value, std::string>::const_iterator it = |
| 200 | 200 |
_map.find(str); |
| 201 | 201 |
if (it == _map.end()) {
|
| 202 | 202 |
throw DataFormatError("Item not found");
|
| 203 | 203 |
} |
| 204 | 204 |
return it->second; |
| 205 | 205 |
} |
| 206 | 206 |
}; |
| 207 | 207 |
|
| 208 | 208 |
template <typename Graph> |
| 209 | 209 |
struct GraphArcLookUpConverter {
|
| 210 | 210 |
const Graph& _graph; |
| 211 | 211 |
const std::map<typename Graph::Edge, std::string>& _map; |
| 212 | 212 |
|
| 213 | 213 |
GraphArcLookUpConverter(const Graph& graph, |
| 214 | 214 |
const std::map<typename Graph::Edge, |
| 215 | 215 |
std::string>& map) |
| 216 | 216 |
: _graph(graph), _map(map) {}
|
| 217 | 217 |
|
| 218 | 218 |
std::string operator()(const typename Graph::Arc& val) {
|
| 219 | 219 |
typename std::map<typename Graph::Edge, std::string> |
| 220 | 220 |
::const_iterator it = _map.find(val); |
| 221 | 221 |
if (it == _map.end()) {
|
| 222 | 222 |
throw DataFormatError("Item not found");
|
| 223 | 223 |
} |
| 224 | 224 |
return (_graph.direction(val) ? '+' : '-') + it->second; |
| 225 | 225 |
} |
| 226 | 226 |
}; |
| 227 | 227 |
|
| 228 |
bool isWhiteSpace(char c) {
|
|
| 228 |
inline bool isWhiteSpace(char c) {
|
|
| 229 | 229 |
return c == ' ' || c == '\t' || c == '\v' || |
| 230 | 230 |
c == '\n' || c == '\r' || c == '\f'; |
| 231 | 231 |
} |
| 232 | 232 |
|
| 233 |
bool isEscaped(char c) {
|
|
| 233 |
inline bool isEscaped(char c) {
|
|
| 234 | 234 |
return c == '\\' || c == '\"' || c == '\'' || |
| 235 | 235 |
c == '\a' || c == '\b'; |
| 236 | 236 |
} |
| 237 | 237 |
|
| 238 |
static void writeEscape(std::ostream& os, char c) {
|
|
| 238 |
inline static void writeEscape(std::ostream& os, char c) {
|
|
| 239 | 239 |
switch (c) {
|
| 240 | 240 |
case '\\': |
| 241 | 241 |
os << "\\\\"; |
| 242 | 242 |
return; |
| 243 | 243 |
case '\"': |
| 244 | 244 |
os << "\\\""; |
| 245 | 245 |
return; |
| 246 | 246 |
case '\a': |
| 247 | 247 |
os << "\\a"; |
| 248 | 248 |
return; |
| 249 | 249 |
case '\b': |
| 250 | 250 |
os << "\\b"; |
| 251 | 251 |
return; |
| 252 | 252 |
case '\f': |
| 253 | 253 |
os << "\\f"; |
| 254 | 254 |
return; |
| 255 | 255 |
case '\r': |
| 256 | 256 |
os << "\\r"; |
| 257 | 257 |
return; |
| 258 | 258 |
case '\n': |
| 259 | 259 |
os << "\\n"; |
| 260 | 260 |
return; |
| 261 | 261 |
case '\t': |
| 262 | 262 |
os << "\\t"; |
| 263 | 263 |
return; |
| 264 | 264 |
case '\v': |
| 265 | 265 |
os << "\\v"; |
| 266 | 266 |
return; |
| 267 | 267 |
default: |
| 268 | 268 |
if (c < 0x20) {
|
| 269 | 269 |
std::ios::fmtflags flags = os.flags(); |
| 270 | 270 |
os << '\\' << std::oct << static_cast<int>(c); |
| 271 | 271 |
os.flags(flags); |
| 272 | 272 |
} else {
|
| 273 | 273 |
os << c; |
| 274 | 274 |
} |
| 275 | 275 |
return; |
| 276 | 276 |
} |
| 277 | 277 |
} |
| 278 | 278 |
|
| 279 |
bool requireEscape(const std::string& str) {
|
|
| 279 |
inline bool requireEscape(const std::string& str) {
|
|
| 280 | 280 |
if (str.empty() || str[0] == '@') return true; |
| 281 | 281 |
std::istringstream is(str); |
| 282 | 282 |
char c; |
| 283 | 283 |
while (is.get(c)) {
|
| 284 | 284 |
if (isWhiteSpace(c) || isEscaped(c)) {
|
| 285 | 285 |
return true; |
| 286 | 286 |
} |
| 287 | 287 |
} |
| 288 | 288 |
return false; |
| 289 | 289 |
} |
| 290 | 290 |
|
| 291 |
std::ostream& writeToken(std::ostream& os, const std::string& str) {
|
|
| 291 |
inline std::ostream& writeToken(std::ostream& os, const std::string& str) {
|
|
| 292 | 292 |
|
| 293 | 293 |
if (requireEscape(str)) {
|
| 294 | 294 |
os << '\"'; |
| 295 | 295 |
for (std::string::const_iterator it = str.begin(); |
| 296 | 296 |
it != str.end(); ++it) {
|
| 297 | 297 |
writeEscape(os, *it); |
| 298 | 298 |
} |
| 299 | 299 |
os << '\"'; |
| 300 | 300 |
} else {
|
| 301 | 301 |
os << str; |
| 302 | 302 |
} |
| 303 | 303 |
return os; |
| 304 | 304 |
} |
| 305 | 305 |
|
| 306 | 306 |
} |
| 307 | 307 |
|
| 308 | 308 |
template <typename Digraph> |
| 309 | 309 |
class DigraphWriter; |
| 310 | 310 |
|
| 311 | 311 |
template <typename Digraph> |
| 312 | 312 |
DigraphWriter<Digraph> digraphWriter(std::ostream& os, |
| 313 | 313 |
const Digraph& digraph); |
| 314 | 314 |
|
| 315 | 315 |
template <typename Digraph> |
| 316 | 316 |
DigraphWriter<Digraph> digraphWriter(const std::string& fn, |
| 317 | 317 |
const Digraph& digraph); |
| 318 | 318 |
|
| 319 | 319 |
template <typename Digraph> |
| 320 | 320 |
DigraphWriter<Digraph> digraphWriter(const char *fn, |
| 321 | 321 |
const Digraph& digraph); |
| 322 | 322 |
|
| 323 | 323 |
/// \ingroup lemon_io |
| 324 | 324 |
/// |
| 325 | 325 |
/// \brief \ref lgf-format "LGF" writer for directed graphs |
| 326 | 326 |
/// |
| 327 | 327 |
/// This utility writes an \ref lgf-format "LGF" file. |
| 328 | 328 |
/// |
| 329 | 329 |
/// The writing method does a batch processing. The user creates a |
| 330 | 330 |
/// writer object, then various writing rules can be added to the |
| 331 | 331 |
/// writer, and eventually the writing is executed with the \c run() |
| 332 | 332 |
/// member function. A map writing rule can be added to the writer |
| 333 | 333 |
/// with the \c nodeMap() or \c arcMap() members. An optional |
| 334 | 334 |
/// converter parameter can also be added as a standard functor |
| 335 | 335 |
/// converting from the value type of the map to \c std::string. If it |
| 336 | 336 |
/// is set, it will determine how the value type of the map is written to |
| 337 | 337 |
/// the output stream. If the functor is not set, then a default |
| 338 | 338 |
/// conversion will be used. The \c attribute(), \c node() and \c |
| 339 | 339 |
/// arc() functions are used to add attribute writing rules. |
| 340 | 340 |
/// |
| 341 | 341 |
///\code |
| 342 | 342 |
/// DigraphWriter<Digraph>(std::cout, digraph). |
| 343 | 343 |
/// nodeMap("coordinates", coord_map).
|
| 344 | 344 |
/// nodeMap("size", size).
|
| 345 | 345 |
/// nodeMap("title", title).
|
| 346 | 346 |
/// arcMap("capacity", cap_map).
|
| 347 | 347 |
/// node("source", src).
|
| 348 | 348 |
/// node("target", trg).
|
| 349 | 349 |
/// attribute("caption", caption).
|
| 350 | 350 |
/// run(); |
| 351 | 351 |
///\endcode |
| 352 | 352 |
/// |
| 353 | 353 |
/// |
| 354 | 354 |
/// By default, the writer does not write additional captions to the |
| 355 | 355 |
/// sections, but they can be give as an optional parameter of |
| 356 | 356 |
/// the \c nodes(), \c arcs() or \c |
| 357 | 357 |
/// attributes() functions. |
| 358 | 358 |
/// |
| 359 | 359 |
/// The \c skipNodes() and \c skipArcs() functions forbid the |
| 360 | 360 |
/// writing of the sections. If two arc sections should be written |
| 361 | 361 |
/// to the output, it can be done in two passes, the first pass |
| 362 | 362 |
/// writes the node section and the first arc section, then the |
| 363 | 363 |
/// second pass skips the node section and writes just the arc |
| 364 | 364 |
/// section to the stream. The output stream can be retrieved with |
| 365 | 365 |
/// the \c ostream() function, hence the second pass can append its |
| 366 | 366 |
/// output to the output of the first pass. |
| 367 | 367 |
template <typename _Digraph> |
| 368 | 368 |
class DigraphWriter {
|
| 369 | 369 |
public: |
| 370 | 370 |
|
| 371 | 371 |
typedef _Digraph Digraph; |
| 372 | 372 |
TEMPLATE_DIGRAPH_TYPEDEFS(Digraph); |
| 373 | 373 |
|
| 374 | 374 |
private: |
| 375 | 375 |
|
| 376 | 376 |
|
| 377 | 377 |
std::ostream* _os; |
| 378 | 378 |
bool local_os; |
| 379 | 379 |
|
| 380 | 380 |
const Digraph& _digraph; |
| 381 | 381 |
|
| 382 | 382 |
std::string _nodes_caption; |
| 383 | 383 |
std::string _arcs_caption; |
| 384 | 384 |
std::string _attributes_caption; |
| 385 | 385 |
|
| 386 | 386 |
typedef std::map<Node, std::string> NodeIndex; |
| 387 | 387 |
NodeIndex _node_index; |
0 comments (0 inline)