chars 0.2.0 → 0.2.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gemspec +0 -0
- data/.yardopts +1 -1
- data/ChangeLog.md +9 -0
- data/README.md +4 -0
- data/Rakefile +3 -2
- data/chars.gemspec +124 -7
- data/gemspec.yml +5 -3
- data/lib/chars/char_set.rb +157 -38
- data/lib/chars/chars.rb +24 -20
- data/lib/chars/extensions/integer.rb +17 -17
- data/lib/chars/version.rb +1 -1
- data/spec/char_set_spec.rb +63 -89
- data/spec/chars_spec.rb +14 -73
- data/spec/{integer_spec.rb → extensions/integer_spec.rb} +1 -2
- data/spec/{string_spec.rb → extensions/string_spec.rb} +1 -2
- data/spec/spec_helper.rb +1 -0
- metadata +18 -38
data/.gemspec
ADDED
File without changes
|
data/.yardopts
CHANGED
@@ -1 +1 @@
|
|
1
|
-
--markup markdown --title 'Chars Documentation' --protected --files ChangeLog.md,LICENSE.txt
|
1
|
+
--markup markdown --title 'Chars Documentation' --protected --quiet --files ChangeLog.md,LICENSE.txt
|
data/ChangeLog.md
CHANGED
@@ -1,3 +1,12 @@
|
|
1
|
+
### 0.2.1 / 2011-06-22
|
2
|
+
|
3
|
+
* Added {Chars::CharSet.[]}
|
4
|
+
* Added {Chars::CharSet#<<}.
|
5
|
+
* Added {Chars::CharSet#byte_to_char}.
|
6
|
+
* Added {Chars::CharSet#char_to_byte}.
|
7
|
+
* Added a cache of characters of the bytes within {Chars::CharSet}.
|
8
|
+
* Use `String#each_char` to distinguish Unicode from ASCII.
|
9
|
+
|
1
10
|
### 0.2.0 / 2010-10-27
|
2
11
|
|
3
12
|
* Make sure all enumerable methods in {Chars::CharSet} return an
|
data/README.md
CHANGED
data/Rakefile
CHANGED
@@ -2,7 +2,7 @@ require 'rubygems'
|
|
2
2
|
require 'rake'
|
3
3
|
|
4
4
|
begin
|
5
|
-
gem 'ore-tasks', '~> 0.
|
5
|
+
gem 'ore-tasks', '~> 0.4'
|
6
6
|
require 'ore/tasks'
|
7
7
|
|
8
8
|
Ore::Tasks.new
|
@@ -12,7 +12,7 @@ rescue LoadError => e
|
|
12
12
|
end
|
13
13
|
|
14
14
|
begin
|
15
|
-
gem 'rspec', '~> 2.
|
15
|
+
gem 'rspec', '~> 2.4'
|
16
16
|
require 'rspec/core/rake_task'
|
17
17
|
|
18
18
|
RSpec::Core::RakeTask.new
|
@@ -21,6 +21,7 @@ rescue LoadError => e
|
|
21
21
|
abort "Please run `gem install rspec` to install RSpec."
|
22
22
|
end
|
23
23
|
end
|
24
|
+
task :test => :spec
|
24
25
|
task :default => :spec
|
25
26
|
|
26
27
|
begin
|
data/chars.gemspec
CHANGED
@@ -1,10 +1,127 @@
|
|
1
|
-
#
|
1
|
+
# encoding: utf-8
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
3
|
+
require 'yaml'
|
4
|
+
|
5
|
+
Gem::Specification.new do |gemspec|
|
6
|
+
files = if File.directory?('.git')
|
7
|
+
`git ls-files`.split($/)
|
8
|
+
elsif File.directory?('.hg')
|
9
|
+
`hg manifest`.split($/)
|
10
|
+
elsif File.directory?('.svn')
|
11
|
+
`svn ls -R`.split($/).select { |path| File.file?(path) }
|
12
|
+
else
|
13
|
+
Dir['{**/}{.*,*}'].select { |path| File.file?(path) }
|
14
|
+
end
|
15
|
+
|
16
|
+
filter_files = lambda { |paths|
|
17
|
+
case paths
|
18
|
+
when Array
|
19
|
+
(files & paths)
|
20
|
+
when String
|
21
|
+
(files & Dir[paths])
|
22
|
+
end
|
23
|
+
}
|
24
|
+
|
25
|
+
version = {
|
26
|
+
:file => 'lib/chars/version.rb',
|
27
|
+
:constant => 'Chars::VERSION'
|
28
|
+
}
|
29
|
+
|
30
|
+
defaults = {
|
31
|
+
'name' => File.basename(File.dirname(__FILE__)),
|
32
|
+
'files' => files,
|
33
|
+
'executables' => filter_files['bin/*'].map { |path| File.basename(path) },
|
34
|
+
'test_files' => filter_files['{test/{**/}*_test.rb,spec/{**/}*_spec.rb}'],
|
35
|
+
'extra_doc_files' => filter_files['*.{txt,rdoc,md,markdown,tt,textile}'],
|
36
|
+
}
|
37
|
+
|
38
|
+
metadata = defaults.merge(YAML.load_file('gemspec.yml'))
|
39
|
+
|
40
|
+
gemspec.name = metadata.fetch('name',defaults[:name])
|
41
|
+
gemspec.version = if metadata['version']
|
42
|
+
metadata['version']
|
43
|
+
elsif File.file?(version[:file])
|
44
|
+
require File.join('.',version[:file])
|
45
|
+
eval(version[:constant])
|
46
|
+
end
|
47
|
+
|
48
|
+
gemspec.summary = metadata.fetch('summary',metadata['description'])
|
49
|
+
gemspec.description = metadata.fetch('description',metadata['summary'])
|
50
|
+
|
51
|
+
case metadata['license']
|
52
|
+
when Array
|
53
|
+
gemspec.licenses = metadata['license']
|
54
|
+
when String
|
55
|
+
gemspec.license = metadata['license']
|
56
|
+
end
|
57
|
+
|
58
|
+
case metadata['authors']
|
59
|
+
when Array
|
60
|
+
gemspec.authors = metadata['authors']
|
61
|
+
when String
|
62
|
+
gemspec.author = metadata['authors']
|
63
|
+
end
|
64
|
+
|
65
|
+
gemspec.email = metadata['email']
|
66
|
+
gemspec.homepage = metadata['homepage']
|
67
|
+
|
68
|
+
case metadata['require_paths']
|
69
|
+
when Array
|
70
|
+
gemspec.require_paths = metadata['require_paths']
|
71
|
+
when String
|
72
|
+
gemspec.require_path = metadata['require_paths']
|
73
|
+
end
|
74
|
+
|
75
|
+
gemspec.files = filter_files[metadata['files']]
|
76
|
+
|
77
|
+
gemspec.executables = metadata['executables']
|
78
|
+
gemspec.extensions = metadata['extensions']
|
79
|
+
|
80
|
+
if Gem::VERSION < '1.7.'
|
81
|
+
gemspec.default_executable = gemspec.executables.first
|
82
|
+
end
|
83
|
+
|
84
|
+
gemspec.test_files = filter_files[metadata['test_files']]
|
85
|
+
|
86
|
+
unless gemspec.files.include?('.document')
|
87
|
+
gemspec.extra_rdoc_files = metadata['extra_doc_files']
|
88
|
+
end
|
89
|
+
|
90
|
+
gemspec.post_install_message = metadata['post_install_message']
|
91
|
+
gemspec.requirements = metadata['requirements']
|
92
|
+
|
93
|
+
if gemspec.respond_to?(:required_ruby_version=)
|
94
|
+
gemspec.required_ruby_version = metadata['required_ruby_version']
|
95
|
+
end
|
96
|
+
|
97
|
+
if gemspec.respond_to?(:required_rubygems_version=)
|
98
|
+
gemspec.required_rubygems_version = metadata['required_ruby_version']
|
99
|
+
end
|
100
|
+
|
101
|
+
parse_versions = lambda { |versions|
|
102
|
+
case versions
|
103
|
+
when Array
|
104
|
+
versions.map { |v| v.to_s }
|
105
|
+
when String
|
106
|
+
versions.split(/,\s*/)
|
107
|
+
end
|
108
|
+
}
|
109
|
+
|
110
|
+
if metadata['dependencies']
|
111
|
+
metadata['dependencies'].each do |name,versions|
|
112
|
+
gemspec.add_dependency(name,parse_versions[versions])
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
if metadata['runtime_dependencies']
|
117
|
+
metadata['runtime_dependencies'].each do |name,versions|
|
118
|
+
gemspec.add_runtime_dependency(name,parse_versions[versions])
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
if metadata['development_dependencies']
|
123
|
+
metadata['development_dependencies'].each do |name,versions|
|
124
|
+
gemspec.add_development_dependency(name,parse_versions[versions])
|
125
|
+
end
|
6
126
|
end
|
7
|
-
rescue NameError
|
8
|
-
STDERR.puts "The 'chars.gemspec' file requires Ore."
|
9
|
-
STDERR.puts "Run `gem install ore` to install Ore."
|
10
127
|
end
|
data/gemspec.yml
CHANGED
@@ -10,7 +10,9 @@ authors: Postmodern
|
|
10
10
|
email: postmodern.mod3@gmail.com
|
11
11
|
has_yard: true
|
12
12
|
|
13
|
+
required_ruby_version: ">= 1.8.7"
|
14
|
+
|
13
15
|
development_dependencies:
|
14
|
-
ore: ~> 0.
|
15
|
-
|
16
|
-
|
16
|
+
ore-tasks: ~> 0.4
|
17
|
+
rspec: ~> 2.4
|
18
|
+
yard: ~> 0.6.1
|
data/lib/chars/char_set.rb
CHANGED
@@ -6,23 +6,67 @@ module Chars
|
|
6
6
|
#
|
7
7
|
# Creates a new CharSet object.
|
8
8
|
#
|
9
|
-
# @param [Array<String, Integer,
|
9
|
+
# @param [Array<String, Integer, Enumerable>] arguments
|
10
10
|
# The chars for the CharSet.
|
11
11
|
#
|
12
|
-
def initialize(*
|
12
|
+
def initialize(*arguments)
|
13
13
|
super()
|
14
14
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
15
|
+
@chars = Hash.new { |hash,key| hash[key] = byte_to_char(key) }
|
16
|
+
|
17
|
+
arguments.each do |subset|
|
18
|
+
case subset
|
19
|
+
when String, Integer
|
20
|
+
self << subset
|
21
|
+
when Enumerable
|
22
|
+
subset.each { |char| self << char }
|
23
|
+
else
|
24
|
+
raise(ArgumentError,"arguments must be a String, Integer or Enumerable")
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
#
|
30
|
+
# Creates a new character set.
|
31
|
+
#
|
32
|
+
# @see #initialize
|
33
|
+
#
|
34
|
+
# @since 0.2.1
|
35
|
+
#
|
36
|
+
def self.[](*arguments)
|
37
|
+
new(*arguments)
|
38
|
+
end
|
39
|
+
|
40
|
+
#
|
41
|
+
# Adds a character to the set.
|
42
|
+
#
|
43
|
+
# @param [String, Integer] other
|
44
|
+
# The character(s) or byte to add.
|
45
|
+
#
|
46
|
+
# @return [CharSet]
|
47
|
+
# The modified character set.
|
48
|
+
#
|
49
|
+
# @raise [ArgumentError]
|
50
|
+
# The argument was not a {String} or {Integer}.
|
51
|
+
#
|
52
|
+
# @since 0.2.1
|
53
|
+
#
|
54
|
+
def <<(other)
|
55
|
+
case other
|
56
|
+
when String
|
57
|
+
other.each_char do |char|
|
58
|
+
byte = char_to_byte(char)
|
59
|
+
|
60
|
+
@chars[byte] = char
|
61
|
+
super(byte)
|
22
62
|
end
|
23
|
-
}
|
24
63
|
|
25
|
-
|
64
|
+
return self
|
65
|
+
when Integer
|
66
|
+
super(other)
|
67
|
+
else
|
68
|
+
raise(ArgumentError,"can only append Strings and Integers")
|
69
|
+
end
|
26
70
|
end
|
27
71
|
|
28
72
|
alias include_byte? include?
|
@@ -42,8 +86,8 @@ module Chars
|
|
42
86
|
# character set.
|
43
87
|
#
|
44
88
|
def include_char?(char)
|
45
|
-
|
46
|
-
|
89
|
+
unless char.empty?
|
90
|
+
@chars.has_value?(char) || include_byte?(char_to_byte(char))
|
47
91
|
else
|
48
92
|
false
|
49
93
|
end
|
@@ -56,7 +100,7 @@ module Chars
|
|
56
100
|
# All the characters within the character set.
|
57
101
|
#
|
58
102
|
def chars
|
59
|
-
map { |
|
103
|
+
map { |byte| @chars[byte] }
|
60
104
|
end
|
61
105
|
|
62
106
|
#
|
@@ -75,7 +119,7 @@ module Chars
|
|
75
119
|
def each_char
|
76
120
|
return enum_for(:each_char) unless block_given?
|
77
121
|
|
78
|
-
each { |
|
122
|
+
each { |byte| yield @chars[byte] }
|
79
123
|
end
|
80
124
|
|
81
125
|
#
|
@@ -92,7 +136,7 @@ module Chars
|
|
92
136
|
# The selected characters from the character set.
|
93
137
|
#
|
94
138
|
def select_chars(&block)
|
95
|
-
|
139
|
+
each_char.select(&block)
|
96
140
|
end
|
97
141
|
|
98
142
|
#
|
@@ -109,7 +153,7 @@ module Chars
|
|
109
153
|
# The mapped characters of the character set.
|
110
154
|
#
|
111
155
|
def map_chars(&block)
|
112
|
-
|
156
|
+
each_char.map(&block)
|
113
157
|
end
|
114
158
|
|
115
159
|
#
|
@@ -125,7 +169,7 @@ module Chars
|
|
125
169
|
# A random char from the character set.
|
126
170
|
#
|
127
171
|
def random_char
|
128
|
-
random_byte
|
172
|
+
@chars[random_byte]
|
129
173
|
end
|
130
174
|
|
131
175
|
#
|
@@ -168,7 +212,7 @@ module Chars
|
|
168
212
|
def each_random_char(n,&block)
|
169
213
|
return enum_for(:each_random_char,n) unless block_given?
|
170
214
|
|
171
|
-
each_random_byte(n) { |
|
215
|
+
each_random_byte(n) { |byte| yield @chars[byte] }
|
172
216
|
end
|
173
217
|
|
174
218
|
#
|
@@ -215,7 +259,7 @@ module Chars
|
|
215
259
|
# The randomly selected characters.
|
216
260
|
#
|
217
261
|
def random_chars(length)
|
218
|
-
random_bytes(length).map { |
|
262
|
+
random_bytes(length).map { |byte| @chars[byte] }
|
219
263
|
end
|
220
264
|
|
221
265
|
#
|
@@ -245,7 +289,7 @@ module Chars
|
|
245
289
|
# The randomly selected non-repeating characters.
|
246
290
|
#
|
247
291
|
def random_distinct_chars(length)
|
248
|
-
random_distinct_bytes(length).map { |
|
292
|
+
random_distinct_bytes(length).map { |byte| @chars[byte] }
|
249
293
|
end
|
250
294
|
|
251
295
|
#
|
@@ -264,7 +308,6 @@ module Chars
|
|
264
308
|
random_distinct_chars(length).join
|
265
309
|
end
|
266
310
|
|
267
|
-
|
268
311
|
#
|
269
312
|
# Finds sub-strings within given data that are made of characters within
|
270
313
|
# the character set.
|
@@ -284,7 +327,9 @@ module Chars
|
|
284
327
|
# sub-strings themselves.
|
285
328
|
#
|
286
329
|
def strings_in(data,options={})
|
287
|
-
min_length = (
|
330
|
+
min_length = options.fetch(:length,4)
|
331
|
+
|
332
|
+
return found if data.length < min_length
|
288
333
|
|
289
334
|
if options[:offsets]
|
290
335
|
found = {}
|
@@ -298,15 +343,13 @@ module Chars
|
|
298
343
|
}
|
299
344
|
end
|
300
345
|
|
301
|
-
return found if data.length < min_length
|
302
|
-
|
303
346
|
index = 0
|
304
347
|
|
305
348
|
while index <= (data.length - min_length)
|
306
|
-
if self === data[index
|
349
|
+
if self === data[index,min_length]
|
307
350
|
sub_index = (index + min_length)
|
308
351
|
|
309
|
-
while self.include_char?(data[sub_index
|
352
|
+
while self.include_char?(data[sub_index,1])
|
310
353
|
sub_index += 1
|
311
354
|
end
|
312
355
|
|
@@ -324,14 +367,16 @@ module Chars
|
|
324
367
|
# Creates a new CharSet object by unioning the character set with
|
325
368
|
# another character set.
|
326
369
|
#
|
327
|
-
# @param [CharSet, Array, Range]
|
370
|
+
# @param [CharSet, Array, Range] set
|
328
371
|
# The other character set to union with.
|
329
372
|
#
|
330
373
|
# @return [CharSet]
|
331
374
|
# The unioned character sets.
|
332
375
|
#
|
333
|
-
def |(
|
334
|
-
|
376
|
+
def |(set)
|
377
|
+
set = CharSet.new(set) unless set.kind_of?(CharSet)
|
378
|
+
|
379
|
+
return super(set)
|
335
380
|
end
|
336
381
|
|
337
382
|
alias + |
|
@@ -340,7 +385,7 @@ module Chars
|
|
340
385
|
# Compares the bytes within a given string with the bytes of the
|
341
386
|
# character set.
|
342
387
|
#
|
343
|
-
# @param [String] string
|
388
|
+
# @param [String, Enumerable] string
|
344
389
|
# The string to compare with the character set.
|
345
390
|
#
|
346
391
|
# @return [Boolean]
|
@@ -351,9 +396,19 @@ module Chars
|
|
351
396
|
# Chars.alpha === "hello"
|
352
397
|
# # => true
|
353
398
|
#
|
354
|
-
def ===(
|
355
|
-
|
356
|
-
|
399
|
+
def ===(other)
|
400
|
+
case other
|
401
|
+
when String
|
402
|
+
other.each_char.all? { |char| include_char?(char) }
|
403
|
+
when Enumerable
|
404
|
+
other.all? do |element|
|
405
|
+
case element
|
406
|
+
when String
|
407
|
+
include_char?(element)
|
408
|
+
when Integer
|
409
|
+
include_byte?(element)
|
410
|
+
end
|
411
|
+
end
|
357
412
|
else
|
358
413
|
false
|
359
414
|
end
|
@@ -368,19 +423,83 @@ module Chars
|
|
368
423
|
# The inspected character set.
|
369
424
|
#
|
370
425
|
def inspect
|
371
|
-
"#<#{self.class.name}: {" + map { |
|
372
|
-
case
|
426
|
+
"#<#{self.class.name}: {" + map { |byte|
|
427
|
+
case byte
|
373
428
|
when (0x07..0x0d), (0x20..0x7e)
|
374
|
-
|
429
|
+
@chars[byte].dump
|
375
430
|
when 0x00
|
376
431
|
# sly hack to make char-sets more friendly
|
377
432
|
# to us C programmers
|
378
433
|
'"\0"'
|
379
434
|
else
|
380
|
-
"0x%02x" %
|
435
|
+
"0x%02x" % byte
|
381
436
|
end
|
382
437
|
}.join(', ') + "}>"
|
383
438
|
end
|
384
439
|
|
440
|
+
protected
|
441
|
+
|
442
|
+
if RUBY_VERSION > '1.9.'
|
443
|
+
#
|
444
|
+
# Converts a byte to a character.
|
445
|
+
#
|
446
|
+
# @param [Integer] byte
|
447
|
+
# The byte to convert.
|
448
|
+
#
|
449
|
+
# @return [String]
|
450
|
+
# The character.
|
451
|
+
#
|
452
|
+
# @since 0.2.1
|
453
|
+
#
|
454
|
+
def byte_to_char(byte)
|
455
|
+
byte.chr(Encoding::UTF_8)
|
456
|
+
end
|
457
|
+
|
458
|
+
#
|
459
|
+
# Converts a character to a byte.
|
460
|
+
#
|
461
|
+
# @param [String] char
|
462
|
+
# The character to convert.
|
463
|
+
#
|
464
|
+
# @return [Integer]
|
465
|
+
# The byte.
|
466
|
+
#
|
467
|
+
# @since 0.2.1
|
468
|
+
#
|
469
|
+
def char_to_byte(char)
|
470
|
+
char.ord
|
471
|
+
end
|
472
|
+
else
|
473
|
+
#
|
474
|
+
# Converts a byte to a character.
|
475
|
+
#
|
476
|
+
# @param [Integer] byte
|
477
|
+
# The byte to convert.
|
478
|
+
#
|
479
|
+
# @return [String]
|
480
|
+
# The character.
|
481
|
+
#
|
482
|
+
# @since 0.2.1
|
483
|
+
#
|
484
|
+
def byte_to_char(byte)
|
485
|
+
byte.chr
|
486
|
+
end
|
487
|
+
|
488
|
+
#
|
489
|
+
# Converts a character to a byte.
|
490
|
+
#
|
491
|
+
# @param [String] char
|
492
|
+
# The character to convert.
|
493
|
+
#
|
494
|
+
# @return [Integer]
|
495
|
+
# The byte.
|
496
|
+
#
|
497
|
+
# @since 0.2.1
|
498
|
+
#
|
499
|
+
def char_to_byte(char)
|
500
|
+
char[0]
|
501
|
+
end
|
502
|
+
end
|
503
|
+
|
385
504
|
end
|
386
505
|
end
|