<commit_before>// Filename: eggBase.cxx
// Created by:  drose (14Feb00)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc.  All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license.  You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
//
// To contact the maintainers of this program write to
// panda3d-general@lists.sourceforge.net .
//
////////////////////////////////////////////////////////////////////

#include "eggBase.h"

#include "eggGroupNode.h"
#include "eggTexture.h"
#include "eggFilenameNode.h"
#include "eggComment.h"
#include "dcast.h"
#include "string_utils.h"

////////////////////////////////////////////////////////////////////
//     Function: EggBase::Constructor
//       Access: Public
//  Description:
////////////////////////////////////////////////////////////////////
EggBase::
EggBase() {
  add_option
    ("cs", "coordinate-system", 80,
     "Specify the coordinate system to operate in.  This may be one of "
     "'y-up', 'z-up', 'y-up-left', or 'z-up-left'.",
     &EggBase::dispatch_coordinate_system,
     &_got_coordinate_system, &_coordinate_system);

  _normals_mode = NM_preserve;
  _normals_threshold = 0.0;

  _got_transform = false;
  _transform = LMatrix4d::ident_mat();

  _got_coordinate_system = false;
  _coordinate_system = CS_yup_right;

  _noabs = false;
}

////////////////////////////////////////////////////////////////////
//     Function: EggBase::add_normals_options
//       Access: Public
//  Description: Adds -no, -np, etc. as valid options for this
//               program.  If the user specifies one of the options on
//               the command line, the normals will be adjusted when
//               the egg file is written out.
////////////////////////////////////////////////////////////////////
void EggBase::
add_normals_options() {
  static NormalsMode strip = NM_strip;
  static NormalsMode polygon = NM_polygon;
  static NormalsMode vertex = NM_vertex;
  static NormalsMode preserve = NM_preserve;

  add_option
    ("no", "", 48,
     "Strip all normals.",
     &EggBase::dispatch_normals, NULL, &strip);

  add_option
    ("np", "", 48,
     "Strip existing normals and redefine polygon normals.",
     &EggBase::dispatch_normals, NULL, &polygon);

  add_option
    ("nv", "threshold", 48,
     "Strip existing normals and redefine vertex normals.  Consider an edge "
     "between adjacent polygons to be smooth if the angle between them "
     "is less than threshold degrees.",
     &EggBase::dispatch_normals, NULL, &vertex);

  add_option
    ("nn", "", 48,
     "Preserve normals exactly as they are.  This is the default.",
     &EggBase::dispatch_normals, NULL, &preserve);

  add_option
    ("tbn", "name", 48,
     "Compute tangent and binormal for the named texture coordinate "
     "set(s).  The name may include wildcard characters such as * and ?.  "
     "The normal must already exist or have been computed via one of the "
     "above options.  The tangent and binormal are used to implement "
     "bump mapping and related texture-based lighting effects.  This option "
     "may be repeated as necessary to name multiple texture coordinate sets.",
     &EggBase::dispatch_vector_string, NULL, &_tbn_names);

  add_option
    ("tbnall", "", 48,
     "Compute tangent and binormal for all texture coordinate "
     "set(s).  This is equivalent to -tbn \"*\".",
     &EggBase::dispatch_none, &_got_tbnall);
}

////////////////////////////////////////////////////////////////////
//     Function: EggBase::add_transform_options
//       Access: Public
//  Description: Adds -TS, -TT, etc. as valid options for this
//               program.  If the user specifies one of the options on
//               the command line, the data will be transformed when
//               the egg file is written out.
////////////////////////////////////////////////////////////////////
void EggBase::
add_transform_options() {
  add_option
    ("TS", "sx[,sy,sz]", 49,
     "Scale the model uniformly by the given factor (if only one number "
     "is given) or in each axis by sx, sy, sz (if three numbers are given).",
     &EggBase::dispatch_scale, &_got_transform, &_transform);

  add_option
    ("TR", "x,y,z", 49,
     "Rotate the model x degrees about the x axis, then y degrees about the "
     "y axis, and then z degrees about the z axis.",
     &EggBase::dispatch_rotate_xyz, &_got_transform, &_transform);

  add_option
    ("TA", "angle,x,y,z", 49,
     "Rotate the model angle degrees counterclockwise about the given "
     "axis.",
     &EggBase::dispatch_rotate_axis, &_got_transform, &_transform);

  add_option
    ("TT", "x,y,z", 49,
     "Translate the model by the indicated amount.\n\n"
     "All transformation options (-TS, -TR, -TA, -TT) are cumulative and are "
     "applied in the order they are encountered on the command line.",
     &EggBase::dispatch_translate, &_got_transform, &_transform);
}

////////////////////////////////////////////////////////////////////
//     Function: EggBase::convert_paths
//       Access: Public, Static
//  Description: Recursively walks the egg hierarchy.  Any filenames
//               encountered are replaced according to the indicated
//               PathReplace.
////////////////////////////////////////////////////////////////////
void EggBase::
convert_paths(EggNode *node, PathReplace *path_replace,
              const DSearchPath &additional_path) {
  if (node->is_of_type(EggTexture::get_class_type())) {
    EggTexture *egg_tex = DCAST(EggTexture, node);
    Filename fullpath =
      path_replace->match_path(egg_tex->get_filename(), additional_path);
    egg_tex->set_filename(path_replace->store_path(fullpath));
    egg_tex->set_fullpath(fullpath);

    if (egg_tex->has_alpha_filename()) {
      Filename alpha_fullpath =
        path_replace->match_path(egg_tex->get_alpha_filename(), additional_path);
      egg_tex->set_alpha_filename(path_replace->store_path(alpha_fullpath));
      egg_tex->set_alpha_fullpath(alpha_fullpath);
    }

  } else if (node->is_of_type(EggFilenameNode::get_class_type())) {
    EggFilenameNode *egg_fnode = DCAST(EggFilenameNode, node);

    Filename fullpath =
      path_replace->match_path(egg_fnode->get_filename(), additional_path);
    egg_fnode->set_filename(path_replace->store_path(fullpath));
    egg_fnode->set_fullpath(fullpath);

  } else if (node->is_of_type(EggGroupNode::get_class_type())) {
    EggGroupNode *egg_group = DCAST(EggGroupNode, node);
    EggGroupNode::const_iterator ci;
    for (ci = egg_group->begin(); ci != egg_group->end(); ++ci) {
      convert_paths(*ci, path_replace, additional_path);
    }
  }
}

////////////////////////////////////////////////////////////////////
//     Function: EggBase::append_command_comment
//       Access: Protected
//  Description: Inserts a comment into the beginning of the indicated
//               egg file corresponding to the command line that
//               invoked this program.
//
//               Normally this function is called automatically when
//               appropriate by EggWriter, and it's not necessary to
//               call it explicitly.
////////////////////////////////////////////////////////////////////
void EggBase::
append_command_comment(EggData *data) {
  append_command_comment(data, get_exec_command());
}

////////////////////////////////////////////////////////////////////
//     Function: EggBase::append_command_comment
//       Access: Protected, Static
//  Description: Inserts a comment into the beginning of the indicated
//               egg file corresponding to the command line that
//               invoked this program.
//
//               Normally this function is called automatically when
//               appropriate by EggWriter, and it's not necessary to
//               call it explicitly.
////////////////////////////////////////////////////////////////////
void EggBase::
append_command_comment(EggData *data, const string &comment) {
  data->insert(data->begin(), new EggComment("", comment));
}

////////////////////////////////////////////////////////////////////
//     Function: EggBase::dispatch_normals
//       Access: Protected, Static
//  Description: Accepts one of -no, -np, etc. and sets _normals_mode
//               as indicated.  The void * argument is a pointer to a
//               NormalsMode variable that indicates which switch was
//               passed.
////////////////////////////////////////////////////////////////////
bool EggBase::
dispatch_normals(ProgramBase *self, const string &opt, const string &arg, void *mode) {
  EggBase *base = (EggBase *)self;
  return base->ns_dispatch_normals(opt, arg, mode);
}

////////////////////////////////////////////////////////////////////
//     Function: EggBase::ns_dispatch_normals
//       Access: Protected
//  Description: Accepts one of -no, -np, etc. and sets _normals_mode
//               as indicated.  The void * argument is a pointer to a
//               NormalsMode variable that indicates which switch was
//               passed.
////////////////////////////////////////////////////////////////////
bool EggBase::
ns_dispatch_normals(const string &opt, const string &arg, void *mode) {
  _normals_mode = *(NormalsMode *)mode;

  if (_normals_mode == NM_vertex) {
    if (!string_to_double(arg, _normals_threshold)) {
      nout << "Invalid numeric parameter for -" << opt << ": "
           << arg << "\n";
      return false;
    }
  }

  return true;
}

////////////////////////////////////////////////////////////////////
//     Function: EggBase::dispatch_scale
//       Access: Protected, Static
//  Description: Handles -TS, which specifies a scale transform.  Var
//               is an LMatrix4d.
////////////////////////////////////////////////////////////////////
bool EggBase::
dispatch_scale(const string &opt, const string &arg, void *var) {
  LMatrix4d *transform = (LMatrix4d *)var;

  vector_string words;
  tokenize(arg, words, ",");

  double sx, sy, sz;

  bool okflag = false;
  if (words.size() == 3) {
    okflag =
      string_to_double(words[0], sx) &&
      string_to_double(words[1], sy) &&
      string_to_double(words[2], sz);

  } else if (words.size() == 1) {
    okflag =
      string_to_double(words[0], sx);
    sy = sz = sx;
  }

  if (!okflag) {
    nout << "-" << opt
         << " requires one or three numbers separated by commas.\n";
    return false;
  }

  *transform = (*transform) * LMatrix4d::scale_mat(sx, sy, sz);

  return true;
}

////////////////////////////////////////////////////////////////////
//     Function: EggBase::dispatch_rotate_xyz
//       Access: Protected, Static
//  Description: Handles -TR, which specifies a rotate transform about
//               the three cardinal axes.  Var is an LMatrix4d.
////////////////////////////////////////////////////////////////////
bool EggBase::
dispatch_rotate_xyz(ProgramBase *self, const string &opt, const string &arg, void *var) {
  EggBase *base = (EggBase *)self;
  return base->ns_dispatch_rotate_xyz(opt, arg, var);
}

////////////////////////////////////////////////////////////////////
//     Function: EggBase::ns_dispatch_rotate_xyz
//       Access: Protected
//  Description: Handles -TR, which specifies a rotate transform about
//               the three cardinal axes.  Var is an LMatrix4d.
////////////////////////////////////////////////////////////////////
bool EggBase::
ns_dispatch_rotate_xyz(const string &opt, const string &arg, void *var) {
  LMatrix4d *transform = (LMatrix4d *)var;

  vector_string words;
  tokenize(arg, words, ",");

  LVecBase3d xyz;

  bool okflag = false;
  if (words.size() == 3) {
    okflag =
      string_to_double(words[0], xyz[0]) &&
      string_to_double(words[1], xyz[1]) &&
      string_to_double(words[2], xyz[2]);
  }

  if (!okflag) {
    nout << "-" << opt
         << " requires three numbers separated by commas.\n";
    return false;
  }

  LMatrix4d mat =
    LMatrix4d::rotate_mat(xyz[0], LVector3d(1.0, 0.0, 0.0), _coordinate_system) *
    LMatrix4d::rotate_mat(xyz[1], LVector3d(0.0, 1.0, 0.0), _coordinate_system) *
    LMatrix4d::rotate_mat(xyz[2], LVector3d(0.0, 0.0, 1.0), _coordinate_system);

  *transform = (*transform) * mat;

  return true;
}

////////////////////////////////////////////////////////////////////
//     Function: EggBase::dispatch_rotate_axis
//       Access: Protected, Static
//  Description: Handles -TA, which specifies a rotate transform about
//               an arbitrary axis.  Var is an LMatrix4d.
////////////////////////////////////////////////////////////////////
bool EggBase::
dispatch_rotate_axis(ProgramBase *self, const string &opt, const string &arg, void *var) {
  EggBase *base = (EggBase *)self;
  return base->ns_dispatch_rotate_axis(opt, arg, var);
}

////////////////////////////////////////////////////////////////////
//     Function: EggBase::ns_dispatch_rotate_axis
//       Access: Protected
//  Description: Handles -TA, which specifies a rotate transform about
//               an arbitrary axis.  Var is an LMatrix4d.
////////////////////////////////////////////////////////////////////
bool EggBase::
ns_dispatch_rotate_axis(const string &opt, const string &arg, void *var) {
  LMatrix4d *transform = (LMatrix4d *)var;

  vector_string words;
  tokenize(arg, words, ",");

  double angle;
  LVecBase3d axis;

  bool okflag = false;
  if (words.size() == 4) {
    okflag =
      string_to_double(words[0], angle) &&
      string_to_double(words[1], axis[0]) &&
      string_to_double(words[2], axis[1]) &&
      string_to_double(words[3], axis[2]);
  }

  if (!okflag) {
    nout << "-" << opt
         << " requires four numbers separated by commas.\n";
    return false;
  }

  *transform = (*transform) * LMatrix4d::rotate_mat(angle, axis, _coordinate_system);

  return true;
}

