42 inputStream.exceptions(ios_base::failbit | ios_base::badbit);
45 enum State { Init, Comment, SectionName, Key,
Value } state = Init;
46 char currentCharacter;
49 std::size_t whitespace = 0;
50 string sectionName, key, value;
51 sectionName.reserve(16);
56 const auto finishKeyValue = [&state, §ionName, &key, &value, &whitespace,
this] {
57 if (key.empty() && value.empty() && state !=
Value) {
60 if (m_data.empty() || m_data.back().first != sectionName) {
61 m_data.emplace_back(make_pair(sectionName,
decltype(m_data)::value_type::second_type()));
63 m_data.back().second.insert(make_pair(key, value));
71 while (inputStream.get(currentCharacter)) {
75 switch (currentCharacter) {
90 addChar(currentCharacter, key, whitespace);
95 switch (currentCharacter) {
109 addChar(currentCharacter, key, whitespace);
113 switch (currentCharacter) {
121 switch (currentCharacter) {
126 sectionName += currentCharacter;
130 switch (currentCharacter) {
140 addChar(currentCharacter, value, whitespace);
145 }
catch (
const std::ios_base::failure &) {
146 if (!inputStream.eof()) {
219 inputStream.exceptions(ios_base::failbit | ios_base::badbit);
222 enum State { Init, CommentBlock, InlineComment, SectionInlineComment, SectionName, SectionEnd, Key,
Value } state = Init;
223 char currentCharacter;
226 std::string commentBlock, inlineComment, sectionName, key, value;
227 std::size_t keyPadding = 0, valuePadding = 0;
228 commentBlock.reserve(256);
229 inlineComment.reserve(256);
230 sectionName.reserve(16);
235 const auto finishKeyValue = [&,
this] {
236 if (key.empty() && value.empty() && state !=
Value) {
244 .precedingCommentBlock = commentBlock,
245 .followingInlineComment = inlineComment,
246 .paddedKeyLength = key.size() + keyPadding,
250 commentBlock.clear();
251 inlineComment.clear();
252 keyPadding = valuePadding = 0;
257 while (inputStream.get(currentCharacter)) {
261 switch (currentCharacter) {
263 commentBlock += currentCharacter;
266 commentBlock += currentCharacter;
267 state = CommentBlock;
270 keyPadding = valuePadding = 0;
278 addChar(currentCharacter, key, keyPadding);
283 switch (currentCharacter) {
289 state = InlineComment;
290 inlineComment += currentCharacter;
297 addChar(currentCharacter, key, keyPadding);
301 switch (currentCharacter) {
306 commentBlock += currentCharacter;
310 case SectionInlineComment:
311 switch (currentCharacter) {
317 case SectionInlineComment:
318 sections.back().followingInlineComment = inlineComment;
319 inlineComment.clear();
326 inlineComment += currentCharacter;
330 switch (currentCharacter) {
334 sections.back().precedingCommentBlock = commentBlock;
336 commentBlock.clear();
339 sectionName += currentCharacter;
343 switch (currentCharacter) {
348 state = SectionInlineComment;
349 inlineComment += currentCharacter;
352 keyPadding = valuePadding = 0;
359 addChar(currentCharacter, key, keyPadding);
363 switch (currentCharacter) {
369 state = InlineComment;
370 inlineComment += currentCharacter;
373 addChar(currentCharacter, value, valuePadding);
378 }
catch (
const std::ios_base::failure &) {
379 if (!inputStream.eof()) {
393 case SectionInlineComment:
394 sections.emplace_back(
Section{ .name = sectionName, .precedingCommentBlock = commentBlock, .followingInlineComment = inlineComment });
414 outputStream.exceptions(ios_base::failbit | ios_base::badbit);
415 for (
const auto §ion :
sections) {
416 if (!section.precedingCommentBlock.empty()) {
417 outputStream << section.precedingCommentBlock;
420 outputStream <<
'[' << section.name <<
']';
421 if (!section.followingInlineComment.empty()) {
422 outputStream <<
' ' << section.followingInlineComment;
424 outputStream <<
'\n';
426 for (
const auto &field : section.fields) {
427 if (!field.precedingCommentBlock.empty()) {
428 outputStream << field.precedingCommentBlock;
430 outputStream << field.key;
431 for (
auto charsWritten = field.key.size(); charsWritten < field.paddedKeyLength; ++charsWritten) {
435 outputStream <<
'=' <<
' ' << field.value;
437 if (!field.followingInlineComment.empty()) {
441 outputStream << field.followingInlineComment;
443 outputStream <<
'\n';