summaryrefslogtreecommitdiffstats
path: root/src/segtree.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/segtree.c')
-rw-r--r--src/segtree.c47
1 files changed, 41 insertions, 6 deletions
diff --git a/src/segtree.c b/src/segtree.c
index b4e76bf5..bed8bbcf 100644
--- a/src/segtree.c
+++ b/src/segtree.c
@@ -1032,6 +1032,33 @@ static struct expr *interval_to_prefix(struct expr *low, struct expr *i, const m
return __expr_to_set_elem(low, prefix);
}
+static struct expr *interval_to_string(struct expr *low, struct expr *i, const mpz_t range)
+{
+ unsigned int len = div_round_up(i->len, BITS_PER_BYTE);
+ unsigned int prefix_len, str_len;
+ char data[len + 2];
+ struct expr *expr;
+
+ prefix_len = expr_value(i)->len - mpz_scan0(range, 0);
+
+ if (prefix_len > i->len || prefix_len % BITS_PER_BYTE)
+ return interval_to_prefix(low, i, range);
+
+ mpz_export_data(data, expr_value(low)->value, BYTEORDER_BIG_ENDIAN, len);
+
+ str_len = strnlen(data, len);
+ if (str_len >= len || str_len == 0)
+ return interval_to_prefix(low, i, range);
+
+ data[str_len] = '*';
+
+ expr = constant_expr_alloc(&low->location, low->dtype,
+ BYTEORDER_HOST_ENDIAN,
+ (str_len + 1) * BITS_PER_BYTE, data);
+
+ return __expr_to_set_elem(low, expr);
+}
+
static struct expr *interval_to_range(struct expr *low, struct expr *i, mpz_t range)
{
struct expr *tmp;
@@ -1130,16 +1157,24 @@ void interval_map_decompose(struct expr *set)
mpz_and(p, expr_value(low)->value, range);
- if (!mpz_cmp_ui(range, 0))
+ if (!mpz_cmp_ui(range, 0)) {
+ if (expr_basetype(low)->type == TYPE_STRING)
+ mpz_switch_byteorder(expr_value(low)->value, low->len / BITS_PER_BYTE);
+
compound_expr_add(set, expr_get(low));
- else if ((!range_is_prefix(range) ||
- !(i->dtype->flags & DTYPE_F_PREFIX)) ||
- mpz_cmp_ui(p, 0)) {
- struct expr *expr = interval_to_range(low, i, range);
+ } else if (range_is_prefix(range) && !mpz_cmp_ui(p, 0)) {
+ struct expr *expr;
+
+ if (i->dtype->flags & DTYPE_F_PREFIX)
+ expr = interval_to_prefix(low, i, range);
+ else if (expr_basetype(i)->type == TYPE_STRING)
+ expr = interval_to_string(low, i, range);
+ else
+ expr = interval_to_range(low, i, range);
compound_expr_add(set, expr);
} else {
- struct expr *expr = interval_to_prefix(low, i, range);
+ struct expr *expr = interval_to_range(low, i, range);
compound_expr_add(set, expr);
}