<commit_before>#include <iostream>
#include <string>
#include <algorithm>
#include <numeric>
#include <cstdlib>
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/strong_components.hpp>
#include <boost/graph/graphviz.hpp>
#include <boost/program_options.hpp>

#include "datastructs/matrix.h"

#include "polynomials/polynomial.h"
#include "polynomials/non_commutative_polynomial.h"

#include "semirings/commutativeRExp.h"
#include "semirings/float-semiring.h"
#include "semirings/pseudo_linear_set.h"

#ifdef OLD_SEMILINEAR_SET
#include "semirings/semilinSetExp.h"
#else
#include "semirings/semilinear_set.h"
#endif

#include "parser.h"

//#include "newton.h"
#include "newton_generic.h"

template <typename SR>
struct VertexProp {
        std::string name;   // used for graphviz output
        VarId var;         // var and rex combines the equations in the vertex
        Polynomial<SR> rex;
};

// group the equations to SCCs
template <typename SR>
std::vector<std::vector<std::pair<VarId, Polynomial<SR>>>> group_by_scc(std::vector<std::pair<VarId, Polynomial<SR>>> equations, bool graphviz_output)
{
        // create map of variables to [0..n]. this is used to enumerate important variables in a clean way from 0 to n during graph construction
        std::map<VarId, int> var_key;

        // build the graph
        boost::adjacency_list<boost::vecS, boost::vecS, boost::bidirectionalS, VertexProp<SR>> graph(equations.size());
        for(auto e_it = equations.begin(); e_it != equations.end(); ++e_it)
        {
                // if the variable is not yet in the map insert it together with the size of
                // the map. this way we get a unique identifier for the variable counting from 0 to n
                if(var_key.find(e_it->first) == var_key.end())
                        var_key.insert(var_key.begin(), std::pair<VarId,int>(e_it->first,var_key.size()));
                int a = var_key.find(e_it->first)->second; // variable key
                graph[a].var = e_it->first; // store VarId to the vertex
                graph[a].name = Var::GetVar(e_it->first).string(); // store the name to the vertex
                graph[a].rex = e_it->second; // store the regular expression to the vertex

                auto v = e_it->second.get_variables(); // all variables of this rule;
                for(auto v_it = v.begin(); v_it != v.end(); ++v_it)
                {
                        if(var_key.find(*v_it) == var_key.end()) // variable is not yet in the map
                                var_key.insert(var_key.begin(), std::pair<VarId,int>(*v_it,var_key.size()));
                        int b = var_key.find(*v_it)->second; // variable key
                        boost::add_edge(a, b, graph);
                }
        } // graph is complete

        if(graphviz_output)
        {
                // output the created graph to graph.dot
                boost::dynamic_properties dp;
                dp.property("label", boost::get(&VertexProp<SR>::name, graph)); // vertex name is the name of the equation
                dp.property("node_id", get(boost::vertex_index, graph)); // this is needed
                std::ofstream outf("graph.dot");
                boost::write_graphviz_dp(outf, graph, dp);
        }

        // calculate strong connected components and store them in 'component'
        std::vector<int> component(boost::num_vertices(graph));
        boost::strong_components(graph,&component[0]);

        // group neccessary equations together
        int num_comp = *std::max_element(component.begin(), component.end()) + 1; // find the number of components
        std::vector<std::vector<std::pair<VarId,Polynomial<SR>>>> grouped_equations;
        grouped_equations.resize(num_comp);

        // iterate over all vertices (0 to n)
        // collect the necessary variables + equations for every component
        for (unsigned int j = 0; j != component.size(); ++j)
        {
                //std::cout << j << ", " << graph[j].var << " is in component " << component[j] << std::endl;
                grouped_equations[component[j]].push_back(std::pair<VarId,Polynomial<SR>>(graph[j].var, graph[j].rex));
        }

        return grouped_equations;
}

// apply the newton method to the given input
template <typename SR>
std::map<VarId, SR> apply_newton(std::vector<std::pair<VarId, Polynomial<SR>>> equations, bool scc, bool iteration_flag, int iterations, bool graphviz_output)
{
        // TODO: sanity checks on the input!

        // generate an instance of the newton solver
        Newton<SR> newton;

        // if we use the scc method, group the equations
        // the outer vector contains SCCs starting with a bottom SCC at 0
        std::vector<std::vector<std::pair<VarId,Polynomial<SR>>>> equations2;
        if(scc)
        {
                auto tmp = group_by_scc(equations, graphviz_output);
                equations2.insert(equations2.begin(), tmp.begin(), tmp.end());
        }
        else if (!scc)
        {
                equations2.push_back(equations);
        }

        // this holds the solution
        std::map<VarId, SR> solution;

        // the same loop is used for both the scc and the non-scc variant
        // in the non-scc variant, we just run once through the loop
        //for(auto it1 = equations2.begin(); it != equations2.end(); ++it)
        for(unsigned int j = 0; j != equations2.size(); ++j)
        {
                // use the solutions to get rid of variables in the remaining equations
                // does nothing in the first round
                std::vector<std::pair<VarId, Polynomial<SR>>> tmp1;
                for(auto it = equations2[j].begin(); it != equations2[j].end(); ++it)
                { // it = (VarId, Polynomial[SR])
                        auto tmp2 = it->second.partial_eval(solution);
                        tmp1.push_back(std::pair<VarId, Polynomial<SR>>(it->first, tmp2));
                }
                // replace old equations with simplified ones
                equations2[j] = tmp1;

                // dynamic iterations
                if(!iteration_flag)
                        // for commutative and idempotent SRs Newton has converged after n+1 iterations, so use this number as default
                        iterations = equations2[j].size() + 1;

                // do some real work here
                std::map<VarId, SR> result = newton.solve_fixpoint(equations2[j], iterations);

                // copy the results into the solution map
                solution.insert(result.begin(), result.end());
        }

        return solution;
}

template <typename SR>
std::string result_string(std::map<VarId,SR> result)
{
        std::stringstream ss;
        for(auto r_it = result.begin(); r_it != result.end(); ++r_it)
                ss << r_it->first << " == " << r_it->second << std::endl;
        return ss.str();
}

int main(int argc, char* argv[])
{
        namespace po = boost::program_options;

        po::options_description desc("Allowed options");
        desc.add_options()
                ( "scc", "apply newton method iteratively to strongly connected components of the equation graph" )
                ( "help,h", "print this help message" )
                ( "iterations,i", po::value<int>(), "specify the number of newton iterations. default is optimal number" )
                //( "verbose", "enable verbose output" )
                //( "debug", "enable debug output" )
                ( "test", "just for testing purposes ... explicit test defined in main()" )
                ( "file,f", po::value<std::string>(), "input file" )
                ( "float", "float semiring" )
                ( "rexp", "commutative regular expression semiring" )
                ( "slset", "explicit semilinear sets semiring (as vectors)" )
                ( "free", "free semiring" )
                ( "pseudolin", "abstraction over semilinear sets" )
                ( "prefix", po::value<int>(), "prefix semiring with given length")
                ( "graphviz", "create the file graph.dot with the equation graph" )
                ;

        po::variables_map vm;
        po::store(po::parse_command_line(argc, argv, desc), vm);
        po::notify(vm);

        if(vm.count("test")) {
                Newton<SemilinSetExp> newton;
                std::vector<VarId> variables;
                variables.push_back(Var::GetVarId("x"));
                std::cout << "- newton (cnt-SR):" << std::endl;

                std::vector<Polynomial<SemilinSetExp> > polynomials;
                Polynomial<SemilinSetExp> f1 = Polynomial<SemilinSetExp>({
                  { SemilinSetExp(Var::GetVarId("a")), Monomial{ {Var::GetVarId("x"),Var::GetVarId("x")} } },
                  { SemilinSetExp(Var::GetVarId("c")), Monomial{} } });

                polynomials.push_back(f1);

                Matrix<SemilinSetExp> result = newton.solve_fixpoint(polynomials, variables, 2);
                std::cout << result << std::endl;

/*              auto s1 = CommutativeRExp(Var::GetVarId("a"));
                auto s2 = CommutativeRExp(Var::GetVarId("b"));
                auto m1 = Matrix<CommutativeRExp>(1,1,{s1});
                auto m2 = Matrix<CommutativeRExp>(1,1,{s2});
*/

                // this actually led to a strange bug with the ublas-matrix implementation!!
/*              auto s1 = SemilinSetExp(Var::GetVarId("a"));
                auto s2 = SemilinSetExp(Var::GetVarId("b"));
                auto m1 = Matrix<SemilinSetExp>(1,1,{s1});
                auto m2 = Matrix<SemilinSetExp>(1,1,{s2});

                auto m3 = m1*m2;
                std::cout << m3;
*/
                return 0;
        }

        if(vm.count("help"))
        {
                std::cout << desc << std::endl;
                return 0;
        }

        int iterations=0;
        if(vm.count("iterations"))
                iterations = vm["iterations"].as<int>();

        // check if we can do something useful
        if(!vm.count("float") &&
           !vm.count("rexp") &&
           !vm.count("slset") &&
           !vm.count("free") &&
           !vm.count("pseudolin") &&
           !vm.count("prefix")) // check for all compatible parameters
        {
                std::cout << "Please supply a supported semiring :)" << std::endl;
                return 0;
        }

        std::vector<std::string> input;
        std::string line;
        if(vm.count("file"))
        {
                // we are reading the input from the given file
                std::ifstream file;
                file.open(vm["file"].as<std::string>(), std::ifstream::in);
                if(file.fail())
                  std::cerr << "Could not open input file: " << vm["file"].as<std::string>() << std::endl;
                while(std::getline(file, line))
                        input.push_back(line);
        }
        else
        {
                // we are reading from stdin
                while(std::getline(std::cin, line))
                        input.push_back(line);
        }

        // join the input into one string
        std::string input_all = std::accumulate(input.begin(), input.end(), std::string(""));

        Parser p;

        if(vm.count("slset")) {
                std::vector<std::pair<VarId, Polynomial<SemilinSetExp>>> equations(p.slset_parser(input_all));
                if(equations.empty()) return -1;

                for (auto eq_it = equations.begin(); eq_it != equations.end(); ++eq_it)
                {
                        DMSG("* " << eq_it->first << " → " << eq_it->second);
                }

                auto result = apply_newton<SemilinSetExp>(equations, vm.count("scc"), vm.count("iterations"), iterations, vm.count("graphviz"));
                std::cout << result_string(result) << std::endl;
        } else if (vm.count("pseudolin")) {
                std::vector<std::pair<VarId, Polynomial<SemilinSetExp>>>
                  equations(p.slset_parser(input_all));
                auto pseudo_equations =
                  SemilinearToPseudoLinearEquations<
                    DummyDivider,
                    // DummySimplifier
                    SparseVecSimplifier2>(equations);
                auto pseudo_result = apply_newton(pseudo_equations,
                                                  vm.count("scc"),
                                                  vm.count("iterations"),
                                                  iterations,
                                                  vm.count("graphviz"));
                std::cout << result_string(pseudo_result) << std::endl;

        }
        else if(vm.count("rexp")) {
                // parse the input into a list of (Var → Polynomial[SR])
                std::vector<std::pair<VarId, Polynomial<CommutativeRExp>>> equations(p.rexp_parser(input_all));
                if(equations.empty()) return -1;

                for(auto eq_it = equations.begin(); eq_it != equations.end(); ++eq_it)
                {
                        std::cout << "* " << eq_it->first << " → " << eq_it->second << std::endl;
                }

                // apply the newton method to the equations
                auto result = apply_newton<CommutativeRExp>(equations, vm.count("scc"), vm.count("iterations"), iterations, vm.count("graphviz"));
                std::cout << result_string(result) << std::endl;
        }
        else if(vm.count("free")) {
                // parse the input into a list of (Var → Polynomial[SR])
                std::vector<std::pair<VarId, NonCommutativePolynomial<FreeSemiring>>> equations(p.free_parser(input_all));
                if(equations.empty()) return -1;

                for(auto eq_it = equations.begin(); eq_it != equations.end(); ++eq_it)
                {
                        std::cout << "* " << eq_it->first << " → " << eq_it->second << std::endl;
                }

                // apply the newton method to the equations
                //auto result = apply_newton<FreeSemiring>(equations, vm.count("scc"), vm.count("iterations"), iterations, vm.count("graphviz"));
                //std::cout << result_string(result) << std::endl;
        }
        else if(vm.count("prefix")) {
                // parse the input into a list of (Var → Polynomial[SR])
                std::vector<std::pair<VarId, NonCommutativePolynomial<PrefixSemiring>>> equations(p.prefix_parser(input_all, vm["prefix"].as<int>()));
                if(equations.empty()) return -1;

                for(auto eq_it = equations.begin(); eq_it != equations.end(); ++eq_it)
                {
                        std::cout << "* " << eq_it->first << " → " << eq_it->second << std::endl;
                }

                // apply the newton method to the equations
                //auto result = apply_newton<PrefixSemiring>(equations, vm.count("scc"), vm.count("iterations"), iterations, vm.count("graphviz"));
                //std::cout << result_string(result) << std::endl;
        }
        else if(vm.count("float")) {
                std::vector<std::pair<VarId, Polynomial<FloatSemiring>>> equations(p.float_parser(input_all));
                if(equations.empty()) return -1;

                for(auto eq_it = equations.begin(); eq_it != equations.end(); ++eq_it)
                {
                        std::cout << "* " << eq_it->first << " → " << eq_it->second << std::endl;
                }

                auto result = apply_newton<FloatSemiring>(equations, vm.count("scc"), vm.count("iterations"), iterations, vm.count("graphviz"));
                std::cout << result_string(result) << std::endl;
        }

        return 0;
}
<commit_msg>main: major cleanup<commit_after>#include <algorithm>
#include <cstdlib>
#include <iostream>
#include <numeric>
#include <string>

