<commit_before>// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "randomenv.h"

#include "crypto/sha512.h"
#include "support/cleanse.h"
#include "utiltime.h" // for GetTime()
#ifdef WIN32
#include "compat.h" // for Windows API
#endif

#include <algorithm>
#include <vector>

#include <stdint.h>

namespace {

void RandAddSeedPerfmon(CSHA512& hasher)
{
#ifdef WIN32
    // Don't need this on Linux, OpenSSL automatically uses /dev/urandom
    // Seed with the entire set of perfmon data

    // This can take up to 2 seconds, so only do it every 10 minutes
    static int64_t nLastPerfmon;
    if (GetTime() < nLastPerfmon + 10 * 60)
        return;
    nLastPerfmon = GetTime();

    std::vector<unsigned char> vData(250000, 0);
    long ret = 0;
    unsigned long nSize = 0;
    const size_t nMaxSize = 10000000; // Bail out at more than 10MB of performance data
    while (true) {
        nSize = vData.size();
        ret = RegQueryValueExA(HKEY_PERFORMANCE_DATA, "Global", nullptr, nullptr, vData.data(), &nSize);
        if (ret != ERROR_MORE_DATA || vData.size() >= nMaxSize)
            break;
        vData.resize(std::max((vData.size() * 3) / 2, nMaxSize)); // Grow size of buffer exponentially
    }
    RegCloseKey(HKEY_PERFORMANCE_DATA);
    if (ret == ERROR_SUCCESS) {
        hasher.Write(vData.data(), nSize);
        memory_cleanse(vData.data(), nSize);
    } else {
        // Performance data is only a best-effort attempt at improving the
        // situation when the OS randomness (and other sources) aren't
        // adequate. As a result, failure to read it is isn't considered critical,
        // so we don't call RandFailure().
        // TODO: Add logging when the logger is made functional before global
        // constructors have been invoked.
    }
#endif
}

} // namespace

void RandAddDynamicEnv(CSHA512& hasher)
{
    RandAddSeedPerfmon(hasher);
}

void RandAddStaticEnv(CSHA512& hasher)
{
}
<commit_msg>Seed randomness with process id / thread id / various clocks<commit_after>// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "randomenv.h"

#include "crypto/sha512.h"
#include "support/cleanse.h"
#include "utiltime.h" // for GetTime()
#ifdef WIN32
#include "compat.h" // for Windows API
#endif

#include <algorithm>
#include <chrono>
#include <thread>
#include <vector>

#include <stdint.h>
#include <string.h>
#ifndef WIN32
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#endif
#ifdef __MACH__
#include <mach/clock.h>
#include <mach/mach.h>
#include <mach/mach_time.h>
#endif

namespace {

void RandAddSeedPerfmon(CSHA512& hasher)
{
#ifdef WIN32
    // Don't need this on Linux, OpenSSL automatically uses /dev/urandom
    // Seed with the entire set of perfmon data

    // This can take up to 2 seconds, so only do it every 10 minutes
    static int64_t nLastPerfmon;
    if (GetTime() < nLastPerfmon + 10 * 60)
        return;
    nLastPerfmon = GetTime();

    std::vector<unsigned char> vData(250000, 0);
    long ret = 0;
    unsigned long nSize = 0;
    const size_t nMaxSize = 10000000; // Bail out at more than 10MB of performance data
    while (true) {
        nSize = vData.size();
        ret = RegQueryValueExA(HKEY_PERFORMANCE_DATA, "Global", nullptr, nullptr, vData.data(), &nSize);
        if (ret != ERROR_MORE_DATA || vData.size() >= nMaxSize)
            break;
        vData.resize(std::max((vData.size() * 3) / 2, nMaxSize)); // Grow size of buffer exponentially
    }
    RegCloseKey(HKEY_PERFORMANCE_DATA);
    if (ret == ERROR_SUCCESS) {
        hasher.Write(vData.data(), nSize);
        memory_cleanse(vData.data(), nSize);
    } else {
        // Performance data is only a best-effort attempt at improving the
        // situation when the OS randomness (and other sources) aren't
        // adequate. As a result, failure to read it is isn't considered critical,
        // so we don't call RandFailure().
        // TODO: Add logging when the logger is made functional before global
        // constructors have been invoked.
    }
#endif
}

/** Helper to easily feed data into a CSHA512.
 *
 * Note that this does not serialize the passed object (like stream.h's << operators do).
 * Its raw memory representation is used directly.
 */
template<typename T>
CSHA512& operator<<(CSHA512& hasher, const T& data) {
    static_assert(!std::is_same<typename std::decay<T>::type, char*>::value, "Calling operator<<(CSHA512, char*) is probably not what you want");
    static_assert(!std::is_same<typename std::decay<T>::type, unsigned char*>::value, "Calling operator<<(CSHA512, unsigned char*) is probably not what you want");
    static_assert(!std::is_same<typename std::decay<T>::type, const char*>::value, "Calling operator<<(CSHA512, const char*) is probably not what you want");
    static_assert(!std::is_same<typename std::decay<T>::type, const unsigned char*>::value, "Calling operator<<(CSHA512, const unsigned char*) is probably not what you want");
    hasher.Write((const unsigned char*)&data, sizeof(data));
    return hasher;
}

} // namespace

void RandAddDynamicEnv(CSHA512& hasher)
{
    RandAddSeedPerfmon(hasher);

    // Various clocks
#ifdef WIN32
    FILETIME ftime;
    GetSystemTimeAsFileTime(&ftime);
    hasher << ftime;
#else
#  ifndef __MACH__
    // On non-MacOS systems, use various clock_gettime() calls.
    struct timespec ts;
#    ifdef CLOCK_MONOTONIC
    clock_gettime(CLOCK_MONOTONIC, &ts);
    hasher << ts.tv_sec << ts.tv_nsec;
#    endif
#    ifdef CLOCK_REALTIME
    clock_gettime(CLOCK_REALTIME, &ts);
    hasher << ts.tv_sec << ts.tv_nsec;
#    endif
#    ifdef CLOCK_BOOTTIME
    clock_gettime(CLOCK_BOOTTIME, &ts);
    hasher << ts.tv_sec << ts.tv_nsec;
#    endif
#  else
    // On MacOS use mach_absolute_time (number of CPU ticks since boot) as a replacement for CLOCK_MONOTONIC,
    // and clock_get_time for CALENDAR_CLOCK as a replacement for CLOCK_REALTIME.
    hasher << mach_absolute_time();
    // From https://gist.github.com/jbenet/1087739
    clock_serv_t cclock;
    mach_timespec_t mts;
    if (host_get_clock_service(mach_host_self(), CALENDAR_CLOCK, &cclock) == KERN_SUCCESS && clock_get_time(cclock, &mts) == KERN_SUCCESS) {
        hasher << mts.tv_sec << mts.tv_nsec;
        mach_port_deallocate(mach_task_self(), cclock);
    }
#  endif
    // gettimeofday is available on all UNIX systems, but only has microsecond precision.
    struct timeval tv;
    gettimeofday(&tv, nullptr);
    hasher << tv.tv_sec << tv.tv_usec;
#endif
    // Probably redundant, but also use all the clocks C++11 provides:
    hasher << std::chrono::system_clock::now().time_since_epoch().count();
    hasher << std::chrono::steady_clock::now().time_since_epoch().count();
    hasher << std::chrono::high_resolution_clock::now().time_since_epoch().count();
}

void RandAddStaticEnv(CSHA512& hasher)
{
#ifdef WIN32
    hasher << GetCurrentProcessId() << GetCurrentThreadId();
#else
    hasher << getpid();
#endif
    hasher << std::this_thread::get_id();
}
<|endoftext|>


<commit_before>#include "repository.h"
#include "commit.h"
#include "tree.h"
#include "odb.h"
#include "index.h"
#include "tag.h"

using namespace std;

static void StubWeakCallback(Persistent<Value> val, void *data) {
	// TODO: should we actually be doing anything here? node's ObjectWrap deletes the object, but as far as I can tell, the dtor
	// for my weak ref'd stuff is getting called, which means memory is being freed... Unless I'm completely retarded?
}

Persistent<FunctionTemplate> Repository::constructor_template;

void Repository::Init(Handle<Object> target) {
	HandleScope scope;

	Local<FunctionTemplate> t = FunctionTemplate::New(New);
	constructor_template = Persistent<FunctionTemplate>::New(t);
	constructor_template->SetClassName(String::New("Repository"));
	t->InstanceTemplate()->SetInternalFieldCount(1);

	NODE_SET_PROTOTYPE_METHOD(t, "getObjectDatabase", GetODB);
	NODE_SET_PROTOTYPE_METHOD(t, "getCommit", GetCommit);
	NODE_SET_PROTOTYPE_METHOD(t, "getTree", GetTree);
	NODE_SET_PROTOTYPE_METHOD(t, "getTag", GetTag);

	t->InstanceTemplate()->SetAccessor(String::New("index"), IndexGetter);

	target->Set(String::New("Repository"), t->GetFunction());
}

Handle<Value> Repository::New(const Arguments& args) {
	HandleScope scope;

	REQ_ARGS(1);
	REQ_STR_ARG(0, path);

	Repository *repo = new Repository();

	if(int result = git_repository_open(&repo->repo_, *path) != GIT_SUCCESS) {
		Handle<Value> ex = Exception::Error(String::New("Git error."));
		return ThrowException(ex);
	}

	repo->path_ = *path;

	args.This()->Set(String::New("path"), String::New(repo->path_), ReadOnly);

	repo->Wrap(args.This());
	repo->MakeWeak();

	return args.This();
}

Handle<Value> Repository::GetODB(const Arguments& args) {
	HandleScope scope;

	Repository *repo = ObjectWrap::Unwrap<Repository>(args.This());
	git_odb *odb = git_repository_database(repo->repo_);

	Local<Value> arg = External::New(odb);
	Persistent<Object> result(ObjectDatabase::constructor_template->GetFunction()->NewInstance(1, &arg));
	return scope.Close(result);
}

Handle<Value> Repository::GetCommit(const Arguments& args) {
	HandleScope scope;

	REQ_ARGS(1);
	REQ_OID_ARG(0, commitOid);

	Repository *repo = ObjectWrap::Unwrap<Repository>(args.This());
	const char* oidStr = git_oid_allocfmt(&commitOid);

	git_commit* commit;
	if(git_commit_lookup(&commit, repo->repo_, &commitOid) != GIT_SUCCESS) {
		// TODO: error code handling.
		return scope.Close(Null());
	}

	Commit *commitObject = repo->wrapCommit(commit);
	return scope.Close(commitObject->handle_);
}

Handle<Value> Repository::GetTree(const Arguments& args) {
	HandleScope scope;

	REQ_ARGS(1);
	REQ_OID_ARG(0, treeOid);

	Repository *repo = ObjectWrap::Unwrap<Repository>(args.This());

	git_tree *tree;
	if(git_tree_lookup(&tree, repo->repo_, &treeOid) != GIT_SUCCESS) {
		return scope.Close(Null());
	}

	Tree *treeObject = repo->wrapTree(tree);
	return scope.Close(treeObject->handle_);
}

Handle<Value> Repository::GetTag(const Arguments& args) {
	HandleScope scope;

	REQ_ARGS(1);
	REQ_OID_ARG(0, tagOid);

	Repository *repo = ObjectWrap::Unwrap<Repository>(args.This());

	git_tag *tag;
	int res = git_tag_lookup(&tag, repo->repo_, &tagOid);

	if(res != GIT_SUCCESS) {
		return scope.Close(Null());
	}

	Tag *tagObj = repo->wrapTag(tag);
	return scope.Close(tagObj->handle_);

}

Handle<Value> Repository::IndexGetter(Local<String>, const AccessorInfo& info) {
	HandleScope scope;

	Repository *repo = ObjectWrap::Unwrap<Repository>(info.This());
	if(repo->index_ == NULL) {
		git_index *index;
		int result = git_repository_index(&index, repo->repo_);
		if(result == GIT_EBAREINDEX) {
			git_index_open_bare(&index, repo->path_);
		}

		Handle<Value> arg = External::New(index);
		Handle<Object> instance = Index::constructor_template->GetFunction()->NewInstance(1, &arg);
		repo->index_ = ObjectWrap::Unwrap<Index>(instance);
	}

	return repo->index_->handle_;
}

Repository::~Repository() {
	close();
}

