<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
 *
 *****************************************************************************/

//$Id: graphics.hpp 39 2005-04-10 20:39:53Z pavlenko $

#ifndef GRAPHICS_HPP
#define GRAPHICS_HPP
// stl
#include <cmath>
#include <string>
#include <cassert>
// mapnik
#include <mapnik/color.hpp>
#include <mapnik/gamma.hpp>
#include <mapnik/image_data.hpp>
#include <mapnik/envelope.hpp>
#include <mapnik/image_view.hpp>

namespace mapnik
{
    class MAPNIK_DECL Image32
    {
    private:
        unsigned width_;
        unsigned height_;
        Color background_;
        ImageData32 data_;
    public:
        Image32(int width,int height);
        Image32(Image32 const& rhs);
        ~Image32();
        void setBackground(Color const& background);
        const Color& getBackground() const;
        const ImageData32& data() const;

        inline ImageData32& data()
        {
            return data_;
        }

        inline const unsigned char* raw_data() const
        {
            return data_.getBytes();
        }

        inline unsigned char* raw_data()
        {
            return data_.getBytes();
        }

        inline image_view<ImageData32> get_view(unsigned x,unsigned y, unsigned w,unsigned h)
        {
            return image_view<ImageData32>(x,y,w,h,data_);
        }

        void saveToFile(const std::string& file,const std::string& format="auto");

    private:

        inline bool checkBounds(unsigned x, unsigned y) const
        {
            return (x < width_ && y < height_);
        }

    public:
        inline void setPixel(int x,int y,unsigned int rgba)
        {
            if (checkBounds(x,y))
            {
                data_(x,y)=rgba;
            }
        }
        inline void blendPixel(int x,int y,unsigned int rgba1,int t)
        {
            if (checkBounds(x,y))
            {
                unsigned rgba0 = data_(x,y);
                unsigned a1 = t;//(rgba1 >> 24) & 0xff;
                if (a1 == 0) return;
                unsigned r1 = rgba1 & 0xff;
                unsigned g1 = (rgba1 >> 8 ) & 0xff;
                unsigned b1 = (rgba1 >> 16) & 0xff;

                unsigned a0 = (rgba0 >> 24) & 0xff;
                unsigned r0 = (rgba0 & 0xff) * a0;
                unsigned g0 = ((rgba0 >> 8 ) & 0xff) * a0;
                unsigned b0 = ((rgba0 >> 16) & 0xff) * a0;

                a0 = ((a1 + a0) << 8) - a0*a1;

                r0 = ((((r1 << 8) - r0) * a1 + (r0 << 8)) / a0);
                g0 = ((((g1 << 8) - g0) * a1 + (g0 << 8)) / a0);
                b0 = ((((b1 << 8) - b0) * a1 + (b0 << 8)) / a0);
                a0 = a0 >> 8;
                data_(x,y)= (a0 << 24)| (b0 << 16) |  (g0 << 8) | (r0) ;
            }
        }

        inline unsigned width() const
        {
            return width_;
        }

        inline unsigned height() const
        {
            return height_;
        }

        inline void set_rectangle(int x0,int y0,ImageData32 const& data)
        {
            Envelope<int> ext0(0,0,width_,height_);
            Envelope<int> ext1(x0,y0,x0+data.width(),y0+data.height());

            if (ext0.intersects(ext1))
            {
               Envelope<int> box = ext0.intersect(ext1);
               for (int y = box.miny(); y < box.maxy(); ++y)
               {
                  unsigned int* row_to =  data_.getRow(y);
                  unsigned int const * row_from = data.getRow(y-y0);

                  for (int x = box.minx(); x < box.maxx(); ++x)
                  {
                     if (row_to[x-x0] & 0xff000000)
                     {
                        row_to[x-x0] = row_from[x-x0];
                     }
                  }
               }
            }
        }

        inline void set_rectangle_alpha(int x0,int y0,const ImageData32& data)
        {
            Envelope<int> ext0(0,0,width_,height_);
            Envelope<int> ext1(x0,y0,x0 + data.width(),y0 + data.height());

            if (ext0.intersects(ext1))
            {
                Envelope<int> box = ext0.intersect(ext1);
                for (int y = box.miny(); y < box.maxy(); ++y)
                {
                   unsigned int* row_to =  data_.getRow(y);
                   unsigned int const * row_from = data.getRow(y-y0);
                   for (int x = box.minx(); x < box.maxx(); ++x)
                   {
                      unsigned rgba0 = row_to[x];
                      unsigned rgba1 = row_from[x-x0];

                      unsigned a1 = (rgba1 >> 24) & 0xff;
                      if (a1 == 0) continue;
                      unsigned r1 = rgba1 & 0xff;
                      unsigned g1 = (rgba1 >> 8 ) & 0xff;
                      unsigned b1 = (rgba1 >> 16) & 0xff;

                      unsigned a0 = (rgba0 >> 24) & 0xff;
                      unsigned r0 = (rgba0 & 0xff) * a0;
                      unsigned g0 = ((rgba0 >> 8 ) & 0xff) * a0;
                      unsigned b0 = ((rgba0 >> 16) & 0xff) * a0;

                      a0 = ((a1 + a0) << 8) - a0*a1;

                      r0 = ((((r1 << 8) - r0) * a1 + (r0 << 8)) / a0);
                      g0 = ((((g1 << 8) - g0) * a1 + (g0 << 8)) / a0);
                      b0 = ((((b1 << 8) - b0) * a1 + (b0 << 8)) / a0);
                      a0 = a0 >> 8;
                      row_to[x] = (a0 << 24)| (b0 << 16) |  (g0 << 8) | (r0) ;
                   }
                }
            }
        }

        inline void set_rectangle_alpha2(ImageData32 const& data, unsigned x0, unsigned y0, float opacity)
        {
            Envelope<int> ext0(0,0,width_,height_);
            Envelope<int> ext1(x0,y0,x0 + data.width(),y0 + data.height());
            unsigned a1 = int(opacity * 255);

            if (ext0.intersects(ext1))
            {
                Envelope<int> box = ext0.intersect(ext1);
                for (int y = box.miny(); y < box.maxy(); ++y)
                {
                   unsigned int* row_to =  data_.getRow(y);
                   unsigned int const * row_from = data.getRow(y-y0);
                   for (int x = box.minx(); x < box.maxx(); ++x)
                   {
                      unsigned rgba0 = row_to[x];
                      unsigned rgba1 = row_from[x-x0];
                      if (((rgba1 >> 24) & 255)== 0) continue;
                      unsigned r1 = rgba1 & 0xff;
                      unsigned g1 = (rgba1 >> 8 ) & 0xff;
                      unsigned b1 = (rgba1 >> 16) & 0xff;

                      unsigned a0 = (rgba0 >> 24) & 0xff;
                      unsigned r0 = rgba0 & 0xff ;
                      unsigned g0 = (rgba0 >> 8 ) & 0xff;
                      unsigned b0 = (rgba0 >> 16) & 0xff;

                      unsigned a = (a1 * 255 + (255 - a1) * a0 + 127)/255;

                      r0 = (r1*a1 + (((255 - a1) * a0 + 127)/255) * r0 + 127)/a;
                      g0 = (g1*a1 + (((255 - a1) * a0 + 127)/255) * g0 + 127)/a;
                      b0 = (b1*a1 + (((255 - a1) * a0 + 127)/255) * b0 + 127)/a;

                      row_to[x] = (a << 24)| (b0 << 16) |  (g0 << 8) | (r0) ;
                    }
                }
            }
        }
    };
}
#endif //GRAPHICS_HPP
<commit_msg>fixed bug introduced in r495<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
 *
 *****************************************************************************/

//$Id: graphics.hpp 39 2005-04-10 20:39:53Z pavlenko $

#ifndef GRAPHICS_HPP
#define GRAPHICS_HPP
// stl
#include <cmath>
#include <string>
#include <cassert>
// mapnik
#include <mapnik/color.hpp>
#include <mapnik/gamma.hpp>
#include <mapnik/image_data.hpp>
#include <mapnik/envelope.hpp>
#include <mapnik/image_view.hpp>

namespace mapnik
{
    class MAPNIK_DECL Image32
    {
    private:
        unsigned width_;
        unsigned height_;
        Color background_;
        ImageData32 data_;
    public:
        Image32(int width,int height);
        Image32(Image32 const& rhs);
        ~Image32();
        void setBackground(Color const& background);
        const Color& getBackground() const;
        const ImageData32& data() const;

        inline ImageData32& data()
        {
            return data_;
        }

        inline const unsigned char* raw_data() const
        {
            return data_.getBytes();
        }

        inline unsigned char* raw_data()
        {
            return data_.getBytes();
        }

        inline image_view<ImageData32> get_view(unsigned x,unsigned y, unsigned w,unsigned h)
        {
            return image_view<ImageData32>(x,y,w,h,data_);
        }

        void saveToFile(const std::string& file,const std::string& format="auto");

    private:

        inline bool checkBounds(unsigned x, unsigned y) const
        {
            return (x < width_ && y < height_);
        }

    public:
        inline void setPixel(int x,int y,unsigned int rgba)
        {
            if (checkBounds(x,y))
            {
                data_(x,y)=rgba;
            }
        }
        inline void blendPixel(int x,int y,unsigned int rgba1,int t)
        {
            if (checkBounds(x,y))
            {
                unsigned rgba0 = data_(x,y);
                unsigned a1 = t;//(rgba1 >> 24) & 0xff;
                if (a1 == 0) return;
                unsigned r1 = rgba1 & 0xff;
                unsigned g1 = (rgba1 >> 8 ) & 0xff;
                unsigned b1 = (rgba1 >> 16) & 0xff;

                unsigned a0 = (rgba0 >> 24) & 0xff;
                unsigned r0 = (rgba0 & 0xff) * a0;
                unsigned g0 = ((rgba0 >> 8 ) & 0xff) * a0;
                unsigned b0 = ((rgba0 >> 16) & 0xff) * a0;

                a0 = ((a1 + a0) << 8) - a0*a1;

                r0 = ((((r1 << 8) - r0) * a1 + (r0 << 8)) / a0);
                g0 = ((((g1 << 8) - g0) * a1 + (g0 << 8)) / a0);
                b0 = ((((b1 << 8) - b0) * a1 + (b0 << 8)) / a0);
                a0 = a0 >> 8;
                data_(x,y)= (a0 << 24)| (b0 << 16) |  (g0 << 8) | (r0) ;
            }
        }

        inline unsigned width() const
        {
            return width_;
        }

        inline unsigned height() const
        {
            return height_;
        }

        inline void set_rectangle(int x0,int y0,ImageData32 const& data)
        {
            Envelope<int> ext0(0,0,width_,height_);
            Envelope<int> ext1(x0,y0,x0+data.width(),y0+data.height());

            if (ext0.intersects(ext1))
            {
               Envelope<int> box = ext0.intersect(ext1);
               for (int y = box.miny(); y < box.maxy(); ++y)
               {
                  unsigned int* row_to =  data_.getRow(y);
                  unsigned int const * row_from = data.getRow(y-y0);

                  for (int x = box.minx(); x < box.maxx(); ++x)
                  {
                     if (row_from[x-x0] & 0xff000000)
                     {
                        row_to[x] = row_from[x-x0];
                     }
                  }
               }
            }
        }

