<commit_before>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2006 Artem Pavlenko
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/

#ifndef RULE_HPP
#define RULE_HPP
// stl
#include <string>
#include <vector>
// boost
#include <boost/shared_ptr.hpp>
#include <boost/variant.hpp>
// mapnik
#include <mapnik/line_symbolizer.hpp>
#include <mapnik/line_pattern_symbolizer.hpp>
#include <mapnik/polygon_symbolizer.hpp>
#include <mapnik/polygon_pattern_symbolizer.hpp>
#include <mapnik/point_symbolizer.hpp>
#include <mapnik/raster_symbolizer.hpp>
#include <mapnik/shield_symbolizer.hpp>
#include <mapnik/text_symbolizer.hpp>
#include <mapnik/filter.hpp>
#include <mapnik/filter_visitor.hpp>

namespace mapnik
{
    inline bool operator==(point_symbolizer const& lhs,
                           point_symbolizer const& rhs)
    {
        return (&lhs == &rhs);
    }
    inline bool operator==(line_symbolizer const& lhs,
                           line_symbolizer const& rhs)
    {
        return (&lhs == &rhs);
    }
    inline bool operator==(line_pattern_symbolizer const& lhs,
                           line_pattern_symbolizer const& rhs)
    {
        return (&lhs == &rhs);
    }

    inline bool operator==(polygon_symbolizer const& lhs,
                           polygon_symbolizer const& rhs)
    {
        return (&lhs == &rhs);
    }

    inline bool operator==(polygon_pattern_symbolizer const& lhs,
                           polygon_pattern_symbolizer const& rhs)
    {
        return (&lhs == &rhs);
    }

    inline bool operator==(raster_symbolizer const& lhs,
                           raster_symbolizer const& rhs)
    {
        return (&lhs == &rhs);
    }

    inline bool operator==(text_symbolizer const& lhs,
                           text_symbolizer const& rhs)
    {
        return (&lhs == &rhs);
    }

    inline bool operator==(shield_symbolizer const& lhs,
                           shield_symbolizer const& rhs)
    {
        return (&lhs == &rhs);
    }

    typedef boost::variant<point_symbolizer,
                           line_symbolizer,
                           line_pattern_symbolizer,
                           polygon_symbolizer,
                           polygon_pattern_symbolizer,
                           raster_symbolizer,
                           shield_symbolizer,
                           text_symbolizer> symbolizer;

    typedef std::vector<symbolizer> symbolizers;

    template <typename FeatureT> class all_filter;

    template <typename FeatureT,template <typename> class Filter>
    class rule
    {
        typedef Filter<FeatureT> filter_type;
        typedef boost::shared_ptr<filter_type> filter_ptr;
    private:

        std::string name_;
        std::string title_;
        std::string abstract_;
        double min_scale_;
        double max_scale_;
        symbolizers syms_;
        filter_ptr filter_;
        bool else_filter_;
    public:
        rule()
            : name_(),
              title_(),
              abstract_(),
              min_scale_(0),
              max_scale_(std::numeric_limits<double>::infinity()),
              syms_(),
              filter_(new all_filter<FeatureT>),
              else_filter_(false) {}

        rule(const std::string& name,
             const std::string& title="",
             double min_scale_denominator=0,
             double max_scale_denominator=std::numeric_limits<double>::infinity())
            : name_(name),
              title_(title),
              min_scale_(min_scale_denominator),
              max_scale_(max_scale_denominator),
              syms_(),
              filter_(new all_filter<FeatureT>),
              else_filter_(false) {}

        rule(const rule& rhs)
            : name_(rhs.name_),
              title_(rhs.title_),
              abstract_(rhs.abstract_),
              min_scale_(rhs.min_scale_),
              max_scale_(rhs.max_scale_),
              syms_(rhs.syms_),
              filter_(rhs.filter_),
              else_filter_(rhs.else_filter_) {}

        rule& operator=(rule const& rhs)
        {
            rule tmp(rhs);
            swap(tmp);
            return *this;
        }
        bool operator==(rule const& other)
        {
            return  (this == &other);
        }

        void set_max_scale(double scale)
        {
            max_scale_=scale;
        }

        double get_max_scale() const
        {
            return max_scale_;
        }

        void set_min_scale(double scale)
        {
            min_scale_=scale;
        }

        double get_min_scale() const
        {
            return min_scale_;
        }

        void set_name(std::string const& name)
        {
            name_=name;
        }

        std::string const& get_name() const
        {
            return name_;
        }

        std::string const& get_title() const
        {
            return  title_;
        }

        void set_title(std::string const& title)
        {
            title_=title;
        }

        void set_abstract(std::string const& abstract)
        {
            abstract_=abstract;
        }

        std::string const& get_abstract() const
        {
            return abstract_;
        }

        void append(const symbolizer& sym)
        {
            syms_.push_back(sym);
        }

        void remove_at(size_t index)
        {
            if (index < syms_.size())
            {
                syms_.erase(syms_.begin()+index);
            }
        }

        const symbolizers& get_symbolizers() const
        {
            return syms_;
        }

        symbolizers::const_iterator begin()
        {
            return syms_.begin();
        }

        symbolizers::const_iterator end()
        {
            return syms_.end();
        }

        void set_filter(const filter_ptr& filter)
        {
            filter_=filter;
        }

        filter_ptr const& get_filter() const
        {
            return filter_;
        }

        void set_else(bool else_filter)
        {
            else_filter_=else_filter;
        }

        bool has_else_filter() const
        {
            return else_filter_;
        }

        bool active(double scale) const
        {
            return ( scale > min_scale_ && scale < max_scale_ );
        }

        void accept(filter_visitor<FeatureT>& v) const
        {
            v.visit(*this);
        }

    private:

        void swap(rule& rhs) throw()
        {
            name_=rhs.name_;
            title_=rhs.title_;
            abstract_=rhs.abstract_;
            min_scale_=rhs.min_scale_;
            max_scale_=rhs.max_scale_;
            syms_=rhs.syms_;
            filter_=rhs.filter_;
            else_filter_=rhs.else_filter_;
        }
    };

    typedef rule<Feature,filter> rule_type;
}

#endif //RULE_HPP
<commit_msg>fixed scale_denominator  <commit_after>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2006 Artem Pavlenko
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/

#ifndef RULE_HPP
#define RULE_HPP
// stl
#include <string>
#include <vector>
// boost
#include <boost/shared_ptr.hpp>
#include <boost/variant.hpp>
// mapnik
#include <mapnik/line_symbolizer.hpp>
#include <mapnik/line_pattern_symbolizer.hpp>
#include <mapnik/polygon_symbolizer.hpp>
#include <mapnik/polygon_pattern_symbolizer.hpp>
#include <mapnik/point_symbolizer.hpp>
#include <mapnik/raster_symbolizer.hpp>
#include <mapnik/shield_symbolizer.hpp>
#include <mapnik/text_symbolizer.hpp>
#include <mapnik/filter.hpp>
#include <mapnik/filter_visitor.hpp>

namespace mapnik
{
    inline bool operator==(point_symbolizer const& lhs,
                           point_symbolizer const& rhs)
    {
        return (&lhs == &rhs);
    }
    inline bool operator==(line_symbolizer const& lhs,
                           line_symbolizer const& rhs)
    {
        return (&lhs == &rhs);
    }
    inline bool operator==(line_pattern_symbolizer const& lhs,
                           line_pattern_symbolizer const& rhs)
    {
        return (&lhs == &rhs);
    }

    inline bool operator==(polygon_symbolizer const& lhs,
                           polygon_symbolizer const& rhs)
    {
        return (&lhs == &rhs);
    }

    inline bool operator==(polygon_pattern_symbolizer const& lhs,
                           polygon_pattern_symbolizer const& rhs)
    {
        return (&lhs == &rhs);
    }

    inline bool operator==(raster_symbolizer const& lhs,
                           raster_symbolizer const& rhs)
    {
        return (&lhs == &rhs);
    }

    inline bool operator==(text_symbolizer const& lhs,
                           text_symbolizer const& rhs)
    {
        return (&lhs == &rhs);
    }

    inline bool operator==(shield_symbolizer const& lhs,
                           shield_symbolizer const& rhs)
    {
        return (&lhs == &rhs);
    }

    typedef boost::variant<point_symbolizer,
                           line_symbolizer,
                           line_pattern_symbolizer,
                           polygon_symbolizer,
                           polygon_pattern_symbolizer,
                           raster_symbolizer,
                           shield_symbolizer,
                           text_symbolizer> symbolizer;

    typedef std::vector<symbolizer> symbolizers;

    template <typename FeatureT> class all_filter;

    template <typename FeatureT,template <typename> class Filter>
    class rule
    {
        typedef Filter<FeatureT> filter_type;
        typedef boost::shared_ptr<filter_type> filter_ptr;
    private:

        std::string name_;
        std::string title_;
        std::string abstract_;
        double min_scale_;
        double max_scale_;
        symbolizers syms_;
        filter_ptr filter_;
        bool else_filter_;
    public:
        rule()
            : name_(),
              title_(),
              abstract_(),
              min_scale_(0),
              max_scale_(std::numeric_limits<double>::infinity()),
              syms_(),
              filter_(new all_filter<FeatureT>),
              else_filter_(false) {}

        rule(const std::string& name,
             const std::string& title="",
             double min_scale_denominator=0,
             double max_scale_denominator=std::numeric_limits<double>::infinity())
            : name_(name),
              title_(title),
              min_scale_(min_scale_denominator),
              max_scale_(max_scale_denominator),
              syms_(),
              filter_(new all_filter<FeatureT>),
              else_filter_(false) {}

        rule(const rule& rhs)
            : name_(rhs.name_),
              title_(rhs.title_),
              abstract_(rhs.abstract_),
              min_scale_(rhs.min_scale_),
              max_scale_(rhs.max_scale_),
              syms_(rhs.syms_),
              filter_(rhs.filter_),
              else_filter_(rhs.else_filter_) {}

        rule& operator=(rule const& rhs)
        {
            rule tmp(rhs);
            swap(tmp);
            return *this;
        }
        bool operator==(rule const& other)
        {
            return  (this == &other);
        }

        void set_max_scale(double scale)
        {
            max_scale_=scale;
        }

        double get_max_scale() const
        {
            return max_scale_;
        }

        void set_min_scale(double scale)
        {
            min_scale_=scale;
        }

        double get_min_scale() const
        {
            return min_scale_;
        }

