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