2069 template <typename Graph> |
2069 template <typename Graph> |
2070 GraphReader<Graph> graphReader(const char* fn, Graph& graph) { |
2070 GraphReader<Graph> graphReader(const char* fn, Graph& graph) { |
2071 GraphReader<Graph> tmp(fn, graph); |
2071 GraphReader<Graph> tmp(fn, graph); |
2072 return tmp; |
2072 return tmp; |
2073 } |
2073 } |
|
2074 |
|
2075 /// \ingroup lemon_io |
|
2076 /// |
|
2077 /// \brief Reader for the content of the \ref lgf-format "LGF" file |
|
2078 /// |
|
2079 /// This class can be used to read the sections, the map names and |
|
2080 /// the attributes from a file. Usually, the Lemon programs know |
|
2081 /// that, which type of graph, which maps and which attributes |
|
2082 /// should be read from a file, but in general tools (like glemon) |
|
2083 /// the content of an LGF file should be guessed somehow. This class |
|
2084 /// reads the graph and stores the appropriate information for |
|
2085 /// reading the graph. |
|
2086 /// |
|
2087 ///\code LgfContent content("graph.lgf"); |
|
2088 /// content.run(); |
|
2089 /// |
|
2090 /// // does it contain any node section and arc section |
|
2091 /// if (content.nodeSectionNum() == 0 || content.arcSectionNum()) { |
|
2092 /// std::cerr << "Failure, cannot find graph" << std::endl; |
|
2093 /// return -1; |
|
2094 /// } |
|
2095 /// std::cout << "The name of the default node section : " |
|
2096 /// << content.nodeSection(0) << std::endl; |
|
2097 /// std::cout << "The number of the arc maps : " |
|
2098 /// << content.arcMaps(0).size() << std::endl; |
|
2099 /// std::cout << "The name of second arc map : " |
|
2100 /// << content.arcMaps(0)[1] << std::endl; |
|
2101 ///\endcode |
|
2102 class LgfContent { |
|
2103 private: |
|
2104 |
|
2105 std::istream* _is; |
|
2106 bool local_is; |
|
2107 |
|
2108 std::vector<std::string> _node_sections; |
|
2109 std::vector<std::string> _edge_sections; |
|
2110 std::vector<std::string> _attribute_sections; |
|
2111 std::vector<std::string> _extra_sections; |
|
2112 |
|
2113 std::vector<bool> _arc_sections; |
|
2114 |
|
2115 std::vector<std::vector<std::string> > _node_maps; |
|
2116 std::vector<std::vector<std::string> > _edge_maps; |
|
2117 |
|
2118 std::vector<std::vector<std::string> > _attributes; |
|
2119 |
|
2120 |
|
2121 int line_num; |
|
2122 std::istringstream line; |
|
2123 |
|
2124 public: |
|
2125 |
|
2126 /// \brief Constructor |
|
2127 /// |
|
2128 /// Construct an \e LGF content reader, which reads from the given |
|
2129 /// input stream. |
|
2130 LgfContent(std::istream& is) |
|
2131 : _is(&is), local_is(false) {} |
|
2132 |
|
2133 /// \brief Constructor |
|
2134 /// |
|
2135 /// Construct an \e LGF content reader, which reads from the given |
|
2136 /// file. |
|
2137 LgfContent(const std::string& fn) |
|
2138 : _is(new std::ifstream(fn.c_str())), local_is(true) {} |
|
2139 |
|
2140 /// \brief Constructor |
|
2141 /// |
|
2142 /// Construct an \e LGF content reader, which reads from the given |
|
2143 /// file. |
|
2144 LgfContent(const char* fn) |
|
2145 : _is(new std::ifstream(fn)), local_is(true) {} |
|
2146 |
|
2147 /// \brief Copy constructor |
|
2148 /// |
|
2149 /// The copy constructor transfers all data from the other reader, |
|
2150 /// therefore the copied reader will not be usable more. |
|
2151 LgfContent(LgfContent& other) |
|
2152 : _is(other._is), local_is(other.local_is) { |
|
2153 |
|
2154 other._is = 0; |
|
2155 other.local_is = false; |
|
2156 |
|
2157 _node_sections.swap(other._node_sections); |
|
2158 _edge_sections.swap(other._edge_sections); |
|
2159 _attribute_sections.swap(other._attribute_sections); |
|
2160 _extra_sections.swap(other._extra_sections); |
|
2161 |
|
2162 _arc_sections.swap(other._arc_sections); |
|
2163 |
|
2164 _node_maps.swap(other._node_maps); |
|
2165 _edge_maps.swap(other._edge_maps); |
|
2166 _attributes.swap(other._attributes); |
|
2167 } |
|
2168 |
|
2169 /// \brief Destructor |
|
2170 ~LgfContent() { |
|
2171 if (local_is) delete _is; |
|
2172 } |
|
2173 |
|
2174 |
|
2175 /// \name Node sections |
|
2176 /// @{ |
|
2177 |
|
2178 /// \brief Gives back the number of node sections in the file. |
|
2179 /// |
|
2180 /// Gives back the number of node sections in the file. |
|
2181 int nodeSectionNum() const { |
|
2182 return _node_sections.size(); |
|
2183 } |
|
2184 |
|
2185 /// \brief Returns the section name at the given position. |
|
2186 /// |
|
2187 /// Returns the section name at the given position. |
|
2188 const std::string& nodeSection(int i) const { |
|
2189 return _node_sections[i]; |
|
2190 } |
|
2191 |
|
2192 /// \brief Gives back the node maps for the given section. |
|
2193 /// |
|
2194 /// Gives back the node maps for the given section. |
|
2195 const std::vector<std::string>& nodeMaps(int i) const { |
|
2196 return _node_maps[i]; |
|
2197 } |
|
2198 |
|
2199 /// @} |
|
2200 |
|
2201 /// \name Arc sections |
|
2202 /// @{ |
|
2203 |
|
2204 /// \brief Gives back the number of arc sections in the file. |
|
2205 /// |
|
2206 /// Gives back the number of arc sections in the file. |
|
2207 /// \note It is synonim of \c edgeSectionNum(). |
|
2208 int arcSectionNum() const { |
|
2209 return _edge_sections.size(); |
|
2210 } |
|
2211 |
|
2212 /// \brief Returns the section name at the given position. |
|
2213 /// |
|
2214 /// Returns the section name at the given position. |
|
2215 /// \note It is synonim of \c edgeSection(). |
|
2216 const std::string& arcSection(int i) const { |
|
2217 return _edge_sections[i]; |
|
2218 } |
|
2219 |
|
2220 /// \brief Gives back the arc maps for the given section. |
|
2221 /// |
|
2222 /// Gives back the arc maps for the given section. |
|
2223 /// \note It is synonim of \c edgeMaps(). |
|
2224 const std::vector<std::string>& arcMaps(int i) const { |
|
2225 return _edge_maps[i]; |
|
2226 } |
|
2227 |
|
2228 /// \brief Returns true when the section type is \c "@arcs". |
|
2229 /// |
|
2230 /// Returns true when the section type is \c "@arcs", and not "@edges". |
|
2231 bool isArcSection(int i) const { |
|
2232 return _arc_sections[i]; |
|
2233 } |
|
2234 |
|
2235 /// @} |
|
2236 |
|
2237 /// \name Edge sections |
|
2238 /// @{ |
|
2239 |
|
2240 /// \brief Gives back the number of edge sections in the file. |
|
2241 /// |
|
2242 /// Gives back the number of edge sections in the file. |
|
2243 int edgeSectionNum() const { |
|
2244 return _edge_sections.size(); |
|
2245 } |
|
2246 |
|
2247 /// \brief Returns the section name at the given position. |
|
2248 /// |
|
2249 /// Returns the section name at the given position. |
|
2250 const std::string& edgeSection(int i) const { |
|
2251 return _edge_sections[i]; |
|
2252 } |
|
2253 |
|
2254 /// \brief Gives back the edge maps for the given section. |
|
2255 /// |
|
2256 /// Gives back the edge maps for the given section. |
|
2257 const std::vector<std::string>& edgeMaps(int i) const { |
|
2258 return _edge_maps[i]; |
|
2259 } |
|
2260 |
|
2261 /// \brief Returns true when the section type is \c "@edges". |
|
2262 /// |
|
2263 /// Returns true when the section type is \c "@edges", and not "@arcs". |
|
2264 bool isEdgeSection(int i) const { |
|
2265 return !_arc_sections[i]; |
|
2266 } |
|
2267 |
|
2268 /// @} |
|
2269 |
|
2270 /// \name Attribute sections |
|
2271 /// @{ |
|
2272 |
|
2273 /// \brief Gives back the number of attribute sections in the file. |
|
2274 /// |
|
2275 /// Gives back the number of attribute sections in the file. |
|
2276 int attributeSectionNum() const { |
|
2277 return _attribute_sections.size(); |
|
2278 } |
|
2279 |
|
2280 /// \brief Returns the section name at the given position. |
|
2281 /// |
|
2282 /// Returns the section name at the given position. |
|
2283 const std::string& attributeSection(int i) const { |
|
2284 return _attribute_sections[i]; |
|
2285 } |
|
2286 |
|
2287 /// \brief Gives back the attributes for the given section. |
|
2288 /// |
|
2289 /// Gives back the attributes for the given section. |
|
2290 const std::vector<std::string>& attributes(int i) const { |
|
2291 return _attributes[i]; |
|
2292 } |
|
2293 |
|
2294 /// @} |
|
2295 |
|
2296 /// \name Extra sections |
|
2297 /// @{ |
|
2298 |
|
2299 /// \brief Gives back the number of extra sections in the file. |
|
2300 /// |
|
2301 /// Gives back the number of extra sections in the file. |
|
2302 int extraSectionNum() const { |
|
2303 return _extra_sections.size(); |
|
2304 } |
|
2305 |
|
2306 /// \brief Returns the extra section type at the given position. |
|
2307 /// |
|
2308 /// Returns the section type at the given position. |
|
2309 const std::string& extraSection(int i) const { |
|
2310 return _extra_sections[i]; |
|
2311 } |
|
2312 |
|
2313 /// @} |
|
2314 |
|
2315 private: |
|
2316 |
|
2317 bool readLine() { |
|
2318 std::string str; |
|
2319 while(++line_num, std::getline(*_is, str)) { |
|
2320 line.clear(); line.str(str); |
|
2321 char c; |
|
2322 if (line >> std::ws >> c && c != '#') { |
|
2323 line.putback(c); |
|
2324 return true; |
|
2325 } |
|
2326 } |
|
2327 return false; |
|
2328 } |
|
2329 |
|
2330 bool readSuccess() { |
|
2331 return static_cast<bool>(*_is); |
|
2332 } |
|
2333 |
|
2334 void skipSection() { |
|
2335 char c; |
|
2336 while (readSuccess() && line >> c && c != '@') { |
|
2337 readLine(); |
|
2338 } |
|
2339 line.putback(c); |
|
2340 } |
|
2341 |
|
2342 void readMaps(std::vector<std::string>& maps) { |
|
2343 if (!readLine()) |
|
2344 throw DataFormatError("Cannot find map captions"); |
|
2345 std::string map; |
|
2346 while (_reader_bits::readToken(line, map)) { |
|
2347 maps.push_back(map); |
|
2348 } |
|
2349 } |
|
2350 |
|
2351 void readAttributes(std::vector<std::string>& attrs) { |
|
2352 readLine(); |
|
2353 char c; |
|
2354 while (readSuccess() && line >> c && c != '@') { |
|
2355 line.putback(c); |
|
2356 std::string attr; |
|
2357 _reader_bits::readToken(line, attr); |
|
2358 attrs.push_back(attr); |
|
2359 readLine(); |
|
2360 } |
|
2361 line.putback(c); |
|
2362 } |
|
2363 |
|
2364 public: |
|
2365 |
|
2366 /// \name Execution of the content reader |
|
2367 /// @{ |
|
2368 |
|
2369 /// \brief Start the reading |
|
2370 /// |
|
2371 /// This function starts the reading |
|
2372 void run() { |
|
2373 |
|
2374 readLine(); |
|
2375 skipSection(); |
|
2376 |
|
2377 while (readSuccess()) { |
|
2378 |
|
2379 char c; |
|
2380 line >> c; |
|
2381 |
|
2382 std::string section, caption; |
|
2383 _reader_bits::readToken(line, section); |
|
2384 _reader_bits::readToken(line, caption); |
|
2385 |
|
2386 if (section == "nodes") { |
|
2387 _node_sections.push_back(caption); |
|
2388 _node_maps.push_back(std::vector<std::string>()); |
|
2389 readMaps(_node_maps.back()); |
|
2390 readLine(); skipSection(); |
|
2391 } else if (section == "arcs" || section == "edges") { |
|
2392 _edge_sections.push_back(caption); |
|
2393 _arc_sections.push_back(section == "arcs"); |
|
2394 _edge_maps.push_back(std::vector<std::string>()); |
|
2395 readMaps(_edge_maps.back()); |
|
2396 readLine(); skipSection(); |
|
2397 } else if (section == "attributes") { |
|
2398 _attribute_sections.push_back(caption); |
|
2399 _attributes.push_back(std::vector<std::string>()); |
|
2400 readAttributes(_attributes.back()); |
|
2401 } else { |
|
2402 _extra_sections.push_back(section); |
|
2403 readLine(); skipSection(); |
|
2404 } |
|
2405 } |
|
2406 } |
|
2407 |
|
2408 /// @} |
|
2409 |
|
2410 }; |
2074 } |
2411 } |
2075 |
2412 |
2076 #endif |
2413 #endif |