<commit_before>#pragma once
#ifndef DELEGATE_HPP
# define DELEGATE_HPP

#include <cassert>

#include <memory>

#include <new>

#include <type_traits>

#include <utility>

template <typename T> class delegate;

template<class R, class ...A>
class delegate<R (A...)>
{
  typedef R (*stub_ptr_type)(void*, A&&...);

  delegate(void* const o, stub_ptr_type const m) noexcept
    : object_ptr_(o),
      stub_ptr_(m)
  {
  }

public:
  delegate() = default;

  delegate(delegate const&) = default;

  delegate(delegate&&) = default;

  template <class C>
  explicit delegate(C const* const o) noexcept
    : object_ptr_(const_cast<C*>(o))
  {
  }

  template <class C>
  explicit delegate(C const& o) noexcept
    : object_ptr_(const_cast<C*>(&o))
  {
  }

  delegate(R (* const function_ptr)(A...))
  {
    *this = from(function_ptr);
  }

  template <class C>
  delegate(C* const object_ptr, R (C::* const method_ptr)(A...))
  {
    *this = from(object_ptr, method_ptr);
  }

  template <class C>
  delegate(C* const object_ptr, R (C::* const method_ptr)(A...) const)
  {
    *this = from(object_ptr, method_ptr);
  }

  template <class C>
  delegate(C& object, R (C::* const method_ptr)(A...))
  {
    *this = from(object, method_ptr);
  }

  template <class C>
  delegate(C const& object, R (C::* const method_ptr)(A...) const)
  {
    *this = from(object, method_ptr);
  }

  template <
    typename T,
    typename = typename std::enable_if<
      !std::is_same<delegate, typename std::decay<T>::type>::value
    >::type
  >
  delegate(T&& f)
    : store_(operator new(sizeof(T)),
        functor_deleter<typename std::decay<T>::type>),
      store_size_(sizeof(T))
  {
    typedef typename std::decay<T>::type functor_type;

    new (store_.get()) functor_type(std::forward<T>(f));

    object_ptr_ = store_.get();

    stub_ptr_ = functor_stub<functor_type>;

    deleter_ = destructor_stub<functor_type>;
  }

  delegate& operator=(delegate const&) = default;

  delegate& operator=(delegate&& rhs) = default;

  template <class C>
  delegate& operator=(R (C::* const rhs)(A...))
  {
    return *this = from(static_cast<C*>(object_ptr_), rhs);
  }

  template <class C>
  delegate& operator=(R (C::* const rhs)(A...) const)
  {
    return *this = from(static_cast<C const*>(object_ptr_), rhs);
  }

  template <
    typename T,
    typename = typename std::enable_if<
      !std::is_same<delegate, typename std::decay<T>::type>::value
    >::type
  >
  delegate& operator=(T&& f)
  {
    typedef typename std::decay<T>::type functor_type;

    if ((sizeof(T) > store_size_)
      || (decltype(store_.use_count())(1) != store_.use_count()))
    {
      store_.reset(operator new(sizeof(T)), functor_deleter<functor_type>);

      store_size_ = sizeof(T);
    }
    else
    {
      deleter_(store_.get());
    }

    new (store_.get()) functor_type(std::forward<T>(f));

    object_ptr_ = store_.get();

    stub_ptr_ = functor_stub<functor_type>;

    deleter_ = destructor_stub<functor_type>;

    return *this;
  }

  template <R (* const function_ptr)(A...)>
  static delegate from() noexcept
  {
    return { nullptr, function_stub<function_ptr> };
  }

  template <class C, R (C::* const method_ptr)(A...)>
  static delegate from(C* object_ptr) noexcept
  {
    return { object_ptr, method_stub<C, method_ptr> };
  }

  template <class C, R (C::* const method_ptr)(A...) const>
  static delegate from(C const* object_ptr) noexcept
  {
    return { const_cast<C*>(object_ptr), const_method_stub<C, method_ptr> };
  }

  template <class C, R (C::* const method_ptr)(A...)>
  static delegate from(C& object) noexcept
  {
    return { &object, method_stub<C, method_ptr> };
  }

  template <class C, R (C::* const method_ptr)(A...) const>
  static delegate from(C const& object) noexcept
  {
    return { const_cast<C*>(&object), const_method_stub<C, method_ptr> };
  }

  template <typename T>
  static delegate from(T&& f)
  {
    return std::forward<T>(f);
  }

  static delegate from(R (* const function_ptr)(A...))
  {
    return [function_ptr](A&&... args) {
      return (*function_ptr)(std::forward<A>(args)...); };
  }

  template <class C>
  static delegate from(C* const object_ptr,
    R (C::* const method_ptr)(A...))
  {
    return [object_ptr, method_ptr](A&&... args) {
      return (object_ptr->*method_ptr)(std::forward<A>(args)...); };
  }

  template <class C>
  static delegate from(C const* const object_ptr,
    R (C::* const method_ptr)(A...) const)
  {
    return [object_ptr, method_ptr](A&&... args) {
      return (object_ptr->*method_ptr)(std::forward<A>(args)...); };
  }

  template <class C>
  static delegate from(C& object, R (C::* const method_ptr)(A...))
  {
    return [&object, method_ptr](A&&... args) {
      return (object.*method_ptr)(std::forward<A>(args)...); };
  }

  template <class C>
  static delegate from(C const& object,
    R (C::* const method_ptr)(A...) const)
  {
    return [&object, method_ptr](A&&... args) {
      return (object.*method_ptr)(std::forward<A>(args)...); };
  }

  void reset() { stub_ptr_ = nullptr; store_.reset(); }

  void swap(delegate& other) noexcept { ::std::swap(*this, other); }

  bool operator==(delegate const& rhs) const noexcept
  {
    return (object_ptr_ == rhs.object_ptr_) && (stub_ptr_ == rhs.stub_ptr_);
  }

  bool operator!=(delegate const& rhs) const noexcept
  {
    return !operator==(rhs);
  }

  bool operator<(delegate const& rhs) const noexcept
  {
    return (object_ptr_ < rhs.object_ptr_) || (stub_ptr_ < rhs.stub_ptr_);
  }

  explicit operator bool() const noexcept { return stub_ptr_; }

  R operator()(A... args) const
  {
//  assert(stub_ptr);
    return stub_ptr_(object_ptr_, std::forward<A>(args)...);
  }

private:
  friend class ::std::hash<delegate>;

  typedef void (*deleter_type)(void*);

  void* object_ptr_;
  stub_ptr_type stub_ptr_{};

  deleter_type deleter_;

  std::shared_ptr<void> store_;
  std::size_t store_size_;

  template <class T>
  static void destructor_stub(void* const p)
  {
    static_cast<T*>(p)->~T();
  }

  template <class T>
  static void functor_deleter(void* const p)
  {
    static_cast<T*>(p)->~T();

    operator delete(p);
  }

  template <R (*function_ptr)(A...)>
  static R function_stub(void* const, A&&... args)
  {
    return function_ptr(std::forward<A>(args)...);
  }

  template <class C, R (C::*method_ptr)(A...)>
  static R method_stub(void* const object_ptr, A&&... args)
  {
    return (static_cast<C*>(object_ptr)->*method_ptr)(
      std::forward<A>(args)...);
  }

  template <class C, R (C::*method_ptr)(A...) const>
  static R const_method_stub(void* const object_ptr, A&&... args)
  {
    return (static_cast<C const*>(object_ptr)->*method_ptr)(
      std::forward<A>(args)...);
  }

  template <typename T>
  static R functor_stub(void* const object_ptr, A&&... args)
  {
    return (*static_cast<T*>(object_ptr))(std::forward<A>(args)...);
  }
};

namespace std
{
  template <typename R, typename ...A>
  struct hash<delegate<R (A...)> >
  {
    size_t operator()(delegate<R (A...)> const& d) const noexcept
    {
      auto const seed(hash<void*>()(d.object_ptr_) + 0x9e3779b9);

      return hash<typename delegate<R (A...)>::stub_ptr_type>()(d.stub_ptr_)
        + 0x9e3779b9 + (seed << 6) + (seed >> 2);
    }
  };
}

#endif // DELEGATE_HPP
<commit_msg>strips<commit_after>#pragma once
#ifndef DELEGATE_HPP
# define DELEGATE_HPP

#include <cassert>

#include <memory>

#include <new>

#include <type_traits>

#include <utility>

template <typename T> class delegate;

template<class R, class ...A>
class delegate<R (A...)>
{
  typedef R (*stub_ptr_type)(void*, A&&...);

  delegate(void* const o, stub_ptr_type const m) noexcept
    : object_ptr_(o),
      stub_ptr_(m)
  {
  }

public:
  delegate() = default;

  delegate(delegate const&) = default;

  delegate(delegate&&) = default;

  template <class C>
  explicit delegate(C const* const o) noexcept
    : object_ptr_(const_cast<C*>(o))
  {
  }

  template <class C>
  explicit delegate(C const& o) noexcept
    : object_ptr_(const_cast<C*>(&o))
  {
  }

  delegate(R (* const function_ptr)(A...))
  {
    *this = from(function_ptr);
  }

  template <class C>
  delegate(C* const object_ptr, R (C::* const method_ptr)(A...))
  {
    *this = from(object_ptr, method_ptr);
  }

  template <class C>
  delegate(C* const object_ptr, R (C::* const method_ptr)(A...) const)
  {
    *this = from(object_ptr, method_ptr);
  }

  template <class C>
  delegate(C& object, R (C::* const method_ptr)(A...))
  {
    *this = from(object, method_ptr);
  }

  template <class C>
  delegate(C const& object, R (C::* const method_ptr)(A...) const)
  {
    *this = from(object, method_ptr);
  }

  template <
    typename T,
    typename = typename std::enable_if<
      !std::is_same<delegate, typename std::decay<T>::type>::value
    >::type
  >
  delegate(T&& f)
    : store_(operator new(sizeof(T)),
        functor_deleter<typename std::decay<T>::type>),
      store_size_(sizeof(T))
  {
    typedef typename std::decay<T>::type functor_type;

    new (store_.get()) functor_type(std::forward<T>(f));

    object_ptr_ = store_.get();

    stub_ptr_ = functor_stub<functor_type>;

    deleter_ = destructor_stub<functor_type>;
  }

  delegate& operator=(delegate const&) = default;

  delegate& operator=(delegate&& rhs) = default;

  delegate& operator=(R (* const function_ptr)(A...))
  {
    return *this = from(function_ptr);
  }

  template <class C>
  delegate& operator=(R (C::* const rhs)(A...))
  {
    return *this = from(static_cast<C*>(object_ptr_), rhs);
  }

  template <class C>
  delegate& operator=(R (C::* const rhs)(A...) const)
  {
    return *this = from(static_cast<C const*>(object_ptr_), rhs);
  }

  template <
    typename T,
    typename = typename std::enable_if<
      !std::is_same<delegate, typename std::decay<T>::type>::value
    >::type
  >
  delegate& operator=(T&& f)
  {
    typedef typename std::decay<T>::type functor_type;

    if ((sizeof(T) > store_size_)
      || (decltype(store_.use_count())(1) != store_.use_count()))
    {
      store_.reset(operator new(sizeof(T)), functor_deleter<functor_type>);

      store_size_ = sizeof(T);
    }
    else
    {
      deleter_(store_.get());
    }

    new (store_.get()) functor_type(std::forward<T>(f));

    object_ptr_ = store_.get();

    stub_ptr_ = functor_stub<functor_type>;

    deleter_ = destructor_stub<functor_type>;

    return *this;
  }

