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;
}

View file

@ -231,10 +231,9 @@ static void fujson_fmt_obj(pTHX_ fujson_fmt_ctx *ctx, SV *rv, SV *obj) {
static void fujson_fmt(pTHX_ fujson_fmt_ctx *ctx, SV *val) {
SvGETMAGIC(val);
/* XXX: &PL_sv_yes and &PL_sv_no are proper booleans under 5.40, so no need
* to explicitly check for those; does this work in 5.36 as well? */
if (SvIsBOOL(val)) { /* Must check before IOKp & POKp, because bool implies both flags */
if (BOOL_INTERNALS_sv_isbool_true(val)) fustr_write(ctx->out, "true", 4);
int r = fu_2bool(val);
if (r != -1) { /* Must check SvISBOOL() before IOKp & POKp, because it implies both flags */
if (r) fustr_write(ctx->out, "true", 4);
else fustr_write(ctx->out, "false", 5);
} else if (SvPOKp(val)) {
fujson_fmt_str(aTHX_ ctx, SvPVX(val), SvCUR(val), SvUTF8(val));

View file

@ -77,7 +77,8 @@ RECVFN(bool) {
}
SENDFN(bool) {
fustr_write_ch(out, SvTRUE(val) ? 1 : 0);
int r = fu_2bool(val); /* So that we also recognize \0 and \1 */
fustr_write_ch(out, r < 0 ? SvTRUE(val) : r);
}
RECVFN(void) {