<commit_before>//                            MFEM Example 30+
//
// Compile with: make osc
//
// Sample runs:  osc -m ../data/square-disc.mesh -o 1
//               osc -m ../data/square-disc.mesh -o 2
//               osc -m ../data/square-disc.mesh -o 2 -me 1e3
//               osc -m ../data/square-disc-nurbs.mesh -o 2
//               osc -m ../data/star.mesh -o 2 -eo 4
//               osc -m ../data/fichera.mesh -o 2 -me 1e4
//               osc -m ../data/disc-nurbs.mesh -o 2
//               osc -m ../data/ball-nurbs.mesh -o 2 -eo 3 -e 1e-2 -me 1e4
//               osc -m ../data/star-surf.mesh -o 2
//               osc -m ../data/square-disc-surf.mesh -o 2
//               osc -m ../data/amr-quad.mesh -l 2
//
// Description:  This is an example of adaptive mesh refinement preprocessing
//               which lowers the data oscillation [1] to a user-defined
//               relative threshold. There is no PDE being solved.
//
//               MFEM's capability to work with both conforming and
//               nonconforming meshes is demonstrated in example 6. In some
//               problems, the material data or loading data is not sufficiently
//               resolved on the initial mesh. This missing fine scale data
//               reduces the accuracy of the solution as well as the accuracy
//               of some local error estimators. By preprocessing the mesh
//               before the solving the PDE, many issues can be avoided.
//
//               [1] Morin, P., Nochetto, R. H., & Siebert, K. G. (2000).
//                   Data oscillation and convergence of adaptive FEM. SIAM
//                   Journal on Numerical Analysis, 38(2), 466-488.
//
//               [2] Mitchell, W. F. (2013). A collection of 2D elliptic
//                   problems for testing adaptive grid refinement algorithms.
//                   Applied mathematics and computation, 220, 350-364.

#include "mfem.hpp"
#include <fstream>
#include <iostream>

using namespace std;
using namespace mfem;

// Piecewise-affine function which is sometimes mesh-conforming
double affine_function(const Vector &p)
{
   double x = p(0), y = p(1);
   if (x < 0.0)
   {
      return 1.0 + x + y;
   }
   else
   {
      return 1.0;
   }
}

// Piecewise-constant function which is never mesh-conforming
double jump_function(const Vector &p)
{
   if (p.Normlp(2.0) > 0.4 && p.Normlp(2.0) < 0.6) { return 1; }
   if (p.Normlp(2.0) < 0.4 || p.Normlp(2.0) > 0.6) { return 5; }
   return 0;
}

// Singular function derived from the Laplacian of the "steep wavefront"
// problem in [2].
double singular_function(const Vector &p)
{
   double x = p(0), y = p(1);
   double alpha = 1000.0;
   double xc = 0.75, yc = 0.5;
   double r0 = 0.7;
   double r = sqrt(pow(x - xc,2.0) + pow(y - yc,2.0));
   double num = - ( alpha - pow(alpha,3) * (pow(r,2) - pow(r0,2)) );
   double denom = pow(r * ( pow(alpha,2) * pow(r0,2) + pow(alpha,2) * pow(r,2) \
                            - 2 * pow(alpha,2) * r0 * r + 1.0 ),2);
   denom = max(denom,1e-8);
   return num / denom;
}

int main(int argc, char *argv[])
{
   // 1. Parse command-line options.
   const char *mesh_file = "../data/star.mesh";
   int order = 1;
   int nc_limit = 1;
   int max_elems = 1e5;
   double double_max_elems = double(max_elems);
   bool visualization = true;
   double osc_threshold = 1e-3;
   int enriched_order = 5;

   OptionsParser args(argc, argv);
   args.AddOption(&mesh_file, "-m", "--mesh",
                  "Mesh file to use.");
   args.AddOption(&order, "-o", "--order",
                  "Finite element order (polynomial degree).");
   args.AddOption(&nc_limit, "-l", "--nc-limit",
                  "Maximum level of hanging nodes.");
   args.AddOption(&double_max_elems, "-me", "--max-elems",
                  "Stop after reaching this many elements.");
   args.AddOption(&visualization, "-vis", "--visualization", "-no-vis",
                  "--no-visualization",
                  "Enable or disable GLVis visualization.");
   args.AddOption(&osc_threshold, "-e", "--error",
                  "relative data oscillation threshold");
   args.AddOption(&enriched_order, "-eo", "--enriched_order",
                  "Enriched quadrature order.");

   args.Parse();
   if (!args.Good())
   {
      args.PrintUsage(cout);
      return 1;
   }
   args.PrintOptions(cout);

   max_elems = int(double_max_elems);
   Mesh mesh(mesh_file, 1, 1);

   // 2. Since a NURBS mesh can currently only be refined uniformly, we need to
   //    convert it to a piecewise-polynomial curved mesh. First we refine the
   //    NURBS mesh a bit more and then project the curvature to quadratic Nodes.
   if (mesh.NURBSext)
   {
      for (int i = 0; i < 2; i++)
      {
         mesh.UniformRefinement();
      }
      mesh.SetCurvature(2);
   }

   // 3. Define functions and refiner.
   FunctionCoefficient affine_coeff(affine_function);
   FunctionCoefficient jump_coeff(jump_function);
   FunctionCoefficient singular_coeff(singular_function);
   CoefficientRefiner coeffrefiner(order);

   // 4. Connect to GLVis.
   char vishost[] = "localhost";
   int  visport   = 19916;
   socketstream sol_sock;
   if (visualization)
   {
      sol_sock.open(vishost, visport);
   }

   // 5. Define custom integration rule (optional).
   const IntegrationRule *irs[Geometry::NumGeom];
   int order_quad = 2*order + enriched_order;
   for (int i=0; i < Geometry::NumGeom; ++i)
   {
      irs[i] = &(IntRules.Get(i, order_quad));
   }

   // 6. Apply custom refiner settings.
   coeffrefiner.SetIntRule(irs);
   coeffrefiner.SetMaxElements( (long) max_elems);
   coeffrefiner.SetThreshold(osc_threshold);
   coeffrefiner.SetNCLimit(nc_limit);

   // 7. Preprocess mesh to control osc (piecewise-affine function).
   //    This is mostly just a verification check. The oscillation should
   //    be zero if the function is mesh-conforming and order > 0.
   coeffrefiner.SetCoefficient(affine_coeff);
   coeffrefiner.PreprocessMesh(mesh);

   mfem::out  << "\n";
   mfem::out << "Function 0 (affine) \n";
   mfem::out << "Number of Elements " << mesh.GetNE() << "\n";
   mfem::out << "Osc error " << coeffrefiner.GetOsc() << "\n";

   // 8. Preprocess mesh to control osc (jump function).
   coeffrefiner.SetCoefficient(jump_coeff);
   coeffrefiner.PreprocessMesh(mesh);

   mfem::out  << "\n";
   mfem::out << "Function 1 (discontinuous) \n";
   mfem::out << "Number of Elements " << mesh.GetNE() << "\n";
   mfem::out << "Osc error " << coeffrefiner.GetOsc() << "\n";

   // 9. Preprocess mesh to control osc (singular function).
   coeffrefiner.SetCoefficient(singular_coeff);
   coeffrefiner.PreprocessMesh(mesh);

   mfem::out  << "\n";
   mfem::out << "Function 2 (singular) \n";
   mfem::out << "Number of Elements " << mesh.GetNE() << "\n";
   mfem::out << "Osc error " << coeffrefiner.GetOsc() << "\n";

   sol_sock.precision(8);
   sol_sock << "mesh\n" << mesh << flush;

   return 0;
}
<commit_msg>Addressing comments: Added period for conformity.<commit_after>//                            MFEM Example 30+
//
// Compile with: make osc
//
// Sample runs:  osc -m ../data/square-disc.mesh -o 1
//               osc -m ../data/square-disc.mesh -o 2
//               osc -m ../data/square-disc.mesh -o 2 -me 1e3
//               osc -m ../data/square-disc-nurbs.mesh -o 2
//               osc -m ../data/star.mesh -o 2 -eo 4
//               osc -m ../data/fichera.mesh -o 2 -me 1e4
//               osc -m ../data/disc-nurbs.mesh -o 2
//               osc -m ../data/ball-nurbs.mesh -o 2 -eo 3 -e 1e-2 -me 1e4
//               osc -m ../data/star-surf.mesh -o 2
//               osc -m ../data/square-disc-surf.mesh -o 2
//               osc -m ../data/amr-quad.mesh -l 2
//
// Description:  This is an example of adaptive mesh refinement preprocessing
//               which lowers the data oscillation [1] to a user-defined
//               relative threshold. There is no PDE being solved.
//
//               MFEM's capability to work with both conforming and
//               nonconforming meshes is demonstrated in example 6. In some
//               problems, the material data or loading data is not sufficiently
//               resolved on the initial mesh. This missing fine scale data
//               reduces the accuracy of the solution as well as the accuracy
//               of some local error estimators. By preprocessing the mesh
//               before the solving the PDE, many issues can be avoided.
//
//               [1] Morin, P., Nochetto, R. H., & Siebert, K. G. (2000).
//                   Data oscillation and convergence of adaptive FEM. SIAM
//                   Journal on Numerical Analysis, 38(2), 466-488.
//
//               [2] Mitchell, W. F. (2013). A collection of 2D elliptic
//                   problems for testing adaptive grid refinement algorithms.
//                   Applied mathematics and computation, 220, 350-364.

#include "mfem.hpp"
#include <fstream>
#include <iostream>

using namespace std;
using namespace mfem;

// Piecewise-affine function which is sometimes mesh-conforming
double affine_function(const Vector &p)
{
   double x = p(0), y = p(1);
   if (x < 0.0)
   {
      return 1.0 + x + y;
   }
   else
   {
      return 1.0;
   }
}

// Piecewise-constant function which is never mesh-conforming
double jump_function(const Vector &p)
{
   if (p.Normlp(2.0) > 0.4 && p.Normlp(2.0) < 0.6) { return 1; }
   if (p.Normlp(2.0) < 0.4 || p.Normlp(2.0) > 0.6) { return 5; }
   return 0;
}

// Singular function derived from the Laplacian of the "steep wavefront"
// problem in [2].
double singular_function(const Vector &p)
{
   double x = p(0), y = p(1);
   double alpha = 1000.0;
   double xc = 0.75, yc = 0.5;
   double r0 = 0.7;
   double r = sqrt(pow(x - xc,2.0) + pow(y - yc,2.0));
   double num = - ( alpha - pow(alpha,3) * (pow(r,2) - pow(r0,2)) );
   double denom = pow(r * ( pow(alpha,2) * pow(r0,2) + pow(alpha,2) * pow(r,2) \
                            - 2 * pow(alpha,2) * r0 * r + 1.0 ),2);
   denom = max(denom,1e-8);
   return num / denom;
}

