<commit_before>#define _CRT_SECURE_NO_WARNINGS

#include <stdio.h>
#include <string.h>
#include "pcap.h"
#include "http_inject.h"

#pragma comment (lib, "wpcap.lib")

u_char redirect_data[] = "HTTP/1.1 302 Found\r\nLocation: http://warning.or.kr/\r\n\r\n";
u_char blocked_data[] = "HTTP/1.1 200 OK\r\nContent-Length: 8\r\n\r\nblocked!";
int redirect_size = 56;
int blocked_size = 47;
pcap_t *dev_handle;
int main()
{
	pcap_if_t *dev_list;
	pcap_if_t *dev_tmp;
	int input, dev_list_len;

	pcap_findalldevs(&dev_list, (char*)stderr);
	dev_tmp = dev_list;
	for (dev_list_len = 0; dev_tmp != NULL; dev_list_len++)
	{
		printf("%d - %s\n", dev_list_len + 1, dev_tmp->description);
		dev_tmp = dev_tmp->next;
	}
	do
	{
		printf("Select Device : ");
		scanf("%d", &input);
	} while (input < 1 || input >dev_list_len);
	dev_tmp = dev_list;
	for (int i = 0; i < input - 1; i++)
		dev_tmp = dev_tmp->next;

	dev_handle = pcap_open_live(dev_tmp->name, 65536, 1, 100, (char*)stderr);

	pcap_freealldevs(dev_list);

	pcap_loop(dev_handle, 0, packet_handler, NULL);

	pcap_close(dev_handle);
	return 0;
}

void packet_handler(u_char *paramn, const struct pcap_pkthdr *header, const u_char *packet)
{
	int type = mntohs(packet[ETH_PROTO_OFFSET]);

	u_short ipv4_proto = packet[ETH_LENGTH + IPV4_PROTO_OFFSET];

	if (type == IP4 && ipv4_proto == TCP) //IPv4̰ TCP϶
	{
		u_short ipv4_header_size, ipv4_total_length, tcp_header_size;
		ipv4_header_size = packet[ETH_LENGTH + IPV4_LENGTH_OFFSET];
		ipv4_header_size &= 0x0F;
		ipv4_header_size *= 4;

		ipv4_total_length = mntohs(packet[ETH_LENGTH + IPV4_SIZE_OFFSET]);

		tcp_header_size = packet[ETH_LENGTH + ipv4_header_size + TCP_LENGTH_OFFSET];
		tcp_header_size &= 0xF0;
		tcp_header_size /= 0x10;
		tcp_header_size *= 4;

		if (!data_cmp((u_char*)"GET", &packet[ETH_LENGTH + ipv4_header_size + tcp_header_size], 3)) //HTTP û ϰ
		{
			u_char* data_forward = (u_char*)malloc(header->len);
			u_char* data_backward = (u_char*)malloc(header->len);
			u_short ipv4_chk, tcp_chk, ipv4_proto;
			u_long tcp_pr_chk;
			int acknowledgement = 0, sequence = 0, request_tcp_len = 0;

			memcpy(data_forward, packet, header->len);
			memcpy(data_backward, packet, header->len);

			request_tcp_len = ipv4_total_length - ipv4_header_size, tcp_header_size;

			/* TCP   */
			mstrncpy(&data_forward[ETH_LENGTH + ipv4_header_size + tcp_header_size], blocked_data, blocked_size);

			/* RST ÷  */
			data_forward[ETH_LENGTH + ipv4_header_size + TCP_FLAG_OFFSET] = 0b00000100;

			/* IPv4 ü  ȯ */
			ipv4_total_length = ipv4_header_size + tcp_header_size + blocked_size;
			*(u_short*)&data_forward[ETH_LENGTH + IPV4_SIZE_OFFSET] = mntohs(ipv4_total_length);

			/* IPv4 CHECK SUM 0x00  */
			*(u_short*)&data_forward[ETH_LENGTH + IPV4_CHKSUM_OFFSET] = 0x0000;

			/* IPv4 CHECK SUM  */
			ipv4_chk = in_cksum((u_short*)&data_forward[ETH_LENGTH], ipv4_header_size, 0);

			/* IPv4 CHECK SUM  */
			*(u_short*)&data_forward[ETH_LENGTH + IPV4_CHKSUM_OFFSET] = mntohs(ipv4_chk);

			/* TCP CHECK SUM 0x00  */
			*(u_short*)&data_forward[ETH_LENGTH + ipv4_header_size + TCP_CHKSUM_OFFSET] = 0x0000;

			/* TCP CHECK SUM  */
			/* 8 is srcip and dstip size */
			tcp_pr_chk = 0;
			tcp_chk = 0;
			ipv4_proto = data_forward[ETH_LENGTH + IPV4_PROTO_OFFSET];

			tcp_pr_chk += ipv4_proto;
			tcp_pr_chk += ipv4_total_length - ipv4_header_size; //tcp total length
			tcp_chk = in_cksum((u_short*)&data_forward[ETH_LENGTH + ipv4_header_size - 8], 8 + tcp_header_size + blocked_size, tcp_pr_chk);

			/* TCP CHECK SUM  */
			*(u_short*)&data_forward[ETH_LENGTH + ipv4_header_size + TCP_CHKSUM_OFFSET] = mntohs(tcp_chk);

			pcap_sendpacket(dev_handle, data_forward, ETH_LENGTH + ipv4_header_size + tcp_header_size + blocked_size);

			/* TCP   */
			mstrncpy(&data_backward[ETH_LENGTH + ipv4_header_size + tcp_header_size], redirect_data, redirect_size);

			/* IPv4 dst, src IP  */
			mnswap(&data_backward[ETH_LENGTH + IPV4_DIP_OFFSET], &data_backward[ETH_LENGTH + IPV4_SIP_OFFSET], IP_LEN);

			/* TCP port  */
			mnswap(&data_backward[ETH_LENGTH + ipv4_header_size + TCP_SPORT_OFFSET],
				&data_backward[ETH_LENGTH + ipv4_header_size + TCP_DPORT_OFFSET],
				PORT_LEN);

			/* TCP  ѹ <- -> ACK ѹ  */
			/*  + tcp = ACK ѹ */
			sequence = mntohl(*(u_long*)&data_backward[ETH_LENGTH + ipv4_header_size + TCP_SEQUENCE_OFFSET]);
			sequence += request_tcp_len;

			acknowledgement = mntohl(*(u_long*)&data_backward[ETH_LENGTH + ipv4_header_size + TCP_ACKNOWLEDGEMENT_OFFSET]);

			*(u_long*)&data_backward[ETH_LENGTH + ipv4_header_size + TCP_SEQUENCE_OFFSET] = mntohl(acknowledgement);
			*(u_long*)&data_backward[ETH_LENGTH + ipv4_header_size + TCP_ACKNOWLEDGEMENT_OFFSET] = mntohl(sequence);

			/* IPv4 ü  ȯ */
			ipv4_total_length = ipv4_header_size + tcp_header_size + redirect_size;
			*(u_short*)&data_backward[ETH_LENGTH + IPV4_SIZE_OFFSET] = mntohs(ipv4_total_length);

			/* IPv4 CHECK SUM 0x00  */
			*(u_short*)&data_backward[ETH_LENGTH + IPV4_CHKSUM_OFFSET] = 0x0000;

			/* IPv4 CHECK SUM  */
			ipv4_chk = in_cksum((u_short*)&data_backward[ETH_LENGTH], ipv4_header_size, 0);

			/* IPv4 CHECK SUM  */
			*(u_short*)&data_backward[ETH_LENGTH + IPV4_CHKSUM_OFFSET] = mntohs(ipv4_chk);

			/* TCP CHECK SUM 0x00  */
			*(u_short*)&data_backward[ETH_LENGTH + ipv4_header_size + TCP_CHKSUM_OFFSET] = 0x0000;

			/* TCP CHECK SUM  */
			/* 8 is srcip and dstip size */
			tcp_pr_chk = 0;
			tcp_chk = 0;
			ipv4_proto = data_backward[ETH_LENGTH + IPV4_PROTO_OFFSET];

			tcp_pr_chk += ipv4_proto;
			tcp_pr_chk += ipv4_total_length - ipv4_header_size; //tcp total length
			tcp_chk = in_cksum((u_short*)&data_backward[ETH_LENGTH + ipv4_header_size - 8], 8 + tcp_header_size + redirect_size, tcp_pr_chk);

			/* TCP CHECK SUM  */
			*(u_short*)&data_backward[ETH_LENGTH + ipv4_header_size + TCP_CHKSUM_OFFSET] = mntohs(tcp_chk);

			pcap_sendpacket(dev_handle, data_backward, ETH_LENGTH + ipv4_header_size + tcp_header_size + redirect_size);
			free(data_forward);
			free(data_backward);
		}

	}
}
void mstrncpy(u_char* target, u_char* source, int num)
{
	memcpy(target, source, num);
}
int data_cmp(const u_char* source1, const u_char* source2, int len)
{
	for (int i = 0; i < len; i++)
		if (source1[i] != source2[i])
			return 1;
	return 0;
}
u_short in_cksum(u_short *addr, int len, long sum)
{
	u_short answer = 0;
	u_short *w = addr;
	register int nleft = len;

	while (nleft > 1) {
		sum += mntohs(*w++);
		nleft -= 2;
	}

	if (nleft == 1) {
		*(u_char *)(&answer) = *(u_char *)w;
		sum += (short)answer * 0x100;
	}
	sum = (sum >> 16) + (sum & 0xffff);
	sum += (sum >> 16);
	answer = (u_short)~sum;

	return(answer);
}
void mncopy(u_char* destination, u_char* source, int len)
{
	for (int i = 0; i < len; i++)
	{
		destination[i] = source[i];
	}
}
void mnswap(u_char* destination, u_char* source, int len)
{
	for (int i = 0; i < len; i++)
	{
		destination[i] ^= source[i];
		source[i] ^= destination[i];
		destination[i] ^= source[i];
	}
}
inline u_long mntohl(u_long l)
{
	u_long d = 0;
	d += (l & 0xFF000000) >> 24;
	d += (l & 0x00FF0000) >> 8;
	d += (l & 0x0000FF00) << 8;
	d += (l & 0x000000FF) << 24;
	return d;
}
inline u_short mntohs(u_short s)
{
	short d = 0;
	d += (s & 0xFF00) >> 8;
	d += (s & 0x00FF) << 8;
	return d;
}<commit_msg>modifiy code<commit_after>#define _CRT_SECURE_NO_WARNINGS

#include <stdio.h>
#include <string.h>
#include "pcap.h"
#include "http_inject.h"

#pragma comment (lib, "wpcap.lib")

u_char redirect_data[] = "HTTP/1.1 302 Found\r\nLocation: http://warning.or.kr/\r\n\r\n";
u_char blocked_data[] = "HTTP/1.1 200 OK\r\nContent-Length: 8\r\n\r\nblocked!";
int redirect_size = 56;
int blocked_size = 47;
pcap_t *dev_handle;
int main()
{
	pcap_if_t *dev_list;
	pcap_if_t *dev_tmp;
	int input, dev_list_len;

	pcap_findalldevs(&dev_list, (char*)stderr);
	dev_tmp = dev_list;
	for (dev_list_len = 0; dev_tmp != NULL; dev_list_len++)
	{
		printf("%d - %s\n", dev_list_len + 1, dev_tmp->description);
		dev_tmp = dev_tmp->next;
	}
	do
	{
		printf("Select Device : ");
		scanf("%d", &input);
	} while (input < 1 || input >dev_list_len);
	dev_tmp = dev_list;
	for (int i = 0; i < input - 1; i++)
		dev_tmp = dev_tmp->next;

	dev_handle = pcap_open_live(dev_tmp->name, 65536, 1, 100, (char*)stderr);

	pcap_freealldevs(dev_list);

	pcap_loop(dev_handle, 0, packet_handler, NULL);

	pcap_close(dev_handle);
	return 0;
}