void Repository::close() {
	if(repo_) {
		git_repository_free(repo_);
		repo_ = NULL;
	}
}

Commit *Repository::wrapCommit(git_commit *commit) {
	Commit *commitObject;
	if(commitStore_.getObjectFor(commit, &commitObject)) {
		// Commit needs to know who it's daddy is.
		commitObject->repository_ = this;
	}

	return commitObject;
}

Tree *Repository::wrapTree(git_tree *tree) {
	Tree *treeObject;
	if(treeStore_.getObjectFor(tree, &treeObject)) {
		treeObject->repository_ = this;
	}

	return treeObject;
}

Tag *Repository::wrapTag(git_tag *tag) {
	Tag *tagObject;
	if(tagStore_.getObjectFor(tag, &tagObject)) {

	}

	return tagObject;
}
<commit_msg>Remove old crap.<commit_after>#include "repository.h"
#include "commit.h"
#include "tree.h"
#include "odb.h"
#include "index.h"
#include "tag.h"

using namespace std;

Persistent<FunctionTemplate> Repository::constructor_template;

void Repository::Init(Handle<Object> target) {
	HandleScope scope;

	Local<FunctionTemplate> t = FunctionTemplate::New(New);
	constructor_template = Persistent<FunctionTemplate>::New(t);
	constructor_template->SetClassName(String::New("Repository"));
	t->InstanceTemplate()->SetInternalFieldCount(1);

	NODE_SET_PROTOTYPE_METHOD(t, "getObjectDatabase", GetODB);
	NODE_SET_PROTOTYPE_METHOD(t, "getCommit", GetCommit);
	NODE_SET_PROTOTYPE_METHOD(t, "getTree", GetTree);
	NODE_SET_PROTOTYPE_METHOD(t, "getTag", GetTag);

	t->InstanceTemplate()->SetAccessor(String::New("index"), IndexGetter);

	target->Set(String::New("Repository"), t->GetFunction());
}

Handle<Value> Repository::New(const Arguments& args) {
	HandleScope scope;

	REQ_ARGS(1);
	REQ_STR_ARG(0, path);

	Repository *repo = new Repository();

	if(int result = git_repository_open(&repo->repo_, *path) != GIT_SUCCESS) {
		Handle<Value> ex = Exception::Error(String::New("Git error."));
		return ThrowException(ex);
	}

	repo->path_ = *path;

	args.This()->Set(String::New("path"), String::New(repo->path_), ReadOnly);

	repo->Wrap(args.This());
	repo->MakeWeak();

	return args.This();
}

Handle<Value> Repository::GetODB(const Arguments& args) {
	HandleScope scope;

	Repository *repo = ObjectWrap::Unwrap<Repository>(args.This());
	git_odb *odb = git_repository_database(repo->repo_);

	Local<Value> arg = External::New(odb);
	Persistent<Object> result(ObjectDatabase::constructor_template->GetFunction()->NewInstance(1, &arg));
	return scope.Close(result);
}

Handle<Value> Repository::GetCommit(const Arguments& args) {
	HandleScope scope;

	REQ_ARGS(1);
	REQ_OID_ARG(0, commitOid);

	Repository *repo = ObjectWrap::Unwrap<Repository>(args.This());
	const char* oidStr = git_oid_allocfmt(&commitOid);

	git_commit* commit;
	if(git_commit_lookup(&commit, repo->repo_, &commitOid) != GIT_SUCCESS) {
		// TODO: error code handling.
		return scope.Close(Null());
	}

	Commit *commitObject = repo->wrapCommit(commit);
	return scope.Close(commitObject->handle_);
}

Handle<Value> Repository::GetTree(const Arguments& args) {
	HandleScope scope;

	REQ_ARGS(1);
	REQ_OID_ARG(0, treeOid);

	Repository *repo = ObjectWrap::Unwrap<Repository>(args.This());

	git_tree *tree;
	if(git_tree_lookup(&tree, repo->repo_, &treeOid) != GIT_SUCCESS) {
		return scope.Close(Null());
	}

	Tree *treeObject = repo->wrapTree(tree);
	return scope.Close(treeObject->handle_);
}

Handle<Value> Repository::GetTag(const Arguments& args) {
	HandleScope scope;

	REQ_ARGS(1);
	REQ_OID_ARG(0, tagOid);

	Repository *repo = ObjectWrap::Unwrap<Repository>(args.This());

	git_tag *tag;
	int res = git_tag_lookup(&tag, repo->repo_, &tagOid);

	if(res != GIT_SUCCESS) {
		return scope.Close(Null());
	}

	Tag *tagObj = repo->wrapTag(tag);
	return scope.Close(tagObj->handle_);

}

Handle<Value> Repository::IndexGetter(Local<String>, const AccessorInfo& info) {
	HandleScope scope;

	Repository *repo = ObjectWrap::Unwrap<Repository>(info.This());
	if(repo->index_ == NULL) {
		git_index *index;
		int result = git_repository_index(&index, repo->repo_);
		if(result == GIT_EBAREINDEX) {
			git_index_open_bare(&index, repo->path_);
		}

		Handle<Value> arg = External::New(index);
		Handle<Object> instance = Index::constructor_template->GetFunction()->NewInstance(1, &arg);
		repo->index_ = ObjectWrap::Unwrap<Index>(instance);
	}

	return repo->index_->handle_;
}

Repository::~Repository() {
	close();
}

void Repository::close() {
	if(repo_) {
		git_repository_free(repo_);
		repo_ = NULL;
	}
}

Commit *Repository::wrapCommit(git_commit *commit) {
	Commit *commitObject;
	if(commitStore_.getObjectFor(commit, &commitObject)) {
		// Commit needs to know who it's daddy is.
		commitObject->repository_ = this;
	}

	return commitObject;
}

Tree *Repository::wrapTree(git_tree *tree) {
	Tree *treeObject;
	if(treeStore_.getObjectFor(tree, &treeObject)) {
		treeObject->repository_ = this;
	}

	return treeObject;
}

Tag *Repository::wrapTag(git_tag *tag) {
	Tag *tagObject;
	if(tagStore_.getObjectFor(tag, &tagObject)) {

	}

	return tagObject;
}
<|endoftext|>


<commit_before>// Copyright (c) 2019 by Robert Bosch GmbH. All rights reserved.
//
// 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.

namespace iox
{
namespace concurrent
{
template <class ValueType, uint32_t CapacityValue>
SoFi<ValueType, CapacityValue>::SoFi() noexcept
{
}

template <class ValueType, uint32_t CapacityValue>
uint64_t SoFi<ValueType, CapacityValue>::capacity() const noexcept
{
    return m_size - INTERNAL_SIZE_ADD_ON;
}

template <class ValueType, uint32_t CapacityValue>
uint64_t SoFi<ValueType, CapacityValue>::size() const noexcept
{
    uint64_t readPosition;
    uint64_t writePosition;
    do
    {
        readPosition = m_readPosition.load(std::memory_order_relaxed);
        writePosition = m_writePosition.load(std::memory_order_relaxed);
    } while (m_writePosition.load(std::memory_order_relaxed) != writePosition
             || m_readPosition.load(std::memory_order_relaxed) != readPosition);

    return writePosition - readPosition;
}

template <class ValueType, uint32_t CapacityValue>
bool SoFi<ValueType, CapacityValue>::resize(const uint32_t newSize) noexcept
{
    uint64_t newInternalSize = newSize + INTERNAL_SIZE_ADD_ON;
    if (empty() && (newInternalSize <= INTERNAL_SOFI_SIZE))
    {
        m_size = newInternalSize;

        m_readPosition.store(0u, std::memory_order_release);
        m_writePosition.store(0u, std::memory_order_release);

        return true;
    }

    return false;
}

template <class ValueType, uint32_t CapacityValue>
bool SoFi<ValueType, CapacityValue>::empty() const noexcept
{
    uint64_t currentReadPosition;
    bool isEmpty;

    do
    {
        /// @todo read before write since the writer increments the aba counter!!!
        /// @todo write doc with example!!!
        currentReadPosition = m_readPosition.load(std::memory_order_acquire);
        uint64_t currentWritePosition = m_writePosition.load(std::memory_order_acquire);

        isEmpty = (currentWritePosition == currentReadPosition);
        // we need compare without exchange
    } while (!(currentReadPosition == m_readPosition.load(std::memory_order_acquire)));

    return isEmpty;
}

template <class ValueType, uint32_t CapacityValue>
bool SoFi<ValueType, CapacityValue>::pop(ValueType& valueOut) noexcept
{
    return popIf(valueOut, [](ValueType) { return true; });
}

template <class ValueType, uint32_t CapacityValue>
template <typename Verificator_T>
inline bool SoFi<ValueType, CapacityValue>::popIf(ValueType& valueOut, const Verificator_T& verificator) noexcept
{
    uint64_t currentReadPosition = m_readPosition.load(std::memory_order_acquire);
    uint64_t nextReadPosition;

    bool popWasSuccessful{true};
    do
    {
        if (currentReadPosition == m_writePosition.load(std::memory_order_acquire))
        {
            nextReadPosition = currentReadPosition;
            popWasSuccessful = false;
        }
        else
        {
            // we use memcpy here, since the copy assignment is not thread safe in general (we might have an overflow in
            // the push thread and invalidates the object while the copy is running and therefore works on an
            // invalid object); memcpy is also not thread safe, but we discard the object anyway and read it
            // again if its overwritten in between; this is only relevant for types larger than pointer size
            // assign the user data
            std::memcpy(&valueOut, &m_data[static_cast<int32_t>(currentReadPosition) % m_size], sizeof(ValueType));

            /// @brief first we need to peak valueOut if it is fitting the condition and then we have to verify
            ///        if valueOut is not am invalid object, this could be the case if the read position has
            ///        changed
            if (m_readPosition.load(std::memory_order_relaxed) == currentReadPosition && verificator(valueOut) == false)
            {
                popWasSuccessful = false;
            }
            else
            {
                nextReadPosition = currentReadPosition + 1U;
                popWasSuccessful = true;
            }
        }

        // compare and swap
        // if(m_readPosition == currentReadPosition)
        //     m_readPosition = l_next_aba_read_pos
        // else
        //     currentReadPosition = m_readPosition
        // Assign m_aba_read_p to next readable location
    } while (!m_readPosition.compare_exchange_weak(
        currentReadPosition, nextReadPosition, std::memory_order_acq_rel, std::memory_order_acquire));

    return popWasSuccessful;
}

template <class ValueType, uint32_t CapacityValue>
bool SoFi<ValueType, CapacityValue>::push(const ValueType& valueOut, ValueType& f_paramOut_r) noexcept
{
    constexpr bool OVERFLOW{false};

    uint64_t currentWritePosition = m_writePosition.load(std::memory_order_relaxed);
    uint64_t nextWritePosition = currentWritePosition + 1U;

    m_data[static_cast<int32_t>(currentWritePosition) % m_size] = valueOut;
    m_writePosition.store(nextWritePosition, std::memory_order_release);

    uint64_t currentReadPosition = m_readPosition.load(std::memory_order_acquire);

    // check if there is a free position for the next push
    if (nextWritePosition < currentReadPosition + m_size)
    {
        return !OVERFLOW;
    }

    // this is an overflow situation, which means that the next push has no free position, therefore the oldesz value
    // needs to be passed back to the caller

    uint64_t nextReadPosition = currentReadPosition + 1U;

    // we need to update the read position
    // a) it works, then we need to pass the overflow value back
    // b) it doesn't work, which means that the pop thread already took the value in the meantime an no further action
    // is required
    if (m_readPosition.compare_exchange_strong(
            currentReadPosition, nextReadPosition, std::memory_order_acq_rel, std::memory_order_relaxed))
    {
        // no atomic synchronization required because writer can always read his own data
        std::memcpy(&f_paramOut_r, &m_data[static_cast<int32_t>(currentReadPosition) % m_size], sizeof(ValueType));
        return OVERFLOW;
    }

    return !OVERFLOW;
}

} // namespace concurrent
} // namespace iox
<commit_msg>iox-#105 add comment regarding memory ordering<commit_after>// Copyright (c) 2019 by Robert Bosch GmbH. All rights reserved.
//
// 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.