  template <R (* const function_ptr)(A...)>
  static delegate from() noexcept
  {
    return { nullptr, function_stub<function_ptr> };
  }

  template <class C, R (C::* const method_ptr)(A...)>
  static delegate from(C* object_ptr) noexcept
  {
    return { object_ptr, method_stub<C, method_ptr> };
  }

  template <class C, R (C::* const method_ptr)(A...) const>
  static delegate from(C const* object_ptr) noexcept
  {
    return { const_cast<C*>(object_ptr), const_method_stub<C, method_ptr> };
  }

  template <class C, R (C::* const method_ptr)(A...)>
  static delegate from(C& object) noexcept
  {
    return { &object, method_stub<C, method_ptr> };
  }

  template <class C, R (C::* const method_ptr)(A...) const>
  static delegate from(C const& object) noexcept
  {
    return { const_cast<C*>(&object), const_method_stub<C, method_ptr> };
  }

  template <typename T>
  static delegate from(T&& f)
  {
    return std::forward<T>(f);
  }

  static delegate from(R (* const function_ptr)(A...))
  {
    return [function_ptr](A&&... args) {
      return (*function_ptr)(std::forward<A>(args)...); };
  }

  template <class C>
  static delegate from(C* const object_ptr,
    R (C::* const method_ptr)(A...))
  {
    return [object_ptr, method_ptr](A&&... args) {
      return (object_ptr->*method_ptr)(std::forward<A>(args)...); };
  }

  template <class C>
  static delegate from(C const* const object_ptr,
    R (C::* const method_ptr)(A...) const)
  {
    return [object_ptr, method_ptr](A&&... args) {
      return (object_ptr->*method_ptr)(std::forward<A>(args)...); };
  }

  template <class C>
  static delegate from(C& object, R (C::* const method_ptr)(A...))
  {
    return [&object, method_ptr](A&&... args) {
      return (object.*method_ptr)(std::forward<A>(args)...); };
  }

  template <class C>
  static delegate from(C const& object,
    R (C::* const method_ptr)(A...) const)
  {
    return [&object, method_ptr](A&&... args) {
      return (object.*method_ptr)(std::forward<A>(args)...); };
  }

  void reset() { stub_ptr_ = nullptr; store_.reset(); }

  void swap(delegate& other) noexcept { ::std::swap(*this, other); }

  bool operator==(delegate const& rhs) const noexcept
  {
    return (object_ptr_ == rhs.object_ptr_) && (stub_ptr_ == rhs.stub_ptr_);
  }

  bool operator!=(delegate const& rhs) const noexcept
  {
    return !operator==(rhs);
  }

  bool operator<(delegate const& rhs) const noexcept
  {
    return (object_ptr_ < rhs.object_ptr_) || (stub_ptr_ < rhs.stub_ptr_);
  }

  explicit operator bool() const noexcept { return stub_ptr_; }

  R operator()(A... args) const
  {
//  assert(stub_ptr);
    return stub_ptr_(object_ptr_, std::forward<A>(args)...);
  }

private:
  friend class ::std::hash<delegate>;

  typedef void (*deleter_type)(void*);

  void* object_ptr_;
  stub_ptr_type stub_ptr_{};

  deleter_type deleter_;

  std::shared_ptr<void> store_;
  std::size_t store_size_;

  template <class T>
  static void destructor_stub(void* const p)
  {
    static_cast<T*>(p)->~T();
  }

  template <class T>
  static void functor_deleter(void* const p)
  {
    static_cast<T*>(p)->~T();

    operator delete(p);
  }

  template <R (*function_ptr)(A...)>
  static R function_stub(void* const, A&&... args)
  {
    return function_ptr(std::forward<A>(args)...);
  }

  template <class C, R (C::*method_ptr)(A...)>
  static R method_stub(void* const object_ptr, A&&... args)
  {
    return (static_cast<C*>(object_ptr)->*method_ptr)(
      std::forward<A>(args)...);
  }

  template <class C, R (C::*method_ptr)(A...) const>
  static R const_method_stub(void* const object_ptr, A&&... args)
  {
    return (static_cast<C const*>(object_ptr)->*method_ptr)(
      std::forward<A>(args)...);
  }

  template <typename T>
  static R functor_stub(void* const object_ptr, A&&... args)
  {
    return (*static_cast<T*>(object_ptr))(std::forward<A>(args)...);
  }
};

namespace std
{
  template <typename R, typename ...A>
  struct hash<delegate<R (A...)> >
  {
    size_t operator()(delegate<R (A...)> const& d) const noexcept
    {
      auto const seed(hash<void*>()(d.object_ptr_) + 0x9e3779b9);

      return hash<typename delegate<R (A...)>::stub_ptr_type>()(d.stub_ptr_)
        + 0x9e3779b9 + (seed << 6) + (seed >> 2);
    }
  };
}

#endif // DELEGATE_HPP
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: targetdropcontext.cxx,v $
 *
 *  $Revision: 1.7 $
 *
 *  last change: $Author: obo $ $Date: 2006-09-17 16:59:31 $
 *
 *  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_dtrans.hxx"
#ifndef _RTL_UNLOAD_H_
#include <rtl/unload.h>
#endif

#include "targetdropcontext.hxx"

using namespace ::com::sun::star::datatransfer::dnd;
using namespace ::cppu;
using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::lang;

extern rtl_StandardModuleCount g_moduleCount;
TargetDropContext::TargetDropContext( DropTarget* p)
{
    g_moduleCount.modCnt.acquire( &g_moduleCount.modCnt );
    m_pDropTarget= p;
    p->acquire();
}

TargetDropContext::~TargetDropContext()
{
    m_pDropTarget->release();
    g_moduleCount.modCnt.release( &g_moduleCount.modCnt );
}

void SAL_CALL TargetDropContext::acceptDrop( sal_Int8 dropOperation )
        throw( RuntimeException)
{
    m_pDropTarget->_acceptDrop( dropOperation, static_cast<XDropTargetDropContext*>( this) );
}

void SAL_CALL TargetDropContext::rejectDrop( )
        throw( RuntimeException)
{
    m_pDropTarget->_rejectDrop(  static_cast<XDropTargetDropContext*>( this) );
}

void SAL_CALL TargetDropContext::dropComplete( sal_Bool success )
        throw( RuntimeException)
{
    m_pDropTarget->_dropComplete( success, static_cast<XDropTargetDropContext*>( this) );
}
<commit_msg>INTEGRATION: CWS changefileheader (1.7.62); FILE MERGED 2008/04/01 15:13:34 thb 1.7.62.2: #i85898# Stripping all external header guards 2008/03/31 13:09:00 rt 1.7.62.1: #i87441# Change license header to LPGL v3.<commit_after>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: targetdropcontext.cxx,v $
 * $Revision: 1.8 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org 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 version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_dtrans.hxx"
#include <rtl/unload.h>

#include "targetdropcontext.hxx"

using namespace ::com::sun::star::datatransfer::dnd;
using namespace ::cppu;
using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::lang;

extern rtl_StandardModuleCount g_moduleCount;
TargetDropContext::TargetDropContext( DropTarget* p)
{
    g_moduleCount.modCnt.acquire( &g_moduleCount.modCnt );
    m_pDropTarget= p;
    p->acquire();
}

TargetDropContext::~TargetDropContext()
{
    m_pDropTarget->release();
    g_moduleCount.modCnt.release( &g_moduleCount.modCnt );
}

void SAL_CALL TargetDropContext::acceptDrop( sal_Int8 dropOperation )
        throw( RuntimeException)
{
    m_pDropTarget->_acceptDrop( dropOperation, static_cast<XDropTargetDropContext*>( this) );
}

void SAL_CALL TargetDropContext::rejectDrop( )
        throw( RuntimeException)
{
    m_pDropTarget->_rejectDrop(  static_cast<XDropTargetDropContext*>( this) );
}

void SAL_CALL TargetDropContext::dropComplete( sal_Bool success )
        throw( RuntimeException)
{
    m_pDropTarget->_dropComplete( success, static_cast<XDropTargetDropContext*>( this) );
}
<|endoftext|>


<commit_before>/*
 * Copyright 2014 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "Resources.h"
#include "SkBitmap.h"
#include "SkData.h"
#include "SkDecodingImageGenerator.h"
#include "SkForceLinking.h"
#include "SkImageDecoder.h"
#include "SkOSFile.h"
#include "SkRandom.h"
#include "SkStream.h"
#include "Test.h"

__SK_FORCE_IMAGE_DECODER_LINKING;

/**
 * First, make sure that writing an 8-bit RGBA KTX file and then
 * reading it produces the same bitmap.
 */
DEF_TEST(KtxReadWrite, reporter) {

    // Random number generator with explicit seed for reproducibility
    SkRandom rand(0x1005cbad);

    SkBitmap bm8888;
    bm8888.allocN32Pixels(128, 128);

    uint8_t *pixels = reinterpret_cast<uint8_t*>(bm8888.getPixels());
    REPORTER_ASSERT(reporter, pixels);

    if (NULL == pixels) {
        return;
    }

    uint8_t *row = pixels;
    for (int y = 0; y < bm8888.height(); ++y) {
        for (int x = 0; x < bm8888.width(); ++x) {
            uint8_t a = rand.nextRangeU(0, 255);
            uint8_t r = rand.nextRangeU(0, 255);
            uint8_t g = rand.nextRangeU(0, 255);
            uint8_t b = rand.nextRangeU(0, 255);

            SkPMColor &pixel = *(reinterpret_cast<SkPMColor*>(row + x*sizeof(SkPMColor)));
            pixel = SkPreMultiplyARGB(a, r, g, b);
        }
        row += bm8888.rowBytes();
    }
    REPORTER_ASSERT(reporter, !(bm8888.empty()));

    SkAutoDataUnref encodedData(SkImageEncoder::EncodeData(bm8888, SkImageEncoder::kKTX_Type, 0));
    REPORTER_ASSERT(reporter, encodedData);

    SkAutoTUnref<SkMemoryStream> stream(SkNEW_ARGS(SkMemoryStream, (encodedData)));
    REPORTER_ASSERT(reporter, stream);

    SkBitmap decodedBitmap;
    bool imageDecodeSuccess = SkImageDecoder::DecodeStream(stream, &decodedBitmap);
    REPORTER_ASSERT(reporter, imageDecodeSuccess);

    REPORTER_ASSERT(reporter, decodedBitmap.colorType() == bm8888.colorType());
    REPORTER_ASSERT(reporter, decodedBitmap.alphaType() == bm8888.alphaType());
    REPORTER_ASSERT(reporter, decodedBitmap.width() == bm8888.width());
    REPORTER_ASSERT(reporter, decodedBitmap.height() == bm8888.height());
    REPORTER_ASSERT(reporter, !(decodedBitmap.empty()));

    uint8_t *decodedPixels = reinterpret_cast<uint8_t*>(decodedBitmap.getPixels());
    REPORTER_ASSERT(reporter, decodedPixels);
    REPORTER_ASSERT(reporter, decodedBitmap.getSize() == bm8888.getSize());

    if (NULL == decodedPixels) {
        return;
    }

    REPORTER_ASSERT(reporter, memcmp(decodedPixels, pixels, decodedBitmap.getSize()) == 0);
}

/**
 * Next test is to see whether or not reading an unpremultiplied KTX file accurately
 * creates a premultiplied buffer...
 */
