LCOV - code coverage report
Current view: top level - intl/icu/source/i18n - csdetect.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 223 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 22 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) 2005-2016, International Business Machines
       6             :  *   Corporation and others.  All Rights Reserved.
       7             :  **********************************************************************
       8             :  */
       9             : 
      10             : #include "unicode/utypes.h"
      11             : 
      12             : #if !UCONFIG_NO_CONVERSION
      13             : 
      14             : #include "unicode/ucsdet.h"
      15             : 
      16             : #include "csdetect.h"
      17             : #include "csmatch.h"
      18             : #include "uenumimp.h"
      19             : 
      20             : #include "cmemory.h"
      21             : #include "cstring.h"
      22             : #include "umutex.h"
      23             : #include "ucln_in.h"
      24             : #include "uarrsort.h"
      25             : #include "inputext.h"
      26             : #include "csrsbcs.h"
      27             : #include "csrmbcs.h"
      28             : #include "csrutf8.h"
      29             : #include "csrucode.h"
      30             : #include "csr2022.h"
      31             : 
      32             : #define NEW_ARRAY(type,count) (type *) uprv_malloc((count) * sizeof(type))
      33             : #define DELETE_ARRAY(array) uprv_free((void *) (array))
      34             : 
      35             : U_NAMESPACE_BEGIN
      36             : 
      37             : struct CSRecognizerInfo : public UMemory {
      38           0 :     CSRecognizerInfo(CharsetRecognizer *recognizer, UBool isDefaultEnabled)
      39           0 :         : recognizer(recognizer), isDefaultEnabled(isDefaultEnabled) {};
      40             : 
      41           0 :     ~CSRecognizerInfo() {delete recognizer;};
      42             : 
      43             :     CharsetRecognizer *recognizer;
      44             :     UBool isDefaultEnabled;
      45             : };
      46             : 
      47             : U_NAMESPACE_END
      48             : 
      49             : static icu::CSRecognizerInfo **fCSRecognizers = NULL;
      50             : static icu::UInitOnce gCSRecognizersInitOnce;
      51             : static int32_t fCSRecognizers_size = 0;
      52             : 
      53             : U_CDECL_BEGIN
      54           0 : static UBool U_CALLCONV csdet_cleanup(void)
      55             : {
      56             :     U_NAMESPACE_USE
      57           0 :     if (fCSRecognizers != NULL) {
      58           0 :         for(int32_t r = 0; r < fCSRecognizers_size; r += 1) {
      59           0 :             delete fCSRecognizers[r];
      60           0 :             fCSRecognizers[r] = NULL;
      61             :         }
      62             : 
      63           0 :         DELETE_ARRAY(fCSRecognizers);
      64           0 :         fCSRecognizers = NULL;
      65           0 :         fCSRecognizers_size = 0;
      66             :     }
      67           0 :     gCSRecognizersInitOnce.reset();
      68             : 
      69           0 :     return TRUE;
      70             : }
      71             : 
      72             : static int32_t U_CALLCONV
      73           0 : charsetMatchComparator(const void * /*context*/, const void *left, const void *right)
      74             : {
      75             :     U_NAMESPACE_USE
      76             : 
      77           0 :     const CharsetMatch **csm_l = (const CharsetMatch **) left;
      78           0 :     const CharsetMatch **csm_r = (const CharsetMatch **) right;
      79             : 
      80             :     // NOTE: compare is backwards to sort from highest to lowest.
      81           0 :     return (*csm_r)->getConfidence() - (*csm_l)->getConfidence();
      82             : }
      83             : 
      84           0 : static void U_CALLCONV initRecognizers(UErrorCode &status) {
      85             :     U_NAMESPACE_USE
      86           0 :     ucln_i18n_registerCleanup(UCLN_I18N_CSDET, csdet_cleanup);
      87             :     CSRecognizerInfo *tempArray[] = {
      88           0 :         new CSRecognizerInfo(new CharsetRecog_UTF8(), TRUE),
      89             : 
      90           0 :         new CSRecognizerInfo(new CharsetRecog_UTF_16_BE(), TRUE),
      91           0 :         new CSRecognizerInfo(new CharsetRecog_UTF_16_LE(), TRUE),
      92           0 :         new CSRecognizerInfo(new CharsetRecog_UTF_32_BE(), TRUE),
      93           0 :         new CSRecognizerInfo(new CharsetRecog_UTF_32_LE(), TRUE),
      94             : 
      95           0 :         new CSRecognizerInfo(new CharsetRecog_8859_1(), TRUE),
      96           0 :         new CSRecognizerInfo(new CharsetRecog_8859_2(), TRUE),
      97           0 :         new CSRecognizerInfo(new CharsetRecog_8859_5_ru(), TRUE),
      98           0 :         new CSRecognizerInfo(new CharsetRecog_8859_6_ar(), TRUE),
      99           0 :         new CSRecognizerInfo(new CharsetRecog_8859_7_el(), TRUE),
     100           0 :         new CSRecognizerInfo(new CharsetRecog_8859_8_I_he(), TRUE),
     101           0 :         new CSRecognizerInfo(new CharsetRecog_8859_8_he(), TRUE),
     102           0 :         new CSRecognizerInfo(new CharsetRecog_windows_1251(), TRUE),
     103           0 :         new CSRecognizerInfo(new CharsetRecog_windows_1256(), TRUE),
     104           0 :         new CSRecognizerInfo(new CharsetRecog_KOI8_R(), TRUE),
     105           0 :         new CSRecognizerInfo(new CharsetRecog_8859_9_tr(), TRUE),
     106           0 :         new CSRecognizerInfo(new CharsetRecog_sjis(), TRUE),
     107           0 :         new CSRecognizerInfo(new CharsetRecog_gb_18030(), TRUE),
     108           0 :         new CSRecognizerInfo(new CharsetRecog_euc_jp(), TRUE),
     109           0 :         new CSRecognizerInfo(new CharsetRecog_euc_kr(), TRUE),
     110           0 :         new CSRecognizerInfo(new CharsetRecog_big5(), TRUE),
     111             : 
     112           0 :         new CSRecognizerInfo(new CharsetRecog_2022JP(), TRUE),
     113             : #if !UCONFIG_ONLY_HTML_CONVERSION
     114           0 :         new CSRecognizerInfo(new CharsetRecog_2022KR(), TRUE),
     115           0 :         new CSRecognizerInfo(new CharsetRecog_2022CN(), TRUE),
     116             : 
     117           0 :         new CSRecognizerInfo(new CharsetRecog_IBM424_he_rtl(), FALSE),
     118           0 :         new CSRecognizerInfo(new CharsetRecog_IBM424_he_ltr(), FALSE),
     119           0 :         new CSRecognizerInfo(new CharsetRecog_IBM420_ar_rtl(), FALSE),
     120           0 :         new CSRecognizerInfo(new CharsetRecog_IBM420_ar_ltr(), FALSE)
     121             : #endif
     122           0 :     };
     123           0 :     int32_t rCount = UPRV_LENGTHOF(tempArray);
     124             : 
     125           0 :     fCSRecognizers = NEW_ARRAY(CSRecognizerInfo *, rCount);
     126             : 
     127           0 :     if (fCSRecognizers == NULL) {
     128           0 :         status = U_MEMORY_ALLOCATION_ERROR;
     129             :     } 
     130             :     else {
     131           0 :         fCSRecognizers_size = rCount;
     132           0 :         for (int32_t r = 0; r < rCount; r += 1) {
     133           0 :             fCSRecognizers[r] = tempArray[r];
     134           0 :             if (fCSRecognizers[r] == NULL) {
     135           0 :                 status = U_MEMORY_ALLOCATION_ERROR;
     136             :             }
     137             :         }
     138             :     }
     139           0 : }
     140             : 
     141             : U_CDECL_END
     142             : 
     143             : U_NAMESPACE_BEGIN
     144             : 
     145           0 : void CharsetDetector::setRecognizers(UErrorCode &status)
     146             : {
     147           0 :     umtx_initOnce(gCSRecognizersInitOnce, &initRecognizers, status);
     148           0 : }
     149             : 
     150           0 : CharsetDetector::CharsetDetector(UErrorCode &status)
     151           0 :   : textIn(new InputText(status)), resultArray(NULL),
     152             :     resultCount(0), fStripTags(FALSE), fFreshTextSet(FALSE),
     153           0 :     fEnabledRecognizers(NULL)
     154             : {
     155           0 :     if (U_FAILURE(status)) {
     156           0 :         return;
     157             :     }
     158             : 
     159           0 :     setRecognizers(status);
     160             : 
     161           0 :     if (U_FAILURE(status)) {
     162           0 :         return;
     163             :     }
     164             : 
     165           0 :     resultArray = (CharsetMatch **)uprv_malloc(sizeof(CharsetMatch *)*fCSRecognizers_size);
     166             : 
     167           0 :     if (resultArray == NULL) {
     168           0 :         status = U_MEMORY_ALLOCATION_ERROR;
     169           0 :         return;
     170             :     }
     171             : 
     172           0 :     for(int32_t i = 0; i < fCSRecognizers_size; i += 1) {
     173           0 :         resultArray[i] = new CharsetMatch();
     174             : 
     175           0 :         if (resultArray[i] == NULL) {
     176           0 :             status = U_MEMORY_ALLOCATION_ERROR;
     177           0 :             break;
     178             :         }
     179             :     }
     180             : }
     181             : 
     182           0 : CharsetDetector::~CharsetDetector()
     183             : {
     184           0 :     delete textIn;
     185             : 
     186           0 :     for(int32_t i = 0; i < fCSRecognizers_size; i += 1) {
     187           0 :         delete resultArray[i];
     188             :     }
     189             : 
     190           0 :     uprv_free(resultArray);
     191             : 
     192           0 :     if (fEnabledRecognizers) {
     193           0 :         uprv_free(fEnabledRecognizers);
     194             :     }
     195           0 : }
     196             : 
     197           0 : void CharsetDetector::setText(const char *in, int32_t len)
     198             : {
     199           0 :     textIn->setText(in, len);
     200           0 :     fFreshTextSet = TRUE;
     201           0 : }
     202             : 
     203           0 : UBool CharsetDetector::setStripTagsFlag(UBool flag)
     204             : {
     205           0 :     UBool temp = fStripTags;
     206           0 :     fStripTags = flag;
     207           0 :     fFreshTextSet = TRUE;
     208           0 :     return temp;
     209             : }
     210             : 
     211           0 : UBool CharsetDetector::getStripTagsFlag() const
     212             : {
     213           0 :     return fStripTags;
     214             : }
     215             : 
     216           0 : void CharsetDetector::setDeclaredEncoding(const char *encoding, int32_t len) const
     217             : {
     218           0 :     textIn->setDeclaredEncoding(encoding,len);
     219           0 : }
     220             : 
     221           0 : int32_t CharsetDetector::getDetectableCount()
     222             : {
     223           0 :     UErrorCode status = U_ZERO_ERROR;
     224             : 
     225           0 :     setRecognizers(status);
     226             : 
     227           0 :     return fCSRecognizers_size; 
     228             : }
     229             : 
     230           0 : const CharsetMatch *CharsetDetector::detect(UErrorCode &status)
     231             : {
     232           0 :     int32_t maxMatchesFound = 0;
     233             : 
     234           0 :     detectAll(maxMatchesFound, status);
     235             : 
     236           0 :     if(maxMatchesFound > 0) {
     237           0 :         return resultArray[0];
     238             :     } else {
     239           0 :         return NULL;
     240             :     }
     241             : }
     242             : 
     243           0 : const CharsetMatch * const *CharsetDetector::detectAll(int32_t &maxMatchesFound, UErrorCode &status)
     244             : {
     245           0 :     if(!textIn->isSet()) {
     246           0 :         status = U_MISSING_RESOURCE_ERROR;// TODO:  Need to set proper status code for input text not set
     247             : 
     248           0 :         return NULL;
     249           0 :     } else if (fFreshTextSet) {
     250             :         CharsetRecognizer *csr;
     251             :         int32_t            i;
     252             : 
     253           0 :         textIn->MungeInput(fStripTags);
     254             : 
     255             :         // Iterate over all possible charsets, remember all that
     256             :         // give a match quality > 0.
     257           0 :         resultCount = 0;
     258           0 :         for (i = 0; i < fCSRecognizers_size; i += 1) {
     259           0 :             csr = fCSRecognizers[i]->recognizer;
     260           0 :             if (csr->match(textIn, resultArray[resultCount])) {
     261           0 :                 resultCount++;
     262             :             }
     263             :         }
     264             : 
     265           0 :         if (resultCount > 1) {
     266           0 :             uprv_sortArray(resultArray, resultCount, sizeof resultArray[0], charsetMatchComparator, NULL, TRUE, &status);
     267             :         }
     268           0 :         fFreshTextSet = FALSE;
     269             :     }
     270             : 
     271           0 :     maxMatchesFound = resultCount;
     272             : 
     273           0 :     return resultArray;
     274             : }
     275             : 
     276           0 : void CharsetDetector::setDetectableCharset(const char *encoding, UBool enabled, UErrorCode &status)
     277             : {
     278           0 :     if (U_FAILURE(status)) {
     279           0 :         return;
     280             :     }
     281             : 
     282           0 :     int32_t modIdx = -1;
     283           0 :     UBool isDefaultVal = FALSE;
     284           0 :     for (int32_t i = 0; i < fCSRecognizers_size; i++) {
     285           0 :         CSRecognizerInfo *csrinfo = fCSRecognizers[i];
     286           0 :         if (uprv_strcmp(csrinfo->recognizer->getName(), encoding) == 0) {
     287           0 :             modIdx = i;
     288           0 :             isDefaultVal = (csrinfo->isDefaultEnabled == enabled);
     289           0 :             break;
     290             :         }
     291             :     }
     292           0 :     if (modIdx < 0) {
     293             :         // No matching encoding found
     294           0 :         status = U_ILLEGAL_ARGUMENT_ERROR;
     295           0 :         return;
     296             :     }
     297             : 
     298           0 :     if (fEnabledRecognizers == NULL && !isDefaultVal) {
     299             :         // Create an array storing the non default setting
     300           0 :         fEnabledRecognizers = NEW_ARRAY(UBool, fCSRecognizers_size);
     301           0 :         if (fEnabledRecognizers == NULL) {
     302           0 :             status = U_MEMORY_ALLOCATION_ERROR;
     303           0 :             return;
     304             :         }
     305             :         // Initialize the array with default info
     306           0 :         for (int32_t i = 0; i < fCSRecognizers_size; i++) {
     307           0 :             fEnabledRecognizers[i] = fCSRecognizers[i]->isDefaultEnabled;
     308             :         }
     309             :     }
     310             : 
     311           0 :     if (fEnabledRecognizers != NULL) {
     312           0 :         fEnabledRecognizers[modIdx] = enabled;
     313             :     }
     314             : }
     315             : 
     316             : /*const char *CharsetDetector::getCharsetName(int32_t index, UErrorCode &status) const
     317             : {
     318             :     if( index > fCSRecognizers_size-1 || index < 0) {
     319             :         status = U_INDEX_OUTOFBOUNDS_ERROR;
     320             : 
     321             :         return 0;
     322             :     } else {
     323             :         return fCSRecognizers[index]->getName();
     324             :     }
     325             : }*/
     326             : 
     327             : U_NAMESPACE_END
     328             : 
     329             : U_CDECL_BEGIN
     330             : typedef struct {
     331             :     int32_t currIndex;
     332             :     UBool all;
     333             :     UBool *enabledRecognizers;
     334             : } Context;
     335             : 
     336             : 
     337             : 
     338             : static void U_CALLCONV
     339           0 : enumClose(UEnumeration *en) {
     340           0 :     if(en->context != NULL) {
     341           0 :         DELETE_ARRAY(en->context);
     342             :     }
     343             : 
     344           0 :     DELETE_ARRAY(en);
     345           0 : }
     346             : 
     347             : static int32_t U_CALLCONV
     348           0 : enumCount(UEnumeration *en, UErrorCode *) {
     349           0 :     if (((Context *)en->context)->all) {
     350             :         // ucsdet_getAllDetectableCharsets, all charset detector names
     351           0 :         return fCSRecognizers_size;
     352             :     }
     353             : 
     354             :     // Otherwise, ucsdet_getDetectableCharsets - only enabled ones
     355           0 :     int32_t count = 0;
     356           0 :     UBool *enabledArray = ((Context *)en->context)->enabledRecognizers;
     357           0 :     if (enabledArray != NULL) {
     358             :         // custom set
     359           0 :         for (int32_t i = 0; i < fCSRecognizers_size; i++) {
     360           0 :             if (enabledArray[i]) {
     361           0 :                 count++;
     362             :             }
     363             :         }
     364             :     } else {
     365             :         // default set
     366           0 :         for (int32_t i = 0; i < fCSRecognizers_size; i++) {
     367           0 :             if (fCSRecognizers[i]->isDefaultEnabled) {
     368           0 :                 count++;
     369             :             }
     370             :         }
     371             :     }
     372           0 :     return count;
     373             : }
     374             : 
     375             : static const char* U_CALLCONV
     376           0 : enumNext(UEnumeration *en, int32_t *resultLength, UErrorCode * /*status*/) {
     377           0 :     const char *currName = NULL;
     378             : 
     379           0 :     if (((Context *)en->context)->currIndex < fCSRecognizers_size) {
     380           0 :         if (((Context *)en->context)->all) {
     381             :             // ucsdet_getAllDetectableCharsets, all charset detector names
     382           0 :             currName = fCSRecognizers[((Context *)en->context)->currIndex]->recognizer->getName();
     383           0 :             ((Context *)en->context)->currIndex++;
     384             :         } else {
     385             :             // ucsdet_getDetectableCharsets
     386           0 :             UBool *enabledArray = ((Context *)en->context)->enabledRecognizers;
     387           0 :             if (enabledArray != NULL) {
     388             :                 // custome set
     389           0 :                 while (currName == NULL && ((Context *)en->context)->currIndex < fCSRecognizers_size) {
     390           0 :                     if (enabledArray[((Context *)en->context)->currIndex]) {
     391           0 :                         currName = fCSRecognizers[((Context *)en->context)->currIndex]->recognizer->getName();
     392             :                     }
     393           0 :                     ((Context *)en->context)->currIndex++;
     394             :                 }
     395             :             } else {
     396             :                 // default set
     397           0 :                 while (currName == NULL && ((Context *)en->context)->currIndex < fCSRecognizers_size) {
     398           0 :                     if (fCSRecognizers[((Context *)en->context)->currIndex]->isDefaultEnabled) {
     399           0 :                         currName = fCSRecognizers[((Context *)en->context)->currIndex]->recognizer->getName();
     400             :                     }
     401           0 :                     ((Context *)en->context)->currIndex++;
     402             :                 }
     403             :             }
     404             :         }
     405             :     }
     406             : 
     407           0 :     if(resultLength != NULL) {
     408           0 :         *resultLength = currName == NULL ? 0 : (int32_t)uprv_strlen(currName);
     409             :     }
     410             : 
     411           0 :     return currName;
     412             : }
     413             : 
     414             : 
     415             : static void U_CALLCONV
     416           0 : enumReset(UEnumeration *en, UErrorCode *) {
     417           0 :     ((Context *)en->context)->currIndex = 0;
     418           0 : }
     419             : 
     420             : static const UEnumeration gCSDetEnumeration = {
     421             :     NULL,
     422             :     NULL,
     423             :     enumClose,
     424             :     enumCount,
     425             :     uenum_unextDefault,
     426             :     enumNext,
     427             :     enumReset
     428             : };
     429             : 
     430             : U_CDECL_END
     431             : 
     432             : U_NAMESPACE_BEGIN
     433             : 
     434           0 : UEnumeration * CharsetDetector::getAllDetectableCharsets(UErrorCode &status)
     435             : {
     436             : 
     437             :     /* Initialize recognized charsets. */
     438           0 :     setRecognizers(status);
     439             : 
     440           0 :     if(U_FAILURE(status)) {
     441           0 :         return 0;
     442             :     }
     443             : 
     444           0 :     UEnumeration *en = NEW_ARRAY(UEnumeration, 1);
     445           0 :     if (en == NULL) {
     446           0 :         status = U_MEMORY_ALLOCATION_ERROR;
     447           0 :         return 0;
     448             :     }
     449           0 :     memcpy(en, &gCSDetEnumeration, sizeof(UEnumeration));
     450           0 :     en->context = (void*)NEW_ARRAY(Context, 1);
     451           0 :     if (en->context == NULL) {
     452           0 :         status = U_MEMORY_ALLOCATION_ERROR;
     453           0 :         DELETE_ARRAY(en);
     454           0 :         return 0;
     455             :     }
     456           0 :     uprv_memset(en->context, 0, sizeof(Context));
     457           0 :     ((Context*)en->context)->all = TRUE;
     458           0 :     return en;
     459             : }
     460             : 
     461           0 : UEnumeration * CharsetDetector::getDetectableCharsets(UErrorCode &status) const
     462             : {
     463           0 :     if(U_FAILURE(status)) {
     464           0 :         return 0;
     465             :     }
     466             : 
     467           0 :     UEnumeration *en = NEW_ARRAY(UEnumeration, 1);
     468           0 :     if (en == NULL) {
     469           0 :         status = U_MEMORY_ALLOCATION_ERROR;
     470           0 :         return 0;
     471             :     }
     472           0 :     memcpy(en, &gCSDetEnumeration, sizeof(UEnumeration));
     473           0 :     en->context = (void*)NEW_ARRAY(Context, 1);
     474           0 :     if (en->context == NULL) {
     475           0 :         status = U_MEMORY_ALLOCATION_ERROR;
     476           0 :         DELETE_ARRAY(en);
     477           0 :         return 0;
     478             :     }
     479           0 :     uprv_memset(en->context, 0, sizeof(Context));
     480           0 :     ((Context*)en->context)->all = FALSE;
     481           0 :     ((Context*)en->context)->enabledRecognizers = fEnabledRecognizers;
     482           0 :     return en;
     483             : }
     484             : 
     485             : U_NAMESPACE_END
     486             : 
     487             : #endif

Generated by: LCOV version 1.13