void packet_handler(u_char *paramn, const struct pcap_pkthdr *header, const u_char *packet)
{
	int type = mntohs(packet[ETH_PROTO_OFFSET]);

	u_short ipv4_proto = packet[ETH_LEN + IPV4_PROTO_OFFSET];

	if (type == IP4 && ipv4_proto == TCP) //IPv4̰ TCP϶
	{
		u_short ipv4_header_size, ipv4_total_length, tcp_header_size;
		ipv4_header_size = packet[ETH_LEN + IPV4_LENGTH_OFFSET];
		ipv4_header_size &= 0x0F;
		ipv4_header_size *= 4;

		ipv4_total_length = mntohs(packet[ETH_LEN + IPV4_SIZE_OFFSET]);

		tcp_header_size = packet[ETH_LEN + ipv4_header_size + TCP_LENGTH_OFFSET];
		tcp_header_size &= 0xF0;
		tcp_header_size /= 0x10;
		tcp_header_size *= 4;

		if (!data_cmp((u_char*)"GET", &packet[ETH_LEN + ipv4_header_size + tcp_header_size], 3)) //HTTP û ϰ
		{
			u_char* data_forward = (u_char*)malloc(ETH_LEN + ipv4_header_size + tcp_header_size + blocked_size);
			u_char* data_backward = (u_char*)malloc(ETH_LEN + ipv4_header_size + tcp_header_size + redirect_size);
			u_short ipv4_chk, tcp_chk, ipv4_proto;
			u_long tcp_pr_chk;
			int acknowledgement=0, sequence = 0, request_tcp_len = 0;

			memcpy(data_forward, packet, ETH_LEN + ipv4_header_size + tcp_header_size + blocked_size);
			memcpy(data_backward, packet, ETH_LEN + ipv4_header_size + tcp_header_size + blocked_size);

			request_tcp_len = ipv4_total_length - ipv4_header_size, tcp_header_size;

			/* TCP   */
			mstrncpy(&data_forward[ETH_LEN + ipv4_header_size + tcp_header_size], blocked_data, blocked_size);

			/* RST ÷  */
			data_forward[ETH_LEN + ipv4_header_size + TCP_FLAG_OFFSET] = 0b00000100;

			/* IPv4 ü  ȯ */
			ipv4_total_length = ipv4_header_size + tcp_header_size + blocked_size;
			*(u_short*)&data_forward[ETH_LEN + IPV4_SIZE_OFFSET] = mntohs(ipv4_total_length);

			/* IPv4 CHECK SUM 0x00  */
			*(u_short*)&data_forward[ETH_LEN + IPV4_CHKSUM_OFFSET] = 0x0000;

			/* IPv4 CHECK SUM  */
			ipv4_chk = in_cksum((u_short*)&data_forward[ETH_LEN], ipv4_header_size, 0);

			/* IPv4 CHECK SUM  */
			*(u_short*)&data_forward[ETH_LEN + IPV4_CHKSUM_OFFSET] = mntohs(ipv4_chk);

			/* TCP CHECK SUM 0x00  */
			*(u_short*)&data_forward[ETH_LEN + ipv4_header_size + TCP_CHKSUM_OFFSET] = 0x0000;

			/* TCP CHECK SUM  */
			/* 8 is srcip and dstip size */
			tcp_pr_chk = 0;
			tcp_chk = 0;
			ipv4_proto = data_forward[ETH_LEN + IPV4_PROTO_OFFSET];

			tcp_pr_chk += ipv4_proto;
			tcp_pr_chk += ipv4_total_length - ipv4_header_size; //tcp total length
			tcp_chk = in_cksum((u_short*)&data_forward[ETH_LEN + ipv4_header_size - 8], 8 + tcp_header_size + blocked_size, tcp_pr_chk);

			/* TCP CHECK SUM  */
			*(u_short*)&data_forward[ETH_LEN + ipv4_header_size + TCP_CHKSUM_OFFSET] = mntohs(tcp_chk);

			pcap_sendpacket(dev_handle, data_forward, ETH_LEN + ipv4_header_size + tcp_header_size + blocked_size);

			/* TCP   */
			mstrncpy(&data_backward[ETH_LEN + ipv4_header_size + tcp_header_size], redirect_data, redirect_size);

			/* IPv4 dst, src IP  */
			mnswap(&data_backward[ETH_LEN + IPV4_DIP_OFFSET], &data_backward[ETH_LEN + IPV4_SIP_OFFSET], IP_LEN);

			/* TCP port  */
			mnswap(&data_backward[ETH_LEN + ipv4_header_size + TCP_SPORT_OFFSET],
				   &data_backward[ETH_LEN + ipv4_header_size + TCP_DPORT_OFFSET],
				   PORT_LEN);

			/* TCP  ѹ <- -> ACK ѹ  */
			/*  + tcp = ACK ѹ */
			sequence = mntohl(*(u_long*)&data_backward[ETH_LEN + ipv4_header_size + TCP_SEQUENCE_OFFSET]);
			sequence += request_tcp_len;

			acknowledgement = mntohl(*(u_long*)&data_backward[ETH_LEN + ipv4_header_size + TCP_ACKNOWLEDGEMENT_OFFSET]);

			*(u_long*)&data_backward[ETH_LEN + ipv4_header_size + TCP_SEQUENCE_OFFSET] = mntohl(acknowledgement);
			*(u_long*)&data_backward[ETH_LEN + ipv4_header_size + TCP_ACKNOWLEDGEMENT_OFFSET] = mntohl(sequence);

			/* IPv4 ü  ȯ */
			ipv4_total_length = ipv4_header_size + tcp_header_size + redirect_size;
			*(u_short*)&data_backward[ETH_LEN + IPV4_SIZE_OFFSET] = mntohs(ipv4_total_length);

			/* IPv4 CHECK SUM 0x00  */
			*(u_short*)&data_backward[ETH_LEN + IPV4_CHKSUM_OFFSET] = 0x0000;

			/* IPv4 CHECK SUM  */
			ipv4_chk = in_cksum((u_short*)&data_backward[ETH_LEN], ipv4_header_size, 0);

			/* IPv4 CHECK SUM  */
			*(u_short*)&data_backward[ETH_LEN + IPV4_CHKSUM_OFFSET] = mntohs(ipv4_chk);

			/* TCP CHECK SUM 0x00  */
			*(u_short*)&data_backward[ETH_LEN + ipv4_header_size + TCP_CHKSUM_OFFSET] = 0x0000;

			/* TCP CHECK SUM  */
			/* 8 is srcip and dstip size */
			tcp_pr_chk = 0;
			tcp_chk = 0;
			ipv4_proto = data_backward[ETH_LEN + IPV4_PROTO_OFFSET];

			tcp_pr_chk += ipv4_proto;
			tcp_pr_chk += ipv4_total_length - ipv4_header_size; //tcp total length
			tcp_chk = in_cksum((u_short*)&data_backward[ETH_LEN + ipv4_header_size - 8], 8 + tcp_header_size + redirect_size, tcp_pr_chk);

			/* TCP CHECK SUM  */
			*(u_short*)&data_backward[ETH_LEN + ipv4_header_size + TCP_CHKSUM_OFFSET] = mntohs(tcp_chk);

			pcap_sendpacket(dev_handle, data_backward, ETH_LEN + ipv4_header_size + tcp_header_size + redirect_size);
			free(data_forward);
			free(data_backward);
		}

	}
}
void mstrncpy(u_char* target, u_char* source, int num)
{
	memcpy(target, source, num);
}
int data_cmp(const u_char* source1, const u_char* source2, int len)
{
	for (int i = 0; i < len; i++)
		if (source1[i] != source2[i])
			return 1;
	return 0;
}
u_short in_cksum(u_short *addr, int len, long sum)
{
	u_short answer = 0;
	u_short *w = addr;
	register int nleft = len;

	while (nleft > 1) {
		sum += mntohs(*w++);
		nleft -= 2;
	}

	if (nleft == 1) {
		*(u_char *)(&answer) = *(u_char *)w;
		sum += (short)answer * 0x100;
	}
	sum = (sum >> 16) + (sum & 0xffff);
	sum += (sum >> 16);
	answer = (u_short)~sum;

	return(answer);
}
void mncopy(u_char* destination, u_char* source, int len)
{
	for (int i = 0; i < len; i++)
	{
		destination[i] = source[i];
	}
}
void mnswap(u_char* destination, u_char* source, int len)
{
	for (int i = 0; i < len; i++)
	{
		destination[i] ^= source[i];
		source[i] ^= destination[i];
		destination[i] ^= source[i];
	}
}
inline u_long mntohl(u_long l)
{
	u_long d = 0;
	d += (l & 0xFF000000) >> 24;
	d += (l & 0x00FF0000) >> 8;
	d += (l & 0x0000FF00) << 8;
	d += (l & 0x000000FF) << 24;
	return d;
}
inline u_short mntohs(u_short s)
{
	short d = 0;
	d += (s & 0xFF00) >> 8;
	d += (s & 0x00FF) << 8;
	return d;
}<|endoftext|>


<commit_before>#include "oddlib/compressiontype6or7aepsx.hpp"
#include "oddlib/stream.hpp"
#include "logger.hpp"
#include <vector>
#include <cassert>

namespace Oddlib
{
    template<Uint32 BitsSize, typename OutType>
    void NextBits(unsigned int& bitCounter, unsigned int& srcWorkBits, Uint16 *&pSrc1, Uint16 *&pSrcCopy, const signed int kFixedMask, OutType& maskedSrcBits1)
    {
        if (bitCounter < 16)
        {
            const int srcBits = *pSrc1 << bitCounter;
            bitCounter += 16;
            srcWorkBits |= srcBits;
            ++pSrc1;
            pSrcCopy = pSrc1;
        }

        bitCounter -= BitsSize;
        maskedSrcBits1 = static_cast<OutType>(srcWorkBits & (kFixedMask - 1));
        srcWorkBits >>= BitsSize;
    }

    // Function 0x004ABB90 in AE, function 0x8005B09C in AE PSX demo
    template<Uint32 BitsSize>
    std::vector<Uint8> CompressionType6or7AePsx<BitsSize>::Decompress(IStream& stream, Uint32 finalW, Uint32 /*w*/, Uint32 h, Uint32 dataSize)
    {
        std::vector<Uint8> out(finalW*h * 400);
        std::vector<Uint8> in(dataSize);
        stream.ReadBytes(in.data(), in.size());

        Uint16* pInput = (Uint16*)in.data();
        Uint8* pOutput = (Uint8*)out.data();
        int whDWORD = dataSize;

        unsigned int bitCounter = 0; // edx@1
        Uint16 *pSrc1 = 0; // ebp@1
        unsigned int srcWorkBits = 0; // esi@1
        int count = 0; // eax@2
        unsigned int maskedSrcBits1 = 0; // ebx@5
        int remainder = 0; // ebx@6
        int remainderCopy = 0; // ecx@7
        int v14 = 0; // ebx@15
        char v16 = 0; // bl@18
        char bLastByte = 0; // zf@19
        int v19 = 0; // eax@23
        int v23 = 0; // eax@25
        int v24 = 0; // ebx@27
        int v25 = 0; // ebx@28
        int i = 0; // ebp@32
        unsigned char v28 = 0; // cl@33
        Uint16 *pSrcCopy = 0; // [sp+Ch] [bp-31Ch]@1
        int maskedSrcBits1Copy = 0; // [sp+10h] [bp-318h]@5
        int count2 = 0; // [sp+10h] [bp-318h]@11
        int v33 = 0; // [sp+10h] [bp-318h]@25
        signed int kFixedMask = 0; // [sp+14h] [bp-314h]@1
        unsigned int v36 = 0; // [sp+24h] [bp-304h]@1
        char tmp1[256] = {}; // [sp+28h] [bp-300h]@15
        char tmp2[256] = {}; // [sp+128h] [bp-200h]@8
        unsigned char tmp3[256] = {}; // [sp+228h] [bp-100h]@27

        srcWorkBits = 0;
        bitCounter = 0;
        pSrc1 = pInput;
        pSrcCopy = pInput;
        kFixedMask = 1 << BitsSize;                      // could have been the bit depth?
        v36 = ((unsigned int)(1 << BitsSize) >> 1) - 1;
        while (pSrc1 < (Uint16 *)((char *)pInput + ((unsigned int)(BitsSize * whDWORD) >> 3)))// could be the first dword of the frame which is usually the size?
        {
            count = 0;
            do
            {
                NextBits<BitsSize>(bitCounter, srcWorkBits, pSrc1, pSrcCopy, kFixedMask, maskedSrcBits1);

                maskedSrcBits1Copy = maskedSrcBits1;

                if (maskedSrcBits1 > v36)
                {
                    remainder = maskedSrcBits1 - v36;
                    maskedSrcBits1Copy = remainder;
                    if (remainder)
                    {
                        remainderCopy = remainder;
                        do
                        {
                            tmp2[count] = static_cast<char>(count);
                            ++count;
                            --remainder;
                            --remainderCopy;
                        } while (remainderCopy);
                        maskedSrcBits1Copy = remainder;
                    }
                }
                if (count == kFixedMask)
                {
                    break;
                }

                count2 = maskedSrcBits1Copy + 1;
                for (;;)
                {
                    NextBits<BitsSize>(bitCounter, srcWorkBits, pSrc1, pSrcCopy, kFixedMask, v14);
                    *(&tmp1[count] + (tmp2 - tmp1)) = static_cast<char>(v14);
                    if (count != v14)
                    {
                        NextBits<BitsSize>(bitCounter, srcWorkBits, pSrc1, pSrcCopy, kFixedMask, v16);
                        tmp1[count] = static_cast<unsigned char>(v16);
                    }
                    ++count;
                    bLastByte = count2-- == 1;
                    if (bLastByte)
                    {
                        break;
                    }

                    pSrc1 = pSrcCopy; // dead?
                }
                pSrc1 = pSrcCopy; // dead?
            } while (count != kFixedMask);

            NextBits<BitsSize>(bitCounter, srcWorkBits, pSrc1, pSrcCopy, kFixedMask, v19);
            v19 = v19 << BitsSize; // Extra

            NextBits<BitsSize>(bitCounter, srcWorkBits, pSrc1, pSrcCopy, kFixedMask, v33);

            v33 = v33 + v19; // Extra
            v23 = 0;
            for (;;)
            {
                if (v23)
                {
                    --v23;
                    v24 = tmp3[v23];
                    goto LABEL_32;
                }
                v25 = v33--;
                if (!v25)
                {
                    break;
                }

                NextBits<BitsSize>(bitCounter, srcWorkBits, pSrc1, pSrcCopy, kFixedMask, v24);

            LABEL_32:
                for (i = (unsigned char)tmp2[v24]; v24 != i; i = (unsigned char)tmp2[i])
                {
                    v28 = tmp1[v24];
                    v24 = i;
                    tmp3[v23++] = v28;
                }
                pSrc1 = pSrcCopy; // dead?
                *pOutput++ = static_cast<Uint8>(v24);
            }
        }

        return out;

    }

