Skip to content

Commit 6f528db

Browse files
committed
[FEATURE] change cigar.assign_string parameter to string view
1 parent 3f75891 commit 6f528db

File tree

7 files changed

+108
-7
lines changed

7 files changed

+108
-7
lines changed

include/seqan3/alphabet/cigar/cigar.hpp

+15-5
Original file line numberDiff line numberDiff line change
@@ -159,16 +159,26 @@ class cigar : public alphabet_tuple_base<cigar, uint32_t, exposition_only::cigar
159159
/*!\name Write functions
160160
* \{
161161
*/
162-
/*!\brief Assign from the string representation.
162+
/*!\brief Assign from a contigous char array.
163163
* \details
164-
* \experimentalapi{Experimental since version 3.1.}
164+
*
165+
* In order to avoid unnecessary copies, you can initialise a seqan3::cigar from two char pointers that point to a
166+
* contigous char array that stores the cigar string.
167+
*
168+
* \include test/snippet/alphabet/cigar/cigar_assign_string.cpp
169+
*
170+
* \attention If the cigar count cannot be correctly read, `0P` is added instead to the cigar string.
171+
* Adding 0 padding is not impacting the alignment that the cigar string represents but
172+
* keeps the number of cigar elements consistent with the input.
173+
*
174+
* \experimentalapi{Experimental since version 3.2.}
165175
*/
166-
cigar & assign_string(small_string<11> const s) noexcept
176+
cigar & assign_string(std::string_view input) noexcept
167177
{
168178
uint32_t num{};
169-
auto [ptr, errc] = std::from_chars(s.data(), s.data() + 10, num);
179+
auto [ptr, errc] = std::from_chars(input.data(), input.data() + input.size(), num);
170180

171-
if ((errc != std::errc{}) || (!char_is_valid_for<operation>(*ptr)) || (*(ptr + 1) != 0))
181+
if ((errc != std::errc{}) || (!char_is_valid_for<operation>(*ptr)))
172182
{
173183
get<0>(*this) = 0;
174184
assign_char_to('P', get<1>(*this));

include/seqan3/io/sam_file/detail/cigar.hpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -279,7 +279,7 @@ template <seqan3::detail::pairwise_alignment alignment_type>
279279
std::ranges::for_each(cigar_vector,
280280
[&result](auto & cig)
281281
{
282-
result.append(cig.to_string());
282+
result.append(static_cast<std::string_view>(cig.to_string()));
283283
});
284284
return result;
285285
}

include/seqan3/utility/container/small_string.hpp

+20
Original file line numberDiff line numberDiff line change
@@ -362,6 +362,26 @@ class small_string : public small_vector<char, capacity_ + 1>
362362
{
363363
return str();
364364
}
365+
366+
/*!\brief Implicit conversion to std::string_view.
367+
*
368+
* It is the programmer's responsibility to ensure that the resulting string view does not outlive the string.
369+
*
370+
* ### Exceptions
371+
*
372+
* Strong exception guarantee. No data is modified.
373+
*
374+
* ### Complexity
375+
*
376+
* Constant.
377+
*
378+
* \experimentalapi{Experimental since version 3.1.}
379+
* \sa https://en.cppreference.com/w/cpp/string/basic_string/operator_basic_string_view
380+
*/
381+
constexpr operator std::string_view() const noexcept
382+
{
383+
return std::string_view{data_.data(), this->size()};
384+
}
365385
//!\}
366386

367387
/*!\name Input/output
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
#include <seqan3/alphabet/cigar/cigar.hpp>
2+
#include <seqan3/core/debug_stream.hpp>
3+
4+
int main()
5+
{
6+
std::string cigar_str{"4S134M"}; // input
7+
8+
seqan3::cigar letter1{};
9+
seqan3::cigar letter2{};
10+
11+
// Assign from string
12+
// convenient but creates an unnecessary string copy "4S"
13+
letter1.assign_string(cigar_str.substr(0, 2));
14+
letter2.assign_string(cigar_str.substr(2, 4));
15+
seqan3::debug_stream << letter1 << '\n'; // prints 4S
16+
seqan3::debug_stream << letter2 << '\n'; // prints 134M
17+
18+
// Assign from std::string_view (No extra string copies)
19+
// Version 1
20+
letter1.assign_string(std::string_view{cigar_str}.substr(0, 2));
21+
letter2.assign_string(std::string_view{cigar_str}.substr(2, 4));
22+
seqan3::debug_stream << letter1 << '\n'; // prints 4S
23+
seqan3::debug_stream << letter2 << '\n'; // prints 134M
24+
// No extra string copiesersion 2
25+
letter1.assign_string(/*std::string_view*/ {cigar_str.data(), 2});
26+
letter2.assign_string(/*std::string_view*/ {cigar_str.data() + 2, 4});
27+
seqan3::debug_stream << letter1 << '\n'; // prints 4S
28+
seqan3::debug_stream << letter2 << '\n'; // prints 134M
29+
30+
// Assign from char array
31+
letter2.assign_string("40S");
32+
seqan3::debug_stream << letter2 << '\n'; // prints 40S
33+
34+
// Assign from seqan3::small_string
35+
letter2.assign_string(letter1.to_string());
36+
seqan3::debug_stream << letter2 << '\n'; // prints 4S
37+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
4S
2+
134M
3+
4S
4+
134M
5+
4S
6+
134M
7+
40S
8+
4S

