|
From: stephan b. <sg...@us...> - 2004-12-24 15:13:49
|
Update of /cvsroot/pclasses/pclasses2/src/System In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv17916/src/System Modified Files: Mime.cpp Log Message: major reworks Index: Mime.cpp =================================================================== RCS file: /cvsroot/pclasses/pclasses2/src/System/Mime.cpp,v retrieving revision 1.5 retrieving revision 1.6 diff -u -d -r1.5 -r1.6 --- Mime.cpp 24 Dec 2004 12:44:02 -0000 1.5 +++ Mime.cpp 24 Dec 2004 15:13:35 -0000 1.6 @@ -36,6 +36,51 @@ using namespace std; +/** + Internal helper. Parses type/subtype from instr. Returns true on + success, false on error. + + The output goes to the media and subtype strings. + + This function ignores anything following a space after the subtype + name, so it may be used to parse, e.g., mime.types data without + worrying about any trailing file extensions data. + + TODO: add a third (string &) to capture (optional) file extensions + data. +*/ +bool parseMimeType( const std::string instr, + std::string & media, + std::string & subtype ) +{ + std::string::size_type slashat = instr.find("/"); + if( std::string::npos == slashat || + (instr.size()-1) == slashat) // trailing slash + { + CERR << "parseMimeType(["<<instr<<"]) failed\n"; + return false; + } + media = instr.substr(0,slashat); + std::string::size_type spat = instr.find_first_of(" \t", slashat ); + if( std::string::npos == spat ) + { + subtype = instr.substr(slashat+1); + } + else + { + subtype = instr.substr(slashat+1,spat-slashat-1); + } + + //CERR << "parseMimeType(["<<instr<<"]) == ["<<media<<"]/["<<subtype<<"]\n"; + return true; +} + +MimeType::MimeType( const std::string & media_subtype ) +: m_mediaType(), m_subType() +{ + parseMimeType( media_subtype, m_mediaType, m_subType ); +} + MimeType::MimeType(const string& mediaType, const string& subType) : m_mediaType(mediaType), m_subType(subType) { @@ -81,6 +126,7 @@ { m_types.clear(); m_exts.clear(); + m_rexts.clear(); } @@ -91,78 +137,64 @@ } -MimeType* MimeTypeDb::findByMimeType(const string& mimeTypeName) const +const MimeType * +MimeTypeDb::findByMimeType(const string& mimeTypeName) const { typedef MimeTypeMap::const_iterator MI; - - std::string::size_type slashat = mimeTypeName.find("/"); - if( std::string::npos == slashat || - (mimeTypeName.size()-1) == slashat) // trailing slash - { - return 0; - } - - string strMediaType = mimeTypeName.substr(0,slashat); - string strSubType = mimeTypeName.substr(slashat+1); - - const MimeType* type = 0; - pair<MI,MI> i = m_types.equal_range(strMediaType); - while(1) + const MimeType * m = 0; + MI it = this->typeMap().find(mimeTypeName); + if( this->typeMap().end() == it ) { - type = &(*i.first).second; - if(type->subType() == strSubType) - return const_cast<MimeType*>(type); - if(i.first == i.second) - break; - ++i.first; + return m; } - return 0; + m = &((*it).second); + return m; } -MimeType* MimeTypeDb::findByFileExt(const string& fileExt) const +const MimeType * MimeTypeDb::findByFileExt(const string& fileExt) const { - CERR << "findByFileExt() not yet implemented.\n"; return 0; -// const MimeType* type = 0; -// MimeTypeMap::const_iterator i = m_types.begin(); - -// while(i != m_types.end()) -// { -// type = &i->second; - -// const MimeType::FileExtVector& fileExts = type->fileExts(); - -// if(find(fileExts.begin(), fileExts.end(), fileExt) != fileExts.end()) -// return const_cast<MimeType*>(type); - -// ++i; -// } - -// return 0; + const MimeType* m = 0; + FileToMimesMap::const_iterator it = this->m_rexts.lower_bound( fileExt ); + if( it == this->m_rexts.end() ) + { + return m; + } + m = &((*it).second); + return m; } -bool MimeTypeDb::add(const MimeType& type) +bool MimeTypeDb::add(const MimeType& mtype) { - if(findByMimeType(type.mimeType())) - return false; - - insert(type); - return true; + if( this->typeMap().end() != this->typeMap().find( mtype.mimeType() ) ) + { + return false; + } + // CERR << "Adding mime type ["<<mtype.mimeType()<<"]\n"; + this->insert(mtype); + return true; } + +void MimeTypeDb::mapExtension(const MimeType& mimet, const std::string & file_ext ) +{ + // CERR << "mapping extension ["<<file_ext<<"] \t==>\t[" << mimet.mimeType()<<"]\n"; -void MimeTypeDb::insert(const MimeType& type) + //CERR << "add("<<mimet.mimeType()<<", ["<<file_ext<<"])\n"; +// this->add( mimet ); + // @fixme: don't re-insert existing extension entries: + this->m_exts.insert( make_pair( mimet, file_ext ) ); + this->m_rexts.insert( make_pair( file_ext, mimet ) ); +} +void MimeTypeDb::insert(const MimeType& mimet) { - m_types.insert(make_pair(type.mediaType(), type)); + m_types.insert(make_pair(mimet.mimeType(), mimet)); } -#ifndef CERR -#define CERR std::cerr << __FILE__ << ":" << std::dec << __LINE__ << " : " -#endif - std::string findSystemMimeTypeFile() { ::P::System::PathFinder pf; #ifndef WIN32 + pf.addPath( "." ); pf.addPath( PCLASSES_SHARED_DATA_DIR ); pf.addPath( "/etc" ); pf.addPath( "/etc/apache2/conf" ); @@ -176,20 +208,19 @@ return pf.find( "mime" ); } -void readSystemMimeTypes( MimeTypeDb & db ) +size_t readSystemMimeTypes( const std::string & dbfile, MimeTypeDb & db ) { + size_t count = 0; - std::string mf = findSystemMimeTypeFile(); - - if( mf.empty() ) + if( dbfile.empty() ) { CERR << "WARNING: Could not find mime.types database!\n"; - return; + return count; } - - std::ifstream strm(mf.c_str()); + // CERR << "Mime db file=["<<dbfile<<"]\n"; + std::ifstream strm(dbfile.c_str()); std::string line; - std::string::size_type p1, p2; + std::string::size_type pos; std::string ext; std::string rest; std::string strMediaType; @@ -202,38 +233,40 @@ { continue; } - p1 = line.find("/"); - p2 = line.find_first_of( " \t", p1+1 ); - // line.find_first_not_of( "abcdefghijklmnopqrstuvqxyz-ABCDEFGHIJKLMNOPQRSTUVQXYZ0123456789", p1+1 ); - // ^^^ find_first_of( " \t", p1+1 ) is giving me until line.end()! - if( std::string::npos == p1 - || std::string::npos == p2 ) + + strMediaType = strSubType = ""; + if( ! parseMimeType( line, strMediaType, strSubType ) ) { continue; } - strMediaType = line.substr(0,p1); - strSubType = line.substr(p1+1,p2-(p1+1)); - rest = line.substr(p2+1,(line.size()-p2)); -// CERR << "media=["<<strMediaType<<"]\t subtype=["<<strSubType<<"]\t" -// << "rest=["<<rest<<"]\n"; + pos = line.find_first_of( " \t" ); + rest = (std::string::npos == pos) + ? "" + : line.substr(pos+1,(line.size()-pos)); + ///CERR << "media=["<<strMediaType<<"]\t subtype=["<<strSubType<<"]\t" << "rest=["<<rest<<"]\n"; mimet = MimeType(strMediaType, strSubType); - db.typeMap().insert(make_pair(strMediaType, mimet ) ); - + db.add(mimet); + ++count; + if( rest.empty() ) + { + continue; + } std::istringstream istr(rest.c_str()); - p1 = 0; + pos = 0; while( ! istr.eof() ) { istr >> ext; if( ! ext.empty() && ext[0] != '#' ) { - ++p1; - db.extensionsMap().insert(make_pair(mimet, ext ) ); + ++pos; + db.mapExtension( mimet, ext ); } ext = ""; } - // CERR << "Mapped "<<p1<<" file extensions for "<<strMediaType<<" / " << strSubType<<"\n"; + //CERR << "Mapped "<<pos<<" file extensions for "<<strMediaType<<"/" << strSubType<<"\n"; } + return count; } @@ -242,7 +275,12 @@ { if( db.end() == db.begin() ) { - readSystemMimeTypes(db); + std::string mf = findSystemMimeTypeFile(); + if( ! mf.empty() ) + { + size_t c = readSystemMimeTypes(mf,db); + CERR << "Read " << c << " entries from ["<<mf<<"]\n"; + } } } |