    // Explicit template instantiation
    template class CompressionType6or7AePsx<6>;
    template class CompressionType6or7AePsx<8>;
}
<commit_msg>remove goto<commit_after>#include "oddlib/compressiontype6or7aepsx.hpp"
#include "oddlib/stream.hpp"
#include "logger.hpp"
#include <vector>
#include <cassert>

namespace Oddlib
{
    template<Uint32 BitsSize, typename OutType>
    void NextBits(unsigned int& bitCounter, unsigned int& srcWorkBits, Uint16 *&pSrc1, Uint16 *&pSrcCopy, const signed int kFixedMask, OutType& maskedSrcBits1)
    {
        if (bitCounter < 16)
        {
            const int srcBits = *pSrc1 << bitCounter;
            bitCounter += 16;
            srcWorkBits |= srcBits;
            ++pSrc1;
            pSrcCopy = pSrc1;
        }

        bitCounter -= BitsSize;
        maskedSrcBits1 = static_cast<OutType>(srcWorkBits & (kFixedMask - 1));
        srcWorkBits >>= BitsSize;
    }

    // Function 0x004ABB90 in AE, function 0x8005B09C in AE PSX demo
    template<Uint32 BitsSize>
    std::vector<Uint8> CompressionType6or7AePsx<BitsSize>::Decompress(IStream& stream, Uint32 finalW, Uint32 /*w*/, Uint32 h, Uint32 dataSize)
    {
        std::vector<Uint8> out(finalW*h * 400);
        std::vector<Uint8> in(dataSize);
        stream.ReadBytes(in.data(), in.size());

        Uint16* pInput = (Uint16*)in.data();
        Uint8* pOutput = (Uint8*)out.data();
        int whDWORD = dataSize;

        unsigned int bitCounter = 0; // edx@1
        Uint16 *pSrc1 = 0; // ebp@1
        unsigned int srcWorkBits = 0; // esi@1
        int count = 0; // eax@2
        unsigned int maskedSrcBits1 = 0; // ebx@5
        int remainder = 0; // ebx@6
        int remainderCopy = 0; // ecx@7
        int v14 = 0; // ebx@15
        char v16 = 0; // bl@18
        char bLastByte = 0; // zf@19
        int v19 = 0; // eax@23
        int v23 = 0; // eax@25
        int v24 = 0; // ebx@27
        int v25 = 0; // ebx@28
        int i = 0; // ebp@32
        unsigned char v28 = 0; // cl@33
        Uint16 *pSrcCopy = 0; // [sp+Ch] [bp-31Ch]@1
        int maskedSrcBits1Copy = 0; // [sp+10h] [bp-318h]@5
        int count2 = 0; // [sp+10h] [bp-318h]@11
        int v33 = 0; // [sp+10h] [bp-318h]@25
        signed int kFixedMask = 0; // [sp+14h] [bp-314h]@1
        unsigned int v36 = 0; // [sp+24h] [bp-304h]@1
        char tmp1[256] = {}; // [sp+28h] [bp-300h]@15
        char tmp2[256] = {}; // [sp+128h] [bp-200h]@8
        unsigned char tmp3[256] = {}; // [sp+228h] [bp-100h]@27

        srcWorkBits = 0;
        bitCounter = 0;
        pSrc1 = pInput;
        pSrcCopy = pInput;
        kFixedMask = 1 << BitsSize;                      // could have been the bit depth?
        v36 = ((unsigned int)(1 << BitsSize) >> 1) - 1;
        while (pSrc1 < (Uint16 *)((char *)pInput + ((unsigned int)(BitsSize * whDWORD) >> 3)))// could be the first dword of the frame which is usually the size?
        {
            count = 0;
            do
            {
                NextBits<BitsSize>(bitCounter, srcWorkBits, pSrc1, pSrcCopy, kFixedMask, maskedSrcBits1);

                maskedSrcBits1Copy = maskedSrcBits1;

                if (maskedSrcBits1 > v36)
                {
                    remainder = maskedSrcBits1 - v36;
                    maskedSrcBits1Copy = remainder;
                    if (remainder)
                    {
                        remainderCopy = remainder;
                        do
                        {
                            tmp2[count] = static_cast<char>(count);
                            ++count;
                            --remainder;
                            --remainderCopy;
                        } while (remainderCopy);
                        maskedSrcBits1Copy = remainder;
                    }
                }
                if (count == kFixedMask)
                {
                    break;
                }

                count2 = maskedSrcBits1Copy + 1;
                for (;;)
                {
                    NextBits<BitsSize>(bitCounter, srcWorkBits, pSrc1, pSrcCopy, kFixedMask, v14);
                    *(&tmp1[count] + (tmp2 - tmp1)) = static_cast<char>(v14);
                    if (count != v14)
                    {
                        NextBits<BitsSize>(bitCounter, srcWorkBits, pSrc1, pSrcCopy, kFixedMask, v16);
                        tmp1[count] = static_cast<unsigned char>(v16);
                    }
                    ++count;
                    bLastByte = count2-- == 1;
                    if (bLastByte)
                    {
                        break;
                    }

                    pSrc1 = pSrcCopy; // dead?
                }
                pSrc1 = pSrcCopy; // dead?
            } while (count != kFixedMask);

            NextBits<BitsSize>(bitCounter, srcWorkBits, pSrc1, pSrcCopy, kFixedMask, v19);
            v19 = v19 << BitsSize; // Extra

            NextBits<BitsSize>(bitCounter, srcWorkBits, pSrc1, pSrcCopy, kFixedMask, v33);

            v33 = v33 + v19; // Extra
            v23 = 0;
            for (;;)
            {
                if (v23)
                {
                    --v23;
                    v24 = tmp3[v23];
                }
                else
                {
                    v25 = v33--;
                    if (!v25)
                    {
                        break;
                    }

                    NextBits<BitsSize>(bitCounter, srcWorkBits, pSrc1, pSrcCopy, kFixedMask, v24);
                }

                for (i = (unsigned char)tmp2[v24]; v24 != i; i = (unsigned char)tmp2[i])
                {
                    v28 = tmp1[v24];
                    v24 = i;
                    tmp3[v23++] = v28;
                }
                pSrc1 = pSrcCopy; // dead?
                *pOutput++ = static_cast<Uint8>(v24);
            }
        }

        return out;

    }

    // Explicit template instantiation
    template class CompressionType6or7AePsx<6>;
    template class CompressionType6or7AePsx<8>;
}
<|endoftext|>


<commit_before>#pragma once

// v8
#include <v8.h>

// mapnik
#include <mapnik/font_engine_freetype.hpp>

// stl
#include <vector>

#define TOSTR(obj) (*String::Utf8Value((obj)->ToString()))

using namespace v8;

namespace node_mapnik {

static inline Handle<Value> register_fonts(const Arguments& args)
{
    HandleScope scope;

    try
    {
        if (args.Length() == 0 || !args[0]->IsString())
            return ThrowException(Exception::TypeError(
                                      String::New("first argument must be a path to a directory of fonts")));

        bool found = false;

        std::vector<std::string> const names_before = mapnik::freetype_engine::face_names();

        // option hash
        if (args.Length() == 2){
            if (!args[1]->IsObject())
                return ThrowException(Exception::TypeError(
                                          String::New("second argument is optional, but if provided must be an object, eg. { recurse:Boolean }")));

            Local<Object> options = args[1]->ToObject();
            if (options->Has(String::New("recurse")))
            {
                Local<Value> recurse_opt = options->Get(String::New("recurse"));
                if (!recurse_opt->IsBoolean())
                    return ThrowException(Exception::TypeError(
                                              String::New("'recurse' must be a Boolean")));

                bool recurse = recurse_opt->BooleanValue();
                std::string path = TOSTR(args[0]);
                found = mapnik::freetype_engine::register_fonts(path,recurse);
            }
        }
        else
        {
            std::string path = TOSTR(args[0]);
            found = mapnik::freetype_engine::register_fonts(path);
        }

        std::vector<std::string> const& names_after = mapnik::freetype_engine::face_names();
        if (names_after.size() == names_before.size())
            found = false;

        return scope.Close(Boolean::New(found));
    }
    catch (std::exception const& ex)
    {
        return ThrowException(Exception::Error(
                                  String::New(ex.what())));
    }
}

static inline Handle<Value> available_font_faces(const Arguments& args)
{
    HandleScope scope;
    std::vector<std::string> const& names = mapnik::freetype_engine::face_names();
    Local<Array> a = Array::New(names.size());
    for (unsigned i = 0; i < names.size(); ++i)
    {
        a->Set(i, String::New(names[i].c_str()));
    }
    return scope.Close(a);
}

static inline Handle<Value> available_font_files(const Arguments& args)
{
    HandleScope scope;

    std::map<std::string,std::pair<int,std::string> > const& mapping = mapnik::freetype_engine::get_mapping();
    Local<Object> obj = Object::New();
    std::map<std::string,std::pair<int,std::string> >::const_iterator itr;
    for (itr = mapping.begin();itr!=mapping.end();++itr)
    {
        obj->Set(String::NewSymbol(itr->first.c_str()),String::New(itr->second.second.c_str()));
    }

    return scope.Close(obj);
}

}
<commit_msg>revert node-mapnik/mapnik_fonts.hpp<commit_after>#ifndef __NODE_MAPNIK_FONTS_H__
#define __NODE_MAPNIK_FONTS_H__

// v8
#include <v8.h>

// mapnik
#include <mapnik/font_engine_freetype.hpp>

// stl
#include <vector>

#define TOSTR(obj) (*String::Utf8Value((obj)->ToString()))

using namespace v8;

namespace node_mapnik {

static inline Handle<Value> register_fonts(const Arguments& args)
{
    HandleScope scope;

    try
    {
        if (args.Length() == 0 || !args[0]->IsString())
            return ThrowException(Exception::TypeError(
                                      String::New("first argument must be a path to a directory of fonts")));

        bool found = false;

        std::vector<std::string> const names_before = mapnik::freetype_engine::face_names();

        // option hash
        if (args.Length() == 2){
            if (!args[1]->IsObject())
                return ThrowException(Exception::TypeError(
                                          String::New("second argument is optional, but if provided must be an object, eg. { recurse:Boolean }")));

            Local<Object> options = args[1]->ToObject();
            if (options->Has(String::New("recurse")))
            {
                Local<Value> recurse_opt = options->Get(String::New("recurse"));
                if (!recurse_opt->IsBoolean())
                    return ThrowException(Exception::TypeError(
                                              String::New("'recurse' must be a Boolean")));

                bool recurse = recurse_opt->BooleanValue();
                std::string path = TOSTR(args[0]);
                found = mapnik::freetype_engine::register_fonts(path,recurse);
            }
        }
        else
        {
            std::string path = TOSTR(args[0]);
            found = mapnik::freetype_engine::register_fonts(path);
        }

        std::vector<std::string> const& names_after = mapnik::freetype_engine::face_names();
        if (names_after.size() == names_before.size())
            found = false;

        return scope.Close(Boolean::New(found));
    }
    catch (std::exception const& ex)
    {
        return ThrowException(Exception::Error(
                                  String::New(ex.what())));
    }
}

static inline Handle<Value> available_font_faces(const Arguments& args)
{
    HandleScope scope;
    std::vector<std::string> const& names = mapnik::freetype_engine::face_names();
    Local<Array> a = Array::New(names.size());
    for (unsigned i = 0; i < names.size(); ++i)
    {
        a->Set(i, String::New(names[i].c_str()));
    }
    return scope.Close(a);
}

static inline Handle<Value> available_font_files(const Arguments& args)
{
    HandleScope scope;
    std::map<std::string,std::pair<int,std::string> > const& mapping = mapnik::freetype_engine::get_mapping();
    Local<Object> obj = Object::New();
    std::map<std::string,std::pair<int,std::string> >::const_iterator itr;
    for (itr = mapping.begin();itr!=mapping.end();++itr)
    {
        obj->Set(String::NewSymbol(itr->first.c_str()),String::New(itr->second.second.c_str()));
    }
    return scope.Close(obj);
}

}

