]> git.saurik.com Git - apple/icu.git/blame - icuSources/tools/toolutil/flagparser.cpp
ICU-66108.tar.gz
[apple/icu.git] / icuSources / tools / toolutil / flagparser.cpp
CommitLineData
f3c0d7a5
A
1// © 2016 and later: Unicode, Inc. and others.
2// License & terms of use: http://www.unicode.org/copyright.html
729e4ab9 3/******************************************************************************
2ca993e8 4 * Copyright (C) 2009-2015, International Business Machines
729e4ab9
A
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
16static int32_t currentBufferSize = DEFAULT_BUFFER_SIZE;
17
4388f060 18static int32_t extractFlag(char* buffer, int32_t bufferSize, char* flag, int32_t flagSize, const char ** flagNames, int32_t numOfFlags, UErrorCode *status);
729e4ab9
A
19static 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 */
24U_CAPI int32_t U_EXPORT2
4388f060 25parseFlagsFile(const char *fileName, char **flagBuffer, int32_t flagBufferSize, const char ** flagNames, int32_t numOfFlags, UErrorCode *status) {
2ca993e8
A
26 char* buffer = NULL;
27 char* tmpFlagBuffer = NULL;
729e4ab9 28 UBool allocateMoreSpace = FALSE;
51004dcb 29 int32_t idx, i;
729e4ab9
A
30 int32_t result = 0;
31
32 FileStream *f = T_FileStream_open(fileName, "r");
33 if (f == NULL) {
34 *status = U_FILE_ACCESS_ERROR;
2ca993e8 35 goto parseFlagsFile_cleanup;
729e4ab9 36 }
f3c0d7a5
A
37
38 buffer = (char *)uprv_malloc(sizeof(char) * currentBufferSize);
39 tmpFlagBuffer = (char *)uprv_malloc(sizeof(char) * flagBufferSize);
729e4ab9 40
2ca993e8 41 if (buffer == NULL || tmpFlagBuffer == NULL) {
729e4ab9 42 *status = U_MEMORY_ALLOCATION_ERROR;
2ca993e8 43 goto parseFlagsFile_cleanup;
729e4ab9
A
44 }
45
46 do {
47 if (allocateMoreSpace) {
48 allocateMoreSpace = FALSE;
49 currentBufferSize *= 2;
50 uprv_free(buffer);
f3c0d7a5 51 buffer = (char *)uprv_malloc(sizeof(char) * currentBufferSize);
729e4ab9
A
52 if (buffer == NULL) {
53 *status = U_MEMORY_ALLOCATION_ERROR;
2ca993e8 54 goto parseFlagsFile_cleanup;
729e4ab9
A
55 }
56 }
4388f060 57 for (i = 0; i < numOfFlags;) {
729e4ab9 58 if (T_FileStream_readLine(f, buffer, currentBufferSize) == NULL) {
4388f060 59 /* End of file reached. */
729e4ab9
A
60 break;
61 }
4388f060
A
62 if (buffer[0] == '#') {
63 continue;
64 }
729e4ab9 65
f3c0d7a5 66 if ((int32_t)uprv_strlen(buffer) == (currentBufferSize - 1) && buffer[currentBufferSize-2] != '\n') {
729e4ab9
A
67 /* Allocate more space for buffer if it didnot read the entrire line */
68 allocateMoreSpace = TRUE;
69 T_FileStream_rewind(f);
70 break;
71 } else {
51004dcb 72 idx = extractFlag(buffer, currentBufferSize, tmpFlagBuffer, flagBufferSize, flagNames, numOfFlags, status);
729e4ab9
A
73 if (U_FAILURE(*status)) {
74 if (*status == U_BUFFER_OVERFLOW_ERROR) {
75 result = currentBufferSize;
76 } else {
77 result = -1;
78 }
79 break;
4388f060
A
80 } else {
81 if (flagNames != NULL) {
51004dcb
A
82 if (idx >= 0) {
83 uprv_strcpy(flagBuffer[idx], tmpFlagBuffer);
4388f060
A
84 } else {
85 /* No match found. Skip it. */
86 continue;
87 }
88 } else {
89 uprv_strcpy(flagBuffer[i++], tmpFlagBuffer);
90 }
729e4ab9
A
91 }
92 }
93 }
94 } while (allocateMoreSpace && U_SUCCESS(*status));
95
2ca993e8 96parseFlagsFile_cleanup:
4388f060 97 uprv_free(tmpFlagBuffer);
729e4ab9
A
98 uprv_free(buffer);
99
100 T_FileStream_close(f);
2ca993e8
A
101
102 if (U_FAILURE(*status) && *status != U_BUFFER_OVERFLOW_ERROR) {
103 return -1;
104 }
729e4ab9
A
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 */
4388f060 117static int32_t extractFlag(char* buffer, int32_t bufferSize, char* flag, int32_t flagSize, const char **flagNames, int32_t numOfFlags, UErrorCode *status) {
51004dcb 118 int32_t i, idx = -1;
729e4ab9 119 char *pBuffer;
4388f060 120 int32_t offset=0;
729e4ab9
A
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;
4388f060 130 return -1;
729e4ab9
A
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 }
4388f060
A
148
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) {
51004dcb 153 idx = i;
4388f060
A
154 break;
155 }
156 }
157 }
158
51004dcb 159 return idx;
729e4ab9
A
160}
161
162/*
163 * Get the position after the '=' character.
164 */
165static 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}