        void set_name(std::string const& name)
        {
            name_=name;
        }

        std::string const& get_name() const
        {
            return name_;
        }

        std::string const& get_title() const
        {
            return  title_;
        }

        void set_title(std::string const& title)
        {
            title_=title;
        }

        void set_abstract(std::string const& abstract)
        {
            abstract_=abstract;
        }

        std::string const& get_abstract() const
        {
            return abstract_;
        }

        void append(const symbolizer& sym)
        {
            syms_.push_back(sym);
        }

        void remove_at(size_t index)
        {
            if (index < syms_.size())
            {
                syms_.erase(syms_.begin()+index);
            }
        }

        const symbolizers& get_symbolizers() const
        {
            return syms_;
        }

        symbolizers::const_iterator begin()
        {
            return syms_.begin();
        }

        symbolizers::const_iterator end()
        {
            return syms_.end();
        }

        void set_filter(const filter_ptr& filter)
        {
            filter_=filter;
        }

        filter_ptr const& get_filter() const
        {
            return filter_;
        }

        void set_else(bool else_filter)
        {
            else_filter_=else_filter;
        }

        bool has_else_filter() const
        {
            return else_filter_;
        }

        bool active(double scale) const
        {
            return ( scale >= min_scale_ - 1e-6 && scale < max_scale_ + 1e-6);
        }

        void accept(filter_visitor<FeatureT>& v) const
        {
            v.visit(*this);
        }

    private:

        void swap(rule& rhs) throw()
        {
            name_=rhs.name_;
            title_=rhs.title_;
            abstract_=rhs.abstract_;
            min_scale_=rhs.min_scale_;
            max_scale_=rhs.max_scale_;
            syms_=rhs.syms_;
            filter_=rhs.filter_;
            else_filter_=rhs.else_filter_;
        }
    };

    typedef rule<Feature,filter> rule_type;
}

#endif //RULE_HPP
<|endoftext|>


<commit_before>#ifndef _PFASST__UTIL_HPP_
#define _PFASST__UTIL_HPP_

#include <algorithm>
#include <limits>
#include <sstream>
#include <string>
#include <vector>
using namespace std;

#include "pfasst/logging.hpp"

namespace pfasst
{
  /**
   * Compares absolute difference against zero.
   *
   * Takes the absolute value of the difference between @p a and @p b and compares it to the machine precision scaled
   * to the magnitude of @p a and @p b up to the desired precision in units in the last place.
   *
   * @tparam    precision value type of @p a and @p b
   * @param[in] a
   * @param[in] b
   * @param[in] digits    number of digits to compare
   * @ingroup Utilities
   */
  template<typename precision>
  static bool almost_equal(const precision& a, const precision& b,
                           const int digits = numeric_limits<precision>::digits)
  {
    // the machine epsilon has to be scaled to the magnitude of the values used
    // and multiplied by the desired precision in ULPs (units in the last place)
    return abs(a - b) < numeric_limits<precision>::epsilon() * abs(a + b) * digits
    // unless the result is subnormal
           || abs(a - b) < numeric_limits<precision>::min();
  }

  /**
   * Compares against smalles machine epsilon.
   *
   * Takes the absolute value of @p a and compares it against `std::numeric_limits<precision>::epsilon()`.
   *
   * @tparam    precision value type of @p a, e.g. `double`
   * @param[in] a         value to compare
   * @returns   `true` if @p a is closer to zero than the machine precision, `false` otherwise.
   *
   * @ingroup Utilities
   */
  template<typename precision>
  static bool almost_zero(const precision& a)
  {
    return abs(a) < numeric_limits<precision>::epsilon();
  }

  /**
   * A string representation of `std::vector`.
   *
   * Uses `operator<<` on each element of @p vec and seperates each element with @p sep .
   *
   * @tparam    T   type of the vector's elements
   * @param[in] vec vector to print
   * @param[in] sep seperator placed between each element of @p vec
   * @returns string representation of @p vec
   *
   * **Example**:
   * @code{.cpp}
   * std::vector<double> vec{0.0, 0.5, 0.1};
   * join(vec, ", ");  // ==> "[0.0, 0.5, 0.1]"
   * @endcode
   *
   * @ingroup Utilities
   */
  template<typename T>
  static string join(const vector<T>& vec, const string& sep)
  {
    stringstream out;
    out << "[" << LOG_FLOAT;
    for (size_t i = 0; i < vec.size() - 1; ++i) {
      out << vec[i] << sep;
    }
    out << vec.back();
    out << "]";
    return out.str();
  }
}  // ::pfasst

#endif  // _PFASST__UTIL_HPP_
<commit_msg>util: make join function a noop when logging is disabled<commit_after>#ifndef _PFASST__UTIL_HPP_
#define _PFASST__UTIL_HPP_

#include <algorithm>
#include <limits>
#include <sstream>
#include <string>
#include <vector>
using namespace std;

#include "pfasst/logging.hpp"

namespace pfasst
{
  /**
   * Compares absolute difference against zero.
   *
   * Takes the absolute value of the difference between @p a and @p b and compares it to the machine precision scaled
   * to the magnitude of @p a and @p b up to the desired precision in units in the last place.
   *
   * @tparam    precision value type of @p a and @p b
   * @param[in] a
   * @param[in] b
   * @param[in] digits    number of digits to compare
   * @ingroup Utilities
   */
  template<typename precision>
  static bool almost_equal(const precision& a, const precision& b,
                           const int digits = numeric_limits<precision>::digits)
  {
    // the machine epsilon has to be scaled to the magnitude of the values used
    // and multiplied by the desired precision in ULPs (units in the last place)
    return abs(a - b) < numeric_limits<precision>::epsilon() * abs(a + b) * digits
    // unless the result is subnormal
           || abs(a - b) < numeric_limits<precision>::min();
  }

  /**
   * Compares against smalles machine epsilon.
   *
   * Takes the absolute value of @p a and compares it against `std::numeric_limits<precision>::epsilon()`.
   *
   * @tparam    precision value type of @p a, e.g. `double`
   * @param[in] a         value to compare
   * @returns   `true` if @p a is closer to zero than the machine precision, `false` otherwise.
   *
   * @ingroup Utilities
   */
  template<typename precision>
  static bool almost_zero(const precision& a)
  {
    return abs(a) < numeric_limits<precision>::epsilon();
  }

  /**
   * A string representation of `std::vector`.
   *
   * Uses `operator<<` on each element of @p vec and seperates each element with @p sep .
   *
   * @tparam    T   type of the vector's elements
   * @param[in] vec vector to print
   * @param[in] sep seperator placed between each element of @p vec
   * @returns string representation of @p vec
   *
   * **Example**:
   * @code{.cpp}
   * std::vector<double> vec{0.0, 0.5, 0.1};
   * join(vec, ", ");  // ==> "[0.0, 0.5, 0.1]"
   * @endcode
   *
   * @note This funtion is a noop when compiling with `PFASST_NO_LOGGING` defined.
   *
   * @ingroup Utilities
   */
  template<typename T>
  static string join(const vector<T>& vec, const string& sep)
  {
#ifndef PFASST_NO_LOGGING
    stringstream out;
    out << "[" << LOG_FLOAT;
    for (size_t i = 0; i < vec.size() - 1; ++i) {
      out << vec[i] << sep;
    }
    out << vec.back();
    out << "]";
    return out.str();
#else
    return "";
#endif
  }
}  // ::pfasst

#endif  // _PFASST__UTIL_HPP_
<|endoftext|>


<commit_before>// Copyright (c) 2015-2018 Daniel Frey
// Please see LICENSE for license or visit https://github.com/taocpp/sequences/

#ifndef TAO_SEQ_SUM_HPP
#define TAO_SEQ_SUM_HPP

#include <type_traits>
#include <utility>

#include "config.hpp"
#include "integer_sequence.hpp"

#ifndef TAO_FOLD_EXPRESSIONS
#include "make_integer_sequence.hpp"
#include <cstddef>
#endif

namespace tao
{
   namespace seq
   {

#ifdef TAO_FOLD_EXPRESSIONS

      template< typename T, T... Ns >
      struct sum
         : std::integral_constant< T, ( Ns + ... + T( 0 ) ) >
      {
      };

#else

      namespace impl
      {
         template< std::size_t, std::size_t N >
         struct chars
         {
            char dummy[ N + 1 ];
         };

         template< typename, std::size_t... >
         struct collector;

         template< std::size_t... Is, std::size_t... Ns >
         struct collector< index_sequence< Is... >, Ns... >
            : chars< Is, Ns >...
         {
         };

         template< typename T, T lhs, T rhs >
         struct sum_minus_helper
         {
            using type = std::integral_constant< T, lhs - rhs >;
         };

         template< bool, std::size_t N, typename T, T... Ns >
         struct sum
         {
            using type = typename sum_minus_helper< T, T( sizeof( collector< make_index_sequence< N >, ( ( Ns > 0 ) ? Ns : 0 )... > ) ), T( sizeof( collector< make_index_sequence< N >, ( ( Ns < 0 ) ? -Ns : 0 )... > ) ) >::type;
         };

         template< std::size_t N, typename T, T... Ns >
         struct sum< true, N, T, Ns... >
         {
            using type = std::integral_constant< T, T( sizeof( collector< make_index_sequence< N >, ( ( Ns > 0 ) ? Ns : 0 )... > ) - N ) >;
         };

      }  // namespace impl

      template< typename T, T... Ns >
      struct sum
         : impl::sum< std::is_unsigned< T >::value, sizeof...( Ns ) + 1, T, Ns..., 0 >::type
      {
      };

#endif

      template< typename T, T... Ns >
      struct sum< integer_sequence< T, Ns... > >
         : sum< T, Ns... >
      {
      };

   }  // namespace seq

}  // namespace tao

#endif
<commit_msg>Try make VS 2015 happy<commit_after>// Copyright (c) 2015-2018 Daniel Frey
// Please see LICENSE for license or visit https://github.com/taocpp/sequences/

#ifndef TAO_SEQ_SUM_HPP
#define TAO_SEQ_SUM_HPP

#include <type_traits>
#include <utility>

#include "config.hpp"
#include "integer_sequence.hpp"

#ifndef TAO_FOLD_EXPRESSIONS
#include "make_integer_sequence.hpp"
#include <cstddef>
#endif

namespace tao
{
   namespace seq
   {

#ifdef TAO_FOLD_EXPRESSIONS