#endif // __NODE_MAPNIK_FONTS_H__
<|endoftext|>


<commit_before>/*
 * File:   ServerSettingsPage.cpp
 * Author: danny
 *
 * Created on February 24, 2015, 4:15 PM
 */

#include "ServerSettingsPage.h"
#include "WebMenu.h"
#include "WebForm.h"
#include "Main.h"
#include <Poco/Util/LayeredConfiguration.h>
#include <Poco/Util/Application.h>

const std::string ServerSettingsPage::Link("settings.bin");
const std::string ServerSettingsPage::Title("Server Settings");

ServerSettingsPage::ServerSettingsPage()
{
}

ServerSettingsPage::~ServerSettingsPage()
{
}

std::string ServerSettingsPage::title() const
{
    return Title;
}

std::string ServerSettingsPage::subtitle() const
{
    return "Some wisdom";
}

bool ServerSettingsPage::handleForm(Poco::Net::HTMLForm& form, Poco::Net::HTTPServerRequest& request, Poco::Net::HTTPServerResponse& response)
{
    updateSettings(form, "offline", "ion.offline-interval");
    updateSettings(form, "eventsage", "ion.eventsage");
    if (form.has("linklocal")) {
        Poco::Util::Application::instance().config().setBool("ion.ignoreLinkLocal", true);
    }
    else {
        Poco::Util::Application::instance().config().setBool("ion.ignoreLinkLocal", false);
    }

    Main& main = dynamic_cast<Main&> (Poco::Util::Application::instance());
    main.saveConfig();

    return false;
}

bool ServerSettingsPage::renderFormStart(std::ostream& output)
{
    output << Poco::format("<form method='POST' action='%s' >", Link);
    return true;
}

void ServerSettingsPage::renderButtons(std::ostream& output)
{
    output << "<input class='btn btn-success' type='submit' value='Save'> ";
    WebMenu::renderHomeButton(output, "Close");
}

void ServerSettingsPage::renderPanelBody(std::ostream& output, Poco::Net::HTTPServerRequest& request)
{
    Poco::Util::LayeredConfiguration& config = Poco::Util::Application::instance().config();
    WebForm wf(output);
    wf.startRow();
    wf.renderInput("offline", "Offline interval (minutes):", "minutes", config.getString("ion.offline-interval"), true, "number", 2);
    wf.renderInput("eventsage", "Events age (days):", "days", config.getString("ion.eventsage"), true, "number", 2);
    wf.renderChkbox("linklocal", "Ignore link local addresses:", config.getBool("ion.ignoreLinkLocal"), 2);
    wf.endRow();
}

bool ServerSettingsPage::updateSettings(Poco::Net::HTMLForm& form, const std::string& name, const std::string& confKey)
{
    if (form.has(name)) {
        Poco::Util::Application::instance().config().setString(confKey, form.get(name));
        return true;
    }
    return false;
}
<commit_msg>#17:Change the order of the settings in the "Server Settings" screen<commit_after>/*
 * File:   ServerSettingsPage.cpp
 * Author: danny
 *
 * Created on February 24, 2015, 4:15 PM
 */

#include "ServerSettingsPage.h"
#include "WebMenu.h"
#include "WebForm.h"
#include "Main.h"
#include <Poco/Util/LayeredConfiguration.h>
#include <Poco/Util/Application.h>

const std::string ServerSettingsPage::Link("settings.bin");
const std::string ServerSettingsPage::Title("Server Settings");

ServerSettingsPage::ServerSettingsPage()
{
}

ServerSettingsPage::~ServerSettingsPage()
{
}

std::string ServerSettingsPage::title() const
{
    return Title;
}

std::string ServerSettingsPage::subtitle() const
{
    return "Some wisdom";
}

bool ServerSettingsPage::handleForm(Poco::Net::HTMLForm& form, Poco::Net::HTTPServerRequest& request, Poco::Net::HTTPServerResponse& response)
{
    updateSettings(form, "offline", "ion.offline-interval");
    updateSettings(form, "eventsage", "ion.eventsage");
    if (form.has("linklocal")) {
        Poco::Util::Application::instance().config().setBool("ion.ignoreLinkLocal", true);
    }
    else {
        Poco::Util::Application::instance().config().setBool("ion.ignoreLinkLocal", false);
    }

    Main& main = dynamic_cast<Main&> (Poco::Util::Application::instance());
    main.saveConfig();

    return false;
}

bool ServerSettingsPage::renderFormStart(std::ostream& output)
{
    output << Poco::format("<form method='POST' action='%s' >", Link);
    return true;
}

void ServerSettingsPage::renderButtons(std::ostream& output)
{
    output << "<input class='btn btn-success' type='submit' value='Save'> ";
    WebMenu::renderHomeButton(output, "Close");
}

void ServerSettingsPage::renderPanelBody(std::ostream& output, Poco::Net::HTTPServerRequest& request)
{
    Poco::Util::LayeredConfiguration& config = Poco::Util::Application::instance().config();
    WebForm wf(output);
    wf.startRow();
    wf.renderInput("offline", "Offline interval (minutes):", "minutes", config.getString("ion.offline-interval"), true, "number", 3);
    wf.endRow();
    wf.startRow();
    wf.renderInput("eventsage", "Events age (days):", "days", config.getString("ion.eventsage"), true, "number", 3);
    wf.endRow();
    wf.startRow();
    wf.renderChkbox("linklocal", "Ignore link local addresses:", config.getBool("ion.ignoreLinkLocal"), 3);
    wf.endRow();
}

bool ServerSettingsPage::updateSettings(Poco::Net::HTMLForm& form, const std::string& name, const std::string& confKey)
{
    if (form.has(name)) {
        Poco::Util::Application::instance().config().setString(confKey, form.get(name));
        return true;
    }
    return false;
}
<|endoftext|>


<commit_before>/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*\

______]|]]]]|]__]|]]]]|]__]|]]]]]|]__]|]]]]|]__]|]__]|]__]|]]]]|]_______,_______
_____]|]__]|]__]|]_______]|]___]|]__]|]__]|]___]|]_]|]__]|]__]|]_______, ,______
____]|]__]|]__]|]]]]|]__]|]]]]]|]__]|]__]|]____]|]]|]__]|]__]|]_______,   ,_____
___]|]____________]|]__]|]________]|]__________]|]|]__]|]____________, -R- ,____
__]|]____________]|]__]|]________]|]___________]||]__]|]____________,   |   ,___
_]|]_______]|]]]]|]__]|]]]]]|]__]|]____________]|]__]|]____________, , , , , ,__
                                                                      ||  |
\*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/

/* This software is released under the BSD License.
 |
 | Copyright (c) 2011, Kevin P. Barry [the resourcerver project]
 | 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  Resourcerver  Project  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.
 +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/

/*! \file rservr/api/event-functor.hpp
 *  \author Kevin P. Barry
 *  \brief Functor implementation of command-queue callbacks.
 */

#ifndef event_functor_hpp
#define event_functor_hpp

extern "C" {
#include "command-queue.h"
}

#include <vector>

struct event_functor;
struct auto_event_functor;

template <class> struct template_event_functor;
template <class, typename> struct member_event_functor;

typedef std::vector <auto_event_functor> event_functor_list;

extern "C" {
/*! \brief Send a command with a callback functor.
 *
 * Send a command from the command queue with a callback functor to be called
 * when the command's status is updated.
 * \note Allocates a command status object.
 * @see clear_command_status
 * @see destroy_command
 * @see send_command_callback
 * @see encapsulate_callback
 * @see encapsulate_functor
 *
 * \param Command handle for a queued command
 * \param Functor callback functor to be called upon status update
 * \return reference of the sent command
 */
extern command_reference send_command_functor(command_handle Command,
  struct event_functor *Functor);
}

/*! \brief Send a command with callback functors.
 *
 * \note Allocates a command status object.
 * @see clear_command_status
 * @see destroy_command
 * @see send_command_functor
 * @see send_command_callback
 * @see encapsulate_callback
 * @see encapsulate_functor
 *
 * \param Command handle for a queued command
 * \param Functors callback functors to be called upon status update
 * \return reference of the sent command
 */
extern command_reference send_command_functors(command_handle Command,
  const event_functor_list &Functors);

extern "C" {
/*! \brief Add a status callback functor.
 *
 * Add a command status callback functor to an already-sent command's status
 * object.
 * @see send_command_functor
 *
 * \param Reference reference of the sent command
 * \param Functor callback functor to be called upon status update
 * \return success (true) or failure (false)
 */
extern result new_status_functor(command_reference Reference,
  struct event_functor *Functor);
}

/*! \brief Add status callback functors.
 *
 * @see send_command_functors
 *
 * \param Reference reference of the sent command
 * \param Functors callback functors to be called upon status update
 * \return success (true) or failure (false)
 */
extern result new_status_functors(command_reference Reference,
  const event_functor_list &Functors);

/*! \brief Create a functor from a function.
 *
 * Encapsulate a non-member function pointer as an event_functor.
 *
 * \param Callback pointer to the callback function
 * \return dynamically-allocated event_functor
 */
template <class Type> inline event_functor *encapsulate_callback(const Type &Callback)
{ return new template_event_functor <Type> (Callback); }

/*! \brief Create a functor from an object.
 *
 * Encapsulate an object and member function as an event_functor.
 *
 * \param Functor object to call a function against (copied)
 * \param Function pointer to a member function
 * \return dynamically-allocated event_functor
 */
template <class Type, typename Member> inline event_functor
  *encapsulate_functor(const Type &Functor, Member Type:: *Function)
{ return new member_event_functor <Type, Member> (Functor, Function); }

/*! \brief Create a functor from a pointer.
 *
 * Encapsulate a pointer and member function as an event_functor.
 *
 * \param Functor pointer to an object to call a function against
 * \param Function pointer to a member function
 * \return dynamically-allocated event_functor
 */
template <class Type, typename Member> inline event_functor
  *encapsulate_functor(Type *Functor, Member Type:: *Function)
{ return new member_event_functor <Type*, Member> (Functor, Function); }

struct event_functor
{
	virtual result operator () (command_reference Reference, command_event Event,
	  command_event Cumulative, const struct command_info *Info) = 0;

	virtual event_functor *copy() const = 0;
};

class auto_event_functor :
	public event_functor
{
public:
	inline auto_event_functor(event_functor *fFunctor = NULL) : functor(fFunctor) {}

	inline auto_event_functor(event_functor &eEqual) : functor(eEqual.copy()) {}

	inline auto_event_functor &operator = (event_functor &eEqual)
	{
	if (&eEqual == this) return *this;
	event_functor *old_functor = functor;
	functor = NULL;
	delete old_functor;
	functor = eEqual.copy();
	return *this;
	}

	inline result operator () (command_reference rReference, command_event eEvent,
	  command_event cCumulative, const struct command_info *iInfo)
	{ return functor? (*functor)(rReference, eEvent, cCumulative, iInfo) : true; }

	inline event_functor *copy() const
	{ return functor? functor->copy() : NULL; }

private:
	event_functor *functor;
};

template <class Type>
class template_event_functor :
	public event_functor
{
public:
	template_event_functor(const Type &fFunctor) : functor(fFunctor) {}

	inline result operator () (command_reference rReference, command_event eEvent,
	  command_event cCumulative, const struct command_info *iInfo)
	{ return functor(rReference, eEvent, cCumulative, iInfo); }

	inline event_functor *copy() const
	{ return new template_event_functor <Type> (*this); }

private:
	Type functor;
};

template <class Type>
class template_event_functor <Type*> :
	public event_functor
{
public:
	template_event_functor(const Type *fFunctor) : functor(fFunctor) {}

	inline result operator () (command_reference rReference, command_event eEvent,
	  command_event cCumulative, const struct command_info *iInfo)
	{ return functor? (*functor)(rReference, eEvent, cCumulative, iInfo) : true; }

	inline event_functor *copy() const
	{ return new template_event_functor <Type*> (*this); }

private:
	Type *functor;
};

