<commit_before>//======================================================================
//-----------------------------------------------------------------------
/**
 * @file        iutest_console.hpp
 * @brief       iris unit test console
 *
 * @author      t.shirayanagi
 * @par         copyright
 * Copyright (C) 2011-2016, Takazumi Shirayanagi\n
 * This software is released under the new BSD License,
 * see LICENSE
*/
//-----------------------------------------------------------------------
//======================================================================
#ifndef INCG_IRIS_IUTEST_CONSOLE_HPP_DCAC5025_B7BB_424E_A849_9E6FE0A3B460_
#define INCG_IRIS_IUTEST_CONSOLE_HPP_DCAC5025_B7BB_424E_A849_9E6FE0A3B460_

//======================================================================
// include
#include <stdio.h>
#include <stdarg.h>

namespace iutest {
namespace detail
{

//======================================================================
// define
#ifndef IUTEST_VPRINTF
#  define IUTEST_VPRINTF(f, a)  vprintf(f, a)   //!< vprintf 呼び出しマクロ
#endif

#ifndef IUTEST_HAS_COLORCONSOLE
#  if defined(IUTEST_OS_WINDOWS_MOBILE) || defined(IUTEST_OS_NACL)
#    define IUTEST_HAS_COLORCONSOLE 0   //!< 色つきターミナルが使用可能かどうか
#  else
#    define IUTEST_HAS_COLORCONSOLE 1   //!< 色つきターミナルが使用可能かどうか
#  endif
#endif

//======================================================================
// class
/**
 * @internal
 * @brief   カスタム Logger クラス
*/
class iuLogger
{
public:
    virtual ~iuLogger() IUTEST_CXX_DEFAULT_FUNCTION
    virtual void output(const char* fmt, ...)
    {
        va_list va;
        va_start(va, fmt);
        voutput(fmt, va);
        va_end(va);
    }
    virtual void voutput(const char* fmt, va_list va) = 0;
};

/**
 * @internal
 * @brief   コンソールクラス
*/
class iuConsole
{
    template<typename T>
    struct Variable
    {
        static iuLogger* m_pLogger;
    };

    typedef Variable<void> var;

public:
    //! コンソール文字色
    enum Color
    {
        black,
        red,
        green,
        yellow,
        blue,
        magenta,
        cyan,
        white
    };
public:
    /**
     * @brief   標準出力
    */
    static inline void output(const char *fmt, ...);

    /**
     * @brief   標準出力
    */
    static inline void voutput(const char* fmt, va_list va);

    /**
     * @brief   色指定で標準出力
     * @param [in]  color   = 文字色
    */
    static inline void color_output(Color color, const char *fmt, ...);

public:
    /**
     * @brief   標準出力
     * @note    no logger
    */
    static inline void nl_output(const char *fmt, ...);

    /**
     * @brief   標準出力
     * @note    no logger
    */
    static inline void nl_voutput(const char* fmt, va_list va);

public:
    //! Logger のセット
    static iuLogger* SetLogger(iuLogger* logger)
    {
        iuLogger* pre = var::m_pLogger;
        var::m_pLogger = logger;
        return pre;
    }
private:
    static inline void color_output_impl(Color color, const char* fmt, va_list va);
    static inline bool IsShouldUseColor(bool use_color);
    static inline bool HasColorConsole();

private:
    static inline bool IsStringEqual(const char* str1, const char* str2) { return strcmp(str1, str2) == 0; }

    static bool IsColorModeOff()
    {
#if defined(INCG_IRIS_IUTEST_HPP_) && !defined(IUTEST_USE_GTEST)
        return TestFlag::IsEnableFlag(TestFlag::CONSOLE_COLOR_OFF);
#else
        return IUTEST_FLAG(color) == "no";
#endif
    }
    static bool IsColorModeOn()
    {
#if defined(INCG_IRIS_IUTEST_HPP_) && !defined(IUTEST_USE_GTEST)
        return TestFlag::IsEnableFlag(TestFlag::CONSOLE_COLOR_ON);
#else
        return IUTEST_FLAG(color) == "yes";
#endif
    }
    static bool IsColorModeAnsi()
    {
#if defined(INCG_IRIS_IUTEST_HPP_) && !defined(IUTEST_USE_GTEST)
        return TestFlag::IsEnableFlag(TestFlag::CONSOLE_COLOR_ANSI);
#else
        return false;
#endif
    }
};

inline void iuConsole::output(const char *fmt, ...)
{
    va_list va;
    va_start(va, fmt);
    voutput(fmt, va);
    va_end(va);
}
inline void iuConsole::voutput(const char* fmt, va_list va)
{
    if( var::m_pLogger != NULL )
    {
        var::m_pLogger->voutput(fmt, va);
    }
    else
    {
        nl_voutput(fmt, va);
    }
}
inline void iuConsole::color_output(Color color, const char *fmt, ...)
{
    va_list va;
    va_start(va, fmt);

    if( IsShouldUseColor(true) )
    {
        color_output_impl(color, fmt, va);
    }
    else
    {
        voutput(fmt, va);
    }

    va_end(va);
}
inline void iuConsole::nl_output(const char *fmt, ...)
{
    va_list va;
    va_start(va, fmt);
    nl_voutput(fmt, va);
    va_end(va);
}
inline void iuConsole::nl_voutput(const char* fmt, va_list va)
{
    IUTEST_VPRINTF(fmt, va);
}

inline void iuConsole::color_output_impl(Color color, const char* fmt, va_list va)
{
    (void)(fmt);
    (void)(va);
#if defined(IUTEST_OS_WINDOWS) && !defined(IUTEST_OS_WINDOWS_MOBILE) \
        && !defined(IUTEST_OS_WINDOWS_PHONE) && !defined(IUTEST_OS_WINDOWS_RT)
    if( !IsColorModeAnsi() )
    {
        const WORD attr[] = {
            0,
            FOREGROUND_RED,
            FOREGROUND_GREEN,
            FOREGROUND_GREEN | FOREGROUND_RED,
            FOREGROUND_BLUE,
            FOREGROUND_RED | FOREGROUND_BLUE,
            FOREGROUND_GREEN | FOREGROUND_BLUE,
            FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE
        };
        const HANDLE stdout_handle = GetStdHandle(STD_OUTPUT_HANDLE);
        if( stdout_handle != INVALID_HANDLE_VALUE )
        {
            CONSOLE_SCREEN_BUFFER_INFO csbi;
            if( ::GetConsoleScreenBufferInfo(stdout_handle, &csbi) )
            {
                const WORD wAttributes = csbi.wAttributes;

                fflush(stdout);
                ::SetConsoleTextAttribute(stdout_handle, attr[color] | FOREGROUND_INTENSITY);

                voutput(fmt, va);

                fflush(stdout);
                ::SetConsoleTextAttribute(stdout_handle, wAttributes);
                return;
            }
        }
    }
#endif
    {
        output("\033[1;3%cm", '0' + color);
        voutput(fmt, va);
        output("\033[m");
    }
}

inline bool iuConsole::IsShouldUseColor(bool use_color)
{
    if( IsColorModeOn() )
    {
        return true;
    }
    else if( IsColorModeOff() )
    {
        return false;
    }
    static bool has_color = HasColorConsole();
    return use_color && has_color;
}

inline bool iuConsole::HasColorConsole()
{
#if !IUTEST_HAS_COLORCONSOLE
    return false;
#else
#if defined(IUTEST_OS_WINDOWS)
    {
        CONSOLE_SCREEN_BUFFER_INFO csbi;
        if( ::GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi) )
        {
            return true;
        }
    }
#endif
    const char* env = internal::posix::GetEnv("TERM");
    const bool term_conf = (env != NULL) && (
        IsStringEqual(env, "xterm")
        || IsStringEqual(env, "xterm-color")
        || IsStringEqual(env, "xterm-256color")
        || IsStringEqual(env, "screen")
        || IsStringEqual(env, "screen-256color")
        || IsStringEqual(env, "tmux")
        || IsStringEqual(env, "tmux-256color")
        || IsStringEqual(env, "rxvt-unicode")
        || IsStringEqual(env, "rxvt-unicode-256color")
        || IsStringEqual(env, "linux")
        || IsStringEqual(env, "cygwin")
        );
    return term_conf;
#endif
}

}   // end of namespace detail
}   // end of namespace iutest

#if IUTEST_HAS_LIB && IUTEST_HAS_EXTERN_TEMPLATE

IUTEST_PRAGMA_EXTERN_TEMPLATE_WARN_DISABLE_BEGIN()

extern template struct ::iutest::detail::iuConsole::Variable<void>;

IUTEST_PRAGMA_EXTERN_TEMPLATE_WARN_DISABLE_END()

#else

template<typename T>
::iutest::detail::iuLogger* ::iutest::detail::iuConsole::Variable<T>::m_pLogger = NULL;

#endif

#endif // INCG_IRIS_IUTEST_CONSOLE_HPP_DCAC5025_B7BB_424E_A849_9E6FE0A3B460_
<commit_msg>fix cppcheck warning<commit_after>//======================================================================
//-----------------------------------------------------------------------
/**
 * @file        iutest_console.hpp
 * @brief       iris unit test console
 *
 * @author      t.shirayanagi
 * @par         copyright
 * Copyright (C) 2011-2016, Takazumi Shirayanagi\n
 * This software is released under the new BSD License,
 * see LICENSE
*/
//-----------------------------------------------------------------------
//======================================================================
#ifndef INCG_IRIS_IUTEST_CONSOLE_HPP_DCAC5025_B7BB_424E_A849_9E6FE0A3B460_
#define INCG_IRIS_IUTEST_CONSOLE_HPP_DCAC5025_B7BB_424E_A849_9E6FE0A3B460_

//======================================================================
// include
#include <stdio.h>
#include <stdarg.h>

