C++ XML类代码实现

//--------------------------------------------------------------------
// 文件名:        XmlFile.cpp
// 内  容:        
// 说  明:        
// 创建日期:    
// 创建人:        
// 版权所有:    
//--------------------------------------------------------------------

#include "XmlFile.h"
#include "../public/Inlines.h"
#include "../public/Module.h"
#include "../public/CoreFile.h"

/// \file CXmlFile.cpp
/// \brief xml文件

/// entity: CXmlFile
/// \brief xml文件实体
DECLARE_ENTITY("", CXmlFile, IEntity);

/// property: string Name
/// \brief 名字(和文件名一致,为了方便调试)
//DECLARE_PROPERTY_GET(const char*, CXmlFile, Name, GetName);

/// property: string FileName
/// \brief 文件名
DECLARE_PROPERTY(const char*, CXmlFile, FileName, GetFileName,
SetFileName);

/// method: bool LoadFromFile()
/// \brief 从文件读取
DECLARE_METHOD_0(bool, CXmlFile, LoadFromFile);
/// method: bool SaveToFile()
/// \brief 保存到文件
DECLARE_METHOD_0(bool, CXmlFile, SaveToFile);

/// method: bool AddSection(string section)
/// \brief 添加段
/// \param section 段名
DECLARE_METHOD_1(bool, CXmlFile, AddSection, const char*);
/// method: bool FindSection(string section)
/// \brief 查找段
/// \param section 段名
DECLARE_METHOD_1(bool, CXmlFile, FindSection, const char*);
/// method: bool DeleteSection(string section)
/// \brief 删除段
/// \param section 段名
DECLARE_METHOD_1(bool, CXmlFile, DeleteSection, const char*);
/// method: int GetSectionCount()
/// \brief 获得段数量
DECLARE_METHOD_0(size_t, CXmlFile, GetSectionCount);
/// method: table GetSectionList()
/// \brief 获得段列表
DECLARE_METHOD_T(CXmlFile, GetSectionList);

/// method: bool FindItem(string section, string key)
/// \brief 查找项
/// \param section 段名
/// \param key 键名
DECLARE_METHOD_2(bool, CXmlFile, FindItem, const char*, const char*);
/// method: bool DeleteItem(string section, string key)
/// \brief 删除项
/// \param section 段名
/// \param key 键名
DECLARE_METHOD_2(bool, CXmlFile, DeleteItem, const char*, const char*);
/// method: bool GetItemCount(string section)
/// \brief 获得指定段下的项数量
/// \param section 段名
DECLARE_METHOD_1(size_t, CXmlFile, GetItemCount, const char*);
/// method: table GetItemList(string section)
/// \brief 获得指定段下的项列表
/// \param section 段名
DECLARE_METHOD_T(CXmlFile, GetItemList);
/// method: table GetItemValueList(string section, string key)
/// \brief 获得段下指定键的值列表
/// \param section 段名
/// \param key 键名
DECLARE_METHOD_T(CXmlFile, GetItemValueList);

/// method: int ReadInteger(string section, string key, int def)
/// \brief 读取整数值
/// \param section 段名
/// \param key 键名
/// \param def 缺省值
DECLARE_METHOD_3(int, CXmlFile, ReadInteger, const char*, const char*,
int);
/// method: float ReadFloat(string section, string key, float def)
/// \brief 读取浮点数值
/// \param section 段名
/// \param key 键名
/// \param def 缺省值
DECLARE_METHOD_3(float, CXmlFile, ReadFloat, const char*, const char*,
float);
/// method: string ReadString(string section, string key, string def)
/// \brief 读取字符串值
/// \param section 段名
/// \param key 键名
/// \param def 缺省值
DECLARE_METHOD_3(const char*, CXmlFile, ReadString, const char*,
const char*, const char*);

/// method: bool WriteInteger(string section, string key, int value)
/// \brief 写入不重复的整数值
/// \param section 段名
/// \param key 键名
/// \param value 键值
DECLARE_METHOD_3(bool, CXmlFile, WriteInteger, const char*, const char*,
int);
/// method: bool WriteFloat(string section, string key, float value)
/// \brief 写入不重复的浮点数值
/// \param section 段名
/// \param key 键名
/// \param value 键值
DECLARE_METHOD_3(bool, CXmlFile, WriteFloat, const char*, const char*,
float);
/// method: bool WriteString(string section, string key, string value)
/// \brief 写入不重复的字符串值
/// \param section 段名
/// \param key 键名
/// \param value 键值
DECLARE_METHOD_3(bool, CXmlFile, WriteString, const char*, const char*,
const char*);

