@@ -301,6 +301,61 @@ namespace pcpp
301301 return newLayer;
302302 }
303303
304+ // / @brief Construct the next layer in the protocol stack using a factory functor.
305+ // /
306+ // / No validation is performed on the data, outside of what the factory functor may perform.
307+ // / If the factory returns a nullptr, no next layer is set.
308+ // /
309+ // / The factory functor is expected to have the following signature:
310+ // / Layer* factoryFn(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet, ...);
311+ // /
312+ // / This overload infers the Packet from the current layer.
313+ // /
314+ // / @tparam TFactory The factory functor type.
315+ // / @tparam ...Args Parameter pack for extra arguments to pass to the factory functor.
316+ // / @param[in] factoryFn The factory functor to create the layer.
317+ // / @param[in] data The data to construct the layer from
318+ // / @param[in] dataLen The length of the data
319+ // / @param[in] extraArgs Extra arguments to be forwarded to the factory.
320+ // / @return The return value of the factory functor.
321+ template <typename TFactory, typename ... Args>
322+ Layer* constructNextLayerFromFactory (TFactory factoryFn, uint8_t * data, size_t dataLen, Args&&... extraArgs)
323+ {
324+ return constructNextLayerFromFactory<TFactory>(factoryFn, data, dataLen, getAttachedPacket (),
325+ std::forward<Args>(extraArgs)...);
326+ }
327+
328+ // / @brief Construct the next layer in the protocol stack using a factory functor.
329+ // /
330+ // / No validation is performed on the data, outside of what the factory functor may perform.
331+ // / If the factory returns a nullptr, no next layer is set.
332+ // /
333+ // / The factory functor is expected to have the following signature:
334+ // / Layer* factoryFn(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet, ...);
335+ // /
336+ // / @tparam TFactory The factory functor type.
337+ // / @tparam ...Args Parameter pack for extra arguments to pass to the factory functor.
338+ // / @param[in] factoryFn The factory functor to create the layer.
339+ // / @param[in] data The data to construct the layer from
340+ // / @param[in] dataLen The length of the data
341+ // / @param[in] packet The packet the layer belongs to
342+ // / @param[in] extraArgs Extra arguments to be forwarded to the factory.
343+ // / @return The return value of the factory functor.
344+ template <typename TFactory, typename ... Args>
345+ Layer* constructNextLayerFromFactory (TFactory factoryFn, uint8_t * data, size_t dataLen, Packet* packet,
346+ Args&&... extraArgs)
347+ {
348+ if (hasNextLayer ())
349+ {
350+ throw std::runtime_error (" Next layer already exists" );
351+ }
352+
353+ // cppcheck-suppress redundantInitialization
354+ Layer* newLayer = factoryFn (data, dataLen, this , packet, std::forward<Args>(extraArgs)...);
355+ setNextLayer (newLayer);
356+ return newLayer;
357+ }
358+
304359 // / Try to construct the next layer in the protocol stack.
305360 // /
306361 // / This overload infers the Packet from the current layer.
@@ -356,6 +411,8 @@ namespace pcpp
356411 // / @param[in] dataLen The length of the data
357412 // / @param[in] extraArgs Extra arguments to be forwarded to the layer constructor of T
358413 // / @return The constructed layer of type T or TFallback
414+ // / @remarks The parameters extraArgs are forwarded to the factory function, but not to the TFallback
415+ // / constructor.
359416 template <typename T, typename TFallback, typename ... Args>
360417 Layer* tryConstructNextLayerWithFallback (uint8_t * data, size_t dataLen, Args&&... extraArgs)
361418 {
@@ -376,6 +433,8 @@ namespace pcpp
376433 // / @param[in] packet The packet the layer belongs to
377434 // / @param[in] extraArgs Extra arguments to be forwarded to the layer constructor of T
378435 // / @return The constructed layer of type T or TFallback
436+ // / @remarks The parameters extraArgs are forwarded to the factory function, but not to the TFallback
437+ // / constructor.
379438 template <typename T, typename TFallback, typename ... Args>
380439 Layer* tryConstructNextLayerWithFallback (uint8_t * data, size_t dataLen, Packet* packet, Args&&... extraArgs)
381440 {
@@ -387,6 +446,71 @@ namespace pcpp
387446 return constructNextLayer<TFallback>(data, dataLen, packet);
388447 }
389448
449+ // / @brief Try to construct the next layer in the protocol stack using a factory functor with a fallback option.
450+ // /
451+ // / The method will attempt to construct the next layer using the provided factory function.
452+ // / If the factory function returns nullptr, indicating failure to create the layer, the method will then
453+ // / construct a layer of type TFallback.
454+ // /
455+ // / The factory functor is expected to have the following signature:
456+ // / Layer* factoryFn(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet, ...);
457+ // /
458+ // / This overload infers the Packet from the current layer.
459+ // /
460+ // / @tparam TFallback The fallback layer type to construct if the factory fails.
461+ // / @tparam TFactory The factory functor type.
462+ // / @tparam ...Args Parameter pack for extra arguments to pass to the factory functor.
463+ // / @param[in] factoryFn The factory functor to create the layer.
464+ // / @param[in] data The data to construct the layer from
465+ // / @param[in] dataLen The length of the data
466+ // / @param[in] extraArgs Extra arguments to be forwarded to the factory.
467+ // / @return The return value of the factory functor.
468+ // / @remarks The parameters extraArgs are forwarded to the factory function, but not to the TFallback
469+ // / constructor.
470+ template <typename TFallback, typename TFactory, typename ... Args>
471+ Layer* tryConstructNextLayerFromFactoryWithFallback (TFactory factoryFn, uint8_t * data, size_t dataLen,
472+ Args&&... extraArgs)
473+ {
474+ // Note that the fallback is first to allow template argument deduction of the factory type.
475+ return tryConstructNextLayerFromFactoryWithFallback<TFallback, TFactory>(
476+ factoryFn, data, dataLen, getAttachedPacket (), std::forward<Args>(extraArgs)...);
477+ }
478+
479+ // / @brief Try to construct the next layer in the protocol stack using a factory functor with a fallback option.
480+ // /
481+ // / The method will attempt to construct the next layer using the provided factory function.
482+ // / If the factory function returns nullptr, indicating failure to create the layer, the method will then
483+ // / construct a layer of type TFallback.
484+ // /
485+ // / The factory functor is expected to have the following signature:
486+ // / Layer* factoryFn(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet, ...);
487+ // /
488+ // / @tparam TFallback The fallback layer type to construct if the factory fails.
489+ // / @tparam TFactory The factory functor type.
490+ // / @tparam ...Args Parameter pack for extra arguments to pass to the factory functor.
491+ // / @param[in] factoryFn The factory functor to create the layer.
492+ // / @param[in] data The data to construct the layer from
493+ // / @param[in] dataLen The length of the data
494+ // / @param[in] packet The packet the layer belongs to
495+ // / @param[in] extraArgs Extra arguments to be forwarded to the factory.
496+ // / @return The return value of the factory functor.
497+ // / @remarks The parameters extraArgs are forwarded to the factory function, but not to the TFallback
498+ // / constructor.
499+ template <typename TFallback, typename TFactory, typename ... Args>
500+ Layer* tryConstructNextLayerFromFactoryWithFallback (TFactory factoryFn, uint8_t * data, size_t dataLen,
501+ Packet* packet, Args&&... extraArgs)
502+ {
503+ auto nextLayer = constructNextLayerFromFactory<TFactory>(factoryFn, data, dataLen, packet,
504+ std::forward<Args>(extraArgs)...);
505+ if (nextLayer != nullptr )
506+ {
507+ return nextLayer;
508+ }
509+
510+ // factory failed, construct fallback layer
511+ return constructNextLayer<TFallback>(data, dataLen, packet);
512+ }
513+
390514 // / @brief Check if the data is large enough to reinterpret as a type
391515 // /
392516 // / The data must be non-null and at least as large as the type
0 commit comments