5 #ifndef NDS_LITE_UTILS_HH
6 #define NDS_LITE_UTILS_HH
17 template <
typename T >
22 operator( )(
const T& input ) -> T
34 static std::vector< std::string >
35 split(
const std::string& source,
36 const std::string& sep,
39 std::vector< std::string > results;
43 std::string::size_type prev = 0;
44 std::string::size_type pos = 0;
45 if ( sep.size( ) > 0 )
47 std::string::size_type sep_size = sep.size( );
48 while ( pos < source.size( ) && pos != std::string::npos )
50 pos = source.find( sep, prev );
51 if ( pos != std::string::npos )
53 auto tmp = source.substr( prev, pos - prev );
55 results.push_back( tmp );
63 while ( pos < source.size( ) && pos != std::string::npos )
65 pos = source.find_first_of(
" \t\n\r", prev );
66 if ( pos != std::string::npos )
68 auto tmp = source.substr( prev, pos - prev );
70 results.push_back( tmp );
76 auto tmp = source.substr( prev );
78 results.push_back( tmp );
82 template <
typename T >
87 operator( )(
const T& input )
93 template <
typename T >
108 operator( )(
const T& input )
134 template <
typename T >
184 at(
size_t index )
const
186 if ( index >=
size_ )
187 throw std::out_of_range(
188 "accessing outside of the array range" );
189 return data_[ index ];
193 return data_[ index ];
214 std::fill(
begin( ),
end( ), value );
222 template <
typename It,
typename BinaryPred >
233 for ( ; cur !=
end; ++cur, prev = cur )
235 if ( p( *prev, *cur ) )
249 #ifdef _NDS_IMPL_ENABLE_CATCH_TESTS_
255 namespace nds_impl_cmn_utils
264 TEST_CASE(
"An identity transform transforms an object to itself",
265 "[nds2][utils][transforms]" )
269 auto input = std::string(
"hello" );
270 auto output = t_str( input );
271 REQUIRE( input == output );
275 TEST_CASE(
"Test split",
"[utils][split]" )
279 REQUIRE( result.size( ) == 0 );
284 REQUIRE( result.size( ) == 0 );
288 REQUIRE( result.size( ) == 0 );
293 REQUIRE( result.size( ) == 0 );
297 REQUIRE( result.size( ) == 2 );
298 REQUIRE( result[ 0 ] ==
"a" );
299 REQUIRE( result[ 1 ] ==
"c" );
304 REQUIRE( result.size( ) == 2 );
305 REQUIRE( result[ 0 ] ==
"a" );
306 REQUIRE( result[ 1 ] ==
"c" );
310 REQUIRE( result.size( ) == 1 );
311 REQUIRE( result[ 0 ] ==
"abc" );
316 REQUIRE( result.size( ) == 1 );
317 REQUIRE( result[ 0 ] ==
"abc" );
321 REQUIRE( result.size( ) == 6 );
322 std::vector< std::string > expected{
"",
"a",
"ca",
"",
"d",
"" };
323 REQUIRE( result == expected );
327 REQUIRE( result.size( ) == 3 );
328 REQUIRE( result[ 0 ] ==
"c" );
329 REQUIRE( result[ 1 ] ==
"b" );
330 REQUIRE( result[ 2 ] ==
"dog" );
337 REQUIRE( result.size( ) == 3 );
338 REQUIRE( result[ 0 ] ==
"c" );
339 REQUIRE( result[ 1 ] ==
"b" );
340 REQUIRE( result[ 2 ] ==
"dog" );
344 REQUIRE( result.size( ) == 1 );
345 REQUIRE( result[ 0 ] ==
"abc" );
350 REQUIRE( result.size( ) == 1 );
351 REQUIRE( result[ 0 ] ==
"abc" );
355 REQUIRE( result.size( ) == 6 );
356 std::vector< std::string > expected{
"a",
"b",
"",
"",
"c",
"d" };
357 REQUIRE( result == expected );
364 REQUIRE( result.size( ) == 4 );
365 std::vector< std::string > expected{
"a",
"b",
"c",
"d" };
366 REQUIRE( result == expected );
373 REQUIRE( result.size( ) == 4 );
374 std::vector< std::string > expected{
"a",
"b",
"c",
"d" };
375 REQUIRE( result == expected );
379 TEST_CASE(
"TruePredicate",
"[utils][predicates]" )
382 REQUIRE( p( 10000000 ) );
386 REQUIRE( p( -1000000 ) );
389 TEST_CASE(
"FirstNPredicate",
"[utils][predicates]" )
393 for (
auto i = 0; i < 5; ++i )
395 REQUIRE( p.accepted( ) == i );
398 REQUIRE( p.accepted( ) == 5 );
400 REQUIRE( p.accepted( ) == 5 );
402 REQUIRE( p.accepted( ) == 5 );
412 for (
auto i = 0; i < 5; ++i )
424 TEST_CASE(
"Array_view",
"[utils][array_view]" )
426 using namespace nds_impl_cmn_utils;
428 const int ARRAY_SIZE = 20;
429 simple_struct base[ ARRAY_SIZE ];
430 for (
auto i = 0; i < ARRAY_SIZE; ++i )
432 base[ i ].field1 =
static_cast< int >( i );
434 base[ i ].field2,
"a string",
sizeof( base[ i ].field2 ) );
438 REQUIRE( array.empty( ) == false );
439 REQUIRE( array.size( ) == ARRAY_SIZE );
440 REQUIRE( array.max_size( ) == array.size( ) );
441 REQUIRE( array.data( ) == base );
442 REQUIRE( array.begin( ) == base );
443 REQUIRE( array.end( ) == base + ARRAY_SIZE );
444 REQUIRE( &array.at( 0 ) == base );
445 REQUIRE( &array[ 0 ] == base );
446 REQUIRE_THROWS_AS( array.at( ARRAY_SIZE + 1 ), std::out_of_range );
447 REQUIRE_THROWS_AS( array.at( -1 ), std::out_of_range );
448 REQUIRE( &array.front( ) == base );
449 REQUIRE( &array.back( ) == base + ( ARRAY_SIZE - 1 ) );
450 for (
auto i = 0; i < ARRAY_SIZE; ++i )
452 REQUIRE( array.at( i ).field1 ==
static_cast< int >( i ) );
453 REQUIRE( std::strncmp( array.at( i ).field2,
455 sizeof( base[ i ].field2 ) ) == 0 );
457 REQUIRE( array[ i ].field1 == static_cast< int >( i ) );
458 REQUIRE( std::strncmp( array[ i ].field2,
460 sizeof( base[ i ].field2 ) ) == 0 );
465 std::is_same< sstruct_array::value_type, simple_struct >::value,
"" );
466 static_assert( std::is_same< sstruct_array::size_type, std::size_t >::value,
469 std::is_same< sstruct_array::pointer, simple_struct* >::value,
"" );
471 std::is_same< sstruct_array::difference_type, std::ptrdiff_t >::value,
474 std::is_same< sstruct_array::reference, simple_struct& >::value,
"" );
476 std::is_same< sstruct_array::iterator, simple_struct* >::value,
"" );
480 TEST_CASE(
"Empty Span",
"[utils][array_view]" )
482 using namespace nds_impl_cmn_utils;
484 const int ARRAY_SIZE = 5;
485 simple_struct base[ 5 ];
488 REQUIRE( array1.empty( ) );
489 REQUIRE( array1.size( ) == 0 );
490 REQUIRE( array1.data( ) == nullptr );
491 REQUIRE( array1.begin( ) == array1.end( ) );
492 REQUIRE( array1.begin( ) == nullptr );
495 REQUIRE( array2.empty( ) );
496 REQUIRE( array2.size( ) == 0 );
497 REQUIRE( array2.data( ) == nullptr );
498 REQUIRE( array2.begin( ) == array2.end( ) );
499 REQUIRE( array2.begin( ) == nullptr );
502 REQUIRE( array3.empty( ) );
503 REQUIRE( array3.size( ) == 0 );
504 REQUIRE( array3.data( ) == base );
505 REQUIRE( array3.begin( ) == array3.end( ) );
506 REQUIRE( array3.begin( ) == base );
509 TEST_CASE(
"Copy and assign ArrayViews",
"[utils][array_view]" )
511 using namespace nds_impl_cmn_utils;
513 const int ARRAY_SIZE = 5;
514 simple_struct base[ 5 ];
519 REQUIRE( array1.size( ) == array3.size( ) );
520 REQUIRE( array1.data( ) == array3.data( ) );
523 REQUIRE( array3.size( ) == array2.size( ) );
524 REQUIRE( array3.data( ) == array2.data( ) );
526 array3.swap( array1 );
527 REQUIRE( array3.data( ) == base );
528 REQUIRE( array3.size( ) == ARRAY_SIZE );
529 REQUIRE( array1.data( ) == base + 1 );
530 REQUIRE( array1.size( ) == ARRAY_SIZE - 2 );
533 TEST_CASE(
"array_view fill",
"[utils][array_view]" )
535 using namespace nds_impl_cmn_utils;
537 const int ARRAY_SIZE = 5;
538 simple_struct base[ 5 ];
543 std::strncpy( ref.field2,
"answer",
sizeof( ref.field2 ) );
545 for (
auto entry : array )
547 REQUIRE( entry.field1 == 42 );
548 REQUIRE( std::strncmp(
549 entry.field2,
"answer",
sizeof( entry.field2 ) ) == 0 );
552 std::strncpy( ref.field2,
"nonanswer",
sizeof( ref.field2 ) );
554 for (
auto entry : array )
556 REQUIRE( entry.field1 == 32 );
557 REQUIRE( std::strncmp(
558 entry.field2,
"nonanswer",
sizeof( entry.field2 ) ) == 0 );
562 TEST_CASE(
"adjacent_find finds two entries next to each other that are equal",
563 "[utils][algorithms]" )
565 using namespace nds_impl_cmn_utils;
567 auto eq = [](
int a,
int b ) ->
bool {
return a == b; };
570 std::vector< int > s;
571 REQUIRE(
adjacent_find( s.begin( ), s.end( ), eq ) == s.end( ) );
575 std::vector< int > s;
577 REQUIRE(
adjacent_find( s.begin( ), s.end( ), eq ) == s.end( ) );
581 std::vector< int > s;
584 REQUIRE(
adjacent_find( s.begin( ), s.end( ), eq ) == s.end( ) );
588 std::vector< int > s;
591 REQUIRE(
adjacent_find( s.begin( ), s.end( ), eq ) == s.begin( ) );
595 std::vector< int > s{ 1, 0, 5, 5, 6 };
597 REQUIRE( it != s.end( ) );
602 REQUIRE( it != s.end( ) );
607 std::vector< int > s{ 1, 0, 5, 6, 5, 5 };
609 REQUIRE( it != s.end( ) );
614 REQUIRE( it == s.end( ) );
618 #endif // _NDS_IMPL_ENABLE_CATCH_TESTS_
620 #endif // NDS_LITE_UTILS_HH
size_type max_
Definition: utils.hh:125
split_type
Definition: utils.hh:28
std::unique_ptr< T > pointer
Definition: nds_testing.hh:13
pointer begin() const
Definition: utils.hh:174
std::size_t size_type
Definition: utils.hh:97
It adjacent_find(It begin, It end, BinaryPred p)
Definition: utils.hh:224
TEST_CASE("daq_strlcpy copies strings safely when buffers are sufficiently large")
Definition: test_bsd_string.cc:9
reference operator[](size_t index)
Definition: utils.hh:191
T value_type
Definition: utils.hh:138
pointer end() const
Definition: utils.hh:179
Span(T *data, size_type count)
Definition: utils.hh:149
Span(const Span< T > &other)
Definition: utils.hh:145
size_type * ext_cur_
Definition: utils.hh:127
FirstNPredicate(size_type max)
Definition: utils.hh:99
T & reference
Definition: utils.hh:142
static std::vector< std::string > split(const std::string &source, const std::string &sep, split_type filter_mode=INCLUDE_EMPTY_STRING)
Definition: utils.hh:35
T * pointer
Definition: utils.hh:140
void fill(T &value)
Definition: utils.hh:212
std::size_t size_type
Definition: utils.hh:139
reference at(size_t index) const
Definition: utils.hh:184
bool empty() const
Definition: utils.hh:164
T * iterator
Definition: utils.hh:143
FirstNPredicate(size_type max, size_type *ext_tracker)
Definition: utils.hh:103
value_type * data_
Definition: utils.hh:218
reference front() const
Definition: utils.hh:196
size_type max_size() const
Definition: utils.hh:159
size_type local_cur_
Definition: utils.hh:126
void swap(Span< T > &other)
Definition: utils.hh:206
reference back() const
Definition: utils.hh:201
size_type size_
Definition: utils.hh:219
pointer data() const
Definition: utils.hh:169
size_type accepted() const
Definition: utils.hh:119
size_type size() const
Definition: utils.hh:154
std::ptrdiff_t difference_type
Definition: utils.hh:141