////////////////////////////////////////////////////////////////////
//     Function: EggBase::dispatch_translate
//       Access: Protected, Static
//  Description: Handles -TT, which specifies a translate transform.
//               Var is an LMatrix4d.
////////////////////////////////////////////////////////////////////
bool EggBase::
dispatch_translate(const string &opt, const string &arg, void *var) {
  LMatrix4d *transform = (LMatrix4d *)var;

  vector_string words;
  tokenize(arg, words, ",");

  LVector3d trans;

  bool okflag = false;
  if (words.size() == 3) {
    okflag =
      string_to_double(words[0], trans[0]) &&
      string_to_double(words[1], trans[1]) &&
      string_to_double(words[2], trans[2]);
  }

  if (!okflag) {
    nout << "-" << opt
         << " requires three numbers separated by commas.\n";
    return false;
  }

  *transform = (*transform) * LMatrix4d::translate_mat(trans);

  return true;
}
<commit_msg>minor typo<commit_after>// Filename: eggBase.cxx
// Created by:  drose (14Feb00)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc.  All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license.  You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
//
// To contact the maintainers of this program write to
// panda3d-general@lists.sourceforge.net .
//
////////////////////////////////////////////////////////////////////

#include "eggBase.h"

#include "eggGroupNode.h"
#include "eggTexture.h"
#include "eggFilenameNode.h"
#include "eggComment.h"
#include "dcast.h"
#include "string_utils.h"

////////////////////////////////////////////////////////////////////
//     Function: EggBase::Constructor
//       Access: Public
//  Description:
////////////////////////////////////////////////////////////////////
EggBase::
EggBase() {
  add_option
    ("cs", "coordinate-system", 80,
     "Specify the coordinate system to operate in.  This may be one of "
     "'y-up', 'z-up', 'y-up-left', or 'z-up-left'.",
     &EggBase::dispatch_coordinate_system,
     &_got_coordinate_system, &_coordinate_system);

  _normals_mode = NM_preserve;
  _normals_threshold = 0.0;

  _got_transform = false;
  _transform = LMatrix4d::ident_mat();

  _got_coordinate_system = false;
  _coordinate_system = CS_yup_right;

  _noabs = false;
}

////////////////////////////////////////////////////////////////////
//     Function: EggBase::add_normals_options
//       Access: Public
//  Description: Adds -no, -np, etc. as valid options for this
//               program.  If the user specifies one of the options on
//               the command line, the normals will be adjusted when
//               the egg file is written out.
////////////////////////////////////////////////////////////////////
void EggBase::
add_normals_options() {
  static NormalsMode strip = NM_strip;
  static NormalsMode polygon = NM_polygon;
  static NormalsMode vertex = NM_vertex;
  static NormalsMode preserve = NM_preserve;

  add_option
    ("no", "", 48,
     "Strip all normals.",
     &EggBase::dispatch_normals, NULL, &strip);

  add_option
    ("np", "", 48,
     "Strip existing normals and redefine polygon normals.",
     &EggBase::dispatch_normals, NULL, &polygon);

  add_option
    ("nv", "threshold", 48,
     "Strip existing normals and redefine vertex normals.  Consider an edge "
     "between adjacent polygons to be smooth if the angle between them "
     "is less than threshold degrees.",
     &EggBase::dispatch_normals, NULL, &vertex);

  add_option
    ("nn", "", 48,
     "Preserve normals exactly as they are.  This is the default.",
     &EggBase::dispatch_normals, NULL, &preserve);

  add_option
    ("tbn", "name", 48,
     "Compute tangent and binormal for the named texture coordinate "
     "set(s).  The name may include wildcard characters such as * and ?.  "
     "The normal must already exist or have been computed via one of the "
     "above options.  The tangent and binormal are used to implement "
     "bump mapping and related texture-based lighting effects.  This option "
     "may be repeated as necessary to name multiple texture coordinate sets.",
     &EggBase::dispatch_vector_string, NULL, &_tbn_names);

  add_option
    ("tbnall", "", 48,
     "Compute tangent and binormal for all texture coordinate "
     "sets.  This is equivalent to -tbn \"*\".",
     &EggBase::dispatch_none, &_got_tbnall);
}

////////////////////////////////////////////////////////////////////
//     Function: EggBase::add_transform_options
//       Access: Public
//  Description: Adds -TS, -TT, etc. as valid options for this
//               program.  If the user specifies one of the options on
//               the command line, the data will be transformed when
//               the egg file is written out.
////////////////////////////////////////////////////////////////////
void EggBase::
add_transform_options() {
  add_option
    ("TS", "sx[,sy,sz]", 49,
     "Scale the model uniformly by the given factor (if only one number "
     "is given) or in each axis by sx, sy, sz (if three numbers are given).",
     &EggBase::dispatch_scale, &_got_transform, &_transform);

  add_option
    ("TR", "x,y,z", 49,
     "Rotate the model x degrees about the x axis, then y degrees about the "
     "y axis, and then z degrees about the z axis.",
     &EggBase::dispatch_rotate_xyz, &_got_transform, &_transform);

  add_option
    ("TA", "angle,x,y,z", 49,
     "Rotate the model angle degrees counterclockwise about the given "
     "axis.",
     &EggBase::dispatch_rotate_axis, &_got_transform, &_transform);

  add_option
    ("TT", "x,y,z", 49,
     "Translate the model by the indicated amount.\n\n"
     "All transformation options (-TS, -TR, -TA, -TT) are cumulative and are "
     "applied in the order they are encountered on the command line.",
     &EggBase::dispatch_translate, &_got_transform, &_transform);
}

////////////////////////////////////////////////////////////////////
//     Function: EggBase::convert_paths
//       Access: Public, Static
//  Description: Recursively walks the egg hierarchy.  Any filenames
//               encountered are replaced according to the indicated
//               PathReplace.
////////////////////////////////////////////////////////////////////
void EggBase::
convert_paths(EggNode *node, PathReplace *path_replace,
              const DSearchPath &additional_path) {
  if (node->is_of_type(EggTexture::get_class_type())) {
    EggTexture *egg_tex = DCAST(EggTexture, node);
    Filename fullpath =
      path_replace->match_path(egg_tex->get_filename(), additional_path);
    egg_tex->set_filename(path_replace->store_path(fullpath));
    egg_tex->set_fullpath(fullpath);

    if (egg_tex->has_alpha_filename()) {
      Filename alpha_fullpath =
        path_replace->match_path(egg_tex->get_alpha_filename(), additional_path);
      egg_tex->set_alpha_filename(path_replace->store_path(alpha_fullpath));
      egg_tex->set_alpha_fullpath(alpha_fullpath);
    }

  } else if (node->is_of_type(EggFilenameNode::get_class_type())) {
    EggFilenameNode *egg_fnode = DCAST(EggFilenameNode, node);

    Filename fullpath =
      path_replace->match_path(egg_fnode->get_filename(), additional_path);
    egg_fnode->set_filename(path_replace->store_path(fullpath));
    egg_fnode->set_fullpath(fullpath);

  } else if (node->is_of_type(EggGroupNode::get_class_type())) {
    EggGroupNode *egg_group = DCAST(EggGroupNode, node);
    EggGroupNode::const_iterator ci;
    for (ci = egg_group->begin(); ci != egg_group->end(); ++ci) {
      convert_paths(*ci, path_replace, additional_path);
    }
  }
}

////////////////////////////////////////////////////////////////////
//     Function: EggBase::append_command_comment
//       Access: Protected
//  Description: Inserts a comment into the beginning of the indicated
//               egg file corresponding to the command line that
//               invoked this program.
//
//               Normally this function is called automatically when
//               appropriate by EggWriter, and it's not necessary to
//               call it explicitly.
////////////////////////////////////////////////////////////////////
void EggBase::
append_command_comment(EggData *data) {
  append_command_comment(data, get_exec_command());
}

////////////////////////////////////////////////////////////////////
//     Function: EggBase::append_command_comment
//       Access: Protected, Static
//  Description: Inserts a comment into the beginning of the indicated
//               egg file corresponding to the command line that
//               invoked this program.
//
//               Normally this function is called automatically when
//               appropriate by EggWriter, and it's not necessary to
//               call it explicitly.
////////////////////////////////////////////////////////////////////
void EggBase::
append_command_comment(EggData *data, const string &comment) {
  data->insert(data->begin(), new EggComment("", comment));
}

////////////////////////////////////////////////////////////////////
//     Function: EggBase::dispatch_normals
//       Access: Protected, Static
//  Description: Accepts one of -no, -np, etc. and sets _normals_mode
//               as indicated.  The void * argument is a pointer to a
//               NormalsMode variable that indicates which switch was
//               passed.
////////////////////////////////////////////////////////////////////
bool EggBase::
dispatch_normals(ProgramBase *self, const string &opt, const string &arg, void *mode) {
  EggBase *base = (EggBase *)self;
  return base->ns_dispatch_normals(opt, arg, mode);
}

////////////////////////////////////////////////////////////////////
//     Function: EggBase::ns_dispatch_normals
//       Access: Protected
//  Description: Accepts one of -no, -np, etc. and sets _normals_mode
//               as indicated.  The void * argument is a pointer to a
//               NormalsMode variable that indicates which switch was
//               passed.
////////////////////////////////////////////////////////////////////
bool EggBase::
ns_dispatch_normals(const string &opt, const string &arg, void *mode) {
  _normals_mode = *(NormalsMode *)mode;

  if (_normals_mode == NM_vertex) {
    if (!string_to_double(arg, _normals_threshold)) {
      nout << "Invalid numeric parameter for -" << opt << ": "
           << arg << "\n";
      return false;
    }
  }

  return true;
}

////////////////////////////////////////////////////////////////////
//     Function: EggBase::dispatch_scale
//       Access: Protected, Static
//  Description: Handles -TS, which specifies a scale transform.  Var
//               is an LMatrix4d.
////////////////////////////////////////////////////////////////////
bool EggBase::
dispatch_scale(const string &opt, const string &arg, void *var) {
  LMatrix4d *transform = (LMatrix4d *)var;

  vector_string words;
  tokenize(arg, words, ",");

  double sx, sy, sz;

  bool okflag = false;
  if (words.size() == 3) {
    okflag =
      string_to_double(words[0], sx) &&
      string_to_double(words[1], sy) &&
      string_to_double(words[2], sz);

  } else if (words.size() == 1) {
    okflag =
      string_to_double(words[0], sx);
    sy = sz = sx;
  }

  if (!okflag) {
    nout << "-" << opt
         << " requires one or three numbers separated by commas.\n";
    return false;
  }

  *transform = (*transform) * LMatrix4d::scale_mat(sx, sy, sz);

  return true;
}

////////////////////////////////////////////////////////////////////
//     Function: EggBase::dispatch_rotate_xyz
//       Access: Protected, Static
//  Description: Handles -TR, which specifies a rotate transform about
//               the three cardinal axes.  Var is an LMatrix4d.
////////////////////////////////////////////////////////////////////
bool EggBase::
dispatch_rotate_xyz(ProgramBase *self, const string &opt, const string &arg, void *var) {
  EggBase *base = (EggBase *)self;
  return base->ns_dispatch_rotate_xyz(opt, arg, var);
}

////////////////////////////////////////////////////////////////////
//     Function: EggBase::ns_dispatch_rotate_xyz
//       Access: Protected
//  Description: Handles -TR, which specifies a rotate transform about
//               the three cardinal axes.  Var is an LMatrix4d.
////////////////////////////////////////////////////////////////////
bool EggBase::
ns_dispatch_rotate_xyz(const string &opt, const string &arg, void *var) {
  LMatrix4d *transform = (LMatrix4d *)var;

  vector_string words;
  tokenize(arg, words, ",");

  LVecBase3d xyz;

  bool okflag = false;
  if (words.size() == 3) {
    okflag =
      string_to_double(words[0], xyz[0]) &&
      string_to_double(words[1], xyz[1]) &&
      string_to_double(words[2], xyz[2]);
  }

  if (!okflag) {
    nout << "-" << opt
         << " requires three numbers separated by commas.\n";
    return false;
  }

  LMatrix4d mat =
    LMatrix4d::rotate_mat(xyz[0], LVector3d(1.0, 0.0, 0.0), _coordinate_system) *
    LMatrix4d::rotate_mat(xyz[1], LVector3d(0.0, 1.0, 0.0), _coordinate_system) *
    LMatrix4d::rotate_mat(xyz[2], LVector3d(0.0, 0.0, 1.0), _coordinate_system);

  *transform = (*transform) * mat;

  return true;
}

////////////////////////////////////////////////////////////////////
//     Function: EggBase::dispatch_rotate_axis
//       Access: Protected, Static
//  Description: Handles -TA, which specifies a rotate transform about
//               an arbitrary axis.  Var is an LMatrix4d.
////////////////////////////////////////////////////////////////////
bool EggBase::
dispatch_rotate_axis(ProgramBase *self, const string &opt, const string &arg, void *var) {
  EggBase *base = (EggBase *)self;
  return base->ns_dispatch_rotate_axis(opt, arg, var);
}

