@@ -186,11 +186,12 @@ namespace classdesc
186
186
}
187
187
return bestOverload->process (remainder , arguments);
188
188
}
189
-
189
+
190
190
template <class T >
191
- RPPtr RESTProcessSequence<T>::process( const string& remainder, const REST_PROCESS_BUFFER& arguments)
191
+ RPPtr sequenceProcess (T& obj, const string& remainder, const REST_PROCESS_BUFFER& arguments)
192
192
{
193
193
if (remainder .empty ())
194
+ {
194
195
switch (arguments.type ())
195
196
{
196
197
case RESTProcessType::null: break ;
@@ -204,43 +205,72 @@ namespace classdesc
204
205
convert (obj, arguments);
205
206
break ;
206
207
}
207
- else if (startsWith (remainder ," .@elem" ))
208
- {
209
- // extract idx
210
- auto idxStart=find (remainder .begin ()+1 , remainder .end (), ' .' );
211
- if (idxStart==remainder .end ())
212
- throw std::runtime_error (" no index" );
213
- auto idxEnd=find (idxStart+1 , remainder .end (), ' .' );
214
- size_t idx=stoi (string (idxStart+1 , idxEnd));
215
- if (idx>=obj.size ())
216
- {
217
- if (startsWith (remainder ," .@elemNoThrow" ))
218
- return mapAndProcessDummy<typename T::value_type>(string (idxEnd,remainder .end ()), arguments);
219
- else
220
- throw std::runtime_error (" idx out of bounds" );
221
- }
222
- return {};
223
- // auto i=obj.begin();
224
- // std::advance(i, idx);
225
- // auto ip=*i;
226
- // auto r=mapAndProcess(string(idxEnd,remainder.end()), arguments, ip);
227
- // // if we're processing MultiArrays, convert return to a value type as the iterator here will be invalidated out of scope
228
- // if (std::is_base_of<MultiArrayIterator, decltype(i)>::value)
229
- // if (auto v=r->toValue())
230
- // return v;
231
- // return r;
208
+ return makeRESTProcessRef (obj);
232
209
}
233
- else if (startsWith (remainder ," .@insert" ))
234
- insert (obj, arguments);
235
- else if (startsWith (remainder ," .@erase" ))
236
- erase (obj, arguments);
237
210
else if (startsWith (remainder ," .@size" ))
238
211
return makeRESTProcessValueObject (obj.size ());
239
- else
240
- return RESTProcess_t (obj).process (remainder ,arguments); // treat as an object, not container
241
- return std::make_shared<RESTProcessSequence>(obj);
212
+ return RESTProcess_t (obj).process (remainder ,arguments); // treat as an object, not container
242
213
}
243
214
215
+ template <class T > std::tuple<typename T::iterator, string::size_type>
216
+ elemImpl (T& obj, const string& remainder, const REST_PROCESS_BUFFER& arguments)
217
+ {
218
+ // extract idx
219
+ assert (remainder .length ()>2 );
220
+ auto idxStart=remainder .find (' .' ,1 );
221
+ if (idxStart==string::npos)
222
+ throw std::runtime_error (" no index" );
223
+ auto idxEnd=remainder .find (' .' , idxStart+1 );
224
+ if (idxEnd==string::npos) idxEnd=remainder .length ();
225
+ size_t idx=stoi (remainder .substr (idxStart+1 , idxEnd));
226
+ if (idx>=obj.size ())
227
+ {
228
+ // @elemNoThrow doesn't throw out of bounds error, but may throw invalid index
229
+ if (startsWith (remainder ," .@elemNoThrow" ))
230
+ return {obj.end (),string::npos};
231
+ throw std::runtime_error (" idx out of bounds" );
232
+ }
233
+ auto i=obj.begin ();
234
+ std::advance (i, idx);
235
+ return {i,idxEnd};
236
+ }
237
+
238
+ template <class T > RPPtr RESTProcessSequence<T>::process(const string& remainder, const REST_PROCESS_BUFFER& arguments)
239
+ {
240
+ if (startsWith (remainder ," .@elem" ))
241
+ {
242
+ auto [i, idxEnd]=elemImpl (obj,remainder ,arguments);
243
+ if (i==obj.end ()) return std::make_shared<RESTProcessVoid>();
244
+ return mapAndProcess (remainder .substr (idxEnd), arguments, *i);
245
+ }
246
+ if (startsWith (remainder ," .@insert" ))
247
+ {
248
+ insert (obj, arguments);
249
+ return makeRESTProcessRef (obj);
250
+ }
251
+ if (startsWith (remainder ," .@erase" ))
252
+ {
253
+ erase (obj, arguments);
254
+ return makeRESTProcessRef (obj);
255
+ }
256
+ return sequenceProcess (obj,remainder ,arguments);
257
+ }
258
+
259
+ template <class T > RPPtr RESTProcessMultiArray<T>::process(const string& remainder, const REST_PROCESS_BUFFER& arguments)
260
+ {
261
+ if (startsWith (remainder ," .@elem" ))
262
+ {
263
+ auto [i, idxEnd]=elemImpl (actual,remainder ,arguments);
264
+ if (i==actual.end ()) return std::make_shared<RESTProcessVoid>();
265
+ auto r=mapAndProcess (remainder .substr (idxEnd), arguments, *i);
266
+ if (idxEnd==remainder .length () && T::rank>1 )
267
+ // create a copy of the MultiArray iterator before it goes out of scope
268
+ return std::make_shared<RESTProcessMultiArray<typename T::iterator::value_type>>(*i);
269
+ return r;
270
+ }
271
+ return sequenceProcess (actual,remainder ,arguments);
272
+ }
273
+
244
274
template <class T >
245
275
RPPtr RESTProcessAssociativeContainer<T>::process(const string& remainder, const REST_PROCESS_BUFFER& arguments)
246
276
{
0 commit comments