diff options
author | Jan Holesovsky <kendy@suse.cz> | 2012-07-30 17:26:00 +0200 |
---|---|---|
committer | Jan Holesovsky <kendy@suse.cz> | 2012-07-30 17:26:00 +0200 |
commit | cf9fd03724e94a61361c2e7d3cac5422ed77f733 (patch) | |
tree | c1931291eef822f1877aef49c00a3170e8a04603 | |
parent | 2e274f0b882aeaf140ac6e62eaef9c66dad0a59c (diff) |
Rework how tabs_to_spaces work, to allow more types of tabs -> spaces algs.
This kills the 'exclude_tabs' command as not necessary.
-rw-r--r-- | filter.cxx | 186 | ||||
-rw-r--r-- | filter.hxx | 16 | ||||
-rw-r--r-- | repository.cxx | 40 |
3 files changed, 174 insertions, 68 deletions
@@ -13,58 +13,143 @@ #include <cstring> #include <cstdio> #include <iostream> +#include <vector> using namespace std; struct Tabs { int spaces; - bool has_exclusion; + FilterType type; regex_t regex; - regex_t exclusion_regex; - Tabs() : spaces( 0 ), has_exclusion(false) {} + Tabs( int spaces_, FilterType type_ ) : spaces( spaces_ ), type( type_ ) {} ~Tabs() { regfree( ®ex ); } + + bool matches( const string& fname_ ) { return regexec( ®ex, fname_.c_str(), 0, NULL, 0 ) == 0; } }; -static Tabs tabs; +static std::vector< Tabs* > tabs_vector; Filter::Filter( const string& fname_ ) - : column( 0 ), + : spaces( 0 ), + column( 0 ), spaces_to_write( 0 ), + nonspace_appeared( false ), type( NO_FILTER ) { data.reserve( 16384 ); - if ( tabs.spaces > 0 && regexec( &tabs.regex, fname_.c_str(), 0, NULL, 0 ) == 0 && !(tabs.has_exclusion && (regexec( &tabs.exclusion_regex, fname_.c_str(), 0, NULL, 0) == 0))) + for ( std::vector< Tabs* >::const_iterator it = tabs_vector.begin(); it != tabs_vector.end(); ++it ) + { + if ( (*it)->matches( fname_.c_str() ) ) + { + spaces = (*it)->spaces; + type = (*it)->type; + break; // 1st wins + } + } +} + +inline void addDataLoopOld( char*& dest, char what, int& column, int& spaces_to_write, bool& nonspace_appeared, int no_spaces ) +{ + if ( what == '\t' && !nonspace_appeared ) + { + column += no_spaces; + spaces_to_write += no_spaces; + } + else if ( what == ' ' ) + { + ++column; + ++spaces_to_write; + } + else if ( what == '\n' ) { - type = FILTER_TABS; -// fprintf( stderr, "Filter : %s\n", fname_.c_str() ); + // write out any spaces that we need + for ( int i = 0; i < spaces_to_write; ++i ) + *dest++ = ' '; + + *dest++ = what; + column = 0; + spaces_to_write = 0; + nonspace_appeared = false; } else { -// fprintf( stderr, "Do Not filter : %s\n", fname_.c_str() ); + nonspace_appeared = true; + + // write out any spaces that we need + for ( int i = 0; i < spaces_to_write; ++i ) + *dest++ = ' '; + + *dest++ = what; + ++column; + spaces_to_write = 0; } } -inline void addDataLoop( char*& dest, char what, int& column, int& spaces_to_write, int no_spaces ) +inline void addDataLoopCombined( char*& dest, char what, int& column, int& spaces_to_write, bool& nonspace_appeared, int no_spaces ) { if ( what == '\t' ) { - const int tab_size = no_spaces - ( column % no_spaces ); - column += tab_size; - spaces_to_write += tab_size; + if ( nonspace_appeared ) + { + // new behavior + const int tab_size = no_spaces - ( column % no_spaces ); + column += tab_size; + spaces_to_write += tab_size; + } + else + { + // old one + column += no_spaces; + spaces_to_write += no_spaces; + } + } + else if ( what == ' ' ) + { + ++column; + ++spaces_to_write; } else if ( what == '\n' ) { *dest++ = what; column = 0; spaces_to_write = 0; + nonspace_appeared = false; + } + else + { + nonspace_appeared = true; + + // write out any spaces that we need + for ( int i = 0; i < spaces_to_write; ++i ) + *dest++ = ' '; + + *dest++ = what; + ++column; + spaces_to_write = 0; + } +} + +inline void addDataLoopAll( char*& dest, char what, int& column, int& spaces_to_write, bool& nonspace_appeared, int no_spaces ) +{ + if ( what == '\t' ) + { + const int tab_size = no_spaces - ( column % no_spaces ); + column += tab_size; + spaces_to_write += tab_size; } else if ( what == ' ' ) { ++column; ++spaces_to_write; } + else if ( what == '\n' ) + { + *dest++ = what; + column = 0; + spaces_to_write = 0; + } else { // write out any spaces that we need @@ -79,73 +164,62 @@ inline void addDataLoop( char*& dest, char what, int& column, int& spaces_to_wri void Filter::addData( const char* data_, size_t len_ ) { - if ( type == NO_FILTER || tabs.spaces <= 0 ) + if ( type == NO_FILTER || spaces <= 0 ) { data.append( data_, len_ ); return; } - // type == FILTER_TABS - char tmp[tabs.spaces*len_]; + // type == FILTER_ALL + char *tmp = new char[spaces*len_]; char *dest = tmp; - // convert the tabs to spaces (according to tabs.spaces) - for ( const char* it = data_; it < data_ + len_; ++it ) - addDataLoop( dest, *it, column, spaces_to_write, tabs.spaces ); - - data.append( tmp, dest - tmp ); -} - -void Filter::addData( const string& data_ ) -{ - if ( type == NO_FILTER || tabs.spaces <= 0 ) + // convert the tabs to spaces (according to spaces) + switch ( type ) { - data.append( data_ ); - return; + case FILTER_OLD: + for ( const char* it = data_; it < data_ + len_; ++it ) + addDataLoopOld( dest, *it, column, spaces_to_write, nonspace_appeared, spaces ); + break; + case FILTER_COMBINED: + for ( const char* it = data_; it < data_ + len_; ++it ) + addDataLoopCombined( dest, *it, column, spaces_to_write, nonspace_appeared, spaces ); + break; + case FILTER_ALL: + for ( const char* it = data_; it < data_ + len_; ++it ) + addDataLoopAll( dest, *it, column, spaces_to_write, nonspace_appeared, spaces ); + break; + case NO_FILTER: + // NO_FILTER already handled + break; } - // type == FILTER_TABS - char *tmp = new char[tabs.spaces*data_.size()]; - char *dest = tmp; - - // convert the leading tabs to N spaces (according to tabs.spaces) - for ( const char* it = data_.data(), *end = data_.data() + data_.size(); it < end; ++it ) - addDataLoop( dest, *it, column, spaces_to_write, tabs.spaces ); - data.append( tmp, dest - tmp ); delete[] tmp; } +void Filter::addData( const string& data_ ) +{ + addData( data_.data(), data_.size() ); +} + void Filter::write( std::ostream& out_ ) { out_ << "data " << data.size() << endl << data << endl; } -void Filter::setTabsToSpaces( int how_many_spaces_, const std::string& files_regex_ ) +void Filter::addTabsToSpaces( int how_many_spaces_, FilterType type_, const std::string& files_regex_ ) { - tabs.spaces = how_many_spaces_; + Tabs* tabs = new Tabs( how_many_spaces_, type_ ); - int status = regcomp( &tabs.regex, files_regex_.c_str(), REG_EXTENDED | REG_NOSUB ); - if ( status != 0 ) - { - Error::report( "Cannot create regex '" + files_regex_ + "' (for tabs_to_spaces_files)." ); - tabs.spaces = 0; - } -} - -void Filter::setExclusions( const std::string& exclusion_regex_ ) -{ - int status = regcomp( &tabs.exclusion_regex, exclusion_regex_.c_str(), REG_EXTENDED | REG_NOSUB ); - if ( status != 0 ) - { - Error::report( "Cannot create regex '" + exclusion_regex_ + "' (for exclude_tabs)." ); - } + int status = regcomp( &tabs->regex, files_regex_.c_str(), REG_EXTENDED | REG_NOSUB ); + if ( status == 0 ) + tabs_vector.push_back( tabs ); else { - fprintf( stderr, "Setup exclusion filter : %s\n", exclusion_regex_.c_str() ); - tabs. has_exclusion = true; + Error::report( "Cannot create regex '" + files_regex_ + "' (for tabs_to_spaces_files)." ); + delete tabs; } - } @@ -11,17 +11,28 @@ #include <string> #include <ostream> +enum FilterType { + NO_FILTER, ///< No filtering at all + FILTER_OLD, ///< Old way of filtering - each tab is exactly <n> spaces, no filtering after 1st non-tab, non-space character + FILTER_COMBINED, ///< Combined way of filtering - for the tabs before 1st non-tab, non-space character, behave like _OLD, for the rest as _TABS + FILTER_ALL ///< New way of filtering - each tab is converted as if it was a real tab + strip trailing whitespace +}; + class Filter { std::string data; + /// This filter adds considers a tab this amount of spaces. + int spaces; + /// Current column in the output (resets with every \n). int column; /// In order to strip trailing spaces, we do not write them immediately. int spaces_to_write; - enum FilterType { NO_FILTER, FILTER_TABS }; + /// Needed for the 'old' and 'combined' types + bool nonspace_appeared; FilterType type; @@ -34,8 +45,7 @@ public: void write( std::ostream& out_ ); - static void setTabsToSpaces( int how_many_spaces_, const std::string& files_regex_ ); - static void setExclusions( const std::string& exclusion_regex_ ); + static void addTabsToSpaces( int how_many_spaces_, FilterType type_, const std::string& files_regex_ ); }; #endif // _FILTER_HXX_ diff --git a/repository.cxx b/repository.cxx index e79b0f9..066ce68 100644 --- a/repository.cxx +++ b/repository.cxx @@ -417,22 +417,44 @@ bool Repositories::load( const char* fname_, unsigned int max_revs_, int& min_re ( equals != string::npos && line.substr( arg, equals - arg ) == "tabs_to_spaces" ) ) { if ( equals == string::npos ) - Filter::setTabsToSpaces( 8, string( ".*" ) ); + Filter::addTabsToSpaces( 8, FILTER_ALL, string( ".*" ) ); else { size_t comma = line.find( ',', equals + 1 ); if ( comma == string::npos ) - Filter::setTabsToSpaces( atoi( line.substr( equals + 1 ).c_str() ), string( ".*" ) ); + Filter::addTabsToSpaces( atoi( line.substr( equals + 1 ).c_str() ), FILTER_ALL, string( ".*" ) ); else - Filter::setTabsToSpaces( atoi( line.substr( equals + 1, comma - equals - 1 ).c_str() ), - line.substr( comma + 1 ) ); + { + size_t regex = line.find( ',', comma + 1 ); + + if ( comma == string::npos ) + { + Error::report( "Please update your configuration file, ':set tabs_to_spaces' now needs 3 params - amount, type, regex" ); + Filter::addTabsToSpaces( atoi( line.substr( equals + 1, comma - equals - 1 ).c_str() ), + FILTER_ALL, + line.substr( comma + 1 ) ); + } + else + { + FilterType filter_type = FILTER_ALL; + if ( line.substr( comma + 1, regex - comma - 1 ) == "none" ) + filter_type = NO_FILTER; + else if ( line.substr( comma + 1, regex - comma - 1 ) == "old" ) + filter_type = FILTER_OLD; + else if ( line.substr( comma + 1, regex - comma - 1 ) == "combined" ) + filter_type = FILTER_COMBINED; + else if ( line.substr( comma + 1, regex - comma - 1 ) == "all" ) + filter_type = FILTER_ALL; + else + Error::report( "Unknown type of tabs_to_spaces substitution '" + line.substr( comma + 1, regex - comma - 1 ) + "'." ); + + Filter::addTabsToSpaces( atoi( line.substr( equals + 1, comma - equals - 1 ).c_str() ), + filter_type, + line.substr( regex + 1 ) ); + } + } } } - else if ( equals != string::npos && line.substr( arg, equals - arg ) == "exclude_tabs" ) - { - string tmp = line.substr( equals + 1 ); - Filter::setExclusions(line.substr( equals + 1 ).c_str() ); - } else if ( line.substr( arg, equals - arg ) == "cleanup_first" ) { cleanup_first = true; |