////////////////////////////////////////////////////////////////////
//     Function: EggBase::ns_dispatch_rotate_axis
//       Access: Protected
//  Description: Handles -TA, which specifies a rotate transform about
//               an arbitrary axis.  Var is an LMatrix4d.
////////////////////////////////////////////////////////////////////
bool EggBase::
ns_dispatch_rotate_axis(const string &opt, const string &arg, void *var) {
  LMatrix4d *transform = (LMatrix4d *)var;

  vector_string words;
  tokenize(arg, words, ",");

  double angle;
  LVecBase3d axis;

  bool okflag = false;
  if (words.size() == 4) {
    okflag =
      string_to_double(words[0], angle) &&
      string_to_double(words[1], axis[0]) &&
      string_to_double(words[2], axis[1]) &&
      string_to_double(words[3], axis[2]);
  }

  if (!okflag) {
    nout << "-" << opt
         << " requires four numbers separated by commas.\n";
    return false;
  }

  *transform = (*transform) * LMatrix4d::rotate_mat(angle, axis, _coordinate_system);

  return true;
}

////////////////////////////////////////////////////////////////////
//     Function: EggBase::dispatch_translate
//       Access: Protected, Static
//  Description: Handles -TT, which specifies a translate transform.
//               Var is an LMatrix4d.
////////////////////////////////////////////////////////////////////
bool EggBase::
dispatch_translate(const string &opt, const string &arg, void *var) {
  LMatrix4d *transform = (LMatrix4d *)var;

  vector_string words;
  tokenize(arg, words, ",");

  LVector3d trans;

  bool okflag = false;
  if (words.size() == 3) {
    okflag =
      string_to_double(words[0], trans[0]) &&
      string_to_double(words[1], trans[1]) &&
      string_to_double(words[2], trans[2]);
  }

  if (!okflag) {
    nout << "-" << opt
         << " requires three numbers separated by commas.\n";
    return false;
  }

  *transform = (*transform) * LMatrix4d::translate_mat(trans);

  return true;
}
<|endoftext|>


<commit_before>// WindowsPowerManagement.cpp : Defines the entry point for the console application.
//

#include<stdio.h>
#include<Windows.h>
#include<PowrProf.h>

void GetAll() {
	GUID guid;
	DWORD guidSize = sizeof(guid);
	unsigned int schemeIndex = 0;
	while (PowerEnumerate(0, 0, 0, ACCESS_SCHEME, schemeIndex, (UCHAR*)&guid, &guidSize) == 0) {
		// buffer contains the GUID
		UCHAR name[2048];
		DWORD nameSize = 2048;
		DWORD error;
		if ((error = PowerReadFriendlyName(0, &guid, &NO_SUBGROUP_GUID, 0, name, &nameSize)) == 0) {
			for (int i = 0; i < nameSize; i+=2) printf("%c", name[i]);
			printf("\n");
		}
		else {
			printf("Error: %d\n", error);
		}

		GUID subguid;
		DWORD subguidSize = sizeof(subguid);
		unsigned int subgroupIndex = 0;
		while (PowerEnumerate(0, &guid, 0, ACCESS_SUBGROUP, subgroupIndex, (UCHAR*)&subguid, &subguidSize) == 0) {
			nameSize = 2048;
			if ((error = PowerReadFriendlyName(0, &guid, &subguid, 0, name, &nameSize)) == 0) {
				printf("  ");
				for (int i = 0; i < nameSize; i += 2) printf("%c", name[i]);
				printf("\n");
			}
			else {
				printf("Subgroup Error: %d\n", error);
			}

			GUID settingguid;
			DWORD settingguidSize = sizeof(settingguid);
			unsigned int settingIndex = 0;
			while (PowerEnumerate(0, &guid, &subguid, ACCESS_INDIVIDUAL_SETTING, settingIndex, (UCHAR*)&settingguid, &settingguidSize) == 0) {
				nameSize = 2048;
				if ((error = PowerReadFriendlyName(0, &guid, &subguid, &settingguid, name, &nameSize)) == 0) {
					printf("    ");
					for (int i = 0; i < nameSize; i += 2) printf("%c", name[i]);
					printf("\n");
				}
				else {
					printf("Setting Error: %d\n", error);
				}

				DWORD minvalue = 0;
				DWORD maxvalue = 0;
				nameSize = 2048;
				if ((error = PowerReadPossibleValue(0, &subguid, &settingguid, 0, settingIndex, name, &nameSize)) == 0) {
					PowerReadValueMin(0, &subguid, &settingguid, &minvalue);
					PowerReadValueMax(0, &subguid, &settingguid, &maxvalue);
					printf("      ");
					for (int i = 0; i < nameSize; i++) printf("%d ", name[i]);
					printf(" (%d - %d)\n", minvalue, maxvalue);
				}
				else {
					printf("Read Error: %d\n", error);
				}

				settingIndex++;
			}

			subgroupIndex++;
		}

		schemeIndex++;
	}
}

int main()
{
	GetAll();
	int pause;
	scanf_s("%d\n", &pause);
    return 0;
}

<commit_msg>Prints current values of settings and default value of settings<commit_after>// WindowsPowerManagement.cpp : Defines the entry point for the console application.
//

#include<stdio.h>
#include<Windows.h>
#include<PowrProf.h>
#include<string>

void GetAll() {
	GUID guid;
	DWORD guidSize = sizeof(guid);
	unsigned int schemeIndex = 0;
	while (PowerEnumerate(0, 0, 0, ACCESS_SCHEME, schemeIndex, (UCHAR*)&guid, &guidSize) == 0) {
		// buffer contains the GUID
		UCHAR name[2048];
		DWORD nameSize = 2048;
		DWORD error;
		if ((error = PowerReadFriendlyName(0, &guid, &NO_SUBGROUP_GUID, 0, name, &nameSize)) == 0) {
			for (int i = 0; i < nameSize; i+=2) printf("%c", name[i]);
			printf("\n");
		}
		else {
			printf("Error: %d\n", error);
		}

		GUID subguid;
		DWORD subguidSize = sizeof(subguid);
		unsigned int subgroupIndex = 0;
		while (PowerEnumerate(0, &guid, 0, ACCESS_SUBGROUP, subgroupIndex, (UCHAR*)&subguid, &subguidSize) == 0) {
			nameSize = 2048;
			if ((error = PowerReadFriendlyName(0, &guid, &subguid, 0, name, &nameSize)) == 0) {
				printf("  ");
				for (int i = 0; i < nameSize; i += 2) printf("%c", name[i]);
				printf("\n");
			}
			else {
				printf("Subgroup Error: %d\n", error);
			}

			GUID settingguid;
			DWORD settingguidSize = sizeof(settingguid);
			unsigned int settingIndex = 0;
			while (PowerEnumerate(0, &guid, &subguid, ACCESS_INDIVIDUAL_SETTING, settingIndex, (UCHAR*)&settingguid, &settingguidSize) == 0) {
				nameSize = 2048;
				if ((error = PowerReadFriendlyName(0, &guid, &subguid, &settingguid, name, &nameSize)) == 0) {
					printf("    ");
					for (int i = 0; i < nameSize; i += 2) printf("%c", name[i]);
					printf("\n");
				}
				else {
					printf("Setting Error: %d\n", error);
				}

				DWORD DCValueIndex = 0;
				DWORD DCDefaultIndex = 0;
				PowerReadDCValueIndex(0, &guid, &subguid, &settingguid, &DCValueIndex);
				PowerReadDCDefaultIndex(0, &guid, &subguid, &settingguid, &DCDefaultIndex);
				printf("    ");
				printf(" Value: %d, Default: %d\n", DCValueIndex, DCDefaultIndex);

				settingIndex++;
			}

			subgroupIndex++;
		}

		schemeIndex++;
	}
}

int main()
{
	GetAll();
	int pause;
	scanf_s("%d\n", &pause);
    return 0;
}

<|endoftext|>


<commit_before>#include "sqliteindexreader.h"
#include "sqliteindexmanager.h"
#include <sqlite3.h>
#include <set>
using namespace std;

SqliteIndexReader::SqliteIndexReader(SqliteIndexManager* m) :manager(m) {

    int r = sqlite3_open(manager->getDBFile(), &db);
    // any value other than SQLITE_OK is an error
    if (r != SQLITE_OK) {
        printf("could not open db\n");
        db = 0;
        return;
    }
    // speed up by being unsafe (we're only reading anyway)
    r = sqlite3_exec(db, "PRAGMA synchronous = OFF", 0, 0, 0);
    if (r != SQLITE_OK) {
        printf("could not speed up database\n");
    }
}
SqliteIndexReader::~SqliteIndexReader() {
    if (db) {
        int r = sqlite3_close(db);
        if (r != SQLITE_OK) {
            printf("could not create table\n");
        }
    }
}
int
sqliteindexreadercallback(void*arg, int, char**v, char**) {
    std::vector<std::string>& results = *(std::vector<std::string>*)arg;
    results.push_back(v[1]);
    return 0;
}
set<string>
split(const std::string& q) {
    set<string> terms;
    uint pos = q.find(' ');
    uint offset = 0;
    while (pos != string::npos) {
        if (pos-offset > 0) {
            terms.insert(q.substr(offset, pos-offset));
        }
        offset = pos+1;
        pos = q.find(' ', offset);
    }
    if (offset < q.length()) {
        terms.insert(q.substr(offset));
    }
    return terms;
}
#include <sstream>
string
createQueryold(int n) {
    ostringstream q;
    q << "select path from files f ";
    for (int i=0; i<n; ++i) {
        char a = i+'a';
        q <<"join filewords f"<<a<<" on f.rowid = f"<<a<<".fileid join words w"
          <<a<<" on f"<<a<<".wordid = w"<<a<<".wordid ";
    }
    q << "where ";
    for (int i=0; i<n; ++i) {
        char a = i+'a';
        if (i > 0) q << "and ";
        q <<"w"<<a<<".word like ? ";
    }
    return q.str();
}
string
createQuery(int n) {
    // TODO: makeing a query with wildcards slows things down, so we must
    // think about reordering them
    // although we'll never be able to manage queries like 'a% b% c%'
    ostringstream q;
    q << "select path, ";
    // the points for a file is the sum of the fraction of the total occurances
    // of that word in this file
    for (int i=0; i<n; ++i) {
        char a = i+'a';
        if (i > 0) q<<"+";
        q << "f"<<a<<".count*1.0/w"<<a<<".count";
    }
    q << " p from ";
    for (int i=0; i<n; ++i) {
        char a = i+'a';
        q <<"words w"<<a<<",";
    }
    for (int i=0; i<n; ++i) {
        char a = i+'a';
        q <<"filewords f"<<a<<",";
    }
    q <<"files where ";
    for (int i=0; i<n; ++i) {
        char a = i+'a';
        q <<"w"<<a<<".word like ? and w"<<a<<".wordid = f"<<a<<".wordid and ";
    }
    for (int i=1; i<n; ++i) {
        char a = i+'a'-1;
        char b = i+'a';
        q <<"f"<<a<<".fileid = f"<<b<<".fileid and ";
    }
    q <<"fa.fileid = files.rowid order by p limit 100";
    return q.str();
}
vector<string>
SqliteIndexReader::query(const std::string& query) {
    string q = query;
    // replace ' by ''
    size_t p = q.find('\'');
    while (p != string::npos) {
        q.replace(p, 1, "''");
        p = q.find('\'', p+2);
    }
    // replace * by %
    p = q.find('*');
    while (p != string::npos) {
        q.replace(p, 1, "%");
        p = q.find('*');
    }
    // replace ? by _
    p = q.find('?');
    while (p != string::npos) {
        q.replace(p, 1, "_");
        p = q.find('?');
    }
    // split up in terms
    set<string> terms = split(query);
    std::vector<std::string> results;
    if (terms.size() == 0) return results;

    // this sql probably warants some explanation
/*    string sql = "select sp, path from (select fileid, sum(p) sp from ("
        "select fileid, f.count*1.0/w.count p "
        "from words w join filewords f on w.wordid = f.wordid "
        "where word like '";
    sql += q;
    sql += "') group by fileid order by sp desc limit 100) "
        "join files on fileid = files.rowid;";
    char* error;
    int r = sqlite3_exec(db, sql.c_str(), sqliteindexreadercallback,
        &results, &error);
    if (r != SQLITE_OK && error) {
        printf("%s\n", error);
        sqlite3_free(error);
    }
*/
    string sql = createQuery(terms.size());
    manager->ref();
    sqlite3_stmt* stmt;
    int r = sqlite3_prepare(db, sql.c_str(), 0, &stmt, 0);
    if (r != SQLITE_OK) {
        printf("could not prepare query '%s': %s\n", sql.c_str(),
            sqlite3_errmsg(db));
        manager->deref();
        return results;
    }
    set<string>::const_iterator i;
    int j = 1;
    for (i=terms.begin(); i!=terms.end(); ++i) {
        sqlite3_bind_text(stmt, j++, i->c_str(), i->length(),
            SQLITE_STATIC);
    }
    r = sqlite3_step(stmt);
    while (r == SQLITE_ROW) {
        results.push_back((const char*)sqlite3_column_text(stmt, 0));
        r = sqlite3_step(stmt);
    }
    if (r != SQLITE_DONE) {
        printf("error reading query results: %s\n", sqlite3_errmsg(db));
    }
    sqlite3_finalize(stmt);
    manager->deref();
    return results;
}
<commit_msg>Fix query code to be able to use * and ?<commit_after>#include "sqliteindexreader.h"
#include "sqliteindexmanager.h"
#include <sqlite3.h>
#include <set>
#include <sstream>
using namespace std;

