<commit_before>// Copyright (c) 2012 Cloudera, Inc. All rights reserved.

#include "sparrow/state-store-subscriber-service.h"

#include <iostream>
#include <utility>

#include <boost/algorithm/string/join.hpp>
#include <boost/foreach.hpp>
#include <boost/format.hpp>
#include <concurrency/PosixThreadFactory.h>
#include <concurrency/Thread.h>
#include <concurrency/ThreadManager.h>
#include <glog/logging.h>
#include <gflags/gflags.h>
#include <protocol/TBinaryProtocol.h>
#include <transport/TBufferTransports.h>
#include <transport/TServerSocket.h>
#include <transport/TSocket.h>

#include "common/status.h"
#include "gen-cpp/StateStoreService_types.h"
#include "gen-cpp/StateStoreSubscriberService_types.h"

using namespace std;
using namespace boost;
using namespace ::apache::thrift;
using namespace ::apache::thrift::protocol;
using namespace ::apache::thrift::transport;
using namespace ::apache::thrift::server;
using impala::Status;
using impala::THostPort;
using impala::TStatusCode;

namespace sparrow {

const char* StateStoreSubscriber::DISCONNECTED_FROM_STATE_STORE_ERROR =
    "Client disconnected from state store";

StateStoreSubscriber::StateStoreSubscriber(const string& host, int port,
                                           const string& state_store_host,
                                           int state_store_port)
  : server_running_(false) {
  host_port_.host = host;
  host_port_.port = port;
  state_store_host_port_.host = state_store_host;
  state_store_host_port_.port = state_store_port;
}

StateStoreSubscriber::~StateStoreSubscriber() {
  if (!IsRunning()) {
    LOG(ERROR) << "StateStoreSubscriber destructed before being properly shut "
               << "down (using Stop())";
    // This assumes that Stop() cannot be called in a different thread.
    Stop();
  }
}

Status StateStoreSubscriber::RegisterService(const string& service_id,
                                             const THostPort& address) {
  RETURN_IF_ERROR(InitClient());

  TRegisterServiceRequest request;
  request.__set_subscriber_address(host_port_);
  request.__set_service_id(service_id);
  request.__set_service_address(address);
  TRegisterServiceResponse response;
  VLOG(1) << "Attempting to register service " << request.service_id
          << " on subscriber at " << request.subscriber_address.host << ":"
          << request.subscriber_address.port;

  try {
    client_->RegisterService(response, request);
  } catch (TTransportException& e) {
    // Client has gotten disconnected from the state store.
    Status status(e.what());
    status.AddErrorMsg(DISCONNECTED_FROM_STATE_STORE_ERROR);
    return status;
  }
  Status status(response.status);
  if (status.ok()) {
    services_.insert(service_id);
  }
  return status;
}

Status StateStoreSubscriber::UnregisterService(const string& service_id) {
  RETURN_IF_ERROR(InitClient());

  unordered_set<string>::iterator service = services_.find(service_id);
  if (service == services_.end()) {
    format error_status("Service id %1% not registered with this subscriber");
    error_status % service_id;
    return Status(error_status.str());
  }

  TUnregisterServiceRequest request;
  request.__set_subscriber_address(host_port_);
  request.__set_service_id(service_id);
  TUnregisterServiceResponse response;

  try {
    client_->UnregisterService(response, request);
  } catch ( TTransportException& e) {
    Status status(e.what());
    status.AddErrorMsg(DISCONNECTED_FROM_STATE_STORE_ERROR);
    return status;
  }
  Status status(response.status);
  if (status.ok()) {
    services_.erase(service);
  }
  return status;
}

Status StateStoreSubscriber::RegisterSubscription(
    const SubscriptionManager::UpdateCallback& update_callback,
    const unordered_set<string>& update_services, SubscriptionId* id) {
  RETURN_IF_ERROR(InitClient());

  TRegisterSubscriptionRequest request;
  request.__set_subscriber_address(host_port_);
  request.services.insert(update_services.begin(), update_services.end());
  request.__isset.services = true;
  TRegisterSubscriptionResponse response;
  VLOG(1) << "Attempting to register subscriber for services "
          << algorithm::join(update_services, ", ") << " at "
          << request.subscriber_address.host << ":" << request.subscriber_address.port;

  try {
    client_->RegisterSubscription(response, request);
  } catch (TTransportException& e) {
    // Client has gotten disconnected from the state store.
    Status status(e.what());
    status.AddErrorMsg(DISCONNECTED_FROM_STATE_STORE_ERROR);
    return status;
  }

  Status status(response.status);
  if (!status.ok()) {
    return status;
  }
  if (!response.__isset.subscription_id) {
    status.AddErrorMsg("Invalid response: subscription_id not set.");
    return status;
  }

  *id = response.subscription_id;
  lock_guard<mutex> lock(update_callbacks_lock_);
  update_callbacks_.insert(make_pair(response.subscription_id, update_callback));
  return status;
}

Status StateStoreSubscriber::UnregisterSubscription(SubscriptionId id) {
  RETURN_IF_ERROR(InitClient());

  {
    lock_guard<mutex> lock(update_callbacks_lock_);
    UpdateCallbacks::iterator callback = update_callbacks_.find(id);
    if (callback == update_callbacks_.end()) {
      format error_status("Subscription id %1% not registered with this subscriber");
      error_status % id;
      return Status(error_status.str());
    }
  }

  TUnregisterSubscriptionRequest request;
  request.__set_subscriber_address(host_port_);
  request.__set_subscription_id(id);
  TUnregisterSubscriptionResponse response;
  try {
    client_->UnregisterSubscription(response, request);
  } catch (TTransportException& e) {
    Status status(e.what());
    status.AddErrorMsg(DISCONNECTED_FROM_STATE_STORE_ERROR);
    return status;
  }

  Status status(response.status);
  if (status.ok()) {
    lock_guard<mutex> lock(update_callbacks_lock_);
    // Don't use the iterator to erase, because it may have been invalidated by now.
    update_callbacks_.erase(id);
  }
  return Status(response.status);
}

void StateStoreSubscriber::UpdateState(TUpdateStateResponse& response,
                                       const TUpdateStateRequest& request) {
  RETURN_IF_UNSET(request, service_memberships, response);

  ServiceStateMap state;
  StateFromThrift(request, &state);

  // Log all of the new state we just got.
  stringstream new_state;
  BOOST_FOREACH(const ServiceStateMap::value_type& service_state, state) {
    new_state << "State for service " << service_state.first << ":\n" << "Membership: ";
    BOOST_FOREACH(const Membership::value_type& instance,
                  service_state.second.membership) {
      new_state << instance.second.host << ":" << instance.second.port
                << " (at subscriber " << instance.first << "),";
    }
    new_state << "\n";
    // TODO: Log object updates here too, once we include them.
  }
  VLOG(1) << "Received new state:\n" << new_state.str();

  // Make a copy of update_callbacks_, to avoid problems if one of the callbacks
  // calls back into this StateStoreSubscriber, which may deadlock if we are holding
  // the update_callbacks_lock_.
  UpdateCallbacks update_callbacks_copy;
  {
    lock_guard<mutex> lock(update_callbacks_lock_);
    update_callbacks_copy = update_callbacks_;
  }

  // TODO: This is problematic if any of the callbacks take a long time. Eventually,
  // we'll probably want to execute the callbacks asynchronously in a different thread.
  BOOST_FOREACH(UpdateCallbacks::value_type& update, update_callbacks_copy) {
    update.second(state);
  }
  RETURN_AND_SET_STATUS_OK(response);
}

void StateStoreSubscriber::Start() {
  shared_ptr<TProcessor> processor(
      new StateStoreSubscriberServiceProcessor(shared_from_this()));
  shared_ptr<TServerTransport> server_transport(new TServerSocket(host_port_.port));
  shared_ptr<TTransportFactory> transport_factory(new TBufferedTransportFactory());
  shared_ptr<TProtocolFactory> protocol_factory(new TBinaryProtocolFactory());

  LOG(INFO) << "StateStoreSubscriber listening on " << host_port_.port;
  server_.reset(new TSimpleServer(processor, server_transport, transport_factory,
                                  protocol_factory));

  DCHECK(!server_running_);
  server_running_ = true;
  server_thread_.reset(new thread(&TSimpleServer::serve, server_));
}

bool StateStoreSubscriber::IsRunning() {
  return server_running_;
}

void StateStoreSubscriber::Stop() {
  Status status = InitClient();
  if (status.ok()) {
    try {
      // Unregister all running services.
      BOOST_FOREACH(const string& service_id, services_) {
        TUnregisterServiceRequest request;
        request.__set_subscriber_address(host_port_);
        request.__set_service_id(service_id);
        TUnregisterServiceResponse response;
        client_->UnregisterService(response, request);
        Status unregister_status(response.status);
        if (!unregister_status.ok()) {
          LOG(ERROR) << "Error when unregistering service " << service_id << ":"
                     << unregister_status.GetErrorMsg();
        }
      }

     lock_guard<mutex> lock(update_callbacks_lock_);
      // Unregister all subscriptions.
      BOOST_FOREACH(const UpdateCallbacks::value_type& callback_pair,
                    update_callbacks_) {
        SubscriptionId id = callback_pair.first;
        TUnregisterSubscriptionRequest request;
        request.__set_subscriber_address(host_port_);
        request.__set_subscription_id(id);
        TUnregisterSubscriptionResponse response;
        // Ignore any errors in the response.
        client_->UnregisterSubscription(response, request);
        Status unregister_status(response.status);
        if (!unregister_status.ok()) {
          string error_msg;
          unregister_status.GetErrorMsg(&error_msg);
          VLOG(1) << "Error when unregistering subscription " << id << ":"
                  << error_msg;
        }
      }
    } catch (TTransportException& e) {
      LOG(ERROR) << "Connection to state store disrupted when trying to unregister; "
                 << "received error: " << e.what();
    }
  }

  DCHECK(server_running_);
  server_->stop();
  server_running_ = false;
  // TODO: The server seems to keep going indefinitely if the subscriber still has a
  // connection to the state store, causing this to not return.  See if this is possible
  // to fix.
  //server_thread_->join();
}

Status StateStoreSubscriber::InitClient() {
  DCHECK(server_running_);

  Status status;
  if (client_.get() == NULL) {
    shared_ptr<TSocket> socket(new TSocket(state_store_host_port_.host,
                                           state_store_host_port_.port));
    shared_ptr<TTransport> transport(new TBufferedTransport(socket));
    shared_ptr<TProtocol> protocol(new TBinaryProtocol(transport));
    client_.reset(new StateStoreServiceClient(protocol));

    try {
      transport->open();
    } catch (TTransportException& e) {
      status.AddErrorMsg(e.what());
      status.AddErrorMsg("Unable to register with the StateStore");
    }
  }
  return status;
}

}
<commit_msg>Fix backend test failures<commit_after>// Copyright (c) 2012 Cloudera, Inc. All rights reserved.

#include "sparrow/state-store-subscriber-service.h"

#include <iostream>
#include <utility>

#include <boost/algorithm/string/join.hpp>
#include <boost/foreach.hpp>
#include <boost/format.hpp>
#include <concurrency/PosixThreadFactory.h>
#include <concurrency/Thread.h>
#include <concurrency/ThreadManager.h>
#include <glog/logging.h>
#include <gflags/gflags.h>
#include <protocol/TBinaryProtocol.h>
#include <transport/TBufferTransports.h>
#include <transport/TServerSocket.h>
#include <transport/TSocket.h>

#include "common/status.h"
#include "gen-cpp/StateStoreService_types.h"
#include "gen-cpp/StateStoreSubscriberService_types.h"

using namespace std;
using namespace boost;
using namespace ::apache::thrift;
using namespace ::apache::thrift::protocol;
using namespace ::apache::thrift::transport;
using namespace ::apache::thrift::server;
using impala::Status;
using impala::THostPort;
using impala::TStatusCode;

