-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathcsv_handler.h
392 lines (299 loc) · 13.3 KB
/
csv_handler.h
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
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
#pragma once
// C++ STL
#include <iostream>
#include <vector>
#include <initializer_list>
// CGV framework core
#include <cgv/math/fvec.h>
#include <cgv/math/fmat.h>
#include <cgv/media/color.h>
// local includes
#include "traj_loader.h"
/// possible special semantics of attributes found in .csv column(s)
enum class CSV_AttribSemantics
{
ARBITRARY=0, POS, TRAJ_ID, TIMESTAMP
};
#if !defined(CSV_HANDLER_NO_SHORTHAND_ENUM_CSV) || CSV_HANDLER_NO_SHORTHAND_ENUM_CSV==0
/// convenience shorthand for \ref CSV_AttribSemantics
typedef CSV_AttribSemantics CSV;
#endif
/// table format descriptor to identify a supported .csv file.
class csv_descriptor
{
public:
/// Implementation details forward declaration
struct Impl;
/// collection of properties of a .csv descriptor
struct csv_properties
{
struct
{
/// indicates if readable .csv files must have a header row
unsigned char header : 1,
/// indicates if readable .csv files can store more than one trajectory
multi_traj : 1;
};
/// indicates the largest .csv column number referenced by any attribute in the descriptor
unsigned max_col_id;
/// indicates the index of the position attribute in declared attribute list
unsigned pos_id;
/// indicates the index of the trajectory id attribute in the declared attribute list, if any
unsigned traj_id;
};
/// descriptor of one attribute (potentially composed from many columns) encoded in the .csv file
/// ToDo: Add way to describe the data format of a column, right now we always assume one scalar
/// per column. It would be nice to be able to specify string encodings of other data types
/// (like actual strings or composite types like vectors or matrices)
struct attribute
{
/// struct describing a specific .csv data column
struct column
{
/// name of the attribute as specified in the .csv header row
std::string name;
/// whether \ref #name should be treated as case-sensitive or not
bool case_sensitive;
/// the number of this column within the .csv table structure (used only when header-less
/// .csv support is requested)
int number;
/// default constructor
inline column() : case_sensitive(false), number(-1)
{}
/// copy constructor
inline column(const column &other)
: name(other.name), case_sensitive(other.case_sensitive), number(other.number)
{}
/// move constructor
inline column(column &&other)
: name(std::move(other.name)), case_sensitive(other.case_sensitive), number(other.number)
{}
/// constructs with the given case-insensitive name
inline column(const std::string &name)
: name(name), case_sensitive(false), number(-1)
{}
/// constructs with the given case-insensitive name (move semantics)
inline column(std::string &&name)
: name(std::move(name)), case_sensitive(false), number(-1)
{}
/// constructs with the given name and case-sensitivity
inline column(const std::string &name, bool case_sensitive)
: name(name), case_sensitive(case_sensitive), number(-1)
{}
/// constructs with the given name (move semantics) and case-sensitivity
inline column(std::string &&name, bool case_sensitive)
: name(std::move(name)), case_sensitive(case_sensitive), number(-1)
{}
/// constructs with the given name and column number
inline column(const std::string &name, int number)
: name(name), case_sensitive(false), number(number)
{}
/// constructs with the given name (move semantics) and column number
inline column(std::string &&name, int number)
: name(std::move(name)), case_sensitive(false), number(number)
{}
/// constructs with the given name, case-sensitivity and column number
inline column(const std::string &name, bool case_sensitive, int number)
: name(name), case_sensitive(case_sensitive), number(number)
{}
/// constructs with the given name (move semantics), case-sensitivity and column number
inline column(std::string &&name, bool case_sensitive, int number)
: name(std::move(name)), case_sensitive(case_sensitive), number(number)
{}
/// copy assignment
inline column& operator= (const column &other)
{
name = other.name;
case_sensitive = other.case_sensitive;
number = other.number;
return *this;
}
/// move assignment
inline column& operator= (column &&other)
{
name = std::move(other.name);
case_sensitive = other.case_sensitive;
number = other.number;
return *this;
}
};
/// name of the attribute
std::string name;
/// special semantics of this attribute (if applicable)
CSV_AttribSemantics semantics;
/// .csv columns to read samples of this attribute from
std::vector<column> columns;
/// default constructor
attribute() : semantics(CSV::ARBITRARY) {}
/// copy constructor
inline attribute(const attribute &other)
: name(other.name), semantics(other.semantics), columns(other.columns)
{}
/// move constructor
inline attribute(attribute &&other)
: name(std::move(other.name)), semantics(other.semantics), columns(std::move(other.columns))
{}
/// constructs the attribute with given name (copied in), single assigned .csv column (copied in) and semantics
inline attribute(const std::string &name, const column &csv_column,
CSV_AttribSemantics semantics=CSV_AttribSemantics::ARBITRARY)
: name(name), semantics(semantics)
{
columns.emplace_back(csv_column);
}
/// constructs the attribute with given name (copied in), single assigned .csv column (moved in) and semantics
inline attribute(const std::string &name, column &&csv_column,
CSV_AttribSemantics semantics=CSV_AttribSemantics::ARBITRARY)
: name(name), semantics(semantics)
{
columns.emplace_back(std::move(csv_column));
}
/// constructs the attribute with given name (moved in), single assigned .csv column (copied in) and semantics
inline attribute(std::string &&name, const column &csv_column,
CSV_AttribSemantics semantics=CSV_AttribSemantics::ARBITRARY)
: name(std::move(name)), semantics(semantics)
{
columns.emplace_back(csv_column);
}
/// constructs the attribute with given name (moved in), single assigned .csv column (moved in) and semantics
inline attribute(std::string &&name, column &&csv_column,
CSV_AttribSemantics semantics=CSV_AttribSemantics::ARBITRARY)
: name(std::move(name)), semantics(semantics)
{
columns.emplace_back(std::move(csv_column));
}
/// constructs the attribute with given name (copied in), .csv column assignment (copied in) and semantics
inline attribute(const std::string &name, const std::vector<column> &column_assignment,
CSV_AttribSemantics semantics=CSV_AttribSemantics::ARBITRARY)
: name(name), columns(column_assignment), semantics(semantics)
{}
/// constructs the attribute with given name (copied in), .csv column assignment (moved in) and semantics
inline attribute(const std::string &name, std::vector<column> &&column_assignment,
CSV_AttribSemantics semantics=CSV_AttribSemantics::ARBITRARY)
: name(name), columns(std::move(column_assignment)), semantics(semantics)
{}
/// constructs the attribute with given name (moved in), .csv column assignment (copied in) and semantics
inline attribute(std::string &&name, const std::vector<column> &column_assignment,
CSV_AttribSemantics semantics=CSV_AttribSemantics::ARBITRARY)
: name(std::move(name)), columns(column_assignment), semantics(semantics)
{}
/// constructs the attribute with given name (moved in), .csv column assignment (moved in) and semantics
inline attribute(std::string &&name, std::vector<column> &&column_assignment,
CSV_AttribSemantics semantics=CSV_AttribSemantics::ARBITRARY)
: name(std::move(name)), columns(std::move(column_assignment)), semantics(semantics)
{}
/// copy assignment
inline attribute& operator= (const attribute &other)
{
name = other.name;
semantics = other.semantics;
columns = other.columns;
return *this;
}
/// move assignment
inline attribute& operator= (attribute &&other)
{
name = std::move(other.name);
semantics = other.semantics;
columns = std::move(other.columns);
return *this;
}
};
private:
/// implementation handle
Impl *pimpl;
public:
/// default constructor
csv_descriptor();
/// copy constructor
csv_descriptor(const csv_descriptor &other);
/// move constructor
csv_descriptor(csv_descriptor &&other);
/// construct under the given name with the given .csv separator and attribute specification
csv_descriptor(const std::string &name, const std::string &separators,
const std::vector<attribute> &attributes);
/// construct under the given name with the given .csv separator (move semantics) and attribute
/// specification
csv_descriptor(const std::string &name, std::string &&separators,
const std::vector<attribute> &attributes);
/// construct under the given name with the given .csv separator and attribute specification
/// (move semantics)
csv_descriptor(const std::string &name, const std::string &separators,
std::vector<attribute> &&attributes);
/// construct under the given name with the given .csv separator and attribute specification (move
/// semantics on both arguments)
csv_descriptor(const std::string &name, std::string &&separators,
std::vector<attribute> &&attributes);
/// the destructor
~csv_descriptor();
/// copy assignment
csv_descriptor& operator= (const csv_descriptor &other);
/// move assignment
csv_descriptor& operator= (csv_descriptor &&other);
/// reference the name of the described table schema
const std::string& name (void) const;
/// reference the list of column separators expected in the .csv file
const std::string& separators (void) const;
/// reference the file attribute definitions encapsulated by this descriptor
const std::vector<attribute>& attributes (void) const;
/// reference the attribute properties struct
const csv_properties& properties (void) const;
/// inferes the properties that would result from the given list of attribute definitions
static csv_properties infer_properties (const std::vector<attribute> &attributes);
};
/// provides read and write capabilites for trajectories in .csv format. Register an instance of this
/// class using either cgv::base::object_registration_1 (if you want to provide the csv table
/// description only) or cgv::base::object_registration_2 (if you also want to provide a specialized
/// default visual attribute mapping suggestion)
template <class flt_type>
class csv_handler : public traj_format_handler<flt_type>
{
public:
/// handler parent class
typedef traj_format_handler<flt_type> super;
/// real number type
typedef typename super::real real;
/// 2D vector type
typedef typename super::Vec2 Vec2;
/// 3D vector type
typedef typename super::Vec3 Vec3;
/// 4D vector type
typedef typename super::Vec4 Vec4;
/// rgb color type
typedef typename super::Color Color;
/// implementation forward
struct Impl;
private:
/// implementation handle
Impl *pimpl;
protected:
/// explicitely reset implementation-specific state
virtual void cleanup (void);
/// default constructor
csv_handler();
public:
/// Constructs the handler for the given .csv description. Note that the columns mentioned by the
/// descriptors are required for a file to be readable by this handler, but that does not exclude
/// additional columns from being read in also - they will simply be read into additional generic
/// attributes. Also, specifying an expected column number for every attribute in the descriptor
/// will enable loading even in the absence of a header row.
csv_handler(const csv_descriptor &csv_desc, const visual_attribute_mapping<real> &vmap_hints={});
/// Constructs the handler for the given .csv description (move semantics). Note that the columns
/// mentioned by the descriptors are required for a file to be readable by this handler, but that
/// does not exclude additional columns from being read in also - they will simply be read into
/// additional generic attributes. Also, specifying an expected column number for every attribute
/// in the descriptor will enable loading even in the absence of a header row.
csv_handler(csv_descriptor &&csv_desc, const visual_attribute_mapping<real> &vmap_hints={});
/// the destructor
virtual ~csv_handler();
/// reports the name "CSV - {desc}", where {desc} is the name of the csv descriptor schema
const std::string& format_name (void) const;
/// reports the file extensions the handler will claim. Currently always empty (ToDo: make customizable via \ref csv_descriptor )
const std::vector<std::string>& handled_extensions (void) const;
/// test if the given data stream appears to be a .csv file we can interpret
virtual bool can_handle (std::istream &contents) const;
/// parse the given stream containing the .csv file contents and report whether any data was loaded
virtual traj_dataset<flt_type> read (std::istream &contents, DatasetOrigin source, const std::string &path);
/// Check if a given csv description is valid. Note that this only performs superficial checks that are computationally
/// cheap - does not catch all inconsistencies possible in a \ref csv_descriptor !
static bool is_csv_descriptor_valid (const csv_descriptor &csv_desc);
};