1/* Conversion to UTF-8 from legacy encodings. 2 Copyright (C) 2002, 2006-2007, 2009-2010 Free Software Foundation, Inc. 3 4 This program is free software: you can redistribute it and/or modify it 5 under the terms of the GNU Lesser General Public License as published 6 by the Free Software Foundation; either version 3 of the License, or 7 (at your option) any later version. 8 9 This program is distributed in the hope that it will be useful, 10 but WITHOUT ANY WARRANTY; without even the implied warranty of 11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 Lesser General Public License for more details. 13 14 You should have received a copy of the GNU Lesser General Public License 15 along with this program. If not, see <http://www.gnu.org/licenses/>. */ 16 17/* Written by Bruno Haible <bruno@clisp.org>. */ 18 19#include <config.h> 20 21/* Specification. */ 22#include "uniconv.h" 23 24#include <errno.h> 25#include <stdlib.h> 26#include <string.h> 27 28#include "c-strcaseeq.h" 29#include "striconveha.h" 30#include "unistr.h" 31 32uint8_t * 33u8_conv_from_encoding (const char *fromcode, 34 enum iconv_ilseq_handler handler, 35 const char *src, size_t srclen, 36 size_t *offsets, 37 uint8_t *resultbuf, size_t *lengthp) 38{ 39 if (STRCASEEQ (fromcode, "UTF-8", 'U','T','F','-','8',0,0,0,0)) 40 { 41 /* Conversion from UTF-8 to UTF-8. No need to go through iconv(). */ 42 uint8_t *result; 43 44 if (u8_check ((const uint8_t *) src, srclen)) 45 { 46 errno = EILSEQ; 47 return NULL; 48 } 49 50 if (offsets != NULL) 51 { 52 size_t i; 53 54 for (i = 0; i < srclen; ) 55 { 56 int count = u8_mblen ((const uint8_t *) src + i, srclen - i); 57 /* We can rely on count > 0 because of the previous u8_check. */ 58 if (count <= 0) 59 abort (); 60 offsets[i] = i; 61 i++; 62 while (--count > 0) 63 offsets[i++] = (size_t)(-1); 64 } 65 } 66 67 /* Memory allocation. */ 68 if (resultbuf != NULL && *lengthp >= srclen) 69 result = resultbuf; 70 else 71 { 72 result = (uint8_t *) malloc (srclen > 0 ? srclen : 1); 73 if (result == NULL) 74 { 75 errno = ENOMEM; 76 return NULL; 77 } 78 } 79 80 memcpy ((char *) result, src, srclen); 81 *lengthp = srclen; 82 return result; 83 } 84 else 85 { 86 char *result = (char *) resultbuf; 87 size_t length = *lengthp; 88 89 if (mem_iconveha (src, srclen, fromcode, "UTF-8", true, handler, 90 offsets, &result, &length) < 0) 91 return NULL; 92 93 if (result == NULL) /* when (resultbuf == NULL && length == 0) */ 94 { 95 result = (char *) malloc (1); 96 if (result == NULL) 97 { 98 errno = ENOMEM; 99 return NULL; 100 } 101 } 102 *lengthp = length; 103 return (uint8_t *) result; 104 } 105} 106