DEF_TEST(KtxReadUnpremul, reporter) {

    static const uint8_t kHalfWhiteKTX[] = {
        0xAB, 0x4B, 0x54, 0x58, 0x20, 0x31, // First twelve bytes is magic
        0x31, 0xBB, 0x0D, 0x0A, 0x1A, 0x0A, // KTX identifier string
        0x01, 0x02, 0x03, 0x04, // Then magic endian specifier
        0x01, 0x14, 0x00, 0x00, // uint32_t fGLType;
        0x01, 0x00, 0x00, 0x00, // uint32_t fGLTypeSize;
        0x08, 0x19, 0x00, 0x00, // uint32_t fGLFormat;
        0x58, 0x80, 0x00, 0x00, // uint32_t fGLInternalFormat;
        0x08, 0x19, 0x00, 0x00, // uint32_t fGLBaseInternalFormat;
        0x02, 0x00, 0x00, 0x00, // uint32_t fPixelWidth;
        0x02, 0x00, 0x00, 0x00, // uint32_t fPixelHeight;
        0x00, 0x00, 0x00, 0x00, // uint32_t fPixelDepth;
        0x00, 0x00, 0x00, 0x00, // uint32_t fNumberOfArrayElements;
        0x01, 0x00, 0x00, 0x00, // uint32_t fNumberOfFaces;
        0x01, 0x00, 0x00, 0x00, // uint32_t fNumberOfMipmapLevels;
        0x00, 0x00, 0x00, 0x00, // uint32_t fBytesOfKeyValueData;
        0x10, 0x00, 0x00, 0x00, // image size: 2x2 image of RGBA = 4 * 4 = 16 bytes
        0xFF, 0xFF, 0xFF, 0x80, // Pixel 1
        0xFF, 0xFF, 0xFF, 0x80, // Pixel 2
        0xFF, 0xFF, 0xFF, 0x80, // Pixel 3
        0xFF, 0xFF, 0xFF, 0x80};// Pixel 4

    SkAutoTUnref<SkMemoryStream> stream(
        SkNEW_ARGS(SkMemoryStream, (kHalfWhiteKTX, sizeof(kHalfWhiteKTX))));
    REPORTER_ASSERT(reporter, stream);

    SkBitmap decodedBitmap;
    bool imageDecodeSuccess = SkImageDecoder::DecodeStream(stream, &decodedBitmap);
    REPORTER_ASSERT(reporter, imageDecodeSuccess);

    REPORTER_ASSERT(reporter, decodedBitmap.colorType() == kN32_SkColorType);
    REPORTER_ASSERT(reporter, decodedBitmap.alphaType() == kPremul_SkAlphaType);
    REPORTER_ASSERT(reporter, decodedBitmap.width() == 2);
    REPORTER_ASSERT(reporter, decodedBitmap.height() == 2);
    REPORTER_ASSERT(reporter, !(decodedBitmap.empty()));

    uint8_t *decodedPixels = reinterpret_cast<uint8_t*>(decodedBitmap.getPixels());
    REPORTER_ASSERT(reporter, decodedPixels);

    uint8_t *row = decodedPixels;
    for (int j = 0; j < decodedBitmap.height(); ++j) {
        for (int i = 0; i < decodedBitmap.width(); ++i) {
            SkPMColor pixel = *(reinterpret_cast<SkPMColor*>(row + i*sizeof(SkPMColor)));
            REPORTER_ASSERT(reporter, SkPreMultiplyARGB(0x80, 0xFF, 0xFF, 0xFF) == pixel);
        }
        row += decodedBitmap.rowBytes();
    }
}

/**
 * Finally, make sure that if we get ETC1 data from a PKM file that we can then
 * accurately write it out into a KTX file (i.e. transferring the ETC1 data from
 * the PKM to the KTX should produce an identical KTX to the one we have on file)
 */
DEF_TEST(KtxReexportPKM, reporter) {
    SkString pkmFilename = GetResourcePath("mandrill_128.pkm");

    // Load PKM file into a bitmap
    SkBitmap etcBitmap;
    SkAutoTUnref<SkData> fileData(SkData::NewFromFileName(pkmFilename.c_str()));
    REPORTER_ASSERT(reporter, fileData);
    if (NULL == fileData) {
        return;
    }

    bool installDiscardablePixelRefSuccess =
        SkInstallDiscardablePixelRef(
            SkDecodingImageGenerator::Create(
                fileData, SkDecodingImageGenerator::Options()), &etcBitmap);
    REPORTER_ASSERT(reporter, installDiscardablePixelRefSuccess);

    // Write the bitmap out to a KTX file.
    SkData *ktxDataPtr = SkImageEncoder::EncodeData(etcBitmap, SkImageEncoder::kKTX_Type, 0);
    SkAutoDataUnref newKtxData(ktxDataPtr);
    REPORTER_ASSERT(reporter, ktxDataPtr);

    // See is this data is identical to data in existing ktx file.
    SkString ktxFilename = GetResourcePath("mandrill_128.ktx");
    SkAutoDataUnref oldKtxData(SkData::NewFromFileName(ktxFilename.c_str()));
    REPORTER_ASSERT(reporter, oldKtxData->equals(newKtxData));
}
<commit_msg>not a failure if we didn't load the test file<commit_after>/*
 * Copyright 2014 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "Resources.h"
#include "SkBitmap.h"
#include "SkData.h"
#include "SkDecodingImageGenerator.h"
#include "SkForceLinking.h"
#include "SkImageDecoder.h"
#include "SkOSFile.h"
#include "SkRandom.h"
#include "SkStream.h"
#include "Test.h"

__SK_FORCE_IMAGE_DECODER_LINKING;

/**
 * First, make sure that writing an 8-bit RGBA KTX file and then
 * reading it produces the same bitmap.
 */
DEF_TEST(KtxReadWrite, reporter) {

    // Random number generator with explicit seed for reproducibility
    SkRandom rand(0x1005cbad);

    SkBitmap bm8888;
    bm8888.allocN32Pixels(128, 128);

    uint8_t *pixels = reinterpret_cast<uint8_t*>(bm8888.getPixels());
    REPORTER_ASSERT(reporter, pixels);

    if (NULL == pixels) {
        return;
    }

    uint8_t *row = pixels;
    for (int y = 0; y < bm8888.height(); ++y) {
        for (int x = 0; x < bm8888.width(); ++x) {
            uint8_t a = rand.nextRangeU(0, 255);
            uint8_t r = rand.nextRangeU(0, 255);
            uint8_t g = rand.nextRangeU(0, 255);
            uint8_t b = rand.nextRangeU(0, 255);

            SkPMColor &pixel = *(reinterpret_cast<SkPMColor*>(row + x*sizeof(SkPMColor)));
            pixel = SkPreMultiplyARGB(a, r, g, b);
        }
        row += bm8888.rowBytes();
    }
    REPORTER_ASSERT(reporter, !(bm8888.empty()));

    SkAutoDataUnref encodedData(SkImageEncoder::EncodeData(bm8888, SkImageEncoder::kKTX_Type, 0));
    REPORTER_ASSERT(reporter, encodedData);

    SkAutoTUnref<SkMemoryStream> stream(SkNEW_ARGS(SkMemoryStream, (encodedData)));
    REPORTER_ASSERT(reporter, stream);

    SkBitmap decodedBitmap;
    bool imageDecodeSuccess = SkImageDecoder::DecodeStream(stream, &decodedBitmap);
    REPORTER_ASSERT(reporter, imageDecodeSuccess);

    REPORTER_ASSERT(reporter, decodedBitmap.colorType() == bm8888.colorType());
    REPORTER_ASSERT(reporter, decodedBitmap.alphaType() == bm8888.alphaType());
    REPORTER_ASSERT(reporter, decodedBitmap.width() == bm8888.width());
    REPORTER_ASSERT(reporter, decodedBitmap.height() == bm8888.height());
    REPORTER_ASSERT(reporter, !(decodedBitmap.empty()));

    uint8_t *decodedPixels = reinterpret_cast<uint8_t*>(decodedBitmap.getPixels());
    REPORTER_ASSERT(reporter, decodedPixels);
    REPORTER_ASSERT(reporter, decodedBitmap.getSize() == bm8888.getSize());

    if (NULL == decodedPixels) {
        return;
    }

    REPORTER_ASSERT(reporter, memcmp(decodedPixels, pixels, decodedBitmap.getSize()) == 0);
}

/**
 * Next test is to see whether or not reading an unpremultiplied KTX file accurately
 * creates a premultiplied buffer...
 */
DEF_TEST(KtxReadUnpremul, reporter) {

    static const uint8_t kHalfWhiteKTX[] = {
        0xAB, 0x4B, 0x54, 0x58, 0x20, 0x31, // First twelve bytes is magic
        0x31, 0xBB, 0x0D, 0x0A, 0x1A, 0x0A, // KTX identifier string
        0x01, 0x02, 0x03, 0x04, // Then magic endian specifier
        0x01, 0x14, 0x00, 0x00, // uint32_t fGLType;
        0x01, 0x00, 0x00, 0x00, // uint32_t fGLTypeSize;
        0x08, 0x19, 0x00, 0x00, // uint32_t fGLFormat;
        0x58, 0x80, 0x00, 0x00, // uint32_t fGLInternalFormat;
        0x08, 0x19, 0x00, 0x00, // uint32_t fGLBaseInternalFormat;
        0x02, 0x00, 0x00, 0x00, // uint32_t fPixelWidth;
        0x02, 0x00, 0x00, 0x00, // uint32_t fPixelHeight;
        0x00, 0x00, 0x00, 0x00, // uint32_t fPixelDepth;
        0x00, 0x00, 0x00, 0x00, // uint32_t fNumberOfArrayElements;
        0x01, 0x00, 0x00, 0x00, // uint32_t fNumberOfFaces;
        0x01, 0x00, 0x00, 0x00, // uint32_t fNumberOfMipmapLevels;
        0x00, 0x00, 0x00, 0x00, // uint32_t fBytesOfKeyValueData;
        0x10, 0x00, 0x00, 0x00, // image size: 2x2 image of RGBA = 4 * 4 = 16 bytes
        0xFF, 0xFF, 0xFF, 0x80, // Pixel 1
        0xFF, 0xFF, 0xFF, 0x80, // Pixel 2
        0xFF, 0xFF, 0xFF, 0x80, // Pixel 3
        0xFF, 0xFF, 0xFF, 0x80};// Pixel 4

    SkAutoTUnref<SkMemoryStream> stream(
        SkNEW_ARGS(SkMemoryStream, (kHalfWhiteKTX, sizeof(kHalfWhiteKTX))));
    REPORTER_ASSERT(reporter, stream);

    SkBitmap decodedBitmap;
    bool imageDecodeSuccess = SkImageDecoder::DecodeStream(stream, &decodedBitmap);
    REPORTER_ASSERT(reporter, imageDecodeSuccess);

    REPORTER_ASSERT(reporter, decodedBitmap.colorType() == kN32_SkColorType);
    REPORTER_ASSERT(reporter, decodedBitmap.alphaType() == kPremul_SkAlphaType);
    REPORTER_ASSERT(reporter, decodedBitmap.width() == 2);
    REPORTER_ASSERT(reporter, decodedBitmap.height() == 2);
    REPORTER_ASSERT(reporter, !(decodedBitmap.empty()));

    uint8_t *decodedPixels = reinterpret_cast<uint8_t*>(decodedBitmap.getPixels());
    REPORTER_ASSERT(reporter, decodedPixels);

    uint8_t *row = decodedPixels;
    for (int j = 0; j < decodedBitmap.height(); ++j) {
        for (int i = 0; i < decodedBitmap.width(); ++i) {
            SkPMColor pixel = *(reinterpret_cast<SkPMColor*>(row + i*sizeof(SkPMColor)));
            REPORTER_ASSERT(reporter, SkPreMultiplyARGB(0x80, 0xFF, 0xFF, 0xFF) == pixel);
        }
        row += decodedBitmap.rowBytes();
    }
}

