virtfs 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +18 -0
- data/.rspec +2 -0
- data/.travis.yml +8 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +154 -0
- data/Rakefile +5 -0
- data/lib/virtfs-nativefs-thick.rb +1 -0
- data/lib/virtfs-nativefs-thin.rb +1 -0
- data/lib/virtfs.rb +38 -0
- data/lib/virtfs/activation.rb +97 -0
- data/lib/virtfs/block_io.rb +140 -0
- data/lib/virtfs/byte_range.rb +71 -0
- data/lib/virtfs/context.rb +300 -0
- data/lib/virtfs/context_manager.rb +175 -0
- data/lib/virtfs/context_switch_class_methods.rb +96 -0
- data/lib/virtfs/delegate_module.rb +40 -0
- data/lib/virtfs/dir_instance_delegate.rb +3 -0
- data/lib/virtfs/exception.rb +13 -0
- data/lib/virtfs/file_instance_delegate.rb +3 -0
- data/lib/virtfs/file_modes_and_options.rb +293 -0
- data/lib/virtfs/find_class_methods.rb +106 -0
- data/lib/virtfs/io_buffer.rb +133 -0
- data/lib/virtfs/io_instance_delegate.rb +3 -0
- data/lib/virtfs/kernel.rb +146 -0
- data/lib/virtfs/nativefs/thick.rb +30 -0
- data/lib/virtfs/nativefs/thick/dir_class_methods.rb +38 -0
- data/lib/virtfs/nativefs/thick/file_class_methods.rb +178 -0
- data/lib/virtfs/nativefs/thin.rb +32 -0
- data/lib/virtfs/nativefs/thin/dir.rb +30 -0
- data/lib/virtfs/nativefs/thin/dir_class_methods.rb +41 -0
- data/lib/virtfs/nativefs/thin/file.rb +112 -0
- data/lib/virtfs/nativefs/thin/file_class_methods.rb +181 -0
- data/lib/virtfs/protofs/protofs.rb +7 -0
- data/lib/virtfs/protofs/protofs_base.rb +12 -0
- data/lib/virtfs/protofs/protofs_dir.rb +13 -0
- data/lib/virtfs/protofs/protofs_dir_class.rb +31 -0
- data/lib/virtfs/protofs/protofs_file.rb +27 -0
- data/lib/virtfs/protofs/protofs_file_class.rb +136 -0
- data/lib/virtfs/stat.rb +100 -0
- data/lib/virtfs/thin_dir_delegator.rb +79 -0
- data/lib/virtfs/thin_file_delegator.rb +77 -0
- data/lib/virtfs/thin_io_delegator_methods.rb +301 -0
- data/lib/virtfs/thin_io_delegator_methods_bufferio.rb +337 -0
- data/lib/virtfs/v_dir.rb +238 -0
- data/lib/virtfs/v_file.rb +480 -0
- data/lib/virtfs/v_io.rb +243 -0
- data/lib/virtfs/v_pathname.rb +128 -0
- data/lib/virtfs/version.rb +3 -0
- data/spec/activate_spec.rb +202 -0
- data/spec/chroot_spec.rb +120 -0
- data/spec/context_manager_class_spec.rb +246 -0
- data/spec/context_manager_instance_spec.rb +255 -0
- data/spec/context_spec.rb +335 -0
- data/spec/data/UTF-16LE-data.txt +0 -0
- data/spec/data/UTF-8-data.txt +212 -0
- data/spec/dir_class_spec.rb +506 -0
- data/spec/dir_instance_spec.rb +208 -0
- data/spec/file_class_spec.rb +2106 -0
- data/spec/file_instance_spec.rb +154 -0
- data/spec/file_modes_and_options_spec.rb +1556 -0
- data/spec/find_spec.rb +142 -0
- data/spec/io_bufferio_size_shared_examples.rb +371 -0
- data/spec/io_bufferio_size_spec.rb +861 -0
- data/spec/io_bufferio_spec.rb +801 -0
- data/spec/io_class_spec.rb +145 -0
- data/spec/io_instance_spec.rb +516 -0
- data/spec/kernel_spec.rb +285 -0
- data/spec/mount_spec.rb +186 -0
- data/spec/nativefs_local_root_spec.rb +132 -0
- data/spec/path_spec.rb +39 -0
- data/spec/spec_helper.rb +126 -0
- data/tasks/rspec.rake +3 -0
- data/tasks/yard.rake +7 -0
- data/test/UTF-8-demo.txt +212 -0
- data/test/bench.rb +18 -0
- data/test/bio_internal_test.rb +45 -0
- data/test/delegate_io.rb +31 -0
- data/test/delegate_module.rb +62 -0
- data/test/encode_test.rb +42 -0
- data/test/enoent_test.rb +30 -0
- data/test/namespace_test.rb +42 -0
- data/test/read_block_valid_encoding.rb +44 -0
- data/test/read_test.rb +78 -0
- data/test/stream_readers.rb +46 -0
- data/test/utf-16-demo.txt +0 -0
- data/test/utf8_to_utf16.rb +77 -0
- data/test/wrapper_test.rb +34 -0
- data/virtfs.gemspec +29 -0
- metadata +230 -0
data/test/bench.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
big_string = "0123456789" * 1000
|
2
|
+
big_string.force_encoding("ASCII-8BIT")
|
3
|
+
|
4
|
+
t0 = Time.now
|
5
|
+
(0...2_000_000).each do
|
6
|
+
s = big_string.dup
|
7
|
+
s[-1] = ""
|
8
|
+
end
|
9
|
+
t1 = Time.now
|
10
|
+
puts "Index: #{t1 - t0} seconds"
|
11
|
+
|
12
|
+
t0 = Time.now
|
13
|
+
(0...2_000_000).each do
|
14
|
+
s = big_string.dup
|
15
|
+
s.chop!
|
16
|
+
end
|
17
|
+
t1 = Time.now
|
18
|
+
puts "chop!: #{t1 - t0} seconds"
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require "../lib/virtfs"
|
2
|
+
require "tempfile"
|
3
|
+
|
4
|
+
begin
|
5
|
+
@start_marker = "START OF FILE:\n"
|
6
|
+
@end_marker = ":END OF FILE"
|
7
|
+
@data1 = "0123456789"
|
8
|
+
@data2 = "abcdefghijklmnopqrstuvwxyz\n"
|
9
|
+
|
10
|
+
@temp_file = Tempfile.new("VirtFS-IO")
|
11
|
+
@temp_file.write(@start_marker)
|
12
|
+
(0..9).each do
|
13
|
+
@temp_file.write(@data1)
|
14
|
+
@temp_file.write(@data2)
|
15
|
+
end
|
16
|
+
@temp_file.write(@end_marker)
|
17
|
+
@temp_file.close
|
18
|
+
|
19
|
+
@full_path = @temp_file.path
|
20
|
+
@rel_path = File.basename(@full_path)
|
21
|
+
@parent_dir = File.dirname(@full_path)
|
22
|
+
@file_size = VfsRealFile.size(@full_path)
|
23
|
+
|
24
|
+
@utf_8_filename = VfsRealFile.join(__dir__, "UTF-8-demo.txt")
|
25
|
+
|
26
|
+
require "../lib/nativefs"
|
27
|
+
@root = File::SEPARATOR
|
28
|
+
@native_fs = NativeFS.new
|
29
|
+
VirtFS.mount(@native_fs, @root)
|
30
|
+
|
31
|
+
@vfile_read_obj = VirtFS::VFile.new(@full_path, "r:UTF-8")
|
32
|
+
@vfile_read_obj.send(:min_read_buf_sz=, 1)
|
33
|
+
range = @vfile_read_obj.read_buffer.range
|
34
|
+
|
35
|
+
puts "pos = #{@vfile_read_obj.pos}, Range(#{range.first}, #{range.end})"
|
36
|
+
|
37
|
+
char = "X"
|
38
|
+
@vfile_read_obj.ungetc(char)
|
39
|
+
puts "pos = #{@vfile_read_obj.pos}, Range(#{range.first}, #{range.end})"
|
40
|
+
@vfile_read_obj.getc
|
41
|
+
|
42
|
+
rescue => err
|
43
|
+
puts err.to_s
|
44
|
+
puts err.backtrace.join("\n")
|
45
|
+
end
|
data/test/delegate_io.rb
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
require "delegate"
|
2
|
+
|
3
|
+
begin
|
4
|
+
|
5
|
+
class MyFile < DelegateClass(::File)
|
6
|
+
SUPER_CLASSES = [File, IO]
|
7
|
+
|
8
|
+
def initialize(*args)
|
9
|
+
fobj = ::File.new(*args)
|
10
|
+
super(fobj)
|
11
|
+
end
|
12
|
+
|
13
|
+
def is_a?(klass)
|
14
|
+
super(klass) || SUPER_CLASSES.include?(klass)
|
15
|
+
end
|
16
|
+
alias_method :kind_of?, :is_a?
|
17
|
+
end
|
18
|
+
|
19
|
+
f = MyFile.new(__FILE__, "r")
|
20
|
+
|
21
|
+
puts "f.is_a?(File) = #{f.is_a?(File)}"
|
22
|
+
puts "f.is_a?(IO) = #{f.is_a?(IO)}"
|
23
|
+
puts "f.is_a?(MyFile) = #{f.is_a?(MyFile)}"
|
24
|
+
puts "f.is_a?(String) = #{f.is_a?(String)}"
|
25
|
+
|
26
|
+
f.close
|
27
|
+
|
28
|
+
rescue => err
|
29
|
+
puts err.to_s
|
30
|
+
puts err.backtrace.join("\n")
|
31
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
require "delegate"
|
2
|
+
|
3
|
+
begin
|
4
|
+
|
5
|
+
def DelegateModule(superclass)
|
6
|
+
klass = Module.new
|
7
|
+
methods = superclass.instance_methods
|
8
|
+
methods -= ::Delegator.public_api
|
9
|
+
methods -= [:to_s,:inspect,:=~,:!~,:===]
|
10
|
+
klass.module_eval do
|
11
|
+
def __getobj__ # :nodoc:
|
12
|
+
unless defined?(@delegate_dc_obj)
|
13
|
+
return yield if block_given?
|
14
|
+
__raise__ ::ArgumentError, "not delegated"
|
15
|
+
end
|
16
|
+
@delegate_dc_obj
|
17
|
+
end
|
18
|
+
def __setobj__(obj) # :nodoc:
|
19
|
+
__raise__ ::ArgumentError, "cannot delegate to self" if self.equal?(obj)
|
20
|
+
@delegate_dc_obj = obj
|
21
|
+
end
|
22
|
+
methods.each do |method|
|
23
|
+
define_method(method, Delegator.delegating_block(method))
|
24
|
+
end
|
25
|
+
end
|
26
|
+
klass.define_singleton_method :public_instance_methods do |all=true|
|
27
|
+
super(all) - superclass.protected_instance_methods
|
28
|
+
end
|
29
|
+
klass.define_singleton_method :protected_instance_methods do |all=true|
|
30
|
+
super(all) | superclass.protected_instance_methods
|
31
|
+
end
|
32
|
+
return klass
|
33
|
+
end
|
34
|
+
|
35
|
+
FileDelegate = DelegateModule(File)
|
36
|
+
|
37
|
+
class MyIO
|
38
|
+
end
|
39
|
+
|
40
|
+
class MyFile < MyIO
|
41
|
+
include FileDelegate
|
42
|
+
|
43
|
+
def initialize(dobj)
|
44
|
+
__setobj__(dobj)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
fobj = File.new(__FILE__, "r")
|
49
|
+
|
50
|
+
mf = MyFile.new(fobj)
|
51
|
+
|
52
|
+
puts "mf.is_a?(MyFile) = #{mf.is_a?(MyFile)}"
|
53
|
+
puts "mf.is_a?(MyIO) = #{mf.is_a?(MyIO)}"
|
54
|
+
|
55
|
+
puts
|
56
|
+
mf.each { |l| puts l }
|
57
|
+
mf.close
|
58
|
+
|
59
|
+
rescue => err
|
60
|
+
puts err.to_s
|
61
|
+
puts err.backtrace.join("\n")
|
62
|
+
end
|
data/test/encode_test.rb
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
begin
|
2
|
+
#
|
3
|
+
# Find the offset within the file of the first multi-byte character.
|
4
|
+
#
|
5
|
+
binary_string = ""
|
6
|
+
File.open("UTF-16-demo.txt", "rb") do |io|
|
7
|
+
binary_string = io.read
|
8
|
+
end
|
9
|
+
puts "\tbinary_string.encoding.name = #{binary_string.encoding.name} (valid: #{binary_string.valid_encoding?})"
|
10
|
+
puts "\tbinary_string.length = #{binary_string.length}"
|
11
|
+
puts "\tbinary_string.bytesize = #{binary_string.bytesize}"
|
12
|
+
puts
|
13
|
+
|
14
|
+
utf8_string = ""
|
15
|
+
ec = Encoding::Converter.new("UTF-16le", "UTF-8")
|
16
|
+
rv = ec.primitive_convert(binary_string, utf8_string)
|
17
|
+
puts "primitive_convert --> #{rv}"
|
18
|
+
puts "\tutf8_string.encoding.name = #{utf8_string.encoding.name} (valid: #{utf8_string.valid_encoding?})"
|
19
|
+
puts "\tutf8_string.length = #{utf8_string.length}"
|
20
|
+
puts "\tutf8_string.bytesize = #{utf8_string.bytesize}"
|
21
|
+
puts
|
22
|
+
|
23
|
+
nchunk = 0
|
24
|
+
utf8_string = ""
|
25
|
+
ec = Encoding::Converter.new("UTF-16le", "UTF-8")
|
26
|
+
File.open("UTF-16-demo.txt", "rb") do |io|
|
27
|
+
while (binary_string = io.read(99))
|
28
|
+
rv = ec.primitive_convert(binary_string, utf8_string, nil, nil, :partial_input => true)
|
29
|
+
puts "Chunk: #{nchunk}, rv = #{rv}"
|
30
|
+
nchunk += 1
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
puts "nchunk = #{nchunk}"
|
35
|
+
puts "\tutf8_string.encoding.name = #{utf8_string.encoding.name} (valid: #{utf8_string.valid_encoding?})"
|
36
|
+
puts "\tutf8_string.length = #{utf8_string.length}"
|
37
|
+
puts "\tutf8_string.bytesize = #{utf8_string.bytesize}"
|
38
|
+
puts
|
39
|
+
rescue => err
|
40
|
+
puts err.to_s
|
41
|
+
puts err.backtrace.join("\n")
|
42
|
+
end
|
data/test/enoent_test.rb
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
require "yaml"
|
2
|
+
|
3
|
+
begin
|
4
|
+
begin
|
5
|
+
Dir.new("/not/a/dir")
|
6
|
+
rescue => err
|
7
|
+
puts " err => #{err.class.name}"
|
8
|
+
puts " err => #{err.inspect}"
|
9
|
+
puts " err.errno = #{err.errno}"
|
10
|
+
puts " err.class::Errno = #{err.class::Errno}"
|
11
|
+
err = YAML.load(YAML.dump(err))
|
12
|
+
nerr = SystemCallError.new("dir", err.class::Errno)
|
13
|
+
# nerr.message = err.message
|
14
|
+
raise nerr
|
15
|
+
end
|
16
|
+
rescue Errno::ENOENT => oerr
|
17
|
+
puts "**** Got Errno::ENOENT"
|
18
|
+
puts "oerr => #{oerr.class.name}"
|
19
|
+
puts "oerr => #{oerr.inspect}"
|
20
|
+
puts "oerr.errno = #{oerr.errno}"
|
21
|
+
puts "oerr.class::Errno = #{oerr.class::Errno}"
|
22
|
+
rescue SystemCallError => oerr
|
23
|
+
puts "**** Got SystemCallError"
|
24
|
+
rescue => oerr
|
25
|
+
puts "**** Not Errno::ENOENT"
|
26
|
+
puts "oerr => #{oerr.class.name}"
|
27
|
+
puts "oerr => #{oerr.inspect}"
|
28
|
+
puts "oerr.errno = #{oerr.errno}"
|
29
|
+
puts "oerr.class::Errno = #{oerr.class::Errno}"
|
30
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
class MyFile
|
2
|
+
def self.name
|
3
|
+
"MyFile"
|
4
|
+
end
|
5
|
+
end
|
6
|
+
|
7
|
+
class Vfs
|
8
|
+
def self.nest(ext)
|
9
|
+
ext.const_set(:File, MyFile)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
begin
|
14
|
+
|
15
|
+
Module.new do
|
16
|
+
class << self
|
17
|
+
puts self.class.name
|
18
|
+
puts constants.inspect
|
19
|
+
puts File.name
|
20
|
+
|
21
|
+
Vfs.nest(self)
|
22
|
+
puts constants.inspect
|
23
|
+
puts File.name
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
puts
|
28
|
+
|
29
|
+
Module.new do
|
30
|
+
class << self
|
31
|
+
puts self.class.name
|
32
|
+
puts constants.inspect
|
33
|
+
puts File.name
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
puts File.name
|
38
|
+
|
39
|
+
rescue => err
|
40
|
+
puts err.to_s
|
41
|
+
puts err.backtrace.join("\n")
|
42
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require "tempfile"
|
2
|
+
|
3
|
+
begin
|
4
|
+
input_file_name = "UTF-8-demo.txt"
|
5
|
+
external_encoding = Encoding.find("UTF-8")
|
6
|
+
binary_encoding = Encoding.find("ASCII-8BIT")
|
7
|
+
buffer_size = 95
|
8
|
+
|
9
|
+
temp_file = Tempfile.new("rbve")
|
10
|
+
|
11
|
+
File.open(input_file_name, "rb") do |io|
|
12
|
+
block = 0
|
13
|
+
while (binary_string = io.read(buffer_size))
|
14
|
+
binary_string.force_encoding(external_encoding)
|
15
|
+
puts "Block: #{block}, valid: #{binary_string.valid_encoding?}"
|
16
|
+
push_back = 0
|
17
|
+
(0...8).each do
|
18
|
+
break if binary_string.valid_encoding?
|
19
|
+
binary_string.force_encoding(binary_encoding)
|
20
|
+
binary_string[-1] = ""
|
21
|
+
binary_string.force_encoding(external_encoding)
|
22
|
+
push_back += 1
|
23
|
+
end
|
24
|
+
raise "Invalid byte sequence" unless binary_string.valid_encoding?
|
25
|
+
puts "Block: #{block}, valid: #{binary_string.valid_encoding?}, push_back: #{push_back}"
|
26
|
+
temp_file.write(binary_string)
|
27
|
+
io.seek(-push_back, IO::SEEK_CUR) unless push_back == 0
|
28
|
+
block += 1
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
temp_file.close
|
33
|
+
|
34
|
+
input = File.read(input_file_name)
|
35
|
+
output = File.read(temp_file.path)
|
36
|
+
|
37
|
+
puts
|
38
|
+
puts "Input size: #{input.bytesize}"
|
39
|
+
puts "Output size: #{output.bytesize}"
|
40
|
+
puts "Data check pass: #{input == output}"
|
41
|
+
rescue => err
|
42
|
+
puts err.to_s
|
43
|
+
puts err.backtrace.join("\n")
|
44
|
+
end
|
data/test/read_test.rb
ADDED
@@ -0,0 +1,78 @@
|
|
1
|
+
begin
|
2
|
+
#
|
3
|
+
# Find the offset within the file of the first multi-byte character.
|
4
|
+
#
|
5
|
+
first_mb_char_pos = 0
|
6
|
+
File.open("UTF-8-demo.txt", "r:utf-8:utf-8") do |io|
|
7
|
+
io.each_char do |c|
|
8
|
+
if c.length != c.bytesize
|
9
|
+
puts "first_mb_char_pos = #{first_mb_char_pos}, char = '#{c}' #{c.bytes.to_a.inspect}"
|
10
|
+
puts
|
11
|
+
break
|
12
|
+
end
|
13
|
+
first_mb_char_pos += 1
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
puts "Read whole file as binary:"
|
18
|
+
binary_string = ""
|
19
|
+
File.open("UTF-8-demo.txt", "rb") do |io|
|
20
|
+
binary_string = io.read
|
21
|
+
end
|
22
|
+
puts "\tbinary_string.encoding.name = #{binary_string.encoding.name} (valid: #{binary_string.valid_encoding?})"
|
23
|
+
puts "\tbinary_string.length = #{binary_string.length}"
|
24
|
+
puts "\tbinary_string.bytesize = #{binary_string.bytesize}"
|
25
|
+
puts
|
26
|
+
|
27
|
+
puts "Read whole file as utf-8:"
|
28
|
+
utf8_string = ""
|
29
|
+
File.open("UTF-8-demo.txt", "r:utf-8:utf-8") do |io|
|
30
|
+
utf8_string = io.read
|
31
|
+
end
|
32
|
+
puts "\tutf8_string.encoding.name = #{utf8_string.encoding.name} (valid: #{utf8_string.valid_encoding?})"
|
33
|
+
puts "\tutf8_string.length = #{utf8_string.length}"
|
34
|
+
puts "\tutf8_string.bytesize = #{utf8_string.bytesize}"
|
35
|
+
puts
|
36
|
+
|
37
|
+
puts "Partial read (100 bytes) as utf-8:"
|
38
|
+
File.open("UTF-8-demo.txt", "r:utf-8:utf-8") do |io|
|
39
|
+
utf8_string = io.read(100)
|
40
|
+
end
|
41
|
+
puts "\tutf8_string.encoding.name = #{utf8_string.encoding.name} (valid: #{utf8_string.valid_encoding?})"
|
42
|
+
puts "\tutf8_string.length = #{utf8_string.length}"
|
43
|
+
puts "\tutf8_string.bytesize = #{utf8_string.bytesize}"
|
44
|
+
puts
|
45
|
+
|
46
|
+
puts "Offset read (on char boundary) as utf-8:"
|
47
|
+
File.open("UTF-8-demo.txt", "r:utf-8:utf-8") do |io|
|
48
|
+
io.seek(first_mb_char_pos, IO::SEEK_SET)
|
49
|
+
utf8_string = io.read
|
50
|
+
end
|
51
|
+
puts "\tutf8_string.encoding.name = #{utf8_string.encoding.name} (valid: #{utf8_string.valid_encoding?})"
|
52
|
+
puts "\tutf8_string.length = #{utf8_string.length}"
|
53
|
+
puts "\tutf8_string.bytesize = #{utf8_string.bytesize}"
|
54
|
+
puts
|
55
|
+
|
56
|
+
puts "Offset read (not on char boundary) as utf-8:"
|
57
|
+
File.open("UTF-8-demo.txt", "r:utf-8:utf-8") do |io|
|
58
|
+
io.seek(first_mb_char_pos+1, IO::SEEK_SET)
|
59
|
+
utf8_string = io.read
|
60
|
+
end
|
61
|
+
puts "\tutf8_string.encoding.name = #{utf8_string.encoding.name} (valid: #{utf8_string.valid_encoding?})"
|
62
|
+
puts "\tutf8_string.length = #{utf8_string.length}"
|
63
|
+
puts "\tutf8_string.bytesize = #{utf8_string.bytesize}"
|
64
|
+
puts
|
65
|
+
|
66
|
+
# File.open("UTF-8-demo.txt", "r:utf-8:utf-8") do |io|
|
67
|
+
# while utf8_string = io.gets
|
68
|
+
# puts utf8_string
|
69
|
+
# puts "\tutf8_string.encoding.name = #{utf8_string.encoding.name} (valid: #{utf8_string.valid_encoding?})"
|
70
|
+
# puts "\tutf8_string.length = #{utf8_string.length}"
|
71
|
+
# puts "\tutf8_string.bytesize = #{utf8_string.bytesize}"
|
72
|
+
# puts
|
73
|
+
# end
|
74
|
+
# end
|
75
|
+
rescue => err
|
76
|
+
puts err.to_s
|
77
|
+
puts err.backtrace.join("\n")
|
78
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
begin
|
2
|
+
first_mb_char_pos = 0
|
3
|
+
File.open("UTF-8-demo.txt", "r:utf-8:utf-8") do |io|
|
4
|
+
io.each_char do |c|
|
5
|
+
if c.length != c.bytesize
|
6
|
+
puts "first_mb_char_pos = #{first_mb_char_pos}, char = '#{c}' #{c.bytes.to_a.inspect}"
|
7
|
+
puts
|
8
|
+
break
|
9
|
+
end
|
10
|
+
first_mb_char_pos += 1
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
File.open("UTF-8-demo.txt", "r:utf-8:utf-8") do |io|
|
15
|
+
puts "File opened"
|
16
|
+
puts "\tio.pos = #{io.pos}"
|
17
|
+
puts
|
18
|
+
|
19
|
+
puts "Reading 10 bytes."
|
20
|
+
barray = io.each_byte.first(10)
|
21
|
+
puts "\tio.pos = #{io.pos}"
|
22
|
+
puts
|
23
|
+
|
24
|
+
puts "Reading 10 bytes."
|
25
|
+
barray = io.each_char.first(10)
|
26
|
+
puts "\tio.pos = #{io.pos}"
|
27
|
+
puts
|
28
|
+
|
29
|
+
puts "Reading 10 lines."
|
30
|
+
ln = 0
|
31
|
+
io.each_line do |line|
|
32
|
+
break if ln >= 10
|
33
|
+
puts "Line: #{ln}"
|
34
|
+
puts "\tline.length = #{line.length}"
|
35
|
+
puts "\tline.bytesize = #{line.bytesize}"
|
36
|
+
puts "\tline.codepoints.length = #{line.codepoints.length}"
|
37
|
+
puts "\tio.pos = #{io.pos}"
|
38
|
+
puts "\tio.lineno = #{io.lineno}"
|
39
|
+
puts
|
40
|
+
ln += 1
|
41
|
+
end
|
42
|
+
end
|
43
|
+
rescue => err
|
44
|
+
puts err.to_s
|
45
|
+
puts err.backtrace.join("\n")
|
46
|
+
end
|