Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Catalog · How the catalog works
Anything · Lazarus or Delphi
Random projectRandom project

AN62

BASE64 without +/= is AN62 ( AlphaNumeric62 )

View on GitHub

Member rating

No ratings yet.

Sign in to rate this project.

README

AN62(AlphaNumeric62)

BASE64 Encode에는 +/= 기본형 또는 -_= URL형이 있다.
여기서, 항상 특수문자가 문제가 되어. 0~9, A~Z, a~z만으로 이루어진 AlphaNumeric62을 만들어 보았다.

원리

Unicode값 UTF-8 Byte단위 값의 범위 비고
0x000000~0x00007F 0xxx xxxx 0x00~0x7F ASCII
0x000080~0x0007FF 110x xxxx 10xx xxxx 0xC0~0xDF, 0x80~0xBF 유럽
0x000800~0x00FFFF 1110 xxxx 10xx xxxx 10xx xxxx 0xE0~0xEF, 0x80~0xBF 한글등
0x010000~0x10FFFF 1111 0zzz 10zz xxxx 10xx xxxx 10xx xxxx 0xF0~0xF4, 0x80~0xBF

그래서, 0x00~0x7F, 0x80~0xBF, 0xC0~0xDF, 0xE0~0xEF, 0xF0~0xF4 즉, 0x00~0xF4(245가지).

2453 < 624 (14,706,125 < 14,776,336) 이다. (즉, 245가지 3덩어리를 62가지 4덩어리로 표현가능하다.)

BASE64 Encode의 원리도 2563 = 644 즉, 2(8*3) = 2(6*4) 로 3Byte을 6bit씩 4덩어리로 표현한 것이다.

장단점

장점

  • 특수문자(기호)가 없어 어떠한 환경에서 값으로 사용할 수 있음.

단점

  • BASE64는 bit연산으로 구현하고, AN62는 산술연산으로 다소 속도는 느림
  • Binary가 안 된다. ( 대안 : Base62 를 이용한다. )

본 자료는 gitbook 으로 볼 수 있습니다.

지원언어

아래 언어로 소스코드를 올립니다.

Java 예

java
public static void main(String[] args) {
    try {
        String src0 = "http://test.com:8080/an62.do?name=가나다 ㄱㄴ※\n可" ;
        System.out.println("src0["+src0.length()+"]:" + src0) ;
        String an62__tmp0 = AN62.encode(src0) ;
        System.out.println("an62__tmp0:" + an62__tmp0) ;
        String an62__out0 = AN62.decode(an62__tmp0) ;
        System.out.println("an62__out0:" + an62__out0) ;
        String base64_tmp = java.util.Base64.getEncoder().encodeToString(src0.getBytes("utf8")) ;
        System.out.println("base64_tmp:" + base64_tmp) ;
        String base64_out = new String(java.util.Base64.getDecoder().decode(base64_tmp), "utf8") ;
        System.out.println("base64_out:" + base64_out) ;

        // [ 코끼리 = Unicode : 01F418, UTF16 : D83D DC18, UTF8 : F0 9F 90 98 ]
        String src1 = "http://test.com:8080/an62.do?name=가나다 ㄱㄴ※\n可🐘" ;
        System.out.println("src1["+src1.length()+"]:" + src1) ;		// String.length()은 문자갯수가 아니라, UTF16의 길이다. 
        String tmp1 = AN62.encode(src1) ;
        System.out.println("tmp1:" + tmp1) ;
        String out1 = AN62.decode(tmp1) ;
        System.out.println("out1:" + out1) ;

        if(src1.equals(out1))	System.out.println("src1.equals(out1)") ;

    } catch(Exception e) {
        e.printStackTrace();
    }
}

pascal
src0[43]:http://test.com:8080/an62.do?name=가나다 ㄱㄴ※
???
an62__tmp0:QJPMSGcDBxKqT59pP30lEfGUE9WZOXhdCdieS1KqOXeRFbUNWTlJcWWwfKzvXQYGXQk6WQfhvp39
an62__out0:http://test.com:8080/an62.do?name=가나다 ㄱㄴ※
???
base64_tmp:aHR0cDovL3Rlc3QuY29tOjgwODAvYW42Mi5kbz9uYW1lPeqwgOuCmOuLpCDjhLHjhLTigLsK5Y+v
base64_out:http://test.com:8080/an62.do?name=가나다 ㄱㄴ※
???
src1[45]:http://test.com:8080/an62.do?name=가나다 ㄱㄴ※
???????
tmp1:QJPMSGcDBxKqT59pP30lEfGUE9WZOXhdCdieS1KqOXeRFbUNWTlJcWWwfKzvXQYGXQk6WQfhvp39ybpT2S
out1:http://test.com:8080/an62.do?name=가나다 ㄱㄴ※
???????
src1.equals(out1)

C# 예