namespace iutest {
namespace detail
{

//======================================================================
// define
#ifndef IUTEST_VPRINTF
#  define IUTEST_VPRINTF(f, a)  vprintf(f, a)   //!< vprintf 呼び出しマクロ
#endif

#ifndef IUTEST_HAS_COLORCONSOLE
#  if defined(IUTEST_OS_WINDOWS_MOBILE) || defined(IUTEST_OS_NACL)
#    define IUTEST_HAS_COLORCONSOLE 0   //!< 色つきターミナルが使用可能かどうか
#  else
#    define IUTEST_HAS_COLORCONSOLE 1   //!< 色つきターミナルが使用可能かどうか
#  endif
#endif

//======================================================================
// class
/**
 * @internal
 * @brief   カスタム Logger クラス
*/
class iuLogger
{
public:
    virtual ~iuLogger() IUTEST_CXX_DEFAULT_FUNCTION
    virtual void output(const char* fmt, ...)
    {
        va_list va;
        va_start(va, fmt);
        voutput(fmt, va);
        va_end(va);
    }
    virtual void voutput(const char* fmt, va_list va) = 0;
};

/**
 * @internal
 * @brief   コンソールクラス
*/
class iuConsole
{
    template<typename T>
    struct Variable
    {
        static iuLogger* m_pLogger;
    };

    typedef Variable<void> var;

public:
    //! コンソール文字色
    enum Color
    {
        black,
        red,
        green,
        yellow,
        blue,
        magenta,
        cyan,
        white
    };
public:
    /**
     * @brief   標準出力
    */
    static inline void output(const char *fmt, ...);

    /**
     * @brief   標準出力
    */
    static inline void voutput(const char* fmt, va_list va);

    /**
     * @brief   色指定で標準出力
     * @param [in]  color   = 文字色
    */
    static inline void color_output(Color color, const char *fmt, ...);

public:
    /**
     * @brief   標準出力
     * @note    no logger
    */
    static inline void nl_output(const char *fmt, ...);

    /**
     * @brief   標準出力
     * @note    no logger
    */
    static inline void nl_voutput(const char* fmt, va_list va);

public:
    //! Logger のセット
    static iuLogger* SetLogger(iuLogger* logger)
    {
        iuLogger* pre = var::m_pLogger;
        var::m_pLogger = logger;
        return pre;
    }

public:
    /**
     * @brief 色付き表示が無効かどうか
     * @return 真偽値
    */
    static bool IsColorModeOff()
    {
#if defined(INCG_IRIS_IUTEST_HPP_) && !defined(IUTEST_USE_GTEST)
        return TestFlag::IsEnableFlag(TestFlag::CONSOLE_COLOR_OFF);
#else
        return IUTEST_FLAG(color) == "no";
#endif
    }
    /**
     * @brief 色付き表示が有効かどうか
     * @return 真偽値
    */
    static bool IsColorModeOn()
    {
#if defined(INCG_IRIS_IUTEST_HPP_) && !defined(IUTEST_USE_GTEST)
        return TestFlag::IsEnableFlag(TestFlag::CONSOLE_COLOR_ON);
#else
        return IUTEST_FLAG(color) == "yes";
#endif
    }
    /**
     * @brief 色付き表示が ANSI エスケープかどうか
     * @return 真偽値
    */
    static bool IsColorModeAnsi()
    {
#if defined(INCG_IRIS_IUTEST_HPP_) && !defined(IUTEST_USE_GTEST)
        return TestFlag::IsEnableFlag(TestFlag::CONSOLE_COLOR_ANSI);
#else
        return false;
#endif
    }

private:
    static inline void color_output_impl(Color color, const char* fmt, va_list va);
    static inline bool IsShouldUseColor(bool use_color);
    static inline bool HasColorConsole();
    static inline bool IsStringEqual(const char* str1, const char* str2) { return strcmp(str1, str2) == 0; }
};

inline void iuConsole::output(const char *fmt, ...)
{
    va_list va;
    va_start(va, fmt);
    voutput(fmt, va);
    va_end(va);
}
inline void iuConsole::voutput(const char* fmt, va_list va)
{
    if( var::m_pLogger != NULL )
    {
        var::m_pLogger->voutput(fmt, va);
    }
    else
    {
        nl_voutput(fmt, va);
    }
}
inline void iuConsole::color_output(Color color, const char *fmt, ...)
{
    va_list va;
    va_start(va, fmt);

    if( IsShouldUseColor(true) )
    {
        color_output_impl(color, fmt, va);
    }
    else
    {
        voutput(fmt, va);
    }

    va_end(va);
}
inline void iuConsole::nl_output(const char *fmt, ...)
{
    va_list va;
    va_start(va, fmt);
    nl_voutput(fmt, va);
    va_end(va);
}
inline void iuConsole::nl_voutput(const char* fmt, va_list va)
{
    IUTEST_VPRINTF(fmt, va);
}

inline void iuConsole::color_output_impl(Color color, const char* fmt, va_list va)
{
    (void)(fmt);
    (void)(va);
#if defined(IUTEST_OS_WINDOWS) && !defined(IUTEST_OS_WINDOWS_MOBILE) \
        && !defined(IUTEST_OS_WINDOWS_PHONE) && !defined(IUTEST_OS_WINDOWS_RT)
    if( !IsColorModeAnsi() )
    {
        const WORD attr[] = {
            0,
            FOREGROUND_RED,
            FOREGROUND_GREEN,
            FOREGROUND_GREEN | FOREGROUND_RED,
            FOREGROUND_BLUE,
            FOREGROUND_RED | FOREGROUND_BLUE,
            FOREGROUND_GREEN | FOREGROUND_BLUE,
            FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE
        };
        const HANDLE stdout_handle = GetStdHandle(STD_OUTPUT_HANDLE);
        if( stdout_handle != INVALID_HANDLE_VALUE )
        {
            CONSOLE_SCREEN_BUFFER_INFO csbi;
            if( ::GetConsoleScreenBufferInfo(stdout_handle, &csbi) )
            {
                const WORD wAttributes = csbi.wAttributes;

                fflush(stdout);
                ::SetConsoleTextAttribute(stdout_handle, attr[color] | FOREGROUND_INTENSITY);

                voutput(fmt, va);

                fflush(stdout);
                ::SetConsoleTextAttribute(stdout_handle, wAttributes);
                return;
            }
        }
    }
#endif
    {
        output("\033[1;3%cm", '0' + color);
        voutput(fmt, va);
        output("\033[m");
    }
}

inline bool iuConsole::IsShouldUseColor(bool use_color)
{
    if( IsColorModeOn() )
    {
        return true;
    }
    else if( IsColorModeOff() )
    {
        return false;
    }
    static bool has_color = HasColorConsole();
    return use_color && has_color;
}

inline bool iuConsole::HasColorConsole()
{
#if !IUTEST_HAS_COLORCONSOLE
    return false;
#else
#if defined(IUTEST_OS_WINDOWS)
    {
        CONSOLE_SCREEN_BUFFER_INFO csbi;
        if( ::GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi) )
        {
            return true;
        }
    }
#endif
    const char* env = internal::posix::GetEnv("TERM");
    const bool term_conf = (env != NULL) && (
        IsStringEqual(env, "xterm")
        || IsStringEqual(env, "xterm-color")
        || IsStringEqual(env, "xterm-256color")
        || IsStringEqual(env, "screen")
        || IsStringEqual(env, "screen-256color")
        || IsStringEqual(env, "tmux")
        || IsStringEqual(env, "tmux-256color")
        || IsStringEqual(env, "rxvt-unicode")
        || IsStringEqual(env, "rxvt-unicode-256color")
        || IsStringEqual(env, "linux")
        || IsStringEqual(env, "cygwin")
        );
    return term_conf;
#endif
}

}   // end of namespace detail
}   // end of namespace iutest

#if IUTEST_HAS_LIB && IUTEST_HAS_EXTERN_TEMPLATE

IUTEST_PRAGMA_EXTERN_TEMPLATE_WARN_DISABLE_BEGIN()

extern template struct ::iutest::detail::iuConsole::Variable<void>;

IUTEST_PRAGMA_EXTERN_TEMPLATE_WARN_DISABLE_END()

#else

template<typename T>
::iutest::detail::iuLogger* ::iutest::detail::iuConsole::Variable<T>::m_pLogger = NULL;

#endif

#endif // INCG_IRIS_IUTEST_CONSOLE_HPP_DCAC5025_B7BB_424E_A849_9E6FE0A3B460_
<|endoftext|>


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

#include "itkBinShrinkImageFilter.h"
#include "itkImageRegionIteratorWithIndex.h"
#include "itkConstShapedNeighborhoodIterator.h"
#include "itkProgressReporter.h"