namespace sparrow {

const char* StateStoreSubscriber::DISCONNECTED_FROM_STATE_STORE_ERROR =
    "Client disconnected from state store";

StateStoreSubscriber::StateStoreSubscriber(const string& host, int port,
                                           const string& state_store_host,
                                           int state_store_port)
  : server_running_(false) {
  host_port_.host = host;
  host_port_.port = port;
  state_store_host_port_.host = state_store_host;
  state_store_host_port_.port = state_store_port;
}

StateStoreSubscriber::~StateStoreSubscriber() {
  if (IsRunning()) {
    Stop();
  }
}

Status StateStoreSubscriber::RegisterService(const string& service_id,
                                             const THostPort& address) {
  RETURN_IF_ERROR(InitClient());

  TRegisterServiceRequest request;
  request.__set_subscriber_address(host_port_);
  request.__set_service_id(service_id);
  request.__set_service_address(address);
  TRegisterServiceResponse response;
  VLOG(1) << "Attempting to register service " << request.service_id
          << " on subscriber at " << request.subscriber_address.host << ":"
          << request.subscriber_address.port;

  try {
    client_->RegisterService(response, request);
  } catch (TTransportException& e) {
    // Client has gotten disconnected from the state store.
    Status status(e.what());
    status.AddErrorMsg(DISCONNECTED_FROM_STATE_STORE_ERROR);
    return status;
  }
  Status status(response.status);
  if (status.ok()) {
    services_.insert(service_id);
  }
  return status;
}

Status StateStoreSubscriber::UnregisterService(const string& service_id) {
  RETURN_IF_ERROR(InitClient());

  unordered_set<string>::iterator service = services_.find(service_id);
  if (service == services_.end()) {
    format error_status("Service id %1% not registered with this subscriber");
    error_status % service_id;
    return Status(error_status.str());
  }

  TUnregisterServiceRequest request;
  request.__set_subscriber_address(host_port_);
  request.__set_service_id(service_id);
  TUnregisterServiceResponse response;

  try {
    client_->UnregisterService(response, request);
  } catch ( TTransportException& e) {
    Status status(e.what());
    status.AddErrorMsg(DISCONNECTED_FROM_STATE_STORE_ERROR);
    return status;
  }
  Status status(response.status);
  if (status.ok()) {
    services_.erase(service);
  }
  return status;
}

Status StateStoreSubscriber::RegisterSubscription(
    const SubscriptionManager::UpdateCallback& update_callback,
    const unordered_set<string>& update_services, SubscriptionId* id) {
  RETURN_IF_ERROR(InitClient());

  TRegisterSubscriptionRequest request;
  request.__set_subscriber_address(host_port_);
  request.services.insert(update_services.begin(), update_services.end());
  request.__isset.services = true;
  TRegisterSubscriptionResponse response;
  VLOG(1) << "Attempting to register subscriber for services "
          << algorithm::join(update_services, ", ") << " at "
          << request.subscriber_address.host << ":" << request.subscriber_address.port;

  try {
    client_->RegisterSubscription(response, request);
  } catch (TTransportException& e) {
    // Client has gotten disconnected from the state store.
    Status status(e.what());
    status.AddErrorMsg(DISCONNECTED_FROM_STATE_STORE_ERROR);
    return status;
  }

  Status status(response.status);
  if (!status.ok()) {
    return status;
  }
  if (!response.__isset.subscription_id) {
    status.AddErrorMsg("Invalid response: subscription_id not set.");
    return status;
  }

  *id = response.subscription_id;
  lock_guard<mutex> lock(update_callbacks_lock_);
  update_callbacks_.insert(make_pair(response.subscription_id, update_callback));
  return status;
}

Status StateStoreSubscriber::UnregisterSubscription(SubscriptionId id) {
  RETURN_IF_ERROR(InitClient());

  {
    lock_guard<mutex> lock(update_callbacks_lock_);
    UpdateCallbacks::iterator callback = update_callbacks_.find(id);
    if (callback == update_callbacks_.end()) {
      format error_status("Subscription id %1% not registered with this subscriber");
      error_status % id;
      return Status(error_status.str());
    }
  }

  TUnregisterSubscriptionRequest request;
  request.__set_subscriber_address(host_port_);
  request.__set_subscription_id(id);
  TUnregisterSubscriptionResponse response;
  try {
    client_->UnregisterSubscription(response, request);
  } catch (TTransportException& e) {
    Status status(e.what());
    status.AddErrorMsg(DISCONNECTED_FROM_STATE_STORE_ERROR);
    return status;
  }

  Status status(response.status);
  if (status.ok()) {
    lock_guard<mutex> lock(update_callbacks_lock_);
    // Don't use the iterator to erase, because it may have been invalidated by now.
    update_callbacks_.erase(id);
  }
  return Status(response.status);
}

void StateStoreSubscriber::UpdateState(TUpdateStateResponse& response,
                                       const TUpdateStateRequest& request) {
  RETURN_IF_UNSET(request, service_memberships, response);

  ServiceStateMap state;
  StateFromThrift(request, &state);

  // Log all of the new state we just got.
  stringstream new_state;
  BOOST_FOREACH(const ServiceStateMap::value_type& service_state, state) {
    new_state << "State for service " << service_state.first << ":\n" << "Membership: ";
    BOOST_FOREACH(const Membership::value_type& instance,
                  service_state.second.membership) {
      new_state << instance.second.host << ":" << instance.second.port
                << " (at subscriber " << instance.first << "),";
    }
    new_state << "\n";
    // TODO: Log object updates here too, once we include them.
  }
  VLOG(1) << "Received new state:\n" << new_state.str();

  // Make a copy of update_callbacks_, to avoid problems if one of the callbacks
  // calls back into this StateStoreSubscriber, which may deadlock if we are holding
  // the update_callbacks_lock_.
  UpdateCallbacks update_callbacks_copy;
  {
    lock_guard<mutex> lock(update_callbacks_lock_);
    update_callbacks_copy = update_callbacks_;
  }

  // TODO: This is problematic if any of the callbacks take a long time. Eventually,
  // we'll probably want to execute the callbacks asynchronously in a different thread.
  BOOST_FOREACH(UpdateCallbacks::value_type& update, update_callbacks_copy) {
    update.second(state);
  }
  RETURN_AND_SET_STATUS_OK(response);
}

void StateStoreSubscriber::Start() {
  shared_ptr<TProcessor> processor(
      new StateStoreSubscriberServiceProcessor(shared_from_this()));
  shared_ptr<TServerTransport> server_transport(new TServerSocket(host_port_.port));
  shared_ptr<TTransportFactory> transport_factory(new TBufferedTransportFactory());
  shared_ptr<TProtocolFactory> protocol_factory(new TBinaryProtocolFactory());

  LOG(INFO) << "StateStoreSubscriber listening on " << host_port_.port;
  server_.reset(new TSimpleServer(processor, server_transport, transport_factory,
                                  protocol_factory));

  DCHECK(!server_running_);
  server_running_ = true;
  server_thread_.reset(new thread(&TSimpleServer::serve, server_));
}

bool StateStoreSubscriber::IsRunning() {
  return server_running_;
}

void StateStoreSubscriber::Stop() {
  Status status = InitClient();
  if (status.ok()) {
    try {
      // Unregister all running services.
      BOOST_FOREACH(const string& service_id, services_) {
        TUnregisterServiceRequest request;
        request.__set_subscriber_address(host_port_);
        request.__set_service_id(service_id);
        TUnregisterServiceResponse response;
        client_->UnregisterService(response, request);
        Status unregister_status(response.status);
        if (!unregister_status.ok()) {
          LOG(ERROR) << "Error when unregistering service " << service_id << ":"
                     << unregister_status.GetErrorMsg();
        }
      }

     lock_guard<mutex> lock(update_callbacks_lock_);
      // Unregister all subscriptions.
      BOOST_FOREACH(const UpdateCallbacks::value_type& callback_pair,
                    update_callbacks_) {
        SubscriptionId id = callback_pair.first;
        TUnregisterSubscriptionRequest request;
        request.__set_subscriber_address(host_port_);
        request.__set_subscription_id(id);
        TUnregisterSubscriptionResponse response;
        // Ignore any errors in the response.
        client_->UnregisterSubscription(response, request);
        Status unregister_status(response.status);
        if (!unregister_status.ok()) {
          string error_msg;
          unregister_status.GetErrorMsg(&error_msg);
          VLOG(1) << "Error when unregistering subscription " << id << ":"
                  << error_msg;
        }
      }
    } catch (TTransportException& e) {
      LOG(ERROR) << "Connection to state store disrupted when trying to unregister; "
                 << "received error: " << e.what();
    }
  }

  DCHECK(server_running_);
  server_->stop();
  server_running_ = false;
  // TODO: The server seems to keep going indefinitely if the subscriber still has a
  // connection to the state store, causing this to not return.  See if this is possible
  // to fix.
  //server_thread_->join();
}

Status StateStoreSubscriber::InitClient() {
  DCHECK(server_running_);

  Status status;
  if (client_.get() == NULL) {
    shared_ptr<TSocket> socket(new TSocket(state_store_host_port_.host,
                                           state_store_host_port_.port));
    shared_ptr<TTransport> transport(new TBufferedTransport(socket));
    shared_ptr<TProtocol> protocol(new TBinaryProtocol(transport));
    client_.reset(new StateStoreServiceClient(protocol));

    try {
      transport->open();
    } catch (TTransportException& e) {
      status.AddErrorMsg(e.what());
      status.AddErrorMsg("Unable to register with the StateStore");
    }
  }
  return status;
}

}
<|endoftext|>


<commit_before>
//
// Kruskal's algorithm for minimum spanning trees.
//

#ifndef _KRUSKAL_MST_HH
#define _KRUSKAL_MST_HH

#include <algorithm>

#include "disjoint_sets.hh"
#include "graph.hh"

// Utility function to compare edge weights, used in sorting.
bool compare_edge_ptr_weight(const Edge* x, const Edge* y) {
  return x->weight < y->weight;
}

// Find the edges in the minimum spanning tree of g. Returns a pointer
// to a vector of Edge pointers. The Edge pointers refer to the Edge
// objects owned by g. The client is responsible for eventually
// deleting the returned vector.
vector<const Edge*>* kruskal_mst_edges(const Graph& g) {
  assert(!g.empty());

  // Sort the edges into nonincreasing order by weight. We use a
  // stable sort to make unit testing easier, but stability is not
  // otherwise necessary.
  vector<Edge*> sorted_edges = g.edges;
  stable_sort(sorted_edges.begin(),
	      sorted_edges.end(),
	      compare_edge_ptr_weight);

  // Use a disjoint set data structure to keep track of the patchwork
  // forest of spanned subgraphs that we'll create. Initially every
  // vertex is its own component; every time we add an edge, those
  // components get connected. When we're done the whole graph has
  // been connected into one component.
  DisjointSets parts(g.n());

  // Edges in the minimum spanning tree.
  vector<const Edge*>* in_tree(new vector<const Edge*>());

  for (vector<Edge*>::iterator i = sorted_edges.begin();
       i != sorted_edges.end(); ++i) {
    const Edge& e = **i;
    // Does this edge connect distinct components?
    if (parts.find(e.v) != parts.find(e.w)) {
      in_tree->push_back(&e); // Yes, so add it to the tree
      parts.merge(e.v, e.w); // Now the components are one
    }
  }

  return in_tree;
}

#endif
<commit_msg>Fix comment typo<commit_after>
//
// Kruskal's algorithm for minimum spanning trees.
//

#ifndef _KRUSKAL_MST_HH
#define _KRUSKAL_MST_HH

#include <algorithm>

#include "disjoint_sets.hh"
#include "graph.hh"

// Utility function to compare edge weights, used in sorting.
bool compare_edge_ptr_weight(const Edge* x, const Edge* y) {
  return x->weight < y->weight;
}

// Find the edges in the minimum spanning tree of g. Returns a pointer
// to a vector of Edge pointers. The Edge pointers refer to the Edge
// objects owned by g. The client is responsible for eventually
// deleting the returned vector.
vector<const Edge*>* kruskal_mst_edges(const Graph& g) {
  assert(!g.empty());

  // Sort the edges into nondecreasing order by weight. We use a
  // stable sort to make unit testing easier, but stability is not
  // otherwise necessary.
  vector<Edge*> sorted_edges = g.edges;
  stable_sort(sorted_edges.begin(),
	      sorted_edges.end(),
	      compare_edge_ptr_weight);

  // Use a disjoint set data structure to keep track of the patchwork
  // forest of spanned subgraphs that we'll create. Initially every
  // vertex is its own component; every time we add an edge, those
  // components get connected. When we're done the whole graph has
  // been connected into one component.
  DisjointSets parts(g.n());

  // Edges in the minimum spanning tree.
  vector<const Edge*>* in_tree(new vector<const Edge*>());

  for (vector<Edge*>::iterator i = sorted_edges.begin();
       i != sorted_edges.end(); ++i) {
    const Edge& e = **i;
    // Does this edge connect distinct components?
    if (parts.find(e.v) != parts.find(e.w)) {
      in_tree->push_back(&e); // Yes, so add it to the tree
      parts.merge(e.v, e.w); // Now the components are one
    }
  }

  return in_tree;
}

