#!/usr/bin/perl
# Patch SPA json-core.h (z pipewire) dla libstdc++ 16 / GCC 16.
#
# Problem: GCC 16 usunął z <cmath> "using std::isinf/isnormal/signbit" w przestrzeni
# globalnej. Nagłówek SPA to kod C (używa isnormal/isinf/signbit bez kwalifikacji),
# więc kompilacja C++ (np. Qt Multimedia pipewire backend) kończy się:
#   error: 'isnormal' was not declared in this scope; did you mean 'std::isnormal'?
#
# Fix: kwalifikacja std:: pod #ifdef __cplusplus (+ #include <cmath> dla C++).
# W trybie C zostaje oryginał (bez zmian). Skrypt jest IDEMPOTENTNY.
#
# Użycie: perl spa-json-core-cxx.pl <ścieżka/do/json-core.h>
use strict;
use warnings;

my $file = shift @ARGV or die "usage: $0 <json-core.h>\n";
local $/;
open my $fh, '<', $file or die "open $file: $!\n";
my $s = <$fh>;
close $fh;

my $changed = 0;

# 1) #include <cmath> dla C++ po <float.h> (poza extern "C")
if ($s !~ m{\Q#include <cmath>\E}) {
    $s =~ s{^#include <float\.h>\n}{#include <float.h>\n#ifdef __cplusplus\n#include <cmath>\n#endif\n}m
        or warn "WARNING: 'include <float.h>' not found in $file\n";
    $changed = 1;
}

# 2) Ciało spa_json_format_float: std::-kwalifikacja pod __cplusplus
if ($s !~ m{std::isnormal\(val\)}) {
    # SPA używa TABULATORÓW do wcięć
    my $from =
        "\tif (SPA_UNLIKELY(!isnormal(val))) {\n" .
        "\t\tif (isinf(val))\n" .
        "\t\t\tval = signbit(val) ? FLT_MIN : FLT_MAX;";
    my $to =
        "#ifdef __cplusplus\n" .
        "\tif (SPA_UNLIKELY(!std::isnormal(val))) {\n" .
        "\t\tif (std::isinf(val))\n" .
        "\t\t\tval = std::signbit(val) ? FLT_MIN : FLT_MAX;\n" .
        "#else\n" .
        $from . "\n" .
        "#endif";
    $s =~ s{\Q$from\E}{$to}g
        or warn "WARNING: isnormal pattern not found in $file\n";
    $changed = 1;
}

open my $out, '>', $file or die "open $file for write: $!\n";
print $out $s;
close $out;

exit($changed ? 0 : 0);
