Home | History | Annotate | Download | only in toolutil
      1 /******************************************************************************
      2  *   Copyright (C) 2009-2010, International Business Machines
      3  *   Corporation and others.  All Rights Reserved.
      4  *******************************************************************************
      5  */
      6 
      7 #include "flagparser.h"
      8 #include "filestrm.h"
      9 #include "cstring.h"
     10 #include "cmemory.h"
     11 
     12 #define DEFAULT_BUFFER_SIZE 512
     13 
     14 static int32_t currentBufferSize = DEFAULT_BUFFER_SIZE;
     15 
     16 static void extractFlag(char* buffer, int32_t bufferSize, char* flag, int32_t flagSize, UErrorCode *status);
     17 static int32_t getFlagOffset(const char *buffer, int32_t bufferSize);
     18 
     19 /*
     20  * Opens the given fileName and reads in the information storing the data in flagBuffer.
     21  */
     22 U_CAPI int32_t U_EXPORT2
     23 parseFlagsFile(const char *fileName, char **flagBuffer, int32_t flagBufferSize, int32_t numOfFlags, UErrorCode *status) {
     24     char* buffer = uprv_malloc(sizeof(char) * currentBufferSize);
     25     UBool allocateMoreSpace = FALSE;
     26     int32_t i;
     27     int32_t result = 0;
     28 
     29     FileStream *f = T_FileStream_open(fileName, "r");
     30     if (f == NULL) {
     31         *status = U_FILE_ACCESS_ERROR;
     32         return -1;
     33     }
     34 
     35     if (buffer == NULL) {
     36         *status = U_MEMORY_ALLOCATION_ERROR;
     37         return -1;
     38     }
     39 
     40     do {
     41         if (allocateMoreSpace) {
     42             allocateMoreSpace = FALSE;
     43             currentBufferSize *= 2;
     44             uprv_free(buffer);
     45             buffer = uprv_malloc(sizeof(char) * currentBufferSize);
     46             if (buffer == NULL) {
     47                 *status = U_MEMORY_ALLOCATION_ERROR;
     48                 return -1;
     49             }
     50         }
     51         for (i = 0; i < numOfFlags; i++) {
     52             if (T_FileStream_readLine(f, buffer, currentBufferSize) == NULL) {
     53                 *status = U_FILE_ACCESS_ERROR;
     54                 break;
     55             }
     56 
     57             if (uprv_strlen(buffer) == (currentBufferSize - 1) && buffer[currentBufferSize-2] != '\n') {
     58                 /* Allocate more space for buffer if it didnot read the entrire line */
     59                 allocateMoreSpace = TRUE;
     60                 T_FileStream_rewind(f);
     61                 break;
     62             } else {
     63                 extractFlag(buffer, currentBufferSize, flagBuffer[i], flagBufferSize, status);
     64                 if (U_FAILURE(*status)) {
     65                     if (*status == U_BUFFER_OVERFLOW_ERROR) {
     66                         result = currentBufferSize;
     67                     } else {
     68                         result = -1;
     69                     }
     70                     break;
     71                 }
     72             }
     73         }
     74     } while (allocateMoreSpace && U_SUCCESS(*status));
     75 
     76     uprv_free(buffer);
     77 
     78     T_FileStream_close(f);
     79 
     80     if (U_SUCCESS(*status) && result == 0) {
     81         currentBufferSize = DEFAULT_BUFFER_SIZE;
     82     }
     83 
     84     return result;
     85 }
     86 
     87 
     88 /*
     89  * Extract the setting after the '=' and store it in flag excluding the newline character.
     90  */
     91 static void extractFlag(char* buffer, int32_t bufferSize, char* flag, int32_t flagSize, UErrorCode *status) {
     92     int32_t i;
     93     char *pBuffer;
     94     int32_t offset;
     95     UBool bufferWritten = FALSE;
     96 
     97     if (buffer[0] != 0) {
     98         /* Get the offset (i.e. position after the '=') */
     99         offset = getFlagOffset(buffer, bufferSize);
    100         pBuffer = buffer+offset;
    101         for(i = 0;;i++) {
    102             if (i >= flagSize) {
    103                 *status = U_BUFFER_OVERFLOW_ERROR;
    104                 return;
    105             }
    106             if (pBuffer[i+1] == 0) {
    107                 /* Indicates a new line character. End here. */
    108                 flag[i] = 0;
    109                 break;
    110             }
    111 
    112             flag[i] = pBuffer[i];
    113             if (i == 0) {
    114                 bufferWritten = TRUE;
    115             }
    116         }
    117     }
    118 
    119     if (!bufferWritten) {
    120         flag[0] = 0;
    121     }
    122 }
    123 
    124 /*
    125  * Get the position after the '=' character.
    126  */
    127 static int32_t getFlagOffset(const char *buffer, int32_t bufferSize) {
    128     int32_t offset = 0;
    129 
    130     for (offset = 0; offset < bufferSize;offset++) {
    131         if (buffer[offset] == '=') {
    132             offset++;
    133             break;
    134         }
    135     }
    136 
    137     if (offset == bufferSize || (offset - 1) == bufferSize) {
    138         offset = 0;
    139     }
    140 
    141     return offset;
    142 }
    143