1b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/*
2b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *******************************************************************************
3b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *
459d709d503bab6e2b61931737e662dd293b40578ccornelius *   Copyright (C) 2003-2013, International Business Machines
5b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *   Corporation and others.  All Rights Reserved.
6b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *
7b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *******************************************************************************
8b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *   file name:  usprep.cpp
9b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *   encoding:   US-ASCII
10b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *   tab size:   8 (not used)
11b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *   indentation:4
12b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *
13b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *   created on: 2003jul2
14b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *   created by: Ram Viswanadha
15b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru */
16b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
17b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "unicode/utypes.h"
18b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
19b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#if !UCONFIG_NO_IDNA
20b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
21b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "unicode/usprep.h"
22b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
23b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "unicode/unorm.h"
24b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "unicode/ustring.h"
25b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "unicode/uchar.h"
26b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "unicode/uversion.h"
27b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "umutex.h"
28b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "cmemory.h"
29b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "sprpimpl.h"
30b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "ustr_imp.h"
31b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "uhash.h"
32b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "cstring.h"
33b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "udataswp.h"
34b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "ucln_cmn.h"
35b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "ubidi_props.h"
36b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
3750294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoU_NAMESPACE_USE
3850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
39b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CDECL_BEGIN
40b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
41b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/*
42b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruStatic cache for already opened StringPrep profiles
43b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*/
44b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic UHashtable *SHARED_DATA_HASHTABLE = NULL;
4559d709d503bab6e2b61931737e662dd293b40578ccorneliusstatic icu::UInitOnce gSharedDataInitOnce;
46b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
4754dcd9b6a06071f647dac967e9e267abb9410720Craig Corneliusstatic UMutex usprepMutex = U_MUTEX_INITIALIZER;
48b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
49b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/* format version of spp file */
5054dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius//static uint8_t formatVersion[4]={ 0, 0, 0, 0 };
51b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
52b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/* the Unicode version of the sprep data */
53b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic UVersionInfo dataVersion={ 0, 0, 0, 0 };
54b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
55b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru/* Profile names must be aligned to UStringPrepProfileType */
5654dcd9b6a06071f647dac967e9e267abb9410720Craig Corneliusstatic const char * const PROFILE_NAMES[] = {
57b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    "rfc3491",      /* USPREP_RFC3491_NAMEPREP */
58b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    "rfc3530cs",    /* USPREP_RFC3530_NFS4_CS_PREP */
59b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    "rfc3530csci",  /* USPREP_RFC3530_NFS4_CS_PREP_CI */
60b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    "rfc3491",      /* USPREP_RFC3530_NSF4_CIS_PREP */
61b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    "rfc3530mixp",  /* USPREP_RFC3530_NSF4_MIXED_PREP_PREFIX */
62b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    "rfc3491",      /* USPREP_RFC3530_NSF4_MIXED_PREP_SUFFIX */
63b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    "rfc3722",      /* USPREP_RFC3722_ISCSI */
64b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    "rfc3920node",  /* USPREP_RFC3920_NODEPREP */
65b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    "rfc3920res",   /* USPREP_RFC3920_RESOURCEPREP */
66b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    "rfc4011",      /* USPREP_RFC4011_MIB */
67b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    "rfc4013",      /* USPREP_RFC4013_SASLPREP */
68b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    "rfc4505",      /* USPREP_RFC4505_TRACE */
69b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    "rfc4518",      /* USPREP_RFC4518_LDAP */
70b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    "rfc4518ci",    /* USPREP_RFC4518_LDAP_CI */
71b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru};
72b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
73b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic UBool U_CALLCONV
74b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruisSPrepAcceptable(void * /* context */,
75b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru             const char * /* type */,
76b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru             const char * /* name */,
77b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru             const UDataInfo *pInfo) {
78b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(
79b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        pInfo->size>=20 &&
80b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        pInfo->isBigEndian==U_IS_BIG_ENDIAN &&
81b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        pInfo->charsetFamily==U_CHARSET_FAMILY &&
82b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        pInfo->dataFormat[0]==0x53 &&   /* dataFormat="SPRP" */
83b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        pInfo->dataFormat[1]==0x50 &&
84b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        pInfo->dataFormat[2]==0x52 &&
85b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        pInfo->dataFormat[3]==0x50 &&
86b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        pInfo->formatVersion[0]==3 &&
87b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        pInfo->formatVersion[2]==UTRIE_SHIFT &&
88b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        pInfo->formatVersion[3]==UTRIE_INDEX_SHIFT
89b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    ) {
9054dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius        //uprv_memcpy(formatVersion, pInfo->formatVersion, 4);
91b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        uprv_memcpy(dataVersion, pInfo->dataVersion, 4);
92b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return TRUE;
93b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    } else {
94b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return FALSE;
95b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
96b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
97b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
98b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic int32_t U_CALLCONV
99b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QuerugetSPrepFoldingOffset(uint32_t data) {
100b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
101b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return (int32_t)data;
102b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
103b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
104b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
105b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/* hashes an entry  */
106b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic int32_t U_CALLCONV
107b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruhashEntry(const UHashTok parm) {
108b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UStringPrepKey *b = (UStringPrepKey *)parm.pointer;
109b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UHashTok namekey, pathkey;
110b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    namekey.pointer = b->name;
111b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    pathkey.pointer = b->path;
112b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return uhash_hashChars(namekey)+37*uhash_hashChars(pathkey);
113b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
114b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
115b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/* compares two entries */
116b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic UBool U_CALLCONV
117b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QuerucompareEntries(const UHashTok p1, const UHashTok p2) {
118b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UStringPrepKey *b1 = (UStringPrepKey *)p1.pointer;
119b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UStringPrepKey *b2 = (UStringPrepKey *)p2.pointer;
120b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UHashTok name1, name2, path1, path2;
121b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    name1.pointer = b1->name;
122b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    name2.pointer = b2->name;
123b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    path1.pointer = b1->path;
124b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    path2.pointer = b2->path;
125b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return ((UBool)(uhash_compareChars(name1, name2) &
126b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        uhash_compareChars(path1, path2)));
127b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
128b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
129b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic void
130b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruusprep_unload(UStringPrepProfile* data){
131b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    udata_close(data->sprepData);
132b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
133b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
134b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic int32_t
135b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruusprep_internal_flushCache(UBool noRefCount){
136b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UStringPrepProfile *profile = NULL;
137b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UStringPrepKey  *key  = NULL;
138b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t pos = -1;
139b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t deletedNum = 0;
140b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    const UHashElement *e;
141b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
142b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /*
143b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     * if shared data hasn't even been lazy evaluated yet
144b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     * return 0
145b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     */
146b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    umtx_lock(&usprepMutex);
147b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (SHARED_DATA_HASHTABLE == NULL) {
148b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        umtx_unlock(&usprepMutex);
149b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return 0;
150b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
151b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
152b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /*creates an enumeration to iterate through every element in the table */
153b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    while ((e = uhash_nextElement(SHARED_DATA_HASHTABLE, &pos)) != NULL)
154b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {
155b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        profile = (UStringPrepProfile *) e->value.pointer;
156b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        key  = (UStringPrepKey *) e->key.pointer;
157b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
158b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if ((noRefCount== FALSE && profile->refCount == 0) ||
159b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru             noRefCount== TRUE) {
160b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            deletedNum++;
161b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            uhash_removeElement(SHARED_DATA_HASHTABLE, e);
162b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
163b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            /* unload the data */
164b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            usprep_unload(profile);
165b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
166b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if(key->name != NULL) {
167b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                uprv_free(key->name);
168b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                key->name=NULL;
169b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
170b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if(key->path != NULL) {
171b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                uprv_free(key->path);
172b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                key->path=NULL;
173b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
174b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            uprv_free(profile);
175b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            uprv_free(key);
176b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
177b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
178b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
179b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    umtx_unlock(&usprepMutex);
180b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
181b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return deletedNum;
182b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
183b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
184b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/* Works just like ucnv_flushCache()
185b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic int32_t
186b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruusprep_flushCache(){
187b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return usprep_internal_flushCache(FALSE);
188b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
189b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*/
190b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
191b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic UBool U_CALLCONV usprep_cleanup(void){
192b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (SHARED_DATA_HASHTABLE != NULL) {
193b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        usprep_internal_flushCache(TRUE);
194b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (SHARED_DATA_HASHTABLE != NULL && uhash_count(SHARED_DATA_HASHTABLE) == 0) {
195b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            uhash_close(SHARED_DATA_HASHTABLE);
196b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            SHARED_DATA_HASHTABLE = NULL;
197b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
198b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
19959d709d503bab6e2b61931737e662dd293b40578ccornelius    gSharedDataInitOnce.reset();
200b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return (SHARED_DATA_HASHTABLE == NULL);
201b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
202b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CDECL_END
203b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
204b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
205b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/** Initializes the cache for resources */
20659d709d503bab6e2b61931737e662dd293b40578ccorneliusstatic void U_CALLCONV
20759d709d503bab6e2b61931737e662dd293b40578ccorneliuscreateCache(UErrorCode &status) {
20859d709d503bab6e2b61931737e662dd293b40578ccornelius    SHARED_DATA_HASHTABLE = uhash_open(hashEntry, compareEntries, NULL, &status);
20959d709d503bab6e2b61931737e662dd293b40578ccornelius    if (U_FAILURE(status)) {
21059d709d503bab6e2b61931737e662dd293b40578ccornelius        SHARED_DATA_HASHTABLE = NULL;
21159d709d503bab6e2b61931737e662dd293b40578ccornelius    }
21259d709d503bab6e2b61931737e662dd293b40578ccornelius    ucln_common_registerCleanup(UCLN_COMMON_USPREP, usprep_cleanup);
21359d709d503bab6e2b61931737e662dd293b40578ccornelius}
21459d709d503bab6e2b61931737e662dd293b40578ccornelius
215b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic void
216b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruinitCache(UErrorCode *status) {
21759d709d503bab6e2b61931737e662dd293b40578ccornelius    umtx_initOnce(gSharedDataInitOnce, &createCache, *status);
218b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
219b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
220b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic UBool U_CALLCONV
221b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruloadData(UStringPrepProfile* profile,
222b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru         const char* path,
223b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru         const char* name,
224b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru         const char* type,
225b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru         UErrorCode* errorCode) {
226b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* load Unicode SPREP data from file */
227b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UTrie _sprepTrie={ 0,0,0,0,0,0,0 };
228b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UDataMemory *dataMemory;
229b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    const int32_t *p=NULL;
230b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    const uint8_t *pb;
231b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UVersionInfo normUnicodeVersion;
232b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t normUniVer, sprepUniVer, normCorrVer;
233b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
234b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(errorCode==NULL || U_FAILURE(*errorCode)) {
235b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return 0;
236b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
237b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
238b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* open the data outside the mutex block */
239b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    //TODO: change the path
240b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    dataMemory=udata_openChoice(path, type, name, isSPrepAcceptable, NULL, errorCode);
241b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(U_FAILURE(*errorCode)) {
242b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return FALSE;
243b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
244b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
245b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    p=(const int32_t *)udata_getMemory(dataMemory);
246b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    pb=(const uint8_t *)(p+_SPREP_INDEX_TOP);
247b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    utrie_unserialize(&_sprepTrie, pb, p[_SPREP_INDEX_TRIE_SIZE], errorCode);
248b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    _sprepTrie.getFoldingOffset=getSPrepFoldingOffset;
249b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
250b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
251b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(U_FAILURE(*errorCode)) {
252b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        udata_close(dataMemory);
253b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return FALSE;
254b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
255b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
256b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* in the mutex block, set the data for this process */
257b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    umtx_lock(&usprepMutex);
258b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(profile->sprepData==NULL) {
259b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        profile->sprepData=dataMemory;
260b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        dataMemory=NULL;
261b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        uprv_memcpy(&profile->indexes, p, sizeof(profile->indexes));
262b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        uprv_memcpy(&profile->sprepTrie, &_sprepTrie, sizeof(UTrie));
263b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    } else {
264b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        p=(const int32_t *)udata_getMemory(profile->sprepData);
265b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
266b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    umtx_unlock(&usprepMutex);
267b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* initialize some variables */
268b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    profile->mappingData=(uint16_t *)((uint8_t *)(p+_SPREP_INDEX_TOP)+profile->indexes[_SPREP_INDEX_TRIE_SIZE]);
269b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
27050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    u_getUnicodeVersion(normUnicodeVersion);
271b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    normUniVer = (normUnicodeVersion[0] << 24) + (normUnicodeVersion[1] << 16) +
272b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                 (normUnicodeVersion[2] << 8 ) + (normUnicodeVersion[3]);
273b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    sprepUniVer = (dataVersion[0] << 24) + (dataVersion[1] << 16) +
274b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                  (dataVersion[2] << 8 ) + (dataVersion[3]);
275b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    normCorrVer = profile->indexes[_SPREP_NORM_CORRECTNS_LAST_UNI_VERSION];
276b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
277b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(U_FAILURE(*errorCode)){
278b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        udata_close(dataMemory);
279b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return FALSE;
280b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
281b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if( normUniVer < sprepUniVer && /* the Unicode version of SPREP file must be less than the Unicode Vesion of the normalization data */
282b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        normUniVer < normCorrVer && /* the Unicode version of the NormalizationCorrections.txt file should be less than the Unicode Vesion of the normalization data */
283b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        ((profile->indexes[_SPREP_OPTIONS] & _SPREP_NORMALIZATION_ON) > 0) /* normalization turned on*/
284b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      ){
285b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        *errorCode = U_INVALID_FORMAT_ERROR;
286b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        udata_close(dataMemory);
287b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return FALSE;
288b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
289b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    profile->isDataLoaded = TRUE;
290b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
291b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* if a different thread set it first, then close the extra data */
292b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(dataMemory!=NULL) {
293b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        udata_close(dataMemory); /* NULL if it was set correctly */
294b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
295b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
296b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
297b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return profile->isDataLoaded;
298b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
299b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
300b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic UStringPrepProfile*
301b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruusprep_getProfile(const char* path,
302b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                  const char* name,
303b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                  UErrorCode *status){
304b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
305b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UStringPrepProfile* profile = NULL;
306b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
307b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    initCache(status);
308b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
309b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(U_FAILURE(*status)){
310b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return NULL;
311b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
312b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
313b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UStringPrepKey stackKey;
314b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /*
315b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     * const is cast way to save malloc, strcpy and free calls
316b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     * we use the passed in pointers for fetching the data from the
317b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     * hash table which is safe
318b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     */
319b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    stackKey.name = (char*) name;
320b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    stackKey.path = (char*) path;
321b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
322b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* fetch the data from the cache */
323b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    umtx_lock(&usprepMutex);
324b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    profile = (UStringPrepProfile*) (uhash_get(SHARED_DATA_HASHTABLE,&stackKey));
32550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    if(profile != NULL) {
32650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        profile->refCount++;
32750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    }
328b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    umtx_unlock(&usprepMutex);
329b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
33050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    if(profile == NULL) {
331b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* else load the data and put the data in the cache */
33250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        LocalMemory<UStringPrepProfile> newProfile;
33350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        if(newProfile.allocateInsteadAndReset() == NULL) {
334b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            *status = U_MEMORY_ALLOCATION_ERROR;
335b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return NULL;
336b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
337b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
338b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* load the data */
33950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        if(!loadData(newProfile.getAlias(), path, name, _SPREP_DATA_TYPE, status) || U_FAILURE(*status) ){
340b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return NULL;
341b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
34227f654740f2a26ad62a5c155af9199af9e69b889claireho
343b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* get the options */
34450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        newProfile->doNFKC = (UBool)((newProfile->indexes[_SPREP_OPTIONS] & _SPREP_NORMALIZATION_ON) > 0);
34550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        newProfile->checkBiDi = (UBool)((newProfile->indexes[_SPREP_OPTIONS] & _SPREP_CHECK_BIDI_ON) > 0);
346b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
34750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        if(newProfile->checkBiDi) {
34827f654740f2a26ad62a5c155af9199af9e69b889claireho            newProfile->bdp = ubidi_getSingleton();
349b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
35050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
35150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        LocalMemory<UStringPrepKey> key;
35250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        LocalMemory<char> keyName;
35350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        LocalMemory<char> keyPath;
35450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        if( key.allocateInsteadAndReset() == NULL ||
35550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            keyName.allocateInsteadAndCopy(uprv_strlen(name)+1) == NULL ||
35650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            (path != NULL &&
35750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho             keyPath.allocateInsteadAndCopy(uprv_strlen(path)+1) == NULL)
35850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho         ) {
35950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            *status = U_MEMORY_ALLOCATION_ERROR;
36050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            usprep_unload(newProfile.getAlias());
36150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            return NULL;
36250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        }
36350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
364b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        umtx_lock(&usprepMutex);
36527f654740f2a26ad62a5c155af9199af9e69b889claireho        // If another thread already inserted the same key/value, refcount and cleanup our thread data
36627f654740f2a26ad62a5c155af9199af9e69b889claireho        profile = (UStringPrepProfile*) (uhash_get(SHARED_DATA_HASHTABLE,&stackKey));
36727f654740f2a26ad62a5c155af9199af9e69b889claireho        if(profile != NULL) {
36827f654740f2a26ad62a5c155af9199af9e69b889claireho            profile->refCount++;
36927f654740f2a26ad62a5c155af9199af9e69b889claireho            usprep_unload(newProfile.getAlias());
37027f654740f2a26ad62a5c155af9199af9e69b889claireho        }
37127f654740f2a26ad62a5c155af9199af9e69b889claireho        else {
37227f654740f2a26ad62a5c155af9199af9e69b889claireho            /* initialize the key members */
37327f654740f2a26ad62a5c155af9199af9e69b889claireho            key->name = keyName.orphan();
37427f654740f2a26ad62a5c155af9199af9e69b889claireho            uprv_strcpy(key->name, name);
37527f654740f2a26ad62a5c155af9199af9e69b889claireho            if(path != NULL){
37627f654740f2a26ad62a5c155af9199af9e69b889claireho                key->path = keyPath.orphan();
37727f654740f2a26ad62a5c155af9199af9e69b889claireho                uprv_strcpy(key->path, path);
37827f654740f2a26ad62a5c155af9199af9e69b889claireho            }
37927f654740f2a26ad62a5c155af9199af9e69b889claireho            profile = newProfile.orphan();
38027f654740f2a26ad62a5c155af9199af9e69b889claireho
38127f654740f2a26ad62a5c155af9199af9e69b889claireho            /* add the data object to the cache */
38227f654740f2a26ad62a5c155af9199af9e69b889claireho            profile->refCount = 1;
38327f654740f2a26ad62a5c155af9199af9e69b889claireho            uhash_put(SHARED_DATA_HASHTABLE, key.orphan(), profile, status);
38427f654740f2a26ad62a5c155af9199af9e69b889claireho        }
385b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        umtx_unlock(&usprepMutex);
386b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
387b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
388b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return profile;
389b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
390b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
391b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CAPI UStringPrepProfile* U_EXPORT2
392b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruusprep_open(const char* path,
393b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            const char* name,
394b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            UErrorCode* status){
395b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
396b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(status == NULL || U_FAILURE(*status)){
397b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return NULL;
398b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
399b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
400b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* initialize the profile struct members */
401b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return usprep_getProfile(path,name,status);
402b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
403b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
404b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste QueruU_CAPI UStringPrepProfile* U_EXPORT2
405b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queruusprep_openByType(UStringPrepProfileType type,
406b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru				  UErrorCode* status) {
407b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    if(status == NULL || U_FAILURE(*status)){
408b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        return NULL;
409b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    }
410b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    int32_t index = (int32_t)type;
411b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    if (index < 0 || index >= (int32_t)(sizeof(PROFILE_NAMES)/sizeof(PROFILE_NAMES[0]))) {
412b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        *status = U_ILLEGAL_ARGUMENT_ERROR;
413b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        return NULL;
414b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    }
415b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    return usprep_open(NULL, PROFILE_NAMES[index], status);
416b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru}
417b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
418b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CAPI void U_EXPORT2
419b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruusprep_close(UStringPrepProfile* profile){
420b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(profile==NULL){
421b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return;
422b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
423b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
424b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    umtx_lock(&usprepMutex);
425b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* decrement the ref count*/
426b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(profile->refCount > 0){
427b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        profile->refCount--;
428b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
429b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    umtx_unlock(&usprepMutex);
430b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
431b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
432b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
433b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CFUNC void
434b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruuprv_syntaxError(const UChar* rules,
435b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                 int32_t pos,
436b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                 int32_t rulesLen,
437b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                 UParseError* parseError){
438b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(parseError == NULL){
439b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return;
440b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
441b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    parseError->offset = pos;
442b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    parseError->line = 0 ; // we are not using line numbers
443b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
444b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // for pre-context
445b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t start = (pos < U_PARSE_CONTEXT_LEN)? 0 : (pos - (U_PARSE_CONTEXT_LEN-1));
446b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t limit = pos;
447b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
448b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    u_memcpy(parseError->preContext,rules+start,limit-start);
449b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    //null terminate the buffer
450b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    parseError->preContext[limit-start] = 0;
451b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
452b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // for post-context; include error rules[pos]
453b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    start = pos;
454b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    limit = start + (U_PARSE_CONTEXT_LEN-1);
455b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (limit > rulesLen) {
456b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        limit = rulesLen;
457b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
458b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (start < rulesLen) {
459b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        u_memcpy(parseError->postContext,rules+start,limit-start);
460b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
461b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    //null terminate the buffer
462b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    parseError->postContext[limit-start]= 0;
463b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
464b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
465b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
466b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic inline UStringPrepType
467b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QuerugetValues(uint16_t trieWord, int16_t& value, UBool& isIndex){
468b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
469b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UStringPrepType type;
470b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(trieWord == 0){
471b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /*
472b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru         * Initial value stored in the mapping table
473b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru         * just return USPREP_TYPE_LIMIT .. so that
474b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru         * the source codepoint is copied to the destination
475b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru         */
476b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        type = USPREP_TYPE_LIMIT;
477b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        isIndex =FALSE;
478b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        value = 0;
479b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }else if(trieWord >= _SPREP_TYPE_THRESHOLD){
480b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        type = (UStringPrepType) (trieWord - _SPREP_TYPE_THRESHOLD);
481b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        isIndex =FALSE;
482b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        value = 0;
483b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }else{
484b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* get the type */
485b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        type = USPREP_MAP;
486b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* ascertain if the value is index or delta */
487b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if(trieWord & 0x02){
488b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            isIndex = TRUE;
489b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            value = trieWord  >> 2; //mask off the lower 2 bits and shift
490b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }else{
491b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            isIndex = FALSE;
492b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            value = (int16_t)trieWord;
493b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            value =  (value >> 2);
494b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
495b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
496b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if((trieWord>>2) == _SPREP_MAX_INDEX_VALUE){
497b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            type = USPREP_DELETE;
498b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            isIndex =FALSE;
499b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            value = 0;
500b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
501b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
502b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return type;
503b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
504b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
505b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
506b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
507b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic int32_t
508b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruusprep_map(  const UStringPrepProfile* profile,
509b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru             const UChar* src, int32_t srcLength,
510b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru             UChar* dest, int32_t destCapacity,
511b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru             int32_t options,
512b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru             UParseError* parseError,
513b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru             UErrorCode* status ){
514b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
515b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uint16_t result;
516b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t destIndex=0;
517b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t srcIndex;
518b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UBool allowUnassigned = (UBool) ((options & USPREP_ALLOW_UNASSIGNED)>0);
519b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UStringPrepType type;
520b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int16_t value;
521b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UBool isIndex;
522b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    const int32_t* indexes = profile->indexes;
523b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
524b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // no error checking the caller check for error and arguments
525b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // no string length check the caller finds out the string length
526b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
527b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    for(srcIndex=0;srcIndex<srcLength;){
528b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        UChar32 ch;
529b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
530b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        U16_NEXT(src,srcIndex,srcLength,ch);
531b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
532b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        result=0;
533b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
534b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        UTRIE_GET16(&profile->sprepTrie,ch,result);
535b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
536b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        type = getValues(result, value, isIndex);
537b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
538b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // check if the source codepoint is unassigned
539b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if(type == USPREP_UNASSIGNED && allowUnassigned == FALSE){
540b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
541b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            uprv_syntaxError(src,srcIndex-U16_LENGTH(ch), srcLength,parseError);
542b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            *status = U_STRINGPREP_UNASSIGNED_ERROR;
543b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return 0;
544b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
545b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }else if(type == USPREP_MAP){
546b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
547b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            int32_t index, length;
548b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
549b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if(isIndex){
550b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                index = value;
551b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                if(index >= indexes[_SPREP_ONE_UCHAR_MAPPING_INDEX_START] &&
552b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                         index < indexes[_SPREP_TWO_UCHARS_MAPPING_INDEX_START]){
553b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    length = 1;
554b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }else if(index >= indexes[_SPREP_TWO_UCHARS_MAPPING_INDEX_START] &&
555b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                         index < indexes[_SPREP_THREE_UCHARS_MAPPING_INDEX_START]){
556b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    length = 2;
557b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }else if(index >= indexes[_SPREP_THREE_UCHARS_MAPPING_INDEX_START] &&
558b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                         index < indexes[_SPREP_FOUR_UCHARS_MAPPING_INDEX_START]){
559b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    length = 3;
560b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }else{
561b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    length = profile->mappingData[index++];
562b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
563b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
564b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
565b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                /* copy mapping to destination */
566b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                for(int32_t i=0; i< length; i++){
567b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    if(destIndex < destCapacity  ){
568b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        dest[destIndex] = profile->mappingData[index+i];
569b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    }
570b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    destIndex++; /* for pre-flighting */
571b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
572b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                continue;
573b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }else{
574b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                // subtract the delta to arrive at the code point
575b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                ch -= value;
576b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
577b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
578b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }else if(type==USPREP_DELETE){
579b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru             // just consume the codepoint and contine
580b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            continue;
581b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
582b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        //copy the code point into destination
583b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if(ch <= 0xFFFF){
584b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if(destIndex < destCapacity ){
585b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                dest[destIndex] = (UChar)ch;
586b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
587b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            destIndex++;
588b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }else{
589b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if(destIndex+1 < destCapacity ){
590b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                dest[destIndex]   = U16_LEAD(ch);
591b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                dest[destIndex+1] = U16_TRAIL(ch);
592b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
593b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            destIndex +=2;
594b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
595b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
596b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
597b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
598b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return u_terminateUChars(dest, destCapacity, destIndex, status);
599b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
600b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
601b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
602b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic int32_t
603b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruusprep_normalize(   const UChar* src, int32_t srcLength,
604b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    UChar* dest, int32_t destCapacity,
605b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    UErrorCode* status ){
606b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return unorm_normalize(
607b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        src, srcLength,
60850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        UNORM_NFKC, UNORM_UNICODE_3_2,
609b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        dest, destCapacity,
610b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        status);
611b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
612b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
613b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
614b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru /*
615b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru   1) Map -- For each character in the input, check if it has a mapping
616b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      and, if so, replace it with its mapping.
617b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
618b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru   2) Normalize -- Possibly normalize the result of step 1 using Unicode
619b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      normalization.
620b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
621b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru   3) Prohibit -- Check for any characters that are not allowed in the
622b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      output.  If any are found, return an error.
623b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
624b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru   4) Check bidi -- Possibly check for right-to-left characters, and if
625b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      any are found, make sure that the whole string satisfies the
626b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      requirements for bidirectional strings.  If the string does not
627b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      satisfy the requirements for bidirectional strings, return an
628b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      error.
629b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      [Unicode3.2] defines several bidirectional categories; each character
630b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru       has one bidirectional category assigned to it.  For the purposes of
631b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru       the requirements below, an "RandALCat character" is a character that
632b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru       has Unicode bidirectional categories "R" or "AL"; an "LCat character"
633b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru       is a character that has Unicode bidirectional category "L".  Note
634b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
635b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
636b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru       that there are many characters which fall in neither of the above
637b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru       definitions; Latin digits (<U+0030> through <U+0039>) are examples of
638b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru       this because they have bidirectional category "EN".
639b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
640b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru       In any profile that specifies bidirectional character handling, all
641b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru       three of the following requirements MUST be met:
642b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
643b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru       1) The characters in section 5.8 MUST be prohibited.
644b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
645b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru       2) If a string contains any RandALCat character, the string MUST NOT
646b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          contain any LCat character.
647b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
648b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru       3) If a string contains any RandALCat character, a RandALCat
649b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          character MUST be the first character of the string, and a
650b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          RandALCat character MUST be the last character of the string.
651b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*/
652b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
653b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define MAX_STACK_BUFFER_SIZE 300
654b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
655b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
656b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CAPI int32_t U_EXPORT2
657b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruusprep_prepare(   const UStringPrepProfile* profile,
658b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                  const UChar* src, int32_t srcLength,
659b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                  UChar* dest, int32_t destCapacity,
660b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                  int32_t options,
661b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                  UParseError* parseError,
662b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                  UErrorCode* status ){
663b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
664b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // check error status
665b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(status == NULL || U_FAILURE(*status)){
666b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return 0;
667b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
668b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
669b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    //check arguments
670b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(profile==NULL || src==NULL || srcLength<-1 || (dest==NULL && destCapacity!=0)) {
671b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        *status=U_ILLEGAL_ARGUMENT_ERROR;
672b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return 0;
673b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
674b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
675b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UChar b1Stack[MAX_STACK_BUFFER_SIZE], b2Stack[MAX_STACK_BUFFER_SIZE];
676b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UChar *b1 = b1Stack, *b2 = b2Stack;
677b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t b1Len, b2Len=0,
678b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            b1Capacity = MAX_STACK_BUFFER_SIZE ,
679b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            b2Capacity = MAX_STACK_BUFFER_SIZE;
680b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uint16_t result;
681b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t b2Index = 0;
682b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UCharDirection direction=U_CHAR_DIRECTION_COUNT, firstCharDir=U_CHAR_DIRECTION_COUNT;
683b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UBool leftToRight=FALSE, rightToLeft=FALSE;
684b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t rtlPos =-1, ltrPos =-1;
685b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
686b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    //get the string length
687b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(srcLength == -1){
688b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        srcLength = u_strlen(src);
689b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
690b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // map
691b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    b1Len = usprep_map(profile, src, srcLength, b1, b1Capacity, options, parseError, status);
692b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
693b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(*status == U_BUFFER_OVERFLOW_ERROR){
694b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // redo processing of string
695b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* we do not have enough room so grow the buffer*/
696b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        b1 = (UChar*) uprv_malloc(b1Len * U_SIZEOF_UCHAR);
697b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if(b1==NULL){
698b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            *status = U_MEMORY_ALLOCATION_ERROR;
699b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            goto CLEANUP;
700b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
701b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
702b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        *status = U_ZERO_ERROR; // reset error
703b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
704b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        b1Len = usprep_map(profile, src, srcLength, b1, b1Len, options, parseError, status);
705b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
706b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
707b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
708b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // normalize
709b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(profile->doNFKC == TRUE){
710b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        b2Len = usprep_normalize(b1,b1Len, b2,b2Capacity,status);
711b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
712b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if(*status == U_BUFFER_OVERFLOW_ERROR){
713b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            // redo processing of string
714b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            /* we do not have enough room so grow the buffer*/
715b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            b2 = (UChar*) uprv_malloc(b2Len * U_SIZEOF_UCHAR);
716b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if(b2==NULL){
717b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                *status = U_MEMORY_ALLOCATION_ERROR;
718b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                goto CLEANUP;
719b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
720b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
721b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            *status = U_ZERO_ERROR; // reset error
722b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
723b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            b2Len = usprep_normalize(b1,b1Len, b2,b2Len,status);
724b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
725b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
726b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
727b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }else{
728b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        b2 = b1;
729b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        b2Len = b1Len;
730b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
731b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
732b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
733b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(U_FAILURE(*status)){
734b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        goto CLEANUP;
735b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
736b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
737b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UChar32 ch;
738b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UStringPrepType type;
739b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int16_t value;
740b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UBool isIndex;
741b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
742b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // Prohibit and checkBiDi in one pass
743b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    for(b2Index=0; b2Index<b2Len;){
744b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
745b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        ch = 0;
746b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
747b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        U16_NEXT(b2, b2Index, b2Len, ch);
748b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
749b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        UTRIE_GET16(&profile->sprepTrie,ch,result);
750b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
751b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        type = getValues(result, value, isIndex);
752b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
753b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if( type == USPREP_PROHIBITED ||
754b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            ((result < _SPREP_TYPE_THRESHOLD) && (result & 0x01) /* first bit says it the code point is prohibited*/)
755b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru           ){
756b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            *status = U_STRINGPREP_PROHIBITED_ERROR;
757b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            uprv_syntaxError(b1, b2Index-U16_LENGTH(ch), b2Len, parseError);
758b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            goto CLEANUP;
759b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
760b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
761b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if(profile->checkBiDi) {
762b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            direction = ubidi_getClass(profile->bdp, ch);
763b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if(firstCharDir == U_CHAR_DIRECTION_COUNT){
764b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                firstCharDir = direction;
765b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
766b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if(direction == U_LEFT_TO_RIGHT){
767b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                leftToRight = TRUE;
768b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                ltrPos = b2Index-1;
769b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
770b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if(direction == U_RIGHT_TO_LEFT || direction == U_RIGHT_TO_LEFT_ARABIC){
771b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                rightToLeft = TRUE;
772b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                rtlPos = b2Index-1;
773b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
774b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
775b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
776b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(profile->checkBiDi == TRUE){
777b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // satisfy 2
778b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if( leftToRight == TRUE && rightToLeft == TRUE){
779b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            *status = U_STRINGPREP_CHECK_BIDI_ERROR;
780b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            uprv_syntaxError(b2,(rtlPos>ltrPos) ? rtlPos : ltrPos, b2Len, parseError);
781b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            goto CLEANUP;
782b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
783b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
784b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        //satisfy 3
785b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if( rightToLeft == TRUE &&
786b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            !((firstCharDir == U_RIGHT_TO_LEFT || firstCharDir == U_RIGHT_TO_LEFT_ARABIC) &&
787b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru              (direction == U_RIGHT_TO_LEFT || direction == U_RIGHT_TO_LEFT_ARABIC))
788b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru           ){
789b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            *status = U_STRINGPREP_CHECK_BIDI_ERROR;
790b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            uprv_syntaxError(b2, rtlPos, b2Len, parseError);
791b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return FALSE;
792b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
793b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
794b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(b2Len>0 && b2Len <= destCapacity){
795b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        uprv_memmove(dest,b2, b2Len*U_SIZEOF_UCHAR);
796b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
797b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
798b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruCLEANUP:
799b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(b1!=b1Stack){
800b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        uprv_free(b1);
801b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        b1=NULL;
802b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
803b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
804b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(b2!=b1Stack && b2!=b2Stack && b2!=b1 /* b1 should not be freed twice */){
805b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        uprv_free(b2);
806b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        b2=NULL;
807b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
808b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return u_terminateUChars(dest, destCapacity, b2Len, status);
809b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
810b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
811b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
812b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/* data swapping ------------------------------------------------------------ */
813b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
814b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CAPI int32_t U_EXPORT2
815b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruusprep_swap(const UDataSwapper *ds,
816b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            const void *inData, int32_t length, void *outData,
817b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            UErrorCode *pErrorCode) {
818b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    const UDataInfo *pInfo;
819b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t headerSize;
820b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
821b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    const uint8_t *inBytes;
822b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uint8_t *outBytes;
823b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
824b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    const int32_t *inIndexes;
825b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t indexes[16];
826b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
827b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t i, offset, count, size;
828b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
829b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* udata_swapDataHeader checks the arguments */
830b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    headerSize=udata_swapDataHeader(ds, inData, length, outData, pErrorCode);
831b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(pErrorCode==NULL || U_FAILURE(*pErrorCode)) {
832b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return 0;
833b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
834b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
835b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* check data format and format version */
836b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    pInfo=(const UDataInfo *)((const char *)inData+4);
837b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(!(
838b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        pInfo->dataFormat[0]==0x53 &&   /* dataFormat="SPRP" */
839b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        pInfo->dataFormat[1]==0x50 &&
840b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        pInfo->dataFormat[2]==0x52 &&
841b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        pInfo->dataFormat[3]==0x50 &&
842b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        pInfo->formatVersion[0]==3
843b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    )) {
844b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        udata_printError(ds, "usprep_swap(): data format %02x.%02x.%02x.%02x (format version %02x) is not recognized as StringPrep .spp data\n",
845b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                         pInfo->dataFormat[0], pInfo->dataFormat[1],
846b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                         pInfo->dataFormat[2], pInfo->dataFormat[3],
847b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                         pInfo->formatVersion[0]);
848b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        *pErrorCode=U_UNSUPPORTED_ERROR;
849b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return 0;
850b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
851b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
852b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    inBytes=(const uint8_t *)inData+headerSize;
853b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    outBytes=(uint8_t *)outData+headerSize;
854b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
855b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    inIndexes=(const int32_t *)inBytes;
856b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
857b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(length>=0) {
858b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        length-=headerSize;
859b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if(length<16*4) {
860b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            udata_printError(ds, "usprep_swap(): too few bytes (%d after header) for StringPrep .spp data\n",
861b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                             length);
862b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            *pErrorCode=U_INDEX_OUTOFBOUNDS_ERROR;
863b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return 0;
864b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
865b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
866b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
867b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* read the first 16 indexes (ICU 2.8/format version 3: _SPREP_INDEX_TOP==16, might grow) */
868b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    for(i=0; i<16; ++i) {
869b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        indexes[i]=udata_readInt32(ds, inIndexes[i]);
870b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
871b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
872b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* calculate the total length of the data */
873b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    size=
874b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        16*4+ /* size of indexes[] */
875b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        indexes[_SPREP_INDEX_TRIE_SIZE]+
876b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        indexes[_SPREP_INDEX_MAPPING_DATA_SIZE];
877b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
878b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(length>=0) {
879b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if(length<size) {
880b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            udata_printError(ds, "usprep_swap(): too few bytes (%d after header) for all of StringPrep .spp data\n",
881b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                             length);
882b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            *pErrorCode=U_INDEX_OUTOFBOUNDS_ERROR;
883b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return 0;
884b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
885b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
886b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* copy the data for inaccessible bytes */
887b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if(inBytes!=outBytes) {
888b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            uprv_memcpy(outBytes, inBytes, size);
889b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
890b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
891b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        offset=0;
892b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
893b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* swap the int32_t indexes[] */
894b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        count=16*4;
895b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        ds->swapArray32(ds, inBytes, count, outBytes, pErrorCode);
896b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        offset+=count;
897b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
898b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* swap the UTrie */
899b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        count=indexes[_SPREP_INDEX_TRIE_SIZE];
900b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        utrie_swap(ds, inBytes+offset, count, outBytes+offset, pErrorCode);
901b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        offset+=count;
902b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
903b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* swap the uint16_t mappingTable[] */
904b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        count=indexes[_SPREP_INDEX_MAPPING_DATA_SIZE];
905b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        ds->swapArray16(ds, inBytes+offset, count, outBytes+offset, pErrorCode);
906b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        offset+=count;
907b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
908b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
909b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return headerSize+size;
910b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
911b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
912b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif /* #if !UCONFIG_NO_IDNA */
913