namespace iox
{
namespace concurrent
{
template <class ValueType, uint32_t CapacityValue>
SoFi<ValueType, CapacityValue>::SoFi() noexcept
{
}

template <class ValueType, uint32_t CapacityValue>
uint64_t SoFi<ValueType, CapacityValue>::capacity() const noexcept
{
    return m_size - INTERNAL_SIZE_ADD_ON;
}

template <class ValueType, uint32_t CapacityValue>
uint64_t SoFi<ValueType, CapacityValue>::size() const noexcept
{
    uint64_t readPosition;
    uint64_t writePosition;
    do
    {
        readPosition = m_readPosition.load(std::memory_order_relaxed);
        writePosition = m_writePosition.load(std::memory_order_relaxed);
    } while (m_writePosition.load(std::memory_order_relaxed) != writePosition
             || m_readPosition.load(std::memory_order_relaxed) != readPosition);

    return writePosition - readPosition;
}

template <class ValueType, uint32_t CapacityValue>
bool SoFi<ValueType, CapacityValue>::resize(const uint32_t newSize) noexcept
{
    uint64_t newInternalSize = newSize + INTERNAL_SIZE_ADD_ON;
    if (empty() && (newInternalSize <= INTERNAL_SOFI_SIZE))
    {
        m_size = newInternalSize;

        m_readPosition.store(0u, std::memory_order_release);
        m_writePosition.store(0u, std::memory_order_release);

        return true;
    }

    return false;
}

template <class ValueType, uint32_t CapacityValue>
bool SoFi<ValueType, CapacityValue>::empty() const noexcept
{
    uint64_t currentReadPosition;
    bool isEmpty;

    do
    {
        /// @todo read before write since the writer increments the aba counter!!!
        /// @todo write doc with example!!!
        currentReadPosition = m_readPosition.load(std::memory_order_acquire);
        uint64_t currentWritePosition = m_writePosition.load(std::memory_order_acquire);

        isEmpty = (currentWritePosition == currentReadPosition);
        // we need compare without exchange
    } while (!(currentReadPosition == m_readPosition.load(std::memory_order_acquire)));

    return isEmpty;
}

template <class ValueType, uint32_t CapacityValue>
bool SoFi<ValueType, CapacityValue>::pop(ValueType& valueOut) noexcept
{
    return popIf(valueOut, [](ValueType) { return true; });
}

template <class ValueType, uint32_t CapacityValue>
template <typename Verificator_T>
inline bool SoFi<ValueType, CapacityValue>::popIf(ValueType& valueOut, const Verificator_T& verificator) noexcept
{
    uint64_t currentReadPosition = m_readPosition.load(std::memory_order_acquire);
    uint64_t nextReadPosition;

    bool popWasSuccessful{true};
    do
    {
        if (currentReadPosition == m_writePosition.load(std::memory_order_acquire))
        {
            nextReadPosition = currentReadPosition;
            popWasSuccessful = false;
        }
        else
        {
            // we use memcpy here, since the copy assignment is not thread safe in general (we might have an overflow in
            // the push thread and invalidates the object while the copy is running and therefore works on an
            // invalid object); memcpy is also not thread safe, but we discard the object anyway and read it
            // again if its overwritten in between; this is only relevant for types larger than pointer size
            // assign the user data
            std::memcpy(&valueOut, &m_data[static_cast<int32_t>(currentReadPosition) % m_size], sizeof(ValueType));

            /// @brief first we need to peak valueOut if it is fitting the condition and then we have to verify
            ///        if valueOut is not am invalid object, this could be the case if the read position has
            ///        changed
            if (m_readPosition.load(std::memory_order_relaxed) == currentReadPosition && verificator(valueOut) == false)
            {
                popWasSuccessful = false;
            }
            else
            {
                nextReadPosition = currentReadPosition + 1U;
                popWasSuccessful = true;
            }
        }

        // compare and swap
        // if(m_readPosition == currentReadPosition)
        //     m_readPosition = l_next_aba_read_pos
        // else
        //     currentReadPosition = m_readPosition
        // Assign m_aba_read_p to next readable location
    } while (!m_readPosition.compare_exchange_weak(
        currentReadPosition, nextReadPosition, std::memory_order_acq_rel, std::memory_order_acquire));

    return popWasSuccessful;
}

template <class ValueType, uint32_t CapacityValue>
bool SoFi<ValueType, CapacityValue>::push(const ValueType& valueOut, ValueType& f_paramOut_r) noexcept
{
    constexpr bool OVERFLOW{false};

    uint64_t currentWritePosition = m_writePosition.load(std::memory_order_relaxed);
    uint64_t nextWritePosition = currentWritePosition + 1U;

    m_data[static_cast<int32_t>(currentWritePosition) % m_size] = valueOut;
    m_writePosition.store(nextWritePosition, std::memory_order_release);

    uint64_t currentReadPosition = m_readPosition.load(std::memory_order_acquire);

    // check if there is a free position for the next push
    if (nextWritePosition < currentReadPosition + m_size)
    {
        return !OVERFLOW;
    }

    // this is an overflow situation, which means that the next push has no free position, therefore the oldest value
    // needs to be passed back to the caller

    uint64_t nextReadPosition = currentReadPosition + 1U;

    // we need to update the read position
    // a) it works, then we need to pass the overflow value back
    // b) it doesn't work, which means that the pop thread already took the value in the meantime an no further action
    // is required
    // memory order success is memory_order_acq_rel
    //   - this is to prevent the reordering of m_writePosition.store(...) after the increment of the m_readPosition
    //     - in case of an overflow, this might result in the pop thread getting one element less than the capacity of
    //       the SoFi if the push thread is suspended in between this two statements
    //     - it's still possible to get more elements than the capacity, but this is an inherent issue with concurrent
    //       queues and cannot be prevented since there can always be a push during a pop operation
    //   - another issue might be that two consecutive pushes (not concurrent) happen on different CPU cores without
    //     synchronization, then the memory also needs to be synchronized for the overflow case
    // memory order failure is memory_order_relaxed since there is no further synchronization needed if there is no
    // overflow
    if (m_readPosition.compare_exchange_strong(
            currentReadPosition, nextReadPosition, std::memory_order_acq_rel, std::memory_order_relaxed))
    {
        std::memcpy(&f_paramOut_r, &m_data[static_cast<int32_t>(currentReadPosition) % m_size], sizeof(ValueType));
        return OVERFLOW;
    }

    return !OVERFLOW;
}

} // namespace concurrent
} // namespace iox
<|endoftext|>


<commit_before>/*
    subscriptiondialog.cpp

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.
    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software Foundation,
    Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, US
*/

#include "subscriptiondialog.h"
#include "kmmessage.h"

#include <klocale.h>
#include <kdebug.h>

#include <qpushbutton.h>

namespace KMail {

SubscriptionDialog::SubscriptionDialog( QWidget *parent, const QString &caption,
    KAccount * acct )
  : KSubscription( parent, caption, acct, User1, QString::null, false )
{
  // hide unneeded checkboxes
  hideTreeCheckbox();
  hideNewOnlyCheckbox();

  // connect to folderlisting
  ImapAccountBase* iaccount = static_cast<ImapAccountBase*>(acct);
  connect(iaccount, SIGNAL(receivedFolders(QStringList, QStringList,
          QStringList, const ImapAccountBase::jobData &)),
      this, SLOT(slotListDirectory(QStringList, QStringList,
          QStringList, const ImapAccountBase::jobData &)));

  // ok-button
  connect(this, SIGNAL(okClicked()), SLOT(slotSave()));

  // reload-list button
  connect(this, SIGNAL(user1Clicked()), SLOT(slotLoadFolders()));

  // get the folders
  slotLoadFolders();
}

//------------------------------------------------------------------------------
void SubscriptionDialog::slotListDirectory( QStringList mSubfolderNames,
                                            QStringList mSubfolderPaths,
                                            QStringList mSubfolderMimeTypes,
                                            const ImapAccountBase::jobData & jobData )
{
  if (mSubfolderPaths.size() <= 0) return;
  bool onlySubscribed = jobData.onlySubscribed;
  GroupItem *parent = 0;
  mLoading = true;

  if (!onlySubscribed)
  {
    /* we need to find our root-item
       remove the name (and the separator) from the path */
    int start = mSubfolderPaths[0].length() - (mSubfolderNames[0].length()+2);
    int length = mSubfolderNames[0].length()+1;
    if (start < 0) start = 0;
    QString compare = mSubfolderPaths[0];
    compare.remove(start, length);

    QListViewItemIterator it( groupView );
    GroupItem *tmp;
    while ( it.current() != 0 )
    {
      // compare it with each item to find the current root
      tmp = static_cast<GroupItem*>(it.current());
      if (tmp->info().path == compare) {
        parent = tmp;
        break;
      }
      ++it;
    }
  }
  GroupItem *item = 0;
  QString text;
  for (uint i = 0; i < mSubfolderNames.count(); i++)
  {
    if (!onlySubscribed)
    {
      bool create = true;
      if (parent)
      {
        for ( QListViewItem *it = parent->firstChild() ;
            it ; it = it->nextSibling() )
        {
          // check if this item already exists in this hierarchy
          item = static_cast<GroupItem*>(it);
          if (item->info().path == mSubfolderPaths[i])
            create = false;
        }
      }
      if (create)
      {
        KGroupInfo info(mSubfolderNames[i]);
        if (mSubfolderNames[i].upper() == "INBOX")
          info.name = i18n("inbox");
        info.subscribed = false;
        info.path = mSubfolderPaths[i];
        // create a new checkable item
        if (parent)
          item = new GroupItem(parent, info, this, true);
        else
          item = new GroupItem(folderTree(), info, this, true);
      }
      if (item)
      {
        // reset
        item->setOn(false);
      }
    } else {
      // find the item
      QListViewItemIterator it( groupView );
      while ( it.current() != 0 )
      {
        item = static_cast<GroupItem*>(it.current());
        if (item->info().path == mSubfolderPaths[i])
        {
          // subscribed
          item->setOn(true);
        }
        ++it;
      }
    }
    if (mSubfolderMimeTypes[i] == "message/directory" ||
        mSubfolderMimeTypes[i] == "inode/directory")
    {
      // descend
      static_cast<ImapAccountBase*>(mAcct)->listDirectory(mSubfolderPaths[i],
          onlySubscribed);
    }
  }
  if (jobData.inboxOnly)
  {
    ImapAccountBase* ai = static_cast<ImapAccountBase*>(mAcct);
    ai->listDirectory(ai->prefix(), false, true);
    ai->listDirectory(ai->prefix(), true, true);
  }
  slotLoadingComplete();
}

//------------------------------------------------------------------------------
void SubscriptionDialog::slotSave()
{
  // subscribe
  QListViewItemIterator it(subView);
  for ( ; it.current(); ++it)
  {
    static_cast<ImapAccountBase*>(account())->changeSubscription(true,
        static_cast<GroupItem*>(it.current())->info().path);
  }

  // unsubscribe
  QListViewItemIterator it2(unsubView);
  for ( ; it2.current(); ++it2)
  {
    static_cast<ImapAccountBase*>(account())->changeSubscription(false,
        static_cast<GroupItem*>(it2.current())->info().path);
  }
}

//------------------------------------------------------------------------------
void SubscriptionDialog::slotLoadFolders()
{
  KSubscription::slotLoadFolders();
  ImapAccountBase* ai = static_cast<ImapAccountBase*>(account());
  // get folders
  ai->listDirectory(ai->prefix(), false);
  ai->listDirectory(ai->prefix(), true);
}

};

#include "subscriptiondialog.moc"
<commit_msg>Fix crash when account() is null. But better fix it to disable action when accout() is null<commit_after>/*
    subscriptiondialog.cpp

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.
    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software Foundation,
    Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, US
*/

#include "subscriptiondialog.h"
#include "kmmessage.h"

#include <klocale.h>
#include <kdebug.h>

#include <qpushbutton.h>

