<commit_before>#include <v8.h>
#include "macros.h"
#include "gc.h"

#ifdef windows
#	include <my_global.h>
#endif

#include <mysql.h>
#include <stdlib.h>
#include <string>

#define MYSQL_ERROR mysql_error(conn)
#define ASSERT_CONNECTED if (!conn) { return JS_EXCEPTION("No connection established yet."); }
#define MYSQL_PTR MYSQL * conn = LOAD_PTR(0, MYSQL *)

namespace {

v8::Persistent<v8::FunctionTemplate> rest;

void destroy(v8::Handle<v8::Object> obj) {
	v8::Handle<v8::Function> fun = v8::Handle<v8::Function>::Cast(obj->Get(JS_STR("close")));
	fun->Call(obj, 0, NULL);
}

v8::Handle<v8::Value> createResult(MYSQL * conn) {
	MYSQL_RES * res = mysql_store_result(conn);

	if (res) {
		v8::Handle<v8::Value> resargs[] = { v8::External::New((void *) res) };
		return rest->GetFunction()->NewInstance(1, resargs);
	} else {
		if (mysql_field_count(conn)) {
			return JS_EXCEPTION(MYSQL_ERROR);
		} else {
			return JS_BOOL(true);
		}
	}
}

/**
 * MySQL constructor does basically nothing. It just adds "this.close()" method to global GC
 */
JS_METHOD(_mysql) {
	ASSERT_CONSTRUCTOR;
	SAVE_PTR(0, NULL);
	GC * gc = GC_PTR;
	gc->add(args.This(), destroy);
	return args.This();
}

/**
 * Close DB connection
 */
JS_METHOD(_close) {
	MYSQL_PTR;
	if (conn) {
		mysql_close(conn);
		SAVE_PTR(0, NULL);
	}
	return args.This();
}

/**
 * Should be called ASAP: new MySQL().connect("host", "user", "pass", "db")
 */
JS_METHOD(_connect) {
	if (args.Length() < 4) {
		return JS_EXCEPTION("Invalid call format. Use 'mysql.connect(host, user, pass, db)'");
	}

	MYSQL * conn;

	v8::String::Utf8Value host(args[0]);
	v8::String::Utf8Value user(args[1]);
	v8::String::Utf8Value pass(args[2]);
	v8::String::Utf8Value db(args[3]);

	conn = mysql_init(NULL);
	if (!mysql_real_connect(conn, *host, *user, *pass, *db, 0, NULL, CLIENT_MULTI_STATEMENTS)) {
		return JS_EXCEPTION(MYSQL_ERROR);
	} else {
		mysql_query(conn, "SET NAMES 'utf8'");
		SAVE_PTR(0, conn);
		return args.This();
	}
}

/**
 * Query takes a string argument and returns an instance of Result object
 */
JS_METHOD(_query) {
	MYSQL_PTR;
	ASSERT_CONNECTED;
	if (args.Length() < 1) {
		return JS_EXCEPTION("No query specified");
	}
	v8::String::Utf8Value q(args[0]);

	int code = mysql_real_query(conn, *q, q.length());
	if (code != 0) { return JS_EXCEPTION(MYSQL_ERROR); }

	int qc = args.This()->Get(JS_STR("queryCount"))->ToInteger()->Int32Value();
	args.This()->Set(JS_STR("queryCount"), JS_INT(qc+1));

	return createResult(conn);
}

/**
 * Fetch next result from a multi-result set
 */
JS_METHOD(_nextresult) {
	MYSQL_PTR;
	ASSERT_CONNECTED;

	int status = mysql_next_result(conn);

	if (status == -1) { return JS_NULL; }
	if (status > 0) { return JS_EXCEPTION(MYSQL_ERROR); }
	return createResult(conn);
}

JS_METHOD(_affectedrows) {
	MYSQL_PTR;
	ASSERT_CONNECTED;
	return JS_INT(mysql_affected_rows(conn));
}

JS_METHOD(_insertid) {
	MYSQL_PTR;
	ASSERT_CONNECTED;
	return JS_INT(mysql_insert_id(conn));
}

JS_METHOD(_escape) {
	MYSQL_PTR;
	ASSERT_CONNECTED;

	if (args.Length() < 1) {
		return JS_EXCEPTION("Nothing to escape");
	}
	v8::String::Utf8Value str(args[0]);

	int len = args[0]->ToString()->Utf8Length();
	char * result = new char[2*len + 1];

	int length = mysql_real_escape_string(conn, result, *str, len);
	v8::Handle<v8::Value> output = JS_STR(result, length);
	delete[] result;
	return output;
}

JS_METHOD(_qualify) {
	if (args.Length() < 1) {
		return JS_EXCEPTION("Nothing to qualify");
	}

	v8::String::Utf8Value str(args[0]);
	std::string result = "`";
	result += *str;
	result += "`";

	v8::Handle<v8::Value> output = JS_STR(result.c_str());
	return output;
}

JS_METHOD(_result) {
	SAVE_VALUE(0, args[0]);
	return args.This();
}

JS_METHOD(_numrows) {
	MYSQL_RES * res = LOAD_PTR(0, MYSQL_RES *);

	return JS_INT(mysql_num_rows(res));
}

JS_METHOD(_numfields) {
	MYSQL_RES * res = LOAD_PTR(0, MYSQL_RES *);

	return JS_INT(mysql_num_fields(res));
}

JS_METHOD(_fetchnames) {
	MYSQL_RES * res = LOAD_PTR(0, MYSQL_RES *);

	int cnt = mysql_num_fields(res);
	MYSQL_FIELD * fields = mysql_fetch_fields(res);
	v8::Handle<v8::Array> result = v8::Array::New(cnt);

	for(int i = 0; i < cnt; i++) {
		result->Set(JS_INT(i), JS_STR(fields[i].name));
	}

	return result;
}

/**
 * Return result data as an array of JS arrays
 */
JS_METHOD(_fetcharrays) {
	MYSQL_RES * res = LOAD_PTR(0, MYSQL_RES *);
	mysql_data_seek(res, 0);

	int x = mysql_num_fields(res);
	int y = mysql_num_rows(res);
	MYSQL_ROW row;
	v8::Handle<v8::Array> result = v8::Array::New(y);

	for (int i = 0; i < y; i++) {
		row = mysql_fetch_row(res);
		v8::Handle<v8::Array> item = v8::Array::New(x);
		result->Set(JS_INT(i), item);
		for (int j=0; j<x; j++) {
			if (row[j] == NULL) {
				item->Set(JS_INT(j), v8::Null());
			} else {
				item->Set(JS_INT(j), JS_STR(row[j]));
			}
		}
	}

	return result;
}

/**
 * Return result data as an array of JS objects, indexed with column names
 */
JS_METHOD(_fetchobjects) {
	MYSQL_RES * res = LOAD_PTR(0, MYSQL_RES *);
	mysql_data_seek(res, 0);

	int x = mysql_num_fields(res);
	int y = mysql_num_rows(res);
	MYSQL_FIELD * fields = mysql_fetch_fields(res);
	MYSQL_ROW row;
	v8::Handle<v8::Array> result = v8::Array::New(y);

	for (int i = 0; i < y; i++) {
		row = mysql_fetch_row(res);
		v8::Handle<v8::Object> item = v8::Object::New();
		result->Set(JS_INT(i), item);
		for (int j=0; j<x; j++) {
			if (row[j] == NULL) {
				item->Set(JS_STR(fields[j].name), v8::Null());
			} else {
				item->Set(JS_STR(fields[j].name), JS_STR(row[j]));
			}
		}
	}

	return result;
}

} /* end namespace */

SHARED_INIT() {
	v8::HandleScope handle_scope;
	v8::Handle<v8::FunctionTemplate> ft = v8::FunctionTemplate::New(_mysql);
	ft->SetClassName(JS_STR("MySQL"));

	v8::Handle<v8::ObjectTemplate> ot = ft->InstanceTemplate();
	ot->SetInternalFieldCount(1); /* connection */

	/**
	 * Static property, useful for stats gathering
	 */
	ot->Set(JS_STR("queryCount"), JS_INT(0));

	v8::Handle<v8::ObjectTemplate> pt = ft->PrototypeTemplate();

	/**
	 * MySQL prototype methods (new MySQL().*)
	 */
	pt->Set(JS_STR("connect"), v8::FunctionTemplate::New(_connect));
	pt->Set(JS_STR("close"), v8::FunctionTemplate::New(_close));
	pt->Set(JS_STR("query"), v8::FunctionTemplate::New(_query));
	pt->Set(JS_STR("nextResult"), v8::FunctionTemplate::New(_nextresult));
	pt->Set(JS_STR("affectedRows"), v8::FunctionTemplate::New(_affectedrows));
	pt->Set(JS_STR("escape"), v8::FunctionTemplate::New(_escape));
	pt->Set(JS_STR("qualify"), v8::FunctionTemplate::New(_qualify));
	pt->Set(JS_STR("insertId"), v8::FunctionTemplate::New(_insertid));

	rest = v8::Persistent<v8::FunctionTemplate>::New(v8::FunctionTemplate::New(_result));
	rest->SetClassName(JS_STR("Result"));

	v8::Handle<v8::ObjectTemplate> resinst = rest->InstanceTemplate();
	resinst->SetInternalFieldCount(1);

	v8::Handle<v8::ObjectTemplate> resproto = rest->PrototypeTemplate();

	/**
	 * Result prototype methods (new MySQL().query().*)
	 */
	resproto->Set(JS_STR("numRows"), v8::FunctionTemplate::New(_numrows));
	resproto->Set(JS_STR("numFields"), v8::FunctionTemplate::New(_numfields));
	resproto->Set(JS_STR("fetchNames"), v8::FunctionTemplate::New(_fetchnames));
	resproto->Set(JS_STR("fetchArrays"), v8::FunctionTemplate::New(_fetcharrays));
	resproto->Set(JS_STR("fetchObjects"), v8::FunctionTemplate::New(_fetchobjects));

	exports->Set(JS_STR("MySQL"), ft->GetFunction());
}
<commit_msg>mysql result close()<commit_after>#include <v8.h>
#include "macros.h"
#include "gc.h"

#ifdef windows
#	include <my_global.h>
#endif

#include <mysql.h>
#include <stdlib.h>
#include <string>

#define MYSQL_ERROR mysql_error(conn)
#define ASSERT_CONNECTED if (!conn) { return JS_EXCEPTION("No connection established yet."); }
#define MYSQL_PTR MYSQL * conn = LOAD_PTR(0, MYSQL *)

