<commit_before>/*
*  Copyright (c) 2012 The WebM project authors. All Rights Reserved.
*
*  Use of this source code is governed by a BSD-style license
*  that can be found in the LICENSE file in the root of the source
*  tree. An additional intellectual property rights grant can be found
*  in the file PATENTS.  All contributing project authors may
*  be found in the AUTHORS file in the root of the source tree.
*/

#include <math.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>

extern "C" {
#include "vpx_rtcd.h"
}

#include "third_party/googletest/src/include/gtest/gtest.h"
#include "vpx/vpx_integer.h"
#include "vpx_mem/vpx_mem.h"
#include "vp8/encoder/onyx_int.h"

namespace {

const int cospi8sqrt2minus1 = 20091;
const int sinpi8sqrt2 = 35468;

void reference_idct4x4(const int16_t *input, int16_t *output) {
  const int16_t *ip = input;
  int16_t *op = output;

  for (int i = 0; i < 4; ++i) {
    const int a1 = ip[0] + ip[8];
    const int b1 = ip[0] - ip[8];
    const int temp1 = (ip[4] * sinpi8sqrt2) >> 16;
    const int temp2 = ip[12] + ((ip[12] * cospi8sqrt2minus1) >> 16);
    const int c1 = temp1 - temp2;
    const int temp3 = ip[4] + ((ip[4] * cospi8sqrt2minus1) >> 16);
    const int temp4 = (ip[12] * sinpi8sqrt2) >> 16;
    const int d1 = temp3 + temp4;
    op[0] = a1 + d1;
    op[12] = a1 - d1;
    op[4] = b1 + c1;
    op[8] = b1 - c1;
    ++ip;
    ++op;
  }
  ip = output;
  op = output;
  for (int i = 0; i < 4; ++i) {
    const int a1 = ip[0] + ip[2];
    const int b1 = ip[0] - ip[2];
    const int temp1 = (ip[1] * sinpi8sqrt2) >> 16;
    const int temp2 = ip[3] + ((ip[3] * cospi8sqrt2minus1) >> 16);
    const int c1 = temp1 - temp2;
    const int temp3 = ip[1] + ((ip[1] * cospi8sqrt2minus1) >> 16);
    const int temp4 = (ip[3] * sinpi8sqrt2) >> 16;
    const int d1 = temp3 + temp4;
    op[0] = (a1 + d1 + 4) >> 3;
    op[3] = (a1 - d1 + 4) >> 3;
    op[1] = (b1 + c1 + 4) >> 3;
    op[2] = (b1 - c1 + 4) >> 3;
    ip += 4;
    op += 4;
  }
}

// This is a class that generate random numbers for test input.
class ACMRandom {
public:
  explicit ACMRandom(int seed) { Reset(seed); }

  void Reset(int seed) { srand(seed); }

  uint8_t Rand8(void) { return (rand() >> 8) & 0xff; }

  int PseudoUniform(int range) { return (rand() >> 8) % range; }

  int operator()(int n) { return PseudoUniform(n); }

  static int DeterministicSeed(void) { return 0xbaba; }
};

TEST(Vp8FdctTest, SignBiasCheck) {
  ACMRandom rnd(ACMRandom::DeterministicSeed());
  int16_t test_input_block[16];
  int16_t test_output_block[16];
  const int pitch = 8;
  int count_sign_block[16][2];
  const int count_test_block = 1000000;

  memset(count_sign_block, 0, sizeof(count_sign_block));

  for (int i = 0; i < count_test_block; ++i) {
    // Initialize a test block with input range [-255, 255].
    for (int j = 0; j < 16; ++j)
      test_input_block[j] = rnd.Rand8() - rnd.Rand8();

    vp8_short_fdct4x4_c(test_input_block, test_output_block, pitch);

    for (int j = 0; j < 16; ++j) {
      if (test_output_block[j] < 0)
        ++count_sign_block[j][0];
      else if (test_output_block[j] > 0)
        ++count_sign_block[j][1];
    }
  }

  bool bias_acceptable = true;
  for (int j = 0; j < 16; ++j)
    bias_acceptable = bias_acceptable &&
    (abs(count_sign_block[j][0] - count_sign_block[j][1]) < 10000);

  EXPECT_EQ(true, bias_acceptable)
    << "Error: 4x4 FDCT has a sign bias > 1% for input range [-255, 255]";

  memset(count_sign_block, 0, sizeof(count_sign_block));

  for (int i = 0; i < count_test_block; ++i) {
    // Initialize a test block with input range [-15, 15].
    for (int j = 0; j < 16; ++j)
      test_input_block[j] = (rnd.Rand8() >> 4) - (rnd.Rand8() >> 4);

    vp8_short_fdct4x4_c(test_input_block, test_output_block, pitch);

    for (int j = 0; j < 16; ++j) {
      if (test_output_block[j] < 0)
        ++count_sign_block[j][0];
      else if (test_output_block[j] > 0)
        ++count_sign_block[j][1];
    }
  }

  bias_acceptable = true;
  for (int j = 0; j < 16; ++j)
    bias_acceptable = bias_acceptable &&
    (abs(count_sign_block[j][0] - count_sign_block[j][1]) < 100000);

  EXPECT_EQ(true, bias_acceptable)
    << "Error: 4x4 FDCT has a sign bias > 10% for input range [-15, 15]";
};

TEST(Vp8FdctTest, RoundTripErrorCheck) {
  ACMRandom rnd(ACMRandom::DeterministicSeed());
  int max_error = 0;
  double total_error = 0;
  const int count_test_block = 1000000;
  for (int i = 0; i < count_test_block; ++i) {
    int16_t test_input_block[16];
    int16_t test_temp_block[16];
    int16_t test_output_block[16];

    // Initialize a test block with input range [-255, 255].
    for (int j = 0; j < 16; ++j)
      test_input_block[j] = rnd.Rand8() - rnd.Rand8();

    const int pitch = 8;
    vp8_short_fdct4x4_c(test_input_block, test_temp_block, pitch);
    reference_idct4x4(test_temp_block, test_output_block);

    for (int j = 0; j < 16; ++j) {
      const int diff = test_input_block[j] - test_output_block[j];
      const int error = diff * diff;
      if (max_error < error)
        max_error = error;
      total_error += error;
    }
  }

  EXPECT_GE(1, max_error )
    << "Error: FDCT/IDCT has an individual roundtrip error > 1";

  EXPECT_GE(count_test_block, total_error)
    << "Error: FDCT/IDCT has average roundtrip error > 1 per block";
};

}  // namespace
<commit_msg>fdct4x4_test: remove unnecessary includes<commit_after>/*
*  Copyright (c) 2012 The WebM project authors. All Rights Reserved.
*
*  Use of this source code is governed by a BSD-style license
*  that can be found in the LICENSE file in the root of the source
*  tree. An additional intellectual property rights grant can be found
*  in the file PATENTS.  All contributing project authors may
*  be found in the AUTHORS file in the root of the source tree.
*/

#include <math.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>

extern "C" {
#include "vpx_rtcd.h"
}

#include "third_party/googletest/src/include/gtest/gtest.h"
#include "vpx/vpx_integer.h"

namespace {

const int cospi8sqrt2minus1 = 20091;
const int sinpi8sqrt2 = 35468;

void reference_idct4x4(const int16_t *input, int16_t *output) {
  const int16_t *ip = input;
  int16_t *op = output;

  for (int i = 0; i < 4; ++i) {
    const int a1 = ip[0] + ip[8];
    const int b1 = ip[0] - ip[8];
    const int temp1 = (ip[4] * sinpi8sqrt2) >> 16;
    const int temp2 = ip[12] + ((ip[12] * cospi8sqrt2minus1) >> 16);
    const int c1 = temp1 - temp2;
    const int temp3 = ip[4] + ((ip[4] * cospi8sqrt2minus1) >> 16);
    const int temp4 = (ip[12] * sinpi8sqrt2) >> 16;
    const int d1 = temp3 + temp4;
    op[0] = a1 + d1;
    op[12] = a1 - d1;
    op[4] = b1 + c1;
    op[8] = b1 - c1;
    ++ip;
    ++op;
  }
  ip = output;
  op = output;
  for (int i = 0; i < 4; ++i) {
    const int a1 = ip[0] + ip[2];
    const int b1 = ip[0] - ip[2];
    const int temp1 = (ip[1] * sinpi8sqrt2) >> 16;
    const int temp2 = ip[3] + ((ip[3] * cospi8sqrt2minus1) >> 16);
    const int c1 = temp1 - temp2;
    const int temp3 = ip[1] + ((ip[1] * cospi8sqrt2minus1) >> 16);
    const int temp4 = (ip[3] * sinpi8sqrt2) >> 16;
    const int d1 = temp3 + temp4;
    op[0] = (a1 + d1 + 4) >> 3;
    op[3] = (a1 - d1 + 4) >> 3;
    op[1] = (b1 + c1 + 4) >> 3;
    op[2] = (b1 - c1 + 4) >> 3;
    ip += 4;
    op += 4;
  }
}

// This is a class that generate random numbers for test input.
class ACMRandom {
public:
  explicit ACMRandom(int seed) { Reset(seed); }

  void Reset(int seed) { srand(seed); }

  uint8_t Rand8(void) { return (rand() >> 8) & 0xff; }

  int PseudoUniform(int range) { return (rand() >> 8) % range; }

  int operator()(int n) { return PseudoUniform(n); }

