mirror of
https://gerrit.wikimedia.org/r/mediawiki/extensions/AbuseFilter.git
synced 2024-09-24 10:48:17 +00:00
Unicode conversion, phase1: datum should be templated on char type.
added basic_datum<charT>, with typedefs datum and u32datum
This commit is contained in:
parent
dbc2da3177
commit
eb5586854e
26
parser_native/afstring.h
Normal file
26
parser_native/afstring.h
Normal file
|
@ -0,0 +1,26 @@
|
|||
/*
|
||||
* Copyright (c) 2008 Andrew Garrett.
|
||||
* Copyright (c) 2008 River Tarnell <river@wikimedia.org>
|
||||
* Derived from public domain code contributed by Victor Vasiliev.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely. This software is provided 'as-is', without any express or
|
||||
* implied warranty.
|
||||
*/
|
||||
#ifndef AFSTRING_H
|
||||
#define AFSTRING_H
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <unicode/uchar.h>
|
||||
|
||||
typedef std::basic_string<UChar> u32string;
|
||||
typedef std::basic_istream<UChar> u32istream;
|
||||
typedef std::basic_ostream<UChar> u32ostream;
|
||||
typedef std::basic_iostream<UChar> u32iostream;
|
||||
typedef std::basic_istringstream<UChar> u32istringstream;
|
||||
typedef std::basic_ostringstream<UChar> u32ostringstream;
|
||||
typedef std::basic_stringstream<UChar> u32stringstream;
|
||||
|
||||
#endif /* !AFSTRING_H */
|
|
@ -22,430 +22,6 @@
|
|||
|
||||
namespace afp {
|
||||
|
||||
datum::datum() {
|
||||
}
|
||||
|
||||
datum::datum(datum const &other)
|
||||
: value_(other.value_)
|
||||
{
|
||||
}
|
||||
|
||||
datum
|
||||
datum::from_string_convert(std::string const &var)
|
||||
{
|
||||
// Try integer
|
||||
try {
|
||||
return from_int(boost::lexical_cast<long int>(var));
|
||||
} catch (boost::bad_lexical_cast &e) {
|
||||
try {
|
||||
return from_double(boost::lexical_cast<double>(var));
|
||||
} catch (boost::bad_lexical_cast &e) {
|
||||
/* If it's nothing else, it's a string */
|
||||
return from_string(var);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
datum
|
||||
datum::from_string(std::string const &v)
|
||||
{
|
||||
datum d;
|
||||
d.value_ = v;
|
||||
return d;
|
||||
}
|
||||
|
||||
datum
|
||||
datum::from_int(long int v)
|
||||
{
|
||||
datum d;
|
||||
d.value_ = v;
|
||||
return d;
|
||||
}
|
||||
|
||||
datum
|
||||
datum::from_double(double v)
|
||||
{
|
||||
datum d;
|
||||
d.value_ = v;
|
||||
return d;
|
||||
}
|
||||
|
||||
template<> datum datum::from<std::string>(std::string const &v) {
|
||||
return from_string(v);
|
||||
}
|
||||
|
||||
template<> datum datum::from<long int>(long int const &v) {
|
||||
return from_int(v);
|
||||
}
|
||||
|
||||
template<> datum datum::from<double>(double const &v) {
|
||||
return from_double(v);
|
||||
}
|
||||
|
||||
datum & datum::operator= (datum const &other) {
|
||||
// Protect against self-assignment
|
||||
if (this == &other) {
|
||||
return *this;
|
||||
}
|
||||
|
||||
value_ = other.value_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert a string to an integer value.
|
||||
*/
|
||||
template<typename T>
|
||||
struct from_string_converter {
|
||||
typedef T type;
|
||||
|
||||
static type convert(T const &v) {
|
||||
return v;
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct from_string_converter<std::string> {
|
||||
typedef long int type;
|
||||
|
||||
template<typename T>
|
||||
static type convert(T const &v) {
|
||||
try {
|
||||
return boost::lexical_cast<type>(v);
|
||||
} catch (boost::bad_lexical_cast &e) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
* Conversions from datum to other types.
|
||||
*/
|
||||
struct to_string_visitor : boost::static_visitor<std::string> {
|
||||
std::string operator() (std::string const &v) const {
|
||||
return v;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
std::string operator() (T const &v) const {
|
||||
return boost::lexical_cast<std::string>(v);
|
||||
}
|
||||
};
|
||||
|
||||
struct to_int_visitor : boost::static_visitor<long int> {
|
||||
long int operator() (std::string const &v) const {
|
||||
try {
|
||||
return boost::lexical_cast<long int>(v);
|
||||
} catch (boost::bad_lexical_cast &e) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
long int operator() (double o) const {
|
||||
return (long int) o;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
long int operator() (T const &v) const {
|
||||
return v;
|
||||
}
|
||||
};
|
||||
|
||||
struct to_double_visitor : boost::static_visitor<double> {
|
||||
double operator() (std::string const &v) const {
|
||||
try {
|
||||
return boost::lexical_cast<double>(v);
|
||||
} catch (boost::bad_lexical_cast &e) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
double operator() (T const &v) const {
|
||||
return v;
|
||||
}
|
||||
};
|
||||
|
||||
std::string
|
||||
datum::toString() const {
|
||||
return boost::apply_visitor(to_string_visitor(), value_);
|
||||
}
|
||||
|
||||
long int
|
||||
datum::toInt() const {
|
||||
return boost::apply_visitor(to_int_visitor(), value_);
|
||||
}
|
||||
|
||||
double
|
||||
datum::toFloat() const {
|
||||
return boost::apply_visitor(to_double_visitor(), value_);
|
||||
}
|
||||
|
||||
/* Given T and U, find the preferred type for maths (i.e. double, if present) */
|
||||
template<typename T, typename U>
|
||||
struct preferred_type {
|
||||
typedef T type;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct preferred_type<double, T> {
|
||||
typedef double type;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct preferred_type<T, double> {
|
||||
typedef double type;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct preferred_type<double, double> {
|
||||
typedef double type;
|
||||
};
|
||||
|
||||
/*
|
||||
* std::modulus doesn't work with double, so we provide our own.
|
||||
*/
|
||||
template<typename T>
|
||||
struct afpmodulus {
|
||||
T operator() (T const &a, T const &b) const {
|
||||
return a % b;
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct afpmodulus<double> {
|
||||
double operator() (double const &a, double const &b) const {
|
||||
return std::fmod(a, b);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct afppower {
|
||||
T operator() (T const &a, T const &b) const {
|
||||
return std::pow(a,b);
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
* A visitor that performs an arithmetic operation on its arguments,
|
||||
* after doing appropriate int->double promotion.
|
||||
*/
|
||||
template<template<typename V> class Operator>
|
||||
struct arith_visitor : boost::static_visitor<datum> {
|
||||
/*
|
||||
* Anything involving a double returns a double.
|
||||
* Otherwise, int is returned.
|
||||
*/
|
||||
template<typename T, typename U>
|
||||
datum operator() (T const &a, U const &b) const {
|
||||
typedef typename from_string_converter<T>::type a_type;
|
||||
typedef typename from_string_converter<U>::type b_type;
|
||||
|
||||
Operator<typename preferred_type<a_type, b_type>::type> op;
|
||||
return datum::from<typename preferred_type<a_type, b_type>::type>(op(
|
||||
from_string_converter<T>::convert(a),
|
||||
from_string_converter<U>::convert(b)));
|
||||
}
|
||||
|
||||
/*
|
||||
* Unary version.
|
||||
*/
|
||||
template<typename T>
|
||||
datum operator() (T const &a) const {
|
||||
typedef typename from_string_converter<T>::type a_type;
|
||||
|
||||
Operator<typename preferred_type<a_type, a_type>::type> op;
|
||||
return datum::from<typename preferred_type<a_type, a_type>::type>(
|
||||
op(from_string_converter<T>::convert(a)));
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
/*
|
||||
* Like arith_visitor, but for equality comparisons.
|
||||
*/
|
||||
template<
|
||||
template<typename V> class Operator,
|
||||
typename T,
|
||||
typename U>
|
||||
struct compare_visitor_impl {
|
||||
bool operator() (T const &a, U const &b) const {
|
||||
typedef typename from_string_converter<T>::type a_type;
|
||||
typedef typename from_string_converter<U>::type b_type;
|
||||
|
||||
Operator<typename preferred_type<a_type, b_type>::type> op;
|
||||
return op(
|
||||
from_string_converter<T>::convert(a),
|
||||
from_string_converter<U>::convert(b));
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
* Specialise for string<>string comparisons
|
||||
*/
|
||||
template<template<typename V> class Operator>
|
||||
struct compare_visitor_impl<Operator, std::string, std::string> : boost::static_visitor<bool> {
|
||||
bool operator() (std::string const &a, std::string const &b) const {
|
||||
Operator<std::string> op;
|
||||
return op(a, b);
|
||||
}
|
||||
};
|
||||
|
||||
template<template<typename V> class Operator>
|
||||
struct compare_visitor : boost::static_visitor<bool> {
|
||||
template<typename T, typename U>
|
||||
bool operator() (T const &a, U const &b) const {
|
||||
return compare_visitor_impl<Operator, T, U>()(a, b);
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
* For comparisons that only work on integers - strings will be converted.
|
||||
*/
|
||||
template<template<typename V> class Operator>
|
||||
struct arith_compare_visitor : boost::static_visitor<bool> {
|
||||
template<typename T, typename U>
|
||||
bool operator() (T const &a, U const &b) const {
|
||||
typedef typename from_string_converter<T>::type a_type;
|
||||
typedef typename from_string_converter<U>::type b_type;
|
||||
|
||||
Operator<typename preferred_type<a_type, b_type>::type> op;
|
||||
return op(
|
||||
from_string_converter<T>::convert(a),
|
||||
from_string_converter<U>::convert(b));
|
||||
}
|
||||
};
|
||||
|
||||
datum &
|
||||
datum::operator+=(datum const &other)
|
||||
{
|
||||
/*
|
||||
* If either argument is a string, convert both to string. After discussion
|
||||
* on #mediawiki, this seems to be the least confusing option.
|
||||
*/
|
||||
if (value_.which() == 0 || other.value_.which() == 0) {
|
||||
value_ = toString() + other.toString();
|
||||
return *this;
|
||||
}
|
||||
|
||||
datum result = boost::apply_visitor(arith_visitor<std::plus>(), value_, other.value_);
|
||||
*this = result;
|
||||
return *this;
|
||||
}
|
||||
|
||||
datum &
|
||||
datum::operator-=(datum const &other)
|
||||
{
|
||||
datum result = boost::apply_visitor(arith_visitor<std::minus>(), value_, other.value_);
|
||||
*this = result;
|
||||
return *this;
|
||||
}
|
||||
|
||||
datum &
|
||||
datum::operator*=(datum const &other)
|
||||
{
|
||||
datum result = boost::apply_visitor(arith_visitor<std::multiplies>(), value_, other.value_);
|
||||
*this = result;
|
||||
return *this;
|
||||
}
|
||||
|
||||
datum&
|
||||
datum::operator/=(datum const &other)
|
||||
{
|
||||
datum result = boost::apply_visitor(arith_visitor<std::divides>(), value_, other.value_);
|
||||
*this = result;
|
||||
return *this;
|
||||
}
|
||||
|
||||
datum&
|
||||
datum::operator%=(datum const &other)
|
||||
{
|
||||
datum result = boost::apply_visitor(arith_visitor<afpmodulus>(), value_, other.value_);
|
||||
*this = result;
|
||||
return *this;
|
||||
}
|
||||
|
||||
datum
|
||||
datum::operator+() const
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
|
||||
datum
|
||||
datum::operator-() const
|
||||
{
|
||||
return boost::apply_visitor(arith_visitor<std::negate>(), value_);
|
||||
}
|
||||
|
||||
datum
|
||||
operator+(datum const &a, datum const &b) {
|
||||
return datum(a) += b;
|
||||
}
|
||||
|
||||
datum
|
||||
operator-(datum const &a, datum const &b) {
|
||||
return datum(a) -= b;
|
||||
}
|
||||
|
||||
datum
|
||||
operator*(datum const &a, datum const &b) {
|
||||
return datum(a) *= b;
|
||||
}
|
||||
|
||||
datum
|
||||
operator/(datum const &a, datum const &b) {
|
||||
return datum(a) /= b;
|
||||
}
|
||||
|
||||
datum
|
||||
operator%(datum const &a, datum const &b) {
|
||||
return datum(a) %= b;
|
||||
}
|
||||
|
||||
datum
|
||||
pow(datum const &a, datum const &b) {
|
||||
datum result = datum::from_double(std::pow(a.toFloat(),b.toFloat()));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool
|
||||
operator==(datum const &a, datum const &b) {
|
||||
return a.compare(b);
|
||||
}
|
||||
|
||||
bool
|
||||
datum::compare(datum const &other) const {
|
||||
return boost::apply_visitor(compare_visitor<std::equal_to>(), value_, other.value_);
|
||||
}
|
||||
|
||||
bool
|
||||
datum::compare_with_type(datum const &other) const {
|
||||
if (value_.which() != other.value_.which())
|
||||
return false;
|
||||
|
||||
return boost::apply_visitor(compare_visitor<std::equal_to>(), value_, other.value_);
|
||||
}
|
||||
|
||||
bool
|
||||
datum::less_than(datum const &other) const {
|
||||
return boost::apply_visitor(arith_compare_visitor<std::less>(), value_, other.value_);
|
||||
}
|
||||
|
||||
bool
|
||||
operator< (datum const &a, datum const &b) {
|
||||
return a.less_than(b);
|
||||
}
|
||||
|
||||
bool
|
||||
operator<= (datum const &a, datum const &b) {
|
||||
return a.less_than(b) || a == b;
|
||||
}
|
||||
|
||||
bool
|
||||
operator> (datum const &a, datum const &b) {
|
||||
return !(a <= b);
|
||||
}
|
||||
|
||||
bool
|
||||
operator>= (datum const &a, datum const &b) {
|
||||
|
|
|
@ -12,12 +12,20 @@
|
|||
#ifndef AFTYPES_H
|
||||
#define AFTYPES_H
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <ios>
|
||||
#include <iostream>
|
||||
#include <cassert>
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
|
||||
#include <boost/variant.hpp>
|
||||
#include <boost/lexical_cast.hpp>
|
||||
#include <boost/lexical_cast.hpp>
|
||||
#include <boost/variant.hpp>
|
||||
|
||||
#include <unicode/uchar.h>
|
||||
|
||||
namespace afp {
|
||||
|
||||
|
@ -47,58 +55,53 @@ namespace afp {
|
|||
* entirely stack-based, avoiding memory allocation overhead when manipulating
|
||||
* datum objects.
|
||||
*/
|
||||
class datum {
|
||||
public:
|
||||
datum();
|
||||
datum(datum const &oldData);
|
||||
|
||||
template<typename charT>
|
||||
struct basic_datum {
|
||||
typedef std::basic_string<charT> string_t;
|
||||
|
||||
basic_datum();
|
||||
basic_datum(basic_datum<charT> const &oldData);
|
||||
|
||||
// Type forcing construction functions
|
||||
static datum from_string(std::string const &v);
|
||||
static datum from_string_convert(std::string const &v);
|
||||
static datum from_int(long int v);
|
||||
static datum from_double(double v);
|
||||
static basic_datum<charT> from_string(string_t const &v);
|
||||
static basic_datum<charT> from_string_convert(std::basic_string<charT> const &v);
|
||||
static basic_datum<charT> from_int(long int v);
|
||||
static basic_datum<charT> from_double(double v);
|
||||
|
||||
/*
|
||||
* Template versions of the above. See below for the actual
|
||||
* implementations.
|
||||
*/
|
||||
template<typename T> static datum from(T const &v) {
|
||||
return from_int(0);
|
||||
}
|
||||
|
||||
// Assignment operator
|
||||
datum &operator= (const datum & other);
|
||||
basic_datum<charT> &operator= (const basic_datum<charT> & other);
|
||||
|
||||
datum &operator+=(datum const &other);
|
||||
datum &operator-=(datum const &other);
|
||||
datum &operator*=(datum const &other);
|
||||
datum &operator/=(datum const &other);
|
||||
datum &operator%=(datum const &other);
|
||||
basic_datum<charT> &operator+=(basic_datum<charT> const &other);
|
||||
basic_datum<charT> &operator-=(basic_datum<charT> const &other);
|
||||
basic_datum<charT> &operator*=(basic_datum<charT> const &other);
|
||||
basic_datum<charT> &operator/=(basic_datum<charT> const &other);
|
||||
basic_datum<charT> &operator%=(basic_datum<charT> const &other);
|
||||
bool operator!() const;
|
||||
datum operator+() const;
|
||||
datum operator-() const;
|
||||
basic_datum<charT> operator+() const;
|
||||
basic_datum<charT> operator-() const;
|
||||
|
||||
bool compare(datum const &other) const;
|
||||
bool compare_with_type(datum const &other) const;
|
||||
bool less_than(datum const &other) const;
|
||||
bool compare(basic_datum<charT> const &other) const;
|
||||
bool compare_with_type(basic_datum<charT> const &other) const;
|
||||
bool less_than(basic_datum<charT> const &other) const;
|
||||
|
||||
std::string toString() const;
|
||||
string_t toString() const;
|
||||
long int toInt() const;
|
||||
double toFloat() const;
|
||||
bool toBool() const {
|
||||
return (bool) toInt();
|
||||
}
|
||||
|
||||
template<typename char_type, typename traits>
|
||||
template<typename traits>
|
||||
void
|
||||
print_to(std::basic_ostream<char_type, traits> &s) const {
|
||||
print_to(std::basic_ostream<charT, traits> &s) const {
|
||||
s << value_;
|
||||
}
|
||||
|
||||
protected:
|
||||
void _init_from_string(std::string const &);
|
||||
void _init_from_string(string_t const &);
|
||||
|
||||
typedef boost::variant<std::string, long int, double> valuetype;
|
||||
typedef boost::variant<string_t, long int, double> valuetype;
|
||||
valuetype value_;
|
||||
};
|
||||
|
||||
|
@ -116,33 +119,48 @@ private:
|
|||
std::string what_;
|
||||
};
|
||||
|
||||
|
||||
template<> datum datum::from<std::string>(std::string const &v);
|
||||
template<> datum datum::from<long int>(long int const &v);
|
||||
template<> datum datum::from<long int>(long int const &v);
|
||||
|
||||
datum operator+(datum const &a, datum const &b);
|
||||
datum operator-(datum const &a, datum const &b);
|
||||
datum operator*(datum const &a, datum const &b);
|
||||
datum operator/(datum const &a, datum const &b);
|
||||
datum operator%(datum const &a, datum const &b);
|
||||
|
||||
bool operator==(datum const &a, datum const &b);
|
||||
bool operator!=(datum const &a, datum const &b);
|
||||
bool operator<(datum const &a, datum const &b);
|
||||
bool operator>(datum const &a, datum const &b);
|
||||
bool operator<=(datum const &a, datum const &b);
|
||||
bool operator>=(datum const &a, datum const &b);
|
||||
|
||||
datum pow(datum const &a, datum const &b);
|
||||
|
||||
template<typename char_type, typename traits>
|
||||
std::basic_ostream<char_type, traits> &
|
||||
operator<<(std::basic_ostream<char_type, traits> &s, datum const &d) {
|
||||
d.print_to(s);
|
||||
return s;
|
||||
}
|
||||
|
||||
#include "datum/create.h"
|
||||
#include "datum/conversion.h"
|
||||
#include "datum/operators.h"
|
||||
|
||||
namespace afp {
|
||||
|
||||
template<typename charT>
|
||||
basic_datum<charT>::basic_datum() {
|
||||
}
|
||||
|
||||
template<typename charT>
|
||||
basic_datum<charT>::basic_datum(basic_datum<charT> const &other)
|
||||
: value_(other.value_)
|
||||
{
|
||||
}
|
||||
|
||||
template<typename charT>
|
||||
bool
|
||||
basic_datum<charT>::compare(basic_datum<charT> const &other) const {
|
||||
return boost::apply_visitor(datum_impl::compare_visitor<charT, std::equal_to>(), value_, other.value_);
|
||||
}
|
||||
|
||||
template<typename charT>
|
||||
bool
|
||||
basic_datum<charT>::compare_with_type(basic_datum<charT> const &other) const {
|
||||
if (value_.which() != other.value_.which())
|
||||
return false;
|
||||
|
||||
return boost::apply_visitor(datum_impl::compare_visitor<charT, std::equal_to>(), value_, other.value_);
|
||||
}
|
||||
|
||||
template<typename charT>
|
||||
bool
|
||||
basic_datum<charT>::less_than(basic_datum<charT> const &other) const {
|
||||
return boost::apply_visitor(datum_impl::arith_compare_visitor<charT, std::less>(), value_, other.value_);
|
||||
}
|
||||
|
||||
typedef basic_datum<char> datum;
|
||||
typedef basic_datum<UChar> u32datum;
|
||||
|
||||
} // namespace afp
|
||||
|
||||
#endif /* !AFTYPES_H */
|
||||
|
|
83
parser_native/include/datum/conversion.h
Normal file
83
parser_native/include/datum/conversion.h
Normal file
|
@ -0,0 +1,83 @@
|
|||
/*
|
||||
* Copyright (c) 2008 Andrew Garrett.
|
||||
* Copyright (c) 2008 River Tarnell <river@wikimedia.org>
|
||||
* Derived from public domain code contributed by Victor Vasiliev.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely. This software is provided 'as-is', without any express or
|
||||
* implied warranty.
|
||||
*/
|
||||
|
||||
#ifndef DATUM_CONVERSION_H
|
||||
#define DATUM_CONVERSION_H
|
||||
|
||||
#include "datum/visitors.h"
|
||||
|
||||
namespace afp {
|
||||
|
||||
template<typename charT>
|
||||
basic_datum<charT>
|
||||
basic_datum<charT>::from_string_convert(basic_datum<charT>::string_t const &var)
|
||||
{
|
||||
// Try integer
|
||||
try {
|
||||
return from_int(boost::lexical_cast<long int>(var));
|
||||
} catch (boost::bad_lexical_cast &e) {
|
||||
try {
|
||||
return from_double(boost::lexical_cast<double>(var));
|
||||
} catch (boost::bad_lexical_cast &e) {
|
||||
/* If it's nothing else, it's a string */
|
||||
return from_string(var);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<typename charT>
|
||||
basic_datum<charT>
|
||||
basic_datum<charT>::from_string(basic_datum<charT>::string_t const &v)
|
||||
{
|
||||
basic_datum<charT> d;
|
||||
d.value_ = v;
|
||||
return d;
|
||||
}
|
||||
|
||||
template<typename charT>
|
||||
basic_datum<charT>
|
||||
basic_datum<charT>::from_int(long int v)
|
||||
{
|
||||
basic_datum<charT> d;
|
||||
d.value_ = v;
|
||||
return d;
|
||||
}
|
||||
|
||||
template<typename charT>
|
||||
basic_datum<charT>
|
||||
basic_datum<charT>::from_double(double v)
|
||||
{
|
||||
basic_datum<charT> d;
|
||||
d.value_ = v;
|
||||
return d;
|
||||
}
|
||||
|
||||
template<typename charT>
|
||||
std::basic_string<charT>
|
||||
basic_datum<charT>::toString() const {
|
||||
return boost::apply_visitor(datum_impl::to_string_visitor<charT>(), value_);
|
||||
}
|
||||
|
||||
template<typename charT>
|
||||
long int
|
||||
basic_datum<charT>::toInt() const {
|
||||
return boost::apply_visitor(datum_impl::to_int_visitor<charT>(), value_);
|
||||
}
|
||||
|
||||
template<typename charT>
|
||||
double
|
||||
basic_datum<charT>::toFloat() const {
|
||||
return boost::apply_visitor(datum_impl::to_double_visitor<charT>(), value_);
|
||||
}
|
||||
|
||||
} // namespace afp
|
||||
|
||||
#endif /* !DATUM_CONVERSION_H */
|
43
parser_native/include/datum/create.h
Normal file
43
parser_native/include/datum/create.h
Normal file
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* Copyright (c) 2008 Andrew Garrett.
|
||||
* Copyright (c) 2008 River Tarnell <river@wikimedia.org>
|
||||
* Derived from public domain code contributed by Victor Vasiliev.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely. This software is provided 'as-is', without any express or
|
||||
* implied warranty.
|
||||
*/
|
||||
|
||||
#ifndef DATUM_CREATE_H
|
||||
#define DATUM_CREATE_H
|
||||
|
||||
namespace afp {
|
||||
|
||||
template<typename charT, typename T>
|
||||
struct create_datum;
|
||||
|
||||
template<typename charT>
|
||||
struct create_datum<charT, long int> {
|
||||
static basic_datum<charT> create(long int v) {
|
||||
return basic_datum<charT>::from_int(v);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename charT>
|
||||
struct create_datum<charT, double> {
|
||||
static basic_datum<charT> create(double v) {
|
||||
return basic_datum<charT>::from_double(v);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename charT>
|
||||
struct create_datum<charT, std::string> {
|
||||
static basic_datum<charT> create(std::basic_string<charT> const &v) {
|
||||
return basic_datum<charT>::from_string(v);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif /* !DATUM_CREATE_H */
|
239
parser_native/include/datum/operators.h
Normal file
239
parser_native/include/datum/operators.h
Normal file
|
@ -0,0 +1,239 @@
|
|||
/*
|
||||
* Copyright (c) 2008 Andrew Garrett.
|
||||
* Copyright (c) 2008 River Tarnell <river@wikimedia.org>
|
||||
* Derived from public domain code contributed by Victor Vasiliev.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely. This software is provided 'as-is', without any express or
|
||||
* implied warranty.
|
||||
*/
|
||||
|
||||
#ifndef DATUM_OPERATORS_H
|
||||
#define DATUM_OPERATORS_H
|
||||
|
||||
#include "datum/visitors.h"
|
||||
|
||||
namespace afp {
|
||||
|
||||
namespace datum_impl {
|
||||
|
||||
/*
|
||||
* std::modulus doesn't work with double, so we provide our own.
|
||||
*/
|
||||
template<typename T>
|
||||
struct afpmodulus {
|
||||
T operator() (T const &a, T const &b) const {
|
||||
return a % b;
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct afpmodulus<double> {
|
||||
double operator() (double const &a, double const &b) const {
|
||||
return std::fmod(a, b);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct afppower {
|
||||
T operator() (T const &a, T const &b) const {
|
||||
return std::pow(a,b);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace datum_impl
|
||||
|
||||
template<typename charT>
|
||||
basic_datum<charT> operator+(basic_datum<charT> const &a, basic_datum<charT> const &b);
|
||||
template<typename charT>
|
||||
basic_datum<charT> operator-(basic_datum<charT> const &a, basic_datum<charT> const &b);
|
||||
template<typename charT>
|
||||
basic_datum<charT> operator*(basic_datum<charT> const &a, basic_datum<charT> const &b);
|
||||
template<typename charT>
|
||||
basic_datum<charT> operator/(basic_datum<charT> const &a, basic_datum<charT> const &b);
|
||||
template<typename charT>
|
||||
basic_datum<charT> operator%(basic_datum<charT> const &a, basic_datum<charT> const &b);
|
||||
|
||||
template<typename charT>
|
||||
bool operator==(basic_datum<charT> const &a, basic_datum<charT> const &b);
|
||||
template<typename charT>
|
||||
bool operator!=(basic_datum<charT> const &a, basic_datum<charT> const &b);
|
||||
template<typename charT>
|
||||
bool operator<(basic_datum<charT> const &a, basic_datum<charT> const &b);
|
||||
template<typename charT>
|
||||
bool operator>(basic_datum<charT> const &a, basic_datum<charT> const &b);
|
||||
template<typename charT>
|
||||
bool operator<=(basic_datum<charT> const &a, basic_datum<charT> const &b);
|
||||
template<typename charT>
|
||||
bool operator>=(basic_datum<charT> const &a, basic_datum<charT> const &b);
|
||||
|
||||
template<typename charT>
|
||||
basic_datum<charT> pow(basic_datum<charT> const &a, basic_datum<charT> const &b);
|
||||
|
||||
template<typename charT, typename char_type, typename traits>
|
||||
std::basic_ostream<char_type, traits> &
|
||||
operator<<(std::basic_ostream<char_type, traits> &s, basic_datum<charT> const &d) {
|
||||
d.print_to(s);
|
||||
return s;
|
||||
}
|
||||
|
||||
template<typename charT>
|
||||
basic_datum<charT> &
|
||||
basic_datum<charT>::operator= (basic_datum<charT> const &other) {
|
||||
value_ = other.value_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename charT>
|
||||
basic_datum<charT> &
|
||||
basic_datum<charT>::operator+=(basic_datum<charT> const &other)
|
||||
{
|
||||
/*
|
||||
* If either argument is a string, convert both to string. After discussion
|
||||
* on #mediawiki, this seems to be the least confusing option.
|
||||
*/
|
||||
if (value_.which() == 0 || other.value_.which() == 0) {
|
||||
value_ = toString() + other.toString();
|
||||
return *this;
|
||||
}
|
||||
|
||||
basic_datum<charT> result = boost::apply_visitor(datum_impl::arith_visitor<charT, std::plus>(), value_, other.value_);
|
||||
*this = result;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename charT>
|
||||
basic_datum<charT> &
|
||||
basic_datum<charT>::operator-=(basic_datum<charT> const &other)
|
||||
{
|
||||
basic_datum<charT> result = boost::apply_visitor(datum_impl::arith_visitor<charT, std::minus>(), value_, other.value_);
|
||||
*this = result;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename charT>
|
||||
basic_datum<charT> &
|
||||
basic_datum<charT>::operator*=(basic_datum<charT> const &other)
|
||||
{
|
||||
basic_datum<charT> result = boost::apply_visitor(datum_impl::arith_visitor<charT, std::multiplies>(), value_, other.value_);
|
||||
*this = result;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename charT>
|
||||
basic_datum<charT>&
|
||||
basic_datum<charT>::operator/=(basic_datum<charT> const &other)
|
||||
{
|
||||
basic_datum<charT> result = boost::apply_visitor(datum_impl::arith_visitor<charT, std::divides>(), value_, other.value_);
|
||||
*this = result;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename charT>
|
||||
basic_datum<charT>&
|
||||
basic_datum<charT>::operator%=(basic_datum<charT> const &other)
|
||||
{
|
||||
basic_datum<charT> result = boost::apply_visitor(
|
||||
datum_impl::arith_visitor<charT, datum_impl::afpmodulus>(), value_, other.value_);
|
||||
*this = result;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename charT>
|
||||
basic_datum<charT>
|
||||
basic_datum<charT>::operator+() const
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename charT>
|
||||
basic_datum<charT>
|
||||
basic_datum<charT>::operator-() const
|
||||
{
|
||||
return boost::apply_visitor(datum_impl::arith_visitor<charT, std::negate>(), value_);
|
||||
}
|
||||
|
||||
template<typename charT>
|
||||
basic_datum<charT>
|
||||
operator+(basic_datum<charT> const &a, basic_datum<charT> const &b) {
|
||||
return basic_datum<charT>(a) += b;
|
||||
}
|
||||
|
||||
template<typename charT>
|
||||
basic_datum<charT>
|
||||
operator-(basic_datum<charT> const &a, basic_datum<charT> const &b) {
|
||||
return basic_datum<charT>(a) -= b;
|
||||
}
|
||||
|
||||
template<typename charT>
|
||||
basic_datum<charT>
|
||||
operator*(basic_datum<charT> const &a, basic_datum<charT> const &b) {
|
||||
return basic_datum<charT>(a) *= b;
|
||||
}
|
||||
|
||||
template<typename charT>
|
||||
basic_datum<charT>
|
||||
operator/(basic_datum<charT> const &a, basic_datum<charT> const &b) {
|
||||
return basic_datum<charT>(a) /= b;
|
||||
}
|
||||
|
||||
template<typename charT>
|
||||
basic_datum<charT>
|
||||
operator%(basic_datum<charT> const &a, basic_datum<charT> const &b) {
|
||||
return basic_datum<charT>(a) %= b;
|
||||
}
|
||||
|
||||
template<typename charT>
|
||||
basic_datum<charT>
|
||||
pow(basic_datum<charT> const &a, basic_datum<charT> const &b) {
|
||||
basic_datum<charT> result = basic_datum<charT>::from_double(std::pow(a.toFloat(),b.toFloat()));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
template<typename charT>
|
||||
bool
|
||||
operator==(basic_datum<charT> const &a, basic_datum<charT> const &b) {
|
||||
return a.compare(b);
|
||||
}
|
||||
|
||||
template<typename charT>
|
||||
bool
|
||||
operator< (basic_datum<charT> const &a, basic_datum<charT> const &b) {
|
||||
return a.less_than(b);
|
||||
}
|
||||
|
||||
template<typename charT>
|
||||
bool
|
||||
operator<= (basic_datum<charT> const &a, basic_datum<charT> const &b) {
|
||||
return a.less_than(b) || a == b;
|
||||
}
|
||||
|
||||
template<typename charT>
|
||||
bool
|
||||
operator> (basic_datum<charT> const &a, basic_datum<charT> const &b) {
|
||||
return !(a <= b);
|
||||
}
|
||||
|
||||
template<typename charT>
|
||||
bool
|
||||
operator>= (basic_datum<charT> const &a, basic_datum<charT> const &b) {
|
||||
return !(a < b);
|
||||
}
|
||||
|
||||
template<typename charT>
|
||||
bool
|
||||
operator!= (basic_datum<charT> const &a, basic_datum<charT> const &b) {
|
||||
return !(a == b);
|
||||
}
|
||||
|
||||
template<typename charT>
|
||||
bool
|
||||
basic_datum<charT>::operator! () const {
|
||||
return !toBool();
|
||||
}
|
||||
|
||||
} // namespace afp
|
||||
|
||||
#endif /* !DATUM_OPERATORS_H */
|
223
parser_native/include/datum/visitors.h
Normal file
223
parser_native/include/datum/visitors.h
Normal file
|
@ -0,0 +1,223 @@
|
|||
/*
|
||||
* Copyright (c) 2008 Andrew Garrett.
|
||||
* Copyright (c) 2008 River Tarnell <river@wikimedia.org>
|
||||
* Derived from public domain code contributed by Victor Vasiliev.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely. This software is provided 'as-is', without any express or
|
||||
* implied warranty.
|
||||
*/
|
||||
|
||||
#ifndef DATUM_VISITORS_H
|
||||
#define DATUM_VISITORS_H
|
||||
|
||||
#include "datum/create.h"
|
||||
|
||||
namespace afp {
|
||||
namespace datum_impl {
|
||||
|
||||
/* Given T and U, find the preferred type for maths (i.e. double, if present) */
|
||||
template<typename T, typename U>
|
||||
struct preferred_type {
|
||||
typedef T type;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct preferred_type<double, T> {
|
||||
typedef double type;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct preferred_type<T, double> {
|
||||
typedef double type;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct preferred_type<double, double> {
|
||||
typedef double type;
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Convert a string to an integer value.
|
||||
*/
|
||||
template<typename charT, typename T>
|
||||
struct from_string_converter {
|
||||
typedef T type;
|
||||
|
||||
static type convert(T const &v) {
|
||||
return v;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename charT>
|
||||
struct from_string_converter<charT, std::basic_string<charT> > {
|
||||
typedef long int type;
|
||||
|
||||
template<typename T>
|
||||
static type convert(T const &v) {
|
||||
try {
|
||||
return boost::lexical_cast<type>(v);
|
||||
} catch (boost::bad_lexical_cast &e) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
* Conversions from datum to other types.
|
||||
*/
|
||||
template<typename charT>
|
||||
struct to_string_visitor : boost::static_visitor<std::basic_string<charT> > {
|
||||
std::basic_string<charT> operator() (std::basic_string<charT> const &v) const {
|
||||
return v;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
std::basic_string<charT> operator() (T const &v) const {
|
||||
return boost::lexical_cast<std::basic_string<charT> >(v);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename charT>
|
||||
struct to_int_visitor : boost::static_visitor<long int> {
|
||||
long int operator() (std::basic_string<charT> const &v) const {
|
||||
try {
|
||||
return boost::lexical_cast<long int>(v);
|
||||
} catch (boost::bad_lexical_cast &e) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
long int operator() (double o) const {
|
||||
return (long int) o;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
long int operator() (T const &v) const {
|
||||
return v;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename charT>
|
||||
struct to_double_visitor : boost::static_visitor<double> {
|
||||
double operator() (std::basic_string<charT> const &v) const {
|
||||
try {
|
||||
return boost::lexical_cast<double>(v);
|
||||
} catch (boost::bad_lexical_cast &e) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
double operator() (T const &v) const {
|
||||
return v;
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
* A visitor that performs an arithmetic operation on its arguments,
|
||||
* after doing appropriate int->double promotion.
|
||||
*/
|
||||
template<typename charT, template<typename V> class Operator>
|
||||
struct arith_visitor : boost::static_visitor<basic_datum<charT> > {
|
||||
/*
|
||||
* Anything involving a double returns a double.
|
||||
* Otherwise, int is returned.
|
||||
*/
|
||||
template<typename T, typename U>
|
||||
basic_datum<charT> operator() (T const &a, U const &b) const {
|
||||
typedef typename from_string_converter<charT, T>::type a_type;
|
||||
typedef typename from_string_converter<charT, U>::type b_type;
|
||||
typedef typename preferred_type<a_type, b_type>::type preferred_type;
|
||||
|
||||
Operator<preferred_type> op;
|
||||
return create_datum<charT, preferred_type>::create(op(
|
||||
from_string_converter<charT, T>::convert(a),
|
||||
from_string_converter<charT, U>::convert(b)));
|
||||
}
|
||||
|
||||
/*
|
||||
* Unary version.
|
||||
*/
|
||||
template<typename T>
|
||||
basic_datum<charT> operator() (T const &a) const {
|
||||
typedef typename from_string_converter<charT, T>::type a_type;
|
||||
typedef typename preferred_type<a_type, a_type>::type preferred_type;
|
||||
|
||||
Operator<preferred_type> op;
|
||||
return create_datum<charT, preferred_type>::create(
|
||||
op(from_string_converter<charT, T>::convert(a)));
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
/*
|
||||
* Like arith_visitor, but for equality comparisons.
|
||||
*/
|
||||
template<
|
||||
typename charT,
|
||||
template<typename V> class Operator,
|
||||
typename T,
|
||||
typename U>
|
||||
struct compare_visitor_impl {
|
||||
bool operator() (T const &a, U const &b) const {
|
||||
typedef typename from_string_converter<charT, T>::type a_type;
|
||||
typedef typename from_string_converter<charT, U>::type b_type;
|
||||
typedef typename preferred_type<a_type, b_type>::type preferred_type;
|
||||
|
||||
Operator<preferred_type> op;
|
||||
return op(
|
||||
from_string_converter<charT, T>::convert(a),
|
||||
from_string_converter<charT, U>::convert(b));
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
* Specialise for string<>string comparisons
|
||||
*/
|
||||
template<typename charT, template<typename V> class Operator>
|
||||
struct compare_visitor_impl<
|
||||
charT,
|
||||
Operator,
|
||||
std::basic_string<charT>,
|
||||
std::basic_string<charT>
|
||||
> : boost::static_visitor<bool> {
|
||||
|
||||
bool operator() (std::basic_string<charT> const &a, std::basic_string<charT> const &b) const {
|
||||
Operator<std::basic_string<charT> > op;
|
||||
return op(a, b);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename charT, template<typename V> class Operator>
|
||||
struct compare_visitor : boost::static_visitor<bool> {
|
||||
template<typename T, typename U>
|
||||
bool operator() (T const &a, U const &b) const {
|
||||
return compare_visitor_impl<charT, Operator, T, U>()(a, b);
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
* For comparisons that only work on integers - strings will be converted.
|
||||
*/
|
||||
template<typename charT, template<typename V> class Operator>
|
||||
struct arith_compare_visitor : boost::static_visitor<bool> {
|
||||
template<typename T, typename U>
|
||||
bool operator() (T const &a, U const &b) const {
|
||||
typedef typename from_string_converter<charT, T>::type a_type;
|
||||
typedef typename from_string_converter<charT, U>::type b_type;
|
||||
typedef typename preferred_type<a_type, b_type>::type preferred_type;
|
||||
|
||||
Operator<preferred_type> op;
|
||||
return op(
|
||||
from_string_converter<charT, T>::convert(a),
|
||||
from_string_converter<charT, U>::convert(b));
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace datum_impl
|
||||
} // namespace afp
|
||||
|
||||
#endif /* !DATUM_VISITORS_H */
|
|
@ -9,7 +9,7 @@
|
|||
|
||||
include makefile.config
|
||||
|
||||
CPPFLAGS = $(EXTRA_CPPFLAGS)
|
||||
CPPFLAGS = -Iinclude $(EXTRA_CPPFLAGS)
|
||||
LDFLAGS = $(EXTRA_LDFLAGS)
|
||||
|
||||
LIBS = -lboost_regex$(BOOST_TAG) -licuuc -licui18n -licudata
|
||||
|
@ -18,7 +18,6 @@ expr: CPPFLAGS+=-DTEST_PARSER
|
|||
|
||||
af_expr_objs = \
|
||||
af_expr-affunctions.o \
|
||||
af_expr-aftypes.o \
|
||||
af_expr-parser.o \
|
||||
af_expr-filter_evaluator.o \
|
||||
af_expr-eval.o \
|
||||
|
@ -28,7 +27,6 @@ af_expr_objs = \
|
|||
|
||||
af_parser_objs = \
|
||||
af_parser-affunctions.o \
|
||||
af_parser-aftypes.o \
|
||||
af_parser-main.o \
|
||||
af_parser-parser.o \
|
||||
af_parser-request.o \
|
||||
|
@ -38,7 +36,6 @@ af_parser_objs = \
|
|||
|
||||
check_objs = \
|
||||
check-affunctions.o \
|
||||
check-aftypes.o \
|
||||
check-check.o \
|
||||
check-parser.o \
|
||||
check-utf8.o \
|
||||
|
@ -47,7 +44,6 @@ check_objs = \
|
|||
|
||||
syntax_check_objs = \
|
||||
syntax_check-affunctions.o \
|
||||
syntax_check-aftypes.o \
|
||||
syntax_check-filter_evaluator.o \
|
||||
syntax_check-parser.o \
|
||||
syntax_check-utf8.o \
|
||||
|
@ -55,7 +51,6 @@ syntax_check_objs = \
|
|||
syntax_check-syntax_check.o
|
||||
|
||||
expr_objs = \
|
||||
expr-aftypes.o \
|
||||
expr-parser.o
|
||||
|
||||
progs = check af_parser syntax_check af_expr expr
|
||||
|
|
|
@ -370,7 +370,7 @@ struct parser_grammar : public grammar<parser_grammar, parser_closure::context_t
|
|||
pow_expr =
|
||||
in_expr[pow_expr.val = arg1]
|
||||
>> !(
|
||||
"**" >> pow_expr[pow_expr.val = bind(&afp::pow)(pow_expr.val, arg1)]
|
||||
"**" >> pow_expr[pow_expr.val = bind(&afp::pow<char>)(pow_expr.val, arg1)]
|
||||
)
|
||||
;
|
||||
|
||||
|
|
Loading…
Reference in a new issue