int main(int argc, char *argv[])
{
   // 1. Parse command-line options.
   const char *mesh_file = "../data/star.mesh";
   int order = 1;
   int nc_limit = 1;
   int max_elems = 1e5;
   double double_max_elems = double(max_elems);
   bool visualization = true;
   double osc_threshold = 1e-3;
   int enriched_order = 5;

   OptionsParser args(argc, argv);
   args.AddOption(&mesh_file, "-m", "--mesh",
                  "Mesh file to use.");
   args.AddOption(&order, "-o", "--order",
                  "Finite element order (polynomial degree).");
   args.AddOption(&nc_limit, "-l", "--nc-limit",
                  "Maximum level of hanging nodes.");
   args.AddOption(&double_max_elems, "-me", "--max-elems",
                  "Stop after reaching this many elements.");
   args.AddOption(&visualization, "-vis", "--visualization", "-no-vis",
                  "--no-visualization",
                  "Enable or disable GLVis visualization.");
   args.AddOption(&osc_threshold, "-e", "--error",
                  "relative data oscillation threshold.");
   args.AddOption(&enriched_order, "-eo", "--enriched_order",
                  "Enriched quadrature order.");

   args.Parse();
   if (!args.Good())
   {
      args.PrintUsage(cout);
      return 1;
   }
   args.PrintOptions(cout);

   max_elems = int(double_max_elems);
   Mesh mesh(mesh_file, 1, 1);

   // 2. Since a NURBS mesh can currently only be refined uniformly, we need to
   //    convert it to a piecewise-polynomial curved mesh. First we refine the
   //    NURBS mesh a bit more and then project the curvature to quadratic Nodes.
   if (mesh.NURBSext)
   {
      for (int i = 0; i < 2; i++)
      {
         mesh.UniformRefinement();
      }
      mesh.SetCurvature(2);
   }

   // 3. Define functions and refiner.
   FunctionCoefficient affine_coeff(affine_function);
   FunctionCoefficient jump_coeff(jump_function);
   FunctionCoefficient singular_coeff(singular_function);
   CoefficientRefiner coeffrefiner(order);

   // 4. Connect to GLVis.
   char vishost[] = "localhost";
   int  visport   = 19916;
   socketstream sol_sock;
   if (visualization)
   {
      sol_sock.open(vishost, visport);
   }

   // 5. Define custom integration rule (optional).
   const IntegrationRule *irs[Geometry::NumGeom];
   int order_quad = 2*order + enriched_order;
   for (int i=0; i < Geometry::NumGeom; ++i)
   {
      irs[i] = &(IntRules.Get(i, order_quad));
   }

   // 6. Apply custom refiner settings.
   coeffrefiner.SetIntRule(irs);
   coeffrefiner.SetMaxElements( (long) max_elems);
   coeffrefiner.SetThreshold(osc_threshold);
   coeffrefiner.SetNCLimit(nc_limit);

   // 7. Preprocess mesh to control osc (piecewise-affine function).
   //    This is mostly just a verification check. The oscillation should
   //    be zero if the function is mesh-conforming and order > 0.
   coeffrefiner.SetCoefficient(affine_coeff);
   coeffrefiner.PreprocessMesh(mesh);

   mfem::out  << "\n";
   mfem::out << "Function 0 (affine) \n";
   mfem::out << "Number of Elements " << mesh.GetNE() << "\n";
   mfem::out << "Osc error " << coeffrefiner.GetOsc() << "\n";

   // 8. Preprocess mesh to control osc (jump function).
   coeffrefiner.SetCoefficient(jump_coeff);
   coeffrefiner.PreprocessMesh(mesh);

   mfem::out  << "\n";
   mfem::out << "Function 1 (discontinuous) \n";
   mfem::out << "Number of Elements " << mesh.GetNE() << "\n";
   mfem::out << "Osc error " << coeffrefiner.GetOsc() << "\n";

   // 9. Preprocess mesh to control osc (singular function).
   coeffrefiner.SetCoefficient(singular_coeff);
   coeffrefiner.PreprocessMesh(mesh);

   mfem::out  << "\n";
   mfem::out << "Function 2 (singular) \n";
   mfem::out << "Number of Elements " << mesh.GetNE() << "\n";
   mfem::out << "Osc error " << coeffrefiner.GetOsc() << "\n";

   sol_sock.precision(8);
   sol_sock << "mesh\n" << mesh << flush;

   return 0;
}
<|endoftext|>


<commit_before>#include <ctype.h>
#include <vector>
#include <string>
#include <errno.h>
#include <string.h>
#include <sstream>
#include <cstdlib>
#include <assert.h>

#include "PhnReader.hh"
#include "str.hh"

PhnReader::Phn::Phn()
  : start(0), end(0)
{
}

PhnReader::PhnReader(HmmSet *model)
  : m_file(NULL), m_model(model),
    m_state_num_labels(false), m_relative_sample_numbers(false)
{
  Segmentator::IndexProbPair p(-1, 1);
  set_frame_rate(125); // Default frame rate

  // Initialize the current state and its probability
  m_cur_pdf.push_back(p);
}

PhnReader::~PhnReader()
{
  close();
}

void
PhnReader::open(std::string filename)
{
  m_current_line = 0;
  m_first_line = 0;
  m_last_line = 0;
  m_first_frame = 0;
  m_last_frame = 0;
  m_current_frame = -1;
  m_eof_flag = false;

  close();

  m_file = fopen(filename.c_str(), "r");
  if (!m_file) {
    fprintf(stderr, "PhnReader::open(): could not open %s\n",
	    filename.c_str());
    perror("error");
    exit(1);
  }
}

void
PhnReader::close()
{
  if (m_file)
    fclose(m_file);
  m_file = NULL;
}

void
PhnReader::reset(void)
{
  assert( m_file != NULL );
  fseek(m_file, 0, SEEK_SET);

  m_current_line = 0;
  m_current_frame = -1;
  m_eof_flag = false;
  if (m_first_frame > 0)
    set_frame_limits(m_first_frame, m_last_frame);
  if (m_first_line > 0)
    set_line_limits(m_first_line, m_last_line, NULL);
}

void
PhnReader::set_line_limits(int first_line, int last_line,
                           int *first_frame)
{
  Phn phn;
  m_first_line = first_line;
  m_last_line = last_line;

  while (m_current_line < m_first_line)
    next_phn_line(phn);

  if (first_frame != NULL)
  {
    *first_frame = phn.start;
    if (m_relative_sample_numbers)
      (*first_frame) += m_first_frame;
  }
}

void
PhnReader::set_frame_limits(int first_frame, int last_frame)
{
  Phn phn;

  m_first_frame = first_frame;
  m_last_frame = last_frame;
  if (!m_relative_sample_numbers)
  {
    long oldpos = ftell(m_file);
    long curpos = oldpos;

    while (next_phn_line(phn)) {
      oldpos = curpos;
      curpos = ftell(m_file);
      if (phn.end < 0 || phn.end > m_first_frame)
      {
        fseek(m_file, oldpos, SEEK_SET);
        m_current_line--;
        return;
      }
    }
  }
}

bool
PhnReader::init_utterance_segmentation(void)
{
  m_eof_flag = false;
  if (!next_phn_line(m_cur_phn))
    m_eof_flag = true;
  return !m_eof_flag;
}

bool
PhnReader::next_frame(void)
{
  int cur_state_index = -1;

  assert( m_model != NULL );

  if (m_eof_flag)
    return false;

  // Segmentator object must reset the model cache during next_frame()
  m_model->reset_cache();

  if (m_current_frame == -1)
  {
    // Initialize the current frame to the beginning of the file
    m_current_frame = m_cur_phn.start;
    assert( m_cur_phn.end >= m_current_frame );
  }
  else
  {
    m_current_frame++;
  }

  assert( m_current_frame >= m_cur_phn.start );
  assert( m_current_frame <= m_cur_phn.end );

  if (m_state_num_labels)
  {
    cur_state_index = m_cur_phn.state;
  }
  else
  {
    if (m_cur_phn.state < 0)
      throw std::string("PhnReader::next_frame(): A state segmented phn file is required");
    Hmm &hmm = m_model->hmm(m_model->hmm_index(m_cur_phn.label[0]));
    cur_state_index = hmm.state(m_cur_phn.state);
  }
  m_cur_pdf.back().index = m_model->emission_pdf_index(cur_state_index);

  bool new_phn_loaded = false;
  Phn prev_phn = m_cur_phn;

  // Do we need to load more phn lines?
  while (m_current_frame+1 >= m_cur_phn.end)
  {
    if (!next_phn_line(m_cur_phn))
    {
      m_eof_flag = true; // For the next call
      break;
    }
    new_phn_loaded = true;
  }

  if (m_collect_transitions)
  {
    m_transition_info.clear();
    if (!m_eof_flag) // Not the last frame
    {
      std::vector<int> &tr_index=m_model->state(cur_state_index).transitions();
      int transition_index = -1;

      if (new_phn_loaded)
      {
        // Out transition
        if (m_state_num_labels)
        {
          // We don't have information which transition it is, select the first
          // out transition
          for (int i = 0; i < (int)tr_index.size(); i++)
            if (m_model->transition(tr_index[i]).target_offset != 0)
            {
              transition_index = tr_index[i];
              break;
            }
        }
        else
        {
          int cur_state = prev_phn.state;
          Hmm &cur_hmm = m_model->hmm(m_model->hmm_index(prev_phn.label[0]));

          // Find the correct transition
          for (int i = 0; i < (int)tr_index.size(); i++)
          {
            int next_state =
              m_model->transition(tr_index[i]).target_offset+cur_state;

            if ((next_state >= cur_hmm.num_states() &&
                 m_cur_phn.state == 0) ||
                (next_state == m_cur_phn.state))
            {
              transition_index = tr_index[i];
              break;
            }
          }
        }
      }
      else
      {
        // Self transition
        for (int i = 0; i < (int)tr_index.size(); i++)
          if (m_model->transition(tr_index[i]).target_offset == 0)
          {
            transition_index = tr_index[i];
            break;
          }
      }
      if (transition_index == -1)
      {
        throw std::string("PhnReader::next_frame(): Correct transition was not found");
      }
      if (transition_index != -1)
      {
        Segmentator::IndexProbPair new_transition(transition_index, 1);
        m_transition_info.push_back(new_transition);
      }
    }
  }

  return true;
}

