//
//===----------------------------------------------------------------------===//
+#include "llvm/Support/Errc.h"
#include "llvm/Support/YAMLTraits.h"
#include "llvm/ADT/Twine.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/YAMLParser.h"
#include "llvm/Support/raw_ostream.h"
-#include <cstring>
#include <cctype>
+#include <cstring>
using namespace llvm;
using namespace yaml;
// Input
//===----------------------------------------------------------------------===//
-Input::Input(StringRef InputContent, void *Ctxt)
+Input::Input(StringRef InputContent,
+ void *Ctxt,
+ SourceMgr::DiagHandlerTy DiagHandler,
+ void *DiagHandlerCtxt)
: IO(Ctxt),
Strm(new Stream(InputContent, SrcMgr)),
- CurrentNode(NULL) {
+ CurrentNode(nullptr) {
+ if (DiagHandler)
+ SrcMgr.setDiagHandler(DiagHandler, DiagHandlerCtxt);
DocIterator = Strm->begin();
}
Input::~Input() {
}
-error_code Input::error() {
- return EC;
-}
+std::error_code Input::error() { return EC; }
-void Input::setDiagHandler(SourceMgr::DiagHandlerTy Handler, void *Ctxt) {
- SrcMgr.setDiagHandler(Handler, Ctxt);
-}
+// Pin the vtables to this file.
+void Input::HNode::anchor() {}
+void Input::EmptyHNode::anchor() {}
+void Input::ScalarHNode::anchor() {}
+void Input::MapHNode::anchor() {}
+void Input::SequenceHNode::anchor() {}
-bool Input::outputting() const {
+bool Input::outputting() {
return false;
}
bool Input::setCurrentDocument() {
if (DocIterator != Strm->end()) {
Node *N = DocIterator->getRoot();
+ if (!N) {
+ assert(Strm->failed() && "Root is NULL iff parsing failed");
+ EC = make_error_code(errc::invalid_argument);
+ return false;
+ }
+
if (isa<NullNode>(N)) {
// Empty files are allowed and ignored
++DocIterator;
return setCurrentDocument();
}
- TopNode.reset(this->createHNodes(N));
+ TopNode = this->createHNodes(N);
CurrentNode = TopNode.get();
return true;
}
return false;
}
-void Input::nextDocument() {
- ++DocIterator;
+bool Input::nextDocument() {
+ return ++DocIterator != Strm->end();
}
bool Input::mapTag(StringRef Tag, bool Default) {
void Input::beginMapping() {
if (EC)
return;
- MapHNode *MN = dyn_cast<MapHNode>(CurrentNode);
+ // CurrentNode can be null if the document is empty.
+ MapHNode *MN = dyn_cast_or_null<MapHNode>(CurrentNode);
if (MN) {
MN->ValidKeys.clear();
}
UseDefault = false;
if (EC)
return false;
+
+ // CurrentNode is null for empty documents, which is an error in case required
+ // nodes are present.
+ if (!CurrentNode) {
+ if (Required)
+ EC = make_error_code(errc::invalid_argument);
+ return false;
+ }
+
MapHNode *MN = dyn_cast<MapHNode>(CurrentNode);
if (!MN) {
setError(CurrentNode, "not a mapping");
return false;
}
MN->ValidKeys.push_back(Key);
- HNode *Value = MN->Mapping[Key];
+ HNode *Value = MN->Mapping[Key].get();
if (!Value) {
if (Required)
setError(CurrentNode, Twine("missing required key '") + Key + "'");
void Input::endMapping() {
if (EC)
return;
- MapHNode *MN = dyn_cast<MapHNode>(CurrentNode);
+ // CurrentNode can be null if the document is empty.
+ MapHNode *MN = dyn_cast_or_null<MapHNode>(CurrentNode);
if (!MN)
return;
- for (MapHNode::NameToNode::iterator i = MN->Mapping.begin(),
- End = MN->Mapping.end(); i != End; ++i) {
- if (!MN->isValidKey(i->first())) {
- setError(i->second, Twine("unknown key '") + i->first() + "'");
+ for (const auto &NN : MN->Mapping) {
+ if (!MN->isValidKey(NN.first())) {
+ setError(NN.second.get(), Twine("unknown key '") + NN.first() + "'");
break;
}
}
return false;
if (SequenceHNode *SQ = dyn_cast<SequenceHNode>(CurrentNode)) {
SaveInfo = CurrentNode;
- CurrentNode = SQ->Entries[Index];
+ CurrentNode = SQ->Entries[Index].get();
return true;
}
return false;
return false;
if (SequenceHNode *SQ = dyn_cast<SequenceHNode>(CurrentNode)) {
SaveInfo = CurrentNode;
- CurrentNode = SQ->Entries[index];
+ CurrentNode = SQ->Entries[index].get();
return true;
}
return false;
return false;
if (SequenceHNode *SQ = dyn_cast<SequenceHNode>(CurrentNode)) {
unsigned Index = 0;
- for (std::vector<HNode *>::iterator i = SQ->Entries.begin(),
- End = SQ->Entries.end(); i != End; ++i) {
- if (ScalarHNode *SN = dyn_cast<ScalarHNode>(*i)) {
+ for (auto &N : SQ->Entries) {
+ if (ScalarHNode *SN = dyn_cast<ScalarHNode>(N.get())) {
if (SN->value().equals(Str)) {
BitValuesUsed[Index] = true;
return true;
assert(BitValuesUsed.size() == SQ->Entries.size());
for (unsigned i = 0; i < SQ->Entries.size(); ++i) {
if (!BitValuesUsed[i]) {
- setError(SQ->Entries[i], "unknown bit value");
+ setError(SQ->Entries[i].get(), "unknown bit value");
return;
}
}
}
}
-void Input::scalarString(StringRef &S) {
+void Input::scalarString(StringRef &S, bool) {
if (ScalarHNode *SN = dyn_cast<ScalarHNode>(CurrentNode)) {
S = SN->value();
} else {
}
void Input::setError(HNode *hnode, const Twine &message) {
+ assert(hnode && "HNode must not be NULL");
this->setError(hnode->_node, message);
}
EC = make_error_code(errc::invalid_argument);
}
-Input::HNode *Input::createHNodes(Node *N) {
+std::unique_ptr<Input::HNode> Input::createHNodes(Node *N) {
SmallString<128> StringStorage;
if (ScalarNode *SN = dyn_cast<ScalarNode>(N)) {
StringRef KeyStr = SN->getValue(StringStorage);
memcpy(Buf, &StringStorage[0], Len);
KeyStr = StringRef(Buf, Len);
}
- return new ScalarHNode(N, KeyStr);
+ return llvm::make_unique<ScalarHNode>(N, KeyStr);
} else if (SequenceNode *SQ = dyn_cast<SequenceNode>(N)) {
- SequenceHNode *SQHNode = new SequenceHNode(N);
- for (SequenceNode::iterator i = SQ->begin(), End = SQ->end(); i != End;
- ++i) {
- HNode *Entry = this->createHNodes(i);
+ auto SQHNode = llvm::make_unique<SequenceHNode>(N);
+ for (Node &SN : *SQ) {
+ auto Entry = this->createHNodes(&SN);
if (EC)
break;
- SQHNode->Entries.push_back(Entry);
+ SQHNode->Entries.push_back(std::move(Entry));
}
- return SQHNode;
+ return std::move(SQHNode);
} else if (MappingNode *Map = dyn_cast<MappingNode>(N)) {
- MapHNode *mapHNode = new MapHNode(N);
- for (MappingNode::iterator i = Map->begin(), End = Map->end(); i != End;
- ++i) {
- ScalarNode *KeyScalar = dyn_cast<ScalarNode>(i->getKey());
+ auto mapHNode = llvm::make_unique<MapHNode>(N);
+ for (KeyValueNode &KVN : *Map) {
+ Node *KeyNode = KVN.getKey();
+ ScalarNode *KeyScalar = dyn_cast<ScalarNode>(KeyNode);
+ if (!KeyScalar) {
+ setError(KeyNode, "Map key must be a scalar");
+ break;
+ }
StringStorage.clear();
StringRef KeyStr = KeyScalar->getValue(StringStorage);
if (!StringStorage.empty()) {
memcpy(Buf, &StringStorage[0], Len);
KeyStr = StringRef(Buf, Len);
}
- HNode *ValueHNode = this->createHNodes(i->getValue());
+ auto ValueHNode = this->createHNodes(KVN.getValue());
if (EC)
break;
- mapHNode->Mapping[KeyStr] = ValueHNode;
+ mapHNode->Mapping[KeyStr] = std::move(ValueHNode);
}
- return mapHNode;
+ return std::move(mapHNode);
} else if (isa<NullNode>(N)) {
- return new EmptyHNode(N);
+ return llvm::make_unique<EmptyHNode>(N);
} else {
setError(N, "unknown node kind");
- return NULL;
+ return nullptr;
}
}
bool Input::MapHNode::isValidKey(StringRef Key) {
- for (SmallVectorImpl<const char *>::iterator i = ValidKeys.begin(),
- End = ValidKeys.end(); i != End; ++i) {
- if (Key.equals(*i))
+ for (const char *K : ValidKeys) {
+ if (Key.equals(K))
return true;
}
return false;
return false;
}
-Input::MapHNode::~MapHNode() {
- for (MapHNode::NameToNode::iterator i = Mapping.begin(), End = Mapping.end();
- i != End; ++i) {
- delete i->second;
- }
-}
-
-Input::SequenceHNode::~SequenceHNode() {
- for (std::vector<HNode*>::iterator i = Entries.begin(), End = Entries.end();
- i != End; ++i) {
- delete *i;
- }
-}
-
-
-
//===----------------------------------------------------------------------===//
// Output
//===----------------------------------------------------------------------===//
Output::~Output() {
}
-bool Output::outputting() const {
+bool Output::outputting() {
return true;
}
this->outputUpToEndOfLine(" ]");
}
-void Output::scalarString(StringRef &S) {
- const char ScalarSafeChars[] = "abcdefghijklmnopqrstuvwxyz"
- "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-/^., \t";
-
+void Output::scalarString(StringRef &S, bool MustQuote) {
this->newLineCheck();
if (S.empty()) {
// Print '' for the empty string because leaving the field empty is not
this->outputUpToEndOfLine("''");
return;
}
- if (S.find_first_not_of(ScalarSafeChars) == StringRef::npos &&
- !isspace(S.front()) && !isspace(S.back())) {
- // If the string consists only of safe characters, print it out without
- // quotes.
+ if (!MustQuote) {
+ // Only quote if we must.
this->outputUpToEndOfLine(S);
return;
}
Val = Scalar;
return StringRef();
}
+
+void ScalarTraits<std::string>::output(const std::string &Val, void *,
+ raw_ostream &Out) {
+ Out << Val;
+}
+
+StringRef ScalarTraits<std::string>::input(StringRef Scalar, void *,
+ std::string &Val) {
+ Val = Scalar.str();
+ return StringRef();
+}
void ScalarTraits<uint8_t>::output(const uint8_t &Val, void *,
raw_ostream &Out) {