簡體   English   中英

遍歷 yaml-cpp 中的所有節點,包括遞歸錨點/別名

[英]Iterate Through All Nodes In yaml-cpp Including Recursive Anchor/Alias

給定YAML::Node我們如何訪問該節點內的所有標量節點(以修改它們)? 我最好的猜測是遞歸 function:

void parseNode(YAML::Node node) {
    if (node.IsMap()) {
        for (YAML::iterator it = node.begin(); it != node.end(); ++it) {
            parseNode(it->second);
        }
    }
    else if (node.IsSequence()) {
        for (YAML::iterator it = node.begin(); it != node.end(); ++it) {
            parseNode(*it);
        }
    }
    else if (node.IsScalar()) {
        // Perform modifications here.
    }
}

這對我的需求很好,除了在一種情況下:如果有遞歸錨/別名。 (我認為 YAML 1.2 規范允許這樣做? yaml-cpp在解析時當然不會拋出Exception )例如:

first: &firstanchor
  a: 5
  b: *firstanchor

上面的代碼將重復跟隨錨的別名,直到崩潰(SEGFAULT)可能是由於堆棧問題。 如何克服這個問題?

  • 有沒有更好的方法來遍歷整個未知的Node結構來解決這個問題?
  • 有沒有辦法通過公共 API 從Node檢查它是否是別名,這樣我們就可以維護一堆以前訪問過的別名來檢測循環和中斷。
  • 或者有沒有辦法獲取一些唯一的Node標識符,這樣我就可以維護一堆以前訪問過的節點?
  • 或者最后是這個遞歸錨/別名不符合規范 - 在這種情況下,我如何檢查它的出現以確保我可以返回適當的錯誤?

識別節點最明顯的方法是使用它們的m_pNode指針; 但是,這是不可公開查詢的。 下一個最好的方法是使用bool Node::is(const Node& rhs) const ,遺憾的是它不允許我們在搜索循環時進行任何排序以提高性能。

所以你要做的是維護當前的節點堆棧並在下降之前搜索它,例如

class Visitor {
public:
  using Callback = std::function<void(const YAML::Node&)>;
  Visitor(Callback cb): stack(), cb(cb) {}

  void visitSubgraph(const YAML::Node &cur) {
    stack.push_back(target);
    if (cur.IsMap()) {
      for (const auto &pair : cur) {
        descend(pair.second);
      }
    } else if (node.IsSequence()) {
      for (const auto &child : cur) {
        descend(child);
      }
    } else if (node.IsScalar()) {
      cb(cur);
    }
    stack.pop_back();
  }
private:
  void descend(const YAML::Node &target) {
    for (const auto &item : stack) {
      if (item.is(target)) return;
    }
    visitSubgraph(target);
  }

  std::vector<YAML::Node> stack;
  Callback cb;
};

然后你可以做

Visitor v([](const YAML::Node &scalar) {
  // do whatever with the scalar
});
v.visitSubgraph(node);

(請原諒我的錯誤,我的 C++ 有點生銹;我希望你明白。)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM