<commit_before>/*

Copyright (c) 2007, Arvid Norberg
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 author 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.

*/

#ifdef TORRENT_DEBUG

#ifdef __APPLE__
#include <AvailabilityMacros.h>
#endif

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

// uClibc++ doesn't have cxxabi.h
#if defined __GNUC__ && __GNUC__ >= 3 \
	&& !defined __UCLIBCXX_MAJOR__

#include <cxxabi.h>

std::string demangle(char const* name)
{
// in case this string comes
	// this is needed on linux
	char const* start = strchr(name, '(');
	if (start != 0)
	{
		++start;
	}
	else
	{
		// this is needed on macos x
		start = strstr(name, "0x");
		if (start != 0)
		{
			start = strchr(start, ' ');
			if (start != 0) ++start;
			else start = name;
		}
		else start = name;
	}

	char const* end = strchr(start, '+');
	if (end) while (*(end-1) == ' ') --end;

	std::string in;
	if (end == 0) in.assign(start);
	else in.assign(start, end);

	size_t len;
	int status;
	char* unmangled = ::abi::__cxa_demangle(in.c_str(), 0, &len, &status);
	if (unmangled == 0) return in;
	std::string ret(unmangled);
	free(unmangled);
	return ret;
}

#else
std::string demangle(char const* name) { return name; }
#endif

#include <stdlib.h>
#include <stdio.h>
#include <signal.h>
#include "libtorrent/version.hpp"

// execinfo.h is available in the MacOS X 10.5 SDK.
#if (defined __linux__ || (defined __APPLE__ && MAC_OS_X_VERSION_MIN_REQUIRED >= 1050))
#include <execinfo.h>

void print_backtrace(char* out, int len)
{
	void* stack[50];
	int size = backtrace(stack, 50);
	char** symbols = backtrace_symbols(stack, size);

	for (int i = 1; i < size && len > 0; ++i)
	{
		int ret = snprintf(out, len, "%d: %s\n", i, demangle(symbols[i]).c_str());
		out += ret;
		len -= ret;
	}

	free(symbols);
}
#else

void print_backtrace(FILE* out, char const* label) {}

#endif

#if TORRENT_PRODUCTION_ASSERTS
char const* libtorrent_assert_log = "asserts.log";
#endif

void assert_fail(char const* expr, int line, char const* file, char const* function, char const* value)
{
#if TORRENT_PRODUCTION_ASSERTS
	FILE* out = fopen(libtorrent_assert_log, "a+");
	if (out == 0) out = stderr;
#else
	FILE* out = stderr;
#endif

	char stack[8192];
	print_backtrace(stack, sizeof(stack));

	fprintf(out, "assertion failed. Please file a bugreport at "
		"http://code.rasterbar.com/libtorrent/newticket\n"
		"Please include the following information:\n\n"
		"version: " LIBTORRENT_VERSION "\n"
		"%s\n"
		"file: '%s'\n"
		"line: %d\n"
		"function: %s\n"
		"expression: %s\n"
		"%s%s\n"
		"stack:\n"
		"%s\n"
		, LIBTORRENT_REVISION, file, line, function, expr
		, value ? value : "", value ? "\n" : ""
		, stack);

	// if production asserts are defined, don't abort, just print the error
#if TORRENT_PRODUCTION_ASSERTS
	if (out != stderr) fclose(out);
#else
 	// send SIGINT to the current process
 	// to break into the debugger
 	raise(SIGINT);
 	abort();
#endif
}

#else

void assert_fail(char const* expr, int line, char const* file, char const* function) {}

#endif

<commit_msg>we need backtraces for asio-debugging as well<commit_after>/*

Copyright (c) 2007, Arvid Norberg
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 author 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.

*/

#if defined TORRENT_DEBUG || defined TORRENT_ASIO_DEBUGGING

#ifdef __APPLE__
#include <AvailabilityMacros.h>
#endif

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

// uClibc++ doesn't have cxxabi.h
#if defined __GNUC__ && __GNUC__ >= 3 \
	&& !defined __UCLIBCXX_MAJOR__

#include <cxxabi.h>

std::string demangle(char const* name)
{
// in case this string comes
	// this is needed on linux
	char const* start = strchr(name, '(');
	if (start != 0)
	{
		++start;
	}
	else
	{
		// this is needed on macos x
		start = strstr(name, "0x");
		if (start != 0)
		{
			start = strchr(start, ' ');
			if (start != 0) ++start;
			else start = name;
		}
		else start = name;
	}

	char const* end = strchr(start, '+');
	if (end) while (*(end-1) == ' ') --end;

	std::string in;
	if (end == 0) in.assign(start);
	else in.assign(start, end);

	size_t len;
	int status;
	char* unmangled = ::abi::__cxa_demangle(in.c_str(), 0, &len, &status);
	if (unmangled == 0) return in;
	std::string ret(unmangled);
	free(unmangled);
	return ret;
}

#else
std::string demangle(char const* name) { return name; }
#endif

#include <stdlib.h>
#include <stdio.h>
#include <signal.h>
#include "libtorrent/version.hpp"

// execinfo.h is available in the MacOS X 10.5 SDK.
#if (defined __linux__ || (defined __APPLE__ && MAC_OS_X_VERSION_MIN_REQUIRED >= 1050))
#include <execinfo.h>

void print_backtrace(char* out, int len)
{
	void* stack[50];
	int size = backtrace(stack, 50);
	char** symbols = backtrace_symbols(stack, size);

	for (int i = 1; i < size && len > 0; ++i)
	{
		int ret = snprintf(out, len, "%d: %s\n", i, demangle(symbols[i]).c_str());
		out += ret;
		len -= ret;
	}

	free(symbols);
}
#else

void print_backtrace(FILE* out, char const* label) {}

#endif

#if TORRENT_PRODUCTION_ASSERTS
char const* libtorrent_assert_log = "asserts.log";
#endif

void assert_fail(char const* expr, int line, char const* file, char const* function, char const* value)
{
#if TORRENT_PRODUCTION_ASSERTS
	FILE* out = fopen(libtorrent_assert_log, "a+");
	if (out == 0) out = stderr;
#else
	FILE* out = stderr;
#endif

	char stack[8192];
	print_backtrace(stack, sizeof(stack));

	fprintf(out, "assertion failed. Please file a bugreport at "
		"http://code.rasterbar.com/libtorrent/newticket\n"
		"Please include the following information:\n\n"
		"version: " LIBTORRENT_VERSION "\n"
		"%s\n"
		"file: '%s'\n"
		"line: %d\n"
		"function: %s\n"
		"expression: %s\n"
		"%s%s\n"
		"stack:\n"
		"%s\n"
		, LIBTORRENT_REVISION, file, line, function, expr
		, value ? value : "", value ? "\n" : ""
		, stack);

	// if production asserts are defined, don't abort, just print the error
#if TORRENT_PRODUCTION_ASSERTS
	if (out != stderr) fclose(out);
#else
 	// send SIGINT to the current process
 	// to break into the debugger
 	raise(SIGINT);
 	abort();
#endif
}

#else

void assert_fail(char const* expr, int line, char const* file, char const* function) {}

#endif

<|endoftext|>


<commit_before>/* mbed Microcontroller Library
 * Copyright (c) 2015 ARM Limited
 *
 * 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 <stdio.h>
#include "TestHarness.h"
#include "mbed.h"

/* Serial asynch cross */

#if !DEVICE_SERIAL || !DEVICE_SERIAL_ASYNCH
#error serial_asynch requires asynch Serial
#endif

// Device config
#if defined(TARGET_K64F)
#define TEST_SERIAL_ONE_TX_PIN PTC17 // uart3
#define TEST_SERIAL_TWO_RX_PIN PTD2  // uart2

#elif defined(TARGET_K66F)
#define TEST_SERIAL_ONE_TX_PIN PTD3 // uart2
#define TEST_SERIAL_TWO_RX_PIN PTC16  // uart3

#elif defined(TARGET_EFM32LG_STK3600) || defined(TARGET_EFM32GG_STK3700) || defined(TARGET_EFM32WG_STK3800)
#define TEST_SERIAL_ONE_TX_PIN PD0   // usart1
#define TEST_SERIAL_TWO_RX_PIN PC3   // usart2

#elif defined(TARGET_EFM32ZG_STK3200)
#error "Target not supported (only 2 serial ports available, need 3)"

#elif defined(TARGET_EFM32HG_STK3400)
#define TEST_SERIAL_ONE_TX_PIN PE10 // usart0
#define TEST_SERIAL_TWO_RX_PIN PC1  // usart1

#elif defined(TARGET_B96B_F446VE)
#define TEST_SERIAL_ONE_TX_PIN D1   // UART2
#define TEST_SERIAL_TWO_RX_PIN D4   // UART5

#elif defined(TARGET_NUCLEO_L152RE)
#define TEST_SERIAL_ONE_TX_PIN PB_10   // UART3
#define TEST_SERIAL_TWO_RX_PIN PA_10   // UART1

#elif defined(TARGET_NUCLEO_F103RB)
#define TEST_SERIAL_ONE_TX_PIN PB_10   // UART3
#define TEST_SERIAL_TWO_RX_PIN PA_10   // UART1

#elif defined(TARGET_NUCLEO_F207ZG)
#define TEST_SERIAL_ONE_TX_PIN PC_12   // UART5
#define TEST_SERIAL_TWO_RX_PIN PC_11   // UART4

#elif defined(TARGET_DISCO_F334C8)
#define TEST_SERIAL_ONE_TX_PIN PB_10   // UART3
#define TEST_SERIAL_TWO_RX_PIN PA_10   // UART1

#elif defined(TARGET_NUCLEO_F302R8)
#define TEST_SERIAL_ONE_TX_PIN PB_10   // UART3
#define TEST_SERIAL_TWO_RX_PIN PA_10   // UART1

#elif defined(TARGET_NUCLEO_F303RE)
#define TEST_SERIAL_ONE_TX_PIN PB_10   // UART3
#define TEST_SERIAL_TWO_RX_PIN PA_10   // UART1

#elif defined(TARGET_NUCLEO_F334R8)
#define TEST_SERIAL_ONE_TX_PIN PB_10   // UART3
#define TEST_SERIAL_TWO_RX_PIN PA_10   // UART1

#elif defined(TARGET_DISCO_F429ZI)
#define TEST_SERIAL_ONE_TX_PIN PD_5   // UART2
#define TEST_SERIAL_TWO_RX_PIN PG_9   // UART6

#elif defined(TARGET_NUCLEO_F401RE)
#define TEST_SERIAL_ONE_TX_PIN PB_6  // UART1
#define TEST_SERIAL_TWO_RX_PIN PC_7  // UART6

#elif defined(TARGET_NUCLEO_F411RE)
#define TEST_SERIAL_ONE_TX_PIN PB_6  // UART1
#define TEST_SERIAL_TWO_RX_PIN PC_7  // UART6

#elif defined(TARGET_NUCLEO_F446RE)
#define TEST_SERIAL_ONE_TX_PIN PB_6  // UART1
#define TEST_SERIAL_TWO_RX_PIN PC_7  // UART6

#elif defined(TARGET_NUCLEO_F410RB)
#define TEST_SERIAL_ONE_TX_PIN PB_6  // UART1
#define TEST_SERIAL_TWO_RX_PIN PC_7  // UART6

#elif defined(TARGET_NUCLEO_F429ZI)
#define TEST_SERIAL_ONE_TX_PIN PE_8  // UART7
#define TEST_SERIAL_TWO_RX_PIN PG_9  // UART6

#elif defined(TARGET_NUCLEO_F446ZE)
#define TEST_SERIAL_ONE_TX_PIN PB_6  // UART1
#define TEST_SERIAL_TWO_RX_PIN PG_9  // UART6

#elif defined(TARGET_NUCLEO_L476RG)
#define TEST_SERIAL_ONE_TX_PIN PB_10   // UART3
#define TEST_SERIAL_TWO_RX_PIN PA_10   // UART1

#elif defined(TARGET_RZ_A1H)
#define TEST_SERIAL_ONE_TX_PIN P8_14  // UART4
#define TEST_SERIAL_TWO_RX_PIN P8_11  // UART5

#else

#error Target not supported
#endif

// Test config
#define SHORT_XFR 3
#define LONG_XFR 16
#define TEST_BYTE_TX_BASE 0x5555
#define TEST_BYTE_RX      0x5A5A

volatile int tx_event_flag;
volatile bool tx_complete;

volatile int rx_event_flag;
volatile bool rx_complete;

void cb_tx_done(int event)
{
    tx_complete = true;
    tx_event_flag = event;
}

void cb_rx_done(int event)
{
    rx_complete = true;
    rx_event_flag = event;
}