      template< typename T, T... Ns >
      struct sum
         : std::integral_constant< T, ( Ns + ... + T( 0 ) ) >
      {
      };

#else

      namespace impl
      {
         template< std::size_t, std::size_t N >
         struct chars
         {
            char dummy[ N + 1 ];
         };

         template< typename, std::size_t... >
         struct collector;

         template< std::size_t... Is, std::size_t... Ns >
         struct collector< index_sequence< Is... >, Ns... >
            : chars< Is, Ns >...
         {
         };

         template< typename T, T v >
         struct unary_minus_t
         {
            using type = std::integral_constant< T, -v >;
         };

         template< typename T, T v >
         using unary_minus = typename unary_minus_t< T, v >::type;

         template< bool, std::size_t N, typename T, T... Ns >
         struct sum
         {
            using type = std::integral_constant< T, T( sizeof( collector< make_index_sequence< N >, ( ( Ns > 0 ) ? Ns : 0 )... > ) ) - T( sizeof( collector< make_index_sequence< N >, ( ( Ns < 0 ) ? unary_minus< T, Ns >::value : 0 )... > ) ) >;
         };

         template< std::size_t N, typename T, T... Ns >
         struct sum< true, N, T, Ns... >
         {
            using type = std::integral_constant< T, T( sizeof( collector< make_index_sequence< N >, ( ( Ns > 0 ) ? Ns : 0 )... > ) - N ) >;
         };

      }  // namespace impl

      template< typename T, T... Ns >
      struct sum
         : impl::sum< std::is_unsigned< T >::value, sizeof...( Ns ) + 1, T, Ns..., 0 >::type
      {
      };

#endif

      template< typename T, T... Ns >
      struct sum< integer_sequence< T, Ns... > >
         : sum< T, Ns... >
      {
      };

   }  // namespace seq

}  // namespace tao

#endif
<|endoftext|>


<commit_before>/************************************************************************/
/*                                                                      */
/*               Copyright 1998-2000 by Ullrich Koethe                  */
/*       Cognitive Systems Group, University of Hamburg, Germany        */
/*                                                                      */
/*    This file is part of the VIGRA computer vision library.           */
/*    You may use, modify, and distribute this software according       */
/*    to the terms stated in the LICENSE file included in               */
/*    the VIGRA distribution.                                           */
/*                                                                      */
/*    The VIGRA Website is                                              */
/*        http://kogs-www.informatik.uni-hamburg.de/~koethe/vigra/      */
/*    Please direct questions, bug reports, and contributions to        */
/*        koethe@informatik.uni-hamburg.de                              */
/*                                                                      */
/*  THIS SOFTWARE IS PROVIDED AS IS AND WITHOUT ANY EXPRESS OR          */
/*  IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED      */
/*  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. */
/*                                                                      */
/************************************************************************/

#ifndef VIGRA_ERROR_HXX
#define VIGRA_ERROR_HXX

#include <stdio.h>
#include "vigra/config.hxx"

#ifdef _MSC_VER
#  define snprintf _snprintf
#endif

/*! \page ErrorReporting Error Reporting

    \#include "vigra/error.hxx"

    VIGRA defines the following exception classes:

    \code
    namespace vigra {
        class ContractViolation : public std::exception;
        class PreconditionViolation : public ContractViolation;
        class PostconditionViolation : public ContractViolation;
        class InvariantViolation : public ContractViolation;
    }
    \endcode

    The following associated macros throw the corresponding exception if
    their PREDICATE evaluates to '<TT>false<TT>':

    \code
    vigra_precondition(PREDICATE, MESSAGE);
    vigra_postcondition(PREDICATE, MESSAGE);
    vigra_invariant(PREDICATE, MESSAGE);
    \endcode

    The MESSAGE is passed to the exception and can be retrieved via
    the overloaded member function '<TT>exception.what()<TT>'. If the compiler
    flag '<TT>NDEBUG<TT>' is  not defined, the file name and line number of
    the error are automatically included in the message.

    The following macro

    \code
    vigra_fail(MESSAGE);
    \endcode

    unconditionally throws a '<TT>std::runtime_error<TT>' constructed from the message
    (along with file name and line number, if NDEBUG is not set).

     Usage:

    Include-File:
    "vigra/error.hxx"

    Namespace: vigra (except for the macros, of course)

    \code
    int main(int argc, char ** argv)
    {
        try
        {
            const char* input_file_name = argv[1];

            // read input image
            vigra::ImageImportInfo info(input_file_name);

            // fail if input image is not grayscale
            vigra_precondition(info.isGrayscale(), "Input image must be grayscale");

            ...// process image
        }
        catch (std::exception & e)
        {
            std::cerr << e.what() << std::endl; // print message
            return 1;
        }

        return 0;
    }
    \endcode

    \brief Exceptions and assertions provided by VIGRA
**/

namespace vigra {

class ContractViolation : public StdException
{
  protected:
#ifdef NO_INLINE_STATIC_CONST_DEFINITION
    enum { bufsize_ = 1100 };
#else
    static const int bufsize_ = 1100;
#endif

  public:
    ContractViolation(char const * message)
    {
        snprintf(what_, bufsize_, "%s", message);
    }

    ContractViolation()
    {
        what_[0] = 0;
    }

    ContractViolation(ContractViolation const & o)
    : StdException(o)
    {
        snprintf(what_, bufsize_, "%s", o.what_);
    }

    virtual const char * what() const throw()
    {
        return what_;
    }

    char what_[bufsize_];
};

class PreconditionViolation : public ContractViolation
{
  public:
    PreconditionViolation(char const * message, const char * file, int line)
    {
        snprintf( what_, bufsize_, "\nPrecondition violation!\n%s\n(%s:%d)\n", message, file, line);
    }

    PreconditionViolation(char const * message)
    {
        snprintf( what_, bufsize_, "\nPrecondition violation!\n%s\n", message);
    }
};

class PostconditionViolation : public ContractViolation
{
  public:
    PostconditionViolation(char const * message, const char * file, int line)
    {
        snprintf( what_, bufsize_, "\nPostcondition violation!\n%s\n(%s:%d)\n", message, file, line);
    }

    PostconditionViolation(char const * message)
    {
        snprintf( what_, bufsize_, "\nPostcondition violation!\n%s\n", message);
    }
};

class InvariantViolation : public ContractViolation
{
  public:
    InvariantViolation(char const * message, const char * file, int line)
    {
        snprintf( what_, bufsize_, "\nInvariant violation!\n%s\n(%s:%d)\n", message, file, line);
    }

    InvariantViolation(char const * message)
    {
        snprintf( what_, bufsize_, "\nInvariant violation!\n%s\n", message);
    }
};

#ifndef NDEBUG

inline
void throw_invariant_error(bool predicate, char const * message, char const * file, int line)
{
    if(!predicate)
	   throw vigra::InvariantViolation(message, file, line);
}

inline
void throw_precondition_error(bool predicate, char const * message, char const * file, int line)
{
    if(!predicate)
	   throw vigra::PreconditionViolation(message, file, line);
}

inline
void throw_postcondition_error(bool predicate, char const * message, char const * file, int line)
{
    if(!predicate)
	   throw vigra::PostconditionViolation(message, file, line);
}

inline
void throw_runtime_error(char const * message, char const * file, int line)
{
    char buf[1000];
    snprintf(buf, 1000, "%s (%s:%d)", message, file, line);
    throw std::runtime_error(buf);
}

#define vigra_precondition(PREDICATE, MESSAGE) vigra::throw_precondition_error((PREDICATE), MESSAGE, __FILE__, __LINE__)

#define vigra_postcondition(PREDICATE, MESSAGE) vigra::throw_postcondition_error((PREDICATE), MESSAGE, __FILE__, __LINE__)

#define vigra_invariant(PREDICATE, MESSAGE) vigra::throw_invariant_error((PREDICATE), MESSAGE, __FILE__, __LINE__)

#define vigra_fail(MESSAGE) vigra::throw_runtime_error(MESSAGE, __FILE__, __LINE__)

#else // NDEBUG

inline
void throw_invariant_error(bool predicate, char const * message)
{
    if(!predicate)
	   throw vigra::InvariantViolation(message);
}

inline
void throw_precondition_error(bool predicate, char const * message)
{
    if(!predicate)
	   throw vigra::PreconditionViolation(message);
}

inline
void throw_postcondition_error(bool predicate, char const * message)
{
    if(!predicate)
	   throw vigra::PostconditionViolation(message);
}

#define vigra_precondition(PREDICATE, MESSAGE) vigra::throw_precondition_error((PREDICATE), MESSAGE)

#define vigra_postcondition(PREDICATE, MESSAGE) vigra::throw_postcondition_error((PREDICATE), MESSAGE)

#define vigra_invariant(PREDICATE, MESSAGE) vigra::throw_invariant_error((PREDICATE), MESSAGE)

#define vigra_fail(MESSAGE) throw std::runtime_error(MESSAGE)

#endif // NDEBUG

} // namespace vigra

#endif // VIGRA_ERROR_HXX
<commit_msg>replaced snprintf() with sprintf() for portability<commit_after>/************************************************************************/
/*                                                                      */
/*               Copyright 1998-2000 by Ullrich Koethe                  */
/*       Cognitive Systems Group, University of Hamburg, Germany        */
/*                                                                      */
/*    This file is part of the VIGRA computer vision library.           */
/*    You may use, modify, and distribute this software according       */
/*    to the terms stated in the LICENSE file included in               */
/*    the VIGRA distribution.                                           */
/*                                                                      */
/*    The VIGRA Website is                                              */
/*        http://kogs-www.informatik.uni-hamburg.de/~koethe/vigra/      */
/*    Please direct questions, bug reports, and contributions to        */
/*        koethe@informatik.uni-hamburg.de                              */
/*                                                                      */
/*  THIS SOFTWARE IS PROVIDED AS IS AND WITHOUT ANY EXPRESS OR          */
/*  IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED      */
/*  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. */
/*                                                                      */
/************************************************************************/

#ifndef VIGRA_ERROR_HXX
#define VIGRA_ERROR_HXX

#include <stdexcept>
#include <stdio.h>
#include "vigra/config.hxx"