  static int DeterministicSeed(void) { return 0xbaba; }
};

TEST(Vp8FdctTest, SignBiasCheck) {
  ACMRandom rnd(ACMRandom::DeterministicSeed());
  int16_t test_input_block[16];
  int16_t test_output_block[16];
  const int pitch = 8;
  int count_sign_block[16][2];
  const int count_test_block = 1000000;

  memset(count_sign_block, 0, sizeof(count_sign_block));

  for (int i = 0; i < count_test_block; ++i) {
    // Initialize a test block with input range [-255, 255].
    for (int j = 0; j < 16; ++j)
      test_input_block[j] = rnd.Rand8() - rnd.Rand8();

    vp8_short_fdct4x4_c(test_input_block, test_output_block, pitch);

    for (int j = 0; j < 16; ++j) {
      if (test_output_block[j] < 0)
        ++count_sign_block[j][0];
      else if (test_output_block[j] > 0)
        ++count_sign_block[j][1];
    }
  }

  bool bias_acceptable = true;
  for (int j = 0; j < 16; ++j)
    bias_acceptable = bias_acceptable &&
    (abs(count_sign_block[j][0] - count_sign_block[j][1]) < 10000);

  EXPECT_EQ(true, bias_acceptable)
    << "Error: 4x4 FDCT has a sign bias > 1% for input range [-255, 255]";

  memset(count_sign_block, 0, sizeof(count_sign_block));

  for (int i = 0; i < count_test_block; ++i) {
    // Initialize a test block with input range [-15, 15].
    for (int j = 0; j < 16; ++j)
      test_input_block[j] = (rnd.Rand8() >> 4) - (rnd.Rand8() >> 4);

    vp8_short_fdct4x4_c(test_input_block, test_output_block, pitch);

    for (int j = 0; j < 16; ++j) {
      if (test_output_block[j] < 0)
        ++count_sign_block[j][0];
      else if (test_output_block[j] > 0)
        ++count_sign_block[j][1];
    }
  }

  bias_acceptable = true;
  for (int j = 0; j < 16; ++j)
    bias_acceptable = bias_acceptable &&
    (abs(count_sign_block[j][0] - count_sign_block[j][1]) < 100000);

  EXPECT_EQ(true, bias_acceptable)
    << "Error: 4x4 FDCT has a sign bias > 10% for input range [-15, 15]";
};

TEST(Vp8FdctTest, RoundTripErrorCheck) {
  ACMRandom rnd(ACMRandom::DeterministicSeed());
  int max_error = 0;
  double total_error = 0;
  const int count_test_block = 1000000;
  for (int i = 0; i < count_test_block; ++i) {
    int16_t test_input_block[16];
    int16_t test_temp_block[16];
    int16_t test_output_block[16];

    // Initialize a test block with input range [-255, 255].
    for (int j = 0; j < 16; ++j)
      test_input_block[j] = rnd.Rand8() - rnd.Rand8();

    const int pitch = 8;
    vp8_short_fdct4x4_c(test_input_block, test_temp_block, pitch);
    reference_idct4x4(test_temp_block, test_output_block);

    for (int j = 0; j < 16; ++j) {
      const int diff = test_input_block[j] - test_output_block[j];
      const int error = diff * diff;
      if (max_error < error)
        max_error = error;
      total_error += error;
    }
  }

  EXPECT_GE(1, max_error )
    << "Error: FDCT/IDCT has an individual roundtrip error > 1";

  EXPECT_GE(count_test_block, total_error)
    << "Error: FDCT/IDCT has average roundtrip error > 1 per block";
};

}  // namespace
<|endoftext|>


<commit_before>/*************************************************************************
 *
 * 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: vclxdevice.cxx,v $
 * $Revision: 1.7 $
 *
 * 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_toolkit.hxx"
#include <com/sun/star/awt/DeviceCapability.hpp>

#include <toolkit/awt/vclxdevice.hxx>
#include <toolkit/awt/vclxfont.hxx>
#include <toolkit/awt/vclxbitmap.hxx>
#include <toolkit/helper/vclunohelper.hxx>
#include <toolkit/helper/macros.hxx>
#include <cppuhelper/typeprovider.hxx>

#include <rtl/memory.h>
#include <rtl/uuid.h>

#include <vcl/svapp.hxx>
#include <vcl/outdev.hxx>
#include <vcl/window.hxx>
#include <vcl/print.hxx>
#include <vcl/virdev.hxx>
#include <vcl/bitmapex.hxx>
#include <vcl/font.hxx>

//  ----------------------------------------------------
//  class VCLXDevice
//  ----------------------------------------------------
VCLXDevice::VCLXDevice() : mrMutex( Application::GetSolarMutex() )
{
    mpOutputDevice = NULL;
    nFlags = 0;
}

VCLXDevice::~VCLXDevice()
{
// Was thought for #88347#, but didn't help, because the interface will not be released
// But would be a good idea anyway, check after 6.0, it's a little bit dangerous now
//    if( mpOutputDevice && IsCreatedWithToolkit() )
//    {
//        delete mpOutputDevice;
//    }
}

void VCLXDevice::DestroyOutputDevice()
{
    delete mpOutputDevice;
    mpOutputDevice = NULL;
}

void VCLXDevice::SetCreatedWithToolkit( sal_Bool bCreatedWithToolkit )
{
    if ( bCreatedWithToolkit )
        nFlags |= FLAGS_CREATEDWITHTOOLKIT;
    else
        nFlags &= ~FLAGS_CREATEDWITHTOOLKIT;
}

sal_Bool VCLXDevice::IsCreatedWithToolkit() const
{
    return ( nFlags & FLAGS_CREATEDWITHTOOLKIT ) != 0;
}

// ::com::sun::star::uno::XInterface
::com::sun::star::uno::Any VCLXDevice::queryInterface( const ::com::sun::star::uno::Type & rType ) throw(::com::sun::star::uno::RuntimeException)
{
    ::com::sun::star::uno::Any aRet = ::cppu::queryInterface( rType,
                                        SAL_STATIC_CAST( ::com::sun::star::awt::XDevice*, this ),
                                        SAL_STATIC_CAST( ::com::sun::star::lang::XUnoTunnel*, this ),
                                        SAL_STATIC_CAST( ::com::sun::star::lang::XTypeProvider*, this ) );
    return (aRet.hasValue() ? aRet : OWeakObject::queryInterface( rType ));
}

// ::com::sun::star::lang::XUnoTunnel
IMPL_XUNOTUNNEL( VCLXDevice )

// ::com::sun::star::lang::XTypeProvider
IMPL_XTYPEPROVIDER_START( VCLXDevice )
    getCppuType( ( ::com::sun::star::uno::Reference< ::com::sun::star::awt::XDevice>* ) NULL )
IMPL_XTYPEPROVIDER_END

// ::com::sun::star::awt::XDevice,
::com::sun::star::uno::Reference< ::com::sun::star::awt::XGraphics > VCLXDevice::createGraphics(  ) throw(::com::sun::star::uno::RuntimeException)
{
    ::vos::OGuard aGuard( GetMutex() );

    ::com::sun::star::uno::Reference< ::com::sun::star::awt::XGraphics > xRef;

    if ( mpOutputDevice )
        xRef = mpOutputDevice->CreateUnoGraphics();

    return xRef;
}

::com::sun::star::uno::Reference< ::com::sun::star::awt::XDevice > VCLXDevice::createDevice( sal_Int32 nWidth, sal_Int32 nHeight ) throw(::com::sun::star::uno::RuntimeException)
{
    ::vos::OGuard aGuard( GetMutex() );

    ::com::sun::star::uno::Reference< ::com::sun::star::awt::XDevice >  xRef;
    if ( GetOutputDevice() )
    {
        VCLXVirtualDevice* pVDev = new VCLXVirtualDevice;
        VirtualDevice* pVclVDev = new VirtualDevice( *GetOutputDevice() );
        pVclVDev->SetOutputSizePixel( Size( nWidth, nHeight ) );
        pVDev->SetVirtualDevice( pVclVDev );
        xRef = pVDev;
    }
    return xRef;
}

::com::sun::star::awt::DeviceInfo VCLXDevice::getInfo() throw(::com::sun::star::uno::RuntimeException)
{
    ::vos::OGuard aGuard( GetMutex() );

    ::com::sun::star::awt::DeviceInfo aInfo;

    if( mpOutputDevice )
    {
        Size aDevSz;
        OutDevType eDevType = mpOutputDevice->GetOutDevType();
        if ( eDevType == OUTDEV_WINDOW )
        {
            aDevSz = ((Window*)mpOutputDevice)->GetSizePixel();
            ((Window*)mpOutputDevice)->GetBorder( aInfo.LeftInset, aInfo.TopInset, aInfo.RightInset, aInfo.BottomInset );
        }
        else if ( eDevType == OUTDEV_PRINTER )
        {
            aDevSz = ((Printer*)mpOutputDevice)->GetPaperSizePixel();
            Size aOutSz = mpOutputDevice->GetOutputSizePixel();
            Point aOffset = ((Printer*)mpOutputDevice)->GetPageOffset();
            aInfo.LeftInset = aOffset.X();
            aInfo.TopInset = aOffset.Y();
            aInfo.RightInset = aDevSz.Width() - aOutSz.Width() - aOffset.X();
            aInfo.BottomInset = aDevSz.Height() - aOutSz.Height() - aOffset.Y();
        }
        else // VirtualDevice
        {
            aDevSz = mpOutputDevice->GetOutputSizePixel();
            aInfo.LeftInset = 0;
            aInfo.TopInset = 0;
            aInfo.RightInset = 0;
            aInfo.BottomInset = 0;
        }

        aInfo.Width = aDevSz.Width();
        aInfo.Height = aDevSz.Height();

        Size aTmpSz = mpOutputDevice->LogicToPixel( Size( 1000, 1000 ), MapMode( MAP_CM ) );
        aInfo.PixelPerMeterX = aTmpSz.Width()/10;
        aInfo.PixelPerMeterY = aTmpSz.Height()/10;

        aInfo.BitsPerPixel = mpOutputDevice->GetBitCount();

        aInfo.Capabilities = 0;
        if ( mpOutputDevice->GetOutDevType() != OUTDEV_PRINTER )
            aInfo.Capabilities = ::com::sun::star::awt::DeviceCapability::RASTEROPERATIONS|::com::sun::star::awt::DeviceCapability::GETBITS;
    }

    return aInfo;
}

::com::sun::star::uno::Sequence< ::com::sun::star::awt::FontDescriptor > VCLXDevice::getFontDescriptors(  ) throw(::com::sun::star::uno::RuntimeException)
{
    ::vos::OGuard aGuard( GetMutex() );

    ::com::sun::star::uno::Sequence< ::com::sun::star::awt::FontDescriptor> aFonts;
    if( mpOutputDevice )
    {
        int nFonts = mpOutputDevice->GetDevFontCount();
        if ( nFonts )
        {
            aFonts = ::com::sun::star::uno::Sequence< ::com::sun::star::awt::FontDescriptor>( nFonts );
            ::com::sun::star::awt::FontDescriptor* pFonts = aFonts.getArray();
            for ( int n = 0; n < nFonts; n++ )
                pFonts[n] = VCLUnoHelper::CreateFontDescriptor( mpOutputDevice->GetDevFont( n ) );
        }
    }
    return aFonts;
}

::com::sun::star::uno::Reference< ::com::sun::star::awt::XFont > VCLXDevice::getFont( const ::com::sun::star::awt::FontDescriptor& rDescriptor ) throw(::com::sun::star::uno::RuntimeException)
{
    ::vos::OGuard aGuard( GetMutex() );

    ::com::sun::star::uno::Reference< ::com::sun::star::awt::XFont >  xRef;
    if( mpOutputDevice )
    {
        VCLXFont* pMetric = new VCLXFont;
        pMetric->Init( *this, VCLUnoHelper::CreateFont( rDescriptor, mpOutputDevice->GetFont() ) );
        xRef = pMetric;
    }
    return xRef;
}

::com::sun::star::uno::Reference< ::com::sun::star::awt::XBitmap > VCLXDevice::createBitmap( sal_Int32 nX, sal_Int32 nY, sal_Int32 nWidth, sal_Int32 nHeight ) throw(::com::sun::star::uno::RuntimeException)
{
    ::vos::OGuard aGuard( GetMutex() );

    ::com::sun::star::uno::Reference< ::com::sun::star::awt::XBitmap >  xBmp;
    if( mpOutputDevice )
    {
        Bitmap aBmp = mpOutputDevice->GetBitmap( Point( nX, nY ), Size( nWidth, nHeight ) );

        VCLXBitmap* pBmp = new VCLXBitmap;
        pBmp->SetBitmap( BitmapEx( aBmp ) );
        xBmp = pBmp;
    }
    return xBmp;
}

::com::sun::star::uno::Reference< ::com::sun::star::awt::XDisplayBitmap > VCLXDevice::createDisplayBitmap( const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XBitmap >& rxBitmap ) throw(::com::sun::star::uno::RuntimeException)
{
    ::vos::OGuard aGuard( GetMutex() );

    BitmapEx aBmp = VCLUnoHelper::GetBitmap( rxBitmap );
    VCLXBitmap* pBmp = new VCLXBitmap;
    pBmp->SetBitmap( aBmp );
    ::com::sun::star::uno::Reference< ::com::sun::star::awt::XDisplayBitmap >  xDBmp = pBmp;
    return xDBmp;
}

VCLXVirtualDevice::~VCLXVirtualDevice()
{
    ::vos::OGuard aGuard( GetMutex() );

    DestroyOutputDevice();
}

<commit_msg>INTEGRATION: CWS rptwizard01 (1.6.190); FILE MERGED 2008/05/21 10:11:57 lla 1.6.190.3: RESYNC: (1.6-1.7); FILE MERGED 2008/03/14 14:00:22 lla 1.6.190.2: #i86925# cleanup 2008/03/14 13:47:16 lla 1.6.190.1: #i86925# Unit Converter<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: vclxdevice.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_toolkit.hxx"
#include <com/sun/star/awt/DeviceCapability.hpp>

#include <com/sun/star/util/MeasureUnit.hpp>

#include <toolkit/awt/vclxdevice.hxx>
#include <toolkit/awt/vclxfont.hxx>
#include <toolkit/awt/vclxbitmap.hxx>
#include <toolkit/helper/vclunohelper.hxx>
#include <toolkit/helper/macros.hxx>
#include <cppuhelper/typeprovider.hxx>

#include <rtl/memory.h>
#include <rtl/uuid.h>

#include <vcl/svapp.hxx>
#include <vcl/outdev.hxx>
#include <vcl/window.hxx>
#include <vcl/print.hxx>
#include <vcl/virdev.hxx>
#include <vcl/bitmapex.hxx>
#include <vcl/font.hxx>

//  ----------------------------------------------------
//  class VCLXDevice
//  ----------------------------------------------------
VCLXDevice::VCLXDevice() : mrMutex( Application::GetSolarMutex() )
{
    mpOutputDevice = NULL;
    nFlags = 0;
}

VCLXDevice::~VCLXDevice()
{
// Was thought for #88347#, but didn't help, because the interface will not be released
// But would be a good idea anyway, check after 6.0, it's a little bit dangerous now
//    if( mpOutputDevice && IsCreatedWithToolkit() )
//    {
//        delete mpOutputDevice;
//    }
}

void VCLXDevice::DestroyOutputDevice()
{
    delete mpOutputDevice;
    mpOutputDevice = NULL;
}

void VCLXDevice::SetCreatedWithToolkit( sal_Bool bCreatedWithToolkit )
{
    if ( bCreatedWithToolkit )
        nFlags |= FLAGS_CREATEDWITHTOOLKIT;
    else
        nFlags &= ~FLAGS_CREATEDWITHTOOLKIT;
}

sal_Bool VCLXDevice::IsCreatedWithToolkit() const
{
    return ( nFlags & FLAGS_CREATEDWITHTOOLKIT ) != 0;
}

// ::com::sun::star::uno::XInterface
::com::sun::star::uno::Any VCLXDevice::queryInterface( const ::com::sun::star::uno::Type & rType ) throw(::com::sun::star::uno::RuntimeException)
{
    ::com::sun::star::uno::Any aRet = ::cppu::queryInterface( rType,
                                        SAL_STATIC_CAST( ::com::sun::star::awt::XDevice*, this ),
                                        SAL_STATIC_CAST( ::com::sun::star::lang::XUnoTunnel*, this ),
                                        SAL_STATIC_CAST( ::com::sun::star::lang::XTypeProvider*, this ),
                                        SAL_STATIC_CAST( ::com::sun::star::awt::XUnitConversion*, this ) );
    return (aRet.hasValue() ? aRet : OWeakObject::queryInterface( rType ));
}

// ::com::sun::star::lang::XUnoTunnel
IMPL_XUNOTUNNEL( VCLXDevice )

// ::com::sun::star::lang::XTypeProvider
IMPL_XTYPEPROVIDER_START( VCLXDevice )
    getCppuType( ( ::com::sun::star::uno::Reference< ::com::sun::star::awt::XDevice>* ) NULL ),
    getCppuType( ( ::com::sun::star::uno::Reference< ::com::sun::star::awt::XUnitConversion>* ) NULL )
IMPL_XTYPEPROVIDER_END

// ::com::sun::star::awt::XDevice,
::com::sun::star::uno::Reference< ::com::sun::star::awt::XGraphics > VCLXDevice::createGraphics(  ) throw(::com::sun::star::uno::RuntimeException)
{
    ::vos::OGuard aGuard( GetMutex() );

    ::com::sun::star::uno::Reference< ::com::sun::star::awt::XGraphics > xRef;

    if ( mpOutputDevice )
        xRef = mpOutputDevice->CreateUnoGraphics();

    return xRef;
}

::com::sun::star::uno::Reference< ::com::sun::star::awt::XDevice > VCLXDevice::createDevice( sal_Int32 nWidth, sal_Int32 nHeight ) throw(::com::sun::star::uno::RuntimeException)
{
    ::vos::OGuard aGuard( GetMutex() );

    ::com::sun::star::uno::Reference< ::com::sun::star::awt::XDevice >  xRef;
    if ( GetOutputDevice() )
    {
        VCLXVirtualDevice* pVDev = new VCLXVirtualDevice;
        VirtualDevice* pVclVDev = new VirtualDevice( *GetOutputDevice() );
        pVclVDev->SetOutputSizePixel( Size( nWidth, nHeight ) );
        pVDev->SetVirtualDevice( pVclVDev );
        xRef = pVDev;
    }
    return xRef;
}

::com::sun::star::awt::DeviceInfo VCLXDevice::getInfo() throw(::com::sun::star::uno::RuntimeException)
{
    ::vos::OGuard aGuard( GetMutex() );

    ::com::sun::star::awt::DeviceInfo aInfo;

    if( mpOutputDevice )
    {
        Size aDevSz;
        OutDevType eDevType = mpOutputDevice->GetOutDevType();
        if ( eDevType == OUTDEV_WINDOW )
        {
            aDevSz = ((Window*)mpOutputDevice)->GetSizePixel();
            ((Window*)mpOutputDevice)->GetBorder( aInfo.LeftInset, aInfo.TopInset, aInfo.RightInset, aInfo.BottomInset );
        }
        else if ( eDevType == OUTDEV_PRINTER )
        {
            aDevSz = ((Printer*)mpOutputDevice)->GetPaperSizePixel();
            Size aOutSz = mpOutputDevice->GetOutputSizePixel();
            Point aOffset = ((Printer*)mpOutputDevice)->GetPageOffset();
            aInfo.LeftInset = aOffset.X();
            aInfo.TopInset = aOffset.Y();
            aInfo.RightInset = aDevSz.Width() - aOutSz.Width() - aOffset.X();
            aInfo.BottomInset = aDevSz.Height() - aOutSz.Height() - aOffset.Y();
        }
        else // VirtualDevice
        {
            aDevSz = mpOutputDevice->GetOutputSizePixel();
            aInfo.LeftInset = 0;
            aInfo.TopInset = 0;
            aInfo.RightInset = 0;
            aInfo.BottomInset = 0;
        }

        aInfo.Width = aDevSz.Width();
        aInfo.Height = aDevSz.Height();

        Size aTmpSz = mpOutputDevice->LogicToPixel( Size( 1000, 1000 ), MapMode( MAP_CM ) );
        aInfo.PixelPerMeterX = aTmpSz.Width()/10;
        aInfo.PixelPerMeterY = aTmpSz.Height()/10;

        aInfo.BitsPerPixel = mpOutputDevice->GetBitCount();

        aInfo.Capabilities = 0;
        if ( mpOutputDevice->GetOutDevType() != OUTDEV_PRINTER )
            aInfo.Capabilities = ::com::sun::star::awt::DeviceCapability::RASTEROPERATIONS|::com::sun::star::awt::DeviceCapability::GETBITS;
    }

    return aInfo;
}

::com::sun::star::uno::Sequence< ::com::sun::star::awt::FontDescriptor > VCLXDevice::getFontDescriptors(  ) throw(::com::sun::star::uno::RuntimeException)
{
    ::vos::OGuard aGuard( GetMutex() );

    ::com::sun::star::uno::Sequence< ::com::sun::star::awt::FontDescriptor> aFonts;
    if( mpOutputDevice )
    {
        int nFonts = mpOutputDevice->GetDevFontCount();
        if ( nFonts )
        {
            aFonts = ::com::sun::star::uno::Sequence< ::com::sun::star::awt::FontDescriptor>( nFonts );
            ::com::sun::star::awt::FontDescriptor* pFonts = aFonts.getArray();
            for ( int n = 0; n < nFonts; n++ )
                pFonts[n] = VCLUnoHelper::CreateFontDescriptor( mpOutputDevice->GetDevFont( n ) );
        }
    }
    return aFonts;
}

::com::sun::star::uno::Reference< ::com::sun::star::awt::XFont > VCLXDevice::getFont( const ::com::sun::star::awt::FontDescriptor& rDescriptor ) throw(::com::sun::star::uno::RuntimeException)
{
    ::vos::OGuard aGuard( GetMutex() );

    ::com::sun::star::uno::Reference< ::com::sun::star::awt::XFont >  xRef;
    if( mpOutputDevice )
    {
        VCLXFont* pMetric = new VCLXFont;
        pMetric->Init( *this, VCLUnoHelper::CreateFont( rDescriptor, mpOutputDevice->GetFont() ) );
        xRef = pMetric;
    }
    return xRef;
}

::com::sun::star::uno::Reference< ::com::sun::star::awt::XBitmap > VCLXDevice::createBitmap( sal_Int32 nX, sal_Int32 nY, sal_Int32 nWidth, sal_Int32 nHeight ) throw(::com::sun::star::uno::RuntimeException)
{
    ::vos::OGuard aGuard( GetMutex() );

    ::com::sun::star::uno::Reference< ::com::sun::star::awt::XBitmap >  xBmp;
    if( mpOutputDevice )
    {
        Bitmap aBmp = mpOutputDevice->GetBitmap( Point( nX, nY ), Size( nWidth, nHeight ) );

        VCLXBitmap* pBmp = new VCLXBitmap;
        pBmp->SetBitmap( BitmapEx( aBmp ) );
        xBmp = pBmp;
    }
    return xBmp;
}

::com::sun::star::uno::Reference< ::com::sun::star::awt::XDisplayBitmap > VCLXDevice::createDisplayBitmap( const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XBitmap >& rxBitmap ) throw(::com::sun::star::uno::RuntimeException)
{
    ::vos::OGuard aGuard( GetMutex() );

    BitmapEx aBmp = VCLUnoHelper::GetBitmap( rxBitmap );
    VCLXBitmap* pBmp = new VCLXBitmap;
    pBmp->SetBitmap( aBmp );
    ::com::sun::star::uno::Reference< ::com::sun::star::awt::XDisplayBitmap >  xDBmp = pBmp;
    return xDBmp;
}

VCLXVirtualDevice::~VCLXVirtualDevice()
{
    ::vos::OGuard aGuard( GetMutex() );

    DestroyOutputDevice();
}

// -----------------------------------------------------------------------------
// ::com::sun::star::awt::XTextConstraints
// -----------------------------------------------------------------------------
// ::sal_Int32 SAL_CALL VCLXDevice::getTextWidth( const ::rtl::OUString& Text ) throw (::com::sun::star::uno::RuntimeException)
// {
//  ::vos::OGuard aGuard( GetMutex() );
//     if (Text.getLength() == 0)
//     {
//         return 0;
//     }
//
//     return 1;
// }
//
// ::sal_Int32 SAL_CALL VCLXDevice::getTextHeight(  ) throw (::com::sun::star::uno::RuntimeException)
// {
//  ::vos::OGuard aGuard( GetMutex() );
//     return 1;
// }

// -----------------------------------------------------------------------------
// ::com::sun::star::awt::XUnitConversion
// -----------------------------------------------------------------------------

::com::sun::star::awt::Point SAL_CALL VCLXDevice::convertPointToLogic( const ::com::sun::star::awt::Point& aPoint, ::sal_Int16 TargetUnit ) throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException)
{
    (void)aPoint;
    ::vos::OGuard aGuard( GetMutex() );
    if (TargetUnit == com::sun::star::util::MeasureUnit::PERCENT ||
        TargetUnit == com::sun::star::util::MeasureUnit::PIXEL)
    {
        // pixel or percentage not allowed here
        throw ::com::sun::star::lang::IllegalArgumentException();
    }

    ::com::sun::star::awt::Point aAWTPoint(0,0);
    // X,Y

    if( mpOutputDevice )
    {
        MapMode aMode(VCLUnoHelper::ConvertToMapModeUnit(TargetUnit));
        ::Point aVCLPoint = VCLUnoHelper::ConvertToVCLPoint(aPoint);
        ::Point aDevPoint = mpOutputDevice->PixelToLogic(aVCLPoint, aMode );
        aAWTPoint = VCLUnoHelper::ConvertToAWTPoint(aDevPoint);
    }

    return aAWTPoint;
}

::com::sun::star::awt::Point SAL_CALL VCLXDevice::convertPointToPixel( const ::com::sun::star::awt::Point& aPoint, ::sal_Int16 SourceUnit ) throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException)
{
    (void)aPoint;
    ::vos::OGuard aGuard( GetMutex() );
    if (SourceUnit == com::sun::star::util::MeasureUnit::PERCENT ||
        SourceUnit == com::sun::star::util::MeasureUnit::PIXEL)
    {
        // pixel or percentage not allowed here
        throw ::com::sun::star::lang::IllegalArgumentException();
    }

    ::com::sun::star::awt::Point aAWTPoint(0,0);

    if( mpOutputDevice )
    {
        MapMode aMode(VCLUnoHelper::ConvertToMapModeUnit(SourceUnit));
        ::Point aVCLPoint = VCLUnoHelper::ConvertToVCLPoint(aPoint);
        ::Point aDevPoint = mpOutputDevice->LogicToPixel(aVCLPoint, aMode );
        aAWTPoint = VCLUnoHelper::ConvertToAWTPoint(aDevPoint);
    }

    return aAWTPoint;
}

::com::sun::star::awt::Size SAL_CALL VCLXDevice::convertSizeToLogic( const ::com::sun::star::awt::Size& aSize, ::sal_Int16 TargetUnit ) throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException)
{
    (void)aSize;
    ::vos::OGuard aGuard( GetMutex() );
    if (TargetUnit == com::sun::star::util::MeasureUnit::PERCENT ||
        TargetUnit == com::sun::star::util::MeasureUnit::PIXEL)
    {
        // pixel or percentage not allowed here
        throw ::com::sun::star::lang::IllegalArgumentException();
    }

    ::com::sun::star::awt::Size aAWTSize(0,0);
    // Width, Height

    if( mpOutputDevice )
    {
        MapMode aMode(VCLUnoHelper::ConvertToMapModeUnit(TargetUnit));
        ::Size aVCLSize = VCLUnoHelper::ConvertToVCLSize(aSize);
        ::Size aDevSz = mpOutputDevice->PixelToLogic(aVCLSize, aMode );
        aAWTSize = VCLUnoHelper::ConvertToAWTSize(aDevSz);
    }

    return aAWTSize;
}

::com::sun::star::awt::Size SAL_CALL VCLXDevice::convertSizeToPixel( const ::com::sun::star::awt::Size& aSize, ::sal_Int16 SourceUnit ) throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException)
{
    (void)aSize;
    ::vos::OGuard aGuard( GetMutex() );
    if (SourceUnit == com::sun::star::util::MeasureUnit::PERCENT ||
        SourceUnit == com::sun::star::util::MeasureUnit::PIXEL)
    {
        // pixel or percentage not allowed here
        throw ::com::sun::star::lang::IllegalArgumentException();
    }

    ::com::sun::star::awt::Size aAWTSize(0,0);
    // Width, Height
    if( mpOutputDevice )
    {
        MapMode aMode(VCLUnoHelper::ConvertToMapModeUnit(SourceUnit));
        ::Size aVCLSize = VCLUnoHelper::ConvertToVCLSize(aSize);
        ::Size aDevSz = mpOutputDevice->LogicToPixel(aVCLSize, aMode );
        aAWTSize = VCLUnoHelper::ConvertToAWTSize(aDevSz);
    }

    return aAWTSize;
}

<|endoftext|>


<commit_before>// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/test/ui/ui_test.h"

#include "base/command_line.h"
#include "base/file_path.h"
#include "base/file_util.h"
#include "net/base/net_util.h"

typedef UITest ChromeMainTest;

// Launch the app, then close the app.
TEST_F(ChromeMainTest, AppLaunch) {
  // If we make it here at all, we've succeeded in retrieving the app window
  // in UITest::SetUp()--otherwise we'd fail with an exception in SetUp().

  if (UITest::in_process_renderer()) {
    EXPECT_EQ(1, UITest::GetBrowserProcessCount());
  } else {
    // We should have two instances of the browser process alive -
    // one is the Browser and the other is the Renderer.
    EXPECT_EQ(2, UITest::GetBrowserProcessCount());
  }
}

// Make sure that the testing interface is there and giving reasonable answers.
TEST_F(ChromeMainTest, AppTestingInterface) {
  int window_count = 0;
  EXPECT_TRUE(automation()->GetBrowserWindowCount(&window_count));
  EXPECT_EQ(1, window_count);

  EXPECT_EQ(1, GetTabCount());
}

// Make sure that the second invocation creates a new window.
// This test is disabled. See bug 5671.
TEST_F(ChromeMainTest, DISABLED_SecondLaunch) {
  include_testing_id_ = false;
  use_existing_browser_ = true;

  LaunchBrowser(CommandLine(L""), false);

  int window_count;
  ASSERT_TRUE(automation()->WaitForWindowCountToChange(1, &window_count,
                                                       action_timeout_ms()));
  ASSERT_EQ(2, window_count);
}

TEST_F(ChromeMainTest, ReuseBrowserInstanceWhenOpeningFile) {
  include_testing_id_ = false;
  use_existing_browser_ = true;

  std::wstring test_file = test_data_directory_;
  file_util::AppendToPath(&test_file, L"empty.html");

  CommandLine command_line(L"");
  command_line.AppendLooseValue(test_file);

  LaunchBrowser(command_line, false);

  FilePath test_file_path(FilePath::FromWStringHack(test_file));

  ASSERT_TRUE(automation()->WaitForURLDisplayed(
      net::FilePathToFileURL(test_file_path), action_timeout_ms()));
}
<commit_msg>Make SecondLaunch UI test not-flaky by using more reliable automation calls.<commit_after>// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/test/ui/ui_test.h"

#include "base/command_line.h"
#include "base/file_path.h"
#include "base/file_util.h"
#include "net/base/net_util.h"

typedef UITest ChromeMainTest;

// Launch the app, then close the app.
TEST_F(ChromeMainTest, AppLaunch) {
  // If we make it here at all, we've succeeded in retrieving the app window
  // in UITest::SetUp()--otherwise we'd fail with an exception in SetUp().

  if (UITest::in_process_renderer()) {
    EXPECT_EQ(1, UITest::GetBrowserProcessCount());
  } else {
    // We should have two instances of the browser process alive -
    // one is the Browser and the other is the Renderer.
    EXPECT_EQ(2, UITest::GetBrowserProcessCount());
  }
}

// Make sure that the testing interface is there and giving reasonable answers.
TEST_F(ChromeMainTest, AppTestingInterface) {
  int window_count = 0;
  EXPECT_TRUE(automation()->GetBrowserWindowCount(&window_count));
  EXPECT_EQ(1, window_count);

  EXPECT_EQ(1, GetTabCount());
}

// Make sure that the second invocation creates a new window.
TEST_F(ChromeMainTest, SecondLaunch) {
  include_testing_id_ = false;
  use_existing_browser_ = true;

  LaunchBrowser(CommandLine(L""), false);

  ASSERT_TRUE(automation()->WaitForWindowCountToBecome(2, action_timeout_ms()));
}

TEST_F(ChromeMainTest, ReuseBrowserInstanceWhenOpeningFile) {
  include_testing_id_ = false;
  use_existing_browser_ = true;

  std::wstring test_file = test_data_directory_;
  file_util::AppendToPath(&test_file, L"empty.html");

  CommandLine command_line(L"");
  command_line.AppendLooseValue(test_file);

  LaunchBrowser(command_line, false);

  FilePath test_file_path(FilePath::FromWStringHack(test_file));

  ASSERT_TRUE(automation()->WaitForURLDisplayed(
      net::FilePathToFileURL(test_file_path), action_timeout_ms()));
}
<|endoftext|>


<commit_before>// Copyright 2010-2013 RethinkDB, all rights reserved.
#include "errors.hpp"
#include <boost/bind.hpp>

#include "arch/arch.hpp"
#include "serializer/log/log_serializer.hpp"

namespace stress {
    #include "../stress-client/utils.hpp"
    #include "../stress-client/utils.cc"
    #include "../stress-client/random.cc"
}

class timer_token_t;

struct txn_info_t {
    ticks_t start, end;
};

typedef std::deque<txn_info_t> log_t;

struct txn_callback_t {
    virtual void on_transaction_complete() = 0;
} *cb;

void transact(serializer_t *ser, log_t *log, unsigned inserts, unsigned updates, txn_callback_t *cb) {
    /* If there aren't enough blocks to update, then convert the updates into inserts */
    std::vector<serializer_write_t> writes;

    if (updates > ser->max_block_id()) {
        inserts += updates;
        updates = 0;
    }

    /* To save CPU time (from clearing many bufs) we malloc() one buf and clear it and then
    write all the blocks from that one. I hope this doesn't bias the test. */

    void *dummy_buf = ser->malloc();
    memset(dummy_buf, 0xDB, ser->get_block_size().value());

    writes.reserve(updates + inserts);

    /* As a simple way to avoid updating the same block twice in one transaction, select
    a contiguous range of blocks starting at a random offset within range */

    block_id_t begin = stress::random(0, ser->max_block_id() - updates);

    // We just need some value for this.
    repli_timestamp_t tstamp = repli_timestamp_t::distant_past;
    for (unsigned i = 0; i < updates; i++) {
        writes.push_back(serializer_write_t::make_update(begin + i, tstamp, dummy_buf));
    }

    /* Generate new IDs to insert by simply taking (highest ID + 1) */
    for (unsigned i = 0; i < inserts; i++) {
        writes.push_back(serializer_write_t::make_update(ser->max_block_id() + i, tstamp, dummy_buf));
    }

    do_writes(ser, writes, DEFAULT_DISK_ACCOUNT);

    ser->free(dummy_buf);

    cb->on_transaction_complete();
}

#define RUN_FOREVER (-1)

struct config_t {
    const char *log_file, *tps_log_file;
    log_serializer_static_config_t ser_static_config;
    log_serializer_dynamic_config_t ser_dynamic_config;
    std::string db_filename;
    int duration;   /* Seconds */
    unsigned concurrent_txns;
    unsigned inserts_per_txn, updates_per_txn;
};

struct tester_t :
    public thread_message_t,
    public txn_callback_t
{
    log_t *log;
    FILE *tps_log_fd;
    log_serializer_t *ser;
    unsigned active_txns, total_txns;
    config_t *config;
    thread_pool_t *pool;
    bool stop, interrupted;
    timer_token_t *timer;
    ticks_t last_time;
    unsigned txns_last_sec;
    unsigned secs_so_far;
    scoped_ptr_t<io_backender_t> io_backender;

    struct interrupt_msg_t :
        public thread_message_t
    {
        tester_t *tester;
        interrupt_msg_t(tester_t *tester) : tester(tester) { }
        void on_thread_switch() {
            fprintf(stderr, "Interrupted.\n");
            tester->stop_test();
            cancel_timer(tester->timer);
        }
    } interruptor;

    tester_t(config_t *config, thread_pool_t *pool)
        : tps_log_fd(NULL), ser(NULL), active_txns(0), total_txns(0), config(config),
          pool(pool), stop(false), interrupted(false), last_time(0), txns_last_sec(0),
          secs_so_far(0), io_backender(new pool_io_backender_t), interruptor(this) {
        last_time = get_ticks();
        if(config->tps_log_file) {
            tps_log_fd = fopen(config->tps_log_file, "a");
        }
    }

    /* When on_thread_switch() is called, it could either be the start message telling us to run the
    test or the shutdown message from call_later_on_this_thread(). We differentiate by checking 'ser'. */
    void on_thread_switch() {
        if (!ser) coro_t::spawn(boost::bind(&tester_t::start, this));
        else coro_t::spawn(boost::bind(&tester_t::shutdown, this));
    }

    void start() {
        if (config->log_file) {
            log = new log_t();
        } else {
            log = NULL;
        }

        fprintf(stderr, "Creating a database...\n");
        filepath_file_opener_t file_opener(config->db_filename, io_backender.get());
        log_serializer_t::create(&file_opener,
                                 config->ser_static_config);

        fprintf(stderr, "Starting serializer...\n");
        ser = new log_serializer_t(config->ser_dynamic_config,
                                   &file_opener,
                                   &get_global_perfmon_collection());
        on_serializer_ready(ser);
    }

    void on_serializer_ready(log_serializer_t *ls) {
        fprintf(stderr, "Running test...\n");
        if(config->duration != RUN_FOREVER) {
            timer = fire_timer_once(config->duration * 1000, &tester_t::on_timer, this);
        }

        linux_thread_message_t *prev_interrupt_message = pool->set_interrupt_message(&interruptor);
        guarantee(prev_interrupt_message == NULL);

        pump();
    }

    static void on_timer(void *self) {
        tester_t *tester = (tester_t *)self;
        fprintf(stderr, "Time's up.\n");
        tester->stop_test();
    }

    void pump() {
        while (active_txns < config->concurrent_txns && !stop) {
            active_txns++;
            total_txns++;
            coro_t::spawn_sometime(boost::bind(transact, ser, log, config->inserts_per_txn, config->updates_per_txn, this));
        }

        // See if we need to report the TPS
        ticks_t cur_time = get_ticks();
        if(ticks_to_secs(cur_time - last_time) >= 1.0f) {
            if(tps_log_fd) {
                fprintf(tps_log_fd, "%d\n", txns_last_sec);
            }

            last_time = cur_time;
            txns_last_sec = 0;
            secs_so_far++;

            // Flush every five seconds in case of a crash
            if(secs_so_far % 5 == 0) {
                fflush(tps_log_fd);
            }
        }

        if (active_txns == 0 && stop) {
            /* Serializer doesn't like shutdown() to be called from within
               on_serializer_write_txn() */
            call_later_on_this_thread(this);
        }
    }

    void stop_test() {

        if (stop) return;
        linux_thread_message_t *prev_interrupt_message = pool->set_interrupt_message(NULL);
        guarantee(prev_interrupt_message == &interruptor);

        fprintf(stderr, "Started %d transactions and completed %d of them\n",
            total_txns, total_txns - active_txns);

        if (tps_log_fd)
            fclose(tps_log_fd);

        if (config->log_file) {
            FILE *log_file = fopen(config->log_file, "w");
            log_t::iterator it;
            for (it = log->begin(); it != log->end(); it++) {
                fprintf(log_file, "%.6f %.6f\n", ticks_to_secs(it->start), ticks_to_secs(it->end));
            }
            fclose(log_file);
            fprintf(stderr, "Wrote log to '%s'\n", config->log_file);
            delete(log);
        }

        stop = true;
        if (active_txns > 0) {
            fprintf(stderr, "Waiting for the remaining %d transactions...\n", active_txns);
        }
    }

    void on_transaction_complete() {
        active_txns--;
        txns_last_sec++;
        pump();
    }

    void shutdown() {
        fprintf(stderr, "Waiting for serializer to shut down...\n");
        delete ser;
        on_serializer_shutdown();
    }

    void on_serializer_shutdown() {
        fprintf(stderr, "Done.\n");
        pool->shutdown_thread_pool();
    }
};

const char *read_arg(int &argc, char **&argv) {
    if (argc == 0) {
        fail_due_to_user_error("Expected another argument at the end.");
    } else {
        argc--;
        return (argv++)[0];
    }
}

void parse_config(int argc, char *argv[], config_t *config) {

    config->db_filename = "rethinkdb_data";
    config->log_file = NULL;
    config->tps_log_file = NULL;

    // config->ser_static_config uses its own defaults from constructor
    // config->ser_dynamic_config uses its own defaults from constructor

    config->duration = 10;   /* Seconds */
    config->concurrent_txns = 8;
    config->inserts_per_txn = 10;
    config->updates_per_txn = 2;

    read_arg(argc, argv);

    while (argc) {
        const char *flag = read_arg(argc, argv);

        if (strcmp(flag, "-f") == 0) {
            config->db_filename = read_arg(argc, argv);
        } else if (strcmp(flag, "--log") == 0) {
            config->log_file = read_arg(argc, argv);
        } else if (strcmp(flag, "--tps-log") == 0) {
            config->tps_log_file = read_arg(argc, argv);
        } else if (strcmp(flag, "--block-size") == 0) {
            config->ser_static_config.block_size_ = atoi(read_arg(argc, argv));
        } else if (strcmp(flag, "--extent-size") == 0) {
            config->ser_static_config.extent_size_ = atoi(read_arg(argc, argv));
        } else if (strcmp(flag, "--active-data-extents") == 0) {
            config->ser_dynamic_config.num_active_data_extents = atoi(read_arg(argc, argv));
        } else if (strcmp(flag, "--file-zone-size") == 0) {
            config->ser_dynamic_config.file_zone_size = atoi(read_arg(argc, argv));

        } else if (strcmp(flag, "--duration") == 0) {
            config->duration = atoi(read_arg(argc, argv));
        } else if (strcmp(flag, "--forever") == 0) {
            config->duration = RUN_FOREVER;
        } else if (strcmp(flag, "--concurrent") == 0) {
            config->concurrent_txns = atoi(read_arg(argc, argv));
        } else if (strcmp(flag, "--inserts-per-txn") == 0) {
            config->inserts_per_txn = atoi(read_arg(argc, argv));
        } else if (strcmp(flag, "--updates-per-txn") == 0) {
            config->updates_per_txn = atoi(read_arg(argc, argv));

        } else {
            fail_due_to_user_error("Don't know how to handle \"%s\"", flag);
        }
    }

    rassert(config->ser_static_config.block_size().ser_value() > 0);
    rassert(config->ser_static_config.extent_size() > 0);
    rassert(config->ser_dynamic_config.num_active_data_extents > 0);
    rassert(config->ser_dynamic_config.file_zone_size > 0);
    rassert(config->duration > 0 || config->duration == RUN_FOREVER);
    rassert(config->concurrent_txns > 0);
}

int main(int argc, char *argv[]) {

    config_t config;
    parse_config(argc, argv, &config);

    thread_pool_t thread_pool(1, true);
    tester_t tester(&config, &thread_pool);
    thread_pool.run_thread_pool(&tester);

    return 0;
}
<commit_msg>Made serializer-bench not use pool_io_backender_t.<commit_after>// Copyright 2010-2013 RethinkDB, all rights reserved.
#include "errors.hpp"
#include <boost/bind.hpp>

#include "arch/arch.hpp"
#include "serializer/log/log_serializer.hpp"

namespace stress {
    #include "../stress-client/utils.hpp"
    #include "../stress-client/utils.cc"
    #include "../stress-client/random.cc"
}

class timer_token_t;

struct txn_info_t {
    ticks_t start, end;
};

typedef std::deque<txn_info_t> log_t;

struct txn_callback_t {
    virtual void on_transaction_complete() = 0;
} *cb;

void transact(serializer_t *ser, log_t *log, unsigned inserts, unsigned updates, txn_callback_t *cb) {
    /* If there aren't enough blocks to update, then convert the updates into inserts */
    std::vector<serializer_write_t> writes;

    if (updates > ser->max_block_id()) {
        inserts += updates;
        updates = 0;
    }

    /* To save CPU time (from clearing many bufs) we malloc() one buf and clear it and then
    write all the blocks from that one. I hope this doesn't bias the test. */

    void *dummy_buf = ser->malloc();
    memset(dummy_buf, 0xDB, ser->get_block_size().value());

    writes.reserve(updates + inserts);

    /* As a simple way to avoid updating the same block twice in one transaction, select
    a contiguous range of blocks starting at a random offset within range */

    block_id_t begin = stress::random(0, ser->max_block_id() - updates);

    // We just need some value for this.
    repli_timestamp_t tstamp = repli_timestamp_t::distant_past;
    for (unsigned i = 0; i < updates; i++) {
        writes.push_back(serializer_write_t::make_update(begin + i, tstamp, dummy_buf));
    }

    /* Generate new IDs to insert by simply taking (highest ID + 1) */
    for (unsigned i = 0; i < inserts; i++) {
        writes.push_back(serializer_write_t::make_update(ser->max_block_id() + i, tstamp, dummy_buf));
    }

    do_writes(ser, writes, DEFAULT_DISK_ACCOUNT);

    ser->free(dummy_buf);

    cb->on_transaction_complete();
}

