| /* |
| ******************************************************************************* |
| * |
| * Copyright (C) 1998-1999, International Business Machines |
| * Corporation and others. All Rights Reserved. |
| * |
| ******************************************************************************* |
| * |
| * File ufile.c |
| * |
| * Modification History: |
| * |
| * Date Name Description |
| * 11/19/98 stephen Creation. |
| * 03/12/99 stephen Modified for new C API. |
| * 12/01/99 weiv ufille_fill_uchar_buffer modified to be able to use invariant conversion |
| ******************************************************************************* |
| */ |
| |
| #include <stdio.h> |
| #include "ustdio.h" |
| #include "ufile.h" |
| #include "cmemory.h" |
| #include "cstring.h" |
| |
| #define MIN(a,b) (a < b ? a : b) |
| #define MAX(a,b) (a > b ? a : b) |
| |
| UFILE* |
| u_finit(FileStream *f, const char *cp, |
| UErrorCode *status) |
| { |
| UFILE *result = (UFILE*) uprv_malloc(sizeof(UFILE)); |
| if(result == 0) { |
| *status = U_MEMORY_ALLOCATION_ERROR; |
| return 0; |
| } |
| |
| result->fFile = f; |
| result->fOwnFile = FALSE; |
| result->fUCPos = result->fUCBuffer; |
| result->fUCLimit = result->fUCBuffer; |
| |
| if(cp == 0) { /* weiv: we're using the default converter*/ |
| result->fConverter = ucnv_open(0, status); |
| if(U_FAILURE(*status) || result->fConverter == 0) { |
| T_FileStream_close(result->fFile); |
| uprv_free(result); |
| return 0; |
| } |
| } else if (uprv_strlen(cp)>uprv_strlen("")) { /*weiv: we're specifying the converter*/ |
| result->fConverter = ucnv_open(cp, status); |
| if(U_FAILURE(*status) || result->fConverter == 0) { |
| T_FileStream_close(result->fFile); |
| uprv_free(result); |
| return 0; |
| } |
| } else { /*weiv: we'll go for invariant converter */ |
| result->fConverter = NULL; |
| } |
| |
| |
| return result; |
| } |
| |
| void |
| u_fclose(UFILE *file) |
| { |
| if(file->fOwnFile) |
| T_FileStream_close(file->fFile); |
| |
| ucnv_close(file->fConverter); |
| uprv_free(file); |
| } |
| |
| /* private function used for buffering input */ |
| void |
| ufile_fill_uchar_buffer(UFILE *f, |
| UErrorCode *status) |
| { |
| const char *mySource; |
| const char *mySourceEnd; |
| UChar *myTarget; |
| int32_t bufferSize; |
| int32_t maxCPBytes; |
| int32_t bytesRead; |
| int32_t availLength; |
| int32_t dataSize; |
| |
| if(U_FAILURE(*status)) return; |
| |
| /* shift the buffer if it isn't empty */ |
| dataSize = f->fUCLimit - f->fUCPos; |
| if(dataSize != 0) { |
| uprv_memmove(f->fUCBuffer, |
| f->fUCPos, |
| dataSize * sizeof(UChar)); |
| } |
| |
| /* record how much buffer space is available */ |
| availLength = UFILE_UCHARBUFFER_SIZE - dataSize; |
| |
| /* Determine the # of codepage bytes needed to fill our UChar buffer */ |
| maxCPBytes = availLength * (f->fConverter!=NULL?ucnv_getMaxCharSize(f->fConverter):1); /*weiv: Probably shoud #define it somewhere */ |
| |
| /* Read in the data to convert */ |
| bytesRead = T_FileStream_read(f->fFile,f->fCharBuffer, |
| MIN(maxCPBytes, UFILE_CHARBUFFER_SIZE)); |
| |
| /* Set up conversion parameters */ |
| *status = U_ZERO_ERROR; |
| mySource = f->fCharBuffer; |
| mySourceEnd = f->fCharBuffer + bytesRead; |
| myTarget = f->fUCBuffer + dataSize; |
| bufferSize = UFILE_UCHARBUFFER_SIZE; |
| |
| if(f->fConverter != NULL) { /*weiv: we have a good converter, so we'll just use it */ |
| /* Perform the conversion */ |
| ucnv_toUnicode(f->fConverter, |
| &myTarget, |
| f->fUCBuffer + bufferSize, |
| &mySource, |
| mySourceEnd, |
| NULL, |
| TRUE, |
| status); |
| } else { /*weiv: we couldn't obtain a converter, so we'll go with invariant conversion */ |
| u_charsToUChars(mySource, myTarget, bytesRead); |
| myTarget += bytesRead; |
| } |
| |
| /* update the pointers into our array */ |
| f->fUCPos = f->fUCBuffer; |
| f->fUCLimit = myTarget; |
| } |