TEST_GROUP(Serial_Asynchronous)
{
    uint8_t tx_buf[LONG_XFR];
    uint8_t rx_buf[LONG_XFR];

    Serial *serial_tx;
    Serial *serial_rx;
    event_callback_t tx_callback;
    event_callback_t rx_callback;

    void setup()
    {
        serial_tx = new Serial(TEST_SERIAL_ONE_TX_PIN, NC);
        serial_rx = new Serial(NC, TEST_SERIAL_TWO_RX_PIN);
        tx_complete = false;
        tx_event_flag = 0;
        rx_complete = false;
        rx_event_flag = 0;
        tx_callback.attach(cb_tx_done);
        rx_callback.attach(cb_rx_done);

        // Set the default value of tx_buf
        for (uint32_t i = 0; i < sizeof(tx_buf); i++) {
            tx_buf[i] = i + TEST_BYTE_TX_BASE;
        }
        memset(rx_buf, TEST_BYTE_RX, sizeof(rx_buf));
    }

    void teardown()
    {
        delete serial_tx;
        serial_tx = NULL;
        delete serial_rx;
        serial_rx = NULL;

    }

    uint32_t cmpnbufc(uint8_t expect, uint8_t *actual, uint32_t offset, uint32_t end, const char *file, uint32_t line)
    {
        uint32_t i;
        for (i = offset; i < end; i++){
            if (expect != actual[i]) {
                break;
            }
        }
        if (i < end) {
            CHECK_EQUAL_LOCATION((int)expect, (int)actual[i], file, line);
        }
        CHECK_EQUAL_LOCATION(end, i, file, line);
        return i;
    }

    uint32_t cmpnbuf(uint8_t *expect, uint8_t *actual, uint32_t offset, uint32_t end, const char *file, uint32_t line)
    {
        uint32_t i;
        for (i = offset; i < end; i++){
            if (expect[i] != actual[i]) {
                break;
            }
        }
        if (i < end) {
            CHECK_EQUAL_LOCATION((int)expect[i], (int)actual[i], file, line);
        }
        CHECK_EQUAL_LOCATION(end, i, file, line);
        return i;
    }

};

TEST(Serial_Asynchronous, short_tx_0_rx)
{
    int rc;
    rc = serial_tx->write(tx_buf, SHORT_XFR, tx_callback, -1);
    CHECK_EQUAL(0, rc);

    while (!tx_complete);

    CHECK_EQUAL(SERIAL_EVENT_TX_COMPLETE, tx_event_flag);
    // rx buffer unchanged
    cmpnbufc(TEST_BYTE_RX, rx_buf, 0, sizeof(rx_buf), __FILE__, __LINE__);
}

TEST(Serial_Asynchronous, short_tx_short_rx)
{
    int rc;
    serial_rx->read(rx_buf, SHORT_XFR, rx_callback, -1);
    rc = serial_tx->write(tx_buf, SHORT_XFR, tx_callback, -1);
    CHECK_EQUAL(0, rc);

    while ((!tx_complete) || (!rx_complete));

    CHECK_EQUAL(SERIAL_EVENT_TX_COMPLETE, tx_event_flag);
    CHECK_EQUAL(SERIAL_EVENT_RX_COMPLETE, rx_event_flag);

    // Check that the receive buffer contains the fill byte.
    cmpnbuf(tx_buf, rx_buf, 0, SHORT_XFR, __FILE__, __LINE__);
    // Check that remaining portion of the receive buffer contains the rx test byte
    cmpnbufc(TEST_BYTE_RX, rx_buf, SHORT_XFR, sizeof(rx_buf), __FILE__, __LINE__);
}

TEST(Serial_Asynchronous, long_tx_long_rx)
{
    int rc;
    serial_rx->read(rx_buf, LONG_XFR, rx_callback, -1);
    rc = serial_tx->write(tx_buf, LONG_XFR, tx_callback, -1);
    CHECK_EQUAL(0, rc);

    while ((!tx_complete) || (!rx_complete));

    CHECK_EQUAL(SERIAL_EVENT_TX_COMPLETE, tx_event_flag);
    CHECK_EQUAL(SERIAL_EVENT_RX_COMPLETE, rx_event_flag);

    // Check that the receive buffer contains the fill byte.
    cmpnbuf(tx_buf, rx_buf, 0, LONG_XFR, __FILE__, __LINE__);
    // Check that remaining portion of the receive buffer contains the rx test byte
    cmpnbufc(TEST_BYTE_RX, rx_buf, LONG_XFR, sizeof(rx_buf), __FILE__, __LINE__);
}

TEST(Serial_Asynchronous, rx_parity_error)
{
    int rc;
    // Set different parity for RX and TX
    serial_rx->format(8, SerialBase::Even, 1);
    serial_tx->format(8, SerialBase::Odd, 1);
    serial_rx->read(rx_buf, LONG_XFR, rx_callback, -1);
    rc = serial_tx->write(tx_buf, LONG_XFR, tx_callback, -1);
    CHECK_EQUAL(0, rc);

    while ((!tx_complete) || (!rx_complete));

    CHECK_EQUAL(SERIAL_EVENT_TX_COMPLETE, tx_event_flag);
    CHECK_EQUAL(SERIAL_EVENT_RX_PARITY_ERROR, rx_event_flag);
}

TEST(Serial_Asynchronous, rx_framing_error)
{
   int rc;
   serial_tx->baud(4800);
   serial_rx->read(rx_buf, LONG_XFR, rx_callback, -1);
   rc = serial_tx->write(tx_buf, LONG_XFR, tx_callback, -1);
   CHECK_EQUAL(0, rc);

   while ((!tx_complete) || (!rx_complete));

   CHECK_EQUAL(SERIAL_EVENT_TX_COMPLETE, tx_event_flag);
   CHECK_EQUAL(SERIAL_EVENT_RX_FRAMING_ERROR, rx_event_flag);
}

TEST(Serial_Asynchronous, char_matching_success)
{
    // match found
    serial_rx->read(rx_buf, LONG_XFR, rx_callback, -1, (uint8_t)(TEST_BYTE_TX_BASE+5));
    serial_tx->write(tx_buf, LONG_XFR, tx_callback, -1);

    while ((!tx_complete) || (!rx_complete));

    CHECK_EQUAL(SERIAL_EVENT_TX_COMPLETE, tx_event_flag);
    CHECK_EQUAL(SERIAL_EVENT_RX_CHARACTER_MATCH, rx_event_flag);

    cmpnbufc(TEST_BYTE_RX, rx_buf, 5, sizeof(rx_buf), __FILE__, __LINE__);
}

TEST(Serial_Asynchronous, char_matching_failed)
{
    // no match found (specified match char is not in tx buffer)
    serial_rx->read(rx_buf, LONG_XFR, rx_callback, -1, (uint8_t)(TEST_BYTE_TX_BASE  + sizeof(tx_buf)));
    serial_tx->write(tx_buf, LONG_XFR, tx_callback, -1);

    while ((!tx_complete) || (!rx_complete));

    CHECK_EQUAL(SERIAL_EVENT_TX_COMPLETE, tx_event_flag);
    CHECK_EQUAL(SERIAL_EVENT_RX_COMPLETE, rx_event_flag);

    cmpnbuf(tx_buf, rx_buf, 0, LONG_XFR, __FILE__, __LINE__);
}

TEST(Serial_Asynchronous, char_matching_with_complete)
{
    serial_rx->read(rx_buf, LONG_XFR, rx_callback, -1, (uint8_t)(TEST_BYTE_TX_BASE  + sizeof(tx_buf) - 1));
    serial_tx->write(tx_buf, LONG_XFR, tx_callback, -1);

    while ((!tx_complete) || (!rx_complete));

    CHECK_EQUAL(SERIAL_EVENT_TX_COMPLETE, tx_event_flag);
    CHECK_EQUAL((SERIAL_EVENT_RX_COMPLETE | SERIAL_EVENT_RX_CHARACTER_MATCH), rx_event_flag);

    cmpnbuf(tx_buf, rx_buf, 0, LONG_XFR, __FILE__, __LINE__);
}
<commit_msg>STM32F7 - Add tests for asynchronous serial<commit_after>/* mbed Microcontroller Library
 * Copyright (c) 2015 ARM Limited
 *
 * 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 <stdio.h>
#include "TestHarness.h"
#include "mbed.h"

/* Serial asynch cross */

#if !DEVICE_SERIAL || !DEVICE_SERIAL_ASYNCH
#error serial_asynch requires asynch Serial
#endif

// Device config
#if defined(TARGET_K64F)
#define TEST_SERIAL_ONE_TX_PIN PTC17 // uart3
#define TEST_SERIAL_TWO_RX_PIN PTD2  // uart2

#elif defined(TARGET_K66F)
#define TEST_SERIAL_ONE_TX_PIN PTD3 // uart2
#define TEST_SERIAL_TWO_RX_PIN PTC16  // uart3

#elif defined(TARGET_EFM32LG_STK3600) || defined(TARGET_EFM32GG_STK3700) || defined(TARGET_EFM32WG_STK3800)
#define TEST_SERIAL_ONE_TX_PIN PD0   // usart1
#define TEST_SERIAL_TWO_RX_PIN PC3   // usart2

#elif defined(TARGET_EFM32ZG_STK3200)
#error "Target not supported (only 2 serial ports available, need 3)"

#elif defined(TARGET_EFM32HG_STK3400)
#define TEST_SERIAL_ONE_TX_PIN PE10 // usart0
#define TEST_SERIAL_TWO_RX_PIN PC1  // usart1

#elif defined(TARGET_B96B_F446VE)
#define TEST_SERIAL_ONE_TX_PIN D1   // UART2
#define TEST_SERIAL_TWO_RX_PIN D4   // UART5

#elif defined(TARGET_NUCLEO_L152RE)
#define TEST_SERIAL_ONE_TX_PIN PB_10   // UART3
#define TEST_SERIAL_TWO_RX_PIN PA_10   // UART1

#elif defined(TARGET_NUCLEO_F103RB)
#define TEST_SERIAL_ONE_TX_PIN PB_10   // UART3
#define TEST_SERIAL_TWO_RX_PIN PA_10   // UART1

#elif defined(TARGET_NUCLEO_F207ZG)
#define TEST_SERIAL_ONE_TX_PIN PC_12   // UART5
#define TEST_SERIAL_TWO_RX_PIN PC_11   // UART4

#elif defined(TARGET_DISCO_F334C8)
#define TEST_SERIAL_ONE_TX_PIN PB_10   // UART3
#define TEST_SERIAL_TWO_RX_PIN PA_10   // UART1

#elif defined(TARGET_NUCLEO_F302R8)
#define TEST_SERIAL_ONE_TX_PIN PB_10   // UART3
#define TEST_SERIAL_TWO_RX_PIN PA_10   // UART1

#elif defined(TARGET_NUCLEO_F303RE)
#define TEST_SERIAL_ONE_TX_PIN PB_10   // UART3
#define TEST_SERIAL_TWO_RX_PIN PA_10   // UART1

#elif defined(TARGET_NUCLEO_F334R8)
#define TEST_SERIAL_ONE_TX_PIN PB_10   // UART3
#define TEST_SERIAL_TWO_RX_PIN PA_10   // UART1

#elif defined(TARGET_DISCO_F429ZI)
#define TEST_SERIAL_ONE_TX_PIN PD_5   // UART2
#define TEST_SERIAL_TWO_RX_PIN PG_9   // UART6

#elif defined(TARGET_NUCLEO_F401RE)
#define TEST_SERIAL_ONE_TX_PIN PB_6  // UART1
#define TEST_SERIAL_TWO_RX_PIN PC_7  // UART6

#elif defined(TARGET_NUCLEO_F411RE)
#define TEST_SERIAL_ONE_TX_PIN PB_6  // UART1
#define TEST_SERIAL_TWO_RX_PIN PC_7  // UART6

#elif defined(TARGET_NUCLEO_F446RE)
#define TEST_SERIAL_ONE_TX_PIN PB_6  // UART1
#define TEST_SERIAL_TWO_RX_PIN PC_7  // UART6

#elif defined(TARGET_NUCLEO_F410RB)
#define TEST_SERIAL_ONE_TX_PIN PB_6  // UART1
#define TEST_SERIAL_TWO_RX_PIN PC_7  // UART6

#elif defined(TARGET_NUCLEO_F429ZI)
#define TEST_SERIAL_ONE_TX_PIN PE_8  // UART7
#define TEST_SERIAL_TWO_RX_PIN PG_9  // UART6

#elif defined(TARGET_NUCLEO_F446ZE)
#define TEST_SERIAL_ONE_TX_PIN PB_6  // UART1
#define TEST_SERIAL_TWO_RX_PIN PG_9  // UART6

#elif defined(TARGET_DISCO_F746NG)
#define TEST_SERIAL_ONE_TX_PIN PC_6  // UART6
#define TEST_SERIAL_TWO_RX_PIN PF_6  // UART7

#elif defined(TARGET_NUCLEO_F746ZG)
#define TEST_SERIAL_ONE_TX_PIN PC_12  // UART5
#define TEST_SERIAL_TWO_RX_PIN PC_11  // UART4

#elif defined(TARGET_NUCLEO_F767ZI)
#define TEST_SERIAL_ONE_TX_PIN PC_12  // UART5
#define TEST_SERIAL_TWO_RX_PIN PC_11  // UART4

#elif defined(TARGET_NUCLEO_L476RG)
#define TEST_SERIAL_ONE_TX_PIN PB_10   // UART3
#define TEST_SERIAL_TWO_RX_PIN PA_10   // UART1

#elif defined(TARGET_RZ_A1H)
#define TEST_SERIAL_ONE_TX_PIN P8_14  // UART4
#define TEST_SERIAL_TWO_RX_PIN P8_11  // UART5

#else