        inline void set_rectangle_alpha(int x0,int y0,const ImageData32& data)
        {
            Envelope<int> ext0(0,0,width_,height_);
            Envelope<int> ext1(x0,y0,x0 + data.width(),y0 + data.height());

            if (ext0.intersects(ext1))
            {
                Envelope<int> box = ext0.intersect(ext1);
                for (int y = box.miny(); y < box.maxy(); ++y)
                {
                   unsigned int* row_to =  data_.getRow(y);
                   unsigned int const * row_from = data.getRow(y-y0);
                   for (int x = box.minx(); x < box.maxx(); ++x)
                   {
                      unsigned rgba0 = row_to[x];
                      unsigned rgba1 = row_from[x-x0];

                      unsigned a1 = (rgba1 >> 24) & 0xff;
                      if (a1 == 0) continue;
                      unsigned r1 = rgba1 & 0xff;
                      unsigned g1 = (rgba1 >> 8 ) & 0xff;
                      unsigned b1 = (rgba1 >> 16) & 0xff;

                      unsigned a0 = (rgba0 >> 24) & 0xff;
                      unsigned r0 = (rgba0 & 0xff) * a0;
                      unsigned g0 = ((rgba0 >> 8 ) & 0xff) * a0;
                      unsigned b0 = ((rgba0 >> 16) & 0xff) * a0;

                      a0 = ((a1 + a0) << 8) - a0*a1;

                      r0 = ((((r1 << 8) - r0) * a1 + (r0 << 8)) / a0);
                      g0 = ((((g1 << 8) - g0) * a1 + (g0 << 8)) / a0);
                      b0 = ((((b1 << 8) - b0) * a1 + (b0 << 8)) / a0);
                      a0 = a0 >> 8;
                      row_to[x] = (a0 << 24)| (b0 << 16) |  (g0 << 8) | (r0) ;
                   }
                }
            }
        }

        inline void set_rectangle_alpha2(ImageData32 const& data, unsigned x0, unsigned y0, float opacity)
        {
            Envelope<int> ext0(0,0,width_,height_);
            Envelope<int> ext1(x0,y0,x0 + data.width(),y0 + data.height());
            unsigned a1 = int(opacity * 255);

            if (ext0.intersects(ext1))
            {
                Envelope<int> box = ext0.intersect(ext1);
                for (int y = box.miny(); y < box.maxy(); ++y)
                {
                   unsigned int* row_to =  data_.getRow(y);
                   unsigned int const * row_from = data.getRow(y-y0);
                   for (int x = box.minx(); x < box.maxx(); ++x)
                   {
                      unsigned rgba0 = row_to[x];
                      unsigned rgba1 = row_from[x-x0];
                      if (((rgba1 >> 24) & 255)== 0) continue;
                      unsigned r1 = rgba1 & 0xff;
                      unsigned g1 = (rgba1 >> 8 ) & 0xff;
                      unsigned b1 = (rgba1 >> 16) & 0xff;

                      unsigned a0 = (rgba0 >> 24) & 0xff;
                      unsigned r0 = rgba0 & 0xff ;
                      unsigned g0 = (rgba0 >> 8 ) & 0xff;
                      unsigned b0 = (rgba0 >> 16) & 0xff;

                      unsigned a = (a1 * 255 + (255 - a1) * a0 + 127)/255;

                      r0 = (r1*a1 + (((255 - a1) * a0 + 127)/255) * r0 + 127)/a;
                      g0 = (g1*a1 + (((255 - a1) * a0 + 127)/255) * g0 + 127)/a;
                      b0 = (b1*a1 + (((255 - a1) * a0 + 127)/255) * b0 + 127)/a;

                      row_to[x] = (a << 24)| (b0 << 16) |  (g0 << 8) | (r0) ;
                    }
                }
            }
        }
    };
}
#endif //GRAPHICS_HPP
<|endoftext|>


<commit_before>// This file is part of the dune-stuff project:
//   https://github.com/wwu-numerik/dune-stuff
// Copyright holders: Rene Milk, Felix Schindler
// License: BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause)

#ifndef DUNE_STUFF_FUNCTIONS_VISUALIZATION_HH
#define DUNE_STUFF_FUNCTIONS_VISUALIZATION_HH

#if HAVE_DUNE_GRID
# include <dune/stuff/common/disable_warnings.hh>
#   include <dune/grid/io/file/vtk/function.hh>
# include <dune/stuff/common/reenable_warnings.hh>
#endif

#include <dune/stuff/common/float_cmp.hh>

#include "interfaces.hh"

namespace Dune {
namespace Stuff {
namespace Functions {

#if HAVE_DUNE_GRID

template< class GridViewType, int dimRange, int dimRangeCols >
class VisualizationAdapter
  : public VTKFunction< GridViewType >
{
public:
  typedef typename GridViewType::template Codim< 0 >::Entity EntityType;

  typedef typename GridViewType::ctype              DomainFieldType;
  static const unsigned int                         dimDomain = GridViewType::dimension;
  typedef FieldVector< DomainFieldType, dimDomain > DomainType;

  typedef LocalizableFunctionInterface< EntityType, DomainFieldType, dimDomain, double, dimRange, dimRangeCols >
      FunctionType;

  VisualizationAdapter(const FunctionType& function, const std::string nm = "")
    : function_(function)
    , tmp_value_(0)
    , name_(nm)
  {}

private:
  template< int r, int rC, bool anything = true >
  class Call
  {
  public:
    static int ncomps()
    {
      return 1;
    }

    static double evaluate(const int& /*comp*/, const typename FunctionType::RangeType& val)
    {
      return val.frobenius_norm();
    }
  }; // class Call

  template< int r, bool anything >
  class Call< r, 1, anything >
  {
  public:
    static int ncomps()
    {
      return r;
    }

    static double evaluate(const int& comp, const typename FunctionType::RangeType& val)
    {
      return val[comp];
    }
  }; // class Call< ..., 1, ... >

public:
  virtual int ncomps() const /*DS_OVERRIDE DS_FINAL*/
  {
    return Call< dimRange, dimRangeCols >::ncomps();
  }

  virtual std::string name() const /*DS_OVERRIDE DS_FINAL*/
  {
    if (name_.empty())
      return function_.name();
    else
      return name_;
  }

  virtual double evaluate(int comp, const EntityType& en, const DomainType& xx) const /*DS_OVERRIDE DS_FINAL*/
  {
    assert(comp >= 0);
    assert(comp < dimRange);
    const auto local_func = function_.local_function(en);
    local_func->evaluate(xx, tmp_value_);
    return Call< dimRange, dimRangeCols >::evaluate(comp, tmp_value_);
  }

private:
  const FunctionType& function_;
  mutable typename FunctionType::RangeType tmp_value_;
  const std::string name_;
}; // class VisualizationAdapter

#endif // HAVE_DUNE_GRID

//template< class EntityImp, class DomainFieldImp, int domainDim, class RangeFieldImp, int rangeDimRows, int rangeDimCols = 1 >
//class LocalDifferentiableFunctionDefault;

//template< class EntityImp, class DomainFieldImp, int domainDim, class RangeFieldImp >
//class LocalDifferentiableFunctionDefault< EntityImp, DomainFieldImp, domainDim, RangeFieldImp, 1, 1 >
//  : public LocalfunctionInterface< EntityImp, DomainFieldImp, domainDim, RangeFieldImp, 1, 1 >
//{
//  typedef LocalfunctionInterface< EntityImp, DomainFieldImp, domainDim, RangeFieldImp, 1, 1 > BaseType;
//public:
//  typedef typename BaseType::EntityType EntityType;

//  typedef typename BaseType::DomainFieldType  DomainFieldType;
//  static const unsigned int                   dimDomain = BaseType::dimDomain;
//  typedef typename BaseType::DomainType       DomainType;

//  typedef typename BaseType::RangeFieldType RangeFieldType;
//  static const unsigned int                 dimRange = BaseType::dimRange;
//  static const unsigned int                 dimRangeRows = BaseType::dimRangeRows;
//  static const unsigned int                 dimRangeCols = BaseType::dimRangeCols;
//  typedef typename BaseType::RangeType      RangeType;

//  typedef typename BaseType::JacobianRangeType JacobianRangeType;

//  LocalDifferentiableFunctionDefault(const EntityType& ent)
//    : entity_(ent)
////    , max_variation_(DomainFieldType(0))
//    , disturbed_point_(DomainFieldType(0))
//    , point_value_(RangeFieldType(0))
//    , disturbed_value_(RangeFieldType(0))
//    , hh_(std::max(100.0 * std::numeric_limits< DomainFieldType >::min(), 1e-2))
//  {
////    // get corners
////    const size_t num_corners = entity_.geometry().corners();
////    std::vector< DomainType > corners(num_corners, DomainType(DomainFieldType(0)));
////    for (size_t cc = 0; cc < num_corners; ++cc)
////      corners[cc] = entity_.geometry().corner(cc);
////    // compute max distance per dimension
////    DomainType difference(DomainFieldType(0));
////    for (size_t cc = 0; cc < num_corners; ++cc) {
////      const auto& corner = corners[cc];
////      for (size_t oo = cc + 1; oo < num_corners; ++oo) {
////        const auto& other_corner = corners[oo];
////        difference = corner;
////        difference -= other_corner;
////        max_variation_[cc] = std::max(max_variation_[cc], std::abs(difference[cc]));
////      }
////    }
//    assert(Common::FloatCmp::ne(hh_, DomainFieldType(0)));
//  } // LocalDifferentiableFunctionDefault(...)

//  virtual ~LocalDifferentiableFunctionDefault() {}

//  virtual const EntityType& entity() const DS_OVERRIDE
//  {
//    return entity_;
//  }

//  virtual void evaluate(const DomainType& /*xx*/, RangeType& /*ret*/) const = 0;

//  virtual void jacobian(const DomainType& xx, JacobianRangeType& ret) const DS_OVERRIDE
//  {
//    assert(this->is_a_valid_point(xx));
//    // clear
//    ret *= RangeFieldType(0);
//    // evaluate
//    evaluate(xx, point_value_);
//    // loop over all dimensions
//    for (size_t dd = 0; dd < dimDomain; ++dd) {
//      // disturbe the point
//      disturbed_point_ = xx;
//      disturbed_point_[dd] += hh_;
//      assert(this->is_a_valid_point(disturbed_point_));
////      // find a closer point if that one is not contained in the entity
////      size_t num_tries = 0;
////      while(!this->is_a_valid_point(disturbed_point_) && num_tries < max_tries_) {
////        disturbed_point_[dd] = 0.5*(xx[dd] + disturbed_point_[dd]);
////        ++num_tries;
////      }
////      if (num_tries == max_tries_)
////        DUNE_THROW(InvalidStateException, "Could not find a disturbed point inside the entity!");
//      // compute gradient
//      evaluate(disturbed_point_, disturbed_value_);
////      const DomainFieldType hh = std::abs(disturbed_point_[dd] - xx[dd]);
//      ret[0][dd] = (point_value_ - disturbed_value_) / hh_;
//    } // loop over all dimensions
//  } // ... jacobian(...)

//private:
//  const EntityType& entity_;
////  const size_t max_tries_;
//  DomainFieldType hh_;
////  DomainType max_variation_;
//  mutable DomainType disturbed_point_;
//  mutable RangeType point_value_;
//  mutable RangeType disturbed_value_;
//}; // class LocalDifferentiableFunctionDefault< ..., 1 >

} // namespace Functions
} // namespace Stuff
} // namespace Dune

#endif // DUNE_STUFF_FUNCTIONS_VISUALIZATION_HH
<commit_msg>[functions.default] fixes uselessly commented DS_OVERRIDE DS_FINAL qualifiers<commit_after>// This file is part of the dune-stuff project:
//   https://github.com/wwu-numerik/dune-stuff
// Copyright holders: Rene Milk, Felix Schindler
// License: BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause)

#ifndef DUNE_STUFF_FUNCTIONS_VISUALIZATION_HH
#define DUNE_STUFF_FUNCTIONS_VISUALIZATION_HH

#if HAVE_DUNE_GRID
# include <dune/stuff/common/disable_warnings.hh>
#   include <dune/grid/io/file/vtk/function.hh>
# include <dune/stuff/common/reenable_warnings.hh>
#endif

#include <dune/stuff/common/float_cmp.hh>

