~ubuntu-branches/ubuntu/karmic/firebird2.1/karmic

« back to all changes in this revision

Viewing changes to src/intl/cv_icu.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Damyan Ivanov
  • Date: 2008-05-26 23:59:25 UTC
  • Revision ID: james.westby@ubuntu.com-20080526235925-2pnqj6nxpppoeaer
Tags: upstream-2.1.0.17798-0.ds2
ImportĀ upstreamĀ versionĀ 2.1.0.17798-0.ds2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 *      PROGRAM:        Firebird International support
 
3
 *      MODULE:         cv_icu.cpp
 
4
 *      DESCRIPTION:    Codeset conversion for ICU character sets.
 
5
 *
 
6
 *  The contents of this file are subject to the Initial
 
7
 *  Developer's Public License Version 1.0 (the "License");
 
8
 *  you may not use this file except in compliance with the
 
9
 *  License. You may obtain a copy of the License at
 
10
 *  http://www.ibphoenix.com/main.nfs?a=ibphoenix&page=ibp_idpl.
 
11
 *
 
12
 *  Software distributed under the License is distributed AS IS,
 
13
 *  WITHOUT WARRANTY OF ANY KIND, either express or implied.
 
14
 *  See the License for the specific language governing rights
 
15
 *  and limitations under the License.
 
16
 *
 
17
 *  The Original Code was created by Adriano dos Santos Fernandes
 
18
 *  for the Firebird Open Source RDBMS project.
 
19
 *
 
20
 *  Copyright (c) 2004 Adriano dos Santos Fernandes <adrianosf@uol.com.br>
 
21
 *  and all contributors signed below.
 
22
 *
 
23
 *  All Rights Reserved.
 
24
 *  Contributor(s): ______________________________________.
 
25
 */
 
26
 
 
27
#include "firebird.h"
 
28
#include "../intl/ldcommon.h"
 
29
#include "ld_proto.h"
 
30
#include "cv_icu.h"
 
31
#include "unicode/ucnv.h"
 
32
 
 
33
 
 
34
namespace
 
35
{
 
36
        struct CsConvertImpl
 
37
        {
 
38
                charset* cs;
 
39
        };
 
40
}
 
41
 
 
42
 
 
43
static UConverter* create_converter(csconvert* cv, UErrorCode* status)
 
44
{
 
45
        UConverter* conv = ucnv_open(cv->csconvert_impl->cs->charset_name, status);
 
46
        const void* oldContext;
 
47
 
 
48
        UConverterFromUCallback oldFromAction;
 
49
        ucnv_setFromUCallBack(
 
50
                conv,
 
51
                UCNV_FROM_U_CALLBACK_STOP,
 
52
                NULL,
 
53
                &oldFromAction,
 
54
                &oldContext,
 
55
                status);
 
56
 
 
57
        UConverterToUCallback oldToAction;
 
58
        ucnv_setToUCallBack(
 
59
                conv,
 
60
                UCNV_TO_U_CALLBACK_STOP,
 
61
                NULL,
 
62
                &oldToAction,
 
63
                &oldContext,
 
64
                status);
 
65
 
 
66
        fb_assert(U_SUCCESS(*status));
 
67
 
 
68
        return conv;
 
69
}
 
70
 
 
71
 
 
72
static void convert_destroy(csconvert* cv)
 
73
{
 
74
        delete cv->csconvert_impl;
 
75
}
 
76
 
 
77
 
 
78
static ULONG unicode_to_icu(csconvert* cv,
 
79
                                                        ULONG srcLen,
 
80
                                                        const BYTE* src,
 
81
                                                        ULONG dstLen,
 
82
                                                        BYTE* dst,
 
83
                                                        USHORT* errCode,
 
84
                                                        ULONG* errPosition)
 