SqliteIndexReader::SqliteIndexReader(SqliteIndexManager* m) :manager(m) {

    int r = sqlite3_open(manager->getDBFile(), &db);
    // any value other than SQLITE_OK is an error
    if (r != SQLITE_OK) {
        printf("could not open db\n");
        db = 0;
        return;
    }
    // speed up by being unsafe (we're only reading anyway)
    r = sqlite3_exec(db, "PRAGMA synchronous = OFF", 0, 0, 0);
    if (r != SQLITE_OK) {
        printf("could not speed up database\n");
    }
}
SqliteIndexReader::~SqliteIndexReader() {
    if (db) {
        int r = sqlite3_close(db);
        if (r != SQLITE_OK) {
            printf("could not create table\n");
        }
    }
}
set<string>
split(const std::string& q) {
    set<string> terms;
    uint pos = q.find(' ');
    uint offset = 0;
    while (pos != string::npos) {
        if (pos-offset > 0) {
            terms.insert(q.substr(offset, pos-offset));
        }
        offset = pos+1;
        pos = q.find(' ', offset);
    }
    if (offset < q.length()) {
        terms.insert(q.substr(offset));
    }
    return terms;
}
string
createQuery(int n) {
    // TODO: makeing a query with wildcards slows things down, so we must
    // think about reordering them
    // although we'll never be able to manage queries like 'a% b% c%'
    ostringstream q;
    q << "select path, ";
    // the points for a file is the sum of the fraction of the total occurances
    // of that word in this file
    for (int i=0; i<n; ++i) {
        char a = i+'a';
        if (i > 0) q<<"+";
        q << "f"<<a<<".count*1.0/w"<<a<<".count";
    }
    q << " p from ";
    for (int i=0; i<n; ++i) {
        char a = i+'a';
        q <<"words w"<<a<<",";
    }
    for (int i=0; i<n; ++i) {
        char a = i+'a';
        q <<"filewords f"<<a<<",";
    }
    q <<"files where ";
    for (int i=0; i<n; ++i) {
        char a = i+'a';
        q <<"w"<<a<<".word like ? and w"<<a<<".wordid = f"<<a<<".wordid and ";
    }
    for (int i=1; i<n; ++i) {
        char a = i+'a'-1;
        char b = i+'a';
        q <<"f"<<a<<".fileid = f"<<b<<".fileid and ";
    }
    q <<"fa.fileid = files.rowid order by p limit 100";
    return q.str();
}
vector<string>
SqliteIndexReader::query(const std::string& query) {
    string q = query;
    // replace * by %
    size_t p = q.find('*');
    while (p != string::npos) {
        q.replace(p, 1, "%");
        p = q.find('*');
    }
    // replace ? by _
    p = q.find('?');
    while (p != string::npos) {
        q.replace(p, 1, "_");
        p = q.find('?');
    }
    // split up in terms
    set<string> terms = split(q);
    std::vector<std::string> results;
    if (terms.size() == 0) return results;

    string sql = createQuery(terms.size());
    manager->ref();
    sqlite3_stmt* stmt;
    int r = sqlite3_prepare(db, sql.c_str(), 0, &stmt, 0);
    if (r != SQLITE_OK) {
        printf("could not prepare query '%s': %s\n", sql.c_str(),
            sqlite3_errmsg(db));
        manager->deref();
        return results;
    }
    set<string>::const_iterator i;
    int j = 1;
    for (i=terms.begin(); i!=terms.end(); ++i) {
        sqlite3_bind_text(stmt, j++, i->c_str(), i->length(),
            SQLITE_STATIC);
    }
    r = sqlite3_step(stmt);
    while (r == SQLITE_ROW) {
        results.push_back((const char*)sqlite3_column_text(stmt, 0));
        r = sqlite3_step(stmt);
    }
    if (r != SQLITE_DONE) {
        printf("error reading query results: %s\n", sqlite3_errmsg(db));
    }
    sqlite3_finalize(stmt);
    manager->deref();
    return results;
}
<|endoftext|>


<commit_before>#define DEFINE_DEFAULT_ITERATOR_CTOR
#include "helpers.hpp"
#undef DEFINE_DEFAULT_ITERATOR_CTOR

#include <combinations.hpp>

#include <set>
#include <vector>
#include <string>
#include <iterator>

#include "catch.hpp"

using iter::combinations;
using itertest::BasicIterable;
using itertest::SolidInt;
using CharCombSet = std::vector<std::vector<char>>;

TEST_CASE("combinations: Simple combination of 4", "[combinations]") {
    std::string s{"ABCD"};
    CharCombSet sc;
    for (auto v : combinations(s, 2)) {
        sc.emplace_back(std::begin(v), std::end(v));
    }

    CharCombSet ans =
        {{'A','B'}, {'A','C'}, {'A','D'}, {'B','C'}, {'B','D'}, {'C','D'}};
    REQUIRE( ans == sc );
}

TEST_CASE("combinations: iterators can be compared", "[combinations]") {
    std::string s{"ABCD"};
    auto c = combinations(s, 2);
    auto it = std::begin(c);
    REQUIRE( it == std::begin(c) );
    REQUIRE_FALSE( it != std::begin(c) );
    ++it;
    REQUIRE( it != std::begin(c) );
    REQUIRE_FALSE( it == std::begin(c) );
}

TEST_CASE("combinations: operator->", "[combinations]") {
    std::string s{"ABCD"};
    auto c = combinations(s, 2);
    auto it = std::begin(c);
    REQUIRE( it->size() == 2 );
}

TEST_CASE("combinations: size too large gives no results", "[combinations]") {
    std::string s{"ABCD"};
    auto c = combinations(s, 5);
    REQUIRE( std::begin(c) == std::end(c) );
}

TEST_CASE("combinations: size 0 gives nothing", "[combinations]") {
    std::string s{"ABCD"};
    auto c = combinations(s, 0);
    REQUIRE( std::begin(c) == std::end(c) );
}

TEST_CASE("combinations: iterable without operator*() const", "[combinations]")
{
    BasicIterable<char> bi{'x', 'y', 'z'};
    auto c = combinations(bi, 1);
    auto it = std::begin(c);
    ++it;
    (*it)[0];
}

TEST_CASE("combinations: binds to lvalues, moves rvalues", "[combinations]") {
    BasicIterable<char> bi{'x', 'y', 'z'};
    SECTION("binds to lvalues") {
        combinations(bi, 1);
        REQUIRE_FALSE( bi.was_moved_from() );
    }
    SECTION("moves rvalues") {
        combinations(std::move(bi), 1);
        REQUIRE( bi.was_moved_from() );
    }
}

TEST_CASE("combinations: doesn't move or copy elements of iterable",
        "[combinations]") {
    constexpr SolidInt arr[] = {{6}, {7}, {8}};
    for (auto&& i : combinations(arr, 1)) {
        (void)i;
    }
}

TEST_CASE("combinations: iterator meets requirements", "[combinations]") {
    std::string s{"abc"};
    auto c = combinations(s, 1);
    REQUIRE( itertest::IsIterator<decltype(std::begin(c))>::value );
    auto&& row = *std::begin(c);
    REQUIRE( itertest::IsIterator<decltype(std::begin(row))>::value );
}
<commit_msg>tests comb impl has move ctor only<commit_after>#define DEFINE_DEFAULT_ITERATOR_CTOR
#include "helpers.hpp"
#undef DEFINE_DEFAULT_ITERATOR_CTOR

#include <combinations.hpp>

#include <set>
#include <vector>
#include <string>
#include <iterator>

#include "catch.hpp"

using iter::combinations;
using itertest::BasicIterable;
using itertest::SolidInt;
using CharCombSet = std::vector<std::vector<char>>;

TEST_CASE("combinations: Simple combination of 4", "[combinations]") {
  std::string s{"ABCD"};
  CharCombSet sc;
  for (auto v : combinations(s, 2)) {
    sc.emplace_back(std::begin(v), std::end(v));
  }

  CharCombSet ans = {
      {'A', 'B'}, {'A', 'C'}, {'A', 'D'}, {'B', 'C'}, {'B', 'D'}, {'C', 'D'}};
  REQUIRE(ans == sc);
}

TEST_CASE("combinations: iterators can be compared", "[combinations]") {
  std::string s{"ABCD"};
  auto c = combinations(s, 2);
  auto it = std::begin(c);
  REQUIRE(it == std::begin(c));
  REQUIRE_FALSE(it != std::begin(c));
  ++it;
  REQUIRE(it != std::begin(c));
  REQUIRE_FALSE(it == std::begin(c));
}

TEST_CASE("combinations: operator->", "[combinations]") {
  std::string s{"ABCD"};
  auto c = combinations(s, 2);
  auto it = std::begin(c);
  REQUIRE(it->size() == 2);
}

TEST_CASE("combinations: size too large gives no results", "[combinations]") {
  std::string s{"ABCD"};
  auto c = combinations(s, 5);
  REQUIRE(std::begin(c) == std::end(c));
}

TEST_CASE("combinations: size 0 gives nothing", "[combinations]") {
  std::string s{"ABCD"};
  auto c = combinations(s, 0);
  REQUIRE(std::begin(c) == std::end(c));
}

TEST_CASE(
    "combinations: iterable without operator*() const", "[combinations]") {
  BasicIterable<char> bi{'x', 'y', 'z'};
  auto c = combinations(bi, 1);
  auto it = std::begin(c);
  ++it;
  (*it)[0];
}

TEST_CASE("combinations: binds to lvalues, moves rvalues", "[combinations]") {
  BasicIterable<char> bi{'x', 'y', 'z'};
  SECTION("binds to lvalues") {
    combinations(bi, 1);
    REQUIRE_FALSE(bi.was_moved_from());
  }
  SECTION("moves rvalues") {
    combinations(std::move(bi), 1);
    REQUIRE(bi.was_moved_from());
  }
}

TEST_CASE("combinations: doesn't move or copy elements of iterable",
    "[combinations]") {
  constexpr SolidInt arr[] = {{6}, {7}, {8}};
  for (auto&& i : combinations(arr, 1)) {
    (void)i;
  }
}

TEST_CASE("combinations: iterator meets requirements", "[combinations]") {
  std::string s{"abc"};
  auto c = combinations(s, 1);
  REQUIRE(itertest::IsIterator<decltype(std::begin(c))>::value);
  auto&& row = *std::begin(c);
  REQUIRE(itertest::IsIterator<decltype(std::begin(row))>::value);
}

template <typename T>
using ImpT = decltype(combinations(std::declval<T>(), 1));
TEST_CASE("combinations: has correct ctor and assign ops", "[combinations]") {
  REQUIRE(itertest::IsMoveConstructibleOnly<ImpT<std::string&>>::value);
  REQUIRE(itertest::IsMoveConstructibleOnly<ImpT<std::string>>::value);
}
<|endoftext|>


<commit_before>/*

Copyright (c) 2013, Arvid Norberg
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 the author 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.

*/

#include "test.hpp"
#include "setup_transfer.hpp"

#include "libtorrent/file_storage.hpp"

using namespace libtorrent;

void setup_test_storage(file_storage& st)
{
	st.add_file("test/a", 10000);
	st.add_file("test/b", 20000);
	st.add_file("test/c/a", 30000);
	st.add_file("test/c/b", 40000);

	st.set_piece_length(0x4000);
	st.set_num_pieces((st.total_size() + st.piece_length() - 1) / 0x4000);

	TEST_EQUAL(st.file_name(0), "a");
	TEST_EQUAL(st.file_name(1), "b");
	TEST_EQUAL(st.file_name(2), "a");
	TEST_EQUAL(st.file_name(3), "b");
	TEST_EQUAL(st.name(), "test");

	TEST_EQUAL(st.file_path(0), "test/a");
	TEST_EQUAL(st.file_path(1), "test/b");
	TEST_EQUAL(st.file_path(2), "test/c/a");
	TEST_EQUAL(st.file_path(3), "test/c/b");

	TEST_EQUAL(st.file_size(0), 10000);
	TEST_EQUAL(st.file_size(1), 20000);
	TEST_EQUAL(st.file_size(2), 30000);
	TEST_EQUAL(st.file_size(3), 40000);

	TEST_EQUAL(st.file_offset(0), 0);
	TEST_EQUAL(st.file_offset(1), 10000);
	TEST_EQUAL(st.file_offset(2), 30000);
	TEST_EQUAL(st.file_offset(3), 60000);

	TEST_EQUAL(st.total_size(), 100000);
	TEST_EQUAL(st.piece_length(), 0x4000);
	printf("%d\n", st.num_pieces());
	TEST_EQUAL(st.num_pieces(), (100000 + 0x3fff) / 0x4000);
}

