<commit_before>/*
 * Copyright (c) 2012 Bernhard Firner and Rutgers University
 * All rights reserved.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
 * or visit http://www.gnu.org/licenses/gpl-2.0.html
 */

/*******************************************************************************
 * @file binary_state_solver.cpp
 * Offer binary solutions to the world model based upon binary sensors,
 * such as door switches, on/off power switches, etc.
 *
 * @author Bernhard Firner
 ******************************************************************************/

#include <algorithm>
#include <array>
#include <fstream>
#include <iostream>
#include <map>
#include <string>
#include <time.h>
#include <unistd.h>
#include <utility>
#include <vector>
#include <sstream>

//Handle interrupt signals to exit cleanly.
#include <signal.h>

#include <owl/netbuffer.hpp>
#include <owl/solver_aggregator_connection.hpp>
#include <owl/solver_world_connection.hpp>
#include <owl/sample_data.hpp>
#include <owl/world_model_protocol.hpp>
#include <owl/grail_types.hpp>

#include <owl/client_world_connection.hpp>

using namespace aggregator_solver;

using std::pair;

using world_model::Attribute;
using world_model::grail_time;
using world_model::URI;

//Global variable for the signal handler.
bool interrupted = false;
//Signal handler.
void handler(int signal) {
  psignal( signal, "Received signal ");
  if (interrupted) {
    std::cerr<<"Aborting.\n";
    // This is the second time we've received the interrupt, so just exit.
    exit(-1);
  }
  std::cerr<<"Shutting down...\n";
  interrupted = true;
}

std::u16string toU16(const std::string& str) {
  return std::u16string(str.begin(), str.end());
}

std::string toString(const std::u16string& str) {
  return std::string(str.begin(), str.end());
}

int main(int arg_count, char** arg_vector) {
  if (arg_count == 2 and std::string(arg_vector[1]) == "-?") {
    std::cout<< "name: Switch Solver\n";
    std::cout<< "arguments: worldmodel wm_solver wm_client config_file\n";
    std::cout<< "description: Monitors status of simple on/off switches.\n";
    std::cout<< "requires: 'binary state'\n";
    std::cout<< "config_file: tuple* 2 An item class (eg. door) and the name for its state when the switch is on (eg. closed).\n";
    return 0;
  }

  if (5 > arg_count or (arg_count % 2) == 0) {
    std::cerr<<"This program needs 4 arguments:\n";
    std::cerr<<"\t"<<arg_vector[0]<<" <world model ip> <solver port> <client port> <config file>\n\n";
    std::cerr<<"Lines in the config file consist of the object class to track and the name of its switch status.\n";
    std::cerr<<"For instance: \"doors\" \"closed\"\n";
    return 0;
  }

  //Set up a signal handler to catch interrupt signals so we can close gracefully
  signal(SIGINT, handler);

  //World model IP and ports
  std::string wm_ip(arg_vector[arg_count - 4]);
  int solver_port = std::stoi(std::string((arg_vector[arg_count - 3])));
  int client_port = std::stoi(std::string((arg_vector[arg_count - 2])));

  //Set up the solver world model connection;
  std::string origin = "binary_state_solver";

  //Read in type information from the config file
  //Types for the GRAIL world model will be read from the file
  std::vector<std::pair<std::u16string, bool>> type_pairs;

  //Remember what names correspond to what solutions and build a
  //query to find all objects of interest.
  //Use the object to solution map to map transmitters to URIs
  std::map<std::u16string, std::u16string> object_to_solution;
	//Map of transmitter URI (with binary data type) to object URIs.
  std::map<URI, URI> tx_to_uri;

  std::ifstream config(arg_vector[arg_count-1]);
  if (not config.is_open()) {
    std::cerr<<"Error opening configuration file \""<<arg_vector[arg_count-1]<<"\"\n";
    return 1;
  }
  std::string line;
  //Read in each type and its corresponding name
  while (std::getline(config, line)) {
    std::istringstream is(line);
    std::string obj_class, solution;
    if (is >> obj_class >> solution) {
      //Each switch value is a single byte for on or off but the
      //solution name for each object class is different.
      //Save this as a non-transient solution type
      //Change underlines into spaces.
      std::transform(obj_class.begin(), obj_class.end(), obj_class.begin(),
          [&](char c) { return c == '_' ? ' ' : c;});
      type_pairs.push_back(std::make_pair(toU16(solution), false));
      std::cerr<<"Class \""<<obj_class<<"\" has solution name \""<<solution<<"\"\n";
      object_to_solution[toU16(obj_class)] = toU16(solution);
    }
    else {
      std::cerr<<"Couldn't make sense of line: \""<<line<<"\"\n";
    }
  }
  config.close();

  if (object_to_solution.empty()) {
    std::cerr<<"There are no types in the config file - aborting.\n";
    return 1;
  }

  std::cerr<<"Trying to connect to world model as a solver.\n";
  SolverWorldModel swm(wm_ip, solver_port, type_pairs, toU16(origin));
  if (not swm.connected()) {
    std::cerr<<"Could not connect to the world model as a solver - aborting.\n";
    return 0;
  }

	//Remember switch states so that we only update
  std::map<URI, bool> switch_state;

  //Now handle connecting as a client.
  //Search for any IDs with names <anything>.obj_class.<anything>
  URI desired_ids = u".*\\.";
  if (object_to_solution.size() == 1) {
    desired_ids = u".*\\." + object_to_solution.begin()->first + u"\\..*";
  }
  else {
    desired_ids += u"(";
    for (auto I = object_to_solution.begin(); I != object_to_solution.end(); ++I) {
      //Insert a | (OR in regex) into the regex if this isn't the first object
      if (I != object_to_solution.begin()) {
        desired_ids += u"|";
      }
      desired_ids += I->first;
    }
    desired_ids += u")\\..*";
  }

  //Search for sensors attributes of any matching IDs
  std::vector<URI> attributes{u"sensor.*"};

	//Update IDs one a second
	world_model::grail_time interval = 1000;

	//Set up parameters for a second request of 'binary state' data.
	//Update as data arrives (interval of 0).
	URI binary_ids = u".*";
	std::vector<URI> binary_attributes{u"binary state"};
	world_model::grail_time binary_interval = 1000;

	//We will connect to the world model as a client inside of the processing loop below
	//Whenever we are disconnected we will attempt to reconnect.

  std::cerr<<"Trying to connect to world model as a client.\n";
  ClientWorldConnection cwc(wm_ip, client_port);
	//Send out the requests
	StepResponse sr = cwc.streamRequest(desired_ids, attributes, interval);
	StepResponse binary_response = cwc.streamRequest(binary_ids, binary_attributes, binary_interval);

	std::cerr<<"Starting processing loop...\n";
  while (not interrupted) {
		//Less than operator for two world model attributes
		auto attr_comp = [](const Attribute& a, const Attribute& b) {
			return (a.expiration_date != 0 or a.creation_date < b.creation_date); };
		//Stay connected
    while (not cwc.connected() and not interrupted) {
      std::cerr<<"Waiting 4 seconds before attempting to reconnect client->world model connection\n";
      //Sleep for several seconds after an error before trying to reconnect
      sleep(4);
      cwc.reconnect();
			if (cwc.connected()) {
				//Re-send out the requests
				StepResponse sr = cwc.streamRequest(desired_ids, attributes, interval);
				StepResponse binary_response = cwc.streamRequest(binary_ids, binary_attributes, binary_interval);
			}
    }

		try {

			//Now process the on-demand binary data
			while (binary_response.hasNext() and not interrupted) {
				//Get world model updates
				world_model::WorldState ws = binary_response.next();
				//Check each object for new switch states
				for (const std::pair<URI, std::vector<Attribute>>& I : ws) {
					if (tx_to_uri.end() != tx_to_uri.find(I.first)) {
						URI uri = tx_to_uri[I.first];
						//Get the first byte of the data (will be a one byte binary value)
						bool switch_on = I.second[0].data.at(0);
						if (switch_state.end() == switch_state.find(uri) or switch_state[uri] != switch_on) {
							switch_state[uri] = switch_on;
							//Use the object to solution map to get the solution name.
							for (auto obj_soln = object_to_solution.begin(); obj_soln != object_to_solution.end(); ++obj_soln) {
								if (uri.find(u"." + obj_soln->first + u".") != std::u16string::npos) {
									SolverWorldModel::AttrUpdate soln{obj_soln->second, world_model::getGRAILTime(), uri, std::vector<uint8_t>()};
									pushBackVal<uint8_t>(switch_on ? 1 : 0, soln.data);
									std::vector<SolverWorldModel::AttrUpdate> solns{soln};
									//Send the data to the world model
									bool retry = true;
									while (retry) {
										try {
											retry = false;
											swm.sendData(solns, false);
										}
										catch (std::runtime_error& err) {
											//Retry if this is just a temporary socket error
											if (err.what() == std::string("Error sending data over socket: Resource temporarily unavailable")) {
												std::cerr<<"Experiencing socket slow down with world model connection. Retrying...\n";
												retry = true;
											}
											//Otherwise keep throwing
											else {
												throw err;
											}
										}
									}
									if (switch_on) {
										std::cout<<toString(uri)<<" is "<<toString(obj_soln->second)<<'\n';
									} else {
										std::cout<<toString(uri)<<" is not "<<toString(obj_soln->second)<<'\n';
									}
								}
							}
						}
					}
				}
			}
			//Check for responses to map sensors to object identifiers
			while (sr.hasNext() and not interrupted) {
				//Get world model updates
				world_model::WorldState ws = sr.next();
				//Check each object for switch sensor ID information
				for (const std::pair<URI, std::vector<Attribute>>& I : ws) {
					if (I.second.empty()) {
						std::cerr<<toString(I.first)<<" is an empty object.\n";
					}
					else {
						Attribute newest = *(std::max_element(I.second.begin(), I.second.end(), attr_comp));
						if (newest.expiration_date != 0) {
							//TODO FIXME This attribute has been expired so stop updating the
							//status of this ID in the world model
						}
						//Otherwise, make sure that we have signed up for this sensor's data
						//from the aggregators

						//Transmitters are stored as one byte of physical layer and 16 bytes of ID
						grail_types::transmitter tx_switch = grail_types::readTransmitter(newest.data);
						//Map this transmitter to the ID of the object it corresponds to in the world model
						std::string str = std::to_string(tx_switch.phy) + "." + std::to_string(tx_switch.id.lower);
						tx_to_uri[std::u16string(str.begin(), str.end())] = I.first;
						std::cerr<<"Adding "<<std::string(I.first.begin(), I.first.end())<<" into object map with transmitter "<<std::string(str)<<"\n";
					}
				}
			}
		}
		catch (std::runtime_error& err) {
			std::cerr<<"Error in client->world model connection: "<<err.what()<<'\n';
		}
		//Yield to allow the client world connection to run for a bit
		std::this_thread::yield();
  }
}

