1818
1919namespace csp ::adapters::csv {
2020
21- // Parses exactly "YYYY-MM-DD HH::MM::SS"
22- DateTime parseFixed_YmdHMS (std::string_view date) {
23- if (date.size () < 19 )
24- CSP_THROW (ValueError, " Timestamp too short" );
21+ // Build parser at runtime for extracting date time
22+ std::function<DateTime(std::string_view)>
23+ createParser (std::string_view format) {
2524
26- auto d2 = [&](size_t i) {
27- return (date[i] - ' 0' ) * 10 + (date[i + 1 ] - ' 0' );
28- };
25+ constexpr std::array<std::string_view, 6 > date_format = {" YYYY" , " MM" , " DD" ,
26+ " hh" , " mm" , " ss" };
27+
28+ std::array<int , 6 > date_indices;
2929
30- int year = d2 (0 ) * 100 + d2 (2 );
31- int month = d2 (5 );
32- int day = d2 (8 );
30+ for (int i = 0 ; i < 6 ; ++i) {
31+ auto pos = format.find (date_format[i]);
3332
34- int hour = d2 ( 11 );
35- int minute = d2 ( 14 );
36- int second = d2 ( 17 );
33+ date_indices[i] =
34+ pos == std::string_view::npos ? - 1 : static_cast < int >(pos );
35+ }
3736
38- return DateTime (year, month, day, hour, minute, second);
37+ return [date_indices](std::string_view date) -> DateTime {
38+ std::array<int , 6 > data = {
39+ 0 , // year
40+ 0 , // month
41+ 1 , // day
42+ 0 , // hour
43+ 0 , // minute
44+ 0 // second
45+ };
46+
47+ auto d2 = [&](int idx) {
48+ return (date[idx] - ' 0' ) * 10 + (date[idx + 1 ] - ' 0' );
49+ };
50+
51+ auto d4 = [&](int idx) {
52+ return (date[idx] - ' 0' ) * 1000 + (date[idx + 1 ] - ' 0' ) * 100 +
53+ (date[idx + 2 ] - ' 0' ) * 10 + (date[idx + 3 ] - ' 0' );
54+ };
55+
56+ for (int i = 0 ; i < 6 ; ++i) {
57+ if (date_indices[i] == -1 )
58+ continue ;
59+
60+ if (i == 0 )
61+ data[i] = d4 (date_indices[i]);
62+ else
63+ data[i] = d2 (date_indices[i]);
64+ }
65+
66+ return DateTime (data[0 ], data[1 ], data[2 ], data[3 ], data[4 ], data[5 ]);
67+ };
3968}
4069
4170CsvInputAdapterManager::CsvInputAdapterManager (csp::Engine *engine,
@@ -61,12 +90,10 @@ CsvInputAdapterManager::CsvInputAdapterManager(csp::Engine *engine,
6190 properties.tryGet (" time_format" , m_timeFormat);
6291
6392 if (m_timeFormat.empty ()) {
64- dateParser = parseFixed_YmdHMS;
65- } else if (m_timeFormat == " YYYY-MM-DD HH::MM::SS" ) {
66- dateParser = parseFixed_YmdHMS;
67- } else {
68- CSP_THROW (ValueError, " Time format not supported" );
93+ CSP_THROW (ValueError, " Time format must be provided" );
6994 }
95+
96+ dateParser = createParser (m_timeFormat);
7097}
7198
7299CsvInputAdapterManager::~CsvInputAdapterManager () = default ;
@@ -299,24 +326,21 @@ void CsvInputAdapterManager::bindSubscriberDispatchers() {
299326
300327 auto col = colIndex.find (csvColumn);
301328
302- CSP_TRUE_OR_THROW_RUNTIME (
303- col != colIndex. end (),
304- " Column ' " << csvColumn << " ' not found in CSV header" );
329+ CSP_TRUE_OR_THROW_RUNTIME (col != colIndex. end (),
330+ " Column ' " << csvColumn
331+ << " ' not found in CSV header" );
305332
306333 auto field = meta->field (structField);
307334
308- CSP_TRUE_OR_THROW_RUNTIME (
309- field,
310- " Field '" << structField << " ' not found in struct" );
335+ CSP_TRUE_OR_THROW_RUNTIME (field, " Field '" << structField
336+ << " ' not found in struct" );
311337
312338 size_t idx = col->second ;
313339
314340 subscription.m_fieldSetters .push_back (
315341 [idx, field](StructPtr &s,
316342 const std::vector<std::string_view> &cols) {
317- field->setValue <std::string>(
318- s.get (),
319- std::string (cols[idx]));
343+ field->setValue <std::string>(s.get (), std::string (cols[idx]));
320344 });
321345 }
322346
0 commit comments