<commit_before>/*
 * Copyright (C) 2015 midnightBITS
 *
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without
 * restriction, including without limitation the rights to use, copy,
 * modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

#include "pch.h"
#include <net/utf8.hpp>
#include <iterator>

namespace utf
{
	using UTF8 = uint8_t;
	using UTF16 = wchar_t;
	using UTF32 = uint32_t;

	/*
	* Index into the table below with the first byte of a UTF-8 sequence to
	* get the number of trailing bytes that are supposed to follow it.
	* Note that *legal* UTF-8 values can't have 4 or 5-bytes. The table is
	* left as-is for anyone who may want to do such conversion, which was
	* allowed in earlier algorithms.
	*/
	static const char trailingBytesForUTF8[256] = {
		0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
		0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
		0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
		0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
		0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
		0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
		1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
		2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 3,3,3,3,3,3,3,3,4,4,4,4,5,5,5,5
	};

	/*
	* Magic values subtracted from a buffer value during UTF8 conversion.
	* This table contains as many values as there might be trailing bytes
	* in a UTF-8 sequence.
	*/
	static const UTF32 offsetsFromUTF8[6] = { 0x00000000UL, 0x00003080UL, 0x000E2080UL,
		0x03C82080UL, 0xFA082080UL, 0x82082080UL };

	/*
	* Once the bits are split out into bytes of UTF-8, this is a mask OR-ed
	* into the first byte, depending on how many bytes follow.  There are
	* as many entries in this table as there are UTF-8 sequence types.
	* (I.e., one byte sequence, two byte... etc.). Remember that sequencs
	* for *legal* UTF-8 will be 4 or fewer bytes total.
	*/
	static const UTF8 firstByteMark[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };

	enum {
		UNI_SUR_HIGH_START = 0xD800,
		UNI_SUR_HIGH_END = 0xDBFF,
		UNI_SUR_LOW_START = 0xDC00,
		UNI_SUR_LOW_END = 0xDFFF,
	};

	enum {
		UNI_MAX_BMP = 0x0000FFFF,
		UNI_MAX_UTF16 = 0x0010FFFF,
	};

	static const int halfShift = 10; /* used for shifting by 10 bits */

	static const UTF32 halfBase = 0x0010000UL;
	static const UTF32 halfMask = 0x3FFUL;

	template <typename T>
	static bool isLegalUTF8(T source, int length)
	{
		UTF8 a;
		auto srcptr = source + length;
		switch (length) {
		default: return false;
			/* Everything else falls through when "true"... */
		case 4: if ((a = (*--srcptr)) < 0x80 || a > 0xBF) return false;
		case 3: if ((a = (*--srcptr)) < 0x80 || a > 0xBF) return false;
		case 2: if ((a = (*--srcptr)) < 0x80 || a > 0xBF) return false;

			switch (*source) {
				/* no fall-through in this inner switch */
			case 0xE0: if (a < 0xA0) return false; break;
			case 0xED: if (a > 0x9F) return false; break;
			case 0xF0: if (a < 0x90) return false; break;
			case 0xF4: if (a > 0x8F) return false; break;
			default:   if (a < 0x80) return false;
			}

		case 1: if (*source >= 0x80 && *source < 0xC2) return false;
		}
		if (*source > 0xF4) return false;
		return true;
	}

	std::wstring widen(const std::string& src)
	{
		std::wstring out;
		auto source = src.begin();
		auto sourceEnd = src.end();
		auto target = std::back_inserter(out);

		while (source < sourceEnd) {
			UTF32 ch = 0;
			unsigned short extraBytesToRead = trailingBytesForUTF8[*source];
			if (extraBytesToRead >= sourceEnd - source) {
				break;
			}
			/* Do this check whether lenient or strict */
			if (!isLegalUTF8(source, extraBytesToRead + 1)) {
				break;
			}
			/*
			* The cases all fall through. See "Note A" below.
			*/
			switch (extraBytesToRead) {
			case 5: ch += *source++; ch <<= 6; /* remember, illegal UTF-8 */
			case 4: ch += *source++; ch <<= 6; /* remember, illegal UTF-8 */
			case 3: ch += *source++; ch <<= 6;
			case 2: ch += *source++; ch <<= 6;
			case 1: ch += *source++; ch <<= 6;
			case 0: ch += *source++;
			}
			ch -= offsetsFromUTF8[extraBytesToRead];

			if (ch <= UNI_MAX_BMP) { /* Target is a character <= 0xFFFF */
									 /* UTF-16 surrogate values are illegal in UTF-32 */
				if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) {
					*target++ = '?';
				}
				else {
					*target++ = (UTF16) ch; /* normal case */
				}
			}
			else if (ch > UNI_MAX_UTF16) {
				*target++ = '?';
			}
			else {
				ch -= halfBase;
				*target++ = (UTF16) ((ch >> halfShift) + UNI_SUR_HIGH_START);
				*target++ = (UTF16) ((ch & halfMask) + UNI_SUR_LOW_START);
			}
		}

		return out;
	}

	std::string narrowed(const std::wstring& src) {
		std::string out;
		auto source = src.begin();
		auto sourceEnd = src.end();
		auto target = std::back_inserter(out);

		while (source < sourceEnd) {
			UTF32 ch;
			unsigned short bytesToWrite = 0;
			const UTF32 byteMask = 0xBF;
			const UTF32 byteMark = 0x80;
			auto oldSource = source; /* In case we have to back up because of target overflow. */
			ch = *source++;
			/* If we have a surrogate pair, convert to UTF32 first. */
			if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_HIGH_END) {
				/* If the 16 bits following the high surrogate are in the source buffer... */
				if (source < sourceEnd) {
					UTF32 ch2 = *source;
					/* If it's a low surrogate, convert to UTF32. */
					if (ch2 >= UNI_SUR_LOW_START && ch2 <= UNI_SUR_LOW_END) {
						ch = ((ch - UNI_SUR_HIGH_START) << halfShift)
							+ (ch2 - UNI_SUR_LOW_START) + halfBase;
						++source;
					}
				}
				else { /* We don't have the 16 bits following the high surrogate. */
					--source; /* return to the high surrogate */
					break;
				}
			}

			/* Figure out how many bytes the result will require */
			if (ch < (UTF32) 0x80) {
				bytesToWrite = 1;
			}
			else if (ch < (UTF32) 0x800) {
				bytesToWrite = 2;
			}
			else if (ch < (UTF32) 0x10000) {
				bytesToWrite = 3;
			}
			else if (ch < (UTF32) 0x110000) {
				bytesToWrite = 4;
			}
			else {
				bytesToWrite = 3;
				ch = '?';
			}

			UTF8 mid[4];
			UTF8* midp = mid + sizeof(mid);
			switch (bytesToWrite) { /* note: everything falls through. */
			case 4: *--midp = (UTF8) ((ch | byteMark) & byteMask); ch >>= 6;
			case 3: *--midp = (UTF8) ((ch | byteMark) & byteMask); ch >>= 6;
			case 2: *--midp = (UTF8) ((ch | byteMark) & byteMask); ch >>= 6;
			case 1: *--midp = (UTF8) (ch | firstByteMark[bytesToWrite]);
			}
			for (int i = 0; i < bytesToWrite; ++i)
				*target++ = *midp++;
		}
		return out;
	}
}
<commit_msg>[libnet] Fixing signed char issue with utf::widen<commit_after>/*
 * Copyright (C) 2015 midnightBITS
 *
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without
 * restriction, including without limitation the rights to use, copy,
 * modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

#include "pch.h"
#include <net/utf8.hpp>
#include <iterator>

namespace utf
{
	using UTF8 = uint8_t;
	using UTF16 = wchar_t;
	using UTF32 = uint32_t;

	/*
	* Index into the table below with the first byte of a UTF-8 sequence to
	* get the number of trailing bytes that are supposed to follow it.
	* Note that *legal* UTF-8 values can't have 4 or 5-bytes. The table is
	* left as-is for anyone who may want to do such conversion, which was
	* allowed in earlier algorithms.
	*/
	static const char trailingBytesForUTF8[256] = {
		0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
		0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
		0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
		0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
		0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
		0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
		1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
		2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 3,3,3,3,3,3,3,3,4,4,4,4,5,5,5,5
	};

	/*
	* Magic values subtracted from a buffer value during UTF8 conversion.
	* This table contains as many values as there might be trailing bytes
	* in a UTF-8 sequence.
	*/
	static const UTF32 offsetsFromUTF8[6] = { 0x00000000UL, 0x00003080UL, 0x000E2080UL,
		0x03C82080UL, 0xFA082080UL, 0x82082080UL };

	/*
	* Once the bits are split out into bytes of UTF-8, this is a mask OR-ed
	* into the first byte, depending on how many bytes follow.  There are
	* as many entries in this table as there are UTF-8 sequence types.
	* (I.e., one byte sequence, two byte... etc.). Remember that sequencs
	* for *legal* UTF-8 will be 4 or fewer bytes total.
	*/
	static const UTF8 firstByteMark[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };

	enum {
		UNI_SUR_HIGH_START = 0xD800,
		UNI_SUR_HIGH_END = 0xDBFF,
		UNI_SUR_LOW_START = 0xDC00,
		UNI_SUR_LOW_END = 0xDFFF,
	};

	enum {
		UNI_MAX_BMP = 0x0000FFFF,
		UNI_MAX_UTF16 = 0x0010FFFF,
	};

	static const int halfShift = 10; /* used for shifting by 10 bits */

	static const UTF32 halfBase = 0x0010000UL;
	static const UTF32 halfMask = 0x3FFUL;

	template <typename T>
	static bool isLegalUTF8(T source, int length)
	{
		UTF8 a;
		auto srcptr = source + length;
		switch (length) {
		default: return false;
			/* Everything else falls through when "true"... */
		case 4: if ((a = ((uint8_t)*--srcptr)) < 0x80 || a > 0xBF) return false;
		case 3: if ((a = ((uint8_t)*--srcptr)) < 0x80 || a > 0xBF) return false;
		case 2: if ((a = ((uint8_t)*--srcptr)) < 0x80 || a > 0xBF) return false;

			switch (*source) {
				/* no fall-through in this inner switch */
			case 0xE0: if (a < 0xA0) return false; break;
			case 0xED: if (a > 0x9F) return false; break;
			case 0xF0: if (a < 0x90) return false; break;
			case 0xF4: if (a > 0x8F) return false; break;
			default:   if (a < 0x80) return false;
			}

		case 1: if ((uint8_t) *source >= 0x80 && (uint8_t) *source < 0xC2) return false;
		}
		if ((uint8_t) *source > 0xF4) return false;
		return true;
	}

	std::wstring widen(const std::string& src)
	{
		std::wstring out;
		auto source = src.begin();
		auto sourceEnd = src.end();
		auto target = std::back_inserter(out);

		while (source < sourceEnd) {
			UTF32 ch = 0;
			unsigned short extraBytesToRead = trailingBytesForUTF8[(uint8_t)*source];
			if (extraBytesToRead >= sourceEnd - source) {
				break;
			}
			/* Do this check whether lenient or strict */
			if (!isLegalUTF8(source, extraBytesToRead + 1)) {
				break;
			}
			/*
			* The cases all fall through. See "Note A" below.
			*/
			switch (extraBytesToRead) {
			case 5: ch += (uint8_t)*source++; ch <<= 6; /* remember, illegal UTF-8 */
			case 4: ch += (uint8_t)*source++; ch <<= 6; /* remember, illegal UTF-8 */
			case 3: ch += (uint8_t)*source++; ch <<= 6;
			case 2: ch += (uint8_t)*source++; ch <<= 6;
			case 1: ch += (uint8_t)*source++; ch <<= 6;
			case 0: ch += (uint8_t)*source++;
			}
			ch -= offsetsFromUTF8[extraBytesToRead];

			if (ch <= UNI_MAX_BMP) { /* Target is a character <= 0xFFFF */
									 /* UTF-16 surrogate values are illegal in UTF-32 */
				if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) {
					*target++ = '?';
				}
				else {
					*target++ = (UTF16) ch; /* normal case */
				}
			}
			else if (ch > UNI_MAX_UTF16) {
				*target++ = '?';
			}
			else {
				ch -= halfBase;
				*target++ = (UTF16) ((ch >> halfShift) + UNI_SUR_HIGH_START);
				*target++ = (UTF16) ((ch & halfMask) + UNI_SUR_LOW_START);
			}
		}

		return out;
	}

	std::string narrowed(const std::wstring& src) {
		std::string out;
		auto source = src.begin();
		auto sourceEnd = src.end();
		auto target = std::back_inserter(out);

		while (source < sourceEnd) {
			UTF32 ch;
			unsigned short bytesToWrite = 0;
			const UTF32 byteMask = 0xBF;
			const UTF32 byteMark = 0x80;
			auto oldSource = source; /* In case we have to back up because of target overflow. */
			ch = *source++;
			/* If we have a surrogate pair, convert to UTF32 first. */
			if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_HIGH_END) {
				/* If the 16 bits following the high surrogate are in the source buffer... */
				if (source < sourceEnd) {
					UTF32 ch2 = *source;
					/* If it's a low surrogate, convert to UTF32. */
					if (ch2 >= UNI_SUR_LOW_START && ch2 <= UNI_SUR_LOW_END) {
						ch = ((ch - UNI_SUR_HIGH_START) << halfShift)
							+ (ch2 - UNI_SUR_LOW_START) + halfBase;
						++source;
					}
				}
				else { /* We don't have the 16 bits following the high surrogate. */
					--source; /* return to the high surrogate */
					break;
				}
			}

			/* Figure out how many bytes the result will require */
			if (ch < (UTF32) 0x80) {
				bytesToWrite = 1;
			}
			else if (ch < (UTF32) 0x800) {
				bytesToWrite = 2;
			}
			else if (ch < (UTF32) 0x10000) {
				bytesToWrite = 3;
			}
			else if (ch < (UTF32) 0x110000) {
				bytesToWrite = 4;
			}
			else {
				bytesToWrite = 3;
				ch = '?';
			}

			UTF8 mid[4];
			UTF8* midp = mid + sizeof(mid);
			switch (bytesToWrite) { /* note: everything falls through. */
			case 4: *--midp = (UTF8) ((ch | byteMark) & byteMask); ch >>= 6;
			case 3: *--midp = (UTF8) ((ch | byteMark) & byteMask); ch >>= 6;
			case 2: *--midp = (UTF8) ((ch | byteMark) & byteMask); ch >>= 6;
			case 1: *--midp = (UTF8) (ch | firstByteMark[bytesToWrite]);
			}
			for (int i = 0; i < bytesToWrite; ++i)
				*target++ = *midp++;
		}
		return out;
	}
}
<|endoftext|>


