/*! @file $Id$ */ // 1 2 3 4 5 6 7 8 // 45678901234567890123456789012345678901234567890123456789012345678901234567890 // Kompilation mit: // g++ fussnotensortierer.cxx -o fussnotensortierer -lmrw -lboost_regex // ohne libmrw-c++ (siehe unten): // g++ fussnotensortierer.cxx -o fussnotensortierer -lboost_regex #include #include #include //============================================================================== /* #include // <- so, oder wie folgt: */ /* Kommentar entfernen, wenn mrw-c++ Library fehlt (Option -lmrw entfällt dann) */ #include namespace mrw { class File { public: //------------------------------------------------------------------------ static std::string read(const std::string& filename) throw(std::exception) { std::string contents; // declare on top to allow compiler optimization std::ifstream is(filename.c_str()); std::string::size_type sz(size(is, filename)); contents.resize(sz); // make buffer long enough to store all is.read(contents.begin().operator->(), sz); // hack to get the buffer if (!is.good() && is.eof()) throw std::invalid_argument("Cannot read file: '"+filename+"'"); return contents; } //------------------------------------------------------------------------ static std::string::size_type size(std::ifstream& file, const std::string& filename = "") throw(std::exception) { if (!file) throw std::invalid_argument("Cannot get size of file: '" +filename+"'"); file.seekg(0, std::ios::end); std::string::size_type sz(file.tellg()); file.seekg(0, std::ios::beg); if (!file) throw std::invalid_argument("Cannot get size of file: '" +filename+"'"); return sz; } }; } /*------------------------------------------------------------------------------ */ //============================================================================== //! Datei einlesen, Fussnoten sortieren und nach std::cout schreiben. void sort(char const*const file) { //............................................................................ // Datei vollständig in String einlesen std::string contents(mrw::File::read(file)); //............................................................................ // Erste Hälfte: Bis zur Limite Fussnoten numerieren const std::string DELIM("\n@footnotes:\n"); // Delimiter-Markierung std::map mapper; // number remapping unsigned long num(1); // actual number std::string::iterator von(contents.begin()); boost::match_results match; for (; boost::regex_search(von, contents.end(), match, // suche alle "[x]" boost::regex("\\[[0-9]+\\]|"+DELIM)); von=match[0].second) if (match[0].str()==DELIM) { // Delimiter-Markierung erreicht // Ausgabe von übrigem unbearbeitetem Text std::copy(von, match[0].second, std::ostream_iterator(std::cout)); break; // Abbruch und unten in zweiter Hälfte weiter } else { // Nummer gefunden, bei Bedarf neuen Eintrag erzeugen if (mapper.insert(std::make_pair(match.str(), num)).second) ++num; // Ausgabe von unbearbeitetem Text vorher und umgeschriebener Nummer std::copy(von, match[0].first, std::ostream_iterator(std::cout)); std::cout<<"["< fntexts; // number to text mapper for (von=match[0].second; boost::regex_search(von, contents.end(), match, // suche "[x] ... \n" boost::regex("(\\[[0-9]+\\])([^\n]*)(\n|$)")); von=match[0].second) { std::map::iterator it(mapper.find(match[1])); if (it==mapper.end()) // Nummer gefunden, die noch nicht abgebildet wird it = mapper.insert(std::make_pair(match[1].str(), num++)).first; fntexts[it->second] = match[2].str(); // Text zu Nummer zuweisen std::copy(von, match[0].first, std::ostream_iterator(std::cout)); } //............................................................................ // Zweite Hälfte: Fussnoten und falls vorhanden Überbleibsel ausgeben. std::copy(von, contents.end(), std::ostream_iterator(std::cout)); for (std::map::iterator it(fntexts.begin()); it!=fntexts.end(); ++it) std::cout<<"["<first<<"]"<second<