#endif
<|endoftext|>


<commit_before>/**
 * @file 	GraphParser.cpp
 * @author 	Fabian Wegscheider
 * @date 	Jul 10, 2017
 */

#include <boost/spirit/include/qi.hpp>
#include "GraphParser.h"

using std::string;
using namespace boost::spirit;
using qi::int_;
using qi::double_;
using qi::phrase_parse;
using ascii::space;

GraphParser::GraphParser(string file) {
	inputFile.open(file);
	readSuccessfully = !inputFile.fail();
}

bool GraphParser::readFirstLine(int& numVertices, int& numEdges) {

	string line;
	getline(inputFile, line);	//first line is read

	auto it = line.begin();
	int n, m;
	bool success = phrase_parse(it, line.end(),
			int_[([&n](int j){ n = j; })]
				 >> int_[([&m](int j){ m = j; })], space);

	if (!success || it != line.end()) return false;
	numVertices = n;
	numEdges = m;

	return true;
}

bool GraphParser::read(Edge edges[], double weights[]) {

	assert(NULL != edges);
	assert(NULL != weights);

	/* we use boost::spirit to parse each line */
	string line;

	int i = 0;

	//read line by line
	while (getline(inputFile, line)) {

		auto it = line.begin();
		int start;
		int end;
		double weight;
		bool success = phrase_parse(it, line.end(),
				int_[([&start](int j){ start = j; })]
					 >> int_[([&end](int j){ end = j; })]
							 >> double_[([&weight](double j){ weight = j; })], space);
		if (success && it == line.end()) {
			edges[i] = Edge(start-1, end-1);
			weights[i] = weight;
		} else {
			return false;
		}
		++i;
	}

	return true;
}

<commit_msg>Delete GraphParser.cpp<commit_after><|endoftext|>


<commit_before>// ExporterBridge.cpp : Defines the exported functions for the DLL application.
//

#include "stdafx.h"
#include "HTMLContentControlBridge.h"
#include "resource.h"

#include <unknwn.h>
#include <tchar.h>
#include <msclr\auto_gcroot.h>

#include "..\..\..\..\ToDoList_Dev\Interfaces\ITransText.h"
#include "..\..\..\..\ToDoList_Dev\Interfaces\UITheme.h"
#include "..\..\..\..\ToDoList_Dev\Interfaces\IPreferences.h"
#include "..\..\..\..\ToDoList_Dev\Interfaces\ISpellcheck.h"

////////////////////////////////////////////////////////////////////////////////////////////////

#using <PluginHelpers.dll> as_friend

////////////////////////////////////////////////////////////////////////////////////////////////

using namespace HTMLContentControl;
using namespace System;
using namespace System::Collections::Generic;
using namespace System::Runtime::InteropServices;

using namespace Abstractspoon::Tdl::PluginHelpers;

////////////////////////////////////////////////////////////////////////////////////////////////

// REPLACE THIS WITH NEW GUID!
const LPCWSTR HTML_GUID = L"FE0B6B6E-2B61-4AEB-AA0D-98DBE5942F02";
const LPCWSTR HTML_NAME = L"Html";

////////////////////////////////////////////////////////////////////////////////////////////////

CHTMLContentBridge::CHTMLContentBridge() : m_hIcon(NULL)
{
   HMODULE hMod = LoadLibrary(L"HTMLContentControlBridge.dll"); // us

   m_hIcon = ::LoadIcon(hMod, MAKEINTRESOURCE(IDI_HTML));
}

CHTMLContentBridge::~CHTMLContentBridge()
{
   ::DestroyIcon(m_hIcon);
}

void CHTMLContentBridge::Release()
{
	delete this;
}

void CHTMLContentBridge::SetLocalizer(ITransText* /*pTT*/)
{
	// TODO
}

LPCWSTR CHTMLContentBridge::GetTypeDescription() const
{
	return HTML_NAME;
}

HICON CHTMLContentBridge::GetTypeIcon() const
{
   return m_hIcon;
}

LPCWSTR CHTMLContentBridge::GetTypeID() const
{
	return HTML_GUID;
}

IContentControl* CHTMLContentBridge::CreateCtrl(unsigned short nCtrlID, unsigned long nStyle,
	long nLeft, long nTop, long nWidth, long nHeight, HWND hwndParent)
{
	CHTMLContentControlBridge* pCtrl = new CHTMLContentControlBridge();

	if (!pCtrl->Create(nCtrlID, nStyle, nLeft, nTop, nWidth, nHeight, hwndParent))
	{
		pCtrl->Release();
		pCtrl = NULL;
	}

	return pCtrl;
}

void CHTMLContentBridge::SavePreferences(IPreferences* pPrefs, LPCWSTR szKey) const
{
	// TODO

}

void CHTMLContentBridge::LoadPreferences(const IPreferences* pPrefs, LPCWSTR szKey, bool bAppOnly)
{
	// TODO
}

// returns the length of the html or zero if not supported
int CHTMLContentBridge::ConvertToHtml(const unsigned char* pContent, int nLength,
	LPCWSTR szCharSet, LPWSTR& szHtml, LPCWSTR szImageDir)
{
	szHtml = nullptr;
	return 0;
}

void CHTMLContentBridge::FreeHtmlBuffer(LPWSTR& szHtml)
{
	delete [] szHtml;
	szHtml = nullptr;
}

////////////////////////////////////////////////////////////////////////////////////////////////

// This is the constructor of a class that has been exported.
// see ExporterBridge.h for the class definition
CHTMLContentControlBridge::CHTMLContentControlBridge()
{
}

BOOL CHTMLContentControlBridge::Create(UINT nCtrlID, DWORD nStyle,
	long nLeft, long nTop, long nWidth, long nHeight, HWND hwndParent)
{
	m_wnd = gcnew HTMLContentControl::HTMLContentControlCore(static_cast<IntPtr>(hwndParent));

	HWND hWnd = GetHwnd();

	if (hWnd)
	{
		::SetParent(hWnd, hwndParent);
		::SetWindowLong(hWnd, GWL_ID, nCtrlID);
		::SetWindowLong(hWnd, GWL_STYLE, nStyle);
		::MoveWindow(hWnd, nLeft, nTop, nWidth, nHeight, FALSE);

		return true;
	}

	return false;
}

int CHTMLContentControlBridge::GetContent(unsigned char* pContent) const
{
	cli::array<Byte>^ content = m_wnd->GetContent();
	int nLength = content->Length;

	if (pContent && nLength)
	{
		pin_ptr<Byte> ptrContent = &content[content->GetLowerBound(0)];
		CopyMemory(pContent, ptrContent, nLength);
	}

	return nLength;
}

bool CHTMLContentControlBridge::SetContent(const unsigned char* pContent, int nLength, bool bResetSelection)
{
	cli::array<Byte>^ content = gcnew cli::array<Byte>(nLength);

	for (int i = 0; i < nLength; i++)
		content[i] = pContent[i];

	return m_wnd->SetContent(content, bResetSelection);
}

LPCWSTR CHTMLContentControlBridge::GetTypeID() const
{
	return HTML_GUID;
}

// text content if supported. return false if not supported
int CHTMLContentControlBridge::GetTextContent(LPWSTR szContent, int nLength) const
{
	String^ content = m_wnd->GetTextContent();
	nLength = content->Length;

	if (szContent != nullptr)
	{
		Abstractspoon::Tdl::PluginHelpers::MarshalledString msContent(content);
		CopyMemory(szContent, msContent, (nLength * sizeof(WCHAR)));
	}

	return nLength;
}

bool CHTMLContentControlBridge::SetTextContent(LPCWSTR szContent, bool bResetSelection)
{
	msclr::auto_gcroot<String^> content = gcnew String(szContent);

	return m_wnd->SetTextContent(content, bResetSelection);
}

void CHTMLContentControlBridge::SetReadOnly(bool bReadOnly)
{

}

HWND CHTMLContentControlBridge::GetHwnd() const
{
	return static_cast<HWND>(m_wnd->Handle.ToPointer());
}

void CHTMLContentControlBridge::Release()
{
	::DestroyWindow(GetHwnd());
	delete this;
}

bool CHTMLContentControlBridge::ProcessMessage(MSG* pMsg)
{
	return false;
}

ISpellCheck* CHTMLContentControlBridge::GetSpellCheckInterface()
{
	return nullptr;
}

bool CHTMLContentControlBridge::Undo()
{
	return false;
}

bool CHTMLContentControlBridge::Redo()
{
	return false;
}

void CHTMLContentControlBridge::SetUITheme(const UITHEME* pTheme)
{
	msclr::auto_gcroot<UITheme^> theme = gcnew UITheme(pTheme);

	m_wnd->SetUITheme(theme.get());
}

void CHTMLContentControlBridge::SavePreferences(IPreferences* pPrefs, LPCWSTR szKey) const
{

}

void CHTMLContentControlBridge::LoadPreferences(const IPreferences* pPrefs, LPCWSTR szKey, bool bAppOnly)
{
	msclr::auto_gcroot<Preferences^> prefs = gcnew Preferences(pPrefs);
	msclr::auto_gcroot<String^> key = gcnew String(szKey);

	m_wnd->LoadPreferences(prefs.get(), key.get(), bAppOnly);
}
<commit_msg>Implement conversion to html<commit_after>// ExporterBridge.cpp : Defines the exported functions for the DLL application.
//

#include "stdafx.h"
#include "HTMLContentControlBridge.h"
#include "resource.h"

#include <unknwn.h>
#include <tchar.h>
#include <msclr\auto_gcroot.h>

#include "..\..\..\..\ToDoList_Dev\Interfaces\ITransText.h"
#include "..\..\..\..\ToDoList_Dev\Interfaces\UITheme.h"
#include "..\..\..\..\ToDoList_Dev\Interfaces\IPreferences.h"
#include "..\..\..\..\ToDoList_Dev\Interfaces\ISpellcheck.h"

////////////////////////////////////////////////////////////////////////////////////////////////

#using <PluginHelpers.dll> as_friend

////////////////////////////////////////////////////////////////////////////////////////////////

using namespace HTMLContentControl;
using namespace System;
using namespace System::Collections::Generic;
using namespace System::Runtime::InteropServices;

using namespace Abstractspoon::Tdl::PluginHelpers;

////////////////////////////////////////////////////////////////////////////////////////////////

// REPLACE THIS WITH NEW GUID!
const LPCWSTR HTML_GUID = L"FE0B6B6E-2B61-4AEB-AA0D-98DBE5942F02";
const LPCWSTR HTML_NAME = L"Html";

////////////////////////////////////////////////////////////////////////////////////////////////

CHTMLContentBridge::CHTMLContentBridge() : m_hIcon(NULL)
{
   HMODULE hMod = LoadLibrary(L"HTMLContentControlBridge.dll"); // us

   m_hIcon = ::LoadIcon(hMod, MAKEINTRESOURCE(IDI_HTML));
}

CHTMLContentBridge::~CHTMLContentBridge()
{
   ::DestroyIcon(m_hIcon);
}

void CHTMLContentBridge::Release()
{
	delete this;
}

void CHTMLContentBridge::SetLocalizer(ITransText* /*pTT*/)
{
	// TODO
}

LPCWSTR CHTMLContentBridge::GetTypeDescription() const
{
	return HTML_NAME;
}

HICON CHTMLContentBridge::GetTypeIcon() const
{
   return m_hIcon;
}

LPCWSTR CHTMLContentBridge::GetTypeID() const
{
	return HTML_GUID;
}

IContentControl* CHTMLContentBridge::CreateCtrl(unsigned short nCtrlID, unsigned long nStyle,
	long nLeft, long nTop, long nWidth, long nHeight, HWND hwndParent)
{
	CHTMLContentControlBridge* pCtrl = new CHTMLContentControlBridge();

	if (!pCtrl->Create(nCtrlID, nStyle, nLeft, nTop, nWidth, nHeight, hwndParent))
	{
		pCtrl->Release();
		pCtrl = NULL;
	}

	return pCtrl;
}

