<commit_before>#include "./test_group.hpp"
#include <string>

namespace c4 {
namespace yml {

/**
    See also issue 263.
 */

C4_SUPPRESS_WARNING_GCC_WITH_PUSH("-Wuseless-cast")

constexpr const NodeType_e DQV = (NodeType_e)(DOC | QV);

TEST(empty_scalar, parse_zero_length_strings)
{
    char inp[] = R"(
- ""
- ''
- >
- |
)";

    Tree tr = parse_in_place(inp);

    ASSERT_EQ(tr.rootref().num_children(), 4);
    for(const auto &child : tr.rootref().children())
    {
        ASSERT_EQ(child.type(), QV);
        ASSERT_EQ(child.val(), "");
        ASSERT_FALSE(child.val_is_null());
    }
}

TEST(empty_scalar, build_zero_length_string)
{
    Tree tr;
    NodeRef root = tr.rootref();
    root |= MAP;

    NodeRef non_quoted = root["non_quoted"];
    non_quoted |= SEQ;

    const std::string e;  // empty std::string

    non_quoted.append_child() << "";
    non_quoted.append_child() = "";
    non_quoted.append_child() << e;

    NodeRef quoted = root["quoted"];
    quoted |= SEQ;
    {auto r = quoted.append_child(); r << ""; r.set_type(r.type() | VALQUO);}
    {auto r = quoted.append_child(); r = "";  r.set_type(r.type() | VALQUO);}
    {auto r = quoted.append_child(); r << e;  r.set_type(r.type() | VALQUO);}

    ASSERT_EQ(non_quoted.num_children(), 3);
    for(const auto &child : non_quoted.children())
    {
        EXPECT_EQ(child.type(), VAL);
        EXPECT_EQ(child.val(), "");
        EXPECT_FALSE(child.val_is_null());
    }

    ASSERT_EQ(quoted.num_children(), 3);
    for(const auto &child : quoted.children())
    {
        EXPECT_EQ(child.type(), VAL | VALQUO);
        EXPECT_EQ(child.val(), "");
        EXPECT_FALSE(child.val_is_null());
    }
}

CASE_GROUP(EMPTY_SCALAR)
{
ADD_CASE_TO_GROUP("empty scalar, single quoted",
                  "''",
                  N(DQV, "")
);
}

} // namespace yml
} // namespace c4

C4_SUPPRESS_WARNING_GCC_POP<commit_msg>[impl] refine required behavior with null/non-null empty scalars<commit_after>#include "./test_group.hpp"
#include <string>

namespace c4 {
namespace yml {

// See also issue 263: https://github.com/biojppm/rapidyaml/issues/263

C4_SUPPRESS_WARNING_GCC_WITH_PUSH("-Wuseless-cast")

constexpr const NodeType_e DQV = (NodeType_e)(DOC | QV);

TEST(empty_scalar, parse_zero_length_strings)
{
    char inp[] = R"(
seq:
  - ""
  - ''
  - >
  - |
map:
  a: ""
  b: ''
  c: >
  d: |
)";
    const Tree tr = parse_in_place(inp);
    EXPECT_TRUE(tr["seq"].has_key());
    EXPECT_TRUE(tr["map"].has_key());
    EXPECT_TRUE(tr["seq"].is_seq());
    EXPECT_TRUE(tr["map"].is_map());
    for(const char *name : {"seq", "map"})
    {
        NodeRef node = tr[to_csubstr(name)];
        ASSERT_EQ(node.num_children(), 4);
        for(const auto &child : node.children())
        {
            EXPECT_TRUE(child.is_val_quoted());
            EXPECT_EQ(child.val(), "");
            EXPECT_FALSE(child.val_is_null());
        }
    }
}

TEST(empty_scalar, parse_empty_strings)
{
    char inp[] = R"(
# use multiple empty entries to ensure the parser
# correctly deals with the several cases
seq:
  -
  -
  - 
  -
map:
  a:
  b:
  c: 
  d: 
)";
    const Tree tr = parse_in_place(inp);
    for(const char *name : {"seq", "map"})
    {
        NodeRef node = tr[to_csubstr(name)];
        ASSERT_EQ(node.num_children(), 4);
        for(const auto &child : node.children())
        {
            EXPECT_FALSE(child.type().is_val_quoted());
            EXPECT_EQ(child.val(), "");
            EXPECT_TRUE(child.val_is_null());
        }
    }
}