bool
PhnReader::next_phn_line(Phn &phn)
{
  // Read line at time
  if (!str::read_line(&m_line, m_file)) {
    if (ferror(m_file)) {
      throw str::fmt(1024,
                     "PhnReader::next_phn_line(): read error on line %d: %s\n",
                     m_current_line, strerror(errno));
    }

    if (feof(m_file))
      return false;

    assert(false);
  }

  if (m_last_line > 0 && m_current_line >= m_last_line)
    return false;

  // Parse the line in fields.
  str::chomp(&m_line);
  std::vector<std::string> fields;

  // If the first char is digit, we have start and end fields.
  if (isdigit(m_line[0])) {
    str::split(&m_line, " \t", true, &fields, 4);
    bool ok = true;

    if (fields.size() > 2) {

      // read start & end

      phn.start = (int)(str::str2long(&fields[0], &ok)/m_samples_per_frame);
      phn.end = (int)(str::str2long(&fields[1], &ok)/m_samples_per_frame);

      // read state

      phn.state = -1; // state default value !

      if (strchr(fields[2].c_str(), '.') != NULL){
	phn.state = atoi( (const char*)(strchr(fields[2].c_str(), '.') + 1) );
	fields[2].erase(fields[2].find('.', 0), 2);
      }

    }
    else
      ok = false;

    if (!ok || phn.start > phn.end) {
      throw str::fmt(
        1024,
        "PhnReader::next_phn_line(): invalid start or end time on line %d:\n"
        "%s\n", m_current_line, m_line.c_str());
    }

    fields.erase(fields.begin(), fields.begin() + 2);
  }

  // Otherwise we have just label and comments.
  else {
    str::split(&m_line, " \t", true, &fields, 2);
    phn.start = -1;
    phn.end = -1;
  }

  if (m_relative_sample_numbers && phn.start >= 0)
  {
    phn.start += m_first_frame;
    phn.end += m_first_frame;
  }

  // Is the current starting time out of requested range?
  if (m_last_frame > 0)
  {
    if (phn.start >= m_last_frame)
      return false;
    if (phn.end >= m_last_frame)
      phn.end = m_last_frame;
  }

  if (m_first_frame > 0 && phn.start < m_first_frame && phn.start >= 0)
  {
    phn.start = m_first_frame;
    assert( phn.start > phn.end );
  }

  // Read label and comments
  phn.label.clear();
  if (m_state_num_labels)
  {
    phn.state = atoi(fields[0].c_str()); // State number instead of label
  }
  else
  {
    str::split(&fields[0], ",", false, &phn.label);
  }

  if ((int)fields.size() > 1)
    phn.comment = fields[1];
  else
    phn.comment = "";

  m_current_line++;
  return true;
}

<commit_msg>Moved state number initialization in next_phn_line()<commit_after>#include <ctype.h>
#include <vector>
#include <string>
#include <errno.h>
#include <string.h>
#include <sstream>
#include <cstdlib>
#include <assert.h>

#include "PhnReader.hh"
#include "str.hh"

PhnReader::Phn::Phn()
  : start(0), end(0)
{
}

PhnReader::PhnReader(HmmSet *model)
  : m_file(NULL), m_model(model),
    m_state_num_labels(false), m_relative_sample_numbers(false)
{
  Segmentator::IndexProbPair p(-1, 1);
  set_frame_rate(125); // Default frame rate

  // Initialize the current state and its probability
  m_cur_pdf.push_back(p);
}

PhnReader::~PhnReader()
{
  close();
}

void
PhnReader::open(std::string filename)
{
  m_current_line = 0;
  m_first_line = 0;
  m_last_line = 0;
  m_first_frame = 0;
  m_last_frame = 0;
  m_current_frame = -1;
  m_eof_flag = false;

  close();

  m_file = fopen(filename.c_str(), "r");
  if (!m_file) {
    fprintf(stderr, "PhnReader::open(): could not open %s\n",
	    filename.c_str());
    perror("error");
    exit(1);
  }
}

void
PhnReader::close()
{
  if (m_file)
    fclose(m_file);
  m_file = NULL;
}

void
PhnReader::reset(void)
{
  assert( m_file != NULL );
  fseek(m_file, 0, SEEK_SET);

  m_current_line = 0;
  m_current_frame = -1;
  m_eof_flag = false;
  if (m_first_frame > 0)
    set_frame_limits(m_first_frame, m_last_frame);
  if (m_first_line > 0)
    set_line_limits(m_first_line, m_last_line, NULL);
}

void
PhnReader::set_line_limits(int first_line, int last_line,
                           int *first_frame)
{
  Phn phn;
  m_first_line = first_line;
  m_last_line = last_line;

  while (m_current_line < m_first_line)
    next_phn_line(phn);

  if (first_frame != NULL)
  {
    *first_frame = phn.start;
    if (m_relative_sample_numbers)
      (*first_frame) += m_first_frame;
  }
}

void
PhnReader::set_frame_limits(int first_frame, int last_frame)
{
  Phn phn;

  m_first_frame = first_frame;
  m_last_frame = last_frame;
  if (!m_relative_sample_numbers)
  {
    long oldpos = ftell(m_file);
    long curpos = oldpos;

    while (next_phn_line(phn)) {
      oldpos = curpos;
      curpos = ftell(m_file);
      if (phn.end < 0 || phn.end > m_first_frame)
      {
        fseek(m_file, oldpos, SEEK_SET);
        m_current_line--;
        return;
      }
    }
  }
}

bool
PhnReader::init_utterance_segmentation(void)
{
  m_eof_flag = false;
  if (!next_phn_line(m_cur_phn))
    m_eof_flag = true;
  return !m_eof_flag;
}

bool
PhnReader::next_frame(void)
{
  int cur_state_index = -1;

  assert( m_model != NULL );

  if (m_eof_flag)
    return false;

  // Segmentator object must reset the model cache during next_frame()
  m_model->reset_cache();

  if (m_current_frame == -1)
  {
    // Initialize the current frame to the beginning of the file
    m_current_frame = m_cur_phn.start;
    assert( m_cur_phn.end >= m_current_frame );
  }
  else
  {
    m_current_frame++;
  }

  assert( m_current_frame >= m_cur_phn.start );
  assert( m_current_frame <= m_cur_phn.end );

  if (m_state_num_labels)
  {
    cur_state_index = m_cur_phn.state;
  }
  else
  {
    if (m_cur_phn.state < 0)
      throw std::string("PhnReader::next_frame(): A state segmented phn file is required");
    Hmm &hmm = m_model->hmm(m_model->hmm_index(m_cur_phn.label[0]));
    cur_state_index = hmm.state(m_cur_phn.state);
  }
  m_cur_pdf.back().index = m_model->emission_pdf_index(cur_state_index);

  bool new_phn_loaded = false;
  Phn prev_phn = m_cur_phn;

  // Do we need to load more phn lines?
  while (m_current_frame+1 >= m_cur_phn.end)
  {
    if (!next_phn_line(m_cur_phn))
    {
      m_eof_flag = true; // For the next call
      break;
    }
    new_phn_loaded = true;
  }

  if (m_collect_transitions)
  {
    m_transition_info.clear();
    if (!m_eof_flag) // Not the last frame
    {
      std::vector<int> &tr_index=m_model->state(cur_state_index).transitions();
      int transition_index = -1;

      if (new_phn_loaded)
      {
        // Out transition
        if (m_state_num_labels)
        {
          // We don't have information which transition it is, select the first
          // out transition
          for (int i = 0; i < (int)tr_index.size(); i++)
            if (m_model->transition(tr_index[i]).target_offset != 0)
            {
              transition_index = tr_index[i];
              break;
            }
        }
        else
        {
          int cur_state = prev_phn.state;
          Hmm &cur_hmm = m_model->hmm(m_model->hmm_index(prev_phn.label[0]));

          // Find the correct transition
          for (int i = 0; i < (int)tr_index.size(); i++)
          {
            int next_state =
              m_model->transition(tr_index[i]).target_offset+cur_state;

            if ((next_state >= cur_hmm.num_states() &&
                 m_cur_phn.state == 0) ||
                (next_state == m_cur_phn.state))
            {
              transition_index = tr_index[i];
              break;
            }
          }
        }
      }
      else
      {
        // Self transition
        for (int i = 0; i < (int)tr_index.size(); i++)
          if (m_model->transition(tr_index[i]).target_offset == 0)
          {
            transition_index = tr_index[i];
            break;
          }
      }
      if (transition_index == -1)
      {
        throw std::string("PhnReader::next_frame(): Correct transition was not found");
      }
      if (transition_index != -1)
      {
        Segmentator::IndexProbPair new_transition(transition_index, 1);
        m_transition_info.push_back(new_transition);
      }
    }
  }

  return true;
}

bool
PhnReader::next_phn_line(Phn &phn)
{
  // Read line at time
  if (!str::read_line(&m_line, m_file)) {
    if (ferror(m_file)) {
      throw str::fmt(1024,
                     "PhnReader::next_phn_line(): read error on line %d: %s\n",
                     m_current_line, strerror(errno));
    }

    if (feof(m_file))
      return false;

    assert(false);
  }

  if (m_last_line > 0 && m_current_line >= m_last_line)
    return false;

  // Parse the line in fields.
  str::chomp(&m_line);
  std::vector<std::string> fields;

  phn.state = -1; // state default value !

  // If the first char is digit, we have start and end fields.
  if (isdigit(m_line[0])) {
    str::split(&m_line, " \t", true, &fields, 4);
    bool ok = true;

    if (fields.size() > 2) {

      // read start & end

      phn.start = (int)(str::str2long(&fields[0], &ok)/m_samples_per_frame);
      phn.end = (int)(str::str2long(&fields[1], &ok)/m_samples_per_frame);

      // read state
      if (strchr(fields[2].c_str(), '.') != NULL){
	phn.state = atoi( (const char*)(strchr(fields[2].c_str(), '.') + 1) );
	fields[2].erase(fields[2].find('.', 0), 2);
      }

    }
    else
      ok = false;

    if (!ok || phn.start > phn.end) {
      throw str::fmt(
        1024,
        "PhnReader::next_phn_line(): invalid start or end time on line %d:\n"
        "%s\n", m_current_line, m_line.c_str());
    }

    fields.erase(fields.begin(), fields.begin() + 2);
  }

  // Otherwise we have just label and comments.
  else {
    str::split(&m_line, " \t", true, &fields, 2);
    phn.start = -1;
    phn.end = -1;
  }

  if (m_relative_sample_numbers && phn.start >= 0)
  {
    phn.start += m_first_frame;
    phn.end += m_first_frame;
  }

  // Is the current starting time out of requested range?
  if (m_last_frame > 0)
  {
    if (phn.start >= m_last_frame)
      return false;
    if (phn.end >= m_last_frame)
      phn.end = m_last_frame;
  }

  if (m_first_frame > 0 && phn.start < m_first_frame && phn.start >= 0)
  {
    phn.start = m_first_frame;
    assert( phn.start > phn.end );
  }

  // Read label and comments
  phn.label.clear();
  if (m_state_num_labels)
  {
    phn.state = atoi(fields[0].c_str()); // State number instead of label
  }
  else
  {
    str::split(&fields[0], ",", false, &phn.label);
  }

  if ((int)fields.size() > 1)
    phn.comment = fields[1];
  else
    phn.comment = "";

  m_current_line++;
  return true;
}

