Home | History | Annotate | Download | only in toolutil
      1 /******************************************************************************
      2  *   Copyright (C) 2009-2012, 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 int32_t extractFlag(char* buffer, int32_t bufferSize, char* flag, int32_t flagSize, const char ** flagNames, int32_t numOfFlags, 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, const char ** flagNames, int32_t numOfFlags, UErrorCode *status) {
     24     char* buffer = uprv_malloc(sizeof(char) * currentBufferSize);
     25     char* tmpFlagBuffer = uprv_malloc(sizeof(char) * flagBufferSize);
     26     UBool allocateMoreSpace = FALSE;
     27     int32_t idx, i;
     28     int32_t result = 0;
     29 
     30     FileStream *f = T_FileStream_open(fileName, "r");
     31     if (f == NULL) {
     32         *status = U_FILE_ACCESS_ERROR;
     33         return -1;
     34     }
     35 
     36     if (buffer == NULL) {
     37         *status = U_MEMORY_ALLOCATION_ERROR;
     38         return -1;
     39     }
     40 
     41     do {
     42         if (allocateMoreSpace) {
     43             allocateMoreSpace = FALSE;
     44             currentBufferSize *= 2;
     45             uprv_free(buffer);
     46             buffer = uprv_malloc(sizeof(char) * currentBufferSize);
     47             if (buffer == NULL) {
     48                 uprv_free(tmpFlagBuffer);
     49                 *status = U_MEMORY_ALLOCATION_ERROR;
     50                 return -1;
     51             }
     52         }
     53         for (i = 0; i < numOfFlags;) {
     54             if (T_FileStream_readLine(f, buffer, currentBufferSize) == NULL) {
     55                 /* End of file reached. */
     56                 break;
     57             }
     58             if (buffer[0] == '#') {
     59                 continue;
     60             }
     61 
     62             if (uprv_strlen(buffer) == (currentBufferSize - 1) && buffer[currentBufferSize-2] != '\n') {
     63                 /* Allocate more space for buffer if it didnot read the entrire line */
     64                 allocateMoreSpace = TRUE;
     65                 T_FileStream_rewind(f);
     66                 break;
     67             } else {
     68                 idx = extractFlag(buffer, currentBufferSize, tmpFlagBuffer, flagBufferSize, flagNames, numOfFlags, status);
     69                 if (U_FAILURE(*status)) {
     70                     if (*status == U_BUFFER_OVERFLOW_ERROR) {
     71                         result = currentBufferSize;
     72                     } else {
     73                         result = -1;
     74                     }
     75                     break;
     76                 } else {
     77                     if (flagNames != NULL) {
     78                         if (idx >= 0) {
     79                             uprv_strcpy(flagBuffer[idx], tmpFlagBuffer);
     80                         } else {
     81                             /* No match found.  Skip it. */
     82                             continue;
     83                         }
     84                     } else {
     85                         uprv_strcpy(flagBuffer[i++], tmpFlagBuffer);
     86                     }
     87                 }
     88             }
     89         }
     90     } while (allocateMoreSpace && U_SUCCESS(*status));
     91 
     92     uprv_free(tmpFlagBuffer);
     93     uprv_free(buffer);
     94 
     95     T_FileStream_close(f);
     96 
     97     if (U_SUCCESS(*status) && result == 0) {
     98         currentBufferSize = DEFAULT_BUFFER_SIZE;
     99     }
    100 
    101     return result;
    102 }
    103 
    104 
    105 /*
    106  * Extract the setting after the '=' and store it in flag excluding the newline character.
    107  */
    108 static int32_t extractFlag(char* buffer, int32_t bufferSize, char* flag, int32_t flagSize, const char **flagNames, int32_t numOfFlags, UErrorCode *status) {
    109     int32_t i, idx = -1;
    110     char *pBuffer;
    111     int32_t offset=0;
    112     UBool bufferWritten = FALSE;
    113 
    114     if (buffer[0] != 0) {
    115         /* Get the offset (i.e. position after the '=') */
    116         offset = getFlagOffset(buffer, bufferSize);
    117         pBuffer = buffer+offset;
    118         for(i = 0;;i++) {
    119             if (i >= flagSize) {
    120                 *status = U_BUFFER_OVERFLOW_ERROR;
    121                 return -1;
    122             }
    123             if (pBuffer[i+1] == 0) {
    124                 /* Indicates a new line character. End here. */
    125                 flag[i] = 0;
    126                 break;
    127             }
    128 
    129             flag[i] = pBuffer[i];
    130             if (i == 0) {
    131                 bufferWritten = TRUE;
    132             }
    133         }
    134     }
    135 
    136     if (!bufferWritten) {
    137         flag[0] = 0;
    138     }
    139 
    140     if (flagNames != NULL && offset>0) {
    141         offset--;  /* Move offset back 1 because of '='*/
    142         for (i = 0; i < numOfFlags; i++) {
    143             if (uprv_strncmp(buffer, flagNames[i], offset) == 0) {
    144                 idx = i;
    145                 break;
    146             }
    147         }
    148     }
    149 
    150     return idx;
    151 }
    152 
    153 /*
    154  * Get the position after the '=' character.
    155  */
    156 static int32_t getFlagOffset(const char *buffer, int32_t bufferSize) {
    157     int32_t offset = 0;
    158 
    159     for (offset = 0; offset < bufferSize;offset++) {
    160         if (buffer[offset] == '=') {
    161             offset++;
    162             break;
    163         }
    164     }
    165 
    166     if (offset == bufferSize || (offset - 1) == bufferSize) {
    167         offset = 0;
    168     }
    169 
    170     return offset;
    171 }
    172