Преобразование кодировок

Пример преобразования кодировок. Поддерживаются 437 , 866 , 1251 , 1252 , KOI8-R , UTF8 , UNICODE
Весь принцип кодирования: преобразуем исходную кодировку в UNICODE , а далее из UNICODE  в нужную кодировку. Пример включает 4 функции (2 основные и 2 вспомогательные). Любое кодирование выполняется с помощью 2 функций: EncodeCharToUnicode , EncodeUnicodeToChar. После использования функции EncodeCharToUnicode необходимо освобождать указатель (в примере показано). В перечислении ENUM (E_CODEPAGE) указано , какие параметры можно указывать для различных кодировок. В другом перечислении ENUM (E_ENCODE_ERROR) список ошибок , которые могут возвратить функции.

Платформа: Windows , Linux
Автор: Станислав Будинов

Enum E_CODEPAGE
    CP437
    CP866
    CP1251
    CP1252
    KOI8R
    UTF8
End Enum

Enum E_ENCODE_ERROR
    ENC_ENCODE_OK
    ENC_INVALID_CODEPAGE
    ENC_ERROR_ALLOCATE_MEMORY
    ENC_INVALID_INPUT_BUFFER
    ENC_WRONG_BYTES_SEQUENCE
End Enum

Dim Shared As Long iTable1251(255) = {_
&h0 , &h1 , &h2 , &h3 , &h4 , &h5 , &h6 , &h7 , &h8 , &h9 , &hA ,_
&hB , &hC , &hD , &hE , &hF , &h10 , &h11 , &h12 , &h13 , &h14 ,_
&h15 , &h16 , &h17 , &h18 , &h19 , &h1A , &h1B , &h1C , &h1D ,_
&h1E , &h1F , &h20 , &h21 , &h22 , &h23 , &h24 , &h25 , &h26 ,_
&h27 , &h28 , &h29 , &h2A , &h2B , &h2C , &h2D , &h2E , &h2F ,_
&h30 , &h31 , &h32 , &h33 , &h34 , &h35 , &h36 , &h37 , &h38 ,_
&h39 , &h3A , &h3B , &h3C , &h3D , &h3E , &h3F , &h40 , &h41 ,_
&h42 , &h43 , &h44 , &h45 , &h46 , &h47 , &h48 , &h49 , &h4A ,_
&h4B , &h4C , &h4D , &h4E , &h4F , &h50 , &h51 , &h52 , &h53 ,_
&h54 , &h55 , &h56 , &h57 , &h58 , &h59 , &h5A , &h5B , &h5C ,_
&h5D , &h5E , &h5F , &h60 , &h61 , &h62 , &h63 , &h64 , &h65 ,_
&h66 , &h67 , &h68 , &h69 , &h6A , &h6B , &h6C , &h6D , &h6E ,_
&h6F , &h70 , &h71 , &h72 , &h73 , &h74 , &h75 , &h76 , &h77 ,_
&h78 , &h79 , &h7A , &h7B , &h7C , &h7D , &h7E , &h7F , &h402 ,_
&h403 , &h201A , &h453 , &h201E , &h2026 , &h2020 , &h2021 ,_
&h20AC , &h2030 , &h409 , &h2039 , &h40A , &h40C , &h40B ,_
&h40F , &h452 , &h2018 , &h2019 , &h201C , &h201D , &h2022 ,_
&h2013 , &h2014 , &h20 , &h2122 , &h459 , &h203A , &h45A ,_
&h45C , &h45B , &h45F , &hA0 , &h40E , &h45E , &h408 , &hA4 ,_
&h490 , &hA6 , &hA7 , &h401 , &hA9 , &h404 , &hAB , &hAC ,_
&hAD , &hAE , &h407 , &hB0 , &hB1 , &h406 , &h456 , &h491 ,_
&hB5 , &hB6 , &hB7 , &h451 , &h2116 , &h454 , &hBB , &h458 ,_
&h405 , &h455 , &h457 , &h410 , &h411 , &h412 , &h413 , &h414 ,_
&h415 , &h416 , &h417 , &h418 , &h419 , &h41A , &h41B , &h41C ,_
&h41D , &h41E , &h41F , &h420 , &h421 , &h422 , &h423 , &h424 ,_
&h425 , &h426 , &h427 , &h428 , &h429 , &h42A , &h42B , &h42C ,_
&h42D , &h42E , &h42F , &h430 , &h431 , &h432 , &h433 , &h434 ,_
&h435 , &h436 , &h437 , &h438 , &h439 , &h43A , &h43B , &h43C ,_
&h43D , &h43E , &h43F , &h440 , &h441 , &h442 , &h443 , &h444 ,_
&h445 , &h446 , &h447 , &h448 , &h449 , &h44A , &h44B , &h44C ,_
&h44D , &h44E , &h44F}

