strutils: new functions stripTrailingNewlines() and stripTrailingNewlines_inplace()

This commit is contained in:
Florent Rougon 2016-12-04 00:49:59 +01:00
parent 79f0d3356e
commit 3a4693803b
3 changed files with 77 additions and 0 deletions

View File

@ -238,6 +238,35 @@ namespace simgear {
return do_strip( s, BOTHSTRIP ); return do_strip( s, BOTHSTRIP );
} }
void
stripTrailingNewlines_inplace(string& s)
{
// The following (harder to read) implementation is much slower on
// my system (g++ 6.2.1 on Debian): 11.4 vs. 3.9 seconds on
// 50,000,000 iterations performed on a short CRLF-terminated
// string---and it is even a bit slower (12.9 seconds) with
// std::next(it) instead of (it+1).
//
// for (string::reverse_iterator it = s.rbegin();
// it != s.rend() && (*it == '\r' || *it == '\n'); /* empty */) {
// it = string::reverse_iterator(s.erase( (it+1).base() ));
// }
// Simple and fast
while (!s.empty() && (s.back() == '\r' || s.back() == '\n')) {
s.pop_back();
}
}
string
stripTrailingNewlines(const string& s)
{
string res = s;
stripTrailingNewlines_inplace(res);
return res;
}
string string
rpad( const string & s, string::size_type length, char c ) rpad( const string & s, string::size_type length, char c )
{ {

View File

@ -70,6 +70,24 @@ namespace simgear {
std::string rstrip( const std::string& s ); std::string rstrip( const std::string& s );
std::string strip( const std::string& s ); std::string strip( const std::string& s );
/**
* Return a new string with any trailing \r and \n characters removed.
* Typically useful to clean a CR-terminated line obtained from
* std::getline() which, upon reading CRLF (\r\n), discards the Line
* Feed character (\n) but leaves the Carriage Return (\r) in the
* string.
* @param s Input string
* @return The cleaned string
*/
std::string stripTrailingNewlines(const std::string& s);
/**
* Strip any trailing \r and \n characters from a string.
* Should have slightly less overhead than stripTrailingNewlines().
* @param s Input string (modified in-place)
*/
void stripTrailingNewlines_inplace(std::string& s);
/** /**
* Right-padding of a string to a given length * Right-padding of a string to a given length
* @param s String to pad * @param s String to pad

View File

@ -25,6 +25,34 @@ void test_strip()
SG_CHECK_EQUAL(strutils::strip("\t \na \t b\r \n "), "a \t b"); SG_CHECK_EQUAL(strutils::strip("\t \na \t b\r \n "), "a \t b");
} }
void test_stripTrailingNewlines()
{
SG_CHECK_EQUAL(strutils::stripTrailingNewlines("\rfoobar\n\r\n\n\r\r"),
"\rfoobar");
SG_CHECK_EQUAL(strutils::stripTrailingNewlines("\rfoobar\r"), "\rfoobar");
SG_CHECK_EQUAL(strutils::stripTrailingNewlines("\rfoobar"), "\rfoobar");
SG_CHECK_EQUAL(strutils::stripTrailingNewlines(""), "");
}
void test_stripTrailingNewlines_inplace()
{
string s = "\r\n\r\rfoo\n\r\rbar\n\r\n\r\r\n\r\r";
strutils::stripTrailingNewlines_inplace(s);
SG_CHECK_EQUAL(s, "\r\n\r\rfoo\n\r\rbar");
s = "\rfoobar\r";
strutils::stripTrailingNewlines_inplace(s);
SG_CHECK_EQUAL(s, "\rfoobar");
s = "\rfoobar";
strutils::stripTrailingNewlines_inplace(s);
SG_CHECK_EQUAL(s, "\rfoobar");
s = "";
strutils::stripTrailingNewlines_inplace(s);
SG_CHECK_EQUAL(s, "");
}
void test_starts_with() void test_starts_with()
{ {
SG_VERIFY(strutils::starts_with("banana", "ban")); SG_VERIFY(strutils::starts_with("banana", "ban"));
@ -148,6 +176,8 @@ void test_error_string()
int main(int argc, char* argv[]) int main(int argc, char* argv[])
{ {
test_strip(); test_strip();
test_stripTrailingNewlines();
test_stripTrailingNewlines_inplace();
test_starts_with(); test_starts_with();
test_ends_with(); test_ends_with();
test_simplify(); test_simplify();