mirror of
https://github.com/Karaka-Management/phpOMS.git
synced 2026-02-11 06:28:40 +00:00
Huffman encoding implemented
This commit is contained in:
parent
ce182bab92
commit
121f030064
|
|
@ -1,6 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
final class Huffman
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
229
Utils/Encoding/Huffman/Dictionary.php
Normal file
229
Utils/Encoding/Huffman/Dictionary.php
Normal file
|
|
@ -0,0 +1,229 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Orange Management
|
||||||
|
*
|
||||||
|
* PHP Version 7.0
|
||||||
|
*
|
||||||
|
* @category TBD
|
||||||
|
* @package TBD
|
||||||
|
* @author OMS Development Team <dev@oms.com>
|
||||||
|
* @author Dennis Eichhorn <d.eichhorn@oms.com>
|
||||||
|
* @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 <dev@oms.com>
|
||||||
|
* @author Dennis Eichhorn <d.eichhorn@oms.com>
|
||||||
|
* @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 <d.eichhorn@oms.com>
|
||||||
|
*/
|
||||||
|
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 <d.eichhorn@oms.com>
|
||||||
|
*/
|
||||||
|
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 <d.eichhorn@oms.com>
|
||||||
|
*/
|
||||||
|
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 <d.eichhorn@oms.com>
|
||||||
|
*/
|
||||||
|
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 <d.eichhorn@oms.com>
|
||||||
|
*/
|
||||||
|
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 <d.eichhorn@oms.com>
|
||||||
|
*/
|
||||||
|
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');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
159
Utils/Encoding/Huffman/Huffman.php
Normal file
159
Utils/Encoding/Huffman/Huffman.php
Normal file
|
|
@ -0,0 +1,159 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Orange Management
|
||||||
|
*
|
||||||
|
* PHP Version 7.0
|
||||||
|
*
|
||||||
|
* @category TBD
|
||||||
|
* @package TBD
|
||||||
|
* @author OMS Development Team <dev@oms.com>
|
||||||
|
* @author Dennis Eichhorn <d.eichhorn@oms.com>
|
||||||
|
* @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 <dev@oms.com>
|
||||||
|
* @author Dennis Eichhorn <d.eichhorn@oms.com>
|
||||||
|
* @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 <d.eichhorn@oms.com>
|
||||||
|
*/
|
||||||
|
public function setDictionary(Dictionary $dictionary)
|
||||||
|
{
|
||||||
|
$this->dictionary = $dictionary;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove dictionary
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
* @author Dennis Eichhorn <d.eichhorn@oms.com>
|
||||||
|
*/
|
||||||
|
public function removeDictionary()
|
||||||
|
{
|
||||||
|
$this->dictionary = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get dictionary
|
||||||
|
*
|
||||||
|
* @return Dictionary
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
* @author Dennis Eichhorn <d.eichhorn@oms.com>
|
||||||
|
*/
|
||||||
|
public function getDictionary() : Dictionary
|
||||||
|
{
|
||||||
|
return $this->dictionary;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encode.
|
||||||
|
*
|
||||||
|
* @param string $source Source to encode
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
* @author Dennis Eichhorn <d.eichhorn@oms.com>
|
||||||
|
*/
|
||||||
|
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 <d.eichhorn@oms.com>
|
||||||
|
*/
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user