<commit_before>
#ifdef ESP32

#define FASTLED_INTERNAL
#include "FastLED.h"

// -- Forward reference
class ESP32RMTController;

// -- Array of all controllers
//    This array is filled at the time controllers are registered
//    (Usually when the sketch calls addLeds)
static ESP32RMTController * gControllers[FASTLED_RMT_MAX_CONTROLLERS];

// -- Current set of active controllers, indexed by the RMT
//    channel assigned to them.
static ESP32RMTController * gOnChannel[FASTLED_RMT_MAX_CHANNELS];

static int gNumControllers = 0;
static int gNumStarted = 0;
static int gNumDone = 0;
static int gNext = 0;

static intr_handle_t gRMT_intr_handle = NULL;

// -- Global semaphore for the whole show process
//    Semaphore is not given until all data has been sent
static xSemaphoreHandle gTX_sem = NULL;

static bool gInitialized = false;

ESP32RMTController::ESP32RMTController(int DATA_PIN, int T1, int T2, int T3)
    : mPixelData(0),
      mSize(0),
      mCur(0),
      mWhichHalf(0),
      mBuffer(0),
      mBufferSize(0),
      mCurPulse(0)
{
    // -- Precompute rmt items corresponding to a zero bit and a one bit
    //    according to the timing values given in the template instantiation
    // T1H
    mOne.level0 = 1;
    mOne.duration0 = ESP_TO_RMT_CYCLES(T1+T2); // TO_RMT_CYCLES(T1+T2);
    // T1L
    mOne.level1 = 0;
    mOne.duration1 = ESP_TO_RMT_CYCLES(T3); // TO_RMT_CYCLES(T3);

    // T0H
    mZero.level0 = 1;
    mZero.duration0 = ESP_TO_RMT_CYCLES(T1); // TO_RMT_CYCLES(T1);
    // T0L
    mZero.level1 = 0;
    mZero.duration1 = ESP_TO_RMT_CYCLES(T2+T3); // TO_RMT_CYCLES(T2 + T3);

    gControllers[gNumControllers] = this;
    gNumControllers++;

    mPin = gpio_num_t(DATA_PIN);
}

// -- Getters and setters for use in ClocklessController
uint8_t * ESP32RMTController::getPixelData(int size_in_bytes)
{
    if (mPixelData == 0) {
        mSize = size_in_bytes;
        mPixelData = (uint8_t *) calloc( mSize, sizeof(uint8_t));
    }
    return mPixelData;
}

// -- Initialize RMT subsystem
//    This only needs to be done once
void ESP32RMTController::init()
{
    if (gInitialized) return;

    for (int i = 0; i < FASTLED_RMT_MAX_CHANNELS; i++) {
        gOnChannel[i] = NULL;

        // -- RMT configuration for transmission
        rmt_config_t rmt_tx;
        rmt_tx.channel = rmt_channel_t(i);
        rmt_tx.rmt_mode = RMT_MODE_TX;
        rmt_tx.gpio_num = gpio_num_t(0);  // The particular pin will be assigned later
        rmt_tx.mem_block_num = 1;
        rmt_tx.clk_div = DIVIDER;
        rmt_tx.tx_config.loop_en = false;
        rmt_tx.tx_config.carrier_level = RMT_CARRIER_LEVEL_LOW;
        rmt_tx.tx_config.carrier_en = false;
        rmt_tx.tx_config.idle_level = RMT_IDLE_LEVEL_LOW;
        rmt_tx.tx_config.idle_output_en = true;

        // -- Apply the configuration
        rmt_config(&rmt_tx);

        if (FASTLED_RMT_BUILTIN_DRIVER) {
            rmt_driver_install(rmt_channel_t(i), 0, 0);
        } else {
            // -- Set up the RMT to send 1 pixel of the pulse buffer and then
            //    generate an interrupt. When we get this interrupt we
            //    fill the other part in preparation (kind of like double-buffering)
            rmt_set_tx_thr_intr_en(rmt_channel_t(i), true, PULSES_PER_FILL);
        }
    }

    // -- Create a semaphore to block execution until all the controllers are done
    if (gTX_sem == NULL) {
        gTX_sem = xSemaphoreCreateBinary();
        xSemaphoreGive(gTX_sem);
    }

    if ( ! FASTLED_RMT_BUILTIN_DRIVER) {
        // -- Allocate the interrupt if we have not done so yet. This
        //    interrupt handler must work for all different kinds of
        //    strips, so it delegates to the refill function for each
        //    specific instantiation of ClocklessController.
        if (gRMT_intr_handle == NULL)
            esp_intr_alloc(ETS_RMT_INTR_SOURCE, ESP_INTR_FLAG_LEVEL3, interruptHandler, 0, &gRMT_intr_handle);
    }

    gInitialized = true;
}

