3 #include <iostream> |
3 #include <iostream> |
4 #include <string> |
4 #include <string> |
5 #include <vector> |
5 #include <vector> |
6 #include <list> |
6 #include <list> |
7 #include <map> |
7 #include <map> |
|
8 #include <lemon/error.h> |
8 #include <lemon/xy.h> |
9 #include <lemon/xy.h> |
9 |
10 |
10 class XmlWriter |
11 namespace lemon { |
11 { |
12 |
12 std::ostream& os; |
13 class XmlWriter |
13 int level; |
14 { |
14 |
15 std::ostream& os; |
15 protected: |
16 int level; |
16 void indent(int level) { |
17 |
17 os << std::endl; |
18 protected: |
18 for(int i=0;i<level;i++) os << ' '; |
19 void indent(int level) { |
19 } |
20 os << std::endl; |
20 void tag(const std::string &_tag) { |
21 for(int i=0;i<level;i++) os << ' '; |
21 os << '<' << _tag << '>'; |
22 } |
22 } |
23 void tag(const std::string &_tag) { |
23 void etag(const std::string &_tag) { |
24 os << '<' << _tag << '>'; |
24 os << "</" << _tag << '>'; |
25 } |
25 } |
26 void etag(const std::string &_tag) { |
26 void itag(const std::string &_tag) { indent();tag(_tag); } |
27 os << "</" << _tag << '>'; |
27 void ietag(const std::string &_tag) { indent();etag(_tag); } |
28 } |
28 |
29 void itag(const std::string &_tag) { indent();tag(_tag); } |
29 void beginTag(const std::string &_tag) { |
30 void ietag(const std::string &_tag) { indent();etag(_tag); } |
30 itag(_tag); |
31 |
31 level++; |
32 void beginTag(const std::string &_tag) { |
32 } |
33 itag(_tag); |
33 void endTag(const std::string &_tag) { |
34 level++; |
34 level--; |
35 } |
35 ietag(_tag); |
36 void endTag(const std::string &_tag) { |
36 } |
37 level--; |
37 |
38 ietag(_tag); |
38 public: |
39 } |
39 |
40 |
40 void indent() |
|
41 { |
|
42 if(level>=0) indent(level); |
|
43 else level=0; |
|
44 } |
|
45 |
|
46 ///\e |
|
47 |
|
48 ///\e |
|
49 /// |
|
50 class ContTag |
|
51 { |
|
52 XmlWriter &ix; |
|
53 const std::string _tag; |
|
54 public: |
41 public: |
55 ///\e |
42 |
56 |
43 void indent() |
57 ///\e |
44 { |
58 /// |
45 if(level>=0) indent(level); |
59 ContTag(XmlWriter &_ix,const std::string &_t) : |
46 else level=0; |
60 ix(_ix), _tag(_t) |
47 } |
61 { |
48 |
62 ix.tag(_tag); |
49 ///\e |
63 } |
50 |
64 ~ContTag() { ix.etag(_tag);} |
51 ///\e |
65 }; |
52 /// |
66 |
53 class ContTag |
67 class LineTag |
54 { |
68 { |
55 XmlWriter &ix; |
69 XmlWriter &ix; |
56 const std::string _tag; |
70 const std::string _tag; |
57 public: |
71 public: |
58 ///\e |
72 ///\e |
59 |
|
60 ///\e |
|
61 /// |
|
62 ContTag(XmlWriter &_ix,const std::string &_t) : |
|
63 ix(_ix), _tag(_t) |
|
64 { |
|
65 ix.tag(_tag); |
|
66 } |
|
67 ~ContTag() { ix.etag(_tag);} |
|
68 }; |
|
69 |
|
70 class LineTag |
|
71 { |
|
72 XmlWriter &ix; |
|
73 const std::string _tag; |
|
74 public: |
|
75 ///\e |
73 |
76 |
74 ///\e |
77 ///\e |
75 /// |
78 /// |
76 LineTag(XmlWriter &_ix,const std::string &_t) : |
79 LineTag(XmlWriter &_ix,const std::string &_t) : |
77 ix(_ix), _tag(_t) |
80 ix(_ix), _tag(_t) |
78 { |
81 { |
79 ix.itag(_tag); |
82 ix.itag(_tag); |
80 } |
83 } |
81 ~LineTag() { ix.etag(_tag);} |
84 ~LineTag() { ix.etag(_tag);} |
82 }; |
85 }; |
83 |
86 |
84 ///\e |
87 ///\e |
85 |
88 |
86 ///\e |
89 ///\e |
87 /// |
90 /// |
88 class Tag |
91 class Tag |
89 { |
92 { |
90 XmlWriter &ix; |
93 XmlWriter &ix; |
91 const std::string _tag; |
94 const std::string _tag; |
92 public: |
95 public: |
93 ///\e |
96 ///\e |
94 |
97 |
95 ///\e |
98 ///\e |
96 /// |
99 /// |
97 Tag(XmlWriter &_ix,const std::string &_t) : |
100 Tag(XmlWriter &_ix,const std::string &_t) : |
98 ix(_ix), _tag(_t) |
101 ix(_ix), _tag(_t) |
99 { |
102 { |
100 ix.beginTag(_tag); |
103 ix.beginTag(_tag); |
101 } |
104 } |
102 ~Tag() { |
105 ~Tag() { |
103 ix.endTag(_tag); |
106 ix.endTag(_tag); |
104 } |
107 } |
105 }; |
108 }; |
106 |
109 |
107 ///\e |
110 ///\e |
108 |
111 |
109 ///\e |
112 ///\e |
110 /// |
113 /// |
111 XmlWriter(std::ostream& _os) : os(_os),level(-1) {} |
114 XmlWriter(std::ostream& _os) : os(_os),level(-1) {} |
112 ~XmlWriter() { os<< std::endl; } |
115 ~XmlWriter() { os<< std::endl; } |
113 |
116 |
114 XmlWriter &operator()(int v) |
117 XmlWriter &operator()(int v) |
115 { |
118 { |
116 if(!(os << v)) throw (std::ios::failure ("data format error")); |
119 os << v; |
117 return *this; |
120 return *this; |
118 } |
121 } |
119 XmlWriter &operator()(const std::string &_tag,int v) |
122 XmlWriter &operator()(const std::string &_tag,int v) |
120 { |
123 { |
121 LineTag t(*this,_tag); |
124 LineTag t(*this,_tag); |
122 if(!(os << v)) throw (std::ios::failure ("data format error")); |
125 (*this)(v); |
123 return *this; |
126 return *this; |
124 } |
127 } |
125 XmlWriter &operator()(const std::string &_tag,double v) |
128 XmlWriter &operator()(double v) |
126 { |
129 { |
127 LineTag t(*this,_tag); |
130 os << v; |
128 if(os << v) throw (std::ios::failure ("data format error")); |
131 return *this; |
129 return *this; |
132 } |
130 } |
133 XmlWriter &operator()(const std::string &_tag,double v) |
131 XmlWriter &operator()(double v) |
134 { |
132 { |
135 LineTag t(*this,_tag); |
133 os << v; |
136 (*this)(v); |
134 return *this; |
137 return *this; |
135 } |
138 } |
136 XmlWriter &operator()(const std::string &v) |
139 XmlWriter &operator()(const std::string &v) |
137 { |
140 { |
138 for(std::string::const_iterator i=v.begin();i!=v.end();++i) |
141 for(std::string::const_iterator i=v.begin();i!=v.end();++i) |
139 switch(*i) { |
142 switch(*i) { |
140 case '\\': |
143 case '\\': |
141 os << "\\\\"; |
144 os << "\\\\"; |
142 break; |
145 break; |
143 case '<': |
146 case '<': |
144 os << "\\<"; |
147 os << "\\<"; |
145 break; |
148 break; |
146 case '&': |
149 case '&': |
147 os << "\\&"; |
150 os << "\\&"; |
148 break; |
151 break; |
149 case '\n': |
152 case '\n': |
150 os << "\\n"; |
153 os << "\\n"; |
151 break; |
|
152 default: |
|
153 os<<*i; |
|
154 break; |
|
155 } |
|
156 return *this; |
|
157 } |
|
158 XmlWriter &operator()(const std::string &_tag,const std::string &v) |
|
159 { |
|
160 LineTag t(*this,_tag); |
|
161 (*this)(v); |
|
162 return *this; |
|
163 } |
|
164 ///\e |
|
165 |
|
166 ///\e |
|
167 /// |
|
168 template<class V> |
|
169 XmlWriter &operator()(const std::string &_tag,const V &v) |
|
170 { |
|
171 Tag t(*this,_tag); |
|
172 out(*this,v); |
|
173 return *this; |
|
174 } |
|
175 ///\e |
|
176 |
|
177 ///\e |
|
178 /// |
|
179 template<class V> |
|
180 XmlWriter &operator()(const V &v) |
|
181 { |
|
182 out(*this,v); |
|
183 return *this; |
|
184 } |
|
185 }; |
|
186 |
|
187 ////////////////////////////////////////////////////////////////////// |
|
188 |
|
189 class XmlReader |
|
190 { |
|
191 std::istream& is; |
|
192 |
|
193 std::string next_tag; |
|
194 void skipWhiteSpaces() |
|
195 { |
|
196 char c; |
|
197 while (is.get(c) && std::isspace(c,is.getloc())); |
|
198 is.unget(); |
|
199 } |
|
200 protected: |
|
201 ///\e |
|
202 |
|
203 ///\e |
|
204 /// |
|
205 void useTag() {next_tag.clear();} |
|
206 |
|
207 void useTag(const std::string &_tag) { |
|
208 if(nextTag()==_tag) useTag(); |
|
209 else throw (std::ios::failure ("data format error")); |
|
210 } |
|
211 public: |
|
212 ///\e |
|
213 |
|
214 ///\e |
|
215 /// |
|
216 const std::string &nextTag() |
|
217 { |
|
218 if(next_tag.empty()) { |
|
219 char c; |
|
220 skipWhiteSpaces(); |
|
221 if(!is.get(c) || c!='<') |
|
222 throw (std::ios::failure ("data format error")); |
|
223 next_tag.clear(); |
|
224 while (is.get(c) && c!='>') next_tag.push_back(c); |
|
225 if(c!='>') |
|
226 throw (std::ios::failure ("data format error")); |
|
227 } |
|
228 return next_tag; |
|
229 } |
|
230 |
|
231 ///\e |
|
232 |
|
233 ///\e |
|
234 /// |
|
235 class Tag |
|
236 { |
|
237 XmlReader &ix; |
|
238 const std::string tag; |
|
239 public: |
|
240 ///\e |
|
241 |
|
242 ///\e |
|
243 /// |
|
244 Tag(XmlReader &_ix,const std::string &_tag) : |
|
245 ix(_ix), tag(_tag) |
|
246 { |
|
247 ix.useTag(_tag); |
|
248 } |
|
249 ~Tag() { |
|
250 if(!std::uncaught_exception()) |
|
251 ix.useTag('/'+tag); |
|
252 } |
|
253 }; |
|
254 |
|
255 ///\e |
|
256 |
|
257 ///\e |
|
258 /// |
|
259 XmlReader(std::istream& _is) : is(_is) {} |
|
260 |
|
261 int operator()(const std::string &tag,int &v) |
|
262 { |
|
263 Tag t(*this,tag); |
|
264 if(!(is >> v)) throw (std::ios::failure ("data format error")); |
|
265 return v; |
|
266 } |
|
267 double operator()(const std::string &tag,double &v) |
|
268 { |
|
269 Tag t(*this,tag); |
|
270 if(!(is >> v)) throw (std::ios::failure ("data format error")); |
|
271 return v; |
|
272 } |
|
273 std::string &operator()(const std::string &tag,std::string &v) |
|
274 { |
|
275 Tag t(*this,tag); |
|
276 v.clear(); |
|
277 char c; |
|
278 while (is.get(c) && c!='<') |
|
279 if(c=='\\') |
|
280 if(!is.get(c)) throw (std::ios::failure ("data format error")); |
|
281 else switch(c) { |
|
282 case 'n': |
|
283 v.push_back('\n'); |
|
284 break; |
154 break; |
285 default: |
155 default: |
286 v.push_back(c); |
156 os<<*i; |
287 break; |
157 break; |
288 } |
158 } |
289 else v.push_back(c); |
159 return *this; |
290 if(c!='<') |
160 } |
291 throw (std::ios::failure ("data format error")); |
161 XmlWriter &operator()(const std::string &_tag,const std::string &v) |
292 is.unget(); |
162 { |
293 return v; |
163 LineTag t(*this,_tag); |
294 } |
164 (*this)(v); |
295 ///\e |
165 return *this; |
296 |
166 } |
297 ///\e |
167 ///\e |
298 /// |
168 |
299 template<class V> |
169 ///\e |
300 V &operator()(const std::string &tag,V &v) |
170 /// |
301 { |
171 template<class V> |
302 Tag t(*this,tag); |
172 XmlWriter &operator()(const std::string &_tag,const V &v) |
303 in(*this,v); |
173 { |
304 return v; |
174 Tag t(*this,_tag); |
305 } |
175 out(*this,v); |
306 ///\e |
176 return *this; |
307 |
177 } |
308 ///\e |
178 ///\e |
309 /// |
179 |
310 template<class V> |
180 ///\e |
311 V &operator()(V &v) |
181 /// |
312 { |
182 template<class V> |
313 in(*this,v); |
183 XmlWriter &operator()(const V &v) |
314 return v; |
184 { |
315 } |
185 out(*this,v); |
316 ///\e |
186 return *this; |
317 |
187 } |
318 ///\e |
188 }; |
319 /// |
189 |
320 template<class V> |
190 ////////////////////////////////////////////////////////////////////// |
321 V load(const std::string &tag) |
191 |
322 { |
192 class XmlReader |
323 Tag t(*this,tag); |
193 { |
324 V v; |
194 std::istream& is; |
325 (*this)(tag,v); |
195 std::string next_tag; |
326 return v; |
196 int line_number; |
327 } |
197 |
328 }; |
198 void skipWhiteSpaces() |
329 |
199 { |
330 ////////////////////////////////////////////////////////////////////// |
200 char c; |
331 |
201 while (is.get(c) && std::isspace(c,is.getloc())) if(c=='\n') line_number++; |
332 template<class A,class B> |
202 is.unget(); |
333 void out(XmlWriter &i,const std::pair<A,B> &v) |
203 } |
334 { |
204 protected: |
335 i("first",v.first); |
205 ///\e |
336 i("second",v.second); |
206 |
|
207 ///\e |
|
208 /// |
|
209 void useTag() {next_tag.clear();} |
|
210 |
|
211 void useTag(const std::string &_tag) { |
|
212 if(nextTag()==_tag) useTag(); |
|
213 else throw DataFormatError("",line_number,"Unexpected token name"); |
|
214 } |
|
215 public: |
|
216 ///\e |
|
217 |
|
218 ///\e |
|
219 /// |
|
220 const std::string &nextTag() |
|
221 { |
|
222 if(next_tag.empty()) { |
|
223 char c; |
|
224 skipWhiteSpaces(); |
|
225 if(!is.get(c) || c!='<') |
|
226 throw DataFormatError("",line_number,"Bad token"); |
|
227 next_tag.clear(); |
|
228 while (is.get(c) && c!='>') next_tag.push_back(c); |
|
229 if(c!='>') |
|
230 throw DataFormatError("",line_number,"Bad token"); |
|
231 } |
|
232 return next_tag; |
|
233 } |
|
234 |
|
235 ///\e |
|
236 |
|
237 ///\e |
|
238 /// |
|
239 class Tag |
|
240 { |
|
241 XmlReader &ix; |
|
242 const std::string tag; |
|
243 public: |
|
244 ///\e |
|
245 |
|
246 ///\e |
|
247 /// |
|
248 Tag(XmlReader &_ix,const std::string &_tag) : |
|
249 ix(_ix), tag(_tag) |
|
250 { |
|
251 ix.useTag(_tag); |
|
252 } |
|
253 ~Tag() { |
|
254 if(!std::uncaught_exception()) |
|
255 ix.useTag('/'+tag); |
|
256 } |
|
257 }; |
|
258 |
|
259 ///\e |
|
260 |
|
261 ///\e |
|
262 /// |
|
263 XmlReader(std::istream& _is) : is(_is), line_number(1) {} |
|
264 |
|
265 int operator()(const std::string &tag,int &v) |
|
266 { |
|
267 Tag t(*this,tag); |
|
268 skipWhiteSpaces(); |
|
269 if(!(is >> v)) throw DataFormatError("",line_number,"Not an 'int'"); |
|
270 return v; |
|
271 } |
|
272 double operator()(const std::string &tag,double &v) |
|
273 { |
|
274 Tag t(*this,tag); |
|
275 skipWhiteSpaces(); |
|
276 if(!(is >> v)) |
|
277 throw DataFormatError("",line_number,"Not a 'double'"); |
|
278 return v; |
|
279 } |
|
280 std::string &operator()(const std::string &tag,std::string &v) |
|
281 { |
|
282 Tag t(*this,tag); |
|
283 v.clear(); |
|
284 char c; |
|
285 while (is.get(c) && c!='<') |
|
286 if(c=='\\') |
|
287 if(!is.get(c)) |
|
288 throw DataFormatError("",line_number,"Bad string"); |
|
289 else switch(c) { |
|
290 case 'n': |
|
291 v.push_back('\n'); |
|
292 break; |
|
293 default: |
|
294 v.push_back(c); |
|
295 break; |
|
296 } |
|
297 else { |
|
298 if(c=='\n') line_number++; |
|
299 v.push_back(c); |
|
300 } |
|
301 if(c!='<') |
|
302 throw DataFormatError("",line_number,"Unexpected eof"); |
|
303 is.unget(); |
|
304 return v; |
|
305 } |
|
306 ///\e |
|
307 |
|
308 ///\e |
|
309 /// |
|
310 template<class V> |
|
311 V &operator()(const std::string &tag,V &v) |
|
312 { |
|
313 Tag t(*this,tag); |
|
314 in(*this,v); |
|
315 return v; |
|
316 } |
|
317 ///\e |
|
318 |
|
319 ///\e |
|
320 /// |
|
321 template<class V> |
|
322 V &operator()(V &v) |
|
323 { |
|
324 in(*this,v); |
|
325 return v; |
|
326 } |
|
327 ///\e |
|
328 |
|
329 ///\e |
|
330 /// |
|
331 template<class V> |
|
332 V load(const std::string &tag) |
|
333 { |
|
334 Tag t(*this,tag); |
|
335 V v; |
|
336 (*this)(tag,v); |
|
337 return v; |
|
338 } |
|
339 }; |
|
340 |
|
341 ////////////////////////////////////////////////////////////////////// |
|
342 |
|
343 template<class A> |
|
344 void out(XmlWriter &x,const std::auto_ptr<A> &v) |
|
345 { |
|
346 x(*v); |
|
347 } |
|
348 |
|
349 template<class A> |
|
350 void in(XmlReader &x,std::auto_ptr<A> &v) |
|
351 { |
|
352 v=new A; |
|
353 x(*v); |
|
354 } |
|
355 |
|
356 ////////////////////////////// |
|
357 |
|
358 template<class A,class B> |
|
359 void out(XmlWriter &x,const std::pair<A,B> &v) |
|
360 { |
|
361 x("first",v.first); |
|
362 x("second",v.second); |
|
363 } |
|
364 |
|
365 template<class A,class B> |
|
366 void in(XmlReader &x,std::pair<A,B> &v) |
|
367 { |
|
368 x("first",v.first); |
|
369 x("second",v.second); |
|
370 } |
|
371 |
|
372 ////////////////////////////// |
|
373 |
|
374 template<class T> |
|
375 void out(XmlWriter &x,const std::list<T> &v) |
|
376 { |
|
377 for(typename std::list<T>::const_iterator it=v.begin(); |
|
378 it!=v.end();++it) x("item",*it); |
|
379 } |
|
380 |
|
381 template<class T> |
|
382 void in(XmlReader &x,std::list<T> &v) |
|
383 { |
|
384 while(x.nextTag()=="item") |
|
385 { |
|
386 v.push_back(T()); |
|
387 x("item",v.back()); |
|
388 } |
|
389 } |
|
390 |
|
391 ////////////////////////////// |
|
392 |
|
393 template<class T> |
|
394 void out(XmlWriter &x,const std::vector<T> &v) |
|
395 { |
|
396 for(typename std::vector<T>::const_iterator it=v.begin(); |
|
397 it!=v.end();++it) x("item",*it); |
|
398 } |
|
399 |
|
400 template<class T> |
|
401 void in(XmlReader &x,std::vector<T> &v) |
|
402 { |
|
403 while(x.nextTag()=="item") |
|
404 { |
|
405 v.push_back(T()); |
|
406 x("item",v.back()); |
|
407 } |
|
408 } |
|
409 |
|
410 ////////////////////////////// |
|
411 |
|
412 template<class K,class V> |
|
413 void out(XmlWriter &x,const std::map<K,V> &v) |
|
414 { |
|
415 for(typename std::map<K,V>::const_iterator it=v.begin(); |
|
416 it!=v.end();++it) x("item",*it); |
|
417 } |
|
418 |
|
419 template<class K,class V> |
|
420 void in(XmlReader &x,std::map<K,V> &v) |
|
421 { |
|
422 while(x.nextTag()=="item") |
|
423 { |
|
424 typename std::map<K,V>::value_type it; |
|
425 x("item",it); |
|
426 v.insert(it); |
|
427 } |
|
428 } |
|
429 |
|
430 ////////////////////////////// |
|
431 |
|
432 template<class T> |
|
433 void out(XmlWriter &x,const lemon::xy<T> &v) |
|
434 { |
|
435 // x("x",v.x); |
|
436 // x("y",v.y); |
|
437 { XmlWriter::LineTag t(x,"x"); x(v.x); } |
|
438 { XmlWriter::ContTag t(x,"y"); x(v.y); } |
|
439 } |
|
440 |
|
441 template<class T> |
|
442 void in(XmlReader &x,lemon::xy<T> &v) |
|
443 { |
|
444 x("x",v.x); |
|
445 x("y",v.y); |
|
446 } |
|
447 |
|
448 ////////////////////////////// |
|
449 |
|
450 template<class T> |
|
451 void out(XmlWriter &x,const lemon::BoundingBox<T> &v) |
|
452 { |
|
453 if(!v.empty()) { |
|
454 x("point",v.bottomLeft()); |
|
455 if(v.bottomLeft()!=v.topRight()) x("point",v.topRight()); |
|
456 } |
|
457 } |
|
458 |
|
459 template<class T> |
|
460 void in(XmlReader &x,lemon::BoundingBox<T> &v) |
|
461 { |
|
462 v.clear(); |
|
463 while(x.nextTag()=="point") { |
|
464 lemon::xy<T> co; |
|
465 x("point",co); |
|
466 v.add(co); |
|
467 } |
|
468 } |
|
469 |
337 } |
470 } |
338 |
|
339 template<class A,class B> |
|
340 void in(XmlReader &i,std::pair<A,B> &v) |
|
341 { |
|
342 i("first",v.first); |
|
343 i("second",v.second); |
|
344 } |
|
345 |
|
346 ////////////////////////////// |
|
347 |
|
348 template<class T> |
|
349 void out(XmlWriter &i,const std::list<T> &v) |
|
350 { |
|
351 for(typename std::list<T>::const_iterator it=v.begin(); |
|
352 it!=v.end();++it) i("item",*it); |
|
353 } |
|
354 |
|
355 template<class T> |
|
356 void in(XmlReader &i,std::list<T> &v) |
|
357 { |
|
358 while(i.nextTag()=="item") |
|
359 { |
|
360 v.push_back(T()); |
|
361 i("item",v.back()); |
|
362 } |
|
363 } |
|
364 |
|
365 ////////////////////////////// |
|
366 |
|
367 template<class T> |
|
368 void out(XmlWriter &i,const std::vector<T> &v) |
|
369 { |
|
370 for(typename std::vector<T>::const_iterator it=v.begin(); |
|
371 it!=v.end();++it) i("item",*it); |
|
372 } |
|
373 |
|
374 template<class T> |
|
375 void in(XmlReader &i,std::vector<T> &v) |
|
376 { |
|
377 while(i.nextTag()=="item") |
|
378 { |
|
379 v.push_back(T()); |
|
380 i("item",v.back()); |
|
381 } |
|
382 } |
|
383 |
|
384 ////////////////////////////// |
|
385 |
|
386 template<class K,class V> |
|
387 void out(XmlWriter &i,const std::map<K,V> &v) |
|
388 { |
|
389 for(typename std::map<K,V>::const_iterator it=v.begin(); |
|
390 it!=v.end();++it) i("item",*it); |
|
391 } |
|
392 |
|
393 template<class K,class V> |
|
394 void in(XmlReader &i,std::map<K,V> &v) |
|
395 { |
|
396 while(i.nextTag()=="item") |
|
397 { |
|
398 typename std::map<K,V>::value_type it; |
|
399 i("item",it); |
|
400 v.insert(it); |
|
401 } |
|
402 } |
|
403 |
|
404 ////////////////////////////// |
|
405 |
|
406 template<class T> |
|
407 void out(XmlWriter &i,const lemon::xy<T> &v) |
|
408 { |
|
409 // i("x",v.x); |
|
410 // i("y",v.y); |
|
411 { XmlWriter::LineTag t(i,"x"); i(v.x); } |
|
412 { XmlWriter::ContTag t(i,"y"); i(v.y); } |
|
413 } |
|
414 |
|
415 template<class T> |
|
416 void in(XmlReader &i,lemon::xy<T> &v) |
|
417 { |
|
418 i("x",v.x); |
|
419 i("y",v.y); |
|
420 } |
|
421 |
|
422 ////////////////////////////// |
|
423 |
|
424 template<class T> |
|
425 void out(XmlWriter &i,const lemon::BoundingBox<T> &v) |
|
426 { |
|
427 if(!v.empty()) { |
|
428 i("point",v.bottomLeft()); |
|
429 if(v.bottomLeft()!=v.topRight()) i("point",v.topRight()); |
|
430 } |
|
431 } |
|
432 |
|
433 template<class T> |
|
434 void in(XmlReader &i,lemon::BoundingBox<T> &v) |
|
435 { |
|
436 v.clear(); |
|
437 while(i.nextTag()=="point") { |
|
438 lemon::xy<T> co; |
|
439 i("point",co); |
|
440 v+=co; |
|
441 } |
|
442 } |
|