<commit_before>// vrkit is (C) Copyright 2005-2007
//    by Allen Bierbaum, Aron Bierbuam, Patrick Hartling, and Daniel Shipton
//
// This file is part of vrkit.
//
// vrkit is free software; you can redistribute it and/or modify it under the
// terms of the GNU Lesser General Public License as published by the Free
// Software Foundation; either version 2 of the License, or (at your option)
// any later version.
//
// vrkit 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 program.  If not, see <http://www.gnu.org/licenses/>.

#if defined(WIN32) || defined(WIN64)
#include <windows.h>
#include <iostream>
#include <sstream>
#include <cstdlib>
#include <string>
#include <boost/filesystem/path.hpp>
#include <boost/filesystem/exception.hpp>

namespace fs = boost::filesystem;

/**
 * Windows DLL entry point function. This ensures that the environment
 * variable \c VRKIT_BASE_DIR is set as soon as this DLL is attached to the
 * process. If it is not set, then it sets it based on an assumption about the
 * structure of a vrkit installation. More specifically, an assumption is made
 * that this DLL lives in the \c lib subdirectory of the vrkit installation.
 * Therefore, the root of the vrkit installation is the parent of the
 * directory containing this DLL.
 */
BOOL __stdcall DllMain(HINSTANCE module, DWORD reason, LPVOID reserved)
{
   switch (reason)
   {
      case DLL_PROCESS_ATTACH:
         {
            char tmppath[1024];
            std::memset(tmppath, 0, sizeof(tmppath));
            GetModuleFileName(module, tmppath, sizeof(tmppath));

            try
            {
               fs::path dll_path(tmppath, fs::native);
               fs::path base_dir = dll_path.branch_path().branch_path();
#if defined(VRKIT_DEBUG) && ! defined(_DEBUG)
               // The debug DLL linked against the release runtime is in
               // <base_dir>\lib\debug.
               base_dir = base_dir.branch_path();
#endif
               const std::string base_dir_str =
                  base_dir.native_directory_string();

               char* env_dir(NULL);
#if defined(_MSC_VER) && _MSC_VER >= 1400
               size_t len;
               _dupenv_s(&env_dir, &len, "VRKIT_BASE_DIR");
#else
               env_dir = std::getenv("VRKIT_BASE_DIR");
#endif

               if ( NULL == env_dir )
               {
#if defined(_MSC_VER) && _MSC_VER >= 1400
                  _putenv_s("VRKIT_BASE_DIR", base_dir_str.c_str());
#else
                  std::ostringstream env_stream;
                  env_stream << "VRKIT_BASE_DIR=" << base_dir_str;
                  putenv(env_stream.str().c_str());
#endif
               }
#if defined(_MSC_VER) && _MSC_VER >= 1400
               else
               {
                  std::free(env_dir);
               }
#endif

#if defined(_MSC_VER) && _MSC_VER >= 1400
               _dupenv_s(&env_dir, &len, "VRKIT_DATA_DIR");
#else
               env_dir = std::getenv("VRKIT_DATA_DIR");
#endif

               if ( NULL == env_dir )
               {
                  fs::path data_dir = base_dir / "share" / "vrkit";
                  const std::string data_dir_str =
                     data_dir.native_directory_string();

#if defined(_MSC_VER) && _MSC_VER >= 1400
                  _putenv_s("VRKIT_DATA_DIR", data_dir_str.c_str());
#else
                  std::ostringstream env_stream;
                  env_stream << "VRKIT_DATA_DIR=" << data_dir_str;
                  putenv(env_stream.str().c_str());
#endif
               }
#if defined(_MSC_VER) && _MSC_VER >= 1400
               else
               {
                  std::free(env_dir);
               }
#endif

#if defined(_MSC_VER) && _MSC_VER >= 1400
               _dupenv_s(&env_dir, &len, "VRKIT_PLUGINS_DIR");
#else
               env_dir = std::getenv("VRKIT_PLUGINS_DIR");
#endif

               if ( NULL == env_dir )
               {
                  fs::path plugin_dir = base_dir / "lib" / "vrkit" / "plugins";
                  const std::string plugin_dir_str =
                     plugin_dir.native_directory_string();

#if defined(_MSC_VER) && _MSC_VER >= 1400
                  _putenv_s("VRKIT_PLUGINS_DIR", plugin_dir_str.c_str());
#else
                  std::ostringstream env_stream;
                  env_stream << "VRKIT_PLUGINS_DIR=" << plugin_dir_str;
                  putenv(env_stream.str().c_str());
#endif
               }
#if defined(_MSC_VER) && _MSC_VER >= 1400
               else
               {
                  std::free(env_dir);
               }
#endif
            }
            catch (fs::filesystem_error& ex)
            {
               std::cerr << "Automatic assignment of vrkit environment "
                         << "variables failed:\n" << ex.what() << std::endl;
            }
         }
         break;
      default:
         break;
   }

   return TRUE;
}

#else /* Non-windows or..Unix case. */
#include <dlfcn.h>
#include <string>

#include <boost/filesystem/path.hpp>
#include <boost/filesystem/operations.hpp>
#include <boost/filesystem/exception.hpp>

#include <vpr/System.h>

#include <vrkit/Status.h>
#include <vrkit/Version.h>

namespace fs = boost::filesystem;

extern "C" void __attribute ((constructor)) vrkit_library_init()
{
   Dl_info info;
   info.dli_fname = 0;
   const int result =
      dladdr(reinterpret_cast<const void*>(&vrkit_library_init), &info);

   // NOTE: dladdr(3) really does return a non-zero value on success.
   if ( 0 != result )
   {
      try
      {
         fs::path lib_file(info.dli_fname, fs::native);
         lib_file = fs::system_complete(lib_file);

         // Get the directory containing this shared library.
         const fs::path lib_path = lib_file.branch_path();

         // Start the search for the root of the vrkit installation in the
         // parent of the directory containing this shared library.
         fs::path base_dir = lib_path.branch_path();

         // Use the lib subdirectory to figure out when we have found the root
         // of the vrkit installation tree.
         const fs::path lib_subdir(std::string("lib"));

         bool found(false);
         while ( ! found && ! base_dir.empty() )
         {
            try
            {
               if ( ! fs::exists(base_dir / lib_subdir) )
               {
                  base_dir = base_dir.branch_path();
               }
               else
               {
                  found = true;
               }
            }
            catch (fs::filesystem_error&)
            {
               base_dir = base_dir.branch_path();
            }
         }
         if( found )
         {
            // Construct VRKIT_DATA_DIR and VRKIT_PLUGINS_DIR
            std::string vrkit_versioned_dir_name = "vrkit";
#ifdef VRKIT_USE_VERSIONING
            vrkit_versioned_dir_name.append("-");
            vrkit_versioned_dir_name.append(vrkit::getVersion());
#endif

            // Go from /base to base/lib/versioned_vrkit_dir/plugins
            fs::path plugins_dir = base_dir / "lib" /
                                         vrkit_versioned_dir_name / "plugins";
            // Go from /base to /base/share/versioned_vrkit_dir
            fs::path data_dir = base_dir / "share" /
                                         vrkit_versioned_dir_name;

            std::string vrkit_base_dir_env_var;
            vpr::System::getenv("VRKIT_BASE_DIR", vrkit_base_dir_env_var);
            if ( vrkit_base_dir_env_var.empty() )
            {
               vpr::System::setenv("VRKIT_BASE_DIR", base_dir.string());
               VRKIT_STATUS << "VRKIT_BASE_DIR set to: "
                            << base_dir.string() << std::endl;
            }

            std::string vrkit_data_dir_env_var;
            vpr::System::getenv("VRKIT_DATA_DIR", vrkit_data_dir_env_var);
            if ( vrkit_data_dir_env_var.empty() )
            {
               vpr::System::setenv("VRKIT_DATA_DIR", data_dir.string());
               VRKIT_STATUS << "VRKIT_DATA_DIR set to: "
                            << data_dir.string() << std::endl;
            }

            std::string vrkit_plugin_dir_env_var;
            vpr::System::getenv("VRKIT_PLUGINS_DIR", vrkit_plugin_dir_env_var);
            if ( vrkit_plugin_dir_env_var.empty() )
            {
               vpr::System::setenv("VRKIT_PLUGINS_DIR", plugins_dir.string());
               VRKIT_STATUS << "VRKIT_PLUGINS_DIR set to: "
                            << plugins_dir.string() << std::endl;
            }
         }
      }
      catch (fs::filesystem_error& ex)
      {
         std::cerr << "Automatic assignment of VRKIT_BASE_DIR failed:\n"
                   << ex.what() << std::endl;
      }
   }
}
#endif
<commit_msg>Fixed a compile error when using a version of GCC older than 4.0.<commit_after>// vrkit is (C) Copyright 2005-2007
//    by Allen Bierbaum, Aron Bierbuam, Patrick Hartling, and Daniel Shipton
//
// This file is part of vrkit.
//
// vrkit is free software; you can redistribute it and/or modify it under the
// terms of the GNU Lesser General Public License as published by the Free
// Software Foundation; either version 2 of the License, or (at your option)
// any later version.
//
// vrkit 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 program.  If not, see <http://www.gnu.org/licenses/>.

#if defined(WIN32) || defined(WIN64)
#include <windows.h>
#include <iostream>
#include <sstream>
#include <cstdlib>
#include <string>
#include <boost/filesystem/path.hpp>
#include <boost/filesystem/exception.hpp>

namespace fs = boost::filesystem;

/**
 * Windows DLL entry point function. This ensures that the environment
 * variable \c VRKIT_BASE_DIR is set as soon as this DLL is attached to the
 * process. If it is not set, then it sets it based on an assumption about the
 * structure of a vrkit installation. More specifically, an assumption is made
 * that this DLL lives in the \c lib subdirectory of the vrkit installation.
 * Therefore, the root of the vrkit installation is the parent of the
 * directory containing this DLL.
 */
