string_pattern 2.1.4 → 2.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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