StringNode

문자열 정보를 트리 구조로 가지고 있는 구조체를 만들어 본다.

StringNode는 Data 리스트인 테이블과 자식 StringNode 리스트 Child를 가진다.

명령은 다음과 같다.

void Remove() : 해당 노드와 자식들을 제거한다.
void Insert(const std::string& key, const Data& data) : 해당 노드의 table에 Data를 추가한다.
void Insert(const std::string& key, const StringNode& data) : 해당 노드의 child에 StringNode를 추가한다.
bool Find(const std::string& key, Data& data, bool recursive):  Data를 찾는다. recursive true이면 해당 노드에서만 찾는다.
StringNode* FindNode(const std::string& key) : 해당 노드에서만 String 노드를 찾는다.

#include <map>
#include <string>

struct StringNode;
void RemoveStringNode(StringNode& node);

struct StringNode
{
    struct Data
    {
        std::string type;
        std::string value;
    };

    std::map<std::string, Data> table;
    std::map<std::string, StringNode> child;

    void Remove()
    {
        table.clear();
        RemoveStringNode(*this);
    }

    void Insert(const std::string& key, const Data& data)
    {
        table.insert(std::make_pair(key, data));
    }

    void Insert(const std::string& key, const StringNode& data)
    {
        child.insert(std::make_pair(key, data));
    }

    bool Find(const std::string& key, Data& data, bool recursive = false)
    {
        auto iter = table.find(key);
        if (iter != table.end())
        {
            data.type = iter->second.type;
            data.value = iter->second.value;
            return true;
        }

        if (!recursive)
            return false;

        auto childIter = child.find(key);
        if (childIter != child.end())
        {
            StringNode& node = childIter->second;
            node.Find(key, data);
            return true;
        }
        return false;
    }

    StringNode* FindNode(const std::string& key)
    {
        auto childIter = child.find(key);
        if (childIter != child.end())
        {
            return &childIter->second;
        }
        return nullptr;
    }
};


void RemoveStringNode(StringNode& node)
{
    node.table.clear();
    auto iter = node.child.begin();
    for (; iter != node.child.end(); ++iter)
        RemoveStringNode(iter->second);

    node.child.clear();
}


void TestDataNode()
{
    StringNode root;
    StringNode::Data d;
    d.type = "int"; d.value = "77";
    root.Insert("level", d);
    d.type = "string"; d.value = "jane";
    root.Insert("name", d);

    StringNode child;
    d.type = "float"; d.value = "3.3";
    child.Insert("strength", d);
    d.type = "float"; d.value = "3.4";
    child.Insert("intelligence", d);
    root.Insert("status", child);

    StringNode::Data outData;
    root.Find("name", outData, false);

    StringNode* node = root.FindNode("status");
    root.Remove();
    node = root.FindNode("status");
}

int main()
{
    _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
    {
        TestDataNode();
    }

    return 0;
}

사용법 :

    노드를 하나 만든다.
    StringNode root;

    int 타입의 값 77을  추가한다.  
    StringNode::Data d;
    d.type = "int"; d.value = "77";
    root.Insert("level", d);

    문자열 타입의 값 "jane"을 추가한다.
    d.type = "string"; d.value = "jane";
    root.Insert("name", d);

    자식 노드를 하나 만든다.
    StringNode child;

    float 타입의 값 3.3을 추가한다.
    d.type = "float"; d.value = "3.3";
    child.Insert("strength", d);

    float 타입의 값 3.4을 추가한다.
    d.type = "float"; d.value = "3.4";
    child.Insert("intelligence", d);

    child 노드를 root의 자식 노드로 추가한다.
    root.Insert("status", child);

    root 노드에서 "name"을 검색한다.
    StringNode::Data outData;
    root.Find("name", outData, false);

    root 노드에서 "status" 노드를 찾는다.
    StringNode* node = root.FindNode("status");

    root 노드 포함 하여 모든 자식을 제거한다.
    root.Remove();

    모두 제거 하였기 때문에 node 값은 null이 될것이다.
    node = root.FindNode("status")