5 #ifndef NDS_PROXY_BUFFERED_READER_HH
6 #define NDS_PROXY_BUFFERED_READER_HH
16 template <
typename Reader >
37 r_.write_all( start, end );
51 size_t len_requested = end - start;
55 if (
buf_.size( ) < len_requested )
56 len_requested =
buf_.size( );
57 std::copy(
buf_.data( ),
buf_.data( ) + len_requested, start );
59 return start + len_requested;
71 size_t len_requested = end - start;
73 auto result =
peek( start, end );
89 peek(
char* start,
const char* end )
91 size_t len_requested = end - start;
93 while (
buf_.size( ) < len_requested )
95 std::copy(
buf_.data( ),
buf_.data( ) + len_requested, start );
96 return start + len_requested;
110 template <
typename It >
114 std::vector< char > result;
116 decltype(
buf_.size( ) ) cur = 0;
117 auto remaining =
buf_.size( );
118 for (
bool match =
false; !match; ++cur, --remaining )
120 if ( remaining == 0 )
123 remaining =
buf_.size( ) - cur;
126 if ( std::find( begin_set, end_set,
buf_.at( cur ) ) !=
132 result.resize( cur );
134 buf_.begin( ),
buf_.begin( ) + cur, result.begin( ) );
151 template <
typename It,
typename OutIt >
158 decltype(
buf_.size( ) ) cur = 0;
159 auto remaining =
buf_.size( );
160 OutIt dest_cur = dest_start;
162 for ( ; !match && dest_cur != dest_end;
163 ++cur, --remaining, ++dest_cur )
165 if ( remaining == 0 )
168 remaining =
buf_.size( ) - cur;
171 if ( std::find( begin_set, end_set,
buf_.at( cur ) ) !=
179 std::copy(
buf_.begin( ),
buf_.begin( ) + cur, dest_start );
183 throw std::range_error(
184 "Unable to find matching sequence" );
194 std::vector< char >::size_type
207 const decltype(
buf_.size( ) ) chunk_size = 1024;
208 auto data_size =
buf_.size( );
210 buf_.resize( data_size + chunk_size );
211 auto data_start =
buf_.data( ) + data_size;
214 r_.read_available( data_start, data_start + chunk_size );
217 static_cast< size_t >( result - data_start );
218 if ( data_read_in > 0 )
220 buf_.resize( data_size + data_read_in );
224 buf_.resize( data_size );
225 throw std::runtime_error(
"io operation failed" );
230 consume( std::vector< char >::size_type count )
234 if ( count >=
buf_.size( ) )
239 auto current_size =
buf_.size( );
240 auto new_head =
buf_.data( ) + count;
243 new_head,
buf_.data( ) + current_size,
buf_.data( ) );
244 buf_.resize( current_size - count );
248 template <
typename Reader >
257 const decltype(
buf_.size( ) ) chunk_size = 1024;
258 auto data_size =
buf_.size( );
260 buf_.resize( data_size + chunk_size );
261 auto data_start =
buf_.data( ) + data_size;
264 r_.read_available( data_start, data_start + chunk_size );
267 static_cast< size_t >( result - data_start );
268 if ( data_read_in > 0 )
270 buf_.resize( data_size + data_read_in );
274 buf_.resize( data_size );
275 throw std::runtime_error(
"io operation failed" );
280 consume( std::vector< char >::size_type count )
284 if ( count >=
buf_.size( ) )
289 auto current_size =
buf_.size( );
290 auto new_head =
buf_.data( ) + count;
293 new_head,
buf_.data( ) + current_size,
buf_.data( ) );
294 buf_.resize( current_size - count );
299 :
r_{ std::move( r ) },
buf_{}
316 r_.write_all( start, end );
330 size_t len_requested = end - start;
334 if (
buf_.size( ) < len_requested )
335 len_requested =
buf_.size( );
336 std::copy(
buf_.data( ),
buf_.data( ) + len_requested, start );
338 return start + len_requested;
350 size_t len_requested = end - start;
352 while (
buf_.size( ) < len_requested )
354 std::copy(
buf_.data( ),
buf_.data( ) + len_requested, start );
356 return start + len_requested;
370 template <
typename It >
374 std::vector< char > result;
376 decltype(
buf_.size( ) ) cur = 0;
377 auto remaining =
buf_.size( );
378 for (
bool match =
false; !match; ++cur, --remaining )
380 if ( remaining == 0 )
383 remaining =
buf_.size( ) - cur;
386 if ( std::find( begin_set, end_set,
buf_.at( cur ) ) !=
392 result.resize( cur );
394 buf_.begin( ),
buf_.begin( ) + cur, result.begin( ) );
403 std::vector< char >::size_type
416 #ifdef _NDS_IMPL_ENABLE_CATCH_TESTS_
426 TEST_CASE(
"Create a buffered socket",
"[buffered,create]" )
432 TEST_CASE(
"You can write through a buffered reader",
"[buffered,write]" )
434 using namespace nds_testing;
439 auto hello = std::string(
"hello" );
440 b.write_all( hello.data( ), hello.data( ) + hello.length( ) );
441 REQUIRE( s.str( ) == hello );
443 auto world = std::string(
" world!" );
444 b.write_all( world.data( ), world.data( ) + world.length( ) );
445 REQUIRE( s.str( ) == hello + world );
448 TEST_CASE(
"You can read from a buffered writter",
"[buffered,read]" )
450 using namespace nds_testing;
452 std::vector< char > dest( 20 );
454 auto hello = std::string{
"hello world!" };
459 REQUIRE( b.__buffered_bytes( ) == 0 );
461 auto end = b.read_available( dest.data( ), dest.data( ) + dest.size( ) );
462 REQUIRE( b.__buffered_bytes( ) == 0 );
463 REQUIRE( end != dest.data( ) );
464 REQUIRE( end == dest.data( ) + hello.size( ) );
465 auto output = std::string( dest.data( ), end );
466 REQUIRE( output == hello );
469 TEST_CASE(
"You can read the data in small segments from a buffered reader",
472 using namespace nds_testing;
474 std::vector< char > dest( 5 );
476 auto hello = std::string{
"hello world!" };
481 REQUIRE( b.__buffered_bytes( ) == 0 );
483 auto end = b.read_available( dest.data( ), dest.data( ) + dest.size( ) );
484 REQUIRE( b.__buffered_bytes( ) == ( hello.size( ) - dest.size( ) ) );
485 REQUIRE( end != dest.data( ) );
486 REQUIRE( end == dest.data( ) + dest.size( ) );
487 auto output = std::string( dest.data( ), end );
488 REQUIRE( output == hello.substr( 0, dest.size( ) ) );
490 end = b.read_available( dest.data( ), dest.data( ) + dest.size( ) );
491 REQUIRE( b.__buffered_bytes( ) == ( hello.size( ) - 2 * dest.size( ) ) );
492 REQUIRE( end != dest.data( ) );
493 REQUIRE( end == dest.data( ) + dest.size( ) );
494 output = std::string( dest.data( ), end );
495 REQUIRE( output == hello.substr( dest.size( ), dest.size( ) ) );
498 TEST_CASE(
"You can ask for an exact amount of bytes to be returned",
501 using namespace nds_testing;
503 std::vector< char > dest( 10 );
505 auto input = std::string{
"0123456789" };
510 auto end = b.read_exactly( dest.data( ), dest.data( ) + stride );
511 REQUIRE( b.__buffered_bytes( ) == ( input.size( ) - stride ) );
512 REQUIRE( end == dest.data( ) + stride );
515 b.read_exactly( dest.data( ), dest.data( ) + dest.size( ) ) );
518 TEST_CASE(
"You can peek at an exact amount of data without consuming it",
521 using namespace nds_testing;
523 std::vector< char > dest( 10 );
524 auto input = std::string{
"0123456789" };
530 auto end = b.peek( dest.data( ), dest.data( ) + stride );
531 REQUIRE( b.__buffered_bytes( ) == input.size( ) );
532 REQUIRE( end == dest.data( ) + stride );
533 REQUIRE( std::equal( dest.data( ), dest.data( ) + stride, input.data( ) ) );
536 std::fill( dest.begin( ), dest.end( ), 0 );
538 !std::equal( dest.data( ), dest.data( ) + stride, input.data( ) ) );
540 end = b.read_exactly( dest.data( ), dest.data( ) + stride );
541 REQUIRE( b.__buffered_bytes( ) == input.size( ) - stride );
542 REQUIRE( end == dest.data( ) + stride );
543 REQUIRE( std::equal( dest.data( ), dest.data( ) + stride, input.data( ) ) );
546 TEST_CASE(
"You can ask a buffered read to read until a sequence is found",
547 "[buffered,read_until]" )
549 using namespace nds_testing;
551 auto input = std::string{
"0123456789" };
555 auto terminators = std::string(
"59" );
556 auto result = b.read_until( terminators.begin( ), terminators.end( ) );
557 REQUIRE( std::string( result.begin( ), result.end( ) ) ==
558 std::string(
"012345" ) );
561 TEST_CASE(
"You can ask a buffered read to read until a sequence is found, "
563 "[buffered,read_until]" )
565 using namespace nds_testing;
567 std::vector< char > dest( 5 );
568 auto input = std::string{
"0123456789abcdef" };
572 std::fill( dest.begin( ), dest.end( ), 0 );
573 auto terminators = std::string(
"29" );
574 auto end = b.read_until(
575 terminators.begin( ), terminators.end( ), dest.begin( ), dest.end( ) );
576 auto length = std::distance( dest.begin( ), end );
577 REQUIRE( length == 3 );
578 REQUIRE( std::string( dest.data( ), length ) == std::string(
"012" ) );
581 TEST_CASE(
"A bounded buffered read_until will throw an exception if it cannot "
583 "[buffered,read_until]" )
585 using namespace nds_testing;
587 std::vector< char > dest( 5 );
588 auto input = std::string{
"0123456789abcdef" };
592 auto terminators = std::string(
"Z" );
593 REQUIRE_THROWS_AS( b.read_until( terminators.begin( ),
600 TEST_CASE(
"A bounded buffered read_until will throw an exception if it cannot "
601 "find a sequence when input is empty",
602 "[buffered,read_until]" )
604 using namespace nds_testing;
606 std::vector< char > dest( 5 );
607 auto input = std::string{
"" };
611 auto terminators = std::string(
"Z" );
612 REQUIRE_THROWS_AS( b.read_until( terminators.begin( ),
616 std::runtime_error );
619 TEST_CASE(
"Create an owning buffered socket",
"[buffered,create]" )
627 TEST_CASE(
"You can write through a owning buffered reader",
630 using namespace nds_testing;
632 std::vector< char > buf;
637 auto hello = std::string(
"hello" );
638 b.write_all( hello.data( ), hello.data( ) + hello.length( ) );
639 REQUIRE( std::string( buf.data( ), buf.size( ) ) == hello );
641 auto world = std::string(
" world!" );
642 b.write_all( world.data( ), world.data( ) + world.length( ) );
643 REQUIRE( std::string( buf.data( ), buf.size( ) ) == hello + world );
646 TEST_CASE(
"You can read from a owning buffered writter",
"[buffered,read]" )
648 using namespace nds_testing;
650 std::vector< char > dest( 20 );
652 auto hello = std::string{
"hello world!" };
657 REQUIRE( b.__buffered_bytes( ) == 0 );
659 auto end = b.read_available( dest.data( ), dest.data( ) + dest.size( ) );
660 REQUIRE( b.__buffered_bytes( ) == 0 );
661 REQUIRE( end != dest.data( ) );
662 REQUIRE( end == dest.data( ) + hello.size( ) );
663 auto output = std::string( dest.data( ), end );
664 REQUIRE( output == hello );
668 "You can read the data in small segments from an owning buffered reader",
671 using namespace nds_testing;
673 std::vector< char > dest( 5 );
675 auto hello = std::string{
"hello world!" };
680 REQUIRE( b.__buffered_bytes( ) == 0 );
682 auto end = b.read_available( dest.data( ), dest.data( ) + dest.size( ) );
683 REQUIRE( b.__buffered_bytes( ) == ( hello.size( ) - dest.size( ) ) );
684 REQUIRE( end != dest.data( ) );
685 REQUIRE( end == dest.data( ) + dest.size( ) );
686 auto output = std::string( dest.data( ), end );
687 REQUIRE( output == hello.substr( 0, dest.size( ) ) );
689 end = b.read_available( dest.data( ), dest.data( ) + dest.size( ) );
690 REQUIRE( b.__buffered_bytes( ) == ( hello.size( ) - 2 * dest.size( ) ) );
691 REQUIRE( end != dest.data( ) );
692 REQUIRE( end == dest.data( ) + dest.size( ) );
693 output = std::string( dest.data( ), end );
694 REQUIRE( output == hello.substr( dest.size( ), dest.size( ) ) );
697 TEST_CASE(
"You can ask for an exact amount of bytes to be returned from an "
698 "owning buffered reader",
701 using namespace nds_testing;
703 std::vector< char > dest( 10 );
705 auto input = std::string{
"0123456789" };
710 auto end = b.read_exactly( dest.data( ), dest.data( ) + stride );
711 REQUIRE( b.__buffered_bytes( ) == ( input.size( ) - stride ) );
712 REQUIRE( end == dest.data( ) + stride );
715 b.read_exactly( dest.data( ), dest.data( ) + dest.size( ) ) );
719 "You can ask an owning buffered read to read until a sequence is found",
720 "[buffered,read_until]" )
722 using namespace nds_testing;
724 std::vector< char > dest( 10 );
726 auto input = std::string{
"0123456789" };
730 auto terminators = std::string(
"59" );
731 auto result = b.read_until( terminators.begin( ), terminators.end( ) );
732 REQUIRE( std::string( result.begin( ), result.end( ) ) ==
733 std::string(
"012345" ) );
736 #endif // _NDS_IMPL_ENABLE_CATCH_TESTS_
738 #endif // NDS_PROXY_BUFFERED_READER_HH
BufferedReader(Reader &r)
Definition: buffered_reader.hh:20
Definition: socket.hh:108
void write_all(const char *start, const char *end)
Definition: buffered_reader.hh:314
void fill_buffer()
Definition: buffered_reader.hh:255
void consume(std::vector< char >::size_type count)
Definition: buffered_reader.hh:280
void write_all(const char *start, const char *end)
Definition: buffered_reader.hh:35
std::vector< char >::size_type __buffered_bytes() const
Definition: buffered_reader.hh:404
Reader r_
Definition: buffered_reader.hh:251
OwningBufferedReader(Reader &&r)
Definition: buffered_reader.hh:298
TEST_CASE("daq_strlcpy copies strings safely when buffers are sufficiently large")
Definition: test_bsd_string.cc:9
OutIt read_until(It begin_set, It end_set, OutIt dest_start, OutIt dest_end)
Definition: buffered_reader.hh:153
Reader & r_
Definition: buffered_reader.hh:201
Definition: dummy_socket.hh:45
std::vector< char > read_until(It begin_set, It end_set)
Definition: buffered_reader.hh:112
void consume(std::vector< char >::size_type count)
Definition: buffered_reader.hh:230
std::vector< char > buf_
Definition: buffered_reader.hh:252
char * peek(char *start, const char *end)
Definition: buffered_reader.hh:89
std::vector< char > read_until(It begin_set, It end_set)
Definition: buffered_reader.hh:372
void fill_buffer()
Definition: buffered_reader.hh:205
char * read_exactly(char *start, const char *end)
Definition: buffered_reader.hh:69
std::vector< char >::size_type __buffered_bytes() const
Definition: buffered_reader.hh:195
char * read_available(char *start, char *end)
Definition: buffered_reader.hh:49
char * read_exactly(char *start, const char *end)
Definition: buffered_reader.hh:348
Definition: buffered_reader.hh:249
std::vector< char > buf_
Definition: buffered_reader.hh:202
char * read_available(char *start, char *end)
Definition: buffered_reader.hh:328
Definition: buffered_reader.hh:17
Definition: dummy_socket.hh:14