/*! \page ErrorReporting Error Reporting

    \#include "vigra/error.hxx"

    VIGRA defines the following exception classes:

    \code
    namespace vigra {
        class ContractViolation : public std::exception;
        class PreconditionViolation : public ContractViolation;
        class PostconditionViolation : public ContractViolation;
        class InvariantViolation : public ContractViolation;
    }
    \endcode

    The following associated macros throw the corresponding exception if
    their PREDICATE evaluates to '<TT>false<TT>':

    \code
    vigra_precondition(PREDICATE, MESSAGE);
    vigra_postcondition(PREDICATE, MESSAGE);
    vigra_invariant(PREDICATE, MESSAGE);
    \endcode

    The MESSAGE is passed to the exception and can be retrieved via
    the overloaded member function '<TT>exception.what()<TT>'. If the compiler
    flag '<TT>NDEBUG<TT>' is  not defined, the file name and line number of
    the error are automatically included in the message.

    The following macro

    \code
    vigra_fail(MESSAGE);
    \endcode

    unconditionally throws a '<TT>std::runtime_error<TT>' constructed from the message
    (along with file name and line number, if NDEBUG is not set).

     Usage:

    Include-File:
    "vigra/error.hxx"

    Namespace: vigra (except for the macros, of course)

    \code
    int main(int argc, char ** argv)
    {
        try
        {
            const char* input_file_name = argv[1];

            // read input image
            vigra::ImageImportInfo info(input_file_name);

            // fail if input image is not grayscale
            vigra_precondition(info.isGrayscale(), "Input image must be grayscale");

            ...// process image
        }
        catch (std::exception & e)
        {
            std::cerr << e.what() << std::endl; // print message
            return 1;
        }

        return 0;
    }
    \endcode

    \brief Exceptions and assertions provided by VIGRA
**/

namespace vigra {

class ContractViolation : public StdException
{
  public:
    ContractViolation(char const * prefix, char const * message,
                      char const * file, int line)
    {
        sprintf(what_, "\n%.30s\n%.900s\n(%.100s:%d)\n", prefix, message, file, line);
    }

    ContractViolation(char const * prefix, char const * message)
    {
        sprintf(what_, "\n%.30s\n%.900s\n", prefix, message);
    }

    virtual const char * what() const throw()
    {
        return what_;
    }

  private:
    enum { bufsize_ = 1100 };
    char what_[bufsize_];
};

class PreconditionViolation : public ContractViolation
{
  public:
    PreconditionViolation(char const * message, const char * file, int line)
    : ContractViolation("Precondition violation!", message, file, line)
    {}

    PreconditionViolation(char const * message)
    : ContractViolation("Precondition violation!", message)
    {}
};

class PostconditionViolation : public ContractViolation
{
  public:
    PostconditionViolation(char const * message, const char * file, int line)
    : ContractViolation("Postcondition violation!", message, file, line)
    {}

    PostconditionViolation(char const * message)
    : ContractViolation("Postcondition violation!", message)
    {}
};

class InvariantViolation : public ContractViolation
{
  public:
    InvariantViolation(char const * message, const char * file, int line)
    : ContractViolation("Invariant violation!", message, file, line)
    {}

    InvariantViolation(char const * message)
    : ContractViolation("Invariant violation!", message)
    {}
};

#ifndef NDEBUG

inline
void throw_invariant_error(bool predicate, char const * message, char const * file, int line)
{
    if(!predicate)
	   throw vigra::InvariantViolation(message, file, line);
}

inline
void throw_precondition_error(bool predicate, char const * message, char const * file, int line)
{
    if(!predicate)
	   throw vigra::PreconditionViolation(message, file, line);
}

inline
void throw_postcondition_error(bool predicate, char const * message, char const * file, int line)
{
    if(!predicate)
	   throw vigra::PostconditionViolation(message, file, line);
}

inline
void throw_runtime_error(char const * message, char const * file, int line)
{
    char what_[1100];
    sprintf(what_, "\n%.30s\n%.900s\n(%.100s:%d)\n");
    throw std::runtime_error(what_);
}

#define vigra_precondition(PREDICATE, MESSAGE) vigra::throw_precondition_error((PREDICATE), MESSAGE, __FILE__, __LINE__)

#define vigra_postcondition(PREDICATE, MESSAGE) vigra::throw_postcondition_error((PREDICATE), MESSAGE, __FILE__, __LINE__)

#define vigra_invariant(PREDICATE, MESSAGE) vigra::throw_invariant_error((PREDICATE), MESSAGE, __FILE__, __LINE__)

#define vigra_fail(MESSAGE) vigra::throw_runtime_error(MESSAGE, __FILE__, __LINE__)

#else // NDEBUG

inline
void throw_invariant_error(bool predicate, char const * message)
{
    if(!predicate)
	   throw vigra::InvariantViolation(message);
}

inline
void throw_precondition_error(bool predicate, char const * message)
{
    if(!predicate)
	   throw vigra::PreconditionViolation(message);
}

inline
void throw_postcondition_error(bool predicate, char const * message)
{
    if(!predicate)
	   throw vigra::PostconditionViolation(message);
}

#define vigra_precondition(PREDICATE, MESSAGE) vigra::throw_precondition_error((PREDICATE), MESSAGE)

#define vigra_postcondition(PREDICATE, MESSAGE) vigra::throw_postcondition_error((PREDICATE), MESSAGE)

#define vigra_invariant(PREDICATE, MESSAGE) vigra::throw_invariant_error((PREDICATE), MESSAGE)

#define vigra_fail(MESSAGE) throw std::runtime_error(MESSAGE)

#endif // NDEBUG

} // namespace vigra

#endif // VIGRA_ERROR_HXX
<|endoftext|>