namespace {

v8::Persistent<v8::FunctionTemplate> rest;

void destroy(v8::Handle<v8::Object> obj) {
	v8::Handle<v8::Function> fun = v8::Handle<v8::Function>::Cast(obj->Get(JS_STR("close")));
	fun->Call(obj, 0, NULL);
}

v8::Handle<v8::Value> createResult(MYSQL * conn) {
	MYSQL_RES * res = mysql_store_result(conn);

	if (res) {
		v8::Handle<v8::Value> resargs[] = { v8::External::New((void *) res) };
		return rest->GetFunction()->NewInstance(1, resargs);
	} else {
		if (mysql_field_count(conn)) {
			return JS_EXCEPTION(MYSQL_ERROR);
		} else {
			return JS_BOOL(true);
		}
	}
}

/**
 * MySQL constructor does basically nothing. It just adds "this.close()" method to global GC
 */
JS_METHOD(_mysql) {
	ASSERT_CONSTRUCTOR;
	SAVE_PTR(0, NULL);
	GC * gc = GC_PTR;
	gc->add(args.This(), destroy);
	return args.This();
}

/**
 * Close DB connection
 */
JS_METHOD(_close) {
	MYSQL_PTR;
	if (conn) {
		mysql_close(conn);
		SAVE_PTR(0, NULL);
	}
	return args.This();
}

/**
 * Should be called ASAP: new MySQL().connect("host", "user", "pass", "db")
 */
JS_METHOD(_connect) {
	if (args.Length() < 4) {
		return JS_EXCEPTION("Invalid call format. Use 'mysql.connect(host, user, pass, db)'");
	}

	MYSQL * conn;

	v8::String::Utf8Value host(args[0]);
	v8::String::Utf8Value user(args[1]);
	v8::String::Utf8Value pass(args[2]);
	v8::String::Utf8Value db(args[3]);

	conn = mysql_init(NULL);
	if (!mysql_real_connect(conn, *host, *user, *pass, *db, 0, NULL, CLIENT_MULTI_STATEMENTS)) {
		return JS_EXCEPTION(MYSQL_ERROR);
	} else {
		mysql_query(conn, "SET NAMES 'utf8'");
		SAVE_PTR(0, conn);
		return args.This();
	}
}

/**
 * Query takes a string argument and returns an instance of Result object
 */
JS_METHOD(_query) {
	MYSQL_PTR;
	ASSERT_CONNECTED;
	if (args.Length() < 1) {
		return JS_EXCEPTION("No query specified");
	}
	v8::String::Utf8Value q(args[0]);

	int code = mysql_real_query(conn, *q, q.length());
	if (code != 0) { return JS_EXCEPTION(MYSQL_ERROR); }

	int qc = args.This()->Get(JS_STR("queryCount"))->ToInteger()->Int32Value();
	args.This()->Set(JS_STR("queryCount"), JS_INT(qc+1));

	return createResult(conn);
}

/**
 * Fetch next result from a multi-result set
 */
JS_METHOD(_nextresult) {
	MYSQL_PTR;
	ASSERT_CONNECTED;

	int status = mysql_next_result(conn);

	if (status == -1) { return JS_NULL; }
	if (status > 0) { return JS_EXCEPTION(MYSQL_ERROR); }
	return createResult(conn);
}

JS_METHOD(_affectedrows) {
	MYSQL_PTR;
	ASSERT_CONNECTED;
	return JS_INT(mysql_affected_rows(conn));
}

JS_METHOD(_insertid) {
	MYSQL_PTR;
	ASSERT_CONNECTED;
	return JS_INT(mysql_insert_id(conn));
}

JS_METHOD(_escape) {
	MYSQL_PTR;
	ASSERT_CONNECTED;

	if (args.Length() < 1) {
		return JS_EXCEPTION("Nothing to escape");
	}
	v8::String::Utf8Value str(args[0]);

	int len = args[0]->ToString()->Utf8Length();
	char * result = new char[2*len + 1];

	int length = mysql_real_escape_string(conn, result, *str, len);
	v8::Handle<v8::Value> output = JS_STR(result, length);
	delete[] result;
	return output;
}

JS_METHOD(_qualify) {
	if (args.Length() < 1) {
		return JS_EXCEPTION("Nothing to qualify");
	}

	v8::String::Utf8Value str(args[0]);
	std::string result = "`";
	result += *str;
	result += "`";

	v8::Handle<v8::Value> output = JS_STR(result.c_str());
	return output;
}

JS_METHOD(_result) {
	SAVE_VALUE(0, args[0]);
	return args.This();
}

JS_METHOD(_numrows) {
	MYSQL_RES * res = LOAD_PTR(0, MYSQL_RES *);

	return JS_INT(mysql_num_rows(res));
}

JS_METHOD(_numfields) {
	MYSQL_RES * res = LOAD_PTR(0, MYSQL_RES *);

	return JS_INT(mysql_num_fields(res));
}

JS_METHOD(_fetchnames) {
	MYSQL_RES * res = LOAD_PTR(0, MYSQL_RES *);

	int cnt = mysql_num_fields(res);
	MYSQL_FIELD * fields = mysql_fetch_fields(res);
	v8::Handle<v8::Array> result = v8::Array::New(cnt);

	for(int i = 0; i < cnt; i++) {
		result->Set(JS_INT(i), JS_STR(fields[i].name));
	}

	return result;
}

/**
 * Return result data as an array of JS arrays
 */
JS_METHOD(_fetcharrays) {
	MYSQL_RES * res = LOAD_PTR(0, MYSQL_RES *);
	mysql_data_seek(res, 0);

	int x = mysql_num_fields(res);
	int y = mysql_num_rows(res);
	MYSQL_ROW row;
	v8::Handle<v8::Array> result = v8::Array::New(y);

	for (int i = 0; i < y; i++) {
		row = mysql_fetch_row(res);
		v8::Handle<v8::Array> item = v8::Array::New(x);
		result->Set(JS_INT(i), item);
		for (int j=0; j<x; j++) {
			if (row[j] == NULL) {
				item->Set(JS_INT(j), v8::Null());
			} else {
				item->Set(JS_INT(j), JS_STR(row[j]));
			}
		}
	}

	return result;
}

/**
 * Return result data as an array of JS objects, indexed with column names
 */
JS_METHOD(_fetchobjects) {
	MYSQL_RES * res = LOAD_PTR(0, MYSQL_RES *);
	mysql_data_seek(res, 0);

	int x = mysql_num_fields(res);
	int y = mysql_num_rows(res);
	MYSQL_FIELD * fields = mysql_fetch_fields(res);
	MYSQL_ROW row;
	v8::Handle<v8::Array> result = v8::Array::New(y);

	for (int i = 0; i < y; i++) {
		row = mysql_fetch_row(res);
		v8::Handle<v8::Object> item = v8::Object::New();
		result->Set(JS_INT(i), item);
		for (int j=0; j<x; j++) {
			if (row[j] == NULL) {
				item->Set(JS_STR(fields[j].name), v8::Null());
			} else {
				item->Set(JS_STR(fields[j].name), JS_STR(row[j]));
			}
		}
	}

	return result;
}

JS_METHOD(_result_close) {
	MYSQL_RES * res = LOAD_PTR(0, MYSQL_RES *);
	if (res) {
		mysql_free_result(res);
		SAVE_PTR(0, NULL);
		return JS_BOOL(true);
	} else {
		return JS_BOOL(false);
	}
}

} /* end namespace */

SHARED_INIT() {
	v8::HandleScope handle_scope;
	v8::Handle<v8::FunctionTemplate> ft = v8::FunctionTemplate::New(_mysql);
	ft->SetClassName(JS_STR("MySQL"));

	v8::Handle<v8::ObjectTemplate> ot = ft->InstanceTemplate();
	ot->SetInternalFieldCount(1); /* connection */

	/**
	 * Static property, useful for stats gathering
	 */
	ot->Set(JS_STR("queryCount"), JS_INT(0));

	v8::Handle<v8::ObjectTemplate> pt = ft->PrototypeTemplate();

	/**
	 * MySQL prototype methods (new MySQL().*)
	 */
	pt->Set(JS_STR("connect"), v8::FunctionTemplate::New(_connect));
	pt->Set(JS_STR("close"), v8::FunctionTemplate::New(_close));
	pt->Set(JS_STR("query"), v8::FunctionTemplate::New(_query));
	pt->Set(JS_STR("nextResult"), v8::FunctionTemplate::New(_nextresult));
	pt->Set(JS_STR("affectedRows"), v8::FunctionTemplate::New(_affectedrows));
	pt->Set(JS_STR("escape"), v8::FunctionTemplate::New(_escape));
	pt->Set(JS_STR("qualify"), v8::FunctionTemplate::New(_qualify));
	pt->Set(JS_STR("insertId"), v8::FunctionTemplate::New(_insertid));

	rest = v8::Persistent<v8::FunctionTemplate>::New(v8::FunctionTemplate::New(_result));
	rest->SetClassName(JS_STR("Result"));

	v8::Handle<v8::ObjectTemplate> resinst = rest->InstanceTemplate();
	resinst->SetInternalFieldCount(1);

	v8::Handle<v8::ObjectTemplate> resproto = rest->PrototypeTemplate();

	/**
	 * Result prototype methods (new MySQL().query().*)
	 */
	resproto->Set(JS_STR("numRows"), v8::FunctionTemplate::New(_numrows));
	resproto->Set(JS_STR("numFields"), v8::FunctionTemplate::New(_numfields));
	resproto->Set(JS_STR("fetchNames"), v8::FunctionTemplate::New(_fetchnames));
	resproto->Set(JS_STR("fetchArrays"), v8::FunctionTemplate::New(_fetcharrays));
	resproto->Set(JS_STR("fetchObjects"), v8::FunctionTemplate::New(_fetchobjects));
	resproto->Set(JS_STR("close"), v8::FunctionTemplate::New(_result_close));

	exports->Set(JS_STR("MySQL"), ft->GetFunction());
}
<|endoftext|>


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

#include "thread.h"
#include <stdexcept>

namespace votca {
    namespace tools {

        static void *runwrapper(void *arg) {
            Thread *thread = (Thread*) (arg);
            thread->Run();
            pthread_exit(NULL);
        }

        Thread::Thread() {

        }

        Thread::~Thread() {

        }

        void Thread::Start() {
            pthread_attr_t attr;

            pthread_attr_init(&attr);
            /*
             * according to the POSIX standard, threads are created in the joinable state
             * by default
             * however, some platforms do not obey
             *
             * explicitly create the thread in the joinable state
             * the main program can then wait for the thread by calling pthread_join(thread)
             *
             */
            pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
            _finished = false;

            int rc = pthread_create(&_thread, &attr, runwrapper, (void *) this);
            if (rc) {
                throw std::runtime_error("ERROR; return code from pthread_create() is "
                        + rc);
            }

        }

        void Thread::WaitDone() {
            void * status;
            int rc = pthread_join(_thread, &status);
            if (rc) {
                throw std::runtime_error("ERROR; return code from pthread_join() is "
                        + rc);
            }
            _finished = true;
        }

        bool Thread::IsFinished() const {
            return _finished;
        }

    }
}

<commit_msg>thread.cc: fixed xlC warning<commit_after>/*
 * Copyright 2010 The VOTCA Development Team (http://www.votca.org)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

#include "thread.h"
#include <stdexcept>

namespace votca {
    namespace tools {

        static void *runwrapper(void *arg) {
            Thread *thread = (Thread*) (arg);
            thread->Run();
            pthread_exit(NULL);
            return NULL;
        }

        Thread::Thread() {

        }

        Thread::~Thread() {

        }

        void Thread::Start() {
            pthread_attr_t attr;

            pthread_attr_init(&attr);
            /*
             * according to the POSIX standard, threads are created in the joinable state
             * by default
             * however, some platforms do not obey
             *
             * explicitly create the thread in the joinable state
             * the main program can then wait for the thread by calling pthread_join(thread)
             *
             */
            pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
            _finished = false;

            int rc = pthread_create(&_thread, &attr, runwrapper, (void *) this);
            if (rc) {
                throw std::runtime_error("ERROR; return code from pthread_create() is "
                        + rc);
            }

        }

        void Thread::WaitDone() {
            void * status;
            int rc = pthread_join(_thread, &status);
            if (rc) {
                throw std::runtime_error("ERROR; return code from pthread_join() is "
                        + rc);
            }
            _finished = true;
        }

        bool Thread::IsFinished() const {
            return _finished;
        }

    }
}

<|endoftext|>


<commit_before>#include "include/redis_admin.h"

//TO-DO: When an operation fails, it should automatically detect whether there are
//Sentinels available and, if so, try to failover to another Redis Node.

void RedisAdmin::init(std::string hostname, int port, int timeout_seconds, int timeout_microseconds)
{
  struct timeval timeout = {timeout_seconds, timeout_microseconds};
  c = redisConnectWithTimeout(hostname.c_str(), port, timeout);

  if (c == NULL || c->err) {
    if (c == NULL)
    {
      throw RedisConnectionException( "Error: Cannot Allocate Redis Instance" );
    }
    else if (c->err)
    {
      std::string err_msg (c->errstr);
      err_msg = "Error:" + err_msg;
      throw RedisConnectionException( err_msg );
    }
  exit(1);
  }
}

RedisAdmin::RedisAdmin(std::string hostname, int port)
{
  init(hostname, port, 5, 0);
}

RedisAdmin::RedisAdmin(std::string hostname, int port, int timeout_seconds, int timeout_microseconds)
{
  init(hostname, port, timeout_seconds, timeout_microseconds);
}

RedisAdmin::~RedisAdmin()
{
  if (c)
  {
    delete c;
  }
  if (reply)
  {
    delete reply;
  }
}

//! Load a value from Redis
std::string RedisAdmin::load ( std::string key )
{
  std::string key_str = "GET " + key;
  reply = (redisReply *) redisCommand(c, key_str.c_str());
  std::string reply_str (reply->str);
  freeReplyObject(reply);
  return reply_str;
}

//! Save a value to Redis
bool RedisAdmin::save ( std::string key, std::string msg )
{
  reply = (redisReply *) redisCommand( c, "SET %s %s", key.c_str(), msg.c_str() );
  bool ret_val = false;
  if ( strcmp(reply->str, "OK") == 0 ) {
    ret_val = true;
  }
  freeReplyObject(reply);
  return ret_val;
}

//! Does a key exist in Redis?
bool RedisAdmin::exists ( std::string key )
{
  std::string key_str = "EXISTS " + key;
  reply = (redisReply *) redisCommand(c, key_str.c_str());
  int reply_code = reply->integer;
  freeReplyObject(reply);
  if (reply_code == 1) {
    return true;
  }
  return false;
}