<|endoftext|>


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

#include <atlbase.h>
#include <atlapp.h>
#include <atlmisc.h>

#include "app/gfx/icon_util.h"
#include "base/gfx/size.h"
#include "base/scoped_ptr.h"
#include "base/file_util.h"
#include "base/path_service.h"
#include "chrome/common/chrome_paths.h"
#include "skia/include/SkBitmap.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace {

  static const wchar_t* const kSmallIconName = L"icon_util\\16_X_16_icon.ico";
  static const wchar_t* const kLargeIconName = L"icon_util\\128_X_128_icon.ico";
  static const wchar_t* const kTempIconFilename = L"temp_test_icon.ico";

  class IconUtilTest : public testing::Test {
   public:
    IconUtilTest() {
      PathService::Get(chrome::DIR_TEST_DATA, &test_data_directory_);
    }
    ~IconUtilTest() {}

    static const int kSmallIconWidth = 16;
    static const int kSmallIconHeight = 16;
    static const int kLargeIconWidth = 128;
    static const int kLargeIconHeight = 128;

    // Given a file name for an .ico file and an image dimentions, this
    // function loads the icon and returns an HICON handle.
    HICON LoadIconFromFile(const std::wstring& filename,
                           int width,
                           int height) {
      HICON icon =
          static_cast<HICON>(LoadImage(NULL,
                                       filename.c_str(),
                                       IMAGE_ICON,
                                       width,
                                       height,
                                       LR_LOADTRANSPARENT | LR_LOADFROMFILE));
      return icon;
    }

   protected:
    // The root directory for test files.
    std::wstring test_data_directory_;

   private:
    DISALLOW_EVIL_CONSTRUCTORS(IconUtilTest);
  };
};

// The following test case makes sure IconUtil::SkBitmapFromHICON fails
// gracefully when called with invalid input parameters.
TEST_F(IconUtilTest, TestIconToBitmapInvalidParameters) {
  std::wstring icon_filename(test_data_directory_);
  file_util::AppendToPath(&icon_filename, kSmallIconName);
  gfx::Size icon_size(kSmallIconWidth, kSmallIconHeight);
  HICON icon = LoadIconFromFile(icon_filename,
                                icon_size.width(),
                                icon_size.height());
  ASSERT_TRUE(icon != NULL);

  // Invalid size parameter.
  gfx::Size invalid_icon_size(kSmallIconHeight, 0);
  EXPECT_EQ(IconUtil::CreateSkBitmapFromHICON(icon, invalid_icon_size),
            static_cast<SkBitmap*>(NULL));

  // Invalid icon.
  EXPECT_EQ(IconUtil::CreateSkBitmapFromHICON(NULL, icon_size),
            static_cast<SkBitmap*>(NULL));

  // The following code should succeed.
  scoped_ptr<SkBitmap> bitmap;
  bitmap.reset(IconUtil::CreateSkBitmapFromHICON(icon, icon_size));
  EXPECT_NE(bitmap.get(), static_cast<SkBitmap*>(NULL));
  ::DestroyIcon(icon);
}

// The following test case makes sure IconUtil::CreateHICONFromSkBitmap fails
// gracefully when called with invalid input parameters.
TEST_F(IconUtilTest, TestBitmapToIconInvalidParameters) {
  HICON icon = NULL;
  scoped_ptr<SkBitmap> bitmap;

  // Wrong bitmap format.
  bitmap.reset(new SkBitmap);
  ASSERT_NE(bitmap.get(), static_cast<SkBitmap*>(NULL));
  bitmap->setConfig(SkBitmap::kA8_Config, kSmallIconWidth, kSmallIconHeight);
  icon = IconUtil::CreateHICONFromSkBitmap(*bitmap);
  EXPECT_EQ(icon, static_cast<HICON>(NULL));

  // Invalid bitmap size.
  bitmap.reset(new SkBitmap);
  ASSERT_NE(bitmap.get(), static_cast<SkBitmap*>(NULL));
  bitmap->setConfig(SkBitmap::kARGB_8888_Config, 0, 0);
  icon = IconUtil::CreateHICONFromSkBitmap(*bitmap);
  EXPECT_EQ(icon, static_cast<HICON>(NULL));

  // Valid bitmap configuration but no pixels allocated.
  bitmap.reset(new SkBitmap);
  ASSERT_NE(bitmap.get(), static_cast<SkBitmap*>(NULL));
  bitmap->setConfig(SkBitmap::kARGB_8888_Config,
                    kSmallIconWidth,
                    kSmallIconHeight);
  icon = IconUtil::CreateHICONFromSkBitmap(*bitmap);
  EXPECT_TRUE(icon == NULL);
}

// The following test case makes sure IconUtil::CreateIconFileFromSkBitmap
// fails gracefully when called with invalid input parameters.
TEST_F(IconUtilTest, TestCreateIconFileInvalidParameters) {
  scoped_ptr<SkBitmap> bitmap;
  std::wstring valid_icon_filename(test_data_directory_);
  file_util::AppendToPath(&valid_icon_filename, kSmallIconName);
  std::wstring invalid_icon_filename(L"C:\\<>?.ico");

  // Wrong bitmap format.
  bitmap.reset(new SkBitmap);
  ASSERT_NE(bitmap.get(), static_cast<SkBitmap*>(NULL));
  bitmap->setConfig(SkBitmap::kA8_Config, kSmallIconWidth, kSmallIconHeight);
  EXPECT_FALSE(IconUtil::CreateIconFileFromSkBitmap(*bitmap,
                                                    valid_icon_filename));

  // Invalid bitmap size.
  bitmap.reset(new SkBitmap);
  ASSERT_NE(bitmap.get(), static_cast<SkBitmap*>(NULL));
  bitmap->setConfig(SkBitmap::kARGB_8888_Config, 0, 0);
  EXPECT_FALSE(IconUtil::CreateIconFileFromSkBitmap(*bitmap,
                                                    valid_icon_filename));

  // Bitmap with no allocated pixels.
  bitmap.reset(new SkBitmap);
  ASSERT_NE(bitmap.get(), static_cast<SkBitmap*>(NULL));
  bitmap->setConfig(SkBitmap::kARGB_8888_Config,
                    kSmallIconWidth,
                    kSmallIconHeight);
  EXPECT_FALSE(IconUtil::CreateIconFileFromSkBitmap(*bitmap,
                                                    valid_icon_filename));

  // Invalid file name.
  bitmap->allocPixels();
  // Setting the pixels to black.
  memset(bitmap->getPixels(), 0, bitmap->width() * bitmap->height() * 4);
  EXPECT_FALSE(IconUtil::CreateIconFileFromSkBitmap(*bitmap,
                                                    invalid_icon_filename));
}

// This test case makes sure that when we load an icon from disk and convert
// the HICON into a bitmap, the bitmap has the expected format and dimentions.
TEST_F(IconUtilTest, TestCreateSkBitmapFromHICON) {
  scoped_ptr<SkBitmap> bitmap;
  std::wstring small_icon_filename(test_data_directory_);
  file_util::AppendToPath(&small_icon_filename, kSmallIconName);
  gfx::Size small_icon_size(kSmallIconWidth, kSmallIconHeight);
  HICON small_icon = LoadIconFromFile(small_icon_filename,
                                      small_icon_size.width(),
                                      small_icon_size.height());
  ASSERT_NE(small_icon, static_cast<HICON>(NULL));
  bitmap.reset(IconUtil::CreateSkBitmapFromHICON(small_icon, small_icon_size));
  ASSERT_NE(bitmap.get(), static_cast<SkBitmap*>(NULL));
  EXPECT_EQ(bitmap->width(), small_icon_size.width());
  EXPECT_EQ(bitmap->height(), small_icon_size.height());
  EXPECT_EQ(bitmap->config(), SkBitmap::kARGB_8888_Config);
  ::DestroyIcon(small_icon);

  std::wstring large_icon_filename(test_data_directory_);
  file_util::AppendToPath(&large_icon_filename, kLargeIconName);
  gfx::Size large_icon_size(kLargeIconWidth, kLargeIconHeight);
  HICON large_icon = LoadIconFromFile(large_icon_filename,
                                      large_icon_size.width(),
                                      large_icon_size.height());
  ASSERT_NE(large_icon, static_cast<HICON>(NULL));
  bitmap.reset(IconUtil::CreateSkBitmapFromHICON(large_icon, large_icon_size));
  ASSERT_NE(bitmap.get(), static_cast<SkBitmap*>(NULL));
  EXPECT_EQ(bitmap->width(), large_icon_size.width());
  EXPECT_EQ(bitmap->height(), large_icon_size.height());
  EXPECT_EQ(bitmap->config(), SkBitmap::kARGB_8888_Config);
  ::DestroyIcon(large_icon);
}

// This test case makes sure that when an HICON is created from an SkBitmap,
// the returned handle is valid and refers to an icon with the expected
// dimentions color depth etc.
TEST_F(IconUtilTest, TestBasicCreateHICONFromSkBitmap) {
  scoped_ptr<SkBitmap> bitmap;
  bitmap.reset(new SkBitmap);
  ASSERT_NE(bitmap.get(), static_cast<SkBitmap*>(NULL));
  bitmap->setConfig(SkBitmap::kARGB_8888_Config,
                    kSmallIconWidth,
                    kSmallIconHeight);
  bitmap->allocPixels();
  HICON icon = IconUtil::CreateHICONFromSkBitmap(*bitmap);
  EXPECT_NE(icon, static_cast<HICON>(NULL));
  ICONINFO icon_info;
  ASSERT_TRUE(::GetIconInfo(icon, &icon_info));
  EXPECT_TRUE(icon_info.fIcon);

  // Now that have the icon information, we should obtain the specification of
  // the icon's bitmap and make sure it matches the specification of the
  // SkBitmap we started with.
  //
  // The bitmap handle contained in the icon information is a handle to a
  // compatible bitmap so we need to call ::GetDIBits() in order to retrieve
  // the bitmap's header information.
  BITMAPINFO bitmap_info;
  ::ZeroMemory(&bitmap_info, sizeof(BITMAPINFO));
  bitmap_info.bmiHeader.biSize = sizeof(BITMAPINFO);
  HDC hdc = ::GetDC(NULL);
  int result = ::GetDIBits(hdc,
                           icon_info.hbmColor,
                           0,
                           kSmallIconWidth,
                           NULL,
                           &bitmap_info,
                           DIB_RGB_COLORS);
  ASSERT_GT(result, 0);
  EXPECT_EQ(bitmap_info.bmiHeader.biWidth, kSmallIconWidth);
  EXPECT_EQ(bitmap_info.bmiHeader.biHeight, kSmallIconHeight);
  EXPECT_EQ(bitmap_info.bmiHeader.biPlanes, 1);
  EXPECT_EQ(bitmap_info.bmiHeader.biBitCount, 32);
  ::ReleaseDC(NULL, hdc);
  ::DestroyIcon(icon);
}

