<commit_before><?php

namespace App;

/**
 * A flexible class for parsing/storing color values
 * RGB values can be iterated on using foreach and can be acessed via array keys 0-2
 */
class RGBAColor implements \ArrayAccess {
	/** @var int */
	public $red, $green, $blue;
	/** @var float */
	public $alpha;

	/**
	 * Maps patterns to a boolean indicating whether the results can be used directly (without hex->dec conversion)
	 */
	const PATTERNS = [
		'/#([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})?/i' => false,
		'/#([a-f\d])([a-f\d])([a-f\d])/i' => false,
		'/rgba?\(\s*(\d+),\s*(\d+),\s*(\d+)(?:,\s*([10]|0?\.\d+))?\s*\)/i' => true,
	];

	public function __construct(int $r, int $g, int $b, float $a = 1){
		$this->red = $r;
		$this->green = $g;
		$this->blue = $b;
		$this->alpha = $a;
	}

	public function setRed(int $r){
		$this->red = $r;

		return $this;
	}

	public function setGreen(int $g){
		$this->green = $g;

		return $this;
	}

	public function setBlue(int $b){
		$this->blue = $b;

		return $this;
	}

	public function setAlpha(float $a){
		$this->alpha = $a;

		return $this;
	}

	public function isTransparent(){
		return $this->alpha !== 1.0;
	}

	public function toHex():string {
		return '#'.strtoupper(CoreUtils::pad(base_convert($this->red, 10, 16)).CoreUtils::pad(base_convert($this->green, 10, 16)).CoreUtils::pad(base_convert($this->blue, 10, 16)));
	}

	public function toHexa():string {
		return $this->toHex().strtoupper(CoreUtils::pad(base_convert(round($this->alpha*255),10,16)));
	}

	public function toRGB():string {
		return "rgb({$this->red},{$this->green},{$this->blue})";
	}

	public function toRGBA():string {
		return "rgba({$this->red},{$this->green},{$this->blue},{$this->alpha})";
	}

	public function __toString():string {
		return $this->isTransparent() ? $this->toRGBA() : $this->toHex();
	}

	/**
	 * @param bool $alpha
	 *
	 * @return self
	 */
	public function invert($alpha = false):self {
		$this->red = 255 - $this->red;
		$this->green = 255 - $this->green;
		$this->blue = 255 - $this->blue;
		if ($alpha)
			$this->alpha = 1 - $this->alpha;

		return $this;
	}

	public static function forEachColorIn(string &$input, callable $callback){
		foreach (self::PATTERNS as $pattern => $_)
			$input = preg_replace_callback($pattern, function($match) use ($callback, $pattern){
				return $callback(self::_parseWith($match[0], $pattern));
			}, $input);
	}

	/**
	 * @param string $color
	 * @param string $pattern
	 *
	 * @return self|null
	 */
	private static function _parseWith(string $color, string $pattern):?self {
		if (!preg_match($pattern, $color, $matches))
			return null;

		$values = array_slice($matches, 1, 4);

		if (!self::PATTERNS[$pattern]){
			if (strlen($values[0]) === 1)
				$values = array_map(function($el){ return $el.$el; }, $values);
			$values[0] = intval($values[0], 16);
			$values[1] = intval($values[1], 16);
			$values[2] = intval($values[2], 16);
			if (!empty($values[3]))
				$values[3] = intval($values[3], 16)/255;
		}

		return new self(...$values);
	}

	/**
	 * @param string $color
	 *
	 * @return self|null
	 */
	public static function parse(string $color):?self {
		foreach (self::PATTERNS as $pattern => $_){
			$result = self::_parseWith($color, $pattern);
			if ($result === null)
				continue;

			return $result;
		}

		return null;
	}

    # ArrayAccess support
	private const TRAVERSABLE_KEYS = ['red','green','blue'];
	public function offsetExists ($offset):boolean { return isset(self::TRAVERSABLE_KEYS[$offset]); }
	public function offsetGet    ($offset)         { return $this->{self::TRAVERSABLE_KEYS[$offset]}; }
	public function offsetSet    ($offset, $value) { $this->{self::TRAVERSABLE_KEYS[$offset]} = (int)$value; }
	public function offsetUnset  ($offset)         { throw new \RuntimeException(__CLASS__.' does not support unsetting color values'); }
}<commit_msg>Nothing to see here, move along<commit_after><?php

namespace App;

/**
 * A flexible class for parsing/storing color values
 * RGB values can be iterated on using foreach and can be acessed via array keys 0-2
 */
class RGBAColor implements \ArrayAccess, \Iterator {
	/** @var int */
	public $red, $green, $blue;
	/** @var float */
	public $alpha;

