external 0.1.0 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|