<commit_before>/*
 * getopt.hpp
 *  base classes to handle options that is specified as the command line
 *  parameters
 *
 *  written by janus_wel<janus.wel.3@gmail.com>
 *  This source code is in public domain, and has NO WARRANTY.
 * */

#ifndef GETOPT_HPP
#define GETOPT_HPP

#include "cor.hpp"

#include <stdexcept>
#include <string>
#include <vector>

namespace util {
    namespace getopt {
        /*
         *  a class to refer the parameters
         *  getters
         *      current()   returns the const_iterator that points the
         *                  parameter to be processed at that time.
         *      begin()     returns the const_iterator that points the start of
         *                  the array of parameters.
         *      end()       returns the const_iterator that points the end of
         *                  the array of parameters.
         *      operator()  returns array itself.
         *
         *  And this class has the member function advance(1) to change current
         *  subject forward, but this is called by the class basic_getopt
         *  automatically, so don't call this manually.
         *  */
        template<typename charT> class basic_parameters {
            public:
                typedef charT                                   char_t;
                typedef std::basic_string<char_t>               string_t;
                typedef std::vector<string_t>                   string_array_t;
                typedef typename string_array_t::const_iterator const_iterator;

            private:
                const string_array_t* mv_array;
                const_iterator mv_current;

            public:
                // constructor
                basic_parameters(string_array_t& array)
                    : mv_array(&array), mv_current(array.begin()) {}
                basic_parameters(string_array_t* array)
                    : mv_array(array), mv_current(array->begin()) {}

                // getters
                const const_iterator& current(void) const { return mv_current; }
                const const_iterator begin(void) const { return mv_array->begin(); }
                const const_iterator end(void) const { return mv_array->end(); }
                const string_array_t& operator()(void) const { return *mv_array; }

                // positioning
                void advance(unsigned int n) { std::advance(mv_current, n); }
        };

        /*
         *  classes to represent option's traits
         *  For Microsoft environment, you can define the new trait that has
         *  the prefix "/".
         * */
        template<typename charT> struct option_traits;
        template<> struct option_traits<char> {
            typedef char char_t;
            struct shortname {
                static const char_t* prefix(void) { return "-"; }
                static const unsigned int prefix_length = 1;
            };
            struct longname {
                static const char_t* prefix(void) { return "--"; }
                static const unsigned int prefix_length = 2;
            };
        };
        template<> struct option_traits<wchar_t> {
            typedef wchar_t char_t;
            struct shortname {
                static const char_t* prefix(void) { return L"-"; }
                static const unsigned int prefix_length = 1;
            };
            struct longname {
                static const char_t* prefix(void) { return L"--"; }
                static const unsigned int prefix_length = 2;
            };
        };

        /*
         *  a class to handle parameters as option name and its values
         *  A derived class from this processes a option.
         *  To use:
         *
         *      1. Define a class or struct that is derived from this class.
         *      2. Override the following member functions
         *
         *          - shortname(void) and/or longname(void)
         *              - return option names. shortname() should return one
         *                character as a matter of principle.
         *              - Overriding the only one of two functions is OK.
         *          - handle_params(const parameters_t&)
         *              - handles the current parameter (or more parameters).
         *              - This member function must return a number of
         *                processed parameters. e.g.: the option class that
         *                handles "-v" means "show version information" will
         *                eat up "-v" itself and return 1, the option class
         *                that handles "-s <size>" means "set size to <size>"
         *                will eat up "-v" and "<size>", and return 2.
         * */
        template<typename charT, typename traitsT = option_traits<charT> >
        class basic_option
            : public pattern::cor::basic_handler<unsigned int, basic_parameters<charT> > {
            public:
                typedef charT                       char_t;
                typedef traitsT                     traits_t;
                typedef std::basic_string<char_t>   string_t;
                typedef unsigned int                return_t;
                typedef basic_parameters<char_t>    parameters_t;

            protected:
                typedef typename traits_t::longname     longname_traits_t;
                typedef typename traits_t::shortname    shortname_traits_t;

            protected:
                // member functions to be overridden
                virtual const char_t* shortname(void) const { return NULL; }
                virtual const char_t* longname(void) const { return NULL; }
                virtual return_t handle_params(const parameters_t&) = 0;

            public:
                // typical destructor
                ~basic_option(void) {}

            public:
                // implementations for the virtual member functions of the
                // super class
                bool is_in_charge(const parameters_t& params) const {
                    const string_t& current = *(params.current());
                    if (
                               (
                                is_opt<longname_traits_t>(current)
                             && is_known<longname_traits_t>(current, longname()))
                            || (
                                is_opt<shortname_traits_t>(current)
                             && is_known<shortname_traits_t>(current, shortname()))) {
                        return true;
                    }
                    return false;
                }

                // just delegate
                unsigned int handle_responsibility(const parameters_t& params) {
                    return handle_params(params);
                }

            protected:
                // utilities
                template<typename trT>
                static bool is_opt(const string_t& current) {
                    return current.compare(
                                0,
                                trT::prefix_length,
                                trT::prefix()) == 0;
                }

                template<typename trT>
                static bool is_known(const string_t& current, const char_t* name) {
                    return (
                               name != NULL
                            && current.compare(
                                trT::prefix_length,
                                current.size() - 1,
                                name) == 0);
                }

            public:
                static bool has_opt_prefix(const string_t& current) {
                    return (
                               is_opt<longname_traits_t>(current)
                            || is_opt<shortname_traits_t>(current));
                }
        };

        /*
         *  a class to analyze options
         *  To use:
         *
         *      1. Define a class or struct that is derived from this class.
         *      2. Override the following member functions
         *
         *          - handle_nonopt(const parameters_t&, bool)
         *              - handles non-option parameters.
         *              - The second parameter whose type is bool represents
         *                whether the "current" parameter is unknown option or
         *                not. If it has the option prefix this value is true,
         *                otherwise false.
         *
         *      3. Define some classes that is derived from the class
         *         basic_option.
         *      4. Build the objects of the class that is refered in to step. 1
         *         and 3, and register the subclasses's objects of the class
         *         basic_option on the subclass's object of this class by using
         *         the member function register_option().
         *      5. Call the member function analyze() with an object of
         *         std::vector<string_t> that has parameters.
         * */
        template<typename charT>
        class basic_getopt
            : public pattern::cor::basic_chain<unsigned int, basic_parameters<charT> > {
            public:
                typedef charT                       char_t;
                typedef std::basic_string<char_t>   string_t;
                typedef unsigned int                return_t;
                typedef basic_parameters<char_t>    parameters_t;
                typedef basic_option<char_t>        option_t;
                typedef std::vector<string_t>       string_array_t;

            protected:
                typedef basic_getopt    this_t;

            protected:
                // member functions to be overridden
                virtual unsigned int handle_nonopt(const parameters_t&, bool) = 0;

            public:
                // typical destructor
                ~basic_getopt(void) {}

            protected:
                // implementations for the virtual member functions of the
                // super class
                unsigned int at_end_of_chain(const parameters_t& params) {
                    const string_t& current = *(params.current());
                    bool is_unknown_opt = option_t::has_opt_prefix(current)
                        ? true
                        : false;
                    return handle_nonopt(params, is_unknown_opt);
                }

            public:
                // utilities
                this_t& register_option(option_t& option) {
                    enlink_chain(option);
                    return *this;
                }

                this_t& register_option(option_t* option) {
                    enlink_chain(option);
                    return *this;
                }

                // main function
                unsigned int analyze(string_array_t& data) {
                    parameters_t params(data);
                    unsigned int processed = 0;
                    while (params.current() != params.end()) {
                        unsigned int n = request_to_chain(params);
                        if (n == 0)
                            throw std::logic_error("the function basic_option::handle_params() or basic_getopt::handle_nonopt() must return a non-zero value.");
                        params.advance(n);
                        processed += n;
                    }
                    return processed;
                }

                unsigned int analyze(const int argc, const char_t* const argv[]) {
                    string_array_t data;
                    data.reserve(argc);
                    for (int i = 1; i < argc; ++i) data.push_back(argv[i]);
                    return analyze(data);
                }
        };

        // for convenience
        typedef basic_parameters<char>      parameters;
        typedef basic_option<char>          option;
        typedef basic_getopt<char>          getopt;
        typedef basic_parameters<wchar_t>   wparameters;
        typedef basic_option<wchar_t>       woption;
        typedef basic_getopt<wchar_t>       wgetopt;
    }
}

#endif // GETOPT_HPP

<commit_msg>Use assert()<commit_after>/*
 * getopt.hpp
 *  base classes to handle options that is specified as the command line
 *  parameters
 *
 *  written by janus_wel<janus.wel.3@gmail.com>
 *  This source code is in public domain, and has NO WARRANTY.
 * */

#ifndef GETOPT_HPP
#define GETOPT_HPP

#include "cor.hpp"

#include <cassert>
#include <stdexcept>
#include <string>
#include <vector>

namespace util {
    namespace getopt {
        /*
         *  a class to refer the parameters
         *  getters
         *      current()   returns the const_iterator that points the
         *                  parameter to be processed at that time.
         *      begin()     returns the const_iterator that points the start of
         *                  the array of parameters.
         *      end()       returns the const_iterator that points the end of
         *                  the array of parameters.
         *      operator()  returns array itself.
         *
         *  And this class has the member function advance(1) to change current
         *  subject forward, but this is called by the class basic_getopt
         *  automatically, so don't call this manually.
         *  */
        template<typename charT> class basic_parameters {
            public:
                typedef charT                                   char_t;
                typedef std::basic_string<char_t>               string_t;
                typedef std::vector<string_t>                   string_array_t;
                typedef typename string_array_t::const_iterator const_iterator;

            private:
                const string_array_t* mv_array;
                const_iterator mv_current;

            public:
                // constructor
                basic_parameters(string_array_t& array)
                    : mv_array(&array), mv_current(array.begin()) {}
                basic_parameters(string_array_t* array)
                    : mv_array(array), mv_current(array->begin()) {}

                // getters
                const const_iterator& current(void) const { return mv_current; }
                const const_iterator begin(void) const { return mv_array->begin(); }
                const const_iterator end(void) const { return mv_array->end(); }
                const string_array_t& operator()(void) const { return *mv_array; }

                // positioning
                void advance(unsigned int n) { std::advance(mv_current, n); }
        };

        /*
         *  classes to represent option's traits
         *  For Microsoft environment, you can define the new trait that has
         *  the prefix "/".
         * */
        template<typename charT> struct option_traits;
        template<> struct option_traits<char> {
            typedef char char_t;
            struct shortname {
                static const char_t* prefix(void) { return "-"; }
                static const unsigned int prefix_length = 1;
            };
            struct longname {
                static const char_t* prefix(void) { return "--"; }
                static const unsigned int prefix_length = 2;
            };
        };
        template<> struct option_traits<wchar_t> {
            typedef wchar_t char_t;
            struct shortname {
                static const char_t* prefix(void) { return L"-"; }
                static const unsigned int prefix_length = 1;
            };
            struct longname {
                static const char_t* prefix(void) { return L"--"; }
                static const unsigned int prefix_length = 2;
            };
        };

