]>
Commit | Line | Data |
---|---|---|
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 | ||
16 | static int32_t currentBufferSize = DEFAULT_BUFFER_SIZE; | |
17 | ||
4388f060 | 18 | static int32_t extractFlag(char* buffer, int32_t bufferSize, char* flag, int32_t flagSize, const char ** flagNames, int32_t numOfFlags, UErrorCode *status); |
729e4ab9 A |
19 | static 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 | */ | |
24 | U_CAPI int32_t U_EXPORT2 | |
4388f060 | 25 | parseFlagsFile(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 | 96 | parseFlagsFile_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 | 117 | static 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 | */ | |
165 | static 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 | } |