c#
static void Main(string[] args)
{
    string src0 = "http://test.com:8080/an62.do?name=가나다 ㄱㄴ※\n可";
    Console.WriteLine("src0[" + src0.Length + "]:" + src0);
    string an62__tmp0 = AN62.encode(src0);
    Console.WriteLine("an62__tmp0:" + an62__tmp0);
    string an62__out0 = AN62.decode(an62__tmp0);
    Console.WriteLine("an62__out0:" + an62__out0);
    string base64_tmp = Convert.ToBase64String(Encoding.UTF8.GetBytes(src0));
    Console.WriteLine("base64_tmp:" + base64_tmp);
    string base64_out = Encoding.UTF8.GetString(Convert.FromBase64String(base64_tmp));
    Console.WriteLine("base64_out:" + base64_out);

    // [ 코끼리 = Unicode : 01F418, UTF16 : D83D DC18, UTF8 : F0 9F 90 98 ]
    string src1 = "http://test.com:8080/an62.do?name=가나다 ㄱㄴ※\n可🐘";
    Console.WriteLine("src1[" + src1.Length + "]:" + src1);
    string tmp1 = AN62.encode(src1);
    Console.WriteLine("tmp1:" + tmp1);
    string out1 = AN62.decode(tmp1);
    Console.WriteLine("out1:" + out1);

    if (src1.Equals(out1)) Console.WriteLine("src1.Equals(out1)");
}

pascal
src0[43]:http://test.com:8080/an62.do?name=가나다 ㄱㄴ※
???
an62__tmp0:QJPMSGcDBxKqT59pP30lEfGUE9WZOXhdCdieS1KqOXeRFbUNWTlJcWWwfKzvXQYGXQk6WQfhvp39
an62__out0:http://test.com:8080/an62.do?name=가나다 ㄱㄴ※
???
base64_tmp:aHR0cDovL3Rlc3QuY29tOjgwODAvYW42Mi5kbz9uYW1lPeqwgOuCmOuLpCDjhLHjhLTigLsK5Y+v
base64_out:http://test.com:8080/an62.do?name=가나다 ㄱㄴ※
???
src1[45]:http://test.com:8080/an62.do?name=가나다 ㄱㄴ※
?????
tmp1:QJPMSGcDBxKqT59pP30lEfGUE9WZOXhdCdieS1KqOXeRFbUNWTlJcWWwfKzvXQYGXQk6WQfhvp39ybpT2S
out1:http://test.com:8080/an62.do?name=가나다 ㄱㄴ※
?????
src1.Equals(out1)

JavaScript 예

javascript
function print(msg) {
    if(typeof document !== 'undefined' && typeof msg === 'string')
        document.write(msg.replace(/\n/g,'<br/>') + '<br/>') ;
    console.log(msg) ;
}

try {
    var src0 = "http://test.com:8080/an62.do?name=가나다 ㄱㄴ※\n可" ;
    print('src0['+src0.length+']:' + src0) ;
    var tmp0 = AN62.encode(src0) ;
    print("tmp0:" + tmp0) ;
    var out0 = AN62.decode(tmp0) ;
    print("out0:" + out0) ;

    // [ 코끼리 = Unicode : 01F418, UTF16 : D83D DC18, UTF8 : F0 9F 90 98 ]
    var src1 = "http://test.com:8080/an62.do?name=가나다 ㄱㄴ※\n可🐘" ;
    print('src1['+src1.length+']:' + src1) ;
    var tmp1 = AN62.encode(src1) ;
    print("tmp1:" + tmp1) ;
    var out1 = AN62.decode(tmp1) ;
    print("out1:" + out1) ;

    if(src1 === out1)   print("src1 === out1") ;
} catch(e) {
    print(e) ;
}

pascal
src0[43]:http://test.com:8080/an62.do?name=가나다 ㄱㄴ※
???
tmp0:QJPMSGcDBxKqT59pP30lEfGUE9WZOXhdCdieS1KqOXeRFbUNWTlJcWWwfKzvXQYGXQk6WQfhvp39
out0:http://test.com:8080/an62.do?name=가나다 ㄱㄴ※
???
src1[45]:http://test.com:8080/an62.do?name=가나다 ㄱㄴ※
???????
tmp1:QJPMSGcDBxKqT59pP30lEfGUE9WZOXhdCdieS1KqOXeRFbUNWTlJcWWwfKzvXQYGXQk6WQfhvp39ybpT2S
out1:http://test.com:8080/an62.do?name=가나다 ㄱㄴ※
???????
src1 === out1

Python 예

python
if __name__ == '__main__':
    src0 = 'http://test.com:8080/an62.do?name=가나다 ㄱㄴ※\n可'
    print('src0['+str(len(src0))+']:' + src0)
    an62__tmp0 = AN62.encode(src0)
    print('an62__tmp0:' + an62__tmp0)
    an62__out0 = AN62.decode(an62__tmp0)
    print('an62__out0:' + an62__out0)
    base64_tmp = base64.b64encode(src0.encode('utf8')).decode('utf8')
    print('base64_tmp:' + base64_tmp)
    base64_out = base64.b64decode(base64_tmp.encode('utf8')).decode('utf8')
    print('base64_out:' + base64_out)

    # [ 코끼리 = Unicode : 01F418, UTF16 : D83D DC18, UTF8 : F0 9F 90 98 ]
    src1 = "http://test.com:8080/an62.do?name=가나다 ㄱㄴ※\n可🐘"
    print("src1:["+str(len(src1))+"]" + src1)
    tmp1 = AN62.encode(src1)
    print("tmp1:" + tmp1)
    out1 = AN62.decode(tmp1)
    print("out1:" + out1)

    if(src1 == out1) :
        print("src1 == out1")