int test_main()
{
	{
		file_storage st;
		setup_test_storage(st);

		st.rename_file(0, "test/c/d");
		TEST_EQUAL(st.file_path(0, "./"), "./test/c/d");

		st.rename_file(0, "/tmp/a");
		TEST_EQUAL(st.file_path(0, "./"), "/tmp/a");
	}

	{
		file_storage st;
		st.add_file("a", 10000);

		st.rename_file(0, "test/c/d");
		TEST_EQUAL(st.file_path(0, "./"), "./test/c/d");

		st.rename_file(0, "/tmp/a");
		TEST_EQUAL(st.file_path(0, "./"), "/tmp/a");
	}

	{
		file_storage fs;
		fs.set_piece_length(512);
		fs.add_file("temp_storage/test1.tmp", 17);
		fs.add_file("temp_storage/test2.tmp", 612);
		fs.add_file("temp_storage/test3.tmp", 0);
		fs.add_file("temp_storage/test4.tmp", 0);
		fs.add_file("temp_storage/test5.tmp", 3253);
		// size: 3882
		fs.add_file("temp_storage/test6.tmp", 841);
		// size: 4723

		peer_request rq = fs.map_file(0, 0, 10);
		TEST_EQUAL(rq.piece, 0);
		TEST_EQUAL(rq.start, 0);
		TEST_EQUAL(rq.length, 10);
		rq = fs.map_file(5, 0, 10);
		TEST_EQUAL(rq.piece, 7);
		TEST_EQUAL(rq.start, 298);
		TEST_EQUAL(rq.length, 10);
		rq = fs.map_file(5, 0, 1000);
		TEST_EQUAL(rq.piece, 7);
		TEST_EQUAL(rq.start, 298);
		TEST_EQUAL(rq.length, 841);
	}

	return 0;
}

<commit_msg>fix test_file_storage for windows<commit_after>/*

Copyright (c) 2013, Arvid Norberg
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 the author 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.

*/

#include "test.hpp"
#include "setup_transfer.hpp"

#include "libtorrent/file_storage.hpp"

using namespace libtorrent;

void setup_test_storage(file_storage& st)
{
	st.add_file("test/a", 10000);
	st.add_file("test/b", 20000);
	st.add_file("test/c/a", 30000);
	st.add_file("test/c/b", 40000);

	st.set_piece_length(0x4000);
	st.set_num_pieces((st.total_size() + st.piece_length() - 1) / 0x4000);

	TEST_EQUAL(st.file_name(0), "a");
	TEST_EQUAL(st.file_name(1), "b");
	TEST_EQUAL(st.file_name(2), "a");
	TEST_EQUAL(st.file_name(3), "b");
	TEST_EQUAL(st.name(), "test");

	TEST_EQUAL(st.file_path(0), "test/a");
	TEST_EQUAL(st.file_path(1), "test/b");
	TEST_EQUAL(st.file_path(2), "test/c/a");
	TEST_EQUAL(st.file_path(3), "test/c/b");

	TEST_EQUAL(st.file_size(0), 10000);
	TEST_EQUAL(st.file_size(1), 20000);
	TEST_EQUAL(st.file_size(2), 30000);
	TEST_EQUAL(st.file_size(3), 40000);

	TEST_EQUAL(st.file_offset(0), 0);
	TEST_EQUAL(st.file_offset(1), 10000);
	TEST_EQUAL(st.file_offset(2), 30000);
	TEST_EQUAL(st.file_offset(3), 60000);

	TEST_EQUAL(st.total_size(), 100000);
	TEST_EQUAL(st.piece_length(), 0x4000);
	printf("%d\n", st.num_pieces());
	TEST_EQUAL(st.num_pieces(), (100000 + 0x3fff) / 0x4000);
}

int test_main()
{
	{
		file_storage st;
		setup_test_storage(st);

		st.rename_file(0, "test/c/d");
		TEST_EQUAL(st.file_path(0, "./"), "./test/c/d");

#ifdef TORRENT_WINDOWS
		st.rename_file(0, "c:\\tmp\\a");
		TEST_EQUAL(st.file_path(0, "."), "c:\\tmp\\a");
#else
		st.rename_file(0, "/tmp/a");
		TEST_EQUAL(st.file_path(0, "."), "/tmp/a");
#endif
	}

	{
		file_storage st;
		st.add_file("a", 10000);

		st.rename_file(0, "test/c/d");
		TEST_EQUAL(st.file_path(0, "./"), "./test/c/d");

#ifdef TORRENT_WINDOWS
		st.rename_file(0, "c:\\tmp\\a");
		TEST_EQUAL(st.file_path(0, "."), "c:\\tmp\\a");
#else
		st.rename_file(0, "/tmp/a");
		TEST_EQUAL(st.file_path(0, "."), "/tmp/a");
#endif
	}

	{
		file_storage fs;
		fs.set_piece_length(512);
		fs.add_file(combine_path("temp_storage", "test1.tmp"), 17);
		fs.add_file(combine_path("temp_storage", "test2.tmp"), 612);
		fs.add_file(combine_path("temp_storage", "test3.tmp"), 0);
		fs.add_file(combine_path("temp_storage", "test4.tmp"), 0);
		fs.add_file(combine_path("temp_storage", "test5.tmp"), 3253);
		// size: 3882
		fs.add_file(combine_path("temp_storage", "test6.tmp"), 841);
		// size: 4723

		peer_request rq = fs.map_file(0, 0, 10);
		TEST_EQUAL(rq.piece, 0);
		TEST_EQUAL(rq.start, 0);
		TEST_EQUAL(rq.length, 10);
		rq = fs.map_file(5, 0, 10);
		TEST_EQUAL(rq.piece, 7);
		TEST_EQUAL(rq.start, 298);
		TEST_EQUAL(rq.length, 10);
		rq = fs.map_file(5, 0, 1000);
		TEST_EQUAL(rq.piece, 7);
		TEST_EQUAL(rq.start, 298);
		TEST_EQUAL(rq.length, 841);
	}

	return 0;
}

<|endoftext|>


<commit_before>#include "SSP_Editor.h"

SSP_Editor::SSP_Editor(QWidget *parent)
	: QMainWindow(parent)
{
	m_ui.setupUi(this);

	/*making a fileSystemModel to enable a file viewer in the treeView widget*/
	this->m_model = new QFileSystemModel(this);
	this->m_model->setRootPath("C:/");
	this->m_model->setFilter(QDir::NoDotAndDotDot | QDir::Files);

	/*a list of filters for the treeView*/
	QStringList filters;
	filters << "*.bbf";

	/*setting the filters and disabling the user from seeing any other files*/
	this->m_model->setNameFilters(filters);
	this->m_model->setNameFilterDisables(false);

	/*setting the fileSystemModel to the treeView and connecting the signal slot*/
	QTreeWidgetItem *model = new QTreeWidgetItem(m_ui.treeWidget);
	model->setText(0, "Models");
	m_ui.treeWidget->addTopLevelItem(model);
	QTreeWidgetItem *anim = new QTreeWidgetItem(m_ui.treeWidget);
	anim->setText(0, "Animations");
	m_ui.treeWidget->addTopLevelItem(anim);
	connect(m_ui.treeWidget, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(on_treeView_doubleClicked()));

	/*connecting the rest of the buttons to the functions*/
	connect(m_ui.actionNew_scene, SIGNAL(triggered()), this, SLOT(on_NewScene_clicked()));
	connect(m_ui.actionLoad_scene, SIGNAL(triggered()), this, SLOT(on_LoadScene_clicked()));
	connect(m_ui.actionSave_scene, SIGNAL(triggered()), this, SLOT(on_SaveScene_clicked()));
	connect(m_ui.actionBuild_BPF, SIGNAL(triggered()), this, SLOT(on_BuildBPF_clicked()));

	this->m_fileImporter = new FileImporter(m_ui.treeWidget);
	this->m_D3DRenderWidget = new D3DRenderWidget(m_ui.RenderWidget, this->m_fileImporter);
	this->m_fileImporter->ImportFromServer();
	this->m_fileImporter->LoadImportedFiles();
	//COMMENT ME BACK TO RENDER TO 2nd WIDGET
	//this->m_D3DRenderWidgetPreview = new D3DRenderWidget(m_ui.RenderWidget_2);
}

SSP_Editor::~SSP_Editor()
{
	delete this->m_model;
	delete this->m_fileImporter;
}

void SSP_Editor::on_NewScene_clicked()
{
}

void SSP_Editor::on_LoadScene_clicked()
{
}

void SSP_Editor::on_SaveScene_clicked()
{
}

void SSP_Editor::on_BuildBPF_clicked()
{
}

void SSP_Editor::on_treeView_doubleClicked()
{
	QModelIndex index = m_ui.treeWidget->currentIndex();

	//use index.r to get the right mesh
	/*checking to see if the selected object is valid*/
	if (!index.isValid()) return;

	std::vector<Resources::Model*>* test = m_fileImporter->get_M_models();

	DirectX::XMVECTOR pos = {
		static_cast <float> (rand()) / (static_cast <float> (RAND_MAX / 10)),
		static_cast <float> (rand()) / (static_cast <float> (RAND_MAX / 10)),
		static_cast <float> (rand()) / (static_cast <float> (RAND_MAX / 10))
	};

	this->m_D3DRenderWidget->getCommunicator()->AddModel(test->at(index.row())->GetId(),0,pos,0.0f);

	//QFileInfo fileInfo = this->m_model->fileInfo(index);
	//QString filePath = fileInfo.filePath();

	/*send the filepath to the importer*/

}
<commit_msg>added rand<commit_after>#include "SSP_Editor.h"

SSP_Editor::SSP_Editor(QWidget *parent)
	: QMainWindow(parent)
{
	m_ui.setupUi(this);

	/*making a fileSystemModel to enable a file viewer in the treeView widget*/
	this->m_model = new QFileSystemModel(this);
	this->m_model->setRootPath("C:/");
	this->m_model->setFilter(QDir::NoDotAndDotDot | QDir::Files);

	/*a list of filters for the treeView*/
	QStringList filters;
	filters << "*.bbf";

	/*setting the filters and disabling the user from seeing any other files*/
	this->m_model->setNameFilters(filters);
	this->m_model->setNameFilterDisables(false);

	/*setting the fileSystemModel to the treeView and connecting the signal slot*/
	QTreeWidgetItem *model = new QTreeWidgetItem(m_ui.treeWidget);
	model->setText(0, "Models");
	m_ui.treeWidget->addTopLevelItem(model);
	QTreeWidgetItem *anim = new QTreeWidgetItem(m_ui.treeWidget);
	anim->setText(0, "Animations");
	m_ui.treeWidget->addTopLevelItem(anim);
	connect(m_ui.treeWidget, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(on_treeView_doubleClicked()));

	/*connecting the rest of the buttons to the functions*/
	connect(m_ui.actionNew_scene, SIGNAL(triggered()), this, SLOT(on_NewScene_clicked()));
	connect(m_ui.actionLoad_scene, SIGNAL(triggered()), this, SLOT(on_LoadScene_clicked()));
	connect(m_ui.actionSave_scene, SIGNAL(triggered()), this, SLOT(on_SaveScene_clicked()));
	connect(m_ui.actionBuild_BPF, SIGNAL(triggered()), this, SLOT(on_BuildBPF_clicked()));

	this->m_fileImporter = new FileImporter(m_ui.treeWidget);
	this->m_D3DRenderWidget = new D3DRenderWidget(m_ui.RenderWidget, this->m_fileImporter);
	this->m_fileImporter->ImportFromServer();
	this->m_fileImporter->LoadImportedFiles();
	//COMMENT ME BACK TO RENDER TO 2nd WIDGET
	//this->m_D3DRenderWidgetPreview = new D3DRenderWidget(m_ui.RenderWidget_2);
}

SSP_Editor::~SSP_Editor()
{
	delete this->m_model;
	delete this->m_fileImporter;
}

void SSP_Editor::on_NewScene_clicked()
{
}

void SSP_Editor::on_LoadScene_clicked()
{
}

void SSP_Editor::on_SaveScene_clicked()
{
}

void SSP_Editor::on_BuildBPF_clicked()
{
}

void SSP_Editor::on_treeView_doubleClicked()
{
	QModelIndex index = m_ui.treeWidget->currentIndex();

	//use index.r to get the right mesh
	/*checking to see if the selected object is valid*/
	if (!index.isValid()) return;

	std::vector<Resources::Model*>* test = m_fileImporter->get_M_models();

	DirectX::XMVECTOR pos = {
		-10 + static_cast <float> (rand()) / (static_cast <float> (RAND_MAX / (10 - -10))),
		-10 + static_cast <float> (rand()) / (static_cast <float> (RAND_MAX / (10 - -10))),
		-10 + static_cast <float> (rand()) / (static_cast <float> (RAND_MAX / (10 - -10)))
	};

	this->m_D3DRenderWidget->getCommunicator()->AddModel(test->at(index.row())->GetId(),0,pos,0.0f);

	//QFileInfo fileInfo = this->m_model->fileInfo(index);
	//QString filePath = fileInfo.filePath();

	/*send the filepath to the importer*/

}
<|endoftext|>