// -- Show this string of pixels
//    This is the main entry point for the pixel controller
void ESP32RMTController::showPixels()
{
    if (gNumStarted == 0) {
        // -- First controller: make sure everything is set up
        ESP32RMTController::init();
        xSemaphoreTake(gTX_sem, portMAX_DELAY);

#if FASTLED_ESP32_FLASH_LOCK == 1
        // -- Make sure no flash operations happen right now
        spi_flash_op_lock();
#endif
    }

    // -- Keep track of the number of strips we've seen
    gNumStarted++;

    // -- The last call to showPixels is the one responsible for doing
    //    all of the actual worl
    if (gNumStarted == gNumControllers) {
        gNext = 0;

        // -- First, fill all the available channels
        int channel = 0;
        while (channel < FASTLED_RMT_MAX_CHANNELS && gNext < gNumControllers) {
            ESP32RMTController::startNext(channel);
            channel++;
        }

        // -- Make sure it's been at least 50us since last show
        mWait.wait();

        // -- Start them all
        for (int i = 0; i < channel; i++) {
            ESP32RMTController * pController = gControllers[i];
            pController->tx_start();
        }

        // -- Wait here while the rest of the data is sent. The interrupt handler
        //    will keep refilling the RMT buffers until it is all sent; then it
        //    gives the semaphore back.
        xSemaphoreTake(gTX_sem, portMAX_DELAY);
        xSemaphoreGive(gTX_sem);

        mWait.mark();

        // -- Reset the counters
        gNumStarted = 0;
        gNumDone = 0;
        gNext = 0;

#if FASTLED_ESP32_FLASH_LOCK == 1
        // -- Release the lock on flash operations
        spi_flash_op_unlock();
#endif
    }
}

// -- Start up the next controller
//    This method is static so that it can dispatch to the
//    appropriate startOnChannel method of the given controller.
void ESP32RMTController::startNext(int channel)
{
    if (gNext < gNumControllers) {
        ESP32RMTController * pController = gControllers[gNext];
        pController->startOnChannel(channel);
        gNext++;
    }
}

// -- Start this controller on the given channel
//    This function just initiates the RMT write; it does not wait
//    for it to finish.
void ESP32RMTController::startOnChannel(int channel)
{
    // -- Assign this channel and configure the RMT
    mRMT_channel = rmt_channel_t(channel);

    // -- Store a reference to this controller, so we can get it
    //    inside the interrupt handler
    gOnChannel[channel] = this;

    // -- Assign the pin to this channel
    rmt_set_pin(mRMT_channel, RMT_MODE_TX, mPin);

    if (FASTLED_RMT_BUILTIN_DRIVER) {
        // -- Use the built-in RMT driver to send all the data in one shot
        rmt_register_tx_end_callback(doneOnChannel, 0);
        rmt_write_items(mRMT_channel, mBuffer, mBufferSize, false);
    } else {
        // -- Use our custom driver to send the data incrementally

        // -- Initialize the counters that keep track of where we are in
        //    the pixel data.
        mRMT_mem_ptr = & (RMTMEM.chan[mRMT_channel].data32[0].val);
        mCur = 0;
        mWhichHalf = 0;

        // -- Store 2 pixels worth of data (two "buffers" full)
        fillNext();
        fillNext();

        // -- Turn on the interrupts
        rmt_set_tx_intr_en(mRMT_channel, true);
    }
}

// -- Start RMT transmission
//    Setting this RMT flag is what actually kicks off the peripheral
void ESP32RMTController::tx_start()
{
    rmt_tx_start(mRMT_channel, true);
}

// -- A controller is done
//    This function is called when a controller finishes writing
//    its data. It is called either by the custom interrupt
//    handler (below), or as a callback from the built-in
//    interrupt handler. It is static because we don't know which
//    controller is done until we look it up.
void ESP32RMTController::doneOnChannel(rmt_channel_t channel, void * arg)
{
    ESP32RMTController * pController = gOnChannel[channel];
    portBASE_TYPE HPTaskAwoken = 0;

    // -- Turn off output on the pin
    gpio_matrix_out(pController->mPin, 0x100, 0, 0);

    gOnChannel[channel] = NULL;
    gNumDone++;

    if (gNumDone == gNumControllers) {
        // -- If this is the last controller, signal that we are all done
        if (FASTLED_RMT_BUILTIN_DRIVER) {
            xSemaphoreGive(gTX_sem);
        } else {
            xSemaphoreGiveFromISR(gTX_sem, &HPTaskAwoken);
            if (HPTaskAwoken == pdTRUE) portYIELD_FROM_ISR();
        }
    } else {
        // -- Otherwise, if there are still controllers waiting, then
        //    start the next one on this channel
        if (gNext < gNumControllers) {
            startNext(channel);
            pController->tx_start();
        }
    }
}

// -- Custom interrupt handler
//    This interrupt handler handles two cases: a controller is
//    done writing its data, or a controller needs to fill the
//    next half of the RMT buffer with data.
void IRAM_ATTR ESP32RMTController::interruptHandler(void *arg)
{
    // -- The basic structure of this code is borrowed from the
    //    interrupt handler in esp-idf/components/driver/rmt.c
    uint32_t intr_st = RMT.int_st.val;
    uint8_t channel;

    for (channel = 0; channel < FASTLED_RMT_MAX_CHANNELS; channel++) {
        int tx_done_bit = channel * 3;
        int tx_next_bit = channel + 24;

        ESP32RMTController * pController = gOnChannel[channel];
        if (pController != NULL) {

            // -- More to send on this channel
            if (intr_st & BIT(tx_next_bit)) {
                RMT.int_clr.val |= BIT(tx_next_bit);

                // -- Refill the half of the buffer that we just finished,
                //    allowing the other half to proceed.
                pController->fillNext();
            } else {
                // -- Transmission is complete on this channel
                if (intr_st & BIT(tx_done_bit)) {
                    RMT.int_clr.val |= BIT(tx_done_bit);
                    doneOnChannel(rmt_channel_t(channel), 0);
                }
            }
        }
    }
}

// -- Fill RMT buffer
//    Puts 32 bits of pixel data into the next 32 slots in the RMT memory
//    Each data bit is represented by a 32-bit RMT item that specifies how
//    long to hold the signal high, followed by how long to hold it low.
void IRAM_ATTR ESP32RMTController::fillNext()
{
    if (mCur < mSize) {
        // -- Get the zero and one values into local variables
        uint32_t one_val = mOne.val;
        uint32_t zero_val = mZero.val;

        // -- Fill 32 slots in the RMT memory
        uint8_t a = mPixelData[mCur++];
        uint8_t b = mPixelData[mCur++];
        uint8_t c = mPixelData[mCur++];
        uint8_t d = mPixelData[mCur++];
        register uint32_t pixeldata = a << 24 | b << 16 | c << 8 | d;

        // -- Use locals for speed
        volatile register uint32_t * pItem =  mRMT_mem_ptr;

        // Shift bits out, MSB first, setting RMTMEM.chan[n].data32[x] to the
        // rmt_item32_t value corresponding to the buffered bit value
        for (register uint32_t j = 0; j < PULSES_PER_FILL; j++) {
            *pItem++ = (pixeldata & 0x80000000L) ? one_val : zero_val;
            // Replaces: RMTMEM.chan[mRMT_channel].data32[mCurPulse].val = val;

            pixeldata <<= 1;
        }

        // -- Flip to the other half, resetting the pointer if necessary
        mWhichHalf++;
        if (mWhichHalf == 2) {
            pItem = & (RMTMEM.chan[mRMT_channel].data32[0].val);
            mWhichHalf = 0;
        }

        // -- Store the new pointer back into the object
        mRMT_mem_ptr = pItem;
    } else {
        // -- No more data; signal to the RMT we are done
        for (uint32_t j = 0; j < PULSES_PER_FILL; j++) {
            * mRMT_mem_ptr++ = 0;
        }
    }
}

// -- Init pulse buffer
//    Set up the buffer that will hold all of the pulse items for this
//    controller.
//    This function is only used when the built-in RMT driver is chosen
void ESP32RMTController::initPulseBuffer(int size_in_bytes)
{
    if (mBuffer == 0) {
        // -- Each byte has 8 bits, each bit needs a 32-bit RMT item
        int size = size_in_bytes * 8 * 4;

        mBuffer = (rmt_item32_t *) calloc( mBufferSize, sizeof(rmt_item32_t));
    }
    mCurPulse = 0;
}

// -- Convert a byte into RMT pulses
//    This function is only used when the built-in RMT driver is chosen
void ESP32RMTController::convertByte(uint32_t byteval)
{
    // -- Write one byte's worth of RMT pulses to the big buffer
    byteval <<= 24;
    for (register uint32_t j = 0; j < 8; j++) {
        mBuffer[mCurPulse] = (byteval & 0x80000000L) ? mOne : mZero;
        byteval <<= 1;
        mCurPulse++;
    }
}

#endif
<commit_msg>One more crucial change: tell the ESP-IDF that our interrupt resides in IRAM and therefore does not need to be disabled during flash operations<commit_after>
#ifdef ESP32

#define FASTLED_INTERNAL
#include "FastLED.h"

// -- Forward reference
class ESP32RMTController;

// -- Array of all controllers
//    This array is filled at the time controllers are registered
//    (Usually when the sketch calls addLeds)
static ESP32RMTController * gControllers[FASTLED_RMT_MAX_CONTROLLERS];

// -- Current set of active controllers, indexed by the RMT
//    channel assigned to them.
static ESP32RMTController * gOnChannel[FASTLED_RMT_MAX_CHANNELS];

static int gNumControllers = 0;
static int gNumStarted = 0;
static int gNumDone = 0;
static int gNext = 0;

static intr_handle_t gRMT_intr_handle = NULL;

// -- Global semaphore for the whole show process
//    Semaphore is not given until all data has been sent
static xSemaphoreHandle gTX_sem = NULL;

static bool gInitialized = false;

ESP32RMTController::ESP32RMTController(int DATA_PIN, int T1, int T2, int T3)
    : mPixelData(0),
      mSize(0),
      mCur(0),
      mWhichHalf(0),
      mBuffer(0),
      mBufferSize(0),
      mCurPulse(0)
{
    // -- Precompute rmt items corresponding to a zero bit and a one bit
    //    according to the timing values given in the template instantiation
    // T1H
    mOne.level0 = 1;
    mOne.duration0 = ESP_TO_RMT_CYCLES(T1+T2); // TO_RMT_CYCLES(T1+T2);
    // T1L
    mOne.level1 = 0;
    mOne.duration1 = ESP_TO_RMT_CYCLES(T3); // TO_RMT_CYCLES(T3);

    // T0H
    mZero.level0 = 1;
    mZero.duration0 = ESP_TO_RMT_CYCLES(T1); // TO_RMT_CYCLES(T1);
    // T0L
    mZero.level1 = 0;
    mZero.duration1 = ESP_TO_RMT_CYCLES(T2+T3); // TO_RMT_CYCLES(T2 + T3);

    gControllers[gNumControllers] = this;
    gNumControllers++;

    mPin = gpio_num_t(DATA_PIN);
}

