]> git.saurik.com Git - apple/icu.git/blame - icuSources/tools/toolutil/flagparser.c
ICU-551.51.4.tar.gz
[apple/icu.git] / icuSources / tools / toolutil / flagparser.c
CommitLineData
729e4ab9 1/******************************************************************************
51004dcb 2 * Copyright (C) 2009-2012, 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) {
729e4ab9 24 char* buffer = uprv_malloc(sizeof(char) * currentBufferSize);
4388f060 25 char* tmpFlagBuffer = uprv_malloc(sizeof(char) * flagBufferSize);
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;
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) {
4388f060 48 uprv_free(tmpFlagBuffer);
729e4ab9
A
49 *status = U_MEMORY_ALLOCATION_ERROR;
50 return -1;
51 }
52 }
4388f060 53 for (i = 0; i < numOfFlags;) {
729e4ab9 54 if (T_FileStream_readLine(f, buffer, currentBufferSize) == NULL) {
4388f060 55 /* End of file reached. */
729e4ab9
A
56 break;
57 }
4388f060
A
58 if (buffer[0] == '#') {
59 continue;
60 }
729e4ab9
A
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 {
51004dcb 68 idx = extractFlag(buffer, currentBufferSize, tmpFlagBuffer, flagBufferSize, flagNames, numOfFlags, status);
729e4ab9
A
69 if (U_FAILURE(*status)) {
70 if (*status == U_BUFFER_OVERFLOW_ERROR) {
71 result = currentBufferSize;
72 } else {
73 result = -1;
74 }
75 break;
4388f060
A
76 } else {
77 if (flagNames != NULL) {
51004dcb
A
78 if (idx >= 0) {
79 uprv_strcpy(flagBuffer[idx], tmpFlagBuffer);
4388f060
A
80 } else {
81 /* No match found. Skip it. */
82 continue;
83 }
84 } else {
85 uprv_strcpy(flagBuffer[i++], tmpFlagBuffer);
86 }
729e4ab9
A
87 }
88 }
89 }
90 } while (allocateMoreSpace && U_SUCCESS(*status));
91
4388f060 92 uprv_free(tmpFlagBuffer);
729e4ab9
A
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 */
4388f060 108static int32_t extractFlag(char* buffer, int32_t bufferSize, char* flag, int32_t flagSize, const char **flagNames, int32_t numOfFlags, UErrorCode *status) {
51004dcb 109 int32_t i, idx = -1;
729e4ab9 110 char *pBuffer;
4388f060 111 int32_t offset=0;
729e4ab9
A
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;
4388f060 121 return -1;
729e4ab9
A
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 }
4388f060
A
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) {
51004dcb 144 idx = i;
4388f060
A
145 break;
146 }
147 }
148 }
149
51004dcb 150 return idx;
729e4ab9
A
151}
152
153/*
154 * Get the position after the '=' character.
155 */
156static 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}