// The following test case makes sure IconUtil::CreateIconFileFromSkBitmap
// creates a valid .ico file given an SkBitmap.
TEST_F(IconUtilTest, TestCreateIconFile) {
  scoped_ptr<SkBitmap> bitmap;
  std::wstring icon_filename(test_data_directory_);
  file_util::AppendToPath(&icon_filename, kTempIconFilename);

  // Allocating the bitmap.
  bitmap.reset(new SkBitmap);
  ASSERT_NE(bitmap.get(), static_cast<SkBitmap*>(NULL));
  bitmap->setConfig(SkBitmap::kARGB_8888_Config,
                    kSmallIconWidth,
                    kSmallIconHeight);
  bitmap->allocPixels();

  // Setting the pixels to black.
  memset(bitmap->getPixels(), 0, bitmap->width() * bitmap->height() * 4);

  EXPECT_TRUE(IconUtil::CreateIconFileFromSkBitmap(*bitmap,
                                                   icon_filename));

  // We are currently only testing that it is possible to load an icon from
  // the .ico file we just created. We don't really check the additional icon
  // images created by IconUtil::CreateIconFileFromSkBitmap.
  HICON icon = LoadIconFromFile(icon_filename,
                                kSmallIconWidth,
                                kSmallIconHeight);
  EXPECT_NE(icon, static_cast<HICON>(NULL));
  if (icon != NULL) {
    ::DestroyIcon(icon);
  }
}
<commit_msg>Remove unneeded ATL header includes.<commit_after>// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "app/gfx/icon_util.h"
#include "base/gfx/size.h"
#include "base/scoped_ptr.h"
#include "base/file_util.h"
#include "base/path_service.h"
#include "chrome/common/chrome_paths.h"
#include "skia/include/SkBitmap.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace {

  static const wchar_t* const kSmallIconName = L"icon_util\\16_X_16_icon.ico";
  static const wchar_t* const kLargeIconName = L"icon_util\\128_X_128_icon.ico";
  static const wchar_t* const kTempIconFilename = L"temp_test_icon.ico";

  class IconUtilTest : public testing::Test {
   public:
    IconUtilTest() {
      PathService::Get(chrome::DIR_TEST_DATA, &test_data_directory_);
    }
    ~IconUtilTest() {}

    static const int kSmallIconWidth = 16;
    static const int kSmallIconHeight = 16;
    static const int kLargeIconWidth = 128;
    static const int kLargeIconHeight = 128;

    // Given a file name for an .ico file and an image dimentions, this
    // function loads the icon and returns an HICON handle.
    HICON LoadIconFromFile(const std::wstring& filename,
                           int width,
                           int height) {
      HICON icon =
          static_cast<HICON>(LoadImage(NULL,
                                       filename.c_str(),
                                       IMAGE_ICON,
                                       width,
                                       height,
                                       LR_LOADTRANSPARENT | LR_LOADFROMFILE));
      return icon;
    }

   protected:
    // The root directory for test files.
    std::wstring test_data_directory_;

   private:
    DISALLOW_EVIL_CONSTRUCTORS(IconUtilTest);
  };
};

// The following test case makes sure IconUtil::SkBitmapFromHICON fails
// gracefully when called with invalid input parameters.
TEST_F(IconUtilTest, TestIconToBitmapInvalidParameters) {
  std::wstring icon_filename(test_data_directory_);
  file_util::AppendToPath(&icon_filename, kSmallIconName);
  gfx::Size icon_size(kSmallIconWidth, kSmallIconHeight);
  HICON icon = LoadIconFromFile(icon_filename,
                                icon_size.width(),
                                icon_size.height());
  ASSERT_TRUE(icon != NULL);

  // Invalid size parameter.
  gfx::Size invalid_icon_size(kSmallIconHeight, 0);
  EXPECT_EQ(IconUtil::CreateSkBitmapFromHICON(icon, invalid_icon_size),
            static_cast<SkBitmap*>(NULL));

  // Invalid icon.
  EXPECT_EQ(IconUtil::CreateSkBitmapFromHICON(NULL, icon_size),
            static_cast<SkBitmap*>(NULL));

  // The following code should succeed.
  scoped_ptr<SkBitmap> bitmap;
  bitmap.reset(IconUtil::CreateSkBitmapFromHICON(icon, icon_size));
  EXPECT_NE(bitmap.get(), static_cast<SkBitmap*>(NULL));
  ::DestroyIcon(icon);
}

// The following test case makes sure IconUtil::CreateHICONFromSkBitmap fails
// gracefully when called with invalid input parameters.
TEST_F(IconUtilTest, TestBitmapToIconInvalidParameters) {
  HICON icon = NULL;
  scoped_ptr<SkBitmap> bitmap;

  // Wrong bitmap format.
  bitmap.reset(new SkBitmap);
  ASSERT_NE(bitmap.get(), static_cast<SkBitmap*>(NULL));
  bitmap->setConfig(SkBitmap::kA8_Config, kSmallIconWidth, kSmallIconHeight);
  icon = IconUtil::CreateHICONFromSkBitmap(*bitmap);
  EXPECT_EQ(icon, static_cast<HICON>(NULL));

  // Invalid bitmap size.
  bitmap.reset(new SkBitmap);
  ASSERT_NE(bitmap.get(), static_cast<SkBitmap*>(NULL));
  bitmap->setConfig(SkBitmap::kARGB_8888_Config, 0, 0);
  icon = IconUtil::CreateHICONFromSkBitmap(*bitmap);
  EXPECT_EQ(icon, static_cast<HICON>(NULL));

  // Valid bitmap configuration but no pixels allocated.
  bitmap.reset(new SkBitmap);
  ASSERT_NE(bitmap.get(), static_cast<SkBitmap*>(NULL));
  bitmap->setConfig(SkBitmap::kARGB_8888_Config,
                    kSmallIconWidth,
                    kSmallIconHeight);
  icon = IconUtil::CreateHICONFromSkBitmap(*bitmap);
  EXPECT_TRUE(icon == NULL);
}

// The following test case makes sure IconUtil::CreateIconFileFromSkBitmap
// fails gracefully when called with invalid input parameters.
TEST_F(IconUtilTest, TestCreateIconFileInvalidParameters) {
  scoped_ptr<SkBitmap> bitmap;
  std::wstring valid_icon_filename(test_data_directory_);
  file_util::AppendToPath(&valid_icon_filename, kSmallIconName);
  std::wstring invalid_icon_filename(L"C:\\<>?.ico");

  // Wrong bitmap format.
  bitmap.reset(new SkBitmap);
  ASSERT_NE(bitmap.get(), static_cast<SkBitmap*>(NULL));
  bitmap->setConfig(SkBitmap::kA8_Config, kSmallIconWidth, kSmallIconHeight);
  EXPECT_FALSE(IconUtil::CreateIconFileFromSkBitmap(*bitmap,
                                                    valid_icon_filename));

  // Invalid bitmap size.
  bitmap.reset(new SkBitmap);
  ASSERT_NE(bitmap.get(), static_cast<SkBitmap*>(NULL));
  bitmap->setConfig(SkBitmap::kARGB_8888_Config, 0, 0);
  EXPECT_FALSE(IconUtil::CreateIconFileFromSkBitmap(*bitmap,
                                                    valid_icon_filename));

  // Bitmap with no allocated pixels.
  bitmap.reset(new SkBitmap);
  ASSERT_NE(bitmap.get(), static_cast<SkBitmap*>(NULL));
  bitmap->setConfig(SkBitmap::kARGB_8888_Config,
                    kSmallIconWidth,
                    kSmallIconHeight);
  EXPECT_FALSE(IconUtil::CreateIconFileFromSkBitmap(*bitmap,
                                                    valid_icon_filename));

  // Invalid file name.
  bitmap->allocPixels();
  // Setting the pixels to black.
  memset(bitmap->getPixels(), 0, bitmap->width() * bitmap->height() * 4);
  EXPECT_FALSE(IconUtil::CreateIconFileFromSkBitmap(*bitmap,
                                                    invalid_icon_filename));
}

// This test case makes sure that when we load an icon from disk and convert
// the HICON into a bitmap, the bitmap has the expected format and dimentions.
TEST_F(IconUtilTest, TestCreateSkBitmapFromHICON) {
  scoped_ptr<SkBitmap> bitmap;
  std::wstring small_icon_filename(test_data_directory_);
  file_util::AppendToPath(&small_icon_filename, kSmallIconName);
  gfx::Size small_icon_size(kSmallIconWidth, kSmallIconHeight);
  HICON small_icon = LoadIconFromFile(small_icon_filename,
                                      small_icon_size.width(),
                                      small_icon_size.height());
  ASSERT_NE(small_icon, static_cast<HICON>(NULL));
  bitmap.reset(IconUtil::CreateSkBitmapFromHICON(small_icon, small_icon_size));
  ASSERT_NE(bitmap.get(), static_cast<SkBitmap*>(NULL));
  EXPECT_EQ(bitmap->width(), small_icon_size.width());
  EXPECT_EQ(bitmap->height(), small_icon_size.height());
  EXPECT_EQ(bitmap->config(), SkBitmap::kARGB_8888_Config);
  ::DestroyIcon(small_icon);

  std::wstring large_icon_filename(test_data_directory_);
  file_util::AppendToPath(&large_icon_filename, kLargeIconName);
  gfx::Size large_icon_size(kLargeIconWidth, kLargeIconHeight);
  HICON large_icon = LoadIconFromFile(large_icon_filename,
                                      large_icon_size.width(),
                                      large_icon_size.height());
  ASSERT_NE(large_icon, static_cast<HICON>(NULL));
  bitmap.reset(IconUtil::CreateSkBitmapFromHICON(large_icon, large_icon_size));
  ASSERT_NE(bitmap.get(), static_cast<SkBitmap*>(NULL));
  EXPECT_EQ(bitmap->width(), large_icon_size.width());
  EXPECT_EQ(bitmap->height(), large_icon_size.height());
  EXPECT_EQ(bitmap->config(), SkBitmap::kARGB_8888_Config);
  ::DestroyIcon(large_icon);
}

