Skip to content

Commit

Permalink
lib: strfuncs: Add t_str_oneline().
Browse files Browse the repository at this point in the history
This puts the string on a single line by replacing all newlines with spaces and
dropping any carriage returns
  • Loading branch information
stephanbosch authored and villesavolainen committed Feb 12, 2019
1 parent 03e2a66 commit b8ebcd6
Show file tree
Hide file tree
Showing 3 changed files with 94 additions and 0 deletions.
50 changes: 50 additions & 0 deletions src/lib/strfuncs.c
Expand Up @@ -3,6 +3,7 @@
/* @UNSAFE: whole file */

#include "lib.h"
#include "str.h"
#include "printf-format-fix.h"
#include "strfuncs.h"
#include "array.h"
Expand Down Expand Up @@ -320,6 +321,55 @@ const char *t_str_replace(const char *str, char from, char to)
return out;
}

const char *t_str_oneline(const char *str)
{
string_t *out;
size_t len;
const char *p, *pend, *poff;
bool new_line;

if (strpbrk(str, "\r\n") == NULL)
return str;

len = strlen(str);
out = t_str_new(len + 1);
new_line = TRUE;
p = poff = str;
pend = str + len;
while (p < pend) {
switch (*p) {
case '\r':
if (p > poff)
str_append_data(out, poff, p - poff);
/* just drop \r */
poff = p + 1;
break;
case '\n':
if (p > poff)
str_append_data(out, poff, p - poff);
if (new_line) {
/* coalesce multiple \n into a single space */
} else {
/* first \n after text */
str_append_c(out, ' ');
new_line = TRUE;
}
poff = p + 1;
break;
default:
new_line = FALSE;
break;
}
p++;
}

if (new_line && str_len(out) > 0)
str_truncate(out, str_len(out) - 1);
else if (p > poff)
str_append_data(out, poff, p - poff);
return str_c(out);
}

int i_strocpy(char *dest, const char *src, size_t dstsize)
{
if (dstsize == 0)
Expand Down
4 changes: 4 additions & 0 deletions src/lib/strfuncs.h
Expand Up @@ -45,6 +45,10 @@ const char *t_strconcat(const char *str1, ...)
const char *t_strcut(const char *str, char cutchar);
/* Replace all from->to chars in the string. */
const char *t_str_replace(const char *str, char from, char to);
/* Put the string on a single line by replacing all newlines with spaces and
dropping any carriage returns. Sequences of several newlines are merged into
one space and newlines at the beginning and end of the string are dropped. */
const char *t_str_oneline(const char *str);

/* Like strlcpy(), but return -1 if buffer was overflown, 0 if not. */
int i_strocpy(char *dest, const char *src, size_t dstsize);
Expand Down
40 changes: 40 additions & 0 deletions src/lib/test-strfuncs.c
Expand Up @@ -175,6 +175,45 @@ static void test_t_str_replace(void)
test_end();
}

static void test_t_str_oneline(void)
{
test_begin("t_str_oneline");
test_assert(strcmp(t_str_oneline("\n"), "") == 0);
test_assert(strcmp(t_str_oneline("\r"), "") == 0);
test_assert(strcmp(t_str_oneline("\n\n"), "") == 0);
test_assert(strcmp(t_str_oneline("\r\r"), "") == 0);
test_assert(strcmp(t_str_oneline("\r\n"), "") == 0);
test_assert(strcmp(t_str_oneline("\r\n\r\n"), "") == 0);
test_assert(strcmp(t_str_oneline("\n\r"), "") == 0);
test_assert(strcmp(t_str_oneline("\n\r\n\r"), "") == 0);
test_assert(strcmp(t_str_oneline("foo"), "foo") == 0);
test_assert(strcmp(t_str_oneline("\nfoo"), "foo") == 0);
test_assert(strcmp(t_str_oneline("foo\n"), "foo") == 0);
test_assert(strcmp(t_str_oneline("\nfoo\n"), "foo") == 0);
test_assert(strcmp(t_str_oneline("foo\nbar"), "foo bar") == 0);
test_assert(strcmp(t_str_oneline("foo\n\nbar"), "foo bar") == 0);
test_assert(strcmp(t_str_oneline("\nfoo\nbar"), "foo bar") == 0);
test_assert(strcmp(t_str_oneline("foo\nbar\n"), "foo bar") == 0);
test_assert(strcmp(t_str_oneline("foo\nbar\nbaz"), "foo bar baz") == 0);
test_assert(strcmp(t_str_oneline("\rfoo"), "foo") == 0);
test_assert(strcmp(t_str_oneline("foo\r"), "foo") == 0);
test_assert(strcmp(t_str_oneline("\rfoo\r"), "foo") == 0);
test_assert(strcmp(t_str_oneline("foo\rbar"), "foobar") == 0);
test_assert(strcmp(t_str_oneline("foo\r\rbar"), "foobar") == 0);
test_assert(strcmp(t_str_oneline("\rfoo\rbar"), "foobar") == 0);
test_assert(strcmp(t_str_oneline("foo\rbar\r"), "foobar") == 0);
test_assert(strcmp(t_str_oneline("foo\rbar\rbaz"), "foobarbaz") == 0);
test_assert(strcmp(t_str_oneline("\r\nfoo\r\n"), "foo") == 0);
test_assert(strcmp(t_str_oneline("foo\r\n"), "foo") == 0);
test_assert(strcmp(t_str_oneline("\r\nfoo"), "foo") == 0);
test_assert(strcmp(t_str_oneline("foo\r\nbar"), "foo bar") == 0);
test_assert(strcmp(t_str_oneline("foo\r\n\r\nbar"), "foo bar") == 0);
test_assert(strcmp(t_str_oneline("\r\nfoo\r\nbar"), "foo bar") == 0);
test_assert(strcmp(t_str_oneline("foo\r\nbar\r\n"), "foo bar") == 0);
test_assert(strcmp(t_str_oneline("foo\r\nbar\r\nbaz"), "foo bar baz") == 0);
test_end();
}

static void test_t_str_trim(void)
{
test_begin("t_str_trim");
Expand Down Expand Up @@ -416,6 +455,7 @@ void test_strfuncs(void)
test_t_strsplit();
test_t_strsplit_spaces();
test_t_str_replace();
test_t_str_oneline();
test_t_str_trim();
test_t_str_ltrim();
test_t_str_rtrim();
Expand Down

0 comments on commit b8ebcd6

Please sign in to comment.