<commit_before>#include "stdafx.h"

DIB::DIB()
{
	m_w = m_h = 0;
	m_pitch = 0;
	m_p = 0;
#ifdef _MSC_VER
	m_hbm = NULL;
	m_hdc = NULL;
	m_hbmOld = NULL;
	memset(&m_ds, 0, sizeof(m_ds));
#endif
}

DIB::~DIB()
{
	Destroy();
}

void DIB::Destroy()
{
#ifdef _MSC_VER
	if (m_hbmOld) {
		SelectObject(m_hdc, m_hbmOld);
		m_hbmOld = NULL;
	}
	if (m_hdc) {
		DeleteDC(m_hdc);
		m_hdc = NULL;
	}
	if (m_hbm) {
		DeleteObject(m_hbm);
		m_hbm = NULL;
	}
#else
	free(m_p);
	m_p = nullptr;
#endif
}

bool DIB::Create(int w, int h)
{
	return Create(w, h, 32);
}

#ifndef _MSC_VER
bool DIB::Create(int w, int h, int bits, int)
{
	Destroy();
	m_w = w;
	m_h = h;
	m_pitch = (w * (bits / 8) + 3) & ~3;
	m_p = malloc(m_pitch * h);
	return true;
}
#endif

#ifdef _MSC_VER
bool DIB::Create(int w, int h, int bits, int level)
{
	Destroy();

	switch(bits) {
		case 8:
		case 32:
			break;
		default:
			return false;
	}

	m_w = w;
	m_h = h;

	struct BMI256 : BITMAPINFO {
		RGBQUAD bmiAdditionalColors[255];
	}bmi;
	memset(&bmi, 0, sizeof(bmi));
	BITMAPINFOHEADER *bh = &bmi.bmiHeader;
	bh->biSize = sizeof(BITMAPINFOHEADER);
	bh->biWidth = w;
	bh->biHeight = -h;	// top down
	bh->biPlanes = 1;
	bh->biBitCount = bits;

	if (bits == 8) {
		for (int i = 0; i < 256; i++) {
			int v = std::min(i * 255 / level, 255);
			bmi.bmiColors[i].rgbRed = v;
			bmi.bmiColors[i].rgbGreen = v;
			bmi.bmiColors[i].rgbBlue = v;
			bmi.bmiColors[i].rgbReserved = 0;
		}
	}
	HWND hWnd = GetDesktopWindow();
	HDC hdc = GetDC(hWnd);
	if (!hdc){
		ReleaseDC(hWnd, hdc);
		return false;
	}
	m_hbm = CreateDIBSection(hdc, &bmi, DIB_RGB_COLORS, (void**)&m_p, NULL, 0);
	if (m_hbm == NULL) {
		ReleaseDC(hWnd, hdc);
		Destroy();
		return false;
	}
	m_hdc = CreateCompatibleDC(hdc);
	if (m_hdc == NULL) {
		ReleaseDC(hWnd, hdc);
		return false;
	}
	m_hbmOld = (HBITMAP)SelectObject(m_hdc, m_hbm);
	GetObject(m_hbm, sizeof(DIBSECTION), &m_ds);
	m_pitch = m_ds.dsBm.bmWidthBytes;
	ReleaseDC(hWnd, hdc);
	return true;
}
#endif

void DIB::DibToGL()
{
	for(int y = 0; y < getH(); y++) {
		for (int x = 0; x < getW(); x++) {
			pixel px = getPixel(x, y);
			std::swap(*((char*)(&px) + 0), *((char*)(&px) + 2));
			setPixel(x, y, px);
		}
	}
}

void DIB::DibToGLFont()
{
	for (int y = 0; y < getH(); y++) {
		for (int x = 0; x < getW(); x++) {
			pixel px = getPixel(x, y);
			px = (px << 8) | 0x00ffffff;
			setPixel(x, y, px);
		}
	}
}

void DIB::DibToDXFont()
{
	for (int y = 0; y < getH(); y++) {
		for (int x = 0; x < getW(); x++) {
			pixel px = getPixel(x, y);
			px = (px << 8) | 0x00ffffff;
//			px |= 0xffffff00;
			setPixel(x, y, px);
		}
	}
}

void DIB::FillAlpha()
{
	for (int y = 0; y < getH(); y++) {
		for (int x = 0; x < getW(); x++) {
			*referPixel(x, y) |= 0xff000000;
		}
	}
}

void DIB::Clear(pixel color)
{
	for (int y = 0; y < getH(); y++) {
		for (int x = 0; x < getW(); x++) {
			setPixel(x, y, color);
		}
	}
}

#ifdef _MSC_VER
static bool dibCopy32(DIB *dib, BITMAPINFO *bi, void *bits)
{
	int srcH = bi->bmiHeader.biHeight;
	if (dib->getW() != bi->bmiHeader.biWidth || dib->getH() != abs(srcH)) {
		return false;
	}

	if (bi->bmiHeader.biBitCount != 32) {
		return false;
	}

	for (int y = 0; y < dib->getH(); y++) {
		int srcY = srcH > 0 ? srcH - 1 - y : y;	// support both bottom-up and top-down
		void *dst = dib->referPixel(0, y);
		void *src = (DWORD*)bits + dib->getW() * srcY;
		memcpy(dst, src, dib->getW() * sizeof(DWORD));
	}
	return true;
}
#endif

#ifdef _MSC_VER
bool DIB::LoadFromBmp(const char *file)
{
	bool result = false;
	BITMAPINFO *bi;
	void *bits;
	void *tmp = NULL;

	int size;
	tmp = LoadFile(file, &size);
	if (!tmp) {
		return false;
	}

	BITMAPFILEHEADER *fh = (BITMAPFILEHEADER*)tmp;
	if (fh->bfType != *(WORD*)"BM") {
		goto end;
	}

	bi = (BITMAPINFO*)((BYTE*)tmp + sizeof(*fh));
	bits = (BYTE*)tmp + fh->bfOffBits;

	if (!Create(bi->bmiHeader.biWidth, abs(bi->bmiHeader.biHeight))) {
		goto end;
	}

	StretchDIBits(m_hdc, 0, 0, m_w, m_h, 0, 0, m_w, m_h, bits, bi, DIB_RGB_COLORS, SRCCOPY);

	// StretchDIBits may ignore alpha channel
	// fill the alpha channel for textures
	FillAlpha();

	result = true;
end:
	if (tmp) {
		free(tmp);
	}
	return result;
}

bool DIB::Blt(HDC target, int dstX, int dstY, int w, int h)
{
	return !!BitBlt(target, dstX, dstY, w, h, m_hdc, 0, 0, SRCCOPY);
}

void DIB::Save(const char* fileName)
{
	if (m_ds.dsBm.bmBitsPixel != 32) {
		return;
	}

	int pixSize =  + getW() * getH() * 4;
	int fileSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + pixSize;
	BYTE* img = (BYTE*)calloc(fileSize, 1);
	int ofs = 0;
	BITMAPFILEHEADER& fh = *(BITMAPFILEHEADER*)img;
	ofs += sizeof(BITMAPFILEHEADER);
	BITMAPINFOHEADER& ih = *(BITMAPINFOHEADER*)(img + ofs);
	ofs += sizeof(BITMAPINFOHEADER);
	DWORD* pxs = (DWORD*)(img + ofs);

	fh.bfType = 'MB';
	fh.bfSize = fileSize;
	fh.bfOffBits = ofs;
	ih = m_ds.dsBmih;
	memcpy(pxs, m_p, pixSize);
	if (ih.biHeight > 0) {
		ih.biHeight = -ih.biHeight;	// top down
	}
	SaveFile(fileName, img, fileSize);
	free(img);
}

#endif

bool DIB::Blt(DIB& target, int dstX, int dstY)
{
	if (dstX < 0 || dstY < 0) {
		return false;
	}
	if (dstX + getW() > target.getW()) {
		return false;
	}
	if (dstX + getH() > target.getH()) {
		return false;
	}
	for (int y = 0; y < getH(); y++) {
		for (int x = 0; x < getW(); x++) {
			target.setPixel(dstX + x, dstY + y, getPixel(x, y));
		}
	}
	return true;
}

bool DIB::ApplySoftAA(DIB& target)
{
	if (getW() != target.getW() * 2) {
		return false;
	}
	if (getH() != target.getH() * 2) {
		return false;
	}
	for (int y = 0; y < target.getH(); y++) {
		for (int x = 0; x < target.getW(); x++) {
			pixel color[] = { getPixel(x * 2, y * 2), getPixel(x * 2 + 1, y * 2), getPixel(x * 2, y * 2 + 1), getPixel(x * 2 + 1, y * 2 + 1) };
			IVec4 sum;
			for (int i = 0; i < (int)dimof(color); i++) {
				sum += UnormToIvec4(color[i]);
			}
			sum /= 4;
			target.setPixel(x, y, ivec4ToUnorm(sum));
		}
	}
	return true;
}
<commit_msg>Fix missing glyph bug.<commit_after>#include "stdafx.h"

DIB::DIB()
{
	m_w = m_h = 0;
	m_pitch = 0;
	m_p = 0;
#ifdef _MSC_VER
	m_hbm = NULL;
	m_hdc = NULL;
	m_hbmOld = NULL;
	memset(&m_ds, 0, sizeof(m_ds));
#endif
}

DIB::~DIB()
{
	Destroy();
}

void DIB::Destroy()
{
#ifdef _MSC_VER
	if (m_hbmOld) {
		SelectObject(m_hdc, m_hbmOld);
		m_hbmOld = NULL;
	}
	if (m_hdc) {
		DeleteDC(m_hdc);
		m_hdc = NULL;
	}
	if (m_hbm) {
		DeleteObject(m_hbm);
		m_hbm = NULL;
	}
#else
	free(m_p);
	m_p = nullptr;
#endif
}

bool DIB::Create(int w, int h)
{
	return Create(w, h, 32);
}

#ifndef _MSC_VER
bool DIB::Create(int w, int h, int bits, int)
{
	Destroy();
	m_w = w;
	m_h = h;
	m_pitch = (w * (bits / 8) + 3) & ~3;
	m_p = malloc(m_pitch * h);
	return true;
}
#endif

#ifdef _MSC_VER
bool DIB::Create(int w, int h, int bits, int level)
{
	Destroy();

	switch(bits) {
		case 8:
		case 32:
			break;
		default:
			return false;
	}

	m_w = w;
	m_h = h;

	struct BMI256 : BITMAPINFO {
		RGBQUAD bmiAdditionalColors[255];
	}bmi;
	memset(&bmi, 0, sizeof(bmi));
	BITMAPINFOHEADER *bh = &bmi.bmiHeader;
	bh->biSize = sizeof(BITMAPINFOHEADER);
	bh->biWidth = w;
	bh->biHeight = -h;	// top down
	bh->biPlanes = 1;
	bh->biBitCount = bits;

	if (bits == 8) {
		for (int i = 0; i < 256; i++) {
			int v = std::min(i * 255 / level, 255);
			bmi.bmiColors[i].rgbRed = v;
			bmi.bmiColors[i].rgbGreen = v;
			bmi.bmiColors[i].rgbBlue = v;
			bmi.bmiColors[i].rgbReserved = 0;
		}
	}
	HWND hWnd = GetDesktopWindow();
	HDC hdc = GetDC(hWnd);
	if (!hdc){
		ReleaseDC(hWnd, hdc);
		return false;
	}
	m_hbm = CreateDIBSection(hdc, &bmi, DIB_RGB_COLORS, (void**)&m_p, NULL, 0);
	if (m_hbm == NULL) {
		ReleaseDC(hWnd, hdc);
		Destroy();
		return false;
	}
	m_hdc = CreateCompatibleDC(hdc);
	if (m_hdc == NULL) {
		ReleaseDC(hWnd, hdc);
		return false;
	}
	m_hbmOld = (HBITMAP)SelectObject(m_hdc, m_hbm);
	GetObject(m_hbm, sizeof(DIBSECTION), &m_ds);
	m_pitch = m_ds.dsBm.bmWidthBytes;
	ReleaseDC(hWnd, hdc);
	return true;
}
#endif

void DIB::DibToGL()
{
	for(int y = 0; y < getH(); y++) {
		for (int x = 0; x < getW(); x++) {
			pixel px = getPixel(x, y);
			std::swap(*((char*)(&px) + 0), *((char*)(&px) + 2));
			setPixel(x, y, px);
		}
	}
}

void DIB::DibToGLFont()
{
	for (int y = 0; y < getH(); y++) {
		for (int x = 0; x < getW(); x++) {
			pixel px = getPixel(x, y);
			px = (px << 8) | 0x00ffffff;
			setPixel(x, y, px);
		}
	}
}

void DIB::DibToDXFont()
{
	for (int y = 0; y < getH(); y++) {
		for (int x = 0; x < getW(); x++) {
			pixel px = getPixel(x, y);
			px = (px << 8) | 0x00ffffff;
//			px |= 0xffffff00;
			setPixel(x, y, px);
		}
	}
}

void DIB::FillAlpha()
{
	for (int y = 0; y < getH(); y++) {
		for (int x = 0; x < getW(); x++) {
			*referPixel(x, y) |= 0xff000000;
		}
	}
}

void DIB::Clear(pixel color)
{
	for (int y = 0; y < getH(); y++) {
		for (int x = 0; x < getW(); x++) {
			setPixel(x, y, color);
		}
	}
}

#ifdef _MSC_VER
static bool dibCopy32(DIB *dib, BITMAPINFO *bi, void *bits)
{
	int srcH = bi->bmiHeader.biHeight;
	if (dib->getW() != bi->bmiHeader.biWidth || dib->getH() != abs(srcH)) {
		return false;
	}

	if (bi->bmiHeader.biBitCount != 32) {
		return false;
	}

	for (int y = 0; y < dib->getH(); y++) {
		int srcY = srcH > 0 ? srcH - 1 - y : y;	// support both bottom-up and top-down
		void *dst = dib->referPixel(0, y);
		void *src = (DWORD*)bits + dib->getW() * srcY;
		memcpy(dst, src, dib->getW() * sizeof(DWORD));
	}
	return true;
}
#endif

#ifdef _MSC_VER
bool DIB::LoadFromBmp(const char *file)
{
	bool result = false;
	BITMAPINFO *bi;
	void *bits;
	void *tmp = NULL;

	int size;
	tmp = LoadFile(file, &size);
	if (!tmp) {
		return false;
	}

	BITMAPFILEHEADER *fh = (BITMAPFILEHEADER*)tmp;
	if (fh->bfType != *(WORD*)"BM") {
		goto end;
	}

	bi = (BITMAPINFO*)((BYTE*)tmp + sizeof(*fh));
	bits = (BYTE*)tmp + fh->bfOffBits;

	if (!Create(bi->bmiHeader.biWidth, abs(bi->bmiHeader.biHeight))) {
		goto end;
	}

	StretchDIBits(m_hdc, 0, 0, m_w, m_h, 0, 0, m_w, m_h, bits, bi, DIB_RGB_COLORS, SRCCOPY);

	// StretchDIBits may ignore alpha channel
	// fill the alpha channel for textures
	FillAlpha();

	result = true;
end:
	if (tmp) {
		free(tmp);
	}
	return result;
}

bool DIB::Blt(HDC target, int dstX, int dstY, int w, int h)
{
	return !!BitBlt(target, dstX, dstY, w, h, m_hdc, 0, 0, SRCCOPY);
}

void DIB::Save(const char* fileName)
{
	if (m_ds.dsBm.bmBitsPixel != 32) {
		return;
	}

	int pixSize =  + getW() * getH() * 4;
	int fileSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + pixSize;
	BYTE* img = (BYTE*)calloc(fileSize, 1);
	int ofs = 0;
	BITMAPFILEHEADER& fh = *(BITMAPFILEHEADER*)img;
	ofs += sizeof(BITMAPFILEHEADER);
	BITMAPINFOHEADER& ih = *(BITMAPINFOHEADER*)(img + ofs);
	ofs += sizeof(BITMAPINFOHEADER);
	DWORD* pxs = (DWORD*)(img + ofs);

	fh.bfType = 'MB';
	fh.bfSize = fileSize;
	fh.bfOffBits = ofs;
	ih = m_ds.dsBmih;
	memcpy(pxs, m_p, pixSize);
	if (ih.biHeight > 0) {
		ih.biHeight = -ih.biHeight;	// top down
	}
	SaveFile(fileName, img, fileSize);
	free(img);
}

#endif

bool DIB::Blt(DIB& target, int dstX, int dstY)
{
	if (dstX < 0 || dstY < 0) {
		return false;
	}
	if (dstX + getW() > target.getW()) {
		return false;
	}
	if (dstY + getH() > target.getH()) {
		return false;
	}
	for (int y = 0; y < getH(); y++) {
		for (int x = 0; x < getW(); x++) {
			target.setPixel(dstX + x, dstY + y, getPixel(x, y));
		}
	}
	return true;
}

bool DIB::ApplySoftAA(DIB& target)
{
	if (getW() != target.getW() * 2) {
		return false;
	}
	if (getH() != target.getH() * 2) {
		return false;
	}
	for (int y = 0; y < target.getH(); y++) {
		for (int x = 0; x < target.getW(); x++) {
			pixel color[] = { getPixel(x * 2, y * 2), getPixel(x * 2 + 1, y * 2), getPixel(x * 2, y * 2 + 1), getPixel(x * 2 + 1, y * 2 + 1) };
			IVec4 sum;
			for (int i = 0; i < (int)dimof(color); i++) {
				sum += UnormToIvec4(color[i]);
			}
			sum /= 4;
			target.setPixel(x, y, ivec4ToUnorm(sum));
		}
	}
	return true;
}
<|endoftext|>


<commit_before>#include <ifstream>
#include "cpu.h"

cpu::cpu() {}

void cpu::reset() {
	pc = 0x200;
	for(auto i = 0; i < 4096; i++) {
		memory[i] = 0x0;
	}
	for(auto i = 0; i < 16; i++) {
		v[i] = 0x0;
	}
	stack_pointer = 0x0;

	//TODO set up fonts
}

void cpu::loadProgram(const std::string& filename) {
	reset(); //puts the cpu in a known state
	std::ifstream ifs;
	ifs.open(filename, std::ifstream::in);
	char c = ifs.get();
	uint16_t offset = 0x0;
	while(ifs.good()) {
		memory[pc + offset] = c;
		offset += 1;
		c = ifs.get();
	}
	ifs.close();
}

void cpu::dumpMemory(const std::ostream &stream) {
	//for(auto w = 0; w < )
	//TODO
}

void cpu::run() {
	bool running = true;
	while(running) {
		uint16_t instruction = (static_cast<uint16_t>memory[pc] << 8) | memory[pc + 1];
		switch((instruction & 0xF000) >> 12) {
			case 0x0:
				switch(instruction & 0xFF) {
					case 0xE0: //TODO clear the screen
						break;
					case 0xEE:
						pc = pop();
						break;
				}
				break;
			case 0x8:
				uint8_t x = (instruction & 0x0F00) >> 8;
				uint8_t y = (instruction & 0x00F0) >> 4;
				switch(instruction & 0x000F) {

				}
			default:
				//throw exception
				break;
		}

	}
}

void cpu::push(uint16_t value) {
	stack_pointer += 2;
	if (stack_pointer > 0x1F) //overflow the stack
		stack_pointer = 0x0;
	memory[0xEA0 + stack_pointer] = value & 0xFF00 >> 8;
	memory[0xEA0 + stack_pointer + 1] = value & 0xFF;
}

uint16_t cpu::pop() {
	uint16_t addr = (static_cast<uint16_t>memory[stack_pointer] << 8) | memory[stack_pointer + 1];
	stack_pointer -= 2;
	if (stack_pointer > 0x1F) //handle underflow
		stack_pointer = 0x1F;
	return addr;
}
<commit_msg>Fix tabs<commit_after>#include <ifstream>
#include "cpu.h"

cpu::cpu() {}

void cpu::reset() {
  pc = 0x200;
  for(auto i = 0; i < 4096; i++) {
    memory[i] = 0x0;
  }
  for(auto i = 0; i < 16; i++) {
    v[i] = 0x0;
  }
  stack_pointer = 0x0;

  //TODO set up fonts
}

void cpu::loadProgram(const std::string& filename) {
  reset(); //puts the cpu in a known state
  std::ifstream ifs;
  ifs.open(filename, std::ifstream::in);
  char c = ifs.get();
  uint16_t offset = 0x0;
  while(ifs.good()) {
    memory[pc + offset] = c;
    offset += 1;
    c = ifs.get();
  }
  ifs.close();
}

void cpu::dumpMemory(const std::ostream &stream) {
  //for(auto w = 0; w < )
  //TODO
}

void cpu::run() {
  bool running = true;
  while(running) {
    uint16_t instruction = (static_cast<uint16_t>memory[pc] << 8) | memory[pc + 1];
    switch((instruction & 0xF000) >> 12) {
      case 0x0:
        switch(instruction & 0xFF) {
          case 0xE0: //TODO clear the screen
            break;
          case 0xEE:
            pc = pop();
            break;
        }
        break;
      case 0x8:
        uint8_t x = (instruction & 0x0F00) >> 8;
        uint8_t y = (instruction & 0x00F0) >> 4;
        switch(instruction & 0x000F) {

        }
      default:
        //throw exception
        break;
    }

  }
}

void cpu::push(uint16_t value) {
  stack_pointer += 2;
  if (stack_pointer > 0x1F) //overflow the stack
    stack_pointer = 0x0;
  memory[0xEA0 + stack_pointer] = value & 0xFF00 >> 8;
  memory[0xEA0 + stack_pointer + 1] = value & 0xFF;
}

uint16_t cpu::pop() {
  uint16_t addr = (static_cast<uint16_t>memory[stack_pointer] << 8) | memory[stack_pointer + 1];
  stack_pointer -= 2;
  if (stack_pointer > 0x1F) //handle underflow
    stack_pointer = 0x1F;
  return addr;
}
<|endoftext|>


<commit_before>//============================================================================
// Name        : OctaneCrawler.cpp
// Author      : Berlin Brown (berlin dot brown at gmail.com)
// Version     :
// Copyright   : Copyright Berlin Brown 2012-2013
// License     : BSD
// Description : This is the simplest possible web crawler in C++
//               Uses boost_regex and boost_algorithm
//============================================================================
#include "../wget/crawler.h"

// using namespace std;
// using namespace boost;

namespace uri = boost::network::uri;
namespace  fs = boost::filesystem;

//class WebPage
//{
//public:
//    std::string  hostname;
//    std::string  path;
//
//    WebPage () : hostname (), path () {}
//
//    // std::string&  get_host (const std::string &url)
//    // {
//    //     const boost::regex re ("(?i)https?://(?:www\.)?([^/]+)(.*)");
//    //     boost::smatch what;
//    //     if ( boost::regex_match (url, what, re))
//    //     {
//    //         hostname = what[1];
//    //         boost::algorithm::to_lower (hostname);
//    //         return hostname;
//    //     }
//    //     hostname = "";
//    //     return  hostname;
//    // } // End of method //
//
//    void parse_url (const std::string &url, const std::string &orig_host)
//    {
//        const boost::regex re ("(?i)https?://(?:www\.)?([^/]+)(.*)");
//        boost::smatch what;
//        if ( boost::regex_match (url, what, re))
//        {
//            // We found a full URL, parse out the 'hostname'
//            // Then parse out the page
//            hostname = what[1];
//            boost::algorithm::to_lower (hostname);
//            path = what[2];
//        }
//        else
//        {
//            // We could not find the 'page' but we can build the hostname
//            hostname = orig_host;
//            page = "";
//        } // End of the if - else //
//    } // End of method //
//
//    void parse (const std::string &url, const std::string &altern_host)
//    {
//        const std::string host = parse_url (hrf);
//        if ( !hst.empty ())
//        {
//            // If we have a HTTP prefix
//            // We could end up with a 'hostname' and page
//            parseHref (hst, hrf);
//        } else
//        {
//            hostname = orig_host;
//            page = hrf;
//        }
//        // hostname and page are constructed,
//        // perform post analysis
//        if ( page.length () == 0 )
//        {
//            page = "/";
//        } // End of the if //
//    } // End of the method
//}; // End of the class
//
//
//std::string string_format (const std::string &fmt, ...)
//{
//    int size = 255;
//    std::string str;
//    va_list ap;
//    while ( 1 )
//    {
//        str.resize (size);
//        va_start(ap, fmt);
//        int n = vsnprintf ((char *) str.c_str (), size, fmt.c_str (), ap);
//        va_end(ap);
//        if ( n > -1 && n < size )
//        {
//            str.resize (n);
//            return str;
//        }
//        if ( n > -1 )
//            size = n + 1;
//        else
//            size *= 2;
//    } // End of the while //
//    return str;
//} // End of the function //

