parameterised string functions

This commit is contained in:
jez_higgins 2005-08-18 11:32:29 +00:00
parent 2425702f9d
commit 5491337558
2 changed files with 104 additions and 84 deletions

View file

@ -220,157 +220,175 @@ public:
// string functions // string functions
// string string(object?) // string string(object?)
class StringFn : public XPathFunction<std::string, Arabica::default_string_adaptor<std::string> > template<class string_type, class string_adaptor>
class StringFn : public XPathFunction<string_type, string_adaptor>
{ {
typedef XPathFunction<string_type, string_adaptor> baseT;
public: public:
StringFn(const std::vector<XPathExpressionPtr<std::string, Arabica::default_string_adaptor<std::string> > >& args) : XPathFunction<std::string, Arabica::default_string_adaptor<std::string> >(0, 1, args) { } StringFn(const std::vector<XPathExpressionPtr<string_type, string_adaptor> >& args) : XPathFunction<string_type, string_adaptor>(0, 1, args) { }
virtual XPathValue<std::string>* evaluate(const DOM::Node<std::string>& context, virtual XPathValue<string_type>* evaluate(const DOM::Node<string_type>& context,
const ExecutionContext<std::string, Arabica::default_string_adaptor<std::string> >& executionContext) const const ExecutionContext<string_type, string_adaptor>& executionContext) const
{ {
return new StringValue<std::string, Arabica::default_string_adaptor<std::string> >((argCount() > 0) ? argAsString(0, context, executionContext) : nodeStringValue(context)); return new StringValue<string_type, string_adaptor>((baseT::argCount() > 0) ? baseT::argAsString(0, context, executionContext) : nodeStringValue(context));
} // evaluate } // evaluate
}; // class StringFn }; // class StringFn
// string concat(string, string, string*) // string concat(string, string, string*)
class ConcatFn : public XPathFunction<std::string, Arabica::default_string_adaptor<std::string> > template<class string_type, class string_adaptor>
class ConcatFn : public XPathFunction<string_type, string_adaptor>
{ {
typedef XPathFunction<string_type, string_adaptor> baseT;
public: public:
ConcatFn(const std::vector<XPathExpressionPtr<std::string, Arabica::default_string_adaptor<std::string> > >& args) : XPathFunction<std::string, Arabica::default_string_adaptor<std::string> >(2, -1, args) { } ConcatFn(const std::vector<XPathExpressionPtr<string_type, string_adaptor> >& args) : XPathFunction<string_type, string_adaptor>(2, -1, args) { }
virtual XPathValue<std::string>* evaluate(const DOM::Node<std::string>& context, virtual XPathValue<string_type>* evaluate(const DOM::Node<string_type>& context,
const ExecutionContext<std::string, Arabica::default_string_adaptor<std::string> >& executionContext) const const ExecutionContext<string_type, string_adaptor>& executionContext) const
{ {
std::string s; string_type s;
for(size_t a = 0, ae = argCount(); a < ae; ++a) for(size_t a = 0, ae = baseT::argCount(); a < ae; ++a)
s.append(argAsString(a, context, executionContext)); s.append(baseT::argAsString(a, context, executionContext));
return new StringValue<std::string, Arabica::default_string_adaptor<std::string> >(s); return new StringValue<string_type, string_adaptor>(s);
} // evaluate } // evaluate
}; // ConcatFn }; // ConcatFn
// boolean starts-with(string, string) // boolean starts-with(string, string)
class StartsWithFn : public XPathFunction<std::string, Arabica::default_string_adaptor<std::string> > template<class string_type, class string_adaptor>
class StartsWithFn : public XPathFunction<string_type, string_adaptor>
{ {
typedef XPathFunction<string_type, string_adaptor> baseT;
public: public:
StartsWithFn(const std::vector<XPathExpressionPtr<std::string, Arabica::default_string_adaptor<std::string> > >& args) : XPathFunction<std::string, Arabica::default_string_adaptor<std::string> >(2, 2, args) { } StartsWithFn(const std::vector<XPathExpressionPtr<string_type, string_adaptor> >& args) : XPathFunction<string_type, string_adaptor>(2, 2, args) { }
virtual XPathValue<std::string>* evaluate(const DOM::Node<std::string>& context, virtual XPathValue<string_type>* evaluate(const DOM::Node<string_type>& context,
const ExecutionContext<std::string, Arabica::default_string_adaptor<std::string> >& executionContext) const const ExecutionContext<string_type, string_adaptor>& executionContext) const
{ {
std::string value = argAsString(0, context, executionContext); string_type value = baseT::argAsString(0, context, executionContext);
std::string start = argAsString(1, context, executionContext); string_type start = baseT::argAsString(1, context, executionContext);
if(value.length() < start.length()) if(value.length() < start.length())
return new BoolValue<std::string, Arabica::default_string_adaptor<std::string> >(false); return new BoolValue<string_type, string_adaptor>(false);
for(size_t i = 0, ie = start.length(); i < ie; ++i) for(size_t i = 0, ie = start.length(); i < ie; ++i)
if(value[i] != start[i]) if(value[i] != start[i])
return new BoolValue<std::string, Arabica::default_string_adaptor<std::string> >(false); return new BoolValue<string_type, string_adaptor>(false);
return new BoolValue<std::string, Arabica::default_string_adaptor<std::string> >(true); return new BoolValue<string_type, string_adaptor>(true);
} // evaluate } // evaluate
}; // StartsWithFn }; // StartsWithFn
// boolean contains(string, string) // boolean contains(string, string)
class ContainsFn : public XPathFunction<std::string, Arabica::default_string_adaptor<std::string> > template<class string_type, class string_adaptor>
class ContainsFn : public XPathFunction<string_type, string_adaptor>
{ {
typedef XPathFunction<string_type, string_adaptor> baseT;
public: public:
ContainsFn(const std::vector<XPathExpressionPtr<std::string, Arabica::default_string_adaptor<std::string> > >& args) : XPathFunction<std::string, Arabica::default_string_adaptor<std::string> >(2, 2, args) { } ContainsFn(const std::vector<XPathExpressionPtr<string_type, string_adaptor> >& args) : XPathFunction<string_type, string_adaptor>(2, 2, args) { }
virtual XPathValue<std::string>* evaluate(const DOM::Node<std::string>& context, virtual XPathValue<string_type>* evaluate(const DOM::Node<string_type>& context,
const ExecutionContext<std::string, Arabica::default_string_adaptor<std::string> >& executionContext) const const ExecutionContext<string_type, string_adaptor>& executionContext) const
{ {
return new BoolValue<std::string, Arabica::default_string_adaptor<std::string> >(argAsString(0, context, executionContext).find(argAsString(1, context, executionContext)) != std::string::npos); return new BoolValue<string_type, string_adaptor>(baseT::argAsString(0, context, executionContext).find(baseT::argAsString(1, context, executionContext)) != string_type::npos);
} // evaluate } // evaluate
}; // class ContainsFn }; // class ContainsFn
// string substring-before(string, string) // string substring-before(string, string)
class SubstringBeforeFn : public XPathFunction<std::string, Arabica::default_string_adaptor<std::string> > template<class string_type, class string_adaptor>
class SubstringBeforeFn : public XPathFunction<string_type, string_adaptor>
{ {
typedef XPathFunction<string_type, string_adaptor> baseT;
public: public:
SubstringBeforeFn(const std::vector<XPathExpressionPtr<std::string, Arabica::default_string_adaptor<std::string> > >& args) : XPathFunction<std::string, Arabica::default_string_adaptor<std::string> >(2, 2, args) { } SubstringBeforeFn(const std::vector<XPathExpressionPtr<string_type, string_adaptor> >& args) : XPathFunction<string_type, string_adaptor>(2, 2, args) { }
virtual XPathValue<std::string>* evaluate(const DOM::Node<std::string>& context, virtual XPathValue<string_type>* evaluate(const DOM::Node<string_type>& context,
const ExecutionContext<std::string, Arabica::default_string_adaptor<std::string> >& executionContext) const const ExecutionContext<string_type, string_adaptor>& executionContext) const
{ {
std::string value = argAsString(0, context, executionContext); string_type value = baseT::argAsString(0, context, executionContext);
size_t splitAt = value.find(argAsString(1, context, executionContext)); size_t splitAt = value.find(baseT::argAsString(1, context, executionContext));
if(splitAt == std::string::npos) if(splitAt == string_type::npos)
return new StringValue<std::string, Arabica::default_string_adaptor<std::string> >(""); return new StringValue<string_type, string_adaptor>("");
return new StringValue<std::string, Arabica::default_string_adaptor<std::string> >(value.substr(0, splitAt)); return new StringValue<string_type, string_adaptor>(value.substr(0, splitAt));
} // evaluate } // evaluate
}; // class SubstringBeforeFn }; // class SubstringBeforeFn
// string substring-after(string, string) // string substring-after(string, string)
class SubstringAfterFn : public XPathFunction<std::string, Arabica::default_string_adaptor<std::string> > template<class string_type, class string_adaptor>
class SubstringAfterFn : public XPathFunction<string_type, string_adaptor>
{ {
typedef XPathFunction<string_type, string_adaptor> baseT;
public: public:
SubstringAfterFn(const std::vector<XPathExpressionPtr<std::string, Arabica::default_string_adaptor<std::string> > >& args) : XPathFunction<std::string, Arabica::default_string_adaptor<std::string> >(2, 2, args) { } SubstringAfterFn(const std::vector<XPathExpressionPtr<string_type, string_adaptor> >& args) : XPathFunction<string_type, string_adaptor>(2, 2, args) { }
virtual XPathValue<std::string>* evaluate(const DOM::Node<std::string>& context, virtual XPathValue<string_type>* evaluate(const DOM::Node<string_type>& context,
const ExecutionContext<std::string, Arabica::default_string_adaptor<std::string> >& executionContext) const const ExecutionContext<string_type, string_adaptor>& executionContext) const
{ {
std::string value = argAsString(0, context, executionContext); string_type value = baseT::argAsString(0, context, executionContext);
std::string split = argAsString(1, context, executionContext); string_type split = baseT::argAsString(1, context, executionContext);
size_t splitAt = value.find(split); size_t splitAt = value.find(split);
if((splitAt == std::string::npos) || ((splitAt + split.length()) >= value.length())) if((splitAt == string_type::npos) || ((splitAt + split.length()) >= value.length()))
return new StringValue<std::string, Arabica::default_string_adaptor<std::string> >(""); return new StringValue<string_type, string_adaptor>("");
return new StringValue<std::string, Arabica::default_string_adaptor<std::string> >(value.substr(splitAt + split.length())); return new StringValue<string_type, string_adaptor>(value.substr(splitAt + split.length()));
} // evaluate } // evaluate
}; // class SubstringAfterFn }; // class SubstringAfterFn
// string substring(string, number, number?) // string substring(string, number, number?)
class SubstringFn : public XPathFunction<std::string, Arabica::default_string_adaptor<std::string> > template<class string_type, class string_adaptor>
class SubstringFn : public XPathFunction<string_type, string_adaptor>
{ {
typedef XPathFunction<string_type, string_adaptor> baseT;
public: public:
SubstringFn(const std::vector<XPathExpressionPtr<std::string, Arabica::default_string_adaptor<std::string> > >& args) : XPathFunction<std::string, Arabica::default_string_adaptor<std::string> >(2, 3, args) { } SubstringFn(const std::vector<XPathExpressionPtr<string_type, string_adaptor> >& args) : XPathFunction<string_type, string_adaptor>(2, 3, args) { }
virtual XPathValue<std::string>* evaluate(const DOM::Node<std::string>& context, virtual XPathValue<string_type>* evaluate(const DOM::Node<string_type>& context,
const ExecutionContext<std::string, Arabica::default_string_adaptor<std::string> >& executionContext) const const ExecutionContext<string_type, string_adaptor>& executionContext) const
{ {
std::string value = argAsString(0, context, executionContext); string_type value = baseT::argAsString(0, context, executionContext);
double startAt = roundNumber(argAsNumber(1, context, executionContext)) - 1; double startAt = roundNumber(baseT::argAsNumber(1, context, executionContext)) - 1;
double endAt = roundNumber((argCount() == 3 ? argAsNumber(2, context, executionContext) : Infinity)) + startAt; double endAt = roundNumber((baseT::argCount() == 3 ? baseT::argAsNumber(2, context, executionContext) : Infinity)) + startAt;
if((endAt < 0) || (endAt < startAt) || (isNaN(endAt))) if((endAt < 0) || (endAt < startAt) || (isNaN(endAt)))
return new StringValue<std::string, Arabica::default_string_adaptor<std::string> >(""); return new StringValue<string_type, string_adaptor>("");
if(startAt < 0) if(startAt < 0)
startAt = 0; startAt = 0;
if((isInfinite(endAt)) || (endAt > value.length())) if((isInfinite(endAt)) || (endAt > value.length()))
endAt = value.length(); endAt = value.length();
return new StringValue<std::string, Arabica::default_string_adaptor<std::string> >(value.substr(static_cast<int>(startAt), static_cast<int>(endAt - startAt))); return new StringValue<string_type, string_adaptor>(value.substr(static_cast<int>(startAt), static_cast<int>(endAt - startAt)));
} // evaluate } // evaluate
}; // SubstringFn }; // SubstringFn
// number string-length(string?) // number string-length(string?)
class StringLengthFn : public XPathFunction<std::string, Arabica::default_string_adaptor<std::string> > template<class string_type, class string_adaptor>
class StringLengthFn : public XPathFunction<string_type, string_adaptor>
{ {
typedef XPathFunction<string_type, string_adaptor> baseT;
public: public:
StringLengthFn(const std::vector<XPathExpressionPtr<std::string, Arabica::default_string_adaptor<std::string> > >& args) : XPathFunction<std::string, Arabica::default_string_adaptor<std::string> >(0, 1, args) { } StringLengthFn(const std::vector<XPathExpressionPtr<string_type, string_adaptor> >& args) : XPathFunction<string_type, string_adaptor>(0, 1, args) { }
virtual XPathValue<std::string>* evaluate(const DOM::Node<std::string>& context, virtual XPathValue<string_type>* evaluate(const DOM::Node<string_type>& context,
const ExecutionContext<std::string, Arabica::default_string_adaptor<std::string> >& executionContext) const const ExecutionContext<string_type, string_adaptor>& executionContext) const
{ {
return new NumericValue<std::string, Arabica::default_string_adaptor<std::string> >(((argCount() > 0) ? argAsString(0, context, executionContext) : nodeStringValue(context)).length()); return new NumericValue<string_type, string_adaptor>(((baseT::argCount() > 0) ? baseT::argAsString(0, context, executionContext) : nodeStringValue(context)).length());
} // evaluate } // evaluate
}; // StringLengthFn }; // StringLengthFn
// string normalize-space(string?) // string normalize-space(string?)
class NormalizeSpaceFn : public XPathFunction<std::string, Arabica::default_string_adaptor<std::string> > template<class string_type, class string_adaptor>
class NormalizeSpaceFn : public XPathFunction<string_type, string_adaptor>
{ {
typedef XPathFunction<string_type, string_adaptor> baseT;
public: public:
NormalizeSpaceFn(const std::vector<XPathExpressionPtr<std::string, Arabica::default_string_adaptor<std::string> > >& args) : XPathFunction<std::string, Arabica::default_string_adaptor<std::string> >(0, 1, args) { } NormalizeSpaceFn(const std::vector<XPathExpressionPtr<string_type, string_adaptor> >& args) : XPathFunction<string_type, string_adaptor>(0, 1, args) { }
virtual XPathValue<std::string>* evaluate(const DOM::Node<std::string>& context, virtual XPathValue<string_type>* evaluate(const DOM::Node<string_type>& context,
const ExecutionContext<std::string, Arabica::default_string_adaptor<std::string> >& executionContext) const const ExecutionContext<string_type, string_adaptor>& executionContext) const
{ {
std::string value = ((argCount() > 0) ? argAsString(0, context, executionContext) : nodeStringValue(context)); string_type value = ((baseT::argCount() > 0) ? baseT::argAsString(0, context, executionContext) : nodeStringValue(context));
size_t i = 0, ie = value.length(); size_t i = 0, ie = value.length();
// string leading space // string leading space
@ -390,28 +408,30 @@ public:
if(p != ie) if(p != ie)
value.resize(p); value.resize(p);
return new StringValue<std::string, Arabica::default_string_adaptor<std::string> >(value); return new StringValue<string_type, string_adaptor>(value);
} // evaluate } // evaluate
}; // class NormalizeSpaceFn }; // class NormalizeSpaceFn
// string translate(string, string, string) // string translate(string, string, string)
class TranslateFn : public XPathFunction<std::string, Arabica::default_string_adaptor<std::string> > template<class string_type, class string_adaptor>
class TranslateFn : public XPathFunction<string_type, string_adaptor>
{ {
typedef XPathFunction<string_type, string_adaptor> baseT;
public: public:
TranslateFn(const std::vector<XPathExpressionPtr<std::string, Arabica::default_string_adaptor<std::string> > >& args) : XPathFunction<std::string, Arabica::default_string_adaptor<std::string> >(3, 3, args) { } TranslateFn(const std::vector<XPathExpressionPtr<string_type, string_adaptor> >& args) : XPathFunction<string_type, string_adaptor>(3, 3, args) { }
virtual XPathValue<std::string>* evaluate(const DOM::Node<std::string>& context, virtual XPathValue<string_type>* evaluate(const DOM::Node<string_type>& context,
const ExecutionContext<std::string, Arabica::default_string_adaptor<std::string> >& executionContext) const const ExecutionContext<string_type, string_adaptor>& executionContext) const
{ {
std::string str = argAsString(0, context, executionContext); string_type str = baseT::argAsString(0, context, executionContext);
std::string from = argAsString(1, context, executionContext); string_type from = baseT::argAsString(1, context, executionContext);
std::string to = argAsString(2, context, executionContext); string_type to = baseT::argAsString(2, context, executionContext);
size_t p = 0; size_t p = 0;
for(size_t i = 0, ie = str.length(); i != ie; ++i) for(size_t i = 0, ie = str.length(); i != ie; ++i)
{ {
size_t r = from.find(str[i]); size_t r = from.find(str[i]);
if(r == std::string::npos) if(r == string_type::npos)
++p; ++p;
else if(r < to.length()) else if(r < to.length())
str[p++] = to[r]; str[p++] = to[r];
@ -419,7 +439,7 @@ public:
if(p != str.length()) if(p != str.length())
str.resize(p); str.resize(p);
return new StringValue<std::string, Arabica::default_string_adaptor<std::string> >(str); return new StringValue<string_type, string_adaptor>(str);
} // evaluate } // evaluate
}; // class TranslateFn }; // class TranslateFn

View file

@ -68,16 +68,16 @@ FunctionHolder<string_type, string_adaptor>::FunctionLookupTable[] =
{ "namespace-uri", CreateFn<NamespaceURIFn<string_type, string_adaptor>, string_type, string_adaptor> }, { "namespace-uri", CreateFn<NamespaceURIFn<string_type, string_adaptor>, string_type, string_adaptor> },
{ "name", CreateFn<NameFn<string_type, string_adaptor>, string_type, string_adaptor> }, { "name", CreateFn<NameFn<string_type, string_adaptor>, string_type, string_adaptor> },
// string functions // string functions
{"string", CreateFn<StringFn, string_type, string_adaptor> }, {"string", CreateFn<StringFn<string_type, string_adaptor>, string_type, string_adaptor> },
{"concat", CreateFn<ConcatFn, string_type, string_adaptor> }, {"concat", CreateFn<ConcatFn<string_type, string_adaptor>, string_type, string_adaptor> },
{"starts-with", CreateFn<StartsWithFn, string_type, string_adaptor> }, {"starts-with", CreateFn<StartsWithFn<string_type, string_adaptor>, string_type, string_adaptor> },
{"contains", CreateFn<ContainsFn, string_type, string_adaptor> }, {"contains", CreateFn<ContainsFn<string_type, string_adaptor>, string_type, string_adaptor> },
{"substring-before", CreateFn<SubstringBeforeFn, string_type, string_adaptor> }, {"substring-before", CreateFn<SubstringBeforeFn<string_type, string_adaptor>, string_type, string_adaptor> },
{"substring-after", CreateFn<SubstringAfterFn, string_type, string_adaptor> }, {"substring-after", CreateFn<SubstringAfterFn<string_type, string_adaptor>, string_type, string_adaptor> },
{"substring", CreateFn<SubstringFn, string_type, string_adaptor> }, {"substring", CreateFn<SubstringFn<string_type, string_adaptor>, string_type, string_adaptor> },
{"string-length", CreateFn<StringLengthFn, string_type, string_adaptor> }, {"string-length", CreateFn<StringLengthFn<string_type, string_adaptor>, string_type, string_adaptor> },
{"normalize-space", CreateFn<NormalizeSpaceFn, string_type, string_adaptor> }, {"normalize-space", CreateFn<NormalizeSpaceFn<string_type, string_adaptor>, string_type, string_adaptor> },
{"translate", CreateFn<TranslateFn, string_type, string_adaptor> }, {"translate", CreateFn<TranslateFn<string_type, string_adaptor>, string_type, string_adaptor> },
// boolean functions // boolean functions
{"boolean", CreateFn<BooleanFn, string_type, string_adaptor> }, {"boolean", CreateFn<BooleanFn, string_type, string_adaptor> },
{"not", CreateFn<NotFn, string_type, string_adaptor> }, {"not", CreateFn<NotFn, string_type, string_adaptor> },