Dim Shared As Long iTable866(255) = {_
&h0 , &h1 , &h2 , &h3 , &h4 , &h5 , &h6 , &h7 , &h8 , &h9 , &hA ,_
&hB , &hC , &hD , &hE , &hF , &h10 , &h11 , &h12 , &h13 , &h14 ,_
&h15 , &h16 , &h17 , &h18 , &h19 , &h1A , &h1B , &h1C , &h1D ,_
&h1E , &h1F , &h20 , &h21 , &h22 , &h23 , &h24 , &h25 , &h26 ,_
&h27 , &h28 , &h29 , &h2A , &h2B , &h2C , &h2D , &h2E , &h2F ,_
&h30 , &h31 , &h32 , &h33 , &h34 , &h35 , &h36 , &h37 , &h38 ,_
&h39 , &h3A , &h3B , &h3C , &h3D , &h3E , &h3F , &h40 , &h41 ,_
&h42 , &h43 , &h44 , &h45 , &h46 , &h47 , &h48 , &h49 , &h4A ,_
&h4B , &h4C , &h4D , &h4E , &h4F , &h50 , &h51 , &h52 , &h53 ,_
&h54 , &h55 , &h56 , &h57 , &h58 , &h59 , &h5A , &h5B , &h5C ,_
&h5D , &h5E , &h5F , &h60 , &h61 , &h62 , &h63 , &h64 , &h65 ,_
&h66 , &h67 , &h68 , &h69 , &h6A , &h6B , &h6C , &h6D , &h6E ,_
&h6F , &h70 , &h71 , &h72 , &h73 , &h74 , &h75 , &h76 , &h77 ,_
&h78 , &h79 , &h7A , &h7B , &h7C , &h7D , &h7E , &h7F , &h410 ,_
&h411 , &h412 , &h413 , &h414 , &h415 , &h416 , &h417 , &h418 ,_
&h419 , &h41A , &h41B , &h41C , &h41D , &h41E , &h41F , &h420 ,_
&h421 , &h422 , &h423 , &h424 , &h425 , &h426 , &h427 , &h428 ,_
&h429 , &h42A , &h42B , &h42C , &h42D , &h42E , &h42F , &h430 ,_
&h431 , &h432 , &h433 , &h434 , &h435 , &h436 , &h437 , &h438 ,_
&h439 , &h43A , &h43B , &h43C , &h43D , &h43E , &h43F , &h2591 ,_
&h2592 , &h2593 , &h2502 , &h2524 , &h2561 , &h2562 , &h2556 ,_
&h2555 , &h2563 , &h2551 , &h2557 , &h255D , &h255C , &h255B ,_
&h2510 , &h2514 , &h2534 , &h252C , &h251C , &h2500 , &h253C ,_
&h255E , &h255F , &h255A , &h2554 , &h2569 , &h2566 , &h2560 ,_
&h2550 , &h256C , &h2567 , &h2568 , &h2564 , &h2565 , &h2559 ,_
&h2558 , &h2552 , &h2553 , &h256B , &h256A , &h2518 , &h250C ,_
&h2588 , &h2584 , &h258C , &h2590 , &h2580 , &h440 , &h441 ,_
&h442 , &h443 , &h444 , &h445 , &h446 , &h447 , &h448 , &h449 ,_
&h44A , &h44B , &h44C , &h44D , &h44E , &h44F , &h401 , &h451 ,_
&h404 , &h454 , &h407 , &h457 , &h40E , &h45E , &hB0 , &h2219 ,_
&hB7 , &h221A , &h2116 , &hA4 , &h25A0 , &hA0}