#include "interfaces.hh"

namespace Dune {
namespace Stuff {
namespace Functions {

#if HAVE_DUNE_GRID

template< class GridViewType, int dimRange, int dimRangeCols >
class VisualizationAdapter
  : public VTKFunction< GridViewType >
{
public:
  typedef typename GridViewType::template Codim< 0 >::Entity EntityType;

  typedef typename GridViewType::ctype              DomainFieldType;
  static const unsigned int                         dimDomain = GridViewType::dimension;
  typedef FieldVector< DomainFieldType, dimDomain > DomainType;

  typedef LocalizableFunctionInterface< EntityType, DomainFieldType, dimDomain, double, dimRange, dimRangeCols >
      FunctionType;

  VisualizationAdapter(const FunctionType& function, const std::string nm = "")
    : function_(function)
    , tmp_value_(0)
    , name_(nm)
  {}

private:
  template< int r, int rC, bool anything = true >
  class Call
  {
  public:
    static int ncomps()
    {
      return 1;
    }

    static double evaluate(const int& /*comp*/, const typename FunctionType::RangeType& val)
    {
      return val.frobenius_norm();
    }
  }; // class Call

  template< int r, bool anything >
  class Call< r, 1, anything >
  {
  public:
    static int ncomps()
    {
      return r;
    }

    static double evaluate(const int& comp, const typename FunctionType::RangeType& val)
    {
      return val[comp];
    }
  }; // class Call< ..., 1, ... >

public:
  virtual int ncomps() const DS_OVERRIDE DS_FINAL
  {
    return Call< dimRange, dimRangeCols >::ncomps();
  }

  virtual std::string name() const DS_OVERRIDE DS_FINAL
  {
    if (name_.empty())
      return function_.name();
    else
      return name_;
  }

  virtual double evaluate(int comp, const EntityType& en, const DomainType& xx) const DS_OVERRIDE DS_FINAL
  {
    assert(comp >= 0);
    assert(comp < dimRange);
    const auto local_func = function_.local_function(en);
    local_func->evaluate(xx, tmp_value_);
    return Call< dimRange, dimRangeCols >::evaluate(comp, tmp_value_);
  }

private:
  const FunctionType& function_;
  mutable typename FunctionType::RangeType tmp_value_;
  const std::string name_;
}; // class VisualizationAdapter

#endif // HAVE_DUNE_GRID

//template< class EntityImp, class DomainFieldImp, int domainDim, class RangeFieldImp, int rangeDimRows, int rangeDimCols = 1 >
//class LocalDifferentiableFunctionDefault;

//template< class EntityImp, class DomainFieldImp, int domainDim, class RangeFieldImp >
//class LocalDifferentiableFunctionDefault< EntityImp, DomainFieldImp, domainDim, RangeFieldImp, 1, 1 >
//  : public LocalfunctionInterface< EntityImp, DomainFieldImp, domainDim, RangeFieldImp, 1, 1 >
//{
//  typedef LocalfunctionInterface< EntityImp, DomainFieldImp, domainDim, RangeFieldImp, 1, 1 > BaseType;
//public:
//  typedef typename BaseType::EntityType EntityType;

//  typedef typename BaseType::DomainFieldType  DomainFieldType;
//  static const unsigned int                   dimDomain = BaseType::dimDomain;
//  typedef typename BaseType::DomainType       DomainType;

//  typedef typename BaseType::RangeFieldType RangeFieldType;
//  static const unsigned int                 dimRange = BaseType::dimRange;
//  static const unsigned int                 dimRangeRows = BaseType::dimRangeRows;
//  static const unsigned int                 dimRangeCols = BaseType::dimRangeCols;
//  typedef typename BaseType::RangeType      RangeType;

//  typedef typename BaseType::JacobianRangeType JacobianRangeType;

//  LocalDifferentiableFunctionDefault(const EntityType& ent)
//    : entity_(ent)
////    , max_variation_(DomainFieldType(0))
//    , disturbed_point_(DomainFieldType(0))
//    , point_value_(RangeFieldType(0))
//    , disturbed_value_(RangeFieldType(0))
//    , hh_(std::max(100.0 * std::numeric_limits< DomainFieldType >::min(), 1e-2))
//  {
////    // get corners
////    const size_t num_corners = entity_.geometry().corners();
////    std::vector< DomainType > corners(num_corners, DomainType(DomainFieldType(0)));
////    for (size_t cc = 0; cc < num_corners; ++cc)
////      corners[cc] = entity_.geometry().corner(cc);
////    // compute max distance per dimension
////    DomainType difference(DomainFieldType(0));
////    for (size_t cc = 0; cc < num_corners; ++cc) {
////      const auto& corner = corners[cc];
////      for (size_t oo = cc + 1; oo < num_corners; ++oo) {
////        const auto& other_corner = corners[oo];
////        difference = corner;
////        difference -= other_corner;
////        max_variation_[cc] = std::max(max_variation_[cc], std::abs(difference[cc]));
////      }
////    }
//    assert(Common::FloatCmp::ne(hh_, DomainFieldType(0)));
//  } // LocalDifferentiableFunctionDefault(...)

//  virtual ~LocalDifferentiableFunctionDefault() {}

//  virtual const EntityType& entity() const DS_OVERRIDE
//  {
//    return entity_;
//  }

//  virtual void evaluate(const DomainType& /*xx*/, RangeType& /*ret*/) const = 0;

//  virtual void jacobian(const DomainType& xx, JacobianRangeType& ret) const DS_OVERRIDE
//  {
//    assert(this->is_a_valid_point(xx));
//    // clear
//    ret *= RangeFieldType(0);
//    // evaluate
//    evaluate(xx, point_value_);
//    // loop over all dimensions
//    for (size_t dd = 0; dd < dimDomain; ++dd) {
//      // disturbe the point
//      disturbed_point_ = xx;
//      disturbed_point_[dd] += hh_;
//      assert(this->is_a_valid_point(disturbed_point_));
////      // find a closer point if that one is not contained in the entity
////      size_t num_tries = 0;
////      while(!this->is_a_valid_point(disturbed_point_) && num_tries < max_tries_) {
////        disturbed_point_[dd] = 0.5*(xx[dd] + disturbed_point_[dd]);
////        ++num_tries;
////      }
////      if (num_tries == max_tries_)
////        DUNE_THROW(InvalidStateException, "Could not find a disturbed point inside the entity!");
//      // compute gradient
//      evaluate(disturbed_point_, disturbed_value_);
////      const DomainFieldType hh = std::abs(disturbed_point_[dd] - xx[dd]);
//      ret[0][dd] = (point_value_ - disturbed_value_) / hh_;
//    } // loop over all dimensions
//  } // ... jacobian(...)

//private:
//  const EntityType& entity_;
////  const size_t max_tries_;
//  DomainFieldType hh_;
////  DomainType max_variation_;
//  mutable DomainType disturbed_point_;
//  mutable RangeType point_value_;
//  mutable RangeType disturbed_value_;
//}; // class LocalDifferentiableFunctionDefault< ..., 1 >

} // namespace Functions
} // namespace Stuff
} // namespace Dune

#endif // DUNE_STUFF_FUNCTIONS_VISUALIZATION_HH
<|endoftext|>


<commit_before>#include <sys/time.h>

#include "thread_private.h"
#include "parameters.h"
#include "exception.h"

#define NUM_PAGES (4096 * config.get_nthreads())

bool align_req = false;
int align_size = PAGE_SIZE;

extern struct timeval global_start;

void check_read_content(char *buf, int size, off_t off)
{
	// I assume the space in the buffer is larger than 8 bytes.
	off_t aligned_off = off & (~(sizeof(off_t) - 1));
	long data[2];
	data[0] = aligned_off / sizeof(off_t);
	data[1] = aligned_off / sizeof(off_t) + 1;
	long expected = 0;
	int copy_size = size < (int) sizeof(off_t) ? size : (int) sizeof(off_t);
	memcpy(&expected, ((char *) data) + (off - aligned_off), copy_size);
	long read_value = 0;
	memcpy(&read_value, buf, copy_size);
	if(read_value != expected)
		printf("%ld %ld\n", read_value, expected);
	assert(read_value == expected);
}

void create_write_data(char *buf, int size, off_t off)
{
	off_t aligned_start = off & (~(sizeof(off_t) - 1));
	off_t aligned_end = (off + size) & (~(sizeof(off_t) - 1));
	long start_data = aligned_start / sizeof(off_t);
	long end_data = aligned_end / sizeof(off_t);

	/* If all data is in one 8-byte word. */
	if (aligned_start == aligned_end) {
		memcpy(buf, ((char *) &start_data) + (off - aligned_start), size);
		return;
	}

	int first_size =  (int)(sizeof(off_t) - (off - aligned_start));
	int last_size = (int) (off + size - aligned_end);

	if (first_size == sizeof(off_t))
		first_size = 0;
	if (first_size)
		memcpy(buf, ((char *) &start_data) + (off - aligned_start),
				first_size);
	// Make each buffer written to SSDs different, so it's hard for SSDs
	// to do some tricks on it.
	struct timeval zero = {0, 0};
	long diff = time_diff_us(zero, global_start);
	for (int i = first_size; i < aligned_end - off; i += sizeof(off_t)) {
		*((long *) (buf + i)) = (off + i) / sizeof(off_t) + diff;
	}
	if (aligned_end > aligned_start
			|| (aligned_end == aligned_start && first_size == 0)) {
		if (last_size)
			memcpy(buf + (aligned_end - off), (char *) &end_data, last_size);
	}

	check_read_content(buf, size, off);
}

class cleanup_callback: public callback
{
	rand_buf *buf;
	ssize_t read_bytes;
	int thread_id;
	thread_private *thread;
public:
	cleanup_callback(rand_buf *buf, int idx, thread_private *thread) {
		this->buf = buf;
		read_bytes = 0;
		this->thread_id = idx;
		this->thread = thread;
	}

	int invoke(io_request *rqs[], int num) {
		for (int i = 0; i < num; i++) {
			io_request *rq = rqs[i];
			if (rq->get_access_method() == READ && config.is_verify_read()) {
				off_t off = rq->get_offset();
				for (int i = 0; i < rq->get_num_bufs(); i++) {
					check_read_content(rq->get_buf(i), rq->get_buf_size(i), off);
					off += rq->get_buf_size(i);
				}
			}
			for (int i = 0; i < rq->get_num_bufs(); i++)
				buf->free_entry(rq->get_buf(i));
			read_bytes += rq->get_size();
		}
#ifdef STATISTICS
		thread->num_completes.inc(num);
		thread->num_pending.dec(num);
#endif
		return 0;
	}

	ssize_t get_size() {
		return read_bytes;
	}
};

ssize_t thread_private::get_read_bytes() {
	if (cb)
		return cb->get_size();
	else
		return read_bytes;
}

void thread_private::init() {
	io = factory->create_io(this);
	io->set_max_num_pending_ios(sys_params.get_aio_depth_per_file());
	io->init();

	rand_buf *buf = new rand_buf(NUM_PAGES / (config.get_nthreads()
				// TODO maybe I should set the right entry size for a buffer.
				// If each access size is irregular, I'll break each access
				// into pages so each access is no larger than a page, so it
				// should workl fine.
				/ NUM_NODES) * PAGE_SIZE, config.get_buf_size(), node_id);
	this->buf = buf;
	if (io->support_aio()) {
		cb = new cleanup_callback(buf, idx, this);
		io->set_callback(cb);
	}
}