<commit_msg>Removing unnecessary yield statement that older g++ doesn't have.<commit_after>/*
 * Copyright (c) 2012 Bernhard Firner and Rutgers University
 * All rights reserved.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
 * or visit http://www.gnu.org/licenses/gpl-2.0.html
 */

/*******************************************************************************
 * @file binary_state_solver.cpp
 * Offer binary solutions to the world model based upon binary sensors,
 * such as door switches, on/off power switches, etc.
 *
 * @author Bernhard Firner
 ******************************************************************************/

#include <algorithm>
#include <array>
#include <fstream>
#include <iostream>
#include <map>
#include <string>
#include <time.h>
#include <unistd.h>
#include <utility>
#include <vector>
#include <sstream>

//Handle interrupt signals to exit cleanly.
#include <signal.h>

#include <owl/netbuffer.hpp>
#include <owl/solver_aggregator_connection.hpp>
#include <owl/solver_world_connection.hpp>
#include <owl/sample_data.hpp>
#include <owl/world_model_protocol.hpp>
#include <owl/grail_types.hpp>

#include <owl/client_world_connection.hpp>

using namespace aggregator_solver;

using std::pair;

using world_model::Attribute;
using world_model::grail_time;
using world_model::URI;

//Global variable for the signal handler.
bool interrupted = false;
//Signal handler.
void handler(int signal) {
  psignal( signal, "Received signal ");
  if (interrupted) {
    std::cerr<<"Aborting.\n";
    // This is the second time we've received the interrupt, so just exit.
    exit(-1);
  }
  std::cerr<<"Shutting down...\n";
  interrupted = true;
}

std::u16string toU16(const std::string& str) {
  return std::u16string(str.begin(), str.end());
}

std::string toString(const std::u16string& str) {
  return std::string(str.begin(), str.end());
}

int main(int arg_count, char** arg_vector) {
  if (arg_count == 2 and std::string(arg_vector[1]) == "-?") {
    std::cout<< "name: Switch Solver\n";
    std::cout<< "arguments: worldmodel wm_solver wm_client config_file\n";
    std::cout<< "description: Monitors status of simple on/off switches.\n";
    std::cout<< "requires: 'binary state'\n";
    std::cout<< "config_file: tuple* 2 An item class (eg. door) and the name for its state when the switch is on (eg. closed).\n";
    return 0;
  }

  if (5 > arg_count or (arg_count % 2) == 0) {
    std::cerr<<"This program needs 4 arguments:\n";
    std::cerr<<"\t"<<arg_vector[0]<<" <world model ip> <solver port> <client port> <config file>\n\n";
    std::cerr<<"Lines in the config file consist of the object class to track and the name of its switch status.\n";
    std::cerr<<"For instance: \"doors\" \"closed\"\n";
    return 0;
  }

  //Set up a signal handler to catch interrupt signals so we can close gracefully
  signal(SIGINT, handler);

  //World model IP and ports
  std::string wm_ip(arg_vector[arg_count - 4]);
  int solver_port = std::stoi(std::string((arg_vector[arg_count - 3])));
  int client_port = std::stoi(std::string((arg_vector[arg_count - 2])));

  //Set up the solver world model connection;
  std::string origin = "binary_state_solver";

  //Read in type information from the config file
  //Types for the GRAIL world model will be read from the file
  std::vector<std::pair<std::u16string, bool>> type_pairs;

  //Remember what names correspond to what solutions and build a
  //query to find all objects of interest.
  //Use the object to solution map to map transmitters to URIs
  std::map<std::u16string, std::u16string> object_to_solution;
	//Map of transmitter URI (with binary data type) to object URIs.
  std::map<URI, URI> tx_to_uri;

  std::ifstream config(arg_vector[arg_count-1]);
  if (not config.is_open()) {
    std::cerr<<"Error opening configuration file \""<<arg_vector[arg_count-1]<<"\"\n";
    return 1;
  }
  std::string line;
  //Read in each type and its corresponding name
  while (std::getline(config, line)) {
    std::istringstream is(line);
    std::string obj_class, solution;
    if (is >> obj_class >> solution) {
      //Each switch value is a single byte for on or off but the
      //solution name for each object class is different.
      //Save this as a non-transient solution type
      //Change underlines into spaces.
      std::transform(obj_class.begin(), obj_class.end(), obj_class.begin(),
          [&](char c) { return c == '_' ? ' ' : c;});
      type_pairs.push_back(std::make_pair(toU16(solution), false));
      std::cerr<<"Class \""<<obj_class<<"\" has solution name \""<<solution<<"\"\n";
      object_to_solution[toU16(obj_class)] = toU16(solution);
    }
    else {
      std::cerr<<"Couldn't make sense of line: \""<<line<<"\"\n";
    }
  }
  config.close();

  if (object_to_solution.empty()) {
    std::cerr<<"There are no types in the config file - aborting.\n";
    return 1;
  }

  std::cerr<<"Trying to connect to world model as a solver.\n";
  SolverWorldModel swm(wm_ip, solver_port, type_pairs, toU16(origin));
  if (not swm.connected()) {
    std::cerr<<"Could not connect to the world model as a solver - aborting.\n";
    return 0;
  }

	//Remember switch states so that we only update
  std::map<URI, bool> switch_state;

  //Now handle connecting as a client.
  //Search for any IDs with names <anything>.obj_class.<anything>
  URI desired_ids = u".*\\.";
  if (object_to_solution.size() == 1) {
    desired_ids = u".*\\." + object_to_solution.begin()->first + u"\\..*";
  }
  else {
    desired_ids += u"(";
    for (auto I = object_to_solution.begin(); I != object_to_solution.end(); ++I) {
      //Insert a | (OR in regex) into the regex if this isn't the first object
      if (I != object_to_solution.begin()) {
        desired_ids += u"|";
      }
      desired_ids += I->first;
    }
    desired_ids += u")\\..*";
  }

  //Search for sensors attributes of any matching IDs
  std::vector<URI> attributes{u"sensor.*"};

	//Update IDs one a second
	world_model::grail_time interval = 1000;

	//Set up parameters for a second request of 'binary state' data.
	//Update as data arrives (interval of 0).
	URI binary_ids = u".*";
	std::vector<URI> binary_attributes{u"binary state"};
	world_model::grail_time binary_interval = 0;

	//We will connect to the world model as a client inside of the processing loop below
	//Whenever we are disconnected we will attempt to reconnect.

  std::cerr<<"Trying to connect to world model as a client.\n";
  ClientWorldConnection cwc(wm_ip, client_port);
	//Send out the requests
	StepResponse sr = cwc.streamRequest(desired_ids, attributes, interval);
	StepResponse binary_response = cwc.streamRequest(binary_ids, binary_attributes, binary_interval);

	std::cerr<<"Starting processing loop...\n";
  while (not interrupted) {
		//Less than operator for two world model attributes
		auto attr_comp = [](const Attribute& a, const Attribute& b) {
			return (a.expiration_date != 0 or a.creation_date < b.creation_date); };
		//Stay connected
    while (not cwc.connected() and not interrupted) {
      std::cerr<<"Waiting 4 seconds before attempting to reconnect client->world model connection\n";
      //Sleep for several seconds after an error before trying to reconnect
      sleep(4);
      cwc.reconnect();
			if (cwc.connected()) {
				//Re-send out the requests
				StepResponse sr = cwc.streamRequest(desired_ids, attributes, interval);
				StepResponse binary_response = cwc.streamRequest(binary_ids, binary_attributes, binary_interval);
			}
    }

		try {

			//Now process the on-demand binary data
			while (binary_response.hasNext() and not interrupted) {
				//Get world model updates
				world_model::WorldState ws = binary_response.next();
				//Check each object for new switch states
				for (const std::pair<URI, std::vector<Attribute>>& I : ws) {
					if (tx_to_uri.end() != tx_to_uri.find(I.first)) {
						URI uri = tx_to_uri[I.first];
						//Get the first byte of the data (will be a one byte binary value)
						bool switch_on = I.second[0].data.at(0);
						if (switch_state.end() == switch_state.find(uri) or switch_state[uri] != switch_on) {
							switch_state[uri] = switch_on;
							//Use the object to solution map to get the solution name.
							for (auto obj_soln = object_to_solution.begin(); obj_soln != object_to_solution.end(); ++obj_soln) {
								if (uri.find(u"." + obj_soln->first + u".") != std::u16string::npos) {
									SolverWorldModel::AttrUpdate soln{obj_soln->second, world_model::getGRAILTime(), uri, std::vector<uint8_t>()};
									pushBackVal<uint8_t>(switch_on ? 1 : 0, soln.data);
									std::vector<SolverWorldModel::AttrUpdate> solns{soln};
									//Send the data to the world model
									bool retry = true;
									while (retry) {
										try {
											retry = false;
											swm.sendData(solns, false);
										}
										catch (std::runtime_error& err) {
											//Retry if this is just a temporary socket error
											if (err.what() == std::string("Error sending data over socket: Resource temporarily unavailable")) {
												std::cerr<<"Experiencing socket slow down with world model connection. Retrying...\n";
												retry = true;
											}
											//Otherwise keep throwing
											else {
												throw err;
											}
										}
									}
									if (switch_on) {
										std::cout<<toString(uri)<<" is "<<toString(obj_soln->second)<<'\n';
									} else {
										std::cout<<toString(uri)<<" is not "<<toString(obj_soln->second)<<'\n';
									}
								}
							}
						}
					}
				}
			}
			//Check for responses to map sensors to object identifiers
			while (sr.hasNext() and not interrupted) {
				//Get world model updates
				world_model::WorldState ws = sr.next();
				//Check each object for switch sensor ID information
				for (const std::pair<URI, std::vector<Attribute>>& I : ws) {
					if (I.second.empty()) {
						std::cerr<<toString(I.first)<<" is an empty object.\n";
					}
					else {
						Attribute newest = *(std::max_element(I.second.begin(), I.second.end(), attr_comp));
						if (newest.expiration_date != 0) {
							//TODO FIXME This attribute has been expired so stop updating the
							//status of this ID in the world model
						}
						//Otherwise, make sure that we have signed up for this sensor's data
						//from the aggregators

						//Transmitters are stored as one byte of physical layer and 16 bytes of ID
						grail_types::transmitter tx_switch = grail_types::readTransmitter(newest.data);
						//Map this transmitter to the ID of the object it corresponds to in the world model
						std::string str = std::to_string(tx_switch.phy) + "." + std::to_string(tx_switch.id.lower);
						tx_to_uri[std::u16string(str.begin(), str.end())] = I.first;
						std::cerr<<"Adding "<<std::string(I.first.begin(), I.first.end())<<" into object map with transmitter "<<std::string(str)<<"\n";
					}
				}
			}
		}
		catch (std::runtime_error& err) {
			std::cerr<<"Error in client->world model connection: "<<err.what()<<'\n';
		}
  }
}