//! Delete a value from Redis
bool RedisAdmin::del ( std::string key )
{
  std::string key_str = "DEL " + key;
  reply = (redisReply *) redisCommand( c, key_str.c_str() );
  freeReplyObject(reply);
  if (reply->integer > 0) {
    return true;
  }
  return false;
}

//! Expire a value in Redis after a specified number of seconds
bool RedisAdmin::expire ( std::string key, unsigned int second)
{
  std::string length_key = std::to_string(second);
  reply = (redisReply *) redisCommand( c, "EXPIRE %s %s", key.c_str(), length_key.c_str() );
  freeReplyObject(reply);
  if (reply->integer == 1) {
    return true;
  }
  return false;
}
<commit_msg>Redis Admin Rewrite Fixes<commit_after>#include "include/redis_admin.h"

//TO-DO: When an operation fails, it should automatically detect whether there are
//Sentinels available and, if so, try to failover to another Redis Node.

void RedisAdmin::init(std::string hostname, int port, int timeout_seconds, int timeout_microseconds)
{
  struct timeval timeout = {timeout_seconds, timeout_microseconds};
  c = redisConnectWithTimeout(hostname.c_str(), port, timeout);

  if (c == NULL || c->err) {
    if (c == NULL)
    {
      throw RedisConnectionException( "Error: Cannot Allocate Redis Instance" );
    }
    else if (c->err)
    {
      std::string err_msg (c->errstr);
      err_msg = "Error:" + err_msg;
      throw RedisConnectionException( err_msg );
    }
  exit(1);
  }
}

RedisAdmin::RedisAdmin(std::string hostname, int port)
{
  init(hostname, port, 5, 0);
}

RedisAdmin::RedisAdmin(std::string hostname, int port, int timeout_seconds, int timeout_microseconds)
{
  init(hostname, port, timeout_seconds, timeout_microseconds);
}

RedisAdmin::~RedisAdmin()
{
  if (c)
  {
    redisFree(c);
  }
  if (reply)
  {
    freeReplyObject(reply);
  }
}

//! Load a value from Redis
std::string RedisAdmin::load ( std::string key )
{
  std::string key_str = "GET " + key;
  reply = (redisReply *) redisCommand(c, key_str.c_str());
  std::string reply_str (reply->str);
  freeReplyObject(reply);
  return reply_str;
}

//! Save a value to Redis
bool RedisAdmin::save ( std::string key, std::string msg )
{
  reply = (redisReply *) redisCommand( c, "SET %s %s", key.c_str(), msg.c_str() );
  bool ret_val = false;
  if ( strcmp(reply->str, "OK") == 0 ) {
    ret_val = true;
  }
  freeReplyObject(reply);
  return ret_val;
}

//! Does a key exist in Redis?
bool RedisAdmin::exists ( std::string key )
{
  std::string key_str = "EXISTS " + key;
  reply = (redisReply *) redisCommand(c, key_str.c_str());
  int reply_code = reply->integer;
  freeReplyObject(reply);
  if (reply_code == 1) {
    return true;
  }
  return false;
}

//! Delete a value from Redis
bool RedisAdmin::del ( std::string key )
{
  std::string key_str = "DEL " + key;
  reply = (redisReply *) redisCommand( c, key_str.c_str() );
  freeReplyObject(reply);
  if (reply->integer > 0) {
    return true;
  }
  return false;
}

//! Expire a value in Redis after a specified number of seconds
bool RedisAdmin::expire ( std::string key, unsigned int second)
{
  std::string length_key = std::to_string(second);
  reply = (redisReply *) redisCommand( c, "EXPIRE %s %s", key.c_str(), length_key.c_str() );
  freeReplyObject(reply);
  if (reply->integer == 1) {
    return true;
  }
  return false;
}
<|endoftext|>


<commit_before>/*****************************************************************************
  mapMain.cpp

  (c) 2009 - Aaron Quinlan
  Hall Laboratory
  Department of Biochemistry and Molecular Genetics
  University of Virginia
  aaronquinlan@gmail.com

  Licenced under the GNU General Public License 2.0 license.
******************************************************************************/
#include "mapBed.h"
#include "version.h"

using namespace std;

// define our program name
#define PROGRAM_NAME "bedtools map"

// define our parameter checking macro
#define PARAMETER_CHECK(param, paramLen, actualLen) (strncmp(argv[i], param, min(actualLen, paramLen))== 0) && (actualLen == paramLen)

// function declarations
void map_help(void);

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

    // our configuration variables
    bool showHelp = false;

    // input files
    string bedAFile;
    string bedBFile;
    int column = 5;
    string operation = "sum";
    string nullValue = ".";

    // input arguments
    float overlapFraction = 1E-9;

    bool haveBedA           = false;
    bool haveBedB           = false;
    bool haveColumn         = false;
    bool haveOperation      = false;
    bool haveFraction       = false;
    bool reciprocalFraction = false;
    bool sameStrand         = false;
    bool diffStrand         = false;
    bool printHeader        = false;

    // check to see if we should print out some help
    if(argc <= 1) showHelp = true;

    for(int i = 1; i < argc; i++) {
        int parameterLength = (int)strlen(argv[i]);

        if((PARAMETER_CHECK("-h", 2, parameterLength)) ||
        (PARAMETER_CHECK("--help", 5, parameterLength))) {
            showHelp = true;
        }
    }

    if(showHelp) map_help();

    // do some parsing (all of these parameters require 2 strings)
    for(int i = 1; i < argc; i++) {

        int parameterLength = (int)strlen(argv[i]);

        if(PARAMETER_CHECK("-a", 2, parameterLength)) {
            if ((i+1) < argc) {
                haveBedA = true;
                bedAFile = argv[i + 1];
                i++;
            }
        }
        else if(PARAMETER_CHECK("-b", 2, parameterLength)) {
            if ((i+1) < argc) {
                haveBedB = true;
                bedBFile = argv[i + 1];
                i++;
            }
        }
        else if(PARAMETER_CHECK("-c", 2, parameterLength)) {
            if ((i+1) < argc) {
                haveColumn = true;
                column = atoi(argv[i + 1]);
                i++;
            }
        }
        else if(PARAMETER_CHECK("-o", 2, parameterLength)) {
            if ((i+1) < argc) {
                haveOperation = true;
                operation = argv[i + 1];
                i++;
            }
        }
        else if(PARAMETER_CHECK("-f", 2, parameterLength)) {
            if ((i+1) < argc) {
                haveFraction = true;
                overlapFraction = atof(argv[i + 1]);
                i++;
            }
        }
        else if(PARAMETER_CHECK("-r", 2, parameterLength)) {
            reciprocalFraction = true;
        }
        else if (PARAMETER_CHECK("-s", 2, parameterLength)) {
            sameStrand = true;
        }
        else if (PARAMETER_CHECK("-S", 2, parameterLength)) {
            diffStrand = true;
        }
        else if (PARAMETER_CHECK("-null", 5, parameterLength)) {
            nullValue = argv[i + 1];
            i++;
        }
        else if(PARAMETER_CHECK("-header", 7, parameterLength)) {
            printHeader = true;
        }
        else {
            cerr << endl << "*****ERROR: Unrecognized parameter: " << argv[i] << " *****" << endl << endl;
            showHelp = true;
        }
    }

    // make sure we have both input files
    if (!haveBedA || !haveBedB) {
        cerr << endl << "*****" << endl << "*****ERROR: Need -a and -b files. " << endl << "*****" << endl;
        showHelp = true;
    }

    if (reciprocalFraction && !haveFraction) {
        cerr << endl << "*****" << endl << "*****ERROR: If using -r, you need to define -f." << endl << "*****" << endl;
        showHelp = true;
    }

    if (sameStrand && diffStrand) {
        cerr << endl << "*****" << endl << "*****ERROR: Request either -s OR -S, not both." << endl << "*****" << endl;
        showHelp = true;
    }

    if (!showHelp) {

        BedMap *bm = new BedMap(bedAFile, bedBFile, column, operation,
                                       overlapFraction, sameStrand,
                                       diffStrand, reciprocalFraction,
                                       nullValue, printHeader);
        delete bm;
        return 0;
    }
    else {
        map_help();
        return 0;
    }
}

void map_help(void) {

    cerr << "\nTool:    bedtools map (aka mapBed)" << endl;
    cerr << "Version: " << VERSION << "\n";
    cerr << "Summary: Apply a function to a column from B intervals that overlap A." << endl << endl;

    cerr << "Usage:   " << PROGRAM_NAME << " [OPTIONS] -a <bed/gff/vcf> -b <bed/gff/vcf>" << endl << endl;

    cerr << "Options: " << endl;

    cerr << "\t-c\t"             << "Specify the column from the B file to map onto intervaks in A." << endl;
    cerr                         << "\t\t - Default = 4." << endl << endl;

    cerr << "\t-o\t"             << "Specify the operation that should be applied to -c." << endl;
    cerr                         << "\t\t Valid operations:" << endl;
    cerr                         << "\t\t    sum, min, max," << endl;
    cerr                         << "\t\t    mean, median," << endl;
    cerr                         << "\t\t    collapse (i.e., print a comma separated list (duplicates allowed)), " << endl;
    cerr                         << "\t\t    distinct (i.e., print a comma separated list (NO duplicates allowed)), " << endl;
    cerr                         << "\t\t    count" << endl;
    cerr                         << "\t\t    count_distinct (i.e., a count of the unique values in the column), " << endl;
    cerr                         << "\t\t- Default: sum" << endl << endl;

    cerr << "\t-f\t"             << "Minimum overlap required as a fraction of A." << endl;
    cerr                         << "\t\t- Default is 1E-9 (i.e., 1bp)." << endl;
    cerr                         << "\t\t- FLOAT (e.g. 0.50)" << endl << endl;

    cerr << "\t-r\t"             << "Require that the fraction overlap be reciprocal for A and B." << endl;
    cerr                         << "\t\t- In other words, if -f is 0.90 and -r is used, this requires" << endl;
    cerr                         << "\t\t  that B overlap 90% of A and A _also_ overlaps 90% of B." << endl << endl;

    cerr << "\t-s\t"             << "Require same strandedness.  That is, only report hits in B" << endl;
    cerr                         << "\t\tthat overlap A on the _same_ strand." << endl;
    cerr                         << "\t\t- By default, overlaps are reported without respect to strand." << endl << endl;

    cerr << "\t-S\t"             << "Require different strandedness.  That is, only report hits in B" << endl;
    cerr                         << "\t\tthat overlap A on the _opposite_ strand." << endl;
    cerr                         << "\t\t- By default, overlaps are reported without respect to strand." << endl << endl;

    cerr << "\t-null\t"          << "The value to print if no overlaps are found for an A interval." << endl;
    cerr                         << "\t\t- Default - \".\"" << endl << endl;

    cerr << "\t-header\t"        << "Print the header from the A file prior to results." << endl << endl;

    // end the program here
    exit(1);

}
<commit_msg>Fixed typo. Thanks @daler.<commit_after>/*****************************************************************************
  mapMain.cpp

  (c) 2009 - Aaron Quinlan
  Hall Laboratory
  Department of Biochemistry and Molecular Genetics
  University of Virginia
  aaronquinlan@gmail.com

  Licenced under the GNU General Public License 2.0 license.
******************************************************************************/
#include "mapBed.h"
#include "version.h"

using namespace std;

// define our program name
#define PROGRAM_NAME "bedtools map"

// define our parameter checking macro
#define PARAMETER_CHECK(param, paramLen, actualLen) (strncmp(argv[i], param, min(actualLen, paramLen))== 0) && (actualLen == paramLen)

