<commit_before>#ifdef __AVR__
#include <avr/pgmspace.h>
#elif defined(ESP8266) || defined(ESP32)
#include <pgmspace.h>
#else
/*
 * Not all non-AVR boards installs define macros
 * for compatibility with existing PROGMEM-reading AVR code.
 */
#ifndef PROGMEM
#define PROGMEM
#endif
#ifndef PGM_P
#define PGM_P const char *
#endif
#ifndef SIZE_IRRELEVANT
#define SIZE_IRRELEVANT 0x7fffffff
#endif
#ifndef pgm_read_byte
#define pgm_read_byte(addr) (*(const unsigned char *)(addr))
#endif
#ifndef strcpy_P
char* strncpy_P(char* dest, PGM_P src, size_t size) {
    bool size_known = (size != SIZE_IRRELEVANT);
    const char* read = src;
    char* write = dest;
    char ch = '.';
    while (size > 0 && ch != '\0')
    {
        ch = pgm_read_byte(read++);
        *write++ = ch;
        size--;
    }
    if (size_known)
    {
        while (size > 0)
        {
            *write++ = 0;
            size--;
        }
    }

    return dest;
}
#define strcpy_P(dest, src) strncpy_P((dest), (src), SIZE_IRRELEVANT)
#endif
#endif // PROGMEM

/*
 * TetheringInternet class
 */
const char XOD_PREFIX[] PROGMEM = "+XOD:";

const char OK[] PROGMEM = "OK";
const char FAIL[] PROGMEM = "FAIL";
const char ERROR[] PROGMEM = "ERROR";
const char IPD[] PROGMEM = "IPD,";
const char CLOSED[] PROGMEM = "CLOSED";
const char CIFSR[] PROGMEM = "AT+CIFSR";
const char STAIP[] PROGMEM = "STAIP,\"";

const char AT[] PROGMEM = "AT";
const char CIPSEND[] PROGMEM = "AT+CIPSEND=";
const char CIPSTART[] PROGMEM = "AT+CIPSTART=\"";
const char CIPCLOSE[] PROGMEM = "AT+CIPCLOSE";
const char TCP[] PROGMEM = "TCP";

const char SEND_OK[] PROGMEM = "SEND OK";
const char LINK_IS_NOT[] PROGMEM = "link is not";
const char PROMPT[] PROGMEM = ">";

const char COMMA[] PROGMEM = ",";
const char COMMA_1[] PROGMEM = "\",";
const char COMMA_2[] PROGMEM = "\",\"";
const char COLON[] PROGMEM = ":";

const char EOL[] PROGMEM = "\r\n";

class TetheringInternet {
private:
#ifdef XOD_WASM_SERIAL_H
    WasmSerial_* _serial = &XOD_DEBUG_SERIAL;
#else
    Stream* _serial = &XOD_DEBUG_SERIAL;
#endif
    uint16_t _nodeId;
    bool _connected = false;
    static volatile uint16_t _pkgSize;
    void printPrefix() {
        writeCmd(XOD_PREFIX);
        _serial->print(transactionTime());
        writeCmd(COLON);
        _serial->print(_nodeId);
        writeCmd(COLON);
    }
    uint8_t readCmd(const char* text1, const char* text2 = nullptr, uint32_t timeout = 5000) {
        // setup buffers on stack & copy data from PROGMEM pointers
        char buf1[16] = { '\0' };
        char buf2[16] = { '\0' };
        if (text1 != nullptr)
            strcpy_P(buf1, text1);
        if (text2 != nullptr)
            strcpy_P(buf2, text2);
        uint8_t len1 = strlen(buf1);
        uint8_t len2 = strlen(buf2);
        uint8_t pos1 = 0;
        uint8_t pos2 = 0;
        // read chars until first match or timeout
        uint32_t stop = millis() + timeout;
        do {
            while (_serial->available()) {
                char c = _serial->read();
                pos1 = (c == buf1[pos1]) ? pos1 + 1 : 0;
                pos2 = (c == buf2[pos2]) ? pos2 + 1 : 0;
                if (len1 > 0 && pos1 == len1) {
                    return 1;
                }
                if (len2 > 0 && pos2 == len2) {
                    return 2;
                }
            }
        } while (millis() < stop);
        return 0;
    }
    bool cmdOK(const char* okResponse, const char* failResponse = nullptr, uint32_t timeout = 1000) {
        uint8_t res = readCmd(okResponse, failResponse, timeout);
        return res == 1;
    }
    void writeCmd(const char* text1 = nullptr, const char* text2 = nullptr) {
        char buf[16] = { '\0' };
        strcpy_P(buf, text1);
        _serial->print(buf);
        if (text2 == EOL) {
            _serial->println();
        } else if (text2 != nullptr) {
            strcpy_P(buf, text2);
            _serial->print(buf);
        }
    }
public:
    TetheringInternet(uint16_t nodeId) {
        _nodeId = nodeId;
    }

    static bool isReceiving() {
        return _pkgSize > 0;
    }
    static void beginReceiving(uint16_t pkgSize) {
        _pkgSize = pkgSize;
    }

    bool kick() {
        printPrefix();
        writeCmd(AT, EOL);
        _serial->flush();
        uint8_t res = readCmd(OK, ERROR);
        return res == 1;
    }
    bool openTcp(XString host, uint32_t port, uint16_t keepAlive = 0) {
        printPrefix();
        // Command + connection type
        writeCmd(CIPSTART);
        writeCmd(TCP);
        writeCmd(COMMA_2);
        // Host
        for (auto it = host.iterate(); it; ++it)
            _serial->print((char)*it);
        // Port
        writeCmd(COMMA_1);
        char _port[32];
        xod::formatNumber(port, 0, _port);
        _serial->print(port);
        // Delimiter
        writeCmd(COMMA);
        // Keep alive
        char _keepAlive[1];
        xod::formatNumber(keepAlive, 0, _keepAlive);
        _serial->println(keepAlive);
        _serial->flush();

        _connected = readCmd(OK, ERROR) == 1;
        return _connected;
    }
    bool send(XString req) {
        printPrefix();

        size_t len = length(req);
        char reqLen[len];
        xod::formatNumber(len, 0, reqLen);

        writeCmd(CIPSEND);
        _serial->println(reqLen);
        _serial->flush();

        bool prompt = cmdOK(PROMPT, LINK_IS_NOT);
        if (!prompt)
            return false;

        // Send message in a special way to wrap each line with a XOD prefix
        bool nextLine = true;
        bool cr = false;
        for (auto it = req.iterate(); it; ++it) {
            if (nextLine) {
                printPrefix();
                nextLine = false;
            }
            if (*it == '\r') {
              cr = true;
              _serial->print("\\r");
            } else if (*it == '\n') {
                nextLine = true;
                _serial->print("\\n");
                if (cr) _serial->print('\r');
                _serial->print('\n');
            } else {
                _serial->print((char)*it);
            }
        }

        _serial->flush();

        return cmdOK(SEND_OK, nullptr, 5000);
    }
    bool isConnected() {
      return _connected;
    }
    bool isAvailable() {
        return _serial->available();
    }
    bool receiveByte(char* outBuff, uint32_t timeout = 5000) {
        uint32_t stop = millis() + timeout;
        uint32_t a = 0;
        do {
            if (isAvailable() && isReceiving()) {
                *outBuff = _serial->read();
                _pkgSize--;
                // Response with ACK character to request next chunks
                if (_pkgSize == 0) {
                  printPrefix();
                  _serial->println('\6');
                }
                if (*outBuff == '\4') {
                  // end of transmittion symbol == connection closed
                  _connected = false;
                  _pkgSize = 0;
                }
                return true;
            }
        } while (a < stop);
        return false;
    }
    uint32_t getIP() {
        printPrefix();
        writeCmd(CIFSR, EOL);
        uint8_t code = readCmd(STAIP, ERROR);
        if (code == 1) {
            // found ip
            uint32_t ip[4];
            ip[0] = _serial->parseInt();
            _serial->read(); // .
            ip[1] = _serial->parseInt();
            _serial->read(); // .
            ip[2] = _serial->parseInt();
            _serial->read(); // .
            ip[3] = _serial->parseInt();

            if ((ip[0] | ip[1] | ip[2] | ip[3]) >= 0x100)
                return 0;

            return ip[0] + ip[1] * 0x100 + ip[2] * 0x10000ul + ip[3] * 0x1000000ul;
        }
        return 0;
    }
    bool close(uint8_t linkId) {
        // TODO: MUX
        printPrefix();
        writeCmd(CIPCLOSE, EOL);
        return readCmd(OK, ERROR) == 1;
    }
};

volatile uint16_t TetheringInternet::_pkgSize = 0;

struct State {
    uint8_t mem[sizeof(TetheringInternet)];
    TetheringInternet* inet;
};

using Type = TetheringInternet*;

{{ GENERATED_CODE }}

void evaluate(Context ctx) {
    auto state = getState(ctx);
    state->inet = new (state->mem) TetheringInternet(getNodeId(ctx));
    emitValue<output_INET>(ctx, state->inet);
}
<commit_msg>fix(stdlib): fix sending of the last row of a request in tethering-inet<commit_after>#ifdef __AVR__
#include <avr/pgmspace.h>
#elif defined(ESP8266) || defined(ESP32)
#include <pgmspace.h>
#else
/*
 * Not all non-AVR boards installs define macros
 * for compatibility with existing PROGMEM-reading AVR code.
 */
#ifndef PROGMEM
#define PROGMEM
#endif
#ifndef PGM_P
#define PGM_P const char *
#endif
#ifndef SIZE_IRRELEVANT
#define SIZE_IRRELEVANT 0x7fffffff
#endif
#ifndef pgm_read_byte
#define pgm_read_byte(addr) (*(const unsigned char *)(addr))
#endif
#ifndef strcpy_P
char* strncpy_P(char* dest, PGM_P src, size_t size) {
    bool size_known = (size != SIZE_IRRELEVANT);
    const char* read = src;
    char* write = dest;
    char ch = '.';
    while (size > 0 && ch != '\0')
    {
        ch = pgm_read_byte(read++);
        *write++ = ch;
        size--;
    }
    if (size_known)
    {
        while (size > 0)
        {
            *write++ = 0;
            size--;
        }
    }

    return dest;
}
#define strcpy_P(dest, src) strncpy_P((dest), (src), SIZE_IRRELEVANT)
#endif
#endif // PROGMEM

/*
 * TetheringInternet class
 */
const char XOD_PREFIX[] PROGMEM = "+XOD:";

const char OK[] PROGMEM = "OK";
const char FAIL[] PROGMEM = "FAIL";
const char ERROR[] PROGMEM = "ERROR";
const char IPD[] PROGMEM = "IPD,";
const char CLOSED[] PROGMEM = "CLOSED";
const char CIFSR[] PROGMEM = "AT+CIFSR";
const char STAIP[] PROGMEM = "STAIP,\"";

const char AT[] PROGMEM = "AT";
const char CIPSEND[] PROGMEM = "AT+CIPSEND=";
const char CIPSTART[] PROGMEM = "AT+CIPSTART=\"";
const char CIPCLOSE[] PROGMEM = "AT+CIPCLOSE";
const char TCP[] PROGMEM = "TCP";

const char SEND_OK[] PROGMEM = "SEND OK";
const char LINK_IS_NOT[] PROGMEM = "link is not";
const char PROMPT[] PROGMEM = ">";

const char COMMA[] PROGMEM = ",";
const char COMMA_1[] PROGMEM = "\",";
const char COMMA_2[] PROGMEM = "\",\"";
const char COLON[] PROGMEM = ":";

const char EOL[] PROGMEM = "\r\n";