#error Target not supported
#endif

// Test config
#define SHORT_XFR 3
#define LONG_XFR 16
#define TEST_BYTE_TX_BASE 0x5555
#define TEST_BYTE_RX      0x5A5A

volatile int tx_event_flag;
volatile bool tx_complete;

volatile int rx_event_flag;
volatile bool rx_complete;

void cb_tx_done(int event)
{
    tx_complete = true;
    tx_event_flag = event;
}

void cb_rx_done(int event)
{
    rx_complete = true;
    rx_event_flag = event;
}

TEST_GROUP(Serial_Asynchronous)
{
    uint8_t tx_buf[LONG_XFR];
    uint8_t rx_buf[LONG_XFR];

    Serial *serial_tx;
    Serial *serial_rx;
    event_callback_t tx_callback;
    event_callback_t rx_callback;

    void setup()
    {
        serial_tx = new Serial(TEST_SERIAL_ONE_TX_PIN, NC);
        serial_rx = new Serial(NC, TEST_SERIAL_TWO_RX_PIN);
        tx_complete = false;
        tx_event_flag = 0;
        rx_complete = false;
        rx_event_flag = 0;
        tx_callback.attach(cb_tx_done);
        rx_callback.attach(cb_rx_done);

        // Set the default value of tx_buf
        for (uint32_t i = 0; i < sizeof(tx_buf); i++) {
            tx_buf[i] = i + TEST_BYTE_TX_BASE;
        }
        memset(rx_buf, TEST_BYTE_RX, sizeof(rx_buf));
    }

    void teardown()
    {
        delete serial_tx;
        serial_tx = NULL;
        delete serial_rx;
        serial_rx = NULL;

    }

    uint32_t cmpnbufc(uint8_t expect, uint8_t *actual, uint32_t offset, uint32_t end, const char *file, uint32_t line)
    {
        uint32_t i;
        for (i = offset; i < end; i++){
            if (expect != actual[i]) {
                break;
            }
        }
        if (i < end) {
            CHECK_EQUAL_LOCATION((int)expect, (int)actual[i], file, line);
        }
        CHECK_EQUAL_LOCATION(end, i, file, line);
        return i;
    }

    uint32_t cmpnbuf(uint8_t *expect, uint8_t *actual, uint32_t offset, uint32_t end, const char *file, uint32_t line)
    {
        uint32_t i;
        for (i = offset; i < end; i++){
            if (expect[i] != actual[i]) {
                break;
            }
        }
        if (i < end) {
            CHECK_EQUAL_LOCATION((int)expect[i], (int)actual[i], file, line);
        }
        CHECK_EQUAL_LOCATION(end, i, file, line);
        return i;
    }

};

TEST(Serial_Asynchronous, short_tx_0_rx)
{
    int rc;
    rc = serial_tx->write(tx_buf, SHORT_XFR, tx_callback, -1);
    CHECK_EQUAL(0, rc);

    while (!tx_complete);

    CHECK_EQUAL(SERIAL_EVENT_TX_COMPLETE, tx_event_flag);
    // rx buffer unchanged
    cmpnbufc(TEST_BYTE_RX, rx_buf, 0, sizeof(rx_buf), __FILE__, __LINE__);
}

TEST(Serial_Asynchronous, short_tx_short_rx)
{
    int rc;
    serial_rx->read(rx_buf, SHORT_XFR, rx_callback, -1);
    rc = serial_tx->write(tx_buf, SHORT_XFR, tx_callback, -1);
    CHECK_EQUAL(0, rc);

    while ((!tx_complete) || (!rx_complete));

    CHECK_EQUAL(SERIAL_EVENT_TX_COMPLETE, tx_event_flag);
    CHECK_EQUAL(SERIAL_EVENT_RX_COMPLETE, rx_event_flag);

    // Check that the receive buffer contains the fill byte.
    cmpnbuf(tx_buf, rx_buf, 0, SHORT_XFR, __FILE__, __LINE__);
    // Check that remaining portion of the receive buffer contains the rx test byte
    cmpnbufc(TEST_BYTE_RX, rx_buf, SHORT_XFR, sizeof(rx_buf), __FILE__, __LINE__);
}

TEST(Serial_Asynchronous, long_tx_long_rx)
{
    int rc;
    serial_rx->read(rx_buf, LONG_XFR, rx_callback, -1);
    rc = serial_tx->write(tx_buf, LONG_XFR, tx_callback, -1);
    CHECK_EQUAL(0, rc);

    while ((!tx_complete) || (!rx_complete));

    CHECK_EQUAL(SERIAL_EVENT_TX_COMPLETE, tx_event_flag);
    CHECK_EQUAL(SERIAL_EVENT_RX_COMPLETE, rx_event_flag);

    // Check that the receive buffer contains the fill byte.
    cmpnbuf(tx_buf, rx_buf, 0, LONG_XFR, __FILE__, __LINE__);
    // Check that remaining portion of the receive buffer contains the rx test byte
    cmpnbufc(TEST_BYTE_RX, rx_buf, LONG_XFR, sizeof(rx_buf), __FILE__, __LINE__);
}

TEST(Serial_Asynchronous, rx_parity_error)
{
    int rc;
    // Set different parity for RX and TX
    serial_rx->format(8, SerialBase::Even, 1);
    serial_tx->format(8, SerialBase::Odd, 1);
    serial_rx->read(rx_buf, LONG_XFR, rx_callback, -1);
    rc = serial_tx->write(tx_buf, LONG_XFR, tx_callback, -1);
    CHECK_EQUAL(0, rc);

    while ((!tx_complete) || (!rx_complete));

    CHECK_EQUAL(SERIAL_EVENT_TX_COMPLETE, tx_event_flag);
    CHECK_EQUAL(SERIAL_EVENT_RX_PARITY_ERROR, rx_event_flag);
}

TEST(Serial_Asynchronous, rx_framing_error)
{
   int rc;
   serial_tx->baud(4800);
   serial_rx->read(rx_buf, LONG_XFR, rx_callback, -1);
   rc = serial_tx->write(tx_buf, LONG_XFR, tx_callback, -1);
   CHECK_EQUAL(0, rc);

   while ((!tx_complete) || (!rx_complete));

   CHECK_EQUAL(SERIAL_EVENT_TX_COMPLETE, tx_event_flag);
   CHECK_EQUAL(SERIAL_EVENT_RX_FRAMING_ERROR, rx_event_flag);
}

TEST(Serial_Asynchronous, char_matching_success)
{
    // match found
    serial_rx->read(rx_buf, LONG_XFR, rx_callback, -1, (uint8_t)(TEST_BYTE_TX_BASE+5));
    serial_tx->write(tx_buf, LONG_XFR, tx_callback, -1);

    while ((!tx_complete) || (!rx_complete));

    CHECK_EQUAL(SERIAL_EVENT_TX_COMPLETE, tx_event_flag);
    CHECK_EQUAL(SERIAL_EVENT_RX_CHARACTER_MATCH, rx_event_flag);

    cmpnbufc(TEST_BYTE_RX, rx_buf, 5, sizeof(rx_buf), __FILE__, __LINE__);
}

TEST(Serial_Asynchronous, char_matching_failed)
{
    // no match found (specified match char is not in tx buffer)
    serial_rx->read(rx_buf, LONG_XFR, rx_callback, -1, (uint8_t)(TEST_BYTE_TX_BASE  + sizeof(tx_buf)));
    serial_tx->write(tx_buf, LONG_XFR, tx_callback, -1);

    while ((!tx_complete) || (!rx_complete));

    CHECK_EQUAL(SERIAL_EVENT_TX_COMPLETE, tx_event_flag);
    CHECK_EQUAL(SERIAL_EVENT_RX_COMPLETE, rx_event_flag);

    cmpnbuf(tx_buf, rx_buf, 0, LONG_XFR, __FILE__, __LINE__);
}

TEST(Serial_Asynchronous, char_matching_with_complete)
{
    serial_rx->read(rx_buf, LONG_XFR, rx_callback, -1, (uint8_t)(TEST_BYTE_TX_BASE  + sizeof(tx_buf) - 1));
    serial_tx->write(tx_buf, LONG_XFR, tx_callback, -1);

    while ((!tx_complete) || (!rx_complete));

    CHECK_EQUAL(SERIAL_EVENT_TX_COMPLETE, tx_event_flag);
    CHECK_EQUAL((SERIAL_EVENT_RX_COMPLETE | SERIAL_EVENT_RX_CHARACTER_MATCH), rx_event_flag);

    cmpnbuf(tx_buf, rx_buf, 0, LONG_XFR, __FILE__, __LINE__);
}
<|endoftext|>


<commit_before>/*

Copyright (c) 2007, Arvid Norberg
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 author 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.

*/

#ifdef __GNUC__

#include <cxxabi.h>
#include <string>
#include <cstring>
#include <stdlib.h>

std::string demangle(char const* name)
{
// in case this string comes
	char const* start = strchr(name, '(');
	if (start != 0) ++start;
	else start = name;
	char const* end = strchr(start, '+');

	std::string in;
	if (end == 0) in.assign(start);
	else in.assign(start, end);

	size_t len;
	int status;
	char* unmangled = ::abi::__cxa_demangle(in.c_str(), 0, &len, &status);
	if (unmangled == 0) return in;
	std::string ret(unmangled);
	free(unmangled);
	return ret;
}

#endif

#ifdef TORRENT_DEBUG

#include <stdlib.h>
#include <stdio.h>
#include <signal.h>
#if defined __linux__ && defined __GNUC__
#include <execinfo.h>
#endif

void assert_fail(char const* expr, int line, char const* file, char const* function)
{

	fprintf(stderr, "assertion failed. Please file a bugreport at "
		"http://code.rasterbar.com/libtorrent/newticket\n"
		"Please include the following information:\n\n"
		"file: '%s'\n"
		"line: %d\n"
		"function: %s\n"
		"expression: %s\n"
		"stack:\n", file, line, function, expr);

#if defined __linux__ && defined __GNUC__
	void* stack[50];
	int size = backtrace(stack, 50);
	char** symbols = backtrace_symbols(stack, size);

	for (int i = 0; i < size; ++i)
	{
		fprintf(stderr, "%d: %s\n", i, demangle(symbols[i]).c_str());
	}

	free(symbols);
#endif
 	// send SIGINT to the current process
 	// to break into the debugger
 	raise(SIGINT);
 	abort();
}

#else

void assert_fail(char const* expr, int line, char const* file, char const* function) {}

#endif

<commit_msg>simplified assert.cpp, included stack-traces on Mac (assumes 10.5). Makes it easier to debug asio hangs since the backtraces can be used externally<commit_after>/*

Copyright (c) 2007, Arvid Norberg
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 author 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.

*/

#ifdef TORRENT_DEBUG

#ifdef __GNUC__

#include <cxxabi.h>
#include <string>
#include <cstring>
#include <stdlib.h>

std::string demangle(char const* name)
{
// in case this string comes
	// this is needed on linux
	char const* start = strchr(name, '(');
	if (start != 0)
	{
		++start;
	}
	else
	{
		// this is needed on macos x
		start = strstr(name, "0x");
		if (start != 0)
		{
			start = strchr(start, ' ');
			if (start != 0) ++start;
			else start = name;
		}
		else start = name;
	}

	char const* end = strchr(start, '+');
	if (end) while (*(end-1) == ' ') --end;

	std::string in;
	if (end == 0) in.assign(start);
	else in.assign(start, end);

	size_t len;
	int status;
	char* unmangled = ::abi::__cxa_demangle(in.c_str(), 0, &len, &status);
	if (unmangled == 0) return in;
	std::string ret(unmangled);
	free(unmangled);
	return ret;
}

#endif

#include <stdlib.h>
#include <stdio.h>
#include <signal.h>

// execinfo.h is available in the MacOS X 10.5 SDK. I
// don't know of a define to distiguish between SDKs, so
// for now, all Mac builds are assumed to be using 10.5
// for debug builds. If this fails for you, just remove
// the __APPLE__ check
#if (defined __linux__ || defined __APPLE__)
#include <execinfo.h>

void print_backtrace(char const* label)
{
	void* stack[50];
	int size = backtrace(stack, 50);
	char** symbols = backtrace_symbols(stack, size);

	fprintf(stderr, "%s\n", label);
	for (int i = 1; i < size; ++i)
	{
		fprintf(stderr, "%d: %s\n", i, demangle(symbols[i]).c_str());
	}

	free(symbols);
}
#else

void print_backtrace(char const* label) {}

#endif

void assert_fail(char const* expr, int line, char const* file, char const* function)
{

	fprintf(stderr, "assertion failed. Please file a bugreport at "
		"http://code.rasterbar.com/libtorrent/newticket\n"
		"Please include the following information:\n\n"
		"file: '%s'\n"
		"line: %d\n"
		"function: %s\n"
		"expression: %s\n", file, line, function, expr);

	print_backtrace("stack:");

 	// send SIGINT to the current process
 	// to break into the debugger
 	raise(SIGINT);
 	abort();
}

#else

void assert_fail(char const* expr, int line, char const* file, char const* function) {}

#endif

<|endoftext|>


<commit_before>#include <mach/mach_port.h>
#include <mach/mach_interface.h>
#include <mach/mach_init.h>

