• 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 ini config file, need call SetConfigFilePath first
76      *
77      * @return int - 0 Success; -1 file not exist
78      */
79     int LoadConfig();
80 
81     /**
82      * @Description Save config to file
83      *
84      * @return int - 0 Success; -1 Failed
85      */
86     int SaveConfig();
87 
88     /**
89      * @Description Get config values
90      *
91      * @param results - output config values
92      * @return int - 0 Success, -1 Failed
93      */
94     int GetValue(std::vector<T> &results);
95 
96     /**
97      * @Description Get config values
98      *
99      * @return config values
100      */
101     const std::vector<T>& GetValue() const;
102 
103     /**
104      * @Description Set the config value
105      *
106      * @param values - input config values
107      * @return int - 0 Success, -1 Failed
108      */
109     int SetValue(const std::vector<T> &values);
110 
111 private:
112     std::string mFileName;
113     std::vector<T> mValues;
114 };
115 
116 template<typename T>
SetConfigFilePath(const std::string & fileName)117 int WifiConfigFileImpl<T>::SetConfigFilePath(const std::string &fileName)
118 {
119     mFileName = fileName;
120     return 0;
121 }
122 
123 template<typename T>
LoadConfig()124 int WifiConfigFileImpl<T>::LoadConfig()
125 {
126     std::ifstream fs(mFileName.c_str());
127     if (!fs.is_open()) {
128         LOGE("Loading config file: %{public}s, fs.is_open() failed!", mFileName.c_str());
129         return -1;
130     }
131     mValues.clear();
132     bool bSection = false;
133     T item;
134     std::string line;
135     while (std::getline(fs, line)) {
136         TrimString(line);
137         if (line.empty()) {
138             continue;
139         }
140         if (line[0] == '[' && line[line.length() - 1] == ']') {
141             if (bSection) {
142                 mValues.push_back(item);
143             }
144             bSection = true;
145             ClearTClass(item); /* template function, needing specialization */
146             continue;
147         }
148         std::string::size_type npos = line.find("=");
149         if (npos == std::string::npos) {
150             continue;
151         }
152         std::string key = line.substr(0, npos);
153         std::string value = line.substr(npos + 1);
154         TrimString(key);
155         TrimString(value);
156         /* template function, needing specialization */
157         SetTClassKeyValue(item, key, value);
158     }
159     if (bSection) {
160         mValues.push_back(item);
161     }
162     fs.close();
163     return 0;
164 }
165 
166 template<typename T>
SaveConfig()167 int WifiConfigFileImpl<T>::SaveConfig()
168 {
169     FILE* fp = fopen(mFileName.c_str(), "w");
170     if (!fp) {
171         LOGE("Save config file: %{public}s, fopen() failed!", mFileName.c_str());
172         return -1;
173     }
174     std::ostringstream ss;
175     for (std::size_t i = 0; i < mValues.size(); ++i) {
176         T &item = mValues[i];
177         /*
178          * here use template function GetTClassName OutTClassString, needing
179          * specialization.
180          */
181         ss << "[" << GetTClassName<T>() << "_" << (i + 1) << "]" << std::endl;
182         ss << OutTClassString(item) << std::endl;
183     }
184     std::string content = ss.str();
185     int ret = fwrite(content.c_str(), 1, content.length(), fp);
186     if (ret != (int)content.length()) {
187         LOGE("Save config file: %{public}s, fwrite() failed!", mFileName.c_str());
188     }
189     (void)fflush(fp);
190     (void)fsync(fileno(fp));
191     (void)fclose(fp);
192     mValues.clear(); /* clear values */
193     return 0;
194 }
195 
196 template<typename T>
GetValue(std::vector<T> & results)197 int WifiConfigFileImpl<T>::GetValue(std::vector<T> &results)
198 {
199     /*
200      * swap, WifiConfigFileImpl not saved this config when next use, call LoadConfig first
201      */
202     std::swap(results, mValues);
203     return 0;
204 }
205 
206 template <typename T>
GetValue()207 const std::vector<T>& WifiConfigFileImpl<T>::GetValue() const
208 {
209     return mValues;
210 }
211 
212 template <typename T>
SetValue(const std::vector<T> & results)213 int WifiConfigFileImpl<T>::SetValue(const std::vector<T> &results)
214 {
215     mValues = results;
216     return 0;
217 }
218 }  // namespace Wifi
219 }  // namespace OHOS
220 #endif