<|endoftext|>


<commit_before>#pragma once

#include <ctime>
#include <initializer_list>
#include <utility>

#include "blackhole/attribute/name.hpp"
#include "blackhole/attribute/scope.hpp"
#include "blackhole/attribute/set.hpp"
#include "blackhole/attribute/view.hpp"
#include "blackhole/attribute/traits.hpp"
#include "blackhole/attribute/value.hpp"
#include "blackhole/utils/timeval.hpp"
#include "blackhole/utils/types.hpp"
#include "blackhole/utils/underlying.hpp"
#include "blackhole/utils/noexcept.hpp"

namespace blackhole {

namespace attribute {

/*!
 * Simple typedef for attributes initializer list.
 * Useful when specifying local attributes.
 */
typedef std::initializer_list<std::pair<name_t, value_t>> list;

// Dynamic attribute factory function.
template<typename T>
inline
pair_t
make(const name_t& name, const T& value, scope_t scope = DEFAULT_SCOPE) {
    return std::make_pair(name, attribute_t(value, scope));
}

template<typename T>
inline
pair_t
make(const name_t& name, T&& value, scope_t scope = DEFAULT_SCOPE) {
    return std::make_pair(name, attribute_t(std::move(value), scope));
}

// Attribute packing/unpacking/extracting.
template<typename T, class = void>
struct traits {
    static inline T pack(const T& value) {
        return value;
    }

    static inline T extract(const set_view_t& attributes, const name_t& name) {
        return boost::get<T>(attributes.at(name).value);
    }
};

template<typename T>
struct traits<T, typename std::enable_if<std::is_enum<T>::value>::type> {
    typedef typename aux::underlying_type<T>::type underlying_type;

    static inline underlying_type pack(const T& value) {
        return static_cast<underlying_type>(value);
    }

    static inline T extract(const set_view_t& attributes, const name_t& name) {
        return static_cast<T>(boost::get<underlying_type>(attributes.at(name).value));
    }
};

} // namespace attribute

} // namespace blackhole
<commit_msg>[Code Style] Comments.<commit_after>#pragma once

#include <ctime>
#include <initializer_list>
#include <utility>

#include "blackhole/attribute/name.hpp"
#include "blackhole/attribute/scope.hpp"
#include "blackhole/attribute/set.hpp"
#include "blackhole/attribute/view.hpp"
#include "blackhole/attribute/traits.hpp"
#include "blackhole/attribute/value.hpp"
#include "blackhole/utils/timeval.hpp"
#include "blackhole/utils/types.hpp"
#include "blackhole/utils/underlying.hpp"
#include "blackhole/utils/noexcept.hpp"

namespace blackhole {

namespace attribute {

/*!
 * Simple typedef for attributes initializer list.
 * Useful when specifying local attributes.
 */
typedef std::initializer_list<std::pair<name_t, value_t>> list;

/*!
 * Dynamic attribute factory function.
 */
template<typename T>
inline
pair_t
make(const name_t& name, const T& value, scope_t scope = DEFAULT_SCOPE) {
    return std::make_pair(name, attribute_t(value, scope));
}

template<typename T>
inline
pair_t
make(const name_t& name, T&& value, scope_t scope = DEFAULT_SCOPE) {
    return std::make_pair(name, attribute_t(std::move(value), scope));
}

// Attribute packing/unpacking/extracting.
template<typename T, class = void>
struct traits {
    static inline T pack(const T& value) {
        return value;
    }

    static inline T extract(const set_view_t& attributes, const name_t& name) {
        return boost::get<T>(attributes.at(name).value);
    }
};

template<typename T>
struct traits<T, typename std::enable_if<std::is_enum<T>::value>::type> {
    typedef typename aux::underlying_type<T>::type underlying_type;

    static inline underlying_type pack(const T& value) {
        return static_cast<underlying_type>(value);
    }

    static inline T extract(const set_view_t& attributes, const name_t& name) {
        return static_cast<T>(boost::get<underlying_type>(attributes.at(name).value));
    }
};

} // namespace attribute

} // namespace blackhole
<|endoftext|>


<commit_before>// This file is part of the dune-gdt project:
//   http://users.dune-project.org/projects/dune-gdt
// Copyright holders: Felix Albrecht
// License: BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause)

#ifndef DUNE_GDT_DISCRETEFUNCTION_DIFFERENCE_HH
#define DUNE_GDT_DISCRETEFUNCTION_DIFFERENCE_HH

#include <type_traits>

#include <dune/stuff/functions/interfaces.hh>

namespace Dune {
namespace GDT {

namespace LocalFunction {

template <class EntityType, class MinuendType, class SubtrahendType>
class Difference;

template <class EntityImp, class MinuendType, class SubtrahendType>
class DifferenceTraits
{
public:
  typedef typename MinuendType::template LocalFunction<EntityImp>::Type LocalMinuendType;
  typedef typename SubtrahendType::template LocalFunction<EntityImp>::Type LocalSubtrahendType;
  typedef typename LocalMinuendType::DomainFieldType DomainFieldType;
  static_assert(std::is_same<DomainFieldType, typename LocalSubtrahendType::DomainFieldType>::value,
                "DomainFieldType of LocalMinuendType and LocalSubtrahendType do not match!");
  static const unsigned int dimDomain = LocalMinuendType::dimDomain;
  static_assert(dimDomain == LocalSubtrahendType::dimDomain,
                "dimDomain of LocalMinuendType and LocalSubtrahendType do not match!");
  typedef typename LocalMinuendType::RangeFieldType RangeFieldType;
  static_assert(std::is_same<RangeFieldType, typename LocalSubtrahendType::RangeFieldType>::value,
                "RangeFieldType of LocalMinuendType and LocalSubtrahendType do not match!");
  static const unsigned int dimRangeRows = LocalMinuendType::dimRangeRows;
  static_assert(dimRangeRows == LocalSubtrahendType::dimRangeRows,
                "dimRangeRows of LocalMinuendType and LocalSubtrahendType do not match!");
  static const unsigned int dimRangeCols = LocalMinuendType::dimRangeCols;
  static_assert(dimRangeCols == LocalSubtrahendType::dimRangeCols,
                "dimRangeCols of LocalMinuendType and LocalSubtrahendType do not match!");
  typedef EntityImp EntityType;
  typedef Difference<EntityType, MinuendType, SubtrahendType> derived_type;
  static_assert(std::is_base_of<Stuff::LocalFunctionInterface<typename LocalMinuendType::Traits, DomainFieldType,
                                                              dimDomain, RangeFieldType, dimRangeRows, dimRangeCols>,
                                LocalMinuendType>::value,
                "LocalMinuendType has to be derived from Stuff::LocalFunctionInterface!");
  static_assert(std::is_base_of<Stuff::LocalFunctionInterface<typename LocalSubtrahendType::Traits, DomainFieldType,
                                                              dimDomain, RangeFieldType, dimRangeRows, dimRangeCols>,
                                LocalSubtrahendType>::value,
                "LocalSubtrahendType has to be derived from Stuff::LocalFunctionInterface!");
};

template <class EntityImp, class MinuendType, class SubtrahendType>
class Difference
    : public Stuff::
          LocalFunctionInterface<DifferenceTraits<EntityImp, MinuendType, SubtrahendType>,
                                 typename DifferenceTraits<EntityImp, MinuendType, SubtrahendType>::DomainFieldType,
                                 DifferenceTraits<EntityImp, MinuendType, SubtrahendType>::dimDomain,
                                 typename DifferenceTraits<EntityImp, MinuendType, SubtrahendType>::RangeFieldType,
                                 DifferenceTraits<EntityImp, MinuendType, SubtrahendType>::dimRangeRows,
                                 DifferenceTraits<EntityImp, MinuendType, SubtrahendType>::dimRangeCols>
{
  typedef Stuff::
      LocalFunctionInterface<DifferenceTraits<EntityImp, MinuendType, SubtrahendType>,
                             typename DifferenceTraits<EntityImp, MinuendType, SubtrahendType>::DomainFieldType,
                             DifferenceTraits<EntityImp, MinuendType, SubtrahendType>::dimDomain,
                             typename DifferenceTraits<EntityImp, MinuendType, SubtrahendType>::RangeFieldType,
                             DifferenceTraits<EntityImp, MinuendType, SubtrahendType>::dimRangeRows,
                             DifferenceTraits<EntityImp, MinuendType, SubtrahendType>::dimRangeCols> BaseType;
  typedef Difference<EntityImp, MinuendType, SubtrahendType> ThisType;

public:
  typedef DifferenceTraits<EntityImp, MinuendType, SubtrahendType> Traits;

private:
  typedef typename Traits::LocalMinuendType LocalMinuendType;
  typedef typename Traits::LocalSubtrahendType LocalSubtrahendType;

public:
  typedef typename Traits::EntityType EntityType;

  typedef typename BaseType::DomainType DomainType;
  typedef typename BaseType::RangeType RangeType;
  typedef typename BaseType::JacobianRangeType JacobianRangeType;

  Difference(const EntityType& entity, const MinuendType& minuend, const SubtrahendType& subtrahend)
    : entity_(entity)
    , minuend_(minuend)
    , subtrahend_(subtrahend)
    , local_minuend_(new LocalMinuendType(minuend_.localFunction(entity_)))
    , local_subtrahend_(new LocalSubtrahendType(subtrahend_.localFunction(entity_)))
    , tmp_value_(0)
    , tmp_jacobian_value_(0)
  {
  }

  Difference(const ThisType& other)
    : entity_(other.entity_)
    , minuend_(other.minuend_)
    , subtrahend_(other.subtrahend_)
    , local_minuend_(new LocalMinuendType(minuend_.localFunction(entity_)))
    , local_subtrahend_(new LocalSubtrahendType(subtrahend_.localFunction(entity_)))
    , tmp_value_(0)
    , tmp_jacobian_value_(0)
  {
  }

  ~Difference()
  {
    delete local_minuend_;
    delete local_subtrahend_;
  }

private:
  ThisType& operator=(const ThisType& other);

public:
  const EntityType& entity() const
  {
    return entity_;
  }

  virtual int order() const
  {
    if ((local_minuend_->order() < 0) || (local_subtrahend_->order() < 0))
      return -1;
    else
      return std::max(local_minuend_->order(), local_subtrahend_->order());
  }

  void evaluate(const DomainType& xx, RangeType& ret) const
  {
    local_minuend_->evaluate(xx, ret);
    local_subtrahend_->evaluate(xx, tmp_value_);
    ret -= tmp_value_;
  }

  void jacobian(const DomainType& xx, JacobianRangeType& ret) const
  {
    local_minuend_->evaluate(xx, ret);
    local_subtrahend_->evaluate(xx, tmp_jacobian_value_);
    ret -= tmp_jacobian_value_;
  }

private:
  const EntityType& entity_;
  const MinuendType& minuend_;
  const SubtrahendType& subtrahend_;
  const LocalMinuendType* local_minuend_;
  const LocalSubtrahendType* local_subtrahend_;
  mutable RangeType tmp_value_;
  mutable JacobianRangeType tmp_jacobian_value_;
};

} // namespace LocalFunction

namespace DiscreteFunction {

template <class MinuendType, class SubtrahendType>
class Difference : public Stuff::LocalizableFunction
{
  static_assert(std::is_base_of<Stuff::LocalizableFunction, MinuendType>::value,
                "MinuendType has to be derived from Stuff::LocalizableFunction!");
  static_assert(std::is_base_of<Stuff::LocalizableFunction, SubtrahendType>::value,
                "SubtrahendType has to be derived from Stuff::LocalizableFunction!");

public:
  template <class EntityType>
  class LocalFunction
  {
  public:
    typedef GDT::LocalFunction::Difference<EntityType, MinuendType, SubtrahendType> Type;
  };

  Difference(const MinuendType& minuend, const SubtrahendType& subtrahend)
    : minuend_(minuend)
    , subtrahend_(subtrahend)
  {
  }

  template <class EntityType>
  typename LocalFunction<EntityType>::Type localFunction(const EntityType& entity) const
  {
    return typename LocalFunction<EntityType>::Type(entity, minuend_, subtrahend_);
  }

private:
  const MinuendType& minuend_;
  const SubtrahendType& subtrahend_;
}; // class Difference

} // namespace DiscreteFunction
} // namespace GDT
} // namespace Dune

#endif // DUNE_GDT_DISCRETEFUNCTION_DIFFERENCE_HH
<commit_msg>[discretefunction.difference] fix jacobian()<commit_after>// This file is part of the dune-gdt project:
//   http://users.dune-project.org/projects/dune-gdt
// Copyright holders: Felix Albrecht
// License: BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause)

#ifndef DUNE_GDT_DISCRETEFUNCTION_DIFFERENCE_HH
#define DUNE_GDT_DISCRETEFUNCTION_DIFFERENCE_HH

#include <type_traits>

#include <dune/stuff/functions/interfaces.hh>

namespace Dune {
namespace GDT {

namespace LocalFunction {

template <class EntityType, class MinuendType, class SubtrahendType>
class Difference;

template <class EntityImp, class MinuendType, class SubtrahendType>
class DifferenceTraits
{
public:
  typedef typename MinuendType::template LocalFunction<EntityImp>::Type LocalMinuendType;
  typedef typename SubtrahendType::template LocalFunction<EntityImp>::Type LocalSubtrahendType;
  typedef typename LocalMinuendType::DomainFieldType DomainFieldType;
  static_assert(std::is_same<DomainFieldType, typename LocalSubtrahendType::DomainFieldType>::value,
                "DomainFieldType of LocalMinuendType and LocalSubtrahendType do not match!");
  static const unsigned int dimDomain = LocalMinuendType::dimDomain;
  static_assert(dimDomain == LocalSubtrahendType::dimDomain,
                "dimDomain of LocalMinuendType and LocalSubtrahendType do not match!");
  typedef typename LocalMinuendType::RangeFieldType RangeFieldType;
  static_assert(std::is_same<RangeFieldType, typename LocalSubtrahendType::RangeFieldType>::value,
                "RangeFieldType of LocalMinuendType and LocalSubtrahendType do not match!");
  static const unsigned int dimRangeRows = LocalMinuendType::dimRangeRows;
  static_assert(dimRangeRows == LocalSubtrahendType::dimRangeRows,
                "dimRangeRows of LocalMinuendType and LocalSubtrahendType do not match!");
  static const unsigned int dimRangeCols = LocalMinuendType::dimRangeCols;
  static_assert(dimRangeCols == LocalSubtrahendType::dimRangeCols,
                "dimRangeCols of LocalMinuendType and LocalSubtrahendType do not match!");
  typedef EntityImp EntityType;
  typedef Difference<EntityType, MinuendType, SubtrahendType> derived_type;
  static_assert(std::is_base_of<Stuff::LocalFunctionInterface<typename LocalMinuendType::Traits, DomainFieldType,
                                                              dimDomain, RangeFieldType, dimRangeRows, dimRangeCols>,
                                LocalMinuendType>::value,
                "LocalMinuendType has to be derived from Stuff::LocalFunctionInterface!");
  static_assert(std::is_base_of<Stuff::LocalFunctionInterface<typename LocalSubtrahendType::Traits, DomainFieldType,
                                                              dimDomain, RangeFieldType, dimRangeRows, dimRangeCols>,
                                LocalSubtrahendType>::value,
                "LocalSubtrahendType has to be derived from Stuff::LocalFunctionInterface!");
};

template <class EntityImp, class MinuendType, class SubtrahendType>
class Difference
    : public Stuff::
          LocalFunctionInterface<DifferenceTraits<EntityImp, MinuendType, SubtrahendType>,
                                 typename DifferenceTraits<EntityImp, MinuendType, SubtrahendType>::DomainFieldType,
                                 DifferenceTraits<EntityImp, MinuendType, SubtrahendType>::dimDomain,
                                 typename DifferenceTraits<EntityImp, MinuendType, SubtrahendType>::RangeFieldType,
                                 DifferenceTraits<EntityImp, MinuendType, SubtrahendType>::dimRangeRows,
                                 DifferenceTraits<EntityImp, MinuendType, SubtrahendType>::dimRangeCols>
{
  typedef Stuff::
      LocalFunctionInterface<DifferenceTraits<EntityImp, MinuendType, SubtrahendType>,
                             typename DifferenceTraits<EntityImp, MinuendType, SubtrahendType>::DomainFieldType,
                             DifferenceTraits<EntityImp, MinuendType, SubtrahendType>::dimDomain,
                             typename DifferenceTraits<EntityImp, MinuendType, SubtrahendType>::RangeFieldType,
                             DifferenceTraits<EntityImp, MinuendType, SubtrahendType>::dimRangeRows,
                             DifferenceTraits<EntityImp, MinuendType, SubtrahendType>::dimRangeCols> BaseType;
  typedef Difference<EntityImp, MinuendType, SubtrahendType> ThisType;

public:
  typedef DifferenceTraits<EntityImp, MinuendType, SubtrahendType> Traits;

private:
  typedef typename Traits::LocalMinuendType LocalMinuendType;
  typedef typename Traits::LocalSubtrahendType LocalSubtrahendType;

public:
  typedef typename Traits::EntityType EntityType;

  typedef typename BaseType::DomainType DomainType;
  typedef typename BaseType::RangeType RangeType;
  typedef typename BaseType::JacobianRangeType JacobianRangeType;

  Difference(const EntityType& entity, const MinuendType& minuend, const SubtrahendType& subtrahend)
    : entity_(entity)
    , minuend_(minuend)
    , subtrahend_(subtrahend)
    , local_minuend_(new LocalMinuendType(minuend_.localFunction(entity_)))
    , local_subtrahend_(new LocalSubtrahendType(subtrahend_.localFunction(entity_)))
    , tmp_value_(0)
    , tmp_jacobian_value_(0)
  {
  }

  Difference(const ThisType& other)
    : entity_(other.entity_)
    , minuend_(other.minuend_)
    , subtrahend_(other.subtrahend_)
    , local_minuend_(new LocalMinuendType(minuend_.localFunction(entity_)))
    , local_subtrahend_(new LocalSubtrahendType(subtrahend_.localFunction(entity_)))
    , tmp_value_(0)
    , tmp_jacobian_value_(0)
  {
  }

  ~Difference()
  {
    delete local_minuend_;
    delete local_subtrahend_;
  }

private:
  ThisType& operator=(const ThisType& other);

public:
  const EntityType& entity() const
  {
    return entity_;
  }

  virtual int order() const
  {
    if ((local_minuend_->order() < 0) || (local_subtrahend_->order() < 0))
      return -1;
    else
      return std::max(local_minuend_->order(), local_subtrahend_->order());
  }

  void evaluate(const DomainType& xx, RangeType& ret) const
  {
    local_minuend_->evaluate(xx, ret);
    local_subtrahend_->evaluate(xx, tmp_value_);
    ret -= tmp_value_;
  }

  void jacobian(const DomainType& xx, JacobianRangeType& ret) const
  {
    local_minuend_->jacobian(xx, ret);
    local_subtrahend_->jacobian(xx, tmp_jacobian_value_);
    ret -= tmp_jacobian_value_;
  }

private:
  const EntityType& entity_;
  const MinuendType& minuend_;
  const SubtrahendType& subtrahend_;
  const LocalMinuendType* local_minuend_;
  const LocalSubtrahendType* local_subtrahend_;
  mutable RangeType tmp_value_;
  mutable JacobianRangeType tmp_jacobian_value_;
};

} // namespace LocalFunction

namespace DiscreteFunction {

template <class MinuendType, class SubtrahendType>
class Difference : public Stuff::LocalizableFunction
{
  static_assert(std::is_base_of<Stuff::LocalizableFunction, MinuendType>::value,
                "MinuendType has to be derived from Stuff::LocalizableFunction!");
  static_assert(std::is_base_of<Stuff::LocalizableFunction, SubtrahendType>::value,
                "SubtrahendType has to be derived from Stuff::LocalizableFunction!");

public:
  template <class EntityType>
  class LocalFunction
  {
  public:
    typedef GDT::LocalFunction::Difference<EntityType, MinuendType, SubtrahendType> Type;
  };