        /*
         *  a class to handle parameters as option name and its values
         *  A derived class from this processes a option.
         *  To use:
         *
         *      1. Define a class or struct that is derived from this class.
         *      2. Override the following member functions
         *
         *          - shortname(void) and/or longname(void)
         *              - return option names. shortname() should return one
         *                character as a matter of principle.
         *              - Overriding the only one of two functions is OK.
         *          - handle_params(const parameters_t&)
         *              - handles the current parameter (or more parameters).
         *              - This member function must return a number of
         *                processed parameters. e.g.: the option class that
         *                handles "-v" means "show version information" will
         *                eat up "-v" itself and return 1, the option class
         *                that handles "-s <size>" means "set size to <size>"
         *                will eat up "-v" and "<size>", and return 2.
         * */
        template<typename charT, typename traitsT = option_traits<charT> >
        class basic_option
            : public pattern::cor::basic_handler<unsigned int, basic_parameters<charT> > {
            public:
                typedef charT                       char_t;
                typedef traitsT                     traits_t;
                typedef std::basic_string<char_t>   string_t;
                typedef unsigned int                return_t;
                typedef basic_parameters<char_t>    parameters_t;

            protected:
                typedef typename traits_t::longname     longname_traits_t;
                typedef typename traits_t::shortname    shortname_traits_t;

            protected:
                // member functions to be overridden
                virtual const char_t* shortname(void) const { return NULL; }
                virtual const char_t* longname(void) const { return NULL; }
                virtual return_t handle_params(const parameters_t&) = 0;

            public:
                // typical destructor
                ~basic_option(void) {}

            public:
                // implementations for the virtual member functions of the
                // super class
                bool is_in_charge(const parameters_t& params) const {
                    const string_t& current = *(params.current());
                    if (
                               (
                                is_opt<longname_traits_t>(current)
                             && is_known<longname_traits_t>(current, longname()))
                            || (
                                is_opt<shortname_traits_t>(current)
                             && is_known<shortname_traits_t>(current, shortname()))) {
                        return true;
                    }
                    return false;
                }

                // just delegate
                unsigned int handle_responsibility(const parameters_t& params) {
                    return handle_params(params);
                }

            protected:
                // utilities
                template<typename trT>
                static bool is_opt(const string_t& current) {
                    return current.compare(
                                0,
                                trT::prefix_length,
                                trT::prefix()) == 0;
                }

                template<typename trT>
                static bool is_known(const string_t& current, const char_t* name) {
                    return (
                               name != NULL
                            && current.compare(
                                trT::prefix_length,
                                current.size() - 1,
                                name) == 0);
                }

            public:
                static bool has_opt_prefix(const string_t& current) {
                    return (
                               is_opt<longname_traits_t>(current)
                            || is_opt<shortname_traits_t>(current));
                }
        };

        /*
         *  a class to analyze options
         *  To use:
         *
         *      1. Define a class or struct that is derived from this class.
         *      2. Override the following member functions
         *
         *          - handle_nonopt(const parameters_t&, bool)
         *              - handles non-option parameters.
         *              - The second parameter whose type is bool represents
         *                whether the "current" parameter is unknown option or
         *                not. If it has the option prefix this value is true,
         *                otherwise false.
         *
         *      3. Define some classes that is derived from the class
         *         basic_option.
         *      4. Build the objects of the class that is refered in to step. 1
         *         and 3, and register the subclasses's objects of the class
         *         basic_option on the subclass's object of this class by using
         *         the member function register_option().
         *      5. Call the member function analyze() with an object of
         *         std::vector<string_t> that has parameters.
         * */
        template<typename charT>
        class basic_getopt
            : public pattern::cor::basic_chain<unsigned int, basic_parameters<charT> > {
            public:
                typedef charT                       char_t;
                typedef std::basic_string<char_t>   string_t;
                typedef unsigned int                return_t;
                typedef basic_parameters<char_t>    parameters_t;
                typedef basic_option<char_t>        option_t;
                typedef std::vector<string_t>       string_array_t;

            protected:
                typedef basic_getopt    this_t;

            protected:
                // member functions to be overridden
                virtual unsigned int handle_nonopt(const parameters_t&, bool) = 0;

            public:
                // typical destructor
                ~basic_getopt(void) {}

            protected:
                // implementations for the virtual member functions of the
                // super class
                unsigned int at_end_of_chain(const parameters_t& params) {
                    const string_t& current = *(params.current());
                    bool is_unknown_opt = option_t::has_opt_prefix(current)
                        ? true
                        : false;
                    return handle_nonopt(params, is_unknown_opt);
                }

            public:
                // utilities
                this_t& register_option(option_t& option) {
                    enlink_chain(option);
                    return *this;
                }

                this_t& register_option(option_t* option) {
                    enlink_chain(option);
                    return *this;
                }

                // main function
                unsigned int analyze(string_array_t& data) {
                    parameters_t params(data);
                    unsigned int processed = 0;
                    while (params.current() != params.end()) {
                        unsigned int n = request_to_chain(params);
                        assert(n != 0);
                        params.advance(n);
                        processed += n;
                    }
                    return processed;
                }

                unsigned int analyze(const int argc, const char_t* const argv[]) {
                    string_array_t data;
                    data.reserve(argc);
                    for (int i = 1; i < argc; ++i) data.push_back(argv[i]);
                    return analyze(data);
                }
        };

        // for convenience
        typedef basic_parameters<char>      parameters;
        typedef basic_option<char>          option;
        typedef basic_getopt<char>          getopt;
        typedef basic_parameters<wchar_t>   wparameters;
        typedef basic_option<wchar_t>       woption;
        typedef basic_getopt<wchar_t>       wgetopt;
    }
}

#endif // GETOPT_HPP

<|endoftext|>


<commit_before>/*
 * This file is part of Clockwork.
 *
 * Copyright (c) 2014-2016 Jeremy Othieno.
 *
 * The MIT License (MIT)
 * 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.
 */
#ifndef CLOCKWORK_WEAK_VARIANT_HH
#define CLOCKWORK_WEAK_VARIANT_HH

#include <type_traits>

namespace clockwork {
/**
 * Checks whether Type is a valid reference type.
 * This generic implementation always returns true.
 */
template<class Type>
struct GenericWeakVariantValidator : std::integral_constant<bool, true> {};
/**
 * A WeakVariant is a data type, based on a variant, that contains a non-owning
 * reference to any kind of object.
 */
template<template<typename> class Validator = GenericWeakVariantValidator>
class WeakVariant {
public:
	/**
	 * Returns the referenced value as a specified type.
	 */
	template<class Type> Type& as();
	/**
	 * Returns the referenced value as a specified type.
	 */
	template<class Type> const Type& as() const;
	/**
	 * Instantiates a WeakVariant object that references the specified value.
	 * @param value the referenced value.
	 */
	template<class Type> static WeakVariant<Validator> create(Type& value);
private:
	/**
	 * Instantiates a WeakVariant object to the specified value.
	 * @param the referenced value.
	 */
	inline explicit WeakVariant(void* const value);
	/**
	 * Instantiates a WeakVariant object to the specified immutable value.
	 * @param the referenced value.
	 */
	inline explicit WeakVariant(const void* const value);
	/**
	 * The referenced value.
	 */
	union Reference {
		/**
		 * Instantiates a Reference object that references a specified object.
		 */
		inline explicit Reference(void* const value);
		/**
		 * Instantiates a Reference object that references a specified immutable object.
		 */
		inline explicit Reference(const void* const value);
		/**
		 * A pointer to a mutable value.
		 */
		void* value;
		/**
		 * A pointer to an immutable value.
		 */
		const void* const_value;
	} reference_;
};

template<template<typename> class Validator>
WeakVariant<Validator>::WeakVariant(void* const value) :
reference_(value) {}

template<template<typename> class Validator>
WeakVariant<Validator>::WeakVariant(const void* const value) :
reference_(value) {}

template<template<typename> class Validator>
WeakVariant<Validator>::Reference::Reference(void* const v) :
value(v) {}

template<template<typename> class Validator>
WeakVariant<Validator>::Reference::Reference(const void* const v) :
const_value(v) {}

template<template<typename> class Validator>
template<class T> T&
WeakVariant<Validator>::as() {
	static_assert(Validator<T>::value);
	return *static_cast<T*>(reference_.value);
}

template<template<typename> class Validator>
template<class T> const T&
WeakVariant<Validator>::as() const {
	static_assert(Validator<T>::value);
	return *static_cast<const T*>(reference_.const_value);
}

template<template<typename> class Validator>
template<class T> WeakVariant<Validator>
WeakVariant<Validator>::create(T& value) {
	static_assert(Validator<T>::value);
	return WeakVariant<Validator>(&value);
}
} // namespace clockwork

#endif // CLOCKWORK_WEAK_VARIANT_HH
<commit_msg>Add a default constructor to the WeakVariant class<commit_after>/*
 * This file is part of Clockwork.
 *
 * Copyright (c) 2014-2016 Jeremy Othieno.
 *
 * The MIT License (MIT)
 * 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.
 */
#ifndef CLOCKWORK_WEAK_VARIANT_HH
#define CLOCKWORK_WEAK_VARIANT_HH

#include <type_traits>

namespace clockwork {
/**
 * Checks whether Type is a valid reference type.
 * This generic implementation always returns true.
 */
template<class Type>
struct GenericWeakVariantValidator : std::integral_constant<bool, true> {};
/**
 * A WeakVariant is a data type, based on a variant, that contains a non-owning
 * reference to any kind of object.
 */
template<template<typename> class Validator = GenericWeakVariantValidator>
class WeakVariant {
public:
	/**
	 * Instantiates an invalid WeakVariant object.
	 * This is necessary for data structures that require a default constructor.
	 */
	WeakVariant();
	/**
	 * Returns true if the WeakVariant is valid, false otherwise. A WeakVariant
	 * is considered valid if, and only if, it references an object.
	 */
	bool isValid() const;
	/**
	 * Returns the referenced value as a specified type.
	 */
	template<class Type> Type& as();
	/**
	 * Returns the referenced value as a specified type.
	 */
	template<class Type> const Type& as() const;
	/**
	 * Instantiates a WeakVariant object that references the specified value.
	 * @param value the referenced value.
	 */
	template<class Type> static WeakVariant<Validator> create(Type& value);
private:
	/**
	 * Instantiates a WeakVariant object to the specified value.
	 * @param the referenced value.
	 */
	inline explicit WeakVariant(void* const value);
	/**
	 * Instantiates a WeakVariant object to the specified immutable value.
	 * @param the referenced value.
	 */
	inline explicit WeakVariant(const void* const value);
	/**
	 * The referenced value.
	 */
	union Reference {
		/**
		 * Instantiates a Reference object that does not reference any object.
		 */
		inline explicit Reference(std::nullptr_t);
		/**
		 * Instantiates a Reference object that references a specified object.
		 */
		inline explicit Reference(void* const value);
		/**
		 * Instantiates a Reference object that references a specified immutable object.
		 */
		inline explicit Reference(const void* const value);
		/**
		 * A pointer to a mutable value.
		 */
		void* value;
		/**
		 * A pointer to an immutable value.
		 */
		const void* const_value;
	} reference_;
};

template<template<typename> class Validator>
WeakVariant<Validator>::WeakVariant() :
reference_(nullptr) {}

template<template<typename> class Validator>
WeakVariant<Validator>::WeakVariant(void* const value) :
reference_(value) {}

template<template<typename> class Validator>
WeakVariant<Validator>::WeakVariant(const void* const value) :
reference_(value) {}

template<template<typename> class Validator>
WeakVariant<Validator>::Reference::Reference(std::nullptr_t) :
value(nullptr) {}

template<template<typename> class Validator>
WeakVariant<Validator>::Reference::Reference(void* const v) :
value(v) {}

template<template<typename> class Validator>
WeakVariant<Validator>::Reference::Reference(const void* const v) :
const_value(v) {}

template<template<typename> class Validator>
bool
WeakVariant<Validator>::isValid() const {
	return reference_.const_value != nullptr;
}

template<template<typename> class Validator>
template<class T> T&
WeakVariant<Validator>::as() {
	static_assert(Validator<T>::value);
	return *static_cast<T*>(reference_.value);
}

template<template<typename> class Validator>
template<class T> const T&
WeakVariant<Validator>::as() const {
	static_assert(Validator<T>::value);
	return *static_cast<const T*>(reference_.const_value);
}

template<template<typename> class Validator>
template<class T> WeakVariant<Validator>
WeakVariant<Validator>::create(T& value) {
	static_assert(Validator<T>::value);
	return WeakVariant<Validator>(&value);
}
} // namespace clockwork