namespace itk
{

/**
 *
 */
template <class TInputImage, class TOutputImage>
BinShrinkImageFilter<TInputImage,TOutputImage>
::BinShrinkImageFilter()
{
}

/**
 *
 */
template <class TInputImage, class TOutputImage>
void
BinShrinkImageFilter<TInputImage,TOutputImage>
::ThreadedGenerateData(const OutputImageRegionType& outputRegionForThread,
                       ThreadIdType threadId)
{
  itkDebugMacro(<<"Actually executing");

  // Get the input and output pointers
  InputImageConstPointer  inputPtr = this->GetInput();
  OutputImagePointer      outputPtr = this->GetOutput();

  typedef typename NumericTraits<typename TInputImage::PixelType>::RealType AccumulatePixelType;

  // Define/declare an iterator that will walk the output region for this
  // thread.
  typedef ImageRegionIteratorWithIndex<TOutputImage> OutputIterator;
  OutputIterator outIt(outputPtr, outputRegionForThread);

  // Define a few indices that will be used to transform from an input pixel
  // to an output pixel
  OutputIndexType   outputIndex;
  InputIndexType    inputIndex;
  OutputOffsetType  offsetIndex  = this->ComputeOffsetIndex();

  typedef ConstShapedNeighborhoodIterator< TInputImage > ConstNeighborhoodIteratorType;
  typename ConstNeighborhoodIteratorType::RadiusType radius;
  typedef typename ConstNeighborhoodIteratorType::RadiusType::SizeValueType RadiusValueType;
  for (unsigned int i=0; i < TInputImage::ImageDimension; i++)
    {
    radius[i] = Math::Ceil<RadiusValueType>( this->GetShrinkFactors()[i]*0.5 - 0.5);
    }

  ConstNeighborhoodIteratorType inputIt( radius, inputPtr,
                                         inputPtr->GetRequestedRegion() );

  // Set up shaped neighbor hood by defining the offsets
  OutputOffsetType negativeOffset, positiveOffset, iOffset;
  typedef typename OutputOffsetType::OffsetValueType OffsetValueType;
  for ( unsigned int i=0; i < TInputImage::ImageDimension; i++)
    {
    negativeOffset[i] = -Math::Ceil<OffsetValueType>( this->GetShrinkFactors()[i]*0.5 - 0.5);
    positiveOffset[i] =  Math::Floor<OffsetValueType>( this->GetShrinkFactors()[i]*0.5 - 0.5);
    }

  iOffset = negativeOffset;
  while (iOffset[TInputImage::ImageDimension-1] <= positiveOffset[TInputImage::ImageDimension-1])
    {
    inputIt.ActivateOffset( iOffset );

    ++iOffset[0];

    for (unsigned int i=0; i < TInputImage::ImageDimension - 1; i++)
      {
      if (iOffset[i] > positiveOffset[i])
        {
        iOffset[i] = negativeOffset[i];
        ++iOffset[i+1];
        }
      }
    }

  // convert the shrink factor for convenient multiplication
  typename TOutputImage::SizeType  factorSize;
  for (unsigned int i=0; i < TInputImage::ImageDimension; i++)
    {
    factorSize[i] = this->GetShrinkFactors()[i];
    }

  bool degeneratelySmall = false;
  const typename TInputImage::SizeType &inputSize = inputPtr->GetLargestPossibleRegion().GetSize();
  for (unsigned int i=0; i < TInputImage::ImageDimension; i++)
    {
    // the interator neighborhood will fit unless the image was
    // degenerately small, ie the followign is true
    if ( inputSize[i] < this->GetShrinkFactors()[i] )
      {
      degeneratelySmall = true;
      break;
      }
    }
  /*
  // we don't use a face algorithm since we know the neighborhood must
  // fit unless the input image was degeneratly small
  if ( degeneratelySmall )
    {
    inputIt.NeedToUseBoundaryConditionOn();
    }
  else
    {
    inputIt.NeedToUseBoundaryConditionOff();
    }
  */

  // support progress methods/callbacks
  ProgressReporter progress(this, threadId, outputRegionForThread.GetNumberOfPixels());

  while ( !outIt.IsAtEnd() )
    {
    // determine the index and physical location of the output pixel
    outputIndex = outIt.GetIndex();

    // an optimized version of
    // outputPtr->TransformIndexToPhysicalPoint(outputIndex, tempPoint);
    // inputPtr->TransformPhysicalPointToIndex(tempPoint, inputIndex);
    // but without the rounding and precision issues
    inputIndex = outputIndex * factorSize + offsetIndex;

    // Set the iterator at the desired location
    inputIt.SetLocation( inputIndex );

    AccumulatePixelType sum = NumericTraits<AccumulatePixelType>::Zero;
    // Walk the neighborhood

    typename ConstNeighborhoodIteratorType::ConstIterator ci = inputIt.Begin();

    for (ci.GoToBegin(); !ci.IsAtEnd(); ++ci)
      {
      sum += AccumulatePixelType( ci.Get() );
      }
    // this statement is made to work with RGB pixel types
    sum = sum * (1.0 / double( inputIt.GetActiveIndexListSize() ) );

    // set the mean value to the output image
    outIt.Set( sum );
    ++outIt;

    progress.CompletedPixel();
    }
}

/**
 *
 */
template <class TInputImage, class TOutputImage>
void
BinShrinkImageFilter<TInputImage,TOutputImage>
::GenerateInputRequestedRegion()
{
  // call the superclass' implementation of this method
  Superclass::GenerateInputRequestedRegion();

  // get pointers to the input and output
  InputImagePointer  inputPtr = const_cast<TInputImage *> (this->GetInput());
  OutputImagePointer outputPtr = this->GetOutput();

  if ( !inputPtr || !outputPtr )
    {
    return;
    }

  // Compute the input requested region (size and start index)
  // Use the image transformations to insure an input requested region
  // that will provide the proper range
  unsigned int i;
  const typename TOutputImage::SizeType& outputRequestedRegionSize
    = outputPtr->GetRequestedRegion().GetSize();
  const typename TOutputImage::IndexType& outputRequestedRegionStartIndex
    = outputPtr->GetRequestedRegion().GetIndex();

  typename TInputImage::IndexType  inputIndex0,  inputIndex1;
  typename TInputImage::SizeType   inputSize;

  // convert the shrink factor for convenient multiplication
  typename TOutputImage::SizeType  factorSize;
  for (unsigned int i=0; i < TInputImage::ImageDimension; i++)
    {
    factorSize[i] = this->GetShrinkFactors()[i];
    }

  OutputOffsetType  offsetIndex  = this->ComputeOffsetIndex();

  typename TInputImage::OffsetType negativeOffset, positiveOffset;
  typedef typename TInputImage::OffsetType::OffsetValueType OffsetValueType;
  for ( i=0; i < TInputImage::ImageDimension; i++)
    {
    negativeOffset[i] = -Math::Ceil<OffsetValueType>( this->GetShrinkFactors()[i]*0.5 - 0.5);
    positiveOffset[i] =  Math::Floor<OffsetValueType>( this->GetShrinkFactors()[i]*0.5 - 0.5);
    }

  for ( i=0; i < TInputImage::ImageDimension; i++)
    {
    inputIndex0[i] = outputRequestedRegionStartIndex[i]*factorSize[i] + offsetIndex[i] + negativeOffset[i];
    inputIndex1[i] = (outputRequestedRegionStartIndex[i]+outputRequestedRegionSize[i]-1)*factorSize[i] + offsetIndex[i] + positiveOffset[i];

    inputSize[i] = inputIndex1[i] - inputIndex0[i] + 1;
    }

  typename TInputImage::RegionType inputRequestedRegion;
  inputRequestedRegion.SetIndex( inputIndex0 );
  inputRequestedRegion.SetSize( inputSize );

  inputRequestedRegion.Crop( inputPtr->GetLargestPossibleRegion() );

  inputPtr->SetRequestedRegion( inputRequestedRegion );
}

/**
 *
 */
template <class TInputImage, class TOutputImage>
typename BinShrinkImageFilter<TInputImage,TOutputImage>::OutputOffsetType
BinShrinkImageFilter<TInputImage,TOutputImage>
::ComputeOffsetIndex(void)
{
  // get pointers to the input and output
  InputImageConstPointer inputPtr  = this->GetInput();
  OutputImagePointer     outputPtr = this->GetOutput();

  assert( inputPtr && outputPtr );

  OutputIndexType           outputIndex;
  InputIndexType            inputIndex;
  OutputOffsetType          offsetIndex;

  typename TOutputImage::PointType tempPoint;

  // use this index to compute the offset everywhere in this class
  outputIndex = outputPtr->GetLargestPossibleRegion().GetIndex();
  inputIndex = inputPtr->GetLargestPossibleRegion().GetIndex();

  // We wish to perform the following mapping of outputIndex to
  // inputIndex on all points in our region
  outputPtr->TransformIndexToPhysicalPoint( outputIndex, tempPoint );
  inputPtr->TransformPhysicalPointToIndex( tempPoint, inputIndex );

  // Given that the size is scaled by a constant factor eq:
  // inputIndex = outputIndex * factorSize
  // is equivalent up to a fixed offset which we now compute
  for ( unsigned int i=0; i < TInputImage::ImageDimension; i++ )
    {
    offsetIndex[i] = inputIndex[i] - outputIndex[i]*this->GetShrinkFactors()[i];
    }

  return offsetIndex;
}

} // end namespace itk

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

#include "itkBinShrinkImageFilter.h"
#include "itkImageRegionIteratorWithIndex.h"
#include "itkConstShapedNeighborhoodIterator.h"
#include "itkProgressReporter.h"

