1 // © 2016 and later: Unicode, Inc. and others.
2 // License & terms of use: http://www.unicode.org/copyright.html
3 /******************************************************************************
4 * Copyright (C) 2009-2015, International Business Machines
5 * Corporation and others. All Rights Reserved.
6 *******************************************************************************
9 #include "flagparser.h"
14 #define DEFAULT_BUFFER_SIZE 512
16 static int32_t currentBufferSize
= DEFAULT_BUFFER_SIZE
;
18 static int32_t extractFlag(char* buffer
, int32_t bufferSize
, char* flag
, int32_t flagSize
, const char ** flagNames
, int32_t numOfFlags
, UErrorCode
*status
);
19 static int32_t getFlagOffset(const char *buffer
, int32_t bufferSize
);
22 * Opens the given fileName and reads in the information storing the data in flagBuffer.
24 U_CAPI
int32_t U_EXPORT2
25 parseFlagsFile(const char *fileName
, char **flagBuffer
, int32_t flagBufferSize
, const char ** flagNames
, int32_t numOfFlags
, UErrorCode
*status
) {
27 char* tmpFlagBuffer
= NULL
;
28 UBool allocateMoreSpace
= FALSE
;
32 FileStream
*f
= T_FileStream_open(fileName
, "r");
34 *status
= U_FILE_ACCESS_ERROR
;
35 goto parseFlagsFile_cleanup
;
38 buffer
= (char *)uprv_malloc(sizeof(char) * currentBufferSize
);
39 tmpFlagBuffer
= (char *)uprv_malloc(sizeof(char) * flagBufferSize
);
41 if (buffer
== NULL
|| tmpFlagBuffer
== NULL
) {
42 *status
= U_MEMORY_ALLOCATION_ERROR
;
43 goto parseFlagsFile_cleanup
;
47 if (allocateMoreSpace
) {
48 allocateMoreSpace
= FALSE
;
49 currentBufferSize
*= 2;
51 buffer
= (char *)uprv_malloc(sizeof(char) * currentBufferSize
);
53 *status
= U_MEMORY_ALLOCATION_ERROR
;
54 goto parseFlagsFile_cleanup
;
57 for (i
= 0; i
< numOfFlags
;) {
58 if (T_FileStream_readLine(f
, buffer
, currentBufferSize
) == NULL
) {
59 /* End of file reached. */
62 if (buffer
[0] == '#') {
66 if ((int32_t)uprv_strlen(buffer
) == (currentBufferSize
- 1) && buffer
[currentBufferSize
-2] != '\n') {
67 /* Allocate more space for buffer if it didnot read the entrire line */
68 allocateMoreSpace
= TRUE
;
69 T_FileStream_rewind(f
);
72 idx
= extractFlag(buffer
, currentBufferSize
, tmpFlagBuffer
, flagBufferSize
, flagNames
, numOfFlags
, status
);
73 if (U_FAILURE(*status
)) {
74 if (*status
== U_BUFFER_OVERFLOW_ERROR
) {
75 result
= currentBufferSize
;
81 if (flagNames
!= NULL
) {
83 uprv_strcpy(flagBuffer
[idx
], tmpFlagBuffer
);
85 /* No match found. Skip it. */
89 uprv_strcpy(flagBuffer
[i
++], tmpFlagBuffer
);
94 } while (allocateMoreSpace
&& U_SUCCESS(*status
));
96 parseFlagsFile_cleanup
:
97 uprv_free(tmpFlagBuffer
);
100 T_FileStream_close(f
);
102 if (U_FAILURE(*status
) && *status
!= U_BUFFER_OVERFLOW_ERROR
) {
106 if (U_SUCCESS(*status
) && result
== 0) {
107 currentBufferSize
= DEFAULT_BUFFER_SIZE
;
115 * Extract the setting after the '=' and store it in flag excluding the newline character.
117 static int32_t extractFlag(char* buffer
, int32_t bufferSize
, char* flag
, int32_t flagSize
, const char **flagNames
, int32_t numOfFlags
, UErrorCode
*status
) {
121 UBool bufferWritten
= FALSE
;
123 if (buffer
[0] != 0) {
124 /* Get the offset (i.e. position after the '=') */
125 offset
= getFlagOffset(buffer
, bufferSize
);
126 pBuffer
= buffer
+offset
;
129 *status
= U_BUFFER_OVERFLOW_ERROR
;
132 if (pBuffer
[i
+1] == 0) {
133 /* Indicates a new line character. End here. */
138 flag
[i
] = pBuffer
[i
];
140 bufferWritten
= TRUE
;
145 if (!bufferWritten
) {
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) {
163 * Get the position after the '=' character.
165 static int32_t getFlagOffset(const char *buffer
, int32_t bufferSize
) {
168 for (offset
= 0; offset
< bufferSize
;offset
++) {
169 if (buffer
[offset
] == '=') {
175 if (offset
== bufferSize
|| (offset
- 1) == bufferSize
) {