<commit_before>// Copyright 2010-2012 Google
// 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.
//
// This model implements a simple jobshop problem with
// earlyness-tardiness costs.
//
// A earlyness-tardinessjobshop is a standard scheduling problem where
// you must schedule a set of jobs on a set of machines.  Each job is
// a sequence of tasks (a task can only start when the preceding task
// finished), each of which occupies a single specific machine during
// a specific duration. Therefore, a job is a sequence of pairs
// (machine id, duration), along with a release data (minimum start
// date of the first task of the job, and due data (end time of the
// last job) with a tardiness linear penalty.

// The objective is to minimize the sum of early-tardy penalties for each job.
//
// This will be modelled by sets of intervals variables (see class
// IntervalVar in constraint_solver/constraint_solver.h), one per
// task, representing the [start_time, end_time] of the task.  Tasks
// in the same job will be linked by precedence constraints.  Tasks on
// the same machine will be covered by Sequence constraints.

#include <cstdio>
#include <cstdlib>

#include <vector>

#include "base/commandlineflags.h"
#include "base/commandlineflags.h"
#include "base/integral_types.h"
#include "base/logging.h"
#include "base/stringprintf.h"
#include "constraint_solver/constraint_solver.h"
#include "linear_solver/linear_solver.h"
#include "util/string_array.h"
#include "cpp/jobshop_earlytardy.h"

DEFINE_string(
    jet_file,
    "",
    "Required: input file description the scheduling problem to solve, "
    "in our jet format:\n"
    "  - the first line is \"<number of jobs> <number of machines>\"\n"
    "  - then one line per job, with a single space-separated "
    "list of \"<machine index> <duration>\", ended by due_date, early_cost,"
    "late_cost\n"
    "note: jobs with one task are not supported");
DEFINE_int32(machine_count, 10, "Machine count");
DEFINE_int32(job_count, 10, "Job count");
DEFINE_int32(max_release_date, 0, "Max release date");
DEFINE_int32(max_early_cost, 0, "Max earlyness weight");
DEFINE_int32(max_tardy_cost, 3, "Max tardiness weight");
DEFINE_int32(max_duration, 10, "Max duration of a task");
DEFINE_int32(scale_factor, 130, "Scale factor (in percent)");
DEFINE_int32(seed, 1, "Random seed");
DEFINE_int32(time_limit_in_ms, 0, "Time limit in ms, 0 means no limit.");
DEFINE_bool(time_placement, false, "Use MIP based time placement");
DECLARE_bool(log_prefix);

namespace operations_research {
class TimePlacement : public DecisionBuilder {
 public:
  TimePlacement(const EtJobShopData& data,
                const std::vector<SequenceVar*>& all_sequences,
                const std::vector<std::vector<IntervalVar*> >& jobs_to_tasks)
      : data_(data),
        all_sequences_(all_sequences),
        jobs_to_tasks_(jobs_to_tasks),
        horizon_(data_.horizon()),
        mp_solver_("TimePlacement", MPSolver::GLPK_MIXED_INTEGER_PROGRAMMING),
        num_tasks_(0) {
    for (int i = 0; i < jobs_to_tasks_.size(); ++i) {
      num_tasks_ += jobs_to_tasks_[i].size();
    }
  }

  virtual ~TimePlacement() {}

  virtual Decision* Next(Solver* const solver) {
    mp_solver_.Clear();
    std::vector<std::vector<MPVariable*> > all_vars;
    hash_map<IntervalVar*, MPVariable*> mapping;
    const double infinity = mp_solver_.infinity();
    all_vars.resize(all_sequences_.size());

    // Creates the MP Variables.
    for (int s = 0; s < jobs_to_tasks_.size(); ++s) {
      for (int t = 0; t < jobs_to_tasks_[s].size(); ++t) {
        IntervalVar* const task = jobs_to_tasks_[s][t];
        const string name = StringPrintf("J%dT%d", s, t);
        MPVariable* const var =
            mp_solver_.MakeIntVar(task->StartMin(), task->StartMax(), name);
        mapping[task] = var;
      }
    }

      // Adds the jobs precedence constraints.
    for (int j = 0; j < jobs_to_tasks_.size(); ++j) {
      for (int t = 0; t < jobs_to_tasks_[j].size() - 1; ++t) {
        IntervalVar* const first_task = jobs_to_tasks_[j][t];
        const int duration = first_task->DurationMax();
        IntervalVar* const second_task = jobs_to_tasks_[j][t + 1];
        MPVariable* const first_var = mapping[first_task];
        MPVariable* const second_var = mapping[second_task];
        MPConstraint* const ct =
            mp_solver_.MakeRowConstraint(duration, infinity);
        ct->SetCoefficient(second_var, 1.0);
        ct->SetCoefficient(first_var, -1.0);
      }
    }

    // Adds the ranked machines constraints.
    for (int s = 0; s < all_sequences_.size(); ++s) {
      SequenceVar* const sequence = all_sequences_[s];
      std::vector<int> rank_firsts;
      std::vector<int> rank_lasts;
      std::vector<int> unperformed;
      sequence->FillSequence(&rank_firsts, &rank_lasts, &unperformed);
      CHECK_EQ(0, rank_lasts.size());
      CHECK_EQ(0, unperformed.size());
      for (int i = 0; i < rank_firsts.size() - 1; ++i) {
        IntervalVar* const first_task = sequence->Interval(rank_firsts[i]);
        const int duration = first_task->DurationMax();
        IntervalVar* const second_task = sequence->Interval(rank_firsts[i + 1]);
        MPVariable* const first_var = mapping[first_task];
        MPVariable* const second_var = mapping[second_task];
        MPConstraint* const ct =
            mp_solver_.MakeRowConstraint(duration, infinity);
        ct->SetCoefficient(second_var, 1.0);
        ct->SetCoefficient(first_var, -1.0);
      }
    }

    // Creates penalty terms
    std::vector<MPVariable*> terms;
    mp_solver_.MakeIntVarArray(jobs_to_tasks_.size(),
                               0,
                               infinity,
                               "terms",
                               &terms);
    for (int j = 0; j < jobs_to_tasks_.size(); ++j) {
      mp_solver_.MutableObjective()->SetCoefficient(terms[j], 1.0);
    }
    mp_solver_.MutableObjective()->SetMinimization();
    // Forces penalty terms to be above late and early costs.
    for (int j = 0; j < jobs_to_tasks_.size(); ++j) {
      IntervalVar* const last_task = jobs_to_tasks_[j].back();
      const int duration = last_task->DurationMin();
      MPVariable* const mp_start = mapping[last_task];
      const Job& job = data_.GetJob(j);
      const int ideal_start = job.due_date - duration;
      const int early_offset = job.early_cost * ideal_start;
      MPConstraint* const early_ct =
          mp_solver_.MakeRowConstraint(early_offset, infinity);
      early_ct->SetCoefficient(terms[j], 1);
      early_ct->SetCoefficient(mp_start, job.early_cost);

      const int tardy_offset = job.tardy_cost * ideal_start;
      MPConstraint* const tardy_ct =
          mp_solver_.MakeRowConstraint(-tardy_offset, infinity);
      tardy_ct->SetCoefficient(terms[j], 1);
      tardy_ct->SetCoefficient(mp_start, -job.tardy_cost);
    }

    // Sets minization and solve.
    CHECK_EQ(MPSolver::OPTIMAL, mp_solver_.Solve());
    LOG(INFO) << "MP cost = " << mp_solver_.objective_value();
    for (int j = 0; j < jobs_to_tasks_.size(); ++j) {
      for (int t = 0; t < jobs_to_tasks_[j].size(); ++t) {
        IntervalVar* const first_task = jobs_to_tasks_[j][t];
        MPVariable* const first_var = mapping[first_task];
        const int date = first_var->solution_value();
        first_task->SetStartRange(date, date);
      }
    }
    return NULL;
  }

  virtual string DebugString() const {
    return "TimePlacement";
  }

 private:
  const EtJobShopData& data_;
  const std::vector<SequenceVar*>& all_sequences_;
  const std::vector<std::vector<IntervalVar*> >& jobs_to_tasks_;
  const int horizon_;
  MPSolver mp_solver_;
  int num_tasks_;
};

void EtJobShop(const EtJobShopData& data) {
  Solver solver("et_jobshop");
  const int machine_count = data.machine_count();
  const int job_count = data.job_count();
  const int horizon = data.horizon();

  // ----- Creates all Intervals and vars -----

  // Stores all tasks attached interval variables per job.
  std::vector<std::vector<IntervalVar*> > jobs_to_tasks(job_count);
  // machines_to_tasks stores the same interval variables as above, but
  // grouped my machines instead of grouped by jobs.
  std::vector<std::vector<IntervalVar*> > machines_to_tasks(machine_count);

  // Creates all individual interval variables.
  for (int job_id = 0; job_id < job_count; ++job_id) {
    const Job& job = data.GetJob(job_id);
    const std::vector<Task>& tasks = job.all_tasks;
    for (int task_index = 0; task_index < tasks.size(); ++task_index) {
      const Task& task = tasks[task_index];
      CHECK_EQ(job_id, task.job_id);
      const string name = StringPrintf("J%dM%dI%dD%d",
                                       task.job_id,
                                       task.machine_id,
                                       task_index,
                                       task.duration);
      IntervalVar* const one_task =
          solver.MakeFixedDurationIntervalVar(0,
                                              horizon,
                                              task.duration,
                                              false,
                                              name);
      jobs_to_tasks[task.job_id].push_back(one_task);
      machines_to_tasks[task.machine_id].push_back(one_task);
    }
  }

  // ----- Creates model -----

  // Creates precedences inside jobs.
  for (int job_id = 0; job_id < job_count; ++job_id) {
    const int task_count = jobs_to_tasks[job_id].size();
    for (int task_index = 0; task_index < task_count - 1; ++task_index) {
      IntervalVar* const t1 = jobs_to_tasks[job_id][task_index];
      IntervalVar* const t2 = jobs_to_tasks[job_id][task_index + 1];
      Constraint* const prec =
          solver.MakeIntervalVarRelation(t2, Solver::STARTS_AFTER_END, t1);
      solver.AddConstraint(prec);
    }
  }

  // Add release date.
  for (int job_id = 0; job_id < job_count; ++job_id) {
    const Job& job = data.GetJob(job_id);
    IntervalVar* const t = jobs_to_tasks[job_id][0];
    Constraint* const prec =
        solver.MakeIntervalVarRelation(t,
                                       Solver::STARTS_AFTER,
                                       job.release_date);
    solver.AddConstraint(prec);
  }

  std::vector<IntVar*> penalties;
  for (int job_id = 0; job_id < job_count; ++job_id) {
    const Job& job = data.GetJob(job_id);
    IntervalVar* const t = jobs_to_tasks[job_id][machine_count - 1];
    IntVar* const penalty =
        solver.MakeConvexPiecewiseExpr(t->EndExpr(),
                                       job.early_cost,
                                       job.due_date,
                                       job.due_date,
                                       job.tardy_cost)->Var();
    penalties.push_back(penalty);
  }

  // Adds disjunctive constraints on unary resources.
  for (int machine_id = 0; machine_id < machine_count; ++machine_id) {
    solver.AddConstraint(
        solver.MakeDisjunctiveConstraint(machines_to_tasks[machine_id]));
  }

  // Creates sequences variables on machines. A sequence variable is a
  // dedicated variable whose job is to sequence interval variables.
  std::vector<SequenceVar*> all_sequences;
  for (int machine_id = 0; machine_id < machine_count; ++machine_id) {
    const string name = StringPrintf("Machine_%d", machine_id);
    SequenceVar* const sequence =
        solver.MakeSequenceVar(machines_to_tasks[machine_id], name);
    all_sequences.push_back(sequence);
  }

  // Objective: minimize the weighted penalties.
  IntVar* const objective_var = solver.MakeSum(penalties)->Var();
  OptimizeVar* const objective_monitor = solver.MakeMinimize(objective_var, 1);

  // ----- Search monitors and decision builder -----

  // This decision builder will rank all tasks on all machines.
  DecisionBuilder* const sequence_phase =
      solver.MakePhase(all_sequences, Solver::SEQUENCE_DEFAULT);

  // After the ranking of tasks, the schedule is still loose and any
  // task can be postponed at will. But, because the problem is now a PERT
  // (http://en.wikipedia.org/wiki/Program_Evaluation_and_Review_Technique),
  // we can schedule each task at its earliest start time. This is
  // conveniently done by fixing the objective variable to its
  // minimum value.
  DecisionBuilder* const obj_phase =
      FLAGS_time_placement ?
      solver.RevAlloc(new TimePlacement(data, all_sequences, jobs_to_tasks)) :
      solver.MakePhase(objective_var,
                       Solver::CHOOSE_FIRST_UNBOUND,
                       Solver::ASSIGN_MIN_VALUE);

  // The main decision builder (ranks all tasks, then fixes the
  // objective_variable).
  DecisionBuilder* const main_phase =
      solver.Compose(sequence_phase, obj_phase);

  // Search log.
  const int kLogFrequency = 1000000;
  SearchMonitor* const search_log =
      solver.MakeSearchLog(kLogFrequency, objective_monitor);

  SearchLimit* limit = NULL;
  if (FLAGS_time_limit_in_ms > 0) {
    limit = solver.MakeTimeLimit(FLAGS_time_limit_in_ms);
  }

  // Search.
  solver.Solve(main_phase, search_log, objective_monitor, limit);
}
}  // namespace operations_research