<commit_before>/**
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *  http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#ifndef __STOUT_UUID_HPP__
#define __STOUT_UUID_HPP__

#include <assert.h>

#include <sstream>
#include <string>

#include <boost/uuid/uuid.hpp>
#include <boost/uuid/uuid_generators.hpp>
#include <boost/uuid/uuid_io.hpp>

#include <stout/thread_local.hpp>

struct UUID : boost::uuids::uuid
{
public:
  static UUID random()
  {
    static THREAD_LOCAL boost::uuids::random_generator* generator =
      new boost::uuids::random_generator();

    return UUID((*generator)());
  }

  static UUID fromBytes(const std::string& s)
  {
    boost::uuids::uuid uuid;
    memcpy(&uuid, s.data(), s.size());
    return UUID(uuid);
  }

  static UUID fromString(const std::string& s)
  {
    boost::uuids::uuid uuid;
    std::istringstream in(s);
    in >> uuid;
    return UUID(uuid);
  }

  std::string toBytes() const
  {
    assert(sizeof(data) == size());
    return std::string(reinterpret_cast<const char*>(data), sizeof(data));
  }

  std::string toString() const
  {
    std::ostringstream out;
    out << *this;
    return out.str();
  }

private:
  explicit UUID(const boost::uuids::uuid& uuid)
    : boost::uuids::uuid(uuid) {}
};

namespace std {

template <>
struct hash<UUID>
{
  typedef size_t result_type;

  typedef UUID argument_type;

  result_type operator()(const argument_type& uuid) const
  {
    return boost::uuids::hash_value(uuid);
  }
};

} // namespace std {

#endif // __STOUT_UUID_HPP__
<commit_msg>Fixed a compiler error in UUID on OSX.<commit_after>/**
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *  http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#ifndef __STOUT_UUID_HPP__
#define __STOUT_UUID_HPP__

#include <assert.h>

#include <sstream>
#include <string>

#include <boost/uuid/uuid.hpp>
#include <boost/uuid/uuid_generators.hpp>
#include <boost/uuid/uuid_io.hpp>

#include <stout/thread_local.hpp>

struct UUID : boost::uuids::uuid
{
public:
  static UUID random()
  {
    static THREAD_LOCAL boost::uuids::random_generator* generator = NULL;

    if (generator == NULL) {
      generator = new boost::uuids::random_generator();
    }

    return UUID((*generator)());
  }

  static UUID fromBytes(const std::string& s)
  {
    boost::uuids::uuid uuid;
    memcpy(&uuid, s.data(), s.size());
    return UUID(uuid);
  }

  static UUID fromString(const std::string& s)
  {
    boost::uuids::uuid uuid;
    std::istringstream in(s);
    in >> uuid;
    return UUID(uuid);
  }

  std::string toBytes() const
  {
    assert(sizeof(data) == size());
    return std::string(reinterpret_cast<const char*>(data), sizeof(data));
  }

  std::string toString() const
  {
    std::ostringstream out;
    out << *this;
    return out.str();
  }

private:
  explicit UUID(const boost::uuids::uuid& uuid)
    : boost::uuids::uuid(uuid) {}
};

namespace std {

template <>
struct hash<UUID>
{
  typedef size_t result_type;

  typedef UUID argument_type;

  result_type operator()(const argument_type& uuid) const
  {
    return boost::uuids::hash_value(uuid);
  }
};

} // namespace std {

#endif // __STOUT_UUID_HPP__
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2019 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "src/trace_processor/importers/common/clock_tracker.h"

#include <inttypes.h>

#include <algorithm>
#include <queue>

#include "perfetto/base/logging.h"
#include "perfetto/ext/base/hash.h"
#include "src/trace_processor/storage/trace_storage.h"
#include "src/trace_processor/types/trace_processor_context.h"

#include "protos/perfetto/common/builtin_clock.pbzero.h"
#include "protos/perfetto/trace/clock_snapshot.pbzero.h"

namespace perfetto {
namespace trace_processor {

using Clock = protos::pbzero::ClockSnapshot::Clock;

ClockTracker::ClockTracker(TraceProcessorContext* ctx)
    : context_(ctx),
      trace_time_clock_id_(protos::pbzero::BUILTIN_CLOCK_BOOTTIME) {}

ClockTracker::~ClockTracker() = default;

void ClockTracker::AddSnapshot(const std::vector<ClockValue>& clocks) {
  const auto snapshot_id = cur_snapshot_id_++;

  // Clear the cache
  static_assert(std::is_trivial<decltype(cache_)>::value, "must be trivial");
  memset(&cache_[0], 0, sizeof(cache_));

  // Compute the fingerprint of the snapshot by hashing all clock ids. This is
  // used by the clock pathfinding logic.
  base::Hash hasher;
  for (const auto& clock : clocks)
    hasher.Update(clock.clock_id);
  const auto snapshot_hash = static_cast<SnapshotHash>(hasher.digest());

  // Add a new entry in each clock's snapshot vector.
  for (const auto& clock : clocks) {
    ClockId clock_id = clock.clock_id;
    ClockDomain& domain = clocks_[clock_id];
    if (domain.snapshots.empty()) {
      if (clock.is_incremental && !ClockIsSeqScoped(clock_id)) {
        PERFETTO_ELOG("Clock sync error: the global clock with id=%" PRIu64
                      " cannot use incremental encoding; this is only "
                      "supported for sequence-scoped clocks.",
                      clock_id);
        context_->storage->IncrementStats(stats::invalid_clock_snapshots);
        return;
      }
      domain.unit_multiplier_ns = clock.unit_multiplier_ns;
      domain.is_incremental = clock.is_incremental;
    } else if (PERFETTO_UNLIKELY(
                   domain.unit_multiplier_ns != clock.unit_multiplier_ns ||
                   domain.is_incremental != clock.is_incremental)) {
      PERFETTO_ELOG("Clock sync error: the clock domain with id=%" PRIu64
                    " (unit=%" PRIu64
                    ", incremental=%d), was previously registered with "
                    "different properties (unit=%" PRIu64 ", incremental=%d).",
                    clock_id, clock.unit_multiplier_ns, clock.is_incremental,
                    domain.unit_multiplier_ns, domain.is_incremental);
      context_->storage->IncrementStats(stats::invalid_clock_snapshots);
      return;
    }
    const int64_t timestamp_ns =
        clock.absolute_timestamp * domain.unit_multiplier_ns;
    domain.last_timestamp_ns = timestamp_ns;

    ClockSnapshots& vect = domain.snapshots[snapshot_hash];
    if (!vect.snapshot_ids.empty() &&
        PERFETTO_UNLIKELY(vect.snapshot_ids.back() == snapshot_id)) {
      PERFETTO_ELOG("Clock sync error: duplicate clock domain with id=%" PRIu64
                    " at snapshot %" PRIu32 ".",
                    clock_id, snapshot_id);
      context_->storage->IncrementStats(stats::invalid_clock_snapshots);
      return;
    }

    // Clock ids in the range [64, 128) are sequence-scoped and must be
    // translated to global ids via SeqScopedClockIdToGlobal() before calling
    // this function.
    PERFETTO_DCHECK(!IsReservedSeqScopedClockId(clock_id));

    // Snapshot IDs must be always monotonic.
    PERFETTO_DCHECK(vect.snapshot_ids.empty() ||
                    vect.snapshot_ids.back() < snapshot_id);

    if (!vect.timestamps_ns.empty() &&
        timestamp_ns < vect.timestamps_ns.back()) {
      // Clock is not monotonic.

      if (clock_id == trace_time_clock_id_) {
        // The trace clock cannot be non-monotonic.
        PERFETTO_ELOG("Clock sync error: the trace clock (id=%" PRIu64
                      ") is not monotonic at snapshot %" PRIu32 ". %" PRId64
                      " not >= %" PRId64 ".",
                      clock_id, snapshot_id, timestamp_ns,
                      vect.timestamps_ns.back());
        context_->storage->IncrementStats(stats::invalid_clock_snapshots);
        return;
      }

      PERFETTO_DLOG("Detected non-monotonic clock with ID %" PRIu64, clock_id);

      // For the other clocks the best thing we can do is mark it as
      // non-monotonic and refuse to use it as a source clock in the resolution
      // graph. We can still use it as a target clock, but not viceversa.
      // The concrete example is the CLOCK_REALTIME going 1h backwards during
      // daylight saving. We can still answer the question "what was the
      // REALTIME timestamp when BOOTTIME was X?" but we can't answer the
      // opposite question because there can be two valid BOOTTIME(s) for the
      // same REALTIME instant because of the 1:many relationship.
      non_monotonic_clocks_.insert(clock_id);

      // Erase all edges from the graph that start from this clock (but keep the
      // ones that end on this clock).
      auto begin = graph_.lower_bound(ClockGraphEdge{clock_id, 0, 0});
      auto end = graph_.lower_bound(ClockGraphEdge{clock_id + 1, 0, 0});
      graph_.erase(begin, end);
    }
    vect.snapshot_ids.emplace_back(snapshot_id);
    vect.timestamps_ns.emplace_back(timestamp_ns);
  }

  // Create graph edges for all the possible tuples of clocks in this snapshot.
  // If the snapshot contains clock a, b, c, d create edges [ab, ac, ad, bc, bd,
  // cd] and the symmetrical ones [ba, ca, da, bc, db, dc].
  // This is to store the information: Clock A is syncable to Clock B via the
  // snapshots of type (hash).
  // Clocks that were previously marked as non-monotonic won't be added as
  // valid sources.
  for (auto it1 = clocks.begin(); it1 != clocks.end(); ++it1) {
    auto it2 = it1;
    ++it2;
    for (; it2 != clocks.end(); ++it2) {
      if (!non_monotonic_clocks_.count(it1->clock_id))
        graph_.emplace(it1->clock_id, it2->clock_id, snapshot_hash);

      if (!non_monotonic_clocks_.count(it2->clock_id))
        graph_.emplace(it2->clock_id, it1->clock_id, snapshot_hash);
    }
  }
}

// Finds the shortest clock resolution path in the graph that allows to
// translate a timestamp from |src| to |target| clocks.
// The return value looks like the following: "If you want to convert a
// timestamp from clock C1 to C2 you need to first convert C1 -> C3 using the
// snapshot hash A, then convert C3 -> C2 via snapshot hash B".
ClockTracker::ClockPath ClockTracker::FindPath(ClockId src, ClockId target) {
  // This is a classic breadth-first search. Each node in the queue holds also
  // the full path to reach that node.
  // We assume the graph is acyclic, if it isn't the ClockPath::kMaxLen will
  // stop the search anyways.
  PERFETTO_CHECK(src != target);
  std::queue<ClockPath> queue;
  queue.emplace(src);

  while (!queue.empty()) {
    ClockPath cur_path = queue.front();
    queue.pop();

    const ClockId cur_clock_id = cur_path.last;
    if (cur_clock_id == target)
      return cur_path;

    if (cur_path.len >= ClockPath::kMaxLen)
      continue;

    // Expore all the adjacent clocks.
    // The lower_bound() below returns an iterator to the first edge that starts
    // on |cur_clock_id|. The edges are sorted by (src, target, hash).
    for (auto it = std::lower_bound(graph_.begin(), graph_.end(),
                                    ClockGraphEdge(cur_clock_id, 0, 0));
         it != graph_.end() && std::get<0>(*it) == cur_clock_id; ++it) {
      ClockId next_clock_id = std::get<1>(*it);
      SnapshotHash hash = std::get<2>(*it);
      queue.push(ClockPath(cur_path, next_clock_id, hash));
    }
  }
  return ClockPath();  // invalid path.
}

base::Optional<int64_t> ClockTracker::ConvertSlowpath(ClockId src_clock_id,
                                                      int64_t src_timestamp,
                                                      ClockId target_clock_id) {
  PERFETTO_DCHECK(!IsReservedSeqScopedClockId(src_clock_id));
  PERFETTO_DCHECK(!IsReservedSeqScopedClockId(target_clock_id));

  context_->storage->IncrementStats(stats::clock_sync_cache_miss);

  ClockPath path = FindPath(src_clock_id, target_clock_id);
  if (!path.valid()) {
    PERFETTO_DLOG("No path from clock %" PRIu64 " to %" PRIu64
                  " at timestamp %" PRId64,
                  src_clock_id, target_clock_id, src_timestamp);
    context_->storage->IncrementStats(stats::clock_sync_failure);
    return base::nullopt;
  }

  // We can cache only single-path resolutions between two clocks.
  // Caching multi-path resolutions is harder because the (src,target) tuple
  // is not enough as a cache key: at any step the |ns| value can yield to a
  // different choice of the next snapshot. Multi-path resolutions don't seem
  // too frequent these days, so we focus only on caching the more frequent
  // one-step resolutions (typically from any clock to the trace clock).
  const bool cacheable = path.len == 1;
  CachedClockPath cache_entry{};

  // Iterate trough the path found and translate timestamps onto the new clock
  // domain on each step, until the target domain is reached.
  ClockDomain* src_domain = GetClock(src_clock_id);
  int64_t ns = src_domain->ToNs(src_timestamp);
  for (uint32_t i = 0; i < path.len; ++i) {
    const ClockGraphEdge edge = path.at(i);
    ClockDomain* cur_clock = GetClock(std::get<0>(edge));
    ClockDomain* next_clock = GetClock(std::get<1>(edge));
    const SnapshotHash hash = std::get<2>(edge);

    // Find the closest timestamp within the snapshots of the source clock.
    const ClockSnapshots& cur_snap = cur_clock->GetSnapshot(hash);
    const auto& ts_vec = cur_snap.timestamps_ns;
    auto it = std::upper_bound(ts_vec.begin(), ts_vec.end(), ns);
    if (it != ts_vec.begin())
      --it;

    // Now lookup the snapshot id that matches the closest timestamp.
    size_t index = static_cast<size_t>(std::distance(ts_vec.begin(), it));
    PERFETTO_DCHECK(index < ts_vec.size());
    PERFETTO_DCHECK(cur_snap.snapshot_ids.size() == ts_vec.size());
    uint32_t snapshot_id = cur_snap.snapshot_ids[index];

    // And use that to retrieve the corresponding time in the next clock domain.
    // The snapshot id must exist in the target clock domain. If it doesn't
    // either the hash logic or the pathfinding logic are bugged.
    const ClockSnapshots& next_snap = next_clock->GetSnapshot(hash);
    auto next_it = std::lower_bound(next_snap.snapshot_ids.begin(),
                                    next_snap.snapshot_ids.end(), snapshot_id);
    PERFETTO_DCHECK(next_it != next_snap.snapshot_ids.end() &&
                    *next_it == snapshot_id);
    size_t next_index = static_cast<size_t>(
        std::distance(next_snap.snapshot_ids.begin(), next_it));
    PERFETTO_DCHECK(next_index < next_snap.snapshot_ids.size());
    int64_t next_timestamp_ns = next_snap.timestamps_ns[next_index];

    // The translated timestamp is the relative delta of the source timestamp
    // from the closest snapshot found (ns - *it), plus the timestamp in
    // the new clock domain for the same snapshot id.
    const int64_t adj = next_timestamp_ns - *it;
    ns += adj;

    // On the first iteration, keep track of the bounds for the cache entry.
    // This will allow future Convert() calls to skip the pathfinder logic
    // as long as the query stays within the bound.
    if (cacheable) {
      PERFETTO_DCHECK(i == 0);
      const int64_t kInt64Min = std::numeric_limits<int64_t>::min();
      const int64_t kInt64Max = std::numeric_limits<int64_t>::max();
      cache_entry.min_ts_ns = it == ts_vec.begin() ? kInt64Min : *it;
      auto ubound = it + 1;
      cache_entry.max_ts_ns = ubound == ts_vec.end() ? kInt64Max : *ubound;
      cache_entry.translation_ns = adj;
    }

    // The last clock in the path must be the target clock.
    PERFETTO_DCHECK(i < path.len - 1 || std::get<1>(edge) == target_clock_id);
  }

  if (cacheable) {
    cache_entry.src = src_clock_id;
    cache_entry.src_domain = src_domain;
    cache_entry.target = target_clock_id;
    cache_[rnd_() % cache_.size()] = cache_entry;
  }

  return ns;
}

}  // namespace trace_processor
}  // namespace perfetto
<commit_msg>Remove unnecessarily standard-incompliant code. am: 1142652106 am: 666c4e0ea4<commit_after>/*
 * Copyright (C) 2019 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "src/trace_processor/importers/common/clock_tracker.h"

#include <inttypes.h>

#include <algorithm>
#include <queue>

#include "perfetto/base/logging.h"
#include "perfetto/ext/base/hash.h"
#include "src/trace_processor/storage/trace_storage.h"
#include "src/trace_processor/types/trace_processor_context.h"

#include "protos/perfetto/common/builtin_clock.pbzero.h"
#include "protos/perfetto/trace/clock_snapshot.pbzero.h"

namespace perfetto {
namespace trace_processor {

using Clock = protos::pbzero::ClockSnapshot::Clock;

ClockTracker::ClockTracker(TraceProcessorContext* ctx)
    : context_(ctx),
      trace_time_clock_id_(protos::pbzero::BUILTIN_CLOCK_BOOTTIME) {}

ClockTracker::~ClockTracker() = default;

void ClockTracker::AddSnapshot(const std::vector<ClockValue>& clocks) {
  const auto snapshot_id = cur_snapshot_id_++;

  // Clear the cache
  cache_.fill({});

  // Compute the fingerprint of the snapshot by hashing all clock ids. This is
  // used by the clock pathfinding logic.
  base::Hash hasher;
  for (const auto& clock : clocks)
    hasher.Update(clock.clock_id);
  const auto snapshot_hash = static_cast<SnapshotHash>(hasher.digest());

  // Add a new entry in each clock's snapshot vector.
  for (const auto& clock : clocks) {
    ClockId clock_id = clock.clock_id;
    ClockDomain& domain = clocks_[clock_id];
    if (domain.snapshots.empty()) {
      if (clock.is_incremental && !ClockIsSeqScoped(clock_id)) {
        PERFETTO_ELOG("Clock sync error: the global clock with id=%" PRIu64
                      " cannot use incremental encoding; this is only "
                      "supported for sequence-scoped clocks.",
                      clock_id);
        context_->storage->IncrementStats(stats::invalid_clock_snapshots);
        return;
      }
      domain.unit_multiplier_ns = clock.unit_multiplier_ns;
      domain.is_incremental = clock.is_incremental;
    } else if (PERFETTO_UNLIKELY(
                   domain.unit_multiplier_ns != clock.unit_multiplier_ns ||
                   domain.is_incremental != clock.is_incremental)) {
      PERFETTO_ELOG("Clock sync error: the clock domain with id=%" PRIu64
                    " (unit=%" PRIu64
                    ", incremental=%d), was previously registered with "
                    "different properties (unit=%" PRIu64 ", incremental=%d).",
                    clock_id, clock.unit_multiplier_ns, clock.is_incremental,
                    domain.unit_multiplier_ns, domain.is_incremental);
      context_->storage->IncrementStats(stats::invalid_clock_snapshots);
      return;
    }
    const int64_t timestamp_ns =
        clock.absolute_timestamp * domain.unit_multiplier_ns;
    domain.last_timestamp_ns = timestamp_ns;

    ClockSnapshots& vect = domain.snapshots[snapshot_hash];
    if (!vect.snapshot_ids.empty() &&
        PERFETTO_UNLIKELY(vect.snapshot_ids.back() == snapshot_id)) {
      PERFETTO_ELOG("Clock sync error: duplicate clock domain with id=%" PRIu64
                    " at snapshot %" PRIu32 ".",
                    clock_id, snapshot_id);
      context_->storage->IncrementStats(stats::invalid_clock_snapshots);
      return;
    }

    // Clock ids in the range [64, 128) are sequence-scoped and must be
    // translated to global ids via SeqScopedClockIdToGlobal() before calling
    // this function.
    PERFETTO_DCHECK(!IsReservedSeqScopedClockId(clock_id));

    // Snapshot IDs must be always monotonic.
    PERFETTO_DCHECK(vect.snapshot_ids.empty() ||
                    vect.snapshot_ids.back() < snapshot_id);

    if (!vect.timestamps_ns.empty() &&
        timestamp_ns < vect.timestamps_ns.back()) {
      // Clock is not monotonic.

      if (clock_id == trace_time_clock_id_) {
        // The trace clock cannot be non-monotonic.
        PERFETTO_ELOG("Clock sync error: the trace clock (id=%" PRIu64
                      ") is not monotonic at snapshot %" PRIu32 ". %" PRId64
                      " not >= %" PRId64 ".",
                      clock_id, snapshot_id, timestamp_ns,
                      vect.timestamps_ns.back());
        context_->storage->IncrementStats(stats::invalid_clock_snapshots);
        return;
      }

      PERFETTO_DLOG("Detected non-monotonic clock with ID %" PRIu64, clock_id);

      // For the other clocks the best thing we can do is mark it as
      // non-monotonic and refuse to use it as a source clock in the resolution
      // graph. We can still use it as a target clock, but not viceversa.
      // The concrete example is the CLOCK_REALTIME going 1h backwards during
      // daylight saving. We can still answer the question "what was the
      // REALTIME timestamp when BOOTTIME was X?" but we can't answer the
      // opposite question because there can be two valid BOOTTIME(s) for the
      // same REALTIME instant because of the 1:many relationship.
      non_monotonic_clocks_.insert(clock_id);

      // Erase all edges from the graph that start from this clock (but keep the
      // ones that end on this clock).
      auto begin = graph_.lower_bound(ClockGraphEdge{clock_id, 0, 0});
      auto end = graph_.lower_bound(ClockGraphEdge{clock_id + 1, 0, 0});
      graph_.erase(begin, end);
    }
    vect.snapshot_ids.emplace_back(snapshot_id);
    vect.timestamps_ns.emplace_back(timestamp_ns);
  }

  // Create graph edges for all the possible tuples of clocks in this snapshot.
  // If the snapshot contains clock a, b, c, d create edges [ab, ac, ad, bc, bd,
  // cd] and the symmetrical ones [ba, ca, da, bc, db, dc].
  // This is to store the information: Clock A is syncable to Clock B via the
  // snapshots of type (hash).
  // Clocks that were previously marked as non-monotonic won't be added as
  // valid sources.
  for (auto it1 = clocks.begin(); it1 != clocks.end(); ++it1) {
    auto it2 = it1;
    ++it2;
    for (; it2 != clocks.end(); ++it2) {
      if (!non_monotonic_clocks_.count(it1->clock_id))
        graph_.emplace(it1->clock_id, it2->clock_id, snapshot_hash);

      if (!non_monotonic_clocks_.count(it2->clock_id))
        graph_.emplace(it2->clock_id, it1->clock_id, snapshot_hash);
    }
  }
}

// Finds the shortest clock resolution path in the graph that allows to
// translate a timestamp from |src| to |target| clocks.
// The return value looks like the following: "If you want to convert a
// timestamp from clock C1 to C2 you need to first convert C1 -> C3 using the
// snapshot hash A, then convert C3 -> C2 via snapshot hash B".
ClockTracker::ClockPath ClockTracker::FindPath(ClockId src, ClockId target) {
  // This is a classic breadth-first search. Each node in the queue holds also
  // the full path to reach that node.
  // We assume the graph is acyclic, if it isn't the ClockPath::kMaxLen will
  // stop the search anyways.
  PERFETTO_CHECK(src != target);
  std::queue<ClockPath> queue;
  queue.emplace(src);

  while (!queue.empty()) {
    ClockPath cur_path = queue.front();
    queue.pop();

    const ClockId cur_clock_id = cur_path.last;
    if (cur_clock_id == target)
      return cur_path;

    if (cur_path.len >= ClockPath::kMaxLen)
      continue;

    // Expore all the adjacent clocks.
    // The lower_bound() below returns an iterator to the first edge that starts
    // on |cur_clock_id|. The edges are sorted by (src, target, hash).
    for (auto it = std::lower_bound(graph_.begin(), graph_.end(),
                                    ClockGraphEdge(cur_clock_id, 0, 0));
         it != graph_.end() && std::get<0>(*it) == cur_clock_id; ++it) {
      ClockId next_clock_id = std::get<1>(*it);
      SnapshotHash hash = std::get<2>(*it);
      queue.push(ClockPath(cur_path, next_clock_id, hash));
    }
  }
  return ClockPath();  // invalid path.
}

base::Optional<int64_t> ClockTracker::ConvertSlowpath(ClockId src_clock_id,
                                                      int64_t src_timestamp,
                                                      ClockId target_clock_id) {
  PERFETTO_DCHECK(!IsReservedSeqScopedClockId(src_clock_id));
  PERFETTO_DCHECK(!IsReservedSeqScopedClockId(target_clock_id));

  context_->storage->IncrementStats(stats::clock_sync_cache_miss);

  ClockPath path = FindPath(src_clock_id, target_clock_id);
  if (!path.valid()) {
    PERFETTO_DLOG("No path from clock %" PRIu64 " to %" PRIu64
                  " at timestamp %" PRId64,
                  src_clock_id, target_clock_id, src_timestamp);
    context_->storage->IncrementStats(stats::clock_sync_failure);
    return base::nullopt;
  }

  // We can cache only single-path resolutions between two clocks.
  // Caching multi-path resolutions is harder because the (src,target) tuple
  // is not enough as a cache key: at any step the |ns| value can yield to a
  // different choice of the next snapshot. Multi-path resolutions don't seem
  // too frequent these days, so we focus only on caching the more frequent
  // one-step resolutions (typically from any clock to the trace clock).
  const bool cacheable = path.len == 1;
  CachedClockPath cache_entry{};

  // Iterate trough the path found and translate timestamps onto the new clock
  // domain on each step, until the target domain is reached.
  ClockDomain* src_domain = GetClock(src_clock_id);
  int64_t ns = src_domain->ToNs(src_timestamp);
  for (uint32_t i = 0; i < path.len; ++i) {
    const ClockGraphEdge edge = path.at(i);
    ClockDomain* cur_clock = GetClock(std::get<0>(edge));
    ClockDomain* next_clock = GetClock(std::get<1>(edge));
    const SnapshotHash hash = std::get<2>(edge);

    // Find the closest timestamp within the snapshots of the source clock.
    const ClockSnapshots& cur_snap = cur_clock->GetSnapshot(hash);
    const auto& ts_vec = cur_snap.timestamps_ns;
    auto it = std::upper_bound(ts_vec.begin(), ts_vec.end(), ns);
    if (it != ts_vec.begin())
      --it;

    // Now lookup the snapshot id that matches the closest timestamp.
    size_t index = static_cast<size_t>(std::distance(ts_vec.begin(), it));
    PERFETTO_DCHECK(index < ts_vec.size());
    PERFETTO_DCHECK(cur_snap.snapshot_ids.size() == ts_vec.size());
    uint32_t snapshot_id = cur_snap.snapshot_ids[index];

    // And use that to retrieve the corresponding time in the next clock domain.
    // The snapshot id must exist in the target clock domain. If it doesn't
    // either the hash logic or the pathfinding logic are bugged.
    const ClockSnapshots& next_snap = next_clock->GetSnapshot(hash);
    auto next_it = std::lower_bound(next_snap.snapshot_ids.begin(),
                                    next_snap.snapshot_ids.end(), snapshot_id);
    PERFETTO_DCHECK(next_it != next_snap.snapshot_ids.end() &&
                    *next_it == snapshot_id);
    size_t next_index = static_cast<size_t>(
        std::distance(next_snap.snapshot_ids.begin(), next_it));
    PERFETTO_DCHECK(next_index < next_snap.snapshot_ids.size());
    int64_t next_timestamp_ns = next_snap.timestamps_ns[next_index];

    // The translated timestamp is the relative delta of the source timestamp
    // from the closest snapshot found (ns - *it), plus the timestamp in
    // the new clock domain for the same snapshot id.
    const int64_t adj = next_timestamp_ns - *it;
    ns += adj;

    // On the first iteration, keep track of the bounds for the cache entry.
    // This will allow future Convert() calls to skip the pathfinder logic
    // as long as the query stays within the bound.
    if (cacheable) {
      PERFETTO_DCHECK(i == 0);
      const int64_t kInt64Min = std::numeric_limits<int64_t>::min();
      const int64_t kInt64Max = std::numeric_limits<int64_t>::max();
      cache_entry.min_ts_ns = it == ts_vec.begin() ? kInt64Min : *it;
      auto ubound = it + 1;
      cache_entry.max_ts_ns = ubound == ts_vec.end() ? kInt64Max : *ubound;
      cache_entry.translation_ns = adj;
    }

    // The last clock in the path must be the target clock.
    PERFETTO_DCHECK(i < path.len - 1 || std::get<1>(edge) == target_clock_id);
  }

  if (cacheable) {
    cache_entry.src = src_clock_id;
    cache_entry.src_domain = src_domain;
    cache_entry.target = target_clock_id;
    cache_[rnd_() % cache_.size()] = cache_entry;
  }

  return ns;
}

}  // namespace trace_processor
}  // namespace perfetto
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: stringdata.hxx,v $
 *
 *  $Revision: 1.2 $
 *
 *  last change: $Author: np $ $Date: 2002-11-01 12:18:50 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library 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
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser 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
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#ifndef COSV_STRINGDATA_HXX
#define COSV_STRINGDATA_HXX

#include <cosv/str_types.hxx>

namespace csv
{

/** @tpl CHAR
    The expression CHAR(0) has to be valid.
*/
template <class CHAR>
class StringData
{
  public:
    typedef StringData          self;