class TetheringInternet {
private:
#ifdef XOD_WASM_SERIAL_H
    WasmSerial_* _serial = &XOD_DEBUG_SERIAL;
#else
    Stream* _serial = &XOD_DEBUG_SERIAL;
#endif
    uint16_t _nodeId;
    bool _connected = false;
    static volatile uint16_t _pkgSize;
    void printPrefix() {
        writeCmd(XOD_PREFIX);
        _serial->print(transactionTime());
        writeCmd(COLON);
        _serial->print(_nodeId);
        writeCmd(COLON);
    }
    uint8_t readCmd(const char* text1, const char* text2 = nullptr, uint32_t timeout = 5000) {
        // setup buffers on stack & copy data from PROGMEM pointers
        char buf1[16] = { '\0' };
        char buf2[16] = { '\0' };
        if (text1 != nullptr)
            strcpy_P(buf1, text1);
        if (text2 != nullptr)
            strcpy_P(buf2, text2);
        uint8_t len1 = strlen(buf1);
        uint8_t len2 = strlen(buf2);
        uint8_t pos1 = 0;
        uint8_t pos2 = 0;
        // read chars until first match or timeout
        uint32_t stop = millis() + timeout;
        do {
            while (_serial->available()) {
                char c = _serial->read();
                pos1 = (c == buf1[pos1]) ? pos1 + 1 : 0;
                pos2 = (c == buf2[pos2]) ? pos2 + 1 : 0;
                if (len1 > 0 && pos1 == len1) {
                    return 1;
                }
                if (len2 > 0 && pos2 == len2) {
                    return 2;
                }
            }
        } while (millis() < stop);
        return 0;
    }
    bool cmdOK(const char* okResponse, const char* failResponse = nullptr, uint32_t timeout = 1000) {
        uint8_t res = readCmd(okResponse, failResponse, timeout);
        return res == 1;
    }
    void writeCmd(const char* text1 = nullptr, const char* text2 = nullptr) {
        char buf[16] = { '\0' };
        strcpy_P(buf, text1);
        _serial->print(buf);
        if (text2 == EOL) {
            _serial->println();
        } else if (text2 != nullptr) {
            strcpy_P(buf, text2);
            _serial->print(buf);
        }
    }
public:
    TetheringInternet(uint16_t nodeId) {
        _nodeId = nodeId;
    }

    static bool isReceiving() {
        return _pkgSize > 0;
    }
    static void beginReceiving(uint16_t pkgSize) {
        _pkgSize = pkgSize;
    }

    bool kick() {
        printPrefix();
        writeCmd(AT, EOL);
        _serial->flush();
        uint8_t res = readCmd(OK, ERROR);
        return res == 1;
    }
    bool openTcp(XString host, uint32_t port, uint16_t keepAlive = 0) {
        printPrefix();
        // Command + connection type
        writeCmd(CIPSTART);
        writeCmd(TCP);
        writeCmd(COMMA_2);
        // Host
        for (auto it = host.iterate(); it; ++it)
            _serial->print((char)*it);
        // Port
        writeCmd(COMMA_1);
        char _port[32];
        xod::formatNumber(port, 0, _port);
        _serial->print(port);
        // Delimiter
        writeCmd(COMMA);
        // Keep alive
        char _keepAlive[1];
        xod::formatNumber(keepAlive, 0, _keepAlive);
        _serial->println(keepAlive);
        _serial->flush();

        _connected = readCmd(OK, ERROR) == 1;
        return _connected;
    }
    bool send(XString req) {
        printPrefix();

        size_t len = length(req);
        char reqLen[len];
        xod::formatNumber(len, 0, reqLen);

        writeCmd(CIPSEND);
        _serial->println(reqLen);
        _serial->flush();

        bool prompt = cmdOK(PROMPT, LINK_IS_NOT);
        if (!prompt)
            return false;

        // Send message in a special way to wrap each line with a XOD prefix
        bool nextLine = true;
        bool cr = false;
        for (auto it = req.iterate(); it; ++it) {
            if (nextLine) {
                printPrefix();
                nextLine = false;
            }
            if (*it == '\r') {
              cr = true;
              _serial->print("\\r");
            } else if (*it == '\n') {
                nextLine = true;
                _serial->print("\\n");
                if (cr) _serial->print('\r');
                _serial->print('\n');
            } else {
                _serial->print((char)*it);
            }
        }
        // Ensure the latest line of request sent
        if (!nextLine) {
            _serial->println();
        }

        _serial->flush();

        return cmdOK(SEND_OK, nullptr, 5000);
    }
    bool isConnected() {
      return _connected;
    }
    bool isAvailable() {
        return _serial->available();
    }
    bool receiveByte(char* outBuff, uint32_t timeout = 5000) {
        uint32_t stop = millis() + timeout;
        uint32_t a = 0;
        do {
            if (isAvailable() && isReceiving()) {
                *outBuff = _serial->read();
                _pkgSize--;
                // Response with ACK character to request next chunks
                if (_pkgSize == 0) {
                  printPrefix();
                  _serial->println('\6');
                }
                if (*outBuff == '\4') {
                  // end of transmittion symbol == connection closed
                  _connected = false;
                  _pkgSize = 0;
                }
                return true;
            }
        } while (a < stop);
        return false;
    }
    uint32_t getIP() {
        printPrefix();
        writeCmd(CIFSR, EOL);
        uint8_t code = readCmd(STAIP, ERROR);
        if (code == 1) {
            // found ip
            uint32_t ip[4];
            ip[0] = _serial->parseInt();
            _serial->read(); // .
            ip[1] = _serial->parseInt();
            _serial->read(); // .
            ip[2] = _serial->parseInt();
            _serial->read(); // .
            ip[3] = _serial->parseInt();

            if ((ip[0] | ip[1] | ip[2] | ip[3]) >= 0x100)
                return 0;

            return ip[0] + ip[1] * 0x100 + ip[2] * 0x10000ul + ip[3] * 0x1000000ul;
        }
        return 0;
    }
    bool close(uint8_t linkId) {
        // TODO: MUX
        printPrefix();
        writeCmd(CIPCLOSE, EOL);
        return readCmd(OK, ERROR) == 1;
    }
};

volatile uint16_t TetheringInternet::_pkgSize = 0;

struct State {
    uint8_t mem[sizeof(TetheringInternet)];
    TetheringInternet* inet;
};

using Type = TetheringInternet*;

{{ GENERATED_CODE }}

void evaluate(Context ctx) {
    auto state = getState(ctx);
    state->inet = new (state->mem) TetheringInternet(getNodeId(ctx));
    emitValue<output_INET>(ctx, state->inet);
}
<|endoftext|>


<commit_before>/*
Copyright (c) 2007, Regents of the University of Alaska

All rights reserved.

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

    * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
    * Neither the name of the Geographic Information Network of Alaska nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

#include "common.h"
#include "polygon.h"
#include "debugplot.h"

#ifdef MIN
#undef MIN
#endif
#define MIN(a,b) ((a)<(b)?(a):(b))

#ifndef bool
#define uint8_t bool
#endif
#ifndef false
#define false 0
#endif
#ifndef true
#define true (!false)
#endif

/*
static inline double sqlen(vertex_t v0, vertex_t v1) {
	double dx = v1.x - v0.x;
	double dy = v1.y - v0.y;
	return dx*dx + dy*dy;
}

static int is_seg_good(ring_t *ring, int v0_idx) {
	double radius = 10.0; // FIXME
	double rad2 = radius*radius;

	vertex_t *pts = ring->pts;
	int npts = ring->npts;

	int vl_idx = v0_idx;
	int vr_idx = (v0_idx+1) % npts;
	vertex_t v0 = pts[vl_idx];
	vertex_t v1 = pts[vr_idx];
	vertex_t center;
	center.x = (v0.x + v1.x) / 2.0;
	center.y = (v0.y + v1.y) / 2.0;

	for(;;) {
		if(sqlen(center, pts[vr_idx]) > rad2) break;
		vr_idx = (vr_idx+1) % npts;
		if(vr_idx == vl_idx) return 0; // FIXME
	}
	for(;;) {
		if(sqlen(center, pts[vl_idx]) > rad2) break;
		vl_idx = (vl_idx+npts-1) % npts;
		if(vr_idx == vl_idx) return 0; // FIXME
	}

	double up=0, dn=0, lf=0, rt=0;
	for(int i=vl_idx; i!=vr_idx; i=(i+1)%npts) {
		vertex_t v0 = pts[i];
		vertex_t v1 = pts[(i+1)%npts];
		double dx = v1.x - v0.x;
		double dy = v1.y - v0.y;
		if(dx<0) lf += -dx;
		if(dx>0) rt +=  dx;
		if(dy<0) dn += -dy;
		if(dy>0) up +=  dy;
	}
	double loopback = MIN(up,dn) + MIN(lf,rt);

	return loopback == 0;
}

ring_t pinch_excursions(ring_t *ring, report_image_t *dbuf) {
	for(int i=0; i<ring->npts; i++) {
		vertex_t v0 = ring->pts[i];
		vertex_t v1 = ring->pts[(i+1)%ring->npts];
		int good = is_seg_good(ring, i);
		if(good) plot_line(dbuf, v0, v1, 255, 0, 0);
	}
	return *ring;
}
*/

static inline double seg_ang(vertex_t v0, vertex_t v1) {
	double dx = v1.x - v0.x;
	double dy = v1.y - v0.y;
	return atan2(dy, dx);
}

static int find_bottom_pt(ring_t *ring) {
	double min = 0;
	int min_idx = -1;
	for(int i=0; i<ring->npts; i++) {
		double y = ring->pts[i].y;
		if(i==0 || y<min) {
			min = y;
			min_idx = i;
		}
	}
	return min_idx;
}

static int find_next_convex(ring_t *ring, int start_idx, int limit_idx, double start_ang, double *ang_out) {
	int npts = ring->npts;
	vertex_t *pts = ring->pts;
	vertex_t v0 = pts[start_idx];
	double min_angdiff = 2.0 * M_PI;
	int best_vert = -1;
	double best_segang = 0;
	for(int i=(start_idx+1)%npts; i!=limit_idx; i=(i+1)%npts) {
		vertex_t v1 = pts[i];
		double segang = seg_ang(v0, v1);
		double angdiff = segang - start_ang;
		while(angdiff < 0) angdiff += 2.0 * M_PI;
		while(angdiff >= 2.0 * M_PI) angdiff -= 2.0 * M_PI;
		if(angdiff < min_angdiff) {
			min_angdiff = angdiff;
			best_vert = i;
			best_segang = segang;
		}
	}
	if(ang_out) *ang_out = best_segang;
	return best_vert;
}

static bool *find_chull(ring_t *ring) {
	bool *keep = (bool *)malloc_or_die(sizeof(bool) * ring->npts);
	for(int i=0; i<ring->npts; i++) keep[i] = false;

	int start_idx = find_bottom_pt(ring);
	keep[start_idx] = true;
	double ang = -M_PI;
	int idx = start_idx;
	for(;;) {
		idx = find_next_convex(ring, idx, start_idx, ang, &ang);
		if(idx < 0) break;
		keep[idx] = true;
	}

	return keep;
}

static double subring_area(ring_t *ring, int from, int to) {
	int npts = ring->npts;
	vertex_t *pts = ring->pts;

	double accum = 0;
	int i;
	for(i=from; ; i=(i+1)%npts) {
		int i2 = i==to ? from : (i+1)%npts;
		double x0 = pts[i].x;
		double y0 = pts[i].y;
		double x1 = pts[i2].x;
		double y1 = pts[i2].y;
		accum += x0*y1 - x1*y0;
		if(i == to) break;
	}
	return accum / 2.0;
}

static void refine(ring_t *ring, bool *keep) {
	int npts = ring->npts;
	vertex_t *pts = ring->pts;
	for(int i=0; i<npts; i++) {
		if(!keep[i]) continue;
		for(;;) {
			int j;
			for(j=(i+1)%npts; j!=i; j=(j+1)%npts) {
				if(keep[j]) break;
			}
			double area = subring_area(ring, i, j);
			area = fabs(area); // FIXME
			printf("area = %g\n", area);
			if(area > 1000) {
				if(j>i) keep[(i+j)/2] = true;
				else keep[((i+j+npts)/2)%npts] = true;
			} else {
				break;
			}
		}
	}
}

