fixed leading/trailing newlines with printing to ostreams (fixes #48)

also:
- change internal nan constant to match qNaN bits on x86/ARM
This commit is contained in:
Mark Gillard 2020-07-21 16:11:32 +03:00
parent 7314fbf8c2
commit 9afa43e7c2
10 changed files with 147 additions and 57 deletions

View File

@ -184,7 +184,7 @@ namespace toml
&& !arr->template get_as<table>(0_sz)->is_inline();
};
//values, arrays, and inline tables/table arrays
// values, arrays, and inline tables/table arrays
for (auto&& [k, v] : tbl)
{
const auto type = v.type();
@ -206,7 +206,7 @@ namespace toml
}
}
//non-inline tables
// non-inline tables
for (auto&& [k, v] : tbl)
{
const auto type = v.type();
@ -214,8 +214,8 @@ namespace toml
continue;
auto& child_tbl = *reinterpret_cast<const table*>(&v);
//we can skip indenting and emitting the headers for tables that only contain other tables
//(so we don't over-nest)
// we can skip indenting and emitting the headers for tables that only contain other tables
// (so we don't over-nest)
size_t child_value_count{}; //includes inline tables and non-table arrays
size_t child_table_count{};
size_t child_table_array_count{};
@ -248,19 +248,21 @@ namespace toml
if (child_value_count == 0_sz && (child_table_count > 0_sz || child_table_array_count > 0_sz))
skip_self = true;
if (!skip_self)
base::increase_indent();
key_path.push_back(impl::default_formatter_make_key_segment(k));
if (!skip_self)
{
base::print_newline();
base::print_newline(true);
if (!base::naked_newline())
{
base::print_newline();
base::print_newline(true);
}
base::increase_indent();
base::print_indent();
impl::print_to_stream("["sv, base::stream());
print_key_path();
impl::print_to_stream("]"sv, base::stream());
base::print_newline(true);
base::print_newline();
}
print(child_tbl);
@ -270,7 +272,7 @@ namespace toml
base::decrease_indent();
}
//table arrays
// table arrays
for (auto&& [k, v] : tbl)
{
if (!is_non_inline_array_of_tables(v))
@ -310,6 +312,7 @@ namespace toml
{
base::decrease_indent(); // so root kvps and tables have the same indent
print(tbl);
base::print_newline();
}
break;
}

View File

@ -95,6 +95,12 @@ namespace toml
return (flags_ & format_flags::allow_multi_line_strings) != format_flags::none;
}
[[nodiscard]]
bool naked_newline() const noexcept
{
return naked_newline_;
}
void clear_naked_newline() noexcept
{
naked_newline_ = false;

View File

@ -98,9 +98,17 @@ namespace toml
{
switch (auto source_type = base::source().type())
{
case node_type::table: print(*reinterpret_cast<const table*>(&base::source())); break;
case node_type::array: print(*reinterpret_cast<const array*>(&base::source())); break;
default: base::print_value(base::source(), source_type);
case node_type::table:
print(*reinterpret_cast<const table*>(&base::source()));
base::print_newline();
break;
case node_type::array:
print(*reinterpret_cast<const array*>(&base::source()));
break;
default:
base::print_value(base::source(), source_type);
}
}

View File

@ -1044,7 +1044,7 @@ namespace toml
// and/or std::numeric_limits<double>::infinity() (e.g. due to -ffast-math and friends)
constexpr uint64_t neg_inf = 0b1111111111110000000000000000000000000000000000000000000000000000ull;
constexpr uint64_t pos_inf = 0b0111111111110000000000000000000000000000000000000000000000000000ull;
constexpr uint64_t qnan = 0b0111111111111000000000000000000000000000000000000000000000000000ull;
constexpr uint64_t qnan = 0b1111111111111000000000000000000000000000000000000000000000000001ull;
double rval;
std::memcpy(&rval, inf ? (negative ? &neg_inf : &pos_inf) : &qnan, sizeof(double));
return rval;

View File

@ -9,6 +9,12 @@
#ifdef __clang__
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Weverything"
#elif defined (__GNUC__)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wall"
#pragma GCC diagnostic ignored "-Wextra"
#pragma GCC diagnostic ignored "-Wpadded"
#pragma GCC diagnostic ignored "-Wfloat-equal"
#endif
#if __has_include(<Catch2/single_include/catch2/catch.hpp>)
@ -19,4 +25,7 @@
#ifdef __clang__
#pragma clang diagnostic pop
#elif defined (__GNUC__)
#pragma GCC diagnostic pop
#endif

View File

@ -271,3 +271,48 @@ TEST_CASE("tables - insertion and erasure")
#endif // TOML_WINDOWS_COMPAT
}
TEST_CASE("tables - printing")
{
static constexpr auto to_string = [](std::string_view some_toml)
{
auto val = toml::parse(some_toml);
std::stringstream ss;
ss << val;
return ss.str();
};
{
static constexpr auto some_toml = R"(val1 = 1
val2 = 2
val3 = 3
)"sv; //new line at end!
CHECK(to_string(some_toml) == some_toml);
}
{
static constexpr auto some_toml = R"([a_table]
a = 1
b = 2
c = 3
)"sv; //new line at end!
CHECK(to_string(some_toml) == some_toml);
}
{
static constexpr auto some_toml = R"(val1 = 1
val2 = 2
val3 = 3
[a_table]
a = 1
b = 2
c = 3
)"sv; //new line at end!
CHECK(to_string(some_toml) == some_toml);
}
}

View File

@ -115,15 +115,15 @@ compiler_supports_fast_math = compiler.links('''
fast_math_modes = [ false, true ]
exception_modes = [ true, false ]
strict_modes = [ false, true ]
unreleased_feature_modes = [ false, true ]
cpp20_modes = [ false, true ]
executables = []
counter = 0
foreach cpp20 : cpp20_modes
foreach strict : strict_modes
if cpp20 and not compiler_supports_cpp20
continue
endif
if cpp20 and not compiler_supports_cpp20
continue
endif
foreach unrel : unreleased_feature_modes
foreach fast_math : fast_math_modes
if fast_math and not compiler_supports_fast_math
continue
@ -134,12 +134,6 @@ foreach cpp20 : cpp20_modes
overrides = []
args = []
if compiler_supports_float16
if compiler.get_id() == 'gcc'
args += '-mfp16-format=ieee'
endif
endif
if cpp20
name = 'cpp20'
overrides += 'cpp_std=none'
@ -152,13 +146,6 @@ foreach cpp20 : cpp20_modes
name = 'cpp17'
endif
if strict
name = name + '_strict'
args += '-DTOML_UNRELEASED_FEATURES=0'
else
args += '-DTOML_UNRELEASED_FEATURES=1'
endif
if not exceptions
name = name + '_noexcept'
overrides += 'cpp_eh=none'
@ -172,6 +159,13 @@ foreach cpp20 : cpp20_modes
endif
endif
if unrel
name = name + '_unrel'
args += '-DTOML_UNRELEASED_FEATURES=1'
else
args += '-DTOML_UNRELEASED_FEATURES=0'
endif
if counter % 6 == 3
args += '-DTOML_ALL_INLINE=1'
endif
@ -182,16 +176,11 @@ foreach cpp20 : cpp20_modes
args += '-DUSE_TARTANLLAMA_OPTIONAL=1'
name = name + '_tlopt'
endif
if compiler.get_id() == 'gcc'
args += '-Wno-padded'
args += '-Wno-float-equal'
endif
if compiler.get_id() == 'clang'
args += '-Wno-padded'
args += '-Wno-float-equal'
args += '-Wno-double-promotion'
if compiler_supports_float16
if compiler.get_id() == 'gcc'
args += '-mfp16-format=ieee'
endif
endif
executables += [[

View File

@ -1,3 +1,8 @@
// This file is a part of toml++ and is subject to the the terms of the MIT license.
// Copyright (c) 2019-2020 Mark Gillard <mark.gillard@outlook.com.au>
// See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text.
// SPDX-License-Identifier: MIT
#pragma once
#include "settings.h"
@ -55,7 +60,7 @@ inline double make_infinity(int sign = 1) noexcept
TOML_ATTR(const)
inline double make_nan() noexcept
{
constexpr uint64_t qnan = 0b0111111111111000000000000000000000000000000000000000000000000000ull;
constexpr uint64_t qnan = 0b1111111111111000000000000000000000000000000000000000000000000001ull;
double val;
std::memcpy(&val, &qnan, sizeof(double));
return val;

View File

@ -8,6 +8,12 @@
#ifdef __clang__
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Weverything"
#elif defined (__GNUC__)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wall"
#pragma GCC diagnostic ignored "-Wextra"
#pragma GCC diagnostic ignored "-Wpadded"
#pragma GCC diagnostic ignored "-Wfloat-equal"
#endif
#if __has_include(<tloptional/include/tl/optional.hpp>)
@ -18,5 +24,7 @@
#ifdef __clang__
#pragma clang diagnostic pop
#elif defined (__GNUC__)
#pragma GCC diagnostic pop
#endif

View File

@ -5538,6 +5538,12 @@ namespace toml
return (flags_ & format_flags::allow_multi_line_strings) != format_flags::none;
}
[[nodiscard]]
bool naked_newline() const noexcept
{
return naked_newline_;
}
void clear_naked_newline() noexcept
{
naked_newline_ = false;
@ -5846,7 +5852,7 @@ namespace toml
&& !arr->template get_as<table>(0_sz)->is_inline();
};
//values, arrays, and inline tables/table arrays
// values, arrays, and inline tables/table arrays
for (auto&& [k, v] : tbl)
{
const auto type = v.type();
@ -5868,7 +5874,7 @@ namespace toml
}
}
//non-inline tables
// non-inline tables
for (auto&& [k, v] : tbl)
{
const auto type = v.type();
@ -5876,8 +5882,8 @@ namespace toml
continue;
auto& child_tbl = *reinterpret_cast<const table*>(&v);
//we can skip indenting and emitting the headers for tables that only contain other tables
//(so we don't over-nest)
// we can skip indenting and emitting the headers for tables that only contain other tables
// (so we don't over-nest)
size_t child_value_count{}; //includes inline tables and non-table arrays
size_t child_table_count{};
size_t child_table_array_count{};
@ -5910,19 +5916,21 @@ namespace toml
if (child_value_count == 0_sz && (child_table_count > 0_sz || child_table_array_count > 0_sz))
skip_self = true;
if (!skip_self)
base::increase_indent();
key_path.push_back(impl::default_formatter_make_key_segment(k));
if (!skip_self)
{
base::print_newline();
base::print_newline(true);
if (!base::naked_newline())
{
base::print_newline();
base::print_newline(true);
}
base::increase_indent();
base::print_indent();
impl::print_to_stream("["sv, base::stream());
print_key_path();
impl::print_to_stream("]"sv, base::stream());
base::print_newline(true);
base::print_newline();
}
print(child_tbl);
@ -5932,7 +5940,7 @@ namespace toml
base::decrease_indent();
}
//table arrays
// table arrays
for (auto&& [k, v] : tbl)
{
if (!is_non_inline_array_of_tables(v))
@ -5972,6 +5980,7 @@ namespace toml
{
base::decrease_indent(); // so root kvps and tables have the same indent
print(tbl);
base::print_newline();
}
break;
}
@ -6127,9 +6136,17 @@ namespace toml
{
switch (auto source_type = base::source().type())
{
case node_type::table: print(*reinterpret_cast<const table*>(&base::source())); break;
case node_type::array: print(*reinterpret_cast<const array*>(&base::source())); break;
default: base::print_value(base::source(), source_type);
case node_type::table:
print(*reinterpret_cast<const table*>(&base::source()));
base::print_newline();
break;
case node_type::array:
print(*reinterpret_cast<const array*>(&base::source()));
break;
default:
base::print_value(base::source(), source_type);
}
}
@ -9160,7 +9177,7 @@ namespace toml
// and/or std::numeric_limits<double>::infinity() (e.g. due to -ffast-math and friends)
constexpr uint64_t neg_inf = 0b1111111111110000000000000000000000000000000000000000000000000000ull;
constexpr uint64_t pos_inf = 0b0111111111110000000000000000000000000000000000000000000000000000ull;
constexpr uint64_t qnan = 0b0111111111111000000000000000000000000000000000000000000000000000ull;
constexpr uint64_t qnan = 0b1111111111111000000000000000000000000000000000000000000000000001ull;
double rval;
std::memcpy(&rval, inf ? (negative ? &neg_inf : &pos_inf) : &qnan, sizeof(double));
return rval;