pascal
src0[43]:http://test.com:8080/an62.do?name=가나다 ㄱㄴ※
???
an62__tmp0:QJPMSGcDBxKqT59pP30lEfGUE9WZOXhdCdieS1KqOXeRFbUNWTlJcWWwfKzvXQYGXQk6WQfhvp39
an62__out0:http://test.com:8080/an62.do?name=가나다 ㄱㄴ※
???
base64_tmp:aHR0cDovL3Rlc3QuY29tOjgwODAvYW42Mi5kbz9uYW1lPeqwgOuCmOuLpCDjhLHjhLTigLsK5Y+v
base64_out:http://test.com:8080/an62.do?name=가나다 ㄱㄴ※
???
src1:[44]http://test.com:8080/an62.do?name=가나다 ㄱㄴ※
???????
tmp1:QJPMSGcDBxKqT59pP30lEfGUE9WZOXhdCdieS1KqOXeRFbUNWTlJcWWwfKzvXQYGXQk6WQfhvp39ybpT2S
out1:http://test.com:8080/an62.do?name=가나다 ㄱㄴ※
???????
src1 == out1

CPP(Windows)예

cpp
// charset : EUC-KR(on Windows)
#include <cstdio>
#include <clocale>
#include "an62.h"
#include "zstring.h"

int main(int argc, char *argv[])
{
    std::string locale(std::setlocale(LC_ALL, "")) ;
    printf("locale : [%s]\n", locale.c_str()) ;
    printf("sizeof(wchar_t) : %zd\n", sizeof(wchar_t)) ;

    {
        std::wstring src0 = L"http://test.com:8080/an62.do?name=가나다 ㄱㄴ※\n可" ;
        printf("src0[%zd]:%s\n", src0.length(), wstring2system(src0).c_str()) ;
        std::string tmp0 = an62::encode(src0) ;
        printf("tmp0:%s\n", tmp0.c_str()) ;
        std::wstring out0 = an62::decode(tmp0) ;
        printf("out0:%s\n", wstring2system(out0).c_str()) ;
        printf("src0.compare(out0) : %d\n", src0.compare(out0)) ;
    }
    {
        std::string src0 = "http://test.com:8080/an62.do?name=가나다 ㄱㄴ※\n可" ;
        printf("src0[%zd]:%s\n", src0.length(), src0.c_str()) ;
        std::string tmp0 = an62::encode(system2wstring(src0)) ;
        printf("tmp0:%s\n", tmp0.c_str()) ;
        std::string out0 = wstring2ansi(an62::decode(tmp0)) ;
        printf("out0:%s\n", out0.c_str()) ;
        printf("src0.compare(out0) : %d\n", src0.compare(out0)) ;
    }
    
    {
        // [ 코끼리 = Unicode : 01F418, UTF16 : D83D DC18, UTF8 : F0 9F 90 98 ]
        std::wstring src1 = L"http://test.com:8080/an62.do?name=가나다 ㄱㄴ※\n可" ;
        if(sizeof(wchar_t) == 2) {	// Windows
            src1.push_back(0xD83D) ;
            src1.push_back(0xDC18) ;
        }
        else {	// Linux
            src1.push_back((wchar_t)0x01F418) ;
        }
        printf("src1[%zd]:%s\n", src1.length(), wstring2system(src1).c_str()) ;
        std::string tmp1 = an62::encode(src1) ;
        printf("tmp1:%s\n", tmp1.c_str()) ;
        std::wstring out1 = an62::decode(tmp1) ;
        printf("out1:%s\n", wstring2system(out1).c_str()) ;
        printf("src1.compare(out1) : %d\n", src1.compare(out1)) ;
    }

    {
        // [ 코끼리 = Unicode : 01F418, UTF16 : D83D DC18, UTF8 : F0 9F 90 98 ]
        std::string utf8 = system2utf8("http://test.com:8080/an62.do?name=가나다 ㄱㄴ※\n可") ;
        utf8.push_back((char)0xF0) ;
        utf8.push_back((char)0x9F) ;
        utf8.push_back((char)0x90) ;
        utf8.push_back((char)0x98) ;
        std::string tmp1 = an62::encode(utf8_to_wstring(utf8)) ;
        printf("utf8[%zd]:%s\n", utf8.length(), utf8_to_system(utf8).c_str()) ;
        printf("tmp1:%s\n", tmp1.c_str()) ;
        std::string out8 = wstring2utf8(an62::decode(tmp1)) ;
        printf("out8[%zd]:%s\n", out8.length(), utf8_to_system(out8).c_str()) ;
        printf("utf8.compare(out8) : %d\n", utf8.compare(out8)) ;
    }

    return 0 ;
}

pascal
locale : [Korean_Korea.949]
sizeof(wchar_t) : 2
src0[43]:http://test.com:8080/an62.do?name=가나다 ㄱㄴ※
???
tmp0:QJPMSGcDBxKqT59pP30lEfGUE9WZOXhdCdieS1KqOXeRFbUNWTlJcWWwfKzvXQYGXQk6WQfhvp39
out0:http://test.com:8080/an62.do?name=가나다 ㄱㄴ※
???
src0.compare(out0) : 0
src0[50]:http://test.com:8080/an62.do?name=가나다 ㄱㄴ※
???
tmp0:QJPMSGcDBxKqT59pP30lEfGUE9WZOXhdCdieS1KqOXeRFbUNWTlJcWWwfKzvXQYGXQk6WQfhvp39
out0:http://test.com:8080/an62.do?name=가나다 ㄱㄴ※
???
src0.compare(out0) : 0
src1[45]:http://test.com:8080/an62.do?name=가나다 ㄱㄴ※
?????
tmp1:QJPMSGcDBxKqT59pP30lEfGUE9WZOXhdCdieS1KqOXeRFbUNWTlJcWWwfKzvXQYGXQk6WQfhvp39ybpT2S
out1:http://test.com:8080/an62.do?name=가나다 ㄱㄴ※
?????
src1.compare(out1) : 0
utf8[61]:http://test.com:8080/an62.do?name=가나다 ㄱㄴ※
?????
tmp1:QJPMSGcDBxKqT59pP30lEfGUE9WZOXhdCdieS1KqOXeRFbUNWTlJcWWwfKzvXQYGXQk6WQfhvp39ybpT2S
out8[61]:http://test.com:8080/an62.do?name=가나다 ㄱㄴ※
?????
utf8.compare(out8) : 0

