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