// function declarations
void map_help(void);

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

    // our configuration variables
    bool showHelp = false;

    // input files
    string bedAFile;
    string bedBFile;
    int column = 5;
    string operation = "sum";
    string nullValue = ".";

    // input arguments
    float overlapFraction = 1E-9;

    bool haveBedA           = false;
    bool haveBedB           = false;
    bool haveColumn         = false;
    bool haveOperation      = false;
    bool haveFraction       = false;
    bool reciprocalFraction = false;
    bool sameStrand         = false;
    bool diffStrand         = false;
    bool printHeader        = false;

    // check to see if we should print out some help
    if(argc <= 1) showHelp = true;

    for(int i = 1; i < argc; i++) {
        int parameterLength = (int)strlen(argv[i]);

        if((PARAMETER_CHECK("-h", 2, parameterLength)) ||
        (PARAMETER_CHECK("--help", 5, parameterLength))) {
            showHelp = true;
        }
    }

    if(showHelp) map_help();

    // do some parsing (all of these parameters require 2 strings)
    for(int i = 1; i < argc; i++) {

        int parameterLength = (int)strlen(argv[i]);

        if(PARAMETER_CHECK("-a", 2, parameterLength)) {
            if ((i+1) < argc) {
                haveBedA = true;
                bedAFile = argv[i + 1];
                i++;
            }
        }
        else if(PARAMETER_CHECK("-b", 2, parameterLength)) {
            if ((i+1) < argc) {
                haveBedB = true;
                bedBFile = argv[i + 1];
                i++;
            }
        }
        else if(PARAMETER_CHECK("-c", 2, parameterLength)) {
            if ((i+1) < argc) {
                haveColumn = true;
                column = atoi(argv[i + 1]);
                i++;
            }
        }
        else if(PARAMETER_CHECK("-o", 2, parameterLength)) {
            if ((i+1) < argc) {
                haveOperation = true;
                operation = argv[i + 1];
                i++;
            }
        }
        else if(PARAMETER_CHECK("-f", 2, parameterLength)) {
            if ((i+1) < argc) {
                haveFraction = true;
                overlapFraction = atof(argv[i + 1]);
                i++;
            }
        }
        else if(PARAMETER_CHECK("-r", 2, parameterLength)) {
            reciprocalFraction = true;
        }
        else if (PARAMETER_CHECK("-s", 2, parameterLength)) {
            sameStrand = true;
        }
        else if (PARAMETER_CHECK("-S", 2, parameterLength)) {
            diffStrand = true;
        }
        else if (PARAMETER_CHECK("-null", 5, parameterLength)) {
            nullValue = argv[i + 1];
            i++;
        }
        else if(PARAMETER_CHECK("-header", 7, parameterLength)) {
            printHeader = true;
        }
        else {
            cerr << endl << "*****ERROR: Unrecognized parameter: " << argv[i] << " *****" << endl << endl;
            showHelp = true;
        }
    }

    // make sure we have both input files
    if (!haveBedA || !haveBedB) {
        cerr << endl << "*****" << endl << "*****ERROR: Need -a and -b files. " << endl << "*****" << endl;
        showHelp = true;
    }

    if (reciprocalFraction && !haveFraction) {
        cerr << endl << "*****" << endl << "*****ERROR: If using -r, you need to define -f." << endl << "*****" << endl;
        showHelp = true;
    }

    if (sameStrand && diffStrand) {
        cerr << endl << "*****" << endl << "*****ERROR: Request either -s OR -S, not both." << endl << "*****" << endl;
        showHelp = true;
    }

    if (!showHelp) {

        BedMap *bm = new BedMap(bedAFile, bedBFile, column, operation,
                                       overlapFraction, sameStrand,
                                       diffStrand, reciprocalFraction,
                                       nullValue, printHeader);
        delete bm;
        return 0;
    }
    else {
        map_help();
        return 0;
    }
}

void map_help(void) {

    cerr << "\nTool:    bedtools map (aka mapBed)" << endl;
    cerr << "Version: " << VERSION << "\n";
    cerr << "Summary: Apply a function to a column from B intervals that overlap A." << endl << endl;

    cerr << "Usage:   " << PROGRAM_NAME << " [OPTIONS] -a <bed/gff/vcf> -b <bed/gff/vcf>" << endl << endl;

    cerr << "Options: " << endl;

    cerr << "\t-c\t"             << "Specify the column from the B file to map onto intervals in A." << endl;
    cerr                         << "\t\t - Default = 4." << endl << endl;

    cerr << "\t-o\t"             << "Specify the operation that should be applied to -c." << endl;
    cerr                         << "\t\t Valid operations:" << endl;
    cerr                         << "\t\t    sum, min, max," << endl;
    cerr                         << "\t\t    mean, median," << endl;
    cerr                         << "\t\t    collapse (i.e., print a comma separated list (duplicates allowed)), " << endl;
    cerr                         << "\t\t    distinct (i.e., print a comma separated list (NO duplicates allowed)), " << endl;
    cerr                         << "\t\t    count" << endl;
    cerr                         << "\t\t    count_distinct (i.e., a count of the unique values in the column), " << endl;
    cerr                         << "\t\t- Default: sum" << endl << endl;

    cerr << "\t-f\t"             << "Minimum overlap required as a fraction of A." << endl;
    cerr                         << "\t\t- Default is 1E-9 (i.e., 1bp)." << endl;
    cerr                         << "\t\t- FLOAT (e.g. 0.50)" << endl << endl;

    cerr << "\t-r\t"             << "Require that the fraction overlap be reciprocal for A and B." << endl;
    cerr                         << "\t\t- In other words, if -f is 0.90 and -r is used, this requires" << endl;
    cerr                         << "\t\t  that B overlap 90% of A and A _also_ overlaps 90% of B." << endl << endl;

    cerr << "\t-s\t"             << "Require same strandedness.  That is, only report hits in B" << endl;
    cerr                         << "\t\tthat overlap A on the _same_ strand." << endl;
    cerr                         << "\t\t- By default, overlaps are reported without respect to strand." << endl << endl;

    cerr << "\t-S\t"             << "Require different strandedness.  That is, only report hits in B" << endl;
    cerr                         << "\t\tthat overlap A on the _opposite_ strand." << endl;
    cerr                         << "\t\t- By default, overlaps are reported without respect to strand." << endl << endl;

    cerr << "\t-null\t"          << "The value to print if no overlaps are found for an A interval." << endl;
    cerr                         << "\t\t- Default - \".\"" << endl << endl;

    cerr << "\t-header\t"        << "Print the header from the A file prior to results." << endl << endl;

    // end the program here
    exit(1);

}
<|endoftext|>


<commit_before>/*
Copyright 2013-present Barefoot Networks, Inc.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

#include <sstream>

#include <algorithm>
#include "source_file.h"
#include "exceptions.h"
#include "lib/log.h"

void IHasDbPrint::print() const { dbprint(std::cout); std::cout << std::endl; }

namespace Util {
SourcePosition::SourcePosition(unsigned lineNumber, unsigned columnNumber)
        : lineNumber(lineNumber),
          columnNumber(columnNumber) {
    if (lineNumber == 0)
        BUG("Line numbering should start at one");
}

cstring SourcePosition::toString() const {
    return Util::printf_format("%d:%d", lineNumber, columnNumber);
}

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

SourceInfo::SourceInfo(const InputSources* sources, SourcePosition start,
                       SourcePosition end)
        : sources(sources), start(start), end(end) {
    BUG_CHECK(sources != nullptr, "Invalid InputSources in SourceInfo");
    if (!start.isValid() || !end.isValid())
        BUG("Invalid source position in SourceInfo %1%-%2%",
                          start.toString(), end.toString());
    if (start > end)
        BUG("SourceInfo position start %1% after end %2%",
                          start.toString(), end.toString());
}

cstring SourceInfo::toDebugString() const {
    return Util::printf_format("(%s)-(%s)", start.toString(), end.toString());
}

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

InputSources::InputSources() : sealed(false) {
    mapLine(nullptr, 1);  // the first line read will be line 1 of stdin
    contents.push_back("");
}

void InputSources::addComment(SourceInfo srcInfo, bool singleLine, cstring body) {
    if (!singleLine)
        // Drop the "*/"
        body = body.exceptLast(2);
    auto comment = new Comment(srcInfo, singleLine, body);
    comments.push_back(comment);
}

/// prevent further changes
void InputSources::seal() {
    LOG4(toDebugString());
    if (sealed)
        BUG("InputSources already sealed");
    sealed = true;
}

unsigned InputSources::lineCount() const {
    int size = contents.size();
    if (contents.back().empty()) {
        // do not count the last line if it is empty.
        size -= 1;
        if (size < 0)
            BUG("Negative line count");
    }
    return size;
}

// Append this text to the last line
void InputSources::appendToLastLine(StringRef text) {
    if (sealed)
        BUG("Appending to sealed InputSources");
    // Text should not contain any newline characters
    for (size_t i = 0; i < text.len; i++) {
        char c = text[i];
        if (c == '\n')
            BUG("Text contains newlines");
    }
    contents.back() += text.toString();
}

// Append a newline and start a new line
void InputSources::appendNewline(StringRef newline) {
    if (sealed)
        BUG("Appending to sealed InputSources");
    contents.back() += newline.toString();
    contents.push_back("");  // start a new line
}

void InputSources::appendText(const char* text) {
    if (text == nullptr)
        BUG("Null text being appended");
    StringRef ref = text;

    while (ref.len > 0) {
        const char* nl = ref.find("\r\n");
        if (nl == nullptr) {
            appendToLastLine(ref);
            break;
        }

        size_t toCut = nl - ref.p;
        if (toCut != 0) {
            StringRef nonnl(ref.p, toCut);
            appendToLastLine(nonnl);
            ref += toCut;
        } else {
            if (ref[0] == '\n') {
                appendNewline("\n");
                ref += 1;
            } else if (ref.len > 2 && ref[0] == '\r' && ref[1] == '\n') {
                appendNewline("\r\n");
                ref += 2;
            } else {
                // Just \r
                appendToLastLine(ref.substr(0, 1));
                ref += 1;
            }
        }
    }
}

cstring InputSources::getLine(unsigned lineNumber) const {
    if (lineNumber == 0) {
        return "";
        // BUG("Lines are numbered starting at 1");
        // don't throw: this code may be called by exceptions
        // reporting on elements that have no source position
    }
    return contents.at(lineNumber - 1);
}

void InputSources::mapLine(cstring file, unsigned originalSourceLineNo) {
    if (sealed)
        BUG("Changing mapping to sealed InputSources");
    unsigned lineno = getCurrentLineNumber();
    line_file_map.emplace(lineno, SourceFileLine(file, originalSourceLineNo));
}

SourceFileLine InputSources::getSourceLine(unsigned line) const {
    auto it = line_file_map.upper_bound(line+1);
    if (it == line_file_map.begin())
        // There must be always something mapped to line 0
        BUG("No source information for line %1%", line);
    LOG3(line << " mapped to " << it->first << "," << it->second.toString());
    --it;
    LOG3(line << " corrected to " << it->first << "," << it->second.toString());
    // For a source file such as
    // ----------
    // # 1 "x.p4"
    // parser start { }
    // ----------
    // The first line indicates that line 2 is the first line in x.p4
    // line=2, it->first=1, it->second.sourceLine=1
    // So we have to subtract one to get the real line number.
    const auto nominalLine = line - it->first + it->second.sourceLine;
    const auto realLine = nominalLine > 0 ? nominalLine - 1 : 0;
    return SourceFileLine(it->second.fileName, realLine);
}

unsigned InputSources::getCurrentLineNumber() const {
    return contents.size();
}

SourcePosition InputSources::getCurrentPosition() const {
    unsigned line = getCurrentLineNumber();
    unsigned column = contents.back().size();
    return SourcePosition(line, column);
}

cstring InputSources::getSourceFragment(const SourcePosition &position) const {
    SourceInfo info(this, position, position);
    return getSourceFragment(info);
}

cstring carets(cstring source, unsigned start, unsigned end) {
    std::stringstream builder;
    if (start > source.size())
        start = source.size();

    unsigned i;
    for (i=0; i < start; i++) {
        char c = source.c_str()[i];
        if (c == ' ' || c == '\t')
            builder.put(c);
        else
            builder.put(' ');
    }

    for (; i < std::max(end, start+1); i++)
        builder.put('^');

    return builder.str();
}

cstring InputSources::getSourceFragment(const SourceInfo &position) const {
    if (!position.isValid())
        return "";

    // If the position spans multiple lines, truncate to just the first line
    if (position.getEnd().getLineNumber() > position.getStart().getLineNumber())
        return getSourceFragment(position.getStart());

    cstring result = getLine(position.getStart().getLineNumber());
    // Normally result has a newline, but if not
    // then we have to add a newline
    cstring toadd = "";
    if (result.find('\n') == nullptr)
        toadd = cstring::newline;
    cstring marker = carets(result, position.getStart().getColumnNumber(),
                            position.getEnd().getColumnNumber());
    return result + toadd + marker + cstring::newline;
}

