use re::engine::Plugin (
comp => sub {},
exec => sub {},
+ free => sub {},
);
To write a custom engine which imports your functions into the
re::engine::Plugin->import(
comp => \&comp,
exec => \&exec,
+ free => \&free,
);
}
# Implementation of the engine
sub comp { ... }
sub exec { ... }
+ sub free { ... }
1;
=head2 exec
- exec => sub {
- my ($rx, $str) = @_;
+ my $ponies;
+ use re::engine::Plugin(
+ exec => sub {
+ my ($rx, $str) = @_;
- # We always like ponies!
- return 1 if $str ~~ /pony/;
+ # We always like ponies!
+ if ($str ~~ /pony/) {
+ $ponies++;
+ return 1;
+ }
- # Failed to match
- return;
- }
+ # Failed to match
+ return;
+ }
+ );
Called when a regex is being executed, i.e. when it's being matched
against something. The scalar being matched against the pattern is
This callback can also be specified on an individual basis with the
L</callbacks> method.
+=head2 free
+
+ use re::engine::Plugin(
+ free => sub {
+ my ($rx) = @_;
+
+ say 'matched ' ($ponies // 'no')
+ . ' pon' . ($ponies > 1 ? 'ies' : 'y');
+
+ return;
+ }
+ );
+
+Called when the regexp structure is freed by the perl interpreter.
+Note that this happens pretty late in the destruction process, but
+still before global destruction kicks in. The only argument this
+callback receives is the C<re::engine::Plugin> object associated
+with the regexp, and its return value is ignored.
+
+This callback can also be specified on an individual basis with the
+L</callbacks> method.
+
=head1 METHODS
=head2 str
callback currently attached to the regular expression for the type given as
the key by the code reference passed as the corresponding value.
-The only valid key is currently C<exec>. See L</exec> for more details about
-this callback.
+The only valid keys are currently C<exec> and C<free>. See L</exec> and
+L</free> for more details about these callbacks.
=head2 num_captures
typedef struct {
SV *comp;
SV *exec;
+ SV *free;
} xsh_hints_user_t;
static SV *rep_validate_callback(SV *code) {
static void xsh_hints_user_init(pTHX_ xsh_hints_user_t *hv, xsh_hints_user_t *v) {
hv->comp = rep_validate_callback(v->comp);
hv->exec = rep_validate_callback(v->exec);
+ hv->free = rep_validate_callback(v->free);
return;
}
static void xsh_hints_user_clone(pTHX_ xsh_hints_user_t *nv, xsh_hints_user_t *ov, CLONE_PARAMS *params) {
nv->comp = xsh_dup_inc(ov->comp, params);
nv->exec = xsh_dup_inc(ov->exec, params);
+ nv->free = xsh_dup_inc(ov->free, params);
return;
}
static void xsh_hints_user_deinit(pTHX_ xsh_hints_user_t *hv) {
SvREFCNT_dec(hv->comp);
SvREFCNT_dec(hv->exec);
+ SvREFCNT_dec(hv->free);
return;
}
SvREFCNT_inc_simple_void_NN(h->exec);
}
+ /* Same goes for the free callback, if there's one. */
+ if (h->free) {
+ re->cb_free = h->free;
+ SvREFCNT_inc_simple_void_NN(h->free);
+ }
+
re->cb_num_capture_buff_FETCH = NULL;
re->cb_num_capture_buff_STORE = NULL;
re->cb_num_capture_buff_LENGTH = NULL;
{
struct regexp *rx;
re__engine__Plugin self;
+ SV *callback;
+ dSP;
if (PL_dirty)
return;
rx = rxREGEXP(RX);
SELF_FROM_PPRIVATE(self, rx->pprivate);
- SvREFCNT_dec(self->pattern);
- SvREFCNT_dec(self->str);
- SvREFCNT_dec(self->stash);
-
- SvREFCNT_dec(self->cb_exec);
-
- SvREFCNT_dec(self->cb_num_capture_buff_FETCH);
- SvREFCNT_dec(self->cb_num_capture_buff_STORE);
- SvREFCNT_dec(self->cb_num_capture_buff_LENGTH);
-
- self->rx = NULL;
-
- Safefree(self);
-
- SvREFCNT_dec(rx->pprivate);
-
-/*
- dSP;
- SV *callback;
-
callback = self->cb_free;
if (callback) {
FREETMPS;
LEAVE;
}
+
+ SvREFCNT_dec(self->pattern);
+ SvREFCNT_dec(self->str);
+ SvREFCNT_dec(self->stash);
+
+ SvREFCNT_dec(self->cb_exec);
+
+ SvREFCNT_dec(self->cb_num_capture_buff_FETCH);
+ SvREFCNT_dec(self->cb_num_capture_buff_STORE);
+ SvREFCNT_dec(self->cb_num_capture_buff_LENGTH);
+
+ self->rx = NULL;
+
+ Safefree(self);
+
+ SvREFCNT_dec(rx->pprivate);
+
return;
-*/
}
void *
}
XSRETURN(0);
+void
+_free(re::engine::Plugin self, ...)
+PPCODE:
+ if (items > 1) {
+ SvREFCNT_dec(self->cb_free);
+ self->cb_free = ST(1);
+ SvREFCNT_inc_simple_void(self->cb_free);
+ }
+ XSRETURN(0);
+
void
_num_capture_buff_FETCH(re::engine::Plugin self, ...)
PPCODE:
XSRETURN(0);
SV *
-_tag(SV *comp, SV *exec)
+_tag(SV *comp, SV *exec, SV *free)
PREINIT:
xsh_hints_user_t arg;
CODE:
arg.comp = comp;
arg.exec = exec;
+ arg.free = free;
RETVAL = xsh_hints_tag(&arg);
OUTPUT:
RETVAL