#endif // CLOCKWORK_WEAK_VARIANT_HH
<|endoftext|>


<commit_before>//  (C) Copyright Gennadiy Rozental 2001.
//  Permission to copy, use, modify, sell and distribute this software
//  is granted provided this copyright notice appears in all copies.
//  This software is provided "as is" without express or implied warranty,
//  and with no claim as to its suitability for any purpose.
//
//  See http://www.boost.org for most recent version including documentation.

// LOCAL
#include <boost/test/unit_test_result.hpp>
#include <boost/test/unit_test_suite.hpp>

// BOOST
#include <boost/config.hpp>
#include <boost/scoped_ptr.hpp>

// STL
#include <list>
#include <algorithm>
#include <cassert>
#include <iostream>
#include <iomanip>
#include <cmath>

# ifdef BOOST_NO_STDC_NAMESPACE
namespace std { using ::log10; using ::strncmp; }
# endif

namespace boost {

namespace unit_test_framework {

// ************************************************************************** //
// **************               unit_test_result               ************** //
// ************************************************************************** //

struct unit_test_result::Impl {
    unit_test_result*               m_parent;
    std::list<unit_test_result*>    m_children;
    unit_test_counter               m_assertions_passed;
    unit_test_counter               m_assertions_failed;
    unit_test_counter               m_expected_failures;
    unit_test_counter               m_test_cases_passed;
    unit_test_counter               m_test_cases_failed;
    bool                            m_exception_caught;
    char const*                     m_test_case_name;

    static boost::scoped_ptr<unit_test_result> m_head;
    static unit_test_result*        m_curr;

    bool                            is_failed()   { return m_assertions_failed != m_expected_failures || m_exception_caught; }
    unit_test_counter               result_code() { return is_failed()
                                                        ? ( (m_assertions_failed != 0) ? m_assertions_failed : -1 )
                                                        : 0; }
};

boost::scoped_ptr<unit_test_result> unit_test_result::Impl::m_head;
unit_test_result* unit_test_result::Impl::m_curr = NULL;

//____________________________________________________________________________//

unit_test_result::unit_test_result( unit_test_result* parent, char const* test_case_name, unit_test_counter exp_fail )
: m_pimpl( new Impl )
{
    m_pimpl->m_parent            = parent;
    m_pimpl->m_test_case_name    = test_case_name;

    m_pimpl->m_assertions_passed = 0;
    m_pimpl->m_assertions_failed = 0;
    m_pimpl->m_expected_failures = exp_fail;
    m_pimpl->m_test_cases_passed = 0;
    m_pimpl->m_test_cases_failed = 0;
    m_pimpl->m_exception_caught  = false;

}

//____________________________________________________________________________//

static void safe_delete( unit_test_result* ptr ) { boost::checked_delete<unit_test_result>( ptr ); }

unit_test_result::~unit_test_result()
{
    std::for_each( m_pimpl->m_children.begin(), m_pimpl->m_children.end(), &safe_delete );
}

//____________________________________________________________________________//

unit_test_result&
unit_test_result::instance()
{
    assert( Impl::m_head.get() != NULL );

    return Impl::m_curr == NULL ? *Impl::m_head : *Impl::m_curr;
}

//____________________________________________________________________________//

void
unit_test_result::test_case_start( char const* name, unit_test_counter expected_failures )
{
    unit_test_result* new_result_set = new unit_test_result( Impl::m_curr, name, expected_failures );

    if( Impl::m_curr == NULL ) {
        Impl::m_head.reset( new_result_set );
    }
    else
        Impl::m_curr->m_pimpl->m_children.push_back( new_result_set );

    Impl::m_curr = new_result_set;
}

//____________________________________________________________________________//

void
unit_test_result::test_case_end()
{
    assert( Impl::m_curr != NULL );

    Impl*             curr_impl = Impl::m_curr->m_pimpl.get();
    unit_test_result* parent    = curr_impl->m_parent;

    if( parent != NULL ) {
        // accumulate results
        parent->m_pimpl->m_assertions_passed += curr_impl->m_assertions_passed;
        parent->m_pimpl->m_assertions_failed += curr_impl->m_assertions_failed;
        parent->m_pimpl->m_test_cases_passed += curr_impl->m_test_cases_passed;
        parent->m_pimpl->m_test_cases_failed += curr_impl->m_test_cases_failed;

        // for test_cases (vs. test_suite)
        if( curr_impl->m_test_cases_passed == 0 && curr_impl->m_test_cases_failed == 0 ) {
            if( curr_impl->is_failed() )
                parent->m_pimpl->m_test_cases_failed++;
            else
                parent->m_pimpl->m_test_cases_passed++;
        }

    }

    Impl::m_curr = parent;
}

//____________________________________________________________________________//

void
unit_test_result::increase_expected_failures( unit_test_counter amount )
{
    m_pimpl->m_expected_failures += amount;

    if( m_pimpl->m_parent != NULL )
        m_pimpl->m_parent->increase_expected_failures( amount );
}

//____________________________________________________________________________//

void
unit_test_result::inc_failed_assertions()
{
    m_pimpl->m_assertions_failed++;
}

//____________________________________________________________________________//

void
unit_test_result::inc_passed_assertions()
{
    m_pimpl->m_assertions_passed++;
}

//____________________________________________________________________________//

void
unit_test_result::caught_exception()
{
    m_pimpl->m_exception_caught = true;
}

//____________________________________________________________________________//

char const*
unit_test_result::test_case_name()
{
    return m_pimpl->m_test_case_name;
}

//____________________________________________________________________________//

namespace {
std::string ps_name( bool p_s, char const* singular_form )  { return p_s ? std::string( singular_form ).append( "s" ) : singular_form; }
std::string cs_name( bool c_s )                             { return c_s ? "case" : "suite"; }
std::string quote( char const* name )                       { return std::string( " \"" ).append( name ).append( "\" "); }
}

//____________________________________________________________________________//

void
unit_test_result::confirmation_report( std::ostream& where_to )
{
    assert( this != NULL );

    bool failed     = m_pimpl->m_test_cases_failed != 0 || m_pimpl->is_failed();
    bool case_suite = m_pimpl->m_test_cases_failed + m_pimpl->m_test_cases_passed <= 1;

    if( failed ) {
        if( m_pimpl->m_assertions_failed > 0 )
            where_to << "\n*** " << m_pimpl->m_assertions_failed
                     << ps_name( m_pimpl->m_assertions_failed != 1, " Failure" )
                     << " in test " << cs_name( case_suite )
                     << quote( m_pimpl->m_test_case_name );
        if( m_pimpl->m_exception_caught )
            where_to << "\n*** Test " << cs_name( case_suite )
                     << quote( m_pimpl->m_test_case_name ) << "is aborted due to uncaught exception or fatal error";
        where_to << std::endl;
    }
    else
        where_to << "\n*** No errors detected" << std::endl;
}

//____________________________________________________________________________//

void
unit_test_result::short_report( std::ostream& where_to, int indent )
{
    assert( this != NULL );

    bool              failed           = m_pimpl->m_test_cases_failed != 0 || m_pimpl->is_failed();
    unit_test_counter total_test_cases = m_pimpl->m_test_cases_failed + m_pimpl->m_test_cases_passed;
    unit_test_counter total_assertions = m_pimpl->m_assertions_failed + m_pimpl->m_assertions_passed;

    std::string indent_string( indent*2, ' ' );

    where_to << "\n" << indent_string << "Test " << cs_name( total_test_cases <= 1 )
             << quote( m_pimpl->m_test_case_name )
             << (failed ? "failed with:\n" : "passed with:\n");

    if( total_test_cases > 1 ) {
        int width = static_cast<int>( std::log10( (float)std::max( m_pimpl->m_test_cases_passed,
                                                                   m_pimpl->m_test_cases_failed ) ) ) + 1;
        where_to << indent_string << std::setw( width ) << m_pimpl->m_test_cases_passed
                 << " test " << ps_name( m_pimpl->m_test_cases_passed != 1, "case" ) << " out of " << total_test_cases << " passed\n";
        where_to << indent_string << std::setw( width ) << m_pimpl->m_test_cases_failed
                 << " test " << ps_name( m_pimpl->m_test_cases_failed != 1, "case" ) << " out of " << total_test_cases << " failed\n";
    }

    int width = total_assertions > 0
                  ? static_cast<int>( std::log10( (float)std::max( m_pimpl->m_assertions_passed,
                                                                   m_pimpl->m_assertions_failed ) ) ) + 1
                  : 1;

    where_to << indent_string << std::setw( width ) << m_pimpl->m_assertions_passed
             << ps_name( m_pimpl->m_assertions_passed != 1, " assertion" ) << " out of "
             << total_assertions << " passed\n";
    where_to << indent_string << std::setw( width ) << m_pimpl->m_assertions_failed
             << ps_name( m_pimpl->m_assertions_failed != 1, " assertion" ) << " out of "
             << total_assertions << " failed\n";

    if( m_pimpl->m_expected_failures > 0 ) {
        where_to << indent_string << "while " << m_pimpl->m_expected_failures
                 << ps_name( m_pimpl->m_expected_failures != 1, " failure" ) << " expected\n";
    }

    where_to.flush();
}

//____________________________________________________________________________//

void
unit_test_result::detailed_report( std::ostream& where_to, int indent )
{
    short_report( where_to, indent );

    std::list<unit_test_result*>::iterator it  = m_pimpl->m_children.begin();
    std::list<unit_test_result*>::iterator end = m_pimpl->m_children.end();

    while( it != end ) {
        unit_test_result* next = *(it++);
        next->detailed_report( where_to, indent+1 );
    }
}

//____________________________________________________________________________//

int
unit_test_result::result_code()
{
    return m_pimpl->result_code();
}

//____________________________________________________________________________//

} // namespace unit_test_framework

} // namespace boost