CPP(Linux) 예

cpp
// charset : UTF-8(on Linux)
#include "an62.h"

#include <clocale>
#include <cstdio>

#include "zstring.h"

int main(int argc, char *argv[])
{
    std::string locale(std::setlocale(LC_ALL, "")) ;
    printf("locale : [%s]\n", locale.c_str()) ;
    printf("sizeof(wchar_t) : %zd\n", sizeof(wchar_t)) ;
    
    {
        std::wstring src0 = L"http://test.com:8080/an62.do?name=가나다 ㄱㄴ※\n可" ;
        printf("src0[%zd]:%s\n", src0.length(), wstring2system(src0).c_str()) ;
        std::string tmp0 = an62::encode(src0) ;
        printf("tmp0:%s\n", tmp0.c_str()) ;
        std::wstring out0 = an62::decode(tmp0) ;
        printf("out0:%s\n", wstring2system(out0).c_str()) ;
        printf("src0.compare(out0) : %d\n", src0.compare(out0)) ;
    }
    {
        std::string src0 = "http://test.com:8080/an62.do?name=가나다 ㄱㄴ※\n可" ;
        printf("src0[%zd]:%s\n", src0.length(), src0.c_str()) ;
        std::string tmp0 = an62::encode(system2wstring(src0)) ;
        printf("tmp0:%s\n", tmp0.c_str()) ;
        std::string out0 = wstring2system(an62::decode(tmp0)) ;
        printf("out0:%s\n", out0.c_str()) ;
        printf("src0.compare(out0) : %d\n", src0.compare(out0)) ;
    }
    
    {
        // [ 코끼리 = Unicode : 01F418, UTF16 : D83D DC18, UTF8 : F0 9F 90 98 ]
        std::wstring src1 = L"http://test.com:8080/an62.do?name=가나다 ㄱㄴ※\n可" ;
        if(sizeof(wchar_t) == 2) {	// Windows
            src1.push_back(0xD83D) ;
            src1.push_back(0xDC18) ;
        }
        else {	// Linux
            src1.push_back(0x01F418) ;
        }
        printf("src1[%zd]:%s\n", src1.length(), wstring2system(src1).c_str()) ;
        std::string tmp1 = an62::encode(src1) ;
        printf("tmp1:%s\n", tmp1.c_str()) ;
        std::wstring out1 = an62::decode(tmp1) ;
        printf("out1:%s\n", wstring2system(out1).c_str()) ;
        printf("src1.compare(out1) : %d\n", src1.compare(out1)) ;
    }

    {
        // [ 코끼리 = Unicode : 01F418, UTF16 : D83D DC18, UTF8 : F0 9F 90 98 ]
        std::string utf8 = system2utf8("http://test.com:8080/an62.do?name=가나다 ㄱㄴ※\n可🐘") ;
        std::string tmp1 = an62::encode(utf8_to_wstring(utf8)) ;
        printf("utf8[%zd]:%s\n", utf8.length(), utf8_to_system(utf8).c_str()) ;
        printf("tmp1:%s\n", tmp1.c_str()) ;
        std::string out8 = wstring2utf8(an62::decode(tmp1)) ;
        printf("out8[%zd]:%s\n", out8.length(), utf8_to_system(out8).c_str()) ;
        printf("utf8.compare(out8) : %d\n", utf8.compare(out8)) ;
    }

    return 0 ;
}

pascal
locale : [ko_KR.UTF-8]
sizeof(wchar_t) : 4
src0[43]:http://test.com:8080/an62.do?name=가나다 ㄱㄴ※
???
tmp0:QJPMSGcDBxKqT59pP30lEfGUE9WZOXhdCdieS1KqOXeRFbUNWTlJcWWwfKzvXQYGXQk6WQfhvp39
out0:http://test.com:8080/an62.do?name=가나다 ㄱㄴ※
???
src0.compare(out0) : 0
src0[57]:http://test.com:8080/an62.do?name=가나다 ㄱㄴ※
???
tmp0:QJPMSGcDBxKqT59pP30lEfGUE9WZOXhdCdieS1KqOXeRFbUNWTlJcWWwfKzvXQYGXQk6WQfhvp39
out0:http://test.com:8080/an62.do?name=가나다 ㄱㄴ※
???
src0.compare(out0) : 0
src1[44]:http://test.com:8080/an62.do?name=가나다 ㄱㄴ※
???????
tmp1:QJPMSGcDBxKqT59pP30lEfGUE9WZOXhdCdieS1KqOXeRFbUNWTlJcWWwfKzvXQYGXQk6WQfhvp39ybpT2S
out1:http://test.com:8080/an62.do?name=가나다 ㄱㄴ※
???????
src1.compare(out1) : 0
utf8[61]:http://test.com:8080/an62.do?name=가나다 ㄱㄴ※
???????
tmp1:QJPMSGcDBxKqT59pP30lEfGUE9WZOXhdCdieS1KqOXeRFbUNWTlJcWWwfKzvXQYGXQk6WQfhvp39ybpT2S
out8[61]:http://test.com:8080/an62.do?name=가나다 ㄱㄴ※
???????
utf8.compare(out8) : 0