#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/strong_components.hpp>
#include <boost/graph/graphviz.hpp>
#include <boost/program_options.hpp>

#include "datastructs/matrix.h"

#include "polynomials/polynomial.h"
#include "polynomials/non_commutative_polynomial.h"

#include "semirings/commutativeRExp.h"
#include "semirings/float-semiring.h"
#include "semirings/pseudo_linear_set.h"

#ifdef OLD_SEMILINEAR_SET
#include "semirings/semilinSetExp.h"
#else
#include "semirings/semilinear_set.h"
#endif

#include "parser.h"

//#include "newton.h"
#include "newton_generic.h"

template <typename SR>
struct VertexProp {
  std::string name;   // used for graphviz output
  VarId var;         // var and rex combines the equations in the vertex
  Polynomial<SR> rex;
};

// group the equations to SCCs
template <typename SR>
std::vector< std::vector< std::pair< VarId, Polynomial<SR> > > >
group_by_scc(const std::vector< std::pair< VarId, Polynomial<SR> > > &equations,
             bool graphviz_output) {
  // create map of variables to [0..n]. this is used to enumerate important variables in a clean way from 0 to n during graph construction
  std::map<VarId, int> var_key;

  // build the graph
  boost::adjacency_list<boost::vecS,
                        boost::vecS,
                        boost::bidirectionalS,
                        VertexProp<SR>> graph(equations.size());
  // for (auto e_it = equations.begin(); e_it != equations.end(); ++e_it)
  for (const auto &eq : equations) {
    // if the variable is not yet in the map insert it together with the size of
    // the map. this way we get a unique identifier for the variable counting from 0 to n
    if (var_key.find(eq.first) == var_key.end()) {
      var_key.insert(std::make_pair(eq.first, var_key.size()));
    }
    int a = var_key.find(eq.first)->second; // variable key
    graph[a].var = eq.first; // store VarId to the vertex
    graph[a].name = Var::GetVar(eq.first).string(); // store the name to the vertex
    graph[a].rex = eq.second; // store the regular expression to the vertex

    auto variables = eq.second.get_variables(); // all variables of this rule;
    // for (auto v_it = v.begin(); v_it != v.end(); ++v_it)
    for (const auto &var : variables) {
      if (var_key.find(var) == var_key.end()) // variable is not yet in the map
        var_key.insert(var_key.begin(), std::pair<VarId,int>(var,var_key.size()));
      int b = var_key.find(var)->second; // variable key
      boost::add_edge(a, b, graph);
    }
  } // graph is complete

  if (graphviz_output) {
    // output the created graph to graph.dot
    boost::dynamic_properties dp;
    dp.property("label", boost::get(&VertexProp<SR>::name, graph)); // vertex name is the name of the equation
    dp.property("node_id", get(boost::vertex_index, graph)); // this is needed
    std::ofstream outf("graph.dot");
    boost::write_graphviz_dp(outf, graph, dp);
  }

  // calculate strong connected components and store them in 'component'
  std::vector<int> component(boost::num_vertices(graph));
  boost::strong_components(graph,&component[0]);

  // group neccessary equations together
  int num_comp = *std::max_element(component.begin(), component.end()) + 1; // find the number of components
  std::vector< std::vector< std::pair< VarId,Polynomial<SR> > > >
    grouped_equations(num_comp);
  // grouped_equations.resize(num_comp);

  // iterate over all vertices (0 to n)
  // collect the necessary variables + equations for every component
  for (std::size_t j = 0; j != component.size(); ++j) {
    //std::cout << j << ", " << graph[j].var << " is in component " << component[j] << std::endl;
    grouped_equations[component[j]].push_back(std::pair<VarId,Polynomial<SR>>(graph[j].var, graph[j].rex));
  }

  return grouped_equations;
}

// apply the newton method to the given input
template <typename SR>
std::map<VarId, SR> apply_newton(
    const std::vector< std::pair< VarId, Polynomial<SR> > > &equations,
    bool scc, bool iteration_flag, std::size_t iterations, bool graphviz_output) {

  // TODO: sanity checks on the input!

  // generate an instance of the newton solver
  Newton<SR> newton;

  // if we use the scc method, group the equations
  // the outer vector contains SCCs starting with a bottom SCC at 0
  std::vector< std::vector< std::pair< VarId,Polynomial<SR> > > > equations2;
  if (scc) {
    auto tmp = group_by_scc(equations, graphviz_output);
    equations2.insert(equations2.begin(), tmp.begin(), tmp.end());
  }
  else if (!scc) {
    equations2.push_back(equations);
  }

  // this holds the solution
  std::map<VarId, SR> solution;

  // the same loop is used for both the scc and the non-scc variant
  // in the non-scc variant, we just run once through the loop
  //for (auto it1 = equations2.begin(); it != equations2.end(); ++it)
  for (std::size_t j = 0; j != equations2.size(); ++j) {
    // use the solutions to get rid of variables in the remaining equations
    // does nothing in the first round
    std::vector<std::pair<VarId, Polynomial<SR>>> tmp1;
    for (auto it = equations2[j].begin(); it != equations2[j].end(); ++it)
    { // it = (VarId, Polynomial[SR])
      auto tmp2 = it->second.partial_eval(solution);
      tmp1.push_back(std::pair<VarId, Polynomial<SR>>(it->first, tmp2));
    }
    // replace old equations with simplified ones
    equations2[j] = tmp1;

    // dynamic iterations
    if (!iteration_flag) {
      // for commutative and idempotent SRs Newton has converged after n+1 iterations, so use this number as default
      iterations = equations2[j].size() + 1;
    }

    // do some real work here
    std::map<VarId, SR> result = newton.solve_fixpoint(equations2[j], iterations);

    // copy the results into the solution map
    solution.insert(result.begin(), result.end());
  }

  return solution;
}

template <typename SR>
std::string result_string(const std::map<VarId, SR> &result) {
  std::stringstream ss;
  for (auto r_it = result.begin(); r_it != result.end(); ++r_it) {
    ss << r_it->first << " == " << r_it->second << std::endl;
  }
  return ss.str();
}

template <typename Container>
void PrintEquations(const Container &equations) {
  std::cout << "Equations:" << std::endl;
  for (auto &eq : equations) {
    std::cout << "* " << eq.first << " → " << eq.second << std::endl;
  }
}

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

  namespace po = boost::program_options;

  po::options_description desc("Allowed options");
  desc.add_options()
    ( "scc", "apply newton method iteratively to strongly connected components of the equation graph" )
    ( "help,h", "print this help message" )
    ( "iterations,i", po::value<int>(), "specify the number of newton iterations. default is optimal number" )
    //( "verbose", "enable verbose output" )
    //( "debug", "enable debug output" )
    ( "test", "just for testing purposes ... explicit test defined in main()" )
    ( "file,f", po::value<std::string>(), "input file" )
    ( "float", "float semiring" )
    ( "rexp", "commutative regular expression semiring" )
    ( "slset", "explicit semilinear sets semiring (as vectors)" )
    ( "free", "free semiring" )
    ( "pseudolin", "abstraction over semilinear sets" )
    ( "prefix", po::value<int>(), "prefix semiring with given length")
    ( "graphviz", "create the file graph.dot with the equation graph" )
    ;

  po::variables_map vm;
  po::store(po::parse_command_line(argc, argv, desc), vm);
  po::notify(vm);

  if (vm.count("test")) {
    Newton<SemilinSetExp> newton;
    std::vector<VarId> variables;
    variables.push_back(Var::GetVarId("x"));
    std::cout << "- newton (cnt-SR):" << std::endl;

    std::vector<Polynomial<SemilinSetExp> > polynomials;
    Polynomial<SemilinSetExp> f1 = Polynomial<SemilinSetExp>({
        { SemilinSetExp(Var::GetVarId("a")), Monomial{ {Var::GetVarId("x"),Var::GetVarId("x")} } },
        { SemilinSetExp(Var::GetVarId("c")), Monomial{} } });

    polynomials.push_back(f1);

    Matrix<SemilinSetExp> result = newton.solve_fixpoint(polynomials, variables, 2);
    std::cout << result << std::endl;

    /*              auto s1 = CommutativeRExp(Var::GetVarId("a"));
                    auto s2 = CommutativeRExp(Var::GetVarId("b"));
                    auto m1 = Matrix<CommutativeRExp>(1,1,{s1});
                    auto m2 = Matrix<CommutativeRExp>(1,1,{s2});
                    */

    // this actually led to a strange bug with the ublas-matrix implementation!!
    /*              auto s1 = SemilinSetExp(Var::GetVarId("a"));
                    auto s2 = SemilinSetExp(Var::GetVarId("b"));
                    auto m1 = Matrix<SemilinSetExp>(1,1,{s1});
                    auto m2 = Matrix<SemilinSetExp>(1,1,{s2});

                    auto m3 = m1*m2;
                    std::cout << m3;
                    */
    return 0;
  }

  if (vm.count("help")) {
    std::cout << desc << std::endl;
    return 0;
  }

  int iterations=0;
  if (vm.count("iterations"))
          iterations = vm["iterations"].as<int>();

  // check if we can do something useful
  if (!vm.count("float") &&
      !vm.count("rexp") &&
      !vm.count("slset") &&
      !vm.count("free") &&
      !vm.count("pseudolin") &&
      !vm.count("prefix")) {
    std::cout << "Please supply a supported semiring :)" << std::endl;
    return 0;
  }

  std::vector<std::string> input;
  std::string line;
  if (vm.count("file")) {
    // we are reading the input from the given file
    std::ifstream file;
    file.open(vm["file"].as<std::string>(), std::ifstream::in);
    if (file.fail()) {
      std::cerr << "Could not open input file: " << vm["file"].as<std::string>() << std::endl;
    }
    while (std::getline(file, line)) {
      input.push_back(line);
    }
  } else {
    // we are reading from stdin
    while (std::getline(std::cin, line)) {
      input.push_back(line);
    }
  }

  // join the input into one string
  std::string input_all =
    std::accumulate(input.begin(), input.end(), std::string(""));

  Parser p;

  if (vm.count("slset")) {

    auto equations = p.slset_parser(input_all);
    if (equations.empty()) return EXIT_FAILURE;

    PrintEquations(equations);

    auto result = apply_newton<SemilinSetExp>(equations,
                                              vm.count("scc"),
                                              vm.count("iterations"),
                                              iterations,
                                              vm.count("graphviz"));
    std::cout << result_string(result) << std::endl;

  } else if (vm.count("pseudolin")) {

    auto equations = p.slset_parser(input_all);
    auto pseudo_equations =
      SemilinearToPseudoLinearEquations<
      DummyDivider,
      // DummySimplifier
      SparseVecSimplifier2>(equations);

    PrintEquations(pseudo_equations);

    auto pseudo_result = apply_newton(pseudo_equations,
                                      vm.count("scc"),
                                      vm.count("iterations"),
                                      iterations,
                                      vm.count("graphviz"));
    std::cout << result_string(pseudo_result) << std::endl;

  } else if (vm.count("rexp")) {

    // parse the input into a list of (Var → Polynomial[SR])
    auto equations = p.rexp_parser(input_all);
    if (equations.empty()) return EXIT_FAILURE;

    PrintEquations(equations);

    // apply the newton method to the equations
    auto result = apply_newton<CommutativeRExp>(equations,
                                                vm.count("scc"),
                                                vm.count("iterations"),
                                                iterations,
                                                vm.count("graphviz"));
    std::cout << result_string(result) << std::endl;

  } else if (vm.count("free")) {

    // parse the input into a list of (Var → Polynomial[SR])
    auto equations = p.free_parser(input_all);
    if (equations.empty()) return EXIT_FAILURE;

    PrintEquations(equations);

    // apply the newton method to the equations
    //auto result = apply_newton<FreeSemiring>(equations,
    //                                         vm.count("scc"),
    //                                         vm.count("iterations"),
    //                                         iterations,
    //                                         vm.count("graphviz"));
    //std::cout << result_string(result) << std::endl;

  } else if (vm.count("prefix")) {

    // parse the input into a list of (Var → Polynomial[SR])
    auto equations = p.prefix_parser(input_all, vm["prefix"].as<int>());
    if (equations.empty()) return EXIT_FAILURE;

    PrintEquations(equations);

    // apply the newton method to the equations
    //auto result = apply_newton<PrefixSemiring>(equations,
    //                                           vm.count("scc"),
    //                                           vm.count("iterations"),
    //                                           iterations,
    //                                           vm.count("graphviz"));
    //std::cout << result_string(result) << std::endl;

  } else if (vm.count("float")) {

    auto equations = p.float_parser(input_all);
    if (equations.empty()) return EXIT_FAILURE;

    PrintEquations(equations);

    auto result = apply_newton<FloatSemiring>(equations,
                                              vm.count("scc"),
                                              vm.count("iterations"),
                                              iterations,
                                              vm.count("graphviz"));
    std::cout << result_string(result) << std::endl;
  }

  return EXIT_SUCCESS;
}
<|endoftext|>


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

