/lib/string-random.php

https://github.com/tatakatata/kaden · PHP · 199 lines · 162 code · 24 blank · 13 comment · 31 complexity · d86401380ee5a153e46a6a7e28ef739d MD5 · raw file

  1. <?php
  2. /**
  3. * String_Random
  4. * PerlのString::RandomのPHP版です。
  5. *
  6. * 履歴
  7. * 2008/01/18 ver 0.01
  8. * 2008/09/16 ver 0.02
  9. *
  10. * @author ittetsu miyazaki<ittetsu.miyazaki@gmail.com>
  11. * @version 0.02
  12. * @package String
  13. * @access public
  14. */
  15. class String_Random {
  16. var $max = 10;
  17. var $patterns;
  18. var $regch = array(
  19. '\\' => '_slash',
  20. '.' => '_dot',
  21. '[' => '_bracket',
  22. '*' => '_asterisk',
  23. '+' => '_plus',
  24. '?' => '_question',
  25. '{' => '_brace',
  26. );
  27. function String_Random($max = null) {
  28. static $patterns;
  29. if ( !$patterns ) {
  30. $upper = range('A','Z');
  31. $lower = range('a','z');
  32. $digit = range('0','9');
  33. $punct_no = array(
  34. '!','"','#','$','%','&',"'",'(',
  35. ')','*','+',',','-','.','/',':',
  36. ';','<','=','>','?','@','[','\\',
  37. ']','^','`','{','|','}','~'
  38. );
  39. $punct = array_merge($punct_no,'_');
  40. $patterns = array(
  41. '.' => array_merge($upper, $lower, $digit, $punct),
  42. '\d' => $digit,
  43. '\D' => array_merge($upper, $lower, $punct),
  44. '\w' => array_merge($upper, $lower, $digit, "_"),
  45. '\W' => $punct_no,
  46. '\s' => array(" ", "\t"),
  47. '\S' => array_merge($upper, $lower, $digit, $punct),
  48. '\t' => array("\t"),
  49. '\n' => array("\n"),
  50. '\r' => array("\r"),
  51. );
  52. }
  53. $this->patterns = $patterns;
  54. if ( !is_null($max) ) $this->max = $max;
  55. }
  56. function randregex ($patterns) {
  57. if ( !is_array($patterns) ) return $this->_randregex($patterns);
  58. $ret = array();
  59. foreach ($patterns as $pattern) {
  60. $ret[] = $this->_randregex($pattern);
  61. }
  62. return $ret;
  63. }
  64. function _randregex ($pattern) {
  65. $string = array();
  66. $chars = preg_split('//',$pattern,-1,PREG_SPLIT_NO_EMPTY);
  67. $i = count($chars);
  68. while ($i--) {
  69. $ch = array_shift($chars);
  70. if ( array_key_exists($ch,$this->regch) ) {
  71. $method = $this->regch[$ch];
  72. $this->$method($ch,$chars,$string);
  73. }
  74. else {
  75. if ( preg_match("/[\$\^\*\(\)\+\{\}\]\|\?]/", $ch) )
  76. trigger_error("'$ch' not implemented. treating literally.",E_USER_WARNING);
  77. $string[] = array($ch);
  78. }
  79. }
  80. $ret = '';
  81. foreach ($string as $ch) {
  82. $ret .= $ch[array_rand($ch)];
  83. }
  84. return $ret;
  85. }
  86. function _slash ($ch,&$chars,&$string) {
  87. if ( !$chars )
  88. trigger_error("regex not terminated",E_USER_ERROR);
  89. $tmp = array_shift($chars);
  90. if ( (string)$tmp === 'x' ) {
  91. $tmp = array_shift($chars) . array_shift($chars);
  92. $string[] = array(chr(hexdec($tmp)));
  93. }
  94. elseif ( preg_match('/[0-7]/',$tmp) ) {
  95. trigger_error("octal parsing not implemented. treating literally.",E_USER_WARNING);
  96. $string[] = array($tmp);
  97. }
  98. elseif ( array_key_exists($ch.$tmp,$this->patterns) ) {
  99. $string[] = $this->patterns[$ch.$tmp];
  100. }
  101. else {
  102. trigger_error("'\\$tmp' being treated as literal '$tmp'",E_USER_WARNING);
  103. $string[] = array($tmp);
  104. }
  105. }
  106. function _dot ($ch,&$chars,&$string) {
  107. $string[] = $this->patterns[$ch];
  108. }
  109. function _bracket ($ch,&$chars,&$string) {
  110. $tmp = array();
  111. $i = count($chars);
  112. while ($i--) {
  113. $ch = array_shift($chars);
  114. if ( (string)$ch === ']' ) break;
  115. if ( (string)$ch === "-" && $chars && $tmp ) {
  116. $ch = array_shift($chars);
  117. for ( $j = ord($tmp[count($tmp)-1]); $j < ord($ch); $j++ ) {
  118. $tmp[] = chr($j+1);
  119. }
  120. }
  121. else {
  122. if ( preg_match('/\W/',$ch) )
  123. trigger_error("'$ch' will be treated literally inside []",E_USER_WARNING);
  124. $tmp[] = $ch;
  125. }
  126. }
  127. if ( (string)$ch !== ']' )
  128. trigger_error("unmatched []",E_USER_ERROR);
  129. $string[] = $tmp;
  130. }
  131. function _asterisk ($ch,&$chars,&$string) {
  132. array_unshift($chars,"{","0",",","}");
  133. }
  134. function _plus ($ch,&$chars,&$string) {
  135. array_unshift($chars,"{","1",",","}");
  136. }
  137. function _question ($ch,&$chars,&$string) {
  138. array_unshift($chars,"{","0",",","1","}");
  139. }
  140. function _brace ($ch,&$chars,&$string) {
  141. if ( !in_array("}",$chars) ) return $string[] = array($ch);
  142. $tmp = '';
  143. $i = count($chars);
  144. while ($i--) {
  145. $ch = array_shift($chars);
  146. if ( (string)$ch === '}' ) break;
  147. if ( !preg_match("/[\d,]/", $ch) )
  148. trigger_error("'$ch' inside {} not supported",E_USER_ERROR);
  149. $tmp .= $ch;
  150. }
  151. if ( preg_match("/,/", $tmp) ) {
  152. if ( !preg_match("/^(\d*),(\d*)$/", $tmp, $matches) )
  153. trigger_error("malformed range {$tmp}",E_USER_ERROR);
  154. $min = strlen($matches[1]) ? $matches[1] : 0;
  155. $max = strlen($matches[2]) ? $matches[2] : $this->max;
  156. if ( $min > $max )
  157. trigger_error("bad range {$tmp}",E_USER_ERROR);
  158. if ( (int)$min === (int)$max ) {
  159. $tmp = $min;
  160. }
  161. else {
  162. $tmp = $min + rand(0,$max - $min);
  163. }
  164. }
  165. if ($tmp) {
  166. $last = $string[count($string)-1];
  167. for ($i = 0; $i < ($tmp-1); $i++) {
  168. $string[] = $last;
  169. }
  170. }
  171. else {
  172. array_pop($string);
  173. }
  174. }
  175. }