Dim Shared As Long iTableKOI8R(255) = {_
&h0 , &h1 , &h2 , &h3 , &h4 , &h5 , &h6 , &h7 , &h8 , &h9 , &hA ,_
&hB , &hC , &hD , &hE , &hF , &h10 , &h11 , &h12 , &h13 , &h14 ,_
&h15 , &h16 , &h17 , &h18 , &h19 , &h1A , &h1B , &h1C , &h1D ,_
&h1E , &h1F , &h20 , &h21 , &h22 , &h23 , &h24 , &h25 , &h26 ,_
&h27 , &h28 , &h29 , &h2A , &h2B , &h2C , &h2D , &h2E , &h2F ,_
&h30 , &h31 , &h32 , &h33 , &h34 , &h35 , &h36 , &h37 , &h38 ,_
&h39 , &h3A , &h3B , &h3C , &h3D , &h3E , &h3F , &h40 , &h41 ,_
&h42 , &h43 , &h44 , &h45 , &h46 , &h47 , &h48 , &h49 , &h4A ,_
&h4B , &h4C , &h4D , &h4E , &h4F , &h50 , &h51 , &h52 , &h53 ,_
&h54 , &h55 , &h56 , &h57 , &h58 , &h59 , &h5A , &h5B , &h5C ,_
&h5D , &h5E , &h5F , &h60 , &h61 , &h62 , &h63 , &h64 , &h65 ,_
&h66 , &h67 , &h68 , &h69 , &h6A , &h6B , &h6C , &h6D , &h6E ,_
&h6F , &h70 , &h71 , &h72 , &h73 , &h74 , &h75 , &h76 , &h77 ,_
&h78 , &h79 , &h7A , &h7B , &h7C , &h7D , &h7E , &h7F , &h2500 ,_
&h2502 , &h250C , &h2510 , &h2514 , &h2518 , &h251C , &h2524 ,_
&h252C , &h2534 , &h253C , &h2580 , &h2584 , &h2588 , &h258C ,_
&h2590 , &h2591 , &h2592 , &h2593 , &h2320 , &h25A0 , &h2219 ,_
&h221A , &h2248 , &h2264 , &h2265 , &hA0 , &h2321 , &hB0 , &hB2 ,_
&hB7 , &hF7 , &h2550 , &h2551 , &h2552 , &h451 , &h2553 , &h2554 ,_
&h2555 , &h2556 , &h2557 , &h2558 , &h2559 , &h255A , &h255B ,_
&h255C , &h255D , &h255E , &h255F , &h2560 , &h2561 , &h401 ,_
&h2562 , &h2563 , &h2564 , &h2565 , &h2566 , &h2567 , &h2568 ,_
&h2569 , &h256A , &h256B , &h256C , &hA9 , &h44E , &h430 , &h431 ,_
&h446 , &h434 , &h435 , &h444 , &h433 , &h445 , &h438 , &h439 ,_
&h43A , &h43B , &h43C , &h43D , &h43E , &h43F , &h44F , &h440 ,_
&h441 , &h442 , &h443 , &h436 , &h432 , &h44C , &h44B , &h437 ,_
&h448 , &h44D , &h449 , &h447 , &h44A , &h42E , &h410 , &h411 ,_
&h426 , &h414 , &h415 , &h424 , &h413 , &h425 , &h418 , &h419 ,_
&h41A , &h41B , &h41C , &h41D , &h41E , &h41F , &h42F , &h420 ,_
&h421 , &h422 , &h423 , &h416 , &h412 , &h42C , &h42B , &h417 ,_
&h428 , &h42D , &h429 , &h427 , &h42A}