<commit_before>//
//  SelfieExperience.cpp
//
//  Created by Soso Limited on 8/5/15.
//
//

#include "SelfieExperience.h"
#include "cinder/MotionManager.h"
#include "cinder/app/App.h"
#include "cinder/Log.h"

using namespace soso;
using namespace cinder;
using namespace std;

SelfieExperience::SelfieExperience( const fs::path &imagePath )
{
	aboutPage.setup( imagePath );

	CI_LOG_I( "Creating Grid Texture" );
	gridTexture = make_shared<GridTexture>( ivec2( 320, 240 ), 12 );

	CI_LOG_I( "Setting up landscape geometry." );
	landscape.setup();
	landscape.setTextureUnits( 0, 1 );
	landscape.setGridSize( gridTexture->getGridDimensions() );

	setupCamera();

	cameraWeight = 0.0f;
	cameraOffset = vec3( 0 );
  auto target = vec3( 5, 0, 0 );
  camera.lookAt( vec3( 0 ), target, vec3( 0, 1, 0 ) );
  camera.setPerspective( 80, app::getWindowAspectRatio(), 0.1f, 50.0f );
	startOrientation = camera.getOrientation();
	cameraEyePoint = vec3( 3.8f, 0.0f, 0.0f );

	MotionManager::enable();
	orientationUpdateConnection = app::App::get()->getSignalUpdate().connect( [this] {
		auto target = quat( vec3(MotionManager::getRotation() * vec4( 0, 0, -1, 0 )), vec3( 1, 0, 0 ) );
		orientationOffset = normalize( slerp( orientationOffset, target, 0.55f ) );
	} );

	auto window = app::getWindow();
	touchesBeganConnection = window->getSignalTouchesBegan().connect([this] (const app::TouchEvent &event) { touchesBegan( event ); });
	touchesMovedConnection = window->getSignalTouchesMoved().connect([this] (const app::TouchEvent &event) { touchesMoved( event ); });
	touchesEndedConnection = window->getSignalTouchesEnded().connect([this] (const app::TouchEvent &event) { touchesEnded( event ); });
}

SelfieExperience::~SelfieExperience()
{
	if (capture) {
    capture->stop();
	}
}

void SelfieExperience::pause()
{
	if (capture) {
		capture->stop();
		capture.reset();
	}

	MotionManager::disable();
}

void SelfieExperience::resume()
{
	MotionManager::enable();
	setupCamera();
}

void SelfieExperience::setupCamera()
{
	if( ! capture )
	{
		CI_LOG_I("Starting Capture");
		try
		{
			CI_LOG_I( "Initializing hardware camera." );
			auto front_facing_camera = ([] {
				auto &devices = Capture::getDevices();
				auto first_device = devices.front();
				for( auto device : devices ) {
					if( device->isFrontFacing() ) {
						return device;
					}
				}
				return first_device;
			}());

			capture = Capture::create( 1280, 960, front_facing_camera );
			capture->start();
		}
		catch( ci::Exception &exc )
		{
			CI_LOG_E( "Error using device camera: " << exc.what() );
		}
	}
	else
	{
		capture->start();
	}
}

void SelfieExperience::update()
{
	aboutPage.update();
	updateCamera();

	if( capture && capture->checkNewFrame() ) {
    gridTexture->addCameraImage( *capture );
  }
}

void SelfieExperience::touchesBegan( const ci::app::TouchEvent &event )
{
	CI_LOG_I("Touches Began");
  for( auto &t : event.getTouches() ) {
    touches.emplace_back( t.getId(), t.getPos(), t.getPos() );
  }
}

void SelfieExperience::touchesMoved( const ci::app::TouchEvent &event )
{
	CI_LOG_I("Touches Moved");
  for( auto &t : event.getTouches() ) {
    for( auto &s : touches ) {
      if( s.id == t.getId() ) {
				s.previous = s.position;
        s.position = t.getPos();
      }
    }
  }
}

void SelfieExperience::touchesEnded( const ci::app::TouchEvent &event )
{
	CI_LOG_I("Touches Ended");
  touches.erase( std::remove_if( touches.begin(), touches.end(), [&event] (const TouchInfo &s) {
    for( auto &t : event.getTouches() ) {
      if (t.getId() == s.id) {
        return true;
      }
    }
    return false;
  }), touches.end() );
}

void SelfieExperience::updateCamera()
{
	if( touches.size() == 1 )
	{
		const auto forward = ([] {
			auto gravity = MotionManager::getGravityDirection();
			if( abs( gravity.x ) > abs( gravity.y ) ) {
				auto x = copysign( 1.0f, gravity.x );
				return vec3( x, 0, 0 );
			}
			else {
				auto y = copysign( 1.0f, gravity.y );
				return vec3( 0, - y, 0 );
			}
		}());

		auto &touch = touches.front();
		auto delta = vec3( touch.position - touch.previous, 0 );
		touch.previous = touch.position;

		auto amount = length( delta );
		auto dir = dot( normalize(delta), forward );

		if( isfinite( amount ) && isfinite( dir ) ) {
			cameraVelocity += amount * dir;
		}
	}

	auto ray = camera.getViewDirection();
	cameraVelocity *= cameraWeight.value();
	cameraOffset += ray * cameraVelocity * 0.0025f;
	cameraVelocity *= 0.86f;

	auto l = length(cameraOffset);
	auto maximum = 2.5f;
	if( l > maximum ) {
		cameraOffset *= (maximum / l);
	}
	camera.setEyePoint( cameraEyePoint() + cameraOffset );

	auto r = glm::slerp( startOrientation, (orientationOffset * MotionManager::getRotation()), cameraWeight.value() );
	cameraOrientation = glm::slerp( cameraOrientation, r, 0.5f );
	camera.setOrientation( cameraOrientation );
}

void SelfieExperience::drawEndCaps() const
{
	gl::ScopedGlslProg prog( gl::getStockShader( gl::ShaderDef().texture(gridTexture->getTexture()->getTarget()) ) );
	gl::ScopedTextureBind tex0( gridTexture->getTexture(), 0 );

	auto mat = translate( vec3( 0, -4.0f, 0 ) );
	auto dims = vec2(gridTexture->getCellDimensions()) / gridTexture->getGridSize();
	auto offset = vec2(gridTexture->getIndexOffset( gridTexture->getCellDimensions(), gridTexture->getCurrentIndex() )) / gridTexture->getGridSize();
	auto rect = Rectf( -1.0f, -1.0f, 1.0f, 1.0f ).scaled( vec2( 1.333f, 1.0f ) ).scaled( 0.2f );
	auto half_pi = (float) M_PI / 2.0f;
	auto xf1 = translate( vec3( - 20.0f, 0.0f, 0.0f ) ) * rotate( - half_pi, vec3( 1, 0, 0 ) ) * rotate( half_pi, vec3( 0, 1, 0 ) );
	auto xf2 = translate( vec3( 4.0f, 0.0f, 0.0f ) ) * rotate( half_pi, vec3( 1, 0, 0 ) ) * rotate( - half_pi, vec3( 0, 1, 0 ) );

	auto draw_rect = [rect, dims, offset] (const mat4 &xf) {
		gl::ScopedModelMatrix m;
		gl::multModelMatrix( xf );
		#if defined(CINDER_ANDROID)
			gl::drawSolidRect( rect, offset + vec2( 0, 1 ) * dims, offset + vec2( 1, 0 ) * dims );
		#else
			gl::drawSolidRect( rect, offset, offset + dims );
		#endif
	};

	draw_rect(xf1);
	draw_rect(xf2);
}

void SelfieExperience::draw()
{
	gl::enableDepthRead();
	gl::enableDepthWrite();
	gl::ScopedTextureBind tex0( gridTexture->getTexture(), 0 );
	gl::ScopedTextureBind tex1( gridTexture->getBlurredTexture(), 1 );
	gl::ScopedMatrices matrices;
	gl::setMatrices( camera );

	landscape.draw( gridTexture->getCurrentIndex() );
	drawEndCaps();

  gl::disableDepthRead();
	gl::setMatricesWindow( app::getWindowSize() );
	aboutPage.draw();
}

void SelfieExperience::showLandscape()
{
	// Stop averaging the orientation.
	orientationUpdateConnection.disconnect();
	// Enable looking around with the gyro
	float zoom = 4.2f;
	app::timeline().apply( &cameraEyePoint, vec3( 0 ), zoom ).easeFn( EaseOutQuart() );
	app::timeline().apply( &cameraWeight, 1.0f, 1.33f ).easeFn( EaseInOutCubic() ).delay( zoom );
	app::timeline().add( [this] { aboutPage.show(); }, app::timeline().getEndTime() );
}
<commit_msg>Remove extra condition.<commit_after>//
//  SelfieExperience.cpp
//
//  Created by Soso Limited on 8/5/15.
//
//

#include "SelfieExperience.h"
#include "cinder/MotionManager.h"
#include "cinder/app/App.h"
#include "cinder/Log.h"

using namespace soso;
using namespace cinder;
using namespace std;

SelfieExperience::SelfieExperience( const fs::path &imagePath )
{
	aboutPage.setup( imagePath );

	CI_LOG_I( "Creating Grid Texture" );
	gridTexture = make_shared<GridTexture>( ivec2( 320, 240 ), 12 );

	CI_LOG_I( "Setting up landscape geometry." );
	landscape.setup();
	landscape.setTextureUnits( 0, 1 );
	landscape.setGridSize( gridTexture->getGridDimensions() );

	setupCamera();

	cameraWeight = 0.0f;
	cameraOffset = vec3( 0 );
  auto target = vec3( 5, 0, 0 );
  camera.lookAt( vec3( 0 ), target, vec3( 0, 1, 0 ) );
  camera.setPerspective( 80, app::getWindowAspectRatio(), 0.1f, 50.0f );
	startOrientation = camera.getOrientation();
	cameraEyePoint = vec3( 3.8f, 0.0f, 0.0f );

	MotionManager::enable();
	orientationUpdateConnection = app::App::get()->getSignalUpdate().connect( [this] {
		auto target = quat( vec3(MotionManager::getRotation() * vec4( 0, 0, -1, 0 )), vec3( 1, 0, 0 ) );
		orientationOffset = normalize( slerp( orientationOffset, target, 0.55f ) );
	} );

	auto window = app::getWindow();
	touchesBeganConnection = window->getSignalTouchesBegan().connect([this] (const app::TouchEvent &event) { touchesBegan( event ); });
	touchesMovedConnection = window->getSignalTouchesMoved().connect([this] (const app::TouchEvent &event) { touchesMoved( event ); });
	touchesEndedConnection = window->getSignalTouchesEnded().connect([this] (const app::TouchEvent &event) { touchesEnded( event ); });
}

SelfieExperience::~SelfieExperience()
{
	if (capture) {
    capture->stop();
	}
}

void SelfieExperience::pause()
{
	if (capture) {
		capture->stop();
		capture.reset();
	}

	MotionManager::disable();
}

void SelfieExperience::resume()
{
	MotionManager::enable();
	setupCamera();
}

void SelfieExperience::setupCamera()
{
	if( ! capture )
	{
		CI_LOG_I("Starting Capture");
		try
		{
			CI_LOG_I( "Initializing hardware camera." );
			auto front_facing_camera = ([] {
				auto &devices = Capture::getDevices();
				auto first_device = devices.front();
				for( auto device : devices ) {
					if( device->isFrontFacing() ) {
						return device;
					}
				}
				return first_device;
			}());

			capture = Capture::create( 1280, 960, front_facing_camera );
			capture->start();
		}
		catch( ci::Exception &exc )
		{
			CI_LOG_E( "Error using device camera: " << exc.what() );
		}
	}
}

void SelfieExperience::update()
{
	aboutPage.update();
	updateCamera();

	if( capture && capture->checkNewFrame() ) {
    gridTexture->addCameraImage( *capture );
  }
}

void SelfieExperience::touchesBegan( const ci::app::TouchEvent &event )
{
	CI_LOG_I("Touches Began");
  for( auto &t : event.getTouches() ) {
    touches.emplace_back( t.getId(), t.getPos(), t.getPos() );
  }
}

void SelfieExperience::touchesMoved( const ci::app::TouchEvent &event )
{
	CI_LOG_I("Touches Moved");
  for( auto &t : event.getTouches() ) {
    for( auto &s : touches ) {
      if( s.id == t.getId() ) {
				s.previous = s.position;
        s.position = t.getPos();
      }
    }
  }
}

void SelfieExperience::touchesEnded( const ci::app::TouchEvent &event )
{
	CI_LOG_I("Touches Ended");
  touches.erase( std::remove_if( touches.begin(), touches.end(), [&event] (const TouchInfo &s) {
    for( auto &t : event.getTouches() ) {
      if (t.getId() == s.id) {
        return true;
      }
    }
    return false;
  }), touches.end() );
}

