]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
add function which does binary operations on lists
authorAlan T. DeKok <aland@freeradius.org>
Sun, 5 Dec 2021 20:30:56 +0000 (15:30 -0500)
committerAlan T. DeKok <aland@freeradius.org>
Tue, 7 Dec 2021 13:32:20 +0000 (08:32 -0500)
src/lib/util/calc.c
src/lib/util/calc.h

index d02cb861783859ed2fdbe6f58f45d852de862b7a..9e37b88096d30ff04747f7b04d6ab4918d6a595d 100644 (file)
@@ -1446,3 +1446,68 @@ int fr_value_calc_unary_op(TALLOC_CTX *ctx, fr_value_box_t *box, fr_token_t op)
 
        return rcode;
 }
+
+/** Apply a set of operations in order to create an output box.
+ *
+ */
+int fr_value_calc_list_op(TALLOC_CTX *ctx, fr_value_box_t *box, fr_token_t op, fr_value_box_list_t const *list)
+{
+       /*
+        *      For octets and string and prepend / append, figure out
+        *      first how long the output is, create a string that
+        *      long, and then loop assigning the values.  Doing it
+        *      this way avoids a lot of intermediate garbage.
+        */
+       if (fr_type_is_variable_size(box->type)) {
+               bool tainted = false;
+               int rcode;
+               size_t len = 0;
+               uint8_t *str, *p;
+               fr_value_box_t src;
+
+               fr_dlist_foreach(list,fr_value_box_t const, a) {
+                       if (a->type != box->type) {
+                               len = 0;
+                               break;
+                       }
+
+                       len += a->vb_length;
+               }
+
+               if (!len) goto brute_force;
+
+               if (box->type == FR_TYPE_STRING) {
+                       str = talloc_array(ctx, uint8_t, len);
+                       if (!str) return -1;
+               } else {
+                       str = talloc_array(ctx, uint8_t, len + 1);
+                       if (!str) return -1;
+
+                       str[len] = '\0';
+               }
+
+               p = str;
+               fr_dlist_foreach(list,fr_value_box_t const, a) {
+                       memcpy(p, a->vb_octets, a->vb_length);
+                       p += a->vb_length;
+                       tainted |= a->tainted;
+               }
+
+               if (box->type == FR_TYPE_STRING) {
+                       fr_value_box_bstrndup_shallow(&src, NULL, (char const *) str, len, tainted);
+               } else {
+                       fr_value_box_memdup_shallow(&src, NULL, str, len, tainted);
+               }
+
+               rcode = fr_value_calc_binary_op(ctx, box, box->type, box, op, &src);
+               talloc_free(str);
+               return rcode;
+       }
+
+brute_force:
+       fr_dlist_foreach(list,fr_value_box_t const, a) {
+               if (fr_value_calc_binary_op(ctx, box, box->type, box, op, a) < 0) return -1;
+       }
+
+       return 0;
+}
index 8fbf10c3a0607dca952b99004a4e9bc6a1cbd8c0..201806d4475cd0778766c4b6146103b7c1522948 100644 (file)
@@ -1,3 +1,4 @@
+
 #pragma once
 /*
  *  This program is free software; you can redistribute it and/or modify
@@ -37,6 +38,8 @@ int fr_value_calc_assignment_op(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_token_t
 
 int fr_value_calc_unary_op(TALLOC_CTX *ctx, fr_value_box_t *box, fr_token_t op) CC_HINT(nonnull(1));
 
+int fr_value_calc_list_op(TALLOC_CTX *ctx, fr_value_box_t *box, fr_token_t op, fr_value_box_list_t const *list);
+
 #ifdef __cplusplus
 }
 #endif