#include <IOKit/pwr_mgt/IOPMLib.h>
#include <IOKit/IOMessage.h>

#include <pthread.h>

#include <uv.h>

#include "pm.h"
#include "constants.h"

io_connect_t  root_port; // a reference to the Root Power Domain IOService
IONotificationPortRef  notifyPortRef; // notification port allocated by IORegisterForSystemPower
pthread_t lookupThread;
pthread_mutex_t notify_mutex;
pthread_cond_t notify_cv;
char *notify_msg;
bool isRunning = false;

void NotifyCallBack(void * refCon, io_service_t service, natural_t messageType, void * messageArgument )
{
    // fprintf(stderr, "messageType %08lx, arg %08lx\n",
    //        (long unsigned int)messageType,
    //        (long unsigned int)messageArgument );

    switch ( messageType )
    {

        case kIOMessageCanSystemSleep:
            /* Idle sleep is about to kick in. This message will not be sent for forced sleep.
             Applications have a chance to prevent sleep by calling IOCancelPowerChange.
             Most applications should not prevent idle sleep.

             Power Management waits up to 30 seconds for you to either allow or deny idle
             sleep. If you don't acknowledge this power change by calling either
             IOAllowPowerChange or IOCancelPowerChange, the system will wait 30
             seconds then go to sleep.
             */

            //Uncomment to cancel idle sleep
            //IOCancelPowerChange( root_port, (long)messageArgument );
            // we will allow idle sleep
            // fprintf(stderr, "kIOMessageCanSystemSleep\n");
            IOAllowPowerChange( root_port, (long)messageArgument );
            break;

        case kIOMessageSystemWillSleep:
            /* The system WILL go to sleep. If you do not call IOAllowPowerChange or
             IOCancelPowerChange to acknowledge this message, sleep will be
             delayed by 30 seconds.

             NOTE: If you call IOCancelPowerChange to deny sleep it returns
             kIOReturnSuccess, however the system WILL still go to sleep.
             */
            // fprintf(stderr, "kIOMessageSystemWillSleep\n");

            pthread_mutex_lock(&notify_mutex);
	        notify_msg = (char*) SLEEP_NOTIFY;
	        pthread_cond_signal(&notify_cv);
	        pthread_mutex_unlock(&notify_mutex);

            IOAllowPowerChange( root_port, (long)messageArgument );
            break;

        case kIOMessageSystemWillPowerOn:
            //System has started the wake up process...
            // fprintf(stderr, "kIOMessageSystemWillPowerOn\n");

            // pthread_mutex_lock(&notify_mutex);
	        // strcpy(notify_msg, "waking");
	        // pthread_cond_signal(&notify_cv);
	        // pthread_mutex_unlock(&notify_mutex);

            break;

        case kIOMessageSystemHasPoweredOn:
            //System has finished waking up...
            // fprintf(stderr, "kIOMessageSystemHasPoweredOn\n");

            pthread_mutex_lock(&notify_mutex);
            notify_msg = (char*) WAKE_NOTIFY;
	        pthread_cond_signal(&notify_cv);
	        pthread_mutex_unlock(&notify_mutex);

            break;

        default:
            break;

    }
}

void NotifyAsync(uv_work_t* req)
{
    pthread_mutex_lock(&notify_mutex);
    pthread_cond_wait(&notify_cv, &notify_mutex);
    pthread_mutex_unlock(&notify_mutex);
}

void NotifyFinished(uv_work_t* req)
{
    pthread_mutex_lock(&notify_mutex);
    if (isRunning)
    {
        Notify(notify_msg);
    }
    pthread_mutex_unlock(&notify_mutex);

    uv_queue_work(uv_default_loop(), req, NotifyAsync, (uv_after_work_cb)NotifyFinished);
}

void *RunLoop(void * arg)
{

    // add the notification port to the application runloop
    CFRunLoopAddSource( CFRunLoopGetCurrent(),
                       IONotificationPortGetRunLoopSource(notifyPortRef), kCFRunLoopCommonModes );

    /* Start the run loop to receive sleep notifications. Don't call CFRunLoopRun if this code
     is running on the main thread of a Cocoa or Carbon application. Cocoa and Carbon
     manage the main thread's run loop for you as part of their event handling
     mechanisms.
     */
    CFRunLoopRun();

    // We should never get here
    fprintf(stderr, "Unexpectedly back from CFRunLoopRun()!\n");

    return NULL;
}

void Start()
{
    isRunning = true;
}

void Stop()
{
    isRunning = false;
    pthread_mutex_lock(&notify_mutex);
    pthread_cond_signal(&notify_cv);
    pthread_mutex_unlock(&notify_mutex);
}

void InitPM()
{
    // notifier object, used to deregister later
    io_object_t            notifierObject;
    // this parameter is passed to the callback
    void*                  refCon = NULL;

    // register to receive system sleep notifications

    root_port = IORegisterForSystemPower( refCon, &notifyPortRef, NotifyCallBack, &notifierObject );
    if ( root_port == 0 )
    {
        fprintf(stderr, "IORegisterForSystemPower failed\n");
    }

    pthread_mutex_init(&notify_mutex, NULL);
    pthread_cond_init(&notify_cv, NULL);

    int rc = pthread_create(&lookupThread, NULL, RunLoop, NULL);
    if (rc)
    {
        fprintf(stderr, "ERROR; return code from pthread_create() is %d\n", rc);
        exit(-1);
    }

    uv_work_t* req = new uv_work_t();
    uv_queue_work(uv_default_loop(), req, NotifyAsync, (uv_after_work_cb)NotifyFinished);

    Start();
}<commit_msg>fix stop<commit_after>#include <mach/mach_port.h>
#include <mach/mach_interface.h>
#include <mach/mach_init.h>

#include <IOKit/pwr_mgt/IOPMLib.h>
#include <IOKit/IOMessage.h>

#include <pthread.h>

#include <uv.h>

#include "pm.h"
#include "constants.h"

io_connect_t  root_port; // a reference to the Root Power Domain IOService
IONotificationPortRef  notifyPortRef; // notification port allocated by IORegisterForSystemPower
pthread_t lookupThread;
pthread_mutex_t notify_mutex;
pthread_cond_t notify_cv;
char *notify_msg;
bool isRunning = false;

void NotifyCallBack(void * refCon, io_service_t service, natural_t messageType, void * messageArgument )
{
    // fprintf(stderr, "messageType %08lx, arg %08lx\n",
    //        (long unsigned int)messageType,
    //        (long unsigned int)messageArgument );

    switch ( messageType )
    {

        case kIOMessageCanSystemSleep:
            /* Idle sleep is about to kick in. This message will not be sent for forced sleep.
             Applications have a chance to prevent sleep by calling IOCancelPowerChange.
             Most applications should not prevent idle sleep.

             Power Management waits up to 30 seconds for you to either allow or deny idle
             sleep. If you don't acknowledge this power change by calling either
             IOAllowPowerChange or IOCancelPowerChange, the system will wait 30
             seconds then go to sleep.
             */

            //Uncomment to cancel idle sleep
            //IOCancelPowerChange( root_port, (long)messageArgument );
            // we will allow idle sleep
            // fprintf(stderr, "kIOMessageCanSystemSleep\n");
            IOAllowPowerChange( root_port, (long)messageArgument );
            break;

        case kIOMessageSystemWillSleep:
            /* The system WILL go to sleep. If you do not call IOAllowPowerChange or
             IOCancelPowerChange to acknowledge this message, sleep will be
             delayed by 30 seconds.

             NOTE: If you call IOCancelPowerChange to deny sleep it returns
             kIOReturnSuccess, however the system WILL still go to sleep.
             */
            // fprintf(stderr, "kIOMessageSystemWillSleep\n");

            pthread_mutex_lock(&notify_mutex);
	        notify_msg = (char*) SLEEP_NOTIFY;
	        pthread_cond_signal(&notify_cv);
	        pthread_mutex_unlock(&notify_mutex);

            IOAllowPowerChange( root_port, (long)messageArgument );
            break;

        case kIOMessageSystemWillPowerOn:
            //System has started the wake up process...
            // fprintf(stderr, "kIOMessageSystemWillPowerOn\n");

            // pthread_mutex_lock(&notify_mutex);
	        // strcpy(notify_msg, "waking");
	        // pthread_cond_signal(&notify_cv);
	        // pthread_mutex_unlock(&notify_mutex);

            break;

        case kIOMessageSystemHasPoweredOn:
            //System has finished waking up...
            // fprintf(stderr, "kIOMessageSystemHasPoweredOn\n");

            pthread_mutex_lock(&notify_mutex);
            notify_msg = (char*) WAKE_NOTIFY;
	        pthread_cond_signal(&notify_cv);
	        pthread_mutex_unlock(&notify_mutex);

            break;

        default:
            break;

    }
}

void NotifyAsync(uv_work_t* req)
{
    pthread_mutex_lock(&notify_mutex);
    pthread_cond_wait(&notify_cv, &notify_mutex);
    pthread_mutex_unlock(&notify_mutex);
}

void NotifyFinished(uv_work_t* req)
{
    if (isRunning)
    {
        pthread_mutex_lock(&notify_mutex);
        Notify(notify_msg);
        pthread_mutex_unlock(&notify_mutex);
        uv_queue_work(uv_default_loop(), req, NotifyAsync, (uv_after_work_cb)NotifyFinished);
    }
}

void *RunLoop(void * arg)
{

    // add the notification port to the application runloop
    CFRunLoopAddSource( CFRunLoopGetCurrent(),
                       IONotificationPortGetRunLoopSource(notifyPortRef), kCFRunLoopCommonModes );

    /* Start the run loop to receive sleep notifications. Don't call CFRunLoopRun if this code
     is running on the main thread of a Cocoa or Carbon application. Cocoa and Carbon
     manage the main thread's run loop for you as part of their event handling
     mechanisms.
     */
    CFRunLoopRun();

    // We should never get here
    fprintf(stderr, "Unexpectedly back from CFRunLoopRun()!\n");

    return NULL;
}

void Start()
{
    isRunning = true;
}

void Stop()
{
    isRunning = false;
    pthread_mutex_lock(&notify_mutex);
    pthread_cond_signal(&notify_cv);
    pthread_mutex_unlock(&notify_mutex);
}

void InitPM()
{
    // notifier object, used to deregister later
    io_object_t            notifierObject;
    // this parameter is passed to the callback
    void*                  refCon = NULL;

    // register to receive system sleep notifications

    root_port = IORegisterForSystemPower( refCon, &notifyPortRef, NotifyCallBack, &notifierObject );
    if ( root_port == 0 )
    {
        fprintf(stderr, "IORegisterForSystemPower failed\n");
    }

    pthread_mutex_init(&notify_mutex, NULL);
    pthread_cond_init(&notify_cv, NULL);

    int rc = pthread_create(&lookupThread, NULL, RunLoop, NULL);
    if (rc)
    {
        fprintf(stderr, "ERROR; return code from pthread_create() is %d\n", rc);
        exit(-1);
    }

    uv_work_t* req = new uv_work_t();
    uv_queue_work(uv_default_loop(), req, NotifyAsync, (uv_after_work_cb)NotifyFinished);

    Start();
}<|endoftext|>


<commit_before>/*
  This file is part of KOrganizer.

  Copyright (c) 1998 Preston Brown <pbrown@kde.org>
  Copyright (C) 2003-2004 Reinhold Kainhofer <reinhold@kainhofer.com>

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

  This program 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 General Public License for more details.

  You should have received a copy of the GNU General Public License along
  with this program; if not, write to the Free Software Foundation, Inc.,
  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.

  As a special exception, permission is given to link this program
  with any edition of Qt, and distribute the resulting executable,
  without including the source code for Qt in the source distribution.
*/

#include "calprinter.h"
#include "calprintdefaultplugins.h"

#include "korganizer/corehelper.h"

#include <kvbox.h>
#include <kconfig.h>
#include <kdebug.h>
#include <kdeversion.h>
#include <kstandardguiitem.h>
#include <kcombobox.h>
#include <kprintpreview.h>

#include <QButtonGroup>
#include <QLabel>
#include <QLayout>
#include <QGridLayout>
#include <QGroupBox>
#include <QPushButton>
#include <QRadioButton>
#include <QSplitter>
#include <QStackedWidget>
#include <QPrintDialog>
#include <QPrinter>

#ifndef KORG_NOPRINTER
#include "calprinter.moc"

CalPrinter::CalPrinter( QWidget *parent, Calendar *calendar, KOrg::CoreHelper *helper )
  : QObject( parent )
{
  mParent = parent;
  mConfig = new KConfig( "korganizer_printing.rc", KConfig::OnlyLocal );
  mCoreHelper = helper;

  init( calendar );
}

CalPrinter::~CalPrinter()
{
  mPrintPlugins.clear();
  delete mConfig;
}