#include "webkit/media/audio_decoder.h"

#include <vector>
#include "base/basictypes.h"
#include "base/string_util.h"
#include "base/time.h"
#include "media/base/limits.h"
#include "media/filters/audio_file_reader.h"
#include "media/filters/in_memory_url_protocol.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebAudioBus.h"

using media::AudioFileReader;
using media::InMemoryUrlProtocol;
using std::vector;
using WebKit::WebAudioBus;

namespace webkit_media {

// Decode in-memory audio file data.
bool DecodeAudioFileData(
    WebKit::WebAudioBus* destination_bus,
    const char* data, size_t data_size, double sample_rate) {
  DCHECK(destination_bus);
  if (!destination_bus)
    return false;

  // Uses the FFmpeg library for audio file reading.
  InMemoryUrlProtocol url_protocol(reinterpret_cast<const uint8*>(data),
                                   data_size, false);
  AudioFileReader reader(&url_protocol);

  if (!reader.Open())
    return false;

  size_t number_of_channels = reader.channels();
  double file_sample_rate = reader.sample_rate();
  double duration = reader.duration().InSecondsF();
  size_t number_of_frames = static_cast<size_t>(reader.number_of_frames());

  // Apply sanity checks to make sure crazy values aren't coming out of
  // FFmpeg.
  if (!number_of_channels ||
      number_of_channels > static_cast<size_t>(media::limits::kMaxChannels) ||
      file_sample_rate < media::limits::kMinSampleRate ||
      file_sample_rate > media::limits::kMaxSampleRate)
    return false;

  // TODO(crogers) : do sample-rate conversion with FFmpeg.
  // For now, we're ignoring the requested 'sample_rate' and returning
  // the WebAudioBus at the file's sample-rate.
  // double destination_sample_rate =
  //   (sample_rate != 0.0) ? sample_rate : file_sample_rate;
  double destination_sample_rate = file_sample_rate;

  DLOG(INFO) << "Decoding file data -"
      << " data: " << data
      << " data size: " << data_size
      << " duration: " << duration
      << " number of frames: " << number_of_frames
      << " sample rate: " << file_sample_rate
      << " number of channels: " << number_of_channels;

  // Change to destination sample-rate.
  number_of_frames = static_cast<size_t>(number_of_frames *
      (destination_sample_rate / file_sample_rate));

  // Allocate and configure the output audio channel data.
  destination_bus->initialize(number_of_channels,
                              number_of_frames,
                              destination_sample_rate);

  // Wrap the channel pointers which will receive the decoded PCM audio.
  vector<float*> audio_data;
  audio_data.reserve(number_of_channels);
  for (size_t i = 0; i < number_of_channels; ++i) {
    audio_data.push_back(destination_bus->channelData(i));
  }

  // Decode the audio file data.
  return reader.Read(audio_data, number_of_frames);
}

}  // namespace webkit_media
<commit_msg>Reduce log level to DVLOG(1) in webkit_media::AudioDecoder.<commit_after>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "webkit/media/audio_decoder.h"

#include <vector>
#include "base/basictypes.h"
#include "base/string_util.h"
#include "base/time.h"
#include "media/base/limits.h"
#include "media/filters/audio_file_reader.h"
#include "media/filters/in_memory_url_protocol.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebAudioBus.h"

using media::AudioFileReader;
using media::InMemoryUrlProtocol;
using std::vector;
using WebKit::WebAudioBus;

namespace webkit_media {

// Decode in-memory audio file data.
bool DecodeAudioFileData(
    WebKit::WebAudioBus* destination_bus,
    const char* data, size_t data_size, double sample_rate) {
  DCHECK(destination_bus);
  if (!destination_bus)
    return false;

  // Uses the FFmpeg library for audio file reading.
  InMemoryUrlProtocol url_protocol(reinterpret_cast<const uint8*>(data),
                                   data_size, false);
  AudioFileReader reader(&url_protocol);

  if (!reader.Open())
    return false;

  size_t number_of_channels = reader.channels();
  double file_sample_rate = reader.sample_rate();
  double duration = reader.duration().InSecondsF();
  size_t number_of_frames = static_cast<size_t>(reader.number_of_frames());

  // Apply sanity checks to make sure crazy values aren't coming out of
  // FFmpeg.
  if (!number_of_channels ||
      number_of_channels > static_cast<size_t>(media::limits::kMaxChannels) ||
      file_sample_rate < media::limits::kMinSampleRate ||
      file_sample_rate > media::limits::kMaxSampleRate)
    return false;

  // TODO(crogers) : do sample-rate conversion with FFmpeg.
  // For now, we're ignoring the requested 'sample_rate' and returning
  // the WebAudioBus at the file's sample-rate.
  // double destination_sample_rate =
  //   (sample_rate != 0.0) ? sample_rate : file_sample_rate;
  double destination_sample_rate = file_sample_rate;

  DVLOG(1) << "Decoding file data -"
           << " data: " << data
           << " data size: " << data_size
           << " duration: " << duration
           << " number of frames: " << number_of_frames
           << " sample rate: " << file_sample_rate
           << " number of channels: " << number_of_channels;

  // Change to destination sample-rate.
  number_of_frames = static_cast<size_t>(number_of_frames *
      (destination_sample_rate / file_sample_rate));

  // Allocate and configure the output audio channel data.
  destination_bus->initialize(number_of_channels,
                              number_of_frames,
                              destination_sample_rate);

  // Wrap the channel pointers which will receive the decoded PCM audio.
  vector<float*> audio_data;
  audio_data.reserve(number_of_channels);
  for (size_t i = 0; i < number_of_channels; ++i) {
    audio_data.push_back(destination_bus->channelData(i));
  }

  // Decode the audio file data.
  return reader.Read(audio_data, number_of_frames);
}

}  // namespace webkit_media
<|endoftext|>


<commit_before>#include <cstdio>
#include <cstdlib>
#include <unistd.h>
#include <string>
#include <string.h>
#include <csignal>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <dirent.h>
#include <fcntl.h>
#include <errno.h>
#include <functional>
#include <unordered_map>
#include <algorithm>
#include <iostream>
#include <sstream>

#if defined(__APPLE__) || defined(__GNUC__) && __GNUC__ * 10  + __GNUC_MINOR__ >= 49
#include <regex>
#endif

#include <cassert>
#include <vector>
#include <fstream>
#include <future>

#include <ctime>

#define BUF_SIZE 4096
#define MAX_LISTEN 128

namespace Cappuccino{

	class Request;
	class Response;

	struct {

		time_t time;
   		struct tm *t_st;

		int port = 1204;
		int sockfd = 0;
		int sessionfd = 0;
	    fd_set mask1fds, mask2fds;

		std::shared_ptr<std::string> view_root;
		std::shared_ptr<std::string> static_root;

		std::unordered_map<std::string,
			std::function<Response(std::shared_ptr<Request>)>
		> routes;

	} context;

	namespace Log{

		std::string current(){
			char timestr[256];
   			time(&context.time);
			strftime(timestr, 255, "%Y-%m-%d %H:%M:%S %Z", localtime(&context.time));
			return timestr;
		}

		static int LogLevel = 0;
		static void debug(std::string msg){
			if(LogLevel >= 1){
				std::cout <<current()<<" "<< msg << std::endl;
			}
		}

		static void info(std::string msg){
			if(LogLevel >= 2){
				std::cout <<current()<<" "<< msg << std::endl;
			}
		}
	};

	namespace signal_utils{

		void signal_handler(int signal){
			close(context.sessionfd);
			close(context.sockfd);
			exit(0);
		}

		void signal_handler_child(int SignalName){
			while(waitpid(-1,NULL,WNOHANG)>0){}
	        signal(SIGCHLD, signal_utils::signal_handler_child);
		}

		void init_signal(){
			if(signal(SIGINT, signal_utils::signal_handler) == SIG_ERR){
				exit(1);
			}
			if(signal(SIGCHLD, signal_utils::signal_handler_child) == SIG_ERR){
				exit(1);
			}
		}
	}

	namespace utils{
		std::vector<std::string> split(const std::string& str, std::string delim) noexcept{
			std::vector<std::string> result;
		    std::string::size_type pos = 0;
		    while(pos != std::string::npos ){
		        std::string::size_type p = str.find(delim, pos);
		        if(p == std::string::npos){
		            result.push_back(str.substr(pos));
		            break;
		        }else{
		            result.push_back(str.substr(pos, p - pos));
		        }
		        pos = p + delim.size();
		    }
		    return result;
		}
	};

