Repository navigation
Fix #207: FR: Add CopyBytesFrom for array types #282
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -258,6 +258,29 @@ class GenericArrayView final { | |
| WriteArrayToTextStream(this, stream, options); | ||
| } | ||
|
|
||
| template <class Container, int N = 0> | ||
| typename ::std::enable_if< | ||
| ((void)N, kAddressableUnitSize * kElementSize == 8), void>::type | ||
| CopyBytesFrom(const Container &source) const { | ||
| EMBOSS_CHECK(IsComplete()); | ||
| EMBOSS_CHECK(static_cast<::std::size_t>(source.size()) == ElementCount()); | ||
| auto it = source.begin(); | ||
| for (::std::size_t i = 0; i < ElementCount(); ++i, ++it) { | ||
| (*this)[i].Write(static_cast<typename ElementView::ValueType>(*it)); | ||
| } | ||
| } | ||
|
Comment on lines
+261
to
+271
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The current implementation of template <class Container, int N = 0>\n typename ::std::enable_if<\n ((void)N, kAddressableUnitSize * kElementSize == 8), void>::type\n CopyBytesFrom(const Container &source) const {\n EMBOSS_CHECK(Ok());\n EMBOSS_CHECK(source.size() == ElementCount());\n auto it = source.begin();\n for (::std::size_t i = 0; i < ElementCount(); ++i, ++it) {\n (*this)[i].Write(static_cast<typename ElementView::ValueType>(*it));\n }\n }\n\n template <typename T, ::std::size_t N, int M = 0>\n typename ::std::enable_if<\n ((void)M, kAddressableUnitSize * kElementSize == 8), void>::type\n CopyBytesFrom(const T (&source)[N]) const {\n EMBOSS_CHECK(Ok());\n EMBOSS_CHECK(N == ElementCount());\n for (::std::size_t i = 0; i < ElementCount(); ++i) {\n (*this)[i].Write(static_cast<typename ElementView::ValueType>(source[i]));\n }\n }
Comment on lines
+261
to
+271
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Using In Emboss, write operations (like template <class Container, int N = 0>
typename ::std::enable_if<
((void)N, kAddressableUnitSize * kElementSize == 8), void>::type
CopyBytesFrom(const Container &source) const {
EMBOSS_CHECK(IsComplete());
EMBOSS_CHECK(source.size() == ElementCount());
auto it = source.begin();
for (::std::size_t i = 0; i < ElementCount(); ++i, ++it) {
(*this)[i].Write(static_cast<typename ElementView::ValueType>(*it));
}
} |
||
|
|
||
| template <typename T, ::std::size_t N, int M = 0> | ||
| typename ::std::enable_if< | ||
| ((void)M, kAddressableUnitSize * kElementSize == 8), void>::type | ||
| CopyBytesFrom(const T (&source)[N]) const { | ||
| EMBOSS_CHECK(IsComplete()); | ||
| EMBOSS_CHECK(N == ElementCount()); | ||
| for (::std::size_t i = 0; i < ElementCount(); ++i) { | ||
| (*this)[i].Write(static_cast<typename ElementView::ValueType>(source[i])); | ||
| } | ||
| } | ||
|
Comment on lines
+273
to
+282
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Similarly to the container overload, using template <typename T, ::std::size_t N, int M = 0>
typename ::std::enable_if<
((void)M, kAddressableUnitSize * kElementSize == 8), void>::type
CopyBytesFrom(const T (&source)[N]) const {
EMBOSS_CHECK(IsComplete());
EMBOSS_CHECK(N == ElementCount());
for (::std::size_t i = 0; i < ElementCount(); ++i) {
(*this)[i].Write(static_cast<typename ElementView::ValueType>(source[i]));
}
} |
||
|
|
||
| static constexpr bool IsAggregate() { return true; } | ||
|
|
||
| BufferType BackingStorage() const { return buffer_; } | ||
|
|
||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -16,6 +16,7 @@ | |||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| #include <string> | ||||||||||||||||||||||||||||||||||||||||||||||||
| #include <type_traits> | ||||||||||||||||||||||||||||||||||||||||||||||||
| #include <array> | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| #include "absl/strings/str_format.h" | ||||||||||||||||||||||||||||||||||||||||||||||||
| #include "gtest/gtest.h" | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -89,6 +90,43 @@ TEST(ArrayView, Methods) { | |||||||||||||||||||||||||||||||||||||||||||||||
| EXPECT_FALSE((ArrayView<FixedUIntView<32>, ReadWriteContiguousBuffer, 1>{ | ||||||||||||||||||||||||||||||||||||||||||||||||
| ReadWriteContiguousBuffer{ | ||||||||||||||||||||||||||||||||||||||||||||||||
| nullptr}}.Ok())); | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| // Test CopyBytesFrom | ||||||||||||||||||||||||||||||||||||||||||||||||
| ::std::array<::std::uint8_t, 4> new_bytes = {0xaa, 0xbb, 0xcc, 0xdd}; | ||||||||||||||||||||||||||||||||||||||||||||||||
| auto dest_array = ArrayView<FixedUIntView<8>, ReadWriteContiguousBuffer, 1>{ | ||||||||||||||||||||||||||||||||||||||||||||||||
| ReadWriteContiguousBuffer{bytes, 4}}; | ||||||||||||||||||||||||||||||||||||||||||||||||
| dest_array.CopyBytesFrom(new_bytes); | ||||||||||||||||||||||||||||||||||||||||||||||||
| EXPECT_EQ(0xaa, bytes[0]); | ||||||||||||||||||||||||||||||||||||||||||||||||
| EXPECT_EQ(0xbb, bytes[1]); | ||||||||||||||||||||||||||||||||||||||||||||||||
| EXPECT_EQ(0xcc, bytes[2]); | ||||||||||||||||||||||||||||||||||||||||||||||||
| EXPECT_EQ(0xdd, bytes[3]); | ||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+94
to
+102
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It is highly recommended to add a test case verifying that
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| // Test CopyBytesFrom with signed elements to ensure values >= 128 do not abort | ||||||||||||||||||||||||||||||||||||||||||||||||
| bytes[0] = 0; | ||||||||||||||||||||||||||||||||||||||||||||||||
| bytes[1] = 0; | ||||||||||||||||||||||||||||||||||||||||||||||||
| bytes[2] = 0; | ||||||||||||||||||||||||||||||||||||||||||||||||
| bytes[3] = 0; | ||||||||||||||||||||||||||||||||||||||||||||||||
| auto dest_signed_array = | ||||||||||||||||||||||||||||||||||||||||||||||||
| ArrayView<FixedIntView<8>, ReadWriteContiguousBuffer, 1>{ | ||||||||||||||||||||||||||||||||||||||||||||||||
| ReadWriteContiguousBuffer{bytes, 4}}; | ||||||||||||||||||||||||||||||||||||||||||||||||
| dest_signed_array.CopyBytesFrom(new_bytes); | ||||||||||||||||||||||||||||||||||||||||||||||||
| EXPECT_EQ(0xaa, bytes[0]); | ||||||||||||||||||||||||||||||||||||||||||||||||
| EXPECT_EQ(0xbb, bytes[1]); | ||||||||||||||||||||||||||||||||||||||||||||||||
| EXPECT_EQ(0xcc, bytes[2]); | ||||||||||||||||||||||||||||||||||||||||||||||||
| EXPECT_EQ(0xdd, bytes[3]); | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| // Test CopyBytesFrom with a raw C-style array | ||||||||||||||||||||||||||||||||||||||||||||||||
| const ::std::uint8_t raw_bytes[4] = {0x11, 0x22, 0x33, 0x44}; | ||||||||||||||||||||||||||||||||||||||||||||||||
| dest_array.CopyBytesFrom(raw_bytes); | ||||||||||||||||||||||||||||||||||||||||||||||||
| EXPECT_EQ(0x11, bytes[0]); | ||||||||||||||||||||||||||||||||||||||||||||||||
| EXPECT_EQ(0x22, bytes[1]); | ||||||||||||||||||||||||||||||||||||||||||||||||
| EXPECT_EQ(0x33, bytes[2]); | ||||||||||||||||||||||||||||||||||||||||||||||||
| EXPECT_EQ(0x44, bytes[3]); | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| #if EMBOSS_CHECK_ABORTS | ||||||||||||||||||||||||||||||||||||||||||||||||
| ::std::array<::std::uint8_t, 3> wrong_size_bytes = {0xaa, 0xbb, 0xcc}; | ||||||||||||||||||||||||||||||||||||||||||||||||
| EXPECT_DEATH(dest_array.CopyBytesFrom(wrong_size_bytes), ""); | ||||||||||||||||||||||||||||||||||||||||||||||||
| #endif // EMBOSS_CHECK_ABORTS | ||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+99
to
130
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. To ensure that EXPECT_EQ(0xaa, bytes[0]);
EXPECT_EQ(0xbb, bytes[1]);
EXPECT_EQ(0xcc, bytes[2]);
EXPECT_EQ(0xdd, bytes[3]);
// Test CopyBytesFrom with signed elements to ensure values >= 128 do not abort
bytes[0] = 0; bytes[1] = 0; bytes[2] = 0; bytes[3] = 0;
auto dest_signed_array = ArrayView<FixedIntView<8>, ReadWriteContiguousBuffer, 1>{
ReadWriteContiguousBuffer{bytes, 4}};
dest_signed_array.CopyBytesFrom(new_bytes);
EXPECT_EQ(0xaa, bytes[0]);
EXPECT_EQ(0xbb, bytes[1]);
EXPECT_EQ(0xcc, bytes[2]);
EXPECT_EQ(0xdd, bytes[3]);
} |
||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| TEST(ArrayView, Ok) { | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Using
operator[]on thesourcecontainer restrictsCopyBytesFromto containers that support random access (likestd::vectororstd::array). Using iterators instead is more idiomatic in C++ templates and allows the method to support any container withbegin()andend()(such asstd::listorstd::forward_list).\n\nAdditionally, to support braced initializer lists directly (e.g.,CopyBytesFrom({0xaa, 0xbb})), you could consider adding an overload takingstd::initializer_list<T>in the future.