@@ -69,36 +69,62 @@ bool file_settings::equals(const file_settings& obj) const noexcept {
69
69
70
70
void file_settings::from_string (const xtd::ustring& text) {
71
71
auto unescaping = [](const ustring& line) {return line.replace (" \\\\ " , " \\ " ).replace (" \\\' " , " \' " ).replace (" \\\" " , " \" " ).replace (" \\ 0" , " \0 " ).replace (" \\ a" , " \a " ).replace (" \\ t" , " \t " ).replace (" \\ r" , " \r " ).replace (" \\ n" , " \n " ).replace (" \\ ;" , " ;" ).replace (" \\ #" , " #" ).replace (" \\ =" , " =" ).replace (" \\ :" , " :" ).replace (" \\ " , " " );};
72
- auto remove_comment = [](const ustring& line) {
72
+ auto separate_comment = [](const ustring& line, ustring& comment ) {
73
73
auto result = line.trim ();
74
74
auto start_with_section = result.starts_with (' [' );
75
75
76
76
auto last_index = result.last_index_of (start_with_section ? ' ]' : ' "' );
77
77
if (last_index == result.npos ) last_index = 0 ;
78
- if (result.index_of_any ({' #' , ' ;' }, last_index) != result.npos ) result = result.remove (result.index_of_any ({' #' , ' ;' }, last_index));
78
+ if (result.index_of_any ({' #' , ' ;' }, last_index) != result.npos ) {
79
+ comment = result.substring (result.index_of_any ({' #' , ' ;' }, last_index));
80
+ result = result.remove (result.index_of_any ({' #' , ' ;' }, last_index));
81
+ }
79
82
return result.trim ();
80
83
};
81
84
section_key_values_.clear ();
85
+ auto comment = ustring::empty_string;
82
86
auto section = ustring::empty_string;
83
- for ( auto line : text. split ({ 10 , 13 }, string_split_options::remove_empty_entries)) {
84
- if ( ustring::is_empty (line) || line. starts_with ( ' ; ' ) || line. starts_with ( ' # ' )) continue ;
87
+ auto comment_break = false ;
88
+ for ( auto line : text. split ({ 10 , 13 } )) {
85
89
line = line.trim ();
86
- if (line.starts_with (' [' )) {
87
- line = remove_comment (line);
88
- if (!line.ends_with (' ]' )) throw format_exception {" Section start with '[' but not end with ']'" , csf_};
89
- section = unescaping (line.substring (1 , line.size () - 2 ));
90
- section_key_values_[section] = {};
91
- }else {
92
- auto key_value = line.split ({' =' });
93
- if (key_value.size () == 1 ) section_key_values_[section][unescaping (key_value[0 ].trim ().trim (' "' ))] = " " ;
94
- else {
95
- auto value = remove_comment (ustring::join (" =" , key_value, 1 ));
96
- if (value.starts_with (' "' ) && value.ends_with (' "' )) value = value.trim (' "' );
97
- if (value.starts_with (' \' ' ) && value.ends_with (' \' ' )) value = value.trim (' \' ' );
98
- section_key_values_[section][unescaping (key_value[0 ].trim ().trim (' "' ))] = unescaping (value);
90
+ if (ustring::is_empty (line)) {
91
+ comment_break = true ;
92
+ } else if (line.starts_with (' ;' ) || line.starts_with (' #' )) {
93
+ if (section_key_values_.empty () && !comment_break) before_all_comment_ += line + " \n " ;
94
+ else comment += line + " \n " ;
95
+ } else {
96
+ comment_break = false ;
97
+ if (line.starts_with (' [' )) {
98
+ auto section_comment = ustring::empty_string;
99
+ line = separate_comment (line, section_comment);
100
+ if (!line.ends_with (' ]' )) throw format_exception {" Section start with '[' but not end with ']'" , csf_};
101
+ section = unescaping (line.substring (1 , line.size () - 2 ));
102
+ if (!ustring::is_empty (section_comment)) section_comment_[section] = section_comment;
103
+ section_key_values_[section] = {};
104
+ if (!ustring::is_empty (comment)) before_section_comment_[section] = comment;
105
+ comment = ustring::empty_string;
106
+ } else {
107
+ // if (!ustring::is_empty(comment)) after_section_comment_[section] = comment;
108
+ // comment = ustring::empty_string;
109
+ auto key_value = line.split ({' =' });
110
+ if (key_value.size () == 1 ) {
111
+ if (!ustring::is_empty (comment)) before_key_comment_[unescaping (key_value[0 ].trim ().trim (' "' ))] = comment;
112
+ section_key_values_[section][unescaping (key_value[0 ].trim ().trim (' "' ))] = " " ;
113
+ } else {
114
+ auto key_comment = ustring::empty_string;
115
+ auto value = separate_comment (ustring::join (" =" , key_value, 1 ), key_comment);
116
+ if (value.starts_with (' "' ) && value.ends_with (' "' )) value = value.trim (' "' );
117
+ if (value.starts_with (' \' ' ) && value.ends_with (' \' ' )) value = value.trim (' \' ' );
118
+ if (!ustring::is_empty (key_comment)) key_comment_[unescaping (key_value[0 ].trim ().trim (' "' ))] = key_comment;
119
+ section_key_values_[section][unescaping (key_value[0 ].trim ().trim (' "' ))] = unescaping (value);
120
+ if (!ustring::is_empty (comment)) before_key_comment_[unescaping (key_value[0 ].trim ().trim (' "' ))] = comment;
121
+ }
122
+ comment = ustring::empty_string;
99
123
}
100
124
}
101
125
}
126
+
127
+ if (!ustring::is_empty (comment)) after_all_comment_ += comment;
102
128
}
103
129
104
130
void file_settings::load (const xtd::ustring& file_path) {
@@ -160,12 +186,33 @@ void file_settings::save_as(ostream& stream) {
160
186
}
161
187
162
188
ustring file_settings::to_string () const noexcept {
189
+ auto split_comment = [](const ustring& comments) {
190
+ auto result = ustring::empty_string;
191
+ for (auto comment : comments.split ({10 , 13 }))
192
+ result += ustring::format (" {}\n " , comment);
193
+ return result;
194
+ };
163
195
auto text = ustring::empty_string;
196
+ if (!ustring::is_empty (before_all_comment_))
197
+ text += split_comment (before_all_comment_);
164
198
for (auto [section, key_value] : section_key_values_) {
165
- if (!ustring::is_empty (section)) text += ustring::format (" {}[{}]\n " , text.size () == 0 ? " " : " \n " , section);
166
- for (auto [key, value] : key_value)
167
- text += ustring::format (" {}={}\n " , key, value.starts_with (' ' ) || value.starts_with (' \t ' ) || value.ends_with (' ' ) || value.ends_with (' \t ' ) || value.contains (" #" ) || value.contains (" ;" ) || value.contains (" =" ) ? ustring::format (" \" {}\" " , value) : value);
199
+ text += text.size () == 0 ? " " : " \n " ;
200
+ auto bs_it = before_section_comment_.find (section);
201
+ if (bs_it != before_section_comment_.end () && !ustring::is_empty (bs_it->second )) text += split_comment (bs_it->second );
202
+ auto s_it = section_comment_.find (section);
203
+ if (!ustring::is_empty (section)) text += ustring::format (" [{}]{}\n " , section, s_it != section_comment_.end () && !ustring::is_empty (s_it->second ) ? ustring::format (" {}" , s_it->second ) : " " );
204
+ auto as_it = after_section_comment_.find (section);
205
+ if (as_it != after_section_comment_.end () && !ustring::is_empty (as_it->second )) text += split_comment (as_it->second );
206
+ for (auto [key, value] : key_value) {
207
+ auto bk_it = before_key_comment_.find (key);
208
+ if (bk_it != before_key_comment_.end () && !ustring::is_empty (bk_it->second )) text += split_comment (bk_it->second );
209
+ auto k_it = key_comment_.find (key);
210
+ text += ustring::format (" {}={}{}\n " , key, value.starts_with (' ' ) || value.starts_with (' \t ' ) || value.ends_with (' ' ) || value.ends_with (' \t ' ) || value.contains (" #" ) || value.contains (" ;" ) || value.contains (" =" ) ? ustring::format (" \" {}\" " , value) : value, k_it != key_comment_.end () && !ustring::is_empty (k_it->second ) ? ustring::format (" {}" , k_it->second ) : " " );
211
+ auto ak_it = after_key_comment_.find (key);
212
+ if (ak_it != after_key_comment_.end () && !ustring::is_empty (ak_it->second )) text += split_comment (ak_it->second );
213
+ }
168
214
}
215
+ if (!ustring::is_empty (after_all_comment_)) text += " \n " + split_comment (after_all_comment_);
169
216
return text;
170
217
}
171
218
0 commit comments