template <class Type, typename Member>
class member_event_functor :
	public event_functor
{
public:
	member_event_functor(const Type &fFunctor, Member Type:: *fFunction) :
	functor(fFunctor), member(fFunction) {}

	inline result operator () (command_reference rReference, command_event eEvent,
	  command_event cCumulative, const struct command_info *iInfo)
	{ return (functor.*member)(rReference, eEvent, cCumulative, iInfo); }

	inline member_event_functor *copy() const
	{ return new member_event_functor <Type, Member> (*this); }

private:
	Type           functor;
	Member Type:: *member;
};

template <class Type, typename Member>
class member_event_functor <Type*, Member> :
	public event_functor
{
public:
	member_event_functor(Type *fFunctor, Member Type:: *fFunction) :
	functor(fFunctor), member(fFunction) {}

	inline result operator () (command_reference rReference, command_event eEvent,
	  command_event cCumulative, const struct command_info *iInfo)
	{ return functor? (functor->*member)(rReference, eEvent, cCumulative, iInfo) : true; }

	inline member_event_functor *copy() const
	{ return new member_event_functor <Type*, Member> (*this); }

private:
	Type          *functor;
	Member Type:: *member;
};

#endif //event_functor_hpp
<commit_msg>gamma.8 - fixed memory leak introduced by callback functors<commit_after>/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*\

______]|]]]]|]__]|]]]]|]__]|]]]]]|]__]|]]]]|]__]|]__]|]__]|]]]]|]_______,_______
_____]|]__]|]__]|]_______]|]___]|]__]|]__]|]___]|]_]|]__]|]__]|]_______, ,______
____]|]__]|]__]|]]]]|]__]|]]]]]|]__]|]__]|]____]|]]|]__]|]__]|]_______,   ,_____
___]|]____________]|]__]|]________]|]__________]|]|]__]|]____________, -R- ,____
__]|]____________]|]__]|]________]|]___________]||]__]|]____________,   |   ,___
_]|]_______]|]]]]|]__]|]]]]]|]__]|]____________]|]__]|]____________, , , , , ,__
                                                                      ||  |
\*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/

/* This software is released under the BSD License.
 |
 | Copyright (c) 2011, Kevin P. Barry [the resourcerver project]
 | 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  Resourcerver  Project  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.
 +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/

/*! \file rservr/api/event-functor.hpp
 *  \author Kevin P. Barry
 *  \brief Functor implementation of command-queue callbacks.
 */

#ifndef event_functor_hpp
#define event_functor_hpp

extern "C" {
#include "command-queue.h"
}

#include <vector>

struct event_functor;
struct auto_event_functor;

template <class> struct template_event_functor;
template <class, typename> struct member_event_functor;

typedef std::vector <auto_event_functor> event_functor_list;

extern "C" {
/*! \brief Send a command with a callback functor.
 *
 * Send a command from the command queue with a callback functor to be called
 * when the command's status is updated.
 * \note Allocates a command status object.
 * @see clear_command_status
 * @see destroy_command
 * @see send_command_callback
 * @see encapsulate_callback
 * @see encapsulate_functor
 *
 * \param Command handle for a queued command
 * \param Functor callback functor to be called upon status update
 * \return reference of the sent command
 */
extern command_reference send_command_functor(command_handle Command,
  struct event_functor *Functor);
}

/*! \brief Send a command with callback functors.
 *
 * \note Allocates a command status object.
 * @see clear_command_status
 * @see destroy_command
 * @see send_command_functor
 * @see send_command_callback
 * @see encapsulate_callback
 * @see encapsulate_functor
 *
 * \param Command handle for a queued command
 * \param Functors callback functors to be called upon status update
 * \return reference of the sent command
 */
extern command_reference send_command_functors(command_handle Command,
  const event_functor_list &Functors);

extern "C" {
/*! \brief Add a status callback functor.
 *
 * Add a command status callback functor to an already-sent command's status
 * object.
 * @see send_command_functor
 *
 * \param Reference reference of the sent command
 * \param Functor callback functor to be called upon status update
 * \return success (true) or failure (false)
 */
extern result new_status_functor(command_reference Reference,
  struct event_functor *Functor);
}

/*! \brief Add status callback functors.
 *
 * @see send_command_functors
 *
 * \param Reference reference of the sent command
 * \param Functors callback functors to be called upon status update
 * \return success (true) or failure (false)
 */
extern result new_status_functors(command_reference Reference,
  const event_functor_list &Functors);

/*! \brief Create a functor from a function.
 *
 * Encapsulate a non-member function pointer as an event_functor.
 *
 * \param Callback pointer to the callback function
 * \return dynamically-allocated event_functor
 */
template <class Type> inline event_functor *encapsulate_callback(const Type &Callback)
{ return new template_event_functor <Type> (Callback); }

/*! \brief Create a functor from an object.
 *
 * Encapsulate an object and member function as an event_functor.
 *
 * \param Functor object to call a function against (copied)
 * \param Function pointer to a member function
 * \return dynamically-allocated event_functor
 */
template <class Type, typename Member> inline event_functor
  *encapsulate_functor(const Type &Functor, Member Type:: *Function)
{ return new member_event_functor <Type, Member> (Functor, Function); }

/*! \brief Create a functor from a pointer.
 *
 * Encapsulate a pointer and member function as an event_functor.
 *
 * \param Functor pointer to an object to call a function against
 * \param Function pointer to a member function
 * \return dynamically-allocated event_functor
 */
template <class Type, typename Member> inline event_functor
  *encapsulate_functor(Type *Functor, Member Type:: *Function)
{ return new member_event_functor <Type*, Member> (Functor, Function); }

struct event_functor
{
	virtual result operator () (command_reference Reference, command_event Event,
	  command_event Cumulative, const struct command_info *Info) = 0;

	virtual event_functor *copy() const = 0;
};

class auto_event_functor :
	public event_functor
{
public:
	inline auto_event_functor(event_functor *fFunctor = NULL) : functor(fFunctor) {}

	inline auto_event_functor(event_functor &eEqual) : functor(eEqual.copy()) {}

	inline auto_event_functor &operator = (event_functor &eEqual)
	{
	if (&eEqual == this) return *this;
	event_functor *old_functor = functor;
	functor = NULL;
	delete old_functor;
	functor = eEqual.copy();
	return *this;
	}

	inline result operator () (command_reference rReference, command_event eEvent,
	  command_event cCumulative, const struct command_info *iInfo)
	{ return functor? (*functor)(rReference, eEvent, cCumulative, iInfo) : true; }

	inline event_functor *copy() const
	{ return functor? functor->copy() : NULL; }

	~auto_event_functor()
	{
	event_functor *old_functor = functor;
	functor = NULL;
	delete old_functor;
	}

private:
	event_functor *functor;
};

template <class Type>
class template_event_functor :
	public event_functor
{
public:
	template_event_functor(const Type &fFunctor) : functor(fFunctor) {}

	inline result operator () (command_reference rReference, command_event eEvent,
	  command_event cCumulative, const struct command_info *iInfo)
	{ return functor(rReference, eEvent, cCumulative, iInfo); }

	inline event_functor *copy() const
	{ return new template_event_functor <Type> (*this); }

private:
	Type functor;
};

template <class Type>
class template_event_functor <Type*> :
	public event_functor
{
public:
	template_event_functor(const Type *fFunctor) : functor(fFunctor) {}

	inline result operator () (command_reference rReference, command_event eEvent,
	  command_event cCumulative, const struct command_info *iInfo)
	{ return functor? (*functor)(rReference, eEvent, cCumulative, iInfo) : true; }

	inline event_functor *copy() const
	{ return new template_event_functor <Type*> (*this); }

private:
	Type *functor;
};

template <class Type, typename Member>
class member_event_functor :
	public event_functor
{
public:
	member_event_functor(const Type &fFunctor, Member Type:: *fFunction) :
	functor(fFunctor), member(fFunction) {}

	inline result operator () (command_reference rReference, command_event eEvent,
	  command_event cCumulative, const struct command_info *iInfo)
	{ return (functor.*member)(rReference, eEvent, cCumulative, iInfo); }

	inline member_event_functor *copy() const
	{ return new member_event_functor <Type, Member> (*this); }

private:
	Type           functor;
	Member Type:: *member;
};

template <class Type, typename Member>
class member_event_functor <Type*, Member> :
	public event_functor
{
public:
	member_event_functor(Type *fFunctor, Member Type:: *fFunction) :
	functor(fFunctor), member(fFunction) {}

	inline result operator () (command_reference rReference, command_event eEvent,
	  command_event cCumulative, const struct command_info *iInfo)
	{ return functor? (functor->*member)(rReference, eEvent, cCumulative, iInfo) : true; }

	inline member_event_functor *copy() const
	{ return new member_event_functor <Type*, Member> (*this); }

private:
	Type          *functor;
	Member Type:: *member;
};

#endif //event_functor_hpp
<|endoftext|>


<commit_before>#if !defined(SYSSTATD_REQUEST_HANDLER_HPP_INCLUDED)
#define SYSSTATD_REQUEST_HANDLER_HPP_INCLUDED

#include <asio_http/http_server.hpp>

struct request_handler
{
	typedef basic_http_connection<request_handler> connection_type;
	void operator()(const connection_type::pointer & ptr);
};

#endif<commit_msg>Fixed Linux build.<commit_after>#if !defined(SYSSTATD_REQUEST_HANDLER_HPP_INCLUDED)
#define SYSSTATD_REQUEST_HANDLER_HPP_INCLUDED

#include <iostream>
#include <asio_http/http_server.hpp>

struct request_handler
{
	typedef basic_http_connection<request_handler> connection_type;
	void operator()(const connection_type::pointer & ptr);
};

#endif<|endoftext|>


<commit_before>// Copyright (c) 2014 Romuald Perrot, Pierre Moulon, Chris Sweeney.

// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

#ifndef OPENMVG_IMAGE_IMAGE_CONVOLUTION_HPP_
#define OPENMVG_IMAGE_IMAGE_CONVOLUTION_HPP_

#include "openMVG/numeric/accumulator_trait.hpp"

/**
 ** @file Standard 2D image convolution functions :
 ** - vertical
 ** - horizontal
 ** - 2D (using standard 2d kernel of with separable kernels)
 **/