85
{
 
86
        *errCode = 0;
 
87
        *errPosition = 0;
 
88
 
 
89
        if (dst == NULL)
 
90
                return srcLen / sizeof(UChar) * cv->csconvert_impl->cs->charset_max_bytes_per_char;
 
91
 
 
92
        UErrorCode status = U_ZERO_ERROR;
 
93
        UConverter* conv = create_converter(cv, &status);
 
94
 
 
95
        ULONG len = ucnv_fromUChars(conv, reinterpret_cast<char*>(dst), dstLen,
 
96
        Firebird::Aligner<UChar>(src, srcLen), srcLen / sizeof(UChar), &status);
 
97
 
 
98
        if (!U_SUCCESS(status))
 
99
        {
 
100
                len = INTL_BAD_STR_LENGTH;
 
101
 
 
102
                if (status == U_INVALID_CHAR_FOUND)
 
103
                        *errCode = CS_CONVERT_ERROR;
 
104
                else if (status == U_TRUNCATED_CHAR_FOUND)
 
105
                        *errCode = CS_TRUNCATION_ERROR;
 
106
                else
 
107
                {
 
108
                        fb_assert(false);
 
109
                        *errCode = CS_CONVERT_ERROR;
 
110
                }
 
111
        }
 
112
 
 
113
        ucnv_close(conv);
 
114
 
 
115
        return len;
 
116
}
 
117
 
 
118
 
 
119
static ULONG icu_to_unicode(csconvert* cv,
 
120
                                                        ULONG srcLen,
 
121
                                                        const BYTE* src,
 
122
                                                        ULONG dstLen,
 
123
                                                        BYTE* dst,
 
124
                                                        USHORT* errCode,
 
125
                                                        ULONG* errPosition)
 
126
{
 
127
        *errCode = 0;
 
128
        *errPosition = 0;
 
129
 
 
130
        if (dst == NULL)
 
131
                return srcLen / cv->csconvert_impl->cs->charset_min_bytes_per_char * sizeof(UChar);
 
132
 
 
133
        UErrorCode status = U_ZERO_ERROR;
 
134
        UConverter* conv = create_converter(cv, &status);
 
135
 
 
136
        ULONG len = ucnv_toUChars(conv, Firebird::OutAligner<UChar>(dst, dstLen), dstLen / sizeof(UChar),
 
137
        reinterpret_cast<const char*>(src), srcLen, &status);
 
138
 
 
139
        if (!U_SUCCESS(status))
 
140
        {
 
141
                len = INTL_BAD_STR_LENGTH;
 
142
 
 
143
                if (status == U_INVALID_CHAR_FOUND)
 
144
                        *errCode = CS_BAD_INPUT;
 
145
                else if (status == U_TRUNCATED_CHAR_FOUND)
 
146
                        *errCode = CS_TRUNCATION_ERROR;
 
147
                else
 
148
                {
 
149
                        fb_assert(false);
 
150
                        *errCode = CS_BAD_INPUT;
 
151
                }
 
152
        }
 
153
        else
 
154
                len *= sizeof(UChar);
 
155
 
 
156
        ucnv_close(conv);
 
157
 
 
158
        return len;
 
159
}
 
160
 
 
161
 
 
162
void CVICU_convert_init(charset* cs)
 
163
{
 
164
        cs->charset_to_unicode.csconvert_version = CSCONVERT_VERSION_1;
 
165
        cs->charset_to_unicode.csconvert_name = "ICU->UNICODE";
 
166
        cs->charset_to_unicode.csconvert_fn_convert = icu_to_unicode;
 
167
        cs->charset_to_unicode.csconvert_fn_destroy = convert_destroy;
 
168
        cs->charset_to_unicode.csconvert_impl = new CsConvertImpl();
 
169
        cs->charset_to_unicode.csconvert_impl->cs = cs;
 
170
 
 
171
        cs->charset_from_unicode.csconvert_version = CSCONVERT_VERSION_1;
 
172
        cs->charset_from_unicode.csconvert_name = "UNICODE->ICU";
 
173
        cs->charset_from_unicode.csconvert_fn_convert = unicode_to_icu;
 
174
        cs->charset_from_unicode.csconvert_fn_destroy = convert_destroy;
 
175
        cs->charset_from_unicode.csconvert_impl = new CsConvertImpl();
 
176
        cs->charset_from_unicode.csconvert_impl->cs = cs;
 
177
}