ext/ccsv.c in ccsv-0.1.2 vs ext/ccsv.c in ccsv-1.0.1
- old
+ new
@@ -1,34 +1,165 @@
+#include <limits.h>
#include "ccsv.h"
static VALUE rb_cC;
-static VALUE foreach(VALUE self, VALUE filename) {
+/* Ccsv.foreach(filename,delimiter,[index],[range,...]) do |line| ... */
- FILE *file = fopen(StringValueCStr(filename), "r");
- if (file == NULL)
- rb_raise(rb_eRuntimeError, "File not found");
+struct pair_st {
+ long int low,high;
+};
+#define MAX_INTERVALS 1024
+
+static VALUE foreach(int argc, VALUE* argv, VALUE self) {
+ char DELIM=DEF_DELIM;
char *line = NULL;
size_t len = 0;
- char *token;
- int idx;
+ char *token,*start,*nobackslash,*t2, *str;
+ int idx,count,pairs_count,searchfield,flag,i,array_length,range_i,len2;
+ long check;
+ FILE *file;
+ ID min_method, max_method;
+ VALUE min_val, max_val;
+ VALUE tmp_value, rest_args, filename;
+ ID array_length_method; /*----------------------------------------*/
+ struct pair_st pairs[MAX_INTERVALS];
VALUE ary;
-
+
+ rb_scan_args(argc,argv,"1*", &filename, &rest_args);
+
+/* if (argc == 0) { // there should only be 1 or 2 arguments
+ rb_raise(rb_eArgError, "wrong number of arguments");
+ }
+
+ file = fopen(StringValueCStr(argv[0]), "r");
+ if (file == NULL)
+ rb_raise(rb_eRuntimeError, "File not found");
+*/
+ file = fopen(StringValueCStr(filename), "r");
+ if(file==NULL){
+ rb_raise(rb_eRuntimeError, "File not found");
+ }
+
+ if (argc >1 ) { /* delimiter */
+ tmp_value=rb_ary_entry(rest_args,0);
+ str=StringValueCStr(tmp_value);
+ DELIM=str[0];
+ }
+
+ if (argc >2 ) { /* search index */
+ tmp_value=rb_ary_entry(rest_args,1);
+ searchfield=NUM2INT(tmp_value);
+ }
+ else{
+ searchfield=-1;
+ }
+
+ min_val=rb_funcall(rest_args,rb_intern("length"), 0);
+ array_length=NUM2INT(min_val);
+ /*rb_warn("Length=%d",array_length);*/
+
+ min_method = rb_intern("min");
+ max_method = rb_intern("max");
+ /*------------test_id = rb_intern("class");*/
+ range_i=0;
+ for(idx=2;idx<array_length;++idx){
+ min_val=rb_funcall(rb_ary_entry(rest_args,idx),rb_intern("length"), 0);
+ len2=NUM2INT(min_val);
+ for(i=0;i<len2;++i){
+ VALUE e=rb_ary_entry(rb_ary_entry(rest_args,idx),i);
+ if(range_i>MAX_INTERVALS)
+ rb_raise(rb_eRuntimeError, "Too much ranges passed");
+ if(TYPE(e) == T_NIL){
+ pairs[range_i].low=LONG_MIN;
+ pairs[range_i].high=LONG_MAX;
+
+ continue; /* just skip nil */
+ }
+ if (! (rb_respond_to(e, min_method) & rb_respond_to(e, max_method)))
+ rb_raise(rb_eRuntimeError, "Not range passed to Ccsv.foreach");
+
+ min_val=rb_funcall(e, min_method, 0);
+ max_val=rb_funcall(e, max_method, 0);
+ /* rb_warn("!\n");*/
+ pairs[range_i].low=NUM2LONG(min_val);
+ /*rb_warn("2\n");*/
+ pairs[range_i].high=NUM2LONG(max_val);
+ /*rb_warn("RANGE: %ld .. %ld (%d)\n",(long)pairs[range_i].low,(long)pairs[range_i].high,(int)(range_i));*/
+ range_i++;
+ }
+ }
+ pairs_count=range_i;
+
while (getline(&line, &len, file) != -1) {
+ /* chomp! */
+ if(token=index(line,EOL)){
+ *token='\0';
+ }
+ /*rb_warning("4\n");*/
ary = rb_ary_new();
- token = strtok(line, DELIMITERS);
+ start=line;
+ nobackslash=line;
+ while(token=index(nobackslash, DELIM)){
+/* rb_warning("5\n");*/
+ count=0;
+ t2=token-1;
+ while((t2>=line) && (*t2=='\\'))
+ {++count;--t2;}
+ if(count%2 ==1){ /* backslashed! skip */
+ nobackslash=token;
+ continue;
+ }
+ break;
+ }
idx = 0;
+ flag=1;
while (token != NULL) {
- rb_ary_store(ary, idx, rb_str_new(token, strlen(token)));
- idx ++;
- token = strtok(NULL, DELIMITERS);
+ *token='\0';
+ if(searchfield==idx){
+ flag=0;
+ /* do check! */
+ sscanf(start,"%ld",&check);
+ for(i=0;i<pairs_count;++i){
+ /*rb_warn("check %ld: [%ld .. %ld]",check,pairs[i].low,pairs[i].high);*/
+ if(pairs[i].low<check && pairs[i].high>check){
+ /*rb_warn("check passed");*/
+ flag=1; /* yahooo! */
+ break;
+ }
+ }
+ }
+
+ /* not in ranges! */
+ if(flag==0)
+ break;
+
+ rb_ary_store(ary, idx, rb_str_new(start, token-start));
+ idx++;
+ nobackslash=start=token+1;
+ while(token=index(nobackslash, DELIM)){
+ count=0;
+ t2=token-1;
+ while((t2>=line) && (*t2=='\\'))
+ {++count;--t2;}
+ if(count%2 ==1){ /* backslashed! skip */
+ nobackslash=token;
+ continue;
+ }
+ break;
+ }
}
+ if(flag==0)
+ continue;
+ /* last item */
+ rb_ary_store(ary, idx, rb_str_new(start, strlen(start)));
/* OBJ_FREEZE(ary); */
+
rb_yield(ary);
/* FL_UNSET((ary), FL_FREEZE); */
/* for(idx = 0; idx < RARRAY_LEN(ary); idx ++) {
rb_ary_store(ary, idx, Qnil);
@@ -43,7 +174,9 @@
void
Init_ccsv()
{
rb_cC = rb_define_class("Ccsv", rb_cObject);
- rb_define_singleton_method(rb_cC, "foreach", foreach, 1);
+ rb_define_singleton_method(rb_cC, "foreach", foreach, -1);
+ rb_define_const(rb_cC, "MAX", LONG2NUM(LONG_MAX));
+ rb_define_const(rb_cC, "MIN", LONG2NUM(LONG_MIN));
}