Dim Shared As Long iTable437(255) = {_
&h0 , &h1 , &h2 , &h3 , &h4 , &h5 , &h6 , &h7 , &h8 , &h9 , &hA ,_
&hB , &hC , &hD , &hE , &hF , &h10 , &h11 , &h12 , &h13 , &h14 ,_
&h15 , &h16 , &h17 , &h18 , &h19 , &h1A , &h1B , &h1C , &h1D ,_
&h1E , &h1F , &h20 , &h21 , &h22 , &h23 , &h24 , &h25 , &h26 ,_
&h27 , &h28 , &h29 , &h2A , &h2B , &h2C , &h2D , &h2E , &h2F ,_
&h30 , &h31 , &h32 , &h33 , &h34 , &h35 , &h36 , &h37 , &h38 ,_
&h39 , &h3A , &h3B , &h3C , &h3D , &h3E , &h3F , &h40 , &h41 ,_
&h42 , &h43 , &h44 , &h45 , &h46 , &h47 , &h48 , &h49 , &h4A ,_
&h4B , &h4C , &h4D , &h4E , &h4F , &h50 , &h51 , &h52 , &h53 ,_
&h54 , &h55 , &h56 , &h57 , &h58 , &h59 , &h5A , &h5B , &h5C ,_
&h5D , &h5E , &h5F , &h60 , &h61 , &h62 , &h63 , &h64 , &h65 ,_
&h66 , &h67 , &h68 , &h69 , &h6A , &h6B , &h6C , &h6D , &h6E ,_
&h6F , &h70 , &h71 , &h72 , &h73 , &h74 , &h75 , &h76 , &h77 ,_
&h78 , &h79 , &h7A , &h7B , &h7C , &h7D , &h7E , &h7F , &hC7 ,_
&hFC , &hE9 , &hE2 , &hE4 , &hE0 , &hE5 , &hE7 , &hEA , &hEB ,_
&hE8 , &hEF , &hEE , &hEC , &hC4 , &hC5 , &hC9 , &hE6 , &hC6 ,_
&hF4 , &hF6 , &hF2 , &hFB , &hF9 , &hFF , &hD6 , &hDC , &hA2 ,_
&hA3 , &hA5 , &h20A7 , &h192 , &hE1 , &hED , &hF3 , &hFA , &hF1 ,_
&hD1 , &hAA , &hBA , &hBF , &h2310 , &hAC , &hBD , &hBC , &hA1 ,_
&hAB , &hBB , &h2591 , &h2592 , &h2593 , &h2502 , &h2524 , &h2561 ,_
&h2562 , &h2556 , &h2555 , &h2563 , &h2551 , &h2557 , &h255D ,_
&h255C , &h255B , &h2510 , &h2514 , &h2534 , &h252C , &h251C ,_
&h2500 , &h253C , &h255E , &h255F , &h255A , &h2554 , &h2569 ,_
&h2566 , &h2560 , &h2550 , &h256C , &h2567 , &h2568 , &h2564 ,_
&h2565 , &h2559 , &h2558 , &h2552 , &h2553 , &h256B , &h256A ,_
&h2518 , &h250C , &h2588 , &h2584 , &h258C , &h2590 , &h2580 ,_
&h3B1 , &hDF , &h393 , &h3C0 , &h3A3 , &h3C3 , &hB5 , &h3C4 ,_
&h3A6 , &h398 , &h3A9 , &h3B4 , &h221E , &h3C6 , &h3B5 , &h2229 ,_
&h2261 , &hB1 , &h2265 , &h2264 , &h2320 , &h2321 , &hF7 , &h2248 ,_
&hB0 , &h2219 , &hB7 , &h221A , &h207F , &hB2 , &h25A0 , &hA0}

