sub_string 1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +51 -0
- data/LICENSE.txt +20 -0
- data/Makefile +23 -0
- data/README.en.rdoc +173 -0
- data/Rakefile +9 -0
- data/lib/sub_string.rb +22 -0
- data/sub_string.gemspec +52 -0
- data/test/test_sub_string.rb +124 -0
- metadata +71 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: c328fe148dea22de40b0b91fcb890ecad51ec98b52579bd963ec3595a5c5d312
|
4
|
+
data.tar.gz: 2490b15f6bab5c743d02db40e5857acf9fd6b3b38b75fa7d155869e7dce957e3
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 573037a06377750a49a90d0ed95ca0ab59deb693eec7410b9a618352f334927e229a10a621e0c7a380f8deb4f201d5925b112871442b0fbb4d32ef86bc4dafb3
|
7
|
+
data.tar.gz: bab762511ada2c4e0c5b959c243605ad503d7e38f11ec1eebab0acbfa84eb95e6b3bbd9b9a3d0b6a609001521d455fde94489436dcbbfd0ebd31ea014adb1449
|
data/.gitignore
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
# See https://help.github.com/articles/ignoring-files for more about ignoring files.
|
2
|
+
#
|
3
|
+
# If you find yourself ignoring temporary files generated by your text editor
|
4
|
+
# or operating system, you probably want to add a global ignore instead:
|
5
|
+
# git config --global core.excludesfile '~/.gitignore_global'
|
6
|
+
|
7
|
+
# Ignore bundler config.
|
8
|
+
/.bundle
|
9
|
+
/vendor/bundle
|
10
|
+
|
11
|
+
# Ignore all logfiles and tempfiles.
|
12
|
+
/log/*
|
13
|
+
/tmp/*
|
14
|
+
!/log/.keep
|
15
|
+
!/tmp/.keep
|
16
|
+
|
17
|
+
.rbenv-version
|
18
|
+
# unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
|
19
|
+
.rvmrc
|
20
|
+
|
21
|
+
/node_modules
|
22
|
+
/yarn-error.log
|
23
|
+
|
24
|
+
.byebug_history
|
25
|
+
|
26
|
+
*.[oa]
|
27
|
+
*.so
|
28
|
+
*~
|
29
|
+
*.nogem
|
30
|
+
*nogem.*
|
31
|
+
*.bak
|
32
|
+
*.BAK
|
33
|
+
*.backup
|
34
|
+
*.org
|
35
|
+
*.orig
|
36
|
+
*.elc
|
37
|
+
*.pyc
|
38
|
+
\#*\#
|
39
|
+
|
40
|
+
# Elastic Beanstalk Files
|
41
|
+
.elasticbeanstalk/*
|
42
|
+
!.elasticbeanstalk/*.cfg.yml
|
43
|
+
!.elasticbeanstalk/*.global.yml
|
44
|
+
|
45
|
+
# yard
|
46
|
+
*.yardoc
|
47
|
+
|
48
|
+
# Ruby Gem doc
|
49
|
+
*.gem
|
50
|
+
doc/*
|
51
|
+
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2012-2018 Scott Chacon and others
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/Makefile
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
ALL =
|
2
|
+
|
3
|
+
objs =
|
4
|
+
|
5
|
+
.SUFFIXES: .so .o .c .f
|
6
|
+
|
7
|
+
#.o.so:
|
8
|
+
# ${LD} ${LFLAGS} -o $@ $< ${LINK_LIB}
|
9
|
+
|
10
|
+
all: ${ALL}
|
11
|
+
|
12
|
+
|
13
|
+
.PHONY: clean test doc
|
14
|
+
clean:
|
15
|
+
$(RM) bin/*~
|
16
|
+
|
17
|
+
## You may need RUBYLIB=`pwd`/lib:$RUBYLIB
|
18
|
+
test:
|
19
|
+
rake test
|
20
|
+
|
21
|
+
doc:
|
22
|
+
yard doc; [[ -x ".github" && ( "README.en.rdoc" -nt ".github/README.md" ) ]] && ( ruby -r rdoc -e 'puts RDoc::Markup::ToMarkdown.new.convert ARGF.read' < README.en.rdoc > .github/README.md ; echo ".github/README.md is updated." ) || exit 0
|
23
|
+
|
data/README.en.rdoc
ADDED
@@ -0,0 +1,173 @@
|
|
1
|
+
|
2
|
+
= SubString - Duck-typed String class with negligible memory use
|
3
|
+
|
4
|
+
== Summary
|
5
|
+
|
6
|
+
Class {SubString} that expresses Ruby sub-String but taking up negligible memory space, as its instance holds the positional information only. It behaves exactly like String (duck-typing), except destructive modification is prohibited. If the original string is destructively modified, warning is issued.
|
7
|
+
|
8
|
+
For the detailed background concept (and algorithm), see the reference page of the
|
9
|
+
generalized parent class, SubObject, either at the
|
10
|
+
{Ruby Gems page}[http://rubygems.org/gems/sub_object]
|
11
|
+
or in
|
12
|
+
{Github}[https://github.com/masasakano/sub_object] .
|
13
|
+
|
14
|
+
The full package of this class is found also in
|
15
|
+
{SubString Ruby Gems page}[http://rubygems.org/gems/sub_string] and
|
16
|
+
in {Github}[https://github.com/masasakano/sub_string]
|
17
|
+
|
18
|
+
|
19
|
+
== Description
|
20
|
+
|
21
|
+
This class takes three parameters in the initialization: *source*, *pos*
|
22
|
+
(starting positional character-index), and *size* (of the substring of the original String *source*.
|
23
|
+
|
24
|
+
SubObject.new( source, position, size )
|
25
|
+
|
26
|
+
The constructed instance of this class keeps only these three pieces
|
27
|
+
of information (plus a hash value, strictly speaking), and hence uses negligible internal memory space on its own.
|
28
|
+
Note that only the information this instance needs for *source* is
|
29
|
+
+source.object_id+ or equivalent, which is really negligible in size.
|
30
|
+
In other words, this class does not create the copy of sub-Object from
|
31
|
+
the original source object as the Ruby default +String#[i,j]+ does.
|
32
|
+
|
33
|
+
Then, whenever it is referred to, it reconstructs the original
|
34
|
+
sub-String object:
|
35
|
+
|
36
|
+
source[pos, size]
|
37
|
+
|
38
|
+
and works exactly like *source*
|
39
|
+
({duck-typing}[https://en.wikipedia.org/wiki/Duck_typing]).
|
40
|
+
|
41
|
+
As an example, the child class {SubString}[http://rubygems.org/gems/sub_string] (provided as a different Gem)
|
42
|
+
works as:
|
43
|
+
|
44
|
+
src = "abcdef"
|
45
|
+
ss = SubString.new(src, -4, 3) # => Similar to "abcdef"[-4,3]
|
46
|
+
print ss # => "cde" (STDOUT)
|
47
|
+
ss+'3p' # => "cde3p"
|
48
|
+
ss.upcase # => "CDE"
|
49
|
+
ss.sub(/^./, 'Q') # => "Qde"
|
50
|
+
ss.is_a?(String) # => true
|
51
|
+
"xy_"+ss # => "xy_cde"
|
52
|
+
"cde" == ss # => true
|
53
|
+
|
54
|
+
Internally the instance holds the source object. Therefore, as long
|
55
|
+
as the instance is alive, the source object is never garbage-collected (GC).
|
56
|
+
|
57
|
+
=== Instance methods
|
58
|
+
|
59
|
+
The following is the instance methods of {SubObject}[http://rubygems.org/gems/sub_object] unique to this class.
|
60
|
+
|
61
|
+
+#source()+:: Returns the first argument (+source+ String) given in initialization. The returned value is dup-ped and **frozen**.
|
62
|
+
+#pos()+:: Returns the second argument (positional index) given in initialization.
|
63
|
+
+#subsize()+:: Returns the third argument (size) given in initialization. Equivalent to the method +#size+.
|
64
|
+
+#pos_size()+:: Returns the two-component array of +[pos, subsize]+
|
65
|
+
+#to_source()+:: Returns the instance projected with +to_src+
|
66
|
+
|
67
|
+
In addition, +#inspect+ is redefined.
|
68
|
+
|
69
|
+
Any public methods but destructive ones that are defined for the +source+ can
|
70
|
+
be applied to the instance of this class.
|
71
|
+
|
72
|
+
=== Potential use
|
73
|
+
|
74
|
+
Each sub-String in Ruby like +String[i, j]+ or +String[i..j]+ takes up memory
|
75
|
+
according to the length of the sub-String. Consider an example:
|
76
|
+
|
77
|
+
src = "Some very extremely lengthy string.... (snipped)".
|
78
|
+
sub = src[1..-1]
|
79
|
+
|
80
|
+
The variable +sub+ uses up about the same memory of +src+.
|
81
|
+
If a great number of +sub+ is created and held alive, the total memory
|
82
|
+
used by the process can become quicly multifold, even by orders of magnitude.
|
83
|
+
|
84
|
+
This is where this class comes in handy. For example, a parsing
|
85
|
+
program applied to a huge text document with a complex grammar may
|
86
|
+
hold a number of such String variables. By using this class instead
|
87
|
+
of String, it can save some valuable memory.
|
88
|
+
|
89
|
+
=== Warning about destructive methods to this instance or worse, to the source
|
90
|
+
|
91
|
+
If the source object has been destructively altered, such as with the
|
92
|
+
destructive method +clear+, the corresponding object of this class
|
93
|
+
is likely not to make sense any more. This class can detect such destructive
|
94
|
+
modification (using the method +Object#hash+) and issues a warning
|
95
|
+
whenever it is accessed after the source object has been destructively
|
96
|
+
altered, unless the appropriate global settings (see the next section)
|
97
|
+
are set to suppress it.
|
98
|
+
|
99
|
+
Similarly, because this class supplies an object with the filter +String#to_str+
|
100
|
+
when it receives any message (i.e., method),
|
101
|
+
it does not make sense to apply a destructive change on the instance of this class.
|
102
|
+
Therefore, whenever a destructive method (such as, +String#sub!+ and
|
103
|
+
+String#replace+ or even +String#force_encoding+) is applied to an
|
104
|
+
instance of this class, it
|
105
|
+
raises NoMethodError exception (or tries to with the best effort). The routine to identify the
|
106
|
+
destructive method relies thoroughly on the method name.
|
107
|
+
The methods ending with "!" are regarded as destructive and all the
|
108
|
+
built-in destructive methods of String (as of Ruby 2.6.5).
|
109
|
+
|
110
|
+
If a user library adds destructive methods with the name not ending
|
111
|
+
with "!" in the String class, you can register it in the inherited class constant
|
112
|
+
DESTRUCTIVE_METHODS so the instances of this class will
|
113
|
+
recognize them (Note that it is recommended to use a destructive
|
114
|
+
method for it, perhaps with one of +Array#<<+, +Array#append+, +Array#push+, +Array#concat+ etc).
|
115
|
+
The reference of the parent
|
116
|
+
{SubObject}[http://rubygems.org/gems/sub_object] class describes the
|
117
|
+
detail of the mechanism of how it works (if you are interested).
|
118
|
+
|
119
|
+
Note that if a (user-defined) desturctive method of String passes the
|
120
|
+
check by this class objects,
|
121
|
+
the result is most likely to be different from intended. It certainly
|
122
|
+
never alters this instance destructively, and
|
123
|
+
the returned value may be not like the expected value.
|
124
|
+
|
125
|
+
=== Suppressing the warning
|
126
|
+
|
127
|
+
This class objects issues a warning in default every time it detects the *source*
|
128
|
+
String object has been destructively modified. My best advice is,
|
129
|
+
never alter the *source* object destructively! It makes no sense to
|
130
|
+
use this object in such a case.
|
131
|
+
|
132
|
+
However if you want to suppress the warning message, set the Ruby
|
133
|
+
global variable +$VERBOSE+ to nil. Alternatively, you can control it with
|
134
|
+
a class instance variable as
|
135
|
+
|
136
|
+
SubObject.verbose # => getter
|
137
|
+
SubObject.verbose=true # => setter
|
138
|
+
|
139
|
+
If it is set either TRUE or FALSE, this verbosity level has a
|
140
|
+
priority, regardless of the value of +$VERBOSE+.
|
141
|
+
In default it is nil and $VERBOSE is referred to.
|
142
|
+
|
143
|
+
|
144
|
+
== Install
|
145
|
+
|
146
|
+
This script requires {Ruby}[http://www.ruby-lang.org] Version 2.0
|
147
|
+
or above.
|
148
|
+
|
149
|
+
You can install it from the usual Ruby gem command.
|
150
|
+
Or, alternatively, download it and put the library file in one of your Ruby library search paths.
|
151
|
+
|
152
|
+
== Developer's note
|
153
|
+
|
154
|
+
The master of this README file is found in
|
155
|
+
{RubyGems/sub_object}[https://rubygems.org/gems/sub_object]
|
156
|
+
|
157
|
+
=== Tests
|
158
|
+
|
159
|
+
Ruby codes under the directory <tt>test/</tt> are the test scripts.
|
160
|
+
You can run them from the top directory as <tt>ruby test/test_****.rb</tt>
|
161
|
+
or simply run <tt>make test</tt>.
|
162
|
+
|
163
|
+
== Known bugs and Todo items
|
164
|
+
|
165
|
+
* This class ignores any optional (keyword) parameters for the methods. It is due to the fact Ruby {BasicObject#method_missing}[https://ruby-doc.org/core-2.6.5/BasicObject.html#method-i-method_missing] does not take them into account as of Ruby-2.6.5. It may change in future versions of Ruby. As far as the Ruby built-in methods of String are concerned, it does not matter because none of them uses one. However, if String uses such user-defined methods, it may encounter a trouble.
|
166
|
+
|
167
|
+
|
168
|
+
== Copyright
|
169
|
+
|
170
|
+
Author:: Masa Sakano < info a_t wisebabel dot com >
|
171
|
+
Versions:: The versions of this package follow Semantic Versioning (2.0.0) http://semver.org/
|
172
|
+
License:: MIT
|
173
|
+
|
data/Rakefile
ADDED
data/lib/sub_string.rb
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
|
3
|
+
require 'sub_object' # Gem: {SubObject}[http://rubygems.org/gems/sub_object]
|
4
|
+
|
5
|
+
# Child class of SubObject for String: SubString
|
6
|
+
#
|
7
|
+
# See for detail the full reference in the top page
|
8
|
+
# {SubString}[http://rubygems.org/gems/sub_string]
|
9
|
+
# and in {Github}[https://github.com/masasakano/sub_string]
|
10
|
+
# and also
|
11
|
+
# {SubObject}[http://rubygems.org/gems/sub_object]
|
12
|
+
# and that in {Github}[https://github.com/masasakano/sub_object]
|
13
|
+
#
|
14
|
+
# @author Masa Sakano (Wise Babel Ltd)
|
15
|
+
#
|
16
|
+
class SubString < SubObject
|
17
|
+
# Symbol of the method that projects to (returns) the original-like instance;
|
18
|
+
# e.g., :to_str for String. The value should be overwritten in the child class of SubObject.
|
19
|
+
TO_SOURCE_METHOD = :to_str
|
20
|
+
alias_method TO_SOURCE_METHOD, :to_source
|
21
|
+
end
|
22
|
+
|
data/sub_string.gemspec
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
require 'rake'
|
4
|
+
require 'date'
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = %q{sub_string}.sub(/.*/){|c| (c == File.basename(Dir.pwd)) ? c : raise("ERROR: s.name=(#{c}) in gemspec seems wrong!")}
|
8
|
+
s.version = "1.0"
|
9
|
+
# s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
10
|
+
# s.bindir = 'bin'
|
11
|
+
# %w(sub_string).each do |f|
|
12
|
+
# path = s.bindir+'/'+f
|
13
|
+
# File.executable?(path) ? s.executables << f : raise("ERROR: Executable (#{path}) is not executable!")
|
14
|
+
# end
|
15
|
+
s.authors = ["Masa Sakano"]
|
16
|
+
s.date = %q{2019-11-05}.sub(/.*/){|c| (Date.parse(c) == Date.today) ? c : raise("ERROR: s.date=(#{c}) is not today!")}
|
17
|
+
s.summary = %q{Duck-typed String class with negligible memory use}
|
18
|
+
s.description = %q{Class SubString that expresses Ruby sub-String but taking up negligible memory space, as its instance holds the positional information only. It behaves exactly like String (duck-typing), except destructive modification is prohibited. If the original string is destructively altered, warning is issued.}
|
19
|
+
# s.email = %q{abc@example.com}
|
20
|
+
s.extra_rdoc_files = [
|
21
|
+
#"LICENSE.txt",
|
22
|
+
"README.en.rdoc",
|
23
|
+
]
|
24
|
+
s.license = 'MIT'
|
25
|
+
s.files = FileList['.gitignore','lib/**/*.rb','[A-Z]*','test/**/*.rb', '*.gemspec'].to_a.delete_if{ |f|
|
26
|
+
ret = false
|
27
|
+
arignore = IO.readlines('.gitignore')
|
28
|
+
arignore.map{|i| i.chomp}.each do |suffix|
|
29
|
+
if File.fnmatch(suffix, File.basename(f))
|
30
|
+
ret = true
|
31
|
+
break
|
32
|
+
end
|
33
|
+
end
|
34
|
+
ret
|
35
|
+
}
|
36
|
+
s.files.reject! { |fn| File.symlink? fn }
|
37
|
+
|
38
|
+
s.add_runtime_dependency 'sub_object', '>= 1.0'
|
39
|
+
# s.add_development_dependency "bourne", [">= 0"]
|
40
|
+
s.homepage = %q{https://www.wisebabel.com}
|
41
|
+
s.rdoc_options = ["--charset=UTF-8"]
|
42
|
+
|
43
|
+
# s.require_paths = ["lib"] # Default "lib"
|
44
|
+
s.required_ruby_version = '>= 2.0' # respond_to_missing?
|
45
|
+
s.test_files = Dir['test/**/*.rb']
|
46
|
+
s.test_files.reject! { |fn| File.symlink? fn }
|
47
|
+
# s.requirements << 'libmagick, v6.0' # Simply, info to users.
|
48
|
+
# s.rubygems_version = %q{1.3.5} # This is always set automatically!!
|
49
|
+
|
50
|
+
s.metadata["yard.run"] = "yri" # use "yard" to build full HTML docs.
|
51
|
+
end
|
52
|
+
|
@@ -0,0 +1,124 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
# @author Masa Sakano (Wise Babel Ltd)
|
4
|
+
|
5
|
+
#require 'open3'
|
6
|
+
require 'sub_object'
|
7
|
+
require 'sub_string'
|
8
|
+
|
9
|
+
$stdout.sync=true
|
10
|
+
$stderr.sync=true
|
11
|
+
# print '$LOAD_PATH=';p $LOAD_PATH
|
12
|
+
|
13
|
+
#################################################
|
14
|
+
# Unit Test
|
15
|
+
#################################################
|
16
|
+
|
17
|
+
gem "minitest"
|
18
|
+
# require 'minitest/unit'
|
19
|
+
require 'minitest/autorun'
|
20
|
+
|
21
|
+
class TestUnitSubString < MiniTest::Test
|
22
|
+
T = true
|
23
|
+
F = false
|
24
|
+
SCFNAME = File.basename(__FILE__)
|
25
|
+
EXE = "%s/../bin/%s" % [File.dirname(__FILE__), File.basename(__FILE__).sub(/^test_(.+)\.rb/, '\1')]
|
26
|
+
|
27
|
+
def setup
|
28
|
+
end
|
29
|
+
|
30
|
+
def teardown
|
31
|
+
end
|
32
|
+
|
33
|
+
def test_sub_string01
|
34
|
+
assert_raises(TypeError){ SubString.new [9,8], -3, 2 }
|
35
|
+
|
36
|
+
str = 'abcdefghijklm'
|
37
|
+
obj = SubString.new str, -5, 2
|
38
|
+
assert_raises(TypeError){ SubString.new str, -3, :a }
|
39
|
+
assert_equal obj, "ij"
|
40
|
+
assert_equal "ij", obj
|
41
|
+
assert( "ij"==obj )
|
42
|
+
assert_operator obj, ">", "ii"
|
43
|
+
assert_operator "ii", "<", obj
|
44
|
+
assert( SubString.method_defined?(:to_str), "obj=#{obj.inspect}" )
|
45
|
+
assert( obj.methods.include? :to_str )
|
46
|
+
assert_equal 'ijKL', obj+"KL"
|
47
|
+
assert_equal "IJ", obj.upcase
|
48
|
+
assert obj.instance_of?(SubString)
|
49
|
+
refute obj.instance_of?(SubObject)
|
50
|
+
assert obj.respond_to?(:upcase), "upcase: to_source = (#{obj.to_source.inspect}); methods: #{obj.methods.sort.inspect}"
|
51
|
+
assert obj.respond_to?(:gsub), "to_source = (#{obj.to_source.inspect}); methods: #{obj.methods.sort.inspect}"
|
52
|
+
refute obj.respond_to?(:gsub!)
|
53
|
+
refute obj.respond_to?(:naiyo)
|
54
|
+
assert_raises(NoMethodError){ obj.push 5 }
|
55
|
+
assert_raises(NoMethodError){ obj.keep_if{} }
|
56
|
+
assert_raises(NoMethodError){ obj.sub! }
|
57
|
+
assert_raises(NoMethodError){ obj.replace }
|
58
|
+
|
59
|
+
mutex = Mutex.new
|
60
|
+
exclu = Thread.new {
|
61
|
+
mutex.synchronize {
|
62
|
+
org_verbose = $VERBOSE
|
63
|
+
assert_output('', ''){ _ = SubString.verbose }
|
64
|
+
begin
|
65
|
+
$VERBOSE = true
|
66
|
+
assert_nil SubString.verbose
|
67
|
+
SubString.verbose=nil;
|
68
|
+
assert_nil SubString.verbose
|
69
|
+
str.sub!(/^./){|c| c.upcase}
|
70
|
+
assert_output('', /destructively/){ obj.source }
|
71
|
+
$VERBOSE = false
|
72
|
+
assert_output('', /destructively/){ obj.source }
|
73
|
+
$VERBOSE = nil
|
74
|
+
assert_output('', ''){ obj.source }
|
75
|
+
|
76
|
+
SubString.verbose = true
|
77
|
+
assert_equal true, SubString.verbose
|
78
|
+
assert_equal true, SubString.instance_variable_get(:@verbosity)
|
79
|
+
assert_output('', /destructively/){ obj.source }
|
80
|
+
SubString.verbose = false
|
81
|
+
assert_equal false, SubString.verbose
|
82
|
+
assert_output('', ''){ obj.source }
|
83
|
+
$VERBOSE = true
|
84
|
+
assert_output('', ''){ obj.source }
|
85
|
+
SubString.verbose=nil;
|
86
|
+
assert_output('', /destructively/){ obj.source }
|
87
|
+
|
88
|
+
# Original String recovered, hence its hash value.
|
89
|
+
str.sub!(/^./){|c| c.downcase}
|
90
|
+
assert_output('', ''){ obj.source }
|
91
|
+
ensure
|
92
|
+
$VERBOSE = org_verbose
|
93
|
+
SubString.verbose=nil;
|
94
|
+
end
|
95
|
+
}
|
96
|
+
}
|
97
|
+
exclu.join
|
98
|
+
end
|
99
|
+
|
100
|
+
def test_sub_string02
|
101
|
+
str = 'abcdefghijklm'*20
|
102
|
+
obj = SubString.new str, 0, 120
|
103
|
+
str.upcase!
|
104
|
+
siz = nil
|
105
|
+
_, err = capture_io { siz = obj.size }
|
106
|
+
assert_equal '..."'+"\n", err[-5..-1]
|
107
|
+
assert_equal 60, (err.split(']')[-1].size-4)/10.0.round*10
|
108
|
+
assert_equal 120, siz
|
109
|
+
end
|
110
|
+
|
111
|
+
# As in README.en.rdoc
|
112
|
+
def test_sub_string03
|
113
|
+
src = "abcdef"
|
114
|
+
ss = SubString.new(src, -4, 3) # => Similar to "abcdef"[-4,3]
|
115
|
+
assert_operator "cde", '==', ss
|
116
|
+
assert_equal "cde", ss.to_s
|
117
|
+
assert_equal "cde3p", ss+'3p'
|
118
|
+
assert_equal "CDE", ss.upcase
|
119
|
+
assert_equal "Qde", ss.sub(/^./, 'Q')
|
120
|
+
assert ss.is_a?(String)
|
121
|
+
assert_equal "xy_cde", "xy_"+ss
|
122
|
+
end
|
123
|
+
end # class TestUnitSubString < MiniTest::Test
|
124
|
+
|
metadata
ADDED
@@ -0,0 +1,71 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: sub_string
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: '1.0'
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Masa Sakano
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2019-11-05 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: sub_object
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.0'
|
27
|
+
description: Class SubString that expresses Ruby sub-String but taking up negligible
|
28
|
+
memory space, as its instance holds the positional information only. It behaves
|
29
|
+
exactly like String (duck-typing), except destructive modification is prohibited. If
|
30
|
+
the original string is destructively altered, warning is issued.
|
31
|
+
email:
|
32
|
+
executables: []
|
33
|
+
extensions: []
|
34
|
+
extra_rdoc_files:
|
35
|
+
- README.en.rdoc
|
36
|
+
files:
|
37
|
+
- ".gitignore"
|
38
|
+
- LICENSE.txt
|
39
|
+
- Makefile
|
40
|
+
- README.en.rdoc
|
41
|
+
- Rakefile
|
42
|
+
- lib/sub_string.rb
|
43
|
+
- sub_string.gemspec
|
44
|
+
- test/test_sub_string.rb
|
45
|
+
homepage: https://www.wisebabel.com
|
46
|
+
licenses:
|
47
|
+
- MIT
|
48
|
+
metadata:
|
49
|
+
yard.run: yri
|
50
|
+
post_install_message:
|
51
|
+
rdoc_options:
|
52
|
+
- "--charset=UTF-8"
|
53
|
+
require_paths:
|
54
|
+
- lib
|
55
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
56
|
+
requirements:
|
57
|
+
- - ">="
|
58
|
+
- !ruby/object:Gem::Version
|
59
|
+
version: '2.0'
|
60
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
61
|
+
requirements:
|
62
|
+
- - ">="
|
63
|
+
- !ruby/object:Gem::Version
|
64
|
+
version: '0'
|
65
|
+
requirements: []
|
66
|
+
rubygems_version: 3.0.3
|
67
|
+
signing_key:
|
68
|
+
specification_version: 4
|
69
|
+
summary: Duck-typed String class with negligible memory use
|
70
|
+
test_files:
|
71
|
+
- test/test_sub_string.rb
|