Eine aufbereitete Darstellung der Quelle

 
     
 
 
Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 

Benutzer

Quelle  mariadb-conv.cc   Sprache: C

 

/*
   Copyright (c) 2001, 2013, Oracle and/or its affiliates.
   Copyright (c) 2010, 2019, MariaDB

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; version 2 of the License.

   This program 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 General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA
*/


/*
   Character set conversion utility
*/


#define VER "1.0"
#include "mariadb.h"
#include "client_priv.h"
#include "sql_string.h"
#include "my_dir.h"
#include <welcome_copyright_notice.h>

class CmdOpt
{
public:
  const char *m_charset_from;
  const char *m_charset_to;
  const char *m_delimiter;
  my_bool m_continue;
  CmdOpt()
   :m_charset_from("latin1"),
    m_charset_to("latin1"),
    m_delimiter(NULL),
    m_continue(FALSE)
  { }
  static CHARSET_INFO *csinfo_by_name(const char *csname)
  {
    return get_charset_by_csname(csname, MY_CS_PRIMARY, MYF(MY_UTF8_IS_UTF8MB3));
  }
  CHARSET_INFO *csinfo_from() const
  {
    return m_charset_from ? csinfo_by_name(m_charset_from) : NULL;
  }
  CHARSET_INFO *csinfo_to() const
  {
    return m_charset_to ? csinfo_by_name(m_charset_to) : NULL;
  }
};


static CmdOpt opt;