ring_t pinch_excursions(ring_t *ring, report_image_t *dbuf) {
	int npts = ring->npts;
	vertex_t *pts = ring->pts;

	if(!ring_is_ccw(ring)) {
		// reverse ring to make it CCW
		for(int i=0; i<npts/2; i++) {
			vertex_t tmp = pts[i];
			pts[i] = pts[npts-1-i];
			pts[npts-1-i] = tmp;
		}
	}

	bool *keep = find_chull(ring);

	refine(ring, keep);

	int nkeep = 0;
	for(int i=0; i<npts; i++) {
		if(keep[i]) nkeep++;
	}

	ring_t outring = *ring;
	outring.npts = nkeep;
	outring.pts = (vertex_t *)malloc_or_die(sizeof(vertex_t) * outring.npts);
	int oidx=0;
	for(int i=0; i<npts; i++) {
		if(keep[i]) outring.pts[oidx++] = pts[i];
	}

	for(int i=0; i<outring.npts; i++) {
		vertex_t v0 = outring.pts[i];
		vertex_t v1 = outring.pts[(i+1)%outring.npts];
		plot_line(dbuf, v0, v1, 255, 0, 0);
	}

	return outring;
}
<commit_msg>more pincher<commit_after>/*
Copyright (c) 2007, Regents of the University of Alaska

All rights reserved.

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

    * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
    * Neither the name of the Geographic Information Network of Alaska nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

#include "common.h"
#include "polygon.h"
#include "debugplot.h"

#ifdef MIN
#undef MIN
#endif
#define MIN(a,b) ((a)<(b)?(a):(b))

#ifndef bool
#define uint8_t bool
#endif
#ifndef false
#define false 0
#endif
#ifndef true
#define true (!false)
#endif

/*
static inline double sqlen(vertex_t v0, vertex_t v1) {
	double dx = v1.x - v0.x;
	double dy = v1.y - v0.y;
	return dx*dx + dy*dy;
}

static int is_seg_good(ring_t *ring, int v0_idx) {
	double radius = 10.0; // FIXME
	double rad2 = radius*radius;

	vertex_t *pts = ring->pts;
	int npts = ring->npts;

	int vl_idx = v0_idx;
	int vr_idx = (v0_idx+1) % npts;
	vertex_t v0 = pts[vl_idx];
	vertex_t v1 = pts[vr_idx];
	vertex_t center;
	center.x = (v0.x + v1.x) / 2.0;
	center.y = (v0.y + v1.y) / 2.0;

	for(;;) {
		if(sqlen(center, pts[vr_idx]) > rad2) break;
		vr_idx = (vr_idx+1) % npts;
		if(vr_idx == vl_idx) return 0; // FIXME
	}
	for(;;) {
		if(sqlen(center, pts[vl_idx]) > rad2) break;
		vl_idx = (vl_idx+npts-1) % npts;
		if(vr_idx == vl_idx) return 0; // FIXME
	}

	double up=0, dn=0, lf=0, rt=0;
	for(int i=vl_idx; i!=vr_idx; i=(i+1)%npts) {
		vertex_t v0 = pts[i];
		vertex_t v1 = pts[(i+1)%npts];
		double dx = v1.x - v0.x;
		double dy = v1.y - v0.y;
		if(dx<0) lf += -dx;
		if(dx>0) rt +=  dx;
		if(dy<0) dn += -dy;
		if(dy>0) up +=  dy;
	}
	double loopback = MIN(up,dn) + MIN(lf,rt);

	return loopback == 0;
}

ring_t pinch_excursions(ring_t *ring, report_image_t *dbuf) {
	for(int i=0; i<ring->npts; i++) {
		vertex_t v0 = ring->pts[i];
		vertex_t v1 = ring->pts[(i+1)%ring->npts];
		int good = is_seg_good(ring, i);
		if(good) plot_line(dbuf, v0, v1, 255, 0, 0);
	}
	return *ring;
}
*/

static inline double seg_ang(vertex_t v0, vertex_t v1) {
	double dx = v1.x - v0.x;
	double dy = v1.y - v0.y;
	return atan2(dy, dx);
}

static int find_bottom_pt(ring_t *ring) {
	double min = 0;
	int min_idx = -1;
	for(int i=0; i<ring->npts; i++) {
		double y = ring->pts[i].y;
		if(i==0 || y<min) {
			min = y;
			min_idx = i;
		}
	}
	return min_idx;
}

static int find_next_convex(ring_t *ring, int start_idx, int limit_idx, double start_ang, double *ang_out) {
	int npts = ring->npts;
	vertex_t *pts = ring->pts;
	vertex_t v0 = pts[start_idx];
	double min_angdiff = 2.0 * M_PI;
	int best_vert = -1;
	double best_segang = 0;
	for(int i=(start_idx+1)%npts; i!=limit_idx; i=(i+1)%npts) {
		vertex_t v1 = pts[i];
		double segang = seg_ang(v0, v1);
//printf("start_ang=%g*PI, seg_ang=%g*PI\n", start_ang/M_PI, segang/M_PI);
		double angdiff = segang - start_ang;
		while(angdiff < 0) angdiff += 2.0 * M_PI;
		while(angdiff >= 2.0 * M_PI) angdiff -= 2.0 * M_PI;
		if(angdiff < min_angdiff) {
			min_angdiff = angdiff;
			best_vert = i;
			best_segang = segang;
		}
	}
	if(best_vert < 0) {
		return limit_idx;
	} else if(min_angdiff >= M_PI) {
		//fatal_error("point on wrong side of half-plane (ang=%g*PI)", min_angdiff/M_PI);
		return -1;
	} else {
		if(ang_out) *ang_out = best_segang;
		return best_vert;
	}
}

static bool *find_chull(ring_t *ring) {
	bool *keep = (bool *)malloc_or_die(sizeof(bool) * ring->npts);
	for(int i=0; i<ring->npts; i++) keep[i] = false;

	int start_idx = find_bottom_pt(ring);
	keep[start_idx] = true;
	double ang = 0;
	int idx = start_idx;
	for(;;) {
		idx = find_next_convex(ring, idx, start_idx, ang, &ang);
		if(idx < 0) fatal_error("could not get convex hull");
		if(idx == start_idx) break;
		keep[idx] = true;
	}

	return keep;
}

static double subring_area(ring_t *ring, int from, int to) {
	int npts = ring->npts;
	vertex_t *pts = ring->pts;

	double accum = 0;
	int i;
	for(i=from; ; i=(i+1)%npts) {
		int i2 = i==to ? from : (i+1)%npts;
		double x0 = pts[i].x;
		double y0 = pts[i].y;
		double x1 = pts[i2].x;
		double y1 = pts[i2].y;
		accum -= x0*y1 - x1*y0;
		if(i == to) break;
	}
	if(accum < 0) {
		// FIXME
		printf("subring_area was negative\n");
		//fatal_error("subring_area was negative");
	}
	return accum / 2.0;
}

static int next_keep(int npts, bool *keep, int i) {
	for(int j=(i+1)%npts; j!=i; j=(j+1)%npts) {
		if(keep[j]) return j;
	}
	return i;
}

static int prev_keep(int npts, bool *keep, int i) {
	for(int j=(i+npts-1)%npts; j!=i; j=(j+npts-1)%npts) {
		if(keep[j]) return j;
	}
	return i;
}

static int reach_point(ring_t *ring, bool *keep, int from, int to, double ang) {
	int npts = ring->npts;
	vertex_t *pts = ring->pts;

	int idx = from;
	for(;;) {
		idx = find_next_convex(ring, idx, to, ang, &ang);
		if(idx < 0) return 1;
		keep[idx] = true;
		if(idx == to) break;
	}
	for(int pk=from;;) {
		int nk = next_keep(npts, keep, pk);
		if(nk == to) return 0;

		for(int i=0; i<npts; i++) {
			int i2 = (i+1)%npts;
			if(i==pk || i==nk || i2==pk || i2==nk) continue;
			if(line_intersects_line(pts[pk], pts[nk], pts[i], pts[i2], 0)) return 1;
		}

		pk = nk;
	}
}

/*
static int chord_crosses_arc(ring_t *ring, int c0, int c1, int from, int to) {
	int npts = ring->npts;
	vertex_t *pts = ring->pts;

	for(int i=from; i!=to; i=(i+1)%npts) {
		int i2 = (i+1)%npts;
		if(i==c0 || i==c1 || i2==c0 || i2==c1) continue;
		if(line_intersects_line(pts[c0], pts[c1], pts[i], pts[i2], 0)) return 1;
	}
	return 0;
}
*/

static int refine_seg(ring_t *ring, bool *keep_orig, int from, int to) {
	int npts = ring->npts;
	vertex_t *pts = ring->pts;
	bool *keep_new = (bool *)malloc_or_die(sizeof(bool) * npts);

	int mid; // FIXME
	if(to>from) mid = (from+to)/2;
	else mid = ((from+to+npts)/2)%npts;

	double best_area = 0;

	for(int i=(from+1)%npts; i!=to; i=(i+1)%npts) {
		//if(i != mid) continue; // FIXME
		memcpy(keep_new, keep_orig, sizeof(bool) * npts);
		keep_new[i] = true;

		double ang = seg_ang(pts[from], pts[to]);
		int error = reach_point(ring, keep_new, from, i, ang);
		if(error) {
			continue; // FIXME
			fatal_error("could not reach middle point");
		}

		int pk = prev_keep(npts, keep_new, i);
		if(pk == i) fatal_error("pk == i");
		ang = seg_ang(pts[i], pts[pk]);
		error = reach_point(ring, keep_new, i, to, ang);
		if(error) continue;

		double area = 0;
		for(int pk=from;;) {
			int nk = next_keep(npts, keep_new, pk);
			if(nk == to) break;
			area += subring_area(ring, pk, nk);
			pk = nk;
		}
		//printf("a2 = %g\n", area);

		if(area > best_area) {
			best_area = area;
			memcpy(keep_orig, keep_new, sizeof(bool) * npts);
		}
	}
	return best_area == 0;
}

static void refine_ring(ring_t *ring, bool *keep) {
	int npts = ring->npts;
	int nref=0; // FIXME
	for(int i=0; i<npts; i++) {
		if(!keep[i]) continue;
		for(;;) {
			int j = next_keep(npts, keep, i);
			double area = subring_area(ring, i, j);
			//printf("area = %g\n", area);
			if(area > 1000) { // FIXME
				int error = refine_seg(ring, keep, i, j);
				if(error) break;
				nref++;
				printf("nref=%d\n", nref);
				//if(nref > 0) return; // FIXME
			} else {
				break;
			}
		}
	}
}

ring_t pinch_excursions(ring_t *ring, report_image_t *dbuf) {
	int npts = ring->npts;
	vertex_t *pts = ring->pts;

	if(!ring_is_ccw(ring)) {
		// reverse ring to make it CCW
		for(int i=0; i<npts/2; i++) {
			vertex_t tmp = pts[i];
			pts[i] = pts[npts-1-i];
			pts[npts-1-i] = tmp;
		}
	}

	bool *keep = find_chull(ring);

	refine_ring(ring, keep);

	int nkeep = 0;
	for(int i=0; i<npts; i++) {
		if(keep[i]) nkeep++;
	}

	ring_t outring = *ring;
	outring.npts = nkeep;
	outring.pts = (vertex_t *)malloc_or_die(sizeof(vertex_t) * outring.npts);
	int oidx=0;
	for(int i=0; i<npts; i++) {
		if(keep[i]) outring.pts[oidx++] = pts[i];
	}

	for(int i=0; i<outring.npts; i++) {
		vertex_t v0 = outring.pts[i];
		vertex_t v1 = outring.pts[(i+1)%outring.npts];
		plot_line(dbuf, v0, v1, 255, 0, 0);
	}

	return outring;
}
<|endoftext|>