  Difference(const MinuendType& minuend, const SubtrahendType& subtrahend)
    : minuend_(minuend)
    , subtrahend_(subtrahend)
  {
  }

  template <class EntityType>
  typename LocalFunction<EntityType>::Type localFunction(const EntityType& entity) const
  {
    return typename LocalFunction<EntityType>::Type(entity, minuend_, subtrahend_);
  }

private:
  const MinuendType& minuend_;
  const SubtrahendType& subtrahend_;
}; // class Difference

} // namespace DiscreteFunction
} // namespace GDT
} // namespace Dune

#endif // DUNE_GDT_DISCRETEFUNCTION_DIFFERENCE_HH
<|endoftext|>


<commit_before>// This file is part of the dune-gdt project:
//   http://users.dune-project.org/projects/dune-gdt
// Copyright holders: Felix Schindler
// License: BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause)

#ifndef DUNE_GDT_PRODUCTS_ESV2007_HH
#define DUNE_GDT_PRODUCTS_ESV2007_HH

#include <dune/gdt/playground/localevaluation/ESV2007.hh>
#include <dune/gdt/localoperator/codim0.hh>

#include "../../products/interfaces.hh"
#include "../../products/base.hh"

namespace Dune {
namespace GDT {
namespace Products {
namespace ESV2007 {

// forward, to be used in the traits
template <class GridViewImp, class DiffusionImp, class DiffusiveFluxImp, class RangeImp, class SourceImp,
          class FieldImp = double>
class DiffusiveFluxEstimate;

template <class GridViewImp, class DiffusionImp, class DiffusiveFluxImp, class RangeImp, class SourceImp,
          class FieldImp>
class DiffusiveFluxEstimateTraits
{
public:
  typedef DiffusiveFluxEstimate<GridViewImp, DiffusionImp, DiffusiveFluxImp, RangeImp, SourceImp, FieldImp>
      derived_type;
  typedef GridViewImp GridViewType;
  typedef DiffusionImp DiffusionType;
  typedef DiffusiveFluxImp DiffusiveFluxType;
  typedef RangeImp RangeType;
  typedef SourceImp SourceType;
  typedef FieldImp FieldType;

private:
  typedef LocalEvaluation::ESV2007::DiffusiveFluxEstimate<DiffusionType, DiffusiveFluxType> LocalEvalautionType;

public:
  typedef LocalOperator::Codim0Integral<LocalEvalautionType> LocalOperatorType;
}; // class DiffusiveFluxEstimateTraits

template <class GridViewImp, class DiffusionImp, class DiffusiveFluxImp, class RangeImp, class SourceImp,
          class FieldImp>
class DiffusiveFluxEstimate
    : public Products::LocalizableBase<DiffusiveFluxEstimateTraits<GridViewImp, DiffusionImp, DiffusiveFluxImp,
                                                                   RangeImp, SourceImp, FieldImp>>
{
  typedef Products::LocalizableBase<DiffusiveFluxEstimateTraits<GridViewImp, DiffusionImp, DiffusiveFluxImp, RangeImp,
                                                                SourceImp, FieldImp>> BaseType;

public:
  typedef DiffusiveFluxEstimateTraits<GridViewImp, DiffusionImp, DiffusiveFluxImp, RangeImp, SourceImp, FieldImp>
      Traits;
  using typename BaseType::GridViewType;
  typedef typename Traits::DiffusionType DiffusionType;
  typedef typename Traits::DiffusiveFluxType DiffusiveFluxType;
  using typename BaseType::RangeType;
  using typename BaseType::SourceType;
  typedef typename Traits::LocalOperatorType LocalOperatorType;

  DiffusiveFluxEstimate(const GridViewType& grd_vw, const RangeType& rng, const SourceType& src,
                        const DiffusionType& diffusion, const DiffusiveFluxType& diffusive_flux,
                        const size_t over_integrate = 0)
    : BaseType(grd_vw, rng, src)
    , diffusion_(diffusion)
    , diffusive_flux_(diffusive_flux)
    , local_operator_(over_integrate, diffusion_, diffusive_flux_)
  {
  }

  ~DiffusiveFluxEstimate()
  {
  }

private:
  virtual const LocalOperatorType& local_operator() const
  {
    return local_operator_;
  }

  const DiffusionType& diffusion_;
  const DiffusiveFluxType& diffusive_flux_;
  const LocalOperatorType local_operator_;
}; // class DiffusiveFluxEstimate

} // namespace ESV2007
} // namespace Products
} // namespace GDT
} // namespace Dune

#endif // DUNE_GDT_PRODUCTS_ESV2007_HH
<commit_msg>[products.ESV2007] added first draft of a 2nd variant<commit_after>// This file is part of the dune-gdt project:
//   http://users.dune-project.org/projects/dune-gdt
// Copyright holders: Felix Schindler
// License: BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause)

#ifndef DUNE_GDT_PRODUCTS_ESV2007_HH
#define DUNE_GDT_PRODUCTS_ESV2007_HH

#include <dune/gdt/playground/localevaluation/ESV2007.hh>
#include <dune/gdt/localoperator/codim0.hh>

#include "../../products/interfaces.hh"
#include "../../products/base.hh"

