string_pattern 2.1.4 → 2.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 28c7899f11212df7952a480dfd6b4e55080387d258980d004a7a78fe64c0915d
4
- data.tar.gz: 6513592762e0a85e0a727386c40e75081b065d139afed808a26cb2af669856a3
3
+ metadata.gz: a5ea5dcf2857bafae800bd597d980c72aacb0c84b774ba698fc1107e1b9f29cf
4
+ data.tar.gz: a69ccae4e72b74692c61cbcf58d987a07c5a320e8d82c14165cba389df49615b
5
5
  SHA512:
6
- metadata.gz: 515dd4e564d3b9be7586a4c18153faf4b3d79761bffcf2fd26b516df141e681f2ff0774a30556e3a9cd16b2cbfdd83a2780dcad3a378e386e8e87a1d7183db98
7
- data.tar.gz: 70fbd57c3e47798f1b1414e4ccc63266bc896039b5cfa22960af6e3f669dbfe372488f1c72c5af0fd573ca8777703fdc791806d818c254f0a4f416c4e21c0d46
6
+ metadata.gz: 1d8a2fe7b5923924787234724b7f50a8f3cc860cbd7c01066e7ff7239a611ae3c64f1155e07ffe974344a1a8f91c4b1655230f7d0f92d54607c1e0289334bbab
7
+ data.tar.gz: bc3abd91a3885901f6c4e265ef21f4e65fc0053482328d864dd3ac7b31214129bd2c198c78f94976e160a55af6e07631cd32b8478a9e0decd87f04851d265b8d
data/README.md CHANGED
@@ -1,6 +1,8 @@
1
1
  # StringPattern
2
2
 
