1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright (c) 2008, by Sun Microsystems, Inc. 23 * All rights reserved. 24 */ 25 26 #include <stdio.h> 27 #include <errno.h> 28 #include <stdlib.h> 29 #include <sys/types.h> 30 #define __NEED_VISCII_2_UNI__ 31 #include <unicode_viscii.h> /* Unicode to viscii mapping table */ 32 #include "common_defs.h" 33 34 35 typedef struct _icv_state { 36 char keepc[4]; /* maximum # byte of UCS code */ 37 int _errno; /* internal errno */ 38 } _iconv_st; 39 40 41 42 /* 43 * Open; called from iconv_open() 44 */ 45 void * 46 _icv_open() 47 { 48 _iconv_st *st; 49 50 if ((st = (_iconv_st *)malloc(sizeof(_iconv_st))) == NULL) { 51 errno = ENOMEM; 52 return ((void *) -1); 53 } 54 55 st->_errno = 0; 56 return ((void *) st); 57 } 58 59 60 /* 61 * Close; called from iconv_close() 62 */ 63 void 64 _icv_close(_iconv_st *st) 65 { 66 if (!st) 67 errno = EBADF; 68 else 69 free(st); 70 } 71 72 73 /* 74 * Actual conversion; called from iconv() 75 */ 76 size_t 77 _icv_iconv(_iconv_st *st, char **inbuf, size_t *inbytesleft, 78 char **outbuf, size_t *outbytesleft) 79 { 80 81 #ifdef DEBUG 82 fprintf(stderr, "========== iconv(): viscii -->UTF-8 ==========\n"); 83 #endif 84 if (st == NULL) { 85 errno = EBADF; 86 return ((size_t) -1); 87 } 88 89 if (inbuf == NULL || *inbuf == NULL) { /* Reset request. */ 90 st->_errno = 0; 91 return ((size_t) 0); 92 } 93 94 st->_errno = 0; /* reset internal errno */ 95 errno = 0; /* reset external errno */ 96 97 /* convert viscii encoding to UTF-8 */ 98 while (*inbytesleft > 0 && *outbytesleft > 0) { 99 unsigned long uni = 0; 100 101 viscii_2_uni((unsigned char*)*inbuf, &uni); 102 if (uni < 0x80) { 103 *(*outbuf)++ = (char)uni; 104 (*outbytesleft) -= 1; 105 } else if (uni >= 0x0080 && uni <= 0x07ff) { 106 if (*outbytesleft < 2 ) { 107 errno = E2BIG; 108 return((size_t)-1); 109 } 110 *(*outbuf)++ = (char)((uni >> 6) & 0x1f) | 0xc0; 111 *(*outbuf)++ = (char)(uni & 0x3f) | 0x80; 112 *outbytesleft -= 2; 113 } else if (uni >= 0x0800 && uni <= 0xffff) { 114 if (*outbytesleft < 3) { 115 errno = E2BIG; 116 return((size_t)-1); 117 } 118 *(*outbuf)++ = (char)((uni >> 12) & 0xf) | 0xe0; 119 *(*outbuf)++ = (char)((uni >>6) & 0x3f) | 0x80; 120 *(*outbuf)++ = (char)(uni & 0x3f) | 0x80; 121 *outbytesleft -= 3; 122 } 123 124 (*inbuf)++; 125 (*inbytesleft)--; 126 127 } 128 129 if ( *inbytesleft > 0 && *outbytesleft <= 0 ) { 130 errno = E2BIG; 131 return ((size_t)-1); 132 } 133 134 return ((size_t)(*inbytesleft)); 135 } 136