<commit_before>/* Copyright (c) 2010-2013, AOYAMA Kazuharu
 * All rights reserved.
 *
 * This software may be used and distributed according to the terms of
 * the New BSD License, which is incorporated herein by reference.
 */

#include <QStringList>
#include <TGlobal>
#include <TWebApplication>
#include <TLogger>
#include <TLog>
#include <TActionContext>
#include <TActionThread>
#include <TActionWorker>
#include <TActionForkProcess>
#include <stdlib.h>
#include <limits.h>
#include "tloggerfactory.h"
#include "tsharedmemorylogstream.h"
#include "tbasiclogstream.h"
#include "tsystemglobal.h"
#ifdef Q_OS_WIN
# include <Windows.h>
#endif
#undef tDebug
#undef tTrace
#define APPLICATION_ABORT  "ApplicationAbortOnFatal"

static TAbstractLogStream *stream = 0;

/*!
  Sets up all the loggers set in the logger.ini.
  This function is for internal use only.
*/
void tSetupLoggers()
{
    QList<TLogger *> loggers;
    QStringList loggerList = Tf::app()->loggerSettings().value("Loggers").toString().split(' ', QString::SkipEmptyParts);

    for (QStringListIterator i(loggerList); i.hasNext(); ) {
        TLogger *lgr = TLoggerFactory::create(i.next());
        if (lgr) {
            loggers << lgr;
            tSystemDebug("Logger added: %s", qPrintable(lgr->key()));
        }
    }

    if (!stream) {
        if (Tf::app()->multiProcessingModule() == TWebApplication::Prefork) {
            stream = new TSharedMemoryLogStream(loggers, 4096, qApp);
        } else {
            stream = new TBasicLogStream(loggers, qApp);
        }
    }
}

static void tMessage(int priority, const char *msg, va_list ap)
{
    TLog log(priority, QString().vsprintf(msg, ap).toLocal8Bit());
    if (stream)
        stream->writeLog(log);
}

static void tFlushMessage()
{
    if (stream)
        stream->flush();
}

/*!
  Writes the fatal message \a msg to the file app.log.
*/
void tFatal(const char *msg, ...)
{
    va_list ap;
    va_start(ap, msg);
    tMessage(TLogger::Fatal, msg, ap);
    va_end(ap);
    tFlushMessage();

    if (Tf::app()->appSettings().value(APPLICATION_ABORT).toBool()) {
#if (defined(Q_OS_UNIX) || defined(Q_CC_MINGW))
        abort(); // trap; generates core dump
#else
        _exit(-1);
#endif
    }
}

/*!
  Writes the error message \a msg to the file app.log.
*/
void tError(const char *msg, ...)
{
    va_list ap;
    va_start(ap, msg);
    tMessage(TLogger::Error, msg, ap);
    va_end(ap);
    tFlushMessage();
}

/*!
  Writes the warning message \a msg to the file app.log.
*/
void tWarn(const char *msg, ...)
{
    va_list ap;
    va_start(ap, msg);
    tMessage(TLogger::Warn, msg, ap);
    va_end(ap);
    tFlushMessage();
}

/*!
  Writes the information message \a msg to the file app.log.
*/
void tInfo(const char *msg, ...)
{
    va_list ap;
    va_start(ap, msg);
    tMessage(TLogger::Info, msg, ap);
    va_end(ap);
}

/*!
  Writes the debug message \a msg to the file app.log.
*/
void tDebug(const char *msg, ...)
{
    va_list ap;
    va_start(ap, msg);
    tMessage(TLogger::Debug, msg, ap);
    va_end(ap);
}

/*!
  Writes the trace message \a msg to the file app.log.
*/
void tTrace(const char *msg, ...)
{
    va_list ap;
    va_start(ap, msg);
    tMessage(TLogger::Trace, msg, ap);
    va_end(ap);
}

/*!
  Returns a global pointer referring to the unique application object.
*/
TWebApplication *Tf::app()
{
    return static_cast<TWebApplication *>(qApp);
}

/*!
  Causes the current thread to sleep for \a msecs milliseconds.
*/
void Tf::msleep(unsigned long msecs)
{
#if defined(Q_OS_WIN)
    ::Sleep(msecs);
#else
    struct timeval tv;
    gettimeofday(&tv, 0);
    struct timespec ti;
    ti.tv_nsec = (tv.tv_usec + (msecs % 1000) * 1000) * 1000;
    ti.tv_sec = tv.tv_sec + (msecs / 1000) + (ti.tv_nsec / 1000000000);
    ti.tv_nsec %= 1000000000;

    pthread_mutex_t mtx;
    pthread_cond_t cnd;

    pthread_mutex_init(&mtx, 0);
    pthread_cond_init(&cnd, 0);

    pthread_mutex_lock(&mtx);
    pthread_cond_timedwait(&cnd, &mtx, &ti);
    pthread_mutex_unlock(&mtx);

    pthread_cond_destroy(&cnd);
    pthread_mutex_destroy(&mtx);
#endif
}

/*!
  Random number generator in the range from 0 to \a max.
  The maximum number of \a max is UINT_MAX.
 */
quint32 Tf::random(quint32 max)
{
    return (quint32)((double)randXor128() * (1.0 + max) / (1.0 + UINT_MAX));
}

/*
  Xorshift random number generator implement
*/
static QMutex randMutex;
static quint32 x = 123456789;
static quint32 y = 362436169;
static quint32 z = 987654321;
static quint32 w = 1;

/*!
  Sets the argument \a seed to be used to generate a new random number sequence
  of xorshift random integers to be returned by randXor128().
  This function is thread-safe.
*/
void Tf::srandXor128(quint32 seed)
{
    QMutexLocker lock(&randMutex);
    w = seed;
    z = w ^ (w >> 8) ^ (w << 5);
}

/*!
  Returns a value between 0 and UINT_MAX, the next number in the current
  sequence of xorshift random integers.
  This function is thread-safe.
*/
quint32 Tf::randXor128()
{
    QMutexLocker lock(&randMutex);
    quint32 t;
    t = x ^ (x << 11);
    x = y;
    y = z;
    z = w;
    w = w ^ (w >> 19) ^ (t ^ (t >> 8));
    return w;
}

TActionContext *Tf::currentContext()
{
    TActionContext *context = 0;

    switch ( Tf::app()->multiProcessingModule() ) {
    case TWebApplication::Prefork:
        context = TActionForkProcess::currentContext();
        if (!context) {
            throw RuntimeException("The current process is not TActionProcess", __FILE__, __LINE__);
        }
        break;

    case TWebApplication::Thread:
        context = qobject_cast<TActionThread *>(QThread::currentThread());
        if (!context) {
            throw RuntimeException("The current thread is not TActionThread", __FILE__, __LINE__);
        }
        break;

    case TWebApplication::Hybrid:
#ifdef Q_OS_LINUX
        context = qobject_cast<TActionWorker *>(QThread::currentThread());
        if (!context) {
            throw RuntimeException("The current thread is not TActionWorker", __FILE__, __LINE__);
        }
#else
        tFatal("Unsupported MPM: hybrid");
#endif
        break;

    default:
        break;
    }
    return context;
}

QSqlDatabase &Tf::currentSqlDatabase(int id)
{
    return currentContext()->getSqlDatabase(id);
}
<commit_msg>modified randXor128(), QMutex unused.<commit_after>/* Copyright (c) 2010-2013, AOYAMA Kazuharu
 * All rights reserved.
 *
 * This software may be used and distributed according to the terms of
 * the New BSD License, which is incorporated herein by reference.
 */

#include <QStringList>
#include <QAtomicPointer>
#include <TGlobal>
#include <TWebApplication>
#include <TLogger>
#include <TLog>
#include <TActionContext>
#include <TActionThread>
#include <TActionWorker>
#include <TActionForkProcess>
#include <stdlib.h>
#include <limits.h>
#include "tloggerfactory.h"
#include "tsharedmemorylogstream.h"
#include "tbasiclogstream.h"
#include "tsystemglobal.h"
#ifdef Q_OS_WIN
# include <Windows.h>
#endif
#undef tDebug
#undef tTrace
#define APPLICATION_ABORT  "ApplicationAbortOnFatal"

static TAbstractLogStream *stream = 0;

/*!
  Sets up all the loggers set in the logger.ini.
  This function is for internal use only.
*/
void tSetupLoggers()
{
    QList<TLogger *> loggers;
    QStringList loggerList = Tf::app()->loggerSettings().value("Loggers").toString().split(' ', QString::SkipEmptyParts);

    for (QStringListIterator i(loggerList); i.hasNext(); ) {
        TLogger *lgr = TLoggerFactory::create(i.next());
        if (lgr) {
            loggers << lgr;
            tSystemDebug("Logger added: %s", qPrintable(lgr->key()));
        }
    }

    if (!stream) {
        if (Tf::app()->multiProcessingModule() == TWebApplication::Prefork) {
            stream = new TSharedMemoryLogStream(loggers, 4096, qApp);
        } else {
            stream = new TBasicLogStream(loggers, qApp);
        }
    }
}

static void tMessage(int priority, const char *msg, va_list ap)
{
    TLog log(priority, QString().vsprintf(msg, ap).toLocal8Bit());
    if (stream)
        stream->writeLog(log);
}

static void tFlushMessage()
{
    if (stream)
        stream->flush();
}

/*!
  Writes the fatal message \a msg to the file app.log.
*/
void tFatal(const char *msg, ...)
{
    va_list ap;
    va_start(ap, msg);
    tMessage(TLogger::Fatal, msg, ap);
    va_end(ap);
    tFlushMessage();

    if (Tf::app()->appSettings().value(APPLICATION_ABORT).toBool()) {
#if (defined(Q_OS_UNIX) || defined(Q_CC_MINGW))
        abort(); // trap; generates core dump
#else
        _exit(-1);
#endif
    }
}

/*!
  Writes the error message \a msg to the file app.log.
*/
void tError(const char *msg, ...)
{
    va_list ap;
    va_start(ap, msg);
    tMessage(TLogger::Error, msg, ap);
    va_end(ap);
    tFlushMessage();
}

/*!
  Writes the warning message \a msg to the file app.log.
*/
void tWarn(const char *msg, ...)
{
    va_list ap;
    va_start(ap, msg);
    tMessage(TLogger::Warn, msg, ap);
    va_end(ap);
    tFlushMessage();
}

/*!
  Writes the information message \a msg to the file app.log.
*/
void tInfo(const char *msg, ...)
{
    va_list ap;
    va_start(ap, msg);
    tMessage(TLogger::Info, msg, ap);
    va_end(ap);
}

/*!
  Writes the debug message \a msg to the file app.log.
*/
void tDebug(const char *msg, ...)
{
    va_list ap;
    va_start(ap, msg);
    tMessage(TLogger::Debug, msg, ap);
    va_end(ap);
}

/*!
  Writes the trace message \a msg to the file app.log.
*/
void tTrace(const char *msg, ...)
{
    va_list ap;
    va_start(ap, msg);
    tMessage(TLogger::Trace, msg, ap);
    va_end(ap);
}

/*!
  Returns a global pointer referring to the unique application object.
*/
TWebApplication *Tf::app()
{
    return static_cast<TWebApplication *>(qApp);
}

/*!
  Causes the current thread to sleep for \a msecs milliseconds.
*/
void Tf::msleep(unsigned long msecs)
{
#if defined(Q_OS_WIN)
    ::Sleep(msecs);
#else
    struct timeval tv;
    gettimeofday(&tv, 0);
    struct timespec ti;
    ti.tv_nsec = (tv.tv_usec + (msecs % 1000) * 1000) * 1000;
    ti.tv_sec = tv.tv_sec + (msecs / 1000) + (ti.tv_nsec / 1000000000);
    ti.tv_nsec %= 1000000000;

    pthread_mutex_t mtx;
    pthread_cond_t cnd;

    pthread_mutex_init(&mtx, 0);
    pthread_cond_init(&cnd, 0);

    pthread_mutex_lock(&mtx);
    pthread_cond_timedwait(&cnd, &mtx, &ti);
    pthread_mutex_unlock(&mtx);

    pthread_cond_destroy(&cnd);
    pthread_mutex_destroy(&mtx);
#endif
}

/*!
  Random number generator in the range from 0 to \a max.
  The maximum number of \a max is UINT_MAX.
 */
quint32 Tf::random(quint32 max)
{
    return (quint32)((double)randXor128() * (1.0 + max) / (1.0 + UINT_MAX));
}

/*
  Xorshift random number generator implement
*/
struct Rand
{
    quint32 x;
    quint32 y;
    quint32 z;
    quint32 w;
};

static QAtomicPointer<Rand> randNumber;

/*!
  Sets the argument \a seed to be used to generate a new random number sequence
  of xorshift random integers to be returned by randXor128().
  This function is thread-safe.
*/
void Tf::srandXor128(quint32 seed)
{
    // initial numbers
    Rand *r = new Rand;
    r->x = 123456789;
    r->y = 362436169;
    r->z = 777777777;
    r->w = seed;

    Rand *oldr = randNumber.fetchAndStoreOrdered(r);
    if (oldr)
        delete oldr;
}

/*!
  Returns a value between 0 and UINT_MAX, the next number in the current
  sequence of xorshift random integers.
  This function is thread-safe.
*/
quint32 Tf::randXor128()
{
    Rand *newr = new Rand;
    Rand tmp;
    quint32 t;

    for (;;) {
        Rand *oldr = (Rand*)randNumber;
        memcpy(&tmp, oldr, sizeof(tmp));
        t = tmp.x ^ (tmp.x << 11);
        newr->x = tmp.y;
        newr->y = tmp.z;
        newr->z = tmp.w;
        newr->w = tmp.w ^ (tmp.w >> 19) ^ (t ^ (t >> 8));

        if (randNumber.testAndSetOrdered(oldr, newr)) {
            delete oldr;
            break;
        }
    }
    return newr->w;
}

TActionContext *Tf::currentContext()
{
    TActionContext *context = 0;

    switch ( Tf::app()->multiProcessingModule() ) {
    case TWebApplication::Prefork:
        context = TActionForkProcess::currentContext();
        if (!context) {
            throw RuntimeException("The current process is not TActionProcess", __FILE__, __LINE__);
        }
        break;

    case TWebApplication::Thread:
        context = qobject_cast<TActionThread *>(QThread::currentThread());
        if (!context) {
            throw RuntimeException("The current thread is not TActionThread", __FILE__, __LINE__);
        }
        break;

    case TWebApplication::Hybrid:
#ifdef Q_OS_LINUX
        context = qobject_cast<TActionWorker *>(QThread::currentThread());
        if (!context) {
            throw RuntimeException("The current thread is not TActionWorker", __FILE__, __LINE__);
        }
#else
        tFatal("Unsupported MPM: hybrid");
#endif
        break;

    default:
        break;
    }
    return context;
}

QSqlDatabase &Tf::currentSqlDatabase(int id)
{
    return currentContext()->getSqlDatabase(id);
}
<|endoftext|>


<commit_before>#include <cassert>

#include "parlex/details/subjob.hpp"
#include "parlex/parser.hpp"
#include "parlex/details/job.hpp"
#include "parlex/details/context.hpp"
#include "parlex/permutation.hpp"
#include "parlex/state_machine.hpp"
#include "parlex/details/producer.hpp"
#include "parlex/details/logging.hpp"

//#define FORCE_RECURSION

namespace parlex {

parser::parser(int threadCount) : activeCount(0), terminating(false) {
	for (; threadCount > 0; --threadCount) {
		workers.emplace_back([=]() {
			DBG("thread ", threadCount, " started");
			std::unique_lock<std::mutex> lock(mutex);
			goto wait;
			while (!terminating) {
				{
					DBG("THREAD ", threadCount, " POPPING ITEM");
					std::tuple<details::context_ref, int> & item = work.front();
					work.pop();
					lock.unlock();
					auto const & context = std::get<0>(item);
					auto const nextDfaState = std::get<1>(item);
					//DBG("thread ", threadCount, " executing dfa state");
					context.owner().machine.process(context, nextDfaState);
					context.owner().end_dependency(); //reference code A
					if (--activeCount == 0) {
						halt_cv.notify_one();
					}
					lock.lock();
				}
wait:
				work_cv.wait(lock, [this]() { return work.size() > 0 || terminating; });
			}
		});
	}
}

parser::~parser() {
	terminating = true;
	work_cv.notify_all();
	for (auto & thread : workers) {
		thread.join();
	}
}

abstract_syntax_graph parser::parse(recognizer const & r, std::u32string const & document) {
	std::unique_lock<std::mutex> lock(mutex); //use the lock to make sure we see activeCount != 0
	details::job j(*this, document, r);
#ifndef FORCE_RECURSION
	assert(activeCount > 0);
#endif
	while (true) {
		halt_cv.wait(lock, [this](){ return activeCount == 0; });
		DBG("parser is idle; checking for deadlocks");
		if (handle_deadlocks(j)) {
			break;
		}
	};
	assert(activeCount == 0);
	return construct_result(j, match(match_class(r, 0), document.size()));
}

void parser::schedule(details::context_ref const & c, int nextDfaState) {
	DBG("scheduling m: ", c.owner().machine.get_id(), " b:", c.owner().documentPosition, " s:", nextDfaState, " p:", c.current_document_position());
#ifndef FORCE_RECURSION
	activeCount++;
	std::unique_lock<std::mutex> lock(mutex);
	work.emplace(std::make_tuple(c, nextDfaState));
	work_cv.notify_one();
#else
	c.owner().machine.process(c, nextDfaState);
#endif
}

abstract_syntax_graph parser::construct_result(details::job const & j, match const & match) {
	abstract_syntax_graph result(match);
	for (auto const & pair : j.producers) {
		details::producer const & producer = *pair.second;
		for (auto const & pair2 : producer.match_to_permutations) {
			struct match const & match = pair2.first;
			std::set<permutation> const & permutations = pair2.second;
			result.table[match] = permutations;
		}
	}
	return result;
}

bool parser::handle_deadlocks(details::job const & j) {
	return true;
	assert(activeCount == 0);
	//build a dependency graph and detect cyclical portions that should be halted
	//if no subjobs remain, return true
	//otherwise return false (still work to be done)

	//Examine subscriptions from one subjob to another to construct the graph
	std::map<match_class, std::set<match_class>> all_subscriptions;
	std::set<match_class> growing;
	for (auto const & i : j.producers) {
		match_class const & matchClass = i.first;
		details::producer const & p = *i.second;
		if (p.r.is_terminal() || p.completed) {
			continue;
		}
		for (auto const & subscription : p.consumers) {
			details::context_ref const & c = subscription.c;
			match_class temp(c.owner().machine, c.current_document_position());
			all_subscriptions[matchClass].insert(temp);
		}
		growing.insert(matchClass);
	}

	//Apply transitivity to the graph
	while (growing.size() > 0) {
		std::set<match_class> nextGrowing;
		for (auto const & i : all_subscriptions) {
			match_class const & matchClassA = i.first;
			for (auto const & matchClassB : i.second) {
				for (auto const & matchClassC : all_subscriptions[matchClassB]) {
					if (all_subscriptions[matchClassA].insert(matchClassC).second) {
                        nextGrowing.insert(matchClassA);
					}
				}
			}
		}
		std::swap(growing, nextGrowing);
	}

    bool anyHalted = false;
	//halt subjobs that are subcribed to themselves (in)directly
	for (auto const & i : all_subscriptions) {
		match_class const & matchClass = i.first;
		details::subjob & sj = *(details::subjob*)&(j.producers.find(matchClass)->second);
		if (i.second.count(matchClass) > 0) {
			//sj.halt_for_deadlock();
			anyHalted = true;
		}
	}
	return !anyHalted;
}

}
<commit_msg>call subjob.terminate in deadlock breaker<commit_after>#include <cassert>

#include "parlex/details/subjob.hpp"
#include "parlex/parser.hpp"
#include "parlex/details/job.hpp"
#include "parlex/details/context.hpp"
#include "parlex/permutation.hpp"
#include "parlex/state_machine.hpp"
#include "parlex/details/producer.hpp"
#include "parlex/details/logging.hpp"

//#define FORCE_RECURSION

namespace parlex {

parser::parser(int threadCount) : activeCount(0), terminating(false) {
	for (; threadCount > 0; --threadCount) {
		workers.emplace_back([=]() {
			DBG("thread ", threadCount, " started");
			std::unique_lock<std::mutex> lock(mutex);
			goto wait;
			while (!terminating) {
				{
					DBG("THREAD ", threadCount, " POPPING ITEM");
					std::tuple<details::context_ref, int> & item = work.front();
					work.pop();
					lock.unlock();
					auto const & context = std::get<0>(item);
					auto const nextDfaState = std::get<1>(item);
					//DBG("thread ", threadCount, " executing dfa state");
					context.owner().machine.process(context, nextDfaState);
					context.owner().end_dependency(); //reference code A
					if (--activeCount == 0) {
						halt_cv.notify_one();
					}
					lock.lock();
				}
wait:
				work_cv.wait(lock, [this]() { return work.size() > 0 || terminating; });
			}
		});
	}
}

parser::~parser() {
	terminating = true;
	work_cv.notify_all();
	for (auto & thread : workers) {
		thread.join();
	}
}

abstract_syntax_graph parser::parse(recognizer const & r, std::u32string const & document) {
	std::unique_lock<std::mutex> lock(mutex); //use the lock to make sure we see activeCount != 0
	details::job j(*this, document, r);
#ifndef FORCE_RECURSION
	assert(activeCount > 0);
#endif
	while (true) {
		halt_cv.wait(lock, [this](){ return activeCount == 0; });
		DBG("parser is idle; checking for deadlocks");
		if (handle_deadlocks(j)) {
			break;
		}
	};
	assert(activeCount == 0);
	return construct_result(j, match(match_class(r, 0), document.size()));
}

void parser::schedule(details::context_ref const & c, int nextDfaState) {
	DBG("scheduling m: ", c.owner().machine.get_id(), " b:", c.owner().documentPosition, " s:", nextDfaState, " p:", c.current_document_position());
#ifndef FORCE_RECURSION
	activeCount++;
	std::unique_lock<std::mutex> lock(mutex);
	work.emplace(std::make_tuple(c, nextDfaState));
	work_cv.notify_one();
#else
	c.owner().machine.process(c, nextDfaState);
#endif
}

abstract_syntax_graph parser::construct_result(details::job const & j, match const & match) {
	abstract_syntax_graph result(match);
	for (auto const & pair : j.producers) {
		details::producer const & producer = *pair.second;
		for (auto const & pair2 : producer.match_to_permutations) {
			struct match const & match = pair2.first;
			std::set<permutation> const & permutations = pair2.second;
			result.table[match] = permutations;
		}
	}
	return result;
}

bool parser::handle_deadlocks(details::job const & j) {
	return true;
	assert(activeCount == 0);
	//build a dependency graph and detect cyclical portions that should be halted
	//if no subjobs remain, return true
	//otherwise return false (still work to be done)

	//Examine subscriptions from one subjob to another to construct the graph
	std::map<match_class, std::set<match_class>> all_subscriptions;
	std::set<match_class> growing;
	for (auto const & i : j.producers) {
		match_class const & matchClass = i.first;
		details::producer const & p = *i.second;
		if (p.r.is_terminal() || p.completed) {
			continue;
		}
		for (auto const & subscription : p.consumers) {
			details::context_ref const & c = subscription.c;
			match_class temp(c.owner().machine, c.current_document_position());
			all_subscriptions[matchClass].insert(temp);
		}
		growing.insert(matchClass);
	}

	//Apply transitivity to the graph
	while (growing.size() > 0) {
		std::set<match_class> nextGrowing;
		for (auto const & i : all_subscriptions) {
			match_class const & matchClassA = i.first;
			for (auto const & matchClassB : i.second) {
				for (auto const & matchClassC : all_subscriptions[matchClassB]) {
					if (all_subscriptions[matchClassA].insert(matchClassC).second) {
                        nextGrowing.insert(matchClassA);
					}
				}
			}
		}
		std::swap(growing, nextGrowing);
	}

    bool anyHalted = false;
	//halt subjobs that are subcribed to themselves (in)directly
	for (auto const & i : all_subscriptions) {
		match_class const & matchClass = i.first;
		details::subjob & sj = *(details::subjob*)&(j.producers.find(matchClass)->second);
		if (i.second.count(matchClass) > 0) {
			sj.terminate();
			anyHalted = true;
		}
	}
	return !anyHalted;
}

}
<|endoftext|>


<commit_before>/*
 * Copyright(c) Sophist Solutions, Inc. 1990-2017.  All rights reserved
 */
#include "../StroikaPreComp.h"

#include "../../Foundation/Characters/StringBuilder.h"
#include "../../Foundation/Characters/String_Constant.h"
#include "../../Foundation/Containers/Mapping.h"
#include "../../Foundation/DataExchange/Variant/JSON/Reader.h"
#include "../../Foundation/DataExchange/Variant/JSON/Writer.h"

#include "Basic.h"

using namespace Stroika::Foundation;
using namespace Stroika::Foundation::Containers;
using namespace Stroika::Foundation::DataExchange;

using namespace Stroika::Frameworks;
using namespace Stroika::Frameworks::WebService;

using Characters::StringBuilder;
using Characters::String_Constant;

/*
 ********************************************************************************
 **************** WebService::GetWebServiceArgsAsVariantValue *******************
 ********************************************************************************
 */
VariantValue WebService::GetWebServiceArgsAsVariantValue (Request* request, const Optional<String>& fromInMessage)
{
    String method{request->GetHTTPMethod ()};
    if (method == L"POST") {
        return Variant::JSON::Reader ().Read (request->GetBody ());
    }
    else if (method == L"GET") {
        IO::Network::URL url = request->GetURL ();
        // get query args
        // For now - only support String values of query-string args
        Mapping<String, VariantValue> result;
        url.GetQuery ().GetMap ().Apply ([&result](const KeyValuePair<String, String>& kvp) { result.Add (kvp.fKey, kvp.fValue); });
        return VariantValue{result};
    }
    else {
        Execution::Throw (Execution::StringException (
            String_Constant{L"Expected GET with query-string arguments or POST"} +
            (fromInMessage ? (L" from " + *fromInMessage) : L"")));
    }
}

/*
 ********************************************************************************
 **************************** WebService::ExpectedMethod ************************
 ********************************************************************************
 */
void WebService::ExpectedMethod (const Request* request, const Set<String>& methods, const Optional<String>& fromInMessage)
{
    String method{request->GetHTTPMethod ()};
    if (not methods.Contains (method)) {
        Execution::Throw (Execution::StringException (
            String_Constant{L"Expected GET with query-string arguments or POST"} +
            (fromInMessage ? (L" from " + *fromInMessage) : L"")));
    }
}

void WebService::ExpectedMethod (const Request* request, const WebServiceMethodDescription& wsMethodDescription)
{
    ExpectedMethod (request, wsMethodDescription.fAllowedMethods, wsMethodDescription.fOperation);
}

/*
 ********************************************************************************
 **************************** WebService::WriteResponse *************************
 ********************************************************************************
 */
void WebService::WriteResponse (Response* response, const WebServiceMethodDescription& webServiceDescription, const VariantValue& responseValue)
{
    Require (webServiceDescription.fResponseType == DataExchange::PredefinedInternetMediaType::JSON_CT ()); // all we support for now
    response->write (Variant::JSON::Writer ().WriteAsBLOB (responseValue));
    response->SetContentType (webServiceDescription.fResponseType);
}

/*
 ********************************************************************************
 **************************** WebService::WriteDocsPage *************************
 ********************************************************************************
 */
void WebService::WriteDocsPage (Response* response, const Sequence<WebServiceMethodDescription>& operations, const String& h1Text)
{
    response->writeln (L"");
    response->writeln (L"");
    response->writeln (L"");
    response->printf (L"
%s
", h1Text.c_str ());
    response->writeln (L"
");
    auto writeDocs = [=](const String& methodName, const String& docs, const String& exampleCall) {
        response->writeln (L"
");
        response->printf (L"%s", methodName.c_str (), methodName.c_str ());
        response->printf (L"
%s
", docs.c_str ());
        response->printf (L"
%s
", exampleCall.c_str ());
        response->writeln (L"
");
    };
    for (WebServiceMethodDescription i : operations) {
        StringBuilder tmpDocs;
        if (i.fDetailedDocs) {
            i.fDetailedDocs->Apply ([&](const String& i) { tmpDocs += L"
" + i + L"
"; });
        }
        StringBuilder tmpCurl;
        if (i.fCurlExample) {
            i.fCurlExample->Apply ([&](const String& i) { tmpCurl += L"
" + i + L"
"; });
        }
        writeDocs (i.fOperation, tmpDocs.c_str (), tmpCurl.c_str ());
    }
    response->writeln (L"
");
    response->writeln (L"");
    response->writeln (L"");
    response->SetContentType (DataExchange::PredefinedInternetMediaType::Text_HTML_CT ());
}
<commit_msg>WebService::GetWebServiceArgsAsVariantValue () - handle null body<commit_after>/*
 * Copyright(c) Sophist Solutions, Inc. 1990-2017.  All rights reserved
 */
#include "../StroikaPreComp.h"

#include "../../Foundation/Characters/StringBuilder.h"
#include "../../Foundation/Characters/String_Constant.h"
#include "../../Foundation/Containers/Mapping.h"
#include "../../Foundation/DataExchange/Variant/JSON/Reader.h"
#include "../../Foundation/DataExchange/Variant/JSON/Writer.h"

#include "Basic.h"

using namespace Stroika::Foundation;
using namespace Stroika::Foundation::Containers;
using namespace Stroika::Foundation::DataExchange;

using namespace Stroika::Frameworks;
using namespace Stroika::Frameworks::WebService;

using Characters::StringBuilder;
using Characters::String_Constant;

/*
 ********************************************************************************
 **************** WebService::GetWebServiceArgsAsVariantValue *******************
 ********************************************************************************
 */
VariantValue WebService::GetWebServiceArgsAsVariantValue (Request* request, const Optional<String>& fromInMessage)
{
    String method{request->GetHTTPMethod ()};
    if (method == L"POST") {
        // Allow missing (content-size: 0) for args to method - and dont fail it as invalid json
        // @also - @todo - check ContentType ebfore reading as JSON!!!
        Memory::BLOB inData = request->GetBody ();
        return inData.empty () ? VariantValue{} : Variant::JSON::Reader ().Read (inData);
    }
    else if (method == L"GET") {
        IO::Network::URL url = request->GetURL ();
        // get query args
        // For now - only support String values of query-string args
        Mapping<String, VariantValue> result;
        url.GetQuery ().GetMap ().Apply ([&result](const KeyValuePair<String, String>& kvp) { result.Add (kvp.fKey, kvp.fValue); });
        return VariantValue{result};
    }
    else {
        Execution::Throw (Execution::StringException (
            String_Constant{L"Expected GET with query-string arguments or POST"} +
            (fromInMessage ? (L" from " + *fromInMessage) : L"")));
    }
}

/*
 ********************************************************************************
 **************************** WebService::ExpectedMethod ************************
 ********************************************************************************
 */
void WebService::ExpectedMethod (const Request* request, const Set<String>& methods, const Optional<String>& fromInMessage)
{
    String method{request->GetHTTPMethod ()};
    if (not methods.Contains (method)) {
        Execution::Throw (Execution::StringException (
            String_Constant{L"Expected GET with query-string arguments or POST"} +
            (fromInMessage ? (L" from " + *fromInMessage) : L"")));
    }
}

void WebService::ExpectedMethod (const Request* request, const WebServiceMethodDescription& wsMethodDescription)
{
    ExpectedMethod (request, wsMethodDescription.fAllowedMethods, wsMethodDescription.fOperation);
}

/*
 ********************************************************************************
 **************************** WebService::WriteResponse *************************
 ********************************************************************************
 */
void WebService::WriteResponse (Response* response, const WebServiceMethodDescription& webServiceDescription, const VariantValue& responseValue)
{
    Require (webServiceDescription.fResponseType == DataExchange::PredefinedInternetMediaType::JSON_CT ()); // all we support for now
    response->write (Variant::JSON::Writer ().WriteAsBLOB (responseValue));
    response->SetContentType (webServiceDescription.fResponseType);
}

/*
 ********************************************************************************
 **************************** WebService::WriteDocsPage *************************
 ********************************************************************************
 */
void WebService::WriteDocsPage (Response* response, const Sequence<WebServiceMethodDescription>& operations, const String& h1Text)
{
    response->writeln (L"");
    response->writeln (L"");
    response->writeln (L"");
    response->printf (L"
%s
", h1Text.c_str ());
    response->writeln (L"
");
    auto writeDocs = [=](const String& methodName, const String& docs, const String& exampleCall) {
        response->writeln (L"
");
        response->printf (L"%s", methodName.c_str (), methodName.c_str ());
        response->printf (L"
%s
", docs.c_str ());
        response->printf (L"
%s
", exampleCall.c_str ());
        response->writeln (L"
");
    };
    for (WebServiceMethodDescription i : operations) {
        StringBuilder tmpDocs;
        if (i.fDetailedDocs) {
            i.fDetailedDocs->Apply ([&](const String& i) { tmpDocs += L"
" + i + L"
"; });
        }
        StringBuilder tmpCurl;
        if (i.fCurlExample) {
            i.fCurlExample->Apply ([&](const String& i) { tmpCurl += L"
" + i + L"
"; });
        }
        writeDocs (i.fOperation, tmpDocs.c_str (), tmpCurl.c_str ());
    }
    response->writeln (L"
");
    response->writeln (L"");
    response->writeln (L"");
    response->SetContentType (DataExchange::PredefinedInternetMediaType::Text_HTML_CT ());
}
<|endoftext|>


<commit_before>//=======================================================================
// Copyright Baptiste Wicht 2011.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)
//=======================================================================

#include "parser/EDDIGrammar.hpp"
#include "lexer/adapttokens.hpp"

using namespace eddic;

parser::EddiGrammar::EddiGrammar(const lexer::Lexer& lexer) :
        EddiGrammar::base_type(program, "EDDI Grammar"),
        value(lexer),
        type(lexer){

    compound_op.add
        ("+=", ast::Operator::ADD)
        ("-=", ast::Operator::SUB)
        ("/=", ast::Operator::DIV)
        ("*=", ast::Operator::MUL)
        ("%=", ast::Operator::MOD)
        ;

    const_ %=
            (lexer.const_ > boost::spirit::attr(true))
        |   boost::spirit::attr(false);

    else_if_ %=
            lexer.else_
        >>  lexer.if_
        >>  lexer.left_parenth
        >>  value
        >>  lexer.right_parenth
        >>  lexer.left_brace
        >>  *(instruction)
        >>  lexer.right_brace;

    else_ %=
            lexer.else_
        >>  lexer.left_brace
        >>  *(instruction)
        >>  lexer.right_brace;

    if_ %=
            lexer.if_
        >>  lexer.left_parenth
        >>  value
        >>  lexer.right_parenth
        >>  lexer.left_brace
        >>  *(instruction)
        >>  lexer.right_brace
        >>  *(else_if_)
        >>  -(else_);

    for_ %=
            lexer.for_
        >   lexer.left_parenth
        >   -declaration
        >   lexer.stop
        >   -value
        >   lexer.stop
        >   -repeatable_instruction
        >   lexer.right_parenth
        >   lexer.left_brace
        >   (*instruction)
        >   lexer.right_brace;

    foreach_ =
            lexer.foreach_
        >>  lexer.left_parenth
        >>  lexer.identifier
        >>  lexer.identifier
        >>  lexer.from_
        >>  lexer.integer
        >>  lexer.to_
        >>  lexer.integer
        >>  lexer.right_parenth
        >>  lexer.left_brace
        >>  *(instruction)
        >>  lexer.right_brace;

    foreachin_ =
            lexer.foreach_
        >>  lexer.left_parenth
        >>  lexer.identifier
        >>  lexer.identifier
        >>  lexer.in_
        >>  lexer.identifier
        >>  lexer.right_parenth
        >>  lexer.left_brace
        >>  *(instruction)
        >>  lexer.right_brace;

    while_ %=
            lexer.while_
        >   lexer.left_parenth
        >   value
        >   lexer.right_parenth
        >   lexer.left_brace
        >   *(instruction)
        >   lexer.right_brace;

    do_while_ %=
            lexer.do_while_
        >   lexer.left_brace
        >   *(instruction)
        >   lexer.right_brace
        >   lexer.left_parenth
        >   value
        >   lexer.right_parenth;

    declaration %=
            const_
        >>  lexer.identifier
        >>  lexer.identifier
        >>  -(lexer.assign >> value);

    arrayDeclaration %=
            lexer.identifier
        >>  lexer.identifier
        >>  lexer.left_bracket
        >>  lexer.integer
        >>  lexer.right_bracket;

    assignment %=
            lexer.identifier
        >>  lexer.assign
        >>  value;

    compound_assignment %=
            lexer.identifier
        >>  qi::adapttokens[compound_op]
        >>  value;

    return_ %=
            lexer.return_
        >>  value
        >>  lexer.stop;

    arrayAssignment %=
            lexer.identifier
        >>  lexer.left_bracket
        >>  value
        >>  lexer.right_bracket
        >>  lexer.assign
        >>  value;

    globalDeclaration %=
            const_
        >>  lexer.identifier
        >>  lexer.identifier
        >>  -(lexer.assign >> value.constant)
        >>  lexer.stop;

    globalArrayDeclaration %=
            lexer.identifier
        >>  lexer.identifier
        >>  lexer.left_bracket
        >>  lexer.integer
        >>  lexer.right_bracket
        >>  lexer.stop;

    swap %=
            lexer.identifier
        >>  lexer.swap
        >>  lexer.identifier;

    instruction %=
            (value.functionCall > lexer.stop)
        |   (assignment > lexer.stop)
        |   (compound_assignment > lexer.stop)
        |   (declaration >> lexer.stop)
        |   (value.suffix_operation > lexer.stop)
        |   (value.prefix_operation > lexer.stop)
        |   (arrayDeclaration >> lexer.stop)
        |   (arrayAssignment > lexer.stop)
        |   if_
        |   for_
        |   while_
        |   foreach_
        |   foreachin_
        |   return_
        |   (swap > lexer.stop);

    //TODO Check that to see if it's complete and correct
    repeatable_instruction =
            assignment
        |   swap
        |   compound_assignment
        |   value.suffix_operation
        |   value.prefix_operation
        |   value.functionCall
        |   arrayAssignment;

    arg %=
            type
        >>  lexer.identifier;

    function %=
            lexer.identifier
        >>  lexer.identifier
        >>  lexer.left_parenth
        >>  -( arg >> *( lexer.comma > arg))
        >>  lexer.right_parenth
        >>  lexer.left_brace
        >>  *(instruction)
        >>  lexer.right_brace;

    standardImport %=
            lexer.include
        >>  lexer.less
        >>  lexer.identifier
        >>  lexer.greater;

    import %=
            lexer.include
        >>  lexer.litteral;

    program %=
            qi::eps
        >>  *(function | globalDeclaration | globalArrayDeclaration | standardImport | import);

    //Name the rules
    globalDeclaration.name("EDDI global variable");
    function.name("EDDI function declaration");
    program.name("EDDI program");
}
<commit_msg>Fix the grammar<commit_after>//=======================================================================
// Copyright Baptiste Wicht 2011.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)
//=======================================================================

#include "parser/EDDIGrammar.hpp"
#include "lexer/adapttokens.hpp"

using namespace eddic;

parser::EddiGrammar::EddiGrammar(const lexer::Lexer& lexer) :
        EddiGrammar::base_type(program, "EDDI Grammar"),
        value(lexer),
        type(lexer){

    compound_op.add
        ("+=", ast::Operator::ADD)
        ("-=", ast::Operator::SUB)
        ("/=", ast::Operator::DIV)
        ("*=", ast::Operator::MUL)
        ("%=", ast::Operator::MOD)
        ;

    const_ %=
            (lexer.const_ > boost::spirit::attr(true))
        |   boost::spirit::attr(false);

    else_if_ %=
            lexer.else_
        >>  lexer.if_
        >>  lexer.left_parenth
        >>  value
        >>  lexer.right_parenth
        >>  lexer.left_brace
        >>  *(instruction)
        >>  lexer.right_brace;

    else_ %=
            lexer.else_
        >>  lexer.left_brace
        >>  *(instruction)
        >>  lexer.right_brace;

    if_ %=
            lexer.if_
        >>  lexer.left_parenth
        >>  value
        >>  lexer.right_parenth
        >>  lexer.left_brace
        >>  *(instruction)
        >>  lexer.right_brace
        >>  *(else_if_)
        >>  -(else_);

    for_ %=
            lexer.for_
        >   lexer.left_parenth
        >   -declaration
        >   lexer.stop
        >   -value
        >   lexer.stop
        >   -repeatable_instruction
        >   lexer.right_parenth
        >   lexer.left_brace
        >   (*instruction)
        >   lexer.right_brace;

    foreach_ =
            lexer.foreach_
        >>  lexer.left_parenth
        >>  lexer.identifier
        >>  lexer.identifier
        >>  lexer.from_
        >>  lexer.integer
        >>  lexer.to_
        >>  lexer.integer
        >>  lexer.right_parenth
        >>  lexer.left_brace
        >>  *(instruction)
        >>  lexer.right_brace;

    foreachin_ =
            lexer.foreach_
        >>  lexer.left_parenth
        >>  lexer.identifier
        >>  lexer.identifier
        >>  lexer.in_
        >>  lexer.identifier
        >>  lexer.right_parenth
        >>  lexer.left_brace
        >>  *(instruction)
        >>  lexer.right_brace;

    while_ %=
            lexer.while_
        >   lexer.left_parenth
        >   value
        >   lexer.right_parenth
        >   lexer.left_brace
        >   *(instruction)
        >   lexer.right_brace;

    do_while_ %=
            lexer.do_
        >   lexer.left_brace
        >   *(instruction)
        >   lexer.right_brace
        >   lexer.while_
        >   lexer.left_parenth
        >   value
        >   lexer.right_parenth;

    declaration %=
            const_
        >>  lexer.identifier
        >>  lexer.identifier
        >>  -(lexer.assign >> value);

    arrayDeclaration %=
            lexer.identifier
        >>  lexer.identifier
        >>  lexer.left_bracket
        >>  lexer.integer
        >>  lexer.right_bracket;

    assignment %=
            lexer.identifier
        >>  lexer.assign
        >>  value;

    compound_assignment %=
            lexer.identifier
        >>  qi::adapttokens[compound_op]
        >>  value;

    return_ %=
            lexer.return_
        >>  value
        >>  lexer.stop;

    arrayAssignment %=
            lexer.identifier
        >>  lexer.left_bracket
        >>  value
        >>  lexer.right_bracket
        >>  lexer.assign
        >>  value;

    globalDeclaration %=
            const_
        >>  lexer.identifier
        >>  lexer.identifier
        >>  -(lexer.assign >> value.constant)
        >>  lexer.stop;

    globalArrayDeclaration %=
            lexer.identifier
        >>  lexer.identifier
        >>  lexer.left_bracket
        >>  lexer.integer
        >>  lexer.right_bracket
        >>  lexer.stop;

    swap %=
            lexer.identifier
        >>  lexer.swap
        >>  lexer.identifier;

    instruction %=
            (value.functionCall > lexer.stop)
        |   (assignment > lexer.stop)
        |   (compound_assignment > lexer.stop)
        |   (declaration >> lexer.stop)
        |   (value.suffix_operation > lexer.stop)
        |   (value.prefix_operation > lexer.stop)
        |   (arrayDeclaration >> lexer.stop)
        |   (arrayAssignment > lexer.stop)
        |   if_
        |   for_
        |   while_
        |   foreach_
        |   foreachin_
        |   return_
        |   (swap > lexer.stop);

    //TODO Check that to see if it's complete and correct
    repeatable_instruction =
            assignment
        |   swap
        |   compound_assignment
        |   value.suffix_operation
        |   value.prefix_operation
        |   value.functionCall
        |   arrayAssignment;

    arg %=
            type
        >>  lexer.identifier;

    function %=
            lexer.identifier
        >>  lexer.identifier
        >>  lexer.left_parenth
        >>  -( arg >> *( lexer.comma > arg))
        >>  lexer.right_parenth
        >>  lexer.left_brace
        >>  *(instruction)
        >>  lexer.right_brace;

    standardImport %=
            lexer.include
        >>  lexer.less
        >>  lexer.identifier
        >>  lexer.greater;

    import %=
            lexer.include
        >>  lexer.litteral;

    program %=
            qi::eps
        >>  *(function | globalDeclaration | globalArrayDeclaration | standardImport | import);

    //Name the rules
    globalDeclaration.name("EDDI global variable");
    function.name("EDDI function declaration");
    program.name("EDDI program");
}
<|endoftext|>


<commit_before>//
//  BBBMain.cpp
//  WoodenRadio
//
//  Created by Roderick Mann on 12/4/14.
//  Copyright (c) 2014 Latency: Zero. All rights reserved.
//

//
//	Standard Includes
//

#include <fcntl.h>
#include <cmath>
#include <cstdlib>
#include <cstring>

//
//	Library Includes
//

#include <pruio.h>

//
//	Project Includes
//

#include "GPIO.h"
#include "Radio.h"
#include "RadioDebug.h"

float
readADC(int inChannel)
{
	char path[128];
	snprintf(path, 128, "/sys/bus/iio/devices/iio:device0/in_voltage%u_raw", inChannel);
	int fd = ::open(path, O_RDONLY);
	if (fd < 0)
	{
		LogDebug("Unable to open ADC0: %s", std::strerror(errno));
		return 0.0;
	}

	float result = 0.0;

	char buf[16];
	ssize_t bytesRead = ::read(fd, buf, sizeof (buf) - 1);
	if (bytesRead > 0)
	{
		buf[bytesRead] = 0;
		//LogDebug("Read %s", buf);
		int v = ::atoi(buf);
		result = v / 4095.0;
	}
	else
	{
		LogDebug("Bytes read: %u/%u", bytesRead, sizeof (buf) - 1);
	}

	::close(fd);

	return result;
}

void
configGPIOs()
{

}

int
main(int inArgCount, const char** inArgs)
{
	//	Validate arguments…

	if (inArgCount < 2)
	{
		LogDebug("usage: %s <path to data directory>\n", inArgs[0]);
		return -1;
	}

	//	Create the GPIOs…

	GPIO	onOff(66);
	onOff.setInput();

	//	Create the radio…

	std::string p(inArgs[1]);
	Radio* mRadio = new Radio(p);
	mRadio->start();

	mRadio->setOn(true);

	//	Loop over reading the input state,
	//	and updating the radio…

	int count = 0;
	while (true)
	{
		//	Once every 10 times through the loop,
		//	check the GPIOs…

		if (count-- <= 0)
		{
			count = 10;

			bool on = onOff.get();
			mRadio->setOn(on);
		}

		float f = readADC(0);
		mRadio->setFrequency(f);
		//LogDebug("Set frequency to: %.3f", f);

		float v = readADC(1);
		mRadio->setVolume(v);
		//LogDebug("Set vol: %.3f", v);

		std::chrono::milliseconds dur(100);
		std::this_thread::sleep_for(dur);
	}

	//	Hang out while the radio runs…

	mRadio->join();

	return 0;
}
<commit_msg>Removed code to always turn on radio on launch.<commit_after>//
//  BBBMain.cpp
//  WoodenRadio
//
//  Created by Roderick Mann on 12/4/14.
//  Copyright (c) 2014 Latency: Zero. All rights reserved.
//

//
//	Standard Includes
//

#include <fcntl.h>
#include <cmath>
#include <cstdlib>
#include <cstring>

//
//	Library Includes
//

#include <pruio.h>

//
//	Project Includes
//

#include "GPIO.h"
#include "Radio.h"
#include "RadioDebug.h"

float
readADC(int inChannel)
{
	char path[128];
	snprintf(path, 128, "/sys/bus/iio/devices/iio:device0/in_voltage%u_raw", inChannel);
	int fd = ::open(path, O_RDONLY);
	if (fd < 0)
	{
		LogDebug("Unable to open ADC0: %s", std::strerror(errno));
		return 0.0;
	}

	float result = 0.0;

	char buf[16];
	ssize_t bytesRead = ::read(fd, buf, sizeof (buf) - 1);
	if (bytesRead > 0)
	{
		buf[bytesRead] = 0;
		//LogDebug("Read %s", buf);
		int v = ::atoi(buf);
		result = v / 4095.0;
	}
	else
	{
		LogDebug("Bytes read: %u/%u", bytesRead, sizeof (buf) - 1);
	}

	::close(fd);

	return result;
}

void
configGPIOs()
{

}

int
main(int inArgCount, const char** inArgs)
{
	//	Validate arguments…

	if (inArgCount < 2)
	{
		LogDebug("usage: %s <path to data directory>\n", inArgs[0]);
		return -1;
	}

	//	Create the GPIOs…

	GPIO	onOff(66);
	onOff.setInput();

	//	Create the radio…

	std::string p(inArgs[1]);
	Radio* mRadio = new Radio(p);
	mRadio->start();

	//	Loop over reading the input state,
	//	and updating the radio…

	int count = 0;
	while (true)
	{
		//	Once every 10 times through the loop,
		//	check the GPIOs…

		if (count-- <= 0)
		{
			count = 10;

			bool on = onOff.get();
			mRadio->setOn(on);
		}

		float f = readADC(0);
		mRadio->setFrequency(f);
		//LogDebug("Set frequency to: %.3f", f);

		float v = readADC(1);
		mRadio->setVolume(v);
		//LogDebug("Set vol: %.3f", v);

		std::chrono::milliseconds dur(100);
		std::this_thread::sleep_for(dur);
	}

	//	Hang out while the radio runs…

	mRadio->join();

	return 0;
}
<|endoftext|>


<commit_before>//===----------------------------------------------------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// UNSUPPORTED: libcpp-has-no-threads, c++98, c++03, c++11, c++14

// <atomic>

// static constexpr bool is_always_lock_free;

#include <atomic>
#include <cassert>

#if !defined(__cpp_lib_atomic_is_always_lock_free)
# error Feature test macro missing.
#endif

template <typename T> void checkAlwaysLockFree() {
  if (std::atomic<T>::is_always_lock_free)
    assert(std::atomic<T>().is_lock_free());
}

int main()
{
// structs and unions can't be defined in the template invocation.
// Work around this with a typedef.
#define CHECK_ALWAYS_LOCK_FREE(T)                                              \
  do {                                                                         \
    typedef T type;                                                            \
    checkAlwaysLockFree<type>();                                               \
  } while (0)

    CHECK_ALWAYS_LOCK_FREE(bool);
    CHECK_ALWAYS_LOCK_FREE(char);
    CHECK_ALWAYS_LOCK_FREE(signed char);
    CHECK_ALWAYS_LOCK_FREE(unsigned char);
    CHECK_ALWAYS_LOCK_FREE(char16_t);
    CHECK_ALWAYS_LOCK_FREE(char32_t);
    CHECK_ALWAYS_LOCK_FREE(wchar_t);
    CHECK_ALWAYS_LOCK_FREE(short);
    CHECK_ALWAYS_LOCK_FREE(unsigned short);
    CHECK_ALWAYS_LOCK_FREE(int);
    CHECK_ALWAYS_LOCK_FREE(unsigned int);
    CHECK_ALWAYS_LOCK_FREE(long);
    CHECK_ALWAYS_LOCK_FREE(unsigned long);
    CHECK_ALWAYS_LOCK_FREE(long long);
    CHECK_ALWAYS_LOCK_FREE(unsigned long long);
    CHECK_ALWAYS_LOCK_FREE(std::nullptr_t);
    CHECK_ALWAYS_LOCK_FREE(void*);
    CHECK_ALWAYS_LOCK_FREE(float);
    CHECK_ALWAYS_LOCK_FREE(double);
    CHECK_ALWAYS_LOCK_FREE(long double);
    CHECK_ALWAYS_LOCK_FREE(int __attribute__((vector_size(1 * sizeof(int)))));
    CHECK_ALWAYS_LOCK_FREE(int __attribute__((vector_size(2 * sizeof(int)))));
    CHECK_ALWAYS_LOCK_FREE(int __attribute__((vector_size(4 * sizeof(int)))));
    CHECK_ALWAYS_LOCK_FREE(int __attribute__((vector_size(16 * sizeof(int)))));
    CHECK_ALWAYS_LOCK_FREE(int __attribute__((vector_size(32 * sizeof(int)))));
    CHECK_ALWAYS_LOCK_FREE(float __attribute__((vector_size(1 * sizeof(float)))));
    CHECK_ALWAYS_LOCK_FREE(float __attribute__((vector_size(2 * sizeof(float)))));
    CHECK_ALWAYS_LOCK_FREE(float __attribute__((vector_size(4 * sizeof(float)))));
    CHECK_ALWAYS_LOCK_FREE(float __attribute__((vector_size(16 * sizeof(float)))));
    CHECK_ALWAYS_LOCK_FREE(float __attribute__((vector_size(32 * sizeof(float)))));
    CHECK_ALWAYS_LOCK_FREE(double __attribute__((vector_size(1 * sizeof(double)))));
    CHECK_ALWAYS_LOCK_FREE(double __attribute__((vector_size(2 * sizeof(double)))));
    CHECK_ALWAYS_LOCK_FREE(double __attribute__((vector_size(4 * sizeof(double)))));
    CHECK_ALWAYS_LOCK_FREE(double __attribute__((vector_size(16 * sizeof(double)))));
    CHECK_ALWAYS_LOCK_FREE(double __attribute__((vector_size(32 * sizeof(double)))));
    CHECK_ALWAYS_LOCK_FREE(struct Empty {});
    CHECK_ALWAYS_LOCK_FREE(struct OneInt { int i; });
    CHECK_ALWAYS_LOCK_FREE(struct IntArr2 { int i[2]; });
    CHECK_ALWAYS_LOCK_FREE(struct LLIArr2 { long long int i[2]; });
    CHECK_ALWAYS_LOCK_FREE(struct LLIArr4 { long long int i[4]; });
    CHECK_ALWAYS_LOCK_FREE(struct LLIArr8 { long long int i[8]; });
    CHECK_ALWAYS_LOCK_FREE(struct LLIArr16 { long long int i[16]; });
    CHECK_ALWAYS_LOCK_FREE(struct Padding { char c; /* padding */ long long int i; });
    CHECK_ALWAYS_LOCK_FREE(union IntFloat { int i; float f; });

    // C macro and static constexpr must be consistent.
    static_assert(std::atomic<bool>::is_always_lock_free == (2 == ATOMIC_BOOL_LOCK_FREE));
    static_assert(std::atomic<char>::is_always_lock_free == (2 == ATOMIC_CHAR_LOCK_FREE));
    static_assert(std::atomic<signed char>::is_always_lock_free == (2 == ATOMIC_CHAR_LOCK_FREE));
    static_assert(std::atomic<unsigned char>::is_always_lock_free == (2 == ATOMIC_CHAR_LOCK_FREE));
    static_assert(std::atomic<char16_t>::is_always_lock_free == (2 == ATOMIC_CHAR16_T_LOCK_FREE));
    static_assert(std::atomic<char32_t>::is_always_lock_free == (2 == ATOMIC_CHAR32_T_LOCK_FREE));
    static_assert(std::atomic<wchar_t>::is_always_lock_free == (2 == ATOMIC_WCHAR_T_LOCK_FREE));
    static_assert(std::atomic<short>::is_always_lock_free == (2 == ATOMIC_SHORT_LOCK_FREE));
    static_assert(std::atomic<unsigned short>::is_always_lock_free == (2 == ATOMIC_SHORT_LOCK_FREE));
    static_assert(std::atomic<int>::is_always_lock_free == (2 == ATOMIC_INT_LOCK_FREE));
    static_assert(std::atomic<unsigned int>::is_always_lock_free == (2 == ATOMIC_INT_LOCK_FREE));
    static_assert(std::atomic<long>::is_always_lock_free == (2 == ATOMIC_LONG_LOCK_FREE));
    static_assert(std::atomic<unsigned long>::is_always_lock_free == (2 == ATOMIC_LONG_LOCK_FREE));
    static_assert(std::atomic<long long>::is_always_lock_free == (2 == ATOMIC_LLONG_LOCK_FREE));
    static_assert(std::atomic<unsigned long long>::is_always_lock_free == (2 == ATOMIC_LLONG_LOCK_FREE));
    static_assert(std::atomic<void*>::is_always_lock_free == (2 == ATOMIC_POINTER_LOCK_FREE));
    static_assert(std::atomic<std::nullptr_t>::is_always_lock_free == (2 == ATOMIC_POINTER_LOCK_FREE));
}
<commit_msg>Work around PR31864 - ATOMIC_LLONG_LOCK_FREE is incorrect in 32 bit builds<commit_after>//===----------------------------------------------------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// UNSUPPORTED: libcpp-has-no-threads, c++98, c++03, c++11, c++14

// <atomic>

// static constexpr bool is_always_lock_free;

#include <atomic>
#include <cassert>

#if !defined(__cpp_lib_atomic_is_always_lock_free)
# error Feature test macro missing.
#endif

template <typename T> void checkAlwaysLockFree() {
  if (std::atomic<T>::is_always_lock_free)
    assert(std::atomic<T>().is_lock_free());
}

// FIXME: This separate test is needed to work around llvm.org/PR31864
// which causes ATOMIC_LLONG_LOCK_FREE to be defined as '1' in 32-bit builds
// even though __atomic_always_lock_free returns true for the same type.
constexpr bool NeedWorkaroundForPR31864 =
#if defined(__clang__)
(sizeof(void*) == 4); // Needed on 32 bit builds
#else
false;
#endif

template <bool Disable = NeedWorkaroundForPR31864,
  std::enable_if_t<!Disable>* = nullptr,
  class LLong = long long,
  class ULLong = unsigned long long>
void checkLongLongTypes() {
  static_assert(std::atomic<LLong>::is_always_lock_free == (2 == ATOMIC_LLONG_LOCK_FREE));
  static_assert(std::atomic<ULLong>::is_always_lock_free == (2 == ATOMIC_LLONG_LOCK_FREE));
}

// Used to make the calls to __atomic_always_lock_free dependent on a template
// parameter.
template <class T> constexpr size_t getSizeOf() { return sizeof(T); }

template <bool Enable = NeedWorkaroundForPR31864,
  std::enable_if_t<Enable>* = nullptr,
  class LLong = long long,
  class ULLong = unsigned long long>
void checkLongLongTypes() {
  constexpr bool ExpectLockFree = __atomic_always_lock_free(getSizeOf<LLong>(), 0);
  static_assert(std::atomic<LLong>::is_always_lock_free == ExpectLockFree, "");
  static_assert(std::atomic<ULLong>::is_always_lock_free == ExpectLockFree, "");
  static_assert((0 != ATOMIC_LLONG_LOCK_FREE) == ExpectLockFree, "");
}

int main()
{
// structs and unions can't be defined in the template invocation.
// Work around this with a typedef.
#define CHECK_ALWAYS_LOCK_FREE(T)                                              \
  do {                                                                         \
    typedef T type;                                                            \
    checkAlwaysLockFree<type>();                                               \
  } while (0)

    CHECK_ALWAYS_LOCK_FREE(bool);
    CHECK_ALWAYS_LOCK_FREE(char);
    CHECK_ALWAYS_LOCK_FREE(signed char);
    CHECK_ALWAYS_LOCK_FREE(unsigned char);
    CHECK_ALWAYS_LOCK_FREE(char16_t);
    CHECK_ALWAYS_LOCK_FREE(char32_t);
    CHECK_ALWAYS_LOCK_FREE(wchar_t);
    CHECK_ALWAYS_LOCK_FREE(short);
    CHECK_ALWAYS_LOCK_FREE(unsigned short);
    CHECK_ALWAYS_LOCK_FREE(int);
    CHECK_ALWAYS_LOCK_FREE(unsigned int);
    CHECK_ALWAYS_LOCK_FREE(long);
    CHECK_ALWAYS_LOCK_FREE(unsigned long);
    CHECK_ALWAYS_LOCK_FREE(long long);
    CHECK_ALWAYS_LOCK_FREE(unsigned long long);
    CHECK_ALWAYS_LOCK_FREE(std::nullptr_t);
    CHECK_ALWAYS_LOCK_FREE(void*);
    CHECK_ALWAYS_LOCK_FREE(float);
    CHECK_ALWAYS_LOCK_FREE(double);
    CHECK_ALWAYS_LOCK_FREE(long double);
    CHECK_ALWAYS_LOCK_FREE(int __attribute__((vector_size(1 * sizeof(int)))));
    CHECK_ALWAYS_LOCK_FREE(int __attribute__((vector_size(2 * sizeof(int)))));
    CHECK_ALWAYS_LOCK_FREE(int __attribute__((vector_size(4 * sizeof(int)))));
    CHECK_ALWAYS_LOCK_FREE(int __attribute__((vector_size(16 * sizeof(int)))));
    CHECK_ALWAYS_LOCK_FREE(int __attribute__((vector_size(32 * sizeof(int)))));
    CHECK_ALWAYS_LOCK_FREE(float __attribute__((vector_size(1 * sizeof(float)))));
    CHECK_ALWAYS_LOCK_FREE(float __attribute__((vector_size(2 * sizeof(float)))));
    CHECK_ALWAYS_LOCK_FREE(float __attribute__((vector_size(4 * sizeof(float)))));
    CHECK_ALWAYS_LOCK_FREE(float __attribute__((vector_size(16 * sizeof(float)))));
    CHECK_ALWAYS_LOCK_FREE(float __attribute__((vector_size(32 * sizeof(float)))));
    CHECK_ALWAYS_LOCK_FREE(double __attribute__((vector_size(1 * sizeof(double)))));
    CHECK_ALWAYS_LOCK_FREE(double __attribute__((vector_size(2 * sizeof(double)))));
    CHECK_ALWAYS_LOCK_FREE(double __attribute__((vector_size(4 * sizeof(double)))));
    CHECK_ALWAYS_LOCK_FREE(double __attribute__((vector_size(16 * sizeof(double)))));
    CHECK_ALWAYS_LOCK_FREE(double __attribute__((vector_size(32 * sizeof(double)))));
    CHECK_ALWAYS_LOCK_FREE(struct Empty {});
    CHECK_ALWAYS_LOCK_FREE(struct OneInt { int i; });
    CHECK_ALWAYS_LOCK_FREE(struct IntArr2 { int i[2]; });
    CHECK_ALWAYS_LOCK_FREE(struct LLIArr2 { long long int i[2]; });
    CHECK_ALWAYS_LOCK_FREE(struct LLIArr4 { long long int i[4]; });
    CHECK_ALWAYS_LOCK_FREE(struct LLIArr8 { long long int i[8]; });
    CHECK_ALWAYS_LOCK_FREE(struct LLIArr16 { long long int i[16]; });
    CHECK_ALWAYS_LOCK_FREE(struct Padding { char c; /* padding */ long long int i; });
    CHECK_ALWAYS_LOCK_FREE(union IntFloat { int i; float f; });

    // C macro and static constexpr must be consistent.
    static_assert(std::atomic<bool>::is_always_lock_free == (2 == ATOMIC_BOOL_LOCK_FREE));
    static_assert(std::atomic<char>::is_always_lock_free == (2 == ATOMIC_CHAR_LOCK_FREE));
    static_assert(std::atomic<signed char>::is_always_lock_free == (2 == ATOMIC_CHAR_LOCK_FREE));
    static_assert(std::atomic<unsigned char>::is_always_lock_free == (2 == ATOMIC_CHAR_LOCK_FREE));
    static_assert(std::atomic<char16_t>::is_always_lock_free == (2 == ATOMIC_CHAR16_T_LOCK_FREE));
    static_assert(std::atomic<char32_t>::is_always_lock_free == (2 == ATOMIC_CHAR32_T_LOCK_FREE));
    static_assert(std::atomic<wchar_t>::is_always_lock_free == (2 == ATOMIC_WCHAR_T_LOCK_FREE));
    static_assert(std::atomic<short>::is_always_lock_free == (2 == ATOMIC_SHORT_LOCK_FREE));
    static_assert(std::atomic<unsigned short>::is_always_lock_free == (2 == ATOMIC_SHORT_LOCK_FREE));
    static_assert(std::atomic<int>::is_always_lock_free == (2 == ATOMIC_INT_LOCK_FREE));
    static_assert(std::atomic<unsigned int>::is_always_lock_free == (2 == ATOMIC_INT_LOCK_FREE));
    static_assert(std::atomic<long>::is_always_lock_free == (2 == ATOMIC_LONG_LOCK_FREE));
    static_assert(std::atomic<unsigned long>::is_always_lock_free == (2 == ATOMIC_LONG_LOCK_FREE));
    checkLongLongTypes();
    static_assert(std::atomic<void*>::is_always_lock_free == (2 == ATOMIC_POINTER_LOCK_FREE));
    static_assert(std::atomic<std::nullptr_t>::is_always_lock_free == (2 == ATOMIC_POINTER_LOCK_FREE));
}
<|endoftext|>


<commit_before>/*
 *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include "webrtc/system_wrappers/interface/clock.h"

#include "testing/gtest/include/gtest/gtest.h"

namespace webrtc {

TEST(ClockTest, NtpTime) {
  Clock* clock = Clock::GetRealTimeClock();
  uint32_t seconds;
  uint32_t fractions;
  clock->CurrentNtp(seconds, fractions);
  int64_t milliseconds = clock->CurrentNtpInMilliseconds();
  EXPECT_GT(milliseconds / 1000, kNtpJan1970);
  EXPECT_GE(milliseconds, Clock::NtpToMs(seconds, fractions));
  EXPECT_NEAR(milliseconds, Clock::NtpToMs(seconds, fractions), 5);
}
}  // namespace webrtc
<commit_msg>Hack clock_unittest fix for parallel execution.<commit_after>/*
 *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include "webrtc/system_wrappers/interface/clock.h"

#include "testing/gtest/include/gtest/gtest.h"

namespace webrtc {

TEST(ClockTest, NtpTime) {
  Clock* clock = Clock::GetRealTimeClock();
  uint32_t seconds;
  uint32_t fractions;
  clock->CurrentNtp(seconds, fractions);
  int64_t milliseconds = clock->CurrentNtpInMilliseconds();
  EXPECT_GT(milliseconds / 1000, kNtpJan1970);
  EXPECT_GE(milliseconds, Clock::NtpToMs(seconds, fractions));
  EXPECT_NEAR(milliseconds, Clock::NtpToMs(seconds, fractions), 100);
}

}  // namespace webrtc
<|endoftext|>


<commit_before>#include "../../include/parser/cmakeparser.h"
#include "../../include/parser/cmlistfilelexer.h"
#include "../../include/cmakefile.h"
#include "../../include/cmakefunction.h"
#include <iostream>
#include <functional>

namespace {

std::string upperCase(std::string subject) {
  std::transform(subject.begin(), subject.end(), subject.begin(), ::toupper);
  return subject;
}

std::string lowerCase(std::string subject) {
  std::transform(subject.begin(), subject.end(), subject.begin(), ::tolower);
  return subject;
}

std::shared_ptr<CmakeFunction> parseCmakeFunction(cmListFileLexer* lexer, const std::string& functionName, int line, int column) {
  cmListFileLexer_Token* token = cmListFileLexer_Scan(lexer);

  int argumentStartColumn = 1;
  while (token->type == cmListFileLexer_Token_Space) {
    token =  cmListFileLexer_Scan(lexer);
    argumentStartColumn--;
  }

  if (!token || token->type != cmListFileLexer_Token_ParenLeft) {
    std::cout << "no token or no parenthesis" << "\n";
    return nullptr;
  }

  int parenthesis = 1;
  std::vector<CmakeFunctionArgument> arguments = {};
  while((token = cmListFileLexer_Scan(lexer))) {
    switch (token->type) {
      case cmListFileLexer_Token_ParenRight:
        parenthesis--;
        if (parenthesis == 0) {
          return std::make_shared<CmakeFunction>(lowerCase(functionName), line, column, token->line, token->column, arguments);
        } else if (parenthesis < 0) {
          return nullptr;
        } else {
          arguments.push_back({token->text, false, token->line, token->column + argumentStartColumn});
        }
        break;
      case cmListFileLexer_Token_ParenLeft:
        parenthesis++;
      case cmListFileLexer_Token_Identifier:
      case cmListFileLexer_Token_ArgumentUnquoted:
        arguments.push_back({token->text, false, token->line, token->column + argumentStartColumn});
        break;
      case cmListFileLexer_Token_ArgumentQuoted:
        arguments.push_back({token->text, true, token->line, token->column + argumentStartColumn});
        break;
      case cmListFileLexer_Token_Newline:
      case cmListFileLexer_Token_Space:
        break;
      default:
        std::cout << "Could not parse token type: " << token->type << " at " << token->line << ":" << token->column << "with text" << token->text << "\n";
        return nullptr;
    }
  }

  return nullptr;
}
}

namespace CmakeParser {

std::shared_ptr<CmakeFile> parse(const std::string& fileName) {
  cmListFileLexer* lexer = cmListFileLexer_New();
  if (!lexer) {
    return nullptr;
  }

  if (!cmListFileLexer_SetFileName(lexer, fileName.c_str(), nullptr)) {
    std::cout << "Could not read " << fileName << "\n";
    return nullptr;
  }

  cmListFileLexer_Token* token;
  bool readError = false;
  bool hasNewline = true;

  std::vector<std::shared_ptr<CmakeFunction>> functions;
  while (!readError && (token = cmListFileLexer_Scan(lexer))) {
    readError = false;
    switch (token->type) {
      case cmListFileLexer_Token_Newline:
        readError = false;
        hasNewline = true;
        break;
      case cmListFileLexer_Token_Identifier:
        if (hasNewline) {
          hasNewline = false;
          const auto function = parseCmakeFunction(lexer, token->text, token->line, token->column);
          if (function) {
            functions.push_back(function);
          }
        }
        break;
    }
  }

  cmListFileLexer_Delete(lexer);
  return std::make_shared<CmakeFile>(fileName, functions);
}

}<commit_msg>Removed parenthesis  offset in cmakeparser<commit_after>#include "../../include/parser/cmakeparser.h"
#include "../../include/parser/cmlistfilelexer.h"
#include "../../include/cmakefile.h"
#include "../../include/cmakefunction.h"
#include <iostream>
#include <functional>

namespace {

std::string upperCase(std::string subject) {
  std::transform(subject.begin(), subject.end(), subject.begin(), ::toupper);
  return subject;
}

std::string lowerCase(std::string subject) {
  std::transform(subject.begin(), subject.end(), subject.begin(), ::tolower);
  return subject;
}

std::shared_ptr<CmakeFunction> parseCmakeFunction(cmListFileLexer* lexer, const std::string& functionName, int line, int column) {
  cmListFileLexer_Token* token = cmListFileLexer_Scan(lexer);

  while (token->type == cmListFileLexer_Token_Space) {
    token =  cmListFileLexer_Scan(lexer);
  }

  if (!token || token->type != cmListFileLexer_Token_ParenLeft) {
    std::cout << "no token or no parenthesis" << "\n";
    return nullptr;
  }

  int parenthesis = 1;
  std::vector<CmakeFunctionArgument> arguments = {};
  while((token = cmListFileLexer_Scan(lexer))) {
    switch (token->type) {
      case cmListFileLexer_Token_ParenRight:
        parenthesis--;
        if (parenthesis == 0) {
          return std::make_shared<CmakeFunction>(lowerCase(functionName), line, column, token->line, token->column, arguments);
        } else if (parenthesis < 0) {
          return nullptr;
        } else {
          arguments.push_back({token->text, false, token->line, token->column});
        }
        break;
      case cmListFileLexer_Token_ParenLeft:
        parenthesis++;
      case cmListFileLexer_Token_Identifier:
      case cmListFileLexer_Token_ArgumentUnquoted:
        arguments.push_back({token->text, false, token->line, token->column});
        break;
      case cmListFileLexer_Token_ArgumentQuoted:
        arguments.push_back({token->text, true, token->line, token->column});
        break;
      case cmListFileLexer_Token_Newline:
      case cmListFileLexer_Token_Space:
        break;
      default:
        std::cout << "Could not parse token type: " << token->type << " at " << token->line << ":" << token->column << "with text" << token->text << "\n";
        return nullptr;
    }
  }

  return nullptr;
}
}

namespace CmakeParser {

std::shared_ptr<CmakeFile> parse(const std::string& fileName) {
  cmListFileLexer* lexer = cmListFileLexer_New();
  if (!lexer) {
    return nullptr;
  }

  if (!cmListFileLexer_SetFileName(lexer, fileName.c_str(), nullptr)) {
    std::cout << "Could not read " << fileName << "\n";
    return nullptr;
  }

  cmListFileLexer_Token* token;
  bool readError = false;
  bool hasNewline = true;

  std::vector<std::shared_ptr<CmakeFunction>> functions;
  while (!readError && (token = cmListFileLexer_Scan(lexer))) {
    readError = false;
    switch (token->type) {
      case cmListFileLexer_Token_Newline:
        readError = false;
        hasNewline = true;
        break;
      case cmListFileLexer_Token_Identifier:
        if (hasNewline) {
          hasNewline = false;
          const auto function = parseCmakeFunction(lexer, token->text, token->line, token->column);
          if (function) {
            functions.push_back(function);
          }
        }
        break;
    }
  }

  cmListFileLexer_Delete(lexer);
  return std::make_shared<CmakeFile>(fileName, functions);
}

}<|endoftext|>


<commit_before>// copyright

#include "cif++/Config.h"

#include "cif++/Cif++.h"
#include "cif++/BondMap.h"
#include "cif++/Compound.h"
#include "cif++/CifUtils.h"

using namespace std;

namespace mmcif
{

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

BondMap::BondMap(const Structure& p)
{
	auto atoms = p.atoms();
	dim = atoms.size();

//	bond = vector<bool>(dim * (dim - 1), false);

	for (auto& atom: atoms)
	{
		size_t ix = index.size();
		index[atom.id()] = ix;
	};

	auto bindAtoms = [this](const string& a, const string& b)
	{
		uint32 ixa = index[a];
		uint32 ixb = index[b];

		bond.insert(key(ixa, ixb));
	};

	auto linkAtoms = [this,&bindAtoms](const string& a, const string& b)
	{
		bindAtoms(a, b);

		link[a].insert(b);
		link[b].insert(a);
	};

	cif::Datablock& db = p.getFile().data();

	// collect all compounds first
	set<string> compounds;
	for (auto c: db["chem_comp"])
		compounds.insert(c["id"].as<string>());

	// make sure we also have all residues in the polyseq
	for (auto m: db["entity_poly_seq"])
	{
		string c = m["mon_id"].as<string>();
		if (compounds.count(c))
			continue;

		cerr << "Warning: mon_id " << c << " is missing in the chem_comp category" << endl;
		compounds.insert(c);
	}

	// first link all residues in a polyseq

	string lastAsymID;
	int lastSeqID = 0;
	for (auto r: db["pdbx_poly_seq_scheme"])
	{
		string asymId;
		int seqId;

		cif::tie(asymId, seqId) = r.get("asym_id", "seq_id");

		if (asymId != lastAsymID)		// first in a new sequece
		{
			lastAsymID = asymId;
			lastSeqID = seqId;
			continue;
		}

		auto c = db["atom_site"].find(cif::Key("label_asym_id") == asymId and cif::Key("label_seq_id") == lastSeqID and cif::Key("label_atom_id") == "C");
		if (c.size() != 1 and VERBOSE > 1)
			cerr << "Unexpected number (" << c.size() << ") of atoms with atom ID C in asym_id " << asymId << " with seq id " << lastSeqID << endl;

		auto n = db["atom_site"].find(cif::Key("label_asym_id") == asymId and cif::Key("label_seq_id") == seqId and cif::Key("label_atom_id") == "N");
		if (n.size() != 1 and VERBOSE > 1)
			cerr << "Unexpected number (" << n.size() << ") of atoms with atom ID N in asym_id " << asymId << " with seq id " << seqId << endl;

		if (not (c.empty() or n.empty()))
			bindAtoms(c.front()["id"].as<string>(), n.front()["id"].as<string>());

		lastSeqID = seqId;
	}

	for (auto l: db["struct_conn"])
	{
		string asym1, asym2, atomId1, atomId2;
		int seqId1, seqId2;
		cif::tie(asym1, asym2, atomId1, atomId2, seqId1, seqId2) =
			l.get("ptnr1_label_asym_id", "ptnr2_label_asym_id",
				  "ptnr1_label_atom_id", "ptnr2_label_atom_id",
				  "ptnr1_label_seq_id", "ptnr2_label_seq_id");

		auto a =
			l["ptnr1_label_seq_id"].empty() ?
				db["atom_site"].find(cif::Key("label_asym_id") == asym1 and cif::Key("label_atom_id") == atomId1) :
				db["atom_site"].find(cif::Key("label_asym_id") == asym1 and cif::Key("label_seq_id") == seqId1 and cif::Key("label_atom_id") == atomId1);

		if (a.size() != 1 and VERBOSE > 1)
			cerr << "Unexpected number (" << a.size() << ") of atoms for link with asym_id " << asym1 << " seq_id " << seqId1 << " atom_id " << atomId1 << endl;

		auto b =
			l["ptnr2_label_seq_id"].empty() ?
				db["atom_site"].find(cif::Key("label_asym_id") == asym2 and cif::Key("label_atom_id") == atomId2) :
				db["atom_site"].find(cif::Key("label_asym_id") == asym2 and cif::Key("label_seq_id") == seqId2 and cif::Key("label_atom_id") == atomId2);

		if (b.size() != 1 and VERBOSE > 1)
			cerr << "Unexpected number (" << b.size() << ") of atoms for link with asym_id " << asym2 << " seq_id " << seqId2 << " atom_id " << atomId2 << endl;

		if (not (a.empty() or b.empty()))
			linkAtoms(a.front()["id"].as<string>(), b.front()["id"].as<string>());
	}

	// then link all atoms in the compounds

	cif::Progress progress(compounds.size(), "Creating bond map");

	for (auto c: compounds)
	{
		auto* compound = mmcif::Compound::create(c);
		if (not compound)
		{
			if (VERBOSE)
				cerr << "Missing compound information for " << c << endl;
			continue;
		}

		if (compound->isWater())
		{
			if (VERBOSE)
				cerr << "skipping water in bond map calculation" << endl;
			continue;
		}

		// loop over poly_seq_scheme
		for (auto r: db["pdbx_poly_seq_scheme"].find(cif::Key("mon_id") == c))
		{
			string asymId;
			int seqId;
			cif::tie(asymId, seqId) = r.get("asym_id", "seq_id");

			vector<Atom> rAtoms;
			copy_if(atoms.begin(), atoms.end(), back_inserter(rAtoms),
				[&](auto& a) { return a.labelAsymId() == asymId and a.labelSeqId() == seqId; });

			for (uint32 i = 0; i + 1 < rAtoms.size(); ++i)
			{
				for (uint32 j = i + 1; j < rAtoms.size(); ++j)
				{
					if (compound->atomsBonded(rAtoms[i].labelAtomId(), rAtoms[j].labelAtomId()))
						bindAtoms(rAtoms[i].id(), rAtoms[j].id());
				}
			}
		}

		// loop over pdbx_nonpoly_scheme
		for (auto r: db["pdbx_nonpoly_scheme"].find(cif::Key("mon_id") == c))
		{
			string asymId;
			cif::tie(asymId) = r.get("asym_id");

			vector<Atom> rAtoms;
			copy_if(atoms.begin(), atoms.end(), back_inserter(rAtoms),
				[&](auto& a) { return a.labelAsymId() == asymId; });
//			for (auto a: db["atom_site"].find(cif::Key("label_asym_id") == asymId))
//				rAtoms.push_back(p.getAtomById(a["id"].as<string>()));

			for (uint32 i = 0; i + 1 < rAtoms.size(); ++i)
			{
				for (uint32 j = i + 1; j < rAtoms.size(); ++j)
				{
					if (compound->atomsBonded(rAtoms[i].labelAtomId(), rAtoms[j].labelAtomId()))
					{
						uint32 ixa = index[rAtoms[i].id()];
						uint32 ixb = index[rAtoms[j].id()];

						bond.insert(key(ixa, ixb));
					}
				}
			}
		}
	}

	// start by creating an index for single bonds

//cout << "Maken van b1_2 voor " << bond.size() << " bindingen" << endl;

	multimap<uint32,uint32> b1_2;
	for (auto& bk: bond)
	{
		uint32 a, b;
		tie(a, b) = dekey(bk);

		b1_2.insert({ a, b });
		b1_2.insert({ b, a });
	}

//cout << "Afmeting b1_2: " << b1_2.size() << endl;

	multimap<uint32,uint32> b1_3;
	for (uint32 i = 0; i < dim; ++i)
	{
		auto a = b1_2.equal_range(i);

		vector<uint32> s;
		for (auto j = a.first; j != a.second; ++j)
			s.push_back(j->second);

		for (size_t si1 = 0; si1 + 1 < s.size(); ++si1)
		{
			for (size_t si2 = si1 + 1; si2 < s.size(); ++si2)
			{
				uint32 x = s[si1];
				uint32 y = s[si2];

				if (isBonded(x, y))
					continue;

				b1_3.insert({ x, y });
				b1_3.insert({ y, x });
			}
		}
	}

//cout << "Afmeting b1_3: " << b1_3.size() << endl;

	for (uint32 i = 0; i < dim; ++i)
	{
		auto a1 = b1_2.equal_range(i);
		auto a2 = b1_3.equal_range(i);

		for (auto ai1 = a1.first; ai1 != a1.second; ++ai1)
		{
			for (auto ai2 = a2.first; ai2 != a2.second; ++ai2)
			{
				uint32 b1 = ai1->second;
				uint32 b2 = ai2->second;

				if (isBonded(b1, b2))
					continue;

				bond_1_4.insert(key(b1, b2));
			}
		}
	}
//cout << "Afmeting b1_4: " << bond_1_4.size() << endl;
}

vector<string> BondMap::linked(const Atom& a) const
{
	auto i = link.find(a.id());

	vector<string> result;

	if (i != link.end())
		result = vector<string>(i->second.begin(), i->second.end());

	return result;
}

}
<commit_msg>more timing stats for all<commit_after>// copyright

#include "cif++/Config.h"

#include "cif++/Cif++.h"
#include "cif++/BondMap.h"
#include "cif++/Compound.h"
#include "cif++/CifUtils.h"

using namespace std;

namespace mmcif
{

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

BondMap::BondMap(const Structure& p)
{
	auto atoms = p.atoms();
	dim = atoms.size();

//	bond = vector<bool>(dim * (dim - 1), false);

	for (auto& atom: atoms)
	{
		size_t ix = index.size();
		index[atom.id()] = ix;
	};

	auto bindAtoms = [this](const string& a, const string& b)
	{
		uint32 ixa = index[a];
		uint32 ixb = index[b];

		bond.insert(key(ixa, ixb));
	};

	auto linkAtoms = [this,&bindAtoms](const string& a, const string& b)
	{
		bindAtoms(a, b);

		link[a].insert(b);
		link[b].insert(a);
	};

	cif::Datablock& db = p.getFile().data();

	// collect all compounds first
	set<string> compounds;
	for (auto c: db["chem_comp"])
		compounds.insert(c["id"].as<string>());

	// make sure we also have all residues in the polyseq
	for (auto m: db["entity_poly_seq"])
	{
		string c = m["mon_id"].as<string>();
		if (compounds.count(c))
			continue;

		if (VERBOSE)
			cerr << "Warning: mon_id " << c << " is missing in the chem_comp category" << endl;
		compounds.insert(c);
	}

	// first link all residues in a polyseq

	string lastAsymID;
	int lastSeqID = 0;
	for (auto r: db["pdbx_poly_seq_scheme"])
	{
		string asymId;
		int seqId;

		cif::tie(asymId, seqId) = r.get("asym_id", "seq_id");

		if (asymId != lastAsymID)		// first in a new sequece
		{
			lastAsymID = asymId;
			lastSeqID = seqId;
			continue;
		}

		auto c = db["atom_site"].find(cif::Key("label_asym_id") == asymId and cif::Key("label_seq_id") == lastSeqID and cif::Key("label_atom_id") == "C");
		if (c.size() != 1 and VERBOSE > 1)
			cerr << "Unexpected number (" << c.size() << ") of atoms with atom ID C in asym_id " << asymId << " with seq id " << lastSeqID << endl;

		auto n = db["atom_site"].find(cif::Key("label_asym_id") == asymId and cif::Key("label_seq_id") == seqId and cif::Key("label_atom_id") == "N");
		if (n.size() != 1 and VERBOSE > 1)
			cerr << "Unexpected number (" << n.size() << ") of atoms with atom ID N in asym_id " << asymId << " with seq id " << seqId << endl;

		if (not (c.empty() or n.empty()))
			bindAtoms(c.front()["id"].as<string>(), n.front()["id"].as<string>());

		lastSeqID = seqId;
	}

	for (auto l: db["struct_conn"])
	{
		string asym1, asym2, atomId1, atomId2;
		int seqId1, seqId2;
		cif::tie(asym1, asym2, atomId1, atomId2, seqId1, seqId2) =
			l.get("ptnr1_label_asym_id", "ptnr2_label_asym_id",
				  "ptnr1_label_atom_id", "ptnr2_label_atom_id",
				  "ptnr1_label_seq_id", "ptnr2_label_seq_id");

		auto a =
			l["ptnr1_label_seq_id"].empty() ?
				db["atom_site"].find(cif::Key("label_asym_id") == asym1 and cif::Key("label_atom_id") == atomId1) :
				db["atom_site"].find(cif::Key("label_asym_id") == asym1 and cif::Key("label_seq_id") == seqId1 and cif::Key("label_atom_id") == atomId1);

		if (a.size() != 1 and VERBOSE > 1)
			cerr << "Unexpected number (" << a.size() << ") of atoms for link with asym_id " << asym1 << " seq_id " << seqId1 << " atom_id " << atomId1 << endl;

		auto b =
			l["ptnr2_label_seq_id"].empty() ?
				db["atom_site"].find(cif::Key("label_asym_id") == asym2 and cif::Key("label_atom_id") == atomId2) :
				db["atom_site"].find(cif::Key("label_asym_id") == asym2 and cif::Key("label_seq_id") == seqId2 and cif::Key("label_atom_id") == atomId2);

		if (b.size() != 1 and VERBOSE > 1)
			cerr << "Unexpected number (" << b.size() << ") of atoms for link with asym_id " << asym2 << " seq_id " << seqId2 << " atom_id " << atomId2 << endl;

		if (not (a.empty() or b.empty()))
			linkAtoms(a.front()["id"].as<string>(), b.front()["id"].as<string>());
	}

	// then link all atoms in the compounds

	cif::Progress progress(compounds.size(), "Creating bond map");

	for (auto c: compounds)
	{
		auto* compound = mmcif::Compound::create(c);
		if (not compound)
		{
			if (VERBOSE)
				cerr << "Missing compound information for " << c << endl;
			continue;
		}

		if (compound->isWater())
		{
			if (VERBOSE)
				cerr << "skipping water in bond map calculation" << endl;
			continue;
		}

		// loop over poly_seq_scheme
		for (auto r: db["pdbx_poly_seq_scheme"].find(cif::Key("mon_id") == c))
		{
			string asymId;
			int seqId;
			cif::tie(asymId, seqId) = r.get("asym_id", "seq_id");

			vector<Atom> rAtoms;
			copy_if(atoms.begin(), atoms.end(), back_inserter(rAtoms),
				[&](auto& a) { return a.labelAsymId() == asymId and a.labelSeqId() == seqId; });

			for (uint32 i = 0; i + 1 < rAtoms.size(); ++i)
			{
				for (uint32 j = i + 1; j < rAtoms.size(); ++j)
				{
					if (compound->atomsBonded(rAtoms[i].labelAtomId(), rAtoms[j].labelAtomId()))
						bindAtoms(rAtoms[i].id(), rAtoms[j].id());
				}
			}
		}

		// loop over pdbx_nonpoly_scheme
		for (auto r: db["pdbx_nonpoly_scheme"].find(cif::Key("mon_id") == c))
		{
			string asymId;
			cif::tie(asymId) = r.get("asym_id");

			vector<Atom> rAtoms;
			copy_if(atoms.begin(), atoms.end(), back_inserter(rAtoms),
				[&](auto& a) { return a.labelAsymId() == asymId; });
//			for (auto a: db["atom_site"].find(cif::Key("label_asym_id") == asymId))
//				rAtoms.push_back(p.getAtomById(a["id"].as<string>()));

			for (uint32 i = 0; i + 1 < rAtoms.size(); ++i)
			{
				for (uint32 j = i + 1; j < rAtoms.size(); ++j)
				{
					if (compound->atomsBonded(rAtoms[i].labelAtomId(), rAtoms[j].labelAtomId()))
					{
						uint32 ixa = index[rAtoms[i].id()];
						uint32 ixb = index[rAtoms[j].id()];

						bond.insert(key(ixa, ixb));
					}
				}
			}
		}
	}

	// start by creating an index for single bonds

//cout << "Maken van b1_2 voor " << bond.size() << " bindingen" << endl;

	multimap<uint32,uint32> b1_2;
	for (auto& bk: bond)
	{
		uint32 a, b;
		tie(a, b) = dekey(bk);

		b1_2.insert({ a, b });
		b1_2.insert({ b, a });
	}

//cout << "Afmeting b1_2: " << b1_2.size() << endl;

	multimap<uint32,uint32> b1_3;
	for (uint32 i = 0; i < dim; ++i)
	{
		auto a = b1_2.equal_range(i);

		vector<uint32> s;
		for (auto j = a.first; j != a.second; ++j)
			s.push_back(j->second);

		for (size_t si1 = 0; si1 + 1 < s.size(); ++si1)
		{
			for (size_t si2 = si1 + 1; si2 < s.size(); ++si2)
			{
				uint32 x = s[si1];
				uint32 y = s[si2];

				if (isBonded(x, y))
					continue;

				b1_3.insert({ x, y });
				b1_3.insert({ y, x });
			}
		}
	}

//cout << "Afmeting b1_3: " << b1_3.size() << endl;

	for (uint32 i = 0; i < dim; ++i)
	{
		auto a1 = b1_2.equal_range(i);
		auto a2 = b1_3.equal_range(i);

		for (auto ai1 = a1.first; ai1 != a1.second; ++ai1)
		{
			for (auto ai2 = a2.first; ai2 != a2.second; ++ai2)
			{
				uint32 b1 = ai1->second;
				uint32 b2 = ai2->second;

				if (isBonded(b1, b2))
					continue;

				bond_1_4.insert(key(b1, b2));
			}
		}
	}
//cout << "Afmeting b1_4: " << bond_1_4.size() << endl;
}

vector<string> BondMap::linked(const Atom& a) const
{
	auto i = link.find(a.id());

	vector<string> result;

	if (i != link.end())
		result = vector<string>(i->second.begin(), i->second.end());

	return result;
}

}
<|endoftext|>