intl/icu/source/io/ustdio.c

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/intl/icu/source/io/ustdio.c	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,726 @@
     1.4 +/*
     1.5 + ******************************************************************************
     1.6 + *
     1.7 + *   Copyright (C) 1998-2011, International Business Machines
     1.8 + *   Corporation and others.  All Rights Reserved.
     1.9 + *
    1.10 + ******************************************************************************
    1.11 + *
    1.12 + * File ustdio.c
    1.13 + *
    1.14 + * Modification History:
    1.15 + *
    1.16 + *   Date        Name        Description
    1.17 + *   11/18/98    stephen     Creation.
    1.18 + *   03/12/99    stephen     Modified for new C API.
    1.19 + *   07/19/99    stephen     Fixed read() and gets()
    1.20 + ******************************************************************************
    1.21 + */
    1.22 +
    1.23 +#include "unicode/ustdio.h"
    1.24 +#include "unicode/putil.h"
    1.25 +#include "cmemory.h"
    1.26 +#include "cstring.h"
    1.27 +#include "ufile.h"
    1.28 +#include "ufmt_cmn.h"
    1.29 +#include "unicode/ucnv.h"
    1.30 +#include "unicode/ustring.h"
    1.31 +
    1.32 +#include <string.h>
    1.33 +
    1.34 +#define DELIM_LF 0x000A
    1.35 +#define DELIM_VT 0x000B
    1.36 +#define DELIM_FF 0x000C
    1.37 +#define DELIM_CR 0x000D
    1.38 +#define DELIM_NEL 0x0085
    1.39 +#define DELIM_LS 0x2028
    1.40 +#define DELIM_PS 0x2029
    1.41 +
    1.42 +/* TODO: is this correct for all codepages? Should we just use \n and let the converter handle it? */
    1.43 +#if U_PLATFORM_USES_ONLY_WIN32_API
    1.44 +static const UChar DELIMITERS [] = { DELIM_CR, DELIM_LF, 0x0000 };
    1.45 +static const uint32_t DELIMITERS_LEN = 2;
    1.46 +/* TODO: Default newline writing should be detected based upon the converter being used. */
    1.47 +#else
    1.48 +static const UChar DELIMITERS [] = { DELIM_LF, 0x0000 };
    1.49 +static const uint32_t DELIMITERS_LEN = 1;
    1.50 +#endif
    1.51 +
    1.52 +#define IS_FIRST_STRING_DELIMITER(c1) \
    1.53 + (UBool)((DELIM_LF <= (c1) && (c1) <= DELIM_CR) \
    1.54 +        || (c1) == DELIM_NEL \
    1.55 +        || (c1) == DELIM_LS \
    1.56 +        || (c1) == DELIM_PS)
    1.57 +#define CAN_HAVE_COMBINED_STRING_DELIMITER(c1) (UBool)((c1) == DELIM_CR)
    1.58 +#define IS_COMBINED_STRING_DELIMITER(c1, c2) \
    1.59 + (UBool)((c1) == DELIM_CR && (c2) == DELIM_LF)
    1.60 +
    1.61 +
    1.62 +#if !UCONFIG_NO_TRANSLITERATION
    1.63 +
    1.64 +U_CAPI UTransliterator* U_EXPORT2
    1.65 +u_fsettransliterator(UFILE *file, UFileDirection direction,
    1.66 +                     UTransliterator *adopt, UErrorCode *status)
    1.67 +{
    1.68 +    UTransliterator *old = NULL;
    1.69 +
    1.70 +    if(U_FAILURE(*status))
    1.71 +    {
    1.72 +        return adopt;
    1.73 +    }
    1.74 +
    1.75 +    if(!file)
    1.76 +    {
    1.77 +        *status = U_ILLEGAL_ARGUMENT_ERROR;
    1.78 +        return adopt;
    1.79 +    }
    1.80 +
    1.81 +    if(direction & U_READ)
    1.82 +    {
    1.83 +        /** TODO: implement */
    1.84 +        *status = U_UNSUPPORTED_ERROR;
    1.85 +        return adopt;
    1.86 +    }
    1.87 +
    1.88 +    if(adopt == NULL) /* they are clearing it */
    1.89 +    {
    1.90 +        if(file->fTranslit != NULL)
    1.91 +        {
    1.92 +            /* TODO: Check side */
    1.93 +            old = file->fTranslit->translit;
    1.94 +            uprv_free(file->fTranslit->buffer);
    1.95 +            file->fTranslit->buffer=NULL;
    1.96 +            uprv_free(file->fTranslit);
    1.97 +            file->fTranslit=NULL;
    1.98 +        }
    1.99 +    }
   1.100 +    else
   1.101 +    {
   1.102 +        if(file->fTranslit == NULL)
   1.103 +        {
   1.104 +            file->fTranslit = (UFILETranslitBuffer*) uprv_malloc(sizeof(UFILETranslitBuffer));
   1.105 +            if(!file->fTranslit)
   1.106 +            {
   1.107 +                *status = U_MEMORY_ALLOCATION_ERROR;
   1.108 +                return adopt;
   1.109 +            }
   1.110 +            file->fTranslit->capacity = 0;
   1.111 +            file->fTranslit->length = 0;
   1.112 +            file->fTranslit->pos = 0;
   1.113 +            file->fTranslit->buffer = NULL;
   1.114 +        }
   1.115 +        else
   1.116 +        {
   1.117 +            old = file->fTranslit->translit;
   1.118 +            ufile_flush_translit(file);
   1.119 +        }
   1.120 +
   1.121 +        file->fTranslit->translit = adopt;
   1.122 +    }
   1.123 +
   1.124 +    return old;
   1.125 +}
   1.126 +
   1.127 +static const UChar * u_file_translit(UFILE *f, const UChar *src, int32_t *count, UBool flush)
   1.128 +{
   1.129 +    int32_t newlen;
   1.130 +    int32_t junkCount = 0;
   1.131 +    int32_t textLength;
   1.132 +    int32_t textLimit;
   1.133 +    UTransPosition pos;
   1.134 +    UErrorCode status = U_ZERO_ERROR;
   1.135 +
   1.136 +    if(count == NULL)
   1.137 +    {
   1.138 +        count = &junkCount;
   1.139 +    }
   1.140 +
   1.141 +    if ((!f)||(!f->fTranslit)||(!f->fTranslit->translit))
   1.142 +    {
   1.143 +        /* fast path */
   1.144 +        return src;
   1.145 +    }
   1.146 +
   1.147 +    /* First: slide over everything */
   1.148 +    if(f->fTranslit->length > f->fTranslit->pos)
   1.149 +    {
   1.150 +        memmove(f->fTranslit->buffer, f->fTranslit->buffer + f->fTranslit->pos,
   1.151 +            (f->fTranslit->length - f->fTranslit->pos)*sizeof(UChar));
   1.152 +    }
   1.153 +    f->fTranslit->length -= f->fTranslit->pos; /* always */
   1.154 +    f->fTranslit->pos = 0;
   1.155 +
   1.156 +    /* Calculate new buffer size needed */
   1.157 +    newlen = (*count + f->fTranslit->length) * 4;
   1.158 +
   1.159 +    if(newlen > f->fTranslit->capacity)
   1.160 +    {
   1.161 +        if(f->fTranslit->buffer == NULL)
   1.162 +        {
   1.163 +            f->fTranslit->buffer = (UChar*)uprv_malloc(newlen * sizeof(UChar));
   1.164 +        }
   1.165 +        else
   1.166 +        {
   1.167 +            f->fTranslit->buffer = (UChar*)uprv_realloc(f->fTranslit->buffer, newlen * sizeof(UChar));
   1.168 +        }
   1.169 +        /* Check for malloc/realloc failure. */
   1.170 +        if (f->fTranslit->buffer == NULL) {
   1.171 +        	return NULL;
   1.172 +        }
   1.173 +        f->fTranslit->capacity = newlen;
   1.174 +    }
   1.175 +
   1.176 +    /* Now, copy any data over */
   1.177 +    u_strncpy(f->fTranslit->buffer + f->fTranslit->length,
   1.178 +        src,
   1.179 +        *count);
   1.180 +    f->fTranslit->length += *count;
   1.181 +
   1.182 +    /* Now, translit in place as much as we can  */
   1.183 +    if(flush == FALSE)
   1.184 +    {
   1.185 +        textLength = f->fTranslit->length;
   1.186 +        pos.contextStart = 0;
   1.187 +        pos.contextLimit = textLength;
   1.188 +        pos.start        = 0;
   1.189 +        pos.limit        = textLength;
   1.190 +
   1.191 +        utrans_transIncrementalUChars(f->fTranslit->translit,
   1.192 +            f->fTranslit->buffer, /* because we shifted */
   1.193 +            &textLength,
   1.194 +            f->fTranslit->capacity,
   1.195 +            &pos,
   1.196 +            &status);
   1.197 +
   1.198 +        /* now: start/limit point to the transliterated text */
   1.199 +        /* Transliterated is [buffer..pos.start) */
   1.200 +        *count            = pos.start;
   1.201 +        f->fTranslit->pos = pos.start;
   1.202 +        f->fTranslit->length = pos.limit;
   1.203 +
   1.204 +        return f->fTranslit->buffer;
   1.205 +    }
   1.206 +    else
   1.207 +    {
   1.208 +        textLength = f->fTranslit->length;
   1.209 +        textLimit = f->fTranslit->length;
   1.210 +
   1.211 +        utrans_transUChars(f->fTranslit->translit,
   1.212 +            f->fTranslit->buffer,
   1.213 +            &textLength,
   1.214 +            f->fTranslit->capacity,
   1.215 +            0,
   1.216 +            &textLimit,
   1.217 +            &status);
   1.218 +
   1.219 +        /* out: converted len */
   1.220 +        *count = textLimit;
   1.221 +
   1.222 +        /* Set pointers to 0 */
   1.223 +        f->fTranslit->pos = 0;
   1.224 +        f->fTranslit->length = 0;
   1.225 +
   1.226 +        return f->fTranslit->buffer;
   1.227 +    }
   1.228 +}
   1.229 +
   1.230 +#endif
   1.231 +
   1.232 +void
   1.233 +ufile_flush_translit(UFILE *f)
   1.234 +{
   1.235 +#if !UCONFIG_NO_TRANSLITERATION
   1.236 +    if((!f)||(!f->fTranslit))
   1.237 +        return;
   1.238 +#endif
   1.239 +
   1.240 +    u_file_write_flush(NULL, 0, f, FALSE, TRUE);
   1.241 +}
   1.242 +
   1.243 +
   1.244 +void
   1.245 +ufile_flush_io(UFILE *f)
   1.246 +{
   1.247 +  if((!f) || (!f->fFile)) {
   1.248 +    return; /* skip if no file */
   1.249 +  }
   1.250 +
   1.251 +  u_file_write_flush(NULL, 0, f, TRUE, FALSE);
   1.252 +}
   1.253 +
   1.254 +
   1.255 +void
   1.256 +ufile_close_translit(UFILE *f)
   1.257 +{
   1.258 +#if !UCONFIG_NO_TRANSLITERATION
   1.259 +    if((!f)||(!f->fTranslit))
   1.260 +        return;
   1.261 +#endif
   1.262 +
   1.263 +    ufile_flush_translit(f);
   1.264 +
   1.265 +#if !UCONFIG_NO_TRANSLITERATION
   1.266 +    if(f->fTranslit->translit)
   1.267 +        utrans_close(f->fTranslit->translit);
   1.268 +
   1.269 +    if(f->fTranslit->buffer)
   1.270 +    {
   1.271 +        uprv_free(f->fTranslit->buffer);
   1.272 +    }
   1.273 +
   1.274 +    uprv_free(f->fTranslit);
   1.275 +    f->fTranslit = NULL;
   1.276 +#endif
   1.277 +}
   1.278 +
   1.279 +
   1.280 +/* Input/output */
   1.281 +
   1.282 +U_CAPI int32_t U_EXPORT2 /* U_CAPI ... U_EXPORT2 added by Peter Kirk 17 Nov 2001 */
   1.283 +u_fputs(const UChar    *s,
   1.284 +        UFILE        *f)
   1.285 +{
   1.286 +    int32_t count = u_file_write(s, u_strlen(s), f);
   1.287 +    count += u_file_write(DELIMITERS, DELIMITERS_LEN, f);
   1.288 +    return count;
   1.289 +}
   1.290 +
   1.291 +U_CAPI UChar32 U_EXPORT2 /* U_CAPI ... U_EXPORT2 added by Peter Kirk 17 Nov 2001 */
   1.292 +u_fputc(UChar32      uc,
   1.293 +        UFILE        *f)
   1.294 +{
   1.295 +    UChar buf[2];
   1.296 +    int32_t idx = 0;
   1.297 +    UBool isError = FALSE;
   1.298 +
   1.299 +    U16_APPEND(buf, idx, sizeof(buf)/sizeof(*buf), uc, isError);
   1.300 +    if (isError) {
   1.301 +        return U_EOF;
   1.302 +    }
   1.303 +    return u_file_write(buf, idx, f) == idx ? uc : U_EOF;
   1.304 +}
   1.305 +
   1.306 +
   1.307 +U_CFUNC int32_t U_EXPORT2
   1.308 +u_file_write_flush(const UChar *chars,
   1.309 +                   int32_t     count,
   1.310 +                   UFILE       *f,
   1.311 +                   UBool       flushIO,
   1.312 +                   UBool       flushTranslit)
   1.313 +{
   1.314 +    /* Set up conversion parameters */
   1.315 +    UErrorCode  status       = U_ZERO_ERROR;
   1.316 +    const UChar *mySource    = chars;
   1.317 +    const UChar *mySourceBegin; 
   1.318 +    const UChar *mySourceEnd;
   1.319 +    char        charBuffer[UFILE_CHARBUFFER_SIZE];
   1.320 +    char        *myTarget   = charBuffer;
   1.321 +    int32_t     written      = 0;
   1.322 +    int32_t     numConverted = 0;
   1.323 +
   1.324 +    if (count < 0) {
   1.325 +        count = u_strlen(chars);
   1.326 +    }
   1.327 +
   1.328 +#if !UCONFIG_NO_TRANSLITERATION
   1.329 +    if((f->fTranslit) && (f->fTranslit->translit))
   1.330 +    {
   1.331 +        /* Do the transliteration */
   1.332 +        mySource = u_file_translit(f, chars, &count, flushTranslit);
   1.333 +    }
   1.334 +#endif
   1.335 +
   1.336 +    /* Write to a string. */
   1.337 +    if (!f->fFile) {
   1.338 +        int32_t charsLeft = (int32_t)(f->str.fLimit - f->str.fPos);
   1.339 +        if (flushIO && charsLeft > count) {
   1.340 +            count++;
   1.341 +        }
   1.342 +        written = ufmt_min(count, charsLeft);
   1.343 +        u_strncpy(f->str.fPos, mySource, written);
   1.344 +        f->str.fPos += written;
   1.345 +        return written;
   1.346 +    }
   1.347 +
   1.348 +    mySourceEnd = mySource + count;
   1.349 +
   1.350 +    /* Perform the conversion in a loop */
   1.351 +    do {
   1.352 +        mySourceBegin = mySource; /* beginning location for this loop */
   1.353 +        status     = U_ZERO_ERROR;
   1.354 +        if(f->fConverter != NULL) { /* We have a valid converter */
   1.355 +            ucnv_fromUnicode(f->fConverter,
   1.356 +                &myTarget,
   1.357 +                charBuffer + UFILE_CHARBUFFER_SIZE,
   1.358 +                &mySource,
   1.359 +                mySourceEnd,
   1.360 +                NULL,
   1.361 +                flushIO,
   1.362 +                &status);
   1.363 +        } else { /*weiv: do the invariant conversion */
   1.364 +            int32_t convertChars = (int32_t) (mySourceEnd - mySource); 
   1.365 +            if (convertChars > UFILE_CHARBUFFER_SIZE) { 
   1.366 +                convertChars = UFILE_CHARBUFFER_SIZE; 
   1.367 +                status = U_BUFFER_OVERFLOW_ERROR; 
   1.368 +            } 
   1.369 +            u_UCharsToChars(mySource, myTarget, convertChars); 
   1.370 +            mySource += convertChars; 
   1.371 +            myTarget += convertChars; 
   1.372 +        }
   1.373 +        numConverted = (int32_t)(myTarget - charBuffer);
   1.374 +
   1.375 +        if (numConverted > 0) {
   1.376 +            /* write the converted bytes */
   1.377 +            fwrite(charBuffer,
   1.378 +                sizeof(char),
   1.379 +                numConverted,
   1.380 +                f->fFile);
   1.381 +
   1.382 +            written     += (int32_t) (mySource - mySourceBegin);
   1.383 +        }
   1.384 +        myTarget     = charBuffer;
   1.385 +    }
   1.386 +    while(status == U_BUFFER_OVERFLOW_ERROR);
   1.387 +
   1.388 +    /* return # of chars written */
   1.389 +    return written;
   1.390 +}
   1.391 +
   1.392 +U_CAPI int32_t U_EXPORT2 /* U_CAPI ... U_EXPORT2 added by Peter Kirk 17 Nov 2001 */
   1.393 +u_file_write(    const UChar     *chars,
   1.394 +             int32_t        count,
   1.395 +             UFILE         *f)
   1.396 +{
   1.397 +    return u_file_write_flush(chars,count,f,FALSE,FALSE);
   1.398 +}
   1.399 +
   1.400 +
   1.401 +/* private function used for buffering input */
   1.402 +void
   1.403 +ufile_fill_uchar_buffer(UFILE *f)
   1.404 +{
   1.405 +    UErrorCode  status;
   1.406 +    const char  *mySource;
   1.407 +    const char  *mySourceEnd;
   1.408 +    UChar       *myTarget;
   1.409 +    int32_t     bufferSize;
   1.410 +    int32_t     maxCPBytes;
   1.411 +    int32_t     bytesRead;
   1.412 +    int32_t     availLength;
   1.413 +    int32_t     dataSize;
   1.414 +    char        charBuffer[UFILE_CHARBUFFER_SIZE];
   1.415 +    u_localized_string *str;
   1.416 +
   1.417 +    if (f->fFile == NULL) {
   1.418 +        /* There is nothing to do. It's a string. */
   1.419 +        return;
   1.420 +    }
   1.421 +
   1.422 +    str = &f->str;
   1.423 +    dataSize = (int32_t)(str->fLimit - str->fPos);
   1.424 +    if (f->fFileno == 0 && dataSize > 0) {
   1.425 +        /* Don't read from stdin too many times. There is still some data. */
   1.426 +        return;
   1.427 +    }
   1.428 +
   1.429 +    /* shift the buffer if it isn't empty */
   1.430 +    if(dataSize != 0) {
   1.431 +        uprv_memmove(f->fUCBuffer, str->fPos, dataSize * sizeof(UChar)); /* not accessing beyond memory */
   1.432 +    }
   1.433 +
   1.434 +
   1.435 +    /* record how much buffer space is available */
   1.436 +    availLength = UFILE_UCHARBUFFER_SIZE - dataSize;
   1.437 +
   1.438 +    /* Determine the # of codepage bytes needed to fill our UChar buffer */
   1.439 +    /* weiv: if converter is NULL, we use invariant converter with charwidth = 1)*/
   1.440 +    maxCPBytes = availLength / (f->fConverter!=NULL?(2*ucnv_getMinCharSize(f->fConverter)):1);
   1.441 +
   1.442 +    /* Read in the data to convert */
   1.443 +    if (f->fFileno == 0) {
   1.444 +        /* Special case. Read from stdin one line at a time. */
   1.445 +        char *retStr = fgets(charBuffer, ufmt_min(maxCPBytes, UFILE_CHARBUFFER_SIZE), f->fFile);
   1.446 +        bytesRead = (int32_t)(retStr ? uprv_strlen(charBuffer) : 0);
   1.447 +    }
   1.448 +    else {
   1.449 +        /* A normal file */
   1.450 +        bytesRead = (int32_t)fread(charBuffer,
   1.451 +            sizeof(char),
   1.452 +            ufmt_min(maxCPBytes, UFILE_CHARBUFFER_SIZE),
   1.453 +            f->fFile);
   1.454 +    }
   1.455 +
   1.456 +    /* Set up conversion parameters */
   1.457 +    status      = U_ZERO_ERROR;
   1.458 +    mySource    = charBuffer;
   1.459 +    mySourceEnd = charBuffer + bytesRead;
   1.460 +    myTarget    = f->fUCBuffer + dataSize;
   1.461 +    bufferSize  = UFILE_UCHARBUFFER_SIZE;
   1.462 +
   1.463 +    if(f->fConverter != NULL) { /* We have a valid converter */
   1.464 +        /* Perform the conversion */
   1.465 +        ucnv_toUnicode(f->fConverter,
   1.466 +            &myTarget,
   1.467 +            f->fUCBuffer + bufferSize,
   1.468 +            &mySource,
   1.469 +            mySourceEnd,
   1.470 +            NULL,
   1.471 +            (UBool)(feof(f->fFile) != 0),
   1.472 +            &status);
   1.473 +
   1.474 +    } else { /*weiv: do the invariant conversion */
   1.475 +        u_charsToUChars(mySource, myTarget, bytesRead);
   1.476 +        myTarget += bytesRead;
   1.477 +    }
   1.478 +
   1.479 +    /* update the pointers into our array */
   1.480 +    str->fPos    = str->fBuffer;
   1.481 +    str->fLimit  = myTarget;
   1.482 +}
   1.483 +
   1.484 +U_CAPI UChar* U_EXPORT2 /* U_CAPI ... U_EXPORT2 added by Peter Kirk 17 Nov 2001 */
   1.485 +u_fgets(UChar        *s,
   1.486 +        int32_t       n,
   1.487 +        UFILE        *f)
   1.488 +{
   1.489 +    int32_t dataSize;
   1.490 +    int32_t count;
   1.491 +    UChar *alias;
   1.492 +    const UChar *limit;
   1.493 +    UChar *sItr;
   1.494 +    UChar currDelim = 0;
   1.495 +    u_localized_string *str;
   1.496 +
   1.497 +    if (n <= 0) {
   1.498 +        /* Caller screwed up. We need to write the null terminatior. */
   1.499 +        return NULL;
   1.500 +    }
   1.501 +
   1.502 +    /* fill the buffer if needed */
   1.503 +    str = &f->str;
   1.504 +    if (str->fPos >= str->fLimit) {
   1.505 +        ufile_fill_uchar_buffer(f);
   1.506 +    }
   1.507 +
   1.508 +    /* subtract 1 from n to compensate for the terminator */
   1.509 +    --n;
   1.510 +
   1.511 +    /* determine the amount of data in the buffer */
   1.512 +    dataSize = (int32_t)(str->fLimit - str->fPos);
   1.513 +
   1.514 +    /* if 0 characters were left, return 0 */
   1.515 +    if (dataSize == 0)
   1.516 +        return NULL;
   1.517 +
   1.518 +    /* otherwise, iteratively fill the buffer and copy */
   1.519 +    count = 0;
   1.520 +    sItr = s;
   1.521 +    currDelim = 0;
   1.522 +    while (dataSize > 0 && count < n) {
   1.523 +        alias = str->fPos;
   1.524 +
   1.525 +        /* Find how much to copy */
   1.526 +        if (dataSize < (n - count)) {
   1.527 +            limit = str->fLimit;
   1.528 +        }
   1.529 +        else {
   1.530 +            limit = alias + (n - count);
   1.531 +        }
   1.532 +
   1.533 +        if (!currDelim) {
   1.534 +            /* Copy UChars until we find the first occurrence of a delimiter character */
   1.535 +            while (alias < limit && !IS_FIRST_STRING_DELIMITER(*alias)) {
   1.536 +                count++;
   1.537 +                *(sItr++) = *(alias++);
   1.538 +            }
   1.539 +            /* Preserve the newline */
   1.540 +            if (alias < limit && IS_FIRST_STRING_DELIMITER(*alias)) {
   1.541 +                if (CAN_HAVE_COMBINED_STRING_DELIMITER(*alias)) {
   1.542 +                    currDelim = *alias;
   1.543 +                }
   1.544 +                else {
   1.545 +                    currDelim = 1;  /* This isn't a newline, but it's used to say
   1.546 +                                    that we should break later. We've checked all
   1.547 +                                    possible newline combinations even across buffer
   1.548 +                                    boundaries. */
   1.549 +                }
   1.550 +                count++;
   1.551 +                *(sItr++) = *(alias++);
   1.552 +            }
   1.553 +        }
   1.554 +        /* If we have a CRLF combination, preserve that too. */
   1.555 +        if (alias < limit) {
   1.556 +            if (currDelim && IS_COMBINED_STRING_DELIMITER(currDelim, *alias)) {
   1.557 +                count++;
   1.558 +                *(sItr++) = *(alias++);
   1.559 +            }
   1.560 +            currDelim = 1;  /* This isn't a newline, but it's used to say
   1.561 +                            that we should break later. We've checked all
   1.562 +                            possible newline combinations even across buffer
   1.563 +                            boundaries. */
   1.564 +        }
   1.565 +
   1.566 +        /* update the current buffer position */
   1.567 +        str->fPos = alias;
   1.568 +
   1.569 +        /* if we found a delimiter */
   1.570 +        if (currDelim == 1) {
   1.571 +            /* break out */
   1.572 +            break;
   1.573 +        }
   1.574 +
   1.575 +        /* refill the buffer */
   1.576 +        ufile_fill_uchar_buffer(f);
   1.577 +
   1.578 +        /* determine the amount of data in the buffer */
   1.579 +        dataSize = (int32_t)(str->fLimit - str->fPos);
   1.580 +    }
   1.581 +
   1.582 +    /* add the terminator and return s */
   1.583 +    *sItr = 0x0000;
   1.584 +    return s;
   1.585 +}
   1.586 +
   1.587 +U_CFUNC UBool U_EXPORT2
   1.588 +ufile_getch(UFILE *f, UChar *ch)
   1.589 +{
   1.590 +    UBool isValidChar = FALSE;
   1.591 +
   1.592 +    *ch = U_EOF;
   1.593 +    /* if we have an available character in the buffer, return it */
   1.594 +    if(f->str.fPos < f->str.fLimit){
   1.595 +        *ch = *(f->str.fPos)++;
   1.596 +        isValidChar = TRUE;
   1.597 +    }
   1.598 +    else {
   1.599 +        /* otherwise, fill the buffer and return the next character */
   1.600 +        if(f->str.fPos >= f->str.fLimit) {
   1.601 +            ufile_fill_uchar_buffer(f);
   1.602 +        }
   1.603 +        if(f->str.fPos < f->str.fLimit) {
   1.604 +            *ch = *(f->str.fPos)++;
   1.605 +            isValidChar = TRUE;
   1.606 +        }
   1.607 +    }
   1.608 +    return isValidChar;
   1.609 +}
   1.610 +
   1.611 +U_CAPI UChar U_EXPORT2 /* U_CAPI ... U_EXPORT2 added by Peter Kirk 17 Nov 2001 */
   1.612 +u_fgetc(UFILE        *f)
   1.613 +{
   1.614 +    UChar ch;
   1.615 +    ufile_getch(f, &ch);
   1.616 +    return ch;
   1.617 +}
   1.618 +
   1.619 +U_CFUNC UBool U_EXPORT2
   1.620 +ufile_getch32(UFILE *f, UChar32 *c32)
   1.621 +{
   1.622 +    UBool isValidChar = FALSE;
   1.623 +    u_localized_string *str;
   1.624 +
   1.625 +    *c32 = U_EOF;
   1.626 +
   1.627 +    /* Fill the buffer if it is empty */
   1.628 +    str = &f->str;
   1.629 +    if (f && str->fPos + 1 >= str->fLimit) {
   1.630 +        ufile_fill_uchar_buffer(f);
   1.631 +    }
   1.632 +
   1.633 +    /* Get the next character in the buffer */
   1.634 +    if (str->fPos < str->fLimit) {
   1.635 +        *c32 = *(str->fPos)++;
   1.636 +        if (U_IS_LEAD(*c32)) {
   1.637 +            if (str->fPos < str->fLimit) {
   1.638 +                UChar c16 = *(str->fPos)++;
   1.639 +                *c32 = U16_GET_SUPPLEMENTARY(*c32, c16);
   1.640 +                isValidChar = TRUE;
   1.641 +            }
   1.642 +            else {
   1.643 +                *c32 = U_EOF;
   1.644 +            }
   1.645 +        }
   1.646 +        else {
   1.647 +            isValidChar = TRUE;
   1.648 +        }
   1.649 +    }
   1.650 +
   1.651 +    return isValidChar;
   1.652 +}
   1.653 +
   1.654 +U_CAPI UChar32 U_EXPORT2 /* U_CAPI ... U_EXPORT2 added by Peter Kirk 17 Nov 2001 */
   1.655 +u_fgetcx(UFILE        *f)
   1.656 +{
   1.657 +    UChar32 ch;
   1.658 +    ufile_getch32(f, &ch);
   1.659 +    return ch;
   1.660 +}
   1.661 +
   1.662 +U_CAPI UChar32 U_EXPORT2 /* U_CAPI ... U_EXPORT2 added by Peter Kirk 17 Nov 2001 */
   1.663 +u_fungetc(UChar32        ch,
   1.664 +    UFILE        *f)
   1.665 +{
   1.666 +    u_localized_string *str;
   1.667 +
   1.668 +    str = &f->str;
   1.669 +
   1.670 +    /* if we're at the beginning of the buffer, sorry! */
   1.671 +    if (str->fPos == str->fBuffer
   1.672 +        || (U_IS_LEAD(ch) && (str->fPos - 1) == str->fBuffer))
   1.673 +    {
   1.674 +        ch = U_EOF;
   1.675 +    }
   1.676 +    else {
   1.677 +        /* otherwise, put the character back */
   1.678 +        /* Remember, read them back on in the reverse order. */
   1.679 +        if (U_IS_LEAD(ch)) {
   1.680 +            if (*--(str->fPos) != U16_TRAIL(ch)
   1.681 +                || *--(str->fPos) != U16_LEAD(ch))
   1.682 +            {
   1.683 +                ch = U_EOF;
   1.684 +            }
   1.685 +        }
   1.686 +        else if (*--(str->fPos) != ch) {
   1.687 +            ch = U_EOF;
   1.688 +        }
   1.689 +    }
   1.690 +    return ch;
   1.691 +}
   1.692 +
   1.693 +U_CAPI int32_t U_EXPORT2 /* U_CAPI ... U_EXPORT2 added by Peter Kirk 17 Nov 2001 */
   1.694 +u_file_read(    UChar        *chars,
   1.695 +    int32_t        count,
   1.696 +    UFILE         *f)
   1.697 +{
   1.698 +    int32_t dataSize;
   1.699 +    int32_t read = 0;
   1.700 +    u_localized_string *str = &f->str;
   1.701 +
   1.702 +    do {
   1.703 +
   1.704 +        /* determine the amount of data in the buffer */
   1.705 +        dataSize = (int32_t)(str->fLimit - str->fPos);
   1.706 +        if (dataSize <= 0) {
   1.707 +            /* fill the buffer */
   1.708 +            ufile_fill_uchar_buffer(f);
   1.709 +            dataSize = (int32_t)(str->fLimit - str->fPos);
   1.710 +        }
   1.711 +
   1.712 +        /* Make sure that we don't read too much */
   1.713 +        if (dataSize > (count - read)) {
   1.714 +            dataSize = count - read;
   1.715 +        }
   1.716 +
   1.717 +        /* copy the current data in the buffer */
   1.718 +        memcpy(chars + read, str->fPos, dataSize * sizeof(UChar));
   1.719 +
   1.720 +        /* update number of items read */
   1.721 +        read += dataSize;
   1.722 +
   1.723 +        /* update the current buffer position */
   1.724 +        str->fPos += dataSize;
   1.725 +    }
   1.726 +    while (dataSize != 0 && read < count);
   1.727 +
   1.728 +    return read;
   1.729 +}

mercurial