TEST(empty_scalar, build_zero_length_string)
{
    Tree tr;
    NodeRef root = tr.rootref();
    root |= MAP;
    auto addseq = [&root](csubstr name) { NodeRef n = root[name]; n |= SEQ; return n; };

    // try both with nonnull-zero-length and null-zero-length
    csubstr empty = csubstr("nonempty").first(0);
    csubstr nullss = {};

    // these are the conditions we wish to cover:
    ASSERT_TRUE(nullss.str == nullptr);
    ASSERT_TRUE(nullss.len == 0u);
    ASSERT_TRUE(empty.str != nullptr);
    ASSERT_TRUE(empty.len == 0u);

    // = and << must have exactly the same behavior where nullity is
    // regarded

    // quoted cases will never be null, regardless of the
    // incoming scalar
    NodeRef quoted = addseq("quoted");
    {NodeRef r = quoted.append_child(); r = ""      ; r.set_type(r.type() | VALQUO);}
    {NodeRef r = quoted.append_child(); r << ""     ; r.set_type(r.type() | VALQUO);}
    {NodeRef r = quoted.append_child(); r = empty   ; r.set_type(r.type() | VALQUO);}
    {NodeRef r = quoted.append_child(); r << empty  ; r.set_type(r.type() | VALQUO);}
    {NodeRef r = quoted.append_child(); r = nullss  ; r.set_type(r.type() | VALQUO);}
    {NodeRef r = quoted.append_child(); r << nullss ; r.set_type(r.type() | VALQUO);}
    {NodeRef r = quoted.append_child(); r = nullptr ; r.set_type(r.type() | VALQUO);}
    {NodeRef r = quoted.append_child(); r << nullptr; r.set_type(r.type() | VALQUO);}
    ASSERT_TRUE(quoted.has_children());
    for(const auto &child : quoted.children())
    {
        EXPECT_TRUE(child.is_val_quoted());
        EXPECT_EQ(child.val(), "");
        EXPECT_EQ(child.val(), nullptr);
        EXPECT_FALSE(child.val_is_null());
    }

    // ... but according to the incoming scalar, non quoted cases may
    // or may not be null
    NodeRef non_quoted = addseq("nonquoted");
    non_quoted.append_child() = "";
    non_quoted.append_child() << "";
    non_quoted.append_child() = empty;
    non_quoted.append_child() << empty;
    non_quoted.append_child() = nullss;
    non_quoted.append_child() << nullss;
    non_quoted.append_child() = nullptr;
    non_quoted.append_child() << nullptr;
    ASSERT_TRUE(non_quoted.has_children());
    size_t pos = 0;
    for(const auto &child : non_quoted.children())
    {
        EXPECT_TRUE(child.is_val());
        EXPECT_EQ(child.val(), "");
        EXPECT_EQ(child.val(), nullptr);
        if(pos < 4u)
            EXPECT_FALSE(child.val_is_null()) << "pos=" << pos;
        else
            EXPECT_TRUE(child.val_is_null()) << "pos=" << pos;
        ++pos;
    }
}

CASE_GROUP(EMPTY_SCALAR)
{
ADD_CASE_TO_GROUP("empty scalar, single quoted",
                  "''",
                  N(DQV, "")
);
}

} // namespace yml
} // namespace c4

C4_SUPPRESS_WARNING_GCC_POP
{'fraction_non_alphanumeric': 0.16404387219837863, 'fraction_numerical': 0.004291845493562232, 'mean_word_length': 2.845965770171149, 'pattern_counts': {'":': 0, '<': 40, '<?xml version=': 0, '>': 8, 'https://': 1, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3190632', 'n_tokens_mistral': 2276, 'n_tokens_neox': 2258, 'n_words': 425}