2017-12-18 14:09:20 +08:00
|
|
|
#ifndef RAPIDXML_UTILS_HPP_INCLUDED
|
|
|
|
#define RAPIDXML_UTILS_HPP_INCLUDED
|
|
|
|
|
|
|
|
// Copyright (C) 2006, 2009 Marcin Kalicinski
|
|
|
|
// Version 1.13
|
|
|
|
// Revision $DateTime: 2009/05/13 01:46:17 $
|
|
|
|
//! \file rapidxml_utils.hpp This file contains high-level rapidxml utilities that can be useful
|
|
|
|
//! in certain simple scenarios. They should probably not be used if maximizing performance is the main objective.
|
|
|
|
|
|
|
|
#include "rapidxml.hpp"
|
|
|
|
#include <vector>
|
|
|
|
#include <string>
|
|
|
|
#include <fstream>
|
|
|
|
#include <stdexcept>
|
|
|
|
|
|
|
|
namespace rapidxml
|
|
|
|
{
|
|
|
|
|
|
|
|
//! Represents data loaded from a file
|
|
|
|
template<class Ch = char>
|
|
|
|
class file
|
|
|
|
{
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
|
|
|
//! Loads file into the memory. Data will be automatically destroyed by the destructor.
|
|
|
|
//! \param filename Filename to load.
|
|
|
|
file(const char *filename)
|
|
|
|
{
|
|
|
|
using namespace std;
|
|
|
|
|
|
|
|
// Open stream
|
|
|
|
basic_ifstream<Ch> stream(filename, ios::binary);
|
|
|
|
if (!stream)
|
|
|
|
throw runtime_error(string("cannot open file ") + filename);
|
|
|
|
stream.unsetf(ios::skipws);
|
|
|
|
|
|
|
|
// Determine stream size
|
|
|
|
stream.seekg(0, ios::end);
|
|
|
|
size_t size = stream.tellg();
|
|
|
|
stream.seekg(0);
|
|
|
|
|
|
|
|
// Load data and add terminating 0
|
|
|
|
m_data.resize(size + 1);
|
|
|
|
stream.read(&m_data.front(), static_cast<streamsize>(size));
|
|
|
|
m_data[size] = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
//! Loads file into the memory. Data will be automatically destroyed by the destructor
|
|
|
|
//! \param stream Stream to load from
|
|
|
|
file(std::basic_istream<Ch> &stream)
|
|
|
|
{
|
|
|
|
using namespace std;
|
|
|
|
|
|
|
|
// Load data and add terminating 0
|
|
|
|
stream.unsetf(ios::skipws);
|
|
|
|
m_data.assign(istreambuf_iterator<Ch>(stream), istreambuf_iterator<Ch>());
|
|
|
|
if (stream.fail() || stream.bad())
|
|
|
|
throw runtime_error("error reading stream");
|
|
|
|
m_data.push_back(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
//! Gets file data.
|
|
|
|
//! \return Pointer to data of file.
|
|
|
|
Ch *data()
|
|
|
|
{
|
|
|
|
return &m_data.front();
|
|
|
|
}
|
|
|
|
|
|
|
|
//! Gets file data.
|
|
|
|
//! \return Pointer to data of file.
|
|
|
|
const Ch *data() const
|
|
|
|
{
|
|
|
|
return &m_data.front();
|
|
|
|
}
|
|
|
|
|
|
|
|
//! Gets file data size.
|
|
|
|
//! \return Size of file data, in characters.
|
|
|
|
std::size_t size() const
|
|
|
|
{
|
|
|
|
return m_data.size();
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
|
|
|
std::vector<Ch> m_data; // File data
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
//! Counts children of node. Time complexity is O(n).
|
|
|
|
//! \return Number of children of node
|
|
|
|
template<class Ch>
|
|
|
|
inline std::size_t count_children(xml_node<Ch> *node)
|
|
|
|
{
|
|
|
|
xml_node<Ch> *child = node->first_node();
|
|
|
|
std::size_t count = 0;
|
|
|
|
while (child)
|
|
|
|
{
|
|
|
|
++count;
|
|
|
|
child = child->next_sibling();
|
|
|
|
}
|
|
|
|
return count;
|
|
|
|
}
|
|
|
|
|
|
|
|
//! Counts attributes of node. Time complexity is O(n).
|
|
|
|
//! \return Number of attributes of node
|
|
|
|
template<class Ch>
|
|
|
|
inline std::size_t count_attributes(xml_node<Ch> *node)
|
|
|
|
{
|
|
|
|
xml_attribute<Ch> *attr = node->first_attribute();
|
|
|
|
std::size_t count = 0;
|
|
|
|
while (attr)
|
|
|
|
{
|
|
|
|
++count;
|
|
|
|
attr = attr->next_attribute();
|
|
|
|
}
|
|
|
|
return count;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|