diff --git a/Utils/Encoding/Huffman.php b/Utils/Encoding/Huffman.php deleted file mode 100644 index ac961924f..000000000 --- a/Utils/Encoding/Huffman.php +++ /dev/null @@ -1,6 +0,0 @@ - + * @author Dennis Eichhorn + * @copyright 2013 Dennis Eichhorn + * @license OMS License 1.0 + * @version 1.0.0 + * @link http://orange-management.com + */ +namespace phpOMS\Utils\Encoding\Huffman; + +/** + * Gray encoding class + * + * @category Framework + * @package phpOMS\Utils + * @author OMS Development Team + * @author Dennis Eichhorn + * @license OMS License 1.0 + * @link http://orange-management.com + * @since 1.0.0 + */ +final class Dictionary +{ + /** + * Huffman dictionary. + * + * @var array + * @since 1.0.0 + */ + private $dictionary = []; + + /** + * Minimum length. + * + * @var int + * @since 1.0.0 + */ + private $min = -1; + + /** + * Maximum length. + * + * @var int + * @since 1.0.0 + */ + private $max = -1; + + /** + * Constructor. + * + * @param string $source Source to create the dictionary from + * + * @since 1.0.0 + * @author Dennis Eichhorn + */ + public function __construct(string $source = '') + { + if (isset($source)) { + $this->generate($source); + } + } + + /** + * Get dictionary value by entry + * + * @param string $entry 1 character entry + * + * @return string + * + * @throws + * + * @since 1.0.0 + * @author Dennis Eichhorn + */ + public function get(string $entry) : string + { + if (strlen($entry) !== 1) { + throw new \Exception('Must be a character.'); + } + + if (!isset($this->dictionary[$entry])) { + throw new \Exception('Character does not exist'); + } + + return $this->dictionary[$entry]; + } + + /** + * Get dictionary entry and reduce value + * + * @param string $value Dictionary value + * + * @return null|string + * + * @since 1.0.0 + * @author Dennis Eichhorn + */ + public function getEntry(&$value) + { + $length = strlen($value); + if ($length < $this->min) { + return null; + } + + for ($i = $this->min; $i <= $this->max; ++$i) { + $needle = substr($value, 0, $i); + + foreach ($this->dictionary as $key => $val) { + if ($needle === $val) { + $value = substr($value, $i); + + return $key; + } + } + } + + return null; + } + + /** + * Set dictionary value + * + * @param string $entry 1 character entry + * @param string $value Dictionary value + * + * @return void + * + * @throws + * + * @since 1.0.0 + * @author Dennis Eichhorn + */ + public function set(string $entry, string $value) + { + if (strlen($entry) !== 1) { + throw new \Exception('Must be a character.'); + } + + if (!isset($this->dictionary[$entry])) { + throw new \Exception('Character does not exist'); + } + + if (strlen(str_replace('0', '', str_replace('1', '', $value))) !== 0) { + throw new \Exception('Bad formatting.'); + } + + $length = strlen($value); + + if ($this->min === -1 || $length < $this->min) { + $this->min = $length; + } + + if ($this->max === -1 || $length > $this->max) { + $this->max = $length; + } + + $this->dictionary[$entry] = $value; + } + + /** + * Generate dictionary from data. + * + * @param string $source Source data to generate dictionary from + * + * @return void + * + * @since 1.0.0 + * @author Dennis Eichhorn + */ + public function generate(string $source) + { + $this->dictionary = []; + $this->min = -1; + $this->max = -1; + + $count = []; + while (isset($source[0])) { + $count[] = [substr_count($source, $source[0]), $source[0]]; + $source = str_replace($source[0], '', $source); + } + + sort($count); + + while (count($count) > 1) { + $row1 = array_shift($count); + $row2 = array_shift($count); + $count[] = [$row1[0] + $row2[0], [$row1, $row2]]; + + sort($count); + } + + $this->fill(is_array($count[0][1]) ? $count[0][1] : $count); + } + + /** + * Fill dictionary. + * + * @param string $entry Source data to generate dictionary from + * @param string $value Dictionary value + * + * @return void + * + * @since 1.0.0 + * @author Dennis Eichhorn + */ + private function fill(string $entry, string $value = '') + { + if (!is_array($entry[0][1])) { + $this->set($entry[0][1], $value . '0'); + } else { + $this->fill($entry[0][1], $value . '0'); + } + + if (isset($entry[1])) { + if (!is_array($entry[1][1])) { + $this->set($entry[1][1], $value . '1'); + } else { + $this->fill($entry[1][1], $value . '1'); + } + } + } +} \ No newline at end of file diff --git a/Utils/Encoding/Huffman/Huffman.php b/Utils/Encoding/Huffman/Huffman.php new file mode 100644 index 000000000..758250182 --- /dev/null +++ b/Utils/Encoding/Huffman/Huffman.php @@ -0,0 +1,159 @@ + + * @author Dennis Eichhorn + * @copyright 2013 Dennis Eichhorn + * @license OMS License 1.0 + * @version 1.0.0 + * @link http://orange-management.com + */ +namespace phpOMS\Utils\Encoding\Huffman; + +/** + * Gray encoding class + * + * @category Framework + * @package phpOMS\Utils + * @author OMS Development Team + * @author Dennis Eichhorn + * @license OMS License 1.0 + * @link http://orange-management.com + * @since 1.0.0 + */ +final class Huffman +{ + /** + * Huffman dictionary. + * + * @var Dictionary + * @since 1.0.0 + */ + private $dictionary = null; + + /** + * Set dictionary + * + * @param Dictionary $dictionary Huffman dictionary + * + * @since 1.0.0 + * @author Dennis Eichhorn + */ + public function setDictionary(Dictionary $dictionary) + { + $this->dictionary = $dictionary; + } + + /** + * Remove dictionary + * + * @since 1.0.0 + * @author Dennis Eichhorn + */ + public function removeDictionary() + { + $this->dictionary = null; + } + + /** + * Get dictionary + * + * @return Dictionary + * + * @since 1.0.0 + * @author Dennis Eichhorn + */ + public function getDictionary() : Dictionary + { + return $this->dictionary; + } + + /** + * Encode. + * + * @param string $source Source to encode + * + * @return string + * + * @since 1.0.0 + * @author Dennis Eichhorn + */ + public function encode(string $source) : string + { + if (empty($source)) { + return ''; + } + + if (!isset($this->dictionary)) { + $this->dictionary = new Dictionary($source); + } + + $binary = ''; + for ($i = 0; isset($source[$i]); ++$i) { + $binary .= $this->dictionary->get($source[$i]); + } + + $splittedBinaryString = str_split('1' . $binary . '1', 8); + $binary = ''; + + foreach ($splittedBinaryString as $i => $c) { + while (strlen($c) < 8) { + $c .= '0'; + } + + $binary .= chr(bindec($c)); + } + + return $binary; + } + + /** + * Decode. + * + * @param string $raw Raw to decode + * + * @return string + * + * @since 1.0.0 + * @author Dennis Eichhorn + */ + public function decode(string $raw) : string + { + if (empty($raw)) { + return ''; + } + + $binary = ''; + $rawLenght = strlen($raw); + $source = ''; + + for ($i = 0; $i < $rawLenght; ++$i) { + $decbin = decbin(ord($raw[$i])); + + while (strlen($decbin) < 8) { + $decbin = '0' . $decbin; + } + + if ($i === 0) { + $decbin = substr($decbin, strpos($decbin, '1') + 1); + } + + if ($i + 1 === $rawLenght) { + $decbin = substr($decbin, 0, strrpos($decbin, '1')); + } + + $binary .= $decbin; + + while (($entry = $this->dictionary->getEntry($binary)) !== null) { + $source .= $entry; + } + } + + return $source; + } +} \ No newline at end of file