extern "C"
{
bool  socket_connect_and_receive (const char *host, int port,
                                  const std::string *request,
                                  std::string *responce)
{
    bool result = false;

    int on = 1;
    int status = -1;
    // Setup the m_sock
    int          m_sock;
    sockaddr_in  m_addr;
    memset (&m_addr, 0, sizeof (m_addr));

    // struct addrinfo *ai;
    // struct addrinfo hints;
    // memset (&hints, 0, sizeof (struct addrinfo));
    // hints.ai_family   = AF_UNSPEC;
    // hints.ai_socktype = SOCK_STREAM;
    // hints.ai_protocol = IPPROTO_TCP;

    if ( m_sock = (int)socket (AF_INET, SOCK_STREAM, 0) < 0)
    {
        syslog (LOG_ERR, "ERROR opening socket.");
        result = true;
        goto FREE;
    }

    // struct hostent *server = gethostbyname (host);
    // if (server == NULL) {
    //    syslog (LOG_ERR, "ERROR, no such host\n");
    //    result = true;
    //    goto FREE;
    //}

    if ( -1  == setsockopt (m_sock, SOL_SOCKET, SO_REUSEADDR,
                            (const char *) &on, sizeof (on)) )
    {
        syslog (LOG_ERR, "ERROR setsockopt is failed");
        result = true;
        goto FREE;
    }
    // { throw wgetConnectErrorException (); }

    // Connect //
    m_addr.sin_family = AF_INET;
    m_addr.sin_port = htons (port);

    status = inet_pton (AF_INET, host, &m_addr.sin_addr);
    if ( errno == EAFNOSUPPORT )
    {
        syslog (LOG_ERR, "ERROR EAFNOSUPPORT");
        result = true;
        goto FREE;
    }
    // { throw wgetNotSupportException (); }

    status = (int)::connect (m_sock, (sockaddr *) &m_addr, sizeof (m_addr));
    if (status < 0)
    {
        syslog (LOG_ERR, "ERROR connecting");
        result = true;
        goto FREE;
    }

    syslog (LOG_INFO, "CONNETCTED");

    status = (int)::send (m_sock, request->c_str (), request->size (), MSG_NOSIGNAL);
    if (status < 0)
    {
        syslog (LOG_ERR, "ERROR sendng GET request.");
        result = true;
        goto FREE;
    }

    syslog (LOG_INFO, "GET %s HTTP/1.1\r\n", host);

    // RECEIVING ....
    char buf[MAXRECV];
    while ( status != 0 )
    {
        memset (buf, 0, MAXRECV);
        status = (int)::recv (m_sock, buf, MAXRECV, 0);
        if (status < 0)
        {
            syslog (LOG_ERR, "ERROR receiving from socket");
            result = true;
            goto FREE;
        }
        responce->append (buf);
    } // End of the while //

FREE:;
    close  (m_sock);
    syslog (LOG_INFO, "CONNETCTION CLOSED");
    return false;
} // End of the function //
}

std::string  wget::formGetRequest  (IN const uri::uri &url)
{
    std::string request = "GET ";

    request.append (url.path ());
    request.append (" HTTP/1.1\r\n");
    request.append ("Host: ");
    request.append (url.host ());
    request.append ("\r\n");
    request.append ("Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.81\r\n");
    request.append (
            "User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:53.0) Gecko/20100101 Firefox/53.0;)\r\n");
    // http://code.google.com/p/octane-crawler/
    request.append ("Connection: close\r\n");
    request.append ("\r\n");
    return request;
} // End of the function //

std::string  wget::formOutFileName (IN const uri::uri &url)
{
    std::string filename;
    const boost::regex rmv_all ("[^a-zA-Z0-9]+");
    filename = boost::regex_replace (url.host () + url.path (), rmv_all, "_");

    if ( boost::starts_with (filename, "_"))
        filename = filename.substr (1, filename.size ());

    if ( boost::ends_with (filename, "_"))
        filename = filename.substr (0, filename.size () - 1);
    return  filename;
} // End of the function //

void  wget::dumpOutFile (IN const std::string &filename,
                         IN const std::string &responce)
{
    fs::path fn (filename);
    fs::path path = saveDir / fn;

    std::ofstream  outFile (path.c_str ());
    outFile << responce << std::endl;
    outFile.close ();
} // End of the function //

void  wget::connect  (const uri::uri &url)
{
    boost::asio::io_service io_service ;
    boost::asio::ip::tcp::resolver resolver(io_service) ;

    boost::asio::ip::tcp::resolver::query query (url.string (), "http");
    boost::asio::ip::tcp::resolver::iterator iter = resolver.resolve (query);
    boost::asio::ip::tcp::resolver::iterator end;
    boost::asio::ip::tcp::endpoint endpoint;
    while (iter != end)
    {
        endpoint = *iter++;
        std::cout << endpoint << std::endl;
    }

    boost::asio::ip::tcp::socket socket(io_service);
    socket.connect(endpoint);

    boost::asio::streambuf  request;
    std::ostream  request_stream (&request);
    request_stream << "GET / HTTP/1.0\r\n";
    request_stream << "Host: localhost \r\n";
    request_stream << "Accept: */*\r\n";
    request_stream << "Connection: close\r\n\r\n";

    boost::asio::write(socket, request);

    boost::asio::streambuf header;
    boost::asio::read_until (socket, header, "\r\n\r\n");

    // std::cout << &response << std::endl;

}

void  wget::download (const uri::uri &url,
                      const int  port,
                      const int  depth,
                      const bool continueDump,
                      const bool verbose)
{
    if ( depth > 0 )
    {
        // HTTP/1.1 defines the "close" connection option for
        // the sender to signal that the connection will be closed
        // after completion of the response.
        std::string request = formGetRequest (url);

        if ( verbose )
        {
            std::cout << "Request: " << request << std::endl;
            std::cout << "=========================" << std::endl;
        }

        // End of building the request //
        std::string responce;
        const char *host = url.host ().c_str ();

        int status = 0;
        int these_tries = tries;
        do
        {
            status = socket_connect_and_receive (host, port, &request, &responce);
        }
        while ( status && --these_tries );
        // { throw wgetException (); }

        crawled.insert (url.string ());

        if ( verbose )
        {
            std::cout << "Response:" << responce << std::endl;
            std::cout << "---------------------------" << std::endl;

        }

        std::string filename = formOutFileName (url);
        dumpOutFile (filename, responce);

        if ( verbose )
        { std::cout << "Writing to file : " << filename << std::endl; }

        if ( recursive && depth > 1 )
        {
            parseHTML (responce, urls);

            if ( noParent )
            {
                // parent
                std::string parentURL = url.string ();
                boost::algorithm::to_lower (parentURL);
                std::string  parentURLescaped = escape_string (parentURL);
                boost::regex parentRgx ("^" + parentURLescaped);

                for ( auto it = begin (urls); it != end (urls); )
                {
                    // std::string  &url = *it;
                    if ( !boost::regex_match (*it, parentRgx) )
                    { it = urls.erase (it); } // previously this was something like m_map.erase(it++);
                    else
                    { ++it; }
                }
            }

            if ( verbose )
            {
                std::cout << "---------------------------" << std::endl;
                std::cout << "Serch for urls in html : " << std::endl;

                for ( auto url : urls )
                    std::cout << url << std::endl;
                getchar ();
            }

            for ( auto url : urls )
            {
                if ( crawled.find (url) != crawled.end ())
                {
                    sleep (delay);
                    download (uri::uri (url), depth - 1, delay);
                    // crawled.insert (url);
                }
            }
        } // end if reucsive
    } // end if depth
} // End of the function //

void wget::fetch (IN  const uri::uri     &url,
                  IN        int           port,
                  IN  const std::string  &request,
                  OUT       std::string  &responce)
{
    try
    {
        boost::asio::ip::tcp::iostream  net_stream (url.string (), "http");
        net_stream.expires_from_now (boost::posix_time::seconds (60));

        if ( !net_stream )
        { throw "Unable to connect: " + net_stream.error ().message (); }

        syslog (LOG_INFO, "CONNECTED");

        // ask for the file
        net_stream << "GET " << url.path () << " HTTP/1.0\r\n";
        net_stream << "Host: " << url.host () << "\r\n";
        net_stream << "Accept: */*\r\n";
        net_stream << "Connection: close\r\n\r\n";

        // Check that response is OK.
        std::string   http_version;
        net_stream >> http_version;

        unsigned int  status_code;
        net_stream >> status_code;
        std::string   status_message;
        std::getline (net_stream, status_message);

        if ( !net_stream && http_version.substr (0, 5) != "HTTP/" )
        { throw "Invalid response\n"; }

        if (status_code != 200)
        { throw "Response returned with status code " + status_code; }

        // Process the response headers, which are terminated by a blank line.
        std::string header;
        while (std::getline (net_stream, header) && header != "\r") {}

        // Write the remaining data to output.
        std::stringstream ss;
        ss << net_stream.rdbuf();
        responce = ss.str();
    }
    catch (std::exception& e)
    { syslog (LOG_ERR, e.what ()); }
}
<commit_msg>del comments<commit_after>#include "../wget/crawler.h"
namespace uri = boost::network::uri;
namespace  fs = boost::filesystem;

extern "C"
{
bool  socket_connect_and_receive (const char *host, int port,
                                  const std::string *request,
                                  std::string *responce)
{
    bool result = false;

    int on = 1;
    int status = -1;
    // Setup the m_sock
    int          m_sock;
    sockaddr_in  m_addr;
    memset (&m_addr, 0, sizeof (m_addr));

    // struct addrinfo *ai;
    // struct addrinfo hints;
    // memset (&hints, 0, sizeof (struct addrinfo));
    // hints.ai_family   = AF_UNSPEC;
    // hints.ai_socktype = SOCK_STREAM;
    // hints.ai_protocol = IPPROTO_TCP;

    if ( m_sock = (int)socket (AF_INET, SOCK_STREAM, 0) < 0)
    {
        syslog (LOG_ERR, "ERROR opening socket.");
        result = true;
        goto FREE;
    }

    // struct hostent *server = gethostbyname (host);
    // if (server == NULL) {
    //    syslog (LOG_ERR, "ERROR, no such host\n");
    //    result = true;
    //    goto FREE;
    //}

    if ( -1  == setsockopt (m_sock, SOL_SOCKET, SO_REUSEADDR,
                            (const char *) &on, sizeof (on)) )
    {
        syslog (LOG_ERR, "ERROR setsockopt is failed");
        result = true;
        goto FREE;
    }
    // { throw wgetConnectErrorException (); }

    // Connect //
    m_addr.sin_family = AF_INET;
    m_addr.sin_port = htons (port);

    status = inet_pton (AF_INET, host, &m_addr.sin_addr);
    if ( errno == EAFNOSUPPORT )
    {
        syslog (LOG_ERR, "ERROR EAFNOSUPPORT");
        result = true;
        goto FREE;
    }
    // { throw wgetNotSupportException (); }

    status = (int)::connect (m_sock, (sockaddr *) &m_addr, sizeof (m_addr));
    if (status < 0)
    {
        syslog (LOG_ERR, "ERROR connecting");
        result = true;
        goto FREE;
    }

    syslog (LOG_INFO, "CONNETCTED");

    status = (int)::send (m_sock, request->c_str (), request->size (), MSG_NOSIGNAL);
    if (status < 0)
    {
        syslog (LOG_ERR, "ERROR sendng GET request.");
        result = true;
        goto FREE;
    }

    syslog (LOG_INFO, "GET %s HTTP/1.1\r\n", host);

    // RECEIVING ....
    char buf[MAXRECV];
    while ( status != 0 )
    {
        memset (buf, 0, MAXRECV);
        status = (int)::recv (m_sock, buf, MAXRECV, 0);
        if (status < 0)
        {
            syslog (LOG_ERR, "ERROR receiving from socket");
            result = true;
            goto FREE;
        }
        responce->append (buf);
    } // End of the while //

FREE:;
    close  (m_sock);
    syslog (LOG_INFO, "CONNETCTION CLOSED");
    return false;
} // End of the function //
}

std::string  wget::formGetRequest  (IN const uri::uri &url)
{
    std::string request = "GET ";
    request.append (url.path ());
    request.append (" HTTP/1.1\r\n");
    request.append ("Host: ");
    request.append (url.host ());
    request.append ("\r\n");
    request.append ("Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.81\r\n");
    request.append ("User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:53.0) Gecko/20100101 Firefox/53.0;)\r\n");
    request.append ("Connection: close\r\n");
    request.append ("\r\n");
    return request;
} // End of the function //

std::string  wget::formOutFileName (IN const uri::uri &url)
{
    std::string filename;
    const boost::regex rmv_all ("[^a-zA-Z0-9]+");
    filename = boost::regex_replace (url.host () + url.path (), rmv_all, "_");

    if ( boost::starts_with (filename, "_"))
        filename = filename.substr (1, filename.size ());

    if ( boost::ends_with (filename, "_"))
        filename = filename.substr (0, filename.size () - 1);
    return  filename;
} // End of the function //

void  wget::dumpOutFile (IN const std::string &filename,
                         IN const std::string &responce)
{
    fs::path fn (filename);
    fs::path path = saveDir / fn;

    std::ofstream  outFile (path.c_str ());
    outFile << responce << std::endl;
    outFile.close ();
} // End of the function //