void CalPrinter::init( Calendar *calendar )
{
  mCalendar = calendar;

  mPrintPlugins.clear();

  mPrintPlugins = mCoreHelper->loadPrintPlugins();
  mPrintPlugins.prepend( new CalPrintTodos() );
  mPrintPlugins.prepend( new CalPrintMonth() );
  mPrintPlugins.prepend( new CalPrintWeek() );
  mPrintPlugins.prepend( new CalPrintDay() );
  mPrintPlugins.prepend( new CalPrintIncidence() );

  KOrg::PrintPlugin::List::Iterator it = mPrintPlugins.begin();
  for ( ; it != mPrintPlugins.end(); ++it ) {
    if ( *it ) {
      (*it)->setConfig( mConfig );
      (*it)->setCalendar( mCalendar );
      (*it)->setKOrgCoreHelper( mCoreHelper );
      (*it)->doLoadConfig();
    }
  }
}

void CalPrinter::setDateRange( const QDate &fd, const QDate &td )
{
  KOrg::PrintPlugin::List::Iterator it = mPrintPlugins.begin();
  for ( ; it != mPrintPlugins.end(); ++it ) {
    (*it)->setDateRange( fd, td );
  }
}

void CalPrinter::print( int type, const QDate &fd, const QDate &td,
                        Incidence::List selectedIncidences, bool preview )
{
  KOrg::PrintPlugin::List::Iterator it = mPrintPlugins.begin();
  for ( it = mPrintPlugins.begin(); it != mPrintPlugins.end(); ++it ) {
    (*it)->setSelectedIncidences( selectedIncidences );
  }
  CalPrintDialog printDialog( mPrintPlugins, mParent );
  KConfigGroup grp( mConfig, "" ); //orientation setting isn't in a group
  printDialog.setOrientation( CalPrinter::ePrintOrientation( grp.readEntry( "Orientation", 1 ) ) );
  printDialog.setPreview( preview );
  printDialog.setPrintType( type );
  setDateRange( fd, td );

  if ( printDialog.exec() == QDialog::Accepted ) {
    grp.writeEntry( "Orientation", (int)printDialog.orientation() );

    // Save all changes in the dialog
    for ( it = mPrintPlugins.begin(); it != mPrintPlugins.end(); ++it ) {
      (*it)->doSaveConfig();
    }
    doPrint( printDialog.selectedPlugin(), printDialog.orientation(), preview );
  }
  for ( it = mPrintPlugins.begin(); it != mPrintPlugins.end(); ++it ) {
    (*it)->setSelectedIncidences( Incidence::List() );
  }
}

void CalPrinter::doPrint( KOrg::PrintPlugin *selectedStyle,
                          CalPrinter::ePrintOrientation dlgorientation, bool preview )
{
  if ( !selectedStyle ) {
    KMessageBox::error( mParent,
                        i18n( "Unable to print, no valid print style was returned." ),
                        i18n( "Printing error" ) );
    return;
  }

  QPrinter printer;
  switch ( dlgorientation ) {
  case eOrientPlugin:
    printer.setOrientation( selectedStyle->defaultOrientation() );
    break;
  case eOrientPortrait:
    printer.setOrientation( QPrinter::Portrait );
    break;
  case eOrientLandscape:
    printer.setOrientation( QPrinter::Landscape );
    break;
  case eOrientPrinter:
  default:
    break;
  }

  if ( preview ) {
    KPrintPreview printPreview( &printer );
    selectedStyle->doPrint( &printer );
    printPreview.exec();
  } else {
    QPrintDialog printDialog( &printer, mParent );
    if ( printDialog.exec() == QDialog::Accepted ) {
      selectedStyle->doPrint( &printer );
    }
  }
}

void CalPrinter::updateConfig()
{
}

CalPrintDialog::CalPrintDialog( KOrg::PrintPlugin::List plugins, QWidget *parent )
  : KDialog( parent )
{
  setCaption( i18n( "Print" ) );
  setButtons( Ok | Cancel );
  setModal( true );
  KVBox *page = new KVBox( this );
  setMainWidget( page );

  QSplitter *splitter = new QSplitter( page );
  splitter->setOrientation( Qt::Horizontal );

  QGroupBox *typeBox = new QGroupBox( i18n( "Print Style" ), splitter );
  QBoxLayout *typeLayout = new QVBoxLayout( typeBox );
  mTypeGroup = new QButtonGroup( typeBox );

  QWidget *splitterRight = new QWidget( splitter );
  QGridLayout *splitterRightLayout = new QGridLayout( splitterRight );
  splitterRightLayout->setMargin( marginHint() );
  splitterRightLayout->setSpacing( spacingHint() );

  mConfigArea = new QStackedWidget( splitterRight );
  splitterRightLayout->addMultiCellWidget( mConfigArea, 0, 0, 0, 1 );
  QLabel *orientationLabel = new QLabel( i18n( "Page &orientation:" ), splitterRight );
  splitterRightLayout->addWidget( orientationLabel, 1, 0 );

  mOrientationSelection = new KComboBox( splitterRight );
  mOrientationSelection->addItem( i18n( "Use Default Orientation of Selected Style" ) );
  mOrientationSelection->addItem( i18n( "Use Printer Default" ) );
  mOrientationSelection->addItem( i18n( "Portrait" ) );
  mOrientationSelection->addItem( i18n( "Landscape" ) );
  splitterRightLayout->addWidget( mOrientationSelection, 1, 1 );

  // signals and slots connections
  connect( mTypeGroup, SIGNAL( buttonClicked( int ) ), SLOT( setPrintType( int ) ) );
  orientationLabel->setBuddy( mOrientationSelection );

  // First insert the config widgets into the widget stack. This possibly assigns
  // proper ids (when two plugins have the same sortID), so store them in a map
  // and use these new IDs to later sort the plugins for the type selection.
  for ( KOrg::PrintPlugin::List::Iterator it = plugins.begin(); it != plugins.end(); ++it ) {
    int newid = mConfigArea->insertWidget( (*it)->sortID(), (*it)->configWidget( mConfigArea ) );
    mPluginIDs[newid] = (*it);
  }
  // Insert all plugins in sorted order; plugins with clashing IDs will be first
  QMap<int, KOrg::PrintPlugin*>::ConstIterator mapit;
  int firstButton = true;
  int id = 0;
  for ( mapit = mPluginIDs.begin(); mapit != mPluginIDs.end(); ++mapit ) {
    KOrg::PrintPlugin *p = mapit.value();
    QRadioButton *radioButton = new QRadioButton( p->description() );
    radioButton->setEnabled( p->enabled() );
    if ( firstButton && p->enabled() ) {
      firstButton = false;
      radioButton->setChecked( true );
      setPrintType( id );
    }
    mTypeGroup->addButton( radioButton, mapit.key() );
    typeLayout->addWidget( radioButton );
    id++;
  }
  typeLayout->insertStretch( -1, 100 );
  connect( this, SIGNAL(okClicked()), SLOT(slotOk()) );
  setMinimumSize( minimumSizeHint() );
  resize( minimumSizeHint() );
}

CalPrintDialog::~CalPrintDialog()
{
}

void CalPrintDialog::setPreview( bool preview )
{
  if ( preview ) {
    setButtonText( Ok, i18n( "&Preview" ) );
  } else {
    setButtonText( Ok, KStandardGuiItem::print().text() );
  }
}

void CalPrintDialog::setPrintType( int i )
{
  mConfigArea->setCurrentIndex( i );
  mConfigArea->currentWidget()->raise();
}

void CalPrintDialog::setOrientation( CalPrinter::ePrintOrientation orientation )
{
  mOrientation = orientation;
  mOrientationSelection->setCurrentIndex( mOrientation );
}

KOrg::PrintPlugin *CalPrintDialog::selectedPlugin()
{
  int id = mConfigArea->currentIndex();
  if ( mPluginIDs.contains( id ) ) {
    return mPluginIDs[id];
  } else {
    return 0;
  }
}

void CalPrintDialog::slotOk()
{
  mOrientation =
    ( CalPrinter::ePrintOrientation )mOrientationSelection->currentIndex();

  QMap<int, KOrg::PrintPlugin*>::Iterator it = mPluginIDs.begin();
  for ( ; it != mPluginIDs.end(); ++it ) {
    if ( it.value() ) {
      it.value()->readSettingsWidget();
    }
  }
}

#endif
<commit_msg>deprecated-- also, don't allow the splitter to collapse children because then the print type button group disappears, and that isn't good.<commit_after>/*
  This file is part of KOrganizer.

  Copyright (c) 1998 Preston Brown <pbrown@kde.org>
  Copyright (C) 2003-2004 Reinhold Kainhofer <reinhold@kainhofer.com>

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

  This program 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 General Public License for more details.

  You should have received a copy of the GNU General Public License along
  with this program; if not, write to the Free Software Foundation, Inc.,
  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.

  As a special exception, permission is given to link this program
  with any edition of Qt, and distribute the resulting executable,
  without including the source code for Qt in the source distribution.
*/

#include "calprinter.h"
#include "calprintdefaultplugins.h"

#include "korganizer/corehelper.h"

#include <kvbox.h>
#include <kconfig.h>
#include <kdebug.h>
#include <kdeversion.h>
#include <kstandardguiitem.h>
#include <kcombobox.h>
#include <kprintpreview.h>

#include <QButtonGroup>
#include <QLabel>
#include <QLayout>
#include <QGridLayout>
#include <QGroupBox>
#include <QPushButton>
#include <QRadioButton>
#include <QSplitter>
#include <QStackedWidget>
#include <QPrintDialog>
#include <QPrinter>

#ifndef KORG_NOPRINTER
#include "calprinter.moc"

CalPrinter::CalPrinter( QWidget *parent, Calendar *calendar, KOrg::CoreHelper *helper )
  : QObject( parent )
{
  mParent = parent;
  mConfig = new KConfig( "korganizer_printing.rc", KConfig::OnlyLocal );
  mCoreHelper = helper;

  init( calendar );
}

CalPrinter::~CalPrinter()
{
  mPrintPlugins.clear();
  delete mConfig;
}

void CalPrinter::init( Calendar *calendar )
{
  mCalendar = calendar;

  mPrintPlugins.clear();

  mPrintPlugins = mCoreHelper->loadPrintPlugins();
  mPrintPlugins.prepend( new CalPrintTodos() );
  mPrintPlugins.prepend( new CalPrintMonth() );
  mPrintPlugins.prepend( new CalPrintWeek() );
  mPrintPlugins.prepend( new CalPrintDay() );
  mPrintPlugins.prepend( new CalPrintIncidence() );

  KOrg::PrintPlugin::List::Iterator it = mPrintPlugins.begin();
  for ( ; it != mPrintPlugins.end(); ++it ) {
    if ( *it ) {
      (*it)->setConfig( mConfig );
      (*it)->setCalendar( mCalendar );
      (*it)->setKOrgCoreHelper( mCoreHelper );
      (*it)->doLoadConfig();
    }
  }
}

void CalPrinter::setDateRange( const QDate &fd, const QDate &td )
{
  KOrg::PrintPlugin::List::Iterator it = mPrintPlugins.begin();
  for ( ; it != mPrintPlugins.end(); ++it ) {
    (*it)->setDateRange( fd, td );
  }
}

void CalPrinter::print( int type, const QDate &fd, const QDate &td,
                        Incidence::List selectedIncidences, bool preview )
{
  KOrg::PrintPlugin::List::Iterator it = mPrintPlugins.begin();
  for ( it = mPrintPlugins.begin(); it != mPrintPlugins.end(); ++it ) {
    (*it)->setSelectedIncidences( selectedIncidences );
  }
  CalPrintDialog printDialog( mPrintPlugins, mParent );
  KConfigGroup grp( mConfig, "" ); //orientation setting isn't in a group
  printDialog.setOrientation( CalPrinter::ePrintOrientation( grp.readEntry( "Orientation", 1 ) ) );
  printDialog.setPreview( preview );
  printDialog.setPrintType( type );
  setDateRange( fd, td );

  if ( printDialog.exec() == QDialog::Accepted ) {
    grp.writeEntry( "Orientation", (int)printDialog.orientation() );

    // Save all changes in the dialog
    for ( it = mPrintPlugins.begin(); it != mPrintPlugins.end(); ++it ) {
      (*it)->doSaveConfig();
    }
    doPrint( printDialog.selectedPlugin(), printDialog.orientation(), preview );
  }
  for ( it = mPrintPlugins.begin(); it != mPrintPlugins.end(); ++it ) {
    (*it)->setSelectedIncidences( Incidence::List() );
  }
}

void CalPrinter::doPrint( KOrg::PrintPlugin *selectedStyle,
                          CalPrinter::ePrintOrientation dlgorientation, bool preview )
{
  if ( !selectedStyle ) {
    KMessageBox::error( mParent,
                        i18n( "Unable to print, no valid print style was returned." ),
                        i18n( "Printing error" ) );
    return;
  }

  QPrinter printer;
  switch ( dlgorientation ) {
  case eOrientPlugin:
    printer.setOrientation( selectedStyle->defaultOrientation() );
    break;
  case eOrientPortrait:
    printer.setOrientation( QPrinter::Portrait );
    break;
  case eOrientLandscape:
    printer.setOrientation( QPrinter::Landscape );
    break;
  case eOrientPrinter:
  default:
    break;
  }

  if ( preview ) {
    KPrintPreview printPreview( &printer );
    selectedStyle->doPrint( &printer );
    printPreview.exec();
  } else {
    QPrintDialog printDialog( &printer, mParent );
    if ( printDialog.exec() == QDialog::Accepted ) {
      selectedStyle->doPrint( &printer );
    }
  }
}