Dim Shared As Long iTable1252(255) = {_
&h0 , &h1 , &h2 , &h3 , &h4 , &h5 , &h6 , &h7 , &h8 , &h9 , &hA ,_
&hB , &hC , &hD , &hE , &hF , &h10 , &h11 , &h12 , &h13 , &h14 ,_
&h15 , &h16 , &h17 , &h18 , &h19 , &h1A , &h1B , &h1C , &h1D ,_
&h1E , &h1F , &h20 , &h21 , &h22 , &h23 , &h24 , &h25 , &h26 ,_
&h27 , &h28 , &h29 , &h2A , &h2B , &h2C , &h2D , &h2E , &h2F ,_
&h30 , &h31 , &h32 , &h33 , &h34 , &h35 , &h36 , &h37 , &h38 ,_
&h39 , &h3A , &h3B , &h3C , &h3D , &h3E , &h3F , &h40 , &h41 ,_
&h42 , &h43 , &h44 , &h45 , &h46 , &h47 , &h48 , &h49 , &h4A ,_
&h4B , &h4C , &h4D , &h4E , &h4F , &h50 , &h51 , &h52 , &h53 ,_
&h54 , &h55 , &h56 , &h57 , &h58 , &h59 , &h5A , &h5B , &h5C ,_
&h5D , &h5E , &h5F , &h60 , &h61 , &h62 , &h63 , &h64 , &h65 ,_
&h66 , &h67 , &h68 , &h69 , &h6A , &h6B , &h6C , &h6D , &h6E ,_
&h6F , &h70 , &h71 , &h72 , &h73 , &h74 , &h75 , &h76 , &h77 ,_
&h78 , &h79 , &h7A , &h7B , &h7C , &h7D , &h7E , &h7F , &h20AC ,_
&h20 , &h201A , &h192 , &h201E , &h2026 , &h2020 , &h2021 , &h2C6 ,_
&h2030 , &h160 , &h2039 , &h152 , &h20 , &h17D , &h20 , &h20 ,_
&h2018 , &h2019 , &h201C , &h201D , &h2022 , &h2013 , &h2014 ,_
&h2DC , &h2122 , &h161 , &h203A , &h153 , &h20 , &h17E , &h178 ,_
&hA0 , &hA1 , &hA2 , &hA3 , &hA4 , &hA5 , &hA6 , &hA7 , &hA8 ,_
&hA9 , &hAA , &hAB , &hAC , &hAD , &hAE , &hAF , &hB0 , &hB1 ,_
&hB2 , &hB3 , &hB4 , &hB5 , &hB6 , &hB7 , &hB8 , &hB9 , &hBA ,_
&hBB , &hBC , &hBD , &hBE , &hBF , &hC0 , &hC1 , &hC2 , &hC3 ,_
&hC4 , &hC5 , &hC6 , &hC7 , &hC8 , &hC9 , &hCA , &hCB , &hCC ,_
&hCD , &hCE , &hCF , &hD0 , &hD1 , &hD2 , &hD3 , &hD4 , &hD5 ,_
&hD6 , &hD7 , &hD8 , &hD9 , &hDA , &hDB , &hDC , &hDD , &hDE ,_
&hDF , &hE0 , &hE1 , &hE2 , &hE3 , &hE4 , &hE5 , &hE6 , &hE7 ,_
&hE8 , &hE9 , &hEA , &hEB , &hEC , &hED , &hEE , &hEF , &hF0 ,_
&hF1 , &hF2 , &hF3 , &hF4 , &hF5 , &hF6 , &hF7 , &hF8 , &hF9 ,_
&hFA , &hFB , &hFC , &hFD , &hFE , &hFF}