/**
 * Finally, make sure that if we get ETC1 data from a PKM file that we can then
 * accurately write it out into a KTX file (i.e. transferring the ETC1 data from
 * the PKM to the KTX should produce an identical KTX to the one we have on file)
 */
DEF_TEST(KtxReexportPKM, reporter) {
    SkString pkmFilename = GetResourcePath("mandrill_128.pkm");

    // Load PKM file into a bitmap
    SkBitmap etcBitmap;
    SkAutoTUnref<SkData> fileData(SkData::NewFromFileName(pkmFilename.c_str()));
    if (NULL == fileData) {
        SkDebugf("KtxReexportPKM: can't load test file %s\n", pkmFilename.c_str());
        return;
    }

    bool installDiscardablePixelRefSuccess =
        SkInstallDiscardablePixelRef(
            SkDecodingImageGenerator::Create(
                fileData, SkDecodingImageGenerator::Options()), &etcBitmap);
    REPORTER_ASSERT(reporter, installDiscardablePixelRefSuccess);

    // Write the bitmap out to a KTX file.
    SkData *ktxDataPtr = SkImageEncoder::EncodeData(etcBitmap, SkImageEncoder::kKTX_Type, 0);
    SkAutoDataUnref newKtxData(ktxDataPtr);
    REPORTER_ASSERT(reporter, ktxDataPtr);

    // See is this data is identical to data in existing ktx file.
    SkString ktxFilename = GetResourcePath("mandrill_128.ktx");
    SkAutoDataUnref oldKtxData(SkData::NewFromFileName(ktxFilename.c_str()));
    REPORTER_ASSERT(reporter, oldKtxData->equals(newKtxData));
}
<|endoftext|>


<commit_before>/*
    This file is part of libkcal.

    Copyright (c) 2003 Cornelius Schumacher <schumacher@kde.org>

    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
    along with this library; see the file COPYING.LIB.  If not, write to
    the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
    Boston, MA 02111-1307, USA.
*/

#include <typeinfo>
#include <stdlib.h>

#include <qdatetime.h>
#include <qstring.h>
#include <qptrlist.h>

#include <klocale.h>
#include <kdebug.h>
#include <kurl.h>
#include <kio/job.h>
#include <kstandarddirs.h>

#include <kabc/stdaddressbook.h>
#include <kabc/locknull.h>

#include "vcaldrag.h"
#include "vcalformat.h"
#include "icalformat.h"
#include "exceptions.h"
#include "incidence.h"
#include "event.h"
#include "todo.h"
#include "journal.h"
#include "filestorage.h"
#include "libkcal/alarm.h"

#include <kresources/configwidget.h>

#include "resourcekabcconfig.h"

#include "resourcekabc.h"

using namespace KCal;

extern "C"
{
  void *init_kcal_kabc()
  {
    return new KRES::PluginFactory<ResourceKABC,ResourceKABCConfig>();
  }
}

ResourceKABC::ResourceKABC( const KConfig* config )
  : ResourceCalendar( config )
{
  if ( config ) {
    readConfig( config );
  }

  init();
}

ResourceKABC::ResourceKABC( )
  : ResourceCalendar( 0 )
{
  mAlarmDays = 1;
  mAlarm = false;

  init();
}

ResourceKABC::~ResourceKABC()
{
  delete mLock;
}

void ResourceKABC::init()
{
  setType( "birthdays" );

  mOpen = false;
  setReadOnly( true );

  mLock = new KABC::LockNull( false );

  mAddressbook = KABC::StdAddressBook::self();
  connect( mAddressbook, SIGNAL(addressBookChanged(AddressBook*)), SLOT( reload() ) );
}

void ResourceKABC::readConfig( const KConfig *config )
{
  mAlarmDays = config->readNumEntry( "AlarmDays", 1 );
  mAlarm = config->readBoolEntry( "Alarm", false );
}

void ResourceKABC::writeConfig( KConfig *config )
{
  ResourceCalendar::writeConfig( config );
  config->writeEntry( "AlarmDays", mAlarmDays );
  config->writeEntry( "Alarm", mAlarm );
  load();
}

bool ResourceKABC::doOpen()
{
  kdDebug(5800) << "ResourceKABC::doOpen()" << endl;

  mOpen = true;

  return true;
}

bool ResourceKABC::load()
{
  kdDebug() << "ResourceKABC::load()" << endl;

  if ( !mOpen ) return true;

  mCalendar.close();

  // import from kabc
  QString summary;

  KABC::Addressee::List anniversaries;
  KABC::Addressee::List::Iterator addrIt;

  KABC::AddressBook::Iterator it;
  for ( it = mAddressbook->begin(); it != mAddressbook->end(); ++it ) {

    QDateTime birthdate = (*it).birthday().date();
    if ( birthdate.isValid() ) {
      kdDebug() << "found a birthday " << birthdate.toString() << endl;

      QString name = (*it).nickName();
      if (name.isEmpty()) name = (*it).realName();
      summary = i18n("%1's birthday").arg( name );

      Event *ev = new Event();

      ev->setDtStart(birthdate);
      ev->setDtEnd(birthdate);
      ev->setHasEndDate(true);
      ev->setFloats(true);

      ev->setSummary(summary);

      // Set the recurrence
      Recurrence *vRecurrence = ev->recurrence();
      vRecurrence->setRecurStart(birthdate);
      vRecurrence->setYearly(Recurrence::rYearlyMonth,1,-1);
      vRecurrence->addYearlyNum(birthdate.date().month());

      ev->clearAlarms();

      if ( mAlarm ) {
        // Set the alarm
        Alarm* vAlarm = ev->newAlarm();
        vAlarm->setText(summary);
        vAlarm->setTime(birthdate);
        // 24 hours before
        vAlarm->setStartOffset( -1440 * mAlarmDays );
        vAlarm->setEnabled(true);
      }

      // insert category
      ev->setCategories(i18n("Birthday"));

      ev->setReadOnly( true );
      mCalendar.addEvent(ev);
      kdDebug() << "imported " << birthdate.toString() << endl;
    }

    QDateTime anniversary = QDate::fromString( (*it).custom( "KADDRESSBOOK", "X-Anniversary" ), Qt::ISODate );
    if ( !anniversary.isValid() )
      continue;

    QString name = (*it).custom( "KADDRESSBOOK", "X-SpousesName" );
    if ( name.isEmpty() )
      anniversaries.append( *it );
    else {
      bool found = false;
      for ( addrIt = anniversaries.begin(); addrIt != anniversaries.end(); ++addrIt ) {
        if ( name == (*addrIt).realName() ) {
          QDateTime spouseAnniversary = QDate::fromString( (*addrIt).custom( "KADDRESSBOOK", "X-Anniversary" ), Qt::ISODate );
          if ( anniversary == spouseAnniversary ) {
            found = true;
            break;

          }
        }
      }

      if ( !found )
        anniversaries.append( *it );
    }
  }

  for ( addrIt = anniversaries.begin(); addrIt != anniversaries.end(); ++addrIt ) {
    QDateTime anniversary = QDate::fromString( (*addrIt).custom( "KADDRESSBOOK", "X-Anniversary" ), Qt::ISODate );
    kdDebug() << "found a anniversary " << anniversary.toString() << endl;

    QString name = (*addrIt).nickName();
    QString spouseName = (*addrIt).custom( "KADDRESSBOOK", "X-SpousesName" );
    if ( name.isEmpty() )
      name = (*addrIt).givenName();
    if ( !spouseName.isEmpty() ) {
      KABC::Addressee spouse;
      spouse.setNameFromString( spouseName );
      name += " & " + spouse.givenName();
    }
    summary = i18n("%1's anniversary").arg( name );

    Event *ev = new Event();

    ev->setDtStart(anniversary);
    ev->setDtEnd(anniversary);
    ev->setHasEndDate(true);
    ev->setFloats(true);

    ev->setSummary(summary);

    // Set the recurrence
    Recurrence *vRecurrence = ev->recurrence();
    vRecurrence->setRecurStart(anniversary);
    vRecurrence->setYearly(Recurrence::rYearlyMonth,1,-1);
    vRecurrence->addYearlyNum(anniversary.date().month());

    ev->clearAlarms();

    if ( mAlarm ) {
      // Set the alarm
      Alarm* vAlarm = ev->newAlarm();
      vAlarm->setText(summary);
      vAlarm->setTime(anniversary);
      // 24 hours before
      vAlarm->setStartOffset( -1440 * mAlarmDays );
      vAlarm->setEnabled(true);
    }

    // insert category
    ev->setCategories(i18n("Anniversary"));

    ev->setReadOnly( true );
    mCalendar.addEvent(ev);
    kdDebug() << "imported " << anniversary.toString() << endl;
  }

  emit resourceChanged( this );

  return true;
}

void ResourceKABC::setAlarm( bool a )
{
  mAlarm = a;
}

bool ResourceKABC::alarm()
{
  return mAlarm;
}

void ResourceKABC::setAlarmDays( int ad )
{
  mAlarmDays = ad;
}

int ResourceKABC::alarmDays()
{
  return mAlarmDays;
}

bool ResourceKABC::save()
{
  // is always read only!
  return true;
}

bool ResourceKABC::isSaving()
{
  return false;
}

KABC::Lock *ResourceKABC::lock()
{
  return mLock;
}

void ResourceKABC::doClose()
{
  if ( !mOpen ) return;

  mCalendar.close();
  mOpen = false;
}

bool ResourceKABC::addEvent(Event*)
{
  return false;
}

void ResourceKABC::deleteEvent(Event*)
{
}

Event *ResourceKABC::event( const QString &uid )
{
  return mCalendar.event( uid );
}

Event::List ResourceKABC::rawEventsForDate(const QDate &qd, bool sorted)
{
  return mCalendar.rawEventsForDate( qd, sorted );
}

Event::List ResourceKABC::rawEvents( const QDate &start, const QDate &end,
                                          bool inclusive )
{
  return mCalendar.rawEvents( start, end, inclusive );
}

Event::List ResourceKABC::rawEventsForDate(const QDateTime &qdt)
{
  return mCalendar.rawEventsForDate( qdt.date() );
}

Event::List ResourceKABC::rawEvents()
{
  return mCalendar.rawEvents();
}

bool ResourceKABC::addTodo(Todo*)
{
  return false;
}

void ResourceKABC::deleteTodo(Todo*)
{
}

Todo::List ResourceKABC::rawTodos()
{
  return mCalendar.rawTodos();
}

Todo *ResourceKABC::todo( const QString &uid )
{
  return mCalendar.todo( uid );
}

Todo::List ResourceKABC::todos( const QDate &date )
{
  return mCalendar.todos( date );
}

bool ResourceKABC::addJournal(Journal*)
{
  return false;
}

void ResourceKABC::deleteJournal(Journal*)
{
}

Journal *ResourceKABC::journal(const QDate &date)
{
//  kdDebug(5800) << "ResourceKABC::journal() " << date.toString() << endl;

  return mCalendar.journal( date );
}

Journal *ResourceKABC::journal(const QString &uid)
{
  return mCalendar.journal( uid );
}

Journal::List ResourceKABC::journals()
{
  return mCalendar.journals();
}

