1 // Copyright (C) 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 *******************************************************************************
9 #include "flagparser.h"
14 #define DEFAULT_BUFFER_SIZE 512
16 static int32_t currentBufferSize = DEFAULT_BUFFER_SIZE;
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);
22 * Opens the given fileName and reads in the information storing the data in flagBuffer.
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) {
27 char* tmpFlagBuffer = NULL;
28 UBool allocateMoreSpace = FALSE;
32 FileStream *f = T_FileStream_open(fileName, "r");
34 *status = U_FILE_ACCESS_ERROR;
35 goto parseFlagsFile_cleanup;
38 buffer = uprv_malloc(sizeof(char) * currentBufferSize);
39 tmpFlagBuffer = uprv_malloc(sizeof(char) * flagBufferSize);
41 if (buffer == NULL || tmpFlagBuffer == NULL) {
42 *status = U_MEMORY_ALLOCATION_ERROR;
43 goto parseFlagsFile_cleanup;
47 if (allocateMoreSpace) {
48 allocateMoreSpace = FALSE;
49 currentBufferSize *= 2;
51 buffer = uprv_malloc(sizeof(char) * currentBufferSize);
53 *status = U_MEMORY_ALLOCATION_ERROR;
54 goto parseFlagsFile_cleanup;
57 for (i = 0; i < numOfFlags;) {
58 if (T_FileStream_readLine(f, buffer, currentBufferSize) == NULL) {
59 /* End of file reached. */
62 if (buffer[0] == '#') {
66 if ((int32_t)uprv_strlen(buffer) == (currentBufferSize - 1) && buffer[currentBufferSize-2] != '\n') {
67 /* Allocate more space for buffer if it didnot read the entrire line */
68 allocateMoreSpace = TRUE;
69 T_FileStream_rewind(f);
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;
81 if (flagNames != NULL) {
83 uprv_strcpy(flagBuffer[idx], tmpFlagBuffer);
85 /* No match found. Skip it. */
89 uprv_strcpy(flagBuffer[i++], tmpFlagBuffer);
94 } while (allocateMoreSpace && U_SUCCESS(*status));
96 parseFlagsFile_cleanup:
97 uprv_free(tmpFlagBuffer);
100 T_FileStream_close(f);
102 if (U_FAILURE(*status) && *status != U_BUFFER_OVERFLOW_ERROR) {
106 if (U_SUCCESS(*status) && result == 0) {
107 currentBufferSize = DEFAULT_BUFFER_SIZE;
115 * Extract the setting after the '=' and store it in flag excluding the newline character.
117 static int32_t extractFlag(char* buffer, int32_t bufferSize, char* flag, int32_t flagSize, const char **flagNames, int32_t numOfFlags, UErrorCode *status) {
121 UBool bufferWritten = FALSE;
123 if (buffer[0] != 0) {
124 /* Get the offset (i.e. position after the '=') */
125 offset = getFlagOffset(buffer, bufferSize);
126 pBuffer = buffer+offset;
129 *status = U_BUFFER_OVERFLOW_ERROR;
132 if (pBuffer[i+1] == 0) {
133 /* Indicates a new line character. End here. */
138 flag[i] = pBuffer[i];
140 bufferWritten = TRUE;
145 if (!bufferWritten) {
149 if (flagNames != NULL && 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) {
163 * Get the position after the '=' character.
165 static int32_t getFlagOffset(const char *buffer, int32_t bufferSize) {
168 for (offset = 0; offset < bufferSize;offset++) {
169 if (buffer[offset] == '=') {
175 if (offset == bufferSize || (offset - 1) == bufferSize) {