8
0
mirror of https://github.com/FirebirdSQL/firebird.git synced 2025-01-24 12:03:02 +01:00
firebird-mirror/src/jrd/CharSet.cpp
asfernandes 1d422a8330 1) Refactor intl_classes.h and intl.cpp
2) Make conversions from CharSet1->UTF16->CharSet2 job of CsConvert class
2006-10-10 19:40:33 +00:00

243 lines
6.8 KiB
C++

/*
* PROGRAM: JRD Intl
* MODULE: CharSet.cpp
* DESCRIPTION: International text support routines
*
* copyright (c) 1992, 1993 by Borland International
*/
/************* history ************
*
* COMPONENT: JRD MODULE: INTL.CPP
* generated by Marion V2.5 2/6/90
* from dev db on 4-JAN-1995
*****************************************************************
*
* PR 2002-06-02 Added ugly c hack in
* intl_back_compat_alloc_func_lookup.
* When someone has time we need to change the references to
* return (void*) function to something more C++ like
*
* 42 4711 3 11 17 tamlin 2001
* Added silly numbers before my name, and converted it to C++.
*
* 18850 daves 4-JAN-1995
* Fix gds__alloc usage
*
* 18837 deej 31-DEC-1994
* fixing up HARBOR_MERGE
*
* 18821 deej 27-DEC-1994
* HARBOR MERGE
*
* 18789 jdavid 19-DEC-1994
* Cast some functions
*
* 17508 jdavid 15-JUL-1994
* Bring it up to date
*
* 17500 daves 13-JUL-1994
* Bug 6645: Different calculation of partial keys
*
* 17202 katz 24-MAY-1994
* PC_PLATFORM requires the .dll extension
*
* 17191 katz 23-MAY-1994
* OS/2 requires the .dll extension
*
* 17180 katz 23-MAY-1994
* Define location of DLL on OS/2
*
* 17149 katz 20-MAY-1994
* In JRD, isc_arg_number arguments are SLONG's not int's
*
* 16633 daves 19-APR-1994
* Bug 6202: International licensing uses INTERNATIONAL product code
*
* 16555 katz 17-APR-1994
* The last argument of calls to ERR_post should be 0
*
* 16521 katz 14-APR-1994
* Borland C needs a decorated symbol to lookup
*
* 16403 daves 8-APR-1994
* Bug 6441: Emit an error whenever transliteration from ttype_binary attempted
*
* 16141 katz 28-MAR-1994
* Don't declare return value from ISC_lookup_entrypoint as API_ROUTINE
*
* The contents of this file are subject to the Interbase Public
* License Version 1.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy
* of the License at http://www.Inprise.com/IPL.html
*
* Software distributed under the License is distributed on an
* "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express
* or implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code was created by Inprise Corporation
* and its predecessors. Portions created by Inprise Corporation are
* Copyright (C) Inprise Corporation.
*
* All Rights Reserved.
* Contributor(s): ______________________________________.
*
* 2002.10.29 Sean Leyne - Removed obsolete "Netware" port
*
* 2002.10.30 Sean Leyne - Removed support for obsolete "PC_PLATFORM" define
*
* 2006.10.10 Adriano dos Santos Fernandes - refactored from intl.cpp
*
*/
#include "firebird.h"
#include "../jrd/intl_classes.h"
using namespace Jrd;
namespace
{
class FixedWidthCharSet : public CharSet
{
public:
FixedWidthCharSet(USHORT _id, charset* _cs) : CharSet(_id, _cs) {}
virtual ULONG length(ULONG srcLen, const UCHAR* src, bool countTrailingSpaces) const;
virtual ULONG substring(ULONG srcLen, const UCHAR* src, ULONG dstLen, UCHAR* dst, ULONG startPos, ULONG len) const;
};
class MultiByteCharSet : public CharSet
{
public:
MultiByteCharSet(USHORT _id, charset* _cs) : CharSet(_id, _cs) {}
virtual ULONG length(ULONG srcLen, const UCHAR* src, bool countTrailingSpaces) const;
virtual ULONG substring(ULONG srcLen, const UCHAR* src, ULONG dstLen, UCHAR* dst, ULONG startPos, ULONG len) const;
};
} // namespace
//-------------
ULONG FixedWidthCharSet::length(ULONG srcLen, const UCHAR* src, bool countTrailingSpaces) const
{
if (!countTrailingSpaces)
srcLen = removeTrailingSpaces(srcLen, src);
if (getStruct()->charset_fn_length)
return getStruct()->charset_fn_length(getStruct(), srcLen, src);
else
return srcLen / minBytesPerChar();
}
ULONG FixedWidthCharSet::substring(ULONG srcLen, const UCHAR* src, ULONG dstLen, UCHAR* dst, ULONG startPos, ULONG len) const
{
ULONG result;
if (getStruct()->charset_fn_substring)
result = getStruct()->charset_fn_substring(getStruct(), srcLen, src, dstLen, dst, startPos, len);
else
{
fb_assert(src != NULL && dst != NULL);
if (dstLen < len * minBytesPerChar())
result = INTL_BAD_STR_LENGTH;
else if (startPos * minBytesPerChar() > srcLen)
result = 0;
else
{
result = MIN(srcLen / minBytesPerChar() - startPos, len) * minBytesPerChar();
memcpy(dst, src + startPos * minBytesPerChar(), result);
}
}
if (result == INTL_BAD_STR_LENGTH)
Firebird::status_exception::raise(isc_arith_except, 0);
return result;
}
//-------------
ULONG MultiByteCharSet::length(ULONG srcLen, const UCHAR* src, bool countTrailingSpaces) const
{
if (!countTrailingSpaces)
srcLen = removeTrailingSpaces(srcLen, src);
if (getStruct()->charset_fn_length)
return getStruct()->charset_fn_length(getStruct(), srcLen, src);
else
{
ULONG len = getConvToUnicode().convertLength(srcLen);
// convert to UTF16
Firebird::HalfStaticArray<USHORT, BUFFER_SMALL> str;
len = getConvToUnicode().convert(srcLen, src, len,
str.getBuffer(len / sizeof(USHORT)));
// calculate length of UTF16
return UnicodeUtil::utf16Length(len, str.begin());
}
}
ULONG MultiByteCharSet::substring(ULONG srcLen, const UCHAR* src, ULONG dstLen, UCHAR* dst, ULONG startPos, ULONG len) const
{
ULONG result;
if (getStruct()->charset_fn_substring)
result = getStruct()->charset_fn_substring(getStruct(), srcLen, src, dstLen, dst, startPos, len);
else
{
fb_assert(src != NULL && dst != NULL);
if (len == 0 || startPos >= srcLen)
return 0;
// convert to UTF16
Firebird::HalfStaticArray<UCHAR, BUFFER_SMALL> str;
ULONG unilength = getConvToUnicode().convertLength(srcLen);
unilength = getConvToUnicode().convert(srcLen, src, unilength,
reinterpret_cast<USHORT*>(str.getBuffer(unilength)));
// generate substring of UTF16
Firebird::HalfStaticArray<UCHAR, BUFFER_SMALL> substr;
unilength = UnicodeUtil::utf16Substring(unilength, reinterpret_cast<const USHORT*>(str.begin()),
unilength, reinterpret_cast<USHORT*>(substr.getBuffer(unilength)), startPos, len);
// convert generated substring to original charset
result = getConvFromUnicode().convert(unilength, substr.begin(), dstLen, dst);
}
if (result == INTL_BAD_STR_LENGTH)
Firebird::status_exception::raise(isc_arith_except, 0);
return result;
}
//-------------
namespace Jrd {
CharSet* CharSet::createInstance(MemoryPool& pool, USHORT id, charset* cs)
{
if (cs->charset_min_bytes_per_char != cs->charset_max_bytes_per_char)
return FB_NEW(pool) MultiByteCharSet(id, cs);
else
return FB_NEW(pool) FixedWidthCharSet(id, cs);
}
} // namespace Jrd