void thread_private::run()
{
	int node_id = io->get_node_id();
	gettimeofday(&start_time, NULL);
	io_request reqs[NUM_REQS_BY_USER];
	char *entry = NULL;
	if (config.is_use_aio())
		assert(io->support_aio());
	if (!config.is_use_aio()) {
		entry = (char *) valloc(config.get_buf_size());
	}
	while (gen->has_next()) {
		if (config.is_use_aio()) {
			int i;
			int num_reqs_by_user = min(io->get_remaining_io_slots(), NUM_REQS_BY_USER);
			for (i = 0; i < num_reqs_by_user && gen->has_next(); ) {
				workload_t workload = gen->next();
				int access_method = workload.read ? READ : WRITE;
				off_t off = workload.off;
				int size = workload.size;
				if (align_req) {
					off = ROUND(off, align_size);
					size = ROUNDUP(off + size, align_size)
						- ROUND(off, align_size);
				}
				/*
				 * If the size of the request is larger than a page size,
				 * and the user explicitly wants to use multibuf requests.
				 */
				if (config.get_buf_type() == MULTI_BUF) {
					throw unsupported_exception();
#if 0
					assert(off % PAGE_SIZE == 0);
					int num_vecs = size / PAGE_SIZE;
					reqs[i].init(off, io, access_method, node_id);
					assert(buf->get_entry_size() >= PAGE_SIZE);
					for (int k = 0; k < num_vecs; k++) {
						reqs[i].add_buf(buf->next_entry(PAGE_SIZE), PAGE_SIZE);
					}
					i++;
#endif
				}
				else if (config.get_buf_type() == SINGLE_SMALL_BUF) {
again:
					num_reqs_by_user = min(io->get_remaining_io_slots(), NUM_REQS_BY_USER);
					while (size > 0 && i < num_reqs_by_user) {
						off_t next_off = ROUNDUP_PAGE(off + 1);
						if (next_off > off + size)
							next_off = off + size;
						char *p = buf->next_entry(next_off - off);
						if (p == NULL)
							break;
						if (access_method == WRITE && config.is_verify_read())
							create_write_data(p, next_off - off, off);
						reqs[i].init(p, off, next_off - off, access_method,
								io, node_id);
						size -= next_off - off;
						off = next_off;
						i++;
					}
					if (size > 0) {
						io->access(reqs, i);
						if (io->get_remaining_io_slots() <= 0) {
							int num_ios = io->get_max_num_pending_ios() / 10;
							if (num_ios == 0)
								num_ios = 1;
							io->wait4complete(num_ios);
						}
#ifdef STATISTICS
						num_pending.inc(i);
#endif
						num_accesses += i;
						i = 0;
						goto again;
					}
				}
				else {
					char *p = buf->next_entry(size);
					if (p == NULL)
						break;
					if (access_method == WRITE && config.is_verify_read())
						create_write_data(p, size, off);
					reqs[i++].init(p, off, size, access_method, io, node_id);
				}
			}
			io->access(reqs, i);
			if (io->get_remaining_io_slots() <= 0) {
				int num_ios = io->get_max_num_pending_ios() / 10;
				if (num_ios == 0)
					num_ios = 1;
				io->wait4complete(num_ios);
			}
			num_accesses += i;
#ifdef STATISTICS
			int curr = num_pending.inc(i);
			if (max_num_pending < curr)
				max_num_pending = curr;
			if (num_accesses % 100 == 0) {
				num_sampling++;
				tot_num_pending += curr;
			}
#endif
		}
		else {
			int ret = 0;
			workload_t workload = gen->next();
			off_t off = workload.off;
			int access_method = workload.read ? READ : WRITE;
			int entry_size = workload.size;
			if (align_req) {
				off = ROUND(off, align_size);
				entry_size = ROUNDUP(off + entry_size, align_size)
					- ROUND(off, align_size);
			}

			if (config.get_buf_type() == SINGLE_SMALL_BUF) {
				while (entry_size > 0) {
					/*
					 * generate the data for writing the file,
					 * so the data in the file isn't changed.
					 */
					if (access_method == WRITE && config.is_verify_read()) {
						create_write_data(entry, entry_size, off);
					}
					// There is at least one byte we need to access in the page.
					// By adding 1 and rounding up the offset, we'll get the next page
					// behind the current offset.
					off_t next_off = ROUNDUP_PAGE(off + 1);
					if (next_off > off + entry_size)
						next_off = off + entry_size;
					io_status status = io->access(entry, off, next_off - off,
							access_method);
					assert(!(status == IO_UNSUPPORTED));
					if (status == IO_OK) {
						num_accesses++;
						if (access_method == READ && config.is_verify_read()) {
							check_read_content(entry, next_off - off, off);
						}
						read_bytes += ret;
					}
					if (status == IO_FAIL) {
						perror("access");
						::exit(1);
					}
					entry_size -= next_off - off;
					off = next_off;
				}
			}
			else {
				if (access_method == WRITE && config.is_verify_read()) {
					create_write_data(entry, entry_size, off);
				}
				io_status status = io->access(entry, off, entry_size,
						access_method);
				assert(!(status == IO_UNSUPPORTED));
				if (status == IO_OK) {
					num_accesses++;
					if (access_method == READ && config.is_verify_read()) {
						check_read_content(entry, entry_size, off);
					}
					read_bytes += ret;
				}
				if (status == IO_FAIL) {
					perror("access");
					::exit(1);
				}
			}
		}
	}
	printf("thread %d has issued all requests\n", idx);
	io->cleanup();
	gettimeofday(&end_time, NULL);

	// Stop itself.
	stop();
}

int thread_private::attach2cpu()
{
#if NCPUS > 0
	cpu_set_t cpuset;
	pthread_t thread = pthread_self();
	CPU_ZERO(&cpuset);
	int cpu_num = idx % NCPUS;
	CPU_SET(cpu_num, &cpuset);
	int ret = pthread_setaffinity_np(thread, sizeof(cpu_set_t), &cpuset);
	if (ret != 0) {
		perror("pthread_setaffinity_np");
		exit(1);
	}
	return ret;
#else
	return -1;
#endif
}

#ifdef USE_PROCESS
static int process_create(pid_t *pid, void (*func)(void *), void *priv)
{
	pid_t id = fork();

	if (id < 0)
		return -1;

	if (id == 0) {	// child
		func(priv);
		exit(0);
	}

	if (id > 0)
		*pid = id;
	return 0;
}

static int process_join(pid_t pid)
{
	int status;
	pid_t ret = waitpid(pid, &status, 0);
	return ret < 0 ? ret : 0;
}
#endif
<commit_msg>Simplify conversion from workload to io requests.<commit_after>#include <sys/time.h>

#include "thread_private.h"
#include "parameters.h"
#include "exception.h"

#define NUM_PAGES (4096 * config.get_nthreads())

bool align_req = false;
int align_size = PAGE_SIZE;

extern struct timeval global_start;

void check_read_content(char *buf, int size, off_t off)
{
	// I assume the space in the buffer is larger than 8 bytes.
	off_t aligned_off = off & (~(sizeof(off_t) - 1));
	long data[2];
	data[0] = aligned_off / sizeof(off_t);
	data[1] = aligned_off / sizeof(off_t) + 1;
	long expected = 0;
	int copy_size = size < (int) sizeof(off_t) ? size : (int) sizeof(off_t);
	memcpy(&expected, ((char *) data) + (off - aligned_off), copy_size);
	long read_value = 0;
	memcpy(&read_value, buf, copy_size);
	if(read_value != expected)
		printf("%ld %ld\n", read_value, expected);
	assert(read_value == expected);
}

void create_write_data(char *buf, int size, off_t off)
{
	off_t aligned_start = off & (~(sizeof(off_t) - 1));
	off_t aligned_end = (off + size) & (~(sizeof(off_t) - 1));
	long start_data = aligned_start / sizeof(off_t);
	long end_data = aligned_end / sizeof(off_t);

	/* If all data is in one 8-byte word. */
	if (aligned_start == aligned_end) {
		memcpy(buf, ((char *) &start_data) + (off - aligned_start), size);
		return;
	}

	int first_size =  (int)(sizeof(off_t) - (off - aligned_start));
	int last_size = (int) (off + size - aligned_end);

	if (first_size == sizeof(off_t))
		first_size = 0;
	if (first_size)
		memcpy(buf, ((char *) &start_data) + (off - aligned_start),
				first_size);
	// Make each buffer written to SSDs different, so it's hard for SSDs
	// to do some tricks on it.
	struct timeval zero = {0, 0};
	long diff = time_diff_us(zero, global_start);
	for (int i = first_size; i < aligned_end - off; i += sizeof(off_t)) {
		*((long *) (buf + i)) = (off + i) / sizeof(off_t) + diff;
	}
	if (aligned_end > aligned_start
			|| (aligned_end == aligned_start && first_size == 0)) {
		if (last_size)
			memcpy(buf + (aligned_end - off), (char *) &end_data, last_size);
	}

	check_read_content(buf, size, off);
}

class cleanup_callback: public callback
{
	rand_buf *buf;
	ssize_t read_bytes;
	int thread_id;
	thread_private *thread;
public:
	cleanup_callback(rand_buf *buf, int idx, thread_private *thread) {
		this->buf = buf;
		read_bytes = 0;
		this->thread_id = idx;
		this->thread = thread;
	}

	int invoke(io_request *rqs[], int num) {
		for (int i = 0; i < num; i++) {
			io_request *rq = rqs[i];
			if (rq->get_access_method() == READ && config.is_verify_read()) {
				off_t off = rq->get_offset();
				for (int i = 0; i < rq->get_num_bufs(); i++) {
					check_read_content(rq->get_buf(i), rq->get_buf_size(i), off);
					off += rq->get_buf_size(i);
				}
			}
			for (int i = 0; i < rq->get_num_bufs(); i++)
				buf->free_entry(rq->get_buf(i));
			read_bytes += rq->get_size();
		}
#ifdef STATISTICS
		thread->num_completes.inc(num);
		thread->num_pending.dec(num);
#endif
		return 0;
	}

	ssize_t get_size() {
		return read_bytes;
	}
};

ssize_t thread_private::get_read_bytes() {
	if (cb)
		return cb->get_size();
	else
		return read_bytes;
}

void thread_private::init() {
	io = factory->create_io(this);
	io->set_max_num_pending_ios(sys_params.get_aio_depth_per_file());
	io->init();

	rand_buf *buf = new rand_buf(NUM_PAGES / (config.get_nthreads()
				// TODO maybe I should set the right entry size for a buffer.
				// If each access size is irregular, I'll break each access
				// into pages so each access is no larger than a page, so it
				// should workl fine.
				/ NUM_NODES) * PAGE_SIZE, config.get_buf_size(), node_id);
	this->buf = buf;
	if (io->support_aio()) {
		cb = new cleanup_callback(buf, idx, this);
		io->set_callback(cb);
	}
}

class work2req_converter
{
	workload_t workload;
	int align_size;
	rand_buf *buf;
	io_interface *io;
public:
	work2req_converter(io_interface *io, rand_buf * buf, int align_size) {
		workload.off = -1;
		workload.size = -1;
		workload.read = 0;
		this->align_size = align_size;
		this->buf = buf;
		this->io = io;
	}

	void init(const workload_t &workload) {
		this->workload = workload;
		if (align_size > 0) {
			this->workload.off = ROUND(workload.off, align_size);
			this->workload.size = ROUNDUP(workload.off
					+ workload.size, align_size)
				- ROUND(workload.off, align_size);
		}
	}

	bool has_complete() const {
		return workload.size <= 0;
	}

	int to_reqs(int buf_type, int num, io_request reqs[]);
};

