//==============================================================================
/* #include <mrw/file.hpp> // <- so, oder wie folgt: */
/* Kommentar entfernen, wenn mrw-c++ Library fehlt (Option -lmrw entfällt dann) */
#include <fstream>
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<std::string, unsigned long> mapper; // number remapping
unsigned long num(1); // actual number
std::string::iterator von(contents.begin());
boost::match_results<std::string::iterator> 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<char>(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<char>(std::cout));
std::cout<<"["<<mapper[match.str()]<<"]";
}
//............................................................................
// Zweite Hälfte: Intern Abbildung von Nummern auf Text (Fussnoten) aufbauen
std::map<unsigned long, std::string> 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<std::string, unsigned long>::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<char>(std::cout));
}
//............................................................................
// Zweite Hälfte: Fussnoten und falls vorhanden Überbleibsel ausgeben.
std::copy(von, contents.end(), std::ostream_iterator<char>(std::cout));
for (std::map<unsigned long, std::string>::iterator it(fntexts.begin());
it!=fntexts.end(); ++it)
std::cout<<"["<<it->first<<"]"<<it->second<<std::endl;
}
//==============================================================================
//! Ruft nur für alle Dateien in der Argumentliste sort() auf
int main(const int argv, char const*const*const argc) {
for (int i(1); i<argv; ++i) sort(argc[i]);
return 0;
}