// -- Getters and setters for use in ClocklessController
uint8_t * ESP32RMTController::getPixelData(int size_in_bytes)
{
    if (mPixelData == 0) {
        mSize = size_in_bytes;
        mPixelData = (uint8_t *) calloc( mSize, sizeof(uint8_t));
    }
    return mPixelData;
}

// -- Initialize RMT subsystem
//    This only needs to be done once
void ESP32RMTController::init()
{
    if (gInitialized) return;

    for (int i = 0; i < FASTLED_RMT_MAX_CHANNELS; i++) {
        gOnChannel[i] = NULL;

        // -- RMT configuration for transmission
        rmt_config_t rmt_tx;
        rmt_tx.channel = rmt_channel_t(i);
        rmt_tx.rmt_mode = RMT_MODE_TX;
        rmt_tx.gpio_num = gpio_num_t(0);  // The particular pin will be assigned later
        rmt_tx.mem_block_num = 1;
        rmt_tx.clk_div = DIVIDER;
        rmt_tx.tx_config.loop_en = false;
        rmt_tx.tx_config.carrier_level = RMT_CARRIER_LEVEL_LOW;
        rmt_tx.tx_config.carrier_en = false;
        rmt_tx.tx_config.idle_level = RMT_IDLE_LEVEL_LOW;
        rmt_tx.tx_config.idle_output_en = true;

        // -- Apply the configuration
        rmt_config(&rmt_tx);

        if (FASTLED_RMT_BUILTIN_DRIVER) {
            rmt_driver_install(rmt_channel_t(i), 0, 0);
        } else {
            // -- Set up the RMT to send 1 pixel of the pulse buffer and then
            //    generate an interrupt. When we get this interrupt we
            //    fill the other part in preparation (kind of like double-buffering)
            rmt_set_tx_thr_intr_en(rmt_channel_t(i), true, PULSES_PER_FILL);
        }
    }

    // -- Create a semaphore to block execution until all the controllers are done
    if (gTX_sem == NULL) {
        gTX_sem = xSemaphoreCreateBinary();
        xSemaphoreGive(gTX_sem);
    }

    if ( ! FASTLED_RMT_BUILTIN_DRIVER) {
        // -- Allocate the interrupt if we have not done so yet. This
        //    interrupt handler must work for all different kinds of
        //    strips, so it delegates to the refill function for each
        //    specific instantiation of ClocklessController.
        if (gRMT_intr_handle == NULL)
            esp_intr_alloc(ETS_RMT_INTR_SOURCE, ESP_INTR_FLAG_IRAM | ESP_INTR_FLAG_LEVEL3, interruptHandler, 0, &gRMT_intr_handle);
    }

    gInitialized = true;
}

// -- Show this string of pixels
//    This is the main entry point for the pixel controller
void ESP32RMTController::showPixels()
{
    if (gNumStarted == 0) {
        // -- First controller: make sure everything is set up
        ESP32RMTController::init();
        xSemaphoreTake(gTX_sem, portMAX_DELAY);

#if FASTLED_ESP32_FLASH_LOCK == 1
        // -- Make sure no flash operations happen right now
        spi_flash_op_lock();
#endif
    }

    // -- Keep track of the number of strips we've seen
    gNumStarted++;

    // -- The last call to showPixels is the one responsible for doing
    //    all of the actual worl
    if (gNumStarted == gNumControllers) {
        gNext = 0;

        // -- First, fill all the available channels
        int channel = 0;
        while (channel < FASTLED_RMT_MAX_CHANNELS && gNext < gNumControllers) {
            ESP32RMTController::startNext(channel);
            channel++;
        }

        // -- Make sure it's been at least 50us since last show
        mWait.wait();

        // -- Start them all
        for (int i = 0; i < channel; i++) {
            ESP32RMTController * pController = gControllers[i];
            pController->tx_start();
        }

        // -- Wait here while the rest of the data is sent. The interrupt handler
        //    will keep refilling the RMT buffers until it is all sent; then it
        //    gives the semaphore back.
        xSemaphoreTake(gTX_sem, portMAX_DELAY);
        xSemaphoreGive(gTX_sem);

        mWait.mark();

        // -- Reset the counters
        gNumStarted = 0;
        gNumDone = 0;
        gNext = 0;

#if FASTLED_ESP32_FLASH_LOCK == 1
        // -- Release the lock on flash operations
        spi_flash_op_unlock();
#endif
    }
}

// -- Start up the next controller
//    This method is static so that it can dispatch to the
//    appropriate startOnChannel method of the given controller.
void ESP32RMTController::startNext(int channel)
{
    if (gNext < gNumControllers) {
        ESP32RMTController * pController = gControllers[gNext];
        pController->startOnChannel(channel);
        gNext++;
    }
}

// -- Start this controller on the given channel
//    This function just initiates the RMT write; it does not wait
//    for it to finish.
void ESP32RMTController::startOnChannel(int channel)
{
    // -- Assign this channel and configure the RMT
    mRMT_channel = rmt_channel_t(channel);

    // -- Store a reference to this controller, so we can get it
    //    inside the interrupt handler
    gOnChannel[channel] = this;

    // -- Assign the pin to this channel
    rmt_set_pin(mRMT_channel, RMT_MODE_TX, mPin);

    if (FASTLED_RMT_BUILTIN_DRIVER) {
        // -- Use the built-in RMT driver to send all the data in one shot
        rmt_register_tx_end_callback(doneOnChannel, 0);
        rmt_write_items(mRMT_channel, mBuffer, mBufferSize, false);
    } else {
        // -- Use our custom driver to send the data incrementally

        // -- Initialize the counters that keep track of where we are in
        //    the pixel data.
        mRMT_mem_ptr = & (RMTMEM.chan[mRMT_channel].data32[0].val);
        mCur = 0;
        mWhichHalf = 0;

        // -- Store 2 pixels worth of data (two "buffers" full)
        fillNext();
        fillNext();

        // -- Turn on the interrupts
        rmt_set_tx_intr_en(mRMT_channel, true);
    }
}

// -- Start RMT transmission
//    Setting this RMT flag is what actually kicks off the peripheral
void ESP32RMTController::tx_start()
{
    rmt_tx_start(mRMT_channel, true);
}

// -- A controller is done
//    This function is called when a controller finishes writing
//    its data. It is called either by the custom interrupt
//    handler (below), or as a callback from the built-in
//    interrupt handler. It is static because we don't know which
//    controller is done until we look it up.
void ESP32RMTController::doneOnChannel(rmt_channel_t channel, void * arg)
{
    ESP32RMTController * pController = gOnChannel[channel];
    portBASE_TYPE HPTaskAwoken = 0;

    // -- Turn off output on the pin
    gpio_matrix_out(pController->mPin, 0x100, 0, 0);

    gOnChannel[channel] = NULL;
    gNumDone++;

    if (gNumDone == gNumControllers) {
        // -- If this is the last controller, signal that we are all done
        if (FASTLED_RMT_BUILTIN_DRIVER) {
            xSemaphoreGive(gTX_sem);
        } else {
            xSemaphoreGiveFromISR(gTX_sem, &HPTaskAwoken);
            if (HPTaskAwoken == pdTRUE) portYIELD_FROM_ISR();
        }
    } else {
        // -- Otherwise, if there are still controllers waiting, then
        //    start the next one on this channel
        if (gNext < gNumControllers) {
            startNext(channel);
            pController->tx_start();
        }
    }
}

// -- Custom interrupt handler
//    This interrupt handler handles two cases: a controller is
//    done writing its data, or a controller needs to fill the
//    next half of the RMT buffer with data.
void IRAM_ATTR ESP32RMTController::interruptHandler(void *arg)
{
    // -- The basic structure of this code is borrowed from the
    //    interrupt handler in esp-idf/components/driver/rmt.c
    uint32_t intr_st = RMT.int_st.val;
    uint8_t channel;

    for (channel = 0; channel < FASTLED_RMT_MAX_CHANNELS; channel++) {
        int tx_done_bit = channel * 3;
        int tx_next_bit = channel + 24;

        ESP32RMTController * pController = gOnChannel[channel];
        if (pController != NULL) {

            // -- More to send on this channel
            if (intr_st & BIT(tx_next_bit)) {
                RMT.int_clr.val |= BIT(tx_next_bit);

                // -- Refill the half of the buffer that we just finished,
                //    allowing the other half to proceed.
                pController->fillNext();
            } else {
                // -- Transmission is complete on this channel
                if (intr_st & BIT(tx_done_bit)) {
                    RMT.int_clr.val |= BIT(tx_done_bit);
                    doneOnChannel(rmt_channel_t(channel), 0);
                }
            }
        }
    }
}

// -- Fill RMT buffer
//    Puts 32 bits of pixel data into the next 32 slots in the RMT memory
//    Each data bit is represented by a 32-bit RMT item that specifies how
//    long to hold the signal high, followed by how long to hold it low.
void IRAM_ATTR ESP32RMTController::fillNext()
{
    if (mCur < mSize) {
        // -- Get the zero and one values into local variables
        uint32_t one_val = mOne.val;
        uint32_t zero_val = mZero.val;

        // -- Fill 32 slots in the RMT memory
        uint8_t a = mPixelData[mCur++];
        uint8_t b = mPixelData[mCur++];
        uint8_t c = mPixelData[mCur++];
        uint8_t d = mPixelData[mCur++];
        register uint32_t pixeldata = a << 24 | b << 16 | c << 8 | d;

        // -- Use locals for speed
        volatile register uint32_t * pItem =  mRMT_mem_ptr;

        // Shift bits out, MSB first, setting RMTMEM.chan[n].data32[x] to the
        // rmt_item32_t value corresponding to the buffered bit value
        for (register uint32_t j = 0; j < PULSES_PER_FILL; j++) {
            *pItem++ = (pixeldata & 0x80000000L) ? one_val : zero_val;
            // Replaces: RMTMEM.chan[mRMT_channel].data32[mCurPulse].val = val;

            pixeldata <<= 1;
        }

        // -- Flip to the other half, resetting the pointer if necessary
        mWhichHalf++;
        if (mWhichHalf == 2) {
            pItem = & (RMTMEM.chan[mRMT_channel].data32[0].val);
            mWhichHalf = 0;
        }

        // -- Store the new pointer back into the object
        mRMT_mem_ptr = pItem;
    } else {
        // -- No more data; signal to the RMT we are done
        for (uint32_t j = 0; j < PULSES_PER_FILL; j++) {
            * mRMT_mem_ptr++ = 0;
        }
    }
}