namespace Dune {
namespace GDT {
namespace Products {
namespace ESV2007 {

// forward, to be used in the traits
template <class GridViewImp, class DiffusionFactorType, class DiffusiveFluxType, class RangeImp, class SourceImp,
          class FieldImp = double, class DiffusionTensorType = void>
class DiffusiveFluxEstimate;

namespace internal {

template <class GridViewImp, class DiffusionFactorType, class DiffusiveFluxType, class RangeImp, class SourceImp,
          class FieldImp, class DiffusionTensorType = void>
class DiffusiveFluxEstimateTraits
{
public:
  typedef DiffusiveFluxEstimate<GridViewImp, DiffusionFactorType, DiffusiveFluxType, RangeImp, SourceImp, FieldImp,
                                DiffusionTensorType> derived_type;
  typedef GridViewImp GridViewType;
  typedef RangeImp RangeType;
  typedef SourceImp SourceType;
  typedef FieldImp FieldType;

private:
  typedef LocalEvaluation::ESV2007::DiffusiveFluxEstimate<DiffusionFactorType, DiffusiveFluxType, DiffusionTensorType>
      LocalEvalautionType;

public:
  typedef LocalOperator::Codim0Integral<LocalEvalautionType> LocalOperatorType;
}; // class DiffusiveFluxEstimateTraits

template <class GridViewImp, class DiffusionType, class DiffusiveFluxType, class RangeImp, class SourceImp,
          class FieldImp>
class DiffusiveFluxEstimateTraits<GridViewImp, DiffusionType, DiffusiveFluxType, RangeImp, SourceImp, FieldImp, void>
{
public:
  typedef DiffusiveFluxEstimate<GridViewImp, DiffusionType, DiffusiveFluxType, RangeImp, SourceImp, FieldImp>
      derived_type;
  typedef GridViewImp GridViewType;
  typedef RangeImp RangeType;
  typedef SourceImp SourceType;
  typedef FieldImp FieldType;

private:
  typedef LocalEvaluation::ESV2007::DiffusiveFluxEstimate<DiffusionType, DiffusiveFluxType> LocalEvalautionType;

public:
  typedef LocalOperator::Codim0Integral<LocalEvalautionType> LocalOperatorType;
}; // class DiffusiveFluxEstimateTraits< ..., void >

} // namespace internal

template <class GridViewImp, class DiffusionType, class DiffusiveFluxType, class RangeImp, class SourceImp,
          class FieldImp>
class DiffusiveFluxEstimate<GridViewImp, DiffusionType, DiffusiveFluxType, RangeImp, SourceImp, FieldImp, void>
    : public Products::LocalizableBase<internal::DiffusiveFluxEstimateTraits<GridViewImp, DiffusionType,
                                                                             DiffusiveFluxType, RangeImp, SourceImp,
                                                                             FieldImp>>
{
  typedef Products::LocalizableBase<internal::DiffusiveFluxEstimateTraits<GridViewImp, DiffusionType, DiffusiveFluxType,
                                                                          RangeImp, SourceImp, FieldImp>> BaseType;

public:
  typedef internal::DiffusiveFluxEstimateTraits<GridViewImp, DiffusionType, DiffusiveFluxType, RangeImp, SourceImp,
                                                FieldImp> Traits;
  using typename BaseType::GridViewType;
  using typename BaseType::RangeType;
  using typename BaseType::SourceType;
  typedef typename Traits::LocalOperatorType LocalOperatorType;

  DiffusiveFluxEstimate(const GridViewType& grd_vw, const RangeType& rng, const SourceType& src,
                        const DiffusionType& diffusion, const DiffusiveFluxType& diffusive_flux,
                        const size_t over_integrate = 0)
    : BaseType(grd_vw, rng, src)
    , diffusion_(diffusion)
    , diffusive_flux_(diffusive_flux)
    , local_operator_(over_integrate, diffusion_, diffusive_flux_)
  {
  }

  ~DiffusiveFluxEstimate()
  {
  }

private:
  virtual const LocalOperatorType& local_operator() const DS_OVERRIDE DS_FINAL
  {
    return local_operator_;
  }

  const DiffusionType& diffusion_;
  const DiffusiveFluxType& diffusive_flux_;
  const LocalOperatorType local_operator_;
}; // class DiffusiveFluxEstimate< ..., void >

template <class GridViewImp, class DiffusionFactorType, class DiffusiveFluxType, class RangeImp, class SourceImp,
          class FieldImp, class DiffusionTensorType>
class DiffusiveFluxEstimate
    : public Products::LocalizableBase<internal::DiffusiveFluxEstimateTraits<GridViewImp, DiffusionFactorType,
                                                                             DiffusiveFluxType, RangeImp, SourceImp,
                                                                             FieldImp, DiffusionTensorType>>
{
  typedef Products::LocalizableBase<internal::DiffusiveFluxEstimateTraits<GridViewImp, DiffusionFactorType,
                                                                          DiffusiveFluxType, RangeImp, SourceImp,
                                                                          FieldImp, DiffusionTensorType>> BaseType;

public:
  typedef internal::DiffusiveFluxEstimateTraits<GridViewImp, DiffusionFactorType, DiffusiveFluxType, RangeImp,
                                                SourceImp, FieldImp, DiffusionTensorType> Traits;
  using typename BaseType::GridViewType;
  using typename BaseType::RangeType;
  using typename BaseType::SourceType;
  typedef typename Traits::LocalOperatorType LocalOperatorType;

  DiffusiveFluxEstimate(const GridViewType& grd_vw, const RangeType& rng, const SourceType& src,
                        const DiffusionFactorType& diffusion_factor, const DiffusionTensorType& diffusion_tensor,
                        const DiffusiveFluxType& diffusive_flux, const size_t over_integrate = 0)
    : BaseType(grd_vw, rng, src)
    , diffusion_factor_(diffusion_factor)
    , diffusion_tensor_(diffusion_tensor)
    , diffusive_flux_(diffusive_flux)
    , local_operator_(over_integrate, diffusion_factor_, diffusion_tensor_, diffusive_flux_)
  {
  }

  ~DiffusiveFluxEstimate()
  {
  }

private:
  virtual const LocalOperatorType& local_operator() const DS_OVERRIDE DS_FINAL
  {
    return local_operator_;
  }

  const DiffusionFactorType& diffusion_factor_;
  const DiffusionTensorType& diffusion_tensor_;
  const DiffusiveFluxType& diffusive_flux_;
  const LocalOperatorType local_operator_;
}; // class DiffusiveFluxEstimate

} // namespace ESV2007
} // namespace Products
} // namespace GDT
} // namespace Dune

#endif // DUNE_GDT_PRODUCTS_ESV2007_HH
<|endoftext|>


<commit_before>#include <ptrace.hh>
#include <utils.hh>

#include <unistd.h>
#include <sys/ptrace.h>
#include <sys/user.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sched.h>
#include <map>
#include <list>

class Ptrace : public IPtrace
{
public:
	Ptrace()
	{
		m_breakpointId = 0;
	}

	bool readMemory(uint8_t *dst, void *start, size_t bytes)
	{
		memcpy(dst, start, bytes);

		return true;
	}

	int forkAndAttach()
	{
		pid_t child, who;
		int status;

		child = fork();
		if (child < 0) {
			error("fork failed!\n");
			return -1;
		}

		if (child == 0) {
			int res;

			/* We're in the child, set me as traced */
			res = ptrace(PTRACE_TRACEME, 0, 0, 0);
			if (res < 0) {
				error("Can't set me as ptraced");
				return -1;
			}
			kill(getpid(), SIGSTOP);

			return 0;
		}

		/* Wait for the initial stop */
		who = waitpid(child, &status, 0);
		if (who < 0) {
			error("waitpid failed");
			return -1;
		}
		if (!WIFSTOPPED(status)) {
			error("Child hasn't stopped: %x\n", status);
			return -1;
		}
		ptrace(PTRACE_SETOPTIONS, child, 0, PTRACE_O_TRACECLONE | PTRACE_O_TRACEFORK);

		m_child = child;

		return child;
	}

	int setBreakpoint(void *addr)
	{
		uint8_t data;
		int id;

		// There already?
		if (m_addrToBreakpointMap.find(addr) != m_addrToBreakpointMap.end())
			return m_addrToBreakpointMap[addr];

		if (readMemory(&data, addr, 1) == false)
			return -1;

		id = m_breakpointId++;

		m_breakpointToAddrMap[id] = addr;
		m_addrToBreakpointMap[addr] = id;
		m_instructionMap[addr] = data;

		// Set the breakpoint
		writeByte(m_child, addr, 0xcc);

		return -1;
	}

	bool clearBreakpoint(int id)
	{
		if (m_breakpointToAddrMap.find(id) == m_breakpointToAddrMap.end())
			return false;

		void *addr = m_breakpointToAddrMap[id];

		panic_if(m_addrToBreakpointMap.find(addr) == m_addrToBreakpointMap.end(),
				"Breakpoint id, but no addr-to-id map!");

		panic_if(m_instructionMap.find(addr) == m_instructionMap.end(),
				"Breakpoint found, but no instruction data at that point!");

		m_breakpointToAddrMap.erase(id);
		m_addrToBreakpointMap.erase(addr);

		// Clear the actual breakpoint instruction
		writeByte(m_child, addr, m_instructionMap[addr]);

		return true;
	}

	void saveRegisters(int pid, void *regs)
	{
		ptrace(PTRACE_GETREGS, pid, 0, regs);
	}

	void loadRegisters(int pid, void *regs)
	{
		ptrace(PTRACE_SETREGS, pid, 0, regs);
	}

	void singleStep(int pid)
	{
		void *pc = getPc(pid);

		panic_if(m_instructionMap.find(pc) == m_instructionMap.end(),
				"Single-step over no breakpoint at %p", pc);

		writeByte(pid, pc, m_instructionMap[pc]);
		long res = ptrace(PTRACE_SINGLESTEP, pid, 0, NULL);
		panic_if(res < 0,
				"ptrace singlestep failed!\n");
		writeByte(pid, pc, 0xcc);
	}

	const PtraceEvent continueExecution(int pid)
	{
		PtraceEvent out;
		int status;
		int who;

		// Assume error
		out.type = ptrace_error;
		out.eventId = -1;
		out.addr = NULL;

		ptrace(PTRACE_CONT, pid, 0, 0);

		who = waitpid(pid, &status, __WALL);
		if (who == -1)
			return out;

		// A signal?
		if (WIFSTOPPED(status)) {
			// A trap?
			if (WSTOPSIG(status) == SIGTRAP) {
				out.type = ptrace_breakpoint;
				out.eventId = -1;
				out.addr = getPc(pid);

				// Breakpoint id
				addrToBreakpointMap_t::iterator it = m_addrToBreakpointMap.find(out.addr);
				if (it != m_addrToBreakpointMap.end())
					out.eventId = it->second;

				return out;
			}
			// No, deliver it directly
			ptrace(PTRACE_CONT, who, 0, WSTOPSIG(status));
		}
		// Thread died?
		if (WIFSIGNALED(status) || WIFEXITED(status)) {
			if (who == pid) {
				out.type = ptrace_exit;
				out.eventId = -1;
				out.addr = NULL;
				return out;
			}
		}

		return out;
	}

private:
	void *getPc(int pid)
	{
		struct user_regs_struct regs;

		memset(&regs, 0, sizeof(regs));
		ptrace(PTRACE_GETREGS, pid, 0, &regs);

		return (void *)(regs.eip - 1);
	}

	// Assume x86 with single-byte breakpoint instructions for now...
	void writeByte(int pid, void *addr, uint8_t byte)
	{
		unsigned long aligned = getAligned((unsigned long)addr);
		unsigned long offs = (unsigned long)addr - aligned;
		unsigned long shift = 8 * offs;
		unsigned long data = byte;
		unsigned long old_data;
		unsigned long val;

		old_data = ptrace(PTRACE_PEEKTEXT, pid, 0, 0);
		val = (old_data & ~(0xffUL << shift)) | (data << shift);
		ptrace(PTRACE_POKETEXT, pid, aligned, val);
	}

	unsigned long getAligned(unsigned long addr)
	{
		return (addr / sizeof(unsigned long)) * sizeof(unsigned long);
	}

	typedef std::map<int, void *> breakpointToAddrMap_t;
	typedef std::map<void *, int> addrToBreakpointMap_t;
	typedef std::map<void *, uint8_t> instructionMap_t;

	int m_breakpointId;

	instructionMap_t m_instructionMap;
	breakpointToAddrMap_t m_breakpointToAddrMap;
	addrToBreakpointMap_t m_addrToBreakpointMap;

	pid_t m_child;
};