void  wget::connect  (const uri::uri &url)
{
    boost::asio::io_service io_service ;
    boost::asio::ip::tcp::resolver resolver(io_service) ;

    boost::asio::ip::tcp::resolver::query query (url.string (), "http");
    boost::asio::ip::tcp::resolver::iterator iter = resolver.resolve (query);
    boost::asio::ip::tcp::resolver::iterator end;
    boost::asio::ip::tcp::endpoint endpoint;
    while (iter != end)
    {
        endpoint = *iter++;
        std::cout << endpoint << std::endl;
    }

    boost::asio::ip::tcp::socket socket(io_service);
    socket.connect(endpoint);

    boost::asio::streambuf  request;
    std::ostream  request_stream (&request);
    request_stream << "GET / HTTP/1.0\r\n";
    request_stream << "Host: localhost \r\n";
    request_stream << "Accept: */*\r\n";
    request_stream << "Connection: close\r\n\r\n";

    boost::asio::write(socket, request);

    boost::asio::streambuf header;
    boost::asio::read_until (socket, header, "\r\n\r\n");

    // std::cout << &response << std::endl;

}

void  wget::download (const uri::uri &url,
                      const int  port,
                      const int  depth,
                      const bool continueDump,
                      const bool verbose)
{
    if ( depth > 0 )
    {
        // HTTP/1.1 defines the "close" connection option for
        // the sender to signal that the connection will be closed
        // after completion of the response.
        std::string request = formGetRequest (url);

        if ( verbose )
        {
            std::cout << "Request: " << request << std::endl;
            std::cout << "=========================" << std::endl;
        }

        // End of building the request //
        std::string responce;
        const char *host = url.host ().c_str ();

        int status = 0;
        int these_tries = tries;
        do
        {
            status = socket_connect_and_receive (host, port, &request, &responce);
        }
        while ( status && --these_tries );
        // { throw wgetException (); }

        crawled.insert (url.string ());

        if ( verbose )
        {
            std::cout << "Response:" << responce << std::endl;
            std::cout << "---------------------------" << std::endl;

        }

        std::string filename = formOutFileName (url);
        dumpOutFile (filename, responce);

        if ( verbose )
        { std::cout << "Writing to file : " << filename << std::endl; }

        if ( recursive && depth > 1 )
        {
            parseHTML (responce, urls);

            if ( noParent )
            {
                // parent
                std::string parentURL = url.string ();
                boost::algorithm::to_lower (parentURL);
                std::string  parentURLescaped = escape_string (parentURL);
                boost::regex parentRgx ("^" + parentURLescaped);

                for ( auto it = begin (urls); it != end (urls); )
                {
                    // std::string  &url = *it;
                    if ( !boost::regex_match (*it, parentRgx) )
                    { it = urls.erase (it); } // previously this was something like m_map.erase(it++);
                    else
                    { ++it; }
                }
            }

            if ( verbose )
            {
                std::cout << "---------------------------" << std::endl;
                std::cout << "Serch for urls in html : " << std::endl;

                for ( auto url : urls )
                    std::cout << url << std::endl;
                getchar ();
            }

            for ( auto url : urls )
            {
                if ( crawled.find (url) != crawled.end ())
                {
                    sleep (delay);
                    download (uri::uri (url), depth - 1, delay);
                    // crawled.insert (url);
                }
            }
        } // end if reucsive
    } // end if depth
} // End of the function //

void wget::fetch (IN  const uri::uri     &url,
                  IN        int           port,
                  IN  const std::string  &request,
                  OUT       std::string  &responce)
{
    try
    {
        boost::asio::ip::tcp::iostream  net_stream (url.string (), "http");
        net_stream.expires_from_now (boost::posix_time::seconds (60));

        if ( !net_stream )
        { throw "Unable to connect: " + net_stream.error ().message (); }

        syslog (LOG_INFO, "CONNECTED");

        // ask for the file
        net_stream << "GET " << url.path () << " HTTP/1.0\r\n";
        net_stream << "Host: " << url.host () << "\r\n";
        net_stream << "Accept: */*\r\n";
        net_stream << "Connection: close\r\n\r\n";

        // Check that response is OK.
        std::string   http_version;
        net_stream >> http_version;

        unsigned int  status_code;
        net_stream >> status_code;
        std::string   status_message;
        std::getline (net_stream, status_message);

        if ( !net_stream && http_version.substr (0, 5) != "HTTP/" )
        { throw "Invalid response\n"; }

        if (status_code != 200)
        { throw "Response returned with status code " + status_code; }

        // Process the response headers, which are terminated by a blank line.
        std::string header;
        while (std::getline (net_stream, header) && header != "\r") {}

        // Write the remaining data to output.
        std::stringstream ss;
        ss << net_stream.rdbuf();
        responce = ss.str();
    }
    catch (std::exception& e)
    { syslog (LOG_ERR, e.what ()); }
}
<|endoftext|>


<commit_before>#include <boost/test/unit_test.hpp>

#include "test_element.h"
#include "clotho/powerset/variable_subset.hpp"

typedef clotho::powersets::variable_subset< test_element > subset_type;
typedef typename subset_type::powerset_type powerset_type;
typedef powerset_type::block_map_type bmap;

BOOST_AUTO_TEST_SUITE( test_powerset )

/**
 * Create an empty powerset
 *
 * Manually append element to powerset
 * Verify that new element is assigned to expected index
 *
 * Verify allocated size
 */
BOOST_AUTO_TEST_CASE( create_powerset_append) {
    powerset_type ps;

    typename powerset_type::element_index_type idx = ps.appendElement( test_element( 0., 1.0) );
    BOOST_REQUIRE_MESSAGE( idx == 0, "Unexpected index " << idx << " returned for " << 0 << "(" << 0 << ")" );
    BOOST_REQUIRE_MESSAGE( ps.variable_allocated_size() == bmap::bits_per_block, "Unexpected variable space: " << ps.variable_allocated_size() );
}

/**
 * Create an empty powerset
 *
 * Manually add element to powerset (results in append)
 * Verify that new element is assigned to expected index
 *
 * Verify allocated size
 */
BOOST_AUTO_TEST_CASE( create_powerset_add) {

    powerset_type ps;

    typename powerset_type::element_index_type idx = ps.addElement( test_element( 0., 1.0) );
    BOOST_REQUIRE_MESSAGE( idx == 0, "Unexpected index " << idx << " returned for " << 0 << "(" << 0 << ")" );

    BOOST_REQUIRE_MESSAGE( ps.size() == 1, "Unexpected size" );
    BOOST_REQUIRE_MESSAGE( ps.variable_allocated_size() == bmap::bits_per_block, "Unexpected variable space: " << ps.variable_allocated_size() );
}

/**
 * Create an empty powerset
 *
 * Manually append first element to powerset
 * Verify that new element is assigned to expected index
 *
 * add the remaining elements of a block
 * Verify that each new element is assigned to expected index
 *
 * Verify allocated size
 */
BOOST_AUTO_TEST_CASE( create_powerset_width ) {
    powerset_type ps;

    BOOST_REQUIRE_MESSAGE( ps.empty(), "Unexpected size" );

    typename powerset_type::element_index_type idx = ps.appendElement( test_element( 0., 1.0) );
    BOOST_REQUIRE_MESSAGE( idx == 0, "Unexpected index " << idx << " returned for " << 0 << "(" << 0 << ")" );

    BOOST_REQUIRE_MESSAGE( ps.variable_allocated_size() == bmap::bits_per_block, "Unexpected variable space: " << ps.variable_allocated_size() );

    for( unsigned int i = 1; i < bmap::bits_per_block; ++i ) {
        double v = (double) i;
        double k = v / (double) bmap::bits_per_block;
        test_element te(k, 1.0);

        typename powerset_type::element_index_type e_idx = ps.findFreeIndex(te);

        BOOST_REQUIRE_MESSAGE( e_idx == i, e_idx << " != " << i );

        typename powerset_type::element_index_type idx = ps.addElement(te);

        BOOST_REQUIRE_MESSAGE( idx == i, "Unexpected index " << idx << " returned for " << i << "(" << k << "; " << e_idx << ")" );
    }

    const unsigned int bpb = bmap::bits_per_block;
    BOOST_REQUIRE_MESSAGE( ps.variable_allocated_size() == bpb, "Unexpected size: " << ps.variable_allocated_size() << "(" << bpb << ")" );
}

/**
 * Create an empty powerset
 *
 * find_or_create elements in a round robin order.
 * Verify that each new element is assigned to expected index
 */
BOOST_AUTO_TEST_CASE( create_powerset_find_or_create_unique ) {
    powerset_type ps;

    const unsigned int sub_div = 3;
    const double div_offset = (1.0/ ((double)sub_div*bmap::bits_per_block));

    for( unsigned int i = 0; i < sub_div * bmap::bits_per_block; ++i ) {
        double v = (double) (i % bmap::bits_per_block);

        unsigned int s = (i / bmap::bits_per_block );

        double k = v / (double) bmap::bits_per_block + (double)s*div_offset;
        test_element te(k, 1.0);

        typename powerset_type::element_index_type idx = ps.find_or_create(te);

        BOOST_REQUIRE_MESSAGE( idx == i, "Unexpected index " << idx << " returned for " << i << "(" << k << ")" );
    }

    const unsigned int bpb = sub_div * bmap::bits_per_block;
    BOOST_REQUIRE_MESSAGE( ps.variable_allocated_size() == bpb, "Unexpected size: " << ps.variable_allocated_size() << "(" << bpb << ")" );
}

/**
 * Create an empty powerset
 *
 * find_or_create an element to the powerset (results in create)
 *
 * Verify that it is in expected position
 *
 * find_or_create different element with same key (results in find)
 *
 * Verify that element index returned is same as earlier element.
 */
BOOST_AUTO_TEST_CASE( create_powerset_find_or_create_collision ) {
    powerset_type ps;

    double k = 0.5;
    test_element te(k, 1.0);
    typename powerset_type::element_index_type idx = ps.find_or_create(te);
    BOOST_REQUIRE_MESSAGE( idx == bmap()(te), "Unexpected index " << idx << " returned for " << 0 << "(" << k << ")" );

    test_element te2(k, 2.0);
    typename powerset_type::element_index_type cidx = ps.find_or_create(te2);
    BOOST_REQUIRE_MESSAGE( cidx == idx, "Unexpected index " << idx << " returned for " << cidx << "(" << k << ")" );
}

/**
 * Create an empty powerset
 *
 * find_or_create elements in a bit position order.
 * Every element after the first in each sub-division should result in a collision.
 *
 * Verify that each new element is assigned to expected index
 */
BOOST_AUTO_TEST_CASE( create_powerset_find_or_create_order_collision ) {
    powerset_type ps;

    const unsigned int sub_div = 3;
    const double div_offset = (1.0/ ((double)sub_div*bmap::bits_per_block));

    for( unsigned int i = 0; i < bmap::bits_per_block; ++i ) {
        for( unsigned int j = 0; j < sub_div; ++j ) {
            double v = (double)i;
            double k = v / (double) bmap::bits_per_block + (double)j*div_offset;

            test_element te(k, 1.0);

            unsigned int e_idx = i + j * bmap::bits_per_block;
            typename powerset_type::element_index_type idx = ps.find_or_create(te);

            BOOST_REQUIRE_MESSAGE( idx == e_idx, "Unexpected index " << idx << " returned for " << e_idx << "(" << k << ")" );
        }
    }

    const unsigned int e_size = sub_div * bmap::bits_per_block;
    BOOST_REQUIRE_MESSAGE( ps.variable_allocated_size() == e_size, "Unexpected size: " << ps.variable_allocated_size() << "(" << e_size << ")" );
}

/**
 * Creates a subset of the powerset
 *
 * Verify that subset was added to family
 *
 * Adds a element
 *
 * Checks that element has been added to the set and subset
 * Checks subset count
 * Verifies expected sizes
 * Verifies expected bit state
 *
 * Removes earlier element
 * Checks subset count
 * Checks element bit state
 */
BOOST_AUTO_TEST_CASE( create_powerset_subset ) {
    powerset_type ps;

    typename powerset_type::subset_ptr c = ps.create_subset();

    BOOST_REQUIRE_MESSAGE( ps.family_size() == 1, "Subset was not added to family");

    double k = 0.5;
    test_element te(k, 1.0);

    c->addElement( te );

    size_t cnt = c->count();
    BOOST_REQUIRE_MESSAGE( cnt == 1, "Element has not been added to the subset: " << cnt << "(1)" );

    const unsigned int bpb = bmap::bits_per_block;
    BOOST_REQUIRE_MESSAGE( ps.variable_allocated_size() == bpb, "Unexpected size: " << ps.variable_allocated_size() << "(" << bpb << ")" );

    typename powerset_type::element_index_type idx = ps.find_or_create(te);
    BOOST_REQUIRE_MESSAGE( idx == bmap()(te), "Unexpected index " << idx << " returned for " << 0 << "(" << k << ")" );

    BOOST_REQUIRE_MESSAGE( c->check_state( idx ), "Unexpected state for element after add" );

    c->removeElement( te );

    cnt = c->count();
    BOOST_REQUIRE_MESSAGE( cnt == 0, "Element has not been removed to the subset: " << cnt << "(0)" );
    BOOST_REQUIRE_MESSAGE( !c->check_state( idx ), "Unexpected state for element after remove" );
}