Alarm::List ResourceKABC::alarmsTo( const QDateTime &to )
{
  return mCalendar.alarmsTo( to );
}

Alarm::List ResourceKABC::alarms( const QDateTime &from, const QDateTime &to )
{
//  kdDebug(5800) << "ResourceKABC::alarms(" << from.toString() << " - " << to.toString() << ")\n";

  return mCalendar.alarms( from, to );
}

void ResourceKABC::update(IncidenceBase *)
{
}

void ResourceKABC::dump() const
{
  ResourceCalendar::dump();
}

void ResourceKABC::reload()
{
  load();
}

void ResourceKABC::setTimeZoneId( const QString& tzid )
{
  mCalendar.setTimeZoneId( tzid );
}

#include "resourcekabc.moc"
<commit_msg>KABC::StdAddressBook loads all resources when calling ::self(), so it shouldn't be done in ResourceKABC::init().<commit_after>/*
    This file is part of libkcal.

    Copyright (c) 2003 Cornelius Schumacher <schumacher@kde.org>

    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
    along with this library; see the file COPYING.LIB.  If not, write to
    the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
    Boston, MA 02111-1307, USA.
*/

#include <typeinfo>
#include <stdlib.h>

#include <qdatetime.h>
#include <qstring.h>
#include <qptrlist.h>

#include <klocale.h>
#include <kdebug.h>
#include <kurl.h>
#include <kio/job.h>
#include <kstandarddirs.h>

#include <kabc/stdaddressbook.h>
#include <kabc/locknull.h>

#include "vcaldrag.h"
#include "vcalformat.h"
#include "icalformat.h"
#include "exceptions.h"
#include "incidence.h"
#include "event.h"
#include "todo.h"
#include "journal.h"
#include "filestorage.h"
#include "libkcal/alarm.h"

#include <kresources/configwidget.h>

#include "resourcekabcconfig.h"

#include "resourcekabc.h"

using namespace KCal;

extern "C"
{
  void *init_kcal_kabc()
  {
    return new KRES::PluginFactory<ResourceKABC,ResourceKABCConfig>();
  }
}

ResourceKABC::ResourceKABC( const KConfig* config )
  : ResourceCalendar( config )
{
  if ( config ) {
    readConfig( config );
  }

  init();
}

ResourceKABC::ResourceKABC( )
  : ResourceCalendar( 0 )
{
  mAlarmDays = 1;
  mAlarm = false;

  init();
}

ResourceKABC::~ResourceKABC()
{
  delete mLock;
}

void ResourceKABC::init()
{
  setType( "birthdays" );

  mOpen = false;
  setReadOnly( true );

  mLock = new KABC::LockNull( false );

  mAddressbook = 0;
}

void ResourceKABC::readConfig( const KConfig *config )
{
  mAlarmDays = config->readNumEntry( "AlarmDays", 1 );
  mAlarm = config->readBoolEntry( "Alarm", false );
}

void ResourceKABC::writeConfig( KConfig *config )
{
  ResourceCalendar::writeConfig( config );
  config->writeEntry( "AlarmDays", mAlarmDays );
  config->writeEntry( "Alarm", mAlarm );
  load();
}

bool ResourceKABC::doOpen()
{
  kdDebug(5800) << "ResourceKABC::doOpen()" << endl;

  mAddressbook = KABC::StdAddressBook::self();
  connect( mAddressbook, SIGNAL(addressBookChanged(AddressBook*)), SLOT( reload() ) );

  mOpen = true;

  return true;
}

bool ResourceKABC::load()
{
  kdDebug() << "ResourceKABC::load()" << endl;

  if ( !mOpen ) return true;

  mCalendar.close();

  // import from kabc
  QString summary;

  KABC::Addressee::List anniversaries;
  KABC::Addressee::List::Iterator addrIt;

  KABC::AddressBook::Iterator it;
  for ( it = mAddressbook->begin(); it != mAddressbook->end(); ++it ) {

    QDateTime birthdate = (*it).birthday().date();
    if ( birthdate.isValid() ) {
      kdDebug() << "found a birthday " << birthdate.toString() << endl;

      QString name = (*it).nickName();
      if (name.isEmpty()) name = (*it).realName();
      summary = i18n("%1's birthday").arg( name );

      Event *ev = new Event();

      ev->setDtStart(birthdate);
      ev->setDtEnd(birthdate);
      ev->setHasEndDate(true);
      ev->setFloats(true);

      ev->setSummary(summary);

      // Set the recurrence
      Recurrence *vRecurrence = ev->recurrence();
      vRecurrence->setRecurStart(birthdate);
      vRecurrence->setYearly(Recurrence::rYearlyMonth,1,-1);
      vRecurrence->addYearlyNum(birthdate.date().month());

      ev->clearAlarms();

      if ( mAlarm ) {
        // Set the alarm
        Alarm* vAlarm = ev->newAlarm();
        vAlarm->setText(summary);
        vAlarm->setTime(birthdate);
        // 24 hours before
        vAlarm->setStartOffset( -1440 * mAlarmDays );
        vAlarm->setEnabled(true);
      }

      // insert category
      ev->setCategories(i18n("Birthday"));

      ev->setReadOnly( true );
      mCalendar.addEvent(ev);
      kdDebug() << "imported " << birthdate.toString() << endl;
    }

    QDateTime anniversary = QDate::fromString( (*it).custom( "KADDRESSBOOK", "X-Anniversary" ), Qt::ISODate );
    if ( !anniversary.isValid() )
      continue;

    QString name = (*it).custom( "KADDRESSBOOK", "X-SpousesName" );
    if ( name.isEmpty() )
      anniversaries.append( *it );
    else {
      bool found = false;
      for ( addrIt = anniversaries.begin(); addrIt != anniversaries.end(); ++addrIt ) {
        if ( name == (*addrIt).realName() ) {
          QDateTime spouseAnniversary = QDate::fromString( (*addrIt).custom( "KADDRESSBOOK", "X-Anniversary" ), Qt::ISODate );
          if ( anniversary == spouseAnniversary ) {
            found = true;
            break;

          }
        }
      }

      if ( !found )
        anniversaries.append( *it );
    }
  }

  for ( addrIt = anniversaries.begin(); addrIt != anniversaries.end(); ++addrIt ) {
    QDateTime anniversary = QDate::fromString( (*addrIt).custom( "KADDRESSBOOK", "X-Anniversary" ), Qt::ISODate );
    kdDebug() << "found a anniversary " << anniversary.toString() << endl;

    QString name = (*addrIt).nickName();
    QString spouseName = (*addrIt).custom( "KADDRESSBOOK", "X-SpousesName" );
    if ( name.isEmpty() )
      name = (*addrIt).givenName();
    if ( !spouseName.isEmpty() ) {
      KABC::Addressee spouse;
      spouse.setNameFromString( spouseName );
      name += " & " + spouse.givenName();
    }
    summary = i18n("%1's anniversary").arg( name );

    Event *ev = new Event();

    ev->setDtStart(anniversary);
    ev->setDtEnd(anniversary);
    ev->setHasEndDate(true);
    ev->setFloats(true);

    ev->setSummary(summary);

    // Set the recurrence
    Recurrence *vRecurrence = ev->recurrence();
    vRecurrence->setRecurStart(anniversary);
    vRecurrence->setYearly(Recurrence::rYearlyMonth,1,-1);
    vRecurrence->addYearlyNum(anniversary.date().month());

    ev->clearAlarms();

    if ( mAlarm ) {
      // Set the alarm
      Alarm* vAlarm = ev->newAlarm();
      vAlarm->setText(summary);
      vAlarm->setTime(anniversary);
      // 24 hours before
      vAlarm->setStartOffset( -1440 * mAlarmDays );
      vAlarm->setEnabled(true);
    }

    // insert category
    ev->setCategories(i18n("Anniversary"));

    ev->setReadOnly( true );
    mCalendar.addEvent(ev);
    kdDebug() << "imported " << anniversary.toString() << endl;
  }

  emit resourceChanged( this );

  return true;
}

void ResourceKABC::setAlarm( bool a )
{
  mAlarm = a;
}

bool ResourceKABC::alarm()
{
  return mAlarm;
}

void ResourceKABC::setAlarmDays( int ad )
{
  mAlarmDays = ad;
}

int ResourceKABC::alarmDays()
{
  return mAlarmDays;
}

bool ResourceKABC::save()
{
  // is always read only!
  return true;
}

bool ResourceKABC::isSaving()
{
  return false;
}

KABC::Lock *ResourceKABC::lock()
{
  return mLock;
}

void ResourceKABC::doClose()
{
  if ( !mOpen ) return;

  mCalendar.close();
  mOpen = false;
}

bool ResourceKABC::addEvent(Event*)
{
  return false;
}

void ResourceKABC::deleteEvent(Event*)
{
}

Event *ResourceKABC::event( const QString &uid )
{
  return mCalendar.event( uid );
}

Event::List ResourceKABC::rawEventsForDate(const QDate &qd, bool sorted)
{
  return mCalendar.rawEventsForDate( qd, sorted );
}

Event::List ResourceKABC::rawEvents( const QDate &start, const QDate &end,
                                          bool inclusive )
{
  return mCalendar.rawEvents( start, end, inclusive );
}

Event::List ResourceKABC::rawEventsForDate(const QDateTime &qdt)
{
  return mCalendar.rawEventsForDate( qdt.date() );
}

Event::List ResourceKABC::rawEvents()
{
  return mCalendar.rawEvents();
}

bool ResourceKABC::addTodo(Todo*)
{
  return false;
}

void ResourceKABC::deleteTodo(Todo*)
{
}

Todo::List ResourceKABC::rawTodos()
{
  return mCalendar.rawTodos();
}

Todo *ResourceKABC::todo( const QString &uid )
{
  return mCalendar.todo( uid );
}

Todo::List ResourceKABC::todos( const QDate &date )
{
  return mCalendar.todos( date );
}

bool ResourceKABC::addJournal(Journal*)
{
  return false;
}

void ResourceKABC::deleteJournal(Journal*)
{
}

Journal *ResourceKABC::journal(const QDate &date)
{
//  kdDebug(5800) << "ResourceKABC::journal() " << date.toString() << endl;

  return mCalendar.journal( date );
}

Journal *ResourceKABC::journal(const QString &uid)
{
  return mCalendar.journal( uid );
}

Journal::List ResourceKABC::journals()
{
  return mCalendar.journals();
}

Alarm::List ResourceKABC::alarmsTo( const QDateTime &to )
{
  return mCalendar.alarmsTo( to );
}

Alarm::List ResourceKABC::alarms( const QDateTime &from, const QDateTime &to )
{
//  kdDebug(5800) << "ResourceKABC::alarms(" << from.toString() << " - " << to.toString() << ")\n";

  return mCalendar.alarms( from, to );
}

void ResourceKABC::update(IncidenceBase *)
{
}

void ResourceKABC::dump() const
{
  ResourceCalendar::dump();
}

void ResourceKABC::reload()
{
  load();
}

void ResourceKABC::setTimeZoneId( const QString& tzid )
{
  mCalendar.setTimeZoneId( tzid );
}

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


<commit_before>/*
    This file is part of tgl-library

    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 Street, Fifth Floor, Boston, MA  02110-1301  USA

    Copyright Vitaly Valtman 2013-2015
    Copyright Topology LP 2016
*/

#include "tgl_mime_type.h"

#include <cctype>
#include <algorithm>
#include <map>

#include "auto/tgl_mime_data.cpp"

static const std::string s_default_mime_type("application/octet-stream");