void CalPrinter::updateConfig()
{
}

CalPrintDialog::CalPrintDialog( KOrg::PrintPlugin::List plugins, QWidget *parent )
  : KDialog( parent )
{
  setCaption( i18n( "Print" ) );
  setButtons( Ok | Cancel );
  setModal( true );
  KVBox *page = new KVBox( this );
  setMainWidget( page );

  QSplitter *splitter = new QSplitter( page );
  splitter->setOrientation( Qt::Horizontal );
  splitter->setChildrenCollapsible( false );
  QGroupBox *typeBox = new QGroupBox( i18n( "Print Style" ), splitter );
  QBoxLayout *typeLayout = new QVBoxLayout( typeBox );
  mTypeGroup = new QButtonGroup( typeBox );

  QWidget *splitterRight = new QWidget( splitter );
  QGridLayout *splitterRightLayout = new QGridLayout( splitterRight );
  splitterRightLayout->setMargin( marginHint() );
  splitterRightLayout->setSpacing( spacingHint() );

  mConfigArea = new QStackedWidget( splitterRight );
  splitterRightLayout->addWidget( mConfigArea, 0, 0, 1, 2 );
  QLabel *orientationLabel = new QLabel( i18n( "Page &orientation:" ), splitterRight );
  splitterRightLayout->addWidget( orientationLabel, 1, 0 );

  mOrientationSelection = new KComboBox( splitterRight );
  mOrientationSelection->addItem( i18n( "Use Default Orientation of Selected Style" ) );
  mOrientationSelection->addItem( i18n( "Use Printer Default" ) );
  mOrientationSelection->addItem( i18n( "Portrait" ) );
  mOrientationSelection->addItem( i18n( "Landscape" ) );
  splitterRightLayout->addWidget( mOrientationSelection, 1, 1 );

  // signals and slots connections
  connect( mTypeGroup, SIGNAL( buttonClicked( int ) ), SLOT( setPrintType( int ) ) );
  orientationLabel->setBuddy( mOrientationSelection );

  // First insert the config widgets into the widget stack. This possibly assigns
  // proper ids (when two plugins have the same sortID), so store them in a map
  // and use these new IDs to later sort the plugins for the type selection.
  for ( KOrg::PrintPlugin::List::Iterator it = plugins.begin(); it != plugins.end(); ++it ) {
    int newid = mConfigArea->insertWidget( (*it)->sortID(), (*it)->configWidget( mConfigArea ) );
    mPluginIDs[newid] = (*it);
  }
  // Insert all plugins in sorted order; plugins with clashing IDs will be first
  QMap<int, KOrg::PrintPlugin*>::ConstIterator mapit;
  int firstButton = true;
  int id = 0;
  for ( mapit = mPluginIDs.begin(); mapit != mPluginIDs.end(); ++mapit ) {
    KOrg::PrintPlugin *p = mapit.value();
    QRadioButton *radioButton = new QRadioButton( p->description() );
    radioButton->setEnabled( p->enabled() );
    if ( firstButton && p->enabled() ) {
      firstButton = false;
      radioButton->setChecked( true );
      setPrintType( id );
    }
    mTypeGroup->addButton( radioButton, mapit.key() );
    typeLayout->addWidget( radioButton );
    id++;
  }
  typeLayout->insertStretch( -1, 100 );
  connect( this, SIGNAL(okClicked()), SLOT(slotOk()) );
  setMinimumSize( minimumSizeHint() );
  resize( minimumSizeHint() );
}

CalPrintDialog::~CalPrintDialog()
{
}

void CalPrintDialog::setPreview( bool preview )
{
  if ( preview ) {
    setButtonText( Ok, i18n( "&Preview" ) );
  } else {
    setButtonText( Ok, KStandardGuiItem::print().text() );
  }
}

void CalPrintDialog::setPrintType( int i )
{
  mConfigArea->setCurrentIndex( i );
  mConfigArea->currentWidget()->raise();
}

void CalPrintDialog::setOrientation( CalPrinter::ePrintOrientation orientation )
{
  mOrientation = orientation;
  mOrientationSelection->setCurrentIndex( mOrientation );
}

KOrg::PrintPlugin *CalPrintDialog::selectedPlugin()
{
  int id = mConfigArea->currentIndex();
  if ( mPluginIDs.contains( id ) ) {
    return mPluginIDs[id];
  } else {
    return 0;
  }
}

void CalPrintDialog::slotOk()
{
  mOrientation =
    ( CalPrinter::ePrintOrientation )mOrientationSelection->currentIndex();

  QMap<int, KOrg::PrintPlugin*>::Iterator it = mPluginIDs.begin();
  for ( ; it != mPluginIDs.end(); ++it ) {
    if ( it.value() ) {
      it.value()->readSettingsWidget();
    }
  }
}

#endif
<|endoftext|>


<commit_before>// Copyright 2010-2013 Google
// 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 <algorithm>
#include <string>
#include <vector>

#include "base/integral_types.h"
#include "base/concise_iterator.h"
#include "base/int-type-indexed-vector.h"
#include "base/int-type.h"
#include "base/logging.h"
#include "base/hash.h"
#include "base/scoped_ptr.h"
#include "base/stringprintf.h"
#include "constraint_solver/constraint_solver.h"
#include "constraint_solver/constraint_solveri.h"
#include "util/string_array.h"

namespace operations_research {
// Diffn constraint, Non overlapping rectangles.
namespace {
DEFINE_INT_TYPE(Box, int);
class Diffn : public Constraint {
 public:
  Diffn(Solver* const solver,
        const std::vector<IntVar*>& x_vars,
        const std::vector<IntVar*>& y_vars,
        const std::vector<IntVar*>& x_size,
        const std::vector<IntVar*>& y_size)
      : Constraint(solver),
        x_(x_vars),
        y_(y_vars),
        dx_(x_size),
        dy_(y_size),
        size_(x_vars.size()) {
    CHECK_EQ(x_vars.size(), y_vars.size());
    CHECK_EQ(x_vars.size(), x_size.size());
    CHECK_EQ(x_vars.size(), y_size.size());
  }

  virtual ~Diffn() {}

  virtual void Post() {
    Solver* const s = solver();
    for (int i = 0; i < size_; ++i) {
      Demon* const demon =
          MakeConstraintDemon1(solver(),
                               this,
                               &Diffn::RangeBox,
                               "RangeBox",
                               i);
      x_[i]->WhenRange(demon);
      y_[i]->WhenRange(demon);
      dx_[i]->WhenRange(demon);
      dy_[i]->WhenRange(demon);
    }
    delayed_demon_ = MakeDelayedConstraintDemon0(
        solver(),
        this,
        &Diffn::PropagateAll,
        "PropagateAll");
    if (AreAllBound(dx_) && AreAllBound(dy_) &&
        IsArrayInRange(x_, 0LL, kint64max) &&
        IsArrayInRange(y_, 0LL, kint64max)) {
      // We can add redundant cumulative constraints.

      // Cumulative on x variables.e
      const int64 min_x = MinVarArray(x_);
      const int64 max_x = MaxVarArray(x_);
      const int64 max_size_x = MaxVarArray(dx_);
      const int64 min_y = MinVarArray(y_);
      const int64 max_y = MaxVarArray(y_);
      const int64 max_size_y = MaxVarArray(dy_);
      vector<int64> size_x;
      FillValues(dx_, &size_x);
      vector<int64> size_y;
      FillValues(dy_, &size_y);

      AddCumulativeConstraint(x_, size_x, size_y, max_size_y + max_y - min_y);
      AddCumulativeConstraint(y_, size_y, size_x, max_size_x + max_x - min_x);
    }
  }

  virtual void InitialPropagate() {
    // All sizes should be > 0.
    for (int i = 0; i < size_; ++i) {
      dx_[i]->SetMin(1);
      dy_[i]->SetMin(1);
    }

    // Force propagation on all boxes.
    to_propagate_.clear();
    for (int i = 0; i < size_; i++) {
      to_propagate_.insert(i);
    }
    PropagateAll();
  }

  void RangeBox(int box) {
    to_propagate_.insert(box);
    EnqueueDelayedDemon(delayed_demon_);
  }

  void PropagateAll() {
    for (ConstIter<hash_set<int>> it(to_propagate_); !it.at_end(); ++it) {
      const int box = *it;
      FillNeighbors(box);
      CheckEnergy(box);
      PushOverlappingBoxes(box);
    }
    to_propagate_.clear();
  }

  virtual string DebugString() const {
    return StringPrintf("Diffn(x = [%s], y = [%s], dx = [%s], dy = [%s]))",
                        DebugStringVector(x_, ", ").c_str(),
                        DebugStringVector(y_, ", ").c_str(),
                        DebugStringVector(dx_, ", ").c_str(),
                        DebugStringVector(dy_, ", ").c_str());
  }

  virtual void Accept(ModelVisitor* const visitor) const {
    visitor->BeginVisitConstraint(ModelVisitor::kDisjunctive, this);
    visitor->VisitIntegerVariableArrayArgument(
        ModelVisitor::kPositionXArgument, x_);
    visitor->VisitIntegerVariableArrayArgument(
        ModelVisitor::kPositionYArgument, y_);
    visitor->VisitIntegerVariableArrayArgument(
        ModelVisitor::kSizeXArgument, dx_);
    visitor->VisitIntegerVariableArrayArgument(
        ModelVisitor::kSizeYArgument, dy_);
    visitor->EndVisitConstraint(ModelVisitor::kDisjunctive, this);
  }

 private:
  bool Overlap(int i, int j) {
    if (DisjointHorizontal(i, j) || DisjointVertical(i, j)) {
      return false;
    }
    return true;
  }

  bool DisjointHorizontal(int i, int j) {
    return (x_[i]->Min() >= x_[j]->Max() + dx_[j]->Max())
        || (x_[j]->Min() >= x_[i]->Max() + dx_[i]->Max());
  }

  bool DisjointVertical(int i, int j) {
    return (y_[i]->Min() >= y_[j]->Max() + dy_[j]->Max())
        || (y_[j]->Min() >= y_[i]->Max() + dy_[i]->Max());
  }

  // Fill neighbors_ with all boxes overlapping box.
  void FillNeighbors(int box) {
    neighbors_.clear();
    for (int other = 0; other < size_; ++other) {
      if (other != box && Overlap(other, box)) {
        neighbors_.push_back(other);
      }
    }
  }

  // Check that the minimum area of a set of boxes is always contained in
  // the bounding box of these boxes.
  void CheckEnergy(int box) {
    int64 area_min_x = x_[box]->Min();
    int64 area_max_x = x_[box]->Max() + dx_[box]->Max();
    int64 area_min_y = y_[box]->Min();
    int64 area_max_y = y_[box]->Max() + dy_[box]->Max();
    int64 sum_of_areas = dx_[box]->Min() * dy_[box]->Min();
    for (int i = 0; i < neighbors_.size(); ++i) {
      const int other = neighbors_[i];
      // Update Bounding box.
      area_min_x = std::min(area_min_x, x_[other]->Min());
      area_max_x = std::max(area_max_x, x_[other]->Max() + dx_[other]->Max());
      area_min_y = std::min(area_min_y, y_[other]->Min());
      area_max_y = std::max(area_max_y, y_[other]->Max() + dy_[other]->Max());
      // Update sum of areas.
      sum_of_areas += dx_[other]->Min() * dy_[other]->Min();
      const int64 bounding_area =
          (area_max_x - area_min_x) * (area_max_y - area_min_y);
      if (sum_of_areas > bounding_area) {
        solver()->Fail();
      }
    }
  }

  // Push all boxes apart the mandatory part of a box.
  void PushOverlappingBoxes(int box) {
    // Mandatory part of box.
    const int64 start_max_box_x = x_[box]->Max();
    const int64 end_min_box_x = x_[box]->Min() + dx_[box]->Min();
    const int64 start_max_box_y = y_[box]->Max();
    const int64 end_min_box_y = y_[box]->Min() + dy_[box]->Min();
    // Mandatory part non empty?
    if (start_max_box_x < end_min_box_x && start_max_box_y < end_min_box_y) {
      // Try to push overlapping boxes.
      for (int i = 0; i < neighbors_.size(); ++i) {
        PushOneBox(box, neighbors_[i], start_max_box_x,
                   end_min_box_x, start_max_box_y,
                   end_min_box_y);
      }
    }
  }

  void PushOneDirection(int box, int other, int64 start_max_box,
                        int64 end_min_box, int64 start_max_other,
                        int64 end_min_other,
                        const std::vector<IntVar*>& positions,
                        const std::vector<IntVar*>& sizes) {
    if (end_min_other > start_max_box) {
      // Other is forced after box.
      positions[other]->SetMin(end_min_box);
      positions[box]->SetMax(start_max_other - sizes[box]->Min());
      sizes[box]->SetMax(start_max_other - positions[box]->Min());
    } else if (end_min_box > start_max_other) {
      // Box is forced after other.
      positions[box]->SetMin(end_min_other);
      positions[other]->SetMax(start_max_box - sizes[other]->Min());
      sizes[other]->SetMax(start_max_box - positions[other]->Min());
    }
  }

