16f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org/*
26f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org******************************************************************************
36f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*
46f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*   Copyright (C) 2003-2013, International Business Machines
56f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*   Corporation and others.  All Rights Reserved.
66f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*
76f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org******************************************************************************
86f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*   file name:  ucnv_ext.cpp
96f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*   encoding:   US-ASCII
106f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*   tab size:   8 (not used)
116f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*   indentation:4
126f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*
136f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*   created on: 2003jun13
146f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*   created by: Markus W. Scherer
156f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*
166f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*   Conversion extensions
176f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*/
186f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
196f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "unicode/utypes.h"
206f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
216f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#if !UCONFIG_NO_CONVERSION && !UCONFIG_NO_LEGACY_CONVERSION
226f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
236f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "unicode/uset.h"
246f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "ucnv_bld.h"
256f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "ucnv_cnv.h"
266f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "ucnv_ext.h"
276f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "cmemory.h"
286f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "uassert.h"
296f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
306f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org/* to Unicode --------------------------------------------------------------- */
316f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
326f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org/*
336f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * @return lookup value for the byte, if found; else 0
346f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org */
356f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstatic inline uint32_t
366f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgucnv_extFindToU(const uint32_t *toUSection, int32_t length, uint8_t byte) {
376f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    uint32_t word0, word;
386f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    int32_t i, start, limit;
396f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
406f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /* check the input byte against the lowest and highest section bytes */
416f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    start=(int32_t)UCNV_EXT_TO_U_GET_BYTE(toUSection[0]);
426f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    limit=(int32_t)UCNV_EXT_TO_U_GET_BYTE(toUSection[length-1]);
436f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(byte<start || limit<byte) {
446f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return 0; /* the byte is out of range */
456f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
466f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
476f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(length==((limit-start)+1)) {
486f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* direct access on a linear array */
496f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return UCNV_EXT_TO_U_GET_VALUE(toUSection[byte-start]); /* could be 0 */
506f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
516f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
526f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /* word0 is suitable for <=toUSection[] comparison, word for <toUSection[] */
536f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    word0=UCNV_EXT_TO_U_MAKE_WORD(byte, 0);
546f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
556f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /*
566f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     * Shift byte once instead of each section word and add 0xffffff.
576f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     * We will compare the shifted/added byte (bbffffff) against
586f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     * section words which have byte values in the same bit position.
596f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     * If and only if byte bb < section byte ss then bbffffff<ssvvvvvv
606f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     * for all v=0..f
616f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     * so we need not mask off the lower 24 bits of each section word.
626f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     */
636f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    word=word0|UCNV_EXT_TO_U_VALUE_MASK;
646f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
656f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /* binary search */
666f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    start=0;
676f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    limit=length;
686f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    for(;;) {
696f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        i=limit-start;
706f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(i<=1) {
716f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            break; /* done */
726f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
736f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* start<limit-1 */
746f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
756f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(i<=4) {
766f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            /* linear search for the last part */
776f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if(word0<=toUSection[start]) {
786f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                break;
796f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
806f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if(++start<limit && word0<=toUSection[start]) {
816f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                break;
826f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
836f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if(++start<limit && word0<=toUSection[start]) {
846f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                break;
856f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
866f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            /* always break at start==limit-1 */
876f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            ++start;
886f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            break;
896f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
906f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
916f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        i=(start+limit)/2;
926f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(word<toUSection[i]) {
936f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            limit=i;
946f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        } else {
956f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            start=i;
966f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
976f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
986f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
996f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /* did we really find it? */
1006f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(start<limit && byte==UCNV_EXT_TO_U_GET_BYTE(word=toUSection[start])) {
1016f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return UCNV_EXT_TO_U_GET_VALUE(word); /* never 0 */
1026f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    } else {
1036f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return 0; /* not found */
1046f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
1056f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
1066f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1076f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org/*
1086f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * TRUE if not an SI/SO stateful converter,
1096f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * or if the match length fits with the current converter state
1106f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org */
1116f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#define UCNV_EXT_TO_U_VERIFY_SISO_MATCH(sisoState, match) \
1126f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    ((sisoState)<0 || ((sisoState)==0) == (match==1))
1136f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1146f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org/*
1156f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * this works like ucnv_extMatchFromU() except
1166f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * - the first character is in pre
1176f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * - no trie is used
1186f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * - the returned matchLength is not offset by 2
1196f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org */
1206f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstatic int32_t
1216f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgucnv_extMatchToU(const int32_t *cx, int8_t sisoState,
1226f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                 const char *pre, int32_t preLength,
1236f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                 const char *src, int32_t srcLength,
1246f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                 uint32_t *pMatchValue,
1256f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                 UBool /*useFallback*/, UBool flush) {
1266f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    const uint32_t *toUTable, *toUSection;
1276f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1286f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    uint32_t value, matchValue;
1296f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    int32_t i, j, idx, length, matchLength;
1306f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    uint8_t b;
1316f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1326f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(cx==NULL || cx[UCNV_EXT_TO_U_LENGTH]<=0) {
1336f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return 0; /* no extension data, no match */
1346f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
1356f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1366f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /* initialize */
1376f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    toUTable=UCNV_EXT_ARRAY(cx, UCNV_EXT_TO_U_INDEX, uint32_t);
1386f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    idx=0;
1396f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1406f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    matchValue=0;
1416f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    i=j=matchLength=0;
1426f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1436f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(sisoState==0) {
1446f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* SBCS state of an SI/SO stateful converter, look at only exactly 1 byte */
1456f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(preLength>1) {
1466f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            return 0; /* no match of a DBCS sequence in SBCS mode */
1476f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        } else if(preLength==1) {
1486f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            srcLength=0;
1496f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        } else /* preLength==0 */ {
1506f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if(srcLength>1) {
1516f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                srcLength=1;
1526f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
1536f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
1546f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        flush=TRUE;
1556f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
1566f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1576f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /* we must not remember fallback matches when not using fallbacks */
1586f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1596f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /* match input units until there is a full match or the input is consumed */
1606f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    for(;;) {
1616f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* go to the next section */
1626f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        toUSection=toUTable+idx;
1636f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1646f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* read first pair of the section */
1656f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        value=*toUSection++;
1666f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        length=UCNV_EXT_TO_U_GET_BYTE(value);
1676f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        value=UCNV_EXT_TO_U_GET_VALUE(value);
1686f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if( value!=0 &&
1696f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            (UCNV_EXT_TO_U_IS_ROUNDTRIP(value) ||
1706f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org             TO_U_USE_FALLBACK(useFallback)) &&
1716f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            UCNV_EXT_TO_U_VERIFY_SISO_MATCH(sisoState, i+j)
1726f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        ) {
1736f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            /* remember longest match so far */
1746f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            matchValue=value;
1756f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            matchLength=i+j;
1766f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
1776f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1786f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* match pre[] then src[] */
1796f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(i<preLength) {
1806f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            b=(uint8_t)pre[i++];
1816f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        } else if(j<srcLength) {
1826f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            b=(uint8_t)src[j++];
1836f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        } else {
1846f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            /* all input consumed, partial match */
1856f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if(flush || (length=(i+j))>UCNV_EXT_MAX_BYTES) {
1866f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                /*
1876f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                 * end of the entire input stream, stop with the longest match so far
1886f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                 * or: partial match must not be longer than UCNV_EXT_MAX_BYTES
1896f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                 * because it must fit into state buffers
1906f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                 */
1916f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                break;
1926f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            } else {
1936f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                /* continue with more input next time */
1946f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                return -length;
1956f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
1966f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
1976f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1986f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* search for the current UChar */
1996f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        value=ucnv_extFindToU(toUSection, length, b);
2006f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(value==0) {
2016f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            /* no match here, stop with the longest match so far */
2026f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            break;
2036f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        } else {
2046f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if(UCNV_EXT_TO_U_IS_PARTIAL(value)) {
2056f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                /* partial match, continue */
2066f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                idx=(int32_t)UCNV_EXT_TO_U_GET_PARTIAL_INDEX(value);
2076f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            } else {
2086f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                if( (UCNV_EXT_TO_U_IS_ROUNDTRIP(value) ||
2096f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                     TO_U_USE_FALLBACK(useFallback)) &&
2106f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    UCNV_EXT_TO_U_VERIFY_SISO_MATCH(sisoState, i+j)
2116f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                ) {
2126f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    /* full match, stop with result */
2136f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    matchValue=value;
2146f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    matchLength=i+j;
2156f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                } else {
2166f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    /* full match on fallback not taken, stop with the longest match so far */
2176f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                }
2186f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                break;
2196f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
2206f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
2216f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
2226f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
2236f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(matchLength==0) {
2246f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* no match at all */
2256f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return 0;
2266f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
2276f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
2286f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /* return result */
2296f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    *pMatchValue=UCNV_EXT_TO_U_MASK_ROUNDTRIP(matchValue);
2306f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return matchLength;
2316f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
2326f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
2336f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstatic inline void
2346f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgucnv_extWriteToU(UConverter *cnv, const int32_t *cx,
2356f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                 uint32_t value,
2366f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                 UChar **target, const UChar *targetLimit,
2376f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                 int32_t **offsets, int32_t srcIndex,
2386f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                 UErrorCode *pErrorCode) {
2396f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /* output the result */
2406f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(UCNV_EXT_TO_U_IS_CODE_POINT(value)) {
2416f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* output a single code point */
2426f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        ucnv_toUWriteCodePoint(
2436f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            cnv, UCNV_EXT_TO_U_GET_CODE_POINT(value),
2446f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            target, targetLimit,
2456f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            offsets, srcIndex,
2466f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            pErrorCode);
2476f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    } else {
2486f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* output a string - with correct data we have resultLength>0 */
2496f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        ucnv_toUWriteUChars(
2506f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            cnv,
2516f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            UCNV_EXT_ARRAY(cx, UCNV_EXT_TO_U_UCHARS_INDEX, UChar)+
2526f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                UCNV_EXT_TO_U_GET_INDEX(value),
2536f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            UCNV_EXT_TO_U_GET_LENGTH(value),
2546f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            target, targetLimit,
2556f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            offsets, srcIndex,
2566f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            pErrorCode);
2576f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
2586f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
2596f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
2606f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org/*
2616f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * get the SI/SO toU state (state 0 is for SBCS, 1 for DBCS),
2626f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * or 1 for DBCS-only,
2636f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * or -1 if the converter is not SI/SO stateful
2646f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org *
2656f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * Note: For SI/SO stateful converters getting here,
2666f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * cnv->mode==0 is equivalent to firstLength==1.
2676f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org */
2686f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#define UCNV_SISO_STATE(cnv) \
2696f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    ((cnv)->sharedData->mbcs.outputType==MBCS_OUTPUT_2_SISO ? (int8_t)(cnv)->mode : \
2706f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     (cnv)->sharedData->mbcs.outputType==MBCS_OUTPUT_DBCS_ONLY ? 1 : -1)
2716f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
2726f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org/*
2736f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * target<targetLimit; set error code for overflow
2746f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org */
2756f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgU_CFUNC UBool
2766f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgucnv_extInitialMatchToU(UConverter *cnv, const int32_t *cx,
2776f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                        int32_t firstLength,
2786f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                        const char **src, const char *srcLimit,
2796f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                        UChar **target, const UChar *targetLimit,
2806f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                        int32_t **offsets, int32_t srcIndex,
2816f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                        UBool flush,
2826f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                        UErrorCode *pErrorCode) {
2836f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    uint32_t value = 0;  /* initialize output-only param to 0 to silence gcc */
2846f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    int32_t match;
2856f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
2866f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /* try to match */
2876f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    match=ucnv_extMatchToU(cx, (int8_t)UCNV_SISO_STATE(cnv),
2886f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                           (const char *)cnv->toUBytes, firstLength,
2896f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                           *src, (int32_t)(srcLimit-*src),
2906f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                           &value,
2916f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                           cnv->useFallback, flush);
2926f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(match>0) {
2936f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* advance src pointer for the consumed input */
2946f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        *src+=match-firstLength;
2956f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
2966f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* write result to target */
2976f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        ucnv_extWriteToU(cnv, cx,
2986f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                         value,
2996f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                         target, targetLimit,
3006f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                         offsets, srcIndex,
3016f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                         pErrorCode);
3026f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return TRUE;
3036f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    } else if(match<0) {
3046f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* save state for partial match */
3056f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        const char *s;
3066f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        int32_t j;
3076f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
3086f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* copy the first code point */
3096f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        s=(const char *)cnv->toUBytes;
3106f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        cnv->preToUFirstLength=(int8_t)firstLength;
3116f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        for(j=0; j<firstLength; ++j) {
3126f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            cnv->preToU[j]=*s++;
3136f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
3146f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
3156f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* now copy the newly consumed input */
3166f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        s=*src;
3176f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        match=-match;
3186f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        for(; j<match; ++j) {
3196f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            cnv->preToU[j]=*s++;
3206f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
3216f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        *src=s; /* same as *src=srcLimit; because we reached the end of input */
3226f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        cnv->preToULength=(int8_t)match;
3236f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return TRUE;
3246f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    } else /* match==0 no match */ {
3256f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return FALSE;
3266f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
3276f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
3286f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
3296f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgU_CFUNC UChar32
3306f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgucnv_extSimpleMatchToU(const int32_t *cx,
3316f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                       const char *source, int32_t length,
3326f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                       UBool useFallback) {
3336f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    uint32_t value = 0;  /* initialize output-only param to 0 to silence gcc */
3346f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    int32_t match;
3356f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
3366f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(length<=0) {
3376f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return 0xffff;
3386f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
3396f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
3406f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /* try to match */
3416f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    match=ucnv_extMatchToU(cx, -1,
3426f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                           source, length,
3436f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                           NULL, 0,
3446f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                           &value,
3456f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                           useFallback, TRUE);
3466f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(match==length) {
3476f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* write result for simple, single-character conversion */
3486f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(UCNV_EXT_TO_U_IS_CODE_POINT(value)) {
3496f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            return UCNV_EXT_TO_U_GET_CODE_POINT(value);
3506f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
3516f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
3526f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
3536f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /*
3546f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     * return no match because
3556f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     * - match>0 && value points to string: simple conversion cannot handle multiple code points
3566f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     * - match>0 && match!=length: not all input consumed, forbidden for this function
3576f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     * - match==0: no match found in the first place
3586f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     * - match<0: partial match, not supported for simple conversion (and flush==TRUE)
3596f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     */
3606f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return 0xfffe;
3616f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
3626f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
3636f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org/*
3646f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * continue partial match with new input
3656f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * never called for simple, single-character conversion
3666f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org */
3676f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgU_CFUNC void
3686f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgucnv_extContinueMatchToU(UConverter *cnv,
3696f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                         UConverterToUnicodeArgs *pArgs, int32_t srcIndex,
3706f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                         UErrorCode *pErrorCode) {
3716f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    uint32_t value = 0;  /* initialize output-only param to 0 to silence gcc */
3726f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    int32_t match, length;
3736f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
3746f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    match=ucnv_extMatchToU(cnv->sharedData->mbcs.extIndexes, (int8_t)UCNV_SISO_STATE(cnv),
3756f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                           cnv->preToU, cnv->preToULength,
3766f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                           pArgs->source, (int32_t)(pArgs->sourceLimit-pArgs->source),
3776f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                           &value,
3786f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                           cnv->useFallback, pArgs->flush);
3796f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(match>0) {
3806f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(match>=cnv->preToULength) {
3816f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            /* advance src pointer for the consumed input */
3826f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            pArgs->source+=match-cnv->preToULength;
3836f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            cnv->preToULength=0;
3846f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        } else {
3856f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            /* the match did not use all of preToU[] - keep the rest for replay */
3866f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            length=cnv->preToULength-match;
3876f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            uprv_memmove(cnv->preToU, cnv->preToU+match, length);
3886f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            cnv->preToULength=(int8_t)-length;
3896f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
3906f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
3916f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* write result */
3926f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        ucnv_extWriteToU(cnv, cnv->sharedData->mbcs.extIndexes,
3936f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                         value,
3946f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                         &pArgs->target, pArgs->targetLimit,
3956f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                         &pArgs->offsets, srcIndex,
3966f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                         pErrorCode);
3976f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    } else if(match<0) {
3986f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* save state for partial match */
3996f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        const char *s;
4006f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        int32_t j;
4016f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
4026f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* just _append_ the newly consumed input to preToU[] */
4036f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        s=pArgs->source;
4046f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        match=-match;
4056f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        for(j=cnv->preToULength; j<match; ++j) {
4066f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            cnv->preToU[j]=*s++;
4076f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
4086f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        pArgs->source=s; /* same as *src=srcLimit; because we reached the end of input */
4096f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        cnv->preToULength=(int8_t)match;
4106f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    } else /* match==0 */ {
4116f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /*
4126f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         * no match
4136f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         *
4146f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         * We need to split the previous input into two parts:
4156f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         *
4166f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         * 1. The first codepage character is unmappable - that's how we got into
4176f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         *    trying the extension data in the first place.
4186f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         *    We need to move it from the preToU buffer
4196f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         *    to the error buffer, set an error code,
4206f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         *    and prepare the rest of the previous input for 2.
4216f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         *
4226f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         * 2. The rest of the previous input must be converted once we
4236f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         *    come back from the callback for the first character.
4246f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         *    At that time, we have to try again from scratch to convert
4256f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         *    these input characters.
4266f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         *    The replay will be handled by the ucnv.c conversion code.
4276f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         */
4286f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
4296f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* move the first codepage character to the error field */
4306f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        uprv_memcpy(cnv->toUBytes, cnv->preToU, cnv->preToUFirstLength);
4316f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        cnv->toULength=cnv->preToUFirstLength;
4326f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
4336f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* move the rest up inside the buffer */
4346f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        length=cnv->preToULength-cnv->preToUFirstLength;
4356f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(length>0) {
4366f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            uprv_memmove(cnv->preToU, cnv->preToU+cnv->preToUFirstLength, length);
4376f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
4386f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
4396f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* mark preToU for replay */
4406f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        cnv->preToULength=(int8_t)-length;
4416f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
4426f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* set the error code for unassigned */
4436f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        *pErrorCode=U_INVALID_CHAR_FOUND;
4446f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
4456f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
4466f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
4476f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org/* from Unicode ------------------------------------------------------------- */
4486f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
4496f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org// Use roundtrips, "good one-way" mappings, and some normal fallbacks.
4506f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstatic inline UBool
4516f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgextFromUUseMapping(UBool useFallback, uint32_t value, UChar32 firstCP) {
4526f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return
4536f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        ((value&UCNV_EXT_FROM_U_STATUS_MASK)!=0 ||
4546f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            FROM_U_USE_FALLBACK(useFallback, firstCP)) &&
4556f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        (value&UCNV_EXT_FROM_U_RESERVED_MASK)==0;
4566f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
4576f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
4586f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org/*
4596f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * @return index of the UChar, if found; else <0
4606f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org */
4616f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstatic inline int32_t
4626f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgucnv_extFindFromU(const UChar *fromUSection, int32_t length, UChar u) {
4636f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    int32_t i, start, limit;
4646f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
4656f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /* binary search */
4666f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    start=0;
4676f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    limit=length;
4686f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    for(;;) {
4696f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        i=limit-start;
4706f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(i<=1) {
4716f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            break; /* done */
4726f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
4736f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* start<limit-1 */
4746f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
4756f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(i<=4) {
4766f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            /* linear search for the last part */
4776f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if(u<=fromUSection[start]) {
4786f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                break;
4796f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
4806f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if(++start<limit && u<=fromUSection[start]) {
4816f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                break;
4826f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
4836f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if(++start<limit && u<=fromUSection[start]) {
4846f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                break;
4856f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
4866f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            /* always break at start==limit-1 */
4876f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            ++start;
4886f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            break;
4896f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
4906f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
4916f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        i=(start+limit)/2;
4926f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(u<fromUSection[i]) {
4936f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            limit=i;
4946f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        } else {
4956f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            start=i;
4966f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
4976f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
4986f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
4996f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /* did we really find it? */
5006f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(start<limit && u==fromUSection[start]) {
5016f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return start;
5026f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    } else {
5036f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return -1; /* not found */
5046f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
5056f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
5066f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
5076f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org/*
5086f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * @param cx pointer to extension data; if NULL, returns 0
5096f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * @param firstCP the first code point before all the other UChars
5106f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * @param pre UChars that must match; !initialMatch: partial match with them
5116f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * @param preLength length of pre, >=0
5126f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * @param src UChars that can be used to complete a match
5136f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * @param srcLength length of src, >=0
5146f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * @param pMatchValue [out] output result value for the match from the data structure
5156f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * @param useFallback "use fallback" flag, usually from cnv->useFallback
5166f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * @param flush TRUE if the end of the input stream is reached
5176f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * @return >1: matched, return value=total match length (number of input units matched)
5186f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org *          1: matched, no mapping but request for <subchar1>
5196f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org *             (only for the first code point)
5206f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org *          0: no match
5216f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org *         <0: partial match, return value=negative total match length
5226f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org *             (partial matches are never returned for flush==TRUE)
5236f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org *             (partial matches are never returned as being longer than UCNV_EXT_MAX_UCHARS)
5246f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org *         the matchLength is 2 if only firstCP matched, and >2 if firstCP and
5256f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org *         further code units matched
5266f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org */
5276f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstatic int32_t
5286f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgucnv_extMatchFromU(const int32_t *cx,
5296f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                   UChar32 firstCP,
5306f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                   const UChar *pre, int32_t preLength,
5316f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                   const UChar *src, int32_t srcLength,
5326f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                   uint32_t *pMatchValue,
5336f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                   UBool useFallback, UBool flush) {
5346f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    const uint16_t *stage12, *stage3;
5356f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    const uint32_t *stage3b;
5366f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
5376f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    const UChar *fromUTableUChars, *fromUSectionUChars;
5386f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    const uint32_t *fromUTableValues, *fromUSectionValues;
5396f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
5406f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    uint32_t value, matchValue;
5416f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    int32_t i, j, idx, length, matchLength;
5426f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    UChar c;
5436f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
5446f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(cx==NULL) {
5456f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return 0; /* no extension data, no match */
5466f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
5476f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
5486f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /* trie lookup of firstCP */
5496f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    idx=firstCP>>10; /* stage 1 index */
5506f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(idx>=cx[UCNV_EXT_FROM_U_STAGE_1_LENGTH]) {
5516f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return 0; /* the first code point is outside the trie */
5526f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
5536f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
5546f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    stage12=UCNV_EXT_ARRAY(cx, UCNV_EXT_FROM_U_STAGE_12_INDEX, uint16_t);
5556f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    stage3=UCNV_EXT_ARRAY(cx, UCNV_EXT_FROM_U_STAGE_3_INDEX, uint16_t);
5566f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    idx=UCNV_EXT_FROM_U(stage12, stage3, idx, firstCP);
5576f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
5586f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    stage3b=UCNV_EXT_ARRAY(cx, UCNV_EXT_FROM_U_STAGE_3B_INDEX, uint32_t);
5596f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    value=stage3b[idx];
5606f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(value==0) {
5616f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return 0;
5626f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
5636f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
5646f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /*
5656f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     * Tests for (value&UCNV_EXT_FROM_U_RESERVED_MASK)==0:
5666f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     * Do not interpret values with reserved bits used, for forward compatibility,
5676f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     * and do not even remember intermediate results with reserved bits used.
5686f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     */
5696f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
5706f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(UCNV_EXT_TO_U_IS_PARTIAL(value)) {
5716f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* partial match, enter the loop below */
5726f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        idx=(int32_t)UCNV_EXT_FROM_U_GET_PARTIAL_INDEX(value);
5736f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
5746f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* initialize */
5756f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        fromUTableUChars=UCNV_EXT_ARRAY(cx, UCNV_EXT_FROM_U_UCHARS_INDEX, UChar);
5766f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        fromUTableValues=UCNV_EXT_ARRAY(cx, UCNV_EXT_FROM_U_VALUES_INDEX, uint32_t);
5776f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
5786f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        matchValue=0;
5796f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        i=j=matchLength=0;
5806f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
5816f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* we must not remember fallback matches when not using fallbacks */
5826f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
5836f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* match input units until there is a full match or the input is consumed */
5846f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        for(;;) {
5856f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            /* go to the next section */
5866f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            fromUSectionUChars=fromUTableUChars+idx;
5876f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            fromUSectionValues=fromUTableValues+idx;
5886f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
5896f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            /* read first pair of the section */
5906f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            length=*fromUSectionUChars++;
5916f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            value=*fromUSectionValues++;
5926f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if(value!=0 && extFromUUseMapping(useFallback, value, firstCP)) {
5936f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                /* remember longest match so far */
5946f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                matchValue=value;
5956f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                matchLength=2+i+j;
5966f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
5976f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
5986f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            /* match pre[] then src[] */
5996f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if(i<preLength) {
6006f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                c=pre[i++];
6016f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            } else if(j<srcLength) {
6026f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                c=src[j++];
6036f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            } else {
6046f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                /* all input consumed, partial match */
6056f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                if(flush || (length=(i+j))>UCNV_EXT_MAX_UCHARS) {
6066f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    /*
6076f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                     * end of the entire input stream, stop with the longest match so far
6086f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                     * or: partial match must not be longer than UCNV_EXT_MAX_UCHARS
6096f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                     * because it must fit into state buffers
6106f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                     */
6116f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    break;
6126f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                } else {
6136f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    /* continue with more input next time */
6146f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    return -(2+length);
6156f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                }
6166f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
6176f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
6186f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            /* search for the current UChar */
6196f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            idx=ucnv_extFindFromU(fromUSectionUChars, length, c);
6206f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if(idx<0) {
6216f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                /* no match here, stop with the longest match so far */
6226f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                break;
6236f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            } else {
6246f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                value=fromUSectionValues[idx];
6256f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                if(UCNV_EXT_FROM_U_IS_PARTIAL(value)) {
6266f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    /* partial match, continue */
6276f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    idx=(int32_t)UCNV_EXT_FROM_U_GET_PARTIAL_INDEX(value);
6286f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                } else {
6296f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    if(extFromUUseMapping(useFallback, value, firstCP)) {
6306f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                        /* full match, stop with result */
6316f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                        matchValue=value;
6326f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                        matchLength=2+i+j;
6336f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    } else {
6346f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                        /* full match on fallback not taken, stop with the longest match so far */
6356f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    }
6366f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    break;
6376f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                }
6386f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
6396f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
6406f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
6416f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(matchLength==0) {
6426f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            /* no match at all */
6436f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            return 0;
6446f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
6456f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    } else /* result from firstCP trie lookup */ {
6466f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(extFromUUseMapping(useFallback, value, firstCP)) {
6476f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            /* full match, stop with result */
6486f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            matchValue=value;
6496f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            matchLength=2;
6506f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        } else {
6516f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            /* fallback not taken */
6526f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            return 0;
6536f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
6546f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
6556f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
6566f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /* return result */
6576f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(matchValue==UCNV_EXT_FROM_U_SUBCHAR1) {
6586f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return 1; /* assert matchLength==2 */
6596f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
6606f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
6616f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    *pMatchValue=matchValue;
6626f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return matchLength;
6636f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
6646f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
6656f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org/*
6666f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * @param value fromUnicode mapping table value; ignores roundtrip and reserved bits
6676f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org */
6686f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstatic inline void
6696f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgucnv_extWriteFromU(UConverter *cnv, const int32_t *cx,
6706f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                   uint32_t value,
6716f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                   char **target, const char *targetLimit,
6726f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                   int32_t **offsets, int32_t srcIndex,
6736f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                   UErrorCode *pErrorCode) {
6746f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    uint8_t buffer[1+UCNV_EXT_MAX_BYTES];
6756f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    const uint8_t *result;
6766f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    int32_t length, prevLength;
6776f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
6786f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    length=UCNV_EXT_FROM_U_GET_LENGTH(value);
6796f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    value=(uint32_t)UCNV_EXT_FROM_U_GET_DATA(value);
6806f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
6816f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /* output the result */
6826f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(length<=UCNV_EXT_FROM_U_MAX_DIRECT_LENGTH) {
6836f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /*
6846f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         * Generate a byte array and then write it below.
6856f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         * This is not the fastest possible way, but it should be ok for
6866f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         * extension mappings, and it is much simpler.
6876f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         * Offset and overflow handling are only done once this way.
6886f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         */
6896f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        uint8_t *p=buffer+1; /* reserve buffer[0] for shiftByte below */
6906f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        switch(length) {
6916f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        case 3:
6926f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            *p++=(uint8_t)(value>>16);
6936f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        case 2: /*fall through*/
6946f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            *p++=(uint8_t)(value>>8);
6956f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        case 1: /*fall through*/
6966f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            *p++=(uint8_t)value;
6976f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        default:
6986f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            break; /* will never occur */
6996f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
7006f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        result=buffer+1;
7016f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    } else {
7026f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        result=UCNV_EXT_ARRAY(cx, UCNV_EXT_FROM_U_BYTES_INDEX, uint8_t)+value;
7036f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
7046f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
7056f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /* with correct data we have length>0 */
7066f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
7076f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if((prevLength=cnv->fromUnicodeStatus)!=0) {
7086f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* handle SI/SO stateful output */
7096f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        uint8_t shiftByte;
7106f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
7116f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(prevLength>1 && length==1) {
7126f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            /* change from double-byte mode to single-byte */
7136f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            shiftByte=(uint8_t)UCNV_SI;
7146f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            cnv->fromUnicodeStatus=1;
7156f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        } else if(prevLength==1 && length>1) {
7166f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            /* change from single-byte mode to double-byte */
7176f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            shiftByte=(uint8_t)UCNV_SO;
7186f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            cnv->fromUnicodeStatus=2;
7196f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        } else {
7206f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            shiftByte=0;
7216f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
7226f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
7236f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(shiftByte!=0) {
7246f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            /* prepend the shift byte to the result bytes */
7256f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            buffer[0]=shiftByte;
7266f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if(result!=buffer+1) {
7276f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                uprv_memcpy(buffer+1, result, length);
7286f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
7296f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            result=buffer;
7306f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            ++length;
7316f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
7326f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
7336f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
7346f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    ucnv_fromUWriteBytes(cnv, (const char *)result, length,
7356f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                         target, targetLimit,
7366f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                         offsets, srcIndex,
7376f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                         pErrorCode);
7386f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
7396f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
7406f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org/*
7416f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * target<targetLimit; set error code for overflow
7426f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org */
7436f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgU_CFUNC UBool
7446f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgucnv_extInitialMatchFromU(UConverter *cnv, const int32_t *cx,
7456f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                          UChar32 cp,
7466f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                          const UChar **src, const UChar *srcLimit,
7476f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                          char **target, const char *targetLimit,
7486f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                          int32_t **offsets, int32_t srcIndex,
7496f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                          UBool flush,
7506f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                          UErrorCode *pErrorCode) {
7516f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    uint32_t value = 0;  /* initialize output-only param to 0 to silence gcc */
7526f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    int32_t match;
7536f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
7546f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /* try to match */
7556f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    match=ucnv_extMatchFromU(cx, cp,
7566f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                             NULL, 0,
7576f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                             *src, (int32_t)(srcLimit-*src),
7586f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                             &value,
7596f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                             cnv->useFallback, flush);
7606f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
7616f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /* reject a match if the result is a single byte for DBCS-only */
7626f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if( match>=2 &&
7636f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        !(UCNV_EXT_FROM_U_GET_LENGTH(value)==1 &&
7646f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org          cnv->sharedData->mbcs.outputType==MBCS_OUTPUT_DBCS_ONLY)
7656f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    ) {
7666f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* advance src pointer for the consumed input */
7676f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        *src+=match-2; /* remove 2 for the initial code point */
7686f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
7696f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* write result to target */
7706f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        ucnv_extWriteFromU(cnv, cx,
7716f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                           value,
7726f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                           target, targetLimit,
7736f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                           offsets, srcIndex,
7746f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                           pErrorCode);
7756f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return TRUE;
7766f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    } else if(match<0) {
7776f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* save state for partial match */
7786f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        const UChar *s;
7796f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        int32_t j;
7806f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
7816f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* copy the first code point */
7826f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        cnv->preFromUFirstCP=cp;
7836f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
7846f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* now copy the newly consumed input */
7856f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        s=*src;
7866f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        match=-match-2; /* remove 2 for the initial code point */
7876f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        for(j=0; j<match; ++j) {
7886f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            cnv->preFromU[j]=*s++;
7896f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
7906f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        *src=s; /* same as *src=srcLimit; because we reached the end of input */
7916f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        cnv->preFromULength=(int8_t)match;
7926f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return TRUE;
7936f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    } else if(match==1) {
7946f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* matched, no mapping but request for <subchar1> */
7956f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        cnv->useSubChar1=TRUE;
7966f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return FALSE;
7976f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    } else /* match==0 no match */ {
7986f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return FALSE;
7996f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
8006f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
8016f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
8026f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org/*
8036f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * Used by ISO 2022 implementation.
8046f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * @return number of bytes in *pValue; negative number if fallback; 0 for no mapping
8056f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org */
8066f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgU_CFUNC int32_t
8076f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgucnv_extSimpleMatchFromU(const int32_t *cx,
8086f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                         UChar32 cp, uint32_t *pValue,
8096f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                         UBool useFallback) {
8106f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    uint32_t value;
8116f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    int32_t match;
8126f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
8136f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /* try to match */
8146f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    match=ucnv_extMatchFromU(cx,
8156f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                             cp,
8166f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                             NULL, 0,
8176f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                             NULL, 0,
8186f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                             &value,
8196f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                             useFallback, TRUE);
8206f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(match>=2) {
8216f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* write result for simple, single-character conversion */
8226f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        int32_t length;
8236f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        int isRoundtrip;
8246f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
8256f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        isRoundtrip=UCNV_EXT_FROM_U_IS_ROUNDTRIP(value);
8266f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        length=UCNV_EXT_FROM_U_GET_LENGTH(value);
8276f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        value=(uint32_t)UCNV_EXT_FROM_U_GET_DATA(value);
8286f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
8296f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(length<=UCNV_EXT_FROM_U_MAX_DIRECT_LENGTH) {
8306f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            *pValue=value;
8316f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            return isRoundtrip ? length : -length;
8326f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#if 0 /* not currently used */
8336f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        } else if(length==4) {
8346f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            /* de-serialize a 4-byte result */
8356f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            const uint8_t *result=UCNV_EXT_ARRAY(cx, UCNV_EXT_FROM_U_BYTES_INDEX, uint8_t)+value;
8366f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            *pValue=
8376f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                ((uint32_t)result[0]<<24)|
8386f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                ((uint32_t)result[1]<<16)|
8396f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                ((uint32_t)result[2]<<8)|
8406f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                result[3];
8416f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            return isRoundtrip ? 4 : -4;
8426f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#endif
8436f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
8446f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
8456f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
8466f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /*
8476f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     * return no match because
8486f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     * - match>1 && resultLength>4: result too long for simple conversion
8496f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     * - match==1: no match found, <subchar1> preferred
8506f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     * - match==0: no match found in the first place
8516f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     * - match<0: partial match, not supported for simple conversion (and flush==TRUE)
8526f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     */
8536f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return 0;
8546f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
8556f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
8566f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org/*
8576f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * continue partial match with new input, requires cnv->preFromUFirstCP>=0
8586f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * never called for simple, single-character conversion
8596f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org */
8606f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgU_CFUNC void
8616f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgucnv_extContinueMatchFromU(UConverter *cnv,
8626f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                           UConverterFromUnicodeArgs *pArgs, int32_t srcIndex,
8636f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                           UErrorCode *pErrorCode) {
8646f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    uint32_t value = 0;  /* initialize output-only param to 0 to silence gcc */
8656f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    int32_t match;
8666f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
8676f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    match=ucnv_extMatchFromU(cnv->sharedData->mbcs.extIndexes,
8686f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                             cnv->preFromUFirstCP,
8696f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                             cnv->preFromU, cnv->preFromULength,
8706f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                             pArgs->source, (int32_t)(pArgs->sourceLimit-pArgs->source),
8716f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                             &value,
8726f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                             cnv->useFallback, pArgs->flush);
8736f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(match>=2) {
8746f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        match-=2; /* remove 2 for the initial code point */
8756f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
8766f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(match>=cnv->preFromULength) {
8776f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            /* advance src pointer for the consumed input */
8786f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            pArgs->source+=match-cnv->preFromULength;
8796f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            cnv->preFromULength=0;
8806f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        } else {
8816f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            /* the match did not use all of preFromU[] - keep the rest for replay */
8826f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            int32_t length=cnv->preFromULength-match;
8836f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            uprv_memmove(cnv->preFromU, cnv->preFromU+match, length*U_SIZEOF_UCHAR);
8846f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            cnv->preFromULength=(int8_t)-length;
8856f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
8866f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
8876f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* finish the partial match */
8886f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        cnv->preFromUFirstCP=U_SENTINEL;
8896f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
8906f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* write result */
8916f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        ucnv_extWriteFromU(cnv, cnv->sharedData->mbcs.extIndexes,
8926f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                           value,
8936f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                           &pArgs->target, pArgs->targetLimit,
8946f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                           &pArgs->offsets, srcIndex,
8956f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                           pErrorCode);
8966f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    } else if(match<0) {
8976f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* save state for partial match */
8986f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        const UChar *s;
8996f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        int32_t j;
9006f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
9016f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* just _append_ the newly consumed input to preFromU[] */
9026f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        s=pArgs->source;
9036f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        match=-match-2; /* remove 2 for the initial code point */
9046f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        for(j=cnv->preFromULength; j<match; ++j) {
9056f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            U_ASSERT(j>=0);
9066f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            cnv->preFromU[j]=*s++;
9076f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
9086f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        pArgs->source=s; /* same as *src=srcLimit; because we reached the end of input */
9096f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        cnv->preFromULength=(int8_t)match;
9106f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    } else /* match==0 or 1 */ {
9116f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /*
9126f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         * no match
9136f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         *
9146f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         * We need to split the previous input into two parts:
9156f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         *
9166f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         * 1. The first code point is unmappable - that's how we got into
9176f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         *    trying the extension data in the first place.
9186f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         *    We need to move it from the preFromU buffer
9196f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         *    to the error buffer, set an error code,
9206f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         *    and prepare the rest of the previous input for 2.
9216f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         *
9226f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         * 2. The rest of the previous input must be converted once we
9236f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         *    come back from the callback for the first code point.
9246f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         *    At that time, we have to try again from scratch to convert
9256f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         *    these input characters.
9266f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         *    The replay will be handled by the ucnv.c conversion code.
9276f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         */
9286f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
9296f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(match==1) {
9306f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            /* matched, no mapping but request for <subchar1> */
9316f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            cnv->useSubChar1=TRUE;
9326f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
9336f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
9346f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* move the first code point to the error field */
9356f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        cnv->fromUChar32=cnv->preFromUFirstCP;
9366f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        cnv->preFromUFirstCP=U_SENTINEL;
9376f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
9386f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* mark preFromU for replay */
9396f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        cnv->preFromULength=-cnv->preFromULength;
9406f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
9416f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* set the error code for unassigned */
9426f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        *pErrorCode=U_INVALID_CHAR_FOUND;
9436f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
9446f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
9456f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
9466f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstatic UBool
9476f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgextSetUseMapping(UConverterUnicodeSet which, int32_t minLength, uint32_t value) {
9486f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(which==UCNV_ROUNDTRIP_SET) {
9496f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        // Add only code points for which the roundtrip flag is set.
9506f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        // Do not add any fallbacks, even if ucnv_fromUnicode() would use them
9516f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        // (fallbacks from PUA). See the API docs for ucnv_getUnicodeSet().
9526f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        //
9536f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        // By analogy, also do not add "good one-way" mappings.
9546f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        //
9556f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        // Do not add entries with reserved bits set.
9566f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(((value&(UCNV_EXT_FROM_U_ROUNDTRIP_FLAG|UCNV_EXT_FROM_U_RESERVED_MASK))!=
9576f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                UCNV_EXT_FROM_U_ROUNDTRIP_FLAG)) {
9586f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            return FALSE;
9596f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
9606f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    } else /* UCNV_ROUNDTRIP_AND_FALLBACK_SET */ {
9616f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        // Do not add entries with reserved bits set.
9626f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if((value&UCNV_EXT_FROM_U_RESERVED_MASK)!=0) {
9636f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            return FALSE;
9646f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
9656f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
9666f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    // Do not add <subchar1> entries or other (future?) pseudo-entries
9676f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    // with an output length of 0.
9686f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return UCNV_EXT_FROM_U_GET_LENGTH(value)>=minLength;
9696f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
9706f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
9716f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstatic void
9726f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgucnv_extGetUnicodeSetString(const UConverterSharedData *sharedData,
9736f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                            const int32_t *cx,
9746f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                            const USetAdder *sa,
9756f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                            UConverterUnicodeSet which,
9766f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                            int32_t minLength,
9776f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                            UChar32 firstCP,
9786f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                            UChar s[UCNV_EXT_MAX_UCHARS], int32_t length,
9796f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                            int32_t sectionIndex,
9806f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                            UErrorCode *pErrorCode) {
9816f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    const UChar *fromUSectionUChars;
9826f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    const uint32_t *fromUSectionValues;
9836f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
9846f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    uint32_t value;
9856f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    int32_t i, count;
9866f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
9876f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    fromUSectionUChars=UCNV_EXT_ARRAY(cx, UCNV_EXT_FROM_U_UCHARS_INDEX, UChar)+sectionIndex;
9886f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    fromUSectionValues=UCNV_EXT_ARRAY(cx, UCNV_EXT_FROM_U_VALUES_INDEX, uint32_t)+sectionIndex;
9896f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
9906f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /* read first pair of the section */
9916f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    count=*fromUSectionUChars++;
9926f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    value=*fromUSectionValues++;
9936f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
9946f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(extSetUseMapping(which, minLength, value)) {
9956f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(length==U16_LENGTH(firstCP)) {
9966f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            /* add the initial code point */
9976f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            sa->add(sa->set, firstCP);
9986f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        } else {
9996f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            /* add the string so far */
10006f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            sa->addString(sa->set, s, length);
10016f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
10026f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
10036f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
10046f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    for(i=0; i<count; ++i) {
10056f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* append this code unit and recurse or add the string */
10066f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        s[length]=fromUSectionUChars[i];
10076f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        value=fromUSectionValues[i];
10086f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
10096f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(value==0) {
10106f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            /* no mapping, do nothing */
10116f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        } else if(UCNV_EXT_FROM_U_IS_PARTIAL(value)) {
10126f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            ucnv_extGetUnicodeSetString(
10136f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                sharedData, cx, sa, which, minLength,
10146f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                firstCP, s, length+1,
10156f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                (int32_t)UCNV_EXT_FROM_U_GET_PARTIAL_INDEX(value),
10166f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                pErrorCode);
10176f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        } else if(extSetUseMapping(which, minLength, value)) {
10186f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            sa->addString(sa->set, s, length+1);
10196f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
10206f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
10216f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
10226f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
10236f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgU_CFUNC void
10246f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgucnv_extGetUnicodeSet(const UConverterSharedData *sharedData,
10256f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                      const USetAdder *sa,
10266f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                      UConverterUnicodeSet which,
10276f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                      UConverterSetFilter filter,
10286f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                      UErrorCode *pErrorCode) {
10296f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    const int32_t *cx;
10306f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    const uint16_t *stage12, *stage3, *ps2, *ps3;
10316f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    const uint32_t *stage3b;
10326f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
10336f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    uint32_t value;
10346f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    int32_t st1, stage1Length, st2, st3, minLength;
10356f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
10366f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    UChar s[UCNV_EXT_MAX_UCHARS];
10376f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    UChar32 c;
10386f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    int32_t length;
10396f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
10406f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    cx=sharedData->mbcs.extIndexes;
10416f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(cx==NULL) {
10426f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return;
10436f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
10446f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
10456f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    stage12=UCNV_EXT_ARRAY(cx, UCNV_EXT_FROM_U_STAGE_12_INDEX, uint16_t);
10466f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    stage3=UCNV_EXT_ARRAY(cx, UCNV_EXT_FROM_U_STAGE_3_INDEX, uint16_t);
10476f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    stage3b=UCNV_EXT_ARRAY(cx, UCNV_EXT_FROM_U_STAGE_3B_INDEX, uint32_t);
10486f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
10496f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    stage1Length=cx[UCNV_EXT_FROM_U_STAGE_1_LENGTH];
10506f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
10516f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /* enumerate the from-Unicode trie table */
10526f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    c=0; /* keep track of the current code point while enumerating */
10536f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
10546f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(filter==UCNV_SET_FILTER_2022_CN) {
10556f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        minLength=3;
10566f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    } else if( sharedData->mbcs.outputType==MBCS_OUTPUT_DBCS_ONLY ||
10576f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org               filter!=UCNV_SET_FILTER_NONE
10586f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    ) {
10596f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* DBCS-only, ignore single-byte results */
10606f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        minLength=2;
10616f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    } else {
10626f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        minLength=1;
10636f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
10646f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
10656f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /*
10666f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     * the trie enumeration is almost the same as
10676f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     * in MBCSGetUnicodeSet() for MBCS_OUTPUT_1
10686f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     */
10696f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    for(st1=0; st1<stage1Length; ++st1) {
10706f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        st2=stage12[st1];
10716f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(st2>stage1Length) {
10726f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            ps2=stage12+st2;
10736f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            for(st2=0; st2<64; ++st2) {
10746f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                if((st3=(int32_t)ps2[st2]<<UCNV_EXT_STAGE_2_LEFT_SHIFT)!=0) {
10756f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    /* read the stage 3 block */
10766f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    ps3=stage3+st3;
10776f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
10786f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    do {
10796f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                        value=stage3b[*ps3++];
10806f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                        if(value==0) {
10816f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                            /* no mapping, do nothing */
10826f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                        } else if(UCNV_EXT_FROM_U_IS_PARTIAL(value)) {
10836f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                            // Recurse for partial results.
10846f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                            length=0;
10856f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                            U16_APPEND_UNSAFE(s, length, c);
10866f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                            ucnv_extGetUnicodeSetString(
10876f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                                sharedData, cx, sa, which, minLength,
10886f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                                c, s, length,
10896f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                                (int32_t)UCNV_EXT_FROM_U_GET_PARTIAL_INDEX(value),
10906f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                                pErrorCode);
10916f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                        } else if(extSetUseMapping(which, minLength, value)) {
10926f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                            switch(filter) {
10936f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                            case UCNV_SET_FILTER_2022_CN:
10946f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                                if(!(UCNV_EXT_FROM_U_GET_LENGTH(value)==3 && UCNV_EXT_FROM_U_GET_DATA(value)<=0x82ffff)) {
10956f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                                    continue;
10966f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                                }
10976f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                                break;
10986f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                            case UCNV_SET_FILTER_SJIS:
10996f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                                if(!(UCNV_EXT_FROM_U_GET_LENGTH(value)==2 && (value=UCNV_EXT_FROM_U_GET_DATA(value))>=0x8140 && value<=0xeffc)) {
11006f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                                    continue;
11016f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                                }
11026f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                                break;
11036f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                            case UCNV_SET_FILTER_GR94DBCS:
11046f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                                if(!(UCNV_EXT_FROM_U_GET_LENGTH(value)==2 &&
11056f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                                     (uint16_t)((value=UCNV_EXT_FROM_U_GET_DATA(value))-0xa1a1)<=(0xfefe - 0xa1a1) &&
11066f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                                     (uint8_t)(value-0xa1)<=(0xfe - 0xa1))) {
11076f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                                    continue;
11086f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                                }
11096f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                                break;
11106f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                            case UCNV_SET_FILTER_HZ:
11116f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                                if(!(UCNV_EXT_FROM_U_GET_LENGTH(value)==2 &&
11126f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                                     (uint16_t)((value=UCNV_EXT_FROM_U_GET_DATA(value))-0xa1a1)<=(0xfdfe - 0xa1a1) &&
11136f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                                     (uint8_t)(value-0xa1)<=(0xfe - 0xa1))) {
11146f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                                    continue;
11156f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                                }
11166f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                                break;
11176f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                            default:
11186f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                                /*
11196f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                                 * UCNV_SET_FILTER_NONE,
11206f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                                 * or UCNV_SET_FILTER_DBCS_ONLY which is handled via minLength
11216f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                                 */
11226f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                                break;
11236f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                            }
11246f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                            sa->add(sa->set, c);
11256f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                        }
11266f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    } while((++c&0xf)!=0);
11276f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                } else {
11286f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    c+=16; /* empty stage 3 block */
11296f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                }
11306f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
11316f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        } else {
11326f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            c+=1024; /* empty stage 2 block */
11336f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
11346f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
11356f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
11366f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
11376f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#endif /* #if !UCONFIG_NO_LEGACY_CONVERSION */
1138