1 /**
2 * Copyright 2021 Huawei Technologies Co., Ltd
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "src/common/config_file.h"
18
19 #ifdef _MSC_VER
20 #define PATH_MAX 1024
21 #endif
22 namespace {
23 constexpr size_t kLengthOfParentheses = 2;
24 constexpr size_t kMinSectionLineLength = 2;
25 constexpr size_t kMaxValidLineCount = 100000;
26 constexpr size_t kMaxLineCount = 100100;
27 } // namespace
28
29 namespace mindspore {
30 namespace lite {
31 namespace {
ParseLine(const std::string & line,std::map<std::string,std::string> * section_config,std::string * section,size_t * valid_line_count,std::map<std::string,std::map<std::string,std::string>> * config)32 void ParseLine(const std::string &line, std::map<std::string, std::string> *section_config, std::string *section,
33 size_t *valid_line_count, std::map<std::string, std::map<std::string, std::string>> *config) {
34 // eg: [section]
35 // key=value
36 if (line[0] == '[' && line[line.length() - 1] == ']') {
37 if (!section->empty() && !section_config->empty()) {
38 (void)config->insert(std::make_pair(*section, *section_config));
39 }
40 section_config->clear();
41 *section = line.substr(1, line.length() - kLengthOfParentheses);
42 *valid_line_count = *valid_line_count + 1;
43 }
44
45 if (!section->empty()) {
46 auto index = line.find('=');
47 if (index == std::string::npos) {
48 return;
49 }
50 auto key = line.substr(0, index);
51 if (index + 1 > line.size()) {
52 return;
53 }
54 auto value = line.substr(index + 1);
55 lite::Trim(&key);
56 lite::Trim(&value);
57 (void)section_config->insert(std::make_pair(key, value));
58 *valid_line_count = *valid_line_count + 1;
59 }
60 }
61 } // namespace
62
GetAllSectionInfoFromConfigFile(const std::string & file,ConfigInfos * config)63 int GetAllSectionInfoFromConfigFile(const std::string &file, ConfigInfos *config) {
64 if (file.empty() || config == nullptr) {
65 MS_LOG(ERROR) << "input Invalid!check file and config.";
66 return RET_ERROR;
67 }
68 auto resolved_path = std::make_unique<char[]>(PATH_MAX);
69 if (resolved_path == nullptr) {
70 MS_LOG(ERROR) << "new resolved_path fail!";
71 return RET_ERROR;
72 }
73
74 #ifdef _WIN32
75 char *real_path = _fullpath(resolved_path.get(), file.c_str(), MAX_CONFIG_FILE_LENGTH);
76 #else
77 char *real_path = realpath(file.c_str(), resolved_path.get());
78 #endif
79 if (real_path == nullptr || strlen(real_path) == 0) {
80 MS_LOG(ERROR) << "file path is not valid : " << file;
81 return RET_ERROR;
82 }
83 std::ifstream ifs(resolved_path.get());
84 if (!ifs.good()) {
85 MS_LOG(ERROR) << "file: " << real_path << " is not exist";
86 return RET_ERROR;
87 }
88 if (!ifs.is_open()) {
89 MS_LOG(ERROR) << "file: " << real_path << "open failed";
90 return RET_ERROR;
91 }
92 std::string line;
93 std::string section;
94 std::map<std::string, std::string> section_config;
95 size_t line_count = 0;
96 size_t valid_line_count = 0;
97 while (std::getline(ifs, line)) {
98 line_count++;
99 if (line_count >= kMaxLineCount || valid_line_count >= kMaxValidLineCount) {
100 MS_LOG(ERROR) << "config too many lines!";
101 ifs.close();
102 return RET_ERROR;
103 }
104 lite::Trim(&line);
105 if (line.length() <= kMinSectionLineLength || line[0] == '#') {
106 continue;
107 }
108 ParseLine(line, §ion_config, §ion, &valid_line_count, config);
109 }
110 if (!section.empty() && !section_config.empty()) {
111 (void)config->insert(std::make_pair(section, section_config));
112 }
113 ifs.close();
114 return RET_OK;
115 }
116
ParserExecutionPlan(const std::map<std::string,std::string> * config_infos,std::map<std::string,TypeId> * data_type_plan)117 void ParserExecutionPlan(const std::map<std::string, std::string> *config_infos,
118 std::map<std::string, TypeId> *data_type_plan) {
119 for (auto info : *config_infos) {
120 std::string op_name = info.first;
121 std::string value = info.second;
122 if (value.empty()) {
123 MS_LOG(WARNING) << "Empty info in execution_plan";
124 continue;
125 }
126 if (value[0] == '"' && value[value.length() - 1] == '"') {
127 value = value.substr(1, value.length() - kLengthOfParentheses);
128 }
129 auto index = value.find(':');
130 if (index == std::string::npos) {
131 MS_LOG(WARNING) << "Invalid info in execution_plan: " << value;
132 continue;
133 }
134 auto data_type_key = value.substr(0, index);
135 if (index + 1 > value.size()) {
136 return;
137 }
138 auto data_type_value = value.substr(index + 1);
139 if (data_type_key != "data_type") {
140 MS_LOG(WARNING) << "Invalid key in execution_plan: " << value;
141 continue;
142 }
143 TypeId type_id = kTypeUnknown;
144 if (data_type_value == "float32") {
145 type_id = kNumberTypeFloat32;
146 } else if (data_type_value == "float16") {
147 type_id = kNumberTypeFloat16;
148 } else {
149 MS_LOG(WARNING) << "Invalid value in execution_plan: " << value;
150 continue;
151 }
152 (void)data_type_plan->insert(std::make_pair(op_name, type_id));
153 }
154 }
155 } // namespace lite
156 } // namespace mindspore
157