external 0.1.0 → 0.3.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/History +7 -0
- data/MIT-LICENSE +1 -3
- data/README +162 -127
- data/lib/external.rb +2 -3
- data/lib/external/base.rb +174 -47
- data/lib/external/chunkable.rb +131 -105
- data/lib/external/enumerable.rb +78 -33
- data/lib/external/io.rb +163 -398
- data/lib/external/patches/ruby_1_8_io.rb +31 -0
- data/lib/external/patches/windows_io.rb +53 -0
- data/lib/external/patches/windows_utils.rb +27 -0
- data/lib/external/utils.rb +148 -0
- data/lib/external_archive.rb +840 -0
- data/lib/external_array.rb +57 -0
- data/lib/external_index.rb +1053 -0
- metadata +42 -58
- data/lib/ext_arc.rb +0 -108
- data/lib/ext_arr.rb +0 -727
- data/lib/ext_ind.rb +0 -1120
- data/test/benchmarks/benchmarks_20070918.txt +0 -45
- data/test/benchmarks/benchmarks_20070921.txt +0 -91
- data/test/benchmarks/benchmarks_20071006.txt +0 -147
- data/test/benchmarks/test_copy_file.rb +0 -80
- data/test/benchmarks/test_pos_speed.rb +0 -47
- data/test/benchmarks/test_read_time.rb +0 -55
- data/test/cached_ext_ind_test.rb +0 -219
- data/test/check/benchmark_check.rb +0 -441
- data/test/check/namespace_conflicts_check.rb +0 -23
- data/test/check/pack_check.rb +0 -90
- data/test/ext_arc_test.rb +0 -286
- data/test/ext_arr/alt_sep.txt +0 -3
- data/test/ext_arr/cr_lf_input.txt +0 -3
- data/test/ext_arr/input.index +0 -0
- data/test/ext_arr/input.txt +0 -1
- data/test/ext_arr/inputb.index +0 -0
- data/test/ext_arr/inputb.txt +0 -1
- data/test/ext_arr/lf_input.txt +0 -3
- data/test/ext_arr/lines.txt +0 -19
- data/test/ext_arr/without_index.txt +0 -1
- data/test/ext_arr_test.rb +0 -534
- data/test/ext_ind_test.rb +0 -1472
- data/test/external/base_test.rb +0 -74
- data/test/external/chunkable_test.rb +0 -182
- data/test/external/index/input.index +0 -0
- data/test/external/index/inputb.index +0 -0
- data/test/external/io_test.rb +0 -414
- data/test/external_test_helper.rb +0 -31
- data/test/external_test_suite.rb +0 -4
- data/test/test_array.rb +0 -1192
metadata
CHANGED
@@ -1,84 +1,68 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: external
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Simon Chiang
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date:
|
12
|
+
date: 2008-09-27 00:00:00 -06:00
|
13
13
|
default_executable:
|
14
|
-
dependencies:
|
15
|
-
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: tap
|
17
|
+
type: :development
|
18
|
+
version_requirement:
|
19
|
+
version_requirements: !ruby/object:Gem::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ~>
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: 0.10.7
|
24
|
+
version:
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: mspec
|
27
|
+
type: :development
|
28
|
+
version_requirement:
|
29
|
+
version_requirements: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ~>
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 1.5.0
|
34
|
+
version:
|
16
35
|
description:
|
17
|
-
email: simon.chiang@
|
36
|
+
email: simon.a.chiang@gmail.com
|
18
37
|
executables: []
|
19
38
|
|
20
39
|
extensions: []
|
21
40
|
|
22
41
|
extra_rdoc_files:
|
23
|
-
- README
|
24
42
|
- MIT-LICENSE
|
43
|
+
- README
|
25
44
|
- History
|
26
45
|
files:
|
27
|
-
-
|
28
|
-
- test/benchmarks/benchmarks_20070918.txt
|
29
|
-
- test/benchmarks/benchmarks_20070921.txt
|
30
|
-
- test/benchmarks/benchmarks_20071006.txt
|
31
|
-
- test/benchmarks/test_copy_file.rb
|
32
|
-
- test/benchmarks/test_pos_speed.rb
|
33
|
-
- test/benchmarks/test_read_time.rb
|
34
|
-
- test/cached_ext_ind_test.rb
|
35
|
-
- test/check
|
36
|
-
- test/check/benchmark_check.rb
|
37
|
-
- test/check/namespace_conflicts_check.rb
|
38
|
-
- test/check/pack_check.rb
|
39
|
-
- test/ext_arc_test.rb
|
40
|
-
- test/ext_arr
|
41
|
-
- test/ext_arr/alt_sep.txt
|
42
|
-
- test/ext_arr/cr_lf_input.txt
|
43
|
-
- test/ext_arr/input.index
|
44
|
-
- test/ext_arr/input.txt
|
45
|
-
- test/ext_arr/inputb.index
|
46
|
-
- test/ext_arr/inputb.txt
|
47
|
-
- test/ext_arr/lf_input.txt
|
48
|
-
- test/ext_arr/lines.txt
|
49
|
-
- test/ext_arr/without_index.txt
|
50
|
-
- test/ext_arr_test.rb
|
51
|
-
- test/ext_ind_test.rb
|
52
|
-
- test/external
|
53
|
-
- test/external/base_test.rb
|
54
|
-
- test/external/chunkable_test.rb
|
55
|
-
- test/external/index
|
56
|
-
- test/external/index/input.index
|
57
|
-
- test/external/index/inputb.index
|
58
|
-
- test/external/io_test.rb
|
59
|
-
- test/external_test_helper.rb
|
60
|
-
- test/external_test_suite.rb
|
61
|
-
- test/test_array.rb
|
62
|
-
- lib/ext_arc.rb
|
63
|
-
- lib/ext_arr.rb
|
64
|
-
- lib/ext_ind.rb
|
65
|
-
- lib/external
|
46
|
+
- lib/external.rb
|
66
47
|
- lib/external/base.rb
|
67
48
|
- lib/external/chunkable.rb
|
68
49
|
- lib/external/enumerable.rb
|
69
50
|
- lib/external/io.rb
|
70
|
-
- lib/external.rb
|
71
|
-
-
|
51
|
+
- lib/external/patches/ruby_1_8_io.rb
|
52
|
+
- lib/external/patches/windows_io.rb
|
53
|
+
- lib/external/patches/windows_utils.rb
|
54
|
+
- lib/external/utils.rb
|
55
|
+
- lib/external_archive.rb
|
56
|
+
- lib/external_array.rb
|
57
|
+
- lib/external_index.rb
|
72
58
|
- MIT-LICENSE
|
59
|
+
- README
|
73
60
|
- History
|
74
61
|
has_rdoc: true
|
75
62
|
homepage: http://rubyforge.org/projects/external/
|
76
63
|
post_install_message:
|
77
|
-
rdoc_options:
|
78
|
-
|
79
|
-
- External
|
80
|
-
- --main
|
81
|
-
- README
|
64
|
+
rdoc_options: []
|
65
|
+
|
82
66
|
require_paths:
|
83
67
|
- lib
|
84
68
|
required_ruby_version: !ruby/object:Gem::Requirement
|
@@ -95,10 +79,10 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
95
79
|
version:
|
96
80
|
requirements: []
|
97
81
|
|
98
|
-
rubyforge_project:
|
99
|
-
rubygems_version:
|
82
|
+
rubyforge_project: external
|
83
|
+
rubygems_version: 1.2.0
|
100
84
|
signing_key:
|
101
85
|
specification_version: 2
|
102
|
-
summary:
|
103
|
-
test_files:
|
104
|
-
|
86
|
+
summary: array-like access to external data files
|
87
|
+
test_files: []
|
88
|
+
|
data/lib/ext_arc.rb
DELETED
@@ -1,108 +0,0 @@
|
|
1
|
-
require 'ext_arr'
|
2
|
-
require 'stringio'
|
3
|
-
require 'strscan'
|
4
|
-
|
5
|
-
class ExtArc < ExtArr
|
6
|
-
|
7
|
-
def str_to_entry(str)
|
8
|
-
str
|
9
|
-
end
|
10
|
-
|
11
|
-
def entry_to_str(entry)
|
12
|
-
entry.to_s
|
13
|
-
end
|
14
|
-
|
15
|
-
def reindex_by_scan(pattern=/\r?\n|$/)
|
16
|
-
index_format = index.format
|
17
|
-
reindex do |index|
|
18
|
-
io.scan do |scan_pos, string|
|
19
|
-
scanner = StringScanner.new(string)
|
20
|
-
while advanced = scanner.search_full(pattern, true, false)
|
21
|
-
break unless advanced > 0
|
22
|
-
|
23
|
-
index.unframed_write [scan_pos, advanced]
|
24
|
-
scan_pos += advanced
|
25
|
-
end
|
26
|
-
|
27
|
-
scanner.restsize
|
28
|
-
end
|
29
|
-
end
|
30
|
-
end
|
31
|
-
|
32
|
-
def reindex_by_sep(options={})
|
33
|
-
options = {
|
34
|
-
:sep_string => $/,
|
35
|
-
:entry_follows_sep => false,
|
36
|
-
:exclude_sep => false
|
37
|
-
}.merge(options)
|
38
|
-
|
39
|
-
sep_string = options[:sep_string]
|
40
|
-
entry_follows_sep = options[:entry_follows_sep]
|
41
|
-
exclude_sep = options[:exclude_sep]
|
42
|
-
sep_string_length = sep_string.length
|
43
|
-
|
44
|
-
reindex do |index|
|
45
|
-
current_pos = 0
|
46
|
-
entry_begin = 0
|
47
|
-
|
48
|
-
io_length = io.length
|
49
|
-
io.each_line(sep_string) do |line|
|
50
|
-
# Note positions MUST be built up using line.length
|
51
|
-
# io.pos cannot return positions greater than ~2.1e9
|
52
|
-
current_pos += line.length
|
53
|
-
entry_end = current_pos - (entry_follows_sep && current_pos != io_length ? 1 : 0)
|
54
|
-
|
55
|
-
unless entry_end == entry_begin
|
56
|
-
if exclude_sep
|
57
|
-
if entry_follows_sep
|
58
|
-
entry_begin += sep_string_length
|
59
|
-
else
|
60
|
-
entry_end -= sep_string_length
|
61
|
-
end
|
62
|
-
end
|
63
|
-
|
64
|
-
index.unframed_write [entry_begin, entry_end-entry_begin]
|
65
|
-
entry_begin = entry_end
|
66
|
-
end
|
67
|
-
end
|
68
|
-
end
|
69
|
-
end
|
70
|
-
|
71
|
-
def reindex_by_line(options={}) # :nodoc:
|
72
|
-
options = {
|
73
|
-
:sep_string => $/,
|
74
|
-
:break_before => false,
|
75
|
-
:exclude_break => false
|
76
|
-
}.merge(options)
|
77
|
-
|
78
|
-
sep_string = options[:sep_string]
|
79
|
-
break_before = options[:break_before]
|
80
|
-
exclude_break = options[:exclude_break]
|
81
|
-
|
82
|
-
reindex do |index|
|
83
|
-
last_pos = 0
|
84
|
-
current_pos = 0
|
85
|
-
range_begin = 0
|
86
|
-
|
87
|
-
io.each_line(sep_string) do |line|
|
88
|
-
# Note positions MUST be built up using line.length
|
89
|
-
# io.pos cannot return positions greater than ~2.1e9
|
90
|
-
last_pos = current_pos
|
91
|
-
current_pos += line.length
|
92
|
-
|
93
|
-
if (block_given? ? yield(line) : true)
|
94
|
-
range_end = (break_before || exclude_break) ? last_pos : current_pos
|
95
|
-
unless range_end == range_begin
|
96
|
-
index.unframed_write [range_begin, range_end-range_begin]
|
97
|
-
end
|
98
|
-
range_begin = (break_before && !exclude_break) ? last_pos : current_pos
|
99
|
-
end
|
100
|
-
end
|
101
|
-
|
102
|
-
range_end = current_pos
|
103
|
-
unless range_end == range_begin
|
104
|
-
index.unframed_write [range_begin, range_end-range_begin]
|
105
|
-
end
|
106
|
-
end
|
107
|
-
end
|
108
|
-
end
|
data/lib/ext_arr.rb
DELETED
@@ -1,727 +0,0 @@
|
|
1
|
-
require 'external/base'
|
2
|
-
require 'ext_ind'
|
3
|
-
require 'yaml'
|
4
|
-
|
5
|
-
#--
|
6
|
-
# later separate out individual objects logically
|
7
|
-
# If writing, create new files:
|
8
|
-
# - base/object_id.aio (new file for recieving appends)
|
9
|
-
# - base/object_id.index (copy of existing index -- made on first insertion)
|
10
|
-
# - in index, -index indicates object_id.aio file whereas +index indicates original file
|
11
|
-
# - .consolidate(rename) resolves changes in index into the object_id file, renaming as needed
|
12
|
-
# requires index rewrite as well, to remove negatives
|
13
|
-
#
|
14
|
-
# If appending, ONLY allow << and all changes get committed to the original file.
|
15
|
-
#
|
16
|
-
# This should allow returning of new arrayio objects under read/write conditions
|
17
|
-
# By default read-only. No insertions. New ExtArr objects inherit parent mode.
|
18
|
-
#
|
19
|
-
# Independent modes:
|
20
|
-
# - r
|
21
|
-
# - r+
|
22
|
-
# - For safety, w/w+ will by default act as r/r+, simply creating new .aio and .index files
|
23
|
-
# changes to the originals will NOT be made unless .consolidate(rename) is used. Allow option io_w => true
|
24
|
-
# - b ALWAYS on with Windows
|
25
|
-
#++
|
26
|
-
|
27
|
-
class ExtArr < External::Base
|
28
|
-
class << self
|
29
|
-
def [](*args)
|
30
|
-
ab = self.new
|
31
|
-
args.each do |arg|
|
32
|
-
ab[ab.length] = arg
|
33
|
-
end
|
34
|
-
ab
|
35
|
-
end
|
36
|
-
|
37
|
-
def default_index_options
|
38
|
-
{:format => 'II', :nil_value => [0,0], :cached => true}
|
39
|
-
end
|
40
|
-
|
41
|
-
def default_index_filepath(filepath)
|
42
|
-
filepath.chomp(File.extname(filepath)) + '.index'
|
43
|
-
end
|
44
|
-
end
|
45
|
-
|
46
|
-
attr_reader :index, :pos_index, :length_index
|
47
|
-
|
48
|
-
def initialize(io=nil, options={})
|
49
|
-
super(io)
|
50
|
-
|
51
|
-
@max_gap = 10000
|
52
|
-
@max_chunk_size = 1000000
|
53
|
-
|
54
|
-
@pos_index = options[:pos_index] == nil ? 0 : options[:pos_index]
|
55
|
-
@length_index = options[:length_index] == nil ? 1 : options[:length_index]
|
56
|
-
|
57
|
-
# TODO -- merge in specified index options
|
58
|
-
index_options = self.class.default_index_options
|
59
|
-
|
60
|
-
# determine the index file. if a file is specified,
|
61
|
-
# use it, otherwise infer the index filepath from
|
62
|
-
# the io. Note a nil index_file is ok -- this simply
|
63
|
-
# means the index file will be a Tempfile
|
64
|
-
index_file = if options.has_key?(:index_file)
|
65
|
-
options[:index_file]
|
66
|
-
elsif io.kind_of?(File)
|
67
|
-
self.class.default_index_filepath(io.path)
|
68
|
-
else
|
69
|
-
nil
|
70
|
-
end
|
71
|
-
|
72
|
-
# ensure the file exists before trying to open it
|
73
|
-
if io.kind_of?(File) && !File.exists?(index_file)
|
74
|
-
FileUtils.touch(index_file)
|
75
|
-
end
|
76
|
-
@index = ExtInd.open(index_file, "r+", index_options)
|
77
|
-
end
|
78
|
-
|
79
|
-
def closed?
|
80
|
-
super && (!index.respond_to?(:close) || index.closed?)
|
81
|
-
end
|
82
|
-
|
83
|
-
def close
|
84
|
-
super
|
85
|
-
index.close unless !index.respond_to?(:close) || index.closed?
|
86
|
-
end
|
87
|
-
|
88
|
-
def reindex
|
89
|
-
index.clear
|
90
|
-
io.flush unless io.generic_mode == "r"
|
91
|
-
io.rewind
|
92
|
-
|
93
|
-
if block_given?
|
94
|
-
yield(index)
|
95
|
-
else
|
96
|
-
current_pos = 0
|
97
|
-
entry_begin = 0
|
98
|
-
|
99
|
-
io_length = io.length
|
100
|
-
io.each_line('---') do |line|
|
101
|
-
# Note positions MUST be built up using line.length
|
102
|
-
# io.pos cannot return positions greater than ~2.1e9
|
103
|
-
current_pos += line.length
|
104
|
-
entry_end = current_pos - (current_pos == io_length ? 0 : 3)
|
105
|
-
|
106
|
-
unless entry_begin == entry_end
|
107
|
-
index.unframed_write [entry_begin, entry_end-entry_begin]
|
108
|
-
entry_begin = entry_end
|
109
|
-
end
|
110
|
-
end
|
111
|
-
end
|
112
|
-
self
|
113
|
-
end
|
114
|
-
|
115
|
-
def str_to_entry(str)
|
116
|
-
str == nil ? nil : YAML.load(str)
|
117
|
-
end
|
118
|
-
|
119
|
-
def entry_to_str(entry)
|
120
|
-
# could chop the beginning and end to save space
|
121
|
-
# (ie "--- blah\n" => "blah") but there would be
|
122
|
-
# a tradeoff for time. especially true for Numerics
|
123
|
-
# which don't need anything to be retranslated properly
|
124
|
-
entry.to_yaml
|
125
|
-
end
|
126
|
-
|
127
|
-
def entry_pos(index)
|
128
|
-
index[pos_index]
|
129
|
-
end
|
130
|
-
|
131
|
-
def entry_length(index)
|
132
|
-
index[length_index]
|
133
|
-
end
|
134
|
-
|
135
|
-
###########################
|
136
|
-
# Array methods
|
137
|
-
###########################
|
138
|
-
|
139
|
-
# def &(another)
|
140
|
-
# not_implemented
|
141
|
-
# end
|
142
|
-
|
143
|
-
# def *(arg)
|
144
|
-
# not_implemented
|
145
|
-
# end
|
146
|
-
|
147
|
-
def +(another)
|
148
|
-
self.concat(another)
|
149
|
-
end
|
150
|
-
|
151
|
-
# def -(another)
|
152
|
-
# not_implemented
|
153
|
-
# end
|
154
|
-
|
155
|
-
def <<(obj)
|
156
|
-
self[length] = obj
|
157
|
-
self
|
158
|
-
end
|
159
|
-
|
160
|
-
def <=>(another)
|
161
|
-
case another
|
162
|
-
when Array
|
163
|
-
if another.length < self.length
|
164
|
-
# if another is equal to the matching subset of self,
|
165
|
-
# then self is obviously the longer array and wins.
|
166
|
-
result = (self.to_a(another.length) <=> another)
|
167
|
-
result == 0 ? 1 : result
|
168
|
-
else
|
169
|
-
self.to_a <=> another
|
170
|
-
end
|
171
|
-
when ExtArr
|
172
|
-
# if indexes are equal, additional
|
173
|
-
# 'quick' comparisons are allowed
|
174
|
-
if self.index == another.index
|
175
|
-
|
176
|
-
# equal in comparison if the ios are equal
|
177
|
-
return 0 if self.io.quick_compare(another.io)
|
178
|
-
end
|
179
|
-
|
180
|
-
self.io.flush
|
181
|
-
another.io.flush
|
182
|
-
|
183
|
-
# should chunk compare
|
184
|
-
if another.length > self.length
|
185
|
-
result = (self.to_a <=> another.to_a(self.length))
|
186
|
-
result == 0 ? -1 : result
|
187
|
-
elsif another.length < self.length
|
188
|
-
result = (self.to_a(another.length) <=> another.to_a)
|
189
|
-
result == 0 ? 1 : result
|
190
|
-
else
|
191
|
-
self.to_a <=> another.to_a
|
192
|
-
end
|
193
|
-
else
|
194
|
-
raise TypeError.new("can't convert from #{another.class} to ExtArr or Array")
|
195
|
-
end
|
196
|
-
end
|
197
|
-
|
198
|
-
def ==(another)
|
199
|
-
case another
|
200
|
-
when Array
|
201
|
-
# test simply based on length
|
202
|
-
return false unless self.length == another.length
|
203
|
-
|
204
|
-
# compare arrays
|
205
|
-
self.to_a == another
|
206
|
-
|
207
|
-
when ExtArr
|
208
|
-
# test simply based on length
|
209
|
-
return false unless self.length == another.length
|
210
|
-
|
211
|
-
# if indexes are equal, additional
|
212
|
-
# 'quick' comparisons are allowed
|
213
|
-
if self.index == another.index
|
214
|
-
|
215
|
-
# equal in comparison if the ios are equal
|
216
|
-
return true if (self.io.sort_compare(another.io, (self.index.buffer_size/2).ceil)) == 0
|
217
|
-
end
|
218
|
-
|
219
|
-
# compare arrays
|
220
|
-
self.to_a == another.to_a
|
221
|
-
else
|
222
|
-
false
|
223
|
-
end
|
224
|
-
end
|
225
|
-
|
226
|
-
def [](input, length=nil)
|
227
|
-
# two call types are required because while ExtInd can take
|
228
|
-
# a nil length, Array cannot and index can be either
|
229
|
-
entries = (length == nil ? index[input] : index[input, length])
|
230
|
-
|
231
|
-
# for conformance with array range retrieval
|
232
|
-
return entries if entries.nil? || entries.empty?
|
233
|
-
|
234
|
-
if length == nil && !input.kind_of?(Range)
|
235
|
-
pos, length =
|
236
|
-
|
237
|
-
# single entry, just read it
|
238
|
-
io.pos = entry_pos(entries)
|
239
|
-
str_to_entry( io.read(entry_length(entries)) )
|
240
|
-
else
|
241
|
-
pos = nil
|
242
|
-
entries.collect do |entry|
|
243
|
-
|
244
|
-
# only set io position if necessary
|
245
|
-
epos = entry_pos(entry)
|
246
|
-
unless pos == epos
|
247
|
-
pos = epos
|
248
|
-
io.pos = pos
|
249
|
-
end
|
250
|
-
|
251
|
-
elen = entry_length(entry)
|
252
|
-
pos += elen
|
253
|
-
|
254
|
-
# read entry
|
255
|
-
str_to_entry( io.read(elen) )
|
256
|
-
end
|
257
|
-
end
|
258
|
-
end
|
259
|
-
|
260
|
-
def []=(*args)
|
261
|
-
raise ArgumentError.new("wrong number of arguments (1 for 2)") if args.length < 2
|
262
|
-
index, length, value = args
|
263
|
-
value = length if args.length == 2
|
264
|
-
|
265
|
-
if index.kind_of?(Range)
|
266
|
-
raise TypeError.new("can't convert Range into Integer") if args.length == 3
|
267
|
-
# for conformance with setting a range with nil (truncates)
|
268
|
-
value = [] if value.nil?
|
269
|
-
offset, length = split_range(index)
|
270
|
-
return (self[offset, length + 1] = value)
|
271
|
-
end
|
272
|
-
|
273
|
-
index += self.length if index < 0
|
274
|
-
raise IndexError.new("index #{index} out of range") if index < 0
|
275
|
-
|
276
|
-
entry_pos = self.io.length
|
277
|
-
io.pos = entry_pos
|
278
|
-
|
279
|
-
if args.length == 2
|
280
|
-
|
281
|
-
#value = self.to_a if value.kind_of?(ExtInd)
|
282
|
-
|
283
|
-
# write entry to io first as a check
|
284
|
-
# that io is open for writing.
|
285
|
-
entry_length = io.write( entry_to_str(value) )
|
286
|
-
io.length += entry_length
|
287
|
-
|
288
|
-
self.index[index] = [entry_pos, entry_length]
|
289
|
-
|
290
|
-
else
|
291
|
-
indicies = []
|
292
|
-
|
293
|
-
values = case value
|
294
|
-
when Array then value
|
295
|
-
when ExtArr
|
296
|
-
if value.object_id == self.object_id
|
297
|
-
# special case, self will be reading and
|
298
|
-
# writing from the same io, producing
|
299
|
-
# incorrect results
|
300
|
-
|
301
|
-
# potential to load a huge amount of data
|
302
|
-
self.to_a
|
303
|
-
else
|
304
|
-
value
|
305
|
-
end
|
306
|
-
else
|
307
|
-
[value]
|
308
|
-
end
|
309
|
-
|
310
|
-
values.each do |value|
|
311
|
-
entry_length = io.write( entry_to_str(value) )
|
312
|
-
indicies << [entry_pos, entry_length]
|
313
|
-
|
314
|
-
io.length += entry_length
|
315
|
-
entry_pos += entry_length
|
316
|
-
end
|
317
|
-
|
318
|
-
self.index[index, length] = indicies
|
319
|
-
end
|
320
|
-
end
|
321
|
-
|
322
|
-
# def abbrev(pattern=nil)
|
323
|
-
# not_implemented
|
324
|
-
# end
|
325
|
-
|
326
|
-
# def assoc(obj)
|
327
|
-
# not_implemented
|
328
|
-
# end
|
329
|
-
|
330
|
-
# Returns entry at index
|
331
|
-
def at(index)
|
332
|
-
self[index]
|
333
|
-
end
|
334
|
-
|
335
|
-
# Removes all elements from _self_.
|
336
|
-
def clear
|
337
|
-
io.truncate(0)
|
338
|
-
index.clear
|
339
|
-
self
|
340
|
-
end
|
341
|
-
|
342
|
-
# def compact
|
343
|
-
# not_implemented
|
344
|
-
# end
|
345
|
-
|
346
|
-
# def compact!
|
347
|
-
# not_implemented
|
348
|
-
# end
|
349
|
-
|
350
|
-
def concat(another)
|
351
|
-
case another
|
352
|
-
when Array, ExtArr
|
353
|
-
another.each {|item| self[length] = item }
|
354
|
-
else
|
355
|
-
raise TypeError.new("can't convert #{another.class} into ExtArr or Array")
|
356
|
-
end
|
357
|
-
self
|
358
|
-
end
|
359
|
-
|
360
|
-
# def dclone
|
361
|
-
# not_implemented
|
362
|
-
# end
|
363
|
-
|
364
|
-
# def delete(obj)
|
365
|
-
# not_implemented
|
366
|
-
# end
|
367
|
-
|
368
|
-
# def delete_at(index)
|
369
|
-
# not_implemented
|
370
|
-
# end
|
371
|
-
|
372
|
-
# def delete_if # :yield: item
|
373
|
-
# not_implemented
|
374
|
-
# end
|
375
|
-
|
376
|
-
def each(&block) # :yield: item
|
377
|
-
pos = nil
|
378
|
-
index.each do |entry|
|
379
|
-
# only set io position if necessary
|
380
|
-
unless pos == entry[pos_index]
|
381
|
-
pos = entry[pos_index]
|
382
|
-
io.pos = pos
|
383
|
-
end
|
384
|
-
|
385
|
-
pos += entry[length_index]
|
386
|
-
|
387
|
-
# yield entry
|
388
|
-
yield str_to_entry( io.read(entry[length_index]) )
|
389
|
-
end
|
390
|
-
self
|
391
|
-
end
|
392
|
-
|
393
|
-
#
|
394
|
-
def each_index(&block) # :yield: index
|
395
|
-
0.upto(length-1, &block)
|
396
|
-
self
|
397
|
-
end
|
398
|
-
|
399
|
-
# Returns true if _self_ contains no elements
|
400
|
-
def empty?
|
401
|
-
length == 0
|
402
|
-
end
|
403
|
-
|
404
|
-
def eql?(another)
|
405
|
-
self == another
|
406
|
-
end
|
407
|
-
|
408
|
-
# def fetch(index, default=nil, &block)
|
409
|
-
# index += index_length if index < 0
|
410
|
-
# val = (index >= length ? default : self[index])
|
411
|
-
# block_given? ? yield(val) : val
|
412
|
-
# end
|
413
|
-
#
|
414
|
-
# def fill(*args)
|
415
|
-
# not_implemented
|
416
|
-
# end
|
417
|
-
|
418
|
-
# Returns the first n entries (default 1)
|
419
|
-
def first(n=nil)
|
420
|
-
n.nil? ? self[0] : self[0,n]
|
421
|
-
end
|
422
|
-
|
423
|
-
# def flatten
|
424
|
-
# not_implemented
|
425
|
-
# end
|
426
|
-
|
427
|
-
# def flatten!
|
428
|
-
# not_implemented
|
429
|
-
# end
|
430
|
-
|
431
|
-
# def frozen?
|
432
|
-
# not_implemented
|
433
|
-
# end
|
434
|
-
|
435
|
-
# def hash
|
436
|
-
# not_implemented
|
437
|
-
# end
|
438
|
-
|
439
|
-
# def include?(obj)
|
440
|
-
# not_implemented
|
441
|
-
# end
|
442
|
-
|
443
|
-
# def index(obj)
|
444
|
-
# not_implemented
|
445
|
-
# end
|
446
|
-
#
|
447
|
-
# def indexes(*args)
|
448
|
-
# values_at(*args)
|
449
|
-
# end
|
450
|
-
#
|
451
|
-
# def indicies(*args)
|
452
|
-
# values_at(*args)
|
453
|
-
# end
|
454
|
-
|
455
|
-
# def replace(other)
|
456
|
-
# not_implemented
|
457
|
-
# end
|
458
|
-
|
459
|
-
# def insert(index, *obj)
|
460
|
-
# self[index] = obj
|
461
|
-
# end
|
462
|
-
|
463
|
-
# def inspect
|
464
|
-
# not_implemented
|
465
|
-
# end
|
466
|
-
|
467
|
-
# def join(sep=$,)
|
468
|
-
# not_implemented
|
469
|
-
# end
|
470
|
-
|
471
|
-
# Returns the last n entries (default 1)
|
472
|
-
def last(n=nil)
|
473
|
-
return self[-1] if n.nil?
|
474
|
-
|
475
|
-
start = length-n
|
476
|
-
start = 0 if start < 0
|
477
|
-
self[start, n]
|
478
|
-
end
|
479
|
-
|
480
|
-
# Returns the number of entries in self
|
481
|
-
def length
|
482
|
-
index.length
|
483
|
-
end
|
484
|
-
|
485
|
-
# def nitems
|
486
|
-
# not_implemented
|
487
|
-
# end
|
488
|
-
|
489
|
-
# def pack(aTemplateString)
|
490
|
-
# not_implemented
|
491
|
-
# end
|
492
|
-
|
493
|
-
# def pop
|
494
|
-
# not_implemented
|
495
|
-
# end
|
496
|
-
|
497
|
-
# def pretty_print(q)
|
498
|
-
# not_implemented
|
499
|
-
# end
|
500
|
-
|
501
|
-
# def pretty_print_cycle(q)
|
502
|
-
# not_implemented
|
503
|
-
# end
|
504
|
-
|
505
|
-
# def push(*obj)
|
506
|
-
# not_implemented
|
507
|
-
# end
|
508
|
-
|
509
|
-
# def quote
|
510
|
-
# not_implemented
|
511
|
-
# end
|
512
|
-
|
513
|
-
# def rassoc(key)
|
514
|
-
# not_implemented
|
515
|
-
# end
|
516
|
-
|
517
|
-
# def replace(another)
|
518
|
-
# not_implemented
|
519
|
-
# end
|
520
|
-
|
521
|
-
# def reverse
|
522
|
-
# not_implemented
|
523
|
-
# end
|
524
|
-
|
525
|
-
# def reverse!
|
526
|
-
# not_implemented
|
527
|
-
# end
|
528
|
-
|
529
|
-
# def reverse_each(&block)
|
530
|
-
# reverse_chunk do |offset, length|
|
531
|
-
# self[offset, length].reverse_each(&block)
|
532
|
-
# end
|
533
|
-
# end
|
534
|
-
|
535
|
-
# def rindex(obj)
|
536
|
-
# not_implemented
|
537
|
-
# end
|
538
|
-
|
539
|
-
# def select # :yield: item
|
540
|
-
# not_implemented
|
541
|
-
# end
|
542
|
-
|
543
|
-
# def shift
|
544
|
-
# not_implemented
|
545
|
-
# end
|
546
|
-
|
547
|
-
# Alias for length
|
548
|
-
def size
|
549
|
-
length
|
550
|
-
end
|
551
|
-
|
552
|
-
# def slice(*args)
|
553
|
-
# self.call(:[], *args)
|
554
|
-
# end
|
555
|
-
|
556
|
-
# def slice!(*args)
|
557
|
-
# not_implemented
|
558
|
-
# end
|
559
|
-
|
560
|
-
def to_a(length=self.length)
|
561
|
-
length == 0 ? [] : self[0, length]
|
562
|
-
end
|
563
|
-
|
564
|
-
# def to_ary
|
565
|
-
# not_implemented
|
566
|
-
# end
|
567
|
-
|
568
|
-
# Returns _self_.join.
|
569
|
-
# def to_s
|
570
|
-
# self.join
|
571
|
-
# end
|
572
|
-
|
573
|
-
# def to_yaml(opts={})
|
574
|
-
# self[0, self.length].to_yaml(opts)
|
575
|
-
# end
|
576
|
-
|
577
|
-
# def transpose
|
578
|
-
# not_implemented
|
579
|
-
# end
|
580
|
-
|
581
|
-
# def uniq
|
582
|
-
# not_implemented
|
583
|
-
# end
|
584
|
-
|
585
|
-
# def uniq!
|
586
|
-
# not_implemented
|
587
|
-
# end
|
588
|
-
|
589
|
-
# def unshift(*obj)
|
590
|
-
# not_implemented
|
591
|
-
# end
|
592
|
-
|
593
|
-
# Returns an array containing the chars in io corresponding to the given
|
594
|
-
# selector(s). The selectors may be either integer indices or ranges
|
595
|
-
# def values_at(*selectors)
|
596
|
-
# selectors.collect {|s| self[s]}.flatten
|
597
|
-
# end
|
598
|
-
|
599
|
-
# def yaml_initialize(tag, val)
|
600
|
-
# not_implemented
|
601
|
-
# end
|
602
|
-
|
603
|
-
# def |(another)
|
604
|
-
# not_implemented
|
605
|
-
# end
|
606
|
-
end
|
607
|
-
|
608
|
-
# class Hold # :nodoc:
|
609
|
-
#
|
610
|
-
#
|
611
|
-
# #
|
612
|
-
# # def each_with_slice(&block)
|
613
|
-
# # index.each do |slice|
|
614
|
-
# # yield( read(slice), slice )
|
615
|
-
# # end
|
616
|
-
# # end
|
617
|
-
#
|
618
|
-
#
|
619
|
-
# def scan_collect(indicies=index, &block)
|
620
|
-
# return indicies if indicies.nil? || indicies.empty?
|
621
|
-
#
|
622
|
-
# collection = []
|
623
|
-
# span(*indicies) do |offset, length, spans|
|
624
|
-
# io.pos = offset
|
625
|
-
# scanner = StringScanner.new(io.read(length))
|
626
|
-
#
|
627
|
-
# spans.collect {|i| indicies[i]}.each do |span|
|
628
|
-
# soffset, slength = span
|
629
|
-
# sbegin = soffset - offset
|
630
|
-
# send = sbegin + slength
|
631
|
-
#
|
632
|
-
# scanner.pos = sbegin
|
633
|
-
# collection << yield(scanner, offset, span)
|
634
|
-
# raise "Oops! Scanned beyond end [begin, end, index]: #{[sbegin, send, span]}" if scanner.pos > send
|
635
|
-
# end
|
636
|
-
# end
|
637
|
-
# collection
|
638
|
-
# end
|
639
|
-
#
|
640
|
-
#
|
641
|
-
#
|
642
|
-
#
|
643
|
-
#
|
644
|
-
# # def set_modes(mode)
|
645
|
-
# # @uncached = parse_mode(mode, 'u')
|
646
|
-
# # end
|
647
|
-
# #
|
648
|
-
# # def parse_mode(mode, let)
|
649
|
-
# # if mode =~ Regexp.new(let, Regexp::IGNORECASE)
|
650
|
-
# # mode.delete!(let)
|
651
|
-
# # true
|
652
|
-
# # else
|
653
|
-
# # false
|
654
|
-
# # end
|
655
|
-
# # end
|
656
|
-
#
|
657
|
-
# #def default_span
|
658
|
-
# # use this rather than io.length because for very large io, io.length is prone to errors
|
659
|
-
# # last = index.last
|
660
|
-
# # [0, last.first + last.last]
|
661
|
-
# #end
|
662
|
-
#
|
663
|
-
# # def io_fetch(index, length)
|
664
|
-
# # io.pos = index unless io.pos = index
|
665
|
-
# #
|
666
|
-
# # if length.nil?
|
667
|
-
# # io.read(1)
|
668
|
-
# # else
|
669
|
-
# # results = []
|
670
|
-
# # str = io.read(length)
|
671
|
-
# # str.each_char {|c| results << c} if str
|
672
|
-
# # results
|
673
|
-
# # end
|
674
|
-
# # end
|
675
|
-
# #
|
676
|
-
# # # MUST increment io length to the end position if it writes past io.length
|
677
|
-
# # def io_store(index, value)
|
678
|
-
# # io.pos = index unless io.pos = index
|
679
|
-
# # end_pos = index + io.write(value)
|
680
|
-
# # io.length = end_pos if end_pos > io.length
|
681
|
-
# # end
|
682
|
-
#
|
683
|
-
# def index=(index)
|
684
|
-
# @index.close if @index.respond_to?(:close)
|
685
|
-
#
|
686
|
-
# # cache the index if specified
|
687
|
-
# @index = if cached?
|
688
|
-
# # if in cached mode, transform
|
689
|
-
#
|
690
|
-
# case index
|
691
|
-
# when Array then index
|
692
|
-
# when ExtInd
|
693
|
-
# cached_index = index.read(nil, 0)
|
694
|
-
# index.close
|
695
|
-
# cached_index
|
696
|
-
# when nil
|
697
|
-
# if io.respond_to?(:path)
|
698
|
-
# index_file = self.class.default_index_filepath(io.path)
|
699
|
-
# ExtInd.read(index_file, index_options)
|
700
|
-
# else
|
701
|
-
# []
|
702
|
-
# end
|
703
|
-
# else
|
704
|
-
# raise "unknown index type: #{index}"
|
705
|
-
# end
|
706
|
-
# else
|
707
|
-
# case index
|
708
|
-
# when Array
|
709
|
-
# uncached_index = ExtInd.new(nil, index_options)
|
710
|
-
# uncached_index.write(index)
|
711
|
-
# uncached_index
|
712
|
-
# when ExtInd then index
|
713
|
-
# when nil
|
714
|
-
# if io.respond_to?(:path)
|
715
|
-
# index_file = self.class.default_index_filepath(io.path)
|
716
|
-
# ExtInd.open(index_file, index_options)
|
717
|
-
# else
|
718
|
-
# ExtInd.new(nil, index_options)
|
719
|
-
# end
|
720
|
-
# else
|
721
|
-
# raise "unknown index type: #{index}"
|
722
|
-
# end
|
723
|
-
# end
|
724
|
-
#
|
725
|
-
#
|
726
|
-
# end
|
727
|
-
# end
|