blob: b5254b150a96abadab440c15d1962cfc87c7f8b0 [file] [log] [blame]
#include "AudioParamParserPriv.h"
EXPORT ParamTreeView *paramTreeViewCreate(AudioType *audioType, int verMaj, int verMin)
{
ParamTreeView *paramTreeView = malloc(sizeof(ParamTreeView));
paramTreeView->audioType = audioType;
paramTreeView->verMaj = verMaj;
paramTreeView->verMin = verMin;
paramTreeView->treeRootHash = NULL;
return paramTreeView;
}
EXPORT void paramTreeViewRelease(ParamTreeView *paramTreeView)
{
if (paramTreeView)
{
if (paramTreeView->treeRootHash)
{
TreeRoot *tmp, *item;
HASH_ITER(hh, paramTreeView->treeRootHash, item, tmp)
{
HASH_DEL(paramTreeView->treeRootHash, item);
treeRootRelease(item);
}
}
free(paramTreeView);
}
}
EXPORT TreeRoot *treeRootCreate(const char *name, xmlNode *treeRootNode, ParamTreeView *paramTreeView)
{
TreeRoot *treeRoot = malloc(sizeof(TreeRoot));
treeRoot->name = strdup(name);
treeRoot->treeRootNode = treeRootNode;
treeRoot->paramTreeView = paramTreeView;
treeRoot->featureHash = NULL;
treeRoot->switchFieldInfo = NULL;
return treeRoot;
}
EXPORT void treeRootRelease(TreeRoot *treeRoot)
{
if (treeRoot)
{
if (treeRoot->featureHash)
{
Feature *tmp, *item;
HASH_ITER(hh, treeRoot->featureHash, item, tmp)
{
HASH_DEL(treeRoot->featureHash, item);
featureRelease(item);
}
}
free(treeRoot->name);
free(treeRoot);
}
}
EXPORT Feature *featureCreate(const char *name, AudioType *audioType, FieldInfo *switchFieldInfo, const char *featureOption)
{
Feature *feature = malloc(sizeof(Feature));
feature->name = strdup(name);
feature->audioType = audioType;
if (featureOption)
{
feature->featureOption = strdup(featureOption);
}
else
{
feature->featureOption = NULL;
}
feature->categoryPathHash = NULL;
feature->featureFieldHash = NULL;
feature->switchFieldInfo = switchFieldInfo;
return feature;
}
EXPORT void featureRelease(Feature *feature)
{
if (feature)
{
if (feature->categoryPathHash)
{
CategoryPath *tmp, *item;
HASH_ITER(hh, feature->categoryPathHash, item, tmp)
{
HASH_DEL(feature->categoryPathHash, item);
categoryPathRelease(item);
}
}
if (feature->featureFieldHash)
{
FeatureField *tmp, *item;
HASH_ITER(hh, feature->featureFieldHash, item, tmp)
{
HASH_DEL(feature->featureFieldHash, item);
featureFieldRelease(item);
}
}
if (feature->name)
{
free(feature->name);
}
if (feature->featureOption)
{
free(feature->featureOption);
}
free(feature);
}
}
EXPORT APP_STATUS categoryPathValidation(CategoryPath *categoryPath)
{
char *path;
char *categoryGroup;
if (!strcmp(categoryPath->path, ""))
{
return APP_NO_ERROR;
}
path = strdup(categoryPath->path);
categoryGroup = strtok(path, ARRAY_SEPERATOR);
if (audioTypeValidCategoryGroupName(categoryPath->feature->audioType, categoryGroup) == APP_ERROR)
{
free(path);
return APP_ERROR;
}
while ((categoryGroup = strtok(NULL, ARRAY_SEPERATOR)) != NULL)
{
if (audioTypeValidCategoryGroupName(categoryPath->feature->audioType, categoryGroup) == APP_ERROR)
{
free(path);
return APP_ERROR;
}
}
free(path);
return APP_NO_ERROR;
}
EXPORT CategoryPath *categoryPathCreate(Feature *feature, const char *path)
{
CategoryPath *categoryPath = malloc(sizeof(CategoryPath));
categoryPath->path = strdup(path);
categoryPath->feature = feature;
#ifdef WIN32
/* The category path validation only run on win32 */
if (categoryPathValidation(categoryPath) == APP_ERROR)
{
ERR_LOG("The %s feature's category path is not belong to categoryGroup! (%s)\n", feature->name, categoryPath->path);
categoryPathRelease(categoryPath);
return NULL;
}
#endif
return categoryPath;
}
EXPORT void categoryPathRelease(CategoryPath *categoryPath)
{
if (categoryPath)
{
free(categoryPath->path);
free(categoryPath);
}
}
EXPORT FeatureField *featureFieldCreate(FieldInfo *fieldInfo)
{
FeatureField *featureField = malloc(sizeof(FeatureField));
featureField->fieldInfo = fieldInfo;
return featureField;
}
EXPORT void featureFieldRelease(FeatureField *featureField)
{
if (featureField)
{
free(featureField);
}
}
EXPORT Feature *treeRootGetFeatureByName(TreeRoot *treeRoot, const char *featureName)
{
Feature *feature;
HASH_FIND_STR(treeRoot->featureHash, featureName, feature);
return feature;
}
CategoryPath *findFeatureCategoryPath(char **arr, int *Switch, int n, Feature *feature)
{
CategoryPath *categoryPath = NULL;
UT_string *path = NULL;
int i;
/* Generate the search string */
utstring_new(path);
for (i = 0; i < n; ++i)
{
if (i == n - 1)
{
utstring_printf(path, "%s", arr[Switch[i]]);
}
else
{
utstring_printf(path, "%s,", arr[Switch[i]]);
}
}
/* Find the categoryPath */
HASH_FIND_STR(feature->categoryPathHash, utstring_body(path), categoryPath);
DEBUG_LOG("Search path = %s, paramTree = 0x%p\n", utstring_body(path), categoryPath);
utstring_free(path);
return categoryPath;
}
CategoryPath *fuzzySearchFeatureCategoryPath(char **arr, int totalSize, int pickSize, Feature *feature)
{
CategoryPath *categoryPath = NULL;
int i, j, pos = pickSize - 1;
int *swpArray;
if (pickSize > totalSize)
{
return categoryPath;
}
swpArray = (int *)malloc(sizeof(int) * totalSize);
for (i = 0; i < totalSize; ++i)
{
swpArray[i] = i;
}
categoryPath = findFeatureCategoryPath(arr, swpArray, pickSize, feature);
if (categoryPath)
{
free(swpArray);
return categoryPath;
}
do
{
if (swpArray[pickSize - 1] == totalSize - 1)
{
--pos;
}
else
{
pos = pickSize - 1;
}
++swpArray[pos];
for (j = pos + 1; j < pickSize; ++j)
{
swpArray[j] = swpArray[j - 1] + 1;
}
categoryPath = findFeatureCategoryPath(arr, swpArray, pickSize, feature);
if (categoryPath)
{
free(swpArray);
return categoryPath;
}
}
while (swpArray[0] < totalSize - pickSize);
free(swpArray);
return categoryPath;
}
CategoryPath *searchFeatureCategoryPath(Feature *feature, const char *categoryPath)
{
CategoryPath *featureCategoryPath;
char **categoryArray;
char *category;
char *tmpStr;
size_t numOfCategoryType;
size_t numOfCategory;
size_t i = 0;
DEBUG_LOG("+Feature = %s, categoryPath = %s\n", feature->name, categoryPath);
/* Full path search first */
HASH_FIND_STR(feature->categoryPathHash, categoryPath, featureCategoryPath);
if (featureCategoryPath)
{
DEBUG_LOG("fuzzySearch paramTree found. (path = %s)\n", featureCategoryPath->path);
return featureCategoryPath;
}
else if (!strcmp(categoryPath, ""))
{
return NULL;
}
/* Setup array for fuzzy search path enum */
numOfCategoryType = audioTypeGetNumOfCategoryType(feature->audioType);
categoryArray = malloc(sizeof(char *) * numOfCategoryType);
tmpStr = strdup(categoryPath ? categoryPath : "");
category = strtok(tmpStr, ARRAY_SEPERATOR);
if (!category)
{
ERR_LOG("Cannot parse category\n");
free(categoryArray);
free(tmpStr);
return NULL;
}
categoryArray[i++] = category;
while ((category = strtok(NULL, ARRAY_SEPERATOR)) != NULL)
{
categoryArray[i++] = category;
}
numOfCategory = i;
/* Fuzzy search */
for (i = 1; i < numOfCategory; i++)
{
featureCategoryPath = fuzzySearchFeatureCategoryPath(categoryArray, numOfCategory, numOfCategory - i, feature);
if (featureCategoryPath)
{
break;
}
}
if (!featureCategoryPath)
{
/* If no paramTree found, try to get the root paramTree */
HASH_FIND_STR(feature->categoryPathHash, "", featureCategoryPath);
}
free(categoryArray);
free(tmpStr);
DEBUG_LOG("-fuzzySearch featureCategoryPath %s found. \n", featureCategoryPath ? "" : "not ");
return featureCategoryPath;
}
EXPORT int featureIsCategoryPathSupport(Feature *feature, const char *categoryPath)
{
/* Get the category path */
CategoryPath *featureCategoryPath = NULL;
UT_string *searchPath;
if (!feature)
{
ERR_LOG("feature is NULL\n");
return 0;
}
if (!categoryPath)
{
ERR_LOG("categoryPath is NULL\n");
return 0;
}
/* Check if feature support all categoryPath first */
featureCategoryPath = searchFeatureCategoryPath(feature, "");
if (featureCategoryPath)
{
return 1;
}
searchPath = utilNormalizeCategoryGroupPathForAudioType(categoryPath, feature->audioType);
if (!searchPath)
{
ERR_LOG("Cannot normalize categoryPath for %s AudioType. (path = %s)\n", feature->audioType->name, categoryPath);
return 0;
}
/* Search the feature's category path */
featureCategoryPath = searchFeatureCategoryPath(feature, utstring_body(searchPath));
utstring_free(searchPath);
if (featureCategoryPath)
{
return 1;
}
else
{
return 0;
}
}