Skip to content

Commit 0ba9d36

Browse files
WanZhiQiu-acwangzhiqiangstephenberry
authored
add support of dynamically sized Eigen types (#1541)
* add support of dynamically sized Eigen types * ensure buffer bounds safety and add unit test for dynamic Eigen matrix. * more tests and safer iterator handling * fix duplication * More tests * cleaning * Added missing resize in BEVE reading * formatting * improve/fix unit tests * fix invalid return --------- Co-authored-by: wangzhiqiang <wangzhiqiang@fscut.com> Co-authored-by: Stephen Berry <stephenberry.developer@gmail.com>
1 parent 9a11620 commit 0ba9d36

File tree

2 files changed

+303
-7
lines changed

2 files changed

+303
-7
lines changed

include/glaze/ext/eigen.hpp

+63-2
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,10 @@ namespace glz
3232
static void op(auto& value, is_context auto&& ctx, auto&& it, auto&& end)
3333
{
3434
++it;
35+
if (it >= end) [[unlikely]] {
36+
ctx.error = error_code::unexpected_end;
37+
return;
38+
}
3539
constexpr uint8_t layout = uint8_t(!T::IsRowMajor);
3640
if (uint8_t(*it) != layout) {
3741
ctx.error = error_code::syntax_error;
@@ -45,22 +49,29 @@ namespace glz
4549
}
4650
};
4751

52+
// A dynamic matrix in both rows and columns
4853
template <matrix_t T>
49-
requires(T::RowsAtCompileTime < 0 || T::ColsAtCompileTime < 0)
54+
requires(T::RowsAtCompileTime < 0 && T::ColsAtCompileTime < 0)
5055
struct from<BEVE, T>
5156
{
5257
template <auto Opts>
5358
static void op(auto& value, is_context auto&& ctx, auto&& it, auto&& end)
5459
{
5560
++it;
61+
if (it >= end) [[unlikely]] {
62+
ctx.error = error_code::unexpected_end;
63+
return;
64+
}
5665
constexpr uint8_t layout = uint8_t(!T::IsRowMajor);
5766
if (uint8_t(*it) != layout) {
5867
ctx.error = error_code::syntax_error;
68+
return;
5969
}
6070
++it;
6171
std::array<Eigen::Index, 2> extents;
6272
detail::read<BEVE>::op<Opts>(extents, ctx, it, end);
6373

74+
value.resize(extents[0], extents[1]);
6475
std::span<typename T::Scalar> view(value.data(), extents[0] * extents[1]);
6576
detail::read<BEVE>::op<Opts>(view, ctx, it, end);
6677
}
@@ -88,8 +99,9 @@ namespace glz
8899
}
89100
};
90101

102+
// A dynamic matrix in both rows and columns
91103
template <matrix_t T>
92-
requires(T::RowsAtCompileTime < 0 || T::ColsAtCompileTime < 0)
104+
requires(T::RowsAtCompileTime < 0 && T::ColsAtCompileTime < 0)
93105
struct to<BEVE, T>
94106
{
95107
template <auto Opts>
@@ -134,6 +146,55 @@ namespace glz
134146
detail::to<JSON, Value>::template op<Opts>(view, ctx, b, ix);
135147
}
136148
};
149+
150+
// A dynamic matrix in both rows and columns
151+
template <matrix_t T>
152+
requires(T::RowsAtCompileTime < 0 && T::ColsAtCompileTime < 0)
153+
struct to<JSON, T>
154+
{
155+
template <auto Opts>
156+
static void op(auto&& value, is_context auto&& ctx, auto&& b, auto&& ix)
157+
{
158+
dump<'['>(b, ix);
159+
using RowColT = std::array<Eigen::Index, 2>;
160+
RowColT extents{value.rows(), value.cols()};
161+
detail::to<JSON, RowColT>::template op<Opts>(extents, ctx, b, ix);
162+
dump<','>(b, ix);
163+
164+
std::span<typename T::Scalar> view(value.data(), value.size());
165+
using Value = std::remove_cvref_t<decltype(view)>;
166+
detail::to<JSON, Value>::template op<Opts>(view, ctx, b, ix);
167+
dump<']'>(b, ix);
168+
}
169+
};
170+
171+
// A dynamic matrix in both rows and columns
172+
template <matrix_t T>
173+
requires(T::RowsAtCompileTime < 0 && T::ColsAtCompileTime < 0)
174+
struct from<JSON, T>
175+
{
176+
template <auto Opts>
177+
static void op(auto& value, is_context auto&& ctx, auto&& it, auto&& end)
178+
{
179+
GLZ_MATCH_OPEN_BRACKET;
180+
std::array<Eigen::Index, 2> extents; //NOLINT
181+
detail::read<JSON>::op<Opts>(extents, ctx, it, end);
182+
value.resize(extents[0], extents[1]);
183+
if (*it == ',') {
184+
// we have data
185+
++it;
186+
if constexpr (not Opts.null_terminated) {
187+
if (it == end) [[unlikely]] {
188+
ctx.error = error_code::unexpected_end;
189+
return;
190+
}
191+
}
192+
std::span<typename T::Scalar> view(value.data(), extents[0] * extents[1]);
193+
detail::read<JSON>::op<Opts>(view, ctx, it, end);
194+
}
195+
GLZ_MATCH_CLOSE_BRACKET;
196+
}
197+
};
137198
} // namespace detail
138199
} // namespace glaze
139200

0 commit comments

Comments
 (0)