static const char kUsage[] =
    "Usage: see flags.\nThis program runs a simple job shop optimization "
    "output besides the debug LOGs of the solver.";

int main(int argc, char **argv) {
  FLAGS_log_prefix = false;
  google::SetUsageMessage(kUsage);
  google::ParseCommandLineFlags(&argc, &argv, true);
  operations_research::EtJobShopData data;
  if (!FLAGS_jet_file.empty()) {
    data.LoadJetFile(FLAGS_jet_file);
  } else {
    data.GenerateRandomData(FLAGS_machine_count,
                            FLAGS_job_count,
                            FLAGS_max_release_date,
                            FLAGS_max_early_cost,
                            FLAGS_max_tardy_cost,
                            FLAGS_max_duration,
                            FLAGS_scale_factor,
                            FLAGS_seed);
  }
  operations_research::EtJobShop(data);
  return 0;
}
<commit_msg>implement time placement code for early tardy<commit_after>// Copyright 2010-2012 Google
// 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.
//
// This model implements a simple jobshop problem with
// earlyness-tardiness costs.
//
// A earlyness-tardinessjobshop is a standard scheduling problem where
// you must schedule a set of jobs on a set of machines.  Each job is
// a sequence of tasks (a task can only start when the preceding task
// finished), each of which occupies a single specific machine during
// a specific duration. Therefore, a job is a sequence of pairs
// (machine id, duration), along with a release data (minimum start
// date of the first task of the job, and due data (end time of the
// last job) with a tardiness linear penalty.

// The objective is to minimize the sum of early-tardy penalties for each job.
//
// This will be modelled by sets of intervals variables (see class
// IntervalVar in constraint_solver/constraint_solver.h), one per
// task, representing the [start_time, end_time] of the task.  Tasks
// in the same job will be linked by precedence constraints.  Tasks on
// the same machine will be covered by Sequence constraints.

#include <cstdio>
#include <cstdlib>

#include <vector>

#include "base/commandlineflags.h"
#include "base/commandlineflags.h"
#include "base/integral_types.h"
#include "base/logging.h"
#include "base/stringprintf.h"
#include "constraint_solver/constraint_solver.h"
#include "linear_solver/linear_solver.h"
#include "util/string_array.h"
#include "cpp/jobshop_earlytardy.h"

DEFINE_string(
    jet_file,
    "",
    "Required: input file description the scheduling problem to solve, "
    "in our jet format:\n"
    "  - the first line is \"<number of jobs> <number of machines>\"\n"
    "  - then one line per job, with a single space-separated "
    "list of \"<machine index> <duration>\", ended by due_date, early_cost,"
    "late_cost\n"
    "note: jobs with one task are not supported");
DEFINE_int32(machine_count, 10, "Machine count");
DEFINE_int32(job_count, 10, "Job count");
DEFINE_int32(max_release_date, 0, "Max release date");
DEFINE_int32(max_early_cost, 0, "Max earlyness weight");
DEFINE_int32(max_tardy_cost, 3, "Max tardiness weight");
DEFINE_int32(max_duration, 10, "Max duration of a task");
DEFINE_int32(scale_factor, 130, "Scale factor (in percent)");
DEFINE_int32(seed, 1, "Random seed");
DEFINE_int32(time_limit_in_ms, 0, "Time limit in ms, 0 means no limit.");
DEFINE_bool(time_placement, false, "Use MIP based time placement");
DECLARE_bool(log_prefix);

namespace operations_research {
class TimePlacement : public DecisionBuilder {
 public:
  TimePlacement(const EtJobShopData& data,
                const std::vector<SequenceVar*>& all_sequences,
                const std::vector<std::vector<IntervalVar*> >& jobs_to_tasks)
      : data_(data),
        all_sequences_(all_sequences),
        jobs_to_tasks_(jobs_to_tasks),
        horizon_(data_.horizon()),
        mp_solver_("TimePlacement", MPSolver::GLPK_MIXED_INTEGER_PROGRAMMING),
        num_tasks_(0) {
    for (int i = 0; i < jobs_to_tasks_.size(); ++i) {
      num_tasks_ += jobs_to_tasks_[i].size();
    }
  }

  virtual ~TimePlacement() {}

  virtual Decision* Next(Solver* const solver) {
    mp_solver_.Clear();
    std::vector<std::vector<MPVariable*> > all_vars;
    hash_map<IntervalVar*, MPVariable*> mapping;
    const double infinity = mp_solver_.infinity();
    all_vars.resize(all_sequences_.size());

    // Creates the MP Variables.
    for (int s = 0; s < jobs_to_tasks_.size(); ++s) {
      for (int t = 0; t < jobs_to_tasks_[s].size(); ++t) {
        IntervalVar* const task = jobs_to_tasks_[s][t];
        const string name = StringPrintf("J%dT%d", s, t);
        MPVariable* const var =
            mp_solver_.MakeIntVar(task->StartMin(), task->StartMax(), name);
        mapping[task] = var;
      }
    }

      // Adds the jobs precedence constraints.
    for (int j = 0; j < jobs_to_tasks_.size(); ++j) {
      for (int t = 0; t < jobs_to_tasks_[j].size() - 1; ++t) {
        IntervalVar* const first_task = jobs_to_tasks_[j][t];
        const int duration = first_task->DurationMax();
        IntervalVar* const second_task = jobs_to_tasks_[j][t + 1];
        MPVariable* const first_var = mapping[first_task];
        MPVariable* const second_var = mapping[second_task];
        MPConstraint* const ct =
            mp_solver_.MakeRowConstraint(duration, infinity);
        ct->SetCoefficient(second_var, 1.0);
        ct->SetCoefficient(first_var, -1.0);
      }
    }

    // Adds the ranked machines constraints.
    for (int s = 0; s < all_sequences_.size(); ++s) {
      SequenceVar* const sequence = all_sequences_[s];
      std::vector<int> rank_firsts;
      std::vector<int> rank_lasts;
      std::vector<int> unperformed;
      sequence->FillSequence(&rank_firsts, &rank_lasts, &unperformed);
      CHECK_EQ(0, rank_lasts.size());
      CHECK_EQ(0, unperformed.size());
      for (int i = 0; i < rank_firsts.size() - 1; ++i) {
        IntervalVar* const first_task = sequence->Interval(rank_firsts[i]);
        const int duration = first_task->DurationMax();
        IntervalVar* const second_task = sequence->Interval(rank_firsts[i + 1]);
        MPVariable* const first_var = mapping[first_task];
        MPVariable* const second_var = mapping[second_task];
        MPConstraint* const ct =
            mp_solver_.MakeRowConstraint(duration, infinity);
        ct->SetCoefficient(second_var, 1.0);
        ct->SetCoefficient(first_var, -1.0);
      }
    }

    // Creates penalty terms and objective.
    std::vector<MPVariable*> terms;
    mp_solver_.MakeIntVarArray(jobs_to_tasks_.size(),
                               0,
                               infinity,
                               "terms",
                               &terms);
    for (int j = 0; j < jobs_to_tasks_.size(); ++j) {
      mp_solver_.MutableObjective()->SetCoefficient(terms[j], 1.0);
    }
    mp_solver_.MutableObjective()->SetMinimization();

    // Forces penalty terms to be above late and early costs.
    for (int j = 0; j < jobs_to_tasks_.size(); ++j) {
      IntervalVar* const last_task = jobs_to_tasks_[j].back();
      const int duration = last_task->DurationMin();
      MPVariable* const mp_start = mapping[last_task];
      const Job& job = data_.GetJob(j);
      const int ideal_start = job.due_date - duration;
      const int early_offset = job.early_cost * ideal_start;
      MPConstraint* const early_ct =
          mp_solver_.MakeRowConstraint(early_offset, infinity);
      early_ct->SetCoefficient(terms[j], 1);
      early_ct->SetCoefficient(mp_start, job.early_cost);

      const int tardy_offset = job.tardy_cost * ideal_start;
      MPConstraint* const tardy_ct =
          mp_solver_.MakeRowConstraint(-tardy_offset, infinity);
      tardy_ct->SetCoefficient(terms[j], 1);
      tardy_ct->SetCoefficient(mp_start, -job.tardy_cost);
    }

    // Solve.
    CHECK_EQ(MPSolver::OPTIMAL, mp_solver_.Solve());

    // Inject MIP solution into the CP part.
    LOG(INFO) << "MP cost = " << mp_solver_.objective_value();
    for (int j = 0; j < jobs_to_tasks_.size(); ++j) {
      for (int t = 0; t < jobs_to_tasks_[j].size(); ++t) {
        IntervalVar* const first_task = jobs_to_tasks_[j][t];
        MPVariable* const first_var = mapping[first_task];
        const int date = first_var->solution_value();
        first_task->SetStartRange(date, date);
      }
    }
    return NULL;
  }

  virtual string DebugString() const {
    return "TimePlacement";
  }

