sub_string 1.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.
- 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
|