BOOL __stdcall DllMain(HINSTANCE module, DWORD reason, LPVOID reserved)
{
   switch (reason)
   {
      case DLL_PROCESS_ATTACH:
         {
            char tmppath[1024];
            std::memset(tmppath, 0, sizeof(tmppath));
            GetModuleFileName(module, tmppath, sizeof(tmppath));

            try
            {
               fs::path dll_path(tmppath, fs::native);
               fs::path base_dir = dll_path.branch_path().branch_path();
#if defined(VRKIT_DEBUG) && ! defined(_DEBUG)
               // The debug DLL linked against the release runtime is in
               // <base_dir>\lib\debug.
               base_dir = base_dir.branch_path();
#endif
               const std::string base_dir_str =
                  base_dir.native_directory_string();

               char* env_dir(NULL);
#if defined(_MSC_VER) && _MSC_VER >= 1400
               size_t len;
               _dupenv_s(&env_dir, &len, "VRKIT_BASE_DIR");
#else
               env_dir = std::getenv("VRKIT_BASE_DIR");
#endif

               if ( NULL == env_dir )
               {
#if defined(_MSC_VER) && _MSC_VER >= 1400
                  _putenv_s("VRKIT_BASE_DIR", base_dir_str.c_str());
#else
                  std::ostringstream env_stream;
                  env_stream << "VRKIT_BASE_DIR=" << base_dir_str;
                  putenv(env_stream.str().c_str());
#endif
               }
#if defined(_MSC_VER) && _MSC_VER >= 1400
               else
               {
                  std::free(env_dir);
               }
#endif

#if defined(_MSC_VER) && _MSC_VER >= 1400
               _dupenv_s(&env_dir, &len, "VRKIT_DATA_DIR");
#else
               env_dir = std::getenv("VRKIT_DATA_DIR");
#endif

               if ( NULL == env_dir )
               {
                  fs::path data_dir = base_dir / "share" / "vrkit";
                  const std::string data_dir_str =
                     data_dir.native_directory_string();

#if defined(_MSC_VER) && _MSC_VER >= 1400
                  _putenv_s("VRKIT_DATA_DIR", data_dir_str.c_str());
#else
                  std::ostringstream env_stream;
                  env_stream << "VRKIT_DATA_DIR=" << data_dir_str;
                  putenv(env_stream.str().c_str());
#endif
               }
#if defined(_MSC_VER) && _MSC_VER >= 1400
               else
               {
                  std::free(env_dir);
               }
#endif

#if defined(_MSC_VER) && _MSC_VER >= 1400
               _dupenv_s(&env_dir, &len, "VRKIT_PLUGINS_DIR");
#else
               env_dir = std::getenv("VRKIT_PLUGINS_DIR");
#endif

               if ( NULL == env_dir )
               {
                  fs::path plugin_dir = base_dir / "lib" / "vrkit" / "plugins";
                  const std::string plugin_dir_str =
                     plugin_dir.native_directory_string();

#if defined(_MSC_VER) && _MSC_VER >= 1400
                  _putenv_s("VRKIT_PLUGINS_DIR", plugin_dir_str.c_str());
#else
                  std::ostringstream env_stream;
                  env_stream << "VRKIT_PLUGINS_DIR=" << plugin_dir_str;
                  putenv(env_stream.str().c_str());
#endif
               }
#if defined(_MSC_VER) && _MSC_VER >= 1400
               else
               {
                  std::free(env_dir);
               }
#endif
            }
            catch (fs::filesystem_error& ex)
            {
               std::cerr << "Automatic assignment of vrkit environment "
                         << "variables failed:\n" << ex.what() << std::endl;
            }
         }
         break;
      default:
         break;
   }

   return TRUE;
}

#else /* Non-windows or..Unix case. */
#include <dlfcn.h>
#include <string>

#include <boost/filesystem/path.hpp>
#include <boost/filesystem/operations.hpp>
#include <boost/filesystem/exception.hpp>

#include <vpr/System.h>

#include <vrkit/Status.h>
#include <vrkit/Version.h>

namespace fs = boost::filesystem;

extern "C" void __attribute ((constructor)) vrkit_library_init()
{
   Dl_info info;
   info.dli_fname = 0;
   const int result =
#if defined(__GNUC__) && __GNUC_MAJOR__ < 4
      dladdr((void*) &vrkit_library_init, &info);
#else
      dladdr(reinterpret_cast<void*>(&vrkit_library_init), &info);
#endif

   // NOTE: dladdr(3) really does return a non-zero value on success.
   if ( 0 != result )
   {
      try
      {
         fs::path lib_file(info.dli_fname, fs::native);
         lib_file = fs::system_complete(lib_file);

         // Get the directory containing this shared library.
         const fs::path lib_path = lib_file.branch_path();

         // Start the search for the root of the vrkit installation in the
         // parent of the directory containing this shared library.
         fs::path base_dir = lib_path.branch_path();

         // Use the lib subdirectory to figure out when we have found the root
         // of the vrkit installation tree.
         const fs::path lib_subdir(std::string("lib"));

         bool found(false);
         while ( ! found && ! base_dir.empty() )
         {
            try
            {
               if ( ! fs::exists(base_dir / lib_subdir) )
               {
                  base_dir = base_dir.branch_path();
               }
               else
               {
                  found = true;
               }
            }
            catch (fs::filesystem_error&)
            {
               base_dir = base_dir.branch_path();
            }
         }
         if( found )
         {
            // Construct VRKIT_DATA_DIR and VRKIT_PLUGINS_DIR
            std::string vrkit_versioned_dir_name = "vrkit";
#ifdef VRKIT_USE_VERSIONING
            vrkit_versioned_dir_name.append("-");
            vrkit_versioned_dir_name.append(vrkit::getVersion());
#endif

            // Go from /base to base/lib/versioned_vrkit_dir/plugins
            fs::path plugins_dir = base_dir / "lib" /
                                         vrkit_versioned_dir_name / "plugins";
            // Go from /base to /base/share/versioned_vrkit_dir
            fs::path data_dir = base_dir / "share" /
                                         vrkit_versioned_dir_name;

            std::string vrkit_base_dir_env_var;
            vpr::System::getenv("VRKIT_BASE_DIR", vrkit_base_dir_env_var);
            if ( vrkit_base_dir_env_var.empty() )
            {
               vpr::System::setenv("VRKIT_BASE_DIR", base_dir.string());
               VRKIT_STATUS << "VRKIT_BASE_DIR set to: "
                            << base_dir.string() << std::endl;
            }

            std::string vrkit_data_dir_env_var;
            vpr::System::getenv("VRKIT_DATA_DIR", vrkit_data_dir_env_var);
            if ( vrkit_data_dir_env_var.empty() )
            {
               vpr::System::setenv("VRKIT_DATA_DIR", data_dir.string());
               VRKIT_STATUS << "VRKIT_DATA_DIR set to: "
                            << data_dir.string() << std::endl;
            }

            std::string vrkit_plugin_dir_env_var;
            vpr::System::getenv("VRKIT_PLUGINS_DIR", vrkit_plugin_dir_env_var);
            if ( vrkit_plugin_dir_env_var.empty() )
            {
               vpr::System::setenv("VRKIT_PLUGINS_DIR", plugins_dir.string());
               VRKIT_STATUS << "VRKIT_PLUGINS_DIR set to: "
                            << plugins_dir.string() << std::endl;
            }
         }
      }
      catch (fs::filesystem_error& ex)
      {
         std::cerr << "Automatic assignment of VRKIT_BASE_DIR failed:\n"
                   << ex.what() << std::endl;
      }
   }
}
#endif
<|endoftext|>


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

  Program:   Visualization Toolkit
  Module:    ContourF.cc
  Language:  C++
  Date:      02/07/94
  Version:   1.4

Copyright (c) 1993-1995 Ken Martin, Will Schroeder, Bill Lorensen.

This software is copyrighted by Ken Martin, Will Schroeder and Bill Lorensen.
The following terms apply to all files associated with the software unless
explicitly disclaimed in individual files. This copyright specifically does
not apply to the related textbook "The Visualization Toolkit" ISBN
013199837-4 published by Prentice Hall which is covered by its own copyright.

The authors hereby grant permission to use, copy, and distribute this
software and its documentation for any purpose, provided that existing
copyright notices are retained in all copies and that this notice is included
verbatim in any distributions. Additionally, the authors grant permission to
modify this software and its documentation for any purpose, provided that
such modifications are not distributed without the explicit consent of the
authors and that existing copyright notices are retained in all copies. Some
of the algorithms implemented by this software are patented, observe all
applicable patent law.

IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY FOR
DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY DERIVATIVES THEREOF,
EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, INCLUDING,
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE, AND NON-INFRINGEMENT.  THIS SOFTWARE IS PROVIDED ON AN
"AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE
MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.

=========================================================================*/
#include "vtkContourFilter.hh"
#include "vtkFloatScalars.hh"
#include "vtkCell.hh"
#include "vtkMergePoints.hh"
#include "vtkMarchingSquares.hh"
#include "vtkMarchingCubes.hh"

// Description:
// Construct object with initial range (0,1) and single contour value
// of 0.0.
vtkContourFilter::vtkContourFilter()
{
  for (int i=0; i<VTK_MAX_CONTOURS; i++) this->Values[i] = 0.0;
  this->NumberOfContours = 1;
  this->Range[0] = 0.0;
  this->Range[1] = 1.0;
  this->ComputeNormals = 1;
  this->ComputeGradients = 0;
  this->ComputeScalars = 1;
}

// Description:
// Set a particular contour value at contour number i. The index i ranges
// between 0<=i<NumberOfContours.
void vtkContourFilter::SetValue(int i, float value)
{
  i = (i >= VTK_MAX_CONTOURS ? VTK_MAX_CONTOURS-1 : (i < 0 ? 0 : i) );
  if ( this->Values[i] != value )
    {
    this->Modified();
    this->Values[i] = value;
    if ( i >= this->NumberOfContours ) this->NumberOfContours = i + 1;
    if ( value < this->Range[0] ) this->Range[0] = value;
    if ( value > this->Range[1] ) this->Range[1] = value;
    }
}