<commit_before>// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/ui/views/dropdown_bar_host.h"

#include "base/logging.h"

NativeWebKeyboardEvent DropdownBarHost::GetKeyboardEvent(
     const TabContents* contents,
     const views::KeyEvent& key_event) {
  // TODO(beng):
  NOTIMPLEMENTED();
  return NativeWebKeyboardEvent();
}

void DropdownBarHost::SetWidgetPositionNative(const gfx::Rect& new_pos,
                                              bool no_redraw) {
  // TODO(beng):
  NOTIMPLEMENTED();
}
<commit_msg>Gets the findbar to at least show up.<commit_after>// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/ui/views/dropdown_bar_host.h"

#include "base/logging.h"
#include "ui/aura/window.h"
#include "views/widget/widget.h"

NativeWebKeyboardEvent DropdownBarHost::GetKeyboardEvent(
     const TabContents* contents,
     const views::KeyEvent& key_event) {
  return NativeWebKeyboardEvent(key_event.native_event());
}

void DropdownBarHost::SetWidgetPositionNative(const gfx::Rect& new_pos,
                                              bool no_redraw) {
  if (!host_->IsVisible())
    host_->GetNativeView()->Show();
  host_->GetNativeView()->SetBounds(new_pos);
}
<|endoftext|>


<commit_before>/*
    Copyright © 2010, 2011, 2012 Vladimír Vondruš <mosra@centrum.cz>

    This file is part of Magnum.

    Magnum is free software: you can redistribute it and/or modify
    it under the terms of the GNU Lesser General Public License version 3
    only, as published by the Free Software Foundation.

    Magnum is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    GNU Lesser General Public License version 3 for more details.
*/

#include <Utility/Debug.h>

#include "Context.h"
#include "Platform/WindowlessGlxApplication.h"

namespace Magnum {

class MagnumInfo: public Platform::WindowlessGlxApplication {
    public:
        MagnumInfo(int& argc, char** argv);

        inline int exec() override { return 0; }
};

MagnumInfo::MagnumInfo(int& argc, char** argv): WindowlessGlxApplication(argc, argv) {
    Context* c = Context::current();

    Debug() << "";
    Debug() << "  +---------------------------------------------------------+";
    Debug() << "  | Information about Magnum engine and OpenGL capabilities |";
    Debug() << "  +---------------------------------------------------------+";
    Debug() << "";

    Debug() << "Used application: Platform::WindowlessGlxApplication";
    {
        Debug d;
        d << "Compilation flags:";
        #ifdef MAGNUM_TARGET_GLES
        d << "MAGNUM_TARGET_GLES";
        #endif
        #ifdef MAGNUM_TARGET_GLES2
        d << "MAGNUM_TARGET_GLES2";
        #endif
        #ifdef MAGNUM_TARGET_NACL
        d << "MAGNUM_TARGET_NACL";
        #endif
        #ifdef CORRADE_GCC46_COMPATIBILITY
        d << "CORRADE_GCC46_COMPATIBILITY";
        #endif
    }
    Debug() << "";

    Debug() << "Vendor:" << c->vendorString();
    Debug() << "Renderer:" << c->rendererString();
    Debug() << "OpenGL version:" << c->version() << '(' + c->versionString() + ')';
    Debug() << "GLSL version:" << c->version() << '(' + c->shadingLanguageVersionString() + ')';
    Debug() << "";

    /* Get first future (not supported) version */
    std::vector<Version> versions{
        #ifndef MAGNUM_TARGET_GLES
        Version::GL300,
        Version::GL310,
        Version::GL320,
        Version::GL330,
        Version::GL400,
        Version::GL410,
        Version::GL420,
        Version::GL430,
        #else
        Version::GLES200,
        Version::GLES300,
        #endif
        Version::None
    };
    std::size_t future = 0;
    while(versions[future] != Version::None && c->isVersionSupported(versions[future]))
        ++future;

    /* Display supported OpenGL extensions from unsupported versions */
    for(std::size_t i = future; i != versions.size(); ++i) {
        if(versions[i] != Version::None)
            Debug() << versions[i] << "extension support:";
        else Debug() << "Vendor extension support:";

        for(const auto& extension: Extension::extensions(versions[i])) {
            std::string extensionName = extension.string();
            Debug d;
            d << "  " << extensionName << std::string(60-extensionName.size(), ' ');
            if(c->isExtensionSupported(extension))
                d << "SUPPORTED";
            else if(c->isVersionSupported(extension.requiredVersion()))
                d << "    -    ";
            else
                d << "   ---   ";
        }

        Debug() << "";
    }
}

}

MAGNUM_WINDOWLESSGLXAPPLICATION_MAIN(Magnum::MagnumInfo)
<commit_msg>No trailing whitespace in magnum-info utility.<commit_after>/*
    Copyright © 2010, 2011, 2012 Vladimír Vondruš <mosra@centrum.cz>

    This file is part of Magnum.

    Magnum is free software: you can redistribute it and/or modify
    it under the terms of the GNU Lesser General Public License version 3
    only, as published by the Free Software Foundation.

    Magnum is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    GNU Lesser General Public License version 3 for more details.
*/

#include <Utility/Debug.h>

#include "Context.h"
#include "Platform/WindowlessGlxApplication.h"

namespace Magnum {

class MagnumInfo: public Platform::WindowlessGlxApplication {
    public:
        MagnumInfo(int& argc, char** argv);

        inline int exec() override { return 0; }
};

MagnumInfo::MagnumInfo(int& argc, char** argv): WindowlessGlxApplication(argc, argv) {
    Context* c = Context::current();

    Debug() << "";
    Debug() << "  +---------------------------------------------------------+";
    Debug() << "  | Information about Magnum engine and OpenGL capabilities |";
    Debug() << "  +---------------------------------------------------------+";
    Debug() << "";

    Debug() << "Used application: Platform::WindowlessGlxApplication";
    {
        Debug d;
        d << "Compilation flags:";
        #ifdef MAGNUM_TARGET_GLES
        d << "MAGNUM_TARGET_GLES";
        #endif
        #ifdef MAGNUM_TARGET_GLES2
        d << "MAGNUM_TARGET_GLES2";
        #endif
        #ifdef MAGNUM_TARGET_NACL
        d << "MAGNUM_TARGET_NACL";
        #endif
        #ifdef CORRADE_GCC46_COMPATIBILITY
        d << "CORRADE_GCC46_COMPATIBILITY";
        #endif
    }
    Debug() << "";

    Debug() << "Vendor:" << c->vendorString();
    Debug() << "Renderer:" << c->rendererString();
    Debug() << "OpenGL version:" << c->version() << '(' + c->versionString() + ')';
    Debug() << "GLSL version:" << c->version() << '(' + c->shadingLanguageVersionString() + ')';
    Debug() << "";

    /* Get first future (not supported) version */
    std::vector<Version> versions{
        #ifndef MAGNUM_TARGET_GLES
        Version::GL300,
        Version::GL310,
        Version::GL320,
        Version::GL330,
        Version::GL400,
        Version::GL410,
        Version::GL420,
        Version::GL430,
        #else
        Version::GLES200,
        Version::GLES300,
        #endif
        Version::None
    };
    std::size_t future = 0;
    while(versions[future] != Version::None && c->isVersionSupported(versions[future]))
        ++future;

    /* Display supported OpenGL extensions from unsupported versions */
    for(std::size_t i = future; i != versions.size(); ++i) {
        if(versions[i] != Version::None)
            Debug() << versions[i] << "extension support:";
        else Debug() << "Vendor extension support:";

        for(const auto& extension: Extension::extensions(versions[i])) {
            std::string extensionName = extension.string();
            Debug d;
            d << "  " << extensionName << std::string(60-extensionName.size(), ' ');
            if(c->isExtensionSupported(extension))
                d << "SUPPORTED";
            else if(c->isVersionSupported(extension.requiredVersion()))
                d << "    -";
            else
                d << "   ---";
        }

        Debug() << "";
    }
}

}

MAGNUM_WINDOWLESSGLXAPPLICATION_MAIN(Magnum::MagnumInfo)
<|endoftext|>


<commit_before>#include "stickynote.h"

#include <QHostAddress>
#include <QTcpServer>

#include "stickynoteconnection.h"

K_EXPORT_PLASMA_APPLET(stickynote, StickyNote)

StickyNote::StickyNote(QObject *_parent, const QVariantList &_args)
: Plasma::Applet(_parent, _args), m_server(0)
{
	setAspectRatioMode(Plasma::IgnoreAspectRatio);
	setBackgroundHints(Plasma::Applet::NoBackground);

	resize(0, 0);
}

StickyNote::~StickyNote(void)
{
	delete m_server;
}

void
StickyNote::init(void)
{
	m_server = new QTcpServer(this);

	connect(m_server, SIGNAL(newConnection()),
	    this, SLOT(on_server_newConnection()));

	// TODO: make address and port customizable
	if (!m_server->listen(QHostAddress::LocalHost, 12345))
		setFailedToLaunch(true,
		    "Failed, You might already have a StickyNotes plasmoid running.");
}

void
StickyNote::paintInterface(QPainter *_painter,
    const QStyleOptionGraphicsItem *_option, const QRect &_rect)
{
	Q_UNUSED(_option);
	Q_UNUSED(_painter);
	Q_UNUSED(_rect);
}

void
StickyNote::on_server_newConnection(void)
{
	QTcpSocket *client;

	if ((client = m_server->nextPendingConnection()))
		new StickyNoteConnection(*this, *client);
}

<commit_msg>Add missing i18n<commit_after>#include "stickynote.h"

#include <QHostAddress>
#include <QTcpServer>

#include "stickynoteconnection.h"

K_EXPORT_PLASMA_APPLET(stickynote, StickyNote)

StickyNote::StickyNote(QObject *_parent, const QVariantList &_args)
: Plasma::Applet(_parent, _args), m_server(0)
{
	setAspectRatioMode(Plasma::IgnoreAspectRatio);
	setBackgroundHints(Plasma::Applet::NoBackground);

	resize(0, 0);
}

StickyNote::~StickyNote(void)
{
	delete m_server;
}

void
StickyNote::init(void)
{
	m_server = new QTcpServer(this);

	connect(m_server, SIGNAL(newConnection()),
	    this, SLOT(on_server_newConnection()));

	// TODO: make address and port customizable
	if (!m_server->listen(QHostAddress::LocalHost, 12345))
		setFailedToLaunch(true,
		    i18n("Failed, You might already have a StickyNotes plasmoid running."));
}

void
StickyNote::paintInterface(QPainter *_painter,
    const QStyleOptionGraphicsItem *_option, const QRect &_rect)
{
	Q_UNUSED(_option);
	Q_UNUSED(_painter);
	Q_UNUSED(_rect);
}

void
StickyNote::on_server_newConnection(void)
{
	QTcpSocket *client;

	if ((client = m_server->nextPendingConnection()))
		new StickyNoteConnection(*this, *client);
}

<|endoftext|>