cstring InputSources::getBriefSourceFragment(const SourceInfo &position) const {
    if (!position.isValid())
        return "";

    cstring result = getLine(position.getStart().getLineNumber());
    unsigned int start = position.getStart().getColumnNumber();
    unsigned int end;
    cstring toadd = "";

    // If the position spans multiple lines, truncate to just the first line
    if (position.getEnd().getLineNumber() > position.getStart().getLineNumber()) {
        // go to the end of the first line
        end = result.size();
        if (result.find('\n') != nullptr) {
            --end;
        }
        toadd = " ...";
    } else {
        end = position.getEnd().getColumnNumber();
    }

    // Adding escape character in front of '"' character to properly store
    // quote marks as part of JSON properties, they must be escaped.
    if (result.find('"') != nullptr) {
        cstring out = result.replace("\"", "\\\"");
        return out.substr(0, out.size()-1);
    }

    return result.substr(start, end - start) + toadd;
}

cstring InputSources::toDebugString() const {
    std::stringstream builder;
    for (auto line : contents)
        builder << line;
    builder << "---------------" << std::endl;
    for (auto lf : line_file_map)
        builder << lf.first << ": " << lf.second.toString() << std::endl;
    return cstring(builder.str());
}

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

cstring SourceInfo::toSourceFragment() const {
    if (!isValid())
        return "";
    return sources->getSourceFragment(*this);
}

cstring SourceInfo::toBriefSourceFragment() const {
    if (!isValid())
        return "";
    return sources->getBriefSourceFragment(*this);
}

cstring SourceInfo::toPositionString() const {
    if (!isValid())
        return "";
    SourceFileLine position = sources->getSourceLine(start.getLineNumber());
    return position.toString();
}

cstring SourceInfo::toSourcePositionData(unsigned *outLineNumber,
                                         unsigned *outColumnNumber) const {
    SourceFileLine position = sources->getSourceLine(start.getLineNumber());
    if (outLineNumber != nullptr) {
        *outLineNumber = position.sourceLine;
    }
    if (outColumnNumber != nullptr) {
        *outColumnNumber = start.getColumnNumber();
    }
    return position.fileName.c_str();
}

SourceFileLine SourceInfo::toPosition() const {
    return sources->getSourceLine(start.getLineNumber());
}

cstring SourceInfo::getSourceFile() const {
    auto sourceLine = sources->getSourceLine(start.getLineNumber());
    return sourceLine.fileName;
}

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

cstring SourceFileLine::toString() const {
    return Util::printf_format("%s(%d)", fileName.c_str(), sourceLine);
}

}  // namespace Util
<commit_msg>Fix off-by-one bug in source file position calculation (#3124)<commit_after>/*
Copyright 2013-present Barefoot Networks, Inc.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

#include <sstream>

#include <algorithm>
#include "source_file.h"
#include "exceptions.h"
#include "lib/log.h"

void IHasDbPrint::print() const { dbprint(std::cout); std::cout << std::endl; }

namespace Util {
SourcePosition::SourcePosition(unsigned lineNumber, unsigned columnNumber)
        : lineNumber(lineNumber),
          columnNumber(columnNumber) {
    if (lineNumber == 0)
        BUG("Line numbering should start at one");
}

cstring SourcePosition::toString() const {
    return Util::printf_format("%d:%d", lineNumber, columnNumber);
}

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

SourceInfo::SourceInfo(const InputSources* sources, SourcePosition start,
                       SourcePosition end)
        : sources(sources), start(start), end(end) {
    BUG_CHECK(sources != nullptr, "Invalid InputSources in SourceInfo");
    if (!start.isValid() || !end.isValid())
        BUG("Invalid source position in SourceInfo %1%-%2%",
                          start.toString(), end.toString());
    if (start > end)
        BUG("SourceInfo position start %1% after end %2%",
                          start.toString(), end.toString());
}

cstring SourceInfo::toDebugString() const {
    return Util::printf_format("(%s)-(%s)", start.toString(), end.toString());
}

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

InputSources::InputSources() : sealed(false) {
    mapLine(nullptr, 1);  // the first line read will be line 1 of stdin
    contents.push_back("");
}

void InputSources::addComment(SourceInfo srcInfo, bool singleLine, cstring body) {
    if (!singleLine)
        // Drop the "*/"
        body = body.exceptLast(2);
    auto comment = new Comment(srcInfo, singleLine, body);
    comments.push_back(comment);
}

/// prevent further changes
void InputSources::seal() {
    LOG4(toDebugString());
    if (sealed)
        BUG("InputSources already sealed");
    sealed = true;
}

unsigned InputSources::lineCount() const {
    int size = contents.size();
    if (contents.back().empty()) {
        // do not count the last line if it is empty.
        size -= 1;
        if (size < 0)
            BUG("Negative line count");
    }
    return size;
}

// Append this text to the last line
void InputSources::appendToLastLine(StringRef text) {
    if (sealed)
        BUG("Appending to sealed InputSources");
    // Text should not contain any newline characters
    for (size_t i = 0; i < text.len; i++) {
        char c = text[i];
        if (c == '\n')
            BUG("Text contains newlines");
    }
    contents.back() += text.toString();
}

// Append a newline and start a new line
void InputSources::appendNewline(StringRef newline) {
    if (sealed)
        BUG("Appending to sealed InputSources");
    contents.back() += newline.toString();
    contents.push_back("");  // start a new line
}

void InputSources::appendText(const char* text) {
    if (text == nullptr)
        BUG("Null text being appended");
    StringRef ref = text;

    while (ref.len > 0) {
        const char* nl = ref.find("\r\n");
        if (nl == nullptr) {
            appendToLastLine(ref);
            break;
        }

        size_t toCut = nl - ref.p;
        if (toCut != 0) {
            StringRef nonnl(ref.p, toCut);
            appendToLastLine(nonnl);
            ref += toCut;
        } else {
            if (ref[0] == '\n') {
                appendNewline("\n");
                ref += 1;
            } else if (ref.len > 2 && ref[0] == '\r' && ref[1] == '\n') {
                appendNewline("\r\n");
                ref += 2;
            } else {
                // Just \r
                appendToLastLine(ref.substr(0, 1));
                ref += 1;
            }
        }
    }
}

cstring InputSources::getLine(unsigned lineNumber) const {
    if (lineNumber == 0) {
        return "";
        // BUG("Lines are numbered starting at 1");
        // don't throw: this code may be called by exceptions
        // reporting on elements that have no source position
    }
    return contents.at(lineNumber - 1);
}

void InputSources::mapLine(cstring file, unsigned originalSourceLineNo) {
    if (sealed)
        BUG("Changing mapping to sealed InputSources");
    unsigned lineno = getCurrentLineNumber();
    line_file_map.emplace(lineno, SourceFileLine(file, originalSourceLineNo));
}

SourceFileLine InputSources::getSourceLine(unsigned line) const {
    auto it = line_file_map.upper_bound(line);
    if (it == line_file_map.begin())
        // There must be always something mapped to line 0
        BUG("No source information for line %1%", line);
    LOG3(line << " mapped to " << it->first << "," << it->second.toString());
    --it;
    LOG3(line << " corrected to " << it->first << "," << it->second.toString());
    // For a source file such as
    // ----------
    // # 1 "x.p4"
    // parser start { }
    // ----------
    // The first line indicates that line 2 is the first line in x.p4
    // line=2, it->first=1, it->second.sourceLine=1
    // So we have to subtract one to get the real line number.
    const auto nominalLine = line - it->first + it->second.sourceLine;
    const auto realLine = nominalLine > 0 ? nominalLine - 1 : 0;
    return SourceFileLine(it->second.fileName, realLine);
}

unsigned InputSources::getCurrentLineNumber() const {
    return contents.size();
}

SourcePosition InputSources::getCurrentPosition() const {
    unsigned line = getCurrentLineNumber();
    unsigned column = contents.back().size();
    return SourcePosition(line, column);
}

cstring InputSources::getSourceFragment(const SourcePosition &position) const {
    SourceInfo info(this, position, position);
    return getSourceFragment(info);
}

cstring carets(cstring source, unsigned start, unsigned end) {
    std::stringstream builder;
    if (start > source.size())
        start = source.size();

    unsigned i;
    for (i=0; i < start; i++) {
        char c = source.c_str()[i];
        if (c == ' ' || c == '\t')
            builder.put(c);
        else
            builder.put(' ');
    }

    for (; i < std::max(end, start+1); i++)
        builder.put('^');

    return builder.str();
}

cstring InputSources::getSourceFragment(const SourceInfo &position) const {
    if (!position.isValid())
        return "";

    // If the position spans multiple lines, truncate to just the first line
    if (position.getEnd().getLineNumber() > position.getStart().getLineNumber())
        return getSourceFragment(position.getStart());

    cstring result = getLine(position.getStart().getLineNumber());
    // Normally result has a newline, but if not
    // then we have to add a newline
    cstring toadd = "";
    if (result.find('\n') == nullptr)
        toadd = cstring::newline;
    cstring marker = carets(result, position.getStart().getColumnNumber(),
                            position.getEnd().getColumnNumber());
    return result + toadd + marker + cstring::newline;
}

cstring InputSources::getBriefSourceFragment(const SourceInfo &position) const {
    if (!position.isValid())
        return "";

    cstring result = getLine(position.getStart().getLineNumber());
    unsigned int start = position.getStart().getColumnNumber();
    unsigned int end;
    cstring toadd = "";

    // If the position spans multiple lines, truncate to just the first line
    if (position.getEnd().getLineNumber() > position.getStart().getLineNumber()) {
        // go to the end of the first line
        end = result.size();
        if (result.find('\n') != nullptr) {
            --end;
        }
        toadd = " ...";
    } else {
        end = position.getEnd().getColumnNumber();
    }

    // Adding escape character in front of '"' character to properly store
    // quote marks as part of JSON properties, they must be escaped.
    if (result.find('"') != nullptr) {
        cstring out = result.replace("\"", "\\\"");
        return out.substr(0, out.size()-1);
    }

    return result.substr(start, end - start) + toadd;
}

cstring InputSources::toDebugString() const {
    std::stringstream builder;
    for (auto line : contents)
        builder << line;
    builder << "---------------" << std::endl;
    for (auto lf : line_file_map)
        builder << lf.first << ": " << lf.second.toString() << std::endl;
    return cstring(builder.str());
}

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

cstring SourceInfo::toSourceFragment() const {
    if (!isValid())
        return "";
    return sources->getSourceFragment(*this);
}

cstring SourceInfo::toBriefSourceFragment() const {
    if (!isValid())
        return "";
    return sources->getBriefSourceFragment(*this);
}

cstring SourceInfo::toPositionString() const {
    if (!isValid())
        return "";
    SourceFileLine position = sources->getSourceLine(start.getLineNumber());
    return position.toString();
}

cstring SourceInfo::toSourcePositionData(unsigned *outLineNumber,
                                         unsigned *outColumnNumber) const {
    SourceFileLine position = sources->getSourceLine(start.getLineNumber());
    if (outLineNumber != nullptr) {
        *outLineNumber = position.sourceLine;
    }
    if (outColumnNumber != nullptr) {
        *outColumnNumber = start.getColumnNumber();
    }
    return position.fileName.c_str();
}

SourceFileLine SourceInfo::toPosition() const {
    return sources->getSourceLine(start.getLineNumber());
}

cstring SourceInfo::getSourceFile() const {
    auto sourceLine = sources->getSourceLine(start.getLineNumber());
    return sourceLine.fileName;
}

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

cstring SourceFileLine::toString() const {
    return Util::printf_format("%s(%d)", fileName.c_str(), sourceLine);
}

}  // namespace Util
<|endoftext|>


<commit_before>#include "vtkExodusIIReader.h"
#include "vtkGmshReader.h"
#include "vtkXMLUnstructuredGridReader.h"
#include "vtkXMLPUnstructuredGridReader.h"
#include "vtkTriangleReader.h"
#include "vtkMultiBlockDataSet.h"
#include "vtkUnstructuredGrid.h"
#include "vtkXMLUnstructuredGridWriter.h"
#include "vtkXMLMultiBlockDataWriter.h"
#include "vtkGmshWriter.h"
#include "vtkAppendFilter.h"
#include "vtkCellData.h"
#include "vtkIntArray.h"
#include "vtkIdTypeArray.h"

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

#include "mesh_converter.h"

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

  std::string input_format="exodus";
  std::string output_format="gmsh";
  int opt;

  if (argc <3) {
    print_usage();
    return 0;
  }

  while (  (opt = getopt(argc, argv, "i::o::h")) != -1 ) {
    switch ( opt ) {
    case 'i':
      if (optarg) {
	input_format = optarg;
      }
      break;
    case 'o':
      if (optarg) {
	output_format = optarg;
      }
      break;
    case 'h':
      print_usage();
      break;
    case '?':
      cerr << "Unknown option: '" << char(optopt) << "'!" << endl;
      break;
    }
  }

  vtkMultiBlockDataSet* mbdata = NULL;
  vtkUnstructuredGrid* ugdata  = NULL;

  if (input_format.compare("exodus")==0 ) {
    mbdata = read_exodusII(argv[optind++]);
  }  else if (input_format.compare("gmsh")==0 ) {
    ugdata = read_gmsh(argv[optind++]);
  }  else if (input_format.compare("vtu")==0 ) {
    ugdata = read_vtu(argv[optind++]);
  }  else if (input_format.compare("pvtu")==0 ) {
    ugdata = read_pvtu(argv[optind++]);
  }  else if (input_format.compare("triangle")==0 ) {
    ugdata = read_triangle(argv[optind++]);
  }  else {
    std::cout<< "Unrecognised input format: "<< input_format << std::endl;
    return 1;
  }

  int flag;

  if (output_format.compare("gmsh")==0) {
    if (mbdata) {
      ugdata=multiblock_to_unstucturedgrid(mbdata);
    }
    flag=write_gmsh(ugdata,argv[optind]);
  } else if (output_format.compare("vtu")==0) {
    if (mbdata) {
      ugdata=multiblock_to_unstucturedgrid(mbdata);
    }
    flag=write_vtu(ugdata,argv[optind]);
  }  else if (output_format.compare("vtm")==0) {
    if (ugdata) {
      //      mbdata=unstucturedgrid_to_multiblock(ugdata);
    }
    flag=write_vtm(mbdata,argv[optind]);
  } else {
    std::cout<< "Unrecognised output format: "<<output_format<<std::endl;
    return 1;
  }

  if (mbdata){
    mbdata->Delete();
  }
  if (ugdata){
    ugdata->Delete();
  }

  return flag;
}