void vtkContourFilter::GenerateValues(int numContours, float range1,
				     float range2)
{
  float rng[2];

  rng[0] = range1;
  rng[1] = range2;
  this->GenerateValues(numContours,rng);
}

// Description:
// Generate numContours equally spaced contour values between specified
// range. Contour values will include min/max range values.
void vtkContourFilter::GenerateValues(int numContours, float range[2])
{
  float val, incr;
  int i;

  numContours = (numContours >= VTK_MAX_CONTOURS ? VTK_MAX_CONTOURS-1 :
                (numContours > 1 ? numContours : 2) );

  incr = (range[1] - range[0]) / (numContours-1);
  for (i=0, val=range[0]; i < numContours; i++, val+=incr)
    {
    this->SetValue(i,val);
    }

  this->NumberOfContours = numContours;
}

//
// General contouring filter.  Handles arbitrary input.
//
void vtkContourFilter::Execute()
{
  int cellId, i;
  vtkIdList *cellPts;
  vtkScalars *inScalars;
  vtkFloatScalars cellScalars(VTK_CELL_SIZE);
  vtkCell *cell;
  float *range, value;
  vtkFloatScalars *newScalars;
  vtkCellArray *newVerts, *newLines, *newPolys;
  vtkFloatPoints *newPts;
  cellScalars.ReferenceCountingOff();
  vtkPolyData *output = this->GetOutput();

  vtkDebugMacro(<< "Executing contour filter");

  if ( ! (inScalars = this->Input->GetPointData()->GetScalars()) )
    {
    vtkErrorMacro(<<"No scalar data to contour");
    return;
    }

  // If structured points, use more efficient algorithms
  if ( ! strcmp(this->Input->GetDataType(),"vtkStructuredPoints") )
    {
    int dim = this->Input->GetCell(0)->GetCellDimension();

    if ( this->Input->GetCell(0)->GetCellDimension() >= 2 )
      {
      this->StructuredPointsContour(dim);
      return;
      }
    }

  range = inScalars->GetRange();
//
// Create objects to hold output of contour operation
//
  newPts = new vtkFloatPoints(10000,25000);
  newVerts = new vtkCellArray(10000,25000);
  newLines = new vtkCellArray(10000,25000);
  newPolys = new vtkCellArray(10000,25000);
  newScalars = new vtkFloatScalars(10000,25000);
//
// Loop over all contour values.  Then for each contour value,
// loop over all cells.
//
  for (i=0; i<this->NumberOfContours; i++)
    {
    value = this->Values[i];
    for (cellId=0; cellId<Input->GetNumberOfCells(); cellId++)
      {
      cell = Input->GetCell(cellId);
      cellPts = cell->GetPointIds();
      inScalars->GetScalars(*cellPts,cellScalars);

      cell->Contour(value, &cellScalars, newPts, newVerts, newLines, newPolys, newScalars);

      } // for all cells
    } // for all contour values

  vtkDebugMacro(<<"Created: "
               << newPts->GetNumberOfPoints() << " points, "
               << newVerts->GetNumberOfCells() << " verts, "
               << newLines->GetNumberOfCells() << " lines, "
               << newPolys->GetNumberOfCells() << " triangles");
//
// Update ourselves.  Because we don't know up front how many verts, lines,
// polys we've created, take care to reclaim memory.
//
  output->SetPoints(newPts);
  newPts->Delete();

  output->GetPointData()->SetScalars(newScalars);
  newScalars->Delete();

  if (newVerts->GetNumberOfCells()) output->SetVerts(newVerts);
  newVerts->Delete();

  if (newLines->GetNumberOfCells()) output->SetLines(newLines);
  newLines->Delete();

  if (newPolys->GetNumberOfCells()) output->SetPolys(newPolys);
  newPolys->Delete();

  output->Squeeze();
}

//
// Special method handles structured points
//
void vtkContourFilter::StructuredPointsContour(int dim)
{
  vtkPolyData *output;
  vtkPolyData *thisOutput = (vtkPolyData *)this->Output;
  int i;

  if ( dim == 2 ) //marching squares
    {
    static vtkMarchingSquares msquares;

    msquares.SetInput((vtkStructuredPoints *)this->Input);
    msquares.SetDebug(this->Debug);
    for (i=0; i < this->NumberOfContours; i++)
      msquares.SetValue(i,this->Values[i]);

    msquares.Update();
    output = msquares.GetOutput();
    }

  else //marching cubes
    {
    static vtkMarchingCubes mcubes;

    mcubes.SetInput((vtkStructuredPoints *)this->Input);
    mcubes.SetComputeNormals (this->ComputeNormals);
    mcubes.SetComputeGradients (this->ComputeGradients);
    mcubes.SetComputeScalars (this->ComputeScalars);
    mcubes.SetDebug(this->Debug);
    for (i=0; i < this->NumberOfContours; i++)
      mcubes.SetValue(i,this->Values[i]);

    mcubes.Update();
    output = mcubes.GetOutput();
    }

  thisOutput->CopyStructure(output);
  *thisOutput->GetPointData() = *output->GetPointData();
  output->Initialize();
}

void vtkContourFilter::PrintSelf(ostream& os, vtkIndent indent)
{
  int i;

  vtkDataSetToPolyFilter::PrintSelf(os,indent);

  os << indent << "Number Of Contours : " << this->NumberOfContours << "\n";
  os << indent << "Contour Values: \n";
  for ( i=0; i<this->NumberOfContours; i++)
    {
    os << indent << "  Value " << i << ": " << this->Values[i] << "\n";
    }
}

<commit_msg>ENH: Fixed static variable bug.<commit_after>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    ContourF.cc
  Language:  C++
  Date:      02/07/94
  Version:   1.4

Copyright (c) 1993-1995 Ken Martin, Will Schroeder, Bill Lorensen.

This software is copyrighted by Ken Martin, Will Schroeder and Bill Lorensen.
The following terms apply to all files associated with the software unless
explicitly disclaimed in individual files. This copyright specifically does
not apply to the related textbook "The Visualization Toolkit" ISBN
013199837-4 published by Prentice Hall which is covered by its own copyright.

The authors hereby grant permission to use, copy, and distribute this
software and its documentation for any purpose, provided that existing
copyright notices are retained in all copies and that this notice is included
verbatim in any distributions. Additionally, the authors grant permission to
modify this software and its documentation for any purpose, provided that
such modifications are not distributed without the explicit consent of the
authors and that existing copyright notices are retained in all copies. Some
of the algorithms implemented by this software are patented, observe all
applicable patent law.

IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY FOR
DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY DERIVATIVES THEREOF,
EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, INCLUDING,
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE, AND NON-INFRINGEMENT.  THIS SOFTWARE IS PROVIDED ON AN
"AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE
MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.

=========================================================================*/
#include "vtkContourFilter.hh"
#include "vtkFloatScalars.hh"
#include "vtkCell.hh"
#include "vtkMergePoints.hh"
#include "vtkMarchingSquares.hh"
#include "vtkMarchingCubes.hh"

// Description:
// Construct object with initial range (0,1) and single contour value
// of 0.0.
vtkContourFilter::vtkContourFilter()
{
  for (int i=0; i<VTK_MAX_CONTOURS; i++) this->Values[i] = 0.0;
  this->NumberOfContours = 1;
  this->Range[0] = 0.0;
  this->Range[1] = 1.0;
  this->ComputeNormals = 1;
  this->ComputeGradients = 0;
  this->ComputeScalars = 1;
}

// Description:
// Set a particular contour value at contour number i. The index i ranges
// between 0<=i<NumberOfContours.
void vtkContourFilter::SetValue(int i, float value)
{
  i = (i >= VTK_MAX_CONTOURS ? VTK_MAX_CONTOURS-1 : (i < 0 ? 0 : i) );
  if ( this->Values[i] != value )
    {
    this->Modified();
    this->Values[i] = value;
    if ( i >= this->NumberOfContours ) this->NumberOfContours = i + 1;
    if ( value < this->Range[0] ) this->Range[0] = value;
    if ( value > this->Range[1] ) this->Range[1] = value;
    }
}

void vtkContourFilter::GenerateValues(int numContours, float range1,
				     float range2)
{
  float rng[2];

  rng[0] = range1;
  rng[1] = range2;
  this->GenerateValues(numContours,rng);
}

// Description:
// Generate numContours equally spaced contour values between specified
// range. Contour values will include min/max range values.
void vtkContourFilter::GenerateValues(int numContours, float range[2])
{
  float val, incr;
  int i;

  numContours = (numContours >= VTK_MAX_CONTOURS ? VTK_MAX_CONTOURS-1 :
                (numContours > 1 ? numContours : 2) );

  incr = (range[1] - range[0]) / (numContours-1);
  for (i=0, val=range[0]; i < numContours; i++, val+=incr)
    {
    this->SetValue(i,val);
    }

  this->NumberOfContours = numContours;
}