/// method: bool AddInteger(string section, string key, int value)
/// \brief 添加有可能重复的整数值
/// \param section 段名
/// \param key 键名
/// \param value 键值
DECLARE_METHOD_3(bool, CXmlFile, AddInteger, const char*, const char*, int);
/// method: bool AddFloat(string section, string key, float value)
/// \brief 添加有可能重复的浮点数值
/// \param section 段名
/// \param key 键名
/// \param value 键值
DECLARE_METHOD_3(bool, CXmlFile, AddFloat, const char*, const char*, float);
/// method: bool AddString(string section, string key, string value)
/// \brief 添加有可能重复的字符串值
/// \param section 段名
/// \param key 键名
/// \param value 键值
DECLARE_METHOD_3(bool, CXmlFile, AddString, const char*, const char*, const char*);

/// method: const char* GetSectionByIndex(size_t index) const;
/// \brief 获得指定段名
/// \param index 序号
DECLARE_METHOD_1(const char*, CXmlFile, GetSectionByIndex, size_t);

CXmlFile::CXmlFile()
{
    m_pXmlValue = 0;
}

CXmlFile::CXmlFile(const char* filename):
m_strFileName(filename)
{
    Assert(filename != NULL);
    
    m_pXmlValue = 0;
}

CXmlFile::~CXmlFile()
{
    ReleaseRes();
}

void CXmlFile::Release()
{
    if (!GetID().IsNull())
    {
        // create from CreateEntity
        GetCore()->DeleteEntity(GetID());
    }
    else
    {
        // create from  NewInstance
        delete this;
    }
}

void CXmlFile::ReleaseRes()
{
    const int section_size = static_cast<int>(m_sectionVec.size());
    for (int i = 0; i < section_size; ++i)
    {
        const section_t_xml * pSection = m_sectionVec[i];
        if (0 != pSection)
        {
            delete pSection;
            pSection = 0;
        }
    }

    m_sectionVec.clear();

    const int item_size = static_cast<int>(m_itemVec.size());
    for (int i = 0; i < item_size; ++i)
    {
        const item_t_xml * pItem = m_itemVec[i];
        if (0 != pItem)
        {
            delete pItem;
            pItem = 0;
        }
    }

    m_itemVec.clear();

    m_sectionMap.clear();

    m_doc.clear();
    if (0 != m_pXmlValue)
    {
        delete[] m_pXmlValue;
        m_pXmlValue = 0;
    }
}

void CXmlFile::SetFileName(const char *filename)
{
    Assert(filename != NULL);

    m_strFileName = filename;
}

const char* CXmlFile::GetFileName() const
{
    return m_strFileName.c_str();
}

bool CXmlFile::LoadFromFile()
{
    ReleaseRes();
    
    FILE *file = NULL;

    file = core_file::fopen(m_strFileName.c_str(), "rb");
    if (file == NULL)
    {
        return false;
    }

    long lengths = 0;
    core_file::fseek( file, 0, SEEK_END );
    lengths = core_file::ftell( file );
    core_file::fseek(file, 0, SEEK_SET);
    
    m_pXmlValue = NEW char[lengths +1 ];

    memset(m_pXmlValue, 0, lengths +1 );
    size_t result = core_file::fread(m_pXmlValue, sizeof(char),lengths, file );
    if (result == 0)
    {
        delete[] m_pXmlValue;
        m_pXmlValue = 0;

        return false;
    }

    m_pXmlValue[lengths] = '\0';
    core_file::fclose(file);

//    rapidxml::xml_document<>  doc;
    rapidxml::xml_node<char> * pNodeRoot = NULL;

    //将文件加载到数据表
    m_doc.clear();
    m_doc.parse<0>(m_pXmlValue);

    pNodeRoot = m_doc.first_node("Object");
    if(NULL == pNodeRoot)
    {
        m_doc.clear();
        delete[] m_pXmlValue;
        m_pXmlValue = 0;

        return false;
    }

    rapidxml::xml_node<char> *pNodeProperty = pNodeRoot->first_node("Property");

    if (NULL == pNodeProperty)
    {
        m_doc.clear();
        delete[] m_pXmlValue;
        m_pXmlValue = 0;

        return true;
    }

    while (pNodeProperty)
    {
        rapidxml::xml_attribute<char> *attr = pNodeProperty->first_attribute();

        if (attr)
        {
            const char * name = attr->value();

            size_t hash_value = GetHashValue(name);

            // 缺省名字为空的段
            section_t_xml * pSection =
                NEW section_t_xml(name, (unsigned int)hash_value, m_itemVec.size(), 0);

            rapidxml::xml_attribute<char>* pXmlAttribut =  attr->next_attribute();

            while(pXmlAttribut)
            {
                const char * itemname = pXmlAttribut->name();
                const char * itemvalue = pXmlAttribut->value();
                const int hash = GetHashValue(itemname);

                item_t_xml * pItem =
                    NEW item_t_xml(itemname, hash, itemvalue);

                m_itemVec.push_back(pItem);

                pSection->m_nItemCount++;
                pXmlAttribut = pXmlAttribut->next_attribute();
            }

            m_sectionMap.insert(std::make_pair(hash_value,
                                               m_sectionVec.size()));

            m_sectionVec.push_back(pSection);
        }

        pNodeProperty = pNodeProperty->next_sibling("Property");
    }
    //m_doc.clear();
    //delete[] m_pXmlValue;
    return true;
}

