• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021-2022 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #ifndef OHOS_WIFI_CONFIG_FILE_IMPL_H
17 #define OHOS_WIFI_CONFIG_FILE_IMPL_H
18 #include <fstream>
19 #include <sstream>
20 #include <string>
21 #include <unistd.h>
22 #include <vector>
23 #include "wifi_config_file_spec.h"
24 #include "wifi_log.h"
25 
26 namespace OHOS {
27 namespace Wifi {
28 /**
29  * @Description Remove head and tail space
30  *
31  * @param str - String
32  */
TrimString(std::string & str)33 static inline void TrimString(std::string &str)
34 {
35     int i = 0;
36     int j = static_cast<int>(str.length()) - 1;
37     while (i < static_cast<int>(str.length()) && str[i] == ' ') {
38         ++i;
39     }
40     while (j >= 0 && str[j] == ' ') {
41         --j;
42     }
43     str = ((i > j) ? "" : str.substr(i, j - i + 1));
44 }
45 
46 /**
47  * @Description Delete comment message begin with ; and #
48  *
49  * @param str - String
50  */
DelComment(std::string & str)51 static inline void DelComment(std::string &str)
52 {
53     std::string::size_type i = 0;
54     for (; i < str.length(); ++i) {
55         if (str[i] == ';' || str[i] == '#') {
56             str = str.substr(0, i);
57             break;
58         }
59     }
60     return;
61 }
62 
63 template<typename T>
64 class WifiConfigFileImpl {
65 public:
66     /**
67      * @Description Set the config file path
68      *
69      * @param fileName - file name
70      * @return int - 0 success
71      */
72     int SetConfigFilePath(const std::string &fileName);
73 
74     /**
75      * @Description read and parses the network section of ini config file, need call SetConfigFilePath first
76      *
77      * @return int - 0 Success; >0 parse failed
78      */
79     int ReadNetworkSection(T &item, std::ifstream &fs, std::string &line);
80 
81     /**
82      * @Description read and parses the networks of ini config file, need call SetConfigFilePath first
83      *
84      * @return int - 0 Success; >0 parse failed
85      */
86     int ReadNetwork(T &item, std::ifstream &fs, std::string &line);
87 
88     /**
89      * @Description read and parses the ini config file, need call SetConfigFilePath first
90      *
91      * @return int - 0 Success; -1 file not exist
92      */
93     int LoadConfig();
94 
95     /**
96      * @Description Save config to file
97      *
98      * @return int - 0 Success; -1 Failed
99      */
100     int SaveConfig();
101 
102     /**
103      * @Description Get config values
104      *
105      * @param results - output config values
106      * @return int - 0 Success, -1 Failed
107      */
108     int GetValue(std::vector<T> &results);
109 
110     /**
111      * @Description Get config values
112      *
113      * @return config values
114      */
115     const std::vector<T>& GetValue() const;
116 
117     /**
118      * @Description Set the config value
119      *
120      * @param values - input config values
121      * @return int - 0 Success, -1 Failed
122      */
123     int SetValue(const std::vector<T> &values);
124 
125 private:
126     std::string mFileName;
127     std::vector<T> mValues;
128 };
129 
130 template<typename T>
SetConfigFilePath(const std::string & fileName)131 int WifiConfigFileImpl<T>::SetConfigFilePath(const std::string &fileName)
132 {
133     mFileName = fileName;
134     return 0;
135 }
136 
137 template<typename T>
ReadNetworkSection(T & item,std::ifstream & fs,std::string & line)138 int WifiConfigFileImpl<T>::ReadNetworkSection(T &item, std::ifstream &fs, std::string &line)
139 {
140     int sectionError = 0;
141     while (std::getline(fs, line)) {
142         TrimString(line);
143         if (line.empty()) {
144             continue;
145         }
146         if (line[0] == '<' && line[line.length() - 1] == '>') {
147             return sectionError;
148         }
149         std::string::size_type npos = line.find("=");
150         if (npos == std::string::npos) {
151             LOGE("Invalid config line");
152             sectionError++;
153             continue;
154         }
155         std::string key = line.substr(0, npos);
156         std::string value = line.substr(npos + 1);
157         TrimString(key);
158         TrimString(value);
159         /* template function, needing specialization */
160         sectionError += SetTClassKeyValue(item, key, value);
161     }
162     LOGE("Section config not end correctly");
163     sectionError++;
164     return sectionError;
165 }
166 
167 template<typename T>
ReadNetwork(T & item,std::ifstream & fs,std::string & line)168 int WifiConfigFileImpl<T>::ReadNetwork(T &item, std::ifstream &fs, std::string &line)
169 {
170     int networkError = 0;
171     while (std::getline(fs, line)) {
172         TrimString(line);
173         if (line.empty()) {
174             continue;
175         }
176         if (line[0] == '<' && line[line.length() - 1] == '>') {
177             networkError += ReadNetworkSection(item, fs, line);
178         } else if (line.compare("}") == 0) {
179             return networkError;
180         } else {
181             LOGE("Invalid config line");
182             networkError++;
183         }
184     }
185     LOGE("Network config not end correctly");
186     networkError++;
187     return networkError;
188 }
189 
190 template<typename T>
LoadConfig()191 int WifiConfigFileImpl<T>::LoadConfig()
192 {
193     if (mFileName.empty()) {
194         LOGE("File name is empty.");
195         return -1;
196     }
197     std::ifstream fs(mFileName.c_str());
198     if (!fs.is_open()) {
199         LOGD("Loading config file: %{public}s, fs.is_open() failed!", mFileName.c_str());
200         return -1;
201     }
202     mValues.clear();
203     T item;
204     std::string line;
205     int configError;
206     while (std::getline(fs, line)) {
207         TrimString(line);
208         if (line.empty()) {
209             continue;
210         }
211         if (line[0] == '[' && line[line.length() - 1] == '{') {
212             ClearTClass(item); /* template function, needing specialization */
213             configError = ReadNetwork(item, fs, line);
214             if (configError > 0) {
215                 LOGE("Parse network failed.");
216                 continue;
217             }
218             mValues.push_back(item);
219         }
220     }
221     fs.close();
222     return 0;
223 }
224 
225 template<typename T>
SaveConfig()226 int WifiConfigFileImpl<T>::SaveConfig()
227 {
228     if (mFileName.empty()) {
229         LOGE("File name is empty.");
230         return -1;
231     }
232     FILE* fp = fopen(mFileName.c_str(), "w");
233     if (!fp) {
234         LOGE("Save config file: %{public}s, fopen() failed!", mFileName.c_str());
235         return -1;
236     }
237     std::ostringstream ss;
238     for (std::size_t i = 0; i < mValues.size(); ++i) {
239         T &item = mValues[i];
240         /*
241          * here use template function GetTClassName OutTClassString, needing
242          * specialization.
243          */
244         ss << "[" << GetTClassName<T>() << "_" << (i + 1) << "] {" << std::endl;
245         ss << OutTClassString(item) << std::endl;
246         ss << "}" << std::endl;
247     }
248     std::string content = ss.str();
249     int ret = fwrite(content.c_str(), 1, content.length(), fp);
250     if (ret != (int)content.length()) {
251         LOGE("Save config file: %{public}s, fwrite() failed!", mFileName.c_str());
252     }
253     (void)fflush(fp);
254     (void)fsync(fileno(fp));
255     (void)fclose(fp);
256     mValues.clear(); /* clear values */
257     return 0;
258 }
259 
260 template<typename T>
GetValue(std::vector<T> & results)261 int WifiConfigFileImpl<T>::GetValue(std::vector<T> &results)
262 {
263     /*
264      * swap, WifiConfigFileImpl not saved this config when next use, call LoadConfig first
265      */
266     std::swap(results, mValues);
267     return 0;
268 }
269 
270 template <typename T>
GetValue()271 const std::vector<T>& WifiConfigFileImpl<T>::GetValue() const
272 {
273     return mValues;
274 }
275 
276 template <typename T>
SetValue(const std::vector<T> & results)277 int WifiConfigFileImpl<T>::SetValue(const std::vector<T> &results)
278 {
279     mValues = results;
280     return 0;
281 }
282 }  // namespace Wifi
283 }  // namespace OHOS
284 #endif