1+ #ifndef TIGERAPI_PROPERTIES_H
2+ #define TIGERAPI_PROPERTIES_H
3+
4+ #include < string>
5+ #include < map>
6+ #include < fstream>
7+ #include < sstream>
8+ #include " utils.h"
9+
10+ namespace TIGER_API {
11+ class Properties {
12+ public:
13+ void load (std::ifstream& input) {
14+ std::string line;
15+ while (std::getline (input, line)) {
16+ // 跳过空行和注释行
17+ if (line.empty () || line[0 ] == ' #' || line[0 ] == ' !' ) {
18+ continue ;
19+ }
20+
21+ // 查找第一个非转义的等号或冒号
22+ size_t pos = 0 ;
23+ while ((pos = line.find_first_of (" =:" , pos)) != std::string::npos) {
24+ if (pos == 0 || line[pos - 1 ] != ' \\ ' ) {
25+ break ;
26+ }
27+ pos++;
28+ }
29+
30+ if (pos != std::string::npos) {
31+ std::string key = trim (line.substr (0 , pos));
32+ std::string value = trim (line.substr (pos + 1 ));
33+
34+ // 处理转义字符
35+ value = unescape (value);
36+
37+ // 存储为 utility::string_t
38+ properties[utility::conversions::to_string_t (key)] =
39+ utility::conversions::to_string_t (value);
40+ }
41+ }
42+ }
43+
44+ utility::string_t get_property (const utility::string_t & key) const {
45+ auto it = properties.find (key);
46+ if (it != properties.end ()) {
47+ return it->second ;
48+ }
49+ return utility::string_t ();
50+ }
51+
52+ void store (std::ofstream& output) const {
53+ // 写入文件头注释
54+ output << " # Properties" << std::endl;
55+ output << " # " << get_current_datetime () << std::endl;
56+ output << std::endl;
57+
58+ // 写入所有属性
59+ for (const auto & pair : properties) {
60+ std::string key = utility::conversions::to_utf8string (pair.first );
61+ std::string value = utility::conversions::to_utf8string (pair.second );
62+
63+ // 转义特殊字符
64+ key = escape (key);
65+ value = escape (value);
66+
67+ output << key << " =" << value << std::endl;
68+ }
69+ }
70+
71+ private:
72+ std::map<utility::string_t , utility::string_t > properties;
73+
74+ static std::string trim (const std::string& str) {
75+ const std::string whitespace = " \t\n\r\f\v " ;
76+ size_t start = str.find_first_not_of (whitespace);
77+ if (start == std::string::npos) {
78+ return " " ;
79+ }
80+ size_t end = str.find_last_not_of (whitespace);
81+ return str.substr (start, end - start + 1 );
82+ }
83+
84+ static std::string unescape (const std::string& str) {
85+ std::string result;
86+ bool escaped = false ;
87+
88+ for (size_t i = 0 ; i < str.length (); i++) {
89+ if (escaped) {
90+ switch (str[i]) {
91+ case ' n' : result += ' \n ' ; break ;
92+ case ' t' : result += ' \t ' ; break ;
93+ case ' r' : result += ' \r ' ; break ;
94+ case ' \\ ' : result += ' \\ ' ; break ;
95+ default : result += str[i]; break ;
96+ }
97+ escaped = false ;
98+ } else if (str[i] == ' \\ ' ) {
99+ escaped = true ;
100+ } else {
101+ result += str[i];
102+ }
103+ }
104+
105+ return result;
106+ }
107+
108+ static std::string escape (const std::string& str) {
109+ std::string result;
110+ for (char c : str) {
111+ switch (c) {
112+ case ' \n ' : result += " \\ n" ; break ;
113+ case ' \t ' : result += " \\ t" ; break ;
114+ case ' \r ' : result += " \\ r" ; break ;
115+ case ' \\ ' : result += " \\\\ " ; break ;
116+ case ' =' : result += " \\ =" ; break ;
117+ case ' :' : result += " \\ :" ; break ;
118+ case ' ' : result += " \\ " ; break ;
119+ default : result += c; break ;
120+ }
121+ }
122+ return result;
123+ }
124+
125+ static std::string get_current_datetime () {
126+ auto now = std::chrono::system_clock::now ();
127+ auto time = std::chrono::system_clock::to_time_t (now);
128+ std::string timestamp (30 , ' \0 ' );
129+ std::strftime (×tamp[0 ], timestamp.size (),
130+ " %Y-%m-%d %H:%M:%S" ,
131+ std::localtime (&time));
132+ return timestamp;
133+ }
134+ };
135+ }
136+
137+ #endif // TIGERAPI_PROPERTIES_H
0 commit comments