//  Revision History
//   5 Oct 01  Initial version (Gennadiy Rozental)

// EOF
<commit_msg>Borland fix from Gennadiy<commit_after>//  (C) Copyright Gennadiy Rozental 2001.
//  Permission to copy, use, modify, sell and distribute this software
//  is granted provided this copyright notice appears in all copies.
//  This software is provided "as is" without express or implied warranty,
//  and with no claim as to its suitability for any purpose.
//
//  See http://www.boost.org for most recent version including documentation.

// LOCAL
#include <boost/test/unit_test_result.hpp>
#include <boost/test/unit_test_suite.hpp>

// BOOST
#include <boost/config.hpp>
#include <boost/scoped_ptr.hpp>

// STL
#include <list>
#include <algorithm>
#include <cassert>
#include <iostream>
#include <iomanip>
#include <cmath>

# ifdef BOOST_NO_STDC_NAMESPACE
namespace std { using ::log10; using ::strncmp; }
# endif

namespace boost {

namespace unit_test_framework {

// ************************************************************************** //
// **************               unit_test_result               ************** //
// ************************************************************************** //

struct unit_test_result::Impl {
    unit_test_result*               m_parent;
    std::list<unit_test_result*>    m_children;
    unit_test_counter               m_assertions_passed;
    unit_test_counter               m_assertions_failed;
    unit_test_counter               m_expected_failures;
    unit_test_counter               m_test_cases_passed;
    unit_test_counter               m_test_cases_failed;
    bool                            m_exception_caught;
    char const*                     m_test_case_name;

    static boost::scoped_ptr<unit_test_result> m_head;
    static unit_test_result*        m_curr;

    bool                            is_failed()   { return m_assertions_failed != m_expected_failures || m_exception_caught; }
    unit_test_counter               result_code() { return is_failed()
                                                        ? ( (m_assertions_failed != 0) ? m_assertions_failed : -1 )
                                                        : 0; }
};

boost::scoped_ptr<unit_test_result> unit_test_result::Impl::m_head;
unit_test_result* unit_test_result::Impl::m_curr = NULL;

//____________________________________________________________________________//

unit_test_result::unit_test_result( unit_test_result* parent, char const* test_case_name, unit_test_counter exp_fail )
: m_pimpl( new Impl )
{
    m_pimpl->m_parent            = parent;
    m_pimpl->m_test_case_name    = test_case_name;

    m_pimpl->m_assertions_passed = 0;
    m_pimpl->m_assertions_failed = 0;
    m_pimpl->m_expected_failures = exp_fail;
    m_pimpl->m_test_cases_passed = 0;
    m_pimpl->m_test_cases_failed = 0;
    m_pimpl->m_exception_caught  = false;

}

//____________________________________________________________________________//

static void safe_delete( unit_test_result* ptr ) { boost::checked_delete<unit_test_result>( ptr ); }

unit_test_result::~unit_test_result()
{
    std::for_each( m_pimpl->m_children.begin(), m_pimpl->m_children.end(), &safe_delete );
}

//____________________________________________________________________________//

unit_test_result&
unit_test_result::instance()
{
    assert( Impl::m_head.get() != NULL );

    return Impl::m_curr == NULL ? *Impl::m_head : *Impl::m_curr;
}

//____________________________________________________________________________//

void
unit_test_result::test_case_start( char const* name, unit_test_counter expected_failures )
{
    unit_test_result* new_result_set = new unit_test_result( Impl::m_curr, name, expected_failures );

    if( Impl::m_curr == NULL ) {
        Impl::m_head.reset( new_result_set );
    }
    else
        Impl::m_curr->m_pimpl->m_children.push_back( new_result_set );

    Impl::m_curr = new_result_set;
}

//____________________________________________________________________________//

void
unit_test_result::test_case_end()
{
    assert( Impl::m_curr != NULL );

    Impl*             curr_impl = Impl::m_curr->m_pimpl.get();
    unit_test_result* parent    = curr_impl->m_parent;

    if( parent != NULL ) {
        // accumulate results
        parent->m_pimpl->m_assertions_passed += curr_impl->m_assertions_passed;
        parent->m_pimpl->m_assertions_failed += curr_impl->m_assertions_failed;
        parent->m_pimpl->m_test_cases_passed += curr_impl->m_test_cases_passed;
        parent->m_pimpl->m_test_cases_failed += curr_impl->m_test_cases_failed;

        // for test_cases (vs. test_suite)
        if( curr_impl->m_test_cases_passed == 0 && curr_impl->m_test_cases_failed == 0 ) {
            if( curr_impl->is_failed() )
                parent->m_pimpl->m_test_cases_failed++;
            else
                parent->m_pimpl->m_test_cases_passed++;
        }

    }

    Impl::m_curr = parent;
}

//____________________________________________________________________________//

void
unit_test_result::increase_expected_failures( unit_test_counter amount )
{
    m_pimpl->m_expected_failures += amount;

    if( m_pimpl->m_parent != NULL )
        m_pimpl->m_parent->increase_expected_failures( amount );
}

//____________________________________________________________________________//

void
unit_test_result::inc_failed_assertions()
{
    m_pimpl->m_assertions_failed++;
}

//____________________________________________________________________________//

void
unit_test_result::inc_passed_assertions()
{
    m_pimpl->m_assertions_passed++;
}

//____________________________________________________________________________//

void
unit_test_result::caught_exception()
{
    m_pimpl->m_exception_caught = true;
}

//____________________________________________________________________________//

char const*
unit_test_result::test_case_name()
{
    return m_pimpl->m_test_case_name;
}

//____________________________________________________________________________//

namespace {
std::string ps_name( bool p_s, char const* singular_form )  { return p_s ? std::string( singular_form ).append( "s" ) : std::string( singular_form ); }
std::string cs_name( bool c_s )                             { return c_s ? "case" : "suite"; }
std::string quote( char const* name )                       { return std::string( " \"" ).append( name ).append( "\" "); }
}

//____________________________________________________________________________//

void
unit_test_result::confirmation_report( std::ostream& where_to )
{
    assert( this != NULL );

    bool failed     = m_pimpl->m_test_cases_failed != 0 || m_pimpl->is_failed();
    bool case_suite = m_pimpl->m_test_cases_failed + m_pimpl->m_test_cases_passed <= 1;

    if( failed ) {
        if( m_pimpl->m_assertions_failed > 0 )
            where_to << "\n*** " << m_pimpl->m_assertions_failed
                     << ps_name( m_pimpl->m_assertions_failed != 1, " Failure" )
                     << " in test " << cs_name( case_suite )
                     << quote( m_pimpl->m_test_case_name );
        if( m_pimpl->m_exception_caught )
            where_to << "\n*** Test " << cs_name( case_suite )
                     << quote( m_pimpl->m_test_case_name ) << "is aborted due to uncaught exception or fatal error";
        where_to << std::endl;
    }
    else
        where_to << "\n*** No errors detected" << std::endl;
}

//____________________________________________________________________________//

void
unit_test_result::short_report( std::ostream& where_to, int indent )
{
    assert( this != NULL );

    bool              failed           = m_pimpl->m_test_cases_failed != 0 || m_pimpl->is_failed();
    unit_test_counter total_test_cases = m_pimpl->m_test_cases_failed + m_pimpl->m_test_cases_passed;
    unit_test_counter total_assertions = m_pimpl->m_assertions_failed + m_pimpl->m_assertions_passed;

    std::string indent_string( indent*2, ' ' );

    where_to << "\n" << indent_string << "Test " << cs_name( total_test_cases <= 1 )
             << quote( m_pimpl->m_test_case_name )
             << (failed ? "failed with:\n" : "passed with:\n");

    if( total_test_cases > 1 ) {
        int width = static_cast<int>( std::log10( (float)std::max( m_pimpl->m_test_cases_passed,
                                                                   m_pimpl->m_test_cases_failed ) ) ) + 1;
        where_to << indent_string << std::setw( width ) << m_pimpl->m_test_cases_passed
                 << " test " << ps_name( m_pimpl->m_test_cases_passed != 1, "case" ) << " out of " << total_test_cases << " passed\n";
        where_to << indent_string << std::setw( width ) << m_pimpl->m_test_cases_failed
                 << " test " << ps_name( m_pimpl->m_test_cases_failed != 1, "case" ) << " out of " << total_test_cases << " failed\n";
    }

    int width = total_assertions > 0
                  ? static_cast<int>( std::log10( (float)std::max( m_pimpl->m_assertions_passed,
                                                                   m_pimpl->m_assertions_failed ) ) ) + 1
                  : 1;

    where_to << indent_string << std::setw( width ) << m_pimpl->m_assertions_passed
             << ps_name( m_pimpl->m_assertions_passed != 1, " assertion" ) << " out of "
             << total_assertions << " passed\n";
    where_to << indent_string << std::setw( width ) << m_pimpl->m_assertions_failed
             << ps_name( m_pimpl->m_assertions_failed != 1, " assertion" ) << " out of "
             << total_assertions << " failed\n";

    if( m_pimpl->m_expected_failures > 0 ) {
        where_to << indent_string << "while " << m_pimpl->m_expected_failures
                 << ps_name( m_pimpl->m_expected_failures != 1, " failure" ) << " expected\n";
    }

    where_to.flush();
}

//____________________________________________________________________________//

void
unit_test_result::detailed_report( std::ostream& where_to, int indent )
{
    short_report( where_to, indent );

    std::list<unit_test_result*>::iterator it  = m_pimpl->m_children.begin();
    std::list<unit_test_result*>::iterator end = m_pimpl->m_children.end();

    while( it != end ) {
        unit_test_result* next = *(it++);
        next->detailed_report( where_to, indent+1 );
    }
}

//____________________________________________________________________________//

int
unit_test_result::result_code()
{
    return m_pimpl->result_code();
}

//____________________________________________________________________________//

} // namespace unit_test_framework

} // namespace boost

//  Revision History
//   5 Oct 01  Initial version (Gennadiy Rozental)

// EOF
<|endoftext|>


<commit_before>#include <QString>
#include <typeinfo>
#include "kernel.h"
#include "ilwisdata.h"
#include "range.h"
#include "domain.h"
#include "domainitem.h"
#include "itemdomain.h"
#include "itemrange.h"

using namespace Ilwis;

QHash<QString, CreateItemFunc> ItemRange::_createItem;

bool ItemRange::contains(SPRange rng, bool ) const
{
    SPItemRange itemrng = rng.staticCast<ItemRange>();
    for(int  i=0; i < itemrng->count(); ++i) {
        if(!contains(itemrng->itemByOrder(i)->name()))
            return false;
    }
    return true;
}

bool ItemRange::contains(const ItemRange &itemrng, bool ) const
{
    for(int  i=0; i < itemrng.count(); ++i) {
        if(!contains(itemrng.itemByOrder(i)->name()))
            return false;
    }
    return true;
}

QVariant ItemRange::ensure(const QVariant &v, bool ) const
{
    if ( contains(v))
        return v;
    return v;
}

DomainItem *ItemRange::create(const QString& type){
    auto iter = _createItem.find(type);
    if ( iter != _createItem.end())
        return iter.value()(type);
    return 0;
}

void ItemRange::addCreateItem(const QString& type, CreateItemFunc func){
    _createItem[type] = func;
}