void CHTMLContentBridge::SavePreferences(IPreferences* pPrefs, LPCWSTR szKey) const
{
	// TODO

}

void CHTMLContentBridge::LoadPreferences(const IPreferences* pPrefs, LPCWSTR szKey, bool bAppOnly)
{
	// TODO
}

// returns the length of the html or zero if not supported
int CHTMLContentBridge::ConvertToHtml(const unsigned char* pContent, int nLength,
	LPCWSTR szCharSet, LPWSTR& szHtml, LPCWSTR szImageDir)
{
	if (nLength == 0)
		return 0;

	// pContent is the body
	int nCharLen = ((nLength / 2) + 1);
	szHtml = new WCHAR[nCharLen];

	ZeroMemory(szHtml, nCharLen * sizeof(WCHAR));
	CopyMemory(szHtml, pContent, nLength);

	return nCharLen;
}

void CHTMLContentBridge::FreeHtmlBuffer(LPWSTR& szHtml)
{
	delete [] szHtml;
	szHtml = nullptr;
}

////////////////////////////////////////////////////////////////////////////////////////////////

// This is the constructor of a class that has been exported.
// see ExporterBridge.h for the class definition
CHTMLContentControlBridge::CHTMLContentControlBridge()
{
}

BOOL CHTMLContentControlBridge::Create(UINT nCtrlID, DWORD nStyle,
	long nLeft, long nTop, long nWidth, long nHeight, HWND hwndParent)
{
	m_wnd = gcnew HTMLContentControl::HTMLContentControlCore(static_cast<IntPtr>(hwndParent));

	HWND hWnd = GetHwnd();

	if (hWnd)
	{
		::SetParent(hWnd, hwndParent);
		::SetWindowLong(hWnd, GWL_ID, nCtrlID);
		::SetWindowLong(hWnd, GWL_STYLE, nStyle);
		::MoveWindow(hWnd, nLeft, nTop, nWidth, nHeight, FALSE);

		return true;
	}

	return false;
}

int CHTMLContentControlBridge::GetContent(unsigned char* pContent) const
{
	cli::array<Byte>^ content = m_wnd->GetContent();
	int nLength = content->Length;

	if (pContent && nLength)
	{
		pin_ptr<Byte> ptrContent = &content[content->GetLowerBound(0)];
		CopyMemory(pContent, ptrContent, nLength);
	}

	return nLength;
}

bool CHTMLContentControlBridge::SetContent(const unsigned char* pContent, int nLength, bool bResetSelection)
{
	cli::array<Byte>^ content = gcnew cli::array<Byte>(nLength);

	for (int i = 0; i < nLength; i++)
		content[i] = pContent[i];

	return m_wnd->SetContent(content, bResetSelection);
}

LPCWSTR CHTMLContentControlBridge::GetTypeID() const
{
	return HTML_GUID;
}

// text content if supported. return false if not supported
int CHTMLContentControlBridge::GetTextContent(LPWSTR szContent, int nLength) const
{
	String^ content = m_wnd->GetTextContent();
	nLength = content->Length;

	if (szContent != nullptr)
	{
		Abstractspoon::Tdl::PluginHelpers::MarshalledString msContent(content);
		CopyMemory(szContent, msContent, (nLength * sizeof(WCHAR)));
	}

	return nLength;
}

bool CHTMLContentControlBridge::SetTextContent(LPCWSTR szContent, bool bResetSelection)
{
	msclr::auto_gcroot<String^> content = gcnew String(szContent);

	return m_wnd->SetTextContent(content, bResetSelection);
}

void CHTMLContentControlBridge::SetReadOnly(bool bReadOnly)
{

}

HWND CHTMLContentControlBridge::GetHwnd() const
{
	return static_cast<HWND>(m_wnd->Handle.ToPointer());
}

void CHTMLContentControlBridge::Release()
{
	::DestroyWindow(GetHwnd());
	delete this;
}

bool CHTMLContentControlBridge::ProcessMessage(MSG* pMsg)
{
	return false;
}

ISpellCheck* CHTMLContentControlBridge::GetSpellCheckInterface()
{
	return nullptr;
}

bool CHTMLContentControlBridge::Undo()
{
	return false;
}

bool CHTMLContentControlBridge::Redo()
{
	return false;
}

void CHTMLContentControlBridge::SetUITheme(const UITHEME* pTheme)
{
	msclr::auto_gcroot<UITheme^> theme = gcnew UITheme(pTheme);

	m_wnd->SetUITheme(theme.get());
}

void CHTMLContentControlBridge::SavePreferences(IPreferences* pPrefs, LPCWSTR szKey) const
{

}

void CHTMLContentControlBridge::LoadPreferences(const IPreferences* pPrefs, LPCWSTR szKey, bool bAppOnly)
{
	msclr::auto_gcroot<Preferences^> prefs = gcnew Preferences(pPrefs);
	msclr::auto_gcroot<String^> key = gcnew String(szKey);

	m_wnd->LoadPreferences(prefs.get(), key.get(), bAppOnly);
}
<|endoftext|>


<commit_before>/////////////////////////////////////////////////////////////////////////
// $Id: load32bitOShack.cc,v 1.8 2002/04/18 00:22:19 bdenney Exp $
/////////////////////////////////////////////////////////////////////////
//
//  Copyright (C) 2001  MandrakeSoft S.A.
//
//    MandrakeSoft S.A.
//    43, rue d'Aboukir
//    75002 Paris - France
//    http://www.linux-mandrake.com/
//    http://www.mandrakesoft.com/
//
//  This library is free software; you can redistribute it and/or
//  modify it under the terms of the GNU Lesser General Public
//  License as published by the Free Software Foundation; either
//  version 2 of the License, or (at your option) any later version.
//
//  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

#include "bochs.h"
#define LOG_THIS genlog->

static void bx_load_linux_hack(void);
static void bx_load_null_kernel_hack(void);
static Bit32u bx_load_kernel_image(char *path, Bit32u paddr);

  void
bx_load32bitOSimagehack(void)
{
  // Replay IO from log to initialize IO devices to
  // a reasonable state needed for the OS.  This is done
  // in lieu of running the 16-bit BIOS to init things,
  // since we want to test straight 32bit stuff for
  // freemware.

  FILE *fp;

  fp = fopen(bx_options.load32bitOSImage.Oiolog->getptr (), "r");

  if (fp == NULL) {
    BX_PANIC(("could not open IO init file."));
    }

  while (1) {
    unsigned len, op, port, val;
    int ret;
    ret = fscanf(fp, "%u %u %x %x\n",
      &len, &op, &port, &val);
    if (ret != 4) {
      BX_PANIC(("could not open IO init file."));
      }
    if (op == 0) {
      // read
      (void) bx_devices.inp(port, len);
      }
    else if (op == 1) {
      // write
      bx_devices.outp(port, val, len);
      }
    else {
      BX_PANIC(("bad IO op in init filen"));
      }
    if (feof(fp)) break;
    }

  // Invoke proper hack depending on which OS image we're loading
  switch (bx_options.load32bitOSImage.OwhichOS->get ()) {
    case Load32bitOSLinux:
      bx_load_linux_hack();
      break;
    case Load32bitOSNullKernel:
      bx_load_null_kernel_hack();
      break;
    default:
      BX_PANIC(("load32bitOSImage: OS not recognized"));
    }
}

struct gdt_entry
{
  Bit32u low;
  Bit32u high;
};
struct linux_setup_params
{
   /* 0x000 */ Bit8u   orig_x;
   /* 0x001 */ Bit8u   orig_y;
   /* 0x002 */ Bit16u  memory_size_std;
   /* 0x004 */ Bit16u  orig_video_page;
   /* 0x006 */ Bit8u   orig_video_mode;
   /* 0x007 */ Bit8u   orig_video_cols;
   /* 0x008 */ Bit16u  unused1;
   /* 0x00a */ Bit16u  orig_video_ega_bx;
   /* 0x00c */ Bit16u  unused2;
   /* 0x00e */ Bit8u   orig_video_lines;
   /* 0x00f */ Bit8u   orig_video_isVGA;
   /* 0x010 */ Bit16u  orig_video_points;
   /* 0x012 */ Bit8u   pad1[0x40 - 0x12];
   /* 0x040 */ Bit8u   apm_info[0x80 - 0x40];
   /* 0x080 */ Bit8u   hd0_info[16];
   /* 0x090 */ Bit8u   hd1_info[16];
   /* 0x0a0 */ Bit8u   pad2[0x1e0 - 0xa0];
   /* 0x1e0 */ Bit32u  memory_size_ext;
   /* 0x1e4 */ Bit8u   pad3[0x1f1 - 0x1e4];
   /* 0x1f1 */ Bit8u   setup_sects;
   /* 0x1f2 */ Bit16u  mount_root_rdonly;
   /* 0x1f4 */ Bit16u  sys_size;
   /* 0x1f6 */ Bit16u  swap_dev;
   /* 0x1f8 */ Bit16u  ramdisk_flags;
   /* 0x1fa */ Bit16u  vga_mode;
   /* 0x1fc */ Bit16u  orig_root_dev;
   /* 0x1fe */ Bit16u  bootsect_magic;
   /* 0x200 */ Bit8u   pad4[0x210 - 0x200];
   /* 0x210 */ Bit32u  loader_type;
   /* 0x214 */ Bit32u  kernel_start;
   /* 0x218 */ Bit32u  initrd_start;
   /* 0x21c */ Bit32u  initrd_size;
   /* 0x220 */ Bit8u   pad5[0x400 - 0x220];
   /* 0x400 */ struct  gdt_entry gdt[128];
   /* 0x800 */ Bit8u   commandline[2048];
};

  static void
bx_load_linux_setup_params( Bit32u initrd_start, Bit32u initrd_size )
{
  BX_MEM_C *mem = BX_MEM(0);
  struct linux_setup_params *params =
         (struct linux_setup_params *) &mem->vector[0x00090000];

  memset( params, '\0', sizeof(*params) );

  /* Video settings (standard VGA) */
  params->orig_x = 0;
  params->orig_y = 0;
  params->orig_video_page = 0;
  params->orig_video_mode = 3;
  params->orig_video_cols = 80;
  params->orig_video_lines = 25;
  params->orig_video_points = 16;
  params->orig_video_isVGA = 1;
  params->orig_video_ega_bx = 3;

  /* Memory size (total mem - 1MB, in KB) */
  params->memory_size_ext = (mem->megabytes - 1) * 1024;

  /* Boot parameters */
  params->loader_type = 1;
  params->bootsect_magic = 0xaa55;
  params->mount_root_rdonly = 0;
  params->orig_root_dev = 0x0100;
  params->initrd_start = initrd_start;
  params->initrd_size  = initrd_size;

  /* Initial GDT */
  params->gdt[2].high = 0x00cf9a00;
  params->gdt[2].low  = 0x0000ffff;
  params->gdt[3].high = 0x00cf9200;
  params->gdt[3].low  = 0x0000ffff;
}

  void
bx_load_linux_hack(void)
{
  Bit32u initrd_start = 0, initrd_size = 0;

  // The RESET function will have been called first.
  // Set CPU and memory features which are assumed at this point.

  // Load Linux kernel image
  bx_load_kernel_image( bx_options.load32bitOSImage.Opath->getptr (), 0x100000 );

  // Load initial ramdisk image if requested
  if ( bx_options.load32bitOSImage.Oinitrd->getptr () )
  {
    initrd_start = 0x00800000;  /* FIXME: load at top of memory */
    initrd_size  = bx_load_kernel_image( bx_options.load32bitOSImage.Oinitrd->getptr (), initrd_start );
  }

  // Setup Linux startup parameters buffer
  bx_load_linux_setup_params( initrd_start, initrd_size );

  // Enable A20 line
  BX_SET_ENABLE_A20( 1 );

  // Setup PICs the way Linux likes it
  BX_OUTP( 0x20, 0x11, 1 );
  BX_OUTP( 0xA0, 0x11, 1 );
  BX_OUTP( 0x21, 0x20, 1 );
  BX_OUTP( 0xA1, 0x28, 1 );
  BX_OUTP( 0x21, 0x04, 1 );
  BX_OUTP( 0xA1, 0x02, 1 );
  BX_OUTP( 0x21, 0x01, 1 );
  BX_OUTP( 0xA1, 0x01, 1 );
  BX_OUTP( 0x21, 0xFF, 1 );
  BX_OUTP( 0xA1, 0xFB, 1 );

  // Disable interrupts and NMIs
  BX_CPU(0)->eflags.if_ = 0;
  BX_OUTP( 0x70, 0x80, 1 );

  // Enter protected mode
  BX_CPU(0)->cr0.pe = 1;
  BX_CPU(0)->cr0.val32 |= 0x01;

  // Set up initial GDT
  BX_CPU(0)->gdtr.limit = 0x400;
  BX_CPU(0)->gdtr.base  = 0x00090400;

  // Jump to protected mode entry point
  BX_CPU(0)->jump_protected( NULL, 0x10, 0x00100000 );
}

  void