<commit_before>/**
 * Copyright © 2016 IBM Corporation
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include <iostream>
#include <memory>
#include <cstring>
#include <cstdlib>
#include <chrono>
#include "sensorset.hpp"
#include "sensorcache.hpp"
#include "hwmon.hpp"
#include "sysfs.hpp"
#include "mainloop.hpp"

using namespace std::literals::chrono_literals;

MainLoop::MainLoop(
    sdbusplus::bus::bus&& bus,
    const std::string& path,
    const char* prefix,
    const char* root)
    : _bus(std::move(bus)),
      _manager(sdbusplus::server::manager::manager(_bus, root)),
      _shutdown(false),
      _path(path),
      _prefix(prefix),
      _root(root),
      state()
{
    if (_path.back() == '/')
    {
        _path.pop_back();
    }
}

void MainLoop::shutdown() noexcept
{
    _shutdown = true;
}

void MainLoop::run()
{
    // Check sysfs for available sensors.
    auto sensors = std::make_unique<SensorSet>(_path);
    auto sensor_cache = std::make_unique<SensorCache>();

    for (auto& i : *sensors)
    {
        // Ignore inputs without a label.
        std::string envKey = "LABEL_" + i.first.first + i.first.second;
        std::string label;

        auto env = getenv(envKey.c_str());

        if (env)
        {
            label.assign(env);
        }

        if (label.empty())
        {
            continue;
        }

        // Get the initial value for the value interface.
        auto sysfsPath = make_sysfs_path(
                             _path,
                             i.first.first,
                             i.first.second,
                             hwmon::entry::input);
        int val = 0;
        read_sysfs(sysfsPath, val);

        Object o;
        std::string objectPath{_root};

        objectPath.append("/");
        objectPath.append(i.first.first);
        objectPath.append("/");
        objectPath.append(label);

        auto iface = std::make_shared<ValueObject>(_bus, objectPath.c_str());
        iface->value(val);
        o.emplace(InterfaceType::VALUE, iface);

        auto value = std::make_tuple(
                         std::move(i.second),
                         std::move(label),
                         std::move(o));

        state[std::move(i.first)] = std::move(value);
    }

    {
        struct Free
        {
            void operator()(char* ptr) const
            {
                free(ptr);
            }
        };

        auto copy = std::unique_ptr<char, Free>(strdup(_path.c_str()));
        auto busname = std::string(_prefix) + '.' + basename(copy.get());
        _bus.request_name(busname.c_str());
    }

    // TODO: Issue#3 - Need to make calls to the dbus sensor cache here to
    //       ensure the objects all exist?

    // Polling loop.
    while (!_shutdown)
    {
        // Iterate through all the sensors.
        for (auto& i : state)
        {
            auto& attrs = std::get<0>(i.second);
            if (attrs.find(hwmon::entry::input) != attrs.end())
            {
                // Read value from sensor.
                int value = 0;
                read_sysfs(make_sysfs_path(_path,
                                           i.first.first, i.first.second,
                                           hwmon::entry::input),
                           value);

                // Update sensor cache.
                if (sensor_cache->update(i.first, value))
                {
                    // TODO: Issue#4 - dbus event here.
                    std::cout << i.first.first << i.first.second << " = "
                              << value << std::endl;
                }
            }
        }

        // Respond to DBus
        _bus.process_discard();

        // Sleep until next interval.
        // TODO: Issue#5 - Make this configurable.
        // TODO: Issue#6 - Optionally look at polling interval sysfs entry.
        _bus.wait((1000000us).count());

        // TODO: Issue#7 - Should probably periodically check the SensorSet
        //       for new entries.
    }
}

// vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
<commit_msg>Set Sensors.Value unit and scale properties<commit_after>/**
 * Copyright © 2016 IBM Corporation
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include <iostream>
#include <memory>
#include <cstring>
#include <cstdlib>
#include <chrono>
#include <algorithm>
#include "sensorset.hpp"
#include "sensorcache.hpp"
#include "hwmon.hpp"
#include "sysfs.hpp"
#include "mainloop.hpp"

using namespace std::literals::chrono_literals;

static constexpr auto typeAttrMap =
{
    // 1 - hwmon class
    // 2 - unit
    // 3 - sysfs scaling factor
    std::make_tuple(
        hwmon::type::ctemp,
        ValueInterface::Unit::DegreesC,
        -3),
    std::make_tuple(
        hwmon::type::cfan,
        ValueInterface::Unit::RPMS,
        0),
    std::make_tuple(
        hwmon::type::cvolt,
        ValueInterface::Unit::Volts,
        -3),
};

auto getHwmonType(decltype(typeAttrMap)::const_reference attrs)
{
    return std::get<0>(attrs);
}

auto getUnit(decltype(typeAttrMap)::const_reference attrs)
{
    return std::get<1>(attrs);
}

auto getScale(decltype(typeAttrMap)::const_reference attrs)
{
    return std::get<2>(attrs);
}

MainLoop::MainLoop(
    sdbusplus::bus::bus&& bus,
    const std::string& path,
    const char* prefix,
    const char* root)
    : _bus(std::move(bus)),
      _manager(sdbusplus::server::manager::manager(_bus, root)),
      _shutdown(false),
      _path(path),
      _prefix(prefix),
      _root(root),
      state()
{
    if (_path.back() == '/')
    {
        _path.pop_back();
    }
}

void MainLoop::shutdown() noexcept
{
    _shutdown = true;
}

void MainLoop::run()
{
    // Check sysfs for available sensors.
    auto sensors = std::make_unique<SensorSet>(_path);
    auto sensor_cache = std::make_unique<SensorCache>();

    for (auto& i : *sensors)
    {
        // Ignore inputs without a label.
        std::string envKey = "LABEL_" + i.first.first + i.first.second;
        std::string label;

        auto env = getenv(envKey.c_str());

        if (env)
        {
            label.assign(env);
        }

        if (label.empty())
        {
            continue;
        }

        // Get the initial value for the value interface.
        auto sysfsPath = make_sysfs_path(
                             _path,
                             i.first.first,
                             i.first.second,
                             hwmon::entry::input);
        int val = 0;
        read_sysfs(sysfsPath, val);

        Object o;
        std::string objectPath{_root};

        objectPath.append("/");
        objectPath.append(i.first.first);
        objectPath.append("/");
        objectPath.append(label);

        auto iface = std::make_shared<ValueObject>(_bus, objectPath.c_str());
        iface->value(val);

        const auto& attrs = std::find_if(
                                typeAttrMap.begin(),
                                typeAttrMap.end(),
                                [&](const auto & e)
        {
            return i.first.first == getHwmonType(e);
        });
        if (attrs != typeAttrMap.end())
        {
            iface->unit(getUnit(*attrs));
            iface->scale(getScale(*attrs));
        }

        o.emplace(InterfaceType::VALUE, iface);

        auto value = std::make_tuple(
                         std::move(i.second),
                         std::move(label),
                         std::move(o));

        state[std::move(i.first)] = std::move(value);
    }

    {
        struct Free
        {
            void operator()(char* ptr) const
            {
                free(ptr);
            }
        };

        auto copy = std::unique_ptr<char, Free>(strdup(_path.c_str()));
        auto busname = std::string(_prefix) + '.' + basename(copy.get());
        _bus.request_name(busname.c_str());
    }

    // TODO: Issue#3 - Need to make calls to the dbus sensor cache here to
    //       ensure the objects all exist?

    // Polling loop.
    while (!_shutdown)
    {
        // Iterate through all the sensors.
        for (auto& i : state)
        {
            auto& attrs = std::get<0>(i.second);
            if (attrs.find(hwmon::entry::input) != attrs.end())
            {
                // Read value from sensor.
                int value = 0;
                read_sysfs(make_sysfs_path(_path,
                                           i.first.first, i.first.second,
                                           hwmon::entry::input),
                           value);

                // Update sensor cache.
                if (sensor_cache->update(i.first, value))
                {
                    // TODO: Issue#4 - dbus event here.
                    std::cout << i.first.first << i.first.second << " = "
                              << value << std::endl;
                }
            }
        }

        // Respond to DBus
        _bus.process_discard();

        // Sleep until next interval.
        // TODO: Issue#5 - Make this configurable.
        // TODO: Issue#6 - Optionally look at polling interval sysfs entry.
        _bus.wait((1000000us).count());

        // TODO: Issue#7 - Should probably periodically check the SensorSet
        //       for new entries.
    }
}

// vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
<|endoftext|>


<commit_before>// The libMesh Finite Element Library.
// Copyright (C) 2002-2012 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner

// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.

// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.

// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

// Local includes
#include "elem.h"
#include "fe.h"
#include "fe_interface.h"

namespace libMesh
{

  // ------------------------------------------------------------
  // Hierarchic-specific implementations

  // Anonymous namespace for local helper functions
  namespace {

    void l2_hierarchic_nodal_soln(const Elem* elem,
				  const Order order,
				  const std::vector<Number>& elem_soln,
				  std::vector<Number>&       nodal_soln,
				  unsigned Dim)
    {
      const unsigned int n_nodes = elem->n_nodes();

      const ElemType elem_type = elem->type();

      nodal_soln.resize(n_nodes);

      const Order totalorder = static_cast<Order>(order + elem->p_level());

      // FEType object to be passed to various FEInterface functions below.
      FEType fe_type(totalorder, L2_HIERARCHIC);

      switch (totalorder)
	{
	  // Constant shape functions
	case CONSTANT:
	  {
	    libmesh_assert (elem_soln.size() == 1);

	    const Number val = elem_soln[0];

	    for (unsigned int n=0; n<n_nodes; n++)
	      nodal_soln[n] = val;

	    return;
	  }

	  // For other orders do interpolation at the nodes
	  // explicitly.
	default:
	  {

	    const unsigned int n_sf =
	      // FE<Dim,T>::n_shape_functions(elem_type, totalorder);
	      FEInterface::n_shape_functions(Dim, fe_type, elem_type);

	    std::vector<Point> refspace_nodes;
	    FEBase::get_refspace_nodes(elem_type,refspace_nodes);
	    libmesh_assert (refspace_nodes.size() == n_nodes);

	    for (unsigned int n=0; n<n_nodes; n++)
	      {
		libmesh_assert (elem_soln.size() == n_sf);

		// Zero before summation
		nodal_soln[n] = 0;

		// u_i = Sum (alpha_i phi_i)
		for (unsigned int i=0; i<n_sf; i++)
		  nodal_soln[n] += elem_soln[i] *
		    // FE<Dim,T>::shape(elem, order, i, mapped_point);
		    FEInterface::shape(Dim, fe_type, elem, i, refspace_nodes[n]);
	      }

	    return;
	  }
	}
    } // l2_hierarchic_nodal_soln()

    unsigned int l2_hierarchic_n_dofs(const ElemType t, const Order o)
    {
      libmesh_assert (o > 0);
      switch (t)
	{
	case NODEELEM:
	  return 1;
	case EDGE2:
	case EDGE3:
	  return (o+1);
	case QUAD4:
	case QUAD8:
	case QUAD9:
	  return ((o+1)*(o+1));
	case HEX8:
	case HEX20:
	case HEX27:
	  return ((o+1)*(o+1)*(o+1));
	case TRI6:
	  return ((o+1)*(o+2)/2);
	default:
	  libmesh_error();
	}

      libmesh_error();
      return 0;
    } // l2_hierarchic_n_dofs()

  } // anonymous namespace

  // Do full-specialization of nodal_soln() function for every
  // dimension, instead of explicit instantiation at the end of this
  // file.
  // This could be macro-ified so that it fits on one line...
  template <>
  void FE<0,L2_HIERARCHIC>::nodal_soln(const Elem* elem,
				       const Order order,
				       const std::vector<Number>& elem_soln,
				       std::vector<Number>& nodal_soln)
  { l2_hierarchic_nodal_soln(elem, order, elem_soln, nodal_soln, /*Dim=*/0); }

  template <>
  void FE<1,L2_HIERARCHIC>::nodal_soln(const Elem* elem,
				       const Order order,
				       const std::vector<Number>& elem_soln,
				       std::vector<Number>& nodal_soln)
  { l2_hierarchic_nodal_soln(elem, order, elem_soln, nodal_soln, /*Dim=*/1); }

  template <>
  void FE<2,L2_HIERARCHIC>::nodal_soln(const Elem* elem,
				       const Order order,
				       const std::vector<Number>& elem_soln,
				       std::vector<Number>& nodal_soln)
  { l2_hierarchic_nodal_soln(elem, order, elem_soln, nodal_soln, /*Dim=*/2); }

  template <>
  void FE<3,L2_HIERARCHIC>::nodal_soln(const Elem* elem,
				       const Order order,
				       const std::vector<Number>& elem_soln,
				       std::vector<Number>& nodal_soln)
  { l2_hierarchic_nodal_soln(elem, order, elem_soln, nodal_soln, /*Dim=*/3); }

  // Full specialization of n_dofs() function for every dimension
  template <> unsigned int FE<0,L2_HIERARCHIC>::n_dofs(const ElemType t, const Order o) { return l2_hierarchic_n_dofs(t, o); }
  template <> unsigned int FE<1,L2_HIERARCHIC>::n_dofs(const ElemType t, const Order o) { return l2_hierarchic_n_dofs(t, o); }
  template <> unsigned int FE<2,L2_HIERARCHIC>::n_dofs(const ElemType t, const Order o) { return l2_hierarchic_n_dofs(t, o); }
  template <> unsigned int FE<3,L2_HIERARCHIC>::n_dofs(const ElemType t, const Order o) { return l2_hierarchic_n_dofs(t, o); }

  // Full specialization of n_dofs_at_node() function for every dimension.
  // Discontinuous L2 elements only have interior nodes
  template <> unsigned int FE<0,L2_HIERARCHIC>::n_dofs_at_node(const ElemType, const Order, const unsigned int) { return 0; }
  template <> unsigned int FE<1,L2_HIERARCHIC>::n_dofs_at_node(const ElemType, const Order, const unsigned int) { return 0; }
  template <> unsigned int FE<2,L2_HIERARCHIC>::n_dofs_at_node(const ElemType, const Order, const unsigned int) { return 0; }
  template <> unsigned int FE<3,L2_HIERARCHIC>::n_dofs_at_node(const ElemType, const Order, const unsigned int) { return 0; }

  // Full specialization of n_dofs_per_elem() function for every dimension.
  template <> unsigned int FE<0,L2_HIERARCHIC>::n_dofs_per_elem(const ElemType t, const Order o) { return l2_hierarchic_n_dofs(t, o); }
  template <> unsigned int FE<1,L2_HIERARCHIC>::n_dofs_per_elem(const ElemType t, const Order o) { return l2_hierarchic_n_dofs(t, o); }
  template <> unsigned int FE<2,L2_HIERARCHIC>::n_dofs_per_elem(const ElemType t, const Order o) { return l2_hierarchic_n_dofs(t, o); }
  template <> unsigned int FE<3,L2_HIERARCHIC>::n_dofs_per_elem(const ElemType t, const Order o) { return l2_hierarchic_n_dofs(t, o); }

  // L2 Hierarchic FEMs are C^0 continuous
  template <> FEContinuity FE<0,L2_HIERARCHIC>::get_continuity() const { return C_ZERO; }
  template <> FEContinuity FE<1,L2_HIERARCHIC>::get_continuity() const { return C_ZERO; }
  template <> FEContinuity FE<2,L2_HIERARCHIC>::get_continuity() const { return C_ZERO; }
  template <> FEContinuity FE<3,L2_HIERARCHIC>::get_continuity() const { return C_ZERO; }

  // L2 Hierarchic FEMs are hierarchic (duh!)
  template <> bool FE<0,L2_HIERARCHIC>::is_hierarchic() const { return true; }
  template <> bool FE<1,L2_HIERARCHIC>::is_hierarchic() const { return true; }
  template <> bool FE<2,L2_HIERARCHIC>::is_hierarchic() const { return true; }
  template <> bool FE<3,L2_HIERARCHIC>::is_hierarchic() const { return true; }

#ifdef LIBMESH_ENABLE_AMR
  // compute_constraints() specializations are only needed for 2 and 3D
  template <>
  void FE<2,L2_HIERARCHIC>::compute_constraints (DofConstraints &constraints,
						 DofMap &dof_map,
						 const unsigned int variable_number,
						 const Elem* elem)
  { compute_proj_constraints(constraints, dof_map, variable_number, elem); }

  template <>
  void FE<3,L2_HIERARCHIC>::compute_constraints (DofConstraints &constraints,
						 DofMap &dof_map,
						 const unsigned int variable_number,
						 const Elem* elem)
  { compute_proj_constraints(constraints, dof_map, variable_number, elem); }
#endif // #ifdef LIBMESH_ENABLE_AMR

  // L2-Hierarchic FEM shapes need reinit
  template <> bool FE<0,L2_HIERARCHIC>::shapes_need_reinit() const { return true; }
  template <> bool FE<1,L2_HIERARCHIC>::shapes_need_reinit() const { return true; }
  template <> bool FE<2,L2_HIERARCHIC>::shapes_need_reinit() const { return true; }
  template <> bool FE<3,L2_HIERARCHIC>::shapes_need_reinit() const { return true; }

} // namespace libMesh
<commit_msg>Fixed get_continuity in fe_l2_hierarchic.C, it should return DISCONTINUOUS. Also, change compute_constraints to a NOOP.<commit_after>// The libMesh Finite Element Library.
// Copyright (C) 2002-2012 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner

// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.

// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.

// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

// Local includes
#include "elem.h"
#include "fe.h"
#include "fe_interface.h"

namespace libMesh
{

  // ------------------------------------------------------------
  // Hierarchic-specific implementations

  // Anonymous namespace for local helper functions
  namespace {

    void l2_hierarchic_nodal_soln(const Elem* elem,
				  const Order order,
				  const std::vector<Number>& elem_soln,
				  std::vector<Number>&       nodal_soln,
				  unsigned Dim)
    {
      const unsigned int n_nodes = elem->n_nodes();

      const ElemType elem_type = elem->type();

      nodal_soln.resize(n_nodes);

      const Order totalorder = static_cast<Order>(order + elem->p_level());

      // FEType object to be passed to various FEInterface functions below.
      FEType fe_type(totalorder, L2_HIERARCHIC);

      switch (totalorder)
	{
	  // Constant shape functions
	case CONSTANT:
	  {
	    libmesh_assert (elem_soln.size() == 1);

	    const Number val = elem_soln[0];

	    for (unsigned int n=0; n<n_nodes; n++)
	      nodal_soln[n] = val;

	    return;
	  }

	  // For other orders do interpolation at the nodes
	  // explicitly.
	default:
	  {

	    const unsigned int n_sf =
	      // FE<Dim,T>::n_shape_functions(elem_type, totalorder);
	      FEInterface::n_shape_functions(Dim, fe_type, elem_type);

	    std::vector<Point> refspace_nodes;
	    FEBase::get_refspace_nodes(elem_type,refspace_nodes);
	    libmesh_assert (refspace_nodes.size() == n_nodes);

	    for (unsigned int n=0; n<n_nodes; n++)
	      {
		libmesh_assert (elem_soln.size() == n_sf);

		// Zero before summation
		nodal_soln[n] = 0;

		// u_i = Sum (alpha_i phi_i)
		for (unsigned int i=0; i<n_sf; i++)
		  nodal_soln[n] += elem_soln[i] *
		    // FE<Dim,T>::shape(elem, order, i, mapped_point);
		    FEInterface::shape(Dim, fe_type, elem, i, refspace_nodes[n]);
	      }

	    return;
	  }
	}
    } // l2_hierarchic_nodal_soln()

    unsigned int l2_hierarchic_n_dofs(const ElemType t, const Order o)
    {
      libmesh_assert (o > 0);
      switch (t)
	{
	case NODEELEM:
	  return 1;
	case EDGE2:
	case EDGE3:
	  return (o+1);
	case QUAD4:
	case QUAD8:
	case QUAD9:
	  return ((o+1)*(o+1));
	case HEX8:
	case HEX20:
	case HEX27:
	  return ((o+1)*(o+1)*(o+1));
	case TRI6:
	  return ((o+1)*(o+2)/2);
	default:
	  libmesh_error();
	}

      libmesh_error();
      return 0;
    } // l2_hierarchic_n_dofs()

  } // anonymous namespace

  // Do full-specialization of nodal_soln() function for every
  // dimension, instead of explicit instantiation at the end of this
  // file.
  // This could be macro-ified so that it fits on one line...
  template <>
  void FE<0,L2_HIERARCHIC>::nodal_soln(const Elem* elem,
				       const Order order,
				       const std::vector<Number>& elem_soln,
				       std::vector<Number>& nodal_soln)
  { l2_hierarchic_nodal_soln(elem, order, elem_soln, nodal_soln, /*Dim=*/0); }

  template <>
  void FE<1,L2_HIERARCHIC>::nodal_soln(const Elem* elem,
				       const Order order,
				       const std::vector<Number>& elem_soln,
				       std::vector<Number>& nodal_soln)
  { l2_hierarchic_nodal_soln(elem, order, elem_soln, nodal_soln, /*Dim=*/1); }

  template <>
  void FE<2,L2_HIERARCHIC>::nodal_soln(const Elem* elem,
				       const Order order,
				       const std::vector<Number>& elem_soln,
				       std::vector<Number>& nodal_soln)
  { l2_hierarchic_nodal_soln(elem, order, elem_soln, nodal_soln, /*Dim=*/2); }

  template <>
  void FE<3,L2_HIERARCHIC>::nodal_soln(const Elem* elem,
				       const Order order,
				       const std::vector<Number>& elem_soln,
				       std::vector<Number>& nodal_soln)
  { l2_hierarchic_nodal_soln(elem, order, elem_soln, nodal_soln, /*Dim=*/3); }

  // Full specialization of n_dofs() function for every dimension
  template <> unsigned int FE<0,L2_HIERARCHIC>::n_dofs(const ElemType t, const Order o) { return l2_hierarchic_n_dofs(t, o); }
  template <> unsigned int FE<1,L2_HIERARCHIC>::n_dofs(const ElemType t, const Order o) { return l2_hierarchic_n_dofs(t, o); }
  template <> unsigned int FE<2,L2_HIERARCHIC>::n_dofs(const ElemType t, const Order o) { return l2_hierarchic_n_dofs(t, o); }
  template <> unsigned int FE<3,L2_HIERARCHIC>::n_dofs(const ElemType t, const Order o) { return l2_hierarchic_n_dofs(t, o); }

  // Full specialization of n_dofs_at_node() function for every dimension.
  // Discontinuous L2 elements only have interior nodes
  template <> unsigned int FE<0,L2_HIERARCHIC>::n_dofs_at_node(const ElemType, const Order, const unsigned int) { return 0; }
  template <> unsigned int FE<1,L2_HIERARCHIC>::n_dofs_at_node(const ElemType, const Order, const unsigned int) { return 0; }
  template <> unsigned int FE<2,L2_HIERARCHIC>::n_dofs_at_node(const ElemType, const Order, const unsigned int) { return 0; }
  template <> unsigned int FE<3,L2_HIERARCHIC>::n_dofs_at_node(const ElemType, const Order, const unsigned int) { return 0; }

  // Full specialization of n_dofs_per_elem() function for every dimension.
  template <> unsigned int FE<0,L2_HIERARCHIC>::n_dofs_per_elem(const ElemType t, const Order o) { return l2_hierarchic_n_dofs(t, o); }
  template <> unsigned int FE<1,L2_HIERARCHIC>::n_dofs_per_elem(const ElemType t, const Order o) { return l2_hierarchic_n_dofs(t, o); }
  template <> unsigned int FE<2,L2_HIERARCHIC>::n_dofs_per_elem(const ElemType t, const Order o) { return l2_hierarchic_n_dofs(t, o); }
  template <> unsigned int FE<3,L2_HIERARCHIC>::n_dofs_per_elem(const ElemType t, const Order o) { return l2_hierarchic_n_dofs(t, o); }

  // L2 Hierarchic FEMs are C^0 continuous
  template <> FEContinuity FE<0,L2_HIERARCHIC>::get_continuity() const { return DISCONTINUOUS; }
  template <> FEContinuity FE<1,L2_HIERARCHIC>::get_continuity() const { return DISCONTINUOUS; }
  template <> FEContinuity FE<2,L2_HIERARCHIC>::get_continuity() const { return DISCONTINUOUS; }
  template <> FEContinuity FE<3,L2_HIERARCHIC>::get_continuity() const { return DISCONTINUOUS; }