ItemRange *ItemRange::merge(const QSharedPointer<ItemRange> &nr1, const QSharedPointer<ItemRange> &nr2)
{
    //TODO:
    return 0;
}

void ItemRange::addRange(const ItemRange &range)
{
    for(quint32 i=0; i < range.count(); ++i) {
        if (!contains(range.item(i)->name()))
            add(range.item(i)->clone());
    }
}
<commit_msg>correct return now for ensure<commit_after>#include <QString>
#include <typeinfo>
#include "kernel.h"
#include "ilwisdata.h"
#include "range.h"
#include "domain.h"
#include "domainitem.h"
#include "itemdomain.h"
#include "itemrange.h"

using namespace Ilwis;

QHash<QString, CreateItemFunc> ItemRange::_createItem;

bool ItemRange::contains(SPRange rng, bool ) const
{
    SPItemRange itemrng = rng.staticCast<ItemRange>();
    for(int  i=0; i < itemrng->count(); ++i) {
        if(!contains(itemrng->itemByOrder(i)->name()))
            return false;
    }
    return true;
}

bool ItemRange::contains(const ItemRange &itemrng, bool ) const
{
    for(int  i=0; i < itemrng.count(); ++i) {
        if(!contains(itemrng.itemByOrder(i)->name()))
            return false;
    }
    return true;
}

QVariant ItemRange::ensure(const QVariant &v, bool ) const
{
    if ( contains(v))
        return v;
    return QVariant();
}

DomainItem *ItemRange::create(const QString& type){
    auto iter = _createItem.find(type);
    if ( iter != _createItem.end())
        return iter.value()(type);
    return 0;
}

void ItemRange::addCreateItem(const QString& type, CreateItemFunc func){
    _createItem[type] = func;
}

ItemRange *ItemRange::merge(const QSharedPointer<ItemRange> &nr1, const QSharedPointer<ItemRange> &nr2)
{
    //TODO:
    return 0;
}

void ItemRange::addRange(const ItemRange &range)
{
    for(quint32 i=0; i < range.count(); ++i) {
        if (!contains(range.item(i)->name()))
            add(range.item(i)->clone());
    }
}
<|endoftext|>


<commit_before> /*
  * jabberresourcepool.cpp
  *
  * Copyright (c) 2004 by Till Gerken <till@tantalo.net>
  *
  * Kopete    (c) by the Kopete developers  <kopete-devel@kde.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.                                   *
  * *                                                                       *
  * *************************************************************************
  */

#include <qptrlist.h>
#include <kdebug.h>
#include "jabberresourcepool.h"
#include "jabberresource.h"
#include "jabbercontactpool.h"
#include "jabberbasecontact.h"
#include "jabberaccount.h"

/**
 * This resource will be returned if no other resource
 * for a given JID can be found. It's an empty offline
 * resource.
 */
XMPP::Resource JabberResourcePool::EmptyResource ( "", XMPP::Status ( "", "", 0, false ) );

JabberResourcePool::JabberResourcePool ( JabberAccount *account )
{

	// automatically delete all resources in the pool upon removal
	mPool.setAutoDelete (true);

	mAccount = account;

}

JabberResourcePool::~JabberResourcePool ()
{
}

void JabberResourcePool::slotResourceDestroyed (QObject *sender)
{
	kdDebug(JABBER_DEBUG_GLOBAL) << k_funcinfo << "Resource has been destroyed, collecting the pieces." << endl;

	JabberResource *oldResource = static_cast<JabberResource *>(sender);

	// remove this resource from the lock list if it existed
	mLockList.remove ( oldResource );

}

void JabberResourcePool::slotResourceUpdated ( JabberResource *resource )
{

	QPtrList<JabberBaseContact> list = mAccount->contactPool()->findRelevantSources ( resource->jid () );

	for(JabberBaseContact *mContact = list.first (); mContact; mContact = list.next ())
	{
		mContact->updateResourceList ();
	}

}

void JabberResourcePool::notifyRelevantContacts ( const XMPP::Jid &jid )
{

	QPtrList<JabberBaseContact> list = mAccount->contactPool()->findRelevantSources ( jid );

	for(JabberBaseContact *mContact = list.first (); mContact; mContact = list.next ())
	{
		mContact->reevaluateStatus ();
	}

}

void JabberResourcePool::addResource ( const XMPP::Jid &jid, const XMPP::Resource &resource )
{

	// see if the resource already exists
	for(JabberResource *mResource = mPool.first (); mResource; mResource = mPool.next ())
	{
		if ( (mResource->jid().userHost().lower() == jid.userHost().lower()) && (mResource->resource().name().lower() == resource.name().lower()) )
		{
			kdDebug(JABBER_DEBUG_GLOBAL) << k_funcinfo << "Updating existing resource " << resource.name() << " for " << jid.userHost() << endl;

			// It exists, update it. Don't do a "lazy" update by deleting
			// it here and readding it with new parameters later on,
			// any possible lockings to this resource will get lost.
			mResource->setResource ( resource );

			// we still need to notify the contact in case the status
			// of this resource changed
			notifyRelevantContacts ( jid );

			return;
		}
	}

	kdDebug(JABBER_DEBUG_GLOBAL) << k_funcinfo << "Adding new resource " << resource.name() << " for " << jid.userHost() << endl;

	// create new resource instance and add it to the dictionary
	JabberResource *newResource = new JabberResource(mAccount, jid, resource);
	connect ( newResource, SIGNAL ( destroyed (QObject *) ), this, SLOT ( slotResourceDestroyed (QObject *) ) );
	connect ( newResource, SIGNAL ( updated (JabberResource *) ), this, SLOT ( slotResourceUpdated (JabberResource *) ) );
	mPool.append ( newResource );

	// send notifications out to the relevant contacts that
	// a new resource is available for them
	notifyRelevantContacts ( jid );

}

void JabberResourcePool::removeResource ( const XMPP::Jid &jid, const XMPP::Resource &resource )
{
	kdDebug(JABBER_DEBUG_GLOBAL) << k_funcinfo << "Removing resource " << resource.name() << " from " << jid.userHost() << endl;

	for(JabberResource *mResource = mPool.first (); mResource; mResource = mPool.next ())
	{
		if ( (mResource->jid().userHost().lower() == jid.userHost().lower()) && (mResource->resource().name().lower() == resource.name().lower()) )
		{
			mPool.remove ();
			notifyRelevantContacts ( jid );
			return;
		}
	}

	kdDebug(JABBER_DEBUG_GLOBAL) << k_funcinfo << "WARNING: No match found!" << endl;

}

void JabberResourcePool::removeAllResources ( const XMPP::Jid &jid )
{
	kdDebug(JABBER_DEBUG_GLOBAL) << k_funcinfo << "Removing all resources for " << jid.userHost() << endl;

	for(JabberResource *mResource = mPool.first (); mResource; mResource = mPool.next ())
	{
		if ( mResource->jid().userHost().lower() == jid.userHost().lower() )
		{
			// only remove preselected resource in case there is one
			if ( !jid.resource().isEmpty () && ( jid.resource () == mResource->resource().name () ) )
				mPool.remove ();
		}
	}

}

void JabberResourcePool::clear ()
{
	kdDebug(JABBER_DEBUG_GLOBAL) << k_funcinfo << "Clearing the resource pool." << endl;

	/*
	 * Since many contacts can have multiple resources, we can't simply delete
	 * each resource and trigger a notification upon each deletion. This would
	 * cause lots of status updates in the GUI and create unnecessary flicker
	 * and API traffic. Instead, collect all JIDs, clear the dictionary
	 * and then notify all JIDs after the resources have been deleted.
	 */

	QStringList jidList;

	for ( JabberResource *mResource = mPool.first (); mResource; mResource = mPool.next () )
	{
		jidList += mResource->jid().full ();
	}

	/*
	 * Since mPool has autodeletion enabled, this will cause all
	 * items to be deleted. The lock list will be cleaned automatically.
	 */
	mPool.clear ();

	/*
	 * Now go through the list of JIDs and notify each contact
	 * of its status change
	 */
	for ( QStringList::Iterator it = jidList.begin (); it != jidList.end (); ++it )
	{
		notifyRelevantContacts ( XMPP::Jid ( *it ) );
	}

}

void JabberResourcePool::lockToResource ( const XMPP::Jid &jid, const XMPP::Resource &resource )
{

	kdDebug(JABBER_DEBUG_GLOBAL) << k_funcinfo << "Locking " << jid.full() << " to " << resource.name() << endl;

	// remove all existing locks first
	removeLock ( jid );

	// find the resource in our dictionary that matches
	for(JabberResource *mResource = mPool.first (); mResource; mResource = mPool.next ())
	{
		if ( (mResource->jid().userHost().lower() == jid.full().lower()) && (mResource->resource().name().lower() == resource.name().lower()) )
		{
			mLockList.append ( mResource );
			return;
		}
	}

	kdDebug(JABBER_DEBUG_GLOBAL) << k_funcinfo << "WARNING: No match found!" << endl;

}

void JabberResourcePool::removeLock ( const XMPP::Jid &jid )
{
	kdDebug(JABBER_DEBUG_GLOBAL) << k_funcinfo << "Removing resource lock for " << jid.userHost() << endl;

	// find the resource in our dictionary that matches
	for(JabberResource *mResource = mPool.first (); mResource; mResource = mPool.next ())
	{
		if ( (mResource->jid().userHost().lower() == jid.userHost().lower()) )
		{
			mLockList.remove (mResource);
		}
	}

	kdDebug(JABBER_DEBUG_GLOBAL) << k_funcinfo << "No locks found." << endl;

}

const XMPP::Resource &JabberResourcePool::lockedResource ( const XMPP::Jid &jid )
{

	// check if the JID already carries a resource, then we will have to use that one
	if ( !jid.resource().isEmpty () )
	{
		// we are subscribed to a JID, find the according resource in the pool
		for ( JabberResource *mResource = mPool.first (); mResource; mResource = mPool.next () )
		{
			if ( ( mResource->jid().userHost().lower () == jid.userHost().lower () ) && ( mResource->resource().name () == jid.resource () ) )
			{
				return mResource->resource ();
			}
		}

		kdDebug ( JABBER_DEBUG_GLOBAL ) << k_funcinfo << "WARNING: No resource found in pool, returning as offline." << endl;

		return EmptyResource;
	}

	// see if we have a locked resource
	for(JabberResource *mResource = mLockList.first (); mResource; mResource = mLockList.next ())
	{
		if ( mResource->jid().userHost().lower() == jid.userHost().lower() )
		{
			kdDebug (JABBER_DEBUG_GLOBAL) << k_funcinfo << "Current lock for " << jid.userHost () << " is '" << mResource->resource().name () << "'" << endl;
			return mResource->resource ();
		}
	}

	kdDebug (JABBER_DEBUG_GLOBAL) << k_funcinfo << "No lock available for " << jid.userHost () << endl;

	// there's no locked resource, return an empty resource
	return EmptyResource;

}