namespace KMail {

SubscriptionDialog::SubscriptionDialog( QWidget *parent, const QString &caption,
    KAccount * acct )
  : KSubscription( parent, caption, acct, User1, QString::null, false )
{
  // hide unneeded checkboxes
  hideTreeCheckbox();
  hideNewOnlyCheckbox();

  // connect to folderlisting
  ImapAccountBase* iaccount = static_cast<ImapAccountBase*>(acct);
  connect(iaccount, SIGNAL(receivedFolders(QStringList, QStringList,
          QStringList, const ImapAccountBase::jobData &)),
      this, SLOT(slotListDirectory(QStringList, QStringList,
          QStringList, const ImapAccountBase::jobData &)));

  // ok-button
  connect(this, SIGNAL(okClicked()), SLOT(slotSave()));

  // reload-list button
  connect(this, SIGNAL(user1Clicked()), SLOT(slotLoadFolders()));

  // get the folders
  slotLoadFolders();
}

//------------------------------------------------------------------------------
void SubscriptionDialog::slotListDirectory( QStringList mSubfolderNames,
                                            QStringList mSubfolderPaths,
                                            QStringList mSubfolderMimeTypes,
                                            const ImapAccountBase::jobData & jobData )
{
  if (mSubfolderPaths.size() <= 0) return;
  bool onlySubscribed = jobData.onlySubscribed;
  GroupItem *parent = 0;
  mLoading = true;

  if (!onlySubscribed)
  {
    /* we need to find our root-item
       remove the name (and the separator) from the path */
    int start = mSubfolderPaths[0].length() - (mSubfolderNames[0].length()+2);
    int length = mSubfolderNames[0].length()+1;
    if (start < 0) start = 0;
    QString compare = mSubfolderPaths[0];
    compare.remove(start, length);

    QListViewItemIterator it( groupView );
    GroupItem *tmp;
    while ( it.current() != 0 )
    {
      // compare it with each item to find the current root
      tmp = static_cast<GroupItem*>(it.current());
      if (tmp->info().path == compare) {
        parent = tmp;
        break;
      }
      ++it;
    }
  }
  GroupItem *item = 0;
  QString text;
  for (uint i = 0; i < mSubfolderNames.count(); i++)
  {
    if (!onlySubscribed)
    {
      bool create = true;
      if (parent)
      {
        for ( QListViewItem *it = parent->firstChild() ;
            it ; it = it->nextSibling() )
        {
          // check if this item already exists in this hierarchy
          item = static_cast<GroupItem*>(it);
          if (item->info().path == mSubfolderPaths[i])
            create = false;
        }
      }
      if (create)
      {
        KGroupInfo info(mSubfolderNames[i]);
        if (mSubfolderNames[i].upper() == "INBOX")
          info.name = i18n("inbox");
        info.subscribed = false;
        info.path = mSubfolderPaths[i];
        // create a new checkable item
        if (parent)
          item = new GroupItem(parent, info, this, true);
        else
          item = new GroupItem(folderTree(), info, this, true);
      }
      if (item)
      {
        // reset
        item->setOn(false);
      }
    } else {
      // find the item
      QListViewItemIterator it( groupView );
      while ( it.current() != 0 )
      {
        item = static_cast<GroupItem*>(it.current());
        if (item->info().path == mSubfolderPaths[i])
        {
          // subscribed
          item->setOn(true);
        }
        ++it;
      }
    }
    if (mSubfolderMimeTypes[i] == "message/directory" ||
        mSubfolderMimeTypes[i] == "inode/directory")
    {
      // descend
      static_cast<ImapAccountBase*>(mAcct)->listDirectory(mSubfolderPaths[i],
          onlySubscribed);
    }
  }
  if (jobData.inboxOnly)
  {
    ImapAccountBase* ai = static_cast<ImapAccountBase*>(mAcct);
    ai->listDirectory(ai->prefix(), false, true);
    ai->listDirectory(ai->prefix(), true, true);
  }
  slotLoadingComplete();
}

//------------------------------------------------------------------------------
void SubscriptionDialog::slotSave()
{
    if (!account())
        return;
    // subscribe
  QListViewItemIterator it(subView);
  for ( ; it.current(); ++it)
  {
    static_cast<ImapAccountBase*>(account())->changeSubscription(true,
        static_cast<GroupItem*>(it.current())->info().path);
  }

  // unsubscribe
  QListViewItemIterator it2(unsubView);
  for ( ; it2.current(); ++it2)
  {
    static_cast<ImapAccountBase*>(account())->changeSubscription(false,
        static_cast<GroupItem*>(it2.current())->info().path);
  }
}

//------------------------------------------------------------------------------
void SubscriptionDialog::slotLoadFolders()
{
  KSubscription::slotLoadFolders();
  if ( !account())
      return;
  ImapAccountBase* ai = static_cast<ImapAccountBase*>(account());
  // get folders
  ai->listDirectory(ai->prefix(), false);
  ai->listDirectory(ai->prefix(), true);
}

};

#include "subscriptiondialog.moc"
<|endoftext|>


<commit_before>#include <SDL2/SDL.h>
#ifdef main
#undef main
#endif
#include "cudaray.h"

static float rnd()
{
    static long a = 3;
    a = (((a * 214013L + 2531011L) >> 16) & 32767);

    return (((a % 65556) + 1)) / 65556.0f;
}

struct t_light_aux
{
    float r;
    float xangle;
    float yangle;
    float speed;
};

double time_get()
{
    uint64_t time = SDL_GetPerformanceCounter();
    uint64_t frequency = SDL_GetPerformanceFrequency();

    return ((double)time) / ((double)frequency);
}

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

    static const int width = 800;
    static const int height = 800;

    SDL_Window * window;
    SDL_Renderer * renderer;
    SDL_CreateWindowAndRenderer( width, height, SDL_WINDOW_SHOWN, &window, &renderer );
    SDL_Texture * texture = SDL_CreateTexture( renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, width, height );

    SDL_RenderSetLogicalSize( renderer, width, height );

    const size_t n_spheres = 2;
    t_sphere * spheres = (t_sphere *)calloc( n_spheres, sizeof( t_sphere ) );
    for( int i = 0; i < n_spheres; ++i )
    {
        t_sphere * sphere = spheres + i;

        vec3_set( sphere->position, width / 2.0f, height / 2.0f, 0.0f );
        vec3_set( sphere->color, 1.0f, 1.0f, 1.0f );

        t_vec3 extra;
        vec3_set( extra, rnd() * 100.0f, rnd() * 100.0f, rnd() * 100.0f );
        vec3_add( sphere->position, extra );
        sphere->radius = 50.0f + rnd() * 25.0f;
    }

    const size_t n_lights = 1;
    t_light * lights = (t_light *)calloc( n_lights, sizeof( t_light ) );
    t_light_aux * lights_aux = ( t_light_aux * )calloc( n_lights, sizeof( t_light_aux ) );
    for( int i = 1; i < n_lights; ++i )
    {
        t_light * light = lights + i;
        t_light_aux * aux = lights_aux + i;

        light->intensity = 0.25f + rnd();
        if( light->intensity > 1.0f )
            light->intensity = 1.0f;

        vec3_set( light->color, rnd() + 0.25f, rnd() + 0.25f, rnd() + 0.25f );
        vec3_clamp( light->color, 0.0f, 1.0f );

        aux->r = 50.0f + rnd() * 200.0f;
        aux->xangle = rnd() * 3.14;
        aux->yangle = rnd() * 3.14;
        aux->speed = rnd() * 4.0f;
    }

    vec3_set( spheres[1].position, width / 2.0f, height / 2.0f, 0.0f );
    spheres[1].radius = 100.0f;
    vec3_set( spheres[0].position, width / 2.0f + 50.0f, height / 2.0f, 300.0f );
    spheres[0].radius = 50.0f;

    spheres[0].color[1] = 0.0f;
    spheres[0].color[2] = 0.0f;

    lights[0].intensity = 1.0f;
    vec3_set( lights[0].color, 1.0f, 1.0f, 1.0f );
    vec3_set( lights[0].position, width / 2.0f, height / 2.0f, 500.0f );

    uint32_t img[ width ][ height ];
    memset( &img, 0, sizeof( img ) );

    float t = 0.0f;
    float speed = 0.3f;
    int acceleration = 0;;

    double timestamp = time_get();
    int frame_counter = 0;

    double average = 0.0f;
    bool average_initialized = false;

    for( ;; )
    {
        SDL_Event event;
        while( SDL_PollEvent( &event ) )
        {
            switch( event.type )
            {
                case SDL_KEYUP:
                    switch( event.key.keysym.sym )
                    {
                        case SDLK_ESCAPE:
                            return 0;
                        case SDLK_RIGHT:
                            if( !event.key.repeat )
                                acceleration -= 1;
                            break;
                        case SDLK_LEFT:
                            if( !event.key.repeat )
                                acceleration += 1;
                            break;
                    }
                    break;

                case SDL_KEYDOWN:
                    switch( event.key.keysym.sym )
                    {
                        case SDLK_RIGHT:
                            if( !event.key.repeat )
                                acceleration += 1;
                            break;
                        case SDLK_LEFT:
                            if( !event.key.repeat )
                                acceleration -= 1;
                            break;
                    }
                    break;
            }
        }

        vec3_set( lights[0].position, width / 2.0f, height / 2.0f, 300.0f );
        t_vec3 shift;
        vec3_set( shift, (150.0f) * cosf(t), 0.0f, (150.0f) * sinf(t) );
        vec3_add( lights[0].position, shift );

        for( int i = 1; i < n_lights; ++i )
        {
            t_light * light = lights + i;
            t_light_aux * aux = lights_aux + i;

            t_vec3 shift;
            vec3_set( shift, aux->r * cosf( aux->xangle ) * sin( aux->yangle ), aux->r * sin( aux->xangle ) * cos( aux->yangle ), aux->r * sinf( aux->yangle ) );

            vec3_set( light->position, width / 2.0f, height / 2.0f, 0.0f );
            vec3_add( light->position, shift );

            aux->xangle += speed * aux->speed;
            aux->yangle += speed * aux->speed;
        }

        cuda_main( width, height, (uint32_t *)img, spheres, n_spheres, lights, n_lights );

        img[ (int)lights[0].position[1] ][ (int)lights[0].position[0] ] = 0xff00ffff;

        SDL_UpdateTexture( texture, NULL, img, width * sizeof( uint32_t ) );
        SDL_RenderClear( renderer );
        SDL_RenderCopy( renderer, texture, NULL, NULL );
        SDL_RenderPresent( renderer );
        SDL_Delay( 2 );

        t += speed;
        speed += acceleration * 0.01f;

        frame_counter++;
        if( frame_counter == 10 )
        {
            frame_counter = 0;
            double now = time_get();
            double time_per_frame = (now - timestamp) / 10.0;
            timestamp = now;

            printf( "time per frame: %fms\n", time_per_frame * 1000.0 );

            if( !average_initialized )
                average = time_per_frame;
            else
                average = (average + time_per_frame) / 2.0;
        }
    }

    printf( "average time per frame: %f\n", average );

    SDL_DestroyWindow( window );
    SDL_Quit();

    return 0;

}
<commit_msg>Fix quitting with escape.<commit_after>#include <SDL2/SDL.h>
#ifdef main
#undef main
#endif
#include "cudaray.h"

static float rnd()
{
    static long a = 3;
    a = (((a * 214013L + 2531011L) >> 16) & 32767);

    return (((a % 65556) + 1)) / 65556.0f;
}

struct t_light_aux
{
    float r;
    float xangle;
    float yangle;
    float speed;
};

