Merge 15fb22eee0 into 39f737443b
This commit is contained in:
commit
75522096e4
151
include/yaml-cpp/tagresolver.h
Normal file
151
include/yaml-cpp/tagresolver.h
Normal file
@ -0,0 +1,151 @@
|
||||
|
||||
#include "yaml-cpp/dll.h"
|
||||
#include "yaml-cpp/eventhandler.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace YAML {
|
||||
struct Mark;
|
||||
|
||||
/**
|
||||
* TagResolver is a base class for tag resolution.
|
||||
* It acts as an event filter: it is an EventHandler itself,
|
||||
* and it passes events on to a client EventHandler
|
||||
* while resolving tags in the process.
|
||||
|
||||
* This base class passes events unmodified.
|
||||
* A subclass is supposed to implement tag resolution
|
||||
* according to a particular schema,
|
||||
* as recommended by the YAML 1.2 spec:
|
||||
* http://yaml.org/spec/1.2/spec.html#Schema
|
||||
|
||||
* Note that each tag in a schema also needs to provide
|
||||
* a canonical representation of its values.
|
||||
* Mapping values into canonical representations
|
||||
* is not the responsibility of TagResolver though.
|
||||
*/
|
||||
|
||||
class YAML_CPP_API TagResolver : public EventHandler
|
||||
{
|
||||
public:
|
||||
using string = std::string;
|
||||
|
||||
TagResolver(EventHandler & client): m_client(client) {}
|
||||
|
||||
virtual void OnDocumentStart(const Mark& mark)
|
||||
{
|
||||
m_client.OnDocumentStart(mark);
|
||||
}
|
||||
|
||||
virtual void OnDocumentEnd()
|
||||
{
|
||||
m_client.OnDocumentEnd();
|
||||
}
|
||||
|
||||
virtual void OnNull(const Mark& mark, anchor_t anchor)
|
||||
{
|
||||
m_client.OnNull(mark, anchor);
|
||||
}
|
||||
|
||||
virtual void OnAlias(const Mark& mark, anchor_t anchor)
|
||||
{
|
||||
m_client.OnAlias(mark, anchor);
|
||||
}
|
||||
|
||||
virtual void OnScalar(const Mark& mark, const std::string& tag,
|
||||
anchor_t anchor, const std::string& value)
|
||||
{
|
||||
m_client.OnScalar(mark, tag, anchor, value);
|
||||
}
|
||||
|
||||
virtual void OnSequenceStart(const Mark& mark, const std::string& tag,
|
||||
anchor_t anchor, EmitterStyle::value style)
|
||||
{
|
||||
m_client.OnSequenceStart(mark, tag, anchor, style);
|
||||
}
|
||||
|
||||
virtual void OnSequenceEnd()
|
||||
{
|
||||
m_client.OnSequenceEnd();
|
||||
}
|
||||
|
||||
virtual void OnMapStart(const Mark& mark, const std::string& tag,
|
||||
anchor_t anchor, EmitterStyle::value style)
|
||||
{
|
||||
m_client.OnMapStart(mark, tag, anchor, style);
|
||||
}
|
||||
|
||||
virtual void OnMapEnd()
|
||||
{
|
||||
m_client.OnMapEnd();
|
||||
}
|
||||
|
||||
EventHandler & m_client;
|
||||
};
|
||||
|
||||
/**
|
||||
* Implements tag resolution according to Core Schema,
|
||||
* as defined by YAML 1.2 spec:
|
||||
* http://yaml.org/spec/1.2/spec.html#id2804923
|
||||
*/
|
||||
|
||||
class YAML_CPP_API CoreTagResolver : public TagResolver
|
||||
{
|
||||
private:
|
||||
|
||||
static bool IsBase10Digit(char c)
|
||||
{
|
||||
return c >= '0' and c <= '9';
|
||||
}
|
||||
|
||||
static bool IsBase8Digit(char c)
|
||||
{
|
||||
return c >= '0' and c <= '7';
|
||||
}
|
||||
|
||||
static bool IsBase16Digit(char c)
|
||||
{
|
||||
return IsBase10Digit(c) || (c >= 'a' and c <= 'f') || (c >= 'A' and c <= 'F');
|
||||
}
|
||||
|
||||
static bool IsBase8Int(const string & text);
|
||||
static bool IsBase16Int(const string & text);
|
||||
static bool isBase10Int(const string & text);
|
||||
|
||||
public:
|
||||
CoreTagResolver(EventHandler & client): TagResolver(client) {}
|
||||
|
||||
static bool TagIsNonSpecific(const string & tag)
|
||||
{
|
||||
return (tag == "?" || tag == "!");
|
||||
}
|
||||
|
||||
|
||||
static bool ScalarIsNull(const string & text)
|
||||
{
|
||||
return (text == "null" || text == "Null" || text == "NULL" || text == "~");
|
||||
}
|
||||
|
||||
static bool ScalarIsBool(const string & text)
|
||||
{
|
||||
return text == "true" ||
|
||||
text == "True" ||
|
||||
text == "TRUE" ||
|
||||
text == "false" ||
|
||||
text == "False" ||
|
||||
text == "FALSE";
|
||||
}
|
||||
|
||||
static bool ScalarIsInt(const string & text);
|
||||
|
||||
static bool ScalarIsFloat(const string & text);
|
||||
|
||||
virtual void OnScalar(const Mark& mark, const std::string& tag,
|
||||
anchor_t anchor, const std::string& value);
|
||||
virtual void OnSequenceStart(const Mark& mark, const std::string& tag,
|
||||
anchor_t anchor, EmitterStyle::value style);
|
||||
virtual void OnMapStart(const Mark& mark, const std::string& tag,
|
||||
anchor_t anchor, EmitterStyle::value style);
|
||||
};
|
||||
|
||||
}
|
||||
187
src/tagresolver.cpp
Normal file
187
src/tagresolver.cpp
Normal file
@ -0,0 +1,187 @@
|
||||
#include "../include/yaml-cpp/tagresolver.h"
|
||||
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
|
||||
namespace YAML {
|
||||
|
||||
bool CoreTagResolver::IsBase8Int(const string & text)
|
||||
{
|
||||
if (text.empty())
|
||||
return false;
|
||||
for (string::size_type i = 0; i < text.size(); ++i)
|
||||
{
|
||||
if (!IsBase8Digit(text[i]))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CoreTagResolver::IsBase16Int(const string & text)
|
||||
{
|
||||
if (text.empty())
|
||||
return false;
|
||||
for (string::size_type i = 0; i < text.size(); ++i)
|
||||
{
|
||||
if (!IsBase16Digit(text[i]))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CoreTagResolver::isBase10Int(const string & text)
|
||||
{
|
||||
using namespace std;
|
||||
|
||||
if (text.empty())
|
||||
return false;
|
||||
string::size_type pos = 0;
|
||||
if ( text[pos] == '-' ||
|
||||
text[pos] == '+' )
|
||||
pos += 1;
|
||||
if (pos == text.size())
|
||||
return false;
|
||||
for (; pos < text.size(); ++pos)
|
||||
{
|
||||
if (!IsBase10Digit(text[pos]))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CoreTagResolver::ScalarIsInt(const string & text)
|
||||
{
|
||||
if (text.substr(0,2) == "0o")
|
||||
{
|
||||
return IsBase8Int(text.substr(2));
|
||||
}
|
||||
else if (text.substr(0,2) == "0x")
|
||||
{
|
||||
return IsBase16Int(text.substr(2));
|
||||
}
|
||||
else
|
||||
{
|
||||
return isBase10Int(text);
|
||||
}
|
||||
}
|
||||
|
||||
bool CoreTagResolver::ScalarIsFloat(const string & text)
|
||||
{
|
||||
static std::vector<string> inf = { ".inf", ".Inf", ".INF" };
|
||||
static std::vector<string> nan = { ".nan", ".NaN", ".NAN" };
|
||||
|
||||
if (text.empty())
|
||||
return false;
|
||||
|
||||
if (std::find(nan.begin(), nan.end(), text) != nan.end())
|
||||
return true;
|
||||
|
||||
string::size_type pos = 0;
|
||||
|
||||
if ( text[0] == '-' ||
|
||||
text[0] == '+' )
|
||||
{
|
||||
pos += 1;
|
||||
}
|
||||
|
||||
if (pos == text.size())
|
||||
return false;
|
||||
|
||||
if (std::find(inf.begin(), inf.end(), text.substr(pos)) != inf.end())
|
||||
return true;
|
||||
|
||||
string::size_type intStart = pos;
|
||||
while(pos < text.size() && IsBase10Digit(text[pos]))
|
||||
{
|
||||
++pos;
|
||||
}
|
||||
bool hasInt = pos > intStart;
|
||||
|
||||
if (pos == text.size())
|
||||
return false;
|
||||
|
||||
if (text[pos] != '.')
|
||||
return false;
|
||||
++pos;
|
||||
|
||||
string::size_type fracStart = pos;
|
||||
while(pos < text.size() && IsBase10Digit(text[pos]))
|
||||
{
|
||||
++pos;
|
||||
}
|
||||
bool hasFrac = pos > fracStart;
|
||||
|
||||
if (!hasInt && !hasFrac)
|
||||
return false;
|
||||
|
||||
if (pos == text.size())
|
||||
return true;
|
||||
|
||||
if (text[pos] != 'e' && text[pos] != 'E')
|
||||
return false;
|
||||
++pos;
|
||||
|
||||
if ( text[pos] == '-' || text[pos] == '+' )
|
||||
++pos;
|
||||
|
||||
string::size_type expStart = pos;
|
||||
while(pos < text.size() && IsBase10Digit(text[pos]))
|
||||
{
|
||||
++pos;
|
||||
}
|
||||
if (pos == expStart)
|
||||
return false;
|
||||
if (pos != text.size())
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
void CoreTagResolver::OnScalar(const Mark& mark, const std::string& tag,
|
||||
anchor_t anchor, const std::string& value)
|
||||
{
|
||||
if (tag == "!")
|
||||
{
|
||||
TagResolver::OnScalar(mark, "tag:yaml.org,2002:str", anchor, value);
|
||||
}
|
||||
else if (tag == "?")
|
||||
{
|
||||
string resolved_tag;
|
||||
|
||||
if (ScalarIsNull(value))
|
||||
resolved_tag = "tag:yaml.org,2002:null";
|
||||
else if (ScalarIsBool(value))
|
||||
resolved_tag = "tag:yaml.org,2002:bool";
|
||||
else if (ScalarIsInt(value))
|
||||
resolved_tag = "tag:yaml.org,2002:int";
|
||||
else if (ScalarIsFloat(value))
|
||||
resolved_tag = "tag:yaml.org,2002:float";
|
||||
else
|
||||
resolved_tag = "tag:yaml.org,2002:str";
|
||||
|
||||
TagResolver::OnScalar(mark, resolved_tag, anchor, value);
|
||||
}
|
||||
else
|
||||
{
|
||||
TagResolver::OnScalar(mark, tag, anchor, value);
|
||||
}
|
||||
}
|
||||
|
||||
void CoreTagResolver::OnSequenceStart(const Mark& mark, const std::string& tag,
|
||||
anchor_t anchor, EmitterStyle::value style)
|
||||
{
|
||||
if (TagIsNonSpecific(tag))
|
||||
TagResolver::OnSequenceStart(mark, "tag:yaml.org,2002:seq", anchor, style);
|
||||
else
|
||||
TagResolver::OnSequenceStart(mark, tag, anchor, style);
|
||||
}
|
||||
|
||||
void CoreTagResolver::OnMapStart(const Mark& mark, const std::string& tag,
|
||||
anchor_t anchor, EmitterStyle::value style)
|
||||
{
|
||||
if (TagIsNonSpecific(tag))
|
||||
TagResolver::OnMapStart(mark, "tag:yaml.org,2002:map", anchor, style);
|
||||
else
|
||||
TagResolver::OnMapStart(mark, tag, anchor, style);
|
||||
}
|
||||
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user