|  | /* | 
|  | ********************************************************************** | 
|  | * Copyright (c) 2002-2014, International Business Machines | 
|  | * Corporation and others.  All Rights Reserved. | 
|  | ********************************************************************** | 
|  | * Author: Alan Liu | 
|  | * Created: October 30 2002 | 
|  | * Since: ICU 2.4 | 
|  | * 2010nov19 Markus Scherer  Rewrite for formatVersion 2. | 
|  | ********************************************************************** | 
|  | */ | 
|  | #include "starboard/client_porting/poem/string_poem.h" | 
|  | #include "propname.h" | 
|  | #include "unicode/uchar.h" | 
|  | #include "unicode/udata.h" | 
|  | #include "unicode/uscript.h" | 
|  | #include "umutex.h" | 
|  | #include "cmemory.h" | 
|  | #include "cstring.h" | 
|  | #include "uarrsort.h" | 
|  | #include "uinvchar.h" | 
|  |  | 
|  | #define INCLUDED_FROM_PROPNAME_CPP | 
|  | #include "propname_data.h" | 
|  |  | 
|  | U_CDECL_BEGIN | 
|  |  | 
|  | /** | 
|  | * Get the next non-ignorable ASCII character from a property name | 
|  | * and lowercases it. | 
|  | * @return ((advance count for the name)<<8)|character | 
|  | */ | 
|  | static inline int32_t | 
|  | getASCIIPropertyNameChar(const char *name) { | 
|  | int32_t i; | 
|  | char c; | 
|  |  | 
|  | /* Ignore delimiters '-', '_', and ASCII White_Space */ | 
|  | for(i=0; | 
|  | (c=name[i++])==0x2d || c==0x5f || | 
|  | c==0x20 || (0x09<=c && c<=0x0d); | 
|  | ) {} | 
|  |  | 
|  | if(c!=0) { | 
|  | return (i<<8)|(uint8_t)uprv_asciitolower((char)c); | 
|  | } else { | 
|  | return i<<8; | 
|  | } | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Get the next non-ignorable EBCDIC character from a property name | 
|  | * and lowercases it. | 
|  | * @return ((advance count for the name)<<8)|character | 
|  | */ | 
|  | static inline int32_t | 
|  | getEBCDICPropertyNameChar(const char *name) { | 
|  | int32_t i; | 
|  | char c; | 
|  |  | 
|  | /* Ignore delimiters '-', '_', and EBCDIC White_Space */ | 
|  | for(i=0; | 
|  | (c=name[i++])==0x60 || c==0x6d || | 
|  | c==0x40 || c==0x05 || c==0x15 || c==0x25 || c==0x0b || c==0x0c || c==0x0d; | 
|  | ) {} | 
|  |  | 
|  | if(c!=0) { | 
|  | return (i<<8)|(uint8_t)uprv_ebcdictolower((char)c); | 
|  | } else { | 
|  | return i<<8; | 
|  | } | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Unicode property names and property value names are compared "loosely". | 
|  | * | 
|  | * UCD.html 4.0.1 says: | 
|  | *   For all property names, property value names, and for property values for | 
|  | *   Enumerated, Binary, or Catalog properties, use the following | 
|  | *   loose matching rule: | 
|  | * | 
|  | *   LM3. Ignore case, whitespace, underscore ('_'), and hyphens. | 
|  | * | 
|  | * This function does just that, for (char *) name strings. | 
|  | * It is almost identical to ucnv_compareNames() but also ignores | 
|  | * C0 White_Space characters (U+0009..U+000d, and U+0085 on EBCDIC). | 
|  | * | 
|  | * @internal | 
|  | */ | 
|  |  | 
|  | U_CAPI int32_t U_EXPORT2 | 
|  | uprv_compareASCIIPropertyNames(const char *name1, const char *name2) { | 
|  | int32_t rc, r1, r2; | 
|  |  | 
|  | for(;;) { | 
|  | r1=getASCIIPropertyNameChar(name1); | 
|  | r2=getASCIIPropertyNameChar(name2); | 
|  |  | 
|  | /* If we reach the ends of both strings then they match */ | 
|  | if(((r1|r2)&0xff)==0) { | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | /* Compare the lowercased characters */ | 
|  | if(r1!=r2) { | 
|  | rc=(r1&0xff)-(r2&0xff); | 
|  | if(rc!=0) { | 
|  | return rc; | 
|  | } | 
|  | } | 
|  |  | 
|  | name1+=r1>>8; | 
|  | name2+=r2>>8; | 
|  | } | 
|  | } | 
|  |  | 
|  | U_CAPI int32_t U_EXPORT2 | 
|  | uprv_compareEBCDICPropertyNames(const char *name1, const char *name2) { | 
|  | int32_t rc, r1, r2; | 
|  |  | 
|  | for(;;) { | 
|  | r1=getEBCDICPropertyNameChar(name1); | 
|  | r2=getEBCDICPropertyNameChar(name2); | 
|  |  | 
|  | /* If we reach the ends of both strings then they match */ | 
|  | if(((r1|r2)&0xff)==0) { | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | /* Compare the lowercased characters */ | 
|  | if(r1!=r2) { | 
|  | rc=(r1&0xff)-(r2&0xff); | 
|  | if(rc!=0) { | 
|  | return rc; | 
|  | } | 
|  | } | 
|  |  | 
|  | name1+=r1>>8; | 
|  | name2+=r2>>8; | 
|  | } | 
|  | } | 
|  |  | 
|  | U_CDECL_END | 
|  |  | 
|  | U_NAMESPACE_BEGIN | 
|  |  | 
|  | int32_t PropNameData::findProperty(int32_t property) { | 
|  | int32_t i=1;  // valueMaps index, initially after numRanges | 
|  | for(int32_t numRanges=valueMaps[0]; numRanges>0; --numRanges) { | 
|  | // Read and skip the start and limit of this range. | 
|  | int32_t start=valueMaps[i]; | 
|  | int32_t limit=valueMaps[i+1]; | 
|  | i+=2; | 
|  | if(property<start) { | 
|  | break; | 
|  | } | 
|  | if(property<limit) { | 
|  | return i+(property-start)*2; | 
|  | } | 
|  | i+=(limit-start)*2;  // Skip all entries for this range. | 
|  | } | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | int32_t PropNameData::findPropertyValueNameGroup(int32_t valueMapIndex, int32_t value) { | 
|  | if(valueMapIndex==0) { | 
|  | return 0;  // The property does not have named values. | 
|  | } | 
|  | ++valueMapIndex;  // Skip the BytesTrie offset. | 
|  | int32_t numRanges=valueMaps[valueMapIndex++]; | 
|  | if(numRanges<0x10) { | 
|  | // Ranges of values. | 
|  | for(; numRanges>0; --numRanges) { | 
|  | // Read and skip the start and limit of this range. | 
|  | int32_t start=valueMaps[valueMapIndex]; | 
|  | int32_t limit=valueMaps[valueMapIndex+1]; | 
|  | valueMapIndex+=2; | 
|  | if(value<start) { | 
|  | break; | 
|  | } | 
|  | if(value<limit) { | 
|  | return valueMaps[valueMapIndex+value-start]; | 
|  | } | 
|  | valueMapIndex+=limit-start;  // Skip all entries for this range. | 
|  | } | 
|  | } else { | 
|  | // List of values. | 
|  | int32_t valuesStart=valueMapIndex; | 
|  | int32_t nameGroupOffsetsStart=valueMapIndex+numRanges-0x10; | 
|  | do { | 
|  | int32_t v=valueMaps[valueMapIndex]; | 
|  | if(value<v) { | 
|  | break; | 
|  | } | 
|  | if(value==v) { | 
|  | return valueMaps[nameGroupOffsetsStart+valueMapIndex-valuesStart]; | 
|  | } | 
|  | } while(++valueMapIndex<nameGroupOffsetsStart); | 
|  | } | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | const char *PropNameData::getName(const char *nameGroup, int32_t nameIndex) { | 
|  | int32_t numNames=*nameGroup++; | 
|  | if(nameIndex<0 || numNames<=nameIndex) { | 
|  | return NULL; | 
|  | } | 
|  | // Skip nameIndex names. | 
|  | for(; nameIndex>0; --nameIndex) { | 
|  | nameGroup=uprv_strchr(nameGroup, 0)+1; | 
|  | } | 
|  | if(*nameGroup==0) { | 
|  | return NULL;  // no name (Property[Value]Aliases.txt has "n/a") | 
|  | } | 
|  | return nameGroup; | 
|  | } | 
|  |  | 
|  | UBool PropNameData::containsName(BytesTrie &trie, const char *name) { | 
|  | if(name==NULL) { | 
|  | return FALSE; | 
|  | } | 
|  | UStringTrieResult result=USTRINGTRIE_NO_VALUE; | 
|  | char c; | 
|  | while((c=*name++)!=0) { | 
|  | c=uprv_invCharToLowercaseAscii(c); | 
|  | // Ignore delimiters '-', '_', and ASCII White_Space. | 
|  | if(c==0x2d || c==0x5f || c==0x20 || (0x09<=c && c<=0x0d)) { | 
|  | continue; | 
|  | } | 
|  | if(!USTRINGTRIE_HAS_NEXT(result)) { | 
|  | return FALSE; | 
|  | } | 
|  | result=trie.next((uint8_t)c); | 
|  | } | 
|  | return USTRINGTRIE_HAS_VALUE(result); | 
|  | } | 
|  |  | 
|  | const char *PropNameData::getPropertyName(int32_t property, int32_t nameChoice) { | 
|  | int32_t valueMapIndex=findProperty(property); | 
|  | if(valueMapIndex==0) { | 
|  | return NULL;  // Not a known property. | 
|  | } | 
|  | return getName(nameGroups+valueMaps[valueMapIndex], nameChoice); | 
|  | } | 
|  |  | 
|  | const char *PropNameData::getPropertyValueName(int32_t property, int32_t value, int32_t nameChoice) { | 
|  | int32_t valueMapIndex=findProperty(property); | 
|  | if(valueMapIndex==0) { | 
|  | return NULL;  // Not a known property. | 
|  | } | 
|  | int32_t nameGroupOffset=findPropertyValueNameGroup(valueMaps[valueMapIndex+1], value); | 
|  | if(nameGroupOffset==0) { | 
|  | return NULL; | 
|  | } | 
|  | return getName(nameGroups+nameGroupOffset, nameChoice); | 
|  | } | 
|  |  | 
|  | int32_t PropNameData::getPropertyOrValueEnum(int32_t bytesTrieOffset, const char *alias) { | 
|  | BytesTrie trie(bytesTries+bytesTrieOffset); | 
|  | if(containsName(trie, alias)) { | 
|  | return trie.getValue(); | 
|  | } else { | 
|  | return UCHAR_INVALID_CODE; | 
|  | } | 
|  | } | 
|  |  | 
|  | int32_t PropNameData::getPropertyEnum(const char *alias) { | 
|  | return getPropertyOrValueEnum(0, alias); | 
|  | } | 
|  |  | 
|  | int32_t PropNameData::getPropertyValueEnum(int32_t property, const char *alias) { | 
|  | int32_t valueMapIndex=findProperty(property); | 
|  | if(valueMapIndex==0) { | 
|  | return UCHAR_INVALID_CODE;  // Not a known property. | 
|  | } | 
|  | valueMapIndex=valueMaps[valueMapIndex+1]; | 
|  | if(valueMapIndex==0) { | 
|  | return UCHAR_INVALID_CODE;  // The property does not have named values. | 
|  | } | 
|  | // valueMapIndex is the start of the property's valueMap, | 
|  | // where the first word is the BytesTrie offset. | 
|  | return getPropertyOrValueEnum(valueMaps[valueMapIndex], alias); | 
|  | } | 
|  | U_NAMESPACE_END | 
|  |  | 
|  | //---------------------------------------------------------------------- | 
|  | // Public API implementation | 
|  |  | 
|  | U_CAPI const char* U_EXPORT2 | 
|  | u_getPropertyName(UProperty property, | 
|  | UPropertyNameChoice nameChoice) { | 
|  | U_NAMESPACE_USE | 
|  | return PropNameData::getPropertyName(property, nameChoice); | 
|  | } | 
|  |  | 
|  | U_CAPI UProperty U_EXPORT2 | 
|  | u_getPropertyEnum(const char* alias) { | 
|  | U_NAMESPACE_USE | 
|  | return (UProperty)PropNameData::getPropertyEnum(alias); | 
|  | } | 
|  |  | 
|  | U_CAPI const char* U_EXPORT2 | 
|  | u_getPropertyValueName(UProperty property, | 
|  | int32_t value, | 
|  | UPropertyNameChoice nameChoice) { | 
|  | U_NAMESPACE_USE | 
|  | return PropNameData::getPropertyValueName(property, value, nameChoice); | 
|  | } | 
|  |  | 
|  | U_CAPI int32_t U_EXPORT2 | 
|  | u_getPropertyValueEnum(UProperty property, | 
|  | const char* alias) { | 
|  | U_NAMESPACE_USE | 
|  | return PropNameData::getPropertyValueEnum(property, alias); | 
|  | } | 
|  |  | 
|  | U_CAPI const char*  U_EXPORT2 | 
|  | uscript_getName(UScriptCode scriptCode){ | 
|  | return u_getPropertyValueName(UCHAR_SCRIPT, scriptCode, | 
|  | U_LONG_PROPERTY_NAME); | 
|  | } | 
|  |  | 
|  | U_CAPI const char*  U_EXPORT2 | 
|  | uscript_getShortName(UScriptCode scriptCode){ | 
|  | return u_getPropertyValueName(UCHAR_SCRIPT, scriptCode, | 
|  | U_SHORT_PROPERTY_NAME); | 
|  | } |