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 <errno.h>
33 #include <utils/Log.h>
34 #include <sys/mman.h>
35 #include "PlatformConfig.h"
36 #include "ConfigParser.h"
37 
38 namespace Platform {
39 
40 #define BUF_SIZE                    1024
41 
processProperty(const XML_Char ** attr,ConfigMap & configMap)42 void ConfigParser::processProperty(const XML_Char **attr, ConfigMap &configMap) {
43     if (strcmp(attr[0], "name") != 0) {
44         VIDC_PLAT_LOGH("%s: Element 'name' not found!", __func__);
45         return;
46     }
47 
48     std::string propName(attr[1]);
49 
50     if (strcmp(attr[2], "value") != 0) {
51         VIDC_PLAT_LOGH("%s: Element 'value' not found for %s!", __func__, propName.c_str());
52         return;
53     }
54 
55     std::string propValue(attr[3]);
56 
57     configMap[propName] = propValue;
58 
59     return;
60 }
61 
startTag(void * userdata,const XML_Char * tagName,const XML_Char ** attr)62 void ConfigParser::startTag(void *userdata, const XML_Char *tagName,
63         const XML_Char **attr) {
64     if (strcmp(tagName, "property") == 0) {
65         processProperty(attr, *static_cast<ConfigMap *>(userdata));
66     }
67     return;
68 }
69 
endTag(void * userdata __unused,const XML_Char * tagName __unused)70 void ConfigParser::endTag(void *userdata __unused, const XML_Char *tagName __unused) {
71     return;
72 }
73 
initAndParse(std::string configFile,ConfigMap & configMap)74 int ConfigParser::initAndParse(std::string configFile, ConfigMap &configMap) {
75     int err = 1;
76     XML_Parser parser;
77     FILE *file;
78     file = fopen(configFile.c_str(), "r");
79     if (!file) {
80         VIDC_PLAT_LOGH("%s: Error: %d (%s). Using defaults!",
81             __func__, errno, strerror(errno));
82         return err;
83     }
84 
85     // Create Parser
86     parser = XML_ParserCreate(NULL);
87     if (!parser) {
88         VIDC_PLAT_LOGH("%s: Failed to create XML parser!", __func__);
89         err = -ENODEV;
90         goto fileError;
91     }
92 
93     // Set XML element handlers
94     XML_SetUserData(parser, &configMap);
95     XML_SetElementHandler(parser, startTag, endTag);
96     void *buf;
97     int bytesRead;
98 
99     // Parse
100     while (1) {
101         buf = XML_GetBuffer(parser, BUF_SIZE);
102         if (buf == NULL) {
103             VIDC_PLAT_LOGH("%s: XML_GetBuffer failed", __func__);
104             err = -ENOMEM;
105             goto parserError;
106         }
107 
108         bytesRead = fread(buf, 1, BUF_SIZE, file);
109         if (bytesRead < 0) {
110             VIDC_PLAT_LOGH("%s: fread failed, bytes read = %d", __func__, bytesRead);
111             err = bytesRead;
112             goto parserError;
113         }
114 
115         if (XML_ParseBuffer(parser, bytesRead,
116                 bytesRead == 0) == XML_STATUS_ERROR) {
117             VIDC_PLAT_LOGH("%s: XML_ParseBuffer failed, for %s",
118                     __func__, configFile.c_str());
119             err = -EINVAL;
120             goto parserError;
121         }
122         if (bytesRead == 0)
123             break;
124     }
125 
126     // Free parser and close file in error/ at exit
127     parserError:
128         XML_ParserFree(parser);
129     fileError:
130         fclose(file);
131     return err;
132 }
133 
134 }
135