/***************************************************************************
copyright : ( C ) 2006 by David Nolden
email : david . nolden . kdevelop @ art - master . de
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/***************************************************************************
* *
* This program is free software ; you can redistribute it and / or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation ; either version 2 of the License , or *
* ( at your option ) any later version . *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
# ifndef LEXERCACHE_H
# define LEXERCACHE_H
# include <hashedstring.h>
# include <ext/hash_map>
# include <ksharedptr.h>
# include "macro.h"
# include <kdebug.h>
# include <tqdatetime.h>
# include <tqfileinfo.h>
# include <ext/hash_set>
# include "cachemanager.h"
//#define LEXERCACHE_DEBUG
class LexerCache ;
class CachedLexedFile : public TDEShared , public CacheNode {
public :
///@todo add and manage the set of included files
CachedLexedFile ( const HashedString & fileName , LexerCache * manager ) ;
inline void addString ( const HashedString & string ) {
if ( ! m_definedMacroNames [ string ] ) {
m_strings . insert ( string ) ;
}
}
void addDefinedMacro ( const Macro & macro ) ;
void addUsedMacro ( const Macro & macro ) ;
void addIncludeFile ( const HashedString & file , const TQDateTime & modificationTime ) ;
inline bool hasString ( const HashedString & string ) const {
return m_strings [ string ] ;
}
TQDateTime modificationTime ( ) const ;
void addProblem ( const Problem & p ) ;
TQValueList < Problem > problems ( ) const ;
//The parameter should be a CachedLexedFile that was lexed AFTER the content of this file
void merge ( const CachedLexedFile & file ) ;
bool operator < ( const CachedLexedFile & rhs ) const {
return m_fileName < rhs . m_fileName ;
}
size_t hash ( ) const ;
HashedString fileName ( ) const {
return m_fileName ;
}
const HashedStringSet & includeFiles ( ) const {
return m_includeFiles ;
}
const MacroSet & definedMacros ( ) const {
return m_definedMacros ;
}
const MacroSet & usedMacros ( ) const {
return m_usedMacros ;
}
///Should contain a modification-time for each include-file
const TQMap < HashedString , TQDateTime > & allModificationTimes ( ) const {
return m_allModificationTimes ;
}
private :
friend class LexerCache ;
HashedString m_fileName ;
TQDateTime m_modificationTime ;
HashedStringSet m_strings ; //Set of all strings that can be affected by macros from outside
HashedStringSet m_includeFiles ; //Set of all files
MacroSet m_usedMacros ; //Set of all macros that were used, and were defined outside of this file
MacroSet m_definedMacros ; //Set of all macros that were defined while lexing this file
HashedStringSet m_definedMacroNames ;
TQValueList < Problem > m_problems ;
TQMap < HashedString , TQDateTime > m_allModificationTimes ;
/*
Needed data :
1. Set of all strings that appear in this file ( For memory - reasons they should be taken from a global string - repository , because many will be the same )
2. Set of all macros that were defined outside of , but affected the file
Algorithm :
Iterate over all available macros , and check whether they affect the file . If it does , make sure that the macro is in the macro - set and has the same body .
If the check fails : We need to reparse .
*/
} ;
typedef TDESharedPtr < CachedLexedFile > CachedLexedFilePointer ;
struct CachedLexedFilePointerCompare {
bool operator ( ) ( const CachedLexedFilePointer & lhs , const CachedLexedFilePointer & rhs ) const {
return ( * lhs ) < ( * rhs ) ;
}
} ;
class Driver ;
class LexerCache : public CacheManager {
public :
LexerCache ( Driver * d ) ;
void addLexedFile ( const CachedLexedFilePointer & file ) ;
///Returns zero if no fitting file is available for the current context
CachedLexedFilePointer lexedFile ( const HashedString & fileName ) ;
void clear ( ) ;
const HashedString & unifyString ( const HashedString & str ) {
__gnu_cxx : : hash_set < HashedString > : : const_iterator it = m_totalStringSet . find ( str ) ;
if ( it ! = m_totalStringSet . end ( ) ) {
return * it ;
} else {
m_totalStringSet . insert ( str ) ;
return str ;
}
}
virtual void saveMemory ( ) ;
private :
///before this can be called, initFileModificationCache should be called once
TQDateTime fileModificationTimeCached ( const HashedString & fileName ) ;
void initFileModificationCache ( ) ;
virtual void erase ( const CacheNode * node ) ;
bool sourceChanged ( const CachedLexedFile & file ) ; ///Returns true if the file itself, or any of its dependencies was modified.
//typedef __gnu_cxx::hash_multimap<HashedString, CachedLexedFilePointer> CachedLexedFileMap;
typedef std : : multimap < HashedString , CachedLexedFilePointer > CachedLexedFileMap ;
CachedLexedFileMap m_files ;
__gnu_cxx : : hash_set < HashedString > m_totalStringSet ; ///This is used to reduce memory-usage: Most strings appear again and again. Because TQString is reference-counted, this set contains a unique copy of each string to used for each appearance of the string
struct FileModificationCache {
TQDateTime m_readTime ;
TQDateTime m_modificationTime ;
} ;
typedef __gnu_cxx : : hash_map < HashedString , FileModificationCache > FileModificationMap ;
FileModificationMap m_fileModificationCache ;
Driver * m_driver ;
TQDateTime m_currentDateTime ;
} ;
# endif