// -- Init pulse buffer
//    Set up the buffer that will hold all of the pulse items for this
//    controller.
//    This function is only used when the built-in RMT driver is chosen
void ESP32RMTController::initPulseBuffer(int size_in_bytes)
{
    if (mBuffer == 0) {
        // -- Each byte has 8 bits, each bit needs a 32-bit RMT item
        int size = size_in_bytes * 8 * 4;

        mBuffer = (rmt_item32_t *) calloc( mBufferSize, sizeof(rmt_item32_t));
    }
    mCurPulse = 0;
}

// -- Convert a byte into RMT pulses
//    This function is only used when the built-in RMT driver is chosen
void ESP32RMTController::convertByte(uint32_t byteval)
{
    // -- Write one byte's worth of RMT pulses to the big buffer
    byteval <<= 24;
    for (register uint32_t j = 0; j < 8; j++) {
        mBuffer[mCurPulse] = (byteval & 0x80000000L) ? mOne : mZero;
        byteval <<= 1;
        mCurPulse++;
    }
}

#endif
<|endoftext|>


<commit_before>//
// Copyright 2010-2015 Jacob Dawid <jacob@omg-it.works>
//
// This file is part of QtWebServer.
//
// QtWebServer is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// QtWebServer 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 Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public
// License along with QtWebServer.
// If not, see <http://www.gnu.org/licenses/>.
//
// It is possible to obtain a commercial license of QtWebServer.
// Please contact Jacob Dawid <jacob@omg-it.works>
//

// Own includes
#include "httpwebengine.h"
#include "httprequest.h"
#include "httpresponse.h"

// Qt includes
#include <QString>
#include <QStringList>
#include <QDebug>

namespace QtWebServer {

namespace Http {

WebEngine::WebEngine(QObject *parent) :
    QObject(parent),
    Responder() {
}

void WebEngine::respond(QSslSocket* sslSocket) {
    // Probe if the client awaits an SSL handshake first before reading any
    // data.
    if(probeAwaitsSslHandshake(sslSocket)) {
        // Do not change the following line for security reasons
        sslSocket->setProtocol(QSsl::TlsV1_2OrLater);
        sslSocket->startServerEncryption();
        return;
    }

    // Acquire the socket so we remember it if we should receive more data for
    // this request later.
    Http::Request httpRequest = acquireSocket(sslSocket);

    // Check if the request is valid and complete.
    if(httpRequest.isValid() && httpRequest.isComplete()) {
        // Create a response object.
        Http::Response httpResponse;

        // Match the unique resource identifier on a resource.
        Resource *resource = matchResource(httpRequest.uniqueResourceIdentifier());
        if(resource != 0) {
            // If we found a resource, let it deliver the response.
            resource->deliver(httpRequest, httpResponse);
        } else {
            // Otherwise generate a 404.
            _notFoundPage->deliver(httpRequest, httpResponse);
            httpResponse.setStatusCode(NotFound);
        }

        // Write the complete response to the socket.
        writeToSocket(sslSocket, httpResponse.toByteArray());

        // This is kind of weird, but seems to perform a disconnect in
        // opposition to close.
        sslSocket->disconnectFromHost();

        // We're done with this request, so release the corresponding socket.
        releaseSocket(sslSocket);
    }
}

Http::Request WebEngine::acquireSocket(QSslSocket *sslSocket) {
    // The list of pending requests may be accessed from multiple server
    // threads, so we have to make sure to lock properly.
    MutexLocker mutexLocker(_pendingRequestsMutex); Q_UNUSED(mutexLocker);

    Http::Request httpRequest;

    // Check if we have acquired that socket already.
    if(_pendingRequests.contains(sslSocket)) {
        // Get the current request in progress.
        httpRequest = _pendingRequests.value(sslSocket);

        // Append the data from the socket.
        httpRequest.appendBodyData(sslSocket->readAll());

        // Save back the request in case there is more data to come.
        _pendingRequests.insert(sslSocket, httpRequest);
    } else {
        // Create a completely new request object.
        httpRequest = Http::Request(sslSocket->readAll());

        // Save it in the list of pending requests.
        _pendingRequests.insert(sslSocket, httpRequest);
    }
    return httpRequest;
}

void WebEngine::releaseSocket(QSslSocket *sslSocket) {
    // The list of pending requests may be accessed from multiple server
    // threads, so we have to make sure to lock properly.
    MutexLocker mutexLocker(_pendingRequestsMutex); Q_UNUSED(mutexLocker);

    // Remove all requests concerning this socket.
    _pendingRequests.remove(sslSocket);
}

void WebEngine::addResource(Resource *resource) {
    // The list of pending requests may be accessed from multiple server
    // and other threads, so we have to make sure to lock properly.
    MutexLocker mutexLocker(_resourcesMutex); Q_UNUSED(mutexLocker);
    if(resource == 0) {
        return;
    }

    resource->setParent(this);
    _resources.insert(resource);
}

void WebEngine::addNotFoundPage(Resource *resource)
{
    _notFoundPage = resource;
}

bool WebEngine::probeAwaitsSslHandshake(QSslSocket *sslSocket) {
    // If the connection is already encrypted a handshake doesn't make
    // sense
    if(sslSocket->isEncrypted()) {
        return false;
    }

    // Since there is no way to unambigously tell that the data coming
    // from a client is unencrypted or not, we try to peek the data and
    // see whether we can successfully initiate an SSL handshake.
    // If that also fails, the request is probably broken anyways.
    QByteArray peekBytes = sslSocket->peek(32768);
    Http::Request request(peekBytes);

    // If the data is garbage, it is likely to be encrypted
    return !request.isValid();
}

Resource *WebEngine::matchResource(QString uniqueResourceIdentifier) {
    // The list of pending requests may be accessed from multiple server
    // and other threads, so we have to make sure to lock properly.
    MutexLocker mutexLocker(_resourcesMutex); Q_UNUSED(mutexLocker);

    foreach(Resource *resource, _resources) {
        if(resource->match(uniqueResourceIdentifier)) {
            return resource;
        }
    }

    return 0;
}

QByteArray WebEngine::readFromSocket(QSslSocket *sslSocket) {
    return sslSocket->readAll();
}

void WebEngine::writeToSocket(QSslSocket *sslSocket, QByteArray raw) {
    int bytesWritten = 0;
    int bytesRemaining = 0;
    do {
        bytesWritten = sslSocket->write(raw);
        if(bytesWritten == -1) {
            break;
        }
        raw = raw.right(raw.count() - bytesWritten);
        bytesRemaining = raw.count();
    } while(bytesRemaining > 0);
}

} // namespace Http

} // namespace QtWebServer
<commit_msg>Do not crash if 404 page was not set<commit_after>//
// Copyright 2010-2015 Jacob Dawid <jacob@omg-it.works>
//
// This file is part of QtWebServer.
//
// QtWebServer is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// QtWebServer 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 Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public
// License along with QtWebServer.
// If not, see <http://www.gnu.org/licenses/>.
//
// It is possible to obtain a commercial license of QtWebServer.
// Please contact Jacob Dawid <jacob@omg-it.works>
//

// Own includes
#include "httpwebengine.h"
#include "httprequest.h"
#include "httpresponse.h"

// Qt includes
#include <QString>
#include <QStringList>
#include <QDebug>

