~ubuntu-branches/ubuntu/quantal/icu/quantal

« back to all changes in this revision

Viewing changes to source/common/ucnv_cnv.c

  • Committer: Package Import Robot
  • Author(s): Yves Arrouye
  • Date: 2002-03-03 15:31:13 UTC
  • Revision ID: package-import@ubuntu.com-20020303153113-3ssceqlq45xbmbnc
Tags: upstream-2.0-2.1pre20020303
ImportĀ upstreamĀ versionĀ 2.0-2.1pre20020303

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
******************************************************************************
 
3
*
 
4
*   Copyright (C) 2000-2001, International Business Machines
 
5
*   Corporation and others.  All Rights Reserved.
 
6
*
 
7
******************************************************************************
 
8
*
 
9
*   uconv_cnv.c:
 
10
*   Implements all the low level conversion functions
 
11
*   T_UnicodeConverter_{to,from}Unicode_$ConversionType
 
12
*
 
13
*   Change history:
 
14
*
 
15
*   06/29/2000  helena      Major rewrite of the callback APIs.
 
16
*/
 
17
 
 
18
#include "unicode/utypes.h"
 
19
#include "unicode/ucnv_err.h"
 
20
#include "ucnv_cnv.h"
 
21
#include "unicode/ucnv.h"
 
22
#include "cmemory.h"
 
23
 
 
24
/*Empties the internal unicode output buffer */
 
25
void  ucnv_flushInternalUnicodeBuffer (UConverter * _this,
 
26
                                  UChar * myTarget,
 
27
                                  int32_t * myTargetIndex,
 
28
                                  int32_t targetLength,
 
29
                                  int32_t** offsets,
 
30
                                  UErrorCode * err)
 
31
{
 
32
    int32_t myUCharErrorBufferLength = _this->UCharErrorBufferLength;
 
33
    
 
34
    if (myUCharErrorBufferLength <= targetLength)
 
35
    {
 
36
        /*we have enough space
 
37
        *So we just copy the whole Error Buffer in to the output stream
 
38
        */
 
39
        uprv_memcpy (myTarget,
 
40
            _this->UCharErrorBuffer,
 
41
            sizeof (UChar) * myUCharErrorBufferLength);
 
42
        if (offsets) 
 
43
        {
 
44
            int32_t i=0;
 
45
            for (i=0; i<myUCharErrorBufferLength;i++) (*offsets)[i] = -1; 
 
46
            *offsets += myUCharErrorBufferLength;
 
47
        }
 
48
        *myTargetIndex += myUCharErrorBufferLength;
 
49
        _this->UCharErrorBufferLength = 0;
 
50
    }
 
51
    else
 
52
    {
 
53
        /* We don't have enough space so we copy as much as we can
 
54
        * on the output stream and update the object
 
55
        * by updating the internal buffer*/
 
56
        uprv_memcpy (myTarget, _this->UCharErrorBuffer, sizeof (UChar) * targetLength);
 
57
        if (offsets) 
 
58
        {
 
59
            int32_t i=0;
 
60
            for (i=0; i< targetLength;i++) (*offsets)[i] = -1; 
 
61
            *offsets += targetLength;
 
62
        }
 
63
        uprv_memmove (_this->UCharErrorBuffer,
 
64
                    _this->UCharErrorBuffer + targetLength,
 
65
                    sizeof (UChar) * (myUCharErrorBufferLength - targetLength));
 
66
        _this->UCharErrorBufferLength -= (int8_t) targetLength;
 
67
        *myTargetIndex = targetLength;
 
68
        *err = U_BUFFER_OVERFLOW_ERROR;
 
69
    }
 
70
}
 
71
 
 
72
/*Empties the internal codepage output buffer */
 
73
void  ucnv_flushInternalCharBuffer (UConverter * _this,
 
74
                               char *myTarget,
 
75
                               int32_t * myTargetIndex,
 
76
                               int32_t targetLength,
 
77
                               int32_t** offsets,
 
78
                               UErrorCode * err)
 
79
{
 
80
    int32_t myCharErrorBufferLength = _this->charErrorBufferLength;
 
81
    
 
82
    /*we have enough space */
 
83
    if (myCharErrorBufferLength <= targetLength)
 
84
    {
 
85
        uprv_memcpy (myTarget, _this->charErrorBuffer, myCharErrorBufferLength);
 
86
        if (offsets) 
 
87
        {
 
88
            int32_t i=0;
 
89
            for (i=0; i<myCharErrorBufferLength;i++) (*offsets)[i] = -1; 
 
90
            *offsets += myCharErrorBufferLength;
 
91
        }
 
92
        
 
93
        *myTargetIndex += myCharErrorBufferLength;
 
94
        _this->charErrorBufferLength = 0;
 
95
    }
 
96
    else
 
97
    {
 
98
        /* We don't have enough space so we copy as much as we can
 
99
        * on the output stream and update the object
 
100
        */
 
101
        uprv_memcpy (myTarget, _this->charErrorBuffer, targetLength);
 
102
        if (offsets) 
 
103
        {
 
104
            int32_t i=0;
 
105
            for (i=0; i< targetLength;i++) (*offsets)[i] = -1; 
 
106
            *offsets += targetLength;
 
107
        }
 
108
        uprv_memmove (_this->charErrorBuffer,
 
109
            _this->charErrorBuffer + targetLength,
 
110
            (myCharErrorBufferLength - targetLength));
 
111
        _this->charErrorBufferLength -= (int8_t) targetLength;
 
112
        *myTargetIndex = targetLength;
 
113
        *err = U_BUFFER_OVERFLOW_ERROR;
 
114
    }
 
115
}
 