 private:
  const EtJobShopData& data_;
  const std::vector<SequenceVar*>& all_sequences_;
  const std::vector<std::vector<IntervalVar*> >& jobs_to_tasks_;
  const int horizon_;
  MPSolver mp_solver_;
  int num_tasks_;
};

void EtJobShop(const EtJobShopData& data) {
  Solver solver("et_jobshop");
  const int machine_count = data.machine_count();
  const int job_count = data.job_count();
  const int horizon = data.horizon();

  // ----- Creates all Intervals and vars -----

  // Stores all tasks attached interval variables per job.
  std::vector<std::vector<IntervalVar*> > jobs_to_tasks(job_count);
  // machines_to_tasks stores the same interval variables as above, but
  // grouped my machines instead of grouped by jobs.
  std::vector<std::vector<IntervalVar*> > machines_to_tasks(machine_count);

  // Creates all individual interval variables.
  for (int job_id = 0; job_id < job_count; ++job_id) {
    const Job& job = data.GetJob(job_id);
    const std::vector<Task>& tasks = job.all_tasks;
    for (int task_index = 0; task_index < tasks.size(); ++task_index) {
      const Task& task = tasks[task_index];
      CHECK_EQ(job_id, task.job_id);
      const string name = StringPrintf("J%dM%dI%dD%d",
                                       task.job_id,
                                       task.machine_id,
                                       task_index,
                                       task.duration);
      IntervalVar* const one_task =
          solver.MakeFixedDurationIntervalVar(0,
                                              horizon,
                                              task.duration,
                                              false,
                                              name);
      jobs_to_tasks[task.job_id].push_back(one_task);
      machines_to_tasks[task.machine_id].push_back(one_task);
    }
  }

  // ----- Creates model -----

  // Creates precedences inside jobs.
  for (int job_id = 0; job_id < job_count; ++job_id) {
    const int task_count = jobs_to_tasks[job_id].size();
    for (int task_index = 0; task_index < task_count - 1; ++task_index) {
      IntervalVar* const t1 = jobs_to_tasks[job_id][task_index];
      IntervalVar* const t2 = jobs_to_tasks[job_id][task_index + 1];
      Constraint* const prec =
          solver.MakeIntervalVarRelation(t2, Solver::STARTS_AFTER_END, t1);
      solver.AddConstraint(prec);
    }
  }

  // Add release date.
  for (int job_id = 0; job_id < job_count; ++job_id) {
    const Job& job = data.GetJob(job_id);
    IntervalVar* const t = jobs_to_tasks[job_id][0];
    Constraint* const prec =
        solver.MakeIntervalVarRelation(t,
                                       Solver::STARTS_AFTER,
                                       job.release_date);
    solver.AddConstraint(prec);
  }

  std::vector<IntVar*> penalties;
  for (int job_id = 0; job_id < job_count; ++job_id) {
    const Job& job = data.GetJob(job_id);
    IntervalVar* const t = jobs_to_tasks[job_id][machine_count - 1];
    IntVar* const penalty =
        solver.MakeConvexPiecewiseExpr(t->EndExpr(),
                                       job.early_cost,
                                       job.due_date,
                                       job.due_date,
                                       job.tardy_cost)->Var();
    penalties.push_back(penalty);
  }

  // Adds disjunctive constraints on unary resources.
  for (int machine_id = 0; machine_id < machine_count; ++machine_id) {
    solver.AddConstraint(
        solver.MakeDisjunctiveConstraint(machines_to_tasks[machine_id]));
  }

  // Creates sequences variables on machines. A sequence variable is a
  // dedicated variable whose job is to sequence interval variables.
  std::vector<SequenceVar*> all_sequences;
  for (int machine_id = 0; machine_id < machine_count; ++machine_id) {
    const string name = StringPrintf("Machine_%d", machine_id);
    SequenceVar* const sequence =
        solver.MakeSequenceVar(machines_to_tasks[machine_id], name);
    all_sequences.push_back(sequence);
  }

  // Objective: minimize the weighted penalties.
  IntVar* const objective_var = solver.MakeSum(penalties)->Var();
  OptimizeVar* const objective_monitor = solver.MakeMinimize(objective_var, 1);

  // ----- Search monitors and decision builder -----

  // This decision builder will rank all tasks on all machines.
  DecisionBuilder* const sequence_phase =
      solver.MakePhase(all_sequences, Solver::SEQUENCE_DEFAULT);

  // After the ranking of tasks, the schedule is still loose and any
  // task can be postponed at will. But, because the problem is now a PERT
  // (http://en.wikipedia.org/wiki/Program_Evaluation_and_Review_Technique),
  // we can schedule each task at its earliest start time. This is
  // conveniently done by fixing the objective variable to its
  // minimum value.
  DecisionBuilder* const obj_phase =
      FLAGS_time_placement ?
      solver.RevAlloc(new TimePlacement(data, all_sequences, jobs_to_tasks)) :
      solver.MakePhase(objective_var,
                       Solver::CHOOSE_FIRST_UNBOUND,
                       Solver::ASSIGN_MIN_VALUE);

  // The main decision builder (ranks all tasks, then fixes the
  // objective_variable).
  DecisionBuilder* const main_phase =
      solver.Compose(sequence_phase, obj_phase);

  // Search log.
  const int kLogFrequency = 1000000;
  SearchMonitor* const search_log =
      solver.MakeSearchLog(kLogFrequency, objective_monitor);

  SearchLimit* limit = NULL;
  if (FLAGS_time_limit_in_ms > 0) {
    limit = solver.MakeTimeLimit(FLAGS_time_limit_in_ms);
  }

  // Search.
  solver.Solve(main_phase, search_log, objective_monitor, limit);
}
}  // namespace operations_research

static const char kUsage[] =
    "Usage: see flags.\nThis program runs a simple job shop optimization "
    "output besides the debug LOGs of the solver.";

int main(int argc, char **argv) {
  FLAGS_log_prefix = false;
  google::SetUsageMessage(kUsage);
  google::ParseCommandLineFlags(&argc, &argv, true);
  operations_research::EtJobShopData data;
  if (!FLAGS_jet_file.empty()) {
    data.LoadJetFile(FLAGS_jet_file);
  } else {
    data.GenerateRandomData(FLAGS_machine_count,
                            FLAGS_job_count,
                            FLAGS_max_release_date,
                            FLAGS_max_early_cost,
                            FLAGS_max_tardy_cost,
                            FLAGS_max_duration,
                            FLAGS_scale_factor,
                            FLAGS_seed);
  }
  operations_research::EtJobShop(data);
  return 0;
}
<|endoftext|>


<commit_before><commit_msg>tsan: improve shadow flush benchmark allow to specify access stride<commit_after><|endoftext|>


<commit_before>//===-- SILDis.cpp - SIL function dision utility --------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
//
// This utility is meant to help simplify the dision of test cases from sil
// files by removing (currently only) functions that do not match a
// string. Eventually this should have additional capabilities like stripping
// globals, vtables, etc.
//
//===----------------------------------------------------------------------===//

#include "swift/Subsystems.h"
#include "swift/Frontend/DiagnosticVerifier.h"
#include "swift/Frontend/Frontend.h"
#include "swift/Frontend/PrintingDiagnosticConsumer.h"
#include "swift/Serialization/SerializedModuleLoader.h"
#include "swift/Serialization/SerializedSILLoader.h"
#include "swift/Serialization/ModuleFile.h"
#include "swift/SILPasses/Passes.h"
#include "swift/SIL/SILUndef.h"
#include "swift/AST/Decl.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Signals.h"
using namespace swift;

static llvm::cl::opt<std::string>
InputFilename(llvm::cl::desc("input file"), llvm::cl::init("-"),
              llvm::cl::Positional);

static llvm::cl::opt<std::string>
OutputFilename("o", llvm::cl::desc("output filename"), llvm::cl::init("-"));

static llvm::cl::opt<bool>
EmitVerboseSIL("emit-verbose-sil",
               llvm::cl::desc("Emit locations during sil emission."));

static llvm::cl::list<std::string>
ImportPaths("I", llvm::cl::desc("add a directory to the import search path"));

namespace {
  enum class ActionKind {
    DumpDecls,
    DumpSIL,
  };
} // end anonymous namespace

static llvm::cl::list<ActionKind>
Actions(llvm::cl::desc("Actions:"),
       llvm::cl::values(clEnumValN(ActionKind::DumpDecls,
                                   "dump-decls", "Dump SILModule Decls."),
                        clEnumValN(ActionKind::DumpSIL,
                                   "dump-sil",
                                   "Dump SIL in SILModule."),
                        clEnumValEnd),
        llvm::cl::OneOrMore);

// This function isn't referenced outside its translation unit, but it
// can't use the "static" keyword because its address is used for
// getMainExecutable (since some platforms don't support taking the
// address of main, and some platforms can't implement getMainExecutable
// without being given the address of a function in the main executable).
void anchorForGetMainExecutable() {}

int main(int argc, char **argv) {
  // Print a stack trace if we signal out.
  llvm::sys::PrintStackTraceOnErrorSignal();
  llvm::PrettyStackTraceProgram X(argc, argv);

  llvm::cl::ParseCommandLineOptions(argc, argv, "Swift SIL Disassembler\n");

  // Call llvm_shutdown() on exit to print stats and free memory.
  llvm::llvm_shutdown_obj Y;

  LangOptions LangOpts;
  SearchPathOptions SearchPathOpts;
  SourceManager SourceMgr;
  DiagnosticEngine Diagnostics{SourceMgr};
  std::unique_ptr<ASTContext> Context;
  std::unique_ptr<SILModule> TheSILModule;;

  Context.reset(new ASTContext(LangOpts, SearchPathOpts,
                               SourceMgr, Diagnostics));
  SerializedModuleLoader *SML = SerializedModuleLoader::create(*Context);
  Context->addModuleLoader(SML);

  // For now we only support working on the standard library.
  //
  // TODO: Generalize this.
  Identifier ID = Context->getIdentifier("Swift");
  Module *MainModule = Module::create(ID, *Context);
  Context->LoadedModules[ID.str()] = MainModule;

  PersistentParserState PersistentState;

  llvm::OwningPtr<llvm::MemoryBuffer> InputFile;
  if (llvm::MemoryBuffer::getFileOrSTDIN(InputFilename, InputFile)) {
    fprintf(stderr, "Error! Failed to open file: %s\n", InputFilename.c_str());
    exit(-1);
  }

  unsigned BufferID = SourceMgr.addNewSourceBuffer(InputFile.take());
  // Being cautious in the hack.
  auto Buffer = SourceMgr.getLLVMSourceMgr().getMemoryBuffer(BufferID);

  if (!SerializedModuleLoader::isSerializedAST(Buffer->getBuffer())) {
    fprintf(stderr, "Error! File does not contain AST!\n");
    exit(-1);
  }

  std::unique_ptr<llvm::MemoryBuffer> Input(
    llvm::MemoryBuffer::getMemBuffer(Buffer->getBuffer(),
                                     Buffer->getBufferIdentifier(),
                                     false));
  FileUnit *FUnit;
  if (!(FUnit = SML->loadAST(*MainModule, SourceLoc(), std::move(Input)))) {
    fprintf(stderr, "Error! Failed to load AST.\n");
    exit(-1);
  }

  for (auto Action : Actions)
    switch (Action) {
    case ActionKind::DumpDecls: {
      llvm::SmallVector<Decl *, 16> results;
      FUnit->getTopLevelDecls(results);

      for (auto Decl : results) {
        Decl->print(llvm::outs());
        llvm::outs() << "\n";
      }
      break;
    }
    case ActionKind::DumpSIL: {
      std::unique_ptr<SILModule> SILMod = SILModule::createEmptyModule(MainModule);
      std::unique_ptr<SerializedSILLoader> SL(SerializedSILLoader::create(*Context.get(),
                                                                          SILMod.get(),
                                                                          nullptr));
      SL->getAll();
      SILMod->print(llvm::outs(), EmitVerboseSIL, MainModule);
      break;
    }
    }

  return 0;
}
<commit_msg>Fix typo = /. NFC.<commit_after>//===-- SILDis.cpp - SIL function deserialization utility -----------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
//
// This utility is meant to help simplify the dision of test cases from sil
// files by removing (currently only) functions that do not match a
// string. Eventually this should have additional capabilities like stripping
// globals, vtables, etc.
//
//===----------------------------------------------------------------------===//

#include "swift/Subsystems.h"
#include "swift/Frontend/DiagnosticVerifier.h"
#include "swift/Frontend/Frontend.h"
#include "swift/Frontend/PrintingDiagnosticConsumer.h"
#include "swift/Serialization/SerializedModuleLoader.h"
#include "swift/Serialization/SerializedSILLoader.h"
#include "swift/Serialization/ModuleFile.h"
#include "swift/SILPasses/Passes.h"
#include "swift/SIL/SILUndef.h"
#include "swift/AST/Decl.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Signals.h"
using namespace swift;

static llvm::cl::opt<std::string>
InputFilename(llvm::cl::desc("input file"), llvm::cl::init("-"),
              llvm::cl::Positional);

static llvm::cl::opt<std::string>
OutputFilename("o", llvm::cl::desc("output filename"), llvm::cl::init("-"));

static llvm::cl::opt<bool>
EmitVerboseSIL("emit-verbose-sil",
               llvm::cl::desc("Emit locations during sil emission."));

static llvm::cl::list<std::string>
ImportPaths("I", llvm::cl::desc("add a directory to the import search path"));

namespace {
  enum class ActionKind {
    DumpDecls,
    DumpSIL,
  };
} // end anonymous namespace

static llvm::cl::list<ActionKind>
Actions(llvm::cl::desc("Actions:"),
       llvm::cl::values(clEnumValN(ActionKind::DumpDecls,
                                   "dump-decls", "Dump SILModule Decls."),
                        clEnumValN(ActionKind::DumpSIL,
                                   "dump-sil",
                                   "Dump SIL in SILModule."),
                        clEnumValEnd),
        llvm::cl::OneOrMore);

// This function isn't referenced outside its translation unit, but it
// can't use the "static" keyword because its address is used for
// getMainExecutable (since some platforms don't support taking the
// address of main, and some platforms can't implement getMainExecutable
// without being given the address of a function in the main executable).
void anchorForGetMainExecutable() {}

