]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: samples: adds the field converter.
authorEmeric Brun <ebrun@haproxy.com>
Mon, 3 Nov 2014 16:07:03 +0000 (17:07 +0100)
committerWilly Tarreau <w@1wt.eu>
Mon, 24 Nov 2014 16:44:02 +0000 (17:44 +0100)
field(<index>,<delimiters>)
  Extracts the substring at the given index considering given delimiters from
  an input string. Indexes start at 1 and delimiters are a string formatted
  list of chars.

doc/configuration.txt
src/sample.c

index 0892bc254cac24b22a83364635d7b5a2ee99e3e1..7d3dfb7566b41892ed8cfd1dc02bda1d3cf48ac8 100644 (file)
@@ -10052,6 +10052,11 @@ djb2([<avalanche>])
   32-bit hash is trivial to break. See also "sdbm", "wt6" and the "hash-type"
   directive.
 
+field(<index>,<delimiters>)
+  Extracts the substring at the given index considering given delimiters from
+  an input string. Indexes start at 1 and delimiters are a string formatted
+  list of chars.
+
 hex
   Converts a binary input sample to an hex string containing two hex digits per
   input byte. It is used to log or transfer hex dumps of some binary input data
index 02e39616687c032be90cf5a36da83d2d9c80e579..9837f0c1ef350f303e0f41f7cbd2651a980eee3a 100644 (file)
@@ -1583,6 +1583,92 @@ static int sample_conv_bytes(const struct arg *arg_p, struct sample *smp)
        return 1;
 }
 
+static int sample_conv_field_check(struct arg *args, struct sample_conv *conv,
+                                  const char *file, int line, char **err)
+{
+       struct arg *arg = args;
+
+       if (!arg) {
+               memprintf(err, "Unexpected empty arg list");
+               return 0;
+       }
+
+       if (arg->type != ARGT_UINT) {
+               memprintf(err, "Unexpected arg type");
+               return 0;
+       }
+
+       if (!arg->data.uint) {
+               memprintf(err, "Unexpected value 0 for index");
+               return 0;
+       }
+
+       arg++;
+
+       if (arg->type != ARGT_STR) {
+               memprintf(err, "Unexpected arg type");
+               return 0;
+       }
+
+       if (!arg->data.str.len) {
+               memprintf(err, "Empty separators list");
+               return 0;
+       }
+
+       return 1;
+}
+
+/* This sample function is designed to a return selected part of a string (field).
+ * First arg is the index of the field (start at 1)
+ * Second arg is a char list of separators (type string)
+ */
+static int sample_conv_field(const struct arg *arg_p, struct sample *smp)
+{
+       unsigned int field;
+       char *start, *end;
+       int i;
+
+       if (!arg_p[0].data.uint)
+               return 0;
+
+       field = 1;
+       end = start = smp->data.str.str;
+       while (end - smp->data.str.str < smp->data.str.len) {
+
+               for (i = 0 ; i < arg_p[1].data.str.len ; i++) {
+                       if (*end == arg_p[1].data.str.str[i]) {
+                               if (field == arg_p[0].data.uint)
+                                       goto found;
+                               start = end+1;
+                               field++;
+                               break;
+                       }
+               }
+               end++;
+       }
+
+       /* Field not found */
+       if (field != arg_p[0].data.uint) {
+               smp->data.str.len = 0;
+               return 1;
+       }
+found:
+       smp->data.str.len = end - start;
+       /* If ret string is len 0, no need to
+           change pointers or to update size */
+       if (!smp->data.str.len)
+               return 1;
+
+       smp->data.str.str = start;
+
+       /* Compute remaining size if needed
+           Note: smp->data.str.size cannot be set to 0 */
+       if (smp->data.str.size)
+               smp->data.str.size -= start - smp->data.str.str;
+
+       return 1;
+}
+
 /************************************************************************/
 /*       All supported sample fetch functions must be declared here     */
 /************************************************************************/
@@ -1725,6 +1811,7 @@ static struct sample_conv_kw_list sample_conv_kws = {ILH, {
        { "wt6",    sample_conv_wt6,       ARG1(0,UINT), NULL, SMP_T_BIN,  SMP_T_UINT },
        { "json",   sample_conv_json,      ARG1(1,STR),  sample_conv_json_check, SMP_T_STR,  SMP_T_STR },
        { "bytes",  sample_conv_bytes,     ARG2(1,UINT,UINT), NULL, SMP_T_BIN,  SMP_T_BIN },
+       { "field",  sample_conv_field,     ARG2(2,UINT,STR), sample_conv_field_check, SMP_T_STR,  SMP_T_STR },
        { NULL, NULL, 0, 0, 0 },
 }};