Chandra
view release on metacpan or search on metacpan
SPAGAIN;
if (count > 0 && !SvTRUE(ERRSV)) {
html_sv = newSVsv(POPs);
} else {
/* render not available, stringify */
if (SvTRUE(ERRSV)) {
/* Clear error from failed render attempt */
sv_setsv(ERRSV, &PL_sv_undef);
}
html_sv = newSVsv(content);
}
PUTBACK;
FREETMPS; LEAVE;
} else {
html_sv = newSVsv(content);
}
(void)hv_stores(hv, "_html", html_sv);
RETVAL = SvREFCNT_inc(self);
}
OUTPUT:
RETVAL
# ---- _escape_js (also callable from Perl for tests) ----
SV *
_escape_js(str_sv)
SV *str_sv
CODE:
{
const char *src;
STRLEN src_len;
char *buf;
STRLEN i, j;
src = SvPV(str_sv, src_len);
/* Worst case: every char needs escaping (2x) */
Newx(buf, src_len * 2 + 1, char);
j = 0;
for (i = 0; i < src_len; i++) {
switch (src[i]) {
case '\\': buf[j++] = '\\'; buf[j++] = '\\'; break;
case '\'': buf[j++] = '\\'; buf[j++] = '\''; break;
case '\n': buf[j++] = '\\'; buf[j++] = 'n'; break;
case '\r': buf[j++] = '\\'; buf[j++] = 'r'; break;
default: buf[j++] = src[i]; break;
}
}
RETVAL = newSVpvn(buf, j);
Safefree(buf);
}
OUTPUT:
RETVAL
# ---- _match_route($path) - returns ($handler, %params) or () ----
void
_match_route(self, path_sv)
SV *self
SV *path_sv
PPCODE:
{
HV *hv = (HV *)SvRV(self);
SV **routes_svp = hv_fetchs(hv, "_routes", 0);
const char *path;
STRLEN path_len;
AV *path_parts;
I32 path_count;
path = SvPV(path_sv, path_len);
if (!routes_svp || !SvROK(*routes_svp)) {
/* No routes - set empty opts and return nothing */
(void)hv_stores(hv, "_current_route_opts", newRV_noinc((SV *)newHV()));
XSRETURN(0);
}
/* Split path by '/' */
path_parts = newAV();
sv_2mortal((SV *)path_parts);
{
const char *p = path;
const char *seg_start = p;
while (1) {
if (*p == '/' || *p == '\0') {
av_push(path_parts, newSVpvn(seg_start, p - seg_start));
if (*p == '\0') break;
p++;
seg_start = p;
} else {
p++;
}
}
}
path_count = av_len(path_parts) + 1;
{
AV *routes = (AV *)SvRV(*routes_svp);
I32 route_len = av_len(routes) + 1;
I32 ri;
for (ri = 0; ri < route_len; ri++) {
SV **entry_svp = av_fetch(routes, ri, 0);
AV *entry;
SV **pat_svp, **handler_svp, **opts_svp;
const char *pattern;
STRLEN pat_len;
AV *pat_parts;
I32 pat_count;
I32 pi;
int match;
HV *params;
if (!entry_svp || !SvROK(*entry_svp)) continue;
entry = (AV *)SvRV(*entry_svp);
pat_svp = av_fetch(entry, 0, 0);
handler_svp = av_fetch(entry, 1, 0);
opts_svp = av_fetch(entry, 2, 0);
if (!pat_svp || !handler_svp) continue;
(void)hv_store(hv, cache_key, (I32)strlen(cache_key),
SvREFCNT_inc(RETVAL), 0);
}
}
OUTPUT:
RETVAL
# ---- open_window(%args) - create a child window ----
SV *
open_window(self, ...)
SV *self
CODE:
{
dSP;
int count;
I32 i;
load_module(PERL_LOADMOD_NOIMPORT,
newSVpvs("Chandra::Window"), NULL);
ENTER; SAVETMPS;
PUSHMARK(SP);
XPUSHs(sv_2mortal(newSVpvs("Chandra::Window")));
/* Forward all key-value pairs */
for (i = 1; i < items; i++) {
XPUSHs(ST(i));
}
/* Add parent => $self */
XPUSHs(sv_2mortal(newSVpvs("parent")));
XPUSHs(self);
PUTBACK;
count = call_method("new", G_SCALAR);
SPAGAIN;
RETVAL = (count > 0) ? newSVsv(POPs) : &PL_sv_undef;
PUTBACK;
FREETMPS; LEAVE;
/* Track child windows in _windows array */
if (SvOK(RETVAL)) {
HV *hv = (HV *)SvRV(self);
SV **arr_svp = hv_fetchs(hv, "_windows", 0);
AV *arr;
if (arr_svp && SvROK(*arr_svp)) {
arr = (AV *)SvRV(*arr_svp);
} else {
arr = newAV();
(void)hv_stores(hv, "_windows", newRV_noinc((SV *)arr));
}
av_push(arr, SvREFCNT_inc(RETVAL));
}
}
OUTPUT:
RETVAL
# ---- windows() - return all child windows ----
void
windows(self)
SV *self
PPCODE:
{
HV *hv = (HV *)SvRV(self);
SV **arr_svp = hv_fetchs(hv, "_windows", 0);
if (arr_svp && SvROK(*arr_svp)) {
AV *arr = (AV *)SvRV(*arr_svp);
I32 len = av_len(arr) + 1;
I32 i;
for (i = 0; i < len; i++) {
SV **elem = av_fetch(arr, i, 0);
if (elem && SvOK(*elem)) {
XPUSHs(sv_2mortal(newSVsv(*elem)));
}
}
}
}
# ---- window_by_id($id) - find child window by ID ----
SV *
window_by_id(self, id_sv)
SV *self
SV *id_sv
CODE:
{
HV *hv = (HV *)SvRV(self);
SV **arr_svp = hv_fetchs(hv, "_windows", 0);
const char *target_id = SvPV_nolen(id_sv);
RETVAL = &PL_sv_undef;
if (arr_svp && SvROK(*arr_svp)) {
AV *arr = (AV *)SvRV(*arr_svp);
I32 len = av_len(arr) + 1;
I32 i;
for (i = 0; i < len; i++) {
SV **elem = av_fetch(arr, i, 0);
if (elem && SvOK(*elem) && SvROK(*elem)) {
HV *win_hv = (HV *)SvRV(*elem);
SV **id_svp = hv_fetchs(win_hv, "id", 0);
if (id_svp && SvOK(*id_svp)) {
const char *win_id = SvPV_nolen(*id_svp);
if (strcmp(win_id, target_id) == 0) {
RETVAL = newSVsv(*elem);
break;
}
}
}
}
}
}
OUTPUT:
RETVAL
# ---- window_count() - return number of child windows ----
int
window_count(self)
SV *self
CODE:
}
PUTBACK;
count = call_method("new", G_SCALAR);
SPAGAIN;
splash_obj = (count > 0) ? SvREFCNT_inc(POPs) : &PL_sv_undef;
PUTBACK;
FREETMPS; LEAVE;
}
if (!SvOK(splash_obj) || !sv_isobject(splash_obj)) {
RETVAL = &PL_sv_undef;
goto splash_done;
}
/* show() */
{
ENTER; SAVETMPS;
PUSHMARK(SP);
XPUSHs(splash_obj);
PUTBACK;
call_method("show", G_DISCARD);
FREETMPS; LEAVE;
}
/* Call init callback if provided */
if (init_cb && SvROK(init_cb) && SvTYPE(SvRV(init_cb)) == SVt_PVCV) {
ENTER; SAVETMPS;
PUSHMARK(SP);
XPUSHs(splash_obj);
PUTBACK;
call_sv(init_cb, G_DISCARD | G_EVAL);
SPAGAIN;
if (SvTRUE(ERRSV)) {
warn("Chandra::App->splash init callback died: %s",
SvPV_nolen(ERRSV));
}
FREETMPS; LEAVE;
}
/* close() */
{
ENTER; SAVETMPS;
PUSHMARK(SP);
XPUSHs(splash_obj);
PUTBACK;
call_method("close", G_DISCARD);
FREETMPS; LEAVE;
}
RETVAL = splash_obj;
splash_done: ;
}
OUTPUT:
RETVAL
void
extend_bridge(self, name, source, ...)
SV *self
const char *name
const char *source
PPCODE:
{
char **deps = NULL;
int dep_count = 0;
int i;
PERL_UNUSED_VAR(self);
/* parse optional depends => [...] */
if (items > 3 && (items - 3) % 2 == 0) {
for (i = 3; i < items; i += 2) {
const char *key = SvPV_nolen(ST(i));
if (strcmp(key, "depends") == 0) {
SV *val = ST(i + 1);
if (SvROK(val) && SvTYPE(SvRV(val)) == SVt_PVAV) {
AV *av = (AV *)SvRV(val);
SSize_t alen = av_len(av) + 1;
int j;
dep_count = (int)alen;
if (dep_count > 0) {
Newx(deps, dep_count, char *);
for (j = 0; j < dep_count; j++) {
SV **svp = av_fetch(av, j, 0);
deps[j] = savepv(svp ? SvPV_nolen(*svp) : "");
}
}
}
}
}
}
chandra_ext_register(aTHX_ name, source, deps, dep_count);
if (deps) {
for (i = 0; i < dep_count; i++)
Safefree(deps[i]);
Safefree(deps);
}
XSRETURN(1);
}
( run in 0.837 second using v1.01-cache-2.11-cpan-71847e10f99 )