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