glitch in the license text detected by hyazinthe, thank you!
[oweals/gnunet.git] / src / regex / regex_test_random.c
1 /*
2      This file is part of GNUnet
3      Copyright (C) 2012 GNUnet e.V.
4
5      GNUnet is free software: you can redistribute it and/or modify it
6      under the terms of the GNU Affero General Public License as published
7      by the Free Software Foundation, either version 3 of the License,
8      or (at your option) any later version.
9
10      GNUnet is distributed in the hope that it will be useful, but
11      WITHOUT ANY WARRANTY; without even the implied warranty of
12      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13      Affero General Public License for more details.
14 */
15 /**
16  * @file src/regex/regex_test_random.c
17  * @brief functions for creating random regular expressions and strings
18  * @author Maximilian Szengel
19  */
20 #include "platform.h"
21 #include "regex_test_lib.h"
22 #include "gnunet_crypto_lib.h"
23 #include "regex_internal.h"
24
25
26 /**
27  * Get a (pseudo) random valid literal for building a regular expression.
28  *
29  * @return random valid literal
30  */
31 static char
32 get_random_literal ()
33 {
34   uint32_t ridx;
35
36   ridx =
37       GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
38                                 (uint32_t) strlen (ALLOWED_LITERALS));
39
40   return ALLOWED_LITERALS[ridx];
41 }
42
43
44 /**
45  * Generate a (pseudo) random regular expression of length 'rx_length', as well
46  * as a (optional) string that will be matched by the generated regex. The
47  * returned regex needs to be freed.
48  *
49  * @param rx_length length of the random regex.
50  * @param matching_str (optional) pointer to a string that will contain a string
51  *                     that will be matched by the generated regex, if
52  *                     'matching_str' pointer was not NULL. Make sure you
53  *                     allocated at least rx_length+1 bytes for this sting.
54  *
55  * @return NULL if 'rx_length' is 0, a random regex of length 'rx_length', which
56  *         needs to be freed, otherwise.
57  */
58 char *
59 REGEX_TEST_generate_random_regex (size_t rx_length, char *matching_str)
60 {
61   char *rx;
62   char *rx_p;
63   char *matching_strp;
64   unsigned int i;
65   unsigned int char_op_switch;
66   unsigned int last_was_op;
67   int rx_op;
68   char current_char;
69
70   if (0 == rx_length)
71     return NULL;
72
73   if (NULL != matching_str)
74     matching_strp = matching_str;
75   else
76     matching_strp = NULL;
77
78   rx = GNUNET_malloc (rx_length + 1);
79   rx_p = rx;
80   current_char = 0;
81   last_was_op = 1;
82
83   for (i = 0; i < rx_length; i++)
84   {
85     char_op_switch = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 2);
86
87     if (0 == char_op_switch && !last_was_op)
88     {
89       last_was_op = 1;
90       rx_op = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 4);
91
92       switch (rx_op)
93       {
94       case 0:
95         current_char = '+';
96         break;
97       case 1:
98         current_char = '*';
99         break;
100       case 2:
101         current_char = '?';
102         break;
103       case 3:
104         if (i < rx_length - 1)  /* '|' cannot be at the end */
105           current_char = '|';
106         else
107           current_char = get_random_literal ();
108         break;
109       }
110     }
111     else
112     {
113       current_char = get_random_literal ();
114       last_was_op = 0;
115     }
116
117     if (NULL != matching_strp &&
118         (current_char != '+' && current_char != '*' && current_char != '?' &&
119          current_char != '|'))
120     {
121       *matching_strp = current_char;
122       matching_strp++;
123     }
124
125     *rx_p = current_char;
126     rx_p++;
127   }
128   *rx_p = '\0';
129   if (NULL != matching_strp)
130     *matching_strp = '\0';
131
132   return rx;
133 }
134
135
136 /**
137  * Generate a random string of maximum length 'max_len' that only contains literals allowed
138  * in a regular expression. The string might be 0 chars long but is garantueed
139  * to be shorter or equal to 'max_len'.
140  *
141  * @param max_len maximum length of the string that should be generated.
142  *
143  * @return random string that needs to be freed.
144  */
145 char *
146 REGEX_TEST_generate_random_string (size_t max_len)
147 {
148   unsigned int i;
149   char *str;
150   size_t len;
151
152   if (1 > max_len)
153     return GNUNET_strdup ("");
154
155   len = (size_t) GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, max_len);
156   str = GNUNET_malloc (len + 1);
157
158   for (i = 0; i < len; i++)
159   {
160     str[i] = get_random_literal ();
161   }
162
163   str[i] = '\0';
164
165   return str;
166 }