int work2req_converter::to_reqs(int buf_type, int num, io_request reqs[])
{
	int node_id = io->get_node_id();
	int access_method = workload.read ? READ : WRITE;
	off_t off = workload.off;
	int size = workload.size;

	if (buf_type == MULTI_BUF) {
		throw unsupported_exception();
#if 0
		assert(off % PAGE_SIZE == 0);
		int num_vecs = size / PAGE_SIZE;
		reqs[i].init(off, io, access_method, node_id);
		assert(buf->get_entry_size() >= PAGE_SIZE);
		for (int k = 0; k < num_vecs; k++) {
			reqs[i].add_buf(buf->next_entry(PAGE_SIZE), PAGE_SIZE);
		}
		workload.off += size;
		workload.size = 0;
#endif
	}
	else if (buf_type == SINGLE_SMALL_BUF) {
		int i = 0;
		while (size > 0 && i < num) {
			off_t next_off = ROUNDUP_PAGE(off + 1);
			if (next_off > off + size)
				next_off = off + size;
			char *p = buf->next_entry(next_off - off);
			if (p == NULL)
				break;
			if (access_method == WRITE && config.is_verify_read())
				create_write_data(p, next_off - off, off);
			reqs[i].init(p, off, next_off - off, access_method,
					io, node_id);
			size -= next_off - off;
			off = next_off;
			i++;
		}
		workload.off = off;
		workload.size = size;
		return i;
	}
	else {
		char *p = buf->next_entry(size);
		if (p == NULL)
			return 0;
		if (access_method == WRITE && config.is_verify_read())
			create_write_data(p, size, off);
		reqs[0].init(p, off, size, access_method, io, node_id);
		return 1;
	}
}

void thread_private::run()
{
	gettimeofday(&start_time, NULL);
	io_request reqs[NUM_REQS_BY_USER];
	char *entry = NULL;
	if (config.is_use_aio())
		assert(io->support_aio());
	if (!config.is_use_aio()) {
		entry = (char *) valloc(config.get_buf_size());
	}
	work2req_converter converter(io, buf, align_size);
	while (gen->has_next()) {
		if (config.is_use_aio()) {
			int i;
			int num_reqs_by_user = min(io->get_remaining_io_slots(), NUM_REQS_BY_USER);
			for (i = 0; i < num_reqs_by_user; ) {
				if (converter.has_complete() && gen->has_next()) {
					converter.init(gen->next());
				}
				int ret = converter.to_reqs(config.get_buf_type(),
						num_reqs_by_user - i, reqs + i);
				if (ret == 0)
					break;
				i += ret;
			}
			io->access(reqs, i);
			while (io->get_remaining_io_slots() <= 0) {
				int num_ios = io->get_max_num_pending_ios() / 10;
				if (num_ios == 0)
					num_ios = 1;
				io->wait4complete(num_ios);
			}
			num_accesses += i;
#ifdef STATISTICS
			int curr = num_pending.inc(i);
			if (max_num_pending < curr)
				max_num_pending = curr;
			if (num_accesses % 100 == 0) {
				num_sampling++;
				tot_num_pending += curr;
			}
#endif
		}
		else {
			int ret = 0;
			workload_t workload = gen->next();
			off_t off = workload.off;
			int access_method = workload.read ? READ : WRITE;
			int entry_size = workload.size;
			if (align_req) {
				off = ROUND(off, align_size);
				entry_size = ROUNDUP(off + entry_size, align_size)
					- ROUND(off, align_size);
			}

			if (config.get_buf_type() == SINGLE_SMALL_BUF) {
				while (entry_size > 0) {
					/*
					 * generate the data for writing the file,
					 * so the data in the file isn't changed.
					 */
					if (access_method == WRITE && config.is_verify_read()) {
						create_write_data(entry, entry_size, off);
					}
					// There is at least one byte we need to access in the page.
					// By adding 1 and rounding up the offset, we'll get the next page
					// behind the current offset.
					off_t next_off = ROUNDUP_PAGE(off + 1);
					if (next_off > off + entry_size)
						next_off = off + entry_size;
					io_status status = io->access(entry, off, next_off - off,
							access_method);
					assert(!(status == IO_UNSUPPORTED));
					if (status == IO_OK) {
						num_accesses++;
						if (access_method == READ && config.is_verify_read()) {
							check_read_content(entry, next_off - off, off);
						}
						read_bytes += ret;
					}
					if (status == IO_FAIL) {
						perror("access");
						::exit(1);
					}
					entry_size -= next_off - off;
					off = next_off;
				}
			}
			else {
				if (access_method == WRITE && config.is_verify_read()) {
					create_write_data(entry, entry_size, off);
				}
				io_status status = io->access(entry, off, entry_size,
						access_method);
				assert(!(status == IO_UNSUPPORTED));
				if (status == IO_OK) {
					num_accesses++;
					if (access_method == READ && config.is_verify_read()) {
						check_read_content(entry, entry_size, off);
					}
					read_bytes += ret;
				}
				if (status == IO_FAIL) {
					perror("access");
					::exit(1);
				}
			}
		}
	}
	printf("thread %d has issued all requests\n", idx);
	io->cleanup();
	gettimeofday(&end_time, NULL);

	// Stop itself.
	stop();
}

int thread_private::attach2cpu()
{
#if NCPUS > 0
	cpu_set_t cpuset;
	pthread_t thread = pthread_self();
	CPU_ZERO(&cpuset);
	int cpu_num = idx % NCPUS;
	CPU_SET(cpu_num, &cpuset);
	int ret = pthread_setaffinity_np(thread, sizeof(cpu_set_t), &cpuset);
	if (ret != 0) {
		perror("pthread_setaffinity_np");
		exit(1);
	}
	return ret;
#else
	return -1;
#endif
}

#ifdef USE_PROCESS
static int process_create(pid_t *pid, void (*func)(void *), void *priv)
{
	pid_t id = fork();

	if (id < 0)
		return -1;

	if (id == 0) {	// child
		func(priv);
		exit(0);
	}

	if (id > 0)
		*pid = id;
	return 0;
}

static int process_join(pid_t pid)
{
	int status;
	pid_t ret = waitpid(pid, &status, 0);
	return ret < 0 ? ret : 0;
}
#endif
<|endoftext|>


<commit_before>/*
    Copyright (C) 2008 Torsten Rahn <rahn@kde.org>

    This file is part of the KDE project

    This library is free software you can redistribute it and/or
    modify it under the terms of the GNU Library General Public
    License as published by the Free Software Foundation either
    version 2 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
    Library General Public License for more details.

    You should have received a copy of the GNU Library General Public License
    aint with this library see the file COPYING.LIB.  If not, write to
    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
    Boston, MA 02110-1301, USA.
*/

#include "GeoSceneFilter.h"

namespace Marble
{

GeoSceneFilter::GeoSceneFilter( const QString& name )
{
    m_name = name;
    m_type = "none";
}

GeoSceneFilter::~GeoSceneFilter()
{
   qDeleteAll( m_palette );
}

QString GeoSceneFilter::name() const
{
    return m_name;
}

void GeoSceneFilter::setName( const QString& name )
{
    m_name = name;
}

QString GeoSceneFilter::type() const
{
    return m_type;
}

void GeoSceneFilter::setType( const QString& type )
{
    m_type = type;
}

QList<GeoScenePalette*> GeoSceneFilter::palette() const
{
    return m_palette;
}

void GeoSceneFilter::addPalette( GeoScenePalette *palette )
{
    m_palette.append( palette );
}

int GeoSceneFilter::removePalette( GeoScenePalette *palette )
{
    return m_palette.removeAll( palette );
}

}
<commit_msg>Use ctor init list.<commit_after>/*
    Copyright (C) 2008 Torsten Rahn <rahn@kde.org>

    This file is part of the KDE project

    This library is free software you can redistribute it and/or
    modify it under the terms of the GNU Library General Public
    License as published by the Free Software Foundation either
    version 2 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
    Library General Public License for more details.

    You should have received a copy of the GNU Library General Public License
    aint with this library see the file COPYING.LIB.  If not, write to
    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
    Boston, MA 02110-1301, USA.
*/

#include "GeoSceneFilter.h"

namespace Marble
{

GeoSceneFilter::GeoSceneFilter( const QString& name )
    : m_name( name ),
      m_type( "none" )
{
}

GeoSceneFilter::~GeoSceneFilter()
{
   qDeleteAll( m_palette );
}

QString GeoSceneFilter::name() const
{
    return m_name;
}

void GeoSceneFilter::setName( const QString& name )
{
    m_name = name;
}

QString GeoSceneFilter::type() const
{
    return m_type;
}

void GeoSceneFilter::setType( const QString& type )
{
    m_type = type;
}

QList<GeoScenePalette*> GeoSceneFilter::palette() const
{
    return m_palette;
}

void GeoSceneFilter::addPalette( GeoScenePalette *palette )
{
    m_palette.append( palette );
}

int GeoSceneFilter::removePalette( GeoScenePalette *palette )
{
    return m_palette.removeAll( palette );
}

}
<|endoftext|>


<commit_before>/*****************************************************************************

YASK: Yet Another Stencil Kernel
Copyright (c) 2014-2018, Intel Corporation

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to
deal in the Software without restriction, including without limitation the
rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
sell copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

* The above copyright notice and this permission notice shall be included in
  all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.

*****************************************************************************/

///////// APIs common to the YASK compiler and kernel. ////////////

// This file uses Doxygen 1.8 markup for API documentation-generation.
// See http://www.stack.nl/~dimitri/doxygen.
/** @file yask_common_api.hpp */

#ifndef YASK_COMMON_API
#define YASK_COMMON_API

#include <string>
#include <iostream>
#include <ostream>
#include <memory>

namespace yask {

    /**
     * \defgroup yask YASK Commmon Utilities
     * Types, clases, and functions used in both the \ref sec_yc and \ref sec_yk.
     * @{
     */

    /// Version information.
    /**
       @returns String describing the current version.
    */
    std::string yask_get_version_string();

    /// Type to use for indexing grids.
    /** Index types are signed to allow negative indices in padding/halos. */
#ifdef SWIG
    typedef long int idx_t;     // SWIG doesn't seem to understand int64_t.
#else
    typedef std::int64_t idx_t;
#endif

    // Forward declarations of class-pointers.

    class yask_output;
    /// Shared pointer to \ref yask_output
    typedef std::shared_ptr<yask_output> yask_output_ptr;

    class yask_file_output;
    /// Shared pointer to \ref yask_file_output
    typedef std::shared_ptr<yask_file_output> yask_file_output_ptr;

    class yask_string_output;
    /// Shared pointer to \ref yask_string_output
    typedef std::shared_ptr<yask_string_output> yask_string_output_ptr;

    class yask_stdout_output;
    /// Shared pointer to \ref yask_stdout_output
    typedef std::shared_ptr<yask_stdout_output> yask_stdout_output_ptr;

    class yask_null_output;
    /// Shared pointer to \ref yask_null_output
    typedef std::shared_ptr<yask_null_output> yask_null_output_ptr;

    /// Exception from YASK framework
    /** Objects of this exception contain additional message from yask framework */
    class yask_exception: public std::exception {
    private:
    	/// Additional message container
    	std::string _msg;

    public:

        /// Construct a YASK exception with no message.
    	yask_exception() {};

        /// Construct a YASK exception with `message`.
    	yask_exception(const std::string& message) :
            _msg(message) {};

    	virtual ~yask_exception() {};

        /// Get default message.
        /** Returns a C-style character string describing the general cause of the current error.
            @returns default message of the exception. */
    	virtual const char* what() noexcept;

    	/// Add additional message to this exception.
    	void add_message(const std::string& message
                         /**< [in] Additional message as string. */ );

        /// Get additional message.
        /** @returns additional message as string */
    	const char* get_message() const;
    };

    /// Factory to create output objects.
    class yask_output_factory {
    public:
        virtual ~yask_output_factory() {}

        /// Create a file output object.
        /**
           This object is used to write output to a file.
           @returns Pointer to new output object or null pointer if
           file cannot be opened.
        */
        virtual yask_file_output_ptr
        new_file_output(const std::string& file_name
                        /**< [in] Name of file to open.
                           Any existing file will be truncated. */ ) const;