namespace QtWebServer {

namespace Http {

WebEngine::WebEngine(QObject *parent) :
    QObject(parent),
    Responder(),
    _notFoundPage(Q_NULLPTR) {
}

void WebEngine::respond(QSslSocket* sslSocket) {
    // Probe if the client awaits an SSL handshake first before reading any
    // data.
    if(probeAwaitsSslHandshake(sslSocket)) {
        // Do not change the following line for security reasons
        sslSocket->setProtocol(QSsl::TlsV1_2OrLater);
        sslSocket->startServerEncryption();
        return;
    }

    // Acquire the socket so we remember it if we should receive more data for
    // this request later.
    Http::Request httpRequest = acquireSocket(sslSocket);

    // Check if the request is valid and complete.
    if(httpRequest.isValid() && httpRequest.isComplete()) {
        // Create a response object.
        Http::Response httpResponse;

        // Match the unique resource identifier on a resource.
        Resource *resource = matchResource(httpRequest.uniqueResourceIdentifier());
        if(resource != 0) {
            // If we found a resource, let it deliver the response.
            resource->deliver(httpRequest, httpResponse);
        } else {
            // Otherwise generate a 404.
            if (_notFoundPage) {
                _notFoundPage->deliver(httpRequest, httpResponse);
            } else {
                // if the 404 page was not set, generate simple HTML response
                httpResponse.setBody(QByteArray("
404 Not found
"));
                httpResponse.setHeader(ContentType, "text/html");
            }
            httpResponse.setStatusCode(NotFound);
        }

        // Write the complete response to the socket.
        writeToSocket(sslSocket, httpResponse.toByteArray());

        // This is kind of weird, but seems to perform a disconnect in
        // opposition to close.
        sslSocket->disconnectFromHost();

        // We're done with this request, so release the corresponding socket.
        releaseSocket(sslSocket);
    }
}

Http::Request WebEngine::acquireSocket(QSslSocket *sslSocket) {
    // The list of pending requests may be accessed from multiple server
    // threads, so we have to make sure to lock properly.
    MutexLocker mutexLocker(_pendingRequestsMutex); Q_UNUSED(mutexLocker);

    Http::Request httpRequest;

    // Check if we have acquired that socket already.
    if(_pendingRequests.contains(sslSocket)) {
        // Get the current request in progress.
        httpRequest = _pendingRequests.value(sslSocket);

        // Append the data from the socket.
        httpRequest.appendBodyData(sslSocket->readAll());

        // Save back the request in case there is more data to come.
        _pendingRequests.insert(sslSocket, httpRequest);
    } else {
        // Create a completely new request object.
        httpRequest = Http::Request(sslSocket->readAll());

        // Save it in the list of pending requests.
        _pendingRequests.insert(sslSocket, httpRequest);
    }
    return httpRequest;
}

void WebEngine::releaseSocket(QSslSocket *sslSocket) {
    // The list of pending requests may be accessed from multiple server
    // threads, so we have to make sure to lock properly.
    MutexLocker mutexLocker(_pendingRequestsMutex); Q_UNUSED(mutexLocker);

    // Remove all requests concerning this socket.
    _pendingRequests.remove(sslSocket);
}

void WebEngine::addResource(Resource *resource) {
    // The list of pending requests may be accessed from multiple server
    // and other threads, so we have to make sure to lock properly.
    MutexLocker mutexLocker(_resourcesMutex); Q_UNUSED(mutexLocker);
    if(resource == 0) {
        return;
    }

    resource->setParent(this);
    _resources.insert(resource);
}

void WebEngine::addNotFoundPage(Resource *resource)
{
    _notFoundPage = resource;
}

bool WebEngine::probeAwaitsSslHandshake(QSslSocket *sslSocket) {
    // If the connection is already encrypted a handshake doesn't make
    // sense
    if(sslSocket->isEncrypted()) {
        return false;
    }

    // Since there is no way to unambigously tell that the data coming
    // from a client is unencrypted or not, we try to peek the data and
    // see whether we can successfully initiate an SSL handshake.
    // If that also fails, the request is probably broken anyways.
    QByteArray peekBytes = sslSocket->peek(32768);
    Http::Request request(peekBytes);

    // If the data is garbage, it is likely to be encrypted
    return !request.isValid();
}

Resource *WebEngine::matchResource(QString uniqueResourceIdentifier) {
    // The list of pending requests may be accessed from multiple server
    // and other threads, so we have to make sure to lock properly.
    MutexLocker mutexLocker(_resourcesMutex); Q_UNUSED(mutexLocker);

    foreach(Resource *resource, _resources) {
        if(resource->match(uniqueResourceIdentifier)) {
            return resource;
        }
    }

    return 0;
}

QByteArray WebEngine::readFromSocket(QSslSocket *sslSocket) {
    return sslSocket->readAll();
}

void WebEngine::writeToSocket(QSslSocket *sslSocket, QByteArray raw) {
    int bytesWritten = 0;
    int bytesRemaining = 0;
    do {
        bytesWritten = sslSocket->write(raw);
        if(bytesWritten == -1) {
            break;
        }
        raw = raw.right(raw.count() - bytesWritten);
        bytesRemaining = raw.count();
    } while(bytesRemaining > 0);
}

} // namespace Http

} // namespace QtWebServer
<|endoftext|>


<commit_before>//
// This file is part of the Marble Virtual Globe.
//
// This program is free software licensed under the GNU LGPL. You can
// find a copy of this license in LICENSE.txt in the top directory of
// the source code.
//
// Copyright 2012      Dennis Nienhüser <earthwings@gentoo.org>
//

#include "OfflineDataModel.h"
#include "MarbleDirs.h"

#include <QtCore/QModelIndex>
#include <QtCore/QDir>

OfflineDataModel::OfflineDataModel( QObject *parent ) : QSortFilterProxyModel( parent )
{
    m_newstuffModel.setTargetDirectory( Marble::MarbleDirs::localPath() + "/maps" );
    m_newstuffModel.setRegistryFile( QDir::homePath() + "/.kde/share/apps/knewstuff3/marble-offline-data.knsregistry" );
    m_newstuffModel.setProvider( "http://files.kde.org/marble/newstuff/maps-monav.xml" );

    setSourceModel( &m_newstuffModel );
    QHash<int,QByteArray> roleNames = m_newstuffModel.roleNames();
    roleNames[Qt::UserRole+17] = "continent";
    setRoleNames( roleNames );

    sort( 0 );
    setDynamicSortFilter( true );

    connect( &m_newstuffModel, SIGNAL( installationProgressed( int, qreal ) ), this, SLOT( handleInstallationProgress( int,qreal ) ) );
    connect( &m_newstuffModel, SIGNAL( installationFinished( int ) ), this, SLOT( handleInstallationFinished( int ) ) );
    connect( &m_newstuffModel, SIGNAL( installationFailed( int, QString ) ), this, SLOT( handleInstallationFailed( int, QString ) ) );
    connect( &m_newstuffModel, SIGNAL( uninstallationFinished( int ) ), this, SLOT( handleUninstallationFinished( int ) ) );
}

int OfflineDataModel::count()
{
    return rowCount();
}

QVariant OfflineDataModel::data(const QModelIndex &index, int role) const
{
    if ( index.isValid() && index.row() >= 0 && index.row() < rowCount() && role == Qt::DisplayRole ) {
        QStringList const data = QSortFilterProxyModel::data( index, role ).toString().split( '/' );
        if ( data.size() > 1 ) {
            QString result = data.at( 1 );
            for ( int i=2; i<data.size(); ++i ) {
                result += " / " + data.at( i );
            }
            result.replace( " (Motorcar)", "" );
            result.replace( " (Pedestrian)", "" );
            result.replace( " (Bicycle)", "" );
            return result.trimmed();
        }
    }

    if ( index.isValid() && index.row() >= 0 && index.row() < rowCount() && role == Qt::UserRole+17 ) {
        QStringList const data = QSortFilterProxyModel::data( index, Qt::DisplayRole ).toString().split( '/' );
        if ( data.size() > 1 ) {
            return data.first().trimmed();
        }
    }

    return QSortFilterProxyModel::data( index, role );
}

void OfflineDataModel::install( int index )
{
    m_newstuffModel.install( toSource( index ) );
}

void OfflineDataModel::uninstall( int index )
{
    m_newstuffModel.uninstall( toSource( index ) );
}

void OfflineDataModel::cancel( int index )
{
    m_newstuffModel.cancel( toSource( index ) );
}

int OfflineDataModel::fromSource( int index ) const
{
    return mapFromSource( m_newstuffModel.index( index ) ).row();
}

int OfflineDataModel::toSource(int idx) const
{
    return mapToSource( index( idx, 0 ) ).row();
}

void OfflineDataModel::handleInstallationProgress( int index, qreal progress )
{
    emit installationProgressed( fromSource( index ), progress );
}

void OfflineDataModel::handleInstallationFinished( int index )
{
    emit installationFinished( fromSource( index ) );
}

void OfflineDataModel::handleInstallationFailed( int index, const QString &error )
{
    emit installationFailed( fromSource( index ), error );
}

void OfflineDataModel::handleUninstallationFinished( int index )
{
    emit uninstallationFinished( fromSource( index ) );
}

#include "OfflineDataModel.moc"
<commit_msg>Fix offline data upgrade availability detection. (cherry picked from commit 821928bbd79fca09ba26d528b1b0c48ef606d31a)<commit_after>//
// This file is part of the Marble Virtual Globe.
//
// This program is free software licensed under the GNU LGPL. You can
// find a copy of this license in LICENSE.txt in the top directory of
// the source code.
//
// Copyright 2012      Dennis Nienhüser <earthwings@gentoo.org>
//

#include "OfflineDataModel.h"
#include "MarbleDirs.h"

#include <QtCore/QModelIndex>
#include <QtCore/QDir>

OfflineDataModel::OfflineDataModel( QObject *parent ) : QSortFilterProxyModel( parent )
{
    m_newstuffModel.setTargetDirectory( Marble::MarbleDirs::localPath() + "/maps" );
    m_newstuffModel.setRegistryFile( QDir::homePath() + "/.kde/share/apps/knewstuff3/marble-offline-data.knsregistry", Marble::NewstuffModel::NameTag );
    m_newstuffModel.setProvider( "http://files.kde.org/marble/newstuff/maps-monav.xml" );

    setSourceModel( &m_newstuffModel );
    QHash<int,QByteArray> roleNames = m_newstuffModel.roleNames();
    roleNames[Qt::UserRole+17] = "continent";
    setRoleNames( roleNames );

    sort( 0 );
    setDynamicSortFilter( true );

    connect( &m_newstuffModel, SIGNAL( installationProgressed( int, qreal ) ), this, SLOT( handleInstallationProgress( int,qreal ) ) );
    connect( &m_newstuffModel, SIGNAL( installationFinished( int ) ), this, SLOT( handleInstallationFinished( int ) ) );
    connect( &m_newstuffModel, SIGNAL( installationFailed( int, QString ) ), this, SLOT( handleInstallationFailed( int, QString ) ) );
    connect( &m_newstuffModel, SIGNAL( uninstallationFinished( int ) ), this, SLOT( handleUninstallationFinished( int ) ) );
}

int OfflineDataModel::count()
{
    return rowCount();
}

QVariant OfflineDataModel::data(const QModelIndex &index, int role) const
{
    if ( index.isValid() && index.row() >= 0 && index.row() < rowCount() && role == Qt::DisplayRole ) {
        QStringList const data = QSortFilterProxyModel::data( index, role ).toString().split( '/' );
        if ( data.size() > 1 ) {
            QString result = data.at( 1 );
            for ( int i=2; i<data.size(); ++i ) {
                result += " / " + data.at( i );
            }
            result.replace( " (Motorcar)", "" );
            result.replace( " (Pedestrian)", "" );
            result.replace( " (Bicycle)", "" );
            return result.trimmed();
        }
    }

    if ( index.isValid() && index.row() >= 0 && index.row() < rowCount() && role == Qt::UserRole+17 ) {
        QStringList const data = QSortFilterProxyModel::data( index, Qt::DisplayRole ).toString().split( '/' );
        if ( data.size() > 1 ) {
            return data.first().trimmed();
        }
    }

    return QSortFilterProxyModel::data( index, role );
}

void OfflineDataModel::install( int index )
{
    m_newstuffModel.install( toSource( index ) );
}

void OfflineDataModel::uninstall( int index )
{
    m_newstuffModel.uninstall( toSource( index ) );
}

void OfflineDataModel::cancel( int index )
{
    m_newstuffModel.cancel( toSource( index ) );
}

int OfflineDataModel::fromSource( int index ) const
{
    return mapFromSource( m_newstuffModel.index( index ) ).row();
}

int OfflineDataModel::toSource(int idx) const
{
    return mapToSource( index( idx, 0 ) ).row();
}

void OfflineDataModel::handleInstallationProgress( int index, qreal progress )
{
    emit installationProgressed( fromSource( index ), progress );
}

void OfflineDataModel::handleInstallationFinished( int index )
{
    emit installationFinished( fromSource( index ) );
}

void OfflineDataModel::handleInstallationFailed( int index, const QString &error )
{
    emit installationFailed( fromSource( index ), error );
}

void OfflineDataModel::handleUninstallationFinished( int index )
{
    emit uninstallationFinished( fromSource( index ) );
}

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


<commit_before>/*******************************************************
 * Copyright (c) 2014, ArrayFire
 * All rights reserved.
 *
 * This file is distributed under 3-clause BSD license.
 * The complete license agreement can be obtained at:
 * http://arrayfire.com/licenses/BSD-3-Clause
********************************************************/

#if defined(__APPLE__) && !defined(AF_CUDA)
#include <Accelerate/Accelerate.h>
#include "lapacke.hpp"
#include <cstdint>

#if INTPTR_MAX == INT16MAX
    #define BS 16
#elif INTPTR_MAX == INT32MAX
    #define BS 32
#elif INTPTR_MAX == INT64MAX
    #define BS 64
#else
    #define BS 32
#endif

#define LAPACK_FUNC(X, T, TO)                                                       \
int LAPACKE_##X##geqrf(int layout, int M, int N, T *A, int lda, T *tau)             \
{                                                                                \
    int lwork = N * BS;                                                             \
    T *work = new T[lwork];                                                         \
    int info = 0;                                                                   \
    int ret = X##geqrf_(&M, &N, (TO)A, &lda, (TO)tau, (TO)work, &lwork, &info);     \
    delete [] work;                                                                 \
    return info;                                                                    \
}                                                                                \
int LAPACKE_##X##geqrf_work(int layout, int M, int N, T *A, int lda,                \
                            T *tau, T *work, int lwork)                             \
{                                                                                \
    int info = 0;                                                                   \
    int ret = X##geqrf_(&M, &N, (TO)A, &lda, (TO)tau, (TO)work, &lwork, &info);     \
    return info;                                                                    \
}                                                                                \
int LAPACKE_##X##getrf(int layout, int M, int N, T *A, int lda, int *pivot)         \
{                                                                                \
    int info = 0;                                                                   \
    int ret = X##getrf_(&M, &N, (TO)A, &lda, pivot, &info);                         \
    return info;                                                                    \
}                                                                                \
int LAPACKE_##X##potrf(int layout, char uplo, int N, T *A, int lda)                 \
{                                                                                \
    int info = 0;                                                                   \
    int ret = X##potrf_(&uplo, &N, (TO)A, &lda, &info);                             \
    return info;                                                                    \
}                                                                                \
int LAPACKE_##X##gesv(int layout, int N, int nrhs, T *A, int lda,                   \
                      int *pivot, T *B, int ldb)                                    \
{                                                                                \
    int info = 0;                                                                   \
    int ret = X##gesv_(&N, &nrhs, (TO)A, &lda, pivot, (TO)B, &ldb, &info);          \
    return info;                                                                    \
}                                                                                \
int LAPACKE_##X##gels(int layout, char trans, int M, int N, int nrhs,               \
                      T *A, int lda, T *B, int ldb)                                 \
{                                                                                \
    int lwork = std::min(M, N) + std::max(M, std::max(N, nrhs)) * BS;               \
    T *work = new T[lwork];                                                         \
    int info = 0;                                                                   \
    int ret = X##gels_(&trans, &M, &N, &nrhs, (TO)A, &lda,                          \
                       (TO)B, &ldb, (TO)work, &lwork, &info);                       \
    delete [] work;                                                                 \
    return info;                                                                    \
}                                                                                \
int LAPACKE_##X##getri(int layout, int N, T *A, int lda, const int *pivot)          \
{                                                                                \
    int lwork = N * BS;                                                             \
    T *work = new T[lwork];                                                         \
    int info = 0;                                                                   \
    int ret = X##getri_(&N, (TO)A, &lda, const_cast<int *>(pivot),                  \
                        (TO)work, &lwork, &info);                                   \
    delete [] work;                                                                 \
    return info;                                                                    \
}                                                                                \
int LAPACKE_##X##trtri(int layout, char uplo, char diag, int N, T *A, int lda)      \
{                                                                                \
    int info = 0;                                                                   \
    int ret = X##trtri_(&uplo, &diag, &N, (TO)A, &lda, &info);                      \
    return info;                                                                    \
}                                                                                \
int LAPACKE_##X##larft(int layout, char direct, char storev, int N, int K,          \
                       const T *v, int ldv, const T *tau, T *t, int ldt)            \
{                                                                                \
    int ret = X##larft_(&direct, &storev, &N, &K, (TO)v, &ldv,                      \
                        (TO)const_cast<T*>(tau), (TO)t, &ldt);                      \
    return ret;                                                                     \
}                                                                                \
int LAPACKE_##X##laswp(int layout, int N, T *A, int lda,                            \
                       int k1, int k2, const int *pivot, int incx)                  \
{                                                                                \
    int ret = X##laswp_(&N, (TO)A, &lda, &k1, &k2, const_cast<int*>(pivot), &incx); \
    return ret;                                                                     \
}                                                                                \

LAPACK_FUNC(s, float, float*)
LAPACK_FUNC(d, double, double*)
LAPACK_FUNC(c, cfloat, __CLPK_complex*)
LAPACK_FUNC(z, cdouble, __CLPK_doublecomplex*)

#define LAPACK_GQR(P, X, T, TO)                                                     \
int LAPACKE_##X##P(int layout, int M, int N, int K, T *A, int lda, const T *tau)    \
{                                                                                \
    int lwork = N * 32;                                                             \
    T *work = new T[lwork];                                                         \
    int info = 0;                                                                   \
    int ret = X##P##_(&M, &N, &K, (TO)A, &lda, (TO)tau, (TO)work, &lwork, &info);   \
    delete [] work;                                                                 \
    return info;                                                                    \
}                                                                                \

LAPACK_GQR(orgqr, s, float, float*)
LAPACK_GQR(orgqr, d, double, double*)
LAPACK_GQR(ungqr, c, cfloat, __CLPK_complex*)
LAPACK_GQR(ungqr, z, cdouble, __CLPK_doublecomplex*)

#define LAPACK_GQR_WORK(P, X, T, TO)                                                \
int LAPACKE_##X##P##_work(int layout, int M, int N, int K, T *A, int lda,           \
                          const T *tau, T *work, int lwork)                         \
{                                                                                \
    int info = 0;                                                                   \
    int ret = X##P##_(&M, &N, &K, (TO)A, &lda, (TO)tau, (TO)work, &lwork, &info);   \
    return info;                                                                    \
}                                                                                \

LAPACK_GQR_WORK(orgqr, s, float, float*)
LAPACK_GQR_WORK(orgqr, d, double, double*)
LAPACK_GQR_WORK(ungqr, c, cfloat, __CLPK_complex*)
LAPACK_GQR_WORK(ungqr, z, cdouble, __CLPK_doublecomplex*)

#define LAPACK_MQR_WORK(P, X, T, TO)                                                \
int LAPACKE_##X##P##_work(int layout, char side, char trans, int M, int N, int K,   \
                          const T *A, int lda, const T *tau, T *c, int ldc,         \
                          T *work, int lwork)                                       \
{                                                                                \
    int info = 0;                                                                   \
    int ret = X##P##_(&side, &trans, &M, &N, &K, (TO)A, &lda, (TO)tau, (TO)c, &ldc, \
                      (TO)work, &lwork, &info);                                     \
    return info;                                                                    \
}                                                                                \

LAPACK_MQR_WORK(ormqr, s, float, float*)
LAPACK_MQR_WORK(ormqr, d, double, double*)
LAPACK_MQR_WORK(unmqr, c, cfloat, __CLPK_complex*)
LAPACK_MQR_WORK(unmqr, z, cdouble, __CLPK_doublecomplex*)

#endif
<commit_msg>Adding getrs to backend/lapacke.cpp<commit_after>/*******************************************************
 * Copyright (c) 2014, ArrayFire
 * All rights reserved.
 *
 * This file is distributed under 3-clause BSD license.
 * The complete license agreement can be obtained at:
 * http://arrayfire.com/licenses/BSD-3-Clause
********************************************************/

#if defined(__APPLE__) && !defined(AF_CUDA)
#include <Accelerate/Accelerate.h>
#include "lapacke.hpp"
#include <cstdint>

#if INTPTR_MAX == INT16MAX
    #define BS 16
#elif INTPTR_MAX == INT32MAX
    #define BS 32
#elif INTPTR_MAX == INT64MAX
    #define BS 64
#else
    #define BS 32
#endif

