Colouring-In-XS
view release on metacpan or search on metacpan
include/in.h view on Meta::CPAN
/*
* in.h - Perl-XS bridge helpers for Colouring::In::XS
*
* Provides the glue between Perl SVs/HVs/AVs and the pure-C
* colouring_rgba_t from colouring.h. Header-only; requires
* PERL_NO_GET_CONTEXT, perl.h and XSUB.h already included.
*
* Re-usable by Eshu (CSS preprocessor) or any other XS module
* that works with Colouring::In colour objects.
*/
#ifndef COLOURING_IN_H
#define COLOURING_IN_H
#include "colouring.h"
/* ââ Class name constant ââââââââââââââââââââââââââââââââââââââââ */
#define COLOURING_CLASS "Colouring::In::XS"
#define COLOURING_CLASS_LEN 17
/* ââ Message store (set from Perl side) âââââââââââââââââââââââââ */
/* Holds a refcount-managed reference to the user's message hash so
* the underlying HV stays alive after set_messages() returns. */
static SV * MESSAGES_REF = NULL;
#define MESSAGES \
((MESSAGES_REF && SvROK(MESSAGES_REF)) ? (HV*)SvRV(MESSAGES_REF) : NULL)
/* ââ Bless a hash into the caller's class âââââââââââââââââââââââ */
static SV * xs_new(SV * class, HV * hash) {
dTHX;
if (SvROK(class)) {
char * name = HvNAME(SvSTASH(SvRV(class)));
class = newSVpv(name, strlen(name));
}
return sv_bless(newRV_noinc((SV*)hash), gv_stashsv(class, 0));
}
/* ââ Quick "does this SV look numeric?" check âââââââââââââââââââ */
static int numIs(SV * num) {
dTHX;
if (!num || !SvOK(num)) return 0;
/* looks_like_number is Perl's portable, bounds-safe numeric test
* (handles ints, floats, scientific notation, Unicode digits). The
* previous hand-rolled scanner had an unbounded write into a
* fixed-size stack buffer â a stack-smash on long all-digit input. */
return looks_like_number(num) ? 1 : 0;
}
/* ââ Scale a value that may be a percentage âââââââââââââââââââââ */
static double xs_scaled(SV * num, int size) {
dTHX;
STRLEN len;
char * number = SvPV(num, len);
double n = atof(number);
/* Percent suffix: check the last *character*, not the trailing
* NUL (`number[strlen(number)]` always reads '\0'). */
if (len > 0 && number[len - 1] == '%') {
return (n * size) / 100;
}
return n;
}
/* ââ Extract RGBA from a blessed Colouring::In::XS object âââââââ */
static colouring_rgba_t xs_extract_rgba(SV * self) {
dTHX;
colouring_rgba_t c;
AV * colour = (AV*)SvRV(*hv_fetch((HV*)SvRV(self), "colour", 6, 0));
int len = av_len(colour);
SV *r, *g, *b;
r = len >= 0 ? *av_fetch(colour, 0, 0) : NULL;
g = len >= 1 ? *av_fetch(colour, 1, 0) : NULL;
b = len >= 2 ? *av_fetch(colour, 2, 0) : NULL;
c.r = (r && SvOK(r)) ? SvNV(r) : 255;
c.g = (g && SvOK(g)) ? SvNV(g) : 255;
c.b = (b && SvOK(b)) ? SvNV(b) : 255;
( run in 1.289 second using v1.01-cache-2.11-cpan-39bf76dae61 )