simply_useful 0.1.6 → 0.2.0
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/.document +6 -0
- data/.rspec +1 -0
- data/Gemfile +16 -0
- data/Rakefile +35 -55
- data/VERSION.yml +4 -3
- data/lib/simply_useful/all.rb +3 -0
- data/lib/simply_useful/bsearch.rb +134 -0
- data/lib/{core_ext → simply_useful/core_ext}/hash.rb +0 -0
- data/lib/simply_useful/core_ext/module/property_delegation.rb +23 -0
- data/lib/{core_ext.rb → simply_useful/core_ext.rb} +0 -0
- data/lib/simply_useful/format.rb +8 -0
- data/lib/simply_useful/has_attributes.rb +21 -0
- data/lib/simply_useful/java_native2ascii.rb +47 -0
- data/lib/simply_useful.rb +1 -1
- data/simply_useful.gemspec +55 -41
- data/spec/bsearch_spec.rb +2 -2
- data/spec/core_ext/hash_spec.rb +1 -1
- data/spec/core_ext/property_delegation_spec.rb +43 -0
- data/spec/has_attributes_spec.rb +3 -3
- data/spec/java_native2ascii_spec.rb +7 -4
- data/spec/simply_useful_spec.rb +1 -1
- data/spec/spec.opts +1 -4
- data/spec/spec_helper.rb +4 -2
- metadata +138 -54
- data/.gitignore +0 -10
- data/lib/bsearch.rb +0 -125
- data/lib/format.rb +0 -6
- data/lib/has_attributes.rb +0 -19
- data/lib/java_native2ascii.rb +0 -42
data/.document
ADDED
data/.rspec
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--color
|
data/Gemfile
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
source "http://rubygems.org"
|
2
|
+
# Add dependencies required to use your gem here.
|
3
|
+
# Example:
|
4
|
+
# gem "activesupport", ">= 2.3.5"
|
5
|
+
|
6
|
+
# Add dependencies to develop your gem here.
|
7
|
+
# Include everything needed to run rake, tests, features, etc.
|
8
|
+
group :development do
|
9
|
+
gem "rspec", "~> 2.12.0"
|
10
|
+
gem "rdoc", "~> 3.12"
|
11
|
+
gem "bundler", "~> 1.2.0"
|
12
|
+
gem "jeweler", "~> 1.8.4"
|
13
|
+
gem "simplecov", ">= 0", :require => false
|
14
|
+
|
15
|
+
gem "activesupport", "~> 3"
|
16
|
+
end
|
data/Rakefile
CHANGED
@@ -1,72 +1,52 @@
|
|
1
|
-
|
2
|
-
require 'rubygems'
|
1
|
+
# encoding: utf-8
|
3
2
|
|
4
|
-
|
3
|
+
require 'rubygems'
|
4
|
+
require 'bundler'
|
5
5
|
begin
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
s.homepage = "http://github.com/maciej/simply_useful"
|
12
|
-
s.description = "A set of simply useful classes. Contains extensions to core Ruby classes."
|
13
|
-
s.authors = ["Maciej Bilas"]
|
14
|
-
s.rubyforge_project = %q{simply_useful}
|
15
|
-
end
|
16
|
-
rescue LoadError
|
17
|
-
puts "Jeweler not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
|
6
|
+
Bundler.setup(:default, :development)
|
7
|
+
rescue Bundler::BundlerError => e
|
8
|
+
$stderr.puts e.message
|
9
|
+
$stderr.puts "Run `bundle install` to install missing gems"
|
10
|
+
exit e.status_code
|
18
11
|
end
|
12
|
+
require 'rake'
|
19
13
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
exit(0)
|
14
|
+
|
15
|
+
# Gem building
|
16
|
+
require 'jeweler'
|
17
|
+
Jeweler::Tasks.new do |gem|
|
18
|
+
gem.name = "simply_useful"
|
19
|
+
gem.summary = "A set of simply useful classes"
|
20
|
+
gem.license = "MIT"
|
21
|
+
gem.email = "maciej.bilas@gmail.com"
|
22
|
+
gem.homepage = "http://github.com/maciej/simply_useful"
|
23
|
+
gem.description = "A set of simply useful classes. Contains extensions to core Ruby classes."
|
24
|
+
gem.authors = ["Maciej Bilas"]
|
25
|
+
gem.rubyforge_project = %q{simply_useful}
|
26
|
+
# dependencies defined in Gemfile
|
34
27
|
end
|
28
|
+
Jeweler::RubygemsDotOrgTasks.new
|
35
29
|
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
30
|
+
require 'rspec/core'
|
31
|
+
require 'rspec/core/rake_task'
|
32
|
+
RSpec::Core::RakeTask.new(:spec) do |spec|
|
33
|
+
spec.pattern = FileList['spec/**/*_spec.rb']
|
40
34
|
end
|
41
35
|
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
t.libs << 'test'
|
47
|
-
t.test_files = FileList['test/**/*_test.rb']
|
48
|
-
t.verbose = true
|
49
|
-
end
|
50
|
-
rescue LoadError
|
51
|
-
puts "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
|
36
|
+
desc "Run RSpec with code coverage"
|
37
|
+
task :coverage do |spec|
|
38
|
+
ENV['COVERAGE'] = "true"
|
39
|
+
Rake::Task["spec"].execute
|
52
40
|
end
|
53
41
|
|
54
|
-
|
55
|
-
require 'rake/rdoctask'
|
42
|
+
require 'rdoc/task'
|
56
43
|
Rake::RDocTask.new do |rdoc|
|
44
|
+
version = File.exist?('VERSION') ? File.read('VERSION') : ""
|
45
|
+
|
57
46
|
rdoc.rdoc_dir = 'rdoc'
|
58
|
-
rdoc.title =
|
59
|
-
rdoc.options << '--line-numbers' << '--inline-source'
|
47
|
+
rdoc.title = "simply_useful #{version}"
|
60
48
|
rdoc.rdoc_files.include('README*')
|
61
49
|
rdoc.rdoc_files.include('lib/**/*.rb')
|
62
50
|
end
|
63
51
|
|
64
|
-
# Cucumber
|
65
|
-
begin
|
66
|
-
require 'cucumber/rake/task'
|
67
|
-
Cucumber::Rake::Task.new(:features)
|
68
|
-
rescue LoadError
|
69
|
-
puts "Cucumber is not available. In order to run features, you must: sudo gem install cucumber"
|
70
|
-
end
|
71
|
-
|
72
52
|
task :default => :spec
|
data/VERSION.yml
CHANGED
@@ -0,0 +1,134 @@
|
|
1
|
+
#
|
2
|
+
# Ruby/Bsearch - a binary search library for Ruby.
|
3
|
+
#
|
4
|
+
# Copyright (C) 2001 Satoru Takabayashi <satoru@namazu.org>
|
5
|
+
# All rights reserved.
|
6
|
+
# This is free software with ABSOLUTELY NO WARRANTY.
|
7
|
+
#
|
8
|
+
# You can redistribute it and/or modify it under the terms of
|
9
|
+
# the Ruby's licence.
|
10
|
+
#
|
11
|
+
# Example:
|
12
|
+
#
|
13
|
+
# % irb -r ./bsearch.rb
|
14
|
+
# >> %w(a b c c c d e f).bsearch_first {|x| x <=> "c"}
|
15
|
+
# => 2
|
16
|
+
# >> %w(a b c c c d e f).bsearch_last {|x| x <=> "c"}
|
17
|
+
# => 4
|
18
|
+
# >> %w(a b c e f).bsearch_first {|x| x <=> "c"}
|
19
|
+
# => 2
|
20
|
+
# >> %w(a b e f).bsearch_first {|x| x <=> "c"}
|
21
|
+
# => nil
|
22
|
+
# >> %w(a b e f).bsearch_last {|x| x <=> "c"}
|
23
|
+
# => nil
|
24
|
+
# >> %w(a b e f).bsearch_lower_boundary {|x| x <=> "c"}
|
25
|
+
# => 2
|
26
|
+
# >> %w(a b e f).bsearch_upper_boundary {|x| x <=> "c"}
|
27
|
+
# => 2
|
28
|
+
# >> %w(a b c c c d e f).bsearch_range {|x| x <=> "c"}
|
29
|
+
# => 2...5
|
30
|
+
# >> %w(a b c d e f).bsearch_range {|x| x <=> "c"}
|
31
|
+
# => 2...3
|
32
|
+
# >> %w(a b d e f).bsearch_range {|x| x <=> "c"}
|
33
|
+
# => 2...2
|
34
|
+
module SimplyUseful
|
35
|
+
module Bsearch
|
36
|
+
#VERSION = '1.5'
|
37
|
+
|
38
|
+
#
|
39
|
+
# The binary search algorithm is extracted from Jon Bentley's
|
40
|
+
# Programming Pearls 2nd ed. p.93
|
41
|
+
#
|
42
|
+
|
43
|
+
#
|
44
|
+
# Return the lower boundary. (inside)
|
45
|
+
#
|
46
|
+
def bsearch_lower_boundary (range = 0 ... self.length, &block)
|
47
|
+
lower = range.first() -1
|
48
|
+
upper = if range.exclude_end? then
|
49
|
+
range.last
|
50
|
+
else
|
51
|
+
range.last + 1
|
52
|
+
end
|
53
|
+
while lower + 1 != upper
|
54
|
+
mid = ((lower + upper) / 2).to_i # for working with mathn.rb (Rational)
|
55
|
+
if yield(self[mid]) < 0
|
56
|
+
lower = mid
|
57
|
+
else
|
58
|
+
upper = mid
|
59
|
+
end
|
60
|
+
end
|
61
|
+
return upper
|
62
|
+
end
|
63
|
+
|
64
|
+
#
|
65
|
+
# This method searches the FIRST occurrence which satisfies a
|
66
|
+
# condition given by a block in binary fashion and return the
|
67
|
+
# index of the first occurrence. Return nil if not found.
|
68
|
+
#
|
69
|
+
def bsearch_first (range = 0 ... self.length, &block)
|
70
|
+
boundary = bsearch_lower_boundary(range, &block)
|
71
|
+
if boundary >= self.length || yield(self[boundary]) != 0
|
72
|
+
return nil
|
73
|
+
else
|
74
|
+
return boundary
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
alias bsearch bsearch_first
|
79
|
+
|
80
|
+
#
|
81
|
+
# Return the upper boundary. (outside)
|
82
|
+
#
|
83
|
+
def bsearch_upper_boundary (range = 0 ... self.length, &block)
|
84
|
+
lower = range.first() -1
|
85
|
+
upper = if range.exclude_end? then
|
86
|
+
range.last
|
87
|
+
else
|
88
|
+
range.last + 1
|
89
|
+
end
|
90
|
+
while lower + 1 != upper
|
91
|
+
mid = ((lower + upper) / 2).to_i # for working with mathn.rb (Rational)
|
92
|
+
if yield(self[mid]) <= 0
|
93
|
+
lower = mid
|
94
|
+
else
|
95
|
+
upper = mid
|
96
|
+
end
|
97
|
+
end
|
98
|
+
return lower + 1 # outside of the matching range.
|
99
|
+
end
|
100
|
+
|
101
|
+
#
|
102
|
+
# This method searches the LAST occurrence which satisfies a
|
103
|
+
# condition given by a block in binary fashion and return the
|
104
|
+
# index of the last occurrence. Return nil if not found.
|
105
|
+
#
|
106
|
+
def bsearch_last (range = 0 ... self.length, &block)
|
107
|
+
# `- 1' for canceling `lower + 1' in bsearch_upper_boundary.
|
108
|
+
boundary = bsearch_upper_boundary(range, &block) - 1
|
109
|
+
|
110
|
+
if (boundary <= -1 || yield(self[boundary]) != 0)
|
111
|
+
return nil
|
112
|
+
else
|
113
|
+
return boundary
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
#
|
118
|
+
# Return the search result as a Range object.
|
119
|
+
#
|
120
|
+
def bsearch_range (range = 0 ... self.length, &block)
|
121
|
+
lower = bsearch_lower_boundary(range, &block)
|
122
|
+
upper = bsearch_upper_boundary(range, &block)
|
123
|
+
return lower ... upper
|
124
|
+
end
|
125
|
+
|
126
|
+
def bfind(range = 0 ... self.length, &block)
|
127
|
+
pos = self.bsearch(range, &block)
|
128
|
+
return nil if pos.nil?
|
129
|
+
self[pos]
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
Array.send :include, SimplyUseful::Bsearch
|
File without changes
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'active_support/core_ext/module/delegation'
|
2
|
+
|
3
|
+
class Module
|
4
|
+
|
5
|
+
def delegate_property *properties
|
6
|
+
options = {}
|
7
|
+
methods = []
|
8
|
+
|
9
|
+
properties.each do |options_or_property|
|
10
|
+
if options_or_property.is_a? Hash
|
11
|
+
options.merge! options_or_property
|
12
|
+
else
|
13
|
+
methods << options_or_property
|
14
|
+
methods << "#{options_or_property.to_s}="
|
15
|
+
end
|
16
|
+
end
|
17
|
+
puts methods
|
18
|
+
puts options
|
19
|
+
|
20
|
+
delegate *methods, options
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
File without changes
|
@@ -0,0 +1,8 @@
|
|
1
|
+
# Taken from Mephisto (http://mephistoblog.com/)
|
2
|
+
module SimplyUseful
|
3
|
+
module Format
|
4
|
+
DOMAIN = /^([a-z0-9]([-a-z0-9]*[a-z0-9])?\.)+((a[cdefgilmnoqrstuwxz]|aero|arpa)|(b[abdefghijmnorstvwyz]|biz)|(c[acdfghiklmnorsuvxyz]|cat|com|coop)|d[ejkmoz]|(e[ceghrstu]|edu)|f[ijkmor]|(g[abdefghilmnpqrstuwy]|gov)|(h[kmnrtu]#{(defined? RAILS_ENV) && RAILS_ENV=='test' ? '|host' : ''})|(i[delmnoqrst]|info|int)|(j[emop]|jobs)|k[eghimnprwyz]|l[abcikrstuvy]|(m[acdghklmnopqrstuvwxyz]|mil|mobi|museum)|(n[acefgilopruz]|name|net)|(om|org)|(p[aefghklmnrstwy]|pro)|qa|r[eouw]|s[abcdeghijklmnortvyz]|(t[cdfghjklmnoprtvwz]|travel)|u[agkmsyz]|v[aceginu]|w[fs]|y[etu]|z[amw])$/ unless const_defined?(:DOMAIN)
|
5
|
+
STRING = /^[a-z0-9-]+$/
|
6
|
+
EMAIL = /(\A(\s*)\Z)|(\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\Z)/i
|
7
|
+
end
|
8
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module SimplyUseful
|
2
|
+
module HasAttributes
|
3
|
+
def initialize(attributes = nil)
|
4
|
+
self.attributes = attributes
|
5
|
+
yield self if block_given?
|
6
|
+
end
|
7
|
+
|
8
|
+
def attributes=(attributes) # , guard_protected_attributes = true
|
9
|
+
#attributes = filter_attributes(attributes) if !attributes.blank? && guard_protected_attributes
|
10
|
+
attributes.each do |key, value|
|
11
|
+
send(key.to_s + '=', value)
|
12
|
+
end if attributes
|
13
|
+
end
|
14
|
+
|
15
|
+
def attributes
|
16
|
+
attributes = instance_variables
|
17
|
+
attributes.delete("@errors")
|
18
|
+
Hash[*attributes.collect { |attribute| [attribute[1..-1].to_sym, instance_variable_get(attribute)] }.flatten]
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
require('iconv')
|
2
|
+
|
3
|
+
# Mimics Java's native2ascii tool
|
4
|
+
module SimplyUseful
|
5
|
+
class JavaNative2Ascii
|
6
|
+
def self.ascii2native str
|
7
|
+
str.gsub(/\\u[0-9a-f]{4}/i) do |s|
|
8
|
+
out = ""
|
9
|
+
i = s[2, 4].hex
|
10
|
+
out << (i & 0xFF)
|
11
|
+
out << (i >> 8)
|
12
|
+
# Tested on MacOS 10.6
|
13
|
+
# The UNICODE encoding name apparently disappeared from Iconv
|
14
|
+
# I've changed it to UCS-2LE, which makes the Specs pass.
|
15
|
+
out = Iconv.conv("UTF-8", "UCS-2LE", out)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.native2ascii str
|
20
|
+
out = ""
|
21
|
+
|
22
|
+
arr = str.unpack("U*")
|
23
|
+
return out if arr.nil?
|
24
|
+
# arr_s = arr.size
|
25
|
+
# i = 0
|
26
|
+
#
|
27
|
+
# while i < arr_s
|
28
|
+
# c = arr[i]
|
29
|
+
# if c > 127
|
30
|
+
# out << sprintf("\\u%04x", c)
|
31
|
+
# else
|
32
|
+
# out << c
|
33
|
+
# end
|
34
|
+
# i+=1
|
35
|
+
# end
|
36
|
+
arr.each do |c|
|
37
|
+
if c > 127
|
38
|
+
out << sprintf("\\u%04x", c)
|
39
|
+
else
|
40
|
+
out << c
|
41
|
+
end
|
42
|
+
end
|
43
|
+
out
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
47
|
+
end
|
data/lib/simply_useful.rb
CHANGED
data/simply_useful.gemspec
CHANGED
@@ -1,65 +1,79 @@
|
|
1
1
|
# Generated by jeweler
|
2
2
|
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
-
# Instead, edit Jeweler::Tasks in Rakefile, and run
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
|
4
4
|
# -*- encoding: utf-8 -*-
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
|
-
s.name =
|
8
|
-
s.version = "0.
|
7
|
+
s.name = "simply_useful"
|
8
|
+
s.version = "0.2.0"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Maciej Bilas"]
|
12
|
-
s.date =
|
13
|
-
s.description =
|
14
|
-
s.email =
|
12
|
+
s.date = "2012-12-18"
|
13
|
+
s.description = "A set of simply useful classes. Contains extensions to core Ruby classes."
|
14
|
+
s.email = "maciej.bilas@gmail.com"
|
15
15
|
s.extra_rdoc_files = [
|
16
16
|
"README"
|
17
17
|
]
|
18
18
|
s.files = [
|
19
|
-
".
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
19
|
+
".document",
|
20
|
+
".rspec",
|
21
|
+
"Gemfile",
|
22
|
+
"MIT-LICENSE",
|
23
|
+
"README",
|
24
|
+
"Rakefile",
|
25
|
+
"VERSION.yml",
|
26
|
+
"lib/simply_useful.rb",
|
27
|
+
"lib/simply_useful/all.rb",
|
28
|
+
"lib/simply_useful/bsearch.rb",
|
29
|
+
"lib/simply_useful/core_ext.rb",
|
30
|
+
"lib/simply_useful/core_ext/hash.rb",
|
31
|
+
"lib/simply_useful/core_ext/module/property_delegation.rb",
|
32
|
+
"lib/simply_useful/format.rb",
|
33
|
+
"lib/simply_useful/has_attributes.rb",
|
34
|
+
"lib/simply_useful/java_native2ascii.rb",
|
35
|
+
"simply_useful.gemspec",
|
36
|
+
"spec/bsearch_spec.rb",
|
37
|
+
"spec/core_ext/hash_spec.rb",
|
38
|
+
"spec/core_ext/property_delegation_spec.rb",
|
39
|
+
"spec/has_attributes_spec.rb",
|
40
|
+
"spec/java_native2ascii_spec.rb",
|
41
|
+
"spec/simply_useful_spec.rb",
|
42
|
+
"spec/spec.opts",
|
43
|
+
"spec/spec_helper.rb"
|
39
44
|
]
|
40
|
-
s.homepage =
|
41
|
-
s.
|
45
|
+
s.homepage = "http://github.com/maciej/simply_useful"
|
46
|
+
s.licenses = ["MIT"]
|
42
47
|
s.require_paths = ["lib"]
|
43
|
-
s.rubyforge_project =
|
44
|
-
s.rubygems_version =
|
45
|
-
s.summary =
|
46
|
-
s.test_files = [
|
47
|
-
"spec/spec_helper.rb",
|
48
|
-
"spec/simply_useful_spec.rb",
|
49
|
-
"spec/core_ext/hash_spec.rb",
|
50
|
-
"spec/bsearch_spec.rb",
|
51
|
-
"spec/has_attributes_spec.rb",
|
52
|
-
"spec/java_native2ascii_spec.rb"
|
53
|
-
]
|
48
|
+
s.rubyforge_project = "simply_useful"
|
49
|
+
s.rubygems_version = "1.8.24"
|
50
|
+
s.summary = "A set of simply useful classes"
|
54
51
|
|
55
52
|
if s.respond_to? :specification_version then
|
56
|
-
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
57
53
|
s.specification_version = 3
|
58
54
|
|
59
|
-
if Gem::Version.new(Gem::
|
55
|
+
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
56
|
+
s.add_development_dependency(%q<rspec>, ["~> 2.12.0"])
|
57
|
+
s.add_development_dependency(%q<rdoc>, ["~> 3.12"])
|
58
|
+
s.add_development_dependency(%q<bundler>, ["~> 1.2.0"])
|
59
|
+
s.add_development_dependency(%q<jeweler>, ["~> 1.8.4"])
|
60
|
+
s.add_development_dependency(%q<simplecov>, [">= 0"])
|
61
|
+
s.add_development_dependency(%q<activesupport>, ["~> 3"])
|
60
62
|
else
|
63
|
+
s.add_dependency(%q<rspec>, ["~> 2.12.0"])
|
64
|
+
s.add_dependency(%q<rdoc>, ["~> 3.12"])
|
65
|
+
s.add_dependency(%q<bundler>, ["~> 1.2.0"])
|
66
|
+
s.add_dependency(%q<jeweler>, ["~> 1.8.4"])
|
67
|
+
s.add_dependency(%q<simplecov>, [">= 0"])
|
68
|
+
s.add_dependency(%q<activesupport>, ["~> 3"])
|
61
69
|
end
|
62
70
|
else
|
71
|
+
s.add_dependency(%q<rspec>, ["~> 2.12.0"])
|
72
|
+
s.add_dependency(%q<rdoc>, ["~> 3.12"])
|
73
|
+
s.add_dependency(%q<bundler>, ["~> 1.2.0"])
|
74
|
+
s.add_dependency(%q<jeweler>, ["~> 1.8.4"])
|
75
|
+
s.add_dependency(%q<simplecov>, [">= 0"])
|
76
|
+
s.add_dependency(%q<activesupport>, ["~> 3"])
|
63
77
|
end
|
64
78
|
end
|
65
79
|
|
data/spec/bsearch_spec.rb
CHANGED
data/spec/core_ext/hash_spec.rb
CHANGED
@@ -0,0 +1,43 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), '..', 'spec_helper')
|
2
|
+
require 'simply_useful/core_ext/module/property_delegation'
|
3
|
+
|
4
|
+
class Pair
|
5
|
+
attr_accessor :left, :right
|
6
|
+
|
7
|
+
def initialize(left = nil, right = nil)
|
8
|
+
self.left = left
|
9
|
+
self.right = right
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
class PairWrapper
|
14
|
+
|
15
|
+
delegate_property :left, :right, :to => :backing_pair
|
16
|
+
|
17
|
+
def initialize(backing_pair)
|
18
|
+
@backing_pair = backing_pair
|
19
|
+
end
|
20
|
+
|
21
|
+
protected
|
22
|
+
def backing_pair
|
23
|
+
@backing_pair
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
describe "property delegation" do
|
28
|
+
it "should delegate property getters to the backing object" do
|
29
|
+
pair = Pair.new(1,2)
|
30
|
+
wrapper = PairWrapper.new(pair)
|
31
|
+
|
32
|
+
wrapper.left.should eq(1)
|
33
|
+
wrapper.right.should eq(2)
|
34
|
+
end
|
35
|
+
|
36
|
+
it "should delegate property setters to backing object" do
|
37
|
+
wrapper = PairWrapper.new(Pair.new)
|
38
|
+
|
39
|
+
wrapper.left = 2
|
40
|
+
|
41
|
+
wrapper.left.should eq(2)
|
42
|
+
end
|
43
|
+
end
|
data/spec/has_attributes_spec.rb
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
require File.dirname(__FILE__) + '/spec_helper'
|
2
|
-
require 'has_attributes'
|
2
|
+
require 'simply_useful/has_attributes'
|
3
3
|
|
4
4
|
class ObjectWithAttributes
|
5
|
-
include HasAttributes
|
5
|
+
include SimplyUseful::HasAttributes
|
6
6
|
|
7
7
|
attr_accessor :foo
|
8
8
|
|
@@ -11,7 +11,7 @@ class ObjectWithAttributes
|
|
11
11
|
end
|
12
12
|
end
|
13
13
|
|
14
|
-
describe HasAttributes do
|
14
|
+
describe SimplyUseful::HasAttributes do
|
15
15
|
|
16
16
|
before(:each) do
|
17
17
|
@object_with_attributes = ObjectWithAttributes.new
|
@@ -1,5 +1,8 @@
|
|
1
|
+
#!ruby19
|
2
|
+
# encoding: utf-8
|
3
|
+
|
1
4
|
require File.dirname(__FILE__) + '/spec_helper'
|
2
|
-
require 'java_native2ascii'
|
5
|
+
require 'simply_useful/java_native2ascii'
|
3
6
|
|
4
7
|
class JavaNative2AsciiHelper
|
5
8
|
def native_ascii_pairs
|
@@ -11,7 +14,7 @@ class JavaNative2AsciiHelper
|
|
11
14
|
end
|
12
15
|
end
|
13
16
|
|
14
|
-
describe JavaNative2Ascii do
|
17
|
+
describe SimplyUseful::JavaNative2Ascii do
|
15
18
|
before(:all) do
|
16
19
|
@helper = JavaNative2AsciiHelper.new
|
17
20
|
end
|
@@ -19,14 +22,14 @@ describe JavaNative2Ascii do
|
|
19
22
|
it "should convert from ascii to native" do
|
20
23
|
@helper.native_ascii_pairs.each do |native_ascii|
|
21
24
|
native,ascii = native_ascii
|
22
|
-
JavaNative2Ascii.ascii2native(ascii).should == native
|
25
|
+
SimplyUseful::JavaNative2Ascii.ascii2native(ascii).should == native
|
23
26
|
end
|
24
27
|
end
|
25
28
|
|
26
29
|
it "should convert from native to ascii" do
|
27
30
|
@helper.native_ascii_pairs.each do |native_ascii|
|
28
31
|
native,ascii = native_ascii
|
29
|
-
JavaNative2Ascii.native2ascii(native).should == ascii
|
32
|
+
SimplyUseful::JavaNative2Ascii.native2ascii(native).should == ascii
|
30
33
|
end
|
31
34
|
end
|
32
35
|
end
|
data/spec/simply_useful_spec.rb
CHANGED
data/spec/spec.opts
CHANGED
data/spec/spec_helper.rb
CHANGED
metadata
CHANGED
@@ -1,86 +1,170 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: simply_useful
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
|
5
|
-
|
6
|
-
- 0
|
7
|
-
- 1
|
8
|
-
- 6
|
9
|
-
version: 0.1.6
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.2.0
|
5
|
+
prerelease:
|
10
6
|
platform: ruby
|
11
|
-
authors:
|
7
|
+
authors:
|
12
8
|
- Maciej Bilas
|
13
9
|
autorequire:
|
14
10
|
bindir: bin
|
15
11
|
cert_chain: []
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
12
|
+
date: 2012-12-18 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: rspec
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ~>
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: 2.12.0
|
22
|
+
type: :development
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ~>
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: 2.12.0
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: rdoc
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ~>
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '3.12'
|
38
|
+
type: :development
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ~>
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '3.12'
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: bundler
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ~>
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: 1.2.0
|
54
|
+
type: :development
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ~>
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 1.2.0
|
62
|
+
- !ruby/object:Gem::Dependency
|
63
|
+
name: jeweler
|
64
|
+
requirement: !ruby/object:Gem::Requirement
|
65
|
+
none: false
|
66
|
+
requirements:
|
67
|
+
- - ~>
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: 1.8.4
|
70
|
+
type: :development
|
71
|
+
prerelease: false
|
72
|
+
version_requirements: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ~>
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: 1.8.4
|
78
|
+
- !ruby/object:Gem::Dependency
|
79
|
+
name: simplecov
|
80
|
+
requirement: !ruby/object:Gem::Requirement
|
81
|
+
none: false
|
82
|
+
requirements:
|
83
|
+
- - ! '>='
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: '0'
|
86
|
+
type: :development
|
87
|
+
prerelease: false
|
88
|
+
version_requirements: !ruby/object:Gem::Requirement
|
89
|
+
none: false
|
90
|
+
requirements:
|
91
|
+
- - ! '>='
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: '0'
|
94
|
+
- !ruby/object:Gem::Dependency
|
95
|
+
name: activesupport
|
96
|
+
requirement: !ruby/object:Gem::Requirement
|
97
|
+
none: false
|
98
|
+
requirements:
|
99
|
+
- - ~>
|
100
|
+
- !ruby/object:Gem::Version
|
101
|
+
version: '3'
|
102
|
+
type: :development
|
103
|
+
prerelease: false
|
104
|
+
version_requirements: !ruby/object:Gem::Requirement
|
105
|
+
none: false
|
106
|
+
requirements:
|
107
|
+
- - ~>
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: '3'
|
21
110
|
description: A set of simply useful classes. Contains extensions to core Ruby classes.
|
22
|
-
email: maciej@
|
111
|
+
email: maciej.bilas@gmail.com
|
23
112
|
executables: []
|
24
|
-
|
25
113
|
extensions: []
|
26
|
-
|
27
|
-
extra_rdoc_files:
|
114
|
+
extra_rdoc_files:
|
28
115
|
- README
|
29
|
-
files:
|
30
|
-
- .
|
116
|
+
files:
|
117
|
+
- .document
|
118
|
+
- .rspec
|
119
|
+
- Gemfile
|
31
120
|
- MIT-LICENSE
|
32
121
|
- README
|
33
122
|
- Rakefile
|
34
123
|
- VERSION.yml
|
35
|
-
- lib/bsearch.rb
|
36
|
-
- lib/core_ext.rb
|
37
|
-
- lib/core_ext/hash.rb
|
38
|
-
- lib/format.rb
|
39
|
-
- lib/has_attributes.rb
|
40
|
-
- lib/java_native2ascii.rb
|
41
124
|
- lib/simply_useful.rb
|
125
|
+
- lib/simply_useful/all.rb
|
126
|
+
- lib/simply_useful/bsearch.rb
|
127
|
+
- lib/simply_useful/core_ext.rb
|
128
|
+
- lib/simply_useful/core_ext/hash.rb
|
129
|
+
- lib/simply_useful/core_ext/module/property_delegation.rb
|
130
|
+
- lib/simply_useful/format.rb
|
131
|
+
- lib/simply_useful/has_attributes.rb
|
132
|
+
- lib/simply_useful/java_native2ascii.rb
|
42
133
|
- simply_useful.gemspec
|
43
134
|
- spec/bsearch_spec.rb
|
44
135
|
- spec/core_ext/hash_spec.rb
|
136
|
+
- spec/core_ext/property_delegation_spec.rb
|
45
137
|
- spec/has_attributes_spec.rb
|
46
138
|
- spec/java_native2ascii_spec.rb
|
47
139
|
- spec/simply_useful_spec.rb
|
48
140
|
- spec/spec.opts
|
49
141
|
- spec/spec_helper.rb
|
50
|
-
has_rdoc: true
|
51
142
|
homepage: http://github.com/maciej/simply_useful
|
52
|
-
licenses:
|
53
|
-
|
143
|
+
licenses:
|
144
|
+
- MIT
|
54
145
|
post_install_message:
|
55
|
-
rdoc_options:
|
56
|
-
|
57
|
-
require_paths:
|
146
|
+
rdoc_options: []
|
147
|
+
require_paths:
|
58
148
|
- lib
|
59
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
149
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
150
|
+
none: false
|
151
|
+
requirements:
|
152
|
+
- - ! '>='
|
153
|
+
- !ruby/object:Gem::Version
|
154
|
+
version: '0'
|
155
|
+
segments:
|
64
156
|
- 0
|
65
|
-
|
66
|
-
required_rubygems_version: !ruby/object:Gem::Requirement
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
version: "0"
|
157
|
+
hash: -1403904800812772273
|
158
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
159
|
+
none: false
|
160
|
+
requirements:
|
161
|
+
- - ! '>='
|
162
|
+
- !ruby/object:Gem::Version
|
163
|
+
version: '0'
|
73
164
|
requirements: []
|
74
|
-
|
75
165
|
rubyforge_project: simply_useful
|
76
|
-
rubygems_version: 1.
|
166
|
+
rubygems_version: 1.8.24
|
77
167
|
signing_key:
|
78
168
|
specification_version: 3
|
79
169
|
summary: A set of simply useful classes
|
80
|
-
test_files:
|
81
|
-
- spec/spec_helper.rb
|
82
|
-
- spec/simply_useful_spec.rb
|
83
|
-
- spec/core_ext/hash_spec.rb
|
84
|
-
- spec/bsearch_spec.rb
|
85
|
-
- spec/has_attributes_spec.rb
|
86
|
-
- spec/java_native2ascii_spec.rb
|
170
|
+
test_files: []
|
data/.gitignore
DELETED
data/lib/bsearch.rb
DELETED
@@ -1,125 +0,0 @@
|
|
1
|
-
#
|
2
|
-
# Ruby/Bsearch - a binary search library for Ruby.
|
3
|
-
#
|
4
|
-
# Copyright (C) 2001 Satoru Takabayashi <satoru@namazu.org>
|
5
|
-
# All rights reserved.
|
6
|
-
# This is free software with ABSOLUTELY NO WARRANTY.
|
7
|
-
#
|
8
|
-
# You can redistribute it and/or modify it under the terms of
|
9
|
-
# the Ruby's licence.
|
10
|
-
#
|
11
|
-
# Example:
|
12
|
-
#
|
13
|
-
# % irb -r ./bsearch.rb
|
14
|
-
# >> %w(a b c c c d e f).bsearch_first {|x| x <=> "c"}
|
15
|
-
# => 2
|
16
|
-
# >> %w(a b c c c d e f).bsearch_last {|x| x <=> "c"}
|
17
|
-
# => 4
|
18
|
-
# >> %w(a b c e f).bsearch_first {|x| x <=> "c"}
|
19
|
-
# => 2
|
20
|
-
# >> %w(a b e f).bsearch_first {|x| x <=> "c"}
|
21
|
-
# => nil
|
22
|
-
# >> %w(a b e f).bsearch_last {|x| x <=> "c"}
|
23
|
-
# => nil
|
24
|
-
# >> %w(a b e f).bsearch_lower_boundary {|x| x <=> "c"}
|
25
|
-
# => 2
|
26
|
-
# >> %w(a b e f).bsearch_upper_boundary {|x| x <=> "c"}
|
27
|
-
# => 2
|
28
|
-
# >> %w(a b c c c d e f).bsearch_range {|x| x <=> "c"}
|
29
|
-
# => 2...5
|
30
|
-
# >> %w(a b c d e f).bsearch_range {|x| x <=> "c"}
|
31
|
-
# => 2...3
|
32
|
-
# >> %w(a b d e f).bsearch_range {|x| x <=> "c"}
|
33
|
-
# => 2...2
|
34
|
-
|
35
|
-
module Bsearch
|
36
|
-
#VERSION = '1.5'
|
37
|
-
|
38
|
-
#
|
39
|
-
# The binary search algorithm is extracted from Jon Bentley's
|
40
|
-
# Programming Pearls 2nd ed. p.93
|
41
|
-
#
|
42
|
-
|
43
|
-
#
|
44
|
-
# Return the lower boundary. (inside)
|
45
|
-
#
|
46
|
-
def bsearch_lower_boundary (range = 0 ... self.length, &block)
|
47
|
-
lower = range.first() -1
|
48
|
-
upper = if range.exclude_end? then range.last else range.last + 1 end
|
49
|
-
while lower + 1 != upper
|
50
|
-
mid = ((lower + upper) / 2).to_i # for working with mathn.rb (Rational)
|
51
|
-
if yield(self[mid]) < 0
|
52
|
-
lower = mid
|
53
|
-
else
|
54
|
-
upper = mid
|
55
|
-
end
|
56
|
-
end
|
57
|
-
return upper
|
58
|
-
end
|
59
|
-
|
60
|
-
#
|
61
|
-
# This method searches the FIRST occurrence which satisfies a
|
62
|
-
# condition given by a block in binary fashion and return the
|
63
|
-
# index of the first occurrence. Return nil if not found.
|
64
|
-
#
|
65
|
-
def bsearch_first (range = 0 ... self.length, &block)
|
66
|
-
boundary = bsearch_lower_boundary(range, &block)
|
67
|
-
if boundary >= self.length || yield(self[boundary]) != 0
|
68
|
-
return nil
|
69
|
-
else
|
70
|
-
return boundary
|
71
|
-
end
|
72
|
-
end
|
73
|
-
|
74
|
-
alias bsearch bsearch_first
|
75
|
-
|
76
|
-
#
|
77
|
-
# Return the upper boundary. (outside)
|
78
|
-
#
|
79
|
-
def bsearch_upper_boundary (range = 0 ... self.length, &block)
|
80
|
-
lower = range.first() -1
|
81
|
-
upper = if range.exclude_end? then range.last else range.last + 1 end
|
82
|
-
while lower + 1 != upper
|
83
|
-
mid = ((lower + upper) / 2).to_i # for working with mathn.rb (Rational)
|
84
|
-
if yield(self[mid]) <= 0
|
85
|
-
lower = mid
|
86
|
-
else
|
87
|
-
upper = mid
|
88
|
-
end
|
89
|
-
end
|
90
|
-
return lower + 1 # outside of the matching range.
|
91
|
-
end
|
92
|
-
|
93
|
-
#
|
94
|
-
# This method searches the LAST occurrence which satisfies a
|
95
|
-
# condition given by a block in binary fashion and return the
|
96
|
-
# index of the last occurrence. Return nil if not found.
|
97
|
-
#
|
98
|
-
def bsearch_last (range = 0 ... self.length, &block)
|
99
|
-
# `- 1' for canceling `lower + 1' in bsearch_upper_boundary.
|
100
|
-
boundary = bsearch_upper_boundary(range, &block) - 1
|
101
|
-
|
102
|
-
if (boundary <= -1 || yield(self[boundary]) != 0)
|
103
|
-
return nil
|
104
|
-
else
|
105
|
-
return boundary
|
106
|
-
end
|
107
|
-
end
|
108
|
-
|
109
|
-
#
|
110
|
-
# Return the search result as a Range object.
|
111
|
-
#
|
112
|
-
def bsearch_range (range = 0 ... self.length, &block)
|
113
|
-
lower = bsearch_lower_boundary(range, &block)
|
114
|
-
upper = bsearch_upper_boundary(range, &block)
|
115
|
-
return lower ... upper
|
116
|
-
end
|
117
|
-
|
118
|
-
def bfind(range = 0 ... self.length, &block)
|
119
|
-
pos = self.bsearch(range, &block)
|
120
|
-
return nil if pos.nil?
|
121
|
-
self[pos]
|
122
|
-
end
|
123
|
-
end
|
124
|
-
|
125
|
-
Array.send :include, Bsearch
|
data/lib/format.rb
DELETED
@@ -1,6 +0,0 @@
|
|
1
|
-
# Taken from Mephisto (http://mephistoblog.com/)
|
2
|
-
module Format
|
3
|
-
DOMAIN = /^([a-z0-9]([-a-z0-9]*[a-z0-9])?\.)+((a[cdefgilmnoqrstuwxz]|aero|arpa)|(b[abdefghijmnorstvwyz]|biz)|(c[acdfghiklmnorsuvxyz]|cat|com|coop)|d[ejkmoz]|(e[ceghrstu]|edu)|f[ijkmor]|(g[abdefghilmnpqrstuwy]|gov)|(h[kmnrtu]#{(defined? RAILS_ENV) && RAILS_ENV=='test'?'|host':''})|(i[delmnoqrst]|info|int)|(j[emop]|jobs)|k[eghimnprwyz]|l[abcikrstuvy]|(m[acdghklmnopqrstuvwxyz]|mil|mobi|museum)|(n[acefgilopruz]|name|net)|(om|org)|(p[aefghklmnrstwy]|pro)|qa|r[eouw]|s[abcdeghijklmnortvyz]|(t[cdfghjklmnoprtvwz]|travel)|u[agkmsyz]|v[aceginu]|w[fs]|y[etu]|z[amw])$/ unless const_defined?(:DOMAIN)
|
4
|
-
STRING = /^[a-z0-9-]+$/
|
5
|
-
EMAIL = /(\A(\s*)\Z)|(\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\Z)/i
|
6
|
-
end
|
data/lib/has_attributes.rb
DELETED
@@ -1,19 +0,0 @@
|
|
1
|
-
module HasAttributes
|
2
|
-
def initialize(attributes = nil)
|
3
|
-
self.attributes = attributes
|
4
|
-
yield self if block_given?
|
5
|
-
end
|
6
|
-
|
7
|
-
def attributes=(attributes) # , guard_protected_attributes = true
|
8
|
-
#attributes = filter_attributes(attributes) if !attributes.blank? && guard_protected_attributes
|
9
|
-
attributes.each do |key,value|
|
10
|
-
send(key.to_s + '=', value)
|
11
|
-
end if attributes
|
12
|
-
end
|
13
|
-
|
14
|
-
def attributes
|
15
|
-
attributes = instance_variables
|
16
|
-
attributes.delete("@errors")
|
17
|
-
Hash[*attributes.collect { |attribute| [attribute[1..-1].to_sym, instance_variable_get(attribute)] }.flatten]
|
18
|
-
end
|
19
|
-
end
|
data/lib/java_native2ascii.rb
DELETED
@@ -1,42 +0,0 @@
|
|
1
|
-
require('iconv')
|
2
|
-
|
3
|
-
# Mimics Java's native2ascii tool
|
4
|
-
class JavaNative2Ascii
|
5
|
-
def self.ascii2native str
|
6
|
-
str.gsub(/\\u[0-9a-f]{4}/i) do |s|
|
7
|
-
out = ""
|
8
|
-
i = s[2,4].hex
|
9
|
-
out << (i & 0xFF)
|
10
|
-
out << (i >> 8)
|
11
|
-
out = Iconv.conv("UTF-8", "UNICODE", out)
|
12
|
-
end
|
13
|
-
end
|
14
|
-
|
15
|
-
def self.native2ascii str
|
16
|
-
out = ""
|
17
|
-
|
18
|
-
arr = str.unpack("U*")
|
19
|
-
return out if arr.nil?
|
20
|
-
# arr_s = arr.size
|
21
|
-
# i = 0
|
22
|
-
#
|
23
|
-
# while i < arr_s
|
24
|
-
# c = arr[i]
|
25
|
-
# if c > 127
|
26
|
-
# out << sprintf("\\u%04x", c)
|
27
|
-
# else
|
28
|
-
# out << c
|
29
|
-
# end
|
30
|
-
# i+=1
|
31
|
-
# end
|
32
|
-
arr.each do |c|
|
33
|
-
if c > 127
|
34
|
-
out << sprintf("\\u%04x", c)
|
35
|
-
else
|
36
|
-
out << c
|
37
|
-
end
|
38
|
-
end
|
39
|
-
out
|
40
|
-
end
|
41
|
-
|
42
|
-
end
|