• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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