namespace openMVG
{
/**
 ** General image convolution by a kernel
 ** assume kernel has odd size in both dimensions and (border pixel are copied)
 ** @param img source image
 ** @param kernel convolution kernel
 ** @param out resulting image
 **/
template< typename Image >
void ImageConvolution( const Image & img , const Mat & kernel , Image & out)
{
  const int kernel_width  = kernel.cols() ;
  const int kernel_height = kernel.rows() ;

  assert( kernel_width % 2 != 0 && kernel_height % 2 != 0 ) ;

  typedef typename Image::Tpixel pix_t ;
  typedef typename Accumulator< pix_t >::Type acc_pix_t ;

  out.resize( img.Width() , img.Height() ) ;

  for( int row = 0 ; row < img.rows() ; ++row )
  {
    for( int col = 0 ; col < img.cols() ; ++col )
    {
      acc_pix_t sum = acc_pix_t( ) ;

      for( int i = 0 ; i < kernel_height ; ++i )
      {
        for( int j = 0 ; j < kernel_width ; ++j )
        {
          int idy = row + i - kernel_height / 2 ;
          int idx = col + j - kernel_width / 2 ;

          // Get correct value
          idx = idx < 0 ? 0 : ( idx >= img.cols() ? img.cols() - 1 : idx ) ;
          idy = idy < 0 ? 0 : ( idy >= img.rows() ? img.rows() - 1 : idy ) ;

          sum += kernel( i , j ) * img( idy , idx ) ;
        }
      }
      out( row , col ) = sum ;
    }
  }
}

/**
 ** Horizontal (1d) convolution
 ** assume kernel has odd size
 ** @param img Input image
 ** @param kernel convolution kernel
 ** @param out Output image
 **/
template< typename ImageTypeIn , typename ImageTypeOut, typename Kernel >
static void ImageHorizontalConvolution( const ImageTypeIn & img , const Kernel & kernel , ImageTypeOut & out)
{
  typedef typename ImageTypeIn::Tpixel pix_t ;

  const int rows ( img.rows() );
  const int cols ( img.cols() );

  out.resize( cols , rows ) ;

  const int kernel_width = kernel.size() ;
  const int half_kernel_width = kernel_width / 2 ;

  std::vector<pix_t, Eigen::aligned_allocator<pix_t> > line( cols + kernel_width );

  for( int row = 0 ; row < rows ; ++row )
  {
    // Copy line
    const pix_t start_pix = img.coeffRef( row , 0 ) ;
    for( int k = 0 ; k < half_kernel_width ; ++k ) // pad before
    {
      line[ k ] = start_pix ;
    }
    memcpy(&line[0] + half_kernel_width, img.data() + row * cols, sizeof(pix_t) * cols);
    const pix_t end_pix = img.coeffRef( row , cols - 1 ) ;
    for( int k = 0 ; k < half_kernel_width ; ++k ) // pad after
    {
      line[ k + half_kernel_width + cols ] = end_pix ;
    }

    // Apply convolution
    conv_buffer_( &line[0] , kernel.data() , cols , kernel_width );

    memcpy(out.data() + row * cols, &line[0], sizeof(pix_t) * cols);
  }
}

/**
 ** Vertical (1d) convolution
 ** assume kernel has odd size
 ** @param img Input image
 ** @param kernel convolution kernel
 ** @param out Output image
 **/
template< typename ImageTypeIn , typename ImageTypeOut, typename Kernel >
void ImageVerticalConvolution( const ImageTypeIn & img , const Kernel & kernel , ImageTypeOut & out)
{
  typedef typename ImageTypeIn::Tpixel pix_t ;

  const int kernel_width = kernel.size() ;
  const int half_kernel_width = kernel_width / 2 ;

  const int rows = img.rows() ;
  const int cols = img.cols() ;

  out.resize( cols , rows ) ;

  std::vector<pix_t, Eigen::aligned_allocator<pix_t> > line( rows + kernel_width );

  for( int col = 0 ; col < cols ; ++col )
  {
    // Copy column
    for( int k = 0 ; k < half_kernel_width ; ++k )
    {
      line[ k ] = img.coeffRef( 0 , col ) ;
    }
    for( int k = 0 ; k < rows ; ++k )
    {
      line[ k + half_kernel_width ] = img.coeffRef( k , col ) ;
    }
    for( int k = 0 ; k < half_kernel_width ; ++k )
    {
      line[ k + half_kernel_width + rows ] = img.coeffRef( rows - 1 , col ) ;
    }

    // Apply convolution
    conv_buffer_( &line[0] , kernel.data() , rows , kernel_width );

    for( int row = 0 ; row < rows ; ++row )
    {
      out.coeffRef( row , col ) = line[row];
    }
  }
}

/**
 ** Separable 2D convolution
 ** (nxm kernel is replaced by two 1D convolution of (size n then size m) )
 ** @param img source image
 ** @param horiz_k horizontal kernel
 ** @param vert_k vertical kernel
 ** @param out output image
 **/
template< typename ImageType, typename Kernel >
void ImageSeparableConvolution( const ImageType & img ,
                                const Kernel & horiz_k ,
                                const Kernel & vert_k ,
                                ImageType & out)
{
  // Cast the Kernel to the appropriate type
  typedef typename ImageType::Tpixel pix_t;
  typedef Eigen::Matrix<typename Accumulator<pix_t>::Type, Eigen::Dynamic, 1> VecKernel;
  const VecKernel horiz_k_cast = horiz_k.template cast< typename Accumulator<pix_t>::Type >();
  const VecKernel vert_k_cast = vert_k.template cast< typename Accumulator<pix_t>::Type >();

  ImageType tmp ;
  ImageHorizontalConvolution( img , horiz_k_cast , tmp ) ;
  ImageVerticalConvolution( tmp , vert_k_cast , out ) ;
}

typedef Eigen::Matrix<float, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor> RowMatrixXf;

/// Specialization for Float based image (for a fixed sized convolution)
template <int sigma>
void SeparableConvolution2d(const RowMatrixXf& image,
                            const Eigen::Matrix<float, 1, sigma>& kernel_x,
                            const Eigen::Matrix<float, 1, sigma>& kernel_y,
                            RowMatrixXf* out) {
  const int half_sigma = sigma / 2;

  // Convolving a vertical filter across rows is the same thing as transpose
  // multiply i.e. kernel_y^t * rows. This will give us the convoled value for
  // each row. However, care must be taken at the top and bottom borders.
  const Eigen::Matrix<float, 1, sigma> reverse_kernel_y = kernel_y.reverse();
#ifdef USE_OPENMP
#pragma omp parallel for
#endif
  for (int i = 0; i < half_sigma; i++) {
    const int forward_size = i + half_sigma + 1;
    const int reverse_size = sigma - forward_size;
    out->row(i) = kernel_y.tail(forward_size) *
                  image.block(0, 0, forward_size, image.cols()) +
                  reverse_kernel_y.tail(reverse_size) *
                  image.block(1, 0, reverse_size, image.cols());

    // Apply the same technique for the end rows.
    out->row(image.rows() - i - 1) =
      kernel_y.head(forward_size) *
      image.block(image.rows() - forward_size, 0, forward_size, image.cols())
      +
      reverse_kernel_y.head(reverse_size) *
      image.block(image.rows() - reverse_size - 1, 0, reverse_size, image.cols());
  }

  // Applying the rest of the y filter.
#ifdef USE_OPENMP
#pragma omp parallel for
#endif
  for (int row = half_sigma; row < image.rows() - half_sigma; row++) {
    out->row(row) =  kernel_y * image.block(row - half_sigma, 0, sigma, out->cols());
  }

  // Convolving with the horizontal filter is easy. Rather than using the kernel
  // as a sliding indow, we use the row pixels as a sliding window around the
  // filter. We prepend and append the proper border values so that we are sure
  // to end up with the correct convolved values.
  Eigen::RowVectorXf temp_row(image.cols() + sigma - 1);
#ifdef USE_OPENMP
#pragma omp parallel for firstprivate(temp_row)
#endif
  for (int row = 0; row < out->rows(); row++) {
    temp_row.head<half_sigma>() =
      out->row(row).segment(1, half_sigma).reverse();
    temp_row.segment(half_sigma, image.cols()) = out->row(row);
    temp_row.tail<half_sigma>() =
      out->row(row)
      .segment(image.cols() - 2 - half_sigma, half_sigma)
      .reverse();

    // Convolve the row. We perform the first step here explicitly so that we
    // avoid setting the row equal to zero.
    out->row(row) = kernel_x(0) * temp_row.head(image.cols());
    for (int i = 1; i < sigma; i++) {
      out->row(row) += kernel_x(i) * temp_row.segment(i, image.cols());
    }
  }
}

/// Specialization for Float based image (for arbitrary sized kernel)
static void SeparableConvolution2d(const RowMatrixXf& image,
                            const Eigen::Matrix<float, 1, Eigen::Dynamic>& kernel_x,
                            const Eigen::Matrix<float, 1, Eigen::Dynamic>& kernel_y,
                            RowMatrixXf* out) {
  const int sigma_y = kernel_y.cols();
  const int half_sigma_y = kernel_y.cols() / 2;

  // Convolving a vertical filter across rows is the same thing as transpose
  // multiply i.e. kernel_y^t * rows. This will give us the convoled value for
  // each row. However, care must be taken at the top and bottom borders.
  const Eigen::Matrix<float, 1, Eigen::Dynamic> reverse_kernel_y = kernel_y.reverse();
#if defined(USE_OPENMP)
#pragma omp parallel for
#endif
  for (int i = 0; i < half_sigma_y; i++) {
    const int forward_size = i + half_sigma_y + 1;
    const int reverse_size = sigma_y - forward_size;
    out->row(i) = kernel_y.tail(forward_size) *
                  image.block(0, 0, forward_size, image.cols()) +
                  reverse_kernel_y.tail(reverse_size) *
                  image.block(1, 0, reverse_size, image.cols());

    // Apply the same technique for the end rows.
    out->row(image.rows() - i - 1) =
      kernel_y.head(forward_size) *
      image.block(image.rows() - forward_size, 0, forward_size, image.cols())
      +
      reverse_kernel_y.head(reverse_size) *
      image.block(image.rows() - reverse_size - 1, 0, reverse_size, image.cols());
  }

  // Applying the rest of the y filter.
#if defined(USE_OPENMP)
#pragma omp parallel for
#endif
  for (int row = half_sigma_y; row < image.rows() - half_sigma_y; row++) {
    out->row(row) =  kernel_y * image.block(row - half_sigma_y, 0, sigma_y, out->cols());
  }

  const int sigma_x = kernel_x.cols();
  const int half_sigma_x = kernel_x.cols() / 2;

  // Convolving with the horizontal filter is easy. Rather than using the kernel
  // as a sliding indow, we use the row pixels as a sliding window around the
  // filter. We prepend and append the proper border values so that we are sure
  // to end up with the correct convolved values.
  Eigen::RowVectorXf temp_row(image.cols() + sigma_x - 1);
#if defined(USE_OPENMP)
#pragma omp parallel for firstprivate(temp_row)
#endif
  for (int row = 0; row < out->rows(); row++) {
    temp_row.head(half_sigma_x) =
      out->row(row).segment(1, half_sigma_x).reverse();
    temp_row.segment(half_sigma_x, image.cols()) = out->row(row);
    temp_row.tail(half_sigma_x) =
      out->row(row)
      .segment(image.cols() - 2 - half_sigma_x, half_sigma_x)
      .reverse();

    // Convolve the row. We perform the first step here explicitly so that we
    // avoid setting the row equal to zero.
    out->row(row) = kernel_x(0) * temp_row.head(image.cols());
    for (int i = 1; i < sigma_x; i++) {
      out->row(row) += kernel_x(i) * temp_row.segment(i, image.cols());
    }
  }
}

// Specialization for Image<float> in order to use SeparableConvolution2d
template<typename Kernel>
void ImageSeparableConvolution( const Image<float> & img ,
                                const Kernel & horiz_k ,
                                const Kernel & vert_k ,
                                Image<float> & out)
{
  // Cast the Kernel to the appropriate type
  typedef Image<float>::Tpixel pix_t;
  typedef Eigen::Matrix<typename Accumulator<pix_t>::Type, Eigen::Dynamic, 1> VecKernel;
  const VecKernel horiz_k_cast = horiz_k.template cast< typename Accumulator<pix_t>::Type >();
  const VecKernel vert_k_cast = vert_k.template cast< typename Accumulator<pix_t>::Type >();

  out.resize(img.Width(), img.Height());
  if (horiz_k_cast.rows() == vert_k_cast.rows())
  {
    switch(horiz_k_cast.rows()) {
    case 3:
      SeparableConvolution2d<3>(img.GetMat(), horiz_k_cast, vert_k_cast, &((Image<float>::Base&)out));
      break;
    case 5:
      SeparableConvolution2d<5>(img.GetMat(), horiz_k_cast, vert_k_cast, &((Image<float>::Base&)out));
      break;
    case 7:
      SeparableConvolution2d<7>(img.GetMat(), horiz_k_cast, vert_k_cast, &((Image<float>::Base&)out));
      break;
    case 9:
      SeparableConvolution2d<9>(img.GetMat(), horiz_k_cast, vert_k_cast, &((Image<float>::Base&)out));
      break;
    case 11:
      SeparableConvolution2d<11>(img.GetMat(), horiz_k_cast, vert_k_cast, &((Image<float>::Base&)out));
      break;
    default:
      SeparableConvolution2d(img.GetMat(), horiz_k_cast, vert_k_cast, &((Image<float>::Base&)out));
    }
  }
  else
  {
    Image<float> tmp ;
    ImageHorizontalConvolution( img , horiz_k_cast , tmp ) ;
    ImageVerticalConvolution( tmp , vert_k_cast , out ) ;
  }
}

} // namespace openMVG

#endif // OPENMVG_IMAGE_IMAGE_CONVOLUTION_HPP_

<commit_msg>Use only dynamic optimized separable convolution. Fixed size do not make it faster. Calling tree is simplified. #197<commit_after>// Copyright (c) 2014 Romuald Perrot, Pierre Moulon, Chris Sweeney.

// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

#ifndef OPENMVG_IMAGE_IMAGE_CONVOLUTION_HPP_
#define OPENMVG_IMAGE_IMAGE_CONVOLUTION_HPP_

#include "openMVG/numeric/accumulator_trait.hpp"

/**
 ** @file Standard 2D image convolution functions :
 ** - vertical
 ** - horizontal
 ** - 2D (using standard 2d kernel of with separable kernels)
 **/