bool CXmlFile::LoadFromFile_Rapid()
{
    return LoadFromFile();
}

bool CXmlFile::LoadFromString(const char* str, size_t size)
{
    Assert(str != NULL);

    ReleaseRes();

    const size_t len = strlen(str) + 1;
    
    m_pXmlValue = NEW char[len];
    strncpy(m_pXmlValue, str, len);
    m_pXmlValue[len] = '\0';

//    rapidxml::xml_document<>  doc;
    rapidxml::xml_node<char> * pNodeRoot = NULL;

    //将文件加载到数据表
    m_doc.clear();
    m_doc.parse<0>((char*)m_pXmlValue);

    pNodeRoot = m_doc.first_node("Object");
    if(pNodeRoot == NULL)
    {
        m_doc.clear();
        delete[] m_pXmlValue;
        m_pXmlValue = 0;

        return false;
    }

    rapidxml::xml_node<char> *pNodeProperty = pNodeRoot->first_node("Property");

    if (NULL == pNodeProperty)
    {
        m_doc.clear();
        delete[] m_pXmlValue;
        m_pXmlValue = 0;
        
        return true;
    }

    while (pNodeProperty)
    {
        rapidxml::xml_attribute<char> *attr = pNodeProperty->first_attribute();

        if (attr)
        {
            const char * name = attr->value();

            // 缺省名字为空的段
            section_t_xml * pSection =
                NEW section_t_xml(name, GetHashValue(name), m_itemVec.size(), 0);

            rapidxml::xml_attribute<char>* pXmlAttribut =  attr->next_attribute();

            while(pXmlAttribut)
            {
                const char * itemname = pXmlAttribut->name();
                const char * itemvalue = pXmlAttribut->value();
                const int hash = GetHashValue(itemname);
                
                item_t_xml * pItem =
                    NEW item_t_xml(itemname, hash, itemvalue);

                m_itemVec.push_back(pItem);

                pSection->m_nItemCount++;
                pXmlAttribut =  pXmlAttribut->next_attribute();

            }

            m_sectionVec.push_back(pSection);
        }

        pNodeProperty = pNodeProperty->next_sibling("Property");
    }


    return true;
}

bool CXmlFile::FindSection(const char* section_name) const
{
    Assert(section_name != NULL);

    return (GetSection(section_name) != NULL);
}

bool CXmlFile::FindSectionIndex(const char* section_name, size_t& index) const
{
    Assert(section_name != NULL);

    unsigned int hash = GetHashValue(section_name);

    const size_t SIZE1 = m_sectionVec.size();

    for (size_t i = 0; i < SIZE1; ++i)
    {
        const section_t_xml * pSection = m_sectionVec[i];
        if (0 != pSection &&
            pSection->m_nHash == hash &&
            stricmp(pSection->m_strName, section_name) == 0)
        {
            index = i;
            return true;
        }
    }

    return false;
}

