tmtm-stringvalidator 0.4

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.
Files changed (2) hide show
  1. data/lib/stringvalidator.rb +322 -0
  2. metadata +54 -0
@@ -0,0 +1,322 @@
1
+ # Copyright (C) 2007-2009 TOMITA Masahiro
2
+ # mailto:tommy@tmtm.org
3
+ #
4
+ # = StringValidator
5
+ # Author:: TOMITA Masahiro <tommy@tmtm.org>
6
+ # License:: Ruby's. see http://www.ruby-lang.org/en/LICENSE.txt
7
+ #
8
+ # * 文字列が規則に従うかどうかを検査する
9
+ # * 規則は Ruby のリテラルで記述する。
10
+ #
11
+ # == Download
12
+ # * http://github.com/tmtm/stringvalidator/downloads
13
+ #
14
+ # == Install
15
+ # $ make
16
+ # $ make test
17
+ # # make install
18
+ #
19
+ # == Usage
20
+ # StringValidator.validate(_rule_, _str_) は _str_ が _rule_ に適合していれば、_rule_ に適したオブジェクトを返す。
21
+ # 適合しなければ StringValidator::Error 例外が発生する。
22
+ #
23
+ # StringValidator.validate "abc", "abc" # => "abc"
24
+ # StringValidator.validate /hoge/, "ahoge" # => "ahoge"
25
+ # StringValidator.validate Integer, "123" # => 123
26
+ # StringValidator.validate 123, "123" # => 123
27
+ # StringValidator.validate 1..255, "128" # => 128
28
+ # StringValidator.validate 1.0..255, "10.9" # => 10.9
29
+ # str = "abc"
30
+ # StringValidator.validate ["abc", "def"], str # => str
31
+ # StringValidator.validate({:length=>3..10}, str) # => str
32
+ # StringValidator.validate({:minlength=>3, :rule=>/abc/}, str) # => str
33
+ # StringValidator.validate Proc.new{|a| a == "abc" && 999}, str # =>999
34
+ # StringValidator.validate Proc.new{|s| Date.parse s}, "2007-10-02" # => Date object
35
+ #
36
+ # StringValidator.valid?(_rule_, _str_) は _str_ が _rule_ に適合していれば true、そうでなければ false を返す。
37
+ #
38
+ # 複数ルールの定義
39
+ #
40
+ # rules = {
41
+ # :port => 1..65535,
42
+ # :domain => /\A[a-z0-9-]+(\.[a-z0-9-]+)+\z/i,
43
+ # }
44
+ # v = StringValidator.new rules
45
+ # v.valid? :port, "8080"
46
+ # v.valid? :domain, "tmtm.org"
47
+ #
48
+ # どのルールが適合したか
49
+ #
50
+ # rules = {
51
+ # :port => 1..65535,
52
+ # :domain => /\A[a-z0-9]+(\.[a-z0-9]+)+\z/i
53
+ # }
54
+ # v = StringValidator.new rules
55
+ # v.validated_rule "8080" # => :port
56
+ # v.validated_rule "tmtm.org" # => :domain
57
+ # v.validated_rule "xyz" # => nil
58
+
59
+ # == 文字列の正当性チェック
60
+ class StringValidator
61
+ # エラーの基底クラス
62
+ class Error < StandardError
63
+ # _value_:: 対象文字列
64
+ # _rule_:: ルールオブジェクト
65
+ def initialize(value=nil, rule=nil)
66
+ @rule = rule
67
+ @value = value
68
+ super self.class.errmsg
69
+ end
70
+ attr_reader :rule, :value
71
+
72
+ def self.errmsg()
73
+ @errmsg
74
+ end
75
+ end
76
+
77
+ # Integer に適合しない場合
78
+ class Error::NotInteger < Error
79
+ @errmsg = "not integer"
80
+ end
81
+ # Float に適合しない場合
82
+ class Error::NotFloat < Error
83
+ @errmsg = "not float"
84
+ end
85
+ # Range に適合しない場合
86
+ class Error::OutOfRange < Error
87
+ @errmsg = "out of range"
88
+ end
89
+ # Array, Proc, Class に適合しない場合
90
+ class Error::InvalidValue < Error
91
+ @errmsg = "invalid value"
92
+ end
93
+ # Regexp に適合しない場合
94
+ class Error::RegexpMismatch < Error
95
+ @errmsg = "regexp mismatch"
96
+ end
97
+ # Hash(:length, :charlength) に適合しない場合
98
+ class Error::InvalidLength < Error
99
+ @errmsg = "invalid length"
100
+ end
101
+ # Hash(:minlength, :mincharlength) に適合しない場合
102
+ class Error::TooShort < Error
103
+ @errmsg = "too short"
104
+ end
105
+ # Hash(:maxlength, :maxcharlength) に適合しない場合
106
+ class Error::TooLong < Error
107
+ @errmsg = "too long"
108
+ end
109
+
110
+ # _rule_:: ルールオブジェクト
111
+ # _str_:: 対象文字列
112
+ #
113
+ # _str_ が _rule_ に適合するか検査する。
114
+ # 適合しない場合、StringValidator::Error 例外が発生する。
115
+ #
116
+ # StringValidator#validate(_rule_, _str_) と同じ。
117
+ #
118
+ def self.validate(rule, str)
119
+ self.new(nil).validate(rule, str)
120
+ end
121
+
122
+ # _rule_:: ルールオブジェクト
123
+ # _str_:: 対象文字列
124
+ #
125
+ # validate(_rule_, _str_) が成功すれば true, そうでなければ false を返す。
126
+ #
127
+ def self.valid?(rule, str)
128
+ begin
129
+ self.validate(rule, str)
130
+ rescue Error
131
+ return false
132
+ end
133
+ return true
134
+ end
135
+
136
+ # _rule_:: Hash オブジェクト。{:key => rule_object, ...}
137
+ def initialize(rule)
138
+ @rule = rule
139
+ end
140
+
141
+ # _rule_:: ルールキー。initialize に与えた Hash のキー
142
+ # _str_:: 対象文字列
143
+ #
144
+ # _str_ が _rule_ に適合するか検査する。
145
+ # 適合しない場合、StringValidator::Error 例外が発生する。
146
+ #
147
+ # === _rule_ の形式
148
+ #
149
+ # ==== Integer (Integer そのもの。Integer オブジェクトではない)
150
+ # Integer(_str_) が成功した場合に _str_ を正当とみなす。
151
+ # Integer オブジェクトを返す。
152
+ # ==== Float (Float そのもの。Float オブジェクトではない)
153
+ # Float(_str_) が成功した場合に _str_ を正当とみなす。
154
+ # Float オブジェクトを返す。
155
+ # ==== Range オブジェクト
156
+ # _rule_ が _str_ を含んでいれば _str_ を正当とみなす。
157
+ # _rule_ に応じて、Integer, Float, String オブジェクトを返す。
158
+ # ==== Regexp オブジェクト
159
+ # _str_ が _rule_ に適合すれば _str_ を正当とみなす。
160
+ # _str_ を返す。
161
+ # ==== Proc オブジェクト
162
+ # _rule_.call(_str_) が例外を発生しなければ _str_ を正当とみなす。
163
+ # _rule_.call(_str_) の結果を返す。
164
+ # ==== Array オブジェクト
165
+ # _rule_ の要素をルールとして評価し、正当な要素が一つでもあれば正当とみなす。
166
+ # 最初に正当になったルールの結果を返す。
167
+ # ==== Hash オブジェクト
168
+ # 複数のルールが指定された場合は、すべてのルールを満たせば正当とみなす。
169
+ # 結果は、:rule(なければ :any, :all)の評価結果。:rule, :any, :all のいずれもなければ str が評価結果となる。
170
+ # [<tt>:any => _array_</tt>]
171
+ # Array と同じ。
172
+ # [<tt>:all => _array_</tt>]
173
+ # _array_ の要素をルールとして評価し、すべての要素が正当であれば正当とみなす。
174
+ # 評価結果は、最初の要素のルールの評価結果。
175
+ # [<tt>:rule => _obj_</tt>]
176
+ # _obj_ をルールとして評価する。
177
+ # [<tt>:length => _integer_ or _range_</tt>]
178
+ # _str_ の長さ(バイト数)が _integer_ に一致する場合、または _range_ 内であれば正当とみなす。
179
+ # [<tt>:maxlength => _integer_</tt>]
180
+ # _str_ の長さ(バイト数)が _integer_ 以下であれば正当とみなす。
181
+ # [<tt>:minlength => _integer_</tt>]
182
+ # _str_ の長さ(バイト数)が _integer_ 以上であれば正当とみなす。
183
+ # [<tt>:charlength => _integer_ or _range_</tt>]
184
+ # _str_ の長さ(文字数)が _integer_ に一致する場合、または _range_ 内であれば正当とみなす。文字数は $KCODE に依存する。
185
+ # [<tt>:maxcharlength => _integer_</tt>]
186
+ # _str_ の長さ(文字数)が _integer_ 以下であれば正当とみなす。文字数は $KCODE に依存する。
187
+ # [<tt>:mincharlength => _integer_</tt>]
188
+ # _str_ の長さ(文字数)が _integer_ 以上であれば正当とみなす。文字数は $KCODE に依存する。
189
+ # ==== Symbol オブジェクト
190
+ # new の引数として渡したハッシュの、キー _rule_ に対応する値をルールとして評価する。
191
+ # ==== Class オブジェクト
192
+ # _rule_.new(_str_) が成功すれば正当とみなす。
193
+ # _rule_.new(_str_) を返す。
194
+ # ==== other
195
+ # _str_ が _rule_.to_s と等しければ正当とみなす。
196
+ # _rule_ を返す。
197
+ #
198
+ def validate(rule, str)
199
+ if rule == Integer then
200
+ begin
201
+ return Integer(str)
202
+ rescue ArgumentError
203
+ raise Error::NotInteger.new(str, rule)
204
+ end
205
+ end
206
+ if rule == Float then
207
+ begin
208
+ return Float(str)
209
+ rescue ArgumentError
210
+ raise Error::NotFloat.new(str, rule)
211
+ end
212
+ end
213
+ case rule
214
+ when Range then
215
+ if rule.first.is_a? Integer and rule.last.is_a? Integer then
216
+ validate(Integer, str)
217
+ raise Error::OutOfRange.new(str, rule) unless rule.include?(str.to_i)
218
+ return str.to_i
219
+ elsif rule.first.is_a? Numeric then
220
+ validate(Float, str)
221
+ raise Error::OutOfRange.new(str, rule) unless rule.include?(str.to_f)
222
+ return str.to_f
223
+ end
224
+ raise Error::OutOfRange.new(str, rule) unless rule.include?(str)
225
+ return str
226
+ when Regexp then
227
+ raise Error::RegexpMismatch.new(str, rule) unless rule =~ str
228
+ return str
229
+ when Proc then
230
+ begin
231
+ return rule.call(str)
232
+ rescue
233
+ raise Error::InvalidValue.new(str, rule)
234
+ end
235
+ return ret if ret
236
+ when Array then
237
+ rule.each do |i|
238
+ begin
239
+ return self.validate(i, str)
240
+ rescue Error
241
+ nil
242
+ end
243
+ end
244
+ raise Error::InvalidValue.new(str, rule)
245
+ when Hash then
246
+ ret = {}
247
+ rule.each do |k,v|
248
+ case k
249
+ when :any
250
+ ret[k] = self.validate(v, str)
251
+ when :all
252
+ ret[k] = v.map{|i| self.validate(i, str)}.first
253
+ when :rule
254
+ ret[k] = self.validate(v, str)
255
+ when :length
256
+ begin
257
+ self.validate v, str.length.to_s
258
+ rescue Error
259
+ raise Error::InvalidLength.new(str, rule)
260
+ end
261
+ when :maxlength
262
+ raise Error::TooLong.new(str, rule) unless str.length <= v
263
+ when :minlength
264
+ raise Error::TooShort.new(str, rule) unless str.length >= v
265
+ when :charlength
266
+ begin
267
+ self.validate v, str.split(//).length.to_s
268
+ rescue Error
269
+ raise Error::InvalidLength.new(str, rule)
270
+ end
271
+ when :maxcharlength
272
+ raise Error::TooLong.new(str, rule) unless str.split(//).length <= v
273
+ when :mincharlength
274
+ raise Error::TooShort.new(str, rule) unless str.split(//).length >= v
275
+ else
276
+ raise ArgumentError, "Invalid key: #{k}"
277
+ end
278
+ end
279
+ return ret[:rule] || ret[:any] || ret[:all] || str
280
+ when Class then
281
+ begin
282
+ return rule.new(str)
283
+ rescue
284
+ raise Error::InvalidValue.new(str, rule)
285
+ end
286
+ when Symbol then
287
+ raise ArgumentError, "No such rule: #{rule}" unless @rule and @rule.key? rule
288
+ return self.class.validate(@rule[rule], str)
289
+ else
290
+ return rule if rule.to_s == str
291
+ end
292
+ raise Error::InvalidValue.new(str, rule)
293
+ end
294
+
295
+ # _rule_:: ルールキー。initialize に与えた Hash のキー
296
+ # _str_:: 対象文字列
297
+ #
298
+ # StringValidator#validate(_rule_, _str) が成功すれば true, そうでなければ false を返す。
299
+ #
300
+ def valid?(rule, str)
301
+ begin
302
+ validate(rule, str)
303
+ rescue Error
304
+ return false
305
+ end
306
+ return true
307
+ end
308
+
309
+ # _str_:: 対象文字列
310
+ #
311
+ # initialize に与えた Hash のキーのルールを順に評価し、最初に適合したキー値を返す。
312
+ # 適合したルールがない場合は nil を返す。
313
+ def validated_rule(str)
314
+ @rule.keys.sort{|a,b|a.to_s<=>b.to_s}.each do |k|
315
+ if valid?(@rule[k], str) then
316
+ return k
317
+ end
318
+ end
319
+ return nil
320
+ end
321
+
322
+ end
metadata ADDED
@@ -0,0 +1,54 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: tmtm-stringvalidator
3
+ version: !ruby/object:Gem::Version
4
+ version: "0.4"
5
+ platform: ruby
6
+ authors:
7
+ - Tomita Masahiro
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-09-22 00:00:00 -07:00
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ description: StringValidator is a Ruby library for validating string
17
+ email: tommy@tmtm.org
18
+ executables: []
19
+
20
+ extensions: []
21
+
22
+ extra_rdoc_files: []
23
+
24
+ files:
25
+ - lib/stringvalidator.rb
26
+ has_rdoc: true
27
+ homepage: http://github.com/tmtm/stringvalidator
28
+ licenses:
29
+ post_install_message:
30
+ rdoc_options:
31
+ - --charset=utf-8
32
+ require_paths:
33
+ - lib
34
+ required_ruby_version: !ruby/object:Gem::Requirement
35
+ requirements:
36
+ - - ">="
37
+ - !ruby/object:Gem::Version
38
+ version: "0"
39
+ version:
40
+ required_rubygems_version: !ruby/object:Gem::Requirement
41
+ requirements:
42
+ - - ">="
43
+ - !ruby/object:Gem::Version
44
+ version: "0"
45
+ version:
46
+ requirements: []
47
+
48
+ rubyforge_project: stringvalidator
49
+ rubygems_version: 1.3.5
50
+ signing_key:
51
+ specification_version: 2
52
+ summary: StringValidator is a Ruby library for validating string
53
+ test_files: []
54
+