[Feature]add MT2731_MP2_MR2_SVN388 baseline version

Change-Id: Ief04314834b31e27effab435d3ca8ba33b499059
diff --git a/src/multimedia/audio-tuning/audio-xml-parser/mt2635/AudioParamTreeView.c b/src/multimedia/audio-tuning/audio-xml-parser/mt2635/AudioParamTreeView.c
new file mode 100644
index 0000000..b5254b1
--- /dev/null
+++ b/src/multimedia/audio-tuning/audio-xml-parser/mt2635/AudioParamTreeView.c
@@ -0,0 +1,398 @@
+#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;
+    }
+}