//
// General contouring filter.  Handles arbitrary input.
//
void vtkContourFilter::Execute()
{
  int cellId, i;
  vtkIdList *cellPts;
  vtkScalars *inScalars;
  vtkFloatScalars cellScalars(VTK_CELL_SIZE);
  vtkCell *cell;
  float *range, value;
  vtkFloatScalars *newScalars;
  vtkCellArray *newVerts, *newLines, *newPolys;
  vtkFloatPoints *newPts;
  cellScalars.ReferenceCountingOff();
  vtkPolyData *output = this->GetOutput();

  vtkDebugMacro(<< "Executing contour filter");

  if ( ! (inScalars = this->Input->GetPointData()->GetScalars()) )
    {
    vtkErrorMacro(<<"No scalar data to contour");
    return;
    }

  // If structured points, use more efficient algorithms
  if ( ! strcmp(this->Input->GetDataType(),"vtkStructuredPoints") )
    {
    int dim = this->Input->GetCell(0)->GetCellDimension();

    if ( this->Input->GetCell(0)->GetCellDimension() >= 2 )
      {
      this->StructuredPointsContour(dim);
      return;
      }
    }

  range = inScalars->GetRange();
//
// Create objects to hold output of contour operation
//
  newPts = new vtkFloatPoints(10000,25000);
  newVerts = new vtkCellArray(10000,25000);
  newLines = new vtkCellArray(10000,25000);
  newPolys = new vtkCellArray(10000,25000);
  newScalars = new vtkFloatScalars(10000,25000);
//
// Loop over all contour values.  Then for each contour value,
// loop over all cells.
//
  for (i=0; i<this->NumberOfContours; i++)
    {
    value = this->Values[i];
    for (cellId=0; cellId<Input->GetNumberOfCells(); cellId++)
      {
      cell = Input->GetCell(cellId);
      cellPts = cell->GetPointIds();
      inScalars->GetScalars(*cellPts,cellScalars);

      cell->Contour(value, &cellScalars, newPts, newVerts, newLines, newPolys, newScalars);

      } // for all cells
    } // for all contour values

  vtkDebugMacro(<<"Created: "
               << newPts->GetNumberOfPoints() << " points, "
               << newVerts->GetNumberOfCells() << " verts, "
               << newLines->GetNumberOfCells() << " lines, "
               << newPolys->GetNumberOfCells() << " triangles");
//
// Update ourselves.  Because we don't know up front how many verts, lines,
// polys we've created, take care to reclaim memory.
//
  output->SetPoints(newPts);
  newPts->Delete();

  output->GetPointData()->SetScalars(newScalars);
  newScalars->Delete();

  if (newVerts->GetNumberOfCells()) output->SetVerts(newVerts);
  newVerts->Delete();

  if (newLines->GetNumberOfCells()) output->SetLines(newLines);
  newLines->Delete();

  if (newPolys->GetNumberOfCells()) output->SetPolys(newPolys);
  newPolys->Delete();

  output->Squeeze();
}

//
// Special method handles structured points
//
void vtkContourFilter::StructuredPointsContour(int dim)
{
  vtkPolyData *output;
  vtkPolyData *thisOutput = (vtkPolyData *)this->Output;
  int i;

  if ( dim == 2 ) //marching squares
    {
    static vtkMarchingSquares msquares;

    msquares.SetInput((vtkStructuredPoints *)this->Input);
    msquares.SetDebug(this->Debug);
    msquares.SetNumberOfContours(this->NumberOfContours);
    for (i=0; i < this->NumberOfContours; i++)
      msquares.SetValue(i,this->Values[i]);

    msquares.Update();
    output = msquares.GetOutput();
    }

  else //marching cubes
    {
    static vtkMarchingCubes mcubes;

    mcubes.SetInput((vtkStructuredPoints *)this->Input);
    mcubes.SetComputeNormals (this->ComputeNormals);
    mcubes.SetComputeGradients (this->ComputeGradients);
    mcubes.SetComputeScalars (this->ComputeScalars);
    mcubes.SetDebug(this->Debug);
    mcubes.SetNumberOfContours(this->NumberOfContours);
    for (i=0; i < this->NumberOfContours; i++)
      mcubes.SetValue(i,this->Values[i]);

    mcubes.Update();
    output = mcubes.GetOutput();
    }

  thisOutput->CopyStructure(output);
  *thisOutput->GetPointData() = *output->GetPointData();
  output->Initialize();
}

void vtkContourFilter::PrintSelf(ostream& os, vtkIndent indent)
{
  int i;

  vtkDataSetToPolyFilter::PrintSelf(os,indent);

  os << indent << "Number Of Contours : " << this->NumberOfContours << "\n";
  os << indent << "Contour Values: \n";
  for ( i=0; i<this->NumberOfContours; i++)
    {
    os << indent << "  Value " << i << ": " << this->Values[i] << "\n";
    }
}

<|endoftext|>


<commit_before>#include "costs.hpp"
#include "layout.hpp"
#include "typo.hpp"

#include <iostream>

// auto reduce_typos(const std::vector<Typo> &t) -> int {
//   auto result = 0;
//   for (const auto &v : t) {
//     result += v.cost;
//   }
//   return result;
// }

// auto do_stuff(const std::string &correct, const std::string &typo)
//     -> std::vector<Typo> {
//   if (correct.size() == 1 && typo.size() == 2) {
//     return std::vector<Typo>();
//   }

//   if (correct.size() == 1) {
//     auto result = do_stuff(correct, typo.substr(0, typo.size() - 1));
//     result.emplace_back(TypoClass::Insert,
//                         compute_insert_cost(typo[typo.size() - 3],
//                                             typo[typo.size() - 2],
//                                             typo.back()),
//                         typo.size() - 3, typo);
//     return result;
//   }
//   if (typo.size() == 2) {
//     auto result = std::vector<Typo>(correct.size() - 1);
//     for (auto &v : result) {
//       v.kind = TypoClass::Delete;
//       v.cost = 6;
//       v.idx = -1;
//       v.typo = typo;
//     }
//     return result;
//   }

//   auto options = std::vector<std::vector<Typo>>();
//   auto corr = correct.back();
//   auto left = typo[typo.size() - 3];
//   auto curr = typo[typo.size() - 2];
//   auto right = typo.back();

//   if (corr == curr) {
//     return do_stuff(correct.substr(0, correct.size() - 1),
//                     typo.substr(0, typo.size() - 1));
//   }

//   auto substitute = do_stuff(correct.substr(0, correct.size() - 1),
//                              typo.substr(0, typo.size() - 1));
//   substitute.emplace_back(TypoClass::Substitute,
//                           compute_substitute_cost(corr, curr), typo.size() -
//                           3,
//                           typo);
//   options.push_back(substitute);

//   auto insert = do_stuff(correct, typo.substr(0, typo.size() - 1));
//   insert.emplace_back(TypoClass::Insert, compute_insert_cost(left, curr,
//   right),
//                       typo.size() - 2, typo);
//   options.push_back(insert);

//   auto del = do_stuff(correct.substr(0, correct.size() - 1), typo);
//   del.emplace_back(TypoClass::Delete, compute_delete_cost(curr, corr),
//                    typo.size() - 1, typo);
//   options.push_back(del);

//   if (corr == left) {
//     auto traveller = curr;
//     auto idx =

//         auto transpose =
//             do_stuff(correct.substr(0, correct.size() - 1), new_string);
//     transpose.emplace_back(TypoClass::Transpose,
//                            compute_transpose_cost(left, curr), typo.size() -
//                            3,
//                            typo);
//     options.push_back(transpose);
//   }

//   auto mini = 0;
//   auto minv = reduce_typos(options[0]);
//   for (auto i = 1; i < options.size(); i++) {
//     const auto cost = reduce_typos(options[i]);
//     if (cost < minv) {
//       mini = i;
//       minv = cost;
//     }
//   }
//   return options[mini];
// }

// auto prep_stuff(const std::string &correct, const std::string &actual)
//     -> std::vector<Typo> {
//   return do_stuff("\0" + correct, "\0" + actual + '\0');
// }

auto main(const int argc, const char **argv) -> int {
  std::cout << "Still just a stub!\n";
  std::cout << "But now I compile!\n";

  const std::string correct = "the rain in spain stays mainly on the plain";
  const std::string actual = "teh driafna i pasin staya ksjnmly in the eplani";
  TransposeList result{};
  find_tranpose(result, sentinel + correct, sentinel + actual);

  for (const auto &pairs : result) {
    auto i = pairs.first / actual.size();
    auto j = pairs.first % actual.size();
    std::cout << i << "," << j << " (" << correct[i] << "," << actual[j]
              << "): ";
    for (const auto &value : pairs.second) {
      std::cout << value << " ";
    }
    std::cout << std::endl;
  }

  find_typos(result, correct, actual);
}
<commit_msg>Fixed example string to reflect project instructions.<commit_after>#include "costs.hpp"
#include "layout.hpp"
#include "typo.hpp"

#include <iostream>

// auto reduce_typos(const std::vector<Typo> &t) -> int {
//   auto result = 0;
//   for (const auto &v : t) {
//     result += v.cost;
//   }
//   return result;
// }

// auto do_stuff(const std::string &correct, const std::string &typo)
//     -> std::vector<Typo> {
//   if (correct.size() == 1 && typo.size() == 2) {
//     return std::vector<Typo>();
//   }

//   if (correct.size() == 1) {
//     auto result = do_stuff(correct, typo.substr(0, typo.size() - 1));
//     result.emplace_back(TypoClass::Insert,
//                         compute_insert_cost(typo[typo.size() - 3],
//                                             typo[typo.size() - 2],
//                                             typo.back()),
//                         typo.size() - 3, typo);
//     return result;
//   }
//   if (typo.size() == 2) {
//     auto result = std::vector<Typo>(correct.size() - 1);
//     for (auto &v : result) {
//       v.kind = TypoClass::Delete;
//       v.cost = 6;
//       v.idx = -1;
//       v.typo = typo;
//     }
//     return result;
//   }

//   auto options = std::vector<std::vector<Typo>>();
//   auto corr = correct.back();
//   auto left = typo[typo.size() - 3];
//   auto curr = typo[typo.size() - 2];
//   auto right = typo.back();

//   if (corr == curr) {
//     return do_stuff(correct.substr(0, correct.size() - 1),
//                     typo.substr(0, typo.size() - 1));
//   }

//   auto substitute = do_stuff(correct.substr(0, correct.size() - 1),
//                              typo.substr(0, typo.size() - 1));
//   substitute.emplace_back(TypoClass::Substitute,
//                           compute_substitute_cost(corr, curr), typo.size() -
//                           3,
//                           typo);
//   options.push_back(substitute);