bx_load_null_kernel_hack(void)
{
  // The RESET function will have been called first.
  // Set CPU and memory features which are assumed at this point.

  bx_load_kernel_image(bx_options.load32bitOSImage.Opath->getptr (), 0x100000);

  // EIP deltas
  BX_CPU(0)->prev_eip =
  BX_CPU(0)->eip = 0x00100000;

  // CS deltas
  BX_CPU(0)->sregs[BX_SEG_REG_CS].cache.u.segment.base = 0x00000000;
  BX_CPU(0)->sregs[BX_SEG_REG_CS].cache.u.segment.limit = 0xFFFFF;
  BX_CPU(0)->sregs[BX_SEG_REG_CS].cache.u.segment.limit_scaled = 0xFFFFFFFF;
  BX_CPU(0)->sregs[BX_SEG_REG_CS].cache.u.segment.g   = 1; // page gran
  BX_CPU(0)->sregs[BX_SEG_REG_CS].cache.u.segment.d_b = 1; // 32bit

  // DS deltas
  BX_CPU(0)->sregs[BX_SEG_REG_DS].cache.u.segment.base = 0x00000000;
  BX_CPU(0)->sregs[BX_SEG_REG_DS].cache.u.segment.limit = 0xFFFFF;
  BX_CPU(0)->sregs[BX_SEG_REG_DS].cache.u.segment.limit_scaled = 0xFFFFFFFF;
  BX_CPU(0)->sregs[BX_SEG_REG_DS].cache.u.segment.g   = 1; // page gran
  BX_CPU(0)->sregs[BX_SEG_REG_DS].cache.u.segment.d_b = 1; // 32bit

  // CR0 deltas
  BX_CPU(0)->cr0.pe = 1; // protected mode
}

  Bit32u
bx_load_kernel_image(char *path, Bit32u paddr)
{
  struct stat stat_buf;
  int fd, ret;
  unsigned long size, offset;
  Bit32u page_size;

  // read in ROM BIOS image file
  fd = open(path, O_RDONLY
#ifdef O_BINARY
            | O_BINARY
#endif
           );
  if (fd < 0) {
    BX_INFO(( "load_kernel_image: couldn't open image file '%s'.", path ));
    BX_EXIT(1);
    }
  ret = fstat(fd, &stat_buf);
  if (ret) {
    BX_INFO(( "load_kernel_image: couldn't stat image file '%s'.", path ));
    BX_EXIT(1);
    }

  size = stat_buf.st_size;
  page_size = ((Bit32u)size + 0xfff) & ~0xfff;

  BX_MEM_C *mem = BX_MEM(0);
  if ( (paddr + size) > mem->len ) {
    BX_INFO(( "load_kernel_image: address range > physical memsize!" ));
    BX_EXIT(1);
    }

  offset = 0;
  while (size > 0) {
    ret = read(fd, (bx_ptr_t) &mem->vector[paddr + offset], size);
    if (ret <= 0) {
      BX_INFO(( "load_kernel_image: read failed on image" ));
      BX_EXIT(1);
      }
    size -= ret;
    offset += ret;
    }
  close(fd);
  BX_INFO(( "#(%u) load_kernel_image: '%s', size=%u read into memory at %08x",
          BX_SIM_ID, path,
          (unsigned) stat_buf.st_size,
          (unsigned) paddr ));

  return page_size;
}
<commit_msg>- use eflags accessor instead of using field directly<commit_after>/////////////////////////////////////////////////////////////////////////
// $Id: load32bitOShack.cc,v 1.9 2002/09/11 03:56:22 bdenney Exp $
/////////////////////////////////////////////////////////////////////////
//
//  Copyright (C) 2001  MandrakeSoft S.A.
//
//    MandrakeSoft S.A.
//    43, rue d'Aboukir
//    75002 Paris - France
//    http://www.linux-mandrake.com/
//    http://www.mandrakesoft.com/
//
//  This library is free software; you can redistribute it and/or
//  modify it under the terms of the GNU Lesser General Public
//  License as published by the Free Software Foundation; either
//  version 2 of the License, or (at your option) any later version.
//
//  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

#include "bochs.h"
#define LOG_THIS genlog->

static void bx_load_linux_hack(void);
static void bx_load_null_kernel_hack(void);
static Bit32u bx_load_kernel_image(char *path, Bit32u paddr);

  void
bx_load32bitOSimagehack(void)
{
  // Replay IO from log to initialize IO devices to
  // a reasonable state needed for the OS.  This is done
  // in lieu of running the 16-bit BIOS to init things,
  // since we want to test straight 32bit stuff for
  // freemware.

  FILE *fp;

  fp = fopen(bx_options.load32bitOSImage.Oiolog->getptr (), "r");

  if (fp == NULL) {
    BX_PANIC(("could not open IO init file."));
    }

  while (1) {
    unsigned len, op, port, val;
    int ret;
    ret = fscanf(fp, "%u %u %x %x\n",
      &len, &op, &port, &val);
    if (ret != 4) {
      BX_PANIC(("could not open IO init file."));
      }
    if (op == 0) {
      // read
      (void) bx_devices.inp(port, len);
      }
    else if (op == 1) {
      // write
      bx_devices.outp(port, val, len);
      }
    else {
      BX_PANIC(("bad IO op in init filen"));
      }
    if (feof(fp)) break;
    }

  // Invoke proper hack depending on which OS image we're loading
  switch (bx_options.load32bitOSImage.OwhichOS->get ()) {
    case Load32bitOSLinux:
      bx_load_linux_hack();
      break;
    case Load32bitOSNullKernel:
      bx_load_null_kernel_hack();
      break;
    default:
      BX_PANIC(("load32bitOSImage: OS not recognized"));
    }
}

struct gdt_entry
{
  Bit32u low;
  Bit32u high;
};
struct linux_setup_params
{
   /* 0x000 */ Bit8u   orig_x;
   /* 0x001 */ Bit8u   orig_y;
   /* 0x002 */ Bit16u  memory_size_std;
   /* 0x004 */ Bit16u  orig_video_page;
   /* 0x006 */ Bit8u   orig_video_mode;
   /* 0x007 */ Bit8u   orig_video_cols;
   /* 0x008 */ Bit16u  unused1;
   /* 0x00a */ Bit16u  orig_video_ega_bx;
   /* 0x00c */ Bit16u  unused2;
   /* 0x00e */ Bit8u   orig_video_lines;
   /* 0x00f */ Bit8u   orig_video_isVGA;
   /* 0x010 */ Bit16u  orig_video_points;
   /* 0x012 */ Bit8u   pad1[0x40 - 0x12];
   /* 0x040 */ Bit8u   apm_info[0x80 - 0x40];
   /* 0x080 */ Bit8u   hd0_info[16];
   /* 0x090 */ Bit8u   hd1_info[16];
   /* 0x0a0 */ Bit8u   pad2[0x1e0 - 0xa0];
   /* 0x1e0 */ Bit32u  memory_size_ext;
   /* 0x1e4 */ Bit8u   pad3[0x1f1 - 0x1e4];
   /* 0x1f1 */ Bit8u   setup_sects;
   /* 0x1f2 */ Bit16u  mount_root_rdonly;
   /* 0x1f4 */ Bit16u  sys_size;
   /* 0x1f6 */ Bit16u  swap_dev;
   /* 0x1f8 */ Bit16u  ramdisk_flags;
   /* 0x1fa */ Bit16u  vga_mode;
   /* 0x1fc */ Bit16u  orig_root_dev;
   /* 0x1fe */ Bit16u  bootsect_magic;
   /* 0x200 */ Bit8u   pad4[0x210 - 0x200];
   /* 0x210 */ Bit32u  loader_type;
   /* 0x214 */ Bit32u  kernel_start;
   /* 0x218 */ Bit32u  initrd_start;
   /* 0x21c */ Bit32u  initrd_size;
   /* 0x220 */ Bit8u   pad5[0x400 - 0x220];
   /* 0x400 */ struct  gdt_entry gdt[128];
   /* 0x800 */ Bit8u   commandline[2048];
};

  static void
bx_load_linux_setup_params( Bit32u initrd_start, Bit32u initrd_size )
{
  BX_MEM_C *mem = BX_MEM(0);
  struct linux_setup_params *params =
         (struct linux_setup_params *) &mem->vector[0x00090000];

  memset( params, '\0', sizeof(*params) );

  /* Video settings (standard VGA) */
  params->orig_x = 0;
  params->orig_y = 0;
  params->orig_video_page = 0;
  params->orig_video_mode = 3;
  params->orig_video_cols = 80;
  params->orig_video_lines = 25;
  params->orig_video_points = 16;
  params->orig_video_isVGA = 1;
  params->orig_video_ega_bx = 3;

  /* Memory size (total mem - 1MB, in KB) */
  params->memory_size_ext = (mem->megabytes - 1) * 1024;

  /* Boot parameters */
  params->loader_type = 1;
  params->bootsect_magic = 0xaa55;
  params->mount_root_rdonly = 0;
  params->orig_root_dev = 0x0100;
  params->initrd_start = initrd_start;
  params->initrd_size  = initrd_size;

  /* Initial GDT */
  params->gdt[2].high = 0x00cf9a00;
  params->gdt[2].low  = 0x0000ffff;
  params->gdt[3].high = 0x00cf9200;
  params->gdt[3].low  = 0x0000ffff;
}

  void
bx_load_linux_hack(void)
{
  Bit32u initrd_start = 0, initrd_size = 0;

  // The RESET function will have been called first.
  // Set CPU and memory features which are assumed at this point.

  // Load Linux kernel image
  bx_load_kernel_image( bx_options.load32bitOSImage.Opath->getptr (), 0x100000 );

  // Load initial ramdisk image if requested
  if ( bx_options.load32bitOSImage.Oinitrd->getptr () )
  {
    initrd_start = 0x00800000;  /* FIXME: load at top of memory */
    initrd_size  = bx_load_kernel_image( bx_options.load32bitOSImage.Oinitrd->getptr (), initrd_start );
  }

  // Setup Linux startup parameters buffer
  bx_load_linux_setup_params( initrd_start, initrd_size );

  // Enable A20 line
  BX_SET_ENABLE_A20( 1 );

  // Setup PICs the way Linux likes it
  BX_OUTP( 0x20, 0x11, 1 );
  BX_OUTP( 0xA0, 0x11, 1 );
  BX_OUTP( 0x21, 0x20, 1 );
  BX_OUTP( 0xA1, 0x28, 1 );
  BX_OUTP( 0x21, 0x04, 1 );
  BX_OUTP( 0xA1, 0x02, 1 );
  BX_OUTP( 0x21, 0x01, 1 );
  BX_OUTP( 0xA1, 0x01, 1 );
  BX_OUTP( 0x21, 0xFF, 1 );
  BX_OUTP( 0xA1, 0xFB, 1 );

  // Disable interrupts and NMIs
  BX_CPU(0)->eflags.clear_IF ();
  BX_OUTP( 0x70, 0x80, 1 );

  // Enter protected mode
  BX_CPU(0)->cr0.pe = 1;
  BX_CPU(0)->cr0.val32 |= 0x01;

  // Set up initial GDT
  BX_CPU(0)->gdtr.limit = 0x400;
  BX_CPU(0)->gdtr.base  = 0x00090400;

  // Jump to protected mode entry point
  BX_CPU(0)->jump_protected( NULL, 0x10, 0x00100000 );
}

  void