const XMPP::Resource &JabberResourcePool::bestResource ( const XMPP::Jid &jid, bool honourLock )
{
	kdDebug(JABBER_DEBUG_GLOBAL) << k_funcinfo << "Determining best resource for " << jid.full () << endl;

	// FIXME: the code below would be more efficient if it would cache results

	if ( honourLock )
	{
		// if we are locked to a certain resource, always return that one
		const XMPP::Resource &mResource = lockedResource ( jid );
		if ( !mResource.name().isEmpty() )
		{
			kdDebug(JABBER_DEBUG_GLOBAL) << k_funcinfo << "We have a locked resource '" << mResource.name () << "' for " << jid.full () << endl;
			return mResource;
		}
	}

	JabberResource *bestResource = 0L;
	JabberResource *currentResource = 0L;

	for(currentResource = mPool.first (); currentResource; currentResource = mPool.next ())
	{
		// make sure we are only looking up resources for the specified JID
		if ( currentResource->jid().userHost().lower() != jid.userHost().lower() )
		{
			continue;
		}

		// take first resource if no resource has been chosen yet
		if(!bestResource)
		{
			kdDebug(JABBER_DEBUG_GLOBAL) << k_funcinfo << "Taking '" << currentResource->resource().name () << "' as first available resource." << endl;

			bestResource = currentResource;
			continue;
		}

		if(currentResource->resource().priority() > bestResource->resource().priority())
		{
			kdDebug(JABBER_DEBUG_GLOBAL) << k_funcinfo << "Using '" << currentResource->resource().name () << "' due to better priority." << endl;

			// got a better match by priority
			bestResource = currentResource;
		}
		else
		{
			if(currentResource->resource().priority() == bestResource->resource().priority())
			{
				if(currentResource->resource().status().timeStamp() > bestResource->resource().status().timeStamp())
				{
					kdDebug(JABBER_DEBUG_GLOBAL) << k_funcinfo << "Using '" << currentResource->resource().name () << "' due to better timestamp." << endl;

					// got a better match by timestamp (priorities are equal)
					bestResource = currentResource;
				}
			}
		}
	}

	return (bestResource == 0L) ? EmptyResource : bestResource->resource();

}

void JabberResourcePool::findResources ( const XMPP::Jid &jid, JabberResourcePool::ResourceList &resourceList )
{

	for(JabberResource *mResource = mPool.first (); mResource; mResource = mPool.next ())
	{
		if ( mResource->jid().userHost().lower() == jid.userHost().lower() )
		{
			// we found a resource for the JID, let's see if the JID already contains a resource
			if ( !jid.resource().isEmpty() && ( jid.resource().lower() != mResource->resource().name().lower() ) )
				// the JID contains a resource but it's not the one we have in the dictionary,
				// thus we have to ignore this resource
				continue;

			resourceList.append ( mResource );
		}
	}

}

void JabberResourcePool::findResources ( const XMPP::Jid &jid, XMPP::ResourceList &resourceList )
{

	for(JabberResource *mResource = mPool.first (); mResource; mResource = mPool.next ())
	{
		if ( mResource->jid().userHost().lower() == jid.userHost().lower() )
		{
			// we found a resource for the JID, let's see if the JID already contains a resource
			if ( !jid.resource().isEmpty() && ( jid.resource().lower() != mResource->resource().name().lower() ) )
				// the JID contains a resource but it's not the one we have in the dictionary,
				// thus we have to ignore this resource
				continue;

			resourceList.append ( mResource->resource () );
		}
	}

}

#include "jabberresourcepool.moc"
<commit_msg>Fix logic when removing resources.<commit_after> /*
  * jabberresourcepool.cpp
  *
  * Copyright (c) 2004 by Till Gerken <till@tantalo.net>
  *
  * Kopete    (c) by the Kopete developers  <kopete-devel@kde.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.                                   *
  * *                                                                       *
  * *************************************************************************
  */

#include <qptrlist.h>
#include <kdebug.h>
#include "jabberresourcepool.h"
#include "jabberresource.h"
#include "jabbercontactpool.h"
#include "jabberbasecontact.h"
#include "jabberaccount.h"

/**
 * This resource will be returned if no other resource
 * for a given JID can be found. It's an empty offline
 * resource.
 */
XMPP::Resource JabberResourcePool::EmptyResource ( "", XMPP::Status ( "", "", 0, false ) );

JabberResourcePool::JabberResourcePool ( JabberAccount *account )
{

	// automatically delete all resources in the pool upon removal
	mPool.setAutoDelete (true);

	mAccount = account;

}

JabberResourcePool::~JabberResourcePool ()
{
}

void JabberResourcePool::slotResourceDestroyed (QObject *sender)
{
	kdDebug(JABBER_DEBUG_GLOBAL) << k_funcinfo << "Resource has been destroyed, collecting the pieces." << endl;

	JabberResource *oldResource = static_cast<JabberResource *>(sender);

	// remove this resource from the lock list if it existed
	mLockList.remove ( oldResource );

}

void JabberResourcePool::slotResourceUpdated ( JabberResource *resource )
{

	QPtrList<JabberBaseContact> list = mAccount->contactPool()->findRelevantSources ( resource->jid () );

	for(JabberBaseContact *mContact = list.first (); mContact; mContact = list.next ())
	{
		mContact->updateResourceList ();
	}

}

void JabberResourcePool::notifyRelevantContacts ( const XMPP::Jid &jid )
{

	QPtrList<JabberBaseContact> list = mAccount->contactPool()->findRelevantSources ( jid );

	for(JabberBaseContact *mContact = list.first (); mContact; mContact = list.next ())
	{
		mContact->reevaluateStatus ();
	}

}

void JabberResourcePool::addResource ( const XMPP::Jid &jid, const XMPP::Resource &resource )
{

	// see if the resource already exists
	for(JabberResource *mResource = mPool.first (); mResource; mResource = mPool.next ())
	{
		if ( (mResource->jid().userHost().lower() == jid.userHost().lower()) && (mResource->resource().name().lower() == resource.name().lower()) )
		{
			kdDebug(JABBER_DEBUG_GLOBAL) << k_funcinfo << "Updating existing resource " << resource.name() << " for " << jid.userHost() << endl;

			// It exists, update it. Don't do a "lazy" update by deleting
			// it here and readding it with new parameters later on,
			// any possible lockings to this resource will get lost.
			mResource->setResource ( resource );

			// we still need to notify the contact in case the status
			// of this resource changed
			notifyRelevantContacts ( jid );

			return;
		}
	}

	kdDebug(JABBER_DEBUG_GLOBAL) << k_funcinfo << "Adding new resource " << resource.name() << " for " << jid.userHost() << endl;

	// create new resource instance and add it to the dictionary
	JabberResource *newResource = new JabberResource(mAccount, jid, resource);
	connect ( newResource, SIGNAL ( destroyed (QObject *) ), this, SLOT ( slotResourceDestroyed (QObject *) ) );
	connect ( newResource, SIGNAL ( updated (JabberResource *) ), this, SLOT ( slotResourceUpdated (JabberResource *) ) );
	mPool.append ( newResource );

	// send notifications out to the relevant contacts that
	// a new resource is available for them
	notifyRelevantContacts ( jid );

}

void JabberResourcePool::removeResource ( const XMPP::Jid &jid, const XMPP::Resource &resource )
{
	kdDebug(JABBER_DEBUG_GLOBAL) << k_funcinfo << "Removing resource " << resource.name() << " from " << jid.userHost() << endl;

	for(JabberResource *mResource = mPool.first (); mResource; mResource = mPool.next ())
	{
		if ( (mResource->jid().userHost().lower() == jid.userHost().lower()) && (mResource->resource().name().lower() == resource.name().lower()) )
		{
			mPool.remove ();
			notifyRelevantContacts ( jid );
			return;
		}
	}

	kdDebug(JABBER_DEBUG_GLOBAL) << k_funcinfo << "WARNING: No match found!" << endl;

}

void JabberResourcePool::removeAllResources ( const XMPP::Jid &jid )
{
	kdDebug(JABBER_DEBUG_GLOBAL) << k_funcinfo << "Removing all resources for " << jid.userHost() << endl;

	for(JabberResource *mResource = mPool.first (); mResource; mResource = mPool.next ())
	{
		if ( mResource->jid().userHost().lower() == jid.userHost().lower() )
		{
			// only remove preselected resource in case there is one
			if ( jid.resource().isEmpty () || ( jid.resource().lower () == mResource->resource().name().lower () ) )
			{
				kdDebug(JABBER_DEBUG_GLOBAL) << k_funcinfo << "Removing resource " << jid.userHost() << "/" << mResource->resource().name () << endl;
				mPool.remove ();
			}
		}
	}

}

void JabberResourcePool::clear ()
{
	kdDebug(JABBER_DEBUG_GLOBAL) << k_funcinfo << "Clearing the resource pool." << endl;

	/*
	 * Since many contacts can have multiple resources, we can't simply delete
	 * each resource and trigger a notification upon each deletion. This would
	 * cause lots of status updates in the GUI and create unnecessary flicker
	 * and API traffic. Instead, collect all JIDs, clear the dictionary
	 * and then notify all JIDs after the resources have been deleted.
	 */

	QStringList jidList;

	for ( JabberResource *mResource = mPool.first (); mResource; mResource = mPool.next () )
	{
		jidList += mResource->jid().full ();
	}

	/*
	 * Since mPool has autodeletion enabled, this will cause all
	 * items to be deleted. The lock list will be cleaned automatically.
	 */
	mPool.clear ();

	/*
	 * Now go through the list of JIDs and notify each contact
	 * of its status change
	 */
	for ( QStringList::Iterator it = jidList.begin (); it != jidList.end (); ++it )
	{
		notifyRelevantContacts ( XMPP::Jid ( *it ) );
	}

}

void JabberResourcePool::lockToResource ( const XMPP::Jid &jid, const XMPP::Resource &resource )
{

	kdDebug(JABBER_DEBUG_GLOBAL) << k_funcinfo << "Locking " << jid.full() << " to " << resource.name() << endl;

	// remove all existing locks first
	removeLock ( jid );

	// find the resource in our dictionary that matches
	for(JabberResource *mResource = mPool.first (); mResource; mResource = mPool.next ())
	{
		if ( (mResource->jid().userHost().lower() == jid.full().lower()) && (mResource->resource().name().lower() == resource.name().lower()) )
		{
			mLockList.append ( mResource );
			return;
		}
	}

	kdDebug(JABBER_DEBUG_GLOBAL) << k_funcinfo << "WARNING: No match found!" << endl;

}

void JabberResourcePool::removeLock ( const XMPP::Jid &jid )
{
	kdDebug(JABBER_DEBUG_GLOBAL) << k_funcinfo << "Removing resource lock for " << jid.userHost() << endl;

	// find the resource in our dictionary that matches
	for(JabberResource *mResource = mPool.first (); mResource; mResource = mPool.next ())
	{
		if ( (mResource->jid().userHost().lower() == jid.userHost().lower()) )
		{
			mLockList.remove (mResource);
		}
	}

	kdDebug(JABBER_DEBUG_GLOBAL) << k_funcinfo << "No locks found." << endl;

}

