blob: b5254b150a96abadab440c15d1962cfc87c7f8b0 [file] [log] [blame]
rjw1f884582022-01-06 17:20:42 +08001#include "AudioParamParserPriv.h"
2
3EXPORT ParamTreeView *paramTreeViewCreate(AudioType *audioType, int verMaj, int verMin)
4{
5 ParamTreeView *paramTreeView = malloc(sizeof(ParamTreeView));
6 paramTreeView->audioType = audioType;
7 paramTreeView->verMaj = verMaj;
8 paramTreeView->verMin = verMin;
9 paramTreeView->treeRootHash = NULL;
10 return paramTreeView;
11}
12
13EXPORT void paramTreeViewRelease(ParamTreeView *paramTreeView)
14{
15 if (paramTreeView)
16 {
17 if (paramTreeView->treeRootHash)
18 {
19 TreeRoot *tmp, *item;
20 HASH_ITER(hh, paramTreeView->treeRootHash, item, tmp)
21 {
22 HASH_DEL(paramTreeView->treeRootHash, item);
23 treeRootRelease(item);
24 }
25 }
26 free(paramTreeView);
27 }
28}
29
30EXPORT TreeRoot *treeRootCreate(const char *name, xmlNode *treeRootNode, ParamTreeView *paramTreeView)
31{
32 TreeRoot *treeRoot = malloc(sizeof(TreeRoot));
33 treeRoot->name = strdup(name);
34 treeRoot->treeRootNode = treeRootNode;
35 treeRoot->paramTreeView = paramTreeView;
36 treeRoot->featureHash = NULL;
37 treeRoot->switchFieldInfo = NULL;
38 return treeRoot;
39}
40
41EXPORT void treeRootRelease(TreeRoot *treeRoot)
42{
43 if (treeRoot)
44 {
45 if (treeRoot->featureHash)
46 {
47 Feature *tmp, *item;
48 HASH_ITER(hh, treeRoot->featureHash, item, tmp)
49 {
50 HASH_DEL(treeRoot->featureHash, item);
51 featureRelease(item);
52 }
53 }
54
55 free(treeRoot->name);
56 free(treeRoot);
57 }
58}
59
60EXPORT Feature *featureCreate(const char *name, AudioType *audioType, FieldInfo *switchFieldInfo, const char *featureOption)
61{
62 Feature *feature = malloc(sizeof(Feature));
63 feature->name = strdup(name);
64 feature->audioType = audioType;
65
66 if (featureOption)
67 {
68 feature->featureOption = strdup(featureOption);
69 }
70 else
71 {
72 feature->featureOption = NULL;
73 }
74
75 feature->categoryPathHash = NULL;
76 feature->featureFieldHash = NULL;
77 feature->switchFieldInfo = switchFieldInfo;
78 return feature;
79}
80
81EXPORT void featureRelease(Feature *feature)
82{
83 if (feature)
84 {
85 if (feature->categoryPathHash)
86 {
87 CategoryPath *tmp, *item;
88 HASH_ITER(hh, feature->categoryPathHash, item, tmp)
89 {
90 HASH_DEL(feature->categoryPathHash, item);
91 categoryPathRelease(item);
92 }
93 }
94
95 if (feature->featureFieldHash)
96 {
97 FeatureField *tmp, *item;
98 HASH_ITER(hh, feature->featureFieldHash, item, tmp)
99 {
100 HASH_DEL(feature->featureFieldHash, item);
101 featureFieldRelease(item);
102 }
103 }
104
105 if (feature->name)
106 {
107 free(feature->name);
108 }
109
110 if (feature->featureOption)
111 {
112 free(feature->featureOption);
113 }
114
115 free(feature);
116 }
117}
118
119EXPORT APP_STATUS categoryPathValidation(CategoryPath *categoryPath)
120{
121 char *path;
122 char *categoryGroup;
123
124 if (!strcmp(categoryPath->path, ""))
125 {
126 return APP_NO_ERROR;
127 }
128
129 path = strdup(categoryPath->path);
130 categoryGroup = strtok(path, ARRAY_SEPERATOR);
131 if (audioTypeValidCategoryGroupName(categoryPath->feature->audioType, categoryGroup) == APP_ERROR)
132 {
133 free(path);
134 return APP_ERROR;
135 }
136
137 while ((categoryGroup = strtok(NULL, ARRAY_SEPERATOR)) != NULL)
138 {
139 if (audioTypeValidCategoryGroupName(categoryPath->feature->audioType, categoryGroup) == APP_ERROR)
140 {
141 free(path);
142 return APP_ERROR;
143 }
144 }
145
146 free(path);
147 return APP_NO_ERROR;
148}
149
150EXPORT CategoryPath *categoryPathCreate(Feature *feature, const char *path)
151{
152 CategoryPath *categoryPath = malloc(sizeof(CategoryPath));
153 categoryPath->path = strdup(path);
154 categoryPath->feature = feature;
155
156#ifdef WIN32
157 /* The category path validation only run on win32 */
158 if (categoryPathValidation(categoryPath) == APP_ERROR)
159 {
160 ERR_LOG("The %s feature's category path is not belong to categoryGroup! (%s)\n", feature->name, categoryPath->path);
161 categoryPathRelease(categoryPath);
162 return NULL;
163 }
164#endif
165
166 return categoryPath;
167}
168
169EXPORT void categoryPathRelease(CategoryPath *categoryPath)
170{
171 if (categoryPath)
172 {
173 free(categoryPath->path);
174 free(categoryPath);
175 }
176}
177
178EXPORT FeatureField *featureFieldCreate(FieldInfo *fieldInfo)
179{
180 FeatureField *featureField = malloc(sizeof(FeatureField));
181 featureField->fieldInfo = fieldInfo;
182
183 return featureField;
184}
185
186EXPORT void featureFieldRelease(FeatureField *featureField)
187{
188 if (featureField)
189 {
190 free(featureField);
191 }
192}
193
194EXPORT Feature *treeRootGetFeatureByName(TreeRoot *treeRoot, const char *featureName)
195{
196 Feature *feature;
197 HASH_FIND_STR(treeRoot->featureHash, featureName, feature);
198 return feature;
199}
200
201CategoryPath *findFeatureCategoryPath(char **arr, int *Switch, int n, Feature *feature)
202{
203 CategoryPath *categoryPath = NULL;
204 UT_string *path = NULL;
205 int i;
206
207 /* Generate the search string */
208 utstring_new(path);
209 for (i = 0; i < n; ++i)
210 {
211 if (i == n - 1)
212 {
213 utstring_printf(path, "%s", arr[Switch[i]]);
214 }
215 else
216 {
217 utstring_printf(path, "%s,", arr[Switch[i]]);
218 }
219 }
220
221 /* Find the categoryPath */
222 HASH_FIND_STR(feature->categoryPathHash, utstring_body(path), categoryPath);
223 DEBUG_LOG("Search path = %s, paramTree = 0x%p\n", utstring_body(path), categoryPath);
224
225 utstring_free(path);
226 return categoryPath;
227}
228
229CategoryPath *fuzzySearchFeatureCategoryPath(char **arr, int totalSize, int pickSize, Feature *feature)
230{
231 CategoryPath *categoryPath = NULL;
232 int i, j, pos = pickSize - 1;
233 int *swpArray;
234
235 if (pickSize > totalSize)
236 {
237 return categoryPath;
238 }
239
240 swpArray = (int *)malloc(sizeof(int) * totalSize);
241
242 for (i = 0; i < totalSize; ++i)
243 {
244 swpArray[i] = i;
245 }
246
247 categoryPath = findFeatureCategoryPath(arr, swpArray, pickSize, feature);
248 if (categoryPath)
249 {
250 free(swpArray);
251 return categoryPath;
252 }
253
254 do
255 {
256 if (swpArray[pickSize - 1] == totalSize - 1)
257 {
258 --pos;
259 }
260 else
261 {
262 pos = pickSize - 1;
263 }
264
265 ++swpArray[pos];
266
267 for (j = pos + 1; j < pickSize; ++j)
268 {
269 swpArray[j] = swpArray[j - 1] + 1;
270 }
271
272 categoryPath = findFeatureCategoryPath(arr, swpArray, pickSize, feature);
273 if (categoryPath)
274 {
275 free(swpArray);
276 return categoryPath;
277 }
278
279 }
280 while (swpArray[0] < totalSize - pickSize);
281
282 free(swpArray);
283 return categoryPath;
284}
285
286CategoryPath *searchFeatureCategoryPath(Feature *feature, const char *categoryPath)
287{
288 CategoryPath *featureCategoryPath;
289 char **categoryArray;
290 char *category;
291 char *tmpStr;
292 size_t numOfCategoryType;
293 size_t numOfCategory;
294 size_t i = 0;
295
296 DEBUG_LOG("+Feature = %s, categoryPath = %s\n", feature->name, categoryPath);
297
298 /* Full path search first */
299 HASH_FIND_STR(feature->categoryPathHash, categoryPath, featureCategoryPath);
300 if (featureCategoryPath)
301 {
302 DEBUG_LOG("fuzzySearch paramTree found. (path = %s)\n", featureCategoryPath->path);
303 return featureCategoryPath;
304 }
305 else if (!strcmp(categoryPath, ""))
306 {
307 return NULL;
308 }
309
310 /* Setup array for fuzzy search path enum */
311 numOfCategoryType = audioTypeGetNumOfCategoryType(feature->audioType);
312 categoryArray = malloc(sizeof(char *) * numOfCategoryType);
313
314 tmpStr = strdup(categoryPath ? categoryPath : "");
315 category = strtok(tmpStr, ARRAY_SEPERATOR);
316 if (!category)
317 {
318 ERR_LOG("Cannot parse category\n");
319 free(categoryArray);
320 free(tmpStr);
321 return NULL;
322 }
323 categoryArray[i++] = category;
324
325 while ((category = strtok(NULL, ARRAY_SEPERATOR)) != NULL)
326 {
327 categoryArray[i++] = category;
328 }
329 numOfCategory = i;
330
331 /* Fuzzy search */
332 for (i = 1; i < numOfCategory; i++)
333 {
334 featureCategoryPath = fuzzySearchFeatureCategoryPath(categoryArray, numOfCategory, numOfCategory - i, feature);
335 if (featureCategoryPath)
336 {
337 break;
338 }
339 }
340
341 if (!featureCategoryPath)
342 {
343 /* If no paramTree found, try to get the root paramTree */
344 HASH_FIND_STR(feature->categoryPathHash, "", featureCategoryPath);
345 }
346
347 free(categoryArray);
348 free(tmpStr);
349
350 DEBUG_LOG("-fuzzySearch featureCategoryPath %s found. \n", featureCategoryPath ? "" : "not ");
351 return featureCategoryPath;
352}
353
354EXPORT int featureIsCategoryPathSupport(Feature *feature, const char *categoryPath)
355{
356 /* Get the category path */
357 CategoryPath *featureCategoryPath = NULL;
358 UT_string *searchPath;
359
360 if (!feature)
361 {
362 ERR_LOG("feature is NULL\n");
363 return 0;
364 }
365
366 if (!categoryPath)
367 {
368 ERR_LOG("categoryPath is NULL\n");
369 return 0;
370 }
371
372 /* Check if feature support all categoryPath first */
373 featureCategoryPath = searchFeatureCategoryPath(feature, "");
374 if (featureCategoryPath)
375 {
376 return 1;
377 }
378
379 searchPath = utilNormalizeCategoryGroupPathForAudioType(categoryPath, feature->audioType);
380 if (!searchPath)
381 {
382 ERR_LOG("Cannot normalize categoryPath for %s AudioType. (path = %s)\n", feature->audioType->name, categoryPath);
383 return 0;
384 }
385
386 /* Search the feature's category path */
387 featureCategoryPath = searchFeatureCategoryPath(feature, utstring_body(searchPath));
388 utstring_free(searchPath);
389
390 if (featureCategoryPath)
391 {
392 return 1;
393 }
394 else
395 {
396 return 0;
397 }
398}