private function readKeyValue($str, &$p)
    {

        $c = substr($str, $p, 1);

        // Unquoted string.
        if ($c != '"') {
            $len = strcspn($str, " \r\n\t,=>", $p);
            $value = substr($str, $p, $len);
            $p += $len;
            // $value = stripcslashes($value)
            $value = str_replace( '\\"', '"', $value );
            $value = str_replace( '\\\\', '\\', $value );
            return $value;
        }

        // Quoted string.
        $m = null;
        if (preg_match('/" ((?' . '>[^"\\\\]+|\\\\.)*) "/Asx', $str, $m, 0, $p)) {
            $p += strlen( $m[0] );
            // $value = stripcslashes($m[1]);
            $value = str_replace( '\\"', '"', $m[1] );
            $value = str_replace( '\\\\', '\\', $value );
            return $value;
        }

        // Error.
        throw new \Exception( "quoted or unquoted string `{$str}` only" );

    }