namespace itk
{

/**
 *
 */
template <class TInputImage, class TOutputImage>
BinShrinkImageFilter<TInputImage,TOutputImage>
::BinShrinkImageFilter()
{
}

/**
 *
 */
template <class TInputImage, class TOutputImage>
void
BinShrinkImageFilter<TInputImage,TOutputImage>
::ThreadedGenerateData(const OutputImageRegionType& outputRegionForThread,
                       ThreadIdType threadId)
{
  itkDebugMacro(<<"Actually executing");

  // Get the input and output pointers
  InputImageConstPointer  inputPtr = this->GetInput();
  OutputImagePointer      outputPtr = this->GetOutput();

  typedef typename NumericTraits<typename TInputImage::PixelType>::RealType AccumulatePixelType;

  // Define/declare an iterator that will walk the output region for this
  // thread.
  typedef ImageRegionIteratorWithIndex<TOutputImage> OutputIterator;
  OutputIterator outIt(outputPtr, outputRegionForThread);

  // Define a few indices that will be used to transform from an input pixel
  // to an output pixel
  OutputIndexType   outputIndex;
  InputIndexType    inputIndex;
  OutputOffsetType  offsetIndex  = this->ComputeOffsetIndex();

  typedef ConstShapedNeighborhoodIterator< TInputImage > ConstNeighborhoodIteratorType;
  typename ConstNeighborhoodIteratorType::RadiusType radius;
  typedef typename ConstNeighborhoodIteratorType::RadiusType::SizeValueType RadiusValueType;
  for (unsigned int i=0; i < TInputImage::ImageDimension; ++i)
    {
    radius[i] = Math::Ceil<RadiusValueType>( this->GetShrinkFactors()[i]*0.5 - 0.5);
    }

  ConstNeighborhoodIteratorType inputIt( radius, inputPtr,
                                         inputPtr->GetRequestedRegion() );

  // Set up shaped neighbor hood by defining the offsets
  OutputOffsetType negativeOffset, positiveOffset, iOffset;
  typedef typename OutputOffsetType::OffsetValueType OffsetValueType;
  for ( unsigned int i=0; i < TInputImage::ImageDimension; ++i)
    {
    negativeOffset[i] = -Math::Ceil<OffsetValueType>( this->GetShrinkFactors()[i]*0.5 - 0.5);
    positiveOffset[i] =  Math::Floor<OffsetValueType>( this->GetShrinkFactors()[i]*0.5 - 0.5);
    }

  iOffset = negativeOffset;
  while (iOffset[TInputImage::ImageDimension-1] <= positiveOffset[TInputImage::ImageDimension-1])
    {
    inputIt.ActivateOffset( iOffset );

    ++iOffset[0];

    for (unsigned int i=0; i < TInputImage::ImageDimension - 1; ++i)
      {
      if (iOffset[i] > positiveOffset[i])
        {
        iOffset[i] = negativeOffset[i];
        ++iOffset[i+1];
        }
      }
    }

  // convert the shrink factor for convenient multiplication
  typename TOutputImage::SizeType  factorSize;
  for (unsigned int i=0; i < TInputImage::ImageDimension; ++i)
    {
    factorSize[i] = this->GetShrinkFactors()[i];
    }

  bool degeneratelySmall = false;
  const typename TInputImage::SizeType &inputSize = inputPtr->GetLargestPossibleRegion().GetSize();
  for (unsigned int i=0; i < TInputImage::ImageDimension; ++i)
    {
    // the interator neighborhood will fit unless the image was
    // degenerately small, ie the followign is true
    if ( inputSize[i] < this->GetShrinkFactors()[i] )
      {
      degeneratelySmall = true;
      break;
      }
    }
  /*
  // we don't use a face algorithm since we know the neighborhood must
  // fit unless the input image was degeneratly small
  if ( degeneratelySmall )
    {
    inputIt.NeedToUseBoundaryConditionOn();
    }
  else
    {
    inputIt.NeedToUseBoundaryConditionOff();
    }
  */

  // support progress methods/callbacks
  ProgressReporter progress(this, threadId, outputRegionForThread.GetNumberOfPixels());

  while ( !outIt.IsAtEnd() )
    {
    // determine the index and physical location of the output pixel
    outputIndex = outIt.GetIndex();

    // an optimized version of
    // outputPtr->TransformIndexToPhysicalPoint(outputIndex, tempPoint);
    // inputPtr->TransformPhysicalPointToIndex(tempPoint, inputIndex);
    // but without the rounding and precision issues
    inputIndex = outputIndex * factorSize + offsetIndex;

    // Set the iterator at the desired location
    inputIt.SetLocation( inputIndex );

    AccumulatePixelType sum = NumericTraits<AccumulatePixelType>::Zero;
    // Walk the neighborhood

    typename ConstNeighborhoodIteratorType::ConstIterator ci = inputIt.Begin();

    for (ci.GoToBegin(); !ci.IsAtEnd(); ++ci)
      {
      sum += AccumulatePixelType( ci.Get() );
      }
    // this statement is made to work with RGB pixel types
    sum = sum * (1.0 / double( inputIt.GetActiveIndexListSize() ) );

    // set the mean value to the output image
    outIt.Set( sum );
    ++outIt;

    progress.CompletedPixel();
    }
}

/**
 *
 */
template <class TInputImage, class TOutputImage>
void
BinShrinkImageFilter<TInputImage,TOutputImage>
::GenerateInputRequestedRegion()
{
  // call the superclass' implementation of this method
  Superclass::GenerateInputRequestedRegion();

  // get pointers to the input and output
  InputImagePointer  inputPtr = const_cast<TInputImage *> (this->GetInput());
  OutputImagePointer outputPtr = this->GetOutput();

  if ( !inputPtr || !outputPtr )
    {
    return;
    }

  // Compute the input requested region (size and start index)
  // Use the image transformations to insure an input requested region
  // that will provide the proper range
  const typename TOutputImage::SizeType& outputRequestedRegionSize
    = outputPtr->GetRequestedRegion().GetSize();
  const typename TOutputImage::IndexType& outputRequestedRegionStartIndex
    = outputPtr->GetRequestedRegion().GetIndex();

  typename TInputImage::IndexType  inputIndex0,  inputIndex1;
  typename TInputImage::SizeType   inputSize;

  // convert the shrink factor for convenient multiplication
  typename TOutputImage::SizeType  factorSize;
  for (unsigned int i=0; i < TInputImage::ImageDimension; ++i)
    {
    factorSize[i] = this->GetShrinkFactors()[i];
    }

  OutputOffsetType  offsetIndex  = this->ComputeOffsetIndex();

  typename TInputImage::OffsetType negativeOffset, positiveOffset;
  typedef typename TInputImage::OffsetType::OffsetValueType OffsetValueType;
  for ( unsigned int i=0; i < TInputImage::ImageDimension; ++i)
    {
    negativeOffset[i] = -Math::Ceil<OffsetValueType>( this->GetShrinkFactors()[i]*0.5 - 0.5);
    positiveOffset[i] =  Math::Floor<OffsetValueType>( this->GetShrinkFactors()[i]*0.5 - 0.5);
    }

  for ( unsigned int i=0; i < TInputImage::ImageDimension; ++i)
    {
    inputIndex0[i] = outputRequestedRegionStartIndex[i]*factorSize[i] + offsetIndex[i] + negativeOffset[i];
    inputIndex1[i] = (outputRequestedRegionStartIndex[i]+outputRequestedRegionSize[i]-1)*factorSize[i] + offsetIndex[i] + positiveOffset[i];

    inputSize[i] = inputIndex1[i] - inputIndex0[i] + 1;
    }

  typename TInputImage::RegionType inputRequestedRegion;
  inputRequestedRegion.SetIndex( inputIndex0 );
  inputRequestedRegion.SetSize( inputSize );

  inputRequestedRegion.Crop( inputPtr->GetLargestPossibleRegion() );

  inputPtr->SetRequestedRegion( inputRequestedRegion );
}

/**
 *
 */
template <class TInputImage, class TOutputImage>
typename BinShrinkImageFilter<TInputImage,TOutputImage>::OutputOffsetType
BinShrinkImageFilter<TInputImage,TOutputImage>
::ComputeOffsetIndex(void)
{
  // get pointers to the input and output
  InputImageConstPointer inputPtr  = this->GetInput();
  OutputImagePointer     outputPtr = this->GetOutput();

  assert( inputPtr && outputPtr );

  OutputIndexType           outputIndex;
  InputIndexType            inputIndex;
  OutputOffsetType          offsetIndex;

  typename TOutputImage::PointType tempPoint;

  // use this index to compute the offset everywhere in this class
  outputIndex = outputPtr->GetLargestPossibleRegion().GetIndex();
  inputIndex = inputPtr->GetLargestPossibleRegion().GetIndex();

  // We wish to perform the following mapping of outputIndex to
  // inputIndex on all points in our region
  outputPtr->TransformIndexToPhysicalPoint( outputIndex, tempPoint );
  inputPtr->TransformPhysicalPointToIndex( tempPoint, inputIndex );

  // Given that the size is scaled by a constant factor eq:
  // inputIndex = outputIndex * factorSize
  // is equivalent up to a fixed offset which we now compute
  for ( unsigned int i=0; i < TInputImage::ImageDimension; ++i )
    {
    offsetIndex[i] = inputIndex[i] - outputIndex[i]*this->GetShrinkFactors()[i];
    }

  return offsetIndex;
}

} // end namespace itk

#endif
<|endoftext|>


<commit_before>#include "osg/Image"
#include "osg/Notify"

#include <osg/Geode>

#include "osg/GL"

#include "osgDB/FileNameUtils"
#include "osgDB/Registry"
#include "osgDB/FileUtils"

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#ifndef SEEK_SET
#  define SEEK_SET 0
#endif

#include "QTtexture.h"

using namespace osg;

class ReaderWriterQT : public osgDB::ReaderWriter
{
    public:
        virtual const char* className() { return "Default Quicktime Image Reader/Writer"; }

        virtual bool acceptsExtension(const std::string& extension)
        {
            // this should be the only image importer required on the Mac
            // dont know what else it supports, but these will do
            return osgDB::equalCaseInsensitive(extension,"rgb") ||
                osgDB::equalCaseInsensitive(extension,"rgba") ||
                osgDB::equalCaseInsensitive(extension,"jpg") ||
                osgDB::equalCaseInsensitive(extension,"jpeg") ||
                osgDB::equalCaseInsensitive(extension,"tiff") ||
                osgDB::equalCaseInsensitive(extension,"pict") ||
                osgDB::equalCaseInsensitive(extension,"gif") ||
                osgDB::equalCaseInsensitive(extension,"png") ||
                osgDB::equalCaseInsensitive(extension,"pict") ||
                osgDB::equalCaseInsensitive(extension,"pct") ||
                osgDB::equalCaseInsensitive(extension,"tga");
        }