double time_get()
{
    uint64_t time = SDL_GetPerformanceCounter();
    uint64_t frequency = SDL_GetPerformanceFrequency();

    return ((double)time) / ((double)frequency);
}

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

    static const int width = 800;
    static const int height = 800;

    SDL_Window * window;
    SDL_Renderer * renderer;
    SDL_CreateWindowAndRenderer( width, height, SDL_WINDOW_SHOWN, &window, &renderer );
    SDL_Texture * texture = SDL_CreateTexture( renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, width, height );

    SDL_RenderSetLogicalSize( renderer, width, height );

    const size_t n_spheres = 2;
    t_sphere * spheres = (t_sphere *)calloc( n_spheres, sizeof( t_sphere ) );
    for( int i = 0; i < n_spheres; ++i )
    {
        t_sphere * sphere = spheres + i;

        vec3_set( sphere->position, width / 2.0f, height / 2.0f, 0.0f );
        vec3_set( sphere->color, 1.0f, 1.0f, 1.0f );

        t_vec3 extra;
        vec3_set( extra, rnd() * 100.0f, rnd() * 100.0f, rnd() * 100.0f );
        vec3_add( sphere->position, extra );
        sphere->radius = 50.0f + rnd() * 25.0f;
    }

    const size_t n_lights = 1;
    t_light * lights = (t_light *)calloc( n_lights, sizeof( t_light ) );
    t_light_aux * lights_aux = ( t_light_aux * )calloc( n_lights, sizeof( t_light_aux ) );
    for( int i = 1; i < n_lights; ++i )
    {
        t_light * light = lights + i;
        t_light_aux * aux = lights_aux + i;

        light->intensity = 0.25f + rnd();
        if( light->intensity > 1.0f )
            light->intensity = 1.0f;

        vec3_set( light->color, rnd() + 0.25f, rnd() + 0.25f, rnd() + 0.25f );
        vec3_clamp( light->color, 0.0f, 1.0f );

        aux->r = 50.0f + rnd() * 200.0f;
        aux->xangle = rnd() * 3.14;
        aux->yangle = rnd() * 3.14;
        aux->speed = rnd() * 4.0f;
    }

    vec3_set( spheres[1].position, width / 2.0f, height / 2.0f, 0.0f );
    spheres[1].radius = 100.0f;
    vec3_set( spheres[0].position, width / 2.0f + 50.0f, height / 2.0f, 300.0f );
    spheres[0].radius = 50.0f;

    spheres[0].color[1] = 0.0f;
    spheres[0].color[2] = 0.0f;

    lights[0].intensity = 1.0f;
    vec3_set( lights[0].color, 1.0f, 1.0f, 1.0f );
    vec3_set( lights[0].position, width / 2.0f, height / 2.0f, 500.0f );

    uint32_t img[ width ][ height ];
    memset( &img, 0, sizeof( img ) );

    float t = 0.0f;
    float speed = 0.3f;
    int acceleration = 0;;

    double timestamp = time_get();
    int frame_counter = 0;

    double average = 0.0f;
    bool average_initialized = false;
    bool running = true;

    while( running )
    {
        SDL_Event event;
        while( SDL_PollEvent( &event ) )
        {
            switch( event.type )
            {
                case SDL_KEYUP:
                    switch( event.key.keysym.sym )
                    {
                        case SDLK_ESCAPE:
                            running = false;
                            break;
                        case SDLK_RIGHT:
                            if( !event.key.repeat )
                                acceleration -= 1;
                            break;
                        case SDLK_LEFT:
                            if( !event.key.repeat )
                                acceleration += 1;
                            break;
                    }
                    break;

                case SDL_KEYDOWN:
                    switch( event.key.keysym.sym )
                    {
                        case SDLK_RIGHT:
                            if( !event.key.repeat )
                                acceleration += 1;
                            break;
                        case SDLK_LEFT:
                            if( !event.key.repeat )
                                acceleration -= 1;
                            break;
                    }
                    break;
            }

            if( !running )
                break;
        }
        if( !running )
            break;

        vec3_set( lights[0].position, width / 2.0f, height / 2.0f, 300.0f );
        t_vec3 shift;
        vec3_set( shift, (150.0f) * cosf(t), 0.0f, (150.0f) * sinf(t) );
        vec3_add( lights[0].position, shift );

        for( int i = 1; i < n_lights; ++i )
        {
            t_light * light = lights + i;
            t_light_aux * aux = lights_aux + i;

            t_vec3 shift;
            vec3_set( shift, aux->r * cosf( aux->xangle ) * sin( aux->yangle ), aux->r * sin( aux->xangle ) * cos( aux->yangle ), aux->r * sinf( aux->yangle ) );

            vec3_set( light->position, width / 2.0f, height / 2.0f, 0.0f );
            vec3_add( light->position, shift );

            aux->xangle += speed * aux->speed;
            aux->yangle += speed * aux->speed;
        }

        cuda_main( width, height, (uint32_t *)img, spheres, n_spheres, lights, n_lights );

        img[ (int)lights[0].position[1] ][ (int)lights[0].position[0] ] = 0xff00ffff;

        SDL_UpdateTexture( texture, NULL, img, width * sizeof( uint32_t ) );
        SDL_RenderClear( renderer );
        SDL_RenderCopy( renderer, texture, NULL, NULL );
        SDL_RenderPresent( renderer );
        SDL_Delay( 2 );

        t += speed;
        speed += acceleration * 0.01f;

        frame_counter++;
        if( frame_counter == 10 )
        {
            frame_counter = 0;
            double now = time_get();
            double time_per_frame = (now - timestamp) / 10.0;
            timestamp = now;

            printf( "time per frame: %fms\n", time_per_frame * 1000.0 );

            if( !average_initialized )
                average = time_per_frame;
            else
                average = (average + time_per_frame) / 2.0;
        }
    }

    printf( "average time per frame: %f\n", average );

    SDL_DestroyWindow( window );
    SDL_Quit();

    return 0;

}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2014 liblcf authors
 * This file is released under the MIT License
 * http://opensource.org/licenses/MIT
 */

#include "reader_options.h"
#include "rpg_actor.h"
#include "rpg_event.h"
#include "rpg_map.h"
#include "rpg_mapinfo.h"
#include "rpg_system.h"
#include "rpg_save.h"
#include "rpg_chipset.h"
#include "rpg_parameters.h"
#include "data.h"

void RPG::SaveActor::Setup(int actor_id) {
	const RPG::Actor& actor = Data::actors[actor_id - 1];
	ID = actor.ID;
	name = actor.name;
	title = actor.title;
	sprite_name = actor.character_name;
	sprite_id = actor.character_index;
	sprite_flags = actor.transparent ? 3 : 0;
	face_name = actor.face_name;
	face_id = actor.face_index;
	level = actor.initial_level;
	exp = 0;
	hp_mod = 0;
	sp_mod = 0;
	attack_mod = 0;
	defense_mod = 0;
	spirit_mod = 0;
	agility_mod = 0;
	skills_size = 0;
	skills.clear();
	equipped.clear();
	equipped.push_back(actor.initial_equipment.weapon_id);
	equipped.push_back(actor.initial_equipment.shield_id);
	equipped.push_back(actor.initial_equipment.armor_id);
	equipped.push_back(actor.initial_equipment.helmet_id);
	equipped.push_back(actor.initial_equipment.accessory_id);
	current_hp = 0;
	current_sp = 0;
	battle_commands = actor.battle_commands;
	status_size = 0;
	status.clear();
	changed_class = false;
	class_id = actor.class_id;
	row = -1;
	two_weapon = actor.two_swords_style;
	lock_equipment = actor.fix_equipment;
	auto_battle = actor.auto_battle;
	mighty_guard = actor.super_guard;
	unknown_60 = -1;
}

void RPG::SaveInventory::Setup() {
	party = Data::system.party;
	party_size = party.size();
}

void RPG::SaveMapEvent::Setup(const RPG::Event& event) {
	ID = event.ID;
	position_x = event.x;
	position_y = event.y;
}

void RPG::SaveMapInfo::Setup() {
	position_x = 0;
	position_y = 0;
	lower_tiles.resize(144);
	upper_tiles.resize(144);
	for (int i = 0; i < 144; i++) {
		lower_tiles[i] = i;
		upper_tiles[i] = i;
	}
}

void RPG::SaveMapInfo::Setup(const RPG::Map& map) {
	chipset_id = map.chipset_id;
	parallax_name = map.parallax_name;
	parallax_horz = map.parallax_loop_x;
	parallax_vert = map.parallax_loop_y;
	parallax_horz_auto = map.parallax_auto_loop_x;
	parallax_vert_auto = map.parallax_auto_loop_y;
	parallax_horz_speed = map.parallax_sx;
	parallax_vert_speed = map.parallax_sy;
}

void RPG::SaveMapInfo::Setup(const RPG::MapInfo& map_info) {
	encounter_rate = map_info.encounter_steps;
}

void RPG::SaveSystem::Setup() {
	const RPG::System& system = Data::system;
	screen = 0;
	frame_count = 0;
	graphics_name = system.system_name;
	switches_size = Data::switches.size();
	switches.clear();
	switches.resize(switches_size);
	variables_size = Data::variables.size();
	variables.clear();
	variables.resize(variables_size);
	face_name = "";
	face_id = -1;
	face_right = false;
	face_flip = false;
	transparent = false;
	unknown_3d = -1;
	title_music = system.title_music;
	battle_music = system.battle_music;
	battle_end_music = system.battle_end_music;
	inn_music = system.inn_music;
	// current_music
	// unknown1_music FIXME
	// unknown2_music FIXME
	// stored_music
	boat_music = system.boat_music;
	ship_music = system.ship_music;
	airship_music = system.airship_music;
	gameover_music = system.gameover_music;
	cursor_se = system.cursor_se;
	decision_se = system.decision_se;
	cancel_se = system.cancel_se;
	buzzer_se = system.buzzer_se;
	battle_se = system.battle_se;
	escape_se = system.escape_se;
	enemy_attack_se = system.enemy_attack_se;
	enemy_damaged_se = system.enemy_damaged_se;
	actor_damaged_se = system.actor_damaged_se;
	dodge_se = system.dodge_se;
	enemy_death_se = system.enemy_death_se;
	item_se = system.item_se;
	transition_out = system.transition_out;
	transition_in = system.transition_in;
	battle_start_fadeout = system.battle_start_fadeout;
	battle_start_fadein = system.battle_start_fadein;
	battle_end_fadeout = system.battle_end_fadeout;
	battle_end_fadein = system.battle_end_fadein;
	teleport_allowed = true;
	escape_allowed = true;
	save_allowed = true;
	menu_allowed = true;
	background = "";
	save_count = 0;
	save_slot = -1;
}

void RPG::Save::Setup() {
	system.Setup();
	screen = RPG::SaveScreen();
	pictures.clear();
	pictures.resize(50);
	for (int i = 1; i <= (int)pictures.size(); i++) {
		pictures[i - 1].ID = i;
	}
	actors.clear();
	actors.resize(Data::actors.size());
	for (int i = 1; i <= (int) actors.size(); i++)
		actors[i - 1].Setup(i);
	map_info.Setup();
}

void RPG::Actor::Setup() {
	if (Data::system.ldb_id == 2003) {
		final_level = final_level == -1 ? 99 : final_level;
		exp_base = exp_base == -1 ? 300 : exp_base;
		exp_inflation = exp_inflation == -1 ? 300 : exp_inflation;
	}
	else {
		final_level = final_level == -1 ? 50 : final_level;
		exp_base = exp_base == -1 ? 30 : exp_base;
		exp_inflation = exp_inflation == -1 ? 30 : exp_inflation;
	}
	parameters.Setup(final_level);
}

void RPG::MapInfo::Init() {
	music.name = "(OFF)";
}

void RPG::Chipset::Init() {
	terrain_data.resize(162, 1);
	passable_data_lower.resize(162, 15);
	passable_data_upper.resize(162, 15);
}

void RPG::Parameters::Setup(int final_level) {
	maxhp.resize(final_level + 1, 1);
	maxsp.resize(final_level + 1, 0);
	attack.resize(final_level + 1, 1);
	defense.resize(final_level + 1, 1);
	spirit.resize(final_level + 1, 1);
	agility.resize(final_level + 1, 1);
}
<commit_msg>Use correct rpg parameters vector size<commit_after>/*
 * Copyright (c) 2014 liblcf authors
 * This file is released under the MIT License
 * http://opensource.org/licenses/MIT
 */

#include "reader_options.h"
#include "rpg_actor.h"
#include "rpg_event.h"
#include "rpg_map.h"
#include "rpg_mapinfo.h"
#include "rpg_system.h"
#include "rpg_save.h"
#include "rpg_chipset.h"
#include "rpg_parameters.h"
#include "data.h"

void RPG::SaveActor::Setup(int actor_id) {
	const RPG::Actor& actor = Data::actors[actor_id - 1];
	ID = actor.ID;
	name = actor.name;
	title = actor.title;
	sprite_name = actor.character_name;
	sprite_id = actor.character_index;
	sprite_flags = actor.transparent ? 3 : 0;
	face_name = actor.face_name;
	face_id = actor.face_index;
	level = actor.initial_level;
	exp = 0;
	hp_mod = 0;
	sp_mod = 0;
	attack_mod = 0;
	defense_mod = 0;
	spirit_mod = 0;
	agility_mod = 0;
	skills_size = 0;
	skills.clear();
	equipped.clear();
	equipped.push_back(actor.initial_equipment.weapon_id);
	equipped.push_back(actor.initial_equipment.shield_id);
	equipped.push_back(actor.initial_equipment.armor_id);
	equipped.push_back(actor.initial_equipment.helmet_id);
	equipped.push_back(actor.initial_equipment.accessory_id);
	current_hp = 0;
	current_sp = 0;
	battle_commands = actor.battle_commands;
	status_size = 0;
	status.clear();
	changed_class = false;
	class_id = actor.class_id;
	row = -1;
	two_weapon = actor.two_swords_style;
	lock_equipment = actor.fix_equipment;
	auto_battle = actor.auto_battle;
	mighty_guard = actor.super_guard;
	unknown_60 = -1;
}

