ox 1.4.6 → 1.5.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of ox might be problematic. Click here for more details.
- data/README.md +8 -2
- data/ext/ox/dump.c +129 -33
- data/ext/ox/gen_load.c +13 -13
- data/ext/ox/obj_load.c +21 -18
- data/ext/ox/ox.c +155 -158
- data/ext/ox/ox.h +48 -50
- data/ext/ox/parse.c +1 -1
- data/ext/ox/sax.c +29 -29
- data/lib/ox/version.rb +1 -1
- data/test/files.rb +4 -9
- data/test/func.rb +33 -0
- data/test/perf.rb +91 -0
- data/test/perf_obj.rb +61 -138
- data/test/sample.rb +9 -16
- data/test/sample/change.rb +14 -0
- data/test/sample/dir.rb +19 -0
- data/test/sample/doc.rb +36 -0
- data/test/sample/file.rb +48 -0
- data/test/sample/group.rb +16 -0
- data/test/sample/hasprops.rb +16 -0
- data/test/sample/layer.rb +12 -0
- data/test/sample/line.rb +20 -0
- data/test/sample/oval.rb +10 -0
- data/test/sample/rect.rb +10 -0
- data/test/sample/shape.rb +35 -0
- data/test/sample/text.rb +20 -0
- metadata +16 -2
data/ext/ox/ox.h
CHANGED
@@ -59,7 +59,7 @@ extern "C" {
|
|
59
59
|
#define NO_RSTRUCT 1
|
60
60
|
#endif
|
61
61
|
|
62
|
-
#define raise_error(msg, xml, current)
|
62
|
+
#define raise_error(msg, xml, current) _ox_raise_error(msg, xml, current, __FILE__, __LINE__)
|
63
63
|
|
64
64
|
#define MAX_TEXT_LEN 4096
|
65
65
|
#define MAX_ATTRS 1024
|
@@ -204,58 +204,56 @@ typedef struct _Options {
|
|
204
204
|
char effort; // Effort
|
205
205
|
} *Options;
|
206
206
|
|
207
|
-
extern VALUE
|
208
|
-
extern void
|
207
|
+
extern VALUE ox_parse(char *xml, ParseCallbacks pcb, char **endp, int trace, Effort effort);
|
208
|
+
extern void _ox_raise_error(const char *msg, const char *xml, const char *current, const char* file, int line);
|
209
209
|
|
210
|
-
extern void
|
210
|
+
extern void ox_sax_parse(VALUE handler, VALUE io, int convert);
|
211
211
|
|
212
|
-
extern char*
|
213
|
-
extern void
|
212
|
+
extern char* ox_write_obj_to_str(VALUE obj, Options copts);
|
213
|
+
extern void ox_write_obj_to_file(VALUE obj, const char *path, Options copts);
|
214
214
|
|
215
|
-
extern struct _Options
|
215
|
+
extern struct _Options ox_default_options;
|
216
216
|
|
217
217
|
extern VALUE Ox;
|
218
218
|
|
219
|
-
extern ID
|
220
|
-
extern ID
|
221
|
-
extern ID
|
222
|
-
extern ID
|
223
|
-
extern ID
|
224
|
-
extern ID
|
225
|
-
extern ID
|
226
|
-
extern ID
|
227
|
-
extern ID
|
228
|
-
extern ID
|
229
|
-
extern ID
|
230
|
-
extern ID
|
231
|
-
extern ID
|
232
|
-
extern ID
|
233
|
-
extern ID
|
234
|
-
extern ID
|
235
|
-
extern ID
|
236
|
-
extern ID
|
237
|
-
extern ID
|
238
|
-
extern ID
|
239
|
-
extern ID
|
240
|
-
extern ID
|
241
|
-
extern ID
|
242
|
-
extern ID
|
243
|
-
extern ID
|
244
|
-
extern ID
|
245
|
-
extern ID
|
246
|
-
extern ID
|
247
|
-
extern ID
|
248
|
-
extern ID
|
249
|
-
extern ID
|
250
|
-
extern ID
|
251
|
-
|
252
|
-
extern VALUE
|
253
|
-
extern VALUE
|
254
|
-
extern VALUE
|
255
|
-
extern VALUE
|
256
|
-
extern VALUE
|
257
|
-
extern VALUE version_sym;
|
258
|
-
extern VALUE zero_fixnum;
|
219
|
+
extern ID ox_at_id;
|
220
|
+
extern ID ox_attr_id;
|
221
|
+
extern ID ox_attributes_id;
|
222
|
+
extern ID ox_beg_id;
|
223
|
+
extern ID ox_cdata_id;
|
224
|
+
extern ID ox_comment_id;
|
225
|
+
extern ID ox_den_id;
|
226
|
+
extern ID ox_doctype_id;
|
227
|
+
extern ID ox_end_element_id;
|
228
|
+
extern ID ox_end_id;
|
229
|
+
extern ID ox_error_id;
|
230
|
+
extern ID ox_excl_id;
|
231
|
+
extern ID ox_fileno_id;
|
232
|
+
extern ID ox_inspect_id;
|
233
|
+
extern ID ox_instruct_id;
|
234
|
+
extern ID ox_keys_id;
|
235
|
+
extern ID ox_local_id;
|
236
|
+
extern ID ox_mesg_id;
|
237
|
+
extern ID ox_message_id;
|
238
|
+
extern ID ox_nodes_id;
|
239
|
+
extern ID ox_num_id;
|
240
|
+
extern ID ox_parse_id;
|
241
|
+
extern ID ox_read_id;
|
242
|
+
extern ID ox_readpartial_id;
|
243
|
+
extern ID ox_start_element_id;
|
244
|
+
extern ID ox_text_id;
|
245
|
+
extern ID ox_to_c_id;
|
246
|
+
extern ID ox_to_s_id;
|
247
|
+
extern ID ox_to_sym_id;
|
248
|
+
extern ID ox_tv_sec_id;
|
249
|
+
extern ID ox_tv_usec_id;
|
250
|
+
extern ID ox_value_id;
|
251
|
+
|
252
|
+
extern VALUE ox_empty_string;
|
253
|
+
extern VALUE ox_encoding_sym;
|
254
|
+
extern VALUE ox_struct_class;
|
255
|
+
extern VALUE ox_time_class;
|
256
|
+
extern VALUE ox_zero_fixnum;
|
259
257
|
|
260
258
|
extern VALUE ox_document_clas;
|
261
259
|
extern VALUE ox_element_clas;
|
@@ -264,9 +262,9 @@ extern VALUE ox_comment_clas;
|
|
264
262
|
extern VALUE ox_doctype_clas;
|
265
263
|
extern VALUE ox_cdata_clas;
|
266
264
|
|
267
|
-
extern Cache
|
268
|
-
extern Cache
|
269
|
-
extern Cache
|
265
|
+
extern Cache ox_symbol_cache;
|
266
|
+
extern Cache ox_class_cache;
|
267
|
+
extern Cache ox_attr_cache;
|
270
268
|
|
271
269
|
#if defined(__cplusplus)
|
272
270
|
#if 0
|
data/ext/ox/parse.c
CHANGED
data/ext/ox/sax.c
CHANGED
@@ -174,13 +174,13 @@ str2sym(const char *str, SaxDrive dr) {
|
|
174
174
|
VALUE *slot;
|
175
175
|
VALUE sym;
|
176
176
|
|
177
|
-
if (Qundef == (sym = ox_cache_get(
|
177
|
+
if (Qundef == (sym = ox_cache_get(ox_symbol_cache, str, &slot))) {
|
178
178
|
#ifdef HAVE_RUBY_ENCODING_H
|
179
179
|
if (0 != dr->encoding) {
|
180
180
|
VALUE rstr = rb_str_new2(str);
|
181
181
|
|
182
182
|
rb_enc_associate(rstr, dr->encoding);
|
183
|
-
sym = rb_funcall(rstr,
|
183
|
+
sym = rb_funcall(rstr, ox_to_sym_id, 0);
|
184
184
|
} else {
|
185
185
|
sym = ID2SYM(rb_intern(str));
|
186
186
|
}
|
@@ -216,20 +216,20 @@ ox_sax_parse(VALUE handler, VALUE io, int convert) {
|
|
216
216
|
|
217
217
|
static void
|
218
218
|
sax_drive_init(SaxDrive dr, VALUE handler, VALUE io, int convert) {
|
219
|
-
if (rb_respond_to(io,
|
219
|
+
if (rb_respond_to(io, ox_readpartial_id)) {
|
220
220
|
VALUE rfd;
|
221
221
|
|
222
|
-
if (rb_respond_to(io,
|
222
|
+
if (rb_respond_to(io, ox_fileno_id) && Qnil != (rfd = rb_funcall(io, ox_fileno_id, 0))) {
|
223
223
|
dr->read_func = read_from_fd;
|
224
224
|
dr->fd = FIX2INT(rfd);
|
225
225
|
} else {
|
226
226
|
dr->read_func = read_from_io_partial;
|
227
227
|
dr->io = io;
|
228
228
|
}
|
229
|
-
} else if (rb_respond_to(io,
|
229
|
+
} else if (rb_respond_to(io, ox_read_id)) {
|
230
230
|
VALUE rfd;
|
231
231
|
|
232
|
-
if (rb_respond_to(io,
|
232
|
+
if (rb_respond_to(io, ox_fileno_id) && Qnil != (rfd = rb_funcall(io, ox_fileno_id, 0))) {
|
233
233
|
dr->read_func = read_from_fd;
|
234
234
|
dr->fd = FIX2INT(rfd);
|
235
235
|
} else {
|
@@ -249,20 +249,20 @@ sax_drive_init(SaxDrive dr, VALUE handler, VALUE io, int convert) {
|
|
249
249
|
dr->col = 0;
|
250
250
|
dr->handler = handler;
|
251
251
|
dr->convert_special = convert;
|
252
|
-
dr->has_instruct = rb_respond_to(handler,
|
253
|
-
dr->has_attr = rb_respond_to(handler,
|
254
|
-
dr->has_doctype = rb_respond_to(handler,
|
255
|
-
dr->has_comment = rb_respond_to(handler,
|
256
|
-
dr->has_cdata = rb_respond_to(handler,
|
257
|
-
dr->has_text = rb_respond_to(handler,
|
258
|
-
dr->has_start_element = rb_respond_to(handler,
|
259
|
-
dr->has_end_element = rb_respond_to(handler,
|
260
|
-
dr->has_error = rb_respond_to(handler,
|
252
|
+
dr->has_instruct = rb_respond_to(handler, ox_instruct_id);
|
253
|
+
dr->has_attr = rb_respond_to(handler, ox_attr_id);
|
254
|
+
dr->has_doctype = rb_respond_to(handler, ox_doctype_id);
|
255
|
+
dr->has_comment = rb_respond_to(handler, ox_comment_id);
|
256
|
+
dr->has_cdata = rb_respond_to(handler, ox_cdata_id);
|
257
|
+
dr->has_text = rb_respond_to(handler, ox_text_id);
|
258
|
+
dr->has_start_element = rb_respond_to(handler, ox_start_element_id);
|
259
|
+
dr->has_end_element = rb_respond_to(handler, ox_end_element_id);
|
260
|
+
dr->has_error = rb_respond_to(handler, ox_error_id);
|
261
261
|
#ifdef HAVE_RUBY_ENCODING_H
|
262
|
-
if ('\0' == *
|
262
|
+
if ('\0' == *ox_default_options.encoding) {
|
263
263
|
dr->encoding = 0;
|
264
264
|
} else {
|
265
|
-
dr->encoding = rb_enc_find(
|
265
|
+
dr->encoding = rb_enc_find(ox_default_options.encoding);
|
266
266
|
}
|
267
267
|
#endif
|
268
268
|
}
|
@@ -329,7 +329,7 @@ sax_drive_error(SaxDrive dr, const char *msg, int critical) {
|
|
329
329
|
args[0] = rb_str_new2(msg);
|
330
330
|
args[1] = INT2FIX(dr->line);
|
331
331
|
args[2] = INT2FIX(dr->col);
|
332
|
-
rb_funcall2(dr->handler,
|
332
|
+
rb_funcall2(dr->handler, ox_error_id, 3, args);
|
333
333
|
} else if (critical) {
|
334
334
|
sax_drive_cleanup(dr);
|
335
335
|
rb_raise(rb_eSyntaxError, "%s at line %d, column %d\n", msg, dr->line, dr->col);
|
@@ -438,7 +438,7 @@ read_instruction(SaxDrive dr) {
|
|
438
438
|
VALUE args[1];
|
439
439
|
|
440
440
|
args[0] = rb_str_new2(dr->str);
|
441
|
-
rb_funcall2(dr->handler,
|
441
|
+
rb_funcall2(dr->handler, ox_instruct_id, 1, args);
|
442
442
|
}
|
443
443
|
if (0 != read_attrs(dr, c, '?', '?', (0 == strcmp("xml", dr->str)))) {
|
444
444
|
return -1;
|
@@ -471,7 +471,7 @@ read_doctype(SaxDrive dr) {
|
|
471
471
|
VALUE args[1];
|
472
472
|
|
473
473
|
args[0] = rb_str_new2(dr->str);
|
474
|
-
rb_funcall2(dr->handler,
|
474
|
+
rb_funcall2(dr->handler, ox_doctype_id, 1, args);
|
475
475
|
}
|
476
476
|
dr->str = 0;
|
477
477
|
|
@@ -513,7 +513,7 @@ read_cdata(SaxDrive dr) {
|
|
513
513
|
rb_enc_associate(args[0], dr->encoding);
|
514
514
|
}
|
515
515
|
#endif
|
516
|
-
rb_funcall2(dr->handler,
|
516
|
+
rb_funcall2(dr->handler, ox_cdata_id, 1, args);
|
517
517
|
}
|
518
518
|
dr->str = 0;
|
519
519
|
|
@@ -557,7 +557,7 @@ read_comment(SaxDrive dr) {
|
|
557
557
|
rb_enc_associate(args[0], dr->encoding);
|
558
558
|
}
|
559
559
|
#endif
|
560
|
-
rb_funcall2(dr->handler,
|
560
|
+
rb_funcall2(dr->handler, ox_comment_id, 1, args);
|
561
561
|
}
|
562
562
|
dr->str = 0;
|
563
563
|
|
@@ -582,7 +582,7 @@ read_element(SaxDrive dr) {
|
|
582
582
|
VALUE args[1];
|
583
583
|
|
584
584
|
args[0] = name;
|
585
|
-
rb_funcall2(dr->handler,
|
585
|
+
rb_funcall2(dr->handler, ox_start_element_id, 1, args);
|
586
586
|
}
|
587
587
|
if ('/' == c) {
|
588
588
|
closed = 1;
|
@@ -606,7 +606,7 @@ read_element(SaxDrive dr) {
|
|
606
606
|
VALUE args[1];
|
607
607
|
|
608
608
|
args[0] = name;
|
609
|
-
rb_funcall2(dr->handler,
|
609
|
+
rb_funcall2(dr->handler, ox_end_element_id, 1, args);
|
610
610
|
}
|
611
611
|
} else {
|
612
612
|
if (0 != read_children(dr, 0)) {
|
@@ -620,7 +620,7 @@ read_element(SaxDrive dr) {
|
|
620
620
|
VALUE args[1];
|
621
621
|
|
622
622
|
args[0] = name;
|
623
|
-
rb_funcall2(dr->handler,
|
623
|
+
rb_funcall2(dr->handler, ox_end_element_id, 1, args);
|
624
624
|
}
|
625
625
|
}
|
626
626
|
dr->str = 0;
|
@@ -654,7 +654,7 @@ read_text(SaxDrive dr) {
|
|
654
654
|
rb_enc_associate(args[0], dr->encoding);
|
655
655
|
}
|
656
656
|
#endif
|
657
|
-
rb_funcall2(dr->handler,
|
657
|
+
rb_funcall2(dr->handler, ox_text_id, 1, args);
|
658
658
|
}
|
659
659
|
return 0;
|
660
660
|
}
|
@@ -711,7 +711,7 @@ read_attrs(SaxDrive dr, char c, char termc, char term2, int is_xml) {
|
|
711
711
|
rb_enc_associate(args[1], dr->encoding);
|
712
712
|
}
|
713
713
|
#endif
|
714
|
-
rb_funcall2(dr->handler,
|
714
|
+
rb_funcall2(dr->handler, ox_attr_id, 2, args);
|
715
715
|
}
|
716
716
|
c = next_non_white(dr);
|
717
717
|
}
|
@@ -801,7 +801,7 @@ partial_io_cb(VALUE rdr) {
|
|
801
801
|
size_t cnt;
|
802
802
|
|
803
803
|
args[0] = ULONG2NUM(dr->buf_end - dr->cur);
|
804
|
-
rstr = rb_funcall2(dr->io,
|
804
|
+
rstr = rb_funcall2(dr->io, ox_readpartial_id, 1, args);
|
805
805
|
str = StringValuePtr(rstr);
|
806
806
|
cnt = strlen(str);
|
807
807
|
//printf("*** read %lu bytes, str: '%s'\n", cnt, str);
|
@@ -831,7 +831,7 @@ io_cb(VALUE rdr) {
|
|
831
831
|
|
832
832
|
args[0] = ULONG2NUM(dr->buf_end - dr->cur);
|
833
833
|
//args[0] = SIZET2NUM(dr->buf_end - dr->cur);
|
834
|
-
rstr = rb_funcall2(dr->io,
|
834
|
+
rstr = rb_funcall2(dr->io, ox_read_id, 1, args);
|
835
835
|
str = StringValuePtr(rstr);
|
836
836
|
cnt = strlen(str);
|
837
837
|
//printf("*** read %lu bytes, str: '%s'\n", cnt, str);
|
data/lib/ox/version.rb
CHANGED
data/test/files.rb
CHANGED
@@ -8,12 +8,11 @@ if $0 == __FILE__
|
|
8
8
|
end
|
9
9
|
|
10
10
|
require 'pp'
|
11
|
-
require '
|
12
|
-
require '
|
13
|
-
require 'test/ox/dir'
|
11
|
+
require 'sample/file'
|
12
|
+
require 'sample/dir'
|
14
13
|
|
15
14
|
def files(dir)
|
16
|
-
d = ::
|
15
|
+
d = ::Sample::Dir.new(dir)
|
17
16
|
Dir.new(dir).each do |fn|
|
18
17
|
next if fn.start_with?('.')
|
19
18
|
filename = File.join(dir, fn)
|
@@ -21,14 +20,10 @@ def files(dir)
|
|
21
20
|
if File.directory?(filename)
|
22
21
|
d << files(filename)
|
23
22
|
else
|
24
|
-
d <<
|
23
|
+
d << ::Sample::File.new(filename)
|
25
24
|
end
|
26
25
|
end
|
27
26
|
#pp d
|
28
27
|
d
|
29
28
|
end
|
30
29
|
|
31
|
-
if $0 == __FILE__
|
32
|
-
File.open('files.xml', "w") { |f| f.write(Ox.dump(files('.'), :indent => 2, :opt_format => true)) }
|
33
|
-
#Ox.to_file(files('.'), 'files2.xml', :indent => 2, :opt_format => true)
|
34
|
-
end
|
data/test/func.rb
CHANGED
@@ -191,6 +191,17 @@ class Func < ::Test::Unit::TestCase
|
|
191
191
|
assert_equal(loaded.class.superclass.to_s, 'Ox::Bag')
|
192
192
|
end
|
193
193
|
|
194
|
+
def test_bad_class
|
195
|
+
xml = %{<?xml version="1.0"?>
|
196
|
+
<o c="Bad:Boy">
|
197
|
+
<i a="@x">3</i>
|
198
|
+
</o>
|
199
|
+
}
|
200
|
+
assert_raise(SyntaxError) {
|
201
|
+
Ox.load(xml, :mode => :object, :trace => 0)
|
202
|
+
}
|
203
|
+
end
|
204
|
+
|
194
205
|
def test_xml_instruction
|
195
206
|
xml = Ox.dump("test", :mode => :object, :with_xml => false)
|
196
207
|
assert_equal("<s>test</s>\n", xml)
|
@@ -430,6 +441,28 @@ class Func < ::Test::Unit::TestCase
|
|
430
441
|
assert_equal("test", obj)
|
431
442
|
end
|
432
443
|
|
444
|
+
def test_generic_string
|
445
|
+
xml = %{<?xml?>
|
446
|
+
<Str>A <boo></Str>
|
447
|
+
}
|
448
|
+
doc = Ox.load(xml, :mode => :generic)
|
449
|
+
xml2 = Ox.dump(doc, :with_xml => true)
|
450
|
+
assert_equal(xml, xml2)
|
451
|
+
end
|
452
|
+
|
453
|
+
def test_generic_encoding
|
454
|
+
if RUBY_VERSION.start_with?('1.8')
|
455
|
+
assert(true)
|
456
|
+
else
|
457
|
+
xml = %{<?xml encoding="UTF-8"?>
|
458
|
+
<Str><まきえ></Str>
|
459
|
+
}
|
460
|
+
doc = Ox.load(xml, :mode => :generic)
|
461
|
+
xml2 = Ox.dump(doc, :with_xml => true)
|
462
|
+
assert_equal(xml, xml2)
|
463
|
+
end
|
464
|
+
end
|
465
|
+
|
433
466
|
def test_IO
|
434
467
|
f = File.open(__FILE__, "r")
|
435
468
|
assert_raise(NotImplementedError) {
|
data/test/perf.rb
ADDED
@@ -0,0 +1,91 @@
|
|
1
|
+
|
2
|
+
class Perf
|
3
|
+
|
4
|
+
def initialize()
|
5
|
+
@items = []
|
6
|
+
end
|
7
|
+
|
8
|
+
def add(title, op, &blk)
|
9
|
+
@items << Item.new(title, op, &blk)
|
10
|
+
end
|
11
|
+
|
12
|
+
def run(iter)
|
13
|
+
base = Item.new(nil, nil) { }
|
14
|
+
base.run(iter, 0.0)
|
15
|
+
@items.each do |i|
|
16
|
+
i.run(iter, base.duration)
|
17
|
+
if i.error.nil?
|
18
|
+
puts "#{i.title}.#{i.op} #{iter} times in %0.3f seconds or %0.3f #{i.op}/sec." % [i.duration, iter / i.duration]
|
19
|
+
else
|
20
|
+
puts "***** #{i.title}.#{i.op} failed! #{i.error}"
|
21
|
+
end
|
22
|
+
end
|
23
|
+
summary()
|
24
|
+
end
|
25
|
+
|
26
|
+
def summary()
|
27
|
+
fastest = nil
|
28
|
+
slowest = nil
|
29
|
+
width = 6
|
30
|
+
@items.each do |i|
|
31
|
+
next if i.duration.nil?
|
32
|
+
width = i.title.size if width < i.title.size
|
33
|
+
end
|
34
|
+
iva = @items.clone
|
35
|
+
iva.delete_if { |i| i.duration.nil? }
|
36
|
+
iva.sort_by! { |i| i.duration }
|
37
|
+
puts
|
38
|
+
puts "Summary:"
|
39
|
+
puts "%*s time (secs) rate (ops/sec)" % [width, 'System']
|
40
|
+
puts "#{'-' * width} ----------- --------------"
|
41
|
+
iva.each do |i|
|
42
|
+
if i.duration.nil?
|
43
|
+
else
|
44
|
+
puts "%*s %11.3f %14.3f" % [width, i.title, i.duration, i.rate ]
|
45
|
+
end
|
46
|
+
end
|
47
|
+
puts
|
48
|
+
puts "Comparison Matrix\n(performance factor, 2.0 row is means twice as fast as column)"
|
49
|
+
puts ([' ' * width] + iva.map { |i| "%*s" % [width, i.title] }).join(' ')
|
50
|
+
puts (['-' * width] + iva.map { |i| '-' * width }).join(' ')
|
51
|
+
iva.each do |i|
|
52
|
+
line = ["%*s" % [width, i.title]]
|
53
|
+
iva.each do |o|
|
54
|
+
line << "%*.2f" % [width, o.duration / i.duration]
|
55
|
+
end
|
56
|
+
puts line.join(' ')
|
57
|
+
end
|
58
|
+
puts
|
59
|
+
end
|
60
|
+
|
61
|
+
class Item
|
62
|
+
attr_accessor :title
|
63
|
+
attr_accessor :op
|
64
|
+
attr_accessor :blk
|
65
|
+
attr_accessor :duration
|
66
|
+
attr_accessor :rate
|
67
|
+
attr_accessor :error
|
68
|
+
|
69
|
+
def initialize(title, op, &blk)
|
70
|
+
@title = title
|
71
|
+
@blk = blk
|
72
|
+
@op = op
|
73
|
+
@duration = nil
|
74
|
+
@rate = nil
|
75
|
+
@error = nil
|
76
|
+
end
|
77
|
+
|
78
|
+
def run(iter, base)
|
79
|
+
begin
|
80
|
+
start = Time.now
|
81
|
+
iter.times { @blk.call }
|
82
|
+
@duration = Time.now - start - base
|
83
|
+
@duration = 0.0 if @duration < 0.0
|
84
|
+
@rate = iter / @duration
|
85
|
+
rescue Exception => e
|
86
|
+
@error = "#{e.class}: #{e.message}"
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
end # Item
|
91
|
+
end # Perf
|