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 +}