void SelfieExperience::updateCamera()
{
	if( touches.size() == 1 )
	{
		const auto forward = ([] {
			auto gravity = MotionManager::getGravityDirection();
			if( abs( gravity.x ) > abs( gravity.y ) ) {
				auto x = copysign( 1.0f, gravity.x );
				return vec3( x, 0, 0 );
			}
			else {
				auto y = copysign( 1.0f, gravity.y );
				return vec3( 0, - y, 0 );
			}
		}());

		auto &touch = touches.front();
		auto delta = vec3( touch.position - touch.previous, 0 );
		touch.previous = touch.position;

		auto amount = length( delta );
		auto dir = dot( normalize(delta), forward );

		if( isfinite( amount ) && isfinite( dir ) ) {
			cameraVelocity += amount * dir;
		}
	}

	auto ray = camera.getViewDirection();
	cameraVelocity *= cameraWeight.value();
	cameraOffset += ray * cameraVelocity * 0.0025f;
	cameraVelocity *= 0.86f;

	auto l = length(cameraOffset);
	auto maximum = 2.5f;
	if( l > maximum ) {
		cameraOffset *= (maximum / l);
	}
	camera.setEyePoint( cameraEyePoint() + cameraOffset );

	auto r = glm::slerp( startOrientation, (orientationOffset * MotionManager::getRotation()), cameraWeight.value() );
	cameraOrientation = glm::slerp( cameraOrientation, r, 0.5f );
	camera.setOrientation( cameraOrientation );
}

void SelfieExperience::drawEndCaps() const
{
	gl::ScopedGlslProg prog( gl::getStockShader( gl::ShaderDef().texture(gridTexture->getTexture()->getTarget()) ) );
	gl::ScopedTextureBind tex0( gridTexture->getTexture(), 0 );

	auto mat = translate( vec3( 0, -4.0f, 0 ) );
	auto dims = vec2(gridTexture->getCellDimensions()) / gridTexture->getGridSize();
	auto offset = vec2(gridTexture->getIndexOffset( gridTexture->getCellDimensions(), gridTexture->getCurrentIndex() )) / gridTexture->getGridSize();
	auto rect = Rectf( -1.0f, -1.0f, 1.0f, 1.0f ).scaled( vec2( 1.333f, 1.0f ) ).scaled( 0.2f );
	auto half_pi = (float) M_PI / 2.0f;
	auto xf1 = translate( vec3( - 20.0f, 0.0f, 0.0f ) ) * rotate( - half_pi, vec3( 1, 0, 0 ) ) * rotate( half_pi, vec3( 0, 1, 0 ) );
	auto xf2 = translate( vec3( 4.0f, 0.0f, 0.0f ) ) * rotate( half_pi, vec3( 1, 0, 0 ) ) * rotate( - half_pi, vec3( 0, 1, 0 ) );

	auto draw_rect = [rect, dims, offset] (const mat4 &xf) {
		gl::ScopedModelMatrix m;
		gl::multModelMatrix( xf );
		#if defined(CINDER_ANDROID)
			gl::drawSolidRect( rect, offset + vec2( 0, 1 ) * dims, offset + vec2( 1, 0 ) * dims );
		#else
			gl::drawSolidRect( rect, offset, offset + dims );
		#endif
	};

	draw_rect(xf1);
	draw_rect(xf2);
}

void SelfieExperience::draw()
{
	gl::enableDepthRead();
	gl::enableDepthWrite();
	gl::ScopedTextureBind tex0( gridTexture->getTexture(), 0 );
	gl::ScopedTextureBind tex1( gridTexture->getBlurredTexture(), 1 );
	gl::ScopedMatrices matrices;
	gl::setMatrices( camera );

	landscape.draw( gridTexture->getCurrentIndex() );
	drawEndCaps();

  gl::disableDepthRead();
	gl::setMatricesWindow( app::getWindowSize() );
	aboutPage.draw();
}

void SelfieExperience::showLandscape()
{
	// Stop averaging the orientation.
	orientationUpdateConnection.disconnect();
	// Enable looking around with the gyro
	float zoom = 4.2f;
	app::timeline().apply( &cameraEyePoint, vec3( 0 ), zoom ).easeFn( EaseOutQuart() );
	app::timeline().apply( &cameraWeight, 1.0f, 1.33f ).easeFn( EaseInOutCubic() ).delay( zoom );
	app::timeline().add( [this] { aboutPage.show(); }, app::timeline().getEndTime() );
}
<|endoftext|>


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

// condor includes
#include "condor_common.h"
#include "condor_qmgr.h"

// local includes
#include "Codec.h"
#include "AviaryUtils.h"

using namespace compat_classad;
using namespace aviary::codec;
using namespace aviary::util;

// TODO: defer until linking issues sorted
//Codec*
//DefaultCodecFactory::createCodec() {
//    if (!m_codec) {
//        m_codec = new BaseCodec;
//    }
//    return m_codec;
//}

BaseCodec::BaseCodec()
{
    //
}

BaseCodec::~BaseCodec()
{
    //
}

bool
BaseCodec::addAttributeToMap (ClassAd& ad, const char* name, AttributeMapType& _map)
{
    ExprTree *expr;

    // All these extra lookups are horrible. They have to
    // be there because the ClassAd may have multiple
    // copies of the same attribute name! This means that
    // the last attribute with a given name will set the
    // value, but the last attribute tends to be the
    // attribute with the oldest (wrong) value. How
    // annoying is that!
    if (!(expr = ad.Lookup(name))) {
        dprintf(D_FULLDEBUG, "Warning: failed to lookup attribute '%s' from ad\n", name);
        return false;
    }

    classad::Value value;
    ad.EvaluateExpr(expr,value);
	std::string key = name;
    switch (value.GetType()) {
        // seems this covers expressions also
        case classad::Value::ERROR_VALUE:
        case classad::Value::UNDEFINED_VALUE:
        case classad::Value::BOOLEAN_VALUE:
            _map[key] = new AviaryAttribute(AviaryAttribute::EXPR_TYPE,trimQuotes(ExprTreeToString(expr)).c_str());
            break;
        case classad::Value::INTEGER_VALUE:
            _map[key] = new AviaryAttribute(AviaryAttribute::INTEGER_TYPE,ExprTreeToString(expr));
            break;
        case classad::Value::REAL_VALUE:
            _map[key] = new AviaryAttribute(AviaryAttribute::FLOAT_TYPE,ExprTreeToString(expr));
            break;
        case classad::Value::STRING_VALUE:
        default:
            _map[key] = new AviaryAttribute(AviaryAttribute::STRING_TYPE,trimQuotes(ExprTreeToString(expr)).c_str());
    }

    return true;
}

bool
BaseCodec::classAdToMap(ClassAd& ad, AttributeMapType& _map)
{
    ExprTree *expr;
	const char *name;
	ad.ResetExpr();
	_map.clear();
	while (ad.NextExpr(name,expr)) {
		if (!addAttributeToMap(ad, name, _map)) {
                    return false;
		}
	}

// //debug
//        if (DebugFlags & D_FULLDEBUG) {
//            ad.dPrint(D_FULLDEBUG|D_NOHEADER);
//        }

    return true;
}

bool
BaseCodec::mapToClassAd(AttributeMapType& _map, ClassAd& ad, string& text)
{

    for (AttributeMapIterator entry = _map.begin(); _map.end() != entry; entry++) {
        const char* name = entry->first.c_str();

		if (isKeyword(name)) {
			text = "Reserved ClassAd keyword cannot be an attribute name: "+ entry->first;
			return false;
		}

        AviaryAttribute* value = entry->second;

        switch (value->getType()) {
            case AviaryAttribute::INTEGER_TYPE:
                ad.Assign(name, atoi(value->getValue()));
                break;
            case AviaryAttribute::FLOAT_TYPE:
                ad.Assign(name, atof(value->getValue()));
                break;
            case AviaryAttribute::STRING_TYPE:
                ad.Assign(name, value->getValue());
                break;
            case AviaryAttribute::EXPR_TYPE:
                ad.AssignExpr(name, value->getValue());
                break;
            default:
                dprintf(D_FULLDEBUG, "Warning: Unknown/unsupported type in map for attribute '%s'\n", name);
        }
    }

//     // debug
//     if (DebugFlags & D_FULLDEBUG) {
//           ad.dPrint(D_FULLDEBUG|D_NOHEADER);
//     }

    return true;
}
<commit_msg>Fix to properly encode int and real values in aviary contrib (including equivalent expressions like time())<commit_after>/***************************************************************
 *
 * Copyright (C) 2009-2011 Red Hat, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you
 * may not use this file except in compliance with the License.  You may
 * obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 ***************************************************************/

// condor includes
#include "condor_common.h"
#include "condor_qmgr.h"

// local includes
#include "Codec.h"
#include "AviaryUtils.h"

using namespace compat_classad;
using namespace aviary::codec;
using namespace aviary::util;

// TODO: defer until linking issues sorted
//Codec*
//DefaultCodecFactory::createCodec() {
//    if (!m_codec) {
//        m_codec = new BaseCodec;
//    }
//    return m_codec;
//}

BaseCodec::BaseCodec()
{
    //
}

BaseCodec::~BaseCodec()
{
    //
}

bool
BaseCodec::addAttributeToMap (ClassAd& ad, const char* name, AttributeMapType& _map)
{
    ExprTree *expr;

    // All these extra lookups are horrible. They have to
    // be there because the ClassAd may have multiple
    // copies of the same attribute name! This means that
    // the last attribute with a given name will set the
    // value, but the last attribute tends to be the
    // attribute with the oldest (wrong) value. How
    // annoying is that!
    if (!(expr = ad.Lookup(name))) {
        dprintf(D_FULLDEBUG, "Warning: failed to lookup attribute '%s' from ad\n", name);
        return false;
    }

    classad::Value value;
    ad.EvaluateExpr(expr,value);
	std::string key = name;
    switch (value.GetType()) {
        // seems this covers expressions also
        case classad::Value::ERROR_VALUE:
        case classad::Value::UNDEFINED_VALUE:
        case classad::Value::BOOLEAN_VALUE:
            _map[key] = new AviaryAttribute(AviaryAttribute::EXPR_TYPE,trimQuotes(ExprTreeToString(expr)).c_str());
            break;
        case classad::Value::INTEGER_VALUE:
        {
            int i;
            value.IsIntegerValue (i);
            string i_str;
            sprintf(i_str,"%d",i);
            _map[key] = new AviaryAttribute(AviaryAttribute::INTEGER_TYPE,i_str.c_str());
            break;
        }
        case classad::Value::REAL_VALUE:
        {
            double d;
            value.IsRealValue(d);
            string d_str;
            sprintf(d_str,"%f",d);
            _map[key] = new AviaryAttribute(AviaryAttribute::FLOAT_TYPE,d_str.c_str());
            break;
        }
        case classad::Value::STRING_VALUE:
        default:
            _map[key] = new AviaryAttribute(AviaryAttribute::STRING_TYPE,trimQuotes(ExprTreeToString(expr)).c_str());
    }

    return true;
}

bool
BaseCodec::classAdToMap(ClassAd& ad, AttributeMapType& _map)
{
    ExprTree *expr;
	const char *name;
	ad.ResetExpr();
	_map.clear();
	while (ad.NextExpr(name,expr)) {
		if (!addAttributeToMap(ad, name, _map)) {
                    return false;
		}
	}

// //debug
//        if (DebugFlags & D_FULLDEBUG) {
//            ad.dPrint(D_FULLDEBUG|D_NOHEADER);
//        }

    return true;
}

bool
BaseCodec::mapToClassAd(AttributeMapType& _map, ClassAd& ad, string& text)
{

    for (AttributeMapIterator entry = _map.begin(); _map.end() != entry; entry++) {
        const char* name = entry->first.c_str();

		if (isKeyword(name)) {
			text = "Reserved ClassAd keyword cannot be an attribute name: "+ entry->first;
			return false;
		}

        AviaryAttribute* value = entry->second;

        switch (value->getType()) {
            case AviaryAttribute::INTEGER_TYPE:
                ad.Assign(name, atoi(value->getValue()));
                break;
            case AviaryAttribute::FLOAT_TYPE:
                ad.Assign(name, atof(value->getValue()));
                break;
            case AviaryAttribute::STRING_TYPE:
                ad.Assign(name, value->getValue());
                break;
            case AviaryAttribute::EXPR_TYPE:
                ad.AssignExpr(name, value->getValue());
                break;
            default:
                dprintf(D_FULLDEBUG, "Warning: Unknown/unsupported type in map for attribute '%s'\n", name);
        }
    }

//     // debug
//     if (DebugFlags & D_FULLDEBUG) {
//           ad.dPrint(D_FULLDEBUG|D_NOHEADER);
//     }

    return true;
}
<|endoftext|>


<commit_before>// RUN: %clang_tsan -O1 %s -o %t && TSAN_OPTIONS="$TSAN_OPTIONS halt_on_error=1" not %t 2>&1 | FileCheck %s
#include <pthread.h>
#include <stdio.h>

int X;

void *Thread(void *x) {
  X = 42;
  return 0;
}

int main() {
  fprintf(stderr, "BEFORE\n");
  pthread_t t;
  pthread_create(&t, 0, Thread, 0);
  X = 43;
  pthread_join(t, 0);
  fprintf(stderr, "AFTER\n");
  return 0;
}