  void PushOneBox(int box, int other, int64 start_max_box_x,
                  int64 end_min_box_x, int64 start_max_box_y,
                  int64 end_min_box_y) {
    // Mandatory part of the other box.
    const int64 start_max_other_x = x_[other]->Max();
    const int64 end_min_other_x = x_[other]->Min() + dx_[other]->Min();
    const int64 start_max_other_y = y_[other]->Max();
    const int64 end_min_other_y = y_[other]->Min() + dy_[other]->Min();
    // Mandatory part of the other box is non empty.
    if (start_max_other_x < end_min_other_x &&
        start_max_other_y < end_min_other_y) {
      const bool overlap_horizontal =
          start_max_other_x < end_min_box_x &&
          start_max_box_x < end_min_other_x;
      const bool overlap_vertical =
          start_max_other_y < end_min_box_y &&
          start_max_box_y < end_min_other_y;
      if (overlap_horizontal && overlap_vertical) {
        // Mandatory parts overlap. We fail early.
        solver()->Fail();
      } else if (overlap_horizontal) {
        PushOneDirection(box, other, start_max_box_y, end_min_box_y,
                         start_max_other_y, end_min_other_y,
                         y_, dy_);
      } else if (overlap_vertical) {
        PushOneDirection(box, other, start_max_box_x, end_min_box_x,
                         start_max_other_x, end_min_other_x,
                         x_, dx_);
      }
    }
  }

  void AddCumulativeConstraint(const std::vector<IntVar*>& positions,
                               const std::vector<int64>& sizes,
                               const std::vector<int64>& demands,
                               int64 capacity) {
    vector<IntervalVar*> intervals;
    solver()->MakeFixedDurationIntervalVarArray(
        positions, sizes, "interval", &intervals);
    solver()->AddConstraint(solver()->MakeCumulative(
        intervals, demands, capacity, "cumul"));
  }

  std::vector<IntVar*> x_;
  std::vector<IntVar*> y_;
  std::vector<IntVar*> dx_;
  std::vector<IntVar*> dy_;
  const int64 size_;
  Demon* delayed_demon_;
  hash_set<int> to_propagate_;
  std::vector<int> neighbors_;
};
}  // namespace

Constraint* Solver::MakeNonOverlappingRectanglesConstraint(
    const std::vector<IntVar*>& x_vars,
    const std::vector<IntVar*>& y_vars,
    const std::vector<IntVar*>& x_size,
    const std::vector<IntVar*>& y_size) {
  return RevAlloc(new Diffn(this, x_vars, y_vars, x_size, y_size));
}
}  // namespace operations_research
<commit_msg>simpler implementation of diffn, actually propagates more<commit_after>// Copyright 2010-2013 Google
// 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 <algorithm>
#include <string>
#include <vector>

#include "base/integral_types.h"
#include "base/concise_iterator.h"
#include "base/int-type-indexed-vector.h"
#include "base/int-type.h"
#include "base/logging.h"
#include "base/hash.h"
#include "base/scoped_ptr.h"
#include "base/stringprintf.h"
#include "constraint_solver/constraint_solver.h"
#include "constraint_solver/constraint_solveri.h"
#include "util/string_array.h"

namespace operations_research {
// Diffn constraint, Non overlapping rectangles.
namespace {
DEFINE_INT_TYPE(Box, int);
class Diffn : public Constraint {
 public:
  Diffn(Solver* const solver,
        const std::vector<IntVar*>& x_vars,
        const std::vector<IntVar*>& y_vars,
        const std::vector<IntVar*>& x_size,
        const std::vector<IntVar*>& y_size)
      : Constraint(solver),
        x_(x_vars),
        y_(y_vars),
        dx_(x_size),
        dy_(y_size),
        size_(x_vars.size()) {
    CHECK_EQ(x_vars.size(), y_vars.size());
    CHECK_EQ(x_vars.size(), x_size.size());
    CHECK_EQ(x_vars.size(), y_size.size());
  }

  virtual ~Diffn() {}

  virtual void Post() {
    Solver* const s = solver();
    for (int i = 0; i < size_; ++i) {
      Demon* const demon =
          MakeConstraintDemon1(solver(),
                               this,
                               &Diffn::RangeBox,
                               "RangeBox",
                               i);
      x_[i]->WhenRange(demon);
      y_[i]->WhenRange(demon);
      dx_[i]->WhenRange(demon);
      dy_[i]->WhenRange(demon);
    }
    delayed_demon_ = MakeDelayedConstraintDemon0(
        solver(),
        this,
        &Diffn::PropagateAll,
        "PropagateAll");
    if (AreAllBound(dx_) && AreAllBound(dy_) &&
        IsArrayInRange(x_, 0LL, kint64max) &&
        IsArrayInRange(y_, 0LL, kint64max)) {
      // We can add redundant cumulative constraints.

      // Cumulative on x variables.e
      const int64 min_x = MinVarArray(x_);
      const int64 max_x = MaxVarArray(x_);
      const int64 max_size_x = MaxVarArray(dx_);
      const int64 min_y = MinVarArray(y_);
      const int64 max_y = MaxVarArray(y_);
      const int64 max_size_y = MaxVarArray(dy_);
      vector<int64> size_x;
      FillValues(dx_, &size_x);
      vector<int64> size_y;
      FillValues(dy_, &size_y);

      AddCumulativeConstraint(x_, size_x, size_y, max_size_y + max_y - min_y);
      AddCumulativeConstraint(y_, size_y, size_x, max_size_x + max_x - min_x);
    }
  }

  virtual void InitialPropagate() {
    // All sizes should be > 0.
    for (int i = 0; i < size_; ++i) {
      dx_[i]->SetMin(1);
      dy_[i]->SetMin(1);
    }

    // Force propagation on all boxes.
    to_propagate_.clear();
    for (int i = 0; i < size_; i++) {
      to_propagate_.insert(i);
    }
    PropagateAll();
  }

  void RangeBox(int box) {
    to_propagate_.insert(box);
    EnqueueDelayedDemon(delayed_demon_);
  }

  void PropagateAll() {
    for (ConstIter<hash_set<int>> it(to_propagate_); !it.at_end(); ++it) {
      const int box = *it;
      FillNeighbors(box);
      CheckEnergy(box);
      PushOverlappingBoxes(box);
    }
    to_propagate_.clear();
  }

  virtual string DebugString() const {
    return StringPrintf("Diffn(x = [%s], y = [%s], dx = [%s], dy = [%s]))",
                        DebugStringVector(x_, ", ").c_str(),
                        DebugStringVector(y_, ", ").c_str(),
                        DebugStringVector(dx_, ", ").c_str(),
                        DebugStringVector(dy_, ", ").c_str());
  }

  virtual void Accept(ModelVisitor* const visitor) const {
    visitor->BeginVisitConstraint(ModelVisitor::kDisjunctive, this);
    visitor->VisitIntegerVariableArrayArgument(
        ModelVisitor::kPositionXArgument, x_);
    visitor->VisitIntegerVariableArrayArgument(
        ModelVisitor::kPositionYArgument, y_);
    visitor->VisitIntegerVariableArrayArgument(
        ModelVisitor::kSizeXArgument, dx_);
    visitor->VisitIntegerVariableArrayArgument(
        ModelVisitor::kSizeYArgument, dy_);
    visitor->EndVisitConstraint(ModelVisitor::kDisjunctive, this);
  }

 private:
  bool Overlap(int i, int j) {
    if (DisjointHorizontal(i, j) || DisjointVertical(i, j)) {
      return false;
    }
    return true;
  }

  bool DisjointHorizontal(int i, int j) {
    return (x_[i]->Min() >= x_[j]->Max() + dx_[j]->Max())
        || (x_[j]->Min() >= x_[i]->Max() + dx_[i]->Max());
  }

  bool DisjointVertical(int i, int j) {
    return (y_[i]->Min() >= y_[j]->Max() + dy_[j]->Max())
        || (y_[j]->Min() >= y_[i]->Max() + dy_[i]->Max());
  }

  // Fill neighbors_ with all boxes overlapping box.
  void FillNeighbors(int box) {
    neighbors_.clear();
    for (int other = 0; other < size_; ++other) {
      if (other != box && Overlap(other, box)) {
        neighbors_.push_back(other);
      }
    }
  }

  // Check that the minimum area of a set of boxes is always contained in
  // the bounding box of these boxes.
  void CheckEnergy(int box) {
    int64 area_min_x = x_[box]->Min();
    int64 area_max_x = x_[box]->Max() + dx_[box]->Max();
    int64 area_min_y = y_[box]->Min();
    int64 area_max_y = y_[box]->Max() + dy_[box]->Max();
    int64 sum_of_areas = dx_[box]->Min() * dy_[box]->Min();
    for (int i = 0; i < neighbors_.size(); ++i) {
      const int other = neighbors_[i];
      // Update Bounding box.
      area_min_x = std::min(area_min_x, x_[other]->Min());
      area_max_x = std::max(area_max_x, x_[other]->Max() + dx_[other]->Max());
      area_min_y = std::min(area_min_y, y_[other]->Min());
      area_max_y = std::max(area_max_y, y_[other]->Max() + dy_[other]->Max());
      // Update sum of areas.
      sum_of_areas += dx_[other]->Min() * dy_[other]->Min();
      const int64 bounding_area =
          (area_max_x - area_min_x) * (area_max_y - area_min_y);
      if (sum_of_areas > bounding_area) {
        solver()->Fail();
      }
    }
  }

  // Push all boxes apart the mandatory part of a box.
  void PushOverlappingBoxes(int box) {
    for (int i = 0; i < neighbors_.size(); ++i) {
      PushOneBox(box, neighbors_[i]);
    }
  }

  void PushOneBox(int box, int other) {
    const int count =
        (x_[box]->Min() + dx_[box]->Min() <= x_[other]->Max()) +
        (x_[other]->Min() + dx_[other]->Min() <= x_[box]->Max()) +
        (y_[box]->Min() + dy_[box]->Min() <= y_[other]->Max()) +
        (y_[other]->Min() + dy_[other]->Min() <= y_[box]->Max());
    if (count == 0) {
      solver()->Fail();
    }
    if (count == 1) {  // Only one direction to avoid overlap.
      if (x_[box]->Min() + dx_[box]->Min() <= x_[other]->Max()) {
        x_[other]->SetMin(x_[box]->Min() + dx_[box]->Min());
        x_[box]->SetMax(x_[other]->Max() - dx_[box]->Min());
        dx_[box]->SetMax(x_[other]->Max() - x_[box]->Min());
      } else if (x_[other]->Min() + dx_[other]->Min() <= x_[box]->Max()) {
        x_[box]->SetMin(x_[other]->Min() + dx_[other]->Min());
        x_[other]->SetMax(x_[box]->Max() - dx_[other]->Min());
        dx_[other]->SetMax(x_[box]->Max() - x_[other]->Min());
      } else if (y_[box]->Min() + dy_[box]->Min() <= y_[other]->Max()) {
        y_[other]->SetMin(y_[box]->Min() + dy_[box]->Min());
        y_[box]->SetMax(y_[other]->Max() - dy_[box]->Min());
        dy_[box]->SetMax(y_[other]->Max() - y_[box]->Min());
      } else {
        DCHECK(y_[other]->Min() + dy_[other]->Min() <= y_[box]->Max());
        y_[box]->SetMin(y_[other]->Min() + dy_[other]->Min());
        y_[other]->SetMax(y_[box]->Max() - dy_[other]->Min());
        dy_[other]->SetMax(y_[box]->Max() - y_[other]->Min());
      }
    }
  }

  void AddCumulativeConstraint(const std::vector<IntVar*>& positions,
                               const std::vector<int64>& sizes,
                               const std::vector<int64>& demands,
                               int64 capacity) {
    vector<IntervalVar*> intervals;
    solver()->MakeFixedDurationIntervalVarArray(
        positions, sizes, "interval", &intervals);
    solver()->AddConstraint(solver()->MakeCumulative(
        intervals, demands, capacity, "cumul"));
  }

  std::vector<IntVar*> x_;
  std::vector<IntVar*> y_;
  std::vector<IntVar*> dx_;
  std::vector<IntVar*> dy_;
  const int64 size_;
  Demon* delayed_demon_;
  hash_set<int> to_propagate_;
  std::vector<int> neighbors_;
};
}  // namespace

Constraint* Solver::MakeNonOverlappingRectanglesConstraint(
    const std::vector<IntVar*>& x_vars,
    const std::vector<IntVar*>& y_vars,
    const std::vector<IntVar*>& x_size,
    const std::vector<IntVar*>& y_size) {
  return RevAlloc(new Diffn(this, x_vars, y_vars, x_size, y_size));
}
}  // namespace operations_research
<|endoftext|>


<commit_before>/*
 * Banjax is an ATS plugin that:
 *                    enforce regex bans
 *                    store logs in a mysql db
 *                    run SVM on the log result
 *                    send a ban request to swabber in case of banning.
 *
 * Copyright (c) 2013 eQualit.ie under GNU AGPL v3.0 or later
 *
 * Vmon: June 2013 Initial version
 */

#include <ts/ts.h>
//NULL not defined in c++
#include <cstddef>
#include <string>
#include <vector>
#include <list>
#include <iostream>
#include <iomanip>
using namespace std;

#include <re2/re2.h>
#include <zmq.hpp>

#include "util.h"
#include "banjax_continuation.h"