// This test case makes sure that when an HICON is created from an SkBitmap,
// the returned handle is valid and refers to an icon with the expected
// dimentions color depth etc.
TEST_F(IconUtilTest, TestBasicCreateHICONFromSkBitmap) {
  scoped_ptr<SkBitmap> bitmap;
  bitmap.reset(new SkBitmap);
  ASSERT_NE(bitmap.get(), static_cast<SkBitmap*>(NULL));
  bitmap->setConfig(SkBitmap::kARGB_8888_Config,
                    kSmallIconWidth,
                    kSmallIconHeight);
  bitmap->allocPixels();
  HICON icon = IconUtil::CreateHICONFromSkBitmap(*bitmap);
  EXPECT_NE(icon, static_cast<HICON>(NULL));
  ICONINFO icon_info;
  ASSERT_TRUE(::GetIconInfo(icon, &icon_info));
  EXPECT_TRUE(icon_info.fIcon);

  // Now that have the icon information, we should obtain the specification of
  // the icon's bitmap and make sure it matches the specification of the
  // SkBitmap we started with.
  //
  // The bitmap handle contained in the icon information is a handle to a
  // compatible bitmap so we need to call ::GetDIBits() in order to retrieve
  // the bitmap's header information.
  BITMAPINFO bitmap_info;
  ::ZeroMemory(&bitmap_info, sizeof(BITMAPINFO));
  bitmap_info.bmiHeader.biSize = sizeof(BITMAPINFO);
  HDC hdc = ::GetDC(NULL);
  int result = ::GetDIBits(hdc,
                           icon_info.hbmColor,
                           0,
                           kSmallIconWidth,
                           NULL,
                           &bitmap_info,
                           DIB_RGB_COLORS);
  ASSERT_GT(result, 0);
  EXPECT_EQ(bitmap_info.bmiHeader.biWidth, kSmallIconWidth);
  EXPECT_EQ(bitmap_info.bmiHeader.biHeight, kSmallIconHeight);
  EXPECT_EQ(bitmap_info.bmiHeader.biPlanes, 1);
  EXPECT_EQ(bitmap_info.bmiHeader.biBitCount, 32);
  ::ReleaseDC(NULL, hdc);
  ::DestroyIcon(icon);
}

// The following test case makes sure IconUtil::CreateIconFileFromSkBitmap
// creates a valid .ico file given an SkBitmap.
TEST_F(IconUtilTest, TestCreateIconFile) {
  scoped_ptr<SkBitmap> bitmap;
  std::wstring icon_filename(test_data_directory_);
  file_util::AppendToPath(&icon_filename, kTempIconFilename);

  // Allocating the bitmap.
  bitmap.reset(new SkBitmap);
  ASSERT_NE(bitmap.get(), static_cast<SkBitmap*>(NULL));
  bitmap->setConfig(SkBitmap::kARGB_8888_Config,
                    kSmallIconWidth,
                    kSmallIconHeight);
  bitmap->allocPixels();

  // Setting the pixels to black.
  memset(bitmap->getPixels(), 0, bitmap->width() * bitmap->height() * 4);

  EXPECT_TRUE(IconUtil::CreateIconFileFromSkBitmap(*bitmap,
                                                   icon_filename));

  // We are currently only testing that it is possible to load an icon from
  // the .ico file we just created. We don't really check the additional icon
  // images created by IconUtil::CreateIconFileFromSkBitmap.
  HICON icon = LoadIconFromFile(icon_filename,
                                kSmallIconWidth,
                                kSmallIconHeight);
  EXPECT_NE(icon, static_cast<HICON>(NULL));
  if (icon != NULL) {
    ::DestroyIcon(icon);
  }
}
<|endoftext|>


<commit_before>// testIK.cpp
// Author: Ayman Habib based on Peter Loan's version
/* Copyright (c) 2005, Stanford University and Peter Loan.
*
* 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.
*/

// INCLUDES
#include <string>
#include <OpenSim/Tools/rdTools.h>
#include <OpenSim/Tools/Storage.h>
#include <OpenSim/Tools/ScaleSet.h>
#include <OpenSim/Tools/IO.h>
#include <OpenSim/Simulation/SIMM/SimmModel.h>
#include <OpenSim/Simulation/SIMM/SimmKinematicsEngine.h>
#include <OpenSim/Simulation/SIMM/SimmMarkerSet.h>
#include <OpenSim/Simulation/SIMM/SimmSubject.h>
#include <OpenSim/Simulation/SIMM/SimmMarkerData.h>
#include <OpenSim/Simulation/SIMM/SimmMotionData.h>
#include <OpenSim/Applications/IK/SimmIKSolverImpl.h>
#include <OpenSim/Applications/Scale/SimmScalerImpl.h>
#include <OpenSim/Applications/IK/SimmInverseKinematicsTarget.h>

using namespace OpenSim;
using namespace std;

string filesToCompare[] = {
	"subject_trial_ik.mot"
};
//______________________________________________________________________________
/**
* Test program to read SIMM model elements from an XML file.
*
* @param argc Number of command line arguments (should be 1).
* @param argv Command line arguments:  simmReadXML inFile
*/
int main(int argc,char **argv)
{

	// Construct model and read parameters file
	SimmSubject* subject = new SimmSubject("subject_ik_setup.xml");
	SimmModel* model = subject->createModel();
	model->setup();

	//--------------------- IK proper section
	{
		try
		{
			/* CLAY- Commented out until we fix, so things would compile...

			// Update markers to correspond to those specified in IKParams block, potentially adding new ones
			model->updateMarkers(subject->getIKParams().getMarkerSet());
			// Initialize coordinates based on user input
			model->updateCoordinates(subject->getIKParams().getCoordinateSet());

			// Get trial params
			SimmIKTrialParams& trialParams = subject->getIKParams().getTrialParams(0);
			// Handle coordinates file
			SimmMotionData* coordinateValues = trialParams.getCoordinateValues(*model);

			// Setup IK problem for trial
			// We need SimmInverseKinematicsTarget, iksolver (SimmIKSolverImpl)
			// Create SimmMarkerData Object from trc file of experimental motion data
			SimmMarkerData motionTrialData(trialParams.getMarkerDataFilename());
			motionTrialData.convertToUnits(model->getLengthUnits());
			Storage inputStorage;
			// Convert read trc fil into "common" rdStroage format
			motionTrialData.makeRdStorage(inputStorage);

			if (coordinateValues != 0) {
				// Adjust the user-defined start and end times to make sure they are in the
				// range of the marker data. This must be done so that you only look in the
				// coordinate data for rows that will actually be solved.
				double firstStateTime = inputStorage.getFirstTime();
				double lastStateTime = inputStorage.getLastTime();
				double startTime = (firstStateTime>trialParams.getStartTime()) ? firstStateTime : trialParams.getStartTime();
				double endTime =  (lastStateTime<trialParams.getEndTime()) ? lastStateTime : trialParams.getEndTime();

				// Add the coordinate data to the marker data. There must be a row of
				// corresponding coordinate data for every row of marker data that will
				// be solved, or it is a fatal error.
				coordinateValues->addToRdStorage(inputStorage, startTime, endTime);
			}

			// Create target
			SimmInverseKinematicsTarget *target = new SimmInverseKinematicsTarget(*model, inputStorage);
			// Create solver
			SimmIKSolverImpl *ikSolver = new SimmIKSolverImpl(*target);
			// Solve
			Storage	outputStorage;
			ikSolver->solveFrames(trialParams, inputStorage, outputStorage);

			OpenSim::IO::SetPrecision(6);
			outputStorage.setWriteSIMMHeader(true);
			outputStorage.print(trialParams.getOutputMotionFilename().c_str());

			delete coordinateValues;
			delete ikSolver;
			delete target;

			CLAY */
		}
		catch (Exception &x)
		{
			x.print(cout);
			cout << "Press Return to continue." << endl;
			cout.flush();
			int c = getc( stdin );
			return 1;
		}
	}
	delete subject;

	/* Compare results with standard*/
	bool success = true;
	for (int i=0; i < 1 && success; i++){
		string command = "cmp "+filesToCompare[i]+" "+"std_"+filesToCompare[i];
		success = success && (system(command.c_str())==0);
	}

	return (success?0:1);
}

<commit_msg>Commented out a few lines to make testIK compile.<commit_after>// testIK.cpp
// Author: Ayman Habib based on Peter Loan's version
/* Copyright (c) 2005, Stanford University and Peter Loan.
*
* 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.
*/

// INCLUDES
#include <string>
#include <OpenSim/Tools/rdTools.h>
#include <OpenSim/Tools/Storage.h>
#include <OpenSim/Tools/ScaleSet.h>
#include <OpenSim/Tools/IO.h>
#include <OpenSim/Simulation/SIMM/SimmModel.h>
#include <OpenSim/Simulation/SIMM/SimmKinematicsEngine.h>
#include <OpenSim/Simulation/SIMM/SimmMarkerSet.h>
#include <OpenSim/Simulation/SIMM/SimmSubject.h>
#include <OpenSim/Simulation/SIMM/SimmMarkerData.h>
#include <OpenSim/Simulation/SIMM/SimmMotionData.h>
#include <OpenSim/Applications/IK/SimmIKSolverImpl.h>
#include <OpenSim/Applications/Scale/SimmScalerImpl.h>
#include <OpenSim/Applications/IK/SimmInverseKinematicsTarget.h>

using namespace OpenSim;
using namespace std;

string filesToCompare[] = {
	"subject_trial_ik.mot"
};
//______________________________________________________________________________
/**
* Test program to read SIMM model elements from an XML file.
*
* @param argc Number of command line arguments (should be 1).
* @param argv Command line arguments:  simmReadXML inFile
*/
int main(int argc,char **argv)
{

	// Construct model and read parameters file
	SimmSubject* subject = new SimmSubject("subject_ik_setup.xml");
	SimmModel* model = subject->createModel();
	model->setup();

	//--------------------- IK proper section
	{
		try
		{
			/* CLAY- Commented out until we fix, so things would compile...

			// Update markers to correspond to those specified in IKParams block, potentially adding new ones
			model->updateMarkers(subject->getIKParams().getMarkerSet());
			// Initialize coordinates based on user input
			model->updateCoordinates(subject->getIKParams().getCoordinateSet());

			// Get trial params
			SimmIKTrialParams& trialParams = subject->getIKParams().getTrialParams(0);
			// Handle coordinates file
			SimmMotionData* coordinateValues = trialParams.getCoordinateValues(*model);

			// Setup IK problem for trial
			// We need SimmInverseKinematicsTarget, iksolver (SimmIKSolverImpl)
			// Create SimmMarkerData Object from trc file of experimental motion data
			SimmMarkerData motionTrialData(trialParams.getMarkerDataFilename());
			motionTrialData.convertToUnits(model->getLengthUnits());
			Storage inputStorage;
			// Convert read trc fil into "common" rdStroage format
			motionTrialData.makeRdStorage(inputStorage);

			if (coordinateValues != 0) {
				// Adjust the user-defined start and end times to make sure they are in the
				// range of the marker data. This must be done so that you only look in the
				// coordinate data for rows that will actually be solved.
				double firstStateTime = inputStorage.getFirstTime();
				double lastStateTime = inputStorage.getLastTime();
				double startTime = (firstStateTime>trialParams.getStartTime()) ? firstStateTime : trialParams.getStartTime();
				double endTime =  (lastStateTime<trialParams.getEndTime()) ? lastStateTime : trialParams.getEndTime();

				// Add the coordinate data to the marker data. There must be a row of
				// corresponding coordinate data for every row of marker data that will
				// be solved, or it is a fatal error.
				coordinateValues->addToRdStorage(inputStorage, startTime, endTime);
			}

			// Create target
			SimmInverseKinematicsTarget *target = new SimmInverseKinematicsTarget(*model, inputStorage);
			// Create solver
			SimmIKSolverImpl *ikSolver = new SimmIKSolverImpl(*target);
			// Solve
			Storage	outputStorage;
			ikSolver->solveFrames(trialParams, inputStorage, outputStorage);

			OpenSim::IO::SetPrecision(6);
			outputStorage.setWriteSIMMHeader(true);
			outputStorage.print(trialParams.getOutputMotionFilename().c_str());

			delete coordinateValues;
			delete ikSolver;
			delete target;

			CLAY- Commented out so things would compile. */
		}
		catch (Exception &x)
		{
			x.print(cout);
			cout << "Press Return to continue." << endl;
			cout.flush();
			int c = getc( stdin );
			return 1;
		}
	}
	delete subject;

	/* Compare results with standard*/
	bool success = true;
	for (int i=0; i < 1 && success; i++){
		string command = "cmp "+filesToCompare[i]+" "+"std_"+filesToCompare[i];
		success = success && (system(command.c_str())==0);
	}

	return (success?0:1);
}