int main(int argc, char **argv) {
  // Print a stack trace if we signal out.
  llvm::sys::PrintStackTraceOnErrorSignal();
  llvm::PrettyStackTraceProgram X(argc, argv);

  llvm::cl::ParseCommandLineOptions(argc, argv, "Swift SIL Disassembler\n");

  // Call llvm_shutdown() on exit to print stats and free memory.
  llvm::llvm_shutdown_obj Y;

  LangOptions LangOpts;
  SearchPathOptions SearchPathOpts;
  SourceManager SourceMgr;
  DiagnosticEngine Diagnostics{SourceMgr};
  std::unique_ptr<ASTContext> Context;
  std::unique_ptr<SILModule> TheSILModule;;

  Context.reset(new ASTContext(LangOpts, SearchPathOpts,
                               SourceMgr, Diagnostics));
  SerializedModuleLoader *SML = SerializedModuleLoader::create(*Context);
  Context->addModuleLoader(SML);

  // For now we only support working on the standard library.
  //
  // TODO: Generalize this.
  Identifier ID = Context->getIdentifier("Swift");
  Module *MainModule = Module::create(ID, *Context);
  Context->LoadedModules[ID.str()] = MainModule;

  PersistentParserState PersistentState;

  llvm::OwningPtr<llvm::MemoryBuffer> InputFile;
  if (llvm::MemoryBuffer::getFileOrSTDIN(InputFilename, InputFile)) {
    fprintf(stderr, "Error! Failed to open file: %s\n", InputFilename.c_str());
    exit(-1);
  }

  unsigned BufferID = SourceMgr.addNewSourceBuffer(InputFile.take());
  // Being cautious in the hack.
  auto Buffer = SourceMgr.getLLVMSourceMgr().getMemoryBuffer(BufferID);

  if (!SerializedModuleLoader::isSerializedAST(Buffer->getBuffer())) {
    fprintf(stderr, "Error! File does not contain AST!\n");
    exit(-1);
  }

  std::unique_ptr<llvm::MemoryBuffer> Input(
    llvm::MemoryBuffer::getMemBuffer(Buffer->getBuffer(),
                                     Buffer->getBufferIdentifier(),
                                     false));
  FileUnit *FUnit;
  if (!(FUnit = SML->loadAST(*MainModule, SourceLoc(), std::move(Input)))) {
    fprintf(stderr, "Error! Failed to load AST.\n");
    exit(-1);
  }

  for (auto Action : Actions)
    switch (Action) {
    case ActionKind::DumpDecls: {
      llvm::SmallVector<Decl *, 16> results;
      FUnit->getTopLevelDecls(results);

      for (auto Decl : results) {
        Decl->print(llvm::outs());
        llvm::outs() << "\n";
      }
      break;
    }
    case ActionKind::DumpSIL: {
      std::unique_ptr<SILModule> SILMod = SILModule::createEmptyModule(MainModule);
      std::unique_ptr<SerializedSILLoader> SL(SerializedSILLoader::create(*Context.get(),
                                                                          SILMod.get(),
                                                                          nullptr));
      SL->getAll();
      SILMod->print(llvm::outs(), EmitVerboseSIL, MainModule);
      break;
    }
    }

  return 0;
}
<|endoftext|>


<commit_before>
#include "properties.h"
#include "formats.h"
#include "multimedia.h"

#include <tis.h>

#include <iostream>
#include <iomanip>
#include <unistd.h>

using namespace tcam;

void print_help ()
{
    std::cout << "Commandline camera manipulation utility." << std::endl
              << std::endl
              << "Options:" << std::endl
              << "\t-l - list cameras" << std::endl
              << "\t-p - list properties"  << std::endl
              << "\t-f - list video formats" << std::endl
              << std::endl
              << "Examples:" << std::endl
              << std::endl
              << "Set video format:" << std::endl
              << "\ttis-ctrl -s -f \"format=RGB32,width=1920,height=1080,framerate=15.0,binning=0\" 25410069" << std::endl
              << std::endl
              << "Set property" << std::endl
              << "\ttis-ctrl -s -p \"Auto Exposure=false\""
              << std::endl
              << std::endl;
}

void print_capture_devices (const std::vector<DeviceInfo>& devices)
{
  std::cout << "Available devices:" << std::endl;
  std::cout << "Model\t\tType\tSerial" << std::endl << std::endl;
    for (const auto& d : devices)
    {
      std::cout << d.getName() << "\t" << d.getDeviceTypeAsString() << "\t" << d.getSerial() << std::endl;
    }
    std::cout << std::endl;
}

enum modes
{
    LIST_PROPERTIES = 0,
    SET_PROPERTY,
    LIST_FORMATS,
    SET_FORMAT,
    LIST_DEVICES,
    SAVE_STREAM,
    SAVE_IMAGE,
};

enum INTERACTION
{
    GET = 0,
    SET,
};

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

    if (argc == 1)
    {
        print_help();
        return 0;
    }

    INTERACTION way = GET;
    std::string serial;
    std::string param;
    std::string filename;
    modes do_this;

    for (int i = 0; i < argc; ++i)
    {
        std::string arg = argv[i];

        if (arg == "-h" || arg == "--help")
        {
            print_help();
            return 0;
        }
        else if (arg == "-l" || arg == "--list")
        {
            auto index = getDeviceIndex();
            sleep(3); // let camera detection do its magic
            std::vector<DeviceInfo> device_list = index->getDeviceList();
            print_capture_devices(device_list);
            return 0;
        }
        else if (arg == "-p" || arg == "--list-properties")
        {
            do_this = LIST_PROPERTIES;
            break;
        }
        else if (arg == "-s" || arg == "--set")
        {
            way = SET;
            do_this = SET_PROPERTY;
            int tmp_i = i;
            tmp_i++;
            if (tmp_i >= argc)
            {
                std::cout << "--set requires additional arguments to work properly!" << std::endl;
                return 1;
            }
            param = argv[tmp_i];
            i++;

            // break;
        }
        else if (arg == "-f" || arg == "--format")
        {
            do_this = LIST_FORMATS;
            // break;
        }
        else
        {
            serial = arg;
        }
    }

    if (serial.empty())
    {
        std::cout << "No serial given!" << std::endl;
        return 1;
    }

    auto device_index = getDeviceIndex();
    sleep(3);
    std::vector<DeviceInfo> device_list = device_index->getDeviceList();

    CaptureDevice g;

    for (auto& d : device_list)
    {
        if (d.getSerial().compare(serial) == 0)
        {
            g.openDevice(d);

        }
    }

    if (!g.isDeviceOpen())
    {
        std::cout << "Unable to find device with serial '" << serial << "'" << std::endl;
        return 1;
    }

    switch (do_this)
    {
        case LIST_PROPERTIES:
        {
            print_properties(g.getAvailableProperties());
            break;
        }
        case LIST_FORMATS:
        {
            list_formats(g.getAvailableVideoFormats());
            break;
        }
        case SET_PROPERTY:
        {
            set_property(g, param);
            break;
        }
        case SET_FORMAT:
        {
            set_active_format(g, param);
            break;
        }
        case SAVE_STREAM:
        {
            //save_stream(g, filename);
        }
        case SAVE_IMAGE:
        {
            save_image(g, filename);
            break;
        }
        default:
        {
            std::cout << "Unknown command." << std::endl;
            break;
        }
    }

    return 0;
}
<commit_msg>Corrected header include<commit_after>
#include "properties.h"
#include "formats.h"
#include "multimedia.h"

#include <tcam.h>

#include <iostream>
#include <iomanip>
#include <unistd.h>

using namespace tcam;

void print_help ()
{
    std::cout << "Commandline camera manipulation utility." << std::endl
              << std::endl
              << "Options:" << std::endl
              << "\t-l - list cameras" << std::endl
              << "\t-p - list properties"  << std::endl
              << "\t-f - list video formats" << std::endl
              << std::endl
              << "Examples:" << std::endl
              << std::endl
              << "Set video format:" << std::endl
              << "\ttis-ctrl -s -f \"format=RGB32,width=1920,height=1080,framerate=15.0,binning=0\" 25410069" << std::endl
              << std::endl
              << "Set property" << std::endl
              << "\ttis-ctrl -s -p \"Auto Exposure=false\""
              << std::endl
              << std::endl;
}

void print_capture_devices (const std::vector<DeviceInfo>& devices)
{
  std::cout << "Available devices:" << std::endl;
  std::cout << "Model\t\tType\tSerial" << std::endl << std::endl;
    for (const auto& d : devices)
    {
      std::cout << d.getName() << "\t" << d.getDeviceTypeAsString() << "\t" << d.getSerial() << std::endl;
    }
    std::cout << std::endl;
}

enum modes
{
    LIST_PROPERTIES = 0,
    SET_PROPERTY,
    LIST_FORMATS,
    SET_FORMAT,
    LIST_DEVICES,
    SAVE_STREAM,
    SAVE_IMAGE,
};

enum INTERACTION
{
    GET = 0,
    SET,
};

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

    if (argc == 1)
    {
        print_help();
        return 0;
    }

    INTERACTION way = GET;
    std::string serial;
    std::string param;
    std::string filename;
    modes do_this;

    for (int i = 0; i < argc; ++i)
    {
        std::string arg = argv[i];

        if (arg == "-h" || arg == "--help")
        {
            print_help();
            return 0;
        }
        else if (arg == "-l" || arg == "--list")
        {
            auto index = getDeviceIndex();
            sleep(3); // let camera detection do its magic
            std::vector<DeviceInfo> device_list = index->getDeviceList();
            print_capture_devices(device_list);
            return 0;
        }
        else if (arg == "-p" || arg == "--list-properties")
        {
            do_this = LIST_PROPERTIES;
            break;
        }
        else if (arg == "-s" || arg == "--set")
        {
            way = SET;
            do_this = SET_PROPERTY;
            int tmp_i = i;
            tmp_i++;
            if (tmp_i >= argc)
            {
                std::cout << "--set requires additional arguments to work properly!" << std::endl;
                return 1;
            }
            param = argv[tmp_i];
            i++;

            // break;
        }
        else if (arg == "-f" || arg == "--format")
        {
            do_this = LIST_FORMATS;
            // break;
        }
        else
        {
            serial = arg;
        }
    }

    if (serial.empty())
    {
        std::cout << "No serial given!" << std::endl;
        return 1;
    }

    auto device_index = getDeviceIndex();
    sleep(3);
    std::vector<DeviceInfo> device_list = device_index->getDeviceList();

    CaptureDevice g;

    for (auto& d : device_list)
    {
        if (d.getSerial().compare(serial) == 0)
        {
            g.openDevice(d);

        }
    }

    if (!g.isDeviceOpen())
    {
        std::cout << "Unable to find device with serial '" << serial << "'" << std::endl;
        return 1;
    }

    switch (do_this)
    {
        case LIST_PROPERTIES:
        {
            print_properties(g.getAvailableProperties());
            break;
        }
        case LIST_FORMATS:
        {
            list_formats(g.getAvailableVideoFormats());
            break;
        }
        case SET_PROPERTY:
        {
            set_property(g, param);
            break;
        }
        case SET_FORMAT:
        {
            set_active_format(g, param);
            break;
        }
        case SAVE_STREAM:
        {
            //save_stream(g, filename);
        }
        case SAVE_IMAGE:
        {
            save_image(g, filename);
            break;
        }
        default:
        {
            std::cout << "Unknown command." << std::endl;
            break;
        }
    }

    return 0;
}
<|endoftext|>


<commit_before>/* ---------------------------------------------------------------------------
** This software is in the public domain, furnished "as is", without technical
** support, and with no warranty, express or implied, as to its usefulness for
** any purpose.
**
** rtspvideocapturer.cpp
**
** -------------------------------------------------------------------------*/

#ifdef HAVE_LIVE555

#include "webrtc/base/timeutils.h"
#include "webrtc/base/logging.h"
#include "webrtc/base/optional.h"

#include "webrtc/common_video/h264/sps_parser.h"
#include "webrtc/common_video/h264/h264_common.h"
#include "webrtc/modules/video_coding/h264_sprop_parameter_sets.h"

#include "rtspvideocapturer.h"

uint8_t marker[] = { 0, 0, 0, 1};

RTSPVideoCapturer::RTSPVideoCapturer(const std::string & uri, int timeout, bool rtpovertcp) : m_connection(m_env, this, uri.c_str(), timeout, rtpovertcp, 1)
{
	LOG(INFO) << "RTSPVideoCapturer" << uri ;
}

