1b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/*
2b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*******************************************************************************
3fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius*   Copyright (C) 1996-2014, International Business Machines
4b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*   Corporation and others.  All Rights Reserved.
5b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*******************************************************************************
6b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*   file name:  ucol.cpp
7b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*   encoding:   US-ASCII
8b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*   tab size:   8 (not used)
9b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*   indentation:4
10b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*
11b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* Modification history
12b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* Date        Name      Comments
13b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* 1996-1999   various members of ICU team maintained C API for collation framework
14b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* 02/16/2001  synwee    Added internal method getPrevSpecialCE
15b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* 03/01/2001  synwee    Added maxexpansion functionality.
16b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* 03/16/2001  weiv      Collation framework is rewritten in C and made UCA compliant
17fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius* 2012-2014   markus    Rewritten in C++ again.
18b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*/
19b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
20b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "unicode/utypes.h"
21b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
22b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#if !UCONFIG_NO_COLLATION
23b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
24fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#include "unicode/coll.h"
25fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#include "unicode/tblcoll.h"
26b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho#include "unicode/bytestream.h"
27b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "unicode/coleitr.h"
28fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#include "unicode/ucoleitr.h"
29b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "unicode/ustring.h"
30b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "cmemory.h"
31fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#include "collation.h"
32b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "cstring.h"
33b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "putilimp.h"
34c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru#include "uassert.h"
35fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#include "utracimp.h"
36b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
37b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_NAMESPACE_USE
38b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
39fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusU_CAPI UCollator* U_EXPORT2
40fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusucol_openBinary(const uint8_t *bin, int32_t length,
41b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                const UCollator *base,
42b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                UErrorCode *status)
43b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
44fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    if(U_FAILURE(*status)) { return NULL; }
45fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    RuleBasedCollator *coll = new RuleBasedCollator(
46fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            bin, length,
47fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            RuleBasedCollator::rbcFromUCollator(base),
48fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            *status);
49fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    if(coll == NULL) {
50fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        *status = U_MEMORY_ALLOCATION_ERROR;
51b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return NULL;
52b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
53fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    if(U_FAILURE(*status)) {
54fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        delete coll;
55b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return NULL;
56b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
57fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    return coll->toUCollator();
58b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
59b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
60c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste QueruU_CAPI int32_t U_EXPORT2
61c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queruucol_cloneBinary(const UCollator *coll,
62c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                 uint8_t *buffer, int32_t capacity,
63c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                 UErrorCode *status)
64c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru{
65c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    if(U_FAILURE(*status)) {
66fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        return 0;
67c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
68fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    const RuleBasedCollator *rbc = RuleBasedCollator::rbcFromUCollator(coll);
69fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    if(rbc == NULL && coll != NULL) {
70fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        *status = U_UNSUPPORTED_ERROR;
71fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        return 0;
72c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
73fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    return rbc->cloneBinary(buffer, capacity, *status);
74c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru}
75c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
76b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CAPI UCollator* U_EXPORT2
7759d709d503bab6e2b61931737e662dd293b40578ccorneliusucol_safeClone(const UCollator *coll, void * /*stackBuffer*/, int32_t * pBufferSize, UErrorCode *status)
78b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
79b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (status == NULL || U_FAILURE(*status)){
8059d709d503bab6e2b61931737e662dd293b40578ccornelius        return NULL;
81b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
8259d709d503bab6e2b61931737e662dd293b40578ccornelius    if (coll == NULL) {
83b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru       *status = U_ILLEGAL_ARGUMENT_ERROR;
8459d709d503bab6e2b61931737e662dd293b40578ccornelius        return NULL;
85b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
8659d709d503bab6e2b61931737e662dd293b40578ccornelius    if (pBufferSize != NULL) {
8759d709d503bab6e2b61931737e662dd293b40578ccornelius        int32_t inputSize = *pBufferSize;
8859d709d503bab6e2b61931737e662dd293b40578ccornelius        *pBufferSize = 1;
8959d709d503bab6e2b61931737e662dd293b40578ccornelius        if (inputSize == 0) {
9059d709d503bab6e2b61931737e662dd293b40578ccornelius            return NULL;  // preflighting for deprecated functionality
91b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
92b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
93fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    Collator *newColl = Collator::fromUCollator(coll)->clone();
94fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    if (newColl == NULL) {
9559d709d503bab6e2b61931737e662dd293b40578ccornelius        *status = U_MEMORY_ALLOCATION_ERROR;
96fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    } else {
97fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        *status = U_SAFECLONE_ALLOCATED_WARNING;
98b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
99fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    return newColl->toUCollator();
100b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
101b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
102b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CAPI void U_EXPORT2
103b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruucol_close(UCollator *coll)
104b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
105b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UTRACE_ENTRY_OC(UTRACE_UCOL_CLOSE);
106b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UTRACE_DATA1(UTRACE_INFO, "coll = %p", coll);
107b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(coll != NULL) {
108fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        delete Collator::fromUCollator(coll);
109b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
110b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UTRACE_EXIT();
111b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
112b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
113fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusU_CAPI int32_t U_EXPORT2
114fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusucol_mergeSortkeys(const uint8_t *src1, int32_t src1Length,
115fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                   const uint8_t *src2, int32_t src2Length,
116fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                   uint8_t *dest, int32_t destCapacity) {
117fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    /* check arguments */
118fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    if( src1==NULL || src1Length<-1 || src1Length==0 || (src1Length>0 && src1[src1Length-1]!=0) ||
119fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        src2==NULL || src2Length<-1 || src2Length==0 || (src2Length>0 && src2[src2Length-1]!=0) ||
120fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        destCapacity<0 || (destCapacity>0 && dest==NULL)
121fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    ) {
122fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        /* error, attempt to write a zero byte and return 0 */
123fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        if(dest!=NULL && destCapacity>0) {
124fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            *dest=0;
125c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        }
126fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        return 0;
127b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
128b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
129fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    /* check lengths and capacity */
130fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    if(src1Length<0) {
131fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        src1Length=(int32_t)uprv_strlen((const char *)src1)+1;
132b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
133fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    if(src2Length<0) {
134fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        src2Length=(int32_t)uprv_strlen((const char *)src2)+1;
135b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
136b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
137fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    int32_t destLength=src1Length+src2Length;
138fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    if(destLength>destCapacity) {
139fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        /* the merged sort key does not fit into the destination */
140fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        return destLength;
141b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
142b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
143fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    /* merge the sort keys with the same number of levels */
144fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    uint8_t *p=dest;
145fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    for(;;) {
146fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        /* copy level from src1 not including 00 or 01 */
147fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        uint8_t b;
148fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        while((b=*src1)>=2) {
149fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            ++src1;
150fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            *p++=b;
151b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
152b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
153fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        /* add a 02 merge separator */
154fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        *p++=2;
155b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
156fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        /* copy level from src2 not including 00 or 01 */
157fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        while((b=*src2)>=2) {
158fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            ++src2;
159fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            *p++=b;
160b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
161b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
162fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        /* if both sort keys have another level, then add a 01 level separator and continue */
163fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        if(*src1==1 && *src2==1) {
164fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            ++src1;
165fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            ++src2;
166fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            *p++=1;
167fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        } else {
168fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            break;
169b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
170b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
171b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
172fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    /*
173fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius     * here, at least one sort key is finished now, but the other one
174fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius     * might have some contents left from containing more levels;
175fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius     * that contents is just appended to the result
176b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     */
177fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    if(*src1!=0) {
178fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        /* src1 is not finished, therefore *src2==0, and src1 is appended */
179fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        src2=src1;
180b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
181fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    /* append src2, "the other, unfinished sort key" */
182fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    while((*p++=*src2++)!=0) {}
183b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
184fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    /* the actual length might be less than destLength if either sort key contained illegally embedded zero bytes */
185fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    return (int32_t)(p-dest);
186b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
187b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
188fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusU_CAPI int32_t U_EXPORT2
189fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusucol_getSortKey(const    UCollator    *coll,
190fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        const    UChar        *source,
191fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        int32_t        sourceLength,
192fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        uint8_t        *result,
193fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        int32_t        resultLength)
194b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
195fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    UTRACE_ENTRY(UTRACE_UCOL_GET_SORTKEY);
196fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    if (UTRACE_LEVEL(UTRACE_VERBOSE)) {
197fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        UTRACE_DATA3(UTRACE_VERBOSE, "coll=%p, source string = %vh ", coll, source,
198fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            ((sourceLength==-1 && source!=NULL) ? u_strlen(source) : sourceLength));
199b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
200b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
201fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    int32_t keySize = Collator::fromUCollator(coll)->
202fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            getSortKey(source, sourceLength, result, resultLength);
203b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
204fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    UTRACE_DATA2(UTRACE_VERBOSE, "Sort Key = %vb", result, keySize);
205fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    UTRACE_EXIT_VALUE(keySize);
206fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    return keySize;
207b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
208b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
209fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusU_CAPI int32_t U_EXPORT2
210fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusucol_nextSortKeyPart(const UCollator *coll,
211fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                     UCharIterator *iter,
212fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                     uint32_t state[2],
213fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                     uint8_t *dest, int32_t count,
214fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                     UErrorCode *status)
215b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
216fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    /* error checking */
217fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    if(status==NULL || U_FAILURE(*status)) {
218fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        return 0;
219b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
220fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    UTRACE_ENTRY(UTRACE_UCOL_NEXTSORTKEYPART);
221fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    UTRACE_DATA6(UTRACE_VERBOSE, "coll=%p, iter=%p, state=%d %d, dest=%p, count=%d",
222fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                  coll, iter, state[0], state[1], dest, count);
223b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
224fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    int32_t i = Collator::fromUCollator(coll)->
225fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            internalNextSortKeyPart(iter, state, dest, count, *status);
226b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
227fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    // Return number of meaningful sortkey bytes.
228fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    UTRACE_DATA4(UTRACE_VERBOSE, "dest = %vb, state=%d %d",
229fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                  dest,i, state[0], state[1]);
230fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    UTRACE_EXIT_VALUE_STATUS(i, *status);
231fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    return i;
232b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
233b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
234fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius/**
235fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius * Produce a bound for a given sortkey and a number of levels.
236fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius */
237fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusU_CAPI int32_t U_EXPORT2
238fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusucol_getBound(const uint8_t       *source,
239fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        int32_t             sourceLength,
240fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        UColBoundMode       boundType,
241fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        uint32_t            noOfLevels,
242fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        uint8_t             *result,
243fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        int32_t             resultLength,
244fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        UErrorCode          *status)
245b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
246fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    // consistency checks
247fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    if(status == NULL || U_FAILURE(*status)) {
248fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        return 0;
249b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
250fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    if(source == NULL) {
251fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        *status = U_ILLEGAL_ARGUMENT_ERROR;
252fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        return 0;
253b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
254b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
255fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    int32_t sourceIndex = 0;
256fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    // Scan the string until we skip enough of the key OR reach the end of the key
257fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    do {
258fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        sourceIndex++;
259fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        if(source[sourceIndex] == Collation::LEVEL_SEPARATOR_BYTE) {
260fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            noOfLevels--;
261b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
262fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    } while (noOfLevels > 0
263fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        && (source[sourceIndex] != 0 || sourceIndex < sourceLength));
264b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
265fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    if((source[sourceIndex] == 0 || sourceIndex == sourceLength)
266fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        && noOfLevels > 0) {
267fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            *status = U_SORT_KEY_TOO_SHORT_WARNING;
26850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    }
269b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
270b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
271fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    // READ ME: this code assumes that the values for boundType
272fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    // enum will not changes. They are set so that the enum value
273fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    // corresponds to the number of extra bytes each bound type
274fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    // needs.
275fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    if(result != NULL && resultLength >= sourceIndex+boundType) {
276fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        uprv_memcpy(result, source, sourceIndex);
277fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        switch(boundType) {
278fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            // Lower bound just gets terminated. No extra bytes
279fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        case UCOL_BOUND_LOWER: // = 0
280fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            break;
281fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            // Upper bound needs one extra byte
282fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        case UCOL_BOUND_UPPER: // = 1
283fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            result[sourceIndex++] = 2;
284fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            break;
285fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            // Upper long bound needs two extra bytes
286fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        case UCOL_BOUND_UPPER_LONG: // = 2
287fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            result[sourceIndex++] = 0xFF;
288fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            result[sourceIndex++] = 0xFF;
289fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            break;
290fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        default:
291fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            *status = U_ILLEGAL_ARGUMENT_ERROR;
292fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            return 0;
293c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        }
294fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        result[sourceIndex++] = 0;
295b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
296fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        return sourceIndex;
297fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    } else {
298fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        return sourceIndex+boundType+1;
299b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
300b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
301b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
302fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusU_CAPI void U_EXPORT2
303fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusucol_setMaxVariable(UCollator *coll, UColReorderCode group, UErrorCode *pErrorCode) {
304fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    if(U_FAILURE(*pErrorCode)) { return; }
305fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    Collator::fromUCollator(coll)->setMaxVariable(group, *pErrorCode);
306fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius}
307b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
308fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusU_CAPI UColReorderCode U_EXPORT2
309fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusucol_getMaxVariable(const UCollator *coll) {
310fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    return Collator::fromUCollator(coll)->getMaxVariable();
311fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius}
312c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
313fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusU_CAPI uint32_t  U_EXPORT2
314fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusucol_setVariableTop(UCollator *coll, const UChar *varTop, int32_t len, UErrorCode *status) {
315fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    if(U_FAILURE(*status) || coll == NULL) {
316fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        return 0;
317c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
318fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    return Collator::fromUCollator(coll)->setVariableTop(varTop, len, *status);
319fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius}
320b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
321fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusU_CAPI uint32_t U_EXPORT2 ucol_getVariableTop(const UCollator *coll, UErrorCode *status) {
322fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    if(U_FAILURE(*status) || coll == NULL) {
323fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        return 0;
324b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
325fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    return Collator::fromUCollator(coll)->getVariableTop(*status);
326fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius}
327b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
328fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusU_CAPI void  U_EXPORT2
329fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusucol_restoreVariableTop(UCollator *coll, const uint32_t varTop, UErrorCode *status) {
330fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    if(U_FAILURE(*status) || coll == NULL) {
331fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        return;
332b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
333fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    Collator::fromUCollator(coll)->setVariableTop(varTop, *status);
334b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
335b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
336fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusU_CAPI void  U_EXPORT2
337fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusucol_setAttribute(UCollator *coll, UColAttribute attr, UColAttributeValue value, UErrorCode *status) {
338fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    if(U_FAILURE(*status) || coll == NULL) {
339fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius      return;
34050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    }
341b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
342fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    Collator::fromUCollator(coll)->setAttribute(attr, value, *status);
343fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius}
344c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
345fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusU_CAPI UColAttributeValue  U_EXPORT2
346fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusucol_getAttribute(const UCollator *coll, UColAttribute attr, UErrorCode *status) {
347fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    if(U_FAILURE(*status) || coll == NULL) {
348fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius      return UCOL_DEFAULT;
349b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
350b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
351fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    return Collator::fromUCollator(coll)->getAttribute(attr, *status);
35254dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius}
353b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
354fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusU_CAPI void U_EXPORT2
355fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusucol_setStrength(    UCollator                *coll,
356fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            UCollationStrength        strength)
35754dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius{
358fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    UErrorCode status = U_ZERO_ERROR;
359fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    ucol_setAttribute(coll, UCOL_STRENGTH, strength, &status);
36054dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius}
361c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
362fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusU_CAPI UCollationStrength U_EXPORT2
363fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusucol_getStrength(const UCollator *coll)
36454dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius{
365fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    UErrorCode status = U_ZERO_ERROR;
366fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    return ucol_getAttribute(coll, UCOL_STRENGTH, &status);
367fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius}
36854dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius
369fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusU_CAPI int32_t U_EXPORT2
370fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusucol_getReorderCodes(const UCollator *coll,
371fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                    int32_t *dest,
372fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                    int32_t destCapacity,
373fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                    UErrorCode *status) {
374fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    if (U_FAILURE(*status)) {
375fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        return 0;
37654dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius    }
37754dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius
378fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    return Collator::fromUCollator(coll)->getReorderCodes(dest, destCapacity, *status);
379fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius}
38054dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius
381fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusU_CAPI void U_EXPORT2
382fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusucol_setReorderCodes(UCollator* coll,
383fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                    const int32_t* reorderCodes,
384fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                    int32_t reorderCodesLength,
385fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                    UErrorCode *status) {
386fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    if (U_FAILURE(*status)) {
387fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        return;
388fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    }
38954dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius
390fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    Collator::fromUCollator(coll)->setReorderCodes(reorderCodes, reorderCodesLength, *status);
391fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius}
39254dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius
393fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusU_CAPI int32_t U_EXPORT2
394fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusucol_getEquivalentReorderCodes(int32_t reorderCode,
395fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                    int32_t* dest,
396fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                    int32_t destCapacity,
397fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                    UErrorCode *pErrorCode) {
398fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    return Collator::getEquivalentReorderCodes(reorderCode, dest, destCapacity, *pErrorCode);
399fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius}
40054dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius
401fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusU_CAPI void U_EXPORT2
402fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusucol_getVersion(const UCollator* coll,
403fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                UVersionInfo versionInfo)
404fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius{
405fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    Collator::fromUCollator(coll)->getVersion(versionInfo);
40654dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius}
40754dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius
40854dcd9b6a06071f647dac967e9e267abb9410720Craig CorneliusU_CAPI UCollationResult U_EXPORT2
40954dcd9b6a06071f647dac967e9e267abb9410720Craig Corneliusucol_strcollIter( const UCollator    *coll,
41054dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius                 UCharIterator *sIter,
41154dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius                 UCharIterator *tIter,
41254dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius                 UErrorCode         *status)
41354dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius{
41454dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius    if(!status || U_FAILURE(*status)) {
41554dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius        return UCOL_EQUAL;
41654dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius    }
41754dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius
41854dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius    UTRACE_ENTRY(UTRACE_UCOL_STRCOLLITER);
41954dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius    UTRACE_DATA3(UTRACE_VERBOSE, "coll=%p, sIter=%p, tIter=%p", coll, sIter, tIter);
42054dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius
42154dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius    if(sIter == NULL || tIter == NULL || coll == NULL) {
42254dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius        *status = U_ILLEGAL_ARGUMENT_ERROR;
423fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        UTRACE_EXIT_VALUE_STATUS(UCOL_EQUAL, *status);
42454dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius        return UCOL_EQUAL;
42554dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius    }
42654dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius
427fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    UCollationResult result = Collator::fromUCollator(coll)->compare(*sIter, *tIter, *status);
42854dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius
429fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    UTRACE_EXIT_VALUE_STATUS(result, *status);
43054dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius    return result;
43154dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius}
432b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
433b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
434b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/*                                                                      */
435b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/* ucol_strcoll     Main public API string comparison function          */
436b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/*                                                                      */
437b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CAPI UCollationResult U_EXPORT2
438b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruucol_strcoll( const UCollator    *coll,
439b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru              const UChar        *source,
440b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru              int32_t            sourceLength,
441b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru              const UChar        *target,
442c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru              int32_t            targetLength)
443c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru{
444b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    U_ALIGN_CODE(16);
445b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
446b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UTRACE_ENTRY(UTRACE_UCOL_STRCOLL);
447b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (UTRACE_LEVEL(UTRACE_VERBOSE)) {
448c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        UTRACE_DATA3(UTRACE_VERBOSE, "coll=%p, source=%p, target=%p", coll, source, target);
449c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        UTRACE_DATA2(UTRACE_VERBOSE, "source string = %vh ", source, sourceLength);
450c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        UTRACE_DATA2(UTRACE_VERBOSE, "target string = %vh ", target, targetLength);
451b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
452b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
453c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    UErrorCode status = U_ZERO_ERROR;
454fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    UCollationResult returnVal = Collator::fromUCollator(coll)->
455fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            compare(source, sourceLength, target, targetLength, status);
456fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    UTRACE_EXIT_VALUE_STATUS(returnVal, status);
457b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return returnVal;
458b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
459b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
46054dcd9b6a06071f647dac967e9e267abb9410720Craig CorneliusU_CAPI UCollationResult U_EXPORT2
46154dcd9b6a06071f647dac967e9e267abb9410720Craig Corneliusucol_strcollUTF8(
46254dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius        const UCollator *coll,
46354dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius        const char      *source,
46454dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius        int32_t         sourceLength,
46554dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius        const char      *target,
46654dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius        int32_t         targetLength,
46754dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius        UErrorCode      *status)
46854dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius{
46954dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius    U_ALIGN_CODE(16);
47054dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius
47154dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius    UTRACE_ENTRY(UTRACE_UCOL_STRCOLLUTF8);
47254dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius    if (UTRACE_LEVEL(UTRACE_VERBOSE)) {
47354dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius        UTRACE_DATA3(UTRACE_VERBOSE, "coll=%p, source=%p, target=%p", coll, source, target);
47454dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius        UTRACE_DATA2(UTRACE_VERBOSE, "source string = %vb ", source, sourceLength);
47554dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius        UTRACE_DATA2(UTRACE_VERBOSE, "target string = %vb ", target, targetLength);
47654dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius    }
47754dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius
47854dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius    if (U_FAILURE(*status)) {
47954dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius        /* do nothing */
48054dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius        UTRACE_EXIT_VALUE_STATUS(UCOL_EQUAL, *status);
48154dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius        return UCOL_EQUAL;
48254dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius    }
48354dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius
484fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    UCollationResult returnVal = Collator::fromUCollator(coll)->internalCompareUTF8(
485fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            source, sourceLength, target, targetLength, *status);
48654dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius    UTRACE_EXIT_VALUE_STATUS(returnVal, *status);
48754dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius    return returnVal;
48854dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius}
48954dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius
49054dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius
491b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/* convenience function for comparing strings */
492b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CAPI UBool U_EXPORT2
493b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruucol_greater(    const    UCollator        *coll,
494b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        const    UChar            *source,
495b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        int32_t            sourceLength,
496b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        const    UChar            *target,
497b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        int32_t            targetLength)
498b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
499c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    return (ucol_strcoll(coll, source, sourceLength, target, targetLength)
500c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        == UCOL_GREATER);
501b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
502b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
503b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/* convenience function for comparing strings */
504b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CAPI UBool U_EXPORT2
505b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruucol_greaterOrEqual(    const    UCollator    *coll,
506b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            const    UChar        *source,
507b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            int32_t        sourceLength,
508b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            const    UChar        *target,
509b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            int32_t        targetLength)
510b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
511c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    return (ucol_strcoll(coll, source, sourceLength, target, targetLength)
512c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        != UCOL_LESS);
513b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
514b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
515b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/* convenience function for comparing strings */
516b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CAPI UBool U_EXPORT2
517b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruucol_equal(        const    UCollator        *coll,
518b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            const    UChar            *source,
519b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            int32_t            sourceLength,
520b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            const    UChar            *target,
521b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            int32_t            targetLength)
522b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
523c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    return (ucol_strcoll(coll, source, sourceLength, target, targetLength)
524c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        == UCOL_EQUAL);
525b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
526b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
527b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CAPI void U_EXPORT2
528b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruucol_getUCAVersion(const UCollator* coll, UVersionInfo info) {
529fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    const Collator *c = Collator::fromUCollator(coll);
530fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    if(c != NULL) {
531fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        UVersionInfo v;
532fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        c->getVersion(v);
533fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        // Note: This is tied to how the current implementation encodes the UCA version
534fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        // in the overall getVersion().
535fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        // Alternatively, we could load the root collator and get at lower-level data from there.
536fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        // Either way, it will reflect the input collator's UCA version only
537fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        // if it is a known implementation.
538fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        // It would be cleaner to make this a virtual Collator method.
539fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        info[0] = v[1] >> 3;
540fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        info[1] = v[1] & 7;
541fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        info[2] = v[2] >> 6;
542fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        info[3] = 0;
543fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    }
544fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius}
545fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius
546fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusU_CAPI const UChar * U_EXPORT2
547fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusucol_getRules(const UCollator *coll, int32_t *length) {
548fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    const RuleBasedCollator *rbc = RuleBasedCollator::rbcFromUCollator(coll);
549fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    // OK to crash if coll==NULL: We do not want to check "this" pointers.
550fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    if(rbc != NULL || coll == NULL) {
551fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        const UnicodeString &rules = rbc->getRules();
552fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        U_ASSERT(rules.getBuffer()[rules.length()] == 0);
553fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        *length = rules.length();
554fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        return rules.getBuffer();
555fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    }
556fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    static const UChar _NUL = 0;
557fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    *length = 0;
558fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    return &_NUL;
559fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius}
560fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius
561fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusU_CAPI int32_t U_EXPORT2
562fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusucol_getRulesEx(const UCollator *coll, UColRuleOption delta, UChar *buffer, int32_t bufferLen) {
563fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    UnicodeString rules;
564fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    const RuleBasedCollator *rbc = RuleBasedCollator::rbcFromUCollator(coll);
565fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    if(rbc != NULL || coll == NULL) {
566fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        rbc->getRules(delta, rules);
567fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    }
568fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    if(buffer != NULL && bufferLen > 0) {
569fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        UErrorCode errorCode = U_ZERO_ERROR;
570fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        return rules.extract(buffer, bufferLen, errorCode);
571fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    } else {
572fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        return rules.length();
573fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    }
574fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius}
575fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius
576fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusU_CAPI const char * U_EXPORT2
577fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusucol_getLocale(const UCollator *coll, ULocDataLocaleType type, UErrorCode *status) {
578fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    return ucol_getLocaleByType(coll, type, status);
579fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius}
580fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius
581fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusU_CAPI const char * U_EXPORT2
582fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusucol_getLocaleByType(const UCollator *coll, ULocDataLocaleType type, UErrorCode *status) {
583fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    if(U_FAILURE(*status)) {
584fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        return NULL;
585b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
586fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    UTRACE_ENTRY(UTRACE_UCOL_GETLOCALE);
587fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    UTRACE_DATA1(UTRACE_INFO, "coll=%p", coll);
588fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius
589fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    const char *result;
590fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    const RuleBasedCollator *rbc = RuleBasedCollator::rbcFromUCollator(coll);
591fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    if(rbc == NULL && coll != NULL) {
592fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        *status = U_UNSUPPORTED_ERROR;
593fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        result = NULL;
594fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    } else {
595fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        result = rbc->internalGetLocaleID(type, *status);
596fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    }
597fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius
598fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    UTRACE_DATA1(UTRACE_INFO, "result = %s", result);
599fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    UTRACE_EXIT_STATUS(*status);
600fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    return result;
601fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius}
602fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius
603fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusU_CAPI USet * U_EXPORT2
604fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusucol_getTailoredSet(const UCollator *coll, UErrorCode *status) {
605fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    if(U_FAILURE(*status)) {
606fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        return NULL;
607fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    }
608fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    UnicodeSet *set = Collator::fromUCollator(coll)->getTailoredSet(*status);
609fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    if(U_FAILURE(*status)) {
610fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        delete set;
611fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        return NULL;
612fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    }
613fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    return set->toUSet();
614fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius}
615fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius
616fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusU_CAPI UBool U_EXPORT2
617fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusucol_equals(const UCollator *source, const UCollator *target) {
618fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    return source == target ||
619fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        (*Collator::fromUCollator(source)) == (*Collator::fromUCollator(target));
620b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
621b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
622b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif /* #if !UCONFIG_NO_COLLATION */
623