        /// Create a string output object.
        /**
           This object is used to write output to a string.
           @returns Pointer to new output object.
        */
        virtual yask_string_output_ptr
        new_string_output() const;

        /// Create a stdout output object.
        /**
           This object is used to write output to the standard output stream.
           @returns Pointer to new output object.
        */
        virtual yask_stdout_output_ptr
        new_stdout_output() const;

        /// Create a null output object.
        /**
           This object is used to discard output.
           @returns Pointer to new output object.
        */
        virtual yask_null_output_ptr
        new_null_output() const;
    };

    /// Base interface for output.
    class yask_output {
    public:
        virtual ~yask_output() {}

        /// Access underlying C++ ostream object.
        /** @returns Reference to ostream. */
        virtual std::ostream& get_ostream() =0;
    };

    /// File output.
    class yask_file_output : public virtual yask_output {
    public:
        virtual ~yask_file_output() {}

        /// Get the filename.
        /** @returns String containing filename given during creation. */
        virtual std::string get_filename() const =0;

        /// Close file.
        virtual void close() =0;
    };

    /// String output.
    class yask_string_output : public virtual yask_output {
    public:
        virtual ~yask_string_output() {}

        /// Get the output.
        /** Does not modify current buffer.
            @returns copy of current buffer's contents. */
        virtual std::string get_string() const =0;

        /// Discard contents of current buffer.
        virtual void discard() =0;
    };

    /// Stdout output.
    class yask_stdout_output : public virtual yask_output {
    public:
        virtual ~yask_stdout_output() {}
    };

    /// Null output.
    /** This object will discard all output. */
    class yask_null_output : public virtual yask_output {
    public:
        virtual ~yask_null_output() {}
    };

    /** @}*/

} // namespace yask.

#endif
<commit_msg>Fix typo in API group.<commit_after>/*****************************************************************************

YASK: Yet Another Stencil Kernel
Copyright (c) 2014-2018, Intel Corporation

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to
deal in the Software without restriction, including without limitation the
rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
sell copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

* The above copyright notice and this permission notice shall be included in
  all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.

*****************************************************************************/

///////// APIs common to the YASK compiler and kernel. ////////////

// This file uses Doxygen 1.8 markup for API documentation-generation.
// See http://www.stack.nl/~dimitri/doxygen.
/** @file yask_common_api.hpp */

#ifndef YASK_COMMON_API
#define YASK_COMMON_API

#include <string>
#include <iostream>
#include <ostream>
#include <memory>

namespace yask {

    /**
     * \defgroup yask YASK Common Utilities
     * Types, clases, and functions used in both the \ref sec_yc and \ref sec_yk.
     * @{
     */

    /// Version information.
    /**
       @returns String describing the current version.
    */
    std::string yask_get_version_string();

    /// Type to use for indexing grids.
    /** Index types are signed to allow negative indices in padding/halos. */
#ifdef SWIG
    typedef long int idx_t;     // SWIG doesn't seem to understand int64_t.
#else
    typedef std::int64_t idx_t;
#endif

    // Forward declarations of class-pointers.

    class yask_output;
    /// Shared pointer to \ref yask_output
    typedef std::shared_ptr<yask_output> yask_output_ptr;

    class yask_file_output;
    /// Shared pointer to \ref yask_file_output
    typedef std::shared_ptr<yask_file_output> yask_file_output_ptr;

    class yask_string_output;
    /// Shared pointer to \ref yask_string_output
    typedef std::shared_ptr<yask_string_output> yask_string_output_ptr;

    class yask_stdout_output;
    /// Shared pointer to \ref yask_stdout_output
    typedef std::shared_ptr<yask_stdout_output> yask_stdout_output_ptr;

    class yask_null_output;
    /// Shared pointer to \ref yask_null_output
    typedef std::shared_ptr<yask_null_output> yask_null_output_ptr;

    /// Exception from YASK framework
    /** Objects of this exception contain additional message from yask framework */
    class yask_exception: public std::exception {
    private:
    	/// Additional message container
    	std::string _msg;

    public:

        /// Construct a YASK exception with no message.
    	yask_exception() {};

        /// Construct a YASK exception with `message`.
    	yask_exception(const std::string& message) :
            _msg(message) {};

    	virtual ~yask_exception() {};

        /// Get default message.
        /** Returns a C-style character string describing the general cause of the current error.
            @returns default message of the exception. */
    	virtual const char* what() noexcept;

    	/// Add additional message to this exception.
    	void add_message(const std::string& message
                         /**< [in] Additional message as string. */ );

        /// Get additional message.
        /** @returns additional message as string */
    	const char* get_message() const;
    };

    /// Factory to create output objects.
    class yask_output_factory {
    public:
        virtual ~yask_output_factory() {}

        /// Create a file output object.
        /**
           This object is used to write output to a file.
           @returns Pointer to new output object or null pointer if
           file cannot be opened.
        */
        virtual yask_file_output_ptr
        new_file_output(const std::string& file_name
                        /**< [in] Name of file to open.
                           Any existing file will be truncated. */ ) const;

        /// Create a string output object.
        /**
           This object is used to write output to a string.
           @returns Pointer to new output object.
        */
        virtual yask_string_output_ptr
        new_string_output() const;

        /// Create a stdout output object.
        /**
           This object is used to write output to the standard output stream.
           @returns Pointer to new output object.
        */
        virtual yask_stdout_output_ptr
        new_stdout_output() const;

        /// Create a null output object.
        /**
           This object is used to discard output.
           @returns Pointer to new output object.
        */
        virtual yask_null_output_ptr
        new_null_output() const;
    };

    /// Base interface for output.
    class yask_output {
    public:
        virtual ~yask_output() {}

        /// Access underlying C++ ostream object.
        /** @returns Reference to ostream. */
        virtual std::ostream& get_ostream() =0;
    };

    /// File output.
    class yask_file_output : public virtual yask_output {
    public:
        virtual ~yask_file_output() {}

        /// Get the filename.
        /** @returns String containing filename given during creation. */
        virtual std::string get_filename() const =0;

        /// Close file.
        virtual void close() =0;
    };

    /// String output.
    class yask_string_output : public virtual yask_output {
    public:
        virtual ~yask_string_output() {}

        /// Get the output.
        /** Does not modify current buffer.
            @returns copy of current buffer's contents. */
        virtual std::string get_string() const =0;

        /// Discard contents of current buffer.
        virtual void discard() =0;
    };

    /// Stdout output.
    class yask_stdout_output : public virtual yask_output {
    public:
        virtual ~yask_stdout_output() {}
    };

    /// Null output.
    /** This object will discard all output. */
    class yask_null_output : public virtual yask_output {
    public:
        virtual ~yask_null_output() {}
    };

    /** @}*/

} // namespace yask.

#endif
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: bmpsum.cxx,v $
 *
 *  $Revision: 1.11 $
 *
 *  last change: $Author: vg $ $Date: 2007-04-11 18:24:14 $
 *
 *  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
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_svtools.hxx"

#include <stdio.h>
#include <signal.h>
#include <vector>
#include <set>
#include <map>

#include <rtl/crc.h>
#include <tools/stream.hxx>
#include <tools/fsys.hxx>
#include <vcl/svapp.hxx>
#include <vcl/bitmap.hxx>
#include <vcl/bmpacc.hxx>
#include <vcl/pngread.hxx>

#include "svtools/solar.hrc"
#include "filedlg.hxx"

#define EXIT_NOERROR        0x00000000
#define EXIT_INVALIDFILE    0x00000001
#define EXIT_COMMONERROR    0x80000000

// ----------
// - BmpSum -
// ----------

class BmpSum
{
private:

    sal_uInt32      cExitCode;

    BOOL            GetCommandOption( const ::std::vector< String >& rArgs, const String& rSwitch, String& rSwitchParam );
    BOOL            GetCommandOptions( const ::std::vector< String >& rArgs, const String& rSwitch, ::std::vector< String >& rSwitchParams );

    void            SetExitCode( BYTE cExit )
                    {
                        if( ( EXIT_NOERROR == cExitCode ) || ( cExit != EXIT_NOERROR ) )
                            cExitCode = cExit;
                    }
    void            ShowUsage();
    void            Message( const String& rText, BYTE cExitCode );

    sal_uInt64      GetCRC( Bitmap& rBmp );

    void            ProcessFile( const String& rBmpFileName );
    void            ProcessFileList( const String& rInFileList, const String& rOutFileList, const String& rOutPath );

public:

                    BmpSum();
                    ~BmpSum();

    int             Start( const ::std::vector< String >& rArgs );
};

// -----------------------------------------------------------------------------

BmpSum::BmpSum()
{
}

// -----------------------------------------------------------------------------

BmpSum::~BmpSum()
{
}

// -----------------------------------------------------------------------

BOOL BmpSum::GetCommandOption( const ::std::vector< String >& rArgs, const String& rSwitch, String& rParam )
{
    BOOL bRet = FALSE;

    for( int i = 0, nCount = rArgs.size(); ( i < nCount ) && !bRet; i++ )
    {
        String  aTestStr( '-' );

        for( int n = 0; ( n < 2 ) && !bRet; n++ )
        {
            aTestStr += rSwitch;

            if( aTestStr.CompareIgnoreCaseToAscii( rArgs[ i ] ) == COMPARE_EQUAL )
            {
                bRet = TRUE;

                if( i < ( nCount - 1 ) )
                    rParam = rArgs[ i + 1 ];
                else
                    rParam = String();
            }

            if( 0 == n )
                aTestStr = '/';
        }
    }

    return bRet;
}

// -----------------------------------------------------------------------

BOOL BmpSum::GetCommandOptions( const ::std::vector< String >& rArgs, const String& rSwitch, ::std::vector< String >& rParams )
{
    BOOL bRet = FALSE;

    for( int i = 0, nCount = rArgs.size(); ( i < nCount ); i++ )
    {
        String  aTestStr( '-' );

        for( int n = 0; ( n < 2 ) && !bRet; n++ )
        {
            aTestStr += rSwitch;

            if( aTestStr.CompareIgnoreCaseToAscii( rArgs[ i ] ) == COMPARE_EQUAL )
            {
                if( i < ( nCount - 1 ) )
                    rParams.push_back( rArgs[ i + 1 ] );
                else
                    rParams.push_back( String() );

                break;
            }

            if( 0 == n )
                aTestStr = '/';
        }
    }

    return( rParams.size() > 0 );
}

// -----------------------------------------------------------------------

void BmpSum::Message( const String& rText, BYTE nExitCode )
{
    if( EXIT_NOERROR != nExitCode )
        SetExitCode( nExitCode );

    ByteString aText( rText, RTL_TEXTENCODING_UTF8 );
    aText.Append( "\r\n" );
    fprintf( stderr, aText.GetBuffer() );
}

// -----------------------------------------------------------------------------

void BmpSum::ShowUsage()
{
    Message( String( RTL_CONSTASCII_USTRINGPARAM( "Usage:" ) ), EXIT_NOERROR );
    Message( String( RTL_CONSTASCII_USTRINGPARAM( "    bmpsum bmp_inputfile" ) ), EXIT_NOERROR );
    Message( String( RTL_CONSTASCII_USTRINGPARAM( "    bmpsum -i input_filelist -o output_filelist [-p path_for_copied_bitmaps]" ) ), EXIT_NOERROR );
    Message( String( RTL_CONSTASCII_USTRINGPARAM( "Options:" ) ), EXIT_NOERROR );
    Message( String( RTL_CONSTASCII_USTRINGPARAM( "Examples:" ) ), EXIT_NOERROR );
    Message( String( RTL_CONSTASCII_USTRINGPARAM( "    bmpsum /home/test.bmp" ) ), EXIT_NOERROR );
    Message( String( RTL_CONSTASCII_USTRINGPARAM( "    bmpsum -i /home/inlist.txt -o /home/outlist.txt" ) ), EXIT_NOERROR );
    Message( String( RTL_CONSTASCII_USTRINGPARAM( "    bmpsum -i /home/inlist.txt -o /home/outlist.txt -p /home/outpath" ) ), EXIT_NOERROR );
}

