err(EXIT_FAILURE, "failed to create output columns");
}
-static struct libscols_line *add_line(struct libscols_table *tb, int n)
+static struct libscols_line *add_line(struct libscols_table *tb, int n, int empty)
{
char *data = NULL;
struct libscols_line *ln = scols_table_new_line(tb, NULL);
if (!ln)
err(EXIT_FAILURE, "failed to create output line");
- xasprintf(&data, "#%d", n);
- if (scols_line_refer_data(ln, COL_NAME, data))
- goto fail;
-
- xasprintf(&data, "%d", n);
- if (scols_line_refer_data(ln, COL_NUM, data))
- goto fail;
-
- xasprintf(&data, "%d.%d", n, n);
- if (scols_line_refer_data(ln, COL_FLOAT, data))
- goto fail;
-
- xasprintf(&data, "str%dstr", n);
- if (scols_line_refer_data(ln, COL_STRING, data))
- goto fail;
+ if (empty != 1) {
+ xasprintf(&data, "#%d", n);
+ if (scols_line_refer_data(ln, COL_NAME, data))
+ goto fail;
+ }
+ if (empty != 2) {
+ xasprintf(&data, "%d", n);
+ if (scols_line_refer_data(ln, COL_NUM, data))
+ goto fail;
+ }
+ if (empty != 3) {
+ xasprintf(&data, "%d.%d", n, n);
+ if (scols_line_refer_data(ln, COL_FLOAT, data))
+ goto fail;
+ }
+ if (empty != 4) {
+ xasprintf(&data, "str%dstr", n);
+ if (scols_line_refer_data(ln, COL_STRING, data))
+ goto fail;
+ }
return ln;
fail:
scols_unref_table(tb);
}
for (i = 0; i < 10; i++) {
- struct libscols_line *ln = add_line(tb, i + 1);
+ struct libscols_line *ln = add_line(tb, i + 1, i % 4);
int rc, status = 0;
if (!fltr)
switch (type) {
case F_DATA_STRING:
p = data;
- if (*p == '"') {
+ if (p && *p == '"') {
/* remove quotation marks */
size_t len = strlen(p);
if (*(p + (len - 1)) == '"')
len -= 2;
n->val.str = strndup(p + 1, len);
- } else
+ } else if (data)
n->val.str = strdup((char *) data);
- if (!n->val.str)
+ if (data && !n->val.str)
return -ENOMEM;
break;
case F_DATA_NUMBER:
- n->val.num = *((unsigned long long *) data);
+ n->val.num = data ? *((unsigned long long *) data) : 0;
break;
case F_DATA_FLOAT:
- n->val.fnum = *((long double *) data);
+ n->val.fnum = data ? *((long double *) data) : 0;
break;
case F_DATA_BOOLEAN:
- n->val.boolean = *((bool *) data) == 0 ? 0 : 1;
+ n->val.boolean = data ? (*((bool *) data) == 0 ? 0 : 1) : 0;
break;
default:
return 0;
{
const char *data;
enum filter_data type = n->type;
- int rc;
+ int rc = 0;
if (n->has_value || n->holder != F_HOLDER_COLUMN)
return 0;
return rc;
}
+static int xstrcmp(char *a, char *b)
+{
+ if (!a && !b)
+ return 0;
+ if (!a && b)
+ return -1;
+ if (a && !b)
+ return 1;
+ return strcmp(a, b);
+}
+
static int string_opers(enum filter_etype oper, struct filter_param *l,
struct filter_param *r, int *status)
{
switch (oper) {
case F_EXPR_EQ:
- *status = strcmp(l->val.str, r->val.str) == 0;
+ *status = xstrcmp(l->val.str, r->val.str) == 0;
break;
case F_EXPR_NE:
- *status = strcmp(l->val.str, r->val.str) != 0;
+ *status = xstrcmp(l->val.str, r->val.str) != 0;
break;
case F_EXPR_LE:
- *status = strcmp(l->val.str, r->val.str) <= 0;
+ *status = xstrcmp(l->val.str, r->val.str) <= 0;
break;
case F_EXPR_LT:
- *status = strcmp(l->val.str, r->val.str) < 0;
+ *status = xstrcmp(l->val.str, r->val.str) < 0;
break;
case F_EXPR_GE:
- *status = strcmp(l->val.str, r->val.str) >= 0;
+ *status = xstrcmp(l->val.str, r->val.str) >= 0;
break;
case F_EXPR_GT:
- *status = strcmp(l->val.str, r->val.str) > 0;
+ *status = xstrcmp(l->val.str, r->val.str) > 0;
break;
default:
return -EINVAL;
switch (type) {
case F_DATA_NUMBER:
{
- uint64_t num;
- int rc = ul_strtou64(str, &num, 10);
- if (rc)
- return rc;
+ uint64_t num = 0;
+ if (str) {
+ int rc = ul_strtou64(str, &num, 10);
+ if (rc)
+ return rc;
+ }
n->val.num = num;
break;
}
case F_DATA_FLOAT:
{
- long double num;
- int rc = ul_strtold(str, &num);
- if (rc)
- return rc;
+ long double num = 0;
+ if (str) {
+ int rc = ul_strtold(str, &num);
+ if (rc)
+ return rc;
+ }
n->val.fnum = num;
break;
}
int rc;
enum filter_data orgtype = n->type;
- if (!n->has_value)
- return -EINVAL;
if (type == orgtype)
return 0;
rc = fetch_holder_data(fltr, n, ln);
if (rc)
return rc;
- if (!n->has_value)
- return -EINVAL;
if (type == orgtype) {
filter_ref_node((struct filter_node *) n); /* caller wants to call filter_unref_node() for the result */