static struct my_option long_options[] =
{
  {"from", 'f', "Specifies the encoding of the input.", &opt.m_charset_from,
   &opt.m_charset_from, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
  {"to", 't', "Specifies the encoding of the output.", &opt.m_charset_to,
   &opt.m_charset_to, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
  {"continue", 'c', "Silently ignore conversion errors.",
   &opt.m_continue, &opt.m_continue, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
  {"delimiter", 0, "Treat the specified characters as delimiters.",
    &opt.m_delimiter, &opt.m_delimiter, 0, GET_STR, REQUIRED_ARG,
    0, 0, 0, 0, 0, 0},
  {"character-sets-dir", OPT_CHARSETS_DIR,
   "Directory for character set files.", &charsets_dir,
   &charsets_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
  {0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
};


my_bool
get_one_option(const struct my_option *opt,
               const char *value, const char *filename)
{
  return 0;
}


class File_buffer: public Binary_string
{
public:
  bool load_binary_stream(FILE *file);
  bool load_binary_file_by_name(const char *file);
};


/*
  Load data from a binary stream whose length is not known in advance,
  e.g. from stdin.
*/

bool File_buffer::load_binary_stream(FILE *file)
{
  for ( ; ; )
  {
    char buf[1024];
    if (length() + sizeof(buf) > UINT_MAX32 || reserve(sizeof(buf)))
    {
      fprintf(stderr, "Input data is too large\n");
      return true;
    }
    size_t nbytes= my_fread(file, (uchar *) end(), sizeof(buf), MYF(0));
    if (!nbytes || nbytes == (size_t) -1)
      return false;
    str_length+= (uint32) nbytes;
  }
  return false;
}


/*
  Load data from a file by name.
  The file size is know.
*/

bool File_buffer::load_binary_file_by_name(const char *filename)
{
  MY_STAT sbuf;
  File fd;

  if (!my_stat(filename, &sbuf, MYF(0)))
  {
    fprintf(stderr, "my_stat failed for '%s'\n", filename);
    return true;
  }
 
  if (!MY_S_ISREG(sbuf.st_mode))
  {
    fprintf(stderr, "'%s' is not a regular file\n", filename);
    return true;
  }

  if ((size_t) sbuf.st_size > UINT_MAX32)
  {
    fprintf(stderr, "File '%s' is too large\n", filename);
    return true;
  }

  if (alloc((uint32) sbuf.st_size))
  {
    fprintf(stderr, "Failed to allocate read buffer\n");
    return true;
  }

  if ((fd= my_open(filename, O_RDONLY, MYF(0))) == -1)
  {
    fprintf(stderr, "Could not open '%s'\n", filename);
    return true;
  }

  size_t nbytes= my_read(fd, (uchar*) Ptr, (size_t)sbuf.st_size, MYF(0));
  my_close(fd, MYF(0));
  length((uint32) nbytes);

  return false;
}


class Delimiter
{
protected:
  bool m_delimiter[127];
  bool m_has_delimiter_cached;
  bool has_delimiter_slow() const
  {
    for (size_t i= 0; i < sizeof(m_delimiter); i++)
    {
      if (m_delimiter[i])
        return true;
    }
    return false;
  }
  bool unescape(char *to, char from) const
  {
    switch (from) {
    case '\\': *to= '\\'; return false;
    case 'r':  *to= '\r'; return false;
    case 'n':  *to= '\n'; return false;
    case 't':  *to= '\t'; return false;
    case '0':  *to= '\0'; return false;
    }
    *to= '\0';
    return true;
  }
  bool is_delimiter(char ch) const
  {
    return (signed char) ch < 0 ? false : m_delimiter[(uint32) ch];
  }
public:
  Delimiter()
   :m_has_delimiter_cached(false)
  {
    bzero(&m_delimiter, sizeof(m_delimiter));
  }
  bool has_delimiter() const
  {
    return m_has_delimiter_cached;
  }
  bool set_delimiter_unescape(const char *str)
  {
    m_has_delimiter_cached= false;
    for ( ; *str; str++)
    {
      if ((signed char) *str < 0)
        return true;
      if (*str == '\\')
      {
        char unescaped;
        str++;
        if (!*str || unescape(&unescaped, *str))
          return true;
        m_delimiter[(uint) unescaped]= true;
      }
      else
        m_delimiter[(uint) *str]= true;
    }
    m_has_delimiter_cached= has_delimiter_slow();
    return false;
  }
  size_t get_delimiter_length(const char *str, const char *end) const
  {
    const char *str0= str;
    for ( ; str < end; str++)
    {
      if (!is_delimiter(*str))
        break;
    }
    return str - str0;
  }
  size_t get_data_length(const char *str, const char *end) const
  {
    const char *str0= str;
    for ( ; str < end; str++)
    {
      if (is_delimiter(*str))
        break;
    }
    return str - str0;
  }
};


class Conv_inbuf
{
  const char *m_ptr;
  const char *m_end;
public:
  Conv_inbuf(const char *from, size_t length)
   :m_ptr(from), m_end(from + length)
  { }
  const char *ptr() const { return m_ptr; }
  const char *end() const { return m_end; }
  size_t length() const
  {
    return m_end - m_ptr;
  }
private:
  LEX_CSTRING get_prefix(size_t len)
  {
    LEX_CSTRING res;
    res.str= ptr();
    res.length= len;
    m_ptr+= len;
    return res;
  }
  LEX_CSTRING get_empty_string() const
  {
    static LEX_CSTRING str= {NULL, 0};
    return str;
  }
public:
  LEX_CSTRING get_delimiter_chunk(const Delimiter &delimiter)
  {
    if (!delimiter.has_delimiter())
      return get_empty_string();
    size_t len= delimiter.get_delimiter_length(ptr(), end());
    return get_prefix(len);
  }
  LEX_CSTRING get_data_chunk(const Delimiter &delimiter)
  {
    if (!delimiter.has_delimiter())
      return get_prefix(length());
    size_t len= delimiter.get_data_length(ptr(), end());
    return get_prefix(len);
  }
};


class Conv_outbuf: public Binary_string
{
public:
  bool alloc(size_t out_max_length)
  {
    if (out_max_length >= UINT_MAX32)
    {
      fprintf(stderr, "The data needs a too large output buffer\n");
      return true;
    }
    if (Binary_string::alloc((uint32) out_max_length))
    {
      fprintf(stderr, "Failed to allocate the output buffer\n");
      return true;
    }
    return false;
  }
};


class Conv: public String_copier, public Delimiter
{
  CHARSET_INFO *m_tocs;
  CHARSET_INFO *m_fromcs;
  bool m_continue;
public:
  Conv(CHARSET_INFO *tocs, CHARSET_INFO *fromcs, bool opt_continue)
   :m_tocs(tocs), m_fromcs(fromcs), m_continue(opt_continue)
  { }
  size_t out_buffer_max_length(size_t from_length) const
  {
    return from_length / m_fromcs->mbminlen * m_tocs->mbmaxlen;
  }
  bool convert_data(const char *from, size_t length);
  bool convert_binary_stream(FILE *file)
  {
    File_buffer buf;
    return buf.load_binary_stream(file) ||
           convert_data(buf.ptr(), buf.length());
  }
  bool convert_binary_file_by_name(const char *filename)
  {
    File_buffer buf;
    return buf.load_binary_file_by_name(filename)||
           convert_data(buf.ptr(), buf.length());
  }
private:
  void report_error(const char *from) const
  {
    if (well_formed_error_pos())
    {
      fflush(stdout);
      fprintf(stderr,
              "Illegal %s byte sequence at position %d\n",
              m_fromcs->cs_name.str,
              (uint) (well_formed_error_pos() - from));
    }
    else if (cannot_convert_error_pos())
    {
      fflush(stdout);
      fprintf(stderr,
              "Conversion from %s to %s failed at position %d\n",
              m_fromcs->cs_name.str, m_tocs->cs_name.str,
              (uint) (cannot_convert_error_pos() - from));
    }
  }
  size_t write(const char *str, size_t length) const
  {
    return my_fwrite(stdout, (uchar *) str, length, MY_WME);
  }
};


bool Conv::convert_data(const char *from, size_t from_length)
{
  Conv_inbuf inbuf(from, from_length);
  Conv_outbuf outbuf;

  if (outbuf.alloc(out_buffer_max_length(from_length)))
    return true;

  for ( ; ; )
  {
    LEX_CSTRING delim, data;
    
    delim= inbuf.get_delimiter_chunk(*this);
    if (delim.length)
      write(delim.str, delim.length);

    data= inbuf.get_data_chunk(*this);
    if (!data.length)
      break;
    size_t length= well_formed_copy(m_tocs,
                                    (char *) outbuf.ptr(),
                                    outbuf.alloced_length(),
                                    m_fromcs, data.str, data.length);
    outbuf.length((uint32) length);

    if (most_important_error_pos() && !m_continue)
    {
      report_error(from);
      return true;
    }
    write(outbuf.ptr(), outbuf.length());
  }
  return false;
}


class Session
{
public:
  Session(const char *prog)
  {
    MY_INIT(prog);
  }
  ~Session()
  {
    my_end(0);
  }
  void usage(void)
  {
    print_version();
    puts("Character set conversion utility for MariaDB");
    puts("Usage:");
    printf("%s [OPTION...] [FILE...]\n", my_progname);
    my_print_help(long_options);
  }
};


int main(int argc, char *argv[])
{
  Session session(argv[0]);
  CHARSET_INFO *charset_info_from= NULL;
  CHARSET_INFO *charset_info_to= NULL;

  if (handle_options(&argc, &argv, long_options, get_one_option))
  {
    session.usage();
    return 1;
  }

  if (!(charset_info_from= opt.csinfo_from()))
  {
    fprintf(stderr, "Character set %s is not supported\n", opt.m_charset_from);
    return 1;
  }

  if (!(charset_info_to= opt.csinfo_to()))
  {
    fprintf(stderr, "Character set %s is not supported\n", opt.m_charset_to);
    return 1;
  }

  Conv conv(charset_info_to, charset_info_from, opt.m_continue);
  if (opt.m_delimiter)
  {
    if (charset_info_from->mbminlen > 1 ||
        charset_info_to->mbminlen > 1)
    {
      fprintf(stderr, "--delimiter cannot be used with %s to %s conversion\n",
              charset_info_from->cs_name.str, charset_info_to->cs_name.str);
      return 1;
    }
    if (conv.set_delimiter_unescape(opt.m_delimiter))
    {
      fprintf(stderr, "Bad --delimiter value\n");
      return 1;
    }
  }

  if (argc == 0)
  {
    if (conv.convert_binary_stream(stdin))
      return 1;
  }
  else
  {
    for (int i= 0; i < argc; i++)
    {
      if (conv.convert_binary_file_by_name(argv[i]))
       return 1;
    }
  }

  return 0;
} /* main */

Messung V0.5 in Prozent
C=99 H=95 G=96

¤ Dauer der Verarbeitung: 0.14 Sekunden  (vorverarbeitet am  2026-10-08) ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover

NIST Cobol Testsuite

Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Open Source Software

     Quellcodebibliothek
     Eigene Quellcodes
     Fremde Quellcodes
     Suchen

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik

Statistik
#Sources=1126438
#Domains=1867298