string_pattern 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: da42289c954a52372acd4df016416a501476ae07a272c8f5b06ef7966165183c
4
+ data.tar.gz: b491b377808a1f0211e3bdfb9812b54f1d0b223f85fa5af1a61f2dd0c510fe71
5
+ SHA512:
6
+ metadata.gz: 1609036dca1456ff1f3addfe8126c438de9aa70bcd333251531d97f8c05efd71cc2a5d64ed556ae890d62fa53c1037c8c8b196f2864006669e40f7c121472bf2
7
+ data.tar.gz: dd9463dafbed43c843b0a4397ea1e0feff7c10d5820640f8247b02e3cccf31de6ecdabcf979f3c83c9190a0879d63549f3eceeeff7d08c43389b3ce166b42b05
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2017 Mario Ruiz
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,298 @@
1
+ # StringPattern
2
+
3
+ [![Gem Version](https://badge.fury.io/rb/string_pattern.svg)](https://rubygems.org/gems/string_pattern)
4
+
5
+ With this gem you can easily generate strings supplying a very simple pattern.
6
+ Also you can validate if a text fulfill an specific pattern or even generate a string following a pattern and returning wrong length, value... for testing your applications.
7
+
8
+ ## Installation
9
+
10
+ Add this line to your application's Gemfile:
11
+
12
+ ```ruby
13
+ gem 'string_pattern'
14
+ ```
15
+
16
+ And then execute:
17
+
18
+ $ bundle
19
+
20
+ Or install it yourself as:
21
+
22
+ $ gem install string_pattern
23
+
24
+ ## Usage
25
+
26
+ ### What is a string pattern?
27
+
28
+ A pattern is a string where we supply these elements "a-b:c" where a is min_length, b is max_length (optional) and c is a set of symbol_type
29
+
30
+ min_length: minimum length of the string
31
+
32
+ max_length (optional): maximum length of the string. If not provided, the result will be with the min_length provided
33
+
34
+ symbol_type: The type of the string we want.
35
+ x: from a to z (lowercase)
36
+ X: A to Z (capital letters)
37
+ L: A to Z and a to z
38
+ T: National characters defined on StringPattern.national_chars
39
+ n or N: for numbers. 0 to 9
40
+ $: special characters, $%&#... (includes blank space)
41
+ _: blank space
42
+ *: all characters
43
+ 0: empty string will be accepted. It needs to be at the beginning of the symbol_type string
44
+ @: It will generate a valid email following the official algorithm. It cannot be used with other symbol_type
45
+
46
+ ### How to generate a string following a pattern
47
+
48
+ To generate a string following a pattern you can do it using directly the StringPattern class or the generate method in the class, be aware you can always use also the alias method: gen
49
+
50
+ ```ruby
51
+ require 'string_pattern'
52
+
53
+ #StringPattern class
54
+ p StringPattern.generate "10:N"
55
+ #>3448910834
56
+ p StringPattern.gen "5:X"
57
+ #>JDDDK
58
+
59
+ #String class
60
+ p "4:Nx".gen
61
+ #>xaa3
62
+
63
+ #Symbol class
64
+ p :"10:T".generate
65
+ #>AccBdjklñD
66
+
67
+ #Array class
68
+ p [:"3:N", "fixed", :"3:N"].gen
69
+ #>334fixed920
70
+ p "(,3:N,) ,3:N,-,2:N,-,2:N".split(',').generate
71
+ #>(937) 980-65-05
72
+
73
+ #Kernel
74
+ p gen "3:N"
75
+ #>443
76
+ ```
77
+
78
+ #### Custom characters
79
+
80
+ Also it's possible to provided the characters we want. To do that we'll use the symbol_type [characters]
81
+
82
+ If we want to add the character ] we have to write ]]
83
+
84
+ Examples
85
+
86
+ ```ruby
87
+ # four chars from the ones provided: asDF9
88
+ p "4:[asDF9]".gen #> aaaa, asFF, 9sFD
89
+
90
+ # from 2 to 20 chars, capital and lower chars (Xx) and also valid the characters $#6
91
+ p "2-20:[$#6]Xx".gen #> aaaa, asFF, 66, B$DkKL#9aDD
92
+
93
+ # four chars from these: asDF]9
94
+ p "4:[asDF]]9]".gen #> aa]a, asFF, 9s]D
95
+ ```
96
+
97
+ #### Required characters or symbol types
98
+
99
+ We'll use the symbol / to specify which characters or symbols we want to be included on the resulting string as required values /symbols or characters/
100
+
101
+ If we need to add the character / we'll use //
102
+
103
+ Examples:
104
+
105
+ ```ruby
106
+ # four characters. optional: capitals and numbers, required: lower
107
+ "4:XN/x/".gen # aaaa, FF9b, j4em, asdf, ADFt
108
+
109
+ # from 6 to 15 chars. optional: numbers, capitals and the chars $ and Æ. required the chars: 23abCD
110
+ "6-15:[/23abCD/$Æ]NX".gen # bCa$D32, 32DJIOKLaCb, b23aD568C
111
+
112
+ # from 4 to 9 chars. optional: numbers and capitals. required: lowers and the characters $ and 5
113
+ "4-9:[/$5/]XN/x/".generate # aa5$, F5$F9b, j$4em5, a5sdf$, $ADFt5
114
+ ```
115
+
116
+ #### Excluded characters
117
+
118
+ If we want to exclude a few characters in the result, we'll use the symbol %characters%
119
+
120
+ If you need to exclude the character %, you should use %%
121
+
122
+ Examples:
123
+
124
+ ```ruby
125
+ # from 2 to 20 characters. optional: Numbers and characters A, B and C. excluded: the characters 8 and 3
126
+ "2-20:[%83%ABC]N".gen # B49, 22900, 9CAB, 22, 11CB6270C26C4572A50C
127
+
128
+ # 10 chars. optional: Letters (capital and lower). required: numbers. excluded: the characters 0 and WXYzZ
129
+ "10:L/n/[%0WXYzZ%]".gen # GoO2ukCt4l, Q1Je2remFL, qPg1T92T2H, 4445556781
130
+ ```
131
+
132
+ #### Not fulfilling a pattern
133
+
134
+ If we want our resulting string doesn't fulfill the pattern we supply, then we'll use the symbol ! at the beginning
135
+
136
+ Examples:
137
+
138
+ ```ruby
139
+ "!4:XN/x/".gen # a$aaa, FF9B, j4DDDem, as, 2345
140
+
141
+ "!10:N".gen # 123, 34899Add34, 3434234234234008, AAFj#kd2x
142
+ ```
143
+
144
+ ### Generate a string with specific expected errors
145
+
146
+ Usually for testing purposes you need to generate strings that don't fulfill an specific pattern, then you can supply as a parameter expected_errors (alias: errors)
147
+
148
+ The possible values you can specify is one or more of these ones: :length, :min_length, :max_length, :value, :required_data, :excluded_data, :string_set_not_allowed
149
+
150
+ :length: wrong length, minimum or maximum
151
+ :min_length: wrong minimum length
152
+ :max_length: wrong maximum length
153
+ :value: wrong resultant value
154
+ :required_data: the output string won't include all necessary required data. It works only if required data supplied on the pattern.
155
+ :excluded_data: the resultant string will include one or more characters that should be excluded. It works only if excluded data supplied on the pattern.
156
+ :string_set_not_allowed: it will include one or more characters that are not supposed to be on the string.
157
+
158
+ Examples:
159
+
160
+ ```ruby
161
+ "10-20:N".gen errors: [:min_length]
162
+ #> 627, 098262, 3408
163
+
164
+ "20:N".gen errors: [:length, :value]
165
+ #> |13, tS1b)r-1)<RT65202eTo6bV0g~, 021400323<2ahL0NP86a698063*56076
166
+
167
+ "10:L/n/".gen errors: [:value]
168
+ #> 1hwIw;v{KQ, mpk*l]!7:!, wocipgZt8@
169
+ ```
170
+
171
+ ### Validate if a string is following a pattern
172
+
173
+ If you need to validate if a specific text is fulfilling the pattern you can use the validate method.
174
+
175
+ If a string pattern supplied and no other parameters supplied the output will be an array with the errors detected.
176
+
177
+
178
+ Possible output values, empty array (validation without errors detected) or one or more of: :min_length, :max_length, :length, :value, :string_set_not_allowed, :required_data, :excluded_data
179
+
180
+ In case an array of patterns supplied it will return only true or false
181
+
182
+ Examples:
183
+
184
+ ```ruby
185
+ #StringPattern class
186
+ StringPattern.validate((text: "This text will be validated", pattern: :"10-20:Xn")
187
+ #> [:max_length, :length, :value, :string_set_not_allowed]
188
+
189
+ #String class
190
+ "10:N".validate "333444"
191
+ #> [:min_length, :length]
192
+
193
+ #Symbol class
194
+ :"10:N".validate("333444")
195
+ #> [:min_length, :length]
196
+
197
+ #Array class
198
+ ["5:L","3:xn","4-10:n"].validate "DjkljFFc343444390"
199
+ #> false
200
+ ```
201
+
202
+ If we want to validate a string with a pattern and we are expecting to get specific errors, you can supply the parameter expected_errors (alias: errors) or not_expected_errors (aliases: non_expected_errors, not_errors).
203
+
204
+ In this case the validate method will return true or false.
205
+
206
+ Examples:
207
+
208
+ ```ruby
209
+ "10:N".val "3445", errors: [:min_length]
210
+ #> true
211
+
212
+ "10:N/[09]/".validate "4434039440", errors: [:value]
213
+ #> false
214
+
215
+ "10-12:XN/x/".validate "FDDDDDAA343434", errors: [:max_length, :required_data]
216
+ #> true
217
+ ```
218
+
219
+ ### Configure
220
+
221
+ #### SP_ADD_TO_RUBY
222
+
223
+ This gem adds the methods generate (alias: gen) and validate (alias: val) to the Ruby classes: String, Array and Symbol.
224
+
225
+ Also adds the method generate (alias: gen) to Kernel. By default (true) it is always added.
226
+
227
+ In case you don't want to be added, just before requiring the library set:
228
+
229
+ ```ruby
230
+ SP_ADD_TO_RUBY = false
231
+ require 'string_pattern'
232
+ ```
233
+
234
+ In case it is set to true (default) then you will be able to use:
235
+
236
+ ```ruby
237
+ require 'string_pattern'
238
+
239
+ #String object
240
+ "20-30:@".gen
241
+ #>dkj34MljjJD-df@jfdluul.dfu
242
+
243
+ "10:L/N/[/-./%d%]".validate("12ds6f--.s")
244
+ #>[:value, :string_set_not_allowed]
245
+
246
+ "20-40:@".validate(my_email)
247
+
248
+ #Kernel
249
+ gen "10:N"
250
+ #>3433409877
251
+
252
+ #Array object
253
+ "(,3:N,) ,3:N,-,2:N,-,2:N".split(",").generate
254
+ #>(937) 980-65-05
255
+
256
+ %w{( 3:N ) 1:_ 3:N - 2:N - 2:N}.gen
257
+ #>(045) 448-63-09
258
+
259
+ ["1:L", "5-10:LN", "-", "3:N"].gen
260
+ #>zqWihV-746
261
+ ```
262
+
263
+ #### national_chars
264
+
265
+ To specify which national characters will be used when using the symbol type: T, you use StringPattern.national_chars, by default is the English alphabet
266
+
267
+ ```ruby
268
+ StringPattern.national_chars = (('a'..'z').to_a + ('A'..'Z').to_a).join + "áéíóúÁÉÍÓÚüÜñÑ"
269
+ "10-20:Tn".gen #>AAñ34Ef99éNOP
270
+ ```
271
+
272
+ #### optimistic
273
+
274
+ If true it will check on the strings of the array positions supplied if they have the pattern format and assume in that case that is a pattern. If not it will assume the patterns on the array will be supplied as symbols. By default is set to true.
275
+
276
+ ```ruby
277
+ StringPattern.optimistic = false
278
+ ["5:X","fixedtext", "3:N"].generate
279
+ #>5:Xfixedtext3:N
280
+ [:"5:X","fixedtext", :"3:N"].generate
281
+ #>AUJKJfixedtext454
282
+
283
+ StringPattern.optimistic = true
284
+ ["5:X","fixedtext", "3:N"].generate
285
+ #>KKDMEfixedtext344
286
+ [:"5:X","fixedtext", :"3:N"].generate
287
+ #>SAAERfixedtext988
288
+ ```
289
+
290
+ ## Contributing
291
+
292
+ Bug reports and pull requests are welcome on GitHub at https://github.com/marioruiz/string_pattern.
293
+
294
+
295
+ ## License
296
+
297
+ The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
298
+
@@ -0,0 +1,67 @@
1
+ class Array
2
+ # It will generate an string following the pattern specified
3
+ # The positions with string patterns need to be supplied like symbols:
4
+ # [:"10:N", "fixed", :"10-20:XN/x/"].generate #> "1024320001fixed4OZjNMTnuBibwwj"
5
+ def generate(expected_errors: [], **synonyms)
6
+ StringPattern.generate(self, expected_errors: expected_errors, **synonyms)
7
+ end
8
+
9
+ alias_method :gen, :generate
10
+
11
+ # it will validate an string following the pattern specified
12
+ def validate(string_to_validate, expected_errors: [], not_expected_errors: [], **synonyms)
13
+ StringPattern.validate(text: string_to_validate, pattern: self, expected_errors: expected_errors, not_expected_errors: not_expected_errors, **synonyms)
14
+ end
15
+
16
+ alias_method :val, :validate
17
+ end
18
+
19
+ class String
20
+ # it will generate an string following the pattern specified
21
+ def generate(expected_errors: [], **synonyms)
22
+ StringPattern.generate(self, expected_errors: expected_errors, **synonyms)
23
+ end
24
+
25
+ alias_method :gen, :generate
26
+
27
+ # it will validate an string following the pattern specified
28
+ def validate(string_to_validate, expected_errors: [], not_expected_errors: [], **synonyms)
29
+ StringPattern.validate(text: string_to_validate, pattern: self, expected_errors: expected_errors, not_expected_errors: not_expected_errors, **synonyms)
30
+ end
31
+
32
+ alias_method :val, :validate
33
+ end
34
+
35
+
36
+ class Symbol
37
+ # it will generate an string following the pattern specified
38
+ def generate(expected_errors: [], **synonyms)
39
+ StringPattern.generate(self, expected_errors: expected_errors, **synonyms)
40
+ end
41
+
42
+ alias_method :gen, :generate
43
+
44
+ # it will validate an string following the pattern specified
45
+ def validate(string_to_validate, expected_errors: [], not_expected_errors: [], **synonyms)
46
+ StringPattern.validate(text: string_to_validate, pattern: self.to_s, expected_errors: expected_errors, not_expected_errors: not_expected_errors, **synonyms)
47
+ end
48
+
49
+ alias_method :val, :validate
50
+ end
51
+
52
+
53
+ module Kernel
54
+ public
55
+ # if string or symbol supplied it will generate a string with the supplied pattern specified on the string
56
+ # if array supplied then it will generate a string with the supplied patterns. If a position contains a pattern supply it as symbol, for example: [:"10:N", "fixed", :"10-20:XN/x/"]
57
+ def generate(pattern, expected_errors: [], **synonyms)
58
+ if pattern.kind_of?(String) or pattern.kind_of?(Array) or pattern.kind_of?(Symbol)
59
+ StringPattern.generate(pattern, expected_errors: expected_errors, **synonyms)
60
+ else
61
+ puts " Kernel generate method: class not recognized:#{pattern.class}"
62
+ end
63
+ end
64
+
65
+ alias_method :gen, :generate
66
+ end
67
+
@@ -0,0 +1,859 @@
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
3
+
4
+ # 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
+ # If true it will add 'generate' and 'validate' methods to the classes: Array, String and Symbol. Also it will add 'generate' method to Kernel
6
+ # aliases: 'gen' for 'generate' and 'val' for 'validate'
7
+ # Examples of use:
8
+ # "(,3:N,) ,3:N,-,2:N,-,2:N".split(",").generate #>(937) 980-65-05
9
+ # %w{( 3:N ) 1:_ 3:N - 2:N - 2:N}.gen #>(045) 448-63-09
10
+ # ["1:L", "5-10:LN", "-", "3:N"].gen #>zqWihV-746
11
+ # gen("10:N") #>3433409877
12
+ # "20-30:@".gen #>dkj34MljjJD-df@jfdluul.dfu
13
+ # "10:L/N/[/-./%d%]".validate("12ds6f--.s") #>[:value, :string_set_not_allowed]
14
+ # "20-40:@".validate(my_email)
15
+ # national_chars: (Array, default: english alphabet)
16
+ # Set of characters that will be used when using T pattern
17
+ # optimistic: (TrueFalse, default: true)
18
+ # If true it will check on the strings of the array positions if they have the pattern format and assume in that case that is a pattern.
19
+ class StringPattern
20
+ class << self
21
+ attr_accessor :national_chars, :optimistic
22
+ end
23
+ @national_chars = (('a'..'z').to_a + ('A'..'Z').to_a).join
24
+ @optimistic = true
25
+ NUMBER_SET = ('0'..'9').to_a
26
+ SPECIAL_SET = [' ', '~', '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '-', '_', '+', '=', '{', '}', '[', ']', "'", ';', ':', '?', '>', '<', '`', '|', '/', '"']
27
+ ALPHA_SET_LOWER = ('a'..'z').to_a
28
+ ALPHA_SET_CAPITAL = ('A'..'Z').to_a
29
+
30
+
31
+ Pattern = Struct.new(:min_length, :max_length, :symbol_type, :required_data, :excluded_data, :data_provided,
32
+ :string_set, :all_characters_set)
33
+
34
+ ###############################################
35
+ # Analyze the pattern supplied and returns an object of Pattern structure including:
36
+ # min_length, max_length, symbol_type, required_data, excluded_data, data_provided, string_set, all_characters_set
37
+ ###############################################
38
+ def StringPattern.analyze(pattern, silent:false)
39
+ min_length, max_length, symbol_type=pattern.to_s.scan(/(\d+)-(\d+):(.+)/)[0]
40
+ if min_length.nil?
41
+ min_length, symbol_type=pattern.to_s.scan(/^!?(\d+):(.+)/)[0]
42
+ max_length=min_length
43
+ if min_length.nil?
44
+ puts "pattern argument not valid on StringPattern.generate: #{pattern.inspect}" unless silent
45
+ return pattern.to_s
46
+ end
47
+ end
48
+ symbol_type='!'+symbol_type if pattern.to_s[0]=='!'
49
+ min_length=min_length.to_i
50
+ max_length=max_length.to_i
51
+
52
+ required_data=Array.new
53
+ excluded_data=Array.new
54
+ required=false
55
+ excluded=false
56
+ data_provided=Array.new
57
+ a=symbol_type
58
+ begin_provided=a.index('[')
59
+ excluded_end_tag=false
60
+ if begin_provided!=nil
61
+ c=begin_provided+1
62
+ until c==a.size or (a[c..c]==']' and a[c..c+1]!=']]')
63
+ if a[c..c+1]==']]'
64
+ data_provided.push(']')
65
+ c=c+2
66
+ elsif a[c..c+1]=='%%' and !excluded then
67
+ data_provided.push('%')
68
+ c=c+2
69
+ else
70
+ if a[c..c]=='/' and !excluded
71
+ if a[c..c+1]=='//'
72
+ data_provided.push(a[c..c])
73
+ if required
74
+ required_data.push([a[c..c]])
75
+ end
76
+ c=c+1
77
+ else
78
+ if !required
79
+ required=true
80
+ else
81
+ required=false
82
+ end
83
+ end
84
+ else
85
+ if required
86
+ required_data.push([a[c..c]])
87
+ else
88
+ if a[c..c]=='%'
89
+ if a[c..c+1]=='%%' and excluded
90
+ excluded_data.push([a[c..c]])
91
+ c=c+1
92
+ else
93
+ if !excluded
94
+ excluded=true
95
+ else
96
+ excluded=false
97
+ excluded_end_tag=true
98
+ end
99
+ end
100
+ else
101
+ if excluded
102
+ excluded_data.push([a[c..c]])
103
+ end
104
+ end
105
+
106
+ end
107
+ if excluded==false and excluded_end_tag==false
108
+ data_provided.push(a[c..c])
109
+ end
110
+ excluded_end_tag=false
111
+ end
112
+ c=c+1
113
+ end
114
+ end
115
+ symbol_type=symbol_type[0..begin_provided].to_s + symbol_type[c..symbol_type.size].to_s
116
+ end
117
+
118
+ required=false
119
+ required_symbol=''
120
+ symbol_type.split(//).each {|stc|
121
+ if stc=='/'
122
+ if !required
123
+ required=true
124
+ else
125
+ required=false
126
+ end
127
+ else
128
+ if required
129
+ required_symbol+=stc
130
+ end
131
+ end
132
+ }
133
+ national_set=@national_chars.split(//)
134
+
135
+ if !symbol_type['x'].nil?
136
+ alpha_set=ALPHA_SET_LOWER
137
+ unless symbol_type['X'].nil?
138
+ alpha_set = alpha_set + ALPHA_SET_CAPITAL
139
+ end
140
+ else
141
+ if !symbol_type['X'].nil?
142
+ alpha_set=ALPHA_SET_CAPITAL
143
+ elsif !symbol_type['L'].nil? then
144
+ alpha_set = ALPHA_SET_LOWER + ALPHA_SET_CAPITAL
145
+ else
146
+ alpha_set = ALPHA_SET_LOWER + ALPHA_SET_CAPITAL
147
+ end
148
+ end
149
+ unless symbol_type['T'].nil?
150
+ alpha_set=alpha_set+national_set
151
+ end
152
+
153
+ unless required_symbol['x'].nil?
154
+ required_data.push ALPHA_SET_LOWER
155
+ end
156
+ unless required_symbol['X'].nil?
157
+ required_data.push ALPHA_SET_CAPITAL
158
+ end
159
+ unless required_symbol['L'].nil?
160
+ required_data.push(ALPHA_SET_CAPITAL+ALPHA_SET_LOWER)
161
+ end
162
+ unless required_symbol['T'].nil?
163
+ required_data.push national_set
164
+ end
165
+ required_symbol=required_symbol.downcase
166
+ string_set=Array.new
167
+ all_characters_set=ALPHA_SET_CAPITAL+ALPHA_SET_LOWER+NUMBER_SET+SPECIAL_SET+data_provided+national_set
168
+
169
+ unless symbol_type['_'].nil?
170
+ if symbol_type['$'].nil?
171
+ string_set.push(' ')
172
+ end
173
+ unless required_symbol['_'].nil?
174
+ required_data.push([' '])
175
+ end
176
+ end
177
+
178
+ symbol_type = symbol_type.downcase
179
+
180
+ if !symbol_type['x'].nil? or !symbol_type['l'].nil? or !symbol_type['t'].nil?
181
+ string_set = string_set + alpha_set
182
+ end
183
+ unless symbol_type['n'].nil?
184
+ string_set = string_set + NUMBER_SET
185
+ end
186
+ unless symbol_type['$'].nil?
187
+ string_set = string_set + SPECIAL_SET
188
+ end
189
+ unless symbol_type['*'].nil?
190
+ string_set = string_set+all_characters_set
191
+ end
192
+ if data_provided.size!=0
193
+ string_set = string_set + data_provided
194
+ end
195
+ unless required_symbol['n'].nil?
196
+ required_data.push NUMBER_SET
197
+ end
198
+ unless required_symbol['$'].nil?
199
+ required_data.push SPECIAL_SET
200
+ end
201
+ if excluded_data.size>0
202
+ string_set=string_set-excluded_data.flatten
203
+ end
204
+ string_set.uniq!
205
+ return Pattern.new(min_length, max_length, symbol_type, required_data, excluded_data, data_provided,
206
+ string_set, all_characters_set)
207
+ end
208
+
209
+ ###############################################
210
+ # Generate a random string based on the pattern supplied
211
+ # (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:
212
+ # "10-15:Ln/x/".generate #generate method on String class (alias: gen)
213
+ # ['(', :'3:N', ')', :'6-8:N'].generate #generate method on Array class (alias: gen)
214
+ # generate("10-15:Ln/x/") #generate Ruby Kernel method
215
+ # generate(['(', :'3:N', ')', :'6-8:N']) #generate Ruby Kernel method
216
+ # "(,3:N,) ,3:N,-,2:N,-,2:N".split(",").generate #>(937) #generate method on Array class (alias: gen)
217
+ # %w{( 3:N ) 1:_ 3:N - 2:N - 2:N}.gen #generate method on Array class, using alias gen method
218
+ # Input:
219
+ # pattern: array or string of different patterns. A pattern is a string with this info:
220
+ # "length:symbol_type" or "min_length-max_length:symbol_type"
221
+ # In case an array supplied, the positions using a string pattern should be supplied as symbols if StringPattern.optimistic==false
222
+ #
223
+ # These are the possible string patterns you will be able to supply:
224
+ # 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.
225
+ # min_length -- minimum length of the string
226
+ # max_length (optional) -- maximum length of the string. If not provided the result will be with the min_length provided
227
+ # symbol_type -- the type of the string we want.
228
+ # you can use a combination of any ot these:
229
+ # x for alpha in lowercase
230
+ # X for alpha in capital letters
231
+ # L for all kind of alpha in capital and lower letters
232
+ # T For the national characters defined on StringPattern.national_chars
233
+ # n for number
234
+ # $ for special characters (includes space)
235
+ # _ for space
236
+ # * all characters
237
+ # [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: %%
238
+ # %characters% the characters we don't want on the resulting string. %% to exclude the character %
239
+ # /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: //
240
+ # We can supply 0 to allow empty strings, this character need to be at the beginning
241
+ # If you want to include the character " use \"
242
+ # If you want to include the character \ use \\
243
+ # If you want to include the character [ use \[
244
+ # Another uses: @ for email
245
+ # Examples:
246
+ # [:"6:X", :"3-8:_N"]
247
+ # # 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"
248
+ # [:"6-15:L_N", "fixed text", :"3:N"]
249
+ # # 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"
250
+ # "10-20:LN[=#]"
251
+ # # it will return a string of 10-20 characters containing Letters and/or numbers and/or the characters = and #, for example: eiyweQFWeL#do4Vl
252
+ # "30:TN_[#=]/x/"
253
+ # # 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
254
+ # "10:N[%0%]"
255
+ # # 10 characters length containing numbers and excluding the character 0, for example: 3523497757
256
+ # "10:N[%0%/AB/]"
257
+ # # 10 characters length containing numbers and excluding the character 0 and necessary to contain the characters A B, for example: 3AA4AA57BB
258
+ # "!10:N[%0%/AB/]"
259
+ # # it will generate a string that doesn't fulfill the pattern supplied, examples:
260
+ # # a6oMQ4JK9g
261
+ # # /Y<N6Aa[ae
262
+ # # 3444439A34B32
263
+ # "10:N[%0%/AB/]", errors: [:length]
264
+ # # it will generate a string following the pattern and with the errors supplied, in this case, length, example: AB44
265
+ # Output:
266
+ # the generated string
267
+ ###############################################
268
+ def StringPattern.generate(pattern, expected_errors: [], **synonyms)
269
+ string=''
270
+
271
+ expected_errors=synonyms[:errors] if synonyms.keys.include?(:errors)
272
+
273
+ if expected_errors.kind_of?(Symbol)
274
+ expected_errors=[expected_errors]
275
+ end
276
+
277
+ if pattern.kind_of?(Array)
278
+ pattern.each {|pat|
279
+ if pat.kind_of?(Symbol)
280
+ if pat.to_s.scan(/^!?\d+-?\d*:.+/).size>0
281
+ string<<StringPattern.generate(pat.to_s, expected_errors: expected_errors)
282
+ else
283
+ string<<pat.to_s
284
+ end
285
+ elsif pat.kind_of?(String) then
286
+ if @optimistic and pat.to_s.scan(/^!?\d+-?\d*:.+/).size>0
287
+ string<<StringPattern.generate(pat.to_s, expected_errors: expected_errors)
288
+ else
289
+ string<<pat
290
+ end
291
+ else
292
+ puts "StringPattern.generate: it seems you supplied wrong array of patterns: #{pattern.inspect}, expected_errors: #{expected_errors.inspect}"
293
+ return ''
294
+ end
295
+ }
296
+ return string
297
+ elsif pattern.kind_of?(String) or pattern.kind_of?(Symbol)
298
+ patt=StringPattern.analyze(pattern)
299
+ min_length=patt.min_length
300
+ max_length=patt.max_length
301
+ symbol_type=patt.symbol_type
302
+
303
+ required_data=patt.required_data
304
+ excluded_data=patt.excluded_data
305
+ string_set=patt.string_set
306
+ all_characters_set=patt.all_characters_set
307
+
308
+ required_chars=Array.new
309
+ required_data.each {|rd|
310
+ required_chars<<rd if rd.size==1
311
+ }
312
+ if (required_chars.flatten & excluded_data.flatten).size>0
313
+ 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}"
314
+ return ''
315
+ end
316
+
317
+ string_set_not_allowed=all_characters_set-string_set
318
+
319
+ else
320
+ puts "pattern argument not valid on StringPattern.generate: #{pattern.inspect}, expected_errors: #{expected_errors.inspect}"
321
+ return pattern.to_s
322
+ end
323
+
324
+ allow_empty=false
325
+ deny_pattern=false
326
+ if symbol_type[0..0]=='!'
327
+ deny_pattern=true
328
+ possible_errors=[:length, :value, :required_data, :excluded_data, :string_set_not_allowed]
329
+ (rand(possible_errors.size)+1).times {
330
+ expected_errors<<possible_errors.sample
331
+ }
332
+ expected_errors.uniq!
333
+ if symbol_type[1..1]=='0'
334
+ allow_empty=true
335
+ end
336
+ elsif symbol_type[0..0]=='0' then
337
+ allow_empty=true
338
+ end
339
+ if expected_errors.include?(:min_length) or expected_errors.include?(:length) or
340
+ expected_errors.include?(:max_length)
341
+ allow_empty=!allow_empty
342
+ elsif expected_errors.include?(:value) or
343
+ expected_errors.include?(:excluded_data) or
344
+ expected_errors.include?(:required_data) or
345
+ expected_errors.include?(:string_set_not_allowed) and allow_empty
346
+ allow_empty=false
347
+ end
348
+
349
+ length=min_length
350
+ symbol_type_orig=symbol_type
351
+
352
+ expected_errors_left=expected_errors.dup
353
+
354
+ symbol_type=symbol_type_orig
355
+
356
+ unless deny_pattern
357
+ if required_data.size==0 and expected_errors_left.include?(:required_data)
358
+ 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}"
359
+ return ''
360
+ end
361
+
362
+ if excluded_data.size==0 and expected_errors_left.include?(:excluded_data)
363
+ 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}"
364
+ return ''
365
+ end
366
+
367
+ if string_set_not_allowed.size==0 and expected_errors_left.include?(:string_set_not_allowed)
368
+ 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}"
369
+ return ''
370
+ end
371
+ end
372
+
373
+ if expected_errors_left.include?(:min_length) or
374
+ expected_errors_left.include?(:max_length) or
375
+ expected_errors_left.include?(:length)
376
+ if expected_errors_left.include?(:min_length) or
377
+ (min_length>0 and expected_errors_left.include?(:length) and rand(2)==0)
378
+ if min_length>0
379
+ if allow_empty
380
+ length=rand(min_length).to_i
381
+ else
382
+ length=rand(min_length-1).to_i+1
383
+ end
384
+ if required_data.size>length and required_data.size<min_length
385
+ length=required_data.size
386
+ end
387
+ expected_errors_left.delete(:length)
388
+ expected_errors_left.delete(:min_length)
389
+ else
390
+ 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}"
391
+ return ''
392
+ end
393
+ elsif expected_errors_left.include?(:max_length) or expected_errors_left.include?(:length)
394
+ length=max_length+1+rand(max_length).to_i
395
+ expected_errors_left.delete(:length)
396
+ expected_errors_left.delete(:max_length)
397
+ end
398
+ else
399
+ if allow_empty and rand(7)==1
400
+ length=0
401
+ else
402
+ if max_length==min_length
403
+ length=min_length
404
+ else
405
+ length=min_length + rand(max_length - min_length + 1)
406
+ end
407
+ end
408
+ end
409
+
410
+ if deny_pattern
411
+ if required_data.size==0 and expected_errors_left.include?(:required_data)
412
+ expected_errors_left.delete(:required_data)
413
+ end
414
+
415
+ if excluded_data.size==0 and expected_errors_left.include?(:excluded_data)
416
+ expected_errors_left.delete(:excluded_data)
417
+ end
418
+
419
+ if string_set_not_allowed.size==0 and expected_errors_left.include?(:string_set_not_allowed)
420
+ expected_errors_left.delete(:string_set_not_allowed)
421
+ end
422
+
423
+ if symbol_type=='!@' and expected_errors_left.size==0 and !expected_errors.include?(:length) and
424
+ (expected_errors.include?(:required_data) or expected_errors.include?(:excluded_data))
425
+ expected_errors_left.push(:value)
426
+ end
427
+
428
+ end
429
+
430
+
431
+ string = ''
432
+ if symbol_type!='@' and symbol_type!='!@' and length!=0 and string_set.size!=0
433
+ if string_set.size!=0
434
+ 1.upto(length) {|i| string << string_set.sample.to_s
435
+ }
436
+ end
437
+ if required_data.size>0
438
+ positions_to_set=(0..(string.size-1)).to_a
439
+ required_data.each {|rd|
440
+ if (string.split(//) & rd).size>0
441
+ rd_to_set=(string.split(//) & rd).sample
442
+ else
443
+ rd_to_set=rd.sample
444
+ end
445
+ if ((0 ... string.length).find_all {|i| string[i, 1] == rd_to_set}).size==0
446
+ if positions_to_set.size==0
447
+ puts "pattern not valid on StringPattern.generate, not possible to generate a valid string: #{pattern.inspect}, expected_errors: #{expected_errors.inspect}"
448
+ return ''
449
+ else
450
+ k=positions_to_set.sample
451
+ string[k]=rd_to_set
452
+ positions_to_set.delete(k)
453
+ end
454
+ else
455
+ k=((0 ... string.length).find_all {|i| string[i, 1] == rd_to_set}).sample
456
+ positions_to_set.delete(k)
457
+ end
458
+ }
459
+ end
460
+ excluded_data.each {|ed|
461
+ if (string.split(//) & ed).size>0
462
+ (string.split(//) & ed).each {|s|
463
+ string.gsub!(s, string_set.sample)
464
+ }
465
+ end
466
+ }
467
+
468
+ if expected_errors_left.include?(:value)
469
+ if string_set_not_allowed.size==0
470
+ puts "Not possible to generate a non valid string on StringPattern.generate: #{pattern.inspect}, expected_errors: #{expected_errors.inspect}"
471
+ return ''
472
+ end
473
+ (rand(string.size)+1).times {
474
+ string[rand(string.size)]=(all_characters_set-string_set).sample
475
+ }
476
+ expected_errors_left.delete(:value)
477
+ end
478
+
479
+ if expected_errors_left.include?(:required_data) and required_data.size>0
480
+ (rand(required_data.size)+1).times {
481
+ chars_to_remove=required_data.sample
482
+ chars_to_remove.each {|char_to_remove|
483
+ string.gsub!(char_to_remove, (string_set-chars_to_remove).sample)
484
+ }
485
+ }
486
+ expected_errors_left.delete(:required_data)
487
+ end
488
+
489
+ if expected_errors_left.include?(:excluded_data) and excluded_data.size>0
490
+ (rand(string.size)+1).times {
491
+ string[rand(string.size)]=excluded_data.sample.sample
492
+ }
493
+ expected_errors_left.delete(:excluded_data)
494
+ end
495
+
496
+ if expected_errors_left.include?(:string_set_not_allowed) and string_set_not_allowed.size>0
497
+ (rand(string.size)+1).times {
498
+ string[rand(string.size)]=string_set_not_allowed.sample
499
+ }
500
+ expected_errors_left.delete(:string_set_not_allowed)
501
+ end
502
+
503
+ elsif (symbol_type=='@' or symbol_type=='!@') and length>0
504
+ if min_length>6 and length<6
505
+ length=6
506
+ end
507
+ if deny_pattern and
508
+ (expected_errors.include?(:required_data) or expected_errors.include?(:excluded_data) or
509
+ expected_errors.include?(:string_set_not_allowed))
510
+ expected_errors_left.push(:value)
511
+ expected_errors.push(:value)
512
+ expected_errors.uniq!
513
+ expected_errors_left.uniq!
514
+ end
515
+
516
+ expected_errors_left_orig=expected_errors_left.dup
517
+ tries=0
518
+ begin
519
+ expected_errors_left=expected_errors_left_orig.dup
520
+ tries+=1
521
+ string=''
522
+ alpha_set=ALPHA_SET_LOWER + ALPHA_SET_CAPITAL
523
+ string_set=alpha_set + NUMBER_SET + ['.'] + ['_'] + ['-']
524
+ string_set_not_allowed=all_characters_set-string_set
525
+
526
+ extension='.'
527
+ at_sign='@'
528
+
529
+ if expected_errors_left.include?(:value)
530
+ if rand(2)==1
531
+ extension=(all_characters_set-['.']).sample
532
+ expected_errors_left.delete(:value)
533
+ expected_errors_left.delete(:required_data)
534
+ end
535
+ if rand(2)==1
536
+ 1.upto(rand(7)) {|i| extension << alpha_set.sample.downcase
537
+ }
538
+ (rand(extension.size)+1).times {
539
+ extension[rand(extension.size)]=(string_set-alpha_set-['.']).sample
540
+ }
541
+ expected_errors_left.delete(:value)
542
+ else
543
+ 1.upto(rand(3)+2) {|i| extension << alpha_set.sample.downcase
544
+ }
545
+ end
546
+ if rand(2)==1
547
+ at_sign=(string_set-['@']).sample
548
+ expected_errors_left.delete(:value)
549
+ expected_errors_left.delete(:required_data)
550
+ end
551
+ else
552
+ if length>6
553
+ 1.upto(rand(3)+2) {|i| extension << alpha_set.sample.downcase
554
+ }
555
+ else
556
+ 1.upto(2) {|i| extension << alpha_set.sample.downcase
557
+ }
558
+ end
559
+ end
560
+ length_e=length-extension.size - 1
561
+ length1=rand(length_e-1) + 1
562
+ length2=length_e-length1
563
+ 1.upto(length1) {|i| string << string_set.sample}
564
+
565
+ string << at_sign
566
+
567
+ domain=''
568
+ domain_set=alpha_set + NUMBER_SET + ['.'] + ['-']
569
+ 1.upto(length2) {|i| domain << domain_set.sample.downcase
570
+ }
571
+
572
+ if expected_errors.include?(:value) and rand(2)==1 and domain.size>0
573
+ (rand(domain.size)+1).times {
574
+ domain[rand(domain.size)]=(all_characters_set-domain_set).sample
575
+ }
576
+ expected_errors_left.delete(:value)
577
+ end
578
+ string << domain << extension
579
+
580
+ if expected_errors_left.include?(:value) or expected_errors_left.include?(:string_set_not_allowed)
581
+ (rand(string.size)+1).times {
582
+ string[rand(string.size)]=string_set_not_allowed.sample
583
+ }
584
+ expected_errors_left.delete(:value)
585
+ expected_errors_left.delete(:string_set_not_allowed)
586
+ end
587
+
588
+ error_regular_expression=false
589
+
590
+ if deny_pattern and expected_errors.include?(:length)
591
+ good_result=true #it is already with wrong length
592
+ else
593
+ # I'm doing this because many times the regular expression checking hangs with these characters
594
+ wrong=%w(.. __ -- ._ _. .- -. _- -_ @. @_ @- .@ _@ -@ @@)
595
+ if !(Regexp.union(*wrong) === string) #don't include any or the wrong strings
596
+ if string.index('@').to_i>0 and
597
+ string[0..(string.index('@')-1)].scan(/([a-z0-9]+([\+\._\-][a-z0-9]|)*)/i).join==string[0..(string.index('@')-1)] and
598
+ string[(string.index('@')+1)..-1].scan(/([0-9a-z]+([\.-][a-z0-9]|)*)/i).join==string[string[(string.index('@')+1)..-1]]
599
+ error_regular_expression=false
600
+ else
601
+ error_regular_expression=true
602
+ end
603
+ else
604
+ error_regular_expression=true
605
+ end
606
+
607
+ if expected_errors.size==0
608
+ if error_regular_expression
609
+ good_result=false
610
+ else
611
+ good_result=true
612
+ end
613
+ elsif expected_errors_left.size==0 and
614
+ (expected_errors-[:length, :min_length, :max_length]).size==0
615
+ good_result=true
616
+ elsif expected_errors!=[:length]
617
+ if !error_regular_expression
618
+ good_result=false
619
+ elsif expected_errors.include?(:value)
620
+ good_result=true
621
+ end
622
+ end
623
+ end
624
+
625
+ end until good_result or tries>100
626
+ unless good_result
627
+ puts "Not possible to generate an email on StringPattern.generate: #{pattern.inspect}, expected_errors: #{expected_errors.inspect}"
628
+ return ''
629
+ end
630
+ end
631
+
632
+ return string
633
+ end
634
+
635
+
636
+ ##############################################
637
+ # This method is defined to validate if the text_to_validate supplied follows the pattern
638
+ # It works also with array of patterns but in that case will return only true or false
639
+ # input:
640
+ # text (String) (synonyms: text_to_validate, validate) -- The text to validate
641
+ # pattern -- symbol with this info: "length:symbol_type" or "min_length-max_length:symbol_type"
642
+ # min_length -- minimum length of the string
643
+ # max_length (optional) -- maximum length of the string. If not provided the result will be with the min_length provided
644
+ # symbol_type -- the type of the string we want.
645
+ # expected_errors (Array of symbols) (optional) (synonyms: errors) -- :length, :min_length, :max_length, :value, :required_data, :excluded_data, :string_set_not_allowed
646
+ # 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
647
+ # example:
648
+ # validate(text: "This text will be validated", pattern: :"10-20:Xn", expected_errors: [:value, :max_length])
649
+ #
650
+ # Output:
651
+ # if expected_errors and not_expected_errors are not supplied: an array with all detected errors
652
+ # if expected_errors or not_expected_errors supplied: true or false
653
+ # if array of patterns supplied, it will return true or false
654
+ ###############################################
655
+ def StringPattern.validate(text: '', pattern: '', expected_errors: [], not_expected_errors: [], **synonyms)
656
+ text_to_validate=text
657
+ text_to_validate=synonyms[:text_to_validate] if synonyms.keys.include?(:text_to_validate)
658
+ text_to_validate=synonyms[:validate] if synonyms.keys.include?(:validate)
659
+ expected_errors=synonyms[:errors] if synonyms.keys.include?(:errors)
660
+ not_expected_errors=synonyms[:not_errors] if synonyms.keys.include?(:not_errors)
661
+ not_expected_errors=synonyms[:non_expected_errors] if synonyms.keys.include?(:non_expected_errors)
662
+ #:length, :min_length, :max_length, :value, :required_data, :excluded_data, :string_set_not_allowed
663
+ if (expected_errors.include?(:min_length) or expected_errors.include?(:max_length)) and !expected_errors.include?(:length)
664
+ expected_errors.push(:length)
665
+ end
666
+ if (not_expected_errors.include?(:min_length) or not_expected_errors.include?(:max_length)) and !not_expected_errors.include?(:length)
667
+ not_expected_errors.push(:length)
668
+ end
669
+ if pattern.kind_of?(Array) and pattern.size==1
670
+ pattern=pattern[0]
671
+ elsif pattern.kind_of?(Array) and pattern.size>1 then
672
+ total_min_length=0
673
+ total_max_length=0
674
+ all_errors_collected=Array.new
675
+ result=true
676
+ num_patt=0
677
+ patterns=Array.new
678
+ pattern.each {|pat|
679
+ if (pat.kind_of?(String) and (!StringPattern.optimistic or
680
+ (StringPattern.optimistic and pat.to_s.scan(/(\d+)-(\d+):(.+)/).size==0 and pat.to_s.scan(/^!?(\d+):(.+)/).size==0))) #fixed text
681
+ symbol_type=''
682
+ min_length=max_length=pat.length
683
+ elsif pat.kind_of?(Symbol) or (pat.kind_of?(String) and StringPattern.optimistic and
684
+ (pat.to_s.scan(/(\d+)-(\d+):(.+)/).size>0 or pat.to_s.scan(/^!?(\d+):(.+)/).size>0))
685
+ patt=StringPattern.analyze(pat)
686
+ min_length=patt.min_length
687
+ max_length=patt.max_length
688
+ symbol_type=patt.symbol_type
689
+ else
690
+ puts "String pattern class not supported (#{pat.class} for #{pat})"
691
+ end
692
+
693
+ patterns.push({pattern: pat, min_length: min_length, max_length: max_length, symbol_type: symbol_type})
694
+
695
+ total_min_length+=min_length
696
+ total_max_length+=max_length
697
+
698
+ if num_patt==(pattern.size-1) # i am in the last one
699
+ if text_to_validate.length<total_min_length
700
+ all_errors_collected.push(:length)
701
+ all_errors_collected.push(:min_length)
702
+ end
703
+
704
+ if text_to_validate.length>total_max_length
705
+ all_errors_collected.push(:length)
706
+ all_errors_collected.push(:max_length)
707
+ end
708
+
709
+ end
710
+ num_patt+=1
711
+
712
+
713
+ }
714
+
715
+ num_patt=0
716
+ patterns.each {|patt|
717
+
718
+ tmp_result=false
719
+ (patt[:min_length]..patt[:max_length]).each {|n|
720
+ res=StringPattern.validate(text: text_to_validate[0..n-1], pattern: patt[:pattern], not_expected_errors: not_expected_errors)
721
+ if res.kind_of?(Array)
722
+ all_errors_collected+=res
723
+ end
724
+
725
+ if res.kind_of?(TrueClass) or (res.kind_of?(Array) and res.size==0) #valid
726
+ #we pass in the next one the rest of the pattern array list: pattern: pattern[num_patt+1..pattern.size]
727
+ 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)
728
+
729
+ if res.kind_of?(Array)
730
+ if ((all_errors_collected + res)-expected_errors).size>0
731
+ tmp_result=false
732
+ else
733
+ all_errors_collected+=res
734
+ tmp_result=true
735
+ end
736
+ elsif res.kind_of?(TrueClass) then
737
+ tmp_result=true
738
+ end
739
+ return true if tmp_result
740
+ end
741
+ }
742
+
743
+ unless tmp_result
744
+ return false
745
+ end
746
+ num_patt+=1
747
+ }
748
+ return result
749
+ end
750
+
751
+ if (pattern.kind_of?(String) and (!StringPattern.optimistic or
752
+ (StringPattern.optimistic and pattern.to_s.scan(/(\d+)-(\d+):(.+)/).size==0 and pattern.to_s.scan(/^!?(\d+):(.+)/).size==0))) #fixed text
753
+ symbol_type=''
754
+ min_length=max_length=pattern.length
755
+ else #symbol
756
+ patt=StringPattern.analyze(pattern)
757
+ min_length=patt.min_length
758
+ max_length=patt.max_length
759
+ symbol_type=patt.symbol_type
760
+
761
+ required_data=patt.required_data
762
+ excluded_data=patt.excluded_data
763
+ string_set=patt.string_set
764
+ all_characters_set=patt.all_characters_set
765
+
766
+ required_chars=Array.new
767
+ required_data.each {|rd|
768
+ required_chars<<rd if rd.size==1
769
+ }
770
+ if (required_chars.flatten & excluded_data.flatten).size>0
771
+ 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}"
772
+ return ''
773
+ end
774
+
775
+ end
776
+
777
+ if text_to_validate.nil?
778
+ return false
779
+ end
780
+ detected_errors=Array.new
781
+
782
+ if text_to_validate.length<min_length
783
+ detected_errors.push(:min_length)
784
+ detected_errors.push(:length)
785
+ end
786
+ if text_to_validate.length>max_length
787
+ detected_errors.push(:max_length)
788
+ detected_errors.push(:length)
789
+ end
790
+
791
+ if symbol_type=='' #fixed text
792
+ if pattern.to_s!=text.to_s #not equal
793
+ detected_errors.push(:value)
794
+ detected_errors.push(:required_data)
795
+ end
796
+ else # pattern supplied
797
+ if symbol_type!='@'
798
+ if required_data.size>0
799
+ required_data.each {|rd|
800
+ if (text_to_validate.split(//) & rd).size==0
801
+ detected_errors.push(:value)
802
+ detected_errors.push(:required_data)
803
+ break
804
+ end
805
+ }
806
+ end
807
+ if excluded_data.size>0
808
+ if (excluded_data & text_to_validate.split(//)).size>0
809
+ detected_errors.push(:value)
810
+ detected_errors.push(:excluded_data)
811
+ end
812
+ end
813
+ string_set_not_allowed=all_characters_set-string_set
814
+ text_to_validate.split(//).each {|st|
815
+ if string_set_not_allowed.include?(st)
816
+ detected_errors.push(:value)
817
+ detected_errors.push(:string_set_not_allowed)
818
+ break
819
+ end
820
+ }
821
+ else #symbol_type=="@"
822
+ string=text_to_validate
823
+ wrong=%w(.. __ -- ._ _. .- -. _- -_ @. @_ @- .@ _@ -@ @@)
824
+ if !(Regexp.union(*wrong) === string) #don't include any or the wrong strings
825
+ if string.index('@').to_i>0 and
826
+ string[0..(string.index('@')-1)].scan(/([a-z0-9]+([\+\._\-][a-z0-9]|)*)/i).join==string[0..(string.index('@')-1)] and
827
+ string[(string.index('@')+1)..-1].scan(/([0-9a-z]+([\.-][a-z0-9]|)*)/i).join==string[string[(string.index('@')+1)..-1]]
828
+ error_regular_expression=false
829
+ else
830
+ error_regular_expression=true
831
+ end
832
+ else
833
+ error_regular_expression=true
834
+ end
835
+
836
+ if error_regular_expression
837
+ detected_errors.push(:value)
838
+ end
839
+
840
+ end
841
+ end
842
+
843
+ if expected_errors.size==0 and not_expected_errors.size==0
844
+ return detected_errors
845
+ else
846
+ if expected_errors & detected_errors == expected_errors
847
+ if (not_expected_errors & detected_errors).size > 0
848
+ return false
849
+ else
850
+ return true
851
+ end
852
+ else
853
+ return false
854
+ end
855
+ end
856
+ end
857
+
858
+ end
859
+
metadata ADDED
@@ -0,0 +1,52 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: string_pattern
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Mario Ruiz
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2018-05-21 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: You can easily generate strings supplying a very simple pattern. Also
14
+ you can validate if a text fulfill an specific pattern or even generate a string
15
+ following a pattern and returning wrong length, value... for testing your applications.
16
+ email: marioruizs@gmail.com
17
+ executables: []
18
+ extensions: []
19
+ extra_rdoc_files:
20
+ - LICENSE
21
+ - README.md
22
+ files:
23
+ - LICENSE
24
+ - README.md
25
+ - lib/string/pattern/add_to_ruby.rb
26
+ - lib/string_pattern.rb
27
+ homepage: https://github.com/MarioRuiz/string_pattern
28
+ licenses:
29
+ - MIT
30
+ metadata: {}
31
+ post_install_message:
32
+ rdoc_options: []
33
+ require_paths:
34
+ - lib
35
+ required_ruby_version: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - ">="
38
+ - !ruby/object:Gem::Version
39
+ version: '0'
40
+ required_rubygems_version: !ruby/object:Gem::Requirement
41
+ requirements:
42
+ - - ">="
43
+ - !ruby/object:Gem::Version
44
+ version: '0'
45
+ requirements: []
46
+ rubyforge_project:
47
+ rubygems_version: 2.7.6
48
+ signing_key:
49
+ specification_version: 4
50
+ summary: 'Generates easily random string following a simple pattern. ''10-20:Xn/x/''.generate
51
+ #>qBstvc6JN8ra'
52
+ test_files: []