vtkUnstructuredGrid* multiblock_to_unstucturedgrid(vtkMultiBlockDataSet* data) {
  vtkAppendFilter* appender = vtkAppendFilter::New();
  appender->SetMergePoints(1);

  vtkMultiBlockDataSet* sidesets = vtkMultiBlockDataSet::SafeDownCast(data->GetBlock(4));
  for (int i=0; i<sidesets->GetNumberOfBlocks(); i++) {
    vtkUnstructuredGrid* ugrid = vtkUnstructuredGrid::SafeDownCast(sidesets->GetBlock(i));
    vtkIntArray* eids = vtkIntArray::New();
    eids->SetNumberOfValues(ugrid->GetNumberOfCells());
    ugrid->GetCellData()->GetArray("ObjectId")->SetName("PhysicalIds");
    for (int j=0; j<ugrid->GetNumberOfCells(); j++) {
      eids->SetValue(j,i+1);
    }
    eids->SetName("ElementaryEntities");
    ugrid->GetCellData()->AddArray(eids);
    appender->AddInputData(ugrid);
  }

  vtkMultiBlockDataSet* regions = vtkMultiBlockDataSet::SafeDownCast(data->GetBlock(0));
  for (int i=0; i<regions->GetNumberOfBlocks(); i++) {
    vtkUnstructuredGrid* ugrid = vtkUnstructuredGrid::SafeDownCast(regions->GetBlock(i));
    ugrid->GetCellData()->GetArray("ObjectId")->SetName("PhysicalIds");
    ugrid->GetCellData()->GetArray("GlobalElementId")->SetName("ElementaryEntities");
    appender->AddInputData(ugrid);
  }

  appender->Update();
  vtkUnstructuredGrid* output = vtkUnstructuredGrid::New();
  output->ShallowCopy(appender->GetOutput());
  appender->Delete();

  return output;
}

vtkMultiBlockDataSet* read_exodusII(char* fname){

  std::cout << "Reading from file: " <<fname<<std::endl;

  vtkExodusIIReader* r = vtkExodusIIReader::New();

  r->SetFileName(fname);
  r->UpdateInformation();
  r->GenerateGlobalNodeIdArrayOn();
  r->GenerateGlobalElementIdArrayOn();
  r->GenerateObjectIdCellArrayOn();
  for (int i=0; i<r->GetNumberOfSideSetArrays(); i++) {
    r->SetSideSetArrayStatus(r->GetSideSetArrayName(i),1);
  }
  r->Update();

  vtkMultiBlockDataSet* data;
  data = r->GetOutput();

  return data;
 }

 vtkUnstructuredGrid* read_gmsh(char* fname) {
   std::cout << "Reading from GMSH file: " <<fname<<std::endl;
   vtkGmshReader* reader= vtkGmshReader::New();
   reader->SetFileName(fname);
   reader->Update();
   vtkUnstructuredGrid* ugrid = vtkUnstructuredGrid::New();
   ugrid->ShallowCopy(reader->GetOutput());
   reader->Delete();
   return ugrid;
 }

 vtkUnstructuredGrid* read_vtu(char* fname) {
   std::cout << "Reading from VTK unstructured grid file: " <<fname<<std::endl;
   vtkXMLUnstructuredGridReader* reader= vtkXMLUnstructuredGridReader::New();
   reader->SetFileName(fname);
   reader->Update();
   vtkUnstructuredGrid* ugrid = vtkUnstructuredGrid::New();
   ugrid->ShallowCopy(reader->GetOutput());
   reader->Delete();
   return ugrid;
 }

vtkUnstructuredGrid* read_pvtu(char* fname) {
   std::cout << "Reading from VTK parallel unstructured grid file: " <<fname<<std::endl;
   vtkXMLPUnstructuredGridReader* reader= vtkXMLPUnstructuredGridReader::New();
   reader->SetFileName(fname);
   reader->Update();
   vtkUnstructuredGrid* ugrid = vtkUnstructuredGrid::New();
   ugrid->ShallowCopy(reader->GetOutput());
   reader->Delete();
   return ugrid;
 }

vtkUnstructuredGrid* read_triangle(char* fname) {
   std::cout << "Reading from VTK parallel unstructured grid file: " <<fname<<std::endl;
   vtkTriangleReader* reader= vtkTriangleReader::New();
   reader->SetFileName(fname);
   reader->Update();
   vtkUnstructuredGrid* ugrid = vtkUnstructuredGrid::New();
   ugrid->ShallowCopy(reader->GetOutput());
   reader->Delete();
   return ugrid;
 }

int print_usage(){
  std::cout << "usage: mesh_converter [-i input_format] [-o output_format] [-h] input_file output_file"<<std::endl;
  return 0;
}

int write_gmsh(vtkUnstructuredGrid* data, char* fname){

  std::cout << "Writing to file: " <<fname<<std::endl;

  vtkGmshWriter* writer = vtkGmshWriter::New();
  writer->SetFileName(fname);
  writer->SetInputData(data);
  writer->Write();
  writer->Delete();
  return 0;
}

int write_vtu(vtkUnstructuredGrid* data, char* fname){

  std::cout << "Writing to file: " <<fname<<std::endl;

  vtkXMLUnstructuredGridWriter* writer = vtkXMLUnstructuredGridWriter::New();
  writer->SetFileName(fname);
  writer->SetInputData(data);
  writer->Write();
  writer->Delete();
  return 0;
}

int write_vtm(vtkMultiBlockDataSet* data, char* fname){

  std::cout << "Writing to file: " <<fname<<std::endl;

  vtkXMLMultiBlockDataWriter* writer = vtkXMLMultiBlockDataWriter::New();
  writer->SetFileName(fname);
  writer->SetInputData(data);
  writer->Write();
  writer->Delete();
  return 0;
}

<commit_msg>Add version information.<commit_after>#include "vtkExodusIIReader.h"
#include "vtkGmshReader.h"
#include "vtkXMLUnstructuredGridReader.h"
#include "vtkXMLPUnstructuredGridReader.h"
#include "vtkTriangleReader.h"
#include "vtkMultiBlockDataSet.h"
#include "vtkUnstructuredGrid.h"
#include "vtkXMLUnstructuredGridWriter.h"
#include "vtkXMLMultiBlockDataWriter.h"
#include "vtkGmshWriter.h"
#include "vtkAppendFilter.h"
#include "vtkCellData.h"
#include "vtkIntArray.h"
#include "vtkIdTypeArray.h"

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

#include "mesh_converter.h"

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

  std::string input_format="exodus";
  std::string output_format="gmsh";
  int opt;

  while (  (opt = getopt(argc, argv, "i::o::hV")) != -1 ) {
    switch ( opt ) {
    case 'i':
      if (optarg) {
	input_format = optarg;
      }
      break;
    case 'o':
      if (optarg) {
	output_format = optarg;
      }
      break;
    case 'h':
      print_usage();
      return EXIT_SUCCESS;
      break;
    case 'V':
      print_version();
      return EXIT_SUCCESS;
      break;
    case '?':
      cerr << "Unknown option: '" << char(optopt) << "'!" << endl;
      break;
    }
  }

  if (argc <3) {
    print_usage();
    return 1;
  }

  vtkMultiBlockDataSet* mbdata = NULL;
  vtkUnstructuredGrid* ugdata  = NULL;

  if (input_format.compare("exodus")==0 ) {
    mbdata = read_exodusII(argv[optind++]);
  }  else if (input_format.compare("gmsh")==0 ) {
    ugdata = read_gmsh(argv[optind++]);
  }  else if (input_format.compare("vtu")==0 ) {
    ugdata = read_vtu(argv[optind++]);
  }  else if (input_format.compare("pvtu")==0 ) {
    ugdata = read_pvtu(argv[optind++]);
  }  else if (input_format.compare("triangle")==0 ) {
    ugdata = read_triangle(argv[optind++]);
  }  else {
    std::cout<< "Unrecognised input format: "<< input_format << std::endl;
    return 1;
  }

  int flag;

  if (output_format.compare("gmsh")==0) {
    if (mbdata) {
      ugdata=multiblock_to_unstucturedgrid(mbdata);
    }
    flag=write_gmsh(ugdata,argv[optind]);
  } else if (output_format.compare("vtu")==0) {
    if (mbdata) {
      ugdata=multiblock_to_unstucturedgrid(mbdata);
    }
    flag=write_vtu(ugdata,argv[optind]);
  }  else if (output_format.compare("vtm")==0) {
    if (ugdata) {
      //      mbdata=unstucturedgrid_to_multiblock(ugdata);
    }
    flag=write_vtm(mbdata,argv[optind]);
  } else {
    std::cout<< "Unrecognised output format: "<<output_format<<std::endl;
    return 1;
  }

  if (mbdata){
    mbdata->Delete();
  }
  if (ugdata){
    ugdata->Delete();
  }

  return flag;
}

vtkUnstructuredGrid* multiblock_to_unstucturedgrid(vtkMultiBlockDataSet* data) {
  vtkAppendFilter* appender = vtkAppendFilter::New();
  appender->SetMergePoints(1);

  vtkMultiBlockDataSet* sidesets = vtkMultiBlockDataSet::SafeDownCast(data->GetBlock(4));
  for (int i=0; i<sidesets->GetNumberOfBlocks(); i++) {
    vtkUnstructuredGrid* ugrid = vtkUnstructuredGrid::SafeDownCast(sidesets->GetBlock(i));
    vtkIntArray* eids = vtkIntArray::New();
    eids->SetNumberOfValues(ugrid->GetNumberOfCells());
    ugrid->GetCellData()->GetArray("ObjectId")->SetName("PhysicalIds");
    for (int j=0; j<ugrid->GetNumberOfCells(); j++) {
      eids->SetValue(j,i+1);
    }
    eids->SetName("ElementaryEntities");
    ugrid->GetCellData()->AddArray(eids);
    appender->AddInputData(ugrid);
  }

  vtkMultiBlockDataSet* regions = vtkMultiBlockDataSet::SafeDownCast(data->GetBlock(0));
  for (int i=0; i<regions->GetNumberOfBlocks(); i++) {
    vtkUnstructuredGrid* ugrid = vtkUnstructuredGrid::SafeDownCast(regions->GetBlock(i));
    ugrid->GetCellData()->GetArray("ObjectId")->SetName("PhysicalIds");
    ugrid->GetCellData()->GetArray("GlobalElementId")->SetName("ElementaryEntities");
    appender->AddInputData(ugrid);
  }

  appender->Update();
  vtkUnstructuredGrid* output = vtkUnstructuredGrid::New();
  output->ShallowCopy(appender->GetOutput());
  appender->Delete();

  return output;
}