bool CXmlFile::FindSectionItemIndex(size_t sect_index, const char* key,
                                    size_t& item_index) const
{
    Assert(sect_index < m_sectionVec.size());
    Assert(key != NULL);

    const section_t_xml * pSection = m_sectionVec[sect_index];
    if (0 == pSection)
    {
        return false;
    }

    unsigned int hash = GetHashValue(key);

    const size_t SIZE1 = pSection->m_nItemStart + pSection->m_nItemCount;

    for (size_t i = pSection->m_nItemStart; i < SIZE1; ++i)
    {
        const item_t_xml * pItem = m_itemVec[i];
        if (0 != pItem &&
            pItem->m_nHash == hash &&
            stricmp(pItem->m_strName, key) == 0)
        {
            item_index = i - pSection->m_nItemStart;
            return true;
        }
    }

    return false;
}

size_t CXmlFile::GetSectionList(const IVarList& args, IVarList& result) const
{
    return GetSectionList(result);
}

size_t CXmlFile::GetSectionList(IVarList& result) const
{
    result.Clear();

    const size_t SIZE1 = m_sectionVec.size();

    for (size_t i = 0; i < SIZE1; ++i)
    {
        const section_t_xml * pSection = m_sectionVec[i];
        if (0 != pSection)
        {
            result.AddString(pSection->m_strName);
        }
        else
        {
            result.AddString("");
        }
    }

    return result.GetCount();
}

size_t CXmlFile::GetSectionItemCount(size_t sect_index) const
{
    Assert(sect_index < m_sectionVec.size());

    const section_t_xml * pSection = m_sectionVec[sect_index];

    return (0 != pSection) ? pSection->m_nItemCount : 0;
}

const char* CXmlFile::GetSectionItemKey(size_t sect_index,
                                        size_t item_index) const
{
    Assert(sect_index < m_sectionVec.size());

    const section_t_xml * pSection = m_sectionVec[sect_index];
    if (0 == pSection)
    {
        return "";
    }

    Assert(item_index < pSection->m_nItemCount);

    const item_t_xml * pItem =
        m_itemVec[pSection->m_nItemStart + item_index];
    return (0 != pItem) ? pItem->m_strName : "";
}

const char* CXmlFile::GetSectionItemValue(size_t sect_index,
                                          size_t item_index) const
{
    Assert(sect_index < m_sectionVec.size());

    const section_t_xml * pSection = m_sectionVec[sect_index];
    if (0 == pSection)
    {
        return "";
    }

    Assert(item_index < pSection->m_nItemCount);

    const item_t_xml * pItem =
        m_itemVec[pSection->m_nItemStart + item_index];
    return (0 != pItem) ? pItem->m_strValue : "";
}

bool CXmlFile::FindItem(const char* section_name, const char* key) const
{
    Assert(section_name != NULL);
    Assert(key != NULL);

    const section_t_xml *section = GetSection(section_name);

    if (NULL == section)
    {
        return false;
    }

    return (GetItem(section, key) != NULL);
}

size_t CXmlFile::GetItemCount(const char* section_name) const
{
    const section_t_xml *section = GetSection(section_name);

    if (NULL == section)
    {
        return 0;
    }

    return section->m_nItemCount;
}

size_t CXmlFile::GetItemList(const IVarList& args, IVarList& result) const
{
    const char* section = args.StringVal(0);

    return GetItemList(section, result);
}

size_t CXmlFile::GetItemList(const char* section_name, IVarList& result) const
{
    result.Clear();

    const section_t_xml *section = GetSection(section_name);

    if (NULL == section)
    {
        return 0;
    }

    const size_t SIZE1 = section->m_nItemStart + section->m_nItemCount;

    for (size_t i = section->m_nItemStart; i < SIZE1; ++i)
    {
        const item_t_xml * pItem = m_itemVec[i];
        if (0 != pItem)
        {
            result.AddString(pItem->m_strName);
        }
        else
        {
            result.AddString("");
        }
    }

    return result.GetCount();
}


size_t CXmlFile::GetSectionCount() const
{
    return m_sectionVec.size();
}

const char* CXmlFile::GetSectionByIndex(size_t index) const
{
    Assert(index < m_sectionVec.size());

    const section_t_xml * pSection = m_sectionVec[index];
    return (0 != pSection) ? pSection->m_strName : "";
}

__int64 CXmlFile::ReadInt64(const char* section_name, const char* key, __int64 def) const
{
    const char* str = GetData(section_name, key);

    if (str && strcmp(str, "") != 0)
    {
        return ::_atoi64(str);
    }
    else
    {
        return def;
    }
}

