40 inputStream.exceptions(ios_base::failbit | ios_base::badbit);
43 enum State { Init, Comment, SectionName, Key,
Value } state = Init;
44 char currentCharacter;
47 std::size_t whitespace = 0;
48 string sectionName, key, value;
49 sectionName.reserve(16);
54 const auto finishKeyValue = [&state, §ionName, &key, &value, &whitespace,
this] {
55 if (key.empty() && value.empty() && state !=
Value) {
58 if (m_data.empty() || m_data.back().first != sectionName) {
59 m_data.emplace_back(make_pair(sectionName,
decltype(m_data)::value_type::second_type()));
61 m_data.back().second.insert(make_pair(key, value));
69 while (inputStream.get(currentCharacter)) {
73 switch (currentCharacter) {
88 addChar(currentCharacter, key, whitespace);
93 switch (currentCharacter) {
107 addChar(currentCharacter, key, whitespace);
111 switch (currentCharacter) {
119 switch (currentCharacter) {
124 sectionName += currentCharacter;
128 switch (currentCharacter) {
138 addChar(currentCharacter, value, whitespace);
143 }
catch (
const std::ios_base::failure &) {
144 if (!inputStream.eof()) {
217 inputStream.exceptions(ios_base::failbit | ios_base::badbit);
220 enum State { Init, CommentBlock, InlineComment, SectionInlineComment, SectionName, SectionEnd, Key,
Value } state = Init;
221 char currentCharacter;
224 std::string commentBlock, inlineComment, sectionName, key, value;
225 std::size_t keyPadding = 0, valuePadding = 0;
226 commentBlock.reserve(256);
227 inlineComment.reserve(256);
228 sectionName.reserve(16);
233 const auto finishKeyValue = [&,
this] {
234 if (key.empty() && value.empty() && state !=
Value) {
242 .precedingCommentBlock = commentBlock,
243 .followingInlineComment = inlineComment,
244 .paddedKeyLength = key.size() + keyPadding,
248 commentBlock.clear();
249 inlineComment.clear();
250 keyPadding = valuePadding = 0;
255 while (inputStream.get(currentCharacter)) {
259 switch (currentCharacter) {
261 commentBlock += currentCharacter;
264 commentBlock += currentCharacter;
265 state = CommentBlock;
268 keyPadding = valuePadding = 0;
276 addChar(currentCharacter, key, keyPadding);
281 switch (currentCharacter) {
287 state = InlineComment;
288 inlineComment += currentCharacter;
295 addChar(currentCharacter, key, keyPadding);
299 switch (currentCharacter) {
304 commentBlock += currentCharacter;
308 case SectionInlineComment:
309 switch (currentCharacter) {
315 case SectionInlineComment:
316 sections.back().followingInlineComment = inlineComment;
317 inlineComment.clear();
324 inlineComment += currentCharacter;
328 switch (currentCharacter) {
332 sections.back().precedingCommentBlock = commentBlock;
334 commentBlock.clear();
337 sectionName += currentCharacter;
341 switch (currentCharacter) {
346 state = SectionInlineComment;
347 inlineComment += currentCharacter;
350 keyPadding = valuePadding = 0;
357 addChar(currentCharacter, key, keyPadding);
361 switch (currentCharacter) {
367 state = InlineComment;
368 inlineComment += currentCharacter;
371 addChar(currentCharacter, value, valuePadding);
376 }
catch (
const std::ios_base::failure &) {
377 if (!inputStream.eof()) {
391 case SectionInlineComment:
392 sections.emplace_back(
Section{ .name = sectionName, .precedingCommentBlock = commentBlock, .followingInlineComment = inlineComment });
412 outputStream.exceptions(ios_base::failbit | ios_base::badbit);
413 for (
const auto §ion :
sections) {
414 if (!section.precedingCommentBlock.empty()) {
415 outputStream << section.precedingCommentBlock;
418 outputStream <<
'[' << section.name <<
']';
419 if (!section.followingInlineComment.empty()) {
420 outputStream <<
' ' << section.followingInlineComment;
422 outputStream <<
'\n';
424 for (
const auto &field : section.fields) {
425 if (!field.precedingCommentBlock.empty()) {
426 outputStream << field.precedingCommentBlock;
428 outputStream << field.key;
429 for (
auto charsWritten = field.key.size(); charsWritten < field.paddedKeyLength; ++charsWritten) {
433 outputStream <<
'=' <<
' ' << field.value;
435 if (!field.followingInlineComment.empty()) {
439 outputStream << field.followingInlineComment;
441 outputStream <<
'\n';