bool RTSPVideoCapturer::onNewSession(const char* id,const char* media, const char* codec, const char* sdp)
{
	LOG(INFO) << "RTSPVideoCapturer::onNewSession" << media << "/" << codec << " " << sdp;
	bool success = false;
	if ( (strcmp(media, "video") == 0) && (strcmp(codec, "H264") == 0) )
	{
		const char* pattern="sprop-parameter-sets=";
		const char* sprop=strstr(sdp, pattern);
		if (sprop)
		{
			std::string sdpstr(sprop+strlen(pattern));
			size_t pos = sdpstr.find_first_of(" \r\n");
			if (pos != std::string::npos)
			{
				sdpstr.erase(pos);
			}
			webrtc::H264SpropParameterSets sprops;
			if (sprops.DecodeSprop(sdpstr))
			{
				struct timeval presentationTime;
				timerclear(&presentationTime);

				std::vector<uint8_t> sps;
				sps.insert(sps.end(), marker, marker+sizeof(marker));
				sps.insert(sps.end(), sprops.sps_nalu().begin(), sprops.sps_nalu().end());
				onData(id, sps.data(), sps.size(), presentationTime);

				std::vector<uint8_t> pps;
				pps.insert(pps.end(), marker, marker+sizeof(marker));
				pps.insert(pps.end(), sprops.pps_nalu().begin(), sprops.pps_nalu().end());
				onData(id, pps.data(), pps.size(), presentationTime);
			}
			else
			{
				LOG(WARNING) << "Cannot decode SPS:" << sprop;
			}
		}
		m_h264_id = id;
		success = true;
	}
	else if ( (strcmp(media, "audio") == 0) && (strcmp(codec, "L16") == 0) )
	{
		m_pcm_id = id;
		success = true;
	}
	return success;
}

bool RTSPVideoCapturer::onData(const char* id, unsigned char* buffer, ssize_t size, struct timeval presentationTime)
{
	LOG(INFO) << "RTSPVideoCapturer:onData size:" << size << " GetCaptureFormat:" << GetCaptureFormat();

	int res = 0;

	if (m_h264_id == id) {
		webrtc::H264::NaluType nalu_type = webrtc::H264::ParseNaluType(buffer[sizeof(marker)]);

		if (nalu_type == webrtc::H264::NaluType::kSps) {
			LOG(INFO) << "===========================SPS";
			m_cfg.clear();
			m_cfg.insert(m_cfg.end(), buffer, buffer+size);

			rtc::Optional<webrtc::SpsParser::SpsState> sps = webrtc::SpsParser::ParseSps(buffer+sizeof(marker)+webrtc::H264::kNaluTypeSize, size-sizeof(marker)-webrtc::H264::kNaluTypeSize);
			if (!sps)
			{
				LOG(LS_ERROR) << "cannot parse sps" << std::endl;
				res = -1;
			}
			else
			{
				if (m_decoder.get()) {
					if ( (GetCaptureFormat()->width != sps->width) || (GetCaptureFormat()->height != sps->height) )  {
						LOG(INFO) << "format changed => set format from " << GetCaptureFormat()->width << "x" << GetCaptureFormat()->height	 << " to " << sps->width << "x" << sps->height << std::endl;
						m_decoder.reset(NULL);
					}
				}

				if (!m_decoder.get()) {
					LOG(INFO) << "set format " << sps->width << "x" << sps->height << std::endl;
					cricket::VideoFormat videoFormat(sps->width, sps->height, cricket::VideoFormat::FpsToInterval(25), cricket::FOURCC_H264);
					SetCaptureFormat(&videoFormat);

					m_decoder.reset(m_factory.CreateVideoDecoder(webrtc::VideoCodecType::kVideoCodecH264));
					webrtc::VideoCodec codec_settings;
					codec_settings.codecType = webrtc::VideoCodecType::kVideoCodecH264;
					m_decoder->InitDecode(&codec_settings,2);
					m_decoder->RegisterDecodeCompleteCallback(this);
				}
			}
		}
		else if (nalu_type == webrtc::H264::NaluType::kPps) {
			LOG(INFO) << "===========================PPS";
			m_cfg.insert(m_cfg.end(), buffer, buffer+size);
		}
		else if (m_decoder.get()) {
			if (nalu_type == webrtc::H264::NaluType::kIdr) {
				LOG(INFO) << "===========================IDR";
				uint8_t buf[m_cfg.size() + size];
				memcpy(buf, m_cfg.data(), m_cfg.size());
				memcpy(buf+m_cfg.size(), buffer, size);
				webrtc::EncodedImage input_image(buf, sizeof(buf), sizeof(buf) + webrtc::EncodedImage::GetBufferPaddingBytes(webrtc::VideoCodecType::kVideoCodecH264));
				res = m_decoder->Decode(input_image, false, NULL);
			}
			else {
				LOG(INFO) << "===========================" << nalu_type;
				webrtc::EncodedImage input_image(buffer, size, size + webrtc::EncodedImage::GetBufferPaddingBytes(webrtc::VideoCodecType::kVideoCodecH264));
				res = m_decoder->Decode(input_image, false, NULL);
			}
		} else {
			LOG(LS_ERROR) << "===========================onData no decoder";
			res = -1;
		}
	} else if (m_pcm_id == id) {
	}

	return (res == 0);
}

ssize_t RTSPVideoCapturer::onNewBuffer(unsigned char* buffer, ssize_t size)
{
	ssize_t markerSize = 0;
	if (size > sizeof(marker))
	{
		memcpy( buffer, marker, sizeof(marker) );
		markerSize = sizeof(marker);
	}
	return 	markerSize;
}

int32_t RTSPVideoCapturer::Decoded(webrtc::VideoFrame& decodedImage)
{
	LOG(INFO) << "RTSPVideoCapturer::Decoded";

	this->OnFrame(decodedImage, decodedImage.height(), decodedImage.width());
	return true;
}

cricket::CaptureState RTSPVideoCapturer::Start(const cricket::VideoFormat& format)
{
	SetCaptureFormat(&format);
	SetCaptureState(cricket::CS_RUNNING);
	rtc::Thread::Start();
	return cricket::CS_RUNNING;
}

void RTSPVideoCapturer::Stop()
{
	m_env.stop();
	rtc::Thread::Stop();
	SetCaptureFormat(NULL);
	SetCaptureState(cricket::CS_STOPPED);
}

void RTSPVideoCapturer::Run()
{
	m_env.mainloop();
}

bool RTSPVideoCapturer::GetPreferredFourccs(std::vector<unsigned int>* fourccs)
{
	fourccs->push_back(cricket::FOURCC_H264);
	return true;
}
#endif
<commit_msg>m_h264_id should be set before calling onData<commit_after>/* ---------------------------------------------------------------------------
** This software is in the public domain, furnished "as is", without technical
** support, and with no warranty, express or implied, as to its usefulness for
** any purpose.
**
** rtspvideocapturer.cpp
**
** -------------------------------------------------------------------------*/

#ifdef HAVE_LIVE555

#include "webrtc/base/timeutils.h"
#include "webrtc/base/logging.h"
#include "webrtc/base/optional.h"

#include "webrtc/common_video/h264/sps_parser.h"
#include "webrtc/common_video/h264/h264_common.h"
#include "webrtc/modules/video_coding/h264_sprop_parameter_sets.h"

#include "rtspvideocapturer.h"

uint8_t marker[] = { 0, 0, 0, 1};

RTSPVideoCapturer::RTSPVideoCapturer(const std::string & uri, int timeout, bool rtpovertcp) : m_connection(m_env, this, uri.c_str(), timeout, rtpovertcp, 1)
{
	LOG(INFO) << "RTSPVideoCapturer" << uri ;
}

bool RTSPVideoCapturer::onNewSession(const char* id,const char* media, const char* codec, const char* sdp)
{
	LOG(INFO) << "RTSPVideoCapturer::onNewSession" << media << "/" << codec << " " << sdp;
	bool success = false;
	if ( (strcmp(media, "video") == 0) && (strcmp(codec, "H264") == 0) )
	{
		m_h264_id = id;
		const char* pattern="sprop-parameter-sets=";
		const char* sprop=strstr(sdp, pattern);
		if (sprop)
		{
			std::string sdpstr(sprop+strlen(pattern));
			size_t pos = sdpstr.find_first_of(" \r\n");
			if (pos != std::string::npos)
			{
				sdpstr.erase(pos);
			}
			webrtc::H264SpropParameterSets sprops;
			if (sprops.DecodeSprop(sdpstr))
			{
				struct timeval presentationTime;
				timerclear(&presentationTime);

				std::vector<uint8_t> sps;
				sps.insert(sps.end(), marker, marker+sizeof(marker));
				sps.insert(sps.end(), sprops.sps_nalu().begin(), sprops.sps_nalu().end());
				onData(id, sps.data(), sps.size(), presentationTime);

				std::vector<uint8_t> pps;
				pps.insert(pps.end(), marker, marker+sizeof(marker));
				pps.insert(pps.end(), sprops.pps_nalu().begin(), sprops.pps_nalu().end());
				onData(id, pps.data(), pps.size(), presentationTime);
			}
			else
			{
				LOG(WARNING) << "Cannot decode SPS:" << sprop;
			}
		}
		success = true;
	}
	else if ( (strcmp(media, "audio") == 0) && (strcmp(codec, "L16") == 0) )
	{
		m_pcm_id = id;
		success = true;
	}
	return success;
}

bool RTSPVideoCapturer::onData(const char* id, unsigned char* buffer, ssize_t size, struct timeval presentationTime)
{
	LOG(INFO) << "RTSPVideoCapturer:onData size:" << size << " GetCaptureFormat:" << GetCaptureFormat();

	int res = 0;

	if (m_h264_id == id) {
		webrtc::H264::NaluType nalu_type = webrtc::H264::ParseNaluType(buffer[sizeof(marker)]);

		if (nalu_type == webrtc::H264::NaluType::kSps) {
			LOG(INFO) << "===========================SPS";
			m_cfg.clear();
			m_cfg.insert(m_cfg.end(), buffer, buffer+size);

			rtc::Optional<webrtc::SpsParser::SpsState> sps = webrtc::SpsParser::ParseSps(buffer+sizeof(marker)+webrtc::H264::kNaluTypeSize, size-sizeof(marker)-webrtc::H264::kNaluTypeSize);
			if (!sps)
			{
				LOG(LS_ERROR) << "cannot parse sps" << std::endl;
				res = -1;
			}
			else
			{
				if (m_decoder.get()) {
					if ( (GetCaptureFormat()->width != sps->width) || (GetCaptureFormat()->height != sps->height) )  {
						LOG(INFO) << "format changed => set format from " << GetCaptureFormat()->width << "x" << GetCaptureFormat()->height	 << " to " << sps->width << "x" << sps->height << std::endl;
						m_decoder.reset(NULL);
					}
				}

				if (!m_decoder.get()) {
					LOG(INFO) << "set format " << sps->width << "x" << sps->height << std::endl;
					cricket::VideoFormat videoFormat(sps->width, sps->height, cricket::VideoFormat::FpsToInterval(25), cricket::FOURCC_H264);
					SetCaptureFormat(&videoFormat);

					m_decoder.reset(m_factory.CreateVideoDecoder(webrtc::VideoCodecType::kVideoCodecH264));
					webrtc::VideoCodec codec_settings;
					codec_settings.codecType = webrtc::VideoCodecType::kVideoCodecH264;
					m_decoder->InitDecode(&codec_settings,2);
					m_decoder->RegisterDecodeCompleteCallback(this);
				}
			}
		}
		else if (nalu_type == webrtc::H264::NaluType::kPps) {
			LOG(INFO) << "===========================PPS";
			m_cfg.insert(m_cfg.end(), buffer, buffer+size);
		}
		else if (m_decoder.get()) {
			if (nalu_type == webrtc::H264::NaluType::kIdr) {
				LOG(INFO) << "===========================IDR";
				uint8_t buf[m_cfg.size() + size];
				memcpy(buf, m_cfg.data(), m_cfg.size());
				memcpy(buf+m_cfg.size(), buffer, size);
				webrtc::EncodedImage input_image(buf, sizeof(buf), sizeof(buf) + webrtc::EncodedImage::GetBufferPaddingBytes(webrtc::VideoCodecType::kVideoCodecH264));
				res = m_decoder->Decode(input_image, false, NULL);
			}
			else {
				LOG(INFO) << "===========================" << nalu_type;
				webrtc::EncodedImage input_image(buffer, size, size + webrtc::EncodedImage::GetBufferPaddingBytes(webrtc::VideoCodecType::kVideoCodecH264));
				res = m_decoder->Decode(input_image, false, NULL);
			}
		} else {
			LOG(LS_ERROR) << "===========================onData no decoder";
			res = -1;
		}
	} else if (m_pcm_id == id) {
	}

	return (res == 0);
}

ssize_t RTSPVideoCapturer::onNewBuffer(unsigned char* buffer, ssize_t size)
{
	ssize_t markerSize = 0;
	if (size > sizeof(marker))
	{
		memcpy( buffer, marker, sizeof(marker) );
		markerSize = sizeof(marker);
	}
	return 	markerSize;
}

