forked from Leapus/hamcreek
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcsv.cpp
95 lines (78 loc) · 2.32 KB
/
csv.cpp
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
#include <string>
#include <streambuf>
#include <vector>
#include "csv_exception.hpp"
#include "csv.hpp"
using namespace std::string_literals;
using namespace leapus::csv;
using namespace leapus::exception;
::csv_parser &CSVParser::libcsv(){
return m_libcsv;
}
CSVParser *CSVParser::cast_this(void *user_data){
return static_cast<CSVParser *>(user_data);
}
void CSVParser::field_callback(void *str, size_t len, void *user_data){
auto that = CSVParser::cast_this(user_data);
if(that->m_skip_row) return;
that->field(std::string((char *)str,len));
}
void CSVParser::record_callback(int lastchar, void *user_data){
auto that = CSVParser::cast_this(user_data);
if(that->m_skip_row){
that->m_skip_row = false;
return;
}
that->record();
}
CSVParser::CSVParser(){
csv_exception::check(::csv_init(&m_libcsv, 0), m_libcsv);
}
void CSVParser::parse(const char *data, size_t sz){
csv_exception::check( ::csv_parse(&m_libcsv, data, sz, field_callback, record_callback, this), m_libcsv );
}
void CSVParser::skip_row(){
m_skip_row=true;
}
CSVFile::CSVFile(const std::filesystem::path &path, CSVParser &parser, std::ios_base::openmode mode):
m_parser(parser){
m_filebuf.open(path, mode);
if(!m_filebuf.is_open())
throw std::runtime_error("Failed opening CSV file: "s + path.string());
}
size_t CSVFile::parse(){
size_t sz = m_filebuf.sgetn(m_buf, block_size);
m_parser.parse(m_buf, sz);
return sz;
}
size_t CSVFile::parse_all(){
size_t sz, ct=0;
do{
sz=parse();
ct+=sz;
}while(sz > 0);
return ct;
}
void CSVFile::write_field(const std::string &str){
size_t sz = csv_write(m_outbuf.data(), m_outbuf.size(), str.data(), str.size());
if(sz > m_outbuf.size()){
m_outbuf.resize(sz);
write_field(str);
}
else{
//prepend a comma separator unless it's the first field in the record
if(m_first_field_out){
m_first_field_out = false;
}
else{
m_filebuf.sputc(',');
}
m_filebuf.sputn(m_outbuf.data(), sz);
}
}
//Seems like most radio apps are Windows products, and will likely expect CRLF
void CSVFile::end_record(){
m_filebuf.sputc('\r');
m_filebuf.sputc('\n');
m_first_field_out=true; //remember to skip the leading comma
}