test/unit/alphabet/cigar/cigar_test.cpp

+19
Original file line numberDiff line numberDiff line change
@@ -51,10 +51,29 @@ TEST(cigar, to_string)
5151

5252
TEST(cigar, assign_string)
5353
{
54+
// assign from char array
5455
seqan3::cigar c1{};
5556
c1.assign_string("223M");
5657
EXPECT_EQ(uint32_t{223}, seqan3::to_rank(get<0>(c1)));
5758
EXPECT_EQ('M', get<1>(c1).to_char());
59+
60+
// assign from string
61+
std::string s{"4S"};
62+
c1.assign_string(s);
63+
EXPECT_EQ(uint32_t{4}, seqan3::to_rank(get<0>(c1)));
64+
EXPECT_EQ('S', get<1>(c1).to_char());
65+
66+
// assign from std::string_view
67+
std::string v{s};
68+
c1.assign_string(v);
69+
EXPECT_EQ(uint32_t{4}, seqan3::to_rank(get<0>(c1)));
70+
EXPECT_EQ('S', get<1>(c1).to_char());
71+
72+
// assign from small_string
73+
seqan3::small_string<11> ss{"1234D"};
74+
c1.assign_string(ss);
75+
EXPECT_EQ(uint32_t{1234}, seqan3::to_rank(get<0>(c1)));
76+
EXPECT_EQ('D', get<1>(c1).to_char());
5877
}
5978

6079
TEST(cigar, constexpr_char_literal)

test/unit/utility/container/small_string_test.cpp

+8-1
Original file line numberDiff line numberDiff line change
@@ -104,13 +104,20 @@ TEST(small_string, string)
104104
EXPECT_EQ(em.str(), "hello"s); // explicit
105105
}
106106

107-
TEST(small_string, implicit_conversion)
107+
TEST(small_string, implicit_conversion_string)
108108
{
109109
seqan3::small_string em{"hello"};
110110
std::string str = em;
111111
EXPECT_EQ(str, "hello"s); // explicit
112112
}
113113

114+
TEST(small_string, implicit_conversion_string_view)
115+
{
116+
seqan3::small_string em{"hello"};
117+
std::string_view str_view{em};
118+
EXPECT_EQ(str_view, "hello"s); // explicit
119+
}
120+
114121
constexpr bool erase_test()
115122
{
116123
seqan3::small_string em{"hello"};

0 commit comments

Comments
 (0)