<commit_before>/****************************************************************/
/*               DO NOT MODIFY THIS HEADER                      */
/* MOOSE - Multiphysics Object Oriented Simulation Environment  */
/*                                                              */
/*           (c) 2010 Battelle Energy Alliance, LLC             */
/*                   ALL RIGHTS RESERVED                        */
/*                                                              */
/*          Prepared by Battelle Energy Alliance, LLC           */
/*            Under Contract No. DE-AC07-05ID14517              */
/*            With the U. S. Department of Energy               */
/*                                                              */
/*            See COPYRIGHT for full restrictions               */
/****************************************************************/

#include "ColumnMajorMatrix.h"
#include "petscsys.h"
#include "petscblaslapack.h"

ColumnMajorMatrix::ColumnMajorMatrix(unsigned int rows, unsigned int cols) :
    _n_rows(rows),
    _n_cols(cols),
    _n_entries(rows*cols),
    _values(rows*cols, 0.0)
{
  _values.resize(rows*cols);
}

ColumnMajorMatrix::ColumnMajorMatrix(const ColumnMajorMatrix &rhs) :
    _n_rows(LIBMESH_DIM),
    _n_cols(LIBMESH_DIM),
    _n_entries(_n_cols*_n_cols)
{
  *this = rhs;
}

ColumnMajorMatrix::ColumnMajorMatrix(const TypeTensor<Real> &rhs) :
    _n_rows(LIBMESH_DIM),
    _n_cols(LIBMESH_DIM),
    _n_entries(LIBMESH_DIM*LIBMESH_DIM),
    _values(LIBMESH_DIM*LIBMESH_DIM)
{
  for (unsigned int j=0; j<LIBMESH_DIM; ++j)
    for (unsigned int i=0; i<LIBMESH_DIM; ++i)
      (*this)(i, j) = rhs(i, j);
}

ColumnMajorMatrix::ColumnMajorMatrix(const DenseMatrix<Real> &rhs) :
    _n_rows(LIBMESH_DIM),
    _n_cols(LIBMESH_DIM),
    _n_entries(_n_cols*_n_cols)
{
   *this = rhs;
}

ColumnMajorMatrix::ColumnMajorMatrix(const DenseVector<Real> &rhs) :
    _n_rows(LIBMESH_DIM),
    _n_cols(LIBMESH_DIM),
    _n_entries(_n_cols*_n_cols)
{
   *this = rhs;
}

ColumnMajorMatrix::ColumnMajorMatrix(const TypeVector<Real> & col1,
                                     const TypeVector<Real> & col2,
                                     const TypeVector<Real> & col3) :
    _n_rows(LIBMESH_DIM),
    _n_cols(LIBMESH_DIM),
    _n_entries(LIBMESH_DIM*LIBMESH_DIM),
    _values(LIBMESH_DIM*LIBMESH_DIM)
{
  unsigned int entry = 0;
  for (unsigned int i=0; i<LIBMESH_DIM; i++)
    _values[entry++] = col1(i);

  for (unsigned int i=0; i<LIBMESH_DIM; i++)
    _values[entry++] = col2(i);

  for (unsigned int i=0; i<LIBMESH_DIM; i++)
    _values[entry++] = col3(i);
}

ColumnMajorMatrix ColumnMajorMatrix::kronecker  (const ColumnMajorMatrix &  rhs) const
{
  mooseAssert(_n_rows == rhs._n_cols && _n_cols == rhs._n_rows, "Matrices must be the same shape for a kronecker product!");

  ColumnMajorMatrix ret_matrix(_n_rows*_n_rows, rhs._n_cols*rhs._n_cols);

  for (unsigned int i = 0; i < _n_rows; i++)
    for (unsigned int j = 0; j < _n_cols; j++)
      for (unsigned int k = 0; k < rhs._n_rows; k++)
        for (unsigned int l = 0; l < rhs._n_cols; l++)
          ret_matrix(((i*_n_rows)+k),((j*_n_cols)+l)) = (*this)(i,j) * rhs(k,l);

  return ret_matrix;
}

ColumnMajorMatrix & ColumnMajorMatrix::operator=(const DenseMatrix<Real> &rhs)
{
  mooseAssert(_n_rows == rhs.m(), "different number of rows");
  mooseAssert(_n_cols == rhs.n(), "different number of cols");

  _n_rows = rhs.m();
  _n_cols = rhs.n();
  _n_entries = rhs.m()*rhs.n();
  _values.resize(rhs.m()*rhs.n());

  for (unsigned int j=0; j<_n_cols; ++j)
    for (unsigned int i=0; i<_n_rows; ++i)
         (*this)(i, j) = rhs(i, j);

  return *this;
}

ColumnMajorMatrix & ColumnMajorMatrix::operator=(const DenseVector<Real> &rhs)
{
  mooseAssert(_n_rows == rhs.size(), "different number of rows");
  mooseAssert(_n_cols == 1, "different number of cols");

  _n_rows = rhs.size();
  _n_cols = 1;
  _n_entries = rhs.size();
  _values.resize(rhs.size());

  for (unsigned int i=0; i<_n_rows; ++i)
    (*this)(i) = rhs(i);

  return *this;
}

void
ColumnMajorMatrix::eigen(ColumnMajorMatrix & eval, ColumnMajorMatrix & evec) const
{
   mooseAssert(_n_rows == _n_cols, "Cannot solve eigen system of a non-square matrix!");

  char jobz = 'V';
  char uplo = 'U';
  int n = _n_rows;
  int return_value = 0;

  eval._n_rows = _n_rows;
  eval._n_cols = 1;
  eval._n_entries = _n_rows;
  eval._values.resize(_n_rows);

  evec = *this;

  Real * eval_data = eval.rawData();
  Real * evec_data = evec.rawData();

  int buffer_size = n * 64;
  std::vector<Real> buffer(buffer_size);

  LAPACKsyev_(&jobz, &uplo, &n, evec_data, &n, eval_data, &buffer[0], &buffer_size, &return_value);

  if (return_value)
    mooseError("error in lapack eigen solve");
}

void
ColumnMajorMatrix::eigenNonsym(ColumnMajorMatrix & eval_real, ColumnMajorMatrix & eval_img, ColumnMajorMatrix & evec_right, ColumnMajorMatrix & evec_left) const
{
  mooseAssert(_n_rows == _n_cols, "Cannot solve eigen system of a non-square matrix!");

  ColumnMajorMatrix a(*this);

  char jobvl = 'V';
  char jobvr = 'V';
  int n = _n_rows;
  int return_value = 0;

  eval_real._n_rows = _n_rows;
  eval_real._n_cols = 1;
  eval_real._n_entries = _n_rows;
  eval_real._values.resize(_n_rows);

  eval_img._n_rows = _n_rows;
  eval_img._n_cols = 1;
  eval_img._n_entries = _n_rows;
  eval_img._values.resize(_n_rows);

  Real * a_data = a.rawData();
  Real * eval_r = eval_real.rawData();
  Real * eval_i = eval_img.rawData();
  Real * evec_ri = evec_right.rawData();
  Real * evec_le = evec_left.rawData();

  int buffer_size = n * 64;
  std::vector<Real> buffer(buffer_size);

  LAPACKgeev_(&jobvl, &jobvr, &n, a_data, &n, eval_r, eval_i, evec_le, &n, evec_ri, &n, &buffer[0], &buffer_size, &return_value);

  if (return_value)
    mooseError("error in lapack eigen solve");
}

void
ColumnMajorMatrix::exp(ColumnMajorMatrix & z) const
{
  mooseAssert(_n_rows == _n_cols, "The Matrix being exponentiated is not square");
  ColumnMajorMatrix a(*this);
  ColumnMajorMatrix evals_real(_n_rows,1), evals_img(_n_rows,1), evals_real2(_n_rows,_n_cols);
  ColumnMajorMatrix evec_right(_n_rows,_n_cols), evec_left(_n_rows,_n_cols);
  ColumnMajorMatrix evec_right_inverse(_n_rows,_n_cols);

  a.eigenNonsym(evals_real, evals_img, evec_right, evec_left);

  for (unsigned int i=0; i<_n_rows; i++)
    evals_real2(i,i) = std::exp(evals_real(i,0));

  evec_right.inverse(evec_right_inverse);

  z = evec_right * evals_real2 * evec_right_inverse;
}

void
ColumnMajorMatrix::inverse(ColumnMajorMatrix & invA) const
{
  mooseAssert(_n_rows == _n_cols, "Cannot solve for inverse of a non-square matrix!");
  mooseAssert(_n_rows == invA._n_cols && _n_cols == invA._n_rows, "Matrices must be the same size for matrix inverse!");

  int n = _n_rows;
  int return_value = 0;

  invA = *this;

  std::vector<PetscBLASInt> ipiv(n);
  Real * invA_data = invA.rawData();

  int buffer_size = n * 64;
  std::vector<Real> buffer(buffer_size);

  LAPACKgetrf_(&n, &n, invA_data, &n, &ipiv[0], &return_value);
  LAPACKgetri_(&n, invA_data, &n, &ipiv[0], &buffer[0], &buffer_size, &return_value);

  if (return_value)
    mooseError("error in lapack inverse solve");
}
<commit_msg>Test for minumum PETSc version for dgetri (#4291)<commit_after>/****************************************************************/
/*               DO NOT MODIFY THIS HEADER                      */
/* MOOSE - Multiphysics Object Oriented Simulation Environment  */
/*                                                              */
/*           (c) 2010 Battelle Energy Alliance, LLC             */
/*                   ALL RIGHTS RESERVED                        */
/*                                                              */
/*          Prepared by Battelle Energy Alliance, LLC           */
/*            Under Contract No. DE-AC07-05ID14517              */
/*            With the U. S. Department of Energy               */
/*                                                              */
/*            See COPYRIGHT for full restrictions               */
/****************************************************************/

#include "ColumnMajorMatrix.h"

#include "libmesh/petsc_macro.h"
#include <petscsys.h>
#include <petscblaslapack.h>

#if !defined(LIBMESH_HAVE_PETSC)
  extern "C" void FORTRAN_CALL(dsyev) ( ... );
  extern "C" void FORTRAN_CALL(dgeev) ( ... );
  extern "C" void FORTRAN_CALL(dgetrf) ( ... );
#endif
#if !defined(LIBMESH_HAVE_PETSC) || PETSC_VERSION_LESS_THAN(3,5,0)
  extern "C" void FORTRAN_CALL(dgetri) ( ... ); // matrix inversion routine from LAPACK
#endif

ColumnMajorMatrix::ColumnMajorMatrix(unsigned int rows, unsigned int cols) :
    _n_rows(rows),
    _n_cols(cols),
    _n_entries(rows*cols),
    _values(rows*cols, 0.0)
{
  _values.resize(rows*cols);
}

ColumnMajorMatrix::ColumnMajorMatrix(const ColumnMajorMatrix &rhs) :
    _n_rows(LIBMESH_DIM),
    _n_cols(LIBMESH_DIM),
    _n_entries(_n_cols*_n_cols)
{
  *this = rhs;
}

ColumnMajorMatrix::ColumnMajorMatrix(const TypeTensor<Real> &rhs) :
    _n_rows(LIBMESH_DIM),
    _n_cols(LIBMESH_DIM),
    _n_entries(LIBMESH_DIM*LIBMESH_DIM),
    _values(LIBMESH_DIM*LIBMESH_DIM)
{
  for (unsigned int j=0; j<LIBMESH_DIM; ++j)
    for (unsigned int i=0; i<LIBMESH_DIM; ++i)
      (*this)(i, j) = rhs(i, j);
}

ColumnMajorMatrix::ColumnMajorMatrix(const DenseMatrix<Real> &rhs) :
    _n_rows(LIBMESH_DIM),
    _n_cols(LIBMESH_DIM),
    _n_entries(_n_cols*_n_cols)
{
   *this = rhs;
}

ColumnMajorMatrix::ColumnMajorMatrix(const DenseVector<Real> &rhs) :
    _n_rows(LIBMESH_DIM),
    _n_cols(LIBMESH_DIM),
    _n_entries(_n_cols*_n_cols)
{
   *this = rhs;
}

ColumnMajorMatrix::ColumnMajorMatrix(const TypeVector<Real> & col1,
                                     const TypeVector<Real> & col2,
                                     const TypeVector<Real> & col3) :
    _n_rows(LIBMESH_DIM),
    _n_cols(LIBMESH_DIM),
    _n_entries(LIBMESH_DIM*LIBMESH_DIM),
    _values(LIBMESH_DIM*LIBMESH_DIM)
{
  unsigned int entry = 0;
  for (unsigned int i=0; i<LIBMESH_DIM; i++)
    _values[entry++] = col1(i);

  for (unsigned int i=0; i<LIBMESH_DIM; i++)
    _values[entry++] = col2(i);

  for (unsigned int i=0; i<LIBMESH_DIM; i++)
    _values[entry++] = col3(i);
}

ColumnMajorMatrix ColumnMajorMatrix::kronecker  (const ColumnMajorMatrix &  rhs) const
{
  mooseAssert(_n_rows == rhs._n_cols && _n_cols == rhs._n_rows, "Matrices must be the same shape for a kronecker product!");

  ColumnMajorMatrix ret_matrix(_n_rows*_n_rows, rhs._n_cols*rhs._n_cols);

  for (unsigned int i = 0; i < _n_rows; i++)
    for (unsigned int j = 0; j < _n_cols; j++)
      for (unsigned int k = 0; k < rhs._n_rows; k++)
        for (unsigned int l = 0; l < rhs._n_cols; l++)
          ret_matrix(((i*_n_rows)+k),((j*_n_cols)+l)) = (*this)(i,j) * rhs(k,l);

  return ret_matrix;
}

ColumnMajorMatrix & ColumnMajorMatrix::operator=(const DenseMatrix<Real> &rhs)
{
  mooseAssert(_n_rows == rhs.m(), "different number of rows");
  mooseAssert(_n_cols == rhs.n(), "different number of cols");

  _n_rows = rhs.m();
  _n_cols = rhs.n();
  _n_entries = rhs.m()*rhs.n();
  _values.resize(rhs.m()*rhs.n());

  for (unsigned int j=0; j<_n_cols; ++j)
    for (unsigned int i=0; i<_n_rows; ++i)
         (*this)(i, j) = rhs(i, j);

  return *this;
}

ColumnMajorMatrix & ColumnMajorMatrix::operator=(const DenseVector<Real> &rhs)
{
  mooseAssert(_n_rows == rhs.size(), "different number of rows");
  mooseAssert(_n_cols == 1, "different number of cols");

  _n_rows = rhs.size();
  _n_cols = 1;
  _n_entries = rhs.size();
  _values.resize(rhs.size());

  for (unsigned int i=0; i<_n_rows; ++i)
    (*this)(i) = rhs(i);

  return *this;
}

void
ColumnMajorMatrix::eigen(ColumnMajorMatrix & eval, ColumnMajorMatrix & evec) const
{
   mooseAssert(_n_rows == _n_cols, "Cannot solve eigen system of a non-square matrix!");

  char jobz = 'V';
  char uplo = 'U';
  int n = _n_rows;
  int return_value = 0;

  eval._n_rows = _n_rows;
  eval._n_cols = 1;
  eval._n_entries = _n_rows;
  eval._values.resize(_n_rows);

  evec = *this;

  Real * eval_data = eval.rawData();
  Real * evec_data = evec.rawData();

  int buffer_size = n * 64;
  std::vector<Real> buffer(buffer_size);

#if !defined(LIBMESH_HAVE_PETSC)
  FORTRAN_CALL(dsyev)(&jobz, &uplo, &n, evec_data, &n, eval_data, &buffer[0], &buffer_size, &return_value);
#else
  LAPACKsyev_(&jobz, &uplo, &n, evec_data, &n, eval_data, &buffer[0], &buffer_size, &return_value);
#endif

  if (return_value)
    mooseError("error in lapack eigen solve");
}

void
ColumnMajorMatrix::eigenNonsym(ColumnMajorMatrix & eval_real, ColumnMajorMatrix & eval_img, ColumnMajorMatrix & evec_right, ColumnMajorMatrix & evec_left) const
{
  mooseAssert(_n_rows == _n_cols, "Cannot solve eigen system of a non-square matrix!");

  ColumnMajorMatrix a(*this);

  char jobvl = 'V';
  char jobvr = 'V';
  int n = _n_rows;
  int return_value = 0;

  eval_real._n_rows = _n_rows;
  eval_real._n_cols = 1;
  eval_real._n_entries = _n_rows;
  eval_real._values.resize(_n_rows);

  eval_img._n_rows = _n_rows;
  eval_img._n_cols = 1;
  eval_img._n_entries = _n_rows;
  eval_img._values.resize(_n_rows);

  Real * a_data = a.rawData();
  Real * eval_r = eval_real.rawData();
  Real * eval_i = eval_img.rawData();
  Real * evec_ri = evec_right.rawData();
  Real * evec_le = evec_left.rawData();

  int buffer_size = n * 64;
  std::vector<Real> buffer(buffer_size);

#if !defined(LIBMESH_HAVE_PETSC)
  FORTRAN_CALL(dgeev)(&jobvl, &jobvr, &n, a_data, &n, eval_r, eval_i, evec_le, &n, evec_ri, &n, &buffer[0], &buffer_size, &return_value);
#else
  LAPACKgeev_(&jobvl, &jobvr, &n, a_data, &n, eval_r, eval_i, evec_le, &n, evec_ri, &n, &buffer[0], &buffer_size, &return_value);
#endif

  if (return_value)
    mooseError("error in lapack eigen solve");
}

void
ColumnMajorMatrix::exp(ColumnMajorMatrix & z) const
{
  mooseAssert(_n_rows == _n_cols, "The Matrix being exponentiated is not square");
  ColumnMajorMatrix a(*this);
  ColumnMajorMatrix evals_real(_n_rows,1), evals_img(_n_rows,1), evals_real2(_n_rows,_n_cols);
  ColumnMajorMatrix evec_right(_n_rows,_n_cols), evec_left(_n_rows,_n_cols);
  ColumnMajorMatrix evec_right_inverse(_n_rows,_n_cols);

  a.eigenNonsym(evals_real, evals_img, evec_right, evec_left);

  for (unsigned int i=0; i<_n_rows; i++)
    evals_real2(i,i) = std::exp(evals_real(i,0));

  evec_right.inverse(evec_right_inverse);

  z = evec_right * evals_real2 * evec_right_inverse;
}

void
ColumnMajorMatrix::inverse(ColumnMajorMatrix & invA) const
{
  mooseAssert(_n_rows == _n_cols, "Cannot solve for inverse of a non-square matrix!");
  mooseAssert(_n_rows == invA._n_cols && _n_cols == invA._n_rows, "Matrices must be the same size for matrix inverse!");

  int n = _n_rows;
  int return_value = 0;

  invA = *this;

  std::vector<PetscBLASInt> ipiv(n);
  Real * invA_data = invA.rawData();

  int buffer_size = n * 64;
  std::vector<Real> buffer(buffer_size);

#if !defined(LIBMESH_HAVE_PETSC)
  FORTRAN_CALL(dgetrf)(&n, &n, invA_data, &n, &ipiv[0], &return_value);
#else
  LAPACKgetrf_(&n, &n, invA_data, &n, &ipiv[0], &return_value);
#endif

#if !defined(LIBMESH_HAVE_PETSC) || PETSC_VERSION_LESS_THAN(3,5,0)
  FORTRAN_CALL(dgetri)(&n, invA_data, &n, &ipiv[0], &buffer[0], &buffer_size, &return_value);
#else
  LAPACKgetri_(&n, invA_data, &n, &ipiv[0], &buffer[0], &buffer_size, &return_value);
#endif

  if (return_value)
    mooseError("error in lapack inverse solve");
}
<|endoftext|>


<commit_before>//===- Parser.cpp - Main dispatch module for the Parser library -----------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This library implements the functionality defined in llvm/Assembly/Parser.h
//
//===----------------------------------------------------------------------===//

#include "llvm/Assembly/Parser.h"
#include "LLParser.h"
#include "llvm/Module.h"
#include "llvm/ADT/OwningPtr.h"
#include "llvm/Support/SourceMgr.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/raw_ostream.h"
#include <cstring>
using namespace llvm;

Module *llvm::ParseAssembly(MemoryBuffer *F,
                            Module *M,
                            SMDiagnostic &Err,
                            LLVMContext &Context) {
  SourceMgr SM;
  SM.AddNewSourceBuffer(F, SMLoc());

  // If we are parsing into an existing module, do it.
  if (M)
    return LLParser(F, SM, Err, M).Run() ? 0 : M;

  // Otherwise create a new module.
  OwningPtr<Module> M2(new Module(F->getBufferIdentifier(), Context));
  if (LLParser(F, SM, Err, M2.get()).Run())
    return 0;
  return M2.take();
}

Module *llvm::ParseAssemblyFile(const std::string &Filename, SMDiagnostic &Err,
                                LLVMContext &Context) {
  std::string ErrorStr;
  MemoryBuffer *F = MemoryBuffer::getFileOrSTDIN(Filename.c_str(), &ErrorStr);
  if (F == 0) {
    Err = SMDiagnostic("", -1, -1,
                       "Could not open input file '" + Filename + "'", "");
    return 0;
  }

  return ParseAssembly(F, 0, Err, Context);
}

Module *llvm::ParseAssemblyString(const char *AsmString, Module *M,
                                  SMDiagnostic &Err, LLVMContext &Context) {
  MemoryBuffer *F =
    MemoryBuffer::getMemBuffer(AsmString, AsmString+strlen(AsmString),
                               "<string>");

  return ParseAssembly(F, M, Err, Context);
}
<commit_msg>Make the parser include the lower level error message in its own error message, to be more informative.<commit_after>//===- Parser.cpp - Main dispatch module for the Parser library -----------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This library implements the functionality defined in llvm/Assembly/Parser.h
//
//===----------------------------------------------------------------------===//

#include "llvm/Assembly/Parser.h"
#include "LLParser.h"
#include "llvm/Module.h"
#include "llvm/ADT/OwningPtr.h"
#include "llvm/Support/SourceMgr.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/raw_ostream.h"
#include <cstring>
using namespace llvm;

Module *llvm::ParseAssembly(MemoryBuffer *F,
                            Module *M,
                            SMDiagnostic &Err,
                            LLVMContext &Context) {
  SourceMgr SM;
  SM.AddNewSourceBuffer(F, SMLoc());

  // If we are parsing into an existing module, do it.
  if (M)
    return LLParser(F, SM, Err, M).Run() ? 0 : M;

  // Otherwise create a new module.
  OwningPtr<Module> M2(new Module(F->getBufferIdentifier(), Context));
  if (LLParser(F, SM, Err, M2.get()).Run())
    return 0;
  return M2.take();
}

Module *llvm::ParseAssemblyFile(const std::string &Filename, SMDiagnostic &Err,
                                LLVMContext &Context) {
  std::string ErrorStr;
  MemoryBuffer *F = MemoryBuffer::getFileOrSTDIN(Filename.c_str(), &ErrorStr);
  if (F == 0) {
    Err = SMDiagnostic("", -1, -1,
                       "Could not open input file '" + Filename + "': " +
                       ErrorStr, "");
    return 0;
  }

  return ParseAssembly(F, 0, Err, Context);
}

Module *llvm::ParseAssemblyString(const char *AsmString, Module *M,
                                  SMDiagnostic &Err, LLVMContext &Context) {
  MemoryBuffer *F =
    MemoryBuffer::getMemBuffer(AsmString, AsmString+strlen(AsmString),
                               "<string>");

  return ParseAssembly(F, M, Err, Context);
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: DriverSettings.hxx,v $
 *
 *  $Revision: 1.4 $
 *
 *  last change: $Author: vg $ $Date: 2005-02-21 12:41:52 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the License); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an AS IS basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): Ocke Janssen
 *
 *
 ************************************************************************/
#ifndef DBAUI_DRIVERSETTINGS_HXX
#define DBAUI_DRIVERSETTINGS_HXX

#ifndef _DBAUI_DSNTYPES_HXX_
#include "dsntypes.hxx"
#endif
#include <vector>

class SfxTabPage;
class Window;
namespace dbaui
{
    /// a collection class for all details a driver needs
    class ODriversSettings
    {
    public:

        /** fills the DetailIds for the given type
            @param  _eType
                The Type of the data source.
            @param  _rDetailsIds
                Will be filled.
        */
        static void fillDetailIds(DATASOURCE_TYPE _eType,::std::vector< sal_Int32>& _rDetailsIds);

        /** Creates the detail page for Dbase
            @param  _pParent
            @param  _rAttrSet

            @return SfxTabPage*
        */
        static  SfxTabPage* CreateDbase2( Window* _pParent, const SfxItemSet& _rAttrSet );

