LCOV - code coverage report
Current view: top level - intl/icu/source/i18n - scriptset.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 177 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 26 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : // © 2016 and later: Unicode, Inc. and others.
       2             : // License & terms of use: http://www.unicode.org/copyright.html
       3             : /*
       4             : **********************************************************************
       5             : *   Copyright (C) 2014, International Business Machines
       6             : *   Corporation and others.  All Rights Reserved.
       7             : **********************************************************************
       8             : *
       9             : * scriptset.cpp
      10             : *
      11             : * created on: 2013 Jan 7
      12             : * created by: Andy Heninger
      13             : */
      14             : 
      15             : #include "unicode/utypes.h"
      16             : 
      17             : #include "unicode/uchar.h"
      18             : #include "unicode/unistr.h"
      19             : 
      20             : #include "scriptset.h"
      21             : #include "uassert.h"
      22             : #include "cmemory.h"
      23             : 
      24             : U_NAMESPACE_BEGIN
      25             : 
      26             : //----------------------------------------------------------------------------
      27             : //
      28             : //  ScriptSet implementation
      29             : //
      30             : //----------------------------------------------------------------------------
      31           0 : ScriptSet::ScriptSet() {
      32           0 :     for (uint32_t i=0; i<UPRV_LENGTHOF(bits); i++) {
      33           0 :         bits[i] = 0;
      34             :     }
      35           0 : }
      36             : 
      37           0 : ScriptSet::~ScriptSet() {
      38           0 : }
      39             : 
      40           0 : ScriptSet::ScriptSet(const ScriptSet &other) {
      41           0 :     *this = other;
      42           0 : }
      43             :     
      44             : 
      45           0 : ScriptSet & ScriptSet::operator =(const ScriptSet &other) {
      46           0 :     for (uint32_t i=0; i<UPRV_LENGTHOF(bits); i++) {
      47           0 :         bits[i] = other.bits[i];
      48             :     }
      49           0 :     return *this;
      50             : }
      51             : 
      52             : 
      53           0 : UBool ScriptSet::operator == (const ScriptSet &other) const {
      54           0 :     for (uint32_t i=0; i<UPRV_LENGTHOF(bits); i++) {
      55           0 :         if (bits[i] != other.bits[i]) {
      56           0 :             return FALSE;
      57             :         }
      58             :     }
      59           0 :     return TRUE;
      60             : }
      61             : 
      62           0 : UBool ScriptSet::test(UScriptCode script, UErrorCode &status) const {
      63           0 :     if (U_FAILURE(status)) {
      64           0 :         return FALSE;
      65             :     }
      66           0 :     if (script < 0 || script >= (int32_t)sizeof(bits) * 8) {
      67           0 :         status = U_ILLEGAL_ARGUMENT_ERROR;
      68           0 :         return FALSE;
      69             :     }
      70           0 :     uint32_t index = script / 32;
      71           0 :     uint32_t bit   = 1 << (script & 31);
      72           0 :     return ((bits[index] & bit) != 0);
      73             : }
      74             : 
      75             : 
      76           0 : ScriptSet &ScriptSet::set(UScriptCode script, UErrorCode &status) {
      77           0 :     if (U_FAILURE(status)) {
      78           0 :         return *this;
      79             :     }
      80           0 :     if (script < 0 || script >= (int32_t)sizeof(bits) * 8) {
      81           0 :         status = U_ILLEGAL_ARGUMENT_ERROR;
      82           0 :         return *this;
      83             :     }
      84           0 :     uint32_t index = script / 32;
      85           0 :     uint32_t bit   = 1 << (script & 31);
      86           0 :     bits[index] |= bit;
      87           0 :     return *this;
      88             : }
      89             : 
      90           0 : ScriptSet &ScriptSet::reset(UScriptCode script, UErrorCode &status) {
      91           0 :     if (U_FAILURE(status)) {
      92           0 :         return *this;
      93             :     }
      94           0 :     if (script < 0 || script >= (int32_t)sizeof(bits) * 8) {
      95           0 :         status = U_ILLEGAL_ARGUMENT_ERROR;
      96           0 :         return *this;
      97             :     }
      98           0 :     uint32_t index = script / 32;
      99           0 :     uint32_t bit   = 1 << (script & 31);
     100           0 :     bits[index] &= ~bit;
     101           0 :     return *this;
     102             : }
     103             : 
     104             : 
     105             : 
     106           0 : ScriptSet &ScriptSet::Union(const ScriptSet &other) {
     107           0 :     for (uint32_t i=0; i<UPRV_LENGTHOF(bits); i++) {
     108           0 :         bits[i] |= other.bits[i];
     109             :     }
     110           0 :     return *this;
     111             : }
     112             : 
     113           0 : ScriptSet &ScriptSet::intersect(const ScriptSet &other) {
     114           0 :     for (uint32_t i=0; i<UPRV_LENGTHOF(bits); i++) {
     115           0 :         bits[i] &= other.bits[i];
     116             :     }
     117           0 :     return *this;
     118             : }
     119             : 
     120           0 : ScriptSet &ScriptSet::intersect(UScriptCode script, UErrorCode &status) {
     121           0 :     ScriptSet t;
     122           0 :     t.set(script, status);
     123           0 :     if (U_SUCCESS(status)) {
     124           0 :         this->intersect(t);
     125             :     }
     126           0 :     return *this;
     127             : }
     128             :     
     129           0 : UBool ScriptSet::intersects(const ScriptSet &other) const {
     130           0 :     for (uint32_t i=0; i<UPRV_LENGTHOF(bits); i++) {
     131           0 :         if ((bits[i] & other.bits[i]) != 0) {
     132           0 :             return true;
     133             :         }
     134             :     }
     135           0 :     return false;
     136             : }
     137             : 
     138           0 : UBool ScriptSet::contains(const ScriptSet &other) const {
     139           0 :     ScriptSet t(*this);
     140           0 :     t.intersect(other);
     141           0 :     return (t == other);
     142             : }
     143             : 
     144             : 
     145           0 : ScriptSet &ScriptSet::setAll() {
     146           0 :     for (uint32_t i=0; i<UPRV_LENGTHOF(bits); i++) {
     147           0 :         bits[i] = 0xffffffffu;
     148             :     }
     149           0 :     return *this;
     150             : }
     151             : 
     152             : 
     153           0 : ScriptSet &ScriptSet::resetAll() {
     154           0 :     for (uint32_t i=0; i<UPRV_LENGTHOF(bits); i++) {
     155           0 :         bits[i] = 0;
     156             :     }
     157           0 :     return *this;
     158             : }
     159             : 
     160           0 : int32_t ScriptSet::countMembers() const {
     161             :     // This bit counter is good for sparse numbers of '1's, which is
     162             :     //  very much the case that we will usually have.
     163           0 :     int32_t count = 0;
     164           0 :     for (uint32_t i=0; i<UPRV_LENGTHOF(bits); i++) {
     165           0 :         uint32_t x = bits[i];
     166           0 :         while (x > 0) {
     167           0 :             count++;
     168           0 :             x &= (x - 1);    // and off the least significant one bit.
     169             :         }
     170             :     }
     171           0 :     return count;
     172             : }
     173             : 
     174           0 : int32_t ScriptSet::hashCode() const {
     175           0 :     int32_t hash = 0;
     176           0 :     for (int32_t i=0; i<UPRV_LENGTHOF(bits); i++) {
     177           0 :         hash ^= bits[i];
     178             :     }
     179           0 :     return hash;
     180             : }
     181             : 
     182           0 : int32_t ScriptSet::nextSetBit(int32_t fromIndex) const {
     183             :     // TODO: Wants a better implementation.
     184           0 :     if (fromIndex < 0) {
     185           0 :         return -1;
     186             :     }
     187           0 :     UErrorCode status = U_ZERO_ERROR;
     188           0 :     for (int32_t scriptIndex = fromIndex; scriptIndex < (int32_t)sizeof(bits)*8; scriptIndex++) {
     189           0 :         if (test((UScriptCode)scriptIndex, status)) {
     190           0 :             return scriptIndex;
     191             :         }
     192             :     }
     193           0 :     return -1;
     194             : }
     195             : 
     196           0 : UBool ScriptSet::isEmpty() const {
     197           0 :     for (uint32_t i=0; i<UPRV_LENGTHOF(bits); i++) {
     198           0 :         if (bits[i] != 0) {
     199           0 :             return FALSE;
     200             :         }
     201             :     }
     202           0 :     return TRUE;
     203             : }
     204             : 
     205           0 : UnicodeString &ScriptSet::displayScripts(UnicodeString &dest) const {
     206           0 :     UBool firstTime = TRUE;
     207           0 :     for (int32_t i = nextSetBit(0); i >= 0; i = nextSetBit(i + 1)) {
     208           0 :         if (!firstTime) {
     209           0 :             dest.append((UChar)0x20);
     210             :         }
     211           0 :         firstTime = FALSE;
     212           0 :         const char *scriptName = uscript_getShortName((UScriptCode(i)));
     213           0 :         dest.append(UnicodeString(scriptName, -1, US_INV));
     214             :     }
     215           0 :     return dest;
     216             : }
     217             : 
     218           0 : ScriptSet &ScriptSet::parseScripts(const UnicodeString &scriptString, UErrorCode &status) {
     219           0 :     resetAll();
     220           0 :     if (U_FAILURE(status)) {
     221           0 :         return *this;
     222             :     }
     223           0 :     UnicodeString oneScriptName;
     224           0 :     for (int32_t i=0; i<scriptString.length();) {
     225           0 :         UChar32 c = scriptString.char32At(i);
     226           0 :         i = scriptString.moveIndex32(i, 1);
     227           0 :         if (!u_isUWhiteSpace(c)) {
     228           0 :             oneScriptName.append(c);
     229           0 :             if (i < scriptString.length()) {
     230           0 :                 continue;
     231             :             }
     232             :         }
     233           0 :         if (oneScriptName.length() > 0) {
     234             :             char buf[40];
     235           0 :             oneScriptName.extract(0, oneScriptName.length(), buf, sizeof(buf)-1, US_INV);
     236           0 :             buf[sizeof(buf)-1] = 0;
     237           0 :             int32_t sc = u_getPropertyValueEnum(UCHAR_SCRIPT, buf);
     238           0 :             if (sc == UCHAR_INVALID_CODE) {
     239           0 :                 status = U_ILLEGAL_ARGUMENT_ERROR;
     240             :             } else {
     241           0 :                 this->set((UScriptCode)sc, status);
     242             :             }
     243           0 :             if (U_FAILURE(status)) {
     244           0 :                 return *this;
     245             :             }
     246           0 :             oneScriptName.remove();
     247             :         }
     248             :     }
     249           0 :     return *this;
     250             : }
     251             : 
     252           0 : void ScriptSet::setScriptExtensions(UChar32 codePoint, UErrorCode& status) {
     253           0 :     if (U_FAILURE(status)) { return; }
     254             :     static const int32_t FIRST_GUESS_SCRIPT_CAPACITY = 5;
     255           0 :     MaybeStackArray<UScriptCode,FIRST_GUESS_SCRIPT_CAPACITY> scripts;
     256           0 :     UErrorCode internalStatus = U_ZERO_ERROR;
     257           0 :     int32_t script_count = -1;
     258             : 
     259             :     while (TRUE) {
     260           0 :         script_count = uscript_getScriptExtensions(
     261           0 :             codePoint, scripts.getAlias(), scripts.getCapacity(), &internalStatus);
     262           0 :         if (internalStatus == U_BUFFER_OVERFLOW_ERROR) {
     263             :             // Need to allocate more space
     264           0 :             if (scripts.resize(script_count) == NULL) {
     265           0 :                 status = U_MEMORY_ALLOCATION_ERROR;
     266           0 :                 return;
     267             :             }
     268           0 :             internalStatus = U_ZERO_ERROR;
     269             :         } else {
     270           0 :             break;
     271             :         }
     272             :     }
     273             : 
     274             :     // Check if we failed for some reason other than buffer overflow
     275           0 :     if (U_FAILURE(internalStatus)) {
     276           0 :         status = internalStatus;
     277           0 :         return;
     278             :     }
     279             : 
     280             :     // Load the scripts into the ScriptSet and return
     281           0 :     for (int32_t i = 0; i < script_count; i++) {
     282           0 :         this->set(scripts[i], status);
     283           0 :         if (U_FAILURE(status)) { return; }
     284             :     }
     285             : }
     286             : 
     287             : U_NAMESPACE_END
     288             : 
     289             : U_CAPI UBool U_EXPORT2
     290           0 : uhash_equalsScriptSet(const UElement key1, const UElement key2) {
     291           0 :     icu::ScriptSet *s1 = static_cast<icu::ScriptSet *>(key1.pointer);
     292           0 :     icu::ScriptSet *s2 = static_cast<icu::ScriptSet *>(key2.pointer);
     293           0 :     return (*s1 == *s2);
     294             : }
     295             : 
     296             : U_CAPI int8_t U_EXPORT2
     297           0 : uhash_compareScriptSet(UElement key0, UElement key1) {
     298           0 :     icu::ScriptSet *s0 = static_cast<icu::ScriptSet *>(key0.pointer);
     299           0 :     icu::ScriptSet *s1 = static_cast<icu::ScriptSet *>(key1.pointer);
     300           0 :     int32_t diff = s0->countMembers() - s1->countMembers();
     301           0 :     if (diff != 0) return diff;
     302           0 :     int32_t i0 = s0->nextSetBit(0);
     303           0 :     int32_t i1 = s1->nextSetBit(0);
     304           0 :     while ((diff = i0-i1) == 0 && i0 > 0) {
     305           0 :         i0 = s0->nextSetBit(i0+1);
     306           0 :         i1 = s1->nextSetBit(i1+1);
     307             :     }
     308           0 :     return (int8_t)diff;
     309             : }
     310             : 
     311             : U_CAPI int32_t U_EXPORT2
     312           0 : uhash_hashScriptSet(const UElement key) {
     313           0 :     icu::ScriptSet *s = static_cast<icu::ScriptSet *>(key.pointer);
     314           0 :     return s->hashCode();
     315             : }
     316             : 
     317             : U_CAPI void U_EXPORT2
     318           0 : uhash_deleteScriptSet(void *obj) {
     319           0 :     icu::ScriptSet *s = static_cast<icu::ScriptSet *>(obj);
     320           0 :     delete s;
     321           0 : }

Generated by: LCOV version 1.13