	void init_socket(){
	    struct sockaddr_in server;
		if((context.sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0){
			exit(EXIT_FAILURE);
		}
		memset( &server, 0, sizeof(server));
		server.sin_family = AF_INET;
		server.sin_addr.s_addr = INADDR_ANY;
		server.sin_port = htons(context.port);

		char opt = 1;
		setsockopt(context.sockfd, SOL_SOCKET, SO_REUSEADDR, (char *)&opt, sizeof(char));

		int temp = 1;
  		if(setsockopt(context.sockfd, SOL_SOCKET, SO_REUSEADDR,
	        &temp, sizeof(int))){
		}

		if (bind(context.sockfd, (struct sockaddr *) &server, sizeof(server)) < 0) {
			exit(EXIT_FAILURE);
		}

		if(listen(context.sockfd,  MAX_LISTEN) < 0) {
			exit(EXIT_FAILURE);
		}

	    FD_ZERO(&context.mask1fds);
	    FD_SET(context.sockfd, &context.mask1fds);
	}

	using namespace std;

	pair<string,string> openFile(string aFilename){
		auto filename = aFilename;
		std::ifstream ifs( filename, std::ios::in | std::ios::binary);
		if(ifs.fail()){
			throw std::runtime_error("No such file or directory \""+ filename +"\"\n");
		}
		ifs.seekg( 0, std::ios::end);
		auto pos = ifs.tellg();
		ifs.seekg( 0, std::ios::beg);

		std::vector<char> buf(pos);
		ifs.read(buf.data(), pos);
		string response(buf.cbegin(), buf.cend());

		if( response[0] == '\xFF' && response[1] == '\xD8'){
			return make_pair(response, "image/jpg");
		}else if( response[0] == '\x89' && response[1] == 'P' && response[2] == 'N' && response[3] == 'G'){
			return make_pair(response, "image/png");
		}else if( response[0] == 'G' && response[1] == 'I' && response[2] == 'F' && response[3] == '8' && (response[4] == '7' || response[4] == '9') && response[2] == 'a'){
			return make_pair(response, "image/gif");
		}else{
			return make_pair(response, "text/html");
		}
	}

	void option(int argc, char *argv[]) noexcept{
		char result;
		while((result = getopt(argc,argv,"dp:")) != -1){
			switch(result){
			case 'd':
				Log::LogLevel = 1;
				break;
			case 'p':
				context.port = atoi(optarg);
				break;
			}
		}
	}

	class Request{
		unordered_map<string, string> headerset;
		unordered_map<string, string> paramset;
	  public:
		Request(string method, string url,string protocol):
		method(move(method)),
		url(move(url)),
		protocol(move(protocol))
		{}

		const string method;
		const string url;
		const string protocol;

		void addHeader(string key,string value){
			headerset[key] = move(value);
		}

		void addParams(string key,string value){
			paramset[key] = move(value);
		}

		string header(string key){
			if(headerset.find(key) == headerset.end())
				return "INVALID";
			return headerset[key];
		}

		string params(string key){
			if(paramset.find(key) == paramset.end())
				return "INVALID";
			return paramset[key];
		}
	};

    class Response{

		unordered_map<string, string> headerset;

		int status_;
		string message_;
		string url_;
		string body_;
		string protocol_;
      public:

		Response(weak_ptr<Request> req){
			auto r = req.lock();
			if(r){
				url_ = r->url;
				protocol_ = r->protocol;
			}else{
				throw std::runtime_error("Request  expired!\n");
			}
		}

		Response(int st,string msg,string pro, string bod):
			status_(st),
			message_(msg),
			body_(bod),
			protocol_(pro)
		{}

		Response* message(string msg){
			message_ = msg;
			return this;
		}

		Response* status(int st){
			status_ = st;
			return this;
		}

		Response* file(string filename){
			auto file = openFile(*context.view_root + "/" + filename);
			body_ = file.first;
			headerset["Content-type"] = move(file.second);
			return this;
		}

      	operator string(){
      		return protocol_ + " " + to_string(status_) +" "+ message_ + "\n\n" + body_;
      	}
    };

	string createResponse(char* req) noexcept{
		auto lines = utils::split(string(req), "\n");
		if(lines.empty())
			return Response(400, "Bad Request", "HTTP/1.1", "NN");

		auto tops = utils::split(lines[0], " ");
		if(tops.size() < 3)
			return Response(401, "Bad Request", "HTTP/1.1",  "NN");

		Log::debug(tops[0] +" "+ tops[1] +" "+ tops[2]);

		auto request = shared_ptr<Request>(new Request(tops[0],tops[1],tops[2]));

		if(context.routes.find(tops[1]) != context.routes.end()){
			return context.routes[tops[1]](move(request));
		}

		return Response( 404,"Not found", tops[2], "AA");
	}

	string receiveProcess(int sessionfd){
		char buf[BUF_SIZE] = {};

		if (recv(sessionfd, buf, sizeof(buf), 0) < 0) {
			exit(EXIT_FAILURE);
		}
		do{
			if(strstr(buf, "\r\n")){
				break;
			}
			if (strlen(buf) >= sizeof(buf)) {
				memset(&buf, 0, sizeof(buf));
			}
		}while(read(sessionfd, buf+strlen(buf), sizeof(buf) - strlen(buf)) > 0);
		return createResponse(buf);
	}

	void load(string directory, string filename) noexcept{
		if(filename == "." || filename == "..") return;
		if(filename!="")
			directory += "/" + filename;
		DIR* dir = opendir(directory.c_str());
		if(dir != NULL){
			struct dirent* dent;
	        dent = readdir(dir);
		    while(dent!=NULL){
		        dent = readdir(dir);
		        if(dent!=NULL)
			        load(directory, string(dent->d_name));
		    }
		    closedir(dir);
			delete dent;
			delete dir;
		}else{
			Log::debug("add "+directory);
			context.routes.insert( make_pair(
				"/" + directory,
				[directory,filename](std::shared_ptr<Request> request) -> Cappuccino::Response{
					return Response(200,"OK","HTTP/1.1",openFile(directory).first);
				}
			));
		}
	}

	void loadStaticFiles() noexcept{
		load(*context.static_root,"");
	}

	void route(string url,std::function<Response(std::shared_ptr<Request>)> F){
		context.routes.insert( make_pair( move(url), move(F) ));
	}

	void root(string r){
		context.view_root =  make_shared<string>(move(r));
	}

	void resource(string s){
		context.static_root = make_shared<string>(move(s));
	}

	void run(){

		init_socket();
		signal_utils::init_signal();
		loadStaticFiles();

	    int cd[FD_SETSIZE];
		struct sockaddr_in client;
        int    fd;
        struct timeval tv;

	    for(int i = 0;i < FD_SETSIZE; i++){
	        cd[i] = 0;
	    }

		int I = 0;
	    while(1) {

			if(I>5){
				return;
			}

	        tv.tv_sec = 0;
	        tv.tv_usec = 0;

	        memcpy(&context.mask2fds, &context.mask1fds, sizeof(context.mask1fds));

	        int select_result = select(FD_SETSIZE, &context.mask2fds, (fd_set *)0, (fd_set *)0, &tv);
	        if(select_result < 1) {
	            for(fd = 0; fd < FD_SETSIZE; fd++) {
	                if(cd[fd] == 1) {
	                    close(fd);
	                    FD_CLR(fd, &context.mask1fds);
	                    cd[fd] = 0;
	                }
	            }
	            continue;
	        }
			for(fd = 0; fd < FD_SETSIZE; fd++){
	            if(FD_ISSET(fd,&context.mask2fds)) {
	                if(fd == context.sockfd) {
	                	memset( &client, 0, sizeof(client));
						int len = sizeof(client);
	                    int clientfd = accept(context.sockfd,
	                        (struct sockaddr *)&client,(socklen_t *) &len);
	                        FD_SET(clientfd, &context.mask1fds);
	                }else {
	                    if(cd[fd] == 1) {
	                        close(fd);
	                        FD_CLR(fd, &context.mask1fds);
	                        cd[fd] = 0;
	                    } else {
							string response = receiveProcess(fd);
							write(fd, response.c_str(), response.size());
	                        cd[fd] = 1;

							I++;

	                    }
	                }
	            }
	        }
	    }
	}

	void Cappuccino(int argc, char *argv[]) {
		option(argc, argv);
		context.view_root = make_shared<string>("");
		context.static_root = make_shared<string>("public");
	}
};

namespace Cocoa{
	using namespace Cappuccino;
	using namespace std;

	// Unit Test
	void testOpenFile(){
		auto res = openFile("html/index.html");
		auto lines = utils::split(res.first, "\n");
		assert(!lines.empty());
	}

	void testOpenInvalidFile(){
		try{
			auto res = openFile("html/index");
		}catch(std::runtime_error e){
			cout<< e.what() << endl;
		}
	}
};

<commit_msg>[Add] print version<commit_after>#include <cstdio>
#include <cstdlib>
#include <unistd.h>
#include <string>
#include <string.h>
#include <csignal>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <dirent.h>
#include <fcntl.h>
#include <errno.h>
#include <functional>
#include <unordered_map>
#include <algorithm>
#include <iostream>
#include <sstream>

#if defined(__APPLE__) || defined(__GNUC__) && __GNUC__ * 10  + __GNUC_MINOR__ >= 49
#include <regex>
#endif

#include <cassert>
#include <vector>
#include <fstream>
#include <future>

#include <ctime>

#define BUF_SIZE 4096
#define MAX_LISTEN 128

namespace Cappuccino{

	class Request;
	class Response;

	struct {

		time_t time;
   		struct tm *t_st;

		int port = 1204;
		int sockfd = 0;
		int sessionfd = 0;
	    fd_set mask1fds, mask2fds;

		std::shared_ptr<std::string> view_root;
		std::shared_ptr<std::string> static_root;

		std::unordered_map<std::string,
			std::function<Response(std::shared_ptr<Request>)>
		> routes;

	} context;

	namespace Log{

		std::string current(){
			char timestr[256];
   			time(&context.time);
			strftime(timestr, 255, "%Y-%m-%d %H:%M:%S %Z", localtime(&context.time));
			return timestr;
		}

		static int LogLevel = 0;
		static void debug(std::string msg){
			if(LogLevel >= 1){
				std::cout <<current()<<" "<< msg << std::endl;
			}
		}

		static void info(std::string msg){
			if(LogLevel >= 2){
				std::cout <<current()<<" "<< msg << std::endl;
			}
		}
	};

	namespace signal_utils{

		void signal_handler(int signal){
			close(context.sessionfd);
			close(context.sockfd);
			exit(0);
		}

		void signal_handler_child(int SignalName){
			while(waitpid(-1,NULL,WNOHANG)>0){}
	        signal(SIGCHLD, signal_utils::signal_handler_child);
		}

		void init_signal(){
			if(signal(SIGINT, signal_utils::signal_handler) == SIG_ERR){
				exit(1);
			}
			if(signal(SIGCHLD, signal_utils::signal_handler_child) == SIG_ERR){
				exit(1);
			}
		}
	}

	namespace utils{
		std::vector<std::string> split(const std::string& str, std::string delim) noexcept{
			std::vector<std::string> result;
		    std::string::size_type pos = 0;
		    while(pos != std::string::npos ){
		        std::string::size_type p = str.find(delim, pos);
		        if(p == std::string::npos){
		            result.push_back(str.substr(pos));
		            break;
		        }else{
		            result.push_back(str.substr(pos, p - pos));
		        }
		        pos = p + delim.size();
		    }
		    return result;
		}
	};