Delphi 예

pascal
{ charset : EUC-KR }
program AN62Test;

{$APPTYPE CONSOLE}

uses
  SysUtils,
  AN62 in 'AN62.pas',
  ZString in 'ZString.pas';

var
  wsrc, wout : WideString ;
  wtmp, tmp0, tmp8 : string ;
  src0, out0 : AnsiString ;
  utf8, out8 : UTF8String ;
begin
  WriteLn('----------AnsiString------------') ;
  src0 := 'http://test.com:8080/an62.do?name=가나다 ㄱㄴ※'#10'可' ;
  WriteLn('src0[', Length(src0), ']:', src0) ;

  tmp0 := TAN62.Encode(AnsiToUtf8(src0)) ;
  WriteLn('tmp0[', Length(tmp0), ']:', tmp0) ;

  out0 := Utf8ToAnsi(TAN62.Decode(tmp0)) ;
  WriteLn('out0[', Length(out0), ']:', out0) ;

  WriteLn('src0 = out0 : ', (src0 = out0)) ;

  WriteLn('----------UTF8String----------') ;
  utf8 := AnsiToUtf8('http://test.com:8080/an62.do?name=가나다 ㄱㄴ※'#10'可') ;
  WriteLn('utf8[', Length(utf8), ']:', Utf8ToAnsi(utf8)) ;

  tmp8 := TAN62.Encode(utf8) ;
  WriteLn('tmp8[', Length(tmp8), ']:', tmp8) ;

  out8 := TAN62.Decode(tmp8) ;
  WriteLn('out8[', Length(out8), ']:', Utf8ToAnsi(out8)) ;

  WriteLn('utf8 = out8 : ', (utf8 = out8)) ;

  WriteLn('----------WideString------------') ;
  // [ 코끼리 = Unicode : 01F418, UTF16 : D83D DC18, UTF8 : F0 9F 90 98 ]
  wsrc := 'http://test.com:8080/an62.do?name=가나다 ㄱㄴ※'#10'可' ;
  wsrc := wsrc + #55357 ; // 0xD83D #55357
  wsrc := wsrc + #56344 ; // 0xDC18 #56344
  WriteLn('wsrc[', Length(wsrc), ']:', wsrc) ;

  wtmp := TAN62.Encode(wsrc) ;
  WriteLn('wtmp[', Length(wtmp), ']:', wtmp) ;

  //wout := UTF8Decode(TAN62.Decode(wtmp)) ;  // 코끼리 때문에 안됨.
  wout := TZString.SafeUTF8Decode(TAN62.Decode(wtmp)) ;
  WriteLn('wout[', Length(wout), ']:', wout) ;

  WriteLn('wsrc = wout : ', (wsrc = wout)) ;

  WriteLn('----------UTF8String----------') ;
  // [ 코끼리 = Unicode : 01F418, UTF16 : D83D DC18, UTF8 : F0 9F 90 98 ]
  utf8 := UTF8Encode('http://test.com:8080/an62.do?name=가나다 ㄱㄴ※'#10'可') ;
  utf8 := utf8 + #240 ; // 0xF0 #240
  utf8 := utf8 + #159 ; // 0x9F #159
  utf8 := utf8 + #144 ; // 0x90 #144
  utf8 := utf8 + #152 ; // 0x98 #152
  //WriteLn('utf8[', Length(utf8), ']:', UTF8Decode(utf8)) ; // 코끼리 때문에 안됨.
  WriteLn('utf8[', Length(utf8), ']:', TZString.SafeUTF8Decode(utf8)) ;

  tmp8 := TAN62.Encode(utf8) ;
  WriteLn('tmp8[', Length(tmp8), ']:', tmp8) ;

  out8 := TAN62.Decode(tmp8) ;
  //WriteLn('utf8[', Length(out8)), ']:', UTF8Decode(out8)) ; // 코끼리 때문에 안됨.
  WriteLn('utf8[', Length(out8), ']:', TZString.SafeUTF8Decode(out8)) ;

  WriteLn('utf8 = out8 : ', (utf8 = out8)) ;

  ReadLn;
end.

pascal
----------EUC-KR------------
src0[50]:http://test.com:8080/an62.do?name=가나다 ㄱㄴ※
???
tmp0:QJPMSGcDBxKqT59pP30lEfGUE9WZOXhdCdieS1KqOXeRFbUNWTlJcWWwfKzvXQYGXQk6WQfhvp39
out0[50]:http://test.com:8080/an62.do?name=가나다 ㄱㄴ※
???
src0 = out0
----------UTF-8----------
utf8[57]:http://test.com:8080/an62.do?name=가나다 ㄱㄴ※
???
tmp8:QJPMSGcDBxKqT59pP30lEfGUE9WZOXhdCdieS1KqOXeRFbUNWTlJcWWwfKzvXQYGXQk6WQfhvp39
out8[57]:http://test.com:8080/an62.do?name=가나다 ㄱㄴ※
???
utf8 = out8
----------WideString------------
wsrc[45]:http://test.com:8080/an62.do?name=가나다 ㄱㄴ※
?????
wtmp:QJPMSGcDBxKqT59pP30lEfGUE9WZOXhdCdieS1KqOXeRFbUNWTlJcWWwfKzvXQYGXQk6WQfhvp39ybpT2S
wout[45]:http://test.com:8080/an62.do?name=가나다 ㄱㄴ※
?????
wsrc = wout
----------UTF8String----------
utf8[61]:http://test.com:8080/an62.do?name=가나다 ㄱㄴ※
?????
tmp8:QJPMSGcDBxKqT59pP30lEfGUE9WZOXhdCdieS1KqOXeRFbUNWTlJcWWwfKzvXQYGXQk6WQfhvp39ybpT2S
utf8[61]:http://test.com:8080/an62.do?name=가나다 ㄱㄴ※
?????
utf8 = out8

Free Pascal 예

pascal
{ charset : UTF-8 }
program AN62Test;

{$APPTYPE CONSOLE}

uses
  SysUtils, AN62, ZString;

var
  wsrc, wout : WideString ;
  wtmp, tmp8, tmp0 : string ;
  src0, out0 : AnsiString ;
  utf8, out8 : UTF8String ;

begin
  WriteLn('----------UTF8String----------') ;
  utf8 := AnsiToUtf8(UTf8ToAnsi('http://test.com:8080/an62.do?name=가나다 ㄱㄴ※'#10'可')) ;
  WriteLn('utf8[', Length(utf8), ']:', Utf8ToAnsi(utf8)) ;

  tmp8 := TAN62.Encode(utf8) ;
  WriteLn('tmp8[', Length(tmp8), ']:', tmp8) ;

  out8 := TAN62.Decode(tmp8) ;
  WriteLn('out8[', Length(out8), ']:', Utf8ToAnsi(out8)) ;

  WriteLn('utf8 = out8 : ', (utf8 = out8)) ;

  WriteLn('----------AnsiString------------') ;
  src0 := Utf8ToAnsi('http://test.com:8080/an62.do?name=가나다 ㄱㄴ※'#10'可') ;
  WriteLn('src0[', Length(src0), ']:', src0) ;

  tmp0 := TAN62.Encode(AnsiToUtf8(src0)) ;
  WriteLn('tmp0[', Length(tmp0), ']:', tmp0) ;

  out0 := Utf8ToAnsi(TAN62.Decode(tmp0)) ;
  WriteLn('out0[', Length(out0), ']:', out0) ;

  WriteLn('src0 = out0 : ', (src0 = out0)) ;

  WriteLn('----------WideString----------') ;
  wsrc := UTF8Decode('http://test.com:8080/an62.do?name=가나다 ㄱㄴ※'#10'可') ;
  WriteLn('wsrc[', Length(wsrc), ']:', wsrc) ;

  wtmp := TAN62.Encode(wsrc) ;
  WriteLn('wtmp[', Length(wtmp), ']:', wtmp) ;

  wout := UTF8Decode(TAN62.Decode(wtmp)) ;
  WriteLn('wout[', Length(wout), ']:', wout) ;

  WriteLn('wsrc = wout : ', (wsrc = wout)) ;

  Writeln('----------UTF8String----------') ;
  // [ 코끼리 = Unicode : 01F418, UTF16 : D83D DC18, UTF8 : F0 9F 90 98 ]
  utf8 := UTF8Encode(UTF8Decode('http://test.com:8080/an62.do?name=가나다 ㄱㄴ※'#10'可🐘')) ;
  WriteLn('utf8[', Length(utf8), ']:', UTF8Decode(utf8)) ;

  tmp8 := TAN62.Encode(utf8) ;
  WriteLn('tmp8[', Length(tmp8), ']:', tmp8) ;

  out8 := TAN62.Decode(tmp8) ;
  WriteLn('out8[', Length(out8), ']:', UTF8Decode(out8)) ;

  WriteLn('utf8 = out8 : ', (utf8 = out8)) ;

  WriteLn('----------WideString------------') ;
  // [ 코끼리 = Unicode : 01F418, UTF16 : D83D DC18, UTF8 : F0 9F 90 98 ]
  wsrc := UTF8Decode('http://test.com:8080/an62.do?name=가나다 ㄱㄴ※'#10'可🐘') ;
  WriteLn('wsrc[', Length(wsrc), ']:', wsrc) ;

  wtmp := TAN62.Encode(wsrc) ;
  WriteLn('wtmp[', Length(wtmp), ']:', wtmp) ;

  wout := UTF8Decode(TAN62.Decode(wtmp)) ;
  WriteLn('wout[', Length(wout), ']:', wout) ;

  WriteLn('wsrc = wout : ', (wsrc = wout)) ;

  ReadLn ;
end.

pascal
----------UTF8String----------
utf8[57]:http://test.com:8080/an62.do?name=가나다 ㄱㄴ※
???
tmp8[76]:QJPMSGcDBxKqT59pP30lEfGUE9WZOXhdCdieS1KqOXeRFbUNWTlJcWWwfKzvXQYGXQk6WQfhvp39
out8[57]:http://test.com:8080/an62.do?name=가나다 ㄱㄴ※
???
utf8 = out8 : TRUE
----------AnsiString------------
src0[50]:http://test.com:8080/an62.do?name=가나다 ㄱㄴ※
???
tmp0[76]:QJPMSGcDBxKqT59pP30lEfGUE9WZOXhdCdieS1KqOXeRFbUNWTlJcWWwfKzvXQYGXQk6WQfhvp39
out0[50]:http://test.com:8080/an62.do?name=가나다 ㄱㄴ※
???
src0 = out0 : TRUE
----------WideString----------
wsrc[43]:http://test.com:8080/an62.do?name=가나다 ㄱㄴ※
???
wtmp[76]:QJPMSGcDBxKqT59pP30lEfGUE9WZOXhdCdieS1KqOXeRFbUNWTlJcWWwfKzvXQYGXQk6WQfhvp39
wout[43]:http://test.com:8080/an62.do?name=가나다 ㄱㄴ※
???
wsrc = wout : TRUE
----------UTF8String----------
utf8[61]:http://test.com:8080/an62.do?name=가나다 ㄱㄴ※
?????
tmp8[82]:QJPMSGcDBxKqT59pP30lEfGUE9WZOXhdCdieS1KqOXeRFbUNWTlJcWWwfKzvXQYGXQk6WQfhvp39ybpT2S
out8[61]:http://test.com:8080/an62.do?name=가나다 ㄱㄴ※
?????
utf8 = out8 : TRUE
----------WideString------------
wsrc[45]:http://test.com:8080/an62.do?name=가나다 ㄱㄴ※
?????
wtmp[82]:QJPMSGcDBxKqT59pP30lEfGUE9WZOXhdCdieS1KqOXeRFbUNWTlJcWWwfKzvXQYGXQk6WQfhvp39ybpT2S
wout[45]:http://test.com:8080/an62.do?name=가나다 ㄱㄴ※
?????
wsrc = wout : TRUE

PHP 예

php
<?php require_once 'an62.php' ?>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
</head>
<body>
<code>
<?php
try {
    $src0 = "http://test.com:8080/an62.do?name=가나다 ㄱㄴ※\n可" ;
    printf("src0[%d] : %s<br/>", strlen($src0), nl2br($src0)) ;
    $an62__tmp0 = AN62::encode($src0) ;
    printf("an62__tmp0:%s<br/>", nl2br($an62__tmp0)) ;
    $an62__out0 = AN62::decode($an62__tmp0) ;
    printf("an62__out0:%s<br/>", nl2br($an62__out0)) ;
    $base64_tmp = base64_encode($src0) ;
    printf("base64_tmp:%s<br/>", nl2br($base64_tmp)) ;
    $base64_out = base64_decode($base64_tmp) ;
    printf("base64_out:%s<br/>", nl2br($base64_out)) ;
    
    // [ 코끼리 = Unicode : 01F418, UTF16 : D83D DC18, UTF8 : F0 9F 90 98 ]
    $src1 = "http://test.com:8080/an62.do?name=가나다 ㄱㄴ※\n可🐘" ;
    printf("src1[%d]:%s<br/>", strlen($src1), nl2br($src1)) ;
    $tmp1 = AN62::encode($src1) ;
    printf("tmp1:%s<br/>", nl2br($tmp1)) ;
    $out1 = AN62::decode($tmp1) ;
    printf("out1:%s<br/>", nl2br($out1)) ;

    if($src1 === $out1)	echo("src1 === out1<br/>") ;
    
} catch(Exception $ex) {
    printf("Exception : %s<br/>", $ex->getMessage()) ;
}
?>
</code>
</body>
</html>

pascal
src0[57] : http://test.com:8080/an62.do?name=가나다 ㄱㄴ※
???
an62__tmp0:QJPMSGcDBxKqT59pP30lEfGUE9WZOXhdCdieS1KqOXeRFbUNWTlJcWWwfKzvXQYGXQk6WQfhvp39
an62__out0:http://test.com:8080/an62.do?name=가나다 ㄱㄴ※
???
base64_tmp:aHR0cDovL3Rlc3QuY29tOjgwODAvYW42Mi5kbz9uYW1lPeqwgOuCmOuLpCDjhLHjhLTigLsK5Y+v
base64_out:http://test.com:8080/an62.do?name=가나다 ㄱㄴ※
???
src1[61]:http://test.com:8080/an62.do?name=가나다 ㄱㄴ※
???????
tmp1:QJPMSGcDBxKqT59pP30lEfGUE9WZOXhdCdieS1KqOXeRFbUNWTlJcWWwfKzvXQYGXQk6WQfhvp39ybpT2S
out1:http://test.com:8080/an62.do?name=가나다 ㄱㄴ※
???????
src1 === out1

Kotlin 예

kotlin
import java.util.*

fun main(args: Array<String>) {
    try {
        val src0 = "http://test.com:8080/an62.do?name=가나다 ㄱㄴ※\n可"
        println("src0[" + src0.length + "]:" + src0)
        val an62__tmp0: String = AN62.encode(src0)
        println("an62__tmp0:$an62__tmp0")
        val an62__out0: String = AN62.decode(an62__tmp0)
        println("an62__out0:$an62__out0")
        val base64_tmp = Base64.getEncoder().encodeToString(src0.toByteArray(charset("utf8")))
        println("base64_tmp:$base64_tmp")
        val base64_out = String(Base64.getDecoder().decode(base64_tmp), charset("utf8"))
        println("base64_out:$base64_out")

        // [ 코끼리 = Unicode : 01F418, UTF16 : D83D DC18, UTF8 : F0 9F 90 98 ]
        val src1 = "http://test.com:8080/an62.do?name=가나다 ㄱㄴ※\n可🐘"
        println("src1[" + src1.length + "]:" + src1) // String.length()은 문자갯수가 아니라, UTF16의 길이다.
        val tmp1: String = AN62.encode(src1)
        println("tmp1:$tmp1")
        val out1: String = AN62.decode(tmp1)
        println("out1:$out1")
        if (src1 == out1) println("src1.equals(out1)")
    } catch (e: Exception) {
        e.printStackTrace()
    }
}

pascal
src0[43]:http://test.com:8080/an62.do?name=가나다 ㄱㄴ※
???
an62__tmp0:QJPMSGcDBxKqT59pP30lEfGUE9WZOXhdCdieS1KqOXeRFbUNWTlJcWWwfKzvXQYGXQk6WQfhvp39
an62__out0:http://test.com:8080/an62.do?name=가나다 ㄱㄴ※
???
base64_tmp:aHR0cDovL3Rlc3QuY29tOjgwODAvYW42Mi5kbz9uYW1lPeqwgOuCmOuLpCDjhLHjhLTigLsK5Y+v
base64_out:http://test.com:8080/an62.do?name=가나다 ㄱㄴ※
???
src1[45]:http://test.com:8080/an62.do?name=가나다 ㄱㄴ※
???????
tmp1:QJPMSGcDBxKqT59pP30lEfGUE9WZOXhdCdieS1KqOXeRFbUNWTlJcWWwfKzvXQYGXQk6WQfhvp39ybpT2S
out1:http://test.com:8080/an62.do?name=가나다 ㄱㄴ※
???????
src1.equals(out1)

TypeScript 예

typescript
function print_msg(msg: string): void {
    if(typeof document !== 'undefined')
        document.write(msg.replace(/\n/g,'<br/>') + '<br/>') ;
    console.log(msg) ;
}

try {
    {
        let src: string = "http://test.com:8080/an62.do?name=가나다 ㄱㄴ※\n可" ;
        print_msg(`src[${src.length}]:${src}`) ;
        let tmp: string = AN62.encode(src) ;
        print_msg(`tmp[${tmp.length}]:${tmp}`) ;
        let out: string = AN62.decode(tmp) ;
        print_msg(`out[${out.length}]:${out}`) ;
    }
    {
        // [ 코끼리 = Unicode : 01F418, UTF16 : D83D DC18, UTF8 : F0 9F 90 98 ]
        let src: string = "http://test.com:8080/an62.do?name=가나다 ㄱㄴ※\n可🐘" ;
        print_msg(`src[${src.length}]:${src}`) ;
        let tmp: string = AN62.encode(src) ;
        print_msg(`tmp[${tmp.length}]:${tmp}`) ;
        let out: string = AN62.decode(tmp) ;
        print_msg(`out[${out.length}]:${out}`) ;

        if(src === out)   print_msg("src === out") ;
    }
} catch(e) {
    print_msg(e) ;
}

pascal
src[43]:http://test.com:8080/an62.do?name=가나다 ㄱㄴ※
???
tmp[76]:QJPMSGcDBxKqT59pP30lEfGUE9WZOXhdCdieS1KqOXeRFbUNWTlJcWWwfKzvXQYGXQk6WQfhvp39
out[43]:http://test.com:8080/an62.do?name=가나다 ㄱㄴ※
???
src[45]:http://test.com:8080/an62.do?name=가나다 ㄱㄴ※
???????
tmp[82]:QJPMSGcDBxKqT59pP30lEfGUE9WZOXhdCdieS1KqOXeRFbUNWTlJcWWwfKzvXQYGXQk6WQfhvp39ybpT2S
out[45]:http://test.com:8080/an62.do?name=가나다 ㄱㄴ※
???????
src === out

Rust 예

rust
use an62;

fn main() {
    {
        let src = "http://test.com:8080/an62.do?name=가나다 ㄱㄴ※\n可" ;
        println!("src[{}]: {}", src.len(), src) ;
        let tmp = an62::encode(src);
        println!("tmp[{}]: {}", tmp.len(), tmp) ;
        let out = an62::decode(tmp.as_str()) ;
        match out {
            Some(out) => println!("out[{}]: {}", out.len(), out),
            None => println!("None"),
        }
    }
    {
        // [ 코끼리 = Unicode : 01F418, UTF16 : D83D DC18, UTF8 : F0 9F 90 98 ]
        let src = "http://test.com:8080/an62.do?name=가나다 ㄱㄴ※\n可🐘" ;
        println!("src[{}]: {}", src.len(), src) ;
        let tmp = an62::encode(src);
        println!("tmp[{}]: {}", tmp.len(), tmp) ;
        let out = an62::decode(tmp.as_str()) ;
        match out {
            Some(out) => {
                            println!("out[{}]: {}", out.len(), out) ;
                            if src == out {	println!("src == out") ;	}
                         },
            None => println!("None"),
        }
    }
}

pascal
src[57]: http://test.com:8080/an62.do?name=가나다 ㄱㄴ※
???
tmp[76]: QJPMSGcDBxKqT59pP30lEfGUE9WZOXhdCdieS1KqOXeRFbUNWTlJcWWwfKzvXQYGXQk6WQfhvp39
out[57]: http://test.com:8080/an62.do?name=가나다 ㄱㄴ※
???
src[61]: http://test.com:8080/an62.do?name=가나다 ㄱㄴ※
???????
tmp[82]: QJPMSGcDBxKqT59pP30lEfGUE9WZOXhdCdieS1KqOXeRFbUNWTlJcWWwfKzvXQYGXQk6WQfhvp39ybpT2S
out[61]: http://test.com:8080/an62.do?name=가나다 ㄱㄴ※
???????
src == out