namespace openMVG
{
/**
 ** General image convolution by a kernel
 ** assume kernel has odd size in both dimensions and (border pixel are copied)
 ** @param img source image
 ** @param kernel convolution kernel
 ** @param out resulting image
 **/
template< typename Image >
void ImageConvolution( const Image & img , const Mat & kernel , Image & out)
{
  const int kernel_width  = kernel.cols() ;
  const int kernel_height = kernel.rows() ;

  assert( kernel_width % 2 != 0 && kernel_height % 2 != 0 ) ;

  typedef typename Image::Tpixel pix_t ;
  typedef typename Accumulator< pix_t >::Type acc_pix_t ;

  out.resize( img.Width() , img.Height() ) ;

  for( int row = 0 ; row < img.rows() ; ++row )
  {
    for( int col = 0 ; col < img.cols() ; ++col )
    {
      acc_pix_t sum = acc_pix_t( ) ;

      for( int i = 0 ; i < kernel_height ; ++i )
      {
        for( int j = 0 ; j < kernel_width ; ++j )
        {
          int idy = row + i - kernel_height / 2 ;
          int idx = col + j - kernel_width / 2 ;

          // Get correct value
          idx = idx < 0 ? 0 : ( idx >= img.cols() ? img.cols() - 1 : idx ) ;
          idy = idy < 0 ? 0 : ( idy >= img.rows() ? img.rows() - 1 : idy ) ;

          sum += kernel( i , j ) * img( idy , idx ) ;
        }
      }
      out( row , col ) = sum ;
    }
  }
}

/**
 ** Horizontal (1d) convolution
 ** assume kernel has odd size
 ** @param img Input image
 ** @param kernel convolution kernel
 ** @param out Output image
 **/
template< typename ImageTypeIn , typename ImageTypeOut, typename Kernel >
static void ImageHorizontalConvolution( const ImageTypeIn & img , const Kernel & kernel , ImageTypeOut & out)
{
  typedef typename ImageTypeIn::Tpixel pix_t ;

  const int rows ( img.rows() );
  const int cols ( img.cols() );

  out.resize( cols , rows ) ;

  const int kernel_width = kernel.size() ;
  const int half_kernel_width = kernel_width / 2 ;

  std::vector<pix_t, Eigen::aligned_allocator<pix_t> > line( cols + kernel_width );

  for( int row = 0 ; row < rows ; ++row )
  {
    // Copy line
    const pix_t start_pix = img.coeffRef( row , 0 ) ;
    for( int k = 0 ; k < half_kernel_width ; ++k ) // pad before
    {
      line[ k ] = start_pix ;
    }
    memcpy(&line[0] + half_kernel_width, img.data() + row * cols, sizeof(pix_t) * cols);
    const pix_t end_pix = img.coeffRef( row , cols - 1 ) ;
    for( int k = 0 ; k < half_kernel_width ; ++k ) // pad after
    {
      line[ k + half_kernel_width + cols ] = end_pix ;
    }

    // Apply convolution
    conv_buffer_( &line[0] , kernel.data() , cols , kernel_width );

    memcpy(out.data() + row * cols, &line[0], sizeof(pix_t) * cols);
  }
}

/**
 ** Vertical (1d) convolution
 ** assume kernel has odd size
 ** @param img Input image
 ** @param kernel convolution kernel
 ** @param out Output image
 **/
template< typename ImageTypeIn , typename ImageTypeOut, typename Kernel >
void ImageVerticalConvolution( const ImageTypeIn & img , const Kernel & kernel , ImageTypeOut & out)
{
  typedef typename ImageTypeIn::Tpixel pix_t ;

  const int kernel_width = kernel.size() ;
  const int half_kernel_width = kernel_width / 2 ;

  const int rows = img.rows() ;
  const int cols = img.cols() ;

  out.resize( cols , rows ) ;

  std::vector<pix_t, Eigen::aligned_allocator<pix_t> > line( rows + kernel_width );

  for( int col = 0 ; col < cols ; ++col )
  {
    // Copy column
    for( int k = 0 ; k < half_kernel_width ; ++k )
    {
      line[ k ] = img.coeffRef( 0 , col ) ;
    }
    for( int k = 0 ; k < rows ; ++k )
    {
      line[ k + half_kernel_width ] = img.coeffRef( k , col ) ;
    }
    for( int k = 0 ; k < half_kernel_width ; ++k )
    {
      line[ k + half_kernel_width + rows ] = img.coeffRef( rows - 1 , col ) ;
    }

    // Apply convolution
    conv_buffer_( &line[0] , kernel.data() , rows , kernel_width );

    for( int row = 0 ; row < rows ; ++row )
    {
      out.coeffRef( row , col ) = line[row];
    }
  }
}

/**
 ** Separable 2D convolution
 ** (nxm kernel is replaced by two 1D convolution of (size n then size m) )
 ** @param img source image
 ** @param horiz_k horizontal kernel
 ** @param vert_k vertical kernel
 ** @param out output image
 **/
template< typename ImageType, typename Kernel >
void ImageSeparableConvolution( const ImageType & img ,
                                const Kernel & horiz_k ,
                                const Kernel & vert_k ,
                                ImageType & out)
{
  // Cast the Kernel to the appropriate type
  typedef typename ImageType::Tpixel pix_t;
  typedef Eigen::Matrix<typename Accumulator<pix_t>::Type, Eigen::Dynamic, 1> VecKernel;
  const VecKernel horiz_k_cast = horiz_k.template cast< typename Accumulator<pix_t>::Type >();
  const VecKernel vert_k_cast = vert_k.template cast< typename Accumulator<pix_t>::Type >();

  ImageType tmp ;
  ImageHorizontalConvolution( img , horiz_k_cast , tmp ) ;
  ImageVerticalConvolution( tmp , vert_k_cast , out ) ;
}

typedef Eigen::Matrix<float, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor> RowMatrixXf;

/// Specialization for Float based image (for arbitrary sized kernel)
static void SeparableConvolution2d(const RowMatrixXf& image,
                            const Eigen::Matrix<float, 1, Eigen::Dynamic>& kernel_x,
                            const Eigen::Matrix<float, 1, Eigen::Dynamic>& kernel_y,
                            RowMatrixXf* out) {
  const int sigma_y = kernel_y.cols();
  const int half_sigma_y = kernel_y.cols() / 2;

  // Convolving a vertical filter across rows is the same thing as transpose
  // multiply i.e. kernel_y^t * rows. This will give us the convoled value for
  // each row. However, care must be taken at the top and bottom borders.
  const Eigen::Matrix<float, 1, Eigen::Dynamic> reverse_kernel_y = kernel_y.reverse();
#if defined(USE_OPENMP)
#pragma omp parallel for
#endif
  for (int i = 0; i < half_sigma_y; i++) {
    const int forward_size = i + half_sigma_y + 1;
    const int reverse_size = sigma_y - forward_size;
    out->row(i) = kernel_y.tail(forward_size) *
                  image.block(0, 0, forward_size, image.cols()) +
                  reverse_kernel_y.tail(reverse_size) *
                  image.block(1, 0, reverse_size, image.cols());

    // Apply the same technique for the end rows.
    out->row(image.rows() - i - 1) =
      kernel_y.head(forward_size) *
      image.block(image.rows() - forward_size, 0, forward_size, image.cols())
      +
      reverse_kernel_y.head(reverse_size) *
      image.block(image.rows() - reverse_size - 1, 0, reverse_size, image.cols());
  }

  // Applying the rest of the y filter.
#if defined(USE_OPENMP)
#pragma omp parallel for
#endif
  for (int row = half_sigma_y; row < image.rows() - half_sigma_y; row++) {
    out->row(row) =  kernel_y * image.block(row - half_sigma_y, 0, sigma_y, out->cols());
  }

  const int sigma_x = kernel_x.cols();
  const int half_sigma_x = kernel_x.cols() / 2;

  // Convolving with the horizontal filter is easy. Rather than using the kernel
  // as a sliding window, we use the row pixels as a sliding window around the
  // filter. We prepend and append the proper border values so that we are sure
  // to end up with the correct convolved values.
  Eigen::RowVectorXf temp_row(image.cols() + sigma_x - 1);
#if defined(USE_OPENMP)
#pragma omp parallel for firstprivate(temp_row)
#endif
  for (int row = 0; row < out->rows(); row++) {
    temp_row.head(half_sigma_x) =
      out->row(row).segment(1, half_sigma_x).reverse();
    temp_row.segment(half_sigma_x, image.cols()) = out->row(row);
    temp_row.tail(half_sigma_x) =
      out->row(row)
      .segment(image.cols() - 2 - half_sigma_x, half_sigma_x)
      .reverse();

    // Convolve the row. We perform the first step here explicitly so that we
    // avoid setting the row equal to zero.
    out->row(row) = kernel_x(0) * temp_row.head(image.cols());
    for (int i = 1; i < sigma_x; i++) {
      out->row(row) += kernel_x(i) * temp_row.segment(i, image.cols());
    }
  }
}

// Specialization for Image<float> in order to use SeparableConvolution2d
template<typename Kernel>
void ImageSeparableConvolution( const Image<float> & img ,
                                const Kernel & horiz_k ,
                                const Kernel & vert_k ,
                                Image<float> & out)
{
  // Cast the Kernel to the appropriate type
  typedef Image<float>::Tpixel pix_t;
  typedef Eigen::Matrix<typename Accumulator<pix_t>::Type, Eigen::Dynamic, 1> VecKernel;
  const VecKernel horiz_k_cast = horiz_k.template cast< typename Accumulator<pix_t>::Type >();
  const VecKernel vert_k_cast = vert_k.template cast< typename Accumulator<pix_t>::Type >();

  out.resize(img.Width(), img.Height());
  SeparableConvolution2d(img.GetMat(), horiz_k_cast, vert_k_cast, &((Image<float>::Base&)out));
}

} // namespace openMVG

#endif // OPENMVG_IMAGE_IMAGE_CONVOLUTION_HPP_

<|endoftext|>


<commit_before>/***************************************************************************
 * Copyright (c) Johan Mabille, Sylvain Corlay, Wolf Vollprecht and         *
 * Martin Renou                                                             *
 * Copyright (c) QuantStack                                                 *
 * Copyright (c) Serge Guelton                                              *
 *                                                                          *
 * Distributed under the terms of the BSD 3-Clause License.                 *
 *                                                                          *
 * The full license is in the file LICENSE, distributed with this software. *
 ****************************************************************************/

#ifndef XSIMD_CPUID_HPP
#define XSIMD_CPUID_HPP

#include <algorithm>
#include <cstring>

#if defined(__linux__) && (defined(__ARM_NEON) || defined(_M_ARM))
#include <asm/hwcap.h>
#include <sys/auxv.h>
#endif

#if defined(_MSC_VER)
// Contains the definition of __cpuidex
#include <intrin.h>
#endif

#include "../types/xsimd_all_registers.hpp"

namespace xsimd
{
    namespace detail
    {
        struct supported_arch
        {
            unsigned sse2 : 1;
            unsigned sse3 : 1;
            unsigned ssse3 : 1;
            unsigned sse4_1 : 1;
            unsigned sse4_2 : 1;
            unsigned sse4a : 1;
            unsigned fma3_sse : 1;
            unsigned fma4 : 1;
            unsigned xop : 1;
            unsigned avx : 1;
            unsigned fma3_avx : 1;
            unsigned avx2 : 1;
            unsigned fma3_avx2 : 1;
            unsigned avx512f : 1;
            unsigned avx512cd : 1;
            unsigned avx512dq : 1;
            unsigned avx512bw : 1;
            unsigned neon : 1;
            unsigned neon64 : 1;

            // version number of the best arch available
            unsigned best;

            supported_arch() noexcept
            {
                memset(this, 0, sizeof(supported_arch));

#if defined(__aarch64__) || defined(_M_ARM64)
                neon = 1;
                neon64 = 1;
                best = neon64::version();
#elif defined(__ARM_NEON) || defined(_M_ARM)
#if defined(__linux__)
                neon = bool(getauxval(AT_HWCAP) & HWCAP_NEON);
#else
                // that's very conservative :-/
                neon = 0;
#endif
                neon64 = 0;
                best = neon::version() * neon;

#elif defined(__x86_64__) || defined(__i386__) || defined(_M_AMD64) || defined(_M_IX86)
                auto get_cpuid = [](int reg[4], int func_id) noexcept
                {

#if defined(_MSC_VER)
                    __cpuidex(reg, func_id, 0);

#elif defined(__INTEL_COMPILER)
                    __cpuid(reg, func_id);

#elif defined(__GNUC__) || defined(__clang__)

#if defined(__i386__) && defined(__PIC__)
                    // %ebx may be the PIC register
                    __asm__("xchg{l}\t{%%}ebx, %1\n\t"
                            "cpuid\n\t"
                            "xchg{l}\t{%%}ebx, %1\n\t"
                            : "=a"(reg[0]), "=r"(reg[1]), "=c"(reg[2]),
                              "=d"(reg[3])
                            : "a"(func_id), "c"(0));

#else
                    __asm__("cpuid\n\t"
                            : "=a"(reg[0]), "=b"(reg[1]), "=c"(reg[2]),
                              "=d"(reg[3])
                            : "a"(func_id), "c"(0));
#endif

#else
#error "Unsupported configuration"
#endif
                };

                int regs[4];

                get_cpuid(regs, 0x1);

                sse2 = regs[2] >> 26 & 1;
                best = std::max(best, sse2::version() * sse2);

                sse3 = regs[2] >> 0 & 1;
                best = std::max(best, sse3::version() * sse3);

                ssse3 = regs[2] >> 9 & 1;
                best = std::max(best, ssse3::version() * ssse3);

                sse4_1 = regs[2] >> 19 & 1;
                best = std::max(best, sse4_1::version() * sse4_1);

                sse4_2 = regs[2] >> 20 & 1;
                best = std::max(best, sse4_2::version() * sse4_2);

                fma3_sse = regs[2] >> 12 & 1;
                if (sse4_2)
                    best = std::max(best, fma3<xsimd::sse4_2>::version() * fma3_sse);

                get_cpuid(regs, 0x80000001);
                fma4 = regs[2] >> 16 & 1;
                best = std::max(best, fma4::version() * fma4);

                // sse4a = regs[2] >> 6 & 1;
                // best = std::max(best, XSIMD_X86_AMD_SSE4A_VERSION * sse4a);

                // xop = regs[2] >> 11 & 1;
                // best = std::max(best, XSIMD_X86_AMD_XOP_VERSION * xop);

                avx = regs[2] >> 28 & 1;
                best = std::max(best, avx::version() * avx);

                fma3_avx = avx && fma3_sse;
                best = std::max(best, fma3<xsimd::avx>::version() * fma3_avx);

                get_cpuid(regs, 0x7);
                avx2 = regs[1] >> 5 & 1;
                best = std::max(best, avx2::version() * avx2);

                fma3_avx2 = avx2 && fma3_sse;
                best = std::max(best, fma3<xsimd::avx2>::version() * fma3_avx2);

                avx512f = regs[1] >> 16 & 1;
                best = std::max(best, avx512f::version() * avx512f);

                avx512cd = regs[1] >> 28 & 1;
                best = std::max(best, avx512cd::version() * avx512cd * avx512f);

                avx512dq = regs[1] >> 17 & 1;
                best = std::max(best, avx512dq::version() * avx512dq * avx512cd * avx512f);

                avx512bw = regs[1] >> 30 & 1;
                best = std::max(best, avx512bw::version() * avx512bw * avx512dq * avx512cd * avx512f);

#endif
            }
        };
    }

