From c728e85c8c72e8b947993bd880033d9aeb11095b Mon Sep 17 00:00:00 2001 From: Gunnar Beutner Date: Sun, 10 Mar 2013 15:11:32 +0100 Subject: [PATCH] Implement attribute filters. --- components/livestatus/andfilter.cpp | 9 +- components/livestatus/andfilter.h | 9 +- components/livestatus/attributefilter.cpp | 88 ++++++++++++++++++ components/livestatus/attributefilter.h | 47 ++++++++++ components/livestatus/combinerfilter.cpp | 31 +++++++ components/livestatus/combinerfilter.h | 45 ++++++++++ components/livestatus/filter.h | 2 +- components/livestatus/i2-livestatus.h | 7 +- components/livestatus/livestatus.vcxproj | 6 ++ .../livestatus/livestatus.vcxproj.filters | 18 ++++ components/livestatus/negatefilter.cpp | 32 +++++++ components/livestatus/negatefilter.h | 45 ++++++++++ components/livestatus/orfilter.cpp | 9 +- components/livestatus/orfilter.h | 9 +- components/livestatus/query.cpp | 89 ++++++++++++++++--- components/livestatus/query.h | 3 + components/livestatus/table.cpp | 4 +- components/livestatus/table.h | 6 +- lib/base/qstring.cpp | 75 +++++++++++----- lib/base/qstring.h | 10 +++ 20 files changed, 478 insertions(+), 66 deletions(-) create mode 100644 components/livestatus/attributefilter.cpp create mode 100644 components/livestatus/attributefilter.h create mode 100644 components/livestatus/combinerfilter.cpp create mode 100644 components/livestatus/combinerfilter.h create mode 100644 components/livestatus/negatefilter.cpp create mode 100644 components/livestatus/negatefilter.h diff --git a/components/livestatus/andfilter.cpp b/components/livestatus/andfilter.cpp index 4e56fb533..087f0d3d0 100644 --- a/components/livestatus/andfilter.cpp +++ b/components/livestatus/andfilter.cpp @@ -25,17 +25,12 @@ using namespace livestatus; AndFilter::AndFilter(void) { } -bool AndFilter::Apply(const Object::Ptr& object) +bool AndFilter::Apply(const Table::Ptr& table, const Object::Ptr& object) { BOOST_FOREACH(const Filter::Ptr& filter, m_Filters) { - if (!filter->Apply(object)) + if (!filter->Apply(table, object)) return false; } return true; } - -void AndFilter::AddSubFilter(const Filter::Ptr& filter) -{ - m_Filters.push_back(filter); -} \ No newline at end of file diff --git a/components/livestatus/andfilter.h b/components/livestatus/andfilter.h index dac34afc8..748ef85f1 100644 --- a/components/livestatus/andfilter.h +++ b/components/livestatus/andfilter.h @@ -26,7 +26,7 @@ namespace livestatus /** * @ingroup livestatus */ -class AndFilter : public Filter +class AndFilter : public CombinerFilter { public: typedef shared_ptr Ptr; @@ -34,12 +34,7 @@ public: AndFilter(void); - virtual bool Apply(const Object::Ptr& object); - - void AddSubFilter(const Filter::Ptr& filter); - -private: - vector m_Filters; + virtual bool Apply(const Table::Ptr& table, const Object::Ptr& object); }; } diff --git a/components/livestatus/attributefilter.cpp b/components/livestatus/attributefilter.cpp new file mode 100644 index 000000000..cc6e93d60 --- /dev/null +++ b/components/livestatus/attributefilter.cpp @@ -0,0 +1,88 @@ +/****************************************************************************** + * Icinga 2 * + * Copyright (C) 2012 Icinga Development Team (http://www.icinga.org/) * + * * + * This program is free software; you can redistribute it and/or * + * modify it under the terms of the GNU General Public License * + * as published by the Free Software Foundation; either version 2 * + * of the License, or (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the Free Software Foundation * + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. * + ******************************************************************************/ + +#include "i2-livestatus.h" + +using namespace icinga; +using namespace livestatus; + +AttributeFilter::AttributeFilter(const String& column, const String& op, const String& operand) + : m_Column(column), m_Operator(op), m_Operand(operand) +{ } + +bool AttributeFilter::Apply(const Table::Ptr& table, const Object::Ptr& object) +{ + Table::ColumnAccessor accessor = table->GetColumn(m_Column); + + if (accessor.empty()) + BOOST_THROW_EXCEPTION(invalid_argument("Filter expression uses unknown column '" + m_Column + "'")); + + Value value = accessor(object); + + if (value.IsObjectType()) { + if (m_Operator == ">=") { + Array::Ptr array = value; + BOOST_FOREACH(const String& item, array) { + if (item == m_Operand) + return true; /* Item found in list. */ + } + + return false; /* Item not found in list. */ + } else { + BOOST_THROW_EXCEPTION(invalid_argument("Invalid operator for column '" + m_Column + "': " + m_Operator + " (expected '>=').")); + } + } else { + if (m_Operator == "=") { + if (value.GetType() == ValueNumber) + return (static_cast(value) == Convert::ToDouble(m_Operand)); + else + return (static_cast(value) == m_Operand); + } else if (m_Operator == "~") { + + } else if (m_Operator == "=~") { + return string_iless()(value, m_Operand); + } else if (m_Operator == "~~") { + + } else if (m_Operator == "<") { + if (value.GetType() == ValueNumber) + return (static_cast(value) < Convert::ToDouble(m_Operand)); + else + return (static_cast(value) < m_Operand); + } else if (m_Operator == ">") { + if (value.GetType() == ValueNumber) + return (static_cast(value) > Convert::ToDouble(m_Operand)); + else + return (static_cast(value) > m_Operand); + } else if (m_Operator == "<=") { + if (value.GetType() == ValueNumber) + return (static_cast(value) <= Convert::ToDouble(m_Operand)); + else + return (static_cast(value) <= m_Operand); + } else if (m_Operator == ">=") { + if (value.GetType() == ValueNumber) + return (static_cast(value) >= Convert::ToDouble(m_Operand)); + else + return (static_cast(value) >= m_Operand); + } else { + BOOST_THROW_EXCEPTION(invalid_argument("Unknown operator for column '" + m_Column + "': " + m_Operator)); + } + } + + return false; +} diff --git a/components/livestatus/attributefilter.h b/components/livestatus/attributefilter.h new file mode 100644 index 000000000..eb508dc92 --- /dev/null +++ b/components/livestatus/attributefilter.h @@ -0,0 +1,47 @@ +/****************************************************************************** + * Icinga 2 * + * Copyright (C) 2012 Icinga Development Team (http://www.icinga.org/) * + * * + * This program is free software; you can redistribute it and/or * + * modify it under the terms of the GNU General Public License * + * as published by the Free Software Foundation; either version 2 * + * of the License, or (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the Free Software Foundation * + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. * + ******************************************************************************/ + +#ifndef ATTRIBUTEFILTER_H +#define ATTRIBUTEFILTER_H + +namespace livestatus +{ + +/** + * @ingroup livestatus + */ +class AttributeFilter : public Filter +{ +public: + typedef shared_ptr Ptr; + typedef weak_ptr WeakPtr; + + AttributeFilter(const String& column, const String& op, const String& operand); + + virtual bool Apply(const Table::Ptr& table, const Object::Ptr& object); + +protected: + String m_Column; + String m_Operator; + String m_Operand; +}; + +} + +#endif /* FILTER_H */ diff --git a/components/livestatus/combinerfilter.cpp b/components/livestatus/combinerfilter.cpp new file mode 100644 index 000000000..ce835802e --- /dev/null +++ b/components/livestatus/combinerfilter.cpp @@ -0,0 +1,31 @@ +/****************************************************************************** + * Icinga 2 * + * Copyright (C) 2012 Icinga Development Team (http://www.icinga.org/) * + * * + * This program is free software; you can redistribute it and/or * + * modify it under the terms of the GNU General Public License * + * as published by the Free Software Foundation; either version 2 * + * of the License, or (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the Free Software Foundation * + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. * + ******************************************************************************/ + +#include "i2-livestatus.h" + +using namespace icinga; +using namespace livestatus; + +CombinerFilter::CombinerFilter(void) +{ } + +void CombinerFilter::AddSubFilter(const Filter::Ptr& filter) +{ + m_Filters.push_back(filter); +} \ No newline at end of file diff --git a/components/livestatus/combinerfilter.h b/components/livestatus/combinerfilter.h new file mode 100644 index 000000000..0e92adeb1 --- /dev/null +++ b/components/livestatus/combinerfilter.h @@ -0,0 +1,45 @@ +/****************************************************************************** + * Icinga 2 * + * Copyright (C) 2012 Icinga Development Team (http://www.icinga.org/) * + * * + * This program is free software; you can redistribute it and/or * + * modify it under the terms of the GNU General Public License * + * as published by the Free Software Foundation; either version 2 * + * of the License, or (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the Free Software Foundation * + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. * + ******************************************************************************/ + +#ifndef COMBINERFILTER_H +#define COMBINERFILTER_H + +namespace livestatus +{ + +/** + * @ingroup livestatus + */ +class CombinerFilter : public Filter +{ +public: + typedef shared_ptr Ptr; + typedef weak_ptr WeakPtr; + + CombinerFilter(void); + + void AddSubFilter(const Filter::Ptr& filter); + +protected: + vector m_Filters; +}; + +} + +#endif /* COMBINERFILTER_H */ diff --git a/components/livestatus/filter.h b/components/livestatus/filter.h index 014653421..d60612075 100644 --- a/components/livestatus/filter.h +++ b/components/livestatus/filter.h @@ -32,7 +32,7 @@ public: typedef shared_ptr Ptr; typedef weak_ptr WeakPtr; - virtual bool Apply(const Object::Ptr& object) = 0; + virtual bool Apply(const Table::Ptr& table, const Object::Ptr& object) = 0; protected: Filter(void); diff --git a/components/livestatus/i2-livestatus.h b/components/livestatus/i2-livestatus.h index 73ebd4663..4c7a2fdb6 100644 --- a/components/livestatus/i2-livestatus.h +++ b/components/livestatus/i2-livestatus.h @@ -33,11 +33,14 @@ using namespace icinga; #include "connection.h" -#include "query.h" +#include "table.h" #include "filter.h" +#include "combinerfilter.h" #include "orfilter.h" #include "andfilter.h" -#include "table.h" +#include "negatefilter.h" +#include "attributefilter.h" +#include "query.h" #include "statustable.h" #include "contactgroupstable.h" #include "contactstable.h" diff --git a/components/livestatus/livestatus.vcxproj b/components/livestatus/livestatus.vcxproj index ff9c42e56..2e6c91f97 100644 --- a/components/livestatus/livestatus.vcxproj +++ b/components/livestatus/livestatus.vcxproj @@ -20,12 +20,15 @@ + + + @@ -33,11 +36,14 @@ + + + diff --git a/components/livestatus/livestatus.vcxproj.filters b/components/livestatus/livestatus.vcxproj.filters index 327e12117..69c5274ca 100644 --- a/components/livestatus/livestatus.vcxproj.filters +++ b/components/livestatus/livestatus.vcxproj.filters @@ -42,6 +42,15 @@ Headerdateien + + Headerdateien + + + Headerdateien + + + Headerdateien + @@ -74,5 +83,14 @@ Quelldateien + + Quelldateien + + + Quelldateien + + + Quelldateien + \ No newline at end of file diff --git a/components/livestatus/negatefilter.cpp b/components/livestatus/negatefilter.cpp new file mode 100644 index 000000000..ee02a4d09 --- /dev/null +++ b/components/livestatus/negatefilter.cpp @@ -0,0 +1,32 @@ +/****************************************************************************** + * Icinga 2 * + * Copyright (C) 2012 Icinga Development Team (http://www.icinga.org/) * + * * + * This program is free software; you can redistribute it and/or * + * modify it under the terms of the GNU General Public License * + * as published by the Free Software Foundation; either version 2 * + * of the License, or (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the Free Software Foundation * + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. * + ******************************************************************************/ + +#include "i2-livestatus.h" + +using namespace icinga; +using namespace livestatus; + +NegateFilter::NegateFilter(const Filter::Ptr& inner) + : m_Inner(inner) +{ } + +bool NegateFilter::Apply(const Table::Ptr& table, const Object::Ptr& object) +{ + return !m_Inner->Apply(table, object); +} diff --git a/components/livestatus/negatefilter.h b/components/livestatus/negatefilter.h new file mode 100644 index 000000000..f321789a9 --- /dev/null +++ b/components/livestatus/negatefilter.h @@ -0,0 +1,45 @@ +/****************************************************************************** + * Icinga 2 * + * Copyright (C) 2012 Icinga Development Team (http://www.icinga.org/) * + * * + * This program is free software; you can redistribute it and/or * + * modify it under the terms of the GNU General Public License * + * as published by the Free Software Foundation; either version 2 * + * of the License, or (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the Free Software Foundation * + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. * + ******************************************************************************/ + +#ifndef NEGATEFILTER_H +#define NEGATEFILTER_H + +namespace livestatus +{ + +/** + * @ingroup livestatus + */ +class NegateFilter : public Filter +{ +public: + typedef shared_ptr Ptr; + typedef weak_ptr WeakPtr; + + NegateFilter(const Filter::Ptr& inner); + + virtual bool Apply(const Table::Ptr& table, const Object::Ptr& object); + +private: + Filter::Ptr m_Inner; +}; + +} + +#endif /* NEGATEFILTER_H */ diff --git a/components/livestatus/orfilter.cpp b/components/livestatus/orfilter.cpp index 5989610d3..a05bdf307 100644 --- a/components/livestatus/orfilter.cpp +++ b/components/livestatus/orfilter.cpp @@ -25,20 +25,15 @@ using namespace livestatus; OrFilter::OrFilter(void) { } -bool OrFilter::Apply(const Object::Ptr& object) +bool OrFilter::Apply(const Table::Ptr& table, const Object::Ptr& object) { if (m_Filters.empty()) return true; BOOST_FOREACH(const Filter::Ptr& filter, m_Filters) { - if (filter->Apply(object)) + if (filter->Apply(table, object)) return true; } return false; } - -void OrFilter::AddSubFilter(const Filter::Ptr& filter) -{ - m_Filters.push_back(filter); -} \ No newline at end of file diff --git a/components/livestatus/orfilter.h b/components/livestatus/orfilter.h index 0433354e1..95ff502f5 100644 --- a/components/livestatus/orfilter.h +++ b/components/livestatus/orfilter.h @@ -26,7 +26,7 @@ namespace livestatus /** * @ingroup livestatus */ -class OrFilter : public Filter +class OrFilter : public CombinerFilter { public: typedef shared_ptr Ptr; @@ -34,12 +34,7 @@ public: OrFilter(void); - virtual bool Apply(const Object::Ptr& object); - - void AddSubFilter(const Filter::Ptr& filter); - -private: - vector m_Filters; + virtual bool Apply(const Table::Ptr& table, const Object::Ptr& object); }; } diff --git a/components/livestatus/query.cpp b/components/livestatus/query.cpp index 70ffa964f..8e372cde2 100644 --- a/components/livestatus/query.cpp +++ b/components/livestatus/query.cpp @@ -42,10 +42,15 @@ Query::Query(const vector& lines) } else if (m_Verb == "GET") { m_Table = target; } else { - BOOST_THROW_EXCEPTION(runtime_error("Unknown livestatus verb: " + m_Verb)); + m_Verb = "ERROR"; + m_ErrorCode = 452; + m_ErrorMessage = "Unknown livestatus verb: " + m_Verb; + return; } - for (int i = 1; i < lines.size(); i++) { + deque filters, stats; + + for (unsigned int i = 1; i < lines.size(); i++) { line = lines[i]; size_t col_index = line.FindFirstOf(":"); @@ -58,12 +63,66 @@ Query::Query(const vector& lines) m_OutputFormat = params; else if (header == "Columns") m_Columns = params.Split(is_any_of(" ")); + else if (header == "ColumnHeaders") + m_ColumnHeaders = (params == "on"); + else if (header == "Filter") { + vector tokens = params.Split(is_any_of(" ")); + + if (tokens.size() < 3) { + m_Verb = "ERROR"; + m_ErrorCode = 452; + m_ErrorMessage = "Expected 3 parameters in the filter specification."; + return; + } + + String op = tokens[1]; + bool negate = false; + + if (op == "!=") { + op = "="; + negate = true; + } else if (op == "!~") { + op = "~"; + negate = true; + } else if (op == "!=~") { + op = "=~"; + negate = true; + } else if (op == "!~~") { + op = "~~"; + negate = true; + } + + Filter::Ptr filter = boost::make_shared(tokens[0], op, tokens[2]); + + if (negate) + filter = boost::make_shared(filter); + + filters.push_back(filter); + } else if (header == "Or" || header == "And") { + int num = Convert::ToLong(params); + CombinerFilter::Ptr filter; + + if (header == "Or") + filter = boost::make_shared(); + else + filter = boost::make_shared(); + + while (!filters.empty() && num--) { + filter->AddSubFilter(filters.back()); + filters.pop_back(); + } + + filters.push_back(filter); + } } + + m_Filters.swap(filters); + m_Stats.swap(stats); } void Query::PrintResultSet(ostream& fp, const vector& columns, const Array::Ptr& rs) { - if (m_OutputFormat == "csv" && m_Columns.size() == 0) { + if (m_OutputFormat == "csv" && m_Columns.size() == 0 && m_ColumnHeaders) { bool first = true; BOOST_FOREACH(const String& column, columns) { @@ -113,7 +172,15 @@ void Query::ExecuteGetHelper(const Stream::Ptr& stream) return; } - vector objects = table->FilterRows(Filter::Ptr()); + if (m_Filters.size() > 1) + SendResponse(stream, 452, "There must not be more than one top-level filter expression."); + + Filter::Ptr filter; + + if (!m_Filters.empty()) + filter = m_Filters[0]; + + vector objects = table->FilterRows(filter); vector columns; if (m_Columns.size() > 0) @@ -149,13 +216,9 @@ void Query::ExecuteGetHelper(const Stream::Ptr& stream) void Query::ExecuteCommandHelper(const Stream::Ptr& stream) { - try { - Logger::Write(LogInformation, "livestatus", "Executing command: " + m_Command); - ExternalCommandProcessor::Execute(m_Command); - SendResponse(stream, 200, ""); - } catch (const std::exception& ex) { - SendResponse(stream, 452, diagnostic_information(ex)); - } + Logger::Write(LogInformation, "livestatus", "Executing command: " + m_Command); + ExternalCommandProcessor::Execute(m_Command); + SendResponse(stream, 200, ""); } void Query::ExecuteErrorHelper(const Stream::Ptr& stream) @@ -185,6 +248,7 @@ void Query::PrintFixed16(const Stream::Ptr& stream, int code, const String& data void Query::Execute(const Stream::Ptr& stream) { + try { Logger::Write(LogInformation, "livestatus", "Executing livestatus query: " + m_Verb); if (m_Verb == "GET") @@ -195,6 +259,9 @@ void Query::Execute(const Stream::Ptr& stream) ExecuteErrorHelper(stream); else BOOST_THROW_EXCEPTION(runtime_error("Invalid livestatus query verb.")); + } catch (const std::exception& ex) { + SendResponse(stream, 452, boost::diagnostic_information(ex)); + } if (!m_KeepAlive) stream->Close(); diff --git a/components/livestatus/query.h b/components/livestatus/query.h index 940a80884..247812632 100644 --- a/components/livestatus/query.h +++ b/components/livestatus/query.h @@ -45,6 +45,9 @@ private: String m_Table; vector m_Columns; + deque m_Filters; + deque m_Stats; + String m_OutputFormat; bool m_ColumnHeaders; int m_Limit; diff --git a/components/livestatus/table.cpp b/components/livestatus/table.cpp index 518c9c9ca..6fd00ab9e 100644 --- a/components/livestatus/table.cpp +++ b/components/livestatus/table.cpp @@ -68,14 +68,14 @@ vector Table::FilterRows(const Filter::Ptr& filter) { vector rs; - FetchRows(boost::bind(&Table::FilteredAddRow, boost::ref(rs), filter, _1)); + FetchRows(boost::bind(&Table::FilteredAddRow, this, boost::ref(rs), filter, _1)); return rs; } void Table::FilteredAddRow(vector& rs, const Filter::Ptr& filter, const Object::Ptr& object) { - if (!filter || filter->Apply(object)) + if (!filter || filter->Apply(GetSelf(), object)) rs.push_back(object); } diff --git a/components/livestatus/table.h b/components/livestatus/table.h index 82a9f9ce5..3f7b0cca7 100644 --- a/components/livestatus/table.h +++ b/components/livestatus/table.h @@ -23,6 +23,8 @@ namespace livestatus { +class Filter; + /** * @ingroup livestatus */ @@ -38,7 +40,7 @@ public: virtual String GetName(void) const = 0; - vector FilterRows(const Filter::Ptr& filter); + vector FilterRows(const shared_ptr& filter); ColumnAccessor GetColumn(const String& name) const; vector GetColumnNames(void) const; @@ -59,7 +61,7 @@ protected: private: map m_Columns; - static void FilteredAddRow(vector& rs, const Filter::Ptr& filter, const Object::Ptr& object); + void FilteredAddRow(vector& rs, const shared_ptr& filter, const Object::Ptr& object); }; } diff --git a/lib/base/qstring.cpp b/lib/base/qstring.cpp index e87846086..883fe9f5c 100644 --- a/lib/base/qstring.cpp +++ b/lib/base/qstring.cpp @@ -212,6 +212,61 @@ bool icinga::operator==(const char *lhs, const String& rhs) return lhs == static_cast(rhs); } +bool icinga::operator<(const String& lhs, const char *rhs) +{ + return static_cast(lhs) < rhs; +} + +bool icinga::operator<(const char *lhs, const String& rhs) +{ + return lhs < static_cast(rhs); +} + +bool icinga::operator>(const String& lhs, const String& rhs) +{ + return static_cast(lhs) > static_cast(rhs); +} + +bool icinga::operator>(const String& lhs, const char *rhs) +{ + return static_cast(lhs) > rhs; +} + +bool icinga::operator>(const char *lhs, const String& rhs) +{ + return lhs > static_cast(rhs); +} + +bool icinga::operator<=(const String& lhs, const String& rhs) +{ + return static_cast(lhs) <= static_cast(rhs); +} + +bool icinga::operator<=(const String& lhs, const char *rhs) +{ + return static_cast(lhs) <= rhs; +} + +bool icinga::operator<=(const char *lhs, const String& rhs) +{ + return lhs <= static_cast(rhs); +} + +bool icinga::operator>=(const String& lhs, const String& rhs) +{ + return static_cast(lhs) >= static_cast(rhs); +} + +bool icinga::operator>=(const String& lhs, const char *rhs) +{ + return static_cast(lhs) >= rhs; +} + +bool icinga::operator>=(const char *lhs, const String& rhs) +{ + return lhs >= static_cast(rhs); +} + bool icinga::operator!=(const String& lhs, const String& rhs) { return static_cast(lhs) != static_cast(rhs); @@ -227,26 +282,6 @@ bool icinga::operator!=(const char *lhs, const String& rhs) return lhs != static_cast(rhs); } -bool icinga::operator<(const String& lhs, const char *rhs) -{ - return static_cast(lhs) < rhs; -} - -bool icinga::operator<(const char *lhs, const String& rhs) -{ - return lhs < static_cast(rhs); -} - -bool icinga::operator>(const String& lhs, const char *rhs) -{ - return static_cast(lhs) > rhs; -} - -bool icinga::operator>(const char *lhs, const String& rhs) -{ - return lhs > static_cast(rhs); -} - String::Iterator icinga::range_begin(String& x) { return x.Begin(); diff --git a/lib/base/qstring.h b/lib/base/qstring.h index 4465a2104..2afd61804 100644 --- a/lib/base/qstring.h +++ b/lib/base/qstring.h @@ -122,9 +122,19 @@ I2_BASE_API bool operator!=(const char *lhs, const String& rhs); I2_BASE_API bool operator<(const String& lhs, const char *rhs); I2_BASE_API bool operator<(const char *lhs, const String& rhs); + +I2_BASE_API bool operator>(const String& lhs, const String& rhs); I2_BASE_API bool operator>(const String& lhs, const char *rhs); I2_BASE_API bool operator>(const char *lhs, const String& rhs); +I2_BASE_API bool operator<=(const String& lhs, const String& rhs); +I2_BASE_API bool operator<=(const String& lhs, const char *rhs); +I2_BASE_API bool operator<=(const char *lhs, const String& rhs); + +I2_BASE_API bool operator>=(const String& lhs, const String& rhs); +I2_BASE_API bool operator>=(const String& lhs, const char *rhs); +I2_BASE_API bool operator>=(const char *lhs, const String& rhs); + I2_BASE_API String::Iterator range_begin(String& x); I2_BASE_API String::ConstIterator range_begin(const String& x); I2_BASE_API String::Iterator range_end(String& x);