<|endoftext|>


<commit_before>/*
Copyright (c) 2009-2010 Sony Pictures Imageworks Inc., et al.
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 Sony Pictures Imageworks nor the names of its
  contributors 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.
*/

/////////////////////////////////////////////////////////////////////////
/// \file
///
/// Shader interpreter implementation of string functions
/// such as format, concat, printf, etc.
///
/////////////////////////////////////////////////////////////////////////

#include <cstdarg>

#include <OpenImageIO/strutil.h>
#include <OpenImageIO/filesystem.h>
#include <OpenImageIO/fmath.h>

#include "oslexec_pvt.h"

#define USTR(cstr) (*((ustring *)&cstr))

OSL_NAMESPACE_ENTER
namespace pvt {

// Only define 2-arg version of concat, sort it out upstream
OSL_SHADEOP const char *
osl_concat_sss (const char *s, const char *t)
{
    size_t sl = USTR(s).length();
    size_t tl = USTR(t).length();
    size_t len = sl + tl;
    std::unique_ptr<char[]> heap_buf;
    char local_buf[256];
    char* buf = local_buf;
    if (len > sizeof(local_buf)) {
        heap_buf.reset(new char[len]);
        buf = heap_buf.get();
    }
    memcpy(buf     , s, sl);
    memcpy(buf + sl, t, tl);
    return ustring(local_buf, len).c_str();
}

OSL_SHADEOP int
osl_strlen_is (const char *s)
{
    return (int) USTR(s).length();
}

OSL_SHADEOP int
osl_hash_is (const char *s)
{
    return (int) USTR(s).hash();
}

OSL_SHADEOP int
osl_getchar_isi (const char *str, int index)
{
    return str && unsigned(index) < USTR(str).length() ? str[index] : 0;
}