    typedef str::size           size_type;
    typedef str::position       position_type;

    // LIFECYCLE
                        StringData();
    /** @precond i_pData != 0
        @precond i_nValidLength <= strlen(i_pData)
    */
                        StringData(
                            const CHAR *        i_pData,
                            size_type           i_nValidLength );
                        ~StringData();
    // OPERATORS

    // OPERATIONS

    // INQUIRY
    const CHAR *        Data() const;

    /** @returns the allocated number of CHAR.
        This may be different from the number of bytes.
        There is actually allocated one more CHAR,
        which is guaranteed to be CHAR(0) in all circumstances.
    */
    size_type           Size() const;

  private:
    /*  Because this is used only within a refcounted structure,
        these functions are forbidden - at least yet.
    */
                        StringData(const self&);
    self &              operator=(const self&);

    // DATA
    DYN CHAR *          dpData;
    size_type           nSize;      /// The allocated size - 1 (for the finishing 0).
};

// IMPLEMENTATION

template <class CHAR>
StringData<CHAR>::StringData()
    :   dpData( new CHAR[1] ),
        nSize(0)
{
    *dpData = CHAR(0);
}

template <class CHAR>
StringData<CHAR>::StringData( const CHAR *        i_pData,
                              size_type           i_nValidLength )
    :   dpData( new CHAR[i_nValidLength + 1] ),
        nSize(i_nValidLength)
{
    memcpy( dpData, i_pData, i_nValidLength * sizeof(CHAR) );
    dpData[nSize] = CHAR(0);
}