const XMPP::Resource &JabberResourcePool::lockedResource ( const XMPP::Jid &jid )
{

	// check if the JID already carries a resource, then we will have to use that one
	if ( !jid.resource().isEmpty () )
	{
		// we are subscribed to a JID, find the according resource in the pool
		for ( JabberResource *mResource = mPool.first (); mResource; mResource = mPool.next () )
		{
			if ( ( mResource->jid().userHost().lower () == jid.userHost().lower () ) && ( mResource->resource().name () == jid.resource () ) )
			{
				return mResource->resource ();
			}
		}

		kdDebug ( JABBER_DEBUG_GLOBAL ) << k_funcinfo << "WARNING: No resource found in pool, returning as offline." << endl;

		return EmptyResource;
	}

	// see if we have a locked resource
	for(JabberResource *mResource = mLockList.first (); mResource; mResource = mLockList.next ())
	{
		if ( mResource->jid().userHost().lower() == jid.userHost().lower() )
		{
			kdDebug (JABBER_DEBUG_GLOBAL) << k_funcinfo << "Current lock for " << jid.userHost () << " is '" << mResource->resource().name () << "'" << endl;
			return mResource->resource ();
		}
	}

	kdDebug (JABBER_DEBUG_GLOBAL) << k_funcinfo << "No lock available for " << jid.userHost () << endl;

	// there's no locked resource, return an empty resource
	return EmptyResource;

}

const XMPP::Resource &JabberResourcePool::bestResource ( const XMPP::Jid &jid, bool honourLock )
{
	kdDebug(JABBER_DEBUG_GLOBAL) << k_funcinfo << "Determining best resource for " << jid.full () << endl;

	// FIXME: the code below would be more efficient if it would cache results

	if ( honourLock )
	{
		// if we are locked to a certain resource, always return that one
		const XMPP::Resource &mResource = lockedResource ( jid );
		if ( !mResource.name().isEmpty() )
		{
			kdDebug(JABBER_DEBUG_GLOBAL) << k_funcinfo << "We have a locked resource '" << mResource.name () << "' for " << jid.full () << endl;
			return mResource;
		}
	}

	JabberResource *bestResource = 0L;
	JabberResource *currentResource = 0L;

	for(currentResource = mPool.first (); currentResource; currentResource = mPool.next ())
	{
		// make sure we are only looking up resources for the specified JID
		if ( currentResource->jid().userHost().lower() != jid.userHost().lower() )
		{
			continue;
		}

		// take first resource if no resource has been chosen yet
		if(!bestResource)
		{
			kdDebug(JABBER_DEBUG_GLOBAL) << k_funcinfo << "Taking '" << currentResource->resource().name () << "' as first available resource." << endl;

			bestResource = currentResource;
			continue;
		}

		if(currentResource->resource().priority() > bestResource->resource().priority())
		{
			kdDebug(JABBER_DEBUG_GLOBAL) << k_funcinfo << "Using '" << currentResource->resource().name () << "' due to better priority." << endl;

			// got a better match by priority
			bestResource = currentResource;
		}
		else
		{
			if(currentResource->resource().priority() == bestResource->resource().priority())
			{
				if(currentResource->resource().status().timeStamp() > bestResource->resource().status().timeStamp())
				{
					kdDebug(JABBER_DEBUG_GLOBAL) << k_funcinfo << "Using '" << currentResource->resource().name () << "' due to better timestamp." << endl;

					// got a better match by timestamp (priorities are equal)
					bestResource = currentResource;
				}
			}
		}
	}

	return (bestResource == 0L) ? EmptyResource : bestResource->resource();

}

void JabberResourcePool::findResources ( const XMPP::Jid &jid, JabberResourcePool::ResourceList &resourceList )
{

	for(JabberResource *mResource = mPool.first (); mResource; mResource = mPool.next ())
	{
		if ( mResource->jid().userHost().lower() == jid.userHost().lower() )
		{
			// we found a resource for the JID, let's see if the JID already contains a resource
			if ( !jid.resource().isEmpty() && ( jid.resource().lower() != mResource->resource().name().lower() ) )
				// the JID contains a resource but it's not the one we have in the dictionary,
				// thus we have to ignore this resource
				continue;

			resourceList.append ( mResource );
		}
	}

}

void JabberResourcePool::findResources ( const XMPP::Jid &jid, XMPP::ResourceList &resourceList )
{

	for(JabberResource *mResource = mPool.first (); mResource; mResource = mPool.next ())
	{
		if ( mResource->jid().userHost().lower() == jid.userHost().lower() )
		{
			// we found a resource for the JID, let's see if the JID already contains a resource
			if ( !jid.resource().isEmpty() && ( jid.resource().lower() != mResource->resource().name().lower() ) )
				// the JID contains a resource but it's not the one we have in the dictionary,
				// thus we have to ignore this resource
				continue;

			resourceList.append ( mResource->resource () );
		}
	}

}

#include "jabberresourcepool.moc"
<|endoftext|>


<commit_before>/*
 * privacylist.cpp
 * Copyright (C) 2006  Remko Troncon
 *
 * 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 library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 */

#include <QDomElement>
#include <QString>
#include <QStringList>
#include <QList>

#include <kdebug.h>
#include "jabberprotocol.h"

#include "privacylist.h"

#define ORDER_INCREMENT 10

PrivacyList::PrivacyList(const QString& name, const QList<PrivacyListItem>& items) : name_(name), items_(items)
{
	qSort(items_);
};

PrivacyList::PrivacyList(const QDomElement& e)
{
	fromXml(e);
}

void PrivacyList::updateItem(int index, const PrivacyListItem& item)
{
	unsigned int order = items_[index].order();
	items_[index] = item;
	items_[index].setOrder(order);
}

void PrivacyList::insertItem(int index, const PrivacyListItem& item)
{
	items_.insert(index,item);

	reNumber();
}

void PrivacyList::reNumber()
{
	unsigned int order = 100;
	for (int i = 0; i < items_.size(); ++i) {
    	items_[i].setOrder(order);
		order += ORDER_INCREMENT;
	}
}

bool PrivacyList::moveItemUp(int index)
{
	if (index < items().count() && index > 0) {
		unsigned int order =items_[index].order();
		if (order == items_[index-1].order()) {
			reNumber();
			return true;
		}
		items_[index].setOrder(items_[index-1].order());
		items_[index-1].setOrder(order);
		items_.swap(index,index-1);
		return true;
	}
	else {
		return false;
	}
}

bool PrivacyList::moveItemDown(int index)
{
	if (index >= 0 && index < items().count()-1) {
		unsigned int order =items_[index].order();
		if (order == items_[index+1].order()) {
			reNumber();
			return true;
		}
		items_[index].setOrder(items_[index+1].order());
		items_[index+1].setOrder(order);
		items_.swap(index,index+1);
		return true;
	}
	else {
		return false;
	}
}

bool PrivacyList::onlyBlockItems() const
{
	bool allBlocked = true;
	bool fallThrough = false;
	QList<PrivacyListItem>::ConstIterator it;
    for (it = items_.begin(); it != items_.end() && allBlocked; ++it ) {
		if ((*it).type() == PrivacyListItem::FallthroughType && (*it).action() == PrivacyListItem::Allow && (*it).all()) {
			fallThrough = true;
		}
		else if ((*it).isBlock()) {
			if (fallThrough)
				allBlocked = false;
		}
		else {
			allBlocked = false;
		}
	}
	return allBlocked;
}

QDomElement PrivacyList::toXml(QDomDocument& doc) const
{
	QDomElement list = doc.createElement("list");
	list.setAttribute("name",name());

	for (QList<PrivacyListItem>::ConstIterator it = items_.begin() ; it != items_.end(); it++) {
		list.appendChild((*it).toXml(doc));
	}

	return list;
}

void PrivacyList::fromXml(const QDomElement& el)
{
	//kDebug (JABBER_DEBUG_GLOBAL) << "Parsing privacy list";
	if (el.isNull() || el.tagName() != "list") {
		kWarning (JABBER_DEBUG_GLOBAL) << "Invalid root tag for privacy list.";
		return;
	}

	setName(el.attribute("name"));
	for(QDomNode n = el.firstChild(); !n.isNull(); n = n.nextSibling()) {
		QDomElement e = n.toElement();
		if (!e.isNull())
			items_.append(PrivacyListItem(e));
	}

	qSort(items_);
}

QString PrivacyList::toString() const
{
	QString s;
	for (QList<PrivacyListItem>::ConstIterator it = items_.begin() ; it != items_.end(); it++) {
		s += QString("%1 (%2)\n").arg((*it).toString()).arg((*it).order());
	}
	return s;
}
<commit_msg>Remove extra ;<commit_after>/*
 * privacylist.cpp
 * Copyright (C) 2006  Remko Troncon
 *
 * 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 library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 */

#include <QDomElement>
#include <QString>
#include <QStringList>
#include <QList>

#include <kdebug.h>
#include "jabberprotocol.h"

#include "privacylist.h"

#define ORDER_INCREMENT 10

PrivacyList::PrivacyList(const QString& name, const QList<PrivacyListItem>& items) : name_(name), items_(items)
{
	qSort(items_);
}

PrivacyList::PrivacyList(const QDomElement& e)
{
	fromXml(e);
}

void PrivacyList::updateItem(int index, const PrivacyListItem& item)
{
	unsigned int order = items_[index].order();
	items_[index] = item;
	items_[index].setOrder(order);
}

void PrivacyList::insertItem(int index, const PrivacyListItem& item)
{
	items_.insert(index,item);

	reNumber();
}

void PrivacyList::reNumber()
{
	unsigned int order = 100;
	for (int i = 0; i < items_.size(); ++i) {
    	items_[i].setOrder(order);
		order += ORDER_INCREMENT;
	}
}

bool PrivacyList::moveItemUp(int index)
{
	if (index < items().count() && index > 0) {
		unsigned int order =items_[index].order();
		if (order == items_[index-1].order()) {
			reNumber();
			return true;
		}
		items_[index].setOrder(items_[index-1].order());
		items_[index-1].setOrder(order);
		items_.swap(index,index-1);
		return true;
	}
	else {
		return false;
	}
}

bool PrivacyList::moveItemDown(int index)
{
	if (index >= 0 && index < items().count()-1) {
		unsigned int order =items_[index].order();
		if (order == items_[index+1].order()) {
			reNumber();
			return true;
		}
		items_[index].setOrder(items_[index+1].order());
		items_[index+1].setOrder(order);
		items_.swap(index,index+1);
		return true;
	}
	else {
		return false;
	}
}

bool PrivacyList::onlyBlockItems() const
{
	bool allBlocked = true;
	bool fallThrough = false;
	QList<PrivacyListItem>::ConstIterator it;
    for (it = items_.begin(); it != items_.end() && allBlocked; ++it ) {
		if ((*it).type() == PrivacyListItem::FallthroughType && (*it).action() == PrivacyListItem::Allow && (*it).all()) {
			fallThrough = true;
		}
		else if ((*it).isBlock()) {
			if (fallThrough)
				allBlocked = false;
		}
		else {
			allBlocked = false;
		}
	}
	return allBlocked;
}

QDomElement PrivacyList::toXml(QDomDocument& doc) const
{
	QDomElement list = doc.createElement("list");
	list.setAttribute("name",name());

	for (QList<PrivacyListItem>::ConstIterator it = items_.begin() ; it != items_.end(); it++) {
		list.appendChild((*it).toXml(doc));
	}

	return list;
}

