simplecsv 0.1.2 → 0.1.3

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.
@@ -1,5 +1,6 @@
1
1
  2007-03-18 DATE Ken <itacchi@gmail.com>
2
2
 
3
+ * add SimpleCSV#on_field and SimpleCSV#on_row for parser cutomizing
3
4
  * fix bug: options parameter of SimpleCSV.new do not effect SimpleCSV#parser
4
5
  * implements SimpleCSV#options and SimpleCSV#options=
5
6
 
@@ -1,3 +1,8 @@
1
+ 2007-03-18
2
+
3
+ * 0.1.3
4
+ * add new feature that can customize parsing behavior on subclass
5
+
1
6
  2007-03-18
2
7
 
3
8
  * 0.1.2
data/README.txt CHANGED
@@ -1,4 +1,4 @@
1
- SimpleCSV 0.1.2 README
1
+ SimpleCSV 0.1.3 README
2
2
 
3
3
  What is:
4
4
  SimpleCSV provides simple api to read/write csv.
data/TODO CHANGED
@@ -1,4 +1,3 @@
1
1
  * stream input
2
2
  * refactoring (parse method)
3
- * subclass sutomizing by template method pattern
4
3
  * convenience method such as parse_file
@@ -33,6 +33,7 @@ struct csv_parser_object {
33
33
  }\
34
34
  }
35
35
 
36
+
36
37
  static void free_parser_object(struct csv_parser_object* parser_object)