void RPG::SaveInventory::Setup() {
	party = Data::system.party;
	party_size = party.size();
}

void RPG::SaveMapEvent::Setup(const RPG::Event& event) {
	ID = event.ID;
	position_x = event.x;
	position_y = event.y;
}

void RPG::SaveMapInfo::Setup() {
	position_x = 0;
	position_y = 0;
	lower_tiles.resize(144);
	upper_tiles.resize(144);
	for (int i = 0; i < 144; i++) {
		lower_tiles[i] = i;
		upper_tiles[i] = i;
	}
}

void RPG::SaveMapInfo::Setup(const RPG::Map& map) {
	chipset_id = map.chipset_id;
	parallax_name = map.parallax_name;
	parallax_horz = map.parallax_loop_x;
	parallax_vert = map.parallax_loop_y;
	parallax_horz_auto = map.parallax_auto_loop_x;
	parallax_vert_auto = map.parallax_auto_loop_y;
	parallax_horz_speed = map.parallax_sx;
	parallax_vert_speed = map.parallax_sy;
}

void RPG::SaveMapInfo::Setup(const RPG::MapInfo& map_info) {
	encounter_rate = map_info.encounter_steps;
}

void RPG::SaveSystem::Setup() {
	const RPG::System& system = Data::system;
	screen = 0;
	frame_count = 0;
	graphics_name = system.system_name;
	switches_size = Data::switches.size();
	switches.clear();
	switches.resize(switches_size);
	variables_size = Data::variables.size();
	variables.clear();
	variables.resize(variables_size);
	face_name = "";
	face_id = -1;
	face_right = false;
	face_flip = false;
	transparent = false;
	unknown_3d = -1;
	title_music = system.title_music;
	battle_music = system.battle_music;
	battle_end_music = system.battle_end_music;
	inn_music = system.inn_music;
	// current_music
	// unknown1_music FIXME
	// unknown2_music FIXME
	// stored_music
	boat_music = system.boat_music;
	ship_music = system.ship_music;
	airship_music = system.airship_music;
	gameover_music = system.gameover_music;
	cursor_se = system.cursor_se;
	decision_se = system.decision_se;
	cancel_se = system.cancel_se;
	buzzer_se = system.buzzer_se;
	battle_se = system.battle_se;
	escape_se = system.escape_se;
	enemy_attack_se = system.enemy_attack_se;
	enemy_damaged_se = system.enemy_damaged_se;
	actor_damaged_se = system.actor_damaged_se;
	dodge_se = system.dodge_se;
	enemy_death_se = system.enemy_death_se;
	item_se = system.item_se;
	transition_out = system.transition_out;
	transition_in = system.transition_in;
	battle_start_fadeout = system.battle_start_fadeout;
	battle_start_fadein = system.battle_start_fadein;
	battle_end_fadeout = system.battle_end_fadeout;
	battle_end_fadein = system.battle_end_fadein;
	teleport_allowed = true;
	escape_allowed = true;
	save_allowed = true;
	menu_allowed = true;
	background = "";
	save_count = 0;
	save_slot = -1;
}

void RPG::Save::Setup() {
	system.Setup();
	screen = RPG::SaveScreen();
	pictures.clear();
	pictures.resize(50);
	for (int i = 1; i <= (int)pictures.size(); i++) {
		pictures[i - 1].ID = i;
	}
	actors.clear();
	actors.resize(Data::actors.size());
	for (int i = 1; i <= (int) actors.size(); i++)
		actors[i - 1].Setup(i);
	map_info.Setup();
}

void RPG::Actor::Setup() {
	if (Data::system.ldb_id == 2003) {
		final_level = final_level == -1 ? 99 : final_level;
		exp_base = exp_base == -1 ? 300 : exp_base;
		exp_inflation = exp_inflation == -1 ? 300 : exp_inflation;
	}
	else {
		final_level = final_level == -1 ? 50 : final_level;
		exp_base = exp_base == -1 ? 30 : exp_base;
		exp_inflation = exp_inflation == -1 ? 30 : exp_inflation;
	}
	parameters.Setup(final_level);
}

void RPG::MapInfo::Init() {
	music.name = "(OFF)";
}

void RPG::Chipset::Init() {
	terrain_data.resize(162, 1);
	passable_data_lower.resize(162, 15);
	passable_data_upper.resize(162, 15);
}

void RPG::Parameters::Setup(int final_level) {
	maxhp.resize(final_level, 1);
	maxsp.resize(final_level, 0);
	attack.resize(final_level, 1);
	defense.resize(final_level, 1);
	spirit.resize(final_level, 1);
	agility.resize(final_level, 1);
}
<|endoftext|>


<commit_before>// Copyright (c) 2016 The Zcash developers
// Original code from: https://gist.github.com/laanwj/0e689cfa37b52bcbbb44

/*

To set up a new alert system
----------------------------

Create a new alert key pair:
openssl ecparam -name secp256k1 -genkey -param_enc explicit -outform PEM -out data.pem

Get the private key in hex:
openssl ec -in data.pem -outform DER | tail -c 279 | xxd -p -c 279

Get the public key in hex:
openssl ec -in data.pem -pubout -outform DER | tail -c 65 | xxd -p -c 65

Update the public keys found in chainparams.cpp.

To send an alert message
------------------------

Copy the private keys into alertkeys.h.

Modify the alert parameters, id and message found in this file.

Build and run with -sendalert or -printalert.

./zcashd -printtoconsole -sendalert

One minute after starting up, the alert will be broadcast. It is then
flooded through the network until the nRelayUntil time, and will be
active until nExpiration OR the alert is cancelled.

If you make a mistake, send another alert with nCancel set to cancel
the bad alert.

*/

#include "main.h"
#include "net.h"
#include "alert.h"
#include "init.h"

#include "util.h"
#include "utiltime.h"
#include "key.h"
#include "clientversion.h"
#include "chainparams.h"

#include "alertkeys.h"

static const int64_t DAYS = 24 * 60 * 60;

void ThreadSendAlert()
{
    if (!mapArgs.count("-sendalert") && !mapArgs.count("-printalert"))
        return;

    MilliSleep(60*1000); // Wait a minute so we get connected

    //
    // Alerts are relayed around the network until nRelayUntil, flood
    // filling to every node.
    // After the relay time is past, new nodes are told about alerts
    // when they connect to peers, until either nExpiration or
    // the alert is cancelled by a newer alert.
    // Nodes never save alerts to disk, they are in-memory-only.
    //
    CAlert alert;
    alert.nRelayUntil   = GetTime() + 15 * 60;
    alert.nExpiration   = GetTime() + 365 * 60 * 60;
    alert.nID           = 1040;  // use https://en.bitcoin.it/wiki/Alerts to keep track of alert IDs
    alert.nCancel       = 0;   // cancels previous messages up to this ID number

    // These versions are protocol versions
    // 60002 : 0.7.*
    // 70001 : 0.8.*
    // 70002 : 0.9.*
    alert.nMinVer       = 70002;
    alert.nMaxVer       = 70002;

    //
    // main.cpp:
    //  1000 for Misc warnings like out of disk space and clock is wrong
    //  2000 for longer invalid proof-of-work chain
    //  Higher numbers mean higher priority
    alert.nPriority     = 5000;
    alert.strComment    = "";
    alert.strStatusBar  = "URGENT: Upgrade required: see https://z.cash";

    // Set specific client version/versions here. If setSubVer is empty, no filtering on subver is done:
    // alert.setSubVer.insert(std::string("/Satoshi:0.7.2/"));

    // Sign
    const CChainParams& chainparams = Params();
    std::string networkID = chainparams.NetworkIDString();
    bool fIsTestNet = networkID.compare("test") == 0;
    std::vector<unsigned char> vchTmp(ParseHex(fIsTestNet ? pszTestNetPrivKey : pszPrivKey));
    CPrivKey vchPrivKey(vchTmp.begin(), vchTmp.end());

    CDataStream sMsg(SER_NETWORK, CLIENT_VERSION);
    sMsg << *(CUnsignedAlert*)&alert;
    alert.vchMsg = std::vector<unsigned char>(sMsg.begin(), sMsg.end());
    CKey key;
    if (!key.SetPrivKey(vchPrivKey, false))
    {
        printf("ThreadSendAlert() : key.SetPrivKey failed\n");
        return;
    }
    if (!key.Sign(Hash(alert.vchMsg.begin(), alert.vchMsg.end()), alert.vchSig))
    {
        printf("ThreadSendAlert() : key.Sign failed\n");
        return;
    }

    // Test
    CDataStream sBuffer(SER_NETWORK, CLIENT_VERSION);
    sBuffer << alert;
    CAlert alert2;
    sBuffer >> alert2;
    if (!alert2.CheckSignature(chainparams.AlertKey()))
    {
        printf("ThreadSendAlert() : CheckSignature failed\n");
        return;
    }
    assert(alert2.vchMsg == alert.vchMsg);
    assert(alert2.vchSig == alert.vchSig);
    alert.SetNull();
    printf("\nThreadSendAlert:\n");
    printf("hash=%s\n", alert2.GetHash().ToString().c_str());
    printf("%s\n", alert2.ToString().c_str());
    printf("vchMsg=%s\n", HexStr(alert2.vchMsg).c_str());
    printf("vchSig=%s\n", HexStr(alert2.vchSig).c_str());

    // Confirm
    if (!mapArgs.count("-sendalert"))
        return;
    while (vNodes.size() < 1 && !ShutdownRequested())
        MilliSleep(500);
    if (ShutdownRequested())
        return;
#if 0
#ifdef QT_GUI
    if (ThreadSafeMessageBox("Send alert?", "ThreadSendAlert", wxYES_NO | wxNO_DEFAULT) != wxYES)
        return;
    if (ThreadSafeMessageBox("Send alert, are you sure?", "ThreadSendAlert", wxYES_NO | wxNO_DEFAULT) != wxYES)
    {
        ThreadSafeMessageBox("Nothing sent", "ThreadSendAlert", wxOK);
        return;
    }
#endif
#endif
    // Send
    printf("ThreadSendAlert() : Sending alert\n");
    int nSent = 0;
    {
        LOCK(cs_vNodes);
        BOOST_FOREACH(CNode* pnode, vNodes)
        {
            if (alert2.RelayTo(pnode))
            {
                printf("ThreadSendAlert() : Sent alert to %s\n", pnode->addr.ToString().c_str());
                nSent++;
            }
        }
    }
    printf("ThreadSendAlert() : Alert sent to %d nodes\n", nSent);
}
<commit_msg>Update alert ID start value and URL in comment.<commit_after>// Copyright (c) 2016 The Zcash developers
// Original code from: https://gist.github.com/laanwj/0e689cfa37b52bcbbb44

/*

To set up a new alert system
----------------------------

Create a new alert key pair:
openssl ecparam -name secp256k1 -genkey -param_enc explicit -outform PEM -out data.pem

Get the private key in hex:
openssl ec -in data.pem -outform DER | tail -c 279 | xxd -p -c 279

Get the public key in hex:
openssl ec -in data.pem -pubout -outform DER | tail -c 65 | xxd -p -c 65

Update the public keys found in chainparams.cpp.

To send an alert message
------------------------

Copy the private keys into alertkeys.h.

Modify the alert parameters, id and message found in this file.

Build and run with -sendalert or -printalert.

./zcashd -printtoconsole -sendalert

One minute after starting up, the alert will be broadcast. It is then
flooded through the network until the nRelayUntil time, and will be
active until nExpiration OR the alert is cancelled.

If you make a mistake, send another alert with nCancel set to cancel
the bad alert.

*/

#include "main.h"
#include "net.h"
#include "alert.h"
#include "init.h"

#include "util.h"
#include "utiltime.h"
#include "key.h"
#include "clientversion.h"
#include "chainparams.h"

#include "alertkeys.h"

static const int64_t DAYS = 24 * 60 * 60;

void ThreadSendAlert()
{
    if (!mapArgs.count("-sendalert") && !mapArgs.count("-printalert"))
        return;

    MilliSleep(60*1000); // Wait a minute so we get connected

    //
    // Alerts are relayed around the network until nRelayUntil, flood
    // filling to every node.
    // After the relay time is past, new nodes are told about alerts
    // when they connect to peers, until either nExpiration or
    // the alert is cancelled by a newer alert.
    // Nodes never save alerts to disk, they are in-memory-only.
    //
    CAlert alert;
    alert.nRelayUntil   = GetTime() + 15 * 60;
    alert.nExpiration   = GetTime() + 365 * 60 * 60;
    alert.nID           = 1000;  // use https://z.cash to keep track of alert IDs
    alert.nCancel       = 0;   // cancels previous messages up to this ID number

    // These versions are protocol versions
    // 60002 : 0.7.*
    // 70001 : 0.8.*
    // 70002 : 0.9.*
    alert.nMinVer       = 70002;
    alert.nMaxVer       = 70002;

    //
    // main.cpp:
    //  1000 for Misc warnings like out of disk space and clock is wrong
    //  2000 for longer invalid proof-of-work chain
    //  Higher numbers mean higher priority
    alert.nPriority     = 5000;
    alert.strComment    = "";
    alert.strStatusBar  = "URGENT: Upgrade required: see https://z.cash";

    // Set specific client version/versions here. If setSubVer is empty, no filtering on subver is done:
    // alert.setSubVer.insert(std::string("/Satoshi:0.7.2/"));

    // Sign
    const CChainParams& chainparams = Params();
    std::string networkID = chainparams.NetworkIDString();
    bool fIsTestNet = networkID.compare("test") == 0;
    std::vector<unsigned char> vchTmp(ParseHex(fIsTestNet ? pszTestNetPrivKey : pszPrivKey));
    CPrivKey vchPrivKey(vchTmp.begin(), vchTmp.end());

    CDataStream sMsg(SER_NETWORK, CLIENT_VERSION);
    sMsg << *(CUnsignedAlert*)&alert;
    alert.vchMsg = std::vector<unsigned char>(sMsg.begin(), sMsg.end());
    CKey key;
    if (!key.SetPrivKey(vchPrivKey, false))
    {
        printf("ThreadSendAlert() : key.SetPrivKey failed\n");
        return;
    }
    if (!key.Sign(Hash(alert.vchMsg.begin(), alert.vchMsg.end()), alert.vchSig))
    {
        printf("ThreadSendAlert() : key.Sign failed\n");
        return;
    }

    // Test
    CDataStream sBuffer(SER_NETWORK, CLIENT_VERSION);
    sBuffer << alert;
    CAlert alert2;
    sBuffer >> alert2;
    if (!alert2.CheckSignature(chainparams.AlertKey()))
    {
        printf("ThreadSendAlert() : CheckSignature failed\n");
        return;
    }
    assert(alert2.vchMsg == alert.vchMsg);
    assert(alert2.vchSig == alert.vchSig);
    alert.SetNull();
    printf("\nThreadSendAlert:\n");
    printf("hash=%s\n", alert2.GetHash().ToString().c_str());
    printf("%s\n", alert2.ToString().c_str());
    printf("vchMsg=%s\n", HexStr(alert2.vchMsg).c_str());
    printf("vchSig=%s\n", HexStr(alert2.vchSig).c_str());

    // Confirm
    if (!mapArgs.count("-sendalert"))
        return;
    while (vNodes.size() < 1 && !ShutdownRequested())
        MilliSleep(500);
    if (ShutdownRequested())
        return;
#if 0
#ifdef QT_GUI
    if (ThreadSafeMessageBox("Send alert?", "ThreadSendAlert", wxYES_NO | wxNO_DEFAULT) != wxYES)
        return;
    if (ThreadSafeMessageBox("Send alert, are you sure?", "ThreadSendAlert", wxYES_NO | wxNO_DEFAULT) != wxYES)
    {
        ThreadSafeMessageBox("Nothing sent", "ThreadSendAlert", wxOK);
        return;
    }
#endif
#endif
    // Send
    printf("ThreadSendAlert() : Sending alert\n");
    int nSent = 0;
    {
        LOCK(cs_vNodes);
        BOOST_FOREACH(CNode* pnode, vNodes)
        {
            if (alert2.RelayTo(pnode))
            {
                printf("ThreadSendAlert() : Sent alert to %s\n", pnode->addr.ToString().c_str());
                nSent++;
            }
        }
    }
    printf("ThreadSendAlert() : Alert sent to %d nodes\n", nSent);
}
<|endoftext|>


<commit_before>//
//  simplesim.cpp
//  qsim
//
//  Created by Ben Langmead on 9/12/15.
//  Copyright (c) 2015 JHU. All rights reserved.
//

#include <stdlib.h>
#include <vector>
#include <inttypes.h>
#include "simplesim.h"
#include "fasta.h"
#include "rnglib.hpp"

using namespace std;

/**
 * Return draw from binomial distribution with given n, p.
 */
static inline size_t draw_binomial(size_t n, float p) {
	return (size_t)ignbin((int)n, p);
}

static const char * startswith = "!!ts!!";
static const char * sep = "!!ts-sep!!";

/**
 * Mutate given simulated read in-place.
 */
void SimulatedRead::mutate(const char *seq) {
	const size_t newsz = strlen(qual_);
	while(newsz >= seq_buf_len_) {
		double_seq_buf();
	}
	size_t rdoff = 0, rfoff = 0;
	const size_t edlen = strlen(edit_xscript_);
	for(size_t i = 0; i < edlen; i++) {
		if(edit_xscript_[i] == '=') {
			seq_buf_[rdoff++] = seq[rfoff++];
		} else if(edit_xscript_[i] == 'X') {
			do {
				seq_buf_[rdoff] = "ACGT"[(int)(r4_uni_01() * 4)];
			} while(seq_buf_[rdoff] == seq[rfoff]);
			rdoff++;
			rfoff++;
		} else if(edit_xscript_[i] == 'I') {
			seq_buf_[rdoff++] = "ACGT"[(int)(r4_uni_01() * 4)];
		} else if(edit_xscript_[i] == 'D') {
			rfoff++;
		} else {
			throw 1;
		}
	}
	assert(rdoff == newsz);
	seq_buf_[rdoff] = '\0';
	assert(newsz == strlen(seq_buf_));
}

/**
 * Mapping from ASCII characters for ambiguous nucleotides into masks:
 */
char asc2dnacomp[] = {
	/*   0 */ 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
	/*  16 */ 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
	/*  32 */ 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,'-',  0,  0,
	/*  48 */ 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
	/*  64 */ 0,'T','V','G','H',  0,  0,'C','D',  0,  0,'M',  0,'K','N',  0,
	/*    A   B   C   D           G   H           K       M   N */
	/*  80 */ 0,  0,'Y','S','A',  0,'B','W',  0,'R',  0,  0,  0,  0,  0,  0,
	/*        R   S   T       V   W       Y */
	/*  96 */ 0,'T','V','G','H',  0,  0,'C','D',  0,  0,'M',  0,'K','N',  0,
	/*   a   b   c   d           g   h           k       m   n */
	/* 112 */ 0,  0,'Y','S','A',  0,'B','W',  0,'R',  0,  0,  0,  0,  0,  0,
	/*        r   s   t       v   w       y */
	/* 128 */ 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
	/* 144 */ 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
	/* 160 */ 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
	/* 176 */ 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
	/* 192 */ 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
	/* 208 */ 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
	/* 224 */ 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
	/* 240 */ 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0
};

/**
 * Write a simulated read to an output file.
 */
void SimulatedRead::write_unpaired(FILE *fh, const char *typ) {
	size_t len = strlen(qual_);
	fprintf(fh, "@%s%s%s%s%c%s%" PRIuPTR "%s%d%s%s\n",
			startswith, sep,
			refid_, sep,
			fw_ ? '+' : '-', sep,
			(uintptr_t)refoff_, sep,
			score_, sep,
			typ);
	if(fw_) {
		fputs(seq_buf_, fh);
	} else {
		for(size_t i = 0; i < len; i++) {
			fputc(asc2dnacomp[(int)seq_buf_[len-i-1]], fh);
		}
	}
	fputs("\n+\n", fh);
	if(fw_) {
		fputs(qual_, fh);
	} else {
		for(size_t i = 0; i < len; i++) {
			fputc(qual_[len-i-1], fh);
		}
	}
	fputc('\n', fh);
}

/**
 * Simulate a batch of reads
 */
void StreamingSimulator::simulate_batch(
	float fraction,
	size_t min_u,
	size_t min_c,
	size_t min_d,
	size_t min_b)
{
	size_t nc = 0, nd = 0, nu = 0, nb = 0;
	if(!model_u_.empty()) {
		nu = std::max((size_t)(fraction * model_u_.num_added()), min_u);
	}
	if(!model_b_.empty()) {
		nb = std::max((size_t)(fraction * model_b_.num_added()), min_b);
	}
	if(!model_c_.empty()) {
		nc = std::max((size_t)(fraction * model_c_.num_added()), min_c);
	}
	if(!model_d_.empty()) {
		nd = std::max((size_t)(fraction * model_d_.num_added()), min_d);
	}
	assert(nu + nb + nc + nd > 0);

	std::string refid, refid_full;
	size_t refoff = 0, retsz = 0;
	SimulatedRead rd1, rd2;
	while(true) {
		const char * buf = fa_.next(refid, refid_full, refoff, retsz);
		if(buf == NULL && fa_.done()) {
			break;
		}
		size_t nu_chances = retsz - model_u_.avg_len() + 1;
		size_t nb_chances = retsz - model_b_.avg_len() + 1;
		size_t nc_chances = retsz - model_c_.avg_len() + 1;
		size_t nd_chances = retsz - model_d_.avg_len() + 1;
		size_t nu_samp = draw_binomial(nu, float(nu_chances) / tot_fasta_len_);
		size_t nb_samp = draw_binomial(nb, float(nb_chances) / tot_fasta_len_);
		size_t nc_samp = draw_binomial(nc, float(nc_chances) / tot_fasta_len_);
		size_t nd_samp = draw_binomial(nd, float(nd_chances) / tot_fasta_len_);
		for(size_t i = 0; i < nu_samp; i++) {
			const TemplateUnpaired &t = model_u_.draw();
			size_t nslots = retsz - olap_; // is this right?
			size_t off = (size_t)(r4_uni_01() * nslots);
			assert(off < nslots);
			rd1.init(
				buf + off,
				t.qual_,
				t.edit_xscript_,
				t.fw_flag_ == 'T',
				t.best_score_,
				refid.c_str(),
				refoff);
			rd1.write_unpaired(fh_u_, "unp");
		}
		for(size_t i = 0; i < nb_samp; i++) {
			const TemplateUnpaired &t = model_b_.draw();
			size_t nslots = retsz - olap_; // is this right?
			size_t off = (size_t)(r4_uni_01() * nslots);
			assert(off < nslots);
			rd1.init(
				buf + off,
				t.qual_,
				t.edit_xscript_,
				t.fw_flag_ == 'T',
				t.best_score_,
				refid.c_str(),
				refoff);
			rd1.write_unpaired(fh_u_, t.mate_flag_ == '1' ? "bad_end_mate1" : "bad_end_mate2");
		}
		for(size_t i = 0; i < nc_samp; i++) {
			const TemplatePaired &t = model_c_.draw();
			size_t nslots = retsz - olap_; // is this right?
			size_t off = (size_t)(r4_uni_01() * nslots);
			assert(off < nslots);
			const char *upstream_l = buf + off;
			const char *downstream_l = buf + t.fraglen_ - t.len_2_;
		}
		for(size_t i = 0; i < nd_samp; i++) {
			const TemplatePaired &t = model_d_.draw();
			size_t nslots = retsz - olap_; // is this right?
			size_t off = (size_t)(r4_uni_01() * nslots);
			assert(off < nslots);
		}
	}
}

#ifdef SIMPLESIM_MAIN

#include <fstream>
#include <iostream>

static void test1() {
	SimulatedRead rd;
	const char *ref = "ACGT";
	const char *qual = "ABCD";
	const char *edit_xscript = "====";
	rd.init(ref, qual, edit_xscript,true, 0, "r1", 0);
	assert(strcmp(rd.mutated_seq(), "ACGT") == 0);
	assert(strcmp(rd.qual(), "ABCD") == 0);
	assert(strcmp(rd.edit_xscript(), "====") == 0);
}

