}
}
+static int is_ws(int c)
+{
+ return (c == ' ' || c == '\t' || c == '\f');
+}
+
static void csv_write(void)
{
unsigned char *line = line_nth(&in_line, 0);
continue;
if (c == '\n')
return 1;
- if (c == ' ' || c == '\t' || c == '\f') {
+ if (is_ws(c)) {
ensure_field();
if (!ws)
new_field();
}
}
+/*** Transforms ***/
+
+static void trim_fields(void)
+{
+ unsigned char *line = line_nth(&in_line, 0);
+ for (int i = 0; i < fields_count(&in_fields); i++) {
+ struct field *f = fields_nth(&in_fields, i);
+ while (f->len && is_ws(line[f->start_pos]))
+ f->start_pos++, f->len--;
+ while (f->len && is_ws(line[f->start_pos + f->len - 1]))
+ f->len--;
+ }
+}
+
/*** Field selection ***/
struct selector {
-w, --ws Values separated by arbitrary whitespace\n\
\n\
Format parameters:\n\
--d, --fs=<char> Delimiter of fields\n\
+-d, --fs=<char> Delimiter of fields\n\
\n\
Other options:\n\
-(so far none)\n\
+ --trim Trim leading and trailing whitespaces in fields\n\
");
exit(0);
}
enum long_options {
OPT_HELP = 256,
+ OPT_TRIM = 257,
};
static const struct option long_options[] = {
{ "csv", 0, NULL, 'c' },
{ "fs", 1, NULL, 'd' },
+ { "trim", 0, NULL, OPT_TRIM },
{ "tsv", 0, NULL, 't' },
{ "ws", 0, NULL, 'w' },
{ "help", 0, NULL, OPT_HELP },
int main(int argc, char **argv)
{
int opt;
+ int want_trim = 0;
while ((opt = getopt_long(argc, argv, short_options, long_options, NULL)) >= 0)
switch (opt) {
break;
case OPT_HELP:
usage();
+ case OPT_TRIM:
+ want_trim = 1;
+ break;
default:
bad_args(NULL);
}
if (!in_format->read_line())
break;
+ if (want_trim)
+ trim_fields();
+
fields_reset(&out_fields);
select_fields();