summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJan Holesovsky <kendy@suse.cz>2012-07-30 17:26:00 +0200
committerJan Holesovsky <kendy@suse.cz>2012-07-30 17:26:00 +0200
commitcf9fd03724e94a61361c2e7d3cac5422ed77f733 (patch)
treec1931291eef822f1877aef49c00a3170e8a04603
parent2e274f0b882aeaf140ac6e62eaef9c66dad0a59c (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.cxx186
-rw-r--r--filter.hxx16
-rw-r--r--repository.cxx40
3 files changed, 174 insertions, 68 deletions
diff --git a/filter.cxx b/filter.cxx
index 6bbbc39..642f16d 100644
--- a/filter.cxx
+++ b/filter.cxx
@@ -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( &regex ); }
+
+ bool matches( const string& fname_ ) { return regexec( &regex, 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;
}
-
}
diff --git a/filter.hxx b/filter.hxx
index df541b1..6b5ff52 100644
--- a/filter.hxx
+++ b/filter.hxx
@@ -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;