  // L2 Hierarchic FEMs are hierarchic (duh!)
  template <> bool FE<0,L2_HIERARCHIC>::is_hierarchic() const { return true; }
  template <> bool FE<1,L2_HIERARCHIC>::is_hierarchic() const { return true; }
  template <> bool FE<2,L2_HIERARCHIC>::is_hierarchic() const { return true; }
  template <> bool FE<3,L2_HIERARCHIC>::is_hierarchic() const { return true; }

#ifdef LIBMESH_ENABLE_AMR
  // compute_constraints() is a NOOP for DISCONTINOUS FE's
  template <>
  void FE<2,L2_HIERARCHIC>::compute_constraints (DofConstraints &,
						 DofMap &,
						 const unsigned int,
						 const Elem*)
  { }

  template <>
  void FE<3,L2_HIERARCHIC>::compute_constraints (DofConstraints &,
						 DofMap &,
						 const unsigned int,
						 const Elem*)
  { }
#endif // #ifdef LIBMESH_ENABLE_AMR

  // L2-Hierarchic FEM shapes need reinit
  template <> bool FE<0,L2_HIERARCHIC>::shapes_need_reinit() const { return true; }
  template <> bool FE<1,L2_HIERARCHIC>::shapes_need_reinit() const { return true; }
  template <> bool FE<2,L2_HIERARCHIC>::shapes_need_reinit() const { return true; }
  template <> bool FE<3,L2_HIERARCHIC>::shapes_need_reinit() const { return true; }

} // namespace libMesh
<|endoftext|>


<commit_before>#ifndef IMAP__H__
#define IMAP__H__

#include "zip.hpp"

#include <utility>
#include <type_traits>

namespace iter {

    namespace detail {

    template <std::size_t Index, typename Functor, typename Tup>
    struct Expander {
        template <typename... Ts>
        static auto call(Functor&& f, Tup&& tup, Ts&&... args)
            -> decltype(Expander<Index-1, Functor, Tup>::call(
                    std::forward<Functor>(f),
                    std::forward<Tup>(tup),
                    std::get<Index-1>(tup),
                    std::forward<Ts>(args)...))
        {
            // recurse
            return Expander<Index-1, Functor, Tup>::call(
                    std::forward<Functor>(f),
                    std::forward<Tup>(tup),
                    std::get<Index-1>(tup), // pull out one element
                    std::forward<Ts>(args)...); // everything already expanded
        }
    };

    template <typename Functor, typename Tup>
    struct Expander<0, Functor, Tup> {
        template <typename... Ts>
        static auto call(Functor&& f, Tup&&, Ts&&... args)
            -> decltype(f(std::forward<Ts>(args)...))
        {
            static_assert(
                std::tuple_size<
                    typename std::remove_reference<Tup>::type>::value
                    == sizeof...(Ts),
                "tuple has not been fully expanded");
            return f(std::forward<Ts>(args)...); // the actual call
        }
    };

    template <typename Functor, typename Tup>
    auto call_with_tuple(Functor&& f, Tup&& tup)
        -> decltype(Expander<std::tuple_size<
                    typename std::remove_reference<Tup>::type>::value,
                    Functor, Tup>::call(
                        std::forward<Functor>(f),
                        std::forward<Tup>(tup)))
    {
        return Expander<std::tuple_size<
            typename std::remove_reference<Tup>::type>::value,
            Functor, Tup>::call(
                std::forward<Functor>(f),
                std::forward<Tup>(tup));
    }

    } // end detail

    //Forward declarations of IMap and imap
    template <typename MapFunc, typename... Containers>
    class IMap;

    template <typename MapFunc, typename... Containers>
    IMap<MapFunc, Containers...> imap(MapFunc, Containers&&...);

    template <typename MapFunc, typename... Containers>
    class IMap {
        // The imap function is the only thing allowed to create a IMap
        friend IMap imap<MapFunc, Containers...>(MapFunc, Containers&& ...);

        using ZippedType = decltype(zip(std::declval<Containers>()...));
        using ZippedIterType = iterator_type<ZippedType>;
        private:
            MapFunc map_func;
            ZippedType zipped;

            // Value constructor for use only in the imap function
            IMap(MapFunc map_func, Containers&& ... containers) :
                map_func(map_func),
                zipped(zip(std::forward<Containers>(containers)...))
            { }
            IMap() = delete;
            IMap& operator=(const IMap&) = delete;

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

            class Iterator {
                private:
                    MapFunc map_func;
                    mutable ZippedIterType zipiter;

                public:
                    Iterator(MapFunc map_func, ZippedIterType zipiter) :
                        map_func(map_func),
                        zipiter(zipiter)
                    { }

                    auto operator*() ->
                        decltype(detail::call_with_tuple(
                                    this->map_func, *(this->zipiter)))
                    {
                        return detail::call_with_tuple(
                                this->map_func, *(this->zipiter));
                    }

                    Iterator& operator++() {
                        ++this->zipiter;
                        return *this;
                    }

                    bool operator!=(const Iterator& other) const {
                        return this->zipiter != other.zipiter;
                    }
            };

            Iterator begin() {
                return {this->map_func, this->zipped.begin()};
            }

            Iterator end() {
                return {this->map_func, this->zipped.end()};
            }

    };

    // Helper function to instantiate a IMap
    template <typename MapFunc, typename... Containers>
    IMap<MapFunc, Containers...> imap(
            MapFunc map_func, Containers&& ... containers) {
        return {map_func, std::forward<Containers>(containers)...};
    }

}

#endif //ifndef IMAP__H__
<commit_msg>removes mutable (idk why it was ever there)<commit_after>#ifndef IMAP__H__
#define IMAP__H__

#include "zip.hpp"

#include <utility>
#include <type_traits>

namespace iter {

    namespace detail {

    template <std::size_t Index, typename Functor, typename Tup>
    struct Expander {
        template <typename... Ts>
        static auto call(Functor&& f, Tup&& tup, Ts&&... args)
            -> decltype(Expander<Index-1, Functor, Tup>::call(
                    std::forward<Functor>(f),
                    std::forward<Tup>(tup),
                    std::get<Index-1>(tup),
                    std::forward<Ts>(args)...))
        {
            // recurse
            return Expander<Index-1, Functor, Tup>::call(
                    std::forward<Functor>(f),
                    std::forward<Tup>(tup),
                    std::get<Index-1>(tup), // pull out one element
                    std::forward<Ts>(args)...); // everything already expanded
        }
    };

    template <typename Functor, typename Tup>
    struct Expander<0, Functor, Tup> {
        template <typename... Ts>
        static auto call(Functor&& f, Tup&&, Ts&&... args)
            -> decltype(f(std::forward<Ts>(args)...))
        {
            static_assert(
                std::tuple_size<
                    typename std::remove_reference<Tup>::type>::value
                    == sizeof...(Ts),
                "tuple has not been fully expanded");
            return f(std::forward<Ts>(args)...); // the actual call
        }
    };

    template <typename Functor, typename Tup>
    auto call_with_tuple(Functor&& f, Tup&& tup)
        -> decltype(Expander<std::tuple_size<
                    typename std::remove_reference<Tup>::type>::value,
                    Functor, Tup>::call(
                        std::forward<Functor>(f),
                        std::forward<Tup>(tup)))
    {
        return Expander<std::tuple_size<
            typename std::remove_reference<Tup>::type>::value,
            Functor, Tup>::call(
                std::forward<Functor>(f),
                std::forward<Tup>(tup));
    }

    } // end detail

    //Forward declarations of IMap and imap
    template <typename MapFunc, typename... Containers>
    class IMap;

    template <typename MapFunc, typename... Containers>
    IMap<MapFunc, Containers...> imap(MapFunc, Containers&&...);

    template <typename MapFunc, typename... Containers>
    class IMap {
        // The imap function is the only thing allowed to create a IMap
        friend IMap imap<MapFunc, Containers...>(MapFunc, Containers&& ...);

        using ZippedType = decltype(zip(std::declval<Containers>()...));
        using ZippedIterType = iterator_type<ZippedType>;
        private:
            MapFunc map_func;
            ZippedType zipped;

            // Value constructor for use only in the imap function
            IMap(MapFunc map_func, Containers&& ... containers) :
                map_func(map_func),
                zipped(zip(std::forward<Containers>(containers)...))
            { }
            IMap() = delete;
            IMap& operator=(const IMap&) = delete;

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

            class Iterator {
                private:
                    MapFunc map_func;
                    ZippedIterType zipiter;

                public:
                    Iterator(MapFunc map_func, ZippedIterType zipiter) :
                        map_func(map_func),
                        zipiter(zipiter)
                    { }

                    auto operator*() ->
                        decltype(detail::call_with_tuple(
                                    this->map_func, *(this->zipiter)))
                    {
                        return detail::call_with_tuple(
                                this->map_func, *(this->zipiter));
                    }

                    Iterator& operator++() {
                        ++this->zipiter;
                        return *this;
                    }

                    bool operator!=(const Iterator& other) const {
                        return this->zipiter != other.zipiter;
                    }
            };

            Iterator begin() {
                return {this->map_func, this->zipped.begin()};
            }

            Iterator end() {
                return {this->map_func, this->zipped.end()};
            }

    };

    // Helper function to instantiate a IMap
    template <typename MapFunc, typename... Containers>
    IMap<MapFunc, Containers...> imap(
            MapFunc map_func, Containers&& ... containers) {
        return {map_func, std::forward<Containers>(containers)...};
    }

}

#endif //ifndef IMAP__H__
<|endoftext|>


<commit_before>/**
 * @file
 * @brief Executable running the framework
 */

#include <atomic>
#include <csignal>
#include <cstdlib>
#include <fstream>
#include <memory>
#include <string>
#include <utility>

#include "core/Allpix.hpp"
#include "core/config/ConfigManager.hpp"
#include "core/geometry/GeometryManager.hpp"
#include "core/utils/exceptions.h"

#include "core/utils/log.h"

using namespace allpix;

void clean();
void abort_handler(int);
void interrupt_handler(int);

std::unique_ptr<Allpix> apx;
std::atomic<bool> apx_ready{false};

/**
 * @brief Handle user abort (CTRL+\) which should stop the framework immediately
 * @note This handler is actually not fully reliable (but otherwise crashing is okay...)
 */
void abort_handler(int) {
    // Output interrupt message and clean
    LOG(FATAL) << "Aborting!";
    clean();

    // Ignore any segmentation fault that may arise after this
    std::signal(SIGSEGV, SIG_IGN); // NOLINT
    std::abort();
}

/**
 * @brief Handle termination request (CTRL+C) as soon as possible while keeping the program flow
 */
void interrupt_handler(int) {
    // Stop the framework if it is loaded
    if(apx_ready) {
        LOG(STATUS) << "Interrupted! Finishing up current event...";
        apx->terminate();
    }
}

/**
 * @brief Clean the environment when closing application
 */
void clean() {
    Log::finish();
    if(apx_ready) {
        apx.reset();
    }
}

/**
 * @brief Main function running the application
 */