	void init_socket(){
	    struct sockaddr_in server;
		if((context.sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0){
			exit(EXIT_FAILURE);
		}
		memset( &server, 0, sizeof(server));
		server.sin_family = AF_INET;
		server.sin_addr.s_addr = INADDR_ANY;
		server.sin_port = htons(context.port);

		char opt = 1;
		setsockopt(context.sockfd, SOL_SOCKET, SO_REUSEADDR, (char *)&opt, sizeof(char));

		int temp = 1;
  		if(setsockopt(context.sockfd, SOL_SOCKET, SO_REUSEADDR,
	        &temp, sizeof(int))){
		}

		if (bind(context.sockfd, (struct sockaddr *) &server, sizeof(server)) < 0) {
			exit(EXIT_FAILURE);
		}

		if(listen(context.sockfd,  MAX_LISTEN) < 0) {
			exit(EXIT_FAILURE);
		}

	    FD_ZERO(&context.mask1fds);
	    FD_SET(context.sockfd, &context.mask1fds);
	}

	using namespace std;

	pair<string,string> openFile(string aFilename){
		auto filename = aFilename;
		std::ifstream ifs( filename, std::ios::in | std::ios::binary);
		if(ifs.fail()){
			throw std::runtime_error("No such file or directory \""+ filename +"\"\n");
		}
		ifs.seekg( 0, std::ios::end);
		auto pos = ifs.tellg();
		ifs.seekg( 0, std::ios::beg);

		std::vector<char> buf(pos);
		ifs.read(buf.data(), pos);
		string response(buf.cbegin(), buf.cend());

		if( response[0] == '\xFF' && response[1] == '\xD8'){
			return make_pair(response, "image/jpg");
		}else if( response[0] == '\x89' && response[1] == 'P' && response[2] == 'N' && response[3] == 'G'){
			return make_pair(response, "image/png");
		}else if( response[0] == 'G' && response[1] == 'I' && response[2] == 'F' && response[3] == '8' && (response[4] == '7' || response[4] == '9') && response[2] == 'a'){
			return make_pair(response, "image/gif");
		}else{
			return make_pair(response, "text/html");
		}
	}

	void option(int argc, char *argv[]) noexcept{
		char result;
		while((result = getopt(argc,argv,"dvp:")) != -1){
			switch(result){
			case 'd':
				Log::LogLevel = 1;
				break;
			case 'p':
				context.port = atoi(optarg);
				break;
			case 'v':
				Log::info("version 0.0.3");
				exit(0);
			}
		}
	}

	class Request{
		unordered_map<string, string> headerset;
		unordered_map<string, string> paramset;
	  public:
		Request(string method, string url,string protocol):
		method(move(method)),
		url(move(url)),
		protocol(move(protocol))
		{}

		const string method;
		const string url;
		const string protocol;

		void addHeader(string key,string value){
			headerset[key] = move(value);
		}

		void addParams(string key,string value){
			paramset[key] = move(value);
		}

		string header(string key){
			if(headerset.find(key) == headerset.end())
				return "INVALID";
			return headerset[key];
		}

		string params(string key){
			if(paramset.find(key) == paramset.end())
				return "INVALID";
			return paramset[key];
		}
	};

    class Response{

		unordered_map<string, string> headerset;

		int status_;
		string message_;
		string url_;
		string body_;
		string protocol_;
      public:

		Response(weak_ptr<Request> req){
			auto r = req.lock();
			if(r){
				url_ = r->url;
				protocol_ = r->protocol;
			}else{
				throw std::runtime_error("Request  expired!\n");
			}
		}

		Response(int st,string msg,string pro, string bod):
			status_(st),
			message_(msg),
			body_(bod),
			protocol_(pro)
		{}

		Response* message(string msg){
			message_ = msg;
			return this;
		}

		Response* status(int st){
			status_ = st;
			return this;
		}

		Response* file(string filename){
			auto file = openFile(*context.view_root + "/" + filename);
			body_ = file.first;
			headerset["Content-type"] = move(file.second);
			return this;
		}

      	operator string(){
      		return protocol_ + " " + to_string(status_) +" "+ message_ + "\n\n" + body_;
      	}
    };

	string createResponse(char* req) noexcept{
		auto lines = utils::split(string(req), "\n");
		if(lines.empty())
			return Response(400, "Bad Request", "HTTP/1.1", "NN");

		auto tops = utils::split(lines[0], " ");
		if(tops.size() < 3)
			return Response(401, "Bad Request", "HTTP/1.1",  "NN");

		Log::debug(tops[0] +" "+ tops[1] +" "+ tops[2]);

		auto request = shared_ptr<Request>(new Request(tops[0],tops[1],tops[2]));

		if(context.routes.find(tops[1]) != context.routes.end()){
			return context.routes[tops[1]](move(request));
		}

		return Response( 404,"Not found", tops[2], "AA");
	}

	string receiveProcess(int sessionfd){
		char buf[BUF_SIZE] = {};

		if (recv(sessionfd, buf, sizeof(buf), 0) < 0) {
			exit(EXIT_FAILURE);
		}
		do{
			if(strstr(buf, "\r\n")){
				break;
			}
			if (strlen(buf) >= sizeof(buf)) {
				memset(&buf, 0, sizeof(buf));
			}
		}while(read(sessionfd, buf+strlen(buf), sizeof(buf) - strlen(buf)) > 0);
		return createResponse(buf);
	}

	void load(string directory, string filename) noexcept{
		if(filename == "." || filename == "..") return;
		if(filename!="")
			directory += "/" + filename;
		DIR* dir = opendir(directory.c_str());
		if(dir != NULL){
			struct dirent* dent;
	        dent = readdir(dir);
		    while(dent!=NULL){
		        dent = readdir(dir);
		        if(dent!=NULL)
			        load(directory, string(dent->d_name));
		    }
		    closedir(dir);
			delete dent;
			delete dir;
		}else{
			Log::debug("add "+directory);
			context.routes.insert( make_pair(
				"/" + directory,
				[directory,filename](std::shared_ptr<Request> request) -> Cappuccino::Response{
					return Response(200,"OK","HTTP/1.1",openFile(directory).first);
				}
			));
		}
	}

	void loadStaticFiles() noexcept{
		load(*context.static_root,"");
	}

	void route(string url,std::function<Response(std::shared_ptr<Request>)> F){
		context.routes.insert( make_pair( move(url), move(F) ));
	}

	void root(string r){
		context.view_root =  make_shared<string>(move(r));
	}

	void resource(string s){
		context.static_root = make_shared<string>(move(s));
	}

	void run(){

		init_socket();
		signal_utils::init_signal();
		loadStaticFiles();

	    int cd[FD_SETSIZE];
		struct sockaddr_in client;
        int    fd;
        struct timeval tv;

	    for(int i = 0;i < FD_SETSIZE; i++){
	        cd[i] = 0;
	    }

		int I = 0;
	    while(1) {

			if(I>5){
				return;
			}

	        tv.tv_sec = 0;
	        tv.tv_usec = 0;

	        memcpy(&context.mask2fds, &context.mask1fds, sizeof(context.mask1fds));

	        int select_result = select(FD_SETSIZE, &context.mask2fds, (fd_set *)0, (fd_set *)0, &tv);
	        if(select_result < 1) {
	            for(fd = 0; fd < FD_SETSIZE; fd++) {
	                if(cd[fd] == 1) {
	                    close(fd);
	                    FD_CLR(fd, &context.mask1fds);
	                    cd[fd] = 0;
	                }
	            }
	            continue;
	        }
			for(fd = 0; fd < FD_SETSIZE; fd++){
	            if(FD_ISSET(fd,&context.mask2fds)) {
	                if(fd == context.sockfd) {
	                	memset( &client, 0, sizeof(client));
						int len = sizeof(client);
	                    int clientfd = accept(context.sockfd,
	                        (struct sockaddr *)&client,(socklen_t *) &len);
	                        FD_SET(clientfd, &context.mask1fds);
	                }else {
	                    if(cd[fd] == 1) {
	                        close(fd);
	                        FD_CLR(fd, &context.mask1fds);
	                        cd[fd] = 0;
	                    } else {
							string response = receiveProcess(fd);
							write(fd, response.c_str(), response.size());
	                        cd[fd] = 1;

							I++;

	                    }
	                }
	            }
	        }
	    }
	}

	void Cappuccino(int argc, char *argv[]) {
		option(argc, argv);
		context.view_root = make_shared<string>("");
		context.static_root = make_shared<string>("public");
	}
};

namespace Cocoa{
	using namespace Cappuccino;
	using namespace std;

	// Unit Test
	void testOpenFile(){
		auto res = openFile("html/index.html");
		auto lines = utils::split(res.first, "\n");
		assert(!lines.empty());
	}

	void testOpenInvalidFile(){
		try{
			auto res = openFile("html/index");
		}catch(std::runtime_error e){
			cout<< e.what() << endl;
		}
	}
};

<|endoftext|>


<commit_before>#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <signal.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <dirent.h>
#include <fcntl.h>
#include <errno.h>
#include <string>
#include <functional>
#include <unordered_map>
#include <list>
#include <algorithm>
#include <iostream>
#include <sstream>
#include <map>

#if defined(__APPLE__) || defined(__GNUC__) && __GNUC__ * 10  + __GNUC_MINOR__ >= 49
#include <regex>
#endif

#include <vector>
#include <fstream>
#include <future>

#define BUF_SIZE 4096
#define MAX_LISTEN 128

namespace Cappuccino{

	namespace Log{
		static void debug(std::string msg){
			std::cout << msg << std::endl;
		}

		static void info(std::string msg){
			std::cout << msg << std::endl;
		}
	};

	class Request;
	class Response;

	struct {
		int port = 1204;
		int sockfd = 0;
		int sessionfd = 0;
	    fd_set mask1fds, mask2fds;

		std::shared_ptr<std::string> view_root;
		std::shared_ptr<std::string> static_root;

		std::map<std::string,
			std::function<
				std::unique_ptr<Response>(std::unique_ptr<Request>)
			>
		> routes;
	} context;

	namespace signal_utils{

		void signal_handler(int signal){
			close(context.sessionfd);
			close(context.sockfd);
			exit(0);
		}

		void signal_handler_child(int SignalName){
			while(waitpid(-1,NULL,WNOHANG)>0){}
	        signal(SIGCHLD, signal_utils::signal_handler_child);
		}

		void init_signal(){
			if(signal(SIGINT, signal_utils::signal_handler) == SIG_ERR){
				exit(1);
			}
			if(signal(SIGCHLD, signal_utils::signal_handler_child) == SIG_ERR){
				exit(1);
			}
		}
	}

	namespace utils{
		std::vector<std::string> split(const std::string& str, std::string delim) noexcept{
			std::vector<std::string> result;
		    std::string::size_type pos = 0;
		    while(pos != std::string::npos ){
		        std::string::size_type p = str.find(delim, pos);
		        if(p == std::string::npos){
		            result.push_back(str.substr(pos));
		            break;
		        }else{
		            result.push_back(str.substr(pos, p - pos));
		        }
		        pos = p + delim.size();
		    }
		    return result;
		}
	};

