@@ -125,25 +125,39 @@ template<typename Allocator>
125125void default_array_of_strings_serde<Allocator>::deserialize(
126126 std::istream& is, array_of_strings* items, unsigned num
127127) const {
128- for (unsigned i = 0 ; i < num; ++i) {
129- read<uint32_t >(is); // total_bytes
130- if (!is) throw std::runtime_error (" array_of_strings stream read failed" );
131- const uint8_t num_nodes = read<uint8_t >(is);
132- if (!is) throw std::runtime_error (" array_of_strings stream read failed" );
133- check_num_nodes (num_nodes);
134- array_of_strings array (num_nodes, " " );
135- for (uint8_t j = 0 ; j < num_nodes; ++j) {
136- const uint32_t length = read<uint32_t >(is);
137- if (!is) throw std::runtime_error (" array_of_strings stream read failed" );
138- std::string value (length, ' \0 ' );
139- if (length != 0 ) {
140- is.read (&value[0 ], length);
141- if (!is) throw std::runtime_error (" array_of_strings stream read failed" );
128+ unsigned i = 0 ;
129+ bool failure = false ;
130+ try {
131+ for (; i < num; ++i) {
132+ read<uint32_t >(is); // total_bytes
133+ if (!is) { failure = true ; break ; }
134+ const uint8_t num_nodes = read<uint8_t >(is);
135+ if (!is) { failure = true ; break ; }
136+ check_num_nodes (num_nodes);
137+ array_of_strings array (num_nodes, " " );
138+ for (uint8_t j = 0 ; j < num_nodes; ++j) {
139+ const uint32_t length = read<uint32_t >(is);
140+ if (!is) { failure = true ; break ; }
141+ std::string value (length, ' \0 ' );
142+ if (length != 0 ) {
143+ is.read (&value[0 ], length);
144+ if (!is) { failure = true ; break ; }
145+ }
146+ array[j] = std::move (value);
142147 }
143- array[j] = std::move (value);
148+ if (failure) break ;
149+ summary_allocator alloc (summary_allocator_);
150+ std::allocator_traits<summary_allocator>::construct (alloc, &items[i], std::move (array));
144151 }
152+ } catch (std::istream::failure&) {
153+ failure = true ;
154+ }
155+ if (failure) {
145156 summary_allocator alloc (summary_allocator_);
146- std::allocator_traits<summary_allocator>::construct (alloc, &items[i], std::move (array));
157+ for (unsigned j = 0 ; j < i; ++j) {
158+ std::allocator_traits<summary_allocator>::destroy (alloc, &items[j]);
159+ }
160+ throw std::runtime_error (" array_of_strings stream read failed at item " + std::to_string (i));
147161 }
148162}
149163
@@ -177,28 +191,37 @@ size_t default_array_of_strings_serde<Allocator>::deserialize(
177191) const {
178192 const uint8_t * ptr8 = static_cast <const uint8_t *>(ptr);
179193 size_t bytes_read = 0 ;
180-
181- for (unsigned i = 0 ; i < num; ++i) {
182- check_memory_size (bytes_read + sizeof (uint32_t ), capacity);
183- const size_t item_start = bytes_read;
184- uint32_t total_bytes;
185- bytes_read += copy_from_mem (ptr8 + bytes_read, total_bytes);
186- check_memory_size (item_start + total_bytes, capacity);
187- uint8_t num_nodes;
188- bytes_read += copy_from_mem (ptr8 + bytes_read, num_nodes);
189- check_num_nodes (num_nodes);
190- array_of_strings array (num_nodes, " " );
191- for (uint8_t j = 0 ; j < num_nodes; ++j) {
192- uint32_t length;
193- bytes_read += copy_from_mem (ptr8 + bytes_read, length);
194- std::string value (length, ' \0 ' );
195- if (length != 0 ) {
196- bytes_read += copy_from_mem (ptr8 + bytes_read, &value[0 ], length);
194+ unsigned i = 0 ;
195+
196+ try {
197+ for (; i < num; ++i) {
198+ check_memory_size (bytes_read + sizeof (uint32_t ), capacity);
199+ const size_t item_start = bytes_read;
200+ uint32_t total_bytes;
201+ bytes_read += copy_from_mem (ptr8 + bytes_read, total_bytes);
202+ check_memory_size (item_start + total_bytes, capacity);
203+ uint8_t num_nodes;
204+ bytes_read += copy_from_mem (ptr8 + bytes_read, num_nodes);
205+ check_num_nodes (num_nodes);
206+ array_of_strings array (num_nodes, " " );
207+ for (uint8_t j = 0 ; j < num_nodes; ++j) {
208+ uint32_t length;
209+ bytes_read += copy_from_mem (ptr8 + bytes_read, length);
210+ std::string value (length, ' \0 ' );
211+ if (length != 0 ) {
212+ bytes_read += copy_from_mem (ptr8 + bytes_read, &value[0 ], length);
213+ }
214+ array[j] = std::move (value);
197215 }
198- array[j] = std::move (value);
216+ summary_allocator alloc (summary_allocator_);
217+ std::allocator_traits<summary_allocator>::construct (alloc, &items[i], std::move (array));
199218 }
219+ } catch (...) {
200220 summary_allocator alloc (summary_allocator_);
201- std::allocator_traits<summary_allocator>::construct (alloc, &items[i], std::move (array));
221+ for (unsigned j = 0 ; j < i; ++j) {
222+ std::allocator_traits<summary_allocator>::destroy (alloc, &items[j]);
223+ }
224+ throw ;
202225 }
203226 return bytes_read;
204227}
0 commit comments