/**
 * Create a powerset
 *
 * Create a subset with one element in it, in a sub-scope;
 * Assuming subset_ptr is a shared_ptr, the change in scope should dereference
 * a single instance to the subset, leaving a single instance of the subset
 * in the family.  If the family contains only a single instance of a subset,
 * prune the powerset should remove the subset, and free up lost|fixed
 * elements.
 *
 */
BOOST_AUTO_TEST_CASE( create_powerset_prunespace ) {
    powerset_type ps;

    // change in scope should release one instance of subset_ptr
    {
        typename powerset_type::subset_ptr c = ps.create_subset();

        double k = 0.5;
        test_element te(k, 1.0);

        c->addElement( te );
    }

    BOOST_REQUIRE_MESSAGE( ps.family_size() == 1, "Subset was not added to family");

    const unsigned int bpb = bmap::bits_per_block;
    size_t fs = ps.free_size();
    BOOST_REQUIRE_MESSAGE( fs == (bpb - 1), "Unexpected free size " << fs << "(" << (bpb - 1) << ")" );
    BOOST_REQUIRE_MESSAGE( ps.variable_allocated_size() == bpb, "Unexpected size: " << ps.variable_allocated_size() << "(" << bpb << ")" );

    ps.pruneSpace();

    BOOST_REQUIRE_MESSAGE( ps.family_size() == 0, "Subset was not removed from family");

    fs = ps.free_size();
    BOOST_REQUIRE_MESSAGE( fs == bpb, "Unexpected free size " << fs << "(" << bpb << ")" );
}

/**
 * Create a powerset
 *
 * Create a subset with one element in it, in a sub-scope;
 * Create a second subset with the same element (a duplicate of the first subset)
 *
 * As before the first subset should be dereferenced, and will be removed from
 * the family.  The second subset, however, will not because two references to the
 * subset should exist (one in this scope, and one in the family).
 *
 * Therefore, pruning the powerset space should result in the subsets being
 * reduced to 1.  Furthermore, since there is a single subset, with a single
 * element, that element becomes fixed within the powerset.  The fixed element
 * should be copied to the fixed subset, and its positions should be freed
 *
 */
BOOST_AUTO_TEST_CASE( create_powerset_prunespace2 ) {
    powerset_type ps;

    double k = 0.5;
    test_element te(k, 1.0);

    // change in scope should release one instance of subset_ptr
    {
        typename powerset_type::subset_ptr c = ps.create_subset();

        c->addElement( te );
    }

    typename powerset_type::subset_ptr c2 = ps.create_subset();
    c2->addElement(te);

    BOOST_REQUIRE_MESSAGE( ps.family_size() == 2, "Subset was not added to family");

    typename powerset_type::element_index_type idx = ps.find_or_create(te);

    const unsigned int bpb = bmap::bits_per_block;
    size_t fs = ps.free_size();
    BOOST_REQUIRE_MESSAGE( fs == (bpb - 1), "Unexpected free size " << fs << "(" << (bpb - 1) << ")" );
    BOOST_REQUIRE_MESSAGE( ps.variable_allocated_size() == bpb, "Unexpected size: " << ps.variable_allocated_size() << " (" << bpb << ")" );

    ps.pruneSpace();

    fs = ps.free_size();
    BOOST_REQUIRE_MESSAGE( ps.family_size() == 1, "Expected subset was not removed from family " << ps.family_size() << " (1)" );
    BOOST_REQUIRE_MESSAGE( fs == bpb, "Unexpected free size " << fs << " (" << bpb << ")" );
    BOOST_REQUIRE_MESSAGE( ps.fixed_size() == 1, "Unexpected fixed size " << ps.fixed_size() << " (1)");

    typename powerset_type::element_index_type idx2 = ps.find_or_create(te);
    BOOST_REQUIRE_MESSAGE( idx != idx2, "After pruning, fixed element has same index.  Should be different");

    BOOST_REQUIRE_MESSAGE( idx2 == ps.encode_index(0, true), "Unxpected fixed index " << idx2 << " (" << ps.encode_index(0, true) << ")");

    bool is_fixed  = ps.decode_index(idx2);
    BOOST_REQUIRE_MESSAGE( is_fixed, "Unexpected state decoding false (true)" );
    BOOST_REQUIRE_MESSAGE( idx2 == 0, "Unexpected index decoded " << idx2 << " (0)");
}
BOOST_AUTO_TEST_SUITE_END()
<commit_msg>changed block_map to be user_defined; added manual calls to updateFreeIndex<commit_after>#include <boost/test/unit_test.hpp>

#include "test_element.h"
#include "clotho/powerset/variable_subset.hpp"

typedef unsigned long Block;

typedef clotho::powersets::block_map< test_element, Block, clotho::powersets::user_defined > bmap;
typedef clotho::powersets::variable_subset< test_element, Block, bmap > subset_type;
typedef typename subset_type::powerset_type powerset_type;

BOOST_AUTO_TEST_SUITE( test_powerset )

/**
 * Create an empty powerset
 *
 * Manually append element to powerset
 * Verify that new element is assigned to expected index
 *
 * Verify allocated size
 */
BOOST_AUTO_TEST_CASE( create_powerset_append) {
    powerset_type ps;

    typename powerset_type::element_index_type idx = ps.appendElement( test_element( 0., 1.0) );

    BOOST_REQUIRE_MESSAGE( idx == 0, "Unexpected index " << idx << " returned for " << 0 << "(" << 0 << ")" );
    BOOST_REQUIRE_MESSAGE( ps.variable_allocated_size() == bmap::bits_per_block, "Unexpected variable space: " << ps.variable_allocated_size() );

    ps.updateFreeIndex( idx, false );
    BOOST_REQUIRE_MESSAGE( ps.free_size() == (bmap::bits_per_block - 1), "Unexpected number of free space: " << ps.free_size() );
}

/**
 * Create an empty powerset
 *
 * Manually add element to powerset (results in append)
 * Verify that new element is assigned to expected index
 *
 * Verify allocated size
 */
BOOST_AUTO_TEST_CASE( create_powerset_add) {

    powerset_type ps;

    typename powerset_type::element_index_type idx = ps.addElement( test_element( 0., 1.0) );
    BOOST_REQUIRE_MESSAGE( idx == 0, "Unexpected index " << idx << " returned for " << 0 << "(" << 0 << ")" );

    BOOST_REQUIRE_MESSAGE( ps.size() == 1, "Unexpected size" );
    BOOST_REQUIRE_MESSAGE( ps.variable_allocated_size() == bmap::bits_per_block, "Unexpected variable space: " << ps.variable_allocated_size() );
}

/**
 * Create an empty powerset
 *
 * Manually append first element to powerset
 * Verify that new element is assigned to expected index
 *
 * add the remaining elements of a block
 * Verify that each new element is assigned to expected index
 *
 * Verify allocated size
 */
BOOST_AUTO_TEST_CASE( create_powerset_width ) {
    powerset_type ps;

    BOOST_REQUIRE_MESSAGE( ps.empty(), "Unexpected size" );

    typename powerset_type::element_index_type idx = ps.appendElement( test_element( 0., 1.0) );

    BOOST_REQUIRE_MESSAGE( idx == 0, "Unexpected index " << idx << " returned for " << 0 << "(" << 0 << ")" );
    BOOST_REQUIRE_MESSAGE( ps.variable_allocated_size() == bmap::bits_per_block, "Unexpected variable space: " << ps.variable_allocated_size() );

    ps.updateFreeIndex( idx, false );
    BOOST_REQUIRE_MESSAGE( ps.free_size() == (bmap::bits_per_block - 1), "Unexpected number of free space: " << ps.free_size() );

    for( unsigned int i = 1; i < bmap::bits_per_block; ++i ) {
        double v = (double) i;
        double k = v / (double) bmap::bits_per_block;
        test_element te(k, 1.0);

        typename powerset_type::element_index_type e_idx = ps.findFreeIndex(te);

        BOOST_REQUIRE_MESSAGE( e_idx == i, e_idx << " != " << i );

        typename powerset_type::element_index_type idx = ps.addElement(te);

        BOOST_REQUIRE_MESSAGE( idx == i, "Unexpected index " << idx << " returned for " << i << "(" << k << "; " << e_idx << ")" );
    }

    const unsigned int bpb = bmap::bits_per_block;
    BOOST_REQUIRE_MESSAGE( ps.variable_allocated_size() == bpb, "Unexpected size: " << ps.variable_allocated_size() << "(" << bpb << ")" );
}

/**
 * Create an empty powerset
 *
 * find_or_create elements in a round robin order.
 * Verify that each new element is assigned to expected index
 */
BOOST_AUTO_TEST_CASE( create_powerset_find_or_create_unique ) {
    powerset_type ps;

    const unsigned int sub_div = 3;
    const double div_offset = (1.0/ ((double)sub_div*bmap::bits_per_block));

    for( unsigned int i = 0; i < sub_div * bmap::bits_per_block; ++i ) {
        double v = (double) (i % bmap::bits_per_block);

        unsigned int s = (i / bmap::bits_per_block );

        double k = v / (double) bmap::bits_per_block + (double)s*div_offset;
        test_element te(k, 1.0);

        typename powerset_type::element_index_type idx = ps.find_or_create(te);

        BOOST_REQUIRE_MESSAGE( idx == i, "Unexpected index " << idx << " returned for " << i << "(" << k << ")" );
    }

    const unsigned int bpb = sub_div * bmap::bits_per_block;
    BOOST_REQUIRE_MESSAGE( ps.variable_allocated_size() == bpb, "Unexpected size: " << ps.variable_allocated_size() << "(" << bpb << ")" );
}

/**
 * Create an empty powerset
 *
 * find_or_create an element to the powerset (results in create)
 *
 * Verify that it is in expected position
 *
 * find_or_create different element with same key (results in find)
 *
 * Verify that element index returned is same as earlier element.
 */
BOOST_AUTO_TEST_CASE( create_powerset_find_or_create_collision ) {
    powerset_type ps;

    double k = 0.5;
    test_element te(k, 1.0);
    typename powerset_type::element_index_type idx = ps.find_or_create(te);
    BOOST_REQUIRE_MESSAGE( idx == bmap()(te), "Unexpected index " << idx << " returned for " << 0 << "(" << k << ")" );

    test_element te2(k, 2.0);
    typename powerset_type::element_index_type cidx = ps.find_or_create(te2);
    BOOST_REQUIRE_MESSAGE( cidx == idx, "Unexpected index " << idx << " returned for " << cidx << "(" << k << ")" );
}

/**
 * Create an empty powerset
 *
 * find_or_create elements in a bit position order.
 * Every element after the first in each sub-division should result in a collision.
 *
 * Verify that each new element is assigned to expected index
 */
BOOST_AUTO_TEST_CASE( create_powerset_find_or_create_order_collision ) {
    powerset_type ps;

    const unsigned int sub_div = 3;
    const double div_offset = (1.0/ ((double)sub_div*bmap::bits_per_block));

    for( unsigned int i = 0; i < bmap::bits_per_block; ++i ) {
        for( unsigned int j = 0; j < sub_div; ++j ) {
            double v = (double)i;
            double k = v / (double) bmap::bits_per_block + (double)j*div_offset;

            test_element te(k, 1.0);

            unsigned int e_idx = i + j * bmap::bits_per_block;
            typename powerset_type::element_index_type idx = ps.find_or_create(te);

            BOOST_REQUIRE_MESSAGE( idx == e_idx, "Unexpected index " << idx << " returned for " << e_idx << "(" << k << ")" );
        }
    }

    const unsigned int e_size = sub_div * bmap::bits_per_block;
    BOOST_REQUIRE_MESSAGE( ps.variable_allocated_size() == e_size, "Unexpected size: " << ps.variable_allocated_size() << "(" << e_size << ")" );
}

/**
 * Creates a subset of the powerset
 *
 * Verify that subset was added to family
 *
 * Adds a element
 *
 * Checks that element has been added to the set and subset
 * Checks subset count
 * Verifies expected sizes
 * Verifies expected bit state
 *
 * Removes earlier element
 * Checks subset count
 * Checks element bit state
 */
