1 /*
2 * Copyright 2017 Rockchip Electronics Co. LTD
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include <stdio.h>
18 #include <string.h>
19
20 #include "mpp_parse_cfg.h"
21
22 #include "mpp_log.h"
23
24 #define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
25
26 enum CONFIG_TYPE {
27 CONFIG_TYPE_OPTION,
28 CONFIG_TYPE_EVENT,
29
30 OPT_TYPE_INDEX_TYPE,
31 OPT_TYPE_LOOP_NUM,
32
33 IDX_TYPE_FRM_NUM,
34 IDX_TYPE_MSEC,
35 };
36
37 struct options_table {
38 int type;
39 const char *type_str;
40 };
41
42 /* table for converting string to type */
43 static struct options_table op_tbl[] = {
44 {CONFIG_TYPE_OPTION, "[CONFIG]"},
45 {CONFIG_TYPE_EVENT, "[EVENT]"},
46
47 {OPT_TYPE_INDEX_TYPE, "index"},
48 {OPT_TYPE_LOOP_NUM, "loop"},
49
50 {IDX_TYPE_FRM_NUM, "frm"},
51 {IDX_TYPE_MSEC, "msec"},
52 };
53
54 struct cfg_file {
55 FILE *file;
56 char cache[128];
57 RK_S32 cache_on;
58 };
59
60 /* get rid of leading and following space from string */
string_trim(char * string)61 static char *string_trim(char *string)
62 {
63 char *p = string;
64 long len;
65
66 if (string == NULL)
67 return NULL;
68
69 while (*p == ' ')
70 p++;
71
72 len = strlen(p);
73
74 while (p[len - 1] == ' ')
75 len--;
76 p[len] = '\0';
77
78 return p;
79 }
80
read_cfg_line(struct cfg_file * cfg)81 static char *read_cfg_line(struct cfg_file *cfg)
82 {
83 int ch;
84 int i;
85
86 while (!cfg->cache_on) {
87 i = 0;
88
89 while (1) {
90 ch = fgetc(cfg->file);
91 if (i == 0 && ch == EOF)
92 return NULL;
93 else if (ch == EOF || feof(cfg->file) || ch == '\n')
94 break;
95
96 cfg->cache[i++] = ch;
97 }
98 cfg->cache[i] = '\0';
99
100 /* a note, ignore and get the next line */
101 if (cfg->cache[0] != '#')
102 break;
103 }
104
105 cfg->cache_on = 1;
106 return string_trim(cfg->cache);
107 }
108
invalid_cfg_cache(struct cfg_file * cfg)109 static inline void invalid_cfg_cache(struct cfg_file *cfg)
110 {
111 cfg->cache_on = 0;
112 }
113
get_opt_value(char * line)114 static char *get_opt_value(char *line)
115 {
116 size_t i;
117
118 for (i = 0; i < strlen(line); ++i) {
119 if (line[i] == ':')
120 return string_trim(&line[i + 1]);
121 }
122
123 return NULL;
124 }
125
126 /* convert string to index by look up map table */
lookup_opt_type(char * line)127 static int lookup_opt_type(char *line)
128 {
129 size_t i;
130
131 for (i = 0; i < ARRAY_SIZE(op_tbl); ++i) {
132 if (!strncmp(op_tbl[i].type_str, line,
133 strlen(op_tbl[i].type_str))) {
134 mpp_log("option type %s find\n", op_tbl[i].type_str);
135 return op_tbl[i].type;
136 }
137 }
138
139 return -1;
140 }
141
scan_event_line(struct cfg_file * cfg,struct rc_event * event)142 static int scan_event_line(struct cfg_file *cfg, struct rc_event *event)
143 {
144 char *line = read_cfg_line(cfg);
145
146 if (line != NULL && line[0] != '\n' && line[0] != '[') {
147 sscanf(line, "%d\t%d\t%f",
148 &event->idx, &event->bps, &event->fps);
149 mpp_log("idx: %d, bps %u, fps: %f\n",
150 event->idx, event->bps, event->fps);
151 invalid_cfg_cache(cfg);
152 } else {
153 return -1;
154 }
155
156 return 0;
157 }
158
parse_events(struct cfg_file * cfg,struct rc_test_config * ea)159 static int parse_events(struct cfg_file *cfg, struct rc_test_config *ea)
160 {
161 int ret;
162 int i;
163
164 for (i = 0; i < 128; ++i) {
165 ret = scan_event_line(cfg, &ea->event[i]);
166 if (ret < 0) {
167 ea->event_cnt = i;
168 break;
169 }
170 }
171
172 return 0;
173 }
174
parse_options(struct cfg_file * cfg,struct rc_test_config * ea)175 static int parse_options(struct cfg_file *cfg, struct rc_test_config *ea)
176 {
177 char *opt;
178 int type;
179
180 while (1) {
181 opt = read_cfg_line(cfg);
182
183 if (opt && opt[0] != '\n' && opt[0] != '[') {
184 type = lookup_opt_type(opt);
185
186 switch (type) {
187 case OPT_TYPE_INDEX_TYPE:
188 ea->idx_type = lookup_opt_type(get_opt_value(opt));
189 break;
190 case OPT_TYPE_LOOP_NUM:
191 sscanf(get_opt_value(opt), "%d", &ea->loop);
192 mpp_log("loop num: %d\n", ea->loop);
193 break;
194 default:
195 break;
196 }
197
198 invalid_cfg_cache(cfg);
199 } else {
200 break;
201 }
202 }
203 return 0;
204 }
205
mpp_parse_config(char * cfg_url,struct rc_test_config * ea)206 int mpp_parse_config(char *cfg_url, struct rc_test_config *ea)
207 {
208 struct cfg_file cfg;
209
210 if (cfg_url == NULL || strlen(cfg_url) == 0) {
211 mpp_err("invalid input config url\n");
212 return -1;
213 }
214
215 cfg.file = fopen(cfg_url, "rb");
216 if (cfg.file == NULL) {
217 mpp_err("fopen %s failed\n", cfg_url);
218 return -1;
219 }
220 cfg.cache_on = 0;
221
222 while (1) {
223 char *line = read_cfg_line(&cfg);
224
225 if (!line)
226 break;
227
228 invalid_cfg_cache(&cfg);
229 if (line[0] == '[') {
230 int type = lookup_opt_type(line);
231
232 switch (type) {
233 case CONFIG_TYPE_EVENT:
234 parse_events(&cfg, ea);
235 break;
236 case CONFIG_TYPE_OPTION:
237 parse_options(&cfg, ea);
238 break;
239 default:
240 mpp_err("invalid config type find\n");
241 fclose(cfg.file);
242 return -1;
243 }
244 }
245 }
246
247 fclose(cfg.file);
248
249 return 0;
250 }
251
252 #ifdef PARSE_CONFIG_TEST
main(int argc,char ** argv)253 int main(int argc, char **argv)
254 {
255 struct rc_test_config event_array;
256
257 if (argc < 2) {
258 mpp_err("invalid input argument\n");
259 return -1;
260 }
261
262 mpp_parse_config(argv[1], &event_array);
263
264 return 0;
265 }
266 #endif
267