IPtrace &IPtrace::getInstance()
{
	static Ptrace *instance;

	if (!instance)
		instance = new Ptrace();

	return *instance;
}
<commit_msg>ptrace: Correct setBreakpoint return value<commit_after>#include <ptrace.hh>
#include <utils.hh>

#include <unistd.h>
#include <sys/ptrace.h>
#include <sys/user.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sched.h>
#include <map>
#include <list>

class Ptrace : public IPtrace
{
public:
	Ptrace()
	{
		m_breakpointId = 0;
	}

	bool readMemory(uint8_t *dst, void *start, size_t bytes)
	{
		memcpy(dst, start, bytes);

		return true;
	}

	int forkAndAttach()
	{
		pid_t child, who;
		int status;

		child = fork();
		if (child < 0) {
			error("fork failed!\n");
			return -1;
		}

		if (child == 0) {
			int res;

			/* We're in the child, set me as traced */
			res = ptrace(PTRACE_TRACEME, 0, 0, 0);
			if (res < 0) {
				error("Can't set me as ptraced");
				return -1;
			}
			kill(getpid(), SIGSTOP);

			return 0;
		}

		/* Wait for the initial stop */
		who = waitpid(child, &status, 0);
		if (who < 0) {
			error("waitpid failed");
			return -1;
		}
		if (!WIFSTOPPED(status)) {
			error("Child hasn't stopped: %x\n", status);
			return -1;
		}
		ptrace(PTRACE_SETOPTIONS, child, 0, PTRACE_O_TRACECLONE | PTRACE_O_TRACEFORK);

		m_child = child;

		return child;
	}

	int setBreakpoint(void *addr)
	{
		uint8_t data;
		int id;

		// There already?
		if (m_addrToBreakpointMap.find(addr) != m_addrToBreakpointMap.end())
			return m_addrToBreakpointMap[addr];

		if (readMemory(&data, addr, 1) == false)
			return -1;

		id = m_breakpointId++;

		m_breakpointToAddrMap[id] = addr;
		m_addrToBreakpointMap[addr] = id;
		m_instructionMap[addr] = data;

		// Set the breakpoint
		writeByte(m_child, addr, 0xcc);

		return id;
	}

	bool clearBreakpoint(int id)
	{
		if (m_breakpointToAddrMap.find(id) == m_breakpointToAddrMap.end())
			return false;

		void *addr = m_breakpointToAddrMap[id];

		panic_if(m_addrToBreakpointMap.find(addr) == m_addrToBreakpointMap.end(),
				"Breakpoint id, but no addr-to-id map!");

		panic_if(m_instructionMap.find(addr) == m_instructionMap.end(),
				"Breakpoint found, but no instruction data at that point!");

		m_breakpointToAddrMap.erase(id);
		m_addrToBreakpointMap.erase(addr);

		// Clear the actual breakpoint instruction
		writeByte(m_child, addr, m_instructionMap[addr]);

		return true;
	}

	void saveRegisters(int pid, void *regs)
	{
		ptrace(PTRACE_GETREGS, pid, 0, regs);
	}

	void loadRegisters(int pid, void *regs)
	{
		ptrace(PTRACE_SETREGS, pid, 0, regs);
	}

	void singleStep(int pid)
	{
		void *pc = getPc(pid);

		panic_if(m_instructionMap.find(pc) == m_instructionMap.end(),
				"Single-step over no breakpoint at %p", pc);

		writeByte(pid, pc, m_instructionMap[pc]);
		long res = ptrace(PTRACE_SINGLESTEP, pid, 0, NULL);
		panic_if(res < 0,
				"ptrace singlestep failed!\n");
		writeByte(pid, pc, 0xcc);
	}

	const PtraceEvent continueExecution(int pid)
	{
		PtraceEvent out;
		int status;
		int who;

		// Assume error
		out.type = ptrace_error;
		out.eventId = -1;
		out.addr = NULL;

		ptrace(PTRACE_CONT, pid, 0, 0);

		who = waitpid(pid, &status, __WALL);
		if (who == -1)
			return out;

		// A signal?
		if (WIFSTOPPED(status)) {
			// A trap?
			if (WSTOPSIG(status) == SIGTRAP) {
				out.type = ptrace_breakpoint;
				out.eventId = -1;
				out.addr = getPc(pid);

				// Breakpoint id
				addrToBreakpointMap_t::iterator it = m_addrToBreakpointMap.find(out.addr);
				if (it != m_addrToBreakpointMap.end())
					out.eventId = it->second;

				return out;
			}
			// No, deliver it directly
			ptrace(PTRACE_CONT, who, 0, WSTOPSIG(status));
		}
		// Thread died?
		if (WIFSIGNALED(status) || WIFEXITED(status)) {
			if (who == pid) {
				out.type = ptrace_exit;
				out.eventId = -1;
				out.addr = NULL;
				return out;
			}
		}

		return out;
	}

private:
	void *getPc(int pid)
	{
		struct user_regs_struct regs;

		memset(&regs, 0, sizeof(regs));
		ptrace(PTRACE_GETREGS, pid, 0, &regs);

		return (void *)(regs.eip - 1);
	}

	// Assume x86 with single-byte breakpoint instructions for now...
	void writeByte(int pid, void *addr, uint8_t byte)
	{
		unsigned long aligned = getAligned((unsigned long)addr);
		unsigned long offs = (unsigned long)addr - aligned;
		unsigned long shift = 8 * offs;
		unsigned long data = byte;
		unsigned long old_data;
		unsigned long val;

		old_data = ptrace(PTRACE_PEEKTEXT, pid, 0, 0);
		val = (old_data & ~(0xffUL << shift)) | (data << shift);
		ptrace(PTRACE_POKETEXT, pid, aligned, val);
	}

	unsigned long getAligned(unsigned long addr)
	{
		return (addr / sizeof(unsigned long)) * sizeof(unsigned long);
	}

	typedef std::map<int, void *> breakpointToAddrMap_t;
	typedef std::map<void *, int> addrToBreakpointMap_t;
	typedef std::map<void *, uint8_t> instructionMap_t;

	int m_breakpointId;

	instructionMap_t m_instructionMap;
	breakpointToAddrMap_t m_breakpointToAddrMap;
	addrToBreakpointMap_t m_addrToBreakpointMap;

	pid_t m_child;
};

IPtrace &IPtrace::getInstance()
{
	static Ptrace *instance;

	if (!instance)
		instance = new Ptrace();

	return *instance;
}
<|endoftext|>


<commit_before>#ifndef __NODE_OSRM_QUERY_H__
#define __NODE_OSRM_QUERY_H__

// v8
#include <v8.h>

// node
#include <node.h>
#include <node_version.h>
#include <node_object_wrap.h>

#include <OSRM.h>

using namespace v8;

namespace node_osrm {

typedef boost::shared_ptr<RouteParameters> route_parameters_ptr;

class Query: public node::ObjectWrap {
public:
    static Persistent<FunctionTemplate> constructor;
    static void Initialize(Handle<Object> target);
    static Handle<Value> New(Arguments const& args);
    Query();
    inline route_parameters_ptr get() { return this_; }
    void _ref() { Ref(); }
    void _unref() { Unref(); }
private:
    ~Query();
    route_parameters_ptr this_;
};

Persistent<FunctionTemplate> Query::constructor;

void Query::Initialize(Handle<Object> target) {
    HandleScope scope;
    constructor = Persistent<FunctionTemplate>::New(FunctionTemplate::New(Query::New));
    constructor->InstanceTemplate()->SetInternalFieldCount(1);
    constructor->SetClassName(String::NewSymbol("Query"));
    target->Set(String::NewSymbol("Query"),constructor->GetFunction());
}

Query::Query()
  : ObjectWrap(),
    this_(boost::make_shared<RouteParameters>()) { }

Query::~Query() { }

Handle<Value> Query::New(Arguments const& args)
{
    HandleScope scope;
    if (!args.IsConstructCall()) {
        return ThrowException(Exception::Error(String::New("Cannot call constructor as function, you need to use 'new' keyword")));
    }
    try {
        if (args.Length() != 1) {
            return ThrowException(Exception::TypeError(String::New("please provide an object of options for the first argument")));
        }
        if (!args[0]->IsObject()) {
            return ThrowException(Exception::TypeError(String::New("first argument must be an object")));
        }
        Local<Object> obj = args[0]->ToObject();
        if (obj->IsNull() || obj->IsUndefined()) {
            return ThrowException(Exception::TypeError(String::New("first arg must be an object")));
        }
        if (!obj->Has(String::NewSymbol("coordinates"))) {
            return ThrowException(Exception::TypeError(String::New("must provide a coordinates property")));
        }
        Local<Value> coordinates = obj->Get(String::New("coordinates"));
        if (!coordinates->IsArray()) {
            return ThrowException(Exception::TypeError(String::New("coordinates must be an array of (lat/long) pairs")));
        }
        Local<Array> coordinates_array = Local<Array>::Cast(coordinates);
        if (coordinates_array->Length() < 2) {
            return ThrowException(Exception::TypeError(String::New("at least two coordinates must be provided")));
        }

        Query* q = new Query();
        q->this_->zoomLevel = 18; //no generalization
        q->this_->printInstructions = true; //turn by turn instructions
        q->this_->alternateRoute = true; //get an alternate route, too
        q->this_->geometry = true; //retrieve geometry of route
        q->this_->compression = true; //polyline encoding
        q->this_->checkSum = UINT_MAX; //see wiki
        q->this_->service = "viaroute"; //that's routing
        q->this_->outputFormat = "json";
        q->this_->jsonpParameter = ""; //set for jsonp wrapping
        q->this_->language = ""; //unused atm

        for (uint32_t i = 0; i < coordinates_array->Length(); ++i) {
            Local<Value> coordinate = coordinates_array->Get(i);
            if (!coordinate->IsArray()) {
                return ThrowException(Exception::TypeError(String::New("coordinates must be an array of (lat/long) pairs")));
            }
            Local<Array> coordinate_array = Local<Array>::Cast(coordinate);
            if (coordinate_array->Length() != 2) {
                return ThrowException(Exception::TypeError(String::New("coordinates must be an array of (lat/long) pairs")));
            }
            q->this_->coordinates.push_back(
                FixedPointCoordinate(coordinate_array->Get(0)->NumberValue()*COORDINATE_PRECISION,
                                     coordinate_array->Get(1)->NumberValue()*COORDINATE_PRECISION));
        }

        q->Wrap(args.This());
        return args.This();
    } catch (std::exception const& ex) {
        return ThrowException(Exception::TypeError(String::New(ex.what())));
    }
    return Undefined();
}

} // namespace node_osrm