        /** Creates the detail page for ado
            @param  _pParent
            @param  _rAttrSet

            @return SfxTabPage*
        */

        static  SfxTabPage* CreateDbase( Window* _pParent, const SfxItemSet& _rAttrSet );

        /** Creates the detail page for ado
            @param  _pParent
            @param  _rAttrSet

            @return SfxTabPage*
        */
        static  SfxTabPage* CreateAdo( Window* _pParent, const SfxItemSet& _rAttrSet );

        /** Creates the detail page for ODBC
            @param  _pParent
            @param  _rAttrSet

            @return SfxTabPage*
        */
        static  SfxTabPage* CreateODBC( Window* _pParent, const SfxItemSet& _rAttrSet );

        /** Creates the detail page for user
            @param  _pParent
            @param  _rAttrSet

            @return SfxTabPage*
        */
        static  SfxTabPage* CreateUser( Window* _pParent, const SfxItemSet& _rAttrSet );

        /** Creates the detail page for MySQLODBC
            @param  _pParent
            @param  _rAttrSet

            @return SfxTabPage*
        */
        static  SfxTabPage* CreateMySQLODBC( Window* _pParent, const SfxItemSet& _rAttrSet );

        /** Creates the detail page for MySQLJDBC
            @param  _pParent
            @param  _rAttrSet

            @return SfxTabPage*
        */
        static  SfxTabPage* CreateMySQLJDBC( Window* _pParent, const SfxItemSet& _rAttrSet );

        /** Creates the detail page for Oracle JDBC
            @param  _pParent
            @param  _rAttrSet

            @return SfxTabPage*
        */
        static SfxTabPage*  CreateOracleJDBC( Window* pParent, const SfxItemSet& _rAttrSet );

        /** Creates the detail page for Adabas
            @param  _pParent
            @param  _rAttrSet

            @return SfxTabPage*
        */
        static  SfxTabPage* CreateAdabas( Window* _pParent, const SfxItemSet& _rAttrSet );

        /** Creates the detail page for LDAP
            @param  _pParent
            @param  _rAttrSet

            @return SfxTabPage*
        */
        static  SfxTabPage* CreateLDAP( Window* _pParent, const SfxItemSet& _rAttrSet );

        /** Creates the detail page for Text
            @param  _pParent
            @param  _rAttrSet

            @return SfxTabPage*
        */
        static  SfxTabPage* CreateText( Window* _pParent, const SfxItemSet& _rAttrSet );

        /** Creates the GeneratedValues page
            @param  _pParent
            @param  _rAttrSet

            @return SfxTabPage*
        */
        static  SfxTabPage* CreateGeneratedValues( Window* _pParent, const SfxItemSet& _rAttrSet );

        /** Creates a common page with the attribute
              CBTP_USE_ENABLEOUTERJOIN
            @param  _pParent
            @param  _rAttrSet

            @return SfxTabPage*
        */
        static  SfxTabPage* CreateOJDsProperties( Window* _pParent, const SfxItemSet& _rAttrSet );

        /** Creates a common page with the attribute
              CBTP_USE_APPENDTABLEALIAS
            | CBTP_USE_BOOLEANCOMPARISON
            @param  _pParent
            @param  _rAttrSet

            @return SfxTabPage*
        */
        static  SfxTabPage* Create1DsProperties( Window* _pParent, const SfxItemSet& _rAttrSet );

        /** Creates a common page with the attribute
              CBTP_USE_SQL92CHECK
            | CBTP_USE_APPENDTABLEALIAS
            | CBTP_USE_SUPPRESS_VERSION_COLUMN
            | CBTP_USE_BOOLEANCOMPARISON
            @param  _pParent
            @param  _rAttrSet

            @return SfxTabPage*
        */
        static  SfxTabPage* Create2DsProperties( Window* _pParent, const SfxItemSet& _rAttrSet );

        /** Creates a common page with the attribute
              CBTP_USE_SQL92CHECK
            | CBTP_USE_APPENDTABLEALIAS
            | CBTP_USE_SUPPRESS_VERSION_COLUMN
            | CBTP_USE_ENABLEOUTERJOIN
            | CBTP_USE_BOOLEANCOMPARISON
            @param  _pParent
            @param  _rAttrSet

            @return SfxTabPage*
        */
        static  SfxTabPage* Create3DsProperties( Window* _pParent, const SfxItemSet& _rAttrSet );

        /** Creates a common page with the attribute
              CBTP_USE_SQL92CHECK
            | CBTP_USE_APPENDTABLEALIAS
            | CBTP_USE_BOOLEANCOMPARISON
            @param  _pParent
            @param  _rAttrSet

            @return SfxTabPage*
        */
        static  SfxTabPage* CreateFileDsProperties( Window* _pParent, const SfxItemSet& _rAttrSet );

        /** Creates a common page with the attribute
              CBTP_USE_SQL92CHECK
            | CBTP_USE_APPENDTABLEALIAS
            | CBTP_USE_ENABLEOUTERJOIN
            | CBTP_USE_BOOLEANCOMPARISON
            @param  _pParent
            @param  _rAttrSet

            @return SfxTabPage*
        */
        static  SfxTabPage* CreateAccessDsProperties( Window* _pParent, const SfxItemSet& _rAttrSet );

        /** Creates a common page with the attribute
              CBTP_USE_SQL92CHECK
            | CBTP_USE_APPENDTABLEALIAS
            | CBTP_USE_ENABLEOUTERJOIN
            | CBTP_USE_PARAMETERNAMESUBST
            | CBTP_USE_IGNOREDRIVER_PRIV
            | CBTP_USE_SUPPRESS_VERSION_COLUMN
            | CBTP_USE_BOOLEANCOMPARISON
            @param  _pParent
            @param  _rAttrSet

            @return SfxTabPage*
        */
        static  SfxTabPage* Create4DsProperties( Window* _pParent, const SfxItemSet& _rAttrSet );
    };
}

#endif // DBAUI_DRIVERSETTINGS_HXX

<commit_msg>INTEGRATION: CWS ooo19126 (1.4.114); FILE MERGED 2005/09/05 17:33:35 rt 1.4.114.1: #i54170# Change license header: remove SISSL<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: DriverSettings.hxx,v $
 *
 *  $Revision: 1.5 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-08 14:48:08 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/
#ifndef DBAUI_DRIVERSETTINGS_HXX
#define DBAUI_DRIVERSETTINGS_HXX

#ifndef _DBAUI_DSNTYPES_HXX_
#include "dsntypes.hxx"
#endif
#include <vector>

class SfxTabPage;
class Window;
namespace dbaui
{
    /// a collection class for all details a driver needs
    class ODriversSettings
    {
    public:

        /** fills the DetailIds for the given type
            @param  _eType
                The Type of the data source.
            @param  _rDetailsIds
                Will be filled.
        */
        static void fillDetailIds(DATASOURCE_TYPE _eType,::std::vector< sal_Int32>& _rDetailsIds);

        /** Creates the detail page for Dbase
            @param  _pParent
            @param  _rAttrSet

            @return SfxTabPage*
        */
        static  SfxTabPage* CreateDbase2( Window* _pParent, const SfxItemSet& _rAttrSet );

        /** Creates the detail page for ado
            @param  _pParent
            @param  _rAttrSet

            @return SfxTabPage*
        */

        static  SfxTabPage* CreateDbase( Window* _pParent, const SfxItemSet& _rAttrSet );

        /** Creates the detail page for ado
            @param  _pParent
            @param  _rAttrSet

            @return SfxTabPage*
        */
        static  SfxTabPage* CreateAdo( Window* _pParent, const SfxItemSet& _rAttrSet );

        /** Creates the detail page for ODBC
            @param  _pParent
            @param  _rAttrSet

            @return SfxTabPage*
        */
        static  SfxTabPage* CreateODBC( Window* _pParent, const SfxItemSet& _rAttrSet );

        /** Creates the detail page for user
            @param  _pParent
            @param  _rAttrSet

            @return SfxTabPage*
        */
        static  SfxTabPage* CreateUser( Window* _pParent, const SfxItemSet& _rAttrSet );

        /** Creates the detail page for MySQLODBC
            @param  _pParent
            @param  _rAttrSet

            @return SfxTabPage*
        */
        static  SfxTabPage* CreateMySQLODBC( Window* _pParent, const SfxItemSet& _rAttrSet );

        /** Creates the detail page for MySQLJDBC
            @param  _pParent
            @param  _rAttrSet

            @return SfxTabPage*
        */
        static  SfxTabPage* CreateMySQLJDBC( Window* _pParent, const SfxItemSet& _rAttrSet );

        /** Creates the detail page for Oracle JDBC
            @param  _pParent
            @param  _rAttrSet

            @return SfxTabPage*
        */
        static SfxTabPage*  CreateOracleJDBC( Window* pParent, const SfxItemSet& _rAttrSet );

        /** Creates the detail page for Adabas
            @param  _pParent
            @param  _rAttrSet

            @return SfxTabPage*
        */
        static  SfxTabPage* CreateAdabas( Window* _pParent, const SfxItemSet& _rAttrSet );

        /** Creates the detail page for LDAP
            @param  _pParent
            @param  _rAttrSet

            @return SfxTabPage*
        */
        static  SfxTabPage* CreateLDAP( Window* _pParent, const SfxItemSet& _rAttrSet );

        /** Creates the detail page for Text
            @param  _pParent
            @param  _rAttrSet

            @return SfxTabPage*
        */
        static  SfxTabPage* CreateText( Window* _pParent, const SfxItemSet& _rAttrSet );

        /** Creates the GeneratedValues page
            @param  _pParent
            @param  _rAttrSet

            @return SfxTabPage*
        */
        static  SfxTabPage* CreateGeneratedValues( Window* _pParent, const SfxItemSet& _rAttrSet );

        /** Creates a common page with the attribute
              CBTP_USE_ENABLEOUTERJOIN
            @param  _pParent
            @param  _rAttrSet

            @return SfxTabPage*
        */
        static  SfxTabPage* CreateOJDsProperties( Window* _pParent, const SfxItemSet& _rAttrSet );

        /** Creates a common page with the attribute
              CBTP_USE_APPENDTABLEALIAS
            | CBTP_USE_BOOLEANCOMPARISON
            @param  _pParent
            @param  _rAttrSet

            @return SfxTabPage*
        */
        static  SfxTabPage* Create1DsProperties( Window* _pParent, const SfxItemSet& _rAttrSet );

        /** Creates a common page with the attribute
              CBTP_USE_SQL92CHECK
            | CBTP_USE_APPENDTABLEALIAS
            | CBTP_USE_SUPPRESS_VERSION_COLUMN
            | CBTP_USE_BOOLEANCOMPARISON
            @param  _pParent
            @param  _rAttrSet

            @return SfxTabPage*
        */
        static  SfxTabPage* Create2DsProperties( Window* _pParent, const SfxItemSet& _rAttrSet );

        /** Creates a common page with the attribute
              CBTP_USE_SQL92CHECK
            | CBTP_USE_APPENDTABLEALIAS
            | CBTP_USE_SUPPRESS_VERSION_COLUMN
            | CBTP_USE_ENABLEOUTERJOIN
            | CBTP_USE_BOOLEANCOMPARISON
            @param  _pParent
            @param  _rAttrSet

            @return SfxTabPage*
        */
        static  SfxTabPage* Create3DsProperties( Window* _pParent, const SfxItemSet& _rAttrSet );

        /** Creates a common page with the attribute
              CBTP_USE_SQL92CHECK
            | CBTP_USE_APPENDTABLEALIAS
            | CBTP_USE_BOOLEANCOMPARISON
            @param  _pParent
            @param  _rAttrSet

            @return SfxTabPage*
        */
        static  SfxTabPage* CreateFileDsProperties( Window* _pParent, const SfxItemSet& _rAttrSet );

        /** Creates a common page with the attribute
              CBTP_USE_SQL92CHECK
            | CBTP_USE_APPENDTABLEALIAS
            | CBTP_USE_ENABLEOUTERJOIN
            | CBTP_USE_BOOLEANCOMPARISON
            @param  _pParent
            @param  _rAttrSet

            @return SfxTabPage*
        */
        static  SfxTabPage* CreateAccessDsProperties( Window* _pParent, const SfxItemSet& _rAttrSet );

        /** Creates a common page with the attribute
              CBTP_USE_SQL92CHECK
            | CBTP_USE_APPENDTABLEALIAS
            | CBTP_USE_ENABLEOUTERJOIN
            | CBTP_USE_PARAMETERNAMESUBST
            | CBTP_USE_IGNOREDRIVER_PRIV
            | CBTP_USE_SUPPRESS_VERSION_COLUMN
            | CBTP_USE_BOOLEANCOMPARISON
            @param  _pParent
            @param  _rAttrSet

            @return SfxTabPage*
        */
        static  SfxTabPage* Create4DsProperties( Window* _pParent, const SfxItemSet& _rAttrSet );
    };
}

#endif // DBAUI_DRIVERSETTINGS_HXX

<|endoftext|>


<commit_before>/**
 * Copyright (C) 2011 - present by OpenGamma Inc. and the OpenGamma group of companies
 *
 * Please see distribution for license.
 */

#include "stdafx.h"

// Test the functions and objects in Connector/Connector.cpp

#include "Connector/Connector.h"
#define FUDGE_NO_NAMESPACE
#include "Connector/com_opengamma_language_connector_Test.h"

LOGGING (com.opengamma.language.connector.ConnectorTest);

#define TEST_LANGUAGE		TEXT ("test")
#define TIMEOUT_STARTUP		30000
#define TIMEOUT_CALL		3000
#ifdef TIMEOUT_ASYNC
#undef TIMEOUT_ASYNC
#endif /* ifdef TIMEOUT_ASYNC */
#define TIMEOUT_ASYNC		1000

class CTestMessageCallback : public CConnector::CCallback {
private:
	CSemaphore m_oSemaphore;
	CMutex m_oMutex;
	FudgeMsg m_msg;
	int m_nMessages;
	int m_nDisconnects;
protected:
	void OnMessage (FudgeMsg msgPayload) {
		LOGDEBUG (TEXT ("Message received"));
		m_oMutex.Enter ();
		if (m_msg) {
			FudgeMsg_release (m_msg);
		}
		m_msg = msgPayload;
		FudgeMsg_retain (m_msg);
		m_nMessages++;
		m_oMutex.Leave ();
		m_oSemaphore.Signal ();
	}
	void OnThreadDisconnect () {
		LOGDEBUG (TEXT ("Callback thread disconnected"));
		m_oMutex.Enter ();
		m_nDisconnects++;
		m_oMutex.Leave ();
	}
public:
	CTestMessageCallback () : CCallback () {
		m_msg = NULL;
		m_nMessages = 0;
		m_nDisconnects = 0;
	}
	~CTestMessageCallback () {
		LOGDEBUG (TEXT ("Callback object destroyed"));
		if (m_msg) {
			FudgeMsg_release (m_msg);
		}
	}
	bool WaitForMessage (FudgeMsg *pmsg) {
		if (!m_oSemaphore.Wait (TIMEOUT_ASYNC)) {
			LOGDEBUG (TEXT ("Timeout waiting for message"));
			return false;
		}
		bool bResult;
		m_oMutex.Enter ();
		if (m_msg) {
			*pmsg = m_msg;
			FudgeMsg_retain (m_msg);
			bResult = true;
		} else {
			bResult = false;
		}
		m_oMutex.Leave ();
		return bResult;
	}
	bool Disconnected () {
		LOGDEBUG (TEXT ("messages=") << m_nMessages << TEXT (", disconnects=") << m_nDisconnects);
		if (m_nMessages > 0) {
			return m_nDisconnects == 1;
		} else {
			return m_nDisconnects == 0;
		}
	}
};

static CConnector *g_poConnector;
static fudge_i32 g_nonce;
static CTestMessageCallback *g_poCallback;

static void StartConnector () {
	g_poConnector = CConnector::Start (TEST_LANGUAGE);
	ASSERT (g_poConnector);
	ASSERT (g_poConnector->WaitForStartup (TIMEOUT_STARTUP));
	g_poCallback = new CTestMessageCallback ();
	ASSERT (g_poConnector->AddCallback (Test_Class, g_poCallback));
	g_nonce = (fudge_i32)GetTickCount ();
}

static void StopConnector () {
	ASSERT (g_poConnector->Stop ());
	CConnector::Release (g_poConnector);
	g_poConnector = NULL;
	int n;
	for (n = 0; !g_poCallback->Disconnected () && (n < 10); n++) {
		LOGDEBUG (TEXT ("Waiting for disconnect to propogate"));
		CThread::Sleep (TIMEOUT_CALL / 10);
	}
	ASSERT (g_poCallback->Disconnected ());
	CConnector::CCallback::Release (g_poCallback);
}

static void CreateTestMessage (FudgeMsg *pmsg, Operation operation) {
	Test test;
	memset (&test, 0, sizeof (test));
	test._operation = operation;
	test._nonce = g_nonce;
	ASSERT (Test_toFudgeMsg (&test, pmsg) == FUDGE_OK);
}

static void CheckTestResponse (FudgeMsg msg, Operation operation) {
	Test *ptest;
	ASSERT (Test_fromFudgeMsg (msg, &ptest) == FUDGE_OK);
	ASSERT (ptest);
	ASSERT (ptest->_operation == operation);
	ASSERT (ptest->_nonce == g_nonce);
	free (ptest);
}

static void StartStop () {
	// No-op; the fun is in the StartConnector and StopConnector methods
}

static void SyncCall (int nTimeoutFactor = 1) {
	FudgeMsg msgToSend;
	FudgeMsg msgReceived;
	CreateTestMessage (&msgToSend, ECHO_REQUEST);
	ASSERT (g_poConnector->Call (msgToSend, &msgReceived, nTimeoutFactor * TIMEOUT_CALL));
	ASSERT (msgReceived);
	CheckTestResponse (msgReceived, ECHO_RESPONSE);
	FudgeMsg_release (msgReceived);
	ASSERT (!g_poCallback->WaitForMessage (&msgReceived));
	FudgeMsg_release (msgToSend);
}

static void AsyncCall () {
	FudgeMsg msgToSend;
	CreateTestMessage (&msgToSend, VOID_REQUEST);
	ASSERT (g_poConnector->Send (msgToSend));
	// Pause to allow the client to deliver or we see weird things happening in the log (e.g. it poisons itself before processing the message)
	CThread::Sleep (TIMEOUT_ASYNC);
	FudgeMsg_release (msgToSend);
	ASSERT (!g_poCallback->WaitForMessage (&msgToSend));
}

static void SyncCallWithAsyncCallback () {
	FudgeMsg msgToSend;
	FudgeMsg msgReceived;
	CreateTestMessage (&msgToSend, ECHO_REQUEST_A);
	ASSERT (g_poConnector->Call (msgToSend, &msgReceived, TIMEOUT_CALL));
	ASSERT (msgReceived);
	CheckTestResponse (msgReceived, ECHO_RESPONSE);
	FudgeMsg_release (msgReceived);
	ASSERT (g_poCallback->WaitForMessage (&msgReceived));
	CheckTestResponse (msgReceived, ECHO_RESPONSE_A);
	FudgeMsg_release (msgReceived);
	FudgeMsg_release (msgToSend);
}

static void AsyncCallWithAsyncCallback () {
	FudgeMsg msgToSend;
	FudgeMsg msgReceived;
	CreateTestMessage (&msgToSend, VOID_REQUEST_A);
	ASSERT (g_poConnector->Send (msgToSend));
	ASSERT (g_poCallback->WaitForMessage (&msgReceived));
	CheckTestResponse (msgReceived, VOID_RESPONSE_A);
	FudgeMsg_release (msgReceived);
	FudgeMsg_release (msgToSend);
	// Check explicit callback unregistration
	ASSERT (!g_poCallback->Disconnected ());
	ASSERT (g_poConnector->RemoveCallback (g_poCallback));
}

static void JVMCrash () {
	FudgeMsg msgToSend;
	FudgeMsg msgReceived;
	CreateTestMessage (&msgToSend, CRASH_REQUEST);
	unsigned long tStart = GetTickCount ();
	ASSERT (!g_poConnector->Call (msgToSend, &msgReceived, 2 * TIMEOUT_CALL));
	unsigned long tEnd = GetTickCount ();
	// If all is good, the JVM will have crashed quickly and the call was aborted before the timeout
	ASSERT (tEnd - tStart < TIMEOUT_CALL);
	FudgeMsg_release (msgToSend);
	// And now it should be operational again
	SyncCall (3);
}

static void JVMHang () {
	FudgeMsg msgToSend;
	FudgeMsg msgReceived;
	CreateTestMessage (&msgToSend, PAUSE_REQUEST);
	unsigned long tStart = GetTickCount ();
	ASSERT (!g_poConnector->Call (msgToSend, &msgReceived, 4 * TIMEOUT_CALL));
	unsigned long tEnd = GetTickCount ();
	// If all is good, the JVM will have stopped beating and we aborted the call before the timeout
	ASSERT (tEnd - tStart < 3 * TIMEOUT_CALL);
	FudgeMsg_release (msgToSend);
	// And now it should be operational again
	SyncCall (4);
}

BEGIN_TESTS (ConnectorTest)
	TEST (StartStop)
	TEST (SyncCall)
	TEST (AsyncCall)
	TEST (SyncCallWithAsyncCallback)
	TEST (AsyncCallWithAsyncCallback)
	TEST (JVMCrash)
	TEST (JVMHang)
	BEFORE_TEST (StartConnector)
	AFTER_TEST (StopConnector)
END_TESTS
<commit_msg>Increase timeout to full startup allowance when recovering from a JVM crash.<commit_after>/**
 * Copyright (C) 2011 - present by OpenGamma Inc. and the OpenGamma group of companies
 *
 * Please see distribution for license.
 */

#include "stdafx.h"

// Test the functions and objects in Connector/Connector.cpp

#include "Connector/Connector.h"
#define FUDGE_NO_NAMESPACE
#include "Connector/com_opengamma_language_connector_Test.h"

LOGGING (com.opengamma.language.connector.ConnectorTest);

#define TEST_LANGUAGE		TEXT ("test")
#define TIMEOUT_STARTUP		30000
#define TIMEOUT_CALL		3000
#ifdef TIMEOUT_ASYNC
#undef TIMEOUT_ASYNC
#endif /* ifdef TIMEOUT_ASYNC */
#define TIMEOUT_ASYNC		1000

class CTestMessageCallback : public CConnector::CCallback {
private:
	CSemaphore m_oSemaphore;
	CMutex m_oMutex;
	FudgeMsg m_msg;
	int m_nMessages;
	int m_nDisconnects;
protected:
	void OnMessage (FudgeMsg msgPayload) {
		LOGDEBUG (TEXT ("Message received"));
		m_oMutex.Enter ();
		if (m_msg) {
			FudgeMsg_release (m_msg);
		}
		m_msg = msgPayload;
		FudgeMsg_retain (m_msg);
		m_nMessages++;
		m_oMutex.Leave ();
		m_oSemaphore.Signal ();
	}
	void OnThreadDisconnect () {
		LOGDEBUG (TEXT ("Callback thread disconnected"));
		m_oMutex.Enter ();
		m_nDisconnects++;
		m_oMutex.Leave ();
	}
public:
	CTestMessageCallback () : CCallback () {
		m_msg = NULL;
		m_nMessages = 0;
		m_nDisconnects = 0;
	}
	~CTestMessageCallback () {
		LOGDEBUG (TEXT ("Callback object destroyed"));
		if (m_msg) {
			FudgeMsg_release (m_msg);
		}
	}
	bool WaitForMessage (FudgeMsg *pmsg) {
		if (!m_oSemaphore.Wait (TIMEOUT_ASYNC)) {
			LOGDEBUG (TEXT ("Timeout waiting for message"));
			return false;
		}
		bool bResult;
		m_oMutex.Enter ();
		if (m_msg) {
			*pmsg = m_msg;
			FudgeMsg_retain (m_msg);
			bResult = true;
		} else {
			bResult = false;
		}
		m_oMutex.Leave ();
		return bResult;
	}
	bool Disconnected () {
		LOGDEBUG (TEXT ("messages=") << m_nMessages << TEXT (", disconnects=") << m_nDisconnects);
		if (m_nMessages > 0) {
			return m_nDisconnects == 1;
		} else {
			return m_nDisconnects == 0;
		}
	}
};

static CConnector *g_poConnector;
static fudge_i32 g_nonce;
static CTestMessageCallback *g_poCallback;

static void StartConnector () {
	g_poConnector = CConnector::Start (TEST_LANGUAGE);
	ASSERT (g_poConnector);
	ASSERT (g_poConnector->WaitForStartup (TIMEOUT_STARTUP));
	g_poCallback = new CTestMessageCallback ();
	ASSERT (g_poConnector->AddCallback (Test_Class, g_poCallback));
	g_nonce = (fudge_i32)GetTickCount ();
}

static void StopConnector () {
	ASSERT (g_poConnector->Stop ());
	CConnector::Release (g_poConnector);
	g_poConnector = NULL;
	int n;
	for (n = 0; !g_poCallback->Disconnected () && (n < 10); n++) {
		LOGDEBUG (TEXT ("Waiting for disconnect to propogate"));
		CThread::Sleep (TIMEOUT_CALL / 10);
	}
	ASSERT (g_poCallback->Disconnected ());
	CConnector::CCallback::Release (g_poCallback);
}

static void CreateTestMessage (FudgeMsg *pmsg, Operation operation) {
	Test test;
	memset (&test, 0, sizeof (test));
	test._operation = operation;
	test._nonce = g_nonce;
	ASSERT (Test_toFudgeMsg (&test, pmsg) == FUDGE_OK);
}

static void CheckTestResponse (FudgeMsg msg, Operation operation) {
	Test *ptest;
	ASSERT (Test_fromFudgeMsg (msg, &ptest) == FUDGE_OK);
	ASSERT (ptest);
	ASSERT (ptest->_operation == operation);
	ASSERT (ptest->_nonce == g_nonce);
	free (ptest);
}

static void StartStop () {
	// No-op; the fun is in the StartConnector and StopConnector methods
}

static void SyncCall (long lTimeout = TIMEOUT_CALL) {
	FudgeMsg msgToSend;
	FudgeMsg msgReceived;
	CreateTestMessage (&msgToSend, ECHO_REQUEST);
	ASSERT (g_poConnector->Call (msgToSend, &msgReceived, lTimeout));
	ASSERT (msgReceived);
	CheckTestResponse (msgReceived, ECHO_RESPONSE);
	FudgeMsg_release (msgReceived);
	ASSERT (!g_poCallback->WaitForMessage (&msgReceived));
	FudgeMsg_release (msgToSend);
}

static void AsyncCall () {
	FudgeMsg msgToSend;
	CreateTestMessage (&msgToSend, VOID_REQUEST);
	ASSERT (g_poConnector->Send (msgToSend));
	// Pause to allow the client to deliver or we see weird things happening in the log (e.g. it poisons itself before processing the message)
	CThread::Sleep (TIMEOUT_ASYNC);
	FudgeMsg_release (msgToSend);
	ASSERT (!g_poCallback->WaitForMessage (&msgToSend));
}

static void SyncCallWithAsyncCallback () {
	FudgeMsg msgToSend;
	FudgeMsg msgReceived;
	CreateTestMessage (&msgToSend, ECHO_REQUEST_A);
	ASSERT (g_poConnector->Call (msgToSend, &msgReceived, TIMEOUT_CALL));
	ASSERT (msgReceived);
	CheckTestResponse (msgReceived, ECHO_RESPONSE);
	FudgeMsg_release (msgReceived);
	ASSERT (g_poCallback->WaitForMessage (&msgReceived));
	CheckTestResponse (msgReceived, ECHO_RESPONSE_A);
	FudgeMsg_release (msgReceived);
	FudgeMsg_release (msgToSend);
}

static void AsyncCallWithAsyncCallback () {
	FudgeMsg msgToSend;
	FudgeMsg msgReceived;
	CreateTestMessage (&msgToSend, VOID_REQUEST_A);
	ASSERT (g_poConnector->Send (msgToSend));
	ASSERT (g_poCallback->WaitForMessage (&msgReceived));
	CheckTestResponse (msgReceived, VOID_RESPONSE_A);
	FudgeMsg_release (msgReceived);
	FudgeMsg_release (msgToSend);
	// Check explicit callback unregistration
	ASSERT (!g_poCallback->Disconnected ());
	ASSERT (g_poConnector->RemoveCallback (g_poCallback));
}

static void JVMCrash () {
	FudgeMsg msgToSend;
	FudgeMsg msgReceived;
	CreateTestMessage (&msgToSend, CRASH_REQUEST);
	unsigned long tStart = GetTickCount ();
	ASSERT (!g_poConnector->Call (msgToSend, &msgReceived, 2 * TIMEOUT_CALL));
	unsigned long tEnd = GetTickCount ();
	// If all is good, the JVM will have crashed quickly and the call was aborted before the timeout
	ASSERT (tEnd - tStart < TIMEOUT_CALL);
	FudgeMsg_release (msgToSend);
	// And now it should be operational again
	SyncCall (TIMEOUT_STARTUP);
}

static void JVMHang () {
	FudgeMsg msgToSend;
	FudgeMsg msgReceived;
	CreateTestMessage (&msgToSend, PAUSE_REQUEST);
	unsigned long tStart = GetTickCount ();
	ASSERT (!g_poConnector->Call (msgToSend, &msgReceived, 4 * TIMEOUT_CALL));
	unsigned long tEnd = GetTickCount ();
	// If all is good, the JVM will have stopped beating and we aborted the call before the timeout
	ASSERT (tEnd - tStart < 3 * TIMEOUT_CALL);
	FudgeMsg_release (msgToSend);
	// And now it should be operational again
	SyncCall (TIMEOUT_STARTUP);
}

BEGIN_TESTS (ConnectorTest)
	TEST (StartStop)
	TEST (SyncCall)
	TEST (AsyncCall)
	TEST (SyncCallWithAsyncCallback)
	TEST (AsyncCallWithAsyncCallback)
	TEST (JVMCrash)
	TEST (JVMHang)
	BEFORE_TEST (StartConnector)
	AFTER_TEST (StopConnector)
END_TESTS
<|endoftext|>


<commit_before>#include "drake/systems/framework/named_value_vector.h"

#include <map>
#include <memory>
#include <stdexcept>
#include <vector>

#include "drake/drakeSystemFramework_export.h"
#include "drake/util/eigen_matrix_compare.h"

#include <Eigen/Dense>
#include "gtest/gtest.h"
#include "gmock/gmock.h"

namespace drake {
namespace systems {
namespace {

GTEST_TEST(NamedValueVectorTest, Access) {
  NamedValueVector<int> vector(
      std::vector<std::pair<std::string, int>>{{"foo", 1}, {"bar", 2}});
  EXPECT_EQ(1, *vector.get_named_value("foo"));
  EXPECT_EQ(2, *vector.get_named_value("bar"));
  Eigen::Matrix<int, 2, 1> expected;
  expected << 1, 2;
  const double tolerance = 1e-6;
  EXPECT_TRUE(CompareMatrices(vector.get_value(), expected, tolerance,
                              util::MatrixCompareType::absolute));
}

GTEST_TEST(NamedValueVectorTest, Set) {
  NamedValueVector<int> vector(
      std::vector<std::pair<std::string, int>>{{"foo", 1}, {"bar", 2}});
  vector.set_named_value("bar", 5);
  EXPECT_EQ(1, *vector.get_named_value("foo"));
  EXPECT_EQ(5, *vector.get_named_value("bar"));
}

// Tests that setting a name that doesn't exist throws an exception.
GTEST_TEST(NamedValueVectorTest, SetInvalidKey) {
  NamedValueVector<int> vector(
      std::vector<std::pair<std::string, int>>{{"foo", 1}, {"bar", 2}});
  EXPECT_THROW(vector.set_named_value("baz", 5), std::runtime_error);
}

// Tests that getting a name that doesn't exist returns nullptr.
GTEST_TEST(NamedValueVectorTest, GetInvalidKey) {
  NamedValueVector<int> vector(
      std::vector<std::pair<std::string, int>>{{"foo", 1}, {"bar", 2}});
  EXPECT_EQ(nullptr, vector.get_named_value("baz"));
}

GTEST_TEST(NamedValueVectorTest, Mutate) {
  NamedValueVector<int> vector(
      std::vector<std::pair<std::string, int>>{{"foo", 1}, {"bar", 2}});
  vector.get_mutable_value()(1) = 6;
  EXPECT_EQ(1, *vector.get_named_value("foo"));
  EXPECT_EQ(6, *vector.get_named_value("bar"));
}

GTEST_TEST(NamedValueVectorTest, SetWholeVector) {
  NamedValueVector<int> vector(
      std::vector<std::pair<std::string, int>>{{"foo", 1}, {"bar", 2}});
  Eigen::Matrix<int, 2, 1> next_value;
  next_value << 3, 4;
  vector.set_value(next_value);
  EXPECT_EQ(3, *vector.get_named_value("foo"));
  EXPECT_EQ(4, *vector.get_named_value("bar"));
}

// Tests that an error is thrown when the NamedValueVector is set to a vector
// of a different size.
GTEST_TEST(NamedValueVectorTest, ReinitializeInvalid) {
  NamedValueVector<int> vector(
      std::vector<std::pair<std::string, int>>{{"foo", 1}, {"bar", 2}});
  Eigen::Matrix<int, 3, 1> next_value;
  next_value << 3, 4, 5;
  EXPECT_THROW(vector.set_value(next_value), std::runtime_error);
}

// Tests that an error is thrown when there are multiple identically
// named elements.
GTEST_TEST(NamedValueVectorTest, InvalidNames) {
  std::unique_ptr<NamedValueVector<int>> vector;
  EXPECT_THROW(vector.reset(new NamedValueVector<int>(
                   std::vector<std::string>{"foo", "foo"})),
               std::runtime_error);
}

}  // namespace
}  // namespace systems
}  // namespace drake
<commit_msg>Stop using CompareMatrices, which is overkill for integer matrices and doesn't even compile with <int> on Windows.<commit_after>#include "drake/systems/framework/named_value_vector.h"

#include <map>
#include <memory>
#include <stdexcept>
#include <vector>

#include "drake/drakeSystemFramework_export.h"

#include <Eigen/Dense>
#include "gtest/gtest.h"
#include "gmock/gmock.h"

namespace drake {
namespace systems {
namespace {

GTEST_TEST(NamedValueVectorTest, Access) {
  NamedValueVector<int> vector(
      std::vector<std::pair<std::string, int>>{{"foo", 1}, {"bar", 2}});
  EXPECT_EQ(1, *vector.get_named_value("foo"));
  EXPECT_EQ(2, *vector.get_named_value("bar"));
  Eigen::Matrix<int, 2, 1> expected;
  expected << 1, 2;
  const double tolerance = 1e-6;
  EXPECT_EQ(expected, vector.get_value());
}

GTEST_TEST(NamedValueVectorTest, Set) {
  NamedValueVector<int> vector(
      std::vector<std::pair<std::string, int>>{{"foo", 1}, {"bar", 2}});
  vector.set_named_value("bar", 5);
  EXPECT_EQ(1, *vector.get_named_value("foo"));
  EXPECT_EQ(5, *vector.get_named_value("bar"));
}

// Tests that setting a name that doesn't exist throws an exception.
GTEST_TEST(NamedValueVectorTest, SetInvalidKey) {
  NamedValueVector<int> vector(
      std::vector<std::pair<std::string, int>>{{"foo", 1}, {"bar", 2}});
  EXPECT_THROW(vector.set_named_value("baz", 5), std::runtime_error);
}

// Tests that getting a name that doesn't exist returns nullptr.
GTEST_TEST(NamedValueVectorTest, GetInvalidKey) {
  NamedValueVector<int> vector(
      std::vector<std::pair<std::string, int>>{{"foo", 1}, {"bar", 2}});
  EXPECT_EQ(nullptr, vector.get_named_value("baz"));
}

GTEST_TEST(NamedValueVectorTest, Mutate) {
  NamedValueVector<int> vector(
      std::vector<std::pair<std::string, int>>{{"foo", 1}, {"bar", 2}});
  vector.get_mutable_value()(1) = 6;
  EXPECT_EQ(1, *vector.get_named_value("foo"));
  EXPECT_EQ(6, *vector.get_named_value("bar"));
}

GTEST_TEST(NamedValueVectorTest, SetWholeVector) {
  NamedValueVector<int> vector(
      std::vector<std::pair<std::string, int>>{{"foo", 1}, {"bar", 2}});
  Eigen::Matrix<int, 2, 1> next_value;
  next_value << 3, 4;
  vector.set_value(next_value);
  EXPECT_EQ(3, *vector.get_named_value("foo"));
  EXPECT_EQ(4, *vector.get_named_value("bar"));
}

// Tests that an error is thrown when the NamedValueVector is set to a vector
// of a different size.
GTEST_TEST(NamedValueVectorTest, ReinitializeInvalid) {
  NamedValueVector<int> vector(
      std::vector<std::pair<std::string, int>>{{"foo", 1}, {"bar", 2}});
  Eigen::Matrix<int, 3, 1> next_value;
  next_value << 3, 4, 5;
  EXPECT_THROW(vector.set_value(next_value), std::runtime_error);
}

// Tests that an error is thrown when there are multiple identically
// named elements.
GTEST_TEST(NamedValueVectorTest, InvalidNames) {
  std::unique_ptr<NamedValueVector<int>> vector;
  EXPECT_THROW(vector.reset(new NamedValueVector<int>(
                   std::vector<std::string>{"foo", "foo"})),
               std::runtime_error);
}

}  // namespace
}  // namespace systems
}  // namespace drake
<|endoftext|>


<commit_before>/*
-----------------------------------------------------------------------------
This source file is part of OGRE
    (Object-oriented Graphics Rendering Engine)
For the latest info, see http://www.ogre3d.org/

Copyright (c) 2000-2009 Torus Knot Software Ltd

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 "OgreStableHeaders.h"

#include "OgreMovableObject.h"
#include "OgreSceneNode.h"
#include "OgreTagPoint.h"
#include "OgreLight.h"
#include "OgreEntity.h"
#include "OgreRoot.h"
#include "OgreSceneManager.h"
#include "OgreCamera.h"
#include "OgreLodListener.h"

namespace Ogre {
	//-----------------------------------------------------------------------
	//-----------------------------------------------------------------------
	uint32 MovableObject::msDefaultQueryFlags = 0xFFFFFFFF;
	uint32 MovableObject::msDefaultVisibilityFlags = 0xFFFFFFFF;
    //-----------------------------------------------------------------------
    MovableObject::MovableObject()
        : mCreator(0)
        , mManager(0)
        , mParentNode(0)
        , mParentIsTagPoint(false)
        , mVisible(true)
		, mDebugDisplay(false)
        , mUpperDistance(0)
        , mSquaredUpperDistance(0)
        , mBeyondFarDistance(false)
        , mRenderQueueID(RENDER_QUEUE_MAIN)
        , mRenderQueueIDSet(false)
        , mQueryFlags(msDefaultQueryFlags)
        , mVisibilityFlags(msDefaultVisibilityFlags)
        , mCastShadows(true)
        , mRenderingDisabled(false)
        , mListener(0)
        , mLightListUpdated(0)
		, mLightMask(0xFFFFFFFF)
    {
    }
    //-----------------------------------------------------------------------
    MovableObject::MovableObject(const String& name)
        : mName(name)
        , mCreator(0)
        , mManager(0)
        , mParentNode(0)
        , mParentIsTagPoint(false)
        , mVisible(true)
		, mDebugDisplay(false)
        , mUpperDistance(0)
        , mSquaredUpperDistance(0)
        , mBeyondFarDistance(false)
        , mRenderQueueID(RENDER_QUEUE_MAIN)
        , mRenderQueueIDSet(false)
        , mQueryFlags(msDefaultQueryFlags)
        , mVisibilityFlags(msDefaultVisibilityFlags)
        , mCastShadows(true)
        , mRenderingDisabled(false)
        , mListener(0)
        , mLightListUpdated(0)
		, mLightMask(0xFFFFFFFF)
    {
    }
    //-----------------------------------------------------------------------
    MovableObject::~MovableObject()
    {
        // Call listener (note, only called if there's something to do)
        if (mListener)
        {
            mListener->objectDestroyed(this);
        }

        if (mParentNode)
        {
            // detach from parent
            if (mParentIsTagPoint)
            {
                // May be we are a lod entity which not in the parent entity child object list,
                // call this method could safely ignore this case.
                static_cast<TagPoint*>(mParentNode)->getParentEntity()->detachObjectFromBone(this);
            }
            else
            {
                // May be we are a lod entity which not in the parent node child object list,
                // call this method could safely ignore this case.
                static_cast<SceneNode*>(mParentNode)->detachObject(this);
            }
        }
    }
    //-----------------------------------------------------------------------
    void MovableObject::_notifyAttached(Node* parent, bool isTagPoint)
    {
        assert(!mParentNode || !parent);

        bool different = (parent != mParentNode);

        mParentNode = parent;
        mParentIsTagPoint = isTagPoint;

        // Mark light list being dirty, simply decrease
        // counter by one for minimise overhead
        --mLightListUpdated;

        // Call listener (note, only called if there's something to do)
        if (mListener && different)
        {
            if (mParentNode)
                mListener->objectAttached(this);
            else
                mListener->objectDetached(this);
        }
    }
    //-----------------------------------------------------------------------
    Node* MovableObject::getParentNode(void) const
    {
        return mParentNode;
    }
    //-----------------------------------------------------------------------
    SceneNode* MovableObject::getParentSceneNode(void) const
    {
        if (mParentIsTagPoint)
        {
            TagPoint* tp = static_cast<TagPoint*>(mParentNode);
            return tp->getParentEntity()->getParentSceneNode();
        }
        else
        {
            return static_cast<SceneNode*>(mParentNode);
        }
    }
    //-----------------------------------------------------------------------
    bool MovableObject::isAttached(void) const
    {
        return (mParentNode != 0);

    }
	//---------------------------------------------------------------------
	void MovableObject::detachFromParent(void)
	{
		if (isAttached())
		{
			if (mParentIsTagPoint)
			{
				TagPoint* tp = static_cast<TagPoint*>(mParentNode);
				tp->getParentEntity()->detachObjectFromBone(this);
			}
			else
			{
				SceneNode* sn = static_cast<SceneNode*>(mParentNode);
				sn->detachObject(this);
			}
		}
	}
    //-----------------------------------------------------------------------
	bool MovableObject::isInScene(void) const
	{
		if (mParentNode != 0)
		{
			if (mParentIsTagPoint)
			{
				TagPoint* tp = static_cast<TagPoint*>(mParentNode);
				return tp->getParentEntity()->isInScene();
			}
			else
			{
				SceneNode* sn = static_cast<SceneNode*>(mParentNode);
				return sn->isInSceneGraph();
			}
		}
		else
		{
			return false;
		}
	}
    //-----------------------------------------------------------------------
    void MovableObject::_notifyMoved(void)
    {
        // Mark light list being dirty, simply decrease
        // counter by one for minimise overhead
        --mLightListUpdated;

        // Notify listener if exists
        if (mListener)
        {
            mListener->objectMoved(this);
        }
    }
    //-----------------------------------------------------------------------
    void MovableObject::setVisible(bool visible)
    {
        mVisible = visible;
    }
    //-----------------------------------------------------------------------
    bool MovableObject::getVisible(void) const
    {
        return mVisible;
    }
    //-----------------------------------------------------------------------
    bool MovableObject::isVisible(void) const
    {
        if (!mVisible || mBeyondFarDistance || mRenderingDisabled)
            return false;

        SceneManager* sm = Root::getSingleton()._getCurrentSceneManager();
        if (sm && !(getVisibilityFlags() & sm->_getCombinedVisibilityMask()))
            return false;

        return true;
    }
	//-----------------------------------------------------------------------
	void MovableObject::_notifyCurrentCamera(Camera* cam)
	{
		if (mParentNode)
		{
			if (cam->getUseRenderingDistance() && mUpperDistance > 0)
			{
				Real rad = getBoundingRadius();
				Real squaredDepth = mParentNode->getSquaredViewDepth(cam->getLodCamera());
				// Max distance to still render
				Real maxDist = mUpperDistance + rad;
				if (squaredDepth > Math::Sqr(maxDist))
				{
					mBeyondFarDistance = true;
				}
				else
				{
					mBeyondFarDistance = false;
				}
			}
			else
			{
				mBeyondFarDistance = false;
			}

            // Construct event object
            MovableObjectLodChangedEvent evt;
            evt.movableObject = this;
            evt.camera = cam;

            // Notify lod event listeners
            cam->getSceneManager()->_notifyMovableObjectLodChanged(evt);

		}

        mRenderingDisabled = mListener && !mListener->objectRendering(this, cam);
	}
    //-----------------------------------------------------------------------
    void MovableObject::setRenderQueueGroup(uint8 queueID)
    {
		assert(queueID <= RENDER_QUEUE_MAX && "Render queue out of range!");
        mRenderQueueID = queueID;
        mRenderQueueIDSet = true;
    }
    //-----------------------------------------------------------------------
    uint8 MovableObject::getRenderQueueGroup(void) const
    {
        return mRenderQueueID;
    }
    //-----------------------------------------------------------------------
	const Matrix4& MovableObject::_getParentNodeFullTransform(void) const
	{

		if(mParentNode)
		{
			// object attached to a sceneNode
			return mParentNode->_getFullTransform();
		}
        // fallback
        return Matrix4::IDENTITY;
	}
    //-----------------------------------------------------------------------
    const AxisAlignedBox& MovableObject::getWorldBoundingBox(bool derive) const
    {
        if (derive)
        {
            mWorldAABB = this->getBoundingBox();
            mWorldAABB.transformAffine(_getParentNodeFullTransform());
        }

        return mWorldAABB;

    }
    //-----------------------------------------------------------------------
	const Sphere& MovableObject::getWorldBoundingSphere(bool derive) const
	{
		if (derive)
		{
			mWorldBoundingSphere.setRadius(getBoundingRadius());
			mWorldBoundingSphere.setCenter(mParentNode->_getDerivedPosition());
		}
		return mWorldBoundingSphere;
	}
    //-----------------------------------------------------------------------
    const LightList& MovableObject::queryLights(void) const
    {
        // Try listener first
        if (mListener)
        {
            const LightList* lightList =
                mListener->objectQueryLights(this);
            if (lightList)
            {
                return *lightList;
            }
        }

        // Query from parent entity if exists
        if (mParentIsTagPoint)
        {
            TagPoint* tp = static_cast<TagPoint*>(mParentNode);
            return tp->getParentEntity()->queryLights();
        }

        if (mParentNode)
        {
            SceneNode* sn = static_cast<SceneNode*>(mParentNode);

            // Make sure we only update this only if need.
            ulong frame = sn->getCreator()->_getLightsDirtyCounter();
            if (mLightListUpdated != frame)
            {
                mLightListUpdated = frame;

                sn->findLights(mLightList, this->getBoundingRadius(), this->getLightMask());
            }
        }
        else
        {
            mLightList.clear();
        }

        return mLightList;
    }
    //-----------------------------------------------------------------------
    ShadowCaster::ShadowRenderableListIterator MovableObject::getShadowVolumeRenderableIterator(
        ShadowTechnique shadowTechnique, const Light* light,
        HardwareIndexBufferSharedPtr* indexBuffer,
        bool extrudeVertices, Real extrusionDist, unsigned long flags )
    {
        static ShadowRenderableList dummyList;
        return ShadowRenderableListIterator(dummyList.begin(), dummyList.end());
    }
    //-----------------------------------------------------------------------
    const AxisAlignedBox& MovableObject::getLightCapBounds(void) const
    {
        // Same as original bounds
        return getWorldBoundingBox();
    }
    //-----------------------------------------------------------------------
    const AxisAlignedBox& MovableObject::getDarkCapBounds(const Light& light, Real extrusionDist) const
    {
        // Extrude own light cap bounds
        mWorldDarkCapBounds = getLightCapBounds();
        this->extrudeBounds(mWorldDarkCapBounds, light.getAs4DVector(),
            extrusionDist);
        return mWorldDarkCapBounds;

    }
    //-----------------------------------------------------------------------
    Real MovableObject::getPointExtrusionDistance(const Light* l) const
    {
        if (mParentNode)
        {
            return getExtrusionDistance(mParentNode->_getDerivedPosition(), l);
        }
        else
        {
            return 0;
        }
    }
	//-----------------------------------------------------------------------
	uint32 MovableObject::getTypeFlags(void) const
	{
		if (mCreator)
		{
			return mCreator->getTypeFlags();
		}
		else
		{
			return 0xFFFFFFFF;
		}
	}
	//---------------------------------------------------------------------
	void MovableObject::setLightMask(uint32 lightMask)
	{
		this->mLightMask = lightMask;
		//make sure to request a new light list from the scene manager if mask changed
		mLightListUpdated = 0;
	}
	//---------------------------------------------------------------------
	class MORecvShadVisitor : public Renderable::Visitor
	{
	public:
		bool anyReceiveShadows;
		MORecvShadVisitor() : anyReceiveShadows(false)
		{

		}
		void visit(Renderable* rend, ushort lodIndex, bool isDebug,
			Any* pAny = 0)
		{
			Technique* tech = rend->getTechnique();
			bool techReceivesShadows = tech && tech->getParent()->getReceiveShadows();
			anyReceiveShadows = anyReceiveShadows ||
				techReceivesShadows || !tech;
		}
	};
	//---------------------------------------------------------------------
	bool MovableObject::getReceivesShadows()
	{
		MORecvShadVisitor visitor;
		visitRenderables(&visitor);
		return visitor.anyReceiveShadows;

	}
	//-----------------------------------------------------------------------
	//-----------------------------------------------------------------------
	MovableObject* MovableObjectFactory::createInstance(
		const String& name, SceneManager* manager,
		const NameValuePairList* params)
	{
		MovableObject* m = createInstanceImpl(name, params);
		m->_notifyCreator(this);
		m->_notifyManager(manager);
		return m;
	}

}

<commit_msg>Patch 2901062: If you use 2 or more scenemanager and call isVisible() outside of _findVisibleObjects(), current scene manager might be dangling pointer. This change is ok in the current context because a MovableObject is always permanently linked to its parent SceneManager. This may change in future.<commit_after>/*
-----------------------------------------------------------------------------
This source file is part of OGRE
    (Object-oriented Graphics Rendering Engine)
For the latest info, see http://www.ogre3d.org/

Copyright (c) 2000-2009 Torus Knot Software Ltd

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 "OgreStableHeaders.h"

#include "OgreMovableObject.h"
#include "OgreSceneNode.h"
#include "OgreTagPoint.h"
#include "OgreLight.h"
#include "OgreEntity.h"
#include "OgreRoot.h"
#include "OgreSceneManager.h"
#include "OgreCamera.h"
#include "OgreLodListener.h"

namespace Ogre {
	//-----------------------------------------------------------------------
	//-----------------------------------------------------------------------
	uint32 MovableObject::msDefaultQueryFlags = 0xFFFFFFFF;
	uint32 MovableObject::msDefaultVisibilityFlags = 0xFFFFFFFF;
    //-----------------------------------------------------------------------
    MovableObject::MovableObject()
        : mCreator(0)
        , mManager(0)
        , mParentNode(0)
        , mParentIsTagPoint(false)
        , mVisible(true)
		, mDebugDisplay(false)
        , mUpperDistance(0)
        , mSquaredUpperDistance(0)
        , mBeyondFarDistance(false)
        , mRenderQueueID(RENDER_QUEUE_MAIN)
        , mRenderQueueIDSet(false)
        , mQueryFlags(msDefaultQueryFlags)
        , mVisibilityFlags(msDefaultVisibilityFlags)
        , mCastShadows(true)
        , mRenderingDisabled(false)
        , mListener(0)
        , mLightListUpdated(0)
		, mLightMask(0xFFFFFFFF)
    {
    }
    //-----------------------------------------------------------------------
    MovableObject::MovableObject(const String& name)
        : mName(name)
        , mCreator(0)
        , mManager(0)
        , mParentNode(0)
        , mParentIsTagPoint(false)
        , mVisible(true)
		, mDebugDisplay(false)
        , mUpperDistance(0)
        , mSquaredUpperDistance(0)
        , mBeyondFarDistance(false)
        , mRenderQueueID(RENDER_QUEUE_MAIN)
        , mRenderQueueIDSet(false)
        , mQueryFlags(msDefaultQueryFlags)
        , mVisibilityFlags(msDefaultVisibilityFlags)
        , mCastShadows(true)
        , mRenderingDisabled(false)
        , mListener(0)
        , mLightListUpdated(0)
		, mLightMask(0xFFFFFFFF)
    {
    }
    //-----------------------------------------------------------------------
    MovableObject::~MovableObject()
    {
        // Call listener (note, only called if there's something to do)
        if (mListener)
        {
            mListener->objectDestroyed(this);
        }

        if (mParentNode)
        {
            // detach from parent
            if (mParentIsTagPoint)
            {
                // May be we are a lod entity which not in the parent entity child object list,
                // call this method could safely ignore this case.
                static_cast<TagPoint*>(mParentNode)->getParentEntity()->detachObjectFromBone(this);
            }
            else
            {
                // May be we are a lod entity which not in the parent node child object list,
                // call this method could safely ignore this case.
                static_cast<SceneNode*>(mParentNode)->detachObject(this);
            }
        }
    }
    //-----------------------------------------------------------------------
    void MovableObject::_notifyAttached(Node* parent, bool isTagPoint)
    {
        assert(!mParentNode || !parent);

        bool different = (parent != mParentNode);

        mParentNode = parent;
        mParentIsTagPoint = isTagPoint;

        // Mark light list being dirty, simply decrease
        // counter by one for minimise overhead
        --mLightListUpdated;

        // Call listener (note, only called if there's something to do)
        if (mListener && different)
        {
            if (mParentNode)
                mListener->objectAttached(this);
            else
                mListener->objectDetached(this);
        }
    }
    //-----------------------------------------------------------------------
    Node* MovableObject::getParentNode(void) const
    {
        return mParentNode;
    }
    //-----------------------------------------------------------------------
    SceneNode* MovableObject::getParentSceneNode(void) const
    {
        if (mParentIsTagPoint)
        {
            TagPoint* tp = static_cast<TagPoint*>(mParentNode);
            return tp->getParentEntity()->getParentSceneNode();
        }
        else
        {
            return static_cast<SceneNode*>(mParentNode);
        }
    }
    //-----------------------------------------------------------------------
    bool MovableObject::isAttached(void) const
    {
        return (mParentNode != 0);

    }
	//---------------------------------------------------------------------
	void MovableObject::detachFromParent(void)
	{
		if (isAttached())
		{
			if (mParentIsTagPoint)
			{
				TagPoint* tp = static_cast<TagPoint*>(mParentNode);
				tp->getParentEntity()->detachObjectFromBone(this);
			}
			else
			{
				SceneNode* sn = static_cast<SceneNode*>(mParentNode);
				sn->detachObject(this);
			}
		}
	}
    //-----------------------------------------------------------------------
	bool MovableObject::isInScene(void) const
	{
		if (mParentNode != 0)
		{
			if (mParentIsTagPoint)
			{
				TagPoint* tp = static_cast<TagPoint*>(mParentNode);
				return tp->getParentEntity()->isInScene();
			}
			else
			{
				SceneNode* sn = static_cast<SceneNode*>(mParentNode);
				return sn->isInSceneGraph();
			}
		}
		else
		{
			return false;
		}
	}
    //-----------------------------------------------------------------------
    void MovableObject::_notifyMoved(void)
    {
        // Mark light list being dirty, simply decrease
        // counter by one for minimise overhead
        --mLightListUpdated;

        // Notify listener if exists
        if (mListener)
        {
            mListener->objectMoved(this);
        }
    }
    //-----------------------------------------------------------------------
    void MovableObject::setVisible(bool visible)
    {
        mVisible = visible;
    }
    //-----------------------------------------------------------------------
    bool MovableObject::getVisible(void) const
    {
        return mVisible;
    }
    //-----------------------------------------------------------------------
    bool MovableObject::isVisible(void) const
    {
        if (!mVisible || mBeyondFarDistance || mRenderingDisabled)
            return false;

        if (mManager && !(getVisibilityFlags() & mManager->_getCombinedVisibilityMask()))
            return false;

        return true;
    }
	//-----------------------------------------------------------------------
	void MovableObject::_notifyCurrentCamera(Camera* cam)
	{
		if (mParentNode)
		{
			if (cam->getUseRenderingDistance() && mUpperDistance > 0)
			{
				Real rad = getBoundingRadius();
				Real squaredDepth = mParentNode->getSquaredViewDepth(cam->getLodCamera());
				// Max distance to still render
				Real maxDist = mUpperDistance + rad;
				if (squaredDepth > Math::Sqr(maxDist))
				{
					mBeyondFarDistance = true;
				}
				else
				{
					mBeyondFarDistance = false;
				}
			}
			else
			{
				mBeyondFarDistance = false;
			}

            // Construct event object
            MovableObjectLodChangedEvent evt;
            evt.movableObject = this;
            evt.camera = cam;

            // Notify lod event listeners
            cam->getSceneManager()->_notifyMovableObjectLodChanged(evt);

		}

        mRenderingDisabled = mListener && !mListener->objectRendering(this, cam);
	}
    //-----------------------------------------------------------------------
    void MovableObject::setRenderQueueGroup(uint8 queueID)
    {
		assert(queueID <= RENDER_QUEUE_MAX && "Render queue out of range!");
        mRenderQueueID = queueID;
        mRenderQueueIDSet = true;
    }
    //-----------------------------------------------------------------------
    uint8 MovableObject::getRenderQueueGroup(void) const
    {
        return mRenderQueueID;
    }
    //-----------------------------------------------------------------------
	const Matrix4& MovableObject::_getParentNodeFullTransform(void) const
	{

		if(mParentNode)
		{
			// object attached to a sceneNode
			return mParentNode->_getFullTransform();
		}
        // fallback
        return Matrix4::IDENTITY;
	}
    //-----------------------------------------------------------------------
    const AxisAlignedBox& MovableObject::getWorldBoundingBox(bool derive) const
    {
        if (derive)
        {
            mWorldAABB = this->getBoundingBox();
            mWorldAABB.transformAffine(_getParentNodeFullTransform());
        }

        return mWorldAABB;

    }
    //-----------------------------------------------------------------------
	const Sphere& MovableObject::getWorldBoundingSphere(bool derive) const
	{
		if (derive)
		{
			mWorldBoundingSphere.setRadius(getBoundingRadius());
			mWorldBoundingSphere.setCenter(mParentNode->_getDerivedPosition());
		}
		return mWorldBoundingSphere;
	}
    //-----------------------------------------------------------------------
    const LightList& MovableObject::queryLights(void) const
    {
        // Try listener first
        if (mListener)
        {
            const LightList* lightList =
                mListener->objectQueryLights(this);
            if (lightList)
            {
                return *lightList;
            }
        }

        // Query from parent entity if exists
        if (mParentIsTagPoint)
        {
            TagPoint* tp = static_cast<TagPoint*>(mParentNode);
            return tp->getParentEntity()->queryLights();
        }

        if (mParentNode)
        {
            SceneNode* sn = static_cast<SceneNode*>(mParentNode);

            // Make sure we only update this only if need.
            ulong frame = sn->getCreator()->_getLightsDirtyCounter();
            if (mLightListUpdated != frame)
            {
                mLightListUpdated = frame;

                sn->findLights(mLightList, this->getBoundingRadius(), this->getLightMask());
            }
        }
        else
        {
            mLightList.clear();
        }

        return mLightList;
    }
    //-----------------------------------------------------------------------
    ShadowCaster::ShadowRenderableListIterator MovableObject::getShadowVolumeRenderableIterator(
        ShadowTechnique shadowTechnique, const Light* light,
        HardwareIndexBufferSharedPtr* indexBuffer,
        bool extrudeVertices, Real extrusionDist, unsigned long flags )
    {
        static ShadowRenderableList dummyList;
        return ShadowRenderableListIterator(dummyList.begin(), dummyList.end());
    }
    //-----------------------------------------------------------------------
    const AxisAlignedBox& MovableObject::getLightCapBounds(void) const
    {
        // Same as original bounds
        return getWorldBoundingBox();
    }
    //-----------------------------------------------------------------------
    const AxisAlignedBox& MovableObject::getDarkCapBounds(const Light& light, Real extrusionDist) const
    {
        // Extrude own light cap bounds
        mWorldDarkCapBounds = getLightCapBounds();
        this->extrudeBounds(mWorldDarkCapBounds, light.getAs4DVector(),
            extrusionDist);
        return mWorldDarkCapBounds;

    }
    //-----------------------------------------------------------------------
    Real MovableObject::getPointExtrusionDistance(const Light* l) const
    {
        if (mParentNode)
        {
            return getExtrusionDistance(mParentNode->_getDerivedPosition(), l);
        }
        else
        {
            return 0;
        }
    }
	//-----------------------------------------------------------------------
	uint32 MovableObject::getTypeFlags(void) const
	{
		if (mCreator)
		{
			return mCreator->getTypeFlags();
		}
		else
		{
			return 0xFFFFFFFF;
		}
	}
	//---------------------------------------------------------------------
	void MovableObject::setLightMask(uint32 lightMask)
	{
		this->mLightMask = lightMask;
		//make sure to request a new light list from the scene manager if mask changed
		mLightListUpdated = 0;
	}
	//---------------------------------------------------------------------
	class MORecvShadVisitor : public Renderable::Visitor
	{
	public:
		bool anyReceiveShadows;
		MORecvShadVisitor() : anyReceiveShadows(false)
		{

		}
		void visit(Renderable* rend, ushort lodIndex, bool isDebug,
			Any* pAny = 0)
		{
			Technique* tech = rend->getTechnique();
			bool techReceivesShadows = tech && tech->getParent()->getReceiveShadows();
			anyReceiveShadows = anyReceiveShadows ||
				techReceivesShadows || !tech;
		}
	};
	//---------------------------------------------------------------------
	bool MovableObject::getReceivesShadows()
	{
		MORecvShadVisitor visitor;
		visitRenderables(&visitor);
		return visitor.anyReceiveShadows;

	}
	//-----------------------------------------------------------------------
	//-----------------------------------------------------------------------
	MovableObject* MovableObjectFactory::createInstance(
		const String& name, SceneManager* manager,
		const NameValuePairList* params)
	{
		MovableObject* m = createInstanceImpl(name, params);
		m->_notifyCreator(this);
		m->_notifyManager(manager);
		return m;
	}

}

<|endoftext|>


<commit_before>/**
 * Clever programming language
 * Copyright (c) Clever Team
 *
 * This file is distributed under the MIT license. See LICENSE for details.
 */

#include <fstream>
#include "core/value.h"
#include "core/clever.h"
#include "modules/std/file/cfile.h"
#include "types/type.h"
#include "modules/std/core/function.h"

// @TODO(muriloadriano): make this available and use in all Clever API
#define CLEVER_CAST(Type, obj) (static_cast<Type*>(obj))

using ::std::fstream;

namespace clever { namespace packages { namespace std {

namespace detail {

// Given a mode string returns the according ios flag
::std::ios::openmode convert_open_mode(const CString& mode)
{
	// @TODO(muriloadriano): support binary modes.
	if (mode == "r") {
		return ::std::ios_base::in;
	} else if (mode == "w") {
		return ::std::ios_base::out | ::std::ios_base::trunc;
	} else if (mode == "a") {
		return ::std::ios_base::out | ::std::ios_base::app;
	} else if (mode == "r+") {
		return ::std::ios_base::in | ::std::ios_base::out;
	} else if (mode == "w+") {
		return ::std::ios_base::in | ::std::ios_base::out |
				::std::ios_base::trunc;
	} else if (mode == "a+") {
		return ::std::ios_base::in | ::std::ios_base::out |
				::std::ios_base::app;
	} else {
		// @TODO(muriloadriano): return some kind of error here.
		return ::std::ios_base::in;
	}
}

}

void CFile::dump(const void* data) const
{
	dump(data, ::std::cout);
}

void CFile::dump(const void* data, ::std::ostream& out) const
{
	out << "File class (" << data << ")";
}

// File.new(string fileName, string openMode)
void* CFile::allocData(CLEVER_TYPE_CTOR_ARGS) const
{
	// @TODO(muriloadriano): allow object construction with a single argument
	// and check the argument's type.
	return new fstream(args->at(0)->getStr()->c_str(),
		static_cast< ::std::ios_base::openmode>(args->at(1)->getInt()));
}

void CFile::deallocData(CLEVER_TYPE_DTOR_ARGS)
{
	delete CLEVER_CAST(fstream*, data);
}

CLEVER_METHOD(CFile::ctor)
{
	if (!clever_check_args("ss")) {
		return;
	}

	result->setObj(this, allocData(&args));
}

// string File.read()
// Return the next token from the current stream
CLEVER_METHOD(CFile::read)
{
	if (!clever_check_no_args()) {
		return;
	}

	fstream* file = CLEVER_GET_OBJECT(fstream*, CLEVER_THIS());

	CString* token = new CString;
	*file >> *token;

	result->setStr(token);
}

// string File.readLine()
// Return the contents from the current positon until the next line
CLEVER_METHOD(CFile::readLine)
{
	if (!clever_check_no_args()) {
		return;
	}

	fstream* file = CLEVER_GET_OBJECT(fstream*, CLEVER_THIS());

	CString* token = new CString;
	::std::getline(*file, *token);

	result->setStr(token);
}

// void File.write(String)
// Return the contents from the current positon until the next line
// TODO(muriloadriano): allow use other primitive types as argument
CLEVER_METHOD(CFile::write)
{
	if (!clever_check_args("s")) {
		return;
	}

	fstream* file = CLEVER_GET_OBJECT(fstream*, CLEVER_THIS());

	*file << *(args[0]->getStr());
}

// void File.open(string fileName, Int openMode)
CLEVER_METHOD(CFile::open)
{
	if (!clever_check_args("si")) {
		return;
	}

	fstream* file = CLEVER_GET_OBJECT(fstream*, CLEVER_THIS());

	file->open(args[0]->getStr()->c_str(),
		static_cast< ::std::ios_base::openmode>(args[1]->getInt()));
}

// void File.close()
CLEVER_METHOD(CFile::close)
{
	if (!clever_check_no_args()) {
		return;
	}

	fstream* file = CLEVER_GET_OBJECT(fstream*, CLEVER_THIS());
	file->close();
}

// bool File.isOpen()
CLEVER_METHOD(CFile::isOpen)
{
	if (!clever_check_no_args()) {
		return;
	}

	fstream* file = CLEVER_GET_OBJECT(fstream*, CLEVER_THIS());
	result->setBool(file->is_open());
}

CLEVER_TYPE_INIT(CFile::init)
{
	Function* ctor = new Function("File", (MethodPtr)&CFile::ctor);

	setConstructor(ctor);
	addMethod(ctor);
	addMethod(new Function("read",		(MethodPtr)&CFile::read));
	addMethod(new Function("readLine",	(MethodPtr)&CFile::readLine));
	addMethod(new Function("write",		(MethodPtr)&CFile::write));
	addMethod(new Function("open",		(MethodPtr)&CFile::open));
	addMethod(new Function("close",		(MethodPtr)&CFile::close));
	addMethod(new Function("isOpen",	(MethodPtr)&CFile::isOpen));

	addProperty(CSTRING("IN"), new Value(long(::std::ios_base::in), true));
	addProperty(CSTRING("OUT"), new Value(long(::std::ios_base::out), true));
	addProperty(CSTRING("TRUNC"),
		new Value(long(::std::ios_base::trunc), true));
	addProperty(CSTRING("APP"), new Value(long(::std::ios_base::app), true));
	addProperty(CSTRING("ATE"), new Value(long(::std::ios_base::ate), true));
	addProperty(CSTRING("BIN"), new Value(long(::std::ios_base::binary), true));
}

}}} // clever::packages::std
<commit_msg>Changed File ctor to use flags<commit_after>/**
 * Clever programming language
 * Copyright (c) Clever Team
 *
 * This file is distributed under the MIT license. See LICENSE for details.
 */