std::string tgl_extension_by_mime_type(const std::string& mime_type)
{
    std::string mime(mime_type.size(), 0);
    std::transform(mime_type.begin(), mime_type.end(), mime.begin(), static_cast<int (*)(int)>(std::tolower));
    auto it = s_mime_to_extension.find(mime.c_str());
    if (it != s_mime_to_extension.end()) {
        return it->second;
    }
    return std::string();
}

std::string tgl_mime_type_by_filename(const std::string& filename)
{
    auto dot_pos = filename.rfind('.');
    if (dot_pos == std::string::npos || dot_pos == filename.size() - 1) {
       return s_default_mime_type;
    }
    return tgl_mime_type_by_extension(filename.substr(dot_pos + 1));
}

std::string tgl_mime_type_by_extension(const std::string& extension)
{
    std::string ext(extension.size(), 0);
    std::transform(extension.begin(), extension.end(), ext.begin(), static_cast<int (*)(int)>(std::tolower));

    auto it = s_extension_to_mime.find(ext.c_str());
    if (it != s_extension_to_mime.end()) {
        return it->second;
    }

    return s_default_mime_type;
}
<commit_msg>Fix GCC build, missing cstring include<commit_after>/*
    This file is part of tgl-library

    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 Street, Fifth Floor, Boston, MA  02110-1301  USA

    Copyright Vitaly Valtman 2013-2015
    Copyright Topology LP 2016
*/

#include "tgl_mime_type.h"

#include <algorithm>
#include <cctype>
#include <cstring>
#include <map>

#include "auto/tgl_mime_data.cpp"

static const std::string s_default_mime_type("application/octet-stream");

std::string tgl_extension_by_mime_type(const std::string& mime_type)
{
    std::string mime(mime_type.size(), 0);
    std::transform(mime_type.begin(), mime_type.end(), mime.begin(), static_cast<int (*)(int)>(std::tolower));
    auto it = s_mime_to_extension.find(mime.c_str());
    if (it != s_mime_to_extension.end()) {
        return it->second;
    }
    return std::string();
}

std::string tgl_mime_type_by_filename(const std::string& filename)
{
    auto dot_pos = filename.rfind('.');
    if (dot_pos == std::string::npos || dot_pos == filename.size() - 1) {
       return s_default_mime_type;
    }
    return tgl_mime_type_by_extension(filename.substr(dot_pos + 1));
}

std::string tgl_mime_type_by_extension(const std::string& extension)
{
    std::string ext(extension.size(), 0);
    std::transform(extension.begin(), extension.end(), ext.begin(), static_cast<int (*)(int)>(std::tolower));

    auto it = s_extension_to_mime.find(ext.c_str());
    if (it != s_extension_to_mime.end()) {
        return it->second;
    }

    return s_default_mime_type;
}
<|endoftext|>


<commit_before>#include <limits>
#include <algorithm>
#include <iostream>

#include "mue_algorithm.h"

mue::Calculation::Calculation(unsigned int teamcount, Distance_matrix const &distance_matrix, Distance max_single_distance)
:
	_teamcount(teamcount),
	_teams_per_round(teamcount / 3),
	_round_hosts(3),
	_round_guests(3),
	_distance_matrix(distance_matrix),
	_best_distance(std::numeric_limits<float>::max()),
	_max_single_distance(max_single_distance),
	_best_stations(3),
	_solutions(0),
#ifndef PREDEFINED_RANDOM
	_team_round_random(0, _teams_per_round -1),
	_random_generator(std::random_device()())
#else
	_team_shuffle(teamcount * 2)
#endif
{
	BOOST_ASSERT(_teamcount <= MAX_TEAMS);
	BOOST_ASSERT(_teamcount / 3 == float(_teamcount / 3));

	for (unsigned int round = 0; round < 3; ++round) {
		for (Team_id team = 0; team < teamcount; ++team) {
			if (_is_round_host(team, static_cast<Round>(round)))
				_round_hosts[round].push_back(team);
			else
				_round_guests[round].push_back(team);
		}
	}

#ifdef PREDEFINED_RANDOM
	std::random_device randd;
	std::mt19937 generator(randd());
	std::uniform_int_distribution<Team_id> random(0, _teams_per_round -1);

	for (Team_id team = 0; team < teamcount * 2; ++team)
		_team_shuffle[team] = random(generator) + (_teams_per_round * SECOND);
#endif
}

mue::Distance mue::Calculation::dummy_distance(Team_id host, Guest_tuple_generator::GuestPair const &guests) const
{
	if (_is_round_host(guests.first, SECOND))
		return _distance_matrix.lookup(host, guests.first);
	if (_is_round_host(guests.second, SECOND))
		return _distance_matrix.lookup(host, guests.second);

#ifdef PREDEFINED_RANDOM
	return _distance_matrix.lookup(host, _team_shuffle[guests.first + guests.second]) * 2;
#else
	return _distance_matrix.lookup(host, _random_host(SECOND)) * 2;
#endif
}

mue::Distance mue::Calculation::guest_distance(Round_data const &round_data, Team_id host, Guest_tuple_generator::GuestPair const &guests) const
{
	return _distance_matrix.lookup(round_data.prev_host(guests.first), host) +
	       _distance_matrix.lookup(round_data.prev_host(guests.second), host);
}

mue::Distance mue::Calculation::host_distance(Round_data const &round_data, Team_id host) const
{
	return _distance_matrix.lookup(round_data.prev_host(host), host);
}

std::vector<mue::Calculation::Guest_candidate> mue::Calculation::determine_guest_candidates(Round_data const &round_data, Iteration_data const &iteration_data, Team_id current_host, size_t slice) const
{
	std::vector<Guest_candidate> candidates;
	/*
	 * 63 teams have 24 guests (2/3)
	 * (math.factorial(24) / math.factorial(24-2)) / 2 = 276
	 * So for guests of 63 Teams 300 elements are enough.
	 */
	candidates.reserve(300);
	Guest_tuple_generator generator(round_data.guests, iteration_data.used_guests);
	for (Guest_tuple_generator::GuestPair const &guests : generator) {
		if (! iteration_data.seen(current_host, guests.first, guests.second)) {
			if (! round_data.first_round()) {
				float single_distance = guest_distance(round_data, current_host, guests);
				float distance = guest_distance(round_data, current_host, guests);
				if (distance < _best_distance &&  single_distance < _max_single_distance)
					candidates.emplace_back(iteration_data.distance + guest_distance(round_data, current_host, guests), guests);
			} else {
				candidates.emplace_back(dummy_distance(current_host, guests), guests);
			}
		}
	}
	std::sort(candidates.begin(), candidates.end(), [](Guest_candidate const &a, Guest_candidate const &b) { return a.distance < b.distance; });
	return std::vector<Guest_candidate>(candidates.begin(), candidates.begin() + std::min(candidates.size(), slice));
}

mue::Calculation::Round_data mue::Calculation::initial_round_data() const
{
	return Round_data(FIRST, _round_hosts[FIRST], _round_guests[FIRST], std::vector<std::vector<Team_id> >());
}

mue::Calculation::Round_data mue::Calculation::next_round_data(Round_data const &old, Iteration_data const &iteration) const
{
	BOOST_ASSERT(old.round < 2);
	Round next_round = static_cast<Round>(old.round + 1);
	std::vector<std::vector<Team_id> > station_backlog(old.prev_stations);
	station_backlog.push_back(iteration.round_station);
	return Round_data(next_round, _round_hosts[next_round], _round_guests[next_round], station_backlog);
}

std::vector<mue::Team_id> mue::Calculation::round_stations(Round round) const
{
	return _best_stations[round];
}

void mue::Calculation::print_stations(std::vector<std::vector<Team_id> > const &stations)
{
	std::cout << "[";
	bool list_first(true);
	for (int round = 0; round< 3; ++round)
	{
		if (!list_first) {
			std::cout << ", ";
		}
		list_first = false;
		std::cout << "[";
		std::map<Team_id, std::vector<Team_id> > tmp;
		for (size_t i = 0; i < stations[round].size(); ++i) {
			tmp[stations[round][i]].push_back(i);
		}

		bool set_first(true);
		for (std::pair<const Team_id, std::vector<Team_id> > const &meeting : tmp) {
			if (!set_first) {
				std::cout << ", ";
			}
			set_first = false;
			std::cout << "set([" << (int) meeting.second[0]
				  <<    ", " << (int) meeting.second[1]
				  <<    ", " << (int) meeting.second[2]
				  << "])";
		}
		std::cout << "]";
	}
	std::cout << "]";
}

void mue::Calculation::report_success(Round_data const &round_data, Iteration_data const &iteration)
{
	_solutions++;
	if (!_distance_is_better(iteration.distance))
		return;
	_best_distance = iteration.distance;
	std::cout << "new best (" << _solutions << ") " << std::fixed << _best_distance << "  ";
	for (uint8_t round = 0; round < 3; ++round) {
		if (round == round_data.prev_stations.size())
			_best_stations[round] = iteration.round_station;
		else
			_best_stations[round] = round_data.prev_stations[round];
	}
	print_stations(_best_stations);
	std::cout << std::endl;

}

void mue::Calculation::run_distribution(Round_data const &round_data, Iteration_data &iteration, size_t host_index) {
	if (host_index == _teams_per_round) {
		run_new_round(round_data, iteration);
		return;
	}

	Team_id host = round_data.hosts[host_index];

	if (! round_data.first_round()) {
		iteration.distance += host_distance(round_data, host);
		if (!_distance_is_better(iteration.distance))
			return;
	}

	size_t slices = (round_data.first_round() ? _teams_per_round * 3 : _teams_per_round / 3);

	for (Guest_candidate const &candidate : determine_guest_candidates(round_data, iteration, host, slices)) {
		Iteration_data new_iteration(iteration.next_iteration((round_data.first_round() ? iteration.distance : candidate.distance),
					     host, candidate.guests));
		run_distribution(round_data, new_iteration, host_index + 1);
	}
}

void mue::Calculation::run_new_round(Round_data const &round_data, Iteration_data &iteration) {
	if (round_data.round == THIRD) {
		report_success(round_data, iteration);
		return;
	}

	Round_data new_round(next_round_data(round_data, iteration));
	iteration.clear_round_data();

	run_distribution(new_round, iteration, 0);
}

void mue::Calculation::calculate_distribution()
{
	Round_data round_data(initial_round_data());
	Iteration_data iteration_data(_teamcount);

	run_distribution(round_data, iteration_data, 0);

}
<commit_msg>use std::generate instead of custom loop<commit_after>#include <limits>
#include <algorithm>
#include <iostream>

#include "mue_algorithm.h"

mue::Calculation::Calculation(unsigned int teamcount, Distance_matrix const &distance_matrix, Distance max_single_distance)
:
	_teamcount(teamcount),
	_teams_per_round(teamcount / 3),
	_round_hosts(3),
	_round_guests(3),
	_distance_matrix(distance_matrix),
	_best_distance(std::numeric_limits<float>::max()),
	_max_single_distance(max_single_distance),
	_best_stations(3),
	_solutions(0),
#ifndef PREDEFINED_RANDOM
	_team_round_random(0, _teams_per_round -1),
	_random_generator(std::random_device()())
#else
	_team_shuffle(teamcount * 2)