BOOST_AUTO_TEST_CASE( create_powerset_subset ) {
    powerset_type ps;

    typename powerset_type::subset_ptr c = ps.create_subset();

    BOOST_REQUIRE_MESSAGE( ps.family_size() == 1, "Subset was not added to family");

    double k = 0.5;
    test_element te(k, 1.0);

    c->addElement( te );

    size_t cnt = c->count();
    BOOST_REQUIRE_MESSAGE( cnt == 1, "Element has not been added to the subset: " << cnt << "(1)" );

    const unsigned int bpb = bmap::bits_per_block;
    BOOST_REQUIRE_MESSAGE( ps.variable_allocated_size() == bpb, "Unexpected size: " << ps.variable_allocated_size() << "(" << bpb << ")" );

    typename powerset_type::element_index_type idx = ps.find_or_create(te);
    BOOST_REQUIRE_MESSAGE( idx == bmap()(te), "Unexpected index " << idx << " returned for " << 0 << "(" << k << ")" );

    BOOST_REQUIRE_MESSAGE( c->check_state( idx ), "Unexpected state for element after add" );

    c->removeElement( te );

    cnt = c->count();
    BOOST_REQUIRE_MESSAGE( cnt == 0, "Element has not been removed to the subset: " << cnt << "(0)" );
    BOOST_REQUIRE_MESSAGE( !c->check_state( idx ), "Unexpected state for element after remove" );
}

/**
 * Create a powerset
 *
 * Create a subset with one element in it, in a sub-scope;
 * Assuming subset_ptr is a shared_ptr, the change in scope should dereference
 * a single instance to the subset, leaving a single instance of the subset
 * in the family.  If the family contains only a single instance of a subset,
 * prune the powerset should remove the subset, and free up lost|fixed
 * elements.
 *
 */
BOOST_AUTO_TEST_CASE( create_powerset_prunespace ) {
    powerset_type ps;

    // change in scope should release one instance of subset_ptr
    {
        typename powerset_type::subset_ptr c = ps.create_subset();

        double k = 0.5;
        test_element te(k, 1.0);

        c->addElement( te );
    }

    BOOST_REQUIRE_MESSAGE( ps.family_size() == 1, "Subset was not added to family");

    const unsigned int bpb = bmap::bits_per_block;
    size_t fs = ps.free_size();
    BOOST_REQUIRE_MESSAGE( fs == (bpb - 1), "Unexpected free size " << fs << "(" << (bpb - 1) << ")" );
    BOOST_REQUIRE_MESSAGE( ps.variable_allocated_size() == bpb, "Unexpected size: " << ps.variable_allocated_size() << "(" << bpb << ")" );

    ps.pruneSpace();

    BOOST_REQUIRE_MESSAGE( ps.family_size() == 0, "Subset was not removed from family");

    fs = ps.free_size();
    BOOST_REQUIRE_MESSAGE( fs == bpb, "Unexpected free size " << fs << "(" << bpb << ")" );
}

/**
 * Create a powerset
 *
 * Create a subset with one element in it, in a sub-scope;
 * Create a second subset with the same element (a duplicate of the first subset)
 *
 * As before the first subset should be dereferenced, and will be removed from
 * the family.  The second subset, however, will not because two references to the
 * subset should exist (one in this scope, and one in the family).
 *
 * Therefore, pruning the powerset space should result in the subsets being
 * reduced to 1.  Furthermore, since there is a single subset, with a single
 * element, that element becomes fixed within the powerset.  The fixed element
 * should be copied to the fixed subset, and its positions should be freed
 *
 */
BOOST_AUTO_TEST_CASE( create_powerset_prunespace2 ) {
    powerset_type ps;

    double k = 0.5;
    test_element te(k, 1.0);

    // change in scope should release one instance of subset_ptr
    {
        typename powerset_type::subset_ptr c = ps.create_subset();

        c->addElement( te );
    }

    typename powerset_type::subset_ptr c2 = ps.create_subset();
    c2->addElement(te);

    BOOST_REQUIRE_MESSAGE( ps.family_size() == 2, "Subset was not added to family");

    typename powerset_type::element_index_type idx = ps.find_or_create(te);

    const unsigned int bpb = bmap::bits_per_block;
    size_t fs = ps.free_size();
    BOOST_REQUIRE_MESSAGE( fs == (bpb - 1), "Unexpected free size " << fs << "(" << (bpb - 1) << ")" );
    BOOST_REQUIRE_MESSAGE( ps.variable_allocated_size() == bpb, "Unexpected size: " << ps.variable_allocated_size() << " (" << bpb << ")" );

    ps.pruneSpace();

    fs = ps.free_size();
    BOOST_REQUIRE_MESSAGE( ps.family_size() == 1, "Expected subset was not removed from family " << ps.family_size() << " (1)" );
    BOOST_REQUIRE_MESSAGE( fs == bpb, "Unexpected free size " << fs << " (" << bpb << ")" );
    BOOST_REQUIRE_MESSAGE( ps.fixed_size() == 1, "Unexpected fixed size " << ps.fixed_size() << " (1)");

    typename powerset_type::element_index_type idx2 = ps.find_or_create(te);
    BOOST_REQUIRE_MESSAGE( idx != idx2, "After pruning, fixed element has same index.  Should be different");

    BOOST_REQUIRE_MESSAGE( idx2 == ps.encode_index(0, true), "Unxpected fixed index " << idx2 << " (" << ps.encode_index(0, true) << ")");

    bool is_fixed  = ps.decode_index(idx2);
    BOOST_REQUIRE_MESSAGE( is_fixed, "Unexpected state decoding false (true)" );
    BOOST_REQUIRE_MESSAGE( idx2 == 0, "Unexpected index decoded " << idx2 << " (0)");
}
BOOST_AUTO_TEST_SUITE_END()
<|endoftext|>


<commit_before>#include <SDL/SDL.h>
#define W 600
#define H 600
SDL_Surface *s;
int done = 0;
SDL_Event event;

int board[3][3];
int step = 0, player = 0;
int iswin()
{
	for (int i = 0; i < 3; i++)
		if (board[i][0] && board[i][0] == board[i][1]
			&& board[i][1] == board[i][2])
			return board[i][0];
	for (int i = 0; i < 3; i++)
		if (board[0][i] && board[0][i] == board[1][i]
			&& board[1][i] == board[2][i])
			return board[0][i];
	if (board[0][0] && board[0][0] == board[1][1]
		&& board[1][1] == board[2][2])
		return board[0][0];
	if (board[0][2] && board[0][2] == board[1][1]
		&& board[1][1] == board[2][0])
		return board[0][2];
	return 0;
}

int think_max(int &x, int &y);
int think_max(int &x, int &y);

int think_min(int &x, int &y)
{
	if (iswin())
		return -1000;
	if (step >= 9)
		return 0;
	int best = -100000, v;
	for (int i = 0; i < 3; i++)
		for (int j = 0; j < 3; j++)
			if (board[i][j] == 0)
			{
				board[i][j] = -1;
				step++;
				if (iswin() == -1)
				{
					x = i, y = j;
					board[i][j] = 0;
					step--;
					return -100;
				}
				else if (step >= 9)
				{
					x = i, y = j;
					board[i][j] = 0;
					step--;
					return 0;
				}
				else
				{
					v = -think_max(x, y);
					if (best < v)
					{
						x = i, y = j;
						best = v;
					}
					board[i][j] = 0;
					step--;
				}
			}
	return best;
}

int think_max(int &x, int &y)
{
	if (iswin())
		return 1000;
	if (step >= 9)
		return 0;
	int best = -999999, v;
	for (int i = 0; i < 3; i++)
		for (int j = 0; j < 3; j++)
			if (board[i][j] == 0)
			{
				board[i][j] = 1;
				step++;
				if (iswin() == 1)
				{
					x = i, y = j;
					board[i][j] = 0;
					step--;
					return 100;
				}
				else if (step >= 9)
				{
					x = i, y = j;
					board[i][j] = 0;
					step--;
					return 0;
				}
				else
				{
					v = think_min(x, y);
					if (best < v)
					{
						x = i, y = j;
						best = v;
					}
					board[i][j] = 0;
					step--;
				}
			}
	return best;
}

void Draw_block(int x, int y, int w, int h, SDL_Color color)
{
	SDL_Rect rect;
	rect.w = w;
	rect.h = h;
	rect.x = x;
	rect.y = y;
	SDL_FillRect(s, &rect, SDL_MapRGB(s->format, color.r, color.g, color.b));
}

void Draw_mouse(int x, int y)
{
	SDL_Color col = { 0, 0, 0xff };
	Draw_block(x, y, W, 1, col);
	Draw_block(x, 0, 1, H, col);
	Draw_block(x, y, 1, H, col);
	Draw_block(0, y, W, 1, col);
}

void Draw_board()
{
	SDL_Color color[3] = {
		{0xff, 0xff, 0x00},
		{0xff, 0xff, 0xff},
		{0x00, 0xff, 0xff}
	};
	for (int i = 0; i < 3; i++)
		for (int j = 0; j < 3; j++)
		{
			Draw_block(i * 200, j * 200, 190, 190, color[board[i][j] + 1]);
		}
}

int isgameover()
{
	return iswin() != 0 || step >= 9;
}

void Game_reset()
{
	for (int i = 0; i < 3; i++)
		for (int j = 0; j < 3; j++)
			board[i][j] = 0;
	step = 0;
	player = 1;
}

int main()
{
	SDL_Init(SDL_INIT_VIDEO);
	s = SDL_SetVideoMode(W, H, 32, SDL_DOUBLEBUF | SDL_HWSURFACE);
	if (s == NULL)
		return 0;
	Game_reset();
	while (!done)
	{
		SDL_FillRect(s, 0, 0);
		int x, y;
		if (player == 1)
		{
			think_max(x, y);
			if (board[x][y] == 0)
			{
				board[x][y] = 1;
				step++;
				player = -1;
				Draw_board();
				SDL_Flip(s);
			}
		}
		Draw_board();
		SDL_PollEvent(&event);
		Draw_mouse(event.motion.x, event.motion.y);
		if (event.type == SDL_KEYDOWN)
		{
			switch (event.key.keysym.sym)
			{
			case SDLK_ESCAPE:
				done = 1;
				break;
			case SDLK_r:
				Game_reset();
				break;
			}
		}
		if (event.type == SDL_QUIT)
		{
			done = 1;
		}
		if (event.type == SDL_MOUSEBUTTONDOWN)
		{
			for (int i = 0; i < 3; i++)
				for (int j = 0; j < 3; j++)
					if (event.button.x > i * 200
						&& event.button.x < i * 200 + 190
						&& event.button.y > j * 200
						&& event.button.y < j * 200 + 190)
					{
						Draw_block(i * 200, j * 200, 190, 190, (SDL_Color)
								   {
								   255, 0, 0}
						);
						if (board[i][j] == 0 && player == -1 && !isgameover())
						{
							board[i][j] = -1;
							step++;
							player = 1;
						}
					}
		}
		SDL_Flip(s);
	}

	SDL_Quit();
	return 0;
}<commit_msg>remove '-' in think_min()<commit_after>#include <SDL/SDL.h>
#define W 600
#define H 600
SDL_Surface *s;
int done = 0;
SDL_Event event;

int board[3][3];
int step = 0, player = 0;
int iswin()
{
	for (int i = 0; i < 3; i++)
		if (board[i][0] && board[i][0] == board[i][1]
			&& board[i][1] == board[i][2])
			return board[i][0];
	for (int i = 0; i < 3; i++)
		if (board[0][i] && board[0][i] == board[1][i]
			&& board[1][i] == board[2][i])
			return board[0][i];
	if (board[0][0] && board[0][0] == board[1][1]
		&& board[1][1] == board[2][2])
		return board[0][0];
	if (board[0][2] && board[0][2] == board[1][1]
		&& board[1][1] == board[2][0])
		return board[0][2];
	return 0;
}

int think_max(int &x, int &y);
int think_max(int &x, int &y);

int think_min(int &x, int &y)
{
	if (iswin())
		return -1000;
	if (step >= 9)
		return 0;
	int best = -100000, v;
	for (int i = 0; i < 3; i++)
		for (int j = 0; j < 3; j++)
			if (board[i][j] == 0)
			{
				board[i][j] = -1;
				step++;
				if (iswin() == -1)
				{
					x = i, y = j;
					board[i][j] = 0;
					step--;
					return -100;
				}
				else if (step >= 9)
				{
					x = i, y = j;
					board[i][j] = 0;
					step--;
					return 0;
				}
				else
				{
					v = think_max(x, y);
					if (best < v)
					{
						x = i, y = j;
						best = v;
					}
					board[i][j] = 0;
					step--;
				}
			}
	return best;
}

int think_max(int &x, int &y)
{
	if (iswin())
		return 1000;
	if (step >= 9)
		return 0;
	int best = -999999, v;
	for (int i = 0; i < 3; i++)
		for (int j = 0; j < 3; j++)
			if (board[i][j] == 0)
			{
				board[i][j] = 1;
				step++;
				if (iswin() == 1)
				{
					x = i, y = j;
					board[i][j] = 0;
					step--;
					return 100;
				}
				else if (step >= 9)
				{
					x = i, y = j;
					board[i][j] = 0;
					step--;
					return 0;
				}
				else
				{
					v = think_min(x, y);
					if (best < v)
					{
						x = i, y = j;
						best = v;
					}
					board[i][j] = 0;
					step--;
				}
			}
	return best;
}

