charset.c

来自「这个库实现了录象功能」· C语言 代码 · 共 245 行

C
245
字号
/******************************************************************************* charset.c libquicktime - A library for reading and writing quicktime/avi/mp4 files. http://libquicktime.sourceforge.net Copyright (C) 2002 Heroine Virtual Ltd. Copyright (C) 2002-2007 Members of the libquicktime project. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA*******************************************************************************/ #include "lqt_private.h"#include "charset.h"#include <iconv.h>#include <stdlib.h>#include <string.h>#include <errno.h>#define LOG_DOMAIN "charset"struct lqt_charset_converter_s  {  iconv_t cd;  quicktime_t * file; /* For logging */  int utf_8_16;  char * out_charset;  char * in_buffer;  int in_buffer_alloc;  };lqt_charset_converter_t *lqt_charset_converter_create(quicktime_t * file, const char * src_charset, const char * dst_charset)  {  lqt_charset_converter_t * ret = calloc(1, sizeof(*ret));  if(!strcmp(src_charset, LQT_UTF_8_16))    {    ret->out_charset = malloc(strlen(dst_charset)+1);    strcpy(ret->out_charset, dst_charset);    ret->utf_8_16 = 1;    ret->cd = (iconv_t)-1;    }  else    {    ret->cd = iconv_open(dst_charset, src_charset);    if(ret->cd == (iconv_t)-1)      {      free(ret);      return (lqt_charset_converter_t*)0;      }    }  ret->file = file;  return ret;    }#define BYTES_INCREMENT 10static int do_convert(lqt_charset_converter_t * cnv, char * in_string, int len, int * out_len,               char ** ret, int * ret_alloc)  {  char *inbuf;  char *outbuf;  int output_pos;  size_t inbytesleft;  size_t outbytesleft;  /* Check for MP4 Unicode */  if(cnv->utf_8_16 && (cnv->cd == (iconv_t)-1))    {    /* Byte order Little Endian */    if((len > 1) &&       ((uint8_t)in_string[0] == 0xff) &&       ((uint8_t)in_string[1] == 0xfe))      {      cnv->cd = iconv_open(cnv->out_charset, "UTF-16LE");      if(cnv->cd == (iconv_t)-1)        {        lqt_log(cnv->file, LQT_LOG_ERROR, LOG_DOMAIN, "Cannot open iconv for conversion to %s from %s",                 cnv->out_charset, "UTF-16LE");        return 0;        }      }    /* Byte order Big Endian */    else if((len > 1) &&            ((uint8_t)in_string[0] == 0xfe) &&            ((uint8_t)in_string[1] == 0xff))      {      cnv->cd = iconv_open(cnv->out_charset, "UTF-16BE");      if(cnv->cd == (iconv_t)-1)        {        lqt_log(cnv->file, LQT_LOG_ERROR, LOG_DOMAIN, "Cannot open iconv for conversion to %s from %s",                cnv->out_charset, "UTF-16BE");        return 0;        }      }    /* UTF-8 */    else if(!strcmp(cnv->out_charset, "UTF-8"))      {      if(*ret_alloc < len+1)        {        *ret_alloc = len + BYTES_INCREMENT;        *ret       = realloc(*ret, *ret_alloc);        }      strncpy(*ret, in_string, len);      (*ret)[len] = '\0';      if(out_len)        *out_len = len;      return 1;      }    else      {      cnv->cd = iconv_open(cnv->out_charset, "UTF-8");      if(cnv->cd == (iconv_t)-1)        {        lqt_log(cnv->file, LQT_LOG_ERROR, LOG_DOMAIN, "Cannot open iconv for conversion to %s from %s",                cnv->out_charset, "UTF-8");        return 0;        }      }    }        if((*ret_alloc) < len + BYTES_INCREMENT)    {    *ret_alloc = len + BYTES_INCREMENT;    *ret       = realloc(*ret, *ret_alloc);    }  inbytesleft  = len;  outbytesleft = *ret_alloc;  inbuf  = in_string;  outbuf = *ret;  while(1)    {    if(iconv(cnv->cd, &inbuf, &inbytesleft,             &outbuf, &outbytesleft) == (size_t)-1)      {      switch(errno)        {        case E2BIG:          output_pos = (int)(outbuf - *ret);          *ret_alloc   += BYTES_INCREMENT;          outbytesleft += BYTES_INCREMENT;          *ret = realloc(*ret, *ret_alloc);          outbuf = &((*ret)[output_pos]);          break;        case EILSEQ:          lqt_log(cnv->file, LQT_LOG_ERROR, LOG_DOMAIN, "Invalid Multibyte sequence");          return 0;          break;        case EINVAL:          lqt_log(cnv->file, LQT_LOG_ERROR, LOG_DOMAIN, "Incomplete Multibyte sequence");          return 0;          break;        }      }    if(!inbytesleft)      break;    }  /* Zero terminate */  output_pos = (int)(outbuf - *ret);  if(outbytesleft < 2)    {    *ret_alloc+=2;    *ret = realloc(*ret, *ret_alloc);    outbuf = &((*ret)[output_pos]);    }  outbuf[0] = '\0';  outbuf[1] = '\0';  if(out_len)    *out_len = outbuf - *ret;  return 1;  }/* We convert all strings "in place" */void lqt_charset_convert(lqt_charset_converter_t * cnv,                         char ** str, int in_len, int * out_len)  {  char * new = (char*)0;  int new_alloc = 0;  if(!(*str))    return;  if(in_len < 0) in_len = strlen(*str);    if(!do_convert(cnv, *str, in_len, out_len,                 &new, &new_alloc))    {    if(new) free(new);    return;    }  free(*str);  *str = new;  }void lqt_charset_convert_realloc(lqt_charset_converter_t * cnv,                                 const char * in_str, int in_len,                                 char ** out_str, int * out_alloc, int * out_len)  {  if(in_len < 0) in_len = strlen(in_str);  if(cnv->in_buffer_alloc < in_len + 2)    {    cnv->in_buffer_alloc = in_len + 128;    cnv->in_buffer = realloc(cnv->in_buffer, cnv->in_buffer_alloc);    }  memcpy(cnv->in_buffer, in_str, in_len);  cnv->in_buffer[in_len] = '\0';  cnv->in_buffer[in_len+1] = '\0';    do_convert(cnv, cnv->in_buffer, in_len, out_len,             out_str, out_alloc);  }void lqt_charset_converter_destroy(lqt_charset_converter_t * cnv)  {  if(cnv->cd != (iconv_t)-1)    iconv_close(cnv->cd);  if(cnv->out_charset)    free(cnv->out_charset);  free(cnv);  }

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?