    OSL_SHADEOP int
osl_startswith_iss (const char *s_, const char *substr_)
{
    ustring substr (USTR(substr_));
    size_t substr_len = substr.length();
    if (substr_len == 0)         // empty substr always matches
        return 1;
    ustring s (USTR(s_));
    size_t s_len = s.length();
    if (substr_len > s_len)      // longer needle than haystack can't
        return 0;                // match (including empty s)
    return strncmp (s.c_str(), substr.c_str(), substr_len) == 0;
}

OSL_SHADEOP int
osl_endswith_iss (const char *s_, const char *substr_)
{
    ustring substr (USTR(substr_));
    size_t substr_len = substr.length();
    if (substr_len == 0)         // empty substr always matches
        return 1;
    ustring s (USTR(s_));
    size_t s_len = s.length();
    if (substr_len > s_len)      // longer needle than haystack can't
        return 0;                // match (including empty s)
    return strncmp (s.c_str()+s_len-substr_len, substr.c_str(), substr_len) == 0;
}

OSL_SHADEOP int
osl_stoi_is (const char *str)
{
    return str ? Strutil::from_string<int>(str) : 0;
}

OSL_SHADEOP float
osl_stof_fs (const char *str)
{
    return str ? Strutil::from_string<float>(str) : 0.0f;
}

OSL_SHADEOP const char *
osl_substr_ssii (const char *s_, int start, int length)
{
    ustring s (USTR(s_));
    int slen = int (s.length());
    if (slen == 0)
        return NULL;  // No substring of empty string
    int b = start;
    if (b < 0)
        b += slen;
    b = Imath::clamp (b, 0, slen);
    return ustring(s, b, Imath::clamp (length, 0, slen)).c_str();
}

OSL_SHADEOP int
osl_regex_impl (void *sg_, const char *subject_, void *results, int nresults,
                const char *pattern, int fullmatch)
{
    ShaderGlobals *sg = (ShaderGlobals *)sg_;
    ShadingContext *ctx = sg->context;
    const std::string &subject (ustring::from_unique(subject_).string());
    match_results<std::string::const_iterator> mresults;
    const regex &regex (ctx->find_regex (USTR(pattern)));
    if (nresults > 0) {
        std::string::const_iterator start = subject.begin();
        int res = fullmatch ? regex_match (subject, mresults, regex)
                            : regex_search (subject, mresults, regex);
        int *m = (int *)results;
        for (int r = 0;  r < nresults;  ++r) {
            if (r/2 < (int)mresults.size()) {
                if ((r & 1) == 0)
                    m[r] = mresults[r/2].first - start;
                else
                    m[r] = mresults[r/2].second - start;
            } else {
                m[r] = USTR(pattern).length();
            }
        }
        return res;
    } else {
        return fullmatch ? regex_match (subject, regex)
                         : regex_search (subject, regex);
    }
}

OSL_SHADEOP const char *
osl_format (const char* format_str, ...)
{
    va_list args;
    va_start (args, format_str);
    std::string s = Strutil::vformat (format_str, args);
    va_end (args);
    return ustring(s).c_str();
}

OSL_SHADEOP void
osl_printf (ShaderGlobals *sg, const char* format_str, ...)
{
    va_list args;
    va_start (args, format_str);
#if 0
    // Make super sure we know we are excuting LLVM-generated code!
    std::string newfmt = std::string("llvm: ") + format_str;
    format_str = newfmt.c_str();
#endif
    std::string s = Strutil::vformat (format_str, args);
    va_end (args);
    sg->context->messagef("%s", s);
}

OSL_SHADEOP void
osl_error (ShaderGlobals *sg, const char* format_str, ...)
{
    va_list args;
    va_start (args, format_str);
    std::string s = Strutil::vformat (format_str, args);
    va_end (args);
    sg->context->errorf("%s", s);
}

OSL_SHADEOP void
osl_warning (ShaderGlobals *sg, const char* format_str, ...)
{
    if (sg->context->allow_warnings()) {
        va_list args;
        va_start (args, format_str);
        std::string s = Strutil::vformat (format_str, args);
        va_end (args);
        sg->context->warningf("%s", s);
    }
}

OSL_SHADEOP void
osl_fprintf (ShaderGlobals *sg, const char *filename,
             const char* format_str, ...)
{
    va_list args;
    va_start (args, format_str);
    std::string s = Strutil::vformat (format_str, args);
    va_end (args);

    static OIIO::mutex fprintf_mutex;
    OIIO::lock_guard lock (fprintf_mutex);
    FILE *file = OIIO::Filesystem::fopen (filename, "a");
    fputs (s.c_str(), file);
    fclose (file);
}

OSL_SHADEOP int
osl_split (const char *str, ustring *results, const char *sep,
           int maxsplit, int resultslen)
{
    maxsplit = OIIO::clamp (maxsplit, 0, resultslen);
    std::vector<std::string> splits;
    Strutil::split (USTR(str).string(), splits, USTR(sep).string(), maxsplit);
    int n = std::min (maxsplit, (int)splits.size());
    for (int i = 0;  i < n;  ++i)
        results[i] = ustring(splits[i]);
    return n;
}

} // end namespace pvt
OSL_NAMESPACE_EXIT
<commit_msg>Fix bug in recent string patch 1104 (#1105)<commit_after>/*
Copyright (c) 2009-2010 Sony Pictures Imageworks Inc., et al.
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 Sony Pictures Imageworks nor the names of its
  contributors 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.
*/

/////////////////////////////////////////////////////////////////////////
/// \file
///
/// Shader interpreter implementation of string functions
/// such as format, concat, printf, etc.
///
/////////////////////////////////////////////////////////////////////////

#include <cstdarg>

#include <OpenImageIO/strutil.h>
#include <OpenImageIO/filesystem.h>
#include <OpenImageIO/fmath.h>

#include "oslexec_pvt.h"

#define USTR(cstr) (*((ustring *)&cstr))

OSL_NAMESPACE_ENTER
namespace pvt {

// Only define 2-arg version of concat, sort it out upstream
OSL_SHADEOP const char *
osl_concat_sss (const char *s, const char *t)
{
    size_t sl = USTR(s).length();
    size_t tl = USTR(t).length();
    size_t len = sl + tl;
    std::unique_ptr<char[]> heap_buf;
    char local_buf[256];
    char* buf = local_buf;
    if (len > sizeof(local_buf)) {
        heap_buf.reset(new char[len]);
        buf = heap_buf.get();
    }
    memcpy(buf     , s, sl);
    memcpy(buf + sl, t, tl);
    return ustring(buf, len).c_str();
}

OSL_SHADEOP int
osl_strlen_is (const char *s)
{
    return (int) USTR(s).length();
}

OSL_SHADEOP int
osl_hash_is (const char *s)
{
    return (int) USTR(s).hash();
}

OSL_SHADEOP int
osl_getchar_isi (const char *str, int index)
{
    return str && unsigned(index) < USTR(str).length() ? str[index] : 0;
}

    OSL_SHADEOP int
osl_startswith_iss (const char *s_, const char *substr_)
{
    ustring substr (USTR(substr_));
    size_t substr_len = substr.length();
    if (substr_len == 0)         // empty substr always matches
        return 1;
    ustring s (USTR(s_));
    size_t s_len = s.length();
    if (substr_len > s_len)      // longer needle than haystack can't
        return 0;                // match (including empty s)
    return strncmp (s.c_str(), substr.c_str(), substr_len) == 0;
}

OSL_SHADEOP int
osl_endswith_iss (const char *s_, const char *substr_)
{
    ustring substr (USTR(substr_));
    size_t substr_len = substr.length();
    if (substr_len == 0)         // empty substr always matches
        return 1;
    ustring s (USTR(s_));
    size_t s_len = s.length();
    if (substr_len > s_len)      // longer needle than haystack can't
        return 0;                // match (including empty s)
    return strncmp (s.c_str()+s_len-substr_len, substr.c_str(), substr_len) == 0;
}

OSL_SHADEOP int
osl_stoi_is (const char *str)
{
    return str ? Strutil::from_string<int>(str) : 0;
}

OSL_SHADEOP float
osl_stof_fs (const char *str)
{
    return str ? Strutil::from_string<float>(str) : 0.0f;
}

OSL_SHADEOP const char *
osl_substr_ssii (const char *s_, int start, int length)
{
    ustring s (USTR(s_));
    int slen = int (s.length());
    if (slen == 0)
        return NULL;  // No substring of empty string
    int b = start;
    if (b < 0)
        b += slen;
    b = Imath::clamp (b, 0, slen);
    return ustring(s, b, Imath::clamp (length, 0, slen)).c_str();
}

OSL_SHADEOP int
osl_regex_impl (void *sg_, const char *subject_, void *results, int nresults,
                const char *pattern, int fullmatch)
{
    ShaderGlobals *sg = (ShaderGlobals *)sg_;
    ShadingContext *ctx = sg->context;
    const std::string &subject (ustring::from_unique(subject_).string());
    match_results<std::string::const_iterator> mresults;
    const regex &regex (ctx->find_regex (USTR(pattern)));
    if (nresults > 0) {
        std::string::const_iterator start = subject.begin();
        int res = fullmatch ? regex_match (subject, mresults, regex)
                            : regex_search (subject, mresults, regex);
        int *m = (int *)results;
        for (int r = 0;  r < nresults;  ++r) {
            if (r/2 < (int)mresults.size()) {
                if ((r & 1) == 0)
                    m[r] = mresults[r/2].first - start;
                else
                    m[r] = mresults[r/2].second - start;
            } else {
                m[r] = USTR(pattern).length();
            }
        }
        return res;
    } else {
        return fullmatch ? regex_match (subject, regex)
                         : regex_search (subject, regex);
    }
}

OSL_SHADEOP const char *
osl_format (const char* format_str, ...)
{
    va_list args;
    va_start (args, format_str);
    std::string s = Strutil::vformat (format_str, args);
    va_end (args);
    return ustring(s).c_str();
}

OSL_SHADEOP void
osl_printf (ShaderGlobals *sg, const char* format_str, ...)
{
    va_list args;
    va_start (args, format_str);
#if 0
    // Make super sure we know we are excuting LLVM-generated code!
    std::string newfmt = std::string("llvm: ") + format_str;
    format_str = newfmt.c_str();
#endif
    std::string s = Strutil::vformat (format_str, args);
    va_end (args);
    sg->context->messagef("%s", s);
}

OSL_SHADEOP void
osl_error (ShaderGlobals *sg, const char* format_str, ...)
{
    va_list args;
    va_start (args, format_str);
    std::string s = Strutil::vformat (format_str, args);
    va_end (args);
    sg->context->errorf("%s", s);
}

OSL_SHADEOP void
osl_warning (ShaderGlobals *sg, const char* format_str, ...)
{
    if (sg->context->allow_warnings()) {
        va_list args;
        va_start (args, format_str);
        std::string s = Strutil::vformat (format_str, args);
        va_end (args);
        sg->context->warningf("%s", s);
    }
}

OSL_SHADEOP void
osl_fprintf (ShaderGlobals *sg, const char *filename,
             const char* format_str, ...)
{
    va_list args;
    va_start (args, format_str);
    std::string s = Strutil::vformat (format_str, args);
    va_end (args);

    static OIIO::mutex fprintf_mutex;
    OIIO::lock_guard lock (fprintf_mutex);
    FILE *file = OIIO::Filesystem::fopen (filename, "a");
    fputs (s.c_str(), file);
    fclose (file);
}

OSL_SHADEOP int
osl_split (const char *str, ustring *results, const char *sep,
           int maxsplit, int resultslen)
{
    maxsplit = OIIO::clamp (maxsplit, 0, resultslen);
    std::vector<std::string> splits;
    Strutil::split (USTR(str).string(), splits, USTR(sep).string(), maxsplit);
    int n = std::min (maxsplit, (int)splits.size());
    for (int i = 0;  i < n;  ++i)
        results[i] = ustring(splits[i]);
    return n;
}

} // end namespace pvt
OSL_NAMESPACE_EXIT
<|endoftext|>


<commit_before>#include <algorithm>
#include <cstdint>
#include <vector>

#include "ExeUnpacker.h"

#include "../Utilities/Bytes.h"
#include "../Utilities/Debug.h"
#include "../Utilities/String.h"

#include "components/vfs/manager.hpp"

ExeUnpacker::ExeUnpacker(const std::string &filename)
{
	VFS::IStreamPtr stream = VFS::Manager::get().open(filename.c_str());
	Debug::check(stream != nullptr, "Exe Unpacker", "Could not open \"" + filename + "\".");

	stream->seekg(0, std::ios::end);
	const auto fileSize = stream->tellg();
	stream->seekg(0, std::ios::beg);

	std::vector<uint8_t> srcData(fileSize);
	stream->read(reinterpret_cast<char*>(srcData.data()), srcData.size());

	// Beginning and end of compressed data in the executable.
	const uint8_t *compressedStart = srcData.data() + 752;
	const uint8_t *compressedEnd = srcData.data() + (srcData.size() - 8);

	// Last word of compressed data must be 0xFFFF.
	const uint16_t lastCompWord = Bytes::getLE16(compressedEnd - 2);
	Debug::check(lastCompWord == 0xFFFF, "Exe Unpacker",
		"Invalid last compressed word \"" + String::toHexString(lastCompWord) + "\".");

	// Calculate length of decompressed data -- more precise method (for A.EXE).
	const size_t decompLen = [compressedEnd]()
	{
		const uint16_t segment = Bytes::getLE16(compressedEnd);
		const uint16_t offset = Bytes::getLE16(compressedEnd + 2);
		return (segment * 16) + offset;
	}();

	// Buffer for the decompressed data (also little endian).
	std::vector<uint8_t> decomp(decompLen);

	const size_t compressedByteCount = compressedEnd - compressedStart;
	for (size_t i = 0; i < compressedByteCount; i += 2)
	{
		const uint16_t bitArray = Bytes::getLE16(compressedStart + i);

		// Loop over each bit in the bit array.
		for (int bitIndex = 0; bitIndex < 16; ++bitIndex)
		{
			const bool bit = (bitArray & (1 << bitIndex)) != 0;

			// Default mode...

			// Decrypt mode...

			// Copy mode...

			// Maybe make lambdas for each mode, perhaps? Or private class methods?
			// A "DecompressionMode" enum class?
		}
	}

	// Keep this until the decompressor works.
	Debug::crash("Exe Unpacker", "Not implemented.");
}

ExeUnpacker::~ExeUnpacker()
{

}

const std::string &ExeUnpacker::getText() const
{
	return this->text;
}
<commit_msg>Added default and decrypt modes to A.EXE unpacker.<commit_after>#include <algorithm>
#include <array>
#include <cstdint>
#include <vector>

#include "ExeUnpacker.h"

#include "../Utilities/Bytes.h"
#include "../Utilities/Debug.h"
#include "../Utilities/String.h"

#include "components/vfs/manager.hpp"

enum class DecompressionMode
{
	Default,
	Decrypt,
	Copy
};

ExeUnpacker::ExeUnpacker(const std::string &filename)
{
	VFS::IStreamPtr stream = VFS::Manager::get().open(filename.c_str());
	Debug::check(stream != nullptr, "Exe Unpacker", "Could not open \"" + filename + "\".");

	stream->seekg(0, std::ios::end);
	const auto fileSize = stream->tellg();
	stream->seekg(0, std::ios::beg);

	std::vector<uint8_t> srcData(fileSize);
	stream->read(reinterpret_cast<char*>(srcData.data()), srcData.size());

	// Beginning and end of compressed data in the executable.
	const uint8_t *compressedStart = srcData.data() + 752;
	const uint8_t *compressedEnd = srcData.data() + (srcData.size() - 8);

	// Last word of compressed data must be 0xFFFF.
	const uint16_t lastCompWord = Bytes::getLE16(compressedEnd - 2);
	Debug::check(lastCompWord == 0xFFFF, "Exe Unpacker",
		"Invalid last compressed word \"" + String::toHexString(lastCompWord) + "\".");

	// Calculate length of decompressed data -- more precise method (for A.EXE).
	const size_t decompLen = [compressedEnd]()
	{
		const uint16_t segment = Bytes::getLE16(compressedEnd);
		const uint16_t offset = Bytes::getLE16(compressedEnd + 2);
		return (segment * 16) + offset;
	}();

	// Buffer for the decompressed data (also little endian).
	std::vector<uint8_t> decomp(decompLen);

	// Current position for inserting decompressed data.
	size_t decompIndex = 0;

	// The decompression mode determines how bits are interpreted.
	auto mode = DecompressionMode::Default;

	const size_t compressedByteCount = compressedEnd - compressedStart;
	for (size_t i = 0; i < (compressedByteCount - 1); i += 2)
	{
		const uint16_t bitArray = Bytes::getLE16(compressedStart + i);

		// Loop over each bit in the bit array.
		for (int bitIndex = 0; bitIndex < 16; ++bitIndex)
		{
			const bool bit = (bitArray & (1 << bitIndex)) != 0;

			if (mode == DecompressionMode::Default)
			{
				// The value of the bit determines the next mode.
				// - I'm thinking that a decompression "mode" is unnecessary, and the
				//   code can simply branch on the bit itself for copying or decrypting.
				//   Additionally, the mode check above is always true.
				mode = bit ? DecompressionMode::Copy : DecompressionMode::Decrypt;
			}

			if (mode == DecompressionMode::Decrypt)
			{
				// Read the next byte from the compressed data (after the bit array).
				const uint8_t encryptedByte = compressedStart[i + 2];
				i++;

				// Retrieve the XOR key based on the current bit index.
				const std::array<uint8_t, 16> keys =
				{
					15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 16
				};

				const uint8_t key = keys.at(bitIndex);
				const uint8_t decryptedByte = encryptedByte ^ key;

				// Insert the decrypted byte into the decompressed data.
				decomp.at(decompIndex) = decryptedByte;
				decompIndex++;
			}
			else if (mode == DecompressionMode::Copy)
			{

			}

			// Change back to default mode.
			mode = DecompressionMode::Default;
		}
	}

	// Keep this until the decompressor works.
	Debug::crash("Exe Unpacker", "Not implemented.");
}

ExeUnpacker::~ExeUnpacker()
{

}

const std::string &ExeUnpacker::getText() const
{
	return this->text;
}
<|endoftext|>