bx_load_null_kernel_hack(void)
{
  // The RESET function will have been called first.
  // Set CPU and memory features which are assumed at this point.

  bx_load_kernel_image(bx_options.load32bitOSImage.Opath->getptr (), 0x100000);

  // EIP deltas
  BX_CPU(0)->prev_eip =
  BX_CPU(0)->eip = 0x00100000;

  // CS deltas
  BX_CPU(0)->sregs[BX_SEG_REG_CS].cache.u.segment.base = 0x00000000;
  BX_CPU(0)->sregs[BX_SEG_REG_CS].cache.u.segment.limit = 0xFFFFF;
  BX_CPU(0)->sregs[BX_SEG_REG_CS].cache.u.segment.limit_scaled = 0xFFFFFFFF;
  BX_CPU(0)->sregs[BX_SEG_REG_CS].cache.u.segment.g   = 1; // page gran
  BX_CPU(0)->sregs[BX_SEG_REG_CS].cache.u.segment.d_b = 1; // 32bit

  // DS deltas
  BX_CPU(0)->sregs[BX_SEG_REG_DS].cache.u.segment.base = 0x00000000;
  BX_CPU(0)->sregs[BX_SEG_REG_DS].cache.u.segment.limit = 0xFFFFF;
  BX_CPU(0)->sregs[BX_SEG_REG_DS].cache.u.segment.limit_scaled = 0xFFFFFFFF;
  BX_CPU(0)->sregs[BX_SEG_REG_DS].cache.u.segment.g   = 1; // page gran
  BX_CPU(0)->sregs[BX_SEG_REG_DS].cache.u.segment.d_b = 1; // 32bit

  // CR0 deltas
  BX_CPU(0)->cr0.pe = 1; // protected mode
}

  Bit32u
bx_load_kernel_image(char *path, Bit32u paddr)
{
  struct stat stat_buf;
  int fd, ret;
  unsigned long size, offset;
  Bit32u page_size;

  // read in ROM BIOS image file
  fd = open(path, O_RDONLY
#ifdef O_BINARY
            | O_BINARY
#endif
           );
  if (fd < 0) {
    BX_INFO(( "load_kernel_image: couldn't open image file '%s'.", path ));
    BX_EXIT(1);
    }
  ret = fstat(fd, &stat_buf);
  if (ret) {
    BX_INFO(( "load_kernel_image: couldn't stat image file '%s'.", path ));
    BX_EXIT(1);
    }

  size = stat_buf.st_size;
  page_size = ((Bit32u)size + 0xfff) & ~0xfff;

  BX_MEM_C *mem = BX_MEM(0);
  if ( (paddr + size) > mem->len ) {
    BX_INFO(( "load_kernel_image: address range > physical memsize!" ));
    BX_EXIT(1);
    }

  offset = 0;
  while (size > 0) {
    ret = read(fd, (bx_ptr_t) &mem->vector[paddr + offset], size);
    if (ret <= 0) {
      BX_INFO(( "load_kernel_image: read failed on image" ));
      BX_EXIT(1);
      }
    size -= ret;
    offset += ret;
    }
  close(fd);
  BX_INFO(( "#(%u) load_kernel_image: '%s', size=%u read into memory at %08x",
          BX_SIM_ID, path,
          (unsigned) stat_buf.st_size,
          (unsigned) paddr ));

  return page_size;
}
<|endoftext|>


<commit_before>#include <sstream>

#include "sequence.h"

namespace relative
{

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

Sequence::Sequence()
{
  this->sigma = 0;
}

Sequence::Sequence(int_vector_buffer<8>& buffer, uint64_t _size, uint64_t _sigma)
{
  this->sigma = _sigma;
  if(this->sigma > 0) { this->data.width(bitlength(this->sigma - 1)); }
  else { this->data.width(8); }
  this->data.resize(_size);
  for(uint64_t i = 0; i < this->size(); i++) { this->data[i] = buffer[i]; }

  if(this->sigma == 0)
  {
    util::bit_compress(this->data);
    this->sigma = *std::max_element(this->data.begin(), this->data.end()) + 1;
  }

  this->buildRank();
}

Sequence::Sequence(const Sequence& s)
{
  this->copy(s);
}

Sequence::Sequence(Sequence&& s)
{
  *this = std::move(s);
}

Sequence::~Sequence()
{
}

void
Sequence::copy(const Sequence& s)
{
  this->data = s.data;
  this->samples = s.samples;
  this->sigma = s.sigma;
}

void
Sequence::swap(Sequence& s)
{
  if(this != &s)
  {
    this->data.swap(s.data);
    this->samples.swap(s.samples);
    std::swap(this->sigma, s.sigma);
  }
}

Sequence&
Sequence::operator=(const Sequence& s)
{
  if(this != &s) { this->copy(s); }
  return *this;
}

Sequence&
Sequence::operator=(Sequence&& s)
{
  if(this != &s)
  {
    this->data = std::move(s.data);
    this->samples = std::move(s.samples);
    this->sigma = s.sigma;
  }
  return *this;
}

uint64_t
Sequence::serialize(std::ostream& out, structure_tree_node* s, std::string name) const
{
  structure_tree_node* child = structure_tree::add_child(s, name, util::class_name(*this));
  uint64_t written_bytes = 0;
  written_bytes += this->data.serialize(out, child, "data");
  written_bytes += this->samples.serialize(out, child, "samples");
  written_bytes += write_member(this->sigma, out, child, "sigma");
  structure_tree::add_size(child, written_bytes);
  return written_bytes;
}

void
Sequence::load(std::istream& in)
{
  this->data.load(in);
  this->samples.load(in);
  read_member(this->sigma, in);
}

void
Sequence::buildRank()
{
  uint64_t blocks = (this->size() + SAMPLE_RATE - 1) / SAMPLE_RATE;
  int_vector<0> temp((blocks + 1) * this->sigma, 0, bitlength(this->size()));
  for(uint64_t block = 0; block < blocks; block++)
  {
    for(uint64_t c = 0; c < this->sigma; c++) { temp[(block + 1) * this->sigma + c] = temp[block * this->sigma + c]; }
    uint64_t limit = std::min(this->size(), (block + 1) * SAMPLE_RATE);
    for(uint64_t i = block * SAMPLE_RATE; i < limit; i++) { temp[(block + 1) * this->sigma + this->data[i]]++; }
  }
  util::bit_compress(temp); this->samples.swap(temp);
}

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

RLSequence::RLSequence()
{
}

inline void
addBasicRun(uint64_t c, uint64_t run, std::vector<uint8_t>& runs)
{
  runs.push_back(c + RLSequence::SIGMA * (run - 1));
}

void
addRun(uint64_t c, uint64_t run, std::vector<uint8_t>& runs)
{
  while(run > 0)
  {
    // Runs of length <= 41 are encoded in a single byte.
    if(run < RLSequence::MAX_RUN)
    {
      addBasicRun(c, run, runs);
      return;
    }

    uint64_t bytes_remaining = RLSequence::SAMPLE_RATE - (runs.size() % RLSequence::SAMPLE_RATE);
    uint64_t l = (bytes_remaining < 2 ? RLSequence::MAX_RUN - 1 : RLSequence::MAX_RUN);
    addBasicRun(c, l, runs); run -= l;
    if(bytes_remaining < 2) { continue; } // No room for the additional run length in the current block.
    bytes_remaining--;

    // Write the rest of the run with 7 bits/byte, least significant byte first.
    if(bitlength(run) > 7 * bytes_remaining)  // Cannot encode the entire run in current block.
    {
      uint64_t temp = 0;
      for(uint64_t i = 1; i < bytes_remaining; i++) { runs.push_back(0xFF); temp = (temp << 7) | 0x7F; }
      runs.push_back(0x7F); run -= (temp << 7) | 0x7F;
    }
    else
    {
      do
      {
        uint8_t val = run & 0x7F; run >>= 7;
        if(run > 0) { val |= 0x80; }
        runs.push_back(val);
      }
      while(run > 0);
    }
  }
}

RLSequence::RLSequence(int_vector_buffer<8>& buffer, uint64_t _size)
{
  // Process the input.
  uint64_t c = 0, run = 0;
  for(uint64_t i = 0; i < _size; i++)
  {
    if(buffer[i] == c) { run++; }
    else
    {
      addRun(c, run, this->data);
      c = buffer[i]; run = 1;
    }
  }
  addRun(c, run, this->data);

  // Blocks and samples.
  this->buildRank();
}

RLSequence::RLSequence(const RLSequence& s)
{
  this->copy(s);
}

RLSequence::RLSequence(RLSequence&& s)
{
  *this = std::move(s);
}

RLSequence::~RLSequence()
{
}

void
RLSequence::copy(const RLSequence& s)
{
  this->data = s.data;
  for(uint64_t c = 0; c < SIGMA; c++) { this->samples[c] = s.samples[c]; }
  this->block_boundaries = s.block_boundaries;
  util::init_support(this->block_rank, &(this->block_boundaries));
  util::init_support(this->block_select, &(this->block_boundaries));
}

void
RLSequence::swap(RLSequence& s)
{
  if(this != &s)
  {
    this->data.swap(s.data);
    for(uint64_t c = 0; c < SIGMA; c++) { this->samples[c].swap(s.samples[c]); }
    this->block_boundaries.swap(s.block_boundaries);
    util::swap_support(this->block_rank, s.block_rank, &(this->block_boundaries), &(s.block_boundaries));
    util::swap_support(this->block_select, s.block_select, &(this->block_boundaries), &(s.block_boundaries));
  }
}

RLSequence&
RLSequence::operator=(const RLSequence& s)
{
  if(this != &s) { this->copy(s); }
  return *this;
}

RLSequence&
RLSequence::operator=(RLSequence&& s)
{
  if(this != &s)
  {
    this->data = std::move(s.data);
    for(uint64_t c = 0; c < SIGMA; c++) { this->samples[c] = std::move(s.samples[c]); }
    this->block_boundaries = std::move(s.block_boundaries);
    util::init_support(this->block_rank, &(this->block_boundaries));
    util::init_support(this->block_select, &(this->block_boundaries));
  }
  return *this;
}

uint64_t
RLSequence::serialize(std::ostream& out, structure_tree_node* s, std::string name) const
{
  structure_tree_node* child = structure_tree::add_child(s, name, util::class_name(*this));
  uint64_t written_bytes = 0;
  written_bytes += write_vector(this->data, out, child, "data");
  for(uint64_t c = 0; c < SIGMA; c++)
  {
    std::stringstream ss; ss << "samples_" << c;
    written_bytes += this->samples[c].serialize(out, child, ss.str());
  }
  written_bytes += this->block_boundaries.serialize(out, child, "block_boundaries");
  written_bytes += this->block_rank.serialize(out, child, "block_rank");
  written_bytes += this->block_select.serialize(out, child, "block_select");
  structure_tree::add_size(child, written_bytes);
  return written_bytes;
}

void
RLSequence::load(std::istream& in, bool rebuild_samples)
{
  read_vector(this->data, in);
  if(rebuild_samples)
  {
    this->buildRank();
  }
  else
  {
    for(uint64_t c = 0; c < SIGMA; c++) { this->samples[c].load(in); }
    this->block_boundaries.load(in);
    this->block_rank.load(in, &(this->block_boundaries));
    this->block_select.load(in, &(this->block_boundaries));
  }
}

void
RLSequence::buildRank()
{
  std::vector<uint64_t> block_ends;
  uint64_t seq_pos = 0, rle_pos = 0;
  while(rle_pos < this->runs())
  {
    range_type run = this->readRun(rle_pos); seq_pos += run.second;
    if(rle_pos >= this->runs() || rle_pos % SAMPLE_RATE == 0) { block_ends.push_back(seq_pos - 1); }
  }

  // Block boundaries.
  uint64_t blocks = block_ends.size();
  {
    sd_vector<> temp(block_ends.begin(), block_ends.end());
    util::clear(block_ends);
    this->block_boundaries.swap(temp);
    util::init_support(this->block_rank, &(this->block_boundaries));
    util::init_support(this->block_select, &(this->block_boundaries));
  }

  // Samples. SIGMA passes vs. higher space usage? Multi-threaded?
  for(uint64_t c = 0; c < SIGMA; c++)
  {
    int_vector<0> temp(blocks, 0, bitlength(this->size()));
    for(uint64_t block = 0; block < blocks; block++)
    {
      uint64_t rle_pos = block * SAMPLE_RATE, limit = std::min(this->runs(), (block + 1) * SAMPLE_RATE);
      while(rle_pos < limit)
      {
        range_type run = this->readRun(rle_pos);
        if(run.first == c) { temp[block] += run.second; }
      }
    }
    util::assign(this->samples[c], CumulativeArray(temp, temp.size()));
  }
}

uint64_t
RLSequence::hash(const Alphabet& alpha) const
{
  uint64_t rle_pos = 0, val = FNV_OFFSET_BASIS;
  while(rle_pos < this->runs())
  {
    range_type run = this->readRun(rle_pos); run.first = alpha.comp2char[run.first];
    for(uint64_t i = 0; i < run.second; i++) { val = fnv1a_hash(run.first, val); }
  }
  return val;
}

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

template<>
SimpleFM<RLSequence>::SimpleFM(const std::string& base_name, LoadMode mode)
{
  this->sample_rate = 0;

  if(mode == mode_native || mode == mode_ropebwt2)
  {
    std::string filename = base_name + NATIVE_BWT_EXTENSION;
    std::ifstream in(filename.c_str(), std::ios_base::binary);
    if(!in)
    {
      std::cerr << "SimpleFM::SimpleFM(): Cannot open BWT file " << filename << " (native format)" << std::endl;
      return;
    }
    this->bwt.load(in, mode == mode_ropebwt2); in.close();
  }
  else
  {
    int_vector_buffer<8> buffer(base_name + BWT_EXTENSION);
    RLSequence temp(buffer, buffer.size());
    this->bwt.swap(temp);
  }

  this->loadAlphabet(base_name);
  this->loadSamples(base_name);
}

template<>
void
characterCounts(const RLSequence& sequence, uint64_t size, int_vector<64>& counts)
{
  for(uint64_t c = 0; c < counts.size(); c++) { counts[c] = 0; }

  uint64_t rle_pos = 0;
  while(rle_pos < sequence.runs())
  {
    range_type run = sequence.readRun(rle_pos);
    counts[run.first] += run.second;
  }
}

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

} // namespace relative
<commit_msg>Fixed the RLSequence::hash(). Now it uses the right hash function.<commit_after>#include <sstream>

