]> git.saurik.com Git - apple/icu.git/blame - icuSources/tools/toolutil/flagparser.c
ICU-57131.0.1.tar.gz
[apple/icu.git] / icuSources / tools / toolutil / flagparser.c
CommitLineData
729e4ab9 1/******************************************************************************
2ca993e8 2 * Copyright (C) 2009-2015, International Business Machines
729e4ab9
A
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
14static int32_t currentBufferSize = DEFAULT_BUFFER_SIZE;
15
4388f060 16static int32_t extractFlag(char* buffer, int32_t bufferSize, char* flag, int32_t flagSize, const char ** flagNames, int32_t numOfFlags, UErrorCode *status);
729e4ab9
A
17static 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 */
22U_CAPI int32_t U_EXPORT2
4388f060 23parseFlagsFile(const char *fileName, char **flagBuffer, int32_t flagBufferSize, const char ** flagNames, int32_t numOfFlags, UErrorCode *status) {
2ca993e8
A
24 char* buffer = NULL;
25 char* tmpFlagBuffer = NULL;
729e4ab9 26 UBool allocateMoreSpace = FALSE;
51004dcb 27 int32_t idx, i;
729e4ab9
A
28 int32_t result = 0;
29
30 FileStream *f = T_FileStream_open(fileName, "r");
31 if (f == NULL) {
32 *status = U_FILE_ACCESS_ERROR;
2ca993e8 33 goto parseFlagsFile_cleanup;
729e4ab9 34 }
2ca993e8
A
35
36 buffer = uprv_malloc(sizeof(char) * currentBufferSize);
37 tmpFlagBuffer = uprv_malloc(sizeof(char) * flagBufferSize);
729e4ab9 38
2ca993e8 39 if (buffer == NULL || tmpFlagBuffer == NULL) {
729e4ab9 40 *status = U_MEMORY_ALLOCATION_ERROR;
2ca993e8 41 goto parseFlagsFile_cleanup;
729e4ab9
A
42 }
43
44 do {
45 if (allocateMoreSpace) {
46 allocateMoreSpace = FALSE;
47 currentBufferSize *= 2;
48 uprv_free(buffer);
49 buffer = uprv_malloc(sizeof(char) * currentBufferSize);
50 if (buffer == NULL) {
51 *status = U_MEMORY_ALLOCATION_ERROR;
2ca993e8 52 goto parseFlagsFile_cleanup;
729e4ab9
A
53 }
54 }
4388f060 55 for (i = 0; i < numOfFlags;) {
729e4ab9 56 if (T_FileStream_readLine(f, buffer, currentBufferSize) == NULL) {
4388f060 57 /* End of file reached. */
729e4ab9
A
58 break;
59 }
4388f060
A
60 if (buffer[0] == '#') {
61 continue;
62 }
729e4ab9
A
63
64 if (uprv_strlen(buffer) == (currentBufferSize - 1) && buffer[currentBufferSize-2] != '\n') {
65 /* Allocate more space for buffer if it didnot read the entrire line */
66 allocateMoreSpace = TRUE;
67 T_FileStream_rewind(f);
68 break;
69 } else {
51004dcb 70 idx = extractFlag(buffer, currentBufferSize, tmpFlagBuffer, flagBufferSize, flagNames, numOfFlags, status);
729e4ab9
A
71 if (U_FAILURE(*status)) {
72 if (*status == U_BUFFER_OVERFLOW_ERROR) {
73 result = currentBufferSize;
74 } else {
75 result = -1;
76 }
77 break;
4388f060
A
78 } else {
79 if (flagNames != NULL) {
51004dcb
A
80 if (idx >= 0) {
81 uprv_strcpy(flagBuffer[idx], tmpFlagBuffer);
4388f060
A
82 } else {
83 /* No match found. Skip it. */
84 continue;
85 }
86 } else {
87 uprv_strcpy(flagBuffer[i++], tmpFlagBuffer);
88 }
729e4ab9
A
89 }
90 }
91 }
92 } while (allocateMoreSpace && U_SUCCESS(*status));
93
2ca993e8 94parseFlagsFile_cleanup:
4388f060 95 uprv_free(tmpFlagBuffer);
729e4ab9
A
96 uprv_free(buffer);
97
98 T_FileStream_close(f);
2ca993e8
A
99
100 if (U_FAILURE(*status) && *status != U_BUFFER_OVERFLOW_ERROR) {
101 return -1;
102 }
729e4ab9
A
103
104 if (U_SUCCESS(*status) && result == 0) {
105 currentBufferSize = DEFAULT_BUFFER_SIZE;
106 }
107
108 return result;
109}
110
111
112/*
113 * Extract the setting after the '=' and store it in flag excluding the newline character.
114 */
4388f060 115static int32_t extractFlag(char* buffer, int32_t bufferSize, char* flag, int32_t flagSize, const char **flagNames, int32_t numOfFlags, UErrorCode *status) {
51004dcb 116 int32_t i, idx = -1;
729e4ab9 117 char *pBuffer;
4388f060 118 int32_t offset=0;
729e4ab9
A
119 UBool bufferWritten = FALSE;
120
121 if (buffer[0] != 0) {
122 /* Get the offset (i.e. position after the '=') */
123 offset = getFlagOffset(buffer, bufferSize);
124 pBuffer = buffer+offset;
125 for(i = 0;;i++) {
126 if (i >= flagSize) {
127 *status = U_BUFFER_OVERFLOW_ERROR;
4388f060 128 return -1;
729e4ab9
A
129 }
130 if (pBuffer[i+1] == 0) {
131 /* Indicates a new line character. End here. */
132 flag[i] = 0;
133 break;
134 }
135
136 flag[i] = pBuffer[i];
137 if (i == 0) {
138 bufferWritten = TRUE;
139 }
140 }
141 }
142
143 if (!bufferWritten) {
144 flag[0] = 0;
145 }
4388f060
A
146
147 if (flagNames != NULL && offset>0) {
148 offset--; /* Move offset back 1 because of '='*/
149 for (i = 0; i < numOfFlags; i++) {
150 if (uprv_strncmp(buffer, flagNames[i], offset) == 0) {
51004dcb 151 idx = i;
4388f060
A
152 break;
153 }
154 }
155 }
156
51004dcb 157 return idx;
729e4ab9
A
158}
159
160/*
161 * Get the position after the '=' character.
162 */
163static int32_t getFlagOffset(const char *buffer, int32_t bufferSize) {
164 int32_t offset = 0;
165
166 for (offset = 0; offset < bufferSize;offset++) {
167 if (buffer[offset] == '=') {
168 offset++;
169 break;
170 }
171 }
172
173 if (offset == bufferSize || (offset - 1) == bufferSize) {
174 offset = 0;
175 }
176
177 return offset;
178}