//   auto insert = do_stuff(correct, typo.substr(0, typo.size() - 1));
//   insert.emplace_back(TypoClass::Insert, compute_insert_cost(left, curr,
//   right),
//                       typo.size() - 2, typo);
//   options.push_back(insert);

//   auto del = do_stuff(correct.substr(0, correct.size() - 1), typo);
//   del.emplace_back(TypoClass::Delete, compute_delete_cost(curr, corr),
//                    typo.size() - 1, typo);
//   options.push_back(del);

//   if (corr == left) {
//     auto traveller = curr;
//     auto idx =

//         auto transpose =
//             do_stuff(correct.substr(0, correct.size() - 1), new_string);
//     transpose.emplace_back(TypoClass::Transpose,
//                            compute_transpose_cost(left, curr), typo.size() -
//                            3,
//                            typo);
//     options.push_back(transpose);
//   }

//   auto mini = 0;
//   auto minv = reduce_typos(options[0]);
//   for (auto i = 1; i < options.size(); i++) {
//     const auto cost = reduce_typos(options[i]);
//     if (cost < minv) {
//       mini = i;
//       minv = cost;
//     }
//   }
//   return options[mini];
// }

// auto prep_stuff(const std::string &correct, const std::string &actual)
//     -> std::vector<Typo> {
//   return do_stuff("\0" + correct, "\0" + actual + '\0');
// }

auto main(const int argc, const char **argv) -> int {
  std::cout << "Still just a stub!\n";
  std::cout << "But now I compile!\n";

  const std::string correct = "the rain in spain stays mainly on the plain";
  const std::string actual = "teh driafna i pasin staya ksjnmly in th eplani";
  TransposeList result{};
  find_tranpose(result, sentinel + correct, sentinel + actual);

  for (const auto &pairs : result) {
    auto i = pairs.first / actual.size();
    auto j = pairs.first % actual.size();
    std::cout << i << "," << j << " (" << correct[i] << "," << actual[j]
              << "): ";
    for (const auto &value : pairs.second) {
      std::cout << value << " ";
    }
    std::cout << std::endl;
  }

  find_typos(result, correct, actual);
}
<|endoftext|>


<commit_before>//////////////////////////////////////////////////////////////////////////
//
//  Copyright (c) 2007-2009, Image Engine Design Inc. All rights reserved.
//
//  Redistribution and use in source and binary forms, with or without
//  modification, are permitted provided that the following conditions are
//  met:
//
//     * Redistributions of source code must retain the above copyright
//       notice, this list of conditions and the following disclaimer.
//
//     * Redistributions in binary form must reproduce the above copyright
//       notice, this list of conditions and the following disclaimer in the
//       documentation and/or other materials provided with the distribution.
//
//     * Neither the name of Image Engine Design nor the names of any
//       other contributors to this software may be used to endorse or
//       promote products derived from this software without specific prior
//       written permission.
//
//  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
//  IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
//  THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
//  PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
//  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
//  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
//  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
//  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
//  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
//  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
//  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
//////////////////////////////////////////////////////////////////////////

#include "IECoreGL/ColorTexture.h"
#include "IECoreGL/Exception.h"
#include "IECoreGL/NumericTraits.h"

#include "IECore/VectorTypedData.h"
#include "IECore/MessageHandler.h"

using namespace IECoreGL;
using namespace IECore;
using namespace Imath;
using namespace std;
using namespace boost;

IE_CORE_DEFINERUNTIMETYPED( ColorTexture );

ColorTexture::ColorTexture( unsigned int width, unsigned int height )
{
	glGenTextures( 1, &m_texture );
	glBindTexture( GL_TEXTURE_2D, m_texture );

	glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
	glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );
	glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
	glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );

	glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA,
		GL_FLOAT, 0 );
}

ColorTexture::ColorTexture( unsigned int width, unsigned int height, IECore::ConstDataPtr r,
	IECore::ConstDataPtr g, IECore::ConstDataPtr b, IECore::ConstDataPtr a )
{
	construct( width, height, r, g, b, a );
}

static IECore::ConstDataPtr findChannel( const IECore::PrimitiveVariableMap &variables, const char **names )
{
	while( *names!=0 )
	{
		IECore::PrimitiveVariableMap::const_iterator it = variables.find( *names );
		if( it!=variables.end() )
		{
			PrimitiveVariable::Interpolation interpolation = it->second.interpolation;
			if( interpolation==PrimitiveVariable::Vertex ||
				interpolation==PrimitiveVariable::Varying ||
				interpolation==PrimitiveVariable::FaceVarying )
			{
				return it->second.data;
			}
		}
		names++;
	}
	return 0;
}

ColorTexture::ColorTexture( IECore::ConstImagePrimitivePtr image )
{
	static const char *redNames[] = { "r", "R", "red", 0 };
	static const char *greenNames[] = { "g", "G", "green", 0 };
	static const char *blueNames[] = { "b", "B", "blue", 0 };
	static const char *alphaNames[] = { "a", "A", "alpha", 0 };

	IECore::ConstDataPtr r = findChannel( image->variables, redNames );
	IECore::ConstDataPtr g = findChannel( image->variables, greenNames );
	IECore::ConstDataPtr b = findChannel( image->variables, blueNames );
	IECore::ConstDataPtr a = findChannel( image->variables, alphaNames );

	if( !(r && g && b) )
	{
		throw Exception( "Unsupported color format." );
	}

	int width = image->getDataWindow().size().x + 1;
	int height = image->getDataWindow().size().y + 1;
	construct( width, height, r, g, b, a );
}

ColorTexture::~ColorTexture()
{
}

void ColorTexture::construct( unsigned int width, unsigned int height, IECore::ConstDataPtr r,
	IECore::ConstDataPtr g, IECore::ConstDataPtr b, IECore::ConstDataPtr a )
{
	if( r->typeId() != g->typeId() ||
		r->typeId() != b->typeId() ||
		( a && (r->typeId() != a->typeId()) ) )
	{
		throw Exception( "Channel types do not match." );
	}

	if( r->typeId()==UCharVectorData::staticTypeId() )
	{
		castConstruct<UCharVectorData>( width, height, r, g, b, a );
	}
	else if( r->typeId()==CharVectorData::staticTypeId() )
	{
		castConstruct<CharVectorData>( width, height, r, g, b, a );
	}
	else if( r->typeId()==UIntVectorData::staticTypeId() )
	{
		castConstruct<UIntVectorData>( width, height, r, g, b, a );
	}
	else if( r->typeId()==IntVectorData::staticTypeId() )
	{
		castConstruct<IntVectorData>( width, height, r, g, b, a );
	}
	else if( r->typeId()==HalfVectorData::staticTypeId() )
	{
		castConstruct<HalfVectorData>( width, height, r, g, b, a );
	}
	else if( r->typeId()==FloatVectorData::staticTypeId() )
	{
		castConstruct<FloatVectorData>( width, height, r, g, b, a );
	}
	else if( r->typeId()==DoubleVectorData::staticTypeId() )
	{
		castConstruct<DoubleVectorData>( width, height, r, g, b, a );
	}
	else {
		throw Exception( boost::str( boost::format( "Unsupported channel type \"%s\"." ) % r->typeName() ) );
	}
}

template<class T>
void ColorTexture::castConstruct( unsigned int width, unsigned int height, IECore::ConstDataPtr r,
	IECore::ConstDataPtr g, IECore::ConstDataPtr b, IECore::ConstDataPtr a )
{
	templateConstruct( width, height,
		static_pointer_cast<const T>( r ),
		static_pointer_cast<const T>( g ),
		static_pointer_cast<const T>( b ),
		static_pointer_cast<const T>( a )	);
}

template<typename T>
void ColorTexture::templateConstruct( unsigned int width, unsigned int height, boost::intrusive_ptr<const T> r,
	boost::intrusive_ptr<const T> g,  boost::intrusive_ptr<const T> b, boost::intrusive_ptr<const T> a )
{
	typedef typename T::ValueType::value_type ElementType;

	const std::vector<ElementType> &rr = r->readable();
	const std::vector<ElementType> &rg = g->readable();
	const std::vector<ElementType> &rb = b->readable();
	const std::vector<ElementType> *ra = a ? &a->readable() : 0;

	unsigned int n = width * height;
	if( rr.size()!=n || rg.size()!=n || rb.size()!=n || (ra && ra->size()!=n) )
	{
		throw IECore::Exception( "Image data has wrong size." );
	}

	std::vector<ElementType> interleaved( n * (ra ? 4 : 3) );

	unsigned int i = 0;
	for( int y=height-1; y>=0; y-- )
	{
		const ElementType *dr = &rr[y*width];
		const ElementType *dg = &rg[y*width];
		const ElementType *db = &rb[y*width];
		const ElementType *da = ra ? &(*ra)[y*width] : 0;

		for( unsigned int x=0; x<width; x++ )
		{
			interleaved[i++] = dr[x];
			interleaved[i++] = dg[x];
			interleaved[i++] = db[x];
			if( da )
			{
				interleaved[i++] = da[x];
			}
		}
	}

	glGenTextures( 1, &m_texture );
	glBindTexture( GL_TEXTURE_2D, m_texture );

	glPixelStorei( GL_UNPACK_ALIGNMENT, 1 );

	glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
	glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );
	glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
	glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );

	glTexImage2D( GL_TEXTURE_2D, 0, ra ? GL_RGBA : GL_RGB, width, height, 0, ra ? GL_RGBA : GL_RGB,
		NumericTraits<ElementType>::glType(), &interleaved[0] );

	Exception::throwIfError();

}