vtkMultiBlockDataSet* read_exodusII(char* fname){

  std::cout << "Reading from file: " <<fname<<std::endl;

  vtkExodusIIReader* r = vtkExodusIIReader::New();

  r->SetFileName(fname);
  r->UpdateInformation();
  r->GenerateGlobalNodeIdArrayOn();
  r->GenerateGlobalElementIdArrayOn();
  r->GenerateObjectIdCellArrayOn();
  for (int i=0; i<r->GetNumberOfSideSetArrays(); i++) {
    r->SetSideSetArrayStatus(r->GetSideSetArrayName(i),1);
  }
  r->Update();

  vtkMultiBlockDataSet* data;
  data = r->GetOutput();

  return data;
 }

 vtkUnstructuredGrid* read_gmsh(char* fname) {
   std::cout << "Reading from GMSH file: " <<fname<<std::endl;
   vtkGmshReader* reader= vtkGmshReader::New();
   reader->SetFileName(fname);
   reader->Update();
   vtkUnstructuredGrid* ugrid = vtkUnstructuredGrid::New();
   ugrid->ShallowCopy(reader->GetOutput());
   reader->Delete();
   return ugrid;
 }

 vtkUnstructuredGrid* read_vtu(char* fname) {
   std::cout << "Reading from VTK unstructured grid file: " <<fname<<std::endl;
   vtkXMLUnstructuredGridReader* reader= vtkXMLUnstructuredGridReader::New();
   reader->SetFileName(fname);
   reader->Update();
   vtkUnstructuredGrid* ugrid = vtkUnstructuredGrid::New();
   ugrid->ShallowCopy(reader->GetOutput());
   reader->Delete();
   return ugrid;
 }

vtkUnstructuredGrid* read_pvtu(char* fname) {
   std::cout << "Reading from VTK parallel unstructured grid file: " <<fname<<std::endl;
   vtkXMLPUnstructuredGridReader* reader= vtkXMLPUnstructuredGridReader::New();
   reader->SetFileName(fname);
   reader->Update();
   vtkUnstructuredGrid* ugrid = vtkUnstructuredGrid::New();
   ugrid->ShallowCopy(reader->GetOutput());
   reader->Delete();
   return ugrid;
 }

vtkUnstructuredGrid* read_triangle(char* fname) {
   std::cout << "Reading from VTK parallel unstructured grid file: " <<fname<<std::endl;
   vtkTriangleReader* reader= vtkTriangleReader::New();
   reader->SetFileName(fname);
   reader->Update();
   vtkUnstructuredGrid* ugrid = vtkUnstructuredGrid::New();
   ugrid->ShallowCopy(reader->GetOutput());
   reader->Delete();
   return ugrid;
 }

int print_usage(){
  std::cout << "usage: mesh_converter [-i input_format] [-o output_format] [-hV] input_file output_file"<<std::endl;
  return 0;
}

int print_version(){
  std::cout << "mesh_converter "
            << CONVERTER_MAJOR_VERSION<<"."<<CONVERTER_MINOR_VERSION
            <<std::endl;
  return 0;
}

int write_gmsh(vtkUnstructuredGrid* data, char* fname){

  std::cout << "Writing to file: " <<fname<<std::endl;

  vtkGmshWriter* writer = vtkGmshWriter::New();
  writer->SetFileName(fname);
  writer->SetInputData(data);
  writer->Write();
  writer->Delete();
  return 0;
}

int write_vtu(vtkUnstructuredGrid* data, char* fname){

  std::cout << "Writing to file: " <<fname<<std::endl;

  vtkXMLUnstructuredGridWriter* writer = vtkXMLUnstructuredGridWriter::New();
  writer->SetFileName(fname);
  writer->SetInputData(data);
  writer->Write();
  writer->Delete();
  return 0;
}

int write_vtm(vtkMultiBlockDataSet* data, char* fname){

  std::cout << "Writing to file: " <<fname<<std::endl;

  vtkXMLMultiBlockDataWriter* writer = vtkXMLMultiBlockDataWriter::New();
  writer->SetFileName(fname);
  writer->SetInputData(data);
  writer->Write();
  writer->Delete();
  return 0;
}

<|endoftext|>


<commit_before>/* * This file is part of meego-im-framework *
 *
 * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
 * All rights reserved.
 * Contact: Nokia Corporation (directui@nokia.com)
 *
 * If you have questions regarding the use of this file, please contact
 * Nokia at directui@nokia.com.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License version 2.1 as published by the Free Software Foundation
 * and appearing in the file LICENSE.LGPL included in the packaging
 * of this file.
 */

#include "mimapplication.h"

#include <MWindow>
#include <MDebug>

#include "x11wrapper.h"

X11Wrapper::X11Wrapper()
    : remoteWindowId(0),
      remoteWindowXPixmap(0),
      remoteWindowPixmap(),
      pixmapDamage(0)
{
}

MIMApplication::MIMApplication(int &argc, char **argv, bool useSelfComposite)
    : MApplication(argc, argv),
      passThruWindow(0),
      x11Wrapper(new X11Wrapper),
      selfComposited(false)
{
    if (useSelfComposite)
        selfComposited = initializeComposite();
}

MIMApplication::~MIMApplication()
{
    delete x11Wrapper;
}

bool MIMApplication::initializeComposite()
{
    int compositeBase, compositeError;
    if (!XCompositeQueryExtension(QX11Info::display(), &compositeBase, &compositeError))
        return false;

    if (!XQueryExtension(QX11Info::display(), COMPOSITE_NAME, &compositeMajor, &compositeBase, &compositeError))
        return false;

    int major = 0, minor = 2; // XComposite 0.2 required for XCompositeNameWindowPixmap
    if (!XCompositeQueryVersion(QX11Info::display(), &major, &minor))
        return false;

    if (major < 0 || (major == 0 && minor < 2))
        return false;

    int damageError;
    if (!XDamageQueryExtension(QX11Info::display(), &damageBase, &damageError))
        return false;

    return true;
}

bool MIMApplication::x11EventFilter(XEvent *ev)
{
    handleMapNotifyEvents(ev);
    handleTransientEvents(ev);
    handleDamageEvents(ev);
    return MApplication::x11EventFilter(ev);
}

void MIMApplication::handleMapNotifyEvents(XEvent *ev)
{
    if (wasPassThruWindowMapped(ev)) {
        mDebug("MIMApplication") << "PassThru window was mapped.";
        emit passThruWindowMapped();
    } else if (wasPassThruWindowUnmapped(ev)) {
        mDebug("MIMApplication") << "PassThru window was unmapped.";
        emit passThruWindowUnmapped();
    }
}

void MIMApplication::handleTransientEvents(XEvent *ev)
{
    if (0 == x11Wrapper->remoteWindowId || not passThruWindow) {
        return;
    }

    if (wasRemoteWindowIconified(ev) || wasRemoteWindowUnmapped(ev)) {
        mDebug("MIMApplication") << "Remote window was destroyed or iconified - hiding.";
        destroyDamage();
        x11Wrapper->remoteWindowId = 0;
        emit remoteWindowGone();
    }
}

void MIMApplication::setTransientHint(int newRemoteWinId)
{
    if (0 == newRemoteWinId || not activeWindow()) {
        return;
    }

    x11Wrapper->remoteWindowId = newRemoteWinId;

    XSetTransientForHint(QX11Info::display(),
                         passThruWindow->effectiveWinId(),
                         x11Wrapper->remoteWindowId);

    // Using PropertyChangeMask is a work-around for NB#172722 (a WONTFIX):
    XSelectInput(QX11Info::display(),
                 x11Wrapper->remoteWindowId,
                 StructureNotifyMask | PropertyChangeMask);
}

void MIMApplication::setPassThruWindow(QWidget *newPassThruWindow)
{
    if (newPassThruWindow != passThruWindow) {
        passThruWindow = newPassThruWindow;
    }
}

MIMApplication *MIMApplication::instance()
{
    return static_cast<MIMApplication *>(QCoreApplication::instance());
}

bool MIMApplication::wasRemoteWindowIconified(XEvent *ev) const
{
    if (PropertyNotify != ev->type) {
        return false;
    }

    static const Atom wmState = XInternAtom(QX11Info::display(), "WM_STATE", false);

    if (ev->xproperty.atom == wmState) {
        Atom type;
        int format;
        unsigned long length;
        unsigned long after;
        unsigned long *state;
        uchar *data = 0;

        int queryResult = XGetWindowProperty(QX11Info::display(), x11Wrapper->remoteWindowId, wmState, 0, 2,
                                             false, AnyPropertyType, &type, &format, &length,
                                             &after, &data);
        state = (unsigned long *) data;

        bool result = (queryResult == Success && data && format == 32 && *state == IconicState);

        if (data) {
            XFree(data);
        }

        return result;
    }

    return false;
}

bool MIMApplication::wasRemoteWindowUnmapped(XEvent *ev) const
{
    return (UnmapNotify == ev->type &&
            ev->xunmap.event == x11Wrapper->remoteWindowId);
}

bool MIMApplication::wasPassThruWindowMapped(XEvent *ev) const
{
    return (passThruWindow &&
            MapNotify == ev->type &&
            static_cast<WId>(ev->xmap.event) == passThruWindow->effectiveWinId());
}

bool MIMApplication::wasPassThruWindowUnmapped(XEvent *ev) const
{
    return (passThruWindow &&
            UnmapNotify == ev->type &&
            static_cast<WId>(ev->xunmap.event) == passThruWindow->effectiveWinId());
}

void MIMApplication::setupDamage()
{
    if (x11Wrapper->remoteWindowId == 0)
        return;

    if (x11Wrapper->pixmapDamage != 0)
        destroyDamage();

    x11Wrapper->pixmapDamage = XDamageCreate(QX11Info::display(), x11Wrapper->remoteWindowId, XDamageReportNonEmpty);
}

void MIMApplication::destroyDamage()
{
    if (x11Wrapper->pixmapDamage != 0) {
        XDamageDestroy(QX11Info::display(), x11Wrapper->pixmapDamage);
        x11Wrapper->pixmapDamage = 0;
    }
}

void MIMApplication::handleDamageEvents(XEvent *event)
{
    if (x11Wrapper->remoteWindowId == 0 ||
        x11Wrapper->pixmapDamage == 0)
        return;

    if (event->type == damageBase + XDamageNotify) {
        XDamageNotifyEvent *e = reinterpret_cast<XDamageNotifyEvent*>(event);

        if (x11Wrapper->pixmapDamage == e->damage) {
            XserverRegion parts = XFixesCreateRegion(QX11Info::display(), 0, 0);
            XDamageSubtract(QX11Info::display(), e->damage, None, parts);

            QRegion region;

            int nrects;
            XRectangle *rects = XFixesFetchRegion (QX11Info::display(), parts, &nrects);
            if (rects) {
                for (int i = 0; i < nrects; ++i) {
                    region += QRect(rects[i].x, rects[i].y, rects[i].width, rects[i].height);
                }
            }
            free(rects);

            XFixesDestroyRegion(QX11Info::display(), parts);

            // setup remote pixmap when it failed before
            if (x11Wrapper->remoteWindowPixmap.isNull())
                setupRemotePixmap();

            emit remoteWindowUpdated(region);
        }
    }
}

void MIMApplication::redirectRemoteWindow()
{
    if (x11Wrapper->remoteWindowId != 0) {
        xError()->check(compositeMajor, X_CompositeRedirectWindow);
        XCompositeRedirectWindow(QX11Info::display(),
                                 x11Wrapper->remoteWindowId,
                                 CompositeRedirectManual);
        XSync(QX11Info::display(), FALSE);
        if (xError()->result() == BadAccess)
            qDebug() << "Window " << x11Wrapper->remoteWindowId << " was already redirected";

        setupRemotePixmap();

        setupDamage();
        emit remoteWindowUpdated(QRegion());
    }
}

void MIMApplication::unredirectRemoteWindow()
{
    destroyRemotePixmap();
    if (x11Wrapper->remoteWindowId != 0) {
        xError()->check(compositeMajor, X_CompositeUnredirectWindow);
        XCompositeUnredirectWindow(QX11Info::display(),
                                   x11Wrapper->remoteWindowId,
                                   CompositeRedirectManual);
        XSync(QX11Info::display(), FALSE);
        if (xError()->result() == BadAccess)
            qDebug() << "Window " << x11Wrapper->remoteWindowId << " was not redirected";
        destroyDamage();
    }
}

QPixmap MIMApplication::remoteWindowPixmap() const
{
    return x11Wrapper->remoteWindowPixmap;
}

bool MIMApplication::supportsSelfComposite() const
{
    return selfComposited;
}

