public function encode($string, $exclude=null, $keepEscaped=true)
    {
        $result = '';

        if ( !is_string($exclude) ) {
            // encode($string, $keepEscaped)
            $keepEscaped  = $exclude;
            $exclude = $this->defaultChars;
        }
        if( !isset($keepEscaped) ) $keepEscaped = true;

        $cache = $this->getEncodeCache($exclude);

        for ($i = 0, $l = mb_strlen($string); $i < $l; $i++) {
            $ch = mb_substr($string,$i,1);
            $chLen = strlen($ch);

            if ($keepEscaped && $ch === '%' && $i + 2 < $l) {
                if (preg_match("/^[0-9a-f]{2}$/i", mb_substr($string, $i + 1, 2))) {
                    $result .= mb_substr($string, $i, 3);
                    $i += 2;
                    continue;
                }
            }

            if ( $chLen === 1 && ($code = ord($ch)) < 128) {
                $result .= $cache[$code];
                continue;
            }

            $result .= rawurlencode($ch);
        }
        return $result;
    }