<commit_before><?php
namespace Radiergummi\libconfig;

use ArrayAccess;
use Iterator;
use Countable;

/**
 * General purpose config class
 * 
 * @package php-config
 * @author <NAME> <<EMAIL>>
 */
class Config implements \ArrayAccess, \Iterator, \Countable
{

	/**
	 * holds the configuration
	 * 
	 * @var array
	 */
	private $data = array();


	/**
	 * Iterator Access Counter
	 * 
	 * @var int
	 */
	private $iteratorCount = 0;


	/**
	 * Constructor
	 * Populates the data array with the values injected at runtime
	 *
	 * @param mixed $data The raw input data
	 */
	public function __construct($data)
	{

		// if we've got an array, use it, else, we assume this is json.
		$this->data = (is_array($data) ? $data : $this->parse($data));
	}
  
  
	/**
	 * parses the input given as a json string
	 * 
	 * @param string $input the JSON string
	 * @return array the parsed data
	 */
	private function parse($input)
	{
		$data = json_decode($input, true);
		if ($error = json_last_error() != 0) {
			throw new Exception('Error while parsing JSON: ' . $error);
		}

		return $data;
	}


	/**
	 * merges the config data with another array
	 * 
	 * @param string|array $input the data to add
	 * @return void
	 */
	public function add($input)
	{
		// determine if array or path given
		if (is_string($input)) {
			if (is_dir($input)) {
				if (! is_readable($input)) throw new Exception('Directory is not readable.');
				
				// add each file in a directory to the config
				foreach (array_diff(scandir($input), array('..', '.')) as $file) {
					$this->add($file);
				}
				
				// break out
				return;
			} else if (is_file($input)) {
				if (! is_readable($input)) throw new Exception('File is not readable.');
				
				$this->add($this->parse(file_get_contents($input)));
				
				// break out
				return;
			} else {
				// attempt to parse input
				$this->add($this->parse($input));
			}
		}
		// merge the arrays 
		$this->data = array_replace_recursive($input, $this->data);
	}

	/**
	 * gets a value from the config array
	 *
	 * @param string $key (optional) the config key in question
	 * @param mixed $fallback (optional) a fallback value in case the config is empty
	 * @return the value of $data[$key]
	 */
	public function get($key = null, $fallback = null)
	{
		// return the whole config if no key specified
		if (! $key) return $this->data;

		$keys = explode('.', $key);
		$values = $this->data;
		if (count($keys) == 1) {
			$value = $values[$keys[0]];
			return (!empty($value) ? $value : $fallback);
		} else {
			// search the array using the dot character to access nested array values
			foreach($keys as $key) {
				// when a key is not found or we didnt get an array to search return a fallback value
				if(! array_key_exists($key, $values)) {
					return $fallback;
				}
				$values =& $values[$key];
			}
			return $values;
		}
	}


	/**
	 * checks wether a key is set or not
	 *
	 * @param string $key  the config key in question
	 * @return bool wether the key exists or not
	 */
	public function has($key)
	{
		return (! is_null($this->get($key))) ? true : false;	
	}


	/**
	 * sets a value in the config array
	 * 
	 * @param string $key the config key in question
	 * @param mixed $value the value to set 
	 * @return void;
	 */
	public function set($key, $value)
	{
		$array =& $this->data;
		$keys = explode('.', $key);
		// traverse the array into the second last key
		while(count($keys) > 1) {
			$key = array_shift($keys);
			// make sure we have an array to set our new key in
			if( ! array_key_exists($key, $array)) {
				$array[$key] = array();
			}
			$array =& $array[$key];
		}
		$array[array_shift($keys)] = $value;
	}


	/**
	 * erases a key from the array
	 *
	 * @param string $key the config key in question
	 */
	public function erase(string $key)
	{
		$array =& $this->data;
		$keys = explode('.', $key);
		// traverse the array into the second last key
		while(count($keys) > 1) {
			$key = array_shift($keys);
			$array =& $array[$key];
		}
		unset($array[array_shift($keys)]);
	}


	/**
	 * returns the complete config array. Mainly for debug purposes, but what do I know? I'm just a comment.'
	 * 
	 * @return array $data the complete config array
	 */
	 public function __tostring()
	 {
	 	return $this->data;
	 }

	
	/**
	 * ArrayAccess Interface<commit_msg>Update config.php<commit_after><?php
namespace Radiergummi\libconfig;

use ArrayAccess;
use Iterator;
use Countable;

/**
 * General purpose config class
 * 
 * @package php-config
 * @author <NAME> <<EMAIL>>
 */
class Config implements \ArrayAccess, \Iterator, \Countable
{