ImagePrimitivePtr ColorTexture::imagePrimitive() const
{
	glPushAttrib( mask() );

		bind();

		GLint width = 0;
		GLint height = 0;
		glGetTexLevelParameteriv( GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &width );
		glGetTexLevelParameteriv( GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &height );

		GLint internalFormat = 0;
		glGetTexLevelParameteriv( GL_TEXTURE_2D, 0, GL_TEXTURE_INTERNAL_FORMAT, &internalFormat );

		unsigned int numChannels = 4;
		vector<float> data( width * height * numChannels );

		glGetTexImage( GL_TEXTURE_2D, 0, internalFormat, GL_FLOAT, &data[0] );

		FloatVectorDataPtr rd = new FloatVectorData();
		vector<float> &r = rd->writable(); r.resize( width * height );

		FloatVectorDataPtr gd = new FloatVectorData();
		vector<float> &g = gd->writable(); g.resize( width * height );

		FloatVectorDataPtr bd = new FloatVectorData();
		vector<float> &b = bd->writable(); b.resize( width * height );

		FloatVectorDataPtr ad = 0;
		vector<float> *a = 0;
		if( internalFormat==GL_RGBA )
		{
			ad = new FloatVectorData();
			a = &ad->writable(); a->resize( width * height );
		}

		unsigned int i = 0;
		for( int y=height-1; y>=0; y-- )
		{
			float *rr = &r[y*width];
			float *rg = &g[y*width];
			float *rb = &b[y*width];
			float *ra = a ? &(*a)[y*width] : 0;
			for( int x=0; x<width; x++ )
			{
				rr[x] = data[i++];
				rg[x] = data[i++];
				rb[x] = data[i++];
				if( ra )
				{
					ra[x] = data[i++];
				}
			}
		}

		Box2i imageExtents( V2i( 0, 0 ), V2i( width-1, height-1 ) );
		ImagePrimitivePtr image = new ImagePrimitive( imageExtents, imageExtents );
		image->variables["R"] = PrimitiveVariable( PrimitiveVariable::Vertex, rd );
		image->variables["G"] = PrimitiveVariable( PrimitiveVariable::Vertex, gd );
		image->variables["B"] = PrimitiveVariable( PrimitiveVariable::Vertex, bd );
		if( a )
		{
			image->variables["A"] = PrimitiveVariable( PrimitiveVariable::Vertex, ad );
		}

	glPopAttrib();

	return image;
}
<commit_msg>Fixes for problems encountered in snow leopard build.<commit_after>//////////////////////////////////////////////////////////////////////////
//
//  Copyright (c) 2007-2009, Image Engine Design Inc. All rights reserved.
//
//  Redistribution and use in source and binary forms, with or without
//  modification, are permitted provided that the following conditions are
//  met:
//
//     * Redistributions of source code must retain the above copyright
//       notice, this list of conditions and the following disclaimer.
//
//     * Redistributions in binary form must reproduce the above copyright
//       notice, this list of conditions and the following disclaimer in the
//       documentation and/or other materials provided with the distribution.
//
//     * Neither the name of Image Engine Design nor the names of any
//       other contributors to this software may be used to endorse or
//       promote products derived from this software without specific prior
//       written permission.
//
//  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
//  IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
//  THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
//  PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
//  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
//  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
//  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
//  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
//  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
//  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
//  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
//////////////////////////////////////////////////////////////////////////

#include "IECoreGL/ColorTexture.h"
#include "IECoreGL/Exception.h"
#include "IECoreGL/NumericTraits.h"

#include "IECore/VectorTypedData.h"
#include "IECore/MessageHandler.h"

using namespace IECoreGL;
using namespace IECore;
using namespace Imath;
using namespace std;
using namespace boost;

IE_CORE_DEFINERUNTIMETYPED( ColorTexture );

ColorTexture::ColorTexture( unsigned int width, unsigned int height )
{
	glGenTextures( 1, &m_texture );
	glBindTexture( GL_TEXTURE_2D, m_texture );

	glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
	glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );
	glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
	glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );

	glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA,
		GL_FLOAT, 0 );
}

ColorTexture::ColorTexture( unsigned int width, unsigned int height, IECore::ConstDataPtr r,
	IECore::ConstDataPtr g, IECore::ConstDataPtr b, IECore::ConstDataPtr a )
{
	construct( width, height, r, g, b, a );
}

static IECore::ConstDataPtr findChannel( const IECore::PrimitiveVariableMap &variables, const char **names )
{
	while( *names!=0 )
	{
		IECore::PrimitiveVariableMap::const_iterator it = variables.find( *names );
		if( it!=variables.end() )
		{
			PrimitiveVariable::Interpolation interpolation = it->second.interpolation;
			if( interpolation==PrimitiveVariable::Vertex ||
				interpolation==PrimitiveVariable::Varying ||
				interpolation==PrimitiveVariable::FaceVarying )
			{
				return it->second.data;
			}
		}
		names++;
	}
	return 0;
}

ColorTexture::ColorTexture( IECore::ConstImagePrimitivePtr image )
{
	static const char *redNames[] = { "r", "R", "red", 0 };
	static const char *greenNames[] = { "g", "G", "green", 0 };
	static const char *blueNames[] = { "b", "B", "blue", 0 };
	static const char *alphaNames[] = { "a", "A", "alpha", 0 };

	IECore::ConstDataPtr r = findChannel( image->variables, redNames );
	IECore::ConstDataPtr g = findChannel( image->variables, greenNames );
	IECore::ConstDataPtr b = findChannel( image->variables, blueNames );
	IECore::ConstDataPtr a = findChannel( image->variables, alphaNames );

	if( !(r && g && b) )
	{
		throw Exception( "Unsupported color format." );
	}

	int width = image->getDataWindow().size().x + 1;
	int height = image->getDataWindow().size().y + 1;
	construct( width, height, r, g, b, a );
}

ColorTexture::~ColorTexture()
{
}

void ColorTexture::construct( unsigned int width, unsigned int height, IECore::ConstDataPtr r,
	IECore::ConstDataPtr g, IECore::ConstDataPtr b, IECore::ConstDataPtr a )
{
	if( r->typeId() != g->typeId() ||
		r->typeId() != b->typeId() ||
		( a && (r->typeId() != a->typeId()) ) )
	{
		throw Exception( "Channel types do not match." );
	}

	if( r->typeId()==UCharVectorData::staticTypeId() )
	{
		castConstruct<UCharVectorData>( width, height, r, g, b, a );
	}
	else if( r->typeId()==CharVectorData::staticTypeId() )
	{
		castConstruct<CharVectorData>( width, height, r, g, b, a );
	}
	else if( r->typeId()==UIntVectorData::staticTypeId() )
	{
		castConstruct<UIntVectorData>( width, height, r, g, b, a );
	}
	else if( r->typeId()==IntVectorData::staticTypeId() )
	{
		castConstruct<IntVectorData>( width, height, r, g, b, a );
	}
	else if( r->typeId()==HalfVectorData::staticTypeId() )
	{
		castConstruct<HalfVectorData>( width, height, r, g, b, a );
	}
	else if( r->typeId()==FloatVectorData::staticTypeId() )
	{
		castConstruct<FloatVectorData>( width, height, r, g, b, a );
	}
	else if( r->typeId()==DoubleVectorData::staticTypeId() )
	{
		castConstruct<DoubleVectorData>( width, height, r, g, b, a );
	}
	else {
		throw Exception( boost::str( boost::format( "Unsupported channel type \"%s\"." ) % r->typeName() ) );
	}
}

template<class T>
void ColorTexture::castConstruct( unsigned int width, unsigned int height, IECore::ConstDataPtr r,
	IECore::ConstDataPtr g, IECore::ConstDataPtr b, IECore::ConstDataPtr a )
{
	templateConstruct( width, height,
		static_pointer_cast<const T>( r ),
		static_pointer_cast<const T>( g ),
		static_pointer_cast<const T>( b ),
		static_pointer_cast<const T>( a )	);
}

template<typename T>
void ColorTexture::templateConstruct( unsigned int width, unsigned int height, boost::intrusive_ptr<const T> r,
	boost::intrusive_ptr<const T> g,  boost::intrusive_ptr<const T> b, boost::intrusive_ptr<const T> a )
{
	typedef typename T::ValueType::value_type ElementType;

	const std::vector<ElementType> &rr = r->readable();
	const std::vector<ElementType> &rg = g->readable();
	const std::vector<ElementType> &rb = b->readable();
	const std::vector<ElementType> *ra = a ? &a->readable() : 0;

	unsigned int n = width * height;
	if( rr.size()!=n || rg.size()!=n || rb.size()!=n || (ra && ra->size()!=n) )
	{
		throw IECore::Exception( "Image data has wrong size." );
	}

	std::vector<ElementType> interleaved( n * (ra ? 4 : 3) );

	unsigned int i = 0;
	for( int y=height-1; y>=0; y-- )
	{
		const ElementType *dr = &rr[y*width];
		const ElementType *dg = &rg[y*width];
		const ElementType *db = &rb[y*width];
		const ElementType *da = ra ? &(*ra)[y*width] : 0;

		for( unsigned int x=0; x<width; x++ )
		{
			interleaved[i++] = dr[x];
			interleaved[i++] = dg[x];
			interleaved[i++] = db[x];
			if( da )
			{
				interleaved[i++] = da[x];
			}
		}
	}

	glGenTextures( 1, &m_texture );
	glBindTexture( GL_TEXTURE_2D, m_texture );

	glPixelStorei( GL_UNPACK_ALIGNMENT, 1 );

	glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
	glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );
	glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
	glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );

	glTexImage2D( GL_TEXTURE_2D, 0, ra ? GL_RGBA : GL_RGB, width, height, 0, ra ? GL_RGBA : GL_RGB,
		NumericTraits<ElementType>::glType(), &interleaved[0] );

	Exception::throwIfError();

}