void MIMApplication::setupRemotePixmap()
{
    destroyRemotePixmap();

    xError()->check(compositeMajor, X_CompositeNameWindowPixmap);
    x11Wrapper->remoteWindowXPixmap = XCompositeNameWindowPixmap(QX11Info::display(), x11Wrapper->remoteWindowId);
    XSync(QX11Info::display(), FALSE);
    if (xError()->result() == BadMatch) {
        qDebug() << "Cannot get offscreen reference for Window " << x11Wrapper->remoteWindowId;
        return;
    }

    if (x11Wrapper->remoteWindowXPixmap != 0) {
        x11Wrapper->remoteWindowPixmap = QPixmap::fromX11Pixmap(x11Wrapper->remoteWindowXPixmap, QPixmap::ExplicitlyShared);
    }
}

void MIMApplication::destroyRemotePixmap()
{
    x11Wrapper->remoteWindowPixmap = QPixmap();

    if (x11Wrapper->remoteWindowXPixmap != 0) {
        XFreePixmap(QX11Info::display(), x11Wrapper->remoteWindowXPixmap);
        x11Wrapper->remoteWindowXPixmap = 0;
    }
}

MIMXError *MIMApplication::xError() const
{
    return x11Error;
}

MIMXError::MIMXError() :
    request_code(0),
    minor_code(0),
    error_code(0),
    oldHandler(0)
{}

int xErrorHandler(Display *display, XErrorEvent *e)
{
    MIMXError *xerror = MIMApplication::instance()->xError();

    if (xerror->matches(e)) {
        xerror->error_code = e->error_code;
        return 0;
    }

    return xerror->oldHandler(display, e);
}

void MIMXError::check(int major, int minor)
{
    request_code = major;
    minor_code = minor;
    error_code = Success;
    oldHandler = XSetErrorHandler(xErrorHandler);
}

bool MIMXError::matches(XErrorEvent *e)
{
    return e->request_code == request_code && e->minor_code == minor_code;
}

int MIMXError::result()
{
    XSetErrorHandler(oldHandler);
    return error_code;
}
<commit_msg>Fixes: initialize x11Error properly.<commit_after>/* * This file is part of meego-im-framework *
 *
 * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
 * All rights reserved.
 * Contact: Nokia Corporation (directui@nokia.com)
 *
 * If you have questions regarding the use of this file, please contact
 * Nokia at directui@nokia.com.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License version 2.1 as published by the Free Software Foundation
 * and appearing in the file LICENSE.LGPL included in the packaging
 * of this file.
 */

#include "mimapplication.h"

#include <MWindow>
#include <MDebug>

#include "x11wrapper.h"

X11Wrapper::X11Wrapper()
    : remoteWindowId(0),
      remoteWindowXPixmap(0),
      remoteWindowPixmap(),
      pixmapDamage(0)
{
}

MIMApplication::MIMApplication(int &argc, char **argv, bool useSelfComposite)
    : MApplication(argc, argv),
      passThruWindow(0),
      x11Wrapper(new X11Wrapper),
      x11Error(new MIMXError),
      selfComposited(false)
{
    if (useSelfComposite)
        selfComposited = initializeComposite();
}

MIMApplication::~MIMApplication()
{
    delete x11Wrapper;
    delete x11Error;
}

bool MIMApplication::initializeComposite()
{
    int compositeBase, compositeError;
    if (!XCompositeQueryExtension(QX11Info::display(), &compositeBase, &compositeError))
        return false;

    if (!XQueryExtension(QX11Info::display(), COMPOSITE_NAME, &compositeMajor, &compositeBase, &compositeError))
        return false;

    int major = 0, minor = 2; // XComposite 0.2 required for XCompositeNameWindowPixmap
    if (!XCompositeQueryVersion(QX11Info::display(), &major, &minor))
        return false;

    if (major < 0 || (major == 0 && minor < 2))
        return false;

    int damageError;
    if (!XDamageQueryExtension(QX11Info::display(), &damageBase, &damageError))
        return false;

    return true;
}

bool MIMApplication::x11EventFilter(XEvent *ev)
{
    handleMapNotifyEvents(ev);
    handleTransientEvents(ev);
    handleDamageEvents(ev);
    return MApplication::x11EventFilter(ev);
}

void MIMApplication::handleMapNotifyEvents(XEvent *ev)
{
    if (wasPassThruWindowMapped(ev)) {
        mDebug("MIMApplication") << "PassThru window was mapped.";
        emit passThruWindowMapped();
    } else if (wasPassThruWindowUnmapped(ev)) {
        mDebug("MIMApplication") << "PassThru window was unmapped.";
        emit passThruWindowUnmapped();
    }
}

void MIMApplication::handleTransientEvents(XEvent *ev)
{
    if (0 == x11Wrapper->remoteWindowId || not passThruWindow) {
        return;
    }

    if (wasRemoteWindowIconified(ev) || wasRemoteWindowUnmapped(ev)) {
        mDebug("MIMApplication") << "Remote window was destroyed or iconified - hiding.";
        destroyDamage();
        x11Wrapper->remoteWindowId = 0;
        emit remoteWindowGone();
    }
}

void MIMApplication::setTransientHint(int newRemoteWinId)
{
    if (0 == newRemoteWinId || not activeWindow()) {
        return;
    }

    x11Wrapper->remoteWindowId = newRemoteWinId;

    XSetTransientForHint(QX11Info::display(),
                         passThruWindow->effectiveWinId(),
                         x11Wrapper->remoteWindowId);

    // Using PropertyChangeMask is a work-around for NB#172722 (a WONTFIX):
    XSelectInput(QX11Info::display(),
                 x11Wrapper->remoteWindowId,
                 StructureNotifyMask | PropertyChangeMask);
}

void MIMApplication::setPassThruWindow(QWidget *newPassThruWindow)
{
    if (newPassThruWindow != passThruWindow) {
        passThruWindow = newPassThruWindow;
    }
}

MIMApplication *MIMApplication::instance()
{
    return static_cast<MIMApplication *>(QCoreApplication::instance());
}

bool MIMApplication::wasRemoteWindowIconified(XEvent *ev) const
{
    if (PropertyNotify != ev->type) {
        return false;
    }

    static const Atom wmState = XInternAtom(QX11Info::display(), "WM_STATE", false);

    if (ev->xproperty.atom == wmState) {
        Atom type;
        int format;
        unsigned long length;
        unsigned long after;
        unsigned long *state;
        uchar *data = 0;

        int queryResult = XGetWindowProperty(QX11Info::display(), x11Wrapper->remoteWindowId, wmState, 0, 2,
                                             false, AnyPropertyType, &type, &format, &length,
                                             &after, &data);
        state = (unsigned long *) data;

        bool result = (queryResult == Success && data && format == 32 && *state == IconicState);

        if (data) {
            XFree(data);
        }

        return result;
    }

    return false;
}

bool MIMApplication::wasRemoteWindowUnmapped(XEvent *ev) const
{
    return (UnmapNotify == ev->type &&
            ev->xunmap.event == x11Wrapper->remoteWindowId);
}

bool MIMApplication::wasPassThruWindowMapped(XEvent *ev) const
{
    return (passThruWindow &&
            MapNotify == ev->type &&
            static_cast<WId>(ev->xmap.event) == passThruWindow->effectiveWinId());
}

bool MIMApplication::wasPassThruWindowUnmapped(XEvent *ev) const
{
    return (passThruWindow &&
            UnmapNotify == ev->type &&
            static_cast<WId>(ev->xunmap.event) == passThruWindow->effectiveWinId());
}

void MIMApplication::setupDamage()
{
    if (x11Wrapper->remoteWindowId == 0)
        return;

    if (x11Wrapper->pixmapDamage != 0)
        destroyDamage();

    x11Wrapper->pixmapDamage = XDamageCreate(QX11Info::display(), x11Wrapper->remoteWindowId, XDamageReportNonEmpty);
}

void MIMApplication::destroyDamage()
{
    if (x11Wrapper->pixmapDamage != 0) {
        XDamageDestroy(QX11Info::display(), x11Wrapper->pixmapDamage);
        x11Wrapper->pixmapDamage = 0;
    }
}

void MIMApplication::handleDamageEvents(XEvent *event)
{
    if (x11Wrapper->remoteWindowId == 0 ||
        x11Wrapper->pixmapDamage == 0)
        return;

    if (event->type == damageBase + XDamageNotify) {
        XDamageNotifyEvent *e = reinterpret_cast<XDamageNotifyEvent*>(event);

        if (x11Wrapper->pixmapDamage == e->damage) {
            XserverRegion parts = XFixesCreateRegion(QX11Info::display(), 0, 0);
            XDamageSubtract(QX11Info::display(), e->damage, None, parts);

            QRegion region;

            int nrects;
            XRectangle *rects = XFixesFetchRegion (QX11Info::display(), parts, &nrects);
            if (rects) {
                for (int i = 0; i < nrects; ++i) {
                    region += QRect(rects[i].x, rects[i].y, rects[i].width, rects[i].height);
                }
            }
            free(rects);

            XFixesDestroyRegion(QX11Info::display(), parts);

            // setup remote pixmap when it failed before
            if (x11Wrapper->remoteWindowPixmap.isNull())
                setupRemotePixmap();

            emit remoteWindowUpdated(region);
        }
    }
}

void MIMApplication::redirectRemoteWindow()
{
    if (x11Wrapper->remoteWindowId != 0) {
        xError()->check(compositeMajor, X_CompositeRedirectWindow);
        XCompositeRedirectWindow(QX11Info::display(),
                                 x11Wrapper->remoteWindowId,
                                 CompositeRedirectManual);
        XSync(QX11Info::display(), FALSE);
        if (xError()->result() == BadAccess)
            qDebug() << "Window " << x11Wrapper->remoteWindowId << " was already redirected";

        setupRemotePixmap();

        setupDamage();
        emit remoteWindowUpdated(QRegion());
    }
}

void MIMApplication::unredirectRemoteWindow()
{
    destroyRemotePixmap();
    if (x11Wrapper->remoteWindowId != 0) {
        xError()->check(compositeMajor, X_CompositeUnredirectWindow);
        XCompositeUnredirectWindow(QX11Info::display(),
                                   x11Wrapper->remoteWindowId,
                                   CompositeRedirectManual);
        XSync(QX11Info::display(), FALSE);
        if (xError()->result() == BadAccess)
            qDebug() << "Window " << x11Wrapper->remoteWindowId << " was not redirected";
        destroyDamage();
    }
}

QPixmap MIMApplication::remoteWindowPixmap() const
{
    return x11Wrapper->remoteWindowPixmap;
}

bool MIMApplication::supportsSelfComposite() const
{
    return selfComposited;
}

void MIMApplication::setupRemotePixmap()
{
    destroyRemotePixmap();

    xError()->check(compositeMajor, X_CompositeNameWindowPixmap);
    x11Wrapper->remoteWindowXPixmap = XCompositeNameWindowPixmap(QX11Info::display(), x11Wrapper->remoteWindowId);
    XSync(QX11Info::display(), FALSE);
    if (xError()->result() == BadMatch) {
        qDebug() << "Cannot get offscreen reference for Window " << x11Wrapper->remoteWindowId;
        return;
    }

    if (x11Wrapper->remoteWindowXPixmap != 0) {
        x11Wrapper->remoteWindowPixmap = QPixmap::fromX11Pixmap(x11Wrapper->remoteWindowXPixmap, QPixmap::ExplicitlyShared);
    }
}

void MIMApplication::destroyRemotePixmap()
{
    x11Wrapper->remoteWindowPixmap = QPixmap();

    if (x11Wrapper->remoteWindowXPixmap != 0) {
        XFreePixmap(QX11Info::display(), x11Wrapper->remoteWindowXPixmap);
        x11Wrapper->remoteWindowXPixmap = 0;
    }
}

MIMXError *MIMApplication::xError() const
{
    return x11Error;
}

MIMXError::MIMXError() :
    request_code(0),
    minor_code(0),
    error_code(0),
    oldHandler(0)
{}

int xErrorHandler(Display *display, XErrorEvent *e)
{
    MIMXError *xerror = MIMApplication::instance()->xError();

    if (xerror->matches(e)) {
        xerror->error_code = e->error_code;
        return 0;
    }

    return xerror->oldHandler(display, e);
}

void MIMXError::check(int major, int minor)
{
    request_code = major;
    minor_code = minor;
    error_code = Success;
    oldHandler = XSetErrorHandler(xErrorHandler);
}

bool MIMXError::matches(XErrorEvent *e)
{
    return e->request_code == request_code && e->minor_code == minor_code;
}

int MIMXError::result()
{
    XSetErrorHandler(oldHandler);
    return error_code;
}
<|endoftext|>