#endif // __NODE_OSRM_QUERY_H__
<commit_msg>Support alternateRoute option<commit_after>#ifndef __NODE_OSRM_QUERY_H__
#define __NODE_OSRM_QUERY_H__

// v8
#include <v8.h>

// node
#include <node.h>
#include <node_version.h>
#include <node_object_wrap.h>

#include <OSRM.h>

using namespace v8;

namespace node_osrm {

typedef boost::shared_ptr<RouteParameters> route_parameters_ptr;

class Query: public node::ObjectWrap {
public:
    static Persistent<FunctionTemplate> constructor;
    static void Initialize(Handle<Object> target);
    static Handle<Value> New(Arguments const& args);
    Query();
    inline route_parameters_ptr get() { return this_; }
    void _ref() { Ref(); }
    void _unref() { Unref(); }
private:
    ~Query();
    route_parameters_ptr this_;
};

Persistent<FunctionTemplate> Query::constructor;

void Query::Initialize(Handle<Object> target) {
    HandleScope scope;
    constructor = Persistent<FunctionTemplate>::New(FunctionTemplate::New(Query::New));
    constructor->InstanceTemplate()->SetInternalFieldCount(1);
    constructor->SetClassName(String::NewSymbol("Query"));
    target->Set(String::NewSymbol("Query"),constructor->GetFunction());
}

Query::Query()
  : ObjectWrap(),
    this_(boost::make_shared<RouteParameters>()) { }

Query::~Query() { }

Handle<Value> Query::New(Arguments const& args)
{
    HandleScope scope;
    if (!args.IsConstructCall()) {
        return ThrowException(Exception::Error(String::New("Cannot call constructor as function, you need to use 'new' keyword")));
    }
    try {
        if (args.Length() != 1) {
            return ThrowException(Exception::TypeError(String::New("please provide an object of options for the first argument")));
        }
        if (!args[0]->IsObject()) {
            return ThrowException(Exception::TypeError(String::New("first argument must be an object")));
        }
        Local<Object> obj = args[0]->ToObject();
        if (obj->IsNull() || obj->IsUndefined()) {
            return ThrowException(Exception::TypeError(String::New("first arg must be an object")));
        }
        if (!obj->Has(String::NewSymbol("coordinates"))) {
            return ThrowException(Exception::TypeError(String::New("must provide a coordinates property")));
        }
        Local<Value> coordinates = obj->Get(String::New("coordinates"));
        if (!coordinates->IsArray()) {
            return ThrowException(Exception::TypeError(String::New("coordinates must be an array of (lat/long) pairs")));
        }
        Local<Array> coordinates_array = Local<Array>::Cast(coordinates);
        if (coordinates_array->Length() < 2) {
            return ThrowException(Exception::TypeError(String::New("at least two coordinates must be provided")));
        }

        Query* q = new Query();
        q->this_->zoomLevel = 18; //no generalization
        q->this_->printInstructions = true; //turn by turn instructions
        q->this_->alternateRoute = true; //get an alternate route, too
        q->this_->geometry = true; //retrieve geometry of route
        q->this_->compression = true; //polyline encoding
        q->this_->checkSum = UINT_MAX; //see wiki
        q->this_->service = "viaroute"; //that's routing
        q->this_->outputFormat = "json";
        q->this_->jsonpParameter = ""; //set for jsonp wrapping
        q->this_->language = ""; //unused atm

        if (obj->Has(String::NewSymbol("alternateRoute"))) {
            q->this_->alternateRoute = obj->Get(String::New("alternateRoute"))->BooleanValue();
        }

        for (uint32_t i = 0; i < coordinates_array->Length(); ++i) {
            Local<Value> coordinate = coordinates_array->Get(i);
            if (!coordinate->IsArray()) {
                return ThrowException(Exception::TypeError(String::New("coordinates must be an array of (lat/long) pairs")));
            }
            Local<Array> coordinate_array = Local<Array>::Cast(coordinate);
            if (coordinate_array->Length() != 2) {
                return ThrowException(Exception::TypeError(String::New("coordinates must be an array of (lat/long) pairs")));
            }
            q->this_->coordinates.push_back(
                FixedPointCoordinate(coordinate_array->Get(0)->NumberValue()*COORDINATE_PRECISION,
                                     coordinate_array->Get(1)->NumberValue()*COORDINATE_PRECISION));
        }

        q->Wrap(args.This());
        return args.This();
    } catch (std::exception const& ex) {
        return ThrowException(Exception::TypeError(String::New(ex.what())));
    }
    return Undefined();
}

} // namespace node_osrm

#endif // __NODE_OSRM_QUERY_H__
<|endoftext|>


<commit_before>/*
 * Utilities for dealing with regular expressions.
 *
 * author: Max Kellermann <mk@cm4all.com>
 */

#ifndef BENG_PROXY_REGEX_HXX
#define BENG_PROXY_REGEX_HXX

#include <glib.h>

#include <algorithm>

class Error;

class RegexPointer {
protected:
    GRegex *re = nullptr;

    explicit constexpr RegexPointer(GRegex *_re):re(_re) {}

public:
    RegexPointer() = default;
    RegexPointer(const RegexPointer &) = default;

    constexpr bool IsDefined() const {
        return re != nullptr;
    }

    bool Match(const char *s, GMatchInfo **match_info=nullptr) const {
        return g_regex_match(re, s, GRegexMatchFlags(0), match_info);
    }
};

class UniqueRegex : public RegexPointer {
public:
    UniqueRegex() = default;

    UniqueRegex(UniqueRegex &&src):RegexPointer(src) {
        src.re = nullptr;
    }

    ~UniqueRegex() {
        if (re != nullptr)
            g_regex_unref(re);
    }

    UniqueRegex &operator=(UniqueRegex &&src) {
        std::swap(re, src.re);
        return *this;
    }

    bool Compile(const char *pattern, bool capture, GError **error_r) {
        constexpr GRegexCompileFlags default_compile_flags =
            GRegexCompileFlags(G_REGEX_MULTILINE|G_REGEX_DOTALL|
                               G_REGEX_RAW|G_REGEX_NO_AUTO_CAPTURE|
                               G_REGEX_OPTIMIZE);

        auto compile_flags = default_compile_flags;
        if (capture)
            compile_flags = GRegexCompileFlags(compile_flags &
                                               ~G_REGEX_NO_AUTO_CAPTURE);

        return g_regex_new(pattern, compile_flags, GRegexMatchFlags(0),
                           error_r);
    }

    bool Compile(const char *pattern, bool capture, Error &error);
};

struct pool;

/**
 * @return nullptr on error
 */
const char *
expand_string(struct pool *pool, const char *src,
              const GMatchInfo *match_info, GError **error_r);

/**
 * Like expand_string(), but unescape the substitutions with the '%'
 * URI method.
 *
 * @return nullptr on error
 */
const char *
expand_string_unescaped(struct pool *pool, const char *src,
                        const GMatchInfo *match_info,
                        GError **error_r);

#endif
<commit_msg>regex: fix Compile() return value<commit_after>/*
 * Utilities for dealing with regular expressions.
 *
 * author: Max Kellermann <mk@cm4all.com>
 */

#ifndef BENG_PROXY_REGEX_HXX
#define BENG_PROXY_REGEX_HXX

#include <glib.h>

#include <algorithm>

class Error;

class RegexPointer {
protected:
    GRegex *re = nullptr;

    explicit constexpr RegexPointer(GRegex *_re):re(_re) {}

public:
    RegexPointer() = default;
    RegexPointer(const RegexPointer &) = default;

    constexpr bool IsDefined() const {
        return re != nullptr;
    }

    bool Match(const char *s, GMatchInfo **match_info=nullptr) const {
        return g_regex_match(re, s, GRegexMatchFlags(0), match_info);
    }
};

class UniqueRegex : public RegexPointer {
public:
    UniqueRegex() = default;

    UniqueRegex(UniqueRegex &&src):RegexPointer(src) {
        src.re = nullptr;
    }

    ~UniqueRegex() {
        if (re != nullptr)
            g_regex_unref(re);
    }

    UniqueRegex &operator=(UniqueRegex &&src) {
        std::swap(re, src.re);
        return *this;
    }

    bool Compile(const char *pattern, bool capture, GError **error_r) {
        constexpr GRegexCompileFlags default_compile_flags =
            GRegexCompileFlags(G_REGEX_MULTILINE|G_REGEX_DOTALL|
                               G_REGEX_RAW|G_REGEX_NO_AUTO_CAPTURE|
                               G_REGEX_OPTIMIZE);

        auto compile_flags = default_compile_flags;
        if (capture)
            compile_flags = GRegexCompileFlags(compile_flags &
                                               ~G_REGEX_NO_AUTO_CAPTURE);

        re = g_regex_new(pattern, compile_flags, GRegexMatchFlags(0),
                         error_r);
        return re != nullptr;
    }

    bool Compile(const char *pattern, bool capture, Error &error);
};

struct pool;

/**
 * @return nullptr on error
 */
const char *
expand_string(struct pool *pool, const char *src,
              const GMatchInfo *match_info, GError **error_r);

/**
 * Like expand_string(), but unescape the substitutions with the '%'
 * URI method.
 *
 * @return nullptr on error
 */
const char *
expand_string_unescaped(struct pool *pool, const char *src,
                        const GMatchInfo *match_info,
                        GError **error_r);

#endif
<|endoftext|>