Implemented the Write for scalars (including checking which type of scalar it should be)

This commit is contained in:
Jesse Beder
2012-05-21 19:07:56 -05:00
parent 65d80ebc11
commit d86cfc1c63
3 changed files with 88 additions and 15 deletions

View File

@@ -293,6 +293,17 @@ namespace YAML
void Emitter::PrepareTopNode() void Emitter::PrepareTopNode()
{ {
const bool hasAnchor = m_pState->HasAnchor();
const bool hasTag = m_pState->HasTag();
if(!hasAnchor && !hasTag && m_stream.pos() > 0) {
EmitBeginDoc();
}
// TODO: if we were writing null, and
// we wanted it blank, we wouldn't want a space
if(hasAnchor || hasTag)
m_stream << " ";
} }
void Emitter::FlowSeqPrepareNode() void Emitter::FlowSeqPrepareNode()
@@ -321,6 +332,24 @@ namespace YAML
PrepareNode(); PrepareNode();
const bool escapeNonAscii = m_pState->GetOutputCharset() == EscapeNonAscii;
const StringFormat::value strFormat = Utils::ComputeStringFormat(str, m_pState->GetStringFormat(), m_pState->CurGroupFlowType(), escapeNonAscii);
switch(strFormat) {
case StringFormat::Plain:
m_stream << str;
break;
case StringFormat::SingleQuoted:
Utils::WriteSingleQuotedString(m_stream, str);
break;
case StringFormat::DoubleQuoted:
Utils::WriteDoubleQuotedString(m_stream, str, escapeNonAscii);
break;
case StringFormat::Literal:
Utils::WriteLiteralString(m_stream, str, m_pState->CurIndent() + m_pState->GetIndent());
break;
}
m_pState->BeginScalar(); m_pState->BeginScalar();
return *this; return *this;

View File

@@ -128,12 +128,12 @@ namespace YAML
} }
} }
bool IsValidPlainScalar(const std::string& str, bool inFlow, bool allowOnlyAscii) { bool IsValidPlainScalar(const std::string& str, FlowType::value flowType, bool allowOnlyAscii) {
if(str.empty()) if(str.empty())
return false; return false;
// first check the start // first check the start
const RegEx& start = (inFlow ? Exp::PlainScalarInFlow() : Exp::PlainScalar()); const RegEx& start = (flowType == FlowType::Flow ? Exp::PlainScalarInFlow() : Exp::PlainScalar());
if(!start.Matches(str)) if(!start.Matches(str))
return false; return false;
@@ -142,7 +142,7 @@ namespace YAML
return false; return false;
// then check until something is disallowed // then check until something is disallowed
const RegEx& disallowed = (inFlow ? Exp::EndScalarInFlow() : Exp::EndScalar()) const RegEx& disallowed = (flowType == FlowType::Flow ? Exp::EndScalarInFlow() : Exp::EndScalar())
|| (Exp::BlankOrBreak() + Exp::Comment()) || (Exp::BlankOrBreak() + Exp::Comment())
|| Exp::NotPrintable() || Exp::NotPrintable()
|| Exp::Utf8_ByteOrderMark() || Exp::Utf8_ByteOrderMark()
@@ -152,7 +152,7 @@ namespace YAML
while(buffer) { while(buffer) {
if(disallowed.Matches(buffer)) if(disallowed.Matches(buffer))
return false; return false;
if(allowOnlyAscii && (0x7F < static_cast<unsigned char>(buffer[0]))) if(allowOnlyAscii && (0x80 <= static_cast<unsigned char>(buffer[0])))
return false; return false;
++buffer; ++buffer;
} }
@@ -160,7 +160,32 @@ namespace YAML
return true; return true;
} }
void WriteDoubleQuoteEscapeSequence(ostream& out, int codePoint) { bool IsValidSingleQuotedScalar(const std::string& str, bool escapeNonAscii)
{
// TODO: check for non-printable characters?
for(std::size_t i=0;i<str.size();i++) {
if(escapeNonAscii && (0x80 <= static_cast<unsigned char>(str[i])))
return false;
if(str[i] == '\n')
return false;
}
return true;
}
bool IsValidLiteralScalar(const std::string& str, FlowType::value flowType, bool escapeNonAscii)
{
if(flowType == FlowType::Flow)
return false;
// TODO: check for non-printable characters?
for(std::size_t i=0;i<str.size();i++) {
if(escapeNonAscii && (0x80 <= static_cast<unsigned char>(str[i])))
return false;
}
return true;
}
void WriteDoubleQuoteEscapeSequence(ostream& out, int codePoint) {
static const char hexDigits[] = "0123456789abcdef"; static const char hexDigits[] = "0123456789abcdef";
char escSeq[] = "\\U00000000"; char escSeq[] = "\\U00000000";
@@ -198,14 +223,29 @@ namespace YAML
} }
} }
bool WriteString(ostream& out, const std::string& str, bool inFlow, bool escapeNonAscii) StringFormat::value ComputeStringFormat(const std::string& str, EMITTER_MANIP strFormat, FlowType::value flowType, bool escapeNonAscii)
{ {
if(IsValidPlainScalar(str, inFlow, escapeNonAscii)) { switch(strFormat) {
out << str; case Auto:
return true; if(IsValidPlainScalar(str, flowType, escapeNonAscii))
} else return StringFormat::Plain;
return WriteDoubleQuotedString(out, str, escapeNonAscii); return StringFormat::DoubleQuoted;
} case SingleQuoted:
if(IsValidSingleQuotedScalar(str, escapeNonAscii))
return StringFormat::SingleQuoted;
return StringFormat::DoubleQuoted;
case DoubleQuoted:
return StringFormat::DoubleQuoted;
case Literal:
if(IsValidLiteralScalar(str, flowType, escapeNonAscii))
return StringFormat::Literal;
return StringFormat::DoubleQuoted;
default:
break;
}
return StringFormat::DoubleQuoted;
}
bool WriteSingleQuotedString(ostream& out, const std::string& str) bool WriteSingleQuotedString(ostream& out, const std::string& str)
{ {

View File

@@ -6,6 +6,7 @@
#endif #endif
#include "emitterstate.h"
#include "yaml-cpp/ostream.h" #include "yaml-cpp/ostream.h"
#include <string> #include <string>
@@ -13,9 +14,12 @@ namespace YAML
{ {
class Binary; class Binary;
struct StringFormat { enum value { Plain, SingleQuoted, DoubleQuoted, Literal }; };
namespace Utils namespace Utils
{ {
bool WriteString(ostream& out, const std::string& str, bool inFlow, bool escapeNonAscii); StringFormat::value ComputeStringFormat(const std::string& str, EMITTER_MANIP strFormat, FlowType::value flowType, bool escapeNonAscii);
bool WriteSingleQuotedString(ostream& out, const std::string& str); bool WriteSingleQuotedString(ostream& out, const std::string& str);
bool WriteDoubleQuotedString(ostream& out, const std::string& str, bool escapeNonAscii); bool WriteDoubleQuotedString(ostream& out, const std::string& str, bool escapeNonAscii);
bool WriteLiteralString(ostream& out, const std::string& str, int indent); bool WriteLiteralString(ostream& out, const std::string& str, int indent);