summaryrefslogtreecommitdiff
path: root/ex1-9.c
blob: c2a625b60c019903d4014066c7ea6f0d6a6afe17 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
#include <stdio.h>
#include <stdbool.h>
#include <string.h>

static int _remspace_internal(FILE* fin, FILE* fout, FILE* ferr, int pc) {
    int c = fgetc(fin);
    if (c == EOF) {
        // Should I still put EOF here? does it work with pipes or not?
        //fputc(c, fout);
        return 0;
    }
    if (c == ' ' && pc == ' ') {
        // skip it
    } else {
        fputc(c, fout);
    }
    __attribute__((musttail))
    return _remspace_internal(fin, fout, ferr, c);
}

/* Copy stdin to stdout, replacing consecutive spaces with a single space
   Edge case: a leading space is retained if there are leading spaces. */
int remspace(FILE* fin, FILE* fout, FILE* ferr) {
  int res = _remspace_internal(fin, fout, ferr, -1);
  fflush(fout);
  fflush(ferr);
  return res;
}

#ifndef test

int main(void) {
    return remspace(stdin, stdout, stderr);
}

#else

#include "CuTest.h"

void do_test(CuTest* tc, char* input, const char* expected, const char* err_expected) {
    char buf[100] = {0};
    char err_buf[100] = {0};
    FILE* tin = fmemopen(input, strlen(input), "r");
    FILE* tout = fmemopen(buf, 100, "w");
    FILE* terr = fmemopen(err_buf, 100, "w");
    int res = remspace(tin, tout, terr);
    CuAssertIntEquals(tc, 0, res);
    CuAssertStrEquals(tc, expected, buf);
    CuAssertStrEquals(tc, err_expected, err_buf);
}
void test_remspace_empty(CuTest* tc) {
    do_test(tc, "", "", "");
}
void test_remspace_oneword(CuTest* tc) {
    do_test(tc, "foobar", "foobar", "");
}
void test_remspace_leadtrailspace(CuTest* tc) {
    do_test(tc, "  foo   bar  ", " foo bar ", "");
}
CuSuite* remspace_suite() {
    CuSuite* suite = CuSuiteNew();
    SUITE_ADD_TEST(suite, test_remspace_empty);
    SUITE_ADD_TEST(suite, test_remspace_oneword);
    SUITE_ADD_TEST(suite, test_remspace_leadtrailspace);
    return suite;
}
int main(void) {
    CuString* output = CuStringNew();
    CuSuite* suite = CuSuiteNew();
    CuSuiteAddSuite(suite, remspace_suite());
    CuSuiteRun(suite);
    CuSuiteSummary(suite, output);
    CuSuiteDetails(suite, output);
    printf("%s\n", output->buffer);
    return 0;
}

#endif