main
 1#include "spandx.h"
 2
 3#define NEWLINE 10
 4
 5VALUE rb_mSpandx;
 6VALUE rb_mCore;
 7VALUE rb_mCsvParser;
 8
 9// "name","version","license"
10// "name","version","license"\n
11// "name","version","license"\r
12// "name","version","license"\r\n
13// "name","version",""\r\n
14VALUE parse(VALUE self, VALUE line)
15{
16  if (NIL_P(line)) return Qnil;
17
18  char *p;
19
20  p = RSTRING_PTR(line);
21  if (*p != '"') return Qnil;
22
23  const VALUE items = rb_ary_new2(3);
24  const char *s, *n;
25  const long len = RSTRING_LEN(line);
26  enum { open, closed } state = closed;
27
28  for (int i = 0; i < len && *p; i++) {
29    if (*p == '"') {
30      n = p;
31      if (i < (len - 1)) *n++;
32
33      if (state == closed) {
34        s = n;
35        state = open;
36      } else if (state == open) {
37        if (!*n || n == p || *n == ',' || *n == NEWLINE) {
38          rb_ary_push(items, rb_str_new(s, p - s));
39          state = closed;
40        }
41      }
42    }
43    *(p++);
44  }
45
46  return items;
47}
48
49void Init_spandx(void)
50{
51  rb_mSpandx = rb_define_module("Spandx");
52  rb_mCore = rb_define_module_under(rb_mSpandx, "Core");
53  rb_mCsvParser = rb_define_module_under(rb_mCore, "CsvParser");
54  rb_define_module_function(rb_mCsvParser, "parse", parse, 1);
55
56  rb_gc_register_mark_object(rb_mCsvParser);
57}