    inline detail::supported_arch available_architectures() noexcept
    {
        static detail::supported_arch supported;
        return supported;
    }
}

#endif
<commit_msg>Get SSE2 value from reg[3]<commit_after>/***************************************************************************
 * Copyright (c) Johan Mabille, Sylvain Corlay, Wolf Vollprecht and         *
 * Martin Renou                                                             *
 * Copyright (c) QuantStack                                                 *
 * Copyright (c) Serge Guelton                                              *
 *                                                                          *
 * Distributed under the terms of the BSD 3-Clause License.                 *
 *                                                                          *
 * The full license is in the file LICENSE, distributed with this software. *
 ****************************************************************************/

#ifndef XSIMD_CPUID_HPP
#define XSIMD_CPUID_HPP

#include <algorithm>
#include <cstring>

#if defined(__linux__) && (defined(__ARM_NEON) || defined(_M_ARM))
#include <asm/hwcap.h>
#include <sys/auxv.h>
#endif

#if defined(_MSC_VER)
// Contains the definition of __cpuidex
#include <intrin.h>
#endif

#include "../types/xsimd_all_registers.hpp"

namespace xsimd
{
    namespace detail
    {
        struct supported_arch
        {
            unsigned sse2 : 1;
            unsigned sse3 : 1;
            unsigned ssse3 : 1;
            unsigned sse4_1 : 1;
            unsigned sse4_2 : 1;
            unsigned sse4a : 1;
            unsigned fma3_sse : 1;
            unsigned fma4 : 1;
            unsigned xop : 1;
            unsigned avx : 1;
            unsigned fma3_avx : 1;
            unsigned avx2 : 1;
            unsigned fma3_avx2 : 1;
            unsigned avx512f : 1;
            unsigned avx512cd : 1;
            unsigned avx512dq : 1;
            unsigned avx512bw : 1;
            unsigned neon : 1;
            unsigned neon64 : 1;

            // version number of the best arch available
            unsigned best;

            supported_arch() noexcept
            {
                memset(this, 0, sizeof(supported_arch));

#if defined(__aarch64__) || defined(_M_ARM64)
                neon = 1;
                neon64 = 1;
                best = neon64::version();
#elif defined(__ARM_NEON) || defined(_M_ARM)
#if defined(__linux__)
                neon = bool(getauxval(AT_HWCAP) & HWCAP_NEON);
#else
                // that's very conservative :-/
                neon = 0;
#endif
                neon64 = 0;
                best = neon::version() * neon;

#elif defined(__x86_64__) || defined(__i386__) || defined(_M_AMD64) || defined(_M_IX86)
                auto get_cpuid = [](int reg[4], int func_id) noexcept
                {

#if defined(_MSC_VER)
                    __cpuidex(reg, func_id, 0);

#elif defined(__INTEL_COMPILER)
                    __cpuid(reg, func_id);

#elif defined(__GNUC__) || defined(__clang__)

#if defined(__i386__) && defined(__PIC__)
                    // %ebx may be the PIC register
                    __asm__("xchg{l}\t{%%}ebx, %1\n\t"
                            "cpuid\n\t"
                            "xchg{l}\t{%%}ebx, %1\n\t"
                            : "=a"(reg[0]), "=r"(reg[1]), "=c"(reg[2]),
                              "=d"(reg[3])
                            : "a"(func_id), "c"(0));

#else
                    __asm__("cpuid\n\t"
                            : "=a"(reg[0]), "=b"(reg[1]), "=c"(reg[2]),
                              "=d"(reg[3])
                            : "a"(func_id), "c"(0));
#endif

#else
#error "Unsupported configuration"
#endif
                };

                int regs[4];

                get_cpuid(regs, 0x1);

                sse2 = regs[3] >> 26 & 1;
                best = std::max(best, sse2::version() * sse2);

                sse3 = regs[2] >> 0 & 1;
                best = std::max(best, sse3::version() * sse3);

                ssse3 = regs[2] >> 9 & 1;
                best = std::max(best, ssse3::version() * ssse3);

                sse4_1 = regs[2] >> 19 & 1;
                best = std::max(best, sse4_1::version() * sse4_1);

                sse4_2 = regs[2] >> 20 & 1;
                best = std::max(best, sse4_2::version() * sse4_2);

                fma3_sse = regs[2] >> 12 & 1;
                if (sse4_2)
                    best = std::max(best, fma3<xsimd::sse4_2>::version() * fma3_sse);

                get_cpuid(regs, 0x80000001);
                fma4 = regs[2] >> 16 & 1;
                best = std::max(best, fma4::version() * fma4);

                // sse4a = regs[2] >> 6 & 1;
                // best = std::max(best, XSIMD_X86_AMD_SSE4A_VERSION * sse4a);

                // xop = regs[2] >> 11 & 1;
                // best = std::max(best, XSIMD_X86_AMD_XOP_VERSION * xop);

                avx = regs[2] >> 28 & 1;
                best = std::max(best, avx::version() * avx);

                fma3_avx = avx && fma3_sse;
                best = std::max(best, fma3<xsimd::avx>::version() * fma3_avx);

                get_cpuid(regs, 0x7);
                avx2 = regs[1] >> 5 & 1;
                best = std::max(best, avx2::version() * avx2);

                fma3_avx2 = avx2 && fma3_sse;
                best = std::max(best, fma3<xsimd::avx2>::version() * fma3_avx2);

                avx512f = regs[1] >> 16 & 1;
                best = std::max(best, avx512f::version() * avx512f);

                avx512cd = regs[1] >> 28 & 1;
                best = std::max(best, avx512cd::version() * avx512cd * avx512f);

                avx512dq = regs[1] >> 17 & 1;
                best = std::max(best, avx512dq::version() * avx512dq * avx512cd * avx512f);

                avx512bw = regs[1] >> 30 & 1;
                best = std::max(best, avx512bw::version() * avx512bw * avx512dq * avx512cd * avx512f);

#endif
            }
        };
    }

    inline detail::supported_arch available_architectures() noexcept
    {
        static detail::supported_arch supported;
        return supported;
    }
}

#endif
<|endoftext|>


<commit_before>#include "FramePanel.h"
#include <algorithm>

using namespace std;

FramePanel::FramePanel()
{
	contentSize.w = 0;
	contentSize.h = 0;
}

FramePanel::~FramePanel()
{
}

void FramePanel::OnLayoutChange()
{
	Position childOffset = Position(0, 0);
	contentSize = Size(0, 0);

	Size* childSizes = new Size[children.size()];

	if (size.w == SIZE_FILL_PARENT || size.w > 0)
		contentSize.w = calculatedSize.w;
	if (size.h == SIZE_FILL_PARENT || size.h > 0)
		contentSize.h = calculatedSize.h;

	// Position children
	for (int i = 0; i < children.size(); i++)
	{
		View* v = children.at(i);

		Box childMargin = v->GetLayoutMargin();
		v->SetRelativePosition(Position(childMargin.left, childMargin.top));
		Size sizeAreaForChild;
		sizeAreaForChild.w = max(size.w == SIZE_WRAP_CONTENT ? -1 : calculatedSize.w - (childMargin.left + childMargin.right), 0);
		sizeAreaForChild.h = max(size.h == SIZE_WRAP_CONTENT ? -1 : calculatedSize.h - (childMargin.top + childMargin.bottom), 0);
		Size childSize = v->CalculateLayout(sizeAreaForChild);
		Size childSizeIncMargins = childSize + Size(childMargin.left + childMargin.right, childMargin.top + childMargin.bottom);
		childSizes[i] = childSizeIncMargins;

		contentSize.w = max(contentSize.w, childSizeIncMargins.w);
		contentSize.h = max(contentSize.h, childSizeIncMargins.h);
	}

	// Adjust child positions for gravity
	for (int i = 0; i < children.size(); i++)
	{
		View* v = children.at(i);

		Position gravityOffset = GetGravityOffset(childSizes[i], contentSize, children[i]->GetLayoutGravity());
		v->SetRelativePosition(v->GetRelativePosition() + gravityOffset);
	}

	delete[] childSizes;
}

View* FramePanel::Copy()
{
	FramePanel* view = new FramePanel();

	CopyBase(view);

	return view;
}

bool FramePanel::SetProperty(string name, string value)
{
	bool propertyHandled = View::SetProperty(name, value);

	if (propertyHandled)
		return true;

	return false;
}
<commit_msg>FramePanel: throw exception if size is wrapping content while child is filling parent view, instead of silently setting size to zero so nothing is shown.<commit_after>#include "FramePanel.h"
#include <algorithm>

using namespace std;

FramePanel::FramePanel()
{
	contentSize.w = 0;
	contentSize.h = 0;
}

FramePanel::~FramePanel()
{
}

void FramePanel::OnLayoutChange()
{
	Position childOffset = Position(0, 0);
	contentSize = Size(0, 0);

	Size* childSizes = new Size[children.size()];

	if (size.w == SIZE_FILL_PARENT || size.w > 0)
		contentSize.w = calculatedSize.w;
	if (size.h == SIZE_FILL_PARENT || size.h > 0)
		contentSize.h = calculatedSize.h;

	// Position children
	for (int i = 0; i < children.size(); i++)
	{
		View* v = children.at(i);

		if (v->GetSize().w == SIZE_FILL_PARENT && size.w == SIZE_WRAP_CONTENT ||
			v->GetSize().h == SIZE_FILL_PARENT && size.h == SIZE_WRAP_CONTENT)
			throw runtime_error("cannot calculate layout size");

		Box childMargin = v->GetLayoutMargin();
		v->SetRelativePosition(Position(childMargin.left, childMargin.top));
		Size sizeAreaForChild;
		sizeAreaForChild.w = max(size.w == SIZE_WRAP_CONTENT ? -1 : calculatedSize.w - (childMargin.left + childMargin.right), 0);
		sizeAreaForChild.h = max(size.h == SIZE_WRAP_CONTENT ? -1 : calculatedSize.h - (childMargin.top + childMargin.bottom), 0);
		Size childSize = v->CalculateLayout(sizeAreaForChild);
		Size childSizeIncMargins = childSize + Size(childMargin.left + childMargin.right, childMargin.top + childMargin.bottom);
		childSizes[i] = childSizeIncMargins;

		contentSize.w = max(contentSize.w, childSizeIncMargins.w);
		contentSize.h = max(contentSize.h, childSizeIncMargins.h);
	}

	// Adjust child positions for gravity
	for (int i = 0; i < children.size(); i++)
	{
		View* v = children.at(i);

		Position gravityOffset = GetGravityOffset(childSizes[i], contentSize, children[i]->GetLayoutGravity());
		v->SetRelativePosition(v->GetRelativePosition() + gravityOffset);
	}

	delete[] childSizes;
}

View* FramePanel::Copy()
{
	FramePanel* view = new FramePanel();

	CopyBase(view);

	return view;
}

bool FramePanel::SetProperty(string name, string value)
{
	bool propertyHandled = View::SetProperty(name, value);

	if (propertyHandled)
		return true;

	return false;
}
<|endoftext|>