void Draw_block(int x, int y, int w, int h, SDL_Color color)
{
	SDL_Rect rect;
	rect.w = w;
	rect.h = h;
	rect.x = x;
	rect.y = y;
	SDL_FillRect(s, &rect, SDL_MapRGB(s->format, color.r, color.g, color.b));
}

void Draw_mouse(int x, int y)
{
	SDL_Color col = { 0, 0, 0xff };
	Draw_block(x, y, W, 1, col);
	Draw_block(x, 0, 1, H, col);
	Draw_block(x, y, 1, H, col);
	Draw_block(0, y, W, 1, col);
}

void Draw_board()
{
	SDL_Color color[3] = {
		{0xff, 0xff, 0x00},
		{0xff, 0xff, 0xff},
		{0x00, 0xff, 0xff}
	};
	for (int i = 0; i < 3; i++)
		for (int j = 0; j < 3; j++)
		{
			Draw_block(i * 200, j * 200, 190, 190, color[board[i][j] + 1]);
		}
}

int isgameover()
{
	return iswin() != 0 || step >= 9;
}

void Game_reset()
{
	for (int i = 0; i < 3; i++)
		for (int j = 0; j < 3; j++)
			board[i][j] = 0;
	step = 0;
	player = 1;
}

int main()
{
	SDL_Init(SDL_INIT_VIDEO);
	s = SDL_SetVideoMode(W, H, 32, SDL_DOUBLEBUF | SDL_HWSURFACE);
	if (s == NULL)
		return 0;
	Game_reset();
	while (!done)
	{
		SDL_FillRect(s, 0, 0);
		int x, y;
		if (player == 1)
		{
			think_max(x, y);
			if (board[x][y] == 0)
			{
				board[x][y] = 1;
				step++;
				player = -1;
				Draw_board();
				SDL_Flip(s);
			}
		}
		Draw_board();
		SDL_PollEvent(&event);
		Draw_mouse(event.motion.x, event.motion.y);
		if (event.type == SDL_KEYDOWN)
		{
			switch (event.key.keysym.sym)
			{
			case SDLK_ESCAPE:
				done = 1;
				break;
			case SDLK_r:
				Game_reset();
				break;
			}
		}
		if (event.type == SDL_QUIT)
		{
			done = 1;
		}
		if (event.type == SDL_MOUSEBUTTONDOWN)
		{
			for (int i = 0; i < 3; i++)
				for (int j = 0; j < 3; j++)
					if (event.button.x > i * 200
						&& event.button.x < i * 200 + 190
						&& event.button.y > j * 200
						&& event.button.y < j * 200 + 190)
					{
						Draw_block(i * 200, j * 200, 190, 190, (SDL_Color)
								   {
								   255, 0, 0}
						);
						if (board[i][j] == 0 && player == -1 && !isgameover())
						{
							board[i][j] = -1;
							step++;
							player = 1;
						}
					}
		}
		SDL_Flip(s);
	}

	SDL_Quit();
	return 0;
}
<|endoftext|>


<commit_before>#include <csv.h>
#include <boost/lexical_cast.hpp>

#include <fcntl.h>
#include <sys/stat.h>
#include <sys/mman.h>

#include <typeinfo>
#include <iostream>

namespace csv {
namespace detail {

struct Result {
  int number{0};
  std::string message{"success"};
  operator bool() const { return number == 0; }
};
class MappedFile {
 private:
  int fd_;
  size_t size_;
  char* data_;

 public:
  MappedFile(const std::string& filename) : fd_(0), size_(0), data_(NULL) {
    fd_ = ::open(filename.c_str(), O_RDONLY);
    if (fd_ < 0) {
      set_error();
      return;
    }

    struct stat statbuf;
    if (::fstat(fd_, &statbuf) < 0) {
      set_error();
      return;
    }
    size_ = statbuf.st_size;

    data_ = (char*)::mmap(NULL, size_, PROT_READ, MAP_PRIVATE, fd_, 0);
    if (data_ == NULL) {
      set_error();
      return;
    }
  }
  ~MappedFile() {
    ::munmap(data_, size_);
    ::close(fd_);
  }

  const char* begin() const { return data_; }
  const char* end() const { return data_ + size_; }

  operator bool() { return status; }
  detail::Result status;

 private:
  void set_error() {
    status.number = errno;
    status.message = strerror(errno);
  }
};

// generates sequence numbers used in template expansion
namespace sequence {
template <int... Is>
struct index {};

template <int N, int... Is>
struct generate : generate<N - 1, N - 1, Is...> {};

template <int... Is>
struct generate<0, Is...> : index<Is...> {};
}  // namespace sequence

namespace meta {

template <class F>
class fields;
// function pointer
template <class R, class... Args>
class fields<R (*)(Args...)> : public fields<R(Args...)> {};
// member function pointer
template <class C, class R, class... Args>
class fields<R (C::*)(Args...)> : public fields<R(Args...)> {};
// const member function pointer
template <class C, class R, class... Args>
class fields<R (C::*)(Args...) const> : public fields<R(Args...)> {};
// member object pointer
template <class C, class R>
class fields<R(C::*)> : public fields<R(C&)> {};
// functor
template <class F>
class fields : public fields<decltype(&F::operator())> {};
// reference
template <class F>
class fields<F&> : public fields<F> {};
// perfect reference
template <class F>
class fields<F&&> : public fields<F> {};
// impl
template <class R, class... Args>
class fields<R(Args...)> {
  using mutator_t = std::function<void(const char* buf, size_t len)>;

 public:
  fields() {
    setupFieldHandlers(
        typename detail::sequence::generate<sizeof...(Args)>::index());
  }
  void accept_field(const char* buf, size_t len) {
    if (current_field < mutators.size()) {
      mutators[current_field](buf, len);
    }
    ++current_field;
  }
  template <typename F>
  void accept_row(F& func) {
    current_field = 0;
    call_func(func,
              typename detail::sequence::generate<sizeof...(Args)>::index());
  }
  template <typename F, int... S>
  void call_func(F& func, detail::sequence::index<S...>) {
    func(std::get<S>(values)...);
  }

 private:
  std::tuple<typename std::decay<Args>::type...> values;
  std::vector<mutator_t> mutators;
  size_t current_field = 0;

 private:
  template <int... S>
  void setupFieldHandlers(detail::sequence::index<S...>) {
    setupFieldHandlers(std::get<S>(values)...);
  }
  template <typename F, typename... Fa>
  void setupFieldHandlers(F& arg, Fa&... args) {
    mutators.push_back([&arg](const char* buf, size_t len) {
      if (len > 0) {
        arg = boost::lexical_cast<F>(buf, len);
      } else {
        arg = F();
      }
    });
    setupFieldHandlers(args...);
  }
  void setupFieldHandlers() {
    // this is the terminal function for recursive template expansion
  }
};

}  // namespace meta
}  // detail

/* A C++ wrapper around libcsv, see `make_parser` below */
template <typename F>
class CsvParser {
  using this_type = CsvParser<F>;

 public:
  CsvParser(const F& func) : func{func} { csv_init(&parser, 0); }
  ~CsvParser() { csv_free(&parser); }

  //
  void set_delim_char(unsigned char delim) { parser.delim_char = delim; }
  void set_quote_char(unsigned char quote) { parser.quote_char = quote; }
  void set_skip_header() { skip_next_row = true; }

  //
  bool ParseFile(const std::string& filename) {
    detail::MappedFile data(filename);
    if (!data) {
      return status = data.status;
    }
    return Parse(data.begin(), data.end()) && Finish();
  }
  template <typename T>
  bool Parse(const T& str) {
    return Parse(str.data(), str.data() + str.length());
  }
  template <typename It>
  bool Parse(const It& begin, const It& end) {
    csv_parse(&parser, begin, end - begin, on_field, on_record, this);
    return update_status();
  }
  bool Finish() {
    csv_fini(&parser, on_field, on_record, this);
    return update_status();
  }
  const std::string& ErrorString() { return status.message; }
  operator bool() { return status; }

 private:
  static void on_field(void* data, size_t len, void* this_ptr) {
    this_type* t = reinterpret_cast<this_type*>(this_ptr);
    t->accept_field((char*)data, len);
  }
  static void on_record(int, void* this_ptr) {
    this_type* t = reinterpret_cast<this_type*>(this_ptr);
    t->accept_row();
  };

 private:
  detail::meta::fields<F> fields;
  csv_parser parser;
  const F& func;
  detail::Result status;
  bool skip_next_row{false};

 private:
  void accept_field(const char* buf, size_t len) {
    fields.accept_field(buf, len);
  }
  void accept_row() {
    if (skip_next_row) {
      skip_next_row = false;
    } else {
      fields.accept_row(func);
    }
  }
  const detail::Result& update_status() {
    if (status.number == 0 && parser.status != 0) {
      status.number = parser.status;
      status.message = csv_error(&parser);
    }
    return status;
  }
};

template <typename F>
CsvParser<F> make_parser(F&& f) {
  return CsvParser<F>(f);
}

}  // namespace csv
<commit_msg>Add support for parsing from an iostream<commit_after>#include <csv.h>
#include <boost/lexical_cast.hpp>

#include <fcntl.h>
#include <sys/stat.h>
#include <sys/mman.h>

#include <typeinfo>

namespace csv {
namespace detail {

struct Result {
  int number{0};
  std::string message{"success"};
  operator bool() const { return number == 0; }
};
class MappedFile {
 private:
  int fd_;
  size_t size_;
  char* data_;

 public:
  MappedFile(const std::string& filename) : fd_(0), size_(0), data_(NULL) {
    fd_ = ::open(filename.c_str(), O_RDONLY);
    if (fd_ < 0) {
      set_error();
      return;
    }

    struct stat statbuf;
    if (::fstat(fd_, &statbuf) < 0) {
      set_error();
      return;
    }
    size_ = statbuf.st_size;

    data_ = (char*)::mmap(NULL, size_, PROT_READ, MAP_PRIVATE, fd_, 0);
    if (data_ == NULL) {
      set_error();
      return;
    }
  }
  ~MappedFile() {
    ::munmap(data_, size_);
    ::close(fd_);
  }

  const char* begin() const { return data_; }
  const char* end() const { return data_ + size_; }

  operator bool() { return status; }
  detail::Result status;

 private:
  void set_error() {
    status.number = errno;
    status.message = strerror(errno);
  }
};

// generates sequence numbers used in template expansion
namespace sequence {
template <int... Is>
struct index {};

template <int N, int... Is>
struct generate : generate<N - 1, N - 1, Is...> {};

template <int... Is>
struct generate<0, Is...> : index<Is...> {};
}  // namespace sequence

namespace meta {

template <class F>
class fields;
// function pointer
template <class R, class... Args>
class fields<R (*)(Args...)> : public fields<R(Args...)> {};
// member function pointer
template <class C, class R, class... Args>
class fields<R (C::*)(Args...)> : public fields<R(Args...)> {};
// const member function pointer
template <class C, class R, class... Args>
class fields<R (C::*)(Args...) const> : public fields<R(Args...)> {};
// member object pointer
template <class C, class R>
class fields<R(C::*)> : public fields<R(C&)> {};
// functor
template <class F>
class fields : public fields<decltype(&F::operator())> {};
// reference
template <class F>
class fields<F&> : public fields<F> {};
// perfect reference
template <class F>
class fields<F&&> : public fields<F> {};
// impl
template <class R, class... Args>
class fields<R(Args...)> {
  using mutator_t = std::function<void(const char* buf, size_t len)>;

 public:
  fields() {
    setupFieldHandlers(
        typename detail::sequence::generate<sizeof...(Args)>::index());
  }
  void accept_field(const char* buf, size_t len) {
    if (current_field < mutators.size()) {
      mutators[current_field](buf, len);
    }
    ++current_field;
  }
  template <typename F>
  void accept_row(F& func) {
    current_field = 0;
    call_func(func,
              typename detail::sequence::generate<sizeof...(Args)>::index());
  }
  template <typename F, int... S>
  void call_func(F& func, detail::sequence::index<S...>) {
    func(std::get<S>(values)...);
  }

 private:
  std::tuple<typename std::decay<Args>::type...> values;
  std::vector<mutator_t> mutators;
  size_t current_field = 0;

