/**
 * @file    myXml.cpp
 * @brief   XML 解析库实现 — C 接口包装 tinyxml2
 */
#include "myXml.h"
#include "tinyxml2.h"

extern "C"
{

myXmlDoc_t myXml_load_file(const char *path)
{
    if (!path)
    {
        return NULL;
    }

    tinyxml2::XMLDocument *doc = new tinyxml2::XMLDocument();

    if (doc->LoadFile(path) != tinyxml2::XML_SUCCESS)
    {
        delete doc;

        return NULL;
    }

    return (myXmlDoc_t)doc;
}

myXmlDoc_t myXml_new_doc(const char *root_name)
{
    tinyxml2::XMLDocument *doc = new tinyxml2::XMLDocument();

    doc->InsertEndChild(doc->NewDeclaration());

    if (root_name)
    {
        doc->InsertEndChild(doc->NewElement(root_name));
    }

    return (myXmlDoc_t)doc;
}

void myXml_free_doc(myXmlDoc_t doc)
{
    if (doc)
    {
        delete (tinyxml2::XMLDocument *)doc;
    }
}

myXmlElem_t myXml_root_elem(myXmlDoc_t doc)
{
    if (!doc)
    {
        return NULL;
    }

    return (myXmlElem_t)(((tinyxml2::XMLDocument *)doc)->RootElement());
}

int myXml_save_file(myXmlDoc_t doc, const char *path)
{
    if (!doc || !path)
    {
        return -1;
    }

    tinyxml2::XMLDocument *pdoc = (tinyxml2::XMLDocument *)doc;

    return (pdoc->SaveFile(path) == tinyxml2::XML_SUCCESS) ? 0 : -1;
}

myXmlElem_t myXml_first_child(myXmlElem_t parent, const char *name)
{
    if (!parent || !name)
    {
        return NULL;
    }

    return (myXmlElem_t)(((tinyxml2::XMLElement *)parent)->FirstChildElement(name));
}

myXmlElem_t myXml_next_sibling(myXmlElem_t elem, const char *name)
{
    if (!elem || !name)
    {
        return NULL;
    }

    return (myXmlElem_t)(((tinyxml2::XMLElement *)elem)->NextSiblingElement(name));
}

const char *myXml_attr_str(myXmlElem_t elem, const char *name, const char *def_val)
{
    if (!elem || !name)
    {
        return def_val;
    }

    const char *val = ((tinyxml2::XMLElement *)elem)->Attribute(name);

    return val ? val : def_val;
}

float myXml_attr_float(myXmlElem_t elem, const char *name, float def_val)
{
    if (!elem || !name)
    {
        return def_val;
    }

    return ((tinyxml2::XMLElement *)elem)->FloatAttribute(name, def_val);
}

int myXml_attr_int(myXmlElem_t elem, const char *name, int def_val)
{
    if (!elem || !name)
    {
        return def_val;
    }

    return ((tinyxml2::XMLElement *)elem)->IntAttribute(name, def_val);
}

myXmlElem_t myXml_new_child(myXmlElem_t parent, const char *name)
{
    if (!parent || !name)
    {
        return NULL;
    }

    tinyxml2::XMLDocument *doc = ((tinyxml2::XMLElement *)parent)->GetDocument();
    tinyxml2::XMLElement  *el  = doc->NewElement(name);

    if (!el)
    {
        return NULL;
    }

    ((tinyxml2::XMLElement *)parent)->InsertEndChild(el);

    return (myXmlElem_t)(el);
}

void myXml_set_attr(myXmlElem_t elem, const char *name, const char *value)
{
    if (!elem || !name || !value)
    {
        return;
    }

    ((tinyxml2::XMLElement *)elem)->SetAttribute(name, value);
}

void myXml_set_attr_int(myXmlElem_t elem, const char *name, int value)
{
    if (!elem || !name)
    {
        return;
    }

    ((tinyxml2::XMLElement *)elem)->SetAttribute(name, value);
}

void myXml_set_attr_float(myXmlElem_t elem, const char *name, float value)
{
    if (!elem || !name)
    {
        return;
    }

    ((tinyxml2::XMLElement *)elem)->SetAttribute(name, value);
}

} /* extern "C" */