#include <fstream>
#include "core/value.h"
#include "core/clever.h"
#include "modules/std/file/cfile.h"
#include "types/type.h"
#include "modules/std/core/function.h"

// @TODO(muriloadriano): make this available and use in all Clever API
#define CLEVER_CAST(Type, obj) (static_cast<Type*>(obj))

using ::std::fstream;

namespace clever { namespace packages { namespace std {

namespace detail {

// Given a mode string returns the according ios flag
::std::ios::openmode convert_open_mode(const CString& mode)
{
	// @TODO(muriloadriano): support binary modes.
	if (mode == "r") {
		return ::std::ios_base::in;
	} else if (mode == "w") {
		return ::std::ios_base::out | ::std::ios_base::trunc;
	} else if (mode == "a") {
		return ::std::ios_base::out | ::std::ios_base::app;
	} else if (mode == "r+") {
		return ::std::ios_base::in | ::std::ios_base::out;
	} else if (mode == "w+") {
		return ::std::ios_base::in | ::std::ios_base::out |
				::std::ios_base::trunc;
	} else if (mode == "a+") {
		return ::std::ios_base::in | ::std::ios_base::out |
				::std::ios_base::app;
	} else {
		// @TODO(muriloadriano): return some kind of error here.
		return ::std::ios_base::in;
	}
}

}

void CFile::dump(const void* data) const
{
	dump(data, ::std::cout);
}

void CFile::dump(const void* data, ::std::ostream& out) const
{
	out << "File class (" << data << ")";
}

// File.new(string fileName, string openMode)
void* CFile::allocData(CLEVER_TYPE_CTOR_ARGS) const
{
	// @TODO(muriloadriano): allow object construction with a single argument
	// and check the argument's type.
	return new fstream(args->at(0)->getStr()->c_str(),
		static_cast< ::std::ios_base::openmode>(args->at(1)->getInt()));
}

void CFile::deallocData(CLEVER_TYPE_DTOR_ARGS)
{
	delete CLEVER_CAST(fstream*, data);
}

CLEVER_METHOD(CFile::ctor)
{
	if (!clever_check_args("si")) {
		return;
	}

	result->setObj(this, allocData(&args));
}

// string File.read()
// Return the next token from the current stream
CLEVER_METHOD(CFile::read)
{
	if (!clever_check_no_args()) {
		return;
	}

	fstream* file = CLEVER_GET_OBJECT(fstream*, CLEVER_THIS());

	CString* token = new CString;
	*file >> *token;

	result->setStr(token);
}

// string File.readLine()
// Return the contents from the current positon until the next line
CLEVER_METHOD(CFile::readLine)
{
	if (!clever_check_no_args()) {
		return;
	}

	fstream* file = CLEVER_GET_OBJECT(fstream*, CLEVER_THIS());

	CString* token = new CString;
	::std::getline(*file, *token);

	result->setStr(token);
}

// void File.write(String)
// Return the contents from the current positon until the next line
// TODO(muriloadriano): allow use other primitive types as argument
CLEVER_METHOD(CFile::write)
{
	if (!clever_check_args("s")) {
		return;
	}

	fstream* file = CLEVER_GET_OBJECT(fstream*, CLEVER_THIS());

	*file << *(args[0]->getStr());
}

// void File.open(string fileName, Int openMode)
CLEVER_METHOD(CFile::open)
{
	if (!clever_check_args("si")) {
		return;
	}

	fstream* file = CLEVER_GET_OBJECT(fstream*, CLEVER_THIS());

	file->open(args[0]->getStr()->c_str(),
		static_cast< ::std::ios_base::openmode>(args[1]->getInt()));
}

// void File.close()
CLEVER_METHOD(CFile::close)
{
	if (!clever_check_no_args()) {
		return;
	}

	fstream* file = CLEVER_GET_OBJECT(fstream*, CLEVER_THIS());
	file->close();
}

// bool File.isOpen()
CLEVER_METHOD(CFile::isOpen)
{
	if (!clever_check_no_args()) {
		return;
	}

	fstream* file = CLEVER_GET_OBJECT(fstream*, CLEVER_THIS());
	result->setBool(file->is_open());
}

CLEVER_TYPE_INIT(CFile::init)
{
	Function* ctor = new Function("File", (MethodPtr)&CFile::ctor);

	setConstructor(ctor);
	addMethod(ctor);
	addMethod(new Function("read",		(MethodPtr)&CFile::read));
	addMethod(new Function("readLine",	(MethodPtr)&CFile::readLine));
	addMethod(new Function("write",		(MethodPtr)&CFile::write));
	addMethod(new Function("open",		(MethodPtr)&CFile::open));
	addMethod(new Function("close",		(MethodPtr)&CFile::close));
	addMethod(new Function("isOpen",	(MethodPtr)&CFile::isOpen));

	addProperty(CSTRING("IN"), new Value(long(::std::ios_base::in), true));
	addProperty(CSTRING("OUT"), new Value(long(::std::ios_base::out), true));
	addProperty(CSTRING("TRUNC"),
		new Value(long(::std::ios_base::trunc), true));
	addProperty(CSTRING("APP"), new Value(long(::std::ios_base::app), true));
	addProperty(CSTRING("ATE"), new Value(long(::std::ios_base::ate), true));
	addProperty(CSTRING("BIN"), new Value(long(::std::ios_base::binary), true));
}

}}} // clever::packages::std
<|endoftext|>