// Text.cxx #include "dataset_util/Text.h" #include "dataset_util/getcwd.h" #include "dataset_util/XmlElement.h" #include "dataset_util/FileName.h" #include "dataset_util/FileStatus.h" #include "dataset_util/WorkingDirectory.h" #include #include #include using std::string; using std::ostream; using std::ifstream; using std::ofstream; using std::cerr; using std::endl; typedef Text::size_type size_type; typedef Text::Line Line; namespace { const unsigned int MAX = 256; } //********************************************************************** // Local definitions. //********************************************************************** namespace { // Convert plain text to XML text. // < --> < // > --> > // & --> & // Return the mapping of special characters between text and XML. typedef std::pair XmlRepPair; typedef std::vector XmlRepMap; typedef XmlRepMap::size_type RepIndex; const XmlRepMap& xmlreps() { static XmlRepMap reps; if ( reps.size() == 0 ) { reps.push_back(XmlRepPair("&", "&")); reps.push_back(XmlRepPair("<", "<")); reps.push_back(XmlRepPair(">", ">")); } return reps; } // Warning flag. bool& warning_flag() { static bool flag = false; return flag; } } // end unnamed namespace //********************************************************************** // Static member functions. //********************************************************************** // DTD. const Text& Text::dtd() { static Text txt; if ( txt.size() == 0 ) { txt.append(""); txt.append(""); txt.append(""); txt.append(""); txt.append(""); } return txt; } //********************************************************************** // Split and append. int Text:: split(Line line, WordList& words, Line delimiters, bool skipblank) { WordList::size_type size0 = words.size(); Line::size_type lastPos = 0; if ( skipblank ) { lastPos = line.find_first_not_of(delimiters, 0); } Line::size_type pos = line.find_first_of(delimiters, lastPos); while ( lastPos != string::npos ) { words.push_back(line.substr(lastPos, pos - lastPos)); if ( skipblank ) { lastPos = line.find_first_not_of(delimiters, pos); } else { if ( pos == string::npos ) break; lastPos = pos + 1; } pos = line.find_first_of(delimiters, lastPos); } return words.size() - size0; } //********************************************************************** // Split. Text::WordList Text::split(Line line, Line delimiters, bool skipb) { WordList words; split(line, words, delimiters, skipb); return words; } //********************************************************************** // Convert a line from text to XML. void Text::text_to_xml(Line& line) { const XmlRepMap& reps = xmlreps(); for ( RepIndex irep=0; irep 0 ) { string oldrep = reps[irep].second; string newrep = reps[irep].first; Line::size_type ipos = 0; while ( ipos < line.size() ) { ipos = line.find(oldrep, ipos); if ( ipos == Line::npos ) break; line.replace(ipos, oldrep.size(), newrep); ipos += newrep.size(); } } } //********************************************************************** // Set the unprintable warning flag. void Text::set_warn(bool flag) { warning_flag() = flag; } //********************************************************************** // Return the unprintable warning flag. bool Text::warn() { return warning_flag(); } //********************************************************************** // Member functions. //********************************************************************** // Default constructor. Text::Text() : m_valid(true) { } //********************************************************************** // Constructor from a file. Text::Text(Name name, bool read, bool read_required) : m_name(name), m_valid(true) { if ( ! read ) return; FileStatus fstat(name); bool readfail = false; // File already exists. if ( fstat.exists() ) { // File is readable. if ( fstat.is_regular() && fstat.is_readable() ) { // If filename is relative, wait until we have control of the // working directory. WorkingDirectory* pwd = 0; if ( FileName(name).is_relative() ) { pwd = new WorkingDirectory(); } ifstream file(name.c_str()); while ( file && !file.eof() ) { string line; getline(file, line); if ( ! file ) break; // Verify all characters are printable. for ( string::size_type ipos=0; ipos= size() ) return Line(); return m_lines[iline]; } //********************************************************************** // Write to a file. int Text::write(Name iname) const { Name fname = iname; if ( fname == "" ) fname = name(); if ( fname == "" ) return 1; // If filename is relative, wait until we have control of the // working directory. WorkingDirectory* pwd = 0; if ( FileName(fname).is_relative() ) { pwd = new WorkingDirectory(); } ofstream file(fname.c_str()); delete pwd; if ( ! file ) return 2; for ( Text::size_type iline=0; ilineadd_attribute("name", name()); } pele->add_attribute_as_unsigned_int("nline", size()); for ( Text::size_type iline=0; ilineadd_attribute_as_unsigned_int("number", iline); Line ln = line(iline); text_to_xml(ln); pchild->add_attribute("text", ln); pele->add_child(pchild); } return pele; } //********************************************************************** // Free functions. //********************************************************************** // Output stream. ostream& operator<<(ostream& lhs, const Text& rhs) { for ( Text::size_type iline=0; iline