37
38
  {
38
39
  if (parser_object){
@@ -44,7 +45,7 @@ static void free_parser_object(struct csv_parser_object* parser_object)
44
45
  }
45
46
 
46
47
 
47
- static void field_callback(char* s, size_t i, void* obj)
48
+ static void default_field_callback(char* s, size_t i, void* obj)
48
49
  {
49
50
  VALUE row, str;
50
51
 
@@ -53,7 +54,8 @@ static void field_callback(char* s, size_t i, void* obj)
53
54
  rb_ary_push(row, str);
54
55
  }
55
56
 
56
- static void row_callback(char c, void* obj)
57
+
58
+ static void default_row_callback(char c, void* obj)
57
59
  {
58
60
  VALUE row;
59
61
 
@@ -63,6 +65,32 @@ static void row_callback(char c, void* obj)
63
65
  }
64
66
 
65
67
 
68
+ static void field_callback(char* s, size_t i, void* obj)
69
+ {
70
+ VALUE str, len, proc;
71
+
72
+ str = rb_str_new(s, i);
73
+ proc = rb_ivar_get((VALUE)obj, rb_intern("'proc'"));
74
+
75
+ rb_funcall((VALUE)obj, rb_intern("on_field"), 2, str, proc);
76
+ }
77
+
78
+
79
+ static void row_callback(char c, void* obj)
80
+ {
81
+ VALUE str, proc;
82
+ char row_delimiter[2];
83
+
84
+ row_delimiter[0] = c;
85
+ row_delimiter[1] = 0;
86
+
87
+ str = rb_str_new2(row_delimiter);
88
+ proc = rb_ivar_get((VALUE)obj, rb_intern("'proc'"));
89
+
90
+ rb_funcall((VALUE)obj, rb_intern("on_row"), 2, str, proc);
91
+ }
92
+
93
+
66
94
  /*
67
95
  * call-seq:
68
96
  * parse(str, options = nil){|row| ...}
@@ -144,7 +172,7 @@ static VALUE simplecsv_s_parse(int argc, VALUE* argv, VALUE klass)
144
172
  rb_ivar_set(klass, rb_intern("'row'"), rb_ary_new());
145
173
 
146
174
  len = RSTRING(str)->len;
147
- if (csv_parse(parser, StringValuePtr(str), len, field_callback, row_callback, (void*)klass) != len) {
175
+ if (csv_parse(parser, StringValuePtr(str), len, default_field_callback, default_row_callback, (void*)klass) != len) {
148
176
  switch (csv_error(parser)) {
149
177
  case CSV_EPARSE:
150
178
  rb_raise(eCSVParseError, "error while parsing by malformed data");
@@ -163,7 +191,7 @@ static VALUE simplecsv_s_parse(int argc, VALUE* argv, VALUE klass)
163
191
  }
164
192
  }
165
193
 
166
- csv_fini(parser, field_callback, row_callback, (void*)klass);
194
+ csv_fini(parser, default_field_callback, default_row_callback, (void*)klass);
167
195
  csv_free(parser);
168
196
 
169
197
  return Qnil;
@@ -343,14 +371,23 @@ static VALUE simplecsv_set_options(VALUE self, VALUE opts)
343
371
  * [SimpleCSV::ParseError] failed to parse.
344
372
  * [LocalJumpError] You must call this method with block.
345
373
  */
346
- static VALUE simplecsv_parse(VALUE self, VALUE str)
374
+ static VALUE simplecsv_parse(int argc, VALUE* argv, VALUE self)
347
375
  {
376
+ VALUE str, proc;
348
377
  struct csv_parser_object* parser_object;
349
378
  struct csv_parser* parser;
350
379
  int len;
351
380
 
381
+ rb_scan_args(argc, argv, "1&", &str, &proc);
382
+
352
383
  Check_Type(str, T_STRING);
353
384
 
385
+ if (CLASS_OF(self) == cSimpleCSV) {
386
+ rb_need_block();
387
+ }
388
+
389
+ rb_ivar_set(self, rb_intern("'proc'"), proc);
390
+
354
391
  Get_Parser(self, parser_object, parser);
355
392
 
356
393
  len = RSTRING(str)->len;
@@ -380,6 +417,53 @@ static VALUE simplecsv_parse(VALUE self, VALUE str)
380
417
 
381
418
 
382
419
 
420
+ /*
421
+ * call-seq:
422
+ * on_field(str, pr)
423
+ *
424
+ * This method is called when processing each field.
425
+ * You can write "pr.call(some_val)" for pass value to block of `parse' method.
426
+ *
427
+ * ==== Parameters
428
+ * [str] <code>String</code> : field text.
429
+ * [pr] <code>Proc</code> : a block, passing by `parse' method
430
+ */
431
+ static VALUE simplecsv_on_field(VALUE self, VALUE str, VALUE proc)
432
+ {
433
+ VALUE row;
434
+
435
+ row = rb_ivar_get(self, rb_intern("'row'"));
436
+ rb_ary_push(row, str);
437
+
438
+ return Qnil;
439
+ }
440
+
441
+
442
+
443
+ /*
444
+ * call-seq:
445
+ * on_row(str, pr)
446
+ *
447
+ * This method is called when processing each row.
448
+ * You can write "pr.call(some_val)" for pass value to block of `parse' method.
449
+ *
450
+ * ==== Parameters
451
+ * [str] <code>String</code> : row delimitor (\n).
452
+ * [pr] <code>Proc</code> : a block, passing by `parse' method
453
+ */
454
+ static VALUE simplecsv_on_row(VALUE self, VALUE str, VALUE proc)
455
+ {
456
+ VALUE row;
457
+
458
+ row = rb_ivar_get(self, rb_intern("'row'"));
459
+ rb_funcall(proc, rb_intern("call"), 1, row);
460
+ rb_ivar_set(self, rb_intern("'row'"), rb_ary_new());
461
+
462
+ return Qnil;
463
+ }
464
+
465
+
466
+
383
467
  void Init_simplecsv(void)
384
468
  {
385
469
  cSimpleCSV = rb_define_class("SimpleCSV", rb_cObject);
@@ -399,6 +483,8 @@ void Init_simplecsv(void)
399
483
  rb_define_method(cSimpleCSV, "initialize", simplecsv_initialize, -1);
400
484
  rb_define_method(cSimpleCSV, "options", simplecsv_get_options, 0);
401
485
  rb_define_method(cSimpleCSV, "options=", simplecsv_set_options, 1);
402
- rb_define_method(cSimpleCSV, "parse", simplecsv_parse, 1);
486
+ rb_define_method(cSimpleCSV, "parse", simplecsv_parse, -1);
403
487
  rb_define_method(cSimpleCSV, "write", simplecsv_s_write, 1);
488
+ rb_define_method(cSimpleCSV, "on_field", simplecsv_on_field, 2);
489
+ rb_define_method(cSimpleCSV, "on_row", simplecsv_on_row, 2);
404
490
  }
@@ -1,8 +1,8 @@
1
- module SimpleCSV #:nodoc:
1
+ class SimpleCSV #:nodoc:
2
2
  module VERSION #:nodoc:
3
3
  MAJOR = 0
4
4
  MINOR = 1
5
- TINY = 2
5
+ TINY = 3
6
6
 
7
7
  STRING = [MAJOR, MINOR, TINY].join('.')
8
8
  end
@@ -194,7 +194,9 @@ _CSV_
194
194
  simplecsv.parse(''){}
195
195
  end
196
196
 
197
- assert_nil simplecsv.parse('')
197
+ assert_raise(LocalJumpError) do
198
+ assert_nil simplecsv.parse('')
199
+ end
198
200
 
199
201
  simplecsv.parse(<<_CSV_) do |row|
200
202
  test
@@ -285,6 +287,16 @@ _CSV_
285
287
  _CSV_
286
288
  end
287
289
 
290
+ rows = 0
291
+ simplecsv = SimpleCSV.new(SimpleCSV::REPALL_NL)
292
+ simplecsv.parse(<<_CSV_) do |row|
293
+
294
+
295
+
296
+ _CSV_
297
+ rows += 1
298
+ end
299
+ assert_equal 3, rows
288
300
  end
289
301
 
290
302
  def test_write
@@ -311,4 +323,49 @@ _CSV_
311
323
  simplecsv.write([1, 2, 3])
312
324
  end
313
325
  end
326
+
327
+ def test_options
328
+ simplecsv = SimpleCSV.new
329
+ assert_equal 0, simplecsv.options
330
+
331
+ simplecsv = SimpleCSV.new(SimpleCSV::STRICT)
332
+ assert_equal SimpleCSV::STRICT, simplecsv.options
333
+
334
+ simplecsv = SimpleCSV.new(SimpleCSV::REPALL_NL)
335
+ assert_equal SimpleCSV::REPALL_NL, simplecsv.options
336
+
337
+ simplecsv = SimpleCSV.new(SimpleCSV::STRICT | SimpleCSV::REPALL_NL)
338
+ assert_equal SimpleCSV::STRICT | SimpleCSV::REPALL_NL, simplecsv.options
339
+
340
+ simplecsv = SimpleCSV.new
341
+ simplecsv.options = SimpleCSV::STRICT
342
+ assert_equal SimpleCSV::STRICT, simplecsv.options
343
+
344
+ simplecsv = SimpleCSV.new(SimpleCSV::STRICT)
345
+ simplecsv.options = nil
346
+ assert_equal 0, simplecsv.options
347
+ end
348
+
349
+ class FirstLetter < SimpleCSV
350
+ def initialize
351
+ @ary = []
352
+ end
353
+
354
+ def on_field(str, pr)
355
+ @ary << str[0, 1]
356
+ end
357
+
358
+ def on_row(str, pr)
359
+ pr.call(@ary)
360
+ @ary = []
361
+ end
362
+ end
363
+
364
+ def test_subclass_customizing
365
+ FirstLetter.new.parse(<<_CSV_) do |row|
366
+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit.
367
+ _CSV_
368
+ assert_equal ["L", "c"], row
369
+ end
370
+ end
314
371
  end
metadata CHANGED
@@ -3,7 +3,7 @@ rubygems_version: 0.8.11
3
3
  specification_version: 1
4
4
  name: simplecsv
5
5
  version: !ruby/object:Gem::Version
6
- version: 0.1.2
6
+ version: 0.1.3
7
7
  date: 2007-03-18 00:00:00 +09:00
8
8
  summary: SimpleCSV privides simple csv reading/writing api.
9
9
  require_paths: