-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcsv.cpp
More file actions
125 lines (107 loc) · 3.2 KB
/
csv.cpp
File metadata and controls
125 lines (107 loc) · 3.2 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
struct Csv {
Array<u8> data;
s64 index;
Status* status;
u8 sep = ',';
};
void csv_init(Csv* csv, Array<u8> data, Status* status=nullptr) {
if (os_status_initp(&status)) return;
csv->status = status;
csv->data = data;
csv->index = 0;
}
void csv_open(Csv* csv, Array<u8> path, Status* status=nullptr) {
csv_init(csv, os_read_file(path, status), status);
}
void csv_free(Csv* csv) {
array_free(&csv->data);
csv->index = -1;
}
bool csv_empty(Csv* csv) {
if (csv->status->bad()) return true;
return csv->index >= csv->data.size;
}
Array<u8> csv_str(Csv* csv) {
if (csv->status->bad()) return {};
if (csv_empty(csv)) {
os_error_print(csv->status, 20240111011, "Cannot read string from csv, eof\n");
return {};
}
s64 start = csv->index;
if (csv->data[csv->index] == '"') {
s64 j = start;
++csv->index;
for (; csv->index < csv->data.size; ++csv->index) {
u8 c = csv->data[csv->index];
u8 cc = csv->index+1 < csv->data.size ? csv->data[csv->index+1] : 0;
if (c == '"' and cc == '"') {
++csv->index;
} else if (c == '"') {
++csv->index;
if (cc == ',') {
++csv->index;
} else {
if (cc != '\n') {
os_error_print(csv->status, 20240111013, "csv quoted string must be followed by , or newline\n");
return {};
}
}
break;
}
csv->data[j++] = c;
}
return array_subarray(csv->data, start, j);
} else {
s64 end = -1;
for (; csv->index < csv->data.size; ++csv->index) {
u8 c = csv->data[csv->index];
if (c == csv->sep) {
end = csv->index;
++csv->index; break;
} else if (c == '\n') {
end = csv->index;
break;
}
}
if (csv->index == csv->data.size) {
os_error_print(csv->status, 20240111012, "csv does not end in newline\n");
return {};
}
return array_subarray(csv->data, start, end);
}
}
s64 csv_int(Csv* csv) {
auto arr = csv_str(csv);
u64 number = 0;
bool sign = false;
s64 i = 0;
for (; i < arr.size && arr[i] == '-'; ++i) {
sign ^= 1;
}
for (; i < arr.size; ++i) {
u8 c = arr[i];
if ('0' <= c and c <= '9') {
number = 10*number + c - '0';
} else {
os_error_print(csv->status, 20240111014, "csv int contains invalid characters\n");
return 0;
}
}
return sign ? -number : number;
}
#ifdef PHILIB_NUMBER
float csv_float(Csv* csv) {
auto arr = csv_str(csv);
return number_parse<float>(arr, csv->status);
}
double csv_double(Csv* csv) {
auto arr = csv_str(csv);
return number_parse<double>(arr, csv->status);
}
#endif
void csv_row(Csv* csv) {
if (csv->index >= csv->data.size or csv->data[csv->index] != '\n') {
return os_error_print(csv->status, 20240111015, "csv row does not end\n");
}
++csv->index;
}