simplecsv 0.1.2 → 0.1.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -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: