| | 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 | }; |