template <class CHAR>
StringData<CHAR>::~StringData()
{
    delete [] dpData;
}

template <class CHAR>
const CHAR *
StringData<CHAR>::Data() const
{
    return dpData;
}

template <class CHAR>
typename StringData<CHAR>::size_type
StringData<CHAR>::Size() const
{
    return nSize;
}

}   // namespace csv

#endif

<commit_msg>INTEGRATION: CWS ooo19126 (1.2.102); FILE MERGED 2005/09/05 14:08:53 rt 1.2.102.1: #i54170# Change license header: remove SISSL<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: stringdata.hxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-08 07:58:25 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library 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
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser 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
 *
 ************************************************************************/

#ifndef COSV_STRINGDATA_HXX
#define COSV_STRINGDATA_HXX

#include <cosv/str_types.hxx>

namespace csv
{

/** @tpl CHAR
    The expression CHAR(0) has to be valid.
*/
template <class CHAR>
class StringData
{
  public:
    typedef StringData          self;

    typedef str::size           size_type;
    typedef str::position       position_type;

    // LIFECYCLE
                        StringData();
    /** @precond i_pData != 0
        @precond i_nValidLength <= strlen(i_pData)
    */
                        StringData(
                            const CHAR *        i_pData,
                            size_type           i_nValidLength );
                        ~StringData();
    // OPERATORS

    // OPERATIONS

    // INQUIRY
    const CHAR *        Data() const;

    /** @returns the allocated number of CHAR.
        This may be different from the number of bytes.
        There is actually allocated one more CHAR,
        which is guaranteed to be CHAR(0) in all circumstances.
    */
    size_type           Size() const;

  private:
    /*  Because this is used only within a refcounted structure,
        these functions are forbidden - at least yet.
    */
                        StringData(const self&);
    self &              operator=(const self&);

    // DATA
    DYN CHAR *          dpData;
    size_type           nSize;      /// The allocated size - 1 (for the finishing 0).
};

// IMPLEMENTATION

template <class CHAR>
StringData<CHAR>::StringData()
    :   dpData( new CHAR[1] ),
        nSize(0)
{
    *dpData = CHAR(0);
}

template <class CHAR>
StringData<CHAR>::StringData( const CHAR *        i_pData,
                              size_type           i_nValidLength )
    :   dpData( new CHAR[i_nValidLength + 1] ),
        nSize(i_nValidLength)
{
    memcpy( dpData, i_pData, i_nValidLength * sizeof(CHAR) );
    dpData[nSize] = CHAR(0);
}

template <class CHAR>
StringData<CHAR>::~StringData()
{
    delete [] dpData;
}

template <class CHAR>
const CHAR *
StringData<CHAR>::Data() const
{
    return dpData;
}

template <class CHAR>
typename StringData<CHAR>::size_type
StringData<CHAR>::Size() const
{
    return nSize;
}

}   // namespace csv

#endif

<|endoftext|>


<commit_before>/*
 * The Apache Software License, Version 1.1
 *
 *
 * Copyright (c) 1999-2002 The Apache Software Foundation.  All rights
 * reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * 3. The end-user documentation included with the redistribution,
 *    if any, must include the following acknowledgment:
 *       "This product includes software developed by the
 *        Apache Software Foundation (http://www.apache.org/)."
 *    Alternately, this acknowledgment may appear in the software itself,
 *    if and wherever such third-party acknowledgments normally appear.
 *
 * 4. The names "Xalan" and "Apache Software Foundation" must
 *    not be used to endorse or promote products derived from this
 *    software without prior written permission. For written
 *    permission, please contact apache@apache.org.
 *
 * 5. Products derived from this software may not be called "Apache",
 *    nor may "Apache" appear in their name, without prior written
 *    permission of the Apache Software Foundation.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Apache Software Foundation and was
 * originally based on software copyright (c) 1999, International
 * Business Machines, Inc., http://www.ibm.com.  For more
 * information on the Apache Software Foundation, please see
 * <http://www.apache.org/>.
 */
#include "XercesDOMException.hpp"

#include <cassert>

XALAN_CPP_NAMESPACE_BEGIN