int CXmlFile::ReadInteger(const char* section_name, const char* key, int def) const
{
    const char* str = GetData(section_name, key);

    if (str && strcmp(str, "") != 0)
    {
        return atoi(str);
    }
    else
    {
        return def;
    }
}

const char* CXmlFile::GetData(const char* section_name, const char* key) const
{
    Assert(section_name != NULL);
    Assert(key != NULL);

    const section_t_xml *section = GetSection(section_name);

    if (NULL == section)
    {
        return NULL;
    }

    const item_t_xml *item = GetItem(section, key);

    if (NULL == item)
    {
        return NULL;
    }

    return item->m_strValue;
}

size_t CXmlFile::GetItemValueList(const IVarList& args, IVarList& result) const
{
    const char* section = args.StringVal(0);
    const char* key = args.StringVal(1);

    return GetItemValueList(section, key, result);
}

size_t CXmlFile::GetItemValueList(const char* section_name, const char* key, IVarList& result) const
{
    result.Clear();

    const section_t_xml *section = GetSection(section_name);

    if (NULL == section)
    {
        return NULL;
    }

    const size_t SIZE1 = section->m_nItemStart + section->m_nItemCount;

    for (size_t i = section->m_nItemStart; i < SIZE1; ++i)
    {
        const item_t_xml * pItem = m_itemVec[i];
        if (0 != pItem && 0 == stricmp(pItem->m_strName, key))
        {
            result.AddString(pItem->m_strValue);
        }
    }

    return result.GetCount();
}

const CXmlFile::section_t_xml* CXmlFile::GetSection(const char* section_name) const
{
    Assert(section_name != NULL);

    unsigned int hash = GetHashValue(section_name);

    const size_t SIZE1 = m_sectionVec.size();

    if (SIZE1 == m_sectionMap.size())
    {
        // 进行优化查找
        std::pair<SectionMapTypeConstItr, SectionMapTypeConstItr> ii =
            m_sectionMap.equal_range(hash);

        for (SectionMapTypeConstItr i = ii.first; i != ii.second; ++i)
        {
            const section_t_xml * pSection = m_sectionVec[i->second];
            if (0 != pSection &&
                pSection->m_nHash == hash &&
                stricmp(pSection->m_strName, section_name) == 0)
            {
                return pSection;
            }
        }
    }
    else
    {
        for (size_t i = 0; i < SIZE1; ++i)
        {
            const section_t_xml * pSection = m_sectionVec[i];
            if (0 != pSection &&
                pSection->m_nHash == hash &&
                stricmp(pSection->m_strName, section_name) == 0)
            {
                return pSection;
            }
        }
    }

    return NULL;
}


const CXmlFile::item_t_xml* CXmlFile::GetItem(const section_t_xml* section, const char* name) const
{
    Assert(name != NULL);
    Assert(section != NULL);


    unsigned int hash = GetHashValue(name);

    const size_t SIZE1 = section->m_nItemStart + section->m_nItemCount;

    for (size_t i = section->m_nItemStart; i < SIZE1; ++i)
    {
        const item_t_xml * pItem = m_itemVec[i];
        if (0 != pItem &&
            pItem->m_nHash == hash &&
            stricmp(pItem->m_strName, name) == 0)
        {
            return pItem;
        }
    }

    return NULL;
}

char* CXmlFile::ReadString(const char *section_name, const char *key, char *value, size_t maxlen) const
{
    Assert(value != NULL);
    Assert(maxlen > 0);

    const char* str = GetData(section_name, key);

    if (str)
    {
        size_t len = strlen(str);

        if (len >= maxlen)
        {
            len = maxlen - 1;
        }

        memcpy(value, str, len);

        value[len] = 0;
    }

    return value;
}

const char* CXmlFile::ReadString(const char *section_name, const char *key, const char *def) const
{
    Assert(def != NULL);

    const char* str = GetData(section_name, key);

    if (str && strcmp(str, "") != 0)
    {
        return str;
    }
    else
    {
        return def;
    }
}

float CXmlFile::ReadFloat(const char *section_name, const char *key, float def) const
{
    const char* str = GetData(section_name, key);

    if (str && strcmp(str, "") != 0)
    {
        return (float)atof(str);
    }
    else
    {
        return def;
    }
}

