tmtm-stringvalidator 0.4

Sign up to get free protection for your applications and to get access to all the features.
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
+