src/FixedBitNotation.php
public function decode($encodedString, $caseSensitive = true, $strict = false)
    {
        if (!$encodedString || !is_string($encodedString)) {
            // Empty string, nothing to decode
            return '';
        }

        $chars = $this->chars;
        $bitsPerCharacter = $this->bitsPerCharacter;
        $radix = $this->radix;
        $rightPadFinalBits = $this->rightPadFinalBits;
        $padFinalGroup = $this->padFinalGroup;
        $padCharacter = $this->padCharacter;

        // Get index of encoded characters
        if ($this->charmap) {
            $charmap = $this->charmap;
        } else {
            $charmap = array();

            for ($i = 0; $i < $radix; ++$i) {
                $charmap[$chars[$i]] = $i;
            }

            $this->charmap = $charmap;
        }

        // The last encoded character is $encodedString[$lastNotatedIndex]
        $lastNotatedIndex = strlen($encodedString) - 1;

        // Remove trailing padding characters
        while ($encodedString[$lastNotatedIndex] == $padCharacter[0]) {
            $encodedString = substr($encodedString, 0, $lastNotatedIndex);
            --$lastNotatedIndex;
        }

        $rawString = '';
        $byte = 0;
        $bitsWritten = 0;

        // Convert each encoded character to a series of unencoded bits
        for ($c = 0; $c <= $lastNotatedIndex; ++$c) {
            if (!isset($charmap[$encodedString[$c]]) && !$caseSensitive) {
                // Encoded character was not found; try other case
                if (isset($charmap[$cUpper
                = strtoupper($encodedString[$c])])) {
                    $charmap[$encodedString[$c]] = $charmap[$cUpper];
                } elseif (isset($charmap[$cLower
                = strtolower($encodedString[$c])])) {
                    $charmap[$encodedString[$c]] = $charmap[$cLower];
                }
            }

            if (isset($charmap[$encodedString[$c]])) {
                $bitsNeeded = 8 - $bitsWritten;
                $unusedBitCount = $bitsPerCharacter - $bitsNeeded;

                // Get the new bits ready
                if ($bitsNeeded > $bitsPerCharacter) {
                    // New bits aren't enough to complete a byte; shift them
                    // left into position
                    $newBits = $charmap[$encodedString[$c]] << $bitsNeeded
                    - $bitsPerCharacter;
                    $bitsWritten += $bitsPerCharacter;
                } elseif ($c != $lastNotatedIndex || $rightPadFinalBits) {
                    // Zero or more too many bits to complete a byte;
                    // shift right
                    $newBits = $charmap[$encodedString[$c]] >> $unusedBitCount;
                    $bitsWritten = 8; //$bitsWritten += $bitsNeeded;
                } else {
                    // Final bits don't need to be shifted
                    $newBits = $charmap[$encodedString[$c]];
                    $bitsWritten = 8;
                }

                $byte |= $newBits;

                if ($bitsWritten == 8 || $c == $lastNotatedIndex) {
                    // Byte is ready to be written
                    $rawString .= pack('C', $byte);

                    if ($c != $lastNotatedIndex) {
                        // Start the next byte
                        $bitsWritten = $unusedBitCount;
                        $byte = ($charmap[$encodedString[$c]]
                        ^ ($newBits << $unusedBitCount)) << 8 - $bitsWritten;
                    }
                }
            } elseif ($strict) {
                // Unable to decode character; abort
                return null;
            }
        }

        return $rawString;
    }
public function decode($encodedString, $caseSensitive = true, $strict = false)
    {
        if (!$encodedString || !is_string($encodedString)) {
            // Empty string, nothing to decode
            return '';
        }

        $chars = $this->chars;
        $bitsPerCharacter = $this->bitsPerCharacter;
        $radix = $this->radix;
        $rightPadFinalBits = $this->rightPadFinalBits;
        $padFinalGroup = $this->padFinalGroup;
        $padCharacter = $this->padCharacter;

        // Get index of encoded characters
        if ($this->charmap) {
            $charmap = $this->charmap;
        } else {
            $charmap = array();

            for ($i = 0; $i < $radix; ++$i) {
                $charmap[$chars[$i]] = $i;
            }

            $this->charmap = $charmap;
        }

        // The last encoded character is $encodedString[$lastNotatedIndex]
        $lastNotatedIndex = strlen($encodedString) - 1;

        // Remove trailing padding characters
        while ($encodedString[$lastNotatedIndex] == $padCharacter[0]) {
            $encodedString = substr($encodedString, 0, $lastNotatedIndex);
            --$lastNotatedIndex;
        }

        $rawString = '';
        $byte = 0;
        $bitsWritten = 0;

        // Convert each encoded character to a series of unencoded bits
        for ($c = 0; $c <= $lastNotatedIndex; ++$c) {
            if (!isset($charmap[$encodedString[$c]]) && !$caseSensitive) {
                // Encoded character was not found; try other case
                if (isset($charmap[$cUpper
                = strtoupper($encodedString[$c])])) {
                    $charmap[$encodedString[$c]] = $charmap[$cUpper];
                } elseif (isset($charmap[$cLower
                = strtolower($encodedString[$c])])) {
                    $charmap[$encodedString[$c]] = $charmap[$cLower];
                }
            }

            if (isset($charmap[$encodedString[$c]])) {
                $bitsNeeded = 8 - $bitsWritten;
                $unusedBitCount = $bitsPerCharacter - $bitsNeeded;

                // Get the new bits ready
                if ($bitsNeeded > $bitsPerCharacter) {
                    // New bits aren't enough to complete a byte; shift them
                    // left into position
                    $newBits = $charmap[$encodedString[$c]] << $bitsNeeded
                    - $bitsPerCharacter;
                    $bitsWritten += $bitsPerCharacter;
                } elseif ($c != $lastNotatedIndex || $rightPadFinalBits) {
                    // Zero or more too many bits to complete a byte;
                    // shift right
                    $newBits = $charmap[$encodedString[$c]] >> $unusedBitCount;
                    $bitsWritten = 8; //$bitsWritten += $bitsNeeded;
                } else {
                    // Final bits don't need to be shifted
                    $newBits = $charmap[$encodedString[$c]];
                    $bitsWritten = 8;
                }

                $byte |= $newBits;

                if ($bitsWritten == 8 || $c == $lastNotatedIndex) {
                    // Byte is ready to be written
                    $rawString .= pack('C', $byte);

                    if ($c != $lastNotatedIndex) {
                        // Start the next byte
                        $bitsWritten = $unusedBitCount;
                        $byte = ($charmap[$encodedString[$c]]
                        ^ ($newBits << $unusedBitCount)) << 8 - $bitsWritten;
                    }
                }
            } elseif ($strict) {
                // Unable to decode character; abort
                return null;
            }
        }

        return $rawString;
    }
Decode a string.

@param string $encodedString Data to decode
@param bool   $caseSensitive
@param bool   $strict        Returns null if $encodedString contains
an undecodable character

@return string|null