#endif
{
	BOOST_ASSERT(_teamcount <= MAX_TEAMS);
	BOOST_ASSERT(_teamcount / 3 == float(_teamcount / 3));

	for (unsigned int round = 0; round < 3; ++round) {
		for (Team_id team = 0; team < teamcount; ++team) {
			if (_is_round_host(team, static_cast<Round>(round)))
				_round_hosts[round].push_back(team);
			else
				_round_guests[round].push_back(team);
		}
	}

#ifdef PREDEFINED_RANDOM
	std::random_device randd;
	std::mt19937 generator(randd());
	std::uniform_int_distribution<Team_id> random(0, _teams_per_round -1);

	std::generate(_team_shuffle.begin(), _team_shuffle.end(),
			[&] () { return random(generator) + (_teams_per_round * SECOND); });
#endif
}

mue::Distance mue::Calculation::dummy_distance(Team_id host, Guest_tuple_generator::GuestPair const &guests) const
{
	if (_is_round_host(guests.first, SECOND))
		return _distance_matrix.lookup(host, guests.first);
	if (_is_round_host(guests.second, SECOND))
		return _distance_matrix.lookup(host, guests.second);

#ifdef PREDEFINED_RANDOM
	return _distance_matrix.lookup(host, _team_shuffle[guests.first + guests.second]) * 2;
#else
	return _distance_matrix.lookup(host, _random_host(SECOND)) * 2;
#endif
}

mue::Distance mue::Calculation::guest_distance(Round_data const &round_data, Team_id host, Guest_tuple_generator::GuestPair const &guests) const
{
	return _distance_matrix.lookup(round_data.prev_host(guests.first), host) +
	       _distance_matrix.lookup(round_data.prev_host(guests.second), host);
}

mue::Distance mue::Calculation::host_distance(Round_data const &round_data, Team_id host) const
{
	return _distance_matrix.lookup(round_data.prev_host(host), host);
}

std::vector<mue::Calculation::Guest_candidate> mue::Calculation::determine_guest_candidates(Round_data const &round_data, Iteration_data const &iteration_data, Team_id current_host, size_t slice) const
{
	std::vector<Guest_candidate> candidates;
	/*
	 * 63 teams have 24 guests (2/3)
	 * (math.factorial(24) / math.factorial(24-2)) / 2 = 276
	 * So for guests of 63 Teams 300 elements are enough.
	 */
	candidates.reserve(300);
	Guest_tuple_generator generator(round_data.guests, iteration_data.used_guests);
	for (Guest_tuple_generator::GuestPair const &guests : generator) {
		if (! iteration_data.seen(current_host, guests.first, guests.second)) {
			if (! round_data.first_round()) {
				float single_distance = guest_distance(round_data, current_host, guests);
				float distance = guest_distance(round_data, current_host, guests);
				if (distance < _best_distance &&  single_distance < _max_single_distance)
					candidates.emplace_back(iteration_data.distance + guest_distance(round_data, current_host, guests), guests);
			} else {
				candidates.emplace_back(dummy_distance(current_host, guests), guests);
			}
		}
	}
	std::sort(candidates.begin(), candidates.end(), [](Guest_candidate const &a, Guest_candidate const &b) { return a.distance < b.distance; });
	return std::vector<Guest_candidate>(candidates.begin(), candidates.begin() + std::min(candidates.size(), slice));
}

mue::Calculation::Round_data mue::Calculation::initial_round_data() const
{
	return Round_data(FIRST, _round_hosts[FIRST], _round_guests[FIRST], std::vector<std::vector<Team_id> >());
}

mue::Calculation::Round_data mue::Calculation::next_round_data(Round_data const &old, Iteration_data const &iteration) const
{
	BOOST_ASSERT(old.round < 2);
	Round next_round = static_cast<Round>(old.round + 1);
	std::vector<std::vector<Team_id> > station_backlog(old.prev_stations);
	station_backlog.push_back(iteration.round_station);
	return Round_data(next_round, _round_hosts[next_round], _round_guests[next_round], station_backlog);
}

std::vector<mue::Team_id> mue::Calculation::round_stations(Round round) const
{
	return _best_stations[round];
}

void mue::Calculation::print_stations(std::vector<std::vector<Team_id> > const &stations)
{
	std::cout << "[";
	bool list_first(true);
	for (int round = 0; round< 3; ++round)
	{
		if (!list_first) {
			std::cout << ", ";
		}
		list_first = false;
		std::cout << "[";
		std::map<Team_id, std::vector<Team_id> > tmp;
		for (size_t i = 0; i < stations[round].size(); ++i) {
			tmp[stations[round][i]].push_back(i);
		}

		bool set_first(true);
		for (std::pair<const Team_id, std::vector<Team_id> > const &meeting : tmp) {
			if (!set_first) {
				std::cout << ", ";
			}
			set_first = false;
			std::cout << "set([" << (int) meeting.second[0]
				  <<    ", " << (int) meeting.second[1]
				  <<    ", " << (int) meeting.second[2]
				  << "])";
		}
		std::cout << "]";
	}
	std::cout << "]";
}

void mue::Calculation::report_success(Round_data const &round_data, Iteration_data const &iteration)
{
	_solutions++;
	if (!_distance_is_better(iteration.distance))
		return;
	_best_distance = iteration.distance;
	std::cout << "new best (" << _solutions << ") " << std::fixed << _best_distance << "  ";
	for (uint8_t round = 0; round < 3; ++round) {
		if (round == round_data.prev_stations.size())
			_best_stations[round] = iteration.round_station;
		else
			_best_stations[round] = round_data.prev_stations[round];
	}
	print_stations(_best_stations);
	std::cout << std::endl;

}

void mue::Calculation::run_distribution(Round_data const &round_data, Iteration_data &iteration, size_t host_index) {
	if (host_index == _teams_per_round) {
		run_new_round(round_data, iteration);
		return;
	}

	Team_id host = round_data.hosts[host_index];

	if (! round_data.first_round()) {
		iteration.distance += host_distance(round_data, host);
		if (!_distance_is_better(iteration.distance))
			return;
	}

	size_t slices = (round_data.first_round() ? _teams_per_round * 3 : _teams_per_round / 3);

	for (Guest_candidate const &candidate : determine_guest_candidates(round_data, iteration, host, slices)) {
		Iteration_data new_iteration(iteration.next_iteration((round_data.first_round() ? iteration.distance : candidate.distance),
					     host, candidate.guests));
		run_distribution(round_data, new_iteration, host_index + 1);
	}
}

void mue::Calculation::run_new_round(Round_data const &round_data, Iteration_data &iteration) {
	if (round_data.round == THIRD) {
		report_success(round_data, iteration);
		return;
	}

	Round_data new_round(next_round_data(round_data, iteration));
	iteration.clear_round_data();

	run_distribution(new_round, iteration, 0);
}

void mue::Calculation::calculate_distribution()
{
	Round_data round_data(initial_round_data());
	Iteration_data iteration_data(_teamcount);

	run_distribution(round_data, iteration_data, 0);

}
<|endoftext|>


<commit_before>#include <limits>
#include <algorithm>
#include <iostream>

#include "mue_algorithm.h"

mue::Calculation::Calculation(unsigned int           teamcount,
			      Distance_matrix const &distance_matrix,
			      Distance               max_single_distance)
:
	_teamcount(teamcount),
	_teams_per_round(teamcount / 3),
	_round_hosts(3),
	_round_guests(3),
	_distance_matrix(distance_matrix),
	_best_distance(std::numeric_limits<float>::max()),
	_max_single_distance(max_single_distance),
	_forecast(distance_matrix),
	_best_stations(3),
	_solutions(0),
	_firstround_selection(distance_matrix)
{
	BOOST_ASSERT(_teamcount <= MAX_TEAMS);
	BOOST_ASSERT(_teamcount / 3 == float(_teamcount / 3));

	for (unsigned int round = 0; round < 3; ++round) {
		for (Team_id team = 0; team < teamcount; ++team) {
			if (_is_round_host(team, static_cast<Round>(round)))
				_round_hosts[round].push_back(team);
			else
				_round_guests[round].push_back(team);
		}
	}

}

mue::Distance mue::Calculation::guest_distance(Round_data                       const &round_data,
					       Team_id                                host,
					       Guest_tuple_generator::GuestPair const &guests) const
{
	return _distance_matrix.lookup(round_data.prev_host(guests.first), host) +
	       _distance_matrix.lookup(round_data.prev_host(guests.second), host);
}

mue::Distance mue::Calculation::host_distance(Round_data const &round_data, Team_id host) const
{
	return _distance_matrix.lookup(round_data.prev_host(host), host);
}

std::vector<mue::Calculation::Guest_candidate>
mue::Calculation::determine_guest_candidates(Round_data     const &round_data,
					     Iteration_data const &iteration_data,
					     Team_id               current_host,
					     size_t         const &host_idx,
					     size_t                slice) const
{
	BOOST_ASSERT(! round_data.first_round());
	std::vector<Guest_candidate> candidates;
	/*
	 * 63 teams have 42 guests (2/3)
	 * (math.factorial(42) / math.factorial(42-2)) / 2 = 861
	 * So for guests of 63 Teams 900 elements are enough.
	 */
	candidates.reserve(900);
	Guest_tuple_generator generator(round_data.guests, iteration_data.used_guests);
	for (Guest_tuple_generator::GuestPair const &guests : generator) {
		if (! iteration_data.seen(current_host, guests.first, guests.second)) {
			float single_distance =
				guest_distance(round_data, current_host, guests);
			float distance = single_distance + iteration_data.distance;

			if (single_distance < _max_single_distance
			   &&  distance + (round_data.round == SECOND
					  ? _forecast.first_move(host_idx)
					  : _forecast.second_move(host_idx)))
				candidates.emplace_back(distance, guests);
		}
	}
	std::sort(candidates.begin(), candidates.end(),
			[](Guest_candidate const &a, Guest_candidate const &b)
				{ return a.distance < b.distance; });
	return std::vector<Guest_candidate>(candidates.begin(),
					    candidates.begin()
					    + std::min(candidates.size(), slice));
}

std::vector<mue::Calculation::Guest_candidate>
mue::Calculation::firstround_guest_candidates(Iteration_data const &iteration_data,
				              Team_id               current_host) const
{
	std::vector<Guest_candidate> candidates;
	/*
	 * 63 teams have 42 guests (2/3)
	 * (math.factorial(42) / math.factorial(42-2)) / 2 = 861
	 * So for guests of 63 Teams 900 elements are enough.
	 */
	candidates.reserve(900);
	Guest_tuple_generator generator(_firstround_selection.for_host(current_host),
			                iteration_data.used_guests);
	for (Guest_tuple_generator::GuestPair const &guests : generator) {
		if (! iteration_data.seen(current_host, guests.first, guests.second)) {
			candidates.emplace_back(0, guests);
		}
	}
	return candidates;
}

mue::Calculation::Round_data mue::Calculation::initial_round_data() const
{
	return Round_data(FIRST, _round_hosts[FIRST], _round_guests[FIRST],
			  std::vector<std::vector<Team_id> >());
}

mue::Calculation::Round_data mue::Calculation::next_round_data(Round_data const &old,
							       Iteration_data const &iteration) const
{
	BOOST_ASSERT(old.round < 2);
	Round next_round = static_cast<Round>(old.round + 1);
	std::vector<std::vector<Team_id> > station_backlog(old.prev_stations);
	station_backlog.push_back(iteration.round_station);
	return Round_data(next_round, _round_hosts[next_round], _round_guests[next_round], station_backlog);
}

std::vector<mue::Team_id> mue::Calculation::round_stations(Round round) const
{
	return _best_stations[round];
}