template<class ExceptionType>
static XercesDOMException::ExceptionCode
translateErrorCode(ExceptionType	theException)
{
	XercesDOMException::ExceptionCode	theXalanCode = XercesDOMException::UNKNOWN_ERR;

	switch(theException.code)
	{
	case ExceptionType::INDEX_SIZE_ERR:
		theXalanCode = XercesDOMException::INDEX_SIZE_ERR;
		break;

	case ExceptionType::DOMSTRING_SIZE_ERR:
		theXalanCode = XercesDOMException::DOMSTRING_SIZE_ERR;
		break;

	case ExceptionType::HIERARCHY_REQUEST_ERR:
		theXalanCode = XercesDOMException::HIERARCHY_REQUEST_ERR;
		break;

	case ExceptionType::WRONG_DOCUMENT_ERR:
		theXalanCode = XercesDOMException::WRONG_DOCUMENT_ERR;
		break;

	case ExceptionType::INVALID_CHARACTER_ERR:
		theXalanCode = XercesDOMException::INVALID_CHARACTER_ERR;
		break;

	case ExceptionType::NO_DATA_ALLOWED_ERR:
		theXalanCode = XercesDOMException::NO_DATA_ALLOWED_ERR;
		break;

	case ExceptionType::NO_MODIFICATION_ALLOWED_ERR:
		theXalanCode = XercesDOMException::NO_MODIFICATION_ALLOWED_ERR;
		break;

	case ExceptionType::NOT_FOUND_ERR:
		theXalanCode = XercesDOMException::NOT_FOUND_ERR;
		break;

	case ExceptionType::NOT_SUPPORTED_ERR:
		theXalanCode = XercesDOMException::INDEX_SIZE_ERR;
		break;

	case ExceptionType::INUSE_ATTRIBUTE_ERR:
		theXalanCode = XercesDOMException::INUSE_ATTRIBUTE_ERR;
		break;

	case ExceptionType::INVALID_STATE_ERR:
		theXalanCode = XercesDOMException::INVALID_STATE_ERR;
		break;

	case ExceptionType::SYNTAX_ERR:
		theXalanCode = XercesDOMException::SYNTAX_ERR;
		break;

	case ExceptionType::INVALID_MODIFICATION_ERR:
		theXalanCode = XercesDOMException::INVALID_MODIFICATION_ERR;
		break;

	case ExceptionType::NAMESPACE_ERR:
		theXalanCode = XercesDOMException::NAMESPACE_ERR;
		break;

	case ExceptionType::INVALID_ACCESS_ERR:
		theXalanCode = XercesDOMException::INVALID_ACCESS_ERR;
		break;

	default:
		assert(false);
		break;
	};

	return theXalanCode;
}

XercesDOMException::XercesDOMException(ExceptionCode 	code) :
	XalanDOMException(code)
{
}

XercesDOMException::XercesDOMException(const DOM_DOMExceptionType&	theException) :
	XalanDOMException(translateErrorCode(theException))
{
}

#if XERCES_VERSION_MAJOR >= 2
XercesDOMException::XercesDOMException(const DOMExceptionType&	theException) :
	XalanDOMException(translateErrorCode(theException))
{
}
#endif

XercesDOMException::XercesDOMException(const XercesDOMException&	theSource) :
	XalanDOMException(theSource)
{
}

XercesDOMException::~XercesDOMException()
{
}

XALAN_CPP_NAMESPACE_END
<commit_msg>Work-around for the Intel v6 compiler.<commit_after>/*
 * The Apache Software License, Version 1.1
 *
 *
 * Copyright (c) 1999-2002 The Apache Software Foundation.  All rights
 * reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * 3. The end-user documentation included with the redistribution,
 *    if any, must include the following acknowledgment:
 *       "This product includes software developed by the
 *        Apache Software Foundation (http://www.apache.org/)."
 *    Alternately, this acknowledgment may appear in the software itself,
 *    if and wherever such third-party acknowledgments normally appear.
 *
 * 4. The names "Xalan" and "Apache Software Foundation" must
 *    not be used to endorse or promote products derived from this
 *    software without prior written permission. For written
 *    permission, please contact apache@apache.org.
 *
 * 5. Products derived from this software may not be called "Apache",
 *    nor may "Apache" appear in their name, without prior written
 *    permission of the Apache Software Foundation.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Apache Software Foundation and was
 * originally based on software copyright (c) 1999, International
 * Business Machines, Inc., http://www.ibm.com.  For more
 * information on the Apache Software Foundation, please see
 * <http://www.apache.org/>.
 */
#include "XercesDOMException.hpp"

#include <cassert>

XALAN_CPP_NAMESPACE_BEGIN

template<class ExceptionType>
static XercesDOMException::ExceptionCode
translateErrorCode(ExceptionType	theException)
{
	// Ugly hack for a bug in the Intel v6 compiler...
#if __INTEL_COMPILER <= 600
	return XercesDOMException::ExceptionCode(theException.code);
#else
	XercesDOMException::ExceptionCode	theXalanCode = XercesDOMException::UNKNOWN_ERR;

	switch(theException.code)
	{
	case ExceptionType::INDEX_SIZE_ERR:
		theXalanCode = XercesDOMException::INDEX_SIZE_ERR;
		break;

	case ExceptionType::DOMSTRING_SIZE_ERR:
		theXalanCode = XercesDOMException::DOMSTRING_SIZE_ERR;
		break;

	case ExceptionType::HIERARCHY_REQUEST_ERR:
		theXalanCode = XercesDOMException::HIERARCHY_REQUEST_ERR;
		break;

	case ExceptionType::WRONG_DOCUMENT_ERR:
		theXalanCode = XercesDOMException::WRONG_DOCUMENT_ERR;
		break;

	case ExceptionType::INVALID_CHARACTER_ERR:
		theXalanCode = XercesDOMException::INVALID_CHARACTER_ERR;
		break;

	case ExceptionType::NO_DATA_ALLOWED_ERR:
		theXalanCode = XercesDOMException::NO_DATA_ALLOWED_ERR;
		break;

	case ExceptionType::NO_MODIFICATION_ALLOWED_ERR:
		theXalanCode = XercesDOMException::NO_MODIFICATION_ALLOWED_ERR;
		break;

	case ExceptionType::NOT_FOUND_ERR:
		theXalanCode = XercesDOMException::NOT_FOUND_ERR;
		break;

	case ExceptionType::NOT_SUPPORTED_ERR:
		theXalanCode = XercesDOMException::INDEX_SIZE_ERR;
		break;

	case ExceptionType::INUSE_ATTRIBUTE_ERR:
		theXalanCode = XercesDOMException::INUSE_ATTRIBUTE_ERR;
		break;

	case ExceptionType::INVALID_STATE_ERR:
		theXalanCode = XercesDOMException::INVALID_STATE_ERR;
		break;

	case ExceptionType::SYNTAX_ERR:
		theXalanCode = XercesDOMException::SYNTAX_ERR;
		break;

	case ExceptionType::INVALID_MODIFICATION_ERR:
		theXalanCode = XercesDOMException::INVALID_MODIFICATION_ERR;
		break;

	case ExceptionType::NAMESPACE_ERR:
		theXalanCode = XercesDOMException::NAMESPACE_ERR;
		break;

	case ExceptionType::INVALID_ACCESS_ERR:
		theXalanCode = XercesDOMException::INVALID_ACCESS_ERR;
		break;

	default:
		assert(false);
		break;
	};

	return theXalanCode;
#endif
}

XercesDOMException::XercesDOMException(ExceptionCode 	code) :
	XalanDOMException(code)
{
}

XercesDOMException::XercesDOMException(const DOM_DOMExceptionType&	theException) :
	XalanDOMException(translateErrorCode(theException))
{
}

#if XERCES_VERSION_MAJOR >= 2
XercesDOMException::XercesDOMException(const DOMExceptionType&	theException) :
	XalanDOMException(translateErrorCode(theException))
{
}
#endif

XercesDOMException::XercesDOMException(const XercesDOMException&	theSource) :
	XalanDOMException(theSource)
{
}

XercesDOMException::~XercesDOMException()
{
}

XALAN_CPP_NAMESPACE_END
<|endoftext|>


<commit_before>//separate adjacent input strings by a space.
#include <iostream>
#include <string>

using std::string;
using std::cin;
using std::cout;
using std::endl;

int main()
{
  string largeStr;
  string str;
  while (cin >> str)
  {
    if (largeStr.empty())
      largeStr += str;
    else
      largeStr += " " + str;
  }

  cout << "The concatenated string is " << largeStr << endl;

  return 0;
}
<commit_msg>Update ex3_5b.cpp<commit_after>//separate adjacent input strings by a space.
#include <iostream>
#include <string>

using std::string;
using std::cin;
using std::cout;
using std::endl;

int main()
{
    string str;
    for (string buff; cin >> buff; str += (str.empty() ? "" : " ") + buff);
    cout << "The concatenated string is " << str << endl;

    return 0;
}
<|endoftext|>


<commit_before>#include <iostream>
#include <initializer_list>

int sum(std::initializer_list<int> il)
{
    int sum = 0;
    for (auto i : il) sum += i;
    return sum;
}

int main(void)
{
    std::cout << sum({1, 2, 3, 4, 5}) << std::endl;
    return 0;
}
<commit_msg>Update ex6_27.cpp<commit_after>#include <iostream>
#include <initializer_list>

int sum(std::initializer_list<int> il)
{
    int sum = 0;
    for (auto i : il) sum += i;
    return sum;
}

int main()
{
    std::cout << sum({1, 2, 3, 4, 5}) << std::endl;
    return 0;
}
<|endoftext|>


<commit_before>//! @Yue Wang
//!
//! Exercise 9.50:
//! Write a program to process a vector<string>s whose elements represent
//! integral values.
//! Produce the sum of all the elements in that vector.
//! Change the program so that it sums of strings that represent floating-point
//! values.
//!

#include <iostream>
#include <string>
#include <vector>

int sum_for_int(const std::vector<std::string> &v)
{
    int sum = 0;
    for (auto const& s : v) sum += std::stoi(s);
    return sum;
}

float sum_for_float(const std::vector<std::string> &v)
{
    float sum = 0.0;
    for (auto const& s : v) sum += std::stof(s);
    return sum;
}

int main()
{
    std::vector<std::string> v = {"1", "2", "3", "4.5"};
    std::cout << sum_for_int(v) << std::endl;
    std::cout << sum_for_float(v) << std::endl;

    return 0;
}
<commit_msg>Update ex9_50.cpp<commit_after>//! @Yue Wang
//!
//! Exercise 9.50:
//! Write a program to process a vector<string> whose elements represent integral values.
//! Produce the sum of all the elements in that vector.
//! Change the program so that it sums of strings that represent floating-point values.
//!

#include <iostream>
#include <string>
#include <vector>
using namespace std;

int sum_for_int(const vector<string> &svec)
{
    int sum=0;
    for(const auto &s : svec)
        sum+=stoi(s);
    return sum;

}

float sum_for_float(const vector<string> &svec)
{
    float sum=0.0;
    for(const auto &s:svec)
        sum+=stof(s);
    return sum;
}

int main()
{
    vector<string> svec{"1", "2", "3", "4.5"};
    cout<<sum_for_int(svec)<<endl;
    cout<<sum_for_float(svec)<<endl;
}
<|endoftext|>