mb_check_encoding() の代替関数

これまでに挙げた文字コードについて、正規表現を使用して mb_check_encoding() の代替用の関数を書いてみました。ある程度、妥当なものになっているとは思いますが、間違い等に気付いた方がおられましたら、ご指摘ください。
UTF-8 については、RFC3629 を参考にしました。各文字は4バイト以下、冗長な表現、サロゲートペアの領域を FALSE と判定します。

<?php
function is_valid_encoding( $str, $encoding )
{
    switch ( $encoding ) {
    case 'ASCII' :
        $regex = '/(?:'
            . '[\x00-\x7f]'                                             // ASCII (mb_check_encoding)
//          . '[\x00\x09\x0a\x0d\x20-\x7f]'                             // ASCII (mb_detect_encoding)
            . ')/';
        break;

    case 'SJIS' :
        $regex = '/(?:'
            . '[\x00-\x7f]|'                                            // ASCII
            . '[\xa1-\xdf]|'                                            // いわゆる半角カナ
            . '[\x81-\x9f\xe0-\xef][\x40-\x7e\x80-\xfc]'
            . ')/';
        break;

    case 'SJIS-win' :
        $regex = '/(?:'
            . '[\x00-\x7f]|'                                            // ASCII
            . '[\xa1-\xdf]|'                                            // いわゆる半角カナ
            . '[\x81-\x9f\xe0-\xfc][\x40-\x7e\x80-\xfc]'
            . ')/';
        break;

    case 'EUC-JP' :
        $regex = '/(?:'
            . '[\x00-\x7f]|'                                            // ASCII
            . '[\xa1-\xfe][\xa1-\xfe]|'
            . '\x8e[\xa1-\xfe]|'                                        // いわゆる半角カナ
            . '\x8f[\xa1-\xfe][\xa1-\xfe]'
            . ')/';
        break;

    case 'eucJP-win' :
        $regex = '/(?:'
            . '[\x00-\x7f]|'                                            // ASCII
            . '[\xa1-\xfe][\xa1-\xfe]|'
            . '\x8e[\xa1-\xfe]|'                                        // いわゆる半角カナ
            . '\x8f[\xa1-\xfe][\xa1-\xfe]'
            . ')/';
        break;

    case 'CP51932' :
        $regex = '/(?:'
            . '[\x00-\x7f]|'                                            // ASCII
            . '[\xa1-\xfe][\xa1-\xfe]|'
            . '\x8e[\xa1-\xfe]'                                         // いわゆる半角カナ
            . ')/';
        break;

    case 'UTF-8' :                                                      // 参照: http://tools.ietf.org/html/rfc3629
        $regex = '/(?:'
            . '[\x00-\x7f]|'                                            // U+0000   - U+007F
            . '[\xc2-\xdf][\x80-\xbf]|'                                 // U+0080   - U+07FF
            . '\xe0[\xa0-\xbf][\x80-\xbf]|'                             // U+0800   - U+0FFF
            . '[\xe1-\xec][\x80-\xbf][\x80-\xbf]|'                      // U+1000   - U+CFFF
            . '\xed[\x80-\x9f][\x80-\xbf]|'                             // U+D000   - U+D7FF
            . '[\xee-\xef][\x80-\xbf][\x80-\xbf]|'                      // U+E000   - U+FFFF
            . '\xf0[\x90-\xbf][\x80-\xbf][\x80-\xbf]|'                  // U+10000  - U+3FFFF
            . '[\xf1-\xf3][\x80-\xbf][\x80-\xbf][\x80-\xbf]|'           // U+40000  - U+FFFFF
            . '\xf4[\x80-\x8f][\x80-\xbf][\x80-\xbf]|'                  // U+100000 - U+10FFFF
            . ')/';
        break;

    case 'ISO-2022-JP' :
        $regex = '/(?:'
            . '[\x00-\x7f]|'                                            // ASCII
            . '\x1b\x24[\x40\x42](?:[\x21-\x7e][\x21-\x7e])+|'          // ESC $ @,B
            . '\x1b\x24\x28[\x40\x42\x44](?:[\x21-\x7e][\x21-\x7e])+|'  // ESC $ ( @,B,D
            . '\x1b\x28\x42'                                            // ESC ( B
            . ')/';
        break;

    case 'ISO-2022-JP-MS' :
        $regex = '/(?:'
            . '[\x00-\x7f]|'                                            // ASCII
            . '\x1b\x24[\x40\x42](?:[\x21-\x7e][\x21-\x7e])+|'          // ESC $ @,B
            . '\x1b\x24\x28[\x40\x42\x44](?:[\x21-\x7e][\x21-\x7e])+|'  // ESC $ ( @,B,D
            . '\x1b\x28\x42|'                                           // ESC ( B
            . '\x1b\x28\x4a[\x00-\x1a\x1c-\x7f]+|'                      // ESC ( J
            . '\x1b\x28\x49[\x00-\x1a\x1c-\x7f]+'                       // ESC ( I
            . ')/';
        break;

    case 'UTF-16' :
        if ( (bool)preg_match( '/\A\xff\xfe/', $str ) ) {               // BOM(Little Endian)
            $regex = '/(?:'
                . '[\x00-\xff][\x00-\xd7\xe0-\xff]|'                    // U+0000-U+D7FF, U+E000-U+FFFF
                . '[\x00-\xff][\xd8-\xdb][\x00-\xff][\xdc-\xdf]'        // サロゲートペア(U+D800-U+DBFF)
                . ')/';
        }
        else {                                                          // BOM(Big Endian) BOMがない場合は Big Endian
            $regex = '/(?:'
                . '[\x00-\xd7\xe0-\xff][\x00-\xff]|'                    // U+0000-U+D7FF, U+E000-U+FFFF
                . '[\xd8-\xdb][\x00-\xff][\xdc-\xdf][\x00-\xff]'        // サロゲートペア(U+D800-U+DBFF)
                . ')/';
        }
        break;

    case 'UTF-16BE' :                                                   // BOMは不可
        $regex = '/(?:'
            . '[\x00-\xd7\xe0-\xff][\x00-\xff]|'                        // U+0000-U+D7FF, U+E000-U+FFFF
            . '[\xd8-\xdb][\x00-\xff][\xdc-\xdf][\x00-\xff]'            // サロゲートペア(U+D800-U+DBFF)
            . ')/';
        break;

    case 'UTF-16LE' :                                                   // BOMは不可
        $regex = '/(?:'
            . '[\x00-\xff][\x00-\xd7\xe0-\xff]|'                        // U+0000-U+D7FF, U+E000-U+FFFF
            . '[\x00-\xff][\xd8-\xdb][\x00-\xff][\xdc-\xdf]'            // サロゲートペア(U+D800-U+DBFF)
            . ')/';
        break;

    default :
        return FALSE;
    }

    $result = preg_replace( $regex, '', $str );
    if ( $result !== '' ) {
        return FALSE;
    }
    return TRUE;
}

最後の判定に preg_replace() を使用しているのは、preg_match() で長い文字列をマッチさせると、PHP が Segmentation Fault を起こすことがあるためです。この原因は調べていません。
単純な例としては、以下の通りです。

$ php -r 'var_dump( preg_match( "/(.)*/", str_repeat( "A", 10000 ) ) );'
zsh: segmentation fault