sub_object 1.0.2 → 1.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.
- checksums.yaml +4 -4
- data/ChangeLog +5 -0
- data/Makefile +1 -1
- data/README.en.rdoc +28 -16
- data/lib/sub_object.rb +4 -3
- data/sub_object.gemspec +2 -2
- data/test/test_sub_object.rb +22 -0
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 82f0b7dfe21acc55f95a85ede284e7726a2d20b8167933a64f2d19326a603881
|
4
|
+
data.tar.gz: f38d6e5d31d7c2db961bde8324d94f567f50f00ba07deb8c31df45a24cb08471
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0a0af4d1e49ee3f2eeb91a7394c92e797a2911b08a29d5c515e245bc3568aeb7db507e2ac2893894fda41662b8ed9d75a25ab369967368f265664eecc274984d
|
7
|
+
data.tar.gz: c25e3f02f129a10efc1ae05127cf513f4cb627d4941c0f408cded27b1eade3efd0543dd9c05da09f4cb20e73f30907965303f32732ee4237ade69200114e8053
|
data/ChangeLog
CHANGED
data/Makefile
CHANGED
@@ -20,5 +20,5 @@ test:
|
|
20
20
|
|
21
21
|
## yard2md_afterclean in Gem plain_text https://rubygems.org/gems/plain_text
|
22
22
|
doc:
|
23
|
-
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 | yard2md_afterclean > .github/README.md
|
23
|
+
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 | yard2md_afterclean > .github/README.md.$$ && ( mv -f .github/README.md.$$ .github/README.md && echo ".github/README.md is updated." ) || ( echo "ERROR: failed to create .github/README.md" >&2 ) ) || exit 0
|
24
24
|
|
data/README.en.rdoc
CHANGED
@@ -3,15 +3,16 @@
|
|
3
3
|
|
4
4
|
== Summary
|
5
5
|
|
6
|
-
This class {SubObject} is the parent class for
|
6
|
+
This class {SubObject}[http://rubygems.org/gems/sub_object] is the parent class for
|
7
7
|
{SubString}[http://rubygems.org/gems/sub_string] and alike.
|
8
8
|
This class expresses Ruby sub-Object (like Sub-String),
|
9
|
-
which are obtained with the +self[i, j]+ method,
|
9
|
+
which are obtained with the +self[ i, j ]+ method,
|
10
10
|
but taking up negligible memory space, as its instance internally holds
|
11
11
|
the (likely positional, though arbitrary) information +(i, j)+ only. This class provides the base
|
12
12
|
interface so the instance behaves exactly like the original
|
13
13
|
class (String for SubString, for example) as duck-typing, except
|
14
|
-
destructive modification, which is prohibited.
|
14
|
+
destructive modification, which is prohibited. Also, as a bonus, an
|
15
|
+
arbitrary object can be associated with instances of this class with {SubObject#attr}.
|
15
16
|
|
16
17
|
If the original object (which an instance of this class refers to) is ever destructively modified in a way it changes
|
17
18
|
its hash value, warning will be issued whenever this instance is accessed.
|
@@ -30,7 +31,7 @@ SubString class) to suit your child class.
|
|
30
31
|
TO_SOURCE_METHOD = :to_str
|
31
32
|
alias_method TO_SOURCE_METHOD, :to_source
|
32
33
|
|
33
|
-
==
|
34
|
+
== Concept
|
34
35
|
|
35
36
|
This class takes three parameters in the initialization: *source*, *pos*
|
36
37
|
(position), and *size*. *source* is the original object, and
|
@@ -80,10 +81,10 @@ Therefore, whenever a destructive method is applied, this class tries
|
|
80
81
|
to raise NoMethodError exception. The routine to identify the
|
81
82
|
destructive method relies thoroughly on the method name.
|
82
83
|
The methods ending with "!" are regarded as destructive.
|
83
|
-
Other standard
|
84
|
+
Other standard destructive method names are defined in the constant {SubObject::DESTRUCTIVE_METHODS}.
|
84
85
|
Each child class may add entries or modify it.
|
85
86
|
|
86
|
-
Note that if a (likely user-defined)
|
87
|
+
Note that if a (likely user-defined) destructive method passes the check,
|
87
88
|
the result is most likely to be different from intended. It certainly
|
88
89
|
never alters this instance destructively (unless +[]+ method of the
|
89
90
|
source object returns self, which is against the Ruby convention), and
|
@@ -108,7 +109,7 @@ according to the length of the sub-String. Consider an example:
|
|
108
109
|
|
109
110
|
The variable +sub+ uses up about the same memory of +src+.
|
110
111
|
If a great number of +sub+ is created and held alive, the total memory
|
111
|
-
used by the process can become
|
112
|
+
used by the process can become quickly multifold, even by orders of magnitude.
|
112
113
|
|
113
114
|
This is where this class comes in handy. For example, a parsing
|
114
115
|
program applied to a huge text document with a complex grammar may
|
@@ -117,9 +118,12 @@ of String, it can save some valuable memory.
|
|
117
118
|
|
118
119
|
That is precisely why
|
119
120
|
{SubString}[http://rubygems.org/gems/sub_string],
|
120
|
-
which is a child class of this class and for String, is registered as
|
121
|
+
which is a child class of this class and for String, is registered as a separate official Gem.
|
121
122
|
(In practice, this class is a generalised version of *SubString*,
|
122
|
-
which Ruby allows
|
123
|
+
which Ruby allows, being a flexible programming language!)
|
124
|
+
|
125
|
+
Note this class also offers a function to associate an arbitrary
|
126
|
+
object with it with the setter and getter methods of {SubObject#attr=} and {SubObject#attr}.
|
123
127
|
|
124
128
|
== Description
|
125
129
|
|
@@ -127,12 +131,18 @@ which Ruby allows as a flexible programming language!)
|
|
127
131
|
|
128
132
|
Initialize as follows:
|
129
133
|
|
130
|
-
SubObject.new( source, index1, index2 )
|
134
|
+
SubObject.new( source, index1, index2, attr: your_object )
|
131
135
|
|
132
136
|
Usually, +index1+ is the starting index and +index2+ is the size,
|
133
137
|
though how they should be recognized depends on the definition of the method
|
134
138
|
+[i,j]+ of +source+.
|
135
139
|
|
140
|
+
+attr+ option is optional and to set an arbitrary object as an
|
141
|
+
instance variable. The default value is nil. It can be
|
142
|
+
reset any time later with the setter method of {SubObject#attr=}.
|
143
|
+
To store an arbitrary number of pieces of information, a Hash instance
|
144
|
+
would be convenient.
|
145
|
+
|
136
146
|
=== Constant
|
137
147
|
|
138
148
|
{SubObject::DESTRUCTIVE_METHODS}:: This public constant is the array holding the list of the names (as String) of the methods that should be recognized as destructive (other than those ending with "!").
|
@@ -141,27 +151,27 @@ though how they should be recognized depends on the definition of the method
|
|
141
151
|
The class variable +TO_SOURCE_METHOD+ is meant to be set by each
|
142
152
|
child class (and child classes only). For example, if it is the subclass for String, it should
|
143
153
|
be +:to_str+. Specifically, the registered method must respond to
|
144
|
-
+source[i,j]+.
|
154
|
+
+source[i,j]+. Note that in this class (parent class), it is **left unset**, but the (private) method of the
|
145
155
|
same name +to_original_method+ returns +:itself+ instead.
|
146
156
|
|
147
157
|
*WARNING*: Do not set this class variable in this class, as it could result in unexpected behaviours if
|
148
|
-
a child class and
|
158
|
+
a child class and this class (parent) are used simultaneously.
|
149
159
|
|
150
160
|
|
151
161
|
=== Class-global settings and class methods
|
152
162
|
|
153
163
|
When this class is accessed after any alteration of the original
|
154
|
-
source object has been detected, it may issue warning (as the
|
164
|
+
source object has been detected, it may issue warning (as the instance does not make sense any more).
|
155
165
|
The warning is suppressed when the Ruby global variable +$VERBOSE+ is
|
156
166
|
nil (it is false in Ruby default). Or, if the following setting is
|
157
|
-
made (
|
167
|
+
made (internally, it sets/reads a class instance variable) and set non-nil,
|
158
168
|
its value precedes +$VERBOSE+:
|
159
169
|
|
160
170
|
SubObject.verbose # => getter
|
161
171
|
SubObject.verbose=true # => setter
|
162
172
|
|
163
173
|
where SubObject should be replaced with the name of your child class that inherits {SubObject}.
|
164
|
-
If this value is true or false, such a warning is issued or
|
174
|
+
If this value is true or false, such a warning is issued or suppressed,
|
165
175
|
respectively, regardless of the value of the global variable +$VERBOSE+.
|
166
176
|
|
167
177
|
|
@@ -174,6 +184,8 @@ The following is the instance methods of {SubObject} unique to this class.
|
|
174
184
|
+#subsize()+:: Returns the third argument given in initialization (usually meaning the size of the sub-"source"). Usually this is equivalent to the method +#size+; this method is introduced in case the class of the +source+ somehow does not have the +#size+ method.
|
175
185
|
+#pos_size()+:: Returns the two-component array of +[pos, subsize]+
|
176
186
|
+#to_source()+:: Returns the instance as close as the original +source+ (the class of it, etc).
|
187
|
+
+#attr=()+:: Setter of the user-defined instance variable.
|
188
|
+
+#attr()+:: Getter of the user-defined instance variable. The default is nil.
|
177
189
|
|
178
190
|
In addition, {#inspect}[SubObject#inspect] is redefined.
|
179
191
|
|
@@ -201,7 +213,7 @@ Internally, almost any method that the instance receives, except for those speci
|
|
201
213
|
the following order:
|
202
214
|
|
203
215
|
1. {#method_missing}[SubObject#method_missing] (almost any methods except those defined in Object should be processed here)
|
204
|
-
1. +super+ if
|
216
|
+
1. +super+ if destructive (usually NoMethodError, because Object class does not have "destructive" methods, though you may argue +taint+ etc is "destructive")
|
205
217
|
2. Else, +send+ to {#to_source}[SubObject#to_source]
|
206
218
|
2. {#to_source}[SubObject#to_source]
|
207
219
|
1. check whether the original {#source}[SubObject#source] has been altered and issues a warning if the conditions are met.
|
data/lib/sub_object.rb
CHANGED
@@ -81,16 +81,17 @@ class SubObject
|
|
81
81
|
# Starting (character) position
|
82
82
|
attr_reader :pos
|
83
83
|
|
84
|
-
#
|
85
|
-
|
84
|
+
# Setter/Getter of the attribute. nil in default.
|
85
|
+
attr_accessor :attr
|
86
86
|
|
87
87
|
# Returns a new instance of SubObject equivalent to source[ pos, size ]
|
88
88
|
#
|
89
89
|
# @param source [String]
|
90
90
|
# @param pos [Integer]
|
91
91
|
# @param size [Integer]
|
92
|
-
def initialize(source, pos, size)
|
92
|
+
def initialize(source, pos, size, attr: nil)
|
93
93
|
@source, @pos, @isize = source, pos, size
|
94
|
+
@attr = attr
|
94
95
|
|
95
96
|
# Sanity check
|
96
97
|
begin
|
data/sub_object.gemspec
CHANGED
@@ -5,7 +5,7 @@ require 'date'
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = 'sub_object'.sub(/.*/){|c| (c == File.basename(Dir.pwd)) ? c : raise("ERROR: s.name=(#{c}) in gemspec seems wrong!")}
|
8
|
-
s.version = "1.
|
8
|
+
s.version = "1.1".sub(/.*/){|c| fs = Dir.glob('changelog{,.*}', File::FNM_CASEFOLD); raise('More than one ChangeLog exist!') if fs.size > 1; warn("WARNING: Version(s.version=#{c}) already exists in #{fs[0]} - ok?") if fs.size == 1 && !IO.readlines(fs[0]).grep(/^\(Version: #{Regexp.quote c}\)$/).empty? ; c } # n.b., In macOS, changelog and ChangeLog are identical in default.
|
9
9
|
# s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
10
10
|
# s.bindir = 'bin'
|
11
11
|
# %w(sub_object).each do |f|
|
@@ -13,7 +13,7 @@ Gem::Specification.new do |s|
|
|
13
13
|
# File.executable?(path) ? s.executables << f : raise("ERROR: Executable (#{path}) is not executable!")
|
14
14
|
# end
|
15
15
|
s.authors = ["Masa Sakano"]
|
16
|
-
s.date = %q{2019-11-
|
16
|
+
s.date = %q{2019-11-09}.sub(/.*/){|c| (Date.parse(c) == Date.today) ? c : raise("ERROR: s.date=(#{c}) is not today!")}
|
17
17
|
s.summary = %q{Parent class for memory-efficient sub-Something}
|
18
18
|
s.description = %q{Class SubObject that is the parent class for Ruby SubString and SubArray classes and alike, providing the base interface. This and child classes use negligible memory space, as their instance holds the positional information only. It behaves exactly like the source object (duck-typing), except destructive modification is prohibited. If the original source object is destructively altered, the corresponding instance can detect it and issue warning.}
|
19
19
|
# s.email = %q{abc@example.com}
|
data/test/test_sub_object.rb
CHANGED
@@ -101,6 +101,7 @@ class TestUnitSubObject < MiniTest::Test
|
|
101
101
|
assert_equal MyC.new(myo.x+2+3), obj.to_source
|
102
102
|
assert_equal "SubObject", obj.class.name
|
103
103
|
assert_equal "6", obj.to_s
|
104
|
+
assert_nil obj.attr
|
104
105
|
assert myo.respond_to?(:to_s)
|
105
106
|
assert obj.respond_to?(:to_s)
|
106
107
|
assert myo.respond_to?(:plus1)
|
@@ -173,6 +174,16 @@ class TestUnitSubObject < MiniTest::Test
|
|
173
174
|
}
|
174
175
|
}
|
175
176
|
exclu.join
|
177
|
+
|
178
|
+
# Tests of attr
|
179
|
+
myo = MyC.new(1)
|
180
|
+
obj = SubObject.new myo, 2, 3, attr: 5
|
181
|
+
assert_equal 5, obj.attr
|
182
|
+
hs = Hash[{ try: 67 }]
|
183
|
+
obj.attr = hs
|
184
|
+
assert_equal hs, obj.attr
|
185
|
+
obj.attr[:try] = 89
|
186
|
+
assert_equal 89, obj.attr[:try]
|
176
187
|
end
|
177
188
|
|
178
189
|
def test_sub_array01
|
@@ -184,6 +195,7 @@ class TestUnitSubObject < MiniTest::Test
|
|
184
195
|
assert_equal 2, obj.subsize
|
185
196
|
assert_equal [-3, 2], obj.pos_size
|
186
197
|
assert_equal ary[-3, 2], obj.to_source
|
198
|
+
assert_nil obj.attr
|
187
199
|
assert_equal :to_ary, SubObject::SubArray::TO_SOURCE_METHOD
|
188
200
|
assert_equal :itself, SubObject::TO_SOURCE_METHOD
|
189
201
|
assert_raises(TypeError){ SubObject::SubArray.new ary, -3, :a }
|
@@ -205,6 +217,16 @@ class TestUnitSubObject < MiniTest::Test
|
|
205
217
|
refute obj.respond_to?(:naiyo)
|
206
218
|
assert_raises(NoMethodError){ obj.push 5 }
|
207
219
|
assert_raises(NoMethodError){ obj.keep_if{} }
|
220
|
+
|
221
|
+
# Tests of attr
|
222
|
+
ary = [?a, ?b]
|
223
|
+
obj = SubObject::SubArray.new ary, -2, 1, attr: 5
|
224
|
+
assert_equal 5, obj.attr
|
225
|
+
hs = Hash[{ try: 67 }]
|
226
|
+
obj.attr = hs
|
227
|
+
assert_equal hs, obj.attr
|
228
|
+
obj.attr[:try] = 89
|
229
|
+
assert_equal 89, obj.attr[:try]
|
208
230
|
end
|
209
231
|
|
210
232
|
end # class TestUnitSubObject < MiniTest::Test
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sub_object
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: '1.1'
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Masa Sakano
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-11-
|
11
|
+
date: 2019-11-09 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: Class SubObject that is the parent class for Ruby SubString and SubArray
|
14
14
|
classes and alike, providing the base interface. This and child classes use negligible
|