Function EncodeUTF8ToUnicode(sTextUtf8 As String , Byref iError As Integer) As Wstring Ptr
    Dim As Long iIndex
    Dim As Long shUnicodeSymbol
    Dim As Wstring Ptr ws = Callocate(Len(sTextUtf8)*4+4)
    If ws Then
        For i As Long = 0 To Len(sTextUtf8) -1
            If (sTextUtf8[i] And &hF8)  = &hf0 Andalso (sTextUtf8[i+1] And &hC0) = &h80 Andalso (sTextUtf8[i+2] And &hC0) = &h80 Andalso (sTextUtf8[i+3] And &hC0) = &h80 Then
                shUnicodeSymbol = ((sTextUtf8[i] And &h7) Shl 18) Or ((sTextUtf8[i+1] And &h3F) Shl 12) Or (((sTextUtf8[i+2] And &h3F) Shl 6) Or (sTextUtf8[i+3] And &h3F))
                #IFDEF __FB_WIN32__
                    Dim As Long iFirstSG = (((shUnicodeSymbol - &h10000) And &hFFC00) Shr 10) + &hD800
                    Dim As Long iSecondSG = ((shUnicodeSymbol - &h10000) And &h3FF)+&hDC00
                    (*ws)[iIndex] = iFirstSG
                    (*ws)[iIndex+1] = iSecondSG
                    iIndex+=2
                    i+=3
                    Continue For
                #ELSE
                    i+=3
                #ENDIF
            Elseif (sTextUtf8[i] And &hF0)  = &hE0 Andalso (sTextUtf8[i+1] And &hC0) = &h80 Andalso (sTextUtf8[i+2] And &hC0) = &h80 Then
                shUnicodeSymbol = ((sTextUtf8[i] And &hF) Shl 12) Or (((sTextUtf8[i+1] And &h3F) Shl 6) Or (sTextUtf8[i+2] And &h3F))
                i+=2
            Elseif (sTextUtf8[i] And &hC0)  = &hC0 Andalso (sTextUtf8[i+1] And &hC0) = &h80 Then
                shUnicodeSymbol = ((sTextUtf8[i] And &h1F) Shl 6) Or ((sTextUtf8[i+1] And &h3F))
                i+=1
            Elseif (sTextUtf8[i] And &h80)  = &h0 Then
                shUnicodeSymbol = sTextUtf8[i]
            Else
                shUnicodeSymbol = &hFFFD
            Endif
            (*ws)[iIndex] = shUnicodeSymbol
            iIndex+=1
        Next
        (*ws)[iIndex] = 0
    Else
        iError = ENC_ERROR_ALLOCATE_MEMORY
    Endif
    Return ws
End Function

Function EncodeUnicodeToUTF8(wsText As Wstring Ptr , Byref iError As Integer) As String
    If wsText Then
        Dim As Long iSimbol , iIndex , iLen = Len(*wsText)
        Dim As Byte Ptr psz = Allocate(iLen*4+1)
        If psz Then
            For i As Long = 0 To iLen-1
                iSimbol = wsText[i]
                If iSimbol < &h80 Then
                    psz[iIndex] = iSimbol
                    iIndex+=1
                Elseif iSimbol < &h800 Then
                    psz[iIndex] = &hC0 Or (iSimbol Shr 6)
                    psz[iIndex+1] = &h80 Or (iSimbol And &h3f)
                    iIndex+=2
                Elseif iSimbol < &h10000 Then
                    If iSimbol < &hD800 Orelse iSimbol > &hDFFF Then
                        psz[iIndex] = (&he0 Or (&hF And (iSimbol Shr 12)))
                        psz[iIndex+1] = &h80 Or (&h3f And (iSimbol Shr 6))
                        psz[iIndex+2] = &h80 Or (iSimbol And &h3F)
                        iIndex+=3
                    Else
                        If (iSimbol And &hD800) = &hD800 Then
                            If i < iLen-1 Then
                                Dim As Long iSecondSG = wsText[i+1]
                                If (iSecondSG And &hDC00) = &hDC00 Then
                                    iSimbol -= &hD800
                                    iSimbol Shl= 10
                                    iSimbol += &h10000
                                    iSecondSG -= &hDC00
                                    iSimbol += iSecondSG
                                    psz[iIndex] = (&hf0 Or (&h7 And (iSimbol Shr 18)))
                                    psz[iIndex+1] = (&h80 Or (&h3F And (iSimbol Shr 12)))
                                    psz[iIndex+2] = (&h80 Or (&h3f And (iSimbol Shr 6)))
                                    psz[iIndex+3] = &h80 Or (iSimbol And &h3F)
                                    iIndex+=4
                                    i+=1
                                    Continue For
                                Endif
                            Endif
                        Endif
                        psz[iIndex] = &hEF
                        psz[iIndex+1] = &hBF
                        psz[iIndex+2] = &hBD
                        iIndex+=3
                    Endif
                Elseif iSimbol > &hFFFF Andalso iSimbol < &h110000 Then
                    psz[iIndex] = (&hf0 Or (&h7 And (iSimbol Shr 18)))
                    psz[iIndex+1] = (&h80 Or (&h3F And (iSimbol Shr 12)))
                    psz[iIndex+2] = (&h80 Or (&h3f And (iSimbol Shr 6)))
                    psz[iIndex+3] = &h80 Or (iSimbol And &h3F)
                    iIndex+=4
                Else
                    psz[iIndex] = &hEF
                    psz[iIndex+1] = &hBF
                    psz[iIndex+2] = &hBD
                    iIndex+=3
                End If
            Next
            psz[iIndex] = 0
            Function = *Cast(Zstring Ptr, psz)
            Deallocate(psz)
        Else
            iError = ENC_ERROR_ALLOCATE_MEMORY
        Endif
    Else
        iError = ENC_INVALID_INPUT_BUFFER
    Endif
