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