tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

flagparser.cpp (5676B)


      1 // © 2016 and later: Unicode, Inc. and others.
      2 // License & terms of use: http://www.unicode.org/copyright.html
      3 /******************************************************************************
      4 *   Copyright (C) 2009-2015, International Business Machines
      5 *   Corporation and others.  All Rights Reserved.
      6 *******************************************************************************
      7 */
      8 
      9 #include "flagparser.h"
     10 #include "filestrm.h"
     11 #include "cstring.h"
     12 #include "cmemory.h"
     13 
     14 #define DEFAULT_BUFFER_SIZE 512
     15 
     16 static int32_t currentBufferSize = DEFAULT_BUFFER_SIZE;
     17 
     18 static int32_t extractFlag(char* buffer, int32_t bufferSize, char* flag, int32_t flagSize, const char ** flagNames, int32_t numOfFlags, UErrorCode *status);
     19 static int32_t getFlagOffset(const char *buffer, int32_t bufferSize);
     20 
     21 /*
     22 * Opens the given fileName and reads in the information storing the data in flagBuffer.
     23 */
     24 U_CAPI int32_t U_EXPORT2
     25 parseFlagsFile(const char *fileName, char **flagBuffer, int32_t flagBufferSize, const char ** flagNames, int32_t numOfFlags, UErrorCode *status) {
     26    char* buffer = nullptr;
     27    char* tmpFlagBuffer = nullptr;
     28    UBool allocateMoreSpace = false;
     29    int32_t idx, i;
     30    int32_t result = 0;
     31 
     32    FileStream *f = T_FileStream_open(fileName, "r");
     33    if (f == nullptr) {
     34        *status = U_FILE_ACCESS_ERROR;
     35        goto parseFlagsFile_cleanup;
     36    }
     37 
     38    buffer = (char *)uprv_malloc(sizeof(char) * currentBufferSize);
     39    tmpFlagBuffer = (char *)uprv_malloc(sizeof(char) * flagBufferSize);
     40 
     41    if (buffer == nullptr || tmpFlagBuffer == nullptr) {
     42        *status = U_MEMORY_ALLOCATION_ERROR;
     43        goto parseFlagsFile_cleanup;
     44    }
     45 
     46    do {
     47        if (allocateMoreSpace) {
     48            allocateMoreSpace = false;
     49            currentBufferSize *= 2;
     50            uprv_free(buffer);
     51            buffer = (char *)uprv_malloc(sizeof(char) * currentBufferSize);
     52            if (buffer == nullptr) {
     53                *status = U_MEMORY_ALLOCATION_ERROR;
     54                goto parseFlagsFile_cleanup;
     55            }
     56        }
     57        for (i = 0; i < numOfFlags;) {
     58            if (T_FileStream_readLine(f, buffer, currentBufferSize) == nullptr) {
     59                /* End of file reached. */
     60                break;
     61            }
     62            if (buffer[0] == '#') {
     63                continue;
     64            }
     65 
     66            if ((int32_t)uprv_strlen(buffer) == (currentBufferSize - 1) && buffer[currentBufferSize-2] != '\n') {
     67                /* Allocate more space for buffer if it did not read the entire line */
     68                allocateMoreSpace = true;
     69                T_FileStream_rewind(f);
     70                break;
     71            } else {
     72                idx = extractFlag(buffer, currentBufferSize, tmpFlagBuffer, flagBufferSize, flagNames, numOfFlags, status);
     73                if (U_FAILURE(*status)) {
     74                    if (*status == U_BUFFER_OVERFLOW_ERROR) {
     75                        result = currentBufferSize;
     76                    } else {
     77                        result = -1;
     78                    }
     79                    break;
     80                } else {
     81                    if (flagNames != nullptr) {
     82                        if (idx >= 0) {
     83                            uprv_strcpy(flagBuffer[idx], tmpFlagBuffer);
     84                        } else {
     85                            /* No match found.  Skip it. */
     86                            continue;
     87                        }
     88                    } else {
     89                        uprv_strcpy(flagBuffer[i++], tmpFlagBuffer);
     90                    }
     91                }
     92            }
     93        }
     94    } while (allocateMoreSpace && U_SUCCESS(*status));
     95 
     96 parseFlagsFile_cleanup:
     97    uprv_free(tmpFlagBuffer);
     98    uprv_free(buffer);
     99 
    100    T_FileStream_close(f);
    101    
    102    if (U_FAILURE(*status) && *status != U_BUFFER_OVERFLOW_ERROR) {
    103        return -1;
    104    }
    105 
    106    if (U_SUCCESS(*status) && result == 0) {
    107        currentBufferSize = DEFAULT_BUFFER_SIZE;
    108    }
    109 
    110    return result;
    111 }
    112 
    113 
    114 /*
    115 * Extract the setting after the '=' and store it in flag excluding the newline character.
    116 */
    117 static int32_t extractFlag(char* buffer, int32_t bufferSize, char* flag, int32_t flagSize, const char **flagNames, int32_t numOfFlags, UErrorCode *status) {
    118    int32_t i, idx = -1;
    119    char *pBuffer;
    120    int32_t offset=0;
    121    UBool bufferWritten = false;
    122 
    123    if (buffer[0] != 0) {
    124        /* Get the offset (i.e. position after the '=') */
    125        offset = getFlagOffset(buffer, bufferSize);
    126        pBuffer = buffer+offset;
    127        for(i = 0;;i++) {
    128            if (i >= flagSize) {
    129                *status = U_BUFFER_OVERFLOW_ERROR;
    130                return -1;
    131            }
    132            if (pBuffer[i+1] == 0) {
    133                /* Indicates a new line character. End here. */
    134                flag[i] = 0;
    135                break;
    136            }
    137 
    138            flag[i] = pBuffer[i];
    139            if (i == 0) {
    140                bufferWritten = true;
    141            }
    142        }
    143    }
    144 
    145    if (!bufferWritten) {
    146        flag[0] = 0;
    147    }
    148 
    149    if (flagNames != nullptr && offset>0) {
    150        offset--;  /* Move offset back 1 because of '='*/
    151        for (i = 0; i < numOfFlags; i++) {
    152            if (uprv_strncmp(buffer, flagNames[i], offset) == 0) {
    153                idx = i;
    154                break;
    155            }
    156        }
    157    }
    158 
    159    return idx;
    160 }
    161 
    162 /*
    163 * Get the position after the '=' character.
    164 */
    165 static int32_t getFlagOffset(const char *buffer, int32_t bufferSize) {
    166    int32_t offset = 0;
    167 
    168    for (offset = 0; offset < bufferSize;offset++) {
    169        if (buffer[offset] == '=') {
    170            offset++;
    171            break;
    172        }
    173    }
    174 
    175    if (offset == bufferSize || (offset - 1) == bufferSize) {
    176        offset = 0;
    177    }
    178 
    179    return offset;
    180 }