void PrivacyList::fromXml(const QDomElement& el)
{
	//kDebug (JABBER_DEBUG_GLOBAL) << "Parsing privacy list";
	if (el.isNull() || el.tagName() != "list") {
		kWarning (JABBER_DEBUG_GLOBAL) << "Invalid root tag for privacy list.";
		return;
	}

	setName(el.attribute("name"));
	for(QDomNode n = el.firstChild(); !n.isNull(); n = n.nextSibling()) {
		QDomElement e = n.toElement();
		if (!e.isNull())
			items_.append(PrivacyListItem(e));
	}

	qSort(items_);
}

QString PrivacyList::toString() const
{
	QString s;
	for (QList<PrivacyListItem>::ConstIterator it = items_.begin() ; it != items_.end(); it++) {
		s += QString("%1 (%2)\n").arg((*it).toString()).arg((*it).order());
	}
	return s;
}
<|endoftext|>


<commit_before>// RUN: llvm-cov show %S/Inputs/deferred-regions.covmapping -instr-profile %S/Inputs/deferred-regions.profdata -show-line-counts-or-regions -dump -path-equivalence=/Users/vk/src/llvm.org-coverage-braces/llvm/test/tools,%S/.. %s 2&>1 > %t.out && FileCheck %s -input-file %t.out && FileCheck %s -input-file %t.out -check-prefix=MARKER

void foo(int x) {
  if (x == 0) {
    return; // CHECK: [[@LINE]]|{{ +}}1|
  }

} // CHECK: [[@LINE]]|{{ +}}1|

void bar() {
  return;

} // CHECK: [[@LINE]]|{{ +}}1|

void for_loop() {
  if (false)
    return; // CHECK: [[@LINE]]|{{ +}}0|

  for (int i = 0; i < 10; ++i) { // CHECK: [[@LINE]]|{{ +}}2|
    if (i % 2 == 0)
      continue; // CHECK: [[@LINE]]|{{ +}}1|

    if (i % 5 == 0)
      break; // CHECK: [[@LINE]]|{{ +}}0|

    int x = i;
    return; // CHECK: [[@LINE]]|{{ +}}1|

  } // CHECK: [[@LINE]]|{{ +}}1|
}

struct Error {};

void while_loop() {
  if (false)
    return; // CHECK: [[@LINE]]|{{ +}}0|

  int x = 0;
  while (++x < 10) { // CHECK: [[@LINE]]|{{ +}}3|
    if (x == 1)
      continue; // CHECK: [[@LINE]]|{{ +}}1|

    while (++x < 4) { // CHECK: [[@LINE]]|{{ +}}1|
      if (x == 3)
        break; // CHECK: [[@LINE]]|{{ +}}1|
               // CHECK: [[@LINE]]|{{ +}}0|
      while (++x < 5) {} // CHECK: [[@LINE]]|{{ +}}0|
    } // CHECK: [[@LINE]]|{{ +}}1|

    if (x == 0)
      throw Error(); // CHECK: [[@LINE]]|{{ +}}0|

    while (++x < 9) { // CHECK: [[@LINE]]|{{ +}}6|
      if (x == 0) // CHECK: [[@LINE]]|{{ +}}5|
        break; // CHECK: [[@LINE]]|{{ +}}0|

    }
  }
}

void gotos() {
  if (false)
    goto out; // CHECK: [[@LINE]]|{{ +}}0|

  return;

out: // CHECK: [[@LINE]]|{{ +}}1|
	return;
}

int main() {
  foo(0);
  foo(1);
  bar();
  for_loop();
  while_loop();
  gotos();
  return 0;
}

// MARKER: Marker at 4:7 = 2
// MARKER-NEXT: Highlighted line 17, 5 -> 11
// MARKER-NEXT: Marker at 17:5 = 0
// MARKER-NEXT: Marker at 19:3 = 1
// MARKER-NEXT: Marker at 19:19 = 2
// MARKER-NEXT: Marker at 19:27 = 1
// MARKER-NEXT: Marker at 21:7 = 1
// MARKER-NEXT: Marker at 23:5 = 1
// MARKER-NEXT: Marker at 23:9 = 1
// MARKER-NEXT: Highlighted line 24, 7 -> 12
// MARKER-NEXT: Marker at 24:7 = 0
// MARKER-NEXT: Highlighted line 36, 5 -> 11
// MARKER-NEXT: Marker at 36:5 = 0
// MARKER-NEXT: Marker at 39:10 = 3
// MARKER-NEXT: Marker at 41:7 = 1
// MARKER-NEXT: Marker at 43:5 = 1
// MARKER-NEXT: Marker at 43:12 = 1
// MARKER-NEXT: Highlighted line 45, 14 -> ?
// MARKER-NEXT: Marker at 45:9 = 1
// MARKER-NEXT: Highlighted line 46, 1 -> ?
// MARKER-NEXT: Highlighted line 47, 1 -> 7
// MARKER-NEXT: Highlighted line 47, 7 -> 14
// MARKER-NEXT: Highlighted line 47, 14 -> 21
// MARKER-NEXT: Highlighted line 47, 21 -> 23
// MARKER-NEXT: Highlighted line 47, 23 -> 25
// MARKER-NEXT: Marker at 47:7 = 0
// MARKER-NEXT: Marker at 47:14 = 0
// MARKER-NEXT: Marker at 47:23 = 0
// MARKER-NEXT: Highlighted line 51, 7 -> 20
// MARKER-NEXT: Marker at 51:7 = 0
// MARKER-NEXT: Marker at 53:5 = 1
// MARKER-NEXT: Marker at 53:12 = 6
// MARKER-NEXT: Highlighted line 55, 9 -> 14
// MARKER-NEXT: Highlighted line 63, 5 -> 13
// MARKER-NEXT: Marker at 63:5 = 0
// MARKER-NEXT: Highlighted line 67, 1 -> ?
// MARKER-NEXT: Highlighted line 68, 1 -> 8
// MARKER-NEXT: Highlighted line 68, 8 -> ?
// MARKER-NEXT: Highlighted line 69, 1 -> 2
<commit_msg>Fixed a typo in llvm-cov/deferred-region.cpp test.<commit_after>// RUN: llvm-cov show %S/Inputs/deferred-regions.covmapping -instr-profile %S/Inputs/deferred-regions.profdata -show-line-counts-or-regions -dump -path-equivalence=/Users/vk/src/llvm.org-coverage-braces/llvm/test/tools,%S/.. %s 2>&1 > %t.out && FileCheck %s -input-file %t.out && FileCheck %s -input-file %t.out -check-prefix=MARKER

void foo(int x) {
  if (x == 0) {
    return; // CHECK: [[@LINE]]|{{ +}}1|
  }

} // CHECK: [[@LINE]]|{{ +}}1|

void bar() {
  return;

} // CHECK: [[@LINE]]|{{ +}}1|

void for_loop() {
  if (false)
    return; // CHECK: [[@LINE]]|{{ +}}0|

  for (int i = 0; i < 10; ++i) { // CHECK: [[@LINE]]|{{ +}}2|
    if (i % 2 == 0)
      continue; // CHECK: [[@LINE]]|{{ +}}1|

    if (i % 5 == 0)
      break; // CHECK: [[@LINE]]|{{ +}}0|

    int x = i;
    return; // CHECK: [[@LINE]]|{{ +}}1|

  } // CHECK: [[@LINE]]|{{ +}}1|
}

struct Error {};

void while_loop() {
  if (false)
    return; // CHECK: [[@LINE]]|{{ +}}0|

  int x = 0;
  while (++x < 10) { // CHECK: [[@LINE]]|{{ +}}3|
    if (x == 1)
      continue; // CHECK: [[@LINE]]|{{ +}}1|

    while (++x < 4) { // CHECK: [[@LINE]]|{{ +}}1|
      if (x == 3)
        break; // CHECK: [[@LINE]]|{{ +}}1|
               // CHECK: [[@LINE]]|{{ +}}0|
      while (++x < 5) {} // CHECK: [[@LINE]]|{{ +}}0|
    } // CHECK: [[@LINE]]|{{ +}}1|

    if (x == 0)
      throw Error(); // CHECK: [[@LINE]]|{{ +}}0|

    while (++x < 9) { // CHECK: [[@LINE]]|{{ +}}6|
      if (x == 0) // CHECK: [[@LINE]]|{{ +}}5|
        break; // CHECK: [[@LINE]]|{{ +}}0|

    }
  }
}

void gotos() {
  if (false)
    goto out; // CHECK: [[@LINE]]|{{ +}}0|

  return;

out: // CHECK: [[@LINE]]|{{ +}}1|
	return;
}

int main() {
  foo(0);
  foo(1);
  bar();
  for_loop();
  while_loop();
  gotos();
  return 0;
}

// MARKER: Marker at 4:7 = 2
// MARKER-NEXT: Highlighted line 17, 5 -> 11
// MARKER-NEXT: Marker at 17:5 = 0
// MARKER-NEXT: Marker at 19:3 = 1
// MARKER-NEXT: Marker at 19:19 = 2
// MARKER-NEXT: Marker at 19:27 = 1
// MARKER-NEXT: Marker at 21:7 = 1
// MARKER-NEXT: Marker at 23:5 = 1
// MARKER-NEXT: Marker at 23:9 = 1
// MARKER-NEXT: Highlighted line 24, 7 -> 12
// MARKER-NEXT: Marker at 24:7 = 0
// MARKER-NEXT: Highlighted line 36, 5 -> 11
// MARKER-NEXT: Marker at 36:5 = 0
// MARKER-NEXT: Marker at 39:10 = 3
// MARKER-NEXT: Marker at 41:7 = 1
// MARKER-NEXT: Marker at 43:5 = 1
// MARKER-NEXT: Marker at 43:12 = 1
// MARKER-NEXT: Highlighted line 45, 14 -> ?
// MARKER-NEXT: Marker at 45:9 = 1
// MARKER-NEXT: Highlighted line 46, 1 -> ?
// MARKER-NEXT: Highlighted line 47, 1 -> 7
// MARKER-NEXT: Highlighted line 47, 7 -> 14
// MARKER-NEXT: Highlighted line 47, 14 -> 21
// MARKER-NEXT: Highlighted line 47, 21 -> 23
// MARKER-NEXT: Highlighted line 47, 23 -> 25
// MARKER-NEXT: Marker at 47:7 = 0
// MARKER-NEXT: Marker at 47:14 = 0
// MARKER-NEXT: Marker at 47:23 = 0
// MARKER-NEXT: Highlighted line 51, 7 -> 20
// MARKER-NEXT: Marker at 51:7 = 0
// MARKER-NEXT: Marker at 53:5 = 1
// MARKER-NEXT: Marker at 53:12 = 6
// MARKER-NEXT: Highlighted line 55, 9 -> 14
// MARKER-NEXT: Highlighted line 63, 5 -> 13
// MARKER-NEXT: Marker at 63:5 = 0
// MARKER-NEXT: Highlighted line 67, 1 -> ?
// MARKER-NEXT: Highlighted line 68, 1 -> 8
// MARKER-NEXT: Highlighted line 68, 8 -> ?
// MARKER-NEXT: Highlighted line 69, 1 -> 2
<|endoftext|>