int32_t RTSPVideoCapturer::Decoded(webrtc::VideoFrame& decodedImage)
{
	LOG(INFO) << "RTSPVideoCapturer::Decoded";

	this->OnFrame(decodedImage, decodedImage.height(), decodedImage.width());
	return true;
}

cricket::CaptureState RTSPVideoCapturer::Start(const cricket::VideoFormat& format)
{
	SetCaptureFormat(&format);
	SetCaptureState(cricket::CS_RUNNING);
	rtc::Thread::Start();
	return cricket::CS_RUNNING;
}

void RTSPVideoCapturer::Stop()
{
	m_env.stop();
	rtc::Thread::Stop();
	SetCaptureFormat(NULL);
	SetCaptureState(cricket::CS_STOPPED);
}

void RTSPVideoCapturer::Run()
{
	m_env.mainloop();
}

bool RTSPVideoCapturer::GetPreferredFourccs(std::vector<unsigned int>* fourccs)
{
	fourccs->push_back(cricket::FOURCC_H264);
	return true;
}
#endif
<|endoftext|>


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

#include <string.hxx>
#include <winshell.hxx>

void * NewBinaryFromString( const String & rBinStr );
String CreateStringFromData( const void *pData, ULONG nBytes );

String CreateStringFromItemIDList( const CItemIDList & rIDList );

String GetURLFromHostNotation( const String & rPath );
String GetHostNotationFromURL( const String & rURL );

CItemIDList MakeIDToken( const String &rToken );
CItemIDList ParseSpecialURL( const String & rURL );

#endif // _PARSER_HXX
<commit_msg>INTEGRATION: CWS warnings01 (1.2.8); FILE MERGED 2006/02/24 14:49:17 sb 1.2.8.1: #i53898# Made code warning-free; removed dead code.<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: parser.hxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: hr $ $Date: 2006-06-19 13:55:30 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/
#ifndef _PARSER_HXX
#define _PARSER_HXX

#if defined WNT

#include <string.hxx>
#include <winshell.hxx>

void * NewBinaryFromString( const String & rBinStr );
String CreateStringFromData( const void *pData, ULONG nBytes );

String CreateStringFromItemIDList( const CItemIDList & rIDList );

String GetURLFromHostNotation( const String & rPath );
String GetHostNotationFromURL( const String & rURL );

CItemIDList MakeIDToken( const String &rToken );
CItemIDList ParseSpecialURL( const String & rURL );

#endif

#endif // _PARSER_HXX
<|endoftext|>


<commit_before>#include <catch.hpp>
#include <iostream>
#include <initializer_list>

#include "src/mbedtls_config.h"
#include "mbedcrypto/cipher.hpp"
#include "generator.hpp"

///////////////////////////////////////////////////////////////////////////////
namespace {
using cchars = const char*;
using namespace mbedcrypto;
///////////////////////////////////////////////////////////////////////////////
auto hasHash = [](hash_t h) {
    REQUIRE( supports(h) );
    cchars name = to_string(h);

    REQUIRE( supports_hash(name) );
    auto v = from_string<hash_t>(name);
    REQUIRE( v == h );
};

///////////////////////////////////////////////////////////////////////////////
} // namespace anon
///////////////////////////////////////////////////////////////////////////////
TEST_CASE("mbedcrypto types checkings", "[types]") {
    using namespace mbedcrypto;

    SECTION("list installed algorithms") {
        auto hashes = installed_hashes();
        REQUIRE( hashes.size() > 0 );
        std::cout << "\nsupported hash algorithms: ";
        for ( auto h : hashes ) {
            std::cout << to_string(h) << " , ";
        }

        auto ciphers = installed_ciphers();
        REQUIRE( ciphers.size() > 0 );
        std::cout << "\nsupported cipher algorithms: ";
        for ( auto c : ciphers ) {
            std::cout << to_string(c) << " , ";
        }
        std::cout << "\nthis system "
            << (cipher::supports_aes_ni() ? "supports" : "does not support")
            << " AESNI (hardware accelerated AES)";

        auto paddings = installed_paddings();
        REQUIRE( paddings.size() > 0 );
        std::cout << "\nsupported padding algorithms: ";
        for ( auto p : paddings ) {
            std::cout << to_string(p) << " , ";
        }
        std::cout << std::endl;
    }

    SECTION("hashes") {
        REQUIRE_FALSE( supports(hash_t::none) );

        #if defined(MBEDTLS_MD2_C)
        hasHash(hash_t::md2);
        #else
        REQUIRE_FALSE( supports(hash_t::md2) );
        #endif

        #if defined(MBEDTLS_MD4_C)
        hasHash(hash_t::md4);
        #else // MBEDTLS_MD4_C
        REQUIRE_FALSE( supports(hash_t::md4) );
        #endif // MBEDTLS_MD4_C

        #if defined(MBEDTLS_MD5_C)
        hasHash(hash_t::md5);
        #else // MBEDTLS_MD5_C
        REQUIRE_FALSE( supports(hash_t::md5) );
        #endif // MBEDTLS_MD5_C

        #if defined(MBEDTLS_SHA1_C)
        hasHash(hash_t::sha1);
        #else // MBEDTLS_SHA1_C
        REQUIRE_FALSE( supports(hash_t::sha1) );
        #endif // MBEDTLS_SHA1_C

        #if defined(MBEDTLS_SHA256_C)
        hasHash(hash_t::sha224);
        hasHash(hash_t::sha256);
        #else // MBEDTLS_SHA256_C
        REQUIRE_FALSE( supports(hash_t::sha224) );
        REQUIRE_FALSE( supports(hash_t::sha256) );
        #endif // MBEDTLS_SHA256_C

        #if defined(MBEDTLS_SHA512_C)
        hasHash(hash_t::sha384);
        hasHash(hash_t::sha512);
        #else // MBEDTLS_SHA512_C
        REQUIRE_FALSE( supports(hash_t::sha384) );
        REQUIRE_FALSE( supports(hash_t::sha512) );
        #endif // MBEDTLS_SHA512_C

        #if defined(MBEDTLS_RIPEMD160_C)
        hasHash(hash_t::ripemd160);
        #else // MBEDTLS_RIPEMD160_C
        REQUIRE_FALSE( supports(hash_t::ripemd160) );
        #endif // MBEDTLS_RIPEMD160_C

        std::cout << std::endl;

    }

    SECTION("ciphers") {
        const std::initializer_list<cipher_t> Items = {
            cipher_t::none,
            cipher_t::null,
            cipher_t::aes_128_ecb,
            cipher_t::aes_192_ecb,
            cipher_t::aes_256_ecb,
            cipher_t::aes_128_cbc,
            cipher_t::aes_192_cbc,
            cipher_t::aes_256_cbc,
            cipher_t::aes_128_cfb128,
            cipher_t::aes_192_cfb128,
            cipher_t::aes_256_cfb128,
            cipher_t::aes_128_ctr,
            cipher_t::aes_192_ctr,
            cipher_t::aes_256_ctr,
            cipher_t::aes_128_gcm,
            cipher_t::aes_192_gcm,
            cipher_t::aes_256_gcm,
            cipher_t::camellia_128_ecb,
            cipher_t::camellia_192_ecb,
            cipher_t::camellia_256_ecb,
            cipher_t::camellia_128_cbc,
            cipher_t::camellia_192_cbc,
            cipher_t::camellia_256_cbc,
            cipher_t::camellia_128_cfb128,
            cipher_t::camellia_192_cfb128,
            cipher_t::camellia_256_cfb128,
            cipher_t::camellia_128_ctr,
            cipher_t::camellia_192_ctr,
            cipher_t::camellia_256_ctr,
            cipher_t::camellia_128_gcm,
            cipher_t::camellia_192_gcm,
            cipher_t::camellia_256_gcm,
            cipher_t::des_ecb,
            cipher_t::des_cbc,
            cipher_t::des_ede_ecb,
            cipher_t::des_ede_cbc,
            cipher_t::des_ede3_ecb,
            cipher_t::des_ede3_cbc,
            cipher_t::blowfish_ecb,
            cipher_t::blowfish_cbc,
            cipher_t::blowfish_cfb64,
            cipher_t::blowfish_ctr,
            cipher_t::arc4_128,
            cipher_t::aes_128_ccm,
            cipher_t::aes_192_ccm,
            cipher_t::aes_256_ccm,
            cipher_t::camellia_128_ccm,
            cipher_t::camellia_192_ccm,
            cipher_t::camellia_256_ccm,
        };

        for ( auto i : Items ) {
            cchars name = to_string(i);
            if ( name == nullptr )
                continue;

            auto v = from_string<cipher_t>(name);
            REQUIRE( v == i );
        }
    }

    SECTION("paddings") {
        const std::initializer_list<padding_t> Items = {
            padding_t::none,
            padding_t::pkcs7,
            padding_t::one_and_zeros,
            padding_t::zeros_and_len,
            padding_t::zeros,
        };

        for ( auto i : Items ) {
            cchars name = to_string(i);
            if ( name == nullptr )
                continue;

            auto v = from_string<padding_t>(name);
            REQUIRE( v == i );
        }
    }

}

<commit_msg>tests/tdd: report count of installed algorithms<commit_after>#include <catch.hpp>
#include <iostream>
#include <initializer_list>

#include "src/mbedtls_config.h"
#include "mbedcrypto/cipher.hpp"
#include "generator.hpp"