	void init_socket(){
	    struct sockaddr_in server;
		if((context.sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0){
			exit(EXIT_FAILURE);
		}
		memset( &server, 0, sizeof(server));
		server.sin_family = AF_INET;
		server.sin_addr.s_addr = INADDR_ANY;
		server.sin_port = htons(context.port);

		char opt = 1;
		setsockopt(context.sockfd, SOL_SOCKET, SO_REUSEADDR, (char *)&opt, sizeof(char));

		int temp = 1;
  		if(setsockopt(context.sockfd, SOL_SOCKET, SO_REUSEADDR,
	        &temp, sizeof(int))){
		}

		if (bind(context.sockfd, (struct sockaddr *) &server, sizeof(server)) < 0) {
			exit(EXIT_FAILURE);
		}

		if(listen(context.sockfd,  MAX_LISTEN) < 0) {
			exit(EXIT_FAILURE);
		}

	    FD_ZERO(&context.mask1fds);
	    FD_SET(context.sockfd, &context.mask1fds);
	}

	using namespace std;
	using string = string;

	void option(int argc, char *argv[]) noexcept{
		char result;
		while((result = getopt(argc,argv,"dp:")) != -1){
			switch(result){
			case 'd':
				break;
			case 'p':
				context.port = atoi(optarg);
				break;
			}
		}
	}

	class Request{

	};

    class Response{
		int status;
		string message;
      public:
		Response(int st,string msg){
			status = st;
			message = msg;
		}

		Response(string msg){
			message = msg;
		}

      	operator string(){
      		return to_string(status) + " / " + message;
      	}
    };

	Response create_response(char* req) noexcept{
		auto lines = utils::split(string(req), "\n");
		if(lines.empty())
			return Response(400, "Bad Request");

		cout << lines[0] << endl;

		return Response( 200, "OK");
	}

	string receive_process(int sessionfd){
		char buf[BUF_SIZE] = {};
		char method[BUF_SIZE] = {};
		char url[BUF_SIZE] = {};
		char protocol[BUF_SIZE] = {};

		if (recv(sessionfd, buf, sizeof(buf), 0) < 0) {
			exit(EXIT_FAILURE);
		}
		do{
			if(strstr(buf, "\r\n")){
				break;
			}
			if (strlen(buf) >= sizeof(buf)) {
				memset(&buf, 0, sizeof(buf));
			}
		}while(read(sessionfd, buf+strlen(buf), sizeof(buf) - strlen(buf)) > 0);
		return create_response(buf);
	}

	string openFile(string filename){

	}

	time_t client_info[FD_SETSIZE];

	void load(string directory, string filename) noexcept{
		if(filename == "." || filename == "..") return;
		if(filename!="")
			directory += "/" + filename;
		DIR* dir = opendir(directory.c_str());
		if(dir != NULL){
			struct dirent* dent;
	        dent = readdir(dir);
		    while(dent!=NULL){
		        dent = readdir(dir);
		        if(dent!=NULL)
			        load(directory, string(dent->d_name));
		    }
		    closedir(dir);
		}else{
//			auto static_file = Cappuccino::FileLoader(directory);
//			static_file.preload();
			context.routes.insert( make_pair(
				directory +"/" + filename,
				[directory,filename](std::unique_ptr<Request> request) -> std::unique_ptr<Cappuccino::Response>{
					return unique_ptr<Cappuccino::Response>(new Cappuccino::Response(openFile(directory +"/" + filename)));
				}
			));
		}
	}

	void load_static_files() noexcept{
		load(*context.static_root,"");
	}

	void run(){

		context.view_root = make_shared<string>("");
		context.static_root = make_shared<string>("public");

		init_socket();
		signal_utils::init_signal();
		load_static_files();

	    int cd[FD_SETSIZE];
		struct sockaddr_in client;
        int    fd;
        struct timeval tv;

	    for(int i = 0;i < FD_SETSIZE; i++){
	        cd[i] = 0;
	    }

	    while(1) {
	        tv.tv_sec = 0;
	        tv.tv_usec = 0;

	        memcpy(&context.mask2fds, &context.mask1fds, sizeof(context.mask1fds));

	        int select_result = select(FD_SETSIZE, &context.mask2fds, (fd_set *)0, (fd_set *)0, &tv);
	        if(select_result < 1) {
	            for(fd = 0; fd < FD_SETSIZE; fd++) {
	                if(cd[fd] == 1) {
	                    close(fd);
	                    FD_CLR(fd, &context.mask1fds);
	                    cd[fd] = 0;
	                }
	            }
	            continue;
	        }
	        for(fd = 0; fd < FD_SETSIZE; fd++){
	            if(FD_ISSET(fd,&context.mask2fds)) {
	                if(fd == context.sockfd) {
	                	memset( &client, 0, sizeof(client));
						int len = sizeof(client);
	                    int clientfd = accept(context.sockfd, (struct sockaddr *)&client,(socklen_t *) &len);
                        FD_SET(clientfd, &context.mask1fds);
	                }else {
	                    if(cd[fd] == 1) {
	                        close(fd);
	                        FD_CLR(fd, &context.mask1fds);
	                        cd[fd] = 0;
	                    } else {
							string response = receive_process(fd);
							write(fd, response.c_str(), response.size());
	                        cd[fd] = 1;
	                    }
	                }
	            }
	        }
	    }
	}

	void Cappuccino(int argc, char *argv[]) {
		option(argc, argv);
	}
};

namespace Cocoa{
	class App{};
};

<commit_msg>[Write] Request<commit_after>#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <signal.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <dirent.h>
#include <fcntl.h>
#include <errno.h>
#include <string>
#include <functional>
#include <unordered_map>
#include <list>
#include <algorithm>
#include <iostream>
#include <sstream>
#include <map>

#if defined(__APPLE__) || defined(__GNUC__) && __GNUC__ * 10  + __GNUC_MINOR__ >= 49
#include <regex>
#endif

#include <vector>
#include <fstream>
#include <future>

#define BUF_SIZE 4096
#define MAX_LISTEN 128

namespace Cappuccino{

	namespace Log{
		static void debug(std::string msg){
			std::cout << msg << std::endl;
		}

		static void info(std::string msg){
			std::cout << msg << std::endl;
		}
	};

	class Request;
	class Response;

	struct {
		int port = 1204;
		int sockfd = 0;
		int sessionfd = 0;
	    fd_set mask1fds, mask2fds;

		std::shared_ptr<std::string> view_root;
		std::shared_ptr<std::string> static_root;

		std::map<std::string,
			std::function<
				std::unique_ptr<Response>(std::unique_ptr<Request>)
			>
		> routes;
	} context;

	namespace signal_utils{

		void signal_handler(int signal){
			close(context.sessionfd);
			close(context.sockfd);
			exit(0);
		}

		void signal_handler_child(int SignalName){
			while(waitpid(-1,NULL,WNOHANG)>0){}
	        signal(SIGCHLD, signal_utils::signal_handler_child);
		}

		void init_signal(){
			if(signal(SIGINT, signal_utils::signal_handler) == SIG_ERR){
				exit(1);
			}
			if(signal(SIGCHLD, signal_utils::signal_handler_child) == SIG_ERR){
				exit(1);
			}
		}
	}

	namespace utils{
		std::vector<std::string> split(const std::string& str, std::string delim) noexcept{
			std::vector<std::string> result;
		    std::string::size_type pos = 0;
		    while(pos != std::string::npos ){
		        std::string::size_type p = str.find(delim, pos);
		        if(p == std::string::npos){
		            result.push_back(str.substr(pos));
		            break;
		        }else{
		            result.push_back(str.substr(pos, p - pos));
		        }
		        pos = p + delim.size();
		    }
		    return result;
		}
	};