        virtual ReadResult readImage(const std::string& file, const osgDB::ReaderWriter::Options*)
        {
            std::string ext = osgDB::getLowerCaseFileExtension(file);
            if (!acceptsExtension(ext)) return ReadResult::FILE_NOT_HANDLED;

            std::string fileName = osgDB::findDataFile( file );
            if (fileName.empty()) return ReadResult::FILE_NOT_FOUND;

            long origWidth, origHeight,buffWidth,buffHeight,buffDepth,origDepth;

            // NOTE - implememntation means that this will always return 32 bits, so it is hard to work out if
            // an image was monochrome. So it will waste texture memory unless it gets a monochrome hint.

            unsigned char *pixels = LoadBufferFromDarwinPath ( fileName.c_str(), &origWidth,&origHeight,&origDepth,
                                &buffWidth,&buffHeight,
                                &buffDepth);

            // IMPORTANT -
            // origDepth in BYTES, buffDepth in BITS

            if (pixels == 0) {
                    std::cerr << "LoadBufferFromDarwinPath failed " << fileName.c_str() << QTfailureMessage() << std::endl;
                    return 0;
            }

            unsigned int pixelFormat;

            switch(origDepth) {
                case 1 :
                    pixelFormat = GL_RGB;
                    break;
                case 2 :
                    pixelFormat = GL_LUMINANCE_ALPHA;
                    break;
                case 3 :
                    pixelFormat = GL_RGB;
                    break;
                case 4 :
                    pixelFormat = GL_RGBA;
                    break;
                default :
                    std::cerr << "Unknown file type in " << fileName.c_str() << " with " << origDepth << std::endl;
                    pixelFormat = (GLenum)-1;
                    return 0;
                    break;
            }

            {
                unsigned char *srcp=pixels, *dstp=pixels;

                int i, j;

                // swizzle entire image in-place
                for (i=0; i<buffHeight; i++ ) {
                    unsigned char r, g, b, a;
                    switch (origDepth) {
                    /*
                        since 8-bit tgas will get expanded into colour, have to use RGB code for 8-bit images

                        case 1 :
                            for (j=0; j<buffWidth; j++ ) {
                                dstp[0]=srcp[2];
                                srcp+=4;
                                dstp++;
                            }
                            break;
                        */
                        case 2 :
                            for (j=0; j<buffWidth; j++ ) {
                                dstp[1]=srcp[0];
                                dstp[0]=srcp[2];
                                srcp+=4;
                                dstp+=2;
                            }
                            break;
                        case 1 :
                        case 3 :
                            for (j=0; j<buffWidth; j++ ) {
                                dstp[0]=srcp[1];
                                dstp[1]=srcp[2];
                                dstp[2]=srcp[3];
                                srcp+=4;
                                dstp+=3;
                            }
                            break;
                        case 4 :
                            for (j=0; j<buffWidth; j++ ) {
                                r=srcp[1];
                                g=srcp[2];
                                b=srcp[3];
                                a=srcp[0];

                                dstp[0]=r;
                                dstp[1]=g;
                                dstp[2]=b;
                                dstp[3]=a;

                                srcp+=4;
                                dstp+=4;
                            }
                            break;
                        default :
                            // std::cerr << "ERROR IN RETURNED PIXEL DEPTH, CANNOT COPE" << std::endl;
                            return 0;
                            break;
                    }
                }
            }

            Image* image = new Image();
            image->setFileName(fileName.c_str());
            image->setImage(buffWidth,buffHeight,1,
                buffDepth >> 3,
                pixelFormat,
                GL_UNSIGNED_BYTE,
                pixels,
                osg::Image::USE_NEW_DELETE );

            notify(INFO) << "image read ok "<<buffWidth<<"  "<<buffHeight<<std::endl;
            return image;
        }

};

// now register with Registry to instantiate the above
// reader/writer.
osgDB::RegisterReaderWriterProxy<ReaderWriterQT> g_readerWriter_QT_Proxy;
<commit_msg>Changed cerr to osg::notify(osg::WARN)<commit_after>#include "osg/Image"
#include "osg/Notify"

#include <osg/Geode>

#include "osg/GL"

#include "osgDB/FileNameUtils"
#include "osgDB/Registry"
#include "osgDB/FileUtils"

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#ifndef SEEK_SET
#  define SEEK_SET 0
#endif

#include "QTtexture.h"

using namespace osg;

class ReaderWriterQT : public osgDB::ReaderWriter
{
    public:
        virtual const char* className() { return "Default Quicktime Image Reader/Writer"; }

        virtual bool acceptsExtension(const std::string& extension)
        {
            // this should be the only image importer required on the Mac
            // dont know what else it supports, but these will do
            return osgDB::equalCaseInsensitive(extension,"rgb") ||
                osgDB::equalCaseInsensitive(extension,"rgba") ||
                osgDB::equalCaseInsensitive(extension,"jpg") ||
                osgDB::equalCaseInsensitive(extension,"jpeg") ||
                osgDB::equalCaseInsensitive(extension,"tiff") ||
                osgDB::equalCaseInsensitive(extension,"pict") ||
                osgDB::equalCaseInsensitive(extension,"gif") ||
                osgDB::equalCaseInsensitive(extension,"png") ||
                osgDB::equalCaseInsensitive(extension,"pict") ||
                osgDB::equalCaseInsensitive(extension,"pct") ||
                osgDB::equalCaseInsensitive(extension,"tga");
        }

        virtual ReadResult readImage(const std::string& file, const osgDB::ReaderWriter::Options*)
        {
            std::string ext = osgDB::getLowerCaseFileExtension(file);
            if (!acceptsExtension(ext)) return ReadResult::FILE_NOT_HANDLED;

            std::string fileName = osgDB::findDataFile( file );
            if (fileName.empty()) return ReadResult::FILE_NOT_FOUND;

            long origWidth, origHeight,buffWidth,buffHeight,buffDepth,origDepth;

            // NOTE - implememntation means that this will always return 32 bits, so it is hard to work out if
            // an image was monochrome. So it will waste texture memory unless it gets a monochrome hint.

            unsigned char *pixels = LoadBufferFromDarwinPath ( fileName.c_str(), &origWidth,&origHeight,&origDepth,
                                &buffWidth,&buffHeight,
                                &buffDepth);

            // IMPORTANT -
            // origDepth in BYTES, buffDepth in BITS

            if (pixels == 0) {
                    osg::notify(osg::WARN) << "LoadBufferFromDarwinPath failed " << fileName.c_str() << QTfailureMessage() << std::endl;
                    return 0;
            }

            unsigned int pixelFormat;

            switch(origDepth) {
                case 1 :
                    pixelFormat = GL_RGB;
                    break;
                case 2 :
                    pixelFormat = GL_LUMINANCE_ALPHA;
                    break;
                case 3 :
                    pixelFormat = GL_RGB;
                    break;
                case 4 :
                    pixelFormat = GL_RGBA;
                    break;
                default :
                    osg::notify(osg::WARN) << "Unknown file type in " << fileName.c_str() << " with " << origDepth << std::endl;
                    pixelFormat = (GLenum)-1;
                    return 0;
                    break;
            }

            {
                unsigned char *srcp=pixels, *dstp=pixels;

                int i, j;

                // swizzle entire image in-place
                for (i=0; i<buffHeight; i++ ) {
                    unsigned char r, g, b, a;
                    switch (origDepth) {
                    /*
                        since 8-bit tgas will get expanded into colour, have to use RGB code for 8-bit images

                        case 1 :
                            for (j=0; j<buffWidth; j++ ) {
                                dstp[0]=srcp[2];
                                srcp+=4;
                                dstp++;
                            }
                            break;
                        */
                        case 2 :
                            for (j=0; j<buffWidth; j++ ) {
                                dstp[1]=srcp[0];
                                dstp[0]=srcp[2];
                                srcp+=4;
                                dstp+=2;
                            }
                            break;
                        case 1 :
                        case 3 :
                            for (j=0; j<buffWidth; j++ ) {
                                dstp[0]=srcp[1];
                                dstp[1]=srcp[2];
                                dstp[2]=srcp[3];
                                srcp+=4;
                                dstp+=3;
                            }
                            break;
                        case 4 :
                            for (j=0; j<buffWidth; j++ ) {
                                r=srcp[1];
                                g=srcp[2];
                                b=srcp[3];
                                a=srcp[0];

                                dstp[0]=r;
                                dstp[1]=g;
                                dstp[2]=b;
                                dstp[3]=a;

                                srcp+=4;
                                dstp+=4;
                            }
                            break;
                        default :
                            // osg::notify(osg::WARN) << "ERROR IN RETURNED PIXEL DEPTH, CANNOT COPE" << std::endl;
                            return 0;
                            break;
                    }
                }
            }

            Image* image = new Image();
            image->setFileName(fileName.c_str());
            image->setImage(buffWidth,buffHeight,1,
                buffDepth >> 3,
                pixelFormat,
                GL_UNSIGNED_BYTE,
                pixels,
                osg::Image::USE_NEW_DELETE );

            notify(INFO) << "image read ok "<<buffWidth<<"  "<<buffHeight<<std::endl;
            return image;
        }

};

// now register with Registry to instantiate the above
// reader/writer.
osgDB::RegisterReaderWriterProxy<ReaderWriterQT> g_readerWriter_QT_Proxy;
<|endoftext|>


<commit_before>/** Copyright 2008, 2009, 2010, 2011, 2012 Roland Olbricht
*
* This file is part of Overpass_API.
*
* Overpass_API is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* Overpass_API is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Overpass_API.  If not, see <http://www.gnu.org/licenses/>.
*/

#include <fstream>
#include <iostream>
#include <map>
#include <sstream>
#include <string>
#include <vector>