static void test2() {
	SimulatedRead rd;
	const char *ref = "AACC";
	const char *qual = "ABCD";
	const char *edit_xscript = "====";
	rd.init(ref, qual, edit_xscript,false, 0, "r1", 0);
	assert(strcmp(rd.mutated_seq(), "AACC") == 0);
	assert(strcmp(rd.qual(), "ABCD") == 0);
	assert(strcmp(rd.edit_xscript(), "====") == 0);
}

int main(void) {
	test1();
	test2();
	cerr << "ALL TESTS PASSED" << endl;
}
#endif

<commit_msg>added several tests<commit_after>//
//  simplesim.cpp
//  qsim
//
//  Created by Ben Langmead on 9/12/15.
//  Copyright (c) 2015 JHU. All rights reserved.
//

#include <stdlib.h>
#include <vector>
#include <inttypes.h>
#include "simplesim.h"
#include "fasta.h"
#include "rnglib.hpp"

using namespace std;

/**
 * Return draw from binomial distribution with given n, p.
 */
static inline size_t draw_binomial(size_t n, float p) {
	return (size_t)ignbin((int)n, p);
}

static const char * startswith = "!!ts!!";
static const char * sep = "!!ts-sep!!";

/**
 * Mutate given simulated read in-place.
 */
void SimulatedRead::mutate(const char *seq) {
	const size_t newsz = strlen(qual_);
	while(newsz >= seq_buf_len_) {
		double_seq_buf();
	}
	size_t rdoff = 0, rfoff = 0;
	const size_t edlen = strlen(edit_xscript_);
	for(size_t i = 0; i < edlen; i++) {
		if(edit_xscript_[i] == '=') {
			seq_buf_[rdoff++] = seq[rfoff++];
		} else if(edit_xscript_[i] == 'X') {
			do {
				seq_buf_[rdoff] = "ACGT"[(int)(r4_uni_01() * 4)];
			} while(seq_buf_[rdoff] == seq[rfoff]);
			rdoff++;
			rfoff++;
		} else if(edit_xscript_[i] == 'I') {
			seq_buf_[rdoff++] = "ACGT"[(int)(r4_uni_01() * 4)];
		} else if(edit_xscript_[i] == 'D') {
			rfoff++;
		} else {
			throw 1;
		}
	}
	assert(rdoff == newsz);
	seq_buf_[rdoff] = '\0';
	assert(newsz == strlen(seq_buf_));
}

/**
 * Mapping from ASCII characters for ambiguous nucleotides into masks:
 */
char asc2dnacomp[] = {
	/*   0 */ 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
	/*  16 */ 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
	/*  32 */ 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,'-',  0,  0,
	/*  48 */ 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
	/*  64 */ 0,'T','V','G','H',  0,  0,'C','D',  0,  0,'M',  0,'K','N',  0,
	/*    A   B   C   D           G   H           K       M   N */
	/*  80 */ 0,  0,'Y','S','A',  0,'B','W',  0,'R',  0,  0,  0,  0,  0,  0,
	/*        R   S   T       V   W       Y */
	/*  96 */ 0,'T','V','G','H',  0,  0,'C','D',  0,  0,'M',  0,'K','N',  0,
	/*   a   b   c   d           g   h           k       m   n */
	/* 112 */ 0,  0,'Y','S','A',  0,'B','W',  0,'R',  0,  0,  0,  0,  0,  0,
	/*        r   s   t       v   w       y */
	/* 128 */ 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
	/* 144 */ 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
	/* 160 */ 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
	/* 176 */ 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
	/* 192 */ 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
	/* 208 */ 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
	/* 224 */ 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
	/* 240 */ 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0
};

/**
 * Write a simulated read to an output file.
 */
void SimulatedRead::write_unpaired(FILE *fh, const char *typ) {
	size_t len = strlen(qual_);
	fprintf(fh, "@%s%s%s%s%c%s%" PRIuPTR "%s%d%s%s\n",
			startswith, sep,
			refid_, sep,
			fw_ ? '+' : '-', sep,
			(uintptr_t)refoff_, sep,
			score_, sep,
			typ);
	if(fw_) {
		fputs(seq_buf_, fh);
	} else {
		for(size_t i = 0; i < len; i++) {
			fputc(asc2dnacomp[(int)seq_buf_[len-i-1]], fh);
		}
	}
	fputs("\n+\n", fh);
	if(fw_) {
		fputs(qual_, fh);
	} else {
		for(size_t i = 0; i < len; i++) {
			fputc(qual_[len-i-1], fh);
		}
	}
	fputc('\n', fh);
}

/**
 * Simulate a batch of reads
 */
void StreamingSimulator::simulate_batch(
	float fraction,
	size_t min_u,
	size_t min_c,
	size_t min_d,
	size_t min_b)
{
	size_t nc = 0, nd = 0, nu = 0, nb = 0;
	if(!model_u_.empty()) {
		nu = std::max((size_t)(fraction * model_u_.num_added()), min_u);
	}
	if(!model_b_.empty()) {
		nb = std::max((size_t)(fraction * model_b_.num_added()), min_b);
	}
	if(!model_c_.empty()) {
		nc = std::max((size_t)(fraction * model_c_.num_added()), min_c);
	}
	if(!model_d_.empty()) {
		nd = std::max((size_t)(fraction * model_d_.num_added()), min_d);
	}
	assert(nu + nb + nc + nd > 0);

	std::string refid, refid_full;
	size_t refoff = 0, retsz = 0;
	SimulatedRead rd1, rd2;
	while(true) {
		const char * buf = fa_.next(refid, refid_full, refoff, retsz);
		if(buf == NULL && fa_.done()) {
			break;
		}
		size_t nu_chances = retsz - model_u_.avg_len() + 1;
		size_t nb_chances = retsz - model_b_.avg_len() + 1;
		size_t nc_chances = retsz - model_c_.avg_len() + 1;
		size_t nd_chances = retsz - model_d_.avg_len() + 1;
		size_t nu_samp = draw_binomial(nu, float(nu_chances) / tot_fasta_len_);
		size_t nb_samp = draw_binomial(nb, float(nb_chances) / tot_fasta_len_);
		size_t nc_samp = draw_binomial(nc, float(nc_chances) / tot_fasta_len_);
		size_t nd_samp = draw_binomial(nd, float(nd_chances) / tot_fasta_len_);
		for(size_t i = 0; i < nu_samp; i++) {
			const TemplateUnpaired &t = model_u_.draw();
			size_t nslots = retsz - olap_; // is this right?
			size_t off = (size_t)(r4_uni_01() * nslots);
			assert(off < nslots);
			rd1.init(
				buf + off,
				t.qual_,
				t.edit_xscript_,
				t.fw_flag_ == 'T',
				t.best_score_,
				refid.c_str(),
				refoff);
			rd1.write_unpaired(fh_u_, "unp");
		}
		for(size_t i = 0; i < nb_samp; i++) {
			const TemplateUnpaired &t = model_b_.draw();
			size_t nslots = retsz - olap_; // is this right?
			size_t off = (size_t)(r4_uni_01() * nslots);
			assert(off < nslots);
			rd1.init(
				buf + off,
				t.qual_,
				t.edit_xscript_,
				t.fw_flag_ == 'T',
				t.best_score_,
				refid.c_str(),
				refoff);
			rd1.write_unpaired(fh_u_, t.mate_flag_ == '1' ? "bad_end_mate1" : "bad_end_mate2");
		}
		for(size_t i = 0; i < nc_samp; i++) {
			const TemplatePaired &t = model_c_.draw();
			size_t nslots = retsz - olap_; // is this right?
			size_t off = (size_t)(r4_uni_01() * nslots);
			assert(off < nslots);
			const char *upstream_l = buf + off;
			const char *downstream_l = buf + t.fraglen_ - t.len_2_;
		}
		for(size_t i = 0; i < nd_samp; i++) {
			const TemplatePaired &t = model_d_.draw();
			size_t nslots = retsz - olap_; // is this right?
			size_t off = (size_t)(r4_uni_01() * nslots);
			assert(off < nslots);
		}
	}
}

#ifdef SIMPLESIM_MAIN

#include <fstream>
#include <iostream>

static void test1() {
	SimulatedRead rd;
	const char *ref = "ACGT";
	const char *qual = "ABCD";
	const char *edit_xscript = "====";
	rd.init(ref, qual, edit_xscript,true, 0, "r1", 0);
	assert(strcmp(rd.mutated_seq(), "ACGT") == 0);
	assert(strcmp(rd.qual(), "ABCD") == 0);
	assert(strcmp(rd.edit_xscript(), "====") == 0);
}

static void test2() {
	SimulatedRead rd;
	const char *ref = "AACC";
	const char *qual = "ABCD";
	const char *edit_xscript = "====";
	rd.init(ref, qual, edit_xscript,false, 0, "r1", 0);
	assert(strcmp(rd.mutated_seq(), "AACC") == 0);
	assert(strcmp(rd.qual(), "ABCD") == 0);
	assert(strcmp(rd.edit_xscript(), "====") == 0);
}

static void test3() {
	SimulatedRead rd;
	const char *ref = "ACGT";
	const char *qual = "ABCD";
	const char *edit_xscript = "=X==";
	rd.init(ref, qual, edit_xscript,true, 0, "r1", 0);
	assert(strcmp(rd.mutated_seq(), "ACGT") != 0);
	assert(rd.mutated_seq()[0] == 'A');
	assert(rd.mutated_seq()[1] != 'C');
	assert(rd.mutated_seq()[2] == 'G');
	assert(rd.mutated_seq()[3] == 'T');
	assert(strcmp(rd.qual(), "ABCD") == 0);
	assert(strcmp(rd.edit_xscript(), "=X==") == 0);
}

static void test4() {
	SimulatedRead rd;
	const char *ref = "ACGT";
	const char *qual = "ABC";
	const char *edit_xscript = "=D==";
	rd.init(ref, qual, edit_xscript,true, 0, "r1", 0);
	assert(strcmp(rd.mutated_seq(), "AGT") == 0);
	assert(strcmp(rd.qual(), "ABC") == 0);
	assert(strcmp(rd.edit_xscript(), "=D==") == 0);
}

static void test5() {
	SimulatedRead rd;
	const char *ref = "AGT";
	const char *qual = "ABCD";
	const char *edit_xscript = "=I==";
	rd.init(ref, qual, edit_xscript,true, 0, "r1", 0);
	assert(rd.mutated_seq()[0] == 'A');
	assert(rd.mutated_seq()[2] == 'G');
	assert(rd.mutated_seq()[3] == 'T');
	assert(strcmp(rd.qual(), "ABCD") == 0);
	assert(strcmp(rd.edit_xscript(), "=I==") == 0);
}

/**
 * A test where we read the FASTQ output and confirm it makes sense.
 */
static void test6() {
	SimulatedRead rd;
	const char *ref = "ACGT";
	const char *qual = "ABCD";
	const char *edit_xscript = "====";
	const char *fn = ".test6.tmp";
	{
		FILE *fh = fopen(fn, "wb");
		rd.init(ref, qual, edit_xscript, true, 0, "r1", 0);
		rd.write_unpaired(fh, "hello");
		fclose(fh);
	}
	ifstream t(fn);
	string str((istreambuf_iterator<char>(t)), istreambuf_iterator<char>());
	assert(str.rfind("\nACGT\n+\nABCD\n") != string::npos);
	remove(fn);
}

static void test7() {
	SimulatedRead rd;
	const char *ref = "AAACC";
	const char *qual = "EDCBA";
	const char *edit_xscript = "=====";
	const char *fn = ".test7.tmp";
	{
		FILE *fh = fopen(fn, "wb");
		rd.init(ref, qual, edit_xscript, false, 0, "r1", 0);
		rd.write_unpaired(fh, "hello");
		fclose(fh);
	}
	ifstream t(fn);
	string str((istreambuf_iterator<char>(t)), istreambuf_iterator<char>());
	assert(str.rfind("\nGGTTT\n+\nABCDE\n") != string::npos);
	remove(fn);
}

int main(void) {
	test1();
	test2();
	test3();
	test4();
	test5();
	test6();
	test7();
	cerr << "ALL TESTS PASSED" << endl;
}
#endif

<|endoftext|>