#define RUN_FOREVER (-1)

struct config_t {
    const char *log_file, *tps_log_file;
    log_serializer_static_config_t ser_static_config;
    log_serializer_dynamic_config_t ser_dynamic_config;
    std::string db_filename;
    int duration;   /* Seconds */
    unsigned concurrent_txns;
    unsigned inserts_per_txn, updates_per_txn;
};

struct tester_t :
    public thread_message_t,
    public txn_callback_t
{
    log_t *log;
    FILE *tps_log_fd;
    log_serializer_t *ser;
    unsigned active_txns, total_txns;
    config_t *config;
    thread_pool_t *pool;
    bool stop, interrupted;
    timer_token_t *timer;
    ticks_t last_time;
    unsigned txns_last_sec;
    unsigned secs_so_far;
    scoped_ptr_t<io_backender_t> io_backender;

    struct interrupt_msg_t :
        public thread_message_t
    {
        tester_t *tester;
        interrupt_msg_t(tester_t *tester) : tester(tester) { }
        void on_thread_switch() {
            fprintf(stderr, "Interrupted.\n");
            tester->stop_test();
            cancel_timer(tester->timer);
        }
    } interruptor;

    tester_t(config_t *config, thread_pool_t *pool)
        : tps_log_fd(NULL), ser(NULL), active_txns(0), total_txns(0), config(config),
          pool(pool), stop(false), interrupted(false), last_time(0), txns_last_sec(0),
          secs_so_far(0), io_backender(new io_backender_t), interruptor(this) {
        last_time = get_ticks();
        if(config->tps_log_file) {
            tps_log_fd = fopen(config->tps_log_file, "a");
        }
    }

    /* When on_thread_switch() is called, it could either be the start message telling us to run the
    test or the shutdown message from call_later_on_this_thread(). We differentiate by checking 'ser'. */
    void on_thread_switch() {
        if (!ser) coro_t::spawn(boost::bind(&tester_t::start, this));
        else coro_t::spawn(boost::bind(&tester_t::shutdown, this));
    }

    void start() {
        if (config->log_file) {
            log = new log_t();
        } else {
            log = NULL;
        }

        fprintf(stderr, "Creating a database...\n");
        filepath_file_opener_t file_opener(config->db_filename, io_backender.get());
        log_serializer_t::create(&file_opener,
                                 config->ser_static_config);

        fprintf(stderr, "Starting serializer...\n");
        ser = new log_serializer_t(config->ser_dynamic_config,
                                   &file_opener,
                                   &get_global_perfmon_collection());
        on_serializer_ready(ser);
    }

    void on_serializer_ready(log_serializer_t *ls) {
        fprintf(stderr, "Running test...\n");
        if(config->duration != RUN_FOREVER) {
            timer = fire_timer_once(config->duration * 1000, &tester_t::on_timer, this);
        }

        linux_thread_message_t *prev_interrupt_message = pool->set_interrupt_message(&interruptor);
        guarantee(prev_interrupt_message == NULL);

        pump();
    }

    static void on_timer(void *self) {
        tester_t *tester = (tester_t *)self;
        fprintf(stderr, "Time's up.\n");
        tester->stop_test();
    }

    void pump() {
        while (active_txns < config->concurrent_txns && !stop) {
            active_txns++;
            total_txns++;
            coro_t::spawn_sometime(boost::bind(transact, ser, log, config->inserts_per_txn, config->updates_per_txn, this));
        }

        // See if we need to report the TPS
        ticks_t cur_time = get_ticks();
        if(ticks_to_secs(cur_time - last_time) >= 1.0f) {
            if(tps_log_fd) {
                fprintf(tps_log_fd, "%d\n", txns_last_sec);
            }

            last_time = cur_time;
            txns_last_sec = 0;
            secs_so_far++;

            // Flush every five seconds in case of a crash
            if(secs_so_far % 5 == 0) {
                fflush(tps_log_fd);
            }
        }

        if (active_txns == 0 && stop) {
            /* Serializer doesn't like shutdown() to be called from within
               on_serializer_write_txn() */
            call_later_on_this_thread(this);
        }
    }

    void stop_test() {

        if (stop) return;
        linux_thread_message_t *prev_interrupt_message = pool->set_interrupt_message(NULL);
        guarantee(prev_interrupt_message == &interruptor);

        fprintf(stderr, "Started %d transactions and completed %d of them\n",
            total_txns, total_txns - active_txns);

        if (tps_log_fd)
            fclose(tps_log_fd);

        if (config->log_file) {
            FILE *log_file = fopen(config->log_file, "w");
            log_t::iterator it;
            for (it = log->begin(); it != log->end(); it++) {
                fprintf(log_file, "%.6f %.6f\n", ticks_to_secs(it->start), ticks_to_secs(it->end));
            }
            fclose(log_file);
            fprintf(stderr, "Wrote log to '%s'\n", config->log_file);
            delete(log);
        }

        stop = true;
        if (active_txns > 0) {
            fprintf(stderr, "Waiting for the remaining %d transactions...\n", active_txns);
        }
    }

    void on_transaction_complete() {
        active_txns--;
        txns_last_sec++;
        pump();
    }

    void shutdown() {
        fprintf(stderr, "Waiting for serializer to shut down...\n");
        delete ser;
        on_serializer_shutdown();
    }

    void on_serializer_shutdown() {
        fprintf(stderr, "Done.\n");
        pool->shutdown_thread_pool();
    }
};

const char *read_arg(int &argc, char **&argv) {
    if (argc == 0) {
        fail_due_to_user_error("Expected another argument at the end.");
    } else {
        argc--;
        return (argv++)[0];
    }
}

void parse_config(int argc, char *argv[], config_t *config) {

    config->db_filename = "rethinkdb_data";
    config->log_file = NULL;
    config->tps_log_file = NULL;

    // config->ser_static_config uses its own defaults from constructor
    // config->ser_dynamic_config uses its own defaults from constructor

    config->duration = 10;   /* Seconds */
    config->concurrent_txns = 8;
    config->inserts_per_txn = 10;
    config->updates_per_txn = 2;

    read_arg(argc, argv);

    while (argc) {
        const char *flag = read_arg(argc, argv);

        if (strcmp(flag, "-f") == 0) {
            config->db_filename = read_arg(argc, argv);
        } else if (strcmp(flag, "--log") == 0) {
            config->log_file = read_arg(argc, argv);
        } else if (strcmp(flag, "--tps-log") == 0) {
            config->tps_log_file = read_arg(argc, argv);
        } else if (strcmp(flag, "--block-size") == 0) {
            config->ser_static_config.block_size_ = atoi(read_arg(argc, argv));
        } else if (strcmp(flag, "--extent-size") == 0) {
            config->ser_static_config.extent_size_ = atoi(read_arg(argc, argv));
        } else if (strcmp(flag, "--active-data-extents") == 0) {
            config->ser_dynamic_config.num_active_data_extents = atoi(read_arg(argc, argv));
        } else if (strcmp(flag, "--file-zone-size") == 0) {
            config->ser_dynamic_config.file_zone_size = atoi(read_arg(argc, argv));

        } else if (strcmp(flag, "--duration") == 0) {
            config->duration = atoi(read_arg(argc, argv));
        } else if (strcmp(flag, "--forever") == 0) {
            config->duration = RUN_FOREVER;
        } else if (strcmp(flag, "--concurrent") == 0) {
            config->concurrent_txns = atoi(read_arg(argc, argv));
        } else if (strcmp(flag, "--inserts-per-txn") == 0) {
            config->inserts_per_txn = atoi(read_arg(argc, argv));
        } else if (strcmp(flag, "--updates-per-txn") == 0) {
            config->updates_per_txn = atoi(read_arg(argc, argv));

        } else {
            fail_due_to_user_error("Don't know how to handle \"%s\"", flag);
        }
    }

    rassert(config->ser_static_config.block_size().ser_value() > 0);
    rassert(config->ser_static_config.extent_size() > 0);
    rassert(config->ser_dynamic_config.num_active_data_extents > 0);
    rassert(config->ser_dynamic_config.file_zone_size > 0);
    rassert(config->duration > 0 || config->duration == RUN_FOREVER);
    rassert(config->concurrent_txns > 0);
}

int main(int argc, char *argv[]) {

    config_t config;
    parse_config(argc, argv, &config);

    thread_pool_t thread_pool(1, true);
    tester_t tester(&config, &thread_pool);
    thread_pool.run_thread_pool(&tester);

    return 0;
}
<|endoftext|>


<commit_before>//
// Copyright (c) 2014 Toshiaki Takada
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
#include <iostream>
#include <iomanip>

#include <readline/readline.h>
#include <readline/history.h>
#include "json/json.h"

#include "project.hpp"
#include "cli_tree.hpp"
#include "cli_action.hpp"
#include "cli_readline.hpp"
#include "cli.hpp"

const boost::regex CliReadline::re_white_space("^([[:space:]]*)");
const boost::regex CliReadline::re_white_space_only("^([[:space:]]*)$");
const boost::regex CliReadline::re_command_string("^[^[:space:]]+");

size_t
CliReadline::match_token(string& input, CliNode *curr,
                         CliNodeMatchStateVector& state_vec)
{
  CliNode *next;
  CliNodeMatchStateVector matched_vec;

  for (CliNodeVector::iterator it = curr->next_.begin();
       it != curr->next_.end(); ++it)
    {
      next = (*it);

      MatchState state = next->cli_match(input);
      if (state.first == match_success)
        {
          CliNodeMatchStatePair p = make_pair(next, state);
          matched_vec.push_back(p);
        }
    }

  state_vec = matched_vec;

  return matched_vec.size();
}

bool
CliReadline::get_token(string& str, string& token)
{
  boost::smatch m;

  if (boost::regex_search(str, m, re_command_string))
    {
      token = m[0];
      str = m.suffix();

      return true;
    }

  return false;
}

bool
CliReadline::skip_spaces(string& str)
{
  boost::smatch m;

  if (boost::regex_search(str, m, re_white_space))
    {
      str = m.suffix();
      return true;
    }

  return false;
}

void
CliReadline::fill_matched_vec(CliNode *node,
                              CliNodeMatchStateVector& matched_vec)
{
  for (CliNodeVector::iterator it = node->next_.begin();
       it != node->next_.end(); ++it)
    {
      MatchState state = make_pair(match_success, match_partial);
      CliNodeMatchStatePair p = make_pair(*it, state);
      matched_vec.push_back(p);
    }
}

void
CliReadline::filter_matched(CliNodeMatchStateVector& matched_vec,
                            MatchFlag limit)
{
  CliNodeMatchStateVector vec;

  for (CliNodeMatchStateVector::iterator it = matched_vec.begin();
       it != matched_vec.end(); ++it)
    {
      if (it->second.second > limit)
        continue;

      if (it->second.second < limit)
        {
          vec.clear();
          limit = it->second.second;
        }

      vec.push_back(*it);
    }

  matched_vec = vec;
}