// -----------------------------------------------------------------------------

int BmpSum::Start( const ::std::vector< String >& rArgs )
{
    cExitCode = EXIT_NOERROR;

    if( rArgs.size() >= 1 )
    {
        String  aInFileList, aOutFileList, aOutPath;

        if( GetCommandOption( rArgs, 'i', aInFileList ) &&
            GetCommandOption( rArgs, 'o', aOutFileList ) )
        {
            GetCommandOption( rArgs, 'p', aOutPath );
            ProcessFileList( aInFileList, aOutFileList, aOutPath );
        }
        else
        {
            ProcessFile( rArgs[ 0 ] );
        }
    }
    else
    {
        ShowUsage();
        cExitCode = EXIT_COMMONERROR;
    }

    return cExitCode;
}

// -----------------------------------------------------------------------------

sal_uInt64 BmpSum::GetCRC( Bitmap& rBmp )
{
    BitmapReadAccess* pRAcc = rBmp.AcquireReadAccess();
    sal_uInt64        nRet = 0;
    sal_uInt32        nCrc = 0;

    if( pRAcc && pRAcc->Width() && pRAcc->Height() )
    {
        SVBT32 aBT32;

        for( long nY = 0; nY < pRAcc->Height(); ++nY )
        {
            for( long nX = 0; nX < pRAcc->Width(); ++nX )
            {
                const BitmapColor aCol( pRAcc->GetColor( nY, nX ) );

                UInt32ToSVBT32( aCol.GetRed(), aBT32 );
                nCrc = rtl_crc32( nCrc, aBT32, 4 );

                UInt32ToSVBT32( aCol.GetGreen(), aBT32 );
                nCrc = rtl_crc32( nCrc, aBT32, 4 );

                UInt32ToSVBT32( aCol.GetBlue(), aBT32 );
                nCrc = rtl_crc32( nCrc, aBT32, 4 );
            }
        }

        nRet = ( ( (sal_uInt64) pRAcc->Width() ) << 48 ) |
               ( ( (sal_uInt64) pRAcc->Height() ) << 32 ) |
               ( (sal_uInt64) nCrc );
    }

    rBmp.ReleaseAccess( pRAcc );

    return nRet;
}

// -----------------------------------------------------------------------------

void BmpSum::ProcessFile( const String& rBmpFileName )
{
    SvFileStream aIStm( rBmpFileName, STREAM_READ );

    if( aIStm.IsOpen() )
    {
        Bitmap aBmp;

        aIStm >> aBmp;

        if( !aBmp.IsEmpty() )
        {
#ifdef WNT
            fprintf( stdout, "%I64u\r\n", GetCRC( aBmp ) );
#else
            fprintf( stdout, "%llu\r\n", GetCRC( aBmp ) );
#endif
        }
        else
        {
            aIStm.ResetError();
            aIStm.Seek( 0 );

               ::vcl::PNGReader aPngReader( aIStm );

            aBmp = aPngReader.Read().GetBitmap();

              if( !aBmp.IsEmpty() )
            {
#ifdef WNT
                fprintf( stdout, "%I64u\r\n", GetCRC( aBmp ) );
#else
                fprintf( stdout, "%llu\r\n", GetCRC( aBmp ) );
#endif
            }
            else
                Message( String( RTL_CONSTASCII_USTRINGPARAM( "file not valid" ) ), EXIT_INVALIDFILE );
        }
    }
}

// -----------------------------------------------------------------------------

void BmpSum::ProcessFileList( const String& rInFileList,
                              const String& rOutFileList,
                              const String& rOutPath )
{
    SvFileStream    aIStm( rInFileList, STREAM_READ );
    SvFileStream    aOStm( rOutFileList, STREAM_WRITE | STREAM_TRUNC );
    const DirEntry  aBaseDir( rOutPath );

    if( rOutPath.Len() )
        aBaseDir.MakeDir();

    if( aIStm.IsOpen() && aOStm.IsOpen() )
    {
        ByteString                  aReadLine;
        ::std::set< ByteString >    aFileNameSet;

        while( aIStm.ReadLine( aReadLine ) )
        {
            if( aReadLine.Len() )
                aFileNameSet.insert( aReadLine );

            if( aReadLine.Search( "enus" ) != STRING_NOTFOUND )
            {
                static const char* aLanguages[] =
                {
                    "chinsim",
                    "chintrad",
                    "dtch",
                    "enus",
                    "fren",
                    "hebrew"
                    "ital",
                    "japn",
                    "korean",
                    "pol",
                    "poln",
                    "port",
                    "russ",
                    "span",
                    "turk"
                };

                for( sal_uInt32 n = 0; n < 14; ++n )
                {
                    ByteString aLangPath( aReadLine );

                    aLangPath.SearchAndReplace( "enus", aLanguages[ n ] );

                    DirEntry aTestFile( aLangPath );

                    if( aTestFile.Exists() )
                        aFileNameSet.insert( aLangPath );
                }
            }

            aReadLine.Erase();
        }

        aIStm.Close();

        ::std::set< ByteString >::iterator aIter( aFileNameSet.begin() );
        ::std::map< sal_uInt64, ::std::vector< ByteString > > aFileNameMap;

        while( aIter != aFileNameSet.end() )
        {
            ByteString      aStr( *aIter++ );
            SvFileStream    aBmpStm( String( aStr.GetBuffer(), RTL_TEXTENCODING_ASCII_US ), STREAM_READ );
            sal_uInt64      nCRC = 0;

            if( aBmpStm.IsOpen() )
            {
                Bitmap aBmp;

                aBmpStm >> aBmp;

                if( !aBmp.IsEmpty() )
                    nCRC = GetCRC( aBmp );
                else
                {
                    aBmpStm.ResetError();
                    aBmpStm.Seek( 0 );

                       ::vcl::PNGReader aPngReader( aBmpStm );

                    aBmp = aPngReader.Read().GetBitmap();

                      if( !aBmp.IsEmpty() )
                           nCRC = GetCRC( aBmp );

                    else
                        fprintf( stderr, "%s could not be opened\n", aStr.GetBuffer() );
               }

                aBmpStm.Close();
            }

            if( nCRC )
            {
                ::std::map< sal_uInt64, ::std::vector< ByteString > >::iterator aFound( aFileNameMap.find( nCRC ) );

                if( aFound != aFileNameMap.end() )
                    (*aFound).second.push_back( aStr );
                else
                {
                    ::std::vector< ByteString > aVector( 1, aStr );
                    aFileNameMap[ nCRC ]  = aVector;
                }

            }
            else
            {
                ::std::vector< ByteString > aVector( 1, aStr );
                aFileNameMap[ nCRC ]  = aVector;
            }
        }

        ::std::map< sal_uInt64, ::std::vector< ByteString > >::iterator aMapIter( aFileNameMap.begin() );
        sal_uInt32 nFileCount = 0;

        while( aMapIter != aFileNameMap.end() )
        {
            ::std::pair< const sal_uInt64, ::std::vector< ByteString > > aPair( *aMapIter++ );
            ::std::vector< ByteString > aFileNameVector( aPair.second );

            // write new entries
            for( sal_uInt32 i = 0; i < aFileNameVector.size(); ++i )
            {
                ByteString  aStr( ByteString::CreateFromInt64( aPair.first ) );
                ByteString  aFileName( aFileNameVector[ i ] );
                DirEntry    aSrcFile( aFileName );

                aStr += '\t';
                aStr += aFileName;

                aOStm.WriteLine( aStr );

                // copy bitmap
                if( rOutPath.Len() )
                {
                    if( aFileName.Search( ":\\" ) != STRING_NOTFOUND )
                        aFileName.Erase( 0, aFileName.Search( ":\\" ) + 2 );

                    aFileName.SearchAndReplaceAll( '\\', '/' );

                    sal_uInt16  nTokenCount = aFileName.GetTokenCount( '/' );
                    DirEntry    aNewDir( aBaseDir );

                    for( sal_uInt16 n = 0; ( n < nTokenCount - 1 ); n++ )
                    {
                        aNewDir += DirEntry( aFileName.GetToken( n, '/' ) );
                        aNewDir.MakeDir();
                    }

                    aNewDir += DirEntry( aFileName.GetToken( nTokenCount - 1, '/' ) );
                    aSrcFile.CopyTo( aNewDir, FSYS_ACTION_COPYFILE );
                }
            }

            ++nFileCount;
        }

        fprintf(
            stdout, "unique file count: %lu",
            sal::static_int_cast< unsigned long >(nFileCount) );
    }
}

// --------
// - Main -
// --------

int main( int nArgCount, char* ppArgs[] )
{
    ::std::vector< String > aArgs;
    BmpSum                  aBmpSum;

    InitVCL( com::sun::star::uno::Reference< com::sun::star::lang::XMultiServiceFactory >() );

    for( int i = 1; i < nArgCount; i++ )
        aArgs.push_back( String( ppArgs[ i ], RTL_TEXTENCODING_ASCII_US ) );

    return aBmpSum.Start( aArgs );
}
<commit_msg>INTEGRATION: CWS sb81 (1.11.198); FILE MERGED 2007/11/05 08:50:15 sb 1.11.198.1: #i83263# Portable fprintf family conversion specifications.<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: bmpsum.cxx,v $
 *
 *  $Revision: 1.12 $
 *
 *  last change: $Author: ihi $ $Date: 2007-11-22 12:00:43 $
 *
 *  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
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_svtools.hxx"

#include <stdio.h>
#include <signal.h>
#include <vector>
#include <set>
#include <map>

#include <rtl/crc.h>
#include <tools/stream.hxx>
#include <tools/fsys.hxx>
#include <vcl/svapp.hxx>
#include <vcl/bitmap.hxx>
#include <vcl/bmpacc.hxx>
#include <vcl/pngread.hxx>

#include "svtools/solar.hrc"
#include "filedlg.hxx"

#define EXIT_NOERROR        0x00000000
#define EXIT_INVALIDFILE    0x00000001
#define EXIT_COMMONERROR    0x80000000

// ----------
// - BmpSum -
// ----------

class BmpSum
{
private:

    sal_uInt32      cExitCode;

    BOOL            GetCommandOption( const ::std::vector< String >& rArgs, const String& rSwitch, String& rSwitchParam );
    BOOL            GetCommandOptions( const ::std::vector< String >& rArgs, const String& rSwitch, ::std::vector< String >& rSwitchParams );

    void            SetExitCode( BYTE cExit )
                    {
                        if( ( EXIT_NOERROR == cExitCode ) || ( cExit != EXIT_NOERROR ) )
                            cExitCode = cExit;
                    }
    void            ShowUsage();
    void            Message( const String& rText, BYTE cExitCode );

    sal_uInt64      GetCRC( Bitmap& rBmp );

    void            ProcessFile( const String& rBmpFileName );
    void            ProcessFileList( const String& rInFileList, const String& rOutFileList, const String& rOutPath );

public:

                    BmpSum();
                    ~BmpSum();

    int             Start( const ::std::vector< String >& rArgs );
};

// -----------------------------------------------------------------------------

BmpSum::BmpSum()
{
}

// -----------------------------------------------------------------------------

BmpSum::~BmpSum()
{
}

// -----------------------------------------------------------------------

