regex_test_random.c 4.3 KB

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