	void init_socket(){
	    struct sockaddr_in server;
		if((context.sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0){
			exit(EXIT_FAILURE);
		}
		memset( &server, 0, sizeof(server));
		server.sin_family = AF_INET;
		server.sin_addr.s_addr = INADDR_ANY;
		server.sin_port = htons(context.port);

		char opt = 1;
		setsockopt(context.sockfd, SOL_SOCKET, SO_REUSEADDR, (char *)&opt, sizeof(char));

		int temp = 1;
  		if(setsockopt(context.sockfd, SOL_SOCKET, SO_REUSEADDR,
	        &temp, sizeof(int))){
		}

		if (bind(context.sockfd, (struct sockaddr *) &server, sizeof(server)) < 0) {
			exit(EXIT_FAILURE);
		}

		if(listen(context.sockfd,  MAX_LISTEN) < 0) {
			exit(EXIT_FAILURE);
		}

	    FD_ZERO(&context.mask1fds);
	    FD_SET(context.sockfd, &context.mask1fds);
	}

	using namespace std;

	void option(int argc, char *argv[]) noexcept{
		char result;
		while((result = getopt(argc,argv,"dp:")) != -1){
			switch(result){
			case 'd':
				break;
			case 'p':
				context.port = atoi(optarg);
				break;
			}
		}
	}

	class Request{
		map<string, string> headerset;
		map<string, string> paramset;
	  public:
		Request(string method, string url,string protocol):
		method(method),
		url(url),
		protocol(protocol)
		{}

		const string method;
		const string url;
		const string protocol;

		void addHeader(string key,string value){
			headerset[key] = value;
		}

		void addParams(string key,string value){
			paramset[key] = value;
		}

		string header(string key){
			if(headerset.find(key) == headerset.end())
				return "INVALID";
			return headerset[key];
		}

		string params(string key){
			if(paramset.find(key) == paramset.end())
				return "INVALID";
			return paramset[key];
		}

	};

    class Response{
		int status;
		string message;
      public:
		Response(int st,string msg){
			status = st;
			message = msg;
		}

		Response(string msg){
			message = msg;
		}

      	operator string(){
      		return to_string(status) + " / " + message;
      	}
    };

	Response create_response(char* req) noexcept{
		auto lines = utils::split(string(req), "\n");
		if(lines.empty())
			return Response(400, "Bad Request");

		cout << lines[0] << endl;

		return Response( 200, "OK");
	}

	string receive_process(int sessionfd){
		char buf[BUF_SIZE] = {};
		char method[BUF_SIZE] = {};
		char url[BUF_SIZE] = {};
		char protocol[BUF_SIZE] = {};

		if (recv(sessionfd, buf, sizeof(buf), 0) < 0) {
			exit(EXIT_FAILURE);
		}
		do{
			if(strstr(buf, "\r\n")){
				break;
			}
			if (strlen(buf) >= sizeof(buf)) {
				memset(&buf, 0, sizeof(buf));
			}
		}while(read(sessionfd, buf+strlen(buf), sizeof(buf) - strlen(buf)) > 0);
		return create_response(buf);
	}

	string openFile(string filename){

	}

	time_t client_info[FD_SETSIZE];

	void load(string directory, string filename) noexcept{
		if(filename == "." || filename == "..") return;
		if(filename!="")
			directory += "/" + filename;
		DIR* dir = opendir(directory.c_str());
		if(dir != NULL){
			struct dirent* dent;
	        dent = readdir(dir);
		    while(dent!=NULL){
		        dent = readdir(dir);
		        if(dent!=NULL)
			        load(directory, string(dent->d_name));
		    }
		    closedir(dir);
		}else{
//			auto static_file = Cappuccino::FileLoader(directory);
//			static_file.preload();
			context.routes.insert( make_pair(
				directory +"/" + filename,
				[directory,filename](std::unique_ptr<Request> request) -> std::unique_ptr<Cappuccino::Response>{
					return unique_ptr<Cappuccino::Response>(new Cappuccino::Response(openFile(directory +"/" + filename)));
				}
			));
		}
	}

	void load_static_files() noexcept{
		load(*context.static_root,"");
	}

	void run(){

		context.view_root = make_shared<string>("");
		context.static_root = make_shared<string>("public");

		init_socket();
		signal_utils::init_signal();
		load_static_files();

	    int cd[FD_SETSIZE];
		struct sockaddr_in client;
        int    fd;
        struct timeval tv;

	    for(int i = 0;i < FD_SETSIZE; i++){
	        cd[i] = 0;
	    }

	    while(1) {
	        tv.tv_sec = 0;
	        tv.tv_usec = 0;

	        memcpy(&context.mask2fds, &context.mask1fds, sizeof(context.mask1fds));

	        int select_result = select(FD_SETSIZE, &context.mask2fds, (fd_set *)0, (fd_set *)0, &tv);
	        if(select_result < 1) {
	            for(fd = 0; fd < FD_SETSIZE; fd++) {
	                if(cd[fd] == 1) {
	                    close(fd);
	                    FD_CLR(fd, &context.mask1fds);
	                    cd[fd] = 0;
	                }
	            }
	            continue;
	        }
	        for(fd = 0; fd < FD_SETSIZE; fd++){
	            if(FD_ISSET(fd,&context.mask2fds)) {
	                if(fd == context.sockfd) {
	                	memset( &client, 0, sizeof(client));
						int len = sizeof(client);
	                    int clientfd = accept(context.sockfd, (struct sockaddr *)&client,(socklen_t *) &len);
                        FD_SET(clientfd, &context.mask1fds);
	                }else {
	                    if(cd[fd] == 1) {
	                        close(fd);
	                        FD_CLR(fd, &context.mask1fds);
	                        cd[fd] = 0;
	                    } else {
							string response = receive_process(fd);
							write(fd, response.c_str(), response.size());
	                        cd[fd] = 1;
	                    }
	                }
	            }
	        }
	    }
	}

	void Cappuccino(int argc, char *argv[]) {
		option(argc, argv);
	}
};

namespace Cocoa{
	class App{};
};

<|endoftext|>


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

//------------------------------------------------------------------------
// includes
//------------------------------------------------------------------------

#ifndef _OSL_DIAGNOSE_H_
#include <osl/diagnose.h>
#endif

#ifndef _OSL_THREAD_H_
#include <osl/thread.h>
#endif

#ifndef _OSL_PROCESS_H_
#include <osl/process.h>
#endif

#ifndef _OSL_FILE_HXX_
#include <osl/file.hxx>
#endif

#ifndef _RTL_STRBUF_HXX_
#include <rtl/strbuf.hxx>
#endif

#ifndef _CMDMAILSUPPL_HXX_
#include "cmdmailsuppl.hxx"
#endif

#ifndef _CMDMAILMSG_HXX_
#include "cmdmailmsg.hxx"
#endif

#ifndef _COM_SUN_STAR_SYSTEM_SIMPLEMAILCLIENTFLAGS_HPP_
#include <com/sun/star/system/SimpleMailClientFlags.hpp>
#endif

#ifndef _COM_SUN_STAR_CONTAINER_XNAMEACCESS_HPP_
#include <com/sun/star/container/XNameAccess.hpp>
#endif

#ifndef _COM_SUN_STAR_BEANS_PROPERTYVALUE_HPP_
#include <com/sun/star/beans/PropertyValue.hpp>
#endif

#ifndef _COM_SUN_STAR_BEANS_XPROPERTYSET_HPP_
#include <com/sun/star/beans/XPropertySet.hpp>
#endif

#ifndef _COM_SUN_STAR_UNO_XCOMPONENTCONTEXT_HPP_
#include <com/sun/star/uno/XComponentContext.hpp>
#endif

#include <string.h>
#include <errno.h>
#include <unistd.h>

//------------------------------------------------------------------------
// namespace directives
//------------------------------------------------------------------------

using com::sun::star::beans::PropertyValue;
using com::sun::star::system::XSimpleMailClientSupplier;
using com::sun::star::system::XSimpleMailClient;
using com::sun::star::system::XSimpleMailMessage;
using com::sun::star::container::XNameAccess;
using com::sun::star::container::NoSuchElementException;
using rtl::OUString;
using rtl::OUStringToOString;
using rtl::OString;
using rtl::OStringBuffer;
using osl::MutexGuard;
using osl::FileBase;

using namespace cppu;
using namespace com::sun::star::system::SimpleMailClientFlags;
using namespace com::sun::star::uno;
using namespace com::sun::star::lang;

//------------------------------------------------------------------------
// defines
//------------------------------------------------------------------------

#define COMP_IMPL_NAME  "com.sun.star.comp.system.SimpleCommandMail2"

//------------------------------------------------------------------------
// helper functions
//------------------------------------------------------------------------

namespace // private
{
    Sequence< OUString > SAL_CALL Component_getSupportedServiceNames()
    {
        Sequence< OUString > aRet(1);
        aRet[0] = OUString::createFromAscii("com.sun.star.system.SimpleCommandMail");
        return aRet;
    }

} // end private namespace

//-------------------------------------------------
//
//-------------------------------------------------

CmdMailSuppl::CmdMailSuppl( const Reference< XComponentContext >& xContext ) :
    WeakImplHelper3< XSimpleMailClientSupplier, XSimpleMailClient, XServiceInfo >()
{
    Reference< XMultiComponentFactory > xServiceManager = xContext->getServiceManager();

    if ( xServiceManager.is() ) {
        m_xConfigurationProvider = Reference< XMultiServiceFactory > (
            xServiceManager->createInstanceWithContext(
                OUString::createFromAscii( "com.sun.star.configuration.ConfigurationProvider" ), xContext ),
            UNO_QUERY );
    }
}

//-------------------------------------------------
// XSimpleMailClientSupplier
//-------------------------------------------------

Reference< XSimpleMailClient > SAL_CALL CmdMailSuppl::querySimpleMailClient(  )
    throw (RuntimeException)
{
    return static_cast < XSimpleMailClient * > (this);
}

//------------------------------------------------
// XSimpleMailClient
//------------------------------------------------

Reference< XSimpleMailMessage > SAL_CALL CmdMailSuppl::createSimpleMailMessage(  )
        throw (::com::sun::star::uno::RuntimeException)
{
    return Reference< XSimpleMailMessage >( new CmdMailMsg(  ) );
}

//------------------------------------------------
// XSimpleMailClient
//------------------------------------------------

void SAL_CALL CmdMailSuppl::sendSimpleMailMessage( const Reference< XSimpleMailMessage >& xSimpleMailMessage, sal_Int32 aFlag )
    throw (IllegalArgumentException, Exception, RuntimeException)
{
    if ( ! xSimpleMailMessage.is() )
    {
        throw ::com::sun::star::lang::IllegalArgumentException(
            OUString(RTL_CONSTASCII_USTRINGPARAM( "No message specified" )),
            static_cast < XSimpleMailClient * > (this), 1 );
    }

    if( ! m_xConfigurationProvider.is() )
    {
        throw ::com::sun::star::uno::Exception(
            OUString(RTL_CONSTASCII_USTRINGPARAM( "Can not access configuration" )),
            static_cast < XSimpleMailClient * > (this) );
    }

    OStringBuffer aBuffer;

    OUString aProgramURL;
    if ( osl_Process_E_None != osl_getExecutableFile(&aProgramURL.pData) )
    {
        throw ::com::sun::star::uno::Exception(
            OUString(RTL_CONSTASCII_USTRINGPARAM("Cound not determine executable path")),
            static_cast < XSimpleMailClient * > (this));
    }

    OUString aProgram;
    if ( FileBase::E_None != FileBase::getSystemPathFromFileURL(aProgramURL, aProgram))
    {
        throw ::com::sun::star::uno::Exception(
            OUString(RTL_CONSTASCII_USTRINGPARAM("Cound not convert executable path")),
            static_cast < XSimpleMailClient * > (this));
    }

    // The mail client launchers are expected to be in the same directory as the main
    // executable, so prefixing the launchers with the path of the executable including
    // the last slash
    OString aTmp = OUStringToOString(aProgram, osl_getThreadTextEncoding());
    sal_Int32 nIndex = aTmp.lastIndexOf('/');
    if (nIndex > 0)
        aBuffer.append(aTmp.copy(0, nIndex+1));

    aBuffer.append("senddoc ");

    try
    {
        // Query XNameAccess interface of the org.openoffice.Office.Common/ExternalMailer
        // configuration node to retriece the users preferred email application. This may
        // transparently by redirected to e.g. the corresponding GConf setting in GNOME.
        OUString aConfigRoot = OUString(
            RTL_CONSTASCII_USTRINGPARAM( "org.openoffice.Office.Common/ExternalMailer" ) );

        PropertyValue aProperty;
        aProperty.Name = OUString::createFromAscii( "nodepath" );
        aProperty.Value = makeAny( aConfigRoot );

        Sequence< Any > aArgumentList( 1 );
        aArgumentList[0] = makeAny( aProperty );

        Reference< XNameAccess > xNameAccess =
            Reference< XNameAccess > (
                m_xConfigurationProvider->createInstanceWithArguments(
                    OUString::createFromAscii( "com.sun.star.configuration.ConfigurationAccess" ),
                    aArgumentList ),
                UNO_QUERY );

        if( xNameAccess.is() )
        {
            OUString aMailer;

            // Retrieve the value for "Program" node and append it feed senddoc with it
            // using the (undocumented) --mailclient switch
            xNameAccess->getByName( OUString::createFromAscii( "Program" ) ) >>= aMailer;

            if( aMailer.getLength() )
            {
                // make sure we have a system path
                FileBase::getSystemPathFromFileURL( aMailer, aMailer );

                aBuffer.append("--mailclient ");
                aBuffer.append(OUStringToOString( aMailer, osl_getThreadTextEncoding() ));
                aBuffer.append(" ");
            }
        }

    }

    catch( RuntimeException e )
    {
        m_xConfigurationProvider.clear();
        OSL_TRACE( "RuntimeException caught accessing configuration provider." );
        OSL_TRACE( OUStringToOString( e.Message, RTL_TEXTENCODING_ASCII_US ).getStr() );
        throw e;
    }

    // Append originator if set in the message
    if ( xSimpleMailMessage->getOriginator().getLength() > 0 )
    {
        aBuffer.append("--from \"");
        aBuffer.append(OUStringToOString(xSimpleMailMessage->getOriginator(), osl_getThreadTextEncoding()));
        aBuffer.append("\" ");
    }

    // Append receipient if set in the message
    if ( xSimpleMailMessage->getRecipient().getLength() > 0 )
    {
        aBuffer.append("--to \"");
        aBuffer.append(OUStringToOString(xSimpleMailMessage->getRecipient(), osl_getThreadTextEncoding()));
        aBuffer.append("\" ");
    }

    // Append carbon copy receipients set in the message
    Sequence< OUString > aStringList = xSimpleMailMessage->getCcRecipient();
    sal_Int32 n, nmax = aStringList.getLength();
    for ( n = 0; n < nmax; n++ )
    {
        aBuffer.append("--cc \"");
        aBuffer.append(OUStringToOString(aStringList[n], osl_getThreadTextEncoding()));
        aBuffer.append("\" ");
    }

    // Append blind carbon copy receipients set in the message
    aStringList = xSimpleMailMessage->getBccRecipient();
    nmax = aStringList.getLength();
    for ( n = 0; n < nmax; n++ )
    {
        aBuffer.append("--bcc \"");
        aBuffer.append(OUStringToOString(aStringList[n], osl_getThreadTextEncoding()));
        aBuffer.append("\" ");
    }

    // Append subject if set in the message
    if ( xSimpleMailMessage->getSubject().getLength() > 0 )
    {
        aBuffer.append("--subject \"");
        aBuffer.append(OUStringToOString(xSimpleMailMessage->getSubject(), osl_getThreadTextEncoding()));
        aBuffer.append("\" ");
    }

    // Append attachments set in the message
    aStringList = xSimpleMailMessage->getAttachement();
    nmax = aStringList.getLength();
    for ( n = 0; n < nmax; n++ )
    {
        OUString aSystemPath;
        if ( FileBase::E_None == FileBase::getSystemPathFromFileURL(aStringList[n], aSystemPath) )
        {
            aBuffer.append("--attach \"");
            aBuffer.append(OUStringToOString(aSystemPath, RTL_TEXTENCODING_UTF8));
            aBuffer.append("\" ");
        }
    }

    OString cmd = aBuffer.makeStringAndClear();
    if ( 0 != pclose(popen(cmd.getStr(), "w")) )
    {
        throw ::com::sun::star::uno::Exception(
            OUString(RTL_CONSTASCII_USTRINGPARAM( "No mail client configured" )),
            static_cast < XSimpleMailClient * > (this) );
    }
}

// -------------------------------------------------
// XServiceInfo
// -------------------------------------------------

OUString SAL_CALL CmdMailSuppl::getImplementationName(  )
    throw( RuntimeException )
{
    return OUString::createFromAscii( COMP_IMPL_NAME );
}

// -------------------------------------------------
//  XServiceInfo
// -------------------------------------------------

sal_Bool SAL_CALL CmdMailSuppl::supportsService( const OUString& ServiceName )
    throw( RuntimeException )
{
    Sequence < OUString > SupportedServicesNames = Component_getSupportedServiceNames();

    for ( sal_Int32 n = SupportedServicesNames.getLength(); n--; )
        if (SupportedServicesNames[n].compareTo(ServiceName) == 0)
            return sal_True;

    return sal_False;
}

// -------------------------------------------------
//  XServiceInfo
// -------------------------------------------------

Sequence< OUString > SAL_CALL CmdMailSuppl::getSupportedServiceNames(    )
    throw( RuntimeException )
{
    return Component_getSupportedServiceNames();
}

<commit_msg>INTEGRATION: CWS ooo19126 (1.9.70); FILE MERGED 2005/09/05 14:05:03 rt 1.9.70.1: #i54170# Change license header: remove SISSL<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: cmdmailsuppl.cxx,v $
 *
 *  $Revision: 1.10 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-07 19:51:53 $
 *
 *  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
 *
 ************************************************************************/

//------------------------------------------------------------------------
// includes
//------------------------------------------------------------------------

#ifndef _OSL_DIAGNOSE_H_
#include <osl/diagnose.h>
#endif

#ifndef _OSL_THREAD_H_
#include <osl/thread.h>
#endif

#ifndef _OSL_PROCESS_H_
#include <osl/process.h>
#endif

#ifndef _OSL_FILE_HXX_
#include <osl/file.hxx>
#endif

#ifndef _RTL_STRBUF_HXX_
#include <rtl/strbuf.hxx>
#endif

#ifndef _CMDMAILSUPPL_HXX_
#include "cmdmailsuppl.hxx"
#endif

#ifndef _CMDMAILMSG_HXX_
#include "cmdmailmsg.hxx"
#endif

#ifndef _COM_SUN_STAR_SYSTEM_SIMPLEMAILCLIENTFLAGS_HPP_
#include <com/sun/star/system/SimpleMailClientFlags.hpp>
#endif

#ifndef _COM_SUN_STAR_CONTAINER_XNAMEACCESS_HPP_
#include <com/sun/star/container/XNameAccess.hpp>
#endif

#ifndef _COM_SUN_STAR_BEANS_PROPERTYVALUE_HPP_
#include <com/sun/star/beans/PropertyValue.hpp>
#endif

#ifndef _COM_SUN_STAR_BEANS_XPROPERTYSET_HPP_
#include <com/sun/star/beans/XPropertySet.hpp>
#endif

#ifndef _COM_SUN_STAR_UNO_XCOMPONENTCONTEXT_HPP_
#include <com/sun/star/uno/XComponentContext.hpp>
#endif

#include <string.h>
#include <errno.h>
#include <unistd.h>

//------------------------------------------------------------------------
// namespace directives
//------------------------------------------------------------------------

using com::sun::star::beans::PropertyValue;
using com::sun::star::system::XSimpleMailClientSupplier;
using com::sun::star::system::XSimpleMailClient;
using com::sun::star::system::XSimpleMailMessage;
using com::sun::star::container::XNameAccess;
using com::sun::star::container::NoSuchElementException;
using rtl::OUString;
using rtl::OUStringToOString;
using rtl::OString;
using rtl::OStringBuffer;
using osl::MutexGuard;
using osl::FileBase;

using namespace cppu;
using namespace com::sun::star::system::SimpleMailClientFlags;
using namespace com::sun::star::uno;
using namespace com::sun::star::lang;

//------------------------------------------------------------------------
// defines
//------------------------------------------------------------------------

#define COMP_IMPL_NAME  "com.sun.star.comp.system.SimpleCommandMail2"

//------------------------------------------------------------------------
// helper functions
//------------------------------------------------------------------------

namespace // private
{
    Sequence< OUString > SAL_CALL Component_getSupportedServiceNames()
    {
        Sequence< OUString > aRet(1);
        aRet[0] = OUString::createFromAscii("com.sun.star.system.SimpleCommandMail");
        return aRet;
    }

} // end private namespace

//-------------------------------------------------
//
//-------------------------------------------------

CmdMailSuppl::CmdMailSuppl( const Reference< XComponentContext >& xContext ) :
    WeakImplHelper3< XSimpleMailClientSupplier, XSimpleMailClient, XServiceInfo >()
{
    Reference< XMultiComponentFactory > xServiceManager = xContext->getServiceManager();

    if ( xServiceManager.is() ) {
        m_xConfigurationProvider = Reference< XMultiServiceFactory > (
            xServiceManager->createInstanceWithContext(
                OUString::createFromAscii( "com.sun.star.configuration.ConfigurationProvider" ), xContext ),
            UNO_QUERY );
    }
}

//-------------------------------------------------
// XSimpleMailClientSupplier
//-------------------------------------------------

Reference< XSimpleMailClient > SAL_CALL CmdMailSuppl::querySimpleMailClient(  )
    throw (RuntimeException)
{
    return static_cast < XSimpleMailClient * > (this);
}

//------------------------------------------------
// XSimpleMailClient
//------------------------------------------------

Reference< XSimpleMailMessage > SAL_CALL CmdMailSuppl::createSimpleMailMessage(  )
        throw (::com::sun::star::uno::RuntimeException)
{
    return Reference< XSimpleMailMessage >( new CmdMailMsg(  ) );
}

//------------------------------------------------
// XSimpleMailClient
//------------------------------------------------

void SAL_CALL CmdMailSuppl::sendSimpleMailMessage( const Reference< XSimpleMailMessage >& xSimpleMailMessage, sal_Int32 aFlag )
    throw (IllegalArgumentException, Exception, RuntimeException)
{
    if ( ! xSimpleMailMessage.is() )
    {
        throw ::com::sun::star::lang::IllegalArgumentException(
            OUString(RTL_CONSTASCII_USTRINGPARAM( "No message specified" )),
            static_cast < XSimpleMailClient * > (this), 1 );
    }

    if( ! m_xConfigurationProvider.is() )
    {
        throw ::com::sun::star::uno::Exception(
            OUString(RTL_CONSTASCII_USTRINGPARAM( "Can not access configuration" )),
            static_cast < XSimpleMailClient * > (this) );
    }

    OStringBuffer aBuffer;

    OUString aProgramURL;
    if ( osl_Process_E_None != osl_getExecutableFile(&aProgramURL.pData) )
    {
        throw ::com::sun::star::uno::Exception(
            OUString(RTL_CONSTASCII_USTRINGPARAM("Cound not determine executable path")),
            static_cast < XSimpleMailClient * > (this));
    }

    OUString aProgram;
    if ( FileBase::E_None != FileBase::getSystemPathFromFileURL(aProgramURL, aProgram))
    {
        throw ::com::sun::star::uno::Exception(
            OUString(RTL_CONSTASCII_USTRINGPARAM("Cound not convert executable path")),
            static_cast < XSimpleMailClient * > (this));
    }

    // The mail client launchers are expected to be in the same directory as the main
    // executable, so prefixing the launchers with the path of the executable including
    // the last slash
    OString aTmp = OUStringToOString(aProgram, osl_getThreadTextEncoding());
    sal_Int32 nIndex = aTmp.lastIndexOf('/');
    if (nIndex > 0)
        aBuffer.append(aTmp.copy(0, nIndex+1));

    aBuffer.append("senddoc ");

    try
    {
        // Query XNameAccess interface of the org.openoffice.Office.Common/ExternalMailer
        // configuration node to retriece the users preferred email application. This may
        // transparently by redirected to e.g. the corresponding GConf setting in GNOME.
        OUString aConfigRoot = OUString(
            RTL_CONSTASCII_USTRINGPARAM( "org.openoffice.Office.Common/ExternalMailer" ) );

        PropertyValue aProperty;
        aProperty.Name = OUString::createFromAscii( "nodepath" );
        aProperty.Value = makeAny( aConfigRoot );

        Sequence< Any > aArgumentList( 1 );
        aArgumentList[0] = makeAny( aProperty );

        Reference< XNameAccess > xNameAccess =
            Reference< XNameAccess > (
                m_xConfigurationProvider->createInstanceWithArguments(
                    OUString::createFromAscii( "com.sun.star.configuration.ConfigurationAccess" ),
                    aArgumentList ),
                UNO_QUERY );

        if( xNameAccess.is() )
        {
            OUString aMailer;

            // Retrieve the value for "Program" node and append it feed senddoc with it
            // using the (undocumented) --mailclient switch
            xNameAccess->getByName( OUString::createFromAscii( "Program" ) ) >>= aMailer;

            if( aMailer.getLength() )
            {
                // make sure we have a system path
                FileBase::getSystemPathFromFileURL( aMailer, aMailer );

                aBuffer.append("--mailclient ");
                aBuffer.append(OUStringToOString( aMailer, osl_getThreadTextEncoding() ));
                aBuffer.append(" ");
            }
        }

    }

    catch( RuntimeException e )
    {
        m_xConfigurationProvider.clear();
        OSL_TRACE( "RuntimeException caught accessing configuration provider." );
        OSL_TRACE( OUStringToOString( e.Message, RTL_TEXTENCODING_ASCII_US ).getStr() );
        throw e;
    }

    // Append originator if set in the message
    if ( xSimpleMailMessage->getOriginator().getLength() > 0 )
    {
        aBuffer.append("--from \"");
        aBuffer.append(OUStringToOString(xSimpleMailMessage->getOriginator(), osl_getThreadTextEncoding()));
        aBuffer.append("\" ");
    }

    // Append receipient if set in the message
    if ( xSimpleMailMessage->getRecipient().getLength() > 0 )
    {
        aBuffer.append("--to \"");
        aBuffer.append(OUStringToOString(xSimpleMailMessage->getRecipient(), osl_getThreadTextEncoding()));
        aBuffer.append("\" ");
    }

    // Append carbon copy receipients set in the message
    Sequence< OUString > aStringList = xSimpleMailMessage->getCcRecipient();
    sal_Int32 n, nmax = aStringList.getLength();
    for ( n = 0; n < nmax; n++ )
    {
        aBuffer.append("--cc \"");
        aBuffer.append(OUStringToOString(aStringList[n], osl_getThreadTextEncoding()));
        aBuffer.append("\" ");
    }

    // Append blind carbon copy receipients set in the message
    aStringList = xSimpleMailMessage->getBccRecipient();
    nmax = aStringList.getLength();
    for ( n = 0; n < nmax; n++ )
    {
        aBuffer.append("--bcc \"");
        aBuffer.append(OUStringToOString(aStringList[n], osl_getThreadTextEncoding()));
        aBuffer.append("\" ");
    }

    // Append subject if set in the message
    if ( xSimpleMailMessage->getSubject().getLength() > 0 )
    {
        aBuffer.append("--subject \"");
        aBuffer.append(OUStringToOString(xSimpleMailMessage->getSubject(), osl_getThreadTextEncoding()));
        aBuffer.append("\" ");
    }

    // Append attachments set in the message
    aStringList = xSimpleMailMessage->getAttachement();
    nmax = aStringList.getLength();
    for ( n = 0; n < nmax; n++ )
    {
        OUString aSystemPath;
        if ( FileBase::E_None == FileBase::getSystemPathFromFileURL(aStringList[n], aSystemPath) )
        {
            aBuffer.append("--attach \"");
            aBuffer.append(OUStringToOString(aSystemPath, RTL_TEXTENCODING_UTF8));
            aBuffer.append("\" ");
        }
    }

    OString cmd = aBuffer.makeStringAndClear();
    if ( 0 != pclose(popen(cmd.getStr(), "w")) )
    {
        throw ::com::sun::star::uno::Exception(
            OUString(RTL_CONSTASCII_USTRINGPARAM( "No mail client configured" )),
            static_cast < XSimpleMailClient * > (this) );
    }
}

// -------------------------------------------------
// XServiceInfo
// -------------------------------------------------

OUString SAL_CALL CmdMailSuppl::getImplementationName(  )
    throw( RuntimeException )
{
    return OUString::createFromAscii( COMP_IMPL_NAME );
}

// -------------------------------------------------
//  XServiceInfo
// -------------------------------------------------

sal_Bool SAL_CALL CmdMailSuppl::supportsService( const OUString& ServiceName )
    throw( RuntimeException )
{
    Sequence < OUString > SupportedServicesNames = Component_getSupportedServiceNames();

    for ( sal_Int32 n = SupportedServicesNames.getLength(); n--; )
        if (SupportedServicesNames[n].compareTo(ServiceName) == 0)
            return sal_True;

    return sal_False;
}

// -------------------------------------------------
//  XServiceInfo
// -------------------------------------------------

Sequence< OUString > SAL_CALL CmdMailSuppl::getSupportedServiceNames(    )
    throw( RuntimeException )
{
    return Component_getSupportedServiceNames();
}

<|endoftext|>