// CHECK: BEFORE
// CHECK: WARNING: ThreadSanitizer: data race
// CHECK-NOT: AFTER

<commit_msg>tsan: deflake test<commit_after>// RUN: %clang_tsan -O1 %s -o %t && TSAN_OPTIONS="$TSAN_OPTIONS halt_on_error=1" not %t 2>&1 | FileCheck %s
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>

int X;

void *Thread(void *x) {
  sleep(1);
  X = 42;
  return 0;
}

int main() {
  fprintf(stderr, "BEFORE\n");
  pthread_t t;
  pthread_create(&t, 0, Thread, 0);
  X = 43;
  pthread_join(t, 0);
  fprintf(stderr, "AFTER\n");
  return 0;
}

// CHECK: BEFORE
// CHECK: WARNING: ThreadSanitizer: data race
// CHECK-NOT: AFTER

<|endoftext|>


<commit_before><commit_msg>little modification<commit_after><|endoftext|>


<commit_before>#include "AssemblyVisitor.h"

#include <stdexcept>

#include "Program.h"
#include "FunctionBlock.h"

#include "Binary.h"
#include "Unary.h"
#include "Add.h"
#include "Subtract.h"
#include "Multiply.h"
#include "Divide.h"
#include "Modulus.h"
#include "Negate.h"

#include "Variable.h"
#include "Value.h"

void AssemblyVisitor::Visit(const Program & p)
{
    // Visit each FunctionBlock in Program
    Program::ListT funcs = p.GetFunctions();
    for (Program::ListT::const_iterator it = funcs.begin();
         it != funcs.end();
         ++it) {
        if (*it) {
            (*it)->Accept(*this);
        }
    }
}

void AssemblyVisitor::Visit(const FunctionBlock & f)
{
    // get the current SymbolTable and store it on a stack of symbol tables?
    _currTable = f.GetSymbolTable();
    // Print prolog
    _out << ".global " << f.GetName() << std::endl
         << ".type " << f.GetName() << ", @function" << std::endl
         << f.GetName() << ":" << std::endl
         << "\tpushl %ebp /* base pointer on stack */" << std::endl
         << "\tmovl  %esp, %ebp /* change base pointer */" << std::endl;

    // make space for locals
    StatementList const *decls = f.GetDeclarations();
    int localCount = decls->GetStatements().size();
    _out << "\taddl $-" << (localCount * 4) << ", %esp" << std::endl;

    // visit statements
    StatementList const *stmts = f.GetStatements();
    StatementList::ListT slist = stmts->GetStatements();
    for (StatementList::ListT::const_iterator it = slist.begin();
         it != slist.end();
         ++it) {
        (*it)->Accept(*this);
    }

    // Print epilog
    _out << "\tmovl %ebp, %esp" << std::endl
         << "\tpopl %ebp /* restore base pointer */" << std::endl
         << "\tret" << std::endl;
}

void AssemblyVisitor::Visit(const Add & a)
{
    VisitBinary(a, "addl");
}

void AssemblyVisitor::Visit(const Divide & d)
{
    // I'm too lazy to make VisitBinary more generic...
    // get the two children results
    const Expr *l = d.GetLeft();
    const Expr *r = d.GetRight();
    if (!l || !r) {
        throw std::runtime_error("Could not evaluate binary expression");
    }
    l->Accept(*this);
    r->Accept(*this);
    // grab results into registers
	_out << "\tpopl %ebx" << std::endl; // right
	_out << "\tpopl %eax" << std::endl; // left
    // need to divide %eax by %ebx
    _out << "\tcltd" << std::endl
         << "\tidiv %ebx" << std::endl;
    // push result
	_out << "push %eax" << std::endl;
}

void AssemblyVisitor::Visit(const Modulus & d)
{
    // same as divide but return remainder
    // get the two children results
    const Expr *l = d.GetLeft();
    const Expr *r = d.GetRight();
    if (!l || !r) {
        throw std::runtime_error("Could not evaluate binary expression");
    }
    l->Accept(*this);
    r->Accept(*this);
    // grab results into registers
	_out << "\tpopl %ebx" << std::endl; // right
	_out << "\tpopl %eax" << std::endl; // left
    // need to divide %eax by %ebx
    _out << "\tcltd" << std::endl
         << "\tidiv %ebx" << std::endl;
    // push result (remainder)
	_out << "push %edx" << std::endl;
}

void AssemblyVisitor::Visit(const Multiply & m)
{
    VisitBinary(m, "imull");
}

void AssemblyVisitor::Visit(const Negate & n)
{
    VisitUnary(n, "negl");
}

void AssemblyVisitor::Visit(const Subtract & s)
{
    VisitBinary(s, "subl");
}

void AssemblyVisitor::Visit(const Value & v)
{
    // push on stack?
    _out << "\tpushl $" << v.Get() << std::endl;
}

void AssemblyVisitor::Visit(const Variable & v)
{
    // Look up in current symbol table, push some offset of ebp on stack
    int off = _currTable->GetOffset(v.GetName());
    _out << "\tpushl " << off << "(%ebp)" << std::endl;
}

void AssemblyVisitor::Visit(const AssignStmt & a)
{
    // pop something and store it in some offset to ebp depending on var
}

void AssemblyVisitor::Visit(const WriteStmt & w)
{
    // may need to evaluate the RHS, then just output "write ???"
}

void AssemblyVisitor::Visit(const DeclStmt & d)
{
    // allocate space on stack for local, put in current symbol table?
    // this is already done, maybe we don't need a visitor here?
}

void AssemblyVisitor::Visit(const ReturnStmt & r)
{
    // return statement means writing something to eax
}

void AssemblyVisitor::Visit(const FuncCall & f)
{

}

void AssemblyVisitor::VisitBinary(const Binary &b, const std::string &op)
{
    // get the two children results
    const Expr *l = b.GetLeft();
    const Expr *r = b.GetRight();
    if (!l || !r) {
        // WTF, exception
        throw std::runtime_error("Could not evaluate binary expression");
    }
    l->Accept(*this);
    r->Accept(*this);
    // grab results into registers
	_out << "\tpopl %edx" << std::endl; // right
	_out << "\tpopl %eax" << std::endl; // left
    // do op (example addl %edx, %eax // will do %eax = %eax + %edx)
    _out << "\t" << op << " %edx, %eax" << std::endl;
    // push result
	_out << "push %eax" << std::endl;
}

void AssemblyVisitor::VisitUnary(const Unary &u, const std::string &op)
{
    // get the child result
    const Expr *c = u.GetChild();
    if (!c) {
        // WTF, exception
        throw std::runtime_error("Could not evaluate unary expression");
    }
    c->Accept(*this);
    // grab result into register
	_out << "\tpopl %eax" << std::endl;
    // do op (example negl %eax // will do %eax = - %eax)
    _out << "\t" << op << " %eax" << std::endl;
    // push result
	_out << "push %eax" << std::endl;
}
<commit_msg>Added the assignment assembly<commit_after>#include "AssemblyVisitor.h"

#include <stdexcept>

#include "Program.h"
#include "FunctionBlock.h"

#include "Binary.h"
#include "Unary.h"
#include "Add.h"
#include "Subtract.h"
#include "Multiply.h"
#include "Divide.h"
#include "Modulus.h"
#include "Negate.h"

#include "Variable.h"
#include "Value.h"

#include "AssignStmt.h"

void AssemblyVisitor::Visit(const Program & p)
{
    // Visit each FunctionBlock in Program
    Program::ListT funcs = p.GetFunctions();
    for (Program::ListT::const_iterator it = funcs.begin();
         it != funcs.end();
         ++it) {
        if (*it) {
            (*it)->Accept(*this);
        }
    }
}

void AssemblyVisitor::Visit(const FunctionBlock & f)
{
    // get the current SymbolTable and store it on a stack of symbol tables?
    _currTable = f.GetSymbolTable();
    // Print prolog
    _out << ".global " << f.GetName() << std::endl
         << ".type " << f.GetName() << ", @function" << std::endl
         << f.GetName() << ":" << std::endl
         << "\tpushl %ebp /* base pointer on stack */" << std::endl
         << "\tmovl  %esp, %ebp /* change base pointer */" << std::endl;

    // make space for locals
    StatementList const *decls = f.GetDeclarations();
    int localCount = decls->GetStatements().size();
    _out << "\taddl $-" << (localCount * 4) << ", %esp" << std::endl;

    // visit statements
    StatementList const *stmts = f.GetStatements();
    StatementList::ListT slist = stmts->GetStatements();
    for (StatementList::ListT::const_iterator it = slist.begin();
         it != slist.end();
         ++it) {
        (*it)->Accept(*this);
    }

    // Print epilog
    _out << "\tmovl %ebp, %esp" << std::endl
         << "\tpopl %ebp /* restore base pointer */" << std::endl
         << "\tret" << std::endl;
}

void AssemblyVisitor::Visit(const Add & a)
{
    VisitBinary(a, "addl");
}

void AssemblyVisitor::Visit(const Divide & d)
{
    // I'm too lazy to make VisitBinary more generic...
    // get the two children results
    const Expr *l = d.GetLeft();
    const Expr *r = d.GetRight();
    if (!l || !r) {
        throw std::runtime_error("Could not evaluate binary expression");
    }
    l->Accept(*this);
    r->Accept(*this);
    // grab results into registers
	_out << "\tpopl %ebx" << std::endl; // right
	_out << "\tpopl %eax" << std::endl; // left
    // need to divide %eax by %ebx
    _out << "\tcltd" << std::endl
         << "\tidiv %ebx" << std::endl;
    // push result
	_out << "push %eax" << std::endl;
}

void AssemblyVisitor::Visit(const Modulus & d)
{
    // same as divide but return remainder
    // get the two children results
    const Expr *l = d.GetLeft();
    const Expr *r = d.GetRight();
    if (!l || !r) {
        throw std::runtime_error("Could not evaluate binary expression");
    }
    l->Accept(*this);
    r->Accept(*this);
    // grab results into registers
	_out << "\tpopl %ebx" << std::endl; // right
	_out << "\tpopl %eax" << std::endl; // left
    // need to divide %eax by %ebx
    _out << "\tcltd" << std::endl
         << "\tidiv %ebx" << std::endl;
    // push result (remainder)
	_out << "push %edx" << std::endl;
}

void AssemblyVisitor::Visit(const Multiply & m)
{
    VisitBinary(m, "imull");
}

void AssemblyVisitor::Visit(const Negate & n)
{
    VisitUnary(n, "negl");
}

void AssemblyVisitor::Visit(const Subtract & s)
{
    VisitBinary(s, "subl");
}

void AssemblyVisitor::Visit(const Value & v)
{
    // push on stack?
    _out << "\tpushl $" << v.Get() << std::endl;
}

void AssemblyVisitor::Visit(const Variable & v)
{
    // Look up in current symbol table, push some offset of ebp on stack
    int off = _currTable->GetOffset(v.GetName());
    _out << "\tpushl " << off << "(%ebp)" << std::endl;
}

void AssemblyVisitor::Visit(const AssignStmt & a)
{
    // pop something and store it in some offset to ebp depending on var
    Expr const *value = a.GetValue();
    value->Accept(*this);
    // after visiting the RHS of the assignment, the answer is on the stack
    int off = _currTable->GetOffset(a.GetName());
    _out << "\tpopl " << off << "(%ebp)" << std::endl;
}

void AssemblyVisitor::Visit(const WriteStmt & w)
{
    // may need to evaluate the RHS, then just output "write ???"
}

void AssemblyVisitor::Visit(const DeclStmt & d)
{
    // allocate space on stack for local, put in current symbol table?
    // this is already done, maybe we don't need a visitor here?
}

void AssemblyVisitor::Visit(const ReturnStmt & r)
{
    // return statement means writing something to eax
}

void AssemblyVisitor::Visit(const FuncCall & f)
{

}

void AssemblyVisitor::VisitBinary(const Binary &b, const std::string &op)
{
    // get the two children results
    const Expr *l = b.GetLeft();
    const Expr *r = b.GetRight();
    if (!l || !r) {
        // WTF, exception
        throw std::runtime_error("Could not evaluate binary expression");
    }
    l->Accept(*this);
    r->Accept(*this);
    // grab results into registers
	_out << "\tpopl %edx" << std::endl; // right
	_out << "\tpopl %eax" << std::endl; // left
    // do op (example addl %edx, %eax // will do %eax = %eax + %edx)
    _out << "\t" << op << " %edx, %eax" << std::endl;
    // push result
	_out << "push %eax" << std::endl;
}

void AssemblyVisitor::VisitUnary(const Unary &u, const std::string &op)
{
    // get the child result
    const Expr *c = u.GetChild();
    if (!c) {
        // WTF, exception
        throw std::runtime_error("Could not evaluate unary expression");
    }
    c->Accept(*this);
    // grab result into register
	_out << "\tpopl %eax" << std::endl;
    // do op (example negl %eax // will do %eax = - %eax)
    _out << "\t" << op << " %eax" << std::endl;
    // push result
	_out << "push %eax" << std::endl;
}
<|endoftext|>