3
3
  [![Gem Version](https://badge.fury.io/rb/string_pattern.svg)](https://rubygems.org/gems/string_pattern)
4
+ [![Build Status](https://travis-ci.com/MarioRuiz/string_pattern.svg?branch=master)](https://github.com/MarioRuiz/string_pattern)
5
+ [![Coverage Status](https://coveralls.io/repos/github/MarioRuiz/string_pattern/badge.svg?branch=master)](https://coveralls.io/github/MarioRuiz/string_pattern?branch=master)
4
6
 
5
7
  With this gem, you can easily generate strings supplying a very simple pattern. Even generate random words in English or Spanish.
6
8
  Also, you can validate if a text fulfills a specific pattern or even generate a string following a pattern and returning the wrong length, value... for testing your applications. Perfect to be used in test data factories.
@@ -35,10 +35,10 @@ class String
35
35
  # Convert to CamelCase a string
36
36
  ########################################################
37
37
  def to_camel_case
38
- return self if self !~ /_/ && self !~ /\s/ && self =~ /[A-Z]+.*/
38
+ return self if self !~ /_/ && self !~ /\s/ && self =~ /^[A-Z]+.*/
39
39
 
40
- gsub(/\W/, '_')
41
- .split('_').map(&:capitalize).join
40
+ gsub(/\W/, "_")
41
+ .split("_").map(&:capitalize).join
42
42
  end
43
43
  end
44
44
 
@@ -70,40 +70,39 @@ class Regexp
70
70
  # adds method to convert a Regexp to StringPattern
71
71
  # returns an array of string patterns or just one string pattern
72
72
  def to_sp
73
- regexp_s = self.to_s
73
+ regexp_s = self.to_s
74
74
  return StringPattern.cache[regexp_s] unless StringPattern.cache[regexp_s].nil?
75
75
  regexp = Regexp.new regexp_s
76
- require 'regexp_parser'
76
+ require "regexp_parser"
77
77
  default_infinite = StringPattern.default_infinite
78
78
  pata = []
79
- pats = ''
79
+ pats = ""
80
80
  patg = [] # for (aa|bb|cc) group
81
81
  set = false
82
82
  capture = false
83
83
 
84
- range = ''
85
- fixed_text=false
86
- last_char = (regexp.to_s.gsub("?-mix:",'').length)-2
84
+ range = ""
85
+ fixed_text = false
86
+ last_char = (regexp.to_s.gsub("?-mix:", "").length) - 2
87
87
  Regexp::Scanner.scan regexp do |type, token, text, ts, te|
88
88
  if type == :escape
89
89
  if token == :dot
90
90
  token = :literal
91
- text = '.'
91
+ text = "."
92
92
  elsif token == :literal and text.size == 2
93
93
  text = text[1]
94
- else
94
+ else
95
95
  puts "Report token not controlled: type: #{type}, token: #{token}, text: '#{text}' [#{ts}..#{te}]"
96
96
  end
97
97
  end
98
98
 
99
-
100
99
  unless set || (token == :interval) || (token == :zero_or_one) ||
101
- (token == :zero_or_more) || (token == :one_or_more) || (pats == '')
102
- if (pats[0] == '[') && (pats[-1] == ']')
103
- pats[0] = ''
100
+ (token == :zero_or_more) || (token == :one_or_more) || (pats == "")
101
+ if (pats[0] == "[") && (pats[-1] == "]")
102
+ pats[0] = ""
104
103
  if (token == :alternation) || !patg.empty?
105
- if fixed_text
106
- if patg.size==0
104
+ if fixed_text
105
+ if patg.size == 0
107
106
  patg << (pata.pop + pats.chop)
108
107
  else
109
108
  patg[-1] += pats.chop
@@ -112,15 +111,15 @@ class Regexp
112
111
  patg << pats.chop
113
112
  end
114
113
  else
115
- if fixed_text
116
- pata[-1]+=pats.chop
114
+ if fixed_text
115
+ pata[-1] += pats.chop
117
116
  else
118
- if pats.size==2
117
+ if pats.size == 2
119
118
  pata << pats.chop #jal
120
119
  else
121
120
  pata << "1:[#{pats}" #jal
122
121
  end
123
- if last_char==te and type==:literal and token==:literal
122
+ if last_char == te and type == :literal and token == :literal
124
123
  pata << text
125
124
  pats = ""
126
125
  next
@@ -134,66 +133,66 @@ class Regexp
134
133
  pata << "1:#{pats}"
135
134
  end
136
135
  end
137
- pats = ''
136
+ pats = ""
138
137
  end
139
- fixed_text=false
138
+ fixed_text = false
140
139
 
141
140
  case token
142
141
  when :open
143
142
  set = true
144
- pats += '['
143
+ pats += "["
145
144
  when :close
146
145
  if type == :set
147
146
  set = false
148
- if pats[-1] == '['
147
+ if pats[-1] == "["
149
148
  pats.chop!
150
149
  else
151
- pats += ']'
150
+ pats += "]"
152
151
  end
153
152
  elsif type == :group
154
153
  capture = false
155
154
  unless patg.empty?
156
- patg << pats if pats.to_s != ''
155
+ patg << pats if pats.to_s != ""
157
156
  pata << patg
158
157
  patg = []
159
- pats = ''
158
+ pats = ""
160
159
  end
161
160
  end
162
161
  when :capture
163
162
  capture = true if type == :group
164
163
  when :alternation
165
164
  if type == :meta
166
- if pats != ''
165
+ if pats != ""
167
166
  patg << pats
168
- pats = ''
167
+ pats = ""
169
168
  elsif patg.empty?
170
169
  # for the case the first element was not added to patg and was on pata fex: (a+|b|c)
171
170
  patg << pata.pop
172
- end
171
+ end
173
172
  end
174
173
  when :range
175
174
  range = pats[-1]
176
175
  pats.chop!
177
176
  when :digit
178
- pats += 'n'
177
+ pats += "n"
179
178
  when :nondigit
180
- pats += '*[%0123456789%]'
179
+ pats += "*[%0123456789%]"
181
180
  when :space
182
- pats += '_'
181
+ pats += "_"
183
182
  when :nonspace
184
- pats += '*[% %]'
183
+ pats += "*[% %]"
185
184
  when :word
186
- pats += 'Ln_'
185
+ pats += "Ln_"
187
186
  when :nonword
188
- pats += '$'
187
+ pats += "$"
189
188
  when :word_boundary
190
- pats += '$'
189
+ pats += "$"
191
190
  when :dot
192
- pats += '*'
191
+ pats += "*"
193
192
  when :literal
194
- if range == ''
193
+ if range == ""
195
194
  if text.size > 1
196
- fixed_text=true
195
+ fixed_text = true
197
196
  if !patg.empty?
198
197
  patg << text.chop
199
198
  else
@@ -204,42 +203,41 @@ class Regexp
204
203
  pats += text
205
204
  end
206
205
  else
207
- range = range + '-' + text
208
- if range == 'a-z'
209
- pats = 'x' + pats
210
- elsif range == 'A-Z'
211
- pats = 'X' + pats
212
- elsif range == '0-9'
213
- pats = 'n' + pats
206
+ range = range + "-" + text
207
+ if range == "a-z"
208
+ pats = "x" + pats
209
+ elsif range == "A-Z"
210
+ pats = "X" + pats
211
+ elsif range == "0-9"
212
+ pats = "n" + pats
214
213
  else
215
214
  pats += if set
216
215
  (range[0]..range[2]).to_a.join
217
216
  else
218
- '[' + (range[0]..range[2]).to_a.join + ']'
219
- end
220
-
217
+ "[" + (range[0]..range[2]).to_a.join + "]"
218
+ end
221
219
  end
222
- range = ''
220
+ range = ""
223
221
  end
224
- pats = '[' + pats + ']' unless set
222
+ pats = "[" + pats + "]" unless set
225
223
  when :interval
226
- size = text.sub(',', '-').sub('{', '').sub('}', '')
227
- size.chop! if size[-1] == '-'
228
- pats = size + ':' + pats
224
+ size = text.sub(",", "-").sub("{", "").sub("}", "")
225
+ size.chop! if size[-1] == "-"
226
+ pats = size + ":" + pats
229
227
  if !patg.empty?
230
228
  patg << pats
231
229
  else
232
230
  pata << pats
233
231
  end
234
- pats = ''
232
+ pats = ""
235
233
  when :zero_or_one
236
- pats = '0-1:' + pats
234
+ pats = "0-1:" + pats
237
235
  if !patg.empty?
238
236
  patg << pats
239
237
  else
240
238
  pata << pats
241
239
  end
242
- pats = ''
240
+ pats = ""
243
241
  when :zero_or_more
244
242
  pats = "0-#{default_infinite}:" + pats
245
243
  if !patg.empty?
@@ -247,7 +245,7 @@ class Regexp
247
245
  else
248
246
  pata << pats
249
247
  end
250
- pats = ''
248
+ pats = ""
251
249
  when :one_or_more
252
250
  pats = "1-#{default_infinite}:" + pats
253
251
  if !patg.empty?
@@ -255,19 +253,19 @@ class Regexp
255
253
  else
256
254
  pata << pats
257
255
  end
258
- pats = ''
256
+ pats = ""
259
257
  end
260
258
  end
261
- if pats!=""
262
- if pata.empty?
263
- if pats[0]=="[" and pats[-1]=="]" #fex: /[12ab]/
259
+ if pats != ""
260
+ if pata.empty?
261
+ if pats[0] == "[" and pats[-1] == "]" #fex: /[12ab]/
264
262
  pata = ["1:#{pats}"]
265
263
  end
266
264
  else
267
- pata[-1]+=pats[1] #fex: /allo/
265
+ pata[-1] += pats[1] #fex: /allo/
268
266
  end
269
267
  end
270
- if pata.size==1 and pata[0].kind_of?(String)
268
+ if pata.size == 1 and pata[0].kind_of?(String)
271
269
  res = pata[0]
272
270
  else
273
271
  res = pata
@@ -1,5 +1,8 @@
1
1
  SP_ADD_TO_RUBY = true if !defined?(SP_ADD_TO_RUBY)
2
- require_relative 'string/pattern/add_to_ruby' if SP_ADD_TO_RUBY
2
+ require_relative "string/pattern/add_to_ruby" if SP_ADD_TO_RUBY
3
+ require_relative "string/pattern/analyze"
4
+ require_relative "string/pattern/generate"
5
+ require_relative "string/pattern/validate"
3
6
 
4
7
  # SP_ADD_TO_RUBY: (TrueFalse, default: true) You need to add this constant value before requiring the library if you want to modify the default.
5
8
  # If true it will add 'generate' and 'validate' methods to the classes: Array, String and Symbol. Also it will add 'generate' method to Kernel
@@ -19,24 +22,24 @@ require_relative 'string/pattern/add_to_ruby' if SP_ADD_TO_RUBY
19
22
  # dont_repeat: (TrueFalse, default: false)
20
23
  # If you want to generate for example 1000 strings and be sure all those strings are different you can set it to true
21
24
  # default_infinite: (Integer, default: 10)
22
- # In case using regular expressions the maximum when using * or + for repetitions
25
+ # In case using regular expressions the maximum when using * or + for repetitions
23
26
  # word_separator: (String, default: '_')
24
27
  # When generating words using symbol types 'w' or 'p' the character to separate the english or spanish words.
25
28
  class StringPattern
26
29
  class << self
27
30
  attr_accessor :national_chars, :optimistic, :dont_repeat, :cache, :cache_values, :default_infinite, :word_separator
28
31
  end
29
- @national_chars = (('a'..'z').to_a + ('A'..'Z').to_a).join
32
+ @national_chars = (("a".."z").to_a + ("A".."Z").to_a).join
30
33
  @optimistic = true
31
34
  @cache = Hash.new()
32
35
  @cache_values = Hash.new()
33
36
  @dont_repeat = false
34
37
  @default_infinite = 10
35
- @word_separator = '_'
36
- NUMBER_SET = ('0'..'9').to_a
37
- SPECIAL_SET = [' ', '~', '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '-', '_', '+', '=', '{', '}', '[', ']', "'", ';', ':', '?', '>', '<', '`', '|', '/', '"']
38
- ALPHA_SET_LOWER = ('a'..'z').to_a
39
- ALPHA_SET_CAPITAL = ('A'..'Z').to_a
38
+ @word_separator = "_"
39
+ NUMBER_SET = ("0".."9").to_a
40
+ SPECIAL_SET = [" ", "~", "!", "@", "#", "$", "%", "^", "&", "*", "(", ")", "-", "_", "+", "=", "{", "}", "[", "]", "'", ";", ":", "?", ">", "<", "`", "|", "/", '"']
41
+ ALPHA_SET_LOWER = ("a".."z").to_a
42
+ ALPHA_SET_CAPITAL = ("A".."Z").to_a
40
43
  @palabras = []
41
44
  @palabras_camel = []
42
45
  @words = []
@@ -49,984 +52,8 @@ class StringPattern
49
52
  Pattern = Struct.new(:min_length, :max_length, :symbol_type, :required_data, :excluded_data, :data_provided,
50
53
  :string_set, :all_characters_set, :unique)
51
54
 
52
- ###############################################
53
- # Analyze the pattern supplied and returns an object of Pattern structure including:
54
- # min_length, max_length, symbol_type, required_data, excluded_data, data_provided, string_set, all_characters_set
55
- ###############################################
56
- def StringPattern.analyze(pattern, silent: false)
57
- return @cache[pattern.to_s] unless @cache[pattern.to_s].nil?
58
- min_length, max_length, symbol_type = pattern.to_s.scan(/(\d+)-(\d+):(.+)/)[0]
59
- if min_length.nil?
60
- min_length, symbol_type = pattern.to_s.scan(/^!?(\d+):(.+)/)[0]
61
- max_length = min_length
62
- if min_length.nil?
63
- puts "pattern argument not valid on StringPattern.generate: #{pattern.inspect}" unless silent
64
- return pattern.to_s
65
- end
66
- end
67
- if symbol_type[-1]=="&"
68
- symbol_type.chop!
69
- unique = true
70
- else
71
- unique = false
72
- end
73
-
74
- symbol_type = '!' + symbol_type if pattern.to_s[0] == '!'
75
- min_length = min_length.to_i
76
- max_length = max_length.to_i
77
-
78
- required_data = Array.new
79
- excluded_data = Array.new
80
- required = false
81
- excluded = false
82
- data_provided = Array.new
83
- a = symbol_type
84
- begin_provided = a.index('[')
85
- excluded_end_tag = false
86
- unless begin_provided.nil?
87
- c = begin_provided + 1
88
- until c == a.size or (a[c..c] == ']' and a[c..c + 1] != ']]')
89
- if a[c..c + 1] == ']]'
90
- data_provided.push(']')
91
- c = c + 2
92
- elsif a[c..c + 1] == '%%' and !excluded then
93
- data_provided.push('%')
94
- c = c + 2
95
- else
96
- if a[c..c] == '/' and !excluded
97
- if a[c..c + 1] == '//'
98
- data_provided.push(a[c..c])
99
- if required
100
- required_data.push([a[c..c]])
101
- end
102
- c = c + 1
103
- else
104
- if !required
105
- required = true
106
- else
107
- required = false
108
- end
109
- end
110
- else
111
- if required
112
- required_data.push([a[c..c]])
113
- else
114
- if a[c..c] == '%'
115
- if a[c..c + 1] == '%%' and excluded
116
- excluded_data.push([a[c..c]])
117
- c = c + 1
118
- else
119
- if !excluded
120
- excluded = true
121
- else
122
- excluded = false
123
- excluded_end_tag = true
124
- end
125
- end
126
- else
127
- if excluded
128
- excluded_data.push([a[c..c]])
129
- end
130
- end
131
-
132
- end
133
- if excluded == false and excluded_end_tag == false
134
- data_provided.push(a[c..c])
135
- end
136
- excluded_end_tag = false
137
- end
138
- c = c + 1
139
- end
140
- end
141
- symbol_type = symbol_type[0..begin_provided].to_s + symbol_type[c..symbol_type.size].to_s
142
- end
143
-
144
- required = false
145
- required_symbol = ''
146
- if symbol_type.include?("/")
147
- symbol_type.chars.each {|stc|
148
- if stc == '/'
149
- if !required
150
- required = true
151
- else
152
- required = false
153
- end
154
- else
155
- if required
156
- required_symbol += stc
157
- end
158
- end
159
- }
160
- end
161
-
162
- national_set = @national_chars.chars
163
-
164
- if symbol_type.include?('L') then
165
- alpha_set = ALPHA_SET_LOWER + ALPHA_SET_CAPITAL
166
- elsif symbol_type.include?('x')
167
- alpha_set = ALPHA_SET_LOWER
168
- if symbol_type.include?('X')
169
- alpha_set = alpha_set + ALPHA_SET_CAPITAL
170
- end
171
- elsif symbol_type.include?('X')
172
- alpha_set = ALPHA_SET_CAPITAL
173
- else
174
- alpha_set = []
175
- end
176
- if symbol_type.include?('T')
177
- alpha_set = alpha_set + national_set
178
- end
179
-
180
- unless required_symbol.nil?
181
- if required_symbol.include?('x')
182
- required_data.push ALPHA_SET_LOWER
183
- end
184
- if required_symbol.include?('X')
185
- required_data.push ALPHA_SET_CAPITAL
186
- end
187
- if required_symbol.include?('L')
188
- required_data.push(ALPHA_SET_CAPITAL + ALPHA_SET_LOWER)
189
- end
190
- if required_symbol.include?('T')
191
- required_data.push national_set
192
- end
193
- required_symbol = required_symbol.downcase
194
- end
195
- string_set = Array.new
196
- all_characters_set = ALPHA_SET_CAPITAL + ALPHA_SET_LOWER + NUMBER_SET + SPECIAL_SET + data_provided + national_set
197
-
198
- if symbol_type.include?('_')
199
- unless symbol_type.include?('$')
200
- string_set.push(' ')
201
- end
202
- if required_symbol.include?('_')
203
- required_data.push([' '])
204
- end
205
- end
206
-
207
- #symbol_type = symbol_type.downcase
208
-
209
- if symbol_type.downcase.include?('x') or symbol_type.downcase.include?('l') or symbol_type.downcase.include?('t')
210
- string_set = string_set + alpha_set
211
- end
212
- if symbol_type.downcase.include?('n')
213
- string_set = string_set + NUMBER_SET
214
- end
215
- if symbol_type.include?('$')
216
- string_set = string_set + SPECIAL_SET
217
- end
218
- if symbol_type.include?('*')
219
- string_set = string_set + all_characters_set
220
- end
221
- if data_provided.size != 0
222
- string_set = string_set + data_provided
223
- end
224
- unless required_symbol.empty?
225
- if required_symbol.include?('n')
226
- required_data.push NUMBER_SET
227
- end
228
- if required_symbol.include?('$')
229
- required_data.push SPECIAL_SET
230
- end
231
- end
232
- unless excluded_data.empty?
233
- string_set = string_set - excluded_data.flatten
234
- end
235
- string_set.uniq!
236
- @cache[pattern.to_s] = Pattern.new(min_length, max_length, symbol_type, required_data, excluded_data, data_provided,
237
- string_set, all_characters_set, unique)
238
- return @cache[pattern.to_s]
55
+ def self.national_chars=(par)
56
+ @cache = Hash.new()
57
+ @national_chars = par
239
58
  end
240
-
241
- ###############################################
242
- # Generate a random string based on the pattern supplied
243
- # (if SP_ADD_TO_RUBY==true, by default is true) To simplify its use it is part of the String, Array, Symbol and Kernel Ruby so can be easily used also like this:
244
- # "10-15:Ln/x/".generate #generate method on String class (alias: gen)
245
- # ['(', :'3:N', ')', :'6-8:N'].generate #generate method on Array class (alias: gen)
246
- # generate("10-15:Ln/x/") #generate Ruby Kernel method
247
- # generate(['(', :'3:N', ')', :'6-8:N']) #generate Ruby Kernel method
248
- # "(,3:N,) ,3:N,-,2:N,-,2:N".split(",").generate #>(937) #generate method on Array class (alias: gen)
249
- # %w{( 3:N ) 1:_ 3:N - 2:N - 2:N}.gen #generate method on Array class, using alias gen method
250
- # Input:
251
- # pattern: array or string of different patterns. A pattern is a string with this info:
252
- # "length:symbol_type" or "min_length-max_length:symbol_type"
253
- # In case an array supplied, the positions using a string pattern should be supplied as symbols if StringPattern.optimistic==false
254
- #
255
- # These are the possible string patterns you will be able to supply:
256
- # If at the beginning we supply the character ! the resulting string won't fulfill the pattern. This character need to be the first character of the pattern.
257
- # min_length -- minimum length of the string
258
- # max_length (optional) -- maximum length of the string. If not provided the result will be with the min_length provided
259
- # symbol_type -- the type of the string we want.
260
- # you can use a combination of any ot these:
261
- # x for alpha in lowercase
262
- # X for alpha in capital letters
263
- # L for all kind of alpha in capital and lower letters
264
- # T for the national characters defined on StringPattern.national_chars
265
- # n for number
266
- # $ for special characters (includes space)
267
- # _ for space
268
- # * all characters
269
- # [characters] the characters we want. If we want to add also the ] character you have to write: ]]. If we want to add also the % character you have to write: %%
270
- # %characters% the characters we don't want on the resulting string. %% to exclude the character %
271
- # /symbols or characters/ If we want these characters to be included on the resulting string. If we want to add also the / character you have to write: //
272
- # We can supply 0 to allow empty strings, this character need to be at the beginning
273
- # If you want to include the character " use \"
274
- # If you want to include the character \ use \\
275
- # If you want to include the character [ use \[
276
- # Other uses:
277
- # @ for email
278
- # W for English words, capital and lower
279
- # w for English words only lower and words separated by underscore
280
- # P for Spanish words, capital and lower
281
- # p for Spanish words only lower and words separated by underscore
282
- # Examples:
283
- # [:"6:X", :"3-8:_N"]
284
- # # it will return a string starting with 6 capital letters and then a string containing numbers and space from 3 to 8 characters, for example: "LDJKKD34 555"
285
- # [:"6-15:L_N", "fixed text", :"3:N"]
286
- # # it will return a string of 6-15 characters containing Letters-spaces-numbers, then the text: 'fixed text' and at the end a string of 3 characters containing numbers, for example: ["L_N",6,15],"fixed text",["N",3] "3 Am399 afixed text882"
287
- # "10-20:LN[=#]"
288
- # # it will return a string of 10-20 characters containing Letters and/or numbers and/or the characters = and #, for example: eiyweQFWeL#do4Vl
289
- # "30:TN_[#=]/x/"
290
- # # it will return a string of 30 characters containing national characters defined on StringPattern.national_chars and/or numbers and/or spaces and/or the characters # = and it is necessary the resultant string includes lower alpha chars. For example: HaEdQTzJ3=OtXMh1mAPqv7NCy=upLy
291
- # "10:N[%0%]"
292
- # # 10 characters length containing numbers and excluding the character 0, for example: 3523497757
293
- # "10:N[%0%/AB/]"
294
- # # 10 characters length containing numbers and excluding the character 0 and necessary to contain the characters A B, for example: 3AA4AA57BB
295
- # "!10:N[%0%/AB/]"
296
- # # it will generate a string that doesn't fulfill the pattern supplied, examples:
297
- # # a6oMQ4JK9g
298
- # # /Y<N6Aa[ae
299
- # # 3444439A34B32
300
- # "10:N[%0%/AB/]", errors: [:length]
301
- # # it will generate a string following the pattern and with the errors supplied, in this case, length, example: AB44
302
- # Output:
303
- # the generated string
304
- ###############################################
305
- def StringPattern.generate(pattern, expected_errors: [], **synonyms)
306
- tries = 0
307
- begin
308
- good_result = true
309
- tries += 1
310
- string = ''
311
-
312
- expected_errors = synonyms[:errors] if synonyms.keys.include?(:errors)
313
-
314
- if expected_errors.kind_of?(Symbol)
315
- expected_errors = [expected_errors]
316
- end
317
-
318
- if pattern.kind_of?(Array)
319
- pattern.each {|pat|
320
-
321
- if pat.kind_of?(Array) # for the case it is one of the values
322
- pat = pat.sample
323
- end
324
-
325
- if pat.kind_of?(Symbol)
326
- if pat.to_s.scan(/^!?\d+-?\d*:.+/).size > 0
327
- string << StringPattern.generate(pat.to_s, expected_errors: expected_errors)
328
- else
329
- string << pat.to_s
330
- end
331
- elsif pat.kind_of?(String) then
332
- if @optimistic and pat.to_s.scan(/^!?\d+-?\d*:.+/).size > 0
333
- string << StringPattern.generate(pat.to_s, expected_errors: expected_errors)
334
- else
335
- string << pat
336
- end
337
- else
338
- puts "StringPattern.generate: it seems you supplied wrong array of patterns: #{pattern.inspect}, expected_errors: #{expected_errors.inspect}"
339
- return ''
340
- end
341
- }
342
- return string
343
- elsif pattern.kind_of?(String) or pattern.kind_of?(Symbol)
344
- patt = StringPattern.analyze(pattern)
345
- min_length = patt.min_length
346
- max_length = patt.max_length
347
- symbol_type = patt.symbol_type
348
-
349
- required_data = patt.required_data
350
- excluded_data = patt.excluded_data
351
- string_set = patt.string_set
352
- all_characters_set = patt.all_characters_set
353
-
354
- required_chars = Array.new
355
- unless required_data.size == 0
356
- required_data.each {|rd|
357
- required_chars << rd if rd.size == 1
358
- }
359
- unless excluded_data.size == 0
360
- if (required_chars.flatten & excluded_data.flatten).size > 0
361
- puts "pattern argument not valid on StringPattern.generate, a character cannot be required and excluded at the same time: #{pattern.inspect}, expected_errors: #{expected_errors.inspect}"
362
- return ''
363
- end
364
- end
365
- end
366
- string_set_not_allowed = Array.new
367
- elsif pattern.kind_of?(Regexp)
368
- return generate(pattern.to_sp, expected_errors: expected_errors)
369
- else
370
- puts "pattern argument not valid on StringPattern.generate: #{pattern.inspect}, expected_errors: #{expected_errors.inspect}"
371
- return pattern.to_s
372
- end
373
-
374
-
375
- allow_empty = false
376
- deny_pattern = false
377
- if symbol_type[0..0] == '!'
378
- deny_pattern = true
379
- possible_errors = [:length, :value, :required_data, :excluded_data, :string_set_not_allowed]
380
- (rand(possible_errors.size) + 1).times {
381
- expected_errors << possible_errors.sample
382
- }
383
- expected_errors.uniq!
384
- if symbol_type[1..1] == '0'
385
- allow_empty = true
386
- end
387
- elsif symbol_type[0..0] == '0' then
388
- allow_empty = true
389
- end
390
-
391
- if expected_errors.include?(:min_length) or expected_errors.include?(:length) or
392
- expected_errors.include?(:max_length)
393
- allow_empty = !allow_empty
394
- elsif expected_errors.include?(:value) or
395
- expected_errors.include?(:excluded_data) or
396
- expected_errors.include?(:required_data) or
397
- expected_errors.include?(:string_set_not_allowed) and allow_empty
398
- allow_empty = false
399
- end
400
-
401
- length = min_length
402
- symbol_type_orig = symbol_type
403
-
404
- expected_errors_left = expected_errors.dup
405
-
406
- symbol_type = symbol_type_orig
407
-
408
- unless deny_pattern
409
- if required_data.size == 0 and expected_errors_left.include?(:required_data)
410
- puts "required data not supplied on pattern so it won't be possible to generate a wrong string. StringPattern.generate: #{pattern.inspect}, expected_errors: #{expected_errors.inspect}"
411
- return ''
412
- end
413
-
414
- if excluded_data.size == 0 and expected_errors_left.include?(:excluded_data)
415
- puts "excluded data not supplied on pattern so it won't be possible to generate a wrong string. StringPattern.generate: #{pattern.inspect}, expected_errors: #{expected_errors.inspect}"
416
- return ''
417
- end
418
-
419
- if expected_errors_left.include?(:string_set_not_allowed)
420
- string_set_not_allowed = all_characters_set - string_set
421
- if string_set_not_allowed.size == 0 then
422
- puts "all characters are allowed so it won't be possible to generate a wrong string. StringPattern.generate: #{pattern.inspect}, expected_errors: #{expected_errors.inspect}"
423
- return ''
424
- end
425
- end
426
- end
427
-
428
- if expected_errors_left.include?(:min_length) or
429
- expected_errors_left.include?(:max_length) or
430
- expected_errors_left.include?(:length)
431
- if expected_errors_left.include?(:min_length) or
432
- (min_length > 0 and expected_errors_left.include?(:length) and rand(2) == 0)
433
- if min_length > 0
434
- if allow_empty
435
- length = rand(min_length).to_i
436
- else
437
- length = rand(min_length - 1).to_i + 1
438
- end
439
- if required_data.size > length and required_data.size < min_length
440
- length = required_data.size
441
- end
442
- expected_errors_left.delete(:length)
443
- expected_errors_left.delete(:min_length)
444
- else
445
- puts "min_length is 0 so it won't be possible to generate a wrong string smaller than 0 characters. StringPattern.generate: #{pattern.inspect}, expected_errors: #{expected_errors.inspect}"
446
- return ''
447
- end
448
- elsif expected_errors_left.include?(:max_length) or expected_errors_left.include?(:length)
449
- length = max_length + 1 + rand(max_length).to_i
450
- expected_errors_left.delete(:length)
451
- expected_errors_left.delete(:max_length)
452
- end
453
- else
454
- if allow_empty and rand(7) == 1
455
- length = 0
456
- else
457
- if max_length == min_length
458
- length = min_length
459
- else
460
- length = min_length + rand(max_length - min_length + 1)
461
- end
462
- end
463
- end
464
-
465
- if deny_pattern
466
- if required_data.size == 0 and expected_errors_left.include?(:required_data)
467
- expected_errors_left.delete(:required_data)
468
- end
469
-
470
- if excluded_data.size == 0 and expected_errors_left.include?(:excluded_data)
471
- expected_errors_left.delete(:excluded_data)
472
- end
473
-
474
- if expected_errors_left.include?(:string_set_not_allowed)
475
- string_set_not_allowed = all_characters_set - string_set
476
- if string_set_not_allowed.size == 0
477
- expected_errors_left.delete(:string_set_not_allowed)
478
- end
479
- end
480
-
481
- if symbol_type == '!@' and expected_errors_left.size == 0 and !expected_errors.include?(:length) and
482
- (expected_errors.include?(:required_data) or expected_errors.include?(:excluded_data))
483
- expected_errors_left.push(:value)
484
- end
485
-
486
- end
487
-
488
- string = ''
489
- if symbol_type != '@' and symbol_type != '!@' and length != 0 and string_set.size != 0
490
- if string_set.size != 0
491
- 1.upto(length) {|i| string << string_set.sample.to_s
492
- }
493
- end
494
- if required_data.size > 0
495
- positions_to_set = (0..(string.size - 1)).to_a
496
- required_data.each {|rd|
497
- if (string.chars & rd).size > 0
498
- rd_to_set = (string.chars & rd).sample
499
- else
500
- rd_to_set = rd.sample
501
- end
502
- if ((0...string.length).find_all {|i| string[i, 1] == rd_to_set}).size == 0
503
- if positions_to_set.size == 0
504
- puts "pattern not valid on StringPattern.generate, not possible to generate a valid string: #{pattern.inspect}, expected_errors: #{expected_errors.inspect}"
505
- return ''
506
- else
507
- k = positions_to_set.sample
508
- string[k] = rd_to_set
509
- positions_to_set.delete(k)
510
- end
511
- else
512
- k = ((0...string.length).find_all {|i| string[i, 1] == rd_to_set}).sample
513
- positions_to_set.delete(k)
514
- end
515
- }
516
- end
517
- excluded_data.each {|ed|
518
- if (string.chars & ed).size > 0
519
- (string.chars & ed).each {|s|
520
- string.gsub!(s, string_set.sample)
521
- }
522
- end
523
- }
524
-
525
- if expected_errors_left.include?(:value)
526
- string_set_not_allowed = all_characters_set - string_set if string_set_not_allowed.size == 0
527
- if string_set_not_allowed.size == 0
528
- puts "Not possible to generate a non valid string on StringPattern.generate: #{pattern.inspect}, expected_errors: #{expected_errors.inspect}"
529
- return ''
530
- end
531
- (rand(string.size) + 1).times {
532
- string[rand(string.size)] = (all_characters_set - string_set).sample
533
- }
534
- expected_errors_left.delete(:value)
535
- end
536
-
537
- if expected_errors_left.include?(:required_data) and required_data.size > 0
538
- (rand(required_data.size) + 1).times {
539
- chars_to_remove = required_data.sample
540
- chars_to_remove.each {|char_to_remove|
541
- string.gsub!(char_to_remove, (string_set - chars_to_remove).sample)
542
- }
543
- }
544
- expected_errors_left.delete(:required_data)
545
- end
546
-
547
- if expected_errors_left.include?(:excluded_data) and excluded_data.size > 0
548
- (rand(string.size) + 1).times {
549
- string[rand(string.size)] = excluded_data.sample.sample
550
- }
551
- expected_errors_left.delete(:excluded_data)
552
- end
553
-
554
- if expected_errors_left.include?(:string_set_not_allowed)
555
- string_set_not_allowed = all_characters_set - string_set if string_set_not_allowed.size == 0
556
- if string_set_not_allowed.size > 0
557
- (rand(string.size) + 1).times {
558
- string[rand(string.size)] = string_set_not_allowed.sample
559
- }
560
- expected_errors_left.delete(:string_set_not_allowed)
561
- end
562
- end
563
- elsif (symbol_type == 'W' or symbol_type == 'P' or symbol_type=='w' or symbol_type =='p') and length>0
564
- words = []
565
- words_short = []
566
- if symbol_type == 'W'
567
- if @words_camel.empty?
568
- require "pathname"
569
- require "json"
570
- filename = File.join Pathname(File.dirname(__FILE__)), "../data", "english/nouns.json"
571
- nouns = JSON.parse(File.read(filename))
572
- filename = File.join Pathname(File.dirname(__FILE__)), "../data", "english/adjs.json"
573
- adjs = JSON.parse(File.read(filename))
574
- nouns = nouns.map(&:to_camel_case)
575
- adjs = adjs.map(&:to_camel_case)
576
- @words_camel = adjs + nouns
577
- @words_camel_short = @words_camel.sample(2000)
578
- end
579
- words = @words_camel
580
- words_short = @words_camel_short
581
- elsif symbol_type == 'w'
582
- if @words.empty?
583
- require "pathname"
584
- require "json"
585
- filename = File.join Pathname(File.dirname(__FILE__)), "../data", "english/nouns.json"
586
- nouns = JSON.parse(File.read(filename))
587
- filename = File.join Pathname(File.dirname(__FILE__)), "../data", "english/adjs.json"
588
- adjs = JSON.parse(File.read(filename))
589
- @words = adjs + nouns
590
- @words_short = @words.sample(2000)
591
- end
592
- words = @words
593
- words_short = @words_short
594
- elsif symbol_type == 'P'
595
- if @palabras_camel.empty?
596
- require "pathname"
597
- require "json"
598
- filename = File.join Pathname(File.dirname(__FILE__)), "../data", "spanish/palabras#{rand(12)}.json"
599
- palabras = JSON.parse(File.read(filename))
600
- palabras = palabras.map(&:to_camel_case)
601
- @palabras_camel = palabras
602
- @palabras_camel_short = @palabras_camel.sample(2000)
603
- end
604
- words = @palabras_camel
605
- words_short = @palabras_camel_short
606
- elsif symbol_type == 'p'
607
- if @palabras.empty?
608
- require "pathname"
609
- require "json"
610
- filename = File.join Pathname(File.dirname(__FILE__)), "../data", "spanish/palabras#{rand(12)}.json"
611
- palabras = JSON.parse(File.read(filename))
612
- @palabras = palabras
613
- @palabras_short = @palabras.sample(2000)
614
- end
615
- words = @palabras
616
- words_short = @palabras_short
617
- end
618
-
619
- wordr = ""
620
- wordr_array = []
621
- tries = 0
622
- while wordr.length < min_length
623
- tries += 1
624
- length = max_length - wordr.length
625
- if tries > 1000
626
- wordr += 'A'*length
627
- break
628
- end
629
- if symbol_type == 'w' or symbol_type == "p"
630
- length = length -1 if wordr_array.size>0
631
- res = (words_short.select { |word| word.length <= length && word.length!=length-1 && word.length!=length-2 && word.length!=length-3 }).sample.to_s
632
- unless res.to_s==''
633
- wordr_array<<res
634
- wordr = wordr_array.join(@word_separator)
635
- end
636
- else
637
- wordr += (words_short.select { |word| word.length <= length && word.length!=length-1 && word.length!=length-2 && word.length!=length-3}).sample.to_s
638
- end
639
- if (tries % 100) == 0
640
- words_short = words.sample(2000)
641
- end
642
- end
643
- good_result = true
644
- string = wordr
645
-
646
- elsif (symbol_type == '@' or symbol_type == '!@') and length > 0
647
- if min_length > 6 and length < 6
648
- length = 6
649
- end
650
- if deny_pattern and
651
- (expected_errors.include?(:required_data) or expected_errors.include?(:excluded_data) or
652
- expected_errors.include?(:string_set_not_allowed))
653
- expected_errors_left.push(:value)
654
- expected_errors.push(:value)
655
- expected_errors.uniq!
656
- expected_errors_left.uniq!
657
- end
658
-
659
- expected_errors_left_orig = expected_errors_left.dup
660
- tries = 0
661
- begin
662
- expected_errors_left = expected_errors_left_orig.dup
663
- tries += 1
664
- string = ''
665
- alpha_set = ALPHA_SET_LOWER + ALPHA_SET_CAPITAL
666
- string_set = alpha_set + NUMBER_SET + ['.'] + ['_'] + ['-']
667
- string_set_not_allowed = all_characters_set - string_set
668
-
669
- extension = '.'
670
- at_sign = '@'
671
-
672
- if expected_errors_left.include?(:value)
673
- if rand(2) == 1
674
- extension = (all_characters_set - ['.']).sample
675
- expected_errors_left.delete(:value)
676
- expected_errors_left.delete(:required_data)
677
- end
678
- if rand(2) == 1
679
- 1.upto(rand(7)) {|i| extension << alpha_set.sample.downcase
680
- }
681
- (rand(extension.size) + 1).times {
682
- extension[rand(extension.size)] = (string_set - alpha_set - ['.']).sample
683
- }
684
- expected_errors_left.delete(:value)
685
- else
686
- 1.upto(rand(3) + 2) {|i| extension << alpha_set.sample.downcase
687
- }
688
- end
689
- if rand(2) == 1
690
- at_sign = (string_set - ['@']).sample
691
- expected_errors_left.delete(:value)
692
- expected_errors_left.delete(:required_data)
693
- end
694
- else
695
- if length > 6
696
- 1.upto(rand(3) + 2) {|i| extension << alpha_set.sample.downcase
697
- }
698
- else
699
- 1.upto(2) {|i| extension << alpha_set.sample.downcase
700
- }
701
- end
702
- end
703
- length_e = length - extension.size - 1
704
- length1 = rand(length_e - 1) + 1
705
- length2 = length_e - length1
706
- 1.upto(length1) {|i| string << string_set.sample}
707
-
708
- string << at_sign
709
-
710
- domain = ''
711
- domain_set = alpha_set + NUMBER_SET + ['.'] + ['-']
712
- 1.upto(length2) {|i| domain << domain_set.sample.downcase
713
- }
714
-
715
- if expected_errors.include?(:value) and rand(2) == 1 and domain.size > 0
716
- (rand(domain.size) + 1).times {
717
- domain[rand(domain.size)] = (all_characters_set - domain_set).sample
718
- }
719
- expected_errors_left.delete(:value)
720
- end
721
- string << domain << extension
722
-
723
- if expected_errors_left.include?(:value) or expected_errors_left.include?(:string_set_not_allowed)
724
- (rand(string.size) + 1).times {
725
- string[rand(string.size)] = string_set_not_allowed.sample
726
- }
727
- expected_errors_left.delete(:value)
728
- expected_errors_left.delete(:string_set_not_allowed)
729
- end
730
-
731
- error_regular_expression = false
732
-
733
- if deny_pattern and expected_errors.include?(:length)
734
- good_result = true #it is already with wrong length
735
- else
736
- # I'm doing this because many times the regular expression checking hangs with these characters
737
- wrong = %w(.. __ -- ._ _. .- -. _- -_ @. @_ @- .@ _@ -@ @@)
738
- if !(Regexp.union(*wrong) === string) #don't include any or the wrong strings
739
- if string.index('@').to_i > 0 and
740
- string[0..(string.index('@') - 1)].scan(/([a-z0-9]+([\+\._\-][a-z0-9]|)*)/i).join == string[0..(string.index('@') - 1)] and
741
- string[(string.index('@') + 1)..-1].scan(/([0-9a-z]+([\.-][a-z0-9]|)*)/i).join == string[string[(string.index('@') + 1)..-1]]
742
- error_regular_expression = false
743
- else
744
- error_regular_expression = true
745
- end
746
- else
747
- error_regular_expression = true
748
- end
749
-
750
- if expected_errors.size == 0
751
- if error_regular_expression
752
- good_result = false
753
- else
754
- good_result = true
755
- end
756
- elsif expected_errors_left.size == 0 and
757
- (expected_errors - [:length, :min_length, :max_length]).size == 0
758
- good_result = true
759
- elsif expected_errors != [:length]
760
- if !error_regular_expression
761
- good_result = false
762
- elsif expected_errors.include?(:value)
763
- good_result = true
764
- end
765
- end
766
- end
767
-
768
- end until good_result or tries > 100
769
- unless good_result
770
- puts "Not possible to generate an email on StringPattern.generate: #{pattern.inspect}, expected_errors: #{expected_errors.inspect}"
771
- return ''
772
- end
773
- end
774
- if @dont_repeat
775
- if @cache_values[pattern.to_s].nil?
776
- @cache_values[pattern.to_s] = Array.new()
777
- @cache_values[pattern.to_s].push(string)
778
- good_result = true
779
- elsif @cache_values[pattern.to_s].include?(string)
780
- good_result = false
781
- else
782
- @cache_values[pattern.to_s].push(string)
783
- good_result = true
784
- end
785
- end
786
- if pattern.kind_of?(Symbol) and patt.unique
787
- if @cache_values[pattern.__id__].nil?
788
- @cache_values[pattern.__id__] = Array.new()
789
- @cache_values[pattern.__id__].push(string)
790
- good_result = true
791
- elsif @cache_values[pattern.__id__].include?(string)
792
- good_result = false
793
- else
794
- @cache_values[pattern.__id__].push(string)
795
- good_result = true
796
- end
797
- end
798
- end until good_result or tries > 10000
799
- unless good_result
800
- puts "Not possible to generate the string on StringPattern.generate: #{pattern.inspect}, expected_errors: #{expected_errors.inspect}"
801
- puts "Take in consideration if you are using StringPattern.dont_repeat=true that you don't try to generate more strings that are possible to be generated"
802
- return ''
803
- end
804
-
805
- return string
806
- end
807
-
808
-
809
- ##############################################
810
- # This method is defined to validate if the text_to_validate supplied follows the pattern
811
- # It works also with array of patterns but in that case will return only true or false
812
- # input:
813
- # text (String) (synonyms: text_to_validate, validate) -- The text to validate
814
- # pattern -- symbol with this info: "length:symbol_type" or "min_length-max_length:symbol_type"
815
- # min_length -- minimum length of the string
816
- # max_length (optional) -- maximum length of the string. If not provided the result will be with the min_length provided
817
- # symbol_type -- the type of the string we want.
818
- # expected_errors (Array of symbols) (optional) (synonyms: errors) -- :length, :min_length, :max_length, :value, :required_data, :excluded_data, :string_set_not_allowed
819
- # not_expected_errors (Array of symbols) (optional) (synonyms: not_errors, non_expected_errors) -- :length, :min_length, :max_length, :value, :required_data, :excluded_data, :string_set_not_allowed
820
- # example:
821
- # validate(text: "This text will be validated", pattern: :"10-20:Xn", expected_errors: [:value, :max_length])
822
- #
823
- # Output:
824
- # if expected_errors and not_expected_errors are not supplied: an array with all detected errors
825
- # if expected_errors or not_expected_errors supplied: true or false
826
- # if array of patterns supplied, it will return true or false
827
- ###############################################
828
- def StringPattern.validate(text: '', pattern: '', expected_errors: [], not_expected_errors: [], **synonyms)
829
- text_to_validate = text
830
- text_to_validate = synonyms[:text_to_validate] if synonyms.keys.include?(:text_to_validate)
831
- text_to_validate = synonyms[:validate] if synonyms.keys.include?(:validate)
832
- expected_errors = synonyms[:errors] if synonyms.keys.include?(:errors)
833
- not_expected_errors = synonyms[:not_errors] if synonyms.keys.include?(:not_errors)
834
- not_expected_errors = synonyms[:non_expected_errors] if synonyms.keys.include?(:non_expected_errors)
835
- #:length, :min_length, :max_length, :value, :required_data, :excluded_data, :string_set_not_allowed
836
- if (expected_errors.include?(:min_length) or expected_errors.include?(:max_length)) and !expected_errors.include?(:length)
837
- expected_errors.push(:length)
838
- end
839
- if (not_expected_errors.include?(:min_length) or not_expected_errors.include?(:max_length)) and !not_expected_errors.include?(:length)
840
- not_expected_errors.push(:length)
841
- end
842
- if pattern.kind_of?(Array) and pattern.size == 1
843
- pattern = pattern[0]
844
- elsif pattern.kind_of?(Array) and pattern.size > 1 then
845
- total_min_length = 0
846
- total_max_length = 0
847
- all_errors_collected = Array.new
848
- result = true
849
- num_patt = 0
850
- patterns = Array.new
851
- pattern.each {|pat|
852
- if (pat.kind_of?(String) and (!StringPattern.optimistic or
853
- (StringPattern.optimistic and pat.to_s.scan(/(\d+)-(\d+):(.+)/).size == 0 and pat.to_s.scan(/^!?(\d+):(.+)/).size == 0))) #fixed text
854
- symbol_type = ''
855
- min_length = max_length = pat.length
856
- elsif pat.kind_of?(Symbol) or (pat.kind_of?(String) and StringPattern.optimistic and
857
- (pat.to_s.scan(/(\d+)-(\d+):(.+)/).size > 0 or pat.to_s.scan(/^!?(\d+):(.+)/).size > 0))
858
- patt = StringPattern.analyze(pat)
859
- min_length = patt.min_length
860
- max_length = patt.max_length
861
- symbol_type = patt.symbol_type
862
- else
863
- puts "String pattern class not supported (#{pat.class} for #{pat})"
864
- end
865
-
866
- patterns.push({pattern: pat, min_length: min_length, max_length: max_length, symbol_type: symbol_type})
867
-
868
- total_min_length += min_length
869
- total_max_length += max_length
870
-
871
- if num_patt == (pattern.size - 1) # i am in the last one
872
- if text_to_validate.length < total_min_length
873
- all_errors_collected.push(:length)
874
- all_errors_collected.push(:min_length)
875
- end
876
-
877
- if text_to_validate.length > total_max_length
878
- all_errors_collected.push(:length)
879
- all_errors_collected.push(:max_length)
880
- end
881
-
882
- end
883
- num_patt += 1
884
-
885
-
886
- }
887
-
888
- num_patt = 0
889
- patterns.each {|patt|
890
-
891
- tmp_result = false
892
- (patt[:min_length]..patt[:max_length]).each {|n|
893
- res = StringPattern.validate(text: text_to_validate[0..n - 1], pattern: patt[:pattern], not_expected_errors: not_expected_errors)
894
- if res.kind_of?(Array)
895
- all_errors_collected += res
896
- end
897
-
898
- if res.kind_of?(TrueClass) or (res.kind_of?(Array) and res.size == 0) #valid
899
- #we pass in the next one the rest of the pattern array list: pattern: pattern[num_patt+1..pattern.size]
900
- res = StringPattern.validate(text: text_to_validate[n..text_to_validate.length], pattern: pattern[num_patt + 1..pattern.size], expected_errors: expected_errors, not_expected_errors: not_expected_errors)
901
-
902
- if res.kind_of?(Array)
903
- if ((all_errors_collected + res) - expected_errors).size > 0
904
- tmp_result = false
905
- else
906
- all_errors_collected += res
907
- tmp_result = true
908
- end
909
- elsif res.kind_of?(TrueClass) then
910
- tmp_result = true
911
- end
912
- return true if tmp_result
913
- end
914
- }
915
-
916
- unless tmp_result
917
- return false
918
- end
919
- num_patt += 1
920
- }
921
- return result
922
- end
923
-
924
- if (pattern.kind_of?(String) and (!StringPattern.optimistic or
925
- (StringPattern.optimistic and pattern.to_s.scan(/(\d+)-(\d+):(.+)/).size == 0 and pattern.to_s.scan(/^!?(\d+):(.+)/).size == 0))) #fixed text
926
- symbol_type = ''
927
- min_length = max_length = pattern.length
928
- else #symbol
929
- patt = StringPattern.analyze(pattern)
930
- min_length = patt.min_length
931
- max_length = patt.max_length
932
- symbol_type = patt.symbol_type
933
-
934
- required_data = patt.required_data
935
- excluded_data = patt.excluded_data
936
- string_set = patt.string_set
937
- all_characters_set = patt.all_characters_set
938
-
939
- required_chars = Array.new
940
- required_data.each {|rd|
941
- required_chars << rd if rd.size == 1
942
- }
943
- if (required_chars.flatten & excluded_data.flatten).size > 0
944
- puts "pattern argument not valid on StringPattern.validate, a character cannot be required and excluded at the same time: #{pattern.inspect}, expected_errors: #{expected_errors.inspect}"
945
- return ''
946
- end
947
-
948
- end
949
-
950
- if text_to_validate.nil?
951
- return false
952
- end
953
- detected_errors = Array.new
954
-
955
- if text_to_validate.length < min_length
956
- detected_errors.push(:min_length)
957
- detected_errors.push(:length)
958
- end
959
- if text_to_validate.length > max_length
960
- detected_errors.push(:max_length)
961
- detected_errors.push(:length)
962
- end
963
-
964
- if symbol_type == '' #fixed text
965
- if pattern.to_s != text.to_s #not equal
966
- detected_errors.push(:value)
967
- detected_errors.push(:required_data)
968
- end
969
- else # pattern supplied
970
- if symbol_type != '@'
971
- if required_data.size > 0
972
- required_data.each {|rd|
973
- if (text_to_validate.chars & rd).size == 0
974
- detected_errors.push(:value)
975
- detected_errors.push(:required_data)
976
- break
977
- end
978
- }
979
- end
980
- if excluded_data.size > 0
981
- if (excluded_data & text_to_validate.chars).size > 0
982
- detected_errors.push(:value)
983
- detected_errors.push(:excluded_data)
984
- end
985
- end
986
- string_set_not_allowed = all_characters_set - string_set
987
- text_to_validate.chars.each {|st|
988
- if string_set_not_allowed.include?(st)
989
- detected_errors.push(:value)
990
- detected_errors.push(:string_set_not_allowed)
991
- break
992
- end
993
- }
994
- else #symbol_type=="@"
995
- string = text_to_validate
996
- wrong = %w(.. __ -- ._ _. .- -. _- -_ @. @_ @- .@ _@ -@ @@)
997
- if !(Regexp.union(*wrong) === string) #don't include any or the wrong strings
998
- if string.index('@').to_i > 0 and
999
- string[0..(string.index('@') - 1)].scan(/([a-z0-9]+([\+\._\-][a-z0-9]|)*)/i).join == string[0..(string.index('@') - 1)] and
1000
- string[(string.index('@') + 1)..-1].scan(/([0-9a-z]+([\.-][a-z0-9]|)*)/i).join == string[string[(string.index('@') + 1)..-1]]
1001
- error_regular_expression = false
1002
- else
1003
- error_regular_expression = true
1004
- end
1005
- else
1006
- error_regular_expression = true
1007
- end
1008
-
1009
- if error_regular_expression
1010
- detected_errors.push(:value)
1011
- end
1012
-
1013
- end
1014
- end
1015
-
1016
- if expected_errors.size == 0 and not_expected_errors.size == 0
1017
- return detected_errors
1018
- else
1019
- if expected_errors & detected_errors == expected_errors
1020
- if (not_expected_errors & detected_errors).size > 0
1021
- return false
1022
- else
1023
- return true
1024
- end
1025
- else
1026
- return false
1027
- end
1028
- end
1029
- end
1030
-
1031
59
  end
1032
-
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: string_pattern
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.1.4
4
+ version: 2.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mario Ruiz
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-04-12 00:00:00.000000000 Z
11
+ date: 2019-08-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: regexp_parser