-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcsv_select.c
More file actions
148 lines (139 loc) · 4.6 KB
/
csv_select.c
File metadata and controls
148 lines (139 loc) · 4.6 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
/**********************************************
* libcsv, Version 0.3 Alpha *
* Description: CSV library for C *
* Author: Michael Warren, a.k.a Psycho Cod3r *
* Date: November 2020 *
* License: Michael Warren FSL Version 1.1 *
* Current module: Implementation of SQL *
* SELECT command *
**********************************************/
#include <stdlib.h>
#include <string.h>
#include "csv.h"
#include "dfloat.h"
// Creates a set type indexing the records in a table that
// match the expression given by the operator and operand
csv_set *csv_select_subset( csv_table *table, enum operators operator, char *field, char *value ){
csv_set *subset;
int rcount; // # of records in table
csv_record *save;
int i, f;
dfloat64_t *number_field;
dfloat64_t *number_value;
int int1, int2;
char *string_field;
save = table->cur;
// Find the field with the given name:
if( operator != MOD ){
for( f = 0; f < table->rlen; f++ ){
if( !strcmp( table->header[f]->name, field ) )
break;
}
if( f == table->rlen )
// Error: Name not found
return NULL;
}
// Count records in table and use record
// count to create an empty set object:
csv_rewind( table );
rcount = 0;
while( csv_next_record( table ) )
rcount++;
csv_rewind( table );
subset = csv_empty_set( rcount );
for( i = 0; i < rcount; i++ ){
csv_next_record( table );
if( operator == EQ || operator == NE || operator == LT || operator == GT || operator == LE || operator == GE ){
// Numerical comparison operators
if( table->header[f]->type != csv_number )
return NULL;
number_field = csv_get_number_field_by_name( table, field );
number_value = dfloat64_atof( value );
switch( operator ){
case EQ : if( !dfloat64_cmp( number_field, number_value ) )
csv_set_add( subset, i );
break;
case NE : if( dfloat64_cmp( number_field, number_value ) )
csv_set_add( subset, i );
break;
case LT : if( dfloat64_cmp( number_field, number_value ) == -1 )
csv_set_add( subset, i );
break;
case GT : if( dfloat64_cmp( number_field, number_value ) == 1 )
csv_set_add( subset, i );
break;
case LE : if( dfloat64_cmp( number_field, number_value ) <= 0 )
csv_set_add( subset, i );
break;
case GE : if( dfloat64_cmp( number_field, number_value ) >= 0 )
csv_set_add( subset, i );
break;
}
free( number_field );
free( number_value );
}
else if( operator == MOD ){
// Modulus operator
int1 = atoi( field );
int2 = atoi( value );
if( i % int1 == int2 )
csv_set_add( subset, i );
}
else if( operator == SEQ || operator == SNE ){
// String comparison operators
if( table->header[f]->type != csv_string )
return NULL;
string_field = csv_get_string_field_by_name( table, field );
if( operator == SEQ ){
if( !strcmp( string_field, value ) )
csv_set_add( subset, i );
}
else{
if( strcmp( string_field, value ) )
csv_set_add( subset, i );
}
}
}
table->cur = save;
return subset;
}
// Creates a new table consisting of all the records in the
// given table indexed by the given set type
csv_table *csv_select_records_by_subset( csv_table *table, csv_set *subset ){
csv_record *save;
csv_table *subtab;
int rnum;
save = table->cur;
subtab = csv_create_table( table->rlen, table->header );
csv_rewind( table );
rnum = 0;
// Loop copies from table to subtab all records whose bit in the
// given subset is set
while( csv_next_record( table ) ){
if( csv_set_member( rnum++, subset ) )
csv_insert_record( subtab, table->cur->record );
}
table->cur = save;
return subtab;
}
// Returns a partition including the subset and its complement
csv_partition *csv_partition_table_by_subset( csv_table *table, csv_set *subset ){
csv_record *save;
csv_partition *partition;
int rnum;
save = table->cur;
partition = (csv_partition *) malloc( sizeof( csv_partition ) );
partition->ident = csv_create_table( table->rlen, table->header );
partition->cplmt = csv_create_table( table->rlen, table->header );
rnum = 0;
// Loop copies all records with 1 bits to ident and all records
// with 0 bits to cplmt
while( csv_next_record( table ) ){
if( csv_set_member( rnum++, subset ) )
csv_insert_record( partition->ident, table->cur->record );
else
csv_insert_record( partition->cplmt, table->cur->record );
}
table->cur = save;
return partition;
}