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.
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
@@ -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
@@ -83,6 +83,10 @@ set of space characters:
83
83
  Chars.space.random_string(5..10)
84
84
  # => "\r\v\n\t\n\f"
85
85
 
86
+ ## Requirements
87
+
88
+ * [ruby](http://www.ruby-lang.org/) >= 1.8.7
89
+
86
90
  ## Install
87
91
 
88
92
  $ sudo gem install chars
data/Rakefile CHANGED
@@ -2,7 +2,7 @@ require 'rubygems'
2
2
  require 'rake'
3
3
 
4
4
  begin
5
- gem 'ore-tasks', '~> 0.1.2'
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.0.0'
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
@@ -1,10 +1,127 @@
1
- # -*- encoding: utf-8 -*-
1
+ # encoding: utf-8
2
2
 
3
- begin
4
- Ore::Specification.new do |gemspec|
5
- # custom logic here
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
@@ -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.2.0
15
- ore-tasks: ~> 0.1.2
16
- rspec: ~> 2.0.0
16
+ ore-tasks: ~> 0.4
17
+ rspec: ~> 2.4
18
+ yard: ~> 0.6.1
@@ -6,23 +6,67 @@ module Chars
6
6
  #
7
7
  # Creates a new CharSet object.
8
8
  #
9
- # @param [Array<String, Integer, Range>] chars
9
+ # @param [Array<String, Integer, Enumerable>] arguments
10
10
  # The chars for the CharSet.
11
11
  #
12
- def initialize(*chars)
12
+ def initialize(*arguments)
13
13
  super()
14
14
 
15
- merge_chars = lambda { |element|
16
- if element.kind_of?(String)
17
- element.each_byte(&merge_chars)
18
- elsif element.kind_of?(Integer)
19
- self << element
20
- elsif element.kind_of?(Enumerable)
21
- element.each(&merge_chars)
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
- merge_chars.call(chars)
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
- if char.respond_to?(:each_byte)
46
- char.each_byte.any? { |b| include?(b) }
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 { |b| b.chr }
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 { |b| yield b.chr }
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
- chars.select(&block)
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
- chars.map(&block)
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.chr
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) { |b| yield b.chr }
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 { |b| b.chr }
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 { |b| b.chr }
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 = (options[:length] || 4)
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...(index + min_length)]
349
+ if self === data[index,min_length]
307
350
  sub_index = (index + min_length)
308
351
 
309
- while self.include_char?(data[sub_index..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] other_set
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 |(other_set)
334
- super(CharSet.new(other_set))
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 ===(string)
355
- if string.respond_to?(:each_byte)
356
- string.each_byte.all? { |b| include?(b) }
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 { |b|
372
- case b
426
+ "#<#{self.class.name}: {" + map { |byte|
427
+ case byte
373
428
  when (0x07..0x0d), (0x20..0x7e)
374
- b.chr.dump
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" % b
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