Skip to content

Commit

Permalink
[FEATURE] change cigar.assign_string parameter to string view
Browse files Browse the repository at this point in the history
  • Loading branch information
smehringer authored and eseiler committed May 31, 2022
1 parent 3f75891 commit 474d587
Show file tree
Hide file tree
Showing 7 changed files with 108 additions and 7 deletions.
20 changes: 15 additions & 5 deletions include/seqan3/alphabet/cigar/cigar.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -159,16 +159,26 @@ class cigar : public alphabet_tuple_base<cigar, uint32_t, exposition_only::cigar
/*!\name Write functions
* \{
*/
/*!\brief Assign from the string representation.
/*!\brief Assign from a contigous char array.
* \details
* \experimentalapi{Experimental since version 3.1.}
*
* In order to avoid unnecessary copies, you can initialise a seqan3::cigar from two char pointers that point to a
* contigous char array that stores the cigar string.
*
* \include test/snippet/alphabet/cigar/cigar_assign_string.cpp
*
* \attention If the cigar count cannot be correctly read, `0P` is added instead to the cigar string.
* Adding 0 padding is not impacting the alignment that the cigar string represents but
* keeps the number of cigar elements consistent with the input.
*
* \experimentalapi{Experimental since version 3.2.}
*/
cigar & assign_string(small_string<11> const s) noexcept
cigar & assign_string(std::string_view input) noexcept
{
uint32_t num{};
auto [ptr, errc] = std::from_chars(s.data(), s.data() + 10, num);
auto [ptr, errc] = std::from_chars(input.data(), input.data() + input.size(), num);

if ((errc != std::errc{}) || (!char_is_valid_for<operation>(*ptr)) || (*(ptr + 1) != 0))
if ((errc != std::errc{}) || (!char_is_valid_for<operation>(*ptr)))
{
get<0>(*this) = 0;
assign_char_to('P', get<1>(*this));
Expand Down
2 changes: 1 addition & 1 deletion include/seqan3/io/sam_file/detail/cigar.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -279,7 +279,7 @@ template <seqan3::detail::pairwise_alignment alignment_type>
std::ranges::for_each(cigar_vector,
[&result](auto & cig)
{
result.append(cig.to_string());
result.append(static_cast<std::string_view>(cig.to_string()));
});
return result;
}
Expand Down
20 changes: 20 additions & 0 deletions include/seqan3/utility/container/small_string.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -362,6 +362,26 @@ class small_string : public small_vector<char, capacity_ + 1>
{
return str();
}

/*!\brief Implicit conversion to std::string_view.
*
* It is the programmer's responsibility to ensure that the resulting string view does not outlive the string.
*
* ### Exceptions
*
* Strong exception guarantee. No data is modified.
*
* ### Complexity
*
* Constant.
*
* \experimentalapi{Experimental since version 3.1.}
* \sa https://en.cppreference.com/w/cpp/string/basic_string/operator_basic_string_view
*/
constexpr operator std::string_view() const noexcept
{
return std::string_view{data_.data(), this->size()};
}
//!\}

/*!\name Input/output
Expand Down
37 changes: 37 additions & 0 deletions test/snippet/alphabet/cigar/cigar_assign_string.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
#include <seqan3/alphabet/cigar/cigar.hpp>
#include <seqan3/core/debug_stream.hpp>

int main()
{
std::string cigar_str{"4S134M"}; // input

seqan3::cigar letter1{};
seqan3::cigar letter2{};

// Assign from string
// convenient but creates an unnecessary string copy "4S"
letter1.assign_string(cigar_str.substr(0, 2));
letter2.assign_string(cigar_str.substr(2, 4));
seqan3::debug_stream << letter1 << '\n'; // prints 4S
seqan3::debug_stream << letter2 << '\n'; // prints 134M

// Assign from std::string_view (No extra string copies)
// Version 1
letter1.assign_string(std::string_view{cigar_str}.substr(0, 2));
letter2.assign_string(std::string_view{cigar_str}.substr(2, 4));
seqan3::debug_stream << letter1 << '\n'; // prints 4S
seqan3::debug_stream << letter2 << '\n'; // prints 134M
// No extra string copiesersion 2
letter1.assign_string(/*std::string_view*/ {cigar_str.data(), 2});
letter2.assign_string(/*std::string_view*/ {cigar_str.data() + 2, 4});
seqan3::debug_stream << letter1 << '\n'; // prints 4S
seqan3::debug_stream << letter2 << '\n'; // prints 134M

// Assign from char array
letter2.assign_string("40S");
seqan3::debug_stream << letter2 << '\n'; // prints 40S

// Assign from seqan3::small_string
letter2.assign_string(letter1.to_string());
seqan3::debug_stream << letter2 << '\n'; // prints 4S
}
8 changes: 8 additions & 0 deletions test/snippet/alphabet/cigar/cigar_assign_string.err
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
4S
134M
4S
134M
4S
134M
40S
4S
19 changes: 19 additions & 0 deletions test/unit/alphabet/cigar/cigar_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,10 +51,29 @@ TEST(cigar, to_string)

TEST(cigar, assign_string)
{
// assign from char array
seqan3::cigar c1{};
c1.assign_string("223M");
EXPECT_EQ(uint32_t{223}, seqan3::to_rank(get<0>(c1)));
EXPECT_EQ('M', get<1>(c1).to_char());

// assign from string
std::string s{"4S"};
c1.assign_string(s);
EXPECT_EQ(uint32_t{4}, seqan3::to_rank(get<0>(c1)));
EXPECT_EQ('S', get<1>(c1).to_char());

// assign from std::string_view
std::string v{s};
c1.assign_string(v);
EXPECT_EQ(uint32_t{4}, seqan3::to_rank(get<0>(c1)));
EXPECT_EQ('S', get<1>(c1).to_char());

// assign from small_string
seqan3::small_string<11> ss{"1234D"};
c1.assign_string(ss);
EXPECT_EQ(uint32_t{1234}, seqan3::to_rank(get<0>(c1)));
EXPECT_EQ('D', get<1>(c1).to_char());
}

TEST(cigar, constexpr_char_literal)
Expand Down
9 changes: 8 additions & 1 deletion test/unit/utility/container/small_string_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -104,13 +104,20 @@ TEST(small_string, string)
EXPECT_EQ(em.str(), "hello"s); // explicit
}

TEST(small_string, implicit_conversion)
TEST(small_string, implicit_conversion_string)
{
seqan3::small_string em{"hello"};
std::string str = em;
EXPECT_EQ(str, "hello"s); // explicit
}

TEST(small_string, implicit_conversion_string_view)
{
seqan3::small_string em{"hello"};
std::string_view str_view{em};
EXPECT_EQ(str_view, "hello"s); // explicit
}

constexpr bool erase_test()
{
seqan3::small_string em{"hello"};
Expand Down

0 comments on commit 474d587

Please sign in to comment.