	/**
	 * Maps patterns to a boolean indicating whether the results can be used directly (without hex->dec conversion)
	 */
	const PATTERNS = [
		'/#([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})?/i' => false,
		'/#([a-f\d])([a-f\d])([a-f\d])/i' => false,
		'/rgba?\(\s*(\d+),\s*(\d+),\s*(\d+)(?:,\s*([10]|0?\.\d+))?\s*\)/i' => true,
	];

	public function __construct(int $r, int $g, int $b, float $a = 1){
		$this->red = $r;
		$this->green = $g;
		$this->blue = $b;
		$this->alpha = $a;
	}

	public function setRed(int $r){
		$this->red = $r;

		return $this;
	}

	public function setGreen(int $g){
		$this->green = $g;

		return $this;
	}

	public function setBlue(int $b){
		$this->blue = $b;

		return $this;
	}

	public function setAlpha(float $a){
		$this->alpha = $a;

		return $this;
	}

	public function isTransparent(){
		return $this->alpha !== 1.0;
	}

	public function toHex():string {
		return '#'.strtoupper(CoreUtils::pad(base_convert($this->red, 10, 16)).CoreUtils::pad(base_convert($this->green, 10, 16)).CoreUtils::pad(base_convert($this->blue, 10, 16)));
	}

	public function toHexa():string {
		return $this->toHex().strtoupper(CoreUtils::pad(base_convert(round($this->alpha*255),10,16)));
	}

	public function toRGB():string {
		return "rgb({$this->red},{$this->green},{$this->blue})";
	}

	public function toRGBA():string {
		return "rgba({$this->red},{$this->green},{$this->blue},{$this->alpha})";
	}

	public function __toString():string {
		return $this->isTransparent() ? $this->toRGBA() : $this->toHex();
	}

	/**
	 * @param bool $alpha
	 *
	 * @return self
	 */
	public function invert($alpha = false):self {
		$this->red = 255 - $this->red;
		$this->green = 255 - $this->green;
		$this->blue = 255 - $this->blue;
		if ($alpha)
			$this->alpha = 1 - $this->alpha;

		return $this;
	}

	public static function forEachColorIn(string &$input, callable $callback){
		foreach (self::PATTERNS as $pattern => $_)
			$input = preg_replace_callback($pattern, function($match) use ($callback, $pattern){
				return $callback(self::_parseWith($match[0], $pattern));
			}, $input);
	}

	/**
	 * @param string $color
	 * @param string $pattern
	 *
	 * @return self|null
	 */
	private static function _parseWith(string $color, string $pattern):?self {
		if (!preg_match($pattern, $color, $matches))
			return null;

		$values = array_slice($matches, 1, 4);

		if (!self::PATTERNS[$pattern]){
			if (strlen($values[0]) === 1)
				$values = array_map(function($el){ return $el.$el; }, $values);
			$values[0] = intval($values[0], 16);
			$values[1] = intval($values[1], 16);
			$values[2] = intval($values[2], 16);
			if (!empty($values[3]))
				$values[3] = intval($values[3], 16)/255;
		}

		return new self(...$values);
	}

	/**
	 * @param string $color
	 *
	 * @return self|null
	 */
	public static function parse(string $color):?self {
		foreach (self::PATTERNS as $pattern => $_){
			$result = self::_parseWith($color, $pattern);
			if ($result === null)
				continue;

			return $result;
		}

		return null;
	}

	# Iterator support
	private const TRAVERSABLE_KEYS = ['red','green','blue'];
    private $_travPosition = 0;
    public function rewind()  { $this->_travPosition = 0; }
    public function current() { return $this->{self::TRAVERSABLE_KEYS[$this->_travPosition]}; }
    public function key()     { return $this->_travPosition; }
    public function next()    { ++$this->_travPosition; }
    public function valid()   { return isset(self::TRAVERSABLE_KEYS[$this->_travPosition]); }

    # Countable support
    public function count()   { return count(self::TRAVERSABLE_KEYS); }

    # ArrayAccess support
	public function offsetExists ($offset):boolean { return isset(self::TRAVERSABLE_KEYS[$offset]); }
	public function offsetGet    ($offset)         { return $this->{self::TRAVERSABLE_KEYS[$offset]}; }
	public function offsetSet    ($offset, $value) { $this->{self::TRAVERSABLE_KEYS[$offset]} = (int)$value; }
	public function offsetUnset  ($offset)         { throw new \RuntimeException(__CLASS__.' does not support unsetting color values'); }
}
{'fraction_non_alphanumeric': 0.20175649663137632, 'fraction_numerical': 0.016121270452358036, 'mean_word_length': 3.974865350089767, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 89, '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': '4097490', 'n_tokens_mistral': 3247, 'n_tokens_neox': 2916, 'n_words': 672}