#include "sequence.h"

namespace relative
{

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

Sequence::Sequence()
{
  this->sigma = 0;
}

Sequence::Sequence(int_vector_buffer<8>& buffer, uint64_t _size, uint64_t _sigma)
{
  this->sigma = _sigma;
  if(this->sigma > 0) { this->data.width(bitlength(this->sigma - 1)); }
  else { this->data.width(8); }
  this->data.resize(_size);
  for(uint64_t i = 0; i < this->size(); i++) { this->data[i] = buffer[i]; }

  if(this->sigma == 0)
  {
    util::bit_compress(this->data);
    this->sigma = *std::max_element(this->data.begin(), this->data.end()) + 1;
  }

  this->buildRank();
}

Sequence::Sequence(const Sequence& s)
{
  this->copy(s);
}

Sequence::Sequence(Sequence&& s)
{
  *this = std::move(s);
}

Sequence::~Sequence()
{
}

void
Sequence::copy(const Sequence& s)
{
  this->data = s.data;
  this->samples = s.samples;
  this->sigma = s.sigma;
}

void
Sequence::swap(Sequence& s)
{
  if(this != &s)
  {
    this->data.swap(s.data);
    this->samples.swap(s.samples);
    std::swap(this->sigma, s.sigma);
  }
}

Sequence&
Sequence::operator=(const Sequence& s)
{
  if(this != &s) { this->copy(s); }
  return *this;
}

Sequence&
Sequence::operator=(Sequence&& s)
{
  if(this != &s)
  {
    this->data = std::move(s.data);
    this->samples = std::move(s.samples);
    this->sigma = s.sigma;
  }
  return *this;
}

uint64_t
Sequence::serialize(std::ostream& out, structure_tree_node* s, std::string name) const
{
  structure_tree_node* child = structure_tree::add_child(s, name, util::class_name(*this));
  uint64_t written_bytes = 0;
  written_bytes += this->data.serialize(out, child, "data");
  written_bytes += this->samples.serialize(out, child, "samples");
  written_bytes += write_member(this->sigma, out, child, "sigma");
  structure_tree::add_size(child, written_bytes);
  return written_bytes;
}

void
Sequence::load(std::istream& in)
{
  this->data.load(in);
  this->samples.load(in);
  read_member(this->sigma, in);
}

void
Sequence::buildRank()
{
  uint64_t blocks = (this->size() + SAMPLE_RATE - 1) / SAMPLE_RATE;
  int_vector<0> temp((blocks + 1) * this->sigma, 0, bitlength(this->size()));
  for(uint64_t block = 0; block < blocks; block++)
  {
    for(uint64_t c = 0; c < this->sigma; c++) { temp[(block + 1) * this->sigma + c] = temp[block * this->sigma + c]; }
    uint64_t limit = std::min(this->size(), (block + 1) * SAMPLE_RATE);
    for(uint64_t i = block * SAMPLE_RATE; i < limit; i++) { temp[(block + 1) * this->sigma + this->data[i]]++; }
  }
  util::bit_compress(temp); this->samples.swap(temp);
}

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

RLSequence::RLSequence()
{
}

inline void
addBasicRun(uint64_t c, uint64_t run, std::vector<uint8_t>& runs)
{
  runs.push_back(c + RLSequence::SIGMA * (run - 1));
}

void
addRun(uint64_t c, uint64_t run, std::vector<uint8_t>& runs)
{
  while(run > 0)
  {
    // Runs of length <= 41 are encoded in a single byte.
    if(run < RLSequence::MAX_RUN)
    {
      addBasicRun(c, run, runs);
      return;
    }

    uint64_t bytes_remaining = RLSequence::SAMPLE_RATE - (runs.size() % RLSequence::SAMPLE_RATE);
    uint64_t l = (bytes_remaining < 2 ? RLSequence::MAX_RUN - 1 : RLSequence::MAX_RUN);
    addBasicRun(c, l, runs); run -= l;
    if(bytes_remaining < 2) { continue; } // No room for the additional run length in the current block.
    bytes_remaining--;

    // Write the rest of the run with 7 bits/byte, least significant byte first.
    if(bitlength(run) > 7 * bytes_remaining)  // Cannot encode the entire run in current block.
    {
      uint64_t temp = 0;
      for(uint64_t i = 1; i < bytes_remaining; i++) { runs.push_back(0xFF); temp = (temp << 7) | 0x7F; }
      runs.push_back(0x7F); run -= (temp << 7) | 0x7F;
    }
    else
    {
      do
      {
        uint8_t val = run & 0x7F; run >>= 7;
        if(run > 0) { val |= 0x80; }
        runs.push_back(val);
      }
      while(run > 0);
    }
  }
}

RLSequence::RLSequence(int_vector_buffer<8>& buffer, uint64_t _size)
{
  // Process the input.
  uint64_t c = 0, run = 0;
  for(uint64_t i = 0; i < _size; i++)
  {
    if(buffer[i] == c) { run++; }
    else
    {
      addRun(c, run, this->data);
      c = buffer[i]; run = 1;
    }
  }
  addRun(c, run, this->data);

  // Blocks and samples.
  this->buildRank();
}

RLSequence::RLSequence(const RLSequence& s)
{
  this->copy(s);
}

RLSequence::RLSequence(RLSequence&& s)
{
  *this = std::move(s);
}

RLSequence::~RLSequence()
{
}

void
RLSequence::copy(const RLSequence& s)
{
  this->data = s.data;
  for(uint64_t c = 0; c < SIGMA; c++) { this->samples[c] = s.samples[c]; }
  this->block_boundaries = s.block_boundaries;
  util::init_support(this->block_rank, &(this->block_boundaries));
  util::init_support(this->block_select, &(this->block_boundaries));
}

void
RLSequence::swap(RLSequence& s)
{
  if(this != &s)
  {
    this->data.swap(s.data);
    for(uint64_t c = 0; c < SIGMA; c++) { this->samples[c].swap(s.samples[c]); }
    this->block_boundaries.swap(s.block_boundaries);
    util::swap_support(this->block_rank, s.block_rank, &(this->block_boundaries), &(s.block_boundaries));
    util::swap_support(this->block_select, s.block_select, &(this->block_boundaries), &(s.block_boundaries));
  }
}

RLSequence&
RLSequence::operator=(const RLSequence& s)
{
  if(this != &s) { this->copy(s); }
  return *this;
}

RLSequence&
RLSequence::operator=(RLSequence&& s)
{
  if(this != &s)
  {
    this->data = std::move(s.data);
    for(uint64_t c = 0; c < SIGMA; c++) { this->samples[c] = std::move(s.samples[c]); }
    this->block_boundaries = std::move(s.block_boundaries);
    util::init_support(this->block_rank, &(this->block_boundaries));
    util::init_support(this->block_select, &(this->block_boundaries));
  }
  return *this;
}

uint64_t
RLSequence::serialize(std::ostream& out, structure_tree_node* s, std::string name) const
{
  structure_tree_node* child = structure_tree::add_child(s, name, util::class_name(*this));
  uint64_t written_bytes = 0;
  written_bytes += write_vector(this->data, out, child, "data");
  for(uint64_t c = 0; c < SIGMA; c++)
  {
    std::stringstream ss; ss << "samples_" << c;
    written_bytes += this->samples[c].serialize(out, child, ss.str());
  }
  written_bytes += this->block_boundaries.serialize(out, child, "block_boundaries");
  written_bytes += this->block_rank.serialize(out, child, "block_rank");
  written_bytes += this->block_select.serialize(out, child, "block_select");
  structure_tree::add_size(child, written_bytes);
  return written_bytes;
}

void
RLSequence::load(std::istream& in, bool rebuild_samples)
{
  read_vector(this->data, in);
  if(rebuild_samples)
  {
    this->buildRank();
  }
  else
  {
    for(uint64_t c = 0; c < SIGMA; c++) { this->samples[c].load(in); }
    this->block_boundaries.load(in);
    this->block_rank.load(in, &(this->block_boundaries));
    this->block_select.load(in, &(this->block_boundaries));
  }
}

void
RLSequence::buildRank()
{
  std::vector<uint64_t> block_ends;
  uint64_t seq_pos = 0, rle_pos = 0;
  while(rle_pos < this->runs())
  {
    range_type run = this->readRun(rle_pos); seq_pos += run.second;
    if(rle_pos >= this->runs() || rle_pos % SAMPLE_RATE == 0) { block_ends.push_back(seq_pos - 1); }
  }

  // Block boundaries.
  uint64_t blocks = block_ends.size();
  {
    sd_vector<> temp(block_ends.begin(), block_ends.end());
    util::clear(block_ends);
    this->block_boundaries.swap(temp);
    util::init_support(this->block_rank, &(this->block_boundaries));
    util::init_support(this->block_select, &(this->block_boundaries));
  }

  // Samples. SIGMA passes vs. higher space usage? Multi-threaded?
  for(uint64_t c = 0; c < SIGMA; c++)
  {
    int_vector<0> temp(blocks, 0, bitlength(this->size()));
    for(uint64_t block = 0; block < blocks; block++)
    {
      uint64_t rle_pos = block * SAMPLE_RATE, limit = std::min(this->runs(), (block + 1) * SAMPLE_RATE);
      while(rle_pos < limit)
      {
        range_type run = this->readRun(rle_pos);
        if(run.first == c) { temp[block] += run.second; }
      }
    }
    util::assign(this->samples[c], CumulativeArray(temp, temp.size()));
  }
}

uint64_t
RLSequence::hash(const Alphabet& alpha) const
{
  uint64_t rle_pos = 0, val = FNV_OFFSET_BASIS;
  while(rle_pos < this->runs())
  {
    range_type run = this->readRun(rle_pos);
    uint8_t c = alpha.comp2char[run.first];
    for(uint64_t i = 0; i < run.second; i++) { val = fnv1a_hash(c, val); }
  }
  return val;
}

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

template<>
SimpleFM<RLSequence>::SimpleFM(const std::string& base_name, LoadMode mode)
{
  this->sample_rate = 0;

  if(mode == mode_native || mode == mode_ropebwt2)
  {
    std::string filename = base_name + NATIVE_BWT_EXTENSION;
    std::ifstream in(filename.c_str(), std::ios_base::binary);
    if(!in)
    {
      std::cerr << "SimpleFM::SimpleFM(): Cannot open BWT file " << filename << " (native format)" << std::endl;
      return;
    }
    this->bwt.load(in, mode == mode_ropebwt2); in.close();
  }
  else
  {
    int_vector_buffer<8> buffer(base_name + BWT_EXTENSION);
    RLSequence temp(buffer, buffer.size());
    this->bwt.swap(temp);
  }

  this->loadAlphabet(base_name);
  this->loadSamples(base_name);
}

template<>
void
characterCounts(const RLSequence& sequence, uint64_t size, int_vector<64>& counts)
{
  for(uint64_t c = 0; c < counts.size(); c++) { counts[c] = 0; }

  uint64_t rle_pos = 0;
  while(rle_pos < sequence.runs())
  {
    range_type run = sequence.readRun(rle_pos);
    counts[run.first] += run.second;
  }
}

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

} // namespace relative
<|endoftext|>