 private:
  template <int... S>
  void setupFieldHandlers(detail::sequence::index<S...>) {
    setupFieldHandlers(std::get<S>(values)...);
  }
  template <typename F, typename... Fa>
  void setupFieldHandlers(F& arg, Fa&... args) {
    mutators.push_back([&arg](const char* buf, size_t len) {
      if (len > 0) {
        arg = boost::lexical_cast<F>(buf, len);
      } else {
        arg = F();
      }
    });
    setupFieldHandlers(args...);
  }
  void setupFieldHandlers() {
    // this is the terminal function for recursive template expansion
  }
};

}  // namespace meta
}  // detail

/* A C++ wrapper around libcsv, see `make_parser` below */
template <typename F>
class CsvParser {
  using this_type = CsvParser<F>;

 public:
  CsvParser(const F& func) : func{func} { csv_init(&parser, 0); }
  ~CsvParser() { csv_free(&parser); }

  //
  void set_delim_char(unsigned char delim) { parser.delim_char = delim; }
  void set_quote_char(unsigned char quote) { parser.quote_char = quote; }
  void set_skip_header() { skip_next_row = true; }

  //
  bool ParseFile(const std::string& filename) {
    detail::MappedFile data(filename);
    if (!data) {
      return status = data.status;
    }
    return Parse(data.begin(), data.end()) && Finish();
  }
  template <typename T>
  bool Parse(const T& str) {
    return Parse(str.data(), str.data() + str.length());
  }
  template <typename It>
  bool Parse(const It& begin, const It& end) {
    csv_parse(&parser, begin, end - begin, on_field, on_record, this);
    return update_status();
  }
  template <typename IoStream>
  bool Parse(IoStream& input) {
    char buf[4096];
    do {
      input.read(buf, sizeof(buf));
      csv_parse(&parser, buf, input.gcount(), on_field, on_record, this);
    } while (input && update_status());
    return update_status();
  }
  bool Finish() {
    csv_fini(&parser, on_field, on_record, this);
    return update_status();
  }
  const std::string& ErrorString() { return status.message; }
  operator bool() { return status; }

 private:
  static void on_field(void* data, size_t len, void* this_ptr) {
    this_type* t = reinterpret_cast<this_type*>(this_ptr);
    t->accept_field((char*)data, len);
  }
  static void on_record(int, void* this_ptr) {
    this_type* t = reinterpret_cast<this_type*>(this_ptr);
    t->accept_row();
  };

 private:
  detail::meta::fields<F> fields;
  csv_parser parser;
  const F& func;
  detail::Result status;
  bool skip_next_row{false};

 private:
  void accept_field(const char* buf, size_t len) {
    fields.accept_field(buf, len);
  }
  void accept_row() {
    if (skip_next_row) {
      skip_next_row = false;
    } else {
      fields.accept_row(func);
    }
  }
  const detail::Result& update_status() {
    if (status.number == 0 && parser.status != 0) {
      status.number = parser.status;
      status.message = csv_error(&parser);
    }
    return status;
  }
};

template <typename F>
CsvParser<F> make_parser(F&& f) {
  return CsvParser<F>(f);
}

}  // namespace csv
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2015 Samsung Electronics Co., Ltd.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

// CLASS HEADER
#include <dali-toolkit/internal/text/clipping/text-clipper.h>

// EXTERNAL INCLUDES
#include <algorithm>
#include <dali/public-api/common/stage.h>
#include <dali/public-api/render-tasks/render-task-list.h>
#include <dali/integration-api/debug.h>

namespace
{

// Currently on desktop machines 2k x 2k is the maximum frame buffer size, on target is 4k x 4k.
const float MAX_OFFSCREEN_RENDERING_SIZE = 2048.f;

} // namespace

namespace Dali
{

namespace Toolkit
{

namespace Text
{

ClipperPtr Clipper::New( const Vector2& size )
{
  ClipperPtr clipper( new Clipper() );

  // Second-phase init
  clipper->Initialize( size );

  return clipper;
}

Actor Clipper::GetRootActor() const
{
  return mOffscreenRootActor;
}

ImageActor Clipper::GetImageActor() const
{
  return mImageActor;
}

void Clipper::Refresh( const Vector2& size )
{
  const Size offscreenSize( std::min( MAX_OFFSCREEN_RENDERING_SIZE, size.width ),
                            std::min( MAX_OFFSCREEN_RENDERING_SIZE, size.height ) );

  const bool sizeChanged = offscreenSize != mCurrentOffscreenSize;

  if( sizeChanged )
  {
    // Reconfigure camera for current size.
    mOffscreenCameraActor.SetOrthographicProjection( offscreenSize );

    // Recreate frame buffer for offscreen rendering when the size changes.
    FrameBufferImage frameBufferImage = FrameBufferImage::New( offscreenSize.width,
                                                               offscreenSize.height,
                                                               Pixel::RGBA8888 );

    mImageActor.SetSize( offscreenSize );
    mImageActor.SetImage( frameBufferImage );
    mRenderTask.SetTargetFrameBuffer( frameBufferImage );

    // Stores current sizPe to avoid create new Dali resources if text changes.
    mCurrentOffscreenSize = offscreenSize;
  }

  mRenderTask.SetRefreshRate( RenderTask::REFRESH_ONCE );
}

void Clipper::Initialize( const Vector2& size )
{
  const Size offscreenSize( std::min( MAX_OFFSCREEN_RENDERING_SIZE, size.width ),
                            std::min( MAX_OFFSCREEN_RENDERING_SIZE, size.height ) );

  // Create a root actor and an image actor for offscreen rendering.
  mOffscreenRootActor = Layer::New();
  mOffscreenRootActor.SetColorMode( USE_OWN_COLOR );
  mOffscreenRootActor.SetPositionInheritanceMode( DONT_INHERIT_POSITION );
  mOffscreenRootActor.SetInheritScale( false );
  mOffscreenRootActor.SetDepthTestDisabled( true );
  mOffscreenRootActor.SetSize( offscreenSize );

  mImageActor = ImageActor::New();
  mImageActor.SetParentOrigin( ParentOrigin::CENTER );
  mImageActor.SetBlendFunc( BlendingFactor::ONE, BlendingFactor::ONE_MINUS_SRC_ALPHA,
                            BlendingFactor::ONE, BlendingFactor::ONE );
  mImageActor.SetScale( Vector3( 1.0f, -1.0f, 1.0f ) );
  mImageActor.SetSize( offscreenSize );

  // Creates a new camera actor.
  mOffscreenCameraActor = CameraActor::New();
  mOffscreenCameraActor.SetParentOrigin( ParentOrigin::CENTER );
  mOffscreenCameraActor.SetOrthographicProjection( offscreenSize );
  mOffscreenRootActor.Add( mOffscreenCameraActor ); // camera to shoot the offscreen text

  // Creates a new render task.
  mRenderTask = Stage::GetCurrent().GetRenderTaskList().CreateTask();
  mRenderTask.SetSourceActor( mOffscreenRootActor );
  mRenderTask.SetClearColor( Color::TRANSPARENT );
  mRenderTask.SetClearEnabled( true );
  mRenderTask.SetExclusive( true );
  mRenderTask.SetCameraActor( mOffscreenCameraActor );

  // Creates a frame buffer for offscreen rendering
  FrameBufferImage frameBufferImage = FrameBufferImage::New( offscreenSize.width,
                                                             offscreenSize.height,
                                                             Pixel::RGBA8888 );
  mImageActor.SetImage( frameBufferImage );
  mRenderTask.SetTargetFrameBuffer( frameBufferImage );

  // Stores current size to avoid create new Dali resources if text changes.
  mCurrentOffscreenSize = offscreenSize;
}

Clipper::Clipper()
{
}

Clipper::~Clipper()
{
  if( Stage::IsInstalled() )
  {
    UnparentAndReset( mOffscreenRootActor );
    UnparentAndReset( mImageActor );

    Stage::GetCurrent().GetRenderTaskList().RemoveTask( mRenderTask );
  }
}

} // namespace Text

} // namespace Toolkit

} // namespace Dali
<commit_msg>Fix for resizing TextField when Delete button is added<commit_after>/*
 * Copyright (c) 2015 Samsung Electronics Co., Ltd.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

// CLASS HEADER
#include <dali-toolkit/internal/text/clipping/text-clipper.h>

// EXTERNAL INCLUDES
#include <algorithm>
#include <dali/public-api/common/stage.h>
#include <dali/public-api/render-tasks/render-task-list.h>
#include <dali/integration-api/debug.h>

namespace
{

// Currently on desktop machines 2k x 2k is the maximum frame buffer size, on target is 4k x 4k.
const float MAX_OFFSCREEN_RENDERING_SIZE = 2048.f;

} // namespace

namespace Dali
{

namespace Toolkit
{

namespace Text
{

ClipperPtr Clipper::New( const Vector2& size )
{
  ClipperPtr clipper( new Clipper() );

  // Second-phase init
  clipper->Initialize( size );

  return clipper;
}

Actor Clipper::GetRootActor() const
{
  return mOffscreenRootActor;
}

ImageActor Clipper::GetImageActor() const
{
  return mImageActor;
}

void Clipper::Refresh( const Vector2& size )
{
  const Size offscreenSize( std::min( MAX_OFFSCREEN_RENDERING_SIZE, size.width ),
                            std::min( MAX_OFFSCREEN_RENDERING_SIZE, size.height ) );

  const bool sizeChanged = offscreenSize != mCurrentOffscreenSize;

  if( sizeChanged )
  {
    // Reconfigure camera for current size.
    mOffscreenCameraActor.SetOrthographicProjection( offscreenSize );

    // Recreate frame buffer for offscreen rendering when the size changes.
    FrameBufferImage frameBufferImage = FrameBufferImage::New( offscreenSize.width,
                                                               offscreenSize.height,
                                                               Pixel::RGBA8888 );

    mOffscreenRootActor.SetSize( size );

    mImageActor.SetSize( offscreenSize );
    mImageActor.SetImage( frameBufferImage );
    mRenderTask.SetTargetFrameBuffer( frameBufferImage );

    // Stores current sizPe to avoid create new Dali resources if text changes.
    mCurrentOffscreenSize = offscreenSize;
  }

  mRenderTask.SetRefreshRate( RenderTask::REFRESH_ONCE );
}

void Clipper::Initialize( const Vector2& size )
{
  const Size offscreenSize( std::min( MAX_OFFSCREEN_RENDERING_SIZE, size.width ),
                            std::min( MAX_OFFSCREEN_RENDERING_SIZE, size.height ) );

  // Create a root actor and an image actor for offscreen rendering.
  mOffscreenRootActor = Layer::New();
  mOffscreenRootActor.SetColorMode( USE_OWN_COLOR );
  mOffscreenRootActor.SetPositionInheritanceMode( DONT_INHERIT_POSITION );
  mOffscreenRootActor.SetInheritScale( false );
  mOffscreenRootActor.SetDepthTestDisabled( true );
  mOffscreenRootActor.SetSize( offscreenSize );

  mImageActor = ImageActor::New();
  mImageActor.SetParentOrigin( ParentOrigin::CENTER );
  mImageActor.SetBlendFunc( BlendingFactor::ONE, BlendingFactor::ONE_MINUS_SRC_ALPHA,
                            BlendingFactor::ONE, BlendingFactor::ONE );
  mImageActor.SetScale( Vector3( 1.0f, -1.0f, 1.0f ) );
  mImageActor.SetSize( offscreenSize );

  // Creates a new camera actor.
  mOffscreenCameraActor = CameraActor::New();
  mOffscreenCameraActor.SetParentOrigin( ParentOrigin::CENTER );
  mOffscreenCameraActor.SetOrthographicProjection( offscreenSize );
  mOffscreenRootActor.Add( mOffscreenCameraActor ); // camera to shoot the offscreen text

  // Creates a new render task.
  mRenderTask = Stage::GetCurrent().GetRenderTaskList().CreateTask();
  mRenderTask.SetSourceActor( mOffscreenRootActor );
  mRenderTask.SetClearColor( Color::TRANSPARENT );
  mRenderTask.SetClearEnabled( true );
  mRenderTask.SetExclusive( true );
  mRenderTask.SetCameraActor( mOffscreenCameraActor );

  // Creates a frame buffer for offscreen rendering
  FrameBufferImage frameBufferImage = FrameBufferImage::New( offscreenSize.width,
                                                             offscreenSize.height,
                                                             Pixel::RGBA8888 );
  mImageActor.SetImage( frameBufferImage );
  mRenderTask.SetTargetFrameBuffer( frameBufferImage );

  // Stores current size to avoid create new Dali resources if text changes.
  mCurrentOffscreenSize = offscreenSize;
}

Clipper::Clipper()
{
}

Clipper::~Clipper()
{
  if( Stage::IsInstalled() )
  {
    UnparentAndReset( mOffscreenRootActor );
    UnparentAndReset( mImageActor );

    Stage::GetCurrent().GetRenderTaskList().RemoveTask( mRenderTask );
  }
}

} // namespace Text

} // namespace Toolkit

} // namespace Dali
<|endoftext|>