// Return true if command can be completed.
bool
CliReadline::parse(string& line, CliNode *curr,
                   CliNodeMatchStateVector& matched_vec)
{
  boost::smatch m;
  string token;

  matched_vec.clear();
  if (!skip_spaces(line))
    return curr->cmd_;

  fill_matched_vec(curr, matched_vec);

  if (!get_token(line, token))
    return curr->cmd_;

  match_token(token, curr, matched_vec);
  if (line.begin() != line.end())
    {
      filter_matched(matched_vec, match_partial);

      if (matched_vec.size() == 1)
        return parse(line, matched_vec[0].first, matched_vec);
    }

  if (matched_vec.size() == 1)
    curr = matched_vec[0].first;

  return curr->cmd_;
}

enum ExecResult
CliReadline::parse_execute(string& line, CliNode *curr,
                           CliNodeTokenVector& node_token_vec)
{
  boost::smatch m;
  string token;
  CliNodeMatchStateVector matched_vec;

  do {
    if (!skip_spaces(line))
      break;

    if (!get_token(line, token))
      break;

    fill_matched_vec(curr, matched_vec);
    match_token(token, curr, matched_vec);
    filter_matched(matched_vec, match_partial);

    if (matched_vec.size() == 0)
      return exec_unrecognized;
    else if (matched_vec.size() > 1)
      return exec_ambiguous;

    CliNodeTokenPair p = make_pair(matched_vec[0].first, new string(token));
    node_token_vec.push_back(p);

    // Candidate is only one at this point.
    if (line.begin() != line.end())
      return parse_execute(line, matched_vec[0].first, node_token_vec);

    if (matched_vec[0].second.second == match_incomplete)
      return exec_incomplete;

    if (!matched_vec[0].first->cmd_)
      return exec_incomplete;

    curr = matched_vec[0].first;

  } while (0);

  if (curr->cmd_)
    return exec_complete;

  return exec_unrecognized;
}

void
CliReadline::describe_line(CliNode *node, size_t max_len_token)
{
  size_t max_len_help;
  string cli_token(node->cli_token());
  string help(node->help());
  string substr;

  // No enough space to show help, just print without folding.
  if (cli_->ws_.ws_col < max_len_token + 5)
    {
      cout << "  " << left << setw(max_len_token + 2)
           << cli_token << node->help() << endl;
      return;
    }

  max_len_help = cli_->ws_.ws_col - (max_len_token + 5);

  while (help.size() > max_len_help)
    {
      const char *s = help.c_str();
      const char *p = s + max_len_help;

       while (*p != ' ' && p != s)
         p--;

       if (p == s)
         break;

       size_t length = (size_t)(p - s);
       substr = help.substr(0, length);

       cout << "  " << left << setw(max_len_token + 2)
            << cli_token << substr << endl;

       help = help.substr(length + 1);

       cli_token = " ";
     }

   cout << "  " << left << setw(max_len_token + 2)
        << cli_token << help << endl;
 }

 int
 CliReadline::describe()
 {
   // current mode.
   CliTree *tree = cli_->current_mode();
   CliNode *candidate;
   CliNodeMatchStateVector matched_vec;
   string line(" ");
   bool is_cmd = false;

   line += rl_line_buffer;

   cout << "?" << endl;

   is_cmd = parse(line, tree->top_, matched_vec);
   if (!is_cmd && matched_vec.size() == 0)
     {
       cout << "% Unrecognized command" << endl << endl;
     }
   else
     {
       size_t max_len = 0;
       for (CliNodeMatchStateVector::iterator it = matched_vec.begin();
            it != matched_vec.end(); ++it)
         {
           candidate = it->first;
           size_t len = candidate->cli_token().size();
           if (max_len < len)
             max_len = len;
         }

       for (CliNodeMatchStateVector::iterator it = matched_vec.begin();
            it != matched_vec.end(); ++it)
         describe_line(it->first, max_len);

       if (is_cmd)
         cout << "  <cr>" << endl;
     }

   cout << cli_->prompt();
   cout << rl_line_buffer;

   return 0;
 }

 int
 readline_describe(int, int)
 {
   return Cli::readline().describe();
 }

 static char *
 readline_completion_dummy(const char *, int)
 {
   return NULL;
 }

 char *
 CliReadline::completion_matches(const char *text, int state)
 {
   CliTree *tree = cli_->current_mode();
   CliNodeMatchStateVector matched_vec;
   string line(" ");
   bool is_cmd = false;

   line += rl_line_buffer;

   // No input.
   if (rl_end == 0)
     {
       cout << endl << endl;
       cout << cli_->prompt();
       return NULL;
     }

   if (state == 0)
     {
       matched_strvec_ = NULL;
       matched_index_ = 0;

       is_cmd = parse(line, tree->top_, matched_vec);
       if (matched_vec.size() == 0)
         {
           cout << endl;
           if (!is_cmd)
             cout << "% Unrecognized command" << endl << endl;
           cout << cli_->prompt();
           cout << rl_line_buffer;
         }
       else
         {
           int i = 0;

           matched_strvec_ =
             (char **)calloc(matched_vec.size() + 1, sizeof(char *));

           for (CliNodeMatchStateVector::iterator it = matched_vec.begin();
                it != matched_vec.end(); ++it)
             {
               CliNode *node = it->first;
               if (node->type_ == CliTree::keyword)
                 matched_strvec_[i++] = strdup(node->cli_token().c_str());
             }
         }
     }

   if (matched_strvec_ && matched_strvec_[matched_index_])
     return matched_strvec_[matched_index_++];

   return NULL;
 }

 char *
 readline_completion_matches(const char *text, int state)
 {
   return Cli::readline().completion_matches(text, state);
 }

 char **
 CliReadline::completion(const char *text, int start, int end)
 {
   return rl_completion_matches(text, readline_completion_matches);
 }

 char **
 readline_completion(const char *text, int start, int end)
 {
   return Cli::readline().completion(text, start, end);
 }

 void
 CliReadline::init(Cli *cli)
 {
   cli_ = cli;
   utils_.init();

   rl_bind_key('?', readline_describe);
   rl_completion_entry_function = readline_completion_dummy;
   rl_attempted_completion_function = readline_completion;
   rl_completion_append_character = '\0';
 }

 char *
 CliReadline::gets()
 {
   // Clear readline read buffer first.
   if (buf_)
     {
       free(buf_);
       buf_ = NULL;
     }

   // Read a line.
   buf_ = readline(cli_->prompt());

   // Add history.
   if (buf_ && buf_[0] != '\0')
     add_history(buf_);

   return buf_;
 }

 bool
 CliReadline::execute()
 {
   // current mode.
   CliTree *tree = cli_->current_mode();
   CliNodeTokenVector node_token_vec;
   ParamsMap input;
   map<string, bool> keywords;
   string line(" ");
   boost::smatch m;

   line += rl_line_buffer;

   if (!boost::regex_search(line, m, re_white_space_only))
     {
       enum ExecResult
         result = parse_execute(line, tree->top_, node_token_vec);

       switch (result)
         {
         case exec_complete:
           {
             // Populate mode params first.
             for (ParamsMap::iterator it = cli_->params_.begin();
                  it != cli_->params_.end(); ++it)
               input[it->first] = it->second;

             //
             for (CliNodeTokenVector::iterator it = node_token_vec.begin();
                  it != node_token_vec.end(); ++it)
               {
                 CliNode *node = it->first;

                 if (cli_->is_debug())
                   cout << "token: " << node->cli_token() << " "
                        << "input: " << *it->second << endl;

                 if (node->type_ == CliTree::keyword)
                   {
                     keywords[node->def_token()] = true;
                     CliNodeKeyword *knode = (CliNodeKeyword *)node;
                     if (!knode->enum_key().empty())
                       input[knode->enum_key()] = knode->cli_token();
                  }
                else
                  {
                    input[node->def_token()] = node->format_param(*it->second);
//                    if (cli_->is_debug())
//                      cout << "params[" << node->def_token()
//                           << "] = " << *it->second << endl;
                  }
              }

            // Command matched last node.
            CliNode *node = node_token_vec.back().first;

            // Pre-process parameter binding.
            for (CondBindPairVector::iterator it = node->bind_.begin();
                 it != node->bind_.end(); ++it)
              {
                const char *cond = it->first.c_str();

                // Always bind if it is TRUE.
                if (cond[0] == '\0')
                  utils_.bind_interpreter(it->second, input);
                // If the parameter is NOT present.
                else if (cond[0] == '!')
                  {
                    ParamsMap::iterator is = input.find(&cond[1]);
                    if (is == input.end())
                      utils_.bind_interpreter(it->second, input);
                  }
                // If the parameter is present.
                else
                  {
                    ParamsMap::iterator is = input.find(cond);
                    if (is != input.end())
                      utils_.bind_interpreter(it->second, input);
                  }
              }

            // Dump all inputs.
            if (cli_->is_debug())
              for (ParamsMap::iterator it = input.begin();
                   it != input.end(); ++it)
                cout << "input[" << it->first << "] = " << it->second << endl;

            // Dispatch action to appropriate handler.
            for (CliActionVector::iterator it = node->actions_.begin();
                 it != node->actions_.end(); ++it)
              {
                string cond = it->first;
                CliAction *action = it->second;

                // This is default action.
                if (cond == "*")
                  action->handle(cli_, input);
              }
          }
          break;
        case exec_incomplete:
          cout << "% Incomplete command" << endl << endl;
          break;
        case exec_ambiguous:
          cout << "% Ambiguous command" << endl << endl;
          break;
        case exec_unrecognized:
          cout << "% Unrecognized command" << endl << endl;
          break;
        }

      // Cleanup input token strings.
      for (CliNodeTokenVector::iterator it = node_token_vec.begin();
           it != node_token_vec.end(); ++it)
        delete it->second;
    }

  return true;
}

<commit_msg>Fix indent.<commit_after>//
// Copyright (c) 2014 Toshiaki Takada
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
#include <iostream>
#include <iomanip>

#include <readline/readline.h>
#include <readline/history.h>
#include "json/json.h"

#include "project.hpp"
#include "cli_tree.hpp"
#include "cli_action.hpp"
#include "cli_readline.hpp"
#include "cli.hpp"

const boost::regex CliReadline::re_white_space("^([[:space:]]*)");
const boost::regex CliReadline::re_white_space_only("^([[:space:]]*)$");
const boost::regex CliReadline::re_command_string("^[^[:space:]]+");

size_t
CliReadline::match_token(string& input, CliNode *curr,
                         CliNodeMatchStateVector& state_vec)
{
  CliNode *next;
  CliNodeMatchStateVector matched_vec;

  for (CliNodeVector::iterator it = curr->next_.begin();
       it != curr->next_.end(); ++it)
    {
      next = (*it);

      MatchState state = next->cli_match(input);
      if (state.first == match_success)
        {
          CliNodeMatchStatePair p = make_pair(next, state);
          matched_vec.push_back(p);
        }
    }

  state_vec = matched_vec;

  return matched_vec.size();
}

