LCOV - code coverage report
Current view: top level - intl/icu/source/common - unistr_cnv.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 152 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 8 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             : *
       6             : *   Copyright (C) 1999-2014, International Business Machines
       7             : *   Corporation and others.  All Rights Reserved.
       8             : *
       9             : *******************************************************************************
      10             : *   file name:  unistr_cnv.cpp
      11             : *   encoding:   UTF-8
      12             : *   tab size:   8 (not used)
      13             : *   indentation:2
      14             : *
      15             : *   created on: 2004aug19
      16             : *   created by: Markus W. Scherer
      17             : *
      18             : *   Character conversion functions moved here from unistr.cpp
      19             : */
      20             : 
      21             : #include "unicode/utypes.h"
      22             : 
      23             : #if !UCONFIG_NO_CONVERSION
      24             : 
      25             : #include "unicode/putil.h"
      26             : #include "cstring.h"
      27             : #include "cmemory.h"
      28             : #include "unicode/ustring.h"
      29             : #include "unicode/unistr.h"
      30             : #include "unicode/ucnv.h"
      31             : #include "ucnv_imp.h"
      32             : #include "putilimp.h"
      33             : #include "ustr_cnv.h"
      34             : #include "ustr_imp.h"
      35             : 
      36             : U_NAMESPACE_BEGIN
      37             : 
      38             : //========================================
      39             : // Constructors
      40             : //========================================
      41             : 
      42             : #if !U_CHARSET_IS_UTF8
      43             : 
      44             : UnicodeString::UnicodeString(const char *codepageData) {
      45             :     fUnion.fFields.fLengthAndFlags = kShortString;
      46             :     if(codepageData != 0) {
      47             :         doCodepageCreate(codepageData, (int32_t)uprv_strlen(codepageData), 0);
      48             :     }
      49             : }
      50             : 
      51             : UnicodeString::UnicodeString(const char *codepageData,
      52             :                              int32_t dataLength) {
      53             :     fUnion.fFields.fLengthAndFlags = kShortString;
      54             :     if(codepageData != 0) {
      55             :         doCodepageCreate(codepageData, dataLength, 0);
      56             :     }
      57             : }
      58             : 
      59             : // else see unistr.cpp
      60             : #endif
      61             : 
      62           0 : UnicodeString::UnicodeString(const char *codepageData,
      63           0 :                              const char *codepage) {
      64           0 :     fUnion.fFields.fLengthAndFlags = kShortString;
      65           0 :     if(codepageData != 0) {
      66           0 :         doCodepageCreate(codepageData, (int32_t)uprv_strlen(codepageData), codepage);
      67             :     }
      68           0 : }
      69             : 
      70           0 : UnicodeString::UnicodeString(const char *codepageData,
      71             :                              int32_t dataLength,
      72           0 :                              const char *codepage) {
      73           0 :     fUnion.fFields.fLengthAndFlags = kShortString;
      74           0 :     if(codepageData != 0) {
      75           0 :         doCodepageCreate(codepageData, dataLength, codepage);
      76             :     }
      77           0 : }
      78             : 
      79           0 : UnicodeString::UnicodeString(const char *src, int32_t srcLength,
      80             :                              UConverter *cnv,
      81           0 :                              UErrorCode &errorCode) {
      82           0 :     fUnion.fFields.fLengthAndFlags = kShortString;
      83           0 :     if(U_SUCCESS(errorCode)) {
      84             :         // check arguments
      85           0 :         if(src==NULL) {
      86             :             // treat as an empty string, do nothing more
      87           0 :         } else if(srcLength<-1) {
      88           0 :             errorCode=U_ILLEGAL_ARGUMENT_ERROR;
      89             :         } else {
      90             :             // get input length
      91           0 :             if(srcLength==-1) {
      92           0 :                 srcLength=(int32_t)uprv_strlen(src);
      93             :             }
      94           0 :             if(srcLength>0) {
      95           0 :                 if(cnv!=0) {
      96             :                     // use the provided converter
      97           0 :                     ucnv_resetToUnicode(cnv);
      98           0 :                     doCodepageCreate(src, srcLength, cnv, errorCode);
      99             :                 } else {
     100             :                     // use the default converter
     101           0 :                     cnv=u_getDefaultConverter(&errorCode);
     102           0 :                     doCodepageCreate(src, srcLength, cnv, errorCode);
     103           0 :                     u_releaseDefaultConverter(cnv);
     104             :                 }
     105             :             }
     106             :         }
     107             : 
     108           0 :         if(U_FAILURE(errorCode)) {
     109           0 :             setToBogus();
     110             :         }
     111             :     }
     112           0 : }
     113             : 
     114             : //========================================
     115             : // Codeset conversion
     116             : //========================================
     117             : 
     118             : #if !U_CHARSET_IS_UTF8
     119             : 
     120             : int32_t
     121             : UnicodeString::extract(int32_t start,
     122             :                        int32_t length,
     123             :                        char *target,
     124             :                        uint32_t dstSize) const {
     125             :     return extract(start, length, target, dstSize, 0);
     126             : }
     127             : 
     128             : // else see unistr.cpp
     129             : #endif
     130             : 
     131             : int32_t
     132           0 : UnicodeString::extract(int32_t start,
     133             :                        int32_t length,
     134             :                        char *target,
     135             :                        uint32_t dstSize,
     136             :                        const char *codepage) const
     137             : {
     138             :     // if the arguments are illegal, then do nothing
     139           0 :     if(/*dstSize < 0 || */(dstSize > 0 && target == 0)) {
     140           0 :         return 0;
     141             :     }
     142             : 
     143             :     // pin the indices to legal values
     144           0 :     pinIndices(start, length);
     145             : 
     146             :     // We need to cast dstSize to int32_t for all subsequent code.
     147             :     // I don't know why the API was defined with uint32_t but we are stuck with it.
     148             :     // Also, dstSize==0xffffffff means "unlimited" but if we use target+dstSize
     149             :     // as a limit in some functions, it may wrap around and yield a pointer
     150             :     // that compares less-than target.
     151             :     int32_t capacity;
     152           0 :     if(dstSize < 0x7fffffff) {
     153             :         // Assume that the capacity is real and a limit pointer won't wrap around.
     154           0 :         capacity = (int32_t)dstSize;
     155             :     } else {
     156             :         // Pin the capacity so that a limit pointer does not wrap around.
     157           0 :         char *targetLimit = (char *)U_MAX_PTR(target);
     158             :         // U_MAX_PTR(target) returns a targetLimit that is at most 0x7fffffff
     159             :         // greater than target and does not wrap around the top of the address space.
     160           0 :         capacity = (int32_t)(targetLimit - target);
     161             :     }
     162             : 
     163             :     // create the converter
     164             :     UConverter *converter;
     165           0 :     UErrorCode status = U_ZERO_ERROR;
     166             : 
     167             :     // just write the NUL if the string length is 0
     168           0 :     if(length == 0) {
     169           0 :         return u_terminateChars(target, capacity, 0, &status);
     170             :     }
     171             : 
     172             :     // if the codepage is the default, use our cache
     173             :     // if it is an empty string, then use the "invariant character" conversion
     174           0 :     if (codepage == 0) {
     175           0 :         const char *defaultName = ucnv_getDefaultName();
     176           0 :         if(UCNV_FAST_IS_UTF8(defaultName)) {
     177           0 :             return toUTF8(start, length, target, capacity);
     178             :         }
     179           0 :         converter = u_getDefaultConverter(&status);
     180           0 :     } else if (*codepage == 0) {
     181             :         // use the "invariant characters" conversion
     182             :         int32_t destLength;
     183           0 :         if(length <= capacity) {
     184           0 :             destLength = length;
     185             :         } else {
     186           0 :             destLength = capacity;
     187             :         }
     188           0 :         u_UCharsToChars(getArrayStart() + start, target, destLength);
     189           0 :         return u_terminateChars(target, capacity, length, &status);
     190             :     } else {
     191           0 :         converter = ucnv_open(codepage, &status);
     192             :     }
     193             : 
     194           0 :     length = doExtract(start, length, target, capacity, converter, status);
     195             : 
     196             :     // close the converter
     197           0 :     if (codepage == 0) {
     198           0 :         u_releaseDefaultConverter(converter);
     199             :     } else {
     200           0 :         ucnv_close(converter);
     201             :     }
     202             : 
     203           0 :     return length;
     204             : }
     205             : 
     206             : int32_t
     207           0 : UnicodeString::extract(char *dest, int32_t destCapacity,
     208             :                        UConverter *cnv,
     209             :                        UErrorCode &errorCode) const
     210             : {
     211           0 :     if(U_FAILURE(errorCode)) {
     212           0 :         return 0;
     213             :     }
     214             : 
     215           0 :     if(isBogus() || destCapacity<0 || (destCapacity>0 && dest==0)) {
     216           0 :         errorCode=U_ILLEGAL_ARGUMENT_ERROR;
     217           0 :         return 0;
     218             :     }
     219             : 
     220             :     // nothing to do?
     221           0 :     if(isEmpty()) {
     222           0 :         return u_terminateChars(dest, destCapacity, 0, &errorCode);
     223             :     }
     224             : 
     225             :     // get the converter
     226             :     UBool isDefaultConverter;
     227           0 :     if(cnv==0) {
     228           0 :         isDefaultConverter=TRUE;
     229           0 :         cnv=u_getDefaultConverter(&errorCode);
     230           0 :         if(U_FAILURE(errorCode)) {
     231           0 :             return 0;
     232             :         }
     233             :     } else {
     234           0 :         isDefaultConverter=FALSE;
     235           0 :         ucnv_resetFromUnicode(cnv);
     236             :     }
     237             : 
     238             :     // convert
     239           0 :     int32_t len=doExtract(0, length(), dest, destCapacity, cnv, errorCode);
     240             : 
     241             :     // release the converter
     242           0 :     if(isDefaultConverter) {
     243           0 :         u_releaseDefaultConverter(cnv);
     244             :     }
     245             : 
     246           0 :     return len;
     247             : }
     248             : 
     249             : int32_t
     250           0 : UnicodeString::doExtract(int32_t start, int32_t length,
     251             :                          char *dest, int32_t destCapacity,
     252             :                          UConverter *cnv,
     253             :                          UErrorCode &errorCode) const
     254             : {
     255           0 :     if(U_FAILURE(errorCode)) {
     256           0 :         if(destCapacity!=0) {
     257           0 :             *dest=0;
     258             :         }
     259           0 :         return 0;
     260             :     }
     261             : 
     262           0 :     const UChar *src=getArrayStart()+start, *srcLimit=src+length;
     263           0 :     char *originalDest=dest;
     264             :     const char *destLimit;
     265             : 
     266           0 :     if(destCapacity==0) {
     267           0 :         destLimit=dest=0;
     268           0 :     } else if(destCapacity==-1) {
     269             :         // Pin the limit to U_MAX_PTR if the "magic" destCapacity is used.
     270           0 :         destLimit=(char*)U_MAX_PTR(dest);
     271             :         // for NUL-termination, translate into highest int32_t
     272           0 :         destCapacity=0x7fffffff;
     273             :     } else {
     274           0 :         destLimit=dest+destCapacity;
     275             :     }
     276             : 
     277             :     // perform the conversion
     278           0 :     ucnv_fromUnicode(cnv, &dest, destLimit, &src, srcLimit, 0, TRUE, &errorCode);
     279           0 :     length=(int32_t)(dest-originalDest);
     280             : 
     281             :     // if an overflow occurs, then get the preflighting length
     282           0 :     if(errorCode==U_BUFFER_OVERFLOW_ERROR) {
     283             :         char buffer[1024];
     284             : 
     285           0 :         destLimit=buffer+sizeof(buffer);
     286           0 :         do {
     287           0 :             dest=buffer;
     288           0 :             errorCode=U_ZERO_ERROR;
     289           0 :             ucnv_fromUnicode(cnv, &dest, destLimit, &src, srcLimit, 0, TRUE, &errorCode);
     290           0 :             length+=(int32_t)(dest-buffer);
     291           0 :         } while(errorCode==U_BUFFER_OVERFLOW_ERROR);
     292             :     }
     293             : 
     294           0 :     return u_terminateChars(originalDest, destCapacity, length, &errorCode);
     295             : }
     296             : 
     297             : void
     298           0 : UnicodeString::doCodepageCreate(const char *codepageData,
     299             :                                 int32_t dataLength,
     300             :                                 const char *codepage)
     301             : {
     302             :     // if there's nothing to convert, do nothing
     303           0 :     if(codepageData == 0 || dataLength == 0 || dataLength < -1) {
     304           0 :         return;
     305             :     }
     306           0 :     if(dataLength == -1) {
     307           0 :         dataLength = (int32_t)uprv_strlen(codepageData);
     308             :     }
     309             : 
     310           0 :     UErrorCode status = U_ZERO_ERROR;
     311             : 
     312             :     // create the converter
     313             :     // if the codepage is the default, use our cache
     314             :     // if it is an empty string, then use the "invariant character" conversion
     315             :     UConverter *converter;
     316           0 :     if (codepage == 0) {
     317           0 :         const char *defaultName = ucnv_getDefaultName();
     318           0 :         if(UCNV_FAST_IS_UTF8(defaultName)) {
     319           0 :             setToUTF8(StringPiece(codepageData, dataLength));
     320           0 :             return;
     321             :         }
     322           0 :         converter = u_getDefaultConverter(&status);
     323           0 :     } else if(*codepage == 0) {
     324             :         // use the "invariant characters" conversion
     325           0 :         if(cloneArrayIfNeeded(dataLength, dataLength, FALSE)) {
     326           0 :             u_charsToUChars(codepageData, getArrayStart(), dataLength);
     327           0 :             setLength(dataLength);
     328             :         } else {
     329           0 :             setToBogus();
     330             :         }
     331           0 :         return;
     332             :     } else {
     333           0 :         converter = ucnv_open(codepage, &status);
     334             :     }
     335             : 
     336             :     // if we failed, set the appropriate flags and return
     337           0 :     if(U_FAILURE(status)) {
     338           0 :         setToBogus();
     339           0 :         return;
     340             :     }
     341             : 
     342             :     // perform the conversion
     343           0 :     doCodepageCreate(codepageData, dataLength, converter, status);
     344           0 :     if(U_FAILURE(status)) {
     345           0 :         setToBogus();
     346             :     }
     347             : 
     348             :     // close the converter
     349           0 :     if(codepage == 0) {
     350           0 :         u_releaseDefaultConverter(converter);
     351             :     } else {
     352           0 :         ucnv_close(converter);
     353             :     }
     354             : }
     355             : 
     356             : void
     357           0 : UnicodeString::doCodepageCreate(const char *codepageData,
     358             :                                 int32_t dataLength,
     359             :                                 UConverter *converter,
     360             :                                 UErrorCode &status)
     361             : {
     362           0 :     if(U_FAILURE(status)) {
     363           0 :         return;
     364             :     }
     365             : 
     366             :     // set up the conversion parameters
     367           0 :     const char *mySource     = codepageData;
     368           0 :     const char *mySourceEnd  = mySource + dataLength;
     369             :     UChar *array, *myTarget;
     370             : 
     371             :     // estimate the size needed:
     372             :     int32_t arraySize;
     373           0 :     if(dataLength <= US_STACKBUF_SIZE) {
     374             :         // try to use the stack buffer
     375           0 :         arraySize = US_STACKBUF_SIZE;
     376             :     } else {
     377             :         // 1.25 UChar's per source byte should cover most cases
     378           0 :         arraySize = dataLength + (dataLength >> 2);
     379             :     }
     380             : 
     381             :     // we do not care about the current contents
     382           0 :     UBool doCopyArray = FALSE;
     383             :     for(;;) {
     384           0 :         if(!cloneArrayIfNeeded(arraySize, arraySize, doCopyArray)) {
     385           0 :             setToBogus();
     386           0 :             break;
     387             :         }
     388             : 
     389             :         // perform the conversion
     390           0 :         array = getArrayStart();
     391           0 :         myTarget = array + length();
     392           0 :         ucnv_toUnicode(converter, &myTarget,  array + getCapacity(),
     393           0 :             &mySource, mySourceEnd, 0, TRUE, &status);
     394             : 
     395             :         // update the conversion parameters
     396           0 :         setLength((int32_t)(myTarget - array));
     397             : 
     398             :         // allocate more space and copy data, if needed
     399           0 :         if(status == U_BUFFER_OVERFLOW_ERROR) {
     400             :             // reset the error code
     401           0 :             status = U_ZERO_ERROR;
     402             : 
     403             :             // keep the previous conversion results
     404           0 :             doCopyArray = TRUE;
     405             : 
     406             :             // estimate the new size needed, larger than before
     407             :             // try 2 UChar's per remaining source byte
     408           0 :             arraySize = (int32_t)(length() + 2 * (mySourceEnd - mySource));
     409             :         } else {
     410           0 :             break;
     411             :         }
     412             :     }
     413             : }
     414             : 
     415             : U_NAMESPACE_END
     416             : 
     417             : #endif

Generated by: LCOV version 1.13