public static function generate($length = 8, $allowed = RandomString::ASCII, $repeatable = true): string
    {
        $allowedChars = array();
        
        $currentLocale = setlocale(LC_ALL, "0");
        if ($allowed == RandomString::ASCII) {
            setlocale(LC_ALL, "C");
        }
        
        for ($i = 32; $i < 256; $i ++) {
            if (($allowed == RandomString::ASCII && ! ctype_alnum(chr($i))) || (! ctype_print(chr($i)))) {
                continue;
            }
            $allowedChars[] = $i;
        }
        
        self::resetLocaleTo($currentLocale);
        
        $used = array();
        
        $string = "";
        $i = $length;
        while ($i > 0) {
            $index = mt_rand(0, count($allowedChars) - 1);
            if (! $repeatable && in_array($index, $used)) {
                continue;
            }
            $string .= chr($allowedChars[$index]);
            $used[] = $i;
            $i --;
        }
        
        return $string;
    }