bool CXmlFile::AddSection(const char *section_name)
{
    Assert(section_name != NULL);

    if (NULL != GetSection(section_name))
    {
        return false;
    }

    const size_t sec_len = strlen(section_name) + 1;
    char *name = NEW char[sec_len];
    strncpy(name, section_name, sec_len);

    section_t_xml * pSection =
        NEW section_t_xml(name, GetHashValue(section_name), m_itemVec.size(), 0, true);
    m_sectionVec.push_back(pSection);

    return true;
}

bool CXmlFile::DeleteSection(const char *section_name)
{
    std::vector<item_t_xml *>::iterator item_It_begin = m_itemVec.begin();
    std::vector<item_t_xml *>::iterator item_It_end = m_itemVec.end();
    std::vector<section_t_xml *>::iterator section_It_earse = m_sectionVec.begin();
    
    Assert(section_name != NULL);

    size_t sect_index;

    if (!FindSectionIndex(section_name, sect_index))
    {
        return false;
    }

    const section_t_xml * pSection = m_sectionVec[sect_index];
    if (0 == pSection)
    {
        return false;
    }

    const size_t xml_section_size = m_sectionVec.size();
    for (size_t k = sect_index + 1; k < xml_section_size; ++k)
    {
        if (0 != m_sectionVec[k])
        {
            m_sectionVec[k]->m_nItemStart -= pSection->m_nItemCount;
        }
    }

    std::vector<item_t_xml *>::iterator item_it = m_itemVec.begin();    
    for (size_t i = 0; i < m_itemVec.size(); ++i)
    {
        if( i == pSection->m_nItemStart)
        {
            item_It_begin = item_it;
        }

        if(i == (pSection->m_nItemStart + pSection->m_nItemCount))
        {
            item_It_end = item_it;
        }
        ++item_it;
    }
    
    if (pSection->m_nItemStart + pSection->m_nItemCount == m_itemVec.size())
    {
        item_It_end = m_itemVec.end();
    }

    std::vector<section_t_xml *>::iterator section_it = m_sectionVec.begin();
    
    for (size_t i = 0; i < xml_section_size; ++i)
    {
        if(i == sect_index)
        {
            section_It_earse = section_it;
            break;
        }

        ++section_it;
    }
    
    if (pSection->m_nItemCount > 0)
    {
        for (std::vector<item_t_xml *>::iterator itr = item_It_begin;
             itr != item_It_end && itr != m_itemVec.end();
             ++itr)
        {
            const item_t_xml * pItem = *itr;
            if (0 != pItem)
            {
                delete pItem;
                pItem = 0;
            }
        }

        m_itemVec.erase(item_It_begin,item_It_end);
    }
    
    if (0 != (*section_It_earse))
    {
        delete (*section_It_earse);
        *section_It_earse = 0;
    }

    m_sectionVec.erase(section_It_earse);

    return true;
}

bool CXmlFile::DeleteItem(const char* section_name, const char* key)
{
    Assert(section_name != NULL);
    Assert(key != NULL);

    size_t sect_index;

    if (!FindSectionIndex(section_name, sect_index))
    {
        return false;
    }

    section_t_xml * pSection = m_sectionVec[sect_index];
    if (0 == pSection)
    {
        return false;
    }

    unsigned int hash = GetHashValue(key);
    const size_t item_end = pSection->m_nItemStart + pSection->m_nItemCount;

    std::vector<item_t_xml *>::iterator item_it;

    item_it = m_itemVec.begin();

    for (size_t i = pSection->m_nItemStart; i < item_end; ++i)
    {
        const item_t_xml * pItem = m_itemVec[i];
        if (0 != pItem &&
            pItem->m_nHash == hash &&
            stricmp(pItem->m_strName, key) == 0)
        {
            const size_t xml_section_size = m_sectionVec.size();
            for (size_t k = sect_index + 1; k < xml_section_size; ++k)
            {
                if (0 != m_sectionVec[k])
                {
                    --m_sectionVec[k]->m_nItemStart;
                }
            }

            delete pItem;
            pItem = 0;

            m_itemVec.erase(item_it);
            --pSection->m_nItemCount;

            return true;
        }

        ++item_it;
    }


    return false;
}

bool CXmlFile::WriteInteger(const char* section_name, const char* key, int value)
{
    char buf[32];

    sprintf(buf, "%d", value);

    return SetData(section_name, key, buf);
}

bool CXmlFile::WriteString(const char* section_name, const char* key, const char* value)
{
    return SetData(section_name, key, value);
}