///////////////////////////////////////////////////////////////////////////////
namespace {
using cchars = const char*;
using namespace mbedcrypto;
///////////////////////////////////////////////////////////////////////////////
auto hasHash = [](hash_t h) {
    REQUIRE( supports(h) );
    cchars name = to_string(h);

    REQUIRE( supports_hash(name) );
    auto v = from_string<hash_t>(name);
    REQUIRE( v == h );
};

///////////////////////////////////////////////////////////////////////////////
} // namespace anon
///////////////////////////////////////////////////////////////////////////////
TEST_CASE("mbedcrypto types checkings", "[types]") {
    using namespace mbedcrypto;

    SECTION("list installed algorithms") {
        auto hashes = installed_hashes();
        REQUIRE( hashes.size() > 0 );
        std::cout << "\nsupports " << hashes.size() << " hash algorithms: ";
        for ( auto h : hashes ) {
            std::cout << to_string(h) << " , ";
        }

        auto paddings = installed_paddings();
        REQUIRE( paddings.size() > 0 );
        std::cout << "\nsupports " << paddings.size() << " padding algorithms: ";
        for ( auto p : paddings ) {
            std::cout << to_string(p) << " , ";
        }

        auto ciphers = installed_ciphers();
        REQUIRE( ciphers.size() > 0 );
        std::cout << "\nsupports " << ciphers.size() << " cipher algorithms: ";
        for ( auto c : ciphers ) {
            std::cout << to_string(c) << " , ";
        }
        std::cout << "\nthis system "
            << (cipher::supports_aes_ni() ? "supports" : "does not support")
            << " AESNI (hardware accelerated AES)";

        std::cout << std::endl;
    }

    SECTION("hashes") {
        REQUIRE_FALSE( supports(hash_t::none) );

        #if defined(MBEDTLS_MD2_C)
        hasHash(hash_t::md2);
        #else
        REQUIRE_FALSE( supports(hash_t::md2) );
        #endif

        #if defined(MBEDTLS_MD4_C)
        hasHash(hash_t::md4);
        #else // MBEDTLS_MD4_C
        REQUIRE_FALSE( supports(hash_t::md4) );
        #endif // MBEDTLS_MD4_C

        #if defined(MBEDTLS_MD5_C)
        hasHash(hash_t::md5);
        #else // MBEDTLS_MD5_C
        REQUIRE_FALSE( supports(hash_t::md5) );
        #endif // MBEDTLS_MD5_C

        #if defined(MBEDTLS_SHA1_C)
        hasHash(hash_t::sha1);
        #else // MBEDTLS_SHA1_C
        REQUIRE_FALSE( supports(hash_t::sha1) );
        #endif // MBEDTLS_SHA1_C

        #if defined(MBEDTLS_SHA256_C)
        hasHash(hash_t::sha224);
        hasHash(hash_t::sha256);
        #else // MBEDTLS_SHA256_C
        REQUIRE_FALSE( supports(hash_t::sha224) );
        REQUIRE_FALSE( supports(hash_t::sha256) );
        #endif // MBEDTLS_SHA256_C

        #if defined(MBEDTLS_SHA512_C)
        hasHash(hash_t::sha384);
        hasHash(hash_t::sha512);
        #else // MBEDTLS_SHA512_C
        REQUIRE_FALSE( supports(hash_t::sha384) );
        REQUIRE_FALSE( supports(hash_t::sha512) );
        #endif // MBEDTLS_SHA512_C

        #if defined(MBEDTLS_RIPEMD160_C)
        hasHash(hash_t::ripemd160);
        #else // MBEDTLS_RIPEMD160_C
        REQUIRE_FALSE( supports(hash_t::ripemd160) );
        #endif // MBEDTLS_RIPEMD160_C

        std::cout << std::endl;

    }

    SECTION("ciphers") {
        const std::initializer_list<cipher_t> Items = {
            cipher_t::none,
            cipher_t::null,
            cipher_t::aes_128_ecb,
            cipher_t::aes_192_ecb,
            cipher_t::aes_256_ecb,
            cipher_t::aes_128_cbc,
            cipher_t::aes_192_cbc,
            cipher_t::aes_256_cbc,
            cipher_t::aes_128_cfb128,
            cipher_t::aes_192_cfb128,
            cipher_t::aes_256_cfb128,
            cipher_t::aes_128_ctr,
            cipher_t::aes_192_ctr,
            cipher_t::aes_256_ctr,
            cipher_t::aes_128_gcm,
            cipher_t::aes_192_gcm,
            cipher_t::aes_256_gcm,
            cipher_t::camellia_128_ecb,
            cipher_t::camellia_192_ecb,
            cipher_t::camellia_256_ecb,
            cipher_t::camellia_128_cbc,
            cipher_t::camellia_192_cbc,
            cipher_t::camellia_256_cbc,
            cipher_t::camellia_128_cfb128,
            cipher_t::camellia_192_cfb128,
            cipher_t::camellia_256_cfb128,
            cipher_t::camellia_128_ctr,
            cipher_t::camellia_192_ctr,
            cipher_t::camellia_256_ctr,
            cipher_t::camellia_128_gcm,
            cipher_t::camellia_192_gcm,
            cipher_t::camellia_256_gcm,
            cipher_t::des_ecb,
            cipher_t::des_cbc,
            cipher_t::des_ede_ecb,
            cipher_t::des_ede_cbc,
            cipher_t::des_ede3_ecb,
            cipher_t::des_ede3_cbc,
            cipher_t::blowfish_ecb,
            cipher_t::blowfish_cbc,
            cipher_t::blowfish_cfb64,
            cipher_t::blowfish_ctr,
            cipher_t::arc4_128,
            cipher_t::aes_128_ccm,
            cipher_t::aes_192_ccm,
            cipher_t::aes_256_ccm,
            cipher_t::camellia_128_ccm,
            cipher_t::camellia_192_ccm,
            cipher_t::camellia_256_ccm,
        };

        for ( auto i : Items ) {
            cchars name = to_string(i);
            if ( name == nullptr )
                continue;

            auto v = from_string<cipher_t>(name);
            REQUIRE( v == i );
        }
    }

    SECTION("paddings") {
        const std::initializer_list<padding_t> Items = {
            padding_t::none,
            padding_t::pkcs7,
            padding_t::one_and_zeros,
            padding_t::zeros_and_len,
            padding_t::zeros,
        };

        for ( auto i : Items ) {
            cchars name = to_string(i);
            if ( name == nullptr )
                continue;

            auto v = from_string<padding_t>(name);
            REQUIRE( v == i );
        }
    }

}

<|endoftext|>


<commit_before><commit_msg>Crowdin: Sketcher/App/SketchObject.cpp elaborated term in string<commit_after><|endoftext|>


<commit_before>/*
 * Copyright 2006-2008 The FLWOR Foundation.
 *
 * 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.
 */
#include "runtime/rest/rest.h"

#include <curl/curl.h>

#include "runtime/util/iterator_impl.h"
#include "runtime/api/runtimecb.h"
#include "runtime/api/plan_wrapper.h"
#include "runtime/api/plan_iterator_wrapper.h"

#include "store/api/iterator.h"
#include "store/api/item_factory.h"
#include "store/api/store.h"
#include "store/naive/node_items.h"
#include "store/api/copymode.h"
#include "types/root_typemanager.h"
#include "context/static_context.h"
#include "context/namespace_context.h"

#include "zorbatypes/numconversions.h"
#include "zorbatypes/datetime/parse.h"
#include "system/globalenv.h"
#include "zorbaerrors/error_manager.h"

namespace zorba {

/****************************************************************************
 *
 * CurlStreamBuffer
 *
 ****************************************************************************/

CurlStreamBuffer::CurlStreamBuffer(CURLM* aMultiHandle, CURL* aEasyHandle)
  : std::streambuf(), MultiHandle(aMultiHandle), EasyHandle(aEasyHandle)
{
  CurlErrorBuffer = new char[CURLOPT_ERRORBUFFER];
  CurlErrorBuffer[0] = 0;

  curl_easy_setopt(EasyHandle, CURLOPT_ERRORBUFFER, CurlErrorBuffer);
  curl_easy_setopt(EasyHandle, CURLOPT_WRITEDATA, this);
  curl_easy_setopt(EasyHandle, CURLOPT_WRITEFUNCTION, CurlStreamBuffer::write_callback);
  curl_easy_setopt(EasyHandle, CURLOPT_BUFFERSIZE, INITIAL_BUFFER_SIZE);
}

int CurlStreamBuffer::multi_perform()
{
  CURLMsg* msg;
  int MsgsInQueue;
  int StillRunning = 0;
  bool done = false;
  int error = 0;

  while (!done)
  {
    while (CURLM_CALL_MULTI_PERFORM == curl_multi_perform(MultiHandle, &StillRunning))
      ;

    while ((msg = curl_multi_info_read(MultiHandle, &MsgsInQueue)))
      if (msg->msg == CURLMSG_DONE)
      {
        error = msg->data.result;
        done = true;
      }
  }

  // TODO: return message, too ?
  //if (error)
  //  std::cout << "error: [" << CurlErrorBuffer << "]" << std::endl;

  return error;
}

CurlStreamBuffer::~CurlStreamBuffer()
{
  delete[] CurlErrorBuffer;
  CurlErrorBuffer = NULL;
  free(eback());
}

size_t CurlStreamBuffer::write_callback(char* buffer, size_t size, size_t nitems, void* userp)
{
  CurlStreamBuffer* sbuffer = static_cast<CurlStreamBuffer*>(userp);
  size_t result = sbuffer->sputn(buffer, size*nitems);
  sbuffer->setg(sbuffer->eback(), sbuffer->gptr(), sbuffer->pptr());
  return result;
}

int CurlStreamBuffer::overflow(int c)
{
  char* _out_cur = pptr();
  char* _in_cur = gptr();
  char* _in_beg = eback();

  int new_size = 2 * (epptr() - _in_beg);
  if (new_size == 0)
    new_size = INITIAL_BUFFER_SIZE;

  char* new_buffer = (char*)realloc(_in_beg, new_size);

  if (new_buffer != _in_beg)
  {
    _out_cur = new_buffer + (pptr() - pbase());
    _in_cur = new_buffer + (_in_cur - _in_beg);
    _in_beg = new_buffer;
  }
  setp(_out_cur, new_buffer + new_size);
  sputc(c);
  setg(_in_beg, _in_cur, pptr());

  return 0;
}

int CurlStreamBuffer::underflow()
{
  // TODO: place a call to multi_perform() ?
  return EOF;
}

/****************************************************************************
 *
 * ChildrenIterator
 *
 ****************************************************************************/

void ChildrenIteratorState::init(PlanState& planState)
{
  PlanIteratorState::init(planState);
}

void ChildrenIteratorState::reset(PlanState& planState)
{
  PlanIteratorState::reset(planState);
}

bool
ChildrenIterator::nextImpl(store::Item_t& result, PlanState& planState) const
{
  ChildrenIteratorState* state;
  DEFAULT_STACK_INIT(ChildrenIteratorState, state, planState);

  state->index = 0;
  while(state->index < children.size())
  {
    result = children[state->index];
    STACK_PUSH(true, state);
    state->index++;
  }

  STACK_END (state);
}

/****************************************************************************
 *
 * rest-get Iterator
 *
 ****************************************************************************/

ZorbaRestGetIteratorState::ZorbaRestGetIteratorState()
{
}

ZorbaRestGetIteratorState::~ZorbaRestGetIteratorState()
{
}

void
ZorbaRestGetIteratorState::init(PlanState& planState)
{
  PlanIteratorState::init(planState);
}

void
ZorbaRestGetIteratorState::reset(PlanState& planState)
{
  PlanIteratorState::reset(planState);
}

bool ZorbaRestGetIterator::createResultNode(store::Item_t& result, PlanState& planState, xqpString name, ChildrenIterator_t children) const
{
  xqpString ns = "http://www.flworfound.org/rest";
  xqpString pre = "zorba-rest";
  store::Item_t qname;

  GENV_ITEMFACTORY->createQName(qname, ns.getStore(), pre.getStore(), name.getStore());
  xqpStringStore_t baseUri = planState.theRuntimeCB->theStaticContext->final_baseuri().getStore();
  store::NsBindings bindings;
  store::CopyMode copymode;

  std::auto_ptr<store::Iterator> cwrapper;
  if (children != NULL)
    cwrapper.reset(new PlanWrapper(children.getp(), planState.theCompilerCB, planState.dctx()));

  return GENV_ITEMFACTORY->createElementNode(result, (ulong)&planState,
    qname,
    GENV_TYPESYSTEM.XS_UNTYPED_QNAME,
    cwrapper.get(),
    NULL,
    NULL,
    bindings,
    baseUri,
    true,
    true,
    false,
    copymode);
}

bool ZorbaRestGetIterator::createResultNode(store::Item_t& result, PlanState& planState, xqpString name, const QueryLoc& loc, store::Item_t child) const
{
  ChildrenIterator_t childIterator;
  childIterator = new ChildrenIterator(loc, child);
  return createResultNode(result, planState, name, childIterator);
}

bool ZorbaRestGetIterator::createResultNode(store::Item_t& result, PlanState& planState, xqpString name, const QueryLoc& loc, store::Item_t child1, store::Item_t child2) const
{
  ChildrenIterator_t childIterator;
  childIterator = new ChildrenIterator(loc, child1, child2);
  return createResultNode(result, planState, name, childIterator);
}

bool
ZorbaRestGetIterator::nextImpl(store::Item_t& result, PlanState& planState) const
{
  store::Item_t lUri;
  xqpStringStore_t lUriString;
  int code;
  store::Item_t doc = NULL;
  store::Store& store = GENV.getStore();

  ZorbaRestGetIteratorState* state;
  bool valid = false;
  DEFAULT_STACK_INIT(ZorbaRestGetIteratorState, state, planState);

  /********* Initialization ***********************/
  curl_global_init(CURL_GLOBAL_ALL); // TODO: once per application, needs to be moved somewhere else
  state->MultiHandle = curl_multi_init(); // TODO check error
  state->EasyHandle = curl_easy_init();
  state->theStreamBuffer = NULL;
  state->headers = NULL;
  curl_easy_setopt(state->EasyHandle, CURLOPT_HTTPGET, 1);
  curl_easy_setopt(state->EasyHandle, CURLOPT_USERAGENT, "libcurl-agent/1.0");
  curl_easy_setopt(state->EasyHandle, CURLOPT_HEADERFUNCTION, ZorbaRestGetIterator::getHeaderData);
  curl_easy_setopt(state->EasyHandle, CURLOPT_WRITEHEADER, state);
  curl_multi_add_handle(state->MultiHandle, state->EasyHandle);

  if (!CONSUME(lUri, 0)) {
    // todo raise an error
  }

  lUriString = lUri->getStringValue();
  curl_easy_setopt(state->EasyHandle, CURLOPT_URL, lUriString->c_str());

  if (state->theStreamBuffer == 0)
  {
    state->theStreamBuffer = new CurlStreamBuffer(state->MultiHandle, state->EasyHandle);
    state->headers = new std::vector<std::string>();
  }

  code = state->theStreamBuffer->multi_perform();

  /********* Process the reply **********************/
  {
    int result_code;
    if (state->headers->size() == 0)
    {
      result_code = code; // TODO change cURL's error code to something else?
    }
    else if (parse_int_const_position<int>(state->headers->operator[](0), 9, result_code, 1))
    {
      result_code = -1; // TODO change this code
    }

    xqpString temp = NumConversions::intToStr(result_code);
    store::Item_t text_code;
    GENV_ITEMFACTORY->createTextNode(text_code, (ulong)&planState, temp.theStrStore, false, true);
    store::Item_t status_code;
    createResultNode(status_code, planState, "status_code", loc, text_code);

    std::istream is(state->theStreamBuffer);
    try {
      doc = store.loadDocument(lUriString, is);
    }
    catch (...) {
      doc = NULL;
    }

    if (doc != NULL)
    {
      store::Iterator_t children = doc->getChildren();
      children->open();
      store::Item_t child;
      children->next(child);
      store::Item_t payload;
      createResultNode(payload, planState, "payload", loc, child); // TODO: check NULL

      valid = createResultNode(result, planState, "result", loc, status_code, payload);
    }
    else
    {
      valid = createResultNode(result, planState, "result", loc, status_code);
    }
  }

  STACK_PUSH(valid, state);

  /********* Deinitialization ***********************/
  curl_multi_remove_handle(state->MultiHandle, state->EasyHandle);
  curl_easy_cleanup(state->EasyHandle);
  curl_multi_cleanup(state->MultiHandle);
  curl_global_cleanup();
  delete state->theStreamBuffer;
  delete state->headers;

  STACK_END (state);
}

size_t
ZorbaRestGetIterator::getHeaderData(void *ptr, size_t size, size_t nmemb, void *aState)
{
  ZorbaRestGetIteratorState* state = static_cast<ZorbaRestGetIteratorState*>(aState);

  std::string temp(static_cast<char*>(ptr), size*nmemb-1);
  state->headers->push_back(temp);
  // std::cout << "header: " << temp << std::endl;

  return size * nmemb;
}

} /* namespace zorba */
<commit_msg>Fix the REST for windows.<commit_after>/*
 * Copyright 2006-2008 The FLWOR Foundation.
 *
 * 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.
 */