ImagePrimitivePtr ColorTexture::imagePrimitive() const
{

	glPushAttrib( mask() );

		bind();

		GLint width = 0;
		GLint height = 0;
		glGetTexLevelParameteriv( GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &width );
		glGetTexLevelParameteriv( GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &height );

		GLint internalFormat = 0;
		glGetTexLevelParameteriv( GL_TEXTURE_2D, 0, GL_TEXTURE_INTERNAL_FORMAT, &internalFormat );

		unsigned int numChannels = 4;
		vector<float> data( width * height * numChannels );

		glGetTexImage( GL_TEXTURE_2D, 0, GL_RGBA, GL_FLOAT, &data[0] );

		FloatVectorDataPtr rd = new FloatVectorData();
		vector<float> &r = rd->writable(); r.resize( width * height );

		FloatVectorDataPtr gd = new FloatVectorData();
		vector<float> &g = gd->writable(); g.resize( width * height );

		FloatVectorDataPtr bd = new FloatVectorData();
		vector<float> &b = bd->writable(); b.resize( width * height );

		FloatVectorDataPtr ad = 0;
		vector<float> *a = 0;
		// there are potentially loads of different internal formats which denote alpha.
		// these are the only ones encountered so far, but it's not a great way of testing
		// and i can't find another way of doing it.
		if( internalFormat==GL_RGBA || internalFormat==GL_RGBA8_EXT )
		{
			ad = new FloatVectorData();
			a = &ad->writable(); a->resize( width * height );
		}

		unsigned int i = 0;
		for( int y=height-1; y>=0; y-- )
		{
			float *rr = &r[y*width];
			float *rg = &g[y*width];
			float *rb = &b[y*width];
			float *ra = a ? &(*a)[y*width] : 0;
			for( int x=0; x<width; x++ )
			{
				rr[x] = data[i++];
				rg[x] = data[i++];
				rb[x] = data[i++];
				if( ra )
				{
					ra[x] = data[i++];
				}
			}
		}

		Box2i imageExtents( V2i( 0, 0 ), V2i( width-1, height-1 ) );
		ImagePrimitivePtr image = new ImagePrimitive( imageExtents, imageExtents );
		image->variables["R"] = PrimitiveVariable( PrimitiveVariable::Vertex, rd );
		image->variables["G"] = PrimitiveVariable( PrimitiveVariable::Vertex, gd );
		image->variables["B"] = PrimitiveVariable( PrimitiveVariable::Vertex, bd );
		if( a )
		{
			image->variables["A"] = PrimitiveVariable( PrimitiveVariable::Vertex, ad );
		}

	glPopAttrib();

	Exception::throwIfError();

	return image;
}
<|endoftext|>


<commit_before>/*
 * Copyright 2015 ScyllaDB
 */

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

#include <random>
#include <bitset>
#include <boost/test/unit_test.hpp>
#include <boost/range/irange.hpp>
#include <seastar/core/semaphore.hh>
#include <seastar/core/reactor.hh>
#include <seastar/core/thread.hh>

#include "seastarx.hh"
#include "tests/test-utils.hh"
#include "utils/flush_queue.hh"
#include "log.hh"

std::random_device rd;
std::default_random_engine e1(rd());

SEASTAR_TEST_CASE(test_queue_ordering_random_ops) {
    struct env {
        env(size_t n) : promises(n) {}

        utils::flush_queue<int> queue;
        std::vector<promise<>> promises;
        std::vector<int> result;
    };

    auto r = boost::irange(0, 100);

    return do_for_each(r, [](int) {
        constexpr size_t num_ops = 1000;

        auto e = make_lw_shared<env>(num_ops);

        int i = 0;
        for (auto& p : e->promises) {
            e->queue.run_with_ordered_post_op(i, [&p, i] {
                return p.get_future().then([i] {
                    return make_ready_future<int>(i);
                });
            }, [e](int i) {
                e->result.emplace_back(i);
            });
            ++i;
        }

        auto res = e->queue.wait_for_pending();

        std::uniform_int_distribution<size_t> dist(0, num_ops - 1);
        std::bitset<num_ops> set;

        while (!set.all()) {
            size_t i = dist(e1);
            if (!set.test(i)) {
                set[i] = true;
                e->promises[i].set_value();
            }
        }

        return res.then([e] {
            BOOST_CHECK_EQUAL(e->result.size(), e->promises.size());
            BOOST_REQUIRE(std::is_sorted(e->result.begin(), e->result.end()));
        }).finally([e] {
            return e->queue.close().finally([e] { });
        });
    });
}

SEASTAR_TEST_CASE(test_queue_ordering_multi_ops) {
    struct env {
        env() : sem(0) {}

        utils::flush_queue<int> queue;
        std::vector<int> result;
        semaphore sem;
        size_t n = 0;
    };

    auto r = boost::irange(0, 100);

    return do_for_each(r, [](int) {
        constexpr size_t num_ops = 1000;

        auto e = make_lw_shared<env>();

        std::uniform_int_distribution<size_t> dist(0, num_ops - 1);

        for (size_t k = 0; k < num_ops*10; ++k) {
            int i = dist(e1);

            if (e->queue.has_operation(i) || (!e->queue.empty() && e->queue.highest_key() < i)) {
                e->queue.run_with_ordered_post_op(i, [e, i] {
                    return e->sem.wait().then([i] {
                        return make_ready_future<int>(i);
                    });
                }, [e](int i) {
                    e->result.emplace_back(i);
                });
                ++e->n;
            }
        }

        auto res = e->queue.wait_for_pending();

        e->sem.signal(e->n);

        return res.then([e] {
            BOOST_CHECK_EQUAL(e->result.size(), e->n);
            BOOST_REQUIRE(std::is_sorted(e->result.begin(), e->result.end()));
        }).finally([e] {
            return e->queue.close().finally([e] { });
        });
    });
}

template<typename Func, typename Post, typename Then>
static future<> test_propagation(bool propagate, Func&& func, Post&& post, Then&& thn, bool want_except_in_run, bool want_except_in_wait) {
    auto queue = ::make_shared<utils::flush_queue<int>>(propagate);
    auto sem = ::make_shared<semaphore>(0);
    auto xr = ::make_shared<bool>(false);
    auto xw = ::make_shared<bool>(false);

    auto f1 = queue->run_with_ordered_post_op(0, [sem, func = std::forward<Func>(func)]() mutable {
        return sem->wait().then(std::forward<Func>(func));
    }, std::forward<Post>(post)).handle_exception([xr](auto p) {
        *xr = true;
    }).discard_result();

    auto f2 = queue->wait_for_pending(0).then(std::forward<Then>(thn)).handle_exception([xw](auto p) {
        *xw = true;
    }).discard_result();

    sem->signal();

    return seastar::when_all_succeed(std::move(f1), std::move(f2)).finally([sem, queue, want_except_in_run, want_except_in_wait, xr, xw] {
        BOOST_CHECK_EQUAL(want_except_in_run, *xr);
        BOOST_CHECK_EQUAL(want_except_in_wait, *xw);
    }).finally([queue] {
        return queue->close().finally([queue] { });
    });
}

SEASTAR_TEST_CASE(test_propagate_exception_in_op) {
    return test_propagation(true, // propagate exception to waiter
                    [] { return make_exception_future(std::runtime_error("hej")); }, // ex in op
                    [] { BOOST_FAIL("should not reach (1)"); }, // should not reach post
                    [] { BOOST_FAIL("should not reach (2)"); }, // should not reach waiter "then"
                    true,
                    true
                    );
}

SEASTAR_TEST_CASE(test_propagate_exception_in_post) {
    return test_propagation(true, // propagate exception to waiter
                    [] {}, // ok func
                    [] { return make_exception_future(std::runtime_error("hej")); }, // ex in post
                    [] { BOOST_FAIL("should not reach"); }, // should not reach waiter "then"
                    true,
                    true
    );
}

SEASTAR_TEST_CASE(test_no_propagate_exception_in_op) {
    return test_propagation(false, // do not propagate exception to waiter
                    [] { return make_exception_future(std::runtime_error("hej")); }, // ex in op
                    [] { BOOST_FAIL("should not reach"); }, // should not reach post
                    [] {}, // should reach waiter "then"
                    true,
                    false
                    );
}

SEASTAR_TEST_CASE(test_no_propagate_exception_in_post) {
    return test_propagation(false, // do not propagate exception to waiter
                    [] {}, // ok func
                    [] { return make_exception_future(std::runtime_error("hej")); }, // ex in post
                    [] {}, // should reach waiter "then"
                    true,
                    false
                    );
}
<commit_msg>tests: flush_queue_test: de-template<commit_after>/*
 * Copyright 2015 ScyllaDB
 */

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

#include <random>
#include <bitset>
#include <boost/test/unit_test.hpp>
#include <boost/range/irange.hpp>
#include <seastar/core/semaphore.hh>
#include <seastar/core/reactor.hh>
#include <seastar/core/thread.hh>

#include "seastarx.hh"
#include "tests/test-utils.hh"
#include "utils/flush_queue.hh"
#include "log.hh"

std::random_device rd;
std::default_random_engine e1(rd());

SEASTAR_TEST_CASE(test_queue_ordering_random_ops) {
    struct env {
        env(size_t n) : promises(n) {}

        utils::flush_queue<int> queue;
        std::vector<promise<>> promises;
        std::vector<int> result;
    };

    auto r = boost::irange(0, 100);

    return do_for_each(r, [](int) {
        constexpr size_t num_ops = 1000;

        auto e = make_lw_shared<env>(num_ops);

        int i = 0;
        for (auto& p : e->promises) {
            e->queue.run_with_ordered_post_op(i, [&p, i] {
                return p.get_future().then([i] {
                    return make_ready_future<int>(i);
                });
            }, [e](int i) {
                e->result.emplace_back(i);
            });
            ++i;
        }

        auto res = e->queue.wait_for_pending();

        std::uniform_int_distribution<size_t> dist(0, num_ops - 1);
        std::bitset<num_ops> set;

        while (!set.all()) {
            size_t i = dist(e1);
            if (!set.test(i)) {
                set[i] = true;
                e->promises[i].set_value();
            }
        }

        return res.then([e] {
            BOOST_CHECK_EQUAL(e->result.size(), e->promises.size());
            BOOST_REQUIRE(std::is_sorted(e->result.begin(), e->result.end()));
        }).finally([e] {
            return e->queue.close().finally([e] { });
        });
    });
}

