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