#include "runtime/rest/rest.h"

#include <curl/curl.h>

#include "runtime/util/iterator_impl.h"
#include "runtime/api/runtimecb.h"
#include "runtime/api/plan_wrapper.h"
#include "runtime/api/plan_iterator_wrapper.h"

#include "store/api/iterator.h"
#include "store/api/item_factory.h"
#include "store/api/store.h"
#include "store/naive/node_items.h"
#include "store/api/copymode.h"
#include "types/root_typemanager.h"
#include "context/static_context.h"
#include "context/namespace_context.h"

#include "zorbatypes/numconversions.h"
#include "zorbatypes/datetime/parse.h"
#include "system/globalenv.h"
#include "zorbaerrors/error_manager.h"

#include <iostream>
#include <fstream>
using namespace std;

namespace zorba {

/****************************************************************************
 *
 * CurlStreamBuffer
 *
 ****************************************************************************/

CurlStreamBuffer::CurlStreamBuffer(CURLM* aMultiHandle, CURL* aEasyHandle)
  : std::streambuf(), MultiHandle(aMultiHandle), EasyHandle(aEasyHandle)
{
  CurlErrorBuffer = new char[CURLOPT_ERRORBUFFER];
  CurlErrorBuffer[0] = 0;

  curl_easy_setopt(EasyHandle, CURLOPT_ERRORBUFFER, CurlErrorBuffer);
  curl_easy_setopt(EasyHandle, CURLOPT_WRITEDATA, this);
  curl_easy_setopt(EasyHandle, CURLOPT_WRITEFUNCTION, CurlStreamBuffer::write_callback);
  curl_easy_setopt(EasyHandle, CURLOPT_BUFFERSIZE, INITIAL_BUFFER_SIZE);
}

int CurlStreamBuffer::multi_perform()
{
  CURLMsg* msg;
  int MsgsInQueue;
  int StillRunning = 0;
  bool done = false;
  int error = 0;

  while (!done)
  {
    while (CURLM_CALL_MULTI_PERFORM == curl_multi_perform(MultiHandle, &StillRunning))
      ;

    while ((msg = curl_multi_info_read(MultiHandle, &MsgsInQueue)))
      if (msg->msg == CURLMSG_DONE)
      {
        error = msg->data.result;
        done = true;
      }
  }

  // TODO: return message, too ?
  //if (error)
  //  std::cout << "error: [" << CurlErrorBuffer << "]" << std::endl;

  return error;
}

CurlStreamBuffer::~CurlStreamBuffer()
{
  delete[] CurlErrorBuffer;
  CurlErrorBuffer = NULL;
  free(eback());
}

size_t CurlStreamBuffer::write_callback(char* buffer, size_t size, size_t nitems, void* userp)
{
  CurlStreamBuffer* sbuffer = static_cast<CurlStreamBuffer*>(userp);
  size_t result = sbuffer->sputn(buffer, size*nitems);
  sbuffer->setg(sbuffer->eback(), sbuffer->gptr(), sbuffer->pptr());
  return result;
}

int CurlStreamBuffer::overflow(int c)
{
  char* _pptr = pptr();
  char* _gptr = gptr();
  char* _eback = eback();

  int new_size = 2 * (epptr() - _eback);
  if (new_size == 0)
    new_size = INITIAL_BUFFER_SIZE;

  char* new_buffer = (char*)realloc(_eback, new_size);

  if (new_buffer != _eback)
  {
    _pptr = new_buffer + (_pptr - _eback);
    _gptr = new_buffer + (_gptr - _eback);
    _eback = new_buffer;
  }
  setp(_pptr, new_buffer + new_size);
  sputc(c);
  setg(_eback, _gptr, pptr());

  return 0;
}

int CurlStreamBuffer::underflow()
{
  // TODO: place a call to multi_perform() ?
  return EOF;
}

/****************************************************************************
 *
 * ChildrenIterator
 *
 ****************************************************************************/

void ChildrenIteratorState::init(PlanState& planState)
{
  PlanIteratorState::init(planState);
}

void ChildrenIteratorState::reset(PlanState& planState)
{
  PlanIteratorState::reset(planState);
}

bool
ChildrenIterator::nextImpl(store::Item_t& result, PlanState& planState) const
{
  ChildrenIteratorState* state;
  DEFAULT_STACK_INIT(ChildrenIteratorState, state, planState);

  state->index = 0;
  while(state->index < children.size())
  {
    result = children[state->index];
    STACK_PUSH(true, state);
    state->index++;
  }

  STACK_END (state);
}

/****************************************************************************
 *
 * rest-get Iterator
 *
 ****************************************************************************/

ZorbaRestGetIteratorState::ZorbaRestGetIteratorState()
{
}

ZorbaRestGetIteratorState::~ZorbaRestGetIteratorState()
{
}

void
ZorbaRestGetIteratorState::init(PlanState& planState)
{
  PlanIteratorState::init(planState);
}

void
ZorbaRestGetIteratorState::reset(PlanState& planState)
{
  PlanIteratorState::reset(planState);
}

bool ZorbaRestGetIterator::createResultNode(store::Item_t& result, PlanState& planState, xqpString name, ChildrenIterator_t children) const
{
  xqpString ns = "http://www.flworfound.org/rest";
  xqpString pre = "zorba-rest";
  store::Item_t qname;

  GENV_ITEMFACTORY->createQName(qname, ns.getStore(), pre.getStore(), name.getStore());
  xqpStringStore_t baseUri = planState.theRuntimeCB->theStaticContext->final_baseuri().getStore();
  store::NsBindings bindings;
  store::CopyMode copymode;

  std::auto_ptr<store::Iterator> cwrapper;
  if (children != NULL)
    cwrapper.reset(new PlanWrapper(children.getp(), planState.theCompilerCB, planState.dctx()));

  return GENV_ITEMFACTORY->createElementNode(result, (ulong)&planState,
    qname,
    GENV_TYPESYSTEM.XS_UNTYPED_QNAME,
    cwrapper.get(),
    NULL,
    NULL,
    bindings,
    baseUri,
    true,
    true,
    false,
    copymode);
}

bool ZorbaRestGetIterator::createResultNode(store::Item_t& result, PlanState& planState, xqpString name, const QueryLoc& loc, store::Item_t child) const
{
  ChildrenIterator_t childIterator;
  childIterator = new ChildrenIterator(loc, child);
  return createResultNode(result, planState, name, childIterator);
}

bool ZorbaRestGetIterator::createResultNode(store::Item_t& result, PlanState& planState, xqpString name, const QueryLoc& loc, store::Item_t child1, store::Item_t child2) const
{
  ChildrenIterator_t childIterator;
  childIterator = new ChildrenIterator(loc, child1, child2);
  return createResultNode(result, planState, name, childIterator);
}

bool
ZorbaRestGetIterator::nextImpl(store::Item_t& result, PlanState& planState) const
{
  store::Item_t lUri;
  xqpStringStore_t lUriString;
  int code;
  store::Item_t doc = NULL;
  store::Store& store = GENV.getStore();

  ZorbaRestGetIteratorState* state;
  bool valid = false;
  DEFAULT_STACK_INIT(ZorbaRestGetIteratorState, state, planState);

  /********* Initialization ***********************/
  curl_global_init(CURL_GLOBAL_ALL); // TODO: once per application, needs to be moved somewhere else
  state->MultiHandle = curl_multi_init(); // TODO check error
  state->EasyHandle = curl_easy_init();
  state->theStreamBuffer = NULL;
  state->headers = NULL;
  curl_easy_setopt(state->EasyHandle, CURLOPT_HTTPGET, 1);
  curl_easy_setopt(state->EasyHandle, CURLOPT_USERAGENT, "libcurl-agent/1.0");
  curl_easy_setopt(state->EasyHandle, CURLOPT_HEADERFUNCTION, ZorbaRestGetIterator::getHeaderData);
  curl_easy_setopt(state->EasyHandle, CURLOPT_WRITEHEADER, state);
  curl_multi_add_handle(state->MultiHandle, state->EasyHandle);

  if (!CONSUME(lUri, 0)) {
    // todo raise an error
  }

  lUriString = lUri->getStringValue();
  curl_easy_setopt(state->EasyHandle, CURLOPT_URL, lUriString->c_str());

  if (state->theStreamBuffer == 0)
  {
    state->theStreamBuffer = new CurlStreamBuffer(state->MultiHandle, state->EasyHandle);
    state->headers = new std::vector<std::string>();
  }

  code = state->theStreamBuffer->multi_perform();

  /********* Process the reply **********************/
  {
    int result_code;
    if (state->headers->size() == 0)
    {
      result_code = code; // TODO change cURL's error code to something else?
    }
    else if (parse_int_const_position<int>(state->headers->operator[](0), 9, result_code, 1))
    {
      result_code = -1; // TODO change this code
    }

    xqpString temp = NumConversions::intToStr(result_code);
    store::Item_t text_code;
    GENV_ITEMFACTORY->createTextNode(text_code, (ulong)&planState, temp.theStrStore, false, true);
    store::Item_t status_code;
    createResultNode(status_code, planState, "status_code", loc, text_code);

    std::istream is(state->theStreamBuffer);
    try {
      doc = store.loadDocument(lUriString, is);
    }
    catch (...) {
      doc = NULL;
    }

    if (doc != NULL)
    {
      store::Iterator_t children = doc->getChildren();
      children->open();
      store::Item_t child;
      children->next(child);
      store::Item_t payload;
      createResultNode(payload, planState, "payload", loc, child); // TODO: check NULL

      valid = createResultNode(result, planState, "result", loc, status_code, payload);
    }
    else
    {
      valid = createResultNode(result, planState, "result", loc, status_code);
    }
  }

  STACK_PUSH(valid, state);

  /********* Deinitialization ***********************/
  curl_multi_remove_handle(state->MultiHandle, state->EasyHandle);
  curl_easy_cleanup(state->EasyHandle);
  curl_multi_cleanup(state->MultiHandle);
  curl_global_cleanup();
  delete state->theStreamBuffer;
  delete state->headers;

  STACK_END (state);
}

size_t
ZorbaRestGetIterator::getHeaderData(void *ptr, size_t size, size_t nmemb, void *aState)
{
  ZorbaRestGetIteratorState* state = static_cast<ZorbaRestGetIteratorState*>(aState);

  std::string temp(static_cast<char*>(ptr), size*nmemb-1);
  state->headers->push_back(temp);
  // std::cout << "header: " << temp << std::endl;

  return size * nmemb;
}

} /* namespace zorba */
<|endoftext|>


<commit_before><commit_msg>Removed file<commit_after><|endoftext|>