bool
CliReadline::get_token(string& str, string& token)
{
  boost::smatch m;

  if (boost::regex_search(str, m, re_command_string))
    {
      token = m[0];
      str = m.suffix();

      return true;
    }

  return false;
}

bool
CliReadline::skip_spaces(string& str)
{
  boost::smatch m;

  if (boost::regex_search(str, m, re_white_space))
    {
      str = m.suffix();
      return true;
    }

  return false;
}

void
CliReadline::fill_matched_vec(CliNode *node,
                              CliNodeMatchStateVector& matched_vec)
{
  for (CliNodeVector::iterator it = node->next_.begin();
       it != node->next_.end(); ++it)
    {
      MatchState state = make_pair(match_success, match_partial);
      CliNodeMatchStatePair p = make_pair(*it, state);
      matched_vec.push_back(p);
    }
}

void
CliReadline::filter_matched(CliNodeMatchStateVector& matched_vec,
                            MatchFlag limit)
{
  CliNodeMatchStateVector vec;

  for (CliNodeMatchStateVector::iterator it = matched_vec.begin();
       it != matched_vec.end(); ++it)
    {
      if (it->second.second > limit)
        continue;

      if (it->second.second < limit)
        {
          vec.clear();
          limit = it->second.second;
        }

      vec.push_back(*it);
    }

  matched_vec = vec;
}

// Return true if command can be completed.
bool
CliReadline::parse(string& line, CliNode *curr,
                   CliNodeMatchStateVector& matched_vec)
{
  boost::smatch m;
  string token;

  matched_vec.clear();
  if (!skip_spaces(line))
    return curr->cmd_;

  fill_matched_vec(curr, matched_vec);

  if (!get_token(line, token))
    return curr->cmd_;

  match_token(token, curr, matched_vec);
  if (line.begin() != line.end())
    {
      filter_matched(matched_vec, match_partial);

      if (matched_vec.size() == 1)
        return parse(line, matched_vec[0].first, matched_vec);
    }

  if (matched_vec.size() == 1)
    curr = matched_vec[0].first;

  return curr->cmd_;
}

enum ExecResult
CliReadline::parse_execute(string& line, CliNode *curr,
                           CliNodeTokenVector& node_token_vec)
{
  boost::smatch m;
  string token;
  CliNodeMatchStateVector matched_vec;

  do {
    if (!skip_spaces(line))
      break;

    if (!get_token(line, token))
      break;

    fill_matched_vec(curr, matched_vec);
    match_token(token, curr, matched_vec);
    filter_matched(matched_vec, match_partial);

    if (matched_vec.size() == 0)
      return exec_unrecognized;
    else if (matched_vec.size() > 1)
      return exec_ambiguous;

    CliNodeTokenPair p = make_pair(matched_vec[0].first, new string(token));
    node_token_vec.push_back(p);

    // Candidate is only one at this point.
    if (line.begin() != line.end())
      return parse_execute(line, matched_vec[0].first, node_token_vec);

    if (matched_vec[0].second.second == match_incomplete)
      return exec_incomplete;

    if (!matched_vec[0].first->cmd_)
      return exec_incomplete;

    curr = matched_vec[0].first;

  } while (0);

  if (curr->cmd_)
    return exec_complete;

  return exec_unrecognized;
}

void
CliReadline::describe_line(CliNode *node, size_t max_len_token)
{
  size_t max_len_help;
  string cli_token(node->cli_token());
  string help(node->help());
  string substr;

  // No enough space to show help, just print without folding.
  if (cli_->ws_.ws_col < max_len_token + 5)
    {
      cout << "  " << left << setw(max_len_token + 2)
           << cli_token << node->help() << endl;
      return;
    }

  max_len_help = cli_->ws_.ws_col - (max_len_token + 5);

  while (help.size() > max_len_help)
    {
      const char *s = help.c_str();
      const char *p = s + max_len_help;

      while (*p != ' ' && p != s)
        p--;

      if (p == s)
        break;

      size_t length = (size_t)(p - s);
      substr = help.substr(0, length);

      cout << "  " << left << setw(max_len_token + 2)
           << cli_token << substr << endl;

      help = help.substr(length + 1);

      cli_token = " ";
    }

  cout << "  " << left << setw(max_len_token + 2)
       << cli_token << help << endl;
}

int
CliReadline::describe()
{
  // current mode.
  CliTree *tree = cli_->current_mode();
  CliNode *candidate;
  CliNodeMatchStateVector matched_vec;
  string line(" ");
  bool is_cmd = false;

  line += rl_line_buffer;

  cout << "?" << endl;

  is_cmd = parse(line, tree->top_, matched_vec);
  if (!is_cmd && matched_vec.size() == 0)
    {
      cout << "% Unrecognized command" << endl << endl;
    }
  else
    {
      size_t max_len = 0;
      for (CliNodeMatchStateVector::iterator it = matched_vec.begin();
           it != matched_vec.end(); ++it)
        {
          candidate = it->first;
          size_t len = candidate->cli_token().size();
          if (max_len < len)
            max_len = len;
        }

      for (CliNodeMatchStateVector::iterator it = matched_vec.begin();
           it != matched_vec.end(); ++it)
        describe_line(it->first, max_len);

      if (is_cmd)
        cout << "  <cr>" << endl;
    }

  cout << cli_->prompt();
  cout << rl_line_buffer;

  return 0;
}

int
readline_describe(int, int)
{
  return Cli::readline().describe();
}

static char *
readline_completion_dummy(const char *, int)
{
  return NULL;
}

char *
CliReadline::completion_matches(const char *text, int state)
{
  CliTree *tree = cli_->current_mode();
  CliNodeMatchStateVector matched_vec;
  string line(" ");
  bool is_cmd = false;

  line += rl_line_buffer;

  // No input.
  if (rl_end == 0)
    {
      cout << endl << endl;
      cout << cli_->prompt();
      return NULL;
    }

  if (state == 0)
    {
      matched_strvec_ = NULL;
      matched_index_ = 0;

      is_cmd = parse(line, tree->top_, matched_vec);
      if (matched_vec.size() == 0)
        {
          cout << endl;
          if (!is_cmd)
            cout << "% Unrecognized command" << endl << endl;
          cout << cli_->prompt();
          cout << rl_line_buffer;
        }
      else
        {
          int i = 0;

          matched_strvec_ =
            (char **)calloc(matched_vec.size() + 1, sizeof(char *));

          for (CliNodeMatchStateVector::iterator it = matched_vec.begin();
               it != matched_vec.end(); ++it)
            {
              CliNode *node = it->first;
              if (node->type_ == CliTree::keyword)
                matched_strvec_[i++] = strdup(node->cli_token().c_str());
            }
        }
    }

  if (matched_strvec_ && matched_strvec_[matched_index_])
    return matched_strvec_[matched_index_++];

  return NULL;
}

char *
readline_completion_matches(const char *text, int state)
{
  return Cli::readline().completion_matches(text, state);
}

char **
CliReadline::completion(const char *text, int start, int end)
{
  return rl_completion_matches(text, readline_completion_matches);
}

char **
readline_completion(const char *text, int start, int end)
{
  return Cli::readline().completion(text, start, end);
}

void
CliReadline::init(Cli *cli)
{
  cli_ = cli;
  utils_.init();

  rl_bind_key('?', readline_describe);
  rl_completion_entry_function = readline_completion_dummy;
  rl_attempted_completion_function = readline_completion;
  rl_completion_append_character = '\0';
}

char *
CliReadline::gets()
{
  // Clear readline read buffer first.
  if (buf_)
    {
      free(buf_);
      buf_ = NULL;
    }

  // Read a line.
  buf_ = readline(cli_->prompt());

  // Add history.
  if (buf_ && buf_[0] != '\0')
    add_history(buf_);

  return buf_;
}

bool
CliReadline::execute()
{
  // current mode.
  CliTree *tree = cli_->current_mode();
  CliNodeTokenVector node_token_vec;
  ParamsMap input;
  map<string, bool> keywords;
  string line(" ");
  boost::smatch m;

  line += rl_line_buffer;

  if (!boost::regex_search(line, m, re_white_space_only))
    {
      enum ExecResult
        result = parse_execute(line, tree->top_, node_token_vec);

      switch (result)
        {
        case exec_complete:
          {
            // Populate mode params first.
            for (ParamsMap::iterator it = cli_->params_.begin();
                 it != cli_->params_.end(); ++it)
              input[it->first] = it->second;

            //
            for (CliNodeTokenVector::iterator it = node_token_vec.begin();
                 it != node_token_vec.end(); ++it)
              {
                CliNode *node = it->first;

                if (cli_->is_debug())
                  cout << "token: " << node->cli_token() << " "
                       << "input: " << *it->second << endl;

                if (node->type_ == CliTree::keyword)
                  {
                    keywords[node->def_token()] = true;
                    CliNodeKeyword *knode = (CliNodeKeyword *)node;
                    if (!knode->enum_key().empty())
                      input[knode->enum_key()] = knode->cli_token();
                  }
                else
                  {
                    input[node->def_token()] = node->format_param(*it->second);
                  }
              }

            // Command matched last node.
            CliNode *node = node_token_vec.back().first;

            // Pre-process parameter binding.
            for (CondBindPairVector::iterator it = node->bind_.begin();
                 it != node->bind_.end(); ++it)
              {
                const char *cond = it->first.c_str();

                // Always bind if it is TRUE.
                if (cond[0] == '\0')
                  utils_.bind_interpreter(it->second, input);
                // If the parameter is NOT present.
                else if (cond[0] == '!')
                  {
                    ParamsMap::iterator is = input.find(&cond[1]);
                    if (is == input.end())
                      utils_.bind_interpreter(it->second, input);
                  }
                // If the parameter is present.
                else
                  {
                    ParamsMap::iterator is = input.find(cond);
                    if (is != input.end())
                      utils_.bind_interpreter(it->second, input);
                  }
              }

            // Dump all inputs.
            if (cli_->is_debug())
              for (ParamsMap::iterator it = input.begin();
                   it != input.end(); ++it)
                cout << "input[" << it->first << "] = " << it->second << endl;

            // Dispatch action to appropriate handler.
            for (CliActionVector::iterator it = node->actions_.begin();
                 it != node->actions_.end(); ++it)
              {
                string cond = it->first;
                CliAction *action = it->second;

                // This is default action.
                if (cond == "*")
                  action->handle(cli_, input);
              }
          }
          break;
        case exec_incomplete:
          cout << "% Incomplete command" << endl << endl;
          break;
        case exec_ambiguous:
          cout << "% Ambiguous command" << endl << endl;
          break;
        case exec_unrecognized:
          cout << "% Unrecognized command" << endl << endl;
          break;
        }

      // Cleanup input token strings.
      for (CliNodeTokenVector::iterator it = node_token_vec.begin();
           it != node_token_vec.end(); ++it)
        delete it->second;
    }

  return true;
}

<|endoftext|>


<commit_before>#include "player.h"

Player::Player()
{
    //ctor
}
<commit_msg>Cleaning up redundant files.<commit_after><|endoftext|>