mirror of
https://github.com/claunia/flac.git
synced 2025-12-16 18:54:26 +00:00
initial import
This commit is contained in:
23
include/FLAC++/Makefile.am
Normal file
23
include/FLAC++/Makefile.am
Normal file
@@ -0,0 +1,23 @@
|
||||
# libFLAC++ - Free Lossless Audio Codec library
|
||||
# Copyright (C) 2002 Josh Coalson
|
||||
#
|
||||
# This library is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU Library General Public
|
||||
# License as published by the Free Software Foundation; either
|
||||
# version 2 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
|
||||
# Library General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Library General Public
|
||||
# License along with this library; if not, write to the
|
||||
# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
# Boston, MA 02111-1307, USA.
|
||||
|
||||
includedir = ${prefix}/include/FLAC++
|
||||
|
||||
include_HEADERS = \
|
||||
all.h \
|
||||
metadata.h
|
||||
25
include/FLAC++/all.h
Normal file
25
include/FLAC++/all.h
Normal file
@@ -0,0 +1,25 @@
|
||||
/* libFLAC++ - Free Lossless Audio Codec library
|
||||
* Copyright (C) 2002 Josh Coalson
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 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
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef FLACPP__ALL_H
|
||||
#define FLACPP__ALL_H
|
||||
|
||||
#include "metadata.h"
|
||||
|
||||
#endif
|
||||
112
include/FLAC++/metadata.h
Normal file
112
include/FLAC++/metadata.h
Normal file
@@ -0,0 +1,112 @@
|
||||
/* libFLAC++ - Free Lossless Audio Codec library
|
||||
* Copyright (C) 2002 Josh Coalson
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 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
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef FLACPP__METADATA_H
|
||||
#define FLACPP__METADATA_H
|
||||
|
||||
#include "FLAC/metadata.h"
|
||||
|
||||
namespace FLAC {
|
||||
namespace Metadata {
|
||||
|
||||
// NOTE: When the get_*() methods return you a const pointer,
|
||||
// absolutely DO NOT write into it. Always use the set_*()
|
||||
// methods.
|
||||
|
||||
// base class for all metadata blocks
|
||||
class Prototype {
|
||||
protected:
|
||||
Prototype(::FLAC__StreamMetaData *object, bool copy);
|
||||
virtual ~Prototype();
|
||||
|
||||
::FLAC__StreamMetaData *object_;
|
||||
public:
|
||||
inline bool is_valid() const { return 0 != object_; }
|
||||
inline operator bool() const { return is_valid(); }
|
||||
|
||||
bool get_is_last() const;
|
||||
FLAC__MetaDataType get_type() const;
|
||||
unsigned get_length() const; // NOTE: does not include the header, per spec
|
||||
};
|
||||
|
||||
class StreamInfo : public Prototype {
|
||||
public:
|
||||
StreamInfo();
|
||||
StreamInfo(::FLAC__StreamMetaData *object, bool copy = false);
|
||||
~StreamInfo();
|
||||
|
||||
unsigned get_min_blocksize() const;
|
||||
unsigned get_max_blocksize() const;
|
||||
unsigned get_min_framesize() const;
|
||||
unsigned get_max_framesize() const;
|
||||
unsigned get_sample_rate() const;
|
||||
unsigned get_channels() const;
|
||||
unsigned get_bits_per_sample() const;
|
||||
FLAC__uint64 get_total_samples() const;
|
||||
const FLAC__byte *get_md5sum() const;
|
||||
|
||||
void set_min_blocksize(unsigned value);
|
||||
void set_max_blocksize(unsigned value);
|
||||
void set_min_framesize(unsigned value);
|
||||
void set_max_framesize(unsigned value);
|
||||
void set_sample_rate(unsigned value);
|
||||
void set_channels(unsigned value);
|
||||
void set_bits_per_sample(unsigned value);
|
||||
void set_total_samples(FLAC__uint64 value);
|
||||
void set_md5sum(const FLAC__byte value[16]);
|
||||
};
|
||||
|
||||
class Padding : public Prototype {
|
||||
public:
|
||||
Padding();
|
||||
Padding(::FLAC__StreamMetaData *object, bool copy = false);
|
||||
~Padding();
|
||||
};
|
||||
|
||||
class Application : public Prototype {
|
||||
public:
|
||||
Application();
|
||||
Application(::FLAC__StreamMetaData *object, bool copy = false);
|
||||
~Application();
|
||||
|
||||
const FLAC__byte *get_id() const;
|
||||
const FLAC__byte *get_data() const;
|
||||
|
||||
void set_id(FLAC__byte value[4]);
|
||||
bool set_data(FLAC__byte *data, unsigned length, bool copy = false);
|
||||
};
|
||||
|
||||
class SeekTable : public Prototype {
|
||||
public:
|
||||
SeekTable();
|
||||
SeekTable(::FLAC__StreamMetaData *object, bool copy = false);
|
||||
~SeekTable();
|
||||
};
|
||||
|
||||
class VorbisComment : public Prototype {
|
||||
public:
|
||||
VorbisComment();
|
||||
VorbisComment(::FLAC__StreamMetaData *object, bool copy = false);
|
||||
~VorbisComment();
|
||||
};
|
||||
|
||||
};
|
||||
};
|
||||
|
||||
#endif
|
||||
5
include/share/Makefile.am
Normal file
5
include/share/Makefile.am
Normal file
@@ -0,0 +1,5 @@
|
||||
## Process this file with automake to produce Makefile.in
|
||||
|
||||
AUTOMAKE_OPTIONS = foreign
|
||||
|
||||
EXTRA_DIST = utf8.h getopt.h
|
||||
169
include/share/getopt.h
Normal file
169
include/share/getopt.h
Normal file
@@ -0,0 +1,169 @@
|
||||
/* Declarations for getopt.
|
||||
Copyright (C) 1989,90,91,92,93,94,96,97,98 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public License as
|
||||
published by the Free Software Foundation; either version 2 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
The GNU C 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
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with the GNU C Library; see the file COPYING.LIB. If not,
|
||||
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
#ifndef _GETOPT_H
|
||||
|
||||
#ifndef __need_getopt
|
||||
# define _GETOPT_H 1
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* For communication from `getopt' to the caller.
|
||||
When `getopt' finds an option that takes an argument,
|
||||
the argument value is returned here.
|
||||
Also, when `ordering' is RETURN_IN_ORDER,
|
||||
each non-option ARGV-element is returned here. */
|
||||
|
||||
extern char *optarg;
|
||||
|
||||
/* Index in ARGV of the next element to be scanned.
|
||||
This is used for communication to and from the caller
|
||||
and for communication between successive calls to `getopt'.
|
||||
|
||||
On entry to `getopt', zero means this is the first call; initialize.
|
||||
|
||||
When `getopt' returns -1, this is the index of the first of the
|
||||
non-option elements that the caller should itself scan.
|
||||
|
||||
Otherwise, `optind' communicates from one call to the next
|
||||
how much of ARGV has been scanned so far. */
|
||||
|
||||
extern int optind;
|
||||
|
||||
/* Callers store zero here to inhibit the error message `getopt' prints
|
||||
for unrecognized options. */
|
||||
|
||||
extern int opterr;
|
||||
|
||||
/* Set to an option character which was unrecognized. */
|
||||
|
||||
extern int optopt;
|
||||
|
||||
#ifndef __need_getopt
|
||||
/* Describe the long-named options requested by the application.
|
||||
The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector
|
||||
of `struct option' terminated by an element containing a name which is
|
||||
zero.
|
||||
|
||||
The field `has_arg' is:
|
||||
no_argument (or 0) if the option does not take an argument,
|
||||
required_argument (or 1) if the option requires an argument,
|
||||
optional_argument (or 2) if the option takes an optional argument.
|
||||
|
||||
If the field `flag' is not NULL, it points to a variable that is set
|
||||
to the value given in the field `val' when the option is found, but
|
||||
left unchanged if the option is not found.
|
||||
|
||||
To have a long-named option do something other than set an `int' to
|
||||
a compiled-in constant, such as set a value from `optarg', set the
|
||||
option's `flag' field to zero and its `val' field to a nonzero
|
||||
value (the equivalent single-letter option character, if there is
|
||||
one). For long options that have a zero `flag' field, `getopt'
|
||||
returns the contents of the `val' field. */
|
||||
|
||||
struct option
|
||||
{
|
||||
# if defined __STDC__ && __STDC__
|
||||
const char *name;
|
||||
# else
|
||||
char *name;
|
||||
# endif
|
||||
/* has_arg can't be an enum because some compilers complain about
|
||||
type mismatches in all the code that assumes it is an int. */
|
||||
int has_arg;
|
||||
int *flag;
|
||||
int val;
|
||||
};
|
||||
|
||||
/* Names for the values of the `has_arg' field of `struct option'. */
|
||||
|
||||
# define no_argument 0
|
||||
# define required_argument 1
|
||||
# define optional_argument 2
|
||||
#endif /* need getopt */
|
||||
|
||||
|
||||
/* Get definitions and prototypes for functions to process the
|
||||
arguments in ARGV (ARGC of them, minus the program name) for
|
||||
options given in OPTS.
|
||||
|
||||
Return the option character from OPTS just read. Return -1 when
|
||||
there are no more options. For unrecognized options, or options
|
||||
missing arguments, `optopt' is set to the option letter, and '?' is
|
||||
returned.
|
||||
|
||||
The OPTS string is a list of characters which are recognized option
|
||||
letters, optionally followed by colons, specifying that that letter
|
||||
takes an argument, to be placed in `optarg'.
|
||||
|
||||
If a letter in OPTS is followed by two colons, its argument is
|
||||
optional. This behavior is specific to the GNU `getopt'.
|
||||
|
||||
The argument `--' causes premature termination of argument
|
||||
scanning, explicitly telling `getopt' that there are no more
|
||||
options.
|
||||
|
||||
If OPTS begins with `--', then non-option arguments are treated as
|
||||
arguments to the option '\0'. This behavior is specific to the GNU
|
||||
`getopt'. */
|
||||
|
||||
#if defined __STDC__ && __STDC__
|
||||
# ifdef __GNU_LIBRARY__
|
||||
/* Many other libraries have conflicting prototypes for getopt, with
|
||||
differences in the consts, in stdlib.h. To avoid compilation
|
||||
errors, only prototype getopt for the GNU C library. */
|
||||
extern int getopt (int __argc, char *const *__argv, const char *__shortopts);
|
||||
# else /* not __GNU_LIBRARY__ */
|
||||
extern int getopt ();
|
||||
# endif /* __GNU_LIBRARY__ */
|
||||
|
||||
# ifndef __need_getopt
|
||||
extern int getopt_long (int __argc, char *const *__argv, const char *__shortopts,
|
||||
const struct option *__longopts, int *__longind);
|
||||
extern int getopt_long_only (int __argc, char *const *__argv,
|
||||
const char *__shortopts,
|
||||
const struct option *__longopts, int *__longind);
|
||||
|
||||
/* Internal only. Users should not call this directly. */
|
||||
extern int _getopt_internal (int __argc, char *const *__argv,
|
||||
const char *__shortopts,
|
||||
const struct option *__longopts, int *__longind,
|
||||
int __long_only);
|
||||
# endif
|
||||
#else /* not __STDC__ */
|
||||
extern int getopt ();
|
||||
# ifndef __need_getopt
|
||||
extern int getopt_long ();
|
||||
extern int getopt_long_only ();
|
||||
|
||||
extern int _getopt_internal ();
|
||||
# endif
|
||||
#endif /* __STDC__ */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Make sure we later can get all the definitions and declarations. */
|
||||
#undef __need_getopt
|
||||
|
||||
#endif /* getopt.h */
|
||||
23
include/share/utf8.h
Normal file
23
include/share/utf8.h
Normal file
@@ -0,0 +1,23 @@
|
||||
|
||||
/*
|
||||
* Convert a string between UTF-8 and the locale's charset.
|
||||
* Invalid bytes are replaced by '#', and characters that are
|
||||
* not available in the target encoding are replaced by '?'.
|
||||
*
|
||||
* If the locale's charset is not set explicitly then it is
|
||||
* obtained using nl_langinfo(CODESET), where available, the
|
||||
* environment variable CHARSET, or assumed to be US-ASCII.
|
||||
*
|
||||
* Return value of conversion functions:
|
||||
*
|
||||
* -1 : memory allocation failed
|
||||
* 0 : data was converted exactly
|
||||
* 1 : valid data was converted approximately (using '?')
|
||||
* 2 : input was invalid (but still converted, using '#')
|
||||
* 3 : unknown encoding (but still converted, using '?')
|
||||
*/
|
||||
|
||||
void convert_set_charset(const char *charset);
|
||||
|
||||
int utf8_encode(const char *from, char **to);
|
||||
int utf8_decode(const char *from, char **to);
|
||||
25
src/libFLAC++/Makefile.am
Normal file
25
src/libFLAC++/Makefile.am
Normal file
@@ -0,0 +1,25 @@
|
||||
# libFLAC++ - Free Lossless Audio Codec library
|
||||
# Copyright (C) 2002 Josh Coalson
|
||||
#
|
||||
# This library is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU Library General Public
|
||||
# License as published by the Free Software Foundation; either
|
||||
# version 2 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
|
||||
# Library General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Library General Public
|
||||
# License along with this library; if not, write to the
|
||||
# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
# Boston, MA 02111-1307, USA.
|
||||
|
||||
lib_LTLIBRARIES = libFLAC++.la
|
||||
CFLAGS = @CFLAGS@
|
||||
|
||||
libFLAC++_la_LDFLAGS = -version-info 2:1:1
|
||||
|
||||
libFLAC++_la_SOURCES = \
|
||||
metadata.c
|
||||
31
src/libFLAC++/Makefile.lite
Normal file
31
src/libFLAC++/Makefile.lite
Normal file
@@ -0,0 +1,31 @@
|
||||
# libFLAC++ - Free Lossless Audio Codec library
|
||||
# Copyright (C) 2002 Josh Coalson
|
||||
#
|
||||
# This library is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU Library General Public
|
||||
# License as published by the Free Software Foundation; either
|
||||
# version 2 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
|
||||
# Library General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Library General Public
|
||||
# License along with this library; if not, write to the
|
||||
# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
# Boston, MA 02111-1307, USA.
|
||||
|
||||
#
|
||||
# GNU makefile
|
||||
#
|
||||
|
||||
LIB_NAME = libFLAC++
|
||||
INCLUDES = -I../../include
|
||||
|
||||
OBJS = \
|
||||
metadata.o
|
||||
|
||||
include ../../build/lib.mk
|
||||
|
||||
# DO NOT DELETE THIS LINE -- make depend depends on it.
|
||||
41
src/libFLAC++/Makefile.vc
Normal file
41
src/libFLAC++/Makefile.vc
Normal file
@@ -0,0 +1,41 @@
|
||||
# libFLAC++ - Free Lossless Audio Codec library
|
||||
# Copyright (C) 2002 Josh Coalson
|
||||
#
|
||||
# This library is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU Library General Public
|
||||
# License as published by the Free Software Foundation; either
|
||||
# version 2 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
|
||||
# Library General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Library General Public
|
||||
# License along with this library; if not, write to the
|
||||
# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
# Boston, MA 02111-1307, USA.
|
||||
|
||||
!include <win32.mak>
|
||||
|
||||
!IFDEF DEBUG
|
||||
.cc.obj:
|
||||
$(ccc) /D "_LIB" /GX $(cdebug) $(cflags) /I "..\..\include" -DSTRICT -YX /Od /D "_DEBUG" $<
|
||||
!else
|
||||
.cc.obj:
|
||||
$(ccc) /D "_LIB" /O2 $(crelease) $(cflags) /I "..\..\include" -DSTRICT -YX -DNODEBUG $<
|
||||
!endif
|
||||
|
||||
CC_FILES= \
|
||||
metadata.cc
|
||||
|
||||
OBJS= $(CC_FILES:.cc=.obj)
|
||||
|
||||
all: libFLAC++.lib
|
||||
|
||||
libFLAC++.lib: $(OBJS)
|
||||
link.exe -lib /nodefaultlib -out:../../obj/lib/$*.lib $(OBJS)
|
||||
|
||||
clean:
|
||||
-del *.obj ia32\*.obj *.pch
|
||||
-del ..\..\obj\lib\libFLAC++.lib ..\..\obj\lib\libFLAC++.pdb
|
||||
283
src/libFLAC++/metadata.cc
Normal file
283
src/libFLAC++/metadata.cc
Normal file
@@ -0,0 +1,283 @@
|
||||
/* libFLAC++ - Free Lossless Audio Codec library
|
||||
* Copyright (C) 2002 Josh Coalson
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 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
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include "FLAC++/metadata.h"
|
||||
#include "FLAC/assert.h"
|
||||
#include <string.h> // for memcpy()
|
||||
|
||||
namespace FLAC {
|
||||
namespace Metadata {
|
||||
|
||||
//
|
||||
// Prototype
|
||||
//
|
||||
|
||||
Prototype::Prototype(::FLAC__StreamMetaData *object, bool copy)
|
||||
{
|
||||
FLAC__ASSERT(0 != object);
|
||||
object_ = copy? ::FLAC__metadata_object_copy(object) : object;
|
||||
}
|
||||
|
||||
Prototype::~Prototype()
|
||||
{
|
||||
if(0 != object_)
|
||||
FLAC__metadata_object_delete(object_);
|
||||
}
|
||||
|
||||
bool Prototype::get_is_last() const
|
||||
{
|
||||
FLAC__ASSERT(is_valid());
|
||||
return object_->is_last;
|
||||
}
|
||||
|
||||
FLAC__MetaDataType Prototype::get_type() const
|
||||
{
|
||||
FLAC__ASSERT(is_valid());
|
||||
return object_->type;
|
||||
}
|
||||
|
||||
unsigned Prototype::get_length() const
|
||||
{
|
||||
FLAC__ASSERT(is_valid());
|
||||
return object_->length;
|
||||
}
|
||||
|
||||
//
|
||||
// StreamInfo
|
||||
//
|
||||
|
||||
StreamInfo::StreamInfo():
|
||||
Prototype(FLAC__metadata_object_new(FLAC__METADATA_TYPE_STREAMINFO), /*copy=*/false)
|
||||
{ }
|
||||
|
||||
StreamInfo::StreamInfo(::FLAC__StreamMetaData *object, bool copy):
|
||||
Prototype(object, copy)
|
||||
{ }
|
||||
|
||||
StreamInfo::~StreamInfo()
|
||||
{ }
|
||||
|
||||
unsigned StreamInfo::get_min_blocksize() const
|
||||
{
|
||||
FLAC__ASSERT(is_valid());
|
||||
return object_->data.stream_info.min_blocksize;
|
||||
}
|
||||
|
||||
unsigned StreamInfo::get_max_blocksize() const
|
||||
{
|
||||
FLAC__ASSERT(is_valid());
|
||||
return object_->data.stream_info.max_blocksize;
|
||||
}
|
||||
|
||||
unsigned StreamInfo::get_min_framesize() const
|
||||
{
|
||||
FLAC__ASSERT(is_valid());
|
||||
return object_->data.stream_info.min_framesize;
|
||||
}
|
||||
|
||||
unsigned StreamInfo::get_max_framesize() const
|
||||
{
|
||||
FLAC__ASSERT(is_valid());
|
||||
return object_->data.stream_info.max_framesize;
|
||||
}
|
||||
|
||||
unsigned StreamInfo::get_sample_rate() const
|
||||
{
|
||||
FLAC__ASSERT(is_valid());
|
||||
return object_->data.stream_info.sample_rate;
|
||||
}
|
||||
|
||||
unsigned StreamInfo::get_channels() const
|
||||
{
|
||||
FLAC__ASSERT(is_valid());
|
||||
return object_->data.stream_info.channels;
|
||||
}
|
||||
|
||||
unsigned StreamInfo::get_bits_per_sample() const
|
||||
{
|
||||
FLAC__ASSERT(is_valid());
|
||||
return object_->data.stream_info.bits_per_sample;
|
||||
}
|
||||
|
||||
FLAC__uint64 StreamInfo::get_total_samples() const
|
||||
{
|
||||
FLAC__ASSERT(is_valid());
|
||||
return object_->data.stream_info.total_samples;
|
||||
}
|
||||
|
||||
const FLAC__byte *StreamInfo::get_md5sum() const
|
||||
{
|
||||
FLAC__ASSERT(is_valid());
|
||||
return object_->data.stream_info.md5sum;
|
||||
}
|
||||
|
||||
void StreamInfo::set_min_blocksize(unsigned value)
|
||||
{
|
||||
FLAC__ASSERT(is_valid());
|
||||
FLAC__ASSERT(value >= FLAC__MIN_BLOCK_SIZE);
|
||||
FLAC__ASSERT(value <= FLAC__MAX_BLOCK_SIZE);
|
||||
object_->data.stream_info.min_blocksize = value;
|
||||
}
|
||||
|
||||
void StreamInfo::set_max_blocksize(unsigned value)
|
||||
{
|
||||
FLAC__ASSERT(is_valid());
|
||||
FLAC__ASSERT(value >= FLAC__MIN_BLOCK_SIZE);
|
||||
FLAC__ASSERT(value <= FLAC__MAX_BLOCK_SIZE);
|
||||
object_->data.stream_info.max_blocksize = value;
|
||||
}
|
||||
|
||||
void StreamInfo::set_min_framesize(unsigned value)
|
||||
{
|
||||
FLAC__ASSERT(is_valid());
|
||||
FLAC__ASSERT(value < (1u < FLAC__STREAM_METADATA_STREAMINFO_MIN_FRAME_SIZE_LEN));
|
||||
object_->data.stream_info.min_framesize = value;
|
||||
}
|
||||
|
||||
void StreamInfo::set_max_framesize(unsigned value)
|
||||
{
|
||||
FLAC__ASSERT(is_valid());
|
||||
FLAC__ASSERT(value < (1u < FLAC__STREAM_METADATA_STREAMINFO_MAX_FRAME_SIZE_LEN));
|
||||
object_->data.stream_info.max_framesize = value;
|
||||
}
|
||||
|
||||
void StreamInfo::set_sample_rate(unsigned value)
|
||||
{
|
||||
FLAC__ASSERT(is_valid());
|
||||
FLAC__ASSERT(FLAC__format_is_valid_sample_rate(value));
|
||||
object_->data.stream_info.sample_rate = value;
|
||||
}
|
||||
|
||||
void StreamInfo::set_channels(unsigned value)
|
||||
{
|
||||
FLAC__ASSERT(is_valid());
|
||||
FLAC__ASSERT(value > 0);
|
||||
FLAC__ASSERT(value <= FLAC__MAX_CHANNELS);
|
||||
object_->data.stream_info.channels = value;
|
||||
}
|
||||
|
||||
void StreamInfo::set_bits_per_sample(unsigned value)
|
||||
{
|
||||
FLAC__ASSERT(is_valid());
|
||||
FLAC__ASSERT(value >= FLAC__MIN_BITS_PER_SAMPLE);
|
||||
FLAC__ASSERT(value <= FLAC__MAX_BITS_PER_SAMPLE);
|
||||
object_->data.stream_info.bits_per_sample = value;
|
||||
}
|
||||
|
||||
void StreamInfo::set_total_samples(FLAC__uint64 value)
|
||||
{
|
||||
FLAC__ASSERT(is_valid());
|
||||
FLAC__ASSERT(value < (1u << FLAC__STREAM_METADATA_STREAMINFO_TOTAL_SAMPLES_LEN));
|
||||
object_->data.stream_info.total_samples = value;
|
||||
}
|
||||
|
||||
void StreamInfo::set_md5sum(const FLAC__byte value[16])
|
||||
{
|
||||
FLAC__ASSERT(is_valid());
|
||||
FLAC__ASSERT(0 != value);
|
||||
memcpy(object_->data.stream_info.md5sum, value, 16);
|
||||
}
|
||||
|
||||
//
|
||||
// Padding
|
||||
//
|
||||
|
||||
Padding::Padding():
|
||||
Prototype(FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING), /*copy=*/false)
|
||||
{ }
|
||||
|
||||
Padding::Padding(::FLAC__StreamMetaData *object, bool copy):
|
||||
Prototype(object, copy)
|
||||
{ }
|
||||
|
||||
Padding::~Padding()
|
||||
{ }
|
||||
|
||||
//
|
||||
// Application
|
||||
//
|
||||
|
||||
Application::Application():
|
||||
Prototype(FLAC__metadata_object_new(FLAC__METADATA_TYPE_APPLICATION), /*copy=*/false)
|
||||
{ }
|
||||
|
||||
Application::Application(::FLAC__StreamMetaData *object, bool copy):
|
||||
Prototype(object, copy)
|
||||
{ }
|
||||
|
||||
Application::~Application()
|
||||
{ }
|
||||
|
||||
const FLAC__byte *Application::get_id() const
|
||||
{
|
||||
FLAC__ASSERT(is_valid());
|
||||
return object_->data.application.id;
|
||||
}
|
||||
|
||||
const FLAC__byte *Application::get_data() const
|
||||
{
|
||||
FLAC__ASSERT(is_valid());
|
||||
return object_->data.application.data;
|
||||
}
|
||||
|
||||
void Application::set_id(FLAC__byte value[4])
|
||||
{
|
||||
FLAC__ASSERT(is_valid());
|
||||
FLAC__ASSERT(0 != value);
|
||||
memcpy(object_->data.application.id, value, 4);
|
||||
}
|
||||
|
||||
bool Application::set_data(FLAC__byte *data, unsigned length, bool copy)
|
||||
{
|
||||
FLAC__ASSERT(is_valid());
|
||||
return FLAC__metadata_object_application_set_data(object_, data, length, copy);
|
||||
}
|
||||
|
||||
//
|
||||
// SeekTable
|
||||
//
|
||||
|
||||
SeekTable::SeekTable():
|
||||
Prototype(FLAC__metadata_object_new(FLAC__METADATA_TYPE_SEEKTABLE), /*copy=*/false)
|
||||
{ }
|
||||
|
||||
SeekTable::SeekTable(::FLAC__StreamMetaData *object, bool copy):
|
||||
Prototype(object, copy)
|
||||
{ }
|
||||
|
||||
SeekTable::~SeekTable()
|
||||
{ }
|
||||
|
||||
//
|
||||
// VorbisComment
|
||||
//
|
||||
|
||||
VorbisComment::VorbisComment():
|
||||
Prototype(FLAC__metadata_object_new(FLAC__METADATA_TYPE_VORBIS_COMMENT), /*copy=*/false)
|
||||
{ }
|
||||
|
||||
VorbisComment::VorbisComment(::FLAC__StreamMetaData *object, bool copy):
|
||||
Prototype(object, copy)
|
||||
{ }
|
||||
|
||||
VorbisComment::~VorbisComment()
|
||||
{ }
|
||||
|
||||
};
|
||||
};
|
||||
19
src/share/Makefile.am
Normal file
19
src/share/Makefile.am
Normal file
@@ -0,0 +1,19 @@
|
||||
## Process this file with automake to produce Makefile.in
|
||||
|
||||
AUTOMAKE_OPTIONS = foreign
|
||||
|
||||
INCLUDES = -I$(top_srcdir)/include/share
|
||||
|
||||
noinst_LIBRARIES = libutf8.a libgetopt.a
|
||||
|
||||
libutf8_a_SOURCES = charset.c charset.h iconvert.c utf8.c
|
||||
|
||||
libgetopt_a_SOURCES = getopt.c getopt1.c
|
||||
|
||||
EXTRA_DIST = charmaps.h makemap.c charset_test.c charsetmap.h
|
||||
|
||||
debug:
|
||||
$(MAKE) all CFLAGS="@DEBUG@"
|
||||
|
||||
profile:
|
||||
$(MAKE) all CFLAGS="@PROFILE@"
|
||||
14
src/share/Makefile.lite
Normal file
14
src/share/Makefile.lite
Normal file
@@ -0,0 +1,14 @@
|
||||
#
|
||||
# GNU makefile
|
||||
#
|
||||
|
||||
LIB_NAME = libgetopt
|
||||
INCLUDES = -I../../include/share
|
||||
|
||||
OBJS = \
|
||||
getopt.o \
|
||||
getopt1.o
|
||||
|
||||
include ../../build/lib.mk
|
||||
|
||||
# DO NOT DELETE THIS LINE -- make depend depends on it.
|
||||
4
src/share/README
Normal file
4
src/share/README
Normal file
@@ -0,0 +1,4 @@
|
||||
This directory is shamelessly copied from vorbistools. It contains two
|
||||
convenience libraries, one for manipulating UTF-8 strings (GPL) and one
|
||||
for implementing getopt (LGPL). libFLAC does not link to either; the
|
||||
only FLAC tools that do are GPL'ed.
|
||||
57
src/share/charmaps.h
Normal file
57
src/share/charmaps.h
Normal file
@@ -0,0 +1,57 @@
|
||||
|
||||
/*
|
||||
* If you need to generate more maps, use makemap.c on a system
|
||||
* with a decent iconv.
|
||||
*/
|
||||
|
||||
static const unsigned short mapping_iso_8859_2[256] = {
|
||||
0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
|
||||
0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f,
|
||||
0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017,
|
||||
0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f,
|
||||
0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
|
||||
0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
|
||||
0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
|
||||
0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
|
||||
0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
|
||||
0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
|
||||
0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
|
||||
0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f,
|
||||
0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
|
||||
0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f,
|
||||
0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
|
||||
0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x007f,
|
||||
0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087,
|
||||
0x0088, 0x0089, 0x008a, 0x008b, 0x008c, 0x008d, 0x008e, 0x008f,
|
||||
0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097,
|
||||
0x0098, 0x0099, 0x009a, 0x009b, 0x009c, 0x009d, 0x009e, 0x009f,
|
||||
0x00a0, 0x0104, 0x02d8, 0x0141, 0x00a4, 0x013d, 0x015a, 0x00a7,
|
||||
0x00a8, 0x0160, 0x015e, 0x0164, 0x0179, 0x00ad, 0x017d, 0x017b,
|
||||
0x00b0, 0x0105, 0x02db, 0x0142, 0x00b4, 0x013e, 0x015b, 0x02c7,
|
||||
0x00b8, 0x0161, 0x015f, 0x0165, 0x017a, 0x02dd, 0x017e, 0x017c,
|
||||
0x0154, 0x00c1, 0x00c2, 0x0102, 0x00c4, 0x0139, 0x0106, 0x00c7,
|
||||
0x010c, 0x00c9, 0x0118, 0x00cb, 0x011a, 0x00cd, 0x00ce, 0x010e,
|
||||
0x0110, 0x0143, 0x0147, 0x00d3, 0x00d4, 0x0150, 0x00d6, 0x00d7,
|
||||
0x0158, 0x016e, 0x00da, 0x0170, 0x00dc, 0x00dd, 0x0162, 0x00df,
|
||||
0x0155, 0x00e1, 0x00e2, 0x0103, 0x00e4, 0x013a, 0x0107, 0x00e7,
|
||||
0x010d, 0x00e9, 0x0119, 0x00eb, 0x011b, 0x00ed, 0x00ee, 0x010f,
|
||||
0x0111, 0x0144, 0x0148, 0x00f3, 0x00f4, 0x0151, 0x00f6, 0x00f7,
|
||||
0x0159, 0x016f, 0x00fa, 0x0171, 0x00fc, 0x00fd, 0x0163, 0x02d9
|
||||
};
|
||||
|
||||
static struct {
|
||||
const char *name;
|
||||
const unsigned short *map;
|
||||
struct charset *charset;
|
||||
} maps[] = {
|
||||
{ "ISO-8859-2", mapping_iso_8859_2, 0 },
|
||||
{ 0, 0, 0 }
|
||||
};
|
||||
|
||||
static const struct {
|
||||
const char *bad;
|
||||
const char *good;
|
||||
} names[] = {
|
||||
{ "ANSI_X3.4-1968", "us-ascii" },
|
||||
{ 0, 0 }
|
||||
};
|
||||
521
src/share/charset.c
Normal file
521
src/share/charset.c
Normal file
@@ -0,0 +1,521 @@
|
||||
/*
|
||||
* Copyright (C) 2001 Edmund Grimley Evans <edmundo@rano.org>
|
||||
*
|
||||
* 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; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/*
|
||||
* See the corresponding header file for a description of the functions
|
||||
* that this file provides.
|
||||
*
|
||||
* This was first written for Ogg Vorbis but could be of general use.
|
||||
*
|
||||
* The only deliberate assumption about data sizes is that a short has
|
||||
* at least 16 bits, but this code has only been tested on systems with
|
||||
* 8-bit char, 16-bit short and 32-bit int.
|
||||
*/
|
||||
|
||||
#ifndef HAVE_ICONV /* should be ifdef USE_CHARSET_CONVERT */
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "charset.h"
|
||||
|
||||
#include "charmaps.h"
|
||||
|
||||
/*
|
||||
* This is like the standard strcasecmp, but it does not depend
|
||||
* on the locale. Locale-dependent functions can be dangerous:
|
||||
* we once had a bug involving strcasecmp("iso", "ISO") in a
|
||||
* Turkish locale!
|
||||
*
|
||||
* (I'm not really sure what the official standard says
|
||||
* about the sign of strcasecmp("Z", "["), but usually
|
||||
* we're only interested in whether it's zero.)
|
||||
*/
|
||||
|
||||
static int ascii_strcasecmp(const char *s1, const char *s2)
|
||||
{
|
||||
char c1, c2;
|
||||
|
||||
for (;; s1++, s2++) {
|
||||
if (!*s1 || !*s1)
|
||||
break;
|
||||
if (*s1 == *s2)
|
||||
continue;
|
||||
c1 = *s1;
|
||||
if ('a' <= c1 && c1 <= 'z')
|
||||
c1 += 'A' - 'a';
|
||||
c2 = *s2;
|
||||
if ('a' <= c2 && c2 <= 'z')
|
||||
c2 += 'A' - 'a';
|
||||
if (c1 != c2)
|
||||
break;
|
||||
}
|
||||
return (unsigned char)*s1 - (unsigned char)*s2;
|
||||
}
|
||||
|
||||
/*
|
||||
* UTF-8 equivalents of the C library's wctomb() and mbtowc().
|
||||
*/
|
||||
|
||||
int utf8_mbtowc(int *pwc, const char *s, size_t n)
|
||||
{
|
||||
unsigned char c;
|
||||
int wc, i, k;
|
||||
|
||||
if (!n || !s)
|
||||
return 0;
|
||||
|
||||
c = *s;
|
||||
if (c < 0x80) {
|
||||
if (pwc)
|
||||
*pwc = c;
|
||||
return c ? 1 : 0;
|
||||
}
|
||||
else if (c < 0xc2)
|
||||
return -1;
|
||||
else if (c < 0xe0) {
|
||||
if (n >= 2 && (s[1] & 0xc0) == 0x80) {
|
||||
if (pwc)
|
||||
*pwc = ((c & 0x1f) << 6) | (s[1] & 0x3f);
|
||||
return 2;
|
||||
}
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
else if (c < 0xf0)
|
||||
k = 3;
|
||||
else if (c < 0xf8)
|
||||
k = 4;
|
||||
else if (c < 0xfc)
|
||||
k = 5;
|
||||
else if (c < 0xfe)
|
||||
k = 6;
|
||||
else
|
||||
return -1;
|
||||
|
||||
if (n < k)
|
||||
return -1;
|
||||
wc = *s++ & ((1 << (7 - k)) - 1);
|
||||
for (i = 1; i < k; i++) {
|
||||
if ((*s & 0xc0) != 0x80)
|
||||
return -1;
|
||||
wc = (wc << 6) | (*s++ & 0x3f);
|
||||
}
|
||||
if (wc < (1 << (5 * k - 4)))
|
||||
return -1;
|
||||
if (pwc)
|
||||
*pwc = wc;
|
||||
return k;
|
||||
}
|
||||
|
||||
int utf8_wctomb(char *s, int wc1)
|
||||
{
|
||||
unsigned int wc = wc1;
|
||||
|
||||
if (!s)
|
||||
return 0;
|
||||
if (wc < (1 << 7)) {
|
||||
*s++ = wc;
|
||||
return 1;
|
||||
}
|
||||
else if (wc < (1 << 11)) {
|
||||
*s++ = 0xc0 | (wc >> 6);
|
||||
*s++ = 0x80 | (wc & 0x3f);
|
||||
return 2;
|
||||
}
|
||||
else if (wc < (1 << 16)) {
|
||||
*s++ = 0xe0 | (wc >> 12);
|
||||
*s++ = 0x80 | ((wc >> 6) & 0x3f);
|
||||
*s++ = 0x80 | (wc & 0x3f);
|
||||
return 3;
|
||||
}
|
||||
else if (wc < (1 << 21)) {
|
||||
*s++ = 0xf0 | (wc >> 18);
|
||||
*s++ = 0x80 | ((wc >> 12) & 0x3f);
|
||||
*s++ = 0x80 | ((wc >> 6) & 0x3f);
|
||||
*s++ = 0x80 | (wc & 0x3f);
|
||||
return 4;
|
||||
}
|
||||
else if (wc < (1 << 26)) {
|
||||
*s++ = 0xf8 | (wc >> 24);
|
||||
*s++ = 0x80 | ((wc >> 18) & 0x3f);
|
||||
*s++ = 0x80 | ((wc >> 12) & 0x3f);
|
||||
*s++ = 0x80 | ((wc >> 6) & 0x3f);
|
||||
*s++ = 0x80 | (wc & 0x3f);
|
||||
return 5;
|
||||
}
|
||||
else if (wc < (1 << 31)) {
|
||||
*s++ = 0xfc | (wc >> 30);
|
||||
*s++ = 0x80 | ((wc >> 24) & 0x3f);
|
||||
*s++ = 0x80 | ((wc >> 18) & 0x3f);
|
||||
*s++ = 0x80 | ((wc >> 12) & 0x3f);
|
||||
*s++ = 0x80 | ((wc >> 6) & 0x3f);
|
||||
*s++ = 0x80 | (wc & 0x3f);
|
||||
return 6;
|
||||
}
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* The charset "object" and methods.
|
||||
*/
|
||||
|
||||
struct charset {
|
||||
int max;
|
||||
int (*mbtowc)(void *table, int *pwc, const char *s, size_t n);
|
||||
int (*wctomb)(void *table, char *s, int wc);
|
||||
void *map;
|
||||
};
|
||||
|
||||
int charset_mbtowc(struct charset *charset, int *pwc, const char *s, size_t n)
|
||||
{
|
||||
return (*charset->mbtowc)(charset->map, pwc, s, n);
|
||||
}
|
||||
|
||||
int charset_wctomb(struct charset *charset, char *s, int wc)
|
||||
{
|
||||
return (*charset->wctomb)(charset->map, s, wc);
|
||||
}
|
||||
|
||||
int charset_max(struct charset *charset)
|
||||
{
|
||||
return charset->max;
|
||||
}
|
||||
|
||||
/*
|
||||
* Implementation of UTF-8.
|
||||
*/
|
||||
|
||||
static int mbtowc_utf8(void *map, int *pwc, const char *s, size_t n)
|
||||
{
|
||||
return utf8_mbtowc(pwc, s, n);
|
||||
}
|
||||
|
||||
static int wctomb_utf8(void *map, char *s, int wc)
|
||||
{
|
||||
return utf8_wctomb(s, wc);
|
||||
}
|
||||
|
||||
/*
|
||||
* Implementation of US-ASCII.
|
||||
* Probably on most architectures this compiles to less than 256 bytes
|
||||
* of code, so we can save space by not having a table for this one.
|
||||
*/
|
||||
|
||||
static int mbtowc_ascii(void *map, int *pwc, const char *s, size_t n)
|
||||
{
|
||||
int wc;
|
||||
|
||||
if (!n || !s)
|
||||
return 0;
|
||||
wc = (unsigned char)*s;
|
||||
if (wc & ~0x7f)
|
||||
return -1;
|
||||
if (pwc)
|
||||
*pwc = wc;
|
||||
return wc ? 1 : 0;
|
||||
}
|
||||
|
||||
static int wctomb_ascii(void *map, char *s, int wc)
|
||||
{
|
||||
if (!s)
|
||||
return 0;
|
||||
if (wc & ~0x7f)
|
||||
return -1;
|
||||
*s = wc;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Implementation of ISO-8859-1.
|
||||
* Probably on most architectures this compiles to less than 256 bytes
|
||||
* of code, so we can save space by not having a table for this one.
|
||||
*/
|
||||
|
||||
static int mbtowc_iso1(void *map, int *pwc, const char *s, size_t n)
|
||||
{
|
||||
int wc;
|
||||
|
||||
if (!n || !s)
|
||||
return 0;
|
||||
wc = (unsigned char)*s;
|
||||
if (wc & ~0xff)
|
||||
return -1;
|
||||
if (pwc)
|
||||
*pwc = wc;
|
||||
return wc ? 1 : 0;
|
||||
}
|
||||
|
||||
static int wctomb_iso1(void *map, char *s, int wc)
|
||||
{
|
||||
if (!s)
|
||||
return 0;
|
||||
if (wc & ~0xff)
|
||||
return -1;
|
||||
*s = wc;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Implementation of any 8-bit charset.
|
||||
*/
|
||||
|
||||
struct map {
|
||||
const unsigned short *from;
|
||||
struct inverse_map *to;
|
||||
};
|
||||
|
||||
static int mbtowc_8bit(void *map1, int *pwc, const char *s, size_t n)
|
||||
{
|
||||
struct map *map = map1;
|
||||
unsigned short wc;
|
||||
|
||||
if (!n || !s)
|
||||
return 0;
|
||||
wc = map->from[(unsigned char)*s];
|
||||
if (wc == 0xffff)
|
||||
return -1;
|
||||
if (pwc)
|
||||
*pwc = (int)wc;
|
||||
return wc ? 1 : 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* For the inverse map we use a hash table, which has the advantages
|
||||
* of small constant memory requirement and simple memory allocation,
|
||||
* but the disadvantage of slow conversion in the worst case.
|
||||
* If you need real-time performance while letting a potentially
|
||||
* malicious user define their own map, then the method used in
|
||||
* linux/drivers/char/consolemap.c would be more appropriate.
|
||||
*/
|
||||
|
||||
struct inverse_map {
|
||||
unsigned char first[256];
|
||||
unsigned char next[256];
|
||||
};
|
||||
|
||||
/*
|
||||
* The simple hash is good enough for this application.
|
||||
* Use the alternative trivial hashes for testing.
|
||||
*/
|
||||
#define HASH(i) ((i) & 0xff)
|
||||
/* #define HASH(i) 0 */
|
||||
/* #define HASH(i) 99 */
|
||||
|
||||
static struct inverse_map *make_inverse_map(const unsigned short *from)
|
||||
{
|
||||
struct inverse_map *to;
|
||||
char used[256];
|
||||
int i, j, k;
|
||||
|
||||
to = (struct inverse_map *)malloc(sizeof(struct inverse_map));
|
||||
if (!to)
|
||||
return 0;
|
||||
for (i = 0; i < 256; i++)
|
||||
to->first[i] = to->next[i] = used[i] = 0;
|
||||
for (i = 255; i >= 0; i--)
|
||||
if (from[i] != 0xffff) {
|
||||
k = HASH(from[i]);
|
||||
to->next[i] = to->first[k];
|
||||
to->first[k] = i;
|
||||
used[k] = 1;
|
||||
}
|
||||
|
||||
/* Point the empty buckets at an empty list. */
|
||||
for (i = 0; i < 256; i++)
|
||||
if (!to->next[i])
|
||||
break;
|
||||
if (i < 256)
|
||||
for (j = 0; j < 256; j++)
|
||||
if (!used[j])
|
||||
to->first[j] = i;
|
||||
|
||||
return to;
|
||||
}
|
||||
|
||||
int wctomb_8bit(void *map1, char *s, int wc1)
|
||||
{
|
||||
struct map *map = map1;
|
||||
unsigned short wc = wc1;
|
||||
int i;
|
||||
|
||||
if (!s)
|
||||
return 0;
|
||||
|
||||
if (wc1 & ~0xffff)
|
||||
return -1;
|
||||
|
||||
if (1) /* Change 1 to 0 to test the case where malloc fails. */
|
||||
if (!map->to)
|
||||
map->to = make_inverse_map(map->from);
|
||||
|
||||
if (map->to) {
|
||||
/* Use the inverse map. */
|
||||
i = map->to->first[HASH(wc)];
|
||||
for (;;) {
|
||||
if (map->from[i] == wc) {
|
||||
*s = i;
|
||||
return 1;
|
||||
}
|
||||
if (!(i = map->to->next[i]))
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* We don't have an inverse map, so do a linear search. */
|
||||
for (i = 0; i < 256; i++)
|
||||
if (map->from[i] == wc) {
|
||||
*s = i;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* The "constructor" charset_find().
|
||||
*/
|
||||
|
||||
struct charset charset_utf8 = {
|
||||
6,
|
||||
&mbtowc_utf8,
|
||||
&wctomb_utf8,
|
||||
0
|
||||
};
|
||||
|
||||
struct charset charset_iso1 = {
|
||||
1,
|
||||
&mbtowc_iso1,
|
||||
&wctomb_iso1,
|
||||
0
|
||||
};
|
||||
|
||||
struct charset charset_ascii = {
|
||||
1,
|
||||
&mbtowc_ascii,
|
||||
&wctomb_ascii,
|
||||
0
|
||||
};
|
||||
|
||||
struct charset *charset_find(const char *code)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* Find good (MIME) name. */
|
||||
for (i = 0; names[i].bad; i++)
|
||||
if (!ascii_strcasecmp(code, names[i].bad)) {
|
||||
code = names[i].good;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Recognise some charsets for which we avoid using a table. */
|
||||
if (!ascii_strcasecmp(code, "UTF-8"))
|
||||
return &charset_utf8;
|
||||
if (!ascii_strcasecmp(code, "US-ASCII"))
|
||||
return &charset_ascii;
|
||||
if (!ascii_strcasecmp(code, "ISO-8859-1"))
|
||||
return &charset_iso1;
|
||||
|
||||
/* Look for a mapping for a simple 8-bit encoding. */
|
||||
for (i = 0; maps[i].name; i++)
|
||||
if (!ascii_strcasecmp(code, maps[i].name)) {
|
||||
if (!maps[i].charset) {
|
||||
maps[i].charset = (struct charset *)malloc(sizeof(struct charset));
|
||||
if (maps[i].charset) {
|
||||
struct map *map = (struct map *)malloc(sizeof(struct map));
|
||||
if (!map) {
|
||||
free(maps[i].charset);
|
||||
maps[i].charset = 0;
|
||||
}
|
||||
else {
|
||||
maps[i].charset->max = 1;
|
||||
maps[i].charset->mbtowc = &mbtowc_8bit;
|
||||
maps[i].charset->wctomb = &wctomb_8bit;
|
||||
maps[i].charset->map = map;
|
||||
map->from = maps[i].map;
|
||||
map->to = 0; /* inverse mapping is created when required */
|
||||
}
|
||||
}
|
||||
}
|
||||
return maps[i].charset;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Function to convert a buffer from one encoding to another.
|
||||
* Invalid bytes are replaced by '#', and characters that are
|
||||
* not available in the target encoding are replaced by '?'.
|
||||
* Each of TO and TOLEN may be zero, if the result is not needed.
|
||||
* The output buffer is null-terminated, so it is all right to
|
||||
* use charset_convert(fromcode, tocode, s, strlen(s), &t, 0).
|
||||
*/
|
||||
|
||||
int charset_convert(const char *fromcode, const char *tocode,
|
||||
const char *from, size_t fromlen,
|
||||
char **to, size_t *tolen)
|
||||
{
|
||||
int ret = 0;
|
||||
struct charset *charset1, *charset2;
|
||||
char *tobuf, *p, *newbuf;
|
||||
int i, j, wc;
|
||||
|
||||
charset1 = charset_find(fromcode);
|
||||
charset2 = charset_find(tocode);
|
||||
if (!charset1 || !charset2 )
|
||||
return -1;
|
||||
|
||||
tobuf = (char *)malloc(fromlen * charset2->max + 1);
|
||||
if (!tobuf)
|
||||
return -2;
|
||||
|
||||
for (p = tobuf; fromlen; from += i, fromlen -= i, p += j) {
|
||||
i = charset_mbtowc(charset1, &wc, from, fromlen);
|
||||
if (!i)
|
||||
i = 1;
|
||||
else if (i == -1) {
|
||||
i = 1;
|
||||
wc = '#';
|
||||
ret = 2;
|
||||
}
|
||||
j = charset_wctomb(charset2, p, wc);
|
||||
if (j == -1) {
|
||||
if (!ret)
|
||||
ret = 1;
|
||||
j = charset_wctomb(charset2, p, '?');
|
||||
if (j == -1)
|
||||
j = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (tolen)
|
||||
*tolen = p - tobuf;
|
||||
*p++ = '\0';
|
||||
if (to) {
|
||||
newbuf = realloc(tobuf, p - tobuf);
|
||||
*to = newbuf ? newbuf : tobuf;
|
||||
}
|
||||
else
|
||||
free(tobuf);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif /* USE_CHARSET_ICONV */
|
||||
72
src/share/charset.h
Normal file
72
src/share/charset.h
Normal file
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* Copyright (C) 2001 Edmund Grimley Evans <edmundo@rano.org>
|
||||
*
|
||||
* 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; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
/*
|
||||
* These functions are like the C library's mbtowc() and wctomb(),
|
||||
* but instead of depending on the locale they always work in UTF-8,
|
||||
* and they use int instead of wchar_t.
|
||||
*/
|
||||
|
||||
int utf8_mbtowc(int *pwc, const char *s, size_t n);
|
||||
int utf8_wctomb(char *s, int wc);
|
||||
|
||||
/*
|
||||
* This is an object-oriented version of mbtowc() and wctomb().
|
||||
* The caller first uses charset_find() to get a pointer to struct
|
||||
* charset, then uses the mbtowc() and wctomb() methods on it.
|
||||
* The function charset_max() gives the maximum length of a
|
||||
* multibyte character in that encoding.
|
||||
* This API is only appropriate for stateless encodings like UTF-8
|
||||
* or ISO-8859-3, but I have no intention of implementing anything
|
||||
* other than UTF-8 and 8-bit encodings.
|
||||
*
|
||||
* MINOR BUG: If there is no memory charset_find() may return 0 and
|
||||
* there is no way to distinguish this case from an unknown encoding.
|
||||
*/
|
||||
|
||||
struct charset;
|
||||
|
||||
struct charset *charset_find(const char *code);
|
||||
|
||||
int charset_mbtowc(struct charset *charset, int *pwc, const char *s, size_t n);
|
||||
int charset_wctomb(struct charset *charset, char *s, int wc);
|
||||
int charset_max(struct charset *charset);
|
||||
|
||||
/*
|
||||
* Function to convert a buffer from one encoding to another.
|
||||
* Invalid bytes are replaced by '#', and characters that are
|
||||
* not available in the target encoding are replaced by '?'.
|
||||
* Each of TO and TOLEN may be zero if the result is not wanted.
|
||||
* The input or output may contain null bytes, but the output
|
||||
* buffer is also null-terminated, so it is all right to
|
||||
* use charset_convert(fromcode, tocode, s, strlen(s), &t, 0).
|
||||
*
|
||||
* Return value:
|
||||
*
|
||||
* -2 : memory allocation failed
|
||||
* -1 : unknown encoding
|
||||
* 0 : data was converted exactly
|
||||
* 1 : valid data was converted approximately (using '?')
|
||||
* 2 : input was invalid (but still converted, using '#')
|
||||
*/
|
||||
|
||||
int charset_convert(const char *fromcode, const char *tocode,
|
||||
const char *from, size_t fromlen,
|
||||
char **to, size_t *tolen);
|
||||
259
src/share/charset_test.c
Normal file
259
src/share/charset_test.c
Normal file
@@ -0,0 +1,259 @@
|
||||
/*
|
||||
* Copyright (C) 2001 Edmund Grimley Evans <edmundo@rano.org>
|
||||
*
|
||||
* 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; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "charset.h"
|
||||
|
||||
void test_any(struct charset *charset)
|
||||
{
|
||||
int wc;
|
||||
char s[2];
|
||||
|
||||
assert(charset);
|
||||
|
||||
/* Decoder */
|
||||
|
||||
assert(charset_mbtowc(charset, 0, 0, 0) == 0);
|
||||
assert(charset_mbtowc(charset, 0, 0, 1) == 0);
|
||||
assert(charset_mbtowc(charset, 0, (char *)(-1), 0) == 0);
|
||||
|
||||
assert(charset_mbtowc(charset, 0, "a", 0) == 0);
|
||||
assert(charset_mbtowc(charset, 0, "", 1) == 0);
|
||||
assert(charset_mbtowc(charset, 0, "b", 1) == 1);
|
||||
assert(charset_mbtowc(charset, 0, "", 2) == 0);
|
||||
assert(charset_mbtowc(charset, 0, "c", 2) == 1);
|
||||
|
||||
wc = 'x';
|
||||
assert(charset_mbtowc(charset, &wc, "a", 0) == 0 && wc == 'x');
|
||||
assert(charset_mbtowc(charset, &wc, "", 1) == 0 && wc == 0);
|
||||
assert(charset_mbtowc(charset, &wc, "b", 1) == 1 && wc == 'b');
|
||||
assert(charset_mbtowc(charset, &wc, "", 2) == 0 && wc == 0);
|
||||
assert(charset_mbtowc(charset, &wc, "c", 2) == 1 && wc == 'c');
|
||||
|
||||
/* Encoder */
|
||||
|
||||
assert(charset_wctomb(charset, 0, 0) == 0);
|
||||
|
||||
s[0] = s[1] = '.';
|
||||
assert(charset_wctomb(charset, s, 0) == 1 &&
|
||||
s[0] == '\0' && s[1] == '.');
|
||||
assert(charset_wctomb(charset, s, 'x') == 1 &&
|
||||
s[0] == 'x' && s[1] == '.');
|
||||
}
|
||||
|
||||
void test_utf8()
|
||||
{
|
||||
struct charset *charset;
|
||||
int wc;
|
||||
char s[8];
|
||||
|
||||
charset = charset_find("UTF-8");
|
||||
test_any(charset);
|
||||
|
||||
/* Decoder */
|
||||
wc = 0;
|
||||
assert(charset_mbtowc(charset, &wc, "\177", 1) == 1 && wc == 127);
|
||||
assert(charset_mbtowc(charset, &wc, "\200", 2) == -1);
|
||||
assert(charset_mbtowc(charset, &wc, "\301\277", 9) == -1);
|
||||
assert(charset_mbtowc(charset, &wc, "\302\200", 1) == -1);
|
||||
assert(charset_mbtowc(charset, &wc, "\302\200", 2) == 2 && wc == 128);
|
||||
assert(charset_mbtowc(charset, &wc, "\302\200", 3) == 2 && wc == 128);
|
||||
assert(charset_mbtowc(charset, &wc, "\340\237\200", 9) == -1);
|
||||
assert(charset_mbtowc(charset, &wc, "\340\240\200", 9) == 3 &&
|
||||
wc == 1 << 11);
|
||||
assert(charset_mbtowc(charset, &wc, "\360\217\277\277", 9) == -1);
|
||||
assert(charset_mbtowc(charset, &wc, "\360\220\200\200", 9) == 4 &&
|
||||
wc == 1 << 16);
|
||||
assert(charset_mbtowc(charset, &wc, "\370\207\277\277\277", 9) == -1);
|
||||
assert(charset_mbtowc(charset, &wc, "\370\210\200\200\200", 9) == 5 &&
|
||||
wc == 1 << 21);
|
||||
assert(charset_mbtowc(charset, &wc, "\374\203\277\277\277\277", 9) == -1);
|
||||
assert(charset_mbtowc(charset, &wc, "\374\204\200\200\200\200", 9) == 6 &&
|
||||
wc == 1 << 26);
|
||||
assert(charset_mbtowc(charset, &wc, "\375\277\277\277\277\277", 9) == 6 &&
|
||||
wc == 0x7fffffff);
|
||||
|
||||
assert(charset_mbtowc(charset, &wc, "\302\000", 2) == -1);
|
||||
assert(charset_mbtowc(charset, &wc, "\302\300", 2) == -1);
|
||||
assert(charset_mbtowc(charset, &wc, "\340\040\200", 9) == -1);
|
||||
assert(charset_mbtowc(charset, &wc, "\340\340\200", 9) == -1);
|
||||
assert(charset_mbtowc(charset, &wc, "\340\240\000", 9) == -1);
|
||||
assert(charset_mbtowc(charset, &wc, "\340\240\300", 9) == -1);
|
||||
assert(charset_mbtowc(charset, &wc, "\360\020\200\200", 9) == -1);
|
||||
assert(charset_mbtowc(charset, &wc, "\360\320\200\200", 9) == -1);
|
||||
assert(charset_mbtowc(charset, &wc, "\360\220\000\200", 9) == -1);
|
||||
assert(charset_mbtowc(charset, &wc, "\360\220\300\200", 9) == -1);
|
||||
assert(charset_mbtowc(charset, &wc, "\360\220\200\000", 9) == -1);
|
||||
assert(charset_mbtowc(charset, &wc, "\360\220\200\300", 9) == -1);
|
||||
assert(charset_mbtowc(charset, &wc, "\375\077\277\277\277\277", 9) == -1);
|
||||
assert(charset_mbtowc(charset, &wc, "\375\377\277\277\277\277", 9) == -1);
|
||||
assert(charset_mbtowc(charset, &wc, "\375\277\077\277\277\277", 9) == -1);
|
||||
assert(charset_mbtowc(charset, &wc, "\375\277\377\277\277\277", 9) == -1);
|
||||
assert(charset_mbtowc(charset, &wc, "\375\277\277\277\077\277", 9) == -1);
|
||||
assert(charset_mbtowc(charset, &wc, "\375\277\277\277\377\277", 9) == -1);
|
||||
assert(charset_mbtowc(charset, &wc, "\375\277\277\277\277\077", 9) == -1);
|
||||
assert(charset_mbtowc(charset, &wc, "\375\277\277\277\277\377", 9) == -1);
|
||||
|
||||
assert(charset_mbtowc(charset, &wc, "\376\277\277\277\277\277", 9) == -1);
|
||||
assert(charset_mbtowc(charset, &wc, "\377\277\277\277\277\277", 9) == -1);
|
||||
|
||||
/* Encoder */
|
||||
strcpy(s, ".......");
|
||||
assert(charset_wctomb(charset, s, 1 << 31) == -1 &&
|
||||
!strcmp(s, "......."));
|
||||
assert(charset_wctomb(charset, s, 127) == 1 &&
|
||||
!strcmp(s, "\177......"));
|
||||
assert(charset_wctomb(charset, s, 128) == 2 &&
|
||||
!strcmp(s, "\302\200....."));
|
||||
assert(charset_wctomb(charset, s, 0x7ff) == 2 &&
|
||||
!strcmp(s, "\337\277....."));
|
||||
assert(charset_wctomb(charset, s, 0x800) == 3 &&
|
||||
!strcmp(s, "\340\240\200...."));
|
||||
assert(charset_wctomb(charset, s, 0xffff) == 3 &&
|
||||
!strcmp(s, "\357\277\277...."));
|
||||
assert(charset_wctomb(charset, s, 0x10000) == 4 &&
|
||||
!strcmp(s, "\360\220\200\200..."));
|
||||
assert(charset_wctomb(charset, s, 0x1fffff) == 4 &&
|
||||
!strcmp(s, "\367\277\277\277..."));
|
||||
assert(charset_wctomb(charset, s, 0x200000) == 5 &&
|
||||
!strcmp(s, "\370\210\200\200\200.."));
|
||||
assert(charset_wctomb(charset, s, 0x3ffffff) == 5 &&
|
||||
!strcmp(s, "\373\277\277\277\277.."));
|
||||
assert(charset_wctomb(charset, s, 0x4000000) == 6 &&
|
||||
!strcmp(s, "\374\204\200\200\200\200."));
|
||||
assert(charset_wctomb(charset, s, 0x7fffffff) == 6 &&
|
||||
!strcmp(s, "\375\277\277\277\277\277."));
|
||||
}
|
||||
|
||||
void test_ascii()
|
||||
{
|
||||
struct charset *charset;
|
||||
int wc;
|
||||
char s[3];
|
||||
|
||||
charset = charset_find("us-ascii");
|
||||
test_any(charset);
|
||||
|
||||
/* Decoder */
|
||||
wc = 0;
|
||||
assert(charset_mbtowc(charset, &wc, "\177", 2) == 1 && wc == 127);
|
||||
assert(charset_mbtowc(charset, &wc, "\200", 2) == -1);
|
||||
|
||||
/* Encoder */
|
||||
strcpy(s, "..");
|
||||
assert(charset_wctomb(charset, s, 256) == -1 && !strcmp(s, ".."));
|
||||
assert(charset_wctomb(charset, s, 255) == -1);
|
||||
assert(charset_wctomb(charset, s, 128) == -1);
|
||||
assert(charset_wctomb(charset, s, 127) == 1 && !strcmp(s, "\177."));
|
||||
}
|
||||
|
||||
void test_iso1()
|
||||
{
|
||||
struct charset *charset;
|
||||
int wc;
|
||||
char s[3];
|
||||
|
||||
charset = charset_find("iso-8859-1");
|
||||
test_any(charset);
|
||||
|
||||
/* Decoder */
|
||||
wc = 0;
|
||||
assert(charset_mbtowc(charset, &wc, "\302\200", 9) == 1 && wc == 0xc2);
|
||||
|
||||
/* Encoder */
|
||||
strcpy(s, "..");
|
||||
assert(charset_wctomb(charset, s, 256) == -1 && !strcmp(s, ".."));
|
||||
assert(charset_wctomb(charset, s, 255) == 1 && !strcmp(s, "\377."));
|
||||
assert(charset_wctomb(charset, s, 128) == 1 && !strcmp(s, "\200."));
|
||||
}
|
||||
|
||||
void test_iso2()
|
||||
{
|
||||
struct charset *charset;
|
||||
int wc;
|
||||
char s[3];
|
||||
|
||||
charset = charset_find("iso-8859-2");
|
||||
test_any(charset);
|
||||
|
||||
/* Decoder */
|
||||
wc = 0;
|
||||
assert(charset_mbtowc(charset, &wc, "\302\200", 9) == 1 && wc == 0xc2);
|
||||
assert(charset_mbtowc(charset, &wc, "\377", 2) == 1 && wc == 0x2d9);
|
||||
|
||||
/* Encoder */
|
||||
strcpy(s, "..");
|
||||
assert(charset_wctomb(charset, s, 256) == -1 && !strcmp(s, ".."));
|
||||
assert(charset_wctomb(charset, s, 255) == -1 && !strcmp(s, ".."));
|
||||
assert(charset_wctomb(charset, s, 258) == 1 && !strcmp(s, "\303."));
|
||||
assert(charset_wctomb(charset, s, 128) == 1 && !strcmp(s, "\200."));
|
||||
}
|
||||
|
||||
void test_convert()
|
||||
{
|
||||
const char *p;
|
||||
char *q, *r;
|
||||
char s[256];
|
||||
size_t n, n2;
|
||||
int i;
|
||||
|
||||
p = "\000x\302\200\375\277\277\277\277\277";
|
||||
assert(charset_convert("UTF-8", "UTF-8", p, 10, &q, &n) == 0 &&
|
||||
n == 10 && !strcmp(p, q));
|
||||
assert(charset_convert("UTF-8", "UTF-8", "x\301\277y", 4, &q, &n) == 2 &&
|
||||
n == 4 && !strcmp(q, "x##y"));
|
||||
assert(charset_convert("UTF-8", "UTF-8", "x\301\277y", 4, 0, &n) == 2 &&
|
||||
n == 4);
|
||||
assert(charset_convert("UTF-8", "UTF-8", "x\301\277y", 4, &q, 0) == 2 &&
|
||||
!strcmp(q, "x##y"));
|
||||
assert(charset_convert("UTF-8", "iso-8859-1",
|
||||
"\302\200\304\200x", 5, &q, &n) == 1 &&
|
||||
n == 3 && !strcmp(q, "\200?x"));
|
||||
assert(charset_convert("iso-8859-1", "UTF-8",
|
||||
"\000\200\377", 3, &q, &n) == 0 &&
|
||||
n == 5 && !memcmp(q, "\000\302\200\303\277", 5));
|
||||
assert(charset_convert("iso-8859-1", "iso-8859-1",
|
||||
"\000\200\377", 3, &q, &n) == 0 &&
|
||||
n == 3 && !memcmp(q, "\000\200\377", 3));
|
||||
|
||||
assert(charset_convert("iso-8859-2", "utf-8", "\300", 1, &q, &n) == 0 &&
|
||||
n == 2 && !strcmp(q, "\305\224"));
|
||||
assert(charset_convert("utf-8", "iso-8859-2", "\305\224", 2, &q, &n) == 0 &&
|
||||
n == 1 && !strcmp(q, "\300"));
|
||||
|
||||
for (i = 0; i < 256; i++)
|
||||
s[i] = i;
|
||||
|
||||
assert(charset_convert("iso-8859-2", "utf-8", s, 256, &q, &n) == 0);
|
||||
assert(charset_convert("utf-8", "iso-8859-2", q, n, &r, &n2) == 0);
|
||||
assert(n2 == 256 && !memcmp(r, s, n2));
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
test_utf8();
|
||||
test_ascii();
|
||||
test_iso1();
|
||||
test_iso2();
|
||||
|
||||
test_convert();
|
||||
|
||||
return 0;
|
||||
}
|
||||
79
src/share/charsetmap.h
Normal file
79
src/share/charsetmap.h
Normal file
@@ -0,0 +1,79 @@
|
||||
/* This file was automatically generated by make_code_map.pl
|
||||
please don't edit directly
|
||||
Daniel Resare <noa@metamatrix.se>
|
||||
*/
|
||||
charset_map maps[] = {
|
||||
{"ISO-8859-1",
|
||||
{
|
||||
0x0000,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007,
|
||||
0x0008,0x0009,0x000A,0x000B,0x000C,0x000D,0x000E,0x000F,
|
||||
0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017,
|
||||
0x0018,0x0019,0x001A,0x001B,0x001C,0x001D,0x001E,0x001F,
|
||||
0x0020,0x0021,0x0022,0x0023,0x0024,0x0025,0x0026,0x0027,
|
||||
0x0028,0x0029,0x002A,0x002B,0x002C,0x002D,0x002E,0x002F,
|
||||
0x0030,0x0031,0x0032,0x0033,0x0034,0x0035,0x0036,0x0037,
|
||||
0x0038,0x0039,0x003A,0x003B,0x003C,0x003D,0x003E,0x003F,
|
||||
0x0040,0x0041,0x0042,0x0043,0x0044,0x0045,0x0046,0x0047,
|
||||
0x0048,0x0049,0x004A,0x004B,0x004C,0x004D,0x004E,0x004F,
|
||||
0x0050,0x0051,0x0052,0x0053,0x0054,0x0055,0x0056,0x0057,
|
||||
0x0058,0x0059,0x005A,0x005B,0x005C,0x005D,0x005E,0x005F,
|
||||
0x0060,0x0061,0x0062,0x0063,0x0064,0x0065,0x0066,0x0067,
|
||||
0x0068,0x0069,0x006A,0x006B,0x006C,0x006D,0x006E,0x006F,
|
||||
0x0070,0x0071,0x0072,0x0073,0x0074,0x0075,0x0076,0x0077,
|
||||
0x0078,0x0079,0x007A,0x007B,0x007C,0x007D,0x007E,0x007F,
|
||||
0x0080,0x0081,0x0082,0x0083,0x0084,0x0085,0x0086,0x0087,
|
||||
0x0088,0x0089,0x008A,0x008B,0x008C,0x008D,0x008E,0x008F,
|
||||
0x0090,0x0091,0x0092,0x0093,0x0094,0x0095,0x0096,0x0097,
|
||||
0x0098,0x0099,0x009A,0x009B,0x009C,0x009D,0x009E,0x009F,
|
||||
0x00A0,0x00A1,0x00A2,0x00A3,0x00A4,0x00A5,0x00A6,0x00A7,
|
||||
0x00A8,0x00A9,0x00AA,0x00AB,0x00AC,0x00AD,0x00AE,0x00AF,
|
||||
0x00B0,0x00B1,0x00B2,0x00B3,0x00B4,0x00B5,0x00B6,0x00B7,
|
||||
0x00B8,0x00B9,0x00BA,0x00BB,0x00BC,0x00BD,0x00BE,0x00BF,
|
||||
0x00C0,0x00C1,0x00C2,0x00C3,0x00C4,0x00C5,0x00C6,0x00C7,
|
||||
0x00C8,0x00C9,0x00CA,0x00CB,0x00CC,0x00CD,0x00CE,0x00CF,
|
||||
0x00D0,0x00D1,0x00D2,0x00D3,0x00D4,0x00D5,0x00D6,0x00D7,
|
||||
0x00D8,0x00D9,0x00DA,0x00DB,0x00DC,0x00DD,0x00DE,0x00DF,
|
||||
0x00E0,0x00E1,0x00E2,0x00E3,0x00E4,0x00E5,0x00E6,0x00E7,
|
||||
0x00E8,0x00E9,0x00EA,0x00EB,0x00EC,0x00ED,0x00EE,0x00EF,
|
||||
0x00F0,0x00F1,0x00F2,0x00F3,0x00F4,0x00F5,0x00F6,0x00F7,
|
||||
0x00F8,0x00F9,0x00FA,0x00FB,0x00FC,0x00FD,0x00FE,0x00FF
|
||||
}
|
||||
},
|
||||
{"ISO-8859-2",
|
||||
{
|
||||
0x0000,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007,
|
||||
0x0008,0x0009,0x000A,0x000B,0x000C,0x000D,0x000E,0x000F,
|
||||
0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017,
|
||||
0x0018,0x0019,0x001A,0x001B,0x001C,0x001D,0x001E,0x001F,
|
||||
0x0020,0x0021,0x0022,0x0023,0x0024,0x0025,0x0026,0x0027,
|
||||
0x0028,0x0029,0x002A,0x002B,0x002C,0x002D,0x002E,0x002F,
|
||||
0x0030,0x0031,0x0032,0x0033,0x0034,0x0035,0x0036,0x0037,
|
||||
0x0038,0x0039,0x003A,0x003B,0x003C,0x003D,0x003E,0x003F,
|
||||
0x0040,0x0041,0x0042,0x0043,0x0044,0x0045,0x0046,0x0047,
|
||||
0x0048,0x0049,0x004A,0x004B,0x004C,0x004D,0x004E,0x004F,
|
||||
0x0050,0x0051,0x0052,0x0053,0x0054,0x0055,0x0056,0x0057,
|
||||
0x0058,0x0059,0x005A,0x005B,0x005C,0x005D,0x005E,0x005F,
|
||||
0x0060,0x0061,0x0062,0x0063,0x0064,0x0065,0x0066,0x0067,
|
||||
0x0068,0x0069,0x006A,0x006B,0x006C,0x006D,0x006E,0x006F,
|
||||
0x0070,0x0071,0x0072,0x0073,0x0074,0x0075,0x0076,0x0077,
|
||||
0x0078,0x0079,0x007A,0x007B,0x007C,0x007D,0x007E,0x007F,
|
||||
0x0080,0x0081,0x0082,0x0083,0x0084,0x0085,0x0086,0x0087,
|
||||
0x0088,0x0089,0x008A,0x008B,0x008C,0x008D,0x008E,0x008F,
|
||||
0x0090,0x0091,0x0092,0x0093,0x0094,0x0095,0x0096,0x0097,
|
||||
0x0098,0x0099,0x009A,0x009B,0x009C,0x009D,0x009E,0x009F,
|
||||
0x00A0,0x0104,0x02D8,0x0141,0x00A4,0x013D,0x015A,0x00A7,
|
||||
0x00A8,0x0160,0x015E,0x0164,0x0179,0x00AD,0x017D,0x017B,
|
||||
0x00B0,0x0105,0x02DB,0x0142,0x00B4,0x013E,0x015B,0x02C7,
|
||||
0x00B8,0x0161,0x015F,0x0165,0x017A,0x02DD,0x017E,0x017C,
|
||||
0x0154,0x00C1,0x00C2,0x0102,0x00C4,0x0139,0x0106,0x00C7,
|
||||
0x010C,0x00C9,0x0118,0x00CB,0x011A,0x00CD,0x00CE,0x010E,
|
||||
0x0110,0x0143,0x0147,0x00D3,0x00D4,0x0150,0x00D6,0x00D7,
|
||||
0x0158,0x016E,0x00DA,0x0170,0x00DC,0x00DD,0x0162,0x00DF,
|
||||
0x0155,0x00E1,0x00E2,0x0103,0x00E4,0x013A,0x0107,0x00E7,
|
||||
0x010D,0x00E9,0x0119,0x00EB,0x011B,0x00ED,0x00EE,0x010F,
|
||||
0x0111,0x0144,0x0148,0x00F3,0x00F4,0x0151,0x00F6,0x00F7,
|
||||
0x0159,0x016F,0x00FA,0x0171,0x00FC,0x00FD,0x0163,0x02D9
|
||||
}
|
||||
},
|
||||
{NULL}
|
||||
};
|
||||
1047
src/share/getopt.c
Normal file
1047
src/share/getopt.c
Normal file
File diff suppressed because it is too large
Load Diff
188
src/share/getopt1.c
Normal file
188
src/share/getopt1.c
Normal file
@@ -0,0 +1,188 @@
|
||||
/* getopt_long and getopt_long_only entry points for GNU getopt.
|
||||
Copyright (C) 1987,88,89,90,91,92,93,94,96,97,98
|
||||
Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public License as
|
||||
published by the Free Software Foundation; either version 2 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
The GNU C 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
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with the GNU C Library; see the file COPYING.LIB. If not,
|
||||
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include "getopt.h"
|
||||
|
||||
#if !defined __STDC__ || !__STDC__
|
||||
/* This is a separate conditional since some stdc systems
|
||||
reject `defined (const)'. */
|
||||
#ifndef const
|
||||
#define const
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
/* Comment out all this code if we are using the GNU C Library, and are not
|
||||
actually compiling the library itself. This code is part of the GNU C
|
||||
Library, but also included in many other GNU distributions. Compiling
|
||||
and linking in this code is a waste when using the GNU C library
|
||||
(especially if it is a shared library). Rather than having every GNU
|
||||
program understand `configure --with-gnu-libc' and omit the object files,
|
||||
it is simpler to just do this in the source for each such file. */
|
||||
|
||||
#define GETOPT_INTERFACE_VERSION 2
|
||||
#if !defined _LIBC && defined __GLIBC__ && __GLIBC__ >= 2
|
||||
#include <gnu-versions.h>
|
||||
#if _GNU_GETOPT_INTERFACE_VERSION == GETOPT_INTERFACE_VERSION
|
||||
#define ELIDE_CODE
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef ELIDE_CODE
|
||||
|
||||
|
||||
/* This needs to come after some library #include
|
||||
to get __GNU_LIBRARY__ defined. */
|
||||
#ifdef __GNU_LIBRARY__
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
|
||||
#ifndef NULL
|
||||
#define NULL 0
|
||||
#endif
|
||||
|
||||
int
|
||||
getopt_long (argc, argv, options, long_options, opt_index)
|
||||
int argc;
|
||||
char *const *argv;
|
||||
const char *options;
|
||||
const struct option *long_options;
|
||||
int *opt_index;
|
||||
{
|
||||
return _getopt_internal (argc, argv, options, long_options, opt_index, 0);
|
||||
}
|
||||
|
||||
/* Like getopt_long, but '-' as well as '--' can indicate a long option.
|
||||
If an option that starts with '-' (not '--') doesn't match a long option,
|
||||
but does match a short option, it is parsed as a short option
|
||||
instead. */
|
||||
|
||||
int
|
||||
getopt_long_only (argc, argv, options, long_options, opt_index)
|
||||
int argc;
|
||||
char *const *argv;
|
||||
const char *options;
|
||||
const struct option *long_options;
|
||||
int *opt_index;
|
||||
{
|
||||
return _getopt_internal (argc, argv, options, long_options, opt_index, 1);
|
||||
}
|
||||
|
||||
|
||||
#endif /* Not ELIDE_CODE. */
|
||||
|
||||
#ifdef TEST
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
int
|
||||
main (argc, argv)
|
||||
int argc;
|
||||
char **argv;
|
||||
{
|
||||
int c;
|
||||
int digit_optind = 0;
|
||||
|
||||
while (1)
|
||||
{
|
||||
int this_option_optind = optind ? optind : 1;
|
||||
int option_index = 0;
|
||||
static struct option long_options[] =
|
||||
{
|
||||
{"add", 1, 0, 0},
|
||||
{"append", 0, 0, 0},
|
||||
{"delete", 1, 0, 0},
|
||||
{"verbose", 0, 0, 0},
|
||||
{"create", 0, 0, 0},
|
||||
{"file", 1, 0, 0},
|
||||
{0, 0, 0, 0}
|
||||
};
|
||||
|
||||
c = getopt_long (argc, argv, "abc:d:0123456789",
|
||||
long_options, &option_index);
|
||||
if (c == -1)
|
||||
break;
|
||||
|
||||
switch (c)
|
||||
{
|
||||
case 0:
|
||||
printf ("option %s", long_options[option_index].name);
|
||||
if (optarg)
|
||||
printf (" with arg %s", optarg);
|
||||
printf ("\n");
|
||||
break;
|
||||
|
||||
case '0':
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9':
|
||||
if (digit_optind != 0 && digit_optind != this_option_optind)
|
||||
printf ("digits occur in two different argv-elements.\n");
|
||||
digit_optind = this_option_optind;
|
||||
printf ("option %c\n", c);
|
||||
break;
|
||||
|
||||
case 'a':
|
||||
printf ("option a\n");
|
||||
break;
|
||||
|
||||
case 'b':
|
||||
printf ("option b\n");
|
||||
break;
|
||||
|
||||
case 'c':
|
||||
printf ("option c with value `%s'\n", optarg);
|
||||
break;
|
||||
|
||||
case 'd':
|
||||
printf ("option d with value `%s'\n", optarg);
|
||||
break;
|
||||
|
||||
case '?':
|
||||
break;
|
||||
|
||||
default:
|
||||
printf ("?? getopt returned character code 0%o ??\n", c);
|
||||
}
|
||||
}
|
||||
|
||||
if (optind < argc)
|
||||
{
|
||||
printf ("non-option ARGV-elements: ");
|
||||
while (optind < argc)
|
||||
printf ("%s ", argv[optind++]);
|
||||
printf ("\n");
|
||||
}
|
||||
|
||||
exit (0);
|
||||
}
|
||||
|
||||
#endif /* TEST */
|
||||
243
src/share/iconvert.c
Normal file
243
src/share/iconvert.c
Normal file
@@ -0,0 +1,243 @@
|
||||
/*
|
||||
* Copyright (C) 2001 Edmund Grimley Evans <edmundo@rano.org>
|
||||
*
|
||||
* 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; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifdef HAVE_ICONV
|
||||
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <iconv.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
/*
|
||||
* Convert data from one encoding to another. Return:
|
||||
*
|
||||
* -2 : memory allocation failed
|
||||
* -1 : unknown encoding
|
||||
* 0 : data was converted exactly
|
||||
* 1 : data was converted inexactly
|
||||
* 2 : data was invalid (but still converted)
|
||||
*
|
||||
* We convert in two steps, via UTF-8, as this is the only
|
||||
* reliable way of distinguishing between invalid input
|
||||
* and valid input which iconv refuses to transliterate.
|
||||
* We convert from UTF-8 twice, because we have no way of
|
||||
* knowing whether the conversion was exact if iconv returns
|
||||
* E2BIG (due to a bug in the specification of iconv).
|
||||
* An alternative approach is to assume that the output of
|
||||
* iconv is never more than 4 times as long as the input,
|
||||
* but I prefer to avoid that assumption if possible.
|
||||
*/
|
||||
|
||||
int iconvert(const char *fromcode, const char *tocode,
|
||||
const char *from, size_t fromlen,
|
||||
char **to, size_t *tolen)
|
||||
{
|
||||
int ret = 0;
|
||||
iconv_t cd1, cd2;
|
||||
char *ib;
|
||||
char *ob;
|
||||
char *utfbuf, *outbuf, *newbuf;
|
||||
size_t utflen, outlen, ibl, obl, k;
|
||||
char tbuf[2048];
|
||||
|
||||
cd1 = iconv_open("UTF-8", fromcode);
|
||||
if (cd1 == (iconv_t)(-1))
|
||||
return -1;
|
||||
|
||||
cd2 = (iconv_t)(-1);
|
||||
/* Don't use strcasecmp() as it's locale-dependent. */
|
||||
if (!strchr("Uu", tocode[0]) ||
|
||||
!strchr("Tt", tocode[1]) ||
|
||||
!strchr("Ff", tocode[2]) ||
|
||||
tocode[3] != '-' ||
|
||||
tocode[4] != '8' ||
|
||||
tocode[5] != '\0') {
|
||||
char *tocode1;
|
||||
|
||||
/*
|
||||
* Try using this non-standard feature of glibc and libiconv.
|
||||
* This is deliberately not a config option as people often
|
||||
* change their iconv library without rebuilding applications.
|
||||
*/
|
||||
tocode1 = (char *)malloc(strlen(tocode) + 11);
|
||||
if (!tocode1)
|
||||
goto fail;
|
||||
|
||||
strcpy(tocode1, tocode);
|
||||
strcat(tocode1, "//TRANSLIT");
|
||||
cd2 = iconv_open(tocode1, "UTF-8");
|
||||
free(tocode1);
|
||||
|
||||
if (cd2 == (iconv_t)(-1))
|
||||
cd2 = iconv_open(tocode, fromcode);
|
||||
|
||||
if (cd2 == (iconv_t)(-1)) {
|
||||
iconv_close(cd1);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
utflen = 1; /*fromlen * 2 + 1; XXX */
|
||||
utfbuf = (char *)malloc(utflen);
|
||||
if (!utfbuf)
|
||||
goto fail;
|
||||
|
||||
/* Convert to UTF-8 */
|
||||
ib = (char *)from;
|
||||
ibl = fromlen;
|
||||
ob = utfbuf;
|
||||
obl = utflen;
|
||||
for (;;) {
|
||||
k = iconv(cd1, &ib, &ibl, &ob, &obl);
|
||||
assert((!k && !ibl) ||
|
||||
(k == (size_t)(-1) && errno == E2BIG && ibl && obl < 6) ||
|
||||
(k == (size_t)(-1) &&
|
||||
(errno == EILSEQ || errno == EINVAL) && ibl));
|
||||
if (!ibl)
|
||||
break;
|
||||
if (obl < 6) {
|
||||
/* Enlarge the buffer */
|
||||
utflen *= 2;
|
||||
newbuf = (char *)realloc(utfbuf, utflen);
|
||||
if (!newbuf)
|
||||
goto fail;
|
||||
ob = (ob - utfbuf) + newbuf;
|
||||
obl = utflen - (ob - newbuf);
|
||||
utfbuf = newbuf;
|
||||
}
|
||||
else {
|
||||
/* Invalid input */
|
||||
ib++, ibl--;
|
||||
*ob++ = '#', obl--;
|
||||
ret = 2;
|
||||
iconv(cd1, 0, 0, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
if (cd2 == (iconv_t)(-1)) {
|
||||
/* The target encoding was UTF-8 */
|
||||
if (tolen)
|
||||
*tolen = ob - utfbuf;
|
||||
if (!to) {
|
||||
free(utfbuf);
|
||||
iconv_close(cd1);
|
||||
return ret;
|
||||
}
|
||||
newbuf = (char *)realloc(utfbuf, (ob - utfbuf) + 1);
|
||||
if (!newbuf)
|
||||
goto fail;
|
||||
ob = (ob - utfbuf) + newbuf;
|
||||
*ob = '\0';
|
||||
*to = newbuf;
|
||||
iconv_close(cd1);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Truncate the buffer to be tidy */
|
||||
utflen = ob - utfbuf;
|
||||
newbuf = (char *)realloc(utfbuf, utflen);
|
||||
if (!newbuf)
|
||||
goto fail;
|
||||
utfbuf = newbuf;
|
||||
|
||||
/* Convert from UTF-8 to discover how long the output is */
|
||||
outlen = 0;
|
||||
ib = utfbuf;
|
||||
ibl = utflen;
|
||||
while (ibl) {
|
||||
ob = tbuf;
|
||||
obl = sizeof(tbuf);
|
||||
k = iconv(cd2, &ib, &ibl, &ob, &obl);
|
||||
assert((k != (size_t)(-1) && !ibl) ||
|
||||
(k == (size_t)(-1) && errno == E2BIG && ibl) ||
|
||||
(k == (size_t)(-1) && errno == EILSEQ && ibl));
|
||||
if (ibl && !(k == (size_t)(-1) && errno == E2BIG)) {
|
||||
/* Replace one character */
|
||||
char *tb = "?";
|
||||
size_t tbl = 1;
|
||||
|
||||
outlen += ob - tbuf;
|
||||
ob = tbuf;
|
||||
obl = sizeof(tbuf);
|
||||
k = iconv(cd2, &tb, &tbl, &ob, &obl);
|
||||
assert((!k && !tbl) ||
|
||||
(k == (size_t)(-1) && errno == EILSEQ && tbl));
|
||||
for (++ib, --ibl; ibl && (*ib & 0x80); ib++, ibl--)
|
||||
;
|
||||
}
|
||||
outlen += ob - tbuf;
|
||||
}
|
||||
ob = tbuf;
|
||||
obl = sizeof(tbuf);
|
||||
k = iconv(cd2, 0, 0, &ob, &obl);
|
||||
assert(!k);
|
||||
outlen += ob - tbuf;
|
||||
|
||||
/* Convert from UTF-8 for real */
|
||||
outbuf = (char *)malloc(outlen + 1);
|
||||
if (!outbuf)
|
||||
goto fail;
|
||||
ib = utfbuf;
|
||||
ibl = utflen;
|
||||
ob = outbuf;
|
||||
obl = outlen;
|
||||
while (ibl) {
|
||||
k = iconv(cd2, &ib, &ibl, &ob, &obl);
|
||||
assert((k != (size_t)(-1) && !ibl) ||
|
||||
(k == (size_t)(-1) && errno == EILSEQ && ibl));
|
||||
if (k && !ret)
|
||||
ret = 1;
|
||||
if (ibl && !(k == (size_t)(-1) && errno == E2BIG)) {
|
||||
/* Replace one character */
|
||||
char *tb = "?";
|
||||
size_t tbl = 1;
|
||||
|
||||
k = iconv(cd2, &tb, &tbl, &ob, &obl);
|
||||
assert((!k && !tbl) ||
|
||||
(k == (size_t)(-1) && errno == EILSEQ && tbl));
|
||||
for (++ib, --ibl; ibl && (*ib & 0x80); ib++, ibl--)
|
||||
;
|
||||
}
|
||||
}
|
||||
k = iconv(cd2, 0, 0, &ob, &obl);
|
||||
assert(!k);
|
||||
assert(!obl);
|
||||
*ob = '\0';
|
||||
|
||||
free(utfbuf);
|
||||
iconv_close(cd1);
|
||||
iconv_close(cd2);
|
||||
if (tolen)
|
||||
*tolen = outlen;
|
||||
if (!to) {
|
||||
free(outbuf);
|
||||
return ret;
|
||||
}
|
||||
*to = outbuf;
|
||||
return ret;
|
||||
|
||||
fail:
|
||||
free(utfbuf);
|
||||
iconv_close(cd1);
|
||||
if (cd2 != (iconv_t)(-1))
|
||||
iconv_close(cd2);
|
||||
return -2;
|
||||
}
|
||||
|
||||
#endif /* HAVE_ICONV */
|
||||
77
src/share/makemap.c
Normal file
77
src/share/makemap.c
Normal file
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* Copyright (C) 2001 Edmund Grimley Evans <edmundo@rano.org>
|
||||
*
|
||||
* 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; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include <iconv.h>
|
||||
#include <stdio.h>
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
iconv_t cd;
|
||||
const char *ib;
|
||||
char *ob;
|
||||
size_t ibl, obl, k;
|
||||
unsigned char c, buf[4];
|
||||
int i, wc;
|
||||
|
||||
if (argc != 2) {
|
||||
printf("Usage: %s ENCODING\n", argv[0]);
|
||||
printf("Output a charset map for the 8-bit ENCODING.\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
cd = iconv_open("UCS-4", argv[1]);
|
||||
if (cd == (iconv_t)(-1)) {
|
||||
perror("iconv_open");
|
||||
return 1;
|
||||
}
|
||||
|
||||
for (i = 0; i < 256; i++) {
|
||||
c = i;
|
||||
ib = &c;
|
||||
ibl = 1;
|
||||
ob = buf;
|
||||
obl = 4;
|
||||
k = iconv(cd, &ib, &ibl, &ob, &obl);
|
||||
if (!k && !ibl && !obl) {
|
||||
wc = (buf[0] << 24) + (buf[1] << 16) + (buf[2] << 8) + buf[3];
|
||||
if (wc >= 0xffff) {
|
||||
printf("Dodgy value.\n");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
else if (k == (size_t)(-1) && errno == EILSEQ)
|
||||
wc = 0xffff;
|
||||
else {
|
||||
printf("Non-standard iconv.\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (i % 8 == 0)
|
||||
printf(" ");
|
||||
printf("0x%04x", wc);
|
||||
if (i == 255)
|
||||
printf("\n");
|
||||
else if (i % 8 == 7)
|
||||
printf(",\n");
|
||||
else
|
||||
printf(", ");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
314
src/share/utf8.c
Normal file
314
src/share/utf8.c
Normal file
@@ -0,0 +1,314 @@
|
||||
/*
|
||||
* Copyright (C) 2001 Peter Harris <peter.harris@hummingbird.com>
|
||||
* Copyright (C) 2001 Edmund Grimley Evans <edmundo@rano.org>
|
||||
*
|
||||
* 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; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/*
|
||||
* Convert a string between UTF-8 and the locale's charset.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "utf8.h"
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
/* Thanks to Peter Harris <peter.harris@hummingbird.com> for this win32
|
||||
* code.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <windows.h>
|
||||
|
||||
static unsigned char *make_utf8_string(const wchar_t *unicode)
|
||||
{
|
||||
int size = 0, index = 0, out_index = 0;
|
||||
unsigned char *out;
|
||||
unsigned short c;
|
||||
|
||||
/* first calculate the size of the target string */
|
||||
c = unicode[index++];
|
||||
while(c) {
|
||||
if(c < 0x0080) {
|
||||
size += 1;
|
||||
} else if(c < 0x0800) {
|
||||
size += 2;
|
||||
} else {
|
||||
size += 3;
|
||||
}
|
||||
c = unicode[index++];
|
||||
}
|
||||
|
||||
out = malloc(size + 1);
|
||||
if (out == NULL)
|
||||
return NULL;
|
||||
index = 0;
|
||||
|
||||
c = unicode[index++];
|
||||
while(c)
|
||||
{
|
||||
if(c < 0x080) {
|
||||
out[out_index++] = (unsigned char)c;
|
||||
} else if(c < 0x800) {
|
||||
out[out_index++] = 0xc0 | (c >> 6);
|
||||
out[out_index++] = 0x80 | (c & 0x3f);
|
||||
} else {
|
||||
out[out_index++] = 0xe0 | (c >> 12);
|
||||
out[out_index++] = 0x80 | ((c >> 6) & 0x3f);
|
||||
out[out_index++] = 0x80 | (c & 0x3f);
|
||||
}
|
||||
c = unicode[index++];
|
||||
}
|
||||
out[out_index] = 0x00;
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
static wchar_t *make_unicode_string(const unsigned char *utf8)
|
||||
{
|
||||
int size = 0, index = 0, out_index = 0;
|
||||
wchar_t *out;
|
||||
unsigned char c;
|
||||
|
||||
/* first calculate the size of the target string */
|
||||
c = utf8[index++];
|
||||
while(c) {
|
||||
if((c & 0x80) == 0) {
|
||||
index += 0;
|
||||
} else if((c & 0xe0) == 0xe0) {
|
||||
index += 2;
|
||||
} else {
|
||||
index += 1;
|
||||
}
|
||||
size += 1;
|
||||
c = utf8[index++];
|
||||
}
|
||||
|
||||
out = malloc((size + 1) * sizeof(wchar_t));
|
||||
if (out == NULL)
|
||||
return NULL;
|
||||
index = 0;
|
||||
|
||||
c = utf8[index++];
|
||||
while(c)
|
||||
{
|
||||
if((c & 0x80) == 0) {
|
||||
out[out_index++] = c;
|
||||
} else if((c & 0xe0) == 0xe0) {
|
||||
out[out_index] = (c & 0x1F) << 12;
|
||||
c = utf8[index++];
|
||||
out[out_index] |= (c & 0x3F) << 6;
|
||||
c = utf8[index++];
|
||||
out[out_index++] |= (c & 0x3F);
|
||||
} else {
|
||||
out[out_index] = (c & 0x3F) << 6;
|
||||
c = utf8[index++];
|
||||
out[out_index++] |= (c & 0x3F);
|
||||
}
|
||||
c = utf8[index++];
|
||||
}
|
||||
out[out_index] = 0;
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
int utf8_encode(const char *from, char **to)
|
||||
{
|
||||
wchar_t *unicode;
|
||||
int wchars, err;
|
||||
|
||||
wchars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, from,
|
||||
strlen(from), NULL, 0);
|
||||
|
||||
if(wchars == 0)
|
||||
{
|
||||
fprintf(stderr, "Unicode translation error %d\n", GetLastError());
|
||||
return -1;
|
||||
}
|
||||
|
||||
unicode = calloc(wchars + 1, sizeof(unsigned short));
|
||||
if(unicode == NULL)
|
||||
{
|
||||
fprintf(stderr, "Out of memory processing string to UTF8\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
err = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, from,
|
||||
strlen(from), unicode, wchars);
|
||||
if(err != wchars)
|
||||
{
|
||||
free(unicode);
|
||||
fprintf(stderr, "Unicode translation error %d\n", GetLastError());
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* On NT-based windows systems, we could use WideCharToMultiByte(), but
|
||||
* MS doesn't actually have a consistent API across win32.
|
||||
*/
|
||||
*to = make_utf8_string(unicode);
|
||||
|
||||
free(unicode);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int utf8_decode(const char *from, char **to)
|
||||
{
|
||||
wchar_t *unicode;
|
||||
int chars, err;
|
||||
|
||||
/* On NT-based windows systems, we could use MultiByteToWideChar(CP_UTF8), but
|
||||
* MS doesn't actually have a consistent API across win32.
|
||||
*/
|
||||
unicode = make_unicode_string(from);
|
||||
if(unicode == NULL)
|
||||
{
|
||||
fprintf(stderr, "Out of memory processing string from UTF8 to UNICODE16\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
chars = WideCharToMultiByte(GetConsoleCP(), WC_COMPOSITECHECK, unicode,
|
||||
-1, NULL, 0, NULL, NULL);
|
||||
|
||||
if(chars == 0)
|
||||
{
|
||||
fprintf(stderr, "Unicode translation error %d\n", GetLastError());
|
||||
free(unicode);
|
||||
return -1;
|
||||
}
|
||||
|
||||
*to = calloc(chars + 1, sizeof(unsigned char));
|
||||
if(*to == NULL)
|
||||
{
|
||||
fprintf(stderr, "Out of memory processing string to local charset\n");
|
||||
free(unicode);
|
||||
return -1;
|
||||
}
|
||||
|
||||
err = WideCharToMultiByte(GetConsoleCP(), WC_COMPOSITECHECK, unicode,
|
||||
-1, *to, chars, NULL, NULL);
|
||||
if(err != chars)
|
||||
{
|
||||
fprintf(stderr, "Unicode translation error %d\n", GetLastError());
|
||||
free(unicode);
|
||||
free(*to);
|
||||
*to = NULL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
free(unicode);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#else /* End win32. Rest is for real operating systems */
|
||||
|
||||
|
||||
#ifdef HAVE_LANGINFO_CODESET
|
||||
#include <langinfo.h>
|
||||
#endif
|
||||
|
||||
int iconvert(const char *fromcode, const char *tocode,
|
||||
const char *from, size_t fromlen,
|
||||
char **to, size_t *tolen);
|
||||
|
||||
static char *current_charset = 0; /* means "US-ASCII" */
|
||||
|
||||
void convert_set_charset(const char *charset)
|
||||
{
|
||||
|
||||
#ifdef HAVE_LANGINFO_CODESET
|
||||
if (!charset)
|
||||
charset = nl_langinfo(CODESET);
|
||||
#endif
|
||||
|
||||
if (!charset)
|
||||
charset = getenv("CHARSET");
|
||||
|
||||
free(current_charset);
|
||||
current_charset = 0;
|
||||
if (charset && *charset)
|
||||
current_charset = strdup(charset);
|
||||
}
|
||||
|
||||
static int convert_buffer(const char *fromcode, const char *tocode,
|
||||
const char *from, size_t fromlen,
|
||||
char **to, size_t *tolen)
|
||||
{
|
||||
int ret = -1;
|
||||
|
||||
#ifdef HAVE_ICONV
|
||||
ret = iconvert(fromcode, tocode, from, fromlen, to, tolen);
|
||||
if (ret != -1)
|
||||
return ret;
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_ICONV /* should be ifdef USE_CHARSET_CONVERT */
|
||||
ret = charset_convert(fromcode, tocode, from, fromlen, to, tolen);
|
||||
if (ret != -1)
|
||||
return ret;
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int convert_string(const char *fromcode, const char *tocode,
|
||||
const char *from, char **to, char replace)
|
||||
{
|
||||
int ret;
|
||||
size_t fromlen;
|
||||
char *s;
|
||||
|
||||
fromlen = strlen(from);
|
||||
ret = convert_buffer(fromcode, tocode, from, fromlen, to, 0);
|
||||
if (ret == -2)
|
||||
return -1;
|
||||
if (ret != -1)
|
||||
return ret;
|
||||
|
||||
s = malloc(fromlen + 1);
|
||||
if (!s)
|
||||
return -1;
|
||||
strcpy(s, from);
|
||||
*to = s;
|
||||
for (; *s; s++)
|
||||
if (*s & ~0x7f)
|
||||
*s = replace;
|
||||
return 3;
|
||||
}
|
||||
|
||||
int utf8_encode(const char *from, char **to)
|
||||
{
|
||||
char *charset;
|
||||
|
||||
if (!current_charset)
|
||||
convert_set_charset(0);
|
||||
charset = current_charset ? current_charset : "US-ASCII";
|
||||
return convert_string(charset, "UTF-8", from, to, '#');
|
||||
}
|
||||
|
||||
int utf8_decode(const char *from, char **to)
|
||||
{
|
||||
char *charset;
|
||||
|
||||
if (!current_charset)
|
||||
convert_set_charset(0);
|
||||
charset = current_charset ? current_charset : "US-ASCII";
|
||||
return convert_string("UTF-8", charset, from, to, '?');
|
||||
}
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user