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