na_str 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/Makefile +132 -0
- data/README +103 -0
- data/depends/mmap.tar.gz +0 -0
- data/depends/narray-0.5.7p2.tar.gz +0 -0
- data/extconf.rb +9 -0
- data/gemspec.rb +30 -0
- data/install.rb +210 -0
- data/lib/nmap.rb +198 -0
- data/na_str-0.1.0.gem +0 -0
- data/na_str.c +67 -0
- data/nmap.rb +198 -0
- data/samples/a.rb +18 -0
- data/samples/b.rb +47 -0
- data/samples/b.rb.data +0 -0
- data/samples/c.rb +18 -0
- metadata +59 -0
data/Makefile
ADDED
@@ -0,0 +1,132 @@
|
|
1
|
+
|
2
|
+
SHELL = /bin/sh
|
3
|
+
|
4
|
+
#### Start of system configuration section. ####
|
5
|
+
|
6
|
+
srcdir = .
|
7
|
+
topdir = $(rubylibdir)/$(arch)
|
8
|
+
hdrdir = $(rubylibdir)/$(arch)
|
9
|
+
VPATH = $(srcdir)
|
10
|
+
prefix = $(DESTDIR)/dmsp/reference/ruby-1.8.1/
|
11
|
+
exec_prefix = $(prefix)
|
12
|
+
sitedir = $(prefix)/lib/ruby/site_ruby
|
13
|
+
rubylibdir = $(libdir)/ruby/$(ruby_version)
|
14
|
+
builddir = $(ac_builddir)
|
15
|
+
archdir = $(rubylibdir)/$(arch)
|
16
|
+
sbindir = $(exec_prefix)/sbin
|
17
|
+
compile_dir = $(DESTDIR)/dmsp/moby-1-1/reference/build/ruby-1.8.1
|
18
|
+
datadir = $(prefix)/share
|
19
|
+
includedir = $(prefix)/include
|
20
|
+
infodir = $(prefix)/info
|
21
|
+
top_builddir = $(ac_top_builddir)
|
22
|
+
sysconfdir = $(prefix)/etc
|
23
|
+
mandir = $(prefix)/man
|
24
|
+
libdir = $(exec_prefix)/lib
|
25
|
+
sharedstatedir = $(prefix)/com
|
26
|
+
oldincludedir = $(DESTDIR)/usr/include
|
27
|
+
sitearchdir = $(sitelibdir)/$(sitearch)
|
28
|
+
bindir = $(exec_prefix)/bin
|
29
|
+
localstatedir = $(prefix)/var
|
30
|
+
sitelibdir = $(sitedir)/$(ruby_version)
|
31
|
+
libexecdir = $(exec_prefix)/libexec
|
32
|
+
|
33
|
+
CC = gcc
|
34
|
+
LIBRUBY = $(LIBRUBY_A)
|
35
|
+
LIBRUBY_A = lib$(RUBY_SO_NAME)-static.a
|
36
|
+
LIBRUBYARG_SHARED =
|
37
|
+
LIBRUBYARG_STATIC = -l$(RUBY_SO_NAME)-static
|
38
|
+
|
39
|
+
CFLAGS = -fPIC -g -O2 -I /dmsp/reference/ruby-1.8.1//lib/ruby/site_ruby/1.8/i686-linux
|
40
|
+
CPPFLAGS = -I. -I$(topdir) -I$(hdrdir) -I$(srcdir)
|
41
|
+
CXXFLAGS = $(CFLAGS)
|
42
|
+
DLDFLAGS = /dmsp/reference/ruby-1.8.1//lib/ruby/site_ruby/1.8/i686-linux/narray.so
|
43
|
+
LDSHARED = gcc -shared
|
44
|
+
AR = ar
|
45
|
+
EXEEXT =
|
46
|
+
|
47
|
+
RUBY_INSTALL_NAME = ruby
|
48
|
+
RUBY_SO_NAME = $(RUBY_INSTALL_NAME)
|
49
|
+
arch = i686-linux
|
50
|
+
sitearch = i686-linux
|
51
|
+
ruby_version = 1.8
|
52
|
+
RUBY = ruby
|
53
|
+
RM = $(RUBY) -run -e rm -- -f
|
54
|
+
MAKEDIRS = $(RUBY) -run -e mkdir -- -p
|
55
|
+
INSTALL_PROG = $(RUBY) -run -e install -- -vpm 0755
|
56
|
+
INSTALL_DATA = $(RUBY) -run -e install -- -vpm 0644
|
57
|
+
|
58
|
+
#### End of system configuration section. ####
|
59
|
+
|
60
|
+
|
61
|
+
LIBPATH = -L"$(libdir)"
|
62
|
+
DEFFILE =
|
63
|
+
|
64
|
+
CLEANFILES =
|
65
|
+
DISTCLEANFILES =
|
66
|
+
|
67
|
+
target_prefix =
|
68
|
+
LOCAL_LIBS =
|
69
|
+
LIBS = -ldl -lcrypt -lm -lc
|
70
|
+
OBJS = na_str.o
|
71
|
+
TARGET = na_str
|
72
|
+
DLLIB = $(TARGET).so
|
73
|
+
STATIC_LIB = $(TARGET).a
|
74
|
+
|
75
|
+
RUBYCOMMONDIR = $(sitedir)$(target_prefix)
|
76
|
+
RUBYLIBDIR = $(sitelibdir)$(target_prefix)
|
77
|
+
RUBYARCHDIR = $(sitearchdir)$(target_prefix)
|
78
|
+
|
79
|
+
CLEANLIBS = "$(TARGET).{lib,exp,il?,tds,map}" $(DLLIB)
|
80
|
+
CLEANOBJS = "*.{o,a,s[ol],pdb,bak}"
|
81
|
+
|
82
|
+
all: $(DLLIB)
|
83
|
+
static: $(STATIC_LIB)
|
84
|
+
|
85
|
+
clean:
|
86
|
+
@$(RM) $(CLEANLIBS) $(CLEANOBJS) $(CLEANFILES)
|
87
|
+
|
88
|
+
distclean: clean
|
89
|
+
@$(RM) Makefile extconf.h conftest.* mkmf.log
|
90
|
+
@$(RM) core ruby$(EXEEXT) *~ $(DISTCLEANFILES)
|
91
|
+
|
92
|
+
realclean: distclean
|
93
|
+
install: $(RUBYARCHDIR)
|
94
|
+
install: $(RUBYARCHDIR)/$(DLLIB)
|
95
|
+
$(RUBYARCHDIR)/$(DLLIB): $(DLLIB) $(RUBYARCHDIR)
|
96
|
+
@$(INSTALL_PROG) $(DLLIB) $(RUBYARCHDIR)
|
97
|
+
install: $(RUBYLIBDIR)
|
98
|
+
install: $(RUBYLIBDIR)/nmap.rb
|
99
|
+
$(RUBYLIBDIR)/nmap.rb: $(srcdir)/lib/nmap.rb $(RUBYLIBDIR)
|
100
|
+
@$(INSTALL_DATA) $(srcdir)/lib/nmap.rb $(RUBYLIBDIR)
|
101
|
+
$(RUBYARCHDIR):
|
102
|
+
@$(MAKEDIRS) $(RUBYARCHDIR)
|
103
|
+
$(RUBYLIBDIR):
|
104
|
+
@$(MAKEDIRS) $(RUBYLIBDIR)
|
105
|
+
|
106
|
+
site-install: install
|
107
|
+
|
108
|
+
.SUFFIXES: .c .cc .m .cxx .cpp .C .o
|
109
|
+
|
110
|
+
.cc.o:
|
111
|
+
$(CXX) $(CXXFLAGS) $(CPPFLAGS) -c $<
|
112
|
+
|
113
|
+
.cpp.o:
|
114
|
+
$(CXX) $(CXXFLAGS) $(CPPFLAGS) -c $<
|
115
|
+
|
116
|
+
.cxx.o:
|
117
|
+
$(CXX) $(CXXFLAGS) $(CPPFLAGS) -c $<
|
118
|
+
|
119
|
+
.C.o:
|
120
|
+
$(CXX) $(CXXFLAGS) $(CPPFLAGS) -c $<
|
121
|
+
|
122
|
+
.c.o:
|
123
|
+
$(CC) $(CFLAGS) $(CPPFLAGS) -c $<
|
124
|
+
|
125
|
+
$(DLLIB): $(OBJS)
|
126
|
+
@-$(RM) $@
|
127
|
+
$(LDSHARED) $(DLDFLAGS) $(LIBPATH) -o $(DLLIB) $(OBJS) $(LOCAL_LIBS) $(LIBS)
|
128
|
+
|
129
|
+
$(STATIC_LIB): $(OBJS)
|
130
|
+
$(AR) cru $@ $(OBJS)
|
131
|
+
@-ranlib $(DLLIB) 2> /dev/null || true
|
132
|
+
|
data/README
ADDED
@@ -0,0 +1,103 @@
|
|
1
|
+
NAME
|
2
|
+
|
3
|
+
na_str (c extension)
|
4
|
+
|
5
|
+
nmap (reference ruby class which combines narray and mmap)
|
6
|
+
|
7
|
+
|
8
|
+
URIS
|
9
|
+
|
10
|
+
http://codeforpeople.com/lib/ruby/na_str/
|
11
|
+
|
12
|
+
|
13
|
+
SYNOPSIS
|
14
|
+
|
15
|
+
na_str is designed to allow data sharing between narray object and other ruby
|
16
|
+
objects. the shared data is that returned by the objects to_s or to_str method
|
17
|
+
and rb_string_new4. using this technique memory mapped (using guy's mmap
|
18
|
+
extensions) data can be altered with no explicit io on the users part and
|
19
|
+
partial changed to numerical grids can occur very quickly and persistently.
|
20
|
+
|
21
|
+
the nmap.rb reference impl is a concrete example of this usage and is
|
22
|
+
included in the distribution
|
23
|
+
|
24
|
+
|
25
|
+
EXAMPLE USAGE
|
26
|
+
|
27
|
+
jib:~/eg/ruby/na_str > cat a.rb
|
28
|
+
#
|
29
|
+
# the nmap extension is installed along with na_str
|
30
|
+
#
|
31
|
+
require 'nmap'
|
32
|
+
#
|
33
|
+
# the NMap ctor interface is similar to NArray's, but a backing file must also
|
34
|
+
# be specified
|
35
|
+
#
|
36
|
+
path, x, y = 'int.data', 3, 4
|
37
|
+
nmap = NMap.int path, x, y
|
38
|
+
#
|
39
|
+
# copy the last row to the first
|
40
|
+
#
|
41
|
+
nmap.na[true, 0] = nmap.na[true, 3]
|
42
|
+
#
|
43
|
+
# set the last row to be the current time. if you run this a few times you'll
|
44
|
+
# notice that changes to the narray are automatically written to the to
|
45
|
+
# backing file via the magic of mmap
|
46
|
+
#
|
47
|
+
nmap.na[true, 3] = Time.now.to_i
|
48
|
+
#
|
49
|
+
# show the narray
|
50
|
+
#
|
51
|
+
p nmap.na
|
52
|
+
|
53
|
+
|
54
|
+
jib:~/eg/ruby/na_str > ruby a.rb
|
55
|
+
NArray(ref).int(3,4):
|
56
|
+
[ [ 0, 0, 0 ],
|
57
|
+
[ 0, 0, 0 ],
|
58
|
+
[ 0, 0, 0 ],
|
59
|
+
[ 1151439012, 1151439012, 1151439012 ] ]
|
60
|
+
|
61
|
+
jib:~/eg/ruby/na_str > ruby a.rb
|
62
|
+
NArray(ref).int(3,4):
|
63
|
+
[ [ 1151439012, 1151439012, 1151439012 ],
|
64
|
+
[ 0, 0, 0 ],
|
65
|
+
[ 0, 0, 0 ],
|
66
|
+
[ 1151439014, 1151439014, 1151439014 ] ]
|
67
|
+
|
68
|
+
|
69
|
+
SPEED
|
70
|
+
|
71
|
+
jib:~/eg/ruby/na_str > cat a.rb
|
72
|
+
#
|
73
|
+
# reference impl installed with na_str
|
74
|
+
#
|
75
|
+
require 'nmap'
|
76
|
+
#
|
77
|
+
# setup a narray grid containing 1 gb of ints
|
78
|
+
#
|
79
|
+
gb = 2 ** 30
|
80
|
+
mb = 2 ** 20
|
81
|
+
sizeof_int = [42].pack('i').size
|
82
|
+
gig_of_ints = gb / sizeof_int
|
83
|
+
nmap = NMap.int '1GB', gig_of_ints
|
84
|
+
#
|
85
|
+
# set about 1 million of the ints to 42
|
86
|
+
#
|
87
|
+
nmap.na[0 .. mb] = 42
|
88
|
+
#
|
89
|
+
# show that the data was written
|
90
|
+
#
|
91
|
+
p nmap.na[mb - 1]
|
92
|
+
|
93
|
+
|
94
|
+
jib:~/eg/ruby/na_str > time ruby a.rb
|
95
|
+
42
|
96
|
+
|
97
|
+
real 0m0.078s
|
98
|
+
user 0m0.020s
|
99
|
+
sys 0m0.020s
|
100
|
+
|
101
|
+
|
102
|
+
jib:~/eg/ruby/na_str > ls -ltar 1GB
|
103
|
+
-rw-rw-r-- 1 ahoward ahoward 1073741824 Jun 27 14:28 1GB
|
data/depends/mmap.tar.gz
ADDED
Binary file
|
Binary file
|
data/extconf.rb
ADDED
data/gemspec.rb
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
|
2
|
+
lib, version = File::basename(File::dirname(File::expand_path(__FILE__))).split %r/-/, 2
|
3
|
+
|
4
|
+
require 'rubygems'
|
5
|
+
|
6
|
+
Gem::Specification::new do |spec|
|
7
|
+
$VERBOSE = nil
|
8
|
+
spec.name = lib
|
9
|
+
spec.version = version
|
10
|
+
spec.platform = Gem::Platform::RUBY
|
11
|
+
spec.summary = lib
|
12
|
+
|
13
|
+
spec.files = Dir::glob "**/**"
|
14
|
+
spec.executables = Dir::glob("bin/*").map{|exe| File::basename exe}
|
15
|
+
|
16
|
+
spec.require_path = "lib"
|
17
|
+
spec.autorequire = lib
|
18
|
+
|
19
|
+
spec.has_rdoc = File::exist? "doc"
|
20
|
+
spec.test_suite_file = "test/#{ lib }.rb" if File::directory? "test"
|
21
|
+
|
22
|
+
spec.extensions << "extconf.rb" if File::exists? "extconf.rb"
|
23
|
+
|
24
|
+
spec.author = "Ara T. Howard"
|
25
|
+
spec.email = "ara.t.howard@noaa.gov"
|
26
|
+
spec.homepage = "http://codeforpeople.com/lib/ruby/#{ lib }/"
|
27
|
+
|
28
|
+
spec.requirements << "http://moulon.inra.fr/ruby/mmap.html"
|
29
|
+
spec.requirements << "http://narray.rubyforge.org/"
|
30
|
+
end
|
data/install.rb
ADDED
@@ -0,0 +1,210 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require 'rbconfig'
|
3
|
+
require 'find'
|
4
|
+
require 'ftools'
|
5
|
+
require 'tempfile'
|
6
|
+
include Config
|
7
|
+
|
8
|
+
LIBDIR = "lib"
|
9
|
+
LIBDIR_MODE = 0644
|
10
|
+
|
11
|
+
BINDIR = "bin"
|
12
|
+
BINDIR_MODE = 0755
|
13
|
+
|
14
|
+
|
15
|
+
$srcdir = CONFIG["srcdir"]
|
16
|
+
$version = CONFIG["MAJOR"]+"."+CONFIG["MINOR"]
|
17
|
+
$libdir = File.join(CONFIG["libdir"], "ruby", $version)
|
18
|
+
$archdir = File.join($libdir, CONFIG["arch"])
|
19
|
+
$site_libdir = $:.find {|x| x =~ /site_ruby$/}
|
20
|
+
$bindir = CONFIG["bindir"] || CONFIG['BINDIR']
|
21
|
+
$ruby_install_name = CONFIG['ruby_install_name'] || CONFIG['RUBY_INSTALL_NAME'] || 'ruby'
|
22
|
+
$ruby_ext = CONFIG['EXEEXT'] || ''
|
23
|
+
$ruby = File.join($bindir, ($ruby_install_name + $ruby_ext))
|
24
|
+
|
25
|
+
if !$site_libdir
|
26
|
+
$site_libdir = File.join($libdir, "site_ruby")
|
27
|
+
elsif $site_libdir !~ %r/#{Regexp.quote($version)}/
|
28
|
+
$site_libdir = File.join($site_libdir, $version)
|
29
|
+
end
|
30
|
+
|
31
|
+
def install_rb(srcdir=nil, destdir=nil, mode=nil, bin=nil)
|
32
|
+
#{{{
|
33
|
+
path = []
|
34
|
+
dir = []
|
35
|
+
Find.find(srcdir) do |f|
|
36
|
+
next unless FileTest.file?(f)
|
37
|
+
next if (f = f[srcdir.length+1..-1]) == nil
|
38
|
+
next if (/CVS$/ =~ File.dirname(f))
|
39
|
+
next if f =~ %r/\.lnk/
|
40
|
+
path.push f
|
41
|
+
dir |= [File.dirname(f)]
|
42
|
+
end
|
43
|
+
for f in dir
|
44
|
+
next if f == "."
|
45
|
+
next if f == "CVS"
|
46
|
+
File::makedirs(File.join(destdir, f))
|
47
|
+
end
|
48
|
+
for f in path
|
49
|
+
next if (/\~$/ =~ f)
|
50
|
+
next if (/^\./ =~ File.basename(f))
|
51
|
+
unless bin
|
52
|
+
File::install(File.join(srcdir, f), File.join(destdir, f), mode, true)
|
53
|
+
else
|
54
|
+
from = File.join(srcdir, f)
|
55
|
+
to = File.join(destdir, f)
|
56
|
+
shebangify(from) do |sf|
|
57
|
+
$deferr.print from, " -> ", File::catname(from, to), "\n"
|
58
|
+
$deferr.printf "chmod %04o %s\n", mode, to
|
59
|
+
File::install(sf, to, mode, false)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
#}}}
|
64
|
+
end
|
65
|
+
def shebangify f
|
66
|
+
#{{{
|
67
|
+
open(f) do |fd|
|
68
|
+
buf = fd.read 42
|
69
|
+
if buf =~ %r/^\s*#\s*!.*ruby/o
|
70
|
+
ftmp = Tempfile::new("#{ $$ }_#{ File::basename(f) }")
|
71
|
+
begin
|
72
|
+
fd.rewind
|
73
|
+
ftmp.puts "#!#{ $ruby }"
|
74
|
+
while((buf = fd.read(8192)))
|
75
|
+
ftmp.write buf
|
76
|
+
end
|
77
|
+
ftmp.close
|
78
|
+
yield ftmp.path
|
79
|
+
ensure
|
80
|
+
ftmp.close!
|
81
|
+
end
|
82
|
+
else
|
83
|
+
yield f
|
84
|
+
end
|
85
|
+
end
|
86
|
+
#}}}
|
87
|
+
end
|
88
|
+
def ARGV.switch
|
89
|
+
#{{{
|
90
|
+
return nil if self.empty?
|
91
|
+
arg = self.shift
|
92
|
+
return nil if arg == '--'
|
93
|
+
if arg =~ /^-(.)(.*)/
|
94
|
+
return arg if $1 == '-'
|
95
|
+
raise 'unknown switch "-"' if $2.index('-')
|
96
|
+
self.unshift "-#{$2}" if $2.size > 0
|
97
|
+
"-#{$1}"
|
98
|
+
else
|
99
|
+
self.unshift arg
|
100
|
+
nil
|
101
|
+
end
|
102
|
+
#}}}
|
103
|
+
end
|
104
|
+
def ARGV.req_arg
|
105
|
+
#{{{
|
106
|
+
self.shift || raise('missing argument')
|
107
|
+
#}}}
|
108
|
+
end
|
109
|
+
def linkify d, linked = []
|
110
|
+
#--{{{
|
111
|
+
if test ?d, d
|
112
|
+
versioned = Dir[ File::join(d, "*-[0-9].[0-9].[0-9].rb") ]
|
113
|
+
versioned.each do |v|
|
114
|
+
src, dst = v, v.gsub(%r/\-[\d\.]+\.rb$/, '.rb')
|
115
|
+
lnk = nil
|
116
|
+
begin
|
117
|
+
if test ?l, dst
|
118
|
+
lnk = "#{ dst }.lnk"
|
119
|
+
puts "#{ dst } -> #{ lnk }"
|
120
|
+
File::rename dst, lnk
|
121
|
+
end
|
122
|
+
unless test ?e, dst
|
123
|
+
puts "#{ src } -> #{ dst }"
|
124
|
+
File::copy src, dst
|
125
|
+
linked << dst
|
126
|
+
end
|
127
|
+
ensure
|
128
|
+
if lnk
|
129
|
+
at_exit do
|
130
|
+
puts "#{ lnk } -> #{ dst }"
|
131
|
+
File::rename lnk, dst
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
137
|
+
linked
|
138
|
+
#--}}}
|
139
|
+
end
|
140
|
+
|
141
|
+
|
142
|
+
#
|
143
|
+
# main program
|
144
|
+
#
|
145
|
+
|
146
|
+
libdir = $site_libdir
|
147
|
+
bindir = $bindir
|
148
|
+
no_linkify = false
|
149
|
+
linked = nil
|
150
|
+
help = false
|
151
|
+
|
152
|
+
usage = <<-usage
|
153
|
+
#{ File::basename $0 }
|
154
|
+
-d, --destdir <destdir>
|
155
|
+
-l, --libdir <libdir>
|
156
|
+
-b, --bindir <bindir>
|
157
|
+
-r, --ruby <ruby>
|
158
|
+
-n, --no_linkify
|
159
|
+
-s, --sudo
|
160
|
+
-h, --help
|
161
|
+
usage
|
162
|
+
|
163
|
+
begin
|
164
|
+
while switch = ARGV.switch
|
165
|
+
case switch
|
166
|
+
when '-d', '--destdir'
|
167
|
+
libdir = ARGV.req_arg
|
168
|
+
when '-l', '--libdir'
|
169
|
+
libdir = ARGV.req_arg
|
170
|
+
when '-b', '--bindir'
|
171
|
+
bindir = ARGV.req_arg
|
172
|
+
when '-r', '--ruby'
|
173
|
+
$ruby = ARGV.req_arg
|
174
|
+
when '-n', '--no_linkify'
|
175
|
+
no_linkify = true
|
176
|
+
when '-s', '--sudo'
|
177
|
+
sudo = 'sudo'
|
178
|
+
when '-h', '--help'
|
179
|
+
help = true
|
180
|
+
else
|
181
|
+
raise "unknown switch #{switch.dump}"
|
182
|
+
end
|
183
|
+
end
|
184
|
+
rescue
|
185
|
+
STDERR.puts $!.to_s
|
186
|
+
STDERR.puts usage
|
187
|
+
exit 1
|
188
|
+
end
|
189
|
+
|
190
|
+
if help
|
191
|
+
STDOUT.puts usage
|
192
|
+
exit
|
193
|
+
end
|
194
|
+
|
195
|
+
system "#{ sudo } #{ $ruby } pre-install.rb" if test(?s, 'pre-install.rb')
|
196
|
+
|
197
|
+
unless no_linkify
|
198
|
+
linked = linkify('lib') + linkify('bin')
|
199
|
+
end
|
200
|
+
|
201
|
+
system "#{ $ruby } extconf.rb && make && #{ sudo } make install" if test(?s, 'extconf.rb')
|
202
|
+
|
203
|
+
install_rb(LIBDIR, libdir, LIBDIR_MODE)
|
204
|
+
install_rb(BINDIR, bindir, BINDIR_MODE, bin=true)
|
205
|
+
|
206
|
+
if linked
|
207
|
+
linked.each{|path| File::rm_f path}
|
208
|
+
end
|
209
|
+
|
210
|
+
system "#{ sudo } #{ $ruby } post-install.rb" if test(?s, 'post-install.rb')
|
data/lib/nmap.rb
ADDED
@@ -0,0 +1,198 @@
|
|
1
|
+
#
|
2
|
+
# built-in
|
3
|
+
#
|
4
|
+
require "yaml"
|
5
|
+
#
|
6
|
+
# rubyforge.org/raa.ruby-lang.org
|
7
|
+
#
|
8
|
+
require "mmap"
|
9
|
+
require "narray"
|
10
|
+
#
|
11
|
+
# homegrown
|
12
|
+
#
|
13
|
+
require "na_str"
|
14
|
+
#
|
15
|
+
# here we creates a little convenience class for working with memory mapped
|
16
|
+
# numerical grids
|
17
|
+
#
|
18
|
+
class NMap
|
19
|
+
module Util
|
20
|
+
def string_of obj
|
21
|
+
obj.to_str
|
22
|
+
rescue
|
23
|
+
raise ArgumentError, "cannot convert <#{ obj.inspect }> to string"
|
24
|
+
end
|
25
|
+
|
26
|
+
def int_of obj
|
27
|
+
Integer obj
|
28
|
+
rescue
|
29
|
+
raise ArgumentError, "cannot convert <#{ obj.inspect }> to int"
|
30
|
+
end
|
31
|
+
|
32
|
+
def int_list_of obj
|
33
|
+
[*obj].flatten.map{|elem| int_of elem}
|
34
|
+
rescue
|
35
|
+
raise ArgumentError, "cannot convert <#{ obj.inspect }> to int list"
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
class Header < ::Hash
|
40
|
+
include Util
|
41
|
+
|
42
|
+
def initialize path, *argv
|
43
|
+
@path = string_of path
|
44
|
+
|
45
|
+
self.na_type = argv.shift
|
46
|
+
self.shape = argv
|
47
|
+
|
48
|
+
self.na_type = int_of na_type if na_type
|
49
|
+
self.shape = int_list_of shape if shape
|
50
|
+
|
51
|
+
init! if na_type and shape
|
52
|
+
|
53
|
+
load!
|
54
|
+
end
|
55
|
+
|
56
|
+
def init!
|
57
|
+
open(@path, "w"){|f| ::YAML::dump(({}.update self), f)}
|
58
|
+
end
|
59
|
+
|
60
|
+
def load!
|
61
|
+
self.update(open(@path){|f| ::YAML::load f})
|
62
|
+
end
|
63
|
+
|
64
|
+
def na_type
|
65
|
+
self["na_type"]
|
66
|
+
end
|
67
|
+
|
68
|
+
def na_type= val
|
69
|
+
self["na_type"] = val
|
70
|
+
end
|
71
|
+
|
72
|
+
def shape
|
73
|
+
self["shape"]
|
74
|
+
end
|
75
|
+
|
76
|
+
def shape= val
|
77
|
+
self["shape"] = val
|
78
|
+
end
|
79
|
+
|
80
|
+
def self.init(*a, &b) new(*a, &b) end
|
81
|
+
end
|
82
|
+
|
83
|
+
include Util
|
84
|
+
|
85
|
+
attr "path"
|
86
|
+
attr "na_type"
|
87
|
+
attr "shape"
|
88
|
+
attr "lockfile"
|
89
|
+
attr "header"
|
90
|
+
attr "na"
|
91
|
+
attr "closed"
|
92
|
+
|
93
|
+
def initialize path, *argv
|
94
|
+
@path = string_of path
|
95
|
+
|
96
|
+
@na_type = argv.shift
|
97
|
+
@shape = argv
|
98
|
+
|
99
|
+
@na_type = int_of @na_type if @na_type
|
100
|
+
@shape = int_list_of @shape if @shape
|
101
|
+
|
102
|
+
@lockfile = @path + '.lock'
|
103
|
+
|
104
|
+
locked do
|
105
|
+
init! unless test ?s, @path
|
106
|
+
load_header!
|
107
|
+
load!
|
108
|
+
end
|
109
|
+
|
110
|
+
@closed = false
|
111
|
+
|
112
|
+
if block_given?
|
113
|
+
begin
|
114
|
+
yield self
|
115
|
+
ensure
|
116
|
+
close
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
def init!
|
122
|
+
raise ArgumentError, "no na_type" unless @na_type
|
123
|
+
raise ArgumentError, "no shape" unless @shape
|
124
|
+
sizeof_type = NArray::new(@na_type, 1).to_s.size
|
125
|
+
size = @shape.inject(1){|product, dim| product *= dim}
|
126
|
+
pos = sizeof_type * size
|
127
|
+
File.unlink @path rescue nil
|
128
|
+
open(@path, File::CREAT|File::EXCL|File::RDWR){|f| f.truncate pos}
|
129
|
+
Header::init @path + '.nmap', @na_type, @shape
|
130
|
+
end
|
131
|
+
|
132
|
+
def load_header!
|
133
|
+
@header = Header::new @path + '.nmap'
|
134
|
+
@na_type = @header.na_type
|
135
|
+
@shape = @header.shape
|
136
|
+
end
|
137
|
+
|
138
|
+
def load!
|
139
|
+
@mmap = ::Mmap::new @path, "rw", Mmap::MAP_SHARED
|
140
|
+
@na = ::NArray::str @mmap, @na_type, *@shape
|
141
|
+
end
|
142
|
+
|
143
|
+
def locked
|
144
|
+
f = open @lockfile, 'a+'
|
145
|
+
f.flock File::LOCK_EX
|
146
|
+
yield
|
147
|
+
ensure
|
148
|
+
if f
|
149
|
+
f.flock File::LOCK_UN rescue nil
|
150
|
+
f.close rescue nil
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
def sync
|
155
|
+
@mmap.msync
|
156
|
+
end
|
157
|
+
|
158
|
+
def close
|
159
|
+
return if @closed
|
160
|
+
sync
|
161
|
+
@mmap.munmap
|
162
|
+
@mmap = nil
|
163
|
+
@na = nil
|
164
|
+
@closed = true
|
165
|
+
end
|
166
|
+
|
167
|
+
class << self
|
168
|
+
def init(*a, &b) new(*a, &b) end
|
169
|
+
ctors = ::NArray.constants.select{|c| ::NArray.respond_to? c.downcase}
|
170
|
+
ctors.each do |m|
|
171
|
+
module_eval <<-code
|
172
|
+
def #{ m.downcase }(path, *argv)
|
173
|
+
new path, NArray::#{ m }, *argv
|
174
|
+
end
|
175
|
+
code
|
176
|
+
end
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
180
|
+
#
|
181
|
+
# sample usage - be sure to run more than once!!
|
182
|
+
#
|
183
|
+
if $0 == __FILE__
|
184
|
+
require 'tmpdir'
|
185
|
+
require 'yaml'
|
186
|
+
|
187
|
+
ipath = File.join Dir.tmpdir, 'i.na'
|
188
|
+
|
189
|
+
t, f = true, false
|
190
|
+
|
191
|
+
nmap = NMap.int ipath, 3,4
|
192
|
+
na = nmap.na
|
193
|
+
p na
|
194
|
+
na[t,0] = 42
|
195
|
+
na[0,t] = Time.now.to_i
|
196
|
+
p na
|
197
|
+
|
198
|
+
end
|
data/na_str-0.1.0.gem
ADDED
File without changes
|
data/na_str.c
ADDED
@@ -0,0 +1,67 @@
|
|
1
|
+
#include <ruby.h>
|
2
|
+
#include <version.h>
|
3
|
+
#include "narray.h"
|
4
|
+
#include "narray_config.h"
|
5
|
+
|
6
|
+
static VALUE
|
7
|
+
str_new4 (VALUE str)
|
8
|
+
{
|
9
|
+
StringValue (str);
|
10
|
+
if (FL_TEST (str, ELTS_SHARED))
|
11
|
+
{
|
12
|
+
rb_str_buf_cat2 (str, ""); /* unanchor literal string */
|
13
|
+
}
|
14
|
+
return rb_str_new4 (str);
|
15
|
+
}
|
16
|
+
|
17
|
+
static VALUE
|
18
|
+
na_s_str (int argc, VALUE * argv, VALUE klass)
|
19
|
+
{
|
20
|
+
struct NARRAY *ary;
|
21
|
+
VALUE v;
|
22
|
+
VALUE str;
|
23
|
+
int i, type, len = 1, str_len, *shape, rank = argc - 2;
|
24
|
+
|
25
|
+
if (argc < 1)
|
26
|
+
rb_raise (rb_eArgError, "String Argument required");
|
27
|
+
|
28
|
+
if (argc < 2)
|
29
|
+
rb_raise (rb_eArgError, "Type and Size Arguments required");
|
30
|
+
|
31
|
+
type = na_get_typecode (argv[1]);
|
32
|
+
str = str_new4 (argv[0]);
|
33
|
+
str_len = RSTRING (str)->len;
|
34
|
+
|
35
|
+
if (argc == 2)
|
36
|
+
{
|
37
|
+
rank = 1;
|
38
|
+
shape = ALLOCA_N (int, rank);
|
39
|
+
if (str_len % na_sizeof[type] != 0)
|
40
|
+
rb_raise (rb_eArgError, "string size mismatch");
|
41
|
+
shape[0] = str_len / na_sizeof[type];
|
42
|
+
}
|
43
|
+
else
|
44
|
+
{
|
45
|
+
shape = ALLOCA_N (int, rank);
|
46
|
+
for (i = 0; i < rank; i++)
|
47
|
+
len *= shape[i] = NUM2INT (argv[i + 2]);
|
48
|
+
len *= na_sizeof[type];
|
49
|
+
if (len != str_len)
|
50
|
+
rb_raise (rb_eArgError, "size mismatch");
|
51
|
+
}
|
52
|
+
|
53
|
+
v = na_make_object (type, rank, shape, cNArray);
|
54
|
+
GetNArray (v, ary);
|
55
|
+
ary->ptr = RSTRING (str)->ptr;
|
56
|
+
ary->ref = str;
|
57
|
+
|
58
|
+
return v;
|
59
|
+
}
|
60
|
+
|
61
|
+
void
|
62
|
+
Init_na_str ()
|
63
|
+
{
|
64
|
+
rb_require ("narray");
|
65
|
+
rb_define_singleton_method (cNArray, "str", na_s_str, -1);
|
66
|
+
rb_define_singleton_method (cNArray, "from_string", na_s_str, -1);
|
67
|
+
}
|
data/nmap.rb
ADDED
@@ -0,0 +1,198 @@
|
|
1
|
+
#
|
2
|
+
# built-in
|
3
|
+
#
|
4
|
+
require "yaml"
|
5
|
+
#
|
6
|
+
# rubyforge.org/raa.ruby-lang.org
|
7
|
+
#
|
8
|
+
require "mmap"
|
9
|
+
require "narray"
|
10
|
+
#
|
11
|
+
# homegrown
|
12
|
+
#
|
13
|
+
require "na_str"
|
14
|
+
#
|
15
|
+
# here we creates a little convenience class for working with memory mapped
|
16
|
+
# numerical grids
|
17
|
+
#
|
18
|
+
class NMap
|
19
|
+
module Util
|
20
|
+
def string_of obj
|
21
|
+
obj.to_str
|
22
|
+
rescue
|
23
|
+
raise ArgumentError, "cannot convert <#{ obj.inspect }> to string"
|
24
|
+
end
|
25
|
+
|
26
|
+
def int_of obj
|
27
|
+
Integer obj
|
28
|
+
rescue
|
29
|
+
raise ArgumentError, "cannot convert <#{ obj.inspect }> to int"
|
30
|
+
end
|
31
|
+
|
32
|
+
def int_list_of obj
|
33
|
+
[*obj].flatten.map{|elem| int_of elem}
|
34
|
+
rescue
|
35
|
+
raise ArgumentError, "cannot convert <#{ obj.inspect }> to int list"
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
class Header < ::Hash
|
40
|
+
include Util
|
41
|
+
|
42
|
+
def initialize path, *argv
|
43
|
+
@path = string_of path
|
44
|
+
|
45
|
+
self.na_type = argv.shift
|
46
|
+
self.shape = argv
|
47
|
+
|
48
|
+
self.na_type = int_of na_type if na_type
|
49
|
+
self.shape = int_list_of shape if shape
|
50
|
+
|
51
|
+
init! if na_type and shape
|
52
|
+
|
53
|
+
load!
|
54
|
+
end
|
55
|
+
|
56
|
+
def init!
|
57
|
+
open(@path, "w"){|f| ::YAML::dump(({}.update self), f)}
|
58
|
+
end
|
59
|
+
|
60
|
+
def load!
|
61
|
+
self.update(open(@path){|f| ::YAML::load f})
|
62
|
+
end
|
63
|
+
|
64
|
+
def na_type
|
65
|
+
self["na_type"]
|
66
|
+
end
|
67
|
+
|
68
|
+
def na_type= val
|
69
|
+
self["na_type"] = val
|
70
|
+
end
|
71
|
+
|
72
|
+
def shape
|
73
|
+
self["shape"]
|
74
|
+
end
|
75
|
+
|
76
|
+
def shape= val
|
77
|
+
self["shape"] = val
|
78
|
+
end
|
79
|
+
|
80
|
+
def self.init(*a, &b) new(*a, &b) end
|
81
|
+
end
|
82
|
+
|
83
|
+
include Util
|
84
|
+
|
85
|
+
attr "path"
|
86
|
+
attr "na_type"
|
87
|
+
attr "shape"
|
88
|
+
attr "lockfile"
|
89
|
+
attr "header"
|
90
|
+
attr "na"
|
91
|
+
attr "closed"
|
92
|
+
|
93
|
+
def initialize path, *argv
|
94
|
+
@path = string_of path
|
95
|
+
|
96
|
+
@na_type = argv.shift
|
97
|
+
@shape = argv
|
98
|
+
|
99
|
+
@na_type = int_of @na_type if @na_type
|
100
|
+
@shape = int_list_of @shape if @shape
|
101
|
+
|
102
|
+
@lockfile = @path + '.lock'
|
103
|
+
|
104
|
+
locked do
|
105
|
+
init! unless test ?s, @path
|
106
|
+
load_header!
|
107
|
+
load!
|
108
|
+
end
|
109
|
+
|
110
|
+
@closed = false
|
111
|
+
|
112
|
+
if block_given?
|
113
|
+
begin
|
114
|
+
yield self
|
115
|
+
ensure
|
116
|
+
close
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
def init!
|
122
|
+
raise ArgumentError, "no na_type" unless @na_type
|
123
|
+
raise ArgumentError, "no shape" unless @shape
|
124
|
+
sizeof_type = NArray::new(@na_type, 1).to_s.size
|
125
|
+
size = @shape.inject(1){|product, dim| product *= dim}
|
126
|
+
pos = sizeof_type * size
|
127
|
+
File.unlink @path rescue nil
|
128
|
+
open(@path, File::CREAT|File::EXCL|File::RDWR){|f| f.truncate pos}
|
129
|
+
Header::init @path + '.yml', @na_type, @shape
|
130
|
+
end
|
131
|
+
|
132
|
+
def load_header!
|
133
|
+
@header = Header::new @path + '.yml'
|
134
|
+
@na_type = @header.na_type
|
135
|
+
@shape = @header.shape
|
136
|
+
end
|
137
|
+
|
138
|
+
def load!
|
139
|
+
@mmap = ::Mmap::new @path, "rw", Mmap::MAP_SHARED
|
140
|
+
@na = ::NArray::str @mmap, @na_type, *@shape
|
141
|
+
end
|
142
|
+
|
143
|
+
def locked
|
144
|
+
f = open @lockfile, 'a+'
|
145
|
+
f.flock File::LOCK_EX
|
146
|
+
yield
|
147
|
+
ensure
|
148
|
+
if f
|
149
|
+
f.flock File::LOCK_UN rescue nil
|
150
|
+
f.close rescue nil
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
def sync
|
155
|
+
@mmap.msync
|
156
|
+
end
|
157
|
+
|
158
|
+
def close
|
159
|
+
return if @closed
|
160
|
+
sync
|
161
|
+
@mmap.munmap
|
162
|
+
@mmap = nil
|
163
|
+
@na = nil
|
164
|
+
@closed = true
|
165
|
+
end
|
166
|
+
|
167
|
+
class << self
|
168
|
+
def init(*a, &b) new(*a, &b) end
|
169
|
+
ctors = ::NArray.constants.select{|c| ::NArray.respond_to? c.downcase}
|
170
|
+
ctors.each do |m|
|
171
|
+
module_eval <<-code
|
172
|
+
def #{ m.downcase }(path, *argv)
|
173
|
+
new path, NArray::#{ m }, *argv
|
174
|
+
end
|
175
|
+
code
|
176
|
+
end
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
180
|
+
#
|
181
|
+
# sample usage - be sure to run more than once!!
|
182
|
+
#
|
183
|
+
if $0 == __FILE__
|
184
|
+
require 'tmpdir'
|
185
|
+
require 'yaml'
|
186
|
+
|
187
|
+
ipath = File.join Dir.tmpdir, 'i.na'
|
188
|
+
|
189
|
+
t, f = true, false
|
190
|
+
|
191
|
+
nmap = NMap.int ipath, 3,4
|
192
|
+
na = nmap.na
|
193
|
+
p na
|
194
|
+
na[t,0] = 42
|
195
|
+
na[0,t] = Time.now.to_i
|
196
|
+
p na
|
197
|
+
|
198
|
+
end
|
data/samples/a.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
%w( ./lib ../lib . ..).each{|d| $:.unshift d}
|
2
|
+
require 'na_str'
|
3
|
+
|
4
|
+
#
|
5
|
+
# na_str allows you to share memory with any object that responds to to_s or
|
6
|
+
# to_str. the object whose memory is shared is frozen and cannot be modified
|
7
|
+
# and a reference to the object is kept so it is not gc'd. the object's
|
8
|
+
# memory can be modified using this 'view' of the data.
|
9
|
+
#
|
10
|
+
|
11
|
+
buf = [0,0,0,0].pack 'i*'
|
12
|
+
|
13
|
+
na = NArray::str buf, NArray::INT, 4
|
14
|
+
na[0] = 42
|
15
|
+
na[-1] = 42
|
16
|
+
|
17
|
+
p buf.unpack('i*')
|
18
|
+
p buf
|
data/samples/b.rb
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
%w( ./lib ../lib . ..).each{|d| $:.unshift d}
|
2
|
+
require "na_str"
|
3
|
+
require "mmap"
|
4
|
+
require "yaml"
|
5
|
+
|
6
|
+
#
|
7
|
+
# setup
|
8
|
+
#
|
9
|
+
sizeof_int = [42].pack("i").size
|
10
|
+
|
11
|
+
#
|
12
|
+
# setup an empty data file big enough to hold four ints if one doesn"t already
|
13
|
+
# exist
|
14
|
+
#
|
15
|
+
data = __FILE__ + ".data"
|
16
|
+
open(data, File::CREAT|File::EXCL|File::RDWR){|f| f.write(0.chr * 4 * sizeof_int)} rescue nil
|
17
|
+
|
18
|
+
#
|
19
|
+
# show the orginal data - run the script more than once to see that the data
|
20
|
+
# persists between invocations
|
21
|
+
#
|
22
|
+
y "before" => IO::read(data).unpack("i*")
|
23
|
+
|
24
|
+
#
|
25
|
+
# mmap data in
|
26
|
+
#
|
27
|
+
m = Mmap::new data, "rw", Mmap::MAP_SHARED
|
28
|
+
|
29
|
+
#
|
30
|
+
# overlay an narray over the memory map and manipulate it. note that any
|
31
|
+
# changes to the narray changes the memory map, which in turn changes the
|
32
|
+
# file!
|
33
|
+
#
|
34
|
+
na = NArray::str m, NArray::INT, 4
|
35
|
+
na[0] = 42
|
36
|
+
na[-1] = Time.now.to_i.abs
|
37
|
+
|
38
|
+
#
|
39
|
+
# sync, and unmap the data
|
40
|
+
#
|
41
|
+
m.msync
|
42
|
+
m.munmap
|
43
|
+
|
44
|
+
#
|
45
|
+
# show that the underlying data has been transparently changed!
|
46
|
+
#
|
47
|
+
y "after" => IO::read(data).unpack("i*")
|
data/samples/b.rb.data
ADDED
Binary file
|
data/samples/c.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
%w( ./lib ../lib . ..).each{|d| $:.unshift d}
|
2
|
+
#
|
3
|
+
# be sure to run this a few times in a row - wait a second or two between runs
|
4
|
+
# - notice that the data will automagically persist between calls!
|
5
|
+
#
|
6
|
+
require 'tmpdir'
|
7
|
+
require 'nmap'
|
8
|
+
|
9
|
+
ipath = File.join Dir.tmpdir, 'i.na'
|
10
|
+
|
11
|
+
nmap = NMap.int ipath, 3,4
|
12
|
+
na = nmap.na
|
13
|
+
p na
|
14
|
+
|
15
|
+
na[0,true] = Time.now.to_i
|
16
|
+
na[2,true] = 1
|
17
|
+
na[1,1..2] = 42
|
18
|
+
p na
|
metadata
ADDED
@@ -0,0 +1,59 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
rubygems_version: 0.8.11
|
3
|
+
specification_version: 1
|
4
|
+
name: na_str
|
5
|
+
version: !ruby/object:Gem::Version
|
6
|
+
version: 0.1.0
|
7
|
+
date: 2007-02-28 00:00:00.000000 -07:00
|
8
|
+
summary: na_str
|
9
|
+
require_paths:
|
10
|
+
- lib
|
11
|
+
email: ara.t.howard@noaa.gov
|
12
|
+
homepage: http://codeforpeople.com/lib/ruby/na_str/
|
13
|
+
rubyforge_project:
|
14
|
+
description:
|
15
|
+
autorequire: na_str
|
16
|
+
default_executable:
|
17
|
+
bindir: bin
|
18
|
+
has_rdoc: false
|
19
|
+
required_ruby_version: !ruby/object:Gem::Version::Requirement
|
20
|
+
requirements:
|
21
|
+
-
|
22
|
+
- ">"
|
23
|
+
- !ruby/object:Gem::Version
|
24
|
+
version: 0.0.0
|
25
|
+
version:
|
26
|
+
platform: ruby
|
27
|
+
signing_key:
|
28
|
+
cert_chain:
|
29
|
+
authors:
|
30
|
+
- Ara T. Howard
|
31
|
+
files:
|
32
|
+
- depends
|
33
|
+
- extconf.rb
|
34
|
+
- install.rb
|
35
|
+
- lib
|
36
|
+
- Makefile
|
37
|
+
- na_str.c
|
38
|
+
- nmap.rb
|
39
|
+
- README
|
40
|
+
- samples
|
41
|
+
- gemspec.rb
|
42
|
+
- na_str-0.1.0.gem
|
43
|
+
- depends/mmap.tar.gz
|
44
|
+
- depends/narray-0.5.7p2.tar.gz
|
45
|
+
- lib/nmap.rb
|
46
|
+
- samples/b.rb.data
|
47
|
+
- samples/b.rb
|
48
|
+
- samples/a.rb
|
49
|
+
- samples/c.rb
|
50
|
+
test_files: []
|
51
|
+
rdoc_options: []
|
52
|
+
extra_rdoc_files: []
|
53
|
+
executables: []
|
54
|
+
extensions:
|
55
|
+
- extconf.rb
|
56
|
+
requirements:
|
57
|
+
- http://moulon.inra.fr/ruby/mmap.html
|
58
|
+
- http://narray.rubyforge.org/
|
59
|
+
dependencies: []
|