1 /******************************************************************************
2 * Copyright (C) 2009-2015, International Business Machines
3 * Corporation and others. All Rights Reserved.
4 *******************************************************************************
7 #include "flagparser.h"
12 #define DEFAULT_BUFFER_SIZE 512
14 static int32_t currentBufferSize
= DEFAULT_BUFFER_SIZE
;
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
);
20 * Opens the given fileName and reads in the information storing the data in flagBuffer.
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
) {
25 char* tmpFlagBuffer
= NULL
;
26 UBool allocateMoreSpace
= FALSE
;
30 FileStream
*f
= T_FileStream_open(fileName
, "r");
32 *status
= U_FILE_ACCESS_ERROR
;
33 goto parseFlagsFile_cleanup
;
36 buffer
= uprv_malloc(sizeof(char) * currentBufferSize
);
37 tmpFlagBuffer
= uprv_malloc(sizeof(char) * flagBufferSize
);
39 if (buffer
== NULL
|| tmpFlagBuffer
== NULL
) {
40 *status
= U_MEMORY_ALLOCATION_ERROR
;
41 goto parseFlagsFile_cleanup
;
45 if (allocateMoreSpace
) {
46 allocateMoreSpace
= FALSE
;
47 currentBufferSize
*= 2;
49 buffer
= uprv_malloc(sizeof(char) * currentBufferSize
);
51 *status
= U_MEMORY_ALLOCATION_ERROR
;
52 goto parseFlagsFile_cleanup
;
55 for (i
= 0; i
< numOfFlags
;) {
56 if (T_FileStream_readLine(f
, buffer
, currentBufferSize
) == NULL
) {
57 /* End of file reached. */
60 if (buffer
[0] == '#') {
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
);
70 idx
= extractFlag(buffer
, currentBufferSize
, tmpFlagBuffer
, flagBufferSize
, flagNames
, numOfFlags
, status
);
71 if (U_FAILURE(*status
)) {
72 if (*status
== U_BUFFER_OVERFLOW_ERROR
) {
73 result
= currentBufferSize
;
79 if (flagNames
!= NULL
) {
81 uprv_strcpy(flagBuffer
[idx
], tmpFlagBuffer
);
83 /* No match found. Skip it. */
87 uprv_strcpy(flagBuffer
[i
++], tmpFlagBuffer
);
92 } while (allocateMoreSpace
&& U_SUCCESS(*status
));
94 parseFlagsFile_cleanup
:
95 uprv_free(tmpFlagBuffer
);
98 T_FileStream_close(f
);
100 if (U_FAILURE(*status
) && *status
!= U_BUFFER_OVERFLOW_ERROR
) {
104 if (U_SUCCESS(*status
) && result
== 0) {
105 currentBufferSize
= DEFAULT_BUFFER_SIZE
;
113 * Extract the setting after the '=' and store it in flag excluding the newline character.
115 static int32_t extractFlag(char* buffer
, int32_t bufferSize
, char* flag
, int32_t flagSize
, const char **flagNames
, int32_t numOfFlags
, UErrorCode
*status
) {
119 UBool bufferWritten
= FALSE
;
121 if (buffer
[0] != 0) {
122 /* Get the offset (i.e. position after the '=') */
123 offset
= getFlagOffset(buffer
, bufferSize
);
124 pBuffer
= buffer
+offset
;
127 *status
= U_BUFFER_OVERFLOW_ERROR
;
130 if (pBuffer
[i
+1] == 0) {
131 /* Indicates a new line character. End here. */
136 flag
[i
] = pBuffer
[i
];
138 bufferWritten
= TRUE
;
143 if (!bufferWritten
) {
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) {
161 * Get the position after the '=' character.
163 static int32_t getFlagOffset(const char *buffer
, int32_t bufferSize
) {
166 for (offset
= 0; offset
< bufferSize
;offset
++) {
167 if (buffer
[offset
] == '=') {
173 if (offset
== bufferSize
|| (offset
- 1) == bufferSize
) {