	/**
	 * holds the configuration
	 * 
	 * @var array
	 */
	private $data = array();


	/**
	 * Iterator Access Counter
	 * 
	 * @var int
	 */
	private $iteratorCount = 0;


	/**
	 * Constructor
	 * Populates the data array with the values injected at runtime
	 *
	 * @param mixed $data The raw input data
	 */
	public function __construct($data)
	{

		// if we've got an array, use it, else, we assume this is json.
		$this->data = (is_array($data) ? $data : $this->parse($data));
	}
  
  
	/**
	 * parses the input given as a json string
	 * 
	 * @param string $input the JSON string
	 * @return array the parsed data
	 */
	private function parse($input)
	{
		$data = json_decode($input, true);
		if ($error = json_last_error() != 0) {
			throw new Exception('Error while parsing JSON: ' . $error);
		}

		return $data;
	}


	/**
	 * merges the config data with another array
	 * 
	 * @param string|array $input the data to add
	 * @return void
	 */
	public function add($input)
	{
		// determine if array or path given
		if (is_string($input)) {
			if (is_dir($input)) {
				if (! is_readable($input)) throw new Exception('Directory is not readable.');
				
				// add each file in a directory to the config
				foreach (array_diff(scandir($input), array('..', '.')) as $file) {
					$this->add($file);
				}
				
				// break out
				return;
			} else if (is_file($input)) {
				if (! is_readable($input)) throw new Exception('File is not readable.');
				
				$this->add($this->parse(file_get_contents($input)));
				
				// break out
				return;
			} else {
				// attempt to parse input
				$this->add($this->parse($input));
			}
		}
		// merge the arrays 
		$this->data = array_replace_recursive($input, $this->data);
	}

	/**
	 * gets a value from the config array
	 *
	 * @param string $key (optional) the config key in question
	 * @param mixed $fallback (optional) a fallback value in case the config is empty
	 * @return the value of $data[$key]
	 */
	public function get($key = null, $fallback = null)
	{
		// return the whole config if no key specified
		if (! $key) return $this->data;

		$keys = explode('.', $key);
		$values = $this->data;
		if (count($keys) == 1) {
			$value = $values[$keys[0]];
			return (!empty($value) ? $value : $fallback);
		} else {
			// search the array using the dot character to access nested array values
			foreach($keys as $key) {
				// when a key is not found or we didnt get an array to search return a fallback value
				if(! array_key_exists($key, $values)) {
					return $fallback;
				}
				$values =& $values[$key];
			}
			return $values;
		}
	}


	/**
	 * checks wether a key is set or not
	 *
	 * @param string $key  the config key in question
	 * @return bool wether the key exists or not
	 */
	public function has($key)
	{
		return (! is_null($this->get($key))) ? true : false;	
	}


	/**
	 * sets a value in the config array
	 * 
	 * @param string $key the config key in question
	 * @param mixed $value the value to set 
	 * @return void;
	 */
	public function set($key, $value)
	{
		$array =& $this->data;
		$keys = explode('.', $key);
		// traverse the array into the second last key
		while(count($keys) > 1) {
			$key = array_shift($keys);
			// make sure we have an array to set our new key in
			if( ! array_key_exists($key, $array)) {
				$array[$key] = array();
			}
			$array =& $array[$key];
		}
		$array[array_shift($keys)] = $value;
	}


	/**
	 * erases a key from the array
	 *
	 * @param string $key the config key in question
	 */
	public function erase($key)
	{
		$array =& $this->data;
		$keys = explode('.', $key);
		// traverse the array into the second last key
		while(count($keys) > 1) {
			$key = array_shift($keys);
			$array =& $array[$key];
		}
		unset($array[array_shift($keys)]);
	}


	/**
	 * returns the complete config array. Mainly for debug purposes, but what do I know? I'm just a comment.'
	 * 
	 * @return array $data the complete config array
	 */
	 public function __tostring()
	 {
	 	return $this->data;
	 }

	
	/**
	 * ArrayAccess Interface
{'fraction_non_alphanumeric': 0.14566701376836746, 'fraction_numerical': 0.0013884068031933356, 'mean_word_length': 2.8658318425760285, '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': '602273', 'n_tokens_mistral': 3220, 'n_tokens_neox': 2719, 'n_words': 947}