<commit_before><?php declare(strict_types=1);
/*
 * This file is part of the Recursion Context package.
 *
 * (c) <NAME> <<EMAIL>>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace SebastianBergmann\RecursionContext;

/**
 * A context containing previously processed arrays and objects
 * when recursively processing a value.
 */
final class Context
{
    /**
     * @var array[]
     */
    private $arrays;

    /**
     * @var \SplObjectStorage
     */
    private $objects;

    /**
     * Initialises the context
     */
    public function __construct()
    {
        $this->arrays  = [];
        $this->objects = new \SplObjectStorage;
    }

    /**
     * @codeCoverageIgnore
     */
    public function __destruct()
    {
        foreach ($this->arrays as &$array) {
            if (\is_array($array)) {
                \array_pop($array);
                \array_pop($array);
            }
        }
    }

    /**
     * Adds a value to the context.
     *
     * @param array|object $value the value to add
     *
     * @throws InvalidArgumentException Thrown if $value is not an array or object
     *
     * @return bool|int|string the ID of the stored value, either as a string or integer
     */
    public function add(&$value)
    {
        if (\is_array($value)) {
            return $this->addArray($value);
        }

        if (\is_object($value)) {
            return $this->addObject($value);
        }

        throw new InvalidArgumentException(
            'Only arrays and objects are supported'
        );
    }

    /**
     * Checks if the given value exists within the context.
     *
     * @param array|object $value the value to check
     *
     * @throws InvalidArgumentException Thrown if $value is not an array or object
     *
     * @return false|int|string the string or integer ID of the stored value if it has already been seen, or false if the value is not stored
     */
    public function contains(&$value)
    {
        if (\is_array($value)) {
            return $this->containsArray($value);
        }

        if (\is_object($value)) {
            return $this->containsObject($value);
        }

        throw new InvalidArgumentException(
            'Only arrays and objects are supported'
        );
    }

    /**
     * @return bool|int
     */
    private function addArray(array &$array)
    {
        $key = $this->containsArray($array);

        if ($key !== false) {
            return $key;
        }

        $key            = \count($this->arrays);
        $this->arrays[] = &$array;

        if (!isset($array[\PHP_INT_MAX]) && !isset($array[\PHP_INT_MAX - 1])) {
            $array[] = $key;
            $array[] = $this->objects;
        } else { /* cover the improbable case too */
            do {
                $key = \random_int(\PHP_INT_MIN, \PHP_INT_MAX);
            } while (isset($array[$key]));

            $array[$key] = $key;

            do {
                $key = \random_int(\PHP_INT_MIN, \PHP_INT_MAX);
            } while (isset($array[$key]));

            $array[$key] = $this->objects;
        }

        return $key;
    }

    /**
     * @param object $object
     *
     * @return string
     */
    private function addObject($object)
    {
        if (!$this->objects->contains($object)) {
            $this->objects->attach($object);
        }

        return \spl_object_hash($object);
    }

    /**
     * @return false|int
     */
    private function containsArray(array &$array)
    {
        $end = \array_slice($array, -2);

        return isset($end[1]) && $end[1] === $this->objects ? $end[0] : false;<commit_msg>Fix: Add return type declaration<commit_after><?php declare(strict_types=1);
/*
 * This file is part of the Recursion Context package.
 *
 * (c) <NAME> <<EMAIL>>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace SebastianBergmann\RecursionContext;

/**
 * A context containing previously processed arrays and objects
 * when recursively processing a value.
 */
final class Context
{
    /**
     * @var array[]
     */
    private $arrays;

    /**
     * @var \SplObjectStorage
     */
    private $objects;

    /**
     * Initialises the context
     */
    public function __construct()
    {
        $this->arrays  = [];
        $this->objects = new \SplObjectStorage;
    }

    /**
     * @codeCoverageIgnore
     */
    public function __destruct()
    {
        foreach ($this->arrays as &$array) {
            if (\is_array($array)) {
                \array_pop($array);
                \array_pop($array);
            }
        }
    }

    /**
     * Adds a value to the context.
     *
     * @param array|object $value the value to add
     *
     * @throws InvalidArgumentException Thrown if $value is not an array or object
     *
     * @return bool|int|string the ID of the stored value, either as a string or integer
     */
    public function add(&$value)
    {
        if (\is_array($value)) {
            return $this->addArray($value);
        }

        if (\is_object($value)) {
            return $this->addObject($value);
        }

        throw new InvalidArgumentException(
            'Only arrays and objects are supported'
        );
    }

    /**
     * Checks if the given value exists within the context.
     *
     * @param array|object $value the value to check
     *
     * @throws InvalidArgumentException Thrown if $value is not an array or object
     *
     * @return false|int|string the string or integer ID of the stored value if it has already been seen, or false if the value is not stored
     */
    public function contains(&$value)
    {
        if (\is_array($value)) {
            return $this->containsArray($value);
        }

        if (\is_object($value)) {
            return $this->containsObject($value);
        }

        throw new InvalidArgumentException(
            'Only arrays and objects are supported'
        );
    }

    /**
     * @return bool|int
     */
    private function addArray(array &$array)
    {
        $key = $this->containsArray($array);

        if ($key !== false) {
            return $key;
        }

        $key            = \count($this->arrays);
        $this->arrays[] = &$array;

        if (!isset($array[\PHP_INT_MAX]) && !isset($array[\PHP_INT_MAX - 1])) {
            $array[] = $key;
            $array[] = $this->objects;
        } else { /* cover the improbable case too */
            do {
                $key = \random_int(\PHP_INT_MIN, \PHP_INT_MAX);
            } while (isset($array[$key]));

            $array[$key] = $key;

            do {
                $key = \random_int(\PHP_INT_MIN, \PHP_INT_MAX);
            } while (isset($array[$key]));

            $array[$key] = $this->objects;
        }

        return $key;
    }

    /**
     * @param object $object
     */
    private function addObject($object): string
    {
        if (!$this->objects->contains($object)) {
            $this->objects->attach($object);
        }

        return \spl_object_hash($object);
    }

    /**
     * @return false|int
     */
    private function containsArray(array &$array)
    {
        $end = \array_slice($array, -2);

        return isset($end[1]) && $end[1] === $this->objects ? $end[0] : false;
{'fraction_non_alphanumeric': 0.1306160882432069, 'fraction_numerical': 0.0016142050040355124, 'mean_word_length': 1.826996197718631, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 43, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1303954', 'n_tokens_mistral': 2150, 'n_tokens_neox': 2068, 'n_words': 578}