#include <stdint.h>
#include <stdlib.h>
#include <time.h>

#include "cgi-helper.h"
#include "../../expat/expat_justparse_interface.h"
#include "user_interface.h"

using namespace std;

namespace
{
  string autocomplete
      (string& input, Error_Output* error_output, uint32 max_input_size)
  {
    unsigned int pos(0), line_number(1);
    while ((pos < input.size()) && (isspace(input[pos])))
    {
      if (input[pos] == '\n')
	++line_number;
      ++pos;
    }

    if (pos == input.size())
    {
      if (pos == 0)
      {
	if (error_output)
	  error_output->add_encoding_error("Your input is empty.");
      }
      else
      {
	if (error_output)
	  error_output->add_encoding_error("Your input contains only whitespace.");
      }
      return "";
    }

    // pos now points at the first non-whitespace character
    // assert length restriction.
    if (input.size() > max_input_size)
    {
      ostringstream temp;
      temp<<"Input too long (length: "<<input.size()<<", max. allowed: "<<max_input_size<<')';
      if (error_output)
	error_output->add_encoding_error(temp.str());
      return input;
    }

    // pos again points at the first non-whitespace character.
    if (input.substr(pos, 1) == "<" && input.substr(pos, 2) != "<?")
    {
      if (input.find("<osm-script") == string::npos)
        // Add a header line, the root tag 'osm-script' and remove trailing whitespace
      {
        ostringstream temp;
        temp<<"Your input starts with a tag but not the root tag. Thus, a line with the\n"
            <<"datatype declaration and a line with the root tag 'osm-script' is\n"
            <<"added. This shifts line numbering by "<<(int)line_number-3<<" line(s).";
        if (error_output)
          error_output->add_encoding_remark(temp.str());

        input = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<osm-script>\n"
            + input.substr(pos) + "\n</osm-script>\n";
      }
      else
        // Add a header line and remove trailing whitespace.
      {
        ostringstream temp;
        temp<<"Your input contains an 'osm-script' tag. Thus, a line with the\n"
            <<"datatype declaration is added. This shifts line numbering by "
            <<(int)line_number - 2<<" line(s).";
        if (error_output)
          error_output->add_encoding_remark(temp.str());

        input = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" + input.substr(pos);
      }
    }

    return input;
  }
}

string get_xml_cgi(Error_Output* error_output, uint32 max_input_size, string& url, bool& redirect,
		   string& template_name, Web_Output::Http_Methods& http_method, string& allow_header,
                   bool& has_origin)
{
  // Check for various HTTP headers
  char* method = getenv("REQUEST_METHOD");
  if (method)
  {
    if (!strncmp(method, "HEAD", 5))
      http_method = Web_Output::http_head;
    else if (!strncmp(method, "OPTIONS", 8))
      http_method = Web_Output::http_options;
  }
  char* allow_header_c = getenv("HTTP_ACCESS_CONTROL_REQUEST_HEADERS");
  allow_header = ((allow_header_c) ? allow_header_c : "");
  char* origin = getenv("HTTP_ORIGIN");
  has_origin = ((origin) && strnlen(origin, 1) > 0);

  int line_number(1);
  // If there is nonempty input from GET method, use GET
  string input(cgi_get_to_text());
  unsigned int pos(0);
  while ((pos < input.size()) && (isspace(input[pos])))
  {
    if (input[pos] == '\n')
      ++line_number;
    ++pos;
  }

  if (pos == input.size())
  {
    if (http_method == Web_Output::http_options)
      // if we have an OPTIONS request then assume the query is valid
      // As a quick hack set the input to a valid dummy value
      return "out;";

    // otherwise use POST input
    if (pos == 0)
    {
      if (error_output)
        error_output->add_encoding_remark("No input found from GET method. Trying to retrieve input by POST method.");
    }
    else
    {
      if (error_output)
	error_output->add_encoding_remark("Only whitespace found from GET method. Trying to retrieve input by POST method.");
    }

    input = cgi_post_to_text();
    pos = 0;
    line_number = 1;
    while ((pos < input.size()) && (isspace(input[pos])))
    {
      if (input[pos] == '\n')
	++line_number;
      ++pos;
    }

    if (pos == input.size())
    {
      if (pos == 0)
      {
	if (error_output)
	  error_output->add_encoding_error("Your input is empty.");
      }
      else
      {
	if (error_output)
	  error_output->add_encoding_error("Your input contains only whitespace.");
      }
      return "";
    }
  }
  else
  {
    if (error_output)
      error_output->add_encoding_remark("Found input from GET method. Thus, any input from POST is ignored.");
  }

  // pos now points at the first non-whitespace character
  if (input[pos] != '<')
    // reduce input to the part between "data=" and "&"
    // and remove the character escapings from the form
  {
    if (error_output)
      error_output->add_encoding_remark("The server now removes the CGI character escaping.");
    string jsonp;
    input = decode_cgi_to_plain(input, jsonp, url, redirect, template_name);

    // sanity check for template_name
    if (template_name.find("/") != std::string::npos)
    {
      if (error_output)
	error_output->add_encoding_error("Parameter \"template\" must not contain slashes.");
      template_name = "";
    }

    // sanity check for jsonp
    for (std::string::size_type i = 0; i < jsonp.size(); ++i)
    {
      if (!isalnum(jsonp[i]) && !(jsonp[i] == '_'))
      {
	error_output->add_encoding_error("Parameter \"jsonp\" must contain only letters, digits, or the underscore.");
	jsonp = "";
      }
    }

    if (jsonp != "")
      error_output->add_padding(jsonp);
  }
  else
  {
    if (error_output)
      error_output->add_encoding_remark("The first non-whitespace character is '<'. Thus, your input will be interpreted verbatim.");
  }

  input = autocomplete(input, error_output, max_input_size);
  return input;
}

string get_xml_console(Error_Output* error_output, uint32 max_input_size)
{
  if (error_output)
    error_output->add_encoding_remark("Please enter your query and terminate it with CTRL+D.");

  // If there is nonempty input from GET method, use GET
  string input("");
  input = cgi_post_to_text();
  input = autocomplete(input, error_output, max_input_size);
  return input;
}

string probe_client_identifier()
{
  char* remote_addr_c = getenv("REMOTE_ADDR");
  if (!remote_addr_c)
    return "";

  return string(remote_addr_c);
}

uint32 probe_client_token()
{
  string ip_addr = probe_client_identifier();
  if (ip_addr == "")
    return 0;

  string::size_type pos = ip_addr.find(".");
  string::size_type old_pos = 0;
  uint32 client_token = 0;

  // Try IPv4 address format
  while (pos != string::npos)
  {
    client_token = (client_token<<8 |
        atoll(ip_addr.substr(old_pos, pos - old_pos).c_str()));
    old_pos = pos + 1;
    pos = ip_addr.find(".", old_pos);
  }
  client_token = (client_token<<8 |
    atoll(ip_addr.substr(old_pos).c_str()));

  return client_token;
}
<commit_msg>Allow dots in jsonp.<commit_after>/** Copyright 2008, 2009, 2010, 2011, 2012 Roland Olbricht
*
* This file is part of Overpass_API.
*
* Overpass_API is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* Overpass_API is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Overpass_API.  If not, see <http://www.gnu.org/licenses/>.
*/

#include <fstream>
#include <iostream>
#include <map>
#include <sstream>
#include <string>
#include <vector>

#include <stdint.h>
#include <stdlib.h>
#include <time.h>

#include "cgi-helper.h"
#include "../../expat/expat_justparse_interface.h"
#include "user_interface.h"

using namespace std;

namespace
{
  string autocomplete
      (string& input, Error_Output* error_output, uint32 max_input_size)
  {
    unsigned int pos(0), line_number(1);
    while ((pos < input.size()) && (isspace(input[pos])))
    {
      if (input[pos] == '\n')
	++line_number;
      ++pos;
    }

    if (pos == input.size())
    {
      if (pos == 0)
      {
	if (error_output)
	  error_output->add_encoding_error("Your input is empty.");
      }
      else
      {
	if (error_output)
	  error_output->add_encoding_error("Your input contains only whitespace.");
      }
      return "";
    }

    // pos now points at the first non-whitespace character
    // assert length restriction.
    if (input.size() > max_input_size)
    {
      ostringstream temp;
      temp<<"Input too long (length: "<<input.size()<<", max. allowed: "<<max_input_size<<')';
      if (error_output)
	error_output->add_encoding_error(temp.str());
      return input;
    }

    // pos again points at the first non-whitespace character.
    if (input.substr(pos, 1) == "<" && input.substr(pos, 2) != "<?")
    {
      if (input.find("<osm-script") == string::npos)
        // Add a header line, the root tag 'osm-script' and remove trailing whitespace
      {
        ostringstream temp;
        temp<<"Your input starts with a tag but not the root tag. Thus, a line with the\n"
            <<"datatype declaration and a line with the root tag 'osm-script' is\n"
            <<"added. This shifts line numbering by "<<(int)line_number-3<<" line(s).";
        if (error_output)
          error_output->add_encoding_remark(temp.str());

        input = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<osm-script>\n"
            + input.substr(pos) + "\n</osm-script>\n";
      }
      else
        // Add a header line and remove trailing whitespace.
      {
        ostringstream temp;
        temp<<"Your input contains an 'osm-script' tag. Thus, a line with the\n"
            <<"datatype declaration is added. This shifts line numbering by "
            <<(int)line_number - 2<<" line(s).";
        if (error_output)
          error_output->add_encoding_remark(temp.str());

        input = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" + input.substr(pos);
      }
    }

    return input;
  }
}