int main(int argc, const char* argv[]) {
    // Add cout as the default logging stream
    Log::addStream(std::cout);

    // Install abort handler (CTRL+\)
    std::signal(SIGQUIT, abort_handler);

    // Install interrupt handler (CTRL+C)
    std::signal(SIGINT, interrupt_handler);

    // If no arguments are provided, print the help:
    bool print_help = false;
    int return_code = 0;
    if(argc == 1) {
        print_help = true;
        return_code = 1;
    }

    // Parse arguments
    std::string config_file_name;
    std::string log_file_name;
    std::vector<std::string> module_options;
    std::vector<std::string> detector_options;
    for(int i = 1; i < argc; i++) {
        if(strcmp(argv[i], "-h") == 0) {
            print_help = true;
        } else if(strcmp(argv[i], "--version") == 0) {
            std::cout << "Allpix Squared version " << ALLPIX_PROJECT_VERSION << std::endl;
            std::cout << "               built on " << ALLPIX_BUILD_TIME << std::endl;
            std::cout << std::endl;
            std::cout << "Copyright (c) 2017-2018 CERN and the Allpix Squared authors." << std::endl << std::endl;
            std::cout << "This software is distributed under the terms of the MIT License." << std::endl;
            std::cout << "In applying this license, CERN does not waive the privileges and immunities" << std::endl;
            std::cout << "granted to it by virtue of its status as an Intergovernmental Organization" << std::endl;
            std::cout << "or submit itself to any jurisdiction." << std::endl;
            clean();
            return 0;
        } else if(strcmp(argv[i], "-v") == 0 && (i + 1 < argc)) {
            try {
                LogLevel log_level = Log::getLevelFromString(std::string(argv[++i]));
                Log::setReportingLevel(log_level);
            } catch(std::invalid_argument& e) {
                LOG(ERROR) << "Invalid verbosity level \"" << std::string(argv[i]) << "\", ignoring overwrite";
            }
        } else if(strcmp(argv[i], "-c") == 0 && (i + 1 < argc)) {
            config_file_name = std::string(argv[++i]);
        } else if(strcmp(argv[i], "-l") == 0 && (i + 1 < argc)) {
            log_file_name = std::string(argv[++i]);
        } else if(strcmp(argv[i], "-o") == 0 && (i + 1 < argc)) {
            module_options.emplace_back(std::string(argv[++i]));
        } else if(strcmp(argv[i], "-g") == 0 && (i + 1 < argc)) {
            detector_options.emplace_back(std::string(argv[++i]));
        } else {
            LOG(ERROR) << "Unrecognized command line argument \"" << argv[i] << "\"";
            print_help = true;
            return_code = 1;
        }
    }

    // Print help if requested or no arguments given
    if(print_help) {
        std::cout << "Allpix Squared" << std::endl;
        std::cout << "Generic Pixel Detector Simulation Framework" << std::endl;
        std::cout << std::endl;
        std::cout << "Usage: allpix -c <file> [OPTIONS]" << std::endl;
        std::cout << std::endl;
        std::cout << "Options:" << std::endl;
        std::cout << "  -c <file>    configuration file to be used" << std::endl;
        std::cout << "  -l <file>    file to log to besides standard output" << std::endl;
        std::cout << "  -o <option>  extra module configuration option(s) to pass" << std::endl;
        std::cout << "  -g <option>  extra detector configuration options(s) to pass" << std::endl;
        std::cout << "  -v <level>   verbosity level, overwriting the global level" << std::endl;
        std::cout << "  --version    print version information and quit" << std::endl;
        std::cout << std::endl;
        std::cout << "For more help, please see <https://cern.ch/allpix-squared>" << std::endl;
        clean();
        return return_code;
    }

    // Check if we have a configuration file
    if(config_file_name.empty()) {
        LOG(FATAL) << "No configuration file provided! See usage info with \"allpix -h\"";
        clean();
        return 1;
    }

    // Add an extra file to log too if possible
    // NOTE: this stream should be available for the duration of the logging
    std::ofstream log_file;
    if(!log_file_name.empty()) {
        log_file.open(log_file_name, std::ios_base::out | std::ios_base::trunc);
        if(!log_file.good()) {
            LOG(FATAL) << "Cannot write to provided log file! Check if permissions are sufficient.";
            clean();
            return 1;
        }

        Log::addStream(log_file);
    }

    try {
        // Construct main Allpix object
        apx = std::make_unique<Allpix>(config_file_name, module_options, detector_options);
        apx_ready = true;

        // Load modules
        apx->load();

        // Initialize modules (pre-run)
        apx->init();

        // Run modules and event-loop
        apx->run();

        // Finalize modules (post-run)
        apx->finalize();
    } catch(ConfigurationError& e) {
        LOG(FATAL) << "Error in the configuration:" << std::endl
                   << e.what() << std::endl
                   << "The configuration needs to be updated. Cannot continue.";
        return_code = 1;
    } catch(RuntimeError& e) {
        LOG(FATAL) << "Error during execution of run:" << std::endl
                   << e.what() << std::endl
                   << "Please check your configuration and modules. Cannot continue.";
        return_code = 1;
    } catch(LogicError& e) {
        LOG(FATAL) << "Error in the logic of module:" << std::endl
                   << e.what() << std::endl
                   << "Module has to be properly defined. Cannot continue.";
        return_code = 1;
    } catch(std::exception& e) {
        LOG(FATAL) << "Fatal internal error" << std::endl << e.what() << std::endl << "Cannot continue.";
        return_code = 127;
    }

    // Finish the logging
    clean();

    return return_code;
}
<commit_msg>Executable: terminate gracefully at SIGTERM<commit_after>/**
 * @file
 * @brief Executable running the framework
 */

#include <atomic>
#include <csignal>
#include <cstdlib>
#include <fstream>
#include <memory>
#include <string>
#include <utility>

#include "core/Allpix.hpp"
#include "core/config/ConfigManager.hpp"
#include "core/geometry/GeometryManager.hpp"
#include "core/utils/exceptions.h"

#include "core/utils/log.h"

using namespace allpix;

void clean();
void abort_handler(int);
void interrupt_handler(int);

std::unique_ptr<Allpix> apx;
std::atomic<bool> apx_ready{false};

/**
 * @brief Handle user abort (CTRL+\) which should stop the framework immediately
 * @note This handler is actually not fully reliable (but otherwise crashing is okay...)
 */
void abort_handler(int) {
    // Output interrupt message and clean
    LOG(FATAL) << "Aborting!";
    clean();

    // Ignore any segmentation fault that may arise after this
    std::signal(SIGSEGV, SIG_IGN); // NOLINT
    std::abort();
}

/**
 * @brief Handle termination request (CTRL+C) as soon as possible while keeping the program flow
 */
void interrupt_handler(int) {
    // Stop the framework if it is loaded
    if(apx_ready) {
        LOG(STATUS) << "Interrupted! Finishing up current event...";
        apx->terminate();
    }
}

/**
 * @brief Clean the environment when closing application
 */
void clean() {
    Log::finish();
    if(apx_ready) {
        apx.reset();
    }
}

/**
 * @brief Main function running the application
 */
int main(int argc, const char* argv[]) {
    // Add cout as the default logging stream
    Log::addStream(std::cout);

    // Install abort handler (CTRL+\)
    std::signal(SIGQUIT, abort_handler);

    // Install interrupt handler (CTRL+C)
    std::signal(SIGINT, interrupt_handler);

    // Install termination handler (e.g. from "kill"). Gracefully exit, finish last event and quit
    std::signal(SIGTERM, interrupt_handler);

    // If no arguments are provided, print the help:
    bool print_help = false;
    int return_code = 0;
    if(argc == 1) {
        print_help = true;
        return_code = 1;
    }

    // Parse arguments
    std::string config_file_name;
    std::string log_file_name;
    std::vector<std::string> module_options;
    std::vector<std::string> detector_options;
    for(int i = 1; i < argc; i++) {
        if(strcmp(argv[i], "-h") == 0) {
            print_help = true;
        } else if(strcmp(argv[i], "--version") == 0) {
            std::cout << "Allpix Squared version " << ALLPIX_PROJECT_VERSION << std::endl;
            std::cout << "               built on " << ALLPIX_BUILD_TIME << std::endl;
            std::cout << std::endl;
            std::cout << "Copyright (c) 2017-2018 CERN and the Allpix Squared authors." << std::endl << std::endl;
            std::cout << "This software is distributed under the terms of the MIT License." << std::endl;
            std::cout << "In applying this license, CERN does not waive the privileges and immunities" << std::endl;
            std::cout << "granted to it by virtue of its status as an Intergovernmental Organization" << std::endl;
            std::cout << "or submit itself to any jurisdiction." << std::endl;
            clean();
            return 0;
        } else if(strcmp(argv[i], "-v") == 0 && (i + 1 < argc)) {
            try {
                LogLevel log_level = Log::getLevelFromString(std::string(argv[++i]));
                Log::setReportingLevel(log_level);
            } catch(std::invalid_argument& e) {
                LOG(ERROR) << "Invalid verbosity level \"" << std::string(argv[i]) << "\", ignoring overwrite";
            }
        } else if(strcmp(argv[i], "-c") == 0 && (i + 1 < argc)) {
            config_file_name = std::string(argv[++i]);
        } else if(strcmp(argv[i], "-l") == 0 && (i + 1 < argc)) {
            log_file_name = std::string(argv[++i]);
        } else if(strcmp(argv[i], "-o") == 0 && (i + 1 < argc)) {
            module_options.emplace_back(std::string(argv[++i]));
        } else if(strcmp(argv[i], "-g") == 0 && (i + 1 < argc)) {
            detector_options.emplace_back(std::string(argv[++i]));
        } else {
            LOG(ERROR) << "Unrecognized command line argument \"" << argv[i] << "\"";
            print_help = true;
            return_code = 1;
        }
    }

    // Print help if requested or no arguments given
    if(print_help) {
        std::cout << "Allpix Squared" << std::endl;
        std::cout << "Generic Pixel Detector Simulation Framework" << std::endl;
        std::cout << std::endl;
        std::cout << "Usage: allpix -c <file> [OPTIONS]" << std::endl;
        std::cout << std::endl;
        std::cout << "Options:" << std::endl;
        std::cout << "  -c <file>    configuration file to be used" << std::endl;
        std::cout << "  -l <file>    file to log to besides standard output" << std::endl;
        std::cout << "  -o <option>  extra module configuration option(s) to pass" << std::endl;
        std::cout << "  -g <option>  extra detector configuration options(s) to pass" << std::endl;
        std::cout << "  -v <level>   verbosity level, overwriting the global level" << std::endl;
        std::cout << "  --version    print version information and quit" << std::endl;
        std::cout << std::endl;
        std::cout << "For more help, please see <https://cern.ch/allpix-squared>" << std::endl;
        clean();
        return return_code;
    }

    // Check if we have a configuration file
    if(config_file_name.empty()) {
        LOG(FATAL) << "No configuration file provided! See usage info with \"allpix -h\"";
        clean();
        return 1;
    }

    // Add an extra file to log too if possible
    // NOTE: this stream should be available for the duration of the logging
    std::ofstream log_file;
    if(!log_file_name.empty()) {
        log_file.open(log_file_name, std::ios_base::out | std::ios_base::trunc);
        if(!log_file.good()) {
            LOG(FATAL) << "Cannot write to provided log file! Check if permissions are sufficient.";
            clean();
            return 1;
        }

        Log::addStream(log_file);
    }

    try {
        // Construct main Allpix object
        apx = std::make_unique<Allpix>(config_file_name, module_options, detector_options);
        apx_ready = true;

        // Load modules
        apx->load();

        // Initialize modules (pre-run)
        apx->init();

        // Run modules and event-loop
        apx->run();

        // Finalize modules (post-run)
        apx->finalize();
    } catch(ConfigurationError& e) {
        LOG(FATAL) << "Error in the configuration:" << std::endl
                   << e.what() << std::endl
                   << "The configuration needs to be updated. Cannot continue.";
        return_code = 1;
    } catch(RuntimeError& e) {
        LOG(FATAL) << "Error during execution of run:" << std::endl
                   << e.what() << std::endl
                   << "Please check your configuration and modules. Cannot continue.";
        return_code = 1;
    } catch(LogicError& e) {
        LOG(FATAL) << "Error in the logic of module:" << std::endl
                   << e.what() << std::endl
                   << "Module has to be properly defined. Cannot continue.";
        return_code = 1;
    } catch(std::exception& e) {
        LOG(FATAL) << "Fatal internal error" << std::endl << e.what() << std::endl << "Cannot continue.";
        return_code = 127;
    }

    // Finish the logging
    clean();

    return return_code;
}
<|endoftext|>