chars 0.2.0 → 0.2.1
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.
- 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
|