string get_xml_cgi(Error_Output* error_output, uint32 max_input_size, string& url, bool& redirect,
		   string& template_name, Web_Output::Http_Methods& http_method, string& allow_header,
                   bool& has_origin)
{
  // Check for various HTTP headers
  char* method = getenv("REQUEST_METHOD");
  if (method)
  {
    if (!strncmp(method, "HEAD", 5))
      http_method = Web_Output::http_head;
    else if (!strncmp(method, "OPTIONS", 8))
      http_method = Web_Output::http_options;
  }
  char* allow_header_c = getenv("HTTP_ACCESS_CONTROL_REQUEST_HEADERS");
  allow_header = ((allow_header_c) ? allow_header_c : "");
  char* origin = getenv("HTTP_ORIGIN");
  has_origin = ((origin) && strnlen(origin, 1) > 0);

  int line_number(1);
  // If there is nonempty input from GET method, use GET
  string input(cgi_get_to_text());
  unsigned int pos(0);
  while ((pos < input.size()) && (isspace(input[pos])))
  {
    if (input[pos] == '\n')
      ++line_number;
    ++pos;
  }

  if (pos == input.size())
  {
    if (http_method == Web_Output::http_options)
      // if we have an OPTIONS request then assume the query is valid
      // As a quick hack set the input to a valid dummy value
      return "out;";

    // otherwise use POST input
    if (pos == 0)
    {
      if (error_output)
        error_output->add_encoding_remark("No input found from GET method. Trying to retrieve input by POST method.");
    }
    else
    {
      if (error_output)
	error_output->add_encoding_remark("Only whitespace found from GET method. Trying to retrieve input by POST method.");
    }

    input = cgi_post_to_text();
    pos = 0;
    line_number = 1;
    while ((pos < input.size()) && (isspace(input[pos])))
    {
      if (input[pos] == '\n')
	++line_number;
      ++pos;
    }

    if (pos == input.size())
    {
      if (pos == 0)
      {
	if (error_output)
	  error_output->add_encoding_error("Your input is empty.");
      }
      else
      {
	if (error_output)
	  error_output->add_encoding_error("Your input contains only whitespace.");
      }
      return "";
    }
  }
  else
  {
    if (error_output)
      error_output->add_encoding_remark("Found input from GET method. Thus, any input from POST is ignored.");
  }

  // pos now points at the first non-whitespace character
  if (input[pos] != '<')
    // reduce input to the part between "data=" and "&"
    // and remove the character escapings from the form
  {
    if (error_output)
      error_output->add_encoding_remark("The server now removes the CGI character escaping.");
    string jsonp;
    input = decode_cgi_to_plain(input, jsonp, url, redirect, template_name);

    // sanity check for template_name
    if (template_name.find("/") != std::string::npos)
    {
      if (error_output)
	error_output->add_encoding_error("Parameter \"template\" must not contain slashes.");
      template_name = "";
    }

    // sanity check for jsonp
    for (std::string::size_type i = 0; i < jsonp.size(); ++i)
    {
      if (!isalnum(jsonp[i]) && !(jsonp[i] == '_') && !(jsonp[i] == '.'))
      {
	error_output->add_encoding_error("Parameter \"jsonp\" must contain only letters, digits, or the underscore.");
	jsonp = "";
      }
    }

    if (jsonp != "")
      error_output->add_padding(jsonp);
  }
  else
  {
    if (error_output)
      error_output->add_encoding_remark("The first non-whitespace character is '<'. Thus, your input will be interpreted verbatim.");
  }

  input = autocomplete(input, error_output, max_input_size);
  return input;
}

string get_xml_console(Error_Output* error_output, uint32 max_input_size)
{
  if (error_output)
    error_output->add_encoding_remark("Please enter your query and terminate it with CTRL+D.");

  // If there is nonempty input from GET method, use GET
  string input("");
  input = cgi_post_to_text();
  input = autocomplete(input, error_output, max_input_size);
  return input;
}

string probe_client_identifier()
{
  char* remote_addr_c = getenv("REMOTE_ADDR");
  if (!remote_addr_c)
    return "";

  return string(remote_addr_c);
}

uint32 probe_client_token()
{
  string ip_addr = probe_client_identifier();
  if (ip_addr == "")
    return 0;

  string::size_type pos = ip_addr.find(".");
  string::size_type old_pos = 0;
  uint32 client_token = 0;

  // Try IPv4 address format
  while (pos != string::npos)
  {
    client_token = (client_token<<8 |
        atoll(ip_addr.substr(old_pos, pos - old_pos).c_str()));
    old_pos = pos + 1;
    pos = ip_addr.find(".", old_pos);
  }
  client_token = (client_token<<8 |
    atoll(ip_addr.substr(old_pos).c_str()));

  return client_token;
}
<|endoftext|>


<commit_before>/** bidding_agent_ex.cc                                 -*- C++ -*-
    Rémi Attab, 22 Feb 2013
    Copyright (c) 2013 Datacratic.  All rights reserved.

    Example of a simple fixed-price bidding agent.

*/

#include "rtbkit/common/bids.h"
#include "rtbkit/core/banker/slave_banker.h"
#include "rtbkit/core/agent_configuration/agent_config.h"
#include "rtbkit/plugins/bidding_agent/bidding_agent.h"
#include "soa/service/service_utils.h"

#include <boost/program_options/cmdline.hpp>
#include <boost/program_options/options_description.hpp>
#include <boost/program_options/positional_options.hpp>
#include <boost/program_options/parsers.hpp>
#include <boost/program_options/variables_map.hpp>

#include <iostream>
#include <thread>
#include <chrono>
#include <string>     // std::string, std::to_string

using namespace std;
using namespace ML;

namespace RTBKIT {

/******************************************************************************/
/* FIXED PRICE BIDDING AGENT                                                  */
/******************************************************************************/

/** Simple bidding agent whose sole purpose in life is to bid 0.1$ CPM on every
    bid requests it sees. It also has a very simple pacer which ensures that we
    always have at most 1$ to spend every 10 seconds.

 */
struct FixedPriceBiddingAgent :
        public BiddingAgent
{
    FixedPriceBiddingAgent(
            std::shared_ptr<Datacratic::ServiceProxies> services,
            const string& serviceName) :
        BiddingAgent(services, serviceName),
        accountSetup(false)
    {}

    void init(const std::shared_ptr<ApplicationLayer> appLayer)
    {
        // We only want to specify a subset of the callbacks so turn the
        // annoying safety belt off.
        strictMode(false);

        onBidRequest = bind(
                &FixedPriceBiddingAgent::bid, this, _1, _2, _3, _4, _5, _6);

        // This component is used to speak with the master banker and pace the
        // rate at which we spend our budget.
        budgetController.setApplicationLayer(appLayer);
        budgetController.start();

        // Update our pacer every 10 seconds. Note that since this interacts
        // with the budgetController which is only synced up with the router
        // every few seconds, the wait period shouldn't be set too low.
        addPeriodic("FixedPriceBiddingAgent::pace", 10.0,
                [&] (uint64_t) { this->pace(); });

        BiddingAgent::init();

    }

    void start()
    {
        BiddingAgent::start();

        // Build our configuration and tell the world about it.
        setConfig();

    }

    void shutdown()
    {
        BiddingAgent::shutdown();

        budgetController.shutdown();
    }

    /** Sets up an agent configuration for our example. */
    void setConfig()
    {
        config = AgentConfig();

        // Accounts are used to control the allocation of spending budgets for
        // an agent. The whole mechanism is fully generic and can be setup in
        // whatever you feel it bests suits you.
        config.account = {"hello", "world"};

        // Specify the properties of the creatives we are trying to show.
        config.creatives.push_back(Creative::sampleLB);
        config.creatives.push_back(Creative::sampleWS);
        config.creatives.push_back(Creative::sampleBB);
        config.creatives.push_back(Creative::sampleAA);
        config.creatives.push_back(Creative::sampleCC);
        config.creatives.push_back(Creative::sampleDD);
        config.creatives.push_back(Creative::sampleRR);

    //    config.providerConfig["appodeal"]["seat"] = 12;
        config.providerConfig["appodeal"]["iurl"] = "http://www.gnu.org";

                for(auto & c: config.creatives){
                    c.providerConfig["appodeal"]["adm"] = "http://52.208.150.10:17340";
                    c.providerConfig["appodeal"]["nurl"] = "http://adserver.com/123456?winprice=${AUCTION_PRICE}&auction_id=%{bidrequest.id}&adspot_id=%{creative.id}";
                  }

        // Indicate to the router that we want our bid requests to be augmented
        // with our frequency cap augmentor example.
        {
            AugmentationConfig augConfig;

            // Name of the requested augmentor.
            augConfig.name = "frequency-cap-ex";

            // If the augmentor was unable to augment our bid request then it
            // should be filtered before it makes it to our agent.
            augConfig.required = true;

            // Config parameter sent used by the augmentor to determine which
            // tag to set.
            augConfig.config = Json::Value(112);

            // Instruct to router to filter out all bid requests who have not
            // been tagged by our frequency cap augmentor.
            augConfig.filters.include.push_back("pass-frequency-cap-ex");

            config.addAugmentation(augConfig);
        }

        // Configures the agent to only receive 10% of the bid request traffic
        // that matches its filters.
        config.bidProbability = 0.7;

        // Tell the world about our config. We can change the configuration of
        // an agent at any time by calling this function.
        doConfig(config);

    }

    /** Simple fixed price bidding strategy. Note that the router is in charge
        of making sure we stay within budget and don't go bankrupt.
    */
    void bid(
            double timestamp,
            const Id & id,
            std::shared_ptr<RTBKIT::BidRequest> br,
            Bids bids,
            double timeLeftMs,
            const Json::Value & augmentations)
    {

        for (Bid& bid : bids) {

            // In our example, all our creatives are of the different sizes so
            // there should only ever be one biddable creative. Note that that
            // the router won't ask for bids on imp that don't have any
            // biddable creatives.
            ExcAssertEqual(bid.availableCreatives.size(), 1);

            int availableCreative = bid.availableCreatives.front();

            // We don't really need it here but this is how you can get the
            // AdSpot and Creative object from the indexes.
            (void) br->imp[bid.spotIndex];

            (void) config.creatives[availableCreative];

            // Create a 0.0001$ CPM bid with our available creative.
            // Note that by default, the bid price is set to 0 which indicates
            // that we don't wish to bid on the given spot.
            bid.bid(availableCreative, MicroUSD(100));

        }

        // A value that will be passed back to us when we receive the result of
        // our bid.
        Json::Value metadata = 42;

        // Send our bid back to the agent.
        doBid(id, bids, metadata);

    }

    /** Simple pacing scheme which allocates 1$ to spend every period. */
    void pace()
    {
        // We need to register our account once with the banker service.
        if (!accountSetup) {
            accountSetup = true;
            budgetController.addAccountSync(config.account);
        }

        // Make sure we have 1$ to spend for the next period.
        budgetController.topupTransferSync(config.account, USD(1));
    }

    AgentConfig config;

    bool accountSetup;
    SlaveBudgetController budgetController;
};

} // namepsace RTBKIT

