Skip to content
Snippets Groups Projects
pugixml.cpp 266 KiB
Newer Older
  • Learn to ignore specific revisions
  • Radim Vavřík's avatar
    Radim Vavřík committed
    10001 10002 10003 10004 10005 10006 10007 10008 10009 10010 10011 10012 10013 10014 10015 10016 10017 10018 10019 10020 10021 10022 10023 10024 10025 10026 10027 10028 10029 10030 10031 10032 10033 10034 10035 10036 10037 10038 10039 10040 10041 10042 10043 10044 10045 10046 10047 10048 10049 10050 10051 10052 10053 10054 10055 10056 10057 10058 10059 10060 10061 10062 10063 10064 10065 10066 10067 10068 10069 10070 10071 10072 10073 10074 10075 10076 10077 10078 10079 10080 10081 10082 10083 10084 10085 10086 10087 10088 10089 10090 10091 10092 10093 10094 10095 10096 10097 10098 10099 10100 10101 10102 10103 10104 10105 10106 10107 10108 10109 10110 10111 10112 10113 10114 10115 10116 10117 10118 10119 10120 10121 10122 10123 10124 10125 10126 10127 10128 10129 10130 10131 10132 10133 10134 10135 10136 10137 10138 10139 10140 10141 10142 10143 10144 10145 10146 10147 10148 10149 10150 10151 10152 10153 10154 10155 10156 10157 10158 10159 10160 10161 10162 10163 10164 10165 10166 10167 10168 10169 10170 10171 10172 10173 10174 10175 10176 10177 10178 10179 10180 10181 10182 10183 10184 10185 10186 10187 10188 10189 10190 10191 10192 10193 10194 10195 10196 10197 10198 10199 10200 10201 10202 10203 10204 10205 10206 10207 10208 10209 10210 10211 10212 10213 10214 10215 10216 10217 10218 10219 10220 10221 10222 10223 10224 10225 10226 10227 10228 10229 10230 10231 10232 10233 10234 10235 10236 10237 10238 10239 10240 10241 10242 10243 10244 10245 10246 10247 10248 10249 10250
    	PUGI__FN bool xpath_variable_set::set(const char_t* name, const char_t* value)
    	{
    		xpath_variable* var = add(name, xpath_type_string);
    		return var ? var->set(value) : false;
    	}
    
    	PUGI__FN bool xpath_variable_set::set(const char_t* name, const xpath_node_set& value)
    	{
    		xpath_variable* var = add(name, xpath_type_node_set);
    		return var ? var->set(value) : false;
    	}
    
    	PUGI__FN xpath_variable* xpath_variable_set::get(const char_t* name)
    	{
    		return find(name);
    	}
    
    	PUGI__FN const xpath_variable* xpath_variable_set::get(const char_t* name) const
    	{
    		return find(name);
    	}
    
    	PUGI__FN xpath_query::xpath_query(const char_t* query, xpath_variable_set* variables): _impl(0)
    	{
    		impl::xpath_query_impl* qimpl = impl::xpath_query_impl::create();
    
    		if (!qimpl)
    		{
    		#ifdef PUGIXML_NO_EXCEPTIONS
    			_result.error = "Out of memory";
    		#else
    			throw std::bad_alloc();
    		#endif
    		}
    		else
    		{
    			impl::buffer_holder impl_holder(qimpl, impl::xpath_query_impl::destroy);
    
    			qimpl->root = impl::xpath_parser::parse(query, variables, &qimpl->alloc, &_result);
    
    			if (qimpl->root)
    			{
    				_impl = static_cast<impl::xpath_query_impl*>(impl_holder.release());
    				_result.error = 0;
    			}
    		}
    	}
    
    	PUGI__FN xpath_query::~xpath_query()
    	{
    		impl::xpath_query_impl::destroy(_impl);
    	}
    
    	PUGI__FN xpath_value_type xpath_query::return_type() const
    	{
    		if (!_impl) return xpath_type_none;
    
    		return static_cast<impl::xpath_query_impl*>(_impl)->root->rettype();
    	}
    
    	PUGI__FN bool xpath_query::evaluate_boolean(const xpath_node& n) const
    	{
    		if (!_impl) return false;
    		
    		impl::xpath_context c(n, 1, 1);
    		impl::xpath_stack_data sd;
    
    	#ifdef PUGIXML_NO_EXCEPTIONS
    		if (setjmp(sd.error_handler)) return false;
    	#endif
    		
    		return static_cast<impl::xpath_query_impl*>(_impl)->root->eval_boolean(c, sd.stack);
    	}
    	
    	PUGI__FN double xpath_query::evaluate_number(const xpath_node& n) const
    	{
    		if (!_impl) return impl::gen_nan();
    		
    		impl::xpath_context c(n, 1, 1);
    		impl::xpath_stack_data sd;
    
    	#ifdef PUGIXML_NO_EXCEPTIONS
    		if (setjmp(sd.error_handler)) return impl::gen_nan();
    	#endif
    
    		return static_cast<impl::xpath_query_impl*>(_impl)->root->eval_number(c, sd.stack);
    	}
    
    #ifndef PUGIXML_NO_STL
    	PUGI__FN string_t xpath_query::evaluate_string(const xpath_node& n) const
    	{
    		impl::xpath_stack_data sd;
    
    		return impl::evaluate_string_impl(static_cast<impl::xpath_query_impl*>(_impl), n, sd).c_str();
    	}
    #endif
    
    	PUGI__FN size_t xpath_query::evaluate_string(char_t* buffer, size_t capacity, const xpath_node& n) const
    	{
    		impl::xpath_stack_data sd;
    
    		impl::xpath_string r = impl::evaluate_string_impl(static_cast<impl::xpath_query_impl*>(_impl), n, sd);
    
    		size_t full_size = r.length() + 1;
    		
    		if (capacity > 0)
    		{
    			size_t size = (full_size < capacity) ? full_size : capacity;
    			assert(size > 0);
    
    			memcpy(buffer, r.c_str(), (size - 1) * sizeof(char_t));
    			buffer[size - 1] = 0;
    		}
    		
    		return full_size;
    	}
    
    	PUGI__FN xpath_node_set xpath_query::evaluate_node_set(const xpath_node& n) const
    	{
    		if (!_impl) return xpath_node_set();
    
    		impl::xpath_ast_node* root = static_cast<impl::xpath_query_impl*>(_impl)->root;
    
    		if (root->rettype() != xpath_type_node_set)
    		{
    		#ifdef PUGIXML_NO_EXCEPTIONS
    			return xpath_node_set();
    		#else
    			xpath_parse_result res;
    			res.error = "Expression does not evaluate to node set";
    
    			throw xpath_exception(res);
    		#endif
    		}
    		
    		impl::xpath_context c(n, 1, 1);
    		impl::xpath_stack_data sd;
    
    	#ifdef PUGIXML_NO_EXCEPTIONS
    		if (setjmp(sd.error_handler)) return xpath_node_set();
    	#endif
    
    		impl::xpath_node_set_raw r = root->eval_node_set(c, sd.stack);
    
    		return xpath_node_set(r.begin(), r.end(), r.type());
    	}
    
    	PUGI__FN const xpath_parse_result& xpath_query::result() const
    	{
    		return _result;
    	}
    
    	PUGI__FN static void unspecified_bool_xpath_query(xpath_query***)
    	{
    	}
    
    	PUGI__FN xpath_query::operator xpath_query::unspecified_bool_type() const
    	{
    		return _impl ? unspecified_bool_xpath_query : 0;
    	}
    
    	PUGI__FN bool xpath_query::operator!() const
    	{
    		return !_impl;
    	}
    
    	PUGI__FN xpath_node xml_node::select_single_node(const char_t* query, xpath_variable_set* variables) const
    	{
    		xpath_query q(query, variables);
    		return select_single_node(q);
    	}
    
    	PUGI__FN xpath_node xml_node::select_single_node(const xpath_query& query) const
    	{
    		xpath_node_set s = query.evaluate_node_set(*this);
    		return s.empty() ? xpath_node() : s.first();
    	}
    
    	PUGI__FN xpath_node_set xml_node::select_nodes(const char_t* query, xpath_variable_set* variables) const
    	{
    		xpath_query q(query, variables);
    		return select_nodes(q);
    	}
    
    	PUGI__FN xpath_node_set xml_node::select_nodes(const xpath_query& query) const
    	{
    		return query.evaluate_node_set(*this);
    	}
    }
    
    #endif
    
    #ifdef __BORLANDC__
    #	pragma option pop
    #endif
    
    // Intel C++ does not properly keep warning state for function templates,
    // so popping warning state at the end of translation unit leads to warnings in the middle.
    #if defined(_MSC_VER) && !defined(__INTEL_COMPILER)
    #	pragma warning(pop)
    #endif
    
    // Undefine all local macros (makes sure we're not leaking macros in header-only mode)
    #undef PUGI__NO_INLINE
    #undef PUGI__STATIC_ASSERT
    #undef PUGI__DMC_VOLATILE
    #undef PUGI__MSVC_CRT_VERSION
    #undef PUGI__NS_BEGIN
    #undef PUGI__NS_END
    #undef PUGI__FN
    #undef PUGI__FN_NO_INLINE
    #undef PUGI__IS_CHARTYPE_IMPL
    #undef PUGI__IS_CHARTYPE
    #undef PUGI__IS_CHARTYPEX
    #undef PUGI__SKIPWS
    #undef PUGI__OPTSET
    #undef PUGI__PUSHNODE
    #undef PUGI__POPNODE
    #undef PUGI__SCANFOR
    #undef PUGI__SCANWHILE
    #undef PUGI__ENDSEG
    #undef PUGI__THROW_ERROR
    #undef PUGI__CHECK_ERROR
    
    #endif
    
    /**
     * Copyright (c) 2006-2012 Arseny Kapoulkine
     *
     * Permission is hereby granted, free of charge, to any person
     * obtaining a copy of this software and associated documentation
     * files (the "Software"), to deal in the Software without
     * restriction, including without limitation the rights to use,
     * copy, modify, merge, publish, distribute, sublicense, and/or sell
     * copies of the Software, and to permit persons to whom the
     * Software is furnished to do so, subject to the following
     * conditions:
     *
     * The above copyright notice and this permission notice shall be
     * included in all copies or substantial portions of the Software.
     * 
     * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
     * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
     * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
     * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
     * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
     * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
     * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
     * OTHER DEALINGS IN THE SOFTWARE.
     */