116
 
 
117
/**
 
118
 * This function is useful for implementations of getNextUChar().
 
119
 * After a call to a callback function or to toUnicode(), an output buffer
 
120
 * begins with a Unicode code point that needs to be returned as UChar32,
 
121
 * and all following code units must be prepended to the - potentially
 
122
 * prefilled - overflow buffer in the UConverter.
 
123
 * The buffer should be at least of capacity UTF_MAX_CHAR_LENGTH so that a
 
124
 * complete UChar32's UChars fit into it.
 
125
 *
 
126
 * @param cnv    The converter that will get remaining UChars copied to its overflow area.
 
127
 * @param buffer An array of UChars that was passed into a callback function
 
128
 *               or a toUnicode() function.
 
129
 * @param length The number of code units (UChars) that are actually in the buffer.
 
130
 *               This must be >0.
 
131
 * @return The code point from the first UChars in the buffer.
 
132
 */
 
133
U_CFUNC UChar32
 
134
ucnv_getUChar32KeepOverflow(UConverter *cnv, const UChar *buffer, int32_t length) {
 
135
    UChar32 c;
 
136
    int32_t i;
 
137
 
 
138
    if(length<=0) {
 
139
        return 0xffff;
 
140
    }
 
141
 
 
142
    /* get the first code point in the buffer */
 
143
    i=0;
 
144
    UTF_NEXT_CHAR_SAFE(buffer, i, length, c, FALSE);
 
145
    if(i<length) {
 
146
        /* there are UChars left in the buffer that need to go into the overflow buffer */
 
147
        UChar *overflow=cnv->UCharErrorBuffer;
 
148
        int32_t j=cnv->UCharErrorBufferLength;
 
149
 
 
150
        if(j>0) {
 
151
            /* move the overflow buffer contents to make room for the extra UChars */
 
152
            int32_t k;
 
153
 
 
154
            cnv->UCharErrorBufferLength=(int8_t)(k=(length-i)+j);
 
155
            do {
 
156
                overflow[--k]=overflow[--j];
 
157
            } while(j>0);
 
158
        } else {
 
159
            cnv->UCharErrorBufferLength=(int8_t)(length-i);
 
160
        }
 
161
 
 
162
        /* copy the remaining UChars to the beginning of the overflow buffer */
 
163
        do {
 
164
            overflow[j++]=buffer[i++];
 
165
        } while(i<length);
 
166
    }
 
167
    return c;
 
168
}
 
169
 
 
170
/* update target offsets after a callback call */
 
171
U_CFUNC int32_t *
 
172
ucnv_updateCallbackOffsets(int32_t *offsets, int32_t length, int32_t sourceIndex) {
 
173
    if(offsets!=NULL) {
 
174
        if(sourceIndex>=0) {
 
175
            /* add the sourceIndex to the relative offsets that the callback wrote */
 
176
            while(length>0) {
 
177
                *offsets+=sourceIndex;
 
178
                ++offsets;
 
179
                --length;
 
180
            }
 
181
        } else {
 
182
            /* sourceIndex==-1, set -1 offsets */
 
183
            while(length>0) {
 
184
                *offsets=-1;
 
185
                ++offsets;
 
186
                --length;
 
187
            }
 
188
        }
 
189
        return offsets;
 
190
    } else {
 
191
        return NULL;
 
192
    }
 
193
}
 
194
 
 
195
/*
 
196
 * This is a simple implementation of ucnv_getNextUChar() that uses the
 
197
 * converter's toUnicode() function. See ucnv_cnv.h for details.
 
198
 */
 
199
U_CFUNC UChar32
 
200
ucnv_getNextUCharFromToUImpl(UConverterToUnicodeArgs *pArgs,
 
201
                             T_ToUnicodeFunction toU,
 
202
                             UBool collectPairs,
 
203
                             UErrorCode *pErrorCode) {
 
204
    UChar buffer[UTF_MAX_CHAR_LENGTH];
 
205
    const char *realLimit=pArgs->sourceLimit;
 
206
 
 
207
    pArgs->target=buffer;
 
208
    pArgs->targetLimit=buffer+UTF_MAX_CHAR_LENGTH;
 
209
 
 
210
    while(pArgs->source<realLimit) {
 
211
        /* feed in one byte at a time to make sure to get only one character out */
 
212
        pArgs->sourceLimit=pArgs->source+1;
 
213
        pArgs->flush= (UBool)(pArgs->sourceLimit==realLimit);
 
214
 
 
215
        /* convert this byte and check the result */
 
216
        toU(pArgs, pErrorCode);
 
217
        if(U_SUCCESS(*pErrorCode)) {
 
218
            int32_t length=pArgs->target-buffer;
 
219
 
 
220
            /* this test is UTF-16 specific */
 
221
            if(/* some output and
 
222
                  (source consumed or don't collect surrogate pairs or not a surrogate or a surrogate pair) */
 
223
               length>0 &&
 
224
               (pArgs->flush || !collectPairs || !UTF_IS_FIRST_SURROGATE(buffer[0]) || length==2)
 
225
            ) {
 
226
                return ucnv_getUChar32KeepOverflow(pArgs->converter, buffer, length);
 
227
            }
 
228
            /* else continue with the loop */
 
229
        } else if(*pErrorCode==U_BUFFER_OVERFLOW_ERROR) {
 
230
            *pErrorCode=U_ZERO_ERROR;
 
231
            return ucnv_getUChar32KeepOverflow(pArgs->converter, buffer, UTF_MAX_CHAR_LENGTH);
 
232
        } else {
 
233
            /* U_FAILURE() */
 
234
            return 0xffff;
 
235
        }
 
236
    }
 
237
 
 
238
    /* no output because of empty input or only state changes and skipping callbacks */
 
239
    *pErrorCode=U_INDEX_OUTOFBOUNDS_ERROR;
 
240
    return 0xffff;
 
241
}