/******************************************************************************/
/* MAIN                                                                       */
/******************************************************************************/

int main(int argc, char** argv)
{
    using namespace boost::program_options;

    Datacratic::ServiceProxyArguments args;
    RTBKIT::SlaveBankerArguments bankerArgs;

    options_description options = args.makeProgramOptions();
    options.add_options()
        ("help,h", "Print this message");
    options.add(bankerArgs.makeProgramOptions());

    variables_map vm;
    store(command_line_parser(argc, argv).options(options).run(), vm);
    notify(vm);

    if (vm.count("help")) {
        cerr << options << endl;
        return 1;
    }

    auto serviceProxies = args.makeServiceProxies();
    RTBKIT::FixedPriceBiddingAgent agent(serviceProxies, "fixed-price-agent-ex");
    agent.init(bankerArgs.makeApplicationLayer(serviceProxies));
    agent.start();

    while (true) this_thread::sleep_for(chrono::seconds(10));

    // Won't ever reach this point but this is how you shutdown an agent.
    agent.shutdown();

    return 0;
}

<commit_msg>empty<commit_after>/** bidding_agent_ex.cc                                 -*- C++ -*-
    Rémi Attab, 22 Feb 2013
    Copyright (c) 2013 Datacratic.  All rights reserved.

    Example of a simple fixed-price bidding agent.

*/

#include "rtbkit/common/bids.h"
#include "rtbkit/core/banker/slave_banker.h"
#include "rtbkit/core/agent_configuration/agent_config.h"
#include "rtbkit/plugins/bidding_agent/bidding_agent.h"
#include "soa/service/service_utils.h"

#include <boost/program_options/cmdline.hpp>
#include <boost/program_options/options_description.hpp>
#include <boost/program_options/positional_options.hpp>
#include <boost/program_options/parsers.hpp>
#include <boost/program_options/variables_map.hpp>

#include <iostream>
#include <thread>
#include <chrono>
#include <string>     // std::string, std::to_string

using namespace std;
using namespace ML;

namespace RTBKIT {

/******************************************************************************/
/* FIXED PRICE BIDDING AGENT                                                  */
/******************************************************************************/

/** Simple bidding agent whose sole purpose in life is to bid 0.1$ CPM on every
    bid requests it sees. It also has a very simple pacer which ensures that we
    always have at most 1$ to spend every 10 seconds.

 */
struct FixedPriceBiddingAgent :
        public BiddingAgent
{
    FixedPriceBiddingAgent(
            std::shared_ptr<Datacratic::ServiceProxies> services,
            const string& serviceName) :
        BiddingAgent(services, serviceName),
        accountSetup(false)
    {}

    void init(const std::shared_ptr<ApplicationLayer> appLayer)
    {
        // We only want to specify a subset of the callbacks so turn the
        // annoying safety belt off.
        strictMode(false);

        onBidRequest = bind(
                &FixedPriceBiddingAgent::bid, this, _1, _2, _3, _4, _5, _6);

        // This component is used to speak with the master banker and pace the
        // rate at which we spend our budget.
        budgetController.setApplicationLayer(appLayer);
        budgetController.start();

        // Update our pacer every 10 seconds. Note that since this interacts
        // with the budgetController which is only synced up with the router
        // every few seconds, the wait period shouldn't be set too low.
        addPeriodic("FixedPriceBiddingAgent::pace", 10.0,
                [&] (uint64_t) { this->pace(); });

        BiddingAgent::init();

    }

    void start()
    {
        BiddingAgent::start();

        // Build our configuration and tell the world about it.
        setConfig();

    }

    void shutdown()
    {
        BiddingAgent::shutdown();

        budgetController.shutdown();
    }

    /** Sets up an agent configuration for our example. */
    void setConfig()
    {
        config = AgentConfig();

        // Accounts are used to control the allocation of spending budgets for
        // an agent. The whole mechanism is fully generic and can be setup in
        // whatever you feel it bests suits you.
        config.account = {"hello", "world"};

        // Specify the properties of the creatives we are trying to show.
        config.creatives.push_back(Creative::sampleLB);
        config.creatives.push_back(Creative::sampleWS);
        config.creatives.push_back(Creative::sampleBB);
        config.creatives.push_back(Creative::sampleAA);
        config.creatives.push_back(Creative::sampleCC);
        config.creatives.push_back(Creative::sampleDD);
        config.creatives.push_back(Creative::sampleRR);

    //    config.providerConfig["appodeal"]["seat"] = 12;
        config.providerConfig["appodeal"]["iurl"] = "http://www.gnu.org";

                for(auto & c: config.creatives){
                    c.providerConfig["appodeal"]["adm"] = "some_adm";
                    c.providerConfig["appodeal"]["nurl"] = "http://adserver.com/123456?winprice=${AUCTION_PRICE}&auction_id=%{bidrequest.id}&adspot_id=%{creative.id}";
                  }

        // Indicate to the router that we want our bid requests to be augmented
        // with our frequency cap augmentor example.
        {
            AugmentationConfig augConfig;

            // Name of the requested augmentor.
            augConfig.name = "frequency-cap-ex";

            // If the augmentor was unable to augment our bid request then it
            // should be filtered before it makes it to our agent.
            augConfig.required = true;

            // Config parameter sent used by the augmentor to determine which
            // tag to set.
            augConfig.config = Json::Value(112);

            // Instruct to router to filter out all bid requests who have not
            // been tagged by our frequency cap augmentor.
            augConfig.filters.include.push_back("pass-frequency-cap-ex");

            config.addAugmentation(augConfig);
        }

        // Configures the agent to only receive 10% of the bid request traffic
        // that matches its filters.
        config.bidProbability = 0.7;

        // Tell the world about our config. We can change the configuration of
        // an agent at any time by calling this function.
        doConfig(config);

    }

    /** Simple fixed price bidding strategy. Note that the router is in charge
        of making sure we stay within budget and don't go bankrupt.
    */
    void bid(
            double timestamp,
            const Id & id,
            std::shared_ptr<RTBKIT::BidRequest> br,
            Bids bids,
            double timeLeftMs,
            const Json::Value & augmentations)
    {

        for (Bid& bid : bids) {

            // In our example, all our creatives are of the different sizes so
            // there should only ever be one biddable creative. Note that that
            // the router won't ask for bids on imp that don't have any
            // biddable creatives.
            ExcAssertEqual(bid.availableCreatives.size(), 1);

            int availableCreative = bid.availableCreatives.front();

            // We don't really need it here but this is how you can get the
            // AdSpot and Creative object from the indexes.
            (void) br->imp[bid.spotIndex];

            (void) config.creatives[availableCreative];

            // Create a 0.0001$ CPM bid with our available creative.
            // Note that by default, the bid price is set to 0 which indicates
            // that we don't wish to bid on the given spot.
            bid.bid(availableCreative, MicroUSD(100));

        }

        // A value that will be passed back to us when we receive the result of
        // our bid.
        Json::Value metadata = 42;

        // Send our bid back to the agent.
        doBid(id, bids, metadata);

    }

    /** Simple pacing scheme which allocates 1$ to spend every period. */
    void pace()
    {
        // We need to register our account once with the banker service.
        if (!accountSetup) {
            accountSetup = true;
            budgetController.addAccountSync(config.account);
        }

        // Make sure we have 1$ to spend for the next period.
        budgetController.topupTransferSync(config.account, USD(1));
    }

    AgentConfig config;

    bool accountSetup;
    SlaveBudgetController budgetController;
};

} // namepsace RTBKIT

/******************************************************************************/
/* MAIN                                                                       */
/******************************************************************************/

int main(int argc, char** argv)
{
    using namespace boost::program_options;

    Datacratic::ServiceProxyArguments args;
    RTBKIT::SlaveBankerArguments bankerArgs;

    options_description options = args.makeProgramOptions();
    options.add_options()
        ("help,h", "Print this message");
    options.add(bankerArgs.makeProgramOptions());

    variables_map vm;
    store(command_line_parser(argc, argv).options(options).run(), vm);
    notify(vm);

    if (vm.count("help")) {
        cerr << options << endl;
        return 1;
    }

    auto serviceProxies = args.makeServiceProxies();
    RTBKIT::FixedPriceBiddingAgent agent(serviceProxies, "fixed-price-agent-ex");
    agent.init(bankerArgs.makeApplicationLayer(serviceProxies));
    agent.start();

    while (true) this_thread::sleep_for(chrono::seconds(10));

    // Won't ever reach this point but this is how you shutdown an agent.
    agent.shutdown();

    return 0;
}

<|endoftext|>