_codecs_kr.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468
  1. /*
  2. * _codecs_kr.c: Codecs collection for Korean encodings
  3. *
  4. * Written by Hye-Shik Chang <perky@FreeBSD.org>
  5. */
  6. #include "cjkcodecs.h"
  7. #include "mappings_kr.h"
  8. /*
  9. * EUC-KR codec
  10. */
  11. #define EUCKR_JAMO_FIRSTBYTE 0xA4
  12. #define EUCKR_JAMO_FILLER 0xD4
  13. static const unsigned char u2cgk_choseong[19] = {
  14. 0xa1, 0xa2, 0xa4, 0xa7, 0xa8, 0xa9, 0xb1, 0xb2,
  15. 0xb3, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb,
  16. 0xbc, 0xbd, 0xbe
  17. };
  18. static const unsigned char u2cgk_jungseong[21] = {
  19. 0xbf, 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6,
  20. 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce,
  21. 0xcf, 0xd0, 0xd1, 0xd2, 0xd3
  22. };
  23. static const unsigned char u2cgk_jongseong[28] = {
  24. 0xd4, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
  25. 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0,
  26. 0xb1, 0xb2, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xba,
  27. 0xbb, 0xbc, 0xbd, 0xbe
  28. };
  29. ENCODER(euc_kr)
  30. {
  31. while (*inpos < inlen) {
  32. Py_UCS4 c = INCHAR1;
  33. DBCHAR code;
  34. if (c < 0x80) {
  35. WRITEBYTE1((unsigned char)c);
  36. NEXT(1, 1);
  37. continue;
  38. }
  39. if (c > 0xFFFF)
  40. return 1;
  41. REQUIRE_OUTBUF(2);
  42. if (TRYMAP_ENC(cp949, code, c))
  43. ;
  44. else
  45. return 1;
  46. if ((code & 0x8000) == 0) {
  47. /* KS X 1001 coded character */
  48. OUTBYTE1((code >> 8) | 0x80);
  49. OUTBYTE2((code & 0xFF) | 0x80);
  50. NEXT(1, 2);
  51. }
  52. else {
  53. /* Mapping is found in CP949 extension,
  54. but we encode it in KS X 1001:1998,
  55. make-up sequence for EUC-KR. */
  56. REQUIRE_OUTBUF(8);
  57. /* syllable composition precedence */
  58. OUTBYTE1(EUCKR_JAMO_FIRSTBYTE);
  59. OUTBYTE2(EUCKR_JAMO_FILLER);
  60. /* All code points in CP949 extension are in unicode
  61. * Hangul Syllable area. */
  62. assert(0xac00 <= c && c <= 0xd7a3);
  63. c -= 0xac00;
  64. OUTBYTE3(EUCKR_JAMO_FIRSTBYTE);
  65. OUTBYTE4(u2cgk_choseong[c / 588]);
  66. NEXT_OUT(4);
  67. OUTBYTE1(EUCKR_JAMO_FIRSTBYTE);
  68. OUTBYTE2(u2cgk_jungseong[(c / 28) % 21]);
  69. OUTBYTE3(EUCKR_JAMO_FIRSTBYTE);
  70. OUTBYTE4(u2cgk_jongseong[c % 28]);
  71. NEXT(1, 4);
  72. }
  73. }
  74. return 0;
  75. }
  76. #define NONE 127
  77. static const unsigned char cgk2u_choseong[] = { /* [A1, BE] */
  78. 0, 1, NONE, 2, NONE, NONE, 3, 4,
  79. 5, NONE, NONE, NONE, NONE, NONE, NONE, NONE,
  80. 6, 7, 8, NONE, 9, 10, 11, 12,
  81. 13, 14, 15, 16, 17, 18
  82. };
  83. static const unsigned char cgk2u_jongseong[] = { /* [A1, BE] */
  84. 1, 2, 3, 4, 5, 6, 7, NONE,
  85. 8, 9, 10, 11, 12, 13, 14, 15,
  86. 16, 17, NONE, 18, 19, 20, 21, 22,
  87. NONE, 23, 24, 25, 26, 27
  88. };
  89. DECODER(euc_kr)
  90. {
  91. while (inleft > 0) {
  92. unsigned char c = INBYTE1;
  93. Py_UCS4 decoded;
  94. if (c < 0x80) {
  95. OUTCHAR(c);
  96. NEXT_IN(1);
  97. continue;
  98. }
  99. REQUIRE_INBUF(2);
  100. if (c == EUCKR_JAMO_FIRSTBYTE &&
  101. INBYTE2 == EUCKR_JAMO_FILLER) {
  102. /* KS X 1001:1998 make-up sequence */
  103. DBCHAR cho, jung, jong;
  104. REQUIRE_INBUF(8);
  105. if ((*inbuf)[2] != EUCKR_JAMO_FIRSTBYTE ||
  106. (*inbuf)[4] != EUCKR_JAMO_FIRSTBYTE ||
  107. (*inbuf)[6] != EUCKR_JAMO_FIRSTBYTE)
  108. return 1;
  109. c = (*inbuf)[3];
  110. if (0xa1 <= c && c <= 0xbe)
  111. cho = cgk2u_choseong[c - 0xa1];
  112. else
  113. cho = NONE;
  114. c = (*inbuf)[5];
  115. jung = (0xbf <= c && c <= 0xd3) ? c - 0xbf : NONE;
  116. c = (*inbuf)[7];
  117. if (c == EUCKR_JAMO_FILLER)
  118. jong = 0;
  119. else if (0xa1 <= c && c <= 0xbe)
  120. jong = cgk2u_jongseong[c - 0xa1];
  121. else
  122. jong = NONE;
  123. if (cho == NONE || jung == NONE || jong == NONE)
  124. return 1;
  125. OUTCHAR(0xac00 + cho*588 + jung*28 + jong);
  126. NEXT_IN(8);
  127. }
  128. else if (TRYMAP_DEC(ksx1001, decoded, c ^ 0x80, INBYTE2 ^ 0x80)) {
  129. OUTCHAR(decoded);
  130. NEXT_IN(2);
  131. }
  132. else
  133. return 1;
  134. }
  135. return 0;
  136. }
  137. #undef NONE
  138. /*
  139. * CP949 codec
  140. */
  141. ENCODER(cp949)
  142. {
  143. while (*inpos < inlen) {
  144. Py_UCS4 c = INCHAR1;
  145. DBCHAR code;
  146. if (c < 0x80) {
  147. WRITEBYTE1((unsigned char)c);
  148. NEXT(1, 1);
  149. continue;
  150. }
  151. if (c > 0xFFFF)
  152. return 1;
  153. REQUIRE_OUTBUF(2);
  154. if (TRYMAP_ENC(cp949, code, c))
  155. ;
  156. else
  157. return 1;
  158. OUTBYTE1((code >> 8) | 0x80);
  159. if (code & 0x8000)
  160. OUTBYTE2(code & 0xFF); /* MSB set: CP949 */
  161. else
  162. OUTBYTE2((code & 0xFF) | 0x80); /* MSB unset: ks x 1001 */
  163. NEXT(1, 2);
  164. }
  165. return 0;
  166. }
  167. DECODER(cp949)
  168. {
  169. while (inleft > 0) {
  170. unsigned char c = INBYTE1;
  171. Py_UCS4 decoded;
  172. if (c < 0x80) {
  173. OUTCHAR(c);
  174. NEXT_IN(1);
  175. continue;
  176. }
  177. REQUIRE_INBUF(2);
  178. if (TRYMAP_DEC(ksx1001, decoded, c ^ 0x80, INBYTE2 ^ 0x80))
  179. OUTCHAR(decoded);
  180. else if (TRYMAP_DEC(cp949ext, decoded, c, INBYTE2))
  181. OUTCHAR(decoded);
  182. else
  183. return 1;
  184. NEXT_IN(2);
  185. }
  186. return 0;
  187. }
  188. /*
  189. * JOHAB codec
  190. */
  191. static const unsigned char u2johabidx_choseong[32] = {
  192. 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
  193. 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
  194. 0x10, 0x11, 0x12, 0x13, 0x14,
  195. };
  196. static const unsigned char u2johabidx_jungseong[32] = {
  197. 0x03, 0x04, 0x05, 0x06, 0x07,
  198. 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
  199. 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
  200. 0x1a, 0x1b, 0x1c, 0x1d,
  201. };
  202. static const unsigned char u2johabidx_jongseong[32] = {
  203. 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
  204. 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
  205. 0x10, 0x11, 0x13, 0x14, 0x15, 0x16, 0x17,
  206. 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d,
  207. };
  208. static const DBCHAR u2johabjamo[] = {
  209. 0x8841, 0x8c41, 0x8444, 0x9041, 0x8446, 0x8447, 0x9441,
  210. 0x9841, 0x9c41, 0x844a, 0x844b, 0x844c, 0x844d, 0x844e, 0x844f,
  211. 0x8450, 0xa041, 0xa441, 0xa841, 0x8454, 0xac41, 0xb041, 0xb441,
  212. 0xb841, 0xbc41, 0xc041, 0xc441, 0xc841, 0xcc41, 0xd041, 0x8461,
  213. 0x8481, 0x84a1, 0x84c1, 0x84e1, 0x8541, 0x8561, 0x8581, 0x85a1,
  214. 0x85c1, 0x85e1, 0x8641, 0x8661, 0x8681, 0x86a1, 0x86c1, 0x86e1,
  215. 0x8741, 0x8761, 0x8781, 0x87a1,
  216. };
  217. ENCODER(johab)
  218. {
  219. while (*inpos < inlen) {
  220. Py_UCS4 c = INCHAR1;
  221. DBCHAR code;
  222. if (c < 0x80) {
  223. WRITEBYTE1((unsigned char)c);
  224. NEXT(1, 1);
  225. continue;
  226. }
  227. if (c > 0xFFFF)
  228. return 1;
  229. REQUIRE_OUTBUF(2);
  230. if (c >= 0xac00 && c <= 0xd7a3) {
  231. c -= 0xac00;
  232. code = 0x8000 |
  233. (u2johabidx_choseong[c / 588] << 10) |
  234. (u2johabidx_jungseong[(c / 28) % 21] << 5) |
  235. u2johabidx_jongseong[c % 28];
  236. }
  237. else if (c >= 0x3131 && c <= 0x3163)
  238. code = u2johabjamo[c - 0x3131];
  239. else if (TRYMAP_ENC(cp949, code, c)) {
  240. unsigned char c1, c2, t2;
  241. unsigned short t1;
  242. assert((code & 0x8000) == 0);
  243. c1 = code >> 8;
  244. c2 = code & 0xff;
  245. if (((c1 >= 0x21 && c1 <= 0x2c) ||
  246. (c1 >= 0x4a && c1 <= 0x7d)) &&
  247. (c2 >= 0x21 && c2 <= 0x7e)) {
  248. t1 = (c1 < 0x4a ? (c1 - 0x21 + 0x1b2) :
  249. (c1 - 0x21 + 0x197));
  250. t2 = ((t1 & 1) ? 0x5e : 0) + (c2 - 0x21);
  251. OUTBYTE1(t1 >> 1);
  252. OUTBYTE2(t2 < 0x4e ? t2 + 0x31 : t2 + 0x43);
  253. NEXT(1, 2);
  254. continue;
  255. }
  256. else
  257. return 1;
  258. }
  259. else
  260. return 1;
  261. OUTBYTE1(code >> 8);
  262. OUTBYTE2(code & 0xff);
  263. NEXT(1, 2);
  264. }
  265. return 0;
  266. }
  267. #define FILL 0xfd
  268. #define NONE 0xff
  269. static const unsigned char johabidx_choseong[32] = {
  270. NONE, FILL, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05,
  271. 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d,
  272. 0x0e, 0x0f, 0x10, 0x11, 0x12, NONE, NONE, NONE,
  273. NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE,
  274. };
  275. static const unsigned char johabidx_jungseong[32] = {
  276. NONE, NONE, FILL, 0x00, 0x01, 0x02, 0x03, 0x04,
  277. NONE, NONE, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a,
  278. NONE, NONE, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10,
  279. NONE, NONE, 0x11, 0x12, 0x13, 0x14, NONE, NONE,
  280. };
  281. static const unsigned char johabidx_jongseong[32] = {
  282. NONE, FILL, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
  283. 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e,
  284. 0x0f, 0x10, NONE, 0x11, 0x12, 0x13, 0x14, 0x15,
  285. 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, NONE, NONE,
  286. };
  287. static const unsigned char johabjamo_choseong[32] = {
  288. NONE, FILL, 0x31, 0x32, 0x34, 0x37, 0x38, 0x39,
  289. 0x41, 0x42, 0x43, 0x45, 0x46, 0x47, 0x48, 0x49,
  290. 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, NONE, NONE, NONE,
  291. NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE,
  292. };
  293. static const unsigned char johabjamo_jungseong[32] = {
  294. NONE, NONE, FILL, 0x4f, 0x50, 0x51, 0x52, 0x53,
  295. NONE, NONE, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
  296. NONE, NONE, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
  297. NONE, NONE, 0x60, 0x61, 0x62, 0x63, NONE, NONE,
  298. };
  299. static const unsigned char johabjamo_jongseong[32] = {
  300. NONE, FILL, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36,
  301. 0x37, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
  302. 0x40, 0x41, NONE, 0x42, 0x44, 0x45, 0x46, 0x47,
  303. 0x48, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, NONE, NONE,
  304. };
  305. DECODER(johab)
  306. {
  307. while (inleft > 0) {
  308. unsigned char c = INBYTE1, c2;
  309. Py_UCS4 decoded;
  310. if (c < 0x80) {
  311. OUTCHAR(c);
  312. NEXT_IN(1);
  313. continue;
  314. }
  315. REQUIRE_INBUF(2);
  316. c2 = INBYTE2;
  317. if (c < 0xd8) {
  318. /* johab hangul */
  319. unsigned char c_cho, c_jung, c_jong;
  320. unsigned char i_cho, i_jung, i_jong;
  321. c_cho = (c >> 2) & 0x1f;
  322. c_jung = ((c << 3) | c2 >> 5) & 0x1f;
  323. c_jong = c2 & 0x1f;
  324. i_cho = johabidx_choseong[c_cho];
  325. i_jung = johabidx_jungseong[c_jung];
  326. i_jong = johabidx_jongseong[c_jong];
  327. if (i_cho == NONE || i_jung == NONE || i_jong == NONE)
  328. return 1;
  329. /* we don't use U+1100 hangul jamo yet. */
  330. if (i_cho == FILL) {
  331. if (i_jung == FILL) {
  332. if (i_jong == FILL)
  333. OUTCHAR(0x3000);
  334. else
  335. OUTCHAR(0x3100 |
  336. johabjamo_jongseong[c_jong]);
  337. }
  338. else {
  339. if (i_jong == FILL)
  340. OUTCHAR(0x3100 |
  341. johabjamo_jungseong[c_jung]);
  342. else
  343. return 1;
  344. }
  345. } else {
  346. if (i_jung == FILL) {
  347. if (i_jong == FILL)
  348. OUTCHAR(0x3100 |
  349. johabjamo_choseong[c_cho]);
  350. else
  351. return 1;
  352. }
  353. else
  354. OUTCHAR(0xac00 +
  355. i_cho * 588 +
  356. i_jung * 28 +
  357. (i_jong == FILL ? 0 : i_jong));
  358. }
  359. NEXT_IN(2);
  360. } else {
  361. /* KS X 1001 except hangul jamos and syllables */
  362. if (c == 0xdf || c > 0xf9 ||
  363. c2 < 0x31 || (c2 >= 0x80 && c2 < 0x91) ||
  364. (c2 & 0x7f) == 0x7f ||
  365. (c == 0xda && (c2 >= 0xa1 && c2 <= 0xd3)))
  366. return 1;
  367. else {
  368. unsigned char t1, t2;
  369. t1 = (c < 0xe0 ? 2 * (c - 0xd9) :
  370. 2 * c - 0x197);
  371. t2 = (c2 < 0x91 ? c2 - 0x31 : c2 - 0x43);
  372. t1 = t1 + (t2 < 0x5e ? 0 : 1) + 0x21;
  373. t2 = (t2 < 0x5e ? t2 : t2 - 0x5e) + 0x21;
  374. if (TRYMAP_DEC(ksx1001, decoded, t1, t2)) {
  375. OUTCHAR(decoded);
  376. NEXT_IN(2);
  377. }
  378. else {
  379. return 1;
  380. }
  381. }
  382. }
  383. }
  384. return 0;
  385. }
  386. #undef NONE
  387. #undef FILL
  388. BEGIN_MAPPINGS_LIST(3)
  389. MAPPING_DECONLY(ksx1001)
  390. MAPPING_ENCONLY(cp949)
  391. MAPPING_DECONLY(cp949ext)
  392. END_MAPPINGS_LIST
  393. BEGIN_CODECS_LIST(3)
  394. CODEC_STATELESS(euc_kr)
  395. CODEC_STATELESS(cp949)
  396. CODEC_STATELESS(johab)
  397. END_CODECS_LIST
  398. I_AM_A_MODULE_FOR(kr)