Util: Add to_bool() and use it for JSON, Pg & query encoding

To improve interop with legacy modules.
This commit is contained in:
Yorhel 2025-02-25 09:10:03 +01:00
parent 06e2f950fe
commit c7a3415485
10 changed files with 141 additions and 37 deletions

View file

@ -176,3 +176,35 @@ static SV *fustr_done_(pTHX_ fustr *s) {
static double fu_timediff(const struct timespec *a, const struct timespec *b) {
return ((double)(a->tv_sec - b->tv_sec)) + (double)(a->tv_nsec - b->tv_nsec) / 1000000000.0;
}
/* -1 if arg is not a bool, 0 on false, 1 on true */
static int fu_2bool(SV *val) {
if (SvIsBOOL(val)) return BOOL_INTERNALS_sv_isbool_true(val) ? 1 : 0;
if (!SvROK(val)) return -1;
SV *rv = SvRV(val);
if (SvOBJECT(rv)) {
HV *stash = SvSTASH(rv);
/* Historical: "JSON::XS::Boolean", not used by JSON::XS since 3.0 in 2013 */
if (stash == gv_stashpvs("JSON::PP::Boolean", 0) /* Also covers Types::Serialiser::Boolean and used by a bunch of other modules */
|| stash == gv_stashpvs("Mojo::JSON::_Bool", 0)
|| stash == gv_stashpvs("JSON::Tiny::_Bool", 0))
return !!SvIV(rv);
return -1;
}
/* \0 or \1 */
if (SvTYPE(rv) < SVt_PVAV) {
if (SvIOK(rv)) {
IV iv = SvIV(rv);
return iv == 0 ? 0 : iv == 1 ? 1 : -1;
} else if (SvOK(rv)) {
STRLEN len;
char *str = SvPV_nomg(rv, len);
return len != 1 ? -1 : *str == '0' ? 0 : *str == '1' ? 1 : -1;
}
}
return -1;
}