SEASTAR_TEST_CASE(test_queue_ordering_multi_ops) {
    struct env {
        env() : sem(0) {}

        utils::flush_queue<int> queue;
        std::vector<int> result;
        semaphore sem;
        size_t n = 0;
    };

    auto r = boost::irange(0, 100);

    return do_for_each(r, [](int) {
        constexpr size_t num_ops = 1000;

        auto e = make_lw_shared<env>();

        std::uniform_int_distribution<size_t> dist(0, num_ops - 1);

        for (size_t k = 0; k < num_ops*10; ++k) {
            int i = dist(e1);

            if (e->queue.has_operation(i) || (!e->queue.empty() && e->queue.highest_key() < i)) {
                e->queue.run_with_ordered_post_op(i, [e, i] {
                    return e->sem.wait().then([i] {
                        return make_ready_future<int>(i);
                    });
                }, [e](int i) {
                    e->result.emplace_back(i);
                });
                ++e->n;
            }
        }

        auto res = e->queue.wait_for_pending();

        e->sem.signal(e->n);

        return res.then([e] {
            BOOST_CHECK_EQUAL(e->result.size(), e->n);
            BOOST_REQUIRE(std::is_sorted(e->result.begin(), e->result.end()));
        }).finally([e] {
            return e->queue.close().finally([e] { });
        });
    });
}

static future<> test_propagation(bool propagate,
        noncopyable_function<future<> ()> func,
        noncopyable_function<future<> ()> post,
        noncopyable_function<void ()> thn,
        bool want_except_in_run, bool want_except_in_wait) {
    auto queue = ::make_shared<utils::flush_queue<int>>(propagate);
    auto sem = ::make_shared<semaphore>(0);
    auto xr = ::make_shared<bool>(false);
    auto xw = ::make_shared<bool>(false);

    auto f1 = queue->run_with_ordered_post_op(0, [sem, func = std::move(func)]() mutable {
        return sem->wait().then(std::move(func));
    }, std::move(post)).handle_exception([xr](auto p) {
        *xr = true;
    }).discard_result();

    auto f2 = queue->wait_for_pending(0).then(std::move(thn)).handle_exception([xw](auto p) {
        *xw = true;
    }).discard_result();

    sem->signal();

    return seastar::when_all_succeed(std::move(f1), std::move(f2)).finally([sem, queue, want_except_in_run, want_except_in_wait, xr, xw] {
        BOOST_CHECK_EQUAL(want_except_in_run, *xr);
        BOOST_CHECK_EQUAL(want_except_in_wait, *xw);
    }).finally([queue] {
        return queue->close().finally([queue] { });
    });
}

SEASTAR_TEST_CASE(test_propagate_exception_in_op) {
    return test_propagation(true, // propagate exception to waiter
                    [] { return make_exception_future(std::runtime_error("hej")); }, // ex in op
                    [] { BOOST_FAIL("should not reach (1)"); return make_ready_future(); }, // should not reach post
                    [] { BOOST_FAIL("should not reach (2)"); }, // should not reach waiter "then"
                    true,
                    true
                    );
}

SEASTAR_TEST_CASE(test_propagate_exception_in_post) {
    return test_propagation(true, // propagate exception to waiter
                    [] { return make_ready_future(); }, // ok func
                    [] { return make_exception_future(std::runtime_error("hej")); }, // ex in post
                    [] { BOOST_FAIL("should not reach"); }, // should not reach waiter "then"
                    true,
                    true
    );
}

SEASTAR_TEST_CASE(test_no_propagate_exception_in_op) {
    return test_propagation(false, // do not propagate exception to waiter
                    [] { return make_exception_future(std::runtime_error("hej")); }, // ex in op
                    [] { BOOST_FAIL("should not reach"); return make_ready_future(); }, // should not reach post
                    [] {}, // should reach waiter "then"
                    true,
                    false
                    );
}

SEASTAR_TEST_CASE(test_no_propagate_exception_in_post) {
    return test_propagation(false, // do not propagate exception to waiter
                    [] { return make_ready_future(); }, // ok func
                    [] { return make_exception_future(std::runtime_error("hej")); }, // ex in post
                    [] {}, // should reach waiter "then"
                    true,
                    false
                    );
}
<|endoftext|>


<commit_before>#include "WrappedUniversalDetector.h"

#include "universalchardet/nscore.h"
#include "universalchardet/nsUniversalDetector.h"
#include "universalchardet/nsCharSetProber.h"

class wrappedUniversalDetector:public nsUniversalDetector
{
	public:
	wrappedUniversalDetector():nsUniversalDetector(NS_FILTER_ALL) {}

	void Report(const char* aCharset) {}

	const char *charset(float &confidence)
	{
		if(!mGotData)
		{
			confidence=0;
			return 0;
		}

		if(mDetectedCharset)
		{
			confidence=1;
			return mDetectedCharset;
		}

		switch(mInputState)
		{
			case eHighbyte:
			{
				float proberConfidence;
				float maxProberConfidence = (float)0.0;
				PRInt32 maxProber = 0;

				for (PRInt32 i = 0; i < NUM_OF_CHARSET_PROBERS; i++)
				{
					proberConfidence = mCharSetProbers[i]->GetConfidence();
					if (proberConfidence > maxProberConfidence)
					{
						maxProberConfidence = proberConfidence;
						maxProber = i;
					}
				}

				confidence=maxProberConfidence;
				return mCharSetProbers[maxProber]->GetCharSetName();
			}
			break;

			case ePureAscii:
				confidence=0;
				return "US-ASCII";

			default:
				break;
		}

		confidence=0;
		return 0;
	}

	bool done()
	{
		if(mDetectedCharset) return true;
		return false;
	}

	void reset() { Reset(); }
};

extern "C" {

void *AllocUniversalDetector()
{
	return (void *)new wrappedUniversalDetector;
}

void FreeUniversalDetector(void *detectorptr)
{
	delete (wrappedUniversalDetector *)detectorptr;
}

void UniversalDetectorHandleData(void *detectorptr,const char *data,int length)
{
	wrappedUniversalDetector *detector=(wrappedUniversalDetector *)detectorptr;
	if(detector->done()) return;
	detector->HandleData(data,length);
}

void UniversalDetectorReset(void *detectorptr)
{
	wrappedUniversalDetector *detector=(wrappedUniversalDetector *)detectorptr;
	detector->reset();
}

int UniversalDetectorDone(void *detectorptr)
{
	wrappedUniversalDetector *detector=(wrappedUniversalDetector *)detectorptr;
	return detector->done()?1:0;
}

const char *UniversalDetectorCharset(void *detectorptr,float *confidence)
{
	wrappedUniversalDetector *detector=(wrappedUniversalDetector *)detectorptr;
	return detector->charset(*confidence);
}

}
<commit_msg>Fix UniversalDetector crash<commit_after>#include "WrappedUniversalDetector.h"

#include "universalchardet/nscore.h"
#include "universalchardet/nsUniversalDetector.h"
#include "universalchardet/nsCharSetProber.h"

class wrappedUniversalDetector:public nsUniversalDetector
{
	public:
	wrappedUniversalDetector():nsUniversalDetector(NS_FILTER_ALL) {}

	void Report(const char* aCharset) {}

	const char *charset(float &confidence)
	{
		if(!mGotData)
		{
			confidence=0;
			return 0;
		}

		if(mDetectedCharset)
		{
			confidence=1;
			return mDetectedCharset;
		}

		switch(mInputState)
		{
			case eHighbyte:
			{
				float proberConfidence;
				float maxProberConfidence = (float)0.0;
				PRInt32 maxProber = 0;

				for (PRInt32 i = 0; i < NUM_OF_CHARSET_PROBERS; i++)
				{
					proberConfidence = mCharSetProbers[i]->GetConfidence();
					if (proberConfidence > maxProberConfidence)
					{
						maxProberConfidence = proberConfidence;
						maxProber = i;
					}
				}

				confidence=maxProberConfidence;
				return mCharSetProbers[maxProber]->GetCharSetName();
			}
			break;

			case ePureAscii:
				confidence=0;
				return "US-ASCII";

			default:
				break;
		}

		confidence=0;
		return 0;
	}

	bool done()
	{
		if(mDetectedCharset) return true;
		return false;
	}

	void reset() { Reset(); }
};

extern "C" {

void *AllocUniversalDetector()
{
	return (void *)new wrappedUniversalDetector;
}

void FreeUniversalDetector(void *detectorptr)
{
	delete (wrappedUniversalDetector *)detectorptr;
}

void UniversalDetectorHandleData(void *detectorptr,const char *data,int length)
{
	if(length==0) return; // There seems to be a bug in UniversalDetector that accesses beyond the end of 0-length buffers.
	wrappedUniversalDetector *detector=(wrappedUniversalDetector *)detectorptr;
	if(detector->done()) return;
	detector->HandleData(data,length);
}

void UniversalDetectorReset(void *detectorptr)
{
	wrappedUniversalDetector *detector=(wrappedUniversalDetector *)detectorptr;
	detector->reset();
}

int UniversalDetectorDone(void *detectorptr)
{
	wrappedUniversalDetector *detector=(wrappedUniversalDetector *)detectorptr;
	return detector->done()?1:0;
}

const char *UniversalDetectorCharset(void *detectorptr,float *confidence)
{
	wrappedUniversalDetector *detector=(wrappedUniversalDetector *)detectorptr;
	return detector->charset(*confidence);
}

}
<|endoftext|>