bool CXmlFile::WriteFloat(const char *section_name, const char *key, float value)
{
    char buf[32];

    sprintf(buf, "%f", double(value));

    return SetData(section_name, key, buf);

}

bool CXmlFile::AddInteger(const char* section_name, const char* key, int value)
{
    char buf[32];

    sprintf(buf, "%d", value);

    return AddData(section_name, key, buf);
}

bool CXmlFile::AddString(const char* section_name, const char* key, const char* value)
{
    return AddData(section_name, key, value);
}

bool CXmlFile::AddFloat(const char *section_name, const char *key, float value)
{
    char buf[32];

    sprintf(buf, "%f", double(value));

    return AddData(section_name, key, buf);

}

bool CXmlFile::AddData(const char* section_name, const char* key, const char* data)
{
    Assert(section_name != NULL);
    Assert(key != NULL);
    Assert(data != NULL);

    size_t sect_index;

    if (!FindSectionIndex(section_name, sect_index))
    {
        sect_index = m_sectionVec.size();

        AddSection(section_name);
    }
    
    section_t_xml * pSection = m_sectionVec[sect_index];
    if (0 == pSection)
    {
        return false;
    }

    size_t item_index = pSection->m_nItemStart + pSection->m_nItemCount;

    const size_t key_len = strlen(key) + 1;
    char *item_name = NEW char[key_len];
    strncpy(item_name, key, key_len);

    const size_t data_len = strlen(data) + 1;
    char *item_value = NEW char[data_len];
    strncpy(item_value, data, data_len);

    const int hash = GetHashValue(item_name);

    item_t_xml * pItem =
        NEW item_t_xml(item_name, hash, item_value, true, true);

    m_itemVec.insert(m_itemVec.begin()+item_index, 1, pItem);

    ++pSection->m_nItemCount;

    const size_t xml_section_size = m_sectionVec.size();
    for (size_t k = sect_index + 1; k < xml_section_size; ++k)
    {
        if (0 != m_sectionVec[k])
        {
            ++m_sectionVec[k]->m_nItemStart;
        }
    }

    return true;
}

bool CXmlFile::SetData(const char* section_name, const char* key, const char* data)
{
    Assert(section_name != NULL);
    Assert(key != NULL);
    Assert(data != NULL);

    size_t sect_index;

    if (!FindSectionIndex(section_name, sect_index))
    {
        sect_index = m_sectionVec.size();

        AddSection(section_name);

    }

    const section_t_xml * pSection = m_sectionVec[sect_index];
    if (0 == pSection)
    {
        return false;
    }

    item_t_xml *item = (item_t_xml *)GetItem(pSection, key);

    if (NULL == item)
    {
        AddData(section_name, key, data);
    }
    else
    {
        if (item->m_bDelValue)
        {
            delete [] item->m_strValue;
        }
        
        const size_t data_len = strlen(data) + 1;
        char *item_value = NEW char[data_len];
        strncpy(item_value, data, data_len);

        item->m_strValue = item_value;
        item->m_bDelValue = true;
    }

    return true;

}

bool CXmlFile::SaveToFile() const
{
    rapidxml::xml_document<> doc;
    rapidxml::xml_node<char> * pNodeRoot = doc.allocate_node(rapidxml::node_element,"Object");
    doc.append_node(pNodeRoot);

    rapidxml::xml_node<char>* pItemElm = NULL;

    const size_t xml_section_size = m_sectionVec.size();
    for (size_t i = 0; i < xml_section_size; i ++)
    {
        const section_t_xml * pSection = m_sectionVec[i];
        if (0 == pSection)
        {
            continue;
        }

        pItemElm = doc.allocate_node(rapidxml::node_element,"Property");
        pItemElm->append_attribute(doc.allocate_attribute("ID", pSection->m_strName));
        pNodeRoot->append_node(pItemElm);

        size_t start_index = pSection->m_nItemStart;
        size_t end_index = pSection->m_nItemStart + pSection->m_nItemCount;

        for (size_t j = start_index; j < end_index; j ++)
        {
            const item_t_xml * pItem = m_itemVec[j];
            pItemElm->append_attribute(doc.allocate_attribute(pItem->m_strName, pItem->m_strValue));
        }
    }

    std::ofstream out(m_strFileName.c_str());
    out << "<?xml version=\"1.0\" encoding=\"gb2312\"?>\n";
    out << doc;
    out.close();

    return true;
}

// end of file XmlFile.cpp

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

!chen

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值