#include "regex_manager.h"
#include "challenge_manager.h"
#include "white_lister.h"
#include "bot_sniffer.h"

#include "banjax.h"
#include "swabber_interface.h"
#include "ats_event_handler.h"

extern TSCont Banjax::global_contp;

extern const string Banjax::CONFIG_FILENAME = "banjax.conf";

extern Banjax* ATSEventHandler::banjax;
/**
   Read the config file and create filters whose name is
   mentioned in the config file. If you make a new filter
   you need to add it inside this function
*/
void
Banjax::filter_factory(const string& banjax_dir, YAML::Node main_root)
{

    BanjaxFilter* cur_filter;
    if (main_root["challenger"]["regex_banner"]) {
      cur_filter = new RegexManager(banjax_dir, main_root["challenger"]["regex_banner"], &ip_database, &swabber_interface);
    } else if (main_root["challenger"]["challenges"]){
      cur_filter = new ChallengeManager(banjax_dir, main_root["challenger"], &ip_database, &swabber_interface);
    } else if (main_root["white_listed_ips"]){
      cur_filter = new WhiteLister(banjax_dir, main_root["white_listed_ips"]);
    } else if (main_root["botbanger_port"]){
      cur_filter = new BotSniffer(banjax_dir, main_root);
    }

    for(unsigned int i = BanjaxFilter::HTTP_START; i < BanjaxFilter::TOTAL_NO_OF_QUEUES; i++) {
      if (cur_filter->queued_tasks[i]) {
        TSDebug(BANJAX_PLUGIN_NAME, "active task %s %u", cur_filter->BANJAX_FILTER_NAME.c_str(), i);
        task_queues[i].push_back(FilterTask(cur_filter,cur_filter->queued_tasks[i]));
      }
    }
    if(cur_filter){
      filters.push_back(cur_filter);
    }
}

Banjax::Banjax()
  :swabber_interface(&ip_database),
   all_filters_requested_part(0),
   all_filters_response_part(0)
{
  //Everything is static in ATSEventHandle so it is more like a namespace
  //than a class (we never instatiate from it). so the only reason
  //we have to create this object is to set the static reference to banjax into
  //ATSEventHandler, it is somehow the acknowledgementt that only one banjax
  //object can exist
  ATSEventHandler::banjax = this;

  /* create an TSTextLogObject to log blacklisted requests to */
  TSReturnCode error = TSTextLogObjectCreate(BANJAX_PLUGIN_NAME, TS_LOG_MODE_ADD_TIMESTAMP, &log);
  if (!log || error == TS_ERROR) {
    TSDebug(BANJAX_PLUGIN_NAME, "error while creating log");
  }

  TSDebug(BANJAX_PLUGIN_NAME, "in the beginning");

  global_contp = TSContCreate(ATSEventHandler::banjax_global_eventhandler, ip_database.db_mutex);

  BanjaxContinuation* cd = (BanjaxContinuation *) TSmalloc(sizeof(BanjaxContinuation));
  cd = new(cd) BanjaxContinuation(NULL); //no transaction attached to this cont
  TSContDataSet(global_contp, cd);

  cd->contp = global_contp;

  TSHttpHookAdd(TS_HTTP_TXN_START_HOOK, global_contp);

  //creation of filters happen here
  read_configuration();

  //now Get rid of inactives events
  for(unsigned int cur_queue = BanjaxFilter::HTTP_START; cur_queue < BanjaxFilter::TOTAL_NO_OF_QUEUES; cur_queue++, ATSEventHandler::banjax_active_queues[cur_queue] = task_queues[cur_queue].empty() ? false : true);

  //Ask each filter what part of http transaction they are interested in
  for(list<BanjaxFilter*>::iterator cur_filter = filters.begin(); cur_filter != filters.end(); cur_filter++) {
    all_filters_requested_part |= (*cur_filter)->requested_info();
    all_filters_response_part |= (*cur_filter)->response_info();
  }

}

void
Banjax::read_configuration()
{
  // Read the file. If there is an error, report it and exit.
  string sep = "/";
  string banjax_dir = TSPluginDirGet() + sep + BANJAX_PLUGIN_NAME;
  string absolute_config_file = /*TSInstallDirGet() + sep + */ banjax_dir + sep+ CONFIG_FILENAME;

  TSDebug(BANJAX_PLUGIN_NAME, "Reading configuration from [%s]", absolute_config_file.c_str());

  try
  {
    cfg = YAML::LoadFile(absolute_config_file);
  }
  catch(const libconfig::FileIOException &fioex)
  {
    TSDebug(BANJAX_PLUGIN_NAME, "I/O error while reading config file [%s].", absolute_config_file.c_str());
    return;
  }
  catch(const libconfig::ParseException &pex)
  {
    TSDebug(BANJAX_PLUGIN_NAME, "Parse error while reading the config file");
    return;
  }

  for(YAML::const_iterator it=cfg["include"].begin();it!=cfg["include"].end();++it ) {
    string inc_loc = banjax_dir + sep + (*it).as<std::string>();
    YAML::Node sub_cfg = YAML::LoadFile(inc_loc);
    cfg["challenger"]["challenges"].push_back(sub_cfg["challenges"]);
    cfg["challenger"]["regex_banner"].push_back(sub_cfg["regex_banner"]);
  }

  filter_factory(banjax_dir, cfg);

}

/* Global pointer that keep track of banjax global object */
Banjax* p_banjax_plugin;

void
TSPluginInit(int argc, const char *argv[])
{
  (void) argc; (void)argv;
  TSPluginRegistrationInfo info;

  info.plugin_name = (char*) BANJAX_PLUGIN_NAME;
  info.vendor_name = (char*) "eQualit.ie";
  info.support_email = (char*) "info@deflect.ca";

  if (TSPluginRegister(TS_SDK_VERSION_3_0, &info) != TS_SUCCESS) {
    TSError("Plugin registration failed. \n");
  }

  if (!check_ts_version()) {
    TSError("Plugin requires Traffic Server 3.0 or later\n");
    return;
  }
  /* create the banjax object that control the whole procedure */
  p_banjax_plugin = (Banjax*)TSmalloc(sizeof(Banjax));
  p_banjax_plugin = new(p_banjax_plugin) Banjax;

}
<commit_msg>added logging<commit_after>/*
 * Banjax is an ATS plugin that:
 *                    enforce regex bans
 *                    store logs in a mysql db
 *                    run SVM on the log result
 *                    send a ban request to swabber in case of banning.
 *
 * Copyright (c) 2013 eQualit.ie under GNU AGPL v3.0 or later
 *
 * Vmon: June 2013 Initial version
 */

#include <ts/ts.h>
//NULL not defined in c++
#include <cstddef>
#include <string>
#include <vector>
#include <list>
#include <iostream>
#include <iomanip>
using namespace std;

#include <re2/re2.h>
#include <zmq.hpp>

#include "util.h"
#include "banjax_continuation.h"

#include "regex_manager.h"
#include "challenge_manager.h"
#include "white_lister.h"
#include "bot_sniffer.h"

#include "banjax.h"
#include "swabber_interface.h"
#include "ats_event_handler.h"

extern TSCont Banjax::global_contp;

extern const string Banjax::CONFIG_FILENAME = "banjax.conf";

extern Banjax* ATSEventHandler::banjax;
/**
   Read the config file and create filters whose name is
   mentioned in the config file. If you make a new filter
   you need to add it inside this function
*/
void
Banjax::filter_factory(const string& banjax_dir, YAML::Node main_root)
{

    BanjaxFilter* cur_filter;
    if (main_root["challenger"]["regex_banner"]) {
      cur_filter = new RegexManager(banjax_dir, main_root["challenger"]["regex_banner"], &ip_database, &swabber_interface);
    } else if (main_root["challenger"]["challenges"]){
      cur_filter = new ChallengeManager(banjax_dir, main_root["challenger"], &ip_database, &swabber_interface);
    } else if (main_root["white_listed_ips"]){
      cur_filter = new WhiteLister(banjax_dir, main_root["white_listed_ips"]);
    } else if (main_root["botbanger_port"]){
      cur_filter = new BotSniffer(banjax_dir, main_root);
    }

    for(unsigned int i = BanjaxFilter::HTTP_START; i < BanjaxFilter::TOTAL_NO_OF_QUEUES; i++) {
      if (cur_filter->queued_tasks[i]) {
        TSDebug(BANJAX_PLUGIN_NAME, "active task %s %u", cur_filter->BANJAX_FILTER_NAME.c_str(), i);
        task_queues[i].push_back(FilterTask(cur_filter,cur_filter->queued_tasks[i]));
      }
    }
    if(cur_filter){
      filters.push_back(cur_filter);
    }
}

Banjax::Banjax()
  :swabber_interface(&ip_database),
   all_filters_requested_part(0),
   all_filters_response_part(0)
{
  //Everything is static in ATSEventHandle so it is more like a namespace
  //than a class (we never instatiate from it). so the only reason
  //we have to create this object is to set the static reference to banjax into
  //ATSEventHandler, it is somehow the acknowledgementt that only one banjax
  //object can exist
  ATSEventHandler::banjax = this;

  /* create an TSTextLogObject to log blacklisted requests to */
  TSReturnCode error = TSTextLogObjectCreate(BANJAX_PLUGIN_NAME, TS_LOG_MODE_ADD_TIMESTAMP, &log);
  if (!log || error == TS_ERROR) {
    TSDebug(BANJAX_PLUGIN_NAME, "error while creating log");
  }

  TSDebug(BANJAX_PLUGIN_NAME, "in the beginning");

  global_contp = TSContCreate(ATSEventHandler::banjax_global_eventhandler, ip_database.db_mutex);

  BanjaxContinuation* cd = (BanjaxContinuation *) TSmalloc(sizeof(BanjaxContinuation));
  cd = new(cd) BanjaxContinuation(NULL); //no transaction attached to this cont
  TSContDataSet(global_contp, cd);

  cd->contp = global_contp;

  TSHttpHookAdd(TS_HTTP_TXN_START_HOOK, global_contp);

  //creation of filters happen here
  read_configuration();

  //now Get rid of inactives events
  for(unsigned int cur_queue = BanjaxFilter::HTTP_START; cur_queue < BanjaxFilter::TOTAL_NO_OF_QUEUES; cur_queue++, ATSEventHandler::banjax_active_queues[cur_queue] = task_queues[cur_queue].empty() ? false : true);

  //Ask each filter what part of http transaction they are interested in
  for(list<BanjaxFilter*>::iterator cur_filter = filters.begin(); cur_filter != filters.end(); cur_filter++) {
    all_filters_requested_part |= (*cur_filter)->requested_info();
    all_filters_response_part |= (*cur_filter)->response_info();
  }

}

void
Banjax::read_configuration()
{
  // Read the file. If there is an error, report it and exit.
  string sep = "/";
  string banjax_dir = TSPluginDirGet() + sep + BANJAX_PLUGIN_NAME;
  string absolute_config_file = /*TSInstallDirGet() + sep + */ banjax_dir + sep+ CONFIG_FILENAME;
  TSDebug(BANJAX_PLUGIN_NAME, "Reading configuration from [%s]", absolute_config_file.c_str());

  try
  {
    cfg = YAML::LoadFile(absolute_config_file);
  }
  catch(YAML::ParserException& e)
  {
    TSDebug(BANJAX_PLUGIN_NAME, "I/O error while reading config file [%s]: [%s].", absolute_config_file.c_str(), e.what());
    return;
  }

  TSDebug(BANJAX_PLUGIN_NAME, "Finished loading main conf");

  for(YAML::const_iterator it=cfg["include"].begin();it!=cfg["include"].end();++it ) {
    string inc_loc = banjax_dir + sep + (*it).as<std::string>();
    TSDebug(BANJAX_PLUGIN_NAME, "Reading configuration from [%s]", inc_loc.c_str());
    YAML::Node sub_cfg = YAML::LoadFile(inc_loc);
    cfg["challenger"]["challenges"].push_back(sub_cfg["challenges"]);
    cfg["challenger"]["regex_banner"].push_back(sub_cfg["regex_banner"]);
    TSDebug(BANJAX_PLUGIN_NAME, "Finished reading from [%s]", inc_loc.c_str());
  }
  TSDebug(BANJAX_PLUGIN_NAME, "Finished loading include confs");

  filter_factory(banjax_dir, cfg);

}

/* Global pointer that keep track of banjax global object */
Banjax* p_banjax_plugin;

void
TSPluginInit(int argc, const char *argv[])
{
  (void) argc; (void)argv;
  TSPluginRegistrationInfo info;

  info.plugin_name = (char*) BANJAX_PLUGIN_NAME;
  info.vendor_name = (char*) "eQualit.ie";
  info.support_email = (char*) "info@deflect.ca";

  if (TSPluginRegister(TS_SDK_VERSION_3_0, &info) != TS_SUCCESS) {
    TSError("Plugin registration failed. \n");
  }

  if (!check_ts_version()) {
    TSError("Plugin requires Traffic Server 3.0 or later\n");
    return;
  }
  /* create the banjax object that control the whole procedure */
  p_banjax_plugin = (Banjax*)TSmalloc(sizeof(Banjax));
  p_banjax_plugin = new(p_banjax_plugin) Banjax;

}
<|endoftext|>