<commit_before>#include "perlin.h"

#include <armadillo/armadillo>
#include <math.h>
#include <stdlib.h>
#include <time.h>
#include <algorithm>
#include <functional>

#include "mathshelper.h"
#include "interpolation.h"

using namespace arma;
using namespace maths;

namespace perlin {
    //PRIVATE gnre un nombre alatoire entre 0 et 1
    double generateRandom() {
        return rand() / (double) RAND_MAX;
    }

    void generatePerlinOctave(Mat<double> &output,
                              int offset,
                              float frequency,
                              bool repeatable) {

        //Dtermination de la taille de la matrice
        int size = (int) std::min(output.n_rows, output.n_cols);
        //marche le mieux avec des tailles de pattern de la forme 2^n + 1 et frquence en 2^i
        int period = max((int) ((size - 1) / frequency), 1);

        // Implmentation de la rptabilit
        int firstX = 0, firstY = firstX;
        int lastX = repeatable ? size - period : size, lastY = lastX;

        int overflowX = period * ((size - 1) / period);
        if (repeatable) {
            overflowX = size;
        }
        int overflowY = overflowX;

        //Gnration des valeurs alatoires
        for (int x = firstX; x < lastX; x += period) {
            for (int y = firstY; y < lastY; y += period) {
                output(x, y) = generateRandom();
            }
        }

        //Interpolation
        for (int x = 0; x < size; x++) {
            for (int y = 0; y < size; y++) {

                if (x % period != 0 || x >= lastX ||
					y % period != 0 || y >= lastY) {

                    //Calcul des bornes
                    int borneX1, borneX2, borneY1, borneY2;

                    int tileX = min(x, lastX) / period;
                    int tileY = min(y, lastY) / period;

                    borneX1 = tileX * period;
                    borneY1 = tileY * period;
                    borneX2 = borneX1 + period;
                    borneY2 = borneY1 + period;

                    if (borneX2 >= lastX) {
                        borneX2 = overflowX;
                    }
                    if (borneY2 >= lastY) {
                        borneY2 = overflowY;
                    }

                    //Interpolation
                    double v1 = interpolate(borneX1, output(borneX1, borneY1),
                                            borneX2, output(borneX2 % size, borneY1),
                                            x);

                    double v2 = interpolate(borneX1, output(borneX1, borneY2 % size),
                                            borneX2, output(borneX2 % size, borneY2 % size),
                                            x);

                    output(x, y) = interpolate(borneY1, v1, borneY2, v2, y);
                }
            }
        }
    }

    void generatePerlinNoise2D(Mat<double> &output,
                               int offset,
                               int octaveCount,
                               float frequency,
                               float persistence,
                               bool repeatable) {

        //Initialisation du random avec une seed quelconque
        srand(time(NULL));

        //Dtermination de la taille de la matrice
        const uword size = std::min(output.n_rows, output.n_cols);

        output.fill(0);

        double persistenceSum = 0;
        for (int i = 1; i <= octaveCount; i++) {
            persistenceSum += pow(persistence, i);
        }

        Mat<double> octave(size, size);
        for (int i = 1; i <= octaveCount; i++) {
            generatePerlinOctave(octave, offset * (i - 1), frequency * (float) pow(2, i - 1), repeatable);
            output += octave * pow(persistence, i) / persistenceSum;
        }
    }

    Mat<double> generatePerlinNoise2D(int size,
                                      int offset,
                                      int octaves,
                                      float frequency,
                                      float persistence,
                                      bool repeatable) {

        Mat<double> result(size, size);
        generatePerlinNoise2D(result, offset, octaves, frequency, persistence, repeatable);
        return result;
    }

	void join(arma::Mat<double> &mat1,
		      arma::Mat<double> &mat2,
		      const Direction & direction,
		      int octaves,
		      float frequency,
		      float persistence) {

		// Vrification des dimensions de mat1 et mat2
		int length1, length2, depth1, depth2;
		if (direction == Direction::AXIS_Y) {
			length1 = mat1.n_cols;
			length2 = mat2.n_cols;
			depth1 = mat1.n_rows;
			depth2 = mat2.n_rows;
		}
		else {
			length1 = mat1.n_rows;
			length2 = mat2.n_rows;
			depth1 = mat1.n_cols;
			depth2 = mat2.n_cols;
		}

		// TODO dfinir le comportement lorsque length2 /= length1
		int length = min(length1, length2);
		int depth = min(depth1, depth2);

		// Permet d'abstraire les directions.
		// les x sont dans le sens de la longueur des deux matrices  joindre
		// les y reprsentent l'loignement  la jointure.
		// y ngatif -> mat1, y positifs -> mat2
		std::function<double & (int, int)> at;

		switch (direction) {
		case Direction::AXIS_Y:
			at = [&mat1, &mat2](int x, int y) -> double & {
				if (y < 0) {
					return mat1(x, mat1.n_cols + y);
				}
				else {
					return mat2(x, y);
				}
			};
			break;
		case Direction::AXIS_X:
			at = [&mat1, &mat2](int x, int y) -> double & {
				if (y < 0) {
					return mat1(mat1.n_rows + y, x);
				}
				else {
					return mat2(y, x);
				}
			};
			break;
		}

		// Perlin
		int period = (int)ceil(depth / frequency);
		int joinDepth1 = (depth1 / period - 1) * period - depth1;
		int joinDepth2 = period;

		for (int i = 0; i < octaves; i++) {
			// Gnration des points
			for (int y = joinDepth2; y >= joinDepth1 + period; y -= period) {

			}

			// Interpolation entre les points

			// Ajout de l'octave au joint

			// Incrmentation de la priode
			period = (int) ceil(period / 2.0);
		}
	}
}
<commit_msg>Algo join perlin : calcul des offsets<commit_after>#include "perlin.h"

#include <armadillo/armadillo>
#include <math.h>
#include <stdlib.h>
#include <time.h>
#include <algorithm>
#include <functional>

#include "mathshelper.h"
#include "interpolation.h"

using namespace arma;
using namespace maths;

namespace perlin {
    //PRIVATE gnre un nombre alatoire entre 0 et 1
    double generateRandom() {
        return rand() / (double) RAND_MAX;
    }

    void generatePerlinOctave(Mat<double> &output,
                              int offset,
                              float frequency,
                              bool repeatable) {

        //Dtermination de la taille de la matrice
        int size = (int) std::min(output.n_rows, output.n_cols);
        //marche le mieux avec des tailles de pattern de la forme 2^n + 1 et frquence en 2^i
        int period = max((int) ((size - 1) / frequency), 1);

        // Implmentation de la rptabilit
        int firstX = 0, firstY = firstX;
        int lastX = repeatable ? size - period : size, lastY = lastX;

        int overflowX = period * ((size - 1) / period);
        if (repeatable) {
            overflowX = size;
        }
        int overflowY = overflowX;

        //Gnration des valeurs alatoires
        for (int x = firstX; x < lastX; x += period) {
            for (int y = firstY; y < lastY; y += period) {
                output(x, y) = generateRandom();
            }
        }

        //Interpolation
        for (int x = 0; x < size; x++) {
            for (int y = 0; y < size; y++) {

                if (x % period != 0 || x >= lastX ||
					y % period != 0 || y >= lastY) {

                    //Calcul des bornes
                    int borneX1, borneX2, borneY1, borneY2;

                    int tileX = min(x, lastX) / period;
                    int tileY = min(y, lastY) / period;

                    borneX1 = tileX * period;
                    borneY1 = tileY * period;
                    borneX2 = borneX1 + period;
                    borneY2 = borneY1 + period;

                    if (borneX2 >= lastX) {
                        borneX2 = overflowX;
                    }
                    if (borneY2 >= lastY) {
                        borneY2 = overflowY;
                    }

                    //Interpolation
                    double v1 = interpolate(borneX1, output(borneX1, borneY1),
                                            borneX2, output(borneX2 % size, borneY1),
                                            x);

                    double v2 = interpolate(borneX1, output(borneX1, borneY2 % size),
                                            borneX2, output(borneX2 % size, borneY2 % size),
                                            x);

                    output(x, y) = interpolate(borneY1, v1, borneY2, v2, y);
                }
            }
        }
    }

    void generatePerlinNoise2D(Mat<double> &output,
                               int offset,
                               int octaveCount,
                               float frequency,
                               float persistence,
                               bool repeatable) {

        //Initialisation du random avec une seed quelconque
        srand((uint32_t) time(NULL));

        //Dtermination de la taille de la matrice
        const uword size = std::min(output.n_rows, output.n_cols);

        output.fill(0);

        double persistenceSum = 0;
        for (int i = 1; i <= octaveCount; i++) {
            persistenceSum += pow(persistence, i);
        }

        Mat<double> octave(size, size);
        for (int i = 1; i <= octaveCount; i++) {
            generatePerlinOctave(octave, offset * (i - 1), frequency * (float) pow(2, i - 1), repeatable);
            output += octave * pow(persistence, i) / persistenceSum;
        }
    }

    Mat<double> generatePerlinNoise2D(int size,
                                      int offset,
                                      int octaves,
                                      float frequency,
                                      float persistence,
                                      bool repeatable) {

        Mat<double> result((uword) size, (uword) size);
        generatePerlinNoise2D(result, offset, octaves, frequency, persistence, repeatable);
        return result;
    }

	void join(arma::Mat<double> &mat1,
		      arma::Mat<double> &mat2,
		      const Direction & direction,
		      int octaves,
		      float frequency,
		      float persistence) {

		// Vrification des dimensions de mat1 et mat2
		int length1, length2, depth1, depth2;
		if (direction == Direction::AXIS_Y) {
			length1 = (int) mat1.n_cols;
			length2 = (int) mat2.n_cols;
			depth1 = (int) mat1.n_rows;
			depth2 = (int) mat2.n_rows;
		}
		else {
			length1 = (int) mat1.n_rows;
			length2 = (int) mat2.n_rows;
			depth1 = (int) mat1.n_cols;
			depth2 = (int) mat2.n_cols;
		}

		// TODO dfinir le comportement lorsque length2 /= length1
		int length = min(length1, length2);
		int depth = min(depth1, depth2);
        int period = (int) ceil((double) (depth / frequency));

        int joinDepth1 = - (depth1 % period) - period;
        int joinDepth2 = period;
        int joinDepth = joinDepth2 - joinDepth1 - 2;
        int joinOffset = - 1 - joinDepth1;

		// Permet d'abstraire les directions.
		// les x sont dans le sens de la longueur des deux matrices  joindre
		// les y reprsentent l'loignement  la jointure.
		// y < joinOffset -> mat1, y > joinOffset -> mat2
		std::function<double & (int, int)> at;

		switch (direction) {
		case Direction::AXIS_Y:
			at = [&mat1, &mat2, &joinOffset](int x, int y) -> double & {
                y -= joinOffset;
				if (y < 0) {
					return mat1(x, mat1.n_cols + y);
				}
				else {
					return mat2(x, y);
				}
			};
			break;
		case Direction::AXIS_X:
			at = [&mat1, &mat2, &joinOffset](int x, int y) -> double & {
                y -= joinOffset;
				if (y < 0) {
					return mat1(mat1.n_rows + y, x);
				}
				else {
					return mat2(y, x);
				}
			};
			break;
		}

		// Perlin

        Mat<double> octave((uword) length, (uword) joinDepth);

		for (int i = 0; i < octaves; i++) {
            Mat<double> join((uword) length, (uword) joinDepth);

			// Gnration des points
			for (int y = joinDepth2 - period; y >= joinDepth1 + period; y -= period) {
                for (int x = 0; x < length; x += period) {
                    //join(x, y + 1 - joinDepth1);
                }
			}

			// Interpolation entre les points

			// Ajout de l'octave au joint

			// Incrmentation de la priode
			period = (int) ceil(period / 2.0);
		}
	}
}
<|endoftext|>