End Function

Function EncodeCharToUnicode(sText As String , iCodePage As Integer , Byref iError As Integer) As Wstring Ptr
    Dim As Long Ptr pTable
    Select Case iCodePage
        Case CP1251
            pTable = @iTable1251(0)
        Case CP866
            pTable = @iTable866(0)
        Case CP1252
            pTable = @iTable1252(0)
        Case CP437
            pTable = @iTable437(0)
        Case KOI8R
            pTable = @iTableKOI8R(0)
        Case UTF8
            Return EncodeUTF8ToUnicode(sText , iError)
        Case Else
            iError = ENC_INVALID_CODEPAGE
            Return 0
    End Select
    Dim As Wstring Ptr pWstr = Callocate((Len(sText)+1)*Sizeof(Wstring))
    If pWstr Then
        For i As Integer = 0 To Len(sText)-1
            pWstr[i] = pTable[sText[i]]
        Next
        Return pWstr
    Else
        iError = ENC_ERROR_ALLOCATE_MEMORY
    Endif
End Function

Function EncodeUnicodeToChar(pwsText As Wstring Ptr , iCodePage As Integer, Byref iError As Integer) As String
    Redim As Byte bAscii(10000)
    Dim As Long Ptr pTable
    If pwsText = 0 Then
        iError = ENC_INVALID_INPUT_BUFFER
        Return ""
    Endif
    Select Case iCodePage
        Case CP1251
            pTable = @iTable1251(0)
        Case CP866
            pTable = @iTable866(0)
        Case CP1252
            pTable = @iTable1252(0)
        Case CP437
            pTable = @iTable437(0)
        Case KOI8R
            pTable = @iTableKOI8R(0)
        Case UTF8
            Return EncodeUnicodeToUTF8(pwsText , iError)
        Case Else
            iError = ENC_INVALID_CODEPAGE
            Return ""
    End Select
    For i As Integer = 0 To 255
        If i > 127 Then
            If pTable[i] <> 32 Then
                bAscii(pTable[i]) = i
            Endif
        Else
            bAscii(pTable[i]) = i
        Endif
    Next
    Dim As Integer iLenBuf = Len(*pwsText)
    Dim As Zstring Ptr pszText = Callocate(iLenBuf+1)
    If pszText Then
        For i As Integer = 0 To iLenBuf-1
            Dim As Long iNum = pwsText[i]
            If iNum > Ubound(bAscii) Orelse bAscii(iNum) = 0 Then
                iError = ENC_WRONG_BYTES_SEQUENCE
                pszText[i] = &h3F
            Else
                pszText[i] = bAscii(iNum)
            Endif
        Next
        Dim As String sRet = *pszText
        Deallocate(pszText)
        Return sRet
    Else
        iError = ENC_ERROR_ALLOCATE_MEMORY
    Endif
End Function


' Пример преобразования из 1251 в 866
Dim As Integer iError
Dim As String s = "Русский текст"
Dim As Wstring Ptr p = EncodeCharToUnicode(s , CP1251 , iError)
? *p
s = EncodeUnicodeToChar(p , CP866 , iError)
? s
Deallocate(p)