RPG での文字のエンコードの方法として「 323. ASCII エンコードするには 」を
紹介したが、それでは C 言語でのエンコードはやさしいかというとそうでもない。
もちろん C 言語でもエンコードする必要に迫られることがあるのでその方法を紹介しよう。
【 TESTENCD2 】
0001.00 #include 0002.00 #include 0003.00 #include 0004.00 #include /* triml */ 0005.00 #include /* toupper */ 0006.00 #include 0007.00 #include 0008.00 0009.00 #define TRUE 0 0010.00 #define FALSE -1 0011.00 /*( UTF 変数 )*/ 0012.00 #define UTF8 1208 0013.00 #define USA 0 0014.00 #define JPN 1 0015.00 #define CHS 2 0016.00 #define CHT 3 0017.00 #define JPN5035 8 0018.00 0019.00 int encode(char* fromstr, char* tostr, int CNTRY, char* URLPath); 0020.00 char* encodeURIComponentUTF(char* utf8_str); 0021.00 int toUTF8(char* ebcbuf, char* unibuf, int CNTRY); /* UNI_CODE */ 0022.00 int toEBCDIC(char* ebcbuf, char* ascbuf, char* table, /* CVTMOD4 */ 0023.00 char* tbllib, int bSiSo); 0024.00 0025.00 void main(void){ 0026.00 char fromstr[128], tostr[128], URLPath[128]; 0027.00 0028.00 printf("** TESTENCD2: UTF8 エンコードのテスト **?n"); 0029.00 getchar(); 0030.00 0031.00 strcpy(fromstr, "/TEMP/MY#FILE.TMP"); 0032.00 strcpy(URLPath, "http;//www.officequattro.com"); 0033.00 if(encode(fromstr, tostr, JPN5035, URLPath) == FALSE){/* エラー */ 0034.00 printf("HTTPSRV[%d] %s: エンコードでエラーがありました。 ", 0035.00 __LINE__, fromstr); 0036.00 getchar(); 0037.00 exit(-1); 0038.00 }/* エラー */ 0039.00 printf("[%d] 文字列 %s は ?n", __LINE__, fromstr); 0040.00 printf("[%d] %s とエンコードされました。 ?n", __LINE__, tostr); 0041.00 getchar(); 0042.00 exit(0); 0043.00 } 0044.00 0045.00 /*****************************************************************/ 0046.00 int encode(char* fromstr, char* tostr, int CNTRY, char* URLPath) 0047.00 /*****************************************************************/ 0048.00 { 0049.00 char utfbuf[2048]; 0050.00 _Decimal(5,0) dclen, outlen = 0; 0051.00 _Decimal(5,0) maxotl = 2048; 0052.00 int len; 0053.00 0054.00 memset(utfbuf, 0, sizeof(utfbuf)); 0055.00 if((strstr(URLPath, "ea-jp")) != NULL){/* 英語から日本語 */ 0056.00 memset(utfbuf, 0, sizeof(utfbuf)); 0057.00 len = strlen(fromstr); 0058.00 dclen = (_Decimal(5,0))len; 0059.00 QDCXLATE(&dclen, fromstr, "QASCII ", "QSYS ", utfbuf, 0060.00 &maxotl, &outlen, "*JPN ", "N", "*EA "); 0061.00 }/* 英語から日本語 */ 0062.00 else{/* それ以外 */ 0063.00 if(toUTF8(fromstr, utfbuf, CNTRY) == FALSE){/* エラー */ 0064.00 printf("HTTPSRV[%d] UTF8 変換でエラーがありました。 ?n%s?n", __LINE__, 0065.00 fromstr); 0066.00 return FALSE; 0067.00 }/* エラー */ 0068.00 }/* それ以外 */ 0069.00 strcpy(tostr, encodeURIComponentUTF(utfbuf)); 0070.00 return TRUE; 0071.00 } 0072.00 /*****************************************/ 0073.00 char* encodeURIComponentUTF(char* utf8_str) 0074.00 /*****************************************/ 0075.00 /* JavaScript の encodeURIComponent() と同じようにエンコードする */ 0076.00 { 0077.00 char *ptr; 0078.00 char ebc_str[5], utf_str[5]; 0079.00 0080.00 ptr = utf8_str; 0081.00 while(*ptr){/*while*/ 0082.00 #pragma convert(850) 0083.00 if('0' <= *ptr && *ptr <= '9' || 0084.00 'A' <= *ptr && *ptr <= 'Z' || 0085.00 'a' <= *ptr && *ptr <= 'z' || 0086.00 *ptr == '-' || *ptr == '_' || *ptr == '.' || *ptr == '!' || 0087.00 *ptr == '…?' || *ptr == '*' || *ptr == '?'') 0088.00 #pragma convert(0) 0089.00 {/* エンコードの必要なし */ 0090.00 memcpy(utf_str, ptr, 1); 0091.00 utf_str[1] = 0x00; 0092.00 toEBCDIC(ebc_str, utf_str, "EBCDIC5035", "ASNET.COM ", TRUE); 0093.00 memcpy(ptr, ebc_str, 1); 0094.00 ptr ++; 0095.00 continue; 0096.00 }/* エンコードの必要なし */ 0097.00 else{/* エンコードが必要 */ 0098.00 memmove(ptr + 3, ptr + 1, strlen(ptr + 1) + 1); 0099.00 sprintf(ebc_str, "%%%02X", *ptr); 0100.00 memcpy(ptr, ebc_str, 3); 0101.00 ptr += 3; 0102.00 }/* エンコードが必要 */ 0103.00 }/*while*/ 0104.00 return utf8_str; 0105.00 }
【 解説 】
実行してみると
** TESTENCD2: UTF8 エンコードのテスト ** > [39] 文字列 /TEMP/MY#FILE.TMP は [40] %2FTEMP%2FMY%23FILE.TMP とエンコードされました。
のように表示される。
テスト用の文字列「 /TEMP/MY#FILE.TMP 」の文字「 / 」と「 # 」の
部分だけがエンコードされていることがわかる。
/ は UTF-8 では 0x’2f’ なので %2F とエンコードされ、
# は UTF-8 では 0x’23’ なので %23 とエンコードされる。
エンコードのコアの部分は関数: encodeURIComponentUTF で実行されるので
これを利用するなり読み取って欲しい。
なおこの TESTENCD2 は弊社の *SRVPGM: UNI_CODE と CVTMO4 を
バインドする必要があるので読者の環境ではコンパイルすることはできないが
ソースを学習するために紹介した。
AutoWebのユーザーであれば
CRTCMOD MODULE(QTEMP/TESTENCD2) SRCFILE(R610SRC/QCSRC) AUT(*ALL) CRTPGM PGM(TEST.COM/TESTENCD2) MODULE(QTEMP/TESTENCD2) BNDSRVPGM((ASNET.OM/UNI_CODE) (ASNET.COM/CVTMOD4)) ACTGRP(*NEW) AUT(*ALL)
によってコンパイルすることができる。