static int32_t caseMap(UChar *dest, int32_t destCapacity, const UChar *src, int32_t srcLength, UBreakIterator *titleIter, const char *locale, uint32_t options, int32_t toWhichCase, UErrorCode *pErrorCode) { UChar buffer[300]; UChar *temp; const UCaseProps *csp; int32_t destLength; UBool ownTitleIter; /* check argument values */ if(pErrorCode==NULL || U_FAILURE(*pErrorCode)) { return 0; } if( destCapacity<0 || (dest==NULL && destCapacity>0) || src==NULL || srcLength<-1 ) { *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR; return 0; } csp=ucase_getSingleton(pErrorCode); if(U_FAILURE(*pErrorCode)) { return 0; } /* get the string length */ if(srcLength==-1) { srcLength=u_strlen(src); } /* check for overlapping source and destination */ if( dest!=NULL && ((src>=dest && src<(dest+destCapacity)) || (dest>=src && dest<(src+srcLength))) ) { /* overlap: provide a temporary destination buffer and later copy the result */ if(destCapacity<=(sizeof(buffer)/U_SIZEOF_UCHAR)) { /* the stack buffer is large enough */ temp=buffer; } else { /* allocate a buffer */ temp=(UChar *)uprv_malloc(destCapacity*U_SIZEOF_UCHAR); if(temp==NULL) { *pErrorCode=U_MEMORY_ALLOCATION_ERROR; return 0; } } } else { temp=dest; } ownTitleIter=FALSE; destLength=0; if(toWhichCase==FOLD_CASE) { destLength=ustr_foldCase(csp, temp, destCapacity, src, srcLength, options, pErrorCode); } else { UCaseContext csc={ NULL }; int32_t locCache; csc.p=(void *)src; csc.limit=srcLength; locCache=0; /* the internal functions require locale!=NULL */ if(locale==NULL) { locale=uloc_getDefault(); } if(toWhichCase==TO_LOWER) { destLength=_caseMap(csp, ucase_toFullLower, temp, destCapacity, src, &csc, 0, srcLength, locale, &locCache, pErrorCode); } else if(toWhichCase==TO_UPPER) { destLength=_caseMap(csp, ucase_toFullUpper, temp, destCapacity, src, &csc, 0, srcLength, locale, &locCache, pErrorCode); } else /* if(toWhichCase==TO_TITLE) */ { #if UCONFIG_NO_BREAK_ITERATION *pErrorCode=U_UNSUPPORTED_ERROR; #else if(titleIter==NULL) { titleIter=ubrk_open(UBRK_WORD, locale, src, srcLength, pErrorCode); ownTitleIter=(UBool)U_SUCCESS(*pErrorCode); } if(U_SUCCESS(*pErrorCode)) { destLength=_toTitle(csp, temp, destCapacity, src, &csc, srcLength, titleIter, locale, &locCache, pErrorCode); } #endif } } if(temp!=dest) { /* copy the result string to the destination buffer */ if(destLength>0) { int32_t copyLength= destLength<=destCapacity ? destLength : destCapacity; if(copyLength>0) { uprv_memmove(dest, temp, copyLength*U_SIZEOF_UCHAR); } } if(temp!=buffer) { uprv_free(temp); } } #if !UCONFIG_NO_BREAK_ITERATION if(ownTitleIter) { ubrk_close(titleIter); } #endif return u_terminateUChars(dest, destCapacity, destLength, pErrorCode); }
/* fill the uchar buffer */ static UCHARBUF* ucbuf_fillucbuf( UCHARBUF* buf,UErrorCode* error){ UChar* pTarget=NULL; UChar* target=NULL; const char* source=NULL; char carr[MAX_IN_BUF] = {'\0'}; char* cbuf = carr; int32_t inputRead=0; int32_t outputWritten=0; int32_t offset=0; const char* sourceLimit =NULL; int32_t cbufSize=0; pTarget = buf->buffer; /* check if we arrived here without exhausting the buffer*/ if(buf->currentPos<buf->bufLimit){ offset = (int32_t)(buf->bufLimit-buf->currentPos); memmove(buf->buffer,buf->currentPos,offset* sizeof(UChar)); } #if UCBUF_DEBUG memset(pTarget+offset,0xff,sizeof(UChar)*(MAX_IN_BUF-offset)); #endif if(buf->isBuffered){ cbufSize = MAX_IN_BUF; /* read the file */ inputRead=T_FileStream_read(buf->in,cbuf,cbufSize-offset); buf->remaining-=inputRead; }else{ cbufSize = T_FileStream_size(buf->in); cbuf = (char*)uprv_malloc(cbufSize); if (cbuf == NULL) { *error = U_MEMORY_ALLOCATION_ERROR; return NULL; } inputRead= T_FileStream_read(buf->in,cbuf,cbufSize); buf->remaining-=inputRead; } /* just to be sure...*/ if ( 0 == inputRead ) buf->remaining = 0; target=pTarget; /* convert the bytes */ if(buf->conv){ /* set the callback to stop */ UConverterToUCallback toUOldAction ; void* toUOldContext; void* toUNewContext=NULL; ucnv_setToUCallBack(buf->conv, UCNV_TO_U_CALLBACK_STOP, toUNewContext, &toUOldAction, (const void**)&toUOldContext, error); /* since state is saved in the converter we add offset to source*/ target = pTarget+offset; source = cbuf; sourceLimit = source + inputRead; ucnv_toUnicode(buf->conv,&target,target+(buf->bufCapacity-offset), &source,sourceLimit,NULL, (UBool)(buf->remaining==0),error); if(U_FAILURE(*error)){ char context[CONTEXT_LEN+1]; char preContext[CONTEXT_LEN+1]; char postContext[CONTEXT_LEN+1]; int8_t len = CONTEXT_LEN; int32_t start=0; int32_t stop =0; int32_t pos =0; /* use erro1 to preserve the error code */ UErrorCode error1 =U_ZERO_ERROR; if( buf->showWarning==TRUE){ fprintf(stderr,"\n###WARNING: Encountered abnormal bytes while" " converting input stream to target encoding: %s\n", u_errorName(*error)); } /* now get the context chars */ ucnv_getInvalidChars(buf->conv,context,&len,&error1); context[len]= 0 ; /* null terminate the buffer */ pos = (int32_t)(source - cbuf - len); /* for pre-context */ start = (pos <=CONTEXT_LEN)? 0 : (pos - (CONTEXT_LEN-1)); stop = pos-len; memcpy(preContext,cbuf+start,stop-start); /* null terminate the buffer */ preContext[stop-start] = 0; /* for post-context */ start = pos+len; stop = (int32_t)(((pos+CONTEXT_LEN)<= (sourceLimit-cbuf) )? (pos+(CONTEXT_LEN-1)) : (sourceLimit-cbuf)); memcpy(postContext,source,stop-start); /* null terminate the buffer */ postContext[stop-start] = 0; if(buf->showWarning ==TRUE){ /* print out the context */ fprintf(stderr,"\tPre-context: %s\n",preContext); fprintf(stderr,"\tContext: %s\n",context); fprintf(stderr,"\tPost-context: %s\n", postContext); } /* reset the converter */ ucnv_reset(buf->conv); /* set the call back to substitute * and restart conversion */ ucnv_setToUCallBack(buf->conv, UCNV_TO_U_CALLBACK_SUBSTITUTE, toUNewContext, &toUOldAction, (const void**)&toUOldContext, &error1); /* reset source and target start positions */ target = pTarget+offset; source = cbuf; /* re convert */ ucnv_toUnicode(buf->conv,&target,target+(buf->bufCapacity-offset), &source,sourceLimit,NULL, (UBool)(buf->remaining==0),&error1); } outputWritten = (int32_t)(target - pTarget); #if UCBUF_DEBUG { int i; target = pTarget; for(i=0;i<numRead;i++){ /* printf("%c", (char)(*target++));*/ } } #endif }else{ u_charsToUChars(cbuf,target+offset,inputRead); outputWritten=((buf->remaining>cbufSize)? cbufSize:inputRead+offset); } buf->currentPos = pTarget; buf->bufLimit=pTarget+outputWritten; *buf->bufLimit=0; /*NUL terminate*/ if(cbuf!=carr){ uprv_free(cbuf); } return buf; }
/* frees the resources of UChar* buffer */ static void ucbuf_closebuf(UCHARBUF* buf){ uprv_free(buf->buffer); buf->buffer = NULL; }
U_CAPI void U_EXPORT2 ucm_addMapping(UCMTable *table, UCMapping *m, UChar32 codePoints[UCNV_EXT_MAX_UCHARS], uint8_t bytes[UCNV_EXT_MAX_BYTES]) { UCMapping *tm; UChar32 c; int32_t idx; if(table->mappingsLength>=table->mappingsCapacity) { /* make the mappings array larger */ if(table->mappingsCapacity==0) { table->mappingsCapacity=1000; } else { table->mappingsCapacity*=10; } table->mappings=(UCMapping *)uprv_realloc(table->mappings, table->mappingsCapacity*sizeof(UCMapping)); if(table->mappings==NULL) { fprintf(stderr, "ucm error: unable to allocate %d UCMappings\n", (int)table->mappingsCapacity); exit(U_MEMORY_ALLOCATION_ERROR); } if(table->reverseMap!=NULL) { /* the reverseMap must be reallocated in a new sort */ uprv_free(table->reverseMap); table->reverseMap=NULL; } } if(m->uLen>1 && table->codePointsCapacity==0) { table->codePointsCapacity=10000; table->codePoints=(UChar32 *)uprv_malloc(table->codePointsCapacity*4); if(table->codePoints==NULL) { fprintf(stderr, "ucm error: unable to allocate %d UChar32s\n", (int)table->codePointsCapacity); exit(U_MEMORY_ALLOCATION_ERROR); } } if(m->bLen>4 && table->bytesCapacity==0) { table->bytesCapacity=10000; table->bytes=(uint8_t *)uprv_malloc(table->bytesCapacity); if(table->bytes==NULL) { fprintf(stderr, "ucm error: unable to allocate %d bytes\n", (int)table->bytesCapacity); exit(U_MEMORY_ALLOCATION_ERROR); } } if(m->uLen>1) { idx=table->codePointsLength; table->codePointsLength+=m->uLen; if(table->codePointsLength>table->codePointsCapacity) { fprintf(stderr, "ucm error: too many code points in multiple-code point mappings\n"); exit(U_MEMORY_ALLOCATION_ERROR); } uprv_memcpy(table->codePoints+idx, codePoints, m->uLen*4); m->u=idx; } if(m->bLen>4) { idx=table->bytesLength; table->bytesLength+=m->bLen; if(table->bytesLength>table->bytesCapacity) { fprintf(stderr, "ucm error: too many bytes in mappings with >4 charset bytes\n"); exit(U_MEMORY_ALLOCATION_ERROR); } uprv_memcpy(table->bytes+idx, bytes, m->bLen); m->b.idx=idx; } /* set unicodeMask */ for(idx=0; idx<m->uLen; ++idx) { c=codePoints[idx]; if(c>=0x10000) { table->unicodeMask|=UCNV_HAS_SUPPLEMENTARY; /* there are supplementary code points */ } else if(U_IS_SURROGATE(c)) { table->unicodeMask|=UCNV_HAS_SURROGATES; /* there are surrogate code points */ } } /* set flagsType */ if(m->f<0) { table->flagsType|=UCM_FLAGS_IMPLICIT; } else { table->flagsType|=UCM_FLAGS_EXPLICIT; } tm=table->mappings+table->mappingsLength++; uprv_memcpy(tm, m, sizeof(UCMapping)); table->isSorted=FALSE; }
StringEnumeration::~StringEnumeration() { if (chars != NULL && chars != charsBuffer) { uprv_free(chars); } }
/** * Deleter for GNameInfo */ static void U_CALLCONV deleteGNameInfo(void *obj) { uprv_free(obj); }
static int32_t _internal_toUnicode(const UChar* src, int32_t srcLength, UChar* dest, int32_t destCapacity, int32_t options, UStringPrepProfile* nameprep, UParseError* parseError, UErrorCode* status) { //get the options //UBool useSTD3ASCIIRules = (UBool)((options & UIDNA_USE_STD3_RULES) != 0); int32_t namePrepOptions = ((options & UIDNA_ALLOW_UNASSIGNED) != 0) ? USPREP_ALLOW_UNASSIGNED: 0; // TODO Revisit buffer handling. The label should not be over 63 ASCII characters. ICU4J may need to be updated too. UChar b1Stack[MAX_LABEL_BUFFER_SIZE], b2Stack[MAX_LABEL_BUFFER_SIZE], b3Stack[MAX_LABEL_BUFFER_SIZE]; //initialize pointers to stack buffers UChar *b1 = b1Stack, *b2 = b2Stack, *b1Prime=NULL, *b3=b3Stack; int32_t b1Len, b2Len, b1PrimeLen, b3Len, b1Capacity = MAX_LABEL_BUFFER_SIZE, b2Capacity = MAX_LABEL_BUFFER_SIZE, b3Capacity = MAX_LABEL_BUFFER_SIZE, reqLength=0; b1Len = 0; UBool* caseFlags = NULL; UBool srcIsASCII = TRUE; /*UBool srcIsLDH = TRUE; int32_t failPos =0;*/ // step 1: find out if all the codepoints in src are ASCII if(srcLength==-1){ srcLength = 0; for(;src[srcLength]!=0;){ if(src[srcLength]> 0x7f){ srcIsASCII = FALSE; }/*else if(isLDHChar(src[srcLength])==FALSE){ // here we do not assemble surrogates // since we know that LDH code points // are in the ASCII range only srcIsLDH = FALSE; failPos = srcLength; }*/ srcLength++; } }else if(srcLength > 0){ for(int32_t j=0; j<srcLength; j++){ if(src[j]> 0x7f){ srcIsASCII = FALSE; }/*else if(isLDHChar(src[j])==FALSE){ // here we do not assemble surrogates // since we know that LDH code points // are in the ASCII range only srcIsLDH = FALSE; failPos = j; }*/ } }else{ return 0; } if(srcIsASCII == FALSE){ // step 2: process the string b1Len = usprep_prepare(nameprep, src, srcLength, b1, b1Capacity, namePrepOptions, parseError, status); if(*status == U_BUFFER_OVERFLOW_ERROR){ // redo processing of string /* we do not have enough room so grow the buffer*/ b1 = (UChar*) uprv_malloc(b1Len * U_SIZEOF_UCHAR); if(b1==NULL){ *status = U_MEMORY_ALLOCATION_ERROR; goto CLEANUP; } *status = U_ZERO_ERROR; // reset error b1Len = usprep_prepare(nameprep, src, srcLength, b1, b1Len, namePrepOptions, parseError, status); } //bail out on error if(U_FAILURE(*status)){ goto CLEANUP; } }else{ //just point src to b1 b1 = (UChar*) src; b1Len = srcLength; } // The RFC states that // <quote> // ToUnicode never fails. If any step fails, then the original input // is returned immediately in that step. // </quote> //step 3: verify ACE Prefix if(startsWithPrefix(b1,b1Len)){ //step 4: Remove the ACE Prefix b1Prime = b1 + ACE_PREFIX_LENGTH; b1PrimeLen = b1Len - ACE_PREFIX_LENGTH; //step 5: Decode using punycode b2Len = u_strFromPunycode(b1Prime, b1PrimeLen, b2, b2Capacity, caseFlags,status); if(*status == U_BUFFER_OVERFLOW_ERROR){ // redo processing of string /* we do not have enough room so grow the buffer*/ b2 = (UChar*) uprv_malloc(b2Len * U_SIZEOF_UCHAR); if(b2==NULL){ *status = U_MEMORY_ALLOCATION_ERROR; goto CLEANUP; } *status = U_ZERO_ERROR; // reset error b2Len = u_strFromPunycode(b1Prime, b1PrimeLen, b2, b2Len, caseFlags, status); } //step 6:Apply toASCII b3Len = uidna_toASCII(b2, b2Len, b3, b3Capacity, options, parseError, status); if(*status == U_BUFFER_OVERFLOW_ERROR){ // redo processing of string /* we do not have enough room so grow the buffer*/ b3 = (UChar*) uprv_malloc(b3Len * U_SIZEOF_UCHAR); if(b3==NULL){ *status = U_MEMORY_ALLOCATION_ERROR; goto CLEANUP; } *status = U_ZERO_ERROR; // reset error b3Len = uidna_toASCII(b2,b2Len,b3,b3Len,options,parseError, status); } //bail out on error if(U_FAILURE(*status)){ goto CLEANUP; } //step 7: verify if(compareCaseInsensitiveASCII(b1, b1Len, b3, b3Len) !=0){ // Cause the original to be returned. *status = U_IDNA_VERIFICATION_ERROR; goto CLEANUP; } //step 8: return output of step 5 reqLength = b2Len; if(b2Len <= destCapacity) { uprv_memmove(dest, b2, b2Len * U_SIZEOF_UCHAR); } } else{ // See the start of this if statement for why this is commented out. // verify that STD3 ASCII rules are satisfied /*if(useSTD3ASCIIRules == TRUE){ if( srcIsLDH == FALSE // source contains some non-LDH characters || src[0] == HYPHEN || src[srcLength-1] == HYPHEN){ *status = U_IDNA_STD3_ASCII_RULES_ERROR; // populate the parseError struct if(srcIsLDH==FALSE){ // failPos is always set the index of failure uprv_syntaxError(src,failPos, srcLength,parseError); }else if(src[0] == HYPHEN){ // fail position is 0 uprv_syntaxError(src,0,srcLength,parseError); }else{ // the last index in the source is always length-1 uprv_syntaxError(src, (srcLength>0) ? srcLength-1 : srcLength, srcLength,parseError); } goto CLEANUP; } }*/ // just return the source //copy the source to destination if(srcLength <= destCapacity){ uprv_memmove(dest,src,srcLength * U_SIZEOF_UCHAR); } reqLength = srcLength; } CLEANUP: if(b1 != b1Stack && b1!=src){ uprv_free(b1); } if(b2 != b2Stack){ uprv_free(b2); } uprv_free(caseFlags); // The RFC states that // <quote> // ToUnicode never fails. If any step fails, then the original input // is returned immediately in that step. // </quote> // So if any step fails lets copy source to destination if(U_FAILURE(*status)){ //copy the source to destination if(dest && srcLength <= destCapacity){ // srcLength should have already been set earlier. U_ASSERT(srcLength >= 0); uprv_memmove(dest,src,srcLength * U_SIZEOF_UCHAR); } reqLength = srcLength; *status = U_ZERO_ERROR; } return u_terminateUChars(dest, destCapacity, reqLength, status); }
static UFILE* finit_owner(FILE *f, const char *locale, const char *codepage, UBool takeOwnership ) { UErrorCode status = U_ZERO_ERROR; UFILE *result; if(f == NULL) { return 0; } result = (UFILE*) uprv_malloc(sizeof(UFILE)); if(result == NULL) { return 0; } uprv_memset(result, 0, sizeof(UFILE)); result->fFileno = fileno(f); #if U_PLATFORM_USES_ONLY_WIN32_API && _MSC_VER < 1900 /* * Below is a very old workaround (ICU ticket:231). * * Previously, 'FILE*' from inside and outside ICU's DLL * were different, because they pointed into local copies * of the io block. At least by VS 2015 the implementation * is something like: * stdio = _acrt_iob_func(0) * .. which is a function call, so should return the same pointer * regardless of call site. * As of _MSC_VER 1900 this patch is retired, at 16 years old. */ if (0 <= result->fFileno && result->fFileno <= 2) { /* stdin, stdout and stderr need to be special cased for Windows 98 */ #if _MSC_VER >= 1400 result->fFile = &__iob_func()[_fileno(f)]; #else result->fFile = &_iob[_fileno(f)]; #endif } else #endif { result->fFile = f; } result->str.fBuffer = result->fUCBuffer; result->str.fPos = result->fUCBuffer; result->str.fLimit = result->fUCBuffer; #if !UCONFIG_NO_FORMATTING /* if locale is 0, use the default */ if(u_locbund_init(&result->str.fBundle, locale) == 0) { /* DO NOT FCLOSE HERE! */ uprv_free(result); return 0; } #endif /* If the codepage is not "" use the ucnv_open default behavior */ if(codepage == NULL || *codepage != '\0') { result->fConverter = ucnv_open(codepage, &status); } /* else result->fConverter is already memset'd to NULL. */ if(U_SUCCESS(status)) { result->fOwnFile = takeOwnership; } else { #if !UCONFIG_NO_FORMATTING u_locbund_close(&result->str.fBundle); #endif /* DO NOT fclose here!!!!!! */ uprv_free(result); result = NULL; } return result; }
// wrapper around the reference Punycode implementation static int32_t convertToPuny(const UChar* src, int32_t srcLength, UChar* dest, int32_t destCapacity, UErrorCode& status){ uint32_t b1Stack[MAX_LABEL_BUFFER_SIZE]; int32_t b1Len = 0, b1Capacity = MAX_LABEL_BUFFER_SIZE; uint32_t* b1 = b1Stack; char b2Stack[MAX_LABEL_BUFFER_SIZE]; char* b2 = b2Stack; int32_t b2Len =MAX_LABEL_BUFFER_SIZE ; punycode_status error; unsigned char* caseFlags = NULL; u_strToUTF32((UChar32*)b1,b1Capacity,&b1Len,src,srcLength,&status); if(status == U_BUFFER_OVERFLOW_ERROR){ // redo processing of string /* we do not have enough room so grow the buffer*/ b1 = (uint32_t*) uprv_malloc(b1Len * sizeof(uint32_t)); if(b1==NULL){ status = U_MEMORY_ALLOCATION_ERROR; goto CLEANUP; } status = U_ZERO_ERROR; // reset error u_strToUTF32((UChar32*)b1,b1Len,&b1Len,src,srcLength,&status); } if(U_FAILURE(status)){ goto CLEANUP; } //caseFlags = (unsigned char*) uprv_malloc(b1Len *sizeof(unsigned char)); error = punycode_encode(b1Len,b1,caseFlags, (uint32_t*)&b2Len, b2); status = getError(error); if(status == U_BUFFER_OVERFLOW_ERROR){ /* we do not have enough room so grow the buffer*/ b2 = (char*) uprv_malloc( b2Len * sizeof(char)); if(b2==NULL){ status = U_MEMORY_ALLOCATION_ERROR; goto CLEANUP; } status = U_ZERO_ERROR; // reset error punycode_status error = punycode_encode(b1Len,b1,caseFlags, (uint32_t*)&b2Len, b2); status = getError(error); } if(U_FAILURE(status)){ goto CLEANUP; } if(b2Len < destCapacity){ convertASCIIToUChars(b2,dest,b2Len); }else{ status =U_BUFFER_OVERFLOW_ERROR; } CLEANUP: if(b1Stack != b1){ uprv_free(b1); } if(b2Stack != b2){ uprv_free(b2); } uprv_free(caseFlags); return b2Len; }
static void TinyString_dt(TinyString *This) { if (This->s != This->fStaticBuf) { uprv_free(This->s); } TinyString_init(This); }
~AutoBuffer() { if (buffer != stackBuffer) uprv_free(buffer); }
static UDataMemory *udata_cacheDataItem(const char *path, UDataMemory *item, UErrorCode *pErr) { DataCacheElement *newElement; const char *baseName; int32_t nameLen; UHashtable *htable; UDataMemory *oldValue = NULL; UErrorCode subErr = U_ZERO_ERROR; if (U_FAILURE(*pErr)) { return NULL; } /* Create a new DataCacheElement - the thingy we store in the hash table - * and copy the supplied path and UDataMemoryItems into it. */ newElement = uprv_malloc(sizeof(DataCacheElement)); if (newElement == NULL) { *pErr = U_MEMORY_ALLOCATION_ERROR; return NULL; } newElement->item = UDataMemory_createNewInstance(pErr); if (U_FAILURE(*pErr)) { uprv_free(newElement); return NULL; } UDatamemory_assign(newElement->item, item); baseName = findBasename(path); nameLen = (int32_t)uprv_strlen(baseName); newElement->name = uprv_malloc(nameLen+1); if (newElement->name == NULL) { *pErr = U_MEMORY_ALLOCATION_ERROR; uprv_free(newElement->item); uprv_free(newElement); return NULL; } uprv_strcpy(newElement->name, baseName); /* Stick the new DataCacheElement into the hash table. */ htable = udata_getHashTable(); umtx_lock(NULL); oldValue = uhash_get(htable, path); if (oldValue != NULL) { subErr = U_USING_DEFAULT_WARNING; } else { uhash_put( htable, newElement->name, /* Key */ newElement, /* Value */ &subErr); } umtx_unlock(NULL); #ifdef UDATA_DEBUG fprintf(stderr, "Cache: [%s] <<< %p : %s. vFunc=%p\n", newElement->name, newElement->item, u_errorName(subErr), newElement->item->vFuncs); #endif if (subErr == U_USING_DEFAULT_WARNING || U_FAILURE(subErr)) { *pErr = subErr; /* copy sub err unto fillin ONLY if something happens. */ uprv_free(newElement->name); uprv_free(newElement->item); uprv_free(newElement); return oldValue; } return newElement->item; }
static void U_CALLCONV DataCacheElement_deleter(void *pDCEl) { DataCacheElement *p = (DataCacheElement *)pDCEl; udata_close(p->item); /* unmaps storage */ uprv_free(p->name); /* delete the hash key string. */ uprv_free(pDCEl); /* delete 'this' */ }
/** * Implements {@link Transliterator#handleTransliterate}. */ void NameUnicodeTransliterator::handleTransliterate(Replaceable& text, UTransPosition& offsets, UBool isIncremental) const { // The failure mode, here and below, is to behave like Any-Null, // if either there is no name data (max len == 0) or there is no // memory (malloc() => NULL). int32_t maxLen = uprv_getMaxCharNameLength(); if (maxLen == 0) { offsets.start = offsets.limit; return; } // Accomodate the longest possible name ++maxLen; // allow for temporary trailing space char* cbuf = (char*) uprv_malloc(maxLen); if (cbuf == NULL) { offsets.start = offsets.limit; return; } UnicodeString openPat(TRUE, OPEN, -1); UnicodeString str, name; int32_t cursor = offsets.start; int32_t limit = offsets.limit; // Modes: // 0 - looking for open delimiter // 1 - after open delimiter int32_t mode = 0; int32_t openPos = -1; // open delim candidate pos UChar32 c; while (cursor < limit) { c = text.char32At(cursor); switch (mode) { case 0: // looking for open delimiter if (c == OPEN_DELIM) { // quick check first openPos = cursor; int32_t i = ICU_Utility::parsePattern(openPat, text, cursor, limit); if (i >= 0 && i < limit) { mode = 1; name.truncate(0); cursor = i; continue; // *** reprocess char32At(cursor) } } break; case 1: // after open delimiter // Look for legal chars. If \s+ is found, convert it // to a single space. If closeDelimiter is found, exit // the loop. If any other character is found, exit the // loop. If the limit is reached, exit the loop. // Convert \s+ => SPACE. This assumes there are no // runs of >1 space characters in names. if (PatternProps::isWhiteSpace(c)) { // Ignore leading whitespace if (name.length() > 0 && name.charAt(name.length()-1) != SPACE) { name.append(SPACE); // If we are too long then abort. maxLen includes // temporary trailing space, so use '>'. if (name.length() > maxLen) { mode = 0; } } break; } if (c == CLOSE_DELIM) { int32_t len = name.length(); // Delete trailing space, if any if (len > 0 && name.charAt(len-1) == SPACE) { --len; } if (uprv_isInvariantUString(name.getBuffer(), len)) { name.extract(0, len, cbuf, maxLen, US_INV); UErrorCode status = U_ZERO_ERROR; c = u_charFromName(U_EXTENDED_CHAR_NAME, cbuf, &status); if (U_SUCCESS(status)) { // Lookup succeeded // assert(U16_LENGTH(CLOSE_DELIM) == 1); cursor++; // advance over CLOSE_DELIM str.truncate(0); str.append(c); text.handleReplaceBetween(openPos, cursor, str); // Adjust indices for the change in the length of // the string. Do not assume that str.length() == // 1, in case of surrogates. int32_t delta = cursor - openPos - str.length(); cursor -= delta; limit -= delta; // assert(cursor == openPos + str.length()); } } // If the lookup failed, we leave things as-is and // still switch to mode 0 and continue. mode = 0; openPos = -1; // close off candidate continue; // *** reprocess char32At(cursor) } // Check if c is a legal char. We assume here that // legal.contains(OPEN_DELIM) is FALSE, so when we abort a // name, we don't have to go back to openPos+1. if (legal.contains(c)) { name.append(c); // If we go past the longest possible name then abort. // maxLen includes temporary trailing space, so use '>='. if (name.length() >= maxLen) { mode = 0; } } // Invalid character else { --cursor; // Backup and reprocess this character mode = 0; } break; } cursor += U16_LENGTH(c); } offsets.contextLimit += limit - offsets.limit; offsets.limit = limit; // In incremental mode, only advance the cursor up to the last // open delimiter candidate. offsets.start = (isIncremental && openPos >= 0) ? openPos : cursor; uprv_free(cbuf); }
TimeZoneGenericNames* TimeZoneGenericNames::createInstance(const Locale& locale, UErrorCode& status) { if (U_FAILURE(status)) { return NULL; } TimeZoneGenericNames* instance = new TimeZoneGenericNames(); if (instance == NULL) { status = U_MEMORY_ALLOCATION_ERROR; return NULL; } TZGNCoreRef *cacheEntry = NULL; { Mutex lock(&gTZGNLock); if (!gTZGNCoreCacheInitialized) { // Create empty hashtable gTZGNCoreCache = uhash_open(uhash_hashChars, uhash_compareChars, NULL, &status); if (U_SUCCESS(status)) { uhash_setKeyDeleter(gTZGNCoreCache, uprv_free); uhash_setValueDeleter(gTZGNCoreCache, deleteTZGNCoreRef); gTZGNCoreCacheInitialized = TRUE; ucln_i18n_registerCleanup(UCLN_I18N_TIMEZONEGENERICNAMES, tzgnCore_cleanup); } } if (U_FAILURE(status)) { return NULL; } // Check the cache, if not available, create new one and cache const char *key = locale.getName(); cacheEntry = (TZGNCoreRef *)uhash_get(gTZGNCoreCache, key); if (cacheEntry == NULL) { TZGNCore *tzgnCore = NULL; char *newKey = NULL; tzgnCore = new TZGNCore(locale, status); if (tzgnCore == NULL) { status = U_MEMORY_ALLOCATION_ERROR; } if (U_SUCCESS(status)) { newKey = (char *)uprv_malloc(uprv_strlen(key) + 1); if (newKey == NULL) { status = U_MEMORY_ALLOCATION_ERROR; } else { uprv_strcpy(newKey, key); } } if (U_SUCCESS(status)) { cacheEntry = (TZGNCoreRef *)uprv_malloc(sizeof(TZGNCoreRef)); if (cacheEntry == NULL) { status = U_MEMORY_ALLOCATION_ERROR; } else { cacheEntry->obj = tzgnCore; cacheEntry->refCount = 1; cacheEntry->lastAccess = (double)uprv_getUTCtime(); uhash_put(gTZGNCoreCache, newKey, cacheEntry, &status); } } if (U_FAILURE(status)) { if (tzgnCore != NULL) { delete tzgnCore; } if (newKey != NULL) { uprv_free(newKey); } if (cacheEntry != NULL) { uprv_free(cacheEntry); } cacheEntry = NULL; } } else { // Update the reference count cacheEntry->refCount++; cacheEntry->lastAccess = (double)uprv_getUTCtime(); } gAccessCount++; if (gAccessCount >= SWEEP_INTERVAL) { // sweep sweepCache(); gAccessCount = 0; } } // End of mutex locked block if (cacheEntry == NULL) { delete instance; return NULL; } instance->fRef = cacheEntry; return instance; }
U_CFUNC int32_t U_EXPORT2 idnaref_toASCII(const UChar* src, int32_t srcLength, UChar* dest, int32_t destCapacity, int32_t options, UParseError* parseError, UErrorCode* status){ if(status == NULL || U_FAILURE(*status)){ return 0; } if((src == NULL) || (srcLength < -1) || (destCapacity<0) || (!dest && destCapacity > 0)){ *status = U_ILLEGAL_ARGUMENT_ERROR; return 0; } UChar b1Stack[MAX_LABEL_BUFFER_SIZE], b2Stack[MAX_LABEL_BUFFER_SIZE]; //initialize pointers to stack buffers UChar *b1 = b1Stack, *b2 = b2Stack; int32_t b1Len=0, b2Len=0, b1Capacity = MAX_LABEL_BUFFER_SIZE, b2Capacity = MAX_LABEL_BUFFER_SIZE , reqLength=0; //get the options UBool allowUnassigned = (UBool)((options & IDNAREF_ALLOW_UNASSIGNED) != 0); UBool useSTD3ASCIIRules = (UBool)((options & IDNAREF_USE_STD3_RULES) != 0); UBool* caseFlags = NULL; // assume the source contains all ascii codepoints UBool srcIsASCII = TRUE; // assume the source contains all LDH codepoints UBool srcIsLDH = TRUE; int32_t j=0; if(srcLength == -1){ srcLength = u_strlen(src); } // step 1 for( j=0;j<srcLength;j++){ if(src[j] > 0x7F){ srcIsASCII = FALSE; } b1[b1Len++] = src[j]; } // step 2 NamePrepTransform* prep = TestIDNA::getInstance(*status); if(U_FAILURE(*status)){ goto CLEANUP; } b1Len = prep->process(src,srcLength,b1, b1Capacity,allowUnassigned,parseError,*status); if(*status == U_BUFFER_OVERFLOW_ERROR){ // redo processing of string /* we do not have enough room so grow the buffer*/ b1 = (UChar*) uprv_malloc(b1Len * U_SIZEOF_UCHAR); if(b1==NULL){ *status = U_MEMORY_ALLOCATION_ERROR; goto CLEANUP; } *status = U_ZERO_ERROR; // reset error b1Len = prep->process(src,srcLength,b1, b1Len,allowUnassigned, parseError, *status); } // error bail out if(U_FAILURE(*status)){ goto CLEANUP; } if(b1Len == 0){ *status = U_IDNA_ZERO_LENGTH_LABEL_ERROR; goto CLEANUP; } srcIsASCII = TRUE; // step 3 & 4 for( j=0;j<b1Len;j++){ if(b1[j] > 0x7F){// check if output of usprep_prepare is all ASCII srcIsASCII = FALSE; }else if(prep->isLDHChar(b1[j])==FALSE){ // if the char is in ASCII range verify that it is an LDH character{ srcIsLDH = FALSE; } } if(useSTD3ASCIIRules == TRUE){ // verify 3a and 3b if( srcIsLDH == FALSE /* source contains some non-LDH characters */ || b1[0] == HYPHEN || b1[b1Len-1] == HYPHEN){ *status = U_IDNA_STD3_ASCII_RULES_ERROR; goto CLEANUP; } } if(srcIsASCII){ if(b1Len <= destCapacity){ uprv_memmove(dest, b1, b1Len * U_SIZEOF_UCHAR); reqLength = b1Len; }else{ reqLength = b1Len; goto CLEANUP; } }else{ // step 5 : verify the sequence does not begin with ACE prefix if(!startsWithPrefix(b1,b1Len)){ //step 6: encode the sequence with punycode //caseFlags = (UBool*) uprv_malloc(b1Len * sizeof(UBool)); b2Len = convertToPuny(b1,b1Len, b2,b2Capacity,*status); //b2Len = u_strToPunycode(b2,b2Capacity,b1,b1Len, caseFlags, status); if(*status == U_BUFFER_OVERFLOW_ERROR){ // redo processing of string /* we do not have enough room so grow the buffer*/ b2 = (UChar*) uprv_malloc(b2Len * U_SIZEOF_UCHAR); if(b2 == NULL){ *status = U_MEMORY_ALLOCATION_ERROR; goto CLEANUP; } *status = U_ZERO_ERROR; // reset error b2Len = convertToPuny(b1, b1Len, b2, b2Len, *status); //b2Len = u_strToPunycode(b2,b2Len,b1,b1Len, caseFlags, status); } //error bail out if(U_FAILURE(*status)){ goto CLEANUP; } reqLength = b2Len+ACE_PREFIX_LENGTH; if(reqLength > destCapacity){ *status = U_BUFFER_OVERFLOW_ERROR; goto CLEANUP; } //Step 7: prepend the ACE prefix uprv_memcpy(dest,ACE_PREFIX,ACE_PREFIX_LENGTH * U_SIZEOF_UCHAR); //Step 6: copy the contents in b2 into dest uprv_memcpy(dest+ACE_PREFIX_LENGTH, b2, b2Len * U_SIZEOF_UCHAR); }else{ *status = U_IDNA_ACE_PREFIX_ERROR; goto CLEANUP; } } if(reqLength > MAX_LABEL_LENGTH){ *status = U_IDNA_LABEL_TOO_LONG_ERROR; } CLEANUP: if(b1 != b1Stack){ uprv_free(b1); } if(b2 != b2Stack){ uprv_free(b2); } uprv_free(caseFlags); // delete prep; return u_terminateUChars(dest, destCapacity, reqLength, status); }
/* * This method updates the cache and must be called with a lock */ const UChar* TZGNCore::getPartialLocationName(const UnicodeString& tzCanonicalID, const UnicodeString& mzID, UBool isLong, const UnicodeString& mzDisplayName) { U_ASSERT(!tzCanonicalID.isEmpty()); U_ASSERT(!mzID.isEmpty()); U_ASSERT(!mzDisplayName.isEmpty()); PartialLocationKey key; key.tzID = ZoneMeta::findTimeZoneID(tzCanonicalID); key.mzID = ZoneMeta::findMetaZoneID(mzID); key.isLong = isLong; U_ASSERT(key.tzID != NULL && key.mzID != NULL); const UChar* uplname = (const UChar*)uhash_get(fPartialLocationNamesMap, (void *)&key); if (uplname != NULL) { return uplname; } UnicodeString location; UnicodeString usCountryCode; ZoneMeta::getCanonicalCountry(tzCanonicalID, usCountryCode); if (!usCountryCode.isEmpty()) { char countryCode[ULOC_COUNTRY_CAPACITY]; U_ASSERT(usCountryCode.length() < ULOC_COUNTRY_CAPACITY); int32_t ccLen = usCountryCode.extract(0, usCountryCode.length(), countryCode, sizeof(countryCode), US_INV); countryCode[ccLen] = 0; UnicodeString regionalGolden; fTimeZoneNames->getReferenceZoneID(mzID, countryCode, regionalGolden); if (tzCanonicalID == regionalGolden) { // Use country name fLocaleDisplayNames->regionDisplayName(countryCode, location); } else { // Otherwise, use exemplar city name fTimeZoneNames->getExemplarLocationName(tzCanonicalID, location); } } else { fTimeZoneNames->getExemplarLocationName(tzCanonicalID, location); if (location.isEmpty()) { // This could happen when the time zone is not associated with a country, // and its ID is not hierarchical, for example, CST6CDT. // We use the canonical ID itself as the location for this case. location.setTo(tzCanonicalID); } } UErrorCode status = U_ZERO_ERROR; UnicodeString name; fFallbackFormat.format(location, mzDisplayName, name, status); if (U_FAILURE(status)) { return NULL; } uplname = fStringPool.get(name, status); if (U_SUCCESS(status)) { // Add the name to cache PartialLocationKey* cacheKey = (PartialLocationKey *)uprv_malloc(sizeof(PartialLocationKey)); if (cacheKey != NULL) { cacheKey->tzID = key.tzID; cacheKey->mzID = key.mzID; cacheKey->isLong = key.isLong; uhash_put(fPartialLocationNamesMap, (void *)cacheKey, (void *)uplname, &status); if (U_FAILURE(status)) { uprv_free(cacheKey); } else { // put the name to the local trie as well GNameInfo *nameinfo = (ZNameInfo *)uprv_malloc(sizeof(GNameInfo)); if (nameinfo != NULL) { nameinfo->type = isLong ? UTZGNM_LONG : UTZGNM_SHORT; nameinfo->tzID = key.tzID; fGNamesTrie.put(uplname, nameinfo, status); } } } } return uplname; }
U_CFUNC int32_t U_EXPORT2 idnaref_toUnicode(const UChar* src, int32_t srcLength, UChar* dest, int32_t destCapacity, int32_t options, UParseError* parseError, UErrorCode* status){ if(status == NULL || U_FAILURE(*status)){ return 0; } if((src == NULL) || (srcLength < -1) || (destCapacity<0) || (!dest && destCapacity > 0)){ *status = U_ILLEGAL_ARGUMENT_ERROR; return 0; } UChar b1Stack[MAX_LABEL_BUFFER_SIZE], b2Stack[MAX_LABEL_BUFFER_SIZE], b3Stack[MAX_LABEL_BUFFER_SIZE]; //initialize pointers to stack buffers UChar *b1 = b1Stack, *b2 = b2Stack, *b1Prime=NULL, *b3=b3Stack; int32_t b1Len, b2Len, b1PrimeLen, b3Len, b1Capacity = MAX_LABEL_BUFFER_SIZE, b2Capacity = MAX_LABEL_BUFFER_SIZE, b3Capacity = MAX_LABEL_BUFFER_SIZE, reqLength=0; // UParseError parseError; NamePrepTransform* prep = TestIDNA::getInstance(*status); b1Len = 0; UBool* caseFlags = NULL; //get the options UBool allowUnassigned = (UBool)((options & IDNAREF_ALLOW_UNASSIGNED) != 0); UBool useSTD3ASCIIRules = (UBool)((options & IDNAREF_USE_STD3_RULES) != 0); UBool srcIsASCII = TRUE; UBool srcIsLDH = TRUE; int32_t failPos =0; if(U_FAILURE(*status)){ goto CLEANUP; } // step 1: find out if all the codepoints in src are ASCII if(srcLength==-1){ srcLength = 0; for(;src[srcLength]!=0;){ if(src[srcLength]> 0x7f){ srcIsASCII = FALSE; }if(prep->isLDHChar(src[srcLength])==FALSE){ // here we do not assemble surrogates // since we know that LDH code points // are in the ASCII range only srcIsLDH = FALSE; failPos = srcLength; } srcLength++; } }else{ for(int32_t j=0; j<srcLength; j++){ if(src[j]> 0x7f){ srcIsASCII = FALSE; }else if(prep->isLDHChar(src[j])==FALSE){ // here we do not assemble surrogates // since we know that LDH code points // are in the ASCII range only srcIsLDH = FALSE; failPos = j; } } } if(srcIsASCII == FALSE){ // step 2: process the string b1Len = prep->process(src,srcLength,b1,b1Capacity,allowUnassigned, parseError, *status); if(*status == U_BUFFER_OVERFLOW_ERROR){ // redo processing of string /* we do not have enough room so grow the buffer*/ b1 = (UChar*) uprv_malloc(b1Len * U_SIZEOF_UCHAR); if(b1==NULL){ *status = U_MEMORY_ALLOCATION_ERROR; goto CLEANUP; } *status = U_ZERO_ERROR; // reset error b1Len = prep->process(src,srcLength,b1, b1Len,allowUnassigned, parseError, *status); } //bail out on error if(U_FAILURE(*status)){ goto CLEANUP; } }else{ // copy everything to b1 if(srcLength < b1Capacity){ uprv_memmove(b1,src, srcLength * U_SIZEOF_UCHAR); }else{ /* we do not have enough room so grow the buffer*/ b1 = (UChar*) uprv_malloc(srcLength * U_SIZEOF_UCHAR); if(b1==NULL){ *status = U_MEMORY_ALLOCATION_ERROR; goto CLEANUP; } uprv_memmove(b1,src, srcLength * U_SIZEOF_UCHAR); } b1Len = srcLength; } //step 3: verify ACE Prefix if(startsWithPrefix(src,srcLength)){ //step 4: Remove the ACE Prefix b1Prime = b1 + ACE_PREFIX_LENGTH; b1PrimeLen = b1Len - ACE_PREFIX_LENGTH; //step 5: Decode using punycode b2Len = convertFromPuny(b1Prime,b1PrimeLen, b2, b2Capacity, *status); //b2Len = u_strFromPunycode(b2, b2Capacity,b1Prime,b1PrimeLen, caseFlags, status); if(*status == U_BUFFER_OVERFLOW_ERROR){ // redo processing of string /* we do not have enough room so grow the buffer*/ b2 = (UChar*) uprv_malloc(b2Len * U_SIZEOF_UCHAR); if(b2==NULL){ *status = U_MEMORY_ALLOCATION_ERROR; goto CLEANUP; } *status = U_ZERO_ERROR; // reset error b2Len = convertFromPuny(b1Prime,b1PrimeLen, b2, b2Len, *status); //b2Len = u_strFromPunycode(b2, b2Len,b1Prime,b1PrimeLen,caseFlags, status); } //step 6:Apply toASCII b3Len = idnaref_toASCII(b2,b2Len,b3,b3Capacity,options,parseError, status); if(*status == U_BUFFER_OVERFLOW_ERROR){ // redo processing of string /* we do not have enough room so grow the buffer*/ b3 = (UChar*) uprv_malloc(b3Len * U_SIZEOF_UCHAR); if(b3==NULL){ *status = U_MEMORY_ALLOCATION_ERROR; goto CLEANUP; } *status = U_ZERO_ERROR; // reset error b3Len = idnaref_toASCII(b2,b2Len,b3,b3Len, options, parseError, status); } //bail out on error if(U_FAILURE(*status)){ goto CLEANUP; } //step 7: verify if(compareCaseInsensitiveASCII(b1, b1Len, b3, b3Len) !=0){ *status = U_IDNA_VERIFICATION_ERROR; goto CLEANUP; } //step 8: return output of step 5 reqLength = b2Len; if(b2Len <= destCapacity) { uprv_memmove(dest, b2, b2Len * U_SIZEOF_UCHAR); } }else{ // verify that STD3 ASCII rules are satisfied if(useSTD3ASCIIRules == TRUE){ if( srcIsLDH == FALSE /* source contains some non-LDH characters */ || src[0] == HYPHEN || src[srcLength-1] == HYPHEN){ *status = U_IDNA_STD3_ASCII_RULES_ERROR; /* populate the parseError struct */ if(srcIsLDH==FALSE){ // failPos is always set the index of failure uprv_syntaxError(src,failPos, srcLength,parseError); }else if(src[0] == HYPHEN){ // fail position is 0 uprv_syntaxError(src,0,srcLength,parseError); }else{ // the last index in the source is always length-1 uprv_syntaxError(src, (srcLength>0) ? srcLength-1 : srcLength, srcLength,parseError); } goto CLEANUP; } } //copy the source to destination if(srcLength <= destCapacity){ uprv_memmove(dest,src,srcLength * U_SIZEOF_UCHAR); } reqLength = srcLength; } CLEANUP: if(b1 != b1Stack){ uprv_free(b1); } if(b2 != b2Stack){ uprv_free(b2); } uprv_free(caseFlags); // The RFC states that // <quote> // ToUnicode never fails. If any step fails, then the original input // is returned immediately in that step. // </quote> // So if any step fails lets copy source to destination if(U_FAILURE(*status)){ //copy the source to destination if(dest && srcLength <= destCapacity){ if(srcLength == -1) { uprv_memmove(dest,src,u_strlen(src)* U_SIZEOF_UCHAR); } else { uprv_memmove(dest,src,srcLength * U_SIZEOF_UCHAR); } } reqLength = srcLength; *status = U_ZERO_ERROR; } return u_terminateUChars(dest, destCapacity, reqLength, status); }
static int32_t _internal_toASCII(const UChar* src, int32_t srcLength, UChar* dest, int32_t destCapacity, int32_t options, UStringPrepProfile* nameprep, UParseError* parseError, UErrorCode* status) { // TODO Revisit buffer handling. The label should not be over 63 ASCII characters. ICU4J may need to be updated too. UChar b1Stack[MAX_LABEL_BUFFER_SIZE], b2Stack[MAX_LABEL_BUFFER_SIZE]; //initialize pointers to stack buffers UChar *b1 = b1Stack, *b2 = b2Stack; int32_t b1Len=0, b2Len, b1Capacity = MAX_LABEL_BUFFER_SIZE, b2Capacity = MAX_LABEL_BUFFER_SIZE , reqLength=0; int32_t namePrepOptions = ((options & UIDNA_ALLOW_UNASSIGNED) != 0) ? USPREP_ALLOW_UNASSIGNED: 0; UBool* caseFlags = NULL; // the source contains all ascii codepoints UBool srcIsASCII = TRUE; // assume the source contains all LDH codepoints UBool srcIsLDH = TRUE; int32_t j=0; //get the options UBool useSTD3ASCIIRules = (UBool)((options & UIDNA_USE_STD3_RULES) != 0); int32_t failPos = -1; if(srcLength == -1){ srcLength = u_strlen(src); } if(srcLength > b1Capacity){ b1 = (UChar*) uprv_malloc(srcLength * U_SIZEOF_UCHAR); if(b1==NULL){ *status = U_MEMORY_ALLOCATION_ERROR; goto CLEANUP; } b1Capacity = srcLength; } // step 1 for( j=0;j<srcLength;j++){ if(src[j] > 0x7F){ srcIsASCII = FALSE; } b1[b1Len++] = src[j]; } // step 2 is performed only if the source contains non ASCII if(srcIsASCII == FALSE){ // step 2 b1Len = usprep_prepare(nameprep, src, srcLength, b1, b1Capacity, namePrepOptions, parseError, status); if(*status == U_BUFFER_OVERFLOW_ERROR){ // redo processing of string // we do not have enough room so grow the buffer if(b1 != b1Stack){ uprv_free(b1); } b1 = (UChar*) uprv_malloc(b1Len * U_SIZEOF_UCHAR); if(b1==NULL){ *status = U_MEMORY_ALLOCATION_ERROR; goto CLEANUP; } *status = U_ZERO_ERROR; // reset error b1Len = usprep_prepare(nameprep, src, srcLength, b1, b1Len, namePrepOptions, parseError, status); } } // error bail out if(U_FAILURE(*status)){ goto CLEANUP; } if(b1Len == 0){ *status = U_IDNA_ZERO_LENGTH_LABEL_ERROR; goto CLEANUP; } // for step 3 & 4 srcIsASCII = TRUE; for( j=0;j<b1Len;j++){ // check if output of usprep_prepare is all ASCII if(b1[j] > 0x7F){ srcIsASCII = FALSE; }else if(isLDHChar(b1[j])==FALSE){ // if the char is in ASCII range verify that it is an LDH character srcIsLDH = FALSE; failPos = j; } } if(useSTD3ASCIIRules == TRUE){ // verify 3a and 3b // 3(a) Verify the absence of non-LDH ASCII code points; that is, the // absence of 0..2C, 2E..2F, 3A..40, 5B..60, and 7B..7F. // 3(b) Verify the absence of leading and trailing hyphen-minus; that // is, the absence of U+002D at the beginning and end of the // sequence. if( srcIsLDH == FALSE /* source at this point should not contain anyLDH characters */ || b1[0] == HYPHEN || b1[b1Len-1] == HYPHEN){ *status = U_IDNA_STD3_ASCII_RULES_ERROR; /* populate the parseError struct */ if(srcIsLDH==FALSE){ // failPos is always set the index of failure uprv_syntaxError(b1,failPos, b1Len,parseError); }else if(b1[0] == HYPHEN){ // fail position is 0 uprv_syntaxError(b1,0,b1Len,parseError); }else{ // the last index in the source is always length-1 uprv_syntaxError(b1, (b1Len>0) ? b1Len-1 : b1Len, b1Len,parseError); } goto CLEANUP; } } // Step 4: if the source is ASCII then proceed to step 8 if(srcIsASCII){ if(b1Len <= destCapacity){ uprv_memmove(dest, b1, b1Len * U_SIZEOF_UCHAR); reqLength = b1Len; }else{ reqLength = b1Len; goto CLEANUP; } }else{ // step 5 : verify the sequence does not begin with ACE prefix if(!startsWithPrefix(b1,b1Len)){ //step 6: encode the sequence with punycode // do not preserve the case flags for now! // TODO: Preserve the case while implementing the RFE // caseFlags = (UBool*) uprv_malloc(b1Len * sizeof(UBool)); // uprv_memset(caseFlags,TRUE,b1Len); b2Len = u_strToPunycode(b1,b1Len,b2,b2Capacity,caseFlags, status); if(*status == U_BUFFER_OVERFLOW_ERROR){ // redo processing of string /* we do not have enough room so grow the buffer*/ b2 = (UChar*) uprv_malloc(b2Len * U_SIZEOF_UCHAR); if(b2 == NULL){ *status = U_MEMORY_ALLOCATION_ERROR; goto CLEANUP; } *status = U_ZERO_ERROR; // reset error b2Len = u_strToPunycode(b1,b1Len,b2,b2Len,caseFlags, status); } //error bail out if(U_FAILURE(*status)){ goto CLEANUP; } // TODO : Reconsider while implementing the case preserve RFE // convert all codepoints to lower case ASCII // toASCIILower(b2,b2Len); reqLength = b2Len+ACE_PREFIX_LENGTH; if(reqLength > destCapacity){ *status = U_BUFFER_OVERFLOW_ERROR; goto CLEANUP; } //Step 7: prepend the ACE prefix uprv_memcpy(dest,ACE_PREFIX,ACE_PREFIX_LENGTH * U_SIZEOF_UCHAR); //Step 6: copy the contents in b2 into dest uprv_memcpy(dest+ACE_PREFIX_LENGTH, b2, b2Len * U_SIZEOF_UCHAR); }else{ *status = U_IDNA_ACE_PREFIX_ERROR; //position of failure is 0 uprv_syntaxError(b1,0,b1Len,parseError); goto CLEANUP; } } // step 8: verify the length of label if(reqLength > MAX_LABEL_LENGTH){ *status = U_IDNA_LABEL_TOO_LONG_ERROR; } CLEANUP: if(b1 != b1Stack){ uprv_free(b1); } if(b2 != b2Stack){ uprv_free(b2); } uprv_free(caseFlags); return u_terminateUChars(dest, destCapacity, reqLength, status); }
U_CFUNC int32_t U_EXPORT2 idnaref_IDNToUnicode( const UChar* src, int32_t srcLength, UChar* dest, int32_t destCapacity, int32_t options, UParseError* parseError, UErrorCode* status){ if(status == NULL || U_FAILURE(*status)){ return 0; } if((src == NULL) || (srcLength < -1) || (destCapacity<0) || (!dest && destCapacity > 0)){ *status = U_ILLEGAL_ARGUMENT_ERROR; return 0; } int32_t reqLength = 0; UBool done = FALSE; NamePrepTransform* prep = TestIDNA::getInstance(*status); //initialize pointers to stack buffers UChar b1Stack[MAX_LABEL_BUFFER_SIZE]; UChar *b1 = b1Stack; int32_t b1Len, labelLen; UChar* delimiter = (UChar*)src; UChar* labelStart = (UChar*)src; int32_t remainingLen = srcLength; int32_t b1Capacity = MAX_LABEL_BUFFER_SIZE; //get the options // UBool allowUnassigned = (UBool)((options & IDNAREF_ALLOW_UNASSIGNED) != 0); // UBool useSTD3ASCIIRules = (UBool)((options & IDNAREF_USE_STD3_RULES) != 0); if(U_FAILURE(*status)){ goto CLEANUP; } if(srcLength == -1){ for(;;){ if(*delimiter == 0){ break; } labelLen = getNextSeparator(labelStart, -1, prep, &delimiter, &done, status); if(labelLen==0 && done==FALSE){ *status = U_IDNA_ZERO_LENGTH_LABEL_ERROR; } b1Len = idnaref_toUnicode(labelStart, labelLen, b1, b1Capacity, options, parseError, status); if(*status == U_BUFFER_OVERFLOW_ERROR){ // redo processing of string /* we do not have enough room so grow the buffer*/ b1 = (UChar*) uprv_malloc(b1Len * U_SIZEOF_UCHAR); if(b1==NULL){ *status = U_MEMORY_ALLOCATION_ERROR; goto CLEANUP; } *status = U_ZERO_ERROR; // reset error b1Len = idnaref_toUnicode( labelStart, labelLen, b1, b1Len, options, parseError, status); } if(U_FAILURE(*status)){ goto CLEANUP; } int32_t tempLen = (reqLength + b1Len ); // copy to dest if( tempLen< destCapacity){ uprv_memmove(dest+reqLength, b1, b1Len * U_SIZEOF_UCHAR); } reqLength = tempLen; // add the label separator if(done == FALSE){ if(reqLength < destCapacity){ dest[reqLength] = FULL_STOP; } reqLength++; } labelStart = delimiter; } }else{ for(;;){ if(delimiter == src+srcLength){ break; } labelLen = getNextSeparator(labelStart, remainingLen, prep, &delimiter, &done, status); if(labelLen==0 && done==FALSE){ *status = U_IDNA_ZERO_LENGTH_LABEL_ERROR; } b1Len = idnaref_toUnicode( labelStart,labelLen, b1, b1Capacity, options, parseError, status); if(*status == U_BUFFER_OVERFLOW_ERROR){ // redo processing of string /* we do not have enough room so grow the buffer*/ b1 = (UChar*) uprv_malloc(b1Len * U_SIZEOF_UCHAR); if(b1==NULL){ *status = U_MEMORY_ALLOCATION_ERROR; goto CLEANUP; } *status = U_ZERO_ERROR; // reset error b1Len = idnaref_toUnicode( labelStart, labelLen, b1, b1Len, options, parseError, status); } if(U_FAILURE(*status)){ goto CLEANUP; } int32_t tempLen = (reqLength + b1Len ); // copy to dest if( tempLen< destCapacity){ uprv_memmove(dest+reqLength, b1, b1Len * U_SIZEOF_UCHAR); } reqLength = tempLen; // add the label separator if(done == FALSE){ if(reqLength < destCapacity){ dest[reqLength] = FULL_STOP; } reqLength++; } labelStart = delimiter; remainingLen = srcLength - (delimiter - src); } } CLEANUP: if(b1 != b1Stack){ uprv_free(b1); } // delete prep; return u_terminateUChars(dest, destCapacity, reqLength, status); }
UCharsTrieBuilder::~UCharsTrieBuilder() { delete[] elements; uprv_free(uchars); }
U_CFUNC int32_t U_EXPORT2 idnaref_compare( const UChar *s1, int32_t length1, const UChar *s2, int32_t length2, int32_t options, UErrorCode* status){ if(status == NULL || U_FAILURE(*status)){ return -1; } UChar b1Stack[MAX_IDN_BUFFER_SIZE], b2Stack[MAX_IDN_BUFFER_SIZE]; UChar *b1 = b1Stack, *b2 = b2Stack; int32_t b1Len, b2Len, b1Capacity = MAX_IDN_BUFFER_SIZE, b2Capacity = MAX_IDN_BUFFER_SIZE; int32_t result = -1; UParseError parseError; b1Len = idnaref_IDNToASCII(s1, length1, b1, b1Capacity, options, &parseError, status); if(*status == U_BUFFER_OVERFLOW_ERROR){ // redo processing of string /* we do not have enough room so grow the buffer*/ b1 = (UChar*) uprv_malloc(b1Len * U_SIZEOF_UCHAR); if(b1==NULL){ *status = U_MEMORY_ALLOCATION_ERROR; goto CLEANUP; } *status = U_ZERO_ERROR; // reset error b1Len = idnaref_IDNToASCII(s1,length1,b1,b1Len, options, &parseError, status); } b2Len = idnaref_IDNToASCII(s2,length2,b2,b2Capacity,options, &parseError, status); if(*status == U_BUFFER_OVERFLOW_ERROR){ // redo processing of string /* we do not have enough room so grow the buffer*/ b2 = (UChar*) uprv_malloc(b2Len * U_SIZEOF_UCHAR); if(b2==NULL){ *status = U_MEMORY_ALLOCATION_ERROR; goto CLEANUP; } *status = U_ZERO_ERROR; // reset error b2Len = idnaref_IDNToASCII(s2,length2,b2,b2Len,options, &parseError, status); } // when toASCII is applied all label separators are replaced with FULL_STOP result = compareCaseInsensitiveASCII(b1,b1Len,b2,b2Len); CLEANUP: if(b1 != b1Stack){ uprv_free(b1); } if(b2 != b2Stack){ uprv_free(b2); } return result; }
static void U_CALLCONV ucharstrenum_close(UEnumeration* en) { uprv_free(en); }
static UFILE* finit_owner(FILE *f, const char *locale, const char *codepage, UBool takeOwnership ) { UErrorCode status = U_ZERO_ERROR; UFILE *result; if(f == NULL) { return 0; } result = (UFILE*) uprv_malloc(sizeof(UFILE)); if(result == NULL) { return 0; } uprv_memset(result, 0, sizeof(UFILE)); result->fFileno = fileno(f); #ifdef U_WINDOWS if (0 <= result->fFileno && result->fFileno <= 2) { /* stdin, stdout and stderr need to be special cased for Windows 98 */ #if _MSC_VER >= 1400 result->fFile = &__iob_func()[_fileno(f)]; #else result->fFile = &_iob[_fileno(f)]; #endif } else #endif { result->fFile = f; } result->str.fBuffer = result->fUCBuffer; result->str.fPos = result->fUCBuffer; result->str.fLimit = result->fUCBuffer; #if !UCONFIG_NO_FORMATTING /* if locale is 0, use the default */ if(u_locbund_init(&result->str.fBundle, locale) == 0) { /* DO NOT FCLOSE HERE! */ uprv_free(result); return 0; } #endif /* If the codepage is not "" use the ucnv_open default behavior */ if(codepage == NULL || *codepage != '\0') { result->fConverter = ucnv_open(codepage, &status); } /* else result->fConverter is already memset'd to NULL. */ if(U_SUCCESS(status)) { result->fOwnFile = takeOwnership; } else { #if !UCONFIG_NO_FORMATTING u_locbund_close(&result->str.fBundle); #endif /* DO NOT fclose here!!!!!! */ uprv_free(result); result = NULL; } return result; }
static void TestAPI(void) { int32_t intValue=0; char src[30]="HELLO THERE", dest[30]; static const char *const abc="abcdefghijklmnopqrstuvwxyz", *const ABC="ABCDEFGHIJKLMNOPQRSTUVWXYZ"; const char *temp; int32_t i; log_verbose("Testing uprv_tolower() and uprv_toupper()\n"); for(i=0; i<=26; ++i) { dest[i]=uprv_tolower(abc[i]); } if(0!=strcmp(abc, dest)) { log_err("uprv_tolower(abc) failed\n"); } for(i=0; i<=26; ++i) { dest[i]=uprv_tolower(ABC[i]); } if(0!=strcmp(abc, dest)) { log_err("uprv_tolower(ABC) failed\n"); } for(i=0; i<=26; ++i) { dest[i]=uprv_toupper(abc[i]); } if(0!=strcmp(ABC, dest)) { log_err("uprv_toupper(abc) failed\n"); } for(i=0; i<=26; ++i) { dest[i]=uprv_toupper(ABC[i]); } if(0!=strcmp(ABC, dest)) { log_err("uprv_toupper(ABC) failed\n"); } log_verbose("Testing the API in cstring\n"); T_CString_toLowerCase(src); if(uprv_strcmp(src, "hello there") != 0){ log_err("FAIL: *** T_CString_toLowerCase() failed. Expected: \"hello there\", Got: \"%s\"\n", src); } T_CString_toUpperCase(src); if(uprv_strcmp(src, "HELLO THERE") != 0){ log_err("FAIL: *** T_CString_toUpperCase() failed. Expected: \"HELLO THERE\", Got: \"%s\"\n", src); } intValue=T_CString_stringToInteger("34556", 10); if(intValue != 34556){ log_err("FAIL: ****T_CString_stringToInteger(\"34556\", 10) failed. Expected: 34556, Got: %d\n", intValue); } intValue=T_CString_stringToInteger("100", 16); if(intValue != 256){ log_err("FAIL: ****T_CString_stringToInteger(\"100\", 16) failed. Expected: 256, Got: %d\n", intValue); } i = T_CString_integerToString(src, 34556, 10); if(uprv_strcmp(src, "34556") != 0 || i != 5){ log_err("FAIL: ****integerToString(src, 34566, 10); failed. Expected: \"34556\", Got: %s\n", src); } i = T_CString_integerToString(src, 431, 16); if(uprv_stricmp(src, "1AF") != 0 || i != 3){ log_err("FAIL: ****integerToString(src, 431, 16); failed. Expected: \"1AF\", Got: %s\n", src); } i = T_CString_int64ToString(src, U_INT64_MAX, 10); if(uprv_strcmp(src, "9223372036854775807") != 0 || i != 19){ log_err("FAIL: ****integerToString(src, 9223372036854775807, 10); failed. Got: %s\n", src); } i = T_CString_int64ToString(src, U_INT64_MAX, 16); if(uprv_stricmp(src, "7FFFFFFFFFFFFFFF") != 0 || i != 16){ log_err("FAIL: ****integerToString(src, 7FFFFFFFFFFFFFFF, 16); failed. Got: %s\n", src); } uprv_strcpy(src, "this is lower case"); if(T_CString_stricmp(src, "THIS is lower CASE") != 0){ log_err("FAIL: *****T_CString_stricmp() failed."); } if((intValue=T_CString_stricmp(NULL, "first string is null") )!= -1){ log_err("FAIL: T_CString_stricmp() where the first string is null failed. Expected: -1, returned %d\n", intValue); } if((intValue=T_CString_stricmp("second string is null", NULL)) != 1){ log_err("FAIL: T_CString_stricmp() where the second string is null failed. Expected: 1, returned %d\n", intValue); } if((intValue=T_CString_stricmp(NULL, NULL)) != 0){ log_err("FAIL: T_CString_stricmp(NULL, NULL) failed. Expected: 0, returned %d\n", intValue);; } if((intValue=T_CString_stricmp("", "")) != 0){ log_err("FAIL: T_CString_stricmp(\"\", \"\") failed. Expected: 0, returned %d\n", intValue);; } if((intValue=T_CString_stricmp("", "abc")) != -1){ log_err("FAIL: T_CString_stricmp(\"\", \"abc\") failed. Expected: -1, returned %d\n", intValue); } if((intValue=T_CString_stricmp("abc", "")) != 1){ log_err("FAIL: T_CString_stricmp(\"abc\", \"\") failed. Expected: 1, returned %d\n", intValue); } temp=uprv_strdup("strdup"); if(uprv_strcmp(temp, "strdup") !=0 ){ log_err("FAIL: uprv_strdup() failed. Expected: \"strdup\", Got: %s\n", temp); } uprv_free((char *)temp); uprv_strcpy(src, "this is lower case"); if(T_CString_strnicmp(src, "THIS", 4 ) != 0){ log_err("FAIL: *****T_CString_strnicmp() failed."); } if((intValue=T_CString_strnicmp(NULL, "first string is null", 10) )!= -1){ log_err("FAIL: T_CString_strnicmp() where the first string is null failed. Expected: -1, returned %d\n", intValue); } if((intValue=T_CString_strnicmp("second string is null", NULL, 10)) != 1){ log_err("FAIL: T_CString_strnicmp() where the second string is null failed. Expected: 1, returned %d\n", intValue); } if((intValue=T_CString_strnicmp(NULL, NULL, 10)) != 0){ log_err("FAIL: T_CString_strnicmp(NULL, NULL, 10) failed. Expected: 0, returned %d\n", intValue);; } if((intValue=T_CString_strnicmp("", "", 10)) != 0){ log_err("FAIL: T_CString_strnicmp(\"\", \"\") failed. Expected: 0, returned %d\n", intValue);; } if((intValue=T_CString_strnicmp("", "abc", 10)) != -1){ log_err("FAIL: T_CString_stricmp(\"\", \"abc\", 10) failed. Expected: -1, returned %d\n", intValue); } if((intValue=T_CString_strnicmp("abc", "", 10)) != 1){ log_err("FAIL: T_CString_strnicmp(\"abc\", \"\", 10) failed. Expected: 1, returned %d\n", intValue); } }
BitSet::~BitSet() { uprv_free(data); }
U_CAPI UCHARBUF* U_EXPORT2 ucbuf_open(const char* fileName,const char** cp,UBool showWarning, UBool buffered, UErrorCode* error){ FileStream* in = NULL; int32_t fileSize=0; const char* knownCp; if(error==NULL || U_FAILURE(*error)){ return NULL; } if(cp==NULL || fileName==NULL){ *error = U_ILLEGAL_ARGUMENT_ERROR; return FALSE; } if (!uprv_strcmp(fileName, "-")) { in = T_FileStream_stdin(); }else{ in = T_FileStream_open(fileName, "rb"); } if(in!=NULL){ UCHARBUF* buf =(UCHARBUF*) uprv_malloc(sizeof(UCHARBUF)); fileSize = T_FileStream_size(in); if(buf == NULL){ *error = U_MEMORY_ALLOCATION_ERROR; T_FileStream_close(in); return NULL; } buf->in=in; buf->conv=NULL; buf->showWarning = showWarning; buf->isBuffered = buffered; buf->signatureLength=0; if(*cp==NULL || **cp=='\0'){ /* don't have code page name... try to autodetect */ ucbuf_autodetect_fs(in,cp,&buf->conv,&buf->signatureLength,error); }else if(ucbuf_isCPKnown(*cp)){ /* discard BOM */ ucbuf_autodetect_fs(in,&knownCp,&buf->conv,&buf->signatureLength,error); } if(U_SUCCESS(*error) && buf->conv==NULL) { buf->conv=ucnv_open(*cp,error); } if(U_FAILURE(*error)){ ucnv_close(buf->conv); uprv_free(buf); T_FileStream_close(in); return NULL; } if((buf->conv==NULL) && (buf->showWarning==TRUE)){ fprintf(stderr,"###WARNING: No converter defined. Using codepage of system.\n"); } buf->remaining=fileSize-buf->signatureLength; if(buf->isBuffered){ buf->bufCapacity=MAX_U_BUF; }else{ buf->bufCapacity=buf->remaining+buf->signatureLength+1/*for terminating nul*/; } buf->buffer=(UChar*) uprv_malloc(U_SIZEOF_UCHAR * buf->bufCapacity ); if (buf->buffer == NULL) { *error = U_MEMORY_ALLOCATION_ERROR; ucbuf_close(buf); return NULL; } buf->currentPos=buf->buffer; buf->bufLimit=buf->buffer; if(U_FAILURE(*error)){ fprintf(stderr, "Could not open codepage [%s]: %s\n", *cp, u_errorName(*error)); ucbuf_close(buf); return NULL; } ucbuf_fillucbuf(buf,error); if(U_FAILURE(*error)){ ucbuf_close(buf); return NULL; } return buf; } *error =U_FILE_ACCESS_ERROR; return NULL; }
/** * Deleter for TZGNCoreRef */ static void U_CALLCONV deleteTZGNCoreRef(void *obj) { icu::TZGNCoreRef *entry = (icu::TZGNCoreRef*)obj; delete (icu::TZGNCore*) entry->obj; uprv_free(entry); }
U_CAPI int32_t U_EXPORT2 uprv_cnttab_constructTable(CntTable *table, uint32_t mainOffset, UErrorCode *status) { int32_t i = 0, j = 0; if(U_FAILURE(*status) || table->size == 0) { return 0; } table->position = 0; if(table->offsets != NULL) { uprv_free(table->offsets); } table->offsets = (int32_t *)uprv_malloc(table->size*sizeof(int32_t)); if(table->offsets == NULL) { *status = U_MEMORY_ALLOCATION_ERROR; return 0; } /* See how much memory we need */ for(i = 0; i<table->size; i++) { table->offsets[i] = table->position+mainOffset; table->position += table->elements[i]->position; } /* Allocate it */ if(table->CEs != NULL) { uprv_free(table->CEs); } table->CEs = (uint32_t *)uprv_malloc(table->position*sizeof(uint32_t)); if(table->CEs == NULL) { *status = U_MEMORY_ALLOCATION_ERROR; uprv_free(table->offsets); table->offsets = NULL; return 0; } uprv_memset(table->CEs, '?', table->position*sizeof(uint32_t)); if(table->codePoints != NULL) { uprv_free(table->codePoints); } table->codePoints = (UChar *)uprv_malloc(table->position*sizeof(UChar)); if(table->codePoints == NULL) { *status = U_MEMORY_ALLOCATION_ERROR; uprv_free(table->offsets); table->offsets = NULL; uprv_free(table->CEs); table->CEs = NULL; return 0; } uprv_memset(table->codePoints, '?', table->position*sizeof(UChar)); /* Now stuff the things in*/ UChar *cpPointer = table->codePoints; uint32_t *CEPointer = table->CEs; for(i = 0; i<table->size; i++) { int32_t size = table->elements[i]->position; uint8_t ccMax = 0, ccMin = 255, cc = 0; for(j = 1; j<size; j++) { cc = u_getCombiningClass(table->elements[i]->codePoints[j]); if(cc>ccMax) { ccMax = cc; } if(cc<ccMin) { ccMin = cc; } *(cpPointer+j) = table->elements[i]->codePoints[j]; } *cpPointer = ((ccMin==ccMax)?1:0 << 8) | ccMax; uprv_memcpy(CEPointer, table->elements[i]->CEs, size*sizeof(uint32_t)); for(j = 0; j<size; j++) { if(isCntTableElement(*(CEPointer+j))) { *(CEPointer+j) = constructContractCE(getCETag(*(CEPointer+j)), table->offsets[getContractOffset(*(CEPointer+j))]); } } cpPointer += size; CEPointer += size; } // TODO: this one apparently updates the contraction CEs to point to a real address (relative to the // start of the flat file). However, what is done below is just wrong and it affects building of // tailorings that have constructions in a bad way. At least, one should enumerate the trie. Also, // keeping a list of code points that are contractions might be smart, although I'm not sure if it's // feasible. uint32_t CE; for(i = 0; i<=0x10FFFF; i++) { /*CE = ucmpe32_get(table->mapping, i);*/ CE = utrie_get32(table->mapping, i, NULL); if(isCntTableElement(CE)) { CE = constructContractCE(getCETag(CE), table->offsets[getContractOffset(CE)]); /*ucmpe32_set(table->mapping, i, CE);*/ utrie_set32(table->mapping, i, CE); } } return table->position; }
/* *Name : expandLamAlef *Function : LamAlef needs special handling as the LamAlef is * one character while expanding it will give two * characters Lam + Alef, so we need to expand the LamAlef * in near or far spaces according to the options the user * specifies or increase the buffer size. * If there are no spaces to expand the LamAlef, an error * will be set to U_NO_SPACE_AVAILABLE as defined in utypes.h */ static int32_t expandLamAlef(UChar *dest, int32_t sourceLength, int32_t destSize,uint32_t options, UErrorCode *pErrorCode) { int32_t i = 0,j = 0; int32_t countl = 0; int32_t countr = 0; int32_t inpsize = sourceLength; UChar lamalefChar; UChar *tempbuffer=NULL; switch(options&U_SHAPE_LENGTH_MASK) { case U_SHAPE_LENGTH_GROW_SHRINK : destSize = calculateSize(dest,sourceLength,destSize,options); tempbuffer = (UChar *)uprv_malloc((destSize+1)*U_SIZEOF_UCHAR); /* Test for NULL */ if(tempbuffer == NULL) { *pErrorCode = U_MEMORY_ALLOCATION_ERROR; return 0; } uprv_memset(tempbuffer, 0, (destSize+1)*U_SIZEOF_UCHAR); i = j = 0; while(i < destSize && j < destSize) { if( isLamAlefChar(dest[i]) ) { tempbuffer[j] = convertLamAlef[ dest[i] - 0xFEF5 ]; tempbuffer[j+1] = 0x0644; j++; } else tempbuffer[j] = dest[i]; i++; j++; } uprv_memcpy(dest, tempbuffer, destSize*U_SIZEOF_UCHAR); break; case U_SHAPE_LENGTH_FIXED_SPACES_NEAR : for(i = 0;i<sourceLength;i++) { if((dest[i] == 0x0020) && isLamAlefChar(dest[i+1])) { lamalefChar = dest[i+1]; dest[i+1] = 0x0644; dest[i] = convertLamAlef[ lamalefChar - 0xFEF5 ]; } else if((dest[i] != 0x0020) && isLamAlefChar(dest[i+1])) { *pErrorCode=U_NO_SPACE_AVAILABLE; } } destSize = sourceLength; break; case U_SHAPE_LENGTH_FIXED_SPACES_AT_BEGINNING : tempbuffer = (UChar *)uprv_malloc((sourceLength+1)*U_SIZEOF_UCHAR); /* Test for NULL */ if(tempbuffer == NULL) { *pErrorCode = U_MEMORY_ALLOCATION_ERROR; return 0; } uprv_memset(tempbuffer, 0, (sourceLength+1)*U_SIZEOF_UCHAR); i = 0; while(dest[i] == 0x0020) { countl++; i++; } i = j = sourceLength-1; while(i >= 0 && j >= 0) { if( countl>0 && isLamAlefChar(dest[i]) ) { tempbuffer[j] = 0x0644; tempbuffer[j-1] = convertLamAlef[ dest[i] - 0xFEF5 ]; j--; countl--; } else { if( countl == 0 && isLamAlefChar(dest[i]) ) *pErrorCode=U_NO_SPACE_AVAILABLE; tempbuffer[j] = dest[i]; } i--; j--; } uprv_memcpy(dest, tempbuffer, sourceLength*U_SIZEOF_UCHAR); destSize = sourceLength; break; case U_SHAPE_LENGTH_FIXED_SPACES_AT_END : /* LamAlef expansion below is done from right to left to make sure that we consume * the spaces with the LamAlefs as they appear in the visual buffer from right to left */ tempbuffer = (UChar *)uprv_malloc((sourceLength+1)*U_SIZEOF_UCHAR); /* Test for NULL */ if(tempbuffer == NULL) { *pErrorCode = U_MEMORY_ALLOCATION_ERROR; return 0; } uprv_memset(tempbuffer, 0, (sourceLength+1)*U_SIZEOF_UCHAR); while(dest[inpsize-1] == 0x0020) { countr++; inpsize--; } i = sourceLength - countr - 1; j = sourceLength - 1; while(i >= 0 && j >= 0) { if( countr>0 && isLamAlefChar(dest[i]) ) { tempbuffer[j] = 0x0644; tempbuffer[j-1] = convertLamAlef[ dest[i] - 0xFEF5 ]; j--; countr--; } else { if( countr == 0 && isLamAlefChar(dest[i]) ) *pErrorCode=U_NO_SPACE_AVAILABLE; tempbuffer[j] = dest[i]; } i--; j--; } if(countr > 0) { uprv_memcpy(tempbuffer, tempbuffer+countr, sourceLength*U_SIZEOF_UCHAR); if(u_strlen(tempbuffer) < sourceLength) { for(i=sourceLength-1;i>=sourceLength-countr;i--) tempbuffer[i] = 0x0020; } } uprv_memcpy(dest, tempbuffer, sourceLength*U_SIZEOF_UCHAR); destSize = sourceLength; break; default : /* will never occur because of validity checks */ break; } if(tempbuffer) uprv_free(tempbuffer); return destSize; }