BOOL BmpSum::GetCommandOption( const ::std::vector< String >& rArgs, const String& rSwitch, String& rParam )
{
    BOOL bRet = FALSE;

    for( int i = 0, nCount = rArgs.size(); ( i < nCount ) && !bRet; i++ )
    {
        String  aTestStr( '-' );

        for( int n = 0; ( n < 2 ) && !bRet; n++ )
        {
            aTestStr += rSwitch;

            if( aTestStr.CompareIgnoreCaseToAscii( rArgs[ i ] ) == COMPARE_EQUAL )
            {
                bRet = TRUE;

                if( i < ( nCount - 1 ) )
                    rParam = rArgs[ i + 1 ];
                else
                    rParam = String();
            }

            if( 0 == n )
                aTestStr = '/';
        }
    }

    return bRet;
}

// -----------------------------------------------------------------------

BOOL BmpSum::GetCommandOptions( const ::std::vector< String >& rArgs, const String& rSwitch, ::std::vector< String >& rParams )
{
    BOOL bRet = FALSE;

    for( int i = 0, nCount = rArgs.size(); ( i < nCount ); i++ )
    {
        String  aTestStr( '-' );

        for( int n = 0; ( n < 2 ) && !bRet; n++ )
        {
            aTestStr += rSwitch;

            if( aTestStr.CompareIgnoreCaseToAscii( rArgs[ i ] ) == COMPARE_EQUAL )
            {
                if( i < ( nCount - 1 ) )
                    rParams.push_back( rArgs[ i + 1 ] );
                else
                    rParams.push_back( String() );

                break;
            }

            if( 0 == n )
                aTestStr = '/';
        }
    }

    return( rParams.size() > 0 );
}

// -----------------------------------------------------------------------

void BmpSum::Message( const String& rText, BYTE nExitCode )
{
    if( EXIT_NOERROR != nExitCode )
        SetExitCode( nExitCode );

    ByteString aText( rText, RTL_TEXTENCODING_UTF8 );
    aText.Append( "\r\n" );
    fprintf( stderr, aText.GetBuffer() );
}

// -----------------------------------------------------------------------------

void BmpSum::ShowUsage()
{
    Message( String( RTL_CONSTASCII_USTRINGPARAM( "Usage:" ) ), EXIT_NOERROR );
    Message( String( RTL_CONSTASCII_USTRINGPARAM( "    bmpsum bmp_inputfile" ) ), EXIT_NOERROR );
    Message( String( RTL_CONSTASCII_USTRINGPARAM( "    bmpsum -i input_filelist -o output_filelist [-p path_for_copied_bitmaps]" ) ), EXIT_NOERROR );
    Message( String( RTL_CONSTASCII_USTRINGPARAM( "Options:" ) ), EXIT_NOERROR );
    Message( String( RTL_CONSTASCII_USTRINGPARAM( "Examples:" ) ), EXIT_NOERROR );
    Message( String( RTL_CONSTASCII_USTRINGPARAM( "    bmpsum /home/test.bmp" ) ), EXIT_NOERROR );
    Message( String( RTL_CONSTASCII_USTRINGPARAM( "    bmpsum -i /home/inlist.txt -o /home/outlist.txt" ) ), EXIT_NOERROR );
    Message( String( RTL_CONSTASCII_USTRINGPARAM( "    bmpsum -i /home/inlist.txt -o /home/outlist.txt -p /home/outpath" ) ), EXIT_NOERROR );
}

// -----------------------------------------------------------------------------

int BmpSum::Start( const ::std::vector< String >& rArgs )
{
    cExitCode = EXIT_NOERROR;

    if( rArgs.size() >= 1 )
    {
        String  aInFileList, aOutFileList, aOutPath;

        if( GetCommandOption( rArgs, 'i', aInFileList ) &&
            GetCommandOption( rArgs, 'o', aOutFileList ) )
        {
            GetCommandOption( rArgs, 'p', aOutPath );
            ProcessFileList( aInFileList, aOutFileList, aOutPath );
        }
        else
        {
            ProcessFile( rArgs[ 0 ] );
        }
    }
    else
    {
        ShowUsage();
        cExitCode = EXIT_COMMONERROR;
    }

    return cExitCode;
}

// -----------------------------------------------------------------------------

sal_uInt64 BmpSum::GetCRC( Bitmap& rBmp )
{
    BitmapReadAccess* pRAcc = rBmp.AcquireReadAccess();
    sal_uInt64        nRet = 0;
    sal_uInt32        nCrc = 0;

    if( pRAcc && pRAcc->Width() && pRAcc->Height() )
    {
        SVBT32 aBT32;

        for( long nY = 0; nY < pRAcc->Height(); ++nY )
        {
            for( long nX = 0; nX < pRAcc->Width(); ++nX )
            {
                const BitmapColor aCol( pRAcc->GetColor( nY, nX ) );

                UInt32ToSVBT32( aCol.GetRed(), aBT32 );
                nCrc = rtl_crc32( nCrc, aBT32, 4 );

                UInt32ToSVBT32( aCol.GetGreen(), aBT32 );
                nCrc = rtl_crc32( nCrc, aBT32, 4 );

                UInt32ToSVBT32( aCol.GetBlue(), aBT32 );
                nCrc = rtl_crc32( nCrc, aBT32, 4 );
            }
        }

        nRet = ( ( (sal_uInt64) pRAcc->Width() ) << 48 ) |
               ( ( (sal_uInt64) pRAcc->Height() ) << 32 ) |
               ( (sal_uInt64) nCrc );
    }

    rBmp.ReleaseAccess( pRAcc );

    return nRet;
}

// -----------------------------------------------------------------------------

void BmpSum::ProcessFile( const String& rBmpFileName )
{
    SvFileStream aIStm( rBmpFileName, STREAM_READ );

    if( aIStm.IsOpen() )
    {
        Bitmap aBmp;

        aIStm >> aBmp;

        if( !aBmp.IsEmpty() )
        {
            fprintf( stdout, "%" SAL_PRIuUINT64 "\r\n", GetCRC( aBmp ) );
        }
        else
        {
            aIStm.ResetError();
            aIStm.Seek( 0 );

               ::vcl::PNGReader aPngReader( aIStm );

            aBmp = aPngReader.Read().GetBitmap();

              if( !aBmp.IsEmpty() )
            {
                fprintf( stdout, "%" SAL_PRIuUINT64 "\r\n", GetCRC( aBmp ) );
            }
            else
                Message( String( RTL_CONSTASCII_USTRINGPARAM( "file not valid" ) ), EXIT_INVALIDFILE );
        }
    }
}

// -----------------------------------------------------------------------------

void BmpSum::ProcessFileList( const String& rInFileList,
                              const String& rOutFileList,
                              const String& rOutPath )
{
    SvFileStream    aIStm( rInFileList, STREAM_READ );
    SvFileStream    aOStm( rOutFileList, STREAM_WRITE | STREAM_TRUNC );
    const DirEntry  aBaseDir( rOutPath );

    if( rOutPath.Len() )
        aBaseDir.MakeDir();

    if( aIStm.IsOpen() && aOStm.IsOpen() )
    {
        ByteString                  aReadLine;
        ::std::set< ByteString >    aFileNameSet;

        while( aIStm.ReadLine( aReadLine ) )
        {
            if( aReadLine.Len() )
                aFileNameSet.insert( aReadLine );

            if( aReadLine.Search( "enus" ) != STRING_NOTFOUND )
            {
                static const char* aLanguages[] =
                {
                    "chinsim",
                    "chintrad",
                    "dtch",
                    "enus",
                    "fren",
                    "hebrew"
                    "ital",
                    "japn",
                    "korean",
                    "pol",
                    "poln",
                    "port",
                    "russ",
                    "span",
                    "turk"
                };

                for( sal_uInt32 n = 0; n < 14; ++n )
                {
                    ByteString aLangPath( aReadLine );

                    aLangPath.SearchAndReplace( "enus", aLanguages[ n ] );

                    DirEntry aTestFile( aLangPath );

                    if( aTestFile.Exists() )
                        aFileNameSet.insert( aLangPath );
                }
            }

            aReadLine.Erase();
        }

        aIStm.Close();

        ::std::set< ByteString >::iterator aIter( aFileNameSet.begin() );
        ::std::map< sal_uInt64, ::std::vector< ByteString > > aFileNameMap;

        while( aIter != aFileNameSet.end() )
        {
            ByteString      aStr( *aIter++ );
            SvFileStream    aBmpStm( String( aStr.GetBuffer(), RTL_TEXTENCODING_ASCII_US ), STREAM_READ );
            sal_uInt64      nCRC = 0;

            if( aBmpStm.IsOpen() )
            {
                Bitmap aBmp;

                aBmpStm >> aBmp;

                if( !aBmp.IsEmpty() )
                    nCRC = GetCRC( aBmp );
                else
                {
                    aBmpStm.ResetError();
                    aBmpStm.Seek( 0 );

                       ::vcl::PNGReader aPngReader( aBmpStm );

                    aBmp = aPngReader.Read().GetBitmap();

                      if( !aBmp.IsEmpty() )
                           nCRC = GetCRC( aBmp );

                    else
                        fprintf( stderr, "%s could not be opened\n", aStr.GetBuffer() );
               }

                aBmpStm.Close();
            }

            if( nCRC )
            {
                ::std::map< sal_uInt64, ::std::vector< ByteString > >::iterator aFound( aFileNameMap.find( nCRC ) );

                if( aFound != aFileNameMap.end() )
                    (*aFound).second.push_back( aStr );
                else
                {
                    ::std::vector< ByteString > aVector( 1, aStr );
                    aFileNameMap[ nCRC ]  = aVector;
                }

            }
            else
            {
                ::std::vector< ByteString > aVector( 1, aStr );
                aFileNameMap[ nCRC ]  = aVector;
            }
        }

        ::std::map< sal_uInt64, ::std::vector< ByteString > >::iterator aMapIter( aFileNameMap.begin() );
        sal_uInt32 nFileCount = 0;

        while( aMapIter != aFileNameMap.end() )
        {
            ::std::pair< const sal_uInt64, ::std::vector< ByteString > > aPair( *aMapIter++ );
            ::std::vector< ByteString > aFileNameVector( aPair.second );

            // write new entries
            for( sal_uInt32 i = 0; i < aFileNameVector.size(); ++i )
            {
                ByteString  aStr( ByteString::CreateFromInt64( aPair.first ) );
                ByteString  aFileName( aFileNameVector[ i ] );
                DirEntry    aSrcFile( aFileName );

                aStr += '\t';
                aStr += aFileName;

                aOStm.WriteLine( aStr );

                // copy bitmap
                if( rOutPath.Len() )
                {
                    if( aFileName.Search( ":\\" ) != STRING_NOTFOUND )
                        aFileName.Erase( 0, aFileName.Search( ":\\" ) + 2 );

                    aFileName.SearchAndReplaceAll( '\\', '/' );

                    sal_uInt16  nTokenCount = aFileName.GetTokenCount( '/' );
                    DirEntry    aNewDir( aBaseDir );

                    for( sal_uInt16 n = 0; ( n < nTokenCount - 1 ); n++ )
                    {
                        aNewDir += DirEntry( aFileName.GetToken( n, '/' ) );
                        aNewDir.MakeDir();
                    }

                    aNewDir += DirEntry( aFileName.GetToken( nTokenCount - 1, '/' ) );
                    aSrcFile.CopyTo( aNewDir, FSYS_ACTION_COPYFILE );
                }
            }

            ++nFileCount;
        }

        fprintf(
            stdout, "unique file count: %lu",
            sal::static_int_cast< unsigned long >(nFileCount) );
    }
}

// --------
// - Main -
// --------

int main( int nArgCount, char* ppArgs[] )
{
    ::std::vector< String > aArgs;
    BmpSum                  aBmpSum;

    InitVCL( com::sun::star::uno::Reference< com::sun::star::lang::XMultiServiceFactory >() );

    for( int i = 1; i < nArgCount; i++ )
        aArgs.push_back( String( ppArgs[ i ], RTL_TEXTENCODING_ASCII_US ) );

    return aBmpSum.Start( aArgs );
}
<|endoftext|>