void mue::Calculation::print_stations(std::vector<std::vector<Team_id> > const &stations)
{
	std::cout << "[";
	bool list_first(true);
	for (int round = 0; round< 3; ++round)
	{
		if (!list_first) {
			std::cout << ", ";
		}
		list_first = false;
		std::cout << "[";
		std::map<Team_id, std::vector<Team_id> > tmp;
		for (size_t i = 0; i < stations[round].size(); ++i) {
			tmp[stations[round][i]].push_back(i);
		}

		bool set_first(true);
		for (std::pair<const Team_id, std::vector<Team_id> > const &meeting : tmp) {
			if (!set_first) {
				std::cout << ", ";
			}
			set_first = false;
			std::cout << "set([" << (int) meeting.second[0]
				  <<    ", " << (int) meeting.second[1]
				  <<    ", " << (int) meeting.second[2]
				  << "])";
		}
		std::cout << "]";
	}
	std::cout << "]";
}

void mue::Calculation::report_success(Round_data const &round_data, Iteration_data const &iteration)
{
	_solutions++;
	if (!_distance_is_better(iteration.distance))
		return;
	_best_distance = iteration.distance;
	std::cout << "new best (" << _solutions << ") " << std::fixed << _best_distance << "  ";
	for (uint8_t round = 0; round < 3; ++round) {
		if (round == round_data.prev_stations.size())
			_best_stations[round] = iteration.round_station;
		else
			_best_stations[round] = round_data.prev_stations[round];
	}
	print_stations(_best_stations);
	std::cout << std::endl;
	std::cout.flush();
}

void mue::Calculation::run_firstround_distribution(Round_data const &round_data,
						   Iteration_data &iteration, size_t host_index)
{
	if (host_index == _teams_per_round) {
		run_new_round(round_data, iteration);
		return;
	}

	Team_id host = round_data.hosts[host_index];

	for (Guest_candidate const &candidate : firstround_guest_candidates(iteration, host)) {
		Iteration_data new_iteration(iteration.next_iteration((iteration.distance),
					     host, candidate.guests));
		run_firstround_distribution(round_data, new_iteration, host_index + 1);
	}
}

void mue::Calculation::run_distribution(Round_data const &round_data,
					Iteration_data &iteration, size_t host_index)
{
	BOOST_ASSERT(! round_data.first_round());
	if (host_index == _teams_per_round) {
		run_new_round(round_data, iteration);
		return;
	}

	Team_id host = round_data.hosts[host_index];

		iteration.distance += host_distance(round_data, host);
		if (!_distance_is_better(iteration.distance))
			return;

	size_t slices = _teams_per_round / 3;

	for (Guest_candidate const &candidate : determine_guest_candidates(round_data, iteration, host, host_index, slices)) {
		Iteration_data new_iteration(iteration.next_iteration((candidate.distance),
					     host, candidate.guests));
		run_distribution(round_data, new_iteration, host_index + 1);
	}
}

void mue::Calculation::run_new_round(Round_data const &round_data, Iteration_data &iteration)
{
	if (round_data.round == THIRD) {
		report_success(round_data, iteration);
		return;
	}

	Round_data new_round(next_round_data(round_data, iteration));
	iteration.clear_round_data();

	run_distribution(new_round, iteration, 0);
}

void mue::Calculation::calculate_distribution()
{
	Round_data round_data(initial_round_data());
	Iteration_data iteration_data(_teamcount);

	run_firstround_distribution(round_data, iteration_data, 0);

}
<commit_msg>Test first round slicing<commit_after>#include <limits>
#include <algorithm>
#include <iostream>

#include "mue_algorithm.h"

mue::Calculation::Calculation(unsigned int           teamcount,
			      Distance_matrix const &distance_matrix,
			      Distance               max_single_distance)
:
	_teamcount(teamcount),
	_teams_per_round(teamcount / 3),
	_round_hosts(3),
	_round_guests(3),
	_distance_matrix(distance_matrix),
	_best_distance(std::numeric_limits<float>::max()),
	_max_single_distance(max_single_distance),
	_forecast(distance_matrix),
	_best_stations(3),
	_solutions(0),
	_firstround_selection(distance_matrix, _teams_per_round * 2 -2 )
{
	BOOST_ASSERT(_teamcount <= MAX_TEAMS);
	BOOST_ASSERT(_teamcount / 3 == float(_teamcount / 3));

	for (unsigned int round = 0; round < 3; ++round) {
		for (Team_id team = 0; team < teamcount; ++team) {
			if (_is_round_host(team, static_cast<Round>(round)))
				_round_hosts[round].push_back(team);
			else
				_round_guests[round].push_back(team);
		}
	}

}

mue::Distance mue::Calculation::guest_distance(Round_data                       const &round_data,
					       Team_id                                host,
					       Guest_tuple_generator::GuestPair const &guests) const
{
	return _distance_matrix.lookup(round_data.prev_host(guests.first), host) +
	       _distance_matrix.lookup(round_data.prev_host(guests.second), host);
}

mue::Distance mue::Calculation::host_distance(Round_data const &round_data, Team_id host) const
{
	return _distance_matrix.lookup(round_data.prev_host(host), host);
}

std::vector<mue::Calculation::Guest_candidate>
mue::Calculation::determine_guest_candidates(Round_data     const &round_data,
					     Iteration_data const &iteration_data,
					     Team_id               current_host,
					     size_t         const &host_idx,
					     size_t                slice) const
{
	BOOST_ASSERT(! round_data.first_round());
	std::vector<Guest_candidate> candidates;
	/*
	 * 63 teams have 42 guests (2/3)
	 * (math.factorial(42) / math.factorial(42-2)) / 2 = 861
	 * So for guests of 63 Teams 900 elements are enough.
	 */
	candidates.reserve(900);
	Guest_tuple_generator generator(round_data.guests, iteration_data.used_guests);
	for (Guest_tuple_generator::GuestPair const &guests : generator) {
		if (! iteration_data.seen(current_host, guests.first, guests.second)) {
			float single_distance =
				guest_distance(round_data, current_host, guests);
			float distance = single_distance + iteration_data.distance;

			if (single_distance < _max_single_distance
			   &&  distance + (round_data.round == SECOND
					  ? _forecast.first_move(host_idx)
					  : _forecast.second_move(host_idx)))
				candidates.emplace_back(distance, guests);
		}
	}
	std::sort(candidates.begin(), candidates.end(),
			[](Guest_candidate const &a, Guest_candidate const &b)
				{ return a.distance < b.distance; });
	return std::vector<Guest_candidate>(candidates.begin(),
					    candidates.begin()
					    + std::min(candidates.size(), slice));
}

std::vector<mue::Calculation::Guest_candidate>
mue::Calculation::firstround_guest_candidates(Iteration_data const &iteration_data,
				              Team_id               current_host) const
{
	std::vector<Guest_candidate> candidates;
	/*
	 * 63 teams have 42 guests (2/3)
	 * (math.factorial(42) / math.factorial(42-2)) / 2 = 861
	 * So for guests of 63 Teams 900 elements are enough.
	 */
	candidates.reserve(900);
	Guest_tuple_generator generator(_firstround_selection.for_host(current_host),
			                iteration_data.used_guests);
	for (Guest_tuple_generator::GuestPair const &guests : generator) {
		if (! iteration_data.seen(current_host, guests.first, guests.second)) {
			candidates.emplace_back(0, guests);
		}
	}
	return candidates;
}

mue::Calculation::Round_data mue::Calculation::initial_round_data() const
{
	return Round_data(FIRST, _round_hosts[FIRST], _round_guests[FIRST],
			  std::vector<std::vector<Team_id> >());
}

mue::Calculation::Round_data mue::Calculation::next_round_data(Round_data const &old,
							       Iteration_data const &iteration) const
{
	BOOST_ASSERT(old.round < 2);
	Round next_round = static_cast<Round>(old.round + 1);
	std::vector<std::vector<Team_id> > station_backlog(old.prev_stations);
	station_backlog.push_back(iteration.round_station);
	return Round_data(next_round, _round_hosts[next_round], _round_guests[next_round], station_backlog);
}

std::vector<mue::Team_id> mue::Calculation::round_stations(Round round) const
{
	return _best_stations[round];
}

void mue::Calculation::print_stations(std::vector<std::vector<Team_id> > const &stations)
{
	std::cout << "[";
	bool list_first(true);
	for (int round = 0; round< 3; ++round)
	{
		if (!list_first) {
			std::cout << ", ";
		}
		list_first = false;
		std::cout << "[";
		std::map<Team_id, std::vector<Team_id> > tmp;
		for (size_t i = 0; i < stations[round].size(); ++i) {
			tmp[stations[round][i]].push_back(i);
		}

		bool set_first(true);
		for (std::pair<const Team_id, std::vector<Team_id> > const &meeting : tmp) {
			if (!set_first) {
				std::cout << ", ";
			}
			set_first = false;
			std::cout << "set([" << (int) meeting.second[0]
				  <<    ", " << (int) meeting.second[1]
				  <<    ", " << (int) meeting.second[2]
				  << "])";
		}
		std::cout << "]";
	}
	std::cout << "]";
}

void mue::Calculation::report_success(Round_data const &round_data, Iteration_data const &iteration)
{
	_solutions++;
	if (!_distance_is_better(iteration.distance))
		return;
	_best_distance = iteration.distance;
	std::cout << "new best (" << _solutions << ") " << std::fixed << _best_distance << "  ";
	for (uint8_t round = 0; round < 3; ++round) {
		if (round == round_data.prev_stations.size())
			_best_stations[round] = iteration.round_station;
		else
			_best_stations[round] = round_data.prev_stations[round];
	}
	print_stations(_best_stations);
	std::cout << std::endl;
	std::cout.flush();
}

void mue::Calculation::run_firstround_distribution(Round_data const &round_data,
						   Iteration_data &iteration, size_t host_index)
{
	if (host_index == _teams_per_round) {
		run_new_round(round_data, iteration);
		return;
	}

	Team_id host = round_data.hosts[host_index];

	for (Guest_candidate const &candidate : firstround_guest_candidates(iteration, host)) {
		Iteration_data new_iteration(iteration.next_iteration((iteration.distance),
					     host, candidate.guests));
		run_firstround_distribution(round_data, new_iteration, host_index + 1);
	}
}

void mue::Calculation::run_distribution(Round_data const &round_data,
					Iteration_data &iteration, size_t host_index)
{
	BOOST_ASSERT(! round_data.first_round());
	if (host_index == _teams_per_round) {
		run_new_round(round_data, iteration);
		return;
	}

	Team_id host = round_data.hosts[host_index];

		iteration.distance += host_distance(round_data, host);
		if (!_distance_is_better(iteration.distance))
			return;

	size_t slices = _teams_per_round / 3;

	for (Guest_candidate const &candidate : determine_guest_candidates(round_data, iteration, host, host_index, slices)) {
		Iteration_data new_iteration(iteration.next_iteration((candidate.distance),
					     host, candidate.guests));
		run_distribution(round_data, new_iteration, host_index + 1);
	}
}

void mue::Calculation::run_new_round(Round_data const &round_data, Iteration_data &iteration)
{
	if (round_data.round == THIRD) {
		report_success(round_data, iteration);
		return;
	}

	Round_data new_round(next_round_data(round_data, iteration));
	iteration.clear_round_data();

	run_distribution(new_round, iteration, 0);
}

void mue::Calculation::calculate_distribution()
{
	Round_data round_data(initial_round_data());
	Iteration_data iteration_data(_teamcount);

	run_firstround_distribution(round_data, iteration_data, 0);

}
<|endoftext|>