#define LAPACK_FUNC(X, T, TO)                                                       \
int LAPACKE_##X##geqrf(int layout, int M, int N, T *A, int lda, T *tau)             \
{                                                                                \
    int lwork = N * BS;                                                             \
    T *work = new T[lwork];                                                         \
    int info = 0;                                                                   \
    int ret = X##geqrf_(&M, &N, (TO)A, &lda, (TO)tau, (TO)work, &lwork, &info);     \
    delete [] work;                                                                 \
    return info;                                                                    \
}                                                                                \
int LAPACKE_##X##geqrf_work(int layout, int M, int N, T *A, int lda,                \
                            T *tau, T *work, int lwork)                             \
{                                                                                \
    int info = 0;                                                                   \
    int ret = X##geqrf_(&M, &N, (TO)A, &lda, (TO)tau, (TO)work, &lwork, &info);     \
    return info;                                                                    \
}                                                                                \
int LAPACKE_##X##getrf(int layout, int M, int N, T *A, int lda, int *pivot)         \
{                                                                                \
    int info = 0;                                                                   \
    int ret = X##getrf_(&M, &N, (TO)A, &lda, pivot, &info);                         \
    return info;                                                                    \
}                                                                                \
int LAPACKE_##X##getrs(int layout, int M, int N, const T *A,                        \
                       int lda, const int *pivot, T *B, int ldb)                    \
{                                                                                \
    int info = 0;                                                                   \
    int ret = X##getrs_(&M, &N, (TO)A, &lda, (int *)pivot, (TO)B, ldb, &info);      \
    return info;                                                                    \
}                                                                                \
int LAPACKE_##X##potrf(int layout, char uplo, int N, T *A, int lda)                 \
{                                                                                \
    int info = 0;                                                                   \
    int ret = X##potrf_(&uplo, &N, (TO)A, &lda, &info);                             \
    return info;                                                                    \
}                                                                                \
int LAPACKE_##X##gesv(int layout, int N, int nrhs, T *A, int lda,                   \
                      int *pivot, T *B, int ldb)                                    \
{                                                                                \
    int info = 0;                                                                   \
    int ret = X##gesv_(&N, &nrhs, (TO)A, &lda, pivot, (TO)B, &ldb, &info);          \
    return info;                                                                    \
}                                                                                \
int LAPACKE_##X##gels(int layout, char trans, int M, int N, int nrhs,               \
                      T *A, int lda, T *B, int ldb)                                 \
{                                                                                \
    int lwork = std::min(M, N) + std::max(M, std::max(N, nrhs)) * BS;               \
    T *work = new T[lwork];                                                         \
    int info = 0;                                                                   \
    int ret = X##gels_(&trans, &M, &N, &nrhs, (TO)A, &lda,                          \
                       (TO)B, &ldb, (TO)work, &lwork, &info);                       \
    delete [] work;                                                                 \
    return info;                                                                    \
}                                                                                \
int LAPACKE_##X##getri(int layout, int N, T *A, int lda, const int *pivot)          \
{                                                                                \
    int lwork = N * BS;                                                             \
    T *work = new T[lwork];                                                         \
    int info = 0;                                                                   \
    int ret = X##getri_(&N, (TO)A, &lda, const_cast<int *>(pivot),                  \
                        (TO)work, &lwork, &info);                                   \
    delete [] work;                                                                 \
    return info;                                                                    \
}                                                                                \
int LAPACKE_##X##trtri(int layout, char uplo, char diag, int N, T *A, int lda)      \
{                                                                                \
    int info = 0;                                                                   \
    int ret = X##trtri_(&uplo, &diag, &N, (TO)A, &lda, &info);                      \
    return info;                                                                    \
}                                                                                \
int LAPACKE_##X##larft(int layout, char direct, char storev, int N, int K,          \
                       const T *v, int ldv, const T *tau, T *t, int ldt)            \
{                                                                                \
    int ret = X##larft_(&direct, &storev, &N, &K, (TO)v, &ldv,                      \
                        (TO)const_cast<T*>(tau), (TO)t, &ldt);                      \
    return ret;                                                                     \
}                                                                                \
int LAPACKE_##X##laswp(int layout, int N, T *A, int lda,                            \
                       int k1, int k2, const int *pivot, int incx)                  \
{                                                                                \
    int ret = X##laswp_(&N, (TO)A, &lda, &k1, &k2, const_cast<int*>(pivot), &incx); \
    return ret;                                                                     \
}                                                                                \

LAPACK_FUNC(s, float, float*)
LAPACK_FUNC(d, double, double*)
LAPACK_FUNC(c, cfloat, __CLPK_complex*)
LAPACK_FUNC(z, cdouble, __CLPK_doublecomplex*)

#define LAPACK_GQR(P, X, T, TO)                                                     \
int LAPACKE_##X##P(int layout, int M, int N, int K, T *A, int lda, const T *tau)    \
{                                                                                \
    int lwork = N * 32;                                                             \
    T *work = new T[lwork];                                                         \
    int info = 0;                                                                   \
    int ret = X##P##_(&M, &N, &K, (TO)A, &lda, (TO)tau, (TO)work, &lwork, &info);   \
    delete [] work;                                                                 \
    return info;                                                                    \
}                                                                                \

LAPACK_GQR(orgqr, s, float, float*)
LAPACK_GQR(orgqr, d, double, double*)
LAPACK_GQR(ungqr, c, cfloat, __CLPK_complex*)
LAPACK_GQR(ungqr, z, cdouble, __CLPK_doublecomplex*)

#define LAPACK_GQR_WORK(P, X, T, TO)                                                \
int LAPACKE_##X##P##_work(int layout, int M, int N, int K, T *A, int lda,           \
                          const T *tau, T *work, int lwork)                         \
{                                                                                \
    int info = 0;                                                                   \
    int ret = X##P##_(&M, &N, &K, (TO)A, &lda, (TO)tau, (TO)work, &lwork, &info);   \
    return info;                                                                    \
}                                                                                \

LAPACK_GQR_WORK(orgqr, s, float, float*)
LAPACK_GQR_WORK(orgqr, d, double, double*)
LAPACK_GQR_WORK(ungqr, c, cfloat, __CLPK_complex*)
LAPACK_GQR_WORK(ungqr, z, cdouble, __CLPK_doublecomplex*)

#define LAPACK_MQR_WORK(P, X, T, TO)                                                \
int LAPACKE_##X##P##_work(int layout, char side, char trans, int M, int N, int K,   \
                          const T *A, int lda, const T *tau, T *c, int ldc,         \
                          T *work, int lwork)                                       \
{                                                                                \
    int info = 0;                                                                   \
    int ret = X##P##_(&side, &trans, &M, &N, &K, (TO)A, &lda, (TO)tau, (TO)c, &ldc, \
                      (TO)work, &lwork, &info);                                     \
    return info;                                                                    \
}                                                                                \

LAPACK_MQR_WORK(ormqr, s, float, float*)
LAPACK_MQR_WORK(ormqr, d, double, double*)
LAPACK_MQR_WORK(unmqr, c, cfloat, __CLPK_complex*)
LAPACK_MQR_WORK(unmqr, z, cdouble, __CLPK_doublecomplex*)

#endif
<|endoftext|>


<commit_before>// Segment Tree
int st[4*N], v[N], lz[4*N];

void build(int p, int l, int r) {
  if (l == r) { st[p] = v[l]; return; }
  build(2*p, l, (l+r)/2);
  build(2*p+1, (l+r)/2+1, r);
  st[p] = min(st[2*p], st[2*p+1]); // RMQ -> min/max, RSQ -> +
}

void push(int p, int l, int r) {
  if (lz[p]) {
    st[p] = lz[p];
    // RMQ -> update: = lz[p],         increment: += lz[p]
    // RSQ -> update: = (r-l+1)*lz[p], increment: += (r-l+1)*lz[p]
    if(l!=r) lz[2*p] = lz[2*p+1] = lz[p]; // update: =, increment +=
    lz[p] = 0;
  }
}

int query(int p, int l, int r, int i, int j) {
  if (r < i or l > j) return INF; // RMQ -> INF, RSQ -> 0
  push(p, l, r);
  if (l >= i and r <= j) return st[p];
  return min(query(2*p, l, (l+r)/2, i, j),
             query(2*p+1, (l+r)/2+1, r, i, j));
  // RMQ -> min/max, RSQ -> +
}

void update(int p, int l, int r, int i, int j, int v) {
  if (r < i or l > j) return;
  push(p, l, r);
  if (l >= i and r <= j) { lz[p] = v; push(p, l, r); return; }
  update(2*p, l, (l+r)/2, i, j, v);
  update(2*p+1, (l+r)/2+1, r, i, j, v);
  st[p] = min(st[2*p], st[2*p+1]); // RMQ -> min/max, RSQ -> +
}
<commit_msg>Fixed bug in segtree code<commit_after>// Segment Tree
int st[4*N], v[N], lz[4*N];

void build(int p, int l, int r) {
  if (l == r) { st[p] = v[l]; return; }
  build(2*p, l, (l+r)/2);
  build(2*p+1, (l+r)/2+1, r);
  st[p] = min(st[2*p], st[2*p+1]); // RMQ -> min/max, RSQ -> +
}

void push(int p, int l, int r) {
  if (lz[p]) {
    st[p] = lz[p];
    // RMQ -> update: = lz[p],         increment: += lz[p]
    // RSQ -> update: = (r-l+1)*lz[p], increment: += (r-l+1)*lz[p]
    if(l!=r) lz[2*p] = lz[2*p+1] = lz[p]; // update: =, increment +=
    lz[p] = 0;
  }
}

int query(int p, int l, int r, int i, int j) {
  push(p, l, r);
  if (r < i or l > j) return INF; // RMQ -> INF, RSQ -> 0
  if (l >= i and r <= j) return st[p];
  return min(query(2*p, l, (l+r)/2, i, j),
             query(2*p+1, (l+r)/2+1, r, i, j));
  // RMQ -> min/max, RSQ -> +
}

void update(int p, int l, int r, int i, int j, int v) {
  push(p, l, r);
  if (r < i or l > j) return;
  if (l >= i and r <= j) { lz[p] = v; push(p, l, r); return; }
  update(2*p, l, (l+r)/2, i, j, v);
  update(2*p+1, (l+r)/2+1, r, i, j, v);
  st[p] = min(st[2*p], st[2*p+1]); // RMQ -> min/max, RSQ -> +
}
<|endoftext|>