diff --git a/meson.build b/meson.build index 49601f7..457c5d4 100644 --- a/meson.build +++ b/meson.build @@ -18,7 +18,6 @@ dyaml_src = [ 'source/dyaml/escapes.d', 'source/dyaml/event.d', 'source/dyaml/exception.d', - 'source/dyaml/flags.d', 'source/dyaml/hacks.d', 'source/dyaml/linebreak.d', 'source/dyaml/loader.d', diff --git a/source/dyaml/emitter.d b/source/dyaml/emitter.d index ea6bbf1..47a8c31 100644 --- a/source/dyaml/emitter.d +++ b/source/dyaml/emitter.d @@ -27,7 +27,6 @@ import dyaml.encoding; import dyaml.escapes; import dyaml.event; import dyaml.exception; -import dyaml.flags; import dyaml.linebreak; import dyaml.queue; import dyaml.style; @@ -53,9 +52,20 @@ struct ScalarAnalysis //Scalar itself. string scalar; + enum AnalysisFlags + { + empty = 1<<0, + multiline = 1<<1, + allowFlowPlain = 1<<2, + allowBlockPlain = 1<<3, + allowSingleQuoted = 1<<4, + allowDoubleQuoted = 1<<5, + allowBlock = 1<<6, + isNull = 1<<7 + } + ///Analysis results. - Flags!("empty", "multiline", "allowFlowPlain", "allowBlockPlain", - "allowSingleQuoted", "allowDoubleQuoted", "allowBlock", "isNull") flags; + BitFlags!AnalysisFlags flags; } private alias isNewLine = among!('\n', '\u0085', '\u2028', '\u2029'); @@ -991,15 +1001,14 @@ struct Emitter(Range, CharType) if (isOutputRange!(Range, CharType)) analysis.scalar = scalar; //Empty scalar is a special case. - with(analysis.flags) if(scalar is null || scalar == "") + if(scalar is null || scalar == "") { - empty = true; - multiline = false; - allowFlowPlain = false; - allowBlockPlain = true; - allowSingleQuoted = true; - allowDoubleQuoted = true; - allowBlock = false; + with(ScalarAnalysis.AnalysisFlags) + analysis.flags = + empty | + allowBlockPlain | + allowSingleQuoted | + allowDoubleQuoted; return analysis; } @@ -1098,52 +1107,107 @@ struct Emitter(Range, CharType) if (isOutputRange!(Range, CharType)) scalar[index + 2].isSpace; } - with(analysis.flags) + with(ScalarAnalysis.AnalysisFlags) { //Let's decide what styles are allowed. - allowFlowPlain = allowBlockPlain = allowSingleQuoted - = allowDoubleQuoted = allowBlock = true; + analysis.flags |= allowFlowPlain | allowBlockPlain | allowSingleQuoted | + allowDoubleQuoted | allowBlock; //Leading and trailing whitespaces are bad for plain scalars. if(leadingSpace || leadingBreak || trailingSpace || trailingBreak) { - allowFlowPlain = allowBlockPlain = false; + analysis.flags &= ~(allowFlowPlain | allowBlockPlain); } //We do not permit trailing spaces for block scalars. - if(trailingSpace){allowBlock = false;} + if(trailingSpace) + { + analysis.flags &= ~allowBlock; + } //Spaces at the beginning of a new line are only acceptable for block //scalars. if(breakSpace) { - allowFlowPlain = allowBlockPlain = allowSingleQuoted = false; + analysis.flags &= ~(allowFlowPlain | allowBlockPlain | allowSingleQuoted); } //Spaces followed by breaks, as well as special character are only //allowed for double quoted scalars. if(spaceBreak || specialCharacters) { - allowFlowPlain = allowBlockPlain = allowSingleQuoted = allowBlock = false; + analysis.flags &= ~(allowFlowPlain | allowBlockPlain | allowSingleQuoted | allowBlock); } //Although the plain scalar writer supports breaks, we never emit //multiline plain scalars. - if(lineBreaks){allowFlowPlain = allowBlockPlain = false;} + if(lineBreaks) + { + analysis.flags &= ~(allowFlowPlain | allowBlockPlain); + analysis.flags |= multiline; + } //Flow indicators are forbidden for flow plain scalars. - if(flowIndicators){allowFlowPlain = false;} + if(flowIndicators) + { + analysis.flags &= ~allowFlowPlain; + } //Block indicators are forbidden for block plain scalars. - if(blockIndicators){allowBlockPlain = false;} - - empty = false; - multiline = lineBreaks; + if(blockIndicators) + { + analysis.flags &= ~allowBlockPlain; + } } - return analysis; } + @safe unittest + { + with(analyzeScalar("").flags) + { + // workaround for empty being std.range.primitives.empty here + alias empty = ScalarAnalysis.AnalysisFlags.empty; + assert(empty && allowBlockPlain && allowSingleQuoted && allowDoubleQuoted); + } + with(analyzeScalar("a").flags) + { + assert(allowFlowPlain && allowBlockPlain && allowSingleQuoted && allowDoubleQuoted && allowBlock); + } + with(analyzeScalar(" ").flags) + { + assert(allowSingleQuoted && allowDoubleQuoted); + } + with(analyzeScalar(" a").flags) + { + assert(allowSingleQuoted && allowDoubleQuoted); + } + with(analyzeScalar("a ").flags) + { + assert(allowSingleQuoted && allowDoubleQuoted); + } + with(analyzeScalar("\na").flags) + { + assert(allowSingleQuoted && allowDoubleQuoted); + } + with(analyzeScalar("a\n").flags) + { + assert(allowSingleQuoted && allowDoubleQuoted); + } + with(analyzeScalar("\n").flags) + { + assert(multiline && allowSingleQuoted && allowDoubleQuoted && allowBlock); + } + with(analyzeScalar(" \n").flags) + { + assert(multiline && allowDoubleQuoted); + } + with(analyzeScalar("\n a").flags) + { + assert(multiline && allowDoubleQuoted && allowBlock); + } + } + //Writers. ///Start the YAML stream (write the unicode byte order mark). diff --git a/source/dyaml/flags.d b/source/dyaml/flags.d deleted file mode 100644 index 71a141b..0000000 --- a/source/dyaml/flags.d +++ /dev/null @@ -1,74 +0,0 @@ - -// Copyright Ferdinand Majerech 2011. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -///Compact storage of multiple boolean values. -module dyaml.flags; - - -import std.conv; - - -package: - -/** - * Struct holding multiple named boolean values in a single byte. - * - * Can hold at most 8 values. - */ -struct Flags(names ...) if(names.length <= 8) -{ - private: - @disable int opCmp(ref Flags); - - ///Byte storing the flags. - ubyte flags_; - - ///Generate a setter and a getter for each flag. - static string flags(string[] names ...) @safe - in - { - assert(names.length <= 8, "Flags struct can only hold 8 flags"); - } - body - { - string result; - foreach(index, name; names) - { - string istr = to!string(index); - result ~= "\n" ~ - "@property bool " ~ name ~ "(bool value) pure @safe nothrow\n" ~ - "{\n" ~ - " flags_ = value ? flags_ | (1 <<" ~ istr ~ ")\n" ~ - " : flags_ & (0xFF ^ (1 << " ~ istr ~"));\n" ~ - " return value;\n" ~ - "}\n" ~ - "\n" ~ - "@property bool " ~ name ~ "() const pure @safe nothrow\n" ~ - "{\n" ~ - " return (flags_ >> " ~ istr ~ ") & 1;\n" ~ - "}\n"; - } - return result; - } - - public: - ///Flag accessors. - mixin(flags(names)); -} -/// -@safe unittest -{ - Flags!("empty", "multiline") flags; - assert(flags.empty == false && flags.multiline == false); - flags.multiline = true; - assert(flags.empty == false && flags.multiline == true); - flags.empty = true; - assert(flags.empty == true && flags.multiline == true); - flags.multiline = false; - assert(flags.empty == true && flags.multiline == false); - flags.empty = false; - assert(flags.empty == false && flags.multiline == false); -}