1 /*
2  * Copyright (c) 2017 - 2018, The Linux Foundation. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are
6  * met:
7  *     * Redistributions of source code must retain the above copyright
8  *       notice, this list of conditions and the following disclaimer.
9  *     * Redistributions in binary form must reproduce the above
10  *       copyright notice, this list of conditions and the following
11  *       disclaimer in the documentation and/or other materials provided
12  *       with the distribution.
13  *     * Neither the name of The Linux Foundation nor the names of its
14  *       contributors may be used to endorse or promote products derived
15  *       from this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
18  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
21  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
24  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
26  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
27  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  */
29 
30 #define LOG_TAG "ConfigParser"
31 
32 #include <string.h>
33 #include <errno.h>
34 #include <utils/Log.h>
35 #include <sys/mman.h>
36 #include "PlatformConfig.h"
37 #include "ConfigParser.h"
38 
39 namespace Platform {
40 
41 #define BUF_SIZE                    1024
42 
processProperty(const XML_Char ** attr,ConfigMap & configMap)43 void ConfigParser::processProperty(const XML_Char **attr, ConfigMap &configMap) {
44     if (strcmp(attr[0], "name") != 0) {
45         VIDC_PLAT_LOGH("%s: Element 'name' not found!", __func__);
46         return;
47     }
48 
49     std::string propName(attr[1]);
50 
51     if (strcmp(attr[2], "value") != 0) {
52         VIDC_PLAT_LOGH("%s: Element 'value' not found for %s!", __func__, propName.c_str());
53         return;
54     }
55 
56     std::string propValue(attr[3]);
57 
58     configMap[propName] = propValue;
59 
60     return;
61 }
62 
startTag(void * userdata,const XML_Char * tagName,const XML_Char ** attr)63 void ConfigParser::startTag(void *userdata, const XML_Char *tagName,
64         const XML_Char **attr) {
65     if (strcmp(tagName, "property") == 0) {
66         processProperty(attr, *static_cast<ConfigMap *>(userdata));
67     }
68     return;
69 }
70 
endTag(void * userdata __unused,const XML_Char * tagName __unused)71 void ConfigParser::endTag(void *userdata __unused, const XML_Char *tagName __unused) {
72     return;
73 }
74 
initAndParse(std::string configFile,ConfigMap & configMap)75 int ConfigParser::initAndParse(std::string configFile, ConfigMap &configMap) {
76     int err = 1;
77     XML_Parser parser;
78     FILE *file;
79     file = fopen(configFile.c_str(), "r");
80     if (!file) {
81         VIDC_PLAT_LOGH("%s: Error: %d (%s). Using defaults!",
82             __func__, errno, strerror(errno));
83         return err;
84     }
85 
86     // Create Parser
87     parser = XML_ParserCreate(NULL);
88     if (!parser) {
89         VIDC_PLAT_LOGH("%s: Failed to create XML parser!", __func__);
90         err = -ENODEV;
91         goto fileError;
92     }
93 
94     // Set XML element handlers
95     XML_SetUserData(parser, &configMap);
96     XML_SetElementHandler(parser, startTag, endTag);
97     void *buf;
98     int bytesRead;
99 
100     // Parse
101     while (1) {
102         buf = XML_GetBuffer(parser, BUF_SIZE);
103         if (buf == NULL) {
104             VIDC_PLAT_LOGH("%s: XML_GetBuffer failed", __func__);
105             err = -ENOMEM;
106             goto parserError;
107         }
108 
109         bytesRead = fread(buf, 1, BUF_SIZE, file);
110         if (bytesRead < 0) {
111             VIDC_PLAT_LOGH("%s: fread failed, bytes read = %d", __func__, bytesRead);
112             err = bytesRead;
113             goto parserError;
114         }
115 
116         if (XML_ParseBuffer(parser, bytesRead,
117                 bytesRead == 0) == XML_STATUS_ERROR) {
118             VIDC_PLAT_LOGH("%s: XML_ParseBuffer failed, for %s",
119                     __func__, configFile.c_str());
120             err = -EINVAL;
121             goto parserError;
122         }
123         if (bytesRead == 0)
124             break;